From 377c4c21f0e922c0549c3deaea327928bece3b12 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 6 Dec 2017 19:14:24 -0500 Subject: [PATCH 0001/1594] Merge Prebid 1.0 to Master (#1936) * Concurrent auctions (#1593) * Adding timestamp function to utils * Auction manager (WIP) * WIP * Updated targeting with auction instances and added auction status * Updated appnexus and appnexusAst adapter * Added done callback * Removing bidmanager functions * Removing deprecated public api functions * remove bidmanager file * Revert "remove bidmanager file" This reverts commit 616409edb65514d20c02d4e36879a4d3edde1f5d. * Updated appnexus and rubicon adapters to call done callback after all responses are back * Added todo * Fixing circular dependency * filter s2s requests * Emit auction end Add getBidsRequested function * remove unused stuff from adapters * cleanup and fixes * Unit test fixes Added exclude to karma temporarily to support unit tests * added setTimeout for each auction instance * added constants closer to code * binded auction object inside done method * Adding auctionmanager_spec tests and fixes * Remove breakpoint * Moving auction to separate file and unit tests * Merged manually * Merged config api changes * Passing adunits, adunitscodes via constructor and fixing unit tests * added ajax with timeout * convert targeting module to factory pattern * Auction code refactored and unit tests * Updated bidderfactory for 1.0 changes and added unit tests * Renamed placementCode to adUnitCode * Refactor auction and update unit tests * JSDoc for auction and auctionManager * Unit test fixes after rebase * Manual merge new updates to bidmanager and its spec file into auction * Update appnexusAst spec file * Refactor * Prebid 1.0 does not require no_bid to be added * removed side effect by cloning objects * bug fix to set status on already used bid * Removing all !1.0 complaiant adapters * Adding aliases to appnexusAst adapter * Removed bidmanager from currency * Add ignore-loader to handle .md files (#1646) * Auction module refactor (#1644) * Auction moduel refactor * remove comment and global cbtimeout * Config api updates (#1633) * Add timeoutBuffer, s2sconfig, bidderSequence to config * Removing deprecated function and its unit test * fixed linting errors * Adapter/rubicon bid adapter markup (#1674) * initial take on rubiconBidAdapter markup * formatting * formatting, cont. * formatting, cont. * Prebid 1.0 Fix issue with video bid validation (#1680) * Fix issue with video bid validation * Modified tests to stub `auctionManager.getBidsRequested` instead of `getBidRequest` * Move stub to beforeEach hook * Fix lint errors * Add bidRequests param to bid validation * Auction module updated to support currency/hook (#1733) * added hook module to prebid core that allows extension of arbitrary functions * remove unused dependency tiny-queue * change PluginFunction to HookedFunction * more hook documentation fixes * Auction module updated to support currency/hook * remove unused dependency tiny-queue * change PluginFunction to HookedFunction * more hook documentation fixes * WIP * allow context for hooked functions * added tests for context * remove withContext, just use bind * fix in hooks so asyncSeries keeps proper bound context * Unit test fixes * Updated bid validation function * Fixed video unit test * updated sizeMapping to use sizeConfig and support labels (#1772) * updated sizeMapping to use sizeConfig and support labels * added new tests for labels and sizes w/ sizeConfig when making auction * made some names clearer and added type to labels for sizeMapping * make error message more descriptive in adaptermanager * remove extra line in adpatermanager * update package.json with correct version. (#1813) * Unit test fixes for IE 10 and other old browsers (#1810) * Added fix for location.origin * Fixed test case failing in IE and Safari browsers * Added utils.getOrigin method * Updated renderer to use hooks * Rename appnexusAst adapter to appnexus adapter (#1848) * Renamed appnexusAst adapter to appnexus * Updated unit test to use appnexus bidderCode * Remove completed todo comment * fixed safeframe for 1.0 (#1834) * Emit array of objects from BID_TIMEOUT event (#1824) * Emit array of objects from BID_TIMEOUT event * requestId is now auctionId * Use v4 UUID to match previous requestId format * Move function * Move public winningBids to auction (#1828) * Move public winningBids to auction * removed _winningBids * removed _winningBids * bugfix: return only new bids * Updates for PubWise Prebid 1.0 Support (#1847) * Updates for Prebid 1.0 Support * Updates for Bug Fixes and a small refactor * update JSDoc comment. Remove trailing space (#1872) tests were failing due to no trailing space eslint rule. * Prebid 1.0 adxcg analytics adapter fix for bidtimeout event (#1871) * adxcg analytics adapter for 1.0 bidtimeout event * update tests for adxcg analytics 1.0 * Prebid 1.0 prebid server (#1846) * fix adaptermanager s2sTest unit tests * fix s2s log message * remove errant comment * fixed log statement * removed seemingly unnecessary call to transformHeightWidth(adUnit); * removed legacy sizeMapping code block * initial refactor of prebidServerBidAdapter working w/o tests (cherry picked from commit 2b843d0) * add transformSizes back for prebidServer adUnits to fix request * fixed adapterManager_spec tests * added prebidServerBidAdapter tests for 1.0 * fixed lint errors * make sure addBidResponse and doneCb are stubbed for s2s calls * s2s requests now firing BID_REQUESTED event * fixed commented tests and other minor fixes * update defaults in prebidServerBidAdapter and fix doBidderSync bug * add new API for setting defaults in config for modules * Targeting updates (#1689) * Cherry pick alias bidder * Cherry pick alias bidder * Cherry pick alias bidder * Updated test case to not import adapter * targeting updates * targeting functions refactoring * Refactored functions * more refactor of function * added jsdoc and some more refactor * check bid expiry and filtering used bids * make sure we have the right version * Update version to fix invalid semver * video bug fix (#1906) * video bug fix added required params to prebidServerAdapter * Emitted auction_end and updated ttl for prebidServer * fix logging of server adapters * Manually merge bidManager code to auction module (#1905) * Unit test fix in IE for adxcgAnalytics Adapter (#1929) * IE bug fix * get only unique bidders * added log message for xhr timeout (#1928) * remove polyfill.js and remove global polyfills (#1918) * remove polyfill.js and remove global polyfills * make sure find, findIndex, and includes use core-js in tests * switch from virtual function bind core-js to explicit usage. * remove transform-function-bind babel plugin * Replace usePrebidCache with cache:url and remove default (#1904) * replace usePrebidCache with video:cacheUrl and remove default * remove newConfig in dfpAdServerVideo_spec that isn't doing anything * change video.cacheUrl to cache.url * update to cache.url in auction and remove from adapter * pulsepointLiteBidAdapter renamed to pulsepointBidAdapter (#1931) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * Pulsepoint adapter changes * readme updates * add 'x_source.tid' to rubicon requests (#1933) * Bring in pre-1.0 native-image asset adapter change (#1934) * 33Across Adapter: Removed the usage of utils library (#1917) * Removed the usage of utils library to get bidder requests during userSync since this info will now be passed into the method * Fixed extra space which cause lint to fail * Implemented user sync per code review feedback in https://github.com/prebid/Prebid.js/pull/1917 * Minor feedback changes * Re-instated lint check for all files which was accidentally commited after testing * Prebid 1.0 server cache (#1935) * add cache stuff to video for prebid server * add description for cacheMarkup --- .babelrc | 6 +- integrationExamples/gpt/hello_world.html | 170 +- modules/33acrossBidAdapter.js | 65 +- modules/aardvarkBidAdapter.js | 124 -- modules/adbladeBidAdapter.js | 135 -- modules/adbundBidAdapter.js | 69 - modules/adequantBidAdapter.js | 80 - modules/adformBidAdapter.js | 172 -- modules/adkernelAdnBidAdapter.js | 3 +- modules/adkernelBidAdapter.js | 6 +- modules/admediaBidAdapter.js | 107 -- modules/admixerBidAdapter.js | 87 - modules/adomikAnalyticsAdapter.js | 7 +- modules/adsupplyBidAdapter.js | 90 - modules/adxcgAnalyticsAdapter.js | 17 +- modules/adyoulikeBidAdapter.js | 202 --- modules/aerservBidAdapter.js | 116 -- modules/aolBidAdapter.js | 8 +- modules/appnexusAstBidAdapter.js | 430 ----- modules/appnexusBidAdapter.js | 601 +++--- ...AstBidAdapter.md => appnexusBidAdapter.md} | 12 +- modules/atomxBidAdapter.js | 81 - modules/audienceNetworkBidAdapter.js | 6 +- modules/bidfluenceBidAdapter.js | 58 - modules/bridgewellBidAdapter.js | 5 +- modules/brightcomBidAdapter.js | 205 --- modules/c1xBidAdapter.js | 147 -- modules/carambolaBidAdapter.js | 193 -- modules/centroBidAdapter.js | 124 -- modules/colossussspBidAdapter.js | 174 -- modules/coxBidAdapter.js | 258 --- modules/criteoBidAdapter.js | 194 -- modules/currency.js | 6 +- modules/dfpAdServerVideo.js | 6 +- modules/districtmDMXBidAdapter.js | 56 - modules/eplanningBidAdapter.js | 310 ---- modules/essensBidAdapter.js | 170 -- modules/featureforwardBidAdapter.js | 92 - modules/gumgumBidAdapter.js | 176 -- modules/hiromediaBidAdapter.js | 374 ---- modules/imonomyBidAdapter.js | 185 -- modules/indexExchangeBidAdapter.js | 1132 ------------ modules/inneractiveBidAdapter.js | 459 ----- modules/innityBidAdapter.js | 65 - modules/kruxlinkBidAdapter.js | 90 - modules/lifestreetBidAdapter.js | 166 -- modules/mantisBidAdapter.js | 228 --- modules/marsmediaBidAdapter.js | 160 -- modules/memeglobalBidAdapter.js | 124 -- modules/nanointeractiveBidAdapter.js | 2 +- modules/nginadBidAdapter.js | 186 -- modules/orbitsoftBidAdapter.js | 228 --- modules/piximediaBidAdapter.js | 155 -- modules/prebidServerBidAdapter.js | 249 +-- modules/pubgearsBidAdapter.js | 150 -- modules/pubmaticBidAdapter.js | 233 --- modules/pubwiseAnalyticsAdapter.js | 7 +- modules/pulsepointBidAdapter.js | 377 +++- ...eBidAdapter.md => pulsepointBidAdapter.md} | 9 +- modules/pulsepointLiteBidAdapter.js | 330 ---- modules/realvuBidAdapter.js | 238 --- modules/roxotAnalyticsAdapter.js | 7 +- modules/roxotBidAdapter.js | 116 -- modules/rubiconBidAdapter.js | 3 +- modules/rubiconBidAdapter.md | 48 + modules/smartadserverBidAdapter.js | 60 - modules/smartyadsBidAdapter.js | 180 -- modules/sonobiBidAdapter.js | 118 -- modules/spotxBidAdapter.js | 143 -- modules/springserveBidAdapter.js | 116 -- modules/stickyadstvBidAdapter.js | 269 --- modules/tapsenseBidAdapter.js | 89 - modules/thoughtleadrBidAdapter.js | 191 -- modules/tremorBidAdapter.js | 167 -- modules/tripleliftBidAdapter.js | 149 -- modules/twengaBidAdapter.js | 136 -- modules/ucfunnelBidAdapter.js | 95 - modules/unrulyBidAdapter.js | 119 -- modules/vertozBidAdapter.js | 72 - modules/wideorbitBidAdapter.js | 223 --- modules/widespaceBidAdapter.js | 127 -- modules/xhbBidAdapter.js | 172 -- modules/yieldbotBidAdapter.js | 200 -- modules/yieldmoBidAdapter.js | 151 -- package.json | 2 +- src/adaptermanager.js | 385 ++-- src/adapters/bidderFactory.js | 128 +- src/adserver.js | 6 +- src/ajax.js | 148 +- src/auction.js | 506 ++++++ src/auctionManager.js | 98 + src/bidmanager.js | 509 ------ src/config.js | 233 +-- src/constants.json | 3 - src/cpmBucketManager.js | 3 +- src/native.js | 20 +- src/polyfill.js | 14 - src/prebid.js | 348 +--- src/secureCreatives.js | 17 +- src/sizeMapping.js | 126 +- src/targeting.js | 508 ++++-- src/utils.js | 62 +- src/video.js | 20 +- src/videoCache.js | 7 +- test/fixtures/fixtures.js | 80 +- test/fixtures/video/adUnit.json | 2 +- test/fixtures/video/bidRequest.json | 4 +- test/fixtures/video/vastPayloadResponse.json | 6 +- test/fixtures/video/vastUrlResponse.json | 6 +- test/pages/video.html | 2 +- test/spec/api_spec.js | 12 - test/spec/auctionmanager_spec.js | 861 +++++++++ test/spec/bidmanager_spec.js | 684 ------- test/spec/config_spec.js | 32 +- test/spec/e2e/gpt-examples/gpt_outstream.html | 4 +- test/spec/modules/33acrossBidAdapter_spec.js | 234 ++- test/spec/modules/aardvarkBidAdapter_spec.js | 240 --- test/spec/modules/adbladeBidAdapter_spec.js | 206 --- test/spec/modules/adbundBidAdapter_spec.js | 94 - test/spec/modules/adformBidAdapter_spec.js | 198 -- test/spec/modules/admixerBidAdapter_spec.js | 244 --- test/spec/modules/adsupplyBidAdapter_spec.js | 359 ---- .../modules/adxcgAnalyticsAdapter_spec.js | 31 +- test/spec/modules/adyoulikeBidAdapter_spec.js | 314 ---- test/spec/modules/aerservBidAdapter_spec.js | 213 --- .../modules/appnexusAstBidAdapter_spec.js | 428 ----- test/spec/modules/appnexusBidAdapter_spec.js | 437 ++++- test/spec/modules/atomxBidAdapter_spec.js | 150 -- .../spec/modules/bidfluenceBidAdapter_spec.js | 71 - test/spec/modules/c1xBidAdapter_spec.js | 203 --- test/spec/modules/carambolaBidAdapter_spec.js | 139 -- test/spec/modules/centroBidAdapter_spec.js | 225 --- .../modules/colossussspBidAdapter_spec.js | 127 -- .../spec/modules/conversantBidAdapter_spec.js | 1 - test/spec/modules/coxBidAdapter_spec.js | 120 -- test/spec/modules/criteoBidAdapter_spec.js | 274 --- test/spec/modules/currency_spec.js | 7 +- test/spec/modules/dfpAdServerVideo_spec.js | 4 - .../modules/districtmDMXBidAdapter_spec.js | 245 --- test/spec/modules/eplanningBidAdapter_spec.js | 112 -- test/spec/modules/essensBidAdapter_spec.js | 828 --------- .../modules/featureforwardBidAdapter_spec.js | 87 - test/spec/modules/gumgumBidAdapter_spec.js | 295 --- test/spec/modules/hiromediaBidAdapter_spec.js | 331 ---- test/spec/modules/imonomyBidAdapter_spec.js | 109 -- .../indexExchangeBidAdapter_request_spec.js | 528 ------ .../indexExchangeBidAdapter_response_spec.js | 1170 ------------ ...indexExchangeBidAdapter_validation_spec.js | 1607 ----------------- .../indexExchangeBidAdapter_video_spec.js | 953 ---------- .../modules/inneractiveBidAdapter_spec.js | 291 --- test/spec/modules/innityBidAdapter_spec.js | 157 -- .../spec/modules/lifestreetBidAdapter_spec.js | 231 --- test/spec/modules/mantisBidAdapter_spec.js | 168 -- test/spec/modules/marsmediaBidAdapter_spec.js | 185 -- .../spec/modules/memeglobalBidAdapter_spec.js | 170 -- test/spec/modules/orbitsoftBidAdapter_spec.js | 354 ---- test/spec/modules/piximediaBidAdapter_spec.js | 416 ----- .../modules/prebidServerBidAdapter_spec.js | 245 +-- test/spec/modules/pubgearsBidAdapter_spec.js | 287 --- test/spec/modules/pubmaticBidAdapter_spec.js | 276 --- .../spec/modules/pulsepointBidAdapter_spec.js | 383 ++-- .../modules/pulsepointLiteBidAdapter_spec.js | 276 --- test/spec/modules/realvuBidAdapter_spec.js | 61 - test/spec/modules/roxotBidAdapter_spec.js | 123 -- test/spec/modules/rubiconBidAdapter_spec.js | 3 +- test/spec/modules/s2sTesting_spec.js | 3 +- .../sharethroughAnalyticsAdapter_spec.js | 90 - .../modules/smartadserverBidAdapter_spec.js | 154 -- test/spec/modules/smartyadsBidAdapter_spec.js | 128 -- test/spec/modules/sonobiBidAdapter_spec.js | 389 ---- test/spec/modules/spotxBidAdapter_spec.js | 226 --- .../modules/stickyadstvBidAdapter_spec.js | 225 --- test/spec/modules/tapsenseBidAdapter_spec.js | 257 --- .../modules/thoughtleadrBidAdapter_spec.js | 108 -- test/spec/modules/tremorBidAdapter_spec.js | 173 -- .../spec/modules/tripleliftBidAdapter_spec.js | 226 --- test/spec/modules/twengaBidAdapter_spec.js | 119 -- test/spec/modules/ucfunnelBidAdapter_spec.js | 110 -- test/spec/modules/unrulyBidAdapter_spec.js | 278 --- test/spec/modules/vertozBidAdapter_spec.js | 140 -- test/spec/modules/wideorbitBidAdapter_spec.js | 497 ----- test/spec/modules/widespaceBidAdapter_spec.js | 226 --- test/spec/modules/yieldbotBidAdapter_spec.js | 518 ------ test/spec/modules/yieldmoBidAdapter_spec.js | 209 --- test/spec/renderer_spec.js | 38 +- test/spec/sizeMapping_spec.js | 290 +-- test/spec/unit/bidmanager_spec.js | 259 --- test/spec/unit/core/adapterManager_spec.js | 396 +++- test/spec/unit/core/bidderFactory_spec.js | 288 ++- test/spec/unit/core/targeting_spec.js | 59 +- test/spec/unit/pbjs_api_spec.js | 1382 ++++++-------- test/spec/utils_spec.js | 2 +- test/spec/videoCache_spec.js | 23 +- test/spec/video_spec.js | 111 +- 194 files changed, 6020 insertions(+), 32816 deletions(-) delete mode 100644 modules/aardvarkBidAdapter.js delete mode 100644 modules/adbladeBidAdapter.js delete mode 100644 modules/adbundBidAdapter.js delete mode 100644 modules/adequantBidAdapter.js delete mode 100644 modules/adformBidAdapter.js delete mode 100644 modules/admediaBidAdapter.js delete mode 100644 modules/admixerBidAdapter.js delete mode 100644 modules/adsupplyBidAdapter.js delete mode 100644 modules/adyoulikeBidAdapter.js delete mode 100644 modules/aerservBidAdapter.js delete mode 100644 modules/appnexusAstBidAdapter.js rename modules/{appnexusAstBidAdapter.md => appnexusBidAdapter.md} (87%) delete mode 100644 modules/atomxBidAdapter.js delete mode 100644 modules/bidfluenceBidAdapter.js delete mode 100644 modules/brightcomBidAdapter.js delete mode 100644 modules/c1xBidAdapter.js delete mode 100644 modules/carambolaBidAdapter.js delete mode 100644 modules/centroBidAdapter.js delete mode 100644 modules/colossussspBidAdapter.js delete mode 100644 modules/coxBidAdapter.js delete mode 100644 modules/criteoBidAdapter.js delete mode 100644 modules/districtmDMXBidAdapter.js delete mode 100644 modules/eplanningBidAdapter.js delete mode 100644 modules/essensBidAdapter.js delete mode 100644 modules/featureforwardBidAdapter.js delete mode 100644 modules/gumgumBidAdapter.js delete mode 100644 modules/hiromediaBidAdapter.js delete mode 100644 modules/imonomyBidAdapter.js delete mode 100644 modules/indexExchangeBidAdapter.js delete mode 100644 modules/inneractiveBidAdapter.js delete mode 100644 modules/innityBidAdapter.js delete mode 100644 modules/kruxlinkBidAdapter.js delete mode 100644 modules/lifestreetBidAdapter.js delete mode 100644 modules/mantisBidAdapter.js delete mode 100644 modules/marsmediaBidAdapter.js delete mode 100644 modules/memeglobalBidAdapter.js delete mode 100644 modules/nginadBidAdapter.js delete mode 100644 modules/orbitsoftBidAdapter.js delete mode 100644 modules/piximediaBidAdapter.js delete mode 100644 modules/pubgearsBidAdapter.js delete mode 100644 modules/pubmaticBidAdapter.js rename modules/{pulsepointLiteBidAdapter.md => pulsepointBidAdapter.md} (77%) delete mode 100644 modules/pulsepointLiteBidAdapter.js delete mode 100644 modules/realvuBidAdapter.js delete mode 100644 modules/roxotBidAdapter.js create mode 100644 modules/rubiconBidAdapter.md delete mode 100644 modules/smartadserverBidAdapter.js delete mode 100644 modules/smartyadsBidAdapter.js delete mode 100644 modules/sonobiBidAdapter.js delete mode 100644 modules/spotxBidAdapter.js delete mode 100644 modules/springserveBidAdapter.js delete mode 100644 modules/stickyadstvBidAdapter.js delete mode 100644 modules/tapsenseBidAdapter.js delete mode 100644 modules/thoughtleadrBidAdapter.js delete mode 100644 modules/tremorBidAdapter.js delete mode 100644 modules/tripleliftBidAdapter.js delete mode 100644 modules/twengaBidAdapter.js delete mode 100644 modules/ucfunnelBidAdapter.js delete mode 100644 modules/unrulyBidAdapter.js delete mode 100644 modules/vertozBidAdapter.js delete mode 100644 modules/wideorbitBidAdapter.js delete mode 100644 modules/widespaceBidAdapter.js delete mode 100644 modules/xhbBidAdapter.js delete mode 100644 modules/yieldbotBidAdapter.js delete mode 100644 modules/yieldmoBidAdapter.js create mode 100644 src/auction.js create mode 100644 src/auctionManager.js delete mode 100644 src/bidmanager.js delete mode 100644 src/polyfill.js create mode 100644 test/spec/auctionmanager_spec.js delete mode 100644 test/spec/bidmanager_spec.js delete mode 100644 test/spec/modules/aardvarkBidAdapter_spec.js delete mode 100644 test/spec/modules/adbladeBidAdapter_spec.js delete mode 100644 test/spec/modules/adbundBidAdapter_spec.js delete mode 100644 test/spec/modules/adformBidAdapter_spec.js delete mode 100644 test/spec/modules/admixerBidAdapter_spec.js delete mode 100644 test/spec/modules/adsupplyBidAdapter_spec.js delete mode 100644 test/spec/modules/adyoulikeBidAdapter_spec.js delete mode 100644 test/spec/modules/aerservBidAdapter_spec.js delete mode 100644 test/spec/modules/appnexusAstBidAdapter_spec.js delete mode 100644 test/spec/modules/atomxBidAdapter_spec.js delete mode 100644 test/spec/modules/bidfluenceBidAdapter_spec.js delete mode 100644 test/spec/modules/c1xBidAdapter_spec.js delete mode 100644 test/spec/modules/carambolaBidAdapter_spec.js delete mode 100644 test/spec/modules/centroBidAdapter_spec.js delete mode 100644 test/spec/modules/colossussspBidAdapter_spec.js delete mode 100644 test/spec/modules/coxBidAdapter_spec.js delete mode 100644 test/spec/modules/criteoBidAdapter_spec.js delete mode 100644 test/spec/modules/districtmDMXBidAdapter_spec.js delete mode 100644 test/spec/modules/eplanningBidAdapter_spec.js delete mode 100644 test/spec/modules/essensBidAdapter_spec.js delete mode 100644 test/spec/modules/featureforwardBidAdapter_spec.js delete mode 100644 test/spec/modules/gumgumBidAdapter_spec.js delete mode 100644 test/spec/modules/hiromediaBidAdapter_spec.js delete mode 100644 test/spec/modules/imonomyBidAdapter_spec.js delete mode 100644 test/spec/modules/indexExchangeBidAdapter_request_spec.js delete mode 100644 test/spec/modules/indexExchangeBidAdapter_response_spec.js delete mode 100644 test/spec/modules/indexExchangeBidAdapter_validation_spec.js delete mode 100644 test/spec/modules/indexExchangeBidAdapter_video_spec.js delete mode 100644 test/spec/modules/inneractiveBidAdapter_spec.js delete mode 100644 test/spec/modules/innityBidAdapter_spec.js delete mode 100644 test/spec/modules/lifestreetBidAdapter_spec.js delete mode 100644 test/spec/modules/mantisBidAdapter_spec.js delete mode 100644 test/spec/modules/marsmediaBidAdapter_spec.js delete mode 100644 test/spec/modules/memeglobalBidAdapter_spec.js delete mode 100644 test/spec/modules/orbitsoftBidAdapter_spec.js delete mode 100644 test/spec/modules/piximediaBidAdapter_spec.js delete mode 100644 test/spec/modules/pubgearsBidAdapter_spec.js delete mode 100644 test/spec/modules/pubmaticBidAdapter_spec.js delete mode 100644 test/spec/modules/pulsepointLiteBidAdapter_spec.js delete mode 100644 test/spec/modules/realvuBidAdapter_spec.js delete mode 100644 test/spec/modules/roxotBidAdapter_spec.js delete mode 100644 test/spec/modules/sharethroughAnalyticsAdapter_spec.js delete mode 100644 test/spec/modules/smartadserverBidAdapter_spec.js delete mode 100644 test/spec/modules/smartyadsBidAdapter_spec.js delete mode 100644 test/spec/modules/sonobiBidAdapter_spec.js delete mode 100644 test/spec/modules/spotxBidAdapter_spec.js delete mode 100644 test/spec/modules/stickyadstvBidAdapter_spec.js delete mode 100644 test/spec/modules/tapsenseBidAdapter_spec.js delete mode 100644 test/spec/modules/thoughtleadrBidAdapter_spec.js delete mode 100644 test/spec/modules/tremorBidAdapter_spec.js delete mode 100644 test/spec/modules/tripleliftBidAdapter_spec.js delete mode 100644 test/spec/modules/twengaBidAdapter_spec.js delete mode 100644 test/spec/modules/ucfunnelBidAdapter_spec.js delete mode 100644 test/spec/modules/unrulyBidAdapter_spec.js delete mode 100644 test/spec/modules/vertozBidAdapter_spec.js delete mode 100644 test/spec/modules/wideorbitBidAdapter_spec.js delete mode 100644 test/spec/modules/widespaceBidAdapter_spec.js delete mode 100644 test/spec/modules/yieldbotBidAdapter_spec.js delete mode 100644 test/spec/modules/yieldmoBidAdapter_spec.js delete mode 100644 test/spec/unit/bidmanager_spec.js diff --git a/.babelrc b/.babelrc index 8726a848e2e..b366d78478e 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,8 @@ { "presets": ["es2015"], - "plugins": ["transform-object-assign", "transform-es3-property-literals", "transform-es3-member-expression-literals"] + "plugins": [ + "transform-object-assign", + "transform-es3-property-literals", + "transform-es3-member-expression-literals" + ] } diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index 0f5e24a301a..aa4bf5ea782 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -12,91 +12,91 @@ --> - - - - - + + + - - - - - - - -

Prebid.js Test

-
Div-1
-
- -
- - + + function sendAdserverRequest() { + if (pbjs.adserverRequestSent) return; + pbjs.adserverRequestSent = true; + googletag.cmd.push(function() { + pbjs.que.push(function() { + pbjs.setTargetingForGPTAsync(); + googletag.pubads().refresh(); + }); + }); + } + + setTimeout(function() { + sendAdserverRequest(); + }, PREBID_TIMEOUT); + + + + + + + + + +

Prebid.js Test

+
Div-1
+
+ +
+ + \ No newline at end of file diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index b496a66d081..8e73d5c87b4 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -1,5 +1,6 @@ +import { userSync } from 'src/userSync' const { registerBidder } = require('../src/adapters/bidderFactory'); -const utils = require('../src/utils'); +const { config } = require('../src/config'); const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; @@ -38,9 +39,7 @@ function _createServerRequest(bidRequest) { } } - // Allowing site to be a test configuration object or just the id (former required for testing, - // latter when used by publishers) - ttxRequest.site = params.site || { id: params.siteId }; + ttxRequest.site = { id: params.siteId }; // 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 @@ -51,28 +50,18 @@ function _createServerRequest(bidRequest) { withCredentials: false }; - if (bidRequest.params.customHeaders) { - options.customHeaders = bidRequest.params.customHeaders; - } + // Allow the ability to configure the HB endpoint for testing purposes. + const ttxSettings = config.getConfig('ttxSettings'); + const url = (ttxSettings && ttxSettings.url) || END_POINT; return { 'method': 'POST', - 'url': bidRequest.params.url || END_POINT, + 'url': url, 'data': JSON.stringify(ttxRequest), 'options': options } } -// Sync object will always be of type iframe for ttx -function _createSync(bid) { - const syncUrl = bid.params.syncUrl || SYNC_ENDPOINT; - - return { - type: 'iframe', - url: `${syncUrl}&id=${bid.params.siteId || bid.params.site.id}` - } -} - function _getFormatSize(sizeArr) { return { w: sizeArr[0], @@ -81,6 +70,24 @@ function _getFormatSize(sizeArr) { } } +// Register one sync per bid since each ad unit may potenitally be linked to a uniqe guid +// Sync type will always be 'iframe' for 33Across +function _registerUserSyncs(requestData) { + let ttxRequest; + try { + ttxRequest = JSON.parse(requestData); + } catch (err) { + // No point in trying to register sync since the requisite data cannot be parsed. + return; + } + const ttxSettings = config.getConfig('ttxSettings'); + + let syncUrl = (ttxSettings && ttxSettings.syncUrl) || SYNC_ENDPOINT; + + syncUrl = `${syncUrl}&id=${ttxRequest.site.id}`; + userSync.registerSync('iframe', BIDDER_CODE, syncUrl); +} + function isBidRequestValid(bid) { if (bid.bidder !== BIDDER_CODE || typeof bid.params === 'undefined') { return false; @@ -104,7 +111,12 @@ function buildRequests(bidRequests) { } // NOTE: At this point, the response from 33exchange will only ever contain one bid i.e. the highest bid -function interpretResponse(serverResponse) { +function interpretResponse(serverResponse, bidRequest) { + // Register user sync first + if (bidRequest && bidRequest.data) { + _registerUserSyncs(bidRequest.data); + } + const bidResponses = []; // If there are bids, look at the first bid of the first seatbid (see NOTE above for assumption about ttx) @@ -115,24 +127,11 @@ function interpretResponse(serverResponse) { return bidResponses; } -// Register one sync per bid since each ad unit may potenitally be linked to a uniqe guid -function getUserSyncs(syncOptions) { - let syncs = []; - const ttxBidRequests = utils.getBidderRequestAllAdUnits(BIDDER_CODE).bids; - - if (syncOptions.iframeEnabled) { - syncs = ttxBidRequests.map(_createSync); - } - - return syncs; -} - const spec = { code: BIDDER_CODE, isBidRequestValid, buildRequests, - interpretResponse, - getUserSyncs + interpretResponse } registerBidder(spec); diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js deleted file mode 100644 index f52265e4d1d..00000000000 --- a/modules/aardvarkBidAdapter.js +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Adapter for requesting bids from RTK Aardvark - * To request an RTK Aardvark Header bidding account - * or for additional integration support please contact sales@rtk.io - */ - -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var Adapter = require('src/adapter.js').default; -var constants = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -const AARDVARK_CALLBACK_NAME = 'aardvarkResponse'; -const AARDVARK_REQUESTS_MAP = 'aardvarkRequests'; -const AARDVARK_BIDDER_CODE = 'aardvark'; -const DEFAULT_REFERRER = 'thor.rtk.io'; -const DEFAULT_ENDPOINT = 'thor.rtk.io'; - -var endpoint = DEFAULT_ENDPOINT; - -function requestBids(bidderCode, callbackName, bidReqs) { - var ref = utils.getTopWindowLocation(); - var ai = ''; - const scs = []; - const bidIds = []; - - ref = ref ? ref.host : DEFAULT_REFERRER; - - for (var i = 0, l = bidReqs.length, bid, _ai, _sc, _endpoint; i < l; i += 1) { - bid = bidReqs[i]; - _ai = utils.getBidIdParameter('ai', bid.params); - _sc = utils.getBidIdParameter('sc', bid.params); - if (!_ai || !_ai.length || !_sc || !_sc.length) { continue; } - - _endpoint = utils.getBidIdParameter('host', bid.params); - if (_endpoint) { endpoint = _endpoint; } - - if (!ai.length) { ai = _ai; } - if (_sc) { scs.push(_sc); } - - bidIds.push(_sc + '=' + bid.bidId); - - // Create the bidIdsMap for easier mapping back later - $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode][bid.bidId] = bid; - } - - if (!ai.length || !scs.length) { return utils.logWarn('Bad bid request params given for adapter $' + bidderCode + ' (' + AARDVARK_BIDDER_CODE + ')'); } - - adloader.loadScript([ - '//' + endpoint + '/', ai, '/', scs.join('_'), - '/aardvark/?jsonp=$$PREBID_GLOBAL$$.', callbackName, - '&rtkreferer=', ref, '&', bidIds.join('&') - ].join('')); -} - -function registerBidResponse(bidderCode, rawBidResponse) { - if (rawBidResponse.error) { return utils.logWarn('Aardvark bid received with an error, ignoring... [' + rawBidResponse.error + ']'); } - - if (!rawBidResponse.cid) { return utils.logWarn('Aardvark bid received without a callback id, ignoring...'); } - - var bidObj = $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode][rawBidResponse.cid]; - if (!bidObj) { return utils.logWarn('Aardvark request not found: ' + rawBidResponse.cid); } - - if (bidObj.params.sc !== rawBidResponse.id) { return utils.logWarn('Aardvark bid received with a non matching shortcode ' + rawBidResponse.id + ' instead of ' + bidObj.params.sc); } - - var bidResponse = bidfactory.createBid(constants.STATUS.GOOD, bidObj); - bidResponse.bidderCode = bidObj.bidder; - bidResponse.cpm = rawBidResponse.cpm; - bidResponse.ad = rawBidResponse.adm + utils.createTrackPixelHtml(decodeURIComponent(rawBidResponse.nurl)); - bidResponse.width = bidObj.sizes[0][0]; - bidResponse.height = bidObj.sizes[0][1]; - - bidmanager.addBidResponse(bidObj.placementCode, bidResponse); - $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode][rawBidResponse.cid].responded = true; -} - -function registerAardvarkCallback(bidderCode, callbackName) { - $$PREBID_GLOBAL$$[callbackName] = function(rtkResponseObj) { - rtkResponseObj.forEach(function(bidResponse) { - registerBidResponse(bidderCode, bidResponse); - }); - - for (var bidRequestId in $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode]) { - if ($$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode].hasOwnProperty(bidRequestId)) { - var bidRequest = $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode][bidRequestId]; - if (!bidRequest.responded) { - var bidResponse = bidfactory.createBid(constants.STATUS.NO_BID, bidRequest); - bidResponse.bidderCode = bidRequest.bidder; - bidmanager.addBidResponse(bidRequest.placementCode, bidResponse); - } - } - } - }; -} - -const AardvarkAdapter = function() { - var baseAdapter = new Adapter(AARDVARK_BIDDER_CODE); - - $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP] = $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP] || {}; - - baseAdapter.callBids = function (params) { - const bidderCode = baseAdapter.getBidderCode(); - var callbackName = AARDVARK_CALLBACK_NAME; - - if (bidderCode !== AARDVARK_BIDDER_CODE) { callbackName = [AARDVARK_CALLBACK_NAME, bidderCode].join('_'); } - - $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode] = {}; - - registerAardvarkCallback(bidderCode, callbackName); - - return requestBids(bidderCode, callbackName, params.bids || []); - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode - }); -}; - -adaptermanager.registerBidAdapter(new AardvarkAdapter(), 'aardvark'); - -module.exports = AardvarkAdapter; diff --git a/modules/adbladeBidAdapter.js b/modules/adbladeBidAdapter.js deleted file mode 100644 index 50f50f515d9..00000000000 --- a/modules/adbladeBidAdapter.js +++ /dev/null @@ -1,135 +0,0 @@ -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Adblade - * To request an Adblade Header partner account - * or for additional integration support please - * register at http://www.adblade.com. - */ -var AdbladeAdapter = function AdbladeAdapter() { - 'use strict'; - - const BIDDER_CODE = 'adblade'; - const BASE_URI = '//rtb.adblade.com/prebidjs/bid?'; - const DEFAULT_BID_FLOOR = 0.0000000001; - - function _callBids(params) { - var bids = params.bids || []; - var referrer = utils.getTopWindowUrl(); - var loc = utils.getTopWindowLocation(); - var domain = loc.hostname; - var partnerId = 0; - var bidRequests = {}; - - if (bids.length > 0) { - partnerId = '' + bids[0].params.partnerId; - } - - utils._each(bids, function(bid) { - // make sure the "sizes" are an array of arrays - if (!(bid.sizes[0] instanceof Array)) { - bid.sizes = [bid.sizes]; - } - utils._each(bid.sizes, function(size) { - let key = size[0] + 'x' + size[1]; - - bidRequests[key] = bidRequests[key] || { - 'site': { - 'id': partnerId, - 'page': referrer, - 'domain': domain, - 'publisher': { - 'id': partnerId, - 'name': referrer, - 'domain': domain - } - }, - 'id': params.requestId, - 'imp': [], - 'device': { - 'ua': window.navigator.userAgent, - }, - 'cur': ['USD'], - 'user': {} - }; - - bidRequests[key].imp.push({ - 'id': bid.bidId, - 'bidfloor': bid.params.bidFloor || DEFAULT_BID_FLOOR, - 'tag': bid.placementCode, - 'banner': { - 'w': size[0], - 'h': size[1], - }, - 'secure': 0 + (loc.protocol === 'https') - }); - }); - }); - - utils._each(bidRequests, function (bidRequest) { - adloader.loadScript( - utils.tryAppendQueryString( - utils.tryAppendQueryString( - BASE_URI, - 'callback', - '$$PREBID_GLOBAL$$.adbladeResponse' - ), - 'json', - JSON.stringify( - bidRequest - ) - ) - ); - }); - } - - $$PREBID_GLOBAL$$.adbladeResponse = function (response) { - var auctionIdRe = /\$(%7B|\{)AUCTION_ID(%7D|\})/gi; - var auctionPriceRe = /\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi; - var clickUrlRe = /\$(%7B|\{)CLICK_URL(%7D|\})/gi; - - if (typeof (response) === 'undefined' || !response.hasOwnProperty('seatbid') || utils.isEmpty(response.seatbid)) { - // handle empty bids - var bidsRequested = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === BIDDER_CODE).bids; - if (bidsRequested.length > 0) { - let bid = bidfactory.createBid(2); - bid.bidderCode = BIDDER_CODE; - bidmanager.addBidResponse(bidsRequested[0].placementCode, bid); - } - - return; - } - - utils._each(response.seatbid, function(seatbid) { - utils._each(seatbid.bid, function(seatbidBid) { - var bidRequest = utils.getBidRequest(seatbidBid.impid); - var ad = seatbidBid.adm + utils.createTrackPixelHtml(seatbidBid.nurl); - - ad = ad.replace(auctionIdRe, seatbidBid.impid); - ad = ad.replace(clickUrlRe, ''); - ad = ad.replace(auctionPriceRe, seatbidBid.price); - - let bid = bidfactory.createBid(1); - - bid.bidderCode = BIDDER_CODE; - bid.cpm = seatbidBid.price; - bid.ad = ad; - bid.width = seatbidBid.w; - bid.height = seatbidBid.h; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - }); - }); - }; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new AdbladeAdapter(), 'adblade'); - -module.exports = AdbladeAdapter; diff --git a/modules/adbundBidAdapter.js b/modules/adbundBidAdapter.js deleted file mode 100644 index a40fc2b8057..00000000000 --- a/modules/adbundBidAdapter.js +++ /dev/null @@ -1,69 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -function AdBundAdapter() { - var timezone = (new Date()).getTimezoneOffset(); - var bidAPIs = [ - 'http://us-east-engine.adbund.xyz/prebid/ad/get', - 'http://us-west-engine.adbund.xyz/prebid/ad/get' - ]; - // Based on the time zone to select the interface to the server - var bidAPI = bidAPIs[timezone < 0 ? 0 : 1]; - - function _stringify(param) { - var result = []; - var key; - for (key in param) { - if (param.hasOwnProperty(key)) { - result.push(key + '=' + encodeURIComponent(param[key])); - } - } - return result.join('&'); - } - - function _createCallback(bid) { - return function (data) { - var response; - if (data && data.cpm) { - response = bidfactory.createBid(CONSTANTS.STATUS.GOOD); - response.bidderCode = 'adbund'; - Object.assign(response, data); - } else { - response = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); - response.bidderCode = 'adbund'; - } - bidmanager.addBidResponse(bid.placementCode, response); - }; - } - - function _requestBids(bid) { - var info = { - referrer: utils.getTopWindowUrl(), - domain: utils.getTopWindowLocation().hostname, - ua: window.navigator.userAgent - }; - var param = Object.assign({}, bid.params, info); - param.sizes = JSON.stringify(param.sizes || bid.sizes); - param.callback = '$$PREBID_GLOBAL$$.adbundResponse'; - $$PREBID_GLOBAL$$.adbundResponse = _createCallback(bid); - adloader.loadScript(bidAPI + '?' + _stringify(param)); - } - - function _callBids(params) { - (params.bids || []).forEach(function (bid) { - _requestBids(bid); - }); - } - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new AdBundAdapter(), 'adbund'); - -module.exports = AdBundAdapter; diff --git a/modules/adequantBidAdapter.js b/modules/adequantBidAdapter.js deleted file mode 100644 index a12369d0a59..00000000000 --- a/modules/adequantBidAdapter.js +++ /dev/null @@ -1,80 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var CONSTANTS = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -function AdequantAdapter() { - var req_url_base = 'https://rex.adequant.com/rex/c2s_prebid?'; - - function _callBids(params) { - var req_url = []; - var publisher_id = null; - var sizes = []; - var cats = null; - var replies = []; - var placements = {}; - - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bid_request = bids[i]; - var br_params = bid_request.params || {}; - placements[bid_request.placementCode] = true; - - publisher_id = br_params.publisher_id.toString() || publisher_id; - var bidfloor = br_params.bidfloor || 0.01; - cats = br_params.cats || cats; - if (typeof (cats) === 'string') { cats = cats.split(' '); } - var br_sizes = utils.parseSizesInput(bid_request.sizes); - for (var j = 0; j < br_sizes.length; j++) { - sizes.push(br_sizes[j] + '_' + bidfloor); - replies.push(bid_request.placementCode); - } - } - // send out 1 bid request for all bids - if (publisher_id) { req_url.push('a=' + publisher_id); } - if (cats) { req_url.push('c=' + cats.join('+')); } - if (sizes) { req_url.push('s=' + sizes.join('+')); } - - adloader.loadScript(req_url_base + req_url.join('&'), function() { process_bids(replies, placements); }); - } - - function process_bids(replies, placements) { - var placement_code; - var bid; - const adequant_creatives = window.adequant_creatives; - if (adequant_creatives && adequant_creatives.seatbid) { - for (var i = 0; i < adequant_creatives.seatbid.length; i++) { - var bid_response = adequant_creatives.seatbid[i].bid[0]; - placement_code = replies[parseInt(bid_response.impid, 10) - 1]; - if (!placement_code || !placements[placement_code]) { continue; } - - bid = bidfactory.createBid(CONSTANTS.STATUS.GOOD); - bid.bidderCode = 'adequant'; - bid.cpm = bid_response.price; - bid.ad = bid_response.adm; - bid.width = bid_response.w; - bid.height = bid_response.h; - bidmanager.addBidResponse(placement_code, bid); - placements[placement_code] = false; - } - } - for (placement_code in placements) { - if (placements[placement_code]) { - bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); - bid.bidderCode = 'adequant'; - bidmanager.addBidResponse(placement_code, bid); - utils.logMessage('No bid response from Adequant for placement code ' + placement_code); - } - } - } - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new AdequantAdapter(), 'adequant'); - -module.exports = AdequantAdapter; diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js deleted file mode 100644 index 3a1d455b7e2..00000000000 --- a/modules/adformBidAdapter.js +++ /dev/null @@ -1,172 +0,0 @@ -var utils = require('src/utils'); -var adloader = require('src/adloader'); -var bidmanager = require('src/bidmanager'); -var bidfactory = require('src/bidfactory'); -var STATUSCODES = require('src/constants.json').STATUS; -var adaptermanager = require('src/adaptermanager'); -var Adapter = require('src/adapter').default; - -const ADFORM_BIDDER_CODE = 'adform'; - -function AdformAdapter() { - let baseAdapter = new Adapter(ADFORM_BIDDER_CODE); - - function _callBids(params) { - var bid, _value, _key, i, j, k, l, reqParams; - var bids = params.bids; - var request = []; - var callbackName = '_adf_' + utils.getUniqueIdentifierStr(); - var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], ['fd', 1], [ 'url', null ], [ 'tid', null ], [ 'callback', '$$PREBID_GLOBAL$$.' + callbackName ] ]; - - for (i = 0, l = bids.length; i < l; i++) { - bid = bids[i]; - - for (j = 0, k = globalParams.length; j < k; j++) { - _key = globalParams[j][0]; - _value = bid[_key] || bid.params[_key]; - if (_value) { - bid[_key] = bid.params[_key] = null; - globalParams[j][1] = _value; - } - } - - reqParams = bid.params; - reqParams.transactionId = bid.transactionId; - request.push(formRequestUrl(reqParams)); - } - - request.unshift('//' + globalParams[0][1] + '/adx/?rp=4'); - - request.push('auctionId=' + params.requestId); - for (i = 1, l = globalParams.length; i < l; i++) { - _key = globalParams[i][0]; - _value = globalParams[i][1]; - if (_value) { - request.push(globalParams[i][0] + '=' + encodeURIComponent(_value)); - } - } - - $$PREBID_GLOBAL$$[callbackName] = handleCallback(bids); - - adloader.loadScript(request.join('&')); - }; - - function formRequestUrl(reqData) { - var key; - var url = []; - - for (key in reqData) { - if (reqData.hasOwnProperty(key) && reqData[key]) { url.push(key, '=', reqData[key], '&'); } - } - - return encode64(url.join('').slice(0, -1)); - } - - function handleCallback(bids) { - return function handleResponse(adItems) { - var bidObject; - var bidder = baseAdapter.getBidderCode(); - var adItem; - var bid; - for (var i = 0, l = adItems.length; i < l; i++) { - adItem = adItems[i]; - bid = bids[i]; - if (adItem && adItem.response === 'banner' && - verifySize(adItem, bid.sizes)) { - bidObject = bidfactory.createBid(STATUSCODES.GOOD, bid); - bidObject.bidderCode = bidder; - bidObject.cpm = adItem.win_bid; - bidObject.cur = adItem.win_cur; - bidObject.ad = adItem.banner; - bidObject.width = adItem.width; - bidObject.height = adItem.height; - bidObject.dealId = adItem.deal_id; - bidObject.transactionId = bid.transactionId; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } else { - bidObject = bidfactory.createBid(STATUSCODES.NO_BID, bid); - bidObject.bidderCode = bidder; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - } - }; - - function verifySize(adItem, validSizes) { - for (var j = 0, k = validSizes.length; j < k; j++) { - if (adItem.width === validSizes[j][0] && - adItem.height === validSizes[j][1]) { - return true; - } - } - - return false; - } - } - - function encode64(input) { - var out = []; - var chr1; - var chr2; - var chr3; - var enc1; - var enc2; - var enc3; - var enc4; - var i = 0; - var _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_='; - - input = utf8_encode(input); - - while (i < input.length) { - chr1 = input.charCodeAt(i++); - chr2 = input.charCodeAt(i++); - chr3 = input.charCodeAt(i++); - - enc1 = chr1 >> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); - enc4 = chr3 & 63; - - if (isNaN(chr2)) { - enc3 = enc4 = 64; - } else if (isNaN(chr3)) { - enc4 = 64; - } - - out.push(_keyStr.charAt(enc1), _keyStr.charAt(enc2)); - if (enc3 !== 64) { out.push(_keyStr.charAt(enc3)); } - if (enc4 !== 64) { out.push(_keyStr.charAt(enc4)); } - } - - return out.join(''); - } - - function utf8_encode(string) { - string = string.replace(/\r\n/g, '\n'); - var utftext = ''; - - for (var n = 0; n < string.length; n++) { - var c = string.charCodeAt(n); - - if (c < 128) { - utftext += String.fromCharCode(c); - } else if ((c > 127) && (c < 2048)) { - utftext += String.fromCharCode((c >> 6) | 192); - utftext += String.fromCharCode((c & 63) | 128); - } else { - utftext += String.fromCharCode((c >> 12) | 224); - utftext += String.fromCharCode(((c >> 6) & 63) | 128); - utftext += String.fromCharCode((c & 63) | 128); - } - } - - return utftext; - } - - return Object.assign(this, baseAdapter, { - callBids: _callBids - }); -} - -adaptermanager.registerBidAdapter(new AdformAdapter(), ADFORM_BIDDER_CODE); -module.exports = AdformAdapter; diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index b1c8bbf398b..28fb564320d 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; import { BANNER, VIDEO } from 'src/mediaTypes'; +import includes from 'core-js/library/fn/array/includes'; const DEFAULT_ADKERNEL_DSP_DOMAIN = 'tag.adkernel.com'; const VIDEO_TARGETING = ['mimes', 'protocols', 'api']; @@ -28,7 +29,7 @@ function buildImp(bidRequest) { }; if (bidRequest.params.video) { Object.keys(bidRequest.params.video) - .filter(param => VIDEO_TARGETING.includes(param)) + .filter(param => includes(VIDEO_TARGETING, param)) .forEach(param => imp.video[param] = bidRequest.params.video[param]); } } else { diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 095a6cec4b9..016cc5794fb 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -1,6 +1,8 @@ import * as utils from 'src/utils'; import { BANNER, VIDEO } from 'src/mediaTypes'; import {registerBidder} from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', @@ -63,7 +65,7 @@ export const spec = { .reduce((a, b) => a.concat(b), []); return rtbBids.map(rtbBid => { - let imp = rtbImps.find(imp => imp.id === rtbBid.impid); + let imp = find(rtbImps, imp => imp.id === rtbBid.impid); let prBid = { requestId: rtbBid.impid, cpm: rtbBid.price, @@ -119,7 +121,7 @@ function buildImp(bid) { imp.video = {w: size[0], h: size[1]}; if (bid.params.video) { Object.keys(bid.params.video) - .filter(param => VIDEO_TARGETING.includes(param)) + .filter(param => includes(VIDEO_TARGETING, param)) .forEach(param => imp.video[param] = bid.params.video[param]); } } else { diff --git a/modules/admediaBidAdapter.js b/modules/admediaBidAdapter.js deleted file mode 100644 index 4382870eef3..00000000000 --- a/modules/admediaBidAdapter.js +++ /dev/null @@ -1,107 +0,0 @@ -import { getBidRequest } from 'src/utils'; -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var CONSTANTS = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from AdMedia. - * - */ -var AdmediaAdapter = function AdmediaAdapter() { - function _callBids(params) { - var bids; - const bidderUrl = (window.location.protocol) + '//b.admedia.com/banner/prebid/bidder/?'; - bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var request_obj = {}; - var bid = bids[i]; - - if (bid.params.aid) { - request_obj.aid = bid.params.aid; - } else { - utils.logError('required param aid is missing', 'admedia'); - continue; - } - - // optional page_url macro - if (bid.params.page_url) { - request_obj.page_url = bid.params.page_url; - } - - // if set, return a test ad for all aids - if (bid.params.test_ad === 1) { - request_obj.test_ad = 1; - } - - var parsedSizes = utils.parseSizesInput(bid.sizes); - var parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // first value should be "size" - request_obj.size = parsedSizes[0]; - if (parsedSizesLength > 1) { - // any subsequent values should be "promo_sizes" - var promo_sizes = []; - for (var j = 1; j < parsedSizesLength; j++) { - promo_sizes.push(parsedSizes[j]); - } - - request_obj.promo_sizes = promo_sizes.join(','); - } - } - - // detect urls - request_obj.siteDomain = window.location.host; - request_obj.sitePage = window.location.href; - request_obj.siteRef = document.referrer; - request_obj.topUrl = utils.getTopWindowUrl(); - - request_obj.callback = '$$PREBID_GLOBAL$$'; - request_obj.callbackId = bid.bidId; - - var endpoint = bidderUrl + utils.parseQueryStringParameters(request_obj); - - // utils.logMessage('Admedia request built: ' + endpoint); - - adloader.loadScript(endpoint); - } - } - - // expose the callback to global object - $$PREBID_GLOBAL$$.admediaHandler = function(response) { - var bidObject = {}; - var callback_id = response.callback_id; - var placementCode = ''; - var bidObj = getBidRequest(callback_id); - if (bidObj) { - placementCode = bidObj.placementCode; - } - - if (bidObj && response.cpm > 0 && !!response.ad) { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.GOOD); - bidObject.bidderCode = bidObj.bidder; - bidObject.cpm = parseFloat(response.cpm); - bidObject.ad = response.ad; - bidObject.width = response.width; - bidObject.height = response.height; - } else { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); - bidObject.bidderCode = bidObj.bidder; - utils.logMessage('No prebid response from Admedia for placement code ' + placementCode); - } - - bidmanager.addBidResponse(placementCode, bidObject); - }; - - // Export the callBids function, so that prebid.js can execute this function - // when the page asks to send out bid requests. - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new AdmediaAdapter(), 'admedia'); - -module.exports = AdmediaAdapter; diff --git a/modules/admixerBidAdapter.js b/modules/admixerBidAdapter.js deleted file mode 100644 index f7890e81143..00000000000 --- a/modules/admixerBidAdapter.js +++ /dev/null @@ -1,87 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var Ajax = require('src/ajax'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Admixer. - * - * @returns {{callBids: _callBids,responseCallback: _responseCallback}} - */ -var AdmixerAdapter = function AdmixerAdapter() { - var invUrl = '//inv-nets.admixer.net/prebid.aspx'; - var invVastUrl = '//inv-nets.admixer.net/videoprebid.aspx'; - - function _callBids(data) { - var bids = data.bids || []; - for (var i = 0, ln = bids.length; i < ln; i++) { - var bid = bids[i]; - var params = { - 'sizes': utils.parseSizesInput(bid.sizes).join('-'), - 'zone': bid.params && bid.params.zone, - 'callback_uid': bid.placementCode - }; - if (params.zone) { - if (bid.mediaType === 'video') { - var videoParams = {}; - if (typeof bid.video === 'object') { - Object.assign(videoParams, bid.video); - } - Object.assign(videoParams, params); - _requestBid(invVastUrl, params); - } else { - _requestBid(invUrl, params); - } - } else { - var bidObject = bidfactory.createBid(2); - bidObject.bidderCode = 'admixer'; - bidmanager.addBidResponse(params.callback_uid, bidObject); - } - } - } - - function _requestBid(url, params) { - Ajax.ajax(url, _responseCallback, params, {method: 'GET', withCredentials: true}); - } - - function _responseCallback(adUnit) { - try { - adUnit = JSON.parse(adUnit); - } catch (_error) { - adUnit = {result: {cpm: 0}}; - utils.logError(_error); - } - var adUnitCode = adUnit.callback_uid; - var bid = adUnit.result; - var bidObject; - if (bid.cpm > 0) { - bidObject = bidfactory.createBid(1); - bidObject.bidderCode = 'admixer'; - bidObject.cpm = bid.cpm; - if (bid.vastUrl) { - bidObject.mediaType = 'video'; - bidObject.vastUrl = bid.vastUrl; - } else { - bidObject.ad = bid.ad; - } - bidObject.width = bid.width; - bidObject.height = bid.height; - } else { - bidObject = bidfactory.createBid(2); - bidObject.bidderCode = 'admixer'; - } - bidmanager.addBidResponse(adUnitCode, bidObject); - } - - return { - callBids: _callBids, - responseCallback: _responseCallback - }; -}; - -adaptermanager.registerBidAdapter(new AdmixerAdapter(), 'admixer', { - supportedMediaTypes: ['video'] -}); - -module.exports = AdmixerAdapter; diff --git a/modules/adomikAnalyticsAdapter.js b/modules/adomikAnalyticsAdapter.js index c9bd7990ec8..929a4d5deae 100644 --- a/modules/adomikAnalyticsAdapter.js +++ b/modules/adomikAnalyticsAdapter.js @@ -1,7 +1,8 @@ import adapter from 'src/AnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import adaptermanager from 'src/adaptermanager'; -// import utils from 'src/utils'; +import find from 'core-js/library/fn/array/find'; +import findIndex from 'core-js/library/fn/array/find-index'; // Events used in adomik analytics adapter const auctionInit = CONSTANTS.EVENTS.AUCTION_INIT; @@ -139,7 +140,7 @@ adomikAdapter.buildBidResponse = function (bid) { adomikAdapter.sizeUtils = { sizeAlreadyExists: (sizes, typedEventSize) => { - return sizes.find((size) => size.height === typedEventSize.height && size.width === typedEventSize.width); + return find(sizes, (size) => size.height === typedEventSize.height && size.width === typedEventSize.width); }, formatSize: (typedEventSize) => { return { @@ -160,7 +161,7 @@ adomikAdapter.buildTypedEvents = function () { const groupedTypedEvents = []; adomikAdapter.bucketEvents.forEach(function(typedEvent, i) { const [placementCode, type] = [typedEvent.event.placementCode, typedEvent.type]; - let existTypedEvent = groupedTypedEvents.findIndex((groupedTypedEvent) => groupedTypedEvent.placementCode === placementCode); + let existTypedEvent = findIndex(groupedTypedEvents, (groupedTypedEvent) => groupedTypedEvent.placementCode === placementCode); if (existTypedEvent === -1) { groupedTypedEvents.push({ diff --git a/modules/adsupplyBidAdapter.js b/modules/adsupplyBidAdapter.js deleted file mode 100644 index 041437cce98..00000000000 --- a/modules/adsupplyBidAdapter.js +++ /dev/null @@ -1,90 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var utils = require('src/utils'); -var adaptermanager = require('src/adaptermanager'); - -const ADSUPPLY_CODE = 'adsupply'; - -var AdSupplyAdapter = function AdSupplyAdapter() { - function _validateParams(params) { - if (!params || !params.siteId || !params.zoneId || !params.endpointUrl || !params.clientId) { - return false; - } - - if (typeof params.zoneId !== 'number' || params.zoneId <= 0) { - return false; - } - - return true; - } - - function _getRequestUrl(bid) { - var referrerUrl = encodeURIComponent(window.document.referrer); - var rand = encodeURIComponent(Math.floor(Math.random() * 100000 + 1)); - var time = encodeURIComponent(new Date().getTimezoneOffset()); - return '//' + bid.params.endpointUrl + '/banner.engine?id=' + bid.params.siteId + '&z=' + bid.params.zoneId + '&rand=' + rand + '&ver=async' + '&time=' + time + '&referrerurl=' + referrerUrl + '&abr=false' + '&hbt=1&cid=' + encodeURIComponent(bid.params.clientId); - } - - $$PREBID_GLOBAL$$.adSupplyResponseHandler = function (bidId) { - if (!bidId) return; - - var bidRequest = utils.getBidRequest(bidId); - - if (!bidRequest || !bidRequest.params) return; - - var clientId = bidRequest.params.clientId; - var zoneProp = 'b' + bidRequest.params.zoneId; - - if (!window[clientId] || !window[clientId][zoneProp]) return; - - var media = window[clientId][zoneProp].Media; - - if (!media) return; - - if (!media.Url || !media.Ecpm || typeof media.Ecpm !== 'number' || media.Ecpm <= 0) { - var noFillbject = bidfactory.createBid(2, bidRequest); - noFillbject.bidderCode = ADSUPPLY_CODE; - bidmanager.addBidResponse(bidRequest.placementCode, noFillbject); - } else { - var bidObject = bidfactory.createBid(1, bidRequest); - bidObject.bidderCode = ADSUPPLY_CODE; - bidObject.cpm = media.Ecpm; - bidObject.ad = ''; - bidObject.width = media.Width; - bidObject.height = media.Height; - bidmanager.addBidResponse(bidRequest.placementCode, bidObject); - } - }; - - function _makeCallBackHandler(bidId) { - return function () { - $$PREBID_GLOBAL$$.adSupplyResponseHandler(bidId); - }; - } - - function _callBids(params) { - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - if (!_validateParams(bid.params)) continue; - - var clientId = bid.params.clientId; - var zoneProp = 'b' + bid.params.zoneId; - window[clientId] = window[clientId] || {}; - window.window[clientId][zoneProp] = window.window[clientId][zoneProp] || {}; - window.window[clientId][zoneProp].Media = {}; - - var requestUrl = _getRequestUrl(bid); - adloader.loadScript(requestUrl, _makeCallBackHandler(bid.bidId)); - } - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new AdSupplyAdapter(), 'adsupply'); - -module.exports = AdSupplyAdapter; diff --git a/modules/adxcgAnalyticsAdapter.js b/modules/adxcgAnalyticsAdapter.js index 5d2040c8e08..8de0a346ed6 100644 --- a/modules/adxcgAnalyticsAdapter.js +++ b/modules/adxcgAnalyticsAdapter.js @@ -1,12 +1,13 @@ import {ajax} from 'src/ajax'; import adapter from 'src/AnalyticsAdapter'; import adaptermanager from 'src/adaptermanager'; +import CONSTANTS from 'src/constants.json'; import * as url from 'src/url'; import * as utils from 'src/utils'; const emptyUrl = ''; const analyticsType = 'endpoint'; -const adxcgAnalyticsVersion = 'v1.04'; +const adxcgAnalyticsVersion = 'v1.05'; let initOptions; let auctionTimestamp; @@ -22,23 +23,23 @@ var adxcgAnalyticsAdapter = Object.assign(adapter( }), { track({eventType, args}) { if (typeof args !== 'undefined') { - if (eventType === 'bidTimeout') { - events.bidTimeout = args; - } else if (eventType === 'auctionInit') { + if (eventType === CONSTANTS.EVENTS.BID_TIMEOUT) { + events.bidTimeout = args.map(item => item.bidder).filter(utils.uniques); + } else if (eventType === CONSTANTS.EVENTS.AUCTION_INIT) { events.auctionInit = args; auctionTimestamp = args.timestamp; - } else if (eventType === 'bidRequested') { + } else if (eventType === CONSTANTS.EVENTS.BID_REQUESTED) { events.bidRequests.push(args); - } else if (eventType === 'bidResponse') { + } else if (eventType === CONSTANTS.EVENTS.BID_RESPONSE) { events.bidResponses.push(mapBidResponse(args)); - } else if (eventType === 'bidWon') { + } else if (eventType === CONSTANTS.EVENTS.BID_WON) { send({ bidWon: mapBidResponse(args) }); } } - if (eventType === 'auctionEnd') { + if (eventType === CONSTANTS.EVENTS.AUCTION_END) { send(events); } } diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js deleted file mode 100644 index 5192270a94e..00000000000 --- a/modules/adyoulikeBidAdapter.js +++ /dev/null @@ -1,202 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import { format } from 'src/url'; -import { ajax } from 'src/ajax'; -import { STATUS } from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -var AdyoulikeAdapter = function AdyoulikeAdapter() { - const _VERSION = '0.2'; - - const baseAdapter = new Adapter('adyoulike'); - - baseAdapter.callBids = function (bidRequest) { - const bidRequests = {}; - const bids = bidRequest.bids || []; - - const validBids = bids.filter(valid); - validBids.forEach(bid => { bidRequests[bid.params.placement] = bid; }); - - const placements = validBids.map(bid => bid.params.placement); - if (!utils.isEmpty(placements)) { - const body = createBody(bidRequests, placements); - const endpoint = createEndpoint(); - ajax(endpoint, - (response) => { - handleResponse(bidRequests, response); - }, body, { - contentType: 'text/json', - withCredentials: true - }); - } - }; - - /* Create endpoint url */ - function createEndpoint() { - return format({ - protocol: (document.location.protocol === 'https:') ? 'https' : 'http', - host: 'hb-api.omnitagjs.com', - pathname: '/hb-api/prebid', - search: createEndpointQS() - }); - } - - /* Create endpoint query string */ - function createEndpointQS() { - const qs = {}; - - const ref = getReferrerUrl(); - if (ref) { - qs.RefererUrl = encodeURIComponent(ref); - } - - const can = getCanonicalUrl(); - if (can) { - qs.CanonicalUrl = encodeURIComponent(can); - } - - return qs; - } - - /* Create request body */ - function createBody(bidRequests, placements) { - const body = { - Version: _VERSION, - Placements: placements, - TransactionIds: {} - }; - - // performance isn't supported by mobile safari iOS7. window.performance works, but - // evaluates to true on a unit test which expects false. - // - // try/catch was added to un-block the Prebid 0.25 release, but the adyoulike adapter - // maintainers should revisit this and see if it's really what they want. - try { - if (performance && performance.navigation) { - body.PageRefreshed = performance.navigation.type === performance.navigation.TYPE_RELOAD; - } - } catch (e) { - body.PageRefreshed = false; - } - - placements.forEach(placement => { body.TransactionIds[placement] = bidRequests[placement].transactionId; }); - - return JSON.stringify(body); - } - - /* Response handler */ - function handleResponse(bidRequests, response) { - let responses = []; - try { - responses = JSON.parse(response); - } catch (error) { utils.logError(error); } - - const bidResponses = {}; - responses.forEach(response => { - bidResponses[response.Placement] = response; - }); - - Object.keys(bidRequests).forEach(placement => { - addResponse(placement, bidRequests[placement], bidResponses[placement]); - }); - } - - /* Check that a bid has required parameters */ - function valid(bid) { - const sizes = getSize(bid.sizes); - if (!bid.params.placement || !sizes.width || !sizes.height) { - return false; - } - return true; - } - - /* Get current page referrer url */ - function getReferrerUrl() { - let referer = ''; - if (window.self !== window.top) { - try { - referer = window.top.document.referrer; - } catch (e) { } - } else { - referer = document.referrer; - } - return referer; - } - - /* Get current page canonical url */ - function getCanonicalUrl() { - let link; - if (window.self !== window.top) { - try { - link = window.top.document.head.querySelector('link[rel="canonical"][href]'); - } catch (e) { } - } else { - link = document.head.querySelector('link[rel="canonical"][href]'); - } - - if (link) { - return link.href; - } - return ''; - } - - /* Get parsed size from request size */ - function getSize(requestSizes) { - const parsed = {}; - const size = utils.parseSizesInput(requestSizes)[0]; - - if (typeof size !== 'string') { - return parsed; - } - - const parsedSize = size.toUpperCase().split('X'); - const width = parseInt(parsedSize[0], 10); - if (width) { - parsed.width = width; - } - - const height = parseInt(parsedSize[1], 10); - if (height) { - parsed.height = height; - } - - return parsed; - } - - /* Create bid from response */ - function createBid(placementId, bidRequest, response) { - let bid; - if (!response || !response.Banner) { - bid = bidfactory.createBid(STATUS.NO_BID, bidRequest); - } else { - bid = bidfactory.createBid(STATUS.GOOD, bidRequest); - const size = getSize(bidRequest.sizes); - bid.width = size.width; - bid.height = size.height; - bid.cpm = response.Price; - bid.ad = response.Banner; - } - - bid.bidderCode = baseAdapter.getBidderCode(); - - return bid; - } - - /* Add response to bidmanager */ - function addResponse(placementId, bidRequest, response) { - const bid = createBid(placementId, bidRequest, response); - const placement = bidRequest.placementCode; - bidmanager.addBidResponse(placement, bid); - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - }); -}; - -adaptermanager.registerBidAdapter(new AdyoulikeAdapter(), 'adyoulike'); - -module.exports = AdyoulikeAdapter; diff --git a/modules/aerservBidAdapter.js b/modules/aerservBidAdapter.js deleted file mode 100644 index 01966351a82..00000000000 --- a/modules/aerservBidAdapter.js +++ /dev/null @@ -1,116 +0,0 @@ -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -const BIDDER_CODE = 'aerserv'; - -const AerServAdapter = function AerServAdapter() { - const ENVIRONMENTS = { - local: '127.0.0.1:8080', - dev: 'dev-ads.aerserv.com', - stage: 'staging-ads.aerserv.com', - prod: 'ads.aerserv.com' - }; - - const BANNER_PATH = '/as/json/pbjs/v1?'; - const VIDEO_PATH = '/as/json/pbjsvast/v1?'; - const REQUIRED_PARAMS = ['plc']; - - function _isResponseValid(bidRequest, response) { - return ((bidRequest.mediaType === 'video' && response.vastUrl) || (bidRequest.mediaType !== 'video' && response.adm)) && - response.cpm && response.cpm > 0; - } - - function _createBid(bidRequest, response) { - if (_isResponseValid(bidRequest, response)) { - let bid = bidfactory.createBid(1, bidRequest); - bid.bidderCode = BIDDER_CODE; - bid.cpm = response.cpm; - bid.width = response.w; - bid.height = response.h; - if (bidRequest.mediaType === 'video') { - bid.vastUrl = response.vastUrl; - bid.mediaType = 'video'; - } else { - bid.ad = response.adm; - } - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } else { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); - } - } - - function _getFirstSize(sizes) { - let sizeObj = {}; - if (utils.isArray(sizes) && sizes.length > 0 && utils.isArray(sizes[0]) && sizes[0].length === 2) { - sizeObj['vpw'] = sizes[0][0]; - sizeObj['vph'] = sizes[0][1]; - } - return sizeObj; - } - - function _buildQueryParameters(bid, requestParams) { - Object.keys(bid.params).filter(param => param !== 'video') - .forEach(param => requestParams[param] = bid.params[param]); - - if (bid.mediaType === 'video') { - let videoDimensions = _getFirstSize(bid.sizes); - Object.keys(videoDimensions).forEach(param => requestParams[param] = videoDimensions[param]); - Object.keys(bid.params.video || {}).forEach(param => requestParams[param] = bid.params.video[param]); - } - - return utils.parseQueryStringParameters(requestParams); - } - - function _handleResponse(bidRequest) { - return response => { - if (!response && response.length <= 0) { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); - utils.logError('Empty response'); - return; - } - - try { - response = JSON.parse(response); - } catch (e) { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); - utils.logError('Invalid JSON in response'); - return; - } - - _createBid(bidRequest, response); - }; - } - - function _callBids(bidRequests) { - let currentUrl = (window.parent !== window) ? document.referrer : window.location.href; - currentUrl = currentUrl && encodeURIComponent(currentUrl); - - let bids = bidRequests.bids || []; - bids.forEach(bid => { - if (utils.hasValidBidRequest(bid.params, REQUIRED_PARAMS, BIDDER_CODE)) { - let env = ENVIRONMENTS[bid.params['env']] || ENVIRONMENTS['prod']; - let requestPath = bid.mediaType === 'video' ? VIDEO_PATH : BANNER_PATH; - let pageParameters = {url: currentUrl}; - let parameterStr = _buildQueryParameters(bid, pageParameters); - - let url = `//${env}${requestPath}${parameterStr}`; - utils.logMessage('sending request to: ' + url); - ajax(url, _handleResponse(bid), null, {withCredentials: true}); - } else { - bidmanager.addBidResponse(bid.placementCode, bidfactory.createBid(STATUS.NO_BID, bid)); - } - }); - } - - return { - callBids: _callBids - } -}; - -adaptermanager.registerBidAdapter(new AerServAdapter(), BIDDER_CODE, {supportedMediaTypes: ['video']}); - -module.exports = AerServAdapter; diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index c76bd1ccfd6..71b1e4f7902 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -61,12 +61,18 @@ let showCpmAdjustmentWarning = (function () { }; })(); +function isInteger(value) { + return typeof value === 'number' && + isFinite(value) && + Math.floor(value) === value; +} + function template(strings, ...keys) { return function(...values) { let dict = values[values.length - 1] || {}; let result = [strings[0]]; keys.forEach(function(key, i) { - let value = Number.isInteger(key) ? values[key] : dict[key]; + let value = isInteger(key) ? values[key] : dict[key]; result.push(value, strings[i + 1]); }); return result.join(''); diff --git a/modules/appnexusAstBidAdapter.js b/modules/appnexusAstBidAdapter.js deleted file mode 100644 index 94a028f9868..00000000000 --- a/modules/appnexusAstBidAdapter.js +++ /dev/null @@ -1,430 +0,0 @@ -import { Renderer } from 'src/Renderer'; -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; - -const BIDDER_CODE = 'appnexusAst'; -const URL = '//ib.adnxs.com/ut/v3/prebid'; -const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', - 'startdelay', 'skippable', 'playback_method', 'frameworks']; -const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'language']; -const NATIVE_MAPPING = { - body: 'description', - cta: 'ctatext', - image: { - serverName: 'main_image', - requiredParams: { required: true }, - minimumParams: { sizes: [{}] }, - }, - icon: { - serverName: 'icon', - requiredParams: { required: true }, - minimumParams: { sizes: [{}] }, - }, - sponsoredBy: 'sponsored_by', -}; -const SOURCE = 'pbjs'; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO, NATIVE], - - /** - * 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 !!(bid.params.placementId || (bid.params.member && bid.params.invCode)); - }, - - /** - * 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) { - const tags = bidRequests.map(bidToTag); - const userObjBid = bidRequests.find(hasUserInfo); - let userObj; - if (userObjBid) { - userObj = {}; - Object.keys(userObjBid.params.user) - .filter(param => USER_PARAMS.includes(param)) - .forEach(param => userObj[param] = userObjBid.params.user[param]); - } - - const memberIdBid = bidRequests.find(hasMemberId); - const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; - - const payload = { - tags: [...tags], - user: userObj, - sdk: { - source: SOURCE, - version: '$prebid.version$' - } - }; - if (member > 0) { - payload.member_id = member; - } - const payloadString = JSON.stringify(payload); - return { - method: 'POST', - url: URL, - data: payloadString, - 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, {bidderRequest}) { - serverResponse = serverResponse.body; - const bids = []; - if (!serverResponse || serverResponse.error) { - let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; - if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } - utils.logError(errorMessage); - return bids; - } - - if (serverResponse.tags) { - serverResponse.tags.forEach(serverBid => { - const rtbBid = getRtbBid(serverBid); - if (rtbBid) { - if (rtbBid.cpm !== 0 && this.supportedMediaTypes.includes(rtbBid.ad_type)) { - const bid = newBid(serverBid, rtbBid); - bid.mediaType = parseMediaType(rtbBid); - bids.push(bid); - } - } - }); - } - return bids; - }, - - getUserSyncs: function(syncOptions) { - if (syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' - }]; - } - } -} - -function newRenderer(adUnitCode, rtbBid) { - const renderer = Renderer.install({ - id: rtbBid.renderer_id, - url: rtbBid.renderer_url, - config: { adText: `AppNexus Outstream Video Ad via Prebid.js` }, - loaded: false, - }); - - try { - renderer.setRender(outstreamRender); - } catch (err) { - utils.logWarn('Prebid Error calling setRender on renderer', err); - } - - renderer.setEventHandlers({ - impression: () => utils.logMessage('AppNexus outstream video impression event'), - loaded: () => utils.logMessage('AppNexus outstream video loaded event'), - ended: () => { - utils.logMessage('AppNexus outstream renderer video event'); - document.querySelector(`#${adUnitCode}`).style.display = 'none'; - } - }); - return renderer; -} - -/* Turn keywords parameter into ut-compatible format */ -function getKeywords(keywords) { - let arrs = []; - - utils._each(keywords, (v, k) => { - if (utils.isArray(v)) { - let values = []; - utils._each(v, (val) => { - val = utils.getValueString('keywords.' + k, val); - if (val) { values.push(val); } - }); - v = values; - } else { - v = utils.getValueString('keywords.' + k, v); - if (utils.isStr(v)) { - v = [v]; - } else { - return; - } // unsuported types - don't send a key - } - arrs.push({key: k, value: v}); - }); - - return arrs; -} - -/** - * Unpack the Server's Bid into a Prebid-compatible one. - * @param serverBid - * @param rtbBid - * @return Bid - */ -function newBid(serverBid, rtbBid) { - const bid = { - requestId: serverBid.uuid, - cpm: rtbBid.cpm, - creativeId: rtbBid.creative_id, - dealId: rtbBid.deal_id, - currency: 'USD', - netRevenue: true, - ttl: 300 - }; - - if (rtbBid.rtb.video) { - Object.assign(bid, { - width: rtbBid.rtb.video.player_width, - height: rtbBid.rtb.video.player_height, - vastUrl: rtbBid.rtb.video.asset_url, - ttl: 3600 - }); - // This supports Outstream Video - if (rtbBid.renderer_url) { - Object.assign(bid, { - adResponse: serverBid, - renderer: newRenderer(bid.adUnitCode, rtbBid) - }); - bid.adResponse.ad = bid.adResponse.ads[0]; - bid.adResponse.ad.video = bid.adResponse.ad.rtb.video; - } - } else if (rtbBid.rtb[NATIVE]) { - const nativeAd = rtbBid.rtb[NATIVE]; - bid[NATIVE] = { - title: nativeAd.title, - body: nativeAd.desc, - cta: nativeAd.ctatext, - sponsoredBy: nativeAd.sponsored, - image: { - url: nativeAd.main_img && nativeAd.main_img.url, - height: nativeAd.main_img && nativeAd.main_img.height, - width: nativeAd.main_img && nativeAd.main_img.width, - }, - icon: { - url: nativeAd.icon && nativeAd.icon.url, - height: nativeAd.icon && nativeAd.icon.height, - width: nativeAd.icon && nativeAd.icon.width, - }, - clickUrl: nativeAd.link.url, - clickTrackers: nativeAd.link.click_trackers, - impressionTrackers: nativeAd.impression_trackers, - }; - } else { - Object.assign(bid, { - width: rtbBid.rtb.banner.width, - height: rtbBid.rtb.banner.height, - ad: rtbBid.rtb.banner.content - }); - try { - const url = rtbBid.rtb.trackers[0].impression_urls[0]; - const tracker = utils.createTrackPixelHtml(url); - bid.ad += tracker; - } catch (error) { - utils.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; - if (bid.params.reserve) { - tag.reserve = bid.params.reserve; - } - 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 = getSizes(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.externalImpId) { - tag.external_imp_id = bid.params.externalImpId; - } - if (!utils.isEmpty(bid.params.keywords)) { - tag.keywords = getKeywords(bid.params.keywords); - } - - if (bid.mediaType === NATIVE || utils.deepAccess(bid, 'mediaTypes.native')) { - tag.ad_types.push(NATIVE); - - if (bid.nativeParams) { - const nativeRequest = buildNativeRequest(bid.nativeParams); - tag[NATIVE] = {layouts: [nativeRequest]}; - } - } - - const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - - 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 => VIDEO_TARGETING.includes(param)) - .forEach(param => tag.video[param] = bid.params.video[param]); - } - - if ( - (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) || - (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER])) - ) { - tag.ad_types.push(BANNER); - } - - return tag; -} - -/* Turn bid request sizes into ut-compatible format */ -function transformSizes(requestSizes) { - let sizes = []; - let sizeObj = {}; - - 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); - } 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 getRtbBid(tag) { - return tag && tag.ads && tag.ads.length && tag.ads.find(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]); - - // minimum params are passed if no non-required params given on adunit - const minimumParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].minimumParams; - - if (requiredParams && minimumParams) { - // subtract required keys from adunit keys - const adunitKeys = Object.keys(params[key]); - const requiredKeys = Object.keys(requiredParams); - const remaining = adunitKeys.filter(key => !requiredKeys.includes(key)); - - // if none are left over, the minimum params needs to be sent - if (remaining.length === 0) { - request[requestKey] = Object.assign({}, request[requestKey], minimumParams); - } - } - }); - - return request; -} - -function outstreamRender(bid) { - // 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; - } -} - -registerBidder(spec); diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 1fb48b68fc4..d46be776b59 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -1,237 +1,422 @@ -import { getBidRequest } from 'src/utils'; -import adaptermanager from 'src/adaptermanager'; - -var CONSTANTS = require('src/constants'); -var utils = require('src/utils'); -var adloader = require('src/adloader'); -var bidmanager = require('src/bidmanager'); -var bidfactory = require('src/bidfactory'); -var Adapter = require('src/adapter').default; - -var AppNexusAdapter; -AppNexusAdapter = function AppNexusAdapter() { - var baseAdapter = new Adapter('appnexus'); - var usersync = false; - - baseAdapter.callBids = function (params) { - // var bidCode = baseAdapter.getBidderCode(); - - var anArr = params.bids; - - // var bidsCount = anArr.length; - - // set expected bids count for callback execution - // bidmanager.setExpectedBidsCount(bidCode, bidsCount); +import { Renderer } from 'src/Renderer'; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { NATIVE, VIDEO } from 'src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; + +const BIDDER_CODE = 'appnexus'; +const URL = '//ib.adnxs.com/ut/v3/prebid'; +const SUPPORTED_AD_TYPES = ['banner', 'video', 'native']; +const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', + 'startdelay', 'skippable', 'playback_method', 'frameworks']; +const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'language']; +const NATIVE_MAPPING = { + body: 'description', + cta: 'ctatext', + image: { + serverName: 'main_image', + requiredParams: { required: true }, + minimumParams: { sizes: [{}] }, + }, + icon: { + serverName: 'icon', + requiredParams: { required: true }, + minimumParams: { sizes: [{}] }, + }, + sponsoredBy: 'sponsored_by', +}; +const SOURCE = 'pbjs'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['appnexusAst', 'brealtime', 'pagescience', 'defymedia', 'gourmetads', 'matomy', 'featureforward', 'oftmedia'], + supportedMediaTypes: [VIDEO, NATIVE], + + /** + * 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 !!(bid.params.placementId || (bid.params.member && bid.params.invCode)); + }, + + /** + * 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) { + const tags = bidRequests.map(bidToTag); + const userObjBid = find(bidRequests, hasUserInfo); + let userObj; + if (userObjBid) { + userObj = {}; + Object.keys(userObjBid.params.user) + .filter(param => includes(USER_PARAMS, param)) + .forEach(param => userObj[param] = userObjBid.params.user[param]); + } - for (var i = 0; i < anArr.length; i++) { - var bidRequest = anArr[i]; - var callbackId = bidRequest.bidId; - adloader.loadScript(buildJPTCall(bidRequest, callbackId)); + const memberIdBid = find(bidRequests, hasMemberId); + const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; - // store a reference to the bidRequest from the callback id - // bidmanager.pbCallbackMap[callbackId] = bidRequest; + const payload = { + tags: [...tags], + user: userObj, + sdk: { + source: SOURCE, + version: '$prebid.version$' + } + }; + if (member > 0) { + payload.member_id = member; } - }; - - function buildJPTCall(bid, callbackId) { - // determine tag params - var placementId = utils.getBidIdParameter('placementId', bid.params); - - // memberId will be deprecated, use member instead - var memberId = utils.getBidIdParameter('memberId', bid.params); - var member = utils.getBidIdParameter('member', bid.params); - var inventoryCode = utils.getBidIdParameter('invCode', bid.params); - var query = utils.getBidIdParameter('query', bid.params); - var referrer = utils.getBidIdParameter('referrer', bid.params); - var altReferrer = utils.getBidIdParameter('alt_referrer', bid.params); - let usePaymentRule = utils.getBidIdParameter('usePaymentRule', bid.params); - var jptCall = '//ib.adnxs.com/jpt?'; - - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleAnCB'); - jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); - jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); - jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); - jptCall = utils.tryAppendQueryString(jptCall, 'use_pmt_rule', usePaymentRule); - - if (member) { - jptCall = utils.tryAppendQueryString(jptCall, 'member', member); - } else if (memberId) { - jptCall = utils.tryAppendQueryString(jptCall, 'member', memberId); - utils.logMessage('appnexus.callBids: "memberId" will be deprecated soon. Please use "member" instead'); + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: URL, + data: payloadString, + 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, {bidderRequest}) { + serverResponse = serverResponse.body; + const bids = []; + if (!serverResponse || serverResponse.error) { + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; + if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } + utils.logError(errorMessage); + return bids; } - jptCall = utils.tryAppendQueryString(jptCall, 'code', inventoryCode); - jptCall = utils.tryAppendQueryString(jptCall, 'traffic_source_code', (utils.getBidIdParameter('trafficSourceCode', bid.params))); - - // sizes takes a bit more logic - var sizeQueryString = ''; - var parsedSizes = utils.parseSizesInput(bid.sizes); - - // combine string into proper querystring for impbus - var parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // first value should be "size" - sizeQueryString = 'size=' + parsedSizes[0]; - if (parsedSizesLength > 1) { - // any subsequent values should be "promo_sizes" - sizeQueryString += '&promo_sizes='; - for (var j = 1; j < parsedSizesLength; j++) { - sizeQueryString += parsedSizes[j] += ','; + if (serverResponse.tags) { + serverResponse.tags.forEach(serverBid => { + const rtbBid = getRtbBid(serverBid); + if (rtbBid) { + if (rtbBid.cpm !== 0 && includes(SUPPORTED_AD_TYPES, rtbBid.ad_type)) { + const bid = newBid(serverBid, rtbBid); + bid.mediaType = parseMediaType(rtbBid); + bids.push(bid); + } } - - // remove trailing comma - if (sizeQueryString && sizeQueryString.charAt(sizeQueryString.length - 1) === ',') { - sizeQueryString = sizeQueryString.slice(0, sizeQueryString.length - 1); - } - } + }); } - - if (sizeQueryString) { - jptCall += sizeQueryString + '&'; + return bids; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' + }]; } + } +} + +function newRenderer(adUnitCode, rtbBid) { + const renderer = Renderer.install({ + id: rtbBid.renderer_id, + url: rtbBid.renderer_url, + config: { adText: `AppNexus Outstream Video Ad via Prebid.js` }, + loaded: false, + }); - // this will be deprecated soon - var targetingParams = utils.parseQueryStringParameters(query); - - if (targetingParams) { - // don't append a & here, we have already done it in parseQueryStringParameters - jptCall += targetingParams; - } + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } - // append custom attributes: - var paramsCopy = Object.assign({}, bid.params); - - // delete attributes already used - delete paramsCopy.placementId; - delete paramsCopy.memberId; - delete paramsCopy.invCode; - delete paramsCopy.query; - delete paramsCopy.referrer; - delete paramsCopy.alt_referrer; - delete paramsCopy.member; - delete paramsCopy.usePaymentRule; - - // get the reminder - var queryParams = utils.parseQueryStringParameters(paramsCopy); - - // append - if (queryParams) { - jptCall += queryParams; + renderer.setEventHandlers({ + impression: () => utils.logMessage('AppNexus outstream video impression event'), + loaded: () => utils.logMessage('AppNexus outstream video loaded event'), + ended: () => { + utils.logMessage('AppNexus outstream renderer video event'); + document.querySelector(`#${adUnitCode}`).style.display = 'none'; } - - // append referrer - if (referrer === '') { - referrer = utils.getTopWindowUrl(); + }); + return renderer; +} + +/* Turn keywords parameter into ut-compatible format */ +function getKeywords(keywords) { + let arrs = []; + + utils._each(keywords, (v, k) => { + if (utils.isArray(v)) { + let values = []; + utils._each(v, (val) => { + val = utils.getValueString('keywords.' + k, val); + if (val) { values.push(val); } + }); + v = values; + } else { + v = utils.getValueString('keywords.' + k, v); + if (utils.isStr(v)) { + v = [v]; + } else { + return; + } // unsuported types - don't send a key } + arrs.push({key: k, value: v}); + }); - jptCall = utils.tryAppendQueryString(jptCall, 'referrer', referrer); - jptCall = utils.tryAppendQueryString(jptCall, 'alt_referrer', altReferrer); + return arrs; +} + +/** + * Unpack the Server's Bid into a Prebid-compatible one. + * @param serverBid + * @param rtbBid + * @return Bid + */ +function newBid(serverBid, rtbBid) { + const bid = { + requestId: serverBid.uuid, + cpm: rtbBid.cpm, + creativeId: rtbBid.creative_id, + dealId: rtbBid.deal_id, + currency: 'USD', + netRevenue: true, + ttl: 300 + }; - // remove the trailing "&" - if (jptCall.lastIndexOf('&') === jptCall.length - 1) { - jptCall = jptCall.substring(0, jptCall.length - 1); + if (rtbBid.rtb.video) { + Object.assign(bid, { + width: rtbBid.rtb.video.player_width, + height: rtbBid.rtb.video.player_height, + vastUrl: rtbBid.rtb.video.asset_url, + descriptionUrl: rtbBid.rtb.video.asset_url, + ttl: 3600 + }); + // This supports Outstream Video + if (rtbBid.renderer_url) { + Object.assign(bid, { + adResponse: serverBid, + renderer: newRenderer(bid.adUnitCode, rtbBid) + }); + bid.adResponse.ad = bid.adResponse.ads[0]; + bid.adResponse.ad.video = bid.adResponse.ad.rtb.video; } + } else if (rtbBid.rtb['native']) { + const nativeAd = rtbBid.rtb['native']; + bid['native'] = { + title: nativeAd.title, + body: nativeAd.desc, + cta: nativeAd.ctatext, + sponsoredBy: nativeAd.sponsored, + image: { + url: nativeAd.main_img && nativeAd.main_img.url, + height: nativeAd.main_img && nativeAd.main_img.height, + width: nativeAd.main_img && nativeAd.main_img.width, + }, + icon: { + url: nativeAd.icon && nativeAd.icon.url, + height: nativeAd.icon && nativeAd.icon.height, + width: nativeAd.icon && nativeAd.icon.width, + }, + clickUrl: nativeAd.link.url, + clickTrackers: nativeAd.link.click_trackers, + impressionTrackers: nativeAd.impression_trackers, + }; + } else { + Object.assign(bid, { + width: rtbBid.rtb.banner.width, + height: rtbBid.rtb.banner.height, + ad: rtbBid.rtb.banner.content + }); + try { + const url = rtbBid.rtb.trackers[0].impression_urls[0]; + const tracker = utils.createTrackPixelHtml(url); + bid.ad += tracker; + } catch (error) { + utils.logError('Error appending tracking pixel', error); + } + } - // @if NODE_ENV='debug' - utils.logMessage('jpt request built: ' + jptCall); - - // @endif + return bid; +} + +function bidToTag(bid) { + const tag = {}; + tag.sizes = transformSizes(bid.sizes); + tag.primary_size = tag.sizes[0]; + 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; + if (bid.params.reserve) { + tag.reserve = bid.params.reserve; + } + 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 = getSizes(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.externalImpId) { + tag.external_imp_id = bid.params.externalImpId; + } + if (!utils.isEmpty(bid.params.keywords)) { + tag.keywords = getKeywords(bid.params.keywords); + } - // append a timer here to track latency - bid.startTime = new Date().getTime(); + if (bid.mediaType === 'native' || utils.deepAccess(bid, 'mediaTypes.native')) { + tag.ad_types = ['native']; - return jptCall; + if (bid.nativeParams) { + const nativeRequest = buildNativeRequest(bid.nativeParams); + tag['native'] = {layouts: [nativeRequest]}; + } } - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleAnCB = function (jptResponseObj) { - var bidCode; - - if (jptResponseObj && jptResponseObj.callback_uid) { - var responseCPM; - var id = jptResponseObj.callback_uid; - var placementCode = ''; - var bidObj = getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - placementCode = bidObj.placementCode; + if (bid.mediaType === 'video' || (videoMediaType && context !== 'outstream')) { + tag.require_asset_url = true; + } - // set the status - bidObj.status = CONSTANTS.STATUS.GOOD; - } + 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 => tag.video[param] = bid.params.video[param]); + } - // @if NODE_ENV='debug' - utils.logMessage('JSONP callback function called for ad ID: ' + id); - - // @endif - var bid = []; - if (jptResponseObj.result && jptResponseObj.result.cpm && jptResponseObj.result.cpm !== 0) { - responseCPM = parseInt(jptResponseObj.result.cpm, 10); - - // CPM response from /jpt is dollar/cent multiplied by 10000 - // in order to avoid using floats - // switch CPM to "dollar/cent" - responseCPM = responseCPM / 10000; - - // store bid response - // bid status is good (indicating 1) - var adId = jptResponseObj.result.creative_id; - bid = bidfactory.createBid(1, bidObj); - bid.creative_id = adId; - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - bid.adUrl = jptResponseObj.result.ad; - bid.width = jptResponseObj.result.width; - bid.height = jptResponseObj.result.height; - bid.dealId = jptResponseObj.result.deal_id; - - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response from AppNexus for placement code ' + placementCode); - - // @endif - // indicate that there is no bid for this placement - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } + return tag; +} + +/* Turn bid request sizes into ut-compatible format */ +function transformSizes(requestSizes) { + let sizes = []; + let sizeObj = {}; + + 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); + } 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); + } + } - if (!usersync) { - var iframe = utils.createInvisibleIframe(); - iframe.src = '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html'; - try { - document.body.appendChild(iframe); - } catch (error) { - utils.logError(error); - } - usersync = true; + return sizes; +} + +function hasUserInfo(bid) { + return !!bid.params.user; +} + +function hasMemberId(bid) { + return !!parseInt(bid.params.member, 10); +} + +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]); + + // minimum params are passed if no non-required params given on adunit + const minimumParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].minimumParams; + + if (requiredParams && minimumParams) { + // subtract required keys from adunit keys + const adunitKeys = Object.keys(params[key]); + const requiredKeys = Object.keys(requiredParams); + const remaining = adunitKeys.filter(key => !includes(requiredKeys, key)); + + // if none are left over, the minimum params needs to be sent + if (remaining.length === 0) { + request[requestKey] = Object.assign({}, request[requestKey], minimumParams); } - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - - // @endif } - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - buildJPTCall: buildJPTCall }); -}; -adaptermanager.registerBidAdapter(new AppNexusAdapter(), 'appnexus'); -adaptermanager.aliasBidAdapter('appnexus', 'brealtime'); -adaptermanager.aliasBidAdapter('appnexus', 'pagescience'); -adaptermanager.aliasBidAdapter('appnexus', 'defymedia'); -adaptermanager.aliasBidAdapter('appnexus', 'gourmetads'); -adaptermanager.aliasBidAdapter('appnexus', 'matomy'); -adaptermanager.aliasBidAdapter('appnexus', 'featureforward'); -adaptermanager.aliasBidAdapter('appnexus', 'oftmedia'); + return request; +} + +function outstreamRender(bid) { + // 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'; + } +} -module.exports = AppNexusAdapter; +registerBidder(spec); diff --git a/modules/appnexusAstBidAdapter.md b/modules/appnexusBidAdapter.md similarity index 87% rename from modules/appnexusAstBidAdapter.md rename to modules/appnexusBidAdapter.md index 2b370e11616..58f260cdfc8 100644 --- a/modules/appnexusAstBidAdapter.md +++ b/modules/appnexusBidAdapter.md @@ -1,7 +1,7 @@ # Overview ``` -Module Name: AppnexusAst Bid Adapter +Module Name: Appnexus Bid Adapter Module Type: Bidder Adapter Maintainer: info@prebid.org ``` @@ -10,7 +10,7 @@ Maintainer: info@prebid.org Connects to Appnexus exchange for bids. -AppnexusAst bid adapter supports Banner, Video (instream and outstream) and Native. +Appnexus bid adapter supports Banner, Video (instream and outstream) and Native. # Test Parameters ``` @@ -20,7 +20,7 @@ var adUnits = [ code: 'banner-div', sizes: [[300, 250], [300,600]], bids: [{ - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '10433394' } @@ -51,7 +51,7 @@ var adUnits = [ } }, bids: [{ - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '9880618' } @@ -67,7 +67,7 @@ var adUnits = [ }, }, bids: [{ - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '9333431', video: { @@ -88,7 +88,7 @@ var adUnits = [ }, bids: [ { - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '5768085', video: { diff --git a/modules/atomxBidAdapter.js b/modules/atomxBidAdapter.js deleted file mode 100644 index 69bb04a227b..00000000000 --- a/modules/atomxBidAdapter.js +++ /dev/null @@ -1,81 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var Ajax = require('src/ajax'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Atomx. - * - * @returns {{callBids: _callBids, responseCallback: _responseCallback}} - */ -var AtomxAdapter = function AtomxAdapter() { - function _callBids(data) { - if (!window.atomx_prebid) { - adloader.loadScript(window.location.protocol + '//s.ato.mx/b.js', function() { _bid(data); }, true); - } else { - _bid(data); - } - } - - function _bid(data) { - var url = window.atomx_prebid(); - var bids = data.bids || []; - for (var i = 0, ln = bids.length; i < ln; i++) { - var bid = bids[i]; - if (bid.params && bid.params.id) { - var sizes = utils.parseSizesInput(bid.sizes); - for (var j = 0; j < sizes.length; j++) { - Ajax.ajax(url, _responseCallback.bind(this, bid), { - id: bid.params.id, - size: sizes[j], - prebid: bid.placementCode - }, {method: 'GET', noDecodeWholeURL: true}); - } - } else { - var bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bid); - bidObject.bidderCode = 'atomx'; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - } - } - - function _responseCallback(bid, data) { - var bidObject; - try { - data = JSON.parse(data); - - if (data.cpm && data.cpm > 0) { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.GOOD, bid); - bidObject.bidderCode = 'atomx'; - bidObject.cpm = data.cpm * 1000; - if (data.adm) { - bidObject.ad = data.adm; - } else { - bidObject.adUrl = data.url; - } - bidObject.width = data.width; - bidObject.height = data.height; - bidmanager.addBidResponse(bid.placementCode, bidObject); - return; - } - } catch (_error) { - utils.logError(_error); - } - - bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bid); - bidObject.bidderCode = 'atomx'; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - - return { - callBids: _callBids, - responseCallback: _responseCallback - }; -}; - -adaptermanager.registerBidAdapter(new AtomxAdapter(), 'atomx'); - -module.exports = AtomxAdapter; diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 04df8e845c9..41ca539ccba 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -5,6 +5,8 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; import { formatQS } from 'src/url'; import { getTopWindowUrl } from 'src/utils'; +import findIndex from 'core-js/library/fn/array/find-index'; +import includes from 'core-js/library/fn/array/includes'; const code = 'audienceNetwork'; const currency = 'USD'; @@ -47,7 +49,7 @@ const expandSize = size => size.split('x').map(Number); * @param {String} size * @returns {Boolean} */ -const isValidSize = size => ['300x250', '320x50'].includes(size); +const isValidSize = size => includes(['300x250', '320x50'], size); /** * Is this a video format? @@ -139,7 +141,7 @@ const buildRequests = bids => { pageurl, sdk }; - const video = adformats.findIndex(isVideo); + const video = findIndex(adformats, isVideo); if (video !== -1) { [search.playerwidth, search.playerheight] = sizes[video].split('x').map(Number) } diff --git a/modules/bidfluenceBidAdapter.js b/modules/bidfluenceBidAdapter.js deleted file mode 100644 index 73b548a4993..00000000000 --- a/modules/bidfluenceBidAdapter.js +++ /dev/null @@ -1,58 +0,0 @@ -const bidmanager = require('src/bidmanager'); -const bidfactory = require('src/bidfactory'); -const utils = require('src/utils'); -const adloader = require('src/adloader'); -const adaptermanager = require('src/adaptermanager'); - -var BidfluenceAdapter = function BidfluenceAdapter() { - const scriptUrl = '//cdn.bidfluence.com/forge.js'; - - $$PREBID_GLOBAL$$.bfPbjsCB = function (bfr) { - var bidRequest = utils.getBidRequest(bfr.cbID); - var bidObject = null; - if (bfr.cpm > 0) { - bidObject = bidfactory.createBid(1, bidRequest); - bidObject.bidderCode = 'bidfluence'; - bidObject.cpm = bfr.cpm; - bidObject.ad = bfr.ad; - bidObject.width = bfr.width; - bidObject.height = bfr.height; - } else { - bidObject = bidfactory.createBid(2, bidRequest); - bidObject.bidderCode = 'bidfluence'; - } - - bidmanager.addBidResponse(bfr.placementCode, bidObject); - }; - - function _callBids(params) { - var bfbids = params.bids || []; - for (var i = 0; i < bfbids.length; i++) { - var bid = bfbids[i]; - call(bid); - } - } - function call(bid) { - var adunitId = utils.getBidIdParameter('adunitId', bid.params); - var publisherId = utils.getBidIdParameter('pubId', bid.params); - var reservePrice = utils.getBidIdParameter('reservePrice', bid.params); - var pbjsBfobj = { - placementCode: bid.placementCode, - cbID: bid.bidId - }; - - var cb = function () { - /* globals FORGE */ - FORGE.init([adunitId, publisherId, pbjsBfobj, reservePrice]); - }; - - adloader.loadScript(scriptUrl, cb); - } - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new BidfluenceAdapter(), 'bidfluence'); - -module.exports = BidfluenceAdapter; diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index d224355c3a5..ec70342c964 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -1,5 +1,6 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'bridgewell'; const REQUEST_ENDPOINT = '//rec.scupio.com/recweb/prebid.aspx'; @@ -58,8 +59,8 @@ export const spec = { return; } - let matchedResponse = serverResponse.body.find(function(res) { - return !!res && !res.consumed && req.sizes.find(function(size) { + let matchedResponse = find(serverResponse.body, function(res) { + return !!res && !res.consumed && find(req.sizes, function(size) { return res.width === size[0] && res.height === size[1]; }); }); diff --git a/modules/brightcomBidAdapter.js b/modules/brightcomBidAdapter.js deleted file mode 100644 index f1256edeab8..00000000000 --- a/modules/brightcomBidAdapter.js +++ /dev/null @@ -1,205 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Brightcom - */ -var BrightcomAdapter = function BrightcomAdapter() { - // Set Brightcom Bidder URL - var brightcomUrl = 'hb.iselephant.com/auc/ortb'; - - // Define the bidder code - var brightcomBidderCode = 'brightcom'; - - // Define the callback function - var brightcomCallbackFunction = 'window.$$PREBID_GLOBAL$$=window.$$PREBID_GLOBAL$$||window.parent.$$PREBID_GLOBAL$$||window.top.$$PREBID_GLOBAL$$;window.$$PREBID_GLOBAL$$.brightcomResponse'; - - // Manage the requested and received ad units' codes, to know which are invalid (didn't return) - const reqAdUnitsCode = []; - const resAdUnitsCode = []; - - function _callBids(params) { - var bidRequests = params.bids || []; - - // Get page data - var siteDomain = window.location.host; - var sitePage = window.location.href; - - // Prepare impressions object - var brightcomImps = []; - - // Prepare a variable for publisher id - var pubId = ''; - - // Go through the requests and build array of impressions - utils._each(bidRequests, function(bid) { - // Get impression details - var tagId = utils.getBidIdParameter('tagId', bid.params); - var ref = utils.getBidIdParameter('ref', bid.params); - var adWidth = 0; - var adHeight = 0; - - // If no publisher id is set, use the current - if (pubId === '') { - // Get the current publisher id (if it doesn't exist, it'll return '') - pubId = utils.getBidIdParameter('pubId', bid.params); - } - - // Brightcom supports only 1 size per impression - // Check if the array contains 1 size or array of sizes - if (bid.sizes.length === 2 && typeof bid.sizes[0] === 'number' && typeof bid.sizes[1] === 'number') { - // The array contains 1 size (the items are the values) - adWidth = bid.sizes[0]; - adHeight = bid.sizes[1]; - } else { - // The array contains array of sizes, use the first size - adWidth = bid.sizes[0][0]; - adHeight = bid.sizes[0][1]; - } - - // Build the impression - var imp = { - id: utils.getUniqueIdentifierStr(), - banner: { - w: adWidth, - h: adHeight - }, - tagid: tagId - }; - - // If ref exists, create it (in the "ext" object) - if (ref !== '') { - imp.ext = { - refoverride: ref - }; - } - - // Add current impression to collection - brightcomImps.push(imp); - // Add mapping to current bid via impression id - // bidmanager.pbCallbackMap[imp.id] = bid; - - // Add current ad unit's code to tracking - reqAdUnitsCode.push(bid.placementCode); - }); - - // Build the bid request - var brightcomBidReq = { - id: utils.getUniqueIdentifierStr(), - imp: brightcomImps, - site: { - publisher: { - id: pubId - }, - domain: siteDomain, - page: sitePage - } - }; - - // Add timeout data, if available - var PREBID_TIMEOUT = PREBID_TIMEOUT || 0; - var curTimeout = PREBID_TIMEOUT; - if (curTimeout > 0) { - brightcomBidReq.tmax = curTimeout; - } - - // Define the bid request call URL - var bidRequestCallUrl = 'https://' + brightcomUrl + - '?callback=' + encodeURIComponent(brightcomCallbackFunction) + - '&request=' + encodeURIComponent(JSON.stringify(brightcomBidReq)); - - // Add the call to get the bid - adloader.loadScript(bidRequestCallUrl); - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.brightcomResponse = function(brightcomResponseObj) { - var bid = {}; - - // Make sure response is valid - if ( - (brightcomResponseObj) && (brightcomResponseObj.id) && - (brightcomResponseObj.seatbid) && (brightcomResponseObj.seatbid.length !== 0) && - (brightcomResponseObj.seatbid[0].bid) && (brightcomResponseObj.seatbid[0].bid.length !== 0) - ) { - // Go through the received bids - brightcomResponseObj.seatbid[0].bid.forEach(function(curBid) { - // Get the bid request data - var bidRequest = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'brightcom').bids[0]; // this assumes a single request only - - // Make sure the bid exists - if (bidRequest) { - var placementCode = bidRequest.placementCode; - bidRequest.status = CONSTANTS.STATUS.GOOD; - - curBid.placementCode = placementCode; - curBid.size = bidRequest.sizes; - - // Get the creative - var responseCreative = curBid.adm; - // Build the NURL element - var responseNurl = ''; - // Build the ad to display: - var responseAd = decodeURIComponent(responseCreative + responseNurl); - - // Create a valid bid - bid = bidfactory.createBid(1); - - // Set the bid data - bid.creative_id = curBid.Id; - bid.bidderCode = brightcomBidderCode; - bid.cpm = parseFloat(curBid.price); - - // Brightcom tag is in `; - } - } else { - // width and height are only relevant with non-native requests. - // native requests will always return a 2x2 zone size. - bidObject.width = bidResponse.width; - bidObject.height = bidResponse.height; - bidObject.ad = bidResponse.creative; - } - } else { - bidObject = _invalidBidResponse(); - } - return bidObject; - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new CriteoAdapter(), 'criteo'); - -module.exports = CriteoAdapter; diff --git a/modules/currency.js b/modules/currency.js index 19e7d2903f4..f5da02d5d72 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -2,8 +2,8 @@ import bidfactory from 'src/bidfactory'; import { STATUS } from 'src/constants'; import { ajax } from 'src/ajax'; import * as utils from 'src/utils'; -import bidmanager from 'src/bidmanager'; import { config } from 'src/config'; +import { hooks } from 'src/hook.js'; const DEFAULT_CURRENCY_RATE_URL = 'http://currency.prebid.org/latest.json'; const CURRENCY_RATE_PRECISION = 4; @@ -80,7 +80,7 @@ function initCurrency(url) { utils.logInfo('Installing addBidResponse decorator for currency module', arguments); - bidmanager.addBidResponse.addHook(addBidResponseHook, 100); + hooks['addBidResponse'].addHook(addBidResponseHook, 100); if (!currencyRates.conversions) { ajax(url, function (response) { @@ -99,7 +99,7 @@ function initCurrency(url) { function resetCurrency() { utils.logInfo('Uninstalling addBidResponse decorator for currency module', arguments); - bidmanager.addBidResponse.removeHook(addBidResponseHook); + hooks['addBidResponse'].removeHook(addBidResponseHook, 100); adServerCurrency = 'USD'; conversionCache = {}; diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 591b8f7baf3..609e9f46234 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -3,7 +3,7 @@ */ import { registerVideoSupport } from '../src/adServerManager'; -import { getWinningBids } from '../src/targeting'; +import { targeting } from '../src/targeting'; import { formatQS, format as buildUrl, parse } from '../src/url'; import { deepAccess, isEmpty, logError, parseSizesInput } from '../src/utils'; import { config } from '../src/config'; @@ -63,7 +63,7 @@ export default function buildDfpVideoUrl(options) { } const adUnit = options.adUnit; - const bid = options.bid || getWinningBids(adUnit.code)[0]; + const bid = options.bid || targeting.getWinningBids(adUnit.code)[0]; let urlComponents = {}; @@ -138,7 +138,7 @@ function buildUrlFromAdserverUrlComponents(components, bid) { * @return {string | undefined} The encoded vast url if it exists, or undefined */ function getDescriptionUrl(bid, components, prop) { - if (config.getConfig('usePrebidCache')) { return; } + if (config.getConfig('cache.url')) { return; } if (!deepAccess(components, `${prop}.description_url`)) { const vastUrl = bid && bid.vastUrl; diff --git a/modules/districtmDMXBidAdapter.js b/modules/districtmDMXBidAdapter.js deleted file mode 100644 index 1eed5f2150e..00000000000 --- a/modules/districtmDMXBidAdapter.js +++ /dev/null @@ -1,56 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adLoader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -var DistrictmAdaptor = function districtmAdaptor() { - let districtmUrl = window.location.protocol + '//prebid.districtm.ca/lib.js'; - this.callBids = params => { - if (!window.hb_dmx_res) { - adLoader.loadScript(districtmUrl, () => { - this.sendBids(params); - }); - } else { - this.sendBids(params); - } - return params; - }; - - this.handlerRes = function(response, bidObject) { - let bid; - if (parseFloat(response.result.cpm) > 0) { - bid = bidfactory.createBid(1, bidObject); - bid.bidderCode = bidObject.bidder; - bid.cpm = response.result.cpm; - bid.width = response.result.width; - bid.height = response.result.height; - bid.ad = response.result.banner; - bidmanager.addBidResponse(bidObject.placementCode, bid); - } else { - bid = bidfactory.createBid(2, bidObject); - bid.bidderCode = bidObject.bidder; - bidmanager.addBidResponse(bidObject.placementCode, bid); - } - - return bid; - }; - - this.sendBids = function(params) { - var bids = params.bids; - for (var i = 0; i < bids.length; i++) { - bids[i].params.sizes = window.hb_dmx_res.auction.fixSize(bids[i].sizes); - } - window.hb_dmx_res.auction.run(window.hb_dmx_res.ssp, bids, this.handlerRes); - return bids; - }; - - return { - callBids: this.callBids, - sendBids: this.sendBids, - handlerRes: this.handlerRes - }; -}; - -adaptermanager.registerBidAdapter(new DistrictmAdaptor(), 'districtmDMX'); - -module.exports = DistrictmAdaptor; diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js deleted file mode 100644 index 9c09fd3b782..00000000000 --- a/modules/eplanningBidAdapter.js +++ /dev/null @@ -1,310 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adaptermanager = require('src/adaptermanager'); - -function EPlanningAdapter() { - (function() { - const win = window; - const doc = win.document; - const pbjsVar = win.$$PREBID_GLOBAL$$; - const _global = {}; - const _default = { 'sv': 'ads.us.e-planning.net', 't': 0 }; - var rnd; - const FILE = 'file'; - const CALLBACK_FUNCTION = 'hbpb.rH'; - const NULL_SIZE = '1x1'; - const _csRequested = []; - const PROTO = location.protocol === 'https:' ? 'https:' : 'http:'; - const ISV = 'aklc.img.e-planning.net'; - function Hbpb() { - var slots = (function() { - var _data = []; - function Slot(slotId) { - var data = _data[slotId]; - function hasAds() { - return _data[slotId].ads.length; - } - function getSizes() { - return data.sizes; - } - function getSizesString() { - const s = []; - var i; - const sizes = getSizes(); - if (sizes && sizes.length) { - if (typeof sizes[0] === 'object') { - for (i = 0; i < sizes.length; i++) { - s.push(sizes[i][0] + 'x' + sizes[i][1]); - } - } else { - s.push(sizes[0] + 'x' + sizes[1]); - } - } else { - return NULL_SIZE; - } - return s.join(','); - } - return { - getPlacementCode: function() { - return data.placementCode; - }, - getString: function() { - return this.getPlacementCode() + ':' + getSizesString(); - }, - addAd: function(ad) { - _data[slotId].ads.push(ad); - }, - getFormatedResponse: function() { - var ad; - const that = this; - if (hasAds()) { - ad = data.ads[0]; - return { - 'placementCode': that.getPlacementCode(), - 'ad': { - 'ad': ad.adm, - 'cpm': ad.pr, - 'width': ad.size.w, - 'height': ad.size.h - } - }; - } else { - return { 'placementCode': that.getPlacementCode() }; - } - } - }; - } - function findAll() { - var i = 0; - const r = []; - for (i = 0; i < _data.length; i++) { - r.push(new Slot(i)); - } - return r; - } - return { - add: function(slot) { - slot.ads = []; - _data.push(slot); - }, - get: function(slotId) { - return new Slot(slotId); - }, - getString: function() { - const _slots = []; - var i; - var slot; - for (i = 0; i < _data.length; i++) { - slot = this.get(i); - _slots.push(slot.getString()); - } - return _slots.join('+'); - }, - findByPlacementCode: function(placementCode) { - var i; - const _slots = findAll(); - for (i = 0; i < _slots.length; i++) { - if (_slots[i].getPlacementCode() === placementCode) { - return _slots[i]; - } - } - }, - getFormatedResponse: function() { - const _slots = findAll(); - var i; - const r = []; - for (i = 0; i < _slots.length; i++) { - r.push(_slots[i].getFormatedResponse()); - } - return { - 'bids': r - }; - } - }; - })(); - function call(params) { - var i; - const bids = params.bids; - for (i = 0; i < bids.length; i++) { - slots.add({ - _raw: bids[i], - placementCode: bids[i].placementCode, - sizes: bids[i].sizes - }); - setGlobalParam('sv', bids[i]); - setGlobalParam('ci', bids[i]); - setGlobalParam('t', bids[i]); - } - doRequest(); - } - function setGlobalParam(param, bid) { - if (!_global[param]) { - if (bid && bid.params && bid.params[param]) { - _global[param] = bid.params[param]; - } - } - } - function getGlobalParam(param) { - return (_global[param] || _default[param]); - } - function getRandom() { - if (!rnd) { - rnd = Math.random(); - } - return rnd; - } - function getDocURL() { - return escape(win.location.href || FILE); - } - function getReferrerURL() { - return doc.referrer; - } - function getCallbackFunction() { - return CALLBACK_FUNCTION; - } - function doRequest() { - const clienteId = getGlobalParam('ci'); - var url; - const dfpClienteId = '1'; - const sec = 'ROS'; - const params = []; - const t = getGlobalParam('t'); - if (clienteId && !t) { - url = PROTO + '//' + getGlobalParam('sv') + '/hb/1/' + clienteId + '/' + dfpClienteId + '/' + (win.location.hostname || FILE) + '/' + sec + '?'; - params.push('rnd=' + getRandom()); - params.push('e=' + slots.getString()); - if (getDocURL()) { - params.push('ur=' + getDocURL()); - } - if (getReferrerURL()) { - params.push('fr=' + getReferrerURL()); - } - params.push('cb=' + getCallbackFunction()); - params.push('r=pbjs'); - url += params.join('&'); - load(url); - } else if (t) { - url = PROTO + '//' + ISV + '/layers/t_pbjs_' + t + '.js'; - load(url); - } - } - function load(url) { - var script = doc.createElement('script'); - script.src = url; - doc.body.appendChild(script); - } - function callback(response) { - if (pbjsVar && pbjsVar.processEPlanningResponse && typeof pbjsVar.processEPlanningResponse === 'function') { - pbjsVar.processEPlanningResponse(response); - } - } - function syncUsers(cs) { - var i, e, d; - for (i = 0; i < cs.length; i++) { - if (typeof cs[i] === 'string' && _csRequested.indexOf(cs[i]) === -1) { - (new Image()).src = cs[i]; - _csRequested.push(cs[i]); - } else if (typeof cs[i] === 'object' && _csRequested.indexOf(cs[i].u) === -1) { - if (cs[i].j) { - e = doc.createElement('script'); - e.src = cs[i].u; - } else if (cs[i].ifr) { - e = doc.createElement('iframe'); - e.src = cs[i].u; - e.style.width = e.style.height = '1px'; - e.display = 'none'; - } - if (cs[i].data) { - for (d in cs[i].data) { - if (cs[i].data.hasOwnProperty(d)) { - e.setAttribute('data-' + d, cs[i].data[d]); - } - } - } - doc.body.appendChild(e); - _csRequested.push(cs[i].u); - } - } - } - function rH(response) { - var slot, i, o; - if (response && response.sp && response.sp.length) { - for (i = 0; i < response.sp.length; i++) { - if (response.sp[i].a) { - slot = slots.findByPlacementCode(response.sp[i].k); - if (slot) { - for (o = 0; o < response.sp[i].a.length; o++) { - slot.addAd({ - 'adm': response.sp[i].a[o].adm, - 'pr': response.sp[i].a[o].pr, - 'size': { - 'w': response.sp[i].a[o].w, - 'h': response.sp[i].a[o].h - } - }); - } - } - } - } - callback(slots.getFormatedResponse()); - } - if (response && response.cs && response.cs.length) { - syncUsers(response.cs); - } - } - return { - call: function(params) { - return call(params); - }, - rH: function(response) { - return rH(response); - } - }; - } - win.hbpb = win.hbpb || new Hbpb(); - })(); - - window.$$PREBID_GLOBAL$$ = window.$$PREBID_GLOBAL$$ || {}; - window.$$PREBID_GLOBAL$$.processEPlanningResponse = function(response) { - var bids, bidObject, i; - if (response) { - bids = response.bids; - for (i = 0; i < bids.length; i++) { - if (bids[i].ad) { - bidObject = getBidObject(bids[i]); - bidmanager.addBidResponse(bids[i].placementCode, bidObject); - } else { - bidObject = bidfactory.createBid(2); - bidObject.bidderCode = 'eplanning'; - bidmanager.addBidResponse(bids[i].placementCode, bidObject); - } - } - } - }; - - function getBidObject(bid) { - const bidObject = bidfactory.createBid(1); - var i; - bidObject.bidderCode = 'eplanning'; - for (i in bid.ad) { - if (bid.ad.hasOwnProperty(i)) { - bidObject[i] = bid.ad[i]; - } - } - return bidObject; - } - - function _callBids(params) { - if (window.hbpb) { - window.hbpb.call(params); - } - } - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new EPlanningAdapter(), 'eplanning'); - -module.exports = EPlanningAdapter; diff --git a/modules/essensBidAdapter.js b/modules/essensBidAdapter.js deleted file mode 100644 index 1b4df4d1685..00000000000 --- a/modules/essensBidAdapter.js +++ /dev/null @@ -1,170 +0,0 @@ -const CONSTANTS = require('src/constants.json') -const utils = require('src/utils.js') -const bidfactory = require('src/bidfactory.js') -const bidmanager = require('src/bidmanager.js') -const adloader = require('src/adloader') -const Adapter = require('src/adapter.js').default -const adaptermanager = require('src/adaptermanager') - -// Essens Prebid Adapter -function EssensAdapter () { - let baseAdapter = new Adapter('essens') - - const ENDPOINT = 'bid.essrtb.com/bid/prebid_call' - - let receivedBidRequests = {} - - baseAdapter.callBids = function (bidRequest) { - if (!bidRequest) { - utils.logError('empty bid request received') - return - } - receivedBidRequests = bidRequest - - const bids = bidRequest.bids || [] - - const essensBids = bids - .filter(bid => isPlacementBidComplete(bid)) - .map(bid => { - let essensBid = {} - essensBid.impressionId = bid.bidId - essensBid.sizes = utils.parseSizesInput(bid.sizes) - essensBid.placementId = bid.params.placementId - - if (bid.params.dealId) { - essensBid.deal = bid.params.dealId - } - - if (bid.params.floorPrice) { - essensBid.floorPrice = bid.params.floorPrice - } - - return essensBid - }) - - const bidderRequestId = bidRequest.bidderRequestId - const cur = ['USD'] - const urlParam = utils.getTopWindowUrl() - const uaParam = getUa() - - if (!utils.isEmpty(essensBids)) { - const payloadJson = {bidderRequestId: bidderRequestId, cur: cur, url: urlParam, ua: uaParam, imp: essensBids} - - const scriptUrl = '//' + ENDPOINT + '?callback=$$PREBID_GLOBAL$$.essensResponseHandler' + - '&bid=' + encodeURIComponent(JSON.stringify(payloadJson)) - adloader.loadScript(scriptUrl) - } else { - sendEmptyResponseForAllPlacement() - } - - function isPlacementBidComplete (bid) { - if (bid.bidId && bid.params && bid.params.placementId) { - return true - } else { - utils.logError('bid requires missing essential params for essens') - } - } - - function getUa () { - return window.navigator.userAgent - } - } - - function sendEmptyResponseForAllPlacement () { - if (receivedBidRequests && receivedBidRequests.bids) { - receivedBidRequests.bids.forEach(registerEmptyResponse) - } - } - - function registerEmptyResponse (bidRequest) { - const bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidRequest) - bid.bidderCode = 'essens' - bidmanager.addBidResponse(bidRequest.placementCode, bid) - } - - $$PREBID_GLOBAL$$.essensResponseHandler = function (essensResponse) { - utils.logInfo('received bid request from Essens') - if (!isValidResponse(essensResponse)) { - sendEmptyResponseForAllPlacement() - return - } - - registerBids(essensResponse) - - function isValidResponse (essensResponse) { - return !!(essensResponse && essensResponse.id && essensResponse.seatbid) - } - - function registerBids (essensResponses) { - const requestHasResponse = [] - - if (essensResponses.seatbid.length > 0) { - essensResponses.seatbid.filter(isValidSeat).forEach( - seat => seat.bid.forEach(sendResponse)) - } - - receivedBidRequests.bids.filter(request => !hasResponse(request)) - .forEach(registerEmptyResponse) - - function sendResponse (bidCandidate) { - const bidRequest = getBidRequest(bidCandidate.impid) - - const bidsToBeRegister = getBid(bidRequest, bidCandidate) - - if (bidsToBeRegister) { - requestHasResponse.push(bidRequest) - bidmanager.addBidResponse(bidRequest.placementCode, bidsToBeRegister) - } - } - - function hasResponse (request) { - return utils.contains(requestHasResponse, request) - } - - function isValidSeat (seatbid) { - return ((seatbid.bid && seatbid.bid.length !== 0)) - } - - function getBidRequest (id) { - return receivedBidRequests.bids.find(bid => bid.bidId === id) - } - } - - function getBid (pbBidReq, bidCandidate) { - if (!validBid(bidCandidate)) { - return - } - const bid = bidfactory.createBid(CONSTANTS.STATUS.GOOD, pbBidReq) - - bid.creative_id = bidCandidate.crid - bid.adUrl = bidCandidate.ext.adUrl - bid.bidderCode = 'essens' - bid.cpm = parseFloat(bidCandidate.price) - bid.width = parseInt(bidCandidate.w) - bid.height = parseInt(bidCandidate.h) - - if (bidCandidate.dealid) { - bid.dealId = bidCandidate.dealid - } - return bid - } - - function validBid (bid) { - return !!((bid.price && - bid.crid && bid.ext && bid.ext.adUrl && - bid.w && - bid.h && - bid.impid)) - } - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - getBidderCode: baseAdapter.getBidderCode - }) -} - -adaptermanager.registerBidAdapter(new EssensAdapter(), 'essens') - -module.exports = EssensAdapter diff --git a/modules/featureforwardBidAdapter.js b/modules/featureforwardBidAdapter.js deleted file mode 100644 index 53a3a7c5a08..00000000000 --- a/modules/featureforwardBidAdapter.js +++ /dev/null @@ -1,92 +0,0 @@ -import {createBid} from 'src/bidfactory'; -import {addBidResponse} from 'src/bidmanager'; -import {registerBidAdapter} from 'src/adaptermanager'; -import {logError, getTopWindowLocation} from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; - -function FeatureForwardAdapter() { - const bidUrl = window.location.protocol + '//prmbdr.featureforward.com/newbidder/bidder1_prm.php?'; - const ajaxOptions = { - method: 'POST', - withCredentials: true, - contentType: 'text/plain' - }; - - function _callBids(bidderRequest) { - bidderRequest.bids.forEach(bidRequest => { - var i = 0; - try { - while (bidRequest.sizes[i] !== undefined) { - var params = Object.assign({}, environment(), bidRequest.params, {'size': bidRequest.sizes[i]}); - var postRequest = JSON.stringify(params); - var url = bidUrl; - i++; - ajax(url, (bidResponse) => { - bidResponseAvailable(bidRequest, bidResponse); - }, postRequest, ajaxOptions); - } - } catch (e) { - // register passback on any exceptions while attempting to fetch response. - logError('featureforward.requestBid', 'ERROR', e); - bidResponseAvailable(bidRequest); - } - }); - } - - function environment() { - return { - ca: 'BID', - 'if': 0, - url: getTopWindowLocation().href, - refurl: referrer(), - ew: document.documentElement.clientWidth, - eh: document.documentElement.clientHeight, - ln: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage) - }; - } - - function referrer() { - try { - return window.top.document.referrer; - } catch (e) { - return document.referrer; - } - } - - function bidResponseAvailable(bidRequest, rawResponse) { - if (rawResponse) { - var bidResponse = parse(rawResponse); - if (bidResponse) { - var bid = createBid(STATUS.GOOD, bidRequest); - bid.bidderCode = bidRequest.bidder; - bid.cpm = bidResponse.bidCpm; - bid.ad = bidResponse.html; - bid.width = bidResponse.width; - bid.height = bidResponse.height; - addBidResponse(bidRequest.placementCode, bid); - return; - } - } - var passback = createBid(STATUS.NO_BID, bidRequest); - passback.bidderCode = bidRequest.bidder; - addBidResponse(bidRequest.placementCode, passback); - } - - function parse(rawResponse) { - try { - return JSON.parse(rawResponse); - } catch (ex) { - logError('featureforward.safeParse', 'ERROR', ex); - return null; - } - } - - return { - callBids: _callBids - }; -} - -registerBidAdapter(new FeatureForwardAdapter(), 'featureforward'); - -module.exports = FeatureForwardAdapter; diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js deleted file mode 100644 index 521dfabfb2d..00000000000 --- a/modules/gumgumBidAdapter.js +++ /dev/null @@ -1,176 +0,0 @@ -const bidfactory = require('src/bidfactory'); -const bidmanager = require('src/bidmanager'); -const utils = require('src/utils'); -const adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -const BIDDER_CODE = 'gumgum'; -const CALLBACKS = {}; - -const GumgumAdapter = function GumgumAdapter() { - const bidEndpoint = `https://g2.gumgum.com/hbid/imp`; - - let topWindow; - let topScreen; - let pageViewId; - const requestCache = {}; - const throttleTable = {}; - const defaultThrottle = 3e4; - const dtCredentials = { member: 'YcXr87z2lpbB' }; - - try { - topWindow = global.top; - topScreen = topWindow.screen; - } catch (error) { - return utils.logError(error); - } - - function _getTimeStamp() { - return new Date().getTime(); - } - - function _getDigiTrustQueryParams() { - function getDigiTrustId () { - var digiTrustUser = (window.DigiTrust && window.DigiTrust.getUser) ? window.DigiTrust.getUser(dtCredentials) : {}; - return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || ''; - }; - - let digiTrustId = getDigiTrustId(); - // Verify there is an ID and this user has not opted out - if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { - return {}; - } - return { - 'dt': digiTrustId.id - }; - } - - function _callBids({ bids }) { - const browserParams = { - vw: topWindow.innerWidth, - vh: topWindow.innerHeight, - sw: topScreen.width, - sh: topScreen.height, - pu: topWindow.location.href, - ce: navigator.cookieEnabled, - dpr: topWindow.devicePixelRatio || 1 - }; - - utils._each(bids, bidRequest => { - const { bidId - , params = {} - , placementCode - } = bidRequest; - const timestamp = _getTimeStamp(); - const trackingId = params.inScreen; - const nativeId = params['native']; - const slotId = params.inSlot; - const bid = { tmax: $$PREBID_GLOBAL$$.cbTimeout }; - - /* slot/native ads need the placement id */ - switch (true) { - case !!(params.inImage): bid.pi = 1; break; - case !!(params.inScreen): bid.pi = 2; break; - case !!(params.inSlot): bid.pi = 3; break; - case !!(params['native']): bid.pi = 5; break; - default: return utils.logWarn( - `[GumGum] No product selected for the placement ${placementCode}` + - ', please check your implementation.' - ); - } - - /* throttle based on the latest request for this product */ - const productId = bid.pi; - const requestKey = productId + '|' + placementCode; - const throttle = throttleTable[productId]; - const latestRequest = requestCache[requestKey]; - if (latestRequest && throttle && (timestamp - latestRequest) < throttle) { - return utils.logWarn( - `[GumGum] The refreshes for "${placementCode}" with the params ` + - `${JSON.stringify(params)} should be at least ${throttle / 1e3}s apart.` - ); - } - /* update the last request */ - requestCache[requestKey] = timestamp; - - /* tracking id is required for in-image and in-screen */ - if (trackingId) bid.t = trackingId; - /* native ads require a native placement id */ - if (nativeId) bid.ni = nativeId; - /* slot ads require a slot id */ - if (slotId) bid.si = slotId; - - /* include the pageViewId, if any */ - if (pageViewId) bid.pv = pageViewId; - - const cachedBid = Object.assign({ - placementCode, - id: bidId - }, bid); - - const callback = { jsonp: `$$PREBID_GLOBAL$$.handleGumGumCB['${bidId}']` }; - CALLBACKS[bidId] = _handleGumGumResponse(cachedBid); - const query = Object.assign(callback, browserParams, bid, _getDigiTrustQueryParams()); - const bidCall = `${bidEndpoint}?${utils.parseQueryStringParameters(query)}`; - adloader.loadScript(bidCall); - }); - } - - const _handleGumGumResponse = cachedBidRequest => (bidResponse = {}) => { - const { pi: productId - } = cachedBidRequest; - const { ad = {} - , pag = {} - , thms: throttle - } = bidResponse; - /* cache the pageViewId */ - if (pag && pag.pvid) pageViewId = pag.pvid; - if (ad && ad.id) { - /* set the new throttle */ - throttleTable[productId] = throttle || defaultThrottle; - /* create the bid */ - const bid = bidfactory.createBid(1); - const { t: trackingId - } = pag; - bidResponse.request = cachedBidRequest; - const encodedResponse = encodeURIComponent(JSON.stringify(bidResponse)); - const gumgumAdLoader = ``; - Object.assign(bid, { - cpm: ad.price, - ad: gumgumAdLoader, - width: ad.width, - height: ad.height, - bidderCode: BIDDER_CODE - }); - bidmanager.addBidResponse(cachedBidRequest.placementCode, bid); - } else { - const noBid = bidfactory.createBid(2); - noBid.bidderCode = BIDDER_CODE; - bidmanager.addBidResponse(cachedBidRequest.placementCode, noBid); - } - delete CALLBACKS[cachedBidRequest.id]; - }; - - window.$$PREBID_GLOBAL$$.handleGumGumCB = CALLBACKS; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new GumgumAdapter(), 'gumgum'); - -module.exports = GumgumAdapter; diff --git a/modules/hiromediaBidAdapter.js b/modules/hiromediaBidAdapter.js deleted file mode 100644 index f99b3553dfc..00000000000 --- a/modules/hiromediaBidAdapter.js +++ /dev/null @@ -1,374 +0,0 @@ -/** - * Adapter for HIRO Media - * - * @module HiroMediaAdapter - * - * @requires src/ajax - * @requires src/bidfactory - * @requires src/bidmanager - * @requires src/constants - * @requires src/utils - */ -var Ajax = require('src/ajax'); -var bidfactory = require('src/bidfactory'); -var bidmanager = require('src/bidmanager'); -var utils = require('src/utils'); -var STATUS = require('src/constants').STATUS; -var adaptermanager = require('src/adaptermanager'); - -var HiroMediaAdapter = function HiroMediaAdapter() { - 'use strict'; - - /** - * Bidder code - * - * @memberof module:HiroMediaAdapter~ - * @constant {string} - * @private - */ - var BIDDER_CODE = 'hiromedia'; - - /** - * Adapter version - * - * @memberof module:HiroMediaAdapter~ - * @constant {number} - * @private - */ - var ADAPTER_VERSION = 3; - - /** - * Default bid param values - * - * @memberof module:HiroMediaAdapter~ - * @constant {array.} - * @private - */ - var REQUIRED_BID_PARAMS = ['accountId']; - - /** - * Default bid param values - * - * @memberof module:HiroMediaAdapter~ - * @constant {module:HiroMediaAdapter~bidParams} - * @private - */ - var DEFAULT_BID_PARAMS = { - bidUrl: 'https://hb-rtb.ktdpublishers.com/bid/get' - }; - - /** - * Returns true if the given value is `undefined` - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {*} value value to check - * @return {boolean} true if the given value is `undefined`, false otherwise - */ - function isUndefined(value) { - return typeof value === 'undefined'; - } - - /** - * Call bidmanager.addBidResponse - * - * Simple wrapper that will create a bid object with the correct status - * and add the response for the placement. - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {object} bid bid object connected to the response - * @param {object|boolean} [bidResponse] response object for bid, if not - * set the response will be an empty bid response. - */ - function addBidResponse(bid, bidResponse) { - var placementCode = bid.placementCode; - var bidStatus = bidResponse ? STATUS.GOOD : STATUS.NO_BID; - var bidObject = bidfactory.createBid(bidStatus, bid); - - bidObject.bidderCode = BIDDER_CODE; - - if (bidResponse) { - bidObject.cpm = bidResponse.cpm; - bidObject.ad = bidResponse.ad; - bidObject.width = bidResponse.width; - bidObject.height = bidResponse.height; - } - - utils.logMessage('hiromedia.callBids, addBidResponse for ' + placementCode + ' status: ' + bidStatus); - bidmanager.addBidResponse(placementCode, bidObject); - } - - /** - * Return `true` if sampling is larger than a newly created random value - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {number} sampling the value to check - * @return {boolean} `true` if the sampling is larger, `false` otherwise - */ - function checkChance(sampling) { - return Math.random() < sampling; - } - - /** - * Apply a response for all pending bids that have the same response batch key - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {object} response bid response object - * @param {object} bid bid object connected to response - */ - function handleResponse(response, bid) { - // Sample the bid responses according to `response.chance`, - // if `response.chance` is not provided, sample at 100%. - if (isUndefined(response.chance) || checkChance(response.chance)) { - addBidResponse(bid, response); - } else { - addBidResponse(bid, false); - } - } - - /** - * Find browser name and version - * - * Super basic UA parser for the major browser configurations. - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @return {module:HiroMediaAdapter~browserInfo} object containing name and version of browser - * or empty strings. - */ - function getBrowser() { - var ua = navigator.userAgent; - var browsers = [{ - name: 'Mobile', - stringSearch: 'Mobi' - }, { - name: 'Edge' - }, { - name: 'Chrome' - }, { - name: 'Firefox' - }, { - name: 'IE', - versionSearch: /MSIE\s(\d+)/ - }, { - name: 'IE', - stringSearch: 'Trident', - versionSearch: /rv:(\d+)/ - }]; - - var name = ''; - var version = ''; - - browsers.some(function (browser) { - var nameSearch = browser.stringSearch || browser.name; - var defaultVersionSearch = nameSearch + '\\/(\\d+)'; - var versionSearch = browser.versionSearch || defaultVersionSearch; - var versionMatch; - - if (ua.indexOf(nameSearch) !== -1) { - name = browser.name; - versionMatch = ua.match(versionSearch); - if (versionMatch) { - version = versionMatch && versionMatch[1]; - } - return true; - } - }); - - return { - name: name, - version: version - }; - } - - /** - * Return top context domain - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @return {string} domain of top context url. - */ - function getDomain() { - var a = document.createElement('a'); - a.href = utils.getTopWindowUrl(); - return a.hostname; - } - - /** - * Apply default parameters to an object if the parameters are not set - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {module:HiroMediaAdapter~bidParams} bidParams custom parameters for bid - * @return {module:HiroMediaAdapter~bidParams} `bidParams` shallow merged with - * {@linkcode module:HiroMediaAdapter~DEFAULT_BID_PARAMS|DEFAULT_BID_PARAMS} - */ - function defaultParams(bidParams) { - return Object.assign({}, DEFAULT_BID_PARAMS, bidParams); - } - - /** - * Build a {@linkcode module:HiroMediaAdapter~bidInfo|bidInfo} object based on a - * bid sent to {@linkcode module:HiroMediaAdapter#callBids|callBids} - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {object} bid bid from `Prebid.js` - * @return {module:HiroMediaAdapter~bidInfo} information for bid request - */ - function processBid(bid) { - var sizes = utils.parseSizesInput(bid.sizes); - var bidParams = defaultParams(bid.params); - var hasValidBidRequest = utils.hasValidBidRequest(bidParams, REQUIRED_BID_PARAMS, BIDDER_CODE); - var shouldBid = hasValidBidRequest; - var bidInfo = { - bidParams: bidParams, - shouldBid: shouldBid, - selectedSize: sizes[0], - additionalSizes: sizes.slice(1).join(',') - }; - - return bidInfo; - } - - /** - * Wrapper around `JSON.parse()` that returns false on error - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {string} text potential JSON string to convert to object - * @return {object|boolean} object parsed from text or `false` in case of and error - */ - function tryJson(text) { - var object = false; - - try { - object = JSON.parse(text); - } catch (ignore) { - // Ignored - } - - return object; - } - - /** - * Receive a set of bid placements and create bid requests and responses accordingly - * - * @alias module:HiroMediaAdapter#callBids - * - * @param {object} params placement and bid data from `Prebid.js` - */ - function _callBids(params) { - var browser = getBrowser(); - var domain = getDomain(); - var bids = params && params.bids; - var ajaxOptions = { - method: 'GET', - withCredentials: true - }; - - // Fixed data, shared by all requests - var fixedRequest = { - adapterVersion: ADAPTER_VERSION, - browser: browser.name, - browserVersion: browser.version, - domain: domain - }; - - utils.logMessage('hiromedia.callBids'); - - if (bids && bids.length) { - bids.forEach(function (bid) { - var bidInfo = processBid(bid); - var bidParams = bidInfo.bidParams; - utils.logMessage('hiromedia.callBids, bidInfo ' + bid.placementCode + ' ' + bidInfo.shouldBid); - if (bidInfo.shouldBid) { - var url = bidParams.bidUrl; - var requestParams = Object.assign({}, fixedRequest, bidInfo.bidParams, { - placementCode: bid.placementCode, - selectedSize: bidInfo.selectedSize, - additionalSizes: bidInfo.additionalSizes - }); - - Object.keys(requestParams).forEach(function (key) { - if (requestParams[key] === '' || isUndefined(requestParams[key])) { - delete requestParams[key]; - } - }); - - utils.logMessage('hiromedia.callBids, bid request ' + url + ' ' + JSON.stringify(bidInfo.bidRequest)); - - Ajax.ajax(url, { - - success: function(responseText) { - var response = tryJson(responseText); - handleResponse(response, bid); - }, - - error: function(err, xhr) { - utils.logError('hiromedia.callBids, bid request error', xhr.status, err); - addBidResponse(bid, false); - } - - }, requestParams, ajaxOptions); - } else { - // No bid - addBidResponse(bid, false); - } - }); - } - } - - return { - callBids: _callBids - }; - - // JSDoc typedefs - - /** - * Parameters for bids to HIRO Media adapter - * - * @typedef {object} module:HiroMediaAdapter~bidParams - * @private - * - * @property {string} bidUrl the bid server endpoint url - */ - - /** - * Bid object wrapper - * - * @typedef {object} module:HiroMediaAdapter~bidInfo - * @private - * - * @property {string} selectedSize the first size in the the placement sizes array - * @property {string} additionalSizes list of sizes in the placement sizes array besides the first - * @property {module:HiroMediaAdapter~bidParams} bidParams original params passed for bid in #callBids - * @property {boolean} shouldBid flag to determine if the bid is valid for bidding or not - */ - - /** - * browserInfo - * - * @typedef {object} module:HiroMediaAdapter~browserInfo - * @private - * - * @property {string} name browser name (e.g. `'Chrome'` or `'Firefox'`) - * @property {string} version browser major version (e.g. `'53'`) - */ -}; - -adaptermanager.registerBidAdapter(new HiroMediaAdapter(), 'hiromedia'); - -module.exports = HiroMediaAdapter; diff --git a/modules/imonomyBidAdapter.js b/modules/imonomyBidAdapter.js deleted file mode 100644 index 7026c28ba6d..00000000000 --- a/modules/imonomyBidAdapter.js +++ /dev/null @@ -1,185 +0,0 @@ -/* imonomy.js v3.1.0 -Updated : 2017-03-15 */ - -var utils = require('src/utils.js'); -var adloader = require('src/adloader.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -const adaptermanager = require('src/adaptermanager'); -var STATUSCODES = require('src/constants.json').STATUS; - -function ImonomyAdapter() { - return { - callBids: _callBids - }; - - function _callBids(params) { - var request = []; - var siteRef = ''; - var screen_w = ''; - var screen_h = ''; - var language = ''; - var pxr = ''; - var keywords = ''; - var connectiontype = ''; - var domain = ''; - var page = ''; - var bid, i, l; - var bids = params.bids; - var imonomy_domain = 'b.imonomy.com'; - var callbackName = '_hb_' + utils.getUniqueIdentifierStr(); - - try { siteRef = document.referrer } catch (e) { } - try { domain = window.location.host } catch (e) { } - try { pxr = window.devicePixelRatio } catch (e) { } - try { screen_w = screen.width || document.body.clientWidth || 0 } catch (e) { } - try { screen_h = screen.height || document.body.clientHeight || 0 } catch (e) { } - try { page = window.location.pathname + location.search + location.hash } catch (e) { } - - try { - var meta = document.getElementsByTagName('meta') || {}; - keywords = ('keywords' in meta) ? meta['keywords'].content : '' - } catch (e) {} - - try { - var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection; - connectiontype = (connection != undefined) ? connection.type : ''; - } catch (e) {} - - try { - var language_tmp = document.documentElement.lang || navigator.language || navigator.userLanguage || ''; - language = language_tmp.split('-')[0] - } catch (e) {} - - try { - var data = { - pxr: pxr, - page: page, - domain: domain, - siteRef: siteRef, - screen_w: screen_w, - screen_h: screen_h, - language: language, - keywords: keywords, - connectiontype: connectiontype, - requestId: params['requestId'], - bidderRequestId: params['bidderRequestId'], - callback: '$$PREBID_GLOBAL$$.' + callbackName, - publisher_id: params['bids'][0]['params']['publisher_id'], - bids: encodeURIComponent(JSON.stringify(params['bids'])) - }; - - var protocol = (document.location.protocol === 'https:') ? 'https' : 'http'; - request.unshift(protocol + '://' + imonomy_domain + '/openrtb/hb/' + params['bids'][0]['params']['publisher_id'] + '?id=' + utils.getUniqueIdentifierStr()); - - for (var key in data) { - if (data.hasOwnProperty(key)) { - request.push(key + '=' + encodeURIComponent(data[key])); - } - } - - for (i = 0, l = bids.length; i < l; i++) { - bid = bids[i]; - request.push(formRequestUrl(bid.params)); - } - - $$PREBID_GLOBAL$$[callbackName] = handleCallback(bids); - - adloader.loadScript(request.join('&')); - } catch (e) { - } - } - - function formRequestUrl(reqData) { - var key; - var url = []; - - for (key in reqData) { - if (reqData.hasOwnProperty(key) && reqData[key]) { - url.push(key, '=', reqData[key], '&'); - } - } - - return btoa(url.join('').slice(0, -1)); - } - - function handleCallback(bids) { - return function handleResponse(adItems) { - try { - var bidObject; - var bidder = 'imonomy'; - var adItem; - var bid; - - try { - if (adItems.um_list) { - _processUserMatchings(adItems.um_list); - } - } catch (e) { } - - adItems = adItems.ads; - - for (var i = 0, l = bids.length; i < l; i++) { - bid = bids[i]; - adItem = getAdItem(adItems, bids[i].bidId); - - if (adItem) { - bidObject = bidfactory.createBid(STATUSCODES.GOOD, bid); - bidObject.bidderCode = bidder; - bidObject.ad = adItem.ad; - bidObject.cpm = adItem.cpm; - bidObject.cur = adItem.cur; - bidObject.width = adItem.width; - bidObject.height = adItem.height; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } else { - bidObject = bidfactory.createBid(STATUSCODES.NO_BID, bid); - bidObject.bidderCode = bidder; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - } - } catch (e) { - } - }; - } - - function _processUserMatchings(userMatchings) { - var headElem = document.getElementsByTagName('head')[0]; - var createdElem; - - utils._each(userMatchings, function (userMatching) { - createdElem = undefined; - switch (userMatching.type) { - case 'redirect': - createdElem = document.createElement('img'); - break; - case 'iframe': - createdElem = utils.createInvisibleIframe(); - break; - case 'js': - createdElem = document.createElement('script'); - createdElem.type = 'text/javascript'; - createdElem.async = true; - break; - } - if (createdElem) { - createdElem.src = decodeURIComponent(userMatching.Url); - headElem.insertBefore(createdElem, headElem.firstChild); - } - }); - } - - function getAdItem(adItems, imp) { - adItems = adItems || [] - for (var i = 0, l = adItems.length; i < l; i++) { - if (adItems[i].impression_id == imp) { - return adItems[i]; - } - } - - return null; - } -} - -adaptermanager.registerBidAdapter(new ImonomyAdapter(), 'imonomy'); -module.exports = ImonomyAdapter; diff --git a/modules/indexExchangeBidAdapter.js b/modules/indexExchangeBidAdapter.js deleted file mode 100644 index 3ecabf649e0..00000000000 --- a/modules/indexExchangeBidAdapter.js +++ /dev/null @@ -1,1132 +0,0 @@ -// Factory for creating the bidderAdaptor -// jshint ignore:start -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import { STATUS } from 'src/constants'; -import * as url from 'src/url'; -import adloader from 'src/adloader'; -import adaptermanager from 'src/adaptermanager'; - -var ADAPTER_NAME = 'INDEXEXCHANGE'; -var ADAPTER_CODE = 'indexExchange'; - -var CONSTANTS = { - 'INDEX_DEBUG_MODE': { - 'queryParam': 'pbjs_ix_debug', - 'mode': { - 'sandbox': { - 'topFrameLimit': 10, - 'queryValue': 'sandbox', - 'siteID': '999990' - } - } - } -}; - -var OPEN_MARKET = 'IOM'; -var PRIVATE_MARKET = 'IPM'; - -const VIDEO_REQUIRED_PARAMS_MAP = { - siteID: true, - playerType: true, - protocols: true, - maxduration: true -}; -const VIDEO_OPTIONAL_PARAMS_MAP = { - minduration: 0, - startdelay: 'preroll', - linearity: 'linear', - mimes: [], - allowVPAID: true, - apiList: [] -}; -const SUPPORTED_PLAYER_TYPES_MAP = { - HTML5: true, - FLASH: true -}; -const SUPPORTED_PROTOCOLS_MAP = { - 'VAST2': [2, 5], - 'VAST3': [3, 6] -}; -const SUPPORTED_API_MAP = { - FLASH: [1, 2], - HTML5: [2] -}; -const LINEARITY_MAP = { - linear: 1, - nonlinear: 2 -}; -const START_DELAY_MAP = { - preroll: 0, - midroll: -1, - postroll: -2 -}; -const SLOT_ID_PREFIX_MAP = { - preroll: 'pr', - midroll: 'm', - postroll: 'po' -}; -const DEFAULT_MIMES_MAP = { - FLASH: ['video/mp4', 'video/x-flv'], - HTML5: ['video/mp4', 'video/webm'] -}; -const DEFAULT_VPAID_MIMES_MAP = { - FLASH: ['application/x-shockwave-flash'], - HTML5: ['application/javascript'] -}; - -const BASE_CYGNUS_VIDEO_URL_INSECURE = `http://as.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse`; -const BASE_CYGNUS_VIDEO_URL_SECURE = `https://as-sec.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse`; - -window.cygnus_index_parse_res = function(response) { - try { - if (response) { - if (typeof _IndexRequestData !== 'object' || typeof _IndexRequestData.impIDToSlotID !== 'object' || typeof _IndexRequestData.impIDToSlotID[response.id] === 'undefined') { - return; - } - var targetMode = 1; - var callbackFn; - if (typeof _IndexRequestData.reqOptions === 'object' && typeof _IndexRequestData.reqOptions[response.id] === 'object') { - if (typeof _IndexRequestData.reqOptions[response.id].callback === 'function') { - callbackFn = _IndexRequestData.reqOptions[response.id].callback; - } - if (typeof _IndexRequestData.reqOptions[response.id].targetMode === 'number') { - targetMode = _IndexRequestData.reqOptions[response.id].targetMode; - } - } - - _IndexRequestData.lastRequestID = response.id; - _IndexRequestData.targetIDToBid = {}; - _IndexRequestData.targetIDToResp = {}; - _IndexRequestData.targetIDToCreative = {}; - - var allBids = []; - var seatbidLength = typeof response.seatbid === 'undefined' ? 0 : response.seatbid.length; - for (var i = 0; i < seatbidLength; i++) { - for (var j = 0; j < response.seatbid[i].bid.length; j++) { - var bid = response.seatbid[i].bid[j]; - if (typeof bid.ext !== 'object' || typeof bid.ext.pricelevel !== 'string') { - continue; - } - if (typeof _IndexRequestData.impIDToSlotID[response.id][bid.impid] === 'undefined') { - continue; - } - var slotID = _IndexRequestData.impIDToSlotID[response.id][bid.impid]; - var targetID; - var noTargetModeTargetID; - var targetPrefix; - if (typeof bid.ext.dealid === 'string') { - if (targetMode === 1) { - targetID = slotID + bid.ext.pricelevel; - } else { - targetID = slotID + '_' + bid.ext.dealid; - } - noTargetModeTargetID = slotID + '_' + bid.ext.dealid; - targetPrefix = PRIVATE_MARKET + '_'; - } else { - targetID = slotID + bid.ext.pricelevel; - noTargetModeTargetID = slotID + bid.ext.pricelevel; - targetPrefix = OPEN_MARKET + '_'; - } - if (_IndexRequestData.targetIDToBid[targetID] === undefined) { - _IndexRequestData.targetIDToBid[targetID] = [bid.adm]; - } else { - _IndexRequestData.targetIDToBid[targetID].push(bid.adm); - } - if (_IndexRequestData.targetIDToCreative[noTargetModeTargetID] === undefined) { - _IndexRequestData.targetIDToCreative[noTargetModeTargetID] = [bid.adm]; - } else { - _IndexRequestData.targetIDToCreative[noTargetModeTargetID].push(bid.adm); - } - var impBid = {}; - impBid.impressionID = bid.impid; - if (typeof bid.ext.dealid !== 'undefined') { - impBid.dealID = bid.ext.dealid; - } - impBid.bid = bid.price; - impBid.slotID = slotID; - impBid.priceLevel = bid.ext.pricelevel; - impBid.target = targetPrefix + targetID; - _IndexRequestData.targetIDToResp[targetID] = impBid; - allBids.push(impBid); - } - } - if (typeof callbackFn === 'function') { - if (allBids.length === 0) { - callbackFn(response.id); - } else { - callbackFn(response.id, allBids); - } - } - } - } catch (e) {} - - if (typeof window.cygnus_index_ready_state === 'function') { - window.cygnus_index_ready_state(); - } -} - -window.index_render = function(doc, targetID) { - try { - var ad = _IndexRequestData.targetIDToCreative[targetID].pop(); - if (ad != null) { - doc.write(ad); - } else { - var url = utils.getTopWindowLocation().protocol === 'http:' ? 'http://as.casalemedia.com' : 'https://as-sec.casalemedia.com'; - url += '/headerstats?type=RT&s=' + cygnus_index_args.siteID + '&u=' + encodeURIComponent(location.href) + '&r=' + _IndexRequestData.lastRequestID; - var px_call = new Image(); - px_call.src = url + '&blank=' + targetID; - } - } catch (e) {} -} - -window.headertag_render = function(doc, targetID, slotID) { - var index_slot = slotID; - var index_ary = targetID.split(','); - for (var i = 0; i < index_ary.length; i++) { - var unpack = index_ary[i].split('_'); - if (unpack[0] == index_slot) { - index_render(doc, index_ary[i]); - return; - } - } -} - -window.cygnus_index_args = {}; - -var cygnus_index_adunits = [[728, 90], [120, 600], [300, 250], [160, 600], [336, 280], [234, 60], [300, 600], [300, 50], [320, 50], [970, 250], [300, 1050], [970, 90], [180, 150]]; - -var getIndexDebugMode = function() { - return getParameterByName(CONSTANTS.INDEX_DEBUG_MODE.queryParam).toUpperCase(); -} - -var getParameterByName = function (name) { - var wdw = window; - var childsReferrer = ''; - for (var x = 0; x < CONSTANTS.INDEX_DEBUG_MODE.mode.sandbox.topFrameLimit; x++) { - if (wdw.parent == wdw) { - break; - } - try { - childsReferrer = wdw.document.referrer; - } catch (err) {} - wdw = wdw.parent; - } - var topURL = top === self ? location.href : childsReferrer; - var regexS = '[\\?&]' + name + '=([^&#]*)'; - var regex = new RegExp(regexS); - var results = regex.exec(topURL); - if (results === null) { - return ''; - } - return decodeURIComponent(results[1].replace(/\+/g, ' ')); -}; - -var cygnus_index_start = function () { - window.cygnus_index_args.parseFn = cygnus_index_parse_res; - var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - var meta = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"': '\\"', - '\\': '\\\\' - }; - - function escapeCharacter(character) { - var escaped = meta[character]; - if (typeof escaped === 'string') { - return escaped; - } else { - return '\\u' + ('0000' + character.charCodeAt(0).toString(16)).slice(-4); - } - } - - function quote(string) { - escapable.lastIndex = 0; - if (escapable.test(string)) { - return string.replace(escapable, escapeCharacter); - } else { - return string; - } - } - - function OpenRTBRequest(siteID, parseFn, timeoutDelay) { - this.initialized = false; - if (typeof siteID !== 'number' || siteID % 1 !== 0 || siteID < 0) { - throw 'Invalid Site ID'; - } - - timeoutDelay = Number(timeoutDelay); - if (typeof timeoutDelay === 'number' && timeoutDelay % 1 === 0 && timeoutDelay >= 0) { - this.timeoutDelay = timeoutDelay; - } - - this.siteID = siteID; - this.impressions = []; - this._parseFnName = undefined; - - // Get page URL - this.sitePage = undefined; - try { - this.sitePage = utils.getTopWindowUrl(); - } catch (e) {} - // Fallback to old logic if utils.getTopWindowUrl() fails to return site.page - if (typeof this.sitePage === 'undefined' || this.sitePage === '') { - if (top === self) { - this.sitePage = location.href; - } else { - this.sitePage = document.referrer; - } - } - - if (top === self) { - this.topframe = 1; - } else { - this.topframe = 0; - } - - if (typeof parseFn !== 'undefined') { - if (typeof parseFn === 'function') { - this._parseFnName = 'cygnus_index_args.parseFn'; - } else { - throw 'Invalid jsonp target function'; - } - } - - if (typeof _IndexRequestData.requestCounter === 'undefined') { - _IndexRequestData.requestCounter = Math.floor(Math.random() * 256); - } else { - _IndexRequestData.requestCounter = (_IndexRequestData.requestCounter + 1) % 256; - } - - this.requestID = String((new Date().getTime() % 2592000) * 256 + _IndexRequestData.requestCounter + 256); - this.initialized = true; - } - - OpenRTBRequest.prototype.serialize = function () { - var json = '{"id":"' + this.requestID + '","site":{"page":"' + quote(this.sitePage) + '"'; - if (typeof document.referrer === 'string' && document.referrer !== '') { - json += ',"ref":"' + quote(document.referrer) + '"'; - } - - json += '},"imp":['; - for (var i = 0; i < this.impressions.length; i++) { - var impObj = this.impressions[i]; - var ext = []; - json += '{"id":"' + impObj.id + '", "banner":{"w":' + impObj.w + ',"h":' + impObj.h + ',"topframe":' + String(this.topframe) + '}'; - if (typeof impObj.bidfloor === 'number') { - json += ',"bidfloor":' + impObj.bidfloor; - if (typeof impObj.bidfloorcur === 'string') { - json += ',"bidfloorcur":"' + quote(impObj.bidfloorcur) + '"'; - } - } - - if (typeof impObj.slotID === 'string' && (!impObj.slotID.match(/^\s*$/))) { - ext.push('"sid":"' + quote(impObj.slotID) + '"'); - } - - if (typeof impObj.siteID === 'number') { - ext.push('"siteID":' + impObj.siteID); - } - - if (ext.length > 0) { - json += ',"ext": {' + ext.join() + '}'; - } - - if (i + 1 === this.impressions.length) { - json += '}'; - } else { - json += '},'; - } - } - - json += ']}'; - return json; - }; - - OpenRTBRequest.prototype.setPageOverride = function (sitePageOverride) { - if (typeof sitePageOverride === 'string' && (!sitePageOverride.match(/^\s*$/))) { - this.sitePage = sitePageOverride; - return true; - } else { - return false; - } - }; - - OpenRTBRequest.prototype.addImpression = function (width, height, bidFloor, bidFloorCurrency, slotID, siteID) { - var impObj = { - id: String(this.impressions.length + 1) - }; - if (typeof width !== 'number' || width <= 1) { - return null; - } - - if (typeof height !== 'number' || height <= 1) { - return null; - } - - if ((typeof slotID === 'string' || typeof slotID === 'number') && String(slotID).length <= 50) { - impObj.slotID = String(slotID); - } - - impObj.w = width; - impObj.h = height; - if (bidFloor !== undefined && typeof bidFloor !== 'number') { - return null; - } - - if (typeof bidFloor === 'number') { - if (bidFloor < 0) { - return null; - } - - impObj.bidfloor = bidFloor; - if (bidFloorCurrency !== undefined && typeof bidFloorCurrency !== 'string') { - return null; - } - - impObj.bidfloorcur = bidFloorCurrency; - } - - if (typeof siteID !== 'undefined') { - if (typeof siteID === 'number' && siteID % 1 === 0 && siteID >= 0) { - impObj.siteID = siteID; - } else { - return null; - } - } - - this.impressions.push(impObj); - return impObj.id; - }; - - OpenRTBRequest.prototype.buildRequest = function () { - if (this.impressions.length === 0 || this.initialized !== true) { - return; - } - - var jsonURI = encodeURIComponent(this.serialize()); - - var scriptSrc; - if (getIndexDebugMode() == CONSTANTS.INDEX_DEBUG_MODE.mode.sandbox.queryValue.toUpperCase()) { - this.siteID = CONSTANTS.INDEX_DEBUG_MODE.mode.sandbox.siteID; - scriptSrc = utils.getTopWindowLocation().protocol === 'http:' ? 'http://sandbox.ht.indexexchange.com' : 'https://sandbox.ht.indexexchange.com'; - utils.logMessage('IX DEBUG: Sandbox mode activated'); - } else { - scriptSrc = utils.getTopWindowLocation().protocol === 'http:' ? 'http://as.casalemedia.com' : 'https://as-sec.casalemedia.com'; - } - var prebidVersion = encodeURIComponent('$prebid.version$'); - scriptSrc += '/cygnus?v=7&fn=cygnus_index_parse_res&s=' + this.siteID + '&r=' + jsonURI + '&pid=pb' + prebidVersion; - if (typeof this.timeoutDelay === 'number' && this.timeoutDelay % 1 === 0 && this.timeoutDelay >= 0) { - scriptSrc += '&t=' + this.timeoutDelay; - } - - return scriptSrc; - }; - - try { - if (typeof cygnus_index_args === 'undefined' || typeof cygnus_index_args.siteID === 'undefined' || typeof cygnus_index_args.slots === 'undefined') { - return; - } - - var req = new OpenRTBRequest(cygnus_index_args.siteID, cygnus_index_args.parseFn, cygnus_index_args.timeout); - if (cygnus_index_args.url && typeof cygnus_index_args.url === 'string') { - req.setPageOverride(cygnus_index_args.url); - } - - _IndexRequestData.impIDToSlotID[req.requestID] = {}; - _IndexRequestData.reqOptions[req.requestID] = {}; - var slotDef, impID; - - for (var i = 0; i < cygnus_index_args.slots.length; i++) { - slotDef = cygnus_index_args.slots[i]; - - impID = req.addImpression(slotDef.width, slotDef.height, slotDef.bidfloor, slotDef.bidfloorcur, slotDef.id, slotDef.siteID); - if (impID) { - _IndexRequestData.impIDToSlotID[req.requestID][impID] = String(slotDef.id); - } - } - - if (typeof cygnus_index_args.targetMode === 'number') { - _IndexRequestData.reqOptions[req.requestID].targetMode = cygnus_index_args.targetMode; - } - - if (typeof cygnus_index_args.callback === 'function') { - _IndexRequestData.reqOptions[req.requestID].callback = cygnus_index_args.callback; - } - - return req.buildRequest(); - } catch (e) { - utils.logError('Error calling index adapter', ADAPTER_NAME, e); - } -}; - -var IndexExchangeAdapter = function IndexExchangeAdapter() { - let baseAdapter = new Adapter('indexExchange'); - - var slotIdMap = {}; - var requiredParams = [ - /* 0 */ - 'id', - /* 1 */ - 'siteID' - ]; - var firstAdUnitCode = ''; - let bidRequests = {}; - - function passOnBid(adUnitCode) { - var bid = bidfactory.createBid(2); - bid.bidderCode = ADAPTER_CODE; - bidmanager.addBidResponse(adUnitCode, bid); - return bid; - } - - function _callBids(request) { - if (typeof request === 'undefined' || utils.isEmpty(request)) { - return; - } - - var bidArr = request.bids; - - if (typeof window._IndexRequestData === 'undefined') { - window._IndexRequestData = {}; - window._IndexRequestData.impIDToSlotID = {}; - window._IndexRequestData.reqOptions = {}; - } - // clear custom targets at the beginning of every request - _IndexRequestData.targetAggregate = {'open': {}, 'private': {}}; - - // Our standard is to always bid for all known slots. - cygnus_index_args.slots = []; - - var videoImpressions = []; - - // Grab the slot level data for cygnus_index_args - bidArr.forEach(bid => { - if (bid.mediaType === 'video') { - var impression = buildVideoImpressions(bid, bidRequests); - if (typeof impression !== 'undefined') { - videoImpressions.push(impression); - } - } else { - cygnus_index_init(bid); - } - }); - - if (videoImpressions.length > 0) { - sendVideoRequest(request.bidderRequestId, videoImpressions); - } - - if (cygnus_index_args.slots.length > 20) { - utils.logError('Too many unique sizes on slots, will use the first 20.', ADAPTER_NAME); - } - - if (cygnus_index_args.slots.length > 0) { - // bidmanager.setExpectedBidsCount(ADAPTER_CODE, expectedBids); - adloader.loadScript(cygnus_index_start()); - } - - var responded = false; - - // Handle response - window.cygnus_index_ready_state = function () { - if (responded) { - return; - } - responded = true; - - try { - var indexObj = _IndexRequestData.targetIDToBid; - - // Grab all the bids for each slot - for (var adSlotId in slotIdMap) { - var bidObj = slotIdMap[adSlotId]; - var adUnitCode = bidObj.placementCode; - - var bids = []; - - // Grab the bid for current slot - for (var cpmAndSlotId in indexObj) { - var match = /^(T\d_)?(.+)_(\d+)$/.exec(cpmAndSlotId); - // if parse fail, move to next bid - if (!(match)) { - utils.logError('Unable to parse ' + cpmAndSlotId + ', skipping slot', ADAPTER_NAME); - continue; - } - var tier = match[1] || ''; - var slotID = match[2]; - var currentCPM = match[3]; - - var slotObj = getSlotObj(cygnus_index_args, tier + slotID); - // Bid is for the current slot - if (slotID === adSlotId) { - var bid = bidfactory.createBid(1); - bid.cpm = currentCPM / 100; - bid.ad = indexObj[cpmAndSlotId][0]; - bid.bidderCode = ADAPTER_CODE; - bid.width = slotObj.width; - bid.height = slotObj.height; - bid.siteID = slotObj.siteID; - if (typeof _IndexRequestData.targetIDToResp === 'object' && typeof _IndexRequestData.targetIDToResp[cpmAndSlotId] === 'object' && typeof _IndexRequestData.targetIDToResp[cpmAndSlotId].dealID !== 'undefined') { - if (typeof _IndexRequestData.targetAggregate['private'][adUnitCode] === 'undefined') { _IndexRequestData.targetAggregate['private'][adUnitCode] = []; } - bid.dealId = _IndexRequestData.targetIDToResp[cpmAndSlotId].dealID; - _IndexRequestData.targetAggregate['private'][adUnitCode].push(slotID + '_' + _IndexRequestData.targetIDToResp[cpmAndSlotId].dealID); - } else { - if (typeof _IndexRequestData.targetAggregate['open'][adUnitCode] === 'undefined') { _IndexRequestData.targetAggregate['open'][adUnitCode] = []; } - _IndexRequestData.targetAggregate['open'][adUnitCode].push(slotID + '_' + currentCPM); - } - bids.push(bid); - } - } - - if (bids.length > 0) { - // Add all bid responses - for (var i = 0; i < bids.length; i++) { - bidmanager.addBidResponse(adUnitCode, bids[i]); - } - // No bids for expected bid, pass bid - } else { - passOnBid(adUnitCode); - } - } - } catch (e) { - utils.logError('Error calling index adapter', ADAPTER_NAME, e); - logErrorBidResponse(); - } finally { - // ensure that previous targeting mapping is cleared - _IndexRequestData.targetIDToBid = {}; - } - - // slotIdMap is used to determine which slots will be bid on in a given request. - // Therefore it needs to be blanked after the request is handled, else we will submit 'bids' for the wrong ads. - slotIdMap = {}; - }; - } - - function cygnus_index_init(bid) { - if (!utils.hasValidBidRequest(bid.params, requiredParams, ADAPTER_NAME)) { - passOnBid(bid.placementCode); - return; - } - - var sizeID = 0; - - // Expecting nested arrays for sizes - if (!utils.isArray(bid.sizes[0])) { - bid.sizes = [bid.sizes]; - } - - // Create index slots for all bids and sizes - for (var j = 0; j < bid.sizes.length; j++) { - var validSize = false; - for (var k = 0; k < cygnus_index_adunits.length; k++) { - if (bid.sizes[j][0] == cygnus_index_adunits[k][0] && - bid.sizes[j][1] == cygnus_index_adunits[k][1]) { - bid.sizes[j][0] = Number(bid.sizes[j][0]); - bid.sizes[j][1] = Number(bid.sizes[j][1]); - validSize = true; - break; - } - } - - if (!validSize) { - utils.logMessage(ADAPTER_NAME + ' slot excluded from request due to no valid sizes'); - passOnBid(bid.placementCode); - continue; - } - - var usingSizeSpecificSiteID = false; - // Check for size defined in bidder params - if (bid.params.size && utils.isArray(bid.params.size)) { - if (!(bid.sizes[j][0] == bid.params.size[0] && bid.sizes[j][1] == bid.params.size[1])) { - passOnBid(bid.placementCode); - continue; - } - usingSizeSpecificSiteID = true; - } - - if (bid.params.timeout && typeof cygnus_index_args.timeout === 'undefined') { - cygnus_index_args.timeout = bid.params.timeout; - } - - var siteID = Number(bid.params.siteID); - if (typeof siteID !== 'number' || siteID % 1 != 0 || siteID <= 0) { - utils.logMessage(ADAPTER_NAME + ' slot excluded from request due to invalid siteID'); - passOnBid(bid.placementCode); - continue; - } - if (siteID && typeof cygnus_index_args.siteID === 'undefined') { - cygnus_index_args.siteID = siteID; - } - - if (utils.hasValidBidRequest(bid.params, requiredParams, ADAPTER_NAME)) { - firstAdUnitCode = bid.placementCode; - var slotID = bid.params[requiredParams[0]]; - if (typeof slotID !== 'string' && typeof slotID !== 'number') { - utils.logError(ADAPTER_NAME + ' bid contains invalid slot ID from ' + bid.placementCode + '. Discarding slot'); - passOnBid(bid.placementCode); - continue - } - - sizeID++; - var size = { - width: bid.sizes[j][0], - height: bid.sizes[j][1] - }; - - var slotName = usingSizeSpecificSiteID ? String(slotID) : slotID + '_' + sizeID; - slotIdMap[slotName] = bid; - - // Doesn't need the if(primary_request) conditional since we are using the mergeSlotInto function which is safe - cygnus_index_args.slots = mergeSlotInto({ - id: slotName, - width: size.width, - height: size.height, - siteID: siteID || cygnus_index_args.siteID - }, cygnus_index_args.slots); - - if (bid.params.tier2SiteID) { - var tier2SiteID = Number(bid.params.tier2SiteID); - if (typeof tier2SiteID !== 'undefined' && !tier2SiteID) { - continue; - } - - cygnus_index_args.slots = mergeSlotInto({ - id: 'T1_' + slotName, - width: size.width, - height: size.height, - siteID: tier2SiteID - }, cygnus_index_args.slots); - } - - if (bid.params.tier3SiteID) { - var tier3SiteID = Number(bid.params.tier3SiteID); - if (typeof tier3SiteID !== 'undefined' && !tier3SiteID) { - continue; - } - - cygnus_index_args.slots = mergeSlotInto({ - id: 'T2_' + slotName, - width: size.width, - height: size.height, - siteID: tier3SiteID - }, cygnus_index_args.slots); - } - } - } - } - - function sendVideoRequest(requestID, videoImpressions) { - let cygnusRequest = { - 'id': requestID, - 'imp': videoImpressions, - 'site': { - 'page': utils.getTopWindowUrl() - } - }; - - if (!utils.isEmpty(cygnusRequest.imp)) { - let cygnusRequestUrl = createCygnusRequest(cygnusRequest.imp[0].ext.siteID, cygnusRequest); - - adloader.loadScript(cygnusRequestUrl); - } - } - - function buildVideoImpressions(bid) { - if (!validateBid(bid)) { - return; - } - - bid = transformBid(bid); - - // map request id to bid object to retrieve adUnit code in callback - bidRequests[bid.bidId] = {}; - bidRequests[bid.bidId].prebid = bid; - - let cygnusImpression = {}; - cygnusImpression.id = bid.bidId; - - cygnusImpression.ext = {}; - cygnusImpression.ext.siteID = bid.params.video.siteID; - delete bid.params.video.siteID; - - let podType = bid.params.video.startdelay; - if (bid.params.video.startdelay === 0) { - podType = 'preroll'; - } else if (typeof START_DELAY_MAP[bid.params.video.startdelay] === 'undefined') { - podType = 'midroll'; - } - cygnusImpression.ext.sid = [SLOT_ID_PREFIX_MAP[podType], 1, 1, 's'].join('_'); - - cygnusImpression.video = {}; - - if (bid.params.video) { - Object.keys(bid.params.video) - .filter(param => typeof VIDEO_REQUIRED_PARAMS_MAP[param] !== 'undefined' || typeof VIDEO_OPTIONAL_PARAMS_MAP[param] !== 'undefined') - .forEach(param => { - if (param === 'startdelay' && typeof START_DELAY_MAP[bid.params.video[param]] !== 'undefined') { - bid.params.video[param] = START_DELAY_MAP[bid.params.video[param]]; - } - if (param === 'linearity' && typeof LINEARITY_MAP[bid.params.video[param]] !== 'undefined') { - bid.params.video[param] = LINEARITY_MAP[bid.params.video[param]]; - } - cygnusImpression.video[param] = bid.params.video[param]; - }); - } else { - return; - } - - let bidSize = getSizes(bid.sizes).shift(); - if (!bidSize || !bidSize.width || !bidSize.height) { - return; - } - cygnusImpression.video.w = bidSize.width; - cygnusImpression.video.h = bidSize.height; - - bidRequests[bid.bidId].cygnus = cygnusImpression; - - return cygnusImpression; - } - - /* - Function in order to add a slot into the list if it hasn't been created yet, else it returns the same list. - */ - function mergeSlotInto(slot, slotList) { - for (var i = 0; i < slotList.length; i++) { - if (slot.id === slotList[i].id) { - return slotList; - } - } - slotList.push(slot); - return slotList; - } - - function getSlotObj(obj, id) { - var arr = obj.slots; - var returnObj = {}; - utils._each(arr, function (value) { - if (value.id === id) { - returnObj = value; - } - }); - - return returnObj; - } - - function logErrorBidResponse() { - // no bid response - var bid = bidfactory.createBid(2); - bid.bidderCode = ADAPTER_CODE; - - // log error to first add unit - bidmanager.addBidResponse(firstAdUnitCode, bid); - } - - function createCygnusRequest(siteID, cygnusRequest) { - let cygnusUrl = (window.location.protocol === 'https:') ? url.parse(BASE_CYGNUS_VIDEO_URL_SECURE) : url.parse(BASE_CYGNUS_VIDEO_URL_INSECURE); - cygnusUrl.search.s = siteID; - cygnusUrl.search.r = encodeURIComponent(JSON.stringify(cygnusRequest)); - let formattedCygnusUrl = url.format(cygnusUrl); - return formattedCygnusUrl; - } - - /* Notify Prebid of bid responses so bids can get in the auction */ - $$PREBID_GLOBAL$$.handleCygnusResponse = function (response) { - if (!response || !response.seatbid || utils.isEmpty(response.seatbid)) { - utils.logInfo('Cygnus returned no bids'); - - // signal this response is complete - Object.keys(bidRequests) - .forEach(bidId => { - let prebidRequest = bidRequests[bidId].prebid; - let bid = createBidObj(STATUS.NO_BID, prebidRequest); - utils.logInfo(JSON.stringify(bid)); - bidmanager.addBidResponse(prebidRequest.placementCode, bid); - }); - - return; - } - - response.seatbid - .forEach(seat => { - seat.bid.forEach(cygnusBid => { - let validBid = true; - - if (typeof bidRequests[cygnusBid.impid] === 'undefined') { - utils.logInfo('Cygnus returned mismatched id'); - - // signal this response is complete - Object.keys(bidRequests) - .forEach(bidId => { - let prebidRequest = bidRequests[bidId].prebid; - let bid = createBidObj(STATUS.NO_BID, prebidRequest); - bidmanager.addBidResponse(prebidRequest.placementCode, bid); - }); - return; - } - - if (!cygnusBid.ext.vasturl) { - utils.logInfo('Cygnus returned no vast url'); - validBid = false; - } - - if (url.parse(cygnusBid.ext.vasturl).host === window.location.host) { - utils.logInfo('Cygnus returned no vast url'); - validBid = false; - } - - let cpm; - if (typeof cygnusBid.ext.pricelevel === 'string') { - let priceLevel = cygnusBid.ext.pricelevel; - if (priceLevel.charAt(0) === '_') priceLevel = priceLevel.slice(1); - cpm = priceLevel / 100; - if (!utils.isNumber(cpm) || isNaN(cpm)) { - utils.logInfo('Cygnus returned invalid price'); - validBid = false; - } - } else { - validBid = false; - } - - let prebidRequest = bidRequests[cygnusBid.impid].prebid; - let cygnusRequest = bidRequests[cygnusBid.impid].cygnus; - - if (!validBid) { - let bid = createBidObj(STATUS.NO_BID, prebidRequest); - bidmanager.addBidResponse(prebidRequest.placementCode, bid); - return; - } - - let bid = createBidObj(STATUS.GOOD, prebidRequest); - bid.cpm = cpm; - bid.width = cygnusRequest.video.w; - bid.height = cygnusRequest.video.h; - bid.vastUrl = cygnusBid.ext.vasturl; - bid.mediaType = 'video'; - - bidmanager.addBidResponse(prebidRequest.placementCode, bid); - }); - }); - - bidRequests = {}; - }; - - function createBidObj(status, request) { - let bid = bidfactory.createBid(status, request); - bid.code = baseAdapter.getBidderCode(); - bid.bidderCode = baseAdapter.getBidderCode(); - - return bid; - } - - /* Check that a bid has required paramters */ - function validateBid(bid) { - if ( - bid.mediaType === 'video' && - utils.hasValidBidRequest(bid.params.video, Object.keys(VIDEO_REQUIRED_PARAMS_MAP), ADAPTER_NAME) && - isValidSite(bid.params.video.siteID) && - isValidPlayerType(bid.params.video.playerType) && - isValidProtocolArray(bid.params.video.protocols) && - isValidDuration(bid.params.video.maxduration) && bid.params.video.maxduration > 0 - ) { - return bid; - } - } - - function isValidSite(siteID) { - let intSiteID = +siteID; - if (isNaN(intSiteID) || !utils.isNumber(intSiteID) || intSiteID < 0 || utils.isArray(siteID)) { - utils.logError(`Site ID is invalid, must be a number > 0. Got: ${siteID}`); - return false; - } - return true; - } - - function isValidPlayerType(playerType) { - if (typeof playerType === 'undefined' || !utils.isStr(playerType)) { - utils.logError(`Player type is invalid, must be one of: ${Object.keys(SUPPORTED_PLAYER_TYPES_MAP)}`); - return false; - } - playerType = playerType.toUpperCase(); - if (!SUPPORTED_PLAYER_TYPES_MAP[playerType]) { - utils.logError(`Player type is invalid, must be one of: ${Object.keys(SUPPORTED_PLAYER_TYPES_MAP)}`); - return false; - } - return true; - } - - function isValidProtocolArray(protocolArray) { - if (!utils.isArray(protocolArray) || utils.isEmpty(protocolArray)) { - utils.logError(`Protocol array is not an array. Got: ${protocolArray}`); - return false; - } else { - for (var i = 0; i < protocolArray.length; i++) { - let protocol = protocolArray[i]; - if (!SUPPORTED_PROTOCOLS_MAP[protocol]) { - utils.logError(`Protocol array contains an invalid protocol, must be one of: ${SUPPORTED_PROTOCOLS_MAP}. Got: ${protocol}`); - return false; - } - } - } - return true; - } - - function isValidDuration(duration) { - let intDuration = +duration; - if (isNaN(intDuration) || !utils.isNumber(intDuration) || utils.isArray(duration)) { - utils.logError(`Duration is invalid, must be a number. Got: ${duration}`); - return false; - } - return true; - } - - function isValidMimeArray(mimeArray) { - if (!utils.isArray(mimeArray) || utils.isEmpty(mimeArray)) { - utils.logError(`MIMEs array is not an array. Got: ${mimeArray}`); - return false; - } else { - for (var i = 0; i < mimeArray.length; i++) { - let mimeType = mimeArray[i]; - if (!utils.isStr(mimeType) || utils.isEmptyStr(mimeType) || !/^\w+\/[\w-]+$/.test(mimeType)) { - utils.logError(`MIMEs array contains an invalid MIME type. Got: ${mimeType}`); - return false; - } - } - } - return true; - } - - function isValidLinearity(linearity) { - if (!LINEARITY_MAP[linearity]) { - utils.logInfo(`Linearity is invalid, must be one of: ${Object.keys(LINEARITY_MAP)}. Got: ${linearity}`); - return false; - } - return true; - } - - function isValidStartDelay(startdelay) { - if (typeof START_DELAY_MAP[startdelay] === 'undefined') { - let intStartdelay = +startdelay; - if (isNaN(intStartdelay) || !utils.isNumber(intStartdelay) || intStartdelay < -2 || utils.isArray(startdelay)) { - utils.logInfo(`Start delay is invalid, must be a number >= -2. Got: ${startdelay}`); - return false; - } - } - return true; - } - - function isValidApiArray(apiArray, playerType) { - if (!utils.isArray(apiArray) || utils.isEmpty(apiArray)) { - utils.logInfo(`API array is not an array. Got: ${apiArray}`); - return false; - } else { - for (var i = 0; i < apiArray.length; i++) { - let api = +apiArray[i]; - if (isNaN(api) || !SUPPORTED_API_MAP[playerType].includes(api)) { - utils.logInfo(`API array contains an invalid API version. Got: ${api}`); - return false; - } - } - } - return true; - } - - function transformBid(bid) { - bid.params.video.siteID = +bid.params.video.siteID; - bid.params.video.maxduration = +bid.params.video.maxduration; - - bid.params.video.protocols = bid.params.video.protocols.reduce((arr, protocol) => { - return arr.concat(SUPPORTED_PROTOCOLS_MAP[protocol]); - }, []); - - let minduration = bid.params.video.minduration; - if (typeof minduration === 'undefined' || !isValidDuration(minduration)) { - utils.logInfo(`Using default value for 'minduration', default: ${VIDEO_OPTIONAL_PARAMS_MAP.minduration}`); - bid.params.video.minduration = VIDEO_OPTIONAL_PARAMS_MAP.minduration; - } - - let startdelay = bid.params.video.startdelay; - if (typeof startdelay === 'undefined' || !isValidStartDelay(startdelay)) { - utils.logInfo(`Using default value for 'startdelay', default: ${VIDEO_OPTIONAL_PARAMS_MAP.startdelay}`); - bid.params.video.startdelay = VIDEO_OPTIONAL_PARAMS_MAP.startdelay; - } - - let linearity = bid.params.video.linearity; - if (typeof linearity === 'undefined' || !isValidLinearity(linearity)) { - utils.logInfo(`Using default value for 'linearity', default: ${VIDEO_OPTIONAL_PARAMS_MAP.linearity}`); - bid.params.video.linearity = VIDEO_OPTIONAL_PARAMS_MAP.linearity; - } - - let mimes = bid.params.video.mimes; - let playerType = bid.params.video.playerType.toUpperCase(); - if (typeof mimes === 'undefined' || !isValidMimeArray(mimes)) { - utils.logInfo(`Using default value for 'mimes', player type: '${playerType}', default: ${DEFAULT_MIMES_MAP[playerType]}`); - bid.params.video.mimes = DEFAULT_MIMES_MAP[playerType]; - } - - let apiList = bid.params.video.apiList; - if (typeof apiList !== 'undefined' && !isValidApiArray(apiList, playerType)) { - utils.logInfo(`Removing invalid api versions from api list.`); - if (utils.isArray(apiList)) { - bid.params.video.apiList = apiList.filter(api => SUPPORTED_API_MAP[playerType].includes(api)); - } else { - bid.params.video.apiList = []; - } - } - - if (typeof apiList === 'undefined' && bid.params.video.allowVPAID && utils.isA(bid.params.video.allowVPAID, 'Boolean')) { - bid.params.video.mimes = bid.params.video.mimes.concat(DEFAULT_VPAID_MIMES_MAP[playerType]); - bid.params.video.apiList = SUPPORTED_API_MAP[playerType]; - } - - if (utils.isEmpty(bid.params.video.apiList)) { - utils.logInfo(`API list is empty, VPAID ads will not be requested.`); - delete bid.params.video.apiList; - } - - delete bid.params.video.playerType; - delete bid.params.video.allowVPAID; - - return bid; - } - - /* Turn bid request sizes into ut-compatible format */ - function getSizes(requestSizes) { - let sizes = []; - let sizeObj = {}; - - if (utils.isArray(requestSizes) && requestSizes.length === 2 && !utils.isArray(requestSizes[0])) { - if (!utils.isNumber(requestSizes[0]) || !utils.isNumber(requestSizes[1])) { - return sizes; - } - sizeObj.width = requestSizes[0]; - sizeObj.height = requestSizes[1]; - 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; - } - - return Object.assign(this, { - callBids: _callBids - }); -}; - -adaptermanager.registerBidAdapter(new IndexExchangeAdapter(), 'indexExchange', { - supportedMediaTypes: ['video'] -}); - -module.exports = IndexExchangeAdapter; diff --git a/modules/inneractiveBidAdapter.js b/modules/inneractiveBidAdapter.js deleted file mode 100644 index c3b6c0a9027..00000000000 --- a/modules/inneractiveBidAdapter.js +++ /dev/null @@ -1,459 +0,0 @@ -import * as utils from 'src/utils'; -import Adapter from 'src/adapter'; -import {ajax} from 'src/ajax'; -import bidManager from 'src/bidmanager'; -import bidFactory from 'src/bidfactory'; -import {STATUS} from 'src/constants'; -import {formatQS} from 'src/url'; -import adaptermanager from 'src/adaptermanager'; -import { config } from 'src/config'; - -/** - * @type {{IA_JS: string, ADAPTER_NAME: string, V: string, RECTANGLE_SIZE: {W: number, H: number}, SPOT_TYPES: {INTERSTITIAL: string, RECTANGLE: string, FLOATING: string, BANNER: string}, DISPLAY_AD: number, ENDPOINT_URL: string, EVENTS_ENDPOINT_URL: string, RESPONSE_HEADERS_NAME: {PRICING_VALUE: string, AD_H: string, AD_W: string}}} - */ -const CONSTANTS = { - ADAPTER_NAME: 'inneractive', - V: 'IA-JS-HB-PBJS-1.0', - RECTANGLE_SIZE: {W: 300, H: 250}, - - SPOT_TYPES: { - INTERSTITIAL: 'interstitial', - RECTANGLE: 'rectangle', - FLOATING: 'floating', - BANNER: 'banner' - }, - - DISPLAY_AD: 20, - ENDPOINT_URL: '//ad-tag.inner-active.mobi/simpleM2M/requestJsonAd', - EVENTS_ENDPOINT_URL: '//vast-events.inner-active.mobi/Event', - RESPONSE_HEADERS_NAME: { - PRICING_VALUE: 'X-IA-Pricing-Value', - AD_H: 'X-IA-Ad-Height', - AD_W: 'X-IA-Ad-Width' - } -}; - -let iaRef; -try { - iaRef = window.top.document.referrer; -} catch (e) { - iaRef = window.document.referrer; -} - -/** - * gloable util functions - * @type {{defaultsQsParams: {v: (string|string), page: string, mw: boolean, hb: string}, stringToCamel: (function(*)), objectToCamel: (function(*=))}} - */ -const Helpers = { - defaultsQsParams: {v: CONSTANTS.V, page: encodeURIComponent(utils.getTopWindowUrl()), mw: true, hb: 'prebidjs'}, - /** - * Change string format from underscore to camelcase (e.g., APP_ID to appId) - * @param str: string - * @returns string - */ - stringToCamel(str) { - if (str.indexOf('_') === -1) { - const first = str.charAt(0); - if (first !== first.toLowerCase()) { - str = str.toLowerCase(); - } - return str; - } - - str = str.toLowerCase(); - return str.replace(/(\_[a-z])/g, $1 => $1.toUpperCase().replace('_', '')); - }, - - /** - * Change all object keys string format from underscore to camelcase (e.g., {'APP_ID' : ...} to {'appId' : ...}) - * @param params: object - * @returns object - */ - objectToCamel(params) { - Object.keys(params).forEach(key => { - const keyCamelCase = this.stringToCamel(key); - if (keyCamelCase !== key) { - params[keyCamelCase] = params[key]; - delete params[key]; - } - }); - return params; - } -}; - -/** - * Tracking pixels for events - * @type {{fire: (function(*=))}} - */ -const Tracker = { - /** - * Creates a tracking pixel - * @param urls: Array - */ - fire(urls) { - urls.forEach(url => url && ((new Image(1, 1)).src = encodeURI(url))); - } -}; - -/** - * Analytics - * @type {{errorEventName: string, pageProtocol: string, getPageProtocol: (function(): string), getEventUrl: (function(*, *=)), reportEvent: (function(string, Object)), defaults: {v: (string|string), page: string, mw: boolean, hb: string}, eventQueryStringParams: (function(Object): string), createTrackingPixel: (function(string))}} - */ -const Reporter = { - /** - * @private - */ - errorEventName: 'HBPreBidError', - pageProtocol: '', - - /** - * Gets the page protocol based on the document.location.protocol - * The returned string is either http:// or https:// - * @returns {string} - */ - getPageProtocol() { - if (!this.pageProtocol) { - this.pageProtocol = (utils.getTopWindowLocation().protocol === 'http:' ? 'http:' : 'https:'); - } - return this.pageProtocol; - }, - - getEventUrl(evtName, extraDetails) { - let eventsEndpoint = CONSTANTS.EVENTS_ENDPOINT_URL + '?table=' + ((evtName === this.errorEventName) ? 'mbwError' : 'mbwEvent'); - let queryStringParams = this.eventQueryStringParams(extraDetails); - const appId = extraDetails && extraDetails.appId; - let queryStringParamsWithAID = `${queryStringParams}&aid=${appId}_${evtName}_other&evtName=${evtName}`; - return eventsEndpoint + '&' + queryStringParamsWithAID; - }, - - /** - * Reports an event to IA's servers. - * @param {string} evtName - event name as string. - * @param {object} extraDetails - e.g., a JS exception JSON object. - * @param shouldSendOnlyToNewEndpoint - */ - reportEvent(evtName, extraDetails) { - const url = this.getEventUrl(evtName, extraDetails); - this.createTrackingPixel(url); - }, - defaults: Helpers.defaultsQsParams, - - /** - * Ia Event Reporting Query String Parameters, not including App Id. - * @param {object} extraDetails - e.g., a JS exception JSON object. - * @return {string} IA event contcatenated queryString parameters. - */ - eventQueryStringParams(extraDetails) { - const toQS = Object.assign({}, this.defaults, {realAppId: extraDetails && extraDetails.appId, timestamp: Date.now()}); - return formatQS(toQS); - }, - - /** - * Creates a tracking pixel by prepending the page's protocol to the URL sent as the param. - * @param {string} urlWithoutProtocol - the URL to send the tracking pixel to, without the protocol as a prefix. - */ - createTrackingPixel(urlWithoutProtocol) { - Tracker.fire([this.getPageProtocol() + urlWithoutProtocol]); - } -}; - -/** - * Url generator - generates a request URL - * @type {{defaultsParams: *, serverParamNameBySettingParamName: {referrer: string, keywords: string, appId: string, portal: string, age: string, gender: string, isSecured: (boolean|null)}, toServerParams: (function(*)), unwantedValues: *[], getUrlParams: (function(*=))}} - */ -const Url = { - defaultsParams: Object.assign({}, Helpers.defaultsQsParams, {f: CONSTANTS.DISPLAY_AD, fs: false, ref: iaRef}), - serverParamNameBySettingParamName: { - referrer: 'ref', - keywords: 'k', - appId: 'aid', - portal: 'po', - age: 'a', - gender: 'g', - }, - unwantedValues: ['', null, undefined], - - /** - * Maps publisher params to server params - * @param params: object {k:v} - * @returns object {k:v} - */ - toServerParams(params) { - const serverParams = {}; - for (const paramName in params) { - if (params.hasOwnProperty(paramName) && this.serverParamNameBySettingParamName.hasOwnProperty(paramName)) { - serverParams[this.serverParamNameBySettingParamName[paramName]] = params[paramName]; - } else { - serverParams[paramName] = params[paramName]; - } - } - - serverParams.isSecured = Reporter.getPageProtocol() === 'https:' || null; - return serverParams; - }, - - /** - * Prepare querty string to ad server - * @param params: object {k:v} - * @returns : object {k:v} - */ - getUrlParams(params) { - const serverParams = this.toServerParams(params); - const toQueryString = Object.assign({}, this.defaultsParams, serverParams); - for (const paramName in toQueryString) { - if (toQueryString.hasOwnProperty(paramName) && this.unwantedValues.indexOf(toQueryString[paramName]) !== -1) { - delete toQueryString[paramName]; - } - } - toQueryString.fs = params.spotType === CONSTANTS.SPOT_TYPES.INTERSTITIAL; - - if (params.spotType === CONSTANTS.SPOT_TYPES.RECTANGLE) { - toQueryString.rw = CONSTANTS.RECTANGLE_SIZE.W; - toQueryString.rh = CONSTANTS.RECTANGLE_SIZE.H; - } - - if (typeof $$PREBID_GLOBAL$$ !== 'undefined') { - toQueryString.bco = $$PREBID_GLOBAL$$.cbTimeout || config.getConfig('bidderTimeout'); - } - - toQueryString.timestamp = Date.now(); - delete toQueryString.qa; - return toQueryString; - } -}; - -/** - * Http helper to extract metadata - * @type {{headers: *[], getBidHeaders: (function(*))}} - */ -const Http = { - headers: [ - CONSTANTS.RESPONSE_HEADERS_NAME.PRICING_VALUE, - CONSTANTS.RESPONSE_HEADERS_NAME.AD_H, - CONSTANTS.RESPONSE_HEADERS_NAME.AD_W - ], - - /** - * Extract headers data - * @param xhr: XMLHttpRequest - * @returns {} - */ - getBidHeaders(xhr) { - const headersData = {}; - this.headers.forEach(headerName => headersData[headerName] = xhr.getResponseHeader(headerName)); - return headersData; - } -}; - -/** - * InnerActiveAdapter for requesting bids - * @class - */ -class InnerActiveAdapter { - constructor() { - this.iaAdapter = new Adapter(CONSTANTS.ADAPTER_NAME); - this.setBidderCode = this.iaAdapter.setBidderCode.bind(this); - - this.bidByBidId = {}; - } - - /** - * validate if bid request is valid - * @param adSettings: object - * @returns {boolean} - * @private - */ - _isValidRequest(adSettings) { - if (adSettings && adSettings.appId && adSettings.spotType) { - return true; - } - utils.logError('bid requires appId'); - return false; - } - - /** - * Store the bids in a Map object (k: bidId, v: bid)to check later if won - * @param bid - * @returns bid object - * @private - */ - _storeBidRequestDetails(bid) { - this.bidByBidId[bid.bidId] = bid; - return bid; - } - - /** - * @param bidStatus: int ("STATUS": {"GOOD": 1,"NO_BID": 2}) - * @param bidResponse: object - * @returns {type[]} - * @private - */ - _getBidDetails(bidStatus, bidResponse, bidId) { - let bid = bidFactory.createBid(bidStatus, bidResponse); - bid.code = CONSTANTS.ADAPTER_NAME; - bid.bidderCode = bid.code; - if (bidStatus === STATUS.GOOD) { - bid = Object.assign(bid, bidResponse); - this._setBidCpm(bid, bidId); - } - return bid; - } - - _setBidCpm(bid, bidId) { - const storedBid = this.bidByBidId[bidId]; - if (storedBid) { - bid.cpm = (storedBid.params && storedBid.params.qa && storedBid.params.qa.cpm) || bid.cpm; - bid.cpm = (bid.cpm !== null && !isNaN(bid.cpm)) ? parseFloat(bid.cpm) : 0.0; - } - } - - /** - * Validate if response is valid - * @param responseAsJson : object - * @param headersData: {} - * @returns {boolean} - * @private - */ - _isValidBidResponse(responseAsJson, headersData) { - return (responseAsJson && responseAsJson.ad && responseAsJson.ad.html && headersData && headersData[CONSTANTS.RESPONSE_HEADERS_NAME.PRICING_VALUE] > 0); - } - - /** - * When response is received - * @param response: string(json format) - * @param xhr: XMLHttpRequest - * @param bidId: string - * @private - */ - _onResponse(response, xhr, bidId) { - const bid = this.bidByBidId[bidId]; - const [w, h] = bid.sizes[0]; - const size = {w, h}; - let responseAsJson; - const headersData = Http.getBidHeaders(xhr); - try { - responseAsJson = JSON.parse(response); - } catch (error) { - utils.logError(error); - } - - if (!this._isValidBidResponse(responseAsJson, headersData)) { - let errorMessage = `response failed for ${CONSTANTS.ADAPTER_NAME} adapter`; - utils.logError(errorMessage); - const passback = responseAsJson && responseAsJson.config && responseAsJson.config.passback; - if (passback) { - Tracker.fire([passback]); - } - Reporter.reportEvent('HBPreBidNoAd', bid.params); - return bidManager.addBidResponse(bid.placementCode, this._getBidDetails(STATUS.NO_BID)); - } - const bidResponse = { - cpm: headersData[CONSTANTS.RESPONSE_HEADERS_NAME.PRICING_VALUE] * 1000, - width: parseFloat(headersData[CONSTANTS.RESPONSE_HEADERS_NAME.AD_W]) || size.w, - ad: this._getAd(responseAsJson.ad.html, responseAsJson.config.tracking, bid.params), - height: parseFloat(headersData[CONSTANTS.RESPONSE_HEADERS_NAME.AD_H]) || size.h - }; - const auctionBid = this._getBidDetails(STATUS.GOOD, bidResponse, bidId); - bid.adId = auctionBid.adId; - this.bidByBidId[bidId] = bid; - bidManager.addBidResponse(bid.placementCode, auctionBid); - } - - /** - * Returns the ad HTML template - * @param adHtml: string {ad server creative} - * @param tracking: object {impressions, clicks} - * @param bidParams: object - * @returns {string}: create template - * @private - */ - _getAd(adHtml, tracking, bidParams) { - let impressionsHtml = ''; - if (tracking && Array.isArray(tracking.impressions)) { - let impressions = tracking.impressions; - impressions.push(Reporter.getEventUrl('HBPreBidImpression', bidParams, false)); - impressions.forEach(impression => impression && (impressionsHtml += utils.createTrackPixelHtml(impression))); - } - adHtml = impressionsHtml + adHtml.replace(/ - - - - -
${adHtml}
- - - `; - return adTemplate; - } - /** - * Adjust bid params to ia-ad-server params - * @param bid: object - * @private - */ - _toIaBidParams(bid) { - const bidParamsWithCustomParams = Object.assign({}, bid.params, bid.params.customParams); - delete bidParamsWithCustomParams.customParams; - bid.params = Helpers.objectToCamel(bidParamsWithCustomParams); - } - - /** - * Prebid executes for stating an auction - * @param bidRequest: object - */ - callBids(bidRequest) { - const bids = bidRequest.bids || []; - bids.forEach(bid => this._toIaBidParams(bid)); - bids - .filter(bid => this._isValidRequest(bid.params)) - .map(bid => this._storeBidRequestDetails(bid)) - .forEach(bid => ajax(this._getEndpointUrl(bid.params), (response, xhr) => this._onResponse(response, xhr, bid.bidId), Url.getUrlParams(bid.params), {method: 'GET'})); - } - - _getEndpointUrl(params) { - return (params && params.qa && params.qa.url) || Reporter.getPageProtocol() + CONSTANTS.ENDPOINT_URL; - } - - _getStoredBids() { - const storedBids = []; - for (const bidId in this.bidByBidId) { - if (this.bidByBidId.hasOwnProperty(bidId)) { - storedBids.push(this.bidByBidId[bidId]); - } - } - return storedBids; - } - - /** - * Return internal object - testing - * @returns {{Reporter: {errorEventName: string, pageProtocol: string, getPageProtocol: (function(): string), getEventUrl: (function(*, *=)), reportEvent: (function(string, Object)), defaults: {v: (string|string), page: string, mw: boolean, hb: string}, eventQueryStringParams: (function(Object): string), createTrackingPixel: (function(string))}}} - * @private - */ - static _getUtils() { - return {Reporter}; - } -} - -adaptermanager.registerBidAdapter(new InnerActiveAdapter(), 'inneractive'); - -module.exports = InnerActiveAdapter; diff --git a/modules/innityBidAdapter.js b/modules/innityBidAdapter.js deleted file mode 100644 index 79afe7ffe17..00000000000 --- a/modules/innityBidAdapter.js +++ /dev/null @@ -1,65 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var CONSTANTS = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -var InnityAdapter = function InnityAdapter() { - function _callBids(params) { - var bidURL; - const bids = params.bids || []; - const requestURL = window.location.protocol + '//as.innity.com/synd/?cb=' + new Date().getTime() + '&ver=2&hb=1&output=js&'; - for (var i = 0; i < bids.length; i++) { - const requestParams = {}; - const bid = bids[i]; - requestParams.pub = bid.params.pub; - requestParams.zone = bid.params.zone; - // Page URL - requestParams.url = utils.getTopWindowUrl(); - // Sizes - const parseSized = utils.parseSizesInput(bid.sizes); - const arrSize = parseSized[0].split('x'); - requestParams.width = arrSize[0]; - requestParams.height = arrSize[1]; - // Callback function - requestParams.callback = '$$PREBID_GLOBAL$$._doInnityCallback'; - // Callback ID - requestParams.callback_uid = bid.bidId; - // Load Bidder URL - bidURL = requestURL + utils.parseQueryStringParameters(requestParams); - utils.logMessage('Innity.prebid, Bid ID: ' + bid.bidId + ', Pub ID: ' + bid.params.pub + ', Zone ID: ' + bid.params.zone + ', URL: ' + bidURL); - adloader.loadScript(bidURL); - } - } - - $$PREBID_GLOBAL$$._doInnityCallback = function(response) { - var bidObject; - var bidRequest; - var callbackID; - var libURL = window.location.protocol + '//cdn.innity.net/frame_util.js'; - callbackID = response.callback_uid; - bidRequest = utils.getBidRequest(callbackID); - if (response.cpm > 0) { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.GOOD, bidRequest); - bidObject.bidderCode = 'innity'; - bidObject.cpm = parseFloat(response.cpm) / 100; - bidObject.ad = '' + response.tag; - bidObject.width = response.width; - bidObject.height = response.height; - } else { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidRequest); - bidObject.bidderCode = 'innity'; - utils.logMessage('No Bid response from Innity request: ' + callbackID); - } - bidmanager.addBidResponse(bidRequest.placementCode, bidObject); - }; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new InnityAdapter(), 'innity'); - -module.exports = InnityAdapter; diff --git a/modules/kruxlinkBidAdapter.js b/modules/kruxlinkBidAdapter.js deleted file mode 100644 index e3e6569ec1c..00000000000 --- a/modules/kruxlinkBidAdapter.js +++ /dev/null @@ -1,90 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var adaptermanager = require('src/adaptermanager'); - -function _qs(key, value) { - return encodeURIComponent(key) + '=' + encodeURIComponent(value); -} - -function _makeBidResponse(placementCode, bid) { - var bidResponse = bidfactory.createBid(bid !== undefined ? 1 : 2); - bidResponse.bidderCode = 'kruxlink'; - if (bid !== undefined) { - bidResponse.cpm = bid.price; - bidResponse.ad = bid.adm; - bidResponse.width = bid.w; - bidResponse.height = bid.h; - } - bidmanager.addBidResponse(placementCode, bidResponse); -} - -function _makeCallback(id, placements) { - var callback = '_kruxlink_' + id; - $$PREBID_GLOBAL$$[callback] = function(response) { - // Clean up our callback - delete $$PREBID_GLOBAL$$[callback]; - - // Add in the bid respones - if (response.seatbid !== undefined) { - for (var i = 0; i < response.seatbid.length; i++) { - var seatbid = response.seatbid[i]; - if (seatbid.bid !== undefined) { - for (var j = 0; j < seatbid.bid.length; j++) { - var bid = seatbid.bid[j]; - if (bid.impid !== undefined) { - _makeBidResponse(placements[bid.impid], bid); - delete placements[bid.impid]; - } - } - } - } - } - - // Add any no-bids remaining - for (var impid in placements) { - if (placements.hasOwnProperty(impid)) { - _makeBidResponse(placements[impid]); - } - } - }; - - return '$$PREBID_GLOBAL$$.' + callback; -} - -function _callBids(params) { - var impids = []; - var placements = {}; - - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bidRequest = bids[i]; - var bidRequestParams = bidRequest.params || {}; - var impid = bidRequestParams.impid; - placements[impid] = bidRequest.placementCode; - - impids.push(impid); - } - - var callback = _makeCallback(params.bidderRequestId, placements); - var qs = [ - _qs('id', params.bidderRequestId), - _qs('u', window.location.href), - _qs('impid', impids.join(',')), - _qs('calltype', 'pbd'), - _qs('callback', callback) - ]; - var url = 'https://link.krxd.net/hb?' + qs.join('&'); - - adloader.loadScript(url); -} - -function KruxAdapter() { - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new KruxAdapter(), 'kruxlink'); - -module.exports = KruxAdapter; diff --git a/modules/lifestreetBidAdapter.js b/modules/lifestreetBidAdapter.js deleted file mode 100644 index aa65ed1fd71..00000000000 --- a/modules/lifestreetBidAdapter.js +++ /dev/null @@ -1,166 +0,0 @@ -const bidfactory = require('src/bidfactory.js'); -const bidmanager = require('src/bidmanager'); -const utils = require('src/utils.js'); -const adloader = require('src/adloader'); -const adaptermanager = require('src/adaptermanager'); - -const LifestreetAdapter = function LifestreetAdapter() { - const BIDDER_CODE = 'lifestreet'; - const ADAPTER_VERSION = 'prebidJS-1.0'; - const SLOTS_LOAD_MAP = {}; - const PREBID_REQUEST_MESSAGE = 'LSMPrebid Request'; - const PREBID_RESPONSE_MESSAGE = 'LSMPrebid Response'; - - function _callBids(params) { - utils._each(params.bids, bid => { - const jstagUrl = bid.params.jstag_url; - const slot = bid.params.slot; - const adkey = bid.params.adkey; - const adSize = bid.params.ad_size; - let timeout = 700; - if (bid.params.timeout) { - timeout = bid.params.timeout; - } - let shouldRequest = false; - if (jstagUrl && jstagUrl.length > 0 && slot && slot.length > 0 && - adkey && adkey.length > 0 && adSize && adSize.length > 0) { - let adSizeArray = adSize.split('x'); - for (let i = 0; i < adSizeArray.length; ++i) { - adSizeArray[i] = +adSizeArray[i]; - } - if (bid.sizes && (bid.sizes instanceof Array) && bid.sizes.length > 0 && adSizeArray.length > 1) { - bid.sizes = !(bid.sizes[0] instanceof Array) ? [ bid.sizes ] : bid.sizes; - for (let i = 0; i < bid.sizes.length; ++i) { - let size = bid.sizes[i]; - if (size.length > 1) { - if (size[0] === adSizeArray[0] && size[1] === adSizeArray[1]) { - shouldRequest = true; - break; - } - } - } - } else { - shouldRequest = true; - } - } - if (shouldRequest) { - _callJSTag(bid, jstagUrl, timeout); - } else { - _addSlotBidResponse(bid, 0, null, 0, 0); - } - }); - } - - function _callJSTag(bid, jstagUrl, timeout) { - adloader.loadScript(jstagUrl, () => { - /* global LSM_Slot */ - if (LSM_Slot && typeof LSM_Slot === 'function') { - let slotTagParams = { - _preload: 'wait', - _hb_request: ADAPTER_VERSION, - _timeout: timeout, - _onload: (slot, action, cpm, width, height) => { - if (slot.state() !== 'error') { - let slotName = slot.getSlotObjectName(); - $$PREBID_GLOBAL$$[slotName] = slot; - if (slotName && !SLOTS_LOAD_MAP[slotName]) { - SLOTS_LOAD_MAP[slotName] = true; - let ad = _constructLSMAd(jstagUrl, slotName); - _addSlotBidResponse(bid, cpm, ad, width, height); - } else { - slot.show(); - } - } else { - _addSlotBidResponse(bid, 0, null, 0, 0); - } - } - }; - for (let property in bid.params) { - if (property === 'jstag_url' || property === 'timeout') { - continue; - } - if (bid.params.hasOwnProperty(property)) { - slotTagParams[property] = bid.params[property]; - } - } - LSM_Slot(slotTagParams); - window.addEventListener('message', (ev) => { - let key = ev.message ? 'message' : 'data'; - let object = {}; - try { - object = JSON.parse(ev[key]); - } catch (e) { - return; - } - if (object.message && object.message === PREBID_REQUEST_MESSAGE && object.slotName && - window.$$PREBID_GLOBAL$$[object.slotName]) { - ev.source.postMessage(JSON.stringify({ - message: PREBID_RESPONSE_MESSAGE, - slotObject: window.$$PREBID_GLOBAL$$[object.slotName] - }), '*'); - window.$$PREBID_GLOBAL$$[object.slotName].destroy(); - window.$$PREBID_GLOBAL$$[object.slotName] = null; - } - }, false); - } else { - _addSlotBidResponse(bid, 0, null, 0, 0); - } - }); - } - - function _addSlotBidResponse(bid, cpm, ad, width, height) { - let hasResponse = cpm && ad && ad.length > 0; - let bidObject = bidfactory.createBid(hasResponse ? 1 : 2, bid); - bidObject.bidderCode = BIDDER_CODE; - if (hasResponse) { - bidObject.cpm = cpm; - bidObject.ad = ad; - bidObject.width = width; - bidObject.height = height; - } - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - - function _constructLSMAd(jsTagUrl, slotName) { - if (jsTagUrl && slotName) { - return `
- - `; - } - return null; - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new LifestreetAdapter(), 'lifestreet'); - -module.exports = LifestreetAdapter; diff --git a/modules/mantisBidAdapter.js b/modules/mantisBidAdapter.js deleted file mode 100644 index 4dfb62f395b..00000000000 --- a/modules/mantisBidAdapter.js +++ /dev/null @@ -1,228 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var constants = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -function MantisAdapter () { - function inIframe() { - try { - return window.self !== window.top && !window.mantis_link; - } catch (e) { - return true; - } - } - - function isDesktop(ignoreTouch) { - var scope = function (win) { - var width = win.innerWidth || win.document.documentElement.clientWidth || win.document.body.clientWidth; - var supportsTouch = !ignoreTouch && ('ontouchstart' in window || navigator.msMaxTouchPoints); - - return !supportsTouch && (!width || width >= (window.mantis_breakpoint || 768)); - }; - - if (inIframe()) { - try { - return scope(window.top); - } catch (ex) { - } - } - - return scope(window); - } - - function isSendable(val) { - if (val === null || val === undefined) { - return false; - } - - if (typeof val === 'string') { - return !(!val || /^\s*$/.test(val)); - } - - if (typeof val === 'number') { - return !isNaN(val); - } - - return true; - } - - function isObject(value) { - return Object.prototype.toString.call(value) === '[object Object]'; - } - - function isAmp() { - return typeof window.context === 'object' && (window.context.tagName === 'AMP-AD' || window.context.tagName === 'AMP-EMBED'); - } - - function isSecure() { - return document.location.protocol === 'https:'; - } - - function isArray(value) { - return Object.prototype.toString.call(value) === '[object Array]'; - } - - function jsonp(callback) { - if (!window.mantis_jsonp) { - window.mantis_jsonp = []; - } - - window.mantis_jsonp.push(callback); - - return 'mantis_jsonp[' + (window.mantis_jsonp.length - 1) + ']'; - } - - function jsonToQuery(data, chain, form) { - if (!data) { - return null; - } - - var parts = form || []; - - for (var key in data) { - var queryKey = key; - - if (chain) { - queryKey = chain + '[' + key + ']'; - } - - var val = data[key]; - - if (isArray(val)) { - for (var index = 0; index < val.length; index++) { - var akey = queryKey + '[' + index + ']'; - var aval = val[index]; - - if (isObject(aval)) { - jsonToQuery(aval, akey, parts); - } else if (isSendable(aval)) { - parts.push(akey + '=' + encodeURIComponent(aval)); - } - } - } else if (isObject(val)) { - jsonToQuery(val, queryKey, parts); - } else if (isSendable(val)) { - parts.push(queryKey + '=' + encodeURIComponent(val)); - } - } - - return parts.join('&'); - } - - function buildMantisUrl(path, data, domain) { - var params = { - referrer: document.referrer, - tz: new Date().getTimezoneOffset(), - buster: new Date().getTime(), - secure: isSecure() - }; - - if (!inIframe() || isAmp()) { - params.mobile = !isAmp() && isDesktop(true) ? 'false' : 'true'; - } - - if (window.mantis_uuid) { - params.uuid = window.mantis_uuid; - } else if (window.localStorage) { - var localUuid = window.localStorage.getItem('mantis:uuid'); - - if (localUuid) { - params.uuid = localUuid; - } - } - - if (!inIframe()) { - try { - params.title = window.top.document.title; - params.referrer = window.top.document.referrer; - params.url = window.top.document.location.href; - } catch (ex) { - - } - } else { - params.iframe = true; - } - - if (isAmp()) { - if (!params.url && window.context.canonicalUrl) { - params.url = window.context.canonicalUrl; - } - - if (!params.url && window.context.location) { - params.url = window.context.location.href; - } - - if (!params.referrer && window.context.referrer) { - params.referrer = window.context.referrer; - } - } - - Object.keys(data || {}).forEach(function (key) { - params[key] = data[key]; - }); - - var query = jsonToQuery(params); - - return (window.mantis_domain === undefined ? domain || 'https://mantodea.mantisadnetwork.com' : window.mantis_domain) + path + '?' + query; - } - - var Prebid = function (bidfactory, bidmanager, adloader, constants) { - return { - callBids: function (params) { - var property = null; - - params.bids.some(function (bid) { - if (bid.params.property) { - property = bid.params.property; - - return true; - } - }); - - var url = { - jsonp: jsonp(function (resp) { - params.bids.forEach(function (bid) { - var ad = resp.ads[bid.bidId]; - - var bidObject; - - if (ad) { - bidObject = bidfactory.createBid(constants.STATUS.GOOD); - bidObject.bidderCode = 'mantis'; - bidObject.cpm = ad.cpm; - bidObject.ad = ad.html; - bidObject.width = ad.width; - bidObject.height = ad.height; - } else { - bidObject = bidfactory.createBid(constants.STATUS.NO_BID); - bidObject.bidderCode = 'mantis'; - } - - bidmanager.addBidResponse(bid.placementCode, bidObject); - }); - }), - property: property, - bids: params.bids.map(function (bid) { - return { - bidId: bid.bidId, - config: bid.params, - sizes: bid.sizes.map(function (size) { - return {width: size[0], height: size[1]}; - }) - }; - }), - version: 1 - }; - - adloader.loadScript(buildMantisUrl('/website/prebid', url)); - } - }; - }; - - return new Prebid(bidfactory, bidmanager, adloader, constants); -} - -adaptermanager.registerBidAdapter(new MantisAdapter(), 'mantis'); - -module.exports = MantisAdapter; diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js deleted file mode 100644 index e6ad12dd345..00000000000 --- a/modules/marsmediaBidAdapter.js +++ /dev/null @@ -1,160 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import { ajax } from 'src/ajax'; -import { STATUS } from 'src/constants'; -import * as utils from 'src/utils'; -import adaptermanager from 'src/adaptermanager'; - -const MARS_BIDDER_CODE = 'marsmedia'; -const MARS_BIDDER_URL = '//bid306.rtbsrv.com:9306/bidder/?bid=3mhdom'; - -var MarsmediaBidAdapter = function MarsmediaBidAdapter() { - function _callBids(bidderRequest) { - var bids = bidderRequest.bids || []; - - bids.forEach(bid => { - try { - ajax( - MARS_BIDDER_URL, - { - success: handleBidResponse, - error: handleBidError - }, - buildCallParams(bid, bidderRequest), - {} - ); - } catch (err) { - utils.logError('Error sending marsmedia request for publisher id: ' + bid.params.publisherID, null, err); - handleBidError(); - } - - function handleBidResponse(res) { - try { - utils.logMessage('Register bid for publisher ID: ' + bid.params.publisherID); - addBid(res, bid); - } catch (err) { - utils.logError('Error processing response for publisher ID: ' + bid.params.publisherID, null, err); - handleBidError(); - } - } - - function addBid(res, bid) { - var obj; - try { - obj = JSON.parse(res); - } catch (err) { - throw 'Faild to parse bid response'; - } - - if (Object.keys(obj).length === 0 || Object.keys(bid).length === 0) { - throw 'Empty Bid'; - } - - var ad = obj.seatbid[0].bid[0]; - var bid_params = bidfactory.createBid(STATUS.GOOD, bid); - var sizes = bid.sizes[0]; - bid_params.un_id = obj.id; - bid_params.bidderCode = bid.bidder; - bid_params.cpm = Number(ad.price); - bid_params.price = Number(ad.price); - bid_params.width = sizes[0]; - bid_params.height = sizes[1]; - bid_params.ad = ad.adm; - bid_params.cid = ad.cid; - bid_params.seat = obj.seatbid[0].seat; - - bidmanager.addBidResponse(bid.placementCode, bid_params); - } - - function handleBidError() { - var bidObj = bidfactory.createBid(STATUS.NO_BID, bid); - bidObj.bidderCode = bid.bidder; - bidmanager.addBidResponse(bid.bidid, bidObj); - } - }); - } - - function buildCallParams(bidRequest) { - if (typeof bidRequest.params === 'undefined') { - throw 'No params'; - } - - if (typeof bidRequest.sizes === 'undefined' || bidRequest.sizes.length === 0) { - throw 'No sizes'; - } - - if (typeof bidRequest.params.floor === 'undefined') { - throw 'No floor'; - } else if (isNaN(Number(bidRequest.params.floor))) { - throw 'Floor must be numeric value'; - } - - var sizes = bidRequest.sizes[0]; - var floor = (typeof bidRequest.params.floor !== 'undefined' && bidRequest.params.floor === '') ? 0 : bidRequest.params.floor; - var protocol = (window.location.protocol === 'https') ? 1 : 0; - var publisher_id = (typeof bidRequest.params.publisherID !== 'undefined') ? bidRequest.params.publisherID : ''; - var params = {}; - params.id = utils.generateUUID(); - - params.cur = ['USD']; - - params.imp = [{ - id: params.id, - banner: { - w: sizes[0], - h: sizes[1], - secure: protocol - }, - bidfloor: floor - }]; - - params.device = { - ua: navigator.userAgent - }; - - params.user = { - id: publisher_id - }; - - params.app = { - id: params.id, - domain: document.domain, - publisher: { - id: publisher_id - } - }; - - params.site = { - 'id': publisher_id, - 'domain': window.location.hostname, - 'page': document.URL, - 'ref': document.referrer, - 'publisher': { - 'id': publisher_id, - 'domain': window.location.hostname - } - }; - - params.publisher = { - 'id': publisher_id, - 'domain': window.location.hostname - }; - - return JSON.stringify(params); - } - - return Object.assign(new Adapter(MARS_BIDDER_CODE), { - callBids: _callBids, - createNew: MarsmediaBidAdapter.createNew, - buildCallParams: buildCallParams - }); -}; - -MarsmediaBidAdapter.createNew = function() { - return new MarsmediaBidAdapter(); -}; - -adaptermanager.registerBidAdapter(new MarsmediaBidAdapter(), MARS_BIDDER_CODE); - -module.exports = MarsmediaBidAdapter; diff --git a/modules/memeglobalBidAdapter.js b/modules/memeglobalBidAdapter.js deleted file mode 100644 index c47c8ed7381..00000000000 --- a/modules/memeglobalBidAdapter.js +++ /dev/null @@ -1,124 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -var bidderName = 'memeglobal'; -/** - * Adapter for requesting bids from Meme Global Media Group - * OpenRTB compatible - */ -var MemeGlobalAdapter = function MemeGlobalAdapter() { - var bidder = 'stinger.memeglobal.com/api/v1/services/prebid'; - - function _callBids(params) { - var bids = params.bids; - - if (!bids) return; - - for (var i = 0; i < bids.length; i++) { - _requestBid(bids[i]); - } - } - - function _requestBid(bidReq) { - // build bid request object - var domain = window.location.host; - var page = window.location.host + window.location.pathname + location.search + location.hash; - - var tagId = utils.getBidIdParameter('tagid', bidReq.params); - var bidFloor = Number(utils.getBidIdParameter('bidfloor', bidReq.params)); - var adW = 0; - var adH = 0; - - var bidSizes = Array.isArray(bidReq.params.sizes) ? bidReq.params.sizes : bidReq.sizes; - var sizeArrayLength = bidSizes.length; - if (sizeArrayLength === 2 && typeof bidSizes[0] === 'number' && typeof bidSizes[1] === 'number') { - adW = bidSizes[0]; - adH = bidSizes[1]; - } else { - adW = bidSizes[0][0]; - adH = bidSizes[0][1]; - } - - // build bid request with impressions - var bidRequest = { - id: utils.getUniqueIdentifierStr(), - imp: [{ - id: bidReq.bidId, - banner: { - w: adW, - h: adH - }, - tagid: bidReq.placementCode, - bidfloor: bidFloor - }], - site: { - domain: domain, - page: page, - publisher: { - id: tagId - } - } - }; - - var scriptUrl = '//' + bidder + '?callback=window.$$PREBID_GLOBAL$$.mgres' + - '&src=' + CONSTANTS.REPO_AND_VERSION + - '&br=' + encodeURIComponent(JSON.stringify(bidRequest)); - adloader.loadScript(scriptUrl); - } - - function getBidSetForBidder() { - return $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === bidderName); - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.mgres = function (bidResp) { - // valid object? - if ((!bidResp || !bidResp.id) || - (!bidResp.seatbid || bidResp.seatbid.length === 0 || !bidResp.seatbid[0].bid || bidResp.seatbid[0].bid.length === 0)) { - return; - } - - bidResp.seatbid[0].bid.forEach(function (bidderBid) { - var responseCPM; - var placementCode = ''; - - var bidSet = getBidSetForBidder(); - var bidRequested = bidSet.bids.find(b => b.bidId === bidderBid.impid); - if (bidRequested) { - var bidResponse = bidfactory.createBid(1); - placementCode = bidRequested.placementCode; - bidRequested.status = CONSTANTS.STATUS.GOOD; - responseCPM = parseFloat(bidderBid.price); - if (responseCPM === 0) { - var bid = bidfactory.createBid(2); - bid.bidderCode = bidderName; - bidmanager.addBidResponse(placementCode, bid); - return; - } - bidResponse.placementCode = placementCode; - bidResponse.size = bidRequested.sizes; - var responseAd = bidderBid.adm; - var responseNurl = ''; - bidResponse.creative_id = bidderBid.id; - bidResponse.bidderCode = bidderName; - bidResponse.cpm = responseCPM; - bidResponse.ad = decodeURIComponent(responseAd + responseNurl); - bidResponse.width = parseInt(bidderBid.w); - bidResponse.height = parseInt(bidderBid.h); - bidmanager.addBidResponse(placementCode, bidResponse); - } - }); - }; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new MemeGlobalAdapter(), 'memeglobal'); - -module.exports = MemeGlobalAdapter; diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index 9781e36edb6..c4cce6646d3 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -55,7 +55,7 @@ function createSingleBidRequest(bid) { [NQ]: [createNqParam(bid), createCategoryParam(bid)], sizes: bid.sizes.map(value => value[0] + 'x' + value[1]), bidId: bid.bidId, - cors: location.origin + cors: utils.getOrigin() }; } diff --git a/modules/nginadBidAdapter.js b/modules/nginadBidAdapter.js deleted file mode 100644 index 32560120d64..00000000000 --- a/modules/nginadBidAdapter.js +++ /dev/null @@ -1,186 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -var defaultPlacementForBadBid = null; - -/** - * Adapter for requesting bids from NginAd - */ -var NginAdAdapter = function NginAdAdapter() { - var rtbServerDomain = 'placeholder.for.nginad.server.com'; - - function _callBids(params) { - var nginadBids = params.bids || []; - - // De-dupe by tagid then issue single bid request for all bids - _requestBids(_getUniqueTagids(nginadBids)); - } - - // filter bids to de-dupe them? - function _getUniqueTagids(bids) { - var key; - var map = {}; - var PubZoneIds = []; - - for (key in bids) { - map[utils.getBidIdParameter('pzoneid', bids[key].params)] = bids[key]; - } - - for (key in map) { - if (map.hasOwnProperty(key)) { - PubZoneIds.push(map[key]); - } - } - - return PubZoneIds; - } - - function getWidthAndHeight(bid) { - var adW = null; - var adH = null; - - var sizeArrayLength = bid.sizes.length; - if (sizeArrayLength === 2 && typeof bid.sizes[0] === 'number' && typeof bid.sizes[1] === 'number') { - adW = bid.sizes[0]; - adH = bid.sizes[1]; - } else { - adW = bid.sizes[0][0]; - adH = bid.sizes[0][1]; - } - - return [adW, adH]; - } - - function _requestBids(bidReqs) { - // build bid request object - var domain = window.location.host; - var page = window.location.pathname + location.search + location.hash; - - var nginadImps = []; - - // assign the first adUnit (placement) for bad bids; - defaultPlacementForBadBid = bidReqs[0].placementCode; - - // build impression array for nginad - utils._each(bidReqs, function(bid) { - var tagId = utils.getBidIdParameter('pzoneid', bid.params); - var bidFloor = utils.getBidIdParameter('bidfloor', bid.params); - - var whArr = getWidthAndHeight(bid); - - var imp = { - id: bid.bidId, - banner: { - w: whArr[0], - h: whArr[1] - }, - tagid: tagId, - bidfloor: bidFloor - }; - - nginadImps.push(imp); - // bidmanager.pbCallbackMap[imp.id] = bid; - - rtbServerDomain = bid.params.nginadDomain; - }); - - // build bid request with impressions - var nginadBidReq = { - id: utils.getUniqueIdentifierStr(), - imp: nginadImps, - site: { - domain: domain, - page: page - } - }; - - var scriptUrl = window.location.protocol + '//' + rtbServerDomain + '/bid/rtb?callback=window.$$PREBID_GLOBAL$$.nginadResponse' + - '&br=' + encodeURIComponent(JSON.stringify(nginadBidReq)); - - adloader.loadScript(scriptUrl); - } - - function handleErrorResponse(bidReqs, defaultPlacementForBadBid) { - // no response data - if (defaultPlacementForBadBid === null) { - // no id with which to create an dummy bid - return; - } - - var bid = bidfactory.createBid(2); - bid.bidderCode = 'nginad'; - bidmanager.addBidResponse(defaultPlacementForBadBid, bid); - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.nginadResponse = function(nginadResponseObj) { - var bid = {}; - var key; - - // valid object? - if (!nginadResponseObj || !nginadResponseObj.id) { - return handleErrorResponse(nginadResponseObj, defaultPlacementForBadBid); - } - - if (!nginadResponseObj.seatbid || nginadResponseObj.seatbid.length === 0 || !nginadResponseObj.seatbid[0].bid || nginadResponseObj.seatbid[0].bid.length === 0) { - return handleErrorResponse(nginadResponseObj, defaultPlacementForBadBid); - } - - for (key in nginadResponseObj.seatbid[0].bid) { - var nginadBid = nginadResponseObj.seatbid[0].bid[key]; - - var responseCPM; - var placementCode = ''; - var id = nginadBid.impid; - - // try to fetch the bid request we sent NginAd - var bidObj = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'nginad').bids - .find(bid => bid.bidId === id); - if (!bidObj) { - return handleErrorResponse(nginadBid, defaultPlacementForBadBid); - } - - placementCode = bidObj.placementCode; - bidObj.status = CONSTANTS.STATUS.GOOD; - - // place ad response on bidmanager._adResponsesByBidderId - responseCPM = parseFloat(nginadBid.price); - - if (responseCPM === 0) { - handleErrorResponse(nginadBid, id); - } - - nginadBid.placementCode = placementCode; - nginadBid.size = bidObj.sizes; - var responseAd = nginadBid.adm; - - // store bid response - // bid status is good (indicating 1) - bid = bidfactory.createBid(1); - bid.creative_id = nginadBid.Id; - bid.bidderCode = 'nginad'; - bid.cpm = responseCPM; - - // The bid is a mock bid, the true bidding process happens after the publisher tag is called - bid.ad = decodeURIComponent(responseAd); - - var whArr = getWidthAndHeight(bidObj); - bid.width = whArr[0]; - bid.height = whArr[1]; - - bidmanager.addBidResponse(placementCode, bid); - } - }; // nginadResponse - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new NginAdAdapter(), 'nginad'); - -module.exports = NginAdAdapter; diff --git a/modules/orbitsoftBidAdapter.js b/modules/orbitsoftBidAdapter.js deleted file mode 100644 index e01f82a7097..00000000000 --- a/modules/orbitsoftBidAdapter.js +++ /dev/null @@ -1,228 +0,0 @@ -import { getBidRequest } from 'src/utils'; - -let CONSTANTS = require('src/constants'); -let bidmanager = require('src/bidmanager'); -let bidfactory = require('src/bidfactory'); -let adloader = require('src/adloader'); -let utils = require('src/utils'); -let adaptermanager = require('src/adaptermanager'); -let Adapter = require('src/adapter').default; - -let ORBITSOFT_BIDDERCODE = 'orbitsoft'; -let styleParamsToFieldsMap = { - 'title.family': 'f1', // headerFont - 'title.size': 'fs1', // headerFontSize - 'title.weight': 'w1', // headerWeight - 'title.style': 's1', // headerStyle - 'title.color': 'c3', // headerColor - 'description.family': 'f2', // descriptionFont - 'description.size': 'fs2', // descriptionFontSize - 'description.weight': 'w2', // descriptionWeight - 'description.style': 's2', // descriptionStyle - 'description.color': 'c4', // descriptionColor - 'url.family': 'f3', // urlFont - 'url.size': 'fs3', // urlFontSize - 'url.weight': 'w3', // urlWeight - 'url.style': 's3', // urlStyle - 'url.color': 'c5', // urlColor - 'colors.background': 'c2', // borderColor - 'colors.border': 'c1', // borderColor - 'colors.link': 'c6', // lnkColor -}; - -let OrbitsoftAdapter = function OrbitsoftAdapter() { - let baseAdapter = new Adapter(ORBITSOFT_BIDDERCODE); - - baseAdapter.callBids = function(params) { - let bids = params.bids || []; - - for (let i = 0; i < bids.length; i++) { - let bidRequest = bids[i]; - let callbackId = bidRequest.bidId; - let jptCall = buildJPTCall(bidRequest, callbackId); - - if (jptCall) { - adloader.loadScript(jptCall); - } else { - // indicate that there is no bid for this placement - let bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidRequest); - bid.bidderCode = params.bidderCode; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } - } - } - - function buildJPTCall(bid, callbackId) { - // Determine tag params - let placementId = utils.getBidIdParameter('placementId', bid.params); - - let referrer = utils.getBidIdParameter('ref', bid.params); - let location = utils.getBidIdParameter('loc', bid.params); - let jptCall = utils.getBidIdParameter('requestUrl', bid.params); - if (jptCall.length === 0) { - // No param requestUrl - // @if NODE_ENV='debug' - utils.logMessage('No param requestUrl'); - // @endif - return null; - } else { - jptCall += '?'; - } - - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleOASCB'); - jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); - jptCall = utils.tryAppendQueryString(jptCall, 'scid', placementId); - - // Sizes takes a bit more logic - let sizeQueryString; - let parsedSizes = utils.parseSizesInput(bid.sizes); - - // Combine string into proper query string - let parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // First value should be "size" - sizeQueryString = 'size=' + parsedSizes[0]; - jptCall += sizeQueryString + '&'; - } - - // Append custom attributes: - let paramsCopy = Object.assign({}, bid.params); - - // Delete attributes already used - delete paramsCopy.placementId; - delete paramsCopy.referrer; - delete paramsCopy.style; - delete paramsCopy.customParams; - - // Get the reminder - jptCall += utils.parseQueryStringParameters(paramsCopy); - - // Append location & referrer - if (location === '') { - location = utils.getTopWindowUrl(); - } - if (referrer === '') { - referrer = window.top.document.referrer; - } - jptCall = utils.tryAppendQueryString(jptCall, 'loc', location); - jptCall = utils.tryAppendQueryString(jptCall, 'ref', referrer); - - // Remove the trailing "&" - jptCall = removeTrailingAmp(jptCall); - - // @if NODE_ENV='debug' - utils.logMessage('jpt request built: ' + jptCall); - // @endif - - // Append a timer here to track latency - bid.startTime = new Date().getTime(); - - return jptCall; - } - - // Remove the trailing "&" - function removeTrailingAmp(url) { - if (url.lastIndexOf('&') === url.length - 1) { - url = url.substring(0, url.length - 1); - } - return url; - } - - // Expose the callback to the global object - $$PREBID_GLOBAL$$.handleOASCB = function (jptResponseObj) { - let bidCode; - - if (jptResponseObj && jptResponseObj.callback_uid) { - let responseCPM; - let id = jptResponseObj.callback_uid; - let placementCode = ''; - let bidObj = getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; - - placementCode = bidObj.placementCode; - - // Set the status - bidObj.status = CONSTANTS.STATUS.GOOD; - } - - // @if NODE_ENV='debug' - utils.logMessage('JSONP callback function called for ad ID: ' + id); - // @endif - - let bid = []; - if (jptResponseObj.cpm && jptResponseObj.cpm !== 0) { - // Store bid response - responseCPM = jptResponseObj.cpm; - // Bid status is good (indicating 1) - bid = bidfactory.createBid(CONSTANTS.STATUS.GOOD, bidObj); - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - bid.adUrl = jptResponseObj.content_url; - bid.width = jptResponseObj.width; - bid.height = jptResponseObj.height; - - // Styles params - let styles = utils.getBidIdParameter('style', bidObj.params); - let stylesParams = {}; - for (let currentValue in styles) { - if (styles.hasOwnProperty(currentValue)) { - let currentStyle = styles[currentValue]; - for (let field in currentStyle) { - if (currentStyle.hasOwnProperty(field)) { - let styleField = styleParamsToFieldsMap[currentValue + '.' + field]; - if (styleField !== undefined) { - stylesParams[styleField] = currentStyle[field]; - } - } - } - } - } - bid.adUrl += '&' + utils.parseQueryStringParameters(stylesParams); - - // Custom params - let customParams = utils.getBidIdParameter('customParams', bidObj.params); - let customParamsArray = {}; - for (let customField in customParams) { - if (customParams.hasOwnProperty(customField)) { - customParamsArray['c.' + customField] = customParams[customField]; - } - } - let customParamsLink = utils.parseQueryStringParameters(customParamsArray); - if (customParamsLink) { - // Don't append a "&" here, we have already done it in parseQueryStringParameters - bid.adUrl += customParamsLink; - } - - // Remove the trailing "&" - bid.adUrl = removeTrailingAmp(bid.adUrl); - - bidmanager.addBidResponse(placementCode, bid); - } else { - // No response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response from Orbitsoft for placement code ' + placementCode); - // @endif - // indicate that there is no bid for this placement - bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } - } else { - // No response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response for placement'); - // @endif - } - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - buildJPTCall: buildJPTCall - }); -}; - -adaptermanager.registerBidAdapter(new OrbitsoftAdapter(), ORBITSOFT_BIDDERCODE); - -module.exports = OrbitsoftAdapter; diff --git a/modules/piximediaBidAdapter.js b/modules/piximediaBidAdapter.js deleted file mode 100644 index 48d2c9ee37b..00000000000 --- a/modules/piximediaBidAdapter.js +++ /dev/null @@ -1,155 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -var adloader = require('src/adloader.js'); -var Adapter = require('src/adapter.js').default; -var adaptermanager = require('src/adaptermanager'); - -var PiximediaAdapter = function PiximediaAdapter() { - var PREBID_URL = '//static.adserver.pm/prebid'; - var baseAdapter = new Adapter('piximedia'); - var bidStash = {}; - - var tryAppendPixiQueryString = function(url, name, value) { - return url + '/' + encodeURIComponent(name) + '=' + value; - }; - - baseAdapter.callBids = function callBidsPiximedia(params) { - utils._each(params.bids, function(bid) { - // valid bids must include a siteId and an placementId - if (bid.placementCode && bid.sizes && bid.params && bid.params.siteId && bid.params.placementId) { - var sizes = bid.params.hasOwnProperty('sizes') ? bid.params.sizes : bid.sizes; - sizes = utils.parseSizesInput(sizes); - - var cbid = utils.getUniqueIdentifierStr(); - - // we allow overriding the URL in the params - var url = bid.params.prebidUrl || PREBID_URL; - - // params are passed to the Piximedia endpoint, including custom params - for (var key in bid.params) { - /* istanbul ignore else */ - if (bid.params.hasOwnProperty(key)) { - var value = bid.params[key]; - switch (key) { - case 'siteId': - url = tryAppendPixiQueryString(url, 'site_id', encodeURIComponent(value)); - break; - - case 'placementId': - url = tryAppendPixiQueryString(url, 'placement_id', encodeURIComponent(value)); - break; - - case 'dealId': - url = tryAppendPixiQueryString(url, 'l_id', encodeURIComponent(value)); - break; - - case 'sizes': - case 'prebidUrl': - break; - - default: - if (typeof value === 'function') { - url = tryAppendPixiQueryString(url, key, encodeURIComponent((value(baseAdapter, params, bid) || '').toString())); - } else { - url = tryAppendPixiQueryString(url, key, encodeURIComponent((value || '').toString())); - } - break; - } - } - } - - url = tryAppendPixiQueryString(url, 'jsonp', '$$PREBID_GLOBAL$$.handlePiximediaCallback'); - url = tryAppendPixiQueryString(url, 'sizes', encodeURIComponent(sizes.join(','))); - url = tryAppendPixiQueryString(url, 'cbid', encodeURIComponent(cbid)); - url = tryAppendPixiQueryString(url, 'rand', String(Math.floor(Math.random() * 1000000000))); - - bidStash[cbid] = { - 'bidObj': bid, - 'url': url, - 'start': new Date().getTime() - }; - utils.logMessage('[Piximedia] Dispatching header Piximedia to URL ' + url); - adloader.loadScript(url); - } - }); - }; - - /* - * Piximedia's bidResponse should look like: - * - * { - * 'foundbypm': true, // a Boolean, indicating if an ad was found - * 'currency': 'EUR', // the currency, as a String - * 'cpm': 1.99, // the win price as a Number, in currency - * 'dealId': null, // or string value of winning deal ID - * 'width': 300, // width in pixels of winning ad - * 'height': 250, // height in pixels of winning ad - * 'html': 'tag_here' // HTML tag to load if we are picked - * } - * - */ - $$PREBID_GLOBAL$$.handlePiximediaCallback = function(bidResponse) { - if (bidResponse && bidResponse.hasOwnProperty('foundbypm')) { - var stash = bidStash[bidResponse.cbid]; // retrieve our stashed data, by using the cbid - var bid; - - if (stash) { - var bidObj = stash.bidObj; - var timelapsed = new Date().getTime(); - timelapsed = timelapsed - stash.start; - - if (bidResponse.foundbypm && bidResponse.width && bidResponse.height && bidResponse.html && bidResponse.cpm && bidResponse.currency) { - /* we have a valid ad to display */ - bid = bidfactory.createBid(CONSTANTS.STATUS.GOOD); - bid.bidderCode = bidObj.bidder; - bid.width = bidResponse.width; - bid.height = bidResponse.height; - bid.ad = bidResponse.html; - bid.cpm = bidResponse.cpm; - bid.currency = bidResponse.currency; - - if (bidResponse.dealId) { - bid.dealId = bidResponse.dealId; - } else { - bid.dealId = null; - } - - bidmanager.addBidResponse(bidObj.placementCode, bid); - - utils.logMessage('[Piximedia] Registered bidresponse from URL ' + stash.url + - ' (time: ' + String(timelapsed) + ')'); - utils.logMessage('[Piximedia] ======> BID placementCode: ' + bidObj.placementCode + - ' CPM: ' + String(bid.cpm) + ' ' + bid.currency + - ' Format: ' + String(bid.width) + 'x' + String(bid.height)); - } else { - /* we have no ads to display */ - bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); - bid.bidderCode = bidObj.bidder; - bidmanager.addBidResponse(bidObj.placementCode, bid); - - utils.logMessage('[Piximedia] Registered BLANK bidresponse from URL ' + stash.url + - ' (time: ' + String(timelapsed) + ')'); - utils.logMessage('[Piximedia] ======> NOBID placementCode: ' + bidObj.placementCode); - } - - // We should no longer need this stashed object, so drop reference: - bidStash[bidResponse.cbid] = null; - } else { - utils.logMessage("[Piximedia] Couldn't find stash for cbid=" + bidResponse.cbid); - } - } - }; - - // return an object with PiximediaAdapter methods - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - getBidderCode: baseAdapter.getBidderCode - }); -}; - -adaptermanager.registerBidAdapter(new PiximediaAdapter(), 'piximedia'); - -module.exports = PiximediaAdapter; diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 7dc3b9b6d6d..0540d325c79 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -1,6 +1,5 @@ import Adapter from 'src/adapter'; import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; import * as utils from 'src/utils'; import { ajax } from 'src/ajax'; import { STATUS, S2S } from 'src/constants'; @@ -8,12 +7,106 @@ import { cookieSet } from 'src/cookie.js'; import adaptermanager from 'src/adaptermanager'; import { config } from 'src/config'; import { VIDEO } from 'src/mediaTypes'; +import { isValid } from 'src/adapters/bidderFactory'; +import includes from 'core-js/library/fn/array/includes'; const getConfig = config.getConfig; const TYPE = S2S.SRC; -const cookieSetUrl = 'https://acdn.adnxs.com/cookieset/cs.js'; let _synced = false; +const DEFAULT_S2S_TTL = 60; +const DEFAULT_S2S_CURRENCY = 'USD'; +const DEFAULT_S2S_NETREVENUE = true; + +let _s2sConfig; +config.setDefaults({ + 's2sConfig': { + enabled: false, + timeout: 1000, + maxBids: 1, + adapter: 'prebidServer' + } +}); + +/** + * Set config for server to server header bidding + * @typedef {Object} options - required + * @property {boolean} enabled enables S2S bidding + * @property {string[]} bidders bidders to request S2S + * @property {string} endpoint endpoint to contact + * === optional params below === + * @property {number} [timeout] timeout for S2S bidders - should be lower than `pbjs.requestBids({timeout})` + * @property {boolean} [cacheMarkup] whether to cache the adm result + * @property {string} [adapter] adapter code to use for S2S + * @property {string} [syncEndpoint] endpoint URL for syncing cookies + * @property {string} [cookieSetUrl] url for cookie set library, if passed then cookieSet is enabled + */ +function setS2sConfig(options) { + let keys = Object.keys(options); + + if (['accountId', 'bidders', 'endpoint'].filter(key => { + if (!includes(keys, key)) { + utils.logError(key + ' missing in server to server config'); + return true; + } + return false; + }).length > 0) { + return; + } + + _s2sConfig = options; + if (options.syncEndpoint) { + queueSync(options.bidders); + } +} +getConfig('s2sConfig', ({s2sConfig}) => setS2sConfig(s2sConfig)); + +/** + * @param {Array} bidderCodes list of bidders to request user syncs for. + */ +function queueSync(bidderCodes) { + if (_synced) { + return; + } + _synced = true; + const payload = JSON.stringify({ + uuid: utils.generateUUID(), + bidders: bidderCodes + }); + ajax(_s2sConfig.syncEndpoint, (response) => { + try { + response = JSON.parse(response); + response.bidder_status.forEach(bidder => doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder)); + } catch (e) { + utils.logError(e); + } + }, + payload, { + contentType: 'text/plain', + withCredentials: true + }); +} + +/** + * Run a cookie sync for the given type, url, and bidder + * + * @param {string} type the type of sync, "image", "redirect", "iframe" + * @param {string} url the url to sync + * @param {string} bidder name of bidder doing sync for + */ +function doBidderSync(type, url, bidder) { + if (!url) { + utils.logError(`No sync url for bidder "${bidder}": ${url}`); + } else if (type === 'image' || type === 'redirect') { + utils.logMessage(`Invoking image pixel user sync for bidder: "${bidder}"`); + utils.triggerPixel(url); + } else if (type == 'iframe') { + utils.logMessage(`Invoking iframe user sync for bidder: "${bidder}"`); + utils.insertUserSyncIframe(url); + } else { + utils.logError(`User sync type "${type}" not supported for bidder: "${bidder}"`); + } +} /** * Try to convert a value to a type. @@ -73,18 +166,11 @@ const paramTypes = { }, }; -let _cookiesQueued = false; - /** * Bidder adapter for Prebid Server */ -function PrebidServer() { +export function PrebidServer() { let baseAdapter = new Adapter('prebidServer'); - let config; - - baseAdapter.setConfig = function(s2sconfig) { - config = s2sconfig; - }; function convertTypes(adUnits) { adUnits.forEach(adUnit => { @@ -92,11 +178,7 @@ function PrebidServer() { const types = paramTypes[bid.bidder] || []; Object.keys(types).forEach(key => { if (bid.params[key]) { - const converted = types[key](bid.params[key]); - if (converted !== bid.params[key]) { - utils.logMessage(`Mismatched type for Prebid Server : ${bid.bidder} : ${key}. Required Type:${types[key]}`); - } - bid.params[key] = converted; + bid.params[key] = types[key](bid.params[key]); // don't send invalid values if (isNaN(bid.params[key])) { @@ -104,33 +186,14 @@ function PrebidServer() { } } }); - // will collect any custom params and place them under bid.params.keywords attribute in the following manner for pbs to ingest properly - // "keywords":[{"key":"randomKey","value":["123456789"]},{"key":"single_test"},{"key":"myMultiVar","value":["myValue","124578"]}] - let kwArray = []; - Object.keys(bid.params).forEach(key => { - if (bid.bidder === 'appnexus' && (key !== 'member' && key !== 'invCode' && key !== 'placementId')) { - let kvObj = {}; - kvObj.key = key - if (bid.params[key] !== null) { - if (Array.isArray(bid.params[key])) { - kvObj.value = bid.params[key].map(val => tryConvertString(val)); - } else { - kvObj.value = [tryConvertString(bid.params[key])]; - } - } - kwArray.push(kvObj); - delete bid.params[key]; - } - }); - bid.params.keywords = kwArray; }); }); } /* Prebid executes this function when the page asks to send out bid requests */ - baseAdapter.callBids = function(bidRequest) { + baseAdapter.callBids = function(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { const isDebug = !!getConfig('debug'); - const adUnits = utils.deepClone(bidRequest.ad_units); + const adUnits = utils.deepClone(s2sBidRequest.ad_units); adUnits.forEach(adUnit => { let videoMediaType = utils.deepAccess(adUnit, 'mediaTypes.video'); if (videoMediaType) { @@ -140,14 +203,15 @@ function PrebidServer() { // default is assumed to be 'banner' so if there is a video type we assume video only until PBS can support multi format auction. adUnit.media_types = [VIDEO]; } - }) + }); convertTypes(adUnits); let requestJson = { - account_id: config.accountId, - tid: bidRequest.tid, - max_bids: config.maxBids, - timeout_millis: config.timeout, - secure: config.secure, + account_id: _s2sConfig.accountId, + tid: s2sBidRequest.tid, + max_bids: _s2sConfig.maxBids, + timeout_millis: _s2sConfig.timeout, + secure: _s2sConfig.secure, + cache_markup: _s2sConfig.cacheMarkup, url: utils.getTopWindowUrl(), prebid_version: '$prebid.version$', ad_units: adUnits.filter(hasSizes), @@ -157,10 +221,10 @@ function PrebidServer() { // in case config.bidders contains invalid bidders, we only process those we sent requests for. const requestedBidders = requestJson.ad_units.map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(utils.uniques)).reduce(utils.flatten).filter(utils.uniques); function processResponse(response) { - handleResponse(response, requestedBidders); + handleResponse(response, requestedBidders, bidRequests, addBidResponse, done); } const payload = JSON.stringify(requestJson); - ajax(config.endpoint, processResponse, payload, { + ajax(_s2sConfig.endpoint, processResponse, payload, { contentType: 'text/plain', withCredentials: true }); @@ -171,29 +235,8 @@ function PrebidServer() { return unit.sizes && unit.sizes.length; } - /** - * Run a cookie sync for the given type, url, and bidder - * - * @param {string} type the type of sync, "image", "redirect", "iframe" - * @param {string} url the url to sync - * @param {string} bidder name of bidder doing sync for - */ - function doBidderSync(type, url, bidder) { - if (!url) { - utils.logError(`No sync url for bidder "${bidder}": ${url}`); - } else if (type === 'image' || type === 'redirect') { - utils.logMessage(`Invoking image pixel user sync for bidder: "${bidder}"`); - utils.triggerPixel(url); - } else if (type == 'iframe') { - utils.logMessage(`Invoking iframe user sync for bidder: "${bidder}"`); - utils.insertUserSyncIframe(url); - } else { - utils.logError(`User sync type "${type}" not supported for bidder: "${bidder}"`); - } - } - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(response, requestedBidders) { + function handleResponse(response, requestedBidders, bidRequests, addBidResponse, done) { let result; try { result = JSON.parse(response); @@ -201,7 +244,7 @@ function PrebidServer() { if (result.status === 'OK' || result.status === 'no_cookie') { if (result.bidder_status) { result.bidder_status.forEach(bidder => { - if (bidder.no_cookie && !_cookiesQueued) { + if (bidder.no_cookie) { doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder); } }); @@ -217,7 +260,7 @@ function PrebidServer() { if (result.bids) { result.bids.forEach(bidObj => { - let bidRequest = utils.getBidRequest(bidObj.bid_id); + let bidRequest = utils.getBidRequest(bidObj.bid_id, bidRequests); let cpm = bidObj.price; let status; if (cpm !== 0) { @@ -231,6 +274,12 @@ function PrebidServer() { bidObject.creative_id = bidObj.creative_id; bidObject.bidderCode = bidObj.bidder; bidObject.cpm = cpm; + if (bidObj.cache_id) { + bidObject.cache_id = bidObj.cache_id; + } + if (bidObj.cache_url) { + bidObject.cache_url = bidObj.cache_url; + } // From ORTB see section 4.2.3: adm Optional means of conveying ad markup in case the bid wins; supersedes the win notice if markup is included in both. if (bidObj.media_type === VIDEO) { bidObject.mediaType = VIDEO; @@ -257,68 +306,36 @@ function PrebidServer() { if (bidObj.deal_id) { bidObject.dealId = bidObj.deal_id; } + bidObject.requestId = bidObj.bid_id; + bidObject.creativeId = bidObj.creative_id; + + // TODO: Remove when prebid-server returns ttl, currency and netRevenue + bidObject.ttl = (bidObj.ttl) ? bidObj.ttl : DEFAULT_S2S_TTL; + bidObject.currency = (bidObj.currency) ? bidObj.currency : DEFAULT_S2S_CURRENCY; + bidObject.netRevenue = (bidObj.netRevenue) ? bidObj.netRevenue : DEFAULT_S2S_NETREVENUE; - bidmanager.addBidResponse(bidObj.code, bidObject); + if (isValid(bidObj.code, bidObject, bidRequests)) { + addBidResponse(bidObj.code, bidObject); + } }); } - - const receivedBidIds = result.bids ? result.bids.map(bidObj => bidObj.bid_id) : []; - - // issue a no-bid response for every bid request that can not be matched with received bids - requestedBidders.forEach(bidder => { - utils - .getBidderRequestAllAdUnits(bidder) - .bids.filter(bidRequest => !receivedBidIds.includes(bidRequest.bidId)) - .forEach(bidRequest => { - let bidObject = bidfactory.createBid(STATUS.NO_BID, bidRequest); - bidObject.source = TYPE; - bidObject.adUnitCode = bidRequest.placementCode; - bidObject.bidderCode = bidRequest.bidder; - bidmanager.addBidResponse(bidObject.adUnitCode, bidObject); - }); - }); } - if (result.status === 'no_cookie' && config.cookieSet) { + if (result.status === 'no_cookie' && typeof _s2sConfig.cookieSetUrl === 'string') { // cookie sync - cookieSet(cookieSetUrl); + cookieSet(_s2sConfig.cookieSetUrl); } } catch (error) { utils.logError(error); } - if (!result || (result.status && result.status.includes('Error'))) { + if (!result || (result.status && includes(result.status, 'Error'))) { utils.logError('error parsing response: ', result.status); } + + done(); } - /** - * @param {} {bidders} list of bidders to request user syncs for. - */ - baseAdapter.queueSync = function({bidderCodes}) { - if (_synced) { - return; - } - _synced = true; - const payload = JSON.stringify({ - uuid: utils.generateUUID(), - bidders: bidderCodes - }); - ajax(config.syncEndpoint, (response) => { - try { - response = JSON.parse(response); - response.bidder_status.forEach(bidder => doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder)); - } catch (e) { - utils.logError(e); - } - }, - payload, { - contentType: 'text/plain', - withCredentials: true - }); - }; return Object.assign(this, { - queueSync: baseAdapter.queueSync, - setConfig: baseAdapter.setConfig, callBids: baseAdapter.callBids, setBidderCode: baseAdapter.setBidderCode, type: TYPE @@ -326,5 +343,3 @@ function PrebidServer() { } adaptermanager.registerBidAdapter(new PrebidServer(), 'prebidServer'); - -module.exports = PrebidServer; diff --git a/modules/pubgearsBidAdapter.js b/modules/pubgearsBidAdapter.js deleted file mode 100644 index fd6ccee453a..00000000000 --- a/modules/pubgearsBidAdapter.js +++ /dev/null @@ -1,150 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var consts = require('src/constants.json'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); -var d = document; -var SCRIPT = 'script'; -var PARAMS = 'params'; -var SIZES = 'sizes'; -var SIZE = 'size'; -var CPM = 'cpm'; -var AD = 'ad'; -var WIDTH = 'width'; -var HEIGHT = 'height'; -var PUB_ZONE = 'pub_zone'; -var GROSS_PRICE = 'gross_price'; -var RESOURCE = 'resource'; -var DETAIL = 'detail'; -var BIDDER_CODE_RESPONSE_KEY = 'bidderCode'; -var BIDDER_CODE = 'pubgears'; -var SCRIPT_ID = 'pg-header-tag'; -var ATTRIBUTE_PREFIX = 'data-bsm-'; -var SLOT_LIST_ATTRIBUTE = 'slot-list'; -var PUBLISHER_ATTRIBUTE = 'pub'; -var FLAG_ATTRIBUTE = 'flag'; -var PLACEMENT_CODE = 'placementCode'; -var BID_ID = 'bidId'; -var PUBLISHER_PARAM = 'publisherName'; -var PUB_ZONE_PARAM = 'pubZone'; -var BID_RECEIVED_EVENT_NAME = 'onBidResponse'; -var SLOT_READY_EVENT_NAME = 'onResourceComplete'; -var CREATIVE_TEMPLATE = decodeURIComponent("%3Cscript%3E%0A(function(define)%7B%0Adefine(function(a)%7B%0A%09var%20id%3D%20%22pg-ad-%22%20%2B%20Math.floor(Math.random()%20*%201e10)%2C%20d%3D%20document%0A%09d.write(\'%3Cdiv%20id%3D%22\'%2Bid%2B\'%22%3E%3C%2Fdiv%3E\')%0A%09a.push(%7B%0A%09%09pub%3A%20\'%25%25PUBLISHER_NAME%25%25\'%2C%0A%09%09pub_zone%3A%20\'%25%25PUB_ZONE%25%25\'%2C%0A%09%09sizes%3A%20%5B\'%25%25SIZE%25%25\'%5D%2C%0A%09%09flag%3A%20true%2C%0A%09%09container%3A%20d.getElementById(id)%2C%0A%09%7D)%3B%0A%7D)%7D)(function(f)%7Bvar%20key%3D\'uber_imps\'%2Ca%3Dthis%5Bkey%5D%3Dthis%5Bkey%5D%7C%7C%5B%5D%3Bf(a)%3B%7D)%3B%0A%3C%2Fscript%3E%0A%3Cscript%20src%3D%22%2F%2Fc.pubgears.com%2Ftags%2Fb%22%3E%3C%2Fscript%3E%0A"); -var TAG_URL = '//c.pubgears.com/tags/h'; -var publisher = ''; - -adaptermanager.registerBidAdapter(new PubGearsAdapter(), BIDDER_CODE); - -module.exports = PubGearsAdapter; - -function PubGearsAdapter() { - var proxy = null; - var pendingSlots = {}; - var initialized = false; - - this.callBids = callBids; - - function callBids(params) { - var bids = params[consts.JSON_MAPPING.PL_BIDS]; - var slots = bids.map(getSlotFromBidParam); - if (slots.length <= 0) { return; } - publisher = bids[0][PARAMS][PUBLISHER_PARAM]; - - bids.forEach(function(bid) { - var name = getSlotFromBidParam(bid); - pendingSlots[ name ] = bid; - }); - - proxy = proxy || getScript(SCRIPT_ID) || makeScript(slots, publisher, SCRIPT_ID, TAG_URL); - if (!initialized) { registerEventListeners(proxy); } - initialized = true; - } - function loadScript(script) { - var anchor = (function(scripts) { - return scripts[ scripts.length - 1 ]; - })(d.getElementsByTagName(SCRIPT)); - - return anchor.parentNode.insertBefore(script, anchor); - } - function getSlotFromBidParam(bid) { - var size = getSize(bid); - var params = bid[PARAMS]; - var slotName = params[PUB_ZONE_PARAM]; - return [ slotName, size ].join('@'); - } - function getSlotFromResource(resource) { - var size = resource[SIZE]; - var key = [ resource[PUB_ZONE], size ].join('@'); - return key; - } - function getSize(bid) { - var sizes = bid[SIZES]; - var size = Array.isArray(sizes[0]) ? sizes[0] : sizes; - return size.join('x'); - } - function makeScript(slots, publisher, id, url) { - var script = d.createElement(SCRIPT); - script.src = url; - script.id = id; - script.setAttribute(ATTRIBUTE_PREFIX + SLOT_LIST_ATTRIBUTE, slots.join(' ')); - script.setAttribute(ATTRIBUTE_PREFIX + FLAG_ATTRIBUTE, 'true'); - script.setAttribute(ATTRIBUTE_PREFIX + PUBLISHER_ATTRIBUTE, publisher); - - return loadScript(script); - } - function getScript(id) { - return d.getElementById(id); - } - function registerEventListeners(script) { - script.addEventListener(BID_RECEIVED_EVENT_NAME, onBid, true); - script.addEventListener(SLOT_READY_EVENT_NAME, onComplete, true); - } - function onBid(event) { - var data = event[DETAIL]; - var slotKey = getSlotFromResource(data[RESOURCE]); - var bidRequest = pendingSlots[slotKey]; - var adUnitCode = bidRequest[PLACEMENT_CODE]; - var bid = null; - - if (bidRequest) { - bid = buildResponse(data, bidRequest); - bidmanager.addBidResponse(adUnitCode, bid); - utils.logMessage('adding bid respoonse to "' + adUnitCode + '" for bid request "' + bidRequest[BID_ID] + '"'); - } else { - utils.logError('Cannot get placement id for slot "' + slotKey + '"'); - } - } - function buildResponse(eventData, bidRequest) { - var resource = eventData[RESOURCE]; - var dims = resource[SIZE].split('x'); - var price = Number(eventData[GROSS_PRICE]); - var status = isNaN(price) || price <= 0 ? 2 : 1; - - var response = bidfactory.createBid(status, bidRequest); - response[BIDDER_CODE_RESPONSE_KEY] = BIDDER_CODE; - - if (status !== 1) { return response; } - - response[AD] = getCreative(resource); - - response[CPM] = price / 1e3; - response[WIDTH] = dims[0]; - response[HEIGHT] = dims[1]; - return response; - } - function getCreative(resource) { - var token = '%%'; - var creative = CREATIVE_TEMPLATE; - var replacementValues = { - publisher_name: publisher, - pub_zone: resource[PUB_ZONE], - size: resource[SIZE] - }; - return utils.replaceTokenInString(creative, replacementValues, token); - } - function onComplete(event) { - var data = event[DETAIL]; - var slotKey = getSlotFromResource(data[RESOURCE]); - delete pendingSlots[slotKey]; - } -} diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js deleted file mode 100644 index 8176052f9e2..00000000000 --- a/modules/pubmaticBidAdapter.js +++ /dev/null @@ -1,233 +0,0 @@ -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adaptermanager = require('src/adaptermanager'); -const constants = require('src/constants.json'); - -/** - * Adapter for requesting bids from Pubmatic. - * - * @returns {{callBids: _callBids}} - * @constructor - */ -const PubmaticAdapter = function PubmaticAdapter() { - let bids; - let usersync = false; - let _secure = 0; - let _protocol = (window.location.protocol === 'https:' ? (_secure = 1, 'https') : 'http') + '://'; - let iframe; - - let dealChannelValues = { - 1: 'PMP', - 5: 'PREF', - 6: 'PMPG' - }; - - let customPars = { - 'kadgender': 'gender', - 'age': 'kadage', - 'dctr': 'dctr', // Custom Targeting - 'wiid': 'wiid', // Wrapper Impression ID - 'profId': 'profId', // Legacy: Profile ID - 'verId': 'verId', // Legacy: version ID - 'pmzoneid': { // Zone ID - n: 'pmZoneId', - m: function(zoneId) { - if (utils.isStr(zoneId)) { - return zoneId.split(',').slice(0, 50).join(); - } else { - return undefined; - } - } - } - }; - - function _initConf() { - var conf = {}; - var currTime = new Date(); - - conf.SAVersion = '1100'; - conf.wp = 'PreBid'; - conf.js = 1; - conf.wv = constants.REPO_AND_VERSION; - _secure && (conf.sec = 1); - conf.screenResolution = screen.width + 'x' + screen.height; - conf.ranreq = Math.random(); - conf.inIframe = window != top ? '1' : '0'; - - // istanbul ignore else - if (window.navigator.cookieEnabled === false) { - conf.fpcd = '1'; - } - - try { - conf.pageURL = window.top.location.href; - conf.refurl = window.top.document.referrer; - } catch (e) { - conf.pageURL = window.location.href; - conf.refurl = window.document.referrer; - } - - conf.kltstamp = currTime.getFullYear() + - '-' + (currTime.getMonth() + 1) + - '-' + currTime.getDate() + - ' ' + currTime.getHours() + - ':' + currTime.getMinutes() + - ':' + currTime.getSeconds(); - conf.timezone = currTime.getTimezoneOffset() / 60 * -1; - - return conf; - } - - function _handleCustomParams(params, conf) { - // istanbul ignore else - if (!conf.kadpageurl) { - conf.kadpageurl = conf.pageURL; - } - - var key, value, entry; - for (key in customPars) { - // istanbul ignore else - if (customPars.hasOwnProperty(key)) { - value = params[key]; - // istanbul ignore else - if (value) { - entry = customPars[key]; - - if (typeof entry === 'object') { - value = entry.m(value, conf); - key = entry.n; - } else { - key = customPars[key]; - } - - if (utils.isStr(value)) { - conf[key] = value; - } else { - utils.logWarn('PubMatic: Ignoring param key: ' + customPars[key] + ', expects string-value, found ' + typeof value); - } - } - } - } - return conf; - } - - function _cleanSlot(slotName) { - // istanbul ignore else - if (utils.isStr(slotName)) { - return slotName.replace(/^\s+/g, '').replace(/\s+$/g, ''); - } - return ''; - } - - function _legacyExecution(conf, slots) { - var url = _generateLegacyCall(conf, slots); - iframe = utils.createInvisibleIframe(); - var elToAppend = document.getElementsByTagName('head')[0]; - elToAppend.insertBefore(iframe, elToAppend.firstChild); - var iframeDoc = utils.getIframeDocument(iframe); - var content = utils.createContentToExecuteExtScriptInFriendlyFrame(url); - content = content.replace(``, ``); - iframeDoc.write(content); - iframeDoc.close(); - } - - function _generateLegacyCall(conf, slots) { - var request_url = 'gads.pubmatic.com/AdServer/AdCallAggregator'; - return _protocol + request_url + '?' + utils.parseQueryStringParameters(conf) + 'adslots=' + encodeURIComponent('[' + slots.join(',') + ']'); - } - - function _initUserSync(pubId) { - // istanbul ignore else - if (!usersync) { - var iframe = utils.createInvisibleIframe(); - iframe.src = _protocol + 'ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p=' + pubId; - utils.insertElement(iframe, document); - usersync = true; - } - } - - function _callBids(params) { - var conf = _initConf(); - var slots = []; - - conf.pubId = 0; - bids = params.bids || []; - - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - conf.pubId = conf.pubId || bid.params.publisherId; - conf = _handleCustomParams(bid.params, conf); - bid.params.adSlot = _cleanSlot(bid.params.adSlot); - bid.params.adSlot.length && slots.push(bid.params.adSlot); - } - - // istanbul ignore else - if (conf.pubId && slots.length > 0) { - _legacyExecution(conf, slots); - } - - _initUserSync(conf.pubId); - } - - $$PREBID_GLOBAL$$.handlePubmaticCallback = function(bidDetailsMap, progKeyValueMap) { - var i; - var adUnit; - var adUnitInfo; - var bid; - var bidResponseMap = bidDetailsMap; - var bidInfoMap = progKeyValueMap; - - if (!bidResponseMap || !bidInfoMap) { - return; - } - - for (i = 0; i < bids.length; i++) { - var adResponse; - bid = bids[i].params; - adUnit = bidResponseMap[bid.adSlot] || {}; - // adUnitInfo example: bidstatus=0;bid=0.0000;bidid=39620189@320x50;wdeal= - // if using DFP GPT, the params string comes in the format: - // "bidstatus;1;bid;5.0000;bidid;hb_test@468x60;wdeal;" - // the code below detects and handles this. - // istanbul ignore else - if (bidInfoMap[bid.adSlot] && bidInfoMap[bid.adSlot].indexOf('=') === -1) { - bidInfoMap[bid.adSlot] = bidInfoMap[bid.adSlot].replace(/([a-z]+);(.[^;]*)/ig, '$1=$2'); - } - - adUnitInfo = (bidInfoMap[bid.adSlot] || '').split(';').reduce(function(result, pair) { - var parts = pair.split('='); - result[parts[0]] = parts[1]; - return result; - }, {}); - - if (adUnitInfo.bidstatus === '1') { - adResponse = bidfactory.createBid(1); - adResponse.bidderCode = 'pubmatic'; - adResponse.adSlot = bid.adSlot; - adResponse.cpm = Number(adUnitInfo.bid); - adResponse.ad = unescape(adUnit.creative_tag); - adResponse.ad += utils.createTrackPixelIframeHtml(decodeURIComponent(adUnit.tracking_url)); - adResponse.width = adUnit.width; - adResponse.height = adUnit.height; - adResponse.dealId = adUnitInfo.wdeal; - adResponse.dealChannel = dealChannelValues[adUnit.deal_channel] || null; - - bidmanager.addBidResponse(bids[i].placementCode, adResponse); - } else { - // Indicate an ad was not returned - adResponse = bidfactory.createBid(2); - adResponse.bidderCode = 'pubmatic'; - bidmanager.addBidResponse(bids[i].placementCode, adResponse); - } - } - }; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new PubmaticAdapter(), 'pubmatic'); - -module.exports = PubmaticAdapter; diff --git a/modules/pubwiseAnalyticsAdapter.js b/modules/pubwiseAnalyticsAdapter.js index 96ccb26f513..69227cd154a 100644 --- a/modules/pubwiseAnalyticsAdapter.js +++ b/modules/pubwiseAnalyticsAdapter.js @@ -23,7 +23,8 @@ const utils = require('src/utils'); const analyticsType = 'endpoint'; const analyticsName = 'PubWise Analytics: '; let defaultUrl = 'https://api.pubwise.io/api/v4/event/default/'; -let pubwiseVersion = '2.2'; +let pubwiseVersion = '3.0'; +let pubwiseSchema = 'AVOCET'; let configOptions = {site: '', endpoint: 'https://api.pubwise.io/api/v4/event/default/', debug: ''}; let pwAnalyticsEnabled = false; let utmKeys = {utm_source: '', utm_medium: '', utm_campaign: '', utm_term: '', utm_content: ''}; @@ -49,8 +50,7 @@ function enrichWithUTM(dataBag) { let newUtm = false; try { for (let prop in utmKeys) { - let urlValue = utils.getParameterByName(prop); - utmKeys[prop] = urlValue; + utmKeys[prop] = utils.getParameterByName(prop); if (utmKeys[prop] != '') { newUtm = true; dataBag[prop] = utmKeys[prop]; @@ -84,6 +84,7 @@ function sendEvent(eventType, data) { eventType: eventType, args: data, target_site: configOptions.site, + pubwiseSchema: pubwiseSchema, debug: configOptions.debug ? 1 : 0, }; diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 82c8df9a9c1..2c1f6f9174d 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -1,85 +1,332 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); - -var PulsePointAdapter = function PulsePointAdapter() { - var getJsStaticUrl = window.location.protocol + '//tag-st.contextweb.com/getjs.static.js'; - var bidUrl = window.location.protocol + '//bid.contextweb.com/header/tag'; - - function _callBids(params) { - if (typeof window.pp === 'undefined') { - adloader.loadScript(getJsStaticUrl, function () { bid(params); }, true); - } else { - bid(params); - } - } +/* eslint dot-notation:0, quote-props:0 */ +import {logError, getTopWindowLocation} from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const NATIVE_DEFAULTS = { + TITLE_LEN: 100, + DESCR_LEN: 200, + SPONSORED_BY_LEN: 50, + IMG_MIN: 150, + ICON_MIN: 50, +}; + +const DEFAULT_BID_TTL = 20; +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_NET_REVENUE = true; + +/** + * PulsePoint Bid Adapter. + * Contact: ExchangeTeam@pulsepoint.com + * + * Aliases - pulseLite and pulsepointLite are supported for backwards compatibility. + * Formats - Display/Native/Outstream formats supported. + * + */ +export const spec = { - function bid(params) { - var bids = params.bids; - for (var i = 0; i < bids.length; i++) { - var bidRequest = bids[i]; - requestBid(bidRequest); + code: 'pulsepoint', + + aliases: ['pulseLite', 'pulsepointLite'], + + supportedMediaTypes: ['native'], + + isBidRequestValid: bid => ( + !!(bid && bid.params && bid.params.cp && bid.params.ct) + ), + + buildRequests: bidRequests => { + const request = { + id: bidRequests[0].bidderRequestId, + imp: bidRequests.map(slot => impression(slot)), + site: site(bidRequests), + app: app(bidRequests), + device: device(), + }; + return { + method: 'POST', + url: '//bid.contextweb.com/header/ortb', + data: JSON.stringify(request), + }; + }, + + interpretResponse: (response, request) => ( + bidResponseAvailable(request, response) + ), + + getUserSyncs: syncOptions => { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//bh.contextweb.com/visitormatch' + }]; + } else if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: '//bh.contextweb.com/visitormatch/prebid' + }]; } } - function requestBid(bidRequest) { - try { - var ppBidRequest = new window.pp.Ad(bidRequestOptions(bidRequest)); - ppBidRequest.display(); - } catch (e) { - // register passback on any exceptions while attempting to fetch response. - utils.logError('pulsepoint.requestBid', 'ERROR', e); - bidResponseAvailable(bidRequest); +}; + +/** + * Callback for bids, after the call to PulsePoint completes. + */ +function bidResponseAvailable(bidRequest, bidResponse) { + const idToImpMap = {}; + const idToBidMap = {}; + bidResponse = bidResponse.body + // extract the request bids and the response bids, keyed by impr-id + const ortbRequest = parse(bidRequest.data); + ortbRequest.imp.forEach(imp => { + idToImpMap[imp.id] = imp; + }); + if (bidResponse) { + bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { + idToBidMap[bid.impid] = bid; + })); + } + const bids = []; + Object.keys(idToImpMap).forEach(id => { + if (idToBidMap[id]) { + const bid = { + requestId: id, + cpm: idToBidMap[id].price, + creative_id: id, + creativeId: id, + adId: id, + ttl: DEFAULT_BID_TTL, + netRevenue: DEFAULT_NET_REVENUE, + currency: DEFAULT_CURRENCY + }; + if (idToImpMap[id]['native']) { + bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); + bid.mediaType = 'native'; + } else { + bid.ad = idToBidMap[id].adm; + bid.width = idToImpMap[id].banner.w; + bid.height = idToImpMap[id].banner.h; + } + applyExt(bid, idToBidMap[id]) + bids.push(bid); } + }); + return bids; +} + +function applyExt(bid, ortbBid) { + if (ortbBid && ortbBid.ext) { + bid.ttl = ortbBid.ext.ttl || bid.ttl; + bid.currency = ortbBid.ext.currency || bid.currency; + bid.netRevenue = ortbBid.ext.netRevenue != null ? ortbBid.ext.netRevenue : bid.netRevenue; } +} + +/** + * Produces an OpenRTBImpression from a slot config. + */ +function impression(slot) { + return { + id: slot.bidId, + banner: banner(slot), + 'native': nativeImpression(slot), + tagid: slot.params.ct.toString(), + }; +} + +/** + * Produces an OpenRTB Banner object for the slot given. + */ +function banner(slot) { + const size = adSize(slot); + return slot.nativeParams ? null : { + w: size[0], + h: size[1], + }; +} - function bidRequestOptions(bidRequest) { - var callback = bidResponseCallback(bidRequest); - var options = { - cn: 1, - ca: window.pp.requestActions.BID, - cu: bidUrl, - adUnitId: bidRequest.placementCode, - callback: callback +/** + * Produces an OpenRTB Native object for the slot given. + */ +function nativeImpression(slot) { + if (slot.nativeParams) { + const assets = []; + addAsset(assets, titleAsset(assets.length + 1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); + addAsset(assets, dataAsset(assets.length + 1, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); + addAsset(assets, dataAsset(assets.length + 1, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); + addAsset(assets, imageAsset(assets.length + 1, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); + addAsset(assets, imageAsset(assets.length + 1, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); + return { + request: JSON.stringify({ assets }), + ver: '1.1', }; - for (var param in bidRequest.params) { - if (bidRequest.params.hasOwnProperty(param)) { - options[param] = bidRequest.params[param]; - } - } - return options; } + return null; +} - function bidResponseCallback(bid) { - return function (bidResponse) { - bidResponseAvailable(bid, bidResponse); +/** + * Helper method to add an asset to the assets list. + */ +function addAsset(assets, asset) { + if (asset) { + assets.push(asset); + } +} + +/** + * Produces a Native Title asset for the configuration given. + */ +function titleAsset(id, params, defaultLen) { + if (params) { + return { + id, + required: params.required ? 1 : 0, + title: { + len: params.len || defaultLen, + }, }; } + return null; +} + +/** + * Produces a Native Image asset for the configuration given. + */ +function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { + return params ? { + id, + required: params.required ? 1 : 0, + img: { + type, + wmin: params.wmin || defaultMinWidth, + hmin: params.hmin || defaultMinHeight, + } + } : null; +} + +/** + * Produces a Native Data asset for the configuration given. + */ +function dataAsset(id, params, type, defaultLen) { + return params ? { + id, + required: params.required ? 1 : 0, + data: { + type, + len: params.len || defaultLen, + } + } : null; +} + +/** + * Produces an OpenRTB site object. + */ +function site(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; + const appParams = bidderRequest[0].params.app; + if (!appParams) { + return { + publisher: { + id: pubId.toString(), + }, + ref: referrer(), + page: getTopWindowLocation().href, + } + } + return null; +} - function bidResponseAvailable(bidRequest, bidResponse) { - if (bidResponse) { - var adSize = bidRequest.params.cf.toUpperCase().split('X'); - var bid = bidfactory.createBid(1, bidRequest); - bid.bidderCode = bidRequest.bidder; - bid.cpm = bidResponse.bidCpm; - bid.ad = bidResponse.html; - bid.width = adSize[0]; - bid.height = adSize[1]; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } else { - var passback = bidfactory.createBid(2, bidRequest); - passback.bidderCode = bidRequest.bidder; - bidmanager.addBidResponse(bidRequest.placementCode, passback); +/** + * Produces an OpenRTB App object. + */ +function app(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; + const appParams = bidderRequest[0].params.app; + if (appParams) { + return { + publisher: { + id: pubId.toString(), + }, + bundle: appParams.bundle, + storeurl: appParams.storeUrl, + domain: appParams.domain, } } + return null; +} +/** + * Attempts to capture the referrer url. + */ +function referrer() { + try { + return window.top.document.referrer; + } catch (e) { + return document.referrer; + } +} + +/** + * Produces an OpenRTB Device object. + */ +function device() { return { - callBids: _callBids + ua: navigator.userAgent, + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), }; -}; +} + +/** + * Safely parses the input given. Returns null on + * parsing failure. + */ +function parse(rawResponse) { + try { + if (rawResponse) { + return JSON.parse(rawResponse); + } + } catch (ex) { + logError('pulsepointLite.safeParse', 'ERROR', ex); + } + return null; +} -adaptermanager.registerBidAdapter(new PulsePointAdapter(), 'pulsepoint'); +/** + * Determines the AdSize for the slot. + */ +function adSize(slot) { + if (slot.params.cf) { + const size = slot.params.cf.toUpperCase().split('X'); + const width = parseInt(slot.params.cw || size[0], 10); + const height = parseInt(slot.params.ch || size[1], 10); + return [width, height]; + } + return [1, 1]; +} + +/** + * Parses the native response from the Bid given. + */ +function nativeResponse(imp, bid) { + if (imp['native']) { + const nativeAd = parse(bid.adm); + const keys = {}; + if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { + nativeAd['native'].assets.forEach(asset => { + keys.title = asset.title ? asset.title.text : keys.title; + keys.body = asset.data && asset.data.type === 2 ? asset.data.value : keys.body; + keys.sponsoredBy = asset.data && asset.data.type === 1 ? asset.data.value : keys.sponsoredBy; + keys.image = asset.img && asset.img.type === 3 ? asset.img.url : keys.image; + keys.icon = asset.img && asset.img.type === 1 ? asset.img.url : keys.icon; + }); + if (nativeAd['native'].link) { + keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); + } + keys.impressionTrackers = nativeAd['native'].imptrackers; + return keys; + } + } + return null; +} -module.exports = PulsePointAdapter; +registerBidder(spec); diff --git a/modules/pulsepointLiteBidAdapter.md b/modules/pulsepointBidAdapter.md similarity index 77% rename from modules/pulsepointLiteBidAdapter.md rename to modules/pulsepointBidAdapter.md index 23c96758ca0..1b119f0499f 100644 --- a/modules/pulsepointLiteBidAdapter.md +++ b/modules/pulsepointBidAdapter.md @@ -1,6 +1,6 @@ # Overview -**Module Name**: PulsePoint Lite Bidder Adapter +**Module Name**: PulsePoint Bidder Adapter **Module Type**: Bidder Adapter **Maintainer**: ExchangeTeam@pulsepoint.com @@ -8,7 +8,8 @@ Connects to PulsePoint demand source to fetch bids. Banner, Outstream and Native formats are supported. -Please use ```pulseLite``` as the bidder code. +Please use ```pulsepoint``` as the bidder code. +```pulseLite``` and ```pulsepointLite``` aliases also supported as well. # Test Parameters ``` @@ -16,7 +17,7 @@ Please use ```pulseLite``` as the bidder code. code: 'banner-ad-div', sizes: [[300, 250]], bids: [{ - bidder: 'pulsepointLite', + bidder: 'pulsepoint', params: { cf: '300X250', cp: 512379, @@ -33,7 +34,7 @@ Please use ```pulseLite``` as the bidder code. sponsoredBy: { len: 20 } }, bids: [{ - bidder: 'pulseLite', + bidder: 'pulsepoint', params: { cp: 512379, ct: 505642 diff --git a/modules/pulsepointLiteBidAdapter.js b/modules/pulsepointLiteBidAdapter.js deleted file mode 100644 index d851245402c..00000000000 --- a/modules/pulsepointLiteBidAdapter.js +++ /dev/null @@ -1,330 +0,0 @@ -/* eslint dot-notation:0, quote-props:0 */ -import {logError, getTopWindowLocation} from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; - -const NATIVE_DEFAULTS = { - TITLE_LEN: 100, - DESCR_LEN: 200, - SPONSORED_BY_LEN: 50, - IMG_MIN: 150, - ICON_MIN: 50, -}; - -const DEFAULT_BID_TTL = 20; -const DEFAULT_CURRENCY = 'USD'; -const DEFAULT_NET_REVENUE = true; - -/** - * PulsePoint "Lite" Adapter. This adapter implementation is lighter than the - * alternative/original PulsePointAdapter because it has no external - * dependencies and relies on a single OpenRTB request to the PulsePoint - * bidder instead of separate requests per slot. - */ -export const spec = { - - code: 'pulseLite', - - aliases: ['pulsepointLite'], - - supportedMediaTypes: ['native'], - - isBidRequestValid: bid => ( - !!(bid && bid.params && bid.params.cp && bid.params.ct) - ), - - buildRequests: bidRequests => { - const request = { - id: bidRequests[0].bidderRequestId, - imp: bidRequests.map(slot => impression(slot)), - site: site(bidRequests), - app: app(bidRequests), - device: device(), - }; - return { - method: 'POST', - url: '//bid.contextweb.com/header/ortb', - data: JSON.stringify(request), - }; - }, - - interpretResponse: (response, request) => ( - bidResponseAvailable(request, response) - ), - - getUserSyncs: syncOptions => { - if (syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: '//bh.contextweb.com/visitormatch' - }]; - } else if (syncOptions.pixelEnabled) { - return [{ - type: 'image', - url: '//bh.contextweb.com/visitormatch/prebid' - }]; - } - } - -}; - -/** - * Callback for bids, after the call to PulsePoint completes. - */ -function bidResponseAvailable(bidRequest, bidResponse) { - const idToImpMap = {}; - const idToBidMap = {}; - bidResponse = bidResponse.body - // extract the request bids and the response bids, keyed by impr-id - const ortbRequest = parse(bidRequest.data); - ortbRequest.imp.forEach(imp => { - idToImpMap[imp.id] = imp; - }); - if (bidResponse) { - bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { - idToBidMap[bid.impid] = bid; - })); - } - const bids = []; - Object.keys(idToImpMap).forEach(id => { - if (idToBidMap[id]) { - const bid = { - requestId: id, - cpm: idToBidMap[id].price, - creative_id: id, - creativeId: id, - adId: id, - ttl: DEFAULT_BID_TTL, - netRevenue: DEFAULT_NET_REVENUE, - currency: DEFAULT_CURRENCY - }; - if (idToImpMap[id]['native']) { - bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); - bid.mediaType = 'native'; - } else { - bid.ad = idToBidMap[id].adm; - bid.width = idToImpMap[id].banner.w; - bid.height = idToImpMap[id].banner.h; - } - applyExt(bid, idToBidMap[id]) - bids.push(bid); - } - }); - return bids; -} - -function applyExt(bid, ortbBid) { - if (ortbBid && ortbBid.ext) { - bid.ttl = ortbBid.ext.ttl || bid.ttl; - bid.currency = ortbBid.ext.currency || bid.currency; - bid.netRevenue = ortbBid.ext.netRevenue != null ? ortbBid.ext.netRevenue : bid.netRevenue; - } -} - -/** - * Produces an OpenRTBImpression from a slot config. - */ -function impression(slot) { - return { - id: slot.bidId, - banner: banner(slot), - 'native': nativeImpression(slot), - tagid: slot.params.ct.toString(), - }; -} - -/** - * Produces an OpenRTB Banner object for the slot given. - */ -function banner(slot) { - const size = adSize(slot); - return slot.nativeParams ? null : { - w: size[0], - h: size[1], - }; -} - -/** - * Produces an OpenRTB Native object for the slot given. - */ -function nativeImpression(slot) { - if (slot.nativeParams) { - const assets = []; - addAsset(assets, titleAsset(assets.length + 1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); - addAsset(assets, dataAsset(assets.length + 1, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); - addAsset(assets, dataAsset(assets.length + 1, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); - addAsset(assets, imageAsset(assets.length + 1, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); - addAsset(assets, imageAsset(assets.length + 1, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); - return { - request: JSON.stringify({ assets }), - ver: '1.1', - }; - } - return null; -} - -/** - * Helper method to add an asset to the assets list. - */ -function addAsset(assets, asset) { - if (asset) { - assets.push(asset); - } -} - -/** - * Produces a Native Title asset for the configuration given. - */ -function titleAsset(id, params, defaultLen) { - if (params) { - return { - id, - required: params.required ? 1 : 0, - title: { - len: params.len || defaultLen, - }, - }; - } - return null; -} - -/** - * Produces a Native Image asset for the configuration given. - */ -function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { - return params ? { - id, - required: params.required ? 1 : 0, - img: { - type, - wmin: params.wmin || defaultMinWidth, - hmin: params.hmin || defaultMinHeight, - } - } : null; -} - -/** - * Produces a Native Data asset for the configuration given. - */ -function dataAsset(id, params, type, defaultLen) { - return params ? { - id, - required: params.required ? 1 : 0, - data: { - type, - len: params.len || defaultLen, - } - } : null; -} - -/** - * Produces an OpenRTB site object. - */ -function site(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; - const appParams = bidderRequest[0].params.app; - if (!appParams) { - return { - publisher: { - id: pubId.toString(), - }, - ref: referrer(), - page: getTopWindowLocation().href, - } - } - return null; -} - -/** - * Produces an OpenRTB App object. - */ -function app(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; - const appParams = bidderRequest[0].params.app; - if (appParams) { - return { - publisher: { - id: pubId.toString(), - }, - bundle: appParams.bundle, - storeurl: appParams.storeUrl, - domain: appParams.domain, - } - } - return null; -} - -/** - * Attempts to capture the referrer url. - */ -function referrer() { - try { - return window.top.document.referrer; - } catch (e) { - return document.referrer; - } -} - -/** - * Produces an OpenRTB Device object. - */ -function device() { - return { - ua: navigator.userAgent, - language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), - }; -} - -/** - * Safely parses the input given. Returns null on - * parsing failure. - */ -function parse(rawResponse) { - try { - if (rawResponse) { - return JSON.parse(rawResponse); - } - } catch (ex) { - logError('pulsepointLite.safeParse', 'ERROR', ex); - } - return null; -} - -/** - * Determines the AdSize for the slot. - */ -function adSize(slot) { - if (slot.params.cf) { - const size = slot.params.cf.toUpperCase().split('X'); - const width = parseInt(slot.params.cw || size[0], 10); - const height = parseInt(slot.params.ch || size[1], 10); - return [width, height]; - } - return [1, 1]; -} - -/** - * Parses the native response from the Bid given. - */ -function nativeResponse(imp, bid) { - if (imp['native']) { - const nativeAd = parse(bid.adm); - const keys = {}; - if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { - nativeAd['native'].assets.forEach(asset => { - keys.title = asset.title ? asset.title.text : keys.title; - keys.body = asset.data && asset.data.type === 2 ? asset.data.value : keys.body; - keys.sponsoredBy = asset.data && asset.data.type === 1 ? asset.data.value : keys.sponsoredBy; - keys.image = asset.img && asset.img.type === 3 ? asset.img.url : keys.image; - keys.icon = asset.img && asset.img.type === 1 ? asset.img.url : keys.icon; - }); - if (nativeAd['native'].link) { - keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); - } - keys.impressionTrackers = nativeAd['native'].imptrackers; - return keys; - } - } - return null; -} - -registerBidder(spec); diff --git a/modules/realvuBidAdapter.js b/modules/realvuBidAdapter.js deleted file mode 100644 index dfed3d64370..00000000000 --- a/modules/realvuBidAdapter.js +++ /dev/null @@ -1,238 +0,0 @@ -import { getBidRequest } from 'src/utils'; -import adaptermanager from 'src/adaptermanager'; - -const CONSTANTS = require('src/constants'); -const utils = require('src/utils.js'); -const adloader = require('src/adloader.js'); -const bidmanager = require('src/bidmanager.js'); -const bidfactory = require('src/bidfactory.js'); -const Adapter = require('src/adapter.js').default; - -var RealVuAdapter = function RealVuAdapter() { - var baseAdapter = new Adapter('realvu'); - baseAdapter.callBids = function (params) { - var pbids = params.bids; - var boost_back = function() { - var top1 = window; - try { - var wnd = window; - while ((top1 != top) && (typeof (wnd.document) != 'undefined')) { - top1 = wnd; - wnd = wnd.parent; - } - } catch (e) { }; - for (var i = 0; i < pbids.length; i++) { - var bid_rq = pbids[i]; - var sizes = utils.parseSizesInput(bid_rq.sizes); - top1.realvu_boost.addUnitById({ - partner_id: bid_rq.params.partnerId, - unit_id: bid_rq.placementCode, - callback: baseAdapter.boostCall, - pbjs_bid: bid_rq, - size: sizes[0], - mode: 'kvp' - }); - } - }; - adloader.loadScript('//ac.realvu.net/realvu_boost.js', boost_back, 1); - }; - - baseAdapter.boostCall = function(rez) { - var bid_request = rez.pin.pbjs_bid; - var callbackId = bid_request.bidId; - if (rez.realvu === 'yes') { - var adap = new RvAppNexusAdapter(); - adloader.loadScript(adap.buildJPTCall(bid_request, callbackId)); - } else { // not in view - respond with no bid. - var adResponse = bidfactory.createBid(2); - adResponse.bidderCode = 'realvu'; - bidmanager.addBidResponse(bid_request.placementCode, adResponse); - } - }; - - // +copy/pasted appnexusBidAdapter, "handleAnCB" replaced with "handleRvAnCB" - var RvAppNexusAdapter = function RvAppNexusAdapter() { - var usersync = false; - - this.buildJPTCall = function (bid, callbackId) { - // determine tag params - var placementId = utils.getBidIdParameter('placementId', bid.params); - - // memberId will be deprecated, use member instead - var memberId = utils.getBidIdParameter('memberId', bid.params); - var member = utils.getBidIdParameter('member', bid.params); - var inventoryCode = utils.getBidIdParameter('invCode', bid.params); - var query = utils.getBidIdParameter('query', bid.params); - var referrer = utils.getBidIdParameter('referrer', bid.params); - var altReferrer = utils.getBidIdParameter('alt_referrer', bid.params); - var jptCall = '//ib.adnxs.com/jpt?'; - - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleRvAnCB'); - jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); - jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); - jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); - if (member) { - jptCall = utils.tryAppendQueryString(jptCall, 'member', member); - } else if (memberId) { - jptCall = utils.tryAppendQueryString(jptCall, 'member', memberId); - utils.logMessage('appnexus.callBids: "memberId" will be deprecated soon. Please use "member" instead'); - } - - jptCall = utils.tryAppendQueryString(jptCall, 'code', inventoryCode); - jptCall = utils.tryAppendQueryString(jptCall, 'traffic_source_code', (utils.getBidIdParameter('trafficSourceCode', bid.params))); - - // sizes takes a bit more logic - var sizeQueryString = ''; - var parsedSizes = utils.parseSizesInput(bid.sizes); - - // combine string into proper querystring for impbus - var parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // first value should be "size" - sizeQueryString = 'size=' + parsedSizes[0]; - if (parsedSizesLength > 1) { - // any subsequent values should be "promo_sizes" - sizeQueryString += '&promo_sizes='; - for (var j = 1; j < parsedSizesLength; j++) { - sizeQueryString += parsedSizes[j] += ','; - } - - // remove trailing comma - if (sizeQueryString && sizeQueryString.charAt(sizeQueryString.length - 1) === ',') { - sizeQueryString = sizeQueryString.slice(0, sizeQueryString.length - 1); - } - } - } - - if (sizeQueryString) { - jptCall += sizeQueryString + '&'; - } - - // this will be deprecated soon - var targetingParams = utils.parseQueryStringParameters(query); - - if (targetingParams) { - // don't append a & here, we have already done it in parseQueryStringParameters - jptCall += targetingParams; - } - - // append custom attributes: - var paramsCopy = Object.assign({}, bid.params); - - // delete attributes already used - delete paramsCopy.placementId; - delete paramsCopy.memberId; - delete paramsCopy.invCode; - delete paramsCopy.query; - delete paramsCopy.referrer; - delete paramsCopy.alt_referrer; - delete paramsCopy.member; - - // get the reminder - var queryParams = utils.parseQueryStringParameters(paramsCopy); - - // append - if (queryParams) { - jptCall += queryParams; - } - - // append referrer - if (referrer === '') { - referrer = utils.getTopWindowUrl(); - } - - jptCall = utils.tryAppendQueryString(jptCall, 'referrer', referrer); - jptCall = utils.tryAppendQueryString(jptCall, 'alt_referrer', altReferrer); - - // remove the trailing "&" - if (jptCall.lastIndexOf('&') === jptCall.length - 1) { - jptCall = jptCall.substring(0, jptCall.length - 1); - } - - // @if NODE_ENV='debug' - utils.logMessage('jpt request built: ' + jptCall); - // @endif - - // append a timer here to track latency - bid.startTime = new Date().getTime(); - - return jptCall; - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleRvAnCB = function (jptResponseObj) { - var bidCode; - - if (jptResponseObj && jptResponseObj.callback_uid) { - var responseCPM; - var id = jptResponseObj.callback_uid; - var placementCode = ''; - var bidObj = getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; - - placementCode = bidObj.placementCode; - - // set the status - bidObj.status = CONSTANTS.STATUS.GOOD; - } - - // @if NODE_ENV='debug' - utils.logMessage('JSONP callback function called for ad ID: ' + id); - - // @endif - var bid = []; - if (jptResponseObj.result && jptResponseObj.result.cpm && jptResponseObj.result.cpm !== 0) { - responseCPM = parseInt(jptResponseObj.result.cpm, 10); - - // CPM response from /jpt is dollar/cent multiplied by 10000 - // in order to avoid using floats - // switch CPM to "dollar/cent" - responseCPM = responseCPM / 10000; - - // store bid response - // bid status is good (indicating 1) - var adId = jptResponseObj.result.creative_id; - bid = bidfactory.createBid(1, bidObj); - bid.creative_id = adId; - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - bid.adUrl = jptResponseObj.result.ad; - bid.width = jptResponseObj.result.width; - bid.height = jptResponseObj.result.height; - bid.dealId = jptResponseObj.result.deal_id; - - bidmanager.addBidResponse(placementCode, bid); - } else { - // no bid - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } - - if (!usersync) { - var iframe = utils.createInvisibleIframe(); - iframe.src = '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html'; - try { - document.body.appendChild(iframe); - } catch (error) { - utils.logError(error); - } - usersync = true; - } - } else { - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - } - }; - }; - // -copy/pasted appnexusBidAdapter - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - boostCall: baseAdapter.boostCall - }); -}; - -adaptermanager.registerBidAdapter(new RealVuAdapter(), 'realvu'); - -module.exports = RealVuAdapter; diff --git a/modules/roxotAnalyticsAdapter.js b/modules/roxotAnalyticsAdapter.js index 0a274660699..65771ad245d 100644 --- a/modules/roxotAnalyticsAdapter.js +++ b/modules/roxotAnalyticsAdapter.js @@ -1,6 +1,7 @@ import adapter from 'src/AnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import adaptermanager from 'src/adaptermanager'; +import includes from 'core-js/library/fn/array/includes'; const utils = require('src/utils'); @@ -106,7 +107,7 @@ function checkAdUnitConfig() { function buildBidWon(eventType, args) { bidWon.options = initOptions; if (checkAdUnitConfig()) { - if (initOptions.adUnits.includes(args.adUnitCode)) { + if (includes(initOptions.adUnits, args.adUnitCode)) { bidWon.events = [{ args: args, eventType: eventType }]; } } else { @@ -121,7 +122,7 @@ function buildEventStack() { function filterBidsByAdUnit(bids) { var filteredBids = []; bids.forEach(function (bid) { - if (initOptions.adUnits.includes(bid.placementCode)) { + if (includes(initOptions.adUnits, bid.placementCode)) { filteredBids.push(bid); } }); @@ -131,7 +132,7 @@ function filterBidsByAdUnit(bids) { function isValidEvent(eventType, adUnitCode) { if (checkAdUnitConfig()) { let validationEvents = [bidAdjustmentConst, bidResponseConst, bidWonConst]; - if (!initOptions.adUnits.includes(adUnitCode) && validationEvents.includes(eventType)) { + if (!includes(initOptions.adUnits, adUnitCode) && includes(validationEvents, eventType)) { return false; } } diff --git a/modules/roxotBidAdapter.js b/modules/roxotBidAdapter.js deleted file mode 100644 index a2b9b6ca6dc..00000000000 --- a/modules/roxotBidAdapter.js +++ /dev/null @@ -1,116 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -var RoxotAdapter = function RoxotAdapter() { - var roxotUrl = 'r.rxthdr.com'; - - $$PREBID_GLOBAL$$.roxotResponseHandler = roxotResponseHandler; - - return { - callBids: _callBids - }; - - function _callBids(bidReqs) { - utils.logInfo('callBids roxot adapter invoking'); - - var domain = window.location.host; - var page = window.location.pathname + location.search + location.hash; - - var roxotBidReqs = { - id: utils.getUniqueIdentifierStr(), - bids: bidReqs, - site: { - domain: domain, - page: page - } - }; - - var scriptUrl = '//' + roxotUrl + '?callback=$$PREBID_GLOBAL$$.roxotResponseHandler' + - '&src=' + CONSTANTS.REPO_AND_VERSION + - '&br=' + encodeURIComponent(JSON.stringify(roxotBidReqs)); - - adloader.loadScript(scriptUrl); - } - - function roxotResponseHandler(roxotResponseObject) { - utils.logInfo('roxotResponseHandler invoking'); - var placements = []; - - if (isResponseInvalid()) { - return fillPlacementEmptyBid(); - } - - roxotResponseObject.bids.forEach(pushRoxotBid); - var allBidResponse = fillPlacementEmptyBid(placements); - utils.logInfo('roxotResponse handler finish'); - - return allBidResponse; - - function isResponseInvalid() { - return !roxotResponseObject || !roxotResponseObject.bids || !Array.isArray(roxotResponseObject.bids) || roxotResponseObject.bids.length <= 0; - } - - function pushRoxotBid(roxotBid) { - var placementCode = ''; - - var bidReq = $$PREBID_GLOBAL$$ - ._bidsRequested.find(bidSet => bidSet.bidderCode === 'roxot') - .bids.find(bid => bid.bidId === roxotBid.bidId); - - if (!bidReq) { - return pushErrorBid(placementCode); - } - - bidReq.status = CONSTANTS.STATUS.GOOD; - - placementCode = bidReq.placementCode; - placements.push(placementCode); - - var cpm = roxotBid.cpm; - var responseNurl = ''; - - if (!cpm) { - return pushErrorBid(placementCode); - } - - var bid = bidfactory.createBid(1, bidReq); - - bid.creative_id = roxotBid.id; - bid.bidderCode = 'roxot'; - bid.cpm = cpm; - bid.ad = decodeURIComponent(roxotBid.adm + responseNurl); - bid.width = parseInt(roxotBid.w); - bid.height = parseInt(roxotBid.h); - - bidmanager.addBidResponse(placementCode, bid); - } - - function fillPlacementEmptyBid(places) { - $$PREBID_GLOBAL$$ - ._bidsRequested.find(bidSet => bidSet.bidderCode === 'roxot') - .bids.forEach(fillIfNotFilled); - - function fillIfNotFilled(bid) { - if (utils.contains(places, bid.placementCode)) { - return null; - } - - pushErrorBid(bid); - } - } - - function pushErrorBid(bidRequest) { - var bid = bidfactory.createBid(2, bidRequest); - bid.bidderCode = 'roxot'; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } - } -}; - -adaptermanager.registerBidAdapter(new RoxotAdapter(), 'roxot'); - -module.exports = RoxotAdapter; diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 5c7a3dbd05c..48fe18677e0 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -118,6 +118,7 @@ export const spec = { resolution: _getScreenResolution(), account_id: params.accountId, integration: INTEGRATION, + 'x_source.tid': bidRequest.transactionId, timeout: bidderRequest.timeout - (Date.now() - bidderRequest.auctionStart + TIMEOUT_BUFFER), stash_creatives: true, ae_pass_through_parameters: params.video.aeParams, @@ -192,7 +193,7 @@ export const spec = { 'rp_floor', floor, 'rp_secure', isSecure() ? '1' : '0', 'tk_flint', INTEGRATION, - 'tid', bidRequest.transactionId, + 'x_source.tid', bidRequest.transactionId, 'p_screen_res', _getScreenResolution(), 'kw', keywords, 'tk_user_key', userId diff --git a/modules/rubiconBidAdapter.md b/modules/rubiconBidAdapter.md new file mode 100644 index 00000000000..b1871882a9a --- /dev/null +++ b/modules/rubiconBidAdapter.md @@ -0,0 +1,48 @@ +# Overview + +``` +Module Name: Rubicon Project Bid Adapter +Module Type: Bidder Adapter +Maintainer: header-bidding@rubiconproject.com +``` + +# Description + +Connect to Rubicon Project's exchange for bids. + +The Rubicon Project adapter requires setup and approval from the +Rubicon Project team. Please reach out to your account team or +globalsupport@rubiconproject.com for more information. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "rubicon", + params: { + accountId: 1001, + siteId: 113932, + zoneId: 535510 + } + } + ] + },{ + code: 'test-div', + sizes: [[300, 50]], + bids: [ + { + bidder: "rubicon", + params: { + accountId: 1001, + siteId: 113932, + zoneId: 535510 + } + } + ] + } + ]; +``` diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js deleted file mode 100644 index d815f69c752..00000000000 --- a/modules/smartadserverBidAdapter.js +++ /dev/null @@ -1,60 +0,0 @@ -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var url = require('src/url.js'); -var adaptermanager = require('src/adaptermanager'); - -var SmartAdServer = function SmartAdServer() { - var generateCallback = function(bid) { - var callbackId = 'sas_' + utils.getUniqueIdentifierStr(); - $$PREBID_GLOBAL$$[callbackId] = function(adUnit) { - var bidObject; - if (adUnit) { - utils.logMessage(`[SmartAdServer] bid response for placementCode ${bid.placementCode}`); - bidObject = bidfactory.createBid(1); - bidObject.bidderCode = 'smartadserver'; - bidObject.cpm = adUnit.cpm; - bidObject.currency = adUnit.currency; - bidObject.ad = adUnit.ad; - bidObject.width = adUnit.width; - bidObject.height = adUnit.height; - bidObject.dealId = adUnit.dealId; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } else { - utils.logMessage(`[SmartAdServer] no bid response for placementCode ${bid.placementCode}`); - bidObject = bidfactory.createBid(2); - bidObject.bidderCode = 'smartadserver'; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - }; - return callbackId; - }; - - return { - callBids: function(params) { - for (var i = 0; i < params.bids.length; i++) { - var bid = params.bids[i]; - var adCall = url.parse(bid.params.domain); - adCall.pathname = '/prebid'; - adCall.search = { - 'pbjscbk': '$$PREBID_GLOBAL$$.' + generateCallback(bid), - 'siteid': bid.params.siteId, - 'pgid': bid.params.pageId, - 'fmtid': bid.params.formatId, - 'ccy': bid.params.currency || 'USD', - 'bidfloor': bid.params.bidfloor || 0.0, - 'tgt': encodeURIComponent(bid.params.target || ''), - 'tag': bid.placementCode, - 'sizes': bid.sizes.map(size => size[0] + 'x' + size[1]).join(','), - 'async': 1 - }; - adloader.loadScript(url.format(adCall)); - } - } - }; -}; - -adaptermanager.registerBidAdapter(new SmartAdServer(), 'smartadserver'); - -module.exports = SmartAdServer; diff --git a/modules/smartyadsBidAdapter.js b/modules/smartyadsBidAdapter.js deleted file mode 100644 index 89f93f393c7..00000000000 --- a/modules/smartyadsBidAdapter.js +++ /dev/null @@ -1,180 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -const SMARTYADS_BIDDER_CODE = 'smartyads'; - -var sizeMap = { - 1: '468x60', - 2: '728x90', - 8: '120x600', - 9: '160x600', - 10: '300x600', - 15: '300x250', - 16: '336x280', - 19: '300x100', - 43: '320x50', - 44: '300x50', - 48: '300x300', - 54: '300x1050', - 55: '970x90', - 57: '970x250', - 58: '1000x90', - 59: '320x80', - 61: '1000x1000', - 65: '640x480', - 67: '320x480', - 68: '1800x1000', - 72: '320x320', - 73: '320x160', - 83: '480x300', - 94: '970x310', - 96: '970x210', - 101: '480x320', - 102: '768x1024', - 113: '1000x300', - 117: '320x100', - 125: '800x250', - 126: '200x600' -}; - -utils._each(sizeMap, (item, key) => sizeMap[item] = key); - -function SmartyadsAdapter() { - function _callBids(bidderRequest) { - var bids = bidderRequest.bids || []; - - bids.forEach((bid) => { - try { - ajax(buildOptimizedCall(bid), bidCallback, undefined, { withCredentials: true }); - } catch (err) { - utils.logError('Error sending smartyads request for placement code ' + bid.placementCode, null, err); - } - - function bidCallback(responseText) { - try { - utils.logMessage('XHR callback function called for ad ID: ' + bid.bidId); - handleRpCB(responseText, bid); - } catch (err) { - if (typeof err === 'string') { - utils.logWarn(`${err} when processing smartyads response for placement code ${bid.placementCode}`); - } else { - utils.logError('Error processing smartyads response for placement code ' + bid.placementCode, null, err); - } - - // indicate that there is no bid for this placement - let badBid = bidfactory.createBid(STATUS.NO_BID, bid); - badBid.bidderCode = bid.bidder; - badBid.error = err; - bidmanager.addBidResponse(bid.placementCode, badBid); - } - } - }); - } - - function buildOptimizedCall(bid) { - bid.startTime = new Date().getTime(); - - // use smartyads sizes if provided, otherwise adUnit.sizes - var parsedSizes = SmartyadsAdapter.masSizeOrdering( - Array.isArray(bid.params.sizes) ? bid.params.sizes.map(size => (sizeMap[size] || '').split('x')) : bid.sizes - ); - - if (parsedSizes.length < 1) { - throw 'no valid sizes'; - } - - var secure; - if (window.location.protocol !== 'http:') { - secure = 1; - } else { - secure = 0; - } - - const host = window.location.host; - const page = window.location.pathname; - const language = navigator.language; - const deviceWidth = window.screen.width; - const deviceHeight = window.screen.height; - - var queryString = [ - 'banner_id', bid.params.banner_id, - 'size_ad', parsedSizes[0], - 'alt_size_ad', parsedSizes.slice(1).join(',') || undefined, - 'host', host, - 'page', page, - 'language', language, - 'deviceWidth', deviceWidth, - 'deviceHeight', deviceHeight, - 'secure', secure, - 'bidId', bid.bidId, - 'checkOn', 'rf' - ]; - - return queryString.reduce( - (memo, curr, index) => - index % 2 === 0 && queryString[index + 1] !== undefined - ? memo + curr + '=' + encodeURIComponent(queryString[index + 1]) + '&' - : memo, - '//ssp-nj.webtradehub.com/?' - ).slice(0, -1); - } - - function handleRpCB(responseText, bidRequest) { - let ad = JSON.parse(responseText); // can throw - - var bid = bidfactory.createBid(STATUS.GOOD, bidRequest); - bid.creative_id = ad.ad_id; - bid.bidderCode = bidRequest.bidder; - bid.cpm = ad.cpm || 0; - bid.ad = ad.adm; - bid.width = ad.width; - bid.height = ad.height; - bid.dealId = ad.deal; - - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } - - return Object.assign(new Adapter(SMARTYADS_BIDDER_CODE), { // SMARTYADS_BIDDER_CODE smartyads - callBids: _callBids - }); -} - -SmartyadsAdapter.masSizeOrdering = function (sizes) { - const MAS_SIZE_PRIORITY = [15, 2, 9]; - - return utils.parseSizesInput(sizes) - // map sizes while excluding non-matches - .reduce((result, size) => { - let mappedSize = parseInt(sizeMap[size], 10); - if (mappedSize) { - result.push(mappedSize); - } - return result; - }, []) - .sort((first, second) => { - // sort by MAS_SIZE_PRIORITY priority order - const firstPriority = MAS_SIZE_PRIORITY.indexOf(first); - const secondPriority = MAS_SIZE_PRIORITY.indexOf(second); - - if (firstPriority > -1 || secondPriority > -1) { - if (firstPriority === -1) { - return 1; - } - if (secondPriority === -1) { - return -1; - } - return firstPriority - secondPriority; - } - - return first - second; - }); -}; - -adaptermanager.registerBidAdapter(new SmartyadsAdapter(), 'smartyads'); - -module.exports = SmartyadsAdapter; diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js deleted file mode 100644 index 689de8635c9..00000000000 --- a/modules/sonobiBidAdapter.js +++ /dev/null @@ -1,118 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils'); -var adaptermanager = require('src/adaptermanager'); - -var SonobiAdapter = function SonobiAdapter() { - var keymakerAssoc = {}; // Remember placement codes for callback mapping - var bidReqAssoc = {}; // Remember bids for bid complete reporting - - function _phone_in(request) { - var trinity = 'https://apex.go.sonobi.com/trinity.js?key_maker='; - var adSlots = request.bids || []; - var bidderRequestId = request.bidderRequestId; - var ref = '&ref=' + encodeURI(utils.getTopWindowLocation().host); - adloader.loadScript(trinity + JSON.stringify(_keymaker(adSlots)) + '&cv=' + _operator(bidderRequestId) + ref); - } - - function _keymaker(adSlots) { - var keyring = {}; - utils._each(adSlots, function(bidRequest) { - if (bidRequest.params) { - // Optional - var floor = (bidRequest.params.floor) ? bidRequest.params.floor : null; - // Mandatory - var slotIdentifier = (bidRequest.params.ad_unit) ? bidRequest.params.ad_unit : (bidRequest.params.placement_id) ? bidRequest.params.placement_id : null; - var sizes = (bidRequest.params.sizes) ? bidRequest.params.sizes : bidRequest.sizes || null; - sizes = utils.parseSizesInput(sizes).toString(); - - if (utils.isEmpty(sizes)) { - utils.logError('Sonobi adapter expects sizes for ' + bidRequest.placementCode); - } - - var bidId = bidRequest.bidId; - - var args = (sizes) ? ((floor) ? (sizes + '|f=' + floor) : (sizes)) : (floor) ? ('f=' + floor) : ''; - if (/^[\/]?[\d]+[[\/].+[\/]?]?$/.test(slotIdentifier)) { - slotIdentifier = slotIdentifier.charAt(0) === '/' ? slotIdentifier : '/' + slotIdentifier; - keyring[slotIdentifier + '|' + bidId] = args; - keymakerAssoc[slotIdentifier + '|' + bidId] = bidRequest.placementCode; - bidReqAssoc[bidRequest.placementCode] = bidRequest; - } else if (/^[0-9a-fA-F]{20}$/.test(slotIdentifier) && slotIdentifier.length === 20) { - keyring[bidId] = slotIdentifier + '|' + args; - keymakerAssoc[bidId] = bidRequest.placementCode; - bidReqAssoc[bidRequest.placementCode] = bidRequest; - } else { - keymakerAssoc[bidId] = bidRequest.placementCode; - bidReqAssoc[bidRequest.placementCode] = bidRequest; - _failure(bidRequest.placementCode); - utils.logError('The ad unit code or Sonobi Placement id for slot ' + bidRequest.placementCode + ' is invalid'); - } - } - }); - return keyring; - } - - function _operator(bidderRequestId) { - var cb_name = 'sbi_' + bidderRequestId; - window[cb_name] = _trinity; - return cb_name; - } - - function _trinity(response) { - var slots = response.slots || {}; - var sbi_dc = response.sbi_dc || ''; - utils._each(slots, function(bid, slot_id) { - var placementCode = keymakerAssoc[slot_id]; - if (bid.sbi_aid && bid.sbi_mouse && bid.sbi_size) { - _success(placementCode, sbi_dc, bid); - } else { - _failure(placementCode); - } - delete keymakerAssoc[slot_id]; - }); - } - - function _seraph(placementCode) { - var theOne = bidReqAssoc[placementCode]; - delete bidReqAssoc[placementCode]; - return theOne; - } - - function _success(placementCode, sbi_dc, bid) { - var goodBid = bidfactory.createBid(1, _seraph(placementCode)); - if (bid.sbi_dozer) { - goodBid.dealId = bid.sbi_dozer; - } - goodBid.bidderCode = 'sonobi'; - goodBid.ad = _creative(sbi_dc, bid.sbi_aid); - goodBid.cpm = Number(bid.sbi_mouse); - goodBid.width = Number(bid.sbi_size.split('x')[0]) || 1; - goodBid.height = Number(bid.sbi_size.split('x')[1]) || 1; - bidmanager.addBidResponse(placementCode, goodBid); - } - - function _failure(placementCode) { - var failBid = bidfactory.createBid(2, _seraph(placementCode)); - failBid.bidderCode = 'sonobi'; - bidmanager.addBidResponse(placementCode, failBid); - } - - function _creative(sbi_dc, sbi_aid) { - var src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null'; - return ''; - } - - return { - callBids: _phone_in, - formRequest: _keymaker, - parseResponse: _trinity, - success: _success, - failure: _failure - }; -}; - -adaptermanager.registerBidAdapter(new SonobiAdapter(), 'sonobi'); - -module.exports = SonobiAdapter; diff --git a/modules/spotxBidAdapter.js b/modules/spotxBidAdapter.js deleted file mode 100644 index 2e2831a028a..00000000000 --- a/modules/spotxBidAdapter.js +++ /dev/null @@ -1,143 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import adLoader from 'src/adloader'; -import * as utils from 'src/utils'; -import { STATUS } from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -function Spotx() { - let baseAdapter = new Adapter('Spotx'); - let bidReq; - let KVP_Object; - - const _defaultBidderSettings = { - alwaysUseBid: true, - adserverTargeting: [ - { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.spotx_ad_key; - } - } - ] - }; - - bidmanager.registerDefaultBidderSetting('spotx', _defaultBidderSettings); - - baseAdapter.callBids = function(bidRequest) { - if (!bidRequest || !bidRequest.bids || bidRequest.bids.length === 0) { - return; - } - bidReq = bidRequest.bids[0] || []; - - if (!validateParams(bidReq)) { - console.log('Bid Request does not contain valid parameters.'); - return; - } - - loadDSDK(); - }; - - // Load the SpotX Direct AdOS SDK onto the page - function loadDSDK() { - var channelId = bidReq.params.video.channel_id; - adLoader.loadScript('//js.spotx.tv/directsdk/v1/' + channelId + '.js', initDSDK, true); - } - - // We have a Direct AdOS SDK! Set options and initialize it! - function initDSDK() { - var options = bidReq.params.video; - - // If we are passed a id string set the slot and video slot to the element using that id. - if (typeof options.slot === 'string') { - options.slot = document.getElementById(bidReq.params.video.slot); - } - if (typeof options.video_slot === 'string') { - options.video_slot = document.getElementById(bidReq.params.video.video_slot); - } - - var directAdOS = new SpotX.DirectAdOS(options); - - directAdOS.getAdServerKVPs().then(function(adServerKVPs) { - // Got an ad back. Build a successful response. - var resp = { - bids: [] - }; - var bid = {}; - - bid.cmpID = bidReq.params.video.channel_id; - bid.cpm = adServerKVPs.spotx_bid; - bid.url = adServerKVPs.spotx_ad_key; - bid.cur = 'USD'; - bid.bidderCode = 'spotx'; - var sizes = utils.isArray(bidReq.sizes[0]) ? bidReq.sizes[0] : bidReq.sizes; - bid.height = sizes[1]; - bid.width = sizes[0]; - resp.bids.push(bid); - KVP_Object = adServerKVPs; - handleResponse(resp); - }, function() { - // No ad... - handleResponse() - }); - } - - function createBid(status) { - var bid = bidfactory.createBid(status, utils.getBidRequest(bidReq.bidId)); - - // Stuff we have no matter what - bid.bidderCode = bidReq.bidder; - bid.placementCode = bidReq.placementCode; - bid.requestId = bidReq.requestId; - bid.code = bidReq.bidder; - - // Stuff we only get with a successful response - if (status === STATUS.GOOD && KVP_Object) { - let url = '//search.spotxchange.com/ad/vast.html?key=' + KVP_Object.spotx_ad_key; - bid.mediaType = 'video'; - - bid.cpm = KVP_Object.spotx_bid; - bid.vastUrl = url; - bid.spotx_ad_key = KVP_Object.spotx_ad_key; - - var sizes = utils.isArray(bidReq.sizes[0]) ? bidReq.sizes[0] : bidReq.sizes; - bid.height = sizes[1]; - bid.width = sizes[0]; - } - - return bid; - } - - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(response) { - if (!response || !response.bids || !response.bids.length) { - bidmanager.addBidResponse(bidReq.placementCode, createBid(STATUS.NO_BID)); - } else { - bidmanager.addBidResponse(bidReq.placementCode, createBid(STATUS.GOOD, response.bids[0])); - } - } - - function validateParams(request) { - if (typeof request.params !== 'object' && typeof request.params.video !== 'object') { - return false; - } - - // Check that all of our required parameters are defined. - if (bidReq.params.video.channel_id === undefined || bidReq.params.video.slot === undefined || bidReq.params.video.video_slot === undefined) { - return false; - } - return true; - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode - }); -} - -adaptermanager.registerBidAdapter(new Spotx(), 'spotx', { - supportedMediaTypes: ['video'] -}); - -module.exports = Spotx; diff --git a/modules/springserveBidAdapter.js b/modules/springserveBidAdapter.js deleted file mode 100644 index d54702a230f..00000000000 --- a/modules/springserveBidAdapter.js +++ /dev/null @@ -1,116 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -var SpringServeAdapter; -SpringServeAdapter = function SpringServeAdapter() { - function buildSpringServeCall(bid) { - var spCall = window.location.protocol + '//bidder.springserve.com/display/hbid?'; - - // get width and height from bid attribute - var size = bid.sizes[0]; - var width = size[0]; - var height = size[1]; - - spCall += '&w='; - spCall += width; - spCall += '&h='; - spCall += height; - - var params = bid.params; - - // maps param attributes to request parameters - var requestAttrMap = { - sp: 'supplyPartnerId', - imp_id: 'impId' - }; - - for (var property in requestAttrMap) { - if (requestAttrMap.hasOwnProperty && params.hasOwnProperty(requestAttrMap[property])) { - spCall += '&'; - spCall += property; - spCall += '='; - - // get property from params and include it in request - spCall += params[requestAttrMap[property]]; - } - } - - var domain = window.location.hostname; - - // override domain when testing - if (params.hasOwnProperty('test') && params.test === true) { - spCall += '&debug=true'; - domain = 'test.com'; - } - - spCall += '&domain='; - spCall += domain; - spCall += '&callback=$$PREBID_GLOBAL$$.handleSpringServeCB'; - - return spCall; - } - - function _callBids(params) { - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - // bidmanager.pbCallbackMap[bid.params.impId] = params; - adloader.loadScript(buildSpringServeCall(bid)); - } - } - - $$PREBID_GLOBAL$$.handleSpringServeCB = function (responseObj) { - if (responseObj && responseObj.seatbid && responseObj.seatbid.length > 0 && - responseObj.seatbid[0].bid[0] !== undefined) { - // look up the request attributs stored in the bidmanager - var responseBid = responseObj.seatbid[0].bid[0]; - // var requestObj = bidmanager.getPlacementIdByCBIdentifer(responseBid.impid); - var requestBids = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'springserve'); - if (requestBids && requestBids.bids.length > 0) { - requestBids = requestBids.bids.filter(bid => bid.params && bid.params.impId === responseBid.impid); - } else { - requestBids = []; - } - var bid = bidfactory.createBid(1); - var placementCode; - - // assign properties from the original request to the bid object - for (var i = 0; i < requestBids.length; i++) { - var bidRequest = requestBids[i]; - if (bidRequest.bidder === 'springserve') { - placementCode = bidRequest.placementCode; - var size = bidRequest.sizes[0]; - bid.width = size[0]; - bid.height = size[1]; - } - } - - if (requestBids[0]) { bid.bidderCode = requestBids[0].bidder; } - - if (responseBid.hasOwnProperty('price') && responseBid.hasOwnProperty('adm')) { - // assign properties from the response to the bid object - bid.cpm = responseBid.price; - bid.ad = responseBid.adm; - } else { - // make object for invalid bid response - bid = bidfactory.createBid(2); - bid.bidderCode = 'springserve'; - } - - bidmanager.addBidResponse(placementCode, bid); - } - }; - - // Export the callBids function, so that prebid.js can execute this function - // when the page asks to send out bid requests. - return { - callBids: _callBids, - buildSpringServeCall: buildSpringServeCall - }; -}; - -adaptermanager.registerBidAdapter(new SpringServeAdapter(), 'springserve'); - -module.exports = SpringServeAdapter; diff --git a/modules/stickyadstvBidAdapter.js b/modules/stickyadstvBidAdapter.js deleted file mode 100644 index c22e696e74e..00000000000 --- a/modules/stickyadstvBidAdapter.js +++ /dev/null @@ -1,269 +0,0 @@ -var Adapter = require('src/adapter.js').default; -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); - -var StickyAdsTVAdapter = function StickyAdsTVAdapter() { - var STICKYADS_BIDDERCODE = 'stickyadstv'; - var MUSTANG_URL = '//cdn.stickyadstv.com/mustang/mustang.min.js'; - var OUTSTREAM_URL = '//cdn.stickyadstv.com/prime-time/[COMP-ID].min.js'; - - var topMostWindow = getTopMostWindow(); - topMostWindow.stickyadstv_cache = {}; - - function _callBids(params) { - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - // Send out bid request for each bid given its tag IDs and query strings - - if (bid.placementCode && bid.params.zoneId) { - sendBidRequest(bid); - } else { - utils.logWarn('StickyAdsTV: Missing mandatory field(s).'); - } - } - } - - function sendBidRequest(bid) { - var placementCode = bid.placementCode; - - var integrationType = bid.params.format ? bid.params.format : 'inbanner'; - var urltoLoad = MUSTANG_URL; - - if (integrationType !== 'inbanner') { - // integration types are equals to component ids - urltoLoad = OUTSTREAM_URL.replace('[COMP-ID]', integrationType); - } - - var bidRegistered = false; - adloader.loadScript(urltoLoad, function() { - getBid(bid, function(bidObject) { - if (!bidRegistered) { - bidRegistered = true; - bidmanager.addBidResponse(placementCode, bidObject); - } - }); - }, true); - } - - function getBid(bid, callback) { - var zoneId = bid.params.zoneId || bid.params.zone; // accept both - var size = getBiggerSize(bid.sizes); - - // some of our formats doesn't have tools API exposed - var toolsAPI = window.com.stickyadstv.tools; - if (toolsAPI && toolsAPI.ASLoader) { - topMostWindow.stickyadstv_asLoader = new toolsAPI.ASLoader(zoneId, getComponentId(bid.params.format)); - } - - var vastLoader = new window.com.stickyadstv.vast.VastLoader(); - bid.vast = topMostWindow.stickyadstv_cache[bid.placementCode] = vastLoader.getVast(); - - var vastCallback = { - onSuccess: bind(function() { - // 'this' is the bid request here - var bidRequest = this; - - var adHtml = formatAdHTML(bidRequest, size); - var price = extractPrice(bidRequest.vast); - - callback(formatBidObject(bidRequest, true, price, adHtml, size[0], size[1])); - }, bid), - onError: bind(function() { - var bidRequest = this; - callback(formatBidObject(bidRequest, false)); - }, bid) - }; - - var config = { - zoneId: zoneId, - playerSize: size[0] + 'x' + size[1], - vastUrlParams: bid.params.vastUrlParams, - componentId: getComponentId(bid.params.format) - }; - - var api = window.com.stickyadstv[getAPIName(bid.params.format)]; - if (api && typeof api.getPlayerSize === 'function') { - // in screenroll and similar cases we don't use the original div size. - config.playerSize = api.getPlayerSize(); - } - - vastLoader.load(config, vastCallback); - } - - function getComponentId(inputFormat) { - var component = 'mustang'; // default component id - - if (inputFormat && inputFormat !== 'inbanner') { - // format identifiers are equals to their component ids. - component = inputFormat; - } - - return component; - } - - function getAPIName(componentId) { - componentId = componentId || ''; - - // remove dash in componentId to get API name - return componentId.replace('-', ''); - } - - function getBiggerSize(array) { - var result = [1, 1]; - for (var i = 0; i < array.length; i++) { - if (array[i][0] * array[i][1] > result[0] * result[1]) { - result = array[i]; - } - } - return result; - } - - var formatInBannerHTML = function(bid, size) { - var placementCode = bid.placementCode; - - var divHtml = '
'; - - var script = "'; - - return divHtml + script; - }; - - var formatOutstreamHTML = function(bid) { - var placementCode = bid.placementCode; - - var config = bid.params; - - // default placement if no placement is set - if (!config.hasOwnProperty('domId') && !config.hasOwnProperty('auto') && !config.hasOwnProperty('p') && !config.hasOwnProperty('article')) { - config.domId = placementCode; - } - - var script = "'; - - return script; - }; - - function formatAdHTML(bid, size) { - var integrationType = bid.params.format; - - var html = ''; - if (integrationType && integrationType !== 'inbanner') { - html = formatOutstreamHTML(bid); - } else { - html = formatInBannerHTML(bid, size); - } - - return html; - } - - function extractPrice(vast) { - var priceData = vast.getPricing(); - - if (!priceData) { - console.warn("freewheel-ssp: Bid pricing Can't be retreived. You may need to enable pricing on you're zone. Please get in touch with your Freewheel contact."); - } - - return priceData; - } - - function formatBidObject(bidRequest, valid, priceData, html, width, height) { - var bidObject; - if (valid && priceData) { - // valid bid response - bidObject = bidfactory.createBid(1, bidRequest); - bidObject.bidderCode = bidRequest.bidder; - bidObject.cpm = priceData.price; - bidObject.currencyCode = priceData.currency; - bidObject.ad = html; - bidObject.width = width; - bidObject.height = height; - } else { - // invalid bid response - bidObject = bidfactory.createBid(2, bidRequest); - bidObject.bidderCode = bidRequest.bidder; - } - return bidObject; - } - - /** - * returns the top most accessible window - */ - function getTopMostWindow() { - var res = window; - - try { - while (top !== res) { - if (res.parent.location.href.length) { res = res.parent; } - } - } catch (e) {} - - return res; - } - - /* Create a function bound to a given object (assigning `this`, and arguments, - * optionally). Binding with arguments is also known as `curry`. - * Delegates to **ECMAScript 5**'s native `Function.bind` if available. - * We check for `func.bind` first, to fail fast when `func` is undefined. - * - * @param {function} func - * @param {optional} context - * @param {...any} var_args - * @return {function} - */ - var bind = function(func, context) { - return function() { - return func.apply(context, arguments); - }; - }; - - return Object.assign(this, new Adapter(STICKYADS_BIDDERCODE), { - callBids: _callBids, - formatBidObject: formatBidObject, - formatAdHTML: formatAdHTML, - getBiggerSize: getBiggerSize, - getBid: getBid, - getTopMostWindow: getTopMostWindow, - getComponentId: getComponentId, - getAPIName: getAPIName - }); -}; - -adaptermanager.registerBidAdapter(new StickyAdsTVAdapter(), 'stickyadstv'); -adaptermanager.aliasBidAdapter('stickyadstv', 'freewheel-ssp'); - -module.exports = StickyAdsTVAdapter; diff --git a/modules/tapsenseBidAdapter.js b/modules/tapsenseBidAdapter.js deleted file mode 100644 index a984f6cb8ab..00000000000 --- a/modules/tapsenseBidAdapter.js +++ /dev/null @@ -1,89 +0,0 @@ -// v0.0.1 - -const bidfactory = require('src/bidfactory.js'); -const bidmanager = require('src/bidmanager.js'); -const adloader = require('src/adloader'); -const utils = require('src/utils.js'); -const adaptermanager = require('src/adaptermanager'); - -const TapSenseAdapter = function TapSenseAdapter() { - const version = '0.0.1'; - const creativeSizes = [ - '320x50' - ]; - const validParams = [ - 'ufid', - 'refer', - 'ad_unit_id', // required - 'device_id', - 'lat', - 'long', - 'user', // required - 'price_floor', - 'test' - ]; - const SCRIPT_URL = 'https://ads04.tapsense.com/ads/headerad'; - let bids; - $$PREBID_GLOBAL$$.tapsense = {}; - function _callBids(params) { - bids = params.bids || []; - for (let i = 0; i < bids.length; i++) { - let bid = bids[i]; - let isValidSize = false; - if (!bid.sizes || !bid.params.user || !bid.params.ad_unit_id) { - return; - } - let parsedSizes = utils.parseSizesInput(bid.sizes); - for (let k = 0; k < parsedSizes.length; k++) { - if (creativeSizes.indexOf(parsedSizes[k]) > -1) { - isValidSize = true; - break; - } - } - if (isValidSize) { - let queryString = `?price=true&jsonp=1&callback=$$PREBID_GLOBAL$$.tapsense.callback_with_price_${bid.bidId}&version=${version}&`; - $$PREBID_GLOBAL$$.tapsense[`callback_with_price_${bid.bidId}`] = generateCallback(bid.bidId); - let keys = Object.keys(bid.params); - for (let j = 0; j < keys.length; j++) { - if (validParams.indexOf(keys[j]) < 0) continue; - queryString += encodeURIComponent(keys[j]) + '=' + encodeURIComponent(bid.params[keys[j]]) + '&'; - } - _requestBids(SCRIPT_URL + queryString); - } - } - } - - function generateCallback(bidId) { - return function tapsenseCallback(response, price) { - let bidObj; - if (response && price) { - let bidReq = utils.getBidRequest(bidId); - if (response.status.value === 'ok' && response.count_ad_units > 0) { - bidObj = bidfactory.createBid(1, bidObj); - bidObj.cpm = price; - bidObj.width = response.width; - bidObj.height = response.height; - bidObj.ad = response.ad_units[0].html; - } else { - bidObj = bidfactory.createBid(2, bidObj); - } - bidObj.bidderCode = bidReq.bidder; - bidmanager.addBidResponse(bidReq.placementCode, bidObj); - } else { - utils.logMessage('No prebid response'); - } - }; - } - - function _requestBids(scriptURL) { - adloader.loadScript(scriptURL); - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new TapSenseAdapter(), 'tapsense'); - -module.exports = TapSenseAdapter; diff --git a/modules/thoughtleadrBidAdapter.js b/modules/thoughtleadrBidAdapter.js deleted file mode 100644 index 1202575a6cb..00000000000 --- a/modules/thoughtleadrBidAdapter.js +++ /dev/null @@ -1,191 +0,0 @@ -const bidfactory = require('src/bidfactory'); -const bidmanager = require('src/bidmanager'); -const utils = require('src/utils'); -const ajax_1 = require('src/ajax'); -const adaptermanager = require('src/adaptermanager'); - -const COOKIE_SYNC_ID = 'tldr-cookie-sync-div'; -const UID_KEY = 'tldr_uid'; -const URL_API = 'tldr' in window && tldr.config.root_url ? tldr.config.root_url : '//a.thoughtleadr.com/v4/'; -const URL_CDN = 'tldr' in window && tldr.config.cdn_url ? tldr.config.cdn_url : '//cdn.thoughtleadr.com/v4/'; -const BID_AVAILABLE = 1; -const BID_UNAVAILABLE = 2; - -function storageAvailable(type) { - try { - const storage = window[type]; - const x = '__storage_test__'; - storage.setItem(x, x); - storage.removeItem(x); - return true; - } catch (e) { - return e instanceof DOMException && ( - // everything except Firefox - e.code === 22 || - // Firefox - e.code === 1014 || - // test name field too, because code might not be present - // everything except Firefox - e.name === 'QuotaExceededError' || - // Firefox - e.name === 'NS_ERROR_DOM_QUOTA_REACHED') && - // acknowledge QuotaExceededError only if there's something already stored - storage.length !== 0; - } -} - -function getVal(key) { - if (storageAvailable('localStorage')) { - return localStorage[key]; - } - if (storageAvailable('sessionStorage')) { - return sessionStorage[key]; - } - return null; -} - -function setVal(key, val) { - if (storageAvailable('localStorage')) { - localStorage[key] = val; - } - if (storageAvailable('sessionStorage')) { - sessionStorage[key] = val; - } -} - -function getUid() { - let uid = getVal(UID_KEY); - if (!uid) { - uid = utils.generateUUID(null); - setVal(UID_KEY, uid); - } - return uid; -} - -function writeFriendlyFrame(html, container) { - const iframe = document.createElement('iframe'); - iframe.style.width = '0'; - iframe.style.height = '0'; - iframe.style.border = '0'; - - iframe.src = 'javascript:false'; - container.appendChild(iframe); - - const doc = iframe.contentWindow.document; - doc.body.innerHTML = html; - - const scripts = doc.body.getElementsByTagName('script'); - - for (let i = 0; i < scripts.length; i++) { - const scriptEl = scripts.item(i); - if (scriptEl.nodeName === 'SCRIPT') { - executeScript(scriptEl); - } - } - - return iframe; -} - -function executeScript(scriptEl) { - const newEl = document.createElement('script'); - newEl.innerText = scriptEl.text || scriptEl.textContent || scriptEl.innerHTML || ''; - - // ie-compatible copy-paste attributes - const attrs = scriptEl.attributes; - for (let i = attrs.length; i--;) { - newEl.setAttribute(attrs[i].name, attrs[i].value); - } - - if (scriptEl.parentNode) { - scriptEl.parentNode.replaceChild(newEl, scriptEl); - } -} - -const ThoughtleadrAdapter = (function () { - function ThoughtleadrAdapter() { - } - - ThoughtleadrAdapter.prototype.callBids = function (params) { - const bids = (params.bids || []).filter(function (bid) { - return ThoughtleadrAdapter.valid(bid); - }); - - for (let _i = 0, bids_1 = bids; _i < bids_1.length; _i++) { - const bid = bids_1[_i]; - this.requestPlacement(bid); - } - }; - - ThoughtleadrAdapter.prototype.requestPlacement = function (bid) { - const _this = this; - const uid = getUid(); - const size = ThoughtleadrAdapter.getSizes(bid.sizes); - - ajax_1.ajax('' + URL_API + bid.params.placementId + '/header-bid.json?uid=' + uid, function (response) { - const wonBid = JSON.parse(response); - if (wonBid.cookie_syncs) { - _this.syncCookies(wonBid.cookie_syncs); - } - - const script = document.createElement('script'); - script.src = URL_CDN + 'bid.js'; - script.setAttribute('header-bid-token', wonBid.header_bid_token); - - let bidObject; - if (wonBid && wonBid.amount) { - bidObject = bidfactory.createBid(BID_AVAILABLE); - bidObject.bidderCode = 'thoughtleadr'; - bidObject.cpm = wonBid.amount; - bidObject.ad = script.outerHTML; - bidObject.width = size.width; - bidObject.height = size.height; - } else { - bidObject = bidfactory.createBid(BID_UNAVAILABLE); - bidObject.bidderCode = 'thoughtleadr'; - } - bidmanager.addBidResponse(bid.placementCode, bidObject); - }, null); - }; - - ThoughtleadrAdapter.prototype.syncCookies = function (tags) { - if (!tags || !tags.length) { - return; - } - - let container = document.getElementById(COOKIE_SYNC_ID); - if (!container) { - container = document.createElement('div'); - container.id = COOKIE_SYNC_ID; - container.style.width = '0'; - container.style.height = '0'; - document.body.appendChild(container); - } - - for (let _i = 0, tags_1 = tags; _i < tags_1.length; _i++) { - const tag = tags_1[_i]; - writeFriendlyFrame(tag, container); - } - }; - - ThoughtleadrAdapter.valid = function (bid) { - return !!(bid && bid.params && typeof bid.params.placementId === 'string'); - }; - - ThoughtleadrAdapter.getSizes = function (sizes) { - const first = sizes[0]; - if (Array.isArray(first)) { - return ThoughtleadrAdapter.getSizes(first); - } - - return { - width: sizes[0], - height: sizes[1] - }; - }; - - return ThoughtleadrAdapter; -}()); - -adaptermanager.registerBidAdapter(new ThoughtleadrAdapter(), 'thoughtleadr'); - -module.exports = ThoughtleadrAdapter; diff --git a/modules/tremorBidAdapter.js b/modules/tremorBidAdapter.js deleted file mode 100644 index 1294c61e210..00000000000 --- a/modules/tremorBidAdapter.js +++ /dev/null @@ -1,167 +0,0 @@ -/* -* Tremor Video bid Adapter for prebid.js -* */ - -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -const ENDPOINT = '.ads.tremorhub.com/ad/tag'; - -const OPTIONAL_PARAMS = [ - 'mediaId', 'mediaUrl', 'mediaTitle', 'contentLength', 'floor', - 'efloor', 'custom', 'categories', 'keywords', 'blockDomains', - 'c2', 'c3', 'c4', 'skip', 'skipmin', 'skipafter', 'delivery', - 'placement', 'videoMinBitrate', 'videoMaxBitrate' -]; - -/** - * Bidder adapter Tremor Video. Given the list of all ad unit tag IDs, - * sends out a bid request. When a bid response is back, registers the bid - * to Prebid.js. - * Steps: - * - Format and send the bid request - * - Evaluate and handle the response - * - Store potential VAST markup - * - Send request to ad server - * - intercept ad server response - * - Check if the vast wrapper URL is http://cdn.tremorhub.com/static/dummy.xml - * - If yes: then render the locally stored VAST markup by directly passing it to your player - * - Else: give the player the VAST wrapper from your ad server - */ -function TremorAdapter() { - let baseAdapter = new Adapter('tremor'); - - /* Prebid executes this function when the page asks to send out bid requests */ - baseAdapter.callBids = function (bidRequest) { - const bids = bidRequest.bids || []; - bids.filter(bid => valid(bid)) - .map(bid => { - let url = generateUrl(bid); - if (url) { - ajax(url, response => { - handleResponse(bid, response); - }, null, {method: 'GET', withCredentials: true}); - } - }); - }; - - /** - * Generates the url based on the parameters given. Sizes are required. - * The format is: [L,W] or [[L1,W1],...] - * @param bid - * @returns {string} - */ - function generateUrl(bid) { - // get the sizes - let width, height; - if (utils.isArray(bid.sizes) && bid.sizes.length === 2 && (!isNaN(bid.sizes[0]) && !isNaN(bid.sizes[1]))) { - width = bid.sizes[0]; - height = bid.sizes[1]; - } else if (typeof bid.sizes === 'object') { - // take the primary (first) size from the array - width = bid.sizes[0][0]; - height = bid.sizes[0][1]; - } - if (width && height) { - let scheme = ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; - let url = scheme + bid.params.supplyCode + ENDPOINT + '?adCode=' + bid.params.adCode; - - url += ('&playerWidth=' + width); - url += ('&playerHeight=' + height); - url += ('&srcPageUrl=' + encodeURIComponent(document.location.href)); - - OPTIONAL_PARAMS.forEach(param => { - if (bid.params[param]) { - url += ('&' + param + '=' + bid.params[param]); - } - }); - - url = (url + '&fmt=json'); - - return url; - } - } - - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(bidReq, response) { - let bidResult; - - try { - bidResult = JSON.parse(response); - } catch (error) { - utils.logError(error); - } - - if (!bidResult || bidResult.error) { - let errorMessage = `in response for ${baseAdapter.getBidderCode()} adapter`; - if (bidResult && bidResult.error) { - errorMessage += `: ${bidResult.error}`; - } - utils.logError(errorMessage); - - // signal this response is complete - bidmanager.addBidResponse(bidReq.placementCode, createBid(STATUS.NO_BID)); - } - - if (bidResult.seatbid && bidResult.seatbid.length > 0) { - bidResult.seatbid[0].bid.forEach(tag => { - let status = STATUS.GOOD; - const bid = createBid(status, bidReq, tag); - bidmanager.addBidResponse(bidReq.placementCode, bid); - }); - } else { - // signal this response is complete with no bid - bidmanager.addBidResponse(bidReq.placementCode, createBid(STATUS.NO_BID)); - } - } - - /** - * We require the ad code and the supply code to generate a tag url - * @param bid - * @returns {*} - */ - function valid(bid) { - if (bid.params.adCode && bid.params.supplyCode) { - return bid; - } else { - utils.logError('missing bid params'); - } - } - - /** - * Create and return a bid object based on status and tag - * @param status - * @param reqBid - * @param response - */ - function createBid(status, reqBid, response) { - let bid = bidfactory.createBid(status, reqBid); - bid.code = baseAdapter.getBidderCode(); - bid.bidderCode = baseAdapter.getBidderCode(); - - if (response) { - bid.cpm = response.price; - bid.crid = response.crid; - bid.vastXml = response.adm; - bid.mediaType = 'video'; - } - - return bid; - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - }); -} - -adaptermanager.registerBidAdapter(new TremorAdapter(), 'tremor', { - supportedMediaTypes: ['video'] -}); - -module.exports = TremorAdapter; diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js deleted file mode 100644 index 141bdbf32cb..00000000000 --- a/modules/tripleliftBidAdapter.js +++ /dev/null @@ -1,149 +0,0 @@ -var utils = require('src/utils.js'); -var adloader = require('src/adloader.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -var adaptermanager = require('src/adaptermanager'); - -/* TripleLift bidder factory function -* Use to create a TripleLiftAdapter object -*/ - -var TripleLiftAdapter = function TripleLiftAdapter() { - var usersync = false; - - function _callBids(params) { - var tlReq = params.bids; - var bidsCount = tlReq.length; - - // set expected bids count for callback execution - // bidmanager.setExpectedBidsCount('triplelift',bidsCount); - - for (var i = 0; i < bidsCount; i++) { - var bidRequest = tlReq[i]; - var callbackId = bidRequest.bidId; - adloader.loadScript(buildTLCall(bidRequest, callbackId)); - // store a reference to the bidRequest from the callback id - // bidmanager.pbCallbackMap[callbackId] = bidRequest; - } - } - - function buildTLCall(bid, callbackId) { - // determine tag params - var inventoryCode = utils.getBidIdParameter('inventoryCode', bid.params); - var floor = utils.getBidIdParameter('floor', bid.params); - - // build our base tag, based on if we are http or https - var tlURI = '//tlx.3lift.com/header/auction?'; - var tlCall = document.location.protocol + tlURI; - - tlCall = utils.tryAppendQueryString(tlCall, 'callback', '$$PREBID_GLOBAL$$.TLCB'); - tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); - tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); - tlCall = utils.tryAppendQueryString(tlCall, 'callback_id', callbackId); - tlCall = utils.tryAppendQueryString(tlCall, 'inv_code', inventoryCode); - tlCall = utils.tryAppendQueryString(tlCall, 'floor', floor); - - // indicate whether flash support exists - tlCall = utils.tryAppendQueryString(tlCall, 'fe', isFlashEnabled()); - - // sizes takes a bit more logic - var sizeQueryString = utils.parseSizesInput(bid.sizes); - if (sizeQueryString) { - tlCall += 'size=' + sizeQueryString + '&'; - } - - // append referrer - var referrer = utils.getTopWindowUrl(); - tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer); - - // remove the trailing "&" - if (tlCall.lastIndexOf('&') === tlCall.length - 1) { - tlCall = tlCall.substring(0, tlCall.length - 1); - } - - // @if NODE_ENV='debug' - utils.logMessage('tlCall request built: ' + tlCall); - // @endif - - // append a timer here to track latency - bid.startTime = new Date().getTime(); - - return tlCall; - } - - function isFlashEnabled() { - var hasFlash = 0; - try { - // check for Flash support in IE - var fo = new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash'); - if (fo) { hasFlash = 1; } - } catch (e) { - if (navigator.mimeTypes && - navigator.mimeTypes['application/x-shockwave-flash'] !== undefined && - navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) { - hasFlash = 1; - } - } - return hasFlash; - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.TLCB = function(tlResponseObj) { - if (tlResponseObj && tlResponseObj.callback_id) { - var bidObj = utils.getBidRequest(tlResponseObj.callback_id); - var placementCode = bidObj && bidObj.placementCode; - - // @if NODE_ENV='debug' - if (bidObj) { utils.logMessage('JSONP callback function called for inventory code: ' + bidObj.params.inventoryCode); } - // @endif - - var bid = []; - if (tlResponseObj && tlResponseObj.cpm && tlResponseObj.cpm !== 0) { - bid = bidfactory.createBid(1, bidObj); - bid.bidderCode = 'triplelift'; - bid.cpm = tlResponseObj.cpm; - bid.ad = tlResponseObj.ad; - bid.width = tlResponseObj.width; - bid.height = tlResponseObj.height; - bid.dealId = tlResponseObj.deal_id; - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - // @if NODE_ENV='debug' - if (bidObj) { utils.logMessage('No prebid response from TripleLift for inventory code: ' + bidObj.params.inventoryCode); } - // @endif - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = 'triplelift'; - bidmanager.addBidResponse(placementCode, bid); - } - - // run usersyncs - if (!usersync) { - var iframe = utils.createInvisibleIframe(); - iframe.src = '//ib.3lift.com/sync'; - try { - document.body.appendChild(iframe); - } catch (error) { - utils.logError(error); - } - usersync = true; - // suppress TL ad tag from running additional usersyncs - window._tlSyncDone = true; - } - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - // @endif - } - }; - - return { - callBids: _callBids - - }; -}; - -adaptermanager.registerBidAdapter(new TripleLiftAdapter(), 'triplelift'); - -module.exports = TripleLiftAdapter; diff --git a/modules/twengaBidAdapter.js b/modules/twengaBidAdapter.js deleted file mode 100644 index 3a0e1016937..00000000000 --- a/modules/twengaBidAdapter.js +++ /dev/null @@ -1,136 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var adloader = require('src/adloader.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -var Adapter = require('src/adapter.js').default; -var adaptermanager = require('src/adaptermanager'); - -function TwengaAdapter() { - var baseAdapter = new Adapter('twenga'); - - baseAdapter.callBids = function (params) { - for (var i = 0; i < params.bids.length; i++) { - var bidRequest = params.bids[i]; - var callbackId = bidRequest.bidId; - adloader.loadScript(buildBidCall(bidRequest, callbackId)); - } - }; - - function buildBidCall(bid, callbackId) { - var bidUrl = '//rtb.t.c4tw.net/Bid?'; - bidUrl = utils.tryAppendQueryString(bidUrl, 's', 'h'); - bidUrl = utils.tryAppendQueryString(bidUrl, 'callback', '$$PREBID_GLOBAL$$.handleTwCB'); - bidUrl = utils.tryAppendQueryString(bidUrl, 'callback_uid', callbackId); - bidUrl = utils.tryAppendQueryString(bidUrl, 'referrer', utils.getTopWindowUrl()); - if (bid.params) { - for (var key in bid.params) { - var value = bid.params[key]; - switch (key) { - case 'placementId': key = 'id'; break; - case 'siteId': key = 'sid'; break; - case 'publisherId': key = 'pid'; break; - case 'currency': key = 'cur'; break; - case 'bidFloor': key = 'min'; break; - case 'country': key = 'gz'; break; - } - bidUrl = utils.tryAppendQueryString(bidUrl, key, value); - } - } - - var sizes = utils.parseSizesInput(bid.sizes); - if (sizes.length > 0) { - bidUrl = utils.tryAppendQueryString(bidUrl, 'size', sizes.join(',')); - } - - bidUrl += 'ta=1'; - - // @if NODE_ENV='debug' - utils.logMessage('bid request built: ' + bidUrl); - - // @endif - - // append a timer here to track latency - bid.startTime = new Date().getTime(); - - return bidUrl; - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleTwCB = function (bidResponseObj) { - var bidCode; - - if (bidResponseObj && bidResponseObj.callback_uid) { - var responseCPM; - var id = bidResponseObj.callback_uid; - var placementCode = ''; - var bidObj = utils.getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; - - placementCode = bidObj.placementCode; - - bidObj.status = CONSTANTS.STATUS.GOOD; - } - - // @if NODE_ENV='debug' - utils.logMessage('JSONP callback function called for ad ID: ' + id); - - // @endif - var bid = []; - if (bidResponseObj.result && - bidResponseObj.result.cpm && - bidResponseObj.result.cpm !== 0 && - bidResponseObj.result.ad) { - var result = bidResponseObj.result; - - responseCPM = parseInt(result.cpm, 10); - - // CPM response from /Bid is dollar/cent multiplied by 10000 - // in order to avoid using floats - // switch CPM to "dollar/cent" - responseCPM = responseCPM / 10000; - - var ad = result.ad.replace('%%WP%%', result.cpm); - - // store bid response - // bid status is good (indicating 1) - bid = bidfactory.createBid(1, bidObj); - bid.creative_id = result.creative_id; - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - if (ad && (ad.lastIndexOf('http', 0) === 0 || ad.lastIndexOf('//', 0) === 0)) { bid.adUrl = ad; } else { bid.ad = ad; } - bid.width = result.width; - bid.height = result.height; - - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response from Twenga for placement code ' + placementCode); - - // @endif - // indicate that there is no bid for this placement - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - - // @endif - } - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - buildBidCall: buildBidCall - }); -} - -adaptermanager.registerBidAdapter(new TwengaAdapter(), 'twenga'); - -module.exports = TwengaAdapter; diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js deleted file mode 100644 index 978c7508002..00000000000 --- a/modules/ucfunnelBidAdapter.js +++ /dev/null @@ -1,95 +0,0 @@ -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -const VER = 'ADGENT_PREBID-2017051801'; -const UCFUNNEL_BIDDER_CODE = 'ucfunnel'; - -function UcfunnelAdapter() { - function _callBids(params) { - let bids = params.bids || []; - - bids.forEach((bid) => { - try { - ajax(buildOptimizedCall(bid), bidCallback, undefined, { withCredentials: true }); - } catch (err) { - utils.logError('Error sending ucfunnel request for placement code ' + bid.placementCode, null, err); - } - - function bidCallback(responseText) { - try { - utils.logMessage('XHR callback function called for placement code: ' + bid.placementCode); - handleRpCB(responseText, bid); - } catch (err) { - if (typeof err === 'string') { - utils.logWarn(`${err} when processing ucfunnel response for placement code ${bid.placementCode}`); - } else { - utils.logError('Error processing ucfunnel response for placement code ' + bid.placementCode, null, err); - } - - // indicate that there is no bid for this placement - let badBid = bidfactory.createBid(STATUS.NO_BID, bid); - badBid.bidderCode = bid.bidder; - badBid.error = err; - bidmanager.addBidResponse(bid.placementCode, badBid); - } - } - }); - } - - function buildOptimizedCall(bid) { - bid.startTime = new Date().getTime(); - - const host = utils.getTopWindowLocation().host; - const page = utils.getTopWindowLocation().pathname; - const refer = document.referrer; - const language = navigator.language; - const dnt = (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0; - - let queryString = [ - 'ifr', 0, - 'bl', language, - 'je', 1, - 'dnt', dnt, - 'host', host, - 'u', page, - 'ru', refer, - 'adid', bid.params.adid, - 'ver', VER - ]; - - return queryString.reduce( - (memo, curr, index) => - index % 2 === 0 && queryString[index + 1] !== undefined - ? memo + curr + '=' + encodeURIComponent(queryString[index + 1]) + '&' - : memo, - '//agent.aralego.com/header?' - ).slice(0, -1); - } - - function handleRpCB(responseText, bidRequest) { - let ad = JSON.parse(responseText); // can throw - - let bid = bidfactory.createBid(STATUS.GOOD, bidRequest); - bid.creative_id = ad.ad_id; - bid.bidderCode = UCFUNNEL_BIDDER_CODE; - bid.cpm = ad.cpm || 0; - bid.ad = ad.adm; - bid.width = ad.width; - bid.height = ad.height; - bid.dealId = ad.deal; - - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new UcfunnelAdapter(), UCFUNNEL_BIDDER_CODE); - -module.exports = UcfunnelAdapter; diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js deleted file mode 100644 index 0f6b6e40901..00000000000 --- a/modules/unrulyBidAdapter.js +++ /dev/null @@ -1,119 +0,0 @@ -import { ajax } from 'src/ajax' -import bidfactory from 'src/bidfactory' -import bidmanager from 'src/bidmanager' -import * as utils from 'src/utils' -import { STATUS } from 'src/constants' -import { Renderer } from 'src/Renderer' -import adaptermanager from 'src/adaptermanager' - -function createRenderHandler({ bidResponseBid, rendererConfig }) { - function createApi() { - parent.window.unruly['native'].prebid = parent.window.unruly['native'].prebid || {} - parent.window.unruly['native'].prebid.uq = parent.window.unruly['native'].prebid.uq || [] - - return { - render(bidResponseBid) { - parent.window.unruly['native'].prebid.uq.push(['render', bidResponseBid]) - }, - onLoaded(bidResponseBid) {} - } - } - - parent.window.unruly = parent.window.unruly || {} - parent.window.unruly['native'] = parent.window.unruly['native'] || {} - parent.window.unruly['native'].siteId = parent.window.unruly['native'].siteId || rendererConfig.siteId - - const api = createApi() - return { - render() { - api.render(bidResponseBid) - }, - onRendererLoad() { - api.onLoaded(bidResponseBid) - } - } -} - -function createBidResponseHandler(bidRequestBids) { - return { - onBidResponse(responseBody) { - try { - const exchangeResponse = JSON.parse(responseBody) - exchangeResponse.bids.forEach((exchangeBid) => { - const bidResponseBid = bidfactory.createBid(exchangeBid.ext.statusCode, exchangeBid) - - Object.assign( - bidResponseBid, - exchangeBid - ) - - if (exchangeBid.ext.renderer) { - const rendererParams = exchangeBid.ext.renderer - const renderHandler = createRenderHandler({ - bidResponseBid, - rendererConfig: rendererParams.config - }) - - bidResponseBid.renderer = Renderer.install( - Object.assign( - {}, - rendererParams, - { callback: () => renderHandler.onRendererLoad() } - ) - ) - bidResponseBid.renderer.setRender(() => renderHandler.render()) - } - - bidmanager.addBidResponse(exchangeBid.ext.placementCode, bidResponseBid) - }) - } catch (error) { - utils.logError(error); - bidRequestBids.forEach(bidRequestBid => { - const bidResponseBid = bidfactory.createBid(STATUS.NO_BID) - bidmanager.addBidResponse(bidRequestBid.placementCode, bidResponseBid) - }) - } - } - } -} - -function UnrulyAdapter() { - const adapter = { - exchangeUrl: 'https://targeting.unrulymedia.com/prebid', - callBids({ bids: bidRequestBids }) { - if (!bidRequestBids || bidRequestBids.length === 0) { - return - } - - const videoMediaType = utils.deepAccess(bidRequestBids[0], 'mediaTypes.video') - const context = utils.deepAccess(bidRequestBids[0], 'mediaTypes.video.context') - if (videoMediaType && context !== 'outstream') { - return - } - - const payload = { - bidRequests: bidRequestBids - } - - const bidResponseHandler = createBidResponseHandler(bidRequestBids) - - ajax( - adapter.exchangeUrl, - bidResponseHandler.onBidResponse, - JSON.stringify(payload), - { - contentType: 'application/json', - withCredentials: true - } - ) - } - } - - return adapter -} - -adaptermanager.registerBidAdapter(new UnrulyAdapter(), 'unruly', { - supportedMediaTypes: ['video'] -}); - -module.exports = UnrulyAdapter diff --git a/modules/vertozBidAdapter.js b/modules/vertozBidAdapter.js deleted file mode 100644 index b6966dd62d1..00000000000 --- a/modules/vertozBidAdapter.js +++ /dev/null @@ -1,72 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var adaptermanager = require('src/adaptermanager'); - -function VertozAdapter() { - const BASE_URI = '//hb.vrtzads.com/vzhbidder/bid?'; - const BIDDER_NAME = 'vertoz'; - const QUERY_PARAM_KEY = 'q'; - - function _callBids(params) { - var bids = params.bids || []; - - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - let slotBidId = utils.getValue(bid, 'bidId'); - let cb = Math.round(new Date().getTime() / 1000); - let vzEndPoint = BASE_URI; - let reqParams = bid.params || {}; - let placementId = utils.getValue(reqParams, 'placementId'); - let cpm = utils.getValue(reqParams, 'cpmFloor'); - - if (utils.isEmptyStr(placementId)) { - utils.logError('missing params:', BIDDER_NAME, 'Enter valid vzPlacementId'); - return; - } - - let reqSrc = utils.getTopWindowLocation().href; - var vzReq = { - _vzPlacementId: placementId, - _rqsrc: reqSrc, - _cb: cb, - _slotBidId: slotBidId, - _cpm: cpm, - _cbn: '$$PREBID_GLOBAL$$' - }; - - let queryParamValue = JSON.stringify(vzReq); - vzEndPoint = utils.tryAppendQueryString(vzEndPoint, QUERY_PARAM_KEY, queryParamValue); - adloader.loadScript(vzEndPoint); - } - } - - $$PREBID_GLOBAL$$.vzResponse = function (vertozResponse) { - var bidRespObj = vertozResponse; - var bidObject; - var reqBidObj = utils.getBidRequest(bidRespObj.slotBidId); - - if (bidRespObj.cpm) { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.GOOD, reqBidObj); - bidObject.cpm = Number(bidRespObj.cpm); - bidObject.ad = bidRespObj.ad + utils.createTrackPixelHtml(decodeURIComponent(bidRespObj.nurl)); - bidObject.width = bidRespObj.adWidth; - bidObject.height = bidRespObj.adHeight; - } else { - let respStatusText = bidRespObj.statusText; - bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, reqBidObj); - utils.logMessage(respStatusText); - } - - var adSpaceId = reqBidObj.placementCode; - bidObject.bidderCode = BIDDER_NAME; - bidmanager.addBidResponse(adSpaceId, bidObject); - }; - return { callBids: _callBids }; -} - -adaptermanager.registerBidAdapter(new VertozAdapter(), 'vertoz'); - -module.exports = VertozAdapter; diff --git a/modules/wideorbitBidAdapter.js b/modules/wideorbitBidAdapter.js deleted file mode 100644 index f0ed885f6a3..00000000000 --- a/modules/wideorbitBidAdapter.js +++ /dev/null @@ -1,223 +0,0 @@ -const bidfactory = require('src/bidfactory.js'); -const bidmanager = require('src/bidmanager.js'); -const utils = require('src/utils.js'); -const adloader = require('src/adloader'); -const adaptermanager = require('src/adaptermanager'); - -function WideOrbitAdapter() { - const pageImpression = 'JSAdservingMP.ashx?pc={pc}&pbId={pbId}&clk=&exm=&jsv=1.0&tsv=1.0&cts={cts}&arp=0&fl=0&vitp=&vit=&jscb=window.$$PREBID_GLOBAL$$.handleWideOrbitCallback&url={referrer}&fp=&oid=&exr=&mraid=&apid=&apbndl=&mpp=0&uid=&cb={cb}&hb=1'; - const pageRepeatCommonParam = '&gid{o}={gid}&pp{o}=&clk{o}=&rpos{o}={rpos}&ecpm{o}={ecpm}&ntv{o}=&ntl{o}=&adsid{o}='; - const pageRepeatParamId = '&pId{o}={pId}&rank{o}={rank}'; - const pageRepeatParamNamed = '&wsName{o}={wsName}&wName{o}={wName}&rank{o}={rank}&bfDim{o}={width}x{height}&subp{o}={subp}'; - const base = (window.location.protocol) + '//p{pbId}.atemda.com/'; - let bids; - const adapterName = 'wideorbit'; - - function _fixParamNames(param) { - if (!param) { - return; - } - - const properties = ['site', 'page', 'width', 'height', 'rank', 'subPublisher', 'ecpm', 'atf', 'pId', 'pbId', 'referrer']; - let prop; - - utils._each(properties, function (correctName) { - for (prop in param) { - if (param.hasOwnProperty(prop) && prop.toLowerCase() === correctName.toLowerCase()) { - param[correctName] = param[prop]; - break; - } - } - }); - } - - function _setParam(str, param, value) { - var pattern = new RegExp('{' + param + '}', 'g'); - - if (value === true) { - value = 1; - } - if (value === false) { - value = 0; - } - return str.replace(pattern, value); - } - - function _setParams(str, keyValuePairs) { - utils._each(keyValuePairs, function (keyValuePair) { - str = _setParam(str, keyValuePair[0], keyValuePair[1]); - }); - return str; - } - - function _setCommonParams(pos, params) { - return _setParams(pageRepeatCommonParam, [ - ['o', pos], - ['gid', encodeURIComponent(params.tagId)], - ['rpos', params.atf ? 1001 : 0], - ['ecpm', params.ecpm || ''] - ]); - } - - function _getRankParam(rank, pos) { - return rank || pos; - } - - function _setupIdPlacementParameters(pos, params) { - return _setParams(pageRepeatParamId, [ - ['o', pos], - ['pId', params.pId], - ['rank', _getRankParam(params.rank, pos)] - ]); - } - - function _setupNamedPlacementParameters(pos, params) { - return _setParams(pageRepeatParamNamed, [ - ['o', pos], - ['wsName', encodeURIComponent(decodeURIComponent(params.site))], - ['wName', encodeURIComponent(decodeURIComponent(params.page))], - ['width', params.width], - ['height', params.height], - ['subp', params.subPublisher ? encodeURIComponent(decodeURIComponent(params.subPublisher)) : ''], - ['rank', _getRankParam(params.rank, pos)] - ]); - } - - function _setupAdCall(publisherId, placementCount, placementsComponent, referrer) { - return _setParams(base + pageImpression, [ - ['pbId', publisherId], - ['pc', placementCount], - ['cts', new Date().getTime()], - ['cb', Math.floor(Math.random() * 100000000)], - ['referrer', encodeURIComponent(referrer || '')] - ]) + placementsComponent; - } - - function _setupPlacementParameters(pos, params) { - var commonParams = _setCommonParams(pos, params); - - if (params.pId) { - return _setupIdPlacementParameters(pos, params) + commonParams; - } - - return _setupNamedPlacementParameters(pos, params) + commonParams; - } - - function _callBids(params) { - let publisherId; - let bidUrl = ''; - let i; - let referrer; - - bids = params.bids || []; - - for (i = 0; i < bids.length; i++) { - var requestParams = bids[i].params; - - requestParams.tagId = bids[i].placementCode; - - _fixParamNames(requestParams); - - publisherId = requestParams.pbId; - referrer = referrer || requestParams.referrer; - bidUrl += _setupPlacementParameters(i, requestParams); - } - - bidUrl = _setupAdCall(publisherId, bids.length, bidUrl, referrer); - - utils.logMessage('Calling WO: ' + bidUrl); - - adloader.loadScript(bidUrl); - } - - function _processUserMatchings(userMatchings) { - const headElem = document.getElementsByTagName('head')[0]; - let createdElem; - - utils._each(userMatchings, function (userMatching) { - createdElem = undefined; - switch (userMatching.Type) { - case 'redirect': - createdElem = document.createElement('img'); - break; - case 'iframe': - createdElem = utils.createInvisibleIframe(); - break; - case 'js': - createdElem = document.createElement('script'); - createdElem.type = 'text/javascript'; - createdElem.async = true; - break; - } - if (createdElem) { - createdElem.src = decodeURIComponent(userMatching.Url); - headElem.insertBefore(createdElem, headElem.firstChild); - } - }); - } - - function _getBidResponse(id, placements) { - var i; - - for (i = 0; i < placements.length; i++) { - if (placements[i].ExtPlacementId === id) { - return placements[i]; - } - } - } - - function _isUrl(scr) { - return scr.slice(0, 6) === 'http:/' || scr.slice(0, 7) === 'https:/' || scr.slice(0, 2) === '//'; - } - - function _buildAdCode(placement) { - let adCode = placement.Source; - let pixelTag; - - utils._each(placement.TrackingCodes, function (trackingCode) { - if (_isUrl(trackingCode)) { - pixelTag = ''; - } else { - pixelTag = trackingCode; - } - adCode = pixelTag + adCode; - }); - - return adCode; - } - - window.$$PREBID_GLOBAL$$ = window.$$PREBID_GLOBAL$$ || {}; - window.$$PREBID_GLOBAL$$.handleWideOrbitCallback = function (response) { - var bidResponse, - bidObject; - - utils.logMessage('WO response. Placements: ' + response.Placements.length); - - _processUserMatchings(response.UserMatchings); - - utils._each(bids, function (bid) { - bidResponse = _getBidResponse(bid.placementCode, response.Placements); - - if (bidResponse && bidResponse.Type === 'DirectHTML') { - bidObject = bidfactory.createBid(1); - bidObject.cpm = bidResponse.Bid; - bidObject.ad = _buildAdCode(bidResponse); - bidObject.width = bidResponse.Width; - bidObject.height = bidResponse.Height; - } else { - bidObject = bidfactory.createBid(2); - } - - bidObject.bidderCode = adapterName; - bidmanager.addBidResponse(bid.placementCode, bidObject); - }); - }; - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new WideOrbitAdapter(), 'wideorbit'); - -module.exports = WideOrbitAdapter; diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js deleted file mode 100644 index c9e6fb4a11d..00000000000 --- a/modules/widespaceBidAdapter.js +++ /dev/null @@ -1,127 +0,0 @@ - -const utils = require('src/utils.js'); -const adloader = require('src/adloader.js'); -const bidmanager = require('src/bidmanager.js'); -const bidfactory = require('src/bidfactory.js'); -const adaptermanager = require('src/adaptermanager'); -const WS_ADAPTER_VERSION = '1.0.3'; - -function WidespaceAdapter() { - const useSSL = document.location.protocol === 'https:'; - const baseURL = (useSSL ? 'https:' : 'http:') + '//engine.widespace.com/map/engine/hb/dynamic?'; - const callbackName = '$$PREBID_GLOBAL$$.widespaceHandleCB'; - - function _callBids(params) { - let bids = (params && params.bids) || []; - - for (var i = 0; i < bids.length; i++) { - const bid = bids[i]; - const callbackUid = bid.bidId; - const sid = bid.params.sid; - const currency = bid.params.cur || bid.params.currency; - - // Handle Sizes string - let sizeQueryString = ''; - let parsedSizes = utils.parseSizesInput(bid.sizes); - - sizeQueryString = parsedSizes.reduce((prev, curr) => { - return prev ? `${prev},${curr}` : curr; - }, sizeQueryString); - - let requestURL = baseURL; - requestURL = utils.tryAppendQueryString(requestURL, 'hb.ver', WS_ADAPTER_VERSION); - - const params = { - 'hb': '1', - 'hb.name': 'prebidjs', - 'hb.callback': callbackName, - 'hb.callbackUid': callbackUid, - 'hb.sizes': sizeQueryString, - 'hb.currency': currency, - 'sid': sid - }; - - if (bid.params.demo) { - let demoFields = ['gender', 'country', 'region', 'postal', 'city', 'yob']; - for (let i = 0; i < demoFields.length; i++) { - if (!bid.params.demo[demoFields[i]]) { - continue; - } - params['hb.demo.' + demoFields[i]] = bid.params.demo[demoFields[i]]; - } - } - - requestURL += '#'; - - var paramKeys = Object.keys(params); - - for (var k = 0; k < paramKeys.length; k++) { - var key = paramKeys[k]; - requestURL += key + '=' + params[key] + '&'; - } - - // Expose the callback - $$PREBID_GLOBAL$$.widespaceHandleCB = window[callbackName] = handleCallback; - - adloader.loadScript(requestURL); - } - } - - // Handle our callback - var handleCallback = function handleCallback(bidsArray) { - if (!bidsArray) { return; } - - let bidObject; - let bidCode = 'widespace'; - - for (var i = 0, l = bidsArray.length; i < l; i++) { - const bid = bidsArray[i]; - let placementCode = ''; - let validSizes = []; - - bid.sizes = {height: bid.height, width: bid.width}; - - var inBid = utils.getBidRequest(bid.callbackUid); - - if (inBid) { - bidCode = inBid.bidder; - placementCode = inBid.placementCode; - validSizes = inBid.sizes; - } - - if (bid && bid.callbackUid && bid.status !== 'noad' && verifySize(bid.sizes, validSizes)) { - bidObject = bidfactory.createBid(1); - bidObject.bidderCode = bidCode; - bidObject.cpm = bid.cpm; - bidObject.cur = bid.currency; - bidObject.creative_id = bid.adId; - bidObject.ad = bid.code; - bidObject.width = bid.width; - bidObject.height = bid.height; - bidmanager.addBidResponse(placementCode, bidObject); - } else { - bidObject = bidfactory.createBid(2); - bidObject.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bidObject); - } - } - - function verifySize(bid, validSizes) { - for (var j = 0, k = validSizes.length; j < k; j++) { - if (bid.width === validSizes[j][0] && - bid.height === validSizes[j][1]) { - return true; - } - } - return false; - } - }; - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new WidespaceAdapter(), 'widespace'); - -module.exports = WidespaceAdapter; diff --git a/modules/xhbBidAdapter.js b/modules/xhbBidAdapter.js deleted file mode 100644 index a45bb66bb52..00000000000 --- a/modules/xhbBidAdapter.js +++ /dev/null @@ -1,172 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import { STATUS } from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; -import { loadScript } from 'src/adloader'; - -const XhbAdapter = function XhbAdapter() { - const baseAdapter = new Adapter('xhb'); - let usersync = false; - - const _defaultBidderSettings = { - alwaysUseBid: true, - adserverTargeting: [ - { - key: 'hb_xhb_deal', - val: function (bidResponse) { - return bidResponse.dealId; - } - }, - { - key: 'hb_xhb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, - { - key: 'hb_xhb_size', - val: function (bidResponse) { - return bidResponse.width + 'x' + bidResponse.height; - } - } - ] - }; - bidmanager.registerDefaultBidderSetting('xhb', _defaultBidderSettings); - - baseAdapter.callBids = function (params) { - const anArr = params.bids; - for (let i = 0; i < anArr.length; i++) { - let bidRequest = anArr[i]; - let callbackId = bidRequest.bidId; - loadScript(buildJPTCall(bidRequest, callbackId)); - } - }; - - function buildJPTCall(bid, callbackId) { - // determine tag params - const placementId = utils.getBidIdParameter('placementId', bid.params); - const member = utils.getBidIdParameter('member', bid.params); - const inventoryCode = utils.getBidIdParameter('invCode', bid.params); - let referrer = utils.getBidIdParameter('referrer', bid.params); - const altReferrer = utils.getBidIdParameter('alt_referrer', bid.params); - - // Build tag, always use https - let jptCall = 'https://ib.adnxs.com/jpt?'; - - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleXhbCB'); - jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); - jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); - jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); - jptCall = utils.tryAppendQueryString(jptCall, 'member', member); - jptCall = utils.tryAppendQueryString(jptCall, 'code', inventoryCode); - jptCall = utils.tryAppendQueryString(jptCall, 'traffic_source_code', (utils.getBidIdParameter('trafficSourceCode', bid.params))); - - // sizes takes a bit more logic - let sizeQueryString = ''; - let parsedSizes = utils.parseSizesInput(bid.sizes); - - // combine string into proper querystring for impbus - let parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // first value should be "size" - sizeQueryString = 'size=' + parsedSizes[0]; - if (parsedSizesLength > 1) { - // any subsequent values should be "promo_sizes" - sizeQueryString += '&promo_sizes='; - for (let j = 1; j < parsedSizesLength; j++) { - sizeQueryString += parsedSizes[j] += ','; - } - // remove trailing comma - if (sizeQueryString && sizeQueryString.charAt(sizeQueryString.length - 1) === ',') { - sizeQueryString = sizeQueryString.slice(0, sizeQueryString.length - 1); - } - } - } - - if (sizeQueryString) { - jptCall += sizeQueryString + '&'; - } - - // append referrer - if (referrer === '') { - referrer = utils.getTopWindowUrl(); - } - - jptCall = utils.tryAppendQueryString(jptCall, 'referrer', referrer); - jptCall = utils.tryAppendQueryString(jptCall, 'alt_referrer', altReferrer); - - // remove the trailing "&" - if (jptCall.lastIndexOf('&') === jptCall.length - 1) { - jptCall = jptCall.substring(0, jptCall.length - 1); - } - - return jptCall; - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleXhbCB = function (jptResponseObj) { - let bidCode; - - if (jptResponseObj && jptResponseObj.callback_uid) { - let responseCPM; - const id = jptResponseObj.callback_uid; - let placementCode = ''; - const bidObj = utils.getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; - placementCode = bidObj.placementCode; - - // set the status - bidObj.status = STATUS.GOOD; - } - - let bid = []; - if (jptResponseObj.result && jptResponseObj.result.ad && jptResponseObj.result.ad !== '') { - responseCPM = 0.00; - - // store bid response - // bid status is good (indicating 1) - let adId = jptResponseObj.result.creative_id; - bid = bidfactory.createBid(STATUS.GOOD, bidObj); - bid.creative_id = adId; - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - bid.adUrl = jptResponseObj.result.ad; - bid.width = jptResponseObj.result.width; - bid.height = jptResponseObj.result.height; - bid.dealId = '99999999'; - - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - // indicate that there is no bid for this placement - bid = bidfactory.createBid(STATUS.NO_BID, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } - - if (!usersync) { - let iframe = utils.createInvisibleIframe(); - iframe.src = '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html'; - try { - document.body.appendChild(iframe); - } catch (error) { - utils.logError(error); - } - usersync = true; - } - } - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - buildJPTCall: buildJPTCall - }); -}; - -adaptermanager.registerBidAdapter(new XhbAdapter(), 'xhb'); - -module.exports = XhbAdapter; diff --git a/modules/yieldbotBidAdapter.js b/modules/yieldbotBidAdapter.js deleted file mode 100644 index 4f874a82502..00000000000 --- a/modules/yieldbotBidAdapter.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * @overview Yieldbot sponsored Prebid.js adapter. - * @author elljoh - */ -var adloader = require('src/adloader'); -var bidfactory = require('src/bidfactory'); -var bidmanager = require('src/bidmanager'); -var utils = require('src/utils'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Yieldbot. - * - * @returns {Object} Object containing implementation for invocation in {@link module:adaptermanger.callBids} - * @class - */ -function YieldbotAdapter() { - window.ybotq = window.ybotq || []; - - var ybotlib = { - BID_STATUS: { - PENDING: 0, - AVAILABLE: 1, - EMPTY: 2 - }, - pageLevelOption: false, - /** - * Builds the Yieldbot creative tag. - * - * @param {String} slot - The slot name to bid for - * @param {String} size - The dimenstions of the slot - * @private - */ - buildCreative: function (slot, size) { - return '' + - ''; - }, - /** - * Bid response builder. - * - * @param {Object} slotCriteria - Yieldbot bid criteria - * @private - */ - buildBid: function (slotCriteria) { - var bid = {}; - - if (slotCriteria && slotCriteria.ybot_ad && slotCriteria.ybot_ad !== 'n') { - bid = bidfactory.createBid(ybotlib.BID_STATUS.AVAILABLE); - - bid.cpm = parseInt(slotCriteria.ybot_cpm) / 100.0 || 0; // Yieldbot CPM bids are in cents - - var szArr = slotCriteria.ybot_size ? slotCriteria.ybot_size.split('x') : [0, 0]; - var slot = slotCriteria.ybot_slot || ''; - var sizeStr = slotCriteria.ybot_size || ''; // Creative template needs the dimensions string - - bid.width = szArr[0] || 0; - bid.height = szArr[1] || 0; - - bid.ad = ybotlib.buildCreative(slot, sizeStr); - - // Add Yieldbot parameters to allow publisher bidderSettings.yieldbot specific targeting - for (var k in slotCriteria) { - bid[k] = slotCriteria[k]; - } - } else { - bid = bidfactory.createBid(ybotlib.BID_STATUS.EMPTY); - } - - bid.bidderCode = 'yieldbot'; - return bid; - }, - /** - * Unique'ify slot sizes for a Yieldbot bid request
- * Bids may refer to a slot and dimension multiple times on a page, but should exist once in the request. - * @param {Array} sizes An array of sizes to deduplicate - * @private - */ - getUniqueSlotSizes: function(sizes) { - var newSizes = []; - var hasSize = {}; - if (utils.isArray(sizes)) { - for (var idx = 0; idx < sizes.length; idx++) { - var bidSize = sizes[idx] || ''; - if (bidSize && utils.isStr(bidSize) && !hasSize[bidSize]) { - var nSize = bidSize.split('x'); - if (nSize.length > 1) { - newSizes.push([nSize[0], nSize[1]]); - } - hasSize[bidSize] = true; - } - } - } - return newSizes; - }, - /** - * Yieldbot implementation of {@link module:adaptermanger.callBids} - * @param {Object} params - Adapter bid configuration object - * @private - */ - callBids: function (params) { - var bids = params.bids || []; - var ybotq = window.ybotq || []; - - ybotlib.pageLevelOption = false; - - ybotq.push(function () { - var yieldbot = window.yieldbot; - // Empty defined slot bids object - ybotlib.bids = {}; - ybotlib.parsedBidSizes = {}; - // Iterate through bids to obtain Yieldbot slot config - // - Slot config can be different between initial and refresh requests - var psn = 'ERROR_PREBID_DEFINE_YB_PSN'; - var slots = {}; - utils._each(bids, function (v) { - var bid = v; - // bidder params config: http://prebid.org/dev-docs/bidders/yieldbot.html - // - last psn wins - psn = bid.params && bid.params.psn ? bid.params.psn : psn; - var slotName = bid.params && bid.params.slot ? bid.params.slot : 'ERROR_PREBID_DEFINE_YB_SLOT'; - var parsedSizes = utils.parseSizesInput(bid.sizes) || []; - slots[slotName] = slots[slotName] || []; - slots[slotName] = slots[slotName].concat(parsedSizes); - ybotlib.bids[bid.bidId] = bid; - ybotlib.parsedBidSizes[bid.bidId] = parsedSizes; - }); - - for (var bidSlots in slots) { - if (slots.hasOwnProperty(bidSlots)) { - // The same slot name and size may be used for multiple bids. Get unique sizes - // for the request. - slots[bidSlots] = ybotlib.getUniqueSlotSizes(slots[bidSlots]); - } - } - - if (yieldbot._initialized !== true) { - yieldbot.pub(psn); - for (var slotName in slots) { - if (slots.hasOwnProperty(slotName)) { - yieldbot.defineSlot(slotName, { sizes: slots[slotName] }); - } - } - yieldbot.enableAsync(); - yieldbot.go(); - } else if (!utils.isEmpty(slots)) { - yieldbot.nextPageview(slots); - } - }); - - ybotq.push(function () { - ybotlib.handleUpdateState(); - }); - adloader.loadScript('//cdn.yldbt.com/js/yieldbot.intent.js', null, true); - }, - /** - * Yieldbot bid request callback handler. - * - * @see {@link YieldbotAdapter~_callBids} - * @private - */ - handleUpdateState: function () { - var yieldbot = window.yieldbot; - var slotUsed = {}; - - for (var bidId in ybotlib.bids) { - if (ybotlib.bids.hasOwnProperty(bidId)) { - var bidRequest = ybotlib.bids[bidId] || null; - - if (bidRequest && bidRequest.params && bidRequest.params.slot) { - var placementCode = bidRequest.placementCode || 'ERROR_YB_NO_PLACEMENT'; - var criteria = yieldbot.getSlotCriteria(bidRequest.params.slot); - var requestedSizes = ybotlib.parsedBidSizes[bidId] || []; - - var slotSizeOk = false; - for (var idx = 0; idx < requestedSizes.length; idx++) { - var requestedSize = requestedSizes[idx]; - - if (!slotUsed[criteria.ybot_slot] && requestedSize === criteria.ybot_size) { - slotSizeOk = true; - slotUsed[criteria.ybot_slot] = true; - break; - } - } - var bid = ybotlib.buildBid(slotSizeOk ? criteria : { ybot_ad: 'n' }); - bidmanager.addBidResponse(placementCode, bid); - } - } - } - } - }; - return { - callBids: ybotlib.callBids, - getUniqueSlotSizes: ybotlib.getUniqueSlotSizes - }; -} - -adaptermanager.registerBidAdapter(new YieldbotAdapter(), 'yieldbot'); - -module.exports = YieldbotAdapter; diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js deleted file mode 100644 index b7a5ceda08c..00000000000 --- a/modules/yieldmoBidAdapter.js +++ /dev/null @@ -1,151 +0,0 @@ -var utils = require('src/utils.js'); -var adloader = require('src/adloader.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Yieldmo. - * - * @returns {{callBids: _callBids}} - * @constructor - */ - -var YieldmoAdapter = function YieldmoAdapter() { - function _callBids(params) { - var bids = params.bids; - adloader.loadScript(buildYieldmoCall(bids)); - } - - function buildYieldmoCall(bids) { - // build our base tag, based on if we are http or https - var ymURI = '//ads.yieldmo.com/exchange/prebid?'; - var ymCall = document.location.protocol + ymURI; - - // Placement specific information - ymCall = _appendPlacementInformation(ymCall, bids); - - // General impression params - ymCall = _appendImpressionInformation(ymCall); - - // remove the trailing "&" - if (ymCall.lastIndexOf('&') === ymCall.length - 1) { - ymCall = ymCall.substring(0, ymCall.length - 1); - } - - utils.logMessage('ymCall request built: ' + ymCall); - - return ymCall; - } - - function _appendPlacementInformation(url, bids) { - var placements = []; - var placement; - var bid; - - for (var i = 0; i < bids.length; i++) { - bid = bids[i]; - - placement = {}; - placement.callback_id = bid.bidId; - placement.placement_id = bid.placementCode; - placement.sizes = bid.sizes; - - if (bid.params && bid.params.placementId) { - placement.ym_placement_id = bid.params.placementId; - } - - placements.push(placement); - } - - url = utils.tryAppendQueryString(url, 'p', JSON.stringify(placements)); - return url; - } - - function _appendImpressionInformation(url) { - var page_url = document.location; // page url - var pr = document.referrer || ''; // page's referrer - var dnt = (navigator.doNotTrack || false).toString(); // true if user enabled dnt (false by default) - var _s = document.location.protocol === 'https:' ? 1 : 0; // 1 if page is secure - var description = _getPageDescription(); - var title = document.title || ''; // Value of the title from the publisher's page. - var bust = new Date().getTime().toString(); // cache buster - var scrd = window.devicePixelRatio || 0; // screen pixel density - - url = utils.tryAppendQueryString(url, 'callback', '$$PREBID_GLOBAL$$.YMCB'); - url = utils.tryAppendQueryString(url, 'page_url', page_url); - url = utils.tryAppendQueryString(url, 'pr', pr); - url = utils.tryAppendQueryString(url, 'bust', bust); - url = utils.tryAppendQueryString(url, '_s', _s); - url = utils.tryAppendQueryString(url, 'scrd', scrd); - url = utils.tryAppendQueryString(url, 'dnt', dnt); - url = utils.tryAppendQueryString(url, 'description', description); - url = utils.tryAppendQueryString(url, 'title', title); - - return url; - } - - function _getPageDescription() { - if (document.querySelector('meta[name="description"]')) { - return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. - } else { - return ''; - } - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.YMCB = function(ymResponses) { - if (ymResponses && ymResponses.constructor === Array && ymResponses.length > 0) { - for (var i = 0; i < ymResponses.length; i++) { - _registerPlacementBid(ymResponses[i]); - } - } else { - // If an incorrect response is returned, register error bids for all placements - // to prevent Prebid waiting till timeout for response - _registerNoResponseBids(); - - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - } - }; - - function _registerPlacementBid(response) { - var bidObj = utils.getBidRequest(response.callback_id); - var placementCode = bidObj && bidObj.placementCode; - var bid = []; - - if (response && response.cpm && response.cpm !== 0) { - bid = bidfactory.createBid(1, bidObj); - bid.bidderCode = 'yieldmo'; - bid.cpm = response.cpm; - bid.ad = response.ad; - bid.width = response.width; - bid.height = response.height; - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - if (bidObj) { utils.logMessage('No prebid response from yieldmo for placementCode: ' + bidObj.placementCode); } - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = 'yieldmo'; - bidmanager.addBidResponse(placementCode, bid); - } - } - - function _registerNoResponseBids() { - var yieldmoBidRequests = $$PREBID_GLOBAL$$._bidsRequested.find(bid => bid.bidderCode === 'yieldmo'); - - utils._each(yieldmoBidRequests.bids, function (currentBid) { - var bid = []; - bid = bidfactory.createBid(2, currentBid); - bid.bidderCode = 'yieldmo'; - bidmanager.addBidResponse(currentBid.placementCode, bid); - }); - } - - return Object.assign(this, { - callBids: _callBids - }); -}; - -adaptermanager.registerBidAdapter(new YieldmoAdapter(), 'yieldmo'); - -module.exports = YieldmoAdapter; diff --git a/package.json b/package.json index 99558bec6e9..61c9edf2b82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "0.34.1", + "version": "1.0.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { diff --git a/src/adaptermanager.js b/src/adaptermanager.js index b463f7abe8b..95db1e74b2a 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -1,9 +1,12 @@ /** @module adaptermanger */ import { flatten, getBidderCodes, getDefinedParams, shuffle } from './utils'; -import { mapSizes } from './sizeMapping'; +import { resolveStatus } from './sizeMapping'; import { processNativeAdUnitParams, nativeAdapters } from './native'; import { newBidder } from './adapters/bidderFactory'; +import { ajaxBuilder } from 'src/ajax'; +import { config, RANDOM } from 'src/config'; +import includes from 'core-js/library/fn/array/includes'; var utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); @@ -13,100 +16,149 @@ let s2sTestingModule; // store s2sTesting module if it's loaded var _bidderRegistry = {}; exports.bidderRegistry = _bidderRegistry; -// create s2s settings objectType_function -let _s2sConfig = { - endpoint: CONSTANTS.S2S.DEFAULT_ENDPOINT, - adapter: CONSTANTS.S2S.ADAPTER, - syncEndpoint: CONSTANTS.S2S.SYNC_ENDPOINT -}; +let _s2sConfig = {}; +config.getConfig('s2sConfig', config => { + _s2sConfig = config.s2sConfig; +}); -const RANDOM = 'random'; -const FIXED = 'fixed'; +var _analyticsRegistry = {}; -const VALID_ORDERS = {}; -VALID_ORDERS[RANDOM] = true; -VALID_ORDERS[FIXED] = true; +/** + * @typedef {object} LabelDescriptor + * @property {boolean} labelAll describes whether or not this object expects all labels to match, or any label to match + * @property {Array} labels the labels listed on the bidder or adUnit + * @property {Array} activeLabels the labels specified as being active by requestBids + */ + +/** + * Returns object describing the status of labels on the adUnit or bidder along with labels passed into requestBids + * @param bidOrAdUnit the bidder or adUnit to get label info on + * @param activeLabels the labels passed to requestBids + * @returns {LabelDescriptor} + */ +function getLabels(bidOrAdUnit, activeLabels) { + if (bidOrAdUnit.labelAll) { + return {labelAll: true, labels: bidOrAdUnit.labelAll, activeLabels}; + } + return {labelAll: false, labels: bidOrAdUnit.labelAny, activeLabels}; +} -var _analyticsRegistry = {}; -let _bidderSequence = RANDOM; - -function getBids({bidderCode, requestId, bidderRequestId, adUnits}) { - return adUnits.map(adUnit => { - return adUnit.bids.filter(bid => bid.bidder === bidderCode) - .map(bid => { - let sizes = adUnit.sizes; - if (adUnit.sizeMapping) { - let sizeMapping = mapSizes(adUnit); - if (sizeMapping === '') { - return ''; +function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { + return adUnits.reduce((result, adUnit) => { + let {active, sizes: filteredAdUnitSizes} = resolveStatus(getLabels(adUnit, labels), adUnit.sizes); + + if (active) { + result.push(adUnit.bids.filter(bid => bid.bidder === bidderCode) + .reduce((bids, bid) => { + if (adUnit.mediaTypes) { + if (utils.isValidMediaTypes(adUnit.mediaTypes)) { + bid = Object.assign({}, bid, {mediaTypes: adUnit.mediaTypes}); + } else { + utils.logError( + `mediaTypes is not correctly configured for adunit ${adUnit.code}` + ); + } } - sizes = sizeMapping; - } - if (adUnit.mediaTypes) { - if (utils.isValidMediaTypes(adUnit.mediaTypes)) { - bid = Object.assign({}, bid, { mediaTypes: adUnit.mediaTypes }); - } else { - utils.logError( - `mediaTypes is not correctly configured for adunit ${adUnit.code}` - ); + const nativeParams = + adUnit.nativeParams || utils.deepAccess(adUnit, 'mediaTypes.native'); + if (nativeParams) { + bid = Object.assign({}, bid, { + nativeParams: processNativeAdUnitParams(nativeParams), + }); } - } - const nativeParams = - adUnit.nativeParams || utils.deepAccess(adUnit, 'mediaTypes.native'); - if (nativeParams) { - bid = Object.assign({}, bid, { - nativeParams: processNativeAdUnitParams(nativeParams), - }); - } - - bid = Object.assign({}, bid, getDefinedParams(adUnit, [ - 'mediaType', - 'renderer' - ])); - - return Object.assign({}, bid, { - placementCode: adUnit.code, - transactionId: adUnit.transactionId, - sizes: sizes, - bidId: bid.bid_id || utils.getUniqueIdentifierStr(), - bidderRequestId, - requestId - }); - } + bid = Object.assign({}, bid, getDefinedParams(adUnit, [ + 'mediaType', + 'renderer' + ])); + + let {active, sizes} = resolveStatus(getLabels(bid, labels), filteredAdUnitSizes); + + if (active) { + bids.push(Object.assign({}, bid, { + adUnitCode: adUnit.code, + transactionId: adUnit.transactionId, + sizes: sizes, + bidId: bid.bid_id || utils.getUniqueIdentifierStr(), + bidderRequestId, + auctionId + })); + } + return bids; + }, []) ); - }).reduce(flatten, []).filter(val => val !== ''); + } + return result; + }, []).reduce(flatten, []).filter(val => val !== ''); +} + +function transformHeightWidth(adUnit) { + let sizesObj = []; + let sizes = utils.parseSizesInput(adUnit.sizes); + sizes.forEach(size => { + let heightWidth = size.split('x'); + let sizeObj = { + 'w': parseInt(heightWidth[0]), + 'h': parseInt(heightWidth[1]) + }; + sizesObj.push(sizeObj); + }); + return sizesObj; +} + +function getAdUnitCopyForPrebidServer(adUnits) { + let adaptersServerSide = _s2sConfig.bidders; + let adUnitsCopy = utils.deepClone(adUnits); + + adUnitsCopy.forEach((adUnit) => { + adUnit.sizes = transformHeightWidth(adUnit); + + // filter out client side bids + adUnit.bids = adUnit.bids.filter((bid) => { + return includes(adaptersServerSide, bid.bidder) && (!doingS2STesting() || bid.finalSource !== s2sTestingModule.CLIENT); + }).map((bid) => { + bid.bid_id = utils.getUniqueIdentifierStr(); + return bid; + }); + }); + + // don't send empty requests + adUnitsCopy = adUnitsCopy.filter(adUnit => { + return adUnit.bids.length !== 0; + }); + return adUnitsCopy; } -exports.callBids = ({adUnits, cbTimeout}) => { - const requestId = utils.generateUUID(); - const auctionStart = Date.now(); +function getAdUnitCopyForClientAdapters(adUnits) { + let adUnitsClientCopy = utils.deepClone(adUnits); + // filter out s2s bids + adUnitsClientCopy.forEach((adUnit) => { + adUnit.bids = adUnit.bids.filter((bid) => { + return !doingS2STesting() || bid.finalSource !== s2sTestingModule.SERVER; + }) + }); + + // don't send empty requests + adUnitsClientCopy = adUnitsClientCopy.filter(adUnit => { + return adUnit.bids.length !== 0; + }); - const auctionInit = { - timestamp: auctionStart, - requestId, - timeout: cbTimeout - }; - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); + return adUnitsClientCopy; +} +exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, labels) { + let bidRequests = []; let bidderCodes = getBidderCodes(adUnits); - if (_bidderSequence === RANDOM) { + if (config.getConfig('bidderSequence') === RANDOM) { bidderCodes = shuffle(bidderCodes); } - const s2sAdapter = _bidderRegistry[_s2sConfig.adapter]; - if (s2sAdapter) { - s2sAdapter.setConfig(_s2sConfig); - s2sAdapter.queueSync({bidderCodes}); - } - + let clientBidderCodes = bidderCodes; let clientTestAdapters = []; - let s2sTesting = false; if (_s2sConfig.enabled) { // if s2sConfig.bidderControl testing is turned on - s2sTesting = _s2sConfig.testing && typeof s2sTestingModule !== 'undefined'; - if (s2sTesting) { + if (doingS2STesting()) { // get all adapters doing client testing clientTestAdapters = s2sTestingModule.getSourceBidderMap(adUnits)[s2sTestingModule.CLIENT]; } @@ -115,124 +167,125 @@ exports.callBids = ({adUnits, cbTimeout}) => { let adaptersServerSide = _s2sConfig.bidders; // don't call these client side (unless client request is needed for testing) - bidderCodes = bidderCodes.filter((elm) => { - return !adaptersServerSide.includes(elm) || clientTestAdapters.includes(elm); - }); - let adUnitsS2SCopy = utils.deepClone(adUnits); - - // filter out client side bids - adUnitsS2SCopy.forEach((adUnit) => { - if (adUnit.sizeMapping) { - adUnit.sizes = mapSizes(adUnit); - delete adUnit.sizeMapping; - } - adUnit.sizes = transformHeightWidth(adUnit); - adUnit.bids = adUnit.bids.filter((bid) => { - return adaptersServerSide.includes(bid.bidder) && (!s2sTesting || bid.finalSource !== s2sTestingModule.CLIENT); - }).map((bid) => { - bid.bid_id = utils.getUniqueIdentifierStr(); - return bid; - }); - }); - - // don't send empty requests - adUnitsS2SCopy = adUnitsS2SCopy.filter(adUnit => { - return adUnit.bids.length !== 0; + clientBidderCodes = bidderCodes.filter((elm) => { + return !includes(adaptersServerSide, elm) || includes(clientTestAdapters, elm); }); + let adUnitsS2SCopy = getAdUnitCopyForPrebidServer(adUnits); let tid = utils.generateUUID(); adaptersServerSide.forEach(bidderCode => { const bidderRequestId = utils.getUniqueIdentifierStr(); const bidderRequest = { bidderCode, - requestId, + auctionId, bidderRequestId, tid, - bids: getBids({bidderCode, requestId, bidderRequestId, 'adUnits': adUnitsS2SCopy}), - start: new Date().getTime(), + bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsS2SCopy, labels}), auctionStart: auctionStart, timeout: _s2sConfig.timeout, src: CONSTANTS.S2S.SRC }; if (bidderRequest.bids.length !== 0) { - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidderRequest); + bidRequests.push(bidderRequest); } }); + } - let s2sBidRequest = {tid, 'ad_units': adUnitsS2SCopy}; - utils.logMessage(`CALLING S2S HEADER BIDDERS ==== ${adaptersServerSide.join(',')}`); - if (s2sBidRequest.ad_units.length) { - s2sAdapter.callBids(s2sBidRequest); + // client adapters + let adUnitsClientCopy = getAdUnitCopyForClientAdapters(adUnits); + clientBidderCodes.forEach(bidderCode => { + const bidderRequestId = utils.getUniqueIdentifierStr(); + const bidderRequest = { + bidderCode, + auctionId, + bidderRequestId, + bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsClientCopy, labels}), + auctionStart: auctionStart, + timeout: cbTimeout + }; + if (bidderRequest.bids && bidderRequest.bids.length !== 0) { + bidRequests.push(bidderRequest); } + }); + return bidRequests; +}; + +exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { + if (!bidRequests.length) { + utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); + return; } - let _bidderRequests = []; - // client side adapters - let adUnitsClientCopy = utils.deepClone(adUnits); - // filter out s2s bids - adUnitsClientCopy.forEach((adUnit) => { - adUnit.bids = adUnit.bids.filter((bid) => { - return !s2sTesting || bid.finalSource !== s2sTestingModule.SERVER; - }) - }); + let ajax = ajaxBuilder(bidRequests[0].timeout); - // don't send empty requests - adUnitsClientCopy = adUnitsClientCopy.filter(adUnit => { - return adUnit.bids.length !== 0; - }); + let [clientBidRequests, serverBidRequests] = bidRequests.reduce((partitions, bidRequest) => { + partitions[Number(typeof bidRequest.src !== 'undefined' && bidRequest.src === CONSTANTS.S2S.SRC)].push(bidRequest); + return partitions; + }, [[], []]); - bidderCodes.forEach(bidderCode => { - const adapter = _bidderRegistry[bidderCode]; - if (adapter) { - const bidderRequestId = utils.getUniqueIdentifierStr(); - const bidderRequest = { - bidderCode, - requestId, - bidderRequestId, - bids: getBids({bidderCode, requestId, bidderRequestId, 'adUnits': adUnitsClientCopy}), - auctionStart: auctionStart, - timeout: cbTimeout - }; + if (serverBidRequests.length) { + let adaptersServerSide = _s2sConfig.bidders; + const s2sAdapter = _bidderRegistry[_s2sConfig.adapter]; + let tid = serverBidRequests[0].tid; + + if (s2sAdapter) { + let s2sBidRequest = {tid, 'ad_units': getAdUnitCopyForPrebidServer(adUnits)}; + if (s2sBidRequest.ad_units.length) { + let doneCbs = serverBidRequests.map(bidRequest => { + bidRequest.doneCbCallCount = 0; + return doneCb(bidRequest.bidderRequestId) + }); - if (bidderRequest.bids && bidderRequest.bids.length !== 0) { - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - _bidderRequests.push(bidderRequest); + // only log adapters that actually have adUnit bids + let allBidders = s2sBidRequest.ad_units.reduce((adapters, adUnit) => { + return adapters.concat((adUnit.bids || []).reduce((adapters, bid) => { return adapters.concat(bid.bidder) }, [])); + }, []); + utils.logMessage(`CALLING S2S HEADER BIDDERS ==== ${adaptersServerSide.filter(adapter => { + return includes(allBidders, adapter); + }).join(',')}`); + + // fire BID_REQUESTED event for each s2s bidRequest + serverBidRequests.forEach(bidRequest => { + events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); + }); + + // make bid requests + s2sAdapter.callBids( + s2sBidRequest, + serverBidRequests, + addBidResponse, + () => doneCbs.forEach(done => done()), + ajax + ); } - } else { - utils.logError(`Adapter trying to be called which does not exist: ${bidderCode} adaptermanager.callBids`); } - }); + } - _bidderRequests.forEach(bidRequest => { + // handle client adapter requests + clientBidRequests.forEach(bidRequest => { bidRequest.start = new Date().getTime(); + // TODO : Do we check for bid in pool from here and skip calling adapter again ? const adapter = _bidderRegistry[bidRequest.bidderCode]; - if (bidRequest.bids && bidRequest.bids.length !== 0) { + if (adapter) { utils.logMessage(`CALLING BIDDER ======= ${bidRequest.bidderCode}`); events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); - adapter.callBids(bidRequest); + bidRequest.doneCbCallCount = 0; + let done = doneCb(bidRequest.bidderRequestId); + adapter.callBids(bidRequest, addBidResponse, done, ajax); + } else { + utils.logError(`Adapter trying to be called which does not exist: ${bidRequest.bidderCode} adaptermanager.callBids`); } - }) -}; - -function transformHeightWidth(adUnit) { - let sizesObj = []; - let sizes = utils.parseSizesInput(adUnit.sizes); - sizes.forEach(size => { - let heightWidth = size.split('x'); - let sizeObj = { - 'w': parseInt(heightWidth[0]), - 'h': parseInt(heightWidth[1]) - }; - sizesObj.push(sizeObj); }); - return sizesObj; +} + +function doingS2STesting() { + return _s2sConfig && _s2sConfig.enabled && _s2sConfig.testing && s2sTestingModule; } function getSupportedMediaTypes(bidderCode) { let result = []; - if (exports.videoAdapters.includes(bidderCode)) result.push('video'); - if (nativeAdapters.includes(bidderCode)) result.push('native'); + if (includes(exports.videoAdapters, bidderCode)) result.push('video'); + if (includes(nativeAdapters, bidderCode)) result.push('native'); return result; } @@ -243,10 +296,10 @@ exports.registerBidAdapter = function (bidAdaptor, bidderCode, {supportedMediaTy if (typeof bidAdaptor.callBids === 'function') { _bidderRegistry[bidderCode] = bidAdaptor; - if (supportedMediaTypes.includes('video')) { + if (includes(supportedMediaTypes, 'video')) { exports.videoAdapters.push(bidderCode); } - if (supportedMediaTypes.includes('native')) { + if (includes(supportedMediaTypes, 'native')) { nativeAdapters.push(bidderCode); } } else { @@ -319,22 +372,10 @@ exports.enableAnalytics = function (config) { }); }; -exports.setBidderSequence = function (order) { - if (VALID_ORDERS[order]) { - _bidderSequence = order; - } else { - utils.logWarn(`Invalid order: ${order}. Bidder Sequence was not set.`); - } -}; - exports.getBidAdapter = function(bidder) { return _bidderRegistry[bidder]; }; -exports.setS2SConfig = function (config) { - _s2sConfig = config; -}; - // 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 exports.setS2STestingModule = function (module) { diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 7535d6ad613..ed3cc28db32 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -1,13 +1,14 @@ import Adapter from 'src/adapter'; import adaptermanager from 'src/adaptermanager'; import { config } from 'src/config'; -import { ajax } from 'src/ajax'; -import bidmanager from 'src/bidmanager'; import bidfactory from 'src/bidfactory'; import { STATUS } from 'src/constants'; import { userSync } from 'src/userSync'; +import { nativeBidIsValid } from 'src/native'; +import { isValidVideoBid } from 'src/video'; +import includes from 'core-js/library/fn/array/includes'; -import { logWarn, logError, parseQueryStringParameters, delayExecution } from 'src/utils'; +import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest } from 'src/utils'; /** * This file aims to support Adapters during the Prebid 0.x -> 1.x transition. @@ -155,47 +156,24 @@ export function newBidder(spec) { return Object.freeze(spec); }, registerSyncs, - callBids: function(bidderRequest) { + callBids: function(bidderRequest, addBidResponse, done, ajax) { if (!Array.isArray(bidderRequest.bids)) { return; } - // callBids must add a NO_BID response for _every_ AdUnit code, in order for the auction to - // end properly. This map stores placement codes which we've made _real_ bids on. - // - // As we add _real_ bids to the bidmanager, we'll log the ad unit codes here too. Once all the real - // bids have been added, fillNoBids() can be called to add NO_BID bids for any extra ad units, which - // will end the auction. - // - // In Prebid 1.0, this will be simplified to use the `addBidResponse` and `done` callbacks. const adUnitCodesHandled = {}; function addBidWithCode(adUnitCode, bid) { adUnitCodesHandled[adUnitCode] = true; - addBid(adUnitCode, bid); - } - function fillNoBids() { - bidderRequest.bids - .map(bidRequest => bidRequest.placementCode) - .forEach(adUnitCode => { - if (adUnitCode && !adUnitCodesHandled[adUnitCode]) { - addBid(adUnitCode, newEmptyBid()); - } - }); - } - - function addBid(code, bid) { - try { - bidmanager.addBidResponse(code, bid); - } catch (err) { - logError('Error adding bid', code, err); + if (isValid(adUnitCode, bid, [bidderRequest])) { + addBidResponse(adUnitCode, bid); } } - // After all the responses have come back, fill up the "no bid" bids and + // After all the responses have come back, call done() and // register any required usersync pixels. const responses = []; function afterAllResponses() { - fillNoBids(); + done(); registerSyncs(responses); } @@ -222,7 +200,7 @@ export function newBidder(spec) { requests = [requests]; } - // Callbacks don't compose as nicely as Promises. We should call fillNoBids() once _all_ the + // 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(afterAllResponses, requests.length) @@ -274,7 +252,7 @@ export function newBidder(spec) { // 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 fillNoBids(). + // sure to call the `onResponse` function so that we're one step closer to calling done(). function onSuccess(response, responseObj) { try { response = JSON.parse(response); @@ -306,17 +284,12 @@ export function newBidder(spec) { onResponse(); function addBidUsingRequestMap(bid) { - // In Prebid 1.0 all the validation logic from bidmanager will move here, as of now we are only validating new params so that adapters dont miss adding them. - if (hasValidKeys(bid)) { - const bidRequest = bidRequestMap[bid.requestId]; - if (bidRequest) { - const prebidBid = Object.assign(bidfactory.createBid(STATUS.GOOD, bidRequest), bid); - addBidWithCode(bidRequest.placementCode, prebidBid); - } else { - logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bid.requestId}. Ignoring.`); - } + const bidRequest = bidRequestMap[bid.requestId]; + if (bidRequest) { + const prebidBid = Object.assign(bidfactory.createBid(STATUS.GOOD, bidRequest), bid); + addBidWithCode(bidRequest.adUnitCode, prebidBid); } else { - logError(`Bidder ${spec.code} is missing required params. Check http://prebid.org/dev-docs/bidder-adapter-1.html for list of params.`); + logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bid.requestId}. Ignoring.`); } } @@ -328,7 +301,7 @@ export function newBidder(spec) { } // 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 fillNoBids(). + // call onResponse() so that we're one step closer to calling done(). function onFailure(err) { logError(`Server call for ${spec.code} failed: ${err}. Continuing without bids.`); onResponse(); @@ -361,16 +334,69 @@ export function newBidder(spec) { } return true; } +} + +// check that the bid has a width and height set +function validBidSize(adUnitCode, bid, bidRequests) { + if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) { + return true; + } + + const adUnit = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); + + 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 + // response that does not explicitly set width or height + if (parsedSizes.length === 1) { + const [ width, height ] = parsedSizes[0].split('x'); + bid.width = width; + bid.height = height; + return true; + } - function hasValidKeys(bid) { + return false; +} + +// Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. +export function isValid(adUnitCode, bid, bidRequests) { + function hasValidKeys() { let bidKeys = Object.keys(bid); - return COMMON_BID_RESPONSE_KEYS.every(key => bidKeys.includes(key)); + return COMMON_BID_RESPONSE_KEYS.every(key => includes(bidKeys, key)); + } + + function errorMessage(msg) { + return `Invalid bid from ${bid.bidderCode}. Ignoring bid: ${msg}`; } - function newEmptyBid() { - const bid = bidfactory.createBid(STATUS.NO_BID); - bid.code = spec.code; - bid.bidderCode = spec.code; - return bid; + if (!adUnitCode) { + logWarn('No adUnitCode was supplied to addBidResponse.'); + return false; } + + if (!bid) { + logWarn(`Some adapter tried to add an undefined bid for ${adUnitCode}.`); + return false; + } + + if (!hasValidKeys()) { + logError(errorMessage(`Bidder ${bid.bidderCode} is missing required params. Check http://prebid.org/dev-docs/bidder-adapter-1.html for list of params.`)); + return false; + } + + if (bid.mediaType === 'native' && !nativeBidIsValid(bid, bidRequests)) { + logError(errorMessage('Native bid missing some required properties.')); + return false; + } + 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, bidRequests)) { + logError(errorMessage(`Banner bids require a width and height`)); + return false; + } + + return true; } diff --git a/src/adserver.js b/src/adserver.js index 55f4ee9b44f..cfde042e46e 100644 --- a/src/adserver.js +++ b/src/adserver.js @@ -1,12 +1,12 @@ -import {formatQS} from './url'; -import {getWinningBids} from './targeting'; +import { formatQS } from './url'; +import { targeting } from './targeting'; // Adserver parent class const AdServer = function(attr) { this.name = attr.adserver; this.code = attr.code; this.getWinningBidByCode = function() { - return getWinningBids(this.code)[0]; + return targeting.getWinningBids(this.code)[0]; }; }; diff --git a/src/ajax.js b/src/ajax.js index 44ff00a0fe0..19dc1b3869f 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -3,7 +3,6 @@ import {parse as parseURL, format as formatURL} from './url'; var utils = require('./utils'); const XHR_DONE = 4; -let _timeout = 3000; /** * Simple IE9+ and cross-browser ajax request function @@ -14,91 +13,94 @@ let _timeout = 3000; * @param data mixed data * @param options object */ -export function setAjaxTimeout(timeout) { - _timeout = timeout; -} +export const ajax = ajaxBuilder(); -export function ajax(url, callback, data, options = {}) { - try { - let x; - let useXDomainRequest = false; - let method = options.method || (data ? 'POST' : 'GET'); +export function ajaxBuilder(timeout = 3000) { + return function(url, callback, data, options = {}) { + try { + let x; + let useXDomainRequest = false; + let method = options.method || (data ? 'POST' : 'GET'); - let callbacks = typeof callback === 'object' ? callback : { - success: function() { - utils.logMessage('xhr success'); - }, - error: function(e) { - utils.logError('xhr error', null, e); - } - }; + let callbacks = typeof callback === 'object' ? callback : { + success: function() { + utils.logMessage('xhr success'); + }, + error: function(e) { + utils.logError('xhr error', null, e); + } + }; - if (typeof callback === 'function') { - callbacks.success = callback; - } + if (typeof callback === 'function') { + callbacks.success = callback; + } - if (!window.XMLHttpRequest) { - useXDomainRequest = true; - } else { - x = new window.XMLHttpRequest(); - if (x.responseType === undefined) { + if (!window.XMLHttpRequest) { useXDomainRequest = true; + } else { + x = new window.XMLHttpRequest(); + if (x.responseType === undefined) { + useXDomainRequest = true; + } } - } - if (useXDomainRequest) { - x = new window.XDomainRequest(); - x.onload = function () { - callbacks.success(x.responseText, x); - }; + if (useXDomainRequest) { + x = new window.XDomainRequest(); + x.onload = function () { + callbacks.success(x.responseText, x); + }; - // http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 - x.onerror = function () { - callbacks.error('error', x); - }; - x.ontimeout = function () { - callbacks.error('timeout', x); - }; - x.onprogress = function() { - utils.logMessage('xhr onprogress'); - }; - } else { - x.onreadystatechange = function () { - if (x.readyState === XHR_DONE) { - let status = x.status; - if ((status >= 200 && status < 300) || status === 304) { - callbacks.success(x.responseText, x); - } else { - callbacks.error(x.statusText, x); + // http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 + x.onerror = function () { + callbacks.error('error', x); + }; + x.ontimeout = function () { + callbacks.error('timeout', x); + }; + x.onprogress = function() { + utils.logMessage('xhr onprogress'); + }; + } else { + x.onreadystatechange = function () { + if (x.readyState === XHR_DONE) { + let status = x.status; + if ((status >= 200 && status < 300) || status === 304) { + callbacks.success(x.responseText, x); + } else { + callbacks.error(x.statusText, x); + } } - } - }; - } + }; + x.ontimeout = function () { + utils.logError(' xhr timeout after ', x.timeout, 'ms'); + }; + } - if (method === 'GET' && data) { - let urlInfo = parseURL(url, options); - Object.assign(urlInfo.search, data); - url = formatURL(urlInfo); - } + if (method === 'GET' && data) { + let urlInfo = parseURL(url, options); + Object.assign(urlInfo.search, data); + url = formatURL(urlInfo); + } - x.open(method, url); - // IE needs timoeut to be set after open - see #1410 - x.timeout = _timeout; + x.open(method, url); + // IE needs timoeut to be set after open - see #1410 + x.timeout = timeout; - if (!useXDomainRequest) { - if (options.withCredentials) { - x.withCredentials = true; - } - utils._each(options.customHeaders, (value, header) => { - x.setRequestHeader(header, value); - }); - if (options.preflight) { - x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + if (!useXDomainRequest) { + if (options.withCredentials) { + x.withCredentials = true; + } + utils._each(options.customHeaders, (value, header) => { + x.setRequestHeader(header, value); + }); + if (options.preflight) { + x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + } + x.setRequestHeader('Content-Type', options.contentType || 'text/plain'); } - x.setRequestHeader('Content-Type', options.contentType || 'text/plain'); + x.send(method === 'POST' && data); + } catch (error) { + utils.logError('xhr construction', error); } - x.send(method === 'POST' && data); - } catch (error) { - utils.logError('xhr construction', error); } } diff --git a/src/auction.js b/src/auction.js new file mode 100644 index 00000000000..82aaa88cf56 --- /dev/null +++ b/src/auction.js @@ -0,0 +1,506 @@ +/** + * Module for auction instances. + * + * In Prebid 0.x, $$PREBID_GLOBAL$$ had _bidsRequested and _bidsReceived as public properties. + * Starting 1.0, Prebid will support concurrent auctions. Each auction instance will store private properties, bidsRequested and bidsReceived. + * + * AuctionManager will create instance of auction and will store all the auctions. + * + */ + +/** + * @typedef {Object} AdUnit An object containing the adUnit configuration. + * + * @property {string} code A code which will be used to uniquely identify this bidder. This should be the same + * one as is used in the call to registerBidAdapter + * @property {Array.} sizes A list of size for adUnit. + * @property {object} params Any bidder-specific params which the publisher used in their bid request. + * This is guaranteed to have passed the spec.areParamsValid() test. + */ + +/** + * @typedef {Array.} size + */ + +/** + * @typedef {Array.} AdUnitCode + */ + +/** + * @typedef {Object} BidRequest + * //TODO add all properties + */ + +/** + * @typedef {Object} BidReceived + * //TODO add all properties + */ + +/** + * @typedef {Object} Auction + * + * @property {function(): string} getAuctionStatus - returns the auction status which can be any one of 'started', 'in progress' or 'completed' + * @property {function(): AdUnit[]} getAdUnits - return the adUnits for this auction instance + * @property {function(): AdUnitCode[]} getAdUnitCodes - return the adUnitCodes for this auction instance + * @property {function(): BidRequest[]} getBidRequests - get all bid requests for this auction instance + * @property {function(): BidReceived[]} getBidsReceived - get all bid received for this auction instance + * @property {function(): void} startAuctionTimer - sets the bidsBackHandler callback and starts the timer for auction + * @property {function(): void} callBids - sends requests to all adapters for bids + */ + +import { uniques, flatten, timestamp, adUnitsFilter, delayExecution, getBidderRequest } from './utils'; +import { getPriceBucketString } from './cpmBucketManager'; +import { getNativeTargeting } from './native'; +import { getCacheUrl, store } from './videoCache'; +import { Renderer } from 'src/Renderer'; +import { config } from 'src/config'; +import { userSync } from 'src/userSync'; +import { createHook } from 'src/hook'; +import { videoAdUnit } from 'src/video'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; + +const { syncUsers } = userSync; +const utils = require('./utils'); +const adaptermanager = require('./adaptermanager'); +const events = require('./events'); +const CONSTANTS = require('./constants.json'); + +export const AUCTION_STARTED = 'started'; +export const AUCTION_IN_PROGRESS = 'inProgress'; +export const AUCTION_COMPLETED = 'completed'; + +// register event for bid adjustment +events.on(CONSTANTS.EVENTS.BID_ADJUSTMENT, function (bid) { + adjustBids(bid); +}); + +/** + * Creates new auction instance + * + * @param {Object} requestConfig + * @param {AdUnit} requestConfig.adUnits + * @param {AdUnitCode} requestConfig.adUnitCode + * + * @returns {Auction} auction instance + */ +export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) { + let _adUnits = adUnits; + let _labels = labels; + let _adUnitCodes = adUnitCodes; + let _bidderRequests = []; + let _bidsReceived = []; + let _auctionStart; + let _auctionId = utils.generateUUID(); + let _auctionStatus; + let _callback = callback; + let _timer; + let _timeout = cbTimeout; + let _winningBid; + + function addBidRequests(bidderRequests) { _bidderRequests = _bidderRequests.concat(bidderRequests) }; + function addBidReceived(bidsReceived) { _bidsReceived = _bidsReceived.concat(bidsReceived); } + + function startAuctionTimer() { + const timedOut = true; + const timeoutCallback = executeCallback.bind(null, timedOut); + let timer = setTimeout(timeoutCallback, _timeout); + _timer = timer; + } + + function executeCallback(timedOut, cleartimer) { + // clear timer when done calls executeCallback + if (cleartimer) { + clearTimeout(_timer); + } + + if (_callback != null) { + if (timedOut) { + utils.logMessage(`Auction ${_auctionId} timedOut`); + const timedOutBidders = getTimedOutBids(_bidderRequests, _bidsReceived); + if (timedOutBidders.length) { + events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); + } + } + + events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: _auctionId}); + + try { + _auctionStatus = AUCTION_COMPLETED; + const adUnitCodes = _adUnitCodes; + const bids = [_bidsReceived + .filter(adUnitsFilter.bind(this, adUnitCodes)) + .reduce(groupByPlacement, {})]; + _callback.apply($$PREBID_GLOBAL$$, bids); + } catch (e) { + utils.logError('Error executing bidsBackHandler', null, e); + } finally { + // Only automatically sync if the publisher has not chosen to "enableOverride" + let userSyncConfig = config.getConfig('userSync') || {}; + if (!userSyncConfig.enableOverride) { + // Delay the auto sync by the config delay + syncUsers(userSyncConfig.syncDelay); + } + } + _callback = null; + } + } + + function done(bidRequestId) { + var innerBidRequestId = bidRequestId; + return delayExecution(function() { + let request = find(_bidderRequests, (bidRequest) => { + return innerBidRequestId === bidRequest.bidderRequestId; + }); + request.doneCbCallCount += 1; + // In case of mediaType video and prebidCache enabled, call bidsBackHandler after cache is stored. + if ((request.bids.filter(videoAdUnit).length == 0) || (request.bids.filter(videoAdUnit).length > 0 && !config.getConfig('cache.url'))) { + bidsBackAll() + } + }, 1); + } + + /** + * Execute bidBackHandler if all bidders have called done. + */ + function bidsBackAll() { + if (_bidderRequests.every((bidRequest) => bidRequest.doneCbCallCount >= 1)) { + // when all bidders have called done callback atleast once it means auction is complete + utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); + _auctionStatus = AUCTION_COMPLETED; + executeCallback(false, true); + } + } + + function callBids() { + startAuctionTimer(); + _auctionStatus = AUCTION_STARTED; + _auctionStart = Date.now(); + + const auctionInit = { + timestamp: _auctionStart, + auctionId: _auctionId, + timeout: _timeout + }; + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); + + let bidRequests = adaptermanager.makeBidRequests(_adUnits, _auctionStart, _auctionId, _timeout, _labels); + utils.logInfo(`Bids Requested for Auction with id: ${_auctionId}`, bidRequests); + bidRequests.forEach(bidRequest => { + addBidRequests(bidRequest); + }); + + _auctionStatus = AUCTION_IN_PROGRESS; + adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(this), done.bind(this)); + }; + + return { + addBidReceived, + executeCallback, + callBids, + bidsBackAll, + setWinningBid: (winningBid) => { _winningBid = winningBid }, + getWinningBid: () => _winningBid, + getTimeout: () => _timeout, + getAuctionId: () => _auctionId, + getAuctionStatus: () => _auctionStatus, + getAdUnits: () => _adUnits, + getAdUnitCodes: () => _adUnitCodes, + getBidRequests: () => _bidderRequests, + getBidsReceived: () => _bidsReceived, + } +} + +export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid) { + let auctionInstance = this; + let bidRequests = auctionInstance.getBidRequests(); + let auctionId = auctionInstance.getAuctionId(); + + let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequests, auctionId}); + if (bidResponse.mediaType === 'video') { + tryAddVideoBid(bidResponse); + } else { + doCallbacksIfNeeded(); + addBidToAuction(bidResponse); + } + + function doCallbacksIfNeeded() { + if (bidResponse.timeToRespond > auctionInstance.getTimeout() + config.getConfig('timeoutBuffer')) { + auctionInstance.executeCallback(true); + } + } + + // Add a bid to the auction. + function addBidToAuction() { + events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bidResponse); + auctionInstance.addBidReceived(bidResponse); + } + + // Video bids may fail if the cache is down, or there's trouble on the network. + function tryAddVideoBid(bidResponse) { + if (config.getConfig('cache.url')) { + store([bidResponse], function(error, cacheIds) { + if (error) { + utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); + } else { + bidResponse.videoCacheKey = cacheIds[0].uuid; + if (!bid.vastUrl) { + bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); + } + addBidToAuction(bidResponse); + auctionInstance.bidsBackAll(); + } + doCallbacksIfNeeded(); + }); + } else { + addBidToAuction(bidResponse); + doCallbacksIfNeeded(); + } + } +}, 'addBidResponse'); + +// 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, bidRequests, auctionId}) { + let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); + + const start = bidRequest.start; + + let bidObject = Object.assign({}, bid, { + auctionId, + requestId: bidRequest.requestId, + responseTimestamp: timestamp(), + requestTimestamp: start, + cpm: parseFloat(bid.cpm) || 0, + bidder: bid.bidderCode, + adUnitCode + }); + + bidObject.timeToRespond = bidObject.responseTimestamp - bidObject.requestTimestamp; + + // Let listeners know that now is the time to adjust the bid, if they want to. + // + // CAREFUL: Publishers rely on certain bid properties to be available (like cpm), + // but others to not be set yet (like priceStrings). See #1372 and #1389. + events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bidObject); + + // a publisher-defined renderer can be used to render bids + const adUnitRenderer = + bidRequest.bids && bidRequest.bids[0] && bidRequest.bids[0].renderer; + + if (adUnitRenderer) { + bidObject.renderer = Renderer.install({ url: adUnitRenderer.url }); + bidObject.renderer.setRender(adUnitRenderer.render); + } + + const priceStringsObj = getPriceBucketString( + bidObject.cpm, + config.getConfig('customPriceBucket'), + config.getConfig('currency.granularityMultiplier') + ); + bidObject.pbLg = priceStringsObj.low; + bidObject.pbMg = priceStringsObj.med; + bidObject.pbHg = priceStringsObj.high; + bidObject.pbAg = priceStringsObj.auto; + bidObject.pbDg = priceStringsObj.dense; + bidObject.pbCg = priceStringsObj.custom; + + // if there is any key value pairs to map do here + var keyValues; + if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) { + keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject); + } + + // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs + bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); + + return bidObject; +} + +export function getStandardBidderSettings() { + let granularity = config.getConfig('priceGranularity'); + let bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; + if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { + bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; + } + if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { + return bidResponse.pbAg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { + return bidResponse.pbDg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { + return bidResponse.pbLg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { + return bidResponse.pbMg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { + return bidResponse.pbHg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { + return bidResponse.pbCg; + } + } + }, { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + }, { + key: 'hb_deal', + val: function (bidResponse) { + return bidResponse.dealId; + } + } + ] + } + return bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; +} + +export function getKeyValueTargetingPairs(bidderCode, custBidObj) { + var keyValues = {}; + var bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; + + // 1) set the keys from "standard" setting or from prebid defaults + if (custBidObj && bidder_settings) { + // initialize default if not set + const standardSettings = getStandardBidderSettings(); + setKeys(keyValues, standardSettings, custBidObj); + } + + // 2) set keys from specific bidder setting override if they exist + if (bidderCode && custBidObj && bidder_settings && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + setKeys(keyValues, bidder_settings[bidderCode], custBidObj); + custBidObj.sendStandardTargeting = bidder_settings[bidderCode].sendStandardTargeting; + } + + // set native key value targeting + if (custBidObj.native) { + keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj)); + } + + return keyValues; +} + +function setKeys(keyValues, bidderSettings, custBidObj) { + var targeting = bidderSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; + custBidObj.size = custBidObj.getSize(); + + utils._each(targeting, function (kvPair) { + var key = kvPair.key; + var value = kvPair.val; + + if (keyValues[key]) { + utils.logWarn('The key: ' + key + ' is getting ovewritten'); + } + + if (utils.isFn(value)) { + try { + value = value(custBidObj); + } catch (e) { + utils.logError('bidmanager', 'ERROR', e); + } + } + + if ( + ((typeof bidderSettings.suppressEmptyKeys !== 'undefined' && bidderSettings.suppressEmptyKeys === true) || + key === 'hb_deal') && // hb_deal is suppressed automatically if not set + ( + utils.isEmptyStr(value) || + value === null || + value === undefined + ) + ) { + utils.logInfo("suppressing empty key '" + key + "' from adserver targeting"); + } else { + keyValues[key] = value; + } + }); + + return keyValues; +} + +export function adjustBids(bid) { + let code = bid.bidderCode; + let bidPriceAdjusted = bid.cpm; + 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); + } + } + } + + if (bidPriceAdjusted >= 0) { + bid.cpm = bidPriceAdjusted; + } +} + +/** + * groupByPlacement is a reduce function that converts an array of Bid objects + * to an object with placement codes as keys, with each key representing an object + * with an array of `Bid` objects for that placement + * @returns {*} as { [adUnitCode]: { bids: [Bid, Bid, Bid] } } + */ +function groupByPlacement(bidsByPlacement, bid) { + if (!bidsByPlacement[bid.adUnitCode]) { bidsByPlacement[bid.adUnitCode] = { bids: [] }; } + bidsByPlacement[bid.adUnitCode].bids.push(bid); + return bidsByPlacement; +} + +/** + * Returns a list of bids that we haven't received a response yet + * @param {BidRequest[]} bidderRequests List of bids requested for auction instance + * @param {BidReceived[]} bidsReceived List of bids received for auction instance + * + * @typedef {Object} TimedOutBid + * @property {string} bidId The id representing the bid + * @property {string} bidder The string name of the bidder + * @property {string} adUnitCode The code used to uniquely identify the ad unit on the publisher's page + * @property {string} auctionId The id representing the auction + * + * @return {Array} List of bids that Prebid hasn't received a response for + */ +function getTimedOutBids(bidderRequests, bidsReceived) { + const bidRequestedCodes = bidderRequests + .map(bid => bid.bidderCode) + .filter(uniques); + + const bidReceivedCodes = bidsReceived + .map(bid => bid.bidder) + .filter(uniques); + + const timedOutBidderCodes = bidRequestedCodes + .filter(bidder => !includes(bidReceivedCodes, bidder)); + + const timedOutBids = bidderRequests + .map(bid => (bid.bids || []).filter(bid => includes(timedOutBidderCodes, bid.bidder))) + .reduce(flatten, []) + .map(bid => ({ + bidId: bid.bidId, + bidder: bid.bidder, + adUnitCode: bid.adUnitCode, + auctionId: bid.auctionId, + })); + + return timedOutBids; +} diff --git a/src/auctionManager.js b/src/auctionManager.js new file mode 100644 index 00000000000..65723d6c199 --- /dev/null +++ b/src/auctionManager.js @@ -0,0 +1,98 @@ +/** + * AuctionManager modules is responsible for creating auction instances. + * This module is the gateway for Prebid core to access auctions. + * It stores all created instances of auction and can be used to get consolidated values from auction. + */ + +/** + * @typedef {Object} AuctionManager + * + * @property {function(): Array} getBidsRequested - returns cosolidated bid requests + * @property {function(): Array} getBidsReceived - returns cosolidated bid received + * @property {function(): Array} getAdUnits - returns cosolidated adUnits + * @property {function(): Array} getAdUnitCodes - returns cosolidated adUnitCodes + * @property {function(): Object} createAuction - creates auction instance and stores it for future reference + * @property {function(): Object} findBidByAdId - find bid received by adId. This function will be called by $$PREBID_GLOBAL$$.renderAd + * @property {function(): Object} getStandardBidderAdServerTargeting - returns standard bidder targeting for all the adapters. Refer http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.bidderSettings for more details + */ + +import { uniques, flatten } from './utils'; +import { newAuction, getStandardBidderSettings, AUCTION_COMPLETED } from 'src/auction'; +import find from 'core-js/library/fn/array/find'; + +const CONSTANTS = require('./constants.json'); + +/** + * Creates new instance of auctionManager. There will only be one instance of auctionManager but + * a factory is created to assist in testing. + * + * @returns {AuctionManager} auctionManagerInstance + */ +export function newAuctionManager() { + let _auctions = []; + let auctionManager = {}; + + auctionManager.addWinningBid = function(bid) { + const auction = find(_auctions, auction => auction.getAuctionId() === bid.auctionId); + if (auction) { + auction.setWinningBid(bid); + } else { + utils.logWarn(`Auction not found when adding winning bid`); + } + } + + auctionManager.getAllWinningBids = function() { + return _auctions.map(auction => auction.getWinningBid()) + .reduce(flatten, []); + } + + auctionManager.getBidsRequested = function() { + return _auctions.map(auction => auction.getBidRequests()) + .reduce(flatten, []); + }; + + auctionManager.getBidsReceived = function() { + // As of now, an old bid which is not used in auction 1 can be used in auction n. + // To prevent this, bid.ttl (time to live) will be added to this logic and bid pool will also be added + // As of now none of the adapters are sending back bid.ttl + return _auctions.map((auction) => { + if (auction.getAuctionStatus() === AUCTION_COMPLETED) { + return auction.getBidsReceived(); + } + }).reduce(flatten, []) + .filter(bid => bid); + }; + + auctionManager.getAdUnits = function() { + return _auctions.map(auction => auction.getAdUnits()) + .reduce(flatten, []); + }; + + auctionManager.getAdUnitCodes = function() { + return _auctions.map(auction => auction.getAdUnitCodes()) + .reduce(flatten, []) + .filter(uniques); + }; + + auctionManager.createAuction = function({ adUnits, adUnitCodes, callback, cbTimeout, labels }) { + const auction = newAuction({ adUnits, adUnitCodes, callback, cbTimeout, labels }); + _addAuction(auction); + return auction; + }; + + auctionManager.findBidByAdId = function(adId) { + return find(_auctions.map(auction => auction.getBidsReceived()).reduce(flatten, []), bid => bid.adId === adId); + }; + + auctionManager.getStandardBidderAdServerTargeting = function() { + return getStandardBidderSettings()[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; + }; + + function _addAuction(auction) { + _auctions.push(auction); + } + + return auctionManager; +} + +export const auctionManager = newAuctionManager(); diff --git a/src/bidmanager.js b/src/bidmanager.js deleted file mode 100644 index f3379e7fee4..00000000000 --- a/src/bidmanager.js +++ /dev/null @@ -1,509 +0,0 @@ -import { uniques, flatten, adUnitsFilter, getBidderRequest } from './utils'; -import { getPriceBucketString } from './cpmBucketManager'; -import { nativeBidIsValid, getNativeTargeting } from './native'; -import { isValidVideoBid } from './video'; -import { getCacheUrl, store } from './videoCache'; -import { Renderer } from 'src/Renderer'; -import { config } from 'src/config'; -import { createHook } from 'src/hook'; - -var CONSTANTS = require('./constants.json'); -var AUCTION_END = CONSTANTS.EVENTS.AUCTION_END; -var utils = require('./utils.js'); -var events = require('./events'); - -var externalCallbacks = {byAdUnit: [], all: [], oneTime: null, timer: false}; -var defaultBidderSettingsMap = {}; - -/** - * Returns a list of bidders that we haven't received a response yet - * @return {array} [description] - */ -exports.getTimedOutBidders = function () { - return $$PREBID_GLOBAL$$._bidsRequested - .map(getBidderCode) - .filter(uniques) - .filter(bidder => $$PREBID_GLOBAL$$._bidsReceived - .map(getBidders) - .filter(uniques) - .indexOf(bidder) < 0); -}; - -function timestamp() { return new Date().getTime(); } - -function getBidderCode(bidSet) { - return bidSet.bidderCode; -} - -function getBidders(bid) { - return bid.bidder; -} - -function bidsBackAdUnit(adUnitCode) { - const requested = $$PREBID_GLOBAL$$._bidsRequested - .map(request => request.bids - .filter(adUnitsFilter.bind(this, $$PREBID_GLOBAL$$._adUnitCodes)) - .filter(bid => bid.placementCode === adUnitCode)) - .reduce(flatten, []) - .map(bid => { - return bid.bidder === 'indexExchange' - ? bid.sizes.length - : 1; - }).reduce(add, 0); - - const received = $$PREBID_GLOBAL$$._bidsReceived.filter(bid => bid.adUnitCode === adUnitCode).length; - return requested === received; -} - -function add(a, b) { - return a + b; -} - -function bidsBackAll() { - const requested = $$PREBID_GLOBAL$$._bidsRequested - .map(request => request.bids) - .reduce(flatten, []) - .filter(adUnitsFilter.bind(this, $$PREBID_GLOBAL$$._adUnitCodes)) - .map(bid => { - return bid.bidder === 'indexExchange' - ? bid.sizes.length - : 1; - }).reduce((a, b) => a + b, 0); - - const received = $$PREBID_GLOBAL$$._bidsReceived - .filter(adUnitsFilter.bind(this, $$PREBID_GLOBAL$$._adUnitCodes)).length; - - return requested === received; -} - -exports.bidsBackAll = function () { - return bidsBackAll(); -}; - -// Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. -function isValidBid(bid, adUnitCode) { - function errorMessage(msg) { - return `Invalid bid from ${bid.bidderCode}. Ignoring bid: ${msg}`; - } - - if (!bid) { - utils.logError(`Some adapter tried to add an undefined bid for ${adUnitCode}.`); - return false; - } - if (!adUnitCode) { - utils.logError(errorMessage('No adUnitCode was supplied to addBidResponse.')); - return false; - } - - const bidRequest = getBidderRequest(bid.bidderCode, adUnitCode); - if (!bidRequest.start) { - utils.logError(errorMessage('Cannot find valid matching bid request.')); - return false; - } - - if (bid.mediaType === 'native' && !nativeBidIsValid(bid)) { - utils.logError(errorMessage('Native bid missing some required properties.')); - return false; - } - if (bid.mediaType === 'video' && !isValidVideoBid(bid)) { - utils.logError(errorMessage(`Video bid does not have required vastUrl or renderer property`)); - return false; - } - if (bid.mediaType === 'banner' && !validBidSize(bid, adUnitCode)) { - utils.logError(errorMessage(`Banner bids require a width and height`)); - return false; - } - - return true; -} - -// check that the bid has a width and height set -function validBidSize(bid, adUnitCode) { - if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) { - return true; - } - - const adUnit = getBidderRequest(bid.bidderCode, adUnitCode); - const sizes = adUnit && adUnit.bids && adUnit.bids[0] && adUnit.bids[0].sizes; - const parsedSizes = utils.parseSizesInput(sizes); - - // if a banner impression has one valid size, we assign that size to any bid - // response that does not explicitly set width or height - if (parsedSizes.length === 1) { - const [ width, height ] = parsedSizes[0].split('x'); - bid.width = width; - bid.height = height; - return true; - } - - return false; -} - -// Postprocess the bids so that all the universal properties exist, no matter which bidder they came from. -// This should be called before addBidToAuction(). -function prepareBidForAuction(bid, adUnitCode) { - const bidRequest = getBidderRequest(bid.bidderCode, adUnitCode); - - Object.assign(bid, { - requestId: bidRequest.requestId, - responseTimestamp: timestamp(), - requestTimestamp: bidRequest.start, - cpm: parseFloat(bid.cpm) || 0, - bidder: bid.bidderCode, - adUnitCode - }); - - bid.timeToRespond = bid.responseTimestamp - bid.requestTimestamp; - - // Let listeners know that now is the time to adjust the bid, if they want to. - // - // CAREFUL: Publishers rely on certain bid properties to be available (like cpm), - // but others to not be set yet (like priceStrings). See #1372 and #1389. - events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bid); - - // a publisher-defined renderer can be used to render bids - const adUnitRenderer = - bidRequest.bids && bidRequest.bids[0] && bidRequest.bids[0].renderer; - - if (adUnitRenderer) { - bid.renderer = Renderer.install({ url: adUnitRenderer.url }); - bid.renderer.setRender(adUnitRenderer.render); - } - - const priceStringsObj = getPriceBucketString( - bid.cpm, - config.getConfig('customPriceBucket'), - config.getConfig('currency.granularityMultiplier') - ); - bid.pbLg = priceStringsObj.low; - bid.pbMg = priceStringsObj.med; - bid.pbHg = priceStringsObj.high; - bid.pbAg = priceStringsObj.auto; - bid.pbDg = priceStringsObj.dense; - bid.pbCg = priceStringsObj.custom; - - // if there is any key value pairs to map do here - var keyValues; - if (bid.bidderCode && (bid.cpm > 0 || bid.dealId)) { - keyValues = getKeyValueTargetingPairs(bid.bidderCode, bid); - } - - // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs - bid.adserverTargeting = Object.assign(bid.adserverTargeting || {}, keyValues); -} - -function doCallbacksIfNeeded(bid) { - if (bid.timeToRespond > $$PREBID_GLOBAL$$.cbTimeout + $$PREBID_GLOBAL$$.timeoutBuffer) { - const timedOut = true; - exports.executeCallback(timedOut); - } -} - -// Add a bid to the auction. -function addBidToAuction(bid) { - events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bid); - - $$PREBID_GLOBAL$$._bidsReceived.push(bid); - - if (bid.adUnitCode && bidsBackAdUnit(bid.adUnitCode)) { - triggerAdUnitCallbacks(bid.adUnitCode); - } - - if (bidsBackAll()) { - exports.executeCallback(); - } -} - -// Video bids may fail if the cache is down, or there's trouble on the network. -function tryAddVideoBid(bid) { - if (config.getConfig('usePrebidCache')) { - store([bid], function(error, cacheIds) { - if (error) { - utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); - } else { - bid.videoCacheKey = cacheIds[0].uuid; - if (!bid.vastUrl) { - bid.vastUrl = getCacheUrl(bid.videoCacheKey); - } - addBidToAuction(bid); - } - doCallbacksIfNeeded(bid); - }); - } else { - addBidToAuction(bid); - doCallbacksIfNeeded(bid); - } -} - -/* - * This function should be called to by the bidder adapter to register a bid response - */ -exports.addBidResponse = createHook('asyncSeries', function (adUnitCode, bid) { - if (!isValidBid(bid, adUnitCode)) { - return; - } - prepareBidForAuction(bid, adUnitCode); - - if (bid.mediaType === 'video') { - tryAddVideoBid(bid); - } else { - addBidToAuction(bid); - doCallbacksIfNeeded(bid); - } -}); - -function getKeyValueTargetingPairs(bidderCode, custBidObj) { - var keyValues = {}; - var bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; - - // 1) set the keys from "standard" setting or from prebid defaults - if (custBidObj && bidder_settings) { - // initialize default if not set - const standardSettings = getStandardBidderSettings(); - setKeys(keyValues, standardSettings, custBidObj); - } - - if (bidderCode && custBidObj && bidder_settings && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - // 2) set keys from specific bidder setting override if they exist - setKeys(keyValues, bidder_settings[bidderCode], custBidObj); - custBidObj.alwaysUseBid = bidder_settings[bidderCode].alwaysUseBid; - custBidObj.sendStandardTargeting = bidder_settings[bidderCode].sendStandardTargeting; - } else if (defaultBidderSettingsMap[bidderCode]) { - // 2) set keys from standard setting. NOTE: this API doesn't seem to be in use by any Adapter - setKeys(keyValues, defaultBidderSettingsMap[bidderCode], custBidObj); - custBidObj.alwaysUseBid = defaultBidderSettingsMap[bidderCode].alwaysUseBid; - custBidObj.sendStandardTargeting = defaultBidderSettingsMap[bidderCode].sendStandardTargeting; - } - - if (custBidObj['native']) { - keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj)); - } - - return keyValues; -} - -exports.getKeyValueTargetingPairs = function() { - return getKeyValueTargetingPairs(...arguments); -}; - -function setKeys(keyValues, bidderSettings, custBidObj) { - var targeting = bidderSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; - custBidObj.size = custBidObj.getSize(); - - utils._each(targeting, function (kvPair) { - var key = kvPair.key; - var value = kvPair.val; - - if (keyValues[key]) { - utils.logWarn('The key: ' + key + ' is getting ovewritten'); - } - - if (utils.isFn(value)) { - try { - value = value(custBidObj); - } catch (e) { - utils.logError('bidmanager', 'ERROR', e); - } - } - - if ( - ((typeof bidderSettings.suppressEmptyKeys !== 'undefined' && bidderSettings.suppressEmptyKeys === true) || - key === 'hb_deal') && // hb_deal is suppressed automatically if not set - ( - utils.isEmptyStr(value) || - value === null || - value === undefined - ) - ) { - utils.logInfo("suppressing empty key '" + key + "' from adserver targeting"); - } else { - keyValues[key] = value; - } - }); - - return keyValues; -} - -exports.registerDefaultBidderSetting = function (bidderCode, defaultSetting) { - defaultBidderSettingsMap[bidderCode] = defaultSetting; -}; - -exports.executeCallback = function (timedOut) { - // if there's still a timeout running, clear it now - if (!timedOut && externalCallbacks.timer) { - clearTimeout(externalCallbacks.timer); - } - - if (externalCallbacks.all.called !== true) { - processCallbacks(externalCallbacks.all); - externalCallbacks.all.called = true; - - if (timedOut) { - const timedOutBidders = exports.getTimedOutBidders(); - - if (timedOutBidders.length) { - events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); - } - } - } - - // execute one time callback - if (externalCallbacks.oneTime) { - events.emit(AUCTION_END); - try { - processCallbacks([externalCallbacks.oneTime]); - } catch (e) { - utils.logError('Error executing bidsBackHandler', null, e); - } finally { - externalCallbacks.oneTime = null; - externalCallbacks.timer = false; - $$PREBID_GLOBAL$$.clearAuction(); - } - } -}; - -exports.externalCallbackReset = function () { - externalCallbacks.all.called = false; -}; - -function triggerAdUnitCallbacks(adUnitCode) { - // todo : get bid responses and send in args - var singleAdUnitCode = [adUnitCode]; - processCallbacks(externalCallbacks.byAdUnit, singleAdUnitCode); -} - -function processCallbacks(callbackQueue, singleAdUnitCode) { - if (utils.isArray(callbackQueue)) { - callbackQueue.forEach(callback => { - const adUnitCodes = singleAdUnitCode || $$PREBID_GLOBAL$$._adUnitCodes; - const bids = [$$PREBID_GLOBAL$$._bidsReceived - .filter(adUnitsFilter.bind(this, adUnitCodes)) - .reduce(groupByPlacement, {})]; - - callback.apply($$PREBID_GLOBAL$$, bids); - }); - } -} - -/** - * groupByPlacement is a reduce function that converts an array of Bid objects - * to an object with placement codes as keys, with each key representing an object - * with an array of `Bid` objects for that placement - * @returns {*} as { [adUnitCode]: { bids: [Bid, Bid, Bid] } } - */ -function groupByPlacement(bidsByPlacement, bid) { - if (!bidsByPlacement[bid.adUnitCode]) { bidsByPlacement[bid.adUnitCode] = { bids: [] }; } - - bidsByPlacement[bid.adUnitCode].bids.push(bid); - - return bidsByPlacement; -} - -/** - * Add a one time callback, that is discarded after it is called - * @param {Function} callback - * @param timer Timer to clear if callback is triggered before timer time's out - */ -exports.addOneTimeCallback = function (callback, timer) { - externalCallbacks.oneTime = callback; - externalCallbacks.timer = timer; -}; - -exports.addCallback = function (id, callback, cbEvent) { - callback.id = id; - if (CONSTANTS.CB.TYPE.ALL_BIDS_BACK === cbEvent) { - externalCallbacks.all.push(callback); - } else if (CONSTANTS.CB.TYPE.AD_UNIT_BIDS_BACK === cbEvent) { - externalCallbacks.byAdUnit.push(callback); - } -}; - -// register event for bid adjustment -events.on(CONSTANTS.EVENTS.BID_ADJUSTMENT, function (bid) { - adjustBids(bid); -}); - -function adjustBids(bid) { - var code = bid.bidderCode; - var bidPriceAdjusted = bid.cpm; - 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); - } - } - } - - if (bidPriceAdjusted >= 0) { - bid.cpm = bidPriceAdjusted; - } -} - -exports.adjustBids = function() { - return adjustBids(...arguments); -}; - -function getStandardBidderSettings() { - let granularity = config.getConfig('priceGranularity'); - let bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; - if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { - bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; - } - if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { - return bidResponse.pbAg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { - return bidResponse.pbDg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { - return bidResponse.pbLg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { - return bidResponse.pbMg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { - return bidResponse.pbHg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { - return bidResponse.pbCg; - } - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - }, { - key: 'hb_deal', - val: function (bidResponse) { - return bidResponse.dealId; - } - } - ]; - } - return bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; -} - -function getStandardBidderAdServerTargeting() { - return getStandardBidderSettings()[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; -} - -exports.getStandardBidderAdServerTargeting = getStandardBidderAdServerTargeting; diff --git a/src/config.js b/src/config.js index 5ed83e555b2..146c0f17a65 100644 --- a/src/config.js +++ b/src/config.js @@ -8,13 +8,26 @@ * continue to work during a deprecation window. */ import { isValidPriceConfig } from './cpmBucketManager'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; const utils = require('./utils'); const DEFAULT_DEBUG = false; const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_COOKIESYNC_DELAY = 100; -const DEFAULT_ENABLE_SEND_ALL_BIDS = false; +const DEFAULT_ENABLE_SEND_ALL_BIDS = true; + +const DEFAULT_TIMEOUTBUFFER = 200; + +export const RANDOM = 'random'; +const FIXED = 'fixed'; + +const VALID_ORDERS = {}; +VALID_ORDERS[RANDOM] = true; +VALID_ORDERS[FIXED] = true; + +const DEFAULT_BIDDER_SEQUENCE = RANDOM; const GRANULARITY_OPTIONS = { LOW: 'low', @@ -30,117 +43,128 @@ const ALL_TOPICS = '*'; /** * @typedef {object} PrebidConfig * - * @property {bool} usePrebidCache True if we should use prebid-cache to store video bids before adding - * bids to the auction, and false otherwise. **NOTE** This must be true if you want to use the - * dfpAdServerVideo module. + * @property {string} cache.url Set a url if we should use prebid-cache to store video bids before adding + * bids to the auction. **NOTE** This must be set if you want to use the dfpAdServerVideo module. */ export function newConfig() { let listeners = []; - - let defaults = {}; - - let config = { - // `debug` is equivalent to legacy `pbjs.logging` property - _debug: DEFAULT_DEBUG, - get debug() { - if ($$PREBID_GLOBAL$$.logging || $$PREBID_GLOBAL$$.logging === false) { - return $$PREBID_GLOBAL$$.logging; - } - return this._debug; - }, - set debug(val) { - this._debug = val; - }, - - // default timeout for all bids - _bidderTimeout: DEFAULT_BIDDER_TIMEOUT, - get bidderTimeout() { - return $$PREBID_GLOBAL$$.bidderTimeout || this._bidderTimeout; - }, - set bidderTimeout(val) { - this._bidderTimeout = val; - }, - - // domain where prebid is running for cross domain iframe communication - _publisherDomain: DEFAULT_PUBLISHER_DOMAIN, - get publisherDomain() { - return $$PREBID_GLOBAL$$.publisherDomain || this._publisherDomain; - }, - set publisherDomain(val) { - this._publisherDomain = val; - }, - - // delay to request cookie sync to stay out of critical path - _cookieSyncDelay: DEFAULT_COOKIESYNC_DELAY, - get cookieSyncDelay() { - return $$PREBID_GLOBAL$$.cookieSyncDelay || this._cookieSyncDelay; - }, - set cookieSyncDelay(val) { - this._cookieSyncDelay = val; - }, - - // calls existing function which may be moved after deprecation - _priceGranularity: GRANULARITY_OPTIONS.MEDIUM, - set priceGranularity(val) { - if (validatePriceGranularity(val)) { - if (typeof val === 'string') { - this._priceGranularity = (hasGranularity(val)) ? val : GRANULARITY_OPTIONS.MEDIUM; - } else if (typeof val === 'object') { - this._customPriceBucket = val; - this._priceGranularity = GRANULARITY_OPTIONS.CUSTOM; - utils.logMessage('Using custom price granularity'); + let defaults; + let config; + + function resetConfig() { + defaults = {}; + config = { + // `debug` is equivalent to legacy `pbjs.logging` property + _debug: DEFAULT_DEBUG, + get debug() { + return this._debug; + }, + set debug(val) { + this._debug = val; + }, + + // default timeout for all bids + _bidderTimeout: DEFAULT_BIDDER_TIMEOUT, + get bidderTimeout() { + return this._bidderTimeout; + }, + set bidderTimeout(val) { + this._bidderTimeout = val; + }, + + // domain where prebid is running for cross domain iframe communication + _publisherDomain: DEFAULT_PUBLISHER_DOMAIN, + get publisherDomain() { + return this._publisherDomain; + }, + set publisherDomain(val) { + this._publisherDomain = val; + }, + + // delay to request cookie sync to stay out of critical path + _cookieSyncDelay: DEFAULT_COOKIESYNC_DELAY, + get cookieSyncDelay() { + return $$PREBID_GLOBAL$$.cookieSyncDelay || this._cookieSyncDelay; + }, + set cookieSyncDelay(val) { + this._cookieSyncDelay = val; + }, + + // calls existing function which may be moved after deprecation + _priceGranularity: GRANULARITY_OPTIONS.MEDIUM, + set priceGranularity(val) { + if (validatePriceGranularity(val)) { + if (typeof val === 'string') { + this._priceGranularity = (hasGranularity(val)) ? val : GRANULARITY_OPTIONS.MEDIUM; + } else if (typeof val === 'object') { + this._customPriceBucket = val; + this._priceGranularity = GRANULARITY_OPTIONS.CUSTOM; + utils.logMessage('Using custom price granularity'); + } } - } - }, - get priceGranularity() { - return this._priceGranularity; - }, - - _customPriceBucket: {}, - get customPriceBucket() { - return this._customPriceBucket; - }, - - _sendAllBids: DEFAULT_ENABLE_SEND_ALL_BIDS, - get enableSendAllBids() { - return this._sendAllBids; - }, - set enableSendAllBids(val) { - this._sendAllBids = val; - }, - - // calls existing function which may be moved after deprecation - set bidderSequence(val) { - $$PREBID_GLOBAL$$.setBidderSequence(val); - }, - - // calls existing function which may be moved after deprecation - set s2sConfig(val) { - $$PREBID_GLOBAL$$.setS2SConfig(val); - } - }; + }, + get priceGranularity() { + return this._priceGranularity; + }, + + _customPriceBucket: {}, + get customPriceBucket() { + return this._customPriceBucket; + }, + + _sendAllBids: DEFAULT_ENABLE_SEND_ALL_BIDS, + get enableSendAllBids() { + return this._sendAllBids; + }, + set enableSendAllBids(val) { + this._sendAllBids = val; + }, + + _bidderSequence: DEFAULT_BIDDER_SEQUENCE, + get bidderSequence() { + return this._bidderSequence; + }, + set bidderSequence(val) { + if (VALID_ORDERS[val]) { + this._bidderSequence = val; + } else { + utils.logWarn(`Invalid order: ${val}. Bidder Sequence was not set.`); + } + }, - function hasGranularity(val) { - return Object.keys(GRANULARITY_OPTIONS).find(option => val === GRANULARITY_OPTIONS[option]); - } + // timeout buffer to adjust for bidder CDN latency + _timoutBuffer: DEFAULT_TIMEOUTBUFFER, + get timeoutBuffer() { + return this._timoutBuffer; + }, + set timeoutBuffer(val) { + this._timoutBuffer = val; + }, - function validatePriceGranularity(val) { - if (!val) { - utils.logError('Prebid Error: no value passed to `setPriceGranularity()`'); - return false; + }; + + function hasGranularity(val) { + return find(Object.keys(GRANULARITY_OPTIONS), option => val === GRANULARITY_OPTIONS[option]); } - if (typeof val === 'string') { - if (!hasGranularity(val)) { - utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.'); - } - } else if (typeof val === 'object') { - if (!isValidPriceConfig(val)) { - utils.logError('Invalid custom price value passed to `setPriceGranularity()`'); + + function validatePriceGranularity(val) { + if (!val) { + utils.logError('Prebid Error: no value passed to `setPriceGranularity()`'); return false; } + if (typeof val === 'string') { + if (!hasGranularity(val)) { + utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.'); + } + } else if (typeof val === 'object') { + if (!isValidPriceConfig(val)) { + utils.logError('Invalid custom price value passed to `setPriceGranularity()`'); + return false; + } + } + return true; } - return true; } /* @@ -253,7 +277,7 @@ export function newConfig() { // call subscribers of a specific topic, passing only that configuration listeners - .filter(listener => TOPICS.includes(listener.topic)) + .filter(listener => includes(TOPICS, listener.topic)) .forEach(listener => { listener.callback({ [listener.topic]: options[listener.topic] }); }); @@ -264,10 +288,13 @@ export function newConfig() { .forEach(listener => listener.callback(options)); } + resetConfig(); + return { getConfig, setConfig, - setDefaults + setDefaults, + resetConfig }; } diff --git a/src/constants.json b/src/constants.json index 806b3790c12..3e20d462ac7 100644 --- a/src/constants.json +++ b/src/constants.json @@ -54,10 +54,7 @@ "hb_deal" ], "S2S" : { - "DEFAULT_ENDPOINT" : "https://prebid.adnxs.com/pbs/v1/auction", "SRC" : "s2s", - "ADAPTER" : "prebidServer", - "SYNC_ENDPOINT" : "https://prebid.adnxs.com/pbs/v1/cookie_sync", "SYNCED_BIDDERS_KEY": "pbjsSyncs" } } diff --git a/src/cpmBucketManager.js b/src/cpmBucketManager.js index 5eb66bc1376..0061d35f483 100644 --- a/src/cpmBucketManager.js +++ b/src/cpmBucketManager.js @@ -1,3 +1,4 @@ +import find from 'core-js/library/fn/array/find'; const utils = require('src/utils'); const _defaultPrecision = 2; @@ -86,7 +87,7 @@ function getCpmStringValue(cpm, config, granularityMultiplier) { }, { 'max': 0, }); - let bucket = config.buckets.find(bucket => { + let bucket = find(config.buckets, bucket => { if (cpm > cap.max * granularityMultiplier) { // cpm exceeds cap, just return the cap. let precision = bucket.precision; diff --git a/src/native.js b/src/native.js index 9c591aa539c..bfe4b64405d 100644 --- a/src/native.js +++ b/src/native.js @@ -1,4 +1,5 @@ import { deepAccess, getBidRequest, logError, triggerPixel } from './utils'; +import includes from 'core-js/library/fn/array/includes'; export const nativeAdapters = []; @@ -46,7 +47,7 @@ export function processNativeAdUnitParams(params) { * Check if the native type specified in the adUnit is supported by Prebid. */ function typeIsSupported(type) { - if (!(type && Object.keys(SUPPORTED_TYPES).includes(type))) { + if (!(type && includes(Object.keys(SUPPORTED_TYPES), type))) { logError(`${type} nativeParam is not supported`); return false; } @@ -64,19 +65,20 @@ export const nativeAdUnit = adUnit => { const mediaTypes = deepAccess(adUnit, 'mediaTypes.native'); return mediaType || mediaTypes; } -export const nativeBidder = bid => nativeAdapters.includes(bid.bidder); +export const nativeBidder = bid => includes(nativeAdapters, bid.bidder); export const hasNonNativeBidder = adUnit => adUnit.bids.filter(bid => !nativeBidder(bid)).length; -/* +/** * Validate that the native assets on this bid contain all assets that were * marked as required in the adUnit configuration. + * @param {Bid} bid Native bid to validate + * @param {BidRequest[]} bidRequests All bid requests for an auction + * @return {Boolean} If object is valid */ -export function nativeBidIsValid(bid) { - const bidRequest = getBidRequest(bid.adId); - if (!bidRequest) { - return false; - } +export function nativeBidIsValid(bid, bidRequests) { + const bidRequest = getBidRequest(bid.adId, bidRequests); + if (!bidRequest) { return false; } // all native bid responses must define a landing page url if (!deepAccess(bid, 'native.clickUrl')) { @@ -95,7 +97,7 @@ export function nativeBidIsValid(bid) { key => bid['native'][key] ); - return requiredAssets.every(asset => returnedAssets.includes(asset)); + return requiredAssets.every(asset => includes(returnedAssets, asset)); } /* diff --git a/src/polyfill.js b/src/polyfill.js deleted file mode 100644 index 1c8913824ae..00000000000 --- a/src/polyfill.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @module polyfill -Misc polyfills -*/ -require('core-js/fn/array/find'); -require('core-js/fn/array/find-index'); -require('core-js/fn/array/includes'); -require('core-js/fn/object/assign'); - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger -Number.isInteger = Number.isInteger || function(value) { - return typeof value === 'number' && - isFinite(value) && - Math.floor(value) === value; -}; diff --git a/src/prebid.js b/src/prebid.js index 2b61a839b5e..ffecabe05eb 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -4,65 +4,40 @@ import { getGlobal } from './prebidGlobal'; import { flatten, uniques, isGptPubadsDefined, adUnitsFilter } from './utils'; import { videoAdUnit, videoBidder, hasNonVideoBidder } from './video'; import { nativeAdUnit, nativeBidder, hasNonNativeBidder } from './native'; -import './polyfill'; -import { parse as parseURL, format as formatURL } from './url'; import { listenMessagesFromCreative } from './secureCreatives'; import { userSync } from 'src/userSync.js'; import { loadScript } from './adloader'; -import { setAjaxTimeout } from './ajax'; import { config } from './config'; +import { auctionManager } from './auctionManager'; +import { targeting } from './targeting'; +import includes from 'core-js/library/fn/array/includes'; var $$PREBID_GLOBAL$$ = getGlobal(); var CONSTANTS = require('./constants.json'); var utils = require('./utils.js'); -var bidmanager = require('./bidmanager.js'); var adaptermanager = require('./adaptermanager'); var bidfactory = require('./bidfactory'); var events = require('./events'); -var adserver = require('./adserver.js'); -var targeting = require('./targeting.js'); -const { syncUsers, triggerUserSyncs } = userSync; +const { triggerUserSyncs } = userSync; /* private variables */ +const RENDERED = 'rendered'; var BID_WON = CONSTANTS.EVENTS.BID_WON; var SET_TARGETING = CONSTANTS.EVENTS.SET_TARGETING; var ADD_AD_UNITS = CONSTANTS.EVENTS.ADD_AD_UNITS; -var auctionRunning = false; -var bidRequestQueue = []; - var eventValidators = { bidWon: checkDefinedPlacement }; /* Public vars */ - -$$PREBID_GLOBAL$$._bidsRequested = []; -$$PREBID_GLOBAL$$._bidsReceived = []; -// _adUnitCodes stores the current filter to use for adUnits as an array of adUnitCodes -$$PREBID_GLOBAL$$._adUnitCodes = []; -$$PREBID_GLOBAL$$._winningBids = []; -$$PREBID_GLOBAL$$._adsReceived = []; - $$PREBID_GLOBAL$$.bidderSettings = $$PREBID_GLOBAL$$.bidderSettings || {}; -/** @deprecated - use pbjs.setConfig({ bidderTimeout: }) */ -$$PREBID_GLOBAL$$.bidderTimeout = $$PREBID_GLOBAL$$.bidderTimeout; - // current timeout set in `requestBids` or to default `bidderTimeout` $$PREBID_GLOBAL$$.cbTimeout = $$PREBID_GLOBAL$$.cbTimeout || 200; -// timeout buffer to adjust for bidder CDN latency -$$PREBID_GLOBAL$$.timeoutBuffer = 200; - -/** @deprecated - use pbjs.setConfig({ debug: }) */ -$$PREBID_GLOBAL$$.logging = $$PREBID_GLOBAL$$.logging; - -/** @deprecated - use pbjs.setConfig({ publisherDomain: ) */ -$$PREBID_GLOBAL$$.publisherDomain = $$PREBID_GLOBAL$$.publisherDomain; - // let the world know we are loaded $$PREBID_GLOBAL$$.libLoaded = true; @@ -77,11 +52,11 @@ $$PREBID_GLOBAL$$.adUnits = $$PREBID_GLOBAL$$.adUnits || []; $$PREBID_GLOBAL$$.triggerUserSyncs = triggerUserSyncs; function checkDefinedPlacement(id) { - var placementCodes = $$PREBID_GLOBAL$$._bidsRequested.map(bidSet => bidSet.bids.map(bid => bid.placementCode)) + var adUnitCodes = auctionManager.getBidsRequested().map(bidSet => bidSet.bids.map(bid => bid.adUnitCode)) .reduce(flatten) .filter(uniques); - if (!utils.contains(placementCodes, id)) { + if (!utils.contains(adUnitCodes, id)) { utils.logError('The "' + id + '" placement is not defined.'); return; } @@ -89,18 +64,6 @@ function checkDefinedPlacement(id) { return true; } -/** - * When a request for bids is made any stale bids remaining will be cleared for - * a placement included in the outgoing bid request. - */ -function clearPlacements() { - $$PREBID_GLOBAL$$._bidsRequested = []; - - // leave bids received for ad slots not in this bid request - $$PREBID_GLOBAL$$._bidsReceived = $$PREBID_GLOBAL$$._bidsReceived - .filter(bid => !$$PREBID_GLOBAL$$._adUnitCodes.includes(bid.adUnitCode)); -} - function setRenderSize(doc, width, height) { if (doc.defaultView && doc.defaultView.frameElement) { doc.defaultView.frameElement.width = width; @@ -150,22 +113,7 @@ $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCode = function(adUnitCode) { $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargeting', arguments); - return targeting.getAllTargeting(adUnitCode) - .map(targeting => { - return { - [Object.keys(targeting)[0]]: targeting[Object.keys(targeting)[0]] - .map(target => { - return { - [Object.keys(target)[0]]: target[Object.keys(target)[0]].join(', ') - }; - }).reduce((p, c) => Object.assign(c, p), {}) - }; - }) - .reduce(function (accumulator, targeting) { - var key = Object.keys(targeting)[0]; - accumulator[key] = Object.assign({}, accumulator[key], targeting[key]); - return accumulator; - }, {}); + return targeting.getAllTargeting(adUnitCode); }; /** @@ -176,8 +124,8 @@ $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { $$PREBID_GLOBAL$$.getBidResponses = function () { utils.logInfo('Invoking $$PREBID_GLOBAL$$.getBidResponses', arguments); - const responses = $$PREBID_GLOBAL$$._bidsReceived - .filter(adUnitsFilter.bind(this, $$PREBID_GLOBAL$$._adUnitCodes)); + const responses = auctionManager.getBidsReceived() + .filter(adUnitsFilter.bind(this, auctionManager.getAdUnitCodes())); // find the last requested id to get responses for most recent auction only const currentRequestId = responses && responses.length && responses[responses.length - 1].requestId; @@ -202,7 +150,7 @@ $$PREBID_GLOBAL$$.getBidResponses = function () { */ $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode = function (adUnitCode) { - const bids = $$PREBID_GLOBAL$$._bidsReceived.filter(bid => bid.adUnitCode === adUnitCode); + const bids = auctionManager.getBidsReceived().filter(bid => bid.adUnitCode === adUnitCode); return { bids: bids }; @@ -227,7 +175,7 @@ $$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit) { targeting.resetPresetTargeting(adUnit); // now set new targeting keys - targeting.setTargeting(targetingSet); + targeting.setTargetingForGPT(targetingSet); // emit event events.emit(SET_TARGETING); @@ -250,21 +198,6 @@ $$PREBID_GLOBAL$$.setTargetingForAst = function() { events.emit(SET_TARGETING); }; -/** - * Returns a bool if all the bids have returned or timed out - * @alias module:pbjs.allBidsAvailable - * @return {bool} all bids available - * - * @deprecated This function will be removed in Prebid 1.0 - * Alternative solution is in progress. - * See https://github.com/prebid/Prebid.js/issues/1087 for more details. - */ -$$PREBID_GLOBAL$$.allBidsAvailable = function () { - utils.logWarn('$$PREBID_GLOBAL$$.allBidsAvailable will be removed in Prebid 1.0. Alternative solution is in progress. See https://github.com/prebid/Prebid.js/issues/1087 for more details.'); - utils.logInfo('Invoking $$PREBID_GLOBAL$$.allBidsAvailable', arguments); - return bidmanager.bidsBackAll(); -}; - /** * 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 @@ -278,13 +211,14 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { if (doc && id) { try { // lookup ad by ad Id - const bid = $$PREBID_GLOBAL$$._bidsReceived.find(bid => bid.adId === id); + const bid = auctionManager.findBidByAdId(id); if (bid) { + bid.status = RENDERED; // replace macros according to openRTB with price paid = bid.cpm bid.ad = utils.replaceAuctionPrice(bid.ad, bid.cpm); bid.adUrl = utils.replaceAuctionPrice(bid.adUrl, bid.cpm); // save winning bids - $$PREBID_GLOBAL$$._winningBids.push(bid); + auctionManager.addWinningBid(bid); // emit 'bid won' event here events.emit(BID_WON, bid); @@ -339,42 +273,25 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { } }; -/** - * @alias module:pbjs.clearAuction - */ -$$PREBID_GLOBAL$$.clearAuction = function() { - auctionRunning = false; - // Only automatically sync if the publisher has not chosen to "enableOverride" - let userSyncConfig = config.getConfig('userSync') || {}; - if (!userSyncConfig.enableOverride) { - // Delay the auto sync by the config delay - syncUsers(userSyncConfig.syncDelay); - } - - utils.logMessage('Prebid auction cleared'); - if (bidRequestQueue.length) { - bidRequestQueue.shift()(); - } -}; - /** * @param {Object} requestOptions * @param {function} requestOptions.bidsBackHandler * @param {number} requestOptions.timeout * @param {Array} requestOptions.adUnits * @param {Array} requestOptions.adUnitCodes + * @param {Array} requestOptions.labels * @alias module:pbjs.requestBids */ -$$PREBID_GLOBAL$$.requestBids = function ({ bidsBackHandler, timeout, adUnits, adUnitCodes } = {}) { +$$PREBID_GLOBAL$$.requestBids = function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels } = {}) { events.emit('requestBids'); - const cbTimeout = $$PREBID_GLOBAL$$.cbTimeout = timeout || config.getConfig('bidderTimeout'); + const cbTimeout = timeout || config.getConfig('bidderTimeout'); adUnits = adUnits || $$PREBID_GLOBAL$$.adUnits; utils.logInfo('Invoking $$PREBID_GLOBAL$$.requestBids', arguments); if (adUnitCodes && adUnitCodes.length) { // if specific adUnitCodes supplied filter adUnits for those codes - adUnits = adUnits.filter(unit => adUnitCodes.includes(unit.code)); + adUnits = adUnits.filter(unit => includes(adUnitCodes, unit.code)); } else { // otherwise derive adUnitCodes from adUnits adUnitCodes = adUnits && adUnits.map(unit => unit.code); @@ -400,43 +317,21 @@ $$PREBID_GLOBAL$$.requestBids = function ({ bidsBackHandler, timeout, adUnits, a adUnit.bids = adUnit.bids.filter(nativeBidder); }); - if (auctionRunning) { - bidRequestQueue.push(() => { - $$PREBID_GLOBAL$$.requestBids({ bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes }); - }); - return; - } - - auctionRunning = true; - - // we will use adUnitCodes for filtering the current auction - $$PREBID_GLOBAL$$._adUnitCodes = adUnitCodes; - - bidmanager.externalCallbackReset(); - clearPlacements(); - if (!adUnits || adUnits.length === 0) { utils.logMessage('No adUnits configured. No bids requested.'); if (typeof bidsBackHandler === 'function') { - bidmanager.addOneTimeCallback(bidsBackHandler, false); + // executeCallback, this will only be called in case of first request + try { + bidsBackHandler(); + } catch (e) { + utils.logError('Error executing bidsBackHandler', null, e); + } } - bidmanager.executeCallback(); return; } - // set timeout for all bids - const timedOut = true; - const timeoutCallback = bidmanager.executeCallback.bind(bidmanager, timedOut); - const timer = setTimeout(timeoutCallback, cbTimeout); - setAjaxTimeout(cbTimeout); - if (typeof bidsBackHandler === 'function') { - bidmanager.addOneTimeCallback(bidsBackHandler, timer); - } - - adaptermanager.callBids({ adUnits, adUnitCodes, cbTimeout }); - if ($$PREBID_GLOBAL$$._bidsRequested.length === 0) { - bidmanager.executeCallback(); - } + const auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout, labels}); + auction.callBids(); }; /** @@ -507,46 +402,7 @@ $$PREBID_GLOBAL$$.offEvent = function (event, handler, id) { events.off(event, handler, id); }; -/** - * Add a callback event - * @param {string} eventStr event to attach callback to Options: "allRequestedBidsBack" | "adUnitBidsBack" - * @param {Function} func function to execute. Parameters passed into the function: (bidResObj), [adUnitCode]); - * @alias module:pbjs.addCallback - * @returns {string} id for callback - * - * @deprecated This function will be removed in Prebid 1.0 - * Please use onEvent instead. - */ -$$PREBID_GLOBAL$$.addCallback = function (eventStr, func) { - utils.logWarn('$$PREBID_GLOBAL$$.addCallback will be removed in Prebid 1.0. Please use onEvent instead'); - utils.logInfo('Invoking $$PREBID_GLOBAL$$.addCallback', arguments); - var id = null; - if (!eventStr || !func || typeof func !== 'function') { - utils.logError('error registering callback. Check method signature'); - return id; - } - - id = utils.getUniqueIdentifierStr; - bidmanager.addCallback(id, func, eventStr); - return id; -}; - -/** - * Remove a callback event - * //@param {string} cbId id of the callback to remove - * @alias module:pbjs.removeCallback - * @returns {string} id for callback - * - * @deprecated This function will be removed in Prebid 1.0 - * Please use offEvent instead. - */ -$$PREBID_GLOBAL$$.removeCallback = function (/* cbId */) { - // todo - utils.logWarn('$$PREBID_GLOBAL$$.removeCallback will be removed in Prebid 1.0. Please use offEvent instead.'); - return null; -}; - -/** +/* * Wrapper to register bidderAdapter externally (adaptermanager.registerBidAdapter()) * @param {Function} bidderAdaptor [description] * @param {string} bidderCode [description] @@ -575,22 +431,6 @@ $$PREBID_GLOBAL$$.registerAnalyticsAdapter = function (options) { } }; -/** - * @alias module:pbjs.bidsAvailableForAdapter -*/ -$$PREBID_GLOBAL$$.bidsAvailableForAdapter = function (bidderCode) { - utils.logInfo('Invoking $$PREBID_GLOBAL$$.bidsAvailableForAdapter', arguments); - - $$PREBID_GLOBAL$$._bidsRequested.find(bidderRequest => bidderRequest.bidderCode === bidderCode).bids - .map(bid => { - return Object.assign(bid, bidfactory.createBid(1), { - bidderCode, - adUnitCode: bid.placementCode - }); - }) - .map(bid => $$PREBID_GLOBAL$$._bidsReceived.push(bid)); -}; - /** * Wrapper to bidfactory.createBid() * @param {string} statusCode [description] @@ -602,21 +442,6 @@ $$PREBID_GLOBAL$$.createBid = function (statusCode) { return bidfactory.createBid(statusCode); }; -/** - * Wrapper to bidmanager.addBidResponse - * @param {string} adUnitCode [description] - * @param {Object} bid [description] - * @alias module:pbjs.addBidResponse - * @deprecated This function will be removed in Prebid 1.0 - * Each bidder will be passed a reference to addBidResponse function in callBids as an argument. - * See https://github.com/prebid/Prebid.js/issues/1087 for more details. - */ -$$PREBID_GLOBAL$$.addBidResponse = function (adUnitCode, bid) { - utils.logWarn('$$PREBID_GLOBAL$$.addBidResponse will be removed in Prebid 1.0. Each bidder will be passed a reference to addBidResponse function in callBids as an argument. See https://github.com/prebid/Prebid.js/issues/1087 for more details.'); - utils.logInfo('Invoking $$PREBID_GLOBAL$$.addBidResponse', arguments); - bidmanager.addBidResponse(adUnitCode, bid); -}; - /** * Wrapper to adloader.loadScript * @param {string} tagSrc [description] @@ -664,36 +489,6 @@ $$PREBID_GLOBAL$$.aliasBidder = function (bidderCode, alias) { }; /** - * Sets a default price granularity scheme. - * @param {string|Object} granularity - the granularity scheme. - * @alias module:pbjs.setPriceGranularity - * @deprecated - use pbjs.setConfig({ priceGranularity: }) - * "low": $0.50 increments, capped at $5 CPM - * "medium": $0.10 increments, capped at $20 CPM (the default) - * "high": $0.01 increments, capped at $20 CPM - * "auto": Applies a sliding scale to determine granularity - * "dense": Like "auto", but the bid price granularity uses smaller increments, especially at lower CPMs - * - * Alternatively a custom object can be specified: - * { "buckets" : [{"min" : 0,"max" : 20,"increment" : 0.1,"cap" : true}]}; - * See http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.setPriceGranularity for more details - */ -$$PREBID_GLOBAL$$.setPriceGranularity = function (granularity) { - utils.logWarn('$$PREBID_GLOBAL$$.setPriceGranularity will be removed in Prebid 1.0. Use $$PREBID_GLOBAL$$.setConfig({ priceGranularity: }) instead.') - utils.logInfo('Invoking $$PREBID_GLOBAL$$.setPriceGranularity', arguments); - config.setConfig({ priceGranularity: granularity }); -}; - -/** - * @alias module:pbjs.enableSendAllBids - * @deprecated - use pbjs.setConfig({ enableSendAllBids: }) -*/ -$$PREBID_GLOBAL$$.enableSendAllBids = function () { - config.setConfig({ enableSendAllBids: true }); -}; - -/** - * @alias module:pbjs.getAllWinningBids * The bid response object returned by an external bidder adapter during the auction. * @typedef {Object} AdapterBidResponse * @property {string} pbAg Auto granularity price bucket; CPM <= 5 ? increment = 0.05 : CPM > 5 && CPM <= 10 ? increment = 0.10 : CPM > 10 && CPM <= 20 ? increment = 0.50 : CPM > 20 ? priceCap = 20.00. Example: `"0.80"`. @@ -733,56 +528,9 @@ $$PREBID_GLOBAL$$.enableSendAllBids = function () { * @return {Array} A list of bids that have won their respective auctions. */ $$PREBID_GLOBAL$$.getAllWinningBids = function () { - return $$PREBID_GLOBAL$$._winningBids; -}; - -/** - * Build master video tag from publishers adserver tag - * @param {string} adserverTag default url - * @param {Object} options options for video tag - * @alias module:pbjs.buildMasterVideoTagFromAdserverTag - * @deprecated Include the dfpVideoSupport module in your build, and use the $$PREBID_GLOBAL$$.adservers.dfp.buildVideoAdUrl function instead. - * This function will be removed in Prebid 1.0. - */ -$$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag = function (adserverTag, options) { - utils.logWarn('$$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag will be removed in Prebid 1.0. Include the dfpVideoSupport module in your build, and use the $$PREBID_GLOBAL$$.adservers.dfp.buildVideoAdUrl function instead'); - utils.logInfo('Invoking $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag', arguments); - var urlComponents = parseURL(adserverTag); - - // return original adserverTag if no bids received - if ($$PREBID_GLOBAL$$._bidsReceived.length === 0) { - return adserverTag; - } - - var masterTag = ''; - if (options.adserver.toLowerCase() === 'dfp') { - var dfpAdserverObj = adserver.dfpAdserver(options, urlComponents); - if (!dfpAdserverObj.verifyAdserverTag()) { - utils.logError('Invalid adserverTag, required google params are missing in query string'); - } - dfpAdserverObj.appendQueryParams(); - masterTag = formatURL(dfpAdserverObj.urlComponents); - } else { - utils.logError('Only DFP adserver is supported'); - return; - } - return masterTag; + return auctionManager.getAllWinningBids(); }; -/** - * Set the order bidders are called in. Valid values are: - * - * "fixed": Bidders will be called in the order in which they were defined within the adUnit.bids array. - * "random": Bidders will be called in random order. - * - * If never called, Prebid will use "random" as the default. - * - * @param {string} order One of the valid orders, described above. - * @alias module:pbjs.setBidderSequence - * @deprecated - use pbjs.setConfig({ bidderSequence: }) - */ -$$PREBID_GLOBAL$$.setBidderSequence = adaptermanager.setBidderSequence; - /** * Get array of highest cpm bids for all adUnits, or highest cpm bid * object for the given adUnit @@ -794,44 +542,6 @@ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { return targeting.getWinningBids(adUnitCode); }; -/** - * Set config for server to server header bidding - * @deprecated - use pbjs.setConfig({ s2sConfig: }) - * @typedef {Object} options - required - * @property {boolean} enabled enables S2S bidding - * @property {string[]} bidders bidders to request S2S - * === optional params below === - * @property {string} [endpoint] endpoint to contact - * @property {number} [timeout] timeout for S2S bidders - should be lower than `pbjs.requestBids({timeout})` - * @property {string} [adapter] adapter code to use for S2S - * @property {string} [syncEndpoint] endpoint URL for syncing cookies - * @property {boolean} [cookieSet] enables cookieSet functionality - * @alias module:pbjs.setS2SConfig - */ -$$PREBID_GLOBAL$$.setS2SConfig = function(options) { - if (!utils.contains(Object.keys(options), 'accountId')) { - utils.logError('accountId missing in Server to Server config'); - return; - } - - if (!utils.contains(Object.keys(options), 'bidders')) { - utils.logError('bidders missing in Server to Server config'); - return; - } - - const config = Object.assign({ - enabled: false, - endpoint: CONSTANTS.S2S.DEFAULT_ENDPOINT, - timeout: 1000, - maxBids: 1, - adapter: CONSTANTS.S2S.ADAPTER, - syncEndpoint: CONSTANTS.S2S.SYNC_ENDPOINT, - cookieSet: true, - bidders: [] - }, options); - adaptermanager.setS2SConfig(config); -}; - /** * Get Prebid config options * @param {Object} options diff --git a/src/secureCreatives.js b/src/secureCreatives.js index efc1386fde3..424d1402831 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -6,6 +6,9 @@ import events from './events'; import { fireNativeTrackers } from './native'; import { EVENTS } from './constants'; +import { isSlotMatchingAdUnitCode } from './utils'; +import { auctionManager } from './auctionManager'; +import find from 'core-js/library/fn/array/find'; const BID_WON = EVENTS.BID_WON; @@ -23,7 +26,7 @@ function receiveMessage(ev) { } if (data.adId) { - const adObject = $$PREBID_GLOBAL$$._bidsReceived.find(function (bid) { + const adObject = find(auctionManager.getBidsReceived(), function (bid) { return bid.adId === data.adId; }); @@ -31,7 +34,7 @@ function receiveMessage(ev) { sendAdToCreative(adObject, data.adServerDomain, ev.source); // save winning bids - $$PREBID_GLOBAL$$._winningBids.push(adObject); + auctionManager.addWinningBid(adObject); events.emit(BID_WON, adObject); } @@ -43,7 +46,7 @@ function receiveMessage(ev) { // }), '*'); if (data.message === 'Prebid Native') { fireNativeTrackers(data, adObject); - $$PREBID_GLOBAL$$._winningBids.push(adObject); + auctionManager.addWinningBid(adObject); events.emit(BID_WON, adObject); } } @@ -66,11 +69,9 @@ function sendAdToCreative(adObject, remoteDomain, source) { } function resizeRemoteCreative({ adUnitCode, width, height }) { - const iframe = document.getElementById(window.googletag.pubads() - .getSlots().find(slot => { - return slot.getAdUnitPath() === adUnitCode || - slot.getSlotElementId() === adUnitCode; - }).getSlotElementId()).querySelector('iframe'); + const iframe = document.getElementById( + find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot) + .getSlotElementId()).querySelector('iframe'); iframe.width = '' + width; iframe.height = '' + height; diff --git a/src/sizeMapping.js b/src/sizeMapping.js index 9529c567308..4a4c9ff77c1 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -1,61 +1,85 @@ +import { config } from 'src/config'; +import includes from 'core-js/library/fn/array/includes'; + +let sizeConfig = []; + /** - * @module sizeMapping + * @typedef {object} SizeConfig + * + * @property {string} [mediaQuery] A CSS media query string that will to be interpreted by window.matchMedia. If the + * media query matches then the this config will be active and sizesSupported will filter bid and adUnit sizes. If + * this property is not present then this SizeConfig will only be active if triggered manually by a call to + * pbjs.setConfig({labels:['label']) specifying one of the labels present on this SizeConfig. + * @property {Array} sizesSupported The sizes to be accepted if this SizeConfig is enabled. + * @property {Array} labels The active labels to match this SizeConfig to an adUnits and/or bidders. */ -import * as utils from './utils'; -let _win; - -function mapSizes(adUnit) { - if (!isSizeMappingValid(adUnit.sizeMapping)) { - return adUnit.sizes; - } - const width = getScreenWidth(); - if (!width) { - // size not detected - get largest value set for desktop - const mapping = adUnit.sizeMapping.reduce((prev, curr) => { - return prev.minWidth < curr.minWidth ? curr : prev; - }); - if (mapping.sizes && mapping.sizes.length) { - return mapping.sizes; - } - return adUnit.sizes; - } - let sizes = ''; - const mapping = adUnit.sizeMapping.find(sizeMapping => { - return width >= sizeMapping.minWidth; - }); - if (mapping && mapping.sizes && mapping.sizes.length) { - sizes = mapping.sizes; - utils.logMessage(`AdUnit : ${adUnit.code} resized based on device width to : ${sizes}`); - } else { - utils.logMessage(`AdUnit : ${adUnit.code} not mapped to any sizes for device width. This request will be suppressed.`); - } - return sizes; -} -function isSizeMappingValid(sizeMapping) { - if (utils.isArray(sizeMapping) && sizeMapping.length > 0) { - return true; - } - utils.logInfo('No size mapping defined'); - return false; +/** + * + * @param {Array} config + */ +export function setSizeConfig(config) { + sizeConfig = config; } +config.getConfig('sizeConfig', config => setSizeConfig(config.sizeConfig)); -function getScreenWidth(win) { - var w = win || _win || window; - var d = w.document; +/** + * Resolves the unique set of the union of all sizes and labels that are active from a SizeConfig.mediaQuery match + * @param {Array} labels Labels specified on adUnit or bidder + * @param {boolean} labelAll if true, all labels must match to be enabled + * @param {Array} activeLabels Labels passed in through requestBids + * @param {Array>} sizes Sizes specified on adUnit + * @param {Array} configs + * @returns {{labels: Array, sizes: Array>}} + */ +export function resolveStatus({labels = [], labelAll = false, activeLabels = []} = {}, sizes = [], configs = sizeConfig) { + let maps = evaluateSizeConfig(configs); - if (w.innerWidth) { - return w.innerWidth; - } else if (d.body.clientWidth) { - return d.body.clientWidth; - } else if (d.documentElement.clientWidth) { - return d.documentElement.clientWidth; + let filteredSizes; + if (maps.shouldFilter) { + filteredSizes = sizes.filter(size => maps.sizesSupported[size]); + } else { + filteredSizes = sizes; } - return 0; -} -function setWindow(win) { - _win = win; + return { + active: filteredSizes.length > 0 && ( + labels.length === 0 || ( + (!labelAll && ( + labels.some(label => maps.labels[label]) || + labels.some(label => includes(activeLabels, label)) + )) || + (labelAll && ( + labels.reduce((result, label) => !result ? result : ( + maps.labels[label] || includes(activeLabels, label) + ), true) + )) + ) + ), + sizes: filteredSizes + }; } -export { mapSizes, getScreenWidth, setWindow }; +function evaluateSizeConfig(configs) { + return configs.reduce((results, config) => { + if ( + typeof config === 'object' && + typeof config.mediaQuery === 'string' && + matchMedia(config.mediaQuery).matches + ) { + if (Array.isArray(config.sizesSupported)) { + results.shouldFilter = true; + } + ['labels', 'sizesSupported'].forEach( + type => (config[type] || []).forEach( + thing => results[type][thing] = true + ) + ); + } + return results; + }, { + labels: {}, + sizesSupported: {}, + shouldFilter: false + }); +} diff --git a/src/targeting.js b/src/targeting.js index 3081100c8e4..2169af21b2b 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -1,210 +1,366 @@ -import { uniques, isGptPubadsDefined, getHighestCpm, adUnitsFilter, groupBy } from './utils'; +import { uniques, isGptPubadsDefined, getHighestCpm, groupBy, isAdUnitCodeMatchingSlot, timestamp } from './utils'; import { config } from './config'; import { NATIVE_TARGETING_KEYS } from './native'; -const bidmanager = require('./bidmanager'); -const utils = require('./utils'); -var CONSTANTS = require('./constants'); +import { auctionManager } from './auctionManager'; +import includes from 'core-js/library/fn/array/includes'; + +const utils = require('./utils.js'); +var CONSTANTS = require('./constants.json'); -var targeting = exports; var pbTargetingKeys = []; -targeting.resetPresetTargeting = function(adUnitCode) { - if (isGptPubadsDefined()) { +export const BID_TARGETING_SET = 'targetingSet'; + +const MAX_DFP_KEYLENGTH = 20; + +// return unexpired bids +export const isBidExpired = (bid) => (timestamp() - bid.responseTimestamp) < bid.ttl * 1000; + +// return bids whose status is not set. Winning bid can have status `targetingSet` or `rendered`. +const isUnusedBid = (bid) => bid && ((bid.status && bid.status === BID_TARGETING_SET) || !bid.status); + +/** + * @typedef {Object.} targeting + * @property {string} targeting_key + */ + +/** + * @typedef {Object.[]>[]} targetingArray + */ + +export function newTargeting(auctionManager) { + let targeting = {}; + + targeting.resetPresetTargeting = function(adUnitCode) { + if (isGptPubadsDefined()) { + const adUnitCodes = getAdUnitCodes(adUnitCode); + const adUnits = auctionManager.getAdUnits().filter(adUnit => includes(adUnitCodes, adUnit.code)); + window.googletag.pubads().getSlots().forEach(slot => { + pbTargetingKeys.forEach(function(key) { + // reset only registered adunits + adUnits.forEach(function(unit) { + if (unit.code === slot.getAdUnitPath() || + unit.code === slot.getSlotElementId()) { + slot.setTargeting(key, null); + } + }); + }); + }); + } + }; + + /** + * Returns all ad server targeting for all ad units. + * @param {string=} adUnitCode + * @return {Object.} targeting + */ + targeting.getAllTargeting = function(adUnitCode) { const adUnitCodes = getAdUnitCodes(adUnitCode); - const adUnits = $$PREBID_GLOBAL$$.adUnits.filter(adUnit => adUnitCodes.includes(adUnit.code)); - window.googletag.pubads().getSlots().forEach(slot => { - pbTargetingKeys.forEach(function(key) { - // reset only registered adunits - adUnits.forEach(function(unit) { - if (unit.code === slot.getAdUnitPath() || - unit.code === slot.getSlotElementId()) { - slot.setTargeting(key, null); + + // Get targeting for the winning bid. Add targeting for any bids that have + // `alwaysUseBid=true`. If sending all bids is enabled, add targeting for losing bids. + var targeting = getWinningBidTargeting(adUnitCodes) + .concat(getCustomBidTargeting(adUnitCodes)) + .concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes) : []); + + // store a reference of the targeting keys + targeting.map(adUnitCode => { + Object.keys(adUnitCode).map(key => { + adUnitCode[key].map(targetKey => { + if (pbTargetingKeys.indexOf(Object.keys(targetKey)[0]) === -1) { + pbTargetingKeys = Object.keys(targetKey).concat(pbTargetingKeys); } }); }); }); + + targeting = flattenTargeting(targeting); + return targeting; + }; + + /** + * Converts targeting array and flattens to make it easily iteratable + * e.g: Sample input to this function + * ``` + * [ + * { + * "div-gpt-ad-1460505748561-0": [{"hb_bidder": ["appnexusAst"]}] + * }, + * { + * "div-gpt-ad-1460505748561-0": [{"hb_bidder_appnexusAs": ["appnexusAst"]}] + * } + * ] + * ``` + * Resulting array + * ``` + * { + * "div-gpt-ad-1460505748561-0": { + * "hb_bidder": "appnexusAst", + * "hb_bidder_appnexusAs": "appnexusAst" + * } + * } + * ``` + * + * @param {targetingArray} targeting + * @return {Object.} targeting + */ + function flattenTargeting(targeting) { + let targetingObj = targeting.map(targeting => { + return { + [Object.keys(targeting)[0]]: targeting[Object.keys(targeting)[0]] + .map(target => { + return { + [Object.keys(target)[0]]: target[Object.keys(target)[0]].join(', ') + }; + }).reduce((p, c) => Object.assign(c, p), {}) + }; + }).reduce(function (accumulator, targeting) { + var key = Object.keys(targeting)[0]; + accumulator[key] = Object.assign({}, accumulator[key], targeting[key]); + return accumulator; + }, {}); + return targetingObj; } -}; - -targeting.getAllTargeting = function(adUnitCode) { - const adUnitCodes = getAdUnitCodes(adUnitCode); - - // Get targeting for the winning bid. Add targeting for any bids that have - // `alwaysUseBid=true`. If sending all bids is enabled, add targeting for losing bids. - var targeting = getWinningBidTargeting(adUnitCodes) - .concat(getAlwaysUseBidTargeting(adUnitCodes)) - .concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes) : []); - - // store a reference of the targeting keys - targeting.map(adUnitCode => { - Object.keys(adUnitCode).map(key => { - adUnitCode[key].map(targetKey => { - if (pbTargetingKeys.indexOf(Object.keys(targetKey)[0]) === -1) { - pbTargetingKeys = Object.keys(targetKey).concat(pbTargetingKeys); - } - }); - }); - }); - return targeting; -}; - -targeting.setTargeting = function(targetingConfig) { - window.googletag.pubads().getSlots().forEach(slot => { - targetingConfig.filter(targeting => Object.keys(targeting)[0] === slot.getAdUnitPath() || - Object.keys(targeting)[0] === slot.getSlotElementId()) - .forEach(targeting => targeting[Object.keys(targeting)[0]] - .forEach(key => { - key[Object.keys(key)[0]] - .map((value) => { - utils.logMessage(`Attempting to set key value for slot: ${slot.getSlotElementId()} key: ${Object.keys(key)[0]} value: ${value}`); + + /** + * Sets targeting for DFP + * @param {Object.>} targetingConfig + */ + targeting.setTargetingForGPT = function(targetingConfig) { + window.googletag.pubads().getSlots().forEach(slot => { + Object.keys(targetingConfig).filter(isAdUnitCodeMatchingSlot(slot)) + .forEach(targetId => + Object.keys(targetingConfig[targetId]).forEach(key => { + let valueArr = targetingConfig[targetId][key].split(','); + 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(Object.keys(key)[0], value); + }).forEach(value => { + slot.setTargeting(key, value); }); - })); - }); -}; + }) + ) + }) + }; -/** - * normlizes input to a `adUnit.code` array - * @param {(string|string[])} adUnitCode [description] - * @return {string[]} AdUnit code array - */ -function getAdUnitCodes(adUnitCode) { - if (typeof adUnitCode === 'string') { - return [adUnitCode]; - } else if (utils.isArray(adUnitCode)) { - return adUnitCode; + /** + * normlizes input to a `adUnit.code` array + * @param {(string|string[])} adUnitCode [description] + * @return {string[]} AdUnit code array + */ + function getAdUnitCodes(adUnitCode) { + if (typeof adUnitCode === 'string') { + return [adUnitCode]; + } else if (utils.isArray(adUnitCode)) { + return adUnitCode; + } + return auctionManager.getAdUnitCodes() || []; } - return $$PREBID_GLOBAL$$._adUnitCodes || []; -} -/** - * Returns top bids for a given adUnit or set of adUnits. - * @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes - * @return {[type]} [description] - */ -targeting.getWinningBids = function(adUnitCode) { - const adUnitCodes = getAdUnitCodes(adUnitCode); - - return $$PREBID_GLOBAL$$._bidsReceived - .filter(bid => adUnitCodes.includes(bid.adUnitCode)) - .filter(bid => bid.cpm > 0) - .map(bid => bid.adUnitCode) - .filter(uniques) - .map(adUnitCode => $$PREBID_GLOBAL$$._bidsReceived - .filter(bid => bid.adUnitCode === adUnitCode ? bid : null) - .reduce(getHighestCpm, getEmptyBid(adUnitCode))); -}; - -targeting.setTargetingForAst = function() { - let targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); - Object.keys(targeting).forEach(targetId => - Object.keys(targeting[targetId]).forEach(key => { - utils.logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${targeting[targetId][key]}`); - // setKeywords supports string and array as value - if (utils.isStr(targeting[targetId][key]) || utils.isArray(targeting[targetId][key])) { - let keywordsObj = {}; - let input = 'hb_adid'; - let nKey = (key.substring(0, input.length) === input) ? key.toUpperCase() : key; - keywordsObj[nKey] = targeting[targetId][key]; - window.apntag.setKeywords(targetId, keywordsObj); + function getBidsReceived() { + return auctionManager.getBidsReceived() + .filter(isUnusedBid) + .filter(exports.isBidExpired) + } + + /** + * Returns top bids for a given adUnit or set of adUnits. + * @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes + * @return {[type]} [description] + */ + targeting.getWinningBids = function(adUnitCode) { + const adUnitCodes = getAdUnitCodes(adUnitCode); + + return getBidsReceived() + .filter(bid => includes(adUnitCodes, bid.adUnitCode)) + .filter(bid => bid.cpm > 0) + .map(bid => bid.adUnitCode) + .filter(uniques) + .map(adUnitCode => getBidsReceived() + .filter(bid => bid.adUnitCode === adUnitCode ? bid : null) + .reduce(getHighestCpm, getEmptyBid(adUnitCode))); + }; + + /** + * Sets targeting for AST + */ + targeting.setTargetingForAst = function() { + let astTargeting = targeting.getAllTargeting(); + Object.keys(astTargeting).forEach(targetId => + Object.keys(astTargeting[targetId]).forEach(key => { + utils.logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${astTargeting[targetId][key]}`); + // setKeywords supports string and array as value + if (utils.isStr(astTargeting[targetId][key]) || utils.isArray(astTargeting[targetId][key])) { + let keywordsObj = {}; + let input = 'hb_adid'; + let nKey = (key.substring(0, input.length) === input) ? key.toUpperCase() : key; + keywordsObj[nKey] = astTargeting[targetId][key]; + window.apntag.setKeywords(targetId, keywordsObj); + } + }) + ); + }; + + /** + * Get targeting key value pairs for winning bid. + * @param {string[]} AdUnit code array + * @return {targetingArray} winning bids targeting + */ + function getWinningBidTargeting(adUnitCodes) { + let winners = targeting.getWinningBids(adUnitCodes); + winners.forEach((winner) => { + winner.status = BID_TARGETING_SET; + }); + + // TODO : Add losing bids to pool from here ? + let standardKeys = getStandardKeys(); + + winners = winners.map(winner => { + return { + [winner.adUnitCode]: Object.keys(winner.adserverTargeting) + .filter(key => + typeof winner.sendStandardTargeting === 'undefined' || + winner.sendStandardTargeting || + standardKeys.indexOf(key) === -1) + .map(key => ({ + [(key === 'hb_deal') ? `${key}_${winner.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH) : key.substring(0, MAX_DFP_KEYLENGTH)]: [winner.adserverTargeting[key]] + })) + }; + }); + + return winners; + } + + function getStandardKeys() { + return auctionManager.getStandardBidderAdServerTargeting() // in case using a custom standard key set + .map(targeting => targeting.key) + .concat(CONSTANTS.TARGETING_KEYS).filter(uniques); // standard keys defined in the library. + } + + /** + * Merge custom adserverTargeting with same key name for same adUnitCode. + * e.g: Appnexus defining custom keyvalue pair foo:bar and Rubicon defining custom keyvalue pair foo:baz will be merged to foo: ['bar','baz'] + * + * @param {Object[]} acc Accumulator for reducer. It will store updated bidResponse objects + * @param {Object} bid BidResponse + * @param {number} index current index + * @param {Array} arr original array + */ + function mergeAdServerTargeting(acc, bid, index, arr) { + function concatTargetingValue(key) { + return function(currentBidElement) { + if (!utils.isArray(currentBidElement.adserverTargeting[key])) { + currentBidElement.adserverTargeting[key] = [currentBidElement.adserverTargeting[key]]; + } + currentBidElement.adserverTargeting[key] = currentBidElement.adserverTargeting[key].concat(bid.adserverTargeting[key]).filter(uniques); + delete bid.adserverTargeting[key]; } - }) - ); -}; + } -function getWinningBidTargeting(adUnitCodes) { - let winners = targeting.getWinningBids(adUnitCodes); - let standardKeys = getStandardKeys(); + function hasSameAdunitCodeAndKey(key) { + return function(currentBidElement) { + return currentBidElement.adUnitCode === bid.adUnitCode && currentBidElement.adserverTargeting[key] + } + } - winners = winners.map(winner => { - return { - [winner.adUnitCode]: Object.keys(winner.adserverTargeting) - .filter(key => - typeof winner.sendStandardTargeting === 'undefined' || - winner.sendStandardTargeting || - standardKeys.indexOf(key) === -1) - .map(key => ({ [key.substring(0, 20)]: [winner.adserverTargeting[key]] })) - }; - }); + Object.keys(bid.adserverTargeting) + .filter(getCustomKeys()) + .forEach(key => { + if (acc.length) { + acc.filter(hasSameAdunitCodeAndKey(key)) + .forEach(concatTargetingValue(key)); + } + }); + acc.push(bid); + return acc; + } - return winners; -} + function getCustomKeys() { + let standardKeys = getStandardKeys(); + return function(key) { + return standardKeys.indexOf(key) === -1; + } + } -function getStandardKeys() { - return bidmanager.getStandardBidderAdServerTargeting() // in case using a custom standard key set - .map(targeting => targeting.key) - .concat(CONSTANTS.TARGETING_KEYS).filter(uniques); // standard keys defined in the library. -} + function truncateCustomKeys(bid) { + return { + [bid.adUnitCode]: Object.keys(bid.adserverTargeting) + // Get only the non-standard keys of the losing bids, since we + // don't want to override the standard keys of the winning bid. + .filter(getCustomKeys()) + .map(key => { + return { + [key.substring(0, MAX_DFP_KEYLENGTH)]: [bid.adserverTargeting[key]] + }; + }) + } + } -/** - * Get custom targeting keys for bids that have `alwaysUseBid=true`. - */ -function getAlwaysUseBidTargeting(adUnitCodes) { - let standardKeys = getStandardKeys(); - return $$PREBID_GLOBAL$$._bidsReceived - .filter(adUnitsFilter.bind(this, adUnitCodes)) - .map(bid => { - if (bid.alwaysUseBid) { - return { - [bid.adUnitCode]: Object.keys(bid.adserverTargeting).map(key => { - // Get only the non-standard keys of the losing bids, since we - // don't want to override the standard keys of the winning bid. - if (standardKeys.indexOf(key) > -1) { - return; - } + /** + * Get custom targeting key value pairs for bids. + * @param {string[]} AdUnit code array + * @return {targetingArray} bids with custom targeting defined in bidderSettings + */ + function getCustomBidTargeting(adUnitCodes) { + return getBidsReceived() + .filter(bid => includes(adUnitCodes, bid.adUnitCode)) + .map(bid => Object.assign({}, bid)) + .reduce(mergeAdServerTargeting, []) + .map(truncateCustomKeys) + .filter(bid => bid); // removes empty elements in array; + } - return { [key.substring(0, 20)]: [bid.adserverTargeting[key]] }; - }).filter(key => key) // remove empty elements + /** + * Get targeting key value pairs for non-winning bids. + * @param {string[]} AdUnit code array + * @return {targetingArray} all non-winning bids targeting + */ + function getBidLandscapeTargeting(adUnitCodes) { + const standardKeys = CONSTANTS.TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); + const bids = []; + // bucket by adUnitcode + let buckets = groupBy(getBidsReceived(), 'adUnitCode'); + // filter top bid for each bucket by bidder + Object.keys(buckets).forEach(bucketKey => { + let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); + Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(getHighestCpm, getEmptyBid()))); + }); + // populate targeting keys for the remaining bids + return bids.map(bid => { + if (bid.adserverTargeting) { + return { + [bid.adUnitCode]: getTargetingMap(bid, standardKeys.filter( + key => typeof bid.adserverTargeting[key] !== 'undefined') + ) }; } - }) - .filter(bid => bid); // removes empty elements in array; -} + }).filter(bid => bid); // removes empty elements in array + } -function getBidLandscapeTargeting(adUnitCodes) { - const standardKeys = CONSTANTS.TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); - const bids = []; - // bucket by adUnitcode - let buckets = groupBy($$PREBID_GLOBAL$$._bidsReceived, 'adUnitCode'); - // filter top bid for each bucket by bidder - Object.keys(buckets).forEach(bucketKey => { - let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); - Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(getHighestCpm, getEmptyBid()))); - }); - // populate targeting keys for the remaining bids - return bids.map(bid => { - if (bid.adserverTargeting) { + function getTargetingMap(bid, keys) { + return keys.map(key => { return { - [bid.adUnitCode]: getTargetingMap(bid, standardKeys.filter( - key => typeof bid.adserverTargeting[key] !== 'undefined') - ) + [`${key}_${bid.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH)]: [bid.adserverTargeting[key]] }; + }); + } + + targeting.isApntagDefined = function() { + if (window.apntag && utils.isFn(window.apntag.setKeywords)) { + return true; } - }).filter(bid => bid); // removes empty elements in array -} + }; -function getTargetingMap(bid, keys) { - return keys.map(key => { + function getEmptyBid(adUnitCode) { return { - [`${key}_${bid.bidderCode}`.substring(0, 20)]: [bid.adserverTargeting[key]] + adUnitCode: adUnitCode, + cpm: 0, + adserverTargeting: {}, + timeToRespond: 0 }; - }); -} - -targeting.isApntagDefined = function() { - if (window.apntag && utils.isFn(window.apntag.setKeywords)) { - return true; } -}; - -function getEmptyBid(adUnitCode) { - return { - adUnitCode: adUnitCode, - cpm: 0, - adserverTargeting: {}, - timeToRespond: 0 - }; + return targeting; } + +export const targeting = newTargeting(auctionManager); diff --git a/src/utils.js b/src/utils.js index 24d07723742..d5657845492 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,7 @@ import { config } from './config'; import clone from 'just-clone'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; var CONSTANTS = require('./constants'); var _loggingChecked = false; @@ -572,8 +574,8 @@ export function flatten(a, b) { return a.concat(b); } -export function getBidRequest(id) { - return $$PREBID_GLOBAL$$._bidsRequested.map(bidSet => bidSet.bids.find(bid => bid.bidId === id)).find(bid => bid); +export function getBidRequest(id, bidsRequested) { + return find(bidsRequested.map(bidSet => find(bidSet.bids, bid => bid.bidId === id)), bid => bid); } export function getKeys(obj) { @@ -631,7 +633,7 @@ export function shuffle(array) { } export function adUnitsFilter(filter, bid) { - return filter.includes((bid && bid.placementCode) || (bid && bid.adUnitCode)); + return includes(filter, bid && bid.adUnitCode); } /** @@ -665,15 +667,8 @@ export function replaceAuctionPrice(str, cpm) { return str.replace(/\$\{AUCTION_PRICE\}/g, cpm); } -export function getBidderRequestAllAdUnits(bidder) { - return $$PREBID_GLOBAL$$._bidsRequested.find(request => request.bidderCode === bidder); -} - -export function getBidderRequest(bidder, adUnitCode) { - return $$PREBID_GLOBAL$$._bidsRequested.find(request => { - return request.bids - .filter(bid => bid.bidder === bidder && bid.placementCode === adUnitCode).length > 0; - }) || { start: null, requestId: null }; +export function timestamp() { + return new Date().getTime(); } export function cookiesAreEnabled() { @@ -784,17 +779,56 @@ export function isValidMediaTypes(mediaTypes) { const types = Object.keys(mediaTypes); - if (!types.every(type => SUPPORTED_MEDIA_TYPES.includes(type))) { + if (!types.every(type => includes(SUPPORTED_MEDIA_TYPES, type))) { return false; } if (mediaTypes.video && mediaTypes.video.context) { - return SUPPORTED_STREAM_TYPES.includes(mediaTypes.video.context); + return includes(SUPPORTED_STREAM_TYPES, mediaTypes.video.context); } 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, requestId: null }; +} + +/** + * Returns the origin + */ +export function getOrigin() { + // IE10 does not have this property. https://gist.github.com/hbogs/7908703 + if (!window.location.origin) { + return window.location.protocol + '//' + window.location.hostname + (window.location.port ? ':' + window.location.port : ''); + } else { + return window.location.origin; + } +} + +const compareCodeAndSlot = (slot, adUnitCode) => slot.getAdUnitPath() === adUnitCode || slot.getSlotElementId() === adUnitCode; + +/** + * Returns filter function to match adUnitCode in slot + * @param {object} slot GoogleTag slot + * @return {function} filter function + */ +export function isAdUnitCodeMatchingSlot(slot) { + return (adUnitCode) => compareCodeAndSlot(slot, adUnitCode); +} + +/** + * Returns filter function to match adUnitCode in slot + * @param {string} adUnitCode AdUnit code + * @return {function} filter function + */ +export function isSlotMatchingAdUnitCode(adUnitCode) { + return (slot) => compareCodeAndSlot(slot, adUnitCode); +} + /** * Constructs warning message for when unsupported bidders are dropped from an adunit * @param {Object} adUnit ad unit from which the bidder is being dropped diff --git a/src/video.js b/src/video.js index 22255068cc0..8e0775a6d62 100644 --- a/src/video.js +++ b/src/video.js @@ -1,6 +1,7 @@ import { videoAdapters } from './adaptermanager'; import { getBidRequest, deepAccess, logError } from './utils'; import { config } from '../src/config'; +import includes from 'core-js/library/fn/array/includes'; const VIDEO_MEDIA_TYPE = 'video'; const OUTSTREAM = 'outstream'; @@ -13,7 +14,7 @@ export const videoAdUnit = adUnit => { const mediaTypes = deepAccess(adUnit, 'mediaTypes.video'); return mediaType || mediaTypes; }; -export const videoBidder = bid => videoAdapters.includes(bid.bidder); +export const videoBidder = bid => includes(videoAdapters, bid.bidder); export const hasNonVideoBidder = adUnit => adUnit.bids.filter(bid => !videoBidder(bid)).length; @@ -24,11 +25,12 @@ export const hasNonVideoBidder = adUnit => /** * Validate that the assets required for video context are present on the bid - * @param {VideoBid} bid video bid to validate - * @return {boolean} If object is valid + * @param {VideoBid} bid Video bid to validate + * @param {BidRequest[]} bidRequests All bid requests for an auction + * @return {Boolean} If object is valid */ -export function isValidVideoBid(bid) { - const bidRequest = getBidRequest(bid.adId); +export function isValidVideoBid(bid, bidRequests) { + const bidRequest = getBidRequest(bid.adId, bidRequests); const videoMediaType = bidRequest && deepAccess(bidRequest, 'mediaTypes.video'); @@ -37,11 +39,11 @@ export function isValidVideoBid(bid) { // if context not defined assume default 'instream' for video bids // instream bids require a vast url or vast xml content if (!bidRequest || (videoMediaType && context !== OUTSTREAM)) { - // xml-only video bids require prebid-cache to be enabled - if (!config.getConfig('usePrebidCache') && bid.vastXml && !bid.vastUrl) { + // xml-only video bids require a prebid cache url + if (!config.getConfig('cache.url') && bid.vastXml && !bid.vastUrl) { logError(` - This bid contains only vastXml and will not work when prebid-cache is disabled. - Try enabling prebid-cache with pbjs.setConfig({ usePrebidCache: true }); + 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: "..."} }); `); return false; } diff --git a/src/videoCache.js b/src/videoCache.js index fe126fad6e0..2af980316fa 100644 --- a/src/videoCache.js +++ b/src/videoCache.js @@ -10,8 +10,7 @@ */ import { ajax } from './ajax'; - -const BASE_URL = 'https://prebid.adnxs.com/pbc/v1/cache' +import { config } from '../src/config'; /** * @typedef {object} CacheableUrlBid @@ -119,12 +118,12 @@ export function store(bids, done) { puts: bids.map(toStorageRequest) }; - ajax(BASE_URL, shimStorageCallback(done), JSON.stringify(requestData), { + ajax(config.getConfig('cache.url'), shimStorageCallback(done), JSON.stringify(requestData), { contentType: 'text/plain', withCredentials: true }); } export function getCacheUrl(id) { - return `${BASE_URL}?uuid=${id}`; + return `${config.getConfig('cache.url')}?uuid=${id}`; } diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index 8108da3c555..8dbbe265cca 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -317,7 +317,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '0x0', 'foobar': '0x0' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'appnexus', @@ -346,7 +349,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'appnexus', @@ -375,7 +381,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '728x90', 'foobar': '728x90' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'pagescience', @@ -403,7 +412,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'brightcom', @@ -430,7 +442,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'brealtime', @@ -458,7 +473,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'pubmatic', @@ -487,7 +505,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'rubicon', @@ -514,7 +535,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x600', 'foobar': '300x600' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 } ]; } @@ -1015,7 +1039,10 @@ export function getBidResponsesFromAPI() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'brealtime', @@ -1043,7 +1070,10 @@ export function getBidResponsesFromAPI() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'pubmatic', @@ -1072,7 +1102,10 @@ export function getBidResponsesFromAPI() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'rubicon', @@ -1099,7 +1132,10 @@ export function getBidResponsesFromAPI() { 'hb_pb': '10.00', 'hb_size': '300x600', 'foobar': '300x600' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 } ] } @@ -1110,7 +1146,7 @@ export function getBidResponsesFromAPI() { export function getAdServerTargeting() { return { '/19968336/header-bid-tag-0': { - 'foobar': '300x250', + 'foobar': '0x0,300x250,300x600', 'hb_size': '300x250', 'hb_pb': '10.00', 'hb_adid': '233bcbee889d46d', @@ -1179,11 +1215,7 @@ export function getTargetingKeys() { ], [ 'foobar', - '300x250' - ], - [ - 'foobar', - '300x250' + ['0x0', '300x250', '300x600'] ] ]; } @@ -1197,7 +1229,7 @@ export function getTargetingKeysBidLandscape() { 'appnexus' ], [ - 'hb_adid', + 'hb_adid_appnexus', '233bcbee889d46d' ], [ @@ -1210,11 +1242,7 @@ export function getTargetingKeysBidLandscape() { ], [ 'foobar', - '300x250' - ], - [ - 'foobar', - '300x250' + ['0x0', '300x250', '300x600'] ], [ 'hb_bidder_triplelift', @@ -1236,10 +1264,6 @@ export function getTargetingKeysBidLandscape() { 'hb_bidder_appnexus', 'appnexus' ], - [ - 'hb_adid_appnexus', - '233bcbee889d46d' - ], [ 'hb_pb_appnexus', '10.00' diff --git a/test/fixtures/video/adUnit.json b/test/fixtures/video/adUnit.json index 6d2b7c385ad..df55eb25d79 100644 --- a/test/fixtures/video/adUnit.json +++ b/test/fixtures/video/adUnit.json @@ -4,7 +4,7 @@ "mediaType": "video", "bids": [ { - "bidder": "appnexusAst", + "bidder": "appnexus", "params": { "placementId": "9333431", "video": { diff --git a/test/fixtures/video/bidRequest.json b/test/fixtures/video/bidRequest.json index 75f054611c4..f8306e27662 100644 --- a/test/fixtures/video/bidRequest.json +++ b/test/fixtures/video/bidRequest.json @@ -1,10 +1,10 @@ { "auctionStart": 1462918897459, - "bidderCode": "appnexusAst", + "bidderCode": "appnexus", "bidderRequestId": "2946b569352ef2", "bids": [ { - "bidder": "appnexusAst", + "bidder": "appnexus", "params": { "placementId": "9333431", "video": { diff --git a/test/fixtures/video/vastPayloadResponse.json b/test/fixtures/video/vastPayloadResponse.json index 9b621c21d30..7c388de41ed 100644 --- a/test/fixtures/video/vastPayloadResponse.json +++ b/test/fixtures/video/vastPayloadResponse.json @@ -1,8 +1,8 @@ { "adUnitCode": "video1", - "bidder": "appnexusAst", - "bidderCode": "appnexusAst", - "code": "appnexusAst", + "bidder": "appnexus", + "bidderCode": "appnexus", + "code": "appnexus", "dealId": "foo", "cpm": 0.1, "height": 480, diff --git a/test/fixtures/video/vastUrlResponse.json b/test/fixtures/video/vastUrlResponse.json index cba0798251d..f3b023dc7bb 100644 --- a/test/fixtures/video/vastUrlResponse.json +++ b/test/fixtures/video/vastUrlResponse.json @@ -1,8 +1,8 @@ { "adUnitCode": "video1", - "bidder": "appnexusAst", - "bidderCode": "appnexusAst", - "code": "appnexusAst", + "bidder": "appnexus", + "bidderCode": "appnexus", + "code": "appnexus", "dealId": "foo", "cpm": 0.1, "height": 480, diff --git a/test/pages/video.html b/test/pages/video.html index 8d28650cbfc..c6a72b6e26b 100644 --- a/test/pages/video.html +++ b/test/pages/video.html @@ -36,7 +36,7 @@ }, bids: [ { - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '9333431', video: { diff --git a/test/spec/api_spec.js b/test/spec/api_spec.js index b3e2e0fc666..41fafb080ad 100755 --- a/test/spec/api_spec.js +++ b/test/spec/api_spec.js @@ -47,10 +47,6 @@ describe('Publisher API', function () { assert.isFunction($$PREBID_GLOBAL$$.setTargetingForGPTAsync); }); - it('should have function $$PREBID_GLOBAL$$.allBidsAvailable', function () { - assert.isFunction($$PREBID_GLOBAL$$.allBidsAvailable); - }); - it('should have function $$PREBID_GLOBAL$$.renderAd', function () { assert.isFunction($$PREBID_GLOBAL$$.renderAd); }); @@ -67,14 +63,6 @@ describe('Publisher API', function () { assert.isFunction($$PREBID_GLOBAL$$.addAdUnits); }); - it('should have function $$PREBID_GLOBAL$$.addCallback', function () { - assert.isFunction($$PREBID_GLOBAL$$.addCallback); - }); - - it('should have function $$PREBID_GLOBAL$$.removeCallback', function () { - assert.isFunction($$PREBID_GLOBAL$$.removeCallback); - }); - it('should have function $$PREBID_GLOBAL$$.aliasBidder', function () { assert.isFunction($$PREBID_GLOBAL$$.aliasBidder); }); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js new file mode 100644 index 00000000000..c773974d177 --- /dev/null +++ b/test/spec/auctionmanager_spec.js @@ -0,0 +1,861 @@ +import { auctionManager, newAuctionManager } from 'src/auctionManager'; +import { getKeyValueTargetingPairs } from 'src/auction'; +import CONSTANTS from 'src/constants.json'; +import { adjustBids } from 'src/auction'; +import * as auctionModule from 'src/auction'; +import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; +import * as ajaxLib from 'src/ajax'; + +var assert = require('assert'); + +/* use this method to test individual files instead of the whole prebid.js project */ + +// TODO refactor to use the spec files +var utils = require('../../src/utils'); +var bidfactory = require('../../src/bidfactory'); +var fixtures = require('../fixtures/fixtures'); +var adaptermanager = require('src/adaptermanager'); +var events = require('src/events'); + +function timestamp() { + return new Date().getTime(); +} + +describe('auctionmanager.js', function () { + describe('getKeyValueTargetingPairs', function () { + var bid = {}; + var bidPriceCpm = 5.578; + var bidPbLg = 5.50; + var bidPbMg = 5.50; + var bidPbHg = 5.57; + var bidPbAg = 5.50; + + var adUnitCode = '12345'; + var bidderCode = 'appnexus'; + var size = '300x250'; + var adId = '1adId'; + + before(function () { + bid.cpm = bidPriceCpm; + bid.pbLg = bidPbLg; + bid.pbMg = bidPbMg; + bid.pbHg = bidPbHg; + bid.pbAg = bidPbAg; + + bid.height = 300; + bid.width = 250; + bid.adUnitCode = adUnitCode; + bid.getSize = function () { + return this.height + 'x' + this.width; + }; + bid.bidderCode = bidderCode; + bid.adId = adId; + }); + + it('No bidder level configuration defined - default', function () { + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': bidPbMg, + 'hb_size': size + }; + var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + assert.deepEqual(response, expected); + }); + + it('Custom configuration for all bidders', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + standard: { + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return bidResponse.pbHg; + } + }, { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + } + ] + + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': bidPbHg, + 'hb_size': size + }; + var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + assert.deepEqual(response, expected); + }); + + it('Custom configuration for one bidder', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + appnexus: { + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return bidResponse.pbHg; + } + }, { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + } + ] + + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': bidPbHg, + 'hb_size': size + }; + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + }); + + it('Custom configuration for one bidder - not matched', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + nonExistentBidder: { + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return bidResponse.pbHg; + } + }, { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + } + ] + + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': bidPbMg, + 'hb_size': size + }; + var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + assert.deepEqual(response, expected); + }); + + it('Custom bidCpmAdjustment for one bidder and inherit standard but doesn\'t use standard bidCpmAdjustment', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + appnexus: { + bidCpmAdjustment: function (bidCpm) { + return bidCpm * 0.7; + }, + }, + standard: { + bidCpmAdjustment: function (bidCpm) { + return 200; + }, + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return 10.00; + } + } + ] + + } + }; + + var expected = { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': 10.0 }; + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + }); + + it('Standard bidCpmAdjustment changes the bid of any bidder', function () { + const bid = Object.assign({}, + bidfactory.createBid(2), + fixtures.getBidResponses()[5] + ); + + assert.equal(bid.cpm, 0.5); + + $$PREBID_GLOBAL$$.bidderSettings = + { + standard: { + bidCpmAdjustment: function (bidCpm) { + return bidCpm * 0.5; + } + } + }; + + adjustBids(bid) + assert.equal(bid.cpm, 0.25); + }); + + it('Custom bidCpmAdjustment AND custom configuration for one bidder and inherit standard settings', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + appnexus: { + bidCpmAdjustment: function (bidCpm) { + return bidCpm * 0.7; + }, + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return 15.00; + } + } + ] + }, + standard: { + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return 10.00; + }, + }, + { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + } + ] + + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': 15.0, + 'hb_size': '300x250' + }; + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + }); + + it('sendStandardTargeting=false, and inherit custom', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + appnexus: { + sendStandardTargeting: false, + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + return bidResponse.pbHg; + } + } + ] + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': 5.57, + 'hb_size': '300x250' + }; + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + assert.equal(bid.sendStandardTargeting, false); + }); + + it('suppressEmptyKeys=true', function() { + $$PREBID_GLOBAL$$.bidderSettings = + { + standard: { + suppressEmptyKeys: true, + adserverTargeting: [ + { + key: 'aKeyWithAValue', + val: 42 + }, + { + key: 'aKeyWithAnEmptyValue', + val: '' + } + ] + } + }; + + var expected = { + 'aKeyWithAValue': 42 + }; + + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + }); + }); + + describe('adjustBids', () => { + it('should adjust bids if greater than zero and pass copy of bid object', () => { + const bid = Object.assign({}, + bidfactory.createBid(2), + fixtures.getBidResponses()[5] + ); + + assert.equal(bid.cpm, 0.5); + + $$PREBID_GLOBAL$$.bidderSettings = + { + brealtime: { + bidCpmAdjustment: function (bidCpm, bidObj) { + assert.deepEqual(bidObj, bid); + if (bidObj.adUnitCode === 'negative') { + return bidCpm * -0.5; + } + if (bidObj.adUnitCode === 'zero') { + return 0; + } + return bidCpm * 0.5; + }, + }, + standard: { + adserverTargeting: [ + ] + } + }; + + // negative + bid.adUnitCode = 'negative'; + adjustBids(bid) + assert.equal(bid.cpm, 0.5); + + // positive + bid.adUnitCode = 'normal'; + adjustBids(bid) + assert.equal(bid.cpm, 0.25); + + // zero + bid.adUnitCode = 'zero'; + adjustBids(bid) + assert.equal(bid.cpm, 0); + + // reset bidderSettings so we don't mess up further tests + $$PREBID_GLOBAL$$.bidderSettings = {}; + }); + }); + + describe('addBidResponse', () => { + let createAuctionStub; + let adUnits; + let adUnitCodes; + let spec; + let auction; + let ajaxStub; + const BIDDER_CODE = 'sampleBidder'; + let makeRequestsStub; + let bids = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'bidderCode': BIDDER_CODE, + 'requestId': '4d0a6829338a07', + 'creativeId': 'id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + + let bidRequests = [{ + 'bidderCode': BIDDER_CODE, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }]; + + before(() => { + makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + makeRequestsStub.returns(bidRequests); + + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + return function(url, callback) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callback.success('response body', { getResponseHeader: fakeResponse }); + } + }); + }); + + after(() => { + ajaxStub.restore(); + adaptermanager.makeBidRequests.restore(); + }); + + describe('when auction timeout is 3000', () => { + beforeEach(() => { + adUnits = [{ + code: 'adUnit-code', + bids: [ + {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + ] + }]; + adUnitCodes = ['adUnit-code']; + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + + spec = { + code: BIDDER_CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + }); + + afterEach(() => { + auctionModule.newAuction.restore(); + }); + + it('should return proper price bucket increments for dense mode when cpm is in range 0-3', () => { + bids[0].cpm = '1.99'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, '1.99', '0 - 3 hits at to 1 cent increment'); + }); + + it('should return proper price bucket increments for dense mode when cpm is in range 3-8', () => { + bids[0].cpm = '4.39'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, '4.35', '3 - 8 hits at 5 cent increment'); + }); + + it('should return proper price bucket increments for dense mode when cpm is in range 8-20', () => { + bids[0].cpm = '19.99'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, '19.50', '8 - 20 hits at 50 cent increment'); + }); + + it('should return proper price bucket increments for dense mode when cpm is 20+', () => { + bids[0].cpm = '73.07'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, '20.00', '20+ caps at 20.00'); + }); + + it('should place dealIds in adserver targeting', () => { + bids[0].dealId = 'test deal'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.adserverTargeting[`hb_deal`], 'test deal', 'dealId placed in adserverTargeting'); + }); + + it('should pass through default adserverTargeting sent from adapter', () => { + bids[0].adserverTargeting = {}; + bids[0].adserverTargeting.extra = 'stuff'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.adserverTargeting.hb_bidder, 'sampleBidder'); + assert.equal(registeredBid.adserverTargeting.extra, 'stuff'); + }); + + it('installs publisher-defined renderers on bids', () => { + let bidRequests = [{ + 'bidderCode': BIDDER_CODE, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c', + 'renderer': { + url: 'renderer.js', + render: (bid) => bid + } + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }]; + + makeRequestsStub.returns(bidRequests); + let bids1 = Object.assign({}, + bids[0], + { + bidderCode: BIDDER_CODE, + mediaType: 'video-outstream', + } + ); + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids1); + auction.callBids(); + const addedBid = auction.getBidsReceived().pop(); + assert.equal(addedBid.renderer.url, 'renderer.js'); + }); + }); + + describe('with auction timeout 20', () => { + let auction; + let adUnits; + let adUnitCodes; + let createAuctionStub; + let spec; + let getBidderRequestStub; + let eventsEmitSpy; + + beforeEach(() => { + adUnits = [{ + code: 'adUnit-code', + bids: [ + {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + ] + }]; + adUnitCodes = ['adUnit-code']; + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 20}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + getBidderRequestStub = sinon.stub(utils, 'getBidderRequest'); + + let newBidRequest = Object.assign({}, bidRequests[0], {'start': 1000}); + getBidderRequestStub.returns(newBidRequest); + + spec = { + code: BIDDER_CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + eventsEmitSpy = sinon.spy(events, 'emit'); + }); + + afterEach(() => { + auctionModule.newAuction.restore(); + utils.getBidderRequest.restore(); + events.emit.restore(); + }); + + it('should emit BID_TIMEOUT for timed out bids', () => { + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + assert.ok(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BID_TIMEOUT), 'emitted events BID_TIMEOUT'); + }); + }); + }); + + describe('addBidResponse', () => { + let createAuctionStub; + let adUnits; + let adUnitCodes; + let spec; + let spec1; + let auction; + let ajaxStub; + const BIDDER_CODE = 'sampleBidder'; + const BIDDER_CODE1 = 'sampleBidder1'; + + let makeRequestsStub; + let bids = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'bidderCode': BIDDER_CODE, + 'requestId': '4d0a6829338a07', + 'creativeId': 'id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + + let bids1 = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'bidderCode': BIDDER_CODE1, + 'requestId': '5d0a6829338a07', + 'creativeId': 'id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + + let bidRequests = [{ + 'bidderCode': BIDDER_CODE, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }, { + 'bidderCode': BIDDER_CODE1, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '661f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE1, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '5d0a6829338a07', + 'bidderRequestId': '661f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713623, + 'timeout': 3000 + }]; + + before(() => { + makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + makeRequestsStub.returns(bidRequests); + + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + return function(url, callback) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callback.success('response body', { getResponseHeader: fakeResponse }); + } + }); + }); + + after(() => { + ajaxStub.restore(); + adaptermanager.makeBidRequests.restore(); + }); + + beforeEach(() => { + adUnits = [{ + code: 'adUnit-code', + bids: [ + {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + ] + }, { + code: 'adUnit-code-1', + bids: [ + {bidder: BIDDER_CODE1, params: {placementId: 'id'}}, + ] + }]; + adUnitCodes = ['adUnit-code', 'adUnit-code-1']; + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + + spec = { + code: BIDDER_CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + + spec1 = { + code: BIDDER_CODE1, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + }); + + afterEach(() => { + auctionModule.newAuction.restore(); + }); + + it('should not alter bid adID', () => { + registerBidder(spec); + registerBidder(spec1); + + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + + spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec1.isBidRequestValid.returns(true); + spec1.interpretResponse.returns(bids1); + + auction.callBids(); + + const addedBid2 = auction.getBidsReceived().pop(); + assert.equal(addedBid2.adId, bids1[0].requestId); + const addedBid1 = auction.getBidsReceived().pop(); + assert.equal(addedBid1.adId, bids[0].requestId); + }); + + it('should not add banner bids that have no width or height', () => { + bids1[0].width = undefined; + bids1[0].height = undefined; + + registerBidder(spec); + registerBidder(spec1); + + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + + spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec1.isBidRequestValid.returns(true); + spec1.interpretResponse.returns(bids1); + + auction.callBids(); + + let length = auction.getBidsReceived().length; + const addedBid2 = auction.getBidsReceived().pop(); + assert.notEqual(addedBid2.adId, bids1[0].requestId); + assert.equal(length, 1); + }); + }); +}); diff --git a/test/spec/bidmanager_spec.js b/test/spec/bidmanager_spec.js deleted file mode 100644 index 967258a7fbc..00000000000 --- a/test/spec/bidmanager_spec.js +++ /dev/null @@ -1,684 +0,0 @@ -var assert = require('assert'); - -/* use this method to test individual files instead of the whole prebid.js project */ - -// TODO refactor to use the spec files -var utils = require('../../src/utils'); -var bidmanager = require('../../src/bidmanager'); -var bidfactory = require('../../src/bidfactory'); -var fixtures = require('../fixtures/fixtures'); - -function timestamp() { - return new Date().getTime(); -} - -describe('replaceTokenInString', function () { - it('should replace all given tokens in a String', function () { - var tokensToReplace = { - 'foo': 'bar', - 'zap': 'quux' - }; - - var output = utils.replaceTokenInString('hello %FOO%, I am %ZAP%', tokensToReplace, '%'); - assert.equal(output, 'hello bar, I am quux'); - }); - - it('should ignore tokens it does not see', function () { - var output = utils.replaceTokenInString('hello %FOO%', {}, '%'); - - assert.equal(output, 'hello %FOO%'); - }); -}); - -describe('bidmanager.js', function () { - describe('getKeyValueTargetingPairs', function () { - var bid = {}; - var bidPriceCpm = 5.578; - var bidPbLg = 5.50; - var bidPbMg = 5.50; - var bidPbHg = 5.57; - var bidPbAg = 5.50; - - var adUnitCode = '12345'; - var bidderCode = 'appnexus'; - var size = '300x250'; - var adId = '1adId'; - - before(function () { - bid.cpm = bidPriceCpm; - bid.pbLg = bidPbLg; - bid.pbMg = bidPbMg; - bid.pbHg = bidPbHg; - bid.pbAg = bidPbAg; - - bid.height = 300; - bid.width = 250; - bid.adUnitCode = adUnitCode; - bid.getSize = function () { - return this.height + 'x' + this.width; - }; - bid.bidderCode = bidderCode; - bid.adId = adId; - }); - - it('No bidder level configuration defined - default', function () { - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbMg, - 'hb_size': size - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Custom configuration for all bidders', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - standard: { - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return bidResponse.pbHg; - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - } - ] - - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbHg, - 'hb_size': size - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Custom configuration for one bidder', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - appnexus: { - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return bidResponse.pbHg; - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - } - ] - - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbHg, - 'hb_size': size - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Custom configuration for one bidder - not matched', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - nonExistentBidder: { - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return bidResponse.pbHg; - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - } - ] - - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbMg, - 'hb_size': size - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Custom bidCpmAdjustment for one bidder and inherit standard but doesn\'t use standard bidCpmAdjustment', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - appnexus: { - bidCpmAdjustment: function (bidCpm) { - return bidCpm * 0.7; - }, - }, - standard: { - bidCpmAdjustment: function (bidCpm) { - return 200; - }, - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return 10.00; - } - } - ] - - } - }; - - var expected = { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': 10.0 }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Standard bidCpmAdjustment changes the bid of any bidder', function () { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[5] - ); - - assert.equal(bid.cpm, 0.5); - - $$PREBID_GLOBAL$$.bidderSettings = - { - standard: { - bidCpmAdjustment: function (bidCpm) { - return bidCpm * 0.5; - } - } - }; - - bidmanager.adjustBids(bid) - assert.equal(bid.cpm, 0.25); - }); - - it('Custom bidCpmAdjustment AND custom configuration for one bidder and inherit standard settings', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - appnexus: { - bidCpmAdjustment: function (bidCpm) { - return bidCpm * 0.7; - }, - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return 15.00; - } - } - ] - }, - standard: { - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return 10.00; - }, - }, - { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - } - ] - - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': 15.0, - 'hb_size': '300x250' - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('alwaysUseBid=true, sendStandardTargeting=false, and inherit custom', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - appnexus: { - alwaysUseBid: true, - sendStandardTargeting: false, - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - return bidResponse.pbHg; - } - } - ] - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': 5.57, - 'hb_size': '300x250' - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - assert.equal(bid.alwaysUseBid, true); - assert.equal(bid.sendStandardTargeting, false); - }); - - it('suppressEmptyKeys=true', function() { - $$PREBID_GLOBAL$$.bidderSettings = - { - standard: { - suppressEmptyKeys: true, - adserverTargeting: [ - { - key: 'aKeyWithAValue', - val: 42 - }, - { - key: 'aKeyWithAnEmptyValue', - val: '' - } - ] - } - }; - - var expected = { - 'aKeyWithAValue': 42 - }; - - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - }); - - describe('adjustBids', () => { - it('should adjust bids if greater than zero and pass copy of bid object', () => { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[5] - ); - - assert.equal(bid.cpm, 0.5); - - $$PREBID_GLOBAL$$.bidderSettings = - { - brealtime: { - bidCpmAdjustment: function (bidCpm, bidObj) { - assert.deepEqual(bidObj, bid); - if (bidObj.adUnitCode === 'negative') { - return bidCpm * -0.5; - } - if (bidObj.adUnitCode === 'zero') { - return 0; - } - return bidCpm * 0.5; - }, - }, - standard: { - adserverTargeting: [ - ] - } - }; - - // negative - bid.adUnitCode = 'negative'; - bidmanager.adjustBids(bid) - assert.equal(bid.cpm, 0.5); - - // positive - bid.adUnitCode = 'normal'; - bidmanager.adjustBids(bid) - assert.equal(bid.cpm, 0.25); - - // zero - bid.adUnitCode = 'zero'; - bidmanager.adjustBids(bid) - assert.equal(bid.cpm, 0); - - // reset bidderSettings so we don't mess up further tests - $$PREBID_GLOBAL$$.bidderSettings = {}; - }); - }); - - describe('addBidResponse', () => { - before(() => { - $$PREBID_GLOBAL$$.adUnits = fixtures.getAdUnits(); - }); - it('should return proper price bucket increments for dense mode', () => { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[5] - ); - - // 0 - 3 dollars - bid.cpm = '1.99'; - let expectedIncrement = '1.99'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - // pop this bid because another test relies on global $$PREBID_GLOBAL$$._bidsReceived - let registeredBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(registeredBid.pbDg, expectedIncrement, '0 - 3 hits at to 1 cent increment'); - - // 3 - 8 dollars - bid.cpm = '4.39'; - expectedIncrement = '4.35'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - registeredBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(registeredBid.pbDg, expectedIncrement, '3 - 8 hits at 5 cent increment'); - - // 8 - 20 dollars - bid.cpm = '19.99'; - expectedIncrement = '19.50'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - registeredBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(registeredBid.pbDg, expectedIncrement, '8 - 20 hits at 50 cent increment'); - - // 20+ dollars - bid.cpm = '73.07'; - expectedIncrement = '20.00'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - registeredBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(registeredBid.pbDg, expectedIncrement, '20+ caps at 20.00'); - }); - - it('should place dealIds in adserver targeting', () => { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[0] - ); - - bid.dealId = 'test deal'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - const addedBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid.adserverTargeting[`hb_deal`], bid.dealId, 'dealId placed in adserverTargeting'); - }); - - it('should pass through default adserverTargeting sent from adapter', () => { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[0] - ); - - bid.adserverTargeting.extra = 'stuff'; - - bidmanager.addBidResponse(bid.adUnitCode, bid); - const addedBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid.adserverTargeting.hb_bidder, 'triplelift'); - assert.equal(addedBid.adserverTargeting.extra, 'stuff'); - }); - - it('should not alter bid adID', () => { - const bid1 = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[1] - ); - const bid2 = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[3] - ); - - bidmanager.addBidResponse(bid1.adUnitCode, Object.assign({}, bid1)); - bidmanager.addBidResponse(bid2.adUnitCode, Object.assign({}, bid2)); - - const addedBid2 = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid2.adId, bid2.adId); - const addedBid1 = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid1.adId, bid1.adId); - }); - - it('should not add banner bids that have no width or height', () => { - const bid = Object.assign({}, - bidfactory.createBid(1), - { - width: undefined, - height: undefined - } - ); - - bidmanager.addBidResponse('adUnitCode', bid); - - const addedBid = $$PREBID_GLOBAL$$._bidsReceived[$$PREBID_GLOBAL$$._bidsReceived.length - 1]; - - assert.notEqual(bid.adId, addedBid.adId); - }); - - it('should add banner bids that have no width or height but single adunit size', () => { - sinon.stub(utils, 'getBidderRequest', () => ({ - start: timestamp(), - bids: [{ - sizes: [[300, 250]], - }] - })); - - const bid = Object.assign({}, - bidfactory.createBid(1), - { - width: undefined, - height: undefined - } - ); - - bidmanager.addBidResponse('adUnitCode', bid); - - const addedBid = $$PREBID_GLOBAL$$._bidsReceived[$$PREBID_GLOBAL$$._bidsReceived.length - 1]; - - assert.equal(bid.adId, addedBid.adId); - assert.equal(addedBid.width, 300); - assert.equal(addedBid.height, 250); - - utils.getBidderRequest.restore(); - }); - - it('should not add native bids that do not have required assets', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - start: timestamp(), - bidder: 'appnexusAst', - mediaTypes: { - native: { - title: {required: true}, - } - }, - })); - - const bid = Object.assign({}, - bidfactory.createBid(1), - { - bidderCode: 'appnexusAst', - mediaType: 'native', - native: {title: undefined} - } - ); - - const bidsRecCount = $$PREBID_GLOBAL$$._bidsReceived.length; - bidmanager.addBidResponse('adUnit-code', bid); - assert.equal(bidsRecCount, $$PREBID_GLOBAL$$._bidsReceived.length); - - utils.getBidRequest.restore(); - }); - - it('should add native bids that do have required assets', () => { - const bidRequest = () => ({ - start: timestamp(), - bidder: 'appnexusAst', - mediaTypes: { - native: { - title: {required: true}, - } - }, - }); - sinon.stub(utils, 'getBidRequest', bidRequest); - sinon.stub(utils, 'getBidderRequest', bidRequest); - - const bid = Object.assign({}, - bidfactory.createBid(1), - { - bidderCode: 'appnexusAst', - mediaType: 'native', - native: { - title: 'foo', - clickUrl: 'example.link' - } - } - ); - - const bidsRecCount = $$PREBID_GLOBAL$$._bidsReceived.length; - bidmanager.addBidResponse('adUnit-code', bid); - assert.equal(bidsRecCount + 1, $$PREBID_GLOBAL$$._bidsReceived.length); - - utils.getBidRequest.restore(); - utils.getBidderRequest.restore(); - }); - - it('installs publisher-defined renderers on bids', () => { - sinon.stub(utils, 'getBidderRequest', () => ({ - start: timestamp(), - bids: [{ - renderer: { - url: 'renderer.js', - render: (bid) => bid - } - }] - })); - - const bid = Object.assign({}, bidfactory.createBid(1), { - bidderCode: 'appnexusAst', - mediaType: 'video-outstream', - }); - - bidmanager.addBidResponse('adUnit-code', bid); - const addedBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid.renderer.url, 'renderer.js'); - - utils.getBidderRequest.restore(); - }); - - it('requires a renderer on outstream bids', () => { - const bidRequest = () => ({ - start: timestamp(), - bidder: 'appnexusAst', - mediaTypes: { - video: {context: 'outstream'} - }, - }); - - sinon.stub(utils, 'getBidRequest', bidRequest); - sinon.stub(utils, 'getBidderRequest', bidRequest); - - const bid = Object.assign({}, - bidfactory.createBid(1), - { - bidderCode: 'appnexusAst', - mediaType: 'video', - renderer: {render: () => true, url: 'render.js'}, - } - ); - - const bidsRecCount = $$PREBID_GLOBAL$$._bidsReceived.length; - bidmanager.addBidResponse('adUnit-code', bid); - assert.equal(bidsRecCount + 1, $$PREBID_GLOBAL$$._bidsReceived.length); - - utils.getBidRequest.restore(); - utils.getBidderRequest.restore(); - }); - }); -}); diff --git a/test/spec/config_spec.js b/test/spec/config_spec.js index e99e739d630..342319b472f 100644 --- a/test/spec/config_spec.js +++ b/test/spec/config_spec.js @@ -10,16 +10,19 @@ let setDefaults; describe('config API', () => { let logErrorSpy; + let logWarnSpy; beforeEach(() => { const config = newConfig(); getConfig = config.getConfig; setConfig = config.setConfig; setDefaults = config.setDefaults; logErrorSpy = sinon.spy(utils, 'logError'); + logWarnSpy = sinon.spy(utils, 'logWarn'); }); afterEach(() => { utils.logError.restore(); + utils.logWarn.restore(); }); it('setConfig is a function', () => { @@ -59,34 +62,16 @@ describe('config API', () => { expect(getConfig('debug')).to.be.true; }); - // remove test when @deprecated $$PREBID_GLOBAL$$.logging removed - it('gets legacy logging in deprecation window', () => { - $$PREBID_GLOBAL$$.logging = false; - expect(getConfig('debug')).to.equal(false); - }); - it('sets bidderTimeout', () => { setConfig({ bidderTimeout: 1000 }); expect(getConfig('bidderTimeout')).to.be.equal(1000); }); - // remove test when @deprecated $$PREBID_GLOBAL$$.bidderTimeout removed - it('gets legacy bidderTimeout in deprecation window', () => { - $$PREBID_GLOBAL$$.bidderTimeout = 5000; - expect(getConfig('bidderTimeout')).to.equal(5000); - }); - it('gets user-defined publisherDomain', () => { setConfig({ publisherDomain: 'fc.kahuna' }); expect(getConfig('publisherDomain')).to.equal('fc.kahuna'); }); - // remove test when @deprecated $$PREBID_GLOBAL$$.publisherDomain removed - it('gets legacy publisherDomain in deprecation window', () => { - $$PREBID_GLOBAL$$.publisherDomain = 'ad.example.com'; - expect(getConfig('publisherDomain')).to.equal('ad.example.com'); - }); - it('gets default userSync config', () => { const DEFAULT_USERSYNC = { syncEnabled: true, @@ -169,4 +154,15 @@ describe('config API', () => { const error = 'Prebid Error: no value passed to `setPriceGranularity()`'; assert.ok(logErrorSpy.calledWith(error), 'expected error was logged'); }); + + it('should log a warning on invalid values', () => { + setConfig({ bidderSequence: 'unrecognized sequence' }); + expect(logWarnSpy.calledOnce).to.equal(true); + }); + + it('should not log warnings when given recognized values', () => { + setConfig({ bidderSequence: 'fixed' }); + setConfig({ bidderSequence: 'random' }); + expect(logWarnSpy.called).to.equal(false); + }); }); diff --git a/test/spec/e2e/gpt-examples/gpt_outstream.html b/test/spec/e2e/gpt-examples/gpt_outstream.html index 2230248886b..42ba48c98e7 100644 --- a/test/spec/e2e/gpt-examples/gpt_outstream.html +++ b/test/spec/e2e/gpt-examples/gpt_outstream.html @@ -45,7 +45,7 @@ mediaType: 'video-outstream', bids: [ { - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '5768085', video: { @@ -62,7 +62,7 @@ mediaType: 'video-outstream', bids: [ { - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '5768085', video: { diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index edb9958ae66..4754e4d1fa5 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -1,12 +1,21 @@ +const { userSync } = require('../../../src/userSync'); +const { config } = require('../../../src/config'); + const { expect } = require('chai'); -const utils = require('../../../src/utils'); -const { isBidRequestValid, buildRequests, interpretResponse, getUserSyncs } = require('../../../modules/33acrossBidAdapter'); + +const { + isBidRequestValid, + buildRequests, + interpretResponse, + getUserSyncs +} = require('../../../modules/33acrossBidAdapter'); describe('33acrossBidAdapter:', function () { const BIDDER_CODE = '33across'; const SITE_ID = 'pub1234'; const PRODUCT_ID = 'product1'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; + const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch'; beforeEach(function() { this.bidRequests = [ @@ -21,12 +30,12 @@ describe('33acrossBidAdapter:', function () { adUnitCode: 'div-id', requestId: 'r1', sizes: [ - [300, 250], - [728, 90] + [ 300, 250 ], + [ 728, 90 ] ], transactionId: 't1' } - ] + ]; this.sandbox = sinon.sandbox.create(); }); @@ -113,7 +122,7 @@ describe('33acrossBidAdapter:', function () { describe('buildRequests:', function() { it('returns corresponding server requests for each valid bidRequest', function() { const ttxRequest = { - imp: [{ + imp: [ { banner: { format: [ { @@ -133,7 +142,7 @@ describe('33acrossBidAdapter:', function () { prod: PRODUCT_ID } } - }], + } ], site: { id: SITE_ID }, @@ -149,23 +158,19 @@ describe('33acrossBidAdapter:', function () { } } const builtServerRequests = buildRequests(this.bidRequests); - expect(builtServerRequests).to.deep.equal([serverRequest]); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); expect(builtServerRequests.length).to.equal(1); }); - it('returns corresponding server requests for each valid test bidRequest', function() { - delete this.bidRequests[0].params.siteId; - this.bidRequests[0].params.site = { - id: SITE_ID, - page: 'http://test-url.com' - } - this.bidRequests[0].params.customHeaders = { - foo: 'bar' - }; - this.bidRequests[0].params.url = '//staging-ssc.33across.com/api/v1/hb'; + it('returns corresponding test server requests for each valid bidRequest', function() { + this.sandbox.stub(config, 'getConfig', () => { + return { + 'url': 'https://foo.com/hb/' + } + }); const ttxRequest = { - imp: [{ + imp: [ { banner: { format: [ { @@ -185,28 +190,24 @@ describe('33acrossBidAdapter:', function () { prod: PRODUCT_ID } } - }], + } ], site: { - id: SITE_ID, - page: 'http://test-url.com' + id: SITE_ID }, id: 'b1' }; const serverRequest = { method: 'POST', - url: '//staging-ssc.33across.com/api/v1/hb', + url: 'https://foo.com/hb/', data: JSON.stringify(ttxRequest), options: { contentType: 'application/json', - withCredentials: false, - customHeaders: { - foo: 'bar' - } + withCredentials: false } }; const builtServerRequests = buildRequests(this.bidRequests); - expect(builtServerRequests).to.deep.equal([serverRequest]); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); expect(builtServerRequests.length).to.equal(1); }); @@ -216,6 +217,46 @@ describe('33acrossBidAdapter:', function () { }); describe('interpretResponse', function() { + beforeEach(function() { + this.ttxRequest = { + imp: [ { + banner: { + format: [ + { + w: 300, + h: 250, + ext: {} + }, + { + w: 728, + h: 90, + ext: {} + } + ] + }, + ext: { + ttx: { + prod: PRODUCT_ID + } + } + } ], + site: { + id: SITE_ID, + page: 'http://test-url.com' + }, + id: 'b1' + }; + this.serverRequest = { + method: 'POST', + url: '//staging-ssc.33across.com/api/v1/hb', + data: JSON.stringify(this.ttxRequest), + options: { + contentType: 'application/json', + withCredentials: false + } + }; + }); + context('when exactly one bid is returned', function() { it('interprets and returns the single bid response', function() { const serverResponse = { @@ -224,7 +265,7 @@ describe('33acrossBidAdapter:', function () { id: 'b1', seatbid: [ { - bid: [{ + bid: [ { id: '1', adm: '

I am an ad

', ext: { @@ -235,7 +276,7 @@ describe('33acrossBidAdapter:', function () { h: 250, w: 300, price: 0.0938 - }] + } ] } ] }; @@ -253,7 +294,7 @@ describe('33acrossBidAdapter:', function () { netRevenue: true } - expect(interpretResponse({body: serverResponse})).to.deep.equal([bidResponse]); + expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([ bidResponse ]); }); }); @@ -266,7 +307,7 @@ describe('33acrossBidAdapter:', function () { seatbid: [] }; - expect(interpretResponse({body: serverResponse})).to.deep.equal([]); + expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([]); }); }); @@ -278,7 +319,7 @@ describe('33acrossBidAdapter:', function () { id: 'b1', seatbid: [ { - bid: [{ + bid: [ { id: '1', adm: '

I am an ad

', ext: { @@ -305,7 +346,7 @@ describe('33acrossBidAdapter:', function () { ] }, { - bid: [{ + bid: [ { id: '3', adm: '

I am an ad

', ext: { @@ -316,7 +357,7 @@ describe('33acrossBidAdapter:', function () { h: 250, w: 300, price: 0.0938 - }] + } ] } ] }; @@ -334,109 +375,46 @@ describe('33acrossBidAdapter:', function () { netRevenue: true } - expect(interpretResponse({body: serverResponse})).to.deep.equal([bidResponse]); + expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([ bidResponse ]); }); }); - }); - - describe('getUserSyncs', function() { - beforeEach(function() { - this.ttxBids = [ - { - params: { - siteId: 'id1', - productId: 'p1' - } - }, - { - params: { - siteId: 'id2', - productId: 'p1' - } - } - ]; - this.testTTXBids = [ - { - params: { - site: { id: 'id1' }, - productId: 'p1', - syncUrl: 'https://staging-de.tynt.com/deb/v2?m=xch' - } - }, - { - params: { - site: { id: 'id2' }, - productId: 'p1', - syncUrl: 'https://staging-de.tynt.com/deb/v2?m=xch' - } + context('and register user sync', function() { + it('via the production endpoint', function() { + const spy = this.sandbox.spy(userSync, 'registerSync'); + const serverResponse = { + cur: 'USD', + ext: {}, + id: 'b1', + seatbid: [] } - ]; + interpretResponse({ body: serverResponse }, this.serverRequest); + const syncUrl = `${SYNC_ENDPOINT}&id=${this.ttxRequest.site.id}`; - this.syncs = [ - { - type: 'iframe', - url: 'https://de.tynt.com/deb/v2?m=xch&id=id1' - }, - { - type: 'iframe', - url: 'https://de.tynt.com/deb/v2?m=xch&id=id2' - }, - ]; - - this.testSyncs = [ - { - type: 'iframe', - url: 'https://staging-de.tynt.com/deb/v2?m=xch&id=id1' - }, - { - type: 'iframe', - url: 'https://staging-de.tynt.com/deb/v2?m=xch&id=id2' - }, - ]; - }); - - context('when iframe is not enabled', function() { - it('returns empty sync array', function() { - this.sandbox.stub(utils, 'getBidderRequestAllAdUnits', () => ( - { - bids: this.ttxBids - } - )); - const syncOptions = {}; - expect(getUserSyncs(syncOptions)).to.deep.equal([]); + const registerSyncCalled = spy.calledWith('iframe', '33across', syncUrl); + expect(registerSyncCalled).to.be.true; }); - }); - context('when iframe is enabled', function() { - it('returns sync array equal to number of bids for ttx', function() { - this.sandbox.stub(utils, 'getBidderRequestAllAdUnits', () => ( - { - bids: this.ttxBids - } - )); + it('via the test endpoint', function() { + const spy = this.sandbox.spy(userSync, 'registerSync'); - const syncOptions = { - iframeEnabled: true - }; - const syncs = getUserSyncs(syncOptions); - expect(syncs.length).to.equal(this.ttxBids.length); - expect(syncs).to.deep.equal(this.syncs); - }); - - it('returns sync array equal to number of test bids for ttx', function() { - this.sandbox.stub(utils, 'getBidderRequestAllAdUnits', () => ( - { - bids: this.testTTXBids + this.sandbox.stub(config, 'getConfig', () => { + return { + 'syncUrl': 'https://foo.com/deb/v2?m=xch' } - )); + }); - const syncOptions = { - iframeEnabled: true - }; - const syncs = getUserSyncs(syncOptions); - expect(syncs.length).to.equal(this.testTTXBids.length); - expect(syncs).to.deep.equal(this.testSyncs); + const serverResponse = { + cur: 'USD', + ext: {}, + id: 'b1', + seatbid: [] + } + interpretResponse({ body: serverResponse }, this.serverRequest); + const syncUrl = `https://foo.com/deb/v2?m=xch&id=${this.ttxRequest.site.id}`; + + const registerSyncCalled = spy.calledWith('iframe', '33across', syncUrl); + expect(registerSyncCalled).to.be.true; }); }); }); diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js deleted file mode 100644 index 12a47fc946d..00000000000 --- a/test/spec/modules/aardvarkBidAdapter_spec.js +++ /dev/null @@ -1,240 +0,0 @@ -describe('aardvark adapter tests', function () { - const expect = require('chai').expect; - const Adapter = require('modules/aardvarkBidAdapter'); - const bidmanager = require('src/bidmanager'); - const adloader = require('src/adloader'); - const constants = require('src/constants.json'); - - var aardvark, - sandbox, - bidsRequestedOriginal; - - const bidderRequest = { - bidderCode: 'aardvark', - bids: [ - { - bidId: 'bidId1', - bidder: 'aardvark', - placementCode: 'foo', - sizes: [[728, 90]], - rtkid: 1, - params: { - ai: 'AH5S', - sc: 'BirH' - } - }, - { - bidId: 'bidId2', - bidder: 'aardvark', - placementCode: 'bar', - sizes: [[300, 600]], - rtkid: 1, - params: { - ai: 'AH5S', - sc: '661h' - } - } - ] - }, - - bidderRequestCustomHost = { - bidderCode: 'aardvark', - bids: [ - { - bidId: 'bidId1', - bidder: 'aardvark', - placementCode: 'foo', - sizes: [[728, 90]], - rtkid: 1, - params: { - ai: 'AH5S', - sc: 'BirH', - host: 'custom.server.com' - } - }, - { - bidId: 'bidId2', - bidder: 'aardvark', - placementCode: 'bar', - sizes: [[300, 600]], - rtkid: 1, - params: { - ai: 'AH5S', - sc: '661h', - host: 'custom.server.com' - } - } - ] - }, - - // respond - bidderResponse = [ - { - 'adm': '
', - 'cpm': 0.39440, - 'ex': '', - 'height': '90', - 'id': 'BirH', - 'nurl': '', - 'width': '728', - 'cid': 'bidId1' - }, - { - 'adm': '
', - 'cpm': 0.03485, - 'ex': '', - 'height': '600', - 'id': '661h', - 'nurl': '', - 'width': '300', - 'cid': 'bidId2' - } - ]; - - beforeEach(() => { - aardvark = new Adapter(); - sandbox = sinon.sandbox.create(); - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe('callBids', () => { - beforeEach(() => { - sandbox.stub(adloader, 'loadScript'); - aardvark.callBids(bidderRequest); - }); - it('should load script', () => { - sinon.assert.calledOnce(adloader.loadScript); - expect(adloader.loadScript.firstCall.args[0]).to.eql( - '//thor.rtk.io/AH5S/BirH_661h/aardvark/?jsonp=$$PREBID_GLOBAL$$.aardvarkResponse&rtkreferer=localhost:9876&BirH=bidId1&661h=bidId2'); - }); - }); - - describe('callBids with custom host', () => { - beforeEach(() => { - sandbox.stub(adloader, 'loadScript'); - aardvark.callBids(bidderRequestCustomHost); - }); - it('should load script', () => { - sinon.assert.calledOnce(adloader.loadScript); - expect(adloader.loadScript.firstCall.args[0]).to.eql( - '//custom.server.com/AH5S/BirH_661h/aardvark/?jsonp=$$PREBID_GLOBAL$$.aardvarkResponse&rtkreferer=localhost:9876&BirH=bidId1&661h=bidId2'); - }); - }); - - describe('aardvarkResponse', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.aardvarkResponse).to.exist.and.to.be.a('function'); - }); - }); - - describe('add empty bids if no bid returned', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidmanager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - aardvark.callBids(bidderRequest); - - $$PREBID_GLOBAL$$.aardvarkResponse([]); - - firstBid = bidmanager.addBidResponse.firstCall.args[1]; - secondBid = bidmanager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidmanager.addBidResponse); - }); - - it('should have an error statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(constants.STATUS.NO_BID); - expect(secondBid.getStatusCode()).to.eql(constants.STATUS.NO_BID); - }); - - it('should include bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidmanager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidmanager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'aardvark'); - expect(secondBid).to.have.property('bidderCode', 'aardvark'); - }); - }); - - describe('add bids to the manager', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidmanager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - aardvark.callBids(bidderRequest); - - $$PREBID_GLOBAL$$.aardvarkResponse(bidderResponse); - firstBid = bidmanager.addBidResponse.firstCall.args[1]; - secondBid = bidmanager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidmanager.addBidResponse); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidmanager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidmanager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should include bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should have a good statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(constants.STATUS.GOOD); - expect(secondBid.getStatusCode()).to.eql(constants.STATUS.GOOD); - }); - - it('should add the CPM to the bid object', () => { - expect(firstBid).to.have.property('cpm', 0.39440); - expect(secondBid).to.have.property('cpm', 0.03485); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'aardvark'); - expect(secondBid).to.have.property('bidderCode', 'aardvark'); - }); - - it('should include the ad to the bid object', () => { - expect(firstBid).to.have.property('ad'); - expect(secondBid).to.have.property('ad'); - }); - - it('should include the size to the bid object', () => { - expect(firstBid).to.have.property('width', 728); - expect(firstBid).to.have.property('height', 90); - expect(secondBid).to.have.property('width', 300); - expect(secondBid).to.have.property('height', 600); - }); - }); -}); diff --git a/test/spec/modules/adbladeBidAdapter_spec.js b/test/spec/modules/adbladeBidAdapter_spec.js deleted file mode 100644 index ec3c9f6b23e..00000000000 --- a/test/spec/modules/adbladeBidAdapter_spec.js +++ /dev/null @@ -1,206 +0,0 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/adbladeBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; - -describe('adblade adapter', () => { - 'use strict'; - - let bidsRequestedOriginal; - let adapter; - let sandbox; - - const bidderRequest = { - bidderCode: 'adblade', - bids: [ - { - bidId: 'bidId1', - bidder: 'adblade', - placementCode: 'foo', - sizes: [[728, 90]], - params: { - partnerId: 1, - } - } - ] - }; - - beforeEach(() => { - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe('sizes', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - }); - - let bidderRequest = { - bidderCode: 'adblade', - bids: [ - { - bidId: 'bidId1', - bidder: 'adblade', - placementCode: 'foo', - sizes: [[728, 90], [300, 250]], - params: { - partnerId: 1, - } - } - ] - }; - - it('array of arrays', () => { - adapter.callBids(bidderRequest); - sinon.assert.calledTwice(adLoader.loadScript); - - expect(adLoader.loadScript.firstCall.args[0]).to.include('%22banner%22%3A%7B%22w%22%3A728%2C%22h%22%3A90%7D%2C'); // banner:{w:728, h:90} - expect(adLoader.loadScript.firstCall.args[0]).to.include('adblade.com'); - expect(adLoader.loadScript.firstCall.args[0]).to.include('prebidjs'); - - expect(adLoader.loadScript.secondCall.args[0]).to.include('%22banner%22%3A%7B%22w%22%3A300%2C%22h%22%3A250%7D%2C'); // banner:{w:300, h:250} - expect(adLoader.loadScript.secondCall.args[0]).to.include('adblade.com'); - expect(adLoader.loadScript.secondCall.args[0]).to.include('prebidjs'); - }); - - it('array of strings', () => { - bidderRequest.bids[0].sizes = [728, 90]; - adapter.callBids(bidderRequest); - sinon.assert.calledOnce(adLoader.loadScript); - - expect(adLoader.loadScript.firstCall.args[0]).to.include('%22banner%22%3A%7B%22w%22%3A728%2C%22h%22%3A90%7D%2C'); // banner:{w:728, h:90} - expect(adLoader.loadScript.firstCall.args[0]).to.include('adblade.com'); - expect(adLoader.loadScript.firstCall.args[0]).to.include('prebidjs'); - }); - }); - - describe('callBids', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - }); - - it('should load script', () => { - sinon.assert.calledOnce(adLoader.loadScript); - - expect(adLoader.loadScript.firstCall.args[0]).to.include('adblade.com'); - expect(adLoader.loadScript.firstCall.args[0]).to.include('prebidjs'); - }); - }); - - describe('adbladeResponse', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.adbladeResponse).to.exist.and.to.be.a('function'); - }); - }); - - describe('add bids to the manager', () => { - let firstBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = { - 'cur': 'USD', - 'id': '03a9404f-7b39-4d04-b50b-6459b9aa3ffa', - 'seatbid': [ - { - 'seat': '1', - 'bid': [ - { - 'nurl': 'http://example.com', - 'crid': '20063', - 'adomain': [ - 'www.adblade.com' - ], - 'price': 3, - 'w': 728, - 'h': 90, - 'id': '1', - 'adm': '
', - 'impid': 'bidId1', - 'cid': '99' - } - ] - } - ] - }; - $$PREBID_GLOBAL$$.adbladeResponse(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - }); - - it('should have a good statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(1); - }); - - it('should add the CPM to the bid object', () => { - expect(firstBid).to.have.property('cpm', 3); - }); - - it('should include the ad to the bid object', () => { - expect(firstBid).to.have.property('ad'); - }); - - it('should include the size to the bid object', () => { - expect(firstBid).to.have.property('width', 728); - expect(firstBid).to.have.property('height', 90); - }); - }); - - describe('add empty bids if no bid returned', () => { - let firstBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = {}; - $$PREBID_GLOBAL$$.adbladeResponse(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('should have an error statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(2); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'adblade'); - }); - }); -}); diff --git a/test/spec/modules/adbundBidAdapter_spec.js b/test/spec/modules/adbundBidAdapter_spec.js deleted file mode 100644 index da9b2e2e9b9..00000000000 --- a/test/spec/modules/adbundBidAdapter_spec.js +++ /dev/null @@ -1,94 +0,0 @@ -import { expect } from 'chai'; -import Adapter from '../../../modules/adbundBidAdapter'; -import bidManager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; - -describe('adbund adapter tests', function () { - let sandbox; - let adapter; - let server; - - const request = { - bidderCode: 'adbund', - bids: [{ - bidder: 'adbund', - params: { - sid: '110238', - bidfloor: 0.036 - }, - placementCode: 'adbund', - sizes: [[300, 250]], - bidId: 'adbund_bidId', - bidderRequestId: 'adbund_bidderRequestId', - requestId: 'adbund_requestId' - }] - }; - - const response = { - bidderCode: 'adbund', - cpm: 1.06, - height: 250, - width: 300 - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('adbund callBids validation', () => { - beforeEach(() => { - adapter = new Adapter(); - }); - - afterEach(() => { - }); - - it('Valid bid-request', () => { - let bidderRequest; - - sandbox.stub(adapter, 'callBids'); - adapter.callBids(request); - - bidderRequest = adapter.callBids.getCall(0).args[0]; - - expect(bidderRequest).to.have.property('bids') - .that.is.an('array') - .with.lengthOf(1); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .to.have.property('bidder', 'adbund'); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('sizes') - .that.is.an('array') - .with.lengthOf(1) - .that.deep.equals(request.bids[0].sizes); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('bidfloor', 0.036); - }); - - it('Valid bid-response', () => { - var bidderResponse; - - sandbox.stub(bidManager, 'addBidResponse'); - adapter.callBids(request); - bidderResponse = bidManager.addBidResponse.getCall(0) || - bidManager.addBidResponse.getCall(1); - - if (bidderResponse && bidderResponse.args && bidderResponse.args[1]) { - bidderResponse = bidderResponse.args[1]; - expect(bidderResponse.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidderResponse.bidderCode).to.equal(response.bidderCode); - expect(bidderResponse.width).to.equal(response.width); - expect(bidderResponse.height).to.equal(response.height); - expect(bidderResponse.cpm).to.equal(response.cpm); - } - }); - }); -}); diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js deleted file mode 100644 index fa137110ba8..00000000000 --- a/test/spec/modules/adformBidAdapter_spec.js +++ /dev/null @@ -1,198 +0,0 @@ -import { assert } from 'chai'; -import * as utils from 'src/utils'; -import adLoader from 'src/adloader'; -import bidManager from 'src/bidmanager'; -import AdformAdapter from 'modules/adformBidAdapter'; - -describe('Adform adapter', () => { - let _adformAdapter, sandbox; - - describe('request', () => { - it('should create callback method on PREBID_GLOBAL', () => { - assert.typeOf($$PREBID_GLOBAL$$._adf_callback, 'function'); - }); - - it('should pass multiple bids via single request', () => { - const _request = adLoader.loadScript; - - assert(_request.calledOnce); - assert.lengthOf(_request.args[0], 1); - assert.lengthOf(parseUrl(_request.args[0][0]).items, 3); - }); - - it('should handle global request parameters', () => { - const _request = parseUrl(adLoader.loadScript.args[0][0]); - const _query = _request.query; - - assert.equal(_request.path, '//newdomain/adx'); - assert.equal(_query.callback.split('.')[1], '_adf_callback'); - assert.equal(_query.tid, 145); - assert.equal(_query.rp, 4); - assert.equal(_query.fd, 1); - assert.equal(_query.auctionId, '4db6ddaa-ec86-459e-99aa-f7ffe940c473'); - assert.equal(_query.url, encodeURIComponent('some// there')); - }); - - it('should correctly form bid items', () => { - const _items = parseUrl(adLoader.loadScript.args[0][0]).items; - - assert.deepEqual(_items[0], { mid: '1', transactionId: 'transactionId' }); - assert.deepEqual(_items[1], { mid: '2', someVar: 'someValue', transactionId: 'transactionId' }); - assert.deepEqual(_items[2], { mid: '3', pdom: 'home', transactionId: 'transactionId' }); - }); - }); - - describe('response callback', () => { - it('should create bid response item for every requested item', () => { - assert(bidManager.addBidResponse.calledThrice); - }); - - it('should correctly form bid response object', () => { - const _bid = bidManager.addBidResponse.firstCall.args; - const _bidObject = _bid[1]; - - assert.equal(_bid[0], 'code-1'); - assert.equal(_bidObject.statusMessage, 'Bid available'); - assert.equal(_bidObject.bidderCode, 'adform'); - assert.equal(_bidObject.cpm, 1.1); - assert.equal(_bidObject.cur, 'EUR'); - assert.equal(_bidObject.ad, ''); - assert.equal(_bidObject.width, 90); - assert.equal(_bidObject.height, 90); - assert.equal(_bidObject.dealId, 'deal-1'); - assert.equal(_bidObject.transactionId, 'transactionId'); - }); - - it('should correctly form empty bid response object', () => { - const _bid = bidManager.addBidResponse.secondCall.args; - const _bidObject = _bid[1]; - - assert.equal(_bid[0], 'code-2'); - assert.equal(_bidObject.statusMessage, 'Bid returned empty or error response'); - assert.equal(_bidObject.bidderCode, 'adform'); - }); - - it('should filter out item which does not fit required size', () => { - const _bid = bidManager.addBidResponse.thirdCall.args; - const _bidObject = _bid[1]; - - assert.equal(_bid[0], 'code-3'); - assert.equal(_bidObject.statusMessage, 'Bid returned empty or error response'); - assert.equal(_bidObject.bidderCode, 'adform'); - }); - - it('should correctly set bid response adId', () => { - const addResponse = bidManager.addBidResponse; - assert.equal('abc', addResponse.getCall(0).args[1].adId); - assert.equal('123', addResponse.getCall(1).args[1].adId); - assert.equal('a1b', addResponse.getCall(2).args[1].adId); - }); - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - $$PREBID_GLOBAL$$._adf_callback([ - { - response: 'banner', - width: 90, - height: 90, - banner: '', - win_bid: 1.1, - win_cur: 'EUR', - deal_id: 'deal-1' - }, - {}, - { - response: 'banner', - width: 50, - height: 50, - banner: '' - } - ]); - }); - }); - - beforeEach(() => { - var transactionId = 'transactionId'; - _adformAdapter = new AdformAdapter(); - utils.getUniqueIdentifierStr = () => 'callback'; - sandbox = sinon.sandbox.create(); - sandbox.stub(adLoader, 'loadScript'); - _adformAdapter.callBids({ - bidderRequestId: '1a2b3c', - requestId: '4db6ddaa-ec86-459e-99aa-f7ffe940c473', - bids: [ - { - bidId: 'abc', - placementCode: 'code-1', - sizes: [ [ 100, 100], [ 90, 90 ] ], - params: { - mid: 1, - url: 'some// there' - }, - adxDomain: 'newdomain', - tid: 45, - transactionId: transactionId - }, - { - bidId: '123', - placementCode: 'code-2', - sizes: [ [ 100, 100] ], - params: { - mid: 2, - tid: 145, - someVar: 'someValue' - }, - transactionId: transactionId - }, - { - bidId: 'a1b', - placementCode: 'code-3', - sizes: [ [ 50, 40], [ 40, 50 ] ], - params: { - mid: 3, - pdom: 'home' - }, - transactionId: transactionId - } - ]}); - }); - - afterEach(() => { - sandbox.restore(); - }); -}); - -function parseUrl(url) { - const parts = url.split('/'); - const query = parts.pop().split('&'); - return { - path: parts.join('/'), - items: query - .filter((i) => !~i.indexOf('=')) - .map((i) => fromBase64(i) - .split('&') - .reduce(toObject, {})), - query: query - .filter((i) => ~i.indexOf('=')) - .map((i) => i.replace('?', '')) - .reduce(toObject, {}) - }; -} - -function fromBase64(input) { - const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'.split(''); - let bc = 0, bs, buffer, idx = 0, output = ''; - for (; buffer = input.charAt(idx++); - ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, - bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0 - ) { - buffer = chars.indexOf(buffer); - } - return output; -} - -function toObject(cache, string) { - const keyValue = string.split('='); - cache[keyValue[0]] = keyValue[1]; - return cache; -} diff --git a/test/spec/modules/admixerBidAdapter_spec.js b/test/spec/modules/admixerBidAdapter_spec.js deleted file mode 100644 index 0b66f8a9469..00000000000 --- a/test/spec/modules/admixerBidAdapter_spec.js +++ /dev/null @@ -1,244 +0,0 @@ -var chai = require('chai'); -var Adapter = require('modules/admixerBidAdapter')(); -var Ajax = require('src/ajax'); -var bidmanager = require('src/bidmanager.js'); -var CONSTANTS = require('src/constants.json'); - -describe('Admixer adapter', function () { - var validData_1 = { - bids: [ - { - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id'}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [300, 600]] - } - ] - }; - var validData_2 = { - bids: [ - { - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id'}, - placementCode: 'ad-unit-1', - sizes: [300, 250] - } - ] - }; - var invalidData = { - bids: [ - { - bidder: 'admixer', - bidId: 'bid_id', - params: {}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [300, 600]] - } - ] - }; - var validVideoData_1 = { - bids: [ - { - mediaType: 'video', - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id'}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [300, 600]] - } - ] - }; - var validVideoData_2 = { - bids: [ - { - mediaType: 'video', - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id'}, - placementCode: 'ad-unit-1', - sizes: [300, 250] - } - ] - }; - var validVideoData_3 = { - bids: [ - { - mediaType: 'video', - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id', video: {skippable: true}}, - placementCode: 'ad-unit-1', - sizes: [300, 250] - } - ] - }; - var invalidVideoData = { - bids: [ - { - mediaType: 'video', - bidder: 'admixer', - bidId: 'bid_id', - params: {}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [300, 600]] - } - ] - }; - var responseWithAd = JSON.stringify({ - 'result': { - 'cpm': 2.2, - 'ad': '
response ad
', - 'width': 300, - 'height': 250 - }, - 'callback_uid': 'ad-unit-1' - }); - var responseWithoutAd = JSON.stringify({ - 'result': { - 'cpm': 0, - 'ad': '', - 'width': 0, - 'height': 0 - }, - 'callback_uid': 'ad-unit-1' - }); - var responseWithVideoAd = JSON.stringify({ - 'result': { - 'cpm': 2.2, - 'vastUrl': 'http://inv-nets.admixer.net/vastxml.aspx?req=9d651544-daf4-48ed-ae0c-38a60a4e1920&vk=e914f026449e49aeb6eea07b9642a2ce', - 'width': 300, - 'height': 250 - }, - 'callback_uid': 'ad-unit-1' - }); - var responseWithoutVideoAd = JSON.stringify({ - 'result': { - 'cpm': 0, - 'vastUrl': '', - 'width': 0, - 'height': 0 - }, - 'callback_uid': 'ad-unit-1' - }); - var responseEmpty = ''; - var invUrl = '//inv-nets.admixer.net/prebid.aspx'; - var invVastUrl = '//inv-nets.admixer.net/videoprebid.aspx'; - var validJsonParams = { - zone: 'zone_id', - callback_uid: 'ad-unit-1', - sizes: '300x250-300x600' - }; - var validJsonVideoParams = { - zone: 'zone_id', - callback_uid: 'ad-unit-1', - sizes: '300x250-300x600', - skippable: true - }; - describe('bid request with valid data', function () { - var stubAjax; - beforeEach(function () { - stubAjax = sinon.stub(Ajax, 'ajax'); - }); - - afterEach(function () { - stubAjax.restore(); - }); - it('display: bid request should be called. sizes style -> [[],[]]', function () { - Adapter.callBids(validData_1); - sinon.assert.calledOnce(stubAjax); - }); - it('video: bid request should be called. sizes style -> [[],[]]', function () { - Adapter.callBids(validVideoData_1); - sinon.assert.calledOnce(stubAjax); - }); - it('display: bid request should be called. sizes style -> []', function () { - Adapter.callBids(validData_2); - sinon.assert.calledOnce(stubAjax); - }); - it('video: bid request should be called. sizes style -> []', function () { - Adapter.callBids(validVideoData_2); - sinon.assert.calledOnce(stubAjax); - }); - it('display: ajax params should be matched', function () { - Adapter.callBids(validData_1); - sinon.assert.calledWith(stubAjax, sinon.match(invUrl, function () { - }, validJsonParams, {method: 'GET'})); - }); - it('video: ajax params should be matched', function () { - Adapter.callBids(validVideoData_3); - sinon.assert.calledWith(stubAjax, sinon.match(invVastUrl, function () { - }, validJsonVideoParams, {method: 'GET'})); - }); - }); - describe('bid request with invalid data', function () { - var addBidResponse, stubAjax; - beforeEach(function () { - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - stubAjax = sinon.stub(Ajax, 'ajax'); - }); - - afterEach(function () { - addBidResponse.restore(); - stubAjax.restore(); - }); - it('display: ajax shouldn\'t be called', function () { - Adapter.callBids(invalidData); - sinon.assert.notCalled(stubAjax); - }); - it('video: ajax shouldn\'t be called', function () { - Adapter.callBids(invalidVideoData); - sinon.assert.notCalled(stubAjax); - }); - it('display: bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID + '"', function () { - Adapter.callBids(invalidData); - expect(addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(addBidResponse.firstCall.args[1].bidderCode).to.equal('admixer'); - }); - it('video: bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID + '"', function () { - Adapter.callBids(invalidVideoData); - expect(addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(addBidResponse.firstCall.args[1].bidderCode).to.equal('admixer'); - }); - }); - describe('bid response', function () { - var addBidResponse; - beforeEach(function () { - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - afterEach(function () { - addBidResponse.restore(); - }); - it('display: response with ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.GOOD + '"', function () { - Adapter.responseCallback(responseWithAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(arg.bidderCode).to.equal('admixer'); - }); - it('video: response with ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.GOOD + '"', function () { - Adapter.responseCallback(responseWithVideoAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(arg.bidderCode).to.equal('admixer'); - }); - it('display: response without ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(responseWithoutAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('admixer'); - }); - it('video: response without ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(responseWithoutVideoAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('admixer'); - }); - it('display/video: response empty. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(responseEmpty); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('admixer'); - }); - }); -}); diff --git a/test/spec/modules/adsupplyBidAdapter_spec.js b/test/spec/modules/adsupplyBidAdapter_spec.js deleted file mode 100644 index b1bc0bf17f1..00000000000 --- a/test/spec/modules/adsupplyBidAdapter_spec.js +++ /dev/null @@ -1,359 +0,0 @@ -describe('adsupply adapter tests', function () { - const expect = require('chai').expect; - - const AdSupplyAdapter = require('../../../modules/adsupplyBidAdapter'); - const adloader = require('../../../src/adloader'); - const bidmanager = require('../../../src/bidmanager'); - const CONSTANTS = require('../../../src/constants.json'); - let adsupplyAdapter = new AdSupplyAdapter(); - - beforeEach(() => { - $$PREBID_GLOBAL$$._bidsRequested = []; - }); - - it('adsupply response handler should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.adSupplyResponseHandler).to.exist.and.to.be.a('function'); - }); - - it('two requests are sent to adsupply engine', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - zoneId: 111, - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - zoneId: 222, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.calledTwice(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('zoneId is not a number and not specified', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - zoneId: '111', - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('siteId is empty and not specified', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - zoneId: 111, - siteId: '', - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - endpointUrl: 'engine.4dsply.com' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - zoneId: 222, - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('endpointUrl is empty and not specified', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: '' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - zoneId: 222, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('clientId is empty and not specified', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: '', - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - zoneId: 222, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('parameters are missed', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1' - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('Parameters added to the request url', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - zoneId: 111, - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - var requestUrl = stubLoadScript.getCall(0).args[0]; - expect(requestUrl).to.contain('111'); - expect(requestUrl).to.contain('0ab16161-a1de-4683-8837-c420bd4387c0'); - expect(requestUrl).to.contain('engine.4dsply.com'); - expect(requestUrl).to.contain('&hbt=1'); - expect(requestUrl).to.contain('g32db6906-55f4-42b1-a7d2-7dfaddce96fd'); - - adloader.loadScript.restore(); - }); - - it('Response handler invalid data', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - // adapter needs to be called, in order for the stub to register. - new AdSupplyAdapter(); - - // bidId is not valid - $$PREBID_GLOBAL$$.adSupplyResponseHandler(null); - - // bidRequest object is not found - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - let clientId = 'g5d384afa-c050-4bac-b202-dab8fb06e381'; - // Zone property is not found - let bidderRequest = { - bidderCode: 'adsupply', - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: clientId, - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - // Media is not found - window[clientId] = window[clientId] || {}; - window[clientId]['b111'] = window[clientId]['b111'] || {}; - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - sinon.assert.notCalled(stubAddBidResponse); - - $$PREBID_GLOBAL$$._bidsRequested.pop(); - bidmanager.addBidResponse.restore(); - }); - - it('No Fill response', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // adapter needs to be called, in order for the stub to register. - new AdSupplyAdapter(); - - let clientId = 'g5d384afa-c050-4bac-b202-dab8fb06e381'; - // Zone property is not found - let bidderRequest = { - bidderCode: 'adsupply', - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: clientId, - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - window[clientId] = window[clientId] || {}; - window[clientId]['b111'] = window[clientId]['b111'] || {}; - window[clientId]['b111'].Media = { width: 300 }; - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - sinon.assert.calledOnce(stubAddBidResponse); - - let bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - let bidResponse = stubAddBidResponse.getCall(0).args[1]; - expect(bidPlacementCode).to.equal('pc1'); - expect(bidResponse.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(bidResponse.bidderCode).to.equal('adsupply'); - - $$PREBID_GLOBAL$$._bidsRequested.pop(); - bidmanager.addBidResponse.restore(); - }); - - it('Fill response', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // adapter needs to be called, in order for the stub to register. - new AdSupplyAdapter(); - - let clientId = 'g5d384afa-c050-4bac-b202-dab8fb06e381'; - // Zone property is not found - let bidderRequest = { - bidderCode: 'adsupply', - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: clientId, - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - window[clientId] = window[clientId] || {}; - window[clientId]['b111'] = window[clientId]['b111'] || {}; - window[clientId]['b111'].Media = { Width: 300, Height: 250, Url: '/Redirect.engine', Ecpm: 0.0012 }; - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - sinon.assert.calledOnce(stubAddBidResponse); - - let bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - let bidResponse = stubAddBidResponse.getCall(0).args[1]; - expect(bidPlacementCode).to.equal('pc1'); - expect(bidResponse.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidResponse.bidderCode).to.equal('adsupply'); - - $$PREBID_GLOBAL$$._bidsRequested.pop(); - bidmanager.addBidResponse.restore(); - }); -}); diff --git a/test/spec/modules/adxcgAnalyticsAdapter_spec.js b/test/spec/modules/adxcgAnalyticsAdapter_spec.js index 790a39789b2..179b806da48 100644 --- a/test/spec/modules/adxcgAnalyticsAdapter_spec.js +++ b/test/spec/modules/adxcgAnalyticsAdapter_spec.js @@ -20,7 +20,7 @@ describe('adxcg analytics adapter', () => { describe('track', () => { it('builds and sends auction data', () => { - let auctionTimestamp = 42; + let auctionTimestamp = 1496510254313; let initOptions = { publisherId: '42' }; @@ -32,6 +32,21 @@ describe('adxcg analytics adapter', () => { ad: 'adContent' }; + let bidTimeoutArgsV1 = [ + { + bidId: '2baa51527bd015', + bidder: 'bidderOne', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + }, + { + bidId: '6fe3b4c2c23092', + bidder: 'bidderTwo', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + } + ]; + adaptermanager.registerAnalyticsAdapter({ code: 'adxcg', adapter: adxcgAnalyticsAdapter @@ -42,11 +57,21 @@ describe('adxcg analytics adapter', () => { options: initOptions }); + // Step 1: Send auction init event events.emit(constants.EVENTS.AUCTION_INIT, { timestamp: auctionTimestamp }); + + // Step 2: Send bid requested event events.emit(constants.EVENTS.BID_REQUESTED, bidRequest); + + // Step 3: Send bid response event events.emit(constants.EVENTS.BID_RESPONSE, bidResponse); + + // Step 4: Send bid time out event + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeoutArgsV1); + + // Step 5: Send auction end event events.emit(constants.EVENTS.AUCTION_END, {}); expect(requests.length).to.equal(1); @@ -61,8 +86,12 @@ describe('adxcg analytics adapter', () => { expect(auctionEventData.bidResponses[0]).to.not.have.property('ad'); expect(auctionEventData.initOptions).to.deep.equal(initOptions); + expect(auctionEventData.auctionTimestamp).to.equal(auctionTimestamp); + expect(auctionEventData.bidTimeout).to.deep.equal(['bidderOne', 'bidderTwo']); + + // Step 6: Send auction bid won event events.emit(constants.EVENTS.BID_WON, { adId: 'adIdData', ad: 'adContent' diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js deleted file mode 100644 index 05c112c2a99..00000000000 --- a/test/spec/modules/adyoulikeBidAdapter_spec.js +++ /dev/null @@ -1,314 +0,0 @@ -import { expect } from 'chai'; -import { parse } from '../../../src/url'; -import AdyoulikAdapter from '../../../modules/adyoulikeBidAdapter'; -import bidmanager from 'src/bidmanager'; -import { STATUS } from 'src/constants'; - -describe('Adyoulike Adapter', () => { - const endpoint = 'http://hb-api.omnitagjs.com/hb-api/prebid'; - const canonicalUrl = 'http://canonical.url/?t=%26'; - const bidderCode = 'adyoulike'; - const bidRequestWithEmptyPlacement = { - 'bidderCode': 'adyoulike', - 'bids': [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': {}, - 'sizes': '300x250' - } - ], - }; - const bidRequestWithEmptySizes = { - 'bidderCode': 'adyoulike', - 'bids': [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': { - 'placement': 'placement_0' - }, - 'transactionId': 'bid_id_0_transaction_id' - } - ], - }; - const bidRequestWithSinglePlacement = { - 'bidderCode': 'adyoulike', - 'bids': [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': { - 'placement': 'placement_0' - }, - 'sizes': '300x250', - 'transactionId': 'bid_id_0_transaction_id' - } - ], - }; - const bidRequestMultiPlacements = { - 'bidderCode': 'adyoulike', - 'bids': [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': { - 'placement': 'placement_0' - }, - 'sizes': '300x250', - 'transactionId': 'bid_id_0_transaction_id' - }, - { - 'bidId': 'bid_id_1', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-1', - 'params': { - 'placement': 'placement_1' - }, - 'sizes': [[300, 600]], - 'transactionId': 'bid_id_1_transaction_id' - }, - { - 'bidId': 'bid_id_2', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-2', - 'params': {}, - 'sizes': '300x400', - 'transactionId': 'bid_id_2_transaction_id' - }, - { - 'bidId': 'bid_id_3', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-3', - 'params': { - 'placement': 'placement_3' - }, - 'transactionId': 'bid_id_3_transaction_id' - } - ], - }; - - const responseWithEmptyPlacement = [ - { - 'Placement': 'placement_0' - } - ]; - const responseWithSinglePlacement = [ - { - 'Placement': 'placement_0', - 'Banner': 'placement_0', - 'Price': 0.5 - } - ]; - const responseWithMultiplePlacements = [ - { - 'Placement': 'placement_0', - 'Banner': 'placement_0', - 'Price': 0.5 - }, - { - 'Placement': 'placement_1', - 'Banner': 'placement_1', - 'Price': 0.6 - } - ]; - - let adapter; - - beforeEach(() => { - adapter = new AdyoulikAdapter(); - }); - - describe('adapter public API', () => { - const adapter = new AdyoulikAdapter(); - - it('setBidderCode', () => { - expect(adapter.setBidderCode).to.be.a('function'); - }); - it('callBids', () => { - expect(adapter.setBidderCode).to.be.a('function'); - }); - }); - - describe('request function', () => { - let requests; - let xhr; - let addBidResponse; - let canonicalQuery; - - beforeEach(() => { - requests = []; - - xhr = sinon.useFakeXMLHttpRequest(); - xhr.onCreate = request => requests.push(request); - - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - let canonical = document.createElement('link'); - canonical.rel = 'canonical'; - canonical.href = canonicalUrl; - canonicalQuery = sinon.stub(window.top.document.head, 'querySelector'); - canonicalQuery.withArgs('link[rel="canonical"][href]').returns(canonical); - }); - - afterEach(() => { - xhr.restore(); - bidmanager.addBidResponse.restore(); - canonicalQuery.restore(); - }); - - it('requires placement request', () => { - adapter.callBids(bidRequestWithEmptyPlacement); - expect(requests).to.be.empty; - expect(addBidResponse.calledOnce).to.equal(false); - }); - - it('requires sizes in request', () => { - adapter.callBids(bidRequestWithEmptySizes); - expect(requests).to.be.empty; - expect(addBidResponse.calledOnce).to.equal(false); - }); - - it('sends bid request to endpoint with single placement', () => { - adapter.callBids(bidRequestWithSinglePlacement); - expect(requests[0].url).to.contain(endpoint); - expect(requests[0].method).to.equal('POST'); - - expect(requests[0].url).to.contains('CanonicalUrl=' + encodeURIComponent(canonicalUrl)); - - let body = JSON.parse(requests[0].requestBody); - expect(body.Version).to.equal('0.2'); - expect(body.Placements).deep.equal(['placement_0']); - expect(body.PageRefreshed).to.equal(false); - expect(body.TransactionIds).deep.equal({'placement_0': 'bid_id_0_transaction_id'}); - }); - - it('sends bid request to endpoint with single placement without canonical', () => { - canonicalQuery.restore(); - - adapter.callBids(bidRequestWithSinglePlacement); - expect(requests[0].url).to.contain(endpoint); - expect(requests[0].method).to.equal('POST'); - - expect(requests[0].url).to.not.contains('CanonicalUrl=' + encodeURIComponent(canonicalUrl)); - - let body = JSON.parse(requests[0].requestBody); - expect(body.Version).to.equal('0.2'); - expect(body.Placements).deep.equal(['placement_0']); - expect(body.PageRefreshed).to.equal(false); - expect(body.TransactionIds).deep.equal({'placement_0': 'bid_id_0_transaction_id'}); - }); - - it('sends bid request to endpoint with multiple placements', () => { - adapter.callBids(bidRequestMultiPlacements); - expect(requests[0].url).to.contain(endpoint); - expect(requests[0].method).to.equal('POST'); - - expect(requests[0].url).to.contains('CanonicalUrl=' + encodeURIComponent(canonicalUrl)); - - let body = JSON.parse(requests[0].requestBody); - expect(body.Version).to.equal('0.2'); - expect(body.Placements).deep.equal(['placement_0', 'placement_1']); - expect(body.PageRefreshed).to.equal(false); - expect(body.TransactionIds).deep.equal({'placement_0': 'bid_id_0_transaction_id', 'placement_1': 'bid_id_1_transaction_id'}); - }); - }); - - describe('response function', () => { - let server; - let addBidResponse; - - beforeEach(() => { - server = sinon.fakeServer.create(); - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('invalid json', () => { - server.respondWith('{'); - adapter.callBids(bidRequestWithSinglePlacement); - server.respond(); - - expect(addBidResponse.calledOnce).to.equal(true); - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.NO_BID); - expect(addBidResponse.args[0][1].bidderCode).to.equal(bidderCode); - }); - - it('receive reponse with empty placement', () => { - server.respondWith(JSON.stringify(responseWithEmptyPlacement)); - adapter.callBids(bidRequestWithSinglePlacement); - server.respond(); - - expect(addBidResponse.calledOnce).to.equal(true); - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.NO_BID); - expect(addBidResponse.args[0][1].bidderCode).to.equal(bidderCode); - }); - - it('receive reponse with single placement', () => { - server.respondWith(JSON.stringify(responseWithSinglePlacement)); - adapter.callBids(bidRequestWithSinglePlacement); - server.respond(); - - expect(addBidResponse.calledOnce).to.equal(true); - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.GOOD); - expect(addBidResponse.args[0][1].cpm).to.equal(0.5); - expect(addBidResponse.args[0][1].ad).to.equal('placement_0'); - expect(addBidResponse.args[0][1].width).to.equal(300); - expect(addBidResponse.args[0][1].height).to.equal(250); - }); - - it('receive reponse with multiple placement', () => { - server.respondWith(JSON.stringify(responseWithMultiplePlacements)); - adapter.callBids(bidRequestMultiPlacements); - server.respond(); - - expect(addBidResponse.calledTwice).to.equal(true); - - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.GOOD); - expect(addBidResponse.args[0][1].bidderCode).to.equal(bidderCode); - expect(addBidResponse.args[0][1].cpm).to.equal(0.5); - expect(addBidResponse.args[0][1].ad).to.equal('placement_0'); - expect(addBidResponse.args[0][1].width).to.equal(300); - expect(addBidResponse.args[0][1].height).to.equal(250); - - expect(addBidResponse.args[1]).to.have.lengthOf(2); - expect(addBidResponse.args[1][1].getStatusCode()).to.equal(STATUS.GOOD); - expect(addBidResponse.args[1][1].bidderCode).to.equal(bidderCode); - expect(addBidResponse.args[1][1].cpm).to.equal(0.6); - expect(addBidResponse.args[1][1].ad).to.equal('placement_1'); - expect(addBidResponse.args[1][1].width).to.equal(300); - expect(addBidResponse.args[1][1].height).to.equal(600); - }); - - it('receive reponse with invalid placement number', () => { - server.respondWith(JSON.stringify(responseWithSinglePlacement)); - adapter.callBids(bidRequestMultiPlacements); - server.respond(); - - expect(addBidResponse.calledTwice).to.equal(true); - - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.GOOD); - expect(addBidResponse.args[0][1].bidderCode).to.equal(bidderCode); - expect(addBidResponse.args[0][1].cpm).to.equal(0.5); - expect(addBidResponse.args[0][1].ad).to.equal('placement_0'); - expect(addBidResponse.args[0][1].width).to.equal(300); - expect(addBidResponse.args[0][1].height).to.equal(250); - - expect(addBidResponse.args[1]).to.have.lengthOf(2); - expect(addBidResponse.args[1][1].getStatusCode()).to.equal(STATUS.NO_BID); - }); - }); -}); diff --git a/test/spec/modules/aerservBidAdapter_spec.js b/test/spec/modules/aerservBidAdapter_spec.js deleted file mode 100644 index be0f6393063..00000000000 --- a/test/spec/modules/aerservBidAdapter_spec.js +++ /dev/null @@ -1,213 +0,0 @@ -import {expect} from 'chai'; -import AerServAdapter from 'modules/aerservBidAdapter'; -import bidmanager from 'src/bidmanager'; - -const BASE_REQUEST = JSON.stringify({ - bidderCode: 'aerserv', - requestId: 'a595eff7-d5a3-40f8-971c-5b4ef244ec53', - bidderRequestId: '1f8c8c03de01f9', - bids: [ - { - bidder: 'aerserv', - params: { - plc: '480', - }, - placementCode: 'adunit-1', - transactionId: 'a0e033af-f50c-4a7e-aeed-c01c5f709848', - sizes: [[300, 250], [300, 600]], - bidId: '2f4a69463b3bc9', - bidderRequestId: '1f8c8c03de01f9', - requestId: 'a595eff7-d5a3-40f8-971c-5b4ef244ec53' - } - ] -}); - -describe('AerServ Adapter', () => { - let adapter; - let bidmanagerStub; - - beforeEach(() => { - adapter = new AerServAdapter(); - bidmanagerStub = sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - bidmanager.addBidResponse.restore(); - }); - - describe('callBids()', () => { - let xhr; - let requests; - - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => { - xhr.restore(); - }); - - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - it('should not add bid responses with no bids to call', () => { - adapter.callBids({}); - - sinon.assert.notCalled(bidmanager.addBidResponse); - }); - - it('requires plc parameter to make request', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0].params = {}; - adapter.callBids(bidRequest); - expect(requests).to.be.empty; - }); - - it('sends requests to normal endpoint for non-video requests', () => { - adapter.callBids(JSON.parse(BASE_REQUEST)); - expect(requests.length).to.equal(1); - expect(requests[0].url).to.include('/as/json/pbjs/v1'); - }); - - it('sends requests to video endpoint for video requests', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - bidRequest.bids[0]['video'] = {}; - adapter.callBids(bidRequest); - expect(requests[0].url).to.include('/as/json/pbjsvast/v1'); - }); - - it('properly adds video parameters to the request', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - bidRequest.bids[0].params['video'] = { videoParam: 'videoValue' }; - adapter.callBids(bidRequest); - expect(requests[0].url).to.include('videoParam=videoValue'); - }); - - it('parses the first size for video requests', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - adapter.callBids(bidRequest); - expect(requests[0].url).to.include('vpw=300'); - expect(requests[0].url).to.include('vph=250'); - }); - - it('sends requests to production by default', () => { - adapter.callBids(JSON.parse(BASE_REQUEST)); - expect(requests[0].url).to.include('//ads.aerserv.com'); - }); - - it('sends requests to the specified endpoint when \'env\' is provided', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0].params['env'] = 'dev'; - adapter.callBids(bidRequest); - expect(requests[0].url).to.include('//dev-ads.aerserv.com'); - }); - }); - - describe('response handling', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create(); - }); - - afterEach(() => { - server.restore(); - }); - - it('responds with an empty bid without required parameters', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0].params = {}; - adapter.callBids(bidRequest); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with an empty bid on empty response', () => { - server.respondWith(''); - - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with an empty bid on un-parseable JSON response', () => { - server.respondWith('{\"bad\":\"json}'); - - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with a valid bid returned ad', () => { - server.respondWith(JSON.stringify({cpm: 5, w: 320, h: 50, adm: 'sweet ad markup'})); - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(1); - }); - - it('responds with a valid bid from returned ad', () => { - server.respondWith(JSON.stringify({cpm: 5, w: 320, h: 50, vastUrl: 'sweet URL where VAST is at'})); - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - bidRequest.bids[0]['video'] = {}; - adapter.callBids(bidRequest); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(1); - }); - - it('responds with empty bid if response has no ad', () => { - server.respondWith(JSON.stringify({error: 'no ads'})); - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - // things that should never occur - it('responds with empty bid if response has 0 or below cpm', () => { - server.respondWith(JSON.stringify({cpm: 0, w: 320, h: 50, adm: 'sweet ad markup'})); - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with empty bid if response has no markup', () => { - server.respondWith(JSON.stringify({cpm: 5.0, w: 320, h: 50})); - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with an empty bid if response has no video markup', () => { - server.respondWith(JSON.stringify({cpm: 5, w: 320, h: 50})); - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - bidRequest.bids[0]['video'] = {}; - adapter.callBids(bidRequest); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - }); -}); diff --git a/test/spec/modules/appnexusAstBidAdapter_spec.js b/test/spec/modules/appnexusAstBidAdapter_spec.js deleted file mode 100644 index 660ecfc507a..00000000000 --- a/test/spec/modules/appnexusAstBidAdapter_spec.js +++ /dev/null @@ -1,428 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/appnexusAstBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; - -const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; - -describe('AppNexusAdapter', () => { - const adapter = newBidder(spec); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - let bid = { - 'bidder': 'appnexusAst', - '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', () => { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return true when required params found', () => { - 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', () => { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - 'placementId': 0 - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', () => { - let bidRequests = [ - { - 'bidder': 'appnexusAst', - 'params': { - 'placementId': '10433394' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - it('should add source and verison to the tag', () => { - 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', () => { - ['banner', 'video', 'native'].forEach(type => { - 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]); - }); - }); - - it('should populate the ad_types array on outstream requests', () => { - 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']); - }); - - it('sends bid request to ENDPOINT via POST', () => { - 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', () => { - 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 - }); - }); - - it('should attach valid user params to the tag', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - user: { - external_uid: '123', - 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', - }); - }); - - it('should attache native params to the request', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - title: {required: true}, - body: {required: true}, - image: {required: true, sizes: [{ width: 100, height: 100 }] }, - cta: {required: false}, - sponsoredBy: {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}, - main_image: {required: true, sizes: [{ width: 100, height: 100 }] }, - ctatext: {required: false}, - sponsored_by: {required: true} - }); - }); - - it('sets minimum native asset params when not provided on adunit', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: {required: true}, - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: {required: true, sizes: [{}] }, - }); - }); - - it('does not overwrite native ad unit params with mimimum params', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: { - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: { - required: true, - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - }, - }); - }); - - it('should convert keyword params to proper form and attaches to request', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - keywords: { - single: 'val', - singleArr: ['val'], - singleArrNum: [5], - multiValMixed: ['value1', 2, 'value3'], - singleValNum: 123, - 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'] - }]); - }); - - it('should should add payment rules to the request', () => { - 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); - }); - }) - - describe('interpretResponse', () => { - let response = { - 'version': '3.0.0', - 'tags': [ - { - 'uuid': '3db3773286ee59', - 'tag_id': 10433394, - 'auction_id': '4534722592064951574', - 'nobid': false, - 'no_ad_url': 'http://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, - 'rtb': { - 'banner': { - 'content': '', - 'width': 300, - 'height': 250 - }, - 'trackers': [ - { - 'impression_urls': [ - 'http://lax1-ib.adnxs.com/impression' - ], - 'video_events': {} - } - ] - } - } - ] - } - ] - }; - - it('should get correct bid response', () => { - let expectedResponse = [ - { - 'requestId': '3db3773286ee59', - 'cpm': 0.5, - 'creativeId': 29681110, - 'dealId': undefined, - 'width': 300, - 'height': 250, - 'ad': '', - 'mediaType': 'banner', - 'currency': 'USD', - 'ttl': 300, - 'netRevenue': true - } - ]; - let bidderRequest; - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); - }); - - it('handles nobid responses', () => { - 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 non-banner media responses', () => { - let response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'cpm': 0.500000, - 'rtb': { - 'video': { - 'content': '' - } - } - }] - }] - }; - let bidderRequest; - - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result[0]).to.have.property('vastUrl'); - expect(result[0]).to.have.property('mediaType', 'video'); - }); - - it('handles native responses', () => { - let response1 = Object.assign({}, response); - response1.tags[0].ads[0].ad_type = 'native'; - response1.tags[0].ads[0].rtb.native = { - 'title': 'Native Creative', - 'desc': 'Cool description great stuff', - 'ctatext': 'Do it', - 'sponsored': 'AppNexus', - 'icon': { - 'width': 0, - 'height': 0, - 'url': 'http://cdn.adnxs.com/icon.png' - }, - 'main_img': { - 'width': 2352, - 'height': 1516, - 'url': 'http://cdn.adnxs.com/img.png' - }, - 'link': { - 'url': 'https://www.appnexus.com', - 'fallback_url': '', - 'click_trackers': ['http://nym1-ib.adnxs.com/click'] - }, - 'impression_trackers': ['http://example.com'], - }; - let bidderRequest; - - 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('http://cdn.adnxs.com/img.png'); - }); - }); -}); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 96916f3fa35..c95fe18c688 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -1,52 +1,405 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/appnexusBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; - -describe('AppNexus Adapter', () => { - let adapter; - - const REQUEST = { - 'bidderCode': 'appnexus', - 'requestId': 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - 'bidderRequestId': '7101db09af0db2', - 'bids': [ +import { expect } from 'chai'; +import { spec } from 'modules/appnexusBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; + +describe('AppNexusAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'appnexus', + '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', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', () => { + 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', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ { 'bidder': 'appnexus', 'params': { - 'placementId': '4799418', - 'trafficSourceCode': 'source' + 'placementId': '10433394' }, - 'placementCode': '/19968336/header-bid-tag1', - 'sizes': [ - [728, 90], - [970, 90] - ], - 'bidId': '84ab500420319d', - 'bidderRequestId': '7101db09af0db2', - 'requestId': 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6' + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', } - ], - 'start': 1469479810130 - }; - - let sandbox; - let adLoaderStub; - beforeEach(() => { - sandbox = sinon.sandbox.create(); - sandbox.stub(bidManager, 'addBidResponse'); - adLoaderStub = sandbox.stub(adLoader, 'loadScript'); - }); + ]; - afterEach(() => { - sandbox.restore(); - }); + it('should add source and verison to the tag', () => { + 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('sends bid request to ENDPOINT via POST', () => { + 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', () => { + 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 + }); + }); + + it('should attach valid user params to the tag', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + user: { + external_uid: '123', + 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', + }); + }); + + it('should attache native params to the request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + title: {required: true}, + body: {required: true}, + image: {required: true, sizes: [{ width: 100, height: 100 }] }, + cta: {required: false}, + sponsoredBy: {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}, + main_image: {required: true, sizes: [{ width: 100, height: 100 }] }, + ctatext: {required: false}, + sponsored_by: {required: true} + }); + }); + + it('sets minimum native asset params when not provided on adunit', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: {required: true}, + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: {required: true, sizes: [{}] }, + }); + }); + + it('does not overwrite native ad unit params with mimimum params', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: { + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: { + required: true, + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + }, + }); + }); + + it('should convert keyword params to proper form and attaches to request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + 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'] + }]); + }); + + it('should should add payment rules to the request', () => { + 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); + }); + }) + + describe('interpretResponse', () => { + let response = { + 'version': '3.0.0', + 'tags': [ + { + 'uuid': '3db3773286ee59', + 'tag_id': 10433394, + 'auction_id': '4534722592064951574', + 'nobid': false, + 'no_ad_url': 'http://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, + 'rtb': { + 'banner': { + 'content': '', + 'width': 300, + 'height': 250 + }, + 'trackers': [ + { + 'impression_urls': [ + 'http://lax1-ib.adnxs.com/impression' + ], + 'video_events': {} + } + ] + } + } + ] + } + ] + }; + + it('should get correct bid response', () => { + let expectedResponse = [ + { + 'requestId': '3db3773286ee59', + 'cpm': 0.5, + 'creativeId': 29681110, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true + } + ]; + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', () => { + 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 non-banner media responses', () => { + let response = { + 'tags': [{ + 'uuid': '84ab500420319d', + 'ads': [{ + 'ad_type': 'video', + 'cpm': 0.500000, + 'rtb': { + 'video': { + 'content': '' + } + } + }] + }] + }; + let bidderRequest; + + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result[0]).to.have.property('vastUrl'); + expect(result[0]).to.have.property('descriptionUrl'); + expect(result[0]).to.have.property('mediaType', 'video'); + }); + + it('handles native responses', () => { + let response1 = Object.assign({}, response); + response1.tags[0].ads[0].ad_type = 'native'; + response1.tags[0].ads[0].rtb.native = { + 'title': 'Native Creative', + 'desc': 'Cool description great stuff', + 'ctatext': 'Do it', + 'sponsored': 'AppNexus', + 'icon': { + 'width': 0, + 'height': 0, + 'url': 'http://cdn.adnxs.com/icon.png' + }, + 'main_img': { + 'width': 2352, + 'height': 1516, + 'url': 'http://cdn.adnxs.com/img.png' + }, + 'link': { + 'url': 'https://www.appnexus.com', + 'fallback_url': '', + 'click_trackers': ['http://nym1-ib.adnxs.com/click'] + }, + 'impression_trackers': ['http://example.com'], + }; + let bidderRequest; - describe('callBids', () => { - it('should contain traffic_source_code', () => { - adapter = new Adapter(); - adapter.callBids(REQUEST); - expect(adLoaderStub.getCall(0).args[0]).to.contain('traffic_source_code=source'); + 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('http://cdn.adnxs.com/img.png'); }); }); }); diff --git a/test/spec/modules/atomxBidAdapter_spec.js b/test/spec/modules/atomxBidAdapter_spec.js deleted file mode 100644 index 646061912e7..00000000000 --- a/test/spec/modules/atomxBidAdapter_spec.js +++ /dev/null @@ -1,150 +0,0 @@ -var chai = require('chai'); -var Adapter = require('modules/atomxBidAdapter')(); -var Ajax = require('src/ajax'); -var adLoader = require('src/adloader'); -var bidmanager = require('src/bidmanager.js'); -var CONSTANTS = require('src/constants.json'); - -describe('Atomx adapter', function () { - var validData_1 = { - bids: [ - { - bidder: 'atomx', - bidId: 'bid_id', - params: {id: 1234}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [800, 600]] - } - ] - }; - var validData_2 = { - bids: [ - { - bidder: 'adtomx', - bidId: 'bid_id', - params: {id: 5678}, - placementCode: 'ad-unit-1', - sizes: [300, 250] - } - ] - }; - - var invalidData = { - bids: [ - { - bidder: 'atomx', - bidId: 'bid_id', - params: {}, - placementCode: 'ad-unit-1', - sizes: [[300, 250]] - } - ] - }; - - var responseWithAd = JSON.stringify({ - 'cpm': 2.2, - 'url': 'http://p.ato.mx/placement?id=1234', - 'width': 300, - 'height': 250, - 'code': 'ad-unit-1' - }); - var responseWithoutAd = JSON.stringify({ - 'cpm': 0, - 'url': 'http://p.ato.mx/placement?id=1234', - 'width': 300, - 'height': 250, - 'code': 'ad-unit-1' - }); - - var responseEmpty = ''; - var validJsonParams = { - id: '1234', - prebid: 'ad-unit-1', - size: '300x250' - }; - - describe('loads the tag code', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript'); - Adapter.callBids(validData_1); - sinon.assert.calledOnce(stubLoadScript); - let url = stubLoadScript.firstCall.args[0]; - let callback = stubLoadScript.firstCall.args[1]; - expect(url).to.equal('http://s.ato.mx/b.js'); - expect(callback).to.be.a('function'); - }); - describe('bid request with valid data', function () { - var stubAjax; - beforeEach(function () { - window.atomx_prebid = function() { - return '/placement'; - }; - stubAjax = sinon.stub(Ajax, 'ajax'); - }); - afterEach(function () { - stubAjax.restore(); - }); - it('bid request should be called. sizes style -> [[],[]]', function () { - Adapter.callBids(validData_1); - sinon.assert.calledTwice(stubAjax); - }); - it('bid request should be called. sizes style -> []', function () { - Adapter.callBids(validData_2); - sinon.assert.calledOnce(stubAjax); - }); - it('ajax params should be matched', function () { - Adapter.callBids(validData_1); - sinon.assert.calledWith(stubAjax, sinon.match('/placement', function () { - }, validJsonParams, {method: 'GET'})); - }); - }); - describe('bid request with invalid data', function () { - var addBidResponse, stubAjax; - beforeEach(function () { - window.atomx_prebid = function() { - return '/placement'; - }; - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - stubAjax = sinon.stub(Ajax, 'ajax'); - }); - afterEach(function () { - addBidResponse.restore(); - stubAjax.restore(); - }); - it('ajax shouldn\'t be called', function () { - Adapter.callBids(invalidData); - sinon.assert.notCalled(stubAjax); - }); - it('bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID + '"', function () { - Adapter.callBids(invalidData); - expect(addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(addBidResponse.firstCall.args[1].bidderCode).to.equal('atomx'); - }); - }); - describe('bid response', function () { - var addBidResponse; - beforeEach(function () { - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - afterEach(function () { - addBidResponse.restore(); - }); - it('with ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.GOOD + '"', function () { - Adapter.responseCallback(validData_1.bids[0], responseWithAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(arg.bidderCode).to.equal('atomx'); - }); - it('without ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(validData_1.bids[0], responseWithoutAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('atomx'); - }); - it('empty. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(validData_1.bids[0], responseEmpty); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('atomx'); - }) - }); -}); diff --git a/test/spec/modules/bidfluenceBidAdapter_spec.js b/test/spec/modules/bidfluenceBidAdapter_spec.js deleted file mode 100644 index f623954fa9f..00000000000 --- a/test/spec/modules/bidfluenceBidAdapter_spec.js +++ /dev/null @@ -1,71 +0,0 @@ -describe('Bidfluence Adapter', () => { - const expect = require('chai').expect; - const adapter = require('modules/bidfluenceBidAdapter'); - const bidmanager = require('src/bidmanager'); - - var REQUEST = { - bidderCode: 'bidfluence', - sizes: [[300, 250]], - placementCode: 'div-1', - bids: [{ - bidder: 'bidfluence', - params: { - pubId: 'test', - adunitId: 'test' - } - }] - }; - - var RESPONSE = { - ad: 'ad-code', - cpm: 0.9, - width: 300, - height: 250, - placementCode: 'div-1' - }; - - var NO_RESPONSE = { - ad: 'ad-code', - cpm: 0, - width: 300, - height: 250, - placementCode: 'div-1' - }; - - it('Should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.bfPbjsCB).to.exist.and.to.be.a('function'); - }); - - it('Shoud push a valid bid', () => { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - $$PREBID_GLOBAL$$._bidsRequested.push(REQUEST); - adapter(); - $$PREBID_GLOBAL$$.bfPbjsCB(RESPONSE); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('div-1'); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('bidfluence'); - - stubAddBidResponse.restore(); - }); - - it('Shoud push an empty bid', () => { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - $$PREBID_GLOBAL$$._bidsRequested.push(REQUEST); - adapter(); - - $$PREBID_GLOBAL$$.bfPbjsCB(NO_RESPONSE); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('div-1'); - expect(bidObject1.getStatusCode()).to.equal(2); - expect(bidObject1.bidderCode).to.equal('bidfluence'); - - stubAddBidResponse.restore(); - }); -}); diff --git a/test/spec/modules/c1xBidAdapter_spec.js b/test/spec/modules/c1xBidAdapter_spec.js deleted file mode 100644 index e1a48a5b701..00000000000 --- a/test/spec/modules/c1xBidAdapter_spec.js +++ /dev/null @@ -1,203 +0,0 @@ -import {expect} from 'chai'; -import C1XAdapter from 'modules/c1xBidAdapter'; -import bidmanager from 'src/bidmanager'; -import adLoader from 'src/adloader'; - -let getDefaultBidRequest = () => { - return { - bidderCode: 'c1x', - bids: [{ - bidder: 'c1x', - sizes: [[300, 250], [300, 600]], - params: { - siteId: '999', - pixelId: '9999', - placementCode: 'div-c1x-ht', - domain: 'http://c1exchange.com/' - } - }] - }; -}; - -let getDefaultBidResponse = () => { - return { - bid: true, - adId: 'div-c1x-ht', - cpm: 3.31, - ad: '
', - width: 300, - height: 250 - }; -}; - -describe('c1x adapter tests: ', () => { - let pbjs = window.$$PREBID_GLOBAL$$ || {}; - let stubLoadScript; - let adapter; - - function createBidderRequest(bids) { - let bidderRequest = getDefaultBidRequest(); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - return bidderRequest; - } - - beforeEach(() => { - adapter = new C1XAdapter(); - }); - - describe('check callBids()', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - describe('creation of bid url', () => { - beforeEach(() => { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - afterEach(() => { - stubLoadScript.restore(); - }); - it('should be called only once', () => { - adapter.callBids(getDefaultBidRequest()); - sinon.assert.calledOnce(stubLoadScript); - expect(window._c1xResponse).to.exist.and.to.be.a('function'); - }); - it('require parameters before call', () => { - let xhr; - let requests; - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - adapter.callBids(getDefaultBidRequest()); - expect(requests).to.be.empty; - xhr.restore(); - }); - it('should send with correct parameters', () => { - adapter.callBids(getDefaultBidRequest()); - let expectedUrl = stubLoadScript.getCall(0).args[0]; - sinon.assert.calledWith(stubLoadScript, expectedUrl); - }); - it('should hit endpoint with optional param', () => { - let bids = [{ - bidder: 'c1x', - sizes: [[300, 250], [300, 600]], - params: { - siteId: '999', - placementCode: 'div-c1x-ht', - endpoint: 'http://ht-integration.c1exchange.com:9000/ht', - floorPriceMap: { - '300x250': 4.00 - }, - dspid: '4288' - } - }]; - adapter.callBids(createBidderRequest(bids)); - let expectedUrl = stubLoadScript.getCall(0).args[0]; - sinon.assert.calledWith(stubLoadScript, expectedUrl); - bids[0].sizes = [[728, 90]]; - adapter.callBids(createBidderRequest(bids)); - sinon.assert.calledTwice(stubLoadScript); - }); - it('should hit default bidder endpoint', () => { - let bid = getDefaultBidRequest(); - bid.bids[0].params.endpoint = null; - adapter.callBids(bid); - let expectedUrl = stubLoadScript.getCall(0).args[0]; - sinon.assert.calledWith(stubLoadScript, expectedUrl); - }); - it('should throw error msg if no site id provided', () => { - let bid = getDefaultBidRequest(); - bid.bids[0].params.siteId = ''; - adapter.callBids(bid); - sinon.assert.notCalled(stubLoadScript); - }); - it('should not inject audience pixel if no pixelId provided', () => { - let bid = getDefaultBidRequest(); - let responsePId; - bid.bids[0].params.pixelId = ''; - adapter.callBids(bid); - }); - }); - describe('bid response', () => { - let server; - let stubAddBidResponse; - beforeEach(() => { - adapter = new C1XAdapter(); - server = sinon.fakeServer.create(); - stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - stubAddBidResponse.restore(); - }); - - it('callback function should exist', function () { - expect(pbjs._c1xResponse).to.exist.and.to.be.a('function'); - }); - it('should get JSONP from c1x bidder', function () { - let responses = []; - let stubC1XResponseFunc = sinon.stub(pbjs, '_c1xResponse'); - responses.push(getDefaultBidResponse()); - window._c1xResponse(JSON.stringify(responses)); - sinon.assert.calledOnce(stubC1XResponseFunc); - stubC1XResponseFunc.restore(); - }); - it('should be added to bidmanager after returned from bidder', () => { - let responses = []; - responses.push(getDefaultBidResponse()); - pbjs._c1xResponse(responses); - sinon.assert.calledOnce(stubAddBidResponse); - }); - it('should send correct arguments to bidmanager.addBidResponse', () => { - let responses = []; - responses.push(getDefaultBidResponse()); - pbjs._c1xResponse(JSON.stringify(responses)); - var responseAdId = stubAddBidResponse.getCall(0).args[0]; - var bidObject = stubAddBidResponse.getCall(0).args[1]; - expect(responseAdId).to.equal('div-c1x-ht'); - expect(bidObject.cpm).to.equal(3.31); - expect(bidObject.width).to.equal(300); - expect(bidObject.height).to.equal(250); - expect(bidObject.ad).to.equal('
'); - expect(bidObject.bidderCode).to.equal('c1x'); - sinon.assert.calledOnce(stubAddBidResponse); - }); - it('should response to bidmanager when it is a no bid', () => { - let responses = []; - responses.push({'bid': false, 'adId': 'div-gpt-ad-1494499685685-0'}); - pbjs._c1xResponse(responses); - let responseAdId = stubAddBidResponse.getCall(0).args[0]; - let bidObject = stubAddBidResponse.getCall(0).args[1]; - expect(responseAdId).to.equal('div-gpt-ad-1494499685685-0'); - expect(bidObject.statusMessage).to.equal('Bid returned empty or error response'); - sinon.assert.calledOnce(stubAddBidResponse); - }); - it('should show error when bidder sends invalid bid responses', () => { - let responses; - let adUnits = []; - let unit = {}; - let params = getDefaultBidRequest(); - - unit.bids = params.bids; - unit.code = '/123456/header-bid-tag-1'; - unit.sizes = [[300, 250]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - - $$PREBID_GLOBAL$$.adUnits = adUnits; - - pbjs._c1xResponse(responses); - let bidObject = stubAddBidResponse.getCall(0).args[1]; - expect(bidObject.statusMessage).to.equal('Bid returned empty or error response'); - sinon.assert.calledOnce(stubAddBidResponse); - }); - }); -}); diff --git a/test/spec/modules/carambolaBidAdapter_spec.js b/test/spec/modules/carambolaBidAdapter_spec.js deleted file mode 100644 index e68a5c9221d..00000000000 --- a/test/spec/modules/carambolaBidAdapter_spec.js +++ /dev/null @@ -1,139 +0,0 @@ -import {expect} from 'chai'; -import * as utils from 'src/utils'; -import CarambolaAdapter from 'modules/carambolaBidAdapter'; -import bidmanager from 'src/bidmanager'; - -const DEFAULT_BIDDER_REQUEST = { - bidderCode: 'carambola', - requestId: 'c9ad932a-41d9-4821-b6dc-0c8146029faf', - adId: '2e3daacdeed03d', - start: new Date().getTime(), - bids: [{ - bidder: 'carambola', - adId: '2e3daacdeed03d', - requestId: 'c9ad932a-41d9-4821-b6dc-0c8146029faf', - adUnitCode: 'cbola_prebid_code_97', - token: 'CGYCLyIy', - pageViewId: '22478638', - params: { - pid: 'hbtest', - did: 112591, - wid: 0 - } - }] -}; - -const DEFAULT_HB_RESPONSE = { - cpm: 0.1693953107111156, - ad: ' ', - token: '9cd6bf9c-433d-4663-b67f-da727f4cebff', - width: '300', - height: '250', - currencyCode: 'USD', - pageViewId: '22478638', - requestStatus: 1 - -}; - -describe('carambolaAdapter', function () { - let adapter; - - beforeEach(() => adapter = new CarambolaAdapter()); - - function createBidderRequest({bids, params} = {}) { - var bidderRequest = utils.deepClone(DEFAULT_BIDDER_REQUEST); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - if (params) { - bidderRequest.bids.forEach(bid => bid.params = params); - } - return bidderRequest; - } - - describe('callBids()', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - // bid request starts - describe('bid request', () => { - let xhr; - let requests; - - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => xhr.restore()); - - it('requires parameters to be made', () => { - adapter.callBids({}); - expect(requests[0]).to.be.empty; - }); - - it('should hit the default hb.carambo.la endpoint', () => { - adapter.callBids(DEFAULT_BIDDER_REQUEST); - expect(requests[0].url).to.contain('hb.carambo.la'); - }); - - it('should verifiy that a page_view_id is sent', () => { - adapter.callBids(DEFAULT_BIDDER_REQUEST); - expect(requests[0].url).to.contain('pageViewId='); - }); - - it('should should send the correct did', () => { - adapter.callBids(createBidderRequest({ - params: { - did: 112591, - wid: 0 - } - })); - expect(requests[0].url).to.contain('did=112591'); - }); - }); - // bid request ends - - // bid response starts - describe('bid response', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create(); - sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('should be added to bidmanager if response is valid', () => { - server.respondWith(JSON.stringify(DEFAULT_HB_RESPONSE)); - adapter.callBids(DEFAULT_BIDDER_REQUEST); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - }); - - it('should be added to bidmanager with correct bidderCode', () => { - server.respondWith(JSON.stringify(DEFAULT_HB_RESPONSE)); - adapter.callBids(DEFAULT_BIDDER_REQUEST); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1]).to.have.property('bidderCode', 'carambola'); - }); - - it('should have pageViewId matching the pageViewId from related bid request', () => { - server.respondWith(JSON.stringify(DEFAULT_HB_RESPONSE)); - adapter.callBids(DEFAULT_BIDDER_REQUEST); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1]) - .to.have.property('pvid', DEFAULT_BIDDER_REQUEST.bids[0].pageViewId); - }); - }); - // bid response ends - }); -}); diff --git a/test/spec/modules/centroBidAdapter_spec.js b/test/spec/modules/centroBidAdapter_spec.js deleted file mode 100644 index a4bceb5de39..00000000000 --- a/test/spec/modules/centroBidAdapter_spec.js +++ /dev/null @@ -1,225 +0,0 @@ -describe('centro adapter tests', function () { - var expect = require('chai').expect; - var assert = require('chai').assert; - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - - var adapter = require('modules/centroBidAdapter'); - var bidmanager = require('src/bidmanager'); - var adLoader = require('src/adloader'); - var utils = require('src/utils'); - - let stubLoadScript; - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - var logErrorSpy; - beforeEach(function () { - logErrorSpy = sinon.spy(utils, 'logError'); - }); - - afterEach(function () { - logErrorSpy.restore(); - }); - - describe('creation of bid url', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - - it('should fix parameter name', function () { - var params = { - bidderCode: 'centro', - bids: [ - { - bidder: 'centro', - sizes: [[300, 250]], - params: { - unit: 28136, - page_url: 'http://test_url.ru' - }, - bidId: '1234', - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: { - unit: 28137 - }, - bidId: '5678', - placementCode: 'div-gpt-ad-12345-2' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: {}, - bidId: '9101112', - placementCode: 'div-gpt-ad-12345-3' - } - ] - }; - - adapter().callBids(params); - var bidUrl1 = stubLoadScript.getCall(0).args[0]; - var bidUrl2 = stubLoadScript.getCall(1).args[0]; - - sinon.assert.calledWith(logErrorSpy, 'Bid has no unit', 'centro'); - sinon.assert.calledWith(stubLoadScript, bidUrl1); - - var parsedBidUrl = urlParse(bidUrl1); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - var generatedCallback = 'window["adCentroHandler_28136300x2501234"]'; - - expect(parsedBidUrl.hostname).to.equal('staging.brand-server.com'); - expect(parsedBidUrl.pathname).to.equal('/hb'); - - expect(parsedBidUrlQueryString).to.have.property('s').and.to.equal('28136'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.equal('http://test_url.ru'); - expect(parsedBidUrlQueryString).to.have.property('sz').and.to.equal('300x250'); - expect(parsedBidUrlQueryString).to.have.property('callback').and.to.equal(generatedCallback); - - sinon.assert.calledWith(stubLoadScript, bidUrl2); - - parsedBidUrl = urlParse(bidUrl2); - parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - generatedCallback = 'window["adCentroHandler_28137728x905678"]'; - - expect(parsedBidUrl.hostname).to.equal('t.brand-server.com'); - expect(parsedBidUrl.pathname).to.equal('/hb'); - - expect(parsedBidUrlQueryString).to.have.property('s').and.to.equal('28137'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.equal(location.href); - expect(parsedBidUrlQueryString).to.have.property('sz').and.to.equal('728x90'); - expect(parsedBidUrlQueryString).to.have.property('callback').and.to.equal(generatedCallback); - }); - }); - - describe('handling of the callback response', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._bidsReceived = []; - } - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - if (typeof ($$PREBID_GLOBAL$$._adsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._adsReceived = []; - } - - var params = { - bidderCode: 'centro', - bids: [ - { - bidder: 'centro', - sizes: [[300, 250]], - params: { - unit: 28136 - }, - bidId: '12345', - placementCode: '/19968336/header-bid-tag-0' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: { - unit: 111111 - }, - bidId: '12346', - placementCode: '/19968336/header-bid-tag-1' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: { - unit: 222222 - }, - bidId: '12347', - placementCode: '/19968336/header-bid-tag-2' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: { - unit: 333333 - }, - bidId: '12348', - placementCode: '/19968336/header-bid-tag-3' - } - ] - }; - - it('callback function should exist', function () { - adapter().callBids(params); - - expect(window['adCentroHandler_28136300x25012345']) - .to.exist.and.to.be.a('function'); - expect(window['adCentroHandler_111111728x9012346']) - .to.exist.and.to.be.a('function'); - }); - - it('bidmanager.addBidResponse should be called with correct arguments', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - adapter().callBids(params); - - var adUnits = new Array(); - var unit = new Object(); - unit.bids = params.bids; - unit.code = '/19968336/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - - $$PREBID_GLOBAL$$.adUnits = adUnits; - - var response = {'adTag': '
test content
', 'statusMessage': 'Bid available', 'height': 250, '_comment': '', 'value': 0.2, 'width': 300, 'sectionID': 28136}; - var response2 = {'adTag': '', 'statusMessage': 'No bid', 'height': 0, 'value': 0, 'width': 0, 'sectionID': 111111}; - var response3 = {'adTag': '', 'height': 0, 'value': 0, 'width': 0, 'sectionID': 222222}; - var response4 = ''; - - window['adCentroHandler_28136300x25012345'](response); - window['adCentroHandler_111111728x9012346'](response2); - window['adCentroHandler_222222728x9012347'](response3); - window['adCentroHandler_333333728x9012348'](response4); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - var bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - var bidObject2 = stubAddBidResponse.getCall(1).args[1]; - var bidPlacementCode3 = stubAddBidResponse.getCall(2).args[0]; - var bidObject3 = stubAddBidResponse.getCall(2).args[1]; - var bidPlacementCode4 = stubAddBidResponse.getCall(3).args[0]; - var bidObject4 = stubAddBidResponse.getCall(3).args[1]; - - expect(logErrorSpy.getCall(0).args[0]).to.equal('Requested unit is 222222. Bid has missmatch format.'); - expect(logErrorSpy.getCall(1).args[0]).to.equal('Requested unit is 333333. Response has no bid.'); - - expect(bidPlacementCode1).to.equal('/19968336/header-bid-tag-0'); - expect(bidObject1.cpm).to.equal(0.2); - expect(bidObject1.ad).to.equal('
test content
'); - expect(bidObject1.width).to.equal(300); - expect(bidObject1.height).to.equal(250); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('centro'); - - expect(bidPlacementCode2).to.equal('/19968336/header-bid-tag-1'); - expect(bidObject2.getStatusCode()).to.equal(2); - expect(bidPlacementCode3).to.equal('/19968336/header-bid-tag-2'); - expect(bidObject3.getStatusCode()).to.equal(2); - expect(bidPlacementCode4).to.equal('/19968336/header-bid-tag-3'); - expect(bidObject4.getStatusCode()).to.equal(2); - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js deleted file mode 100644 index e8435d90679..00000000000 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ /dev/null @@ -1,127 +0,0 @@ -import { expect } from 'chai'; -import Adapter from '../../../modules/colossussspBidAdapter'; -import adapterManager from 'src/adaptermanager'; -import bidManager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; - -describe('ColossusSSP adapter tests', function () { - let sandbox; - const adUnit = { - code: 'colossusssp', - sizes: [[300, 250], [300, 600]], - bids: [{ - bidder: 'colossusssp', - params: { - placement_id: 0 - } - }] - }; - - const response = { - ad_id: 15, - adm: '
Bid Response
', - cpm: 0.712, - deal: '5e1f0a8f2aa1', - width: 300, - height: 250 - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('ColossusSSP callBids validation', () => { - let bids, - server; - - beforeEach(() => { - bids = []; - server = sinon.fakeServer.create(); - sandbox.stub(bidManager, 'addBidResponse', (elemId, bid) => { - bids.push(bid); - }); - }); - - afterEach(() => { - server.restore(); - }); - - let adapter = adapterManager.bidderRegistry['colossusssp']; - - it('Valid bid-request', () => { - sandbox.stub(adapter, 'callBids'); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - - let bidderRequest = adapter.callBids.getCall(0).args[0]; - - expect(bidderRequest).to.have.property('bids') - .that.is.an('array') - .with.lengthOf(1); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .to.have.property('bidder', 'colossusssp'); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('sizes') - .that.is.an('array') - .with.lengthOf(2) - .that.deep.equals(adUnit.sizes); - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('placement_id', 0); - }); - - it('Valid bid-response', () => { - server.respondWith(JSON.stringify( - response - )); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - server.respond(); - - expect(bids).to.be.lengthOf(1); - expect(bids[0].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bids[0].bidderCode).to.equal('colossusssp'); - expect(bids[0].width).to.equal(300); - expect(bids[0].height).to.equal(250); - expect(bids[0].cpm).to.equal(0.712); - expect(bids[0].dealId).to.equal('5e1f0a8f2aa1'); - }); - }); - - describe('MAS mapping / ordering', () => { - let masSizeOrdering = Adapter.masSizeOrdering; - - it('should not include values without a proper mapping', () => { - let ordering = masSizeOrdering([[320, 50], [42, 42], [300, 250], [640, 480], [0, 0]]); - expect(ordering).to.deep.equal([15, 43, 65]); - }); - - it('should sort values without any MAS priority sizes in regular ascending order', () => { - let ordering = masSizeOrdering([[320, 50], [640, 480], [200, 600]]); - expect(ordering).to.deep.equal([43, 65, 119]); - }); - - it('should sort MAS priority sizes in the proper order w/ rest ascending', () => { - let ordering = masSizeOrdering([[320, 50], [640, 480], [300, 250], [200, 600]]); - expect(ordering).to.deep.equal([15, 43, 65, 119]); - - ordering = masSizeOrdering([[320, 50], [300, 250], [640, 480], [200, 600], [728, 90]]); - expect(ordering).to.deep.equal([15, 2, 43, 65, 119]); - - ordering = masSizeOrdering([ [320, 50], [640, 480], [200, 600], [728, 90]]); - expect(ordering).to.deep.equal([2, 43, 65, 119]); - }) - }); -}); - -function clone(obj) { - return JSON.parse(JSON.stringify(obj)); -} diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index a64a1d956c4..1d62cba72c1 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -3,7 +3,6 @@ import {spec} from 'modules/conversantBidAdapter'; import * as utils from 'src/utils'; var Adapter = require('modules/conversantBidAdapter'); -var bidManager = require('src/bidmanager'); describe('Conversant adapter tests', function() { const siteId = '108060'; diff --git a/test/spec/modules/coxBidAdapter_spec.js b/test/spec/modules/coxBidAdapter_spec.js deleted file mode 100644 index ee1eb991f23..00000000000 --- a/test/spec/modules/coxBidAdapter_spec.js +++ /dev/null @@ -1,120 +0,0 @@ -import Adapter from 'modules/coxBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; -import {expect} from 'chai'; - -describe('CoxAdapter', () => { - let adapter; - let loadScriptStub; - let addBidResponseSpy; - - let emitScript = (script) => { - let node = document.createElement('script'); - node.type = 'text/javascript'; - node.appendChild(document.createTextNode(script)); - document.getElementsByTagName('head')[0].appendChild(node); - }; - - beforeEach(() => { - adapter = new Adapter(); - addBidResponseSpy = sinon.spy(bidManager, 'addBidResponse'); - }); - - afterEach(() => { - loadScriptStub.restore(); - addBidResponseSpy.restore(); - }); - - describe('response handling', () => { - const normalResponse = 'cdsTag.__callback__({"zones":{"as2000005991707":{"ad" : "

FOO<\/h1>","uid" : "","price" : 1.51,"floor" : 0,}},"tpCookieSync":"

FOOKIE<\/h1>"})'; - const zeroPriceResponse = 'cdsTag.__callback__({"zones":{"as2000005991707":{"ad" : "

DEFAULT FOO<\/h1>","uid" : "","price" : 0,"floor" : 0,}},"tpCookieSync":"

FOOKIE<\/h1>"})'; - const incompleteResponse = 'cdsTag.__callback__({"zones":{},"tpCookieSync":"

FOOKIE<\/h1>"})'; - - const oneBidConfig = { - bidderCode: 'cox', - bids: [{ - bidder: 'cox', - placementCode: 'FOO456789', - sizes: [300, 250], - params: { size: '300x250', id: 2000005991707, siteId: 2000100948180, env: 'PROD' }, - }] - }; - - // ===== 1 - it('should provide a correctly populated Bid given a valid response', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript', () => { emitScript(normalResponse); }) - - adapter.callBids(oneBidConfig); - - let bid = addBidResponseSpy.args[0][1]; - expect(bid.cpm).to.equal(1.51); - expect(bid.ad).to.be.a('string'); - expect(bid.bidderCode).to.equal('cox'); - }); - - // ===== 2 - it('should provide an empty Bid given a zero-price response', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript', () => { emitScript(zeroPriceResponse); }) - - adapter.callBids(oneBidConfig); - - let bid = addBidResponseSpy.args[0][1]; - expect(bid.cpm).to.not.be.ok - expect(bid.ad).to.not.be.ok; - }); - - // ===== 3 - it('should provide an empty Bid given an incomplete response', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript', () => { emitScript(incompleteResponse); }) - - adapter.callBids(oneBidConfig); - - let bid = addBidResponseSpy.args[0][1]; - expect(bid.cpm).to.not.be.ok - expect(bid.ad).to.not.be.ok; - }); - - // ===== 4 - it('should not provide a Bid given no response', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript', () => { emitScript(''); }); - - adapter.callBids(oneBidConfig); - - expect(addBidResponseSpy.callCount).to.equal(0); - }); - }); - - describe('request generation', () => { - const missingBidsConfig = { - bidderCode: 'cox', - bids: null, - }; - const missingParamsConfig = { - bidderCode: 'cox', - bids: [{ - bidder: 'cox', - placementCode: 'FOO456789', - sizes: [300, 250], - params: null, - }] - }; - - // ===== 5 - it('should not make an ad call given missing bids in config', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript'); - - adapter.callBids(missingBidsConfig); - - expect(loadScriptStub.callCount).to.equal(0); - }); - - // ===== 6 - it('should not make an ad call given missing params in config', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript'); - - adapter.callBids(missingParamsConfig); - - expect(loadScriptStub.callCount).to.equal(0); - }); - }); -}); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js deleted file mode 100644 index 68c554c7cb4..00000000000 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ /dev/null @@ -1,274 +0,0 @@ -import Adapter from '../../../modules/criteoBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import { ajax } from '../../../src/ajax' -import { expect } from 'chai'; - -var CONSTANTS = require('../../../src/constants'); - -/* ------------ Publishertag stub begin ------------ */ -before(() => { - window.Criteo = { - PubTag: { - DirectBidding: { - DirectBiddingSlot: function DirectBiddingSlot(placementCode, zoneid, nativeCallback, transactionId, sizes) { - return { - impId: placementCode, - nativeCallback: nativeCallback - }; - }, - - DirectBiddingUrlBuilder: function DirectBiddingUrlBuilder(isAudit) { return {} }, - - DirectBiddingEvent: function DirectBiddingEvent(profileId, urlBuilder, slots, success, error, timeout) { - return { - slots: slots, - eval: function () { - var callbacks = { - error: error, - success: success - } - ajax('//bidder.criteo.com/cdb', callbacks) - } - } - }, - - Size: function Size(width, height) { return {width: width, height: height} } - } - } - }; - - window.criteo_pubtag = window.criteo_pubtag || { - push: function (event) { - event.eval(); - } - } - - window.Criteo.events = window.Criteo.events || []; - window.Criteo.events.push = function (elem) { - if (typeof elem === 'function') { - elem(); - } - }; -}); -/* ------------ Publishertag stub end ------------ */ - -describe('criteo adapter test', () => { - let adapter; - let stubAddBidResponse; - - let validBid = { - bidderCode: 'criteo', - bids: [ - { - bidder: 'criteo', - placementCode: 'foo', - sizes: [[250, 350]], - params: { - zoneId: 32934, - audit: 'true' - } - } - ] - }; - - let validResponse = { slots: [{ impid: 'foo', cpm: 1.12, creative: "" }] }; - let invalidResponse = { slots: [{ 'impid': 'unknownSlot' }] } - - let validMultiBid = { - bidderCode: 'criteo', - bids: [ - { - bidder: 'criteo', - placementCode: 'foo', - sizes: [[250, 350]], - params: { - zoneId: 32934, - audit: 'true' - } - }, - { - bidder: 'criteo', - placementCode: 'bar', - sizes: [[250, 350]], - params: { - zoneId: 32935, - audit: 'true' - } - } - ] - }; - - let validNativeResponse = { slots: [{ impid: 'foo', cpm: 1.12, native: { productName: 'product0' } }] }; - let validNativeBid = { - bidderCode: 'criteo', - bids: [ - { - bidder: 'criteo', - placementCode: 'foo', - sizes: [[250, 350]], - params: { - zoneId: 32934, - audit: 'true', - nativeCallback: function (nativeJson) { console.log('Product name: ' + nativeJson.productName) } - } - } - ] - } - - beforeEach(() => { - adapter = new Adapter(); - }); - - afterEach(() => { - stubAddBidResponse.restore(); - }); - - describe('adding bids to the manager', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create({ autoRespond: true, respondImmediately: true }); - server.respondWith(JSON.stringify(validResponse)); - }); - - afterEach(() => { - server.restore(); - }); - - it('adds bid for valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.GOOD }); - done(); - }); - - adapter.callBids(validBid); - }); - - it('adds bid for multibid valid request', (done) => { - let callCount = 0; - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - callCount++; - - if (callCount == 2) { done(); } - }); - - adapter.callBids(validMultiBid); - }); - - it('adds bidderCode to the response of a valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.have.property('bidderCode', 'criteo'); - done(); - }); - - adapter.callBids(validBid); - }); - - it('adds cpm to the response of a valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.have.property('cpm', 1.12); - done(); - }); - adapter.callBids(validBid); - }); - - it('adds creative to the response of a valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.have.property('ad', ""); - done(); - }); - adapter.callBids(validBid); - }); - }); - - describe('adding bids to the manager with native bids', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create({ autoRespond: true, respondImmediately: true }); - server.respondWith(JSON.stringify(validNativeResponse)); - }); - - afterEach(() => { - server.restore(); - }); - - it('adds creative to the response of a native valid request', (done) => { - stubAddBidResponse = sinon.stub( - bidManager, 'addBidResponse', - function (adUnitCode, bid) { - let expectedAdProperty = ``; - - expect(bid).to.have.property('ad', expectedAdProperty); - done(); - }); - adapter.callBids(validNativeBid); - }); - }); - - describe('dealing with unexpected situations', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create({ autoRespond: true, respondImmediately: true }); - }); - - afterEach(() => { - server.restore(); - }); - - it('no bid if cdb handler responds with no bid empty string response', (done) => { - server.respondWith(''); - - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - adapter.callBids(validBid); - }); - - it('no bid if cdb handler responds with no bid empty object response', (done) => { - server.respondWith('{ }'); - - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - adapter.callBids(validBid); - }); - - it('no bid if cdb handler responds with HTTP error', (done) => { - server.respondWith([500, {}, 'Internal Server Error']); - - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - adapter.callBids(validBid); - }); - - it('no bid if response is invalid because response slots don\'t match input slots', (done) => { - server.respondWith(JSON.stringify(invalidResponse)); - - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - adapter.callBids(validBid); - }); - }); -}); diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index 06faa5665c9..37bb01b7c16 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -6,16 +6,21 @@ import { import { setConfig, addBidResponseHook, - currencySupportEnabled, currencyRates } from 'modules/currency'; +import { createHook } from 'src/hook'; + var assert = require('chai').assert; var expect = require('chai').expect; describe('currency', function () { let fakeCurrencyFileServer; + + let fn = sinon.spy(); + let hookFn = createHook('asyncSeries', fn, 'addBidResponse'); + beforeEach(() => { fakeCurrencyFileServer = sinon.fakeServer.create(); }); diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 07439be126c..f7895efa2f2 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -4,7 +4,6 @@ import parse from 'url-parse'; import buildDfpVideoUrl from 'modules/dfpAdServerVideo'; import { parseQS } from 'src/url'; import adUnit from 'test/fixtures/video/adUnit'; -import { newConfig } from 'src/config'; const bid = { videoCacheKey: 'abc', @@ -131,9 +130,6 @@ describe('The DFP video support module', () => { }); it('should not overwrite an existing description_url for object input and cache disabled', () => { - const config = newConfig(); - config.setConfig({ usePrebidCache: true }); - const bidCopy = Object.assign({}, bid); bidCopy.vastUrl = 'vastUrl.example'; diff --git a/test/spec/modules/districtmDMXBidAdapter_spec.js b/test/spec/modules/districtmDMXBidAdapter_spec.js deleted file mode 100644 index 6fc83d88e6d..00000000000 --- a/test/spec/modules/districtmDMXBidAdapter_spec.js +++ /dev/null @@ -1,245 +0,0 @@ -/** - * Created by stevealliance on 2016-11-15. - */ - -import {expect} from 'chai'; -import {should} from 'chai'; -import Adaptor from '../../../modules/districtmDMXBidAdapter'; - -import adLoader from '../../../src/adloader'; - -var _each = function(obj, fn) { - for (var o in obj) { - fn(o, obj[o]); - } -} - -let districtm; -const PREBID_RESPONSE = function() { - return { - result: { - cpm: '3.45', - callbackId: '1490bd6bdc59ce', - width: 300, - height: 250, - banner: 'html' - }, - callback_uid: '1490bd6bdc59ce' - }; -} -const PREBID_PARAMS = { - bidderCode: 'districtmDMX', - requestId: '5ccedbd5-86c1-436f-8649-964262461eac', - bidderRequestId: '1490bd6bdc59ce', - start: new Date().getTime(), - bids: [{ - bidder: 'districtmDMX', - bidId: '84ab500420319d', - bidderRequestId: '1490bd6bdc59ce', - requestId: '5ccedbd5-86c1-436f-8649-964262461eac', - placementCode: 'golden', - params: { - placement: 109801, - floor: '1.00' - }, - sizes: [[300, 250], [300, 600]] - }] -}; - -function resetDm() { - window.hb_dmx_res = undefined; -} - -function activated() { - window.hb_dmx_res = { - ssp: {}, - bh() { - - }, - auction: { - fixSize(s) { - let size; - if (!Array.isArray(s[0])) { - size = [s[0] + 'x' + s[1]]; - } else { - size = s.map(ss => { - return ss[0] + 'x' + ss[1]; - }) - } - - return size; - }, - - run(a, b, c) { - - } - } - } -} - -function definitions() { - districtm.callBids({ - bidderCode: 'districtmDMX', - bids: [ - { - bidder: 'districtmDMX', - adUnitCode: 'golden', - sizes: [[728, 90]], - params: { - siteId: '101000' - } - }, - { - bidder: 'districtmDMX', - adUnitCode: 'stevealliance', - sizes: [[300, 250]], - params: { - siteId: '101000' - } - } - ] - }); -} -describe('DistrictM adapter test', () => { - describe('File loading', () => { - let districtm; - afterEach(() => { - districtm = new Adaptor(); - adLoader.loadScript(districtm.districtUrl, function() {}); - }) - - it('For loading file ', () => { - expect(!window.hb_dmx_res).to.equal(true); - }) - }) - - describe('check for library do exists', () => { - it('library was not loaded', () => { - expect(!window.hb_dmx_res).to.equal(true); - }) - - it('library is now available', () => { - activated(); - - expect(!!window.hb_dmx_res).to.equal(true); - }) - }) - - describe('Check if size get clean', () => { - beforeEach(() => { - activated(); - }) - it('size clean up using fixe size', () => { - activated(); - - expect(window.hb_dmx_res.auction.fixSize([728, 90])[0]).to.equal(['728x90'][0]); - expect(window.hb_dmx_res.auction.fixSize([[300, 250], [300, 600]]).toString()).to.equal(['300x250', '300x600'].toString()); - }) - }) - - describe('Check call bids return no errors', () => { - let districtm; - beforeEach(() => { - districtm = new Adaptor(); - }); - it('check value push using cal bids', () => { - let obj = districtm.callBids(PREBID_PARAMS); - obj.should.have.property('bidderCode'); - obj.should.have.property('requestId'); - obj.should.have.property('bidderRequestId'); - obj.should.have.property('start'); - obj.should.have.property('bids'); - }) - it('check if value got pass correctly for DM params', () => { - let dm = districtm.callBids(PREBID_PARAMS).bids.map(bid => bid); - dm.forEach(a => { - a.should.have.property('bidder'); - a.should.have.property('requestId'); - a.should.have.property('bidderRequestId'); - a.should.have.property('placementCode'); - a.should.have.property('params'); - a.should.have.property('sizes'); - expect(a.bidder).to.equal('districtmDMX'); - expect(a.placementCode).to.equal('golden'); - expect(a.params.placement).to.equal(109801); - }) - }) - }) - - describe('Run prebid definitions !', () => { - let districtm; - beforeEach(() => { - districtm = new Adaptor(); - }) - - it('Run and return send bids', () => { - let sendBids = districtm.sendBids(PREBID_PARAMS); - sendBids.forEach(sb => { - expect(sb.sizes.toString()).to.equal([[300, 250], [300, 600]].toString()); - }) - }) - }) - - describe('HandlerRes function test', () => { - let districtm; - - beforeEach(() => { - districtm = new Adaptor(); - }) - - it('it\'s now time to play with the response ...', () => { - let result = districtm.handlerRes(PREBID_RESPONSE(), PREBID_PARAMS); - _each(result, function(k, v) { - - }) - - expect(result.cpm).to.equal('3.45'); - expect(result.width).to.equal(300); - expect(result.height).to.equal(250); - expect(result.ad).to.equal('html'); - }) - it('it\'s now time to play with the response failure...', () => { - let result = districtm.handlerRes({result: {cpm: 0}}, PREBID_PARAMS); - - result.should.have.property('bidderCode'); - }) - }) - - describe('look at the adloader', () => { - let districtm; - beforeEach(() => { - districtm = new Adaptor(); - sinon.stub(adLoader, 'loadScript'); - }) - - it('Verify districtm library is downloaded if nessesary', () => { - resetDm(); - districtm.callBids(PREBID_PARAMS); - let libraryLoadCall = adLoader.loadScript.firstCall.args[0]; - let callback = adLoader.loadScript.firstCall.args[1]; - expect(libraryLoadCall).to.equal('http://prebid.districtm.ca/lib.js'); - expect(callback).to.be.a('function'); - }); - - afterEach(() => { - adLoader.loadScript.restore(); - }) - }); - describe('run send bid from within !!!', () => { - beforeEach(() => { - districtm = new Adaptor(); - sinon.stub(districtm, 'sendBids'); - }) - - it('last test on send bids', () => { - resetDm(); - districtm.sendBids(PREBID_PARAMS); - expect(districtm.sendBids.calledOnce).to.be.true; - expect(districtm.sendBids.firstCall.args[0]).to.be.a('object'); - }); - - afterEach(() => { - districtm.sendBids.restore(); - }) - }); -}); diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js deleted file mode 100644 index bf09f42f6e7..00000000000 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ /dev/null @@ -1,112 +0,0 @@ -describe('eplanning adapter tests', function () { - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - var adapter = require('modules/eplanningBidAdapter'); - var adLoader = require('src/adloader'); - var expect = require('chai').expect; - var bidmanager = require('src/bidmanager'); - var CONSTANTS = require('src/constants.json'); - - var DEFAULT_PARAMS = { - bidderCode: 'eplanning', - bids: [{ - code: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300, 200]], - bidder: 'eplanning', - params: { - ci: '18f66' - } - }] - }; - - var PARAMS_SERVER_TEST = { - bidderCode: 'eplanning', - bids: [{ - code: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300, 600]], - bidder: 'eplanning', - params: { - ci: '18f66', - t: '1' - } - }] - }; - - var RESPONSE_AD = { - bids: [{ - placementCode: 'div-gpt-ad-1460505748561-0', - ad: { - ad: '

test ad

', - cpm: 1, - width: 300, - height: 250 - } - }] - }; - - var RESPONSE_EMPTY = { - bids: [{ - placementCode: 'div-gpt-ad-1460505748561-0' - }] - }; - - var stubAddBidResponse; - - describe('eplanning tests', function() { - beforeEach(function() { - stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - afterEach(function() { - stubAddBidResponse.restore(); - }); - - it('callback function should exist', function() { - expect($$PREBID_GLOBAL$$.processEPlanningResponse).to.exist.and.to.be.a('function'); - }); - - it('creates a bid response if bid exists', function() { - adapter().callBids(DEFAULT_PARAMS); - $$PREBID_GLOBAL$$.processEPlanningResponse(RESPONSE_AD); - - var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidObject = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode).to.equal('div-gpt-ad-1460505748561-0'); - expect(bidObject.cpm).to.equal(1); - expect(bidObject.ad).to.equal('

test ad

'); - expect(bidObject.width).to.equal(300); - expect(bidObject.height).to.equal(250); - expect(bidObject.getStatusCode()).to.equal(1); - expect(bidObject.bidderCode).to.equal('eplanning'); - }); - - it('creates an empty bid response if there is no bid', function() { - adapter().callBids(DEFAULT_PARAMS); - $$PREBID_GLOBAL$$.processEPlanningResponse(RESPONSE_EMPTY); - - var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidObject = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode).to.equal('div-gpt-ad-1460505748561-0'); - expect(bidObject.getStatusCode()).to.equal(2); - expect(bidObject.bidderCode).to.equal('eplanning'); - }); - - it('creates a bid response and sync users register ad', function() { - adapter().callBids(DEFAULT_PARAMS); - window.hbpb.rH({ - 'sI': { 'k': '18f66' }, - 'sec': { 'k': 'ROS' }, - 'sp': [ { 'k': 'div-gpt-ad-1460505748561-0', 'a': [{ 'w': 300, 'h': 250, 'adm': '

test ad

', 'pr': 1 }] } ], - 'cs': [ - '//test.gif', - { 'j': true, u: '//test.js' }, - { 'ifr': true, u: '//test.html', data: { 'test': 1 } } - ] - }); - var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidObject = stubAddBidResponse.getCall(0).args[1]; - expect(bidObject.getStatusCode()).to.equal(2); - }); - }); -}); diff --git a/test/spec/modules/essensBidAdapter_spec.js b/test/spec/modules/essensBidAdapter_spec.js deleted file mode 100644 index aad3d15b0a9..00000000000 --- a/test/spec/modules/essensBidAdapter_spec.js +++ /dev/null @@ -1,828 +0,0 @@ -import { expect } from 'chai' -import Adapter from 'modules/essensBidAdapter' -import bidmanager from 'src/bidmanager' -import adLoader from 'src/adloader' -describe('Essens adapter tests', function () { - describe('Test callbid method ', function () { - let stubLoadScript - beforeEach(() => { - stubLoadScript = sinon.stub(adLoader, 'loadScript') - }) - - afterEach(() => - stubLoadScript.restore() - ) - - it('bid request without bid', () => { - const essensAdapter = new Adapter() - essensAdapter.callBids() - sinon.assert.notCalled(stubLoadScript) - }) - - it('bid request with missing parameter', () => { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1' - } - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - sinon.assert.notCalled(stubLoadScript) - }) - - it('Bid request with wrong parameter', () => { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT1', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - randomParam: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - sinon.assert.notCalled(stubLoadScript) - }) - - it('add one valid requests', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT1', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - const url = stubLoadScript.getCall(0).args[0] - const payload = decodeURIComponent(url.split('&bid=')[1]) - const payloadJson = JSON.parse(payload) - - expect(payloadJson.ua).to.exist.and.to.be.a('string') - expect(payloadJson.url).to.exist.and.to.be.a('string') - expect(Object.keys(payloadJson.imp).length).to.equal(1) - expect(payloadJson.imp[0].impressionId).to.equal('placement1-for_essensT1') - expect(payloadJson.imp[0].placementId).to.equal('placement1') - expect(Object.keys(payloadJson.imp[0].sizes).length).to.equal(2) - expect(payloadJson.imp[0].sizes[0]).to.equal('100x110') - expect(payloadJson.imp[0].sizes[1]).to.equal('200x210') - sinon.assert.calledOnce(stubLoadScript) - }) - it('add more than one valid requests', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT2', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'placement2-for_essensT2', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [300, 310], - [400, 410] - ], - placementCode: 'div-media1-side_banner-1', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'placement3-for_essensT2', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement3' - }, - sizes: [ - [500, 510], - [600, 610] - ], - placementCode: 'div-media1-side_banner-2', - bidderRequestId: 'impression-for-essens-1', - }, - ] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - const url = stubLoadScript.getCall(0).args[0] - const payload = decodeURIComponent(url.split('&bid=')[1]) - const payloadJson = JSON.parse(payload) - - expect(payloadJson.ua).to.exist.and.to.be.a('string') - expect(payloadJson.url).to.exist.and.to.be.a('string') - expect(Object.keys(payloadJson.imp).length).to.equal(3) - expect(payloadJson.imp[0].impressionId).to.equal('placement1-for_essensT2') - expect(payloadJson.imp[0].placementId).to.equal('placement1') - expect(Object.keys(payloadJson.imp[0].sizes).length).to.equal(2) - expect(payloadJson.imp[0].sizes[0]).to.equal('100x110') - expect(payloadJson.imp[0].sizes[1]).to.equal('200x210') - - expect(payloadJson.imp[1].impressionId).to.equal('placement2-for_essensT2') - expect(payloadJson.imp[1].placementId).to.equal('placement2') - expect(Object.keys(payloadJson.imp[1].sizes).length).to.equal(2) - expect(payloadJson.imp[1].sizes[0]).to.equal('300x310') - expect(payloadJson.imp[1].sizes[1]).to.equal('400x410') - - expect(payloadJson.imp[2].impressionId).to.equal('placement3-for_essensT2') - expect(payloadJson.imp[2].placementId).to.equal('placement3') - expect(Object.keys(payloadJson.imp[2].sizes).length).to.equal(2) - expect(payloadJson.imp[2].sizes[0]).to.equal('500x510') - expect(payloadJson.imp[2].sizes[1]).to.equal('600x610') - sinon.assert.calledOnce(stubLoadScript) - }) - it('should fill all parameters', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT3', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1', - dealId: '1234', - floorPrice: '23.478' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - const url = stubLoadScript.getCall(0).args[0] - const payload = decodeURIComponent(url.split('&bid=')[1]) - const payloadJson = JSON.parse(payload) - - expect(payloadJson.ua).to.exist.and.to.be.a('string') - expect(payloadJson.url).to.exist.and.to.be.a('string') - expect(Object.keys(payloadJson.imp).length).to.equal(1) - expect(payloadJson.imp[0].impressionId).to.equal('placement1-for_essensT3') - expect(payloadJson.imp[0].placementId).to.equal('placement1') - expect(Object.keys(payloadJson.imp[0].sizes).length).to.equal(2) - expect(payloadJson.imp[0].sizes[0]).to.equal('100x110') - expect(payloadJson.imp[0].sizes[1]).to.equal('200x210') - expect(payloadJson.imp[0].deal).to.equal('1234') - expect(payloadJson.imp[0].floorPrice).to.equal('23.478') - }) - it('invalid request: missing mandatory parameters', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT4', - bidder: 'essens', - requestId: 'essens-impression-1', - params: {}, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - sinon.assert.notCalled(stubLoadScript) - }) - }) - - describe('Test essensResponseHandler method', function () { - let stubAddBidResponse - beforeEach(() => { - stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse') - }) - - afterEach(() => { - stubAddBidResponse.restore() - }) - - it('Check method exist', function () { - expect($$PREBID_GLOBAL$$.essensResponseHandler).to.exist.and.to.be.a('function') - }) - - it('Check invalid response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': '1234' - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - const bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - const bidObject1 = stubAddBidResponse.getCall(0).args[1] - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T1') - expect(bidObject1.getStatusCode()).to.equal(2) - expect(bidObject1.bidderCode).to.equal('essens') - - sinon.assert.calledOnce(stubAddBidResponse) - }) - - it('Check empty response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T2', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'placement2-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-side_banner-1T2', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'placement3-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement3' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-side_banner-2T2', - bidderRequestId: 'impression-for-essens-1', - }, - ] - } - - const response = { - 'id': '1234', - 'seatbid': [] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - const bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - const bidObject1 = stubAddBidResponse.getCall(0).args[1] - const bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0] - const bidObject2 = stubAddBidResponse.getCall(1).args[1] - const bidPlacementCode3 = stubAddBidResponse.getCall(2).args[0] - const bidObject3 = stubAddBidResponse.getCall(2).args[1] - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T2') - expect(bidObject1.getStatusCode()).to.equal(2) - expect(bidObject1.bidderCode).to.equal('essens') - - expect(bidPlacementCode2).to.equal('div-media1-side_banner-1T2') - expect(bidObject2.getStatusCode()).to.equal(2) - expect(bidObject2.bidderCode).to.equal('essens') - - expect(bidPlacementCode3).to.equal('div-media1-side_banner-2T2') - expect(bidObject3.getStatusCode()).to.equal(2) - expect(bidObject3.bidderCode).to.equal('essens') - - sinon.assert.calledThrice(stubAddBidResponse) - }) - - it('Check valid response but invalid bid ', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T3', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'bid-on-placement2-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [300, 310], - [400, 410] - ], - placementCode: 'div-media1-side_banner-1T3', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement1-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 100, - 'w': 110 - // ,'ext': { - // 'adUrl': 'creative-link2' - // } - }, - { - 'id': 'responseOnBid1', - // 'impid': 'bid-on-placement2-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 300, - 'w': 310, - 'ext': { - 'adUrl': 'creative-link2' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - let bidPlacementCode1 - let bidPlacementCode2 - let bidObject1 - let bidObject2 - - if (stubAddBidResponse.getCall(0).args[0] === 'div-media1-top_banner-1T3') { - bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0] - bidObject1 = stubAddBidResponse.getCall(0).args[1] - bidObject2 = stubAddBidResponse.getCall(0).args[1] - } else { - bidPlacementCode1 = stubAddBidResponse.getCall(1).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(0).args[0] - bidObject1 = stubAddBidResponse.getCall(1).args[1] - bidObject2 = stubAddBidResponse.getCall(0).args[1] - } - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T3') - expect(bidObject1.getStatusCode()).to.equal(2) - expect(bidObject1.bidderCode).to.equal('essens') - - expect(bidPlacementCode2).to.equal('div-media1-side_banner-1T3') - expect(bidObject2.getStatusCode()).to.equal(2) - expect(bidObject2.bidderCode).to.equal('essens') - - sinon.assert.calledTwice(stubAddBidResponse) - }) - - it('Check single non empty minimal valid response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T3', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement1-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'h': 300, - 'w': 310, - 'ext': { - 'adUrl': 'creative-link' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - const bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - const bidObject1 = stubAddBidResponse.getCall(0).args[1] - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T3') - expect(bidObject1.getStatusCode()).to.equal(1) - expect(bidObject1.bidderCode).to.equal('essens') - expect(bidObject1.creative_id).to.equal('creativeId1') - expect(bidObject1.cpm).to.equal(9.01) - expect(bidObject1.height).to.equal(300) - expect(bidObject1.width).to.equal(310) - expect(bidObject1.adUrl).to.equal('creative-link') - expect(bidObject1.adId).to.equal('bid-on-placement1-for_essens') - - sinon.assert.calledOnce(stubAddBidResponse) - }) - - it('Check single non empty response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T3', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement1-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 300, - 'w': 310, - 'ext': { - 'adUrl': 'creative-link' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - const bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - const bidObject1 = stubAddBidResponse.getCall(0).args[1] - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T3') - expect(bidObject1.getStatusCode()).to.equal(1) - expect(bidObject1.bidderCode).to.equal('essens') - expect(bidObject1.creative_id).to.equal('creativeId1') - expect(bidObject1.cpm).to.equal(9.01) - expect(bidObject1.height).to.equal(300) - expect(bidObject1.width).to.equal(310) - expect(bidObject1.adUrl).to.equal('creative-link') - expect(bidObject1.adId).to.equal('bid-on-placement1-for_essens') - expect(bidObject1.dealId).to.equal('dealId1') - - sinon.assert.calledOnce(stubAddBidResponse) - }) - - it('Check multiple non empty response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T4', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'bid-on-placement2-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [300, 310], - [400, 410] - ], - placementCode: 'div-media1-side_banner-1T4', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement1-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 100, - 'w': 110, - 'ext': { - 'adUrl': 'creative-link1' - } - }, - { - 'id': 'responseOnBid2', - 'impid': 'bid-on-placement2-for_essens', - 'price': 9.02, - 'crid': 'creativeId2', - 'dealid': 'dealId2', - 'h': 400, - 'w': 410, - 'ext': { - 'adUrl': 'creative-link2' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - let bidPlacementCode1 - let bidPlacementCode2 - let bidObject1 - let bidObject2 - - if (stubAddBidResponse.getCall(0).args[0] === 'div-media1-top_banner-1T4') { - bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0] - bidObject1 = stubAddBidResponse.getCall(0).args[1] - bidObject2 = stubAddBidResponse.getCall(1).args[1] - } else { - bidPlacementCode1 = stubAddBidResponse.getCall(1).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(0).args[0] - bidObject1 = stubAddBidResponse.getCall(1).args[1] - bidObject2 = stubAddBidResponse.getCall(0).args[1] - } - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T4') - expect(bidObject1.getStatusCode()).to.equal(1) - expect(bidObject1.bidderCode).to.equal('essens') - expect(bidObject1.creative_id).to.equal('creativeId1') - expect(bidObject1.cpm).to.equal(9.01) - expect(bidObject1.height).to.equal(100) - expect(bidObject1.width).to.equal(110) - expect(bidObject1.adUrl).to.equal('creative-link1') - expect(bidObject1.adId).to.equal('bid-on-placement1-for_essens') - expect(bidObject1.dealId).to.equal('dealId1') - - expect(bidPlacementCode2).to.equal('div-media1-side_banner-1T4') - expect(bidObject2.getStatusCode()).to.equal(1) - expect(bidObject2.bidderCode).to.equal('essens') - expect(bidObject2.creative_id).to.equal('creativeId2') - expect(bidObject2.cpm).to.equal(9.02) - expect(bidObject2.height).to.equal(400) - expect(bidObject2.width).to.equal(410) - expect(bidObject2.adUrl).to.equal('creative-link2') - expect(bidObject2.adId).to.equal('bid-on-placement2-for_essens') - expect(bidObject2.dealId).to.equal('dealId2') - - sinon.assert.calledTwice(stubAddBidResponse) - }) - - it('Check empty and non empty mixed response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T5', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'bid-on-placement2-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [300, 310], - [400, 410] - ], - placementCode: 'div-media1-side_banner-1T5', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement2-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 500, - 'w': 510, - 'ext': { - 'adUrl': 'creative-link' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - let bidPlacementCode1 - let bidPlacementCode2 - let bidObject1 - let bidObject2 - - if (stubAddBidResponse.getCall(0).args[0] === 'div-media1-side_banner-1T5') { - bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0] - bidObject1 = stubAddBidResponse.getCall(0).args[1] - bidObject2 = stubAddBidResponse.getCall(1).args[1] - } else { - bidPlacementCode1 = stubAddBidResponse.getCall(1).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(0).args[0] - bidObject1 = stubAddBidResponse.getCall(1).args[1] - bidObject2 = stubAddBidResponse.getCall(0).args[1] - } - - expect(bidPlacementCode1).to.equal('div-media1-side_banner-1T5') - expect(bidObject1.getStatusCode()).to.equal(1) - expect(bidObject1.bidderCode).to.equal('essens') - expect(bidObject1.creative_id).to.equal('creativeId1') - expect(bidObject1.cpm).to.equal(9.01) - expect(bidObject1.height).to.equal(500) - expect(bidObject1.width).to.equal(510) - expect(bidObject1.adUrl).to.equal('creative-link') - expect(bidObject1.adId).to.equal('bid-on-placement2-for_essens') - expect(bidObject1.dealId).to.equal('dealId1') - - expect(bidPlacementCode2).to.equal('div-media1-top_banner-1T5') - expect(bidObject2.getStatusCode()).to.equal(2) - expect(bidObject2.bidderCode).to.equal('essens') - - sinon.assert.calledTwice(stubAddBidResponse) - }) - }) -}) diff --git a/test/spec/modules/featureforwardBidAdapter_spec.js b/test/spec/modules/featureforwardBidAdapter_spec.js deleted file mode 100644 index 9c6b91d5a36..00000000000 --- a/test/spec/modules/featureforwardBidAdapter_spec.js +++ /dev/null @@ -1,87 +0,0 @@ -import {expect} from 'chai'; -import FeatureForwardAdapter from 'modules/featureforwardBidAdapter'; -import bidManager from 'src/bidmanager'; -import * as ajax from 'src/ajax'; -import {parse as parseURL} from 'src/url'; - -describe('FeatureForward Adapter Tests', () => { - let featureForwardAdapter = new FeatureForwardAdapter(); - let slotConfigs; - let ajaxStub; - beforeEach(() => { - sinon.stub(bidManager, 'addBidResponse'); - ajaxStub = sinon.stub(ajax, 'ajax'); - slotConfigs = { - bids: [ - { - sizes: [[300, 250]], - bidder: 'featureforward', - placementCode: 'test1_placement', - params: { - pubId: '001', - siteId: '111', - placementId: '1', - } - }] - }; - }); - - afterEach(() => { - bidManager.addBidResponse.restore(); - ajaxStub.restore(); - }); - - it('Verify requests sent to FeatureForward', () => { - featureForwardAdapter.callBids(slotConfigs); - var call = ajaxStub.firstCall.args[0]; - var request = JSON.parse(ajaxStub.args[0][2]); - var creds = ajaxStub.args[0][3]; - expect(call).to.equal('http://prmbdr.featureforward.com/newbidder/bidder1_prm.php?'); - expect(request.ca).to.equal('BID'); - expect(request.pubId).to.equal('001'); - expect(request.siteId).to.equal('111'); - expect(request.placementId).to.equal('1'); - expect(request.size[0]).to.equal(300); - expect(request.size[1]).to.equal(250); - expect(creds.method).to.equal('POST'); - }); - - it('Verify bid', () => { - featureForwardAdapter.callBids(slotConfigs); - ajaxStub.firstCall.args[1](JSON.stringify({ - html: 'FF Test Ad', - bidCpm: 0.555, - width: 300, - height: 250 - })); - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(bid.bidderCode).to.equal('featureforward'); - expect(bid.cpm).to.equal(0.555); - expect(bid.ad).to.equal('FF Test Ad'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - }); - - it('Verify passback', () => { - featureForwardAdapter.callBids(slotConfigs); - // trigger a mock ajax callback with no bid. - ajaxStub.firstCall.args[1](null); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(placement).to.equal('test1_placement'); - expect(bid.bidderCode).to.equal('featureforward'); - expect(bid).to.not.have.property('ad'); - expect(bid).to.not.have.property('cpm'); - }); - - it('Verify passback when ajax call fails', () => { - ajaxStub.throws(); - featureForwardAdapter.callBids(slotConfigs); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(placement).to.equal('test1_placement'); - expect(bid.bidderCode).to.equal('featureforward'); - expect(bid).to.not.have.property('ad'); - expect(bid).to.not.have.property('cpm'); - }); -}); diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js deleted file mode 100644 index b90a1a48b15..00000000000 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ /dev/null @@ -1,295 +0,0 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/gumgumBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; -import * as utils from '../../../src/utils'; -import { STATUS } from '../../../src/constants'; - -describe('gumgum adapter', () => { - 'use strict'; - - let adapter; - let sandbox; - - const TEST = { - PUBLISHER_IDENTITY: 'ggumtest', - BIDDER_CODE: 'gumgum', - PLACEMENT: 'placementId', - CPM: 2 - }; - const bidderRequest = { - bidderCode: TEST.BIDDER_CODE, - bids: [{ // in-screen - bidId: 'InScreenBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ], - params: { - inScreen: TEST.PUBLISHER_IDENTITY - } - }, { // in-image - bidId: 'InImageBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ], - params: { - inImage: TEST.PUBLISHER_IDENTITY - } - }, { // native - bidId: 'NativeBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ], - params: { - native: 10 - } - }, { // slot - bidId: 'InSlotBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ], - params: { - inSlot: 10 - } - }, { // no identity - bidId: 'NoIdentityBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ] - }] - }; - const pageParams = { - 'pvid': 'PVID' - }; - const bidderResponse = { - 'ad': { - 'id': 1, - 'width': 728, - 'height': 90, - 'markup': '
some fancy ad
', - 'ii': true, - 'du': 'http://example.com/', - 'price': TEST.CPM, - 'impurl': 'http://example.com/' - }, - 'pag': pageParams - }; - - function mockBidResponse(response) { - sandbox.stub(bidManager, 'addBidResponse'); - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - $$PREBID_GLOBAL$$.handleGumGumCB['InScreenBidId'](response); - return bidManager.addBidResponse.firstCall.args[1]; - } - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('DigiTrust params', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - }); - - it('should send digiTrust params', () => { - window.DigiTrust = { - getUser: function() {} - }; - sandbox.stub(window.DigiTrust, 'getUser', () => - ({ - success: true, - identity: { - privacy: {optout: false}, - id: 'testId' - } - }) - ); - - adapter.callBids(bidderRequest); - expect(adLoader.loadScript.firstCall.args[0]).to.include('&dt=testId'); - delete window.DigiTrust; - }); - - it('should not send DigiTrust params when DigiTrust is not loaded', () => { - adapter.callBids(bidderRequest); - expect(adLoader.loadScript.firstCall.args[0]).to.not.include('&dt'); - }); - - it('should not send DigiTrust params due to opt out', () => { - window.DigiTrust = { - getUser: function() {} - }; - sandbox.stub(window.DigiTrust, 'getUser', () => - ({ - success: true, - identity: { - privacy: {optout: true}, - id: 'testId' - } - }) - ); - - adapter.callBids(bidderRequest); - expect(adLoader.loadScript.firstCall.args[0]).to.not.include('&dt'); - delete window.DigiTrust; - }); - - it('should not send DigiTrust params on failure', () => { - window.DigiTrust = { - getUser: function() {} - }; - sandbox.stub(window.DigiTrust, 'getUser', () => - ({ - success: false, - identity: { - privacy: {optout: false}, - id: 'testId' - } - }) - ); - - adapter.callBids(bidderRequest); - expect(adLoader.loadScript.firstCall.args[0]).to.not.include('&dt'); - delete window.DigiTrust; - }); - }); - - describe('callBids', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - }); - - it('calls the endpoint once per valid bid', () => { - sinon.assert.callCount(adLoader.loadScript, 4); - }); - - it('includes required browser data', () => { - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include('vw'); - endpointRequest.to.include('vh'); - endpointRequest.to.include('sw'); - endpointRequest.to.include('sh'); - }); - - it('includes the global bid timeout', () => { - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include(`tmax=${$$PREBID_GLOBAL$$.cbTimeout}`); - }); - - it('includes the publisher identity', () => { - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include('t=' + TEST.PUBLISHER_IDENTITY); - }); - - it('first call should be in-screen', () => { - expect(adLoader.loadScript.firstCall.args[0]).to.include('pi=2'); - }); - - it('second call should be in-image', () => { - expect(adLoader.loadScript.secondCall.args[0]).to.include('pi=1'); - }); - - it('third call should be native', () => { - expect(adLoader.loadScript.thirdCall.args[0]).to.include('pi=5'); - }); - - it('last call should be slot', () => { - expect(adLoader.loadScript.lastCall.args[0]).to.include('pi=3'); - }); - }); - - describe('handleGumGumCB[...]', () => { - it('exists and is function', () => { - expect($$PREBID_GLOBAL$$.handleGumGumCB['InScreenBidId']).to.exist.and.to.be.a('function'); - }); - }); - - describe('respond with a successful bid', () => { - let successfulBid; - - beforeEach(() => { - successfulBid = mockBidResponse(bidderResponse); - }); - - it('adds one bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('passes the correct placement code as the first param', () => { - const [ placementCode ] = bidManager.addBidResponse.firstCall.args; - expect(placementCode).to.eql(TEST.PLACEMENT); - }); - - it('has a GOOD status code', () => { - const STATUS_CODE = successfulBid.getStatusCode(); - expect(STATUS_CODE).to.eql(STATUS.GOOD); - }); - - it('uses the CPM returned by the server', () => { - expect(successfulBid).to.have.property('cpm', TEST.CPM); - }); - - it('has an ad', () => { - expect(successfulBid).to.have.property('ad'); - }); - - it('has the size specified by the server', () => { - expect(successfulBid).to.have.property('width', 728); - expect(successfulBid).to.have.property('height', 90); - }); - }); - - describe('respond with an empty bid', () => { - let noBid; - - beforeEach(() => { - noBid = mockBidResponse(undefined); - }); - - it('adds one bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('has a NO_BID status code', () => { - expect(noBid.getStatusCode()).to.eql(STATUS.NO_BID); - }); - - it('passes the correct placement code as the first parameter', () => { - const [ placementCode ] = bidManager.addBidResponse.firstCall.args; - expect(placementCode).to.eql(TEST.PLACEMENT); - }); - - it('adds the bidder code to the bid object', () => { - expect(noBid).to.have.property('bidderCode', TEST.BIDDER_CODE); - }); - }); - - describe('refresh throttle', () => { - beforeEach(() => { - mockBidResponse(bidderResponse); - }); - - afterEach(() => { - if (utils.logWarn.restore) { - utils.logWarn.restore(); - } - }); - - it('warns about the throttle limit', function() { - sinon.spy(utils, 'logWarn'); - // call all the binds again - adapter.callBids(bidderRequest); - // the timeout for in-screen should stop one bid request - const warning = expect(utils.logWarn.args[0][0]); - warning.to.include(TEST.PLACEMENT); - warning.to.include('inScreen'); - }); - }); -}); diff --git a/test/spec/modules/hiromediaBidAdapter_spec.js b/test/spec/modules/hiromediaBidAdapter_spec.js deleted file mode 100644 index c1ed4ee6e11..00000000000 --- a/test/spec/modules/hiromediaBidAdapter_spec.js +++ /dev/null @@ -1,331 +0,0 @@ -import { expect } from 'chai'; -import urlParse from 'url-parse'; - -import Adapter from 'modules/hiromediaBidAdapter'; -import bidmanager from 'src/bidmanager'; -import { STATUS } from 'src/constants'; -import * as utils from 'src/utils'; - -describe('hiromedia adapter', function () { - const BIDDER_CODE = 'hiromedia'; - const DEFAULT_ENDPOINT = 'https://hb-rtb.ktdpublishers.com/bid/get'; - - let adapter; - let sandbox; - let xhr; - let addBidResponseStub; - let hasValidBidRequestSpy; - let placementId = 0; - - window.$$PREBID_GLOBAL$$ = window.$$PREBID_GLOBAL$$ || {}; - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - - // Used to spy on bid requests - xhr = sandbox.useFakeXMLHttpRequest(); - - // Used to spy on bid responses - addBidResponseStub = sandbox.stub(bidmanager, 'addBidResponse'); - - // Used to spy on bid validation - hasValidBidRequestSpy = sandbox.spy(utils, 'hasValidBidRequest'); - - placementId = 0; - }); - - afterEach(() => { - sandbox.restore(); - }); - - // Helper function that asserts that no bidding activity (requests nor responses) - // was made during a test. - const assertNoBids = () => { - expect(xhr.requests.length).to.be.equal(0); - sinon.assert.notCalled(addBidResponseStub); - }; - - // Helper function to generate a 'mock' bid object - const makePlacement = (size) => { - placementId += 1; - - return { - bidder: BIDDER_CODE, - sizes: [size], - params: { - accountId: '1337' - }, - placementCode: 'div-gpt-ad-12345-' + placementId - }; - }; - - // 300x250 are in the allowed size by default - const tilePlacement = () => makePlacement([300, 250]); - - // anything else should have no bid by default - const leaderPlacement = () => makePlacement([728, 90]); - - describe('callbids', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - it('tolerates empty arguments', () => { - expect(adapter.callBids).to.not.throw(Error); - assertNoBids(); - }); - - it('tolerates empty params', () => { - expect(adapter.callBids.bind(adapter, {})).to.not.throw(Error); - assertNoBids(); - }); - - it('tolerates empty bids', () => { - expect(adapter.callBids.bind(adapter, {bids: []})).to.not.throw(Error); - assertNoBids(); - }); - - it('invokes a bid request per placement', () => { - const expectedRequests = [{ - placementCode: 'div-gpt-ad-12345-1', - selectedSize: '300x250' - }, { - placementCode: 'div-gpt-ad-12345-2', - selectedSize: '728x90' - }, { - placementCode: 'div-gpt-ad-12345-3', - selectedSize: '300x250' - }]; - - const params = { - bids: [tilePlacement(), leaderPlacement(), tilePlacement()] - }; - - adapter.callBids(params); - expect(xhr.requests.length).to.equal(3); - sinon.assert.notCalled(addBidResponseStub); - sinon.assert.calledThrice(hasValidBidRequestSpy); - - expectedRequests.forEach(function(request, index) { - expect(hasValidBidRequestSpy.returnValues[index]).to.be.equal(true); - - // validate request - const bidRequest = xhr.requests[index].url; - const defaultBidUrl = urlParse(DEFAULT_ENDPOINT); - const bidUrl = urlParse(bidRequest, true); - const query = bidUrl.query; - - expect(bidUrl.hostname).to.equal(defaultBidUrl.hostname); - expect(bidUrl.pathname).to.equal(defaultBidUrl.pathname); - - expect(query).to.have.property('adapterVersion').and.to.equal('3'); - expect(query).to.have.property('placementCode').and.to.equal(request.placementCode); - expect(query).to.have.property('accountId').and.to.equal('1337'); - expect(query).to.have.property('selectedSize').and.to.equal(request.selectedSize); - expect(query).to.not.have.property('additionalSizes'); - expect(query).to.have.property('domain').and.to.equal(window.top.location.hostname); - }); - }); - - // Test additionalSizes parameter - it('attaches multiple sizes to additionalSizes', () => { - const placement = tilePlacement(); - - // Append additional - placement.sizes.push([300, 600]); - placement.sizes.push([300, 900]); - - const params = { - bids: [placement] - }; - - adapter.callBids(params); - expect(xhr.requests.length).to.be.equal(1); - - const bidRequest = xhr.requests[0].url; - const bidUrl = urlParse(bidRequest, true); - const query = bidUrl.query; - - expect(query).to.have.property('selectedSize').and.to.equal('300x250'); - expect(query).to.have.property('additionalSizes').and.to.equal('300x600,300x900'); - }); - - // Test `params.accountId` validation - it('invalidates bids with no id', () => { - const placement = tilePlacement(); - delete placement.params; - - const params = { - bids: [placement] - }; - - adapter.callBids(params); - expect(xhr.requests.length).to.be.equal(0); - sinon.assert.calledOnce(hasValidBidRequestSpy); - sinon.assert.calledOnce(addBidResponseStub); - - expect(hasValidBidRequestSpy.returnValues[0]).to.be.equal(false); - const placementCode = addBidResponseStub.getCall(0).args[0]; - const bidObject = addBidResponseStub.getCall(0).args[1]; - - expect(placementCode).to.be.equal('div-gpt-ad-12345-1'); - expect(bidObject.getStatusCode()).to.be.equal(STATUS.NO_BID); - }); - - // Test `params.bidUrl` - it('accepts a custom bid endpoint url', () => { - const placement = tilePlacement(); - placement.params.bidUrl = DEFAULT_ENDPOINT + '?someparam=value'; - - const params = { - bids: [placement] - }; - - adapter.callBids(params); - expect(xhr.requests.length).to.be.equal(1); - - const bidRequest = xhr.requests[0].url; - const defaultBidUrl = urlParse(DEFAULT_ENDPOINT); - const bidUrl = urlParse(bidRequest, true); - const query = bidUrl.query; - - expect(bidUrl.hostname).to.equal(defaultBidUrl.hostname); - expect(bidUrl.pathname).to.equal(defaultBidUrl.pathname); - - expect(query).to.have.property('someparam').and.to.equal('value'); - }); - }); - - describe('response handler', () => { - let server; - - beforeEach(() => { - server = sandbox.useFakeServer(); - }); - - const assertSingleFailedBidResponse = () => { - sinon.assert.calledOnce(addBidResponseStub); - const placementCode = addBidResponseStub.getCall(0).args[0]; - const bidObject = addBidResponseStub.getCall(0).args[1]; - - expect(placementCode).to.be.equal('div-gpt-ad-12345-1'); - expect(bidObject.getStatusCode()).to.be.equal(STATUS.NO_BID); - }; - - it('tolerates an empty response', () => { - server.respondWith(''); - adapter.callBids({bids: [tilePlacement()]}); - server.respond(); - - assertSingleFailedBidResponse(); - }); - - it('tolerates a response error', () => { - server.respondWith([500, {}, '']); - adapter.callBids({bids: [tilePlacement()]}); - server.respond(); - - assertSingleFailedBidResponse(); - }); - - it('tolerates an invalid response', () => { - server.respondWith('not json'); - adapter.callBids({bids: [tilePlacement()]}); - server.respond(); - - assertSingleFailedBidResponse(); - }); - - it('adds a bid reponse for each pending bid', () => { - const responses = [{ - width: '300', - height: '250', - cpm: 0.4, - ad: '' - }, { - width: '728', - height: '90', - cpm: 0.4, - ad: '' - }]; - - let id = 0; - server.respondWith((request) => { - request.respond(200, {}, JSON.stringify(responses[id])); - id += 1; - }); - - const params = { - bids: [tilePlacement(), leaderPlacement()] - }; - - adapter.callBids(params); - server.respond(); - - expect(server.requests.length).to.be.equal(2); - sinon.assert.calledTwice(addBidResponseStub); - - responses.forEach((expectedResponse, i) => { - const placementCode = addBidResponseStub.getCall(i).args[0]; - const bidObject = addBidResponseStub.getCall(i).args[1]; - - expect(placementCode).to.be.equal('div-gpt-ad-12345-' + (i + 1)); - - expect(bidObject.getStatusCode()).to.be.equal(STATUS.GOOD); - expect(bidObject).to.have.property('cpm').and.to.equal(expectedResponse.cpm); - expect(bidObject).to.have.property('ad').and.to.equal(expectedResponse.ad); - expect(bidObject).to.have.property('width').and.to.equal(expectedResponse.width); - expect(bidObject).to.have.property('height').and.to.equal(expectedResponse.height); - }); - }); - - // We want to check that responses are added according to a sampling value, - // this is possible by stubbing `Math.random`, to ensure the effect is - // limited to the area we check, we create a self destructing stub which - // restores itself once called. - it('adds responses according to the sampling defined in the response', () => { - const response = { - cpm: 0.4, - chance: 0.25, - ad: '' - }; - - // List of "random" values. We check that the first two pass and the last - // one is skipped. - const randomValues = [0.2, 0.3]; - let randomIndex = 0; - - server.respondWith((request) => { - const mathRandomStub = sandbox.stub(Math, 'random', function () { - const randomValue = randomValues[randomIndex]; - - randomIndex += 1; - mathRandomStub.restore(); // self destruct on call - - return randomValue; - }); - - request.respond(200, {}, JSON.stringify(response)); - - mathRandomStub.restore(); - }); - - const params = { - bids: [tilePlacement()] - }; - - adapter.callBids(params); - adapter.callBids(params); - server.respond(); - - sinon.assert.calledTwice(addBidResponseStub); - - const firstBidObject = addBidResponseStub.getCall(0).args[1]; - const secondBidObject = addBidResponseStub.getCall(1).args[1]; - - expect(firstBidObject.getStatusCode()).to.be.equal(STATUS.GOOD); - expect(secondBidObject.getStatusCode()).to.be.equal(STATUS.NO_BID); - }); - }); -}); diff --git a/test/spec/modules/imonomyBidAdapter_spec.js b/test/spec/modules/imonomyBidAdapter_spec.js deleted file mode 100644 index e27a0d69a60..00000000000 --- a/test/spec/modules/imonomyBidAdapter_spec.js +++ /dev/null @@ -1,109 +0,0 @@ -import Adapter from '../../../modules/imonomyBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import {expect} from 'chai'; -import adLoader from '../../../src/adloader'; - -var CONSTANTS = require('../../../src/constants'); - -describe('imonomy adapter test', () => { - var utils = require('src/utils'); - let adapter; - let stubAddBidResponse; - let sandbox; - - let validBid = { - bidderCode: 'imonomy', - bids: [ - { - bidder: 'imonomy', - placementCode: 'foo', - bidId: 'foo', - sizes: [[300, 250]], - params: { - publisher_id: '14567721164', - } - } - ] - }; - - let validResponse = { - ads: [ - { - impression_id: 'foo', - cpm: 1.12, - creative: '' - } - ] - }; - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - stubAddBidResponse.restore(); - sandbox.restore(); - }); - - describe('dealing with diffrent situations', () => { - let server; - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - stubAddBidResponse.restore(); - sandbox.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('no bid if cdb handler responds with no bid empty string response', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(validBid); - var callbackName = '_hb_' + stubGetUniqueIdentifierStr.returnValues[0] - $$PREBID_GLOBAL$$[callbackName]({}) - }); - - it('adds bid for valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.GOOD }); - done(); - }); - - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(validBid); - var callbackName = '_hb_' + stubGetUniqueIdentifierStr.returnValues[0] - $$PREBID_GLOBAL$$[callbackName](validResponse) - }); - - it('adds bid for valid request with UM', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.GOOD }); - done(); - }); - - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(validBid); - var callbackName = '_hb_' + stubGetUniqueIdentifierStr.returnValues[0] - $$PREBID_GLOBAL$$[callbackName](validResponseUM) - }); - }); -}); diff --git a/test/spec/modules/indexExchangeBidAdapter_request_spec.js b/test/spec/modules/indexExchangeBidAdapter_request_spec.js deleted file mode 100644 index 787c6bafde4..00000000000 --- a/test/spec/modules/indexExchangeBidAdapter_request_spec.js +++ /dev/null @@ -1,528 +0,0 @@ -import Adapter from 'modules/indexExchangeBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; -import * as url from 'src/url'; - -var assert = require('chai').assert; -var IndexUtils = require('../../helpers/index_adapter_utils.js'); -var HeaderTagRequest = '/cygnus'; -var SlotThreshold = 20; -var ADAPTER_CODE = 'indexExchange'; - -window.pbjs = window.pbjs || {}; - -describe('indexExchange adapter - Request', function () { - let adapter; - let sandbox; - - beforeEach(function() { - window._IndexRequestData = {}; - _IndexRequestData.impIDToSlotID = {}; - _IndexRequestData.reqOptions = {}; - _IndexRequestData.targetIDToResp = {}; - window.cygnus_index_args = {}; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - sandbox.stub(adLoader, 'loadScript'); - sandbox.stub(bidManager, 'addBidResponse'); - }); - - afterEach(function() { - sandbox.restore(); - }); - - it('test_prebid_indexAdapter_parameter_x3: prebid sends AS request -> x3 parameter does not exist in the request', function () { - var configuredBids = IndexUtils.createBidSlots(); - adapter.callBids({ bids: configuredBids }); - - assert.notInclude(adLoader.loadScript.firstCall.args[0], 'x3=', 'x3 parameter is not in AS request'); - }); - - it('test_prebid_indexAdapter_request_1_1: single slot with single size -> single request object for the slot', function () { - var configuredBids = IndexUtils.createBidSlots(); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.isString(requestJSON.r.id, 'ID is string'); - }); - - it('test_prebid_indexAdapter_request_1_1: single slot with single size -> single request object for the slot', function () { - var configuredBids = IndexUtils.createBidSlots(); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_1_2: single slot with unsupported single size -> indexExchange does not participate in auction', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.unsupportedSizes[0] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, "bidder code match with adapter's name"); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - }); - - it('test_prebid_indexAdapter_request_2_1: single slot with all supported multiple sizes -> multiple request objects for the slot', function () { - var configuredBids = IndexUtils.createBidSlots(1, 5); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_2_2: single slot with all unsupported multiple sizes -> no request objects for the slot', function () { - var isSetExpectedBidsCountCalled = false; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.unsupportedSizes[0], IndexUtils.unsupportedSizes[1], IndexUtils.unsupportedSizes[2] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_request_2_3: single slot with supported, unsupportrd, supported sizes -> only the supported size request objects for the slot', function () { - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], unsupportedSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize)); - }); - - it('test_prebid_indexAdapter_request_2_4: single slot with unsupported, supportrd, unsupported sizes -> only the supported size request objects for the slot', function () { - var unsupportedSize1 = IndexUtils.unsupportedSizes[0]; - var unsupportedSize2 = IndexUtils.unsupportedSizes[1]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ unsupportedSize1, IndexUtils.supportedSizes[1], unsupportedSize2 ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 2, '2 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize1, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize1)); - assert.equal(sidMatched.unmatched.configured[1].size, unsupportedSize2, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize2)); - }); - - it('test_prebid_indexAdapter_request_3: multiple slots with single size below allowed slot threshold -> request for all the slots', function () { - var configuredBids = IndexUtils.createBidSlots(10); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_4: multiple slots with single size at exact allowed slot threshold -> request for all the slots', function () { - var configuredBids = IndexUtils.createBidSlots(SlotThreshold); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_5: multiple slots with single size exceed allowed slot threshold -> request for all the slots', function () { - var requestSlotNumber = SlotThreshold + 1; - var configuredBids = IndexUtils.createBidSlots(requestSlotNumber); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_6: threshold valid + non valid which exceeds threshold -> 1 Ad Server request with supported sizes only', function () { - var unsupportedSizeCount = 1; - var requestSlotNumber = SlotThreshold; - var configuredBids = IndexUtils.createBidSlots(requestSlotNumber); - // add additional unsupported sized slot - var invalidSlotPlacement = IndexUtils.DefaultPlacementCodePrefix + 'invalid'; - var invalidSlotID = 'slot-invalid'; - configuredBids.push(IndexUtils.createBidSlot(invalidSlotPlacement, invalidSlotID, [ IndexUtils.unsupportedSizes[0] ])); - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, unsupportedSizeCount, unsupportedSizeCount + ' of configured bids is missing in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].placementCode, invalidSlotPlacement, "missing slot's placement code is " + invalidSlotPlacement); - assert.equal(sidMatched.unmatched.configured[0].params.id, invalidSlotID, "missing slot's slotID is " + invalidSlotID); - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_7: multiple sizes with slots that exceeds max threshold requests -> 1 Ad Server request with supported sizes only', function () { - var requestSlotNumber = SlotThreshold; - var requestSizeNumber = 2; - var configuredBids = IndexUtils.createBidSlots(requestSlotNumber, requestSizeNumber); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - assert.equal(sidMatched.matched.length, requestSlotNumber * requestSizeNumber, 'All slots each with multiple sizes are in AS request'); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_sizeID_1: 1 prebid size slot, 1 index slot with size -> one slot in AS request 1 no size ID', function () { - var slotID = 52; - var slotSizes = IndexUtils.supportedSizes[0]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ slotSizes ], { slotSize: slotSizes }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - assert.equal(impressionObj.length, 1, '1 slot is made in the request'); - assert.equal(impressionObj[0].banner.w, slotSizes[0], 'the width made in the request matches with request: ' + slotSizes[0]); - assert.equal(impressionObj[0].banner.h, slotSizes[1], 'the height made in the request matches with request: ' + slotSizes[1]); - assert.equal(impressionObj[0].ext.sid, slotID, 'slotID in the request matches with configuration: ' + slotID); - assert.equal(impressionObj[0].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - }); - - it('test_prebid_indexAdapter_request_sizeID_2: multiple prebid size slot, 1 index slot with size -> one slot in AS request 1 no size ID', function () { - var slotID = 52; - var slotSizes = IndexUtils.supportedSizes[0]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ slotSizes, IndexUtils.supportedSizes[1] ], { slotSize: slotSizes }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - assert.equal(impressionObj.length, 1, '1 slot is made in the request'); - assert.equal(impressionObj[0].banner.w, slotSizes[0], 'the width made in the request matches with request: ' + slotSizes[0]); - assert.equal(impressionObj[0].banner.h, slotSizes[1], 'the height made in the request matches with request: ' + slotSizes[1]); - assert.equal(impressionObj[0].ext.sid, slotID, 'slotID in the request matches with configuration: ' + slotID); - assert.equal(impressionObj[0].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - }); - - it('test_prebid_indexAdapter_request_sizeID_3: multiple prebid size slot, index slots with size for all prebid slots -> all size in AS request, no size ID', function () { - var slotID_1 = 52; - var slotID_2 = 53; - var slotSizes_1 = IndexUtils.supportedSizes[0]; - var slotSizes_2 = IndexUtils.supportedSizes[1]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID_1, [ slotSizes_1, slotSizes_2 ], { slotSize: slotSizes_1 }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID_2, [ slotSizes_1, slotSizes_2 ], { slotSize: slotSizes_2 }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - assert.equal(impressionObj.length, 2, '2 slot is made in the request'); - assert.equal(impressionObj[0].banner.w, slotSizes_1[0], 'the width made in the request matches with request: ' + slotSizes_1[0]); - assert.equal(impressionObj[0].banner.h, slotSizes_1[1], 'the height made in the request matches with request: ' + slotSizes_1[1]); - assert.equal(impressionObj[0].ext.sid, slotID_1, 'slotID in the request matches with configuration: ' + slotID_1); - assert.equal(impressionObj[0].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - - assert.equal(impressionObj[1].banner.w, slotSizes_2[0], 'the width made in the request matches with request: ' + slotSizes_2[0]); - assert.equal(impressionObj[1].banner.h, slotSizes_2[1], 'the height made in the request matches with request: ' + slotSizes_2[1]); - assert.equal(impressionObj[1].ext.sid, slotID_2, 'slotID in the request matches with configuration: ' + slotID_2); - assert.equal(impressionObj[1].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - }); - - it('test_prebid_indexAdapter_request_sizeID_4: multiple prebid size slot, 1 index slot but size not in prebid defined size git -> no AS requset', function () { - var slotID = 52; - var slotSizes = IndexUtils.unsupportedSizes[0]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ IndexUtils.supportedSizes[0] ], { slotSize: slotSizes }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_request_sizeID_5: multiple prebid size slot, 1 index slot but size not defined in slot -> no AS requset', function () { - var slotID = 52; - var slotSizes = IndexUtils.supportedSizes[1]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ IndexUtils.supportedSizes[0] ], { slotSize: slotSizes }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_request_different_type_adUnits: both display and video slots -> 2 Ad Server requests, 1 for display and 1 for video', function() { - var videoConfig = { - 'siteID': 6, - 'playerType': 'HTML5', - 'protocols': ['VAST2', 'VAST3'], - 'maxduration': 15 - } - var videoWidth = 640; - var videoHeight = 480; - var configuredBids = IndexUtils.createBidSlots(2); - configuredBids[1].params.video = Object.assign({}, videoConfig); - configuredBids[1].mediaType = 'video'; - configuredBids[1].sizes[0] = videoWidth; - configuredBids[1].sizes[1] = videoHeight; - - adapter.callBids({ bids: configuredBids }); - - sinon.assert.calledTwice(adLoader.loadScript); - - // Check request for display ads - assert.include(adLoader.loadScript.secondCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.secondCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = [IndexUtils.expandSizes(configuredBids[0])]; - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.isString(requestJSON.r.id, 'ID is string'); - - // Check request for video ads - let cygnusRequestUrl = url.parse(encodeURIComponent(adLoader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].ext.siteID).to.equal(videoConfig.siteID); - expect(cygnusRequestUrl.search.r.imp[0].video.maxduration).to.equal(videoConfig.maxduration); - expect(cygnusRequestUrl.search.r.imp[0].video.w).to.equal(videoWidth); - expect(cygnusRequestUrl.search.r.imp[0].video.h).to.equal(videoHeight); - }); -}); diff --git a/test/spec/modules/indexExchangeBidAdapter_response_spec.js b/test/spec/modules/indexExchangeBidAdapter_response_spec.js deleted file mode 100644 index 817244a2c68..00000000000 --- a/test/spec/modules/indexExchangeBidAdapter_response_spec.js +++ /dev/null @@ -1,1170 +0,0 @@ -import Adapter from 'modules/indexExchangeBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; - -var assert = require('chai').assert; -var IndexUtils = require('../../helpers/index_adapter_utils.js'); -var HeaderTagRequest = '/cygnus'; -var SlotThreshold = 20; -var ADAPTER_CODE = 'indexExchange'; -var DefaultValue = { - dealID: 'IXDeal' -}; -window.pbjs = window.pbjs || {}; -var ResponseStatus = { - noBid: 'Bid returned empty or error response' -}; - -describe('indexExchange adapter - Response', function () { - let adapter; - let sandbox; - - beforeEach(function() { - window._IndexRequestData = {}; - _IndexRequestData.impIDToSlotID = {}; - _IndexRequestData.reqOptions = {}; - _IndexRequestData.targetIDToResp = {}; - window.cygnus_index_args = {}; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - sandbox.stub(bidManager, 'addBidResponse'); - sandbox.stub(adLoader, 'loadScript'); - }); - - afterEach(function() { - sandbox.restore(); - }); - - it('test_prebid_indexAdapter_response_1_1: response for single slot with single size -> bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - assert.equal(pair.prebid.length, 1, 'Only one bid is ferched into prebid'); - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_1_2: pass on bid for single slot with single size -> bid fetched into prebid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot1', [ IndexUtils.supportedSizes[0] ]), - ]; - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [ [ true ] ]); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 0, 'No bids are added to prebid'); - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 1, 'no Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_2_1: response for single slot with multiple sizes -> all bids fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 3); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse, [ [1000, 3000, 2000] ]); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid.length, 3, 'all bids are fetched into prebid'); - for (var j = 0; j < pair.prebid.length; j++) { - assert.equal(pair.prebid[j].siteID, pair.expected[j].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[j].siteID); - assert.equal(pair.prebid[j].bidderCode, pair.expected[j].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[j].bidderCode); - assert.equal(pair.prebid[j].width, pair.expected[j].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[j].width); - assert.equal(pair.prebid[j].height, pair.expected[j].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[j].height); - assert.equal(pair.prebid[j].ad, pair.expected[j].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[j].ad); - assert.equal(pair.prebid[j].cpm, pair.expected[j].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[j].cpm); - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_2_2: pass on bid on some sizes for single slot with multiple sizes -> highest bid fetched into prebid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot1', [ IndexUtils.supportedSizes[0], IndexUtils.supportedSizes[1] ]), - ]; - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // pass on bid on second size - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [ [ false, true ] ]); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 1, 'one slot is added to prebid'); - var pair = prebidResponsePair.matched[0]; - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_2_3: pass on bid on all sizes for a single slot -> no bids fetched into prebid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot1', [ IndexUtils.supportedSizes[0], IndexUtils.supportedSizes[1] ]), - ]; - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // pass on bid on all bids - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [ [ true, true ] ]); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 0, 'no bids fetched into prebid'); - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid[0][0].statusMessage, ResponseStatus.noBid, 'Bid response status is set to ' + ResponseStatus.noBid); - }); - - it('test_prebid_indexAdapter_response_3_1: response for multiple slots request with single size for each slots -> all response for all adunit fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(20); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse, [ [1000, 3000, 2000] ]); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_3_2: some slots response returned -> returned bids fetched into prebid ', function () { - var configuredBids = IndexUtils.createBidSlots(2); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - var passOnBid = [ - [ false ], // bids back on first slot - [ true ], // pass on bid on second slot - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, passOnBid); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse, [ [1000, 3000, 2000] ]); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 1, '1 bid from ad server is fetched into prebid'); - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 1, 'One slot passed on bid from Ad Server'); - }); - - it('test_prebid_indexAdapter_response_3_3: response for multiple slots with no response returned -> no bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(2); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - var passOnBid = [ - [ true ], // pass on bid on the first slot - [ true ], // pass on bid on the second slot - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, passOnBid); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse, [ [1000, 3000, 2000] ]); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 0, 'no bids from ad server is fetched into prebid'); - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 2, 'two slots passed on bid from Ad Server'); - }); - - it("test_prebid_indexAdapter_refreshSlot_1: slot refreshes multiple times with different bids on refresh with same price -> response to prebid use correct AS response's creative", function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - - var refreshSetup = [ {price: 1000, request: 'request-1'}, {price: 1000, request: 'request-2'} ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // first ix call - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, [ [requestParams.price] ], requestParams.request); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var j = 0; j < prebidResponsePair.matched.length; j++) { - var pair = prebidResponsePair.matched[j]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - for (var k = 0; k < pair.prebid.length; k++) { - assert.equal(pair.prebid[k].siteID, pair.expected[k].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[k].siteID); - assert.equal(pair.prebid[k].bidderCode, pair.expected[k].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[k].bidderCode); - assert.equal(pair.prebid[k].width, pair.expected[k].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[k].width); - assert.equal(pair.prebid[k].height, pair.expected[k].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[k].height); - assert.equal(pair.prebid[k].ad, pair.expected[k].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[k].ad); - assert.equal(pair.prebid[k].cpm, pair.expected[k].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[k].cpm); - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - - bidManager.addBidResponse.reset(); - adapterResponse = {}; // initialize adapterReaponse for refresh test - } - }); - - it("test_prebid_indexAdapter_refreshSlot_2: slot refreshes multiple times with different bids on refresh with different price, but first bid is higher -> response to prebid use correct AS response's creative", function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - - var refreshSetup = [ {price: 8000, request: 'request-1'}, {price: 1000, request: 'request-2'} ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // first ix call - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, [ [requestParams.price] ], requestParams.request); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var j = 0; j < prebidResponsePair.matched.length; j++) { - var pair = prebidResponsePair.matched[j]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - for (var k = 0; k < pair.prebid.length; k++) { - assert.equal(pair.prebid[k].siteID, pair.expected[k].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[k].siteID); - assert.equal(pair.prebid[k].bidderCode, pair.expected[k].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[k].bidderCode); - assert.equal(pair.prebid[k].width, pair.expected[k].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[k].width); - assert.equal(pair.prebid[k].height, pair.expected[k].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[k].height); - assert.equal(pair.prebid[k].ad, pair.expected[k].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[k].ad); - assert.equal(pair.prebid[k].cpm, pair.expected[k].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[k].cpm); - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - bidManager.addBidResponse.reset(); - adapterResponse = {}; // initialize adapterReaponse for refresh test - } - }); - - it("test_prebid_indexAdapter_refreshSlot_3: slot refreshes multiple times with different bids on refresh with different price, but first bid is lower -> response to prebid use correct AS response's creative", function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - - var refreshSetup = [ {price: 1000, request: 'request-1'}, {price: 8000, request: 'request-2'} ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // first ix call - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, [ [requestParams.price] ], requestParams.request); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var j = 0; j < prebidResponsePair.matched.length; j++) { - var pair = prebidResponsePair.matched[j]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - for (var k = 0; k < pair.prebid.length; k++) { - assert.equal(pair.prebid[k].siteID, pair.expected[k].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[k].siteID); - assert.equal(pair.prebid[k].bidderCode, pair.expected[k].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[k].bidderCode); - assert.equal(pair.prebid[k].width, pair.expected[k].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[k].width); - assert.equal(pair.prebid[k].height, pair.expected[k].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[k].height); - assert.equal(pair.prebid[k].ad, pair.expected[k].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[k].ad); - assert.equal(pair.prebid[k].cpm, pair.expected[k].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[k].cpm); - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - bidManager.addBidResponse.reset(); - adapterResponse = {}; // initialize adapterReaponse for refresh test - } - }); - - it('test_prebid_indexAdapter_refreshSlot_4: got no response the second time -> no bids fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - - var refreshSetup = [ { price: 1000, request: 'request-1', passOnBid: false}, { price: 1000, request: 'request-2', passOnBid: true} ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // first ix call - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, [ [requestParams.price] ], requestParams.request, [ [ requestParams.passOnBid ] ]); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var j = 0; j < prebidResponsePair.matched.length; j++) { - var pair = prebidResponsePair.matched[j]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - for (var k = 0; k < pair.prebid.length; k++) { - assert.equal(pair.prebid[k].siteID, pair.expected[k].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[k].siteID); - assert.equal(pair.prebid[k].bidderCode, pair.expected[k].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[k].bidderCode); - assert.equal(pair.prebid[k].width, pair.expected[k].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[k].width); - assert.equal(pair.prebid[k].height, pair.expected[k].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[k].height); - assert.equal(pair.prebid[k].ad, pair.expected[k].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[k].ad); - assert.equal(pair.prebid[k].cpm, pair.expected[k].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[k].cpm); - } - } - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - if (requestParams.passOnBid) { - assert.equal(prebidResponsePair.unmatched.prebid.length, 1, '1 Adapter response is missing'); - } else { - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - } - - bidManager.addBidResponse.reset(); - adapterResponse = {}; // initialize adapterReaponse for refresh test - } - }); - - it('test_prebid_indexAdapter_refreshSlot_5: unsupported slots refresh -> no ad server request, no bids fetched into prebid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.unsupportedSizes[0] ]) - ]; - - var refreshSetup = [ { request: 'request-1' }, { request: 'request-2' } ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - assert.isFalse(adLoader.loadScript.called, 'no ad server request for ' + requestParams.request) - } - }); - - it('test_prebid_indexAdapter_response_deal_1_1: response for single slot with single size contains alpha deal -> bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: 'ixDeal' } } // first slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[i].dealId, pair.expected[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_1_2: response for single slot with single size contains numeric deal -> bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: '239' } } // first slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[i].dealId, pair.expected[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_1_3: response for single slot with single size contains alpha-numeric deal starting with numeric -> bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: '1234Deal' } } // first slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[i].dealId, pair.expected[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_1_4: response for single slot with single size contains alpha-numeric deal starting with non-numeric -> bid fetched into prebid ', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: 'deal1234' } } // first slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); // Alpha numeric starting with non-numeric - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[i].dealId, pair.expected[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_2_1: response for single slot with multi size, all deal bids returned -> all bid fetched into prebid as deal bid', function () { - var sizeCount = 2; - var configuredBids = IndexUtils.createBidSlots(1, sizeCount); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { deal: 'deal1', dealid: 'ixDealID1', dealname: 'deal name 1' } }, // first slot first size - { ext: { deal: 'deal2', dealid: 'ixDealID2', dealname: 'deal name 2' } }, // first slot second size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - for (var j = 0; j < pair.expected.length; j++) { - assert.equal(pair.prebid[j].siteID, pair.expected[j].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[j].bidderCode, pair.expected[j].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[j].width, pair.expected[j].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[j].height, pair.expected[j].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[j].ad, pair.expected[j].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[j].cpm, pair.expected[j].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[j].dealId, pair.expected[j].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - } - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_2_2: response for single slot with multi size, some deal resposne returned and the rest non deal response -> all bid fetched, only deal response has dealID', function () { - var sizeCount = 2; - var configuredBids = IndexUtils.createBidSlots(1, sizeCount); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { deal: 'deal1', dealid: 'ixDealID1', dealname: 'deal name 1' } } // first slot first size - // No deal on first slot second size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - for (var j = 0; j < pair.expected.length; j++) { - assert.equal(pair.prebid[j].siteID, pair.expected[j].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[j].bidderCode, pair.expected[j].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[j].width, pair.expected[j].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[j].height, pair.expected[j].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[j].ad, pair.expected[j].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[j].cpm, pair.expected[j].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - if (i === 0) { - assert.equal(pair.prebid[j].dealId, pair.expected[j].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } else { - assert.isUndefined(pair.prebid[j].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is not set'); - } - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_2_3: response for single slot with multi size, all returned as non-deal response -> all bid fetched, no response has dealID', function () { - var sizeCount = 2; - var configuredBids = IndexUtils.createBidSlots(1, sizeCount); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - {}, - {} - // No deal on first slot first size - // No deal on first slot second size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - for (var j = 0; j < pair.expected.length; j++) { - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.isUndefined(pair.prebid[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is not set'); - } - } - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_3_1: multi slots, all responses contain deal -> all bid fetched into prebid as deal bid', function () { - var slotCount = 2; - var configuredBids = IndexUtils.createBidSlots(slotCount, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: 'ixDeal1' } } // first slot first size - ], - [ - { ext: { dealid: 'ixDeal2' } } // second slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - assert.equal(pair.prebid[0].dealId, pair.expected[0].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[0].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_3_2: multi slots, some responses contain deal -> all bid fetched, only deal response has dealID', function () { - var slotCount = 2; - var configuredBids = IndexUtils.createBidSlots(slotCount, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: 'ixDeal1' } } // first slot first size - ], - [ - {} - // no deal on second slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - var count = 0; - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - if (count === 0) { // if first slot, check deal parameter - assert.equal(pair.prebid[0].dealId, pair.expected[0].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[0].dealId); - } else { - assert.isUndefined(pair.prebid[0].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is not defined'); - } - count++; - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_3_3: multi slots, no responses contain deal -> all bid fetched, no response has dealID ', function () { - var slotCount = 2; - var configuredBids = IndexUtils.createBidSlots(slotCount, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - {} - // no deal on first slot first size - ], - [ - {} - // no deal on second slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - assert.isUndefined(pair.prebid[0].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is not defined'); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_tier: one slot with multiple tier -> all tier bids are fetched into prebid', function() { - var slotConfig = { - tier2SiteID: IndexUtils.DefaultSiteID + 1, - tier3SiteID: IndexUtils.DefaultSiteID + 2, - }; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], slotConfig), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - assert.equal(sidMatched.matched.length, 3, 'Three slots are configured and sent to AS'); - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check tier 1 site id - var tier2SitePair = sidMatched.matched[1]; - var expectedTierSlotID = 'T1_' + tier2SitePair.configured.params.id + '_1'; - assert.equal(tier2SitePair.sent.ext.sid, expectedTierSlotID, 'request ' + tier2SitePair.name + ' site ID is set to ' + expectedTierSlotID); - assert.isString(tier2SitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedTierSiteID = tier2SitePair.configured.params.tier2SiteID; - assert.equal(tier2SitePair.sent.ext.siteID, expectedTierSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedTierSiteID); - assert.isNumber(tier2SitePair.sent.ext.siteID, 'site ID is integer'); - - // check tier 2 site id - var tier3SitePair = sidMatched.matched[2]; - var expectedTierSlotID = 'T2_' + tier3SitePair.configured.params.id + '_1'; - assert.equal(tier3SitePair.sent.ext.sid, expectedTierSlotID, 'request ' + tier3SitePair.name + ' site ID is set to ' + expectedTierSlotID); - assert.isString(tier3SitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedTier3SiteID = tier3SitePair.configured.params.tier3SiteID; - assert.equal(tier3SitePair.sent.ext.siteID, expectedTier3SiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedTier3SiteID); - assert.isNumber(tier3SitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_callback_bids: callback function defined with bids -> calls callback function with bids', function () { - var callbackCalled = false; - var callback_requestID; - var callback_slots; - window.cygnus_index_args['callback'] = function(requestID, slots) { - callbackCalled = true; - callback_requestID = requestID; - callback_slots = slots; - } - - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON); - cygnus_index_parse_res(asResponse); - - assert.equal(callbackCalled, true, 'callback function is called'); - assert.equal(callback_requestID, requestJSON.r.id, 'callback requestID matches with actual request ID: ' + requestJSON.r.id); - assert.equal(callback_slots.length, 1, 'callback slots include one slot'); - }); - - it('test_prebid_indexAdapter_callback_nobids: callback function defined with no bids -> calls callback function without bids', function () { - var callbackCalled = false; - var callback_requestID; - var callback_slots; - window.cygnus_index_args['callback'] = function(requestID, slots) { - callbackCalled = true; - callback_requestID = requestID; - callback_slots = slots; - } - - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [[true]]); // pass on bid - cygnus_index_parse_res(asResponse); - - assert.equal(callbackCalled, true, 'callback function is called'); - assert.equal(callback_requestID, requestJSON.r.id, 'callback requestID matches with actual request ID: ' + requestJSON.r.id); - assert.isUndefined(callback_slots, 'callback slot is undefined because all bids passed on bid'); - }); - - it('test_prebid_indexAdapter_response_sizeID_1: multiple prebid size slot, index slots with size for all prebid slots -> all size in AS request, no size ID', function () { - var slotID_1 = '52'; - var slotID_2 = '53'; - var slotSizes_1 = IndexUtils.supportedSizes[0]; - var slotSizes_2 = IndexUtils.supportedSizes[1]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + slotID_1, slotID_1, [ slotSizes_1, slotSizes_2 ], { slotSize: slotSizes_1 }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + slotID_2, slotID_2, [ slotSizes_1, slotSizes_2 ], { siteID: IndexUtils.DefaultSiteID + 1 }) - ]; - - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [[true]]); // pass on bid - cygnus_index_parse_res(asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - }); -}); diff --git a/test/spec/modules/indexExchangeBidAdapter_validation_spec.js b/test/spec/modules/indexExchangeBidAdapter_validation_spec.js deleted file mode 100644 index 46a1996cc8a..00000000000 --- a/test/spec/modules/indexExchangeBidAdapter_validation_spec.js +++ /dev/null @@ -1,1607 +0,0 @@ -import Adapter from '../../../modules/indexExchangeBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; - -var assert = require('chai').assert; -var IndexUtils = require('../../helpers/index_adapter_utils.js'); -var HeaderTagRequest = '/cygnus'; -var ADAPTER_CODE = 'indexExchange'; - -window.pbjs = window.pbjs || {}; - -describe('indexExchange adapter - Validation', function () { - let adapter; - let sandbox; - - beforeEach(function() { - window._IndexRequestData = {}; - _IndexRequestData.impIDToSlotID = {}; - _IndexRequestData.reqOptions = {}; - _IndexRequestData.targetIDToResp = {}; - window.cygnus_index_args = {}; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - sandbox.stub(adLoader, 'loadScript'); - sandbox.stub(bidManager, 'addBidResponse'); - }); - - afterEach(function() { - sandbox.restore(); - }); - - it('test_prebid_indexAdapter_sizeValidation_1: request slot has supported and unsupported size -> unsupported size ignored in IX demand request', function () { - // create 2 sizes for 1 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], unsupportedSize ]) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize)); - - // checking bid manager responses. Only one bid back into bidmanager because one size is unsupported - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - }); - - it('test_prebid_indexAdapter_sizeValidation_2_1: some slot has unsupported size -> unsupported slot ignored in IX demand request', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'supported', 'slot_1', [ IndexUtils.supportedSizes[0], ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'unspported', 'slot_2', [ unsupportedSize ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize)); - assert.equal(sidMatched.unmatched.configured[0].params.id, 'slot_2', 'configured bid not in impression obj id is slot_2'); - assert.equal(sidMatched.unmatched.configured[0].params.siteID, IndexUtils.DefaultSiteID + 1, 'configured bid not in impression obj siteID is ' + (IndexUtils.DefaultSiteID + 1)); - }); - - it('test_prebid_indexAdapter_sizeValidation_2_2: multiple slots with sinle size, all slot has supported size -> all slots are sent to IX demand', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'supported1', 'slot_1', [ IndexUtils.supportedSizes[0] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'supported2', 'slot_2', [ IndexUtils.supportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, '0 configured bid is not in impression Obj'); - }); - - it('test_prebid_indexAdapter_sizeValidation_2_3: multiple slots with sinle size, all slot has unsupported size -> all slots are ignored', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'unsupported1', 'slot_1', [ IndexUtils.unsupportedSizes[0] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'unsupported2', 'slot_2', [ IndexUtils.unsupportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to IX demand'); - }); - - it('test_prebid_indexAdapter_sizeValidation_3_1: one slot has supported, unsupported, supported size -> unsupported slot ignored in IX demand request', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'somesupported', 'slot_1', [ IndexUtils.supportedSizes[0], unsupportedSize, IndexUtils.supportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'allsupported', 'slot_2', [ IndexUtils.supportedSizes[2], IndexUtils.supportedSizes[3] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize)); - assert.equal(sidMatched.unmatched.configured[0].params.id, 'slot_1', 'configured bid not in impression obj id is slot_1'); - assert.equal(sidMatched.unmatched.configured[0].params.siteID, IndexUtils.DefaultSiteID, 'configured bid not in impression obj siteID is ' + (IndexUtils.DefaultSiteID)); - }); - - it('test_prebid_indexAdapter_sizeValidation_3_2: one slot has unsupported, supported, unsupported size -> unsupported slot ignored in IX demand request', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize1 = IndexUtils.unsupportedSizes[0]; - var unsupportedSize2 = IndexUtils.unsupportedSizes[1]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'somesupported', 'slot_1', [ unsupportedSize1, IndexUtils.supportedSizes[1], unsupportedSize2 ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'allsupported', 'slot_2', [ IndexUtils.supportedSizes[2], IndexUtils.supportedSizes[3] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 2, '2 configured bid is not in impression Obj'); - - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize1, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize1)); - assert.equal(sidMatched.unmatched.configured[0].params.id, 'slot_1', 'configured bid not in impression obj id is slot_1'); - assert.equal(sidMatched.unmatched.configured[0].params.siteID, IndexUtils.DefaultSiteID, 'configured bid not in impression obj siteID is ' + (IndexUtils.DefaultSiteID)); - - assert.equal(sidMatched.unmatched.configured[1].size, unsupportedSize2, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize2)); - assert.equal(sidMatched.unmatched.configured[1].params.id, 'slot_1', 'configured bid not in impression obj id is slot_1'); - assert.equal(sidMatched.unmatched.configured[1].params.siteID, IndexUtils.DefaultSiteID, 'configured bid not in impression obj siteID is ' + (IndexUtils.DefaultSiteID)); - }); - - it('test_prebid_indexAdapter_sizeValidation_3_3: multiple slots, all slots have supported size -> all slots are included in IX demand request', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'allsupported1', 'slot_1', [ IndexUtils.supportedSizes[0], IndexUtils.supportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'allsupported2', 'slot_2', [ IndexUtils.supportedSizes[2], IndexUtils.supportedSizes[3] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 0, '0 configured bid is not in impression Obj'); - }); - - it('test_prebid_indexAdapter_sizeValidation_3_4: multiple slots, all slots have unsupported size -> no slots are sent to IX demand', function () { - var firstPlacement = IndexUtils.DefaultPlacementCodePrefix + 'allsupported1'; - var secondPlacement = IndexUtils.DefaultPlacementCodePrefix + 'allsupported2'; - var configuredBids = [ - IndexUtils.createBidSlot(firstPlacement, 'slot_1', [ IndexUtils.unsupportedSizes[0], IndexUtils.unsupportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(secondPlacement, 'slot_2', [ IndexUtils.unsupportedSizes[2], IndexUtils.unsupportedSizes[3] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'No request to IX demand'); - - // checking bid manager responses. Only one bid back into bidmanager because one size is unsupported - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - assert.deepEqual(Object.keys(adapterResponse), [firstPlacement, secondPlacement], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[firstPlacement].length, 2, 'two response back returned for placement ' + firstPlacement); - assert.equal(adapterResponse[firstPlacement][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[firstPlacement][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - assert.equal(adapterResponse[firstPlacement][1].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[firstPlacement][1].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - assert.equal(adapterResponse[secondPlacement].length, 2, 'two response back returned for placement ' + secondPlacement); - assert.equal(adapterResponse[secondPlacement][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[secondPlacement][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - assert.equal(adapterResponse[secondPlacement][1].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[secondPlacement][1].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - }); - - it('test_prebid_indexAdapter_param_timeout_integer: timeout is integer -> t parameter that matches with the integer', function () { - var testTimeout = 100; // integer timeout - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.equal(requestJSON.t, testTimeout, 't parameter matches timeout and is included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_quoted_integer: timeout is quoted integer -> t parameter that matches with the integer', function () { - var testTimeout = '100'; // quoted integer timeout - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.equal(requestJSON.t, testTimeout, 't parameter matches timeout and is included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_float: timeout is float number -> t parameter is not included in AS request', function () { - var testTimeout = 1.234; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_float: timeout is float number -> t parameter is not included in AS request', function () { - var testTimeout = 1.234; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_string: timeout is string -> t parameter is not included in AS request', function () { - var testTimeout = 'string'; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_array: timeout is array -> t parameter is not included in AS request', function () { - var testTimeout = [ 'abc' ]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_hash: timeout is hash -> t parameter is not included in AS request', function () { - var testTimeout = { 'timeout': 100 }; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_zero: timeout is zero -> t parameter is not included in AS request', function () { - var testTimeout = 0; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_negative: timeout is negative integer -> t parameter is not included in AS request', function () { - var testTimeout = -100; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_too_big: timeout is bigger than AS max timeout -> t parameter is not included in AS request', function () { - var testTimeout = 25000; // very large timeout - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.equal(requestJSON.t, testTimeout, 't parameter matches timeout and is included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_missing: timeout is missing -> t parameter is not included in AS request', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ]), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_empty_string: timeout is empty string -> t parameter is not included in AS request', function () { - var testTimeout = ''; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout}), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - var test_indexAdapter_slotid = [ - { - 'testname': 'test_prebid_indexAdapter_slotid_integer: slot ID is integer -> slot ID sent to AS in string', - 'slotID': 123, - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_quoted_integer: slot ID is quoted_integer -> slot ID sent to AS in string', - 'slotID': '123', - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_float: slot ID is float -> slot ID sent to AS in string', - 'slotID': 123.45, - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_string: slot ID is string -> slot ID sent to AS in string', - 'slotID': 'string', - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_array: slot ID is array -> slot is not sent to AS', - 'slotID': [ 'arrayelement1', 'arrayelement2' ], - 'expected': 'fail' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_hash: slot ID is hash -> slot is not sent to AS', - 'slotID': { 'hashName': 'hashKey' }, - 'expected': 'fail' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_zero: slot ID is zero integer -> slot ID sent to AS in string', - 'slotID': 0, - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_negative: slot ID is negative integer -> slot ID sent to AS in string', - 'slotID': -100, - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_undefined: slot ID is undefined -> slot is not sent to AS', - 'slotID': undefined, - 'expected': 'fail' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_missing: slot ID is missing -> slot is not sent to AS', - 'param': { 'missingSlotID': true}, - 'expected': 'invalid' - } - ]; - - function base_prebid_indexAdapter_slotid (testname, slotID, expected, param) { - it(testname, function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ IndexUtils.supportedSizes[0] ], param), - ]; - adapter.callBids({ bids: configuredBids }); - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - if (expected == 'pass') { - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSlotID = pair.sent.ext.sid; - var expectedSlotID = pair.configured.params.id + '_1'; - assert.equal(actualSlotID, expectedSlotID, 'request ' + pair.name + ' slot ID is set to ' + expectedSlotID); - assert.isString(actualSlotID, 'slotID is string'); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } else if (expected == 'invalid') { - // case where callBids throws out request due to missing params - assert.isFalse(adLoader.loadScript.called, 'No request to AS') - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - } else { - assert.strictEqual(typeof indexBidRequest, 'undefined', 'No request to AS'); - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - } - }); - }; - - for (var i = 0; i < test_indexAdapter_slotid.length; i++) { - var test = test_indexAdapter_slotid[i]; - base_prebid_indexAdapter_slotid(test.testname, test.slotID, test.expected, test.param); - } - - it('test_prebid_indexAdapter_slotid_multiple_slot: uniqueness for multiple slots -> all slots in ad server request with unique slot id', function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ]), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_2', [ IndexUtils.supportedSizes[1] ]), - ]; - adapter.callBids({ bids: configuredBids }); - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSlotID = pair.sent.ext.sid; - var expectedSlotID = pair.configured.params.id + '_1'; - assert.equal(actualSlotID, expectedSlotID, 'request ' + pair.name + ' slot ID is set to ' + expectedSlotID); - assert.isString(actualSlotID, 'slotID is string'); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_slotid_multiple_same: same across some slots -> all slots in ad server request with same slot id', function() { - var slotName = 'slot_same'; - var secondSlotSize = IndexUtils.supportedSizes[1]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotName, [ IndexUtils.supportedSizes[0] ]), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotName, [ secondSlotSize ]), - ]; - adapter.callBids({ bids: configuredBids }); - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSlotID = pair.sent.ext.sid; - var expectedSlotID = pair.configured.params.id + '_1'; - assert.equal(actualSlotID, expectedSlotID, 'request ' + pair.name + ' slot ID is set to ' + expectedSlotID); - assert.isString(actualSlotID, 'slotID is string'); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, secondSlotSize, 'configured bid not in impression obj size width is' + JSON.stringify(secondSlotSize)); - assert.equal(sidMatched.unmatched.configured[0].params.id, slotName, 'slot name is ' + slotName); - }); - - var test_indexAdapter_siteid = [ - { - 'testname': 'test_prebid_indexAdapter_siteid_integer: site ID is integer -> siteID ID sent to AS as integer', - 'param': { 'siteID': 12345 }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_quoted_integer: site ID is quoted integer -> siteID ID sent to AS as integer', - 'param': { 'siteID': '12345' }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_float: site ID is float -> slot is ignored', - 'param': { 'siteID': 12.345 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_string: site ID is string -> slot is ignored', - 'param': { 'siteID': 'string' }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_array: site ID is array with int -> siteID sent to AS as integer', - 'param': { 'siteID': [ 12345 ] }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_array: site ID is array with quoted int -> siteID sent to AS as integer', - 'param': { 'siteID': [ '12345' ] }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_array: site ID is array with alpha string -> slot is ignored', - 'param': { 'siteID': [ 'ABC' ] }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_hash: site ID is hash -> slot is ignored', - 'param': { 'siteID': { 12345: 678 } }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_zero: site ID is zero integer -> slot is ignored', - 'param': { 'siteID': 0 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_negative: site ID is a negative integer -> slot is ignored', - 'param': { 'siteID': -1234 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_missing: site ID is missing -> slot is ignored', - 'param': { 'missingSiteID': true }, - 'expected': 'invalid', - }, - ]; - - function base_prebid_indexAdapter_siteid (testname, param, expected) { - it(testname, function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], param), - ]; - - adapter.callBids({ bids: configuredBids }); - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - if (expected == 'pass') { - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSiteID = pair.sent.ext.siteID; - var expectedSiteID = pair.configured.params.siteID; - assert.equal(actualSiteID, expectedSiteID, 'request ' + pair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(actualSiteID, 'site ID is integer'); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } else if (expected == 'invalid') { - // case where callBids throws out request due to missing params - assert.isFalse(adLoader.loadScript.called, 'No request to AS'); - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - } else { - assert.isFalse(adLoader.loadScript.called, 'No request to AS'); - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - } - }); - }; - - for (var i = 0; i < test_indexAdapter_siteid.length; i++) { - var test = test_indexAdapter_siteid[i]; - base_prebid_indexAdapter_siteid(test.testname, test.param, test.expected); - } - - // TS: case created by PBA-12 - it('test_prebid_indexAdapter_second_siteid_float: site ID is float -> slot is ignored', function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + '1', 'slot_1', [ IndexUtils.supportedSizes[0] ]), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + '2', 'slot_2', [ IndexUtils.supportedSizes[1] ], { 'siteID': 123.45 }), - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - assert.equal(sidMatched.matched.length, 1, 'one slot is configured and sent to AS'); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSiteID = pair.sent.ext.siteID; - var expectedSiteID = pair.configured.params.siteID; - assert.equal(actualSiteID, expectedSiteID, 'request ' + pair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(actualSiteID, 'site ID is integer'); - } - - assert.equal(sidMatched.unmatched.configured.length, 1, 'float site ID configured bid is missing in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - var test_indexAdapter_tier2siteid = [ - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_integer: tier2 site ID is integer -> siteID ID sent to AS in integer', - 'param': { 'tier2SiteID': 12345 }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_quoted_integer: tier2 site ID is quoted integer -> siteID ID sent to AS in integer', - 'param': { 'tier2SiteID': '12345' }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_float: tier2 site ID is float -> slot is ignored', - 'param': { 'tier2SiteID': 12.345 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_string: tier2 site ID is string -> slot is ignored', - 'param': { 'tier2SiteID': 'string' }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_array: tier2 site ID is array -> slot is ignored', - 'param': { 'tier2SiteID': [ 12345 ] }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_hash: tier2 site ID is hash -> slot is ignored', - 'param': { 'tier2SiteID': { 12345: 678 } }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_zero: tier2 site ID is zero integer -> slot is ignored', - 'param': { 'tier2SiteID': 0 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_negative: tier2 site ID is a negative integer -> slot is ignored', - 'param': { 'tier2SiteID': -1234 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_missing: tier2 site ID is missing -> slot is ignored', - 'param': { 'missingtier2SiteID': true }, - 'expected': 'fail', - }, - ]; - function base_prebid_indexAdapter_tier2siteid (testname, param, expected) { - it(testname, function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], param), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - if (expected == 'pass') { - assert.equal(sidMatched.matched.length, 2, 'Two slots are configured and sent to AS'); - - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check tier site id - var tier2SitePair = sidMatched.matched[1]; - var expectedTierSlotID = 'T1_' + tier2SitePair.configured.params.id + '_1'; - assert.equal(tier2SitePair.sent.ext.sid, expectedTierSlotID, 'request ' + tier2SitePair.name + ' site ID is set to ' + expectedTierSlotID); - assert.isString(tier2SitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedTierSiteID = tier2SitePair.configured.params.tier2SiteID; - assert.equal(tier2SitePair.sent.ext.siteID, expectedTierSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedTierSiteID); - assert.isNumber(tier2SitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } else { - assert.equal(sidMatched.matched.length, 1, 'one slot is configured and sent to AS'); - - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - if (param.missingtier2SiteID) { - assert.equal(sidMatched.unmatched.configured.length, 0, 'one configured bid is missing in impression Obj'); - } else { - assert.equal(sidMatched.unmatched.configured.length, 1, 'one configured bid is missing in impression Obj'); - } - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } - }); - }; - - for (var i = 0; i < test_indexAdapter_tier2siteid.length; i++) { - var test = test_indexAdapter_tier2siteid[i]; - base_prebid_indexAdapter_tier2siteid(test.testname, test.param, test.expected); - } - - var test_indexAdapter_tier3siteid = [ - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_integer: tier3 site ID is integer -> siteID ID sent to AS in integer', - 'param': { 'tier3SiteID': 12345 }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_quoted_integer: tier3 site ID is quoted integer -> siteID ID sent to AS in integer', - 'param': { 'tier3SiteID': '12345' }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_float: tier3 site ID is float -> slot is ignored', - 'param': { 'tier3SiteID': 12.345 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_string: tier3 site ID is string -> slot is ignored', - 'param': { 'tier3SiteID': 'string' }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_array: tier3 site ID is array -> slot is ignored', - 'param': { 'tier3SiteID': [ 12345 ] }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_hash: tier3 site ID is hash -> slot is ignored', - 'param': { 'tier3SiteID': { 12345: 678 } }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_zero: tier3 site ID is zero integer -> slot is ignored', - 'param': { 'tier3SiteID': 0 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_negative: tier3 site ID is a negative integer -> slot is ignored', - 'param': { 'tier3SiteID': -1234 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_missing: tier3 site ID is missing -> slot is ignored', - 'param': { 'missingtier3SiteID': true }, - 'expected': 'fail', - }, - ]; - function base_prebid_indexAdapter_tier3siteid (testname, param, expected) { - it(testname, function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], param), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - if (expected == 'pass') { - assert.equal(sidMatched.matched.length, 2, 'Two slots are configured and sent to AS'); - - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check tier site id - var tier3SitePair = sidMatched.matched[1]; - var expectedTierSlotID = 'T2_' + tier3SitePair.configured.params.id + '_1'; - assert.equal(tier3SitePair.sent.ext.sid, expectedTierSlotID, 'request ' + tier3SitePair.name + ' site ID is set to ' + expectedTierSlotID); - assert.isString(tier3SitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedTierSiteID = tier3SitePair.configured.params.tier3SiteID; - assert.equal(tier3SitePair.sent.ext.siteID, expectedTierSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedTierSiteID); - assert.isNumber(tier3SitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } else { - assert.equal(sidMatched.matched.length, 1, 'one slot is configured and sent to AS'); - - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - if (param.missingtier3SiteID) { - assert.equal(sidMatched.unmatched.configured.length, 0, 'one configured bid is missing in impression Obj'); - } else { - assert.equal(sidMatched.unmatched.configured.length, 1, 'one configured bid is missing in impression Obj'); - } - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } - }); - }; - - for (var i = 0; i < test_indexAdapter_tier3siteid.length; i++) { - var test = test_indexAdapter_tier3siteid[i]; - base_prebid_indexAdapter_tier3siteid(test.testname, test.param, test.expected); - } - - it('test_prebid_indexAdapter_siteID_multiple: multiple slots have same siteIDs -> all slots in ad server request with the same site IDs', function() { - var first_slot = { - slotName: 'slot1', - siteID: 111111, - }; - var second_slot = { - slotName: 'slot2', - siteID: 111111, // same as first slot - }; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, first_slot['slotName'], [ IndexUtils.supportedSizes[0] ], { siteID: first_slot['siteID'] }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, second_slot['slotName'], [ IndexUtils.supportedSizes[1] ], { siteID: second_slot['siteID'] }), - ]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var expectedSiteID = pair.configured.params.siteID; - var actualSiteID = pair.sent.ext.siteID; - assert.equal(actualSiteID, expectedSiteID, 'request ' + pair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(actualSiteID, 'site ID is number'); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - }); - - it('test_prebid_indexAdapter_siteID_different: multiple slots have different siteIDs -> all slots in ad server request with the different site IDs', function() { - var first_slot = { - slotName: 'slot1', - siteID: 111111, - }; - var second_slot = { - slotName: 'slot2', - siteID: 222222, - }; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, first_slot['slotName'], [ IndexUtils.supportedSizes[0] ], { siteID: first_slot['siteID'] }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, second_slot['slotName'], [ IndexUtils.supportedSizes[1] ], { siteID: second_slot['siteID'] }), - ]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var expectedSiteID = pair.configured.params.siteID; - var actualSiteID = pair.sent.ext.siteID; - assert.equal(actualSiteID, expectedSiteID, 'request ' + pair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(actualSiteID, 'site ID is number'); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - }); - - it('test_prebid_indexAdapter_size_singleArr: single sized array -> width and height in integer in request', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', IndexUtils.supportedSizes[0]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_size_singleDim: missing width/height -> size is ignored, no ad server request for bad size', function () { - var oneDimSize = [728]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], oneDimSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, oneDimSize, 'configured bid not in impression obj size width is' + JSON.stringify(oneDimSize)); - }); - - it('test_prebid_indexAdapter_size_missing: missing size -> slot is ignored, no ad server request', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', []) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_size_negativeWidth: negative width -> size is ignored, no ad server request for bad size', function () { - var invalidSize = [-728, 90]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], invalidSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, invalidSize, 'configured bid not in impression obj size width is' + JSON.stringify(invalidSize)); - }); - - it('test_prebid_indexAdapter_size_negativeHeight: negative height -> size is ignored, no ad server request for bad size', function () { - var invalidSize = [728, -90]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], invalidSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, invalidSize, 'configured bid not in impression obj size width is' + JSON.stringify(invalidSize)); - }); - - it('test_prebid_indexAdapter_size_quoted: height and width quoted -> invalid size, no ad server request for invalid size', function () { - var otherSize = ['300', '250']; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, '0 configured bid is not in impression Obj'); - }); - - it('test_prebid_indexAdapter_size_float: height and width float -> invalid size, no ad server request for invalid size ', function () { - var otherSize = [300.1, 250]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_string_1_pba23: height and width string -> invalid size, no ad server request for invalid size ', function () { - var otherSize = [String(IndexUtils.supportedSizes[0][0]), String(IndexUtils.supportedSizes[0][1])]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[1], otherSize, IndexUtils.supportedSizes[2] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, 'all configured bids are in impression Obj'); - }); - - it('test_prebid_indexAdapter_size_string_2: whole size is string -> invalid size, no ad server request for invalid size ', function () { - var otherSize = 'gallery'; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_string_3: entire size structure is string -> no ad server request since size is invalid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', 'gallery') - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_size_hash_1: height or width hash -> invalid size, no ad server request for invalid size ', function () { - var otherSize = [{728: 1}, 90]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_hash_2: whole size hash -> invalid size, no ad server request for invalid size ', function () { - var otherSize = {728: 1, 90: 1}; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_hash_3: entire size structure is hash -> no ad server request since size is invalid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', {728: 90}) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_size_swap: swap size and width for valid so now its invalid -> unsupportedsize, no ad server request for unsupported size ', function () { - var otherSize = [90, 728]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_sameWidth: same width for all sizes in a slot -> ad server request only for supported sizes', function () { - var valid1Size = [300, 250]; - var otherSize = [300, 999]; - var valid2Size = [300, 600]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ valid1Size, otherSize, valid2Size ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_sameHeight: same height for all sizes in a slot -> ad server request only for supported sizes', function () { - var valid1Size = [120, 600]; - var otherSize = [999, 600]; - var valid2Size = [300, 600]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ valid1Size, otherSize, valid2Size ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_request_sizeID_validation_1: multiple prebid size slot, index slots with size for all prebid slots, 1 slot is not configured properly -> all size in AS request, except misconfigured slot', function () { - var slotID_1 = 52; - var slotID_2 = 53; - var slotSizes_1 = IndexUtils.supportedSizes[0]; - var slotSizes_2 = IndexUtils.supportedSizes[1]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID_1, [ slotSizes_1, slotSizes_2 ], { slotSize: [ 728, 'invalid' ] }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID_2, [ slotSizes_1, slotSizes_2 ], { slotSize: slotSizes_2 }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - assert.equal(impressionObj.length, 1, '1 slot is made in the request'); - - assert.equal(impressionObj[0].banner.w, slotSizes_2[0], 'the width made in the request matches with request: ' + slotSizes_2[0]); - assert.equal(impressionObj[0].banner.h, slotSizes_2[1], 'the height made in the request matches with request: ' + slotSizes_2[1]); - assert.equal(impressionObj[0].ext.sid, slotID_2, 'slotID in the request matches with configuration: ' + slotID_2); - assert.equal(impressionObj[0].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - }); -}); diff --git a/test/spec/modules/indexExchangeBidAdapter_video_spec.js b/test/spec/modules/indexExchangeBidAdapter_video_spec.js deleted file mode 100644 index 45231084dcc..00000000000 --- a/test/spec/modules/indexExchangeBidAdapter_video_spec.js +++ /dev/null @@ -1,953 +0,0 @@ -import { expect } from 'chai'; -import Adapter from 'modules/indexExchangeBidAdapter'; -import bidmanager from 'src/bidmanager'; -import adloader from 'src/adloader'; -import * as url from 'src/url'; - -const PREBID_REQUEST = { 'bidderCode': 'indexExchange', 'requestId': '6f4cb846-1901-4fc4-a1a4-5daf58a26e71', 'bidderRequestId': '16940e979c42d4', 'bids': [{ 'bidder': 'indexExchange', 'params': { 'video': { 'siteID': 6, 'playerType': 'HTML5', 'protocols': ['VAST2', 'VAST3'], 'maxduration': 15 } }, 'placementCode': 'video1', 'mediaType': 'video', 'sizes': [640, 480], 'bidId': '2f4e1cc0f992f2', 'bidderRequestId': '16940e979c42d4', 'requestId': '6f4cb846-1901-4fc4-a1a4-5daf58a26e71' }], 'start': 1488236870659, 'auctionStart': 1488236870656, 'timeout': 3000 }; - -const CYGNUS_REQUEST_R_PARAM = { 'id': '16940e979c42d4', 'imp': [{ 'id': '2f4e1cc0f992f2', 'ext': { 'siteID': 6, 'sid': 'pr_1_1_s' }, 'video': { 'protocols': [2, 5, 3, 6], 'maxduration': 15, 'minduration': 0, 'startdelay': 0, 'linearity': 1, 'mimes': ['video/mp4', 'video/webm'], 'w': 640, 'h': 480 } }], 'site': { 'page': 'http://localhost:9876/' }}; - -const PREBID_RESPONSE = { 'bidderCode': 'indexExchange', 'width': 640, 'height': 480, 'statusMessage': 'Bid available', 'adId': '2f4e1cc0f992f2', 'code': 'indexExchange', 'cpm': 10, 'vastUrl': 'http://vast.url' }; - -const CYGNUS_RESPONSE = { 'seatbid': [{ 'bid': [{ 'crid': '1', 'adomain': ['vastdsp.com'], 'adid': '1', 'impid': '2f4e1cc0f992f2', 'cid': '1', 'id': '1', 'ext': { 'vasturl': 'http://vast.url', 'errorurl': 'http://error.url', 'dspid': 1, 'pricelevel': '_1000', 'advbrandid': 75, 'advbrand': 'Nacho Momma' } }], 'seat': '1' }], 'cur': 'USD', 'id': '16940e979c42d4' }; - -const EMPTY_MESSAGE = 'Bid returned empty or error response'; -const ERROR_MESSAGE = 'Bid returned empty or error response'; -const AVAILABLE_MESSAGE = 'Bid available'; - -const CYGNUS_REQUEST_BASE_URL_INSECURE = 'http://as.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse&s=6&r='; - -const CYGNUS_REQUEST_BASE_URL_SECURE = 'https://as-sec.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse&s=6&r='; - -const DEFAULT_MIMES_MAP = { - FLASH: ['video/mp4', 'video/x-flv'], - HTML5: ['video/mp4', 'video/webm'] -}; -const DEFAULT_VPAID_MIMES_MAP = { - FLASH: ['application/x-shockwave-flash'], - HTML5: ['application/javascript'] -}; -const SUPPORTED_API_MAP = { - FLASH: [1, 2], - HTML5: [2] -}; - -describe('indexExchange adapter - Video', () => { - let adapter; - - beforeEach(() => adapter = new Adapter()); - - describe('request to prebid', () => { - let prebidRequest; - - beforeEach(() => { - prebidRequest = JSON.parse(JSON.stringify(PREBID_REQUEST)); - sinon.stub(adloader, 'loadScript'); - }); - - afterEach(() => { - adloader.loadScript.restore(); - }); - - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - describe('should make request with specified values', () => { - let insecureExpectedUrl = url.parse(CYGNUS_REQUEST_BASE_URL_INSECURE.concat(encodeURIComponent(JSON.stringify(CYGNUS_REQUEST_R_PARAM)))); - - let secureExpectedUrl = url.parse(CYGNUS_REQUEST_BASE_URL_SECURE.concat(encodeURIComponent(JSON.stringify(CYGNUS_REQUEST_R_PARAM)))); - - it('when valid HTML5 required bid request parameters are present', () => { - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.protocol).to.equal(insecureExpectedUrl.protocol); - expect(cygnusRequestUrl.hostname).to.equal(insecureExpectedUrl.hostname); - expect(cygnusRequestUrl.port).to.equal(insecureExpectedUrl.port); - expect(cygnusRequestUrl.pathname).to.equal(insecureExpectedUrl.pathname); - - expect(cygnusRequestUrl.search.v).to.equal(insecureExpectedUrl.search.v); - expect(cygnusRequestUrl.search.s).to.equal(insecureExpectedUrl.search.s); - expect(cygnusRequestUrl.search.fn).to.equal(insecureExpectedUrl.search.fn); - expect(cygnusRequestUrl.search.r).to.exist; - - expect(cygnusRequestUrl.search.r.id).to.equal(prebidRequest.bidderRequestId); - - expect(cygnusRequestUrl.search.r.site.page).to.have.string(CYGNUS_REQUEST_R_PARAM.site.page); - - expect(cygnusRequestUrl.search.r.imp).to.be.a('array'); - expect(cygnusRequestUrl.search.r.imp[0]).to.have.all.keys(Object.keys(CYGNUS_REQUEST_R_PARAM.imp[0])); - - expect(cygnusRequestUrl.search.r.imp[0].id).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].id); - - expect(cygnusRequestUrl.search.r.imp[0].ext.siteID).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.siteID); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - - expect(cygnusRequestUrl.search.r.imp[0].video.protocols).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.protocols); - expect(cygnusRequestUrl.search.r.imp[0].video.maxduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.maxduration); - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(DEFAULT_MIMES_MAP.HTML5); - expect(cygnusRequestUrl.search.r.imp[0].video.w).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.w); - expect(cygnusRequestUrl.search.r.imp[0].video.h).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.h); - }); - - it('when valid FLASH required bid request parameters are present', () => { - prebidRequest.bids[0].params.video.playerType = 'FLASH'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.protocol).to.equal(insecureExpectedUrl.protocol); - expect(cygnusRequestUrl.hostname).to.equal(insecureExpectedUrl.hostname); - expect(cygnusRequestUrl.port).to.equal(insecureExpectedUrl.port); - expect(cygnusRequestUrl.pathname).to.equal(insecureExpectedUrl.pathname); - - expect(cygnusRequestUrl.search.v).to.equal(insecureExpectedUrl.search.v); - expect(cygnusRequestUrl.search.s).to.equal(insecureExpectedUrl.search.s); - expect(cygnusRequestUrl.search.fn).to.equal(insecureExpectedUrl.search.fn); - expect(cygnusRequestUrl.search.r).to.exist; - - expect(cygnusRequestUrl.search.r.id).to.equal(prebidRequest.bidderRequestId); - - expect(cygnusRequestUrl.search.r.site.page).to.have.string(CYGNUS_REQUEST_R_PARAM.site.page); - - expect(cygnusRequestUrl.search.r.imp).to.be.a('array'); - expect(cygnusRequestUrl.search.r.imp[0]).to.have.all.keys(Object.keys(CYGNUS_REQUEST_R_PARAM.imp[0])); - - expect(cygnusRequestUrl.search.r.imp[0].id).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].id); - - expect(cygnusRequestUrl.search.r.imp[0].ext.siteID).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.siteID); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - - expect(cygnusRequestUrl.search.r.imp[0].video.protocols).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.protocols); - expect(cygnusRequestUrl.search.r.imp[0].video.maxduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.maxduration); - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(DEFAULT_MIMES_MAP.FLASH); - expect(cygnusRequestUrl.search.r.imp[0].video.w).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.w); - expect(cygnusRequestUrl.search.r.imp[0].video.h).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.h); - }); - - it('when required field site ID is a numeric string', () => { - prebidRequest.bids[0].params.video.siteID = '6'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.s).to.equal(insecureExpectedUrl.search.s); - expect(cygnusRequestUrl.search.r).to.exist; - - expect(cygnusRequestUrl.search.r.imp[0].ext.siteID).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.siteID); - }); - - it('when required field maxduration is a numeric string', () => { - prebidRequest.bids[0].params.video.maxduration = '15'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.maxduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.maxduration); - }); - - describe('when optional field minduration', () => { - it('is valid number', () => { - prebidRequest.bids[0].params.video.minduration = 5; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(prebidRequest.bids[0].params.video.minduration); - }); - - it('is valid number string', () => { - prebidRequest.bids[0].params.video.minduration = '5'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(prebidRequest.bids[0].params.video.minduration); - }); - }); - - describe('when optional field startdelay', () => { - it('is valid string', () => { - prebidRequest.bids[0].params.video.startdelay = 'midroll'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(prebidRequest.bids[0].params.video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string('m_1_1_s'); - }); - - it('is valid number string', () => { - prebidRequest.bids[0].params.video.startdelay = '5'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(prebidRequest.bids[0].params.video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string('m_1_1_s'); - }); - - it('is valid midroll number', () => { - prebidRequest.bids[0].params.video.startdelay = 5; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(prebidRequest.bids[0].params.video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string('m_1_1_s'); - }); - - it('is valid preroll number', () => { - prebidRequest.bids[0].params.video.startdelay = 0; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(prebidRequest.bids[0].params.video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string('pr_1_1_s'); - }); - }); - - describe('when optional field linearity', () => { - it('is valid string', () => { - prebidRequest.bids[0].params.video.linearity = 'nonlinear'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(2); - }); - }); - - describe('when optional field mimes', () => { - it('is valid mime', () => { - prebidRequest.bids[0].params.video.mimes = ['a/b']; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(prebidRequest.bids[0].params.video.mimes); - }); - }); - - describe('when optional field API list', () => { - it('is valid array', () => { - prebidRequest.bids[0].params.video.apiList = [2]; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.include.members([2]); - }); - }); - - describe('when optional field allowVPAID', () => { - it('is valid boolean', () => { - prebidRequest.bids[0].params.video.allowVPAID = true; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.include.members(DEFAULT_VPAID_MIMES_MAP.HTML5); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.include.members(SUPPORTED_API_MAP.HTML5); - }); - }); - }); - - describe('should make request with default values', () => { - describe('when optional field minduration', () => { - it('is invalid string', () => { - prebidRequest.bids[0].params.video.minduration = 'a'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.minduration = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.minduration = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.minduration = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - }); - }); - - describe('when optional field startdelay', () => { - it('is invalid string', () => { - prebidRequest.bids[0].params.video.startdelay = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is invalid number string', () => { - prebidRequest.bids[0].params.video.startdelay = '-5'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is invalid number', () => { - prebidRequest.bids[0].params.video.startdelay = -5; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.startdelay = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.startdelay = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.startdelay = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - }); - - describe('when optional field linearity', () => { - it('is invalid string', () => { - prebidRequest.bids[0].params.video.linearity = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.linearity = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.linearity = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.linearity = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - }); - }); - - describe('when optional field mimes', () => { - it('is invalid mime string', () => { - prebidRequest.bids[0].params.video.mimes = 'a'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.mimes = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.mimes = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.mimes = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - }); - }); - - describe('when optional field API list', () => { - it('is invalid array', () => { - prebidRequest.bids[0].params.video.apiList = ['cucumber']; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.apiList = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.apiList = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is string', () => { - prebidRequest.bids[0].params.video.apiList = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.apiList = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - }); - - describe('when optional field allowVPAID', () => { - it('is not boolean', () => { - prebidRequest.bids[0].params.video.allowVPAID = 'a'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.have.members(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.allowVPAID = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.have.members(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.allowVPAID = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.have.members(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.allowVPAID = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.have.members(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - }); - }) - - describe('should not make request', () => { - describe('when request', () => { - it('is empty', () => { - adapter.callBids({}); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is for no bids', () => { - adapter.callBids({ bids: [] }); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - adapter.callBids(undefined); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - - describe('when request site ID', () => { - it('is negative number', () => { - prebidRequest.bids[0].params.video.siteID = -5; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is negative number string', () => { - prebidRequest.bids[0].params.video.siteID = '-5'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is invalid string', () => { - prebidRequest.bids[0].params.video.siteID = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.siteID = undefined; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - - describe('when request player type', () => { - it('is invalid string', () => { - prebidRequest.bids[0].params.video.playerType = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is number', () => { - prebidRequest.bids[0].params.video.playerType = 1; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.playerType = undefined; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - - describe('when request protocols', () => { - it('is empty array', () => { - prebidRequest.bids[0].params.video.protocols = []; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is a string', () => { - prebidRequest.bids[0].params.video.protocols = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is an invalid array', () => { - prebidRequest.bids[0].params.video.protocols = ['cucumber']; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.protocols = undefined; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - - describe('when request maxduration', () => { - it('is a non-numeric string', () => { - prebidRequest.bids[0].params.video.maxduration = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is a negative number', () => { - prebidRequest.bids[0].params.video.maxduration = -1; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is a negative number string', () => { - prebidRequest.bids[0].params.video.maxduration = '-1'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.maxduration = undefined; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - }); - }); - - describe('response from cygnus', () => { - let response; - let request; - let width; - let height; - - beforeEach(() => { - sinon.stub(bidmanager, 'addBidResponse'); - - [width, height] = PREBID_REQUEST.bids[0].sizes; - - request = JSON.parse(JSON.stringify(PREBID_REQUEST)); - response = JSON.parse(JSON.stringify(CYGNUS_RESPONSE)); - }); - - afterEach(() => { - bidmanager.addBidResponse.restore(); - }); - - describe('should add empty bid', () => { - describe('when response', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is empty object', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse({}); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is empty array', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse({}); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is undefined', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse(undefined); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is number', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse(1); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is string', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse('cucumber'); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is explicit pass', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse({ id: CYGNUS_RESPONSE.id }); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - }); - - describe('when impid', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is mismatched', () => { - response.seatbid[0].bid[0].impid = 'cucumber'; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is undefined', () => { - response.seatbid[0].bid[0].impid = undefined; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is array', () => { - response.seatbid[0].bid[0].impid = []; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is object', () => { - response.seatbid[0].bid[0].impid = {}; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is string', () => { - response.seatbid[0].bid[0].impid = {}; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - }); - - describe('when price level', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is string', () => { - response.seatbid[0].bid[0].ext.pricelevel = 'cucumber'; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is undefined', () => { - response.seatbid[0].bid[0].ext.pricelevel = undefined; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is array', () => { - response.seatbid[0].bid[0].ext.pricelevel = []; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is object', () => { - response.seatbid[0].bid[0].ext.pricelevel = {}; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - }); - - describe('when vasturl', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is undefined', () => { - response.seatbid[0].bid[0].ext.vasturl = undefined; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is number', () => { - response.seatbid[0].bid[0].ext.vasturl = 1; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is not a url', () => { - response.seatbid[0].bid[0].ext.vasturl = 'cucumber'; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - }); - }); - - describe('should add available bid', () => { - describe('when response', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is success', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse(CYGNUS_RESPONSE); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', PREBID_RESPONSE.statusMessage); - expect(response).to.have.property('cpm', PREBID_RESPONSE.cpm); - expect(response).to.have.property('vastUrl', PREBID_RESPONSE.vastUrl); - expect(response).to.have.property('width', PREBID_RESPONSE.width); - expect(response).to.have.property('height', PREBID_RESPONSE.height); - }); - }); - }); - }); -}); diff --git a/test/spec/modules/inneractiveBidAdapter_spec.js b/test/spec/modules/inneractiveBidAdapter_spec.js deleted file mode 100644 index aef9a6b7b49..00000000000 --- a/test/spec/modules/inneractiveBidAdapter_spec.js +++ /dev/null @@ -1,291 +0,0 @@ -/* globals context */ - -import {expect} from 'chai'; -import {default as InneractiveAdapter} from 'modules/inneractiveBidAdapter'; -import bidmanager from 'src/bidmanager'; - -// Using plain-old-style functions, why? see: http://mochajs.org/#arrow-functions -describe('InneractiveAdapter', function () { - let adapter, - bidRequest; - - beforeEach(function () { - adapter = new InneractiveAdapter(); - bidRequest = { - bidderCode: 'inneractive', - bids: [ - { - bidder: 'inneractive', - params: { - appId: '', - }, - placementCode: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300, 600]], - bidId: '507e8db167d219', - bidderRequestId: '49acc957f92917', - requestId: '51381cd0-c29c-405b-9145-20f60abb1e76' - }, - { - bidder: 'inneractive', - params: { - noappId: '...', - }, - placementCode: 'div-gpt-ad-1460505661639-0', - sizes: [[728, 90], [970, 90]], - bidId: '507e8db167d220', - bidderRequestId: '49acc957f92917', - requestId: '51381cd0-c29c-405b-9145-20f60abb1e76' - }, - { - bidder: 'inneractive', - params: { - APP_ID: 'Inneractive_AndroidHelloWorld_Android', - spotType: 'rectangle', - customParams: { - Portal: 7002, - } - }, - placementCode: 'div-gpt-ad-1460505748561-0', - sizes: [[320, 50], [300, 600]], - bidId: '507e8db167d221', - bidderRequestId: '49acc957f92917', - requestId: '51381cd0-c29c-405b-9145-20f60abb1e76' - }, - { - bidder: 'inneractive', - params: { - appId: 'Inneractive_IosHelloWorld_iPhone', - spotType: 'banner', // Just for coverage considerations, no real impact in production - customParams: { - portal: 7001, - gender: '' - } - }, - placementCode: 'div-gpt-ad-1460505661639-0', - sizes: [[728, 90], [970, 90]], - bidId: '507e8db167d222', - bidderRequestId: '49acc957f92917', - requestId: '51381cd0-c29c-405b-9145-20f60abb1e76' - }] - }; - }); - - describe('Reporter', function () { - context('on HBPreBidError event', function () { - it('should contain "mbwError" the inside event report url', function () { - const Reporter = InneractiveAdapter._getUtils().Reporter; - const extraDetailsParam = { - 'appId': 'CrunchMind_DailyDisclosure_other', - 'spotType': 'rectangle', - 'portal': 7002 - }; - let eventReportUrl = Reporter.getEventUrl('HBPreBidError', extraDetailsParam); - expect(eventReportUrl).to.include('mbwError'); - }); - }); - }); - - it('should return an instance of this adapter having a "callBids" method', function () { - expect(adapter) - .to.be.instanceOf(InneractiveAdapter).and - .to.have.property('callBids').and - .to.be.a('function'); - }); - - describe('when sending out bid requests to the ad server', function () { - let bidRequests, - xhr; - - beforeEach(function () { - bidRequests = []; - xhr = sinon.useFakeXMLHttpRequest(); - xhr.onCreate = (request) => { - bidRequests.push(request); - }; - }); - - afterEach(function () { - xhr.restore(); - }); - - context('when there are no bid requests', function () { - it('should not issue a request', function () { - const Reporter = InneractiveAdapter._getUtils().Reporter; - Reporter.getEventUrl('HBPreBidError', { - 'appId': 'CrunchMind_DailyDisclosure_other', - 'spotType': 'rectangle', - 'portal': 7002 - }); - - delete bidRequest.bids; - adapter.callBids(bidRequest); - - expect(bidRequests).to.be.empty; - }); - }); - - context('when there is at least one bid request', function () { - it('should filter out invalid bids', function () { - const INVALID_BIDS_COUNT = 2; - sinon.spy(adapter, '_isValidRequest'); - adapter.callBids(bidRequest); - - for (let id = 0; id < INVALID_BIDS_COUNT; id++) { - expect(adapter._isValidRequest.getCall(id).returned(false)).to.be.true; - } - - adapter._isValidRequest.restore(); - }); - - it('should store all valid bids internally', function () { - adapter.callBids(bidRequest); - expect(Object.keys(adapter.bidByBidId).length).to.equal(2); - }); - - it('should issue ad requests to the ad server for every valid bid', function () { - adapter.callBids(bidRequest); - expect(bidRequests).to.have.lengthOf(2); - }); - }); - }); - - describe('when registering the bids that are returned with Prebid.js', function () { - const BID_DETAILS_ARG_INDEX = 1; - let server; - - beforeEach(function () { - sinon.stub(bidmanager, 'addBidResponse'); - server = sinon.fakeServer.create(); - }); - - afterEach(function () { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - context('when the bid is valid', function () { - let adServerResponse, - headers, - body; - - beforeEach(function () { - adServerResponse = { - headers: { - 'X-IA-Ad-Height': 250, - 'X-IA-Ad-Width': 300, - 'X-IA-Error': 'OK', - 'X-IA-Pricing': 'CPM', - 'X-IA-Pricing-Currency': 'USD', - 'X-IA-Pricing-Value': 0.0005 - }, - body: { - ad: { - html: '' - }, - config: { - tracking: { - impressions: [ - 'http://event.inner-active.mobi/simpleM2M/reportEvent?eventArchetype=impress…pe=3&network=Inneractive_CS&acp=&pcp=&secure=false&rtb=false&houseAd=false' - ], - clicks: [ - 'http://event.inner-active.mobi/simpleM2M/reportEvent?eventArchetype=richMed…pe=3&network=Inneractive_CS&acp=&pcp=&secure=false&rtb=false&houseAd=false', - '' - ], - passback: 'http://event.inner-active.mobi/simpleM2M/reportEvent?eventArchetype=passbac…pe=3&network=Inneractive_CS&acp=&pcp=&secure=false&rtb=false&houseAd=false' - }, - moat: { - countryCode: 'IL' - } - } - } - }; - headers = adServerResponse.headers; - body = JSON.stringify(adServerResponse.body); - }); - - it('should register bid responses with a status code of 1', function () { - server.respondWith([200, headers, body]); - adapter.callBids(bidRequest); - server.respond(); - - let firstRegisteredBidResponse = bidmanager.addBidResponse.firstCall.args[BID_DETAILS_ARG_INDEX]; - expect(firstRegisteredBidResponse) - .to.have.property('statusMessage', 'Bid available'); - }); - - it('should use the first element inside the bid request size array when no (width,height) is returned within the headers', function () { - delete headers['X-IA-Ad-Height']; - delete headers['X-IA-Ad-Width']; - server.respondWith([200, headers, body]); - adapter.callBids(bidRequest); - server.respond(); - - let firstRegisteredBidResponse = bidmanager.addBidResponse.firstCall.args[BID_DETAILS_ARG_INDEX]; - expect(firstRegisteredBidResponse).to.have.property('width', 320); - expect(firstRegisteredBidResponse).to.have.property('height', 50); - }); - }); - - context('when the bid is invalid', function () { - let passbackAdServerResponse, - headers, - body; - - beforeEach(function () { - passbackAdServerResponse = { - headers: { - 'X-IA-Error': 'House Ad', - 'X-IA-Content': 600145, - 'X-IA-Cid': 99999, - 'X-IA-Publisher': 206536, - 'Content-Type': 'application/json; charset=UTF-8', - 'X-IA-Session': 6512147119979250840, - 'X-IA-AdNetwork': 'inneractive360' - }, - body: { - 'ad': { - 'html': '' - }, - 'config': { - 'passback': 'http://event.inner-active.mobi/simpleM2M/reportEvent?eventArchetype=passbac…pe=3&network=Inneractive_CS&acp=&pcp=&secure=false&rtb=false&houseAd=false' - } - } - }; - headers = passbackAdServerResponse.headers; - body = JSON.stringify(passbackAdServerResponse.body); - }); - - it('should register bid responses with a status code of 2', function () { - server.respondWith([200, headers, body]); - adapter.callBids(bidRequest); - server.respond(); - - let firstRegisteredBidResponse = bidmanager.addBidResponse.firstCall.args[BID_DETAILS_ARG_INDEX]; - expect(firstRegisteredBidResponse) - .to.have.property('statusMessage', 'Bid returned empty or error response'); - }); - - it('should handle responses from our server in case we had no ad to offer', function () { - const n = bidRequest.bids.length; - bidRequest.bids[n - 1].params.appId = 'Komoona_InquisitrRectangle2_other'; - server.respondWith([200, headers, body]); - adapter.callBids(bidRequest); - server.respond(); - - let secondRegisteredBidResponse = bidmanager.addBidResponse.secondCall.args[BID_DETAILS_ARG_INDEX]; - expect(secondRegisteredBidResponse) - .to.have.property('statusMessage', 'Bid returned empty or error response'); - }); - - it('should handle JSON.parse errors', function () { - server.respondWith(''); - adapter.callBids(bidRequest); - server.respond(); - - const firstRegisteredBidResponse = bidmanager.addBidResponse.firstCall.args[BID_DETAILS_ARG_INDEX]; - expect(firstRegisteredBidResponse) - .to.have.property('statusMessage', 'Bid returned empty or error response'); - }); - }); - }); -}); diff --git a/test/spec/modules/innityBidAdapter_spec.js b/test/spec/modules/innityBidAdapter_spec.js deleted file mode 100644 index 7e4ac147c68..00000000000 --- a/test/spec/modules/innityBidAdapter_spec.js +++ /dev/null @@ -1,157 +0,0 @@ -describe('innity adapter tests', function () { - var expect = require('chai').expect; - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - var adapter = require('modules/innityBidAdapter'); - var adLoader = require('src/adloader'); - var bidmanager = require('src/bidmanager'); - - var stubLoadScript; - - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - describe('creation of bid url', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._bidsReceived = []; - } - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - - it('bid request for single placement', function () { - var params = { - bids: [{ - placementCode: '/19968336/header-bid-tag-0', - sizes: [[300, 250]], - bidId: 'b12345', - bidder: 'innity', - params: { pub: '267', zone: '62546' } - }] - }; - - adapter().callBids(params); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledOnce(stubLoadScript); - - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrlQueryString).to.have.property('pub').and.to.equal('267'); - expect(parsedBidUrlQueryString).to.have.property('zone').and.to.equal('62546'); - expect(parsedBidUrlQueryString).to.have.property('width').and.to.equal('300'); - expect(parsedBidUrlQueryString).to.have.property('height').and.to.equal('250'); - }); - }); - - describe('handling bid response', function () { - it('should return complete bid response', function() { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - var params = { - bids: [{ - placementCode: '/19968336/header-bid-tag-0', - sizes: [[300, 250]], - bidId: 'b12345', - bidder: 'innity', - params: { pub: '267', zone: '62546' } - }] - }; - - var response = { - cpm: 100, - width: 300, - height: 250, - callback_uid: 'b12345', - tag: ' - `); - expect(bidResponse.cpm).to.equal(1.0); - expect(bidResponse.width).to.equal(160); - expect(bidResponse.height).to.equal(600); - }); - }); - }); -}); diff --git a/test/spec/modules/mantisBidAdapter_spec.js b/test/spec/modules/mantisBidAdapter_spec.js deleted file mode 100644 index ac072aacccf..00000000000 --- a/test/spec/modules/mantisBidAdapter_spec.js +++ /dev/null @@ -1,168 +0,0 @@ -'use strict'; - -describe('mantis adapter tests', function () { - const expect = require('chai').expect; - const Adapter = require('modules/mantisBidAdapter'); - const bidmanager = require('src/bidmanager'); - const adloader = require('src/adloader'); - const constants = require('src/constants.json'); - - var mantis, sandbox; - - beforeEach(() => { - mantis = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - - delete window.context; - delete window.mantis_link; - delete window.mantis_breakpoint; - delete window.mantis_uuid; - }); - - var callBidExample = { - bidderCode: 'mantis', - bids: [ - { - bidId: 'bidId1', - bidder: 'mantis', - placementCode: 'foo', - sizes: [[728, 90]], - params: { - property: '1234', - zoneId: 'zone1' - } - }, - { - bidId: 'bidId2', - bidder: 'mantis', - placementCode: 'bar', - sizes: [[300, 600], [300, 250]], - params: { - property: '1234', - zoneId: 'zone2' - } - } - ] - }; - - describe('callBids', () => { - it('should create appropriate bid responses', () => { - sandbox.stub(bidmanager, 'addBidResponse'); - sandbox.stub(adloader, 'loadScript', function (url) { - var jsonp = eval(decodeURIComponent(url.match(/jsonp=(.*)&property/)[1])); - - jsonp({ - ads: { - bidId1: { - cpm: 1, - html: '', - width: 300, - height: 600 - } - } - }); - }); - - mantis.callBids(callBidExample); - - sinon.assert.calledTwice(bidmanager.addBidResponse); - - expect(bidmanager.addBidResponse.firstCall.args[0]).to.eql('foo'); - - var bid1 = bidmanager.addBidResponse.firstCall.args[1]; - expect(bid1.getStatusCode()).to.eql(constants.STATUS.GOOD); - expect(bid1.bidderCode).to.eql('mantis'); - expect(bid1.cpm).to.eql(1); - expect(bid1.ad).to.eql(''); - expect(bid1.width).to.eql(300); - expect(bid1.height).to.eql(600); - - expect(bidmanager.addBidResponse.secondCall.args[0]).to.eql('bar'); - - var bid2 = bidmanager.addBidResponse.secondCall.args[1]; - expect(bid2.getStatusCode()).to.eql(constants.STATUS.NO_BID); - expect(bid2.bidderCode).to.eql('mantis'); - }); - - it('should load script with relevant bid data', () => { - sandbox.stub(adloader, 'loadScript'); - - mantis.callBids(callBidExample); - - sinon.assert.calledOnce(adloader.loadScript); - - var serverCall = adloader.loadScript.firstCall.args[0]; - - expect(serverCall).to.match(/buster=[0-9]+&/); - expect(serverCall).to.match(/tz=-?[0-9]+&/); - expect(serverCall).to.match(/secure=(true|false)&/); - expect(serverCall).to.string('property=1234&'); - expect(serverCall).to.string('bids[0][bidId]=bidId1&'); - expect(serverCall).to.string('bids[0][sizes][0][width]=728&'); - expect(serverCall).to.string('bids[0][sizes][0][height]=90&'); - expect(serverCall).to.string('bids[0][config][zoneId]=zone1&'); - expect(serverCall).to.string('bids[1][bidId]=bidId2&'); - expect(serverCall).to.string('bids[1][sizes][0][width]=300&'); - expect(serverCall).to.string('bids[1][sizes][0][height]=600&'); - expect(serverCall).to.string('bids[1][sizes][1][width]=300&'); - expect(serverCall).to.string('bids[1][sizes][1][height]=250&'); - expect(serverCall).to.string('bids[1][config][zoneId]=zone2&'); - expect(serverCall).to.string('version=1'); - }); - - /* tests below are to just adhere to code coverage requirements, but it is already tested in our own libraries/deployment process */ - it('should send uuid from window if set', () => { - sandbox.stub(adloader, 'loadScript'); - - window.mantis_uuid = '4321'; - - mantis.callBids(callBidExample); - - sinon.assert.calledOnce(adloader.loadScript); - - var serverCall = adloader.loadScript.firstCall.args[0]; - - expect(serverCall).to.string('uuid=4321&'); - }); - - it('should send mobile = true if breakpoint is hit', () => { - sandbox.stub(adloader, 'loadScript'); - - window.mantis_link = true; // causes iframe detection to not work - window.mantis_breakpoint = 100000000; // force everything to be mobile - - mantis.callBids(callBidExample); - - sinon.assert.calledOnce(adloader.loadScript); - - var serverCall = adloader.loadScript.firstCall.args[0]; - - expect(serverCall).to.string('mobile=true&'); - }); - - it('should send different params if amp is detected', () => { - sandbox.stub(adloader, 'loadScript'); - - window.context = { - tagName: 'AMP-AD', - location: { - href: 'bar', - referrer: 'baz' - } - }; - - mantis.callBids(callBidExample); - - sinon.assert.calledOnce(adloader.loadScript); - - var serverCall = adloader.loadScript.firstCall.args[0]; - - expect(serverCall).to.string('mobile=true&'); - // expect(serverCall).to.string('url=bar&'); - }); - }); -}); diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js deleted file mode 100644 index c9381eb3c5f..00000000000 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ /dev/null @@ -1,185 +0,0 @@ -import { expect } from 'chai'; -import * as ajax from 'src/ajax'; -import bidManager from 'src/bidmanager'; -import MarsmediaBidAdapter from '../../../modules/marsmediaBidAdapter'; -import CONSTANTS from 'src/constants.json'; -import adLoader from 'src/adloader'; - -describe('MarsMedia adapter implementation', () => { - let sandbox, - server, - marsmediaAdapter = new MarsmediaBidAdapter(), - BIDDER_REQUEST, - EMPTY_RESPONSE, - VALID_RESPONSE; - - beforeEach(() => { - BIDDER_REQUEST = { - bidderCode: 'marsmedia', - placementCode: 'div-1', - bids: [ - { - bidder: 'marsmedia', - params: { - publisherID: '1111', - floor: 0 - }, - sizes: [[320, 50]] - } - ] - }; - - EMPTY_RESPONSE = { - 'seatbid': [ - { - 'bid': [ - {} - ] - } - ], - 'bidid': '5616322932456153', - 'cur': 'USD' - }; - - VALID_RESPONSE = { - 'seatbid': [ - { - 'bid': [ - { - 'id': '1', - 'impid': '0c5b2f42-057b-0429-0694-0b42029af9e8', - 'price': 5, - 'adid': '11890', - 'nurl': 'http://ping-hq-2.rtbanalytics.com/bidder/ping_rtb.php?bid=3mhdom&wn=1&a_id=e7a96e1a-9777-5c48-41bc-91151c5b0b8e&gid=&r_id=9625963823905202&a_bp=5.0&a_p=${AUCTION_PRICE}&dcid=1&d=real1.rtbsrv.com&s_id=26&b_r_id=11890&v_id=0&a_pos=&u=5956487987&enp=uQ5qwrn5TQ&oapi=IzJ6W%3D%3DwN4kzN4QjN1kTN23bqB&oai=R2hHylhjYwIWNjFTNxETOtMmYxQTL4QzY10yN3cTOtEWMlZTOhdTZeXpeu&aname=asV6EXbmbP&abundle=ZywyWBnMaH&sdomain=0vQGB%3D%3DQbvNmL2J3ciRncuEDbhVmcKD4pf&spid=iPR8W%3D%3DwN4kzN4QjN1kTNKsMet&s_s_id=5956487987&dcarrier=HMjOzDJYic&city=G9diP6gJT7&uctm=1495112599131&b_id=306&cui=jYGqt%3D0SL8hqk6&hostn=bw7NZyEDbhVmc5j4VD&dspr=X2WmAw4CMCM32y', - 'adm': '', - 'adomain': ['wooga.com'], - 'iurl': 'http://feed-848915510.us-east-1.elb.amazonaws.com/banners/2290/jelly_splash/2861815_jelly-splash-iphone-app_android-app-install_creatives-jelly_320x50.jpg', - 'cid': '11890', - 'crid': '11890', - 'attr': [16] - } - ], - 'seat': '306' - } - ], - 'bidid': '9625963823905202', - 'cur': 'USD' - }; - - sandbox = sinon.sandbox.create(); - server = sinon.fakeServer.create(); - marsmediaAdapter = marsmediaAdapter.createNew(); - - sandbox.stub(bidManager, 'addBidResponse'); - }); - - afterEach(() => { - sandbox.restore(); - server.restore(); - }); - - describe('should receive a valid request bid -', () => { - it('no params', () => { - var bidder_request = BIDDER_REQUEST; - delete bidder_request.bids[0].params; - - expect(marsmediaAdapter.buildCallParams.bind(marsmediaAdapter, bidder_request.bids[0])).to.throw('No params'); - }); - - it('no sizes', () => { - var bidder_request = BIDDER_REQUEST; - delete bidder_request.bids[0].sizes; - - expect(marsmediaAdapter.buildCallParams.bind(marsmediaAdapter, bidder_request.bids[0])).to.throw('No sizes'); - }); - - it('no floor', () => { - var bidder_request = BIDDER_REQUEST; - delete bidder_request.bids[0].params.floor; - - expect(marsmediaAdapter.buildCallParams.bind(marsmediaAdapter, bidder_request.bids[0])).to.throw('No floor'); - }); - - it('floor should be number', () => { - var bidder_request = BIDDER_REQUEST; - bidder_request.bids[0].params.floor = 'str'; - - expect(marsmediaAdapter.buildCallParams.bind(marsmediaAdapter, bidder_request.bids[0])).to.throw('Floor must be numeric value'); - }); - }); - - describe('should receive a valid response -', () => { - it('error building call params', () => { - var request = marsmediaAdapter.buildCallParams(BIDDER_REQUEST.bids[0]); - - expect(request).that.is.an('string'); - - var request_obj = JSON.parse(request); - expect(request_obj).that.is.an('object'); - expect(request_obj).to.have.deep.property('id'); - expect(request_obj).to.have.deep.property('cur'); - - expect(request_obj).to.have.deep.property('imp'); - expect(request_obj['imp'][0]).to.have.deep.property('bidfloor'); - - expect(request_obj).to.have.deep.property('device'); - expect(request_obj).to.have.deep.property('user'); - expect(request_obj).to.have.deep.property('app'); - expect(request_obj).to.have.deep.property('publisher'); - }); - - it('error register bid', () => { - server.respondWith(JSON.stringify(VALID_RESPONSE)); - marsmediaAdapter.callBids(BIDDER_REQUEST); - server.respond(); - - expect(bidManager.addBidResponse.calledOnce).to.equal(true); - expect(bidManager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - }); - }); - - describe('should handle bad response with - ', () => { - it('broken response', () => { - marsmediaAdapter.callBids(BIDDER_REQUEST); - - server.respondWith('{"id":'); - server.respond(); - - expect(bidManager.addBidResponse.calledOnce).to.equal(true); - expect(bidManager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - }); - - it('empty response', () => { - marsmediaAdapter.callBids(BIDDER_REQUEST); - - server.respondWith('{}'); - server.respond(); - - expect(bidManager.addBidResponse.calledOnce).to.equal(true); - expect(bidManager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - }); - - it('empty bids', () => { - marsmediaAdapter.callBids(BIDDER_REQUEST); - - server.respondWith(JSON.stringify(EMPTY_RESPONSE)); - - server.respond(); - let response = JSON.parse(server.response[2]); - - expect(response).to.have.property('seatbid').that.is.an('array').with.lengthOf(1); - expect(response['seatbid'][0]).to.have.property('bid').to.be.lengthOf(1); - }); - - it('no adm', () => { - server.respondWith(JSON.stringify(VALID_RESPONSE)); - - server.respond(); - let response = JSON.parse(server.response[2]); - - expect(response).to.have.property('seatbid').that.is.an('array').with.lengthOf(1); - expect(response['seatbid'][0]).to.have.property('bid').to.be.lengthOf(1); - expect(response['seatbid'][0]['bid'][0]).to.have.property('adm'); - }); - }); -}); diff --git a/test/spec/modules/memeglobalBidAdapter_spec.js b/test/spec/modules/memeglobalBidAdapter_spec.js deleted file mode 100644 index 0dc2d6f1541..00000000000 --- a/test/spec/modules/memeglobalBidAdapter_spec.js +++ /dev/null @@ -1,170 +0,0 @@ -describe('memeglobal adapter tests', function () { - const expect = require('chai').expect; - const adapter = require('modules/memeglobalBidAdapter'); - const bidmanager = require('src/bidmanager'); - const adLoader = require('src/adloader'); - var bidderName = 'memeglobal'; - - let stubLoadScript; - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - function getBidSetForBidder() { - return $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === bidderName); - } - - function checkBidsRequestedInit() { - var bidSet = getBidSetForBidder(); - if (!bidSet) { - var bidderRequest = { - start: null, - requestId: null, - bidder: 'memeglobal', - bidderCode: 'memeglobal', - bids: [] - }; - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - } - } - - describe('functions and initialization', function () { - it('should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.mgres).to.exist.and.to.be.a('function'); - }); - - it('callBids with params', function () { - var params = { - bidderCode: 'memeglobal', - bidder: 'memeglobal', - bids: [{ - bidId: '3c9408cdbf2f68', - sizes: [[300, 250]], - bidder: 'memeglobal', - params: { siteId: '3608', adSizes: '300x250' }, - requestId: '10b327aa396609', - placementCode: 'header-bid-tag-0' - } - ] - }; - - adapter().callBids(params); - sinon.assert.calledOnce(stubLoadScript); - }); - - it('callBids empty params', function () { - var params = { - bidderCode: 'memeglobal', - bidder: 'memeglobal', - bids: [{ - bidId: '3c9408cdbf2f68', - sizes: [[300, 250]], - bidder: 'memeglobal', - params: { siteId: '3608', adSizes: '300x250' }, - requestId: '10b327aa396609', - placementCode: 'header-bid-tag-0' - } - ] - }; - - adapter().callBids({}); - expect(stubLoadScript.callCount).to.equal(0); - }); - }); - - describe('memeglobalResponse', function () { - it('should not add bid responses if no bids returned', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - checkBidsRequestedInit(); - - var bid = { - bidId: 'bidId1', - bidder: 'memeglobal', - params: { - tagid: '007' - }, - sizes: [[300, 250]], - placementCode: 'test-1' - } - // no bids returned in the response. - var response = { - 'id': '54321', - 'seatbid': [] - }; - var bidSet = getBidSetForBidder(); - bidSet.bids.push(bid); - - // adapter needs to be called for stub registration. - adapter() - - $$PREBID_GLOBAL$$.mgres(response); - - expect(stubAddBidResponse.getCall(0)).to.equal(null); - // var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - // expect(bidPlacementCode).to.equal('test-1'); - // - // var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - // expect(bidObject1.getStatusCode()).to.equal(2); - // expect(bidObject1.bidderCode).to.equal('memeglobal'); - - stubAddBidResponse.calledThrice; - stubAddBidResponse.restore(); - }); - - it('should add a bid response for bids returned and empty bid responses for the rest', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - checkBidsRequestedInit(); - - var bid = { - bidId: 'bidId2', - bidder: 'memeglobal', - params: { - tagid: '315045' - }, - sizes: [[320, 50]], - placementCode: 'test-2' - }; - - // Returning a single bid in the response. - var response = { - 'id': '54321111', - 'seatbid': [ { - 'bid': [ { - 'id': '1111111', - 'impid': 'bidId2', - 'price': 0.09, - 'nurl': 'http://url', - 'adm': 'ad-code', - 'h': 250, - 'w': 300, - 'ext': { } - } ] - } ] - }; - - var bidSet = getBidSetForBidder(); - bidSet.bids.push(bid); - adapter() - $$PREBID_GLOBAL$$.mgres(response); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - expect(bidPlacementCode1).to.equal('test-2'); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('memeglobal'); - expect(bidObject1.creative_id).to.equal('1111111'); - expect(bidObject1.cpm).to.equal(0.09); - expect(bidObject1.height).to.equal(250); - expect(bidObject1.width).to.equal(300); - expect(bidObject1.ad).to.equal('ad-code'); - - stubAddBidResponse.calledThrice; - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/orbitsoftBidAdapter_spec.js b/test/spec/modules/orbitsoftBidAdapter_spec.js deleted file mode 100644 index 4b24787f56b..00000000000 --- a/test/spec/modules/orbitsoftBidAdapter_spec.js +++ /dev/null @@ -1,354 +0,0 @@ -describe('Orbitsoft Adapter tests', function () { - const expect = require('chai').expect; - const assert = require('chai').assert; - const OrbitsoftAdapter = require('modules/orbitsoftBidAdapter'); - const bidmanager = require('src/bidmanager'); - const adloader = require('src/adloader'); - const CONSTANTS = require('src/constants.json'); - - const contentCallEndPoint = 'http://orbitsoft.com/ads/show/content?'; - const jptCallEndPoint = 'http://orbitsoft.com/ads/show/hb?'; - - before(() => sinon.stub(document.body, 'appendChild')); - after(() => document.body.appendChild.restore()); - - describe('test orbitsoft callback response', function () { - it('should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.handleOASCB).to.exist.and.to.be.a('function'); - }); - - it('should add empty bid responses if no bids returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft1', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Empty bid response - let response = { - callback_uid: 'bidIdOrbitsoft1', - cpm: 0 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.handleOASCB(response); - - let bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - let bidResponse1 = stubAddBidResponse.getCall(0).args[1]; - expect(bidPlacementCode1).to.equal('test-div-12345'); - expect(bidResponse1.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(bidResponse1.bidderCode).to.equal('orbitsoft'); - stubAddBidResponse.restore(); - }); - - it('should add empty bid responses if no bidId returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft1', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Empty bid response - let response = { - cpm: 0 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.handleOASCB(response); - - expect(stubAddBidResponse.getCall(0)).to.equal(null); - stubAddBidResponse.restore(); - }); - }); - - it('should add bid responses if bids are returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft1', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Bid response - let response = { - callback_uid: 'bidIdOrbitsoft1', - content_url: contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0', - cpm: 0.03, - width: 300, - height: 250 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.handleOASCB(response); - - let bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - let bidResponse1 = stubAddBidResponse.getCall(0).args[1]; - let bid1width = 300; - let bid1height = 250; - let cpm = 0.03; - let content_url = contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0'; - expect(bidPlacementCode1).to.equal('test-div-12345'); - expect(bidResponse1.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidResponse1.bidderCode).to.equal('orbitsoft'); - expect(bidResponse1.width).to.equal(bid1width); - expect(bidResponse1.height).to.equal(bid1height); - expect(bidResponse1.cpm).to.equal(cpm); - expect(bidResponse1.adUrl).to.equal(content_url); - stubAddBidResponse.restore(); - }); - - it('should call loadscript with the correct params', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - let params = { - bids: [ - { - sizes: [[300, 250], [300, 600]], - params: { - placementId: '16', - requestUrl: jptCallEndPoint - } - } - ] - }; - adapter.callBids(params); - - sinon.assert.calledOnce(spyLoadScript); - - let bidUrl = spyLoadScript.getCall(0).args[0]; - expect(bidUrl).to.include(jptCallEndPoint); - expect(bidUrl).to.include('scid=16'); - expect(bidUrl).to.include('size=300x250'); - expect(bidUrl).to.include('loc'); - spyLoadScript.restore(); - }); - - describe('test orbitsoft callback with params', function () { - it('should not call loadscript when inputting with empty params', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - adapter.callBids({}); - assert(!spyLoadScript.called); - spyLoadScript.restore(); - }); - - it('should not call loadscript when inputting without requestUrl param ', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - let params = { - bids: [ - { - params: { - placementId: '16' - } - } - ] - }; - adapter.callBids(params); - assert(!spyLoadScript.called); - spyLoadScript.restore(); - }); - - it('should not call loadscript when inputting with empty params by string ', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - adapter.callBids(''); - assert(!spyLoadScript.called); - spyLoadScript.restore(); - }); - - it('should call loadscript without size in params', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - let params = { - bids: [ - { - params: { - placementId: '16', - requestUrl: jptCallEndPoint - } - } - ] - }; - adapter.callBids(params); - - sinon.assert.calledOnce(spyLoadScript); - - let bidUrl = spyLoadScript.getCall(0).args[0]; - expect(bidUrl).to.include(jptCallEndPoint); - expect(bidUrl).to.include('scid=16'); - expect(bidUrl).to.not.include('size='); - expect(bidUrl).to.include('loc'); - spyLoadScript.restore(); - }); - - it('should add style params to adUrl if bids are returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft2', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint, - style: { - title: { - family: 'Tahoma', - size: 'medium', - weight: 'normal', - style: 'normal', - color: '0053F9' - }, - description: { - family: 'Tahoma', - size: 'medium', - weight: 'normal', - style: 'normal', - color: '0053F9' - }, - url: { - family: 'Tahoma', - size: 'medium', - weight: 'normal', - style: 'normal', - color: '0053F9' - }, - colors: { - background: 'ffffff', - border: 'E0E0E0', - link: '5B99FE' - } - } - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Bid response with content_url - let response = { - callback_uid: 'bidIdOrbitsoft2', - content_url: contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0', - cpm: 0.03, - width: 300, - height: 250 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - $$PREBID_GLOBAL$$.handleOASCB(response); - - let bidResponse1 = stubAddBidResponse.getCall(0).args[1]; - let adUrl = bidResponse1.adUrl; - let content_url = contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0'; - expect(adUrl).to.include(content_url); - expect(adUrl).to.include('f1=Tahoma'); - expect(adUrl).to.include('fs1=medium'); - expect(adUrl).to.include('w1=normal'); - expect(adUrl).to.include('s1=normal'); - expect(adUrl).to.include('c3=0053F9'); - expect(adUrl).to.include('f2=Tahoma'); - expect(adUrl).to.include('fs2=medium'); - expect(adUrl).to.include('w2=normal'); - expect(adUrl).to.include('s2=normal'); - expect(adUrl).to.include('c4=0053F9'); - expect(adUrl).to.include('f3=Tahoma'); - expect(adUrl).to.include('fs3=medium'); - expect(adUrl).to.include('w3=normal'); - expect(adUrl).to.include('s3=normal'); - expect(adUrl).to.include('c5=0053F9'); - expect(adUrl).to.include('c2=ffffff'); - expect(adUrl).to.include('c1=E0E0E0'); - expect(adUrl).to.include('c6=5B99FE'); - - stubAddBidResponse.restore(); - }); - - it('should add custom params to adUrl if bids are returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft3', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint, - customParams: { - macro_name: 'macro_value' - } - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Bid response with custom params - let response = { - callback_uid: 'bidIdOrbitsoft3', - content_url: contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0', - cpm: 0.03, - width: 300, - height: 250 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.handleOASCB(response); - - let bidResponse1 = stubAddBidResponse.getCall(0).args[1]; - let adUrl = bidResponse1.adUrl; - let content_url = contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0'; - expect(adUrl).to.include(content_url); - expect(adUrl).to.include('c.macro_name=macro_value'); - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/piximediaBidAdapter_spec.js b/test/spec/modules/piximediaBidAdapter_spec.js deleted file mode 100644 index 14834c81714..00000000000 --- a/test/spec/modules/piximediaBidAdapter_spec.js +++ /dev/null @@ -1,416 +0,0 @@ -describe('Piximedia adapter tests', function () { - var expect = require('chai').expect; - var urlParse = require('url-parse'); - - // var querystringify = require('querystringify'); - - var Adapter = require('modules/piximediaBidAdapter'); - var adLoader = require('src/adloader'); - var bidmanager = require('src/bidmanager'); - var utils = require('src/utils'); - var CONSTANTS = require('src/constants.json'); - - let stubLoadScript; - - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - describe('creation of prebid url', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._bidsReceived = []; - } - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - if (typeof ($$PREBID_GLOBAL$$._adsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._adsReceived = []; - } - - it('should call the Piximedia prebid URL once on valid calls', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', prebidUrl: '//resources.pm/tests/prebid/bids.js' }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - sinon.assert.calledOnce(stubLoadScript); - }); - - it('should not call the Piximedia prebid URL once on invalid calls', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { prebidUrl: '//resources.pm/tests/prebid/bids.js' }, // this is invalid: site and placement ID are missing - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - sinon.assert.notCalled(stubLoadScript); - }); - - it('should call the correct Prebid URL when using the default URL', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST' }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - - expect(parsedBidUrl.hostname).to.equal('static.adserver.pm'); - expect(parsedBidUrl.query).to.equal(''); - expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/jsonp=$$PREBID_GLOBAL$$.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); - }); - - it('should call the correct Prebid URL when using the default URL with a deal and custom data', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', dealId: 1295, custom: 'bespoke', custom2: function() { return 'bespoke2'; }, custom3: null, custom4: function() {} }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - - expect(parsedBidUrl.hostname).to.equal('static.adserver.pm'); - expect(parsedBidUrl.query).to.equal(''); - expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/l_id=1295/custom=bespoke/custom2=bespoke2/custom3=/custom4=/jsonp=$$PREBID_GLOBAL$$.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); - }); - - it('should call the correct Prebid URL when using the default URL and overridding sizes', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', sizes: [[300, 600], [728, 90]] }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - - expect(parsedBidUrl.hostname).to.equal('static.adserver.pm'); - expect(parsedBidUrl.query).to.equal(''); - expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/jsonp=$$PREBID_GLOBAL$$.handlePiximediaCallback/sizes=300x600%2C728x90/cbid=210af5668b1e23/rand=42'); - }); - - it('should call the correct Prebid URL when supplying a custom URL', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', prebidUrl: '//resources.pm/tests/prebid/bids.js' }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - - expect(parsedBidUrl.hostname).to.equal('resources.pm'); - expect(parsedBidUrl.query).to.equal(''); - expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/tests/prebid/bids.js/site_id=TEST/placement_id=TEST/jsonp=$$PREBID_GLOBAL$$.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); - }); - }); - - describe('handling of the callback response', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._bidsReceived = []; - } - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - if (typeof ($$PREBID_GLOBAL$$._adsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._adsReceived = []; - } - - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', prebidUrl: '//resources.pm/tests/prebid/bids.js' }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - it('Piximedia callback function should exist', function () { - expect($$PREBID_GLOBAL$$.handlePiximediaCallback).to.exist.and.to.be.a('function'); - }); - - it('bidmanager.addBidResponse should be called once with correct arguments', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - - var response = { - foundbypm: true, - currency: 'EUR', - cpm: 1.23, - dealId: 9948, - width: 300, - height: 250, - html: '
ad
' - }; - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - response.cbid = stubGetUniqueIdentifierStr.returnValues[0]; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.calledOnce(stubAddBidResponse); - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('/20164912/header-bid-tag-0'); - expect(bidObject1.cpm).to.equal(1.23); - expect(bidObject1.ad).to.equal('
ad
'); - expect(bidObject1.width).to.equal(300); - expect(bidObject1.dealId).to.equal(9948); - expect(bidObject1.height).to.equal(250); - expect(bidObject1.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidObject1.bidderCode).to.equal('piximedia'); - - stubAddBidResponse.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('bidmanager.addBidResponse should be called once with correct arguments on partial response', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - - // this time, we do not provide dealId - var response = { - foundbypm: true, - cpm: 1.23, - width: 300, - height: 250, - currency: 'EUR', - html: '
ad
' - }; - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - response.cbid = stubGetUniqueIdentifierStr.returnValues[0]; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.calledOnce(stubAddBidResponse); - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('/20164912/header-bid-tag-0'); - expect(bidObject1.cpm).to.equal(1.23); - expect(bidObject1.ad).to.equal('
ad
'); - expect(bidObject1.width).to.equal(300); - expect(bidObject1.height).to.equal(250); - expect(bidObject1.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidObject1.bidderCode).to.equal('piximedia'); - - stubAddBidResponse.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('bidmanager.addBidResponse should be called once without any ads', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - - var response = { - foundbypm: false - }; - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - response.cbid = stubGetUniqueIdentifierStr.returnValues[0]; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.calledOnce(stubAddBidResponse); - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('/20164912/header-bid-tag-0'); - expect(bidObject1.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(bidObject1.bidderCode).to.equal('piximedia'); - - stubAddBidResponse.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('bidmanager.addBidResponse should not be called on bogus cbid', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - - var response = { - foundbypm: false - }; - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - response.cbid = stubGetUniqueIdentifierStr.returnValues[0] + '_BOGUS'; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.notCalled(stubAddBidResponse); - - stubAddBidResponse.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('bidmanager.addBidResponse should not be called on bogus response', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - var response = null; // this is bogus: we expect an object - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.notCalled(stubAddBidResponse); - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 0403617a846..608ac102ace 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1,18 +1,18 @@ import { expect } from 'chai'; -import Adapter from 'modules/prebidServerBidAdapter'; +import { PrebidServer as Adapter } from 'modules/prebidServerBidAdapter'; import adapterManager from 'src/adaptermanager'; -import bidmanager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; import cookie from 'src/cookie'; import { userSync } from 'src/userSync'; +import { ajax } from 'src/ajax'; +import { config } from 'src/config'; let CONFIG = { accountId: '1', enabled: true, bidders: ['appnexus'], timeout: 1000, - endpoint: CONSTANTS.S2S.DEFAULT_ENDPOINT + endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' }; const REQUEST = { @@ -43,10 +43,7 @@ const REQUEST = { 'bidder': 'appnexus', 'params': { 'placementId': '10433394', - 'member': 123, - 'randomKey': 123456789, - 'single_test': null, - 'myMultiVar': ['myValue', 124578] + 'member': 123 } } ] @@ -54,6 +51,40 @@ const REQUEST = { ] }; +const BID_REQUESTS = [ + { + 'bidderCode': 'appnexus', + 'auctionId': '173afb6d132ba3', + 'bidderRequestId': '3d1063078dfcc8', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394', + 'member': 123 + }, + 'bid_id': '123', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'sizes': [ + { + 'w': 300, + 'h': 250 + } + ], + 'bidId': '259fb43aaa06c1', + 'bidderRequestId': '3d1063078dfcc8', + 'auctionId': '173afb6d132ba3' + } + ], + 'auctionStart': 1510852447530, + 'timeout': 5000, + 'src': 's2s', + 'doneCbCallCount': 0 + } +]; + const RESPONSE = { 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', 'status': 'OK', @@ -178,10 +209,17 @@ const RESPONSE_NO_PBS_COOKIE_ERROR = { }; describe('S2S Adapter', () => { - let adapter; + let adapter, + addBidResponse = sinon.spy(), + done = sinon.spy(); beforeEach(() => adapter = new Adapter()); + afterEach(() => { + addBidResponse.reset(); + done.reset(); + }); + describe('request function', () => { let xhr; let requests; @@ -199,13 +237,11 @@ describe('S2S Adapter', () => { }); it('exists converts types', () => { - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid.ad_units[0].bids[0].params.placementId).to.exist.and.to.be.a('number'); expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); - expect(requestBid.ad_units[0].bids[0].params.keywords).to.exist.and.to.be.an('array').and.to.have.lengthOf(3); - expect(requestBid.ad_units[0].bids[0].params.keywords[0]).to.be.an('object').that.has.all.keys('key', 'value'); }); }); @@ -218,13 +254,6 @@ describe('S2S Adapter', () => { sinon.stub(utils, 'insertUserSyncIframe'); sinon.stub(utils, 'logError'); sinon.stub(cookie, 'cookieSet'); - sinon.stub(bidmanager, 'addBidResponse'); - sinon.stub(utils, 'getBidderRequestAllAdUnits').returns({ - bids: [{ - bidId: '123', - placementCode: 'div-gpt-ad-1460505748561-0' - }] - }); sinon.stub(utils, 'getBidRequest').returns({ bidId: '123' }); @@ -232,8 +261,6 @@ describe('S2S Adapter', () => { afterEach(() => { server.restore(); - bidmanager.addBidResponse.restore(); - utils.getBidderRequestAllAdUnits.restore(); utils.getBidRequest.restore(); utils.triggerPixel.restore(); utils.insertUserSyncIframe.restore(); @@ -245,117 +272,85 @@ describe('S2S Adapter', () => { it('registers bids', () => { server.respondWith(JSON.stringify(RESPONSE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); + sinon.assert.calledOnce(addBidResponse); - const response = bidmanager.addBidResponse.firstCall.args[1]; + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); expect(response).to.have.property('adId', '123'); }); - it('registers no-bid response when ad unit not set', () => { + it('does not call addBidResponse and calls done when ad unit not set', () => { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const ad_unit_code = bidmanager.addBidResponse.firstCall.args[0]; - expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); - const bid_request_passed = bidmanager.addBidResponse.firstCall.args[1]; - expect(bid_request_passed).to.have.property('adId', '123'); + sinon.assert.notCalled(addBidResponse); + sinon.assert.calledOnce(done); }); - it('registers no-bid response when server requests cookie sync', () => { + it('does not call addBidResponse and calls done when server requests cookie sync', () => { server.respondWith(JSON.stringify(RESPONSE_NO_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const ad_unit_code = bidmanager.addBidResponse.firstCall.args[0]; - expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); - - const bid_request_passed = bidmanager.addBidResponse.firstCall.args[1]; - expect(bid_request_passed).to.have.property('adId', '123'); + sinon.assert.notCalled(addBidResponse); + sinon.assert.calledOnce(done); }); - it('registers no-bid response when ad unit is set', () => { + it('does not call addBidResponse and calls done when ad unit is set', () => { server.respondWith(JSON.stringify(RESPONSE_NO_BID_UNIT_SET)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - const ad_unit_code = bidmanager.addBidResponse.firstCall.args[0]; - expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); + sinon.assert.notCalled(addBidResponse); + sinon.assert.calledOnce(done); }); - it('registers no-bid response when there are less bids than requests', () => { - utils.getBidderRequestAllAdUnits.restore(); - sinon.stub(utils, 'getBidderRequestAllAdUnits').returns({ - bids: [{ - bidId: '123', - placementCode: 'div-gpt-ad-1460505748561-0' - }, { - bidId: '101111', - placementCode: 'div-gpt-ad-1460505748561-1' - }] - }); - + it('registers successful bids and calls done when there are less bids than requests', () => { server.respondWith(JSON.stringify(RESPONSE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledTwice(bidmanager.addBidResponse); + sinon.assert.calledOnce(addBidResponse); + sinon.assert.calledOnce(done); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('div-gpt-ad-1460505748561-0'); - expect(bidmanager.addBidResponse.secondCall.args[0]).to.equal('div-gpt-ad-1460505748561-1'); + expect(addBidResponse.firstCall.args[0]).to.equal('div-gpt-ad-1460505748561-0'); - expect(bidmanager.addBidResponse.firstCall.args[1]).to.have.property('adId', '123'); - expect(bidmanager.addBidResponse.secondCall.args[1]).to.have.property('adId', '101111'); + expect(addBidResponse.firstCall.args[1]).to.have.property('adId', '123'); - expect(bidmanager.addBidResponse.firstCall.args[1]) + expect(addBidResponse.firstCall.args[1]) .to.have.property('statusMessage', 'Bid available'); - expect(bidmanager.addBidResponse.secondCall.args[1]) - .to.have.property('statusMessage', 'Bid returned empty or error response'); }); it('should have dealId in bidObject', () => { server.respondWith(JSON.stringify(RESPONSE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - const response = bidmanager.addBidResponse.firstCall.args[1]; + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('dealId', 'test-dealid'); }); it('should pass through default adserverTargeting if present in bidObject', () => { server.respondWith(JSON.stringify(RESPONSE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - const response = bidmanager.addBidResponse.firstCall.args[1]; + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('adserverTargeting').that.deep.equals({'foo': 'bar'}); }); @@ -367,8 +362,8 @@ describe('S2S Adapter', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(rubiconAdapter.registerSyncs); @@ -379,27 +374,27 @@ describe('S2S Adapter', () => { it('registers bid responses when server requests cookie sync', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); + sinon.assert.calledOnce(addBidResponse); - const ad_unit_code = bidmanager.addBidResponse.firstCall.args[0]; + const ad_unit_code = addBidResponse.firstCall.args[0]; expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); - const response = bidmanager.addBidResponse.firstCall.args[1]; + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('source', 's2s'); - const bid_request_passed = bidmanager.addBidResponse.firstCall.args[1]; + const bid_request_passed = addBidResponse.firstCall.args[1]; expect(bid_request_passed).to.have.property('adId', '123'); }); it('does cookie sync when no_cookie response', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(utils.triggerPixel); @@ -411,8 +406,8 @@ describe('S2S Adapter', () => { it('logs error when no_cookie response is missing type or url', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE_ERROR)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.notCalled(utils.triggerPixel); @@ -423,22 +418,62 @@ describe('S2S Adapter', () => { it('does not call cookieSet cookie sync when no_cookie response && not opted in', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + let myConfig = Object.assign({}, CONFIG); + + config.setConfig({s2sConfig: myConfig}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.notCalled(cookie.cookieSet); }); it('calls cookieSet cookie sync when no_cookie response && opted in', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - let config = Object.assign({ - cookieSet: true + let myConfig = Object.assign({ + cookieSetUrl: 'https://acdn.adnxs.com/cookieset/cs.js' }, CONFIG); - adapter.setConfig(config); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: myConfig}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(cookie.cookieSet); }); }); + + describe('s2sConfig', () => { + let logErrorSpy; + + beforeEach(() => { + logErrorSpy = sinon.spy(utils, 'logError'); + }); + + afterEach(() => { + utils.logError.restore(); + }); + + it('should log error when accountId is missing', () => { + const options = { + enabled: true, + bidders: ['appnexus'], + timeout: 1000, + adapter: 'prebidServer', + endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' + }; + + config.setConfig({ s2sConfig: options }); + sinon.assert.calledOnce(logErrorSpy); + }); + + it('should log error when bidders is missing', () => { + const options = { + accountId: '1', + enabled: true, + timeout: 1000, + adapter: 's2s', + endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' + }; + + config.setConfig({ s2sConfig: options }); + sinon.assert.calledOnce(logErrorSpy); + }); + }); }); diff --git a/test/spec/modules/pubgearsBidAdapter_spec.js b/test/spec/modules/pubgearsBidAdapter_spec.js deleted file mode 100644 index 81f890e0dfd..00000000000 --- a/test/spec/modules/pubgearsBidAdapter_spec.js +++ /dev/null @@ -1,287 +0,0 @@ -import { expect } from 'chai'; -import Adapter from 'modules/pubgearsBidAdapter' -import bidmanager from 'src/bidmanager' - -describe('PubGearsAdapter', () => { - var adapter, mockScript, - params = { - bids: [] - } - - beforeEach(() => { - adapter = new Adapter() - mockScript = document.createElement('script') - sinon.spy(mockScript, 'setAttribute') - }) - - describe('request function', () => { - beforeEach(() => { - sinon.spy(document, 'createElement') - }) - - afterEach(() => { - document.createElement.restore && document.createElement.restore() - var s = document.getElementById('pg-header-tag') - if (s) { s.parentNode.removeChild(s) } - }) - - it('has `#callBids()` method', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function') - }) - - it('requires bids to make script', () => { - adapter.callBids({bids: []}) - expect(document.createElement.notCalled).to.be.ok - }) - - it('creates script when passed bids', () => { - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - }) - - sinon.assert.calledWith(document.createElement, 'script') - }) - - it('should assign attributes to script', () => { - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - }, - { - bidder: 'pubgears', - sizes: [ [160, 600] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - }) - var script = document.createElement.returnValues[0] - var slots = script.getAttribute('data-bsm-slot-list') - expect(slots).to.equal('testpub.com/combined@300x250 testpub.com/combined@160x600') - expect(script.getAttribute('data-bsm-flag')).to.equal('true') - expect(script.getAttribute('data-bsm-pub')).to.equal('integration') - expect(script.getAttribute('src')).to.equal('//c.pubgears.com/tags/h') - expect(script.id).to.equal('pg-header-tag') - }) - - it('should reuse existing script when called twice', () => { - var params = { - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - }, - { - bidder: 'pubgears', - sizes: [ [160, 600] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - } - adapter.callBids(params) - expect(document.createElement.calledOnce).to.be.true - adapter.callBids(params) - expect(document.createElement.calledOnce).to.be.true - }) - - it('should register event listeners', () => { - var script = document.createElement('script') - script.id = 'pg-header-tag' - var spy = sinon.spy(script, 'addEventListener') - document.body.appendChild(script) - var params = { - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - }, - { - bidder: 'pubgears', - sizes: [ [160, 600] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - } - adapter.callBids(params) - - expect(spy.calledWith('onBidResponse')).to.be.ok - expect(spy.calledWith('onResourceComplete')).to.be.ok - }) - }) - - describe('bids received', () => { - beforeEach(() => { - sinon.spy(bidmanager, 'addBidResponse') - }) - - afterEach(() => { - bidmanager.addBidResponse.restore() - }) - - it('should call bidManager.addBidResponse() when bid received', () => { - var options = { - bubbles: false, - cancelable: false, - detail: { - gross_price: 1000, - resource: { - position: 'atf', - pub_zone: 'testpub.com/combined', - size: '300x250' - } - } - } - - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - }, - { - bidder: 'pubgears', - sizes: [ [160, 600] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - - }) - var script = document.getElementById('pg-header-tag') - var event = new CustomEvent('onBidResponse', options) - script.dispatchEvent(event) - - expect(bidmanager.addBidResponse.calledOnce).to.be.ok - }) - - it('should send correct bid response object when receiving onBidResponse event', () => { - expect(bidmanager.addBidResponse.calledOnce).to.not.be.ok - var bid = { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ bid ] - }) - - var options = { - bubbles: false, - cancelable: false, - detail: { - gross_price: 1000, - resource: { - position: 'atf', - pub_zone: 'testpub.com/combined', - size: '300x250' - } - } - } - var script = document.getElementById('pg-header-tag') - var event = new CustomEvent('onBidResponse', options) - script.dispatchEvent(event) - - var args = bidmanager.addBidResponse.getCall(1).args - expect(args).to.have.length(2) - var bidResponse = args[1] - expect(bidResponse.ad).to.contain(bid.params.pubZone) - }) - - it('should send $0 bid as no-bid response', () => { - var bid = { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ bid ] - }) - - var options = { - bubbles: false, - cancelable: false, - detail: { - gross_price: 0, - resource: { - position: 'atf', - pub_zone: 'testpub.com/combined', - size: '300x250' - } - } - } - var script = document.getElementById('pg-header-tag') - var event = new CustomEvent('onBidResponse', options) - - bidmanager.addBidResponse.reset() - script.dispatchEvent(event) - - var args = bidmanager.addBidResponse.getCall(1).args - var bidResponse = args[1] - expect(bidResponse).to.be.a('object') - expect(bidResponse.getStatusCode()).to.equal(2) - }) - }) -}) diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js deleted file mode 100644 index c7b8cd5cd8e..00000000000 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ /dev/null @@ -1,276 +0,0 @@ -import { - expect -} from 'chai'; -import * as utils from 'src/utils'; -import PubMaticAdapter from 'modules/pubmaticBidAdapter'; -import bidmanager from 'src/bidmanager'; -import constants from 'src/constants.json'; - -let getDefaultBidRequest = () => { - return { - bidderCode: 'pubmatic', - requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - bidderRequestId: '7101db09af0db2', - start: new Date().getTime(), - bids: [{ - bidder: 'pubmatic', - bidId: '84ab500420319d', - bidderRequestId: '7101db09af0db2', - requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - placementCode: 'DIV_1', - params: { - placement: 1234567, - network: '9599.1' - } - }] - }; -}; - -describe('PubMaticAdapter', () => { - let adapter; - - function createBidderRequest({ - bids, - params - } = {}) { - var bidderRequest = getDefaultBidRequest(); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - if (params) { - bidderRequest.bids.forEach(bid => bid.params = params); - } - return bidderRequest; - } - - beforeEach(() => adapter = new PubMaticAdapter()); - - describe('callBids()', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - describe('user syncup', () => { - beforeEach(() => { - sinon.stub(utils, 'insertElement'); - }); - - afterEach(() => { - utils.insertElement.restore(); - }); - - it('usersync is initiated', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90', - age: '20' - } - })); - utils.insertElement.calledOnce.should.be.true; - expect(utils.insertElement.getCall(0).args[0].src).to.equal('http://ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p=9999'); - }); - }); - - describe('bid request', () => { - beforeEach(() => { - sinon.stub(utils, 'createContentToExecuteExtScriptInFriendlyFrame', function() { - return ''; - }); - }); - - afterEach(() => { - utils.createContentToExecuteExtScriptInFriendlyFrame.restore(); - }); - - it('requires parameters to be made', () => { - adapter.callBids({}); - utils.createContentToExecuteExtScriptInFriendlyFrame.calledOnce.should.be.false; - }); - - it('for publisherId 9990 call is made to gads.pubmatic.com', () => { - var bidRequest = createBidderRequest({ - params: { - publisherId: 9990, - adSlot: ' abcd@728x90', - age: '20', - wiid: 'abcdefghijk', - profId: '1234', - verId: '12', - pmzoneid: 'abcd123, efg345', - dctr: 'key=1234,5678' - } - }); - adapter.callBids(bidRequest); - var callURL = utils.createContentToExecuteExtScriptInFriendlyFrame.getCall(0).args[0]; - expect(bidRequest.bids[0].params.adSlot).to.equal('abcd@728x90'); - expect(callURL).to.contain('gads.pubmatic.com/AdServer/AdCallAggregator?'); - expect(callURL).to.contain('SAVersion=1100'); - expect(callURL).to.contain('wp=PreBid'); - expect(callURL).to.contain('js=1'); - expect(callURL).to.contain('screenResolution='); - expect(callURL).to.contain('wv=' + constants.REPO_AND_VERSION); - expect(callURL).to.contain('ranreq='); - expect(callURL).to.contain('inIframe='); - expect(callURL).to.contain('pageURL='); - expect(callURL).to.contain('refurl='); - expect(callURL).to.contain('kltstamp='); - expect(callURL).to.contain('timezone='); - expect(callURL).to.contain('age=20'); - expect(callURL).to.contain('adslots=%5Babcd%40728x90%5D'); - expect(callURL).to.contain('kadpageurl='); - expect(callURL).to.contain('wiid=abcdefghijk'); - expect(callURL).to.contain('profId=1234'); - expect(callURL).to.contain('verId=12'); - expect(callURL).to.contain('pmZoneId=abcd123%2C%20efg345'); - expect(callURL).to.contain('dctr=key%3D1234%2C5678'); - }); - - it('for publisherId 9990 call is made to gads.pubmatic.com, age passed as int not being passed ahead', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9990, - adSlot: 'abcd@728x90', - age: 20, - wiid: 'abcdefghijk', - profId: '1234', - verId: '12', - pmzoneid: {}, - dctr: 1234 - } - })); - var callURL = utils.createContentToExecuteExtScriptInFriendlyFrame.getCall(0).args[0]; - expect(callURL).to.contain('gads.pubmatic.com/AdServer/AdCallAggregator?'); - expect(callURL).to.not.contain('age=20'); - expect(callURL).to.not.contain('dctr=1234'); - }); - - it('for publisherId 9990 call is made to gads.pubmatic.com, invalid data for pmzoneid', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9990, - adSlot: 'abcd@728x90', - age: '20', - wiid: 'abcdefghijk', - profId: '1234', - verId: '12', - pmzoneid: {}, - dctr: 1234 - } - })); - var callURL = utils.createContentToExecuteExtScriptInFriendlyFrame.getCall(0).args[0]; - expect(callURL).to.contain('gads.pubmatic.com/AdServer/AdCallAggregator?'); - expect(callURL).to.not.contain('pmZoneId='); - }); - }); - - describe('#handlePubmaticCallback: ', () => { - beforeEach(() => { - sinon.stub(utils, 'createContentToExecuteExtScriptInFriendlyFrame', function() { - return ''; - }); - sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - utils.createContentToExecuteExtScriptInFriendlyFrame.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('exists and is a function', () => { - expect($$PREBID_GLOBAL$$.handlePubmaticCallback).to.exist.and.to.be.a('function'); - }); - - it('empty response, arguments not passed', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90', - age: '20' - } - })); - $$PREBID_GLOBAL$$.handlePubmaticCallback(); - expect(bidmanager.addBidResponse.callCount).to.equal(0); - }); - - it('empty response', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90', - age: '20' - } - })); - $$PREBID_GLOBAL$$.handlePubmaticCallback({}, {}); - sinon.assert.called(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('DIV_1'); - var theBid = bidmanager.addBidResponse.firstCall.args[1]; - expect(theBid.bidderCode).to.equal('pubmatic'); - expect(theBid.getStatusCode()).to.equal(2); - }); - - it('not empty response', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90:0', - age: '20' - } - })); - $$PREBID_GLOBAL$$.handlePubmaticCallback({ - 'abcd@728x90:0': { - 'ecpm': 10, - 'creative_tag': 'hello', - 'tracking_url': 'http%3a%2f%2fhaso.pubmatic.com%2fads%2f9999%2fGRPBID%2f2.gif%3ftrackid%3d12345', - 'width': 728, - 'height': 90, - 'deal_channel': 5 - } - }, { - 'abcd@728x90:0': 'bidstatus;1;bid;10.0000;bidid;abcd@728x90:0;wdeal;PMERW36842' - }); - sinon.assert.called(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('DIV_1'); - var theBid = bidmanager.addBidResponse.firstCall.args[1]; - expect(theBid.bidderCode).to.equal('pubmatic'); - expect(theBid.adSlot).to.equal('abcd@728x90:0'); - expect(theBid.cpm).to.equal(10); - expect(theBid.width).to.equal(728); - expect(theBid.height).to.equal(90); - expect(theBid.dealId).to.equal('PMERW36842'); - expect(theBid.dealChannel).to.equal('PREF'); - }); - - it('not empty response, without dealChannel', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90', - age: '20' - } - })); - $$PREBID_GLOBAL$$.handlePubmaticCallback({ - 'abcd@728x90': { - 'ecpm': 10, - 'creative_tag': 'hello', - 'tracking_url': 'http%3a%2f%2fhaso.pubmatic.com%2fads%2f9999%2fGRPBID%2f2.gif%3ftrackid%3d12345', - 'width': 728, - 'height': 90 - } - }, { - 'abcd@728x90': 'bidstatus;1;bid;10.0000;bidid;abcd@728x90:0;wdeal;PMERW36842' - }); - sinon.assert.called(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('DIV_1'); - var theBid = bidmanager.addBidResponse.firstCall.args[1]; - expect(theBid.bidderCode).to.equal('pubmatic'); - expect(theBid.adSlot).to.equal('abcd@728x90'); - expect(theBid.cpm).to.equal(10); - expect(theBid.width).to.equal(728); - expect(theBid.height).to.equal(90); - expect(theBid.dealId).to.equal('PMERW36842'); - expect(theBid.dealChannel).to.equal(null); - }); - }); - }); -}); diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 07639310c36..cb99f1b5d98 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -1,163 +1,276 @@ +/* eslint dot-notation:0, quote-props:0 */ import {expect} from 'chai'; -import PulsePointAdapter from '../../../modules/pulsepointBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; +import {spec} from 'modules/pulsepointBidAdapter'; +import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; describe('PulsePoint Adapter Tests', () => { - let pulsepointAdapter = new PulsePointAdapter(); - let slotConfigs; - let requests = []; - let responses = {}; - - function initPulsepointLib() { - /* Mocked PulsePoint library */ - window.pp = { - requestActions: { - BID: 0 + const slotConfigs = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '300x250' + } + }, { + placementCode: '/DfpAccount2/slot2', + bidId: 'bid23456', + params: { + cp: 'p10000', + ct: 't20000', + cf: '728x90' + } + }]; + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + nativeParams: { + title: { required: true, len: 200 }, + image: { wmin: 100 }, + sponsoredBy: { } + }, + params: { + cp: 'p10000', + ct: 't10000' + } + }]; + const appSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + app: { + bundle: 'com.pulsepoint.apps', + storeUrl: 'http://pulsepoint.com/apps', + domain: 'pulsepoint.com', } - }; - /* Ad object */ - window.pp.Ad = function(config) { - this.display = function() { - requests.push(config); - config.callback(responses[config.ct]); - }; - }; - } + } + }]; - function resetPulsepointLib() { - window.pp = undefined; - } + it('Verify build request', () => { + const request = spec.buildRequests(slotConfigs); + expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // site object + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.publisher).to.not.equal(null); + expect(ortbRequest.site.publisher.id).to.equal('p10000'); + expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); + expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); + expect(ortbRequest.imp).to.have.lengthOf(2); + // device object + expect(ortbRequest.device).to.not.equal(null); + expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(ortbRequest.imp[0].tagid).to.equal('t10000'); + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + // slot 2 + expect(ortbRequest.imp[1].tagid).to.equal('t20000'); + expect(ortbRequest.imp[1].banner).to.not.equal(null); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); + }); - beforeEach(() => { - initPulsepointLib(); - sinon.stub(bidManager, 'addBidResponse'); - sinon.stub(adLoader, 'loadScript'); + it('Verify parse response', () => { + const request = spec.buildRequests(slotConfigs); + const ortbRequest = JSON.parse(request.data); + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'This is an Ad' + }] + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.ad).to.equal('This is an Ad'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.adId).to.equal('bid12345'); + expect(bid.creative_id).to.equal('bid12345'); + expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(20); + }); - slotConfigs = { - bids: [ - { - placementCode: '/DfpAccount1/slot1', - bidder: 'pulsepoint', - bidId: 'bid12345', - params: { - cp: 'p10000', - ct: 't10000', - cf: '300x250', - param1: 'value1', - param2: 2 - } - }, { - placementCode: '/DfpAccount2/slot2', - bidder: 'pulsepoint', - bidId: 'bid23456', - params: { - cp: 'p20000', - ct: 't20000', - cf: '728x90' + it('Verify use ttl in ext', () => { + const request = spec.buildRequests(slotConfigs); + const ortbRequest = JSON.parse(request.data); + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'This is an Ad', + ext: { + ttl: 30, + netRevenue: false, + currency: 'INR' } - } - ] + }] + }] }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.ttl).to.equal(30); + expect(bid.netRevenue).to.equal(false); + expect(bid.currency).to.equal('INR'); }); - afterEach(() => { - bidManager.addBidResponse.restore(); - adLoader.loadScript.restore(); - requests = []; - responses = {}; + it('Verify full passback', () => { + const request = spec.buildRequests(slotConfigs); + const bids = spec.interpretResponse({ body: null }, request) + expect(bids).to.have.lengthOf(0); }); - it('Verify requests sent to PulsePoint library', () => { - pulsepointAdapter.callBids(slotConfigs); - expect(requests).to.have.length(2); - // slot 1 - expect(requests[0].cp).to.equal('p10000'); - expect(requests[0].ct).to.equal('t10000'); - expect(requests[0].cf).to.equal('300x250'); - expect(requests[0].ca).to.equal(0); - expect(requests[0].cn).to.equal(1); - expect(requests[0].cu).to.equal('http://bid.contextweb.com/header/tag'); - expect(requests[0].adUnitId).to.equal('/DfpAccount1/slot1'); - expect(requests[0]).to.have.property('callback'); - expect(requests[0].param1).to.equal('value1'); - expect(requests[0].param2).to.equal(2); - // //slot 2 - expect(requests[1].cp).to.equal('p20000'); - expect(requests[1].ct).to.equal('t20000'); - expect(requests[1].cf).to.equal('728x90'); - expect(requests[1].ca).to.equal(0); - expect(requests[1].cn).to.equal(1); - expect(requests[1].cu).to.equal('http://bid.contextweb.com/header/tag'); - expect(requests[1].adUnitId).to.equal('/DfpAccount2/slot2'); - expect(requests[1]).to.have.property('callback'); + it('Verify Native request', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // native impression + expect(ortbRequest.imp[0].tagid).to.equal('t10000'); + expect(ortbRequest.imp[0].banner).to.equal(null); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(3); + // title asset + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + // data asset + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[1].required).to.equal(0); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(1); + expect(nativeRequest.assets[1].data.len).to.equal(50); + // image asset + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[2].title).to.be.undefined; + expect(nativeRequest.assets[2].img).to.not.equal(null); + expect(nativeRequest.assets[2].img.wmin).to.equal(100); + expect(nativeRequest.assets[2].img.hmin).to.equal(150); + expect(nativeRequest.assets[2].img.type).to.equal(3); }); - it('Verify bid', () => { - responses['t10000'] = { - html: 'This is an Ad', - bidCpm: 1.25 + it('Verify Native response', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { title: { text: 'Ad Title'} }, + { data: { type: 1, value: 'Sponsored By: Brand' }}, + { img: { type: 3, url: 'http://images.cdn.brand.com/123' } } + ], + link: { url: 'http://brand.clickme.com/' }, + imptrackers: ['http://imp1.trackme.com/', 'http://imp1.contextweb.com/'] + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: JSON.stringify(nativeResponse) + }] + }] }; - pulsepointAdapter.callBids(slotConfigs); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(placement).to.equal('/DfpAccount1/slot1'); - expect(bid.bidderCode).to.equal('pulsepoint'); + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; expect(bid.cpm).to.equal(1.25); - expect(bid.ad).to.equal('This is an Ad'); - expect(bid.width).to.equal('300'); - expect(bid.height).to.equal('250'); expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Sponsored By: Brand'); + expect(nativeBid.image).to.equal('http://images.cdn.brand.com/123'); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.clickme.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(2); + expect(nativeBid.impressionTrackers[0]).to.equal('http://imp1.trackme.com/'); + expect(nativeBid.impressionTrackers[1]).to.equal('http://imp1.contextweb.com/'); }); - it('Verify passback', () => { - pulsepointAdapter.callBids(slotConfigs); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(placement).to.equal('/DfpAccount1/slot1'); - expect(bid.bidderCode).to.equal('pulsepoint'); - expect(bid).to.not.have.property('ad'); - expect(bid).to.not.have.property('cpm'); - expect(bid.adId).to.equal('bid12345'); + it('Verifies bidder code', () => { + expect(spec.code).to.equal('pulsepoint'); }); - it('Verify PulsePoint library is downloaded if nessesary', () => { - resetPulsepointLib(); - pulsepointAdapter.callBids(slotConfigs); - let libraryLoadCall = adLoader.loadScript.firstCall.args[0]; - let callback = adLoader.loadScript.firstCall.args[1]; - expect(libraryLoadCall).to.equal('http://tag-st.contextweb.com/getjs.static.js'); - expect(callback).to.be.a('function'); + it('Verifies bidder aliases', () => { + expect(spec.aliases).to.have.lengthOf(2); + expect(spec.aliases[0]).to.equal('pulseLite'); + expect(spec.aliases[1]).to.equal('pulsepointLite'); }); - it('Verify Bids get processed after PulsePoint library downloads', () => { - resetPulsepointLib(); - pulsepointAdapter.callBids(slotConfigs); - let callback = adLoader.loadScript.firstCall.args[1]; - let bidCall = bidManager.addBidResponse.firstCall; - expect(callback).to.be.a('function'); - expect(bidCall).to.be.a('null'); - // the library load should initialize pulsepoint lib - initPulsepointLib(); - callback(); - expect(requests.length).to.equal(2); - bidCall = bidManager.addBidResponse.firstCall; - expect(bidCall).to.be.a('object'); - expect(bidCall.args[0]).to.equal('/DfpAccount1/slot1'); - expect(bidCall.args[1]).to.be.a('object'); + it('Verifies supported media types', () => { + expect(spec.supportedMediaTypes).to.have.lengthOf(1); + expect(spec.supportedMediaTypes[0]).to.equal('native'); }); - // related to issue https://github.com/prebid/Prebid.js/issues/866 - it('Verify Passbacks when window.pp is not available', () => { - window.pp = function() {}; - pulsepointAdapter.callBids(slotConfigs); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - // verify that we passed back without exceptions, should window.pp be already taken. - expect(placement).to.equal('/DfpAccount1/slot1'); - expect(bid.bidderCode).to.equal('pulsepoint'); - expect(bid).to.not.have.property('ad'); - expect(bid).to.not.have.property('cpm'); - expect(bid.adId).to.equal('bid12345'); + it('Verifies if bid request valid', () => { + expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); + expect(spec.isBidRequestValid({})).to.equal(false); + expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect(spec.isBidRequestValid({ params: { ct: 123 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { cp: 123 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { ct: 123, cp: 234 }})).to.equal(true); + }); + + it('Verifies sync options', () => { + expect(spec.getUserSyncs({})).to.be.undefined; + expect(spec.getUserSyncs({ iframeEnabled: false})).to.be.undefined; + const options = spec.getUserSyncs({ iframeEnabled: true}); + expect(options).to.not.be.undefined; + expect(options).to.have.lengthOf(1); + expect(options[0].type).to.equal('iframe'); + expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch'); + }); + + it('Verifies image pixel sync', () => { + const options = spec.getUserSyncs({ pixelEnabled: true}); + expect(options).to.not.be.undefined; + expect(options).to.have.lengthOf(1); + expect(options[0].type).to.equal('image'); + expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch/prebid'); + }); + + it('Verify app requests', () => { + const request = spec.buildRequests(appSlotConfig); + const ortbRequest = JSON.parse(request.data); + // site object + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.publisher).to.not.equal(null); + expect(ortbRequest.app.publisher.id).to.equal('p10000'); + expect(ortbRequest.app.bundle).to.equal('com.pulsepoint.apps'); + expect(ortbRequest.app.storeurl).to.equal('http://pulsepoint.com/apps'); + expect(ortbRequest.app.domain).to.equal('pulsepoint.com'); }); }); diff --git a/test/spec/modules/pulsepointLiteBidAdapter_spec.js b/test/spec/modules/pulsepointLiteBidAdapter_spec.js deleted file mode 100644 index 2c6f5f0681f..00000000000 --- a/test/spec/modules/pulsepointLiteBidAdapter_spec.js +++ /dev/null @@ -1,276 +0,0 @@ -/* eslint dot-notation:0, quote-props:0 */ -import {expect} from 'chai'; -import {spec} from 'modules/pulsepointLiteBidAdapter'; -import bidManager from 'src/bidmanager'; -import {getTopWindowLocation} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; - -describe('PulsePoint Lite Adapter Tests', () => { - const slotConfigs = [{ - placementCode: '/DfpAccount1/slot1', - bidId: 'bid12345', - params: { - cp: 'p10000', - ct: 't10000', - cf: '300x250' - } - }, { - placementCode: '/DfpAccount2/slot2', - bidId: 'bid23456', - params: { - cp: 'p10000', - ct: 't20000', - cf: '728x90' - } - }]; - const nativeSlotConfig = [{ - placementCode: '/DfpAccount1/slot3', - bidId: 'bid12345', - nativeParams: { - title: { required: true, len: 200 }, - image: { wmin: 100 }, - sponsoredBy: { } - }, - params: { - cp: 'p10000', - ct: 't10000' - } - }]; - const appSlotConfig = [{ - placementCode: '/DfpAccount1/slot3', - bidId: 'bid12345', - params: { - cp: 'p10000', - ct: 't10000', - app: { - bundle: 'com.pulsepoint.apps', - storeUrl: 'http://pulsepoint.com/apps', - domain: 'pulsepoint.com', - } - } - }]; - - it('Verify build request', () => { - const request = spec.buildRequests(slotConfigs); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // site object - expect(ortbRequest.site).to.not.equal(null); - expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('p10000'); - expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); - expect(ortbRequest.imp).to.have.lengthOf(2); - // device object - expect(ortbRequest.device).to.not.equal(null); - expect(ortbRequest.device.ua).to.equal(navigator.userAgent); - // slot 1 - expect(ortbRequest.imp[0].tagid).to.equal('t10000'); - expect(ortbRequest.imp[0].banner).to.not.equal(null); - expect(ortbRequest.imp[0].banner.w).to.equal(300); - expect(ortbRequest.imp[0].banner.h).to.equal(250); - // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('t20000'); - expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(728); - expect(ortbRequest.imp[1].banner.h).to.equal(90); - }); - - it('Verify parse response', () => { - const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: 'This is an Ad' - }] - }] - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.ad).to.equal('This is an Ad'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.adId).to.equal('bid12345'); - expect(bid.creative_id).to.equal('bid12345'); - expect(bid.creativeId).to.equal('bid12345'); - expect(bid.netRevenue).to.equal(true); - expect(bid.currency).to.equal('USD'); - expect(bid.ttl).to.equal(20); - }); - - it('Verify use ttl in ext', () => { - const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: 'This is an Ad', - ext: { - ttl: 30, - netRevenue: false, - currency: 'INR' - } - }] - }] - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.ttl).to.equal(30); - expect(bid.netRevenue).to.equal(false); - expect(bid.currency).to.equal('INR'); - }); - - it('Verify full passback', () => { - const request = spec.buildRequests(slotConfigs); - const bids = spec.interpretResponse({ body: null }, request) - expect(bids).to.have.lengthOf(0); - }); - - it('Verify Native request', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // native impression - expect(ortbRequest.imp[0].tagid).to.equal('t10000'); - expect(ortbRequest.imp[0].banner).to.equal(null); - const nativePart = ortbRequest.imp[0]['native']; - expect(nativePart).to.not.equal(null); - expect(nativePart.ver).to.equal('1.1'); - expect(nativePart.request).to.not.equal(null); - // native request assets - const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); - expect(nativeRequest).to.not.equal(null); - expect(nativeRequest.assets).to.have.lengthOf(3); - // title asset - expect(nativeRequest.assets[0].id).to.equal(1); - expect(nativeRequest.assets[0].required).to.equal(1); - expect(nativeRequest.assets[0].title).to.not.equal(null); - expect(nativeRequest.assets[0].title.len).to.equal(200); - // data asset - expect(nativeRequest.assets[1].id).to.equal(2); - expect(nativeRequest.assets[1].required).to.equal(0); - expect(nativeRequest.assets[1].title).to.be.undefined; - expect(nativeRequest.assets[1].data).to.not.equal(null); - expect(nativeRequest.assets[1].data.type).to.equal(1); - expect(nativeRequest.assets[1].data.len).to.equal(50); - // image asset - expect(nativeRequest.assets[2].id).to.equal(3); - expect(nativeRequest.assets[2].required).to.equal(0); - expect(nativeRequest.assets[2].title).to.be.undefined; - expect(nativeRequest.assets[2].img).to.not.equal(null); - expect(nativeRequest.assets[2].img.wmin).to.equal(100); - expect(nativeRequest.assets[2].img.hmin).to.equal(150); - expect(nativeRequest.assets[2].img.type).to.equal(3); - }); - - it('Verify Native response', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - const nativeResponse = { - 'native': { - assets: [ - { title: { text: 'Ad Title'} }, - { data: { type: 1, value: 'Sponsored By: Brand' }}, - { img: { type: 3, url: 'http://images.cdn.brand.com/123' } } - ], - link: { url: 'http://brand.clickme.com/' }, - imptrackers: ['http://imp1.trackme.com/', 'http://imp1.contextweb.com/'] - } - }; - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: JSON.stringify(nativeResponse) - }] - }] - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - // verify bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.adId).to.equal('bid12345'); - expect(bid.ad).to.be.undefined; - expect(bid.mediaType).to.equal('native'); - const nativeBid = bid['native']; - expect(nativeBid).to.not.equal(null); - expect(nativeBid.title).to.equal('Ad Title'); - expect(nativeBid.sponsoredBy).to.equal('Sponsored By: Brand'); - expect(nativeBid.image).to.equal('http://images.cdn.brand.com/123'); - expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.clickme.com/')); - expect(nativeBid.impressionTrackers).to.have.lengthOf(2); - expect(nativeBid.impressionTrackers[0]).to.equal('http://imp1.trackme.com/'); - expect(nativeBid.impressionTrackers[1]).to.equal('http://imp1.contextweb.com/'); - }); - - it('Verifies bidder code', () => { - expect(spec.code).to.equal('pulseLite'); - }); - - it('Verifies bidder aliases', () => { - expect(spec.aliases).to.have.lengthOf(1); - expect(spec.aliases[0]).to.equal('pulsepointLite'); - }); - - it('Verifies supported media types', () => { - expect(spec.supportedMediaTypes).to.have.lengthOf(1); - expect(spec.supportedMediaTypes[0]).to.equal('native'); - }); - - it('Verifies if bid request valid', () => { - expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); - expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); - expect(spec.isBidRequestValid({})).to.equal(false); - expect(spec.isBidRequestValid({ params: {} })).to.equal(false); - expect(spec.isBidRequestValid({ params: { ct: 123 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { cp: 123 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { ct: 123, cp: 234 }})).to.equal(true); - }); - - it('Verifies sync options', () => { - expect(spec.getUserSyncs({})).to.be.undefined; - expect(spec.getUserSyncs({ iframeEnabled: false})).to.be.undefined; - const options = spec.getUserSyncs({ iframeEnabled: true}); - expect(options).to.not.be.undefined; - expect(options).to.have.lengthOf(1); - expect(options[0].type).to.equal('iframe'); - expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch'); - }); - - it('Verifies image pixel sync', () => { - const options = spec.getUserSyncs({ pixelEnabled: true}); - expect(options).to.not.be.undefined; - expect(options).to.have.lengthOf(1); - expect(options[0].type).to.equal('image'); - expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch/prebid'); - }); - - it('Verify app requests', () => { - const request = spec.buildRequests(appSlotConfig); - const ortbRequest = JSON.parse(request.data); - // site object - expect(ortbRequest.site).to.equal(null); - expect(ortbRequest.app).to.not.be.null; - expect(ortbRequest.app.publisher).to.not.equal(null); - expect(ortbRequest.app.publisher.id).to.equal('p10000'); - expect(ortbRequest.app.bundle).to.equal('com.pulsepoint.apps'); - expect(ortbRequest.app.storeurl).to.equal('http://pulsepoint.com/apps'); - expect(ortbRequest.app.domain).to.equal('pulsepoint.com'); - }); -}); diff --git a/test/spec/modules/realvuBidAdapter_spec.js b/test/spec/modules/realvuBidAdapter_spec.js deleted file mode 100644 index 36517fa723e..00000000000 --- a/test/spec/modules/realvuBidAdapter_spec.js +++ /dev/null @@ -1,61 +0,0 @@ -import {expect} from 'chai'; -import RealVuAdapter from '../../../modules/realvuBidAdapter'; -import bidmanager from '../../../src/bidmanager'; -import adloader from '../../../src/adloader'; - -describe('RealVu Adapter Test', () => { - let adapter; - - const REQUEST = { - bidderCode: 'realvu', - requestId: '0d67ddab-1502-4897-a7bf-e8078e983405', - bidderRequestId: '1b5e314fe79b1d', - bids: [ - { - bidId: '2d86a04312d95d', - bidder: 'realvu', - bidderRequestId: '1b5e314fe79b1d', - // mediaType:undefined, - params: { - partnerId: '1Y', - placementId: '9339508', - }, - placementCode: 'ad_container_1', - // renderer:undefined, - sizes: [[300, 250]], - transactionId: '0d67ddab-1502-4897-a7bf-e8078e983405' - } - ], - start: 1504628062271 - }; - - var bidResponseStub; - var adloaderStub; - - beforeEach(function() { - bidResponseStub = sinon.stub(bidmanager, 'addBidResponse'); - adloaderStub = sinon.stub(adloader, 'loadScript'); - }); - - afterEach(function() { - adloaderStub.restore(); - bidResponseStub.restore(); - }); - - adapter = new RealVuAdapter(); - - it('load boost', () => { - adapter.callBids(REQUEST); - expect(adloaderStub.getCall(0).args[0]).to.contain('realvu_boost.js'); - }); - - it('callBid "yes"', () => { - adapter.boostCall({realvu: 'yes', pin: {pbjs_bid: REQUEST.bids[0]}}); - expect(adloaderStub.getCall(0).args[0]).to.contain('id=9339508'); - }); - - it('callBid "no"', () => { - adapter.boostCall({realvu: 'no', pin: {pbjs_bid: REQUEST.bids[0]}}); - expect(bidResponseStub.getCall(0).args[1].getStatusCode()).to.equal(2); - }); -}); diff --git a/test/spec/modules/roxotBidAdapter_spec.js b/test/spec/modules/roxotBidAdapter_spec.js deleted file mode 100644 index af7bef291e1..00000000000 --- a/test/spec/modules/roxotBidAdapter_spec.js +++ /dev/null @@ -1,123 +0,0 @@ -describe('Roxot adapter tests', function() { - const expect = require('chai').expect; - const adapter = require('modules/roxotBidAdapter'); - const bidmanager = require('src/bidmanager'); - - describe('roxotResponseHandler', function () { - it('should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.roxotResponseHandler).to.exist.and.to.be.a('function'); - }); - - it('should add empty bid responses if no bids returned', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - var bidderRequest = { - bidderCode: 'roxot', - bids: [ - { - bidId: 'id1', - bidder: 'roxot', - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidId: 'id2', - bidder: 'roxot', - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-2' - }, - ] - }; - - // no bids returned in the response. - var response = { - 'id': '123', - 'bids': [] - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // adapter needs to be called, in order for the stub to register. - adapter(); - - $$PREBID_GLOBAL$$.roxotResponseHandler(response); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - var bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - var bidObject2 = stubAddBidResponse.getCall(1).args[1]; - - expect(bidPlacementCode1).to.equal('div-gpt-ad-12345-1'); - expect(bidObject1.getStatusCode()).to.equal(2); - expect(bidObject1.bidderCode).to.equal('roxot'); - - expect(bidPlacementCode2).to.equal('div-gpt-ad-12345-2'); - expect(bidObject2.getStatusCode()).to.equal(2); - expect(bidObject2.bidderCode).to.equal('roxot'); - - stubAddBidResponse.restore(); - }); - - it('should add a bid response for bids returned and empty bid responses for the rest', () => { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - var bidderRequest = { - bidderCode: 'roxot', - bids: [ - { - bidId: 'id1', - bidder: 'roxot', - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidId: 'id2', - bidder: 'roxot', - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-2' - }, - ] - }; - - // Returning a single bid in the response. - var response = { - 'id': '12345', - 'bids': [ - { - 'bidId': 'id1', - 'cpm': 0.09, - 'nurl': 'http://roxot.example.com', - 'adm': '<>', - 'h': 320, - 'w': 50 - } - ]}; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // adapter needs to be called, in order for the stub to register. - adapter(); - - $$PREBID_GLOBAL$$.roxotResponseHandler(response); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - var bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - var bidObject2 = stubAddBidResponse.getCall(1).args[1]; - - expect(bidPlacementCode1).to.equal('div-gpt-ad-12345-1'); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('roxot'); - expect(bidObject1.cpm).to.equal(0.09); - expect(bidObject1.height).to.equal(320); - expect(bidObject1.width).to.equal(50); - expect(bidObject1.ad).to.equal('<>'); - - expect(bidPlacementCode2).to.equal('div-gpt-ad-12345-2'); - expect(bidObject2.getStatusCode()).to.equal(2); - expect(bidObject2.bidderCode).to.equal('roxot'); - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 52a87f6397f..49c0dd9011e 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -145,7 +145,7 @@ describe('the rubicon adapter', () => { 'rp_secure': /[01]/, 'rand': '0.1', 'tk_flint': INTEGRATION, - 'tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', 'p_screen_res': /\d+x\d+/, 'tk_user_key': '12346', 'kw': 'a,b,c', @@ -451,6 +451,7 @@ describe('the rubicon adapter', () => { expect(post.resolution).to.match(/\d+x\d+/); expect(post.account_id).to.equal('14062'); expect(post.integration).to.equal(INTEGRATION); + expect(post['x_source.tid']).to.equal('d45dd707-a418-42ec-b8a7-b70a6c6fab0b'); expect(post).to.have.property('timeout').that.is.a('number'); expect(post.timeout < 5000).to.equal(true); expect(post.stash_creatives).to.equal(true); diff --git a/test/spec/modules/s2sTesting_spec.js b/test/spec/modules/s2sTesting_spec.js index 4ddd7278f4e..26d5eb8884b 100644 --- a/test/spec/modules/s2sTesting_spec.js +++ b/test/spec/modules/s2sTesting_spec.js @@ -1,5 +1,6 @@ import { getSourceBidderMap, calculateBidSources, getSource } from 'modules/s2sTesting'; import { config } from 'src/config'; +import find from 'core-js/library/fn/array/find'; var events = require('src/events'); var CONSTANTS = require('src/constants.json'); @@ -326,7 +327,7 @@ describe('s2sTesting', function () { expect(targeting).to.be.undefined; return; } - expect(targeting.find((kvp) => { + expect(find(targeting, (kvp) => { return kvp.key === `hb_source_${bidder}`; })).to.be.undefined; } diff --git a/test/spec/modules/sharethroughAnalyticsAdapter_spec.js b/test/spec/modules/sharethroughAnalyticsAdapter_spec.js deleted file mode 100644 index 8968e0461fb..00000000000 --- a/test/spec/modules/sharethroughAnalyticsAdapter_spec.js +++ /dev/null @@ -1,90 +0,0 @@ -import sharethroughAnalytics from 'modules/sharethroughAnalyticsAdapter'; -import { expect } from 'chai'; - -describe('sharethrough analytics adapter', () => { - let sandbox; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('track', () => { - describe('when event type is bidRequested', () => { - beforeEach(() => { - let eventType = 'bidRequested'; - let args = {'bidderCode': 'sharethrough', 'bids': {'0': {'placementCode': 'fake placement Code'}}}; - sharethroughAnalytics.track({eventType, args}) - }); - - it('placementCodeSet contains a value', () => { - expect(sharethroughAnalytics.placementCodeSet['fake placement Code'] == undefined).to.equal(false) - }); - }); - }); - - describe('bid won handler', () => { - let fireLoseBeaconStub; - - beforeEach(() => { - fireLoseBeaconStub = sandbox.stub(sharethroughAnalytics, 'fireLoseBeacon'); - }); - - describe('when bidderCode is not sharethrough and sharethrough is in bid', () => { - beforeEach(() => { - sharethroughAnalytics.placementCodeSet['div-gpt-ad-1460505748561-0'] = {'adserverRequestId': '0eca470d-fcac-48e6-845a-c86483ccaa0c'} - var args = { - 'bidderCode': 'someoneelse', - 'width': 600, - 'height': 300, - 'statusMessage': 'Bid available', - 'adId': '23fbe93a90c924', - 'cpm': 3.984986853301525, - 'adserverRequestId': '0eca470d-fcac-48e6-845a-c86483ccaa0c', - 'winId': '1c404469-f7bb-4e50-b6f6-a8eaf0808999', - 'pkey': 'xKcxTTHyndFyVx7T8GKSzxPE', - 'ad': '
', - 'requestId': 'dd2420bd-cdc2-4c66-8479-f3499ece73da', - 'responseTimestamp': 1473983655565, - 'requestTimestamp': 1473983655458, - 'bidder': 'sharethrough', - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'timeToRespond': 107, - 'pbLg': '3.50', - 'pbMg': '3.90', - 'pbHg': '3.98', - 'pbAg': '3.95', - 'pbDg': '3.95', - 'size': '600x300', - 'adserverTargeting': { - 'hb_bidder': 'sharethrough', - 'hb_adid': '23fbe93a90c924', - 'hb_pb': '3.90', - 'hb_size': '600x300' - } - }; - - sharethroughAnalytics.bidWon(args); - }); - - it('should fire lose beacon', () => { - sinon.assert.calledOnce(fireLoseBeaconStub); - }); - }); - }); - - describe('lose beacon is fired', () => { - beforeEach(() => { - sandbox.stub(sharethroughAnalytics, 'fireBeacon'); - sharethroughAnalytics.fireLoseBeacon('someoneelse', 10.0, 'arid', 'losebeacontype'); - }); - - it('should call correct url', () => { - let winUrl = sharethroughAnalytics.fireBeacon.firstCall.args[0]; - expect(winUrl).to.contain(sharethroughAnalytics.STR_BEACON_HOST + 'winnerBidderCode=someoneelse&winnerCpm=10&arid=arid&type=losebeacontype&hbVersion=%24prebid.version%24&strVersion=0.1.0&hbSource=prebid&'); - }); - }); -}); diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js deleted file mode 100644 index bfb89cf4ead..00000000000 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ /dev/null @@ -1,154 +0,0 @@ -describe('smartadserver adapter tests', function () { - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - var adapter = require('modules/smartadserverBidAdapter'); - var adLoader = require('src/adloader'); - var expect = require('chai').expect; - var bidmanager = require('src/bidmanager'); - var CONSTANTS = require('src/constants.json'); - - var DEFAULT_PARAMS = { - bidderCode: 'smartadserver', - bids: [{ - bidId: 'abcd1234', - sizes: [[300, 250], [300, 200]], - bidder: 'smartadserver', - params: { - domain: 'http://www.smartadserver.com', - siteId: '1234', - pageId: '5678', - formatId: '90', - target: 'test=prebid', - currency: 'EUR', - bidfloor: 0.420 - }, - requestId: 'efgh5678', - placementCode: 'sas_42' - } - ] - }; - - var DEFAULT_PARAMS_WO_OPTIONAL = { - bidderCode: 'smartadserver', - bids: [{ - bidId: 'abcd1234', - sizes: [[300, 250], [300, 200]], - bidder: 'smartadserver', - params: { - domain: 'http://www.smartadserver.com', - siteId: '1234', - pageId: '5678', - formatId: '90' - }, - requestId: 'efgh5678', - placementCode: 'sas_42' - } - ] - }; - - var BID_RESPONSE = { - cpm: 0.42, - ad: 'fake ad content', - width: 300, - height: 250 - }; - - it('set url parameters', function () { - var stubLoadScript = sinon.stub(adLoader, 'loadScript'); - - adapter().callBids(DEFAULT_PARAMS); - - var smartCallback; - for (var k in $$PREBID_GLOBAL$$) { - if (k.lastIndexOf('sas_', 0) === 0) { - smartCallback = k; - break; - } - } - - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('www.smartadserver.com'); - expect(parsedBidUrl.pathname).to.equal('/prebid'); - - expect(parsedBidUrlQueryString).to.have.property('pbjscbk').and.to.equal('$$PREBID_GLOBAL$$.' + smartCallback); - expect(parsedBidUrlQueryString).to.have.property('siteid').and.to.equal('1234'); - expect(parsedBidUrlQueryString).to.have.property('pgid').and.to.equal('5678'); - expect(parsedBidUrlQueryString).to.have.property('fmtid').and.to.equal('90'); - expect(parsedBidUrlQueryString).to.have.property('tgt').and.to.equal('test=prebid'); - expect(parsedBidUrlQueryString).to.have.property('ccy').and.to.equal('EUR'); - expect(parsedBidUrlQueryString).to.have.property('bidfloor').and.to.equal('0.42'); - expect(parsedBidUrlQueryString).to.have.property('tag').and.to.equal('sas_42'); - expect(parsedBidUrlQueryString).to.have.property('sizes').and.to.equal('300x250,300x200'); - expect(parsedBidUrlQueryString).to.have.property('async').and.to.equal('1'); - - stubLoadScript.restore(); - }); - - it('test optional parameters default value', function () { - var stubLoadScript = sinon.stub(adLoader, 'loadScript'); - - adapter().callBids(DEFAULT_PARAMS_WO_OPTIONAL); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrlQueryString).to.have.property('tgt').and.to.equal(''); - expect(parsedBidUrlQueryString).to.have.property('ccy').and.to.equal('USD'); - - stubLoadScript.restore(); - }); - - it('creates an empty bid response if no bids', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript', function(url) { - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - $$PREBID_GLOBAL$$[parsedBidUrlQueryString.pbjscbk.split('.')[1]](null); - }); - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - adapter().callBids(DEFAULT_PARAMS); - - var bidResponsePlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidResponseAd = stubAddBidResponse.getCall(0).args[1]; - - expect(bidResponsePlacementCode).to.equal(DEFAULT_PARAMS.bids[0].placementCode); - expect(bidResponseAd.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(bidResponseAd).to.have.property('bidderCode').and.to.equal('smartadserver'); - - stubLoadScript.restore(); - stubAddBidResponse.restore(); - }); - - it('creates a bid response if bid is returned', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript', function(url) { - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - $$PREBID_GLOBAL$$[parsedBidUrlQueryString.pbjscbk.split('.')[1]](BID_RESPONSE); - }); - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - adapter().callBids(DEFAULT_PARAMS); - - var bidResponsePlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidResponseAd = stubAddBidResponse.getCall(0).args[1]; - - expect(bidResponsePlacementCode).to.equal(DEFAULT_PARAMS.bids[0].placementCode); - expect(bidResponseAd.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidResponseAd).to.have.property('bidderCode').and.to.equal('smartadserver'); - expect(bidResponseAd).to.have.property('cpm').and.to.equal(BID_RESPONSE.cpm); - expect(bidResponseAd).to.have.property('ad').and.to.equal(BID_RESPONSE.ad); - expect(bidResponseAd).to.have.property('width').and.to.equal(BID_RESPONSE.width); - expect(bidResponseAd).to.have.property('height').and.to.equal(BID_RESPONSE.height); - - stubLoadScript.restore(); - stubAddBidResponse.restore(); - }); -}); diff --git a/test/spec/modules/smartyadsBidAdapter_spec.js b/test/spec/modules/smartyadsBidAdapter_spec.js deleted file mode 100644 index d7c723604a6..00000000000 --- a/test/spec/modules/smartyadsBidAdapter_spec.js +++ /dev/null @@ -1,128 +0,0 @@ -import { expect } from 'chai'; -import Adapter from '../../../modules/smartyadsBidAdapter'; -import adapterManager from 'src/adaptermanager'; -import bidManager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; - -describe('Smartyads adapter tests', function () { - let sandbox; - const adUnit = { // TODO CHANGE - code: 'smartyads', - sizes: [[300, 250], [300, 600], [320, 80]], - bids: [{ - bidder: 'smartyads', - params: { - banner_id: 0 - } - }] - }; - - const response = { - ad_id: 0, - adm: 'Test Response', - cpm: 0.5, - deal: 'bf063e2e025c', - height: 240, - width: 360 - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('Smartyads callBids validation', () => { - let bids, - server; - - beforeEach(() => { - bids = []; - server = sinon.fakeServer.create(); - - sandbox.stub(bidManager, 'addBidResponse', (elemId, bid) => { - bids.push(bid); - }); - }); - - afterEach(() => { - server.restore(); - }); - - let adapter = adapterManager.bidderRegistry['smartyads']; - - it('Valid bid-request', () => { - sandbox.stub(adapter, 'callBids'); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - - let bidderRequest = adapter.callBids.getCall(0).args[0]; - - expect(bidderRequest).to.have.property('bids') - .that.is.an('array') - .with.lengthOf(1); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .to.have.property('bidder', 'smartyads'); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('sizes') - .that.is.an('array') - .with.lengthOf(3) - .that.deep.equals(adUnit.sizes); - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('banner_id', 0); - }); - - it('Valid bid-response', () => { - server.respondWith(JSON.stringify( - response - )); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - server.respond(); - - expect(bids).to.be.lengthOf(1); - expect(bids[0].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bids[0].bidderCode).to.equal('smartyads'); - expect(bids[0].width).to.equal(360); - expect(bids[0].height).to.equal(240); - expect(bids[0].cpm).to.equal(0.5); - expect(bids[0].dealId).to.equal('bf063e2e025c'); - }); - }); - - describe('MAS mapping / ordering', () => { - let masSizeOrdering = Adapter.masSizeOrdering; - - it('should not include values without a proper mapping', () => { - let ordering = masSizeOrdering([[320, 50], [42, 42], [300, 250], [640, 480], [1, 1], [336, 280]]); - expect(ordering).to.deep.equal([15, 16, 43, 65]); - }); - - it('should sort values without any MAS priority sizes in regular ascending order', () => { - let ordering = masSizeOrdering([[320, 50], [640, 480], [336, 280], [200, 600]]); - expect(ordering).to.deep.equal([16, 43, 65, 126]); - }); - - it('should sort MAS priority sizes in the proper order w/ rest ascending', () => { - let ordering = masSizeOrdering([[320, 50], [160, 600], [640, 480], [300, 250], [336, 280], [200, 600]]); - expect(ordering).to.deep.equal([15, 9, 16, 43, 65, 126]); - - ordering = masSizeOrdering([[320, 50], [300, 250], [160, 600], [640, 480], [336, 280], [200, 600], [728, 90]]); - expect(ordering).to.deep.equal([15, 2, 9, 16, 43, 65, 126]); - - ordering = masSizeOrdering([[120, 600], [320, 50], [160, 600], [640, 480], [336, 280], [200, 600], [728, 90]]); - expect(ordering).to.deep.equal([2, 9, 8, 16, 43, 65, 126]); - }) - }); -}); - -function clone(obj) { - return JSON.parse(JSON.stringify(obj)); -} diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js deleted file mode 100644 index 346fc18e637..00000000000 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ /dev/null @@ -1,389 +0,0 @@ -const chai = require('chai'); -const expect = require('chai').expect; -const Adapter = require('modules/sonobiBidAdapter'); -const bidManager = require('src/bidmanager'); -const adLoader = require('src/adloader'); -const utils = require('src/utils'); - -chai.config.includeStack = true; - -describe('Sonobi adapter tests', () => { - // Declared each explicitely so we can loop through and observe each test - const adUnit_p = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_p', - sizes: [[300, 250], [300, 600]], - params: { - placement_id: '1a2b3c4d5e6f1a2b3c4d' - } - }] - }; - const adUnit_pd = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_pd', - sizes: [[300, 250], [300, 600]], - params: { - placement_id: '1a2b3c4d5e6f1a2b3c4d', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_pdf = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_pdf', - sizes: [[300, 250], [300, 600]], - params: { - placement_id: '1a2b3c4d5e6f1a2b3c4d', - dom_id: 'div-gpt-ad-12345-0', - floor: '1' - } - }] - }; - const adUnit_a = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_a', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - } - }] - }; - - const adUnit_as = { - code: 'sbi_s', - sizes: [[120, 600], [300, 600], [160, 600]], - bids: [{ - bidder: 'sonobi', - params: { - ad_unit: '/7780971/sparks_prebid_LB', - sizes: [[300, 250], [300, 600]] - } - }] - }; - - const adUnit_ad = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_ad', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_af = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_af', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - floor: '1' - } - }] - }; - const adUnit_adf = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_adf', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0', - floor: '1' - } - }] - }; - const adUnit_A = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_A', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - } - }] - }; - const adUnit_Ad = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_Ad', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_Af = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_Af', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '7780971/sparks_prebid_MR', - floor: '1' - } - }] - }; - const adUnit_Adf = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_Adf', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0', - floor: '1' - } - }] - }; - // You guys surprise me all the time new and exciting ways to break this simple adapter. - const adUnit_m1hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m1hb', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '1a2b3c4d5e6f1a2b3c4d', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_m2hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m2hb', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - placement_id: 'OPTIONAL', - dom_id: 'div-gpt-ad-12345-0', - } - }] - }; - const adUnit_m3hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m3hb', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - placement_id: '', - dom_id: 'div-gpt-ad-12345-0', - } - }] - }; - const adUnit_m4hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m4hb', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '', - placement_id: '1a2b3c4d5e6f1a2b3c4d', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_m5hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m5hb', - sizes: [[300, 250], [300, 600]], - params: { - placement_id: '/7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - // FTFY - const sbi_adUnits = { - 'adUnit_p': adUnit_p, - 'adUnit_pd': adUnit_pd, - 'adUnit_pdf': adUnit_pdf, - 'adUnit_a': adUnit_a, - 'adUnit_as': adUnit_as, - 'adUnit_ad': adUnit_ad, - 'adUnit_af': adUnit_af, - 'adUnit_adf': adUnit_adf, - 'adUnit_A': adUnit_A, - 'adUnit_Ad': adUnit_Ad, - 'adUnit_Af': adUnit_Af, - 'adUnit_Adf': adUnit_Adf, - 'adUnit_m1hb': adUnit_m1hb, - 'adUnit_m2hb': adUnit_m2hb, - 'adUnit_m3hb': adUnit_m3hb, - 'adUnit_m4hb': adUnit_m4hb, - 'adUnit_m5hb': adUnit_m5hb - }; - - // Run the same test against all the (now tons of) different configurations - utils._each(sbi_adUnits, (adUnit, adUnitName) => { - describe('should form valid bid requests', () => { - let adapter = new Adapter(); - let stubLoadScript; - let stubFailBid; - let stubGoodBid; - - beforeEach(() => { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - stubFailBid = sinon.stub(adapter, 'failure'); - stubGoodBid = sinon.stub(adapter, 'success'); - }); - - afterEach(() => { - stubLoadScript.restore(); - stubFailBid.restore(); - stubGoodBid.restore(); - }); - - it('should make trinity key:vals for: ' + adUnitName, () => { - let keymakerBid = adapter.formRequest(adUnit.bids); - // Key matches one of two patterns and chai doesn't have an 'or' clause. - expect(Object.keys(keymakerBid)[0]).to.exist; - expect(Object.keys(keymakerBid)[0]).to.not.be.empty; - expect(keymakerBid[Object.keys(keymakerBid)[0]]).to.exist; - expect(keymakerBid[Object.keys(keymakerBid)[0]]).to.not.be.empty; - // Just having a key and val is sufficient for bidder to attempt to work with it. - }); - - it('should attempt to call bidder for: ' + adUnitName, () => { - adapter.callBids(adUnit); - expect(stubLoadScript.callCount).to.equal(1); - expect(stubFailBid.callCount).to.equal(0); - }); - }); - }); - - describe('should parse bid returns and register bid objects', () => { - let adapter = new Adapter(); - let spyAddBidResponse; - let stubFailBid; - let stubGoodBid; - - const sbi_bid = { - 'slots': - { - 'sbi_a': - { - 'sbi_size': '300x250', - 'sbi_apoc': 'premium', - 'sbi_aid': '159.60.7533347', - 'sbi_mouse': 4.20 - } - }, - 'sbi_dc': 'mco-1-' - }; - - const sbi_video_bid = { - 'slots': - { - 'sbi_a': - { - 'sbi_size': 'outstream', - 'sbi_apoc': 'premium', - 'sbi_aid': '159.60.7533347', - 'sbi_mouse': 4.20, - } - }, - 'sbi_dc': 'mco-1-' - }; - - const sbi_deal_bid = { - 'slots': - { - 'sbi_a': - { - 'sbi_size': '300x250', - 'sbi_apoc': 'premium', - 'sbi_aid': '159.60.7533347', - 'sbi_mouse': 4.20, - 'sbi_dozer': 'apex-test-deal' - } - }, - 'sbi_dc': 'mco-1-' - }; - - const sbi_noBid = { - 'slots': - { - 'sbi_a': {} - }, - 'sbi_dc': 'mco-1-' - }; - - beforeEach(() => { - spyAddBidResponse = sinon.spy(bidManager, 'addBidResponse'); - stubFailBid = sinon.stub(adapter, 'failure'); - stubGoodBid = sinon.stub(adapter, 'success'); - }); - - afterEach(() => { - spyAddBidResponse.restore(); - stubFailBid.restore(); - stubGoodBid.restore(); - }); - - it('should create bid object for good bid return', () => { - adapter.parseResponse(sbi_bid); - expect(spyAddBidResponse.called).to.be.true; - expect(stubFailBid.callCount).to.equal(0); - }); - - it('should create bid object for outstream video bid return', () => { - adapter.parseResponse(sbi_video_bid); - expect(spyAddBidResponse.called).to.be.true; - expect(stubFailBid.callCount).to.equal(0); - }); - - it('should create bid object for deal bid return', () => { - adapter.parseResponse(sbi_deal_bid); - expect(spyAddBidResponse.called).to.be.true; - expect(stubFailBid.callCount).to.equal(0); - }); - - it('should create fail bid object for empty return', () => { - adapter.parseResponse(sbi_noBid); - expect(spyAddBidResponse.called).to.be.true; - expect(stubGoodBid.callCount).to.equal(0); - }); - }); -}); diff --git a/test/spec/modules/spotxBidAdapter_spec.js b/test/spec/modules/spotxBidAdapter_spec.js deleted file mode 100644 index 1b48111b79e..00000000000 --- a/test/spec/modules/spotxBidAdapter_spec.js +++ /dev/null @@ -1,226 +0,0 @@ -import {expect} from 'chai'; -import {assert} from 'chai'; -import Adapter from 'modules/spotxBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; - -const CHANNEL_ID = 85394; -const CACHE_KEY = 'eyJob3N0IjoiZmUwMDEuc3BvdHguZ2FkZ2V0cy5sb2QiLCJja'; - -let bidRequest = { - 'bidderCode': 'spotx', - 'requestId': '4b8bb067-fca9-478b-9207-d24b87fce85c', - 'bidderRequestId': '1bfc89fa86fd1d', - 'timeout': 1000, - 'bids': [ - { - 'bidId': '2626663210bd26', - 'bidder': 'spotx', - 'bidderRequestId': '145a190a61161e', - 'mediaType': 'video', - 'params': { - 'placementId': '123456789', - 'video': { - 'ad_mute': false, - 'autoplay': true, - 'channel_id': CHANNEL_ID, - 'hide_skin': false, - 'slot': null, - 'video_slot': null - } - }, - 'placementCode': 'video1', - 'requestId': '5e1e93aa-55cf-4f73-a56a-8a74d0584c5f', - 'sizes': [[640, 480]], - 'transactionId': 'df629792-c9ae-481e-9ce1-eaa83bde4cdb' - } - ] -}; - -let badBidRequest = { - 'bidderCode': 'spotx', - 'bids': [ - { - 'bidId': '2626663210bd26', - 'bidder': 'spotx', - 'mediaType': 'video', - 'params': { - 'placementId': '123456789', - 'video': { - 'slot': 'contentSpotx', - 'video_slot': 'contentElementSpotx' - } - }, - 'placementCode': 'video1', - } - ] -}; - -var xhrResponse = JSON.stringify({ - 'id': CHANNEL_ID.toString(), - 'cur': 'USD', - 'seatbid': [ - { - 'bid': [ - { - 'id': '47e.fc9b5.90ede6', - 'impid': '1497549328279', - 'impression_guid': 'e2514a4651f311e7b50f113c04e90000', - 'price': '20', - 'adm': '<\/VASTAdTagURI><\/Wrapper><\/Ad><\/VAST>', - 'adomain': 'null', - 'crid': '47e.fc9b5.90ede6', - 'cid': 'null', - 'ext': { - 'cache_key': CACHE_KEY - } - } - ] - } - ] -}); - -describe('spotx adapter tests', () => { - describe('callBids', () => { - let server; - let adapter; - - beforeEach(() => { - adapter = new Adapter(); - - var slot = document.createElement('div'); - slot.setAttribute('id', 'contentSpotx'); - document.body.appendChild(slot); - - var videoSlot = document.createElement('video'); - videoSlot.setAttribute('id', 'contentElementSpotx'); - slot.appendChild(videoSlot); - - var source1 = document.createElement('source'); - source1.setAttribute('src', 'http://rmcdn.2mdn.net/Demo/vast_inspector/android.mp4'); - videoSlot.appendChild(source1); - - bidRequest.bids[0].params.video.slot = slot; - bidRequest.bids[0].params.video.video_slot = videoSlot; - - server = sinon.fakeServer.create(); - server.respondImmediately = true; - }); - - afterEach(() => { - var slot = document.getElementById('contentSpotx'); - while (slot.firstChild) { - slot.removeChild(slot.firstChild); - } - var body = slot.parentElement; - body.removeChild(slot); - - server.restore(); - }); - - it('should load Direct AdOS onto page', () => { - sinon.spy(adLoader, 'loadScript'); - - adapter.callBids(bidRequest); - - sinon.assert.calledOnce(adLoader.loadScript); - expect(adLoader.loadScript.firstCall.args[0]).to.equal('//js.spotx.tv/directsdk/v1/' + CHANNEL_ID + '.js'); - expect(adLoader.loadScript.firstCall.args[1]).to.be.a('function'); - - adLoader.loadScript.restore(); - }); - - it('should not load Direct AdOS onto page if no bid is provided', () => { - sinon.spy(adLoader, 'loadScript'); - - adapter.callBids(); - sinon.assert.notCalled(adLoader.loadScript); - adLoader.loadScript.restore(); - }); - - describe('bid response tests', () => { - let loadScriptStub; - let getAdServerKVPsStub; - - before(() => { - let response = { - spotx_bid: 20, - spotx_ad_key: CACHE_KEY - }; - - getAdServerKVPsStub = sinon.stub(); - getAdServerKVPsStub.onCall(0).returns({ - then: function (successCb) { - return successCb(response); - } - }); - - getAdServerKVPsStub.onCall(1).returns({ - then: function (successCb, failureCb) { - return failureCb(); - } - }); - - window.SpotX = { - DirectAdOS: function(options) { - return { - getAdServerKVPs: getAdServerKVPsStub - } - } - }; - - loadScriptStub = sinon.stub(adLoader, 'loadScript', function(url, callback) { - callback(); - }); - }); - - after(() => { - loadScriptStub.restore(); - }); - - it('should add bid response on success', (done) => { - sinon.stub(bidManager, 'addBidResponse', (placementCode, bid) => { - expect(placementCode).to.equal('video1'); - expect(bid.bidderCode).to.equal('spotx'); - expect(bid.cpm).to.equal(20); - expect(bid.mediaType).to.equal('video'); - expect(bid.statusMessage).to.equal('Bid available'); - expect(bid.vastUrl).to.equal('//search.spotxchange.com/ad/vast.html?key=' + CACHE_KEY); - - bidManager.addBidResponse.restore(); - done(); - }); - - server.respondWith((request) => { - if (request.url.match(/openrtb\/2.3\/dados/) && request.method === 'POST') { - request.respond(200, {}, xhrResponse); - } - }); - - adapter.callBids(bidRequest); - }); - - it('should add failed bid response on error', (done) => { - sinon.stub(bidManager, 'addBidResponse', (placementCode, bid) => { - expect(placementCode).to.equal('video1'); - expect(bid.bidderCode).to.equal('spotx'); - expect(bid.statusMessage).to.equal('Bid returned empty or error response'); - expect(bid.cpm).to.be.undefined; - expect(bid.vastUrl).to.be.undefined; - - bidManager.addBidResponse.restore(); - done(); - }); - - server.respondWith((request) => { - if (request.url.match(/openrtb\/2.3\/dados/) && request.method === 'POST') { - request.respond(204, {}, ''); - } - }); - - adapter.callBids(bidRequest); - }); - }); - }); -}); diff --git a/test/spec/modules/stickyadstvBidAdapter_spec.js b/test/spec/modules/stickyadstvBidAdapter_spec.js deleted file mode 100644 index c0f35b1c406..00000000000 --- a/test/spec/modules/stickyadstvBidAdapter_spec.js +++ /dev/null @@ -1,225 +0,0 @@ -import {expect} from 'chai'; -import {assert} from 'chai'; -import Adapter from '../../../modules/stickyadstvBidAdapter'; -import adLoader from '../../../src/adloader'; - -describe('StickyAdsTV Adapter', function () { - var adapter = void 0; - var sandbox = void 0; - var bidsRequestBuff = void 0; - var bidderRequest = { - bidderCode: 'stickyadstv', - bids: [{ - bidId: 'bidId1', - bidder: 'stickyadstv', - placementCode: 'foo', - sizes: [[300, 250]], - params: { - zoneId: '2003', - format: 'screen-roll' - } - }, { - bidId: 'bidId2', - bidder: 'stickyadstv', - placementCode: 'bar', - sizes: [[728, 90]], - params: { - zoneId: '5562003' - } - }, { - bidId: 'bidId3', - bidder: 'stickyadstv', - placementCode: '', - sizes: [[300, 600]], - params: { - zoneId: '123456' - } - }, { - bidId: 'bidId4', - bidder: 'stickyadstv', - placementCode: 'coo', - sizes: [[300, 600]], - params: { - wrong: 'missing zoneId' - } - }] - }; - - beforeEach(function () { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - bidsRequestBuff = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - }); - - afterEach(function () { - sandbox.restore(); - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestBuff; - }); - - describe('callBids', function () { - beforeEach(function () { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - }); - - it('should be called twice', function () { - sinon.assert.calledTwice(adLoader.loadScript); - }); - - it('should have load screenroll and mustang script', function () { - var url = void 0; - - url = adLoader.loadScript.firstCall.args[0]; - expect(url).to.equal('//cdn.stickyadstv.com/prime-time/screen-roll.min.js'); - - url = adLoader.loadScript.secondCall.args[0]; - expect(url).to.equal('//cdn.stickyadstv.com/mustang/mustang.min.js'); - }); - }); - - describe('getBid', function () { - let bidResponse; - let loadConfig; - let getPricingCalled; - - beforeEach(function () { - // Mock VastLoader for test purpose - window.com = { - stickyadstv: { - vast: { - VastLoader: function() { - this.getVast = function() { - return { - getPricing: function() { - getPricingCalled = true; - return {currency: 'USD', price: 4.000} - } - }; - }; - - this.load = function(config, listener) { - loadConfig = config; - listener.onSuccess(); - }; - } - }, - screenroll: { - getPlayerSize: function() { - return '123x456'; - } - } - } - }; - - adapter.getBid(bidderRequest.bids[0], function(bidObject) { - bidResponse = bidObject; - }); - }); - - afterEach(function() { - delete window.com.stickyadstv.vast.VastLoader; - delete window.com.stickyadstv.vast; - delete window.com.stickyadstv.screenroll; - delete window.com.stickyadstv; - }); - - it('should return a valid bidObject', function () { - expect(bidResponse).to.have.property('cpm', 4.000); - expect(bidResponse).to.have.property('ad', ""); - expect(bidResponse).to.have.property('bidderCode', 'stickyadstv'); - expect(bidResponse).to.have.property('currencyCode', 'USD'); - expect(bidResponse).to.have.property('width', 300); - expect(bidResponse).to.have.property('height', 250); - expect(bidResponse.getStatusCode()).to.equal(1); - }); - - it('should have called load with proper config', function () { - expect(loadConfig).to.have.property('playerSize', '123x456'); - expect(loadConfig).to.have.property('zoneId', '2003'); - }); - - it('should have called getPricing', function () { - expect(getPricingCalled).to.equal(true); - }); - }); - - describe('formatBidObject', function () { - it('should create a valid bid object', function () { - let result = adapter.formatBidObject('', true, {currency: 'EUR', price: '1.2345'}, '
sample
', 200, 300); - - expect(result).to.have.property('cpm', '1.2345'); - expect(result).to.have.property('ad', '
sample
'); - expect(result).to.have.property('currencyCode', 'EUR'); - expect(result).to.have.property('width', 200); - expect(result).to.have.property('height', 300); - expect(result.getStatusCode()).to.equal(1); - }); - - it('should create a invalid bid object because price is not defined', function () { - let result = adapter.formatBidObject('', true, null, '
sample
', 200, 300); - - expect(result.getStatusCode()).to.equal(2); - }); - - it('should create a invalid bid object', function () { - let result = adapter.formatBidObject('', false, {currency: 'EUR', price: '1.2345'}, '
sample
', 200, 300); - - expect(result.getStatusCode()).to.equal(2); - }); - }); - - describe('formatAdHTML', function () { - it('should create an inBanner ad format', function () { - let result = adapter.formatAdHTML({placementCode: 'placementCodeValue', params: {}}, [200, 300]); - - expect(result).to.equal('
'); - }); - - it('should create an intext ad format', function () { - let result = adapter.formatAdHTML({placementCode: 'placementCodeValue', params: {format: 'intext-roll', auto: 'v2', smartPlay: 'true'}}, [200, 300]); - - expect(result).to.equal(''); - }); - - it('should create a screenroll ad format', function () { - let result = adapter.formatAdHTML({placementCode: 'placementCodeValue', params: {format: 'screen-roll', smartPlay: 'true'}}, [200, 300]); - - expect(result).to.equal(''); - }); - }); - - describe('getBiggerSize', function () { - it('should return the bigger size', function () { - let result = adapter.getBiggerSize([[1, 4000], [4000, 1], [200, 300], [0, 0]]); - - expect(result[0]).to.equal(200); - expect(result[1]).to.equal(300); - }); - }); - - describe('top most window', function () { - it('should return the top most window', function () { - let result = adapter.getTopMostWindow(); - - expect(result).to.equal(window.top); - }); - }); - - describe('get component id', function() { - it('should return valid component ids', function() { - expect(adapter.getComponentId('inbanner')).to.equal('mustang'); - expect(adapter.getComponentId('intext-roll')).to.equal('intext-roll'); - expect(adapter.getComponentId('screen-roll')).to.equal('screen-roll'); - }); - }); - - describe('get API name', function() { - it('should return valid API names', function() { - expect(adapter.getAPIName()).to.equal(''); - expect(adapter.getAPIName('intext-roll')).to.equal('intextroll'); - expect(adapter.getAPIName('screen-roll')).to.equal('screenroll'); - expect(adapter.getAPIName('floorad')).to.equal('floorad'); - }); - }); -}); diff --git a/test/spec/modules/tapsenseBidAdapter_spec.js b/test/spec/modules/tapsenseBidAdapter_spec.js deleted file mode 100644 index 71f61af2a65..00000000000 --- a/test/spec/modules/tapsenseBidAdapter_spec.js +++ /dev/null @@ -1,257 +0,0 @@ -import { expect } from 'chai'; -import Adapter from 'modules/tapsenseBidAdapter'; -import bidmanager from 'src/bidmanager'; -import adloader from 'src/adloader'; -import * as utils from 'src/utils'; - -const DEFAULT_BIDDER_REQUEST = { - 'bidderCode': 'tapsense', - 'bidderRequestId': '141ed07a281ca3', - 'requestId': 'b202e550-b0f7-4fb9-bfb4-1aa80f1795b4', - 'start': new Date().getTime(), - 'bids': [ - { - 'sizes': undefined, // set values in tests - 'bidder': 'tapsense', - 'bidId': '2b211418dd0575', - 'bidderRequestId': '141ed07a281ca3', - 'placementCode': 'thisisatest', - 'params': { - 'ufid': 'thisisaufid', - 'refer': 'thisisarefer', - 'version': '0.0.1', - 'ad_unit_id': 'thisisanadunitid', - 'device_id': 'thisisadeviceid', - 'lat': 'thisislat', - 'long': 'thisisalong', - 'user': 'thisisanidfa', - 'price_floor': 0.01 - } - } - ] -}; - -const SUCCESSFUL_RESPONSE = { - 'count_ad_units': 1, - 'status': { - 'value': 'ok', - }, - 'ad_units': [ - { - html: '', - imp_url: 'https://i.tapsense.com' - } - ], - 'id': 'thisisanid', - 'width': 320, - 'height': 50, - 'time': new Date().getTime() -} - -const UNSUCCESSFUL_RESPONSE = { - 'count_ad_units': 0, - 'status': { - 'value': 'nofill' // will be set in test - }, - 'time': new Date().getTime() -} - -function duplicate(obj) { - return JSON.parse(JSON.stringify(obj)); -} - -function makeSuccessfulRequest(adapter) { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = [[320, 50], [500, 500]]; - adapter.callBids(modifiedReq); - return modifiedReq.bids; -} - -describe('TapSenseAdapter', () => { - let adapter, sandbox; - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - afterEach(() => { - sandbox.restore(); - }) - - describe('request function', () => { - beforeEach(() => { - sandbox.stub(adloader, 'loadScript'); - }); - afterEach(() => { - sandbox.restore(); - }); - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - it('requires parameters to make request', () => { - adapter.callBids({}); - sinon.assert.notCalled(adloader.loadScript); - }); - it('does not make a request if missing user', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - delete modifiedReq.bids.user - adapter.callBids(modifiedReq); - sinon.assert.notCalled(adloader.loadScript); - }); - it('does not make a request if missing ad_unit_id', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - delete modifiedReq.bids.ad_unit_id - adapter.callBids(modifiedReq); - sinon.assert.notCalled(adloader.loadScript); - }); - it('does not make a request if ad sizes are incorrect', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = [[500, 500]]; - adapter.callBids(modifiedReq); - sinon.assert.notCalled(adloader.loadScript); - }); - it('does not make a request if ad sizes are invalid format', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = 1234; - adapter.callBids(modifiedReq); - sinon.assert.notCalled(adloader.loadScript); - }); - - describe('requesting an ad', () => { - afterEach(() => { - sandbox.restore(); - }) - it('makes a request if valid sizes are provided (nested array)', () => { - makeSuccessfulRequest(adapter); - sinon.assert.calledOnce(adloader.loadScript); - expect(adloader.loadScript.firstCall.args[0]).to.contain( - 'ads04.tapsense.com' - ); - }); - it('handles a singles array for size parameter', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = [320, 50]; - adapter.callBids(modifiedReq); - expect(adloader.loadScript.firstCall.args[0]).to.contain( - 'ads04.tapsense.com' - ); - }); - it('handles a string for size parameter', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = '320x50'; - adapter.callBids(modifiedReq); - expect(adloader.loadScript.firstCall.args[0]).to.contain( - 'ads04.tapsense.com' - ); - }); - it('handles a string with multiple sizes for size parameter', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = '320x50,500x500'; - adapter.callBids(modifiedReq); - expect(adloader.loadScript.firstCall.args[0]).to.contain( - 'ads04.tapsense.com' - ); - }); - it('appends bid params as a query string when requesting ad', () => { - makeSuccessfulRequest(adapter); - sinon.assert.calledOnce(adloader.loadScript); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /ufid=thisisaufid&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /refer=thisisarefer&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /version=[^&]+&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /jsonp=1&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /ad_unit_id=thisisanadunitid&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /device_id=thisisadeviceid&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /lat=thisislat&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /long=thisisalong&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /user=thisisanidfa&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /price_floor=0\.01&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /callback=$$PREBID_GLOBAL$$\.tapsense\.callback_with_price_.+&/ - ); - }) - }) - }); - - describe('generateCallback', () => { - beforeEach(() => { - sandbox.stub(adloader, 'loadScript'); - }); - afterEach(() => { - sandbox.restore(); - }); - it('generates callback in namespaced object with correct bidder id', () => { - makeSuccessfulRequest(adapter); - expect($$PREBID_GLOBAL$$.tapsense.callback_with_price_2b211418dd0575).to.exist.and.to.be.a('function'); - }) - }); - - describe('response', () => { - beforeEach(() => { - sandbox.stub(bidmanager, 'addBidResponse'); - sandbox.stub(adloader, 'loadScript'); - let bids = makeSuccessfulRequest(adapter); - sandbox.stub(utils, 'getBidRequest', (id) => { - return bids.find((item) => { return item.bidId === id }); - }) - }); - afterEach(() => { - sandbox.restore(); - }); - describe('successful response', () => { - beforeEach(() => { - $$PREBID_GLOBAL$$.tapsense.callback_with_price_2b211418dd0575(SUCCESSFUL_RESPONSE, 1.2); - }); - it('called the bidmanager and registers a bid', () => { - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(1); - }); - it('should have the correct placementCode', () => { - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('thisisatest'); - }); - }); - describe('unsuccessful response', () => { - beforeEach(() => { - $$PREBID_GLOBAL$$.tapsense.callback_with_price_2b211418dd0575(UNSUCCESSFUL_RESPONSE, 1.2); - }) - it('should call the bidmanger and register an invalid bid', () => { - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2); - }); - it('should have the correct placementCode', () => { - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('thisisatest'); - }) - }); - describe('no response/timeout', () => { - it('should not register any bids', () => { - sinon.assert.notCalled(bidmanager.addBidResponse); - }) - }); - describe('edge cases', () => { - it('does not register a bid if no price is supplied', () => { - sandbox.stub(utils, 'logMessage'); - $$PREBID_GLOBAL$$.tapsense.callback_with_price_2b211418dd0575(SUCCESSFUL_RESPONSE); - sinon.assert.notCalled(bidmanager.addBidResponse); - }); - }); - }); -}) diff --git a/test/spec/modules/thoughtleadrBidAdapter_spec.js b/test/spec/modules/thoughtleadrBidAdapter_spec.js deleted file mode 100644 index 3cd2a49e888..00000000000 --- a/test/spec/modules/thoughtleadrBidAdapter_spec.js +++ /dev/null @@ -1,108 +0,0 @@ -'use strict'; -var chai_1 = require('chai'); -var ta = require('modules/thoughtleadrBidAdapter'); -var bidfactory = require('src/bidfactory'); -var ajax = require('src/ajax'); -var Adapter = ta; - -describe('thoughtleadr adapter tests', function () { - var sandbox; - var adapter; - var request; - var createBid; - var ajaxMock; - - before(function () { - sandbox = sinon.sandbox.create(); - }); - - beforeEach(function () { - createBid = sandbox.spy(bidfactory, 'createBid'); - adapter = new Adapter(); - request = { - bidderCode: 'thoughtleadr', - bids: [{ - bidder: 'thoughtleadr', - placementCode: 'abc-123', - sizes: [[300, 250], [400, 400]], - params: { - placementId: 'test-placement', - }, - }], - }; - }); - - afterEach(function () { - sandbox.restore(); - }); - - describe('handleBids', function () { - it('should filter invalid bids', function () { - request.bids.unshift({ - bidder: 'thoughtleadr', - placementCode: 'abc-123', - sizes: [[300, 250], [400, 400]], - params: {}, - }); - request.bids.push({ - bidder: 'thoughtleadr', - placementCode: 'abc-123', - sizes: [[300, 250], [400, 400]], - params: { - incorrectParam: 123, - }, - }); - var requestPlacement = sinon.spy(adapter, 'requestPlacement'); - adapter.callBids(request); - chai_1.expect(requestPlacement.callCount).to.be.equal(1); - chai_1.expect(requestPlacement.getCall(0).args[0]).to.be.equal(request.bids[1]); - }); - }); - - describe('requestPlacement', function () { - it('should request header-bid.json', function () { - ajaxMock = sandbox.stub(ajax, 'ajax', function (url, cb) { - cb(JSON.stringify({ - header_bid_token: 'asd', - media_type: 'article', - amount: 2 - })); - }); - adapter.callBids(request); - chai_1.expect(ajaxMock.callCount).to.be.equal(1); - chai_1.expect(ajaxMock.firstCall.args[0]).to.contains( - '//a.thoughtleadr.com/v4/test-placement/header-bid.json?uid='); - chai_1.expect(createBid.firstCall.args[0]).to.be.equal(1); - }); - - it('should request header-bid.json without bids', function () { - ajaxMock = sandbox.stub(ajax, 'ajax', function (url, cb) { - cb(JSON.stringify({})); - }); - - adapter.callBids(request); - chai_1.expect(ajaxMock.callCount).to.be.equal(1); - chai_1.expect(ajaxMock.firstCall.args[0]).to.contains( - '//a.thoughtleadr.com/v4/test-placement/header-bid.json?uid='); - chai_1.expect(createBid.firstCall.args[0]).to.be.equal(2); - }); - - it('should sync cookies', function () { - ajaxMock = sandbox.stub(ajax, 'ajax', function (url, cb) { - cb(JSON.stringify({ - header_bid_token: 'asd', - media_type: 'article', - amount: 2, - cookie_syncs: [''] - })); - }); - adapter.callBids(request); - - var element = document.getElementById('tldr-cookie-sync-div'); - var iframes = element.getElementsByTagName('iframe'); - chai_1.expect(iframes.length).to.be.equal(1); - - chai_1.expect(iframes[0].contentDocument.body.innerHTML).to.be.equal(''); - }); - }); -}); diff --git a/test/spec/modules/tremorBidAdapter_spec.js b/test/spec/modules/tremorBidAdapter_spec.js deleted file mode 100644 index c09c1112b3e..00000000000 --- a/test/spec/modules/tremorBidAdapter_spec.js +++ /dev/null @@ -1,173 +0,0 @@ -import {expect} from 'chai'; -import Adapter from 'modules/tremorBidAdapter'; -import bidmanager from 'src/bidmanager'; - -const AD_CODE = 'ssp-!demo!-lufip'; -const SUPPLY_CODE = 'ssp-%21demo%21-rm6rh'; -const SIZES = [640, 480]; -const REQUEST = { - 'code': 'video1', - 'sizes': [640, 480], - 'mediaType': 'video', - 'bids': [{ - 'bidder': 'tremor', - 'params': { - 'mediaId': 'MyCoolVideo', - 'mediaUrl': '', - 'mediaTitle': '', - 'contentLength': '', - 'floor': '', - 'efloor': '', - 'custom': '', - 'categories': '', - 'keywords': '', - 'blockDomains': '', - 'c2': '', - 'c3': '', - 'c4': '', - 'skip': '', - 'skipmin': '', - 'skipafter': '', - 'delivery': '', - 'placement': '', - 'videoMinBitrate': '', - 'videoMaxBitrate': '' - } - }] -}; - -const RESPONSE = { - 'cur': 'USD', - 'id': '3dba13e35f3d42f998bc7e65fd871889', - 'seatbid': [{ - 'seat': 'TremorVideo', - 'bid': [{ - 'adomain': [], - 'price': 0.50000, - 'id': '3dba13e35f3d42f998bc7e65fd871889', - 'adm': '\n Tremor Video Test MP4 Creative \n\n \n\n\n\n\n\n \n\n \n\n', - 'impid': '1' - }] - }] -}; - -describe('TremorBidAdapter', () => { - let adapter; - - beforeEach(() => adapter = new Adapter()); - - describe('request function', () => { - let xhr; - let requests; - - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => xhr.restore()); - - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - it('requires paramters to make request', () => { - adapter.callBids({}); - expect(requests).to.be.empty; - }); - - it('requires adCode && supplyCode', () => { - let backup = REQUEST.bids[0].params; - REQUEST.bids[0].params = {adCode: AD_CODE}; - adapter.callBids(REQUEST); - expect(requests).to.be.empty; - REQUEST.bids[0].params = backup; - }); - - it('requires proper sizes to make a bid request', () => { - let backupBid = REQUEST; - backupBid.sizes = []; - adapter.callBids(backupBid); - expect(requests).to.be.empty; - }); - - it('generates a proper ad call URL', () => { - REQUEST.bids[0].params.adCode = AD_CODE; - REQUEST.bids[0].params.supplyCode = SUPPLY_CODE; - REQUEST.bids[0].sizes = SIZES; - adapter.callBids(REQUEST); - const requestUrl = requests[0].url; - let srcPageURl = ('&srcPageUrl=' + encodeURIComponent(document.location.href)); - expect(requestUrl).to.equal('http://ssp-%21demo%21-rm6rh.ads.tremorhub.com/ad/tag?adCode=ssp-!demo!-lufip&playerWidth=640&playerHeight=480' + srcPageURl + '&mediaId=MyCoolVideo&fmt=json'); - }); - - it('generates a proper ad call URL given a different size format', () => { - REQUEST.bids[0].params.adCode = AD_CODE; - REQUEST.bids[0].params.supplyCode = SUPPLY_CODE; - REQUEST.bids[0].sizes = [SIZES]; - adapter.callBids(REQUEST); - const requestUrl = requests[0].url; - let srcPageURl = ('&srcPageUrl=' + encodeURIComponent(document.location.href)); - expect(requestUrl).to.equal('http://ssp-%21demo%21-rm6rh.ads.tremorhub.com/ad/tag?adCode=ssp-!demo!-lufip&playerWidth=640&playerHeight=480' + srcPageURl + '&mediaId=MyCoolVideo&fmt=json'); - }); - }); - - describe('response handler', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create(); - sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('registers bids', () => { - server.respondWith(JSON.stringify(RESPONSE)); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid available'); - expect(response).to.have.property('cpm', 0.50000); - }); - - it('handles nobid responses', () => { - server.respondWith(JSON.stringify({ - 'cur': 'USD', - 'id': 'ff83ce7e00df41c9bce79b651afc7c51', - 'seatbid': [] - })); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property( - 'statusMessage', - 'Bid returned empty or error response' - ); - }); - - it('handles JSON.parse errors', () => { - server.respondWith(''); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property( - 'statusMessage', - 'Bid returned empty or error response' - ); - }); - }); -}); diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js deleted file mode 100644 index 95658883fd0..00000000000 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ /dev/null @@ -1,226 +0,0 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/tripleliftBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; -import {parse as parseURL} from '../../../src/url'; - -describe('triplelift adapter', () => { - let bidsRequestedOriginal; - let adapter; - let sandbox; - - const bidderRequest = { - bidderCode: 'triplelift', - bids: [ - { - bidId: 'bidId1', - bidder: 'triplelift', - placementCode: 'foo', - sizes: [[728, 90]], - params: { - inventoryCode: 'codeA' - } - }, - { - bidId: 'bidId2', - bidder: 'triplelift', - placementCode: 'bar', - sizes: [[300, 600]], - params: { - inventoryCode: 'codeB', - floor: 1 - } - } - ] - }; - - beforeEach(() => { - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe('callBids', () => { - let firstBidScriptURL; - let secondBidScriptURL; - - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - - firstBidScriptURL = adLoader.loadScript.firstCall.args[0]; - secondBidScriptURL = adLoader.loadScript.secondCall.args[0] - }); - - it('should load a script for each bid request', () => { - sinon.assert.calledTwice(adLoader.loadScript); - - let route = 'http://tlx.3lift.com/header/auction?'; - expect(firstBidScriptURL).to.contain(route); - expect(secondBidScriptURL).to.contain(route); - - let firstScriptParams = parseURL(firstBidScriptURL).search; - expect(firstScriptParams).to.have.property('callback', '$$PREBID_GLOBAL$$.TLCB'); - expect(firstScriptParams).to.have.property('callback_id', 'bidId1'); - expect(firstScriptParams).to.have.property('inv_code', 'codeA'); - expect(firstScriptParams).to.have.property('size', '728x90'); - expect(firstScriptParams).to.have.property('referrer'); - - let secondScriptParams = parseURL(secondBidScriptURL).search; - expect(secondScriptParams).to.have.property('callback', '$$PREBID_GLOBAL$$.TLCB'); - expect(secondScriptParams).to.have.property('callback_id', 'bidId2'); - expect(secondScriptParams).to.have.property('inv_code', 'codeB'); - expect(secondScriptParams).to.have.property('size', '300x600'); - expect(secondScriptParams).to.have.property('floor', '1'); - expect(secondScriptParams).to.have.property('referrer'); - }); - }); - - describe('TLCB', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.TLCB).to.exist.and.to.be.a('function'); - }); - }); - - describe('add bids to the manager', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse1 = { - 'ad': '', - 'callback_id': 'bidId1', - 'cpm': 0.20, - 'height': 90, - 'iurl': '', - 'width': 728 - }; - - let bidderReponse2 = { - 'ad': '', - 'callback_id': 'bidId2', - 'cpm': 0.30, - 'height': 600, - 'iurl': '', - 'width': 300, - 'deal_id': 'dealA' - }; - - $$PREBID_GLOBAL$$.TLCB(bidderReponse1); - $$PREBID_GLOBAL$$.TLCB(bidderReponse2); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidManager.addBidResponse); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidManager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should include the bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should have a good statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(1); - expect(secondBid.getStatusCode()).to.eql(1); - }); - - it('should add the CPM to the bid object', () => { - expect(firstBid).to.have.property('cpm', 0.20); - expect(secondBid).to.have.property('cpm', 0.30); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'triplelift'); - expect(secondBid).to.have.property('bidderCode', 'triplelift'); - }); - - it('should include the ad on the bid object', () => { - expect(firstBid).to.have.property('ad'); - expect(secondBid).to.have.property('ad'); - }); - - it('should include the size on the bid object', () => { - expect(firstBid).to.have.property('width', 728); - expect(firstBid).to.have.property('height', 90); - expect(secondBid).to.have.property('width', 300); - expect(secondBid).to.have.property('height', 600); - }); - - it('should include the dealId on the bid object if present', () => { - expect(firstBid).to.have.property('dealId', undefined); - expect(secondBid).to.have.property('dealId', 'dealA'); - }); - }); - - describe('add empty bids if no bid returned', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse1 = {'status': 'no_bid', 'callback_id': 'bidId1'}; - let bidderReponse2 = {'status': 'no_bid', 'callback_id': 'bidId2'}; - - $$PREBID_GLOBAL$$.TLCB(bidderReponse1); - $$PREBID_GLOBAL$$.TLCB(bidderReponse2); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidManager.addBidResponse); - }); - - it('should include the bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should have an error statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(2); - expect(secondBid.getStatusCode()).to.eql(2); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidManager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'triplelift'); - expect(secondBid).to.have.property('bidderCode', 'triplelift'); - }); - }); -}); diff --git a/test/spec/modules/twengaBidAdapter_spec.js b/test/spec/modules/twengaBidAdapter_spec.js deleted file mode 100644 index dcead6c4578..00000000000 --- a/test/spec/modules/twengaBidAdapter_spec.js +++ /dev/null @@ -1,119 +0,0 @@ -describe('twenga adapter tests', function () { - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - var Adapter = require('modules/twengaBidAdapter'); - var adLoader = require('src/adloader'); - var expect = require('chai').expect; - var bidmanager = require('src/bidmanager'); - var CONSTANTS = require('src/constants.json'); - - var DEFAULT_PARAMS = { - bidderCode: 'twenga', - bids: [{ - bidId: 'tw_abcd1234', - sizes: [[300, 250], [300, 200]], - bidder: 'twenga', - params: { - placementId: 'test', - siteId: 1234, - publisherId: 5678, - currency: 'USD', - bidFloor: 0.5, - country: 'DE' - }, - requestId: 'tw_efgh5678', - placementCode: 'tw_42' - }] - }; - - var BID_RESPONSE = { - result: { - cpm: 10000, - width: 300, - height: 250, - ad: '//rtb.t.c4tw.net', - creative_id: 'test' - }, - callback_uid: 'tw_abcd1234' - }; - - it('sets url parameters', function () { - var stubLoadScript = sinon.stub(adLoader, 'loadScript'); - - (new Adapter()).callBids(DEFAULT_PARAMS); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('rtb.t.c4tw.net'); - expect(parsedBidUrl.pathname).to.equal('/Bid'); - - expect(parsedBidUrlQueryString).to.have.property('s').and.to.equal('h'); - expect(parsedBidUrlQueryString).to.have.property('callback').and.to.equal('$$PREBID_GLOBAL$$.handleTwCB'); - expect(parsedBidUrlQueryString).to.have.property('callback_uid').and.to.equal('tw_abcd1234'); - expect(parsedBidUrlQueryString).to.have.property('id').and.to.equal('test'); - - stubLoadScript.restore(); - }); - - var stringToFunction = function (s) { - var scope = global; - var scopeSplit = s.split('.'); - for (var i = 0; i < scopeSplit.length - 1; i++) { - scope = scope[scopeSplit[i]]; - if (scope == undefined) return; - } - return scope[scopeSplit[scopeSplit.length - 1]]; - }; - - it('creates an empty bid response if no bids', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript', function(url) { - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - var callback = stringToFunction(parsedBidUrlQueryString.callback); - expect(callback).to.exist.and.to.be.a('function'); - callback(undefined); - }); - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - (new Adapter()).callBids(DEFAULT_PARAMS); - - expect(stubAddBidResponse.getCall(0)).to.be.null; - - stubAddBidResponse.restore(); - stubLoadScript.restore(); - }); - - it('creates a bid response if bid is returned', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript', function(url) { - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - $$PREBID_GLOBAL$$._bidsRequested - .push({ bidderCode: DEFAULT_PARAMS.bidderCode, - bids: [{ bidId: parsedBidUrlQueryString.callback_uid, - placementCode: DEFAULT_PARAMS.bids[0].placementCode }]}); - - var callback = stringToFunction(parsedBidUrlQueryString.callback); - expect(callback).to.exist.and.to.be.a('function'); - callback(BID_RESPONSE); - }); - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - (new Adapter()).callBids(DEFAULT_PARAMS); - - var bidResponseAd = stubAddBidResponse.getCall(0).args[1]; - - expect(bidResponseAd).to.have.property('cpm').and.to.equal(BID_RESPONSE.result.cpm / 10000); - expect(bidResponseAd).to.have.property('adUrl').and.to.equal(BID_RESPONSE.result.ad); - expect(bidResponseAd).to.have.property('width').and.to.equal(BID_RESPONSE.result.width); - expect(bidResponseAd).to.have.property('height').and.to.equal(BID_RESPONSE.result.height); - - stubAddBidResponse.restore(); - stubLoadScript.restore(); - }); -}); diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js deleted file mode 100644 index d8ddfc041b6..00000000000 --- a/test/spec/modules/ucfunnelBidAdapter_spec.js +++ /dev/null @@ -1,110 +0,0 @@ -import { expect } from 'chai'; -import Adapter from 'modules/ucfunnelBidAdapter'; -import adapterManager from 'src/adaptermanager'; -import bidManager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; - -describe('ucfunnel adapter tests', function () { - let sandbox; - const adUnit = { // TODO CHANGE - code: 'ucfunnel', - sizes: [[300, 250]], - bids: [{ - bidder: 'ucfunnel', - params: { - adid: 'test-ad-83444226E44368D1E32E49EEBE6D29', - width: 300, - height: 250 - } - }] - }; - - const response = { - ad_id: 'ad-83444226E44368D1E32E49EEBE6D29', - adm: '
', - cpm: 0.01, - height: 250, - width: 300 - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('ucfunnel callBids validation', () => { - let bids, - server; - - beforeEach(() => { - bids = []; - server = sinon.fakeServer.create(); - - sandbox.stub(bidManager, 'addBidResponse', (elemId, bid) => { - bids.push(bid); - }); - }); - - afterEach(() => { - server.restore(); - }); - - let adapter = adapterManager.bidderRegistry['ucfunnel']; - - it('Valid bid-request', () => { - sandbox.stub(adapter, 'callBids'); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - - let bidderRequest = adapter.callBids.getCall(0).args[0]; - - expect(bidderRequest).to.have.property('bids') - .that.is.an('array') - .with.lengthOf(1); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .to.have.property('bidder', 'ucfunnel'); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('sizes') - .that.is.an('array') - .with.lengthOf(1) - .that.deep.equals(adUnit.sizes); - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('adid', 'test-ad-83444226E44368D1E32E49EEBE6D29'); - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('width', 300); - }); - - it('Valid bid-response', () => { - server.respondWith(JSON.stringify( - response - )); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - server.respond(); - - expect(bids).to.be.lengthOf(1); - expect(bids[0].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bids[0].bidderCode).to.equal('ucfunnel'); - expect(bids[0].width).to.equal(300); - expect(bids[0].height).to.equal(250); - expect(bids[0].cpm).to.equal(0.01); - }); - }); -}); - -function clone(obj) { - try { - return JSON.parse(JSON.stringify(obj)); - } catch (e) { - return {}; - } -} diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js deleted file mode 100644 index 067f3ea46d0..00000000000 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ /dev/null @@ -1,278 +0,0 @@ -/* globals describe, it, beforeEach, afterEach, sinon */ -import { expect } from 'chai' -import bidfactory from 'src/bidfactory' -import bidmanager from 'src/bidmanager' -import * as utils from 'src/utils' -import { STATUS } from 'src/constants' -import { Renderer } from 'src/Renderer' -import createUnrulyAdapter from 'modules/unrulyBidAdapter' - -describe('UnrulyAdapter', () => { - function createBidRequestBid({ placementCode }) { - return { - 'bidder': 'unruly', - 'params': { - 'uuid': '74544e00-d43b-4f3a-a799-69d22ce979ce', - 'siteId': 794599, - 'placementId': '5768085' - }, - 'placementCode': placementCode, - 'mediaTypes': { video: { context: 'outstream' } }, - 'transactionId': '62890707-3770-497c-a3b8-d905a2d0cb98', - 'sizes': [ - 640, - 480 - ], - 'bidId': '23b86d8f6335ce', - 'bidderRequestId': '1d5b7474eb5416', - 'requestId': '406fe12b-fa3b-4bd3-b3c8-043951b4dac1' - } - } - - function createParams(...bids) { - return { - 'bidderCode': 'unruly', - 'requestId': '406fe12b-fa3b-4bd3-b3c8-043951b4dac1', - 'bidderRequestId': '1d5b7474eb5416', - 'bids': bids, - 'start': 1495794517251, - 'auctionStart': 1495794517250, - 'timeout': 3000 - } - } - - function createOutStreamExchangeBid({ placementCode, statusCode = 1 }) { - return { - 'ext': { - 'statusCode': statusCode, - 'renderer': { - 'id': 'unruly_inarticle', - 'config': {}, - 'url': 'https://video.unrulymedia.com/native/prebid-loader.js' - }, - 'placementCode': placementCode - }, - 'cpm': 20, - 'bidderCode': 'unruly', - 'width': 323, - 'vastUrl': 'https://targeting.unrulymedia.com/in_article?uuid=74544e00-d43b-4f3a-a799-69d22ce979ce&supported_mime_type=application/javascript&supported_mime_type=video/mp4&tj=%7B%22site%22%3A%7B%22lang%22%3A%22en-GB%22%2C%22ref%22%3A%22%22%2C%22page%22%3A%22http%3A%2F%2Fdemo.unrulymedia.com%2FinArticle%2Finarticle_nypost_upbeat%2Ftravel_magazines.html%22%2C%22domain%22%3A%22demo.unrulymedia.com%22%7D%2C%22user%22%3A%7B%22profile%22%3A%7B%22quantcast%22%3A%7B%22segments%22%3A%5B%7B%22id%22%3A%22D%22%7D%2C%7B%22id%22%3A%22T%22%7D%5D%7D%7D%7D%7D&video_width=618&video_height=347', - 'bidId': 'foo', - 'height': 323 - } - } - - function createInStreamExchangeBid({ placementCode, statusCode = 1 }) { - return { - 'ext': { - 'statusCode': statusCode, - 'placementCode': placementCode - }, - 'cpm': 20, - 'bidderCode': 'unruly', - 'width': 323, - 'vastUrl': 'https://targeting.unrulymedia.com/in_article?uuid=74544e00-d43b-4f3a-a799-69d22ce979ce&supported_mime_type=application/javascript&supported_mime_type=video/mp4&tj=%7B%22site%22%3A%7B%22lang%22%3A%22en-GB%22%2C%22ref%22%3A%22%22%2C%22page%22%3A%22http%3A%2F%2Fdemo.unrulymedia.com%2FinArticle%2Finarticle_nypost_upbeat%2Ftravel_magazines.html%22%2C%22domain%22%3A%22demo.unrulymedia.com%22%7D%2C%22user%22%3A%7B%22profile%22%3A%7B%22quantcast%22%3A%7B%22segments%22%3A%5B%7B%22id%22%3A%22D%22%7D%2C%7B%22id%22%3A%22T%22%7D%5D%7D%7D%7D%7D&video_width=618&video_height=347', - 'bidId': 'foo', - 'height': 323 - } - } - - function createExchangeResponse(...bids) { - return { - 'bids': bids - } - } - - let adapter - let server - let sandbox - let fakeRenderer - - beforeEach(() => { - adapter = createUnrulyAdapter() - adapter.exchangeUrl = 'http://localhost:9000/prebid' - - sandbox = sinon.sandbox.create() - sandbox.stub(bidmanager, 'addBidResponse') - sandbox.stub(bidfactory, 'createBid') - sandbox.stub(utils, 'logError') - - fakeRenderer = { - setRender: sinon.stub() - } - - sandbox.stub(Renderer, 'install') - Renderer.install.returns(fakeRenderer) - - server = sinon.fakeServer.create() - }) - - afterEach(() => { - sandbox.restore() - server.restore() - delete parent.window.unruly - }) - - describe('callBids', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function') - }) - - it('requires bids to make request', () => { - adapter.callBids({}) - expect(server.requests).to.be.empty - }) - - it('requires at least one bid to make request', () => { - adapter.callBids({ bids: [] }) - expect(server.requests).to.be.empty - }) - - it('passes bids through to exchange', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - adapter.callBids(params) - - expect(server.requests).to.have.length(1) - expect(server.requests[0].url).to.equal('http://localhost:9000/prebid') - - const requestBody = JSON.parse(server.requests[0].requestBody) - expect(requestBody).to.deep.equal({ - 'bidRequests': params.bids - }) - }) - - it('creates a bid response using status code from exchange for each bid and passes in the exchange response', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - const exchangeBid1 = createOutStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeBid2 = createOutStreamExchangeBid({ placementCode: 'placement2', statusCode: 2 }) - const exchangeResponse = createExchangeResponse(exchangeBid1, exchangeBid2) - - server.respondWith(JSON.stringify(exchangeResponse)) - bidfactory.createBid.returns({}) - - adapter.callBids(params) - server.respond() - - sinon.assert.calledTwice(bidfactory.createBid) - sinon.assert.calledWith(bidfactory.createBid, exchangeBid1.ext.statusCode, exchangeResponse.bids[0]) - sinon.assert.calledWith(bidfactory.createBid, exchangeBid2.ext.statusCode, exchangeResponse.bids[1]) - }) - - it('adds the bid response to the bid manager', () => { - const fakeBid = {} - - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - const exchangeBid = createOutStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeResponse = createExchangeResponse(exchangeBid) - - server.respondWith(JSON.stringify(exchangeResponse)) - bidfactory.createBid.withArgs(exchangeBid.ext.statusCode).returns(fakeBid) - - adapter.callBids(params) - server.respond() - - sinon.assert.calledOnce(bidmanager.addBidResponse) - sinon.assert.calledWith(bidmanager.addBidResponse, exchangeBid.ext.placementCode, fakeBid) - }) - - describe('on invalid exchange response', () => { - it('should create NO_BID response for each bid request bid', () => { - const bidRequestBid1 = createBidRequestBid({ placementCode: 'placement1' }) - const bidRequestBid2 = createBidRequestBid({ placementCode: 'placement2' }) - const params = createParams(bidRequestBid1, bidRequestBid2) - const expectedBid = { 'some': 'props' } - - server.respondWith('this is not json') - bidfactory.createBid.withArgs(STATUS.NO_BID).returns(expectedBid) - - adapter.callBids(params) - server.respond() - - sinon.assert.calledOnce(utils.logError) - sinon.assert.calledTwice(bidmanager.addBidResponse) - sinon.assert.calledWith(bidmanager.addBidResponse, bidRequestBid1.placementCode, expectedBid) - sinon.assert.calledWith(bidmanager.addBidResponse, bidRequestBid2.placementCode, expectedBid) - }) - }) - - describe('InStream', () => { - it('merges bid response defaults', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - const fakeBidDefaults = { some: 'default' } - const fakeBid = Object.assign({}, fakeBidDefaults) - - const exchangeBid = createInStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeResponse = createExchangeResponse(exchangeBid) - server.respondWith(JSON.stringify(exchangeResponse)) - - bidfactory.createBid.withArgs(exchangeBid.ext.statusCode).returns(fakeBid) - - adapter.callBids(params) - server.respond() - - sinon.assert.notCalled(Renderer.install) - expect(fakeBid).to.deep.equal(Object.assign( - {}, - fakeBidDefaults, - exchangeBid - )) - }) - }) - - describe('OutStream', () => { - it('merges bid response defaults with exchange bid and renderer', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - const fakeBidDefaults = { some: 'default' } - const fakeBid = Object.assign({}, fakeBidDefaults) - - const exchangeBid = createOutStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeResponse = createExchangeResponse(exchangeBid) - server.respondWith(JSON.stringify(exchangeResponse)) - - bidfactory.createBid.withArgs(exchangeBid.ext.statusCode).returns(fakeBid) - - const fakeRenderer = {} - Renderer.install.withArgs(Object.assign( - {}, - exchangeBid.ext.renderer, - { callback: sinon.match.func } - )).returns(fakeRenderer) - - adapter.callBids(params) - server.respond() - - expect(fakeBid).to.deep.equal(Object.assign( - {}, - fakeBidDefaults, - exchangeBid, - { renderer: fakeRenderer } - )) - }) - - it('bid is placed on the bid queue when render is called', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - const fakeBidDefaults = { some: 'default' } - const fakeBid = Object.assign({}, fakeBidDefaults) - - const exchangeBid = createOutStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeResponse = createExchangeResponse(exchangeBid) - server.respondWith(JSON.stringify(exchangeResponse)) - - bidfactory.createBid.withArgs(exchangeBid.ext.statusCode).returns(fakeBid) - - adapter.callBids(params) - server.respond() - - sinon.assert.calledOnce(fakeRenderer.setRender) - fakeRenderer.setRender.firstCall.args[0]() - - expect(window.top).to.have.deep.property('unruly.native.prebid.uq'); - expect(window.top.unruly.native.prebid.uq).to.deep.equal([['render', fakeBid]]) - }) - }) - }) -}) diff --git a/test/spec/modules/vertozBidAdapter_spec.js b/test/spec/modules/vertozBidAdapter_spec.js deleted file mode 100644 index 87d0ec8c842..00000000000 --- a/test/spec/modules/vertozBidAdapter_spec.js +++ /dev/null @@ -1,140 +0,0 @@ -import {expect} from 'chai'; -import {assert} from 'chai'; -import Adapter from '../../../modules/vertozBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; - -describe('Vertoz Adapter', () => { - let adapter; - let sandbox; - let bidsRequestBuff; - const bidderRequest = { - bidderCode: 'vertoz', - bids: [{ - bidId: 'bidId1', - bidder: 'vertoz', - placementCode: 'foo', - sizes: [ - [300, 250] - ], - params: { - placementId: 'VZ-HB-123' - } - }, { - bidId: 'bidId2', - bidder: 'vertoz', - placementCode: 'bar', - sizes: [ - [728, 90] - ], - params: { - placementId: 'VZ-HB-456' - } - }, { - bidId: 'bidId3', - bidder: 'vertoz', - placementCode: 'coo', - sizes: [ - [300, 600] - ], - params: { - placementId: '' - } - }] - }; - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - bidsRequestBuff = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - }); - - afterEach(() => { - sandbox.restore(); - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestBuff; - }); - - describe('callBids', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - }); - - it('should be called twice', () => { - sinon.assert.calledTwice(adLoader.loadScript); - }); - }); - - describe('Bid response', () => { - let vzBidRequest; - let bidderReponse = { - 'vzhPlacementId': 'VZ-HB-123', - 'bid': '0fac1b8a-6ba0-4641-bd57-2899b1bedeae_0', - 'adWidth': '300', - 'adHeight': '250', - 'cpm': '1.00000000000000', - 'ad': '
', - 'slotBidId': 'bidId1', - 'nurl': '', - 'statusText': 'vertoz:success' - }; - - beforeEach(() => { - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - }); - - describe('success', () => { - let firstBidReg; - let adSpaceId; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - $$PREBID_GLOBAL$$.vzResponse(bidderReponse); - firstBidReg = bidManager.addBidResponse.firstCall.args[1]; - adSpaceId = bidManager.addBidResponse.firstCall.args[0]; - }); - - it('cpm to have property 1.000000', () => { - expect(firstBidReg).to.have.property('cpm', 1.00); - }); - it('adSpaceId should exist and be equal to placementCode', () => { - expect(adSpaceId).to.equal('foo'); - }); - it('should have property ad', () => { - expect(firstBidReg).to.have.property('ad'); - }); - it('should include the size to the bid object', () => { - expect(firstBidReg).to.have.property('width', '300'); - expect(firstBidReg).to.have.property('height', '250'); - }); - }); - - describe('failure', () => { - let secondBidReg; - let adSpaceId; - let bidderResponse = { - 'vzhPlacementId': 'VZ-HB-456', - 'slotBidId': 'bidId2', - 'statusText': 'vertoz:NO_BIDS' - } - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - $$PREBID_GLOBAL$$.vzResponse(bidderResponse); - secondBidReg = bidManager.addBidResponse.firstCall.args[1]; - adSpaceId = bidManager.addBidResponse.firstCall.args[0]; - }); - - it('should not have cpm property', () => { - expect(secondBidReg.cpm).to.be.undefined; - }); - it('adSpaceId should exist and be equal to placementCode', () => { - expect(adSpaceId).to.equal('bar'); - }); - it('should not have ad property', () => { - expect(secondBidReg.ad).to.be.undefined; - }); - }); - }); -}); diff --git a/test/spec/modules/wideorbitBidAdapter_spec.js b/test/spec/modules/wideorbitBidAdapter_spec.js deleted file mode 100644 index 9ace04883e6..00000000000 --- a/test/spec/modules/wideorbitBidAdapter_spec.js +++ /dev/null @@ -1,497 +0,0 @@ -describe('wideorbit adapter tests', function () { - var expect = require('chai').expect; - var urlParse = require('url-parse'); - - // FYI: querystringify will perform encoding/decoding - var querystringify = require('querystringify'); - - var adapter = require('modules/wideorbitBidAdapter'); - var adLoader = require('src/adloader'); - var bidmanager = require('src/bidmanager'); - - describe('creation of bid url', function () { - let stubLoadScript; - - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - it('should be called only once', function () { - var params = { - bidderCode: 'wideorbit', - bids: [ - { - bidder: 'wideorbit', - params: { - pbId: 1, - pId: 101 - }, - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'wideorbit', - params: { - pbId: 1, - site: 'Site 1', - page: 'Page 1', - width: 100, - height: 200, - subPublisher: 'Sub Publisher 1' - }, - placementCode: 'div-gpt-ad-12345-2' - } - ] - }; - - adapter().callBids(params); - - sinon.assert.calledOnce(stubLoadScript); - }); - - it('should fix parameters name', function () { - var params = { - bidderCode: 'wideorbit', - bids: [ - { - bidder: 'wideorbit', - params: { - PBiD: 1, - PID: 101, - ReferRer: 'http://www.foo.com?param1=param1¶m2=param2' - }, - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'wideorbit', - params: { - pbid: 1, - SiTe: 'Site 1', - Page: 'Page 1', - widTH: 100, - HEIGHT: 200, - SUBPublisher: 'Sub Publisher 1' - }, - placementCode: 'div-gpt-ad-12345-2' - } - ] - }; - - adapter().callBids(params); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('p1.atemda.com') - expect(parsedBidUrl.pathname).to.equal('/JSAdservingMP.ashx') - expect(parsedBidUrlQueryString).to.have.property('pc').and.to.equal('2'); - expect(parsedBidUrlQueryString).to.have.property('pbId').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('jsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('tsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('cts').to.have.length.above(0); - expect(parsedBidUrlQueryString).to.have.property('arp').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('fl').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.$$PREBID_GLOBAL$$.handleWideOrbitCallback'); - expect(parsedBidUrlQueryString).to.have.property('mpp').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('cb').to.have.length.above(0); - expect(parsedBidUrlQueryString).to.have.property('hb').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.equal('http://www.foo.com?param1=param1¶m2=param2'); - - expect(parsedBidUrlQueryString).to.have.property('gid0').and.to.equal('div-gpt-ad-12345-1'); - expect(parsedBidUrlQueryString).to.have.property('rpos0').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('ecpm0').and.to.equal(''); - - expect(parsedBidUrlQueryString).to.have.property('gid1').and.to.equal('div-gpt-ad-12345-2'); - expect(parsedBidUrlQueryString).to.have.property('rpos1').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('ecpm1').and.to.equal(''); - - expect(parsedBidUrlQueryString).to.have.property('pId0').and.to.equal('101'); - expect(parsedBidUrlQueryString).to.have.property('rank0').and.to.equal('0'); - - expect(parsedBidUrlQueryString).to.have.property('wsName1').and.to.equal('Site 1'); - expect(parsedBidUrlQueryString).to.have.property('wName1').and.to.equal('Page 1'); - expect(parsedBidUrlQueryString).to.have.property('rank1').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('bfDim1').and.to.equal('100x200'); - expect(parsedBidUrlQueryString).to.have.property('subp1').and.to.equal('Sub Publisher 1'); - }); - - describe('placement by name', function () { - it('should be called with specific parameters for two bids', function () { - var params = { - bidderCode: 'wideorbit', - bids: [ - { - bidder: 'wideorbit', - params: { - pbId: 1, - site: 'Site 1', - page: 'Page 1', - width: 100, - height: 200, - subPublisher: 'Sub Publisher 1', - atf: true - }, - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'wideorbit', - params: { - pbId: 1, - site: 'Site 2', - page: 'Page 2', - width: 200, - height: 300, - rank: 123, - ecpm: 1.8 - }, - placementCode: 'div-gpt-ad-12345-2' - } - ] - }; - - adapter().callBids(params); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('p1.atemda.com') - expect(parsedBidUrl.pathname).to.equal('/JSAdservingMP.ashx') - expect(parsedBidUrlQueryString).to.have.property('pc').and.to.equal('2'); - expect(parsedBidUrlQueryString).to.have.property('pbId').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('jsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('tsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('cts').to.have.length.above(0); - expect(parsedBidUrlQueryString).to.have.property('arp').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('fl').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.$$PREBID_GLOBAL$$.handleWideOrbitCallback'); - expect(parsedBidUrlQueryString).to.have.property('mpp').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('cb').to.have.length.above(0); - expect(parsedBidUrlQueryString).to.have.property('hb').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.be.empty; - - expect(parsedBidUrlQueryString).to.have.property('gid0').and.to.equal('div-gpt-ad-12345-1'); - expect(parsedBidUrlQueryString).to.have.property('rpos0').and.to.equal('1001'); - expect(parsedBidUrlQueryString).to.have.property('ecpm0').and.to.equal(''); - - expect(parsedBidUrlQueryString).to.have.property('gid1').and.to.equal('div-gpt-ad-12345-2'); - expect(parsedBidUrlQueryString).to.have.property('rpos1').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('ecpm1').and.to.equal('1.8'); - - expect(parsedBidUrlQueryString).to.have.property('wsName0').and.to.equal('Site 1'); - expect(parsedBidUrlQueryString).to.have.property('wName0').and.to.equal('Page 1'); - expect(parsedBidUrlQueryString).to.have.property('rank0').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('bfDim0').and.to.equal('100x200'); - expect(parsedBidUrlQueryString).to.have.property('subp0').and.to.equal('Sub Publisher 1'); - - expect(parsedBidUrlQueryString).to.have.property('wsName1').and.to.equal('Site 2'); - expect(parsedBidUrlQueryString).to.have.property('wName1').and.to.equal('Page 2'); - expect(parsedBidUrlQueryString).to.have.property('rank1').and.to.equal('123'); - expect(parsedBidUrlQueryString).to.have.property('bfDim1').and.to.equal('200x300'); - expect(parsedBidUrlQueryString).to.have.property('subp1').and.to.equal(''); - }); - }); - - describe('placement by id', function () { - it('should be called with specific parameters for two bids', function () { - var params = { - bidderCode: 'wideorbit', - bids: [ - { - bidder: 'wideorbit', - params: { - pbId: 1, - pId: 101, - atf: true, - ecpm: 0.8 - }, - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'wideorbit', - params: { - pbId: 1, - pId: 102, - rank: 123 - }, - placementCode: 'div-gpt-ad-12345-2' - } - ] - }; - - adapter().callBids(params); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('p1.atemda.com') - expect(parsedBidUrl.pathname).to.equal('/JSAdservingMP.ashx') - expect(parsedBidUrlQueryString).to.have.property('pc').and.to.equal('2'); - expect(parsedBidUrlQueryString).to.have.property('pbId').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('jsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('tsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('cts').to.have.length.above(0); - expect(parsedBidUrlQueryString).to.have.property('arp').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('fl').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.$$PREBID_GLOBAL$$.handleWideOrbitCallback'); - expect(parsedBidUrlQueryString).to.have.property('mpp').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('cb').to.have.length.above(0); - expect(parsedBidUrlQueryString).to.have.property('hb').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.be.empty; - - expect(parsedBidUrlQueryString).to.have.property('gid0').and.to.equal('div-gpt-ad-12345-1'); - expect(parsedBidUrlQueryString).to.have.property('rpos0').and.to.equal('1001'); - expect(parsedBidUrlQueryString).to.have.property('ecpm0').and.to.equal('0.8'); - - expect(parsedBidUrlQueryString).to.have.property('gid1').and.to.equal('div-gpt-ad-12345-2'); - expect(parsedBidUrlQueryString).to.have.property('rpos1').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('ecpm1').and.to.equal(''); - - expect(parsedBidUrlQueryString).to.have.property('pId0').and.to.equal('101'); - expect(parsedBidUrlQueryString).to.have.property('rank0').and.to.equal('0'); - - expect(parsedBidUrlQueryString).to.have.property('pId1').and.to.equal('102'); - expect(parsedBidUrlQueryString).to.have.property('rank1').and.to.equal('123'); - }); - }); - }); - - // describe('handling of the callback response', function () { - // - // var placements = [ - // { - // ExtPlacementId: 'div-gpt-ad-12345-1', - // Type: 'DirectHTML', - // Bid: 1.3, - // Width: 50, - // Height: 100, - // Source: '
The AD 1 itself...
', - // TrackingCodes: [ - // 'https://www.admeta.com/1.gif' - // ] - // }, - // { - // ExtPlacementId: 'div-gpt-ad-12345-2', - // Type: 'DirectHTML', - // Bid: 1.5, - // Width: 100, - // Height: 200, - // Source: '
The AD 2 itself...
', - // TrackingCodes: [ - // 'http://www.admeta.com/2a.gif', - // '' - // ] - // }, - // { - // ExtPlacementId: 'div-gpt-ad-12345-3', - // Type: 'Other', - // Bid: 1.7, - // Width: 150, - // Height: 250, - // Source: '
The AD 3 itself...
', - // TrackingCodes: [ - // 'http://www.admeta.com/3.gif' - // ] - // } - // ]; - // - // it('callback function should exist', function () { - // expect($$PREBID_GLOBAL$$.handleWideOrbitCallback).to.exist.and.to.be.a('function'); - // }); - // - // it('bidmanager.addBidResponse should be called thrice with correct arguments', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var params = { - // bidderCode: 'wideorbit', - // bids: [ - // { - // bidder: 'wideorbit', - // params: { - // pbId: 1, - // pId: 101 - // }, - // placementCode: 'div-gpt-ad-12345-1' - // }, - // { - // bidder: 'wideorbit', - // params: { - // pbId: 1, - // site: 'Site 1', - // page: 'Page 1', - // width: 100, - // height: 200, - // subPublisher: 'Sub Publisher 1' - // }, - // placementCode: 'div-gpt-ad-12345-2' - // }, - // { - // bidder: 'wideorbit', - // params: { - // pbId: 1, - // pId: 102 - // }, - // placementCode: 'div-gpt-ad-12345-3' - // }, - // ] - // }; - // - // var response = { - // UserMatchings: [ - // { - // Type: 'redirect', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.gif' - // } - // ], - // Placements: placements - // }; - // - // adapter().callBids(params); - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - // var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - // var bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - // var bidObject2 = stubAddBidResponse.getCall(1).args[1]; - // var bidPlacementCode3 = stubAddBidResponse.getCall(2).args[0]; - // var bidObject3 = stubAddBidResponse.getCall(2).args[1]; - // - // expect(bidPlacementCode1).to.equal('div-gpt-ad-12345-1'); - // expect(bidObject1.cpm).to.equal(1.3); - // expect(bidObject1.ad).to.equal('
The AD 1 itself...
'); - // expect(bidObject1.width).to.equal(50); - // expect(bidObject1.height).to.equal(100); - // expect(bidObject1.getStatusCode()).to.equal(1); - // expect(bidObject1.bidderCode).to.equal('wideorbit'); - // - // expect(bidPlacementCode2).to.equal('div-gpt-ad-12345-2'); - // expect(bidObject2.cpm).to.equal(1.50); - // expect(bidObject2.ad).to.equal('
The AD 2 itself...
'); - // expect(bidObject2.width).to.equal(100); - // expect(bidObject2.height).to.equal(200); - // expect(bidObject2.getStatusCode()).to.equal(1); - // expect(bidObject2.bidderCode).to.equal('wideorbit'); - // - // expect(bidPlacementCode3).to.equal('div-gpt-ad-12345-3'); - // expect(bidObject3.getStatusCode()).to.equal(2); - // expect(bidObject3.bidderCode).to.equal('wideorbit'); - // - // sinon.assert.calledWith(stubAddBidResponse, bidPlacementCode1, bidObject1); - // sinon.assert.calledWith(stubAddBidResponse, bidPlacementCode2, bidObject2); - // sinon.assert.calledWith(stubAddBidResponse, bidPlacementCode3, bidObject3); - // - // sinon.assert.calledThrice(stubAddBidResponse); - // - // stubAddBidResponse.restore(); - // - // }); - // - // it('should append an image to the head when type is set to redirect', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var response = { - // UserMatchings: [ - // { - // Type: 'redirect', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.gif' - // } - // ], - // Placements: placements - // }; - // - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // var imgElement = document.querySelectorAll("head img")[0]; - // - // expect(imgElement).to.exist; - // expect(imgElement.src).to.equal('http://www.admeta.com/1.gif'); - // - // stubAddBidResponse.restore(); - // }); - // - // it('should append an iframe to the head when type is set to iframe', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var response = { - // UserMatchings: [ - // { - // Type: 'iframe', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.ashx' - // } - // ], - // Placements: placements - // }; - // - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // var iframeElement = document.querySelectorAll("head iframe")[0]; - // - // expect(iframeElement).to.exist; - // expect(iframeElement.src).to.equal('http://www.admeta.com/1.ashx'); - // - // stubAddBidResponse.restore(); - // - // }); - // - // it('should append an script to the head when type is set to js', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var response = { - // UserMatchings: [ - // { - // Type: 'js', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.js' - // } - // ], - // Placements: placements - // }; - // - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // var scriptElement = document.querySelectorAll("head script")[0]; - // - // expect(scriptElement).to.exist; - // expect(scriptElement.src).to.equal('http://www.admeta.com/1.js'); - // - // stubAddBidResponse.restore(); - // }); - // - // it('should do nothing when type is set to unrecognized type', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var response = { - // UserMatchings: [ - // { - // Type: 'unrecognized', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.js' - // } - // ], - // Placements: placements - // }; - // - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // stubAddBidResponse.restore(); - // }); - // - // }); -}); diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js deleted file mode 100644 index 75486baa25b..00000000000 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ /dev/null @@ -1,226 +0,0 @@ -import { expect } from 'chai'; -import adLoader from '../../../src/adloader'; -import bidManager from '../../../src/bidmanager'; -import Adapter from '../../../modules/widespaceBidAdapter'; - -const ENDPOINT = '//engine.widespace.com/map/engine/hb/dynamic'; - -const TEST = { - BIDDER_CODE: 'widespace', - CPM: 2.0, - PLACEMENT_CODE: 'aPlacementCode', - SID: 'f666bfaf-69cf-4ed9-9262-08247bb274e4', - CUR: 'EUR' -}; - -const BID_REQUEST = { - 'bidderCode': TEST.BIDDER_CODE, - 'requestId': 'e155185b-3eac-4f3c-8182-cdb57a69df3c', - 'bidderRequestId': '38993e482321e7', - 'bids': [ - { - 'bidder': TEST.BIDDER_CODE, - 'params': { - 'sid': TEST.SID, - 'cur': TEST.CUR - }, - 'placementCode': TEST.PLACEMENT_CODE, - 'sizes': [ - [320, 320], - [320, 250] - ], - 'bidId': '45c7f5afb996c1', - 'bidderRequestId': '7101db09af0db3', - 'requestId': 'e155185b-3eac-4f3c-8182-cdb57a69df3d' - } - ], - 'start': 1479664180396, - 'timeout': 5000 -}; - -let bidRequestWithDemoData = BID_REQUEST; - -const BID_RESPONSE = [{ - 'status': 'ok', - 'reqId': '140590112507', - 'adId': 13963, - 'width': 320, - 'height': 320, - 'cpm': 2.0, - 'currency': 'EUR', - 'code': '

This is a banner

', - 'callbackUid': '45c7f5afb996c1', - 'callback': 'pbjs.widespaceHandleCB' -}]; - -const BID_NOAD_RESPONSE = [{ - 'status': 'noad', - 'reqId': '143509454349', - 'adId': 22, - 'width': 1, - 'height': 1, - 'cpm': 0.0, - 'currency': 'EUR', - 'code': '', - 'callbackUid': '45c7f5afb996c1', - 'callback': 'pbjs.widespaceHandleCB' -}] - -describe('WidespaceAdapter', () => { - let adapter; - let sandbox; - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('callBids', () => { - it('should exists and be a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - describe('with valid request parameters', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(BID_REQUEST); - }); - - it('should call the endpoint once per valid bid', () => { - sinon.assert.callCount(adLoader.loadScript, 1); - }); - - it('should include required request parameters', () => { - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include('sid'); - endpointRequest.to.include('hb'); - endpointRequest.to.include('hb.ver'); - endpointRequest.to.include('hb.callbackUid'); - endpointRequest.to.include('hb.callback'); - endpointRequest.to.include('hb.sizes'); - endpointRequest.to.include('hb.name'); - }); - }); - - describe('with valid request parameters (demo data)', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - bidRequestWithDemoData = BID_REQUEST; - }); - - it('should include required request parameters', () => { - bidRequestWithDemoData.bids[0].params.demo = { - gender: 'F', - country: 'UK', - region: 'Greater London', - postal: 'W1U 8EW', - city: 'London', - yob: 1981 - }; - - adapter.callBids(bidRequestWithDemoData); - - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include('hb.demo.gender'); - endpointRequest.to.include('hb.demo.country'); - endpointRequest.to.include('hb.demo.region'); - endpointRequest.to.include('hb.demo.postal'); - endpointRequest.to.include('hb.demo.city'); - endpointRequest.to.include('hb.demo.yob'); - }); - - it('should not include "hb.demo.gender" as a request parameter, if it hasn\'t been specified', () => { - bidRequestWithDemoData.bids[0].params.demo = { - country: 'UK', - region: 'Greater London', - postal: 'W1U 8EW', - city: 'London', - yob: 1981 - }; - - adapter.callBids(bidRequestWithDemoData); - - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.not.include('hb.demo.gender'); - }); - }); - - describe('with unvalid request parameters', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - }); - - it('should not call the endpoint with if there is no request parameters', () => { - adapter.callBids({}); - sinon.assert.callCount(adLoader.loadScript, 0); - }); - }); - }); - - describe('widespaceHandleCB', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.widespaceHandleCB).to.exist.and.to.be.a('function'); - }); - }); - - describe('respond with a successful bid', () => { - let successfulBid, - placementCode; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - sandbox.stub(adLoader, 'loadScript'); - - adapter.callBids(BID_REQUEST); - $$PREBID_GLOBAL$$._bidsRequested.push(BID_REQUEST); - $$PREBID_GLOBAL$$.widespaceHandleCB(BID_RESPONSE); - - successfulBid = bidManager.addBidResponse.firstCall.args[1]; - placementCode = bidManager.addBidResponse.firstCall.args[0]; - }); - - it('should add one bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('should use the CPM returned by the server', () => { - expect(successfulBid).to.have.property('cpm', TEST.CPM); - }); - - it('should have an OK statusCode', () => { - expect(successfulBid.getStatusCode()).to.eql(1); - }); - - it('should have a valid size', () => { - const bidSize = [successfulBid.width, successfulBid.height] - expect(bidSize).to.eql(BID_REQUEST.bids[0].sizes[0]); - }); - - it('should recive right placementCode', () => { - expect(placementCode).to.eql(TEST.PLACEMENT_CODE); - }); - }); - - describe('respond with a no-ad', () => { - let noadBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - sandbox.stub(adLoader, 'loadScript'); - - adapter.callBids(BID_REQUEST); - $$PREBID_GLOBAL$$._bidsRequested.push(BID_REQUEST); - $$PREBID_GLOBAL$$.widespaceHandleCB(BID_NOAD_RESPONSE); - - noadBid = bidManager.addBidResponse.firstCall.args[1]; - }); - - it('should have an error statusCode', () => { - expect(noadBid.getStatusCode()).to.eql(2); - }); - }); -}); diff --git a/test/spec/modules/yieldbotBidAdapter_spec.js b/test/spec/modules/yieldbotBidAdapter_spec.js deleted file mode 100644 index f7bbcbdb414..00000000000 --- a/test/spec/modules/yieldbotBidAdapter_spec.js +++ /dev/null @@ -1,518 +0,0 @@ -import {expect} from 'chai'; -import YieldbotAdapter from 'modules/yieldbotBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; -import {deepClone} from 'src/utils'; - -const bidderRequest = { - bidderCode: 'yieldbot', - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc5', - bids: [ - { - bidId: '2640ad280208cc', - sizes: [[300, 250], [300, 600]], - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc0', - params: { psn: '1234', slot: 'medrec' }, - requestId: '5f297a1f-3163-46c2-854f-b55fd2e74ec0', - placementCode: '/4294967296/adunit0' - }, - { - bidId: '35751f10be5b6b', - sizes: [[728, 90], [970, 90]], - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc1', - params: { psn: '1234', slot: 'leaderboard' }, - requestId: '5f297a1f-3163-46c2-854f-b55fd2e74ec1', - placementCode: '/4294967296/adunit1' - }, - { - bidId: '2640ad280208cd', - sizes: [[300, 250]], - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc2', - params: { psn: '1234', slot: 'medrec' }, - requestId: '5f297a1f-3163-46c2-854f-b55fd2e74ec2', - placementCode: '/4294967296/adunit2' - }, - ] -}; - -const YB_BID_FIXTURE = { - medrec: { - ybot_ad: 'y', - ybot_slot: 'medrec', - ybot_cpm: '200', - ybot_size: '300x250' - }, - leaderboard: { - ybot_ad: 'n' - }, - noop: { - ybot_ad: 'y', - ybot_slot: 'noop', - ybot_cpm: '200', - ybot_size: '300x250' - } -}; - -function createYieldbotMockLib() { - window.yieldbot = { - _initialized: false, - pub: (psn) => {}, - defineSlot: (slotName, optionalDomIdOrConfigObject, optionalTime) => {}, - enableAsync: () => {}, - go: () => {}, - nextPageview: (slots, callback) => {}, - getSlotCriteria: (slotName) => {} - }; -} - -function restoreYieldbotMockLib() { - window.yieldbot = null; -} - -function mockYieldbotBidRequest() { - window.ybotq = window.ybotq || []; - window.ybotq.forEach(fn => { - fn.apply(window.yieldbot); - }); - window.ybotq = []; -} - -const localSetupTestRegex = /localSetupTest$/; -const MAKE_BID_REQUEST = true; -let sandbox; -let bidManagerStub; -let yieldbotLibStub; - -/** - * Test initialization hook. Makes initial adapter and mock bid requests
- * unless the test is a special case with "localSetupTest".
- * 1. All suite tests are initialized with required mocks and stubs
- * 2. If the test title does not end in "localSetupTest", adapter and - * mock bid requests are executed - * 3. Test titles ending in "localSetupTest" are special case tests and are - * expected to call setupTest(object, MAKE_BID_REQUEST) where - * applicable - * @param {object} testRequest bidder request bids fixture - * @param {boolean} force trigger adapter callBids and Yieldbot library request - * @private - */ -function setupTest(testRequest, force = false) { - sandbox = sinon.sandbox.create(); - - createYieldbotMockLib(); - - sandbox.stub(adLoader, 'loadScript'); - - yieldbotLibStub = {}; - yieldbotLibStub.nextPageview = sandbox.stub(window.yieldbot, 'nextPageview'); - yieldbotLibStub.defineSlot = sandbox.stub(window.yieldbot, 'defineSlot'); - yieldbotLibStub.pub = sandbox.stub(window.yieldbot, 'pub'); - yieldbotLibStub.enableAsync = sandbox.stub(window.yieldbot, 'enableAsync'); - - yieldbotLibStub.getSlotCriteria = - sandbox.stub( - window.yieldbot, - 'getSlotCriteria', - (slotName) => { - return YB_BID_FIXTURE[slotName] || {ybot_ad: 'n'}; - }); - - yieldbotLibStub.go = - sandbox.stub( - window.yieldbot, - 'go', - () => { - window.yieldbot._initialized = true; - }); - - bidManagerStub = sandbox.stub(bidManager, 'addBidResponse'); - - const ybAdapter = new YieldbotAdapter(); - let request = testRequest || deepClone(bidderRequest); - if ((this && !this.currentTest.parent.title.match(localSetupTestRegex)) || force === MAKE_BID_REQUEST) { - ybAdapter.callBids(request); - mockYieldbotBidRequest(); - } - return { adapter: ybAdapter, localRequest: request }; -} - -function restoreTest() { - sandbox.restore(); - restoreYieldbotMockLib(); -} - -describe('Yieldbot adapter tests', function() { - let adapter; - let localRequest; - beforeEach(function () { - const testSetupCtx = setupTest.call(this); - adapter = testSetupCtx.adapter; - localRequest = testSetupCtx.localRequest; - }); - - afterEach(function() { - restoreTest(); - }); - - describe('getUniqueSlotSizes', function() { - it('should return [] for string sizes', function() { - const sizes = adapter.getUniqueSlotSizes('widthxheight'); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for Object sizes', function() { - const sizes = adapter.getUniqueSlotSizes({width: 300, height: 250}); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for boolean sizes', function() { - const sizes = adapter.getUniqueSlotSizes(true); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for undefined sizes', function() { - const sizes = adapter.getUniqueSlotSizes(undefined); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for function sizes', function() { - const sizes = adapter.getUniqueSlotSizes(function () {}); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for number sizes', function() { - const sizes = adapter.getUniqueSlotSizes(1111); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for array of numbers', function() { - const sizes = adapter.getUniqueSlotSizes([300, 250]); - expect(sizes).to.deep.equal([]); - }); - - it('should return array of unique strings', function() { - const sizes = adapter.getUniqueSlotSizes(['300x250', '300x600', '728x90', '300x250']); - expect(sizes).to.deep.equal([['300', '250'], ['300', '600'], ['728', '90']]); - }); - - it('should return array of unique strings for string elements only', function() { - const sizes = adapter.getUniqueSlotSizes(['300x250', ['threexfour']]); - expect(sizes).to.deep.equal([['300', '250']]); - }); - - it('should return array of unique strings, including non-numeric', function() { - const sizes = adapter.getUniqueSlotSizes(['300x250', 'threexfour', 'fivexsix']); - expect(sizes).to.deep.equal([['300', '250'], ['three', 'four'], ['five', 'si']]); - }); - }); - - describe('callBids', function() { - it('should request the yieldbot library', function() { - sinon.assert.calledOnce(adLoader.loadScript); - sinon.assert.calledWith(adLoader.loadScript, '//cdn.yldbt.com/js/yieldbot.intent.js'); - }); - - it('should set a yieldbot psn', function() { - sinon.assert.called(yieldbotLibStub.pub); - sinon.assert.calledWith(yieldbotLibStub.pub, '1234'); - }); - - it('should not repeat multiply defined slot sizes', function() { - sinon.assert.calledTwice(yieldbotLibStub.defineSlot); - sinon.assert.neverCalledWith(yieldbotLibStub.defineSlot, 'medrec', {sizes: [['300', '250'], ['300', '600'], ['300', '250']]}); - }); - - it('should define yieldbot slots', function() { - sinon.assert.calledTwice(yieldbotLibStub.defineSlot); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'medrec', {sizes: [['300', '250'], ['300', '600']]}); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'leaderboard', {sizes: [['728', '90'], ['970', '90']]}); - }); - - it('should not use inherited Object properties, localSetupTest', function() { - let oProto = Object.prototype; - oProto.superProp = ['300', '250']; - - expect(Object.prototype.superProp).to.be.an('array'); - localRequest.bids.forEach((bid) => { - expect(bid.superProp).to.be.an('array'); - }); - - expect(YB_BID_FIXTURE.medrec.superProp).to.deep.equal(['300', '250']); - expect(YB_BID_FIXTURE.leaderboard.superProp).to.deep.equal(['300', '250']); - - restoreTest(); - setupTest(localRequest, MAKE_BID_REQUEST); - - sinon.assert.neverCalledWith(yieldbotLibStub.defineSlot, 'superProp', {sizes: ['300', '250']}); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'medrec', {sizes: [['300', '250'], ['300', '600']]}); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'leaderboard', {sizes: [['728', '90'], ['970', '90']]}); - - delete oProto.superProp; - expect(Object.prototype.superProp).to.be.an('undefined'); - }); - - it('should enable yieldbot async mode', function() { - sinon.assert.called(yieldbotLibStub.enableAsync); - }); - - it('should add bid response after yieldbot request callback', function() { - const plc1 = bidManagerStub.firstCall.args[0]; - expect(plc1).to.equal(localRequest.bids[0].placementCode); - - const pb_bid1 = bidManagerStub.firstCall.args[1]; - expect(pb_bid1.bidderCode).to.equal('yieldbot'); - expect(pb_bid1.cpm).to.equal(2); - expect(pb_bid1.ybot_ad).to.equal('y'); - expect(pb_bid1.ybot_slot).to.equal('medrec'); - expect(pb_bid1.ybot_cpm).to.equal('200'); - expect(pb_bid1.ybot_size).to.equal('300x250'); - - expect(pb_bid1.width).to.equal('300'); - expect(pb_bid1.height).to.equal('250'); - expect(pb_bid1.ad).to.match(/src="\/\/cdn\.yldbt\.com\/js\/yieldbot\.intent\.js/); - expect(pb_bid1.ad).to.match(/yieldbot\.renderAd\('medrec:300x250'\)/); - - const plc2 = bidManagerStub.secondCall.args[0]; - expect(plc2).to.equal(localRequest.bids[1].placementCode); - - const pb_bid2 = bidManagerStub.secondCall.args[1]; - expect(pb_bid2.bidderCode).to.equal('yieldbot'); - expect(pb_bid2.width).to.equal(0); - expect(pb_bid2.height).to.equal(0); - expect(pb_bid2.statusMessage).to.match(/empty.*response/); - }); - - it('should validate slot dimensions, localSetupTest', function() { - let invalidSizeBid = { - bidId: '2640ad280208ce', - sizes: [[728, 90], [300, 250], [970, 90]], - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc3', - params: { psn: '1234', slot: 'medrec' }, - requestId: '5f297a1f-3163-46c2-854f-b55fd2e74ec3', - placementCode: '/4294967296/adunit3' - }; - - const bidResponseMedrec = { - bidderCode: 'yieldbot', - width: '300', - height: '250', - statusMessage: 'Bid available', - cpm: 2, - ybot_ad: 'y', - ybot_slot: 'medrec', - ybot_cpm: '200', - ybot_size: '300x250' - }; - - localRequest.bids = [invalidSizeBid]; - restoreTest(); - setupTest(localRequest, MAKE_BID_REQUEST); - - let bidManagerFirstCall = bidManagerStub.firstCall; - - expect(bidManagerFirstCall.args[0]).to.equal('/4294967296/adunit3'); - expect(bidManagerFirstCall.args[1]).to.include(bidResponseMedrec); - }); - - it('should make slot bid available once only', function() { - const bidResponseMedrec = { - bidderCode: 'yieldbot', - width: '300', - height: '250', - statusMessage: 'Bid available', - cpm: 2, - ybot_ad: 'y', - ybot_slot: 'medrec', - ybot_cpm: '200', - ybot_size: '300x250' - }; - - const bidResponseNone = { - bidderCode: 'yieldbot', - width: 0, - height: 0, - statusMessage: 'Bid returned empty or error response' - }; - - let firstCall = bidManagerStub.firstCall; - let secondCall = bidManagerStub.secondCall; - let thirdCall = bidManagerStub.thirdCall; - - expect(firstCall.args[0]).to.equal('/4294967296/adunit0'); - expect(firstCall.args[1]).to.include(bidResponseMedrec); - - expect(secondCall.args[0]).to.equal('/4294967296/adunit1'); - expect(secondCall.args[1]).to.include(bidResponseNone); - - expect(thirdCall.args[0]).to.equal('/4294967296/adunit2'); - expect(thirdCall.args[1]).to.include(bidResponseNone); - }); - }); - - describe('callBids, refresh', function() { - it('should use yieldbot.nextPageview after first callBids', function() { - expect(window.yieldbot._initialized).to.equal(true); - - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - sinon.assert.calledOnce(yieldbotLibStub.nextPageview); - }); - - it('should call yieldbot.nextPageview with slot config of requested bids', function() { - expect(window.yieldbot._initialized).to.equal(true); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'medrec'); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'leaderboard'); - - const refreshBids = localRequest.bids.filter((object) => { return object.placementCode === '/4294967296/adunit1'; }); - let refreshRequest = deepClone(localRequest); - refreshRequest.bids = refreshBids; - expect(refreshRequest.bids.length).to.equal(1); - - adapter.callBids(refreshRequest); - mockYieldbotBidRequest(); - - const expectedSlots = { 'leaderboard': [['728', '90'], ['970', '90']] }; - - sinon.assert.calledWithExactly(yieldbotLibStub.nextPageview, expectedSlots); - }); - - it('should not repeat multiply defined slot sizes', function() { - // placementCode: '/4294967296/adunit0' - // placementCode: '/4294967296/adunit2' - // Both placements declare medrec:300x250 - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - - sinon.assert.calledOnce(yieldbotLibStub.nextPageview); - const expectedSlots = { 'leaderboard': [['728', '90'], ['970', '90']], 'medrec': [['300', '250'], ['300', '600']]}; - sinon.assert.calledWithExactly(yieldbotLibStub.nextPageview, expectedSlots); - }); - - it('should not add empty bidResponse on callBids without bidsRequested', function() { - expect(window.yieldbot._initialized).to.equal(true); - expect(bidManagerStub.calledThrice).to.equal(true); - - adapter.callBids({}); - mockYieldbotBidRequest(); - - expect(bidManagerStub.calledThrice).to.equal(true); // the initial bids - sinon.assert.notCalled(yieldbotLibStub.nextPageview); - }); - - it('should validate slot dimensions', function() { - localRequest.bids.map(bid => { - bid.sizes = [[640, 480], [1024, 768]]; - }); - - const bidResponseNone = { - bidderCode: 'yieldbot', - width: 0, - height: 0, - statusMessage: 'Bid returned empty or error response' - }; - - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - - expect(bidManagerStub.getCalls().length).to.equal(6); - - let lastNextPageview = yieldbotLibStub.nextPageview.lastCall; - let nextPageviewSlots = lastNextPageview.args[0]; - expect(nextPageviewSlots.medrec).to.deep.equal([['640', '480'], ['1024', '768']]); - expect(nextPageviewSlots.leaderboard).to.deep.equal([['640', '480'], ['1024', '768']]); - - let fourthCall = bidManagerStub.getCall(3); - let fifthCall = bidManagerStub.getCall(4); - let sixthCall = bidManagerStub.getCall(5); - - expect(fourthCall.args[0]).to.equal('/4294967296/adunit0'); - expect(fourthCall.args[1]).to.include(bidResponseNone); - - expect(fifthCall.args[0]).to.equal('/4294967296/adunit1'); - expect(fifthCall.args[1]).to.include(bidResponseNone); - - expect(sixthCall.args[0]).to.equal('/4294967296/adunit2'); - expect(sixthCall.args[1]).to.include(bidResponseNone); - }); - - it('should not make requests for previously requested bids', function() { - const bidResponseMedrec = { - bidderCode: 'yieldbot', - width: '300', - height: '250', - statusMessage: 'Bid available', - cpm: 2, - ybot_ad: 'y', - ybot_slot: 'medrec', - ybot_cpm: '200', - ybot_size: '300x250' - }; - - const bidResponseNone = { - bidderCode: 'yieldbot', - width: 0, - height: 0, - statusMessage: 'Bid returned empty or error response' - }; - - // Refresh #1 - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - - expect(bidManagerStub.getCalls().length).to.equal(6); - - let lastNextPageview = yieldbotLibStub.nextPageview.lastCall; - let nextPageviewSlots = lastNextPageview.args[0]; - expect(nextPageviewSlots.medrec).to.deep.equal([['300', '250'], ['300', '600']]); - expect(nextPageviewSlots.leaderboard).to.deep.equal([['728', '90'], ['970', '90']]); - - let fourthCall = bidManagerStub.getCall(3); - let fifthCall = bidManagerStub.getCall(4); - let sixthCall = bidManagerStub.getCall(5); - - expect(fourthCall.args[0]).to.equal('/4294967296/adunit0'); - expect(fourthCall.args[1]).to.include(bidResponseMedrec); - - expect(fifthCall.args[0]).to.equal('/4294967296/adunit1'); - expect(fifthCall.args[1]).to.include(bidResponseNone); - - expect(sixthCall.args[0]).to.equal('/4294967296/adunit2'); - expect(sixthCall.args[1]).to.include(bidResponseNone); - - localRequest.bids.map(bid => { - bid.sizes = [[640, 480], [1024, 768]]; - }); - let bidForNinethCall = localRequest.bids[localRequest.bids.length - 1]; - bidForNinethCall.sizes = [[300, 250]]; - - // Refresh #2 - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - - expect(bidManagerStub.getCalls().length).to.equal(9); - - lastNextPageview = yieldbotLibStub.nextPageview.lastCall; - nextPageviewSlots = lastNextPageview.args[0]; - expect(nextPageviewSlots.medrec).to.deep.equal([['640', '480'], ['1024', '768'], ['300', '250']]); - expect(nextPageviewSlots.leaderboard).to.deep.equal([['640', '480'], ['1024', '768']]); - - let seventhCall = bidManagerStub.getCall(6); - let eighthCall = bidManagerStub.getCall(7); - let ninethCall = bidManagerStub.getCall(8); - - expect(seventhCall.args[0]).to.equal('/4294967296/adunit0'); - expect(seventhCall.args[1]).to.include(bidResponseNone); - - expect(eighthCall.args[0]).to.equal('/4294967296/adunit1'); - expect(eighthCall.args[1]).to.include(bidResponseNone); - - expect(ninethCall.args[0]).to.equal('/4294967296/adunit2'); - expect(ninethCall.args[1]).to.include(bidResponseMedrec); - }); - }); -}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js deleted file mode 100644 index d2a533be17e..00000000000 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ /dev/null @@ -1,209 +0,0 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/yieldmoBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; -import {parse as parseURL} from '../../../src/url'; - -describe('Yieldmo adapter', () => { - let bidsRequestedOriginal; - let adapter; - let sandbox; - - const bidderRequest = { - bidderCode: 'yieldmo', - bids: [ - { - bidId: 'bidId1', - bidder: 'yieldmo', - placementCode: 'foo', - sizes: [[728, 90]] - }, - { - bidId: 'bidId2', - bidder: 'yieldmo', - placementCode: 'bar', - sizes: [[300, 600], [300, 250]] - } - ] - }; - - beforeEach(() => { - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe('callBids', () => { - let bidRequestURL; - - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - - bidRequestURL = adLoader.loadScript.firstCall.args[0]; - }); - - it('should load a script with passed bid params', () => { - let route = 'http://ads.yieldmo.com/exchange/prebid?'; - let requestParams = parseURL(bidRequestURL).search; - let parsedPlacementParams = JSON.parse(decodeURIComponent(requestParams.p)); - - sinon.assert.calledOnce(adLoader.loadScript); - expect(bidRequestURL).to.contain(route); - - // placement 1 - expect(parsedPlacementParams[0]).to.have.property('callback_id', 'bidId1'); - expect(parsedPlacementParams[0]).to.have.property('placement_id', 'foo'); - expect(parsedPlacementParams[0].sizes[0][0]).to.equal(728); - expect(parsedPlacementParams[0].sizes[0][1]).to.equal(90); - - // placement 2 - expect(parsedPlacementParams[1]).to.have.property('callback_id', 'bidId2'); - expect(parsedPlacementParams[1]).to.have.property('placement_id', 'bar'); - expect(parsedPlacementParams[1].sizes[0][0]).to.equal(300); - expect(parsedPlacementParams[1].sizes[0][1]).to.equal(600); - expect(parsedPlacementParams[1].sizes[1][0]).to.equal(300); - expect(parsedPlacementParams[1].sizes[1][1]).to.equal(250); - - // impression information - expect(requestParams).to.have.property('callback', '$$PREBID_GLOBAL$$.YMCB'); - expect(requestParams).to.have.property('page_url'); - }); - }); - - describe('YMCB', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.YMCB).to.exist.and.to.be.a('function'); - }); - }); - - describe('add bids to the manager', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = [{ - 'cpm': 3.45455, - 'width': 300, - 'height': 250, - 'callback_id': 'bidId1', - 'ad': 'HELLO YIELDMO AD' - }, { - 'cpm': 4.35455, - 'width': 400, - 'height': 350, - 'callback_id': 'bidId2', - 'ad': 'HELLO YIELDMO AD' - }]; - - $$PREBID_GLOBAL$$.YMCB(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidManager.addBidResponse); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidManager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should have a good statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(1); - expect(secondBid.getStatusCode()).to.eql(1); - }); - - it('should add the CPM to the bid object', () => { - expect(firstBid).to.have.property('cpm', 3.45455); - expect(secondBid).to.have.property('cpm', 4.35455); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'yieldmo'); - expect(secondBid).to.have.property('bidderCode', 'yieldmo'); - }); - - it('should include the ad on the bid object', () => { - expect(firstBid).to.have.property('ad'); - expect(secondBid).to.have.property('ad'); - }); - - it('should include the size on the bid object', () => { - expect(firstBid).to.have.property('width', 300); - expect(firstBid).to.have.property('height', 250); - expect(secondBid).to.have.property('width', 400); - expect(secondBid).to.have.property('height', 350); - }); - }); - - describe('add empty bids if no bid returned', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = [{ - 'status': 'no_bid', - 'callback_id': 'bidId1' - }, { - 'status': 'no_bid', - 'callback_id': 'bidId2' - }]; - - $$PREBID_GLOBAL$$.YMCB(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidManager.addBidResponse); - }); - - it('should include the bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should have an error statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(2); - expect(secondBid.getStatusCode()).to.eql(2); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidManager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'yieldmo'); - expect(secondBid).to.have.property('bidderCode', 'yieldmo'); - }); - }); -}); diff --git a/test/spec/renderer_spec.js b/test/spec/renderer_spec.js index 282c4841ac0..4761a914bb8 100644 --- a/test/spec/renderer_spec.js +++ b/test/spec/renderer_spec.js @@ -2,19 +2,26 @@ import { expect } from 'chai'; import { Renderer } from 'src/Renderer'; describe('Renderer: A renderer installed on a bid response', () => { - const testRenderer1 = Renderer.install({ - url: 'https://httpbin.org/post', - config: { test: 'config1' }, - id: 1 - }); - const testRenderer2 = Renderer.install({ - url: 'https://httpbin.org/post', - config: { test: 'config2' }, - id: 2 - }); + let testRenderer1; + let testRenderer2; + let spyRenderFn; + let spyEventHandler; + + beforeEach(() => { + testRenderer1 = Renderer.install({ + url: 'https://httpbin.org/post', + config: { test: 'config1' }, + id: 1 + }); + testRenderer2 = Renderer.install({ + url: 'https://httpbin.org/post', + config: { test: 'config2' }, + id: 2 + }); - const spyRenderFn = sinon.spy(); - const spyEventHandler = sinon.spy(); + spyRenderFn = sinon.spy(); + spyEventHandler = sinon.spy(); + }); it('is an instance of Renderer', () => { expect(testRenderer1 instanceof Renderer).to.equal(true); @@ -34,12 +41,11 @@ describe('Renderer: A renderer installed on a bid response', () => { it('sets a render function with setRender method', () => { testRenderer1.setRender(spyRenderFn); expect(typeof testRenderer1.render).to.equal('function'); - testRenderer1.render(); expect(spyRenderFn.called).to.equal(true); }); - it('sets event handlers with setEventHandlers method', () => { + it('sets event handlers with setEventHandlers method and handles events with installed handlers', () => { testRenderer1.setEventHandlers({ testEvent: spyEventHandler }); @@ -47,16 +53,13 @@ describe('Renderer: A renderer installed on a bid response', () => { expect(testRenderer1.handlers).to.deep.equal({ testEvent: spyEventHandler }); - }); - it('handles events with installed handlers', () => { testRenderer1.handleVideoEvent({ id: 1, eventName: 'testEvent' }); expect(spyEventHandler.called).to.equal(true); }); it('pushes commands to queue if renderer is not loaded', () => { testRenderer1.push(spyRenderFn); - expect(testRenderer1.cmd.length).to.equal(1); // clear queue for next tests @@ -70,6 +73,7 @@ describe('Renderer: A renderer installed on a bid response', () => { testRenderer1.push(func); expect(testRenderer1.cmd.length).to.equal(0); + sinon.assert.calledOnce(func); }); diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index 471d3ba2752..24a6063cf7d 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -1,123 +1,195 @@ import { expect } from 'chai'; -import * as sizeMapping from 'src/sizeMapping'; - -var validAdUnit = { - 'sizes': [300, 250], - 'sizeMapping': [ - { - 'minWidth': 1024, - 'sizes': [[300, 250], [728, 90]] - }, - { - 'minWidth': 480, - 'sizes': [120, 60] - }, - { - 'minWidth': 0, - 'sizes': [20, 20] - } - ] -}; - -var invalidAdUnit = { - 'sizes': [300, 250], - 'sizeMapping': {} // wrong type -}; - -var invalidAdUnit2 = { - 'sizes': [300, 250], - 'sizeMapping': [{ - foo: 'bar' // bad - }] -}; - -let mockWindow = {}; - -function resetMockWindow() { - mockWindow = { - document: { - body: { - clientWidth: 1024 - }, - documentElement: { - clientWidth: 1024 +import { resolveStatus, setSizeConfig } from 'src/sizeMapping'; +import includes from 'core-js/library/fn/array/includes'; + +describe('sizeMapping', () => { + var testSizes = [[970, 90], [728, 90], [300, 250], [300, 100], [80, 80]]; + + var sizeConfig = [{ + 'mediaQuery': '(min-width: 1200px)', + 'sizesSupported': [ + [970, 90], + [728, 90], + [300, 250] + ] + }, { + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250], + [300, 100] + ] + }, { + 'mediaQuery': '(min-width: 0px) and (max-width: 767px)', + 'sizesSupported': [] + }]; + + var sizeConfigWithLabels = [{ + 'mediaQuery': '(min-width: 1200px)', + 'labels': ['desktop'] + }, { + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250] + ], + 'labels': ['tablet', 'phone'] + }, { + 'mediaQuery': '(min-width: 0px) and (max-width: 767px)', + 'sizesSupported': [ + [300, 250], + [300, 100] + ], + 'labels': ['phone'] + }]; + + let sandbox, + matchMediaOverride; + + beforeEach(() => { + setSizeConfig(sizeConfig); + + sandbox = sinon.sandbox.create(); + + matchMediaOverride = {matches: false}; + + sandbox.stub(window, 'matchMedia', (...args) => { + if (typeof matchMediaOverride === 'function') { + return matchMediaOverride.apply(window, args); } - }, - innerWidth: 1024 - }; -} - -describe('sizeMapping', function() { - beforeEach(resetMockWindow); - - it('minWidth should be inclusive', function() { - mockWindow.innerWidth = 1024; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(validAdUnit); - expect(sizes).to.deep.equal([[300, 250], [728, 90]]); + return matchMediaOverride; + }); }); - it('mapSizes 1029 width', function() { - mockWindow.innerWidth = 1029; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(validAdUnit); - expect(sizes).to.deep.equal([[300, 250], [728, 90]]); - expect(validAdUnit.sizes).to.deep.equal([300, 250]); - }); + afterEach(() => { + setSizeConfig([]); - it('mapSizes 400 width', function() { - mockWindow.innerWidth = 400; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(validAdUnit); - expect(sizes).to.deep.equal([20, 20]); - expect(validAdUnit.sizes).to.deep.equal([300, 250]); + sandbox.restore(); }); - it('mapSizes - invalid adUnit - should return sizes', function() { - mockWindow.innerWidth = 1029; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(invalidAdUnit); - expect(sizes).to.deep.equal([300, 250]); - expect(invalidAdUnit.sizes).to.deep.equal([300, 250]); - - mockWindow.innerWidth = 400; - sizeMapping.setWindow(mockWindow); - sizes = sizeMapping.mapSizes(invalidAdUnit); - expect(sizes).to.deep.equal([300, 250]); - expect(invalidAdUnit.sizes).to.deep.equal([300, 250]); - }); + describe('when handling sizes', () => { + it('when one mediaQuery block matches, it should filter the adUnit.sizes passed in', () => { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - it('mapSizes - should return desktop (largest) sizes if screen width not detected', function() { - mockWindow.innerWidth = 0; - mockWindow.document.body.clientWidth = 0; - mockWindow.document.documentElement.clientWidth = 0; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(validAdUnit); - expect(sizes).to.deep.equal([[300, 250], [728, 90]]); - expect(validAdUnit.sizes).to.deep.equal([300, 250]); - }); + let status = resolveStatus(undefined, testSizes, sizeConfig); - it('mapSizes - should return sizes if sizemapping improperly defined ', function() { - mockWindow.innerWidth = 0; - mockWindow.document.body.clientWidth = 0; - mockWindow.document.documentElement.clientWidth = 0; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(invalidAdUnit2); - expect(sizes).to.deep.equal([300, 250]); - expect(validAdUnit.sizes).to.deep.equal([300, 250]); - }); + expect(status).to.deep.equal({ + active: true, + sizes: [[970, 90], [728, 90], [300, 250]] + }) + }); + + it('when multiple mediaQuery block matches, it should filter a union of the matched sizesSupported', () => { + matchMediaOverride = (str) => includes([ + '(min-width: 1200px)', + '(min-width: 768px) and (max-width: 1199px)' + ], str) ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, testSizes, sizeConfig); + expect(status).to.deep.equal({ + active: true, + sizes: [[970, 90], [728, 90], [300, 250], [300, 100]] + }) + }); + + it('if no mediaQueries match, it should allow all sizes specified', () => { + matchMediaOverride = () => ({matches: false}); + + let status = resolveStatus(undefined, testSizes, sizeConfig); + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }) + }); - it('getScreenWidth', function() { - mockWindow.innerWidth = 900; - mockWindow.document.body.clientWidth = 900; - mockWindow.document.documentElement.clientWidth = 900; - expect(sizeMapping.getScreenWidth(mockWindow)).to.equal(900); + it('if a mediaQuery matches and has sizesSupported: [], it should filter all sizes', () => { + matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, testSizes, sizeConfig); + expect(status).to.deep.equal({ + active: false, + sizes: [] + }) + }); + + it('if a mediaQuery matches and no sizesSupported specified, it should not effect adUnit.sizes', () => { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, testSizes, sizeConfigWithLabels); + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }) + }); }); - it('getScreenWidth - should return 0 if it cannot deteremine size', function() { - mockWindow.innerWidth = null; - mockWindow.document.body.clientWidth = null; - mockWindow.document.documentElement.clientWidth = null; - expect(sizeMapping.getScreenWidth(mockWindow)).to.equal(0); + describe('when handling labels', () => { + it('should activate/deactivate adUnits/bidders based on sizeConfig.labels', () => { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus({ + labels: ['desktop'] + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }); + + status = resolveStatus({ + labels: ['tablet'] + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: false, + sizes: testSizes + }); + }); + + it('should active/deactivate adUnits/bidders based on requestBids labels', () => { + let activeLabels = ['us-visitor', 'desktop', 'smart']; + + let status = resolveStatus({ + labels: ['uk-visitor'], + activeLabels + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: false, + sizes: testSizes + }); + + status = resolveStatus({ + labels: ['us-visitor'], + activeLabels + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }); + + status = resolveStatus({ + labels: ['us-visitor', 'tablet'], + labelAll: true, + activeLabels + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: false, + sizes: testSizes + }); + + status = resolveStatus({ + labels: ['us-visitor', 'desktop'], + labelAll: true, + activeLabels + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }); + }); }); }); diff --git a/test/spec/unit/bidmanager_spec.js b/test/spec/unit/bidmanager_spec.js deleted file mode 100644 index 290bf06733e..00000000000 --- a/test/spec/unit/bidmanager_spec.js +++ /dev/null @@ -1,259 +0,0 @@ -import { expect } from 'chai'; -import { config } from 'src/config'; -import constants from 'src/constants'; -import events from 'src/events'; - -import * as bidManager from 'src/bidmanager'; -import useVideoCacheStubs from 'test/mocks/videoCacheStub'; -import adUnit from 'test/fixtures/video/adUnit'; -import bidRequest from 'test/fixtures/video/bidRequest'; -import urlBidResponse from 'test/fixtures/video/vastUrlResponse'; -import payloadBidResponse from 'test/fixtures/video/vastPayloadResponse'; - -function adjustCpm(cpm) { - return cpm + 1; -} - -describe('The Bid Manager', () => { - before(() => { - $$PREBID_GLOBAL$$.cbTimeout = 5000; - $$PREBID_GLOBAL$$.timeoutBuffer = 50; - }); - - describe('addBidResponse() function,', () => { - /** - * Add the bidResponse fixture as a bid into the auction, and run some assertions - * to verify: - * - * 1. Whether or not that bid got added. - * 2. Whether or not the "end of auction" callbacks got called. - */ - function testAddVideoBid(expectBidAdded, expectCallbackCalled, videoCacheStubProvider, usePayloadResponse) { - return function() { - const usePrebidCache = config.getConfig('usePrebidCache'); - const bidToUse = usePayloadResponse ? payloadBidResponse : urlBidResponse; - const mockResponse = Object.assign({}, bidToUse); - const callback = sinon.spy(); - bidManager.addOneTimeCallback(callback); - - mockResponse.getSize = function() { - return `${this.height}x${this.width}`; - }; - bidManager.addBidResponse(adUnit.code, mockResponse); - - const expectedBidsReceived = expectBidAdded ? 1 : 0; - expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(expectedBidsReceived); - - const storeStub = videoCacheStubProvider().store; - if (usePrebidCache) { - expect(storeStub.calledOnce).to.equal(true); - expect(storeStub.getCall(0).args[0][0]).to.equal(mockResponse); - } else { - expect(storeStub.called).to.equal(false); - } - - if (expectedBidsReceived === 1) { - const bid = $$PREBID_GLOBAL$$._bidsReceived[0]; - - // Ensures that the BidAdjustment listeners execute before the bid goes into the auction. - expect(bid.cpm).to.equal(adjustCpm(0.1)); - - if (usePayloadResponse) { - expect(bid.vastXml).to.equal(''); - if (usePrebidCache) { - expect(bid.vastUrl).to.equal(`https://prebid.adnxs.com/pbc/v1/cache?uuid=FAKE_UUID`); - } - } else { - expect(bid.vastUrl).to.equal('www.myVastUrl.com'); - } - if (usePrebidCache) { - expect(bid.videoCacheKey).to.equal('FAKE_UUID'); - } - } - if (expectCallbackCalled) { - expect(callback.calledOnce).to.equal(true); - } else { - expect(callback.called).to.equal(false); - } - }; - } - - /** - * Initialize the global state so that the auction-space looks like we want it to. - * - * @param {Array} adUnits The array of ad units which should appear in this auction. - * @param {function} bidRequestTweaker A function which accepts a basic bidRequest, and - * transforms it to prepare it for auction. - */ - function prepAuction(adUnits, bidRequestTweaker) { - function bidAdjuster(bid) { - if (bid.hasOwnProperty('cpm')) { - bid.hadCpmDuringBidAdjustment = true; - } - if (bid.hasOwnProperty('adUnitCode')) { - bid.hadAdUnitCodeDuringBidAdjustment = true; - } - if (bid.hasOwnProperty('timeToRespond')) { - bid.hadTimeToRespondDuringBidAdjustment = true; - } - if (bid.hasOwnProperty('requestTimestamp')) { - bid.hadRequestTimestampDuringBidAdjustment = true; - } - if (bid.hasOwnProperty('responseTimestamp')) { - bid.hadResponseTimestampDuringBidAdjustment = true; - } - bid.cpm = adjustCpm(bid.cpm); - } - beforeEach(() => { - let thisBidRequest = bidRequest; - if (bidRequestTweaker) { - thisBidRequest = JSON.parse(JSON.stringify(bidRequest)); - bidRequestTweaker(thisBidRequest); - } - - events.on(constants.EVENTS.BID_ADJUSTMENT, bidAdjuster); - - $$PREBID_GLOBAL$$.adUnits = adUnits; - $$PREBID_GLOBAL$$._bidsRequested = [thisBidRequest]; - $$PREBID_GLOBAL$$._bidsReceived = []; - $$PREBID_GLOBAL$$._adUnitCodes = $$PREBID_GLOBAL$$.adUnits.map(unit => unit.code); - }); - - afterEach(() => { - events.off(constants.EVENTS.BID_ADJUSTMENT, bidAdjuster); - }); - } - - function auctionStart(timedOut) { - return timedOut - ? new Date().getTime() - $$PREBID_GLOBAL$$.cbTimeout - $$PREBID_GLOBAL$$.timeoutBuffer - 1 - : new Date().getTime(); - } - - function testAddExpectMoreBids(stubProvider) { - return () => { - // Set up the global state so that we expect two bids, and the auction started just now - // (so as to reduce the chance of timeout. This assumes that the unit test runs run in < 5000 ms). - prepAuction( - [adUnit, Object.assign({}, adUnit, { code: 'video2' })], - (bidRequest) => { - const tweakedBidRequestBid = Object.assign({}, bidRequest.bids[0], { placementCode: 'video2' }); - bidRequest.bids.push(tweakedBidRequestBid); - bidRequest.start = auctionStart(false); - }); - - it("should add video bids, but shouldn't call the end-of-auction callbacks yet", - testAddVideoBid(true, false, stubProvider, false)); - }; - } - - describe('when prebid-cache is enabled', () => { - before(() => { - config.setConfig({ - usePrebidCache: true, - }); - }); - - describe('when the cache is functioning properly', () => { - let stubProvider = useVideoCacheStubs({ - store: [{ uuid: 'FAKE_UUID' }], - }); - - describe('when more bids are expected after this one', testAddExpectMoreBids(stubProvider)); - - describe('when this is the last bid expected in the auction', () => { - // Set up the global state so that we expect only one bid, and the auction started just now - // (so as to reduce the chance of timeout. This assumes that the unit test runs run in < 5000 ms). - prepAuction([adUnit], (bidRequest) => bidRequest.start = auctionStart(false)); - - it("shouldn't add invalid bids", () => { - bidManager.addBidResponse('', { }); - bidManager.addBidResponse('testCode', { mediaType: 'video' }); - bidManager.addBidResponse('testCode', { mediaType: 'native' }); - expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(0); - }); - - it('should add bids with a vastUrl and then execute the callbacks signaling the end of the auction', - testAddVideoBid(true, true, stubProvider, false)); - - it('should add bids with a vastXml and then execute the callbacks signaling the end of the auction', - testAddVideoBid(true, true, stubProvider, true)); - - it('should gracefully do nothing when adUnitCode is undefined', () => { - bidManager.addBidResponse(undefined, {}); - expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(0); - }); - - it('should gracefully do nothing when bid is undefined', () => { - bidManager.addBidResponse('mock/code'); - expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(0); - }); - - it('should attach properties for analytics *before* the BID_ADJUSTMENT event listeners are called', () => { - const copy = Object.assign({}, urlBidResponse); - copy.getSize = function() { - return `${this.height}x${this.width}`; - }; - delete copy.cpm; - bidManager.addBidResponse(adUnit.code, copy); - expect(copy).to.have.property('hadCpmDuringBidAdjustment', true); - expect(copy).to.have.property('hadAdUnitCodeDuringBidAdjustment', true); - expect(copy).to.have.property('hadTimeToRespondDuringBidAdjustment', true); - expect(copy).to.have.property('hadRequestTimestampDuringBidAdjustment', true); - expect(copy).to.have.property('hadResponseTimestampDuringBidAdjustment', true); - }); - }); - - describe('when the auction has timed out', () => { - // Set up the global state to expect two bids, and mock an auction which happened long enough - // in the past that it will *seem* like this bid is arriving after the timeouts. - prepAuction( - [adUnit, Object.assign({}, adUnit, { code: 'video2' })], - (bidRequest) => { - const tweakedBidRequestBid = Object.assign({}, bidRequest.bids[0], { placementCode: 'video2' }); - bidRequest.bids.push(tweakedBidRequestBid); - bidRequest.start = auctionStart(true); - }); - - // Because of the preconditions, this makes sure that the end-of-auction callbacks get called when - // the auction hits the timeout. - it('should add the bid, but also execute the callbacks signaling the end of the auction', - testAddVideoBid(true, true, stubProvider, false)); - }); - }); - - describe('when the cache is failing for some reason,', () => { - let stubProvider = useVideoCacheStubs({ - store: new Error('Unable to save to the cache'), - }); - - describe('when the auction still has time left', () => { - prepAuction([adUnit], (bidRequest) => bidRequest.start = auctionStart(false)); - - it("shouldn't add the bid to the auction, and shouldn't execute the end-of-auction callbacks", - testAddVideoBid(false, false, stubProvider, false)); - }); - - describe('when the auction has timed out', () => { - prepAuction([adUnit], (bidRequest) => bidRequest.start = auctionStart(true)); - it("shouldn't add the bid to the auction, but should execute the end-of-auction callbacks", - testAddVideoBid(false, true, stubProvider, false)); - }) - }); - }); - - describe('when prebid-cache is disabled', () => { - let stubProvider = useVideoCacheStubs({ - store: [{ uuid: 'FAKE_UUID' }], - }); - - before(() => { - config.setConfig({ - usePrebidCache: false, - }); - }); - - describe('when more bids are expected after this one', testAddExpectMoreBids(stubProvider)); - }); - }); -}); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 30452d9725a..21ab14ea99e 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -3,7 +3,11 @@ import AdapterManager from 'src/adaptermanager'; import { getAdUnits } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; +import { config } from 'src/config'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { setSizeConfig } from 'src/sizeMapping'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; var s2sTesting = require('../../../../modules/s2sTesting'); var events = require('../../../../src/events'); @@ -17,21 +21,15 @@ const CONFIG = { }; var prebidServerAdapterMock = { bidder: 'prebidServer', - callBids: sinon.stub(), - setConfig: sinon.stub(), - queueSync: sinon.stub() + callBids: sinon.stub() }; var adequantAdapterMock = { bidder: 'adequant', - callBids: sinon.stub(), - setConfig: sinon.stub(), - queueSync: sinon.stub() + callBids: sinon.stub() }; var appnexusAdapterMock = { bidder: 'appnexus', - callBids: sinon.stub(), - setConfig: sinon.stub(), - queueSync: sinon.stub() + callBids: sinon.stub() }; describe('adapterManager tests', () => { @@ -45,6 +43,44 @@ describe('adapterManager tests', () => { }); it('should log an error if a bidder is used that does not exist', () => { + let bidRequests = [{ + 'bidderCode': 'appnexus', + 'requestId': '1863e370099523', + 'bidderRequestId': '2946b569352ef2', + 'tid': '34566b569352ef2', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418', + 'test': 'me' + }, + 'adUnitCode': '/19968336/header-bid-tag1', + 'sizes': [[728, 90], [970, 70]], + 'bidId': '392b5a6b05d648', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897462, + 'status': 1, + 'transactionId': 'fsafsa' + }, + { + 'bidder': 'fakeBidder', + 'params': { + 'placementId': '4799418' + }, + 'adUnitCode': '/19968336/header-bid-tag-0', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dccdc37746135', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897463, + 'status': 1, + 'transactionId': 'fsafsa' + } + ], + 'start': 1462918897460 + }]; const adUnits = [{ code: 'adUnit-code', bids: [ @@ -53,7 +89,7 @@ describe('adapterManager tests', () => { ] }]; - AdapterManager.callBids({adUnits}); + AdapterManager.callBids(adUnits, bidRequests); sinon.assert.called(utils.logError); }); @@ -64,7 +100,9 @@ describe('adapterManager tests', () => { let count = () => cnt++; events.on(CONSTANTS.EVENTS.BID_REQUESTED, count); AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; - AdapterManager.callBids({adUnits: getAdUnits()}); + let adUnits = getAdUnits(); + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(1); sinon.assert.calledOnce(appnexusAdapterMock.callBids); appnexusAdapterMock.callBids.reset(); @@ -75,17 +113,81 @@ describe('adapterManager tests', () => { describe('S2S tests', () => { beforeEach(() => { - AdapterManager.setS2SConfig(CONFIG); + config.setConfig({s2sConfig: CONFIG}); AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; prebidServerAdapterMock.callBids.reset(); }); it('invokes callBids on the S2S adapter', () => { - AdapterManager.callBids({adUnits: getAdUnits()}); + let bidRequests = [{ + 'bidderCode': 'appnexus', + 'requestId': '1863e370099523', + 'bidderRequestId': '2946b569352ef2', + 'tid': '34566b569352ef2', + 'src': 's2s', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418', + 'test': 'me' + }, + 'adUnitCode': '/19968336/header-bid-tag1', + 'sizes': [ + [ + 728, + 90 + ], + [ + 970, + 90 + ] + ], + 'bidId': '392b5a6b05d648', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897462, + 'status': 1, + 'transactionId': 'fsafsa' + }, + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418' + }, + 'adUnitCode': '/19968336/header-bid-tag-0', + 'sizes': [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ], + 'bidId': '4dccdc37746135', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897463, + 'status': 1, + 'transactionId': 'fsafsa' + } + ], + 'start': 1462918897460 + }]; + + AdapterManager.callBids( + getAdUnits(), + bidRequests, + () => {}, + () => () => {} + ); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); }); + // Enable this test when prebidServer adapter is made 1.0 compliant it('invokes callBids with only s2s bids', () => { const adUnits = getAdUnits(); // adUnit without appnexus bidder @@ -102,7 +204,70 @@ describe('adapterManager tests', () => { } ] }); - AdapterManager.callBids({adUnits: adUnits}); + + let bidRequests = [{ + 'bidderCode': 'appnexus', + 'requestId': '1863e370099523', + 'bidderRequestId': '2946b569352ef2', + 'tid': '34566b569352ef2', + 'src': 's2s', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418', + 'test': 'me' + }, + 'adUnitCode': '/19968336/header-bid-tag1', + 'sizes': [ + [ + 728, + 90 + ], + [ + 970, + 90 + ] + ], + 'bidId': '392b5a6b05d648', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897462, + 'status': 1, + 'transactionId': 'fsafsa' + }, + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418' + }, + 'adUnitCode': '/19968336/header-bid-tag-0', + 'sizes': [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ], + 'bidId': '4dccdc37746135', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897463, + 'status': 1, + 'transactionId': 'fsafsa' + } + ], + 'start': 1462918897460 + }]; + AdapterManager.callBids( + adUnits, + bidRequests, + () => {}, + () => () => {} + ); const requestObj = prebidServerAdapterMock.callBids.firstCall.args[0]; expect(requestObj.ad_units.length).to.equal(2); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); @@ -122,14 +287,18 @@ describe('adapterManager tests', () => { }); it('should fire for s2s requests', () => { - AdapterManager.callBids({adUnits: getAdUnits()}); + let adUnits = getAdUnits(); + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(1); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); }); it('should fire for simultaneous s2s and client requests', () => { AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; - AdapterManager.callBids({adUnits: getAdUnits()}); + let adUnits = getAdUnits(); + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(2); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); sinon.assert.calledOnce(adequantAdapterMock.callBids); @@ -139,38 +308,20 @@ describe('adapterManager tests', () => { }); }); // end s2s tests - describe('The setBidderSequence() function', () => { - let spy; - - beforeEach(() => { - spy = sinon.spy(utils, 'logWarn') - }); - - afterEach(() => { - utils.logWarn.restore(); - }); - - it('should log a warning on invalid values', () => { - AdapterManager.setBidderSequence('unrecognized sequence'); - expect(spy.calledOnce).to.equal(true); - }); - - it('should not log warnings when given recognized values', () => { - AdapterManager.setBidderSequence('fixed'); - AdapterManager.setBidderSequence('random'); - expect(spy.called).to.equal(false); - }); - }) - describe('s2sTesting', () => { function getTestAdUnits() { // copy adUnits return JSON.parse(JSON.stringify(getAdUnits())); } + function callBids(adUnits = getTestAdUnits()) { + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); + } + function checkServerCalled(numAdUnits, numBids) { sinon.assert.calledOnce(prebidServerAdapterMock.callBids); - var requestObj = prebidServerAdapterMock.callBids.firstCall.args[0]; + let requestObj = prebidServerAdapterMock.callBids.firstCall.args[0]; expect(requestObj.ad_units.length).to.equal(numAdUnits); for (let i = 0; i < numAdUnits; i++) { expect(requestObj.ad_units[i].bids.filter((bid) => { @@ -184,16 +335,15 @@ describe('adapterManager tests', () => { expect(adapter.callBids.firstCall.args[0].bids.length).to.equal(numBids); } - var TESTING_CONFIG; - var stubGetSourceBidderMap; + let TESTING_CONFIG = utils.deepClone(CONFIG); + Object.assign(TESTING_CONFIG, { + bidders: ['appnexus', 'adequant'], + testing: true + }); + let stubGetSourceBidderMap; beforeEach(() => { - TESTING_CONFIG = Object.assign(CONFIG, { - bidders: ['appnexus', 'adequant'], - testing: true - }); - - AdapterManager.setS2SConfig(CONFIG); + config.setConfig({s2sConfig: TESTING_CONFIG}); AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; @@ -206,13 +356,13 @@ describe('adapterManager tests', () => { }); afterEach(() => { + config.setConfig({s2sConfig: {}}); s2sTesting.getSourceBidderMap.restore(); }); it('calls server adapter if no sources defined', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: [], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); - AdapterManager.callBids({adUnits: getTestAdUnits()}); + callBids(); // server adapter checkServerCalled(2, 2); @@ -226,8 +376,7 @@ describe('adapterManager tests', () => { it('calls client adapter if one client source defined', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); - AdapterManager.callBids({adUnits: getTestAdUnits()}); + callBids(); // server adapter checkServerCalled(2, 2); @@ -241,8 +390,21 @@ describe('adapterManager tests', () => { it('calls client adapters if client sources defined', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); - AdapterManager.callBids({adUnits: getTestAdUnits()}); + callBids(); + + // server adapter + checkServerCalled(2, 2); + + // appnexus + checkClientCalled(appnexusAdapterMock, 2); + + // adequant + checkClientCalled(adequantAdapterMock, 2); + }); + + it('calls client adapters if client sources defined', () => { + stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); + callBids(); // server adapter checkServerCalled(2, 2); @@ -256,13 +418,12 @@ describe('adapterManager tests', () => { it('does not call server adapter for bidders that go to client', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.CLIENT; adUnits[0].bids[1].finalSource = s2sTesting.CLIENT; adUnits[1].bids[0].finalSource = s2sTesting.CLIENT; adUnits[1].bids[1].finalSource = s2sTesting.CLIENT; - AdapterManager.callBids({adUnits}); + callBids(adUnits); // server adapter sinon.assert.notCalled(prebidServerAdapterMock.callBids); @@ -276,13 +437,12 @@ describe('adapterManager tests', () => { it('does not call client adapters for bidders that go to server', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.SERVER; adUnits[0].bids[1].finalSource = s2sTesting.SERVER; adUnits[1].bids[0].finalSource = s2sTesting.SERVER; adUnits[1].bids[1].finalSource = s2sTesting.SERVER; - AdapterManager.callBids({adUnits}); + callBids(adUnits); // server adapter checkServerCalled(2, 2); @@ -296,13 +456,12 @@ describe('adapterManager tests', () => { it('calls client and server adapters for bidders that go to both', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.BOTH; adUnits[0].bids[1].finalSource = s2sTesting.BOTH; adUnits[1].bids[0].finalSource = s2sTesting.BOTH; adUnits[1].bids[1].finalSource = s2sTesting.BOTH; - AdapterManager.callBids({adUnits}); + callBids(adUnits); // server adapter checkServerCalled(2, 2); @@ -316,13 +475,12 @@ describe('adapterManager tests', () => { it('makes mixed client/server adapter calls for mixed bidder sources', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.CLIENT; adUnits[0].bids[1].finalSource = s2sTesting.CLIENT; adUnits[1].bids[0].finalSource = s2sTesting.SERVER; adUnits[1].bids[1].finalSource = s2sTesting.SERVER; - AdapterManager.callBids({adUnits}); + callBids(adUnits); // server adapter checkServerCalled(1, 2); @@ -387,5 +545,119 @@ describe('adapterManager tests', () => { expect(AdapterManager.videoAdapters).to.include(alias); }); }); + + describe('makeBidRequests', () => { + let adUnits; + beforeEach(() => { + adUnits = utils.deepClone(getAdUnits()).map(adUnit => { + adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus', 'rubicon'], bid.bidder)); + return adUnit; + }) + }); + + describe('sizeMapping', () => { + beforeEach(() => { + sinon.stub(window, 'matchMedia', () => ({matches: true})); + }); + + afterEach(() => { + matchMedia.restore(); + setSizeConfig([]); + }); + + it('should not filter bids w/ no labels', () => { + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + expect(bidRequests.length).to.equal(2); + let rubiconBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'rubicon'); + expect(rubiconBidRequests.bids.length).to.equal(1); + expect(rubiconBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === rubiconBidRequests.bids[0].adUnitCode).sizes); + + let appnexusBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'appnexus'); + expect(appnexusBidRequests.bids.length).to.equal(2); + expect(appnexusBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[0].adUnitCode).sizes); + expect(appnexusBidRequests.bids[1].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).sizes); + }); + + it('should filter sizes using size config', () => { + let validSizes = [ + [728, 90], + [300, 250] + ]; + + let validSizeMap = validSizes.map(size => size.toString()).reduce((map, size) => { + map[size] = true; + return map; + }, {}); + + setSizeConfig([{ + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': validSizes, + 'labels': ['tablet', 'phone'] + }]); + + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + // only valid sizes as specified in size config should show up in bidRequests + bidRequests.forEach(bidRequest => { + bidRequest.bids.forEach(bid => { + bid.sizes.forEach(size => { + expect(validSizeMap[size]).to.equal(true); + }); + }); + }); + + setSizeConfig([{ + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [], + 'labels': ['tablet', 'phone'] + }]); + + bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + // if no valid sizes, all bidders should be filtered out + expect(bidRequests.length).to.equal(0); + }); + + it('should filter adUnits/bidders based on applied labels', () => { + adUnits[0].labelAll = ['visitor-uk', 'mobile']; + adUnits[1].labelAny = ['visitor-uk', 'desktop']; + adUnits[1].bids[0].labelAny = ['mobile']; + adUnits[1].bids[1].labelAll = ['desktop']; + + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + ['visitor-uk', 'desktop'] + ); + + // 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); + expect(bidRequests[0].bids[0].adUnitCode).to.equal(adUnits[1].code); + }); + }) + }); }); }); diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index e621f1fb329..7358017474d 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1,5 +1,4 @@ import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; -import bidmanager from 'src/bidmanager'; import adaptermanager from 'src/adaptermanager'; import * as ajax from 'src/ajax'; import { expect } from 'chai'; @@ -11,15 +10,17 @@ const CODE = 'sampleBidder'; const MOCK_BIDS_REQUEST = { bids: [ { + bidId: 1, requestId: 'first-bid-id', - placementCode: 'mock/placement', + adUnitCode: 'mock/placement', params: { param: 5 } }, { + bidId: 2, requestId: 'second-bid-id', - placementCode: 'mock/placement2', + adUnitCode: 'mock/placement2', params: { badParam: 6 } @@ -29,8 +30,9 @@ const MOCK_BIDS_REQUEST = { describe('bidders created by newBidder', () => { let spec; - let addBidRequestStub; let bidder; + let addBidResponseStub; + let doneStub; beforeEach(() => { spec = { @@ -40,11 +42,9 @@ describe('bidders created by newBidder', () => { interpretResponse: sinon.stub(), getUserSyncs: sinon.stub() }; - addBidRequestStub = sinon.stub(bidmanager, 'addBidResponse'); - }); - afterEach(() => { - addBidRequestStub.restore(); + addBidResponseStub = sinon.stub(); + doneStub = sinon.stub(); }); describe('when the ajax response is irrelevant', () => { @@ -52,6 +52,8 @@ describe('bidders created by newBidder', () => { beforeEach(() => { ajaxStub = sinon.stub(ajax, 'ajax'); + addBidResponseStub.reset(); + doneStub.reset(); }); afterEach(() => { @@ -78,7 +80,7 @@ describe('bidders created by newBidder', () => { spec.isBidRequestValid.returns(true); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -92,7 +94,7 @@ describe('bidders created by newBidder', () => { spec.isBidRequestValid.returns(false); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -106,7 +108,7 @@ describe('bidders created by newBidder', () => { spec.isBidRequestValid.onSecondCall().returns(false); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -120,7 +122,7 @@ describe('bidders created by newBidder', () => { spec.isBidRequestValid.returns(true); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); }); @@ -136,7 +138,7 @@ describe('bidders created by newBidder', () => { data: data }); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(url); @@ -161,7 +163,7 @@ describe('bidders created by newBidder', () => { options: options }); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(url); @@ -184,7 +186,7 @@ describe('bidders created by newBidder', () => { data: data }); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2&`); @@ -208,7 +210,7 @@ describe('bidders created by newBidder', () => { options: opt }); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2&`); @@ -237,12 +239,12 @@ describe('bidders created by newBidder', () => { } ]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledTwice).to.equal(true); }); - it('should add bids for each placement code if no requests are given', () => { + it('should not add bids for each placement code if no requests are given', () => { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -250,13 +252,9 @@ describe('bidders created by newBidder', () => { spec.interpretResponse.returns([]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); - expect(bidmanager.addBidResponse.calledTwice).to.equal(true); - const placementsWithBids = - [bidmanager.addBidResponse.firstCall.args[0], bidmanager.addBidResponse.secondCall.args[0]]; - expect(placementsWithBids).to.contain('mock/placement'); - expect(placementsWithBids).to.contain('mock/placement2'); + expect(addBidResponseStub.callCount).to.equal(0); }); }); @@ -271,6 +269,8 @@ describe('bidders created by newBidder', () => { fakeResponse.returns('headerContent'); callbacks.success('response body', { getResponseHeader: fakeResponse }); }); + addBidResponseStub.reset(); + doneStub.reset(); userSyncStub = sinon.stub(userSync, 'registerSync') logErrorSpy = sinon.spy(utils, 'logError'); }); @@ -292,7 +292,7 @@ describe('bidders created by newBidder', () => { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.interpretResponse.calledOnce).to.equal(true); const response = spec.interpretResponse.firstCall.args[0] @@ -303,6 +303,7 @@ describe('bidders created by newBidder', () => { url: 'test.url.com', data: {} }); + expect(doneStub.calledOnce).to.equal(true); }); it('should call spec.interpretResponse() once for each request made', () => { @@ -323,23 +324,23 @@ describe('bidders created by newBidder', () => { ]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.interpretResponse.calledTwice).to.equal(true); + expect(doneStub.calledOnce).to.equal(true); }); - it('should add bids for each placement code into the bidmanager, even if the bidder doesn\'t bid on all of them', () => { + it('should only add bids for valid adUnit code into the auction, even if the bidder doesn\'t bid on all of them', () => { const bidder = newBidder(spec); const bid = { creativeId: 'creative-id', - bidderCode: 'code', - requestId: 'some-id', + requestId: '1', ad: 'ad-url.com', cpm: 0.5, height: 200, width: 300, - placementCode: 'mock/placement', + adUnitCode: 'mock/placement', currency: 'USD', netRevenue: true, ttl: 300 @@ -354,13 +355,11 @@ describe('bidders created by newBidder', () => { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); - expect(bidmanager.addBidResponse.calledTwice).to.equal(true); - const placementsWithBids = - [bidmanager.addBidResponse.firstCall.args[0], bidmanager.addBidResponse.secondCall.args[0]]; - expect(placementsWithBids).to.contain('mock/placement'); - expect(placementsWithBids).to.contain('mock/placement2'); + expect(addBidResponseStub.calledOnce).to.equal(true); + expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + expect(doneStub.calledOnce).to.equal(true); expect(logErrorSpy.callCount).to.equal(0); }); @@ -375,7 +374,7 @@ describe('bidders created by newBidder', () => { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1].length).to.equal(1); @@ -394,7 +393,7 @@ describe('bidders created by newBidder', () => { url: 'usersync.com' }]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(userSyncStub.called).to.equal(true); expect(userSyncStub.firstCall.args[0]).to.equal('iframe'); @@ -406,7 +405,7 @@ describe('bidders created by newBidder', () => { const bidder = newBidder(spec); const bid = { - requestId: 'some-id', + requestId: '1', ad: 'ad-url.com', cpm: 0.5, height: 200, @@ -423,7 +422,7 @@ describe('bidders created by newBidder', () => { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(logErrorSpy.calledOnce).to.equal(true); }); @@ -436,6 +435,8 @@ describe('bidders created by newBidder', () => { ajaxStub = sinon.stub(ajax, 'ajax', function(url, callbacks) { callbacks.error('ajax call failed.'); }); + addBidResponseStub.reset(); + doneStub.reset(); }); afterEach(() => { @@ -453,12 +454,13 @@ describe('bidders created by newBidder', () => { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.interpretResponse.called).to.equal(false); + expect(doneStub.calledOnce).to.equal(true); }); - it('should add bids for each placement code into the bidmanager', () => { + it('should not add bids for each adunit code into the auction', () => { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -470,13 +472,10 @@ describe('bidders created by newBidder', () => { spec.interpretResponse.returns([]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); - expect(bidmanager.addBidResponse.calledTwice).to.equal(true); - const placementsWithBids = - [bidmanager.addBidResponse.firstCall.args[0], bidmanager.addBidResponse.secondCall.args[0]]; - expect(placementsWithBids).to.contain('mock/placement'); - expect(placementsWithBids).to.contain('mock/placement2'); + expect(addBidResponseStub.callCount).to.equal(0); + expect(doneStub.calledOnce).to.equal(true); }); it('should call spec.getUserSyncs() with no responses', () => { @@ -490,10 +489,11 @@ describe('bidders created by newBidder', () => { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]); + expect(doneStub.calledOnce).to.equal(true); }); }); }); @@ -554,3 +554,193 @@ describe('registerBidder', () => { expect(registerBidAdapterStub.thirdCall.args[1]).to.equal('bar') }); }) + +describe('validate bid response: ', () => { + let spec; + let bidder; + let addBidResponseStub; + let doneStub; + let ajaxStub; + let logErrorSpy; + + let bids = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'requestId': '1', + 'creativeId': 'some-id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + + beforeEach(() => { + spec = { + code: CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + }; + + spec.isBidRequestValid.returns(true); + spec.buildRequests.returns({ + method: 'POST', + url: 'test.url.com', + data: {} + }); + + addBidResponseStub = sinon.stub(); + doneStub = sinon.stub(); + ajaxStub = sinon.stub(ajax, 'ajax', function(url, callbacks) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callbacks.success('response body', { getResponseHeader: fakeResponse }); + }); + logErrorSpy = sinon.spy(utils, 'logError'); + }); + + afterEach(() => { + ajaxStub.restore(); + logErrorSpy.restore(); + }); + + it('should add native bids that do have required assets', () => { + let bidRequest = { + bids: [{ + bidId: 1, + requestId: 'first-bid-id', + adUnitCode: 'mock/placement', + params: { + param: 5 + }, + nativeParams: { + title: {'required': true}, + }, + mediaType: 'native', + }] + }; + + let bids1 = Object.assign({}, + bids[0], + { + 'mediaType': 'native', + 'native': { + 'title': 'Native Creative', + 'clickUrl': 'https://www.link.example', + } + } + ); + + const bidder = newBidder(spec); + + spec.interpretResponse.returns(bids1); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + + expect(addBidResponseStub.calledOnce).to.equal(true); + expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + expect(logErrorSpy.callCount).to.equal(0); + }); + + it('should not add native bids that do not have required assets', () => { + let bidRequest = { + bids: [{ + bidId: 1, + requestId: 'first-bid-id', + adUnitCode: 'mock/placement', + params: { + param: 5 + }, + nativeParams: { + title: {'required': true}, + }, + mediaType: 'native', + }] + }; + + let bids1 = Object.assign({}, + bids[0], + { + bidderCode: CODE, + mediaType: 'native', + native: { + title: undefined, + clickUrl: 'https://www.link.example', + } + } + ); + + const bidder = newBidder(spec); + spec.interpretResponse.returns(bids1); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + + expect(addBidResponseStub.calledOnce).to.equal(false); + expect(logErrorSpy.callCount).to.equal(1); + }); + + it('should add bid when renderer is present on outstream bids', () => { + let bidRequest = { + bids: [{ + bidId: 1, + requestId: 'first-bid-id', + adUnitCode: 'mock/placement', + params: { + param: 5 + }, + mediaTypes: { + video: {context: 'outstream'} + } + }] + }; + + let bids1 = Object.assign({}, + bids[0], + { + bidderCode: CODE, + mediaType: 'video', + renderer: {render: () => true, url: 'render.js'}, + } + ); + + const bidder = newBidder(spec); + + spec.interpretResponse.returns(bids1); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + + expect(addBidResponseStub.calledOnce).to.equal(true); + expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + expect(logErrorSpy.callCount).to.equal(0); + }); + + it('should add banner bids that have no width or height but single adunit size', () => { + let bidRequest = { + bids: [{ + bidder: CODE, + bidId: 1, + requestId: 'first-bid-id', + adUnitCode: 'mock/placement', + params: { + param: 5 + }, + sizes: [[300, 250]], + }] + }; + + let bids1 = Object.assign({}, + bids[0], + { + width: undefined, + height: undefined + } + ); + + const bidder = newBidder(spec); + + spec.interpretResponse.returns(bids1); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + + expect(addBidResponseStub.calledOnce).to.equal(true); + expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + expect(logErrorSpy.callCount).to.equal(0); + }); +}); diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index f705a46a7f7..4e95139a875 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -1,8 +1,10 @@ import { expect } from 'chai'; -import Targeting from 'src/targeting'; +import { targeting as targetingInstance } from 'src/targeting'; import { config } from 'src/config'; import { getAdUnits } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; +import { auctionManager } from 'src/auctionManager'; +import * as targetingModule from 'src/targeting'; const bid1 = { 'bidderCode': 'rubicon', @@ -28,7 +30,10 @@ const bid1 = { 'hb_adid': '148018fe5e', 'hb_pb': '0.53', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }; const bid2 = { @@ -55,45 +60,43 @@ const bid2 = { 'hb_adid': '5454545', 'hb_pb': '0.25', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }; describe('targeting tests', () => { describe('getAllTargeting', () => { + let amBidsReceivedStub; + let amGetAdUnitsStub; + let bidExpiryStub; + beforeEach(() => { $$PREBID_GLOBAL$$._sendAllBids = false; - $$PREBID_GLOBAL$$._bidsReceived = []; - $$PREBID_GLOBAL$$._adUnitCodes = []; - $$PREBID_GLOBAL$$.adUnits = []; + amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived', function() { + return [bid1, bid2]; + }); + amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes', function() { + return ['/123456/header-bid-tag-0']; + }); + bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired', () => true); + }); + + afterEach(() => { + auctionManager.getBidsReceived.restore(); + auctionManager.getAdUnitCodes.restore(); + targetingModule.isBidExpired.restore(); }); it('selects the top bid when _sendAllBids true', () => { - $$PREBID_GLOBAL$$.adUnits = [{ - code: '/123456/header-bid-tag-0', - sizes: [300, 250], - bids: [ - { - 'bidder': 'rubicon', - 'params': { - 'accountId': 10617, - 'siteId': 23635, - 'zoneId': 453908 - } - } - ] - }]; config.setConfig({ enableSendAllBids: true }); - $$PREBID_GLOBAL$$._bidsReceived.push(bid1, bid2); - $$PREBID_GLOBAL$$._adUnitCodes = ['/123456/header-bid-tag-0']; - let targeting = Targeting.getAllTargeting(['/123456/header-bid-tag-0']); - let flattened = []; - targeting.filter(obj => obj['/123456/header-bid-tag-0'] !== undefined).forEach(item => flattened = flattened.concat(item['/123456/header-bid-tag-0'])); - let sendAllBidCpm = flattened.filter(obj => obj.hb_pb_rubicon !== undefined); - let winningBidCpm = flattened.filter(obj => obj.hb_pb !== undefined); + let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf('hb_pb_') != -1) // we shouldn't get more than 1 key for hb_pb_${bidder} expect(sendAllBidCpm.length).to.equal(1); // expect the winning CPM to be equal to the sendAllBidCPM - expect(sendAllBidCpm[0]['hb_pb_rubicon']).to.deep.equal(winningBidCpm[0]['hb_pb']); + expect(targeting['/123456/header-bid-tag-0']['hb_pb_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0']['hb_pb']); }); }); // end getAllTargeting tests }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 1cf366082c0..f0a4f0b8e9a 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -7,7 +7,13 @@ import { getTargetingKeysBidLandscape, getAdUnits } from 'test/fixtures/fixtures'; +import { auctionManager, newAuctionManager } from 'src/auctionManager'; +import { targeting, newTargeting } from 'src/targeting'; import { config as configObj } from 'src/config'; +import * as ajaxLib from 'src/ajax'; +import * as auctionModule from 'src/auction'; +import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; +import * as targetingModule from 'src/targeting'; var assert = require('chai').assert; var expect = require('chai').expect; @@ -16,7 +22,7 @@ var urlParse = require('url-parse'); var prebid = require('src/prebid'); var utils = require('src/utils'); -var bidmanager = require('src/bidmanager'); +// var bidmanager = require('src/bidmanager'); var bidfactory = require('src/bidfactory'); var adloader = require('src/adloader'); var adaptermanager = require('src/adaptermanager'); @@ -25,24 +31,27 @@ var adserver = require('src/adserver'); var CONSTANTS = require('src/constants.json'); // These bid adapters are required to be loaded for the following tests to work -require('modules/appnexusAstBidAdapter'); -require('modules/adequantBidAdapter'); +require('modules/appnexusBidAdapter'); var config = require('test/fixtures/config.json'); $$PREBID_GLOBAL$$ = $$PREBID_GLOBAL$$ || {}; -$$PREBID_GLOBAL$$._bidsRequested = getBidRequests(); -$$PREBID_GLOBAL$$._bidsReceived = getBidResponses(); -$$PREBID_GLOBAL$$.adUnits = getAdUnits(); -$$PREBID_GLOBAL$$._adUnitCodes = $$PREBID_GLOBAL$$.adUnits.map(unit => unit.code); +var adUnits = getAdUnits(); +var adUnitCodes = getAdUnits().map(unit => unit.code); +var bidsBackHandler = function() {}; +const timeout = 2000; +var auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout: timeout}); +auction.getBidRequests = getBidRequests; +auction.getBidsReceived = getBidResponses; +auction.getAdUnits = getAdUnits; +auction.getAuctionStatus = function() { return auctionModule.AUCTION_COMPLETED } function resetAuction() { $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: false }); - $$PREBID_GLOBAL$$.clearAuction(); - $$PREBID_GLOBAL$$._bidsRequested = getBidRequests(); - $$PREBID_GLOBAL$$._bidsReceived = getBidResponses(); - $$PREBID_GLOBAL$$.adUnits = getAdUnits(); - $$PREBID_GLOBAL$$._adUnitCodes = $$PREBID_GLOBAL$$.adUnits.map(unit => unit.code); + auction.getBidRequests = getBidRequests; + auction.getBidsReceived = getBidResponses; + auction.getAdUnits = getAdUnits; + auction.getAuctionStatus = function() { return auctionModule.AUCTION_COMPLETED } } var Slot = function Slot(elementId, pathId) { @@ -138,9 +147,16 @@ window.apntag = { }; describe('Unit: Prebid Module', function () { + let bidExpiryStub; + before(() => { + bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired', () => true); + }); + after(function() { $$PREBID_GLOBAL$$.adUnits = []; + targetingModule.isBidExpired.restore(); }); + describe('getAdserverTargetingForAdUnitCodeStr', function () { beforeEach(() => { resetAuction(); @@ -149,7 +165,7 @@ describe('Unit: Prebid Module', function () { it('should return targeting info as a string', function () { const adUnitCode = config.adUnitCodes[0]; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - var expected = 'foobar=300x250&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; + var expected = 'foobar=0x0%2C300x250%2C300x600&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; var result = $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCodeStr(adUnitCode); assert.equal(expected, result, 'returns expected string of ad targeting info'); }); @@ -194,7 +210,7 @@ describe('Unit: Prebid Module', function () { var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); var expected = { '/19968336/header-bid-tag-0': { - foobar: '300x250', + foobar: '0x0,300x250,300x600', hb_size: '300x250', hb_pb: '10.00', hb_adid: '233bcbee889d46d', @@ -218,17 +234,19 @@ describe('Unit: Prebid Module', function () { assert.deepEqual(targeting, expected); }); - it("should include a losing bid's custom ad targeting key when the bid has `alwaysUseBid` set to `true`", () => { + it("should include a losing bid's custom ad targeting key", () => { // Let's make sure we're getting the expected losing bid. - assert.equal($$PREBID_GLOBAL$$._bidsReceived[0]['bidderCode'], 'triplelift'); - assert.equal($$PREBID_GLOBAL$$._bidsReceived[0]['cpm'], 0.112256); + assert.equal(auction.getBidsReceived()[0]['bidderCode'], 'triplelift'); + assert.equal(auction.getBidsReceived()[0]['cpm'], 0.112256); // Modify the losing bid to have `alwaysUseBid=true` and a custom `adserverTargeting` key. - $$PREBID_GLOBAL$$._bidsReceived[0]['alwaysUseBid'] = true; - $$PREBID_GLOBAL$$._bidsReceived[0]['adserverTargeting'] = { + let _bidsReceived = getBidResponses(); + _bidsReceived[0]['adserverTargeting'] = { always_use_me: 'abc', }; + auction.getBidsReceived = function() { return _bidsReceived }; + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); // Ensure targeting for both ad placements includes the custom key. @@ -239,7 +257,7 @@ describe('Unit: Prebid Module', function () { var expected = { '/19968336/header-bid-tag-0': { - foobar: '300x250', + foobar: '300x250,300x600', hb_size: '300x250', hb_pb: '10.00', hb_adid: '233bcbee889d46d', @@ -254,16 +272,19 @@ describe('Unit: Prebid Module', function () { hb_bidder: 'appnexus' } }; - assert.deepEqual(targeting, expected); }); - it('should not overwrite winning bids custom keys targeting key when the bid has `alwaysUseBid` set to `true`', () => { + it('should not overwrite winning bids custom keys targeting key', () => { + resetAuction(); // mimic a bidderSetting.standard key here for each bid and alwaysUseBid true for every bid - $$PREBID_GLOBAL$$._bidsReceived.forEach(bid => { + let _bidsReceived = getBidResponses(); + _bidsReceived.forEach(bid => { bid.adserverTargeting.custom_ad_id = bid.adId; - bid.alwaysUseBid = true; }); + + auction.getBidsReceived = function() { return _bidsReceived }; + $$PREBID_GLOBAL$$.bidderSettings = { 'standard': { adserverTargeting: [{ @@ -316,26 +337,27 @@ describe('Unit: Prebid Module', function () { }); it('should not send standard targeting keys when the bid has `sendStandardTargeting` set to `false`', () => { - $$PREBID_GLOBAL$$._bidsReceived.forEach(bid => { + let _bidsReceived = getBidResponses(); + _bidsReceived.forEach(bid => { bid.adserverTargeting.custom_ad_id = bid.adId; bid.sendStandardTargeting = false; }); + auction.getBidsReceived = function() { return _bidsReceived }; + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); var expected = { '/19968336/header-bid-tag-0': { - foobar: '300x250', - custom_ad_id: '233bcbee889d46d' + foobar: '0x0,300x250,300x600', + custom_ad_id: '222bb26f9e8bd,233bcbee889d46d,25bedd4813632d7,26e0795ab963896,275bd666f5a5a5d,28f4039c636b6a7,29019e2ab586a5a' }, '/19968336/header-bid-tag1': { foobar: '728x90', custom_ad_id: '24bd938435ec3fc' } }; - assert.deepEqual(targeting, expected); - $$PREBID_GLOBAL$$.bidderSettings = {}; }); }); @@ -350,48 +372,138 @@ describe('Unit: Prebid Module', function () { }; let currentPriceBucket; let bid; + let auction; + let ajaxStub; + let cbTimeout = 3000; + let auctionManagerInstance = newAuctionManager(); + let targeting = newTargeting(auctionManagerInstance); + + let RESPONSE = { + 'version': '0.0.1', + 'tags': [{ + 'uuid': '4d0a6829338a07', + 'tag_id': 4799418, + 'auction_id': '2256922143947979797', + 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', + 'timeout_ms': 2500, + 'ads': [{ + 'content_source': 'rtb', + 'ad_type': 'banner', + 'buyer_member_id': 958, + 'creative_id': 33989846, + 'media_type_id': 1, + 'media_subtype_id': 1, + 'cpm': 1.99, + 'cpm_publisher_currency': 0.500000, + 'publisher_currency_code': '$', + 'client_initiated_ad_counting': true, + 'rtb': { + 'banner': { + 'width': 728, + 'height': 90, + 'content': '' + }, + 'trackers': [{ + 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] + }] + } + }] + }] + }; before(() => { - resetAuction(); + $$PREBID_GLOBAL$$.bidderSettings = {}; currentPriceBucket = configObj.getConfig('priceGranularity'); configObj.setConfig({ priceGranularity: customConfigObject }); - bid = Object.assign({}, - bidfactory.createBid(2), - getBidResponses()[5] - ); + sinon.stub(adaptermanager, 'makeBidRequests', () => ([{ + 'bidderCode': 'appnexus', + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'sizes': [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }] + )); }); after(() => { configObj.setConfig({ priceGranularity: currentPriceBucket }); - resetAuction(); + adaptermanager.makeBidRequests.restore(); }) beforeEach(() => { - $$PREBID_GLOBAL$$._bidsReceived = []; - }) + let adUnits = [{ + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250], [300, 600]], + bids: [{ + bidder: 'appnexus', + params: { + placementId: '10433394' + } + }] + }]; + let adUnitCodes = ['div-gpt-ad-1460505748561-0']; + auction = auctionManagerInstance.createAuction({adUnits, adUnitCodes}); + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + return function(url, callback) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callback.success(JSON.stringify(RESPONSE), { getResponseHeader: fakeResponse }); + } + }); + }); + + afterEach(() => { + ajaxStub.restore(); + }); it('should get correct hb_pb when using bid.cpm is between 0 to 5', () => { - bid.cpm = 2.1234; - bidmanager.addBidResponse(bid.adUnitCode, bid); - expect($$PREBID_GLOBAL$$.getAdserverTargeting()['/19968336/header-bid-tag-0'].hb_pb).to.equal('2.12'); + RESPONSE.tags[0].ads[0].cpm = 2.1234; + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('2.12'); }); it('should get correct hb_pb when using bid.cpm is between 5 to 8', () => { - bid.cpm = 6.78; - bidmanager.addBidResponse(bid.adUnitCode, bid); - expect($$PREBID_GLOBAL$$.getAdserverTargeting()['/19968336/header-bid-tag-0'].hb_pb).to.equal('6.75'); + RESPONSE.tags[0].ads[0].cpm = 6.78; + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('6.75'); }); it('should get correct hb_pb when using bid.cpm is between 8 to 20', () => { - bid.cpm = 19.5234; - bidmanager.addBidResponse(bid.adUnitCode, bid); - expect($$PREBID_GLOBAL$$.getAdserverTargeting()['/19968336/header-bid-tag-0'].hb_pb).to.equal('19.50'); + RESPONSE.tags[0].ads[0].cpm = 19.5234; + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('19.50'); }); it('should get correct hb_pb when using bid.cpm is between 20 to 25', () => { - bid.cpm = 21.5234; - bidmanager.addBidResponse(bid.adUnitCode, bid); - expect($$PREBID_GLOBAL$$.getAdserverTargeting()['/19968336/header-bid-tag-0'].hb_pb).to.equal('21.00'); + RESPONSE.tags[0].ads[0].cpm = 21.5234; + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('21.00'); }); }); @@ -467,6 +579,7 @@ describe('Unit: Prebid Module', function () { it('should set targeting from googletag data', function () { var slots = createSlotArray(); + slots[0].spySetTargeting.reset(); window.googletag.pubads().setSlots(slots); $$PREBID_GLOBAL$$.setTargetingForGPTAsync(); @@ -487,17 +600,20 @@ describe('Unit: Prebid Module', function () { expect(slots[0].spySetTargeting.args).to.deep.contain.members(expected); }); - it('should set targeting for bids with `alwaysUseBid=true`', function () { + it('should set targeting for bids', function () { // Make sure we're getting the expected losing bid. - assert.equal($$PREBID_GLOBAL$$._bidsReceived[0]['bidderCode'], 'triplelift'); - assert.equal($$PREBID_GLOBAL$$._bidsReceived[0]['cpm'], 0.112256); + assert.equal(auctionManager.getBidsReceived()[0]['bidderCode'], 'triplelift'); + assert.equal(auctionManager.getBidsReceived()[0]['cpm'], 0.112256); + resetAuction(); // Modify the losing bid to have `alwaysUseBid=true` and a custom `adserverTargeting` key. - $$PREBID_GLOBAL$$._bidsReceived[0]['alwaysUseBid'] = true; - $$PREBID_GLOBAL$$._bidsReceived[0]['adserverTargeting'] = { + let _bidsReceived = getBidResponses(); + _bidsReceived[0]['adserverTargeting'] = { always_use_me: 'abc', }; + auction.getBidsReceived = function() { return _bidsReceived }; + var slots = createSlotArray(); window.googletag.pubads().setSlots(slots); @@ -522,15 +638,11 @@ describe('Unit: Prebid Module', function () { ], [ 'foobar', - '300x250' + ['300x250', '300x600'] ], [ 'always_use_me', 'abc' - ], - [ - 'foobar', - '300x250' ] ]; @@ -560,16 +672,6 @@ describe('Unit: Prebid Module', function () { }); }); - describe('allBidsAvailable', function () { - it('should call bidmanager.allBidsBack', function () { - var spyAllBidsBack = sinon.spy(bidmanager, 'bidsBackAll'); - - $$PREBID_GLOBAL$$.allBidsAvailable(); - assert.ok(spyAllBidsBack.called, 'called bidmanager.allBidsBack'); - bidmanager.bidsBackAll.restore(); - }); - }); - describe('renderAd', function () { var bidId = 1; var doc = {}; @@ -579,6 +681,21 @@ describe('Unit: Prebid Module', function () { var spyLogMessage = null; var inIframe = true; + function pushBidResponseToAuction(obj) { + adResponse = Object.assign({ + auctionId: 1, + adId: bidId, + width: 300, + height: 250, + }, obj); + auction.getBidsReceived = function() { + let bidsReceived = getBidResponses(); + bidsReceived.push(adResponse); + return bidsReceived; + } + auction.getAuctionId = () => 1; + } + beforeEach(function () { doc = { write: sinon.spy(), @@ -597,13 +714,6 @@ describe('Unit: Prebid Module', function () { }; doc.getElementsByTagName.returns([elStub]); - adResponse = { - adId: bidId, - width: 300, - height: 250, - }; - $$PREBID_GLOBAL$$._bidsReceived.push(adResponse); - spyLogError = sinon.spy(utils, 'logError'); spyLogMessage = sinon.spy(utils, 'logMessage'); @@ -612,8 +722,7 @@ describe('Unit: Prebid Module', function () { }); afterEach(function () { - $$PREBID_GLOBAL$$._bidsReceived.splice($$PREBID_GLOBAL$$._bidsReceived.indexOf(adResponse), 1); - $$PREBID_GLOBAL$$._winningBids = []; + auction.getBidsReceived = getBidResponses; utils.logError.restore(); utils.logMessage.restore(); utils.inIframe.restore(); @@ -632,6 +741,9 @@ describe('Unit: Prebid Module', function () { }); it('should write the ad to the doc', function () { + pushBidResponseToAuction({ + ad: "" + }); adResponse.ad = ""; $$PREBID_GLOBAL$$.renderAd(doc, bidId); assert.ok(doc.write.calledWith(adResponse.ad), 'ad was written to doc'); @@ -639,18 +751,24 @@ describe('Unit: Prebid Module', function () { }); it('should place the url inside an iframe on the doc', function () { - adResponse.adUrl = 'http://server.example.com/ad/ad.js'; + pushBidResponseToAuction({ + adUrl: 'http://server.example.com/ad/ad.js' + }); $$PREBID_GLOBAL$$.renderAd(doc, bidId); assert.ok(elStub.insertBefore.called, 'url was written to iframe in doc'); }); it('should log an error when no ad or url', function () { + pushBidResponseToAuction({}); $$PREBID_GLOBAL$$.renderAd(doc, bidId); var error = 'Error trying to write ad. No ad for bid response id: ' + bidId; assert.ok(spyLogError.calledWith(error), 'expected error was logged'); }); it('should log an error when not in an iFrame', () => { + pushBidResponseToAuction({ + ad: "" + }); inIframe = false; $$PREBID_GLOBAL$$.renderAd(document, bidId); const error = 'Error trying to write ad. Ad render call ad id ' + bidId + ' was prevented from writing to the main document.'; @@ -658,14 +776,17 @@ describe('Unit: Prebid Module', function () { }); it('should not render videos', () => { - adResponse.mediatype = 'video'; + pushBidResponseToAuction({ + mediatype: 'video' + }); $$PREBID_GLOBAL$$.renderAd(doc, bidId); sinon.assert.notCalled(doc.write); - delete adResponse.mediatype; }); it('should catch errors thrown when trying to write ads to the page', function () { - adResponse.ad = ""; + pushBidResponseToAuction({ + ad: "" + }); var error = { message: 'doc write error' }; doc.write = sinon.stub().throws(error); @@ -683,413 +804,396 @@ describe('Unit: Prebid Module', function () { }); it('should save bid displayed to winning bid', function () { + pushBidResponseToAuction({ + ad: "" + }); $$PREBID_GLOBAL$$.renderAd(doc, bidId); - assert.equal($$PREBID_GLOBAL$$._winningBids[0], adResponse); + assert.deepEqual($$PREBID_GLOBAL$$.getAllWinningBids()[0], adResponse); }); }); describe('requestBids', () => { var adUnitsBackup; + var auctionManagerStub; + let logMessageSpy + + let spec = { + code: 'sampleBidder', + isBidRequestValid: () => {}, + buildRequests: () => {}, + interpretResponse: () => {}, + getUserSyncs: () => {} + }; + registerBidder(spec); + + describe('part 1', () => { + beforeEach(() => { + adUnitsBackup = auction.getAdUnits + auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { + return auction; + }); + logMessageSpy = sinon.spy(utils, 'logMessage'); + }); - beforeEach(() => { - adUnitsBackup = $$PREBID_GLOBAL$$.adUnits; - }); - - afterEach(() => { - $$PREBID_GLOBAL$$.adUnits = adUnitsBackup; - resetAuction(); - }); - - it('should add bidsBackHandler callback to bidmanager', () => { - var spyAddOneTimeCallBack = sinon.spy(bidmanager, 'addOneTimeCallback'); - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() { - } - }; - $$PREBID_GLOBAL$$.requestBids(requestObj); - assert.ok(spyAddOneTimeCallBack.calledWith(requestObj.bidsBackHandler), - 'called bidmanager.addOneTimeCallback'); - bidmanager.addOneTimeCallback.restore(); - }); - - it('should log message when adUnits not configured', () => { - const logMessageSpy = sinon.spy(utils, 'logMessage'); + afterEach(() => { + auction.getAdUnits = adUnitsBackup; + auctionManager.createAuction.restore(); + utils.logMessage.restore(); + resetAuction(); + }); - $$PREBID_GLOBAL$$.adUnits = []; - $$PREBID_GLOBAL$$.requestBids({}); + it('should log message when adUnits not configured', () => { + $$PREBID_GLOBAL$$.adUnits = []; + $$PREBID_GLOBAL$$.requestBids({}); - assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); - utils.logMessage.restore(); - }); + assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); + }); - it('should execute callback after timeout', () => { - var spyExecuteCallback = sinon.spy(bidmanager, 'executeCallback'); - var clock = sinon.useFakeTimers(); - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() { - }, + it('should execute callback after timeout', () => { + let clock = sinon.useFakeTimers(); + let requestObj = { + bidsBackHandler: function bidsBackHandlerCallback() {}, + timeout: timeout, + adUnits: auction.getAdUnits() + }; - timeout: 2000 - }; + $$PREBID_GLOBAL$$.requestBids(requestObj); + let re = new RegExp('^Auction [a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12} timedOut$'); + clock.tick(requestObj.timeout - 1); + assert.ok(logMessageSpy.neverCalledWith(sinon.match(re)), 'executeCallback not called'); - $$PREBID_GLOBAL$$.requestBids(requestObj); + clock.tick(1); + assert.ok(logMessageSpy.calledWith(sinon.match(re)), 'executeCallback called'); - clock.tick(requestObj.timeout - 1); - assert.ok(spyExecuteCallback.notCalled, 'bidmanager.executeCallback not called'); + clock.restore(); + }); - clock.tick(1); - assert.ok(spyExecuteCallback.called, 'called bidmanager.executeCallback'); + it('should execute callback immediately if adUnits is empty', () => { + var bidsBackHandler = function bidsBackHandlerCallback() {}; + var spyExecuteCallback = sinon.spy(bidsBackHandler); - bidmanager.executeCallback.restore(); - clock.restore(); - }); + $$PREBID_GLOBAL$$.adUnits = []; + $$PREBID_GLOBAL$$.requestBids({ + bidsBackHandler: spyExecuteCallback + }); - it('should execute callback immediately if adUnits is empty', () => { - var spyExecuteCallback = sinon.spy(bidmanager, 'executeCallback'); + assert.ok(spyExecuteCallback.calledOnce, 'callback executed immediately when adUnits is' + + ' empty'); + }); - $$PREBID_GLOBAL$$.adUnits = []; - $$PREBID_GLOBAL$$.requestBids({}); + it('should not propagate exceptions from bidsBackHandler', () => { + $$PREBID_GLOBAL$$.adUnits = []; - assert.ok(spyExecuteCallback.calledOnce, 'callback executed immediately when adUnits is' + - ' empty'); + var requestObj = { + bidsBackHandler: function bidsBackHandlerCallback() { + var test; + return test.test; + } + }; - bidmanager.executeCallback.restore(); + expect(() => { + $$PREBID_GLOBAL$$.requestBids(requestObj); + }).not.to.throw(); + }); }); - it('should not propagate exceptions from bidsBackHandler', () => { - $$PREBID_GLOBAL$$.adUnits = []; + describe.skip('#video', () => { + let spyCallBids; + let createAuctionStub; + let adUnits; - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() { - var test; - return test.test; - } - }; - - expect(() => { - $$PREBID_GLOBAL$$.requestBids(requestObj); - }).not.to.throw(); - }); + before(() => { + adUnits = [{ + code: 'adUnit-code', + mediaType: 'video', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}}, + {bidder: 'sampleBidder', params: {placementId: 'id'}} + ] + }]; + adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + }); - it('should call callBids function on adaptermanager', () => { - var spyCallBids = sinon.spy(adaptermanager, 'callBids'); + after(() => { + auctionModule.newAuction.restore(); + adaptermanager.callBids.restore(); + }); - $$PREBID_GLOBAL$$.requestBids({}); - assert.ok(spyCallBids.called, 'called adaptermanager.callBids'); - adaptermanager.callBids.restore(); + it('should not callBids if a video adUnit has non-video bidders', () => { + const videoAdaptersBackup = adaptermanager.videoAdapters; + adaptermanager.videoAdapters = ['appnexus']; + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.notCalled(adaptermanager.callBids); + adaptermanager.videoAdapters = videoAdaptersBackup; + }); }); - it('should only request video bidders on video adunits', () => { - sinon.spy(adaptermanager, 'callBids'); - const videoAdaptersBackup = adaptermanager.videoAdapters; - adaptermanager.videoAdapters = ['appnexusAst']; - const adUnits = [{ - code: 'adUnit-code', - mediaType: 'video', - bids: [ - {bidder: 'appnexus', params: {placementId: 'id'}}, - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; - - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + describe('#video', () => { + let spyCallBids; + let createAuctionStub; + let adUnits; - const spyArgs = adaptermanager.callBids.getCall(0); - const biddersCalled = spyArgs.args[0].adUnits[0].bids; - expect(biddersCalled.length).to.equal(1); + before(() => { + adUnits = [{ + code: 'adUnit-code', + mediaType: 'video', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}} + ] + }]; + adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + }) + + after(() => { + auctionModule.newAuction.restore(); + adaptermanager.callBids.restore(); + }); - adaptermanager.callBids.restore(); - adaptermanager.videoAdapters = videoAdaptersBackup; + it('should callBids if a video adUnit has all video bidders', () => { + const videoAdaptersBackup = adaptermanager.videoAdapters; + adaptermanager.videoAdapters = ['appnexus']; + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.calledOnce(adaptermanager.callBids); + adaptermanager.videoAdapters = videoAdaptersBackup; + }); }); - it('should only request video bidders on video adunits configured with mediaTypes', () => { - sinon.spy(adaptermanager, 'callBids'); - const videoAdaptersBackup = adaptermanager.videoAdapters; - adaptermanager.videoAdapters = ['appnexusAst']; - const adUnits = [{ - code: 'adUnit-code', - mediaTypes: {video: {context: 'instream'}}, - bids: [ - {bidder: 'appnexus', params: {placementId: 'id'}}, - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; + describe('#native', () => { + let spyCallBids; + let createAuctionStub; + let adUnits; - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + before(() => { + adUnits = [{ + code: 'adUnit-code', + mediaType: 'native', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}}, + {bidder: 'sampleBidder', params: {placementId: 'id'}} + ] + }]; + adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + }); - const spyArgs = adaptermanager.callBids.getCall(0); - const biddersCalled = spyArgs.args[0].adUnits[0].bids; - expect(biddersCalled.length).to.equal(1); + after(() => { + auctionModule.newAuction.restore(); + adaptermanager.callBids.restore(); + }); - adaptermanager.callBids.restore(); - adaptermanager.videoAdapters = videoAdaptersBackup; + it('should only request native bidders on native adunits', () => { + // appnexus is a native bidder, appnexus is not + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.calledOnce(adaptermanager.callBids); + const spyArgs = adaptermanager.callBids.getCall(0); + const biddersCalled = spyArgs.args[0][0].bids; + expect(biddersCalled.length).to.equal(1); + }); }); - it('should callBids if a video adUnit has all video bidders', () => { - sinon.spy(adaptermanager, 'callBids'); - const videoAdaptersBackup = adaptermanager.videoAdapters; - adaptermanager.videoAdapters = ['appnexusAst']; - const adUnits = [{ - code: 'adUnit-code', - mediaType: 'video', - bids: [ - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; - - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + describe('part 2', () => { + let spyCallBids; + let createAuctionStub; + let adUnits; - adaptermanager.callBids.restore(); - adaptermanager.videoAdapters = videoAdaptersBackup; - }); + before(() => { + adUnits = [{ + code: 'adUnit-code', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: '10433394'}} + ] + }]; + let adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + + adUnits[0]['mediaType'] = 'native'; + adUnitCodes = ['adUnit-code']; + let auction1 = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + + adUnits = [{ + code: 'adUnit-code', + nativeParams: {type: 'image'}, + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}} + ] + }]; + let auction3 = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); - it('should only request native bidders on native adunits', () => { - sinon.spy(adaptermanager, 'callBids'); - // appnexusAst is a native bidder, appnexus is not - const adUnits = [{ - code: 'adUnit-code', - mediaType: 'native', - bids: [ - {bidder: 'appnexus', params: {placementId: 'id'}}, - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; + let createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.onCall(0).returns(auction1); + createAuctionStub.onCall(2).returns(auction3); + createAuctionStub.returns(auction); + }); - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + after(() => { + auctionModule.newAuction.restore(); + }); - const spyArgs = adaptermanager.callBids.getCall(0); - const biddersCalled = spyArgs.args[0].adUnits[0].bids; - expect(biddersCalled.length).to.equal(1); + beforeEach(() => { + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + }) - adaptermanager.callBids.restore(); - }); + afterEach(() => { + adaptermanager.callBids.restore(); + }) - it('should callBids if a native adUnit has all native bidders', () => { - sinon.spy(adaptermanager, 'callBids'); - // TODO: appnexusAst is currently hardcoded in native.js, update this text when fixed - const adUnits = [{ - code: 'adUnit-code', - mediaType: 'native', - bids: [ - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; + it('should callBids if a native adUnit has all native bidders', () => { + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.calledOnce(adaptermanager.callBids); + }); - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + it('should call callBids function on adaptermanager', () => { + let adUnits = [{ + code: 'adUnit-code', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: '10433394'}} + ] + }]; + $$PREBID_GLOBAL$$.requestBids({adUnits}); + assert.ok(spyCallBids.called, 'called adaptermanager.callBids'); + }); - adaptermanager.callBids.restore(); + it('splits native type to individual native assets', () => { + let adUnits = [{ + code: 'adUnit-code', + nativeParams: {type: 'image'}, + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}} + ] + }]; + $$PREBID_GLOBAL$$.requestBids({adUnits}); + const spyArgs = adaptermanager.callBids.getCall(0); + const nativeRequest = spyArgs.args[1][0].bids[0].nativeParams; + expect(nativeRequest).to.deep.equal({ + image: {required: true}, + title: {required: true}, + sponsoredBy: {required: true}, + clickUrl: {required: true}, + body: {required: false}, + icon: {required: false}, + }); + resetAuction(); + }); }); - it('splits native type to individual native assets', () => { - $$PREBID_GLOBAL$$._bidsRequested = []; + describe('part-3', () => { + let auctionManagerInstance = newAuctionManager(); + let auctionManagerStub; + let adUnits1 = getAdUnits().filter((adUnit) => { + return adUnit.code === '/19968336/header-bid-tag1'; + }); + let adUnitCodes1 = getAdUnits().map(unit => unit.code); + let auction1 = auctionManagerInstance.createAuction({adUnits: adUnits1, adUnitCodes: adUnitCodes1}); - const adUnits = [{ - code: 'adUnit-code', - nativeParams: {type: 'image'}, - bids: [ - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; + let adUnits2 = getAdUnits().filter((adUnit) => { + return adUnit.code === '/19968336/header-bid-tag-0'; + }); + let adUnitCodes2 = getAdUnits().map(unit => unit.code); + let auction2 = auctionManagerInstance.createAuction({adUnits: adUnits2, adUnitCodes: adUnitCodes2}); + let spyCallBids; + + auction1.getBidRequests = function() { + return getBidRequests().map((req) => { + req.bids = req.bids.filter((bid) => { + return bid.adUnitCode === '/19968336/header-bid-tag1'; + }); + return (req.bids.length > 0) ? req : undefined; + }).filter((item) => { + return item != undefined; + }); + }; + auction1.getBidsReceived = function() { + return getBidResponses().filter((bid) => { + return bid.adUnitCode === '/19968336/header-bid-tag1'; + }); + }; - $$PREBID_GLOBAL$$.requestBids({adUnits}); + auction2.getBidRequests = function() { + return getBidRequests().map((req) => { + req.bids = req.bids.filter((bid) => { + return bid.adUnitCode === '/19968336/header-bid-tag-0'; + }); + return (req.bids.length > 0) ? req : undefined; + }).filter((item) => { + return item != undefined; + }); + }; + auction2.getBidsReceived = function() { + return getBidResponses().filter((bid) => { + return bid.adUnitCode === '/19968336/header-bid-tag-0'; + }); + }; - const nativeRequest = $$PREBID_GLOBAL$$._bidsRequested[0].bids[0].nativeParams; - expect(nativeRequest).to.deep.equal({ - image: {required: true}, - title: {required: true}, - sponsoredBy: {required: true}, - clickUrl: {required: true}, - body: {required: false}, - icon: {required: false}, + beforeEach(function() { + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + auctionManagerStub = sinon.stub(auctionManager, 'createAuction'); + auctionManagerStub.onCall(0).returns(auction1); + auctionManagerStub.onCall(1).returns(auction2); }); - resetAuction(); - }); + afterEach(function() { + auctionManager.createAuction.restore(); + adaptermanager.callBids.restore(); + }); - it('should queue bid requests when a previous bid request is in process', () => { - var spyCallBids = sinon.spy(adaptermanager, 'callBids'); - var clock = sinon.useFakeTimers(); - var requestObj1 = { - adUnitCodes: ['/19968336/header-bid-tag1'], - bidsBackHandler: function bidsBackHandlerCallback() { - }, + it('should not queue bid requests when a previous bid request is in process', () => { + var requestObj1 = { + bidsBackHandler: function bidsBackHandlerCallback() {}, + timeout: 2000, + adUnits: auction1.getAdUnits() + }; - timeout: 2000 - }; + var requestObj2 = { + bidsBackHandler: function bidsBackHandlerCallback() {}, + timeout: 2000, + adUnits: auction2.getAdUnits() + }; - var requestObj2 = { - adUnitCodes: ['/19968336/header-bid-tag-0'], - bidsBackHandler: function bidsBackHandlerCallback() { - }, + assert.equal(auctionManager.getBidsReceived().length, 8, '_bidsReceived contains 8 bids'); - timeout: 2000 - }; + $$PREBID_GLOBAL$$.requestBids(requestObj1); + $$PREBID_GLOBAL$$.requestBids(requestObj2); - assert.equal($$PREBID_GLOBAL$$._bidsReceived.length, 8, '_bidsReceived contains 8 bids'); - - $$PREBID_GLOBAL$$.requestBids(requestObj1); - $$PREBID_GLOBAL$$.requestBids(requestObj2); - - clock.tick(requestObj1.timeout - 1); - assert.ok(spyCallBids.calledOnce, 'When two requests for bids are made only one should' + - ' callBids immediately'); - assert.equal($$PREBID_GLOBAL$$._bidsReceived.length, 7, '_bidsReceived now contains 7 bids'); - assert.deepEqual($$PREBID_GLOBAL$$._bidsReceived - .find(bid => requestObj1.adUnitCodes.includes(bid.adUnitCode)), undefined, 'Placements' + - ' for' + - ' current request have been cleared of bids'); - assert.deepEqual($$PREBID_GLOBAL$$._bidsReceived - .filter(bid => requestObj2.adUnitCodes.includes(bid.adUnitCode)).length, 7, 'Placements' + - ' for previous request have not been cleared of bids'); - assert.deepEqual($$PREBID_GLOBAL$$._adUnitCodes, ['/19968336/header-bid-tag1'], '_adUnitCodes is' + - ' for first request'); - assert.ok($$PREBID_GLOBAL$$._bidsReceived.length > 0, '_bidsReceived contains bids'); - assert.deepEqual($$PREBID_GLOBAL$$.getBidResponses(), {}, 'yet getBidResponses returns' + - ' empty object for first request (no matching bids for current placement'); - assert.deepEqual($$PREBID_GLOBAL$$.getAdserverTargeting(), {}, 'getAdserverTargeting' + - ' returns empty object for first request'); - clock.tick(1); - - // restore _bidsReceived to simulate more bids returned - $$PREBID_GLOBAL$$._bidsReceived = getBidResponses(); - assert.ok(spyCallBids.calledTwice, 'The second queued request should callBids when the' + - ' first request has completed'); - assert.deepEqual($$PREBID_GLOBAL$$._adUnitCodes, ['/19968336/header-bid-tag-0'], '_adUnitCodes is' + - 'now for second request'); - assert.deepEqual($$PREBID_GLOBAL$$.getBidResponses(), { - '/19968336/header-bid-tag-0': { - 'bids': [ - { - 'bidderCode': 'brightcom', - 'width': 300, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '26e0795ab963896', - 'cpm': 0.17, - 'ad': "", - 'responseTimestamp': 1462919239420, - 'requestTimestamp': 1462919238937, - 'bidder': 'brightcom', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 483, - 'pbLg': '0.00', - 'pbMg': '0.10', - 'pbHg': '0.17', - 'pbAg': '0.15', - 'size': '300x250', - 'requestId': 654321, - 'adserverTargeting': { - 'hb_bidder': 'brightcom', - 'hb_adid': '26e0795ab963896', - 'hb_pb': '10.00', - 'hb_size': '300x250', - 'foobar': '300x250' - } - }, - { - 'bidderCode': 'brealtime', - 'width': 300, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '275bd666f5a5a5d', - 'creative_id': 29681110, - 'cpm': 0.5, - 'adUrl': 'http://lax1-ib.adnxs.com/ab?e=wqT_3QLzBKhzAgAAAwDWAAUBCMjAybkFEIPr4YfMvKLoQBjL84KE1tzG-kkgASotCQAAAQII4D8RAQcQAADgPxkJCQjwPyEJCQjgPykRCaAwuvekAji-B0C-B0gCUNbLkw5YweAnYABokUB4mo8EgAEBigEDVVNEkgUG8FKYAawCoAH6AagBAbABALgBAcABA8gBANABANgBAOABAPABAIoCOnVmKCdhJywgNDk0NDcyLCAxNDYyOTE5MjQwKTt1ZigncicsIDI5NjgxMTEwLDIeAPBvkgLNASFsU2NQWlFpNjBJY0VFTmJMa3c0WUFDREI0Q2N3QURnQVFBUkl2Z2RRdXZla0FsZ0FZSk1IYUFCdzNBMTRDb0FCcGh5SUFRcVFBUUdZQVFHZ0FRR29BUU93QVFDNUFRQUFBQUFBQU9BX3dRRQkMSEFEZ1A4a0JHZmNvazFBejFUX1oVKCRQQV80QUVBOVFFBSw8bUFLS2dOU0NEYUFDQUxVQwUVBEwwCQh0T0FDQU9nQ0FQZ0NBSUFEQVEuLpoCJSFDUWxfYXdpMtAA8KZ3ZUFuSUFRb2lvRFVnZzAu2ALoB-ACx9MB6gIfaHR0cDovL3ByZWJpZC5vcmc6OTk5OS9ncHQuaHRtbIADAIgDAZADAJgDBaADAaoDALADALgDAMADrALIAwDYAwDgAwDoAwD4AwOABACSBAQvanB0mAQAogQKMTAuMS4xMy4zN6gEi-wJsgQICAAQABgAIAC4BADABADIBADSBAsxMC4wLjg1LjIwOA..&s=975cfe6518f064683541240f0d780d93a5f973da&referrer=http%3A%2F%2Fprebid.org%3A9999%2Fgpt.html', - 'responseTimestamp': 1462919239486, - 'requestTimestamp': 1462919238941, - 'bidder': 'brealtime', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 545, - 'pbLg': '0.50', - 'pbMg': '0.50', - 'pbHg': '0.50', - 'pbAg': '0.50', - 'size': '300x250', - 'requestId': 654321, - 'adserverTargeting': { - 'hb_bidder': 'brealtime', - 'hb_adid': '275bd666f5a5a5d', - 'hb_pb': '10.00', - 'hb_size': '300x250', - 'foobar': '300x250' - } - }, - { - 'bidderCode': 'pubmatic', - 'width': '300', - 'height': '250', - 'statusMessage': 'Bid available', - 'adId': '28f4039c636b6a7', - 'adSlot': '39620189@300x250', - 'cpm': 5.9396, - 'ad': "\r
", - 'dealId': '', - 'responseTimestamp': 1462919239544, - 'requestTimestamp': 1462919238922, - 'bidder': 'pubmatic', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 622, - 'pbLg': '5.00', - 'pbMg': '5.90', - 'pbHg': '5.93', - 'pbAg': '5.90', - 'size': '300x250', - 'requestId': 654321, - 'adserverTargeting': { - 'hb_bidder': 'pubmatic', - 'hb_adid': '28f4039c636b6a7', - 'hb_pb': '10.00', - 'hb_size': '300x250', - 'foobar': '300x250' - } - }, - { - 'bidderCode': 'rubicon', - 'width': 300, - 'height': 600, - 'statusMessage': 'Bid available', - 'adId': '29019e2ab586a5a', - 'cpm': 2.74, - 'ad': '', - 'responseTimestamp': 1462919239860, - 'requestTimestamp': 1462919238934, - 'bidder': 'rubicon', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 926, - 'pbLg': '2.50', - 'pbMg': '2.70', - 'pbHg': '2.74', - 'pbAg': '2.70', - 'size': '300x600', - 'requestId': 654321, - 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '29019e2ab586a5a', - 'hb_pb': '10.00', - 'hb_size': '300x600', - 'foobar': '300x600' - } - } - ] - } - }, 'getBidResponses returns info for current bid request'); + assert.ok(spyCallBids.calledTwice, 'When two requests for bids are made both should be' + + ' callBids immediately'); - assert.deepEqual($$PREBID_GLOBAL$$.getAdserverTargeting(), { - '/19968336/header-bid-tag-0': { - 'foobar': '300x250', - 'hb_size': '300x250', - 'hb_pb': '10.00', - 'hb_adid': '233bcbee889d46d', - 'hb_bidder': 'appnexus' + let result = targeting.getAllTargeting(); // $$PREBID_GLOBAL$$.getAdserverTargeting(); + let expected = { + '/19968336/header-bid-tag-0': { + 'foobar': '0x0,300x250,300x600', + 'hb_size': '300x250', + 'hb_pb': '10.00', + 'hb_adid': '233bcbee889d46d', + 'hb_bidder': 'appnexus' + }, + '/19968336/header-bid-tag1': { + 'hb_bidder': 'appnexus', + 'hb_adid': '24bd938435ec3fc', + 'hb_pb': '10.00', + 'hb_size': '728x90', + 'foobar': '728x90' + } } - }, 'targeting info returned for current placements'); - resetAuction(); - adaptermanager.callBids.restore(); + assert.deepEqual(result, expected, 'targeting info returned for current placements'); + }); }); }); @@ -1145,31 +1249,6 @@ describe('Unit: Prebid Module', function () { }); }); - describe('addCallback', () => { - it('should log error and return null id when error registering callback', () => { - var spyLogError = sinon.spy(utils, 'logError'); - var id = $$PREBID_GLOBAL$$.addCallback('event', 'fakeFunction'); - assert.equal(id, null, 'id returned was null'); - assert.ok(spyLogError.calledWith('error registering callback. Check method signature'), - 'expected error was logged'); - utils.logError.restore(); - }); - - it('should add callback to bidmanager', () => { - var spyAddCallback = sinon.spy(bidmanager, 'addCallback'); - var id = $$PREBID_GLOBAL$$.addCallback('event', Function); - assert.ok(spyAddCallback.calledWith(id, Function, 'event'), 'called bidmanager.addCallback'); - bidmanager.addCallback.restore(); - }); - }); - - describe('removeCallback', () => { - it('should return null', () => { - const id = $$PREBID_GLOBAL$$.removeCallback(); - assert.equal(id, null); - }); - }); - describe('registerBidAdapter', () => { it('should register bidAdaptor with adaptermanager', () => { var registerBidAdapterSpy = sinon.spy(adaptermanager, 'registerBidAdapter'); @@ -1191,19 +1270,6 @@ describe('Unit: Prebid Module', function () { }); }); - describe('bidsAvailableForAdapter', () => { - it('should update requested bid with status set to available', () => { - const bidderCode = 'appnexus'; - $$PREBID_GLOBAL$$.bidsAvailableForAdapter(bidderCode); - - const requestedBids = $$PREBID_GLOBAL$$._bidsRequested.find(bid => bid.bidderCode === bidderCode); - requestedBids.bids.forEach(bid => { - assert.equal(bid.bidderCode, bidderCode, 'bidderCode was set'); - assert.equal(bid.statusMessage, 'Bid available', 'bid set as available'); - }); - }); - }); - describe('createBid', () => { it('should return a bid object', () => { const statusCode = 1; @@ -1217,18 +1283,6 @@ describe('Unit: Prebid Module', function () { }); }); - describe('addBidResponse', () => { - it('should call bidmanager.addBidResponse', () => { - const addBidResponseStub = sinon.stub(bidmanager, 'addBidResponse'); - const adUnitCode = 'testcode'; - const bid = $$PREBID_GLOBAL$$.createBid(0); - - $$PREBID_GLOBAL$$.addBidResponse(adUnitCode, bid); - assert.ok(addBidResponseStub.calledWith(adUnitCode, bid), 'called bidmanager.addBidResponse'); - bidmanager.addBidResponse.restore(); - }); - }); - describe('loadScript', () => { it('should call adloader.loadScript', () => { const loadScriptSpy = sinon.spy(adloader, 'loadScript'); @@ -1242,79 +1296,6 @@ describe('Unit: Prebid Module', function () { }); }); - // describe('enableAnalytics', () => { - // let logErrorSpy; - // - // beforeEach(() => { - // logErrorSpy = sinon.spy(utils, 'logError'); - // }); - // - // afterEach(() => { - // utils.logError.restore(); - // }); - // - // it('should log error when not passed options', () => { - // const error = '$$PREBID_GLOBAL$$.enableAnalytics should be called with option {}'; - // $$PREBID_GLOBAL$$.enableAnalytics(); - // assert.ok(logErrorSpy.calledWith(error), 'expected error was logged'); - // }); - // - // it('should call ga.enableAnalytics with options', () => { - // const enableAnalyticsSpy = sinon.spy(ga, 'enableAnalytics'); - // - // let options = {'provider': 'ga'}; - // $$PREBID_GLOBAL$$.enableAnalytics(options); - // assert.ok(enableAnalyticsSpy.calledWith({}), 'ga.enableAnalytics called with empty options object'); - // - // options['options'] = 'testoptions'; - // $$PREBID_GLOBAL$$.enableAnalytics(options); - // assert.ok(enableAnalyticsSpy.calledWith(options.options), 'ga.enableAnalytics called with provided options'); - // - // ga.enableAnalytics.restore(); - // }); - // - // it('should catch errors thrown from ga.enableAnalytics', () => { - // const error = {message: 'Error calling GA: '}; - // const enableAnalyticsStub = sinon.stub(ga, 'enableAnalytics').throws(error); - // const options = {'provider': 'ga'}; - // - // $$PREBID_GLOBAL$$.enableAnalytics(options); - // assert.ok(logErrorSpy.calledWith(error.message), 'expected error was caught'); - // ga.enableAnalytics.restore(); - // }); - // - // it('should return null for other providers', () => { - // const options = {'provider': 'other_provider'}; - // const returnValue = $$PREBID_GLOBAL$$.enableAnalytics(options); - // assert.equal(returnValue, null, 'expected return value'); - // }); - // }); - - describe('sendTimeoutEvent', () => { - it('should emit BID_TIMEOUT for timed out bids', () => { - const eventsEmitSpy = sinon.spy(events, 'emit'); - - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() {}, - timeout: 20 - }; - var adUnits = [{ - code: 'code', - bids: [{ - bidder: 'appnexus', - params: { placementId: '123' } - }] - }]; - $$PREBID_GLOBAL$$.adUnits = adUnits; - $$PREBID_GLOBAL$$.requestBids(requestObj); - - setTimeout(function () { - assert.ok(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BID_TIMEOUT), 'emitted events BID_TIMEOUT'); - events.emit.restore(); - }, 100); - }); - }); - describe('aliasBidder', () => { it('should call adaptermanager.aliasBidder', () => { const aliasBidAdapterSpy = sinon.spy(adaptermanager, 'aliasBidAdapter'); @@ -1388,101 +1369,16 @@ describe('Unit: Prebid Module', function () { }); }); - describe('getAllWinningBids', () => { - it('should return all winning bids', () => { - const bids = {name: 'a winning bid'}; - $$PREBID_GLOBAL$$._winningBids = bids; - - assert.deepEqual($$PREBID_GLOBAL$$.getAllWinningBids(), bids); - - $$PREBID_GLOBAL$$._winningBids = []; - }); - }); - describe('emit event', () => { - it('should call AUCTION_END only once', () => { - resetAuction(); - var spyClearAuction = sinon.spy($$PREBID_GLOBAL$$, 'clearAuction'); - var clock1 = sinon.useFakeTimers(); - - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() {}, - timeout: 2000, - }; - - $$PREBID_GLOBAL$$.requestBids(requestObj); - clock1.tick(2001); - assert.ok(spyClearAuction.calledOnce, true); - - $$PREBID_GLOBAL$$._bidsRequested = [{ - 'bidderCode': 'appnexus', - 'requestId': '1863e370099523', - 'bidderRequestId': '2946b569352ef2', - 'bids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': '4799418', - 'test': 'me' - }, - 'placementCode': '/19968336/header-bid-tag1', - 'sizes': [[728, 90], [970, 90]], - 'bidId': '392b5a6b05d648', - 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', - 'startTime': 1462918897462, - 'status': 1 - } - ], - 'start': 1462918897460 - }]; - - $$PREBID_GLOBAL$$._bidsReceived = []; - - var bid = Object.assign({ - 'bidderCode': 'appnexus', - 'width': 728, - 'height': 90, - 'statusMessage': 'Bid available', - 'adId': '24bd938435ec3fc', - 'creative_id': 33989846, - 'cpm': 0, - 'adUrl': 'http://lax1-ib.adnxs.com/ab?e=wqT_3QLyBKhyAgAAAwDWAAUBCMjAybkFEOOryfjI7rGNWhjL84KE1tzG-kkgASotCQAAAQII4D8RAQcQAADgPxkJCQjwPyEJCQjgPykRCaAwuvekAji-B0C-B0gCUNbJmhBYweAnYABokUB4mt0CgAEBigEDVVNEkgUG8ECYAdgFoAFaqAEBsAEAuAEBwAEDyAEA0AEA2AEA4AEA8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE0NjI5MTkyNDApOwEcLHInLCAzMzk4OTg0NjYeAPBvkgLNASFwU2Y1YUFpNjBJY0VFTmJKbWhBWUFDREI0Q2N3QURnQVFBUkl2Z2RRdXZla0FsZ0FZSk1IYUFCd3lnNTRDb0FCcGh5SUFRcVFBUUdZQVFHZ0FRR29BUU93QVFDNUFRQUFBQUFBQU9BX3dRRQkMSEFEZ1A4a0JJNTJDbGs5VjB6X1oVKCRQQV80QUVBOVFFBSw8bUFLS2dNQ0NENkFDQUxVQwUVBEwwCQh0T0FDQU9nQ0FQZ0NBSUFEQVEuLpoCJSFfZ2lqYXdpMtAA8KZ3ZUFuSUFRb2lvREFnZzgu2ALoB-ACx9MB6gIfaHR0cDovL3ByZWJpZC5vcmc6OTk5OS9ncHQuaHRtbIADAIgDAZADAJgDBaADAaoDALADALgDAMADrALIAwDYAwDgAwDoAwD4AwOABACSBAQvanB0mAQAogQKMTAuMS4xMy4zN6gEi-wJsgQICAAQABgAIAC4BADABADIBADSBAsxMC4wLjgwLjI0MA..&s=1f584d32c2d7ae3ce3662cfac7ca24e710bc7fd0&referrer=http%3A%2F%2Fprebid.org%3A9999%2Fgpt.html', - 'responseTimestamp': 1462919239342, - 'requestTimestamp': 1462919238919, - 'bidder': 'appnexus', - 'adUnitCode': '/19968336/header-bid-tag1', - 'timeToRespond': 423, - 'pbLg': '5.00', - 'pbMg': '10.00', - 'pbHg': '10.00', - 'pbAg': '10.00', - 'size': '728x90', - 'alwaysUseBid': true, - 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '24bd938435ec3fc', - 'hb_pb': '10.00', - 'hb_size': '728x90', - 'foobar': '728x90' - } - }, bidfactory.createBid(2)); - - var adUnits = [{ - code: '/19968336/header-bid-tag1', - bids: [{ - bidder: 'appnexus', - params: { placementId: '123' } - }] - }]; - $$PREBID_GLOBAL$$.adUnits = adUnits; - - const adUnitCode = '/19968336/header-bid-tag1'; - $$PREBID_GLOBAL$$.addBidResponse(adUnitCode, bid); - assert.equal(spyClearAuction.callCount, 1, 'AUCTION_END event emitted more than once'); + let auctionManagerStub; + beforeEach(() => { + auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { + return auction; + }); + }); - clock1.restore(); - resetAuction(); + afterEach(() => { + auctionManager.createAuction.restore(); }); }); @@ -1566,126 +1462,18 @@ describe('Unit: Prebid Module', function () { }); }); - describe('video adserverTag', () => { - var adserverTag = 'https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/19968336/header-bid-tag-0&impl=s&gdfp_req=1&env=vp&output=xml_vast2&unviewed_position_start=1&url=www.test.com'; - - var options = { - 'adserver': 'dfp', - 'code': '/19968336/header-bid-tag-0' - }; - + describe('setBidderSequence', () => { + let auctionManagerStub; beforeEach(() => { - resetAuction(); - $$PREBID_GLOBAL$$._bidsReceived = [ - { - 'bidderCode': 'appnexusAstDummyName', - 'width': 0, - 'height': 0, - 'statusMessage': 'Bid returned empty or error response', - 'adId': '233bcbee889d46d', - 'requestId': 123456, - 'responseTimestamp': 1462919238959, - 'requestTimestamp': 1462919238910, - 'cpm': 0, - 'bidder': 'appnexus', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 49, - 'pbLg': '0.00', - 'pbMg': '0.00', - 'pbHg': '0.00', - 'pbAg': '0.00', - 'pbDg': '0.00', - 'pbCg': '', - 'adserverTargeting': {} - }, - { - 'bidderCode': 'appnexusAst', - 'dealId': '1234', - 'width': 300, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '233bcbee889d46d', - 'creative_id': 29681110, - 'cpm': 10, - 'vastUrl': 'http://www.simplevideoad.com/', - 'responseTimestamp': 1462919239340, - 'requestTimestamp': 1462919238919, - 'bidder': 'appnexus', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 421, - 'pbLg': '5.00', - 'pbMg': '10.00', - 'pbHg': '10.00', - 'pbAg': '10.00', - 'size': '300x250', - 'alwaysUseBid': true, - 'requestId': 123456, - 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '233bcbee889d46d', - 'hb_pb': '10.00', - 'hb_size': '300x250', - 'foobar': '300x250', - 'hb_deal_appnexusAst': '1234' - } - } - ]; - }); - - afterEach(() => { - resetAuction(); - }); - - it('should log error when adserver is not dfp', () => { - var logErrorSpy = sinon.spy(utils, 'logError'); - var options = { - 'adserver': 'anyother', - 'code': '/19968336/header-bid-tag-0' - }; - var masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, options); - assert.ok(logErrorSpy.calledOnce, true); - utils.logError.restore(); - }); - - it('should return original adservertag if bids empty', () => { - $$PREBID_GLOBAL$$._bidsReceived = []; - var masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, options); - expect(masterTagUrl).to.equal(adserverTag); - }); - - it('should return original adservertag if there are no bids for the given placement code', () => { - // urls.js:parse returns port 443 for IE11, blank for other browsers - const ie11port = !!window.MSInputMethodContext && !!document.documentMode ? ':443' : ''; - const adserverTag = `https://pubads.g.doubleclick.net${ie11port}/gampad/ads?sz=640x480&iu=/19968336/header-bid-tag-0&impl=s&gdfp_req=1&env=vp&output=xml_vast2&unviewed_position_start=1&url=www.test.com`; - - const masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, { - 'adserver': 'dfp', - 'code': 'one-without-bids' + auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { + return auction; }); - - expect(masterTagUrl).to.equal(adserverTag); }); - it('should log error when google\'s parameters are missing in adserverTag', () => { - var logErrorSpy = sinon.spy(utils, 'logError'); - var adserverTag = 'https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/19968336/header-bid-tag-0&impl=s&gdfp_req=1&env=vp&output=xml_vast2&unviewed_position_start=1&url=www.test.com'; - var masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, options); - assert.ok(logErrorSpy.calledOnce, true); - utils.logError.restore(); - }); - - it('should append parameters to the adserverTag', () => { - var masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, options); - var masterTagUrlParsed = urlParse(masterTagUrl, true); - var masterTagQuery = masterTagUrlParsed.query; - var expectedTargetingQuery = 'hb_bidder=appnexus&hb_adid=233bcbee889d46d&hb_pb=10.00&hb_size=300x250&foobar=300x250&hb_deal_appnexusAst=1234'; - - expect(masterTagQuery).to.have.property('cust_params').and.to.equal(expectedTargetingQuery); - expect(masterTagQuery).to.have.property('description_url').and.to.equal('http://www.simplevideoad.com/'); + afterEach(() => { + auctionManager.createAuction.restore(); }); - }); - describe('bidderSequence', () => { it('setting to `random` uses shuffled order of adUnits', () => { sinon.spy(utils, 'shuffle'); const requestObj = { @@ -1706,14 +1494,14 @@ describe('Unit: Prebid Module', function () { it('returns an array of winning bid objects for each adUnit', () => { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids(); expect(highestCpmBids.length).to.equal(2); - expect(highestCpmBids[0]).to.deep.equal($$PREBID_GLOBAL$$._bidsReceived[1]); - expect(highestCpmBids[1]).to.deep.equal($$PREBID_GLOBAL$$._bidsReceived[2]); + expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); + expect(highestCpmBids[1]).to.deep.equal(auctionManager.getBidsReceived()[2]); }); it('returns an array containing the highest bid object for the given adUnitCode', () => { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); expect(highestCpmBids.length).to.equal(1); - expect(highestCpmBids[0]).to.deep.equal($$PREBID_GLOBAL$$._bidsReceived[1]); + expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); }); it('returns an empty array when the given adUnit is not found', () => { @@ -1722,8 +1510,10 @@ describe('Unit: Prebid Module', function () { }); it('returns an empty array when the given adUnit has no bids', () => { - $$PREBID_GLOBAL$$._bidsReceived = [$$PREBID_GLOBAL$$._bidsReceived[0]]; - $$PREBID_GLOBAL$$._bidsReceived[0].cpm = 0; + let _bidsReceived = getBidResponses()[0]; + _bidsReceived.cpm = 0; + auction.getBidsReceived = function() { return _bidsReceived }; + const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); expect(highestCpmBids.length).to.equal(0); resetAuction(); @@ -1731,18 +1521,30 @@ describe('Unit: Prebid Module', function () { }); describe('setTargetingForAst', () => { + let targeting; + let auctionManagerInstance; + beforeEach(() => { resetAuction(); + auctionManagerInstance = newAuctionManager(); + sinon.stub(auctionManagerInstance, 'getBidsReceived', function() { + return [getBidResponses()[1]]; + }); + sinon.stub(auctionManagerInstance, 'getAdUnitCodes', function() { + return ['/19968336/header-bid-tag-0']; + }); + targeting = newTargeting(auctionManagerInstance); }); afterEach(() => { + auctionManagerInstance.getBidsReceived.restore(); + auctionManagerInstance.getAdUnitCodes.restore(); resetAuction(); }); it('should set targeting for appnexus apntag object', () => { + const bids = auctionManagerInstance.getBidsReceived(); const adUnitCode = '/19968336/header-bid-tag-0'; - const bidder = 'appnexus'; - const bids = $$PREBID_GLOBAL$$._bidsReceived.filter(bid => (bid.adUnitCode === adUnitCode && bid.bidderCode === bidder)); var expectedAdserverTargeting = bids[0].adserverTargeting; var newAdserverTargeting = {}; @@ -1751,14 +1553,14 @@ describe('Unit: Prebid Module', function () { newAdserverTargeting[nkey] = expectedAdserverTargeting[key]; } - $$PREBID_GLOBAL$$.setTargetingForAst(); + targeting.setTargetingForAst(); expect(newAdserverTargeting).to.deep.equal(window.apntag.tags[adUnitCode].keywords); }); it('should not find hb_adid key in lowercase for all bidders', () => { const adUnitCode = '/19968336/header-bid-tag-0'; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - $$PREBID_GLOBAL$$.setTargetingForAst(); + targeting.setTargetingForAst(); const keywords = Object.keys(window.apntag.tags[adUnitCode].keywords).filter(keyword => (keyword.substring(0, 'hb_adid'.length) === 'hb_adid')); expect(keywords.length).to.equal(0); }); @@ -1797,42 +1599,4 @@ describe('Unit: Prebid Module', function () { assert.equal($$PREBID_GLOBAL$$.que.push, $$PREBID_GLOBAL$$.cmd.push); }); }); - - describe('setS2SConfig', () => { - let logErrorSpy; - - beforeEach(() => { - logErrorSpy = sinon.spy(utils, 'logError'); - }); - - afterEach(() => { - utils.logError.restore(); - }); - - it('should log error when accountId is missing', () => { - const options = { - enabled: true, - bidders: ['appnexus'], - timeout: 1000, - adapter: 'prebidServer', - endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' - }; - - $$PREBID_GLOBAL$$.setConfig({ s2sConfig: {options} }); - assert.ok(logErrorSpy.calledOnce, true); - }); - - it('should log error when bidders is missing', () => { - const options = { - accountId: '1', - enabled: true, - timeout: 1000, - adapter: 's2s', - endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' - }; - - $$PREBID_GLOBAL$$.setConfig({ s2sConfig: {options} }); - assert.ok(logErrorSpy.calledOnce, true); - }); - }); }); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index c2f664e19f0..9f7c57ccb81 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -100,7 +100,7 @@ describe('Utils', function () { var obj = getAdServerTargeting(); var output = utils.transformAdServerTargetingObj(obj[Object.keys(obj)[0]]); - var expected = 'foobar=300x250&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; + var expected = 'foobar=0x0%2C300x250%2C300x600&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; assert.equal(output, expected); }); diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index e9af314218e..ab52b3be145 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -1,6 +1,7 @@ import 'mocha'; import chai from 'chai'; import { getCacheUrl, store } from 'src/videoCache'; +import { config } from 'src/config'; const should = chai.should(); @@ -48,9 +49,17 @@ describe('The video cache', () => { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = (request) => requests.push(request); + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }) }); - afterEach(() => xhr.restore()); + afterEach(() => { + xhr.restore(); + config.resetConfig(); + }); it('should execute the callback with a successful result when store() is called', () => { const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; @@ -128,6 +137,18 @@ describe('The video cache', () => { }); describe('The getCache function', () => { + beforeEach(() => { + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }) + }); + + afterEach(() => { + config.resetConfig(); + }); + it('should return the expected URL', () => { const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; const url = getCacheUrl(uuid); diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js index 512b56c334f..5ad9b662e7f 100644 --- a/test/spec/video_spec.js +++ b/test/spec/video_spec.js @@ -1,82 +1,89 @@ import { isValidVideoBid } from 'src/video'; -import { newConfig } from 'src/config'; -import * as utils from 'src/utils'; describe('video.js', () => { - afterEach(() => { - utils.getBidRequest.restore(); - }); - it('validates valid instream bids', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'appnexusAst', - mediaTypes: { - video: { context: 'instream' }, - }, - })); - - const valid = isValidVideoBid({ + const bid = { + adId: '123abc', vastUrl: 'http://www.example.com/vastUrl' - }); - + }; + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'instream' } + } + }] + }]; + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.be(true); }); it('catches invalid instream bids', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'appnexusAst', - mediaTypes: { - video: { context: 'instream' }, - }, - })); - - const valid = isValidVideoBid({}); - + const bid = { + adId: '123abc' + }; + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'instream' } + } + }] + }]; + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.be(false); }); it('catches invalid bids when prebid-cache is disabled', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'vastOnlyVideoBidder', - mediaTypes: { video: {} }, - })); + const bidRequests = [{ + bids: [{ + bidder: 'vastOnlyVideoBidder', + mediaTypes: { video: {} }, + }] + }]; - const config = newConfig(); - config.setConfig({ usePrebidCache: false }); - - const valid = isValidVideoBid({ vastXml: 'vast' }); + const valid = isValidVideoBid({ vastXml: 'vast' }, bidRequests); expect(valid).to.be(false); }); it('validates valid outstream bids', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'appnexusAst', - mediaTypes: { - video: { context: 'outstream' }, - }, - })); - - const valid = isValidVideoBid({ + const bid = { + adId: '123abc', renderer: { url: 'render.url', render: () => true, } - }); - + }; + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'outstream' } + } + }] + }]; + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.be(true); }); it('catches invalid outstream bids', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'appnexusAst', - mediaTypes: { - video: { context: 'outstream' }, - }, - })); - - const valid = isValidVideoBid({}); - + const bid = { + adId: '123abc' + }; + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'outstream' } + } + }] + }]; + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.be(false); }); }); From 8292bb1b86f36864bcd4f700fdf6567a3e29b298 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 8 Dec 2017 14:43:13 -0700 Subject: [PATCH 0002/1594] use same adUnits copy for s2s in callBids that we made in makeBidRequests (#1940) --- src/adaptermanager.js | 4 +- test/spec/unit/core/adapterManager_spec.js | 156 +++++++++++++++++++++ 2 files changed, 159 insertions(+), 1 deletion(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 95db1e74b2a..670b329ef72 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -180,6 +180,7 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, auctionId, bidderRequestId, tid, + adUnitsS2SCopy, bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsS2SCopy, labels}), auctionStart: auctionStart, timeout: _s2sConfig.timeout, @@ -227,9 +228,10 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { let adaptersServerSide = _s2sConfig.bidders; const s2sAdapter = _bidderRegistry[_s2sConfig.adapter]; let tid = serverBidRequests[0].tid; + let adUnitsS2SCopy = serverBidRequests[0].adUnitsS2SCopy; if (s2sAdapter) { - let s2sBidRequest = {tid, 'ad_units': getAdUnitCopyForPrebidServer(adUnits)}; + let s2sBidRequest = {tid, 'ad_units': adUnitsS2SCopy}; if (s2sBidRequest.ad_units.length) { let doneCbs = serverBidRequests.map(bidRequest => { bidRequest.doneCbCallCount = 0; diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 21ab14ea99e..95a249263b5 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -126,6 +126,84 @@ describe('adapterManager tests', () => { 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', 'src': 's2s', + 'adUnitsS2SCopy': [ + { + 'code': '/19968336/header-bid-tag1', + 'sizes': [ + { + 'w': 728, + 'h': 90 + }, + { + 'w': 970, + 'h': 90 + } + ], + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '543221', + 'test': 'me' + }, + 'placementCode': '/19968336/header-bid-tag1', + 'sizes': [ + [ + 728, + 90 + ], + [ + 970, + 90 + ] + ], + 'bidId': '68136e1c47023d', + 'bidderRequestId': '55e24a66bed717', + 'requestId': '1ff753bd4ae5cb', + 'startTime': 1463510220995, + 'status': 1, + 'bid_id': '378a8914450b334' + } + ] + }, + { + 'code': '/19968336/header-bid-tag-0', + 'sizes': [ + { + 'w': 300, + 'h': 250 + }, + { + 'w': 300, + 'h': 600 + } + ], + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '5324321' + }, + 'placementCode': '/19968336/header-bid-tag-0', + 'sizes': [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ], + 'bidId': '7e5d6af25ed188', + 'bidderRequestId': '55e24a66bed717', + 'requestId': '1ff753bd4ae5cb', + 'startTime': 1463510220996, + 'bid_id': '387d9d9c32ca47c' + } + ] + } + ], 'bids': [ { 'bidder': 'appnexus', @@ -211,6 +289,84 @@ describe('adapterManager tests', () => { 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', 'src': 's2s', + 'adUnitsS2SCopy': [ + { + 'code': '/19968336/header-bid-tag1', + 'sizes': [ + { + 'w': 728, + 'h': 90 + }, + { + 'w': 970, + 'h': 90 + } + ], + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '543221', + 'test': 'me' + }, + 'placementCode': '/19968336/header-bid-tag1', + 'sizes': [ + [ + 728, + 90 + ], + [ + 970, + 90 + ] + ], + 'bidId': '68136e1c47023d', + 'bidderRequestId': '55e24a66bed717', + 'requestId': '1ff753bd4ae5cb', + 'startTime': 1463510220995, + 'status': 1, + 'bid_id': '378a8914450b334' + } + ] + }, + { + 'code': '/19968336/header-bid-tag-0', + 'sizes': [ + { + 'w': 300, + 'h': 250 + }, + { + 'w': 300, + 'h': 600 + } + ], + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '5324321' + }, + 'placementCode': '/19968336/header-bid-tag-0', + 'sizes': [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ], + 'bidId': '7e5d6af25ed188', + 'bidderRequestId': '55e24a66bed717', + 'requestId': '1ff753bd4ae5cb', + 'startTime': 1463510220996, + 'bid_id': '387d9d9c32ca47c' + } + ] + } + ], 'bids': [ { 'bidder': 'appnexus', From fdad39201163974681560a9198da683786750273 Mon Sep 17 00:00:00 2001 From: Denis Logachev Date: Mon, 11 Dec 2017 18:59:50 +0200 Subject: [PATCH 0003/1594] XDomainRequest.send exception fix (#1942) --- src/ajax.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ajax.js b/src/ajax.js index 19dc1b3869f..df52ac949da 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -98,7 +98,11 @@ export function ajaxBuilder(timeout = 3000) { } x.setRequestHeader('Content-Type', options.contentType || 'text/plain'); } - x.send(method === 'POST' && data); + if (method === 'POST' && data) { + x.send(data); + } else { + x.send(); + } } catch (error) { utils.logError('xhr construction', error); } From 93d33ca7e590d0daa7384b55400fe3bc26b1b999 Mon Sep 17 00:00:00 2001 From: takuhou Date: Wed, 13 Dec 2017 01:57:05 +0900 Subject: [PATCH 0004/1594] Added YIELDONE Bid Adapter for Prebid.js 1.0 (#1900) * Added YIELDONE Bid Adapter for Prebid.js 1.0 * Update yieldoneBidAdapter.md change placementId to 44082 * Changed to get size from bid.sizes * fix sizes array --- modules/yieldoneBidAdapter.js | 71 +++++++++ modules/yieldoneBidAdapter.md | 27 ++++ test/spec/modules/yieldoneBidAdapter_spec.js | 147 +++++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 modules/yieldoneBidAdapter.js create mode 100644 modules/yieldoneBidAdapter.md create mode 100644 test/spec/modules/yieldoneBidAdapter_spec.js diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js new file mode 100644 index 00000000000..9f94b5b815e --- /dev/null +++ b/modules/yieldoneBidAdapter.js @@ -0,0 +1,71 @@ +import * as utils from 'src/utils'; +import {config} from 'src/config'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'yieldone'; +const ENDPOINT_URL = '//y.one.impact-ad.jp/h_bid'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['y1'], + isBidRequestValid: function(bid) { + return !!(bid.params.placementId); + }, + buildRequests: function(validBidRequests) { + return validBidRequests.map(bidRequest => { + const params = bidRequest.params; + const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; + const width = sizes.split('x')[0]; + const height = sizes.split('x')[1]; + const placementId = params.placementId; + const cb = Math.floor(Math.random() * 99999999999); + const referrer = encodeURIComponent(utils.getTopWindowUrl()); + const bidId = bidRequest.bidId; + const payload = { + v: 'hb1', + p: placementId, + w: width, + h: height, + cb: cb, + r: referrer, + uid: bidId, + t: 'i' + }; + return { + method: 'GET', + url: ENDPOINT_URL, + data: payload, + } + }); + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + const response = serverResponse.body; + const crid = response.crid || 0; + const width = response.width || 0; + const height = response.height || 0; + const cpm = response.cpm * 1000 || 0; + if (width !== 0 && height !== 0 && cpm !== 0 && crid !== 0) { + const dealId = response.dealid || ''; + const currency = response.currency || 'JPY'; + const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; + const referrer = utils.getTopWindowUrl(); + const bidResponse = { + requestId: bidRequest.data.uid, + cpm: cpm, + width: response.width, + height: response.height, + creativeId: crid, + dealId: dealId, + currency: currency, + netRevenue: netRevenue, + ttl: config.getConfig('_bidderTimeout'), + referrer: referrer, + ad: response.adTag + }; + bidResponses.push(bidResponse); + } + return bidResponses; + } +} +registerBidder(spec); diff --git a/modules/yieldoneBidAdapter.md b/modules/yieldoneBidAdapter.md new file mode 100644 index 00000000000..f1f48637927 --- /dev/null +++ b/modules/yieldoneBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +``` +Module Name: YIELDONE Bidder Adapter +Module Type: Bidder Adapter +Maintainer: y1dev@platform-one.co.jp +``` + +# Description + +Connect to YIELDONE for bids. + +THE YIELDONE adapter requires setup and approval from the Rubicon Project team. Please reach out to your account team or y1s@platform-one.co.jp for more information. + +# Test Parameters +``` + var adUnits = [{ + code: 'banner-ad-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'yieldone', + params: { + placementId: '44082' + } + }] + }]; +``` diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js new file mode 100644 index 00000000000..e763257f097 --- /dev/null +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -0,0 +1,147 @@ +import { expect } from 'chai'; +import { spec } from 'modules/yieldoneBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//y.one.impact-ad.jp/h_bid'; + +describe('yieldoneBidAdapter', function() { + const adapter = newBidder(spec); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'yieldone', + 'params': { + placementId: '44082' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }; + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when placementId not passed correctly', () => { + bid.params.placementId = ''; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when require params are not passed', () => { + let bid = Object.assign({}, bid); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'yieldone', + 'params': { + placementId: '44082' + }, + 'adUnitCode': 'adunit-code1', + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }, + { + 'bidder': 'yieldone', + 'params': { + placementId: '44337' + }, + 'adUnitCode': 'adunit-code2', + 'sizes': [ + [300, 250] + ], + 'bidId': '382091349b149f"', + 'bidderRequestId': '"1f9c98192de251"', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + } + ]; + + const request = spec.buildRequests(bidRequests); + + it('sends bid request to our endpoint via GET', () => { + 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', () => { + expect(request[0].url).to.equal(ENDPOINT); + expect(request[1].url).to.equal(ENDPOINT); + }); + }); + + describe('interpretResponse', () => { + let bidRequest = [ + { + 'method': 'GET', + 'url': '//y.one.impact-ad.jp/h_bid', + 'data': { + 'v': 'hb1', + 'p': '44082', + 'w': '300', + 'h': '250', + 'cb': 12892917383, + 'r': 'http%3A%2F%2Flocalhost%3A9876%2F%3Fid%3D74552836', + 'uid': '23beaa6af6cdde', + 't': 'i' + } + } + ]; + + let serverResponse = { + body: { + 'adTag': '', + 'cpm': 0.0536616, + 'crid': '2494768', + 'statusMessage': 'Bid available', + 'uid': '23beaa6af6cdde', + 'width': 300, + 'height': 250 + } + }; + + it('should get the correct bid response', () => { + let expectedResponse = [{ + 'requestId': '23beaa6af6cdde', + 'cpm': 53.6616, + 'width': 300, + 'height': 250, + 'creativeId': '2494768', + 'dealId': '', + 'currency': 'JPY', + 'netRevenue': true, + 'ttl': 3000, + 'referrer': '', + 'ad': '' + }]; + let result = spec.interpretResponse(serverResponse, bidRequest[0]); + expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); + }); + + it('handles empty bid response', () => { + let response = { + body: { + 'uid': '2c0b634db95a01', + 'height': 0, + 'crid': '', + 'statusMessage': 'Bid returned empty or error response', + 'width': 0, + 'cpm': 0 + } + }; + let result = spec.interpretResponse(response, bidRequest[0]); + expect(result.length).to.equal(0); + }); + }); +}); From 5fe11053b6b61c0b7fde6d620658ac62eeccb37f Mon Sep 17 00:00:00 2001 From: Rich Loveland Date: Thu, 14 Dec 2017 10:36:46 -0500 Subject: [PATCH 0005/1594] Add user-facing docs reminder to PR template (#1956) --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 61eb327fd2c..9fdb04ba556 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -11,6 +11,7 @@ Thank you for your pull request. Please make sure this PR is scoped to one chang - [ ] Refactoring (no functional changes, no api changes) - [ ] Build related changes - [ ] CI related changes +- [ ] Does this change affect user-facing APIs or examples documented on http://prebid.org? - [ ] Other ## Description of change @@ -32,6 +33,9 @@ Be sure to test the integration with your adserver using the [Hello World](/inte - contact email of the adapter’s maintainer - [ ] official adapter submission +For any changes that affect user-facing APIs or example code documented on http://prebid.org, please provide: + +- A link to a PR on the docs repo at https://github.com/prebid/prebid.github.io/ ## Other information From 91bdce61cd829d6a461576be4feba2a24f947cfd Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 15 Dec 2017 11:14:52 -0700 Subject: [PATCH 0006/1594] allow non-mappable sizes to be passed and used in rubicon adapter (#1893) --- modules/rubiconBidAdapter.js | 50 +++++++++++---------- test/spec/modules/rubiconBidAdapter_spec.js | 24 ++++------ 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 48fe18677e0..76a9095be72 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -357,14 +357,13 @@ function parseSizes(bid) { } return size; } - return masSizeOrdering(Array.isArray(params.sizes) - ? params.sizes.map(size => (sizeMap[size] || '').split('x')) : bid.sizes - ); -} -export function masSizeOrdering(sizes) { - const MAS_SIZE_PRIORITY = [15, 2, 9]; + let sizes = Array.isArray(params.sizes) ? params.sizes : mapSizes(bid.sizes) + + return masSizeOrdering(sizes); +} +function mapSizes(sizes) { return utils.parseSizesInput(sizes) // map sizes while excluding non-matches .reduce((result, size) => { @@ -373,25 +372,30 @@ export function masSizeOrdering(sizes) { result.push(mappedSize); } return result; - }, []) - .sort((first, second) => { - // sort by MAS_SIZE_PRIORITY priority order - const firstPriority = MAS_SIZE_PRIORITY.indexOf(first); - const secondPriority = MAS_SIZE_PRIORITY.indexOf(second); - - if (firstPriority > -1 || secondPriority > -1) { - if (firstPriority === -1) { - return 1; - } - if (secondPriority === -1) { - return -1; - } - return firstPriority - secondPriority; + }, []); +} + +export function masSizeOrdering(sizes) { + const MAS_SIZE_PRIORITY = [15, 2, 9]; + + return sizes.sort((first, second) => { + // sort by MAS_SIZE_PRIORITY priority order + const firstPriority = MAS_SIZE_PRIORITY.indexOf(first); + const secondPriority = MAS_SIZE_PRIORITY.indexOf(second); + + if (firstPriority > -1 || secondPriority > -1) { + if (firstPriority === -1) { + return 1; + } + if (secondPriority === -1) { + return -1; } + return firstPriority - secondPriority; + } - // and finally ascending order - return first - second; - }); + // and finally ascending order + return first - second; + }); } var hasSynced = false; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 49c0dd9011e..8c6a244eb3c 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -98,27 +98,19 @@ describe('the rubicon adapter', () => { }); describe('MAS mapping / ordering', () => { - it('should not include values without a proper mapping', () => { - // two invalid sizes included: [42, 42], [1, 1] - let ordering = masSizeOrdering([[320, 50], [42, 42], [300, 250], [640, 480], [1, 1], [336, 280]]); - - expect(ordering).to.deep.equal([15, 16, 43, 65]); - }); - it('should sort values without any MAS priority sizes in regular ascending order', () => { - let ordering = masSizeOrdering([[320, 50], [640, 480], [336, 280], [200, 600]]); - + let ordering = masSizeOrdering([126, 43, 65, 16]); expect(ordering).to.deep.equal([16, 43, 65, 126]); }); it('should sort MAS priority sizes in the proper order w/ rest ascending', () => { - let ordering = masSizeOrdering([[320, 50], [160, 600], [640, 480], [300, 250], [336, 280], [200, 600]]); + let ordering = masSizeOrdering([43, 9, 65, 15, 16, 126]); expect(ordering).to.deep.equal([15, 9, 16, 43, 65, 126]); - ordering = masSizeOrdering([[320, 50], [300, 250], [160, 600], [640, 480], [336, 280], [200, 600], [728, 90]]); + ordering = masSizeOrdering([43, 15, 9, 65, 16, 126, 2]); expect(ordering).to.deep.equal([15, 2, 9, 16, 43, 65, 126]); - ordering = masSizeOrdering([[120, 600], [320, 50], [160, 600], [640, 480], [336, 280], [200, 600], [728, 90]]); + ordering = masSizeOrdering([8, 43, 9, 65, 16, 126, 2]); expect(ordering).to.deep.equal([2, 9, 8, 16, 43, 65, 126]); }); }); @@ -167,20 +159,20 @@ describe('the rubicon adapter', () => { }); }); - it('should use rubicon sizes if present', () => { + it('should use rubicon sizes if present (including non-mappable sizes)', () => { var sizesBidderRequest = clone(bidderRequest); - sizesBidderRequest.bids[0].params.sizes = [55, 57, 59]; + sizesBidderRequest.bids[0].params.sizes = [55, 57, 59, 801]; let [request] = spec.buildRequests(sizesBidderRequest.bids, sizesBidderRequest); let data = parseQuery(request.data); expect(data['size_id']).to.equal('55'); - expect(data['alt_size_ids']).to.equal('57,59'); + expect(data['alt_size_ids']).to.equal('57,59,801'); }); it('should not validate bid request if no valid sizes', () => { var sizesBidderRequest = clone(bidderRequest); - sizesBidderRequest.bids[0].sizes = [[620, 250], [300, 251]]; + sizesBidderRequest.bids[0].sizes = [[621, 250], [300, 251]]; let result = spec.isBidRequestValid(sizesBidderRequest.bids[0]); From bf3242b88ee7724d4d6bea944fed760b2bfd749a Mon Sep 17 00:00:00 2001 From: takuhou Date: Wed, 20 Dec 2017 00:02:36 +0900 Subject: [PATCH 0007/1594] Typo correction of YIELDONE md file (#1954) * Added YIELDONE Bid Adapter for Prebid.js 1.0 * Update yieldoneBidAdapter.md change placementId to 44082 * Changed to get size from bid.sizes * fix sizes array * Fix a typo --- modules/yieldoneBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/yieldoneBidAdapter.md b/modules/yieldoneBidAdapter.md index f1f48637927..b5d96f822b5 100644 --- a/modules/yieldoneBidAdapter.md +++ b/modules/yieldoneBidAdapter.md @@ -10,7 +10,7 @@ Maintainer: y1dev@platform-one.co.jp Connect to YIELDONE for bids. -THE YIELDONE adapter requires setup and approval from the Rubicon Project team. Please reach out to your account team or y1s@platform-one.co.jp for more information. +THE YIELDONE adapter requires setup and approval from the YIELDONE team. Please reach out to your account team or y1s@platform-one.co.jp for more information. # Test Parameters ``` From 6b21369ea6146c365d95c4231d4a9b7693cc1202 Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Tue, 19 Dec 2017 11:10:49 -0500 Subject: [PATCH 0008/1594] Serverbid bid adapter: update alias config (#1963) --- modules/serverbidBidAdapter.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index bca1f8a5ac0..e77d7f32a35 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -15,6 +15,9 @@ const CONFIG = { }, 'insticator': { 'BASE_URI': 'https://e.serverbid.com/api/v2' + }, + 'adsparc': { + 'BASE_URI': 'https://e.serverbid.com/api/v2' } }; From a936adbc9db94d22d504a0aaae82fc38512c11c2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 19 Dec 2017 11:56:38 -0500 Subject: [PATCH 0009/1594] use auctionId instead of requestId (#1968) --- modules/adomikAnalyticsAdapter.js | 2 +- test/spec/modules/adomikAnalyticsAdapter_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/adomikAnalyticsAdapter.js b/modules/adomikAnalyticsAdapter.js index 929a4d5deae..64e3ae14835 100644 --- a/modules/adomikAnalyticsAdapter.js +++ b/modules/adomikAnalyticsAdapter.js @@ -20,7 +20,7 @@ let adomikAdapter = Object.assign(adapter({}), track({ eventType, args }) { switch (eventType) { case auctionInit: - adomikAdapter.currentContext.id = args.requestId + adomikAdapter.currentContext.id = args.auctionId adomikAdapter.currentContext.timeout = args.timeout if (args.config.bidwonTimeout !== undefined && typeof args.config.bidwonTimeout === 'number') { bidwonTimeout = args.config.bidwonTimeout; diff --git a/test/spec/modules/adomikAnalyticsAdapter_spec.js b/test/spec/modules/adomikAnalyticsAdapter_spec.js index a3e0d214e5a..1907cfb14b8 100644 --- a/test/spec/modules/adomikAnalyticsAdapter_spec.js +++ b/test/spec/modules/adomikAnalyticsAdapter_spec.js @@ -33,7 +33,7 @@ describe('Adomik Prebid Analytic', function () { height: 10, statusMessage: 'Bid available', adId: '1234', - requestId: '', + auctionId: '', responseTimestamp: 1496410856397, requestTimestamp: 1496410856295, cpm: 0.1, @@ -58,7 +58,7 @@ describe('Adomik Prebid Analytic', function () { }); // Step 1: Send init auction event - events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions, requestId: 'test-test-test', timeout: 3000}); + events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions, auctionId: 'test-test-test', timeout: 3000}); expect(adomikAnalytics.currentContext).to.deep.equal({ uid: '123456', From 4bb4aaa8e91b85a4d612d158283aa12d77ef41f0 Mon Sep 17 00:00:00 2001 From: guillaume-sticky Date: Tue, 19 Dec 2017 18:02:14 +0100 Subject: [PATCH 0010/1594] Add freewheel ssp bidder adapter for prebid 1.0 (#1793) * add stickyadsTV bidder adapter * init unit test file * ad some unit tests * fix unit test on ad format with parameters * add some unit tests * add unit tests on getBid method * add some test cases in unit tests * minor fix on component id tag. * remove adapters-sticky.json test file * use top most accessible window instead of window.top * Pass in the bid request in the createBid call. * use top most accessible window instead of window.top * add unit tests * update unit tests * fix unit test. * fix CI build * add alias freewheel-ssp * update unit tests on bidderCode value * fix component id values and add unit tests * allws to use any outstream format. * fix ASLoader on futur outstream format versions * minor: fix code format. * update unit tests * minor fix code format * minor: add missing new line at eof * replace StickyAdsTVAdapter by freewheel ssp bd adapter (for prebid 1.0) * remove old stickyadstv unittest spec. * fix server response parsing if sent as object with 'body' field * use the vastXml field for video mediatype * add user sync pixel in freewheel ssp adapter * remove all console log calls (replaced using util helper) * remove useless bidderCode (automatically added by the bidderFactory) * Return the SYNC pixel to be added in the page by Prebid.js * remove instance level properties to enable concurrent bids with the same adapter instance. * fix the request apss through and corresponding unit tests * fix 'freeheelssp' typo --- modules/freewheelSSPBidAdapter.js | 314 ++++++++++++++++++ modules/freewheelSSPBidAdapter.md | 27 ++ .../modules/freewheelSSPBidAdapter_spec.js | 193 +++++++++++ 3 files changed, 534 insertions(+) create mode 100644 modules/freewheelSSPBidAdapter.js create mode 100644 modules/freewheelSSPBidAdapter.md create mode 100644 test/spec/modules/freewheelSSPBidAdapter_spec.js diff --git a/modules/freewheelSSPBidAdapter.js b/modules/freewheelSSPBidAdapter.js new file mode 100644 index 00000000000..7c696c746e6 --- /dev/null +++ b/modules/freewheelSSPBidAdapter.js @@ -0,0 +1,314 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +// import { config } from 'src/config'; + +const BIDDER_CODE = 'freewheel-ssp'; + +const PROTOCOL = getProtocol(); +const FREEWHEEL_ADSSETUP = PROTOCOL + '://ads.stickyadstv.com/www/delivery/swfIndex.php'; +const MUSTANG_URL = PROTOCOL + '://cdn.stickyadstv.com/mustang/mustang.min.js'; +const PRIMETIME_URL = PROTOCOL + '://cdn.stickyadstv.com/prime-time/'; +const USER_SYNC_URL = PROTOCOL + '://ads.stickyadstv.com/auto-user-sync'; + +function getProtocol() { + if (location.protocol && location.protocol.indexOf('https') === 0) { + return 'https'; + } else { + return 'http'; + } +} + +function isValidUrl(str) { + if (!str) { + return false; + } + + // regExp for url validation + var pattern = /^(https?|ftp|file):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/; + return pattern.test(str); +} + +function getBiggerSize(array) { + var result = [0, 0]; + for (var i = 0; i < array.length; i++) { + if (array[i][0] * array[i][1] > result[0] * result[1]) { + result = array[i]; + } + } + return result; +} + +/* +* read the pricing extension with this format: 1.0000 +* @return {object} pricing data in format: {currency: "EUR", price:"1.000"} +*/ +function getPricing(xmlNode) { + var pricingExtNode; + var princingData = {}; + + var extensions = xmlNode.querySelectorAll('Extension'); + extensions.forEach(function(node) { + if (node.getAttribute('type') === 'StickyPricing') { + pricingExtNode = node; + } + }); + + if (pricingExtNode) { + var priceNode = pricingExtNode.querySelector('Price'); + princingData = { + currency: priceNode.getAttribute('currency'), + price: priceNode.textContent || priceNode.innerText + }; + } else { + utils.logWarn('PREBID - ' + BIDDER_CODE + ': Can\'t get pricing data. Is price awareness enabled?'); + } + + return princingData; +} + +function getCreativeId(xmlNode) { + var creaId = ''; + var adNodes = xmlNode.querySelectorAll('Ad'); + + adNodes.forEach(function(el) { + creaId += '[' + el.getAttribute('id') + ']'; + }); + + return creaId; +} + +/** +* returns the top most accessible window +*/ +function getTopMostWindow() { + var res = window; + + try { + while (top !== res) { + if (res.parent.location.href.length) { res = res.parent; } + } + } catch (e) {} + + return res; +} + +function getComponentId(inputFormat) { + var component = 'mustang'; // default component id + + if (inputFormat && inputFormat !== 'inbanner') { + // format identifiers are equals to their component ids. + component = inputFormat; + } + + return component; +} + +function getAPIName(componentId) { + componentId = componentId || ''; + + // remove dash in componentId to get API name + return componentId.replace('-', ''); +} + +function formatAdHTML(bid, size) { + var integrationType = bid.params.format; + + var divHtml = '
'; + + var script = ''; + var libUrl = ''; + if (integrationType && integrationType !== 'inbanner') { + libUrl = PRIMETIME_URL + getComponentId(bid.params.format) + '.min.js'; + script = getOutstreamScript(bid, size); + } else { + libUrl = MUSTANG_URL; + script = getInBannerScript(bid, size); + } + + return divHtml + + ''; +} + +var getInBannerScript = function(bid, size) { + return 'var config = {' + + ' preloadedVast:vast,' + + ' autoPlay:true' + + ' };' + + ' var ad = new window.com.stickyadstv.vpaid.Ad(document.getElementById("freewheelssp_prebid_target"),config);' + + ' (new window.com.stickyadstv.tools.ASLoader(' + bid.params.zoneId + ', \'' + getComponentId(bid.params.format) + '\')).registerEvents(ad);' + + ' ad.initAd(' + size[0] + ',' + size[1] + ',"",0,"","");'; +}; + +var getOutstreamScript = function(bid) { + var placementCode = bid.adUnitCode; + + var config = bid.params; + + // default placement if no placement is set + if (!config.hasOwnProperty('domId') && !config.hasOwnProperty('auto') && !config.hasOwnProperty('p') && !config.hasOwnProperty('article')) { + config.domId = placementCode; + } + + var script = 'var config = {' + + ' preloadedVast:vast,' + + ' ASLoader:new window.com.stickyadstv.tools.ASLoader(' + bid.params.zoneId + ', \'' + getComponentId(bid.params.format) + '\')'; + + for (var key in config) { + // dont' send format parameter + // neither zone nor vastUrlParams value as Vast is already loaded + if (config.hasOwnProperty(key) && key !== 'format' && key !== 'zone' && key !== 'zoneId' && key !== 'vastUrlParams') { + script += ',' + key + ':"' + config[key] + '"'; + } + } + script += '};' + + + 'window.com.stickyadstv.' + getAPIName(bid.params.format) + '.start(config);'; + + return script; +}; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['video'], + aliases: ['stickyadstv'], // former name for freewheel-ssp + /** + * 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 !!(bid.params.zoneId); + }, + + /** + * 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) { + // var currency = config.getConfig(currency); + + var currentBidRequest = bidRequests[0]; + if (bidRequests.length > 1) { + utils.logMessage('Prebid.JS - freewheel bid adapter: only one ad unit is required.'); + } + + var requestParams = { + reqType: 'AdsSetup', + protocolVersion: '2.0', + zoneId: currentBidRequest.params.zoneId, + componentId: getComponentId(currentBidRequest.params.format) + }; + + var location = utils.getTopWindowUrl(); + if (isValidUrl(location)) { + requestParams.loc = location; + } + + var playerSize = getBiggerSize(currentBidRequest.sizes); + if (playerSize[0] > 0 || playerSize[1] > 0) { + requestParams.playerSize = playerSize[0] + 'x' + playerSize[1]; + } + + return { + method: 'GET', + url: FREEWHEEL_ADSSETUP, + data: requestParams, + bidRequest: currentBidRequest + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param {object} request: the built request object containing the initial bidRequest. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, request) { + var bidrequest = request.bidRequest; + var playerSize = getBiggerSize(bidrequest.sizes); + + if (typeof serverResponse == 'object' && typeof serverResponse.body == 'string') { + serverResponse = serverResponse.body; + } + + var xmlDoc; + try { + var parser = new DOMParser(); + xmlDoc = parser.parseFromString(serverResponse, 'application/xml'); + } catch (err) { + utils.logWarn('Prebid.js - ' + BIDDER_CODE + ' : ' + err); + return; + } + + const princingData = getPricing(xmlDoc); + const creativeId = getCreativeId(xmlDoc); + + const topWin = getTopMostWindow(); + if (!topWin.freewheelssp_cache) { + topWin.freewheelssp_cache = {}; + } + topWin.freewheelssp_cache[bidrequest.adUnitCode] = serverResponse; + + const bidResponses = []; + + if (princingData.price) { + const bidResponse = { + requestId: bidrequest.bidId, + cpm: princingData.price, + width: playerSize[0], + height: playerSize[1], + creativeId: creativeId, + currency: princingData.currency, + netRevenue: true, + ttl: 360 + }; + + var mediaTypes = bidrequest.mediaTypes || {}; + if (mediaTypes.video) { + // bidResponse.vastXml = serverResponse; + bidResponse.mediaType = 'video'; + + var blob = new Blob([serverResponse], {type: 'application/xml'}); + bidResponse.vastUrl = window.URL.createObjectURL(blob); + } else { + bidResponse.ad = formatAdHTML(bidrequest, playerSize); + } + + bidResponses.push(bidResponse); + } + + return bidResponses; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: USER_SYNC_URL + }]; + } + } +} +registerBidder(spec); diff --git a/modules/freewheelSSPBidAdapter.md b/modules/freewheelSSPBidAdapter.md new file mode 100644 index 00000000000..ba7915c87e1 --- /dev/null +++ b/modules/freewheelSSPBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +Module Name: Freewheel SSP Bidder Adapter +Module Type: Bidder Adapter +Maintainer: clientsidesdk@freewheel.tv + +# Description + +Module that connects to Freewheel ssp's demand sources + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "freewheel-ssp", + params: { + zoneId : '277225' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/freewheelSSPBidAdapter_spec.js b/test/spec/modules/freewheelSSPBidAdapter_spec.js new file mode 100644 index 00000000000..107259e9805 --- /dev/null +++ b/test/spec/modules/freewheelSSPBidAdapter_spec.js @@ -0,0 +1,193 @@ +import { expect } from 'chai'; +import { spec } from 'modules/freewheelSSPBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; + +describe('freewheelSSP BidAdapter Test', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 zone id' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should add parameters to the tag', () => { + const request = spec.buildRequests(bidRequests); + console.log(request.data); + + const payload = request.data; + expect(payload.reqType).to.equal('AdsSetup'); + expect(payload.protocolVersion).to.equal('2.0'); + expect(payload.zoneId).to.equal('277225'); + expect(payload.componentId).to.equal('mustang'); + expect(payload.playerSize).to.equal('300x600'); + }); + + it('sends bid request to ENDPOINT via GET', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.contain(ENDPOINT); + expect(request.method).to.equal('GET'); + }); + }) + + describe('interpretResponse', () => { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + let formattedBidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225', + 'format': 'floorad' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[600, 250], [300, 600]], + 'bidId': '30b3other1c1838de1e', + 'bidderRequestId': '22edbae273other3bf6', + 'auctionId': '1d1a03079test0a475', + }, + { + 'bidder': 'stickyadstv', + 'params': { + 'zoneId': '277225', + 'format': 'test' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 600]], + 'bidId': '2', + 'bidderRequestId': '3', + 'auctionId': '4', + } + ]; + + let response = '' + + '' + + ' ' + + ' Adswizz' + + ' ' + + ' ' + + ' ' + + ' 00:00:09' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 0.2000' + + ' ' + + ' ' + + ' ' + + ''; + + let ad = '
'; + let formattedAd = '
'; + + it('should get correct bid response', () => { + var request = spec.buildRequests(bidRequests); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: ad + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('should get correct bid response with formated ad', () => { + var request = spec.buildRequests(formattedBidRequests); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: formattedAd + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', () => { + var reqest = spec.buildRequests(formattedBidRequests); + let response = ''; + + let result = spec.interpretResponse(response, reqest); + expect(result.length).to.equal(0); + }); + }); +}); From b7385847cbc76e3a2b3b7e104667b86e8c3130a7 Mon Sep 17 00:00:00 2001 From: optimatic58 <33465594+optimatic58@users.noreply.github.com> Date: Tue, 19 Dec 2017 13:13:20 -0500 Subject: [PATCH 0011/1594] + fixed endpoint request data property names - width to w and height to h (#1955) + updated unit test for the adapter to comply with the property name changes --- modules/optimaticBidAdapter.js | 4 ++-- test/spec/modules/optimaticBidAdapter_spec.js | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/optimaticBidAdapter.js b/modules/optimaticBidAdapter.js index 3130977ea76..2408eb8cefe 100644 --- a/modules/optimaticBidAdapter.js +++ b/modules/optimaticBidAdapter.js @@ -75,8 +75,8 @@ function getData (bid) { bidfloor: bid.params.bidfloor, video: { mimes: ['video/mp4', 'video/ogg', 'video/webm', 'video/x-flv', 'application/javascript', 'application/x-shockwave-flash'], - width: size.width, - height: size.height + w: size.width, + h: size.height } }], site: { diff --git a/test/spec/modules/optimaticBidAdapter_spec.js b/test/spec/modules/optimaticBidAdapter_spec.js index cbea5598627..890c0b78613 100644 --- a/test/spec/modules/optimaticBidAdapter_spec.js +++ b/test/spec/modules/optimaticBidAdapter_spec.js @@ -66,8 +66,8 @@ describe('OptimaticBidAdapter', () => { const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; const [ width, height ] = bidRequest.sizes; - expect(data.imp[0].video.width).to.equal(width); - expect(data.imp[0].video.height).to.equal(height); + expect(data.imp[0].video.w).to.equal(width); + expect(data.imp[0].video.h).to.equal(height); expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); }); @@ -77,8 +77,8 @@ describe('OptimaticBidAdapter', () => { bidRequest.sizes = [[ width, height ]]; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video.width).to.equal(width); - expect(data.imp[0].video.height).to.equal(height); + expect(data.imp[0].video.w).to.equal(width); + expect(data.imp[0].video.h).to.equal(height); }); it('must parse bid size from a string', () => { @@ -87,16 +87,16 @@ describe('OptimaticBidAdapter', () => { bidRequest.sizes = `${width}x${height}`; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video.width).to.equal(width); - expect(data.imp[0].video.height).to.equal(height); + expect(data.imp[0].video.w).to.equal(width); + expect(data.imp[0].video.h).to.equal(height); }); it('must handle an empty bid size', () => { bidRequest.sizes = []; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video.width).to.equal(undefined); - expect(data.imp[0].video.height).to.equal(undefined); + expect(data.imp[0].video.w).to.equal(undefined); + expect(data.imp[0].video.h).to.equal(undefined); }); }); From f1f18e131946af0214a04e496142ca6d3076a27c Mon Sep 17 00:00:00 2001 From: Pratik Thakkar Date: Tue, 19 Dec 2017 23:58:18 +0530 Subject: [PATCH 0012/1594] Added iQM Bid Adapter for Prebid.js 1.0 (#1880) * Added iQM Bid Adapter for Prebid.js 1.0 * Modified URL from http to https * Removed geo function which was fetching user location. --- modules/iqmBidAdapter.js | 137 +++++++++++++++ modules/iqmBidAdapter.md | 41 +++++ test/spec/modules/iqmBidAdapter_spec.js | 219 ++++++++++++++++++++++++ 3 files changed, 397 insertions(+) create mode 100644 modules/iqmBidAdapter.js create mode 100644 modules/iqmBidAdapter.md create mode 100644 test/spec/modules/iqmBidAdapter_spec.js diff --git a/modules/iqmBidAdapter.js b/modules/iqmBidAdapter.js new file mode 100644 index 00000000000..6263caeeba0 --- /dev/null +++ b/modules/iqmBidAdapter.js @@ -0,0 +1,137 @@ +import * as utils from 'src/utils'; +// import {config} from 'src/config'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'iqm'; +const ENDPOINT_URL = 'https://pbd.bids.iqm.com'; +const VERSION = 'v.1.0.0'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['iqm'], // 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 !!(bid && bid.params && bid.params.publisherId && bid.params.placementId && bid.params.tagId); + }, + /** + * Make a server request from the list of BidRequests. + * + * @return ServerRequest Info describing the request to the server. + * @param validBidRequests - an array of bids + */ + buildRequests: function(validBidRequests) { + let requestId = ''; + let siteId = ''; + let device = getDevice(); + return validBidRequests.map(bid => { + requestId = bid.requestId; + let bidfloor = utils.getBidIdParameter('bidfloor', bid.params); + siteId = utils.getBidIdParameter('tagId', bid.params); + const imp = { + id: bid.bidId, + secure: 1, + bidfloor: bidfloor || 0, + displaymanager: 'Prebid.js', + displaymanagerver: VERSION, + mediatype: 'banner' + }; + imp.banner = getSize(bid.sizes); + let data = { + id: requestId, + publisherId: utils.getBidIdParameter('publisherId', bid.params), + tagId: utils.getBidIdParameter('tagId', bid.params), + placementId: utils.getBidIdParameter('placementId', bid.params), + device: device, + site: { + id: siteId, + page: utils.getTopWindowLocation().href, + domain: utils.getTopWindowLocation().host + }, + imp: imp + }; + return { + method: 'POST', + url: ENDPOINT_URL, + data: data + }; + }); + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param bidRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidRequest) { + // const serverBody = serverResponse.body; + // const headerValue = serverResponse.headers.get('some-response-header') + const bidResponses = []; + serverResponse = serverResponse.body; + if (serverResponse && utils.isArray(serverResponse.seatbid)) { + utils._each(serverResponse.seatbid, function(bidList) { + utils._each(bidList.bid, function(bid) { + const responseCPM = parseFloat(bid.price); + if (responseCPM > 0.0 && bid.impid) { + // const responseNurl = bid.nurl || ''; + const bidResponse = { + requestId: bid.impid, + currency: serverResponse.cur || 'USD', + cpm: responseCPM, + netRevenue: true, + creativeId: bid.crid || '', + ad: bid.adm || '', + width: bid.w || bidRequest.data.imp.banner.w, + height: bid.h || bidRequest.data.imp.banner.h, + ttl: bid.ttl || 300 + }; + + bidResponses.push(bidResponse); + } + }) + }); + } + return bidResponses; + } +}; + +let getDevice = function () { + const language = navigator.language ? 'language' : 'userLanguage'; + return { + h: screen.height, + w: screen.width, + dnt: _getDNT() ? 1 : 0, + language: navigator[language].split('-')[0], + make: navigator.vendor ? navigator.vendor : '', + ua: navigator.userAgent, + devicetype: _isMobile() ? 1 : _isConnectedTV() ? 3 : 2 + }; +}; + +let _getDNT = function () { + return navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNotTrack === '1' || navigator.doNotTrack === 'yes'; +}; + +let getSize = function (sizes) { + let sizeMap; + if (sizes.length === 2 && typeof sizes[0] === 'number' && typeof sizes[1] === 'number') { + sizeMap = {w: sizes[0], h: sizes[1]}; + } else { + sizeMap = {w: sizes[0][0], h: sizes[0][1]}; + } + return sizeMap; +}; + +function _isMobile() { + return (/(ios|ipod|ipad|iphone|android)/i).test(global.navigator.userAgent); +} + +function _isConnectedTV() { + return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(global.navigator.userAgent); +} + +registerBidder(spec); diff --git a/modules/iqmBidAdapter.md b/modules/iqmBidAdapter.md new file mode 100644 index 00000000000..d6d1b4d037d --- /dev/null +++ b/modules/iqmBidAdapter.md @@ -0,0 +1,41 @@ +#Overview + +``` +Module Name: iQM Bidder Adapter +Module Type: Bidder Adapter +Maintainer: hbteam@iqm.com +``` + +# Parameters + +| Name | Scope | Description | Example | +| :------------ | :------- | :------------------------ | :------------------- | +| `publisherId` | required | The Publisher ID from iQM | "df5fd732-c5f3-11e7" | +| `tagId` | required | The tag ID from iQM | "1c5c9ec2-c5f4-11e7" | +| `placementId` | required | The Placement ID from iQM | "50cc36fe-c5f4-11e7" | +| `bidfloor` | optional | Bid Floor | 0.50 | + +# Description + +Module that connects to iQM demand sources + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div1', + sizes: [[320, 50]], // display 320x50 + bids: [ + { + bidder: 'iqm', + params: { + publisherId: 'df5fd732-c5f3-11e7-abc4-cec278b6b50a', + tagId: '1c5c9ec2-c5f4-11e7-abc4-cec278b6b50a', + placementId: '50cc36fe-c5f4-11e7-abc4-cec278b6b50a', + bidfloor: 0.50, + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/iqmBidAdapter_spec.js b/test/spec/modules/iqmBidAdapter_spec.js new file mode 100644 index 00000000000..8958a4dfc45 --- /dev/null +++ b/test/spec/modules/iqmBidAdapter_spec.js @@ -0,0 +1,219 @@ +import {expect} from 'chai'; +import {spec} from 'modules/iqmBidAdapter' +import * as utils from 'src/utils'; + +describe('iqmBidAdapter', () => { + const ENDPOINT_URL = 'https://pbd.bids.iqm.com'; + const bidRequests = [{ + bidder: 'iqm', + params: { + position: 1, + tagId: 'tagId-1', + placementId: 'placementId-1', + pubId: 'pubId-1', + secure: true, + bidfloor: 0.5 + }, + placementCode: 'pcode000', + transactionId: 'tx000', + sizes: [[300, 250]], + bidId: 'bid000', + bidderRequestId: '117d765b87bed38', + requestId: 'req000' + }]; + + const bidResponses = { + body: { + id: 'req000', + seatbid: [{ + bid: [{ + nurl: 'nurl', + adm: '', + crid: 'cr-65981', + impid: 'bid000', + price: 0.99, + w: 300, + h: 250, + adomain: ['https://example.com'], + id: 'bid000', + ttl: 300 + }] + }] + }, + headers: {}}; + + const bidResponseEmptySeat = { + body: { + id: 'req000', + seatbid: [] + }, + headers: {} + }; + + const bidResponseEmptyBid = { + body: { + id: 'req000', + seatbid: [{ + bid: [] + }] + }, + headers: {} + }; + + const bidResponseNoImpId = { + body: { + id: 'req000', + seatbid: [{ + bid: [{ + nurl: 'nurl', + adm: '', + crid: 'cr-65981', + price: 0.99, + w: 300, + h: 250, + adomain: ['https://example.com'], + id: 'bid000', + ttl: 300 + }] + }] + }, + headers: {} + }; + + describe('Request verification', () => { + it('basic property verification', () => { + expect(spec.code).to.equal('iqm'); + expect(spec.aliases).to.be.an('array'); + // expect(spec.aliases).to.be.ofSize(1); + expect(spec.aliases).to.have.lengthOf(1); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'iqm', + 'params': { + 'placementId': 'placementId', + 'tagId': 'tagId', + 'publisherId': 'pubId' + }, + 'adUnitCode': 'ad-unit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }; + + it('should return false for empty object', () => { + expect(spec.isBidRequestValid({})).to.equal(false); + }); + + it('should return false for request without param', () => { + let bid = Object.assign({}, bid); + delete bid.params; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false for invalid params', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 'placementId' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true for proper request', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + + describe('buildRequests', () => { + it('sends every bid request to ENDPOINT_URL via POST method', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].method).to.equal('POST'); + expect(requests[0].url).to.equal(ENDPOINT_URL); + // expect(requests[1].method).to.equal('POST'); + // expect(requests[1].url).to.equal(ENDPOINT_URL); + }); + + it('should send request data with every request', () => { + const requests = spec.buildRequests(bidRequests); + const data = requests[0].data; + expect(data.id).to.equal(bidRequests[0].requestId); + + expect(data.imp.id).to.equal(bidRequests[0].bidId); + expect(data.imp.bidfloor).to.equal(bidRequests[0].params.bidfloor); + expect(data.imp.secure).to.equal(1); + expect(data.imp.displaymanager).to.equal('Prebid.js'); + expect(data.imp.displaymanagerver).to.equal('v.1.0.0'); + expect(data.imp.mediatype).to.equal('banner'); + expect(data.imp.banner).to.deep.equal({ + w: 300, + h: 250 + }); + expect(data.publisherId).to.equal(utils.getBidIdParameter('publisherId', bidRequests[0].params)); + expect(data.tagId).to.equal(utils.getBidIdParameter('tagId', bidRequests[0].params)); + expect(data.placementId).to.equal(utils.getBidIdParameter('placementId', bidRequests[0].params)); + expect(data.device.w).to.equal(screen.width); + expect(data.device.h).to.equal(screen.height); + expect(data.device.make).to.equal(navigator.vendor ? navigator.vendor : ''); + expect(data.device.ua).to.equal(navigator.userAgent); + expect(data.device.dnt).to.equal(navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNotTrack === '1' || navigator.doNotTrack === 'yes' ? 1 : 0); + expect(data.site).to.deep.equal({ + id: utils.getBidIdParameter('tagId', bidRequests[0].params), + page: utils.getTopWindowLocation().href, + domain: utils.getTopWindowLocation().host + }); + + expect(data.device.ua).to.equal(navigator.userAgent); + expect(data.device.h).to.equal(screen.height); + expect(data.device.w).to.equal(screen.width); + + expect(data.site.id).to.equal(bidRequests[0].params.tagId); + expect(data.site.page).to.equal(utils.getTopWindowLocation().href); + expect(data.site.domain).to.equal(utils.getTopWindowLocation().host); + }); + }); + + describe('interpretResponse', () => { + it('should handle no bid response', () => { + const response = spec.interpretResponse({ body: null }, { bidRequests }); + expect(response.length).to.equal(0); + }); + + it('should have at least one Seat Object', () => { + const request = spec.buildRequests(bidRequests); + const response = spec.interpretResponse(bidResponseEmptySeat, request); + expect(response.length).to.equal(0); + }); + + it('should have at least one Bid Object', () => { + const request = spec.buildRequests(bidRequests); + const response = spec.interpretResponse(bidResponseEmptyBid, request); + expect(response.length).to.equal(0); + }); + + it('should have impId in Bid Object', () => { + const request = spec.buildRequests(bidRequests); + const response = spec.interpretResponse(bidResponseNoImpId, request); + expect(response.length).to.equal(0); + }); + + it('should handle valid response', () => { + const request = spec.buildRequests(bidRequests); + const response = spec.interpretResponse(bidResponses, request); + expect(response).to.be.an('array').to.have.lengthOf(1); + + let bid = response[0]; + expect(bid).to.have.property('requestId', 'bid000'); + expect(bid).to.have.property('currency', 'USD'); + expect(bid).to.have.property('cpm', 0.99); + expect(bid).to.have.property('creativeId', 'cr-65981'); + expect(bid).to.have.property('width', 300); + expect(bid).to.have.property('height', 250); + expect(bid).to.have.property('ttl', 300); + expect(bid).to.have.property('ad', ''); + }); + }); + }); +}); From 437cb05946b237a810bafdee2b15a9ebaecc6d88 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 19 Dec 2017 11:47:45 -0800 Subject: [PATCH 0013/1594] Remove stray console.log (#1975) --- test/spec/modules/freewheelSSPBidAdapter_spec.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/spec/modules/freewheelSSPBidAdapter_spec.js b/test/spec/modules/freewheelSSPBidAdapter_spec.js index 107259e9805..33bd647efaa 100644 --- a/test/spec/modules/freewheelSSPBidAdapter_spec.js +++ b/test/spec/modules/freewheelSSPBidAdapter_spec.js @@ -57,8 +57,6 @@ describe('freewheelSSP BidAdapter Test', () => { it('should add parameters to the tag', () => { const request = spec.buildRequests(bidRequests); - console.log(request.data); - const payload = request.data; expect(payload.reqType).to.equal('AdsSetup'); expect(payload.protocolVersion).to.equal('2.0'); From d4e1e9853f0c02e8fd83d05476ab2688b1156315 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 19 Dec 2017 14:52:14 -0500 Subject: [PATCH 0014/1594] Remove duplicate request id and fix empty response from getHighesCpmBids, getAdserverTargeting (#1970) * Removed requestId and added auctionId * Updated module fixtures to use auctionId and not requestId * remove request id from external bid object and fix bug for empty result in public api * use auctionId instead of requestId * fixed lint errors --- modules/conversantBidAdapter.js | 2 +- modules/mobfoxBidAdapter.js | 2 +- src/auction.js | 1 - src/prebid.js | 23 +++-- src/targeting.js | 26 ++--- src/utils.js | 23 ++++- test/fixtures/fixtures.js | 98 +++++++++---------- test/fixtures/video/bidRequest.json | 4 +- test/fixtures/video/vastPayloadResponse.json | 2 +- test/fixtures/video/vastUrlResponse.json | 2 +- test/spec/modules/33acrossBidAdapter_spec.js | 2 +- test/spec/modules/adbutlerBidAdapter_spec.js | 4 +- .../adkernelAdnAnalyticsAdapter_spec.js | 6 +- .../modules/adxcgAnalyticsAdapter_spec.js | 2 +- test/spec/modules/aolBidAdapter_spec.js | 4 +- .../spec/modules/conversantBidAdapter_spec.js | 8 +- test/spec/modules/fidelityBidAdapter_spec.js | 4 +- .../modules/huddledmassesBidAdapter_spec.js | 2 +- test/spec/modules/komoonaBidAdapter_spec.js | 4 +- test/spec/modules/mobfoxBidAdapter_spec.js | 23 +---- .../modules/nanointeractiveBidAdapter_spec.js | 2 +- test/spec/modules/quantcastBidAdapter_spec.js | 4 +- test/spec/modules/readpeakBidAdapter_spec.js | 3 +- test/spec/modules/rtbdemandBidAdapter_spec.js | 6 +- test/spec/modules/rubiconBidAdapter_spec.js | 4 +- test/spec/modules/serverbidBidAdapter_spec.js | 8 +- .../modules/underdogmediaBidAdapter_spec.js | 6 +- test/spec/modules/undertoneBidAdapter_spec.js | 8 +- test/spec/unit/core/adapterManager_spec.js | 26 ++--- test/spec/unit/core/bidderFactory_spec.js | 12 +-- test/spec/unit/pbjs_api_spec.js | 2 +- 31 files changed, 162 insertions(+), 161 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index ad0dfc7bcf4..1f6c4f27b77 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -60,7 +60,7 @@ export const spec = { const secure = isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0); siteId = utils.getBidIdParameter('site_id', bid.params); - requestId = bid.requestId; + requestId = bid.auctionId; const format = convertSizes(bid.sizes); diff --git a/modules/mobfoxBidAdapter.js b/modules/mobfoxBidAdapter.js index ff55d330112..3620d8d30e7 100644 --- a/modules/mobfoxBidAdapter.js +++ b/modules/mobfoxBidAdapter.js @@ -9,7 +9,7 @@ export const spec = { code: BIDDER_CODE, aliases: ['mf'], // short code isBidRequestValid: function (bid) { - return bid.params.s !== null && bid.params.s !== undefined && bid.requestId !== null && bid.requestId !== undefined; + return bid.params.s !== null && bid.params.s !== undefined; }, buildRequests: function (validBidRequests) { if (validBidRequests.length > 1) { diff --git a/src/auction.js b/src/auction.js index 82aaa88cf56..45d06c23f59 100644 --- a/src/auction.js +++ b/src/auction.js @@ -268,7 +268,6 @@ function getPreparedBidForAuction({adUnitCode, bid, bidRequests, auctionId}) { let bidObject = Object.assign({}, bid, { auctionId, - requestId: bidRequest.requestId, responseTimestamp: timestamp(), requestTimestamp: start, cpm: parseFloat(bid.cpm) || 0, diff --git a/src/prebid.js b/src/prebid.js index ffecabe05eb..de74f2c4d7b 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -1,7 +1,7 @@ /** @module pbjs */ import { getGlobal } from './prebidGlobal'; -import { flatten, uniques, isGptPubadsDefined, adUnitsFilter } from './utils'; +import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId } from './utils'; import { videoAdUnit, videoBidder, hasNonVideoBidder } from './video'; import { nativeAdUnit, nativeBidder, hasNonNativeBidder } from './native'; import { listenMessagesFromCreative } from './secureCreatives'; @@ -113,7 +113,7 @@ $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCode = function(adUnitCode) { $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargeting', arguments); - return targeting.getAllTargeting(adUnitCode); + return targeting.getAllTargeting(adUnitCode, auctionManager.getBidsReceived()); }; /** @@ -127,16 +127,17 @@ $$PREBID_GLOBAL$$.getBidResponses = function () { const responses = auctionManager.getBidsReceived() .filter(adUnitsFilter.bind(this, auctionManager.getAdUnitCodes())); - // find the last requested id to get responses for most recent auction only - const currentRequestId = responses && responses.length && responses[responses.length - 1].requestId; + // find the last auction id to get responses for most recent auction only + const currentAuctionId = responses && responses.length && responses[responses.length - 1].auctionId; - return responses.map(bid => bid.adUnitCode) + return responses + .map(bid => bid.adUnitCode) .filter(uniques).map(adUnitCode => responses - .filter(bid => bid.requestId === currentRequestId && bid.adUnitCode === adUnitCode)) + .filter(bid => bid.auctionId === currentAuctionId && bid.adUnitCode === adUnitCode)) .filter(bids => bids && bids[0] && bids[0].adUnitCode) .map(bids => { return { - [bids[0].adUnitCode]: { bids: bids } + [bids[0].adUnitCode]: { bids: bids.map(removeRequestId) } }; }) .reduce((a, b) => Object.assign(a, b), {}); @@ -152,7 +153,7 @@ $$PREBID_GLOBAL$$.getBidResponses = function () { $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode = function (adUnitCode) { const bids = auctionManager.getBidsReceived().filter(bid => bid.adUnitCode === adUnitCode); return { - bids: bids + bids: bids.map(removeRequestId) }; }; @@ -528,7 +529,8 @@ $$PREBID_GLOBAL$$.aliasBidder = function (bidderCode, alias) { * @return {Array} A list of bids that have won their respective auctions. */ $$PREBID_GLOBAL$$.getAllWinningBids = function () { - return auctionManager.getAllWinningBids(); + return auctionManager.getAllWinningBids() + .map(removeRequestId); }; /** @@ -539,7 +541,8 @@ $$PREBID_GLOBAL$$.getAllWinningBids = function () { * @return {Array} array containing highest cpm bid object(s) */ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { - return targeting.getWinningBids(adUnitCode); + return targeting.getWinningBids(adUnitCode, auctionManager.getBidsReceived()) + .map(removeRequestId); }; /** diff --git a/src/targeting.js b/src/targeting.js index 2169af21b2b..54324265a21 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -54,14 +54,14 @@ export function newTargeting(auctionManager) { * @param {string=} adUnitCode * @return {Object.} targeting */ - targeting.getAllTargeting = function(adUnitCode) { + targeting.getAllTargeting = function(adUnitCode, bidsReceived = getBidsReceived()) { const adUnitCodes = getAdUnitCodes(adUnitCode); // Get targeting for the winning bid. Add targeting for any bids that have // `alwaysUseBid=true`. If sending all bids is enabled, add targeting for losing bids. - var targeting = getWinningBidTargeting(adUnitCodes) - .concat(getCustomBidTargeting(adUnitCodes)) - .concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes) : []); + var targeting = getWinningBidTargeting(adUnitCodes, bidsReceived) + .concat(getCustomBidTargeting(adUnitCodes, bidsReceived)) + .concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes, bidsReceived) : []); // store a reference of the targeting keys targeting.map(adUnitCode => { @@ -169,15 +169,15 @@ export function newTargeting(auctionManager) { * @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes * @return {[type]} [description] */ - targeting.getWinningBids = function(adUnitCode) { + targeting.getWinningBids = function(adUnitCode, bidsReceived = getBidsReceived()) { const adUnitCodes = getAdUnitCodes(adUnitCode); - return getBidsReceived() + return bidsReceived .filter(bid => includes(adUnitCodes, bid.adUnitCode)) .filter(bid => bid.cpm > 0) .map(bid => bid.adUnitCode) .filter(uniques) - .map(adUnitCode => getBidsReceived() + .map(adUnitCode => bidsReceived .filter(bid => bid.adUnitCode === adUnitCode ? bid : null) .reduce(getHighestCpm, getEmptyBid(adUnitCode))); }; @@ -207,8 +207,8 @@ export function newTargeting(auctionManager) { * @param {string[]} AdUnit code array * @return {targetingArray} winning bids targeting */ - function getWinningBidTargeting(adUnitCodes) { - let winners = targeting.getWinningBids(adUnitCodes); + function getWinningBidTargeting(adUnitCodes, bidsReceived) { + let winners = targeting.getWinningBids(adUnitCodes, bidsReceived); winners.forEach((winner) => { winner.status = BID_TARGETING_SET; }); @@ -302,8 +302,8 @@ export function newTargeting(auctionManager) { * @param {string[]} AdUnit code array * @return {targetingArray} bids with custom targeting defined in bidderSettings */ - function getCustomBidTargeting(adUnitCodes) { - return getBidsReceived() + function getCustomBidTargeting(adUnitCodes, bidsReceived) { + return bidsReceived .filter(bid => includes(adUnitCodes, bid.adUnitCode)) .map(bid => Object.assign({}, bid)) .reduce(mergeAdServerTargeting, []) @@ -316,11 +316,11 @@ export function newTargeting(auctionManager) { * @param {string[]} AdUnit code array * @return {targetingArray} all non-winning bids targeting */ - function getBidLandscapeTargeting(adUnitCodes) { + function getBidLandscapeTargeting(adUnitCodes, bidsReceived) { const standardKeys = CONSTANTS.TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); const bids = []; // bucket by adUnitcode - let buckets = groupBy(getBidsReceived(), 'adUnitCode'); + let buckets = groupBy(bidsReceived, 'adUnitCode'); // filter top bid for each bucket by bidder Object.keys(buckets).forEach(bucketKey => { let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); diff --git a/src/utils.js b/src/utils.js index d5657845492..19014049352 100644 --- a/src/utils.js +++ b/src/utils.js @@ -794,7 +794,7 @@ 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, requestId: null }; + }) || { start: null, auctionId: null }; } /** @@ -845,3 +845,24 @@ export function unsupportedBidderMessage(adUnit, unSupportedBidders) { ${plural} won't fetch demand. `; } + +/** + * Delete property from object + * @param {Object} object + * @param {string} prop + * @return {Object} object + */ +export function deletePropertyFromObject(object, prop) { + let result = Object.assign({}, object) + delete result[prop]; + return result +} + +/** + * Delete requestId from external bid object. + * @param {Object} bid + * @return {Object} bid + */ +export function removeRequestId(bid) { + return exports.deletePropertyFromObject(bid, 'requestId'); +} diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index 8dbbe265cca..b1d94426db0 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -4,7 +4,7 @@ export function getBidRequests() { return [ { 'bidderCode': 'appnexus', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', 'bids': [ { @@ -26,7 +26,7 @@ export function getBidRequests() { ], 'bidId': '392b5a6b05d648', 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897462, 'status': 1, 'transactionId': 'fsafsa' @@ -49,7 +49,7 @@ export function getBidRequests() { ], 'bidId': '4dccdc37746135', 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897463, 'status': 1, 'transactionId': 'fsafsa' @@ -59,7 +59,7 @@ export function getBidRequests() { }, { 'bidderCode': 'pubmatic', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '5e1525bae3eb11', 'bids': [ { @@ -81,7 +81,7 @@ export function getBidRequests() { ], 'bidId': '6d11aa2d5b3659', 'bidderRequestId': '5e1525bae3eb11', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'transactionId': 'fsafsa' } ], @@ -89,7 +89,7 @@ export function getBidRequests() { }, { 'bidderCode': 'rubicon', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '8778750ee15a77', 'bids': [ { @@ -130,7 +130,7 @@ export function getBidRequests() { ], 'bidId': '96aff279720d39', 'bidderRequestId': '8778750ee15a77', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'transactionId': 'fsafsa' } ], @@ -138,7 +138,7 @@ export function getBidRequests() { }, { 'bidderCode': 'triplelift', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '107f5e6e98dcf09', 'bids': [ { @@ -159,7 +159,7 @@ export function getBidRequests() { ], 'bidId': '1144e2f0de84363', 'bidderRequestId': '107f5e6e98dcf09', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897477, 'transactionId': 'fsafsa' } @@ -168,7 +168,7 @@ export function getBidRequests() { }, { 'bidderCode': 'brightcom', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '12eeded736650b4', 'bids': [ { @@ -189,7 +189,7 @@ export function getBidRequests() { ], 'bidId': '135e89c039705da', 'bidderRequestId': '12eeded736650b4', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'status': 1, 'transactionId': 'fsafsa' } @@ -198,7 +198,7 @@ export function getBidRequests() { }, { 'bidderCode': 'brealtime', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '167c4d79b615948', 'bids': [ { @@ -219,7 +219,7 @@ export function getBidRequests() { ], 'bidId': '17dd1d869bed44e', 'bidderRequestId': '167c4d79b615948', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897480, 'status': 1, 'transactionId': 'fsafsa' @@ -229,7 +229,7 @@ export function getBidRequests() { }, { 'bidderCode': 'pagescience', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '18bed198c172a69', 'bids': [ { @@ -250,7 +250,7 @@ export function getBidRequests() { ], 'bidId': '192c8c1df0f5d1d', 'bidderRequestId': '18bed198c172a69', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897481, 'status': 1, 'transactionId': 'fsafsa' @@ -260,7 +260,7 @@ export function getBidRequests() { }, { 'bidderCode': 'amazon', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '20d0d30333715a7', 'bids': [ { @@ -281,7 +281,7 @@ export function getBidRequests() { ], 'bidId': '21ae8131ec04f6e', 'bidderRequestId': '20d0d30333715a7', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'transactionId': 'fsafsa' } ], @@ -310,7 +310,7 @@ export function getBidResponses() { 'pbHg': '0.11', 'pbAg': '0.10', 'size': '0x0', - 'requestId': 123456, + 'auctionId': 123456, 'adserverTargeting': { 'hb_bidder': 'triplelift', 'hb_adid': '222bb26f9e8bd', @@ -342,7 +342,7 @@ export function getBidResponses() { 'pbAg': '10.00', 'size': '300x250', 'alwaysUseBid': true, - 'requestId': 123456, + 'auctionId': 123456, 'adserverTargeting': { 'hb_bidder': 'appnexus', 'hb_adid': '233bcbee889d46d', @@ -374,7 +374,7 @@ export function getBidResponses() { 'pbAg': '10.00', 'size': '728x90', 'alwaysUseBid': true, - 'requestId': 123456, + 'auctionId': 123456, 'adserverTargeting': { 'hb_bidder': 'appnexus', 'hb_adid': '24bd938435ec3fc', @@ -405,7 +405,7 @@ export function getBidResponses() { 'pbHg': '0.50', 'pbAg': '0.50', 'size': '300x250', - 'requestId': 123456, + 'auctionId': 123456, 'adserverTargeting': { 'hb_bidder': 'pagescience', 'hb_adid': '25bedd4813632d7', @@ -435,7 +435,7 @@ export function getBidResponses() { 'pbHg': '0.17', 'pbAg': '0.15', 'size': '300x250', - 'requestId': 654321, + 'auctionId': 654321, 'adserverTargeting': { 'hb_bidder': 'brightcom', 'hb_adid': '26e0795ab963896', @@ -466,7 +466,7 @@ export function getBidResponses() { 'pbHg': '0.50', 'pbAg': '0.50', 'size': '300x250', - 'requestId': 654321, + 'auctionId': 654321, 'adserverTargeting': { 'hb_bidder': 'brealtime', 'hb_adid': '275bd666f5a5a5d', @@ -498,7 +498,7 @@ export function getBidResponses() { 'pbHg': '5.93', 'pbAg': '5.90', 'size': '300x250', - 'requestId': 654321, + 'auctionId': 654321, 'adserverTargeting': { 'hb_bidder': 'pubmatic', 'hb_adid': '28f4039c636b6a7', @@ -528,7 +528,7 @@ export function getBidResponses() { 'pbHg': '2.74', 'pbAg': '2.70', 'size': '300x600', - 'requestId': 654321, + 'auctionId': 654321, 'adserverTargeting': { 'hb_bidder': 'rubicon', 'hb_adid': '29019e2ab586a5a', @@ -609,7 +609,7 @@ export function getAdUnits() { ], 'bidId': '3692954f816efc', 'bidderRequestId': '2b1a75d5e826c4', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'appnexus', @@ -630,7 +630,7 @@ export function getAdUnits() { ], 'bidId': '68136e1c47023d', 'bidderRequestId': '55e24a66bed717', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220995, 'status': 1 } @@ -667,7 +667,7 @@ export function getAdUnits() { ], 'bidId': '7e5d6af25ed188', 'bidderRequestId': '55e24a66bed717', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220996 }, { @@ -689,7 +689,7 @@ export function getAdUnits() { ], 'bidId': '4448d80ac1374e', 'bidderRequestId': '2b1a75d5e826c4', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'triplelift', @@ -709,7 +709,7 @@ export function getAdUnits() { ], 'bidId': '9514d586c52abf', 'bidderRequestId': '8c4f03b838d7ee', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220997 }, { @@ -732,7 +732,7 @@ export function getAdUnits() { ], 'bidId': '113079fed03f58c', 'bidderRequestId': '1048e0df882e965', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'rubicon', @@ -772,7 +772,7 @@ export function getAdUnits() { ], 'bidId': '13c2c2a79d155ea', 'bidderRequestId': '129e383ac549e5d', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'openx', @@ -793,7 +793,7 @@ export function getAdUnits() { ], 'bidId': '154f9cbf82df565', 'bidderRequestId': '1448569c2453b84', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'pubmatic', @@ -814,7 +814,7 @@ export function getAdUnits() { ], 'bidId': '17f8c3a8fb13308', 'bidderRequestId': '16095445eeb05e4', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'pagescience', @@ -834,7 +834,7 @@ export function getAdUnits() { ], 'bidId': '2074d5757675542', 'bidderRequestId': '19883380ef5453a', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510221014 }, { @@ -855,7 +855,7 @@ export function getAdUnits() { ], 'bidId': '222b6ad5a9b835d', 'bidderRequestId': '2163409fdf6f333', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510221015 }, { @@ -878,7 +878,7 @@ export function getAdUnits() { ], 'bidId': '2499961ab3f937a', 'bidderRequestId': '23b57a2de4ae50b', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'adform', @@ -900,7 +900,7 @@ export function getAdUnits() { ], 'bidId': '26605265bf5e9c5', 'bidderRequestId': '25a0902299c17d3', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'amazon', @@ -920,7 +920,7 @@ export function getAdUnits() { ], 'bidId': '2935d8f6764fe45', 'bidderRequestId': '28afa21ca9246c1', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'aol', @@ -941,7 +941,7 @@ export function getAdUnits() { ], 'bidId': '31d1489681dc539', 'bidderRequestId': '30bf32da9080fdd', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'sovrn', @@ -961,7 +961,7 @@ export function getAdUnits() { ], 'bidId': '33c1a8028d91563', 'bidderRequestId': '324bcb47cfcf034', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'pulsepoint', @@ -983,7 +983,7 @@ export function getAdUnits() { ], 'bidId': '379219f0506a26f', 'bidderRequestId': '360ec66bbb0719c', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' }, { 'bidder': 'brightcom', @@ -1003,7 +1003,7 @@ export function getAdUnits() { ], 'bidId': '395cfcf496e7d6d', 'bidderRequestId': '38a776c7f001ea', - 'requestId': '1ff753bd4ae5cb' + 'auctionId': '1ff753bd4ae5cb' } ] } @@ -1032,7 +1032,7 @@ export function getBidResponsesFromAPI() { 'pbHg': '0.17', 'pbAg': '0.15', 'size': '300x250', - 'requestId': 654321, + 'auctionId': 654321, 'adserverTargeting': { 'hb_bidder': 'brightcom', 'hb_adid': '26e0795ab963896', @@ -1063,7 +1063,7 @@ export function getBidResponsesFromAPI() { 'pbHg': '0.50', 'pbAg': '0.50', 'size': '300x250', - 'requestId': 654321, + 'auctionId': 654321, 'adserverTargeting': { 'hb_bidder': 'brealtime', 'hb_adid': '275bd666f5a5a5d', @@ -1095,7 +1095,7 @@ export function getBidResponsesFromAPI() { 'pbHg': '5.93', 'pbAg': '5.90', 'size': '300x250', - 'requestId': 654321, + 'auctionId': 654321, 'adserverTargeting': { 'hb_bidder': 'pubmatic', 'hb_adid': '28f4039c636b6a7', @@ -1125,7 +1125,7 @@ export function getBidResponsesFromAPI() { 'pbHg': '2.74', 'pbAg': '2.70', 'size': '300x600', - 'requestId': 654321, + 'auctionId': 654321, 'adserverTargeting': { 'hb_bidder': 'rubicon', 'hb_adid': '29019e2ab586a5a', @@ -1358,7 +1358,7 @@ export function getTargetingKeysBidLandscape() { export function getBidRequestedPayload() { return { 'bidderCode': 'adequant', - 'requestId': '150f361b202aa8', + 'auctionId': '150f361b202aa8', 'bidderRequestId': '2b193b7a6ff421', 'bids': [ { @@ -1388,7 +1388,7 @@ export function getBidRequestedPayload() { ], 'bidId': '39032dc5c7e834', 'bidderRequestId': '2b193b7a6ff421', - 'requestId': '150f361b202aa8' + 'auctionId': '150f361b202aa8' } ], 'start': 1465426155412 diff --git a/test/fixtures/video/bidRequest.json b/test/fixtures/video/bidRequest.json index f8306e27662..2a598c50183 100644 --- a/test/fixtures/video/bidRequest.json +++ b/test/fixtures/video/bidRequest.json @@ -16,11 +16,11 @@ "sizes": [640,480], "bidId": "392b5a6b05d648", "bidderRequestId": "2946b569352ef2", - "requestId": "6172477f-987f-4523-a967-fa6d7a434ddf", + "auctionId": "6172477f-987f-4523-a967-fa6d7a434ddf", "startTime": 1462918897462 } ], - "requestId": "6172477f-987f-4523-a967-fa6d7a434ddf", + "auctionId": "6172477f-987f-4523-a967-fa6d7a434ddf", "start": 1462918897460, "timeout": 5000 } diff --git a/test/fixtures/video/vastPayloadResponse.json b/test/fixtures/video/vastPayloadResponse.json index 7c388de41ed..2f72907817f 100644 --- a/test/fixtures/video/vastPayloadResponse.json +++ b/test/fixtures/video/vastPayloadResponse.json @@ -7,7 +7,7 @@ "cpm": 0.1, "height": 480, "mediaType": "video", - "requestId": "6172477f-987f-4523-a967-fa6d7a434ddf", + "auctionId": "6172477f-987f-4523-a967-fa6d7a434ddf", "vastXml": "", "width": 640 } diff --git a/test/fixtures/video/vastUrlResponse.json b/test/fixtures/video/vastUrlResponse.json index f3b023dc7bb..a842ed10a71 100644 --- a/test/fixtures/video/vastUrlResponse.json +++ b/test/fixtures/video/vastUrlResponse.json @@ -7,7 +7,7 @@ "cpm": 0.1, "height": 480, "mediaType": "video", - "requestId": "6172477f-987f-4523-a967-fa6d7a434ddf", + "auctionId": "6172477f-987f-4523-a967-fa6d7a434ddf", "vastUrl": "www.myVastUrl.com", "width": 640 } diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 4754e4d1fa5..0b2d65e7db9 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -28,7 +28,7 @@ describe('33acrossBidAdapter:', function () { productId: PRODUCT_ID }, adUnitCode: 'div-id', - requestId: 'r1', + auctionId: 'r1', sizes: [ [ 300, 250 ], [ 728, 90 ] diff --git a/test/spec/modules/adbutlerBidAdapter_spec.js b/test/spec/modules/adbutlerBidAdapter_spec.js index de40f72073b..a46039402e6 100644 --- a/test/spec/modules/adbutlerBidAdapter_spec.js +++ b/test/spec/modules/adbutlerBidAdapter_spec.js @@ -18,7 +18,7 @@ describe('AdButler adapter', () => { placementCode: '/19968336/header-bid-tag-1', sizes: [[300, 250], [300, 600]], bidId: '23acc48ad47af5', - requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', bidderRequestId: '1c56ad30b9b8ca8', transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' } @@ -63,7 +63,7 @@ describe('AdButler adapter', () => { zoneID: '86133', domain: 'servedbyadbutler.com.dan.test' }, - requestId: '10b327aa396609', + auctionId: '10b327aa396609', placementCode: '/123456/header-bid-tag-1' } ], diff --git a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js index 1a14660c6af..282bd62403a 100644 --- a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js +++ b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js @@ -147,7 +147,7 @@ describe('', () => { const REQUEST = { bidderCode: 'adapter', - requestId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', bidderRequestId: '1a6fc81528d0f6', bids: [{ bidder: 'adapter', @@ -157,7 +157,7 @@ describe('', () => { sizes: [[300, 250]], bidId: '208750227436c1', bidderRequestId: '1a6fc81528d0f6', - requestId: '5018eb39-f900-4370-b71e-3bb5b48d324f' + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' }], auctionStart: 1509369418387, timeout: 3000, @@ -173,7 +173,7 @@ describe('', () => { mediaType: 'banner', cpm: 0.015, ad: '', - requestId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', responseTimestamp: 1509369418832, requestTimestamp: 1509369418389, bidder: 'adapter', diff --git a/test/spec/modules/adxcgAnalyticsAdapter_spec.js b/test/spec/modules/adxcgAnalyticsAdapter_spec.js index 179b806da48..46b50214873 100644 --- a/test/spec/modules/adxcgAnalyticsAdapter_spec.js +++ b/test/spec/modules/adxcgAnalyticsAdapter_spec.js @@ -25,7 +25,7 @@ describe('adxcg analytics adapter', () => { publisherId: '42' }; let bidRequest = { - requestId: 'requestIdData' + auctionId: 'requestIdData' }; let bidResponse = { adId: 'adIdData', diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index efa595ecc64..d05f21a7be4 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -54,14 +54,14 @@ let getNexagePostBidParams = () => { let getDefaultBidRequest = () => { return { bidderCode: 'aol', - requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', bidderRequestId: '7101db09af0db2', start: new Date().getTime(), bids: [{ bidder: 'aol', bidId: '84ab500420319d', bidderRequestId: '7101db09af0db2', - requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', placementCode: 'foo', params: getMarketplaceBidParams() }] diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 1d62cba72c1..c99cad473a3 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -22,7 +22,7 @@ describe('Conversant adapter tests', function() { sizes: [[300, 250]], bidId: 'bid000', bidderRequestId: '117d765b87bed38', - requestId: 'req000' + auctionId: 'req000' }, { bidder: 'conversant', params: { @@ -34,7 +34,7 @@ describe('Conversant adapter tests', function() { sizes: [[468, 60]], bidId: 'bid001', bidderRequestId: '117d765b87bed38', - requestId: 'req000' + auctionId: 'req000' }, { bidder: 'conversant', params: { @@ -48,7 +48,7 @@ describe('Conversant adapter tests', function() { sizes: [[300, 600], [160, 600]], bidId: 'bid002', bidderRequestId: '117d765b87bed38', - requestId: 'req000' + auctionId: 'req000' }, { bidder: 'conversant', params: { @@ -68,7 +68,7 @@ describe('Conversant adapter tests', function() { sizes: [640, 480], bidId: 'bid003', bidderRequestId: '117d765b87bed38', - requestId: 'req000' + auctionId: 'req000' }]; const bidResponses = { diff --git a/test/spec/modules/fidelityBidAdapter_spec.js b/test/spec/modules/fidelityBidAdapter_spec.js index 036a34ee0b0..28ea18aacac 100644 --- a/test/spec/modules/fidelityBidAdapter_spec.js +++ b/test/spec/modules/fidelityBidAdapter_spec.js @@ -52,7 +52,7 @@ describe('FidelityAdapter', () => { describe('buildRequests', () => { let bidderRequest = { bidderCode: 'fidelity', - requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', bidderRequestId: '178e34bad3658f', bids: [ { @@ -66,7 +66,7 @@ describe('FidelityAdapter', () => { sizes: [[300, 250], [320, 50]], bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', - requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } ], diff --git a/test/spec/modules/huddledmassesBidAdapter_spec.js b/test/spec/modules/huddledmassesBidAdapter_spec.js index 71638cef96a..f98bc06d0da 100644 --- a/test/spec/modules/huddledmassesBidAdapter_spec.js +++ b/test/spec/modules/huddledmassesBidAdapter_spec.js @@ -10,7 +10,7 @@ describe('HuddledmassesAdapter', () => { placement_id: 0 }, placementCode: 'placementid_0', - requestId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', sizes: [[300, 250]], transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' }; diff --git a/test/spec/modules/komoonaBidAdapter_spec.js b/test/spec/modules/komoonaBidAdapter_spec.js index 82edba28d03..f7038505db3 100644 --- a/test/spec/modules/komoonaBidAdapter_spec.js +++ b/test/spec/modules/komoonaBidAdapter_spec.js @@ -16,7 +16,7 @@ describe('Komoona.com Adapter Tests', () => { ], bidId: '2faedf1095f815', bidderRequestId: '18065867f8ae39', - requestId: '529e1518-b872-45cf-807c-2d41dfa5bcd3' + auctionId: '529e1518-b872-45cf-807c-2d41dfa5bcd3' }, { bidder: 'komoona', @@ -32,7 +32,7 @@ describe('Komoona.com Adapter Tests', () => { ], bidId: '3c34e2367a3f59', bidderRequestId: '18065867f8ae39', - requestId: '529e1518-b872-45cf-807c-2d41dfa5bcd3' + auctionId: '529e1518-b872-45cf-807c-2d41dfa5bcd3' }]; const bidsResponse = { diff --git a/test/spec/modules/mobfoxBidAdapter_spec.js b/test/spec/modules/mobfoxBidAdapter_spec.js index 76bb95430fe..54a057991e3 100644 --- a/test/spec/modules/mobfoxBidAdapter_spec.js +++ b/test/spec/modules/mobfoxBidAdapter_spec.js @@ -14,7 +14,7 @@ describe('mobfox adapter tests', () => { imp_instl: 1 // optional - set to 1 if using interstitial otherwise delete or set to 0 }, placementCode: 'div-gpt-ad-1460505748561-0', - requestId: 'c241c810-18d9-4aa4-a62f-8c1980d8d36b', + auctionId: 'c241c810-18d9-4aa4-a62f-8c1980d8d36b', transactionId: '31f42cba-5920-4e47-adad-69c79d0d4fb4' }]; @@ -29,21 +29,7 @@ describe('mobfox adapter tests', () => { imp_instl: 1 // optional - set to 1 if using interstitial otherwise delete or set to 0 }, placementCode: 'div-gpt-ad-1460505748561-0', - requestId: 'c241c810-18d9-4aa4-a62f-8c1980d8d36b', - transactionId: '31f42cba-5920-4e47-adad-69c79d0d4fb4' - }]; - - let bidRequestInvalid2 = [{ - code: 'div-gpt-ad-1460505748561-0', - sizes: [[320, 480], [300, 250], [300, 600]], - // Replace this object to test a new Adapter! - bidder: 'mobfox', - bidId: '5t5t5t5', - params: { - s: '267d72ac3f77a3f447b32cf7ebf20673', // required - The hash of your inventory to identify which app is making the request, - imp_instl: 1 // optional - set to 1 if using interstitial otherwise delete or set to 0 - }, - placementCode: 'div-gpt-ad-1460505748561-0', + auctionId: 'c241c810-18d9-4aa4-a62f-8c1980d8d36b', transactionId: '31f42cba-5920-4e47-adad-69c79d0d4fb4' }]; @@ -56,11 +42,6 @@ describe('mobfox adapter tests', () => { let isValid = adapter.spec.isBidRequestValid(bidRequestInvalid1[0]); expect(isValid).to.equal(false); }); - - it('test valid MF request failed2', () => { - let isValid = adapter.spec.isBidRequestValid(bidRequestInvalid2[0]); - expect(isValid).to.equal(false); - }); }) describe('buildRequests', () => { diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index b9b9207aca2..01aa60351e8 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -32,7 +32,7 @@ describe('nanointeractive adapter tests', function () { sizes: SIZES, bidId: '24a1c9ec270973', bidderRequestId: '189135372acd55', - requestId: 'ac15bb68-4ef0-477f-93f4-de91c47f00a9' + auctionId: 'ac15bb68-4ef0-477f-93f4-de91c47f00a9' } } diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 14981f198b6..6fd5c3abdf9 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -17,7 +17,7 @@ describe('Quantcast adapter', () => { bidRequest = { bidder: 'quantcast', bidId: '2f7b179d443f14', - requestId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', + auctionId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', bidderRequestId: '1cc026909c24c8', placementCode: 'div-gpt-ad-1438287399331-0', params: { @@ -74,7 +74,7 @@ describe('Quantcast adapter', () => { const bidRequest = { bidder: 'quantcast', bidId: '2f7b179d443f14', - requestId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', + auctionId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', bidderRequestId: '1cc026909c24c8', placementCode: 'div-gpt-ad-1438287399331-0', params: { diff --git a/test/spec/modules/readpeakBidAdapter_spec.js b/test/spec/modules/readpeakBidAdapter_spec.js index 7356cd96a4e..18b52658c4b 100644 --- a/test/spec/modules/readpeakBidAdapter_spec.js +++ b/test/spec/modules/readpeakBidAdapter_spec.js @@ -21,10 +21,9 @@ describe('ReadPeakAdapter', () => { bidfloor: 5.00, publisherId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' }, - auctionId: '1d1a030790a475', bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', - requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } serverResponse = { diff --git a/test/spec/modules/rtbdemandBidAdapter_spec.js b/test/spec/modules/rtbdemandBidAdapter_spec.js index a00f1bf62da..20d3e410aee 100644 --- a/test/spec/modules/rtbdemandBidAdapter_spec.js +++ b/test/spec/modules/rtbdemandBidAdapter_spec.js @@ -52,7 +52,7 @@ describe('rtbdemandAdapter', () => { describe('buildRequests', () => { let bidderRequest = { bidderCode: 'rtbdemand', - requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', bidderRequestId: '178e34bad3658f', bids: [ { @@ -66,7 +66,7 @@ describe('rtbdemandAdapter', () => { sizes: [[300, 250], [320, 50]], bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', - requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' }, { @@ -80,7 +80,7 @@ describe('rtbdemandAdapter', () => { sizes: [[728, 90], [320, 50]], bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', - requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } ], diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 8c6a244eb3c..b02f01ecd93 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -57,7 +57,7 @@ describe('the rubicon adapter', () => { bidderRequest = { bidderCode: 'rubicon', - requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', bidderRequestId: '178e34bad3658f', bids: [ { @@ -83,7 +83,7 @@ describe('the rubicon adapter', () => { sizes: [[300, 250], [320, 50]], bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', - requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } ], diff --git a/test/spec/modules/serverbidBidAdapter_spec.js b/test/spec/modules/serverbidBidAdapter_spec.js index eeb8a6c517c..fb31f925c6e 100644 --- a/test/spec/modules/serverbidBidAdapter_spec.js +++ b/test/spec/modules/serverbidBidAdapter_spec.js @@ -8,7 +8,7 @@ const SMARTSYNC_CALLBACK = 'serverbidCallBids'; const REQUEST = { 'bidderCode': 'serverbid', - 'requestId': 'a4713c32-3762-4798-b342-4ab810ca770d', + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d', 'bidderRequestId': '109f2a181342a9', 'bidRequest': [{ 'bidder': 'serverbid', @@ -23,7 +23,7 @@ const REQUEST = { ], 'bidId': '2b0f82502298c9', 'bidderRequestId': '109f2a181342a9', - 'requestId': 'a4713c32-3762-4798-b342-4ab810ca770d' + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' }, { 'bidder': 'serverbid', @@ -38,7 +38,7 @@ const REQUEST = { ], 'bidId': '123', 'bidderRequestId': '109f2a181342a9', - 'requestId': 'a4713c32-3762-4798-b342-4ab810ca770d' + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' }], 'start': 1487883186070, 'auctionStart': 1487883186069, @@ -115,7 +115,7 @@ describe('Serverbid BidAdapter', () => { placementCode: 'header-bid-tag-1', sizes: [[300, 250], [300, 600]], bidId: '23acc48ad47af5', - requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', bidderRequestId: '1c56ad30b9b8ca8', transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' } diff --git a/test/spec/modules/underdogmediaBidAdapter_spec.js b/test/spec/modules/underdogmediaBidAdapter_spec.js index 1e7a80aaff8..5dc2a65399f 100644 --- a/test/spec/modules/underdogmediaBidAdapter_spec.js +++ b/test/spec/modules/underdogmediaBidAdapter_spec.js @@ -14,7 +14,7 @@ describe('UnderdogMedia adapter', () => { adUnitCode: '/19968336/header-bid-tag-1', sizes: [[300, 250], [300, 600], [728, 90], [160, 600], [320, 50]], bidId: '23acc48ad47af5', - requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', bidderRequestId: '1c56ad30b9b8ca8', transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' } @@ -68,7 +68,7 @@ describe('UnderdogMedia adapter', () => { params: { siteId: '12143' }, - requestId: '10b327aa396609', + auctionId: '10b327aa396609', adUnitCode: '/123456/header-bid-tag-1' } ]; @@ -86,7 +86,7 @@ describe('UnderdogMedia adapter', () => { params: { siteId: '12143' }, - requestId: '10b327aa396609', + auctionId: '10b327aa396609', adUnitCode: '/123456/header-bid-tag-1' } ]; diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index dab9cea98bf..d86a1dc5735 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -11,8 +11,7 @@ const validBidReq = { }, sizes: [[300, 250], [300, 600]], bidId: '263be71e91dd9d', - requestId: '9ad1fa8d-2297-4660-a018-b39945054746', - auctionId: '1d1a030790a475' + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', }; const invalidBidReq = { @@ -22,7 +21,7 @@ const invalidBidReq = { }, sizes: [[300, 250], [300, 600]], bidId: '263be71e91dd9d', - requestId: '9ad1fa8d-2297-4660-a018-b39945054746' + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' }; const bidReq = [{ @@ -33,8 +32,7 @@ const bidReq = [{ }, sizes: [[300, 250], [300, 600]], bidId: '263be71e91dd9d', - requestId: '9ad1fa8d-2297-4660-a018-b39945054746', - auctionId: '1d1a030790a475' + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' }]; const validBidRes = { diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 95a249263b5..1732716c6a4 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -45,7 +45,7 @@ describe('adapterManager tests', () => { it('should log an error if a bidder is used that does not exist', () => { let bidRequests = [{ 'bidderCode': 'appnexus', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', 'bids': [ @@ -59,7 +59,7 @@ describe('adapterManager tests', () => { 'sizes': [[728, 90], [970, 70]], 'bidId': '392b5a6b05d648', 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897462, 'status': 1, 'transactionId': 'fsafsa' @@ -73,7 +73,7 @@ describe('adapterManager tests', () => { 'sizes': [[300, 250], [300, 600]], 'bidId': '4dccdc37746135', 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897463, 'status': 1, 'transactionId': 'fsafsa' @@ -122,7 +122,7 @@ describe('adapterManager tests', () => { it('invokes callBids on the S2S adapter', () => { let bidRequests = [{ 'bidderCode': 'appnexus', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', 'src': 's2s', @@ -159,7 +159,7 @@ describe('adapterManager tests', () => { ], 'bidId': '68136e1c47023d', 'bidderRequestId': '55e24a66bed717', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220995, 'status': 1, 'bid_id': '378a8914450b334' @@ -197,7 +197,7 @@ describe('adapterManager tests', () => { ], 'bidId': '7e5d6af25ed188', 'bidderRequestId': '55e24a66bed717', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220996, 'bid_id': '387d9d9c32ca47c' } @@ -224,7 +224,7 @@ describe('adapterManager tests', () => { ], 'bidId': '392b5a6b05d648', 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897462, 'status': 1, 'transactionId': 'fsafsa' @@ -247,7 +247,7 @@ describe('adapterManager tests', () => { ], 'bidId': '4dccdc37746135', 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897463, 'status': 1, 'transactionId': 'fsafsa' @@ -285,7 +285,7 @@ describe('adapterManager tests', () => { let bidRequests = [{ 'bidderCode': 'appnexus', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', 'src': 's2s', @@ -322,7 +322,7 @@ describe('adapterManager tests', () => { ], 'bidId': '68136e1c47023d', 'bidderRequestId': '55e24a66bed717', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220995, 'status': 1, 'bid_id': '378a8914450b334' @@ -360,7 +360,7 @@ describe('adapterManager tests', () => { ], 'bidId': '7e5d6af25ed188', 'bidderRequestId': '55e24a66bed717', - 'requestId': '1ff753bd4ae5cb', + 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220996, 'bid_id': '387d9d9c32ca47c' } @@ -387,7 +387,7 @@ describe('adapterManager tests', () => { ], 'bidId': '392b5a6b05d648', 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897462, 'status': 1, 'transactionId': 'fsafsa' @@ -410,7 +410,7 @@ describe('adapterManager tests', () => { ], 'bidId': '4dccdc37746135', 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', + 'auctionId': '1863e370099523', 'startTime': 1462918897463, 'status': 1, 'transactionId': 'fsafsa' diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 7358017474d..cac3aa85b77 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -11,7 +11,7 @@ const MOCK_BIDS_REQUEST = { bids: [ { bidId: 1, - requestId: 'first-bid-id', + auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { param: 5 @@ -19,7 +19,7 @@ const MOCK_BIDS_REQUEST = { }, { bidId: 2, - requestId: 'second-bid-id', + auctionId: 'second-bid-id', adUnitCode: 'mock/placement2', params: { badParam: 6 @@ -609,7 +609,7 @@ describe('validate bid response: ', () => { let bidRequest = { bids: [{ bidId: 1, - requestId: 'first-bid-id', + auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { param: 5 @@ -646,7 +646,7 @@ describe('validate bid response: ', () => { let bidRequest = { bids: [{ bidId: 1, - requestId: 'first-bid-id', + auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { param: 5 @@ -682,7 +682,7 @@ describe('validate bid response: ', () => { let bidRequest = { bids: [{ bidId: 1, - requestId: 'first-bid-id', + auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { param: 5 @@ -717,7 +717,7 @@ describe('validate bid response: ', () => { bids: [{ bidder: CODE, bidId: 1, - requestId: 'first-bid-id', + auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { param: 5 diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index f0a4f0b8e9a..c1f7fe82252 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1443,7 +1443,7 @@ describe('Unit: Prebid Module', function () { 'pbAg': '10.00', 'size': '300x250', 'alwaysUseBid': true, - 'requestId': 123456, + 'auctionId': 123456, 'adserverTargeting': { 'hb_bidder': 'appnexus', 'hb_adid': '233bcbee889d46d', From 778c49674616fa258dd93cb3f80bcd8415d7b66b Mon Sep 17 00:00:00 2001 From: rxRTB <34483140+prebidRxRTB@users.noreply.github.com> Date: Wed, 20 Dec 2017 00:48:07 +0300 Subject: [PATCH 0015/1594] [Add BidAdapter] rxrtb adapter for Perbid.js 1.0 (#1950) * Add: rxrtb prebidAdapter * Update: params for test * Update: code format * Update: code format * Update: code format --- modules/rxrtbBidAdapter.js | 140 ++++++++++++++++++++++ modules/rxrtbBidAdapter.md | 32 +++++ test/spec/modules/rxrtbBidAdapter_spec.js | 120 +++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 modules/rxrtbBidAdapter.js create mode 100644 modules/rxrtbBidAdapter.md create mode 100644 test/spec/modules/rxrtbBidAdapter_spec.js diff --git a/modules/rxrtbBidAdapter.js b/modules/rxrtbBidAdapter.js new file mode 100644 index 00000000000..cf03e41c208 --- /dev/null +++ b/modules/rxrtbBidAdapter.js @@ -0,0 +1,140 @@ +import * as utils from 'src/utils'; +import {BANNER} from 'src/mediaTypes'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import {config} from 'src/config'; + +const BIDDER_CODE = 'rxrtb'; +const DEFAULT_HOST = 'bid.rxrtb.bid'; +const AUCTION_TYPE = 2; +const RESPONSE_TTL = 900; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + isBidRequestValid: function (bidRequest) { + return 'params' in bidRequest && bidRequest.params.source !== undefined && bidRequest.params.id !== undefined && Number.isInteger(bidRequest.params.id) && bidRequest.params.token !== undefined; + }, + buildRequests: function (validBidRequests) { + var requests = []; + for (let i = 0; i < validBidRequests.length; i++) { + let prebidReq = makePrebidRequest(validBidRequests[i]); + if (prebidReq) { + requests.push(prebidReq); + } + } + + return requests; + }, + interpretResponse: function (serverResponse, bidRequest) { + let rtbResp = serverResponse.body; + if ((!rtbResp) || (!rtbResp.seatbid)) { + return []; + } + let bidResponses = []; + for (let i = 0; i < rtbResp.seatbid.length; i++) { + let seatbid = rtbResp.seatbid[i]; + for (let j = 0; j < seatbid.bid.length; j++) { + let bid = seatbid.bid[j]; + let bidResponse = { + requestId: bid.impid, + cpm: bid.price, + width: bid.w, + height: bid.h, + mediaType: BANNER, + creativeId: bid.crid, + currency: rtbResp.cur || 'USD', + netRevenue: true, + ttl: bid.exp || RESPONSE_TTL, + ad: bid.adm + }; + bidResponses.push(bidResponse); + } + } + return bidResponses; + }, + getUserSyncs: function (syncOptions, serverResponses) { + return []; + } +} + +registerBidder(spec); + +function getDomain(url) { + var a = document.createElement('a'); + a.href = url; + + return a.host; +} + +function makePrebidRequest(req) { + let host = req.params.host || DEFAULT_HOST; + let url = window.location.protocol + '//' + host + '/dsp?id=' + req.params.id + '&token=' + req.params.token; + let reqData = makeRtbRequest(req); + return { + method: 'POST', + url: url, + data: JSON.stringify(reqData) + }; +} + +function makeRtbRequest(req) { + let imp = []; + imp.push(makeImp(req)); + return { + 'id': req.auctionId, + 'imp': imp, + 'site': makeSite(req), + 'device': makeDevice(), + 'hb': 1, + 'at': req.params.at || AUCTION_TYPE, + 'cur': ['USD'], + 'badv': req.params.badv || '', + 'bcat': req.params.bcat || '', + }; +} + +function makeImp(req) { + let imp = { + 'id': req.bidId, + 'tagid': req.adUnitCode, + 'banner': makeBanner(req) + }; + + if (req.params.bidfloor && Number.isInteger(req.params.bidfloor)) { + imp.bidfloor = req.params.bidfloor + } + + return imp; +} + +function makeBanner(req) { + let format = []; + let banner = {}; + for (let i = 0; i < req.sizes.length; i++) { + format.push({ + w: req.sizes[i][0], + h: req.sizes[i][1] + }); + } + banner.format = format; + if (req.params.pos && Number.isInteger(req.params.pos)) { + banner.pos = req.params.pos; + } + return banner; +} + +function makeSite(req) { + return { + 'id': req.params.source, + 'domain': getDomain(config.getConfig('publisherDomain')), + 'page': utils.getTopWindowUrl(), + 'ref': utils.getTopWindowReferrer() + }; +} + +function makeDevice() { + return { + 'ua': window.navigator.userAgent || '', + 'ip': 1 + }; +} diff --git a/modules/rxrtbBidAdapter.md b/modules/rxrtbBidAdapter.md new file mode 100644 index 00000000000..e9628bed0dc --- /dev/null +++ b/modules/rxrtbBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +Module Name: rxrtb Bidder Adapter + +Module Type: Bidder Adapter + +Maintainer: contact@picellaltd.com + + +# Description + +Module that connects to rxrtb's demand source + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'test-ad', + sizes: [[728, 98]], + bids: [ + { + bidder: 'rxrtb', + params: { + id: 89, + token: '658f11a5efbbce2f9be3f1f146fcbc22', + source: 'prebidtest' + } + } + ] + }, + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/rxrtbBidAdapter_spec.js b/test/spec/modules/rxrtbBidAdapter_spec.js new file mode 100644 index 00000000000..0785c6f144b --- /dev/null +++ b/test/spec/modules/rxrtbBidAdapter_spec.js @@ -0,0 +1,120 @@ +import {expect} from 'chai'; +import {spec} from 'modules/rxrtbBidAdapter'; + +describe('rxrtb adapater', () => { + describe('Test validate req', () => { + it('should accept minimum valid bid', () => { + let bid = { + bidder: 'rxrtb', + params: { + id: 89, + token: '658f11a5efbbce2f9be3f1f146fcbc22', + source: 'prebidtest' + } + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(true); + }); + + it('should reject missing id', () => { + let bid = { + bidder: 'rxrtb', + params: { + token: '658f11a5efbbce2f9be3f1f146fcbc22', + source: 'prebidtest' + } + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(false); + }); + + it('should reject id not Integer', () => { + let bid = { + bidder: 'rxrtb', + params: { + id: '123', + token: '658f11a5efbbce2f9be3f1f146fcbc22', + source: 'prebidtest' + } + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(false); + }); + + it('should reject missing source', () => { + let bid = { + bidder: 'rxrtb', + params: { + id: 89, + token: '658f11a5efbbce2f9be3f1f146fcbc22' + } + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(false); + }); + }); + + describe('Test build request', () => { + it('minimum request', () => { + let bid = { + bidder: 'rxrtb', + sizes: [[728, 90]], + bidId: '4d0a6829338a07', + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '20882439e3238c', + params: { + id: 89, + token: '658f11a5efbbce2f9be3f1f146fcbc22', + source: 'prebidtest' + }, + }; + const req = JSON.parse(spec.buildRequests([bid])[0].data); + + expect(req).to.have.property('id'); + expect(req).to.have.property('imp'); + expect(req).to.have.property('device'); + expect(req).to.have.property('site'); + expect(req).to.have.property('hb'); + expect(req.imp[0]).to.have.property('id'); + expect(req.imp[0]).to.have.property('banner'); + expect(req.device).to.have.property('ip'); + expect(req.device).to.have.property('ua'); + expect(req.site).to.have.property('id'); + expect(req.site).to.have.property('domain'); + }); + }); + + describe('Test interpret response', () => { + it('General banner response', () => { + let resp = spec.interpretResponse({ + body: { + id: 'abcd', + seatbid: [{ + bid: [{ + id: 'abcd', + impid: 'banner-bid', + price: 0.3, + w: 728, + h: 98, + adm: 'hello', + crid: 'efgh', + exp: 5 + }] + }] + } + }, null)[0]; + + expect(resp).to.have.property('requestId', 'banner-bid'); + expect(resp).to.have.property('cpm', 0.3); + expect(resp).to.have.property('width', 728); + expect(resp).to.have.property('height', 98); + expect(resp).to.have.property('creativeId', 'efgh'); + expect(resp).to.have.property('ttl', 5); + expect(resp).to.have.property('ad', 'hello'); + }); + }); +}); From 68e08b1999b3b6ec06ce6d44f9ec18e85a59f0d1 Mon Sep 17 00:00:00 2001 From: Jarrod Swart Date: Tue, 19 Dec 2017 16:50:53 -0500 Subject: [PATCH 0016/1594] ServerBid Server BidAdapter (#1819) * ServerBid Server BidAdapter Allow S2S configuration with ServerBid. * Updates to meet 1.0 callBids/config changes. * Fix linting issues. --- modules/serverbidServerBidAdapter.js | 236 ++++++++++++++ .../modules/serverbidServerBidAdapter_spec.js | 299 ++++++++++++++++++ 2 files changed, 535 insertions(+) create mode 100644 modules/serverbidServerBidAdapter.js create mode 100644 test/spec/modules/serverbidServerBidAdapter_spec.js diff --git a/modules/serverbidServerBidAdapter.js b/modules/serverbidServerBidAdapter.js new file mode 100644 index 00000000000..47d4e518222 --- /dev/null +++ b/modules/serverbidServerBidAdapter.js @@ -0,0 +1,236 @@ +import Adapter from 'src/adapter'; +import bidfactory from 'src/bidfactory'; +import * as utils from 'src/utils'; +import adaptermanager from 'src/adaptermanager'; +import { STATUS, S2S } from 'src/constants'; +import { config } from 'src/config'; + +const TYPE = S2S.SRC; +const getConfig = config.getConfig; +const REQUIRED_S2S_CONFIG_KEYS = ['siteId', 'networkId', 'bidders', 'endpoint']; + +let _s2sConfig; +config.setDefaults({ + 's2sConfig': { + enabled: false, + timeout: 1000, + adapter: 'serverbidServer' + } +}); + +var ServerBidServerAdapter; +ServerBidServerAdapter = function ServerBidServerAdapter() { + const baseAdapter = new Adapter('serverbidServer'); + + const BASE_URI = 'https://e.serverbid.com/api/v2'; + + const sizeMap = [ + null, + '120x90', + '120x90', + '468x60', + '728x90', + '300x250', + '160x600', + '120x600', + '300x100', + '180x150', + '336x280', + '240x400', + '234x60', + '88x31', + '120x60', + '120x240', + '125x125', + '220x250', + '250x250', + '250x90', + '0x0', + '200x90', + '300x50', + '320x50', + '320x480', + '185x185', + '620x45', + '300x125', + '800x250' + ]; + + sizeMap[77] = '970x90'; + sizeMap[123] = '970x250'; + sizeMap[43] = '300x600'; + + function setS2sConfig(options) { + let contains = (xs, x) => xs.indexOf(x) > -1; + let userConfig = Object.keys(options); + + REQUIRED_S2S_CONFIG_KEYS.forEach(key => { + if (!contains(userConfig, key)) { + utils.logError(key + ' missing in server to server config'); + return void 0; // void 0 to beat the linter + } + }) + + _s2sConfig = options; + } + getConfig('s2sConfig', ({s2sConfig}) => setS2sConfig(s2sConfig)); + + function getLocalConfig() { + return (_s2sConfig || {}); + } + + function _convertFields(bid) { + let safeBid = bid || {}; + let converted = {}; + let name = safeBid.bidder; + converted[name] = safeBid.params; + return converted; + } + + baseAdapter.callBids = function(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { + let params = s2sBidRequest; + let shouldDoWorkFn = function(bidRequest) { + return bidRequest && + bidRequest.ad_units && + utils.isArray(bidRequest.ad_units) && + bidRequest.ad_units.length; + } + if (shouldDoWorkFn(params)) { + _callBids(s2sBidRequest, bidRequests, addBidResponse, done, ajax); + } + }; + + function _callBids(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { + let bidRequest = s2sBidRequest; + + // one request per ad unit + for (let i = 0; i < bidRequest.ad_units.length; i++) { + let adunit = bidRequest.ad_units[i]; + let siteId = _s2sConfig.siteId; + let networkId = getLocalConfig().networkId; + let sizes = adunit.sizes; + + const data = { + placements: [], + time: Date.now(), + user: {}, + url: utils.getTopWindowUrl(), + referrer: document.referrer, + enableBotFiltering: true, + includePricingData: true, + parallel: true + }; + + const bids = adunit.bids || []; + + // one placement for each of the bids + for (let i = 0; i < bids.length; i++) { + const bid = bids[i]; + bid.code = adunit.code; + + const placement = Object.assign({}, { + divName: bid.bid_id, + networkId: networkId, + siteId: siteId, + adTypes: bid.adTypes || getSize(sizes), + bidders: _convertFields(bid), + skipSelection: true + }); + + if (placement.networkId && placement.siteId) { + data.placements.push(placement); + } + } + if (data.placements.length) { + ajax(BASE_URI, _responseCallback(addBidResponse, bids), JSON.stringify(data), { method: 'POST', withCredentials: true, contentType: 'application/json' }); + } + } + } + + function _responseCallback(addBidResponse, bids) { + return function (resp) { + let bid; + let bidId; + let result; + let bidObj; + let bidCode; + let placementCode; + let skipSelectionRequestsReturnArray = function (decision) { + return (decision || []).length ? decision[0] : {}; + }; + + try { + result = JSON.parse(resp); + } catch (error) { + utils.logError(error); + } + + for (let i = 0; i < bids.length; i++) { + bidObj = bids[i]; + bidId = bidObj.bid_id; + bidObj.bidId = bidObj.bid_id; + bidCode = bidObj.bidder; + placementCode = bidObj.code; + let noBid = function(bidObj) { + bid = bidfactory.createBid(STATUS.NO_BID, bidObj); + bid.bidderCode = bidCode; + return bid; + }; + + if (result) { + const decision = result.decisions && skipSelectionRequestsReturnArray(result.decisions[bidId]); + const price = decision && decision.pricing && decision.pricing.clearPrice; + + if (decision && price) { + bid = bidfactory.createBid(STATUS.GOOD, bidObj); + bid = Object.assign(bid, {bidderCode: bidCode, + cpm: price, + width: decision.width, + height: decision.height, + ad: retrieveAd(decision)}) + } else { + bid = noBid(bidObj); + } + } else { + bid = noBid(bidObj); + } + addBidResponse(placementCode, bid); + } + done() + } + }; + + function retrieveAd(decision) { + return decision.contents && decision.contents[0] && decision.contents[0].body + utils.createTrackPixelHtml(decision.impressionUrl); + } + + function getSize(sizes) { + let width = 'w'; + let height = 'h'; + const result = []; + sizes.forEach(function(size) { + const index = sizeMap.indexOf(size[width] + 'x' + size[height]); + if (index >= 0) { + result.push(index); + } + }); + return result; + } + + // Export the `callBids` function, so that Prebid.js can execute + // this function when the page asks to send out bid requests. + return Object.assign(this, { + queueSync: baseAdapter.queueSync, + callBids: baseAdapter.callBids, + setBidderCode: baseAdapter.setBidderCode, + type: TYPE + }); +}; + +ServerBidServerAdapter.createNew = function() { + return new ServerBidServerAdapter(); +}; + +adaptermanager.registerBidAdapter(new ServerBidServerAdapter(), 'serverbidServer'); + +module.exports = ServerBidServerAdapter; diff --git a/test/spec/modules/serverbidServerBidAdapter_spec.js b/test/spec/modules/serverbidServerBidAdapter_spec.js new file mode 100644 index 00000000000..7745d0e407c --- /dev/null +++ b/test/spec/modules/serverbidServerBidAdapter_spec.js @@ -0,0 +1,299 @@ +import { expect } from 'chai'; +import Adapter from 'modules/serverbidServerBidAdapter'; +import * as utils from 'src/utils'; +import { config } from 'src/config'; +import { ajax } from 'src/ajax'; + +const ENDPOINT = 'https://e.serverbid.com/api/v2'; + +let CONFIG = { + enabled: true, + bidders: ['appnexus'], + timeout: 1000, + adapter: 'serverbidServer', + networkId: 9969, + siteId: 730181, + endpoint: ENDPOINT +}; + +let CONFIG_ARG = { + s2sConfig: CONFIG +} + +const REQUEST = { + 'account_id': '1', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'max_bids': 1, + 'timeout_millis': 1000, + 'url': '', + 'prebid_version': '0.21.0-pre', + 'ad_units': [ + { + 'code': 'div-gpt-ad-1460505748561-0', + 'sizes': [ + { + 'w': 300, + 'h': 250 + }, + { + 'w': 300, + 'h': 600 + } + ], + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'bids': [ + { + 'bid_id': '123', + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394', + 'member': 123 + } + } + ] + } + ] +}; + +const BID_REQUESTS = [ + { + 'bidderCode': 'appnexus', + 'auctionId': '173afb6d132ba3', + 'bidderRequestId': '3d1063078dfcc8', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394', + 'member': 123 + }, + 'bid_id': '123', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'sizes': [ + { + 'w': 300, + 'h': 250 + } + ], + 'bidId': '259fb43aaa06c1', + 'bidderRequestId': '3d1063078dfcc8', + 'auctionId': '173afb6d132ba3' + } + ], + 'auctionStart': 1510852447530, + 'timeout': 5000, + 'src': 's2s', + 'doneCbCallCount': 0 + } +]; + +const RESPONSE = { + 'user': { 'key': 'ue1-2d33e91b71e74929b4aeecc23f4376f1' }, + 'decisions': { + '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': 300, + 'width': 250, + 'imageUrl': 'https://static.adzerk.net/Advertisers/b0ab77db8a7848c8b78931aed022a5ef.gif', + 'fileName': 'b0ab77db8a7848c8b78931aed022a5ef.gif' + }, + 'template': 'image' + }], + 'height': 250, + 'width': 300, + 'events': [], + 'pricing': {'price': 0.5, 'clearPrice': 0.5, 'revenue': 0.0005, 'rateType': 2, 'eCPM': 0.5} + }], + } +}; + +const RESPONSE_NO_BID_NO_UNIT = { + 'user': { 'key': 'ue1-2d33e91b71e74929b4aeecc23f4376f1' }, + 'decisions': { + '123': [] + } +}; + +const REQUEST_TWO_UNITS = { + 'account_id': '1', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'max_bids': 1, + 'timeout_millis': 1000, + 'url': '', + 'prebid_version': '0.21.0-pre', + 'ad_units': [ + { + 'code': 'div-gpt-ad-1460505748561-0', + 'sizes': [ + { + 'w': 300, + 'h': 250 + }, + { + 'w': 300, + 'h': 600 + } + ], + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'bids': [ + { + 'bid_id': '123', + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394', + 'member': 123 + } + } + ] + }, + { + 'code': 'div-gpt-ad-1460505748561-1', + 'sizes': [ + { + 'w': 300, + 'h': 250 + }, + { + 'w': 300, + 'h': 600 + } + ], + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786bb86d', + 'bids': [ + { + 'bid_id': '101111', + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394', + 'member': 123 + } + } + ] + } + ] +}; + +describe('ServerBid S2S Adapter', () => { + let adapter, + addBidResponse = sinon.spy(), + done = sinon.spy(); + + beforeEach(() => adapter = new Adapter()); + + afterEach(() => { + addBidResponse.reset(); + done.reset(); + }); + + describe('request function', () => { + let xhr; + let requests; + + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + }); + + afterEach(() => xhr.restore()); + + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('response handler', () => { + let server; + + beforeEach(() => { + server = sinon.fakeServer.create(); + sinon.stub(utils, 'getBidRequest').returns({ + bidId: '123' + }); + }); + + afterEach(() => { + server.restore(); + utils.getBidRequest.restore(); + }); + + it('registers bids', () => { + server.respondWith(JSON.stringify(RESPONSE)); + + config.setConfig(CONFIG_ARG); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + sinon.assert.calledOnce(addBidResponse); + + const response = addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('cpm', 0.5); + expect(response).to.have.property('adId', '123'); + }); + + it('registers no-bid response when ad unit not set', () => { + server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); + + config.setConfig(CONFIG_ARG); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + sinon.assert.calledOnce(addBidResponse); + + const ad_unit_code = addBidResponse.firstCall.args[0]; + expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); + + const response = addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); + + const bid_request_passed = addBidResponse.firstCall.args[1]; + expect(bid_request_passed).to.have.property('adId', '123'); + }); + + it('registers no-bid response when ad unit is set', () => { + server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); + + config.setConfig(CONFIG_ARG); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + sinon.assert.calledOnce(addBidResponse); + + const ad_unit_code = addBidResponse.firstCall.args[0]; + expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); + + const response = addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); + }); + + it('registers no-bid response when there are less bids than requests', () => { + server.respondWith(JSON.stringify(RESPONSE)); + + config.setConfig(CONFIG_ARG); + adapter.callBids(REQUEST_TWO_UNITS, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledTwice(addBidResponse); + + expect(addBidResponse.firstCall.args[0]).to.equal('div-gpt-ad-1460505748561-0'); + expect(addBidResponse.secondCall.args[0]).to.equal('div-gpt-ad-1460505748561-1'); + + expect(addBidResponse.firstCall.args[1]).to.have.property('adId', '123'); + expect(addBidResponse.secondCall.args[1]).to.have.property('adId', '101111'); + + expect(addBidResponse.firstCall.args[1]) + .to.have.property('statusMessage', 'Bid available'); + expect(addBidResponse.secondCall.args[1]) + .to.have.property('statusMessage', 'Bid returned empty or error response'); + }); + }); +}); From b7d5da33a7cc8162468df77e301dbfb2380a777c Mon Sep 17 00:00:00 2001 From: Matt Kendall Date: Tue, 19 Dec 2017 17:12:05 -0500 Subject: [PATCH 0017/1594] added hb_source to default keys (#1969) * added hb_source * dropped function to add hb_source since it is now default key * fixed lint error --- modules/s2sTesting.js | 36 -------- src/auction.js | 6 ++ src/bidfactory.js | 2 + src/constants.json | 3 +- test/spec/auctionmanager_spec.js | 23 +++-- test/spec/modules/s2sTesting_spec.js | 127 --------------------------- 6 files changed, 28 insertions(+), 169 deletions(-) diff --git a/modules/s2sTesting.js b/modules/s2sTesting.js index a821383dc2d..60ab150530f 100644 --- a/modules/s2sTesting.js +++ b/modules/s2sTesting.js @@ -1,8 +1,6 @@ import { config } from 'src/config'; import { setS2STestingModule } from 'src/adaptermanager'; -var CONSTANTS = require('src/constants.json'); -const AST = CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING; export const SERVER = 'server'; export const CLIENT = 'client'; @@ -12,43 +10,9 @@ var bidSource = {}; // store bidder sources determined from s2sConfing bidderCon // load s2sConfig config.getConfig('s2sConfig', config => { testing = config.s2sConfig && config.s2sConfig.testing; - addBidderSourceTargeting(config.s2sConfig) calculateBidSources(config.s2sConfig); }); -// function to add hb_source_ adServerTargeting (AST) kvp to bidder settings -function addBidderSourceTargeting(s2sConfig = {}) { - // bail if testing is not turned on - if (!testing) { - return; - } - var bidderSettings = $$PREBID_GLOBAL$$.bidderSettings || {}; - var bidderControl = s2sConfig.bidderControl || {}; - // for each configured bidder - (s2sConfig.bidders || []).forEach((bidder) => { - // remove any existing kvp setting - if (bidderSettings[bidder] && bidderSettings[bidder][AST]) { - bidderSettings[bidder][AST] = bidderSettings[bidder][AST].filter((kvp) => { - return kvp.key !== `hb_source_${bidder}`; - }); - } - // if includeSourceKvp === true add new kvp setting - if (bidderControl[bidder] && bidderControl[bidder].includeSourceKvp) { - bidderSettings[bidder] = bidderSettings[bidder] || {}; - bidderSettings[bidder][AST] = bidderSettings[bidder][AST] || []; - bidderSettings[bidder][AST].push({ - key: `hb_source_${bidder}`, - val: function (bidResponse) { - // default to client (currently only S2S sets this) - return bidResponse.source || CLIENT; - } - }); - // make sure "alwaysUseBid" is true so targeting is set - bidderSettings[bidder].alwaysUseBid = true; - } - }); -} - export function getSourceBidderMap(adUnits = []) { var sourceBidders = {[SERVER]: {}, [CLIENT]: {}}; diff --git a/src/auction.js b/src/auction.js index 45d06c23f59..7c6a752c057 100644 --- a/src/auction.js +++ b/src/auction.js @@ -361,6 +361,12 @@ export function getStandardBidderSettings() { val: function (bidResponse) { return bidResponse.dealId; } + }, + { + key: 'hb_source', + val: function (bidResponse) { + return bidResponse.source; + } } ] } diff --git a/src/bidfactory.js b/src/bidfactory.js index ff57abb8a39..6250969d6df 100644 --- a/src/bidfactory.js +++ b/src/bidfactory.js @@ -16,6 +16,7 @@ var utils = require('./utils.js'); */ function Bid(statusCode, bidRequest) { var _bidId = (bidRequest && bidRequest.bidId) || utils.getUniqueIdentifierStr(); + var _bidSrc = (bidRequest && bidRequest.src) || 'client'; var _statusCode = statusCode || 0; this.bidderCode = (bidRequest && bidRequest.bidder) || ''; @@ -24,6 +25,7 @@ function Bid(statusCode, bidRequest) { this.statusMessage = _getStatus(); this.adId = _bidId; this.mediaType = 'banner'; + this.source = _bidSrc; function _getStatus() { switch (_statusCode) { diff --git a/src/constants.json b/src/constants.json index 3e20d462ac7..e80c118ea83 100644 --- a/src/constants.json +++ b/src/constants.json @@ -51,7 +51,8 @@ "hb_adid", "hb_pb", "hb_size", - "hb_deal" + "hb_deal", + "hb_source" ], "S2S" : { "SRC" : "s2s", diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index c773974d177..688afc35d9d 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -34,6 +34,7 @@ describe('auctionmanager.js', function () { var bidderCode = 'appnexus'; var size = '300x250'; var adId = '1adId'; + var source = 'client'; before(function () { bid.cpm = bidPriceCpm; @@ -50,6 +51,7 @@ describe('auctionmanager.js', function () { }; bid.bidderCode = bidderCode; bid.adId = adId; + bid.source = source; }); it('No bidder level configuration defined - default', function () { @@ -57,7 +59,8 @@ describe('auctionmanager.js', function () { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': bidPbMg, - 'hb_size': size + 'hb_size': size, + 'hb_source': source }; var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); assert.deepEqual(response, expected); @@ -89,6 +92,12 @@ describe('auctionmanager.js', function () { val: function (bidResponse) { return bidResponse.size; } + }, + { + key: 'hb_source', + val: function (bidResponse) { + return bidResponse.source; + } } ] @@ -99,7 +108,8 @@ describe('auctionmanager.js', function () { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': bidPbHg, - 'hb_size': size + 'hb_size': size, + 'hb_source': source }; var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); assert.deepEqual(response, expected); @@ -141,7 +151,8 @@ describe('auctionmanager.js', function () { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': bidPbHg, - 'hb_size': size + 'hb_size': size, + 'hb_source': source }; var response = getKeyValueTargetingPairs(bidderCode, bid); assert.deepEqual(response, expected); @@ -183,7 +194,8 @@ describe('auctionmanager.js', function () { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': bidPbMg, - 'hb_size': size + 'hb_size': size, + 'hb_source': source }; var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); assert.deepEqual(response, expected); @@ -347,7 +359,8 @@ describe('auctionmanager.js', function () { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': 5.57, - 'hb_size': '300x250' + 'hb_size': '300x250', + 'hb_source': source }; var response = getKeyValueTargetingPairs(bidderCode, bid); assert.deepEqual(response, expected); diff --git a/test/spec/modules/s2sTesting_spec.js b/test/spec/modules/s2sTesting_spec.js index 26d5eb8884b..845947a0b38 100644 --- a/test/spec/modules/s2sTesting_spec.js +++ b/test/spec/modules/s2sTesting_spec.js @@ -308,131 +308,4 @@ describe('s2sTesting', function () { }); }); }); - - describe('addBidderSourceTargeting', () => { - const AST = CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING; - - function checkTargeting(bidder) { - var targeting = window.$$PREBID_GLOBAL$$.bidderSettings[bidder][AST]; - var srcTargeting = targeting[targeting.length - 1]; - expect(srcTargeting.key).to.equal(`hb_source_${bidder}`); - expect(srcTargeting.val).to.be.a('function'); - expect(window.$$PREBID_GLOBAL$$.bidderSettings[bidder].alwaysUseBid).to.be.true; - } - - function checkNoTargeting(bidder) { - var bs = window.$$PREBID_GLOBAL$$.bidderSettings; - var targeting = bs[bidder] && bs[bidder][AST]; - if (!targeting) { - expect(targeting).to.be.undefined; - return; - } - expect(find(targeting, (kvp) => { - return kvp.key === `hb_source_${bidder}`; - })).to.be.undefined; - } - - function checkTargetingVal(bidResponse, expectedVal) { - var targeting = window.$$PREBID_GLOBAL$$.bidderSettings[bidResponse.bidderCode][AST]; - var targetingFunc = targeting[targeting.length - 1].val; - expect(targetingFunc(bidResponse)).to.equal(expectedVal); - } - - beforeEach(() => { - // set bidderSettings - window.$$PREBID_GLOBAL$$.bidderSettings = {}; - }); - - it('should not set hb_source_ unless testing is on and includeSourceKvp is set', () => { - config.setConfig({s2sConfig: {bidders: ['rubicon', 'appnexus']}}); - expect(window.$$PREBID_GLOBAL$$.bidderSettings).to.eql({}); - - config.setConfig({s2sConfig: {bidders: ['rubicon', 'appnexus'], testing: true}}); - expect(window.$$PREBID_GLOBAL$$.bidderSettings).to.eql({}); - - config.setConfig({s2sConfig: { - bidders: ['rubicon', 'appnexus'], - testing: true, - bidderControl: { - rubicon: {bidSource: {server: 2, client: 1}}, - appnexus: {bidSource: {server: 1}} - } - }}); - expect(window.$$PREBID_GLOBAL$$.bidderSettings).to.eql({}); - - config.setConfig({s2sConfig: { - bidders: ['rubicon', 'appnexus'], - testing: false, - bidderControl: { - rubicon: {includeSourceKvp: true}, - appnexus: {includeSourceKvp: true} - } - }}); - expect(window.$$PREBID_GLOBAL$$.bidderSettings).to.eql({}); - }); - - it('should set hb_source_ if includeSourceKvp is set', () => { - config.setConfig({s2sConfig: { - bidders: ['rubicon', 'appnexus'], - testing: true, - bidderControl: { - rubicon: {includeSourceKvp: true}, - appnexus: {includeSourceKvp: true} - } - }}); - checkTargeting('rubicon'); - checkTargeting('appnexus'); - checkTargetingVal({bidderCode: 'rubicon', source: 'server'}, 'server'); - checkTargetingVal({bidderCode: 'appnexus', source: 'client'}, 'client'); - - // turn off appnexus - config.setConfig({s2sConfig: { - bidders: ['rubicon', 'appnexus'], - testing: true, - bidderControl: { - rubicon: {includeSourceKvp: true}, - appnexus: {includeSourceKvp: false} - } - }}); - checkTargeting('rubicon'); - checkNoTargeting('appnexus'); - checkTargetingVal({bidderCode: 'rubicon', source: 'client'}, 'client'); - - // should default to "client" - config.setConfig({s2sConfig: { - bidders: ['rubicon', 'appnexus'], - testing: true, - bidderControl: { - rubicon: {includeSourceKvp: true}, - appnexus: {includeSourceKvp: true} - } - }}); - checkTargeting('rubicon'); - checkTargeting('appnexus'); - checkTargetingVal({bidderCode: 'rubicon'}, 'client'); - checkTargetingVal({bidderCode: 'appnexus'}, 'client'); - }); - - it('should reset adServerTargeting when a new config is set', () => { - // set config with targeting - config.setConfig({s2sConfig: { - bidders: ['rubicon', 'appnexus'], - testing: true, - bidderControl: { - rubicon: {includeSourceKvp: true}, - appnexus: {includeSourceKvp: true} - } - }}); - checkTargeting('rubicon'); - checkTargeting('appnexus'); - - // set config without targeting - config.setConfig({s2sConfig: { - bidders: ['rubicon', 'appnexus'], - testing: true - }}); - checkNoTargeting('rubicon'); - checkNoTargeting('appnexus'); - }); - }); }); From 46cdaa1df297b389967334927334e4808bacce2c Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 19 Dec 2017 16:20:11 -0800 Subject: [PATCH 0018/1594] Prebid 1.1.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61c9edf2b82..80a44979db6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.0.0", + "version": "1.1.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 61f0414cfa3a3b62a01e7fa691c0c2422d1f163e Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 19 Dec 2017 16:30:23 -0800 Subject: [PATCH 0019/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 80a44979db6..9d6af175e0e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.1.0", + "version": "1.2.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d784396245794ca853c244be871dfd71d0dbd22a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 20 Dec 2017 11:08:16 -0500 Subject: [PATCH 0020/1594] S2s defaults fix in serverbidServerBidAdapter (#1986) * removed s2s defaults * start timestamp was missing on s2s requests --- modules/serverbidServerBidAdapter.js | 13 +++++-------- src/adaptermanager.js | 5 +++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/modules/serverbidServerBidAdapter.js b/modules/serverbidServerBidAdapter.js index 47d4e518222..4ff8992772f 100644 --- a/modules/serverbidServerBidAdapter.js +++ b/modules/serverbidServerBidAdapter.js @@ -10,13 +10,8 @@ const getConfig = config.getConfig; const REQUIRED_S2S_CONFIG_KEYS = ['siteId', 'networkId', 'bidders', 'endpoint']; let _s2sConfig; -config.setDefaults({ - 's2sConfig': { - enabled: false, - timeout: 1000, - adapter: 'serverbidServer' - } -}); + +const bidder = 'serverbidServer'; var ServerBidServerAdapter; ServerBidServerAdapter = function ServerBidServerAdapter() { @@ -61,6 +56,8 @@ ServerBidServerAdapter = function ServerBidServerAdapter() { sizeMap[43] = '300x600'; function setS2sConfig(options) { + if (options.adapter != bidder) return; + let contains = (xs, x) => xs.indexOf(x) > -1; let userConfig = Object.keys(options); @@ -231,6 +228,6 @@ ServerBidServerAdapter.createNew = function() { return new ServerBidServerAdapter(); }; -adaptermanager.registerBidAdapter(new ServerBidServerAdapter(), 'serverbidServer'); +adaptermanager.registerBidAdapter(new ServerBidServerAdapter(), bidder); module.exports = ServerBidServerAdapter; diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 670b329ef72..c8dc72e7ddc 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -1,6 +1,6 @@ /** @module adaptermanger */ -import { flatten, getBidderCodes, getDefinedParams, shuffle } from './utils'; +import { flatten, getBidderCodes, getDefinedParams, shuffle, timestamp } from './utils'; import { resolveStatus } from './sizeMapping'; import { processNativeAdUnitParams, nativeAdapters } from './native'; import { newBidder } from './adapters/bidderFactory'; @@ -234,6 +234,7 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { let s2sBidRequest = {tid, 'ad_units': adUnitsS2SCopy}; if (s2sBidRequest.ad_units.length) { let doneCbs = serverBidRequests.map(bidRequest => { + bidRequest.start = timestamp(); bidRequest.doneCbCallCount = 0; return doneCb(bidRequest.bidderRequestId) }); @@ -265,7 +266,7 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { // handle client adapter requests clientBidRequests.forEach(bidRequest => { - bidRequest.start = new Date().getTime(); + bidRequest.start = timestamp(); // TODO : Do we check for bid in pool from here and skip calling adapter again ? const adapter = _bidderRegistry[bidRequest.bidderCode]; if (adapter) { From 94cce25fed9000e9a747129d709935a1a9da4a8f Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 20 Dec 2017 11:38:51 -0700 Subject: [PATCH 0021/1594] remove hardcoded localhost port for tests (#1988) --- test/spec/modules/nanointeractiveBidAdapter_spec.js | 8 +++++++- test/spec/modules/readpeakBidAdapter_spec.js | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index 01aa60351e8..4b498c88982 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -1,4 +1,6 @@ import { expect } from 'chai'; +import * as utils from 'src/utils'; + import { ALG, BIDDER_CODE, CATEGORY, DATA_PARTNER_ID, DATA_PARTNER_PIXEL_ID, ENGINE_BASE_URL, NQ, NQ_NAME, SECURITY, @@ -44,7 +46,7 @@ describe('nanointeractive adapter tests', function () { [NQ]: [SEARCH_QUERY, null], sizes: [WIDTH + 'x' + HEIGHT], bidId: '24a1c9ec270973', - cors: 'http://localhost:9876' + cors: 'http://localhost' }; function getSingleBidResponse(isValid) { @@ -84,10 +86,14 @@ describe('nanointeractive adapter tests', function () { expect(nanoBidAdapter.isBidRequestValid(getBid(false))).to.equal(false); }); it('Test buildRequests()', function () { + let stub = sinon.stub(utils, 'getOrigin', () => 'http://localhost'); + let request = nanoBidAdapter.buildRequests([getBid(true)]); expect(request.method).to.equal('POST'); expect(request.url).to.equal(ENGINE_BASE_URL); expect(request.data).to.equal(JSON.stringify([SINGlE_BID_REQUEST])); + + stub.restore(); }); it('Test interpretResponse() length', function () { let bids = nanoBidAdapter.interpretResponse([getSingleBidResponse(true), getSingleBidResponse(false)]); diff --git a/test/spec/modules/readpeakBidAdapter_spec.js b/test/spec/modules/readpeakBidAdapter_spec.js index 18b52658c4b..7da3450f16c 100644 --- a/test/spec/modules/readpeakBidAdapter_spec.js +++ b/test/spec/modules/readpeakBidAdapter_spec.js @@ -99,7 +99,7 @@ describe('ReadPeakAdapter', () => { }, 'id': '11bc5dd5-7421-4dd8-c926-40fa653bec76', 'ref': '', - 'page': 'http://localhost:9876/?id=48509002', + 'page': 'http://localhost', 'domain': 'localhost' }, 'app': null, From 60b9ac57b41ee615dc0c431a5572879c891ac0d2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 20 Dec 2017 13:39:52 -0500 Subject: [PATCH 0022/1594] Fixes unit tests in browsers other than chrome (#1987) * Fixes unit tests in browsers other than chrome * fixed lint errors --- modules/freewheelSSPBidAdapter.js | 9 ++++++--- modules/rxrtbBidAdapter.js | 6 +++--- modules/serverbidServerBidAdapter.js | 4 ++-- src/utils.js | 13 +++++++++++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/modules/freewheelSSPBidAdapter.js b/modules/freewheelSSPBidAdapter.js index 7c696c746e6..64ebb36478b 100644 --- a/modules/freewheelSSPBidAdapter.js +++ b/modules/freewheelSSPBidAdapter.js @@ -47,7 +47,9 @@ function getPricing(xmlNode) { var princingData = {}; var extensions = xmlNode.querySelectorAll('Extension'); - extensions.forEach(function(node) { + // Nodelist.forEach is not supported in IE and Edge + // Workaround given here https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10638731/ + Array.prototype.forEach.call(extensions, function(node) { if (node.getAttribute('type') === 'StickyPricing') { pricingExtNode = node; } @@ -69,8 +71,9 @@ function getPricing(xmlNode) { function getCreativeId(xmlNode) { var creaId = ''; var adNodes = xmlNode.querySelectorAll('Ad'); - - adNodes.forEach(function(el) { + // Nodelist.forEach is not supported in IE and Edge + // Workaround given here https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10638731/ + Array.prototype.forEach.call(adNodes, function(el) { creaId += '[' + el.getAttribute('id') + ']'; }); diff --git a/modules/rxrtbBidAdapter.js b/modules/rxrtbBidAdapter.js index cf03e41c208..55b6991667a 100644 --- a/modules/rxrtbBidAdapter.js +++ b/modules/rxrtbBidAdapter.js @@ -12,7 +12,7 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], isBidRequestValid: function (bidRequest) { - return 'params' in bidRequest && bidRequest.params.source !== undefined && bidRequest.params.id !== undefined && Number.isInteger(bidRequest.params.id) && bidRequest.params.token !== undefined; + return 'params' in bidRequest && bidRequest.params.source !== undefined && bidRequest.params.id !== undefined && utils.isInteger(bidRequest.params.id) && bidRequest.params.token !== undefined; }, buildRequests: function (validBidRequests) { var requests = []; @@ -100,7 +100,7 @@ function makeImp(req) { 'banner': makeBanner(req) }; - if (req.params.bidfloor && Number.isInteger(req.params.bidfloor)) { + if (req.params.bidfloor && utils.isInteger(req.params.bidfloor)) { imp.bidfloor = req.params.bidfloor } @@ -117,7 +117,7 @@ function makeBanner(req) { }); } banner.format = format; - if (req.params.pos && Number.isInteger(req.params.pos)) { + if (req.params.pos && utils.isInteger(req.params.pos)) { banner.pos = req.params.pos; } return banner; diff --git a/modules/serverbidServerBidAdapter.js b/modules/serverbidServerBidAdapter.js index 4ff8992772f..4be96a09bd6 100644 --- a/modules/serverbidServerBidAdapter.js +++ b/modules/serverbidServerBidAdapter.js @@ -139,12 +139,12 @@ ServerBidServerAdapter = function ServerBidServerAdapter() { } } if (data.placements.length) { - ajax(BASE_URI, _responseCallback(addBidResponse, bids), JSON.stringify(data), { method: 'POST', withCredentials: true, contentType: 'application/json' }); + ajax(BASE_URI, _responseCallback(addBidResponse, bids, done), JSON.stringify(data), { method: 'POST', withCredentials: true, contentType: 'application/json' }); } } } - function _responseCallback(addBidResponse, bids) { + function _responseCallback(addBidResponse, bids, done) { return function (resp) { let bid; let bidId; diff --git a/src/utils.js b/src/utils.js index 19014049352..2d185ebe4c6 100644 --- a/src/utils.js +++ b/src/utils.js @@ -866,3 +866,16 @@ export function deletePropertyFromObject(object, prop) { export function removeRequestId(bid) { return exports.deletePropertyFromObject(bid, 'requestId'); } + +/** + * Checks input is integer or not + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger + * @param {*} value + */ +export function isInteger(value) { + if (Number.isInteger) { + return Number.isInteger(value); + } else { + return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; + } +} From ff8f539dac2fdb03745b252d4f2a89c962bf7eb8 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 20 Dec 2017 13:41:09 -0500 Subject: [PATCH 0023/1594] Prebid 1.1.1 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9d6af175e0e..661cbfc3495 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.2.0-pre", + "version": "1.1.1", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 2b1b1fe1f67ebacafd5bb4dc0906dbbaf499e78c Mon Sep 17 00:00:00 2001 From: Matt Kendall Date: Tue, 2 Jan 2018 15:58:54 -0500 Subject: [PATCH 0024/1594] Add note about docs needed before merge (#1959) * Add note about docs needed before merge * Update pr_review.md * Update pr_review.md * Update pr_review.md --- pr_review.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pr_review.md b/pr_review.md index 558b1c8bcb9..1d8cf0c360c 100644 --- a/pr_review.md +++ b/pr_review.md @@ -6,9 +6,10 @@ We take PR review seriously. Please read https://medium.com/@mrjoelkemp/giving-b - Verify PR is a single change type. Example, refactor OR bugfix. If more than 1 type, ask submitter to break out requests. - Verify code under review has at least 80% unit test coverage. If legacy code has no unit test coverage, ask for unit tests to be included in the PR. - Verify tests are green in Travis-ci + local build by running `gulp serve` | `gulp test` -- Verify no code quality violations are present from jscs (should be reported in terminal) +- Verify no code quality violations are present from linting (should be reported in terminal) - Review for obvious errors or bad coding practice / use best judgement here. - If the change is a new feature / change to core prebid.js - review the change with a Tech Lead on the project and make sure they agree with the nature of change. +- If the change results in needing updates to docs (such as public API change, module interface etc), add a label for "needs docs" and inform the submitter they must submit a docs PR to update the appropriate area of Prebid.org **before the PR can merge**. Help them with finding where the docs are located on prebid.org if needed. - If all above is good, add a `LGTM` comment and request 1 additional core member to review. - Once there is 2 `LGTM` on the PR, merge to master - Ask the submitter to add a PR for documentation if applicable. From 402877a940753ac78907812bd852fa2d7c172ab2 Mon Sep 17 00:00:00 2001 From: nissSK Date: Wed, 3 Jan 2018 17:52:55 +0200 Subject: [PATCH 0025/1594] Adding optional width and height to display parameters (#1998) * adding optional size * no tabs --- modules/sekindoUMBidAdapter.js | 2 ++ modules/sekindoUMBidAdapter.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/modules/sekindoUMBidAdapter.js b/modules/sekindoUMBidAdapter.js index 6e866c6547e..6e4ae34bd76 100644 --- a/modules/sekindoUMBidAdapter.js +++ b/modules/sekindoUMBidAdapter.js @@ -47,6 +47,8 @@ export const spec = { queryString = utils.tryAppendQueryString(queryString, 'hbcb', '1');/// legasy queryString = utils.tryAppendQueryString(queryString, 'dcpmflr', bidfloor); queryString = utils.tryAppendQueryString(queryString, 'protocol', protocol); + queryString = utils.tryAppendQueryString(queryString, 'x', bidRequest.params.width); + queryString = utils.tryAppendQueryString(queryString, 'y', bidRequest.params.height); if (bidRequest.mediaType === 'video' || (typeof bidRequest.mediaTypes == 'object' && typeof bidRequest.mediaTypes.video == 'object')) { queryString = utils.tryAppendQueryString(queryString, 'x', bidRequest.params.playerWidth); queryString = utils.tryAppendQueryString(queryString, 'y', bidRequest.params.playerHeight); diff --git a/modules/sekindoUMBidAdapter.md b/modules/sekindoUMBidAdapter.md index 9f44e7a855e..24c2aaec6db 100755 --- a/modules/sekindoUMBidAdapter.md +++ b/modules/sekindoUMBidAdapter.md @@ -19,6 +19,8 @@ Banner, Outstream and Native formats are supported. bidder: 'sekindoUM', params: { spaceId: 14071 + width:300, //optional + weight:250, //optional } }] }, From 30dddf8bbb49ec06dec2fa75ba978d5a97637bfc Mon Sep 17 00:00:00 2001 From: PWyrembak Date: Wed, 3 Jan 2018 20:54:08 +0300 Subject: [PATCH 0026/1594] TrustX adapter update (#1979) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster --- modules/trustxBidAdapter.js | 3 +++ test/spec/modules/trustxBidAdapter_spec.js | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index f16b8b96ec8..ec1f0247455 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -37,11 +37,13 @@ export const spec = { const bidsMap = {}; const bids = validBidRequests || []; let priceType = 'net'; + let reqId; bids.forEach(bid => { if (bid.params.priceType === 'gross') { priceType = 'gross'; } + reqId = bid.bidderRequestId; if (!bidsMap[bid.params.uid]) { bidsMap[bid.params.uid] = [bid]; auids.push(bid.params.uid); @@ -54,6 +56,7 @@ export const spec = { u: utils.getTopWindowUrl(), pt: priceType, auids: auids.join(','), + r: reqId }; return { diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index 918e03674a9..6149545d59f 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -82,6 +82,7 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43'); + expect(payload).to.have.property('r', '22edbae2733bf6'); }); it('auids must not be duplicated', () => { @@ -91,6 +92,7 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43,45'); + expect(payload).to.have.property('r', '22edbae2733bf6'); }); it('pt parameter must be "gross" if params.priceType === "gross"', () => { @@ -101,6 +103,7 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'gross'); expect(payload).to.have.property('auids', '43,45'); + expect(payload).to.have.property('r', '22edbae2733bf6'); delete bidRequests[1].params.priceType; }); @@ -112,6 +115,7 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43,45'); + expect(payload).to.have.property('r', '22edbae2733bf6'); delete bidRequests[1].params.priceType; }); }); From 46dfc43ef0fb9ad9f8cbc578904c6a78d60b8363 Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Wed, 3 Jan 2018 14:00:13 -0500 Subject: [PATCH 0027/1594] Serverbid Bid Adapter: Add new ad sizes (#1983) --- modules/serverbidBidAdapter.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index e77d7f32a35..d120e5c4306 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -176,6 +176,11 @@ const sizeMap = [ sizeMap[77] = '970x90'; sizeMap[123] = '970x250'; sizeMap[43] = '300x600'; +sizeMap[286] = '970x66'; +sizeMap[3230] = '970x280'; +sizeMap[429] = '486x60'; +sizeMap[374] = '700x500'; +sizeMap[934] = '300x1050'; function getSize(sizes) { const result = []; From 569a3d14d1e0b50359236101470aab025a007b9d Mon Sep 17 00:00:00 2001 From: Valentin Zhukovsky Date: Thu, 4 Jan 2018 03:41:07 +0300 Subject: [PATCH 0028/1594] Added dynamic ttl property for One Display and One Mobile. (#2004) --- modules/aolBidAdapter.js | 12 ++++++++---- test/spec/modules/aolBidAdapter_spec.js | 19 +++++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 71b1e4f7902..9b4aa26e1a1 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -39,7 +39,8 @@ const MP_SERVER_MAP = { as: 'adserver-as.adtech.advertising.com' }; const NEXAGE_SERVER = 'hb.nexage.com'; -const BID_RESPONSE_TTL = 300; +const ONE_DISPLAY_TTL = 60; +const ONE_MOBILE_TTL = 3600; $$PREBID_GLOBAL$$.aolGlobals = { pixelsDropped: false @@ -224,7 +225,7 @@ function _parseBidResponse(response, bidRequest) { currency: response.cur, dealId: bidData.dealid, netRevenue: true, - ttl: BID_RESPONSE_TTL + ttl: bidRequest.ttl }; } @@ -274,14 +275,16 @@ function formatBidRequest(endpointCode, bid) { case AOL_ENDPOINTS.DISPLAY.GET: bidRequest = { url: _buildMarketplaceUrl(bid), - method: 'GET' + method: 'GET', + ttl: ONE_DISPLAY_TTL }; break; case AOL_ENDPOINTS.MOBILE.GET: bidRequest = { url: _buildOneMobileGetUrl(bid), - method: 'GET' + method: 'GET', + ttl: ONE_MOBILE_TTL }; break; @@ -289,6 +292,7 @@ function formatBidRequest(endpointCode, bid) { bidRequest = { url: _buildOneMobileBaseUrl(bid), method: 'POST', + ttl: ONE_MOBILE_TTL, data: bid.params, options: { contentType: 'application/json', diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index d05f21a7be4..109c5bf2a0f 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -74,8 +74,10 @@ let getPixels = () => { }; describe('AolAdapter', () => { - const MARKETPLACE_URL = 'adserver-us.adtech.advertising.com/pubapi/3.0/'; - const NEXAGE_URL = 'hb.nexage.com/bidRequest?'; + const MARKETPLACE_URL = '//adserver-us.adtech.advertising.com/pubapi/3.0/'; + const NEXAGE_URL = '//hb.nexage.com/bidRequest?'; + const ONE_DISPLAY_TTL = 60; + const ONE_MOBILE_TTL = 3600; function createCustomBidRequest({bids, params} = {}) { var bidderRequest = getDefaultBidRequest(); @@ -98,7 +100,8 @@ describe('AolAdapter', () => { bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; bidRequest = { bidderCode: 'test-bidder-code', - bidId: 'bid-id' + bidId: 'bid-id', + ttl: 1234 }; bidResponse = { body: getDefaultBidResponse() @@ -125,7 +128,7 @@ describe('AolAdapter', () => { currency: 'USD', dealId: 'deal-id', netRevenue: true, - ttl: 300 + ttl: bidRequest.ttl }); }); @@ -355,6 +358,13 @@ describe('AolAdapter', () => { let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).to.contain('kvage=25;kvheight=3.42;kvtest=key'); }); + + it('should return request object for One Display when configuration is present', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.method).to.equal('GET'); + expect(request.ttl).to.equal(ONE_DISPLAY_TTL); + }); }); describe('One Mobile', () => { @@ -454,6 +464,7 @@ describe('AolAdapter', () => { let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).to.contain(NEXAGE_URL); expect(request.method).to.equal('POST'); + expect(request.ttl).to.equal(ONE_MOBILE_TTL); expect(request.data).to.deep.equal(bidConfig); expect(request.options).to.deep.equal({ contentType: 'application/json', From 8e3047bf31ee4cca4d0fe257ea2de5e3d48e09fc Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 4 Jan 2018 08:54:48 -0700 Subject: [PATCH 0029/1594] pin gulp-connect at non-broken version (#2008) * pin gulp-connect at non-broken version * updated yarn.lock to specify pinned gulp-connect --- package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 661cbfc3495..b4ffaecda35 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", - "gulp-connect": "^5.0.0", + "gulp-connect": "5.0.0", "gulp-documentation": "^3.2.1", "gulp-eslint": "^4.0.0", "gulp-footer": "^1.0.5", diff --git a/yarn.lock b/yarn.lock index a21ba77b901..28d570aa6fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3770,7 +3770,7 @@ gulp-concat@^2.6.0: through2 "^2.0.0" vinyl "^2.0.0" -gulp-connect@^5.0.0: +gulp-connect@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/gulp-connect/-/gulp-connect-5.0.0.tgz#f2fdf306ae911468368c2285f2d782f13eddaf4e" dependencies: From be43c55c07175d3cd95ebbd0a8712ab9274e258b Mon Sep 17 00:00:00 2001 From: agon-qurdina <34247167+agon-qurdina@users.noreply.github.com> Date: Thu, 4 Jan 2018 20:21:14 +0100 Subject: [PATCH 0030/1594] Gjirafa Bidder Adapter (#1944) * Added Gjirafa adapter * Add gjirafa adapter unit test * adapter update * New line * Requested changes * change hello_world.html to one bid * change hello_world.html to one bid * Dropping changes in gitignore and hello_world example * hello_world changes * Drop hello_world and gitignore --- modules/gjirafaBidAdapter.js | 91 ++++++++++++ modules/gjirafaBidAdapter.md | 36 +++++ test/spec/modules/gjirafaBidAdapter_spec.js | 156 ++++++++++++++++++++ 3 files changed, 283 insertions(+) create mode 100644 modules/gjirafaBidAdapter.js create mode 100644 modules/gjirafaBidAdapter.md create mode 100644 test/spec/modules/gjirafaBidAdapter_spec.js diff --git a/modules/gjirafaBidAdapter.js b/modules/gjirafaBidAdapter.js new file mode 100644 index 00000000000..3fbc7d772fa --- /dev/null +++ b/modules/gjirafaBidAdapter.js @@ -0,0 +1,91 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'gjirafa'; +const ENDPOINT_URL = 'https://gjc.gjirafa.com/Home/GetBid'; +const DIMENSION_SEPARATOR = 'x'; +const SIZE_SEPARATOR = ';'; + +export const spec = { + code: BIDDER_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 bid.params && (!!bid.params.placementId || (!!bid.params.minCPM && !!bid.params.minCPC)); + }, + /** + * 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 => { + let gjid = Math.floor(Math.random() * 99999999); + let sizes = generateSizeParam(bidRequest.sizes); + let configId = bidRequest.params.placementId || ''; + let minCPM = bidRequest.params.minCPM || 0.0; + let minCPC = bidRequest.params.minCPC || 0.0; + let allowExplicit = bidRequest.params.explicit || 0; + const body = { + gjid: gjid, + sizes: sizes, + configId: configId, + minCPM: minCPM, + minCPC: minCPC, + allowExplicit: allowExplicit, + referrer: utils.getTopWindowUrl(), + requestid: bidRequest.bidderRequestId, + bidid: bidRequest.bidId + }; + if (document.referrer) { + body.referrer = document.referrer; + } + return { + method: 'GET', + url: ENDPOINT_URL, + data: body + }; + }); + }, + /** + * 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 = []; + const bidResponse = { + requestId: bidRequest.data.bidid, + cpm: serverBody.CPM, + width: serverBody.Width, + height: serverBody.Height, + creativeId: serverBody.CreativeId, + currency: serverBody.Currency, + netRevenue: serverBody.NetRevenue, + ttl: serverBody.TTL, + referrer: serverBody.Referrer, + ad: serverBody.Ad + }; + bidResponses.push(bidResponse); + return bidResponses; + } +} + +/** +* Generate size param for bid request using sizes array +* +* @param {Array} sizes Possible sizes for the ad unit. +* @return {string} Processed sizes param to be used for the bid request. +*/ +function generateSizeParam(sizes) { + return sizes.map(size => size.join(DIMENSION_SEPARATOR)).join(SIZE_SEPARATOR); +} + +registerBidder(spec); diff --git a/modules/gjirafaBidAdapter.md b/modules/gjirafaBidAdapter.md new file mode 100644 index 00000000000..1ec8222d8de --- /dev/null +++ b/modules/gjirafaBidAdapter.md @@ -0,0 +1,36 @@ +# Overview +Module Name: Gjirafa Bidder Adapter Module +Type: Bidder Adapter +Maintainer: agonq@gjirafa.com + +# Description +Gjirafa Bidder Adapter for Prebid.js. + +# Test Parameters +var adUnits = [ +{ + code: 'test-div', + sizes: [[728, 90]], // leaderboard + bids: [ + { + bidder: 'gjirafa', + params: { + placementId: '71-3' + } + } + ] +},{ + code: 'test-div', + sizes: [[300, 250]], // mobile rectangle + bids: [ + { + bidder: 'gjirafa', + params: { + minCPM: 0.0001, + minCPC: 0.001, + explicit: true + } + } + ] +} +]; \ No newline at end of file diff --git a/test/spec/modules/gjirafaBidAdapter_spec.js b/test/spec/modules/gjirafaBidAdapter_spec.js new file mode 100644 index 00000000000..17fbdc33591 --- /dev/null +++ b/test/spec/modules/gjirafaBidAdapter_spec.js @@ -0,0 +1,156 @@ +import { expect } from 'chai'; +import { spec } from 'modules/gjirafaBidAdapter'; + +describe('gjirafaAdapterTest', () => { + describe('bidRequestValidity', () => { + it('bidRequest with placementId, minCPM and minCPC params', () => { + expect(spec.isBidRequestValid({ + bidder: 'gjirafa', + params: { + placementId: 'test-div', + minCPM: 0.0001, + minCPC: 0.001 + } + })).to.equal(true); + }); + + it('bidRequest with only placementId param', () => { + expect(spec.isBidRequestValid({ + bidder: 'gjirafa', + params: { + placementId: 'test-div' + } + })).to.equal(true); + }); + + it('bidRequest with minCPM and minCPC params', () => { + expect(spec.isBidRequestValid({ + bidder: 'gjirafa', + params: { + minCPM: 0.0001, + minCPC: 0.001 + } + })).to.equal(true); + }); + + it('bidRequest with no placementId, minCPM or minCPC params', () => { + expect(spec.isBidRequestValid({ + bidder: 'gjirafa', + params: { + } + })).to.equal(false); + }); + }); + + describe('bidRequest', () => { + const bidRequests = [{ + 'bidder': 'gjirafa', + 'params': { + 'placementId': '71-3' + }, + 'adUnitCode': 'hb-leaderboard', + 'transactionId': 'b6b889bb-776c-48fd-bc7b-d11a1cf0425e', + 'sizes': [[728, 90], [980, 200], [980, 150], [970, 90], [970, 250]], + 'bidId': '10bdc36fe0b48c8', + 'bidderRequestId': '70deaff71c281d', + 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc' + }, + { + 'bidder': 'gjirafa', + 'params': { + 'minCPM': 0.0001, + 'minCPC': 0.001, + 'explicit': true + }, + 'adUnitCode': 'hb-inarticle', + 'transactionId': '8757194d-ea7e-4c06-abc0-cfe92bfc5295', + 'sizes': [[300, 250]], + 'bidId': '81a6dcb65e2bd9', + 'bidderRequestId': '70deaff71c281d', + 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc' + }]; + + it('bidRequest HTTP method', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + }); + }); + + it('bidRequest url', () => { + const endpointUrl = 'https://gjc.gjirafa.com/Home/GetBid'; + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.url).to.match(new RegExp(`${endpointUrl}`)); + }); + }); + + it('bidRequest data', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.data).to.exists; + }); + }); + + it('bidRequest sizes', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].data.sizes).to.equal('728x90;980x200;980x150;970x90;970x250'); + expect(requests[1].data.sizes).to.equal('300x250'); + }); + }); + + describe('interpretResponse', () => { + const bidRequest = { + 'method': 'GET', + 'url': 'https://gjc.gjirafa.com/Home/GetBid', + 'data': { + 'gjid': 2323007, + 'sizes': '728x90;980x200;980x150;970x90;970x250', + 'configId': '71-3', + 'minCPM': 0, + 'minCPC': 0, + 'allowExplicit': 0, + 'referrer': 'http://localhost:9999/integrationExamples/gpt/hello_world.html?pbjs_debug=true', + 'requestid': '26ee8fe87940da7', + 'bidid': '2962dbedc4768bf' + } + }; + + const bidResponse = { + body: [{ + 'CPM': 1, + 'Width': 728, + 'Height': 90, + 'Referrer': 'https://example.com/', + 'Ad': 'test ad', + 'CreativeId': '123abc', + 'NetRevenue': false, + 'Currency': 'EUR', + 'TTL': 360 + }], + headers: {} + }; + + it('all keys present', () => { + const result = spec.interpretResponse(bidResponse, bidRequest); + + let keys = [ + 'requestId', + 'cpm', + 'width', + 'height', + 'creativeId', + 'currency', + 'netRevenue', + 'ttl', + 'referrer', + 'ad' + ]; + + let resultKeys = Object.keys(result[0]); + resultKeys.forEach(function(key) { + expect(keys.indexOf(key) !== -1).to.equal(true); + }); + }) + }); +}); From 87ae6ce062aa4d99cfee2c2dab466de8e17db22d Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Fri, 5 Jan 2018 13:31:02 -0500 Subject: [PATCH 0031/1594] multiformat size validation checks (#1964) * initial commit for multiformat size validation checks * adding unit tests and changes to checkBidRequestSizes function * updates to appnexusBidAdapter --- modules/appnexusBidAdapter.js | 24 +-- src/adaptermanager.js | 51 ++++++ src/native.js | 12 ++ test/spec/native_spec.js | 112 +++++++++++- test/spec/unit/core/adapterManager_spec.js | 188 +++++++++++++++++++++ 5 files changed, 376 insertions(+), 11 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index d46be776b59..7db2b9aab2f 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -216,20 +216,24 @@ function newBid(serverBid, rtbBid) { body: nativeAd.desc, cta: nativeAd.ctatext, sponsoredBy: nativeAd.sponsored, - image: { - url: nativeAd.main_img && nativeAd.main_img.url, - height: nativeAd.main_img && nativeAd.main_img.height, - width: nativeAd.main_img && nativeAd.main_img.width, - }, - icon: { - url: nativeAd.icon && nativeAd.icon.url, - height: nativeAd.icon && nativeAd.icon.height, - width: nativeAd.icon && nativeAd.icon.width, - }, clickUrl: nativeAd.link.url, clickTrackers: nativeAd.link.click_trackers, impressionTrackers: nativeAd.impression_trackers, }; + 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, diff --git a/src/adaptermanager.js b/src/adaptermanager.js index c8dc72e7ddc..5577ffc6fca 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -149,6 +149,9 @@ function getAdUnitCopyForClientAdapters(adUnits) { exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, labels) { let bidRequests = []; + + adUnits = exports.checkBidRequestSizes(adUnits); + let bidderCodes = getBidderCodes(adUnits); if (config.getConfig('bidderSequence') === RANDOM) { bidderCodes = shuffle(bidderCodes); @@ -211,6 +214,54 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, return bidRequests; }; +exports.checkBidRequestSizes = (adUnits) => { + Array.prototype.forEach.call(adUnits, adUnit => { + if (adUnit.sizes) { + utils.logWarn('Usage of adUnits.sizes will eventually be deprecated. Please define size dimensions within the corresponding area of the mediaTypes. (eg mediaTypes.banner.sizes).'); + } + + const mediaTypes = adUnit.mediaTypes; + if (mediaTypes && mediaTypes.banner) { + const banner = mediaTypes.banner; + if (banner.sizes) { + adUnit.sizes = banner.sizes; + } else { + utils.logError('Detected a mediaTypes.banner object did not include sizes. This is a required field for the mediaTypes.banner object. Removing invalid mediaTypes.banner object from request.'); + delete adUnit.mediaTypes.banner; + } + } + + if (mediaTypes && mediaTypes.video) { + const video = mediaTypes.video; + if (video.playerSize) { + if (Array.isArray(video.playerSize) && video.playerSize.length === 2 && Number.isInteger(video.playerSize[0]) && Number.isInteger(video.playerSize[1])) { + adUnit.sizes = video.playerSize; + } else { + 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 adUnit.mediaTypes.video.playerSize; + } + } + } + + if (mediaTypes && mediaTypes.native) { + const native = mediaTypes.native; + if (native.image && native.image.sizes && !Array.isArray(native.image.sizes)) { + utils.logError('Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request.'); + delete adUnit.mediaTypes.native.image.sizes; + } + if (native.image && native.image.aspect_ratios && !Array.isArray(native.image.aspect_ratios)) { + 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 adUnit.mediaTypes.native.image.aspect_ratios; + } + if (native.icon && native.icon.sizes && !Array.isArray(native.icon.sizes)) { + utils.logError('Please use an array of sizes for native.icon.sizes field. Removing invalid mediaTypes.native.icon.sizes property from request.'); + delete adUnit.mediaTypes.native.icon.sizes; + } + } + }); + return adUnits; +} + exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { if (!bidRequests.length) { utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); diff --git a/src/native.js b/src/native.js index bfe4b64405d..6c8ac266471 100644 --- a/src/native.js +++ b/src/native.js @@ -85,6 +85,18 @@ export function nativeBidIsValid(bid, bidRequests) { return false; } + if (deepAccess(bid, 'native.image')) { + if (!deepAccess(bid, 'native.image.height') || !deepAccess(bid, 'native.image.width')) { + return false; + } + } + + if (deepAccess(bid, 'native.icon')) { + if (!deepAccess(bid, 'native.icon.height') || !deepAccess(bid, 'native.icon.width')) { + return false; + } + } + const requestedAssets = bidRequest.nativeParams; if (!requestedAssets) { return true; diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 977575a4d19..fa57ceed5f5 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { fireNativeTrackers, getNativeTargeting } from 'src/native'; +import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid } from 'src/native'; const utils = require('src/utils'); const bid = { @@ -44,3 +44,113 @@ describe('native.js', () => { sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]); }); }); + +describe('validate native', () => { + 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: 'test_bid_id', + adUnitCode: '123/prebid_native_adunit', + bidder: 'test_bidder', + native: { + body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.', + clickTrackers: ['http://my.click.tracker/url'], + icon: { + url: 'http://my.image.file/ad_image.jpg', + height: 75, + width: 75 + }, + image: { + url: 'http://my.icon.file/ad_icon.jpg', + height: 2250, + width: 3000 + }, + clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html', + impressionTrackers: ['http://my.imp.tracker/url'], + title: 'This is an example Prebid Native creative' + } + }; + + let noIconDimBid = { + adId: 'test_bid_id', + adUnitCode: '123/prebid_native_adunit', + bidder: 'test_bidder', + native: { + body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.', + clickTrackers: ['http://my.click.tracker/url'], + icon: { + url: 'http://my.image.file/ad_image.jpg', + height: 0, + width: 0 + }, + image: { + url: 'http://my.icon.file/ad_icon.jpg', + height: 2250, + width: 3000 + }, + clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html', + impressionTrackers: ['http://my.imp.tracker/url'], + title: 'This is an example Prebid Native creative' + } + }; + + let noImgDimBid = { + adId: 'test_bid_id', + adUnitCode: '123/prebid_native_adunit', + bidder: 'test_bidder', + native: { + body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.', + clickTrackers: ['http://my.click.tracker/url'], + icon: { + url: 'http://my.image.file/ad_image.jpg', + height: 75, + width: 75 + }, + image: { + url: 'http://my.icon.file/ad_icon.jpg', + height: 0, + width: 0 + }, + clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html', + impressionTrackers: ['http://my.imp.tracker/url'], + title: 'This is an example Prebid Native creative' + } + }; + + beforeEach(() => {}); + + afterEach(() => {}); + + it('should reject bid if no image sizes are defined', () => { + let result = nativeBidIsValid(validBid, bidReq); + expect(result).to.be.true; + result = nativeBidIsValid(noIconDimBid, bidReq); + expect(result).to.be.false; + result = nativeBidIsValid(noImgDimBid, bidReq); + expect(result).to.be.false; + }); +}); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 1732716c6a4..bba404448a0 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -1,5 +1,6 @@ import { expect } from 'chai'; import AdapterManager from 'src/adaptermanager'; +import { checkBidRequestSizes } from 'src/adaptermanager'; import { getAdUnits } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; @@ -816,4 +817,191 @@ describe('adapterManager tests', () => { }) }); }); + + describe('isValidBidRequest', () => { + describe('positive tests for validating bid request', () => { + beforeEach(() => {}); + + afterEach(() => {}); + it('should main adUnit structure and adUnits.sizes is replaced', () => { + let fullAdUnit = [{ + sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + playerSize: [640, 480] + }, + native: { + image: { + sizes: [150, 150], + aspect_ratios: [140, 140] + }, + icon: { + sizes: [75, 75] + } + } + } + }]; + let result = checkBidRequestSizes(fullAdUnit); + expect(result[0].sizes).to.deep.equal([640, 480]); + expect(result[0].mediaTypes.video.playerSize).to.deep.equal([640, 480]); + expect(result[0].mediaTypes.native.image.sizes).to.deep.equal([150, 150]); + expect(result[0].mediaTypes.native.icon.sizes).to.deep.equal([75, 75]); + expect(result[0].mediaTypes.native.image.aspect_ratios).to.deep.equal([140, 140]); + + let noOptnlFieldAdUnit = [{ + sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + context: 'outstream' + }, + native: { + image: { + required: true + }, + icon: { + required: true + } + } + } + }]; + result = checkBidRequestSizes(noOptnlFieldAdUnit); + expect(result[0].sizes).to.deep.equal([[300, 250]]); + expect(result[0].mediaTypes.video).to.exist; + + let mixedAdUnit = [{ + sizes: [[300, 250], [300, 600]], + mediaTypes: { + video: { + context: 'outstream', + playerSize: [400, 350] + }, + native: { + image: { + aspect_ratios: [200, 150], + required: true + } + } + } + }]; + result = checkBidRequestSizes(mixedAdUnit); + expect(result[0].sizes).to.deep.equal([400, 350]); + expect(result[0].mediaTypes.video).to.exist; + }); + }); + + describe('negative tests for validating bid requests', () => { + beforeEach(() => { + sinon.stub(utils, 'logError'); + }); + + afterEach(() => { + utils.logError.restore(); + }); + + it('should throw error message and delete an object/property', () => { + let badBanner = [{ + sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + name: 'test' + } + } + }]; + let result = checkBidRequestSizes(badBanner); + expect(result[0].sizes).to.deep.equal([[300, 250], [300, 600]]); + expect(result[0].mediaTypes.banner).to.be.undefined; + sinon.assert.called(utils.logError); + + let badVideo1 = [{ + sizes: [[600, 600]], + mediaTypes: { + video: { + playerSize: '600x400' + } + } + }]; + result = checkBidRequestSizes(badVideo1); + expect(result[0].sizes).to.deep.equal([[600, 600]]); + expect(result[0].mediaTypes.video.playerSize).to.be.undefined; + expect(result[0].mediaTypes.video).to.exist; + sinon.assert.called(utils.logError); + + let badVideo2 = [{ + sizes: [[600, 600]], + mediaTypes: { + video: { + playerSize: ['300', '200'] + } + } + }]; + result = checkBidRequestSizes(badVideo2); + expect(result[0].sizes).to.deep.equal([[600, 600]]); + expect(result[0].mediaTypes.video.playerSize).to.be.undefined; + expect(result[0].mediaTypes.video).to.exist; + sinon.assert.called(utils.logError); + + let badVideo3 = [{ + sizes: [[600, 600]], + mediaTypes: { + video: { + playerSize: [[640, 480]] + } + } + }]; + result = checkBidRequestSizes(badVideo3); + expect(result[0].sizes).to.deep.equal([[600, 600]]); + expect(result[0].mediaTypes.video.playerSize).to.be.undefined; + expect(result[0].mediaTypes.video).to.exist; + sinon.assert.called(utils.logError); + + let badNativeImgSize = [{ + mediaTypes: { + native: { + image: { + sizes: '300x250' + } + } + } + }]; + result = checkBidRequestSizes(badNativeImgSize); + expect(result[0].mediaTypes.native.image.sizes).to.be.undefined; + expect(result[0].mediaTypes.native.image).to.exist; + sinon.assert.called(utils.logError); + + let badNativeImgAspRat = [{ + mediaTypes: { + native: { + image: { + aspect_ratios: '300x250' + } + } + } + }]; + result = checkBidRequestSizes(badNativeImgAspRat); + expect(result[0].mediaTypes.native.image.aspect_ratios).to.be.undefined; + expect(result[0].mediaTypes.native.image).to.exist; + sinon.assert.called(utils.logError); + + let badNativeIcon = [{ + mediaTypes: { + native: { + icon: { + sizes: '300x250' + } + } + } + }]; + result = checkBidRequestSizes(badNativeIcon); + expect(result[0].mediaTypes.native.icon.sizes).to.be.undefined; + expect(result[0].mediaTypes.native.icon).to.exist; + sinon.assert.called(utils.logError); + }); + }); + }); }); From 00e8e92552a909139f79ab6e1bf8cf3926326828 Mon Sep 17 00:00:00 2001 From: Galphimbl Date: Tue, 9 Jan 2018 00:04:57 +0200 Subject: [PATCH 0032/1594] Upgrade Admixer adapter for Prebid 1.0 (#1755) * Migrating to Prebid 1.0 * Migrating to Prebid 1.0 * Fix spec --- modules/admixerBidAdapter.js | 74 +++++++++++++ modules/admixerBidAdapter.md | 52 +++++++++ test/spec/modules/admixerBidAdapter_spec.js | 117 ++++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 modules/admixerBidAdapter.js create mode 100644 modules/admixerBidAdapter.md create mode 100644 test/spec/modules/admixerBidAdapter_spec.js diff --git a/modules/admixerBidAdapter.js b/modules/admixerBidAdapter.js new file mode 100644 index 00000000000..6851a7d3bd5 --- /dev/null +++ b/modules/admixerBidAdapter.js @@ -0,0 +1,74 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'admixer'; +const ENDPOINT_URL = '//inv-nets.admixer.net/prebid.1.0.aspx'; +export const spec = { + code: BIDDER_CODE, + aliases: [], + 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) { + return !!bid.params.zone; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {bidderRequest} - bidderRequest.bids[] is an array of AdUnits and bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (bidderRequest) { + const payload = { + imps: [], + referrer: utils.getTopWindowUrl(), + }; + bidderRequest.forEach((bid) => { + if (bid.bidder === BIDDER_CODE) { + payload.imps.push(bid); + } + }); + const payloadString = JSON.stringify(payload); + return { + method: 'GET', + url: ENDPOINT_URL, + data: `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, bidRequest) { + const bidResponses = []; + // loop through serverResponses { + try { + serverResponse = serverResponse.body; + serverResponse.forEach((bidResponse) => { + const bidResp = { + requestId: bidResponse.bidId, + cpm: bidResponse.cpm, + width: bidResponse.width, + height: bidResponse.height, + ad: bidResponse.ad, + ttl: bidResponse.ttl, + creativeId: bidResponse.creativeId, + netRevenue: bidResponse.netRevenue, + currency: bidResponse.currency, + vastUrl: bidResponse.vastUrl, + }; + bidResponses.push(bidResp); + }); + } catch (e) { + utils.logError(e); + } + return bidResponses; + } +}; +registerBidder(spec); diff --git a/modules/admixerBidAdapter.md b/modules/admixerBidAdapter.md new file mode 100644 index 00000000000..682f5629115 --- /dev/null +++ b/modules/admixerBidAdapter.md @@ -0,0 +1,52 @@ +# Overview + +Module Name: Admixer Bidder Adapter +Module Type: Bidder Adapter +Maintainer: contact@admixer.net + +# Description + +Connects to Admixer demand source to fetch bids. +Banner and Video formats are supported. +Please use ```admixer``` as the bidder code. + +# Test Parameters +``` + var adUnits = [ + { + code: 'desktop-banner-ad-div', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "admixer", + params: { + zone: '2eb6bd58-865c-47ce-af7f-a918108c3fd2' + } + } + ] + },{ + code: 'mobile-banner-ad-div', + sizes: [[300, 50]], // a mobile size + bids: [ + { + bidder: "admixer", + params: { + zone: '62211486-c50b-4356-9f0f-411778d31fcc' + } + } + ] + },{ + code: 'video-ad', + sizes: [[300, 50]], + mediaType: 'video', + bids: [ + { + bidder: "admixer", + params: { + zone: 'ebeb1e79-8cb4-4473-b2d0-2e24b7ff47fd' + } + } + ] + }, + ]; +``` diff --git a/test/spec/modules/admixerBidAdapter_spec.js b/test/spec/modules/admixerBidAdapter_spec.js new file mode 100644 index 00000000000..13312e3d24e --- /dev/null +++ b/test/spec/modules/admixerBidAdapter_spec.js @@ -0,0 +1,117 @@ +import {expect} from 'chai'; +import {spec} from 'modules/admixerBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'admixer'; +const ENDPOINT_URL = '//inv-nets.admixer.net/prebid.1.0.aspx'; +const ZONE_ID = '2eb6bd58-865c-47ce-af7f-a918108c3fd2'; + +describe('AdmixerAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.be.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': BIDDER_CODE, + 'params': { + 'zone': ZONE_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'zone': ZONE_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should add referrer and imp to be equal bidRequest', () => { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data.substr(5)); + expect(payload.referrer).to.not.be.undefined; + expect(payload.imps[0]).to.deep.equal(bidRequests[0]); + }); + + it('sends bid request to ENDPOINT via GET', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT_URL); + expect(request.method).to.equal('GET'); + }); + }); + + describe('interpretResponse', () => { + let response = { + body: [{ + 'currency': 'USD', + 'cpm': 6.210000, + 'ad': '
ad
', + 'width': 300, + 'height': 600, + 'creativeId': 'ccca3e5e-0c54-4761-9667-771322fbdffc', + 'ttl': 360, + 'netRevenue': false, + 'bidId': '5e4e763b6bc60b' + }] + }; + + it('should get correct bid response', () => { + const body = response.body; + let expectedResponse = [ + { + 'requestId': body[0].bidId, + 'cpm': body[0].cpm, + 'creativeId': body[0].creativeId, + 'width': body[0].width, + 'height': body[0].height, + 'ad': body[0].ad, + 'vastUrl': undefined, + 'currency': body[0].currency, + 'netRevenue': body[0].netRevenue, + 'ttl': body[0].ttl, + } + ]; + + let result = spec.interpretResponse(response); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + it('handles nobid responses', () => { + let response = []; + + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From 9f3f16f4e8b5ce6076e7462401bd75bfb24a84e6 Mon Sep 17 00:00:00 2001 From: Pupis Date: Wed, 10 Jan 2018 03:46:36 +0200 Subject: [PATCH 0033/1594] Update Adform adapter to Prebid v1.0 (#1947) * test * update adform bid adapter * update unit tests * Added adform adapter description file * updated tests * Another tests update * add auctionId to adformBidAdapter * Final updates to fit 1.0 version * update docs and integration example * Do not mutate original validBidRequests * use atob and btoa instead of custom made module * Renaming one query string parameter --- integrationExamples/gpt/pbjs_example_gpt.html | 2 +- modules/adformBidAdapter.js | 107 ++++++++ modules/adformBidAdapter.md | 30 +++ test/spec/modules/adformBidAdapter_spec.js | 246 ++++++++++++++++++ 4 files changed, 384 insertions(+), 1 deletion(-) create mode 100644 modules/adformBidAdapter.js create mode 100644 modules/adformBidAdapter.md create mode 100644 test/spec/modules/adformBidAdapter_spec.js diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index 2e5c798e218..f1ec912fd26 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -116,7 +116,7 @@ }, { bidder: 'adform', - // available params: [ 'mid', 'inv', 'pdom', 'mname', 'mkw', 'mkv', 'cat', 'bcat', 'bcatrt', 'adv', 'advt', 'cntr', 'cntrt', 'maxp', 'minp', 'sminp', 'w', 'h', 'pb', 'pos', 'cturl', 'iturl', 'cttype', 'hidedomain', 'cdims', 'test' ] + // available params: [ 'mid', 'inv', 'pdom', 'mname', 'mkw', 'mkv', 'cat', 'bcat', 'bcatrt', 'adv', 'advt', 'cntr', 'cntrt', 'maxp', 'minp', 'sminp', 'w', 'h', 'pb', 'pos', 'cturl', 'iturl', 'cttype', 'hidedomain', 'cdims', 'test', priceType ] params: { adxDomain: 'adx.adform.net', //optional mid: 158989, diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js new file mode 100644 index 00000000000..6dba55f88a7 --- /dev/null +++ b/modules/adformBidAdapter.js @@ -0,0 +1,107 @@ +'use strict'; + +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'adform'; +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [], + isBidRequestValid: function (bid) { + return !!(bid.params.mid); + }, + buildRequests: function (validBidRequests) { + var i, l, j, k, bid, _key, _value, reqParams; + var request = []; + var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ] ]; + var netRevenue = 'net'; + var bids = JSON.parse(JSON.stringify(validBidRequests)); + for (i = 0, l = bids.length; i < l; i++) { + bid = bids[i]; + if (bid.params.priceType === 'gross') { + netRevenue = 'gross'; + } + for (j = 0, k = globalParams.length; j < k; j++) { + _key = globalParams[j][0]; + _value = bid[_key] || bid.params[_key]; + if (_value) { + bid[_key] = bid.params[_key] = null; + globalParams[j][1] = _value; + } + } + reqParams = bid.params; + reqParams.transactionId = bid.transactionId; + request.push(formRequestUrl(reqParams)); + } + + request.unshift('//' + globalParams[0][1] + '/adx/?rp=4'); + + request.push('stid=' + validBidRequests[0].requestId); + + for (i = 1, l = globalParams.length; i < l; i++) { + _key = globalParams[i][0]; + _value = globalParams[i][1]; + if (_value) { + request.push(_key + '=' + encodeURIComponent(_value)); + } + } + + return { + method: 'GET', + url: request.join('&'), + bids: validBidRequests, + netRevenue: netRevenue, + bidder: 'adform' + }; + + function formRequestUrl(reqData) { + var key; + var url = []; + + for (key in reqData) { + if (reqData.hasOwnProperty(key) && reqData[key]) { url.push(key, '=', reqData[key], '&'); } + } + + return encodeURIComponent(btoa(url.join('').slice(0, -1))); + } + }, + interpretResponse: function (serverResponse, bidRequest) { + var bidObject, response, bid; + var bidRespones = []; + var bids = bidRequest.bids; + var responses = serverResponse.body; + for (var i = 0; i < responses.length; i++) { + response = responses[i]; + bid = bids[i]; + if (response.response === 'banner' && verifySize(response, bid.sizes)) { + bidObject = { + requestId: bid.bidId, + cpm: response.win_bid, + width: response.width, + height: response.height, + creativeId: bid.bidId, + dealId: response.deal_id, + currency: response.win_cur, + netRevenue: bidRequest.netRevenue !== 'gross', + ttl: 360, + ad: response.banner, + bidderCode: bidRequest.bidder, + transactionId: bid.transactionId + }; + bidRespones.push(bidObject); + } + } + + return bidRespones; + + function verifySize(adItem, validSizes) { + for (var j = 0, k = validSizes.length; j < k; j++) { + if (adItem.width === validSizes[j][0] && + adItem.height === validSizes[j][1]) { + return true; + } + } + return false; + } + } +}; +registerBidder(spec); diff --git a/modules/adformBidAdapter.md b/modules/adformBidAdapter.md new file mode 100644 index 00000000000..9f357b21729 --- /dev/null +++ b/modules/adformBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +Module Name: Adform Bidder Adapter +Module Type: Bidder Adapter +Maintainer: Scope.FL.Scripts@adform.com + +# Description + +Module that connects to Adform demand sources to fetch bids. +Banner formats are supported. + +# Test Parameters +``` + var adUnits = [ + { + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], // a display size + bids: [ + { + bidder: "adform", + params: { + adxDomain: 'adx.adform.net', //optional + mid: '292063', + priceType: 'gross' // default is 'net' + } + } + ] + }, + ]; +``` diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js new file mode 100644 index 00000000000..72f625d08c6 --- /dev/null +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -0,0 +1,246 @@ +import {assert, expect} from 'chai'; +import * as url from 'src/url'; +import {spec} from 'modules/adformBidAdapter'; + +describe('Adform adapter', () => { + let serverResponse, bidRequest, bidResponses; + let bids = []; + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'adform', + 'params': { + 'mid': '19910113' + } + }; + + it('should return true when required params found', () => { + assert(spec.isBidRequestValid(bid)); + }); + + it('should return false when required params are missing', () => { + bid.params = { + adxDomain: 'adx.adform.net' + }; + assert.isFalse(spec.isBidRequestValid(bid)); + }) + }); + + describe('buildRequests', () => { + it('should pass multiple bids via single request', () => { + let request = spec.buildRequests(bids); + let parsedUrl = parseUrl(request.url); + assert.lengthOf(parsedUrl.items, 3); + }); + + it('should handle global request parameters', () => { + let parsedUrl = parseUrl(spec.buildRequests([bids[0]]).url); + let query = parsedUrl.query; + + assert.equal(parsedUrl.path, '//newDomain/adx'); + assert.equal(query.tid, 45); + assert.equal(query.rp, 4); + assert.equal(query.fd, 1); + assert.equal(query.stid, '7aefb970-2045'); + assert.equal(query.url, encodeURIComponent('some// there')); + }); + + it('should set correct request method', () => { + let request = spec.buildRequests([bids[0]]); + assert.equal(request.method, 'GET'); + }); + + it('should correctly form bid items', () => { + let bidList = bids; + let request = spec.buildRequests(bidList); + let parsedUrl = parseUrl(request.url); + assert.deepEqual(parsedUrl.items, [ + { + mid: '1', + transactionId: '5f33781f-9552-4ca1' + }, + { + mid: '2', + someVar: 'someValue', + transactionId: '5f33781f-9552-4iuy', + priceType: 'gross' + }, + { + mid: '3', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + } + ]); + }); + + it('should not change original validBidRequests object', () => { + var resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]]); + assert.deepEqual(resultBids, bids[0]); + }); + }); + + describe('interpretResponse', () => { + it('should respond with empty response when there is empty serverResponse', () => { + let result = spec.interpretResponse({ body: {}}, {}); + assert.deepEqual(result, []); + }); + it('should respond with empty response when sizes doesn\'t match', () => { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 100; + serverResponse.body[0].height = 150; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(serverResponse.body.length, 1); + assert.equal(serverResponse.body[0].response, 'banner'); + assert.deepEqual(result, []); + }); + it('should respond with empty response when response from server is not banner', () => { + serverResponse.body[0].response = 'not banner'; + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.deepEqual(result, []); + }); + it('should interpret server response correctly with one bid', () => { + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest)[0]; + + assert.equal(result.requestId, '2a0cf4e'); + assert.equal(result.cpm, 13.9); + assert.equal(result.width, 300); + assert.equal(result.height, 250); + assert.equal(result.creativeId, '2a0cf4e'); + assert.equal(result.dealId, '123abc'); + assert.equal(result.currency, 'EUR'); + assert.equal(result.netRevenue, true); + assert.equal(result.ttl, 360); + assert.equal(result.ad, ''); + assert.equal(result.bidderCode, 'adform'); + assert.equal(result.transactionId, '5f33781f-9552-4ca1'); + }); + + it('should set correct netRevenue', () => { + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[1]]; + bidRequest.netRevenue = 'gross'; + let result = spec.interpretResponse(serverResponse, bidRequest)[0]; + + assert.equal(result.netRevenue, false); + }); + + it('should create bid response item for every requested item', () => { + let result = spec.interpretResponse(serverResponse, bidRequest); + assert.lengthOf(result, 3); + }); + }); + + beforeEach(() => { + let sizes = [[250, 300], [300, 250], [300, 600]]; + let adUnitCode = ['div-01', 'div-02', 'div-03']; + let placementCode = adUnitCode; + let params = [{ mid: 1, url: 'some// there' }, {adxDomain: null, mid: 2, someVar: 'someValue', priceType: 'gross'}, { adxDomain: null, mid: 3, pdom: 'home' }]; + bids = [ + { + adUnitCode: placementCode[0], + bidId: '2a0cf4e', + bidder: 'adform', + bidderRequestId: '1ab8d9', + params: params[0], + adxDomain: 'newDomain', + tid: 45, + placementCode: placementCode[0], + requestId: '7aefb970-2045', + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-4ca1' + }, + { + adUnitCode: placementCode[1], + bidId: '2a0cf5b', + bidder: 'adform', + bidderRequestId: '1ab8d9', + params: params[1], + placementCode: placementCode[1], + requestId: '7aefb970-2045', + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-4iuy' + }, + { + adUnitCode: placementCode[2], + bidId: '2a0cf6n', + bidder: 'adform', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + requestId: '7aefb970-2045', + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-7ev3' + } + ]; + serverResponse = { + body: [ + { + banner: '', + deal_id: '123abc', + height: 250, + response: 'banner', + width: 300, + win_bid: 13.9, + win_cur: 'EUR' + }, + { + banner: '', + deal_id: '123abc', + height: 300, + response: 'banner', + width: 250, + win_bid: 13.9, + win_cur: 'EUR' + }, + { + banner: '', + deal_id: '123abc', + height: 300, + response: 'banner', + width: 600, + win_bid: 10, + win_cur: 'EUR' + } + ], + headers: {} + }; + bidRequest = { + bidder: 'adform', + bids: bids, + method: 'GET', + url: 'url' + }; + }); +}); + +function parseUrl(url) { + const parts = url.split('/'); + const query = parts.pop().split('&'); + return { + path: parts.join('/'), + items: query + .filter((i) => !~i.indexOf('=')) + .map((i) => atob(decodeURIComponent(i)) + .split('&') + .reduce(toObject, {})), + query: query + .filter((i) => ~i.indexOf('=')) + .map((i) => i.replace('?', '')) + .reduce(toObject, {}) + }; +} + +function toObject(cache, string) { + const keyValue = string.split('='); + cache[keyValue[0]] = keyValue[1]; + return cache; +} From 6414a1f52b720009ed4fa9a4c2ab20039e5062bd Mon Sep 17 00:00:00 2001 From: NasmediaWebtech <34228109+NasmediaWebtech@users.noreply.github.com> Date: Wed, 10 Jan 2018 10:56:04 +0900 Subject: [PATCH 0034/1594] Add NasmediaAdmixer adapter for Perbid.js 1.0 (#1937) * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 --- modules/nasmediaAdmixerBidAdapter.js | 81 ++++++++++ modules/nasmediaAdmixerBidAdapter.md | 32 ++++ .../modules/nasmediaAdmixerBidAdapter_spec.js | 138 ++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 modules/nasmediaAdmixerBidAdapter.js create mode 100644 modules/nasmediaAdmixerBidAdapter.md create mode 100644 test/spec/modules/nasmediaAdmixerBidAdapter_spec.js diff --git a/modules/nasmediaAdmixerBidAdapter.js b/modules/nasmediaAdmixerBidAdapter.js new file mode 100644 index 00000000000..e4892f3d0ed --- /dev/null +++ b/modules/nasmediaAdmixerBidAdapter.js @@ -0,0 +1,81 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const ADMIXER_ENDPOINT = 'https://adn.admixer.co.kr:10443/prebid'; +const DEFAULT_BID_TTL = 360; +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_REVENUE = false; + +export const spec = { + code: 'nasmediaAdmixer', + + isBidRequestValid: function (bid) { + return !!(bid && bid.params && bid.params.ax_key); + }, + + buildRequests: function (validBidRequests) { + return validBidRequests.map(bid => { + let adSize = getSize(bid.sizes); + + return { + method: 'GET', + url: ADMIXER_ENDPOINT, + data: { + ax_key: utils.getBidIdParameter('ax_key', bid.params), + req_id: bid.bidId, + width: adSize.width, + height: adSize.height, + referrer: utils.getTopWindowUrl(), + os: getOsType() + } + } + }) + }, + + interpretResponse: function (serverResponse, bidRequest) { + const serverBody = serverResponse.body; + const bidResponses = []; + + if (serverBody && serverBody.error_code === 0 && serverBody.body && serverBody.body.length > 0) { + let bidData = serverBody.body[0]; + + const bidResponse = { + ad: bidData.ad, + requestId: serverBody.req_id, + creativeId: bidData.ad_id, + cpm: bidData.cpm, + width: bidData.width, + height: bidData.height, + currency: bidData.currency ? bidData.currency : DEFAULT_CURRENCY, + netRevenue: DEFAULT_REVENUE, + ttl: DEFAULT_BID_TTL + }; + + bidResponses.push(bidResponse); + } + return bidResponses; + } +} + +function getOsType() { + let ua = navigator.userAgent.toLowerCase(); + let os = ['android', 'ios', 'mac', 'linux', 'window', 'etc']; + let regexp_os = [/android/i, /iphone|ipad/i, /mac/i, /linux/i, /window/i, '']; + + return regexp_os.some((tos, idx) => { + if (ua.match(tos)) { + return os[idx]; + } + }); +} + +function getSize(sizes) { + let parsedSizes = utils.parseSizesInput(sizes); + let [width, height] = parsedSizes.length ? parsedSizes[0].split('x') : []; + + return { + width: parseInt(width, 10), + height: parseInt(height, 10) + }; +} +registerBidder(spec); diff --git a/modules/nasmediaAdmixerBidAdapter.md b/modules/nasmediaAdmixerBidAdapter.md new file mode 100644 index 00000000000..aa72b7967f8 --- /dev/null +++ b/modules/nasmediaAdmixerBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +``` +Module Name: NasmeidaAdmixer Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@nasmedia.co.kr +``` + +# Description + +Module that connects to NasmediaAdmixer demand sources. +Banner formats are supported. +The NasmediaAdmixer adapter doesn't support multiple sizes per ad-unit and will use the first one if multiple sizes are defined. + + +# Test Parameters +``` + var adUnits = [ + { + code: 'banner-ad-div', + sizes: [[320, 480]], // banner size + bids: [ + { + bidder: 'nasmediaAdmixer', + params: { + ax_key: 'ajj7jba3', //required parameter + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js b/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js new file mode 100644 index 00000000000..7ed65718657 --- /dev/null +++ b/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js @@ -0,0 +1,138 @@ +import {expect} from 'chai'; +import {spec} from 'modules/nasmediaAdmixerBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +describe('nasmediaAdmixerBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + const bid = { + 'bidder': 'nasmediaAdmixer', + 'params': { + 'ax_key': 'ax_key' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '3361d01e67dbd6', + 'bidderRequestId': '2b60dcd392628a', + 'auctionId': '124cb070528662', + }; + + 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', () => { + const bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'ax_key': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const bidRequests = [ + { + 'bidder': 'nasmediaAdmixer', + 'params': { + 'ax_key': 'ajj7jba3' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '3361d01e67dbd6', + 'bidderRequestId': '2b60dcd392628a', + 'auctionId': '124cb070528662', + } + ]; + + it('sends bid request to url via GET', () => { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.method).to.equal('GET'); + expect(request.url).to.match(new RegExp(`https://adn.admixer.co.kr`)); + }); + }); + + describe('interpretResponse', () => { + const response = { + 'body': { + 'bidder': 'nasmedia_admixer', + 'req_id': '861a8e7952c82c', + 'error_code': 0, + 'error_msg': 'OK', + 'body': [{ + 'ad_id': '20049', + 'width': 300, + 'height': 250, + 'currency': 'USD', + 'cpm': 1.769221, + 'ad': '' + }] + }, + 'headers': { + 'get': function () { + } + } + }; + + const bidRequest = { + 'bidder': 'nasmediaAdmixer', + 'params': { + 'ax_key': 'ajj7jba3', + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [320, 480]], + 'bidId': '31300c8b9697cd', + 'bidderRequestId': '2bf570adcf83fa', + 'auctionId': '169827a33f03cc', + }; + + it('should get correct bid response', () => { + const expectedResponse = [ + { + 'requestId': '861a8e7952c82c', + 'cpm': 1.769221, + 'currency': 'USD', + 'width': 300, + 'height': 250, + 'ad': '', + 'creativeId': '20049', + 'ttl': 360, + 'netRevenue': false + } + ]; + + const result = spec.interpretResponse(response, bidRequest); + expect(result).to.have.lengthOf(1); + let resultKeys = Object.keys(result[0]); + expect(resultKeys.sort()).to.deep.equal(Object.keys(expectedResponse[0]).sort()); + resultKeys.forEach(function (k) { + if (k === 'ad') { + expect(result[0][k]).to.match(/$/); + } else { + expect(result[0][k]).to.equal(expectedResponse[0][k]); + } + }); + }); + + it('handles nobid responses', () => { + response.body = { + 'bidder': 'nasmedia_admixer', + 'req_id': '861a8e7952c82c', + 'error_code': 0, + 'error_msg': 'OK', + 'body': [] + }; + + const result = spec.interpretResponse(response, bidRequest); + expect(result).to.have.lengthOf(0); + }); + }); +}); From 3502919887dfb70a309fd3dcd3e4020284a4106c Mon Sep 17 00:00:00 2001 From: jstocker76 Date: Wed, 10 Jan 2018 07:55:33 -0800 Subject: [PATCH 0035/1594] Re-implemented RhythmOne audit beacon in prebid 1.0 interface (#1953) * Re-implemented RhythmOne audit beacon in prebid 1.0 interface * removed references to prebid_global and added more unit test coverage * removed block that sends beacons when usersync is disabled --- modules/rhythmoneBidAdapter.js | 66 +++++++++++++++++-- test/spec/modules/rhythmoneBidAdapter_spec.js | 10 +++ 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 8e7cc5075b2..6b4b5e7d4e6 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -11,6 +11,61 @@ function RhythmOneBidAdapter() { return true; }; + this.getUserSyncs = function (syncOptions) { + let slots = []; + let placementIds = []; + + for (let k in slotsToBids) { + slots.push(k); + placementIds.push(getFirstParam('placementId', [slotsToBids[k]])); + } + + let data = { + doc_version: 1, + doc_type: 'Prebid Audit', + placement_id: placementIds.join(',').replace(/[,]+/g, ',').replace(/^,|,$/g, '') + }; + let w = typeof (window) !== 'undefined' ? window : {document: {location: {href: ''}}}; + let ao = w.document.location.ancestorOrigins; + let q = []; + let u = '//hbevents.1rx.io/audit?'; + + if (ao && ao.length > 0) { + data.ancestor_origins = ao[ao.length - 1]; + } + + data.popped = w.opener !== null ? 1 : 0; + data.framed = w.top === w ? 0 : 1; + + try { + data.url = w.top.document.location.href.toString(); + } catch (ex) { + data.url = w.document.location.href.toString(); + } + + try { + data.prebid_version = '$prebid.version$'; + data.prebid_timeout = config.getConfig('bidderTimeout'); + } catch (ex) { } + + data.response_ms = Date.now() - loadStart; + data.placement_codes = slots.join(','); + data.bidder_version = version; + + for (let k in data) { + q.push(encodeURIComponent(k) + '=' + encodeURIComponent((typeof data[k] === 'object' ? JSON.stringify(data[k]) : data[k]))); + } + + q.sort(); + + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: u + q.join('&') + }]; + } + }; + function getFirstParam(key, validBidRequests) { for (let i = 0; i < validBidRequests.length; i++) { if (validBidRequests[i].params && validBidRequests[i].params[key]) { @@ -22,6 +77,7 @@ function RhythmOneBidAdapter() { let slotsToBids = {}; let that = this; let version = '1.0.0.0'; + let loadStart = Date.now(); this.buildRequests = function (BRs) { let fallbackPlacementId = getFirstParam('placementId', BRs); @@ -29,13 +85,14 @@ function RhythmOneBidAdapter() { return []; } + loadStart = Date.now(); slotsToBids = {}; let query = []; let w = (typeof window !== 'undefined' ? window : {}); - function p(k, v) { - if (v instanceof Array) { v = v.join(','); } + function p(k, v, d) { + if (v instanceof Array) { v = v.join((d || ',')); } if (typeof v !== 'undefined') { query.push(encodeURIComponent(k) + '=' + encodeURIComponent(v)); } } @@ -98,8 +155,7 @@ function RhythmOneBidAdapter() { if ((new w.ActiveXObject('ShockwaveFlash.ShockwaveFlash'))) { return 1; } - } catch (e) { - } + } catch (e) { } } return 0; @@ -186,12 +242,14 @@ function RhythmOneBidAdapter() { if (bidRequest.mediaTypes && bidRequest.mediaTypes.video) { bidResponse.vastUrl = bid.nurl; + bidResponse.mediaType = 'video'; bidResponse.ttl = 10000; } else { bidResponse.ad = bid.adm; } bids.push(bidResponse); } + return bids; }; } diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index cef8975ad2b..ad113b9021a 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -2,6 +2,16 @@ import {spec} from '../../../modules/rhythmoneBidAdapter'; var assert = require('assert'); describe('rhythmone adapter tests', function () { + describe('auditBeacon', function() { + var z = spec; + var beaconURL = z.getUserSyncs({pixelEnabled: true})[0]; + + it('should contain the correct path', function() { + var u = '//hbevents.1rx.io/audit?' + assert.equal(beaconURL.url.substring(0, u.length), u); + }); + }); + describe('rhythmoneResponse', function () { var z = spec; From 289cee2988266c5f8fced1dd080505e807714df3 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Wed, 10 Jan 2018 10:10:49 -0800 Subject: [PATCH 0036/1594] Fix uncached video bids triggering callback early (#2017) * Mark video bid done after it's been cached * Add tests --- src/auction.js | 30 +++++++++++++++++++++--------- test/spec/auctionmanager_spec.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/auction.js b/src/auction.js index 7c6a752c057..2a4cc128c2a 100644 --- a/src/auction.js +++ b/src/auction.js @@ -147,14 +147,24 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } function done(bidRequestId) { - var innerBidRequestId = bidRequestId; + const innerBidRequestId = bidRequestId; return delayExecution(function() { - let request = find(_bidderRequests, (bidRequest) => { + const request = find(_bidderRequests, (bidRequest) => { return innerBidRequestId === bidRequest.bidderRequestId; }); - request.doneCbCallCount += 1; - // In case of mediaType video and prebidCache enabled, call bidsBackHandler after cache is stored. - if ((request.bids.filter(videoAdUnit).length == 0) || (request.bids.filter(videoAdUnit).length > 0 && !config.getConfig('cache.url'))) { + + const nonVideoBid = request.bids.filter(videoAdUnit).length === 0; + const videoBid = request.bids.filter(videoAdUnit).length > 0; + const videoBidNoCache = videoBid && !config.getConfig('cache.url'); + const videoBidWithCache = videoBid && config.getConfig('cache.url'); + + // video bids with cache enabled need to be cached first before saying they are done + if (!videoBidWithCache) { + request.doneCbCallCount += 1; + } + + // in case of mediaType video and prebidCache enabled, call bidsBackHandler after cache is stored. + if (nonVideoBid || videoBidNoCache) { bidsBackAll() } }, 1); @@ -216,7 +226,9 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid let bidRequests = auctionInstance.getBidRequests(); let auctionId = auctionInstance.getAuctionId(); - let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequests, auctionId}); + let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); + let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}); + if (bidResponse.mediaType === 'video') { tryAddVideoBid(bidResponse); } else { @@ -247,6 +259,8 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid if (!bid.vastUrl) { bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); } + // only set this prop after the bid has been cached to avoid early ending auction early in bidsBackAll + bidRequest.doneCbCallCount += 1; addBidToAuction(bidResponse); auctionInstance.bidsBackAll(); } @@ -261,9 +275,7 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid // 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, bidRequests, auctionId}) { - let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); - +function getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}) { const start = bidRequest.start; let bidObject = Object.assign({}, bid, { diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 688afc35d9d..3429087a24f 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -4,6 +4,8 @@ import CONSTANTS from 'src/constants.json'; import { adjustBids } from 'src/auction'; import * as auctionModule from 'src/auction'; import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; +import * as store from 'src/videoCache'; import * as ajaxLib from 'src/ajax'; var assert = require('assert'); @@ -870,5 +872,32 @@ describe('auctionmanager.js', function () { assert.notEqual(addedBid2.adId, bids1[0].requestId); assert.equal(length, 1); }); + + it('should run auction after video bids have been cached', () => { + sinon.stub(store, 'store').callsArgWith(1, null, [{ uuid: 123}]); + sinon.stub(config, 'getConfig').withArgs('cache.url').returns('cache-url'); + + const bidsCopy = [Object.assign({}, bids[0], { mediaType: 'video'})]; + const bids1Copy = [Object.assign({}, bids1[0], { mediaType: 'video'})]; + + registerBidder(spec); + registerBidder(spec1); + + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bidsCopy); + + spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec1.isBidRequestValid.returns(true); + spec1.interpretResponse.returns(bids1Copy); + + auction.callBids(); + + assert.equal(auction.getBidsReceived().length, 2); + assert.equal(auction.getAuctionStatus(), 'completed'); + + config.getConfig.restore(); + store.store.restore(); + }); }); }); From a5f059b5b0ffb7294d8929cb148b7a9feecf8118 Mon Sep 17 00:00:00 2001 From: Matt Kendall Date: Wed, 17 Jan 2018 11:48:52 -0500 Subject: [PATCH 0037/1594] Use sudo to workaround Travis regression (#2041) --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 73b5de5ae4a..364d47edf4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +sudo: required + dist: trusty language: node_js From 108f600d1c9ad3583a4ddaadbb7e615e9465f77e Mon Sep 17 00:00:00 2001 From: Steve Alliance Date: Wed, 17 Jan 2018 17:40:56 -0500 Subject: [PATCH 0038/1594] Adding districtm as an alias (#2018) Adding districtm as an alias since it was also an alias in the previous Prebid version. --- modules/appnexusBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 7db2b9aab2f..21af777bdc5 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -30,7 +30,7 @@ const SOURCE = 'pbjs'; export const spec = { code: BIDDER_CODE, - aliases: ['appnexusAst', 'brealtime', 'pagescience', 'defymedia', 'gourmetads', 'matomy', 'featureforward', 'oftmedia'], + aliases: ['appnexusAst', 'brealtime', 'pagescience', 'defymedia', 'gourmetads', 'matomy', 'featureforward', 'oftmedia', 'districtm'], supportedMediaTypes: [VIDEO, NATIVE], /** From 4418feccb72100843b7d2300657012bd6a5f35f9 Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Wed, 17 Jan 2018 17:42:02 -0500 Subject: [PATCH 0039/1594] Serverbid Bid Adapter: updated docs and ad sizes (#2023) --- modules/serverbidBidAdapter.js | 1 + modules/serverbidBidAdapter.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index d120e5c4306..84cae1fa1c0 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -181,6 +181,7 @@ sizeMap[3230] = '970x280'; sizeMap[429] = '486x60'; sizeMap[374] = '700x500'; sizeMap[934] = '300x1050'; +sizeMap[1578] = '320x100'; function getSize(sizes) { const result = []; diff --git a/modules/serverbidBidAdapter.md b/modules/serverbidBidAdapter.md index 934362c69c4..87b51e665e2 100644 --- a/modules/serverbidBidAdapter.md +++ b/modules/serverbidBidAdapter.md @@ -35,7 +35,7 @@ Connects to Serverbid for receiving bids from configured demand sources. params: { networkId: '9969', siteId: '980639', - zoneId: '178503' + zoneIds: [178503] } } ] From f09865befdaf96c746f45a7b1f8e4e1a1e58cd66 Mon Sep 17 00:00:00 2001 From: ricardoe Date: Thu, 18 Jan 2018 13:27:02 -0600 Subject: [PATCH 0040/1594] GumGum Adapter for Prebid.js 1.0 (#1966) * GumGum Adapter for Prebid.js 1.0 * removed getUserSyncs. Give cpm a non-zero value when bidRequest is for test unit so DFP chooses it. * parsing slot ID as integer from params * ADSS-78 removed bidderCode from response. Correctly parsing bidRequest.sizes to account for 1-dimensional array. --- modules/gumgumBidAdapter.js | 170 +++++++++++++++++++++ modules/gumgumBidAdapter.md | 40 +++++ test/spec/modules/gumgumBidAdapter_spec.js | 138 +++++++++++++++++ 3 files changed, 348 insertions(+) create mode 100644 modules/gumgumBidAdapter.js create mode 100644 modules/gumgumBidAdapter.md create mode 100644 test/spec/modules/gumgumBidAdapter_spec.js diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js new file mode 100644 index 00000000000..2627b7417f5 --- /dev/null +++ b/modules/gumgumBidAdapter.js @@ -0,0 +1,170 @@ +import * as utils from 'src/utils' + +import { config } from 'src/config' +import { registerBidder } from 'src/adapters/bidderFactory' + +const BIDDER_CODE = 'gumgum' +const ALIAS_BIDDER_CODE = ['gg'] +const BID_ENDPOINT = `https://g2.gumgum.com/hbid/imp` +const DT_CREDENTIALS = { member: 'YcXr87z2lpbB' } +const TIME_TO_LIVE = 60 +let browserParams = {}; + +// TODO: potential 0 values for browserParams sent to ad server +function _getBrowserParams() { + let topWindow + let topScreen + if (browserParams.vw) { + // we've already initialized browserParams, just return it. + return browserParams + } + + try { + topWindow = global.top; + topScreen = topWindow.screen; + } catch (error) { + utils.logError(error); + return browserParams + } + + browserParams = { + vw: topWindow.innerWidth, + vh: topWindow.innerHeight, + sw: topScreen.width, + sh: topScreen.height, + pu: utils.getTopWindowUrl(), + ce: utils.cookiesAreEnabled(), + dpr: topWindow.devicePixelRatio || 1 + } + return browserParams +} + +function getWrapperCode(wrapper, data) { + return wrapper.replace('AD_JSON', window.btoa(JSON.stringify(data))) +} + +// TODO: use getConfig() +function _getDigiTrustQueryParams() { + function getDigiTrustId () { + var digiTrustUser = (window.DigiTrust && window.DigiTrust.getUser) ? window.DigiTrust.getUser(DT_CREDENTIALS) : {}; + return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || ''; + }; + + let digiTrustId = getDigiTrustId(); + // Verify there is an ID and this user has not opted out + if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { + return {}; + } + return { + 'dt': digiTrustId.id + }; +} + +/** + * 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. + */ +function isBidRequestValid (bid) { + const { + params, + adUnitCode + } = bid; + + switch (true) { + case !!(params.inScreen): break; + case !!(params.inSlot): break; + default: + utils.logWarn(`[GumGum] No product selected for the placement ${adUnitCode}, please check your implementation.`); + return false; + } + return true; +} + +/** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ +function buildRequests (validBidRequests) { + const bids = []; + utils._each(validBidRequests, bidRequest => { + const timeout = config.getConfig('bidderTimeout'); + const { + bidId, + params = {}, + transactionId + } = bidRequest; + const data = {} + + if (params.inScreen) { + data.t = params.inScreen; + data.pi = 2; + } + if (params.inSlot) { + data.si = parseInt(params.inSlot, 10); + data.pi = 3; + } + + bids.push({ + id: bidId, + tmax: timeout, + tId: transactionId, + pi: data.pi, + sizes: bidRequest.sizes, + url: BID_ENDPOINT, + method: 'GET', + data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams()) + }) + }); + return bids; +} + +/** + * 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. + */ +function interpretResponse (serverResponse, bidRequest) { + const bidResponses = [] + const serverResponseBody = serverResponse.body + const { + ad: { + price: cpm, + id: creativeId, + markup + }, + cw: wrapper + } = serverResponseBody + let isTestUnit = (bidRequest.data && bidRequest.data.pi === 3 && bidRequest.data.si === 9) + let [width, height] = utils.parseSizesInput(bidRequest.sizes)[0].split('x') + + if (creativeId) { + bidResponses.push({ + // dealId: DEAL_ID, + // referrer: REFERER, + ad: wrapper ? getWrapperCode(wrapper, Object.assign({}, serverResponseBody, { bidRequest })) : markup, + cpm: isTestUnit ? 0.1 : cpm, + creativeId, + currency: 'USD', + height, + netRevenue: true, + requestId: bidRequest.id, + ttl: TIME_TO_LIVE, + width + }) + } + return bidResponses +} + +export const spec = { + code: BIDDER_CODE, + aliases: ALIAS_BIDDER_CODE, + isBidRequestValid, + buildRequests, + interpretResponse +} +registerBidder(spec) diff --git a/modules/gumgumBidAdapter.md b/modules/gumgumBidAdapter.md new file mode 100644 index 00000000000..500c2a49e3b --- /dev/null +++ b/modules/gumgumBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +``` +Module Name: GumGum Bidder Adapter +Module Type: Bidder Adapter +Maintainer: engineering@gumgum.com +``` + +# Description + +GumGum adapter for Prebid.js 1.0 + +# Test Parameters +``` +var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: 'gumgum', + params: { + inSlot: '9' // GumGum Slot ID given to the client + } + } + ] + },{ + code: 'test-div', + sizes: [[300, 50]], + bids: [ + { + bidder: 'gumgum', + params: { + inScreen: 'ggumtest' // GumGum Zone ID given to the client + } + } + ] + } +]; +``` diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js new file mode 100644 index 00000000000..30627d4d12d --- /dev/null +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -0,0 +1,138 @@ +import { expect } from 'chai'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { spec } from 'modules/gumgumBidAdapter'; + +const ENDPOINT = 'https://g2.gumgum.com/hbid/imp'; + +describe('gumgumAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'gumgum', + 'params': { + 'inScreen': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'inSlot': '789' + }; + + 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 = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'gumgum', + 'params': { + 'inSlot': '9' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e' + } + ]; + + it('sends bid request to ENDPOINT via GET', () => { + const requests = spec.buildRequests(bidRequests); + const request = requests[0]; + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('GET'); + expect(request.id).to.equal('30b31c1838de1e'); + }); + }) + + describe('interpretResponse', () => { + let serverResponse = { + 'ad': { + 'id': 29593, + 'width': 300, + 'height': 250, + 'ipd': 2000, + 'markup': '

I am an ad

', + 'ii': true, + 'du': null, + 'price': 0, + 'zi': 0, + 'impurl': 'http://g2.gumgum.com/ad/view', + 'clsurl': 'http://g2.gumgum.com/ad/close' + }, + 'pag': { + 't': 'ggumtest', + 'pvid': 'aa8bbb65-427f-4689-8cee-e3eed0b89eec', + 'css': 'html { overflow-y: auto }', + 'js': 'console.log("environment", env);' + }, + 'thms': 10000 + } + let bidRequest = { + id: 12345, + sizes: [[300, 250]], + url: ENDPOINT, + method: 'GET', + pi: 3 + } + + it('should get correct bid response', () => { + let expectedResponse = { + 'ad': '

I am an ad

', + 'cpm': 0, + 'creativeId': 29593, + 'currency': 'USD', + 'height': '250', + 'netRevenue': true, + 'requestId': 12345, + 'width': '300', + // dealId: DEAL_ID, + // referrer: REFERER, + ttl: 60 + }; + expect(spec.interpretResponse({ body: serverResponse }, bidRequest)).to.deep.equal([expectedResponse]); + }); + + it('handles nobid responses', () => { + let response = { + 'ad': {}, + 'pag': { + 't': 'ggumtest', + 'pvid': 'aa8bbb65-427f-4689-8cee-e3eed0b89eec', + 'css': 'html { overflow-y: auto }', + 'js': 'console.log("environment", env);' + }, + 'thms': 10000 + } + let result = spec.interpretResponse({ body: response }, bidRequest); + expect(result.length).to.equal(0); + }); + }) +}); From 1e8155b89f4a0286daa04b45e6e6ff0dfedaeee9 Mon Sep 17 00:00:00 2001 From: vedantseta Date: Tue, 23 Jan 2018 00:11:19 +0530 Subject: [PATCH 0041/1594] Media.net adapter added (#2038) --- modules/medianetBidAdapter.js | 161 +++++++++ modules/medianetBidAdapter.md | 59 ++++ test/spec/modules/medianetBidAdapter_spec.js | 329 +++++++++++++++++++ 3 files changed, 549 insertions(+) create mode 100644 modules/medianetBidAdapter.js create mode 100644 modules/medianetBidAdapter.md create mode 100644 test/spec/modules/medianetBidAdapter_spec.js diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js new file mode 100644 index 00000000000..c0b3fff3c2a --- /dev/null +++ b/modules/medianetBidAdapter.js @@ -0,0 +1,161 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'medianet'; +const BID_URL = 'https://prebid.media.net/rtb/prebid'; + +function siteDetails(site) { + site = site || {}; + + return { + domain: site.domain || utils.getTopWindowLocation().host, + page: site.page || utils.getTopWindowUrl(), + ref: site.ref || utils.getTopWindowReferrer() + } +} + +function filterUrlsByType(urls, type) { + return urls.filter(url => url.type === type); +} + +function transformSizes(sizes) { + if (utils.isArray(sizes) && sizes.length === 2 && !utils.isArray(sizes[0])) { + return [getSize(sizes)]; + } + + return sizes.map(size => getSize(size)) +} + +function getSize(size) { + return { + w: parseInt(size[0], 10), + h: parseInt(size[1], 10) + } +} + +function configuredParams(params) { + return { + customer_id: params.cid + } +} + +function slotParams(bidRequest) { + // check with Media.net Account manager for bid floor and crid parameters + let params = { + id: bidRequest.bidId, + ext: { + dfp_id: bidRequest.adUnitCode + }, + banner: transformSizes(bidRequest.sizes) + }; + + if (bidRequest.params.crid) { + params.tagid = bidRequest.params.crid.toString(); + } + + let bidFloor = parseFloat(bidRequest.params.bidfloor); + if (bidFloor) { + params.bidfloor = bidFloor; + } + return params; +} + +function generatePayload(bidRequests) { + return { + site: siteDetails(bidRequests[0].params.site), + ext: configuredParams(bidRequests[0].params), + id: bidRequests[0].auctionId, + imp: bidRequests.map(request => slotParams(request)) + } +} + +function isValidBid(bid) { + return bid.no_bid === false && parseFloat(bid.cpm) > 0.0; +} + +function fetchCookieSyncUrls(response) { + if (!utils.isEmpty(response) && response[0].body && + response[0].body.ext && utils.isArray(response[0].body.ext.csUrl)) { + return response[0].body.ext.csUrl; + } + + return []; +} + +export const spec = { + + code: BIDDER_CODE, + + /** + * 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 (if cid is present), and false otherwise. + */ + isBidRequestValid: function(bid) { + if (!bid.params) { + utils.logError(`${BIDDER_CODE} : Missing bid parameters`); + return false; + } + + 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; + } + + return true; + }, + + /** + * 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) { + let payload = generatePayload(bidRequests); + + return { + method: 'POST', + url: BID_URL, + data: JSON.stringify(payload) + }; + }, + + /** + * 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) { + let validBids = []; + + if (!serverResponse || !serverResponse.body) { + utils.logInfo(`${BIDDER_CODE} : response is empty`); + return validBids; + } + + let bids = serverResponse.body.bidList; + if (!utils.isArray(bids) || bids.length === 0) { + utils.logInfo(`${BIDDER_CODE} : no bids`); + return validBids; + } + validBids = bids.filter(bid => isValidBid(bid)); + + return validBids; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + let cookieSyncUrls = fetchCookieSyncUrls(serverResponses); + + if (syncOptions.iframeEnabled) { + return filterUrlsByType(cookieSyncUrls, 'iframe'); + } + + if (syncOptions.pixelEnabled) { + return filterUrlsByType(cookieSyncUrls, 'image'); + } + } +}; +registerBidder(spec); diff --git a/modules/medianetBidAdapter.md b/modules/medianetBidAdapter.md new file mode 100644 index 00000000000..2edb120033e --- /dev/null +++ b/modules/medianetBidAdapter.md @@ -0,0 +1,59 @@ +# Overview + +``` +Module Name: media.net Bid Adapter +Module Type: Bidder Adapter +Maintainer: vedant.s@media.net +``` + +# Description + +Connects to Media.net's exchange for bids. +This adapter currently only supports Banner Ads. + +# Sample Ad Unit: For Publishers +```javascript +var adUnits = [{ + code: 'media.net-hb-ad-123456-1', + sizes: [ + [300, 250], + [300, 600], + ], + bids: [{ + bidder: 'medianet', + params: { + cid: '', + bidfloor: '', + crid: '' + } + }] +}]; +``` + +# Ad Unit and Setup: For Testing + +```html + + + +``` \ No newline at end of file diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js new file mode 100644 index 00000000000..db543eda433 --- /dev/null +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -0,0 +1,329 @@ +import {expect} from 'chai'; +import {spec} from 'modules/medianetBidAdapter'; + +let VALID_BID_REQUEST = [{ + 'bidder': 'medianet', + 'params': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + 'sizes': [[300, 250]], + 'bidId': '28f8f8130a583e', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + }, { + 'bidder': 'medianet', + 'params': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-123', + 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + 'sizes': [[300, 251]], + 'bidId': '3f97ca71b1e5c2', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + }], + VALID_BID_REQUEST_INVALID_BIDFLOOR = [{ + 'bidder': 'medianet', + 'params': { + 'cid': 'customer_id', + 'bidfloor': 'abcdef', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + 'sizes': [[300, 250]], + 'bidId': '28f8f8130a583e', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + }, { + 'bidder': 'medianet', + 'params': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-123', + 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + 'sizes': [[300, 251]], + 'bidId': '3f97ca71b1e5c2', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + }], + VALID_PAYLOAD = { + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + }, + 'ext': { + 'customer_id': 'customer_id' + }, + 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'imp': [{ + 'id': '28f8f8130a583e', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-0' + }, + 'banner': [{ + 'w': 300, + 'h': 250 + }] + }, { + 'id': '3f97ca71b1e5c2', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-123' + }, + 'banner': [{ + 'w': 300, + 'h': 251 + }] + }] + }, + VALID_PARAMS = { + bidder: 'medianet', + params: { + cid: '8CUV090' + } + }, + PARAMS_WITHOUT_CID = { + bidder: 'medianet', + params: {} + }, + PARAMS_WITH_INTEGER_CID = { + bidder: 'medianet', + params: { + cid: 8867587 + } + }, + PARAMS_WITH_EMPTY_CID = { + bidder: 'medianet', + params: { + cid: '' + } + }, + SYNC_OPTIONS_BOTH_ENABLED = { + iframeEnabled: true, + pixelEnabled: true, + }, + SYNC_OPTIONS_PIXEL_ENABLED = { + iframeEnabled: false, + pixelEnabled: true, + }, + SYNC_OPTIONS_IFRAME_ENABLED = { + iframeEnabled: true, + pixelEnabled: false, + }, + SERVER_CSYNC_RESPONSE = [{ + body: { + ext: { + csUrl: [{ + type: 'iframe', + url: 'iframe-url' + }, { + type: 'image', + url: 'pixel-url' + }] + } + } + }], + ENABLED_SYNC_IFRAME = [{ + type: 'iframe', + url: 'iframe-url' + }], + ENABLED_SYNC_PIXEL = [{ + type: 'image', + url: 'pixel-url' + }], + SERVER_RESPONSE_CPM_MISSING = { + 'id': 'd90ca32f-3877-424a-b2f2-6a68988df57a', + 'bidList': [{ + 'no_bid': false, + 'requestId': '27210feac00e96', + 'ad': 'ad', + 'width': 300, + 'height': 250, + 'creativeId': '375068987', + 'netRevenue': true + }], + 'ext': { + 'csUrl': [{ + 'type': 'image', + 'url': 'http://cs.media.net/cksync.php' + }, { + 'type': 'iframe', + 'url': 'http://contextual.media.net/checksync.php?&vsSync=1' + }] + } + }, + SERVER_RESPONSE_CPM_ZERO = { + 'id': 'd90ca32f-3877-424a-b2f2-6a68988df57a', + 'bidList': [{ + 'no_bid': false, + 'requestId': '27210feac00e96', + 'ad': 'ad', + 'width': 300, + 'height': 250, + 'creativeId': '375068987', + 'netRevenue': true, + 'cpm': 0.0 + }], + 'ext': { + 'csUrl': [{ + 'type': 'image', + 'url': 'http://cs.media.net/cksync.php' + }, { + 'type': 'iframe', + 'url': 'http://contextual.media.net/checksync.php?&vsSync=1' + }] + } + }, + SERVER_RESPONSE_NOBID = { + 'id': 'd90ca32f-3877-424a-b2f2-6a68988df57a', + 'bidList': [{ + 'no_bid': true, + 'requestId': '3a62cf7a853f84', + 'width': 0, + 'height': 0, + 'ttl': 0, + 'netRevenue': false + }], + 'ext': { + 'csUrl': [{ + 'type': 'image', + 'url': 'http://cs.media.net/cksync.php' + }, { + 'type': 'iframe', + 'url': 'http://contextual.media.net/checksync.php?&vsSync=1' + }] + } + }, + BID_REQUEST_SIZE_AS_1DARRAY = [{ + 'bidder': 'medianet', + 'params': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + 'sizes': [300, 250], + 'bidId': '28f8f8130a583e', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + }, { + 'bidder': 'medianet', + 'params': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-123', + 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + 'sizes': [300, 251], + 'bidId': '3f97ca71b1e5c2', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + }]; + +describe('Media.net bid adapter', () => { + describe('isBidRequestValid', () => { + it('should accept valid bid params', () => { + let isValid = spec.isBidRequestValid(VALID_PARAMS); + expect(isValid).to.equal(true); + }); + + it('should reject bid if cid is not present', () => { + let isValid = spec.isBidRequestValid(PARAMS_WITHOUT_CID); + expect(isValid).to.equal(false); + }); + + it('should reject bid if cid is not a string', () => { + let isValid = spec.isBidRequestValid(PARAMS_WITH_INTEGER_CID); + expect(isValid).to.equal(false); + }); + + it('should reject bid if cid is a empty string', () => { + let isValid = spec.isBidRequestValid(PARAMS_WITH_EMPTY_CID); + expect(isValid).to.equal(false); + }); + }); + + describe('buildRequests', () => { + it('should build valid payload on bid', () => { + let requestObj = spec.buildRequests(VALID_BID_REQUEST); + expect(JSON.parse(requestObj.data)).to.deep.equal(VALID_PAYLOAD); + }); + + it('should accept size as a one dimensional array', () => { + let bidReq = spec.buildRequests(BID_REQUEST_SIZE_AS_1DARRAY); + expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD); + }); + + it('should ignore bidfloor if not a valid number', () => { + let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR); + expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD); + }); + }); + + describe('getUserSyncs', () => { + it('should exclude iframe syncs if iframe is disabled', () => { + let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_PIXEL_ENABLED, SERVER_CSYNC_RESPONSE); + expect(userSyncs).to.deep.equal(ENABLED_SYNC_PIXEL); + }); + + it('should exclude pixel syncs if pixel is disabled', () => { + let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_IFRAME_ENABLED, SERVER_CSYNC_RESPONSE); + expect(userSyncs).to.deep.equal(ENABLED_SYNC_IFRAME); + }); + + it('should choose iframe sync urls if both sync options are enabled', () => { + let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_BOTH_ENABLED, SERVER_CSYNC_RESPONSE); + expect(userSyncs).to.deep.equal(ENABLED_SYNC_IFRAME); + }); + }); + + describe('interpretResponse', () => { + it('should not push bid response if cpm missing', () => { + let validBids = []; + let bids = spec.interpretResponse(SERVER_RESPONSE_CPM_MISSING, []); + expect(bids).to.deep.equal(validBids); + }); + + it('should not push bid response if cpm 0', () => { + let validBids = []; + let bids = spec.interpretResponse(SERVER_RESPONSE_CPM_ZERO, []); + expect(bids).to.deep.equal(validBids); + }); + + it('should not push response if no-bid', () => { + let validBids = []; + let bids = spec.interpretResponse(SERVER_RESPONSE_NOBID, []); + expect(bids).to.deep.equal(validBids) + }); + }); +}); From 25f1e5a7750ce4cf8489dc313420934aaeb934c1 Mon Sep 17 00:00:00 2001 From: Paris Holley Date: Mon, 22 Jan 2018 14:45:06 -0500 Subject: [PATCH 0042/1594] 1.0 adapter support for mantis (#1840) * 1.0 support for mantis adapter * removed some common non-prebid code * Remove bidderCode to fix failing test --- modules/mantisBidAdapter.js | 206 +++++++++++++++++++++ modules/mantisBidAdapter.md | 30 +++ test/spec/modules/mantisBidAdapter_spec.js | 178 ++++++++++++++++++ 3 files changed, 414 insertions(+) create mode 100644 modules/mantisBidAdapter.js create mode 100644 modules/mantisBidAdapter.md create mode 100644 test/spec/modules/mantisBidAdapter_spec.js diff --git a/modules/mantisBidAdapter.js b/modules/mantisBidAdapter.js new file mode 100644 index 00000000000..7247a236e71 --- /dev/null +++ b/modules/mantisBidAdapter.js @@ -0,0 +1,206 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; + +function inIframe() { + try { + return window.self !== window.top && !window.mantis_link; + } catch (e) { + return true; + } +} + +function isDesktop(ignoreTouch) { + var supportsTouch = !ignoreTouch && ('ontouchstart' in window || navigator.msMaxTouchPoints); + if (inIframe()) { + return !supportsTouch; + } + var width = window.innerWidth || window.document.documentElement.clientWidth || window.document.body.clientWidth; + return !supportsTouch && (!width || width >= (window.mantis_breakpoint || 768)); +} + +function storeUuid(uuid) { + if (window.mantis_uuid) { + return false; + } + window.mantis_uuid = uuid; + if (window.localStorage) { + try { + window.localStorage.setItem('mantis:uuid', uuid); + } catch (ex) { + } + } +} + +function isSendable(val) { + if (val === null || val === undefined) { + return false; + } + if (typeof val === 'string') { + return !(!val || /^\s*$/.test(val)); + } + if (typeof val === 'number') { + return !isNaN(val); + } + return true; +} + +function isObject(value) { + return Object.prototype.toString.call(value) === '[object Object]'; +} + +function isAmp() { + return typeof window.context === 'object' && (window.context.tagName === 'AMP-AD' || window.context.tagName === 'AMP-EMBED'); +} + +function isSecure() { + return document.location.protocol === 'https:'; +} + +function isArray(value) { + return Object.prototype.toString.call(value) === '[object Array]'; +} + +function jsonToQuery(data, chain, form) { + if (!data) { + return null; + } + var parts = form || []; + for (var key in data) { + var queryKey = key; + if (chain) { + queryKey = chain + '[' + key + ']'; + } + var val = data[key]; + if (isArray(val)) { + for (var index = 0; index < val.length; index++) { + var akey = queryKey + '[' + index + ']'; + var aval = val[index]; + if (isObject(aval)) { + jsonToQuery(aval, akey, parts); + } else if (isSendable(aval)) { + parts.push(akey + '=' + encodeURIComponent(aval)); + } + } + } else if (isObject(val) && val != data) { + jsonToQuery(val, queryKey, parts); + } else if (isSendable(val)) { + parts.push(queryKey + '=' + encodeURIComponent(val)); + } + } + return parts.join('&'); +} + +function buildMantisUrl(path, data, domain) { + var params = { + referrer: document.referrer, + tz: new Date().getTimezoneOffset(), + buster: new Date().getTime(), + secure: isSecure() + }; + if (!inIframe() || isAmp()) { + params.mobile = !isAmp() && isDesktop(true) ? 'false' : 'true'; + } + if (window.mantis_uuid) { + params.uuid = window.mantis_uuid; + } else if (window.localStorage) { + var localUuid = window.localStorage.getItem('mantis:uuid'); + if (localUuid) { + params.uuid = localUuid; + } + } + if (!inIframe()) { + try { + params.title = window.top.document.title; + params.referrer = window.top.document.referrer; + params.url = window.top.document.location.href; + } catch (ex) { + } + } else { + params.iframe = true; + } + if (isAmp()) { + params.amp = true; + if (!params.url && window.context.canonicalUrl) { + params.url = window.context.canonicalUrl; + } + if (!params.url && window.context.location) { + params.url = window.context.location.href; + } + if (!params.referrer && window.context.referrer) { + params.referrer = window.context.referrer; + } + } + Object.keys(data || {}).forEach(function (key) { + params[key] = data[key]; + }); + var query = jsonToQuery(params); + return (window.mantis_domain === undefined ? domain || 'https://mantodea.mantisadnetwork.com' : window.mantis_domain) + path + '?' + query; +} + +const spec = { + code: 'mantis', + supportedMediaTypes: ['banner', 'video', 'native'], + isBidRequestValid: function (bid) { + return !!(bid.params.property && (bid.params.code || bid.params.zoneId || bid.params.zone)); + }, + buildRequests: function (validBidRequests) { + var property = null; + validBidRequests.some(function (bid) { + if (bid.params.property) { + property = bid.params.property; + return true; + } + }); + const query = { + bids: validBidRequests.map(function (bid) { + return { + bidId: bid.bidId, + config: bid.params, + sizes: bid.sizes.map(function (size) { + return {width: size[0], height: size[1]}; + }) + }; + }), + property: property, + version: 2 + }; + return { + method: 'GET', + url: buildMantisUrl('/prebid/display', query) + '&foo', + data: '' + }; + }, + interpretResponse: function (serverResponse) { + storeUuid(serverResponse.uuid); + return serverResponse.body.ads.map(function (ad) { + return { + requestId: ad.bid, + cpm: ad.cpm, + width: ad.width, + height: ad.height, + ad: ad.html, + ttl: 86400, + creativeId: ad.view, + netRevenue: true, + currency: 'USD' + }; + }); + }, + getUserSyncs: function (syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: buildMantisUrl('/prebid/iframe') + }]; + } + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: buildMantisUrl('/prebid/pixel') + }]; + } + } +}; + +export {spec}; + +registerBidder(spec); diff --git a/modules/mantisBidAdapter.md b/modules/mantisBidAdapter.md new file mode 100644 index 00000000000..d8896c71514 --- /dev/null +++ b/modules/mantisBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +Module Name: MANTIS Ad Network Bid Adapter + +Module Type: Bidder Adapter + +Maintainer: paris@mantisadnetwork.com + +# Description + +Module that connects to MANTIS's demand sources + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'test', + sizes: [[300, 250]], + bids: [ + { + bidder: 'mantis', + params: { + property: 'demo', + zone: 'zone' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/mantisBidAdapter_spec.js b/test/spec/modules/mantisBidAdapter_spec.js new file mode 100644 index 00000000000..e2cd4df9a07 --- /dev/null +++ b/test/spec/modules/mantisBidAdapter_spec.js @@ -0,0 +1,178 @@ +import {expect} from 'chai'; +import {spec} from 'modules/mantisBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +describe('MantisAdapter', () => { + const adapter = newBidder(spec); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'mantis', + 'params': { + 'property': '10433394', + 'zone': 'zone' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'mantis', + 'params': { + 'property': '10433394', + 'zone': 'zone' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('domain override', () => { + window.mantis_domain = 'http://foo'; + const request = spec.buildRequests(bidRequests); + + expect(request.url).to.include('http://foo'); + + delete window.mantis_domain; + }); + + it('standard request', () => { + const request = spec.buildRequests(bidRequests); + + expect(request.url).to.include('property=10433394'); + expect(request.url).to.include('bids[0][bidId]=30b31c1838de1e'); + expect(request.url).to.include('bids[0][config][zone]=zone'); + expect(request.url).to.include('bids[0][sizes][0][width]=300'); + expect(request.url).to.include('bids[0][sizes][0][height]=250'); + expect(request.url).to.include('bids[0][sizes][1][width]=300'); + expect(request.url).to.include('bids[0][sizes][1][height]=600'); + }); + + it('use window uuid', () => { + window.mantis_uuid = 'foo'; + + const request = spec.buildRequests(bidRequests); + + expect(request.url).to.include('uuid=foo'); + + delete window.mantis_uuid; + }); + + it('use storage uuid', () => { + window.localStorage.setItem('mantis:uuid', 'bar'); + + const request = spec.buildRequests(bidRequests); + + expect(request.url).to.include('uuid=bar'); + + window.localStorage.removeItem('mantis:uuid'); + }); + + it('detect amp', () => { + var oldContext = window.context; + + window.context = {}; + window.context.tagName = 'AMP-AD'; + window.context.canonicalUrl = 'foo'; + + const request = spec.buildRequests(bidRequests); + + expect(request.url).to.include('amp=true'); + expect(request.url).to.include('url=foo'); + + delete window.context.tagName; + delete window.context.canonicalUrl; + + window.context = oldContext; + }); + }); + + describe('getUserSyncs', () => { + it('iframe', () => { + let result = spec.getUserSyncs({ + iframeEnabled: true + }); + + expect(result[0].type).to.equal('iframe'); + expect(result[0].url).to.include('https://mantodea.mantisadnetwork.com/prebid/iframe'); + }); + + it('pixel', () => { + let result = spec.getUserSyncs({ + pixelEnabled: true + }); + + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.include('https://mantodea.mantisadnetwork.com/prebid/pixel'); + }); + }); + + describe('interpretResponse', () => { + it('display ads returned', () => { + let response = { + body: { + ads: [ + { + bid: 'bid', + cpm: 1, + view: 'view', + width: 300, + height: 250, + html: '' + } + ] + } + }; + + let expectedResponse = [ + { + requestId: 'bid', + cpm: 1, + width: 300, + height: 250, + ttl: 86400, + ad: '', + creativeId: 'view', + netRevenue: true, + currency: 'USD' + } + ]; + let bidderRequest; + + let result = spec.interpretResponse(response, {bidderRequest}); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + it('no ads returned', () => { + let response = { + body: { + ads: [] + } + }; + let bidderRequest; + + let result = spec.interpretResponse(response, {bidderRequest}); + expect(result.length).to.equal(0); + }); + }); +}); From c58a15896f378282a0c5bb809871e8998f16b974 Mon Sep 17 00:00:00 2001 From: Yann Pravo Date: Mon, 22 Jan 2018 20:57:58 +0100 Subject: [PATCH 0043/1594] Separate bids & won calls (#2015) * separate bids & won calls * readd polyfills --- modules/adomikAnalyticsAdapter.js | 55 ++++++++++--------- .../modules/adomikAnalyticsAdapter_spec.js | 33 ++++------- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/modules/adomikAnalyticsAdapter.js b/modules/adomikAnalyticsAdapter.js index 64e3ae14835..30ef9c7dd90 100644 --- a/modules/adomikAnalyticsAdapter.js +++ b/modules/adomikAnalyticsAdapter.js @@ -1,6 +1,7 @@ import adapter from 'src/AnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import adaptermanager from 'src/adaptermanager'; +import { logInfo } from 'src/utils'; import find from 'core-js/library/fn/array/find'; import findIndex from 'core-js/library/fn/array/find-index'; @@ -12,19 +13,14 @@ const bidResponse = CONSTANTS.EVENTS.BID_RESPONSE; const bidWon = CONSTANTS.EVENTS.BID_WON; const bidTimeout = CONSTANTS.EVENTS.BID_TIMEOUT; -let bidwonTimeout = 1000; - let adomikAdapter = Object.assign(adapter({}), { // Track every event needed track({ eventType, args }) { switch (eventType) { case auctionInit: + adomikAdapter.initializeBucketEvents() adomikAdapter.currentContext.id = args.auctionId - adomikAdapter.currentContext.timeout = args.timeout - if (args.config.bidwonTimeout !== undefined && typeof args.config.bidwonTimeout === 'number') { - bidwonTimeout = args.config.bidwonTimeout; - } break; case bidTimeout: @@ -39,12 +35,9 @@ let adomikAdapter = Object.assign(adapter({}), break; case bidWon: - adomikAdapter.bucketEvents.push({ - type: 'winner', - event: { - id: args.adId, - placementCode: args.adUnitCode - } + adomikAdapter.sendWonEvent({ + id: args.adId, + placementCode: args.adUnitCode }); break; @@ -61,24 +54,25 @@ let adomikAdapter = Object.assign(adapter({}), break; case auctionEnd: - setTimeout(() => { - if (adomikAdapter.bucketEvents.length > 0) { - adomikAdapter.sendTypedEvent(); - } - }, bidwonTimeout); + if (adomikAdapter.bucketEvents.length > 0) { + adomikAdapter.sendTypedEvent(); + } break; } } } ); +adomikAdapter.initializeBucketEvents = function() { + adomikAdapter.bucketEvents = []; +} + adomikAdapter.sendTypedEvent = function() { const groupedTypedEvents = adomikAdapter.buildTypedEvents(); const bulkEvents = { uid: adomikAdapter.currentContext.uid, ahbaid: adomikAdapter.currentContext.id, - timeout: adomikAdapter.currentContext.timeout, hostname: window.location.hostname, eventsByPlacementCode: groupedTypedEvents.map(function(typedEventsByType) { let sizes = []; @@ -108,8 +102,11 @@ adomikAdapter.sendTypedEvent = function() { }) }; + const stringBulkEvents = JSON.stringify(bulkEvents) + logInfo('Events sent to adomik prebid analytic ' + stringBulkEvents); + // Encode object in base64 - const encodedBuf = window.btoa(JSON.stringify(bulkEvents)); + const encodedBuf = window.btoa(stringBulkEvents); // Create final url and split it in 1600 characters max (+endpoint length) const encodedUri = encodeURIComponent(encodedBuf); @@ -122,6 +119,17 @@ adomikAdapter.sendTypedEvent = function() { }) }; +adomikAdapter.sendWonEvent = function (wonEvent) { + 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` +} + adomikAdapter.buildBidResponse = function (bid) { return { bidder: bid.bidderCode.toUpperCase(), @@ -181,23 +189,20 @@ adomikAdapter.buildTypedEvents = function () { return groupedTypedEvents; } -// Initialize adomik object -adomikAdapter.currentContext = {}; -adomikAdapter.bucketEvents = []; - adomikAdapter.adapterEnableAnalytics = adomikAdapter.enableAnalytics; adomikAdapter.enableAnalytics = function (config) { + adomikAdapter.currentContext = {}; + const initOptions = config.options; if (initOptions) { adomikAdapter.currentContext = { uid: initOptions.id, url: initOptions.url, - debug: initOptions.debug, id: '', timeouted: false, - timeout: 0, } + logInfo('Adomik Analytics enabled with config', initOptions); adomikAdapter.adapterEnableAnalytics(config); } }; diff --git a/test/spec/modules/adomikAnalyticsAdapter_spec.js b/test/spec/modules/adomikAnalyticsAdapter_spec.js index 1907cfb14b8..37a5b46a8a2 100644 --- a/test/spec/modules/adomikAnalyticsAdapter_spec.js +++ b/test/spec/modules/adomikAnalyticsAdapter_spec.js @@ -9,6 +9,7 @@ describe('Adomik Prebid Analytic', function () { beforeEach(() => { sinon.spy(adomikAnalytics, 'track'); sinon.spy(adomikAnalytics, 'sendTypedEvent'); + sinon.spy(adomikAnalytics, 'sendWonEvent'); }); afterEach(() => { @@ -51,25 +52,21 @@ describe('Adomik Prebid Analytic', function () { expect(adomikAnalytics.currentContext).to.deep.equal({ uid: '123456', url: 'testurl', - debug: undefined, id: '', - timeouted: false, - timeout: 0, + timeouted: false }); - // Step 1: Send init auction event - events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions, auctionId: 'test-test-test', timeout: 3000}); + // Step 2: Send init auction event + events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions, auctionId: 'test-test-test'}); expect(adomikAnalytics.currentContext).to.deep.equal({ uid: '123456', url: 'testurl', - debug: undefined, id: 'test-test-test', - timeouted: false, - timeout: 3000, + timeouted: false }); - // Step 2: Send bid requested event + // Step 3: Send bid requested event events.emit(constants.EVENTS.BID_REQUESTED, { bids: [bid] }); expect(adomikAnalytics.bucketEvents.length).to.equal(1); @@ -81,7 +78,7 @@ describe('Adomik Prebid Analytic', function () { } }); - // Step 3: Send bid response event + // Step 4: Send bid response event events.emit(constants.EVENTS.BID_RESPONSE, bid); expect(adomikAnalytics.bucketEvents.length).to.equal(2); @@ -102,29 +99,23 @@ describe('Adomik Prebid Analytic', function () { } }); - // Step 4: Send bid won event + // Step 5: Send bid won event events.emit(constants.EVENTS.BID_WON, bid); - expect(adomikAnalytics.bucketEvents.length).to.equal(3); - expect(adomikAnalytics.bucketEvents[2]).to.deep.equal({ - type: 'winner', - event: { - id: '1234', - placementCode: '0000', - } - }); + expect(adomikAnalytics.bucketEvents.length).to.equal(2); - // Step 5: Send bid timeout event + // Step 6: Send bid timeout event events.emit(constants.EVENTS.BID_TIMEOUT, {}); expect(adomikAnalytics.currentContext.timeouted).to.equal(true); - // Step 6: Send auction end event + // Step 7: Send auction end event var clock = sinon.useFakeTimers(); events.emit(constants.EVENTS.AUCTION_END, {}); setTimeout(function() { sinon.assert.callCount(adomikAnalytics.sendTypedEvent, 1); + sinon.assert.callCount(adomikAnalytics.sendWonEvent, 1); done(); }, 3000); From 1b20a1c8c2dc68eb054d5295c26825917e9c5d49 Mon Sep 17 00:00:00 2001 From: lntho Date: Mon, 22 Jan 2018 12:18:31 -0800 Subject: [PATCH 0044/1594] OpenX Adapter: Update to support mediaTypes field, instead of the deprecated mediaType field (#1974) --- modules/openxBidAdapter.js | 22 +++-- modules/openxBidAdapter.md | 10 +- test/spec/modules/openxBidAdapter_spec.js | 111 +++++++++++++++------- 3 files changed, 96 insertions(+), 47 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 051f9ace2de..9ed4f1250f8 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -30,15 +30,21 @@ export const spec = { let requests = []; let bannerRequests = []; let videoRequests = []; - let bannerBids = []; - let videoBids = []; - bids.forEach(function (bid) { - if (bid.mediaType === VIDEO) { - videoBids.push(bid); - } else { - bannerBids.push(bid); + const {bannerBids, videoBids} = bids.reduce(function(acc, curBid) { + // Fallback to banner ads if nothing specified + if (!curBid.mediaTypes || utils.isEmpty(curBid.mediaTypes)) { + if (curBid.mediaType && curBid.mediaType == VIDEO) { + acc.videoBids.push(curBid); + } else { + acc.bannerBids.push(curBid); + } + } else if (curBid.mediaTypes.video) { + acc.videoBids.push(curBid); + } else if (curBid.mediaTypes.banner) { + acc.bannerBids.push(curBid); } - }); + return acc; + }, {bannerBids: [], videoBids: []}); // build banner requests if (bannerBids.length !== 0) { diff --git a/modules/openxBidAdapter.md b/modules/openxBidAdapter.md index 1f04c2fe466..9e9d3ebfa7a 100644 --- a/modules/openxBidAdapter.md +++ b/modules/openxBidAdapter.md @@ -16,13 +16,13 @@ Module that connects to OpenX's demand sources { code: 'test-div', sizes: [[728, 90]], // a display size - mediaType: 'banner', + mediaTypes: {'banner': {}}, bids: [ { - bidder: "openx", + bidder: 'openx', params: { - unit: "539439964", - delDomain: "se-demo-d.openx.net" + unit: '539439964', + delDomain: 'se-demo-d.openx.net' } } ] @@ -30,7 +30,7 @@ Module that connects to OpenX's demand sources { code: 'video1', sizes: [[640,480]], - mediaType: 'video', + mediaTypes: {'video': {}}, bids: [ { bidder: 'openx', diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index eabf1f81f32..0b0e8e54ebb 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -15,7 +15,7 @@ describe('OpenxAdapter', () => { }); describe('isBidRequestValid', () => { - let bid = { + const bid = { 'bidder': 'openx', 'params': { 'unit': '12345678', @@ -29,7 +29,7 @@ describe('OpenxAdapter', () => { 'auctionId': '1d1a030790a475', }; - let videoBid = { + const videoBid = { 'bidder': 'openx', 'params': { 'unit': '12345678', @@ -73,7 +73,7 @@ describe('OpenxAdapter', () => { }); describe('buildRequests for banner ads', () => { - let bidRequestsWithNoMediaType = [{ + const bidRequestsWithNoMediaType = [{ 'bidder': 'openx', 'params': { 'unit': '12345678', @@ -85,7 +85,7 @@ describe('OpenxAdapter', () => { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', }]; - let bidRequests = [{ + const bidRequestsWithMediaType = [{ 'bidder': 'openx', 'params': { 'unit': '12345678', @@ -98,21 +98,40 @@ describe('OpenxAdapter', () => { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', }]; + const bidRequestsWithMediaTypes = [{ + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + 'mediaTypes': {banner: {}}, + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }]; it('should send bid request to openx url via GET, even without mediaType specified', () => { const request = spec.buildRequests(bidRequestsWithNoMediaType); - expect(request[0].url).to.equal('//' + bidRequests[0].params.delDomain + URLBASE); + expect(request[0].url).to.equal('//' + bidRequestsWithNoMediaType[0].params.delDomain + URLBASE); + expect(request[0].method).to.equal('GET'); + }); + + it('should send bid request to openx url via GET, with mediaType specified as banner', () => { + const request = spec.buildRequests(bidRequestsWithMediaType); + expect(request[0].url).to.equal('//' + bidRequestsWithNoMediaType[0].params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); }); - it('should send bid request to openx url via GET', () => { - const request = spec.buildRequests(bidRequests); - expect(request[0].url).to.equal('//' + bidRequests[0].params.delDomain + URLBASE); + it('should send bid request to openx url via GET, with mediaTypes specified with banner type', () => { + const request = spec.buildRequests(bidRequestsWithMediaTypes); + expect(request[0].url).to.equal('//' + bidRequestsWithNoMediaType[0].params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); }); it('should have the correct parameters', () => { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequestsWithNoMediaType); const dataParams = request[0].data; expect(dataParams.auid).to.exist; @@ -122,8 +141,8 @@ describe('OpenxAdapter', () => { }); it('should send out custom params on bids that have customParams specified', () => { - let bidRequest = Object.assign({}, - bidRequests[0], + const bidRequest = Object.assign({}, + bidRequestsWithMediaTypes[0], { params: { 'unit': '12345678', @@ -141,8 +160,8 @@ describe('OpenxAdapter', () => { }); it('should send out custom floors on bids that have customFloors specified', () => { - let bidRequest = Object.assign({}, - bidRequests[0], + const bidRequest = Object.assign({}, + bidRequestsWithMediaTypes[0], { params: { 'unit': '12345678', @@ -160,8 +179,8 @@ describe('OpenxAdapter', () => { }); it('should send out custom bc parameter, if override is present', () => { - let bidRequest = Object.assign({}, - bidRequests[0], + const bidRequest = Object.assign({}, + bidRequestsWithMediaTypes[0], { params: { 'unit': '12345678', @@ -180,7 +199,25 @@ describe('OpenxAdapter', () => { }); describe('buildRequests for video', () => { - let bidRequests = [{ + const bidRequestsWithMediaTypes = [{ + 'bidder': 'openx', + 'mediaTypes': {video: {}}, + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain', + 'video': { + 'url': 'abc.com', + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' + }]; + + const bidRequestsWithMediaType = [{ 'bidder': 'openx', 'mediaType': 'video', 'params': { @@ -198,14 +235,20 @@ describe('OpenxAdapter', () => { 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' }]; - it('should send bid request to openx url via GET', () => { - const request = spec.buildRequests(bidRequests); - expect(request[0].url).to.equal('http://' + bidRequests[0].params.delDomain + URLBASEVIDEO); + it('should send bid request to openx url via GET, with mediaType as video', () => { + const request = spec.buildRequests(bidRequestsWithMediaType); + expect(request[0].url).to.equal('http://' + bidRequestsWithMediaType[0].params.delDomain + URLBASEVIDEO); + expect(request[0].method).to.equal('GET'); + }); + + it('should send bid request to openx url via GET, with mediaTypes having video parameter', () => { + const request = spec.buildRequests(bidRequestsWithMediaTypes); + expect(request[0].url).to.equal('http://' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); it('should have the correct parameters', () => { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequestsWithMediaTypes); const dataParams = request[0].data; expect(dataParams.auid).to.exist; @@ -216,7 +259,7 @@ describe('OpenxAdapter', () => { }); describe('interpretResponse for banner ads', () => { - let bids = [{ + const bids = [{ 'bidder': 'openx', 'params': { 'unit': '12345678', @@ -229,13 +272,13 @@ describe('OpenxAdapter', () => { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', }]; - let bidRequest = { + const bidRequest = { method: 'GET', url: 'url', data: {}, payload: {'bids': bids, 'startTime': new Date()} }; - let bidResponse = { + const bidResponse = { 'ads': { 'version': 1, @@ -272,7 +315,7 @@ describe('OpenxAdapter', () => { } }; it('should return correct bid response', () => { - let expectedResponse = [ + const expectedResponse = [ { 'requestId': '30b31c1838de1e', 'cpm': 1, @@ -287,12 +330,12 @@ describe('OpenxAdapter', () => { } ]; - let result = spec.interpretResponse({body: bidResponse}, bidRequest); + const result = spec.interpretResponse({body: bidResponse}, bidRequest); expect(Object.keys(result[0])).to.eql(Object.keys(expectedResponse[0])); }); it('handles nobid responses', () => { - let bidResponse = { + const bidResponse = { 'ads': { 'version': 1, @@ -302,13 +345,13 @@ describe('OpenxAdapter', () => { } }; - let result = spec.interpretResponse({body: bidResponse}, bidRequest); + const result = spec.interpretResponse({body: bidResponse}, bidRequest); expect(result.length).to.equal(0); }); }); describe('interpretResponse for video ads', () => { - let bids = [{ + const bids = [{ 'bidder': 'openx', 'mediaType': 'video', 'params': { @@ -325,13 +368,13 @@ describe('OpenxAdapter', () => { 'auctionId': '1d1a030790a475', 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' }]; - let bidRequest = { + const bidRequest = { method: 'GET', url: 'url', data: {}, payload: {'bid': bids[0], 'startTime': new Date()} }; - let bidResponse = { + const bidResponse = { 'pub_rev': '1', 'width': '640', 'height': '480', @@ -341,7 +384,7 @@ describe('OpenxAdapter', () => { }; it('should return correct bid response', () => { - let expectedResponse = [ + const expectedResponse = [ { 'requestId': '30b31c1838de1e', 'bidderCode': 'openx', @@ -357,13 +400,13 @@ describe('OpenxAdapter', () => { } ]; - let result = spec.interpretResponse({body: bidResponse}, bidRequest); + const result = spec.interpretResponse({body: bidResponse}, bidRequest); expect(JSON.stringify(Object.keys(result[0]).sort())).to.eql(JSON.stringify(Object.keys(expectedResponse[0]).sort())); }); it('handles nobid responses', () => { - let bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; - let result = spec.interpretResponse({body: bidResponse}, bidRequest); + const bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; + const result = spec.interpretResponse({body: bidResponse}, bidRequest); expect(result.length).to.equal(0); }); }); From c1d86eacdb60133123523c976c53940e8199d20d Mon Sep 17 00:00:00 2001 From: Agustin Insua Date: Mon, 22 Jan 2018 18:57:43 -0300 Subject: [PATCH 0045/1594] Add eplanningBidAdapter (#2003) * Add eplanningBidAdapter * Add new parameter to request * Fix sync URL parameter --- modules/eplanningBidAdapter.js | 156 ++++++++ modules/eplanningBidAdapter.md | 25 ++ test/spec/modules/eplanningBidAdapter_spec.js | 350 ++++++++++++++++++ 3 files changed, 531 insertions(+) create mode 100644 modules/eplanningBidAdapter.js create mode 100644 modules/eplanningBidAdapter.md create mode 100644 test/spec/modules/eplanningBidAdapter_spec.js diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js new file mode 100644 index 00000000000..dfc5f514cf3 --- /dev/null +++ b/modules/eplanningBidAdapter.js @@ -0,0 +1,156 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'eplanning'; +const rnd = Math.random(); +const DEFAULT_SV = 'ads.us.e-planning.net'; +const DEFAULT_ISV = 'i.e-planning.net'; +const PARAMS = ['ci', 'sv', 't']; +const DOLLARS = 'USD'; +const NET_REVENUE = true; +const TTL = 120; +const NULL_SIZE = '1x1'; +const FILE = 'file'; + +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: function(bid) { + return Boolean(bid.params.ci) || Boolean(bid.params.t); + }, + buildRequests: function(bidRequests) { + const method = 'GET'; + const dfpClientId = '1'; + const sec = 'ROS'; + let url; + let params; + const urlConfig = getUrlConfig(bidRequests); + + if (urlConfig.t) { + url = urlConfig.isv + '/layers/t_pbjs_2.json'; + params = {}; + } else { + url = '//' + (urlConfig.sv || DEFAULT_SV) + '/hb/1/' + urlConfig.ci + '/' + dfpClientId + '/' + (utils.getTopWindowLocation().hostname || FILE) + '/' + sec; + const referrerUrl = utils.getTopWindowReferrer(); + const spacesString = getSpacesString(bidRequests); + params = { + rnd: rnd, + e: spacesString, + ur: utils.getTopWindowUrl() || FILE, + r: 'pbjs', + pbv: '$prebid.version$', + ncb: '1' + }; + if (referrerUrl) { + params.fr = referrerUrl; + } + } + + return { + method: method, + url: url, + data: params, + adUnitToBidId: getBidIdMap(bidRequests), + }; + }, + interpretResponse: function(serverResponse, request) { + const response = serverResponse.body; + let bidResponses = []; + + if (response && !utils.isEmpty(response.sp)) { + response.sp.forEach(space => { + if (!utils.isEmpty(space.a)) { + space.a.forEach(ad => { + const bidResponse = { + requestId: request.adUnitToBidId[space.k], + cpm: ad.pr, + width: ad.w, + height: ad.h, + ad: ad.adm, + ttl: TTL, + creativeId: ad.crid, + netRevenue: NET_REVENUE, + currency: DOLLARS, + }; + bidResponses.push(bidResponse); + }); + } + }); + } + + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = []; + const response = !utils.isEmpty(serverResponses) && serverResponses[0].body; + + if (response && !utils.isEmpty(response.cs)) { + const responseSyncs = response.cs; + responseSyncs.forEach(sync => { + if (typeof sync === 'string' && syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: sync, + }); + } else if (typeof sync === 'object' && sync.ifr && syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: sync.u, + }) + } + }); + } + + return syncs; + }, +} + +function cleanName(name) { + return name.replace(/_|\.|-|\//g, '').replace(/\)\(|\(|\)/g, '_').replace(/^_+|_+$/g, ''); +} +function getUrlConfig(bidRequests) { + if (isTestRequest(bidRequests)) { + return getTestConfig(bidRequests.filter(br => br.params.t)); + } + + let config = {}; + bidRequests.forEach(bid => { + PARAMS.forEach(param => { + if (bid.params[param] && !config[param]) { + config[param] = bid.params[param]; + } + }); + }); + + if (config.sv) { + config.sv = '//' + config.sv; + } + + return config; +} +function isTestRequest(bidRequests) { + let isTest = false; + bidRequests.forEach(bid => isTest = bid.params.t); + return isTest; +} +function getTestConfig(bidRequests) { + let isv; + bidRequests.forEach(br => isv = isv || br.params.isv); + return { + t: true, + isv: '//' + (isv || DEFAULT_ISV) + }; +} +function getSpacesString(bids) { + const spacesString = bids.map(bid => + cleanName(bid.adUnitCode) + ':' + (bid.sizes && bid.sizes.length ? utils.parseSizesInput(bid.sizes).join(',') : NULL_SIZE) + ).join('+'); + + return spacesString; +} +function getBidIdMap(bidRequests) { + let map = {}; + bidRequests.forEach(bid => map[cleanName(bid.adUnitCode)] = bid.bidId); + return map; +} + +registerBidder(spec); diff --git a/modules/eplanningBidAdapter.md b/modules/eplanningBidAdapter.md new file mode 100644 index 00000000000..b6cfbb535b6 --- /dev/null +++ b/modules/eplanningBidAdapter.md @@ -0,0 +1,25 @@ +# Overview + +``` +Module Name: E-Planning Bid Adapter +Module Type: Bidder Adapter +Maintainer: ainsua@e-planning.net +``` + +# Description + +Connects to E-Planning exchange for bids. + +# Test Parameters +``` +var adUnits = [{ + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250]], + bids: [{ + bidder: 'eplanning', + params: { + t: 1 + } + }] +}]; +``` diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js new file mode 100644 index 00000000000..2ec7f482edd --- /dev/null +++ b/test/spec/modules/eplanningBidAdapter_spec.js @@ -0,0 +1,350 @@ +import { expect } from 'chai'; +import { spec } from 'modules/eplanningBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +describe('E-Planning Adapter', () => { + const adapter = newBidder('spec'); + const CI = '12345'; + const ADUNIT_CODE = 'adunit-code'; + const ADUNIT_CODE2 = 'adunit-code-dos'; + const CLEAN_ADUNIT_CODE2 = 'adunitcodedos'; + const CLEAN_ADUNIT_CODE = 'adunitcode'; + const BID_ID = '123456789'; + const BID_ID2 = '987654321'; + const CPM = 1.3; + const W = '300'; + const H = '250'; + const ADM = '
This is an ad
'; + const I_ID = '7854abc56248f873'; + const CRID = '1234567890'; + const TEST_ISV = 'leles.e-planning.net'; + const validBid = { + 'bidder': 'eplanning', + 'bidId': BID_ID, + 'params': { + 'ci': CI, + }, + 'adUnitCode': ADUNIT_CODE, + 'sizes': [[300, 250], [300, 600]], + }; + const validBid2 = { + 'bidder': 'eplanning', + 'bidId': BID_ID2, + 'params': { + 'ci': CI, + }, + 'adUnitCode': ADUNIT_CODE2, + 'sizes': [[300, 250], [300, 600]], + }; + const testBid = { + 'bidder': 'eplanning', + 'params': { + 't': 1, + 'isv': TEST_ISV + }, + 'adUnitCode': ADUNIT_CODE, + 'sizes': [[300, 250], [300, 600]], + }; + const invalidBid = { + 'bidder': 'eplanning', + 'params': { + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + }; + const response = { + body: { + 'sI': { + 'k': '12345' + }, + 'sec': { + 'k': 'ROS' + }, + 'sp': [{ + 'k': CLEAN_ADUNIT_CODE, + 'a': [{ + 'adm': ADM, + 'id': '7854abc56248f874', + 'i': I_ID, + 'fi': '7854abc56248f872', + 'ip': '45621afd87462104', + 'w': W, + 'h': H, + 'crid': CRID, + 'pr': CPM + }], + }], + 'cs': [ + 'http://a-sync-url.com/', + { + 'u': 'http://another-sync-url.com/test.php?&partner=123456&endpoint=us-east', + 'ifr': true + } + ] + } + }; + const responseWithTwoAdunits = { + body: { + 'sI': { + 'k': '12345' + }, + 'sec': { + 'k': 'ROS' + }, + 'sp': [{ + 'k': CLEAN_ADUNIT_CODE, + 'a': [{ + 'adm': ADM, + 'id': '7854abc56248f874', + 'i': I_ID, + 'fi': '7854abc56248f872', + 'ip': '45621afd87462104', + 'w': W, + 'h': H, + 'crid': CRID, + 'pr': CPM + }] + }, { + 'k': CLEAN_ADUNIT_CODE2, + 'a': [{ + 'adm': ADM, + 'id': '7854abc56248f874', + 'i': I_ID, + 'fi': '7854abc56248f872', + 'ip': '45621afd87462104', + 'w': W, + 'h': H, + 'crid': CRID, + 'pr': CPM + }], + }, + ], + 'cs': [ + 'http://a-sync-url.com/', + { + 'u': 'http://another-sync-url.com/test.php?&partner=123456&endpoint=us-east', + 'ifr': true + } + ] + } + }; + const responseWithNoAd = { + body: { + 'sI': { + 'k': '12345' + }, + 'sec': { + 'k': 'ROS' + }, + 'sp': [{ + 'k': 'spname', + }], + 'cs': [ + 'http://a-sync-url.com/', + { + 'u': 'http://another-sync-url.com/test.php?&partner=123456&endpoint=us-east', + 'ifr': true + } + ] + } + }; + const responseWithNoSpace = { + body: { + 'sI': { + 'k': '12345' + }, + 'sec': { + 'k': 'ROS' + }, + 'cs': [ + 'http://a-sync-url.com/', + { + 'u': 'http://another-sync-url.com/test.php?&partner=123456&endpoint=us-east', + 'ifr': true + } + ] + } + }; + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when bid has ci parameter', () => { + expect(spec.isBidRequestValid(validBid)).to.equal(true); + }); + + it('should return false when bid does not have ci parameter and is not a test bid', () => { + expect(spec.isBidRequestValid(invalidBid)).to.equal(false); + }); + + it('should return true when bid does not have ci parameter but is a test bid'), () => { + expect(spec.isBidRequestValid(testBid).to.equal(true)); + } + }); + + describe('buildRequests', () => { + let bidRequests = [validBid]; + + it('should create the url correctly', () => { + const url = spec.buildRequests(bidRequests).url; + expect(url).to.equal('//ads.us.e-planning.net/hb/1/' + CI + '/1/localhost/ROS'); + }); + + it('should return GET method', () => { + const method = spec.buildRequests(bidRequests).method; + expect(method).to.equal('GET'); + }); + + it('should return r parameter with value pbjs', () => { + const r = spec.buildRequests(bidRequests).data.r; + expect(r).to.equal('pbjs'); + }); + + it('should return pbv parameter with value prebid version', () => { + const pbv = spec.buildRequests(bidRequests).data.pbv; + expect(pbv).to.equal('$prebid.version$'); + }); + + it('should return e parameter with value according to the adunit sizes', () => { + const e = spec.buildRequests(bidRequests).data.e; + expect(e).to.equal(CLEAN_ADUNIT_CODE + ':300x250,300x600'); + }); + + it('should return correct e parameter with more than one adunit', () => { + const NEW_CODE = ADUNIT_CODE + '2'; + const CLEAN_NEW_CODE = CLEAN_ADUNIT_CODE + '2'; + const anotherBid = { + 'bidder': 'eplanning', + 'params': { + 'ci': CI, + }, + 'adUnitCode': NEW_CODE, + 'sizes': [[100, 100]], + }; + bidRequests.push(anotherBid); + + const e = spec.buildRequests(bidRequests).data.e; + expect(e).to.equal(CLEAN_ADUNIT_CODE + ':300x250,300x600+' + CLEAN_NEW_CODE + ':100x100'); + }); + + it('should return correct e parameter when the adunit has no size', () => { + const noSizeBid = { + 'bidder': 'eplanning', + 'params': { + 'ci': CI, + }, + 'adUnitCode': ADUNIT_CODE, + }; + + const e = spec.buildRequests([noSizeBid]).data.e; + expect(e).to.equal(CLEAN_ADUNIT_CODE + ':1x1'); + }); + + it('should return ur parameter with current window url', () => { + const ur = spec.buildRequests(bidRequests).data.ur; + expect(ur).to.equal(utils.getTopWindowUrl()); + }); + + it('should return fr parameter when there is a referrer', () => { + const referrer = 'thisisafakereferrer'; + const stubGetReferrer = sinon.stub(utils, 'getTopWindowReferrer').returns(referrer); + after(() => stubGetReferrer.restore()); + + const fr = spec.buildRequests(bidRequests).data.fr; + expect(fr).to.equal(referrer); + }); + + it('should return the testing url when the request has the t parameter', () => { + const url = spec.buildRequests([testBid]).url; + const expectedUrl = '//' + TEST_ISV + '/layers/t_pbjs_2.json'; + expect(url).to.equal(expectedUrl); + }); + + it('should return the parameter ncb with value 1', () => { + const ncb = spec.buildRequests(bidRequests).data.ncb; + expect(ncb).to.equal('1'); + }); + }); + + describe('interpretResponse', () => { + it('should return an empty array when there is no ads in the response', () => { + const bidResponses = spec.interpretResponse(responseWithNoAd); + expect(bidResponses).to.be.empty; + }); + + it('should return an empty array when there is no spaces in the response', () => { + const bidResponses = spec.interpretResponse(responseWithNoSpace); + expect(bidResponses).to.be.empty; + }); + + it('should correctly map the parameters in the response', () => { + const bidResponse = spec.interpretResponse(response, { adUnitToBidId: { [CLEAN_ADUNIT_CODE]: BID_ID } })[0]; + const expectedResponse = { + requestId: BID_ID, + cpm: CPM, + width: W, + height: H, + ad: ADM, + ttl: 120, + creativeId: CRID, + netRevenue: true, + currency: 'USD', + }; + expect(bidResponse).to.deep.equal(expectedResponse); + }); + }); + + describe('getUserSyncs', () => { + const sOptionsAllEnabled = { + pixelEnabled: true, + iframeEnabled: true + }; + const sOptionsAllDisabled = { + pixelEnabled: false, + iframeEnabled: false + }; + const sOptionsOnlyPixel = { + pixelEnabled: true, + iframeEnabled: false + }; + const sOptionsOnlyIframe = { + pixelEnabled: false, + iframeEnabled: true + }; + + it('should return an empty array if the response has no syncs', () => { + const noSyncsResponse = { cs: [] }; + const syncs = spec.getUserSyncs(sOptionsAllEnabled, [noSyncsResponse]); + expect(syncs).to.be.empty; + }); + + it('should return an empty array if there is no sync options enabled', () => { + const syncs = spec.getUserSyncs(sOptionsAllDisabled, [response]); + expect(syncs).to.be.empty; + }); + + it('should only return pixels if iframe is not enabled', () => { + const syncs = spec.getUserSyncs(sOptionsOnlyPixel, [response]); + syncs.forEach(sync => expect(sync.type).to.equal('image')); + }); + + it('should only return iframes if pixel is not enabled', () => { + const syncs = spec.getUserSyncs(sOptionsOnlyIframe, [response]); + syncs.forEach(sync => expect(sync.type).to.equal('iframe')); + }); + }); + + describe('adUnits mapping to bidId', () => { + it('should correctly map the bidId to the adunit', () => { + const requests = spec.buildRequests([validBid, validBid2]); + const responses = spec.interpretResponse(responseWithTwoAdunits, requests); + expect(responses[0].requestId).to.equal(BID_ID); + expect(responses[1].requestId).to.equal(BID_ID2); + }); + }); +}); From 64569594731f7f72c732ea32ccb1a460f052611d Mon Sep 17 00:00:00 2001 From: Snoop Date: Tue, 23 Jan 2018 01:30:12 +0200 Subject: [PATCH 0046/1594] Add vi bid adapter (#2020) * VI prebid.js adapter (points dev platform) * fix typo * Changed maintainer email * Added test parameters * Changed bidder hostname to pb.vi-serve.com * updated doc * Update viBidAdapter.md * VI bid adapter - tests * Removed unused import from spec, specified radix in parseInt * handling of various sizes formats --- modules/viBidAdapter.js | 69 ++++++++++++ modules/viBidAdapter.md | 41 ++++++++ test/spec/modules/viBidAdapter_spec.js | 139 +++++++++++++++++++++++++ 3 files changed, 249 insertions(+) create mode 100644 modules/viBidAdapter.js create mode 100644 modules/viBidAdapter.md create mode 100644 test/spec/modules/viBidAdapter_spec.js diff --git a/modules/viBidAdapter.js b/modules/viBidAdapter.js new file mode 100644 index 00000000000..bcfc4e246ac --- /dev/null +++ b/modules/viBidAdapter.js @@ -0,0 +1,69 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'vi'; +const SUPPORTED_MEDIA_TYPES = [BANNER]; + +function isBidRequestValid(bid) { + return !!(bid.params.pubId); +} + +function buildRequests(bidReqs) { + let imps = []; + utils._each(bidReqs, function (bid) { + imps.push({ + id: bid.bidId, + sizes: utils.parseSizesInput(bid.sizes).map(size => size.split('x')), + bidFloor: parseFloat(bid.params.bidFloor) > 0 ? bid.params.bidFloor : 0 + }); + }); + + const bidRequest = { + id: bidReqs[0].requestId, + imps: imps, + publisherId: utils.getBidIdParameter('pubId', bidReqs[0].params), + siteId: utils.getBidIdParameter('siteId', bidReqs[0].params), + cat: utils.getBidIdParameter('cat', bidReqs[0].params), + language: utils.getBidIdParameter('lang', bidReqs[0].params), + domain: utils.getTopWindowLocation().hostname, + page: utils.getTopWindowUrl(), + referrer: utils.getTopWindowReferrer() + }; + return { + method: 'POST', + url: `//pb.vi-serve.com/prebid/bid`, + data: JSON.stringify(bidRequest), + options: {contentType: 'application/json', withCredentials: false} + }; +} + +function interpretResponse(bids) { + let responses = []; + utils._each(bids.body, function(bid) { + responses.push({ + requestId: bid.id, + cpm: parseFloat(bid.price), + width: parseInt(bid.width, 10), + height: parseInt(bid.height, 10), + creativeId: bid.creativeId, + dealId: bid.dealId || null, + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: decodeURIComponent(`${bid.ad}`), + ttl: 60000 + }); + }); + return responses; +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: SUPPORTED_MEDIA_TYPES, + isBidRequestValid, + buildRequests, + interpretResponse +} + +registerBidder(spec); diff --git a/modules/viBidAdapter.md b/modules/viBidAdapter.md new file mode 100644 index 00000000000..23288024fcc --- /dev/null +++ b/modules/viBidAdapter.md @@ -0,0 +1,41 @@ +# Overview + +``` +Module Name: vi bid adapter +Module Type: Bidder adapter +Maintainer: support@vi.ai +``` + +# Description + +The video intelligence (vi) adapter integration to the Prebid library. +Connects to vi’s demand sources. +There should be only one ad unit with vi bid adapter on each single page. + +# Test Parameters + +``` +var adUnits = [{ + code: 'div-0', + sizes: [[320, 480]], + bids: [{ + bidder: 'vi', + params: { + pubId: 'sb_test', + lang: 'en-US', + cat: 'IAB1', + bidFloor: 0.05 //optional + } + }] +}]; +``` + +# Parameters + +| Name | Scope | Description | Example | +| :------------ | :------- | :---------------------------------------------- | :--------------------------------- | +| `pubId` | required | Publisher ID, provided by vi | 'sb_test' | +| `lang` | required | Ad language, in ISO 639-1 language code format | 'en-US', 'es-ES', 'de' | +| `cat` | required | Ad IAB category (top-level or subcategory), single one supported | 'IAB1', 'IAB9-1' | +| `bidFloor` | optional | Lowest value of expected bid price | 0.001 | + diff --git a/test/spec/modules/viBidAdapter_spec.js b/test/spec/modules/viBidAdapter_spec.js new file mode 100644 index 00000000000..e8b0fbcc4b2 --- /dev/null +++ b/test/spec/modules/viBidAdapter_spec.js @@ -0,0 +1,139 @@ +import { expect } from 'chai'; +import { spec } from 'modules/viBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = `//pb.vi-serve.com/prebid/bid`; + +describe('viBidAdapter', function() { + newBidder(spec); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'vi', + 'params': { + 'pubId': 'sb_test', + 'lang': 'en-US', + 'cat': 'IAB1', + 'bidFloor': 0.05 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [320, 480] + ], + 'bidId': '29b891ad542377', + 'bidderRequestId': '1dc9a08206a57b', + 'requestId': '24176695-e3f0-44db-815b-ed97cf5ad49b', + 'placementCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '474da635-9cf0-4188-a3d9-58961be8f905' + }; + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when pubId not passed', () => { + bid.params.pubId = undefined; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [{ + 'bidder': 'vi', + 'params': { + 'pubId': 'sb_test', + 'lang': 'en-US', + 'cat': 'IAB1', + 'bidFloor': 0.05 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [320, 480] + ], + 'bidId': '29b891ad542377', + 'bidderRequestId': '1dc9a08206a57b', + 'requestId': '24176695-e3f0-44db-815b-ed97cf5ad49b', + 'placementCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '474da635-9cf0-4188-a3d9-58961be8f905' + }]; + + const request = spec.buildRequests(bidRequests); + + it('POST bid request to vi', () => { + expect(request.method).to.equal('POST'); + }); + + it('check endpoint URL', () => { + expect(request.url).to.equal(ENDPOINT) + }); + }); + + describe('buildRequests can handle size in 1-dim array', () => { + let bidRequests = [{ + 'bidder': 'vi', + 'params': { + 'pubId': 'sb_test', + 'lang': 'en-US', + 'cat': 'IAB1', + 'bidFloor': 0.05 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [320, 480], + 'bidId': '29b891ad542377', + 'bidderRequestId': '1dc9a08206a57b', + 'requestId': '24176695-e3f0-44db-815b-ed97cf5ad49b', + 'placementCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '474da635-9cf0-4188-a3d9-58961be8f905' + }]; + + const request = spec.buildRequests(bidRequests); + + it('POST bid request to vi', () => { + expect(request.method).to.equal('POST'); + }); + + it('check endpoint URL', () => { + expect(request.url).to.equal(ENDPOINT) + }); + }); + + describe('interpretResponse', () => { + let response = { + body: [{ + 'id': '29b891ad542377', + 'price': 0.1, + 'width': 320, + 'height': 480, + 'ad': '', + 'creativeId': 'dZsPGv' + }] + }; + + it('should get the correct bid response', () => { + let expectedResponse = [{ + 'requestId': '29b891ad542377', + 'cpm': 0.1, + 'width': 320, + 'height': 480, + 'creativeId': 'dZsPGv', + 'dealId': null, + 'currency': 'USD', + 'netRevenue': true, + 'mediaType': 'banner', + 'ad': decodeURIComponent(``), + 'ttl': 60000 + }]; + + let result = spec.interpretResponse(response); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles empty bid response', () => { + let response = { + body: [] + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From ecc34b6f80f35f2cdf19743818ce1a263e5f8be6 Mon Sep 17 00:00:00 2001 From: Erik Dubbelboer Date: Tue, 23 Jan 2018 07:58:18 +0800 Subject: [PATCH 0047/1594] Update Atomx adapter for Prebid v1.0 (#2026) * Update Atomx adapter for Prebid v1.0 * Add code markup --- modules/atomxBidAdapter.js | 107 +++++++++++++++++++ modules/atomxBidAdapter.md | 25 +++++ test/spec/modules/atomxBidAdapter_spec.js | 119 ++++++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 modules/atomxBidAdapter.js create mode 100644 modules/atomxBidAdapter.md create mode 100644 test/spec/modules/atomxBidAdapter_spec.js diff --git a/modules/atomxBidAdapter.js b/modules/atomxBidAdapter.js new file mode 100644 index 00000000000..f946841dffc --- /dev/null +++ b/modules/atomxBidAdapter.js @@ -0,0 +1,107 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'atomx'; + +function getDomain() { + var domain = ''; + + try { + if ((domain === '') && (window.top == window)) { + domain = window.location.href; + } + + if ((domain === '') && (window.top == window.parent)) { + domain = document.referrer; + } + + if (domain == '') { + var atomxt = 'atomxtest'; + + // It should be impossible to change the window.location.ancestorOrigins. + window.location.ancestorOrigins[0] = atomxt; + if (window.location.ancestorOrigins[0] != atomxt) { + var ancestorOrigins = window.location.ancestorOrigins; + + // If the length is 0 we are a javascript tag running in the main domain. + // But window.top != window or window.location.hostname is empty. + if (ancestorOrigins.length == 0) { + // This browser is so fucked up, just return an empty string. + return ''; + } + + // ancestorOrigins is an array where [0] is our own window.location + // and [length-1] is the top window.location. + domain = ancestorOrigins[ancestorOrigins.length - 1]; + } + } + } catch (unused) { + } + + if (domain === '') { + domain = document.referrer; + } + + if (domain === '') { + domain = window.location.href; + } + + return domain.substr(0, 512); +} + +export const spec = { + code: BIDDER_CODE, + + isBidRequestValid: function(bid) { + return bid.params && (!!bid.params.id); + }, + + buildRequests: function(validBidRequests) { + return validBidRequests.map(bidRequest => { + return { + method: 'GET', + url: location.protocol + '//p.ato.mx/placement', + data: { + v: 12, + id: bidRequest.params.id, + size: utils.parseSizesInput(bidRequest.sizes)[0], + prebid: bidRequest.bidId, + b: 0, + h: '7t3y9', + type: 'javascript', + screen: window.screen.width + 'x' + window.screen.height + 'x' + window.screen.colorDepth, + timezone: new Date().getTimezoneOffset(), + domain: getDomain(), + r: document.referrer.substr(0, 512), + }, + }; + }); + }, + + interpretResponse: function (serverResponse, bidRequest) { + const body = serverResponse.body; + const res = { + requestId: body.code, + cpm: body.cpm * 1000, + width: body.width, + height: body.height, + creativeId: body.creative_id, + currency: 'USD', + netRevenue: true, + ttl: 60, + }; + + if (body.adm) { + res.ad = body.adm; + } else { + res.adUrl = body.url; + } + + return [res]; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + return []; + }, +}; +registerBidder(spec); diff --git a/modules/atomxBidAdapter.md b/modules/atomxBidAdapter.md new file mode 100644 index 00000000000..7f32b12fdfe --- /dev/null +++ b/modules/atomxBidAdapter.md @@ -0,0 +1,25 @@ +# Overview +Module Name: Atomx Bidder Adapter Module +Type: Bidder Adapter +Maintainer: erik@atomx.com + +# Description +Atomx Bidder Adapter for Prebid.js. + +# Test Parameters +``` +var adUnits = [ +{ + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: 'atomx', + params: { + id: 4025860, + } + } + ] +} +]; +``` diff --git a/test/spec/modules/atomxBidAdapter_spec.js b/test/spec/modules/atomxBidAdapter_spec.js new file mode 100644 index 00000000000..fdbb01a1838 --- /dev/null +++ b/test/spec/modules/atomxBidAdapter_spec.js @@ -0,0 +1,119 @@ +import { expect } from 'chai'; +import { spec } from 'modules/atomxBidAdapter'; + +describe('atomxAdapterTest', () => { + describe('bidRequestValidity', () => { + it('bidRequest with id param', () => { + expect(spec.isBidRequestValid({ + bidder: 'atomx', + params: { + id: 1234, + }, + })).to.equal(true); + }); + + it('bidRequest with no id param', () => { + expect(spec.isBidRequestValid({ + bidder: 'atomx', + params: { + }, + })).to.equal(false); + }); + }); + + describe('bidRequest', () => { + const bidRequests = [{ + 'bidder': 'atomx', + 'params': { + 'id': '123' + }, + 'adUnitCode': 'aaa', + 'transactionId': '1b8389fe-615c-482d-9f1a-177fb8f7d5b0', + 'sizes': [300, 250], + 'bidId': '1abgs362e0x48a8', + 'bidderRequestId': '70deaff71c281d', + 'auctionId': '5c66da22-426a-4bac-b153-77360bef5337' + }, + { + 'bidder': 'atomx', + 'params': { + 'id': '456', + }, + 'adUnitCode': 'bbb', + 'transactionId': '193995b4-7122-4739-959b-2463282a138b', + 'sizes': [[800, 600]], + 'bidId': '22aidtbx5eabd9', + 'bidderRequestId': '70deaff71c281d', + 'auctionId': 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' + }]; + + it('bidRequest HTTP method', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + }); + }); + + it('bidRequest url', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.url).to.match(new RegExp('p\\.ato\\.mx/placement')); + }); + }); + + it('bidRequest data', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].data.id).to.equal('123'); + expect(requests[0].data.size).to.equal('300x250'); + expect(requests[0].data.prebid).to.equal('1abgs362e0x48a8'); + expect(requests[1].data.id).to.equal('456'); + expect(requests[1].data.size).to.equal('800x600'); + expect(requests[1].data.prebid).to.equal('22aidtbx5eabd9'); + }); + }); + + describe('interpretResponse', () => { + const bidRequest = { + 'method': 'GET', + 'url': 'https://p.ato.mx/placement', + 'data': { + 'v': 12, + 'id': '123', + 'size': '300x250', + 'prebid': '22aidtbx5eabd9', + 'b': 0, + 'h': '7t3y9', + 'type': 'javascript', + 'screen': '800x600x32', + 'timezone': 0, + 'domain': 'https://example.com', + 'r': '', + } + }; + + const bidResponse = { + body: { + 'cpm': 0.00009, + 'width': 300, + 'height': 250, + 'url': 'http://atomx.com', + 'creative_id': 456, + 'code': '22aidtbx5eabd9', + }, + headers: {} + }; + + it('result is correct', () => { + const result = spec.interpretResponse(bidResponse, bidRequest); + + expect(result[0].requestId).to.equal('22aidtbx5eabd9'); + expect(result[0].cpm).to.equal(0.00009 * 1000); + expect(result[0].width).to.equal(300); + expect(result[0].height).to.equal(250); + expect(result[0].creativeId).to.equal(456); + expect(result[0].currency).to.equal('USD'); + expect(result[0].ttl).to.equal(60); + expect(result[0].adUrl).to.equal('http://atomx.com'); + }); + }); +}); From a264553867172994230484df98e9670bd141c699 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Tue, 23 Jan 2018 21:58:02 +0530 Subject: [PATCH 0048/1594] PubMatic 1.0 adapter (#2011) * first commit * ip field removed, added comments to params, netRevenue set to true also changed surce of end-point to prebid-client from prebid-server * added _processFloor * removed comments * fixed unit test cases * review comments * added method _parseSlotParam removed method _processFloor and _processPmZoneId added const for undefined * minor changes * minor change * publisherId isStr check added * test case for string publisherId and adSlot * using prebid apis for getting pageURL and refURL, added a small function to find domain from given url * bid precision set to 2 * Added test cases for interpretResponse function * do not put warning for undefined valued params * changes for UOE-3239 and UOE-3236 * Linting errors fixed * Add geo object in device * Changes to trim kadpageurl and pmzoneid before sending it in request * Remove spaces when multiple Id's added in pmzoneId * rolling back changes for pmzoneid * Add PubMaticBidAdapter param info * Update params in pubmaticBidAdapter.md * Update maintainer mail-id * endpoint changed to hbopenbid.pubmatic.com, netRevenue default value changed to false, test cases updated * changed auction type to 1 * changed at to 1 in test cases * removed comments * UserSync requirements are mentioned in .md file * updated test ids --- modules/pubmaticBidAdapter.js | 291 +++++++++++++++++++ modules/pubmaticBidAdapter.md | 53 ++++ test/spec/modules/pubmaticBidAdapter_spec.js | 180 ++++++++++++ 3 files changed, 524 insertions(+) create mode 100644 modules/pubmaticBidAdapter.js create mode 100644 modules/pubmaticBidAdapter.md create mode 100644 test/spec/modules/pubmaticBidAdapter_spec.js diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js new file mode 100644 index 00000000000..dfcde047580 --- /dev/null +++ b/modules/pubmaticBidAdapter.js @@ -0,0 +1,291 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +const constants = require('src/constants.json'); + +const BIDDER_CODE = 'pubmatic'; +const ENDPOINT = '//hbopenbid.pubmatic.com/translator?source=prebid-client'; +const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; +const CURRENCY = 'USD'; +const AUCTION_TYPE = 1; +const UNDEFINED = undefined; +const CUSTOM_PARAMS = { + 'kadpageurl': '', // Custom page url + 'gender': '', // User gender + 'yob': '', // User year of birth + 'lat': '', // User location - Latitude + 'lon': '', // User Location - Longitude + 'wiid': '', // OpenWrap Wrapper Impression ID + 'profId': '', // OpenWrap Legacy: Profile ID + 'verId': '' // OpenWrap Legacy: version ID +}; +const NET_REVENUE = false; + +let publisherId = 0; + +function _getDomainFromURL(url) { + let anchor = document.createElement('a'); + anchor.href = url; + return anchor.hostname; +} + +function _parseSlotParam(paramName, paramValue) { + if (!utils.isStr(paramValue)) { + paramValue && utils.logWarn('PubMatic: Ignoring param key: ' + paramName + ', expects string-value, found ' + typeof paramValue); + return UNDEFINED; + } + + switch (paramName) { + case 'pmzoneid': + return paramValue.split(',').slice(0, 50).map(id => id.trim()).join(); + case 'kadfloor': + return parseFloat(paramValue) || UNDEFINED; + case 'lat': + return parseFloat(paramValue) || UNDEFINED; + case 'lon': + return parseFloat(paramValue) || UNDEFINED; + case 'yob': + return parseInt(paramValue) || UNDEFINED; + default: + return paramValue; + } +} + +function _cleanSlot(slotName) { + if (utils.isStr(slotName)) { + return slotName.replace(/^\s+/g, '').replace(/\s+$/g, ''); + } + return ''; +} + +function _parseAdSlot(bid) { + bid.params.adUnit = ''; + bid.params.adUnitIndex = '0'; + bid.params.width = 0; + bid.params.height = 0; + + bid.params.adSlot = _cleanSlot(bid.params.adSlot); + + var slot = bid.params.adSlot; + var splits = slot.split(':'); + + slot = splits[0]; + if (splits.length == 2) { + bid.params.adUnitIndex = splits[1]; + } + splits = slot.split('@'); + if (splits.length != 2) { + utils.logWarn('AdSlot Error: adSlot not in required format'); + return; + } + bid.params.adUnit = splits[0]; + splits = splits[1].split('x'); + if (splits.length != 2) { + utils.logWarn('AdSlot Error: adSlot not in required format'); + return; + } + bid.params.width = parseInt(splits[0]); + bid.params.height = parseInt(splits[1]); +} + +function _initConf() { + var conf = {}; + conf.pageURL = utils.getTopWindowUrl(); + conf.refURL = utils.getTopWindowReferrer(); + return conf; +} + +function _handleCustomParams(params, conf) { + if (!conf.kadpageurl) { + conf.kadpageurl = conf.pageURL; + } + + var key, value, entry; + for (key in CUSTOM_PARAMS) { + if (CUSTOM_PARAMS.hasOwnProperty(key)) { + value = params[key]; + if (value) { + entry = CUSTOM_PARAMS[key]; + + if (typeof entry === 'object') { + // will be used in future when we want to process a custom param before using + // 'keyname': {f: function() {}} + value = entry.f(value, conf); + } + + if (utils.isStr(value)) { + conf[key] = value; + } else { + utils.logWarn('PubMatic: Ignoring param : ' + key + ' with value : ' + CUSTOM_PARAMS[key] + ', expects string-value, found ' + typeof value); + } + } + } + } + return conf; +} + +function _createOrtbTemplate(conf) { + return { + id: '' + new Date().getTime(), + at: AUCTION_TYPE, + cur: [CURRENCY], + imp: [], + site: { + page: conf.pageURL, + ref: conf.refURL, + publisher: {} + }, + 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: navigator.language + }, + user: {}, + ext: {} + }; +} + +function _createImpressionObject(bid, conf) { + return { + id: bid.bidId, + tagid: bid.params.adUnit, + bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor), + secure: window.location.protocol === 'https:' ? 1 : 0, + banner: { + pos: 0, + w: bid.params.width, + h: bid.params.height, + topframe: utils.inIframe() ? 0 : 1, + }, + ext: { + pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) + } + }; +} + +export const spec = { + code: BIDDER_CODE, + + /** + * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: bid => { + if (bid && bid.params) { + if (!utils.isStr(bid.params.publisherId)) { + utils.logWarn('PubMatic Error: publisherId is mandatory and cannot be numeric. Call to OpenBid will not be sent.'); + return false; + } + if (!utils.isStr(bid.params.adSlot)) { + utils.logWarn('PubMatic: adSlotId is mandatory and cannot be numeric. Call to OpenBid will not be sent.'); + return false; + } + return true; + } + return false; + }, + + /** + * 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 => { + var conf = _initConf(); + var payload = _createOrtbTemplate(conf); + validBidRequests.forEach(bid => { + _parseAdSlot(bid); + if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height)) { + utils.logWarn('PubMatic: Skipping the non-standard adslot:', bid.params.adSlot, bid); + return; + } + conf.pubId = conf.pubId || bid.params.publisherId; + conf = _handleCustomParams(bid.params, conf); + conf.transactionId = bid.transactionId; + payload.imp.push(_createImpressionObject(bid, conf)); + }); + + if (payload.imp.length == 0) { + return; + } + + payload.site.publisher.id = conf.pubId.trim(); + publisherId = conf.pubId.trim(); + payload.ext.wrapper = {}; + payload.ext.wrapper.profile = conf.profId || UNDEFINED; + payload.ext.wrapper.version = conf.verId || UNDEFINED; + payload.ext.wrapper.wiid = conf.wiid || UNDEFINED; + payload.ext.wrapper.wv = constants.REPO_AND_VERSION; + payload.ext.wrapper.transactionId = conf.transactionId; + payload.ext.wrapper.wp = 'pbjs'; + payload.user.gender = (conf.gender ? conf.gender.trim() : UNDEFINED); + payload.user.geo = {}; + payload.user.geo.lat = _parseSlotParam('lat', conf.lat); + payload.user.geo.lon = _parseSlotParam('lon', conf.lon); + payload.user.yob = _parseSlotParam('yob', conf.yob); + payload.device.geo = {}; + payload.device.geo.lat = _parseSlotParam('lat', conf.lat); + payload.device.geo.lon = _parseSlotParam('lon', conf.lon); + payload.site.page = conf.kadpageurl.trim() || payload.site.page.trim(); + payload.site.domain = _getDomainFromURL(payload.site.page); + return { + method: 'POST', + url: ENDPOINT, + data: JSON.stringify(payload) + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} response A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: (response, request) => { + const bidResponses = []; + try { + if (response.body && response.body.seatbid && response.body.seatbid[0] && response.body.seatbid[0].bid) { + response.body.seatbid[0].bid.forEach(bid => { + let newBid = { + requestId: bid.impid, + cpm: (parseFloat(bid.price) || 0).toFixed(2), + width: bid.w, + height: bid.h, + creativeId: bid.crid || bid.id, + dealId: bid.dealid, + currency: CURRENCY, + netRevenue: NET_REVENUE, + ttl: 300, + referrer: utils.getTopWindowUrl(), + ad: bid.adm + }; + bidResponses.push(newBid); + }); + } + } catch (error) { + utils.logError(error); + } + return bidResponses; + }, + + /** + * Register User Sync. + */ + getUserSyncs: syncOptions => { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: USYNCURL + publisherId + }]; + } else { + utils.logWarn('PubMatic: Please enable iframe based user sync.'); + } + } +}; + +registerBidder(spec); diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md new file mode 100644 index 00000000000..768b3c541f6 --- /dev/null +++ b/modules/pubmaticBidAdapter.md @@ -0,0 +1,53 @@ +# Overview + +``` +Module Name: PubMatic Bid Adapter +Module Type: Bidder Adapter +Maintainer: header-bidding@pubmatic.com +``` + +# Description + +Connects to PubMatic exchange for bids. + +PubMatic bid adapter supports Banner currently. + +# Sample Ad Unit: For Publishers +``` +var adUnits = [ +{ + code: 'test-div', + sizes: [ + [300, 250], + [728, 90] + ], + bids: [{ + bidder: 'pubmatic', + params: { + publisherId: '156209', // required + adSlot: 'pubmatic_test2@300x250', // required + pmzoneid: 'zone1, zone11', // optional + lat: '40.712775', // optional + lon: '-74.005973', // optional + yob: '1982', // optional + kadpageurl: 'www.test.com', // optional + gender: 'M', // optional + kadfloor: '0.50' // optional + } + }] +} +``` + +### Configuration + +PubMatic recommends the UserSync configuration below. Without it, the PubMatic adapter will not able to perform user syncs, which lowers match rate and reduces monetization. + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + enabledBidders: ['pubmatic'], + syncDelay: 6000 + }}); +``` +Note: Combine the above the configuration with any other UserSync configuration. Multiple setConfig() calls overwrite each other and only last call for a given attribute will take effect. diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js new file mode 100644 index 00000000000..cbf17f9478a --- /dev/null +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -0,0 +1,180 @@ +import {expect} from 'chai'; +import {spec} from 'modules/pubmaticBidAdapter'; +import * as utils from 'src/utils'; +const constants = require('src/constants.json'); + +describe('PubMatic adapter', () => { + let bidRequests; + let bidResponses; + + beforeEach(() => { + bidRequests = [ + { + 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' + }, + 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' + } + ]; + + bidResponses = { + 'body': { + 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', + 'seatbid': [{ + 'bid': [{ + 'id': '74858439-49D7-4169-BA5D-44A046315B2F', + 'impid': '22bddb28db77d', + 'price': 1.3, + 'adm': 'image3.pubmatic.com Layer based creative', + 'h': 250, + 'w': 300 + }] + }] + } + }; + }); + + describe('implementation', () => { + describe('Bid validations', () => { + it('valid bid case', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + + it('invalid bid case: publisherId not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: publisherId is not string', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: 301, + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: adSlot not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: adSlot is not string', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: 15671365 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + }); + + describe('Request formation', () => { + it('Endpoint checking', () => { + let request = spec.buildRequests(bidRequests); + expect(request.url).to.equal('//hbopenbid.pubmatic.com/translator?source=prebid-client'); + expect(request.method).to.equal('POST'); + }); + + it('Request params check', () => { + let request = spec.buildRequests(bidRequests); + let data = JSON.parse(request.data); + expect(data.at).to.equal(1); // auction type + expect(data.cur[0]).to.equal('USD'); // currency + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.page).to.equal(bidRequests[0].params.kadpageurl); // forced pageURL + expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id + expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB + expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender + expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID + expect(data.ext.wrapper.profile).to.equal(bidRequests[0].params.profId); // OpenWrap: Wrapper Profile ID + expect(data.ext.wrapper.version).to.equal(bidRequests[0].params.verId); // OpenWrap: Wrapper Profile Version ID + + expect(data.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id + expect(data.imp[0].bidfloor).to.equal(parseFloat(bidRequests[0].params.kadfloor)); // kadfloor + expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid + }); + + it('invalid adslot', () => { + bidRequests[0].params.adSlot = '/15671365/DMDemo'; + let request = spec.buildRequests(bidRequests); + expect(request).to.equal(undefined); + }); + }); + + describe('Response checking', () => { + it('should check for valid response values', () => { + let request = spec.buildRequests(bidRequests); + let response = spec.interpretResponse(bidResponses, request); + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].requestId).to.equal(bidResponses.body.seatbid[0].bid[0].impid); + expect(response[0].cpm).to.equal((bidResponses.body.seatbid[0].bid[0].price).toFixed(2)); + expect(response[0].width).to.equal(bidResponses.body.seatbid[0].bid[0].w); + expect(response[0].height).to.equal(bidResponses.body.seatbid[0].bid[0].h); + if (bidResponses.body.seatbid[0].bid[0].crid) { + expect(response[0].creativeId).to.equal(bidResponses.body.seatbid[0].bid[0].crid); + } else { + expect(response[0].creativeId).to.equal(bidResponses.body.seatbid[0].bid[0].id); + } + expect(response[0].dealId).to.equal(bidResponses.body.seatbid[0].bid[0].dealid); + expect(response[0].currency).to.equal('USD'); + expect(response[0].netRevenue).to.equal(false); + expect(response[0].ttl).to.equal(300); + expect(response[0].referrer).to.include(utils.getTopWindowUrl()); + expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm); + }); + }); + }); +}); From 9b56b11bc8d7b5e4a45c985eb6aa97824cb07708 Mon Sep 17 00:00:00 2001 From: Spacedragoon Date: Tue, 23 Jan 2018 17:32:14 +0100 Subject: [PATCH 0049/1594] Update adapter to prebid v1.0 (#1908) * Update adapter to prebid v1.0 * corrected some things following pullrequest review * slight change to avoid potential error * added the maintainer email * Updated the tests to fit changes * Updated the doc, removed the bidderCode, added adUrl * fix adapter * Added try catch around JSON.parse --- modules/smartadserverBidAdapter.js | 92 ++++++++++ modules/smartadserverBidAdapter.md | 35 ++++ .../modules/smartadserverBidAdapter_spec.js | 157 ++++++++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 modules/smartadserverBidAdapter.js create mode 100644 modules/smartadserverBidAdapter.md create mode 100644 test/spec/modules/smartadserverBidAdapter_spec.js diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js new file mode 100644 index 00000000000..4828f3a36a8 --- /dev/null +++ b/modules/smartadserverBidAdapter.js @@ -0,0 +1,92 @@ +import * as utils from 'src/utils'; +import { + config +} from 'src/config'; +import { + registerBidder +} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'smartadserver'; +export const spec = { + code: BIDDER_CODE, + aliases: ['smart'], // 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 !!(bid.params && bid.params.siteId && bid.params.pageId && bid.params.formatId && bid.params.domain); + }, + /** + * 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) { + // use bidderRequest.bids[] to get bidder-dependent request info + + // if your bidder supports multiple currencies, use config.getConfig(currency) + // to find which one the ad server needs + + // pull requested transaction ID from bidderRequest.bids[].transactionId + var bid = validBidRequests[0]; + const payload = { + siteid: bid.params.siteId, + pageid: bid.params.pageId, + formatid: bid.params.formatId, + currencyCode: config.getConfig('currency.adServerCurrency'), + bidfloor: bid.params.bidfloor || 0.0, + targeting: bid.params.target && bid.params.target != '' ? bid.params.target : undefined, + tagId: bid.adUnitCode, + sizes: bid.sizes.map(size => ({ + w: size[0], + h: size[1] + })), + pageDomain: utils.getTopWindowUrl(), + transactionId: bid.transactionId, + timeout: config.getConfig('bidderTimeout'), + bidId: bid.bidId + }; + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: bid.params.domain + '/prebid/v1', + 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, bidRequest) { + const bidResponses = []; + var response = serverResponse.body; + try { + if (response) { + const bidResponse = { + requestId: JSON.parse(bidRequest.data).bidId, + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.creativeId, + dealId: response.dealId, + currency: response.currency, + netRevenue: response.isNetCpm, + ttl: response.ttl, + referrer: utils.getTopWindowUrl(), + adUrl: response.adUrl, + ad: response.ad + }; + bidResponses.push(bidResponse); + } + } catch (error) { + console.log('Error while parsing smart server response'); + } + return bidResponses; + } +} +registerBidder(spec); diff --git a/modules/smartadserverBidAdapter.md b/modules/smartadserverBidAdapter.md new file mode 100644 index 00000000000..f904aa40b3a --- /dev/null +++ b/modules/smartadserverBidAdapter.md @@ -0,0 +1,35 @@ +# Overview + +``` +Module Name: Smart Ad Server Bidder Adapter +Module Type: Bidder Adapter +Maintainer: gcarnec@smartadserver.com +``` + +# Description + +Connect to Smart for bids. + +The Smart adapter requires setup and approval from the Smart team. +Please reach out to your Technical account manager for more information. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "smart", + params: { + domain: 'http://prg.smartadserver.com', + siteId: 207435, + pageId: 896536, + formatId: 62913 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js new file mode 100644 index 00000000000..5cb4a1277fb --- /dev/null +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -0,0 +1,157 @@ +import { + expect +} from 'chai'; +import { + spec +} from 'modules/smartadserverBidAdapter'; +import { + getTopWindowLocation +} from 'src/utils'; +import { + newBidder +} from 'src/adapters/bidderFactory'; +import { + config +} from 'src/config'; +import * as utils from 'src/utils'; + +describe('Smart ad server bid adapter tests', () => { + var DEFAULT_PARAMS = [{ + adUnitCode: 'sas_42', + bidId: 'abcd1234', + sizes: [ + [300, 250], + [300, 200] + ], + bidder: 'smartadserver', + params: { + domain: 'http://prg.smartadserver.com', + siteId: '1234', + pageId: '5678', + formatId: '90', + target: 'test=prebid', + bidfloor: 0.420 + }, + requestId: 'efgh5678', + transactionId: 'zsfgzzg' + }]; + + var DEFAULT_PARAMS_WO_OPTIONAL = [{ + adUnitCode: 'sas_42', + bidId: 'abcd1234', + sizes: [ + [300, 250], + [300, 200] + ], + bidder: 'smartadserver', + params: { + domain: 'http://prg.smartadserver.com', + siteId: '1234', + pageId: '5678', + formatId: '90' + }, + requestId: 'efgh5678' + }]; + + var BID_RESPONSE = { + body: { + cpm: 12, + width: 300, + height: 250, + creativeId: 'zioeufg', + currency: 'GBP', + isNetCpm: true, + ttl: 300, + adUrl: 'http://awesome.fake.url', + ad: '< --- awesome script --- >' + } + }; + + it('Verify build request', () => { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + } + }); + const request = spec.buildRequests(DEFAULT_PARAMS); + expect(request).to.have.property('url').and.to.equal('http://prg.smartadserver.com/prebid/v1'); + expect(request).to.have.property('method').and.to.equal('POST'); + const requestContent = JSON.parse(request.data); + expect(requestContent).to.have.property('siteid').and.to.equal('1234'); + expect(requestContent).to.have.property('pageid').and.to.equal('5678'); + expect(requestContent).to.have.property('formatid').and.to.equal('90'); + expect(requestContent).to.have.property('currencyCode').and.to.equal('EUR'); + expect(requestContent).to.have.property('bidfloor').and.to.equal(0.42); + expect(requestContent).to.have.property('targeting').and.to.equal('test=prebid'); + expect(requestContent).to.have.property('tagId').and.to.equal('sas_42'); + expect(requestContent).to.have.property('sizes'); + expect(requestContent.sizes[0]).to.have.property('w').and.to.equal(300); + expect(requestContent.sizes[0]).to.have.property('h').and.to.equal(250); + expect(requestContent.sizes[1]).to.have.property('w').and.to.equal(300); + expect(requestContent.sizes[1]).to.have.property('h').and.to.equal(200); + expect(requestContent).to.have.property('pageDomain').and.to.equal(utils.getTopWindowUrl()); + expect(requestContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; + }); + + it('Verify parse response', () => { + const request = spec.buildRequests(DEFAULT_PARAMS); + const bids = spec.interpretResponse(BID_RESPONSE, request); + expect(bids).to.have.lengthOf(1); + const bid = bids[0]; + expect(bid.cpm).to.equal(12); + expect(bid.adUrl).to.equal('http://awesome.fake.url'); + expect(bid.ad).to.equal('< --- awesome script --- >'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.creativeId).to.equal('zioeufg'); + expect(bid.currency).to.equal('GBP'); + expect(bid.netRevenue).to.equal(true); + expect(bid.ttl).to.equal(300); + expect(bid.requestId).to.equal(DEFAULT_PARAMS[0].bidId); + expect(bid.referrer).to.equal(utils.getTopWindowUrl()); + }); + + it('Verifies bidder code', () => { + expect(spec.code).to.equal('smartadserver'); + }); + + it('Verifies bidder aliases', () => { + expect(spec.aliases).to.have.lengthOf(1); + expect(spec.aliases[0]).to.equal('smart'); + }); + + it('Verifies if bid request valid', () => { + expect(spec.isBidRequestValid(DEFAULT_PARAMS[0])).to.equal(true); + expect(spec.isBidRequestValid(DEFAULT_PARAMS_WO_OPTIONAL[0])).to.equal(true); + expect(spec.isBidRequestValid({})).to.equal(false); + expect(spec.isBidRequestValid({ + params: {} + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + pageid: 123 + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + siteid: 123 + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + formatid: 123, + pageid: 234 + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + domain: 'www.test.com', + pageid: 234 + } + })).to.equal(false); + }); + + it('Verifies sync options', () => { + expect(spec.getUserSyncs).to.be.undefined; + }); +}); From 8907cae479185695654dd9bb6bf697be73a92942 Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Tue, 23 Jan 2018 14:04:57 -0500 Subject: [PATCH 0050/1594] InSkin Bidder Adapter (#2016) * initial version * Initial implementation for Inskin/AdZerk bid adapter. * Add required ad types and fix event IDs list. * InSkin Bid Adapter: fixed tests and linter errors * InSkin Media: updated test parameters * InSkin Media: Add maintainer --- modules/inskinBidAdapter.js | 210 +++++++++++++++++ modules/inskinBidAdapter.md | 30 +++ test/spec/modules/inskinBidAdapter_spec.js | 253 +++++++++++++++++++++ 3 files changed, 493 insertions(+) create mode 100644 modules/inskinBidAdapter.js create mode 100644 modules/inskinBidAdapter.md create mode 100644 test/spec/modules/inskinBidAdapter_spec.js diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js new file mode 100644 index 00000000000..5274b5b2ba8 --- /dev/null +++ b/modules/inskinBidAdapter.js @@ -0,0 +1,210 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'inskin'; + +const CONFIG = { + 'inskin': { + 'BASE_URI': 'https://mfad.inskinad.com/api/v2' + } +}; + +export const spec = { + code: BIDDER_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 !!(bid.params.networkId && bid.params.siteId); + }, + + /** + * 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) { + // Do we need to group by bidder? i.e. to make multiple requests for + // different endpoints. + + let ret = { + method: 'POST', + url: '', + data: '', + bidRequest: [] + }; + + if (validBidRequests.length < 1) { + return ret; + } + + let ENDPOINT_URL; + + const data = Object.assign({ + placements: [], + time: Date.now(), + user: {}, + url: utils.getTopWindowUrl(), + referrer: document.referrer, + enableBotFiltering: true, + includePricingData: true, + parallel: true + }, validBidRequests[0].params); + + validBidRequests.map(bid => { + let config = CONFIG[bid.bidder]; + ENDPOINT_URL = config.BASE_URI; + + const placement = Object.assign({ + divName: bid.bidId, + adTypes: bid.adTypes || getSize(bid.sizes), + eventIds: [40, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295] + }, bid.params); + + placement.adTypes.push(5, 9, 163, 2163, 3006); + + if (placement.networkId && placement.siteId) { + data.placements.push(placement); + } + }); + + ret.data = JSON.stringify(data); + ret.bidRequest = validBidRequests; + ret.url = ENDPOINT_URL; + + return ret; + }, + + /** + * 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, bidRequest) { + let bid; + let bids; + let bidId; + let bidObj; + let bidResponses = []; + let bidsMap = {}; + + bids = bidRequest.bidRequest; + + serverResponse = (serverResponse || {}).body; + for (let i = 0; i < bids.length; i++) { + bid = {}; + bidObj = bids[i]; + bidId = bidObj.bidId; + + bidsMap[bidId] = bidObj; + + if (serverResponse) { + const decision = serverResponse.decisions && serverResponse.decisions[bidId]; + const price = decision && decision.pricing && decision.pricing.clearPrice; + + if (decision && price) { + bid.requestId = bidId; + bid.cpm = price; + bid.width = decision.width; + bid.height = decision.height; + bid.ad = retrieveAd(bidId, decision); + bid.currency = 'USD'; + bid.creativeId = decision.adId; + bid.ttl = 360; + bid.netRevenue = true; + bid.referrer = utils.getTopWindowUrl(); + + bidResponses.push(bid); + } + } + } + + if (bidResponses.length) { + window.addEventListener('message', function(e) { + if (!e.data || e.data.from !== 'ism-bid') { + return; + } + + const decision = serverResponse.decisions && serverResponse.decisions[e.data.bidId]; + if (!decision) { + return; + } + + const id = 'ism_tag_' + Math.floor((Math.random() * 10e16)); + window[id] = { + bidId: e.data.bidId, + serverResponse + }; + const script = document.createElement('script'); + script.src = 'https://cdn.inskinad.com/isfe/publishercode/' + bidsMap[e.data.bidId].params.siteId + '/default.js?autoload&id=' + id; + document.getElementsByTagName('head')[0].appendChild(script); + }); + } + + return bidResponses; + }, + + getUserSyncs: function(syncOptions) { + return []; + } +}; + +const sizeMap = [ + null, + '120x90', + '120x90', + '468x60', + '728x90', + '300x250', + '160x600', + '120x600', + '300x100', + '180x150', + '336x280', + '240x400', + '234x60', + '88x31', + '120x60', + '120x240', + '125x125', + '220x250', + '250x250', + '250x90', + '0x0', + '200x90', + '300x50', + '320x50', + '320x480', + '185x185', + '620x45', + '300x125', + '800x250' +]; + +sizeMap[77] = '970x90'; +sizeMap[123] = '970x250'; +sizeMap[43] = '300x600'; + +function getSize(sizes) { + const result = []; + sizes.forEach(function(size) { + const index = sizeMap.indexOf(size[0] + 'x' + size[1]); + if (index >= 0) { + result.push(index); + } + }); + return result; +} + +function retrieveAd(bidId, decision) { + return "'; + + let responseCreativeId = '274'; + let responseCurrency = 'USD'; + + let responseWidth = 300; + let responseHeight = 250; + let responseTtl = 213; + + let sampleResponse = { + id: '66043f5ca44ecd8f8769093b1615b2d9', + seatbid: [ + { + bid: [ + { + id: 'c21bab0e-7668-4d8f-908a-63e094c09197', + impid: '1', + price: responsePrice, + adid: responseCreativeId, + adm: responseCreative, + adomain: [ + 'www.rockyouteststudios.com' + ], + cid: '274', + attr: [], + w: responseWidth, + h: responseHeight, + ext: { + ttl: responseTtl + } + } + ], + seat: '201', + group: 0 + } + ], + bidid: 'c21bab0e-7668-4d8f-908a-63e094c09197', + cur: responseCurrency + }; + + let sampleRequest = { + bidId: incomingRequestId, + mediaTypes: { banner: {} }, + requestId: incomingRequestId + }; + + let result = spec.interpretResponse( + { + body: sampleResponse + }, + sampleRequest + ); + + expect(result.length).to.equal(1); + + let processedBid = result[0]; + + // expect(processedBid.requestId).to.equal(incomingRequestId); + expect(processedBid.cpm).to.equal(responsePrice); + expect(processedBid.width).to.equal(responseWidth); + expect(processedBid.height).to.equal(responseHeight); + expect(processedBid.ad).to.equal(responseCreative); + expect(processedBid.ttl).to.equal(responseTtl); + expect(processedBid.creativeId).to.equal(responseCreativeId); + expect(processedBid.netRevenue).to.equal(true); + expect(processedBid.currency).to.equal(responseCurrency); + }); + + it('returns an valid bid response on sucessful video request', () => { + let incomingRequestId = 'XXtesting-275XX'; + let responsePrice = 6 + + let responseCreative = '\n\n \n \n Mediatastic\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n'; + + let responseCreativeId = '1556'; + let responseCurrency = 'USD'; + + let responseWidth = 284; + let responseHeight = 285; + let responseTtl = 286; + + let sampleResponse = { + id: '1234567890', + seatbid: [ + { + bid: [ + { + id: 'a8ae0b48-a8db-4220-ba0c-7458f452b1f5', + impid: '1', + price: responsePrice, + adid: responseCreativeId, + adm: responseCreative, + cid: '270', + attr: [], + w: responseWidth, + h: responseHeight, + ext: { + ttl: responseTtl + } + } + ], + seat: '201', + group: 0 + } + ], + bidid: 'a8ae0b48-a8db-4220-ba0c-7458f452b1f5', + cur: 'USD' + }; + + let sampleRequest = { + bidId: incomingRequestId, + mediaTypes: { + video: { + } + }, + requestId: incomingRequestId + }; + + let result = spec.interpretResponse( + { + body: sampleResponse + }, + sampleRequest + ); + + expect(result.length).to.equal(1); + + let processedBid = result[0]; + + // expect(processedBid.requestId).to.equal(incomingRequestId); + expect(processedBid.cpm).to.equal(responsePrice); + expect(processedBid.width).to.equal(responseWidth); + expect(processedBid.height).to.equal(responseHeight); + expect(processedBid.ad).to.equal(null); + expect(processedBid.ttl).to.equal(responseTtl); + expect(processedBid.creativeId).to.equal(responseCreativeId); + expect(processedBid.netRevenue).to.equal(true); + expect(processedBid.currency).to.equal(responseCurrency); + expect(processedBid.vastXml).to.equal(responseCreative); + }); + + it('generates event callbacks as expected', () => { + let tally = {}; + let renderer = { + handleVideoEvent: (eventObject) => { + let eventName = eventObject.eventName; + if (tally[eventName]) { + tally[eventName] = tally[eventName] + 1; + } else { + tally[eventName] = 1; + } + } + }; + + let callbacks = internals.playerCallbacks(renderer); + + let validCallbacks = ['LOAD', 'IMPRESSION', 'COMPLETE', 'ERROR']; + + validCallbacks.forEach(event => { + callbacks('n/a', event); + }); + + let callbackKeys = Object.keys(tally); + expect(callbackKeys.length).to.equal(3); + expect(tally['loaded']).to.equal(1); + expect(tally['impression']).to.equal(1); + expect(tally['ended']).to.equal(2); + }); + + it('generates a renderer that will hide on complete', () => { + let elementName = 'test_element_id'; + let selector = `#${elementName}`; + + let mockElement = { + style: { + display: 'some' + } + }; + + document.querySelector = (name) => { + if (name === selector) { + return mockElement; + } else { + return null; + } + }; + + let renderer = internals.generateRenderer({}, elementName); + + renderer.handlers['ended'](); + + expect(mockElement.style.display).to.equal('none'); + }) + }); +}); From 261b9b4c1c20fea08fae7b2b80d3c94e5126a070 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 23 Jan 2018 15:26:32 -0800 Subject: [PATCH 0058/1594] Use polyfilled includes method (#2061) --- src/prebid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prebid.js b/src/prebid.js index df7946db896..86fd678ee7e 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -318,7 +318,7 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa const bidderMediaTypes = (spec && spec.supportedMediaTypes) || ['banner']; // check if the bidder's mediaTypes are not in the adUnit's mediaTypes - const bidderEligible = adUnitMediaTypes.some(type => bidderMediaTypes.includes(type)); + const bidderEligible = adUnitMediaTypes.some(type => includes(bidderMediaTypes, type)); if (!bidderEligible) { // drop the bidder from the ad unit if it's not compatible utils.logWarn(utils.unsupportedBidderMessage(adUnit, bidder)); From 65c76ef80f68eb41962b98d388dde3259e3c1203 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 23 Jan 2018 15:56:07 -0800 Subject: [PATCH 0059/1594] Prebid 1.2.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b4ffaecda35..fdd66001fed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.1.1", + "version": "1.2.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From c9af917ccb06af58c80d50937fc94e75346f8fca Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Wed, 24 Jan 2018 13:50:51 -0800 Subject: [PATCH 0060/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fdd66001fed..fdc8e5b7ea8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.2.0", + "version": "1.3.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From aa0bee7cdadd0683284bb8bbed568262d1fc05b6 Mon Sep 17 00:00:00 2001 From: Miller Date: Wed, 24 Jan 2018 23:54:16 +0200 Subject: [PATCH 0061/1594] Add display support for Vertamedia Adapter (#1945) * Vertamedia prebid.js adapter initial * sync * remove https * add http * remove let * fix typo * fix spaces * add descriptionUrl; remove log * fix getSize * add usege parseSizesInput * Add support for vastTag * Add moulty bid request; set vastUrl for bider; * update for vertamedia adapter to Prebid 1.0 * Add vertamedia md file * Add required fields * Remove defaults; fix md file; * add outstream mediaType support * add outstream mediaType support * Resolve conflicts * fix test * Add Vertamedia display adapter * remove Boolean convert for isBidRequestValid * Remove boolean convert for isBidRequestValid method; fix tests; fix typo * add display support for Vertamedia adapter; documentation update * update tests for VertamediaBidAdapter * add supportedMediaTypes * Add comments * Add moulty mediatypes support * cleanup logs * Add sending multiple sizes --- modules/vertamediaBidAdapter.js | 89 +++++---- modules/vertamediaBidAdapter.md | 58 ++++-- .../spec/modules/vertamediaBidAdapter_spec.js | 181 ++++++++++++++---- 3 files changed, 236 insertions(+), 92 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index b314f6fd872..238495f3966 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -1,16 +1,19 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; -import {VIDEO} from 'src/mediaTypes'; +import {VIDEO, BANNER} from 'src/mediaTypes'; import {Renderer} from 'src/Renderer'; +import findIndex from 'core-js/library/fn/array/find-index'; -const URL = '//rtb.vertamedia.com/hb/'; +const URL = '//hb2.vertamedia.com/auction/'; const BIDDER_CODE = 'vertamedia'; +const OUTSTREAM = 'outstream'; +const DISPLAY = 'display'; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [VIDEO], + supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { - return Boolean(bid && bid.params && bid.params.aid); + return bid && bid.params && bid.params.aid; }, /** @@ -25,7 +28,7 @@ export const spec = { bidderRequest, method: 'GET', url: URL - } + }; }); }, @@ -38,9 +41,6 @@ export const spec = { interpretResponse: function (serverResponse, {bidderRequest}) { serverResponse = serverResponse.body; const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; - const videoMediaType = utils.deepAccess(bidderRequest.bids[0], 'mediaTypes.video'); - const context = utils.deepAccess(bidderRequest.bids[0], 'mediaTypes.video.context'); - const isMediaTypeOutstream = (videoMediaType && context === 'outstream'); let bids = []; @@ -54,76 +54,82 @@ export const spec = { } serverResponse.bids.forEach(serverBid => { - if (serverBid.cpm !== 0) { - const bid = createBid(isMediaTypeOutstream, serverBid); + const requestId = findIndex(bidderRequest.bids, (bidRequest) => { + return bidRequest.bidId === serverBid.requestId; + }); + + if (serverBid.cpm !== 0 && requestId !== -1) { + const bid = createBid(serverBid, getMediaType(bidderRequest.bids[requestId])); + bids.push(bid); } }); return bids; - }, + } }; /** - * Prepare all parameters for request + * Parse mediaType * @param bid {object} * @returns {object} */ function prepareRTBRequestParams(bid) { - let size = getSize(bid.sizes); + const mediaType = utils.deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY; return { domain: utils.getTopWindowLocation().hostname, callbackId: bid.bidId, aid: bid.params.aid, - h: size.height, - w: size.width + ad_type: mediaType, + sizes: utils.parseSizesInput(bid.sizes).join() }; } /** - * Prepare size for request - * @param requestSizes {array} - * @returns {object} bid The bid to validate + * Prepare all parameters for request + * @param bidderRequest {object} + * @returns {object} */ -function getSize(requestSizes) { - const size = utils.parseSizesInput(requestSizes)[0]; - const parsed = {}; - - if (typeof size !== 'string') { - return parsed; - } - - let parsedSize = size.toUpperCase().split('X'); +function getMediaType(bidderRequest) { + const videoMediaType = utils.deepAccess(bidderRequest, 'mediaTypes.video'); + const context = utils.deepAccess(bidderRequest, 'mediaTypes.video.context'); - return { - height: parseInt(parsedSize[1], 10) || undefined, - width: parseInt(parsedSize[0], 10) || undefined - }; + return !videoMediaType ? DISPLAY : context === OUTSTREAM ? OUTSTREAM : VIDEO; } /** * Configure new bid by response - * @param isMediaTypeOutstream {boolean} * @param bidResponse {object} + * @param mediaType {Object} * @returns {object} */ -function createBid(isMediaTypeOutstream, bidResponse) { +function createBid(bidResponse, mediaType) { let bid = { requestId: bidResponse.requestId, creativeId: bidResponse.cmpId, - vastUrl: bidResponse.vastUrl, height: bidResponse.height, currency: bidResponse.cur, width: bidResponse.width, cpm: bidResponse.cpm, - mediaType: 'video', netRevenue: true, + mediaType, ttl: 3600 }; - if (isMediaTypeOutstream) { + if (mediaType === DISPLAY) { + return Object.assign(bid, { + ad: bidResponse.ad + }); + } + + Object.assign(bid, { + vastUrl: bidResponse.vastUrl + }); + + if (mediaType === OUTSTREAM) { Object.assign(bid, { + mediaType: 'video', adResponse: bidResponse, renderer: newRenderer(bidResponse.requestId) }); @@ -132,11 +138,16 @@ function createBid(isMediaTypeOutstream, bidResponse) { return bid; } +/** + * Create Vertamedia renderer + * @param requestId + * @returns {*} + */ function newRenderer(requestId) { const renderer = Renderer.install({ id: requestId, url: '//player.vertamedia.com/outstream-unit/2.01/outstream.min.js', - loaded: false, + loaded: false }); renderer.setRender(outstreamRender); @@ -144,6 +155,10 @@ function newRenderer(requestId) { return renderer; } +/** + * Initialise Vertamedia outstream + * @param bid + */ function outstreamRender(bid) { bid.renderer.push(() => { window.VOutstreamAPI.initOutstreams([{ diff --git a/modules/vertamediaBidAdapter.md b/modules/vertamediaBidAdapter.md index 0ce4f2cbd58..2f6faf5c840 100644 --- a/modules/vertamediaBidAdapter.md +++ b/modules/vertamediaBidAdapter.md @@ -9,33 +9,57 @@ Get access to multiple demand partners across VertaMedia AdExchange and maximize your yield with VertaMedia header bidding adapter. VertaMedia header bidding adapter connects with VertaMedia demand sources in order to fetch bids. -This adapter provides a solution for accessing Video demand +This adapter provides a solution for accessing Video demand and display demand # Test Parameters ``` - var adUnits = [{ + var adUnits = [ + + // Video instream adUnit + { code: 'div-test-div', - sizes: [[640, 480]], // ad size + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'instream' + } + }, bids: [{ - bidder: 'vertamedia', // adapter name - params: { - aid: 332842 - } + bidder: 'vertamedia', + params: { + aid: 332842 + } }] - }{ + }, + + // Video outstream adUnit + { code: 'outstream-test-div', - sizes: [[640, 480]], // ad size + sizes: [[640, 480]], mediaTypes: { - video: { - context: 'outstream' - } + video: { + context: 'outstream' + } }, bids: [{ - bidder: 'vertamedia', // adapter name - params: { - aid: 332842 - } + bidder: 'vertamedia', + params: { + aid: 332842 + } + }] + }, + + // Banner adUnit + { + code: 'div-test-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'vertamedia', + params: { + aid: 324758 + } }] - }]; + } + ]; ``` diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 15466a94aca..32353b0097e 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -2,9 +2,25 @@ import {expect} from 'chai'; import {spec} from 'modules/vertamediaBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -const ENDPOINT = '//rtb.vertamedia.com/hb/'; -const REQUEST = { +const ENDPOINT = '//hb2.vertamedia.com/auction/'; + +const DISPLAY_REQUEST = { + 'bidder': 'vertamedia', + 'params': { + 'aid': 12345 + }, + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '2e41f65424c87c', + 'adUnitCode': 'adunit-code', + 'bidId': '84ab500420319d', + 'sizes': [300, 250] +}; + +const VIDEO_REQUEST = { 'bidder': 'vertamedia', + 'mediaTypes': { + 'video': {} + }, 'params': { 'aid': 12345 }, @@ -12,10 +28,10 @@ const REQUEST = { 'auctionId': '2e41f65424c87c', 'adUnitCode': 'adunit-code', 'bidId': '84ab500420319d', - 'sizes': [640, 480] + 'sizes': [[480, 360], [640, 480]] }; -const serverResponse = { +const SERVER_VIDEO_RESPONSE = { 'source': {'aid': 12345, 'pubId': 54321}, 'bids': [{ 'vastUrl': 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', @@ -30,6 +46,55 @@ const serverResponse = { } ] }; +const SERVER_DISPLAY_RESPONSE = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'ad': '', + 'requestId': '2e41f65424c87c', + 'creative_id': 342516, + 'cmpId': 342516, + 'height': 250, + 'cur': 'USD', + 'width': 300, + 'cpm': 0.9 + }] +}; + +const videoBidderRequest = { + bidderCode: 'bidderCode', + bids: [{mediaTypes: {video: {}}, bidId: '2e41f65424c87c'}] +}; + +const displayBidderRequest = { + bidderCode: 'bidderCode', + bids: [{bidId: '2e41f65424c87c'}] +}; + +const videoEqResponse = [{ + vastUrl: 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', + requestId: '2e41f65424c87c', + creativeId: 342516, + mediaType: 'video', + netRevenue: true, + currency: 'USD', + height: 480, + width: 640, + ttl: 3600, + cpm: 0.9 +}]; + +const displayEqResponse = [{ + requestId: '2e41f65424c87c', + creativeId: 342516, + mediaType: 'display', + netRevenue: true, + currency: 'USD', + ad: '', + height: 250, + width: 300, + ttl: 3600, + cpm: 0.9 +}]; describe('vertamediaBidAdapter', () => { const adapter = newBidder(spec); @@ -42,37 +107,56 @@ describe('vertamediaBidAdapter', () => { describe('isBidRequestValid', () => { it('should return true when required params found', () => { - expect(spec.isBidRequestValid(REQUEST)).to.equal(true); + expect(spec.isBidRequestValid(VIDEO_REQUEST)).to.equal(12345); }); it('should return false when required params are not passed', () => { - let bid = Object.assign({}, REQUEST); + let bid = Object.assign({}, VIDEO_REQUEST); delete bid.params; - expect(spec.isBidRequestValid(bid)).to.equal(false); + expect(spec.isBidRequestValid(bid)).to.equal(undefined); }); }); describe('buildRequests', () => { - let bidRequests = [REQUEST]; + let videoBidRequests = [VIDEO_REQUEST]; + let dispalyBidRequests = [DISPLAY_REQUEST]; - const request = spec.buildRequests(bidRequests, {}); + const displayRequest = spec.buildRequests(dispalyBidRequests, {}); + const videoRequest = spec.buildRequests(videoBidRequests, {}); it('sends bid request to ENDPOINT via GET', () => { - expect(request[0].method).to.equal('GET'); + expect(videoRequest[0].method).to.equal('GET'); + expect(displayRequest[0].method).to.equal('GET'); }); + it('sends bid request to correct ENDPOINT', () => { - expect(request[0].url).to.equal(ENDPOINT); + expect(videoRequest[0].url).to.equal(ENDPOINT); + expect(displayRequest[0].url).to.equal(ENDPOINT); + }); + + it('sends correct video bid parameters', () => { + const bid = Object.assign({}, videoRequest[0].data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'video', + aid: 12345, + sizes: '480x360,640x480' + }; + + expect(bid).to.deep.equal(eq); }); - it('sends correct bid parameters', () => { - const bid = Object.assign({}, request[0].data); + it('sends correct display bid parameters', () => { + const bid = Object.assign({}, displayRequest[0].data); delete bid.domain; const eq = { callbackId: '84ab500420319d', + ad_type: 'display', aid: 12345, - w: 640, - h: 480 + sizes: '300x250' }; expect(bid).to.deep.equal(eq); @@ -80,34 +164,55 @@ describe('vertamediaBidAdapter', () => { }); describe('interpretResponse', () => { - let bidderRequest = { - bidderCode: 'bidderCode', - bids: [{mediaTypes: {video: {}}}] - }; + let serverResponse; + let bidderRequest; + let eqResponse; + + afterEach(() => { + serverResponse = null; + bidderRequest = null; + eqResponse = null; + }); + + it('should get correct video bid response', () => { + serverResponse = SERVER_VIDEO_RESPONSE; + bidderRequest = videoBidderRequest; + eqResponse = videoEqResponse; + + bidServerResponseCheck(); + }); + + it('should get correct display bid response', () => { + serverResponse = SERVER_DISPLAY_RESPONSE; + bidderRequest = displayBidderRequest; + eqResponse = displayEqResponse; + + bidServerResponseCheck(); + }); - it('should get correct bid response', () => { + function bidServerResponseCheck() { const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); - const eq = [{ - vastUrl: 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', - requestId: '2e41f65424c87c', - creativeId: 342516, - mediaType: 'video', - netRevenue: true, - currency: 'USD', - height: 480, - width: 640, - ttl: 3600, - cpm: 0.9 - }]; - - expect(result).to.deep.equal(eq); + + expect(result).to.deep.equal(eqResponse); + } + + function nobidServerResponseCheck() { + const noBidServerResponse = {bids: []}; + const noBidResult = spec.interpretResponse({body: noBidServerResponse}, {bidderRequest}); + + expect(noBidResult.length).to.equal(0); + } + + it('handles video nobid responses', () => { + bidderRequest = videoBidderRequest; + + nobidServerResponseCheck(); }); - it('handles nobid responses', () => { - const nobidServerResponse = {bids: []}; - const nobidResult = spec.interpretResponse({body: nobidServerResponse}, {bidderRequest}); + it('handles display nobid responses', () => { + bidderRequest = displayBidderRequest; - expect(nobidResult.length).to.equal(0); + nobidServerResponseCheck(); }); }); }); From f838057c57e71217db4bc1deae2fdf041096f981 Mon Sep 17 00:00:00 2001 From: moonshells <33766472+moonshells@users.noreply.github.com> Date: Thu, 25 Jan 2018 06:17:11 -0800 Subject: [PATCH 0062/1594] Add video cache key (#2064) * fix media type by assigning it with creative type, create video cache key with the value of impression id * add unit tests * fix typo --- modules/rubiconBidAdapter.js | 2 ++ test/spec/modules/rubiconBidAdapter_spec.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 1e7762ae90d..13ca5d3dc72 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -265,6 +265,7 @@ export const spec = { requestId: bidRequest.bidId, currency: 'USD', creativeId: ad.creative_id, + mediaType: ad.creative_type, cpm: ad.cpm || 0, dealId: ad.deal, ttl: 300, // 5 minutes @@ -275,6 +276,7 @@ export const spec = { bid.height = bidRequest.params.video.playerHeight; bid.vastUrl = ad.creative_depot_url; bid.impression_id = ad.impression_id; + bid.videoCacheKey = ad.impression_id; } else { bid.ad = _renderCreative(ad.script, ad.impression_id); [bid.width, bid.height] = sizeMap[ad.size_id].split('x').map(num => Number(num)); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index b02f01ecd93..2ff8d5fe0e3 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -760,6 +760,8 @@ describe('the rubicon adapter', () => { 'https://fastlane-adv.rubiconproject.com/v1/creative/a40fe16e-d08d-46a9-869d-2e1573599e0c.xml' ); expect(bids[0].impression_id).to.equal('a40fe16e-d08d-46a9-869d-2e1573599e0c'); + expect(bids[0].mediaType).to.equal('video'); + expect(bids[0].videoCacheKey).to.equal('a40fe16e-d08d-46a9-869d-2e1573599e0c'); }); }); }); From 548fce2f3133c89e6d64725f240d2f739449150d Mon Sep 17 00:00:00 2001 From: Kit Westneat Date: Thu, 25 Jan 2018 09:19:13 -0500 Subject: [PATCH 0063/1594] native is reserved keyword, use bracket/quotes to reference property on object (#2066) --- src/auction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auction.js b/src/auction.js index 7a6b44ca459..62250f573b3 100644 --- a/src/auction.js +++ b/src/auction.js @@ -397,7 +397,7 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj) { } // set native key value targeting - if (custBidObj.native) { + if (custBidObj['native']) { keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj)); } From 104376b600e62bc3262bab3a7e72ed7e3c3bca1e Mon Sep 17 00:00:00 2001 From: Gediminas Mikelenas Date: Thu, 25 Jan 2018 17:34:43 +0200 Subject: [PATCH 0064/1594] Add Yieldlab adapter (#1967) * Add Yieldlab adapter * Fix code review issues * Add code review fixes --- modules/yieldlabBidAdapter.js | 107 ++++++++++++++++++ modules/yieldlabBidAdapter.md | 45 ++++++++ test/spec/modules/yieldlabBidAdapter_spec.js | 111 +++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 modules/yieldlabBidAdapter.js create mode 100644 modules/yieldlabBidAdapter.md create mode 100644 test/spec/modules/yieldlabBidAdapter_spec.js diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js new file mode 100644 index 00000000000..17c205359de --- /dev/null +++ b/modules/yieldlabBidAdapter.js @@ -0,0 +1,107 @@ +import * as utils from 'src/utils' +import { registerBidder } from 'src/adapters/bidderFactory' +import find from 'core-js/library/fn/array/find' +import { VIDEO, BANNER } from 'src/mediaTypes' + +const ENDPOINT = 'https://ad.yieldlab.net' +const BIDDER_CODE = 'yieldlab' +const BID_RESPONSE_TTL_SEC = 600 +const CURRENCY_CODE = 'EUR' + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [VIDEO, BANNER], + + isBidRequestValid: function (bid) { + if (bid && bid.params && bid.params.placementId && bid.params.adSize) { + return true + } + return false + }, + + /** + * This method should build correct URL + * @param validBidRequests + * @returns {{method: string, url: string}} + */ + buildRequests: function (validBidRequests) { + const placementIds = [] + const timestamp = Date.now() + + utils._each(validBidRequests, function (bid) { + placementIds.push(bid.params.placementId) + }) + + const placements = placementIds.join(',') + + return { + method: 'GET', + url: `${ENDPOINT}/yp/${placements}?ts=${timestamp}&json=true`, + validBidRequests: validBidRequests + } + }, + + /** + * Map ad values and pricing and stuff + * @param serverResponse + * @param originalBidRequest + */ + interpretResponse: function (serverResponse, originalBidRequest) { + const bidResponses = [] + const timestamp = Date.now() + + originalBidRequest.validBidRequests.forEach(function (bidRequest) { + if (!serverResponse.body) { + return + } + + let matchedBid = find(serverResponse.body, function (bidResponse) { + return bidRequest.params.placementId == bidResponse.id + }) + + if (matchedBid) { + const sizes = parseSize(bidRequest.params.adSize) + const bidResponse = { + requestId: bidRequest.bidId, + cpm: matchedBid.price / 100, + width: sizes[0], + height: sizes[1], + creativeId: '' + matchedBid.id, + dealId: matchedBid.did, + currency: CURRENCY_CODE, + netRevenue: true, + ttl: BID_RESPONSE_TTL_SEC, + referrer: '', + ad: `` + } + if (isVideo(bidRequest)) { + bidResponse.mediaType = VIDEO + bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.accountId}/1x1?ts=${timestamp}` + } + + bidResponses.push(bidResponse) + } + }) + return bidResponses + } +}; + +/** + * Is this a video format? + * @param {String} format + * @returns {Boolean} + */ +function isVideo (format) { + return utils.deepAccess(format, 'mediaTypes.video') +} + +/** + * Expands a 'WxH' string as a 2-element [W, H] array + * @param {String} size + * @returns {Array} + */ +function parseSize (size) { + return size.split('x').map(Number) +} + +registerBidder(spec) diff --git a/modules/yieldlabBidAdapter.md b/modules/yieldlabBidAdapter.md new file mode 100644 index 00000000000..0c9183aa4cd --- /dev/null +++ b/modules/yieldlabBidAdapter.md @@ -0,0 +1,45 @@ +# Overview + +``` +Module Name: Yieldlab Bidder Adapter +Module Type: Bidder Adapter +Maintainer: api@platform-lunar.com +``` + +# Description + +Module that connects to Yieldlab's demand sources + +# Test Parameters +``` + var adUnits = [ + { + code: "test1", + sizes: [[800, 250]] + bids: [{ + bidder: "yieldlab", + params: { + placement: "4206978", + accountId: "2358365", + adSize: "800x250" + } + }] + }, { + code: "test2", + sizes: [[1, 1]], + mediaTypes: { + video: { + context: "instream" + } + }, + bids: [{ + bidder: "yieldlab", + params: { + placementId: "4207034", + accountId: "2358365", + adSize: "1x1" + } + }] + } + ]; +``` diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js new file mode 100644 index 00000000000..2a19763b10a --- /dev/null +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -0,0 +1,111 @@ +import { expect } from 'chai' +import { spec } from 'modules/yieldlabBidAdapter' +import { newBidder } from 'src/adapters/bidderFactory' + +const REQUEST = { + 'bidder': 'yieldlab', + 'params': { + 'placementId': '1111', + 'accountId': '2222', + 'adSize': '800x250' + }, + 'bidderRequestId': '143346cf0f1731', + 'auctionId': '2e41f65424c87c', + 'adUnitCode': 'adunit-code', + 'bidId': '2d925f27f5079f', + 'sizes': [1, 1] +} + +const RESPONSE = { + advertiser: 'yieldlab', + curl: 'https://www.yieldlab.de', + format: 0, + id: 1111, + price: 1 +} + +describe('yieldlabBidAdapter', () => { + const adapter = newBidder(spec) + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function') + }) + }) + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + const request = { + 'params': { + 'placementId': '1111', + 'accountId': '2222', + 'adSize': '800x250' + } + } + expect(spec.isBidRequestValid(request)).to.equal(true) + }) + + it('should return false when required params are not passed', () => { + expect(spec.isBidRequestValid({})).to.equal(false) + }) + }) + + describe('buildRequests', () => { + const bidRequests = [REQUEST] + const request = spec.buildRequests(bidRequests) + + it('sends bid request to ENDPOINT via GET', () => { + expect(request.method).to.equal('GET') + }) + + it('returns a list of valid requests', () => { + expect(request.validBidRequests).to.eql([REQUEST]) + }) + }) + + describe('interpretResponse', () => { + const validRequests = { + validBidRequests: [REQUEST] + } + + it('handles nobid responses', () => { + expect(spec.interpretResponse({body: {}}, {validBidRequests: []}).length).to.equal(0) + expect(spec.interpretResponse({body: []}, {validBidRequests: []}).length).to.equal(0) + }) + + it('should get correct bid response', () => { + const result = spec.interpretResponse({body: [RESPONSE]}, validRequests) + + expect(result[0].requestId).to.equal('2d925f27f5079f') + expect(result[0].cpm).to.equal(0.01) + expect(result[0].width).to.equal(800) + expect(result[0].height).to.equal(250) + expect(result[0].creativeId).to.equal('1111') + expect(result[0].dealId).to.equal(undefined) + expect(result[0].currency).to.equal('EUR') + expect(result[0].netRevenue).to.equal(true) + expect(result[0].ttl).to.equal(600) + expect(result[0].referrer).to.equal('') + expect(result[0].ad).to.include('↵ ↵ ↵
↵ ', + beacon: '', + cpm: 36.0008, + displaytype: '1', + ids: {}, + location_params: null, + locationid: '58279', + native_ad: { + assets: [ + { + data: { + label: 'accompanying_text', + value: 'AD' + }, + id: 501 + }, + { + data: { + label: 'optout_url', + value: 'https://supership.jp/optout/' + }, + id: 502 + }, + { + data: { + ext: { + black_back: 'https://i.socdm.com/sdk/img/icon_adg_optout_26x26_white.png', + }, + label: 'information_icon_url', + value: 'https://i.socdm.com/sdk/img/icon_adg_optout_26x26_gray.png', + id: 503 + } + }, + { + id: 1, + required: 1, + title: {text: 'Title'} + }, + { + id: 2, + img: { + h: 250, + url: 'https://s3-ap-northeast-1.amazonaws.com/sdk-temp/adg-sample-ad/img/300x250.png', + w: 300 + }, + required: 1 + }, + { + id: 3, + img: { + h: 300, + url: 'https://placehold.jp/300x300.png', + w: 300 + }, + required: 1 + }, + { + data: {value: 'Description'}, + id: 5, + required: 0 + }, + { + data: {value: 'CTA'}, + id: 6, + required: 0 + }, + { + data: {value: 'Sponsored'}, + id: 4, + required: 0 + } + ], + imptrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1.gif'], + link: { + clicktrackers: [ + 'https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1_clicktracker_access.gif' + ], + url: 'https://supership.jp' + }, + }, + rotation: '0', + scheduleid: '512603', + sdktype: '0', + creativeid: '1k2kv35vsa5r', + dealid: 'fd5sa5fa7f', + ttl: 1000 + }; + + const bidResponses = [ + { + requestId: '2f6ac468a9c15e', + cpm: 36.0008, + width: 1, + height: 1, + creativeId: '1k2kv35vsa5r', + dealId: 'fd5sa5fa7f', + currency: 'JPY', + netRevenue: true, + ttl: 1000, + referrer: utils.getTopWindowUrl(), + ad: '↵
', + native: { + title: 'Title', + image: { + url: 'https://s3-ap-northeast-1.amazonaws.com/sdk-temp/adg-sample-ad/img/300x250.png', + height: 250, + width: 300 + }, + icon: { + url: 'https://placehold.jp/300x300.png', + height: 300, + width: 300 + }, + sponsoredBy: 'Sponsored', + body: 'Description', + cta: 'CTA', + clickUrl: 'https://supership.jp', + clickTrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1_clicktracker_access.gif'], + impressionTrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1.gif'] + }, + mediaType: NATIVE + } + ]; + + it('no bid responses', () => { + const result = spec.interpretResponse({body: serverResponse}, bidRequests); + expect(result.length).to.equal(0); + }); + + it('handles native responses', () => { + serverResponse.results = [{ad: 'Creative<\/body>'}]; + const result = spec.interpretResponse({body: serverResponse}, bidRequests)[0]; + expect(result.requestId).to.equal(bidResponses[0].requestId); + expect(result.width).to.equal(bidResponses[0].width); + expect(result.height).to.equal(bidResponses[0].height); + expect(result.creativeId).to.equal(bidResponses[0].creativeId); + expect(result.dealId).to.equal(bidResponses[0].dealId); + expect(result.currency).to.equal(bidResponses[0].currency); + expect(result.netRevenue).to.equal(bidResponses[0].netRevenue); + expect(result.ttl).to.equal(bidResponses[0].ttl); + expect(result.referrer).to.equal(bidResponses[0].referrer); + expect(result.native.title).to.equal(bidResponses[0].native.title); + expect(result.native.image.url).to.equal(bidResponses[0].native.image.url); + expect(result.native.image.height).to.equal(bidResponses[0].native.image.height); + expect(result.native.image.width).to.equal(bidResponses[0].native.image.width); + expect(result.native.icon.url).to.equal(bidResponses[0].native.icon.url); + expect(result.native.icon.width).to.equal(bidResponses[0].native.icon.width); + expect(result.native.icon.height).to.equal(bidResponses[0].native.icon.height); + expect(result.native.sponsoredBy).to.equal(bidResponses[0].native.sponsoredBy); + expect(result.native.body).to.equal(bidResponses[0].native.body); + expect(result.native.cta).to.equal(bidResponses[0].native.cta); + expect(result.native.clickUrl).to.equal(bidResponses[0].native.clickUrl); + expect(result.native.impressionTrackers[0]).to.equal(bidResponses[0].native.impressionTrackers[0]); + expect(result.native.clickTrackers[0]).to.equal(bidResponses[0].native.clickTrackers[0]); + expect(result.mediaType).to.equal(bidResponses[0].mediaType); + }); + + it('handles banner responses', () => { + serverResponse.results = [{ad: '↵ ↵ ↵ ↵ ↵
↵ '}]; + delete serverResponse.native_ad; + delete serverResponse.mediaType; + delete bidRequests.bidRequest.mediaTypes; + const result = spec.interpretResponse({body: serverResponse}, bidRequests)[0]; + expect(result.requestId).to.equal(bidResponses[0].requestId); + expect(result.width).to.equal(bidResponses[0].width); + expect(result.height).to.equal(bidResponses[0].height); + expect(result.creativeId).to.equal(bidResponses[0].creativeId); + expect(result.dealId).to.equal(bidResponses[0].dealId); + expect(result.currency).to.equal(bidResponses[0].currency); + expect(result.netRevenue).to.equal(bidResponses[0].netRevenue); + expect(result.ttl).to.equal(bidResponses[0].ttl); + expect(result.referrer).to.equal(bidResponses[0].referrer); + expect(result.ad).to.equal(bidResponses[0].ad); + }); + }); +}); From 017add7314802bfc3e3091b8a69e4884b50424b7 Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Wed, 31 Jan 2018 06:50:46 +0800 Subject: [PATCH 0071/1594] Read secure fields to send requests (#2078) On http page, a video request will then raise an error as the non secure creative will be called from the player which is an https iframe so raise an error. --- modules/rubiconBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 13ca5d3dc72..ee490e55c15 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -112,9 +112,10 @@ export const spec = { if (bidRequest.mediaType === 'video') { let params = bidRequest.params; let size = parseSizes(bidRequest); + let page_rf = !params.referrer ? utils.getTopWindowUrl() : params.referrer; let data = { - page_url: !params.referrer ? utils.getTopWindowUrl() : params.referrer, + page_url: params.secure ? page_rf.replace(/^http:/i, 'https:') : page_rf, resolution: _getScreenResolution(), account_id: params.accountId, integration: INTEGRATION, From 9688c037ceff8bafd2df7a982fcb87eb0805d71f Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Wed, 31 Jan 2018 07:44:32 -0800 Subject: [PATCH 0072/1594] Support setting outstream renderer options (#2025) * Support setting outstream renderer options * Define options in mediaTypes and add test * Move config to renderer.options * Remove default adText --- modules/appnexusBidAdapter.js | 16 +++++++++---- src/auction.js | 2 +- test/spec/modules/appnexusBidAdapter_spec.js | 24 +++++++++++++++++++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 6e5d4820ee1..96163518a3a 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -103,7 +103,7 @@ export const spec = { const rtbBid = getRtbBid(serverBid); if (rtbBid) { if (rtbBid.cpm !== 0 && includes(this.supportedMediaTypes, rtbBid.ad_type)) { - const bid = newBid(serverBid, rtbBid); + const bid = newBid(serverBid, rtbBid, bidderRequest); bid.mediaType = parseMediaType(rtbBid); bids.push(bid); } @@ -123,11 +123,11 @@ export const spec = { } } -function newRenderer(adUnitCode, rtbBid) { +function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { const renderer = Renderer.install({ id: rtbBid.renderer_id, url: rtbBid.renderer_url, - config: { adText: `AppNexus Outstream Video Ad via Prebid.js` }, + config: rendererOptions, loaded: false, }); @@ -178,9 +178,10 @@ function getKeywords(keywords) { * Unpack the Server's Bid into a Prebid-compatible one. * @param serverBid * @param rtbBid + * @param bidderRequest * @return Bid */ -function newBid(serverBid, rtbBid) { +function newBid(serverBid, rtbBid, bidderRequest) { const bid = { requestId: serverBid.uuid, cpm: rtbBid.cpm, @@ -200,9 +201,14 @@ function newBid(serverBid, rtbBid) { }); // This supports Outstream Video if (rtbBid.renderer_url) { + const rendererOptions = utils.deepAccess( + bidderRequest.bids[0], + 'renderer.options' + ); + Object.assign(bid, { adResponse: serverBid, - renderer: newRenderer(bid.adUnitCode, rtbBid) + renderer: newRenderer(bid.adUnitCode, rtbBid, rendererOptions) }); bid.adResponse.ad = bid.adResponse.ads[0]; bid.adResponse.ad.video = bid.adResponse.ad.rtb.video; diff --git a/src/auction.js b/src/auction.js index 62250f573b3..a9701230744 100644 --- a/src/auction.js +++ b/src/auction.js @@ -287,7 +287,7 @@ function getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}) { const adUnitRenderer = bidRequest.bids && bidRequest.bids[0] && bidRequest.bids[0].renderer; - if (adUnitRenderer) { + if (adUnitRenderer && adUnitRenderer.url) { bidObject.renderer = Renderer.install({ url: adUnitRenderer.url }); bidObject.renderer.setRender(adUnitRenderer.render); } diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 6b09690d17a..560fcf40acc 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -1,6 +1,7 @@ import { expect } from 'chai'; import { spec } from 'modules/appnexusBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; @@ -392,7 +393,7 @@ describe('AppNexusAdapter', () => { }); it('handles native responses', () => { - let response1 = Object.assign({}, response); + let response1 = deepClone(response); response1.tags[0].ads[0].ad_type = 'native'; response1.tags[0].ads[0].rtb.native = { 'title': 'Native Creative', @@ -424,5 +425,26 @@ describe('AppNexusAdapter', () => { expect(result[0].native.cta).to.equal('Do it'); expect(result[0].native.image.url).to.equal('http://cdn.adnxs.com/img.png'); }); + + it('supports configuring outstream renderers', () => { + const outstreamResponse = deepClone(response); + outstreamResponse.tags[0].ads[0].rtb.video = {}; + outstreamResponse.tags[0].ads[0].renderer_url = 'renderer.js'; + + const bidderRequest = { + bids: [{ + renderer: { + options: { + adText: 'configured' + } + } + }] + }; + + const result = spec.interpretResponse({ body: outstreamResponse }, {bidderRequest}); + expect(result[0].renderer.config).to.deep.equal( + bidderRequest.bids[0].renderer.options + ); + }); }); }); From c654ebc1ad970053511054784b1792c51916dc31 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Wed, 31 Jan 2018 11:26:32 -0500 Subject: [PATCH 0073/1594] Yieldmo Bid Adapter Update (#2054) * added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync fixed unti tests merge conflicts added mraid check and catch for window.top added height and width, updated tests, fixed interpretResponse, updated md file cleaning up the rebase added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync fixed unti tests added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync added mraid check and catch for window.top added height and width, updated tests, fixed interpretResponse, updated md file * fix tests' * fixed rebase and updated markdown file * added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync fixed unti tests merge conflicts added mraid check and catch for window.top added height and width, updated tests, fixed interpretResponse, updated md file cleaning up the rebase added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync fixed unti tests added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync added mraid check and catch for window.top added height and width, updated tests, fixed interpretResponse, updated md file fix tests' fixed rebase and updated markdown file fixed linting error fixed test test fix * added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync fixed unti tests merge conflicts added mraid check and catch for window.top added height and width, updated tests, fixed interpretResponse, updated md file cleaning up the rebase added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync fixed unti tests added usersync and interpretresponse environments finished building request markdown and test cases pr valid bid requests all tests but user sync added mraid check and catch for window.top added height and width, updated tests, fixed interpretResponse, updated md file * fix tests' * fixed rebase and updated markdown file * update placementId * lint error --- modules/yieldmoBidAdapter.js | 304 ++++++++++++++++++++ modules/yieldmoBidAdapter.md | 31 ++ test/spec/modules/yieldmoBidAdapter_spec.js | 152 ++++++++++ 3 files changed, 487 insertions(+) create mode 100644 modules/yieldmoBidAdapter.js create mode 100644 modules/yieldmoBidAdapter.md create mode 100644 test/spec/modules/yieldmoBidAdapter_spec.js diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js new file mode 100644 index 00000000000..1047224a3b7 --- /dev/null +++ b/modules/yieldmoBidAdapter.js @@ -0,0 +1,304 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'yieldmo'; +const CURRENCY = 'USD'; +const TIME_TO_LIVE = 300; +const NET_REVENUE = true; +const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; +const SERVER_ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; +const localWindow = getTopWindow(); + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['banner'], + /** + * Determines whether or not the given bid request is valid. + * @param {object} bid, bid to validate + * @return boolean, true if valid, otherwise false + */ + isBidRequestValid: function(bid) { + return !!(bid && bid.adUnitCode && bid.bidId); + }, + /** + * 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) { + let serverRequest = { + p: [], + page_url: utils.getTopWindowUrl(), + bust: new Date().getTime().toString(), + pr: utils.getTopWindowReferrer(), + scrd: localWindow.devicePixelRatio || 0, + dnt: getDNT(), + e: getEnvironment(), + description: getPageDescription(), + title: localWindow.document.title || '', + w: localWindow.innerWidth, + h: localWindow.innerHeight + }; + for (var request of bidRequests) { + serverRequest.p.push(addPlacement(request)); + } + serverRequest.p = '[' + serverRequest.p.toString() + ']'; + return { + method: 'GET', + url: SERVER_ENDPOINT, + data: serverRequest + } + }, + /** + * Makes Yieldmo Ad Server response compatible to Prebid specs + * @param serverResponse successful response from Ad Server + * @param bidderRequest original bidRequest + * @return {Bid[]} an array of bids + */ + interpretResponse: function(serverResponse) { + let bids = []; + let data = serverResponse.body; + if (data.length > 0) { + for (var response of data) { + if (response.cpm && response.cpm > 0) { + bids.push(createNewBid(response)); + } + } + } + return bids; + }, + getUserSync: function(syncOptions) { + if (trackingEnabled(syncOptions)) { + return [{ + type: 'iframe', + url: SYNC_ENDPOINT + utils.getOrigin() + }]; + } else { + return []; + } + } +} +registerBidder(spec); + +/*************************************** + * Helper Functions + ***************************************/ + +/** + * Adds placement information to array + * @param request bid request + */ +function addPlacement(request) { + const placementInfo = { + placement_id: request.adUnitCode, + callback_id: request.bidId, + sizes: request.sizes + } + if (request.params && request.params.placementId) { + placementInfo.ym_placement_id = request.params.placementId + } + return JSON.stringify(placementInfo); +} + +/** + * creates a new bid with response information + * @param response server response + */ +function createNewBid(response) { + return { + requestId: response['callback_id'], + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.creativeId, + currency: CURRENCY, + netRevenue: NET_REVENUE, + ttl: TIME_TO_LIVE, + ad: response.ad + }; +} + +/** + * Detects if tracking is allowed + * @returns false if dnt or if not iframe/pixel enabled + */ +function trackingEnabled(options) { + return (isIOS() && !getDNT() && options.iframeEnabled); +} + +/** + * Detects whether we're in iOS + * @returns true if in iOS + */ +function isIOS() { + return /iPhone|iPad|iPod/i.test(window.navigator.userAgent); +} + +/** + * Detects whether dnt is true + * @returns true if user enabled dnt + */ +function getDNT() { + return window.doNotTrack === '1' || window.navigator.doNotTrack === '1' || false; +} + +/** + * get page description + */ +function getPageDescription() { + if (document.querySelector('meta[name="description"]')) { + return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. + } else { + return ''; + } +} + +function getTopWindow() { + try { + return window.top; + } catch (e) { + return window; + } +} + +/*************************************** + * Detect Environment Helper Functions + ***************************************/ + +/** + * Represents a method for loading Yieldmo ads. Environments affect + * which formats can be loaded into the page + * Environments: + * CodeOnPage: 0, // div directly on publisher's page + * Amp: 1, // google Accelerate Mobile Pages ampproject.org + * Mraid = 2, // native loaded through the MRAID spec, without Yieldmo's SDK https://www.iab.net/media/file/IAB_MRAID_v2_FINAL.pdf + * Dfp: 4, // google doubleclick for publishers https://www.doubleclickbygoogle.com/ + * DfpInAmp: 5, // AMP page containing a DFP iframe + * SafeFrame: 10, + * DfpSafeFrame: 11,Sandboxed: 16, // An iframe that can't get to the top window. + * SuperSandboxed: 89, // An iframe without allow-same-origin + * Unknown: 90, // A default sandboxed implementation delivered by EnvironmentDispatch when all positive environment checks fail + */ + +/** + * Detects what environment we're in + * @returns Environment kind + */ +function getEnvironment() { + if (isSuperSandboxedIframe()) { + return 89; + } else if (isDfpInAmp()) { + return 5; + } else if (isDfp()) { + return 4; + } else if (isAmp()) { + return 1; + } else if (isDFPSafeFrame()) { + return 11; + } else if (isSafeFrame()) { + return 10; + } else if (isMraid()) { + return 2; + } else if (isCodeOnPage()) { + return 0; + } else if (isSandboxedIframe()) { + return 16; + } else { + return 90; + } +} + +/** + * @returns true if we are running on the top window at dispatch time + */ +function isCodeOnPage() { + return window === window.parent; +} + +/** + * @returns true if the environment is both DFP and AMP + */ +function isDfpInAmp() { + return isDfp() && isAmp(); +} + +/** + * @returns true if the window is in an iframe whose id and parent element id match DFP + */ +function isDfp() { + try { + const frameElement = window.frameElement; + const parentElement = window.frameElement.parentNode; + if (frameElement && parentElement) { + return frameElement.id.indexOf('google_ads_iframe') > -1 && parentElement.id.indexOf('google_ads_iframe') > -1; + } + return false; + } catch (e) { + return false; + } +} + +/** +* @returns true if there is an AMP context object +*/ +function isAmp() { + try { + const ampContext = window.context || window.parent.context; + if (ampContext && ampContext.pageViewId) { + return ampContext; + } + return false; + } catch (e) { + return false; + } +} + +/** + * @returns true if the environment is a SafeFrame. + */ +function isSafeFrame() { + return window.$sf && window.$sf.ext; +} + +/** + * @returns true if the environment is a dfp safe frame. + */ +function isDFPSafeFrame() { + if (window.location && window.location.href) { + const href = window.location.href; + return isSafeFrame() && href.indexOf('google') !== -1 && href.indexOf('safeframe') !== -1; + } + return false; +} + +/** + * Return true if we are in an iframe and can't access the top window. + */ +function isSandboxedIframe() { + return window.top !== window && !window.frameElement; +} + +/** + * Return true if we cannot document.write to a child iframe (this implies no allow-same-origin) + */ +function isSuperSandboxedIframe() { + const sacrificialIframe = window.document.createElement('iframe'); + try { + sacrificialIframe.setAttribute('style', 'display:none'); + window.document.body.appendChild(sacrificialIframe); + sacrificialIframe.contentWindow._testVar = true; + window.document.body.removeChild(sacrificialIframe); + return false; + } catch (e) { + window.document.body.removeChild(sacrificialIframe); + return true; + } +} + +/** + * @returns true if the window has the attribute identifying MRAID + */ +function isMraid() { + return !!(window.mraid); +} diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md new file mode 100644 index 00000000000..b93f72594bc --- /dev/null +++ b/modules/yieldmoBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +``` +Module Name: Yieldmo Bid Adapter +Module Type: Bidder Adapter +Maintainer: melody@yieldmo.com +Note: Our ads will only render in mobile +``` + +# Description + +Connects to Yieldmo Ad Server for bids. + +Yieldmo bid adapter supports Banner. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'yieldmo', + params: { + placementId: '1779781193098233305' // string with at most 19 characters (may include numbers only) + } + }] + } +]; +``` \ No newline at end of file diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js new file mode 100644 index 00000000000..a91c3dd487a --- /dev/null +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -0,0 +1,152 @@ +import { expect } from 'chai'; +import { spec } from 'modules/yieldmoBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +describe('YieldmoAdapter', () => { + const adapter = newBidder(spec); + const ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; + + let bid = { + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475' + }; + let bidArray = [bid]; + + describe('isBidRequestValid', () => { + it('should return true when necessary information is found', () => { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + + it('should return false when necessary information is not found', () => { + // empty bid + expect(spec.isBidRequestValid({})).to.be.false; + + // empty bidId + bid.bidId = ''; + expect(spec.isBidRequestValid(bid)).to.be.false; + + // empty adUnitCode + bid.bidId = '30b31c1838de1e'; + bid.adUnitCode = ''; + expect(spec.isBidRequestValid(bid)).to.be.false; + + bid.adUnitCode = 'adunit-code'; + }); + }); + + describe('buildRequests', () => { + it('should attempt to send bid requests to the endpoint via GET', () => { + const request = spec.buildRequests(bidArray); + expect(request.method).to.equal('GET'); + expect(request.url).to.be.equal(ENDPOINT); + }); + + it('should place bid information into the p parameter of data', () => { + let placementInfo = spec.buildRequests(bidArray).data.p; + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]]}]'); + + bidArray.push({ + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code-1', + sizes: [[300, 250], [300, 600]], + bidId: '123456789', + bidderRequestId: '987654321', + auctionId: '0246810' + }); + + // multiple placements + placementInfo = spec.buildRequests(bidArray).data.p; + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]]},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]]}]'); + }); + + it('should add placement id if given', () => { + bidArray[0].params.placementId = 'ym_1293871298'; + let placementInfo = spec.buildRequests(bidArray).data.p; + expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"}'); + expect(placementInfo).not.to.include('"ym_placement_id":"ym_0987654321"}'); + + bidArray[1].params.placementId = 'ym_0987654321'; + placementInfo = spec.buildRequests(bidArray).data.p; + expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"}'); + expect(placementInfo).to.include('"ym_placement_id":"ym_0987654321"}'); + }); + + it('should add additional information to data parameter of request', () => { + const data = spec.buildRequests(bidArray).data; + expect(data.hasOwnProperty('page_url')).to.be.true; + expect(data.hasOwnProperty('bust')).to.be.true; + expect(data.hasOwnProperty('pr')).to.be.true; + expect(data.hasOwnProperty('scrd')).to.be.true; + expect(data.dnt).to.be.false; + expect(data.e).to.equal(90); + expect(data.hasOwnProperty('description')).to.be.true; + expect(data.hasOwnProperty('title')).to.be.true; + expect(data.hasOwnProperty('h')).to.be.true; + expect(data.hasOwnProperty('w')).to.be.true; + }) + }); + + describe('interpretResponse', () => { + let serverResponse; + + beforeEach(() => { + serverResponse = { + body: [{ + callback_id: '21989fdbef550a', + cpm: 3.45455, + width: 300, + height: 250, + ad: '
', + creativeId: '9874652394875' + }], + header: 'header?' + }; + }) + + it('should correctly reorder the server response', () => { + const newResponse = spec.interpretResponse(serverResponse); + expect(newResponse.length).to.be.equal(1); + expect(newResponse[0]).to.deep.equal({ + requestId: '21989fdbef550a', + cpm: 3.45455, + width: 300, + height: 250, + creativeId: '9874652394875', + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: '
' + }); + }); + + it('should not add responses if the cpm is 0 or null', () => { + serverResponse.body[0].cpm = 0; + let response = spec.interpretResponse(serverResponse); + expect(response).to.deep.equal([]); + + serverResponse.body[0].cpm = null; + response = spec.interpretResponse(serverResponse); + expect(response).to.deep.equal([]) + }); + }); + + describe('getUserSync', () => { + const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; + let options = { + iframeEnabled: true, + pixelEnabled: true + }; + + it('should return a tracker with type and url as parameters', () => { + // not ios, so tracker will fail + expect(spec.getUserSync(options)).to.deep.equal([]); + }); + }); +}); From 93ce52fe2f810f38e0f0b6de11c5bb8e47643269 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Wed, 31 Jan 2018 18:03:36 +0100 Subject: [PATCH 0074/1594] Added support for ad server currency; added ad unit sizes in test request (#2001) --- modules/improvedigitalBidAdapter.js | 12 ++++++++++-- modules/improvedigitalBidAdapter.md | 3 +++ test/spec/modules/improvedigitalBidAdapter_spec.js | 10 ++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 82c045b9db6..2dcdcb2a808 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -1,11 +1,12 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; import { userSync } from 'src/userSync'; const BIDDER_CODE = 'improvedigital'; export const spec = { - version: '4.0.0', + version: '4.1.0', code: BIDDER_CODE, aliases: ['id'], @@ -113,6 +114,7 @@ function getNormalizedBidRequest(bid) { let localSize = utils.getBidIdParameter('size', bid.params) || null; let bidId = utils.getBidIdParameter('bidId', bid); let transactionId = utils.getBidIdParameter('transactionId', bid); + const currency = config.getConfig('currency.adServerCurrency'); let normalizedBidRequest = {}; if (placementId) { @@ -143,6 +145,9 @@ function getNormalizedBidRequest(bid) { if (transactionId) { normalizedBidRequest.transactionId = transactionId; } + if (currency) { + normalizedBidRequest.currency = currency; + } return normalizedBidRequest; } registerBidder(spec); @@ -160,7 +165,7 @@ function ImproveDigitalAdServerJSClient(endPoint) { AD_SERVER_BASE_URL: 'ad.360yield.com', END_POINT: endPoint || 'hb', AD_SERVER_URL_PARAM: 'jsonp=', - CLIENT_VERSION: 'JS-4.2.0', + CLIENT_VERSION: 'JS-4.3.3', MAX_URL_LENGTH: 2083, ERROR_CODES: { BAD_HTTP_REQUEST_TYPE_PARAM: 1, @@ -337,6 +342,9 @@ function ImproveDigitalAdServerJSClient(endPoint) { if (placementObject.adUnitId) { outputObject.adUnitId = placementObject.adUnitId; } + if (placementObject.currency) { + impressionObject.currency = placementObject.currency.toUpperCase(); + } if (placementObject.placementId) { impressionObject.pid = placementObject.placementId; } diff --git a/modules/improvedigitalBidAdapter.md b/modules/improvedigitalBidAdapter.md index 3d91d4f82f2..d70b624171f 100644 --- a/modules/improvedigitalBidAdapter.md +++ b/modules/improvedigitalBidAdapter.md @@ -12,6 +12,7 @@ Module that connects to Improve Digital's demand sources ``` var adUnits = [{ code: 'div-gpt-ad-1499748733608-0', + sizes: [[600, 290]], bids: [ { bidder: 'improvedigital', @@ -22,6 +23,7 @@ Module that connects to Improve Digital's demand sources ] }, { code: 'div-gpt-ad-1499748833901-0', + sizes: [[250, 250]], bids: [{ bidder: 'improvedigital', params: { @@ -33,6 +35,7 @@ Module that connects to Improve Digital's demand sources }] }, { code: 'div-gpt-ad-1499748913322-0', + sizes: [[300, 300]], bids: [{ bidder: 'improvedigital', params: { diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 3f93a62e850..2725a6ad101 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -1,5 +1,6 @@ import { expect } from 'chai'; import { ImproveDigitalAdServerJSClient, spec } from 'modules/improvedigitalBidAdapter'; +import { config } from 'src/config'; import { userSync } from 'src/userSync'; describe('Improve Digital Adapter Tests', function () { @@ -129,6 +130,15 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.imp[0].banner).to.deep.equal(size); }); + it('should add currency', () => { + const bidRequest = Object.assign({}, simpleBidRequest); + const getConfigStub = sinon.stub(config, 'getConfig').returns('JPY'); + const request = spec.buildRequests([bidRequest])[0]; + const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); + expect(params.bid_request.imp[0].currency).to.equal('JPY'); + getConfigStub.restore(); + }); + it('should return 2 requests', () => { const requests = spec.buildRequests([ simpleBidRequest, From 06e916f26cdd0b5f6e151f71e77d5706db3e45c6 Mon Sep 17 00:00:00 2001 From: danmarketplace <34161426+danmarketplace@users.noreply.github.com> Date: Thu, 1 Feb 2018 20:26:23 +0300 Subject: [PATCH 0075/1594] Make Bid Adapter for Dentsu Aegis Network Marketplace (#1982) * Make Bid Adapter for Dentsu Aegis Network Marketplace * Update DAN_Marketplace adapter --- modules/danmarketplaceBidAdapter.js | 143 +++++++++ modules/danmarketplaceBidAdapter.md | 40 +++ .../modules/danmarketplaceBidAdapter_spec.js | 285 ++++++++++++++++++ 3 files changed, 468 insertions(+) create mode 100644 modules/danmarketplaceBidAdapter.js create mode 100755 modules/danmarketplaceBidAdapter.md create mode 100644 test/spec/modules/danmarketplaceBidAdapter_spec.js diff --git a/modules/danmarketplaceBidAdapter.js b/modules/danmarketplaceBidAdapter.js new file mode 100644 index 00000000000..24b3682042e --- /dev/null +++ b/modules/danmarketplaceBidAdapter.js @@ -0,0 +1,143 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'danmarketplace'; +const ENDPOINT_URL = '//ads.danmarketplace.com/hb'; +const TIME_TO_LIVE = 360; +const ADAPTER_SYNC_URL = '//ads.danmarketplace.com/push_sync'; +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', + noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', + emptyUids: 'Uids should be not empty', + emptySeatbid: 'Seatbid array from response has empty item', + emptyResponse: 'Response is empty', + hasEmptySeatbidArray: 'Response has empty seatbid array', + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' +}; + +/** + * Dentsu Aegis Network Marketplace Bid Adapter. + * Contact: niels@baarsma.net + * + */ +export const spec = { + code: BIDDER_CODE, + + aliases: ['DANMarketplace', 'DAN_Marketplace'], + + isBidRequestValid: function(bid) { + return !!bid.params.uid; + }, + + buildRequests: function(validBidRequests) { + const auids = []; + const bidsMap = {}; + const bids = validBidRequests || []; + let priceType = 'net'; + let reqId; + + bids.forEach(bid => { + if (bid.params.priceType === 'gross') { + priceType = 'gross'; + } + if (!bidsMap[bid.params.uid]) { + bidsMap[bid.params.uid] = [bid]; + auids.push(bid.params.uid); + } else { + bidsMap[bid.params.uid].push(bid); + } + reqId = bid.bidderRequestId; + }); + + const payload = { + u: utils.getTopWindowUrl(), + pt: priceType, + auids: auids.join(','), + r: reqId, + }; + + return { + method: 'GET', + url: ENDPOINT_URL, + data: payload, + bidsMap: bidsMap, + }; + }, + + interpretResponse: function(serverResponse, bidRequest) { + serverResponse = serverResponse && serverResponse.body + const bidResponses = []; + const bidsMap = bidRequest.bidsMap; + const priceType = bidRequest.data.pt; + + let errorMessage; + + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } + + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses); + }); + } + if (errorMessage) utils.logError(errorMessage); + return bidResponses; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: ADAPTER_SYNC_URL + }]; + } + } +} + +function _getBidFromResponse(respItem) { + if (!respItem) { + utils.logError(LOG_ERROR_MESS.emptySeatbid); + } else if (!respItem.bid) { + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + } else if (!respItem.bid[0]) { + utils.logError(LOG_ERROR_MESS.noBid); + } + return respItem && respItem.bid && respItem.bid[0]; +} + +function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { + if (!serverBid) return; + let errorMessage; + if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + awaitingBids.forEach(bid => { + const bidResponse = { + requestId: bid.bidId, // bid.bidderRequestId, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, // bid.bidId, + currency: 'USD', + netRevenue: priceType !== 'gross', + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid + }; + bidResponses.push(bidResponse); + }); + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } + if (errorMessage) { + utils.logError(errorMessage); + } +} + +registerBidder(spec); diff --git a/modules/danmarketplaceBidAdapter.md b/modules/danmarketplaceBidAdapter.md new file mode 100755 index 00000000000..263385949bd --- /dev/null +++ b/modules/danmarketplaceBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +Module Name: Dentsu Aegis Network Marketplace Bidder Adapter +Module Type: Bidder Adapter +Maintainer: niels@baarsma.net + +# Description + +Module that connects to DAN Marketplace demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "danmarketplace", + params: { + uid: '4', + priceType: 'gross' // by default is 'net' + } + } + ] + },{ + code: 'test-div', + sizes: [[728, 90]], + bids: [ + { + bidder: "danmarketplace", + params: { + uid: 5, + priceType: 'gross' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/danmarketplaceBidAdapter_spec.js b/test/spec/modules/danmarketplaceBidAdapter_spec.js new file mode 100644 index 00000000000..ee7f844ae98 --- /dev/null +++ b/test/spec/modules/danmarketplaceBidAdapter_spec.js @@ -0,0 +1,285 @@ +import { expect } from 'chai'; +import { spec } from 'modules/danmarketplaceBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('DAN_Marketplace Adapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'uid': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '6' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '42dbe3a7168a6a', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should attach valid params to the tag', () => { + const request = spec.buildRequests([bidRequests[0]]); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5'); + }); + + it('auids must not be duplicated', () => { + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5,6'); + }); + + it('pt parameter must be "gross" if params.priceType === "gross"', () => { + bidRequests[1].params.priceType = 'gross'; + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'gross'); + expect(payload).to.have.property('auids', '5,6'); + delete bidRequests[1].params.priceType; + }); + + it('pt parameter must be "net" or "gross"', () => { + bidRequests[1].params.priceType = 'some'; + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5,6'); + delete bidRequests[1].params.priceType; + }); + }); + + describe('interpretResponse', () => { + const responses = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 6, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + undefined, + {'bid': [], 'seat': '1'}, + {'seat': '1'}, + ]; + + it('should get correct bid response', () => { + const bidRequests = [ + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should get correct multi bid response', () => { + const bidRequests = [ + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71a5b', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dff80cc4ee346', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '5703af74d0472a', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '300bfeb0d71a5b', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '5703af74d0472a', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 5, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 2
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('handles wrong and nobid responses', () => { + const bidRequests = [ + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '6' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d7190gf', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '7' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71321', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'danmarketplace', + 'params': { + 'uid': '8' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '300bfeb0d7183bb', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + } + ]; + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + expect(result.length).to.equal(0); + }); + }); +}); From 301cf319cf6ba500619a10bc501857dd1190acb7 Mon Sep 17 00:00:00 2001 From: varashellov Date: Thu, 1 Feb 2018 16:56:44 -0800 Subject: [PATCH 0076/1594] Platform.io Bidder Adapter update. Support Native Ads. (#2009) * Add PlatformioBidAdapter * Update platformioBidAdapter.js * Add files via upload * Update hello_world.html * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Update hello_world.html * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update hello_world.html * Add files via upload * Update platformioBidAdapter ## Type of change - [x] Other ## Description of change 1. RequestURL changes 2. Add placementCode to request params * Update platformioBidAdapter * Update platformioBidAdapter ## Type of change - [x] Other ## Description of change 1. RequestURL changes 2. Add placementCode to request params * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.js Endpoint URL change * Update platformioBidAdapter_spec.js Endpoint URL change * Update platformioBidAdapter_spec.js * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Add files via upload * Add files via upload --- modules/platformioBidAdapter.js | 161 ++++++++++++++---- modules/platformioBidAdapter.md | 38 ++++- .../spec/modules/platformioBidAdapter_spec.js | 138 +++++++++++++-- 3 files changed, 279 insertions(+), 58 deletions(-) diff --git a/modules/platformioBidAdapter.js b/modules/platformioBidAdapter.js index fa841dc6026..93907c9bb1a 100644 --- a/modules/platformioBidAdapter.js +++ b/modules/platformioBidAdapter.js @@ -1,10 +1,19 @@ -import {logError, getTopWindowLocation} from 'src/utils'; +import {logError, getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +const NATIVE_DEFAULTS = { + TITLE_LEN: 100, + DESCR_LEN: 200, + SPONSORED_BY_LEN: 50, + IMG_MIN: 150, + ICON_MIN: 50, +}; + export const spec = { code: 'platformio', + supportedMediaTypes: ['native'], isBidRequestValid: bid => ( !!(bid && bid.params && bid.params.pubId && bid.params.siteId) @@ -27,6 +36,7 @@ export const spec = { bidResponseAvailable(request, response.body) ), }; + function bidResponseAvailable(bidRequest, bidResponse) { const idToImpMap = {}; const idToBidMap = {}; @@ -44,19 +54,31 @@ function bidResponseAvailable(bidRequest, bidResponse) { if (idToBidMap[id]) { const bid = {}; bid.requestId = id; - bid.creativeId = idToBidMap[id].adid; + bid.adId = id; + bid.creativeId = id; bid.cpm = idToBidMap[id].price; bid.currency = bidResponse.cur; bid.ttl = 360; bid.netRevenue = true; - bid.ad = idToBidMap[id].adm; - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); - bid.width = idToImpMap[id].banner.w; - bid.height = idToImpMap[id].banner.h; + if (idToImpMap[id]['native']) { + bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); + let nurl = idToBidMap[id].nurl; + nurl = nurl.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); + bid['native']['impressionTrackers'] = [nurl]; + bid.mediaType = 'native'; + } else { + bid.ad = idToBidMap[id].adm; + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); + bid.width = idToImpMap[id].banner.w; + bid.height = idToImpMap[id].banner.h; + } bids.push(bid); } }); @@ -66,43 +88,95 @@ function impression(slot) { return { id: slot.bidId, banner: banner(slot), + 'native': nativeImpression(slot), bidfloor: slot.params.bidFloor || '0.000001', tagid: slot.params.placementId.toString(), }; } function banner(slot) { - const size = slot.params.size.toUpperCase().split('X'); - const width = parseInt(size[0]); - const height = parseInt(size[1]); - return { - w: width, - h: height, + if (!slot.nativeParams) { + const size = slot.params.size.toUpperCase().split('X'); + const width = parseInt(size[0]); + const height = parseInt(size[1]); + return { + w: width, + h: height, + }; }; } -function site(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; - const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; - const appParams = bidderRequest[0].params.app; - if (!appParams) { + +function nativeImpression(slot) { + if (slot.nativeParams) { + const assets = []; + addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); + addAsset(assets, dataAsset(2, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); + addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); + addAsset(assets, imageAsset(4, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); + addAsset(assets, imageAsset(5, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); return { - publisher: { - id: pubId.toString(), - domain: getTopWindowLocation().hostname, + request: JSON.stringify({ assets }), + ver: '1.1', + }; + } + return null; +} + +function addAsset(assets, asset) { + if (asset) { + assets.push(asset); + } +} + +function titleAsset(id, params, defaultLen) { + if (params) { + return { + id, + required: params.required ? 1 : 0, + title: { + len: params.len || defaultLen, }, - id: siteId.toString(), - ref: referrer(), - page: getTopWindowLocation().href, - } + }; } return null; } -function referrer() { - try { - return window.top.document.referrer; - } catch (e) { - return document.referrer; + +function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { + return params ? { + id, + required: params.required ? 1 : 0, + img: { + type, + wmin: params.wmin || defaultMinWidth, + hmin: params.hmin || defaultMinHeight, + } + } : null; +} + +function dataAsset(id, params, type, defaultLen) { + return params ? { + id, + required: params.required ? 1 : 0, + data: { + type, + len: params.len || defaultLen, + } + } : null; +} + +function site(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; + const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; + return { + publisher: { + id: pubId.toString(), + domain: getTopWindowLocation().hostname, + }, + id: siteId.toString(), + ref: getTopWindowReferrer(), + page: getTopWindowLocation().href, } } + function device() { return { ua: navigator.userAgent, @@ -122,4 +196,25 @@ function parse(rawResponse) { return null; } +function nativeResponse(imp, bid) { + if (imp['native']) { + const nativeAd = parse(bid.adm); + const keys = {}; + if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { + nativeAd['native'].assets.forEach(asset => { + keys.title = asset.title ? asset.title.text : keys.title; + keys.body = asset.data && asset.id === 2 ? asset.data.value : keys.body; + keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy; + keys.icon = asset.img && asset.id === 4 ? asset.img.url : keys.icon; + keys.image = asset.img && asset.id === 5 ? asset.img.url : keys.image; + }); + if (nativeAd['native'].link) { + keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); + } + return keys; + } + } + return null; +} + registerBidder(spec); diff --git a/modules/platformioBidAdapter.md b/modules/platformioBidAdapter.md index 0d019d1fe96..81ac81380b0 100644 --- a/modules/platformioBidAdapter.md +++ b/modules/platformioBidAdapter.md @@ -1,12 +1,13 @@ # Overview -**Module Name**: Platform.io Bidder Adapter -**Module Type**: Bidder Adapter -**Maintainer**: sk@ultralab.by +**Module Name**: Platform.io Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: siarhei.kasukhin@platform.io # Description -Connects to Platform.io demand source to fetch bids. +Connects to Platform.io demand source to fetch bids. +Banner and Native formats are supported. Please use ```platformio``` as the bidder code. # Test Parameters @@ -17,11 +18,30 @@ Please use ```platformio``` as the bidder code. bids: [{ bidder: 'platformio', params: { - pubId: '28082', // required - siteId: '26047', // required - size: '250X250', // required - placementId: '123', - bidFloor: '0.001' + pubId: '29521', // required + siteId: '26047', // required + size: '250X250', // required + placementId: '123', + bidFloor: '0.001' + } + }] + },{ + code: 'native-ad-div', + sizes: [[1, 1]], + nativeParams: { + title: { required: true, len: 75 }, + image: { required: true }, + body: { len: 200 }, + sponsoredBy: { len: 20 }, + icon: { required: false } + }, + bids: [{ + bidder: 'platformio', + params: { + pubId: '29521', // required + siteId: '26047', // required + placementId: '123', + bidFloor: '0.001' } }] }]; diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index d775229c9e3..7caca2e0d17 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -1,14 +1,14 @@ import {expect} from 'chai'; import {spec} from 'modules/platformioBidAdapter'; import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; -describe('Platformio Adapter Tests', () => { +describe('Platform.io Adapter Tests', () => { const slotConfigs = [{ placementCode: '/DfpAccount1/slot1', - sizes: [[300, 250]], bidId: 'bid12345', params: { - pubId: '28082', + pubId: '29521', siteId: '26047', placementId: '123', size: '300x250', @@ -16,15 +16,32 @@ describe('Platformio Adapter Tests', () => { } }, { placementCode: '/DfpAccount2/slot2', - sizes: [[250, 250]], bidId: 'bid23456', params: { - pubId: '28082', + pubId: '29521', siteId: '26047', - placementId: '456', - size: '250x250' + placementId: '1234', + size: '728x90', + bidFloor: '0.000001' } }]; + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + nativeParams: { + title: { required: true, len: 200 }, + body: {}, + image: { wmin: 100 }, + sponsoredBy: { }, + icon: { } + }, + params: { + pubId: '29521', + placementId: '123', + siteId: '26047' + } + }]; + it('Verify build request', () => { const request = spec.buildRequests(slotConfigs); expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); @@ -33,7 +50,7 @@ describe('Platformio Adapter Tests', () => { // site object expect(ortbRequest.site).to.not.equal(null); expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('28082'); + expect(ortbRequest.site.publisher.id).to.equal('29521'); expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); expect(ortbRequest.imp).to.have.lengthOf(2); @@ -47,10 +64,10 @@ describe('Platformio Adapter Tests', () => { expect(ortbRequest.imp[0].banner.h).to.equal(250); expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('456'); + expect(ortbRequest.imp[1].tagid).to.equal('1234'); expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(250); - expect(ortbRequest.imp[1].banner.h).to.equal(250); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); }); @@ -62,8 +79,7 @@ describe('Platformio Adapter Tests', () => { bid: [{ impid: ortbRequest.imp[0].id, price: 1.25, - adm: 'This is an Ad', - adid: '471810', + adm: 'This is an Ad' }] }], cur: 'USD' @@ -76,7 +92,9 @@ describe('Platformio Adapter Tests', () => { expect(bid.ad).to.equal('This is an Ad'); expect(bid.width).to.equal(300); expect(bid.height).to.equal(250); - expect(bid.creativeId).to.equal('471810'); + expect(bid.adId).to.equal('bid12345'); + expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); expect(bid.currency).to.equal('USD'); expect(bid.ttl).to.equal(360); }); @@ -87,13 +105,101 @@ describe('Platformio Adapter Tests', () => { expect(bids).to.have.lengthOf(0); }); + it('Verify Native request', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // // native impression + expect(ortbRequest.imp[0].tagid).to.equal('123'); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(5); + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[3].id).to.equal(4); + expect(nativeRequest.assets[4].id).to.equal(5); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(2); + expect(nativeRequest.assets[1].data.len).to.equal(200); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[3].img).to.not.equal(null); + expect(nativeRequest.assets[3].img.wmin).to.equal(50); + expect(nativeRequest.assets[3].img.hmin).to.equal(50); + expect(nativeRequest.assets[3].img.type).to.equal(1); + expect(nativeRequest.assets[4].img).to.not.equal(null); + expect(nativeRequest.assets[4].img.wmin).to.equal(100); + expect(nativeRequest.assets[4].img.hmin).to.equal(150); + expect(nativeRequest.assets[4].img.type).to.equal(3); + }); + + it('Verify Native response', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { id: 1, title: { text: 'Ad Title' } }, + { id: 2, data: { value: 'Test description' } }, + { id: 3, data: { value: 'Brand' } }, + { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png' } }, + { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png' } } + ], + link: { url: 'http://brand.com/' } + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + nurl: 'http://rtb.adx1.com/log', + adm: JSON.stringify(nativeResponse) + }] + }], + cur: 'USD', + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Brand'); + expect(nativeBid.icon).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); + expect(nativeBid.image).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(1); + expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); + }); + it('Verifies bidder code', () => { expect(spec.code).to.equal('platformio'); }); + it('Verifies supported media types', () => { + expect(spec.supportedMediaTypes).to.have.lengthOf(1); + expect(spec.supportedMediaTypes[0]).to.equal('native'); + }); + it('Verifies if bid request valid', () => { expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid({})).to.equal(false); - expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); }); }); From a35780d416f58a89a067f96d38750a46a7d71032 Mon Sep 17 00:00:00 2001 From: Dima Shirokov Date: Fri, 2 Feb 2018 03:03:43 +0200 Subject: [PATCH 0077/1594] Xendiz bid adapter (#1985) * xendizBidAdapter * Prebid endpoint * Drop bidderCode * Sync endpoint update * Test update --- modules/xendizBidAdapter.js | 102 ++++++++++++++++++ modules/xendizBidAdapter.md | 41 +++++++ test/spec/modules/xendizBidAdapter_spec.js | 119 +++++++++++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 modules/xendizBidAdapter.js create mode 100644 modules/xendizBidAdapter.md create mode 100644 test/spec/modules/xendizBidAdapter_spec.js diff --git a/modules/xendizBidAdapter.js b/modules/xendizBidAdapter.js new file mode 100644 index 00000000000..d40d3ada229 --- /dev/null +++ b/modules/xendizBidAdapter.js @@ -0,0 +1,102 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'xendiz'; +const PREBID_ENDPOINT = 'prebid.xendiz.com'; +const SYNC_ENDPOINT = 'https://advsync.com/xendiz/ssp/?pixel=1'; + +const buildURI = () => { + return `//${PREBID_ENDPOINT}/request`; +} + +const getDevice = () => { + const lang = navigator.language; + const width = window.screen.width; + const height = window.screen.height; + + return [lang, width, height]; +}; + +const buildItem = (req) => { + return [ + req.bidId, + req.params, + req.adUnitCode, + req.sizes.map(s => `${s[0]}x${s[1]}`) + ] +} + +export const spec = { + code: BIDDER_CODE, + 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 !!bid.params.pid; + }, + + /** + * 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) { + const payload = { + id: bidRequests[0].auctionId, + items: bidRequests.map(buildItem), + device: getDevice(), + page: utils.getTopWindowUrl(), + dt: +new Date() + }; + const payloadString = JSON.stringify(payload); + + return { + method: 'POST', + url: buildURI(), + 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) { + const bids = serverResponse.body.bids.map(bid => { + return { + requestId: bid.id, + cpm: bid.price, + width: bid.w, + height: bid.h, + creativeId: bid.crid, + netRevenue: bid.netRevenue !== undefined ? bid.netRevenue : true, + dealId: bid.dealid, + currency: bid.cur || 'USD', + ttl: bid.exp || 900, + ad: bid.adm, + } + }); + + return bids; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: SYNC_ENDPOINT + }]; + } + } +} + +registerBidder(spec); diff --git a/modules/xendizBidAdapter.md b/modules/xendizBidAdapter.md new file mode 100644 index 00000000000..4ecabe7070f --- /dev/null +++ b/modules/xendizBidAdapter.md @@ -0,0 +1,41 @@ +# Overview + +Module Name: Xendiz Bidder Adapter +Module Type: Bidder Adapter +Maintainer: hello@xendiz.com + +# Description + +Module that connects to Xendiz demand sources + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "xendiz", + params: { + pid: '00000000-0000-0000-0000-000000000000' + } + } + ] + },{ + code: 'test-div', + sizes: [[300, 50]], + bids: [ + { + bidder: "xendiz", + params: { + pid: '00000000-0000-0000-0000-000000000000', + ext: { + uid: '550e8400-e29b-41d4-a716-446655440000' + } + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/xendizBidAdapter_spec.js b/test/spec/modules/xendizBidAdapter_spec.js new file mode 100644 index 00000000000..1b0ef9c8d4c --- /dev/null +++ b/test/spec/modules/xendizBidAdapter_spec.js @@ -0,0 +1,119 @@ +import { expect } from 'chai'; +import { spec } from 'modules/xendizBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const VALID_ENDPOINT = '//prebid.xendiz.com/request'; +const bidRequest = { + bidder: 'xendiz', + adUnitCode: 'test-div', + sizes: [[300, 250], [300, 600]], + params: { + pid: '550e8400-e29b-41d4-a716-446655440000' + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', +}; + +const bidResponse = { + body: { + id: '1d1a030790a475', + bids: [{ + id: '30b31c1838de1e', + price: 3, + cur: 'USD', + h: 250, + w: 300, + crid: 'test', + dealid: '1', + exp: 900, + adm: 'tag' + }] + } +}; + +const noBidResponse = { body: { id: '1d1a030790a475', bids: [] } }; + +describe('xendizBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return false', () => { + let bid = Object.assign({}, bidRequest); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true', () => { + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + }); + + describe('buildRequests', () => { + it('should format valid url', () => { + const request = spec.buildRequests([bidRequest]); + expect(request.url).to.equal(VALID_ENDPOINT); + }); + + it('should format valid url', () => { + const request = spec.buildRequests([bidRequest]); + expect(request.url).to.equal(VALID_ENDPOINT); + }); + + it('should format valid request body', () => { + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.id).to.exist; + expect(payload.items).to.exist; + expect(payload.device).to.exist; + }); + + it('should attach valid device info', () => { + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.device).to.deep.equal([ + navigator.language, + window.screen.width, + window.screen.height + ]); + }); + + it('should transform sizes', () => { + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + const item = payload.items[0]; + expect(item[item.length - 1]).to.deep.equal(['300x250', '300x600']); + }); + }); + + describe('interpretResponse', () => { + it('should get correct bid response', () => { + const result = spec.interpretResponse(bidResponse); + const validResponse = [{ + requestId: '30b31c1838de1e', + cpm: 3, + width: 300, + height: 250, + creativeId: 'test', + netRevenue: true, + dealId: '1', + currency: 'USD', + ttl: 900, + ad: 'tag' + }]; + + expect(result).to.deep.equal(validResponse); + }); + + it('handles nobid responses', () => { + let result = spec.interpretResponse(noBidResponse); + expect(result.length).to.equal(0); + }); + }); +}); From 0b98a8c85c5ff530bb5ef9f22251a939bee0bff0 Mon Sep 17 00:00:00 2001 From: Rade Popovic <32302052+nanointeractive@users.noreply.github.com> Date: Fri, 2 Feb 2018 02:07:40 +0100 Subject: [PATCH 0078/1594] Bugfix - interpretResponse (#2082) * nanointeractive bid adapter * Bugfix interpretResponse - added body; Removed unnecessary parameters; Adjusted tests; --- modules/nanointeractiveBidAdapter.js | 14 ++------------ modules/nanointeractiveBidAdapter.md | 6 ------ .../modules/nanointeractiveBidAdapter_spec.js | 19 ++++++------------- 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index 05aca3065c9..225859a4360 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -5,26 +5,19 @@ import { BANNER } from '../src/mediaTypes'; export const BIDDER_CODE = 'nanointeractive'; export const ENGINE_BASE_URL = 'https://www.audiencemanager.de/hb'; -export const SECURITY = 'sec'; -export const DATA_PARTNER_ID = 'dpid'; export const DATA_PARTNER_PIXEL_ID = 'pid'; -export const ALG = 'alg'; export const NQ = 'nq'; export const NQ_NAME = 'name'; export const CATEGORY = 'category'; -const DEFAULT_ALG = 'ihr'; - export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], isBidRequestValid(bid) { - const sec = bid.params[SECURITY]; - const dpid = bid.params[DATA_PARTNER_ID]; const pid = bid.params[DATA_PARTNER_PIXEL_ID]; - return !!(sec && dpid && pid); + return !!(pid); }, buildRequests(bidRequests) { let payload = []; @@ -37,7 +30,7 @@ export const spec = { }, interpretResponse(serverResponse) { const bids = []; - serverResponse.forEach(serverBid => { + serverResponse.body.forEach(serverBid => { if (isEngineResponseValid(serverBid)) { bids.push(createSingleBidResponse(serverBid)); } @@ -48,10 +41,7 @@ export const spec = { function createSingleBidRequest(bid) { return { - [SECURITY]: bid.params[SECURITY], - [DATA_PARTNER_ID]: bid.params[DATA_PARTNER_ID], [DATA_PARTNER_PIXEL_ID]: bid.params[DATA_PARTNER_PIXEL_ID], - [ALG]: bid.params[ALG] || DEFAULT_ALG, [NQ]: [createNqParam(bid), createCategoryParam(bid)], sizes: bid.sizes.map(value => value[0] + 'x' + value[1]), bidId: bid.bidId, diff --git a/modules/nanointeractiveBidAdapter.md b/modules/nanointeractiveBidAdapter.md index 0159353750a..0df49999492 100644 --- a/modules/nanointeractiveBidAdapter.md +++ b/modules/nanointeractiveBidAdapter.md @@ -31,8 +31,6 @@ var adUnits = [ bids: [{ bidder: 'nanointeractive', params: { - sec: '04a0cb7fb9ac02840f7f33d68a883780', - dpid: '58bfec94eb0a1916fa380162', pid: '58bfec94eb0a1916fa380163' } }] @@ -44,8 +42,6 @@ var adUnits = [ bids: [{ bidder: 'nanointeractive', params: { - sec: '04a0cb7fb9ac02840f7f33d68a883780', - dpid: '58bfec94eb0a1916fa380162', pid: '58bfec94eb0a1916fa380163', nq: 'user search' } @@ -58,8 +54,6 @@ var adUnits = [ bids: [{ bidder: 'nanointeractive', params: { - sec: '04a0cb7fb9ac02840f7f33d68a883780', - dpid: '58bfec94eb0a1916fa380162', pid: '58bfec94eb0a1916fa380163', name: 'search' } diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index 4b498c88982..14927d929d3 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -2,8 +2,7 @@ import { expect } from 'chai'; import * as utils from 'src/utils'; import { - ALG, - BIDDER_CODE, CATEGORY, DATA_PARTNER_ID, DATA_PARTNER_PIXEL_ID, ENGINE_BASE_URL, NQ, NQ_NAME, SECURITY, + BIDDER_CODE, CATEGORY, DATA_PARTNER_PIXEL_ID, ENGINE_BASE_URL, NQ, NQ_NAME, spec } from '../../../modules/nanointeractiveBidAdapter'; @@ -20,10 +19,7 @@ describe('nanointeractive adapter tests', function () { bidder: BIDDER_CODE, params: (function () { return { - [SECURITY]: isValid === true ? 'sec1' : null, - [DATA_PARTNER_ID]: 'dpid1', - [DATA_PARTNER_PIXEL_ID]: 'pid1', - [ALG]: 'ihr', + [DATA_PARTNER_PIXEL_ID]: isValid === true ? 'pid1' : null, [NQ]: SEARCH_QUERY, [NQ_NAME]: null, [CATEGORY]: null, @@ -38,11 +34,8 @@ describe('nanointeractive adapter tests', function () { } } - const SINGlE_BID_REQUEST = { - [SECURITY]: 'sec1', - [DATA_PARTNER_ID]: 'dpid1', + const SINGLE_BID_REQUEST = { [DATA_PARTNER_PIXEL_ID]: 'pid1', - [ALG]: 'ihr', [NQ]: [SEARCH_QUERY, null], sizes: [WIDTH + 'x' + HEIGHT], bidId: '24a1c9ec270973', @@ -91,16 +84,16 @@ describe('nanointeractive adapter tests', function () { let request = nanoBidAdapter.buildRequests([getBid(true)]); expect(request.method).to.equal('POST'); expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([SINGlE_BID_REQUEST])); + expect(request.data).to.equal(JSON.stringify([SINGLE_BID_REQUEST])); stub.restore(); }); it('Test interpretResponse() length', function () { - let bids = nanoBidAdapter.interpretResponse([getSingleBidResponse(true), getSingleBidResponse(false)]); + let bids = nanoBidAdapter.interpretResponse({body: [getSingleBidResponse(true), getSingleBidResponse(false)]}); expect(bids.length).to.equal(1); }); it('Test interpretResponse() bids', function () { - let bid = nanoBidAdapter.interpretResponse([getSingleBidResponse(true), getSingleBidResponse(false)])[0]; + let bid = nanoBidAdapter.interpretResponse({body: [getSingleBidResponse(true), getSingleBidResponse(false)]})[0]; expect(bid.requestId).to.equal(VALID_BID.requestId); expect(bid.cpm).to.equal(VALID_BID.cpm); expect(bid.width).to.equal(VALID_BID.width); From 1c090417cde9d7800339612b7c6897debed11b78 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Fri, 2 Feb 2018 01:14:37 +0000 Subject: [PATCH 0079/1594] Add support for mixed errors/bids response (#2052) --- modules/audienceNetworkBidAdapter.js | 91 +++++++++---------- .../modules/audienceNetworkBidAdapter_spec.js | 38 ++++++++ 2 files changed, 83 insertions(+), 46 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 2b0e4cd8190..3153a64a48d 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -143,7 +143,7 @@ const buildRequests = bids => { }; const video = findIndex(adformats, isVideo); if (video !== -1) { - [search.playerwidth, search.playerheight] = sizes[video].split('x').map(Number) + [search.playerwidth, search.playerheight] = expandSize(sizes[video]); } const data = formatQS(search); @@ -162,51 +162,50 @@ const buildRequests = bids => { const interpretResponse = ({ body }, { adformats, requestIds, sizes }) => { const ttl = Number(config.getConfig().bidderTimeout); - return body.errors && body.errors.length - ? [] - : Object.keys(body.bids) - // extract Array of bid responses - .map(placementId => body.bids[placementId]) - // flatten - .reduce((a, b) => a.concat(b), []) - // transform to bidResponse - .map((bid, i) => { - const { - bid_id: fb_bidid, - placement_id: creativeId, - bid_price_cents: cpm - } = bid; - - const format = adformats[i]; - const [width, height] = expandSize(flattenSize(sizes[i])); - const ad = createAdHtml(creativeId, format, fb_bidid); - const requestId = requestIds[i]; - - const bidResponse = { - // Prebid attributes - requestId, - cpm: cpm / 100, - width, - height, - ad, - ttl, - creativeId, - netRevenue, - currency, - // Audience Network attributes - hb_bidder, - fb_bidid, - fb_format: format, - fb_placementid: creativeId - }; - // Video attributes - if (isVideo(format)) { - const pageurl = getTopWindowUrlEncoded(); - bidResponse.mediaType = 'video'; - bidResponse.vastUrl = `https://an.facebook.com/v1/instream/vast.xml?placementid=${creativeId}&pageurl=${pageurl}&playerwidth=${width}&playerheight=${height}&bidid=${fb_bidid}`; - } - return bidResponse; - }); + const { bids = {} } = body; + return Object.keys(bids) + // extract Array of bid responses + .map(placementId => bids[placementId]) + // flatten + .reduce((a, b) => a.concat(b), []) + // transform to bidResponse + .map((bid, i) => { + const { + bid_id: fb_bidid, + placement_id: creativeId, + bid_price_cents: cpm + } = bid; + + const format = adformats[i]; + const [width, height] = expandSize(flattenSize(sizes[i])); + const ad = createAdHtml(creativeId, format, fb_bidid); + const requestId = requestIds[i]; + + const bidResponse = { + // Prebid attributes + requestId, + cpm: cpm / 100, + width, + height, + ad, + ttl, + creativeId, + netRevenue, + currency, + // Audience Network attributes + hb_bidder, + fb_bidid, + fb_format: format, + fb_placementid: creativeId + }; + // Video attributes + if (isVideo(format)) { + const pageurl = getTopWindowUrlEncoded(); + bidResponse.mediaType = 'video'; + bidResponse.vastUrl = `https://an.facebook.com/v1/instream/vast.xml?placementid=${creativeId}&pageurl=${pageurl}&playerwidth=${width}&playerheight=${height}&bidid=${fb_bidid}`; + } + return bidResponse; + }); }; export const spec = { diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index cabcdce46f2..6b21eb459d4 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -390,5 +390,43 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseNative.height).to.equal(250); expect(bidResponseNative.ad).to.contain(`placementid:'${nativePlacementId}',format:'native',bidid:'${nativeBidId}'`); }); + + it('mixture of valid native bid and error in response', () => { + const [bidResponse] = interpretResponse({ + body: { + errors: ['test-error-message'], + bids: { + [placementId]: [{ + placement_id: placementId, + bid_id: 'test-bid-id', + bid_price_cents: 123, + bid_price_currency: 'usd', + bid_price_model: 'cpm' + }] + } + } + }, { + adformats: ['native'], + requestIds: [requestId], + sizes: [[300, 250]] + }); + + expect(bidResponse.cpm).to.equal(1.23); + expect(bidResponse.requestId).to.equal(requestId); + expect(bidResponse.width).to.equal(300); + expect(bidResponse.height).to.equal(250); + expect(bidResponse.ad) + .to.contain(`placementid:'${placementId}',format:'native',bidid:'test-bid-id'`, 'ad missing parameters') + .and.to.contain('getElementsByTagName("style")', 'ad missing native styles') + .and.to.contain('
', 'ad missing native container'); + expect(bidResponse.creativeId).to.equal(placementId); + expect(bidResponse.netRevenue).to.equal(true); + expect(bidResponse.currency).to.equal('USD'); + + expect(bidResponse.hb_bidder).to.equal('fan'); + expect(bidResponse.fb_bidid).to.equal('test-bid-id'); + expect(bidResponse.fb_format).to.equal('native'); + expect(bidResponse.fb_placementid).to.equal(placementId); + }); }); }); From 2c7f7ed0c62474672eac5ac9bff8922c7ca5362f Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 1 Feb 2018 17:19:40 -0800 Subject: [PATCH 0080/1594] pass empty responses array for registerSyncs in prebidserverBidAdapter (#2070) --- modules/aolBidAdapter.js | 2 +- modules/prebidServerBidAdapter.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 9b4aa26e1a1..35acb95cdee 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -345,7 +345,7 @@ export const spec = { let bidResponse = bidResponses[0]; if (config.getConfig('aol.userSyncOn') === constants.EVENTS.BID_RESPONSE) { - if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse.ext && bidResponse.ext.pixels) { + if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse && bidResponse.ext && bidResponse.ext.pixels) { $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; return parsePixelItems(bidResponse.ext.pixels); diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 0540d325c79..8f0ded6bb42 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -254,7 +254,7 @@ export function PrebidServer() { requestedBidders.forEach(bidder => { let clientAdapter = adaptermanager.getBidAdapter(bidder); if (clientAdapter && clientAdapter.registerSyncs) { - clientAdapter.registerSyncs(); + clientAdapter.registerSyncs([]); } }); From d7c93506d5ee4122e122323215fe1fc97a4612f2 Mon Sep 17 00:00:00 2001 From: Ryan Chou Date: Fri, 2 Feb 2018 22:09:41 +0800 Subject: [PATCH 0081/1594] Update ucfunnelBidAdapter (#1990) * Add a new ucfunnel Adapter and test page * Add a new ucfunnel Adapter and test page * 1. Use prebid lib in the repo to keep updated 2. Replace var with let 3. Put JSON.parse(JSON.stringify()) into try catch block * utils.getTopWindowLocation is a function * Change to modules from adapters * Migrate to module design * [Dev Fix] Remove width and height which can be got from ad unit id * Update ucfunnelBidAdapter to fit into new spec * Correct the endpoint. Fix the error of query string * Add test case for ucfunnelBidAdapter * Fix lint error * Update version number * Combine all checks on bid request --- modules/ucfunnelBidAdapter.js | 95 ++++++++++++++++ modules/ucfunnelBidAdapter.md | 30 ++++++ test/spec/modules/ucfunnelBidAdapter_spec.js | 108 +++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 modules/ucfunnelBidAdapter.js create mode 100644 modules/ucfunnelBidAdapter.md create mode 100644 test/spec/modules/ucfunnelBidAdapter_spec.js diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js new file mode 100644 index 00000000000..7f652e38c3d --- /dev/null +++ b/modules/ucfunnelBidAdapter.js @@ -0,0 +1,95 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const VER = 'ADGENT_PREBID-2018011501'; +const BID_REQUEST_BASE_URL = '//hb.aralego.com/header'; +const UCFUNNEL_BIDDER_CODE = 'ucfunnel'; + +export const spec = { + code: UCFUNNEL_BIDDER_CODE, + supportedMediaTypes: [BANNER], + /** + * Check if the bid is a valid zone ID in either number or string form + * @param {object} bid the ucfunnel bid to validate + * @return boolean for whether or not a bid is valid + */ + isBidRequestValid: function(bid) { + return !!(bid && bid.params && bid.params.adid && typeof bid.params.adid === 'string'); + }, + + /** + * Format the bid request object for our endpoint + * @param {BidRequest[]} bidRequests Array of ucfunnel bidders + * @return object of parameters for Prebid AJAX request + */ + buildRequests: function(validBidRequests) { + var bidRequests = []; + for (var i = 0; i < validBidRequests.length; i++) { + var bid = validBidRequests[i]; + + var ucfunnelUrlParams = buildUrlParams(bid); + + bidRequests.push({ + method: 'GET', + url: BID_REQUEST_BASE_URL, + bidRequest: bid, + data: ucfunnelUrlParams + }); + } + return bidRequests; + }, + + /** + * Format ucfunnel responses as Prebid bid responses + * @param {ucfunnelResponseObj} ucfunnelResponse A successful response from ucfunnel. + * @return {Bid[]} An array of formatted bids. + */ + interpretResponse: function (ucfunnelResponseObj, request) { + var bidResponses = []; + var bidRequest = request.bidRequest; + var responseBody = ucfunnelResponseObj ? ucfunnelResponseObj.body : {}; + + bidResponses.push({ + requestId: bidRequest.bidId, + cpm: responseBody.cpm || 0, + width: responseBody.width, + height: responseBody.height, + creativeId: responseBody.ad_id, + dealId: responseBody.deal || null, + currency: 'USD', + netRevenue: true, + ttl: 1000, + mediaType: BANNER, + ad: responseBody.adm + }); + + return bidResponses; + } +}; +registerBidder(spec); + +function buildUrlParams(bid) { + const host = utils.getTopWindowLocation().host; + const page = utils.getTopWindowLocation().pathname; + const refer = document.referrer; + const language = navigator.language; + const dnt = (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0; + + let queryString = [ + 'ifr', '0', + 'bl', language, + 'je', '1', + 'dnt', dnt, + 'host', host, + 'u', page, + 'ru', refer, + 'adid', utils.getBidIdParameter('adid', bid.params), + 'ver', VER + ]; + + return queryString.reduce( + (memo, curr, index) => + index % 2 === 0 && queryString[index + 1] !== undefined ? memo + curr + '=' + encodeURIComponent(queryString[index + 1]) + '&' : memo, '' + ).slice(0, -1); +} diff --git a/modules/ucfunnelBidAdapter.md b/modules/ucfunnelBidAdapter.md new file mode 100644 index 00000000000..717d2a0089c --- /dev/null +++ b/modules/ucfunnelBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +``` +Module Name: ucfunnel Bid Adapter +Module Type: Bidder Adapter +Maintainer: ryan.chou@ucfunnel.com +``` + +# Description + +This module connects to ucfunnel's demand sources. It supports display, and rich media formats. +ucfunnel will provide ``adid`` that are specific to your ad type. +Please reach out to ``pr@ucfunnel.com`` to set up an ucfunnel account and above ids. +Use bidder code ```ucfunnel``` for all ucfunnel traffic. + +# Test Parameters + +``` + var adUnits = [ + { + code: 'test-LERC', + sizes: [[300, 250]], + bids: [{ + bidder: 'ucfunnel', + params: { + adid: "test-ad-83444226E44368D1E32E49EEBE6D29" //String - required + } + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js new file mode 100644 index 00000000000..152c7c39b1e --- /dev/null +++ b/test/spec/modules/ucfunnelBidAdapter_spec.js @@ -0,0 +1,108 @@ +import { expect } from 'chai'; +import { spec } from 'modules/ucfunnelBidAdapter'; + +const URL = '//hb.aralego.com/header'; +const BIDDER_CODE = 'ucfunnel'; +const validBidReq = { + bidder: BIDDER_CODE, + params: { + adid: 'test-ad-83444226E44368D1E32E49EEBE6D29' + }, + sizes: [[300, 250]], + bidId: '263be71e91dd9d', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', +}; + +const invalidBidReq = { + bidder: BIDDER_CODE, + params: { + adid: 123456789 + }, + sizes: [[300, 250]], + bidId: '263be71e91dd9d', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' +}; + +const bidReq = [{ + bidder: BIDDER_CODE, + params: { + adid: 'test-ad-83444226E44368D1E32E49EEBE6D29' + }, + sizes: [[300, 250]], + bidId: '263be71e91dd9d', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' +}]; + +const validBidRes = { + ad_id: 'ad-83444226E44368D1E32E49EEBE6D29', + adm: '
', + cpm: 0.01, + height: 250, + width: 300 +}; + +const bidResponse = validBidRes; + +const bidResArray = [ + validBidRes, + { + ad: '', + bidRequestId: '263be71e91dd9d', + cpm: 100, + adId: '123abc', + currency: 'USD', + netRevenue: true, + width: 300, + height: 250, + ttl: 360 + }, + { + ad: '
Hello
', + bidRequestId: '', + cpm: 0, + adId: '123abc', + currency: 'USD', + netRevenue: true, + width: 300, + height: 250, + ttl: 360 + } +]; + +describe('ucfunnel Adapter', () => { + describe('request', () => { + it('should validate bid request', () => { + expect(spec.isBidRequestValid(validBidReq)).to.equal(true); + }); + it('should not validate incorrect bid request', () => { + expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); + }); + }); + describe('build request', () => { + it('Verify bid request', () => { + const request = spec.buildRequests(bidReq); + expect(request[0].method).to.equal('GET'); + expect(request[0].url).to.equal(URL); + expect(request[0].data).to.match(new RegExp(`${bidReq[0].params.adid}`)); + }); + }); + + describe('interpretResponse', () => { + it('should build bid array', () => { + const request = spec.buildRequests(bidReq); + const result = spec.interpretResponse({body: bidResponse}, request[0]); + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', () => { + const request = spec.buildRequests(bidReq); + const result = spec.interpretResponse({body: bidResponse}, request[0]); + const bid = result[0]; + + expect(bid.requestId).to.equal('263be71e91dd9d'); + expect(bid.cpm).to.equal(0.01); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + }); + }); +}); From 8a50184aea32fbee3f181c16fd97e0115181f5ba Mon Sep 17 00:00:00 2001 From: Jarrod Swart Date: Fri, 2 Feb 2018 09:15:40 -0500 Subject: [PATCH 0082/1594] Serverbid server optimization (#2048) * Optimize sending requests. * Add integration example. Minor changes. --- .../gpt/serverbidServer_example.html | 103 ++++++++++++++++++ modules/serverbidServerBidAdapter.js | 36 +++--- 2 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 integrationExamples/gpt/serverbidServer_example.html diff --git a/integrationExamples/gpt/serverbidServer_example.html b/integrationExamples/gpt/serverbidServer_example.html new file mode 100644 index 00000000000..3d76e963663 --- /dev/null +++ b/integrationExamples/gpt/serverbidServer_example.html @@ -0,0 +1,103 @@ + + + + + + + + +

Prebid.js S2S Example

+ +
Div-1
+
+ +
+ + diff --git a/modules/serverbidServerBidAdapter.js b/modules/serverbidServerBidAdapter.js index 4be96a09bd6..1025d29a6c0 100644 --- a/modules/serverbidServerBidAdapter.js +++ b/modules/serverbidServerBidAdapter.js @@ -7,7 +7,7 @@ import { config } from 'src/config'; const TYPE = S2S.SRC; const getConfig = config.getConfig; -const REQUIRED_S2S_CONFIG_KEYS = ['siteId', 'networkId', 'bidders', 'endpoint']; +const REQUIRED_S2S_CONFIG_KEYS = ['siteId', 'networkId', 'bidders']; let _s2sConfig; @@ -100,30 +100,30 @@ ServerBidServerAdapter = function ServerBidServerAdapter() { function _callBids(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { let bidRequest = s2sBidRequest; - // one request per ad unit + const data = { + placements: [], + time: Date.now(), + user: {}, + url: utils.getTopWindowUrl(), + referrer: document.referrer, + enableBotFiltering: true, + includePricingData: true, + parallel: true + }; + const allBids = []; + for (let i = 0; i < bidRequest.ad_units.length; i++) { let adunit = bidRequest.ad_units[i]; let siteId = _s2sConfig.siteId; let networkId = getLocalConfig().networkId; let sizes = adunit.sizes; - const data = { - placements: [], - time: Date.now(), - user: {}, - url: utils.getTopWindowUrl(), - referrer: document.referrer, - enableBotFiltering: true, - includePricingData: true, - parallel: true - }; - - const bids = adunit.bids || []; - + var bids = adunit.bids || []; // one placement for each of the bids for (let i = 0; i < bids.length; i++) { const bid = bids[i]; bid.code = adunit.code; + allBids.push(bid); const placement = Object.assign({}, { divName: bid.bid_id, @@ -138,9 +138,9 @@ ServerBidServerAdapter = function ServerBidServerAdapter() { data.placements.push(placement); } } - if (data.placements.length) { - ajax(BASE_URI, _responseCallback(addBidResponse, bids, done), JSON.stringify(data), { method: 'POST', withCredentials: true, contentType: 'application/json' }); - } + } + if (data.placements.length) { + ajax(BASE_URI, _responseCallback(addBidResponse, allBids, done), JSON.stringify(data), { method: 'POST', withCredentials: true, contentType: 'application/json' }); } } From 8b9c20b035c603aea7ff43d577f2132f95d08fb1 Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Fri, 2 Feb 2018 20:07:56 +0200 Subject: [PATCH 0083/1594] Update vidazooBidAdapter.js (#2076) small adjustment to the user sync mechanism --- modules/vidazooBidAdapter.js | 58 ++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/modules/vidazooBidAdapter.js b/modules/vidazooBidAdapter.js index 385e3b8d427..981f5603a0a 100644 --- a/modules/vidazooBidAdapter.js +++ b/modules/vidazooBidAdapter.js @@ -81,33 +81,39 @@ function interpretResponse(serverResponse, request) { function getUserSyncs(syncOptions, responses) { const {iframeEnabled, pixelEnabled} = syncOptions; - const lookup = {}; - const syncs = []; - responses.forEach(response => { - const {body} = response; - const cookies = body ? body.cookies || [] : []; - cookies.forEach(cookie => { - switch (cookie.type) { - case INTERNAL_SYNC_TYPE.IFRAME: - if (iframeEnabled && !lookup[cookie.src]) { - syncs.push({ - type: EXTERNAL_SYNC_TYPE.IFRAME, - url: cookie.src - }); - } - break; - case INTERNAL_SYNC_TYPE.IMAGE: - if (pixelEnabled && !lookup[cookie.src]) { - syncs.push({ - type: EXTERNAL_SYNC_TYPE.IMAGE, - url: cookie.src - }); - } - break; - } + + if (iframeEnabled) { + return [{ + type: 'iframe', + url: '//static.cliipa.com/basev/sync/user_sync.html' + }]; + } + + if (pixelEnabled) { + const lookup = {}; + const syncs = []; + responses.forEach(response => { + const {body} = response; + const cookies = body ? body.cookies || [] : []; + cookies.forEach(cookie => { + switch (cookie.type) { + case INTERNAL_SYNC_TYPE.IFRAME: + break; + case INTERNAL_SYNC_TYPE.IMAGE: + if (pixelEnabled && !lookup[cookie.src]) { + syncs.push({ + type: EXTERNAL_SYNC_TYPE.IMAGE, + url: cookie.src + }); + } + break; + } + }); }); - }); - return syncs; + return syncs; + } + + return []; } export const spec = { From 9f412aa9441e5e37bbc2c4a58c146574cee6b9b9 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 2 Feb 2018 10:16:42 -0800 Subject: [PATCH 0084/1594] add digitrust support to prebidserverBidAdapter (#2075) * add digitrust support to prebidserverBidAdapter * fixed typo --- modules/prebidServerBidAdapter.js | 23 ++++++++++++ .../modules/prebidServerBidAdapter_spec.js | 35 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 8f0ded6bb42..30a2cf54f02 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -166,6 +166,23 @@ const paramTypes = { }, }; +function _getDigiTrustQueryParams() { + function getDigiTrustId() { + let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); + return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; + } + let digiTrustId = getDigiTrustId(); + // Verify there is an ID and this user has not opted out + if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { + return null; + } + return { + id: digiTrustId.id, + keyv: digiTrustId.keyv, + pref: 0 + }; +} + /** * Bidder adapter for Prebid Server */ @@ -218,6 +235,12 @@ export function PrebidServer() { is_debug: isDebug }; + let digiTrust = _getDigiTrustQueryParams(); + + if (digiTrust) { + requestJson.digiTrust = digiTrust; + } + // in case config.bidders contains invalid bidders, we only process those we sent requests for. const requestedBidders = requestJson.ad_units.map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(utils.uniques)).reduce(utils.flatten).filter(utils.uniques); function processResponse(response) { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 608ac102ace..58a71158865 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -243,6 +243,41 @@ describe('S2S Adapter', () => { expect(requestBid.ad_units[0].bids[0].params.placementId).to.exist.and.to.be.a('number'); expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); }); + + it('adds digitrust id is present and user is not optout', () => { + let digiTrustObj = { + success: true, + identity: { + privacy: { + optout: false + }, + id: 'testId', + keyv: 'testKeyV' + } + }; + + window.DigiTrust = { + getUser: () => digiTrustObj + }; + + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.digiTrust).to.deep.equal({ + id: digiTrustObj.identity.id, + keyv: digiTrustObj.identity.keyv, + pref: 0 + }); + + digiTrustObj.identity.privacy.optout = true; + + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + requestBid = JSON.parse(requests[1].requestBody); + + expect(requestBid.digiTrust).to.not.exist; + + delete window.DigiTrust; + }); }); describe('response handler', () => { From 7773f5854972b6de7e2840ad14a0323ea348fb31 Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Sat, 3 Feb 2018 06:49:53 +0800 Subject: [PATCH 0085/1594] Pass app and device fields to Prebid server (#2044) * Pass app to Prebid server pbsrequest.go code is indeed developed to read the app fields present in the root of PBSRequest json not in the PBSRequest.ad_units child object. So far no app bundle is passed in the prebid server payload to the differents bidders... With this fix, the device and app should be passed in the setConfig rather than AdUnits. * Update prebidServerBidAdapter.js --- modules/prebidServerBidAdapter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 30a2cf54f02..e222ecb446b 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -210,6 +210,8 @@ 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 isDebug = !!getConfig('debug'); + const app = !!getConfig('app'); + const device = !!getConfig('device'); const adUnits = utils.deepClone(s2sBidRequest.ad_units); adUnits.forEach(adUnit => { let videoMediaType = utils.deepAccess(adUnit, 'mediaTypes.video'); @@ -232,7 +234,9 @@ export function PrebidServer() { url: utils.getTopWindowUrl(), prebid_version: '$prebid.version$', ad_units: adUnits.filter(hasSizes), - is_debug: isDebug + is_debug: isDebug, + device: device, + app: app }; let digiTrust = _getDigiTrustQueryParams(); From b69f351bbb296e61b929a5b8113e224c57c0aa20 Mon Sep 17 00:00:00 2001 From: Jarrod Swart Date: Mon, 5 Feb 2018 07:36:38 -0500 Subject: [PATCH 0086/1594] Remove extraneous x. (#2096) --- modules/serverbidBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index f0fa7c18641..2b1de9a9a89 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -19,7 +19,7 @@ const CONFIG = { 'adsparc': { 'BASE_URI': 'https://e.serverbid.com/api/v2' }, - 'automatadx': { + 'automatad': { 'BASE_URI': 'https://e.serverbid.com/api/v2' } }; From 53ab63d985592ee6a0d40b907894c6994095b126 Mon Sep 17 00:00:00 2001 From: Nick Narbone Date: Mon, 5 Feb 2018 13:34:40 -0500 Subject: [PATCH 0087/1594] Adding Sonobi Bidder Adapter (#2033) --- modules/sonobiBidAdapter.js | 137 ++++++++++++ modules/sonobiBidAdapter.md | 32 +++ test/spec/modules/sonobiBidAdapter_spec.js | 229 +++++++++++++++++++++ 3 files changed, 398 insertions(+) create mode 100644 modules/sonobiBidAdapter.js create mode 100644 modules/sonobiBidAdapter.md create mode 100644 test/spec/modules/sonobiBidAdapter_spec.js diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js new file mode 100644 index 00000000000..0211f3ad0b8 --- /dev/null +++ b/modules/sonobiBidAdapter.js @@ -0,0 +1,137 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { getTopWindowLocation, parseSizesInput } from 'src/utils'; +import * as utils from '../src/utils'; + +const BIDDER_CODE = 'sonobi'; +const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; + +export const spec = { + code: BIDDER_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: bid => !!(bid.params && (bid.params.ad_unit || bid.params.placement_id) && (bid.params.sizes || bid.sizes)), + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests - an array of bids + * @return {object} ServerRequest - Info describing the request to the server. + */ + buildRequests: (validBidRequests) => { + const bids = validBidRequests.map(bid => { + let slotIdentifier = _validateSlot(bid) + if (/^[\/]?[\d]+[[\/].+[\/]?]?$/.test(slotIdentifier)) { + slotIdentifier = slotIdentifier.charAt(0) === '/' ? slotIdentifier : '/' + slotIdentifier + return { + [`${slotIdentifier}|${bid.bidId}`]: `${_validateSize(bid)}${_validateFloor(bid)}` + } + } else if (/^[0-9a-fA-F]{20}$/.test(slotIdentifier) && slotIdentifier.length === 20) { + return { + [bid.bidId]: `${slotIdentifier}|${_validateSize(bid)}${_validateFloor(bid)}` + } + } else { + utils.logError(`The ad unit code or Sonobi Placement id for slot ${bid.bidId} is invalid`); + } + }); + + const payload = { + 'key_maker': JSON.stringify(Object.assign({}, ...bids)), + 'ref': getTopWindowLocation().host, + 's': utils.generateUUID(), + }; + + return { + method: 'GET', + url: STR_ENDPOINT, + withCredentials: true, + data: payload + }; + }, + /** + * 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: (serverResponse) => { + const bidResponse = serverResponse.body; + const bidsReturned = []; + + if (Object.keys(bidResponse.slots).length === 0) { + return bidsReturned; + } + + Object.keys(bidResponse.slots).forEach(slot => { + const bid = bidResponse.slots[slot]; + + if (bid.sbi_aid && bid.sbi_mouse && bid.sbi_size) { + const bids = { + requestId: slot.split('|').slice(-1)[0], + cpm: Number(bid.sbi_mouse), + width: Number(bid.sbi_size.split('x')[0]) || 1, + height: Number(bid.sbi_size.split('x')[1]) || 1, + ad: _creative(bidResponse.sbi_dc, bid.sbi_aid), + ttl: 500, + creativeId: bid.sbi_aid, + netRevenue: true, + currency: 'USD', + }; + + if (bid.sbi_dozer) { + bids.dealId = bid.sbi_dozer; + } + + bidsReturned.push(bids); + } + }); + return bidsReturned; + }, + /** + * Register User Sync. + */ + getUserSyncs: (syncOptions, serverResponses) => { + const syncs = []; + if (syncOptions.pixelEnabled && serverResponses[0].body.sbi_px) { + serverResponses[0].body.sbi_px.forEach(pixel => { + syncs.push({ + type: pixel.type, + url: pixel.url + }); + }); + } + return syncs; + } +} + +function _validateSize (bid) { + if (bid.params.sizes) { + return parseSizesInput(bid.params.sizes).join(','); + } + return parseSizesInput(bid.sizes).join(','); +} + +function _validateSlot (bid) { + if (bid.params.ad_unit) { + return bid.params.ad_unit; + } + return bid.params.placement_id; +} + +function _validateFloor (bid) { + if (bid.params.floor) { + return `|f=${bid.params.floor}`; + } + return ''; +} + +function _creative (sbi_dc, sbi_aid) { + const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null'; + return ''; +} + +registerBidder(spec); diff --git a/modules/sonobiBidAdapter.md b/modules/sonobiBidAdapter.md new file mode 100644 index 00000000000..91e4a0e2b2e --- /dev/null +++ b/modules/sonobiBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +``` +Module Name: Sonobi Bidder Adapter +Module Type: Bidder Adapter +Maintainer: apex.prebid@sonobi.com +``` + +# Description + +Module that connects to Sonobi's demand sources. + +# Test Parameters +``` + var adUnits = [ + { + code: 'adUnit_af', + sizes: [[300, 250], [300, 600]], // a display size + bids: [ + { + bidder: 'sonobi', + params: { + ad_unit: '/7780971/sparks_prebid_MR', + placement_id: '1a2b3c4d5e6f1a2b3c4d', // ad_unit and placement_id are mutually exclusive + sizes: [[300, 250], [300, 600]], + floor: 1 // optional + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js new file mode 100644 index 00000000000..525a1bde7cd --- /dev/null +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -0,0 +1,229 @@ +import { expect } from 'chai' +import { spec } from 'modules/sonobiBidAdapter' +import { newBidder } from 'src/adapters/bidderFactory' + +describe('SonobiBidAdapter', () => { + const adapter = newBidder(spec) + + describe('.code', () => { + it('should return a bidder code of sonobi', () => { + expect(spec.code).to.equal('sonobi') + }) + }) + + describe('inherited functions', () => { + it('should exist and be a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function') + }) + }) + + describe('.isBidRequestValid', () => { + let bid = { + 'bidder': 'sonobi', + 'params': { + 'ad_unit': '/7780971/sparks_prebid_MR', + 'sizes': [[300, 250], [300, 600]], + 'floor': '1' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true) + }) + + it('should return true when bid.params.placement_id and bid.params.sizes are found', () => { + let bid = Object.assign({}, bid) + delete bid.params + delete bid.sizes + bid.params = { + 'placement_id': '1a2b3c4d5e6f1a2b3c4d', + 'sizes': [[300, 250], [300, 600]], + } + + expect(spec.isBidRequestValid(bid)).to.equal(true) + }) + + it('should return true when bid.params.placement_id and bid.sizes are found', () => { + let bid = Object.assign({}, bid) + delete bid.params + bid.sizes = [[300, 250], [300, 600]] + bid.params = { + 'placement_id': '1a2b3c4d5e6f1a2b3c4d', + } + + expect(spec.isBidRequestValid(bid)).to.equal(true) + }) + + it('should return true when bid.params.ad_unit and bid.params.sizes are found', () => { + let bid = Object.assign({}, bid) + delete bid.params + delete bid.sizes + bid.params = { + 'ad_unit': '/7780971/sparks_prebid_MR', + 'sizes': [[300, 250], [300, 600]], + } + + expect(spec.isBidRequestValid(bid)).to.equal(true) + }) + + it('should return true when bid.params.ad_unit and bid.sizes are found', () => { + let bid = Object.assign({}, bid) + delete bid.params + bid.sizes = [[300, 250], [300, 600]] + bid.params = { + 'ad_unit': '/7780971/sparks_prebid_MR', + } + + expect(spec.isBidRequestValid(bid)).to.equal(true) + }) + + it('should return false when no params are found', () => { + let bid = Object.assign({}, bid) + delete bid.params + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + + it('should return false when bid.params.placement_id and bid.params.ad_unit are not found', () => { + let bid = Object.assign({}, bid) + delete bid.params + bid.params = { + 'placement_id': 0, + 'ad_unit': 0, + 'sizes': [[300, 250], [300, 600]], + } + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + }) + + describe('.buildRequests', () => { + let bidRequest = [{ + 'bidder': 'sonobi', + 'params': { + 'placement_id': '1a2b3c4d5e6f1a2b3c4d', + 'sizes': [[300, 250], [300, 600]], + 'floor': '1.25', + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1f', + }, + { + 'bidder': 'sonobi', + 'params': { + 'ad_unit': '/7780971/sparks_prebid_LB', + 'sizes': [[300, 250], [300, 600]], + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[120, 600], [300, 600], [160, 600]], + 'bidId': '30b31c1838de1e', + }]; + + let keyMakerData = { + '30b31c1838de1f': '1a2b3c4d5e6f1a2b3c4d|300x250,300x600|f=1.25', + '/7780971/sparks_prebid_LB|30b31c1838de1e': '300x250,300x600', + }; + + it('should return a properly formatted request', () => { + const bidRequests = spec.buildRequests(bidRequest) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.key_maker).to.deep.equal(JSON.stringify(keyMakerData)) + expect(bidRequests.data.ref).not.to.be.empty + expect(bidRequests.data.s).not.to.be.empty + }) + }) + + describe('.interpretResponse', () => { + let bidResponse = { + 'body': { + 'slots': { + '/7780971/sparks_prebid_LB|30b31c1838de1d': { + 'sbi_size': '300x600', + 'sbi_apoc': 'remnant', + 'sbi_aid': '30292e432662bd5f86d90774b944b039', + 'sbi_mouse': 1.07, + }, + '30b31c1838de1f': { + 'sbi_size': '300x250', + 'sbi_apoc': 'remnant', + 'sbi_aid': '30292e432662bd5f86d90774b944b038', + 'sbi_mouse': 1.25, + 'sbi_dozer': 'dozerkey', + }, + '30b31c1838de1e': {}, + }, + 'sbi_dc': 'mco-1-', + 'sbi_px': [{ + 'code': 'so', + 'delay': 0, + 'url': 'https://example.com/pixel.png', + 'type': 'image' + }], + 'sbi_suid': 'af99f47a-e7b1-4791-ab32-34952d87c5a0', + } + }; + + let prebidResponse = [{ + 'requestId': '30b31c1838de1d', + 'cpm': 1.07, + 'width': 300, + 'height': 600, + 'ad': '', + 'ttl': 500, + 'creativeId': '30292e432662bd5f86d90774b944b039', + 'netRevenue': true, + 'currency': 'USD' + }, { + 'requestId': '30b31c1838de1f', + 'cpm': 1.25, + 'width': 300, + 'height': 250, + 'ad': '', + 'ttl': 500, + 'creativeId': '30292e432662bd5f86d90774b944b038', + 'netRevenue': true, + 'currency': 'USD', + 'dealId': 'dozerkey' + }]; + + it('should map bidResponse to prebidResponse', () => { + const response = spec.interpretResponse(bidResponse); + expect(response).to.deep.equal(prebidResponse); + }) + }) + + describe('.getUserSyncs', () => { + let bidResponse = [{ + 'body': { + 'sbi_px': [{ + 'code': 'so', + 'delay': 0, + 'url': 'https://pixel-test', + 'type': 'image' + }] + } + }]; + + it('should return one sync pixel', () => { + expect(spec.getUserSyncs({ pixelEnabled: true }, bidResponse)).to.deep.equal([{ + type: 'image', + url: 'https://pixel-test' + }]); + }) + + it('should return an empty array when sync is enabled but no sync pixel returned', () => { + const pixel = Object.assign({}, bidResponse); + delete pixel[0].body.sbi_px; + expect(spec.getUserSyncs({ pixelEnabled: true }, bidResponse)).to.have.length(0); + }) + + it('should return an empty array', () => { + expect(spec.getUserSyncs({ pixelEnabled: false }, bidResponse)).to.have.length(0); + }) + }) +}) From 77ad2f19f8473dce0c4636d236335c7612a55cc8 Mon Sep 17 00:00:00 2001 From: chanand Date: Tue, 6 Feb 2018 01:00:07 +0200 Subject: [PATCH 0088/1594] add peak adapter (#2040) --- modules/peak226BidAdapter.js | 97 +++++++++++++++++ modules/peak226BidAdapter.md | 31 ++++++ test/spec/modules/peak226BidAdapter_spec.js | 114 ++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 modules/peak226BidAdapter.js create mode 100644 modules/peak226BidAdapter.md create mode 100644 test/spec/modules/peak226BidAdapter_spec.js diff --git a/modules/peak226BidAdapter.js b/modules/peak226BidAdapter.js new file mode 100644 index 00000000000..4f4ee2f97ff --- /dev/null +++ b/modules/peak226BidAdapter.js @@ -0,0 +1,97 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; +import { getTopWindowUrl, logWarn } from 'src/utils'; + +const BIDDER_CODE = 'peak226'; +const URL = '//a.ad216.com/header_bid'; + +export const spec = { + code: BIDDER_CODE, + + supportedMediaTypes: [BANNER], + + isBidRequestValid: function (bid) { + const { params } = bid; + + return !!params.uid; + }, + + buildRequests: function (validBidRequests) { + const bidsMap = validBidRequests.reduce((res, bid) => { + const { uid } = bid.params; + + res[uid] = res[uid] || []; + res[uid].push(bid); + + return res; + }, {}); + + return { + method: 'GET', + url: + URL + + toQueryString({ + u: getTopWindowUrl(), + auids: Object.keys(bidsMap).join(',') + }), + bidsMap + }; + }, + + interpretResponse: function (serverResponse, { bidsMap }) { + const response = serverResponse.body; + const bidResponses = []; + + if (!response) { + logWarn(`No response from ${spec.code} bidder`); + + return bidResponses; + } + + if (!response.seatbid || !response.seatbid.length) { + logWarn(`No seatbid in response from ${spec.code} bidder`); + + return bidResponses; + } + + response.seatbid.forEach((seatbid, i) => { + if (!seatbid.bid || !seatbid.bid.length) { + logWarn(`No bid in seatbid[${i}] response from ${spec.code} bidder`); + return; + } + seatbid.bid.forEach(responseBid => { + const requestBids = bidsMap[responseBid.auid]; + + requestBids.forEach(requestBid => { + bidResponses.push({ + requestId: requestBid.bidId, + bidderCode: spec.code, + width: responseBid.w, + height: responseBid.h, + mediaType: BANNER, + creativeId: responseBid.auid, + ad: responseBid.adm, + cpm: responseBid.price, + currency: 'USD', + netRevenue: true, + ttl: 360 + }); + }); + }); + }); + + return bidResponses; + } +}; + +function toQueryString(obj) { + return Object.keys(obj).reduce( + (str, key, i) => + typeof obj[key] === 'undefined' || obj[key] === '' + ? str + : `${str}${str ? '&' : '?'}${key}=${encodeURIComponent(obj[key])}`, + '' + ); +} + +registerBidder(spec); diff --git a/modules/peak226BidAdapter.md b/modules/peak226BidAdapter.md new file mode 100644 index 00000000000..bae15d6c99f --- /dev/null +++ b/modules/peak226BidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +``` +Module Name: Peak226 Bidder Adapter +Module Type: Bidder Adapter +Maintainer: support@edge226.com +``` + +# Description + +Module that connects to Peak226's demand sources + +# Test Parameters + +``` + var adUnits = [ + { + code: "test-div", + sizes: [[300, 250]], + mediaType: "banner", + bids: [ + { + bidder: "peak226", + params: { + uid: 76131369 + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/peak226BidAdapter_spec.js b/test/spec/modules/peak226BidAdapter_spec.js new file mode 100644 index 00000000000..37bbc1b67bd --- /dev/null +++ b/test/spec/modules/peak226BidAdapter_spec.js @@ -0,0 +1,114 @@ +import { expect } from 'chai'; +import { spec } from 'modules/peak226BidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const URL = 'a.ad216.com/header_bid'; + +describe('PeakAdapter', () => { + const adapter = newBidder(spec); + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + const bid = { + params: { + uid: 123 + } + }; + + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', () => { + const bid = { + params: {} + }; + + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + xdescribe('buildRequests', () => { + const bidRequests = [ + { + params: { + uid: '1234' + } + } + ]; + + it('sends bid request to URL via GET', () => { + const request = spec.buildRequests(bidRequests); + + expect(request.url).to.equal(`${URL}?uids=1234`); + expect(request.method).to.equal('GET'); + }); + }); + + describe('interpretResponse', () => { + it('should handle empty response', () => { + let bids = spec.interpretResponse( + {}, + { + bidsMap: {} + } + ); + + expect(bids).to.be.lengthOf(0); + }); + + it('should handle no seatbid returned', () => { + let response = {}; + + let bids = spec.interpretResponse( + { body: response }, + { + bidsMap: {} + } + ); + + expect(bids).to.be.lengthOf(0); + }); + + it('should handle empty seatbid returned', () => { + let response = { seatbid: [] }; + + let bids = spec.interpretResponse( + { body: response }, + { + bidsMap: {} + } + ); + + expect(bids).to.be.lengthOf(0); + }); + + it('should handle seatbid returned bids', () => { + const bidsMap = { 1: [{ bidId: 11 }] }; + const bid = { + price: 0.2, + auid: 1, + h: 250, + w: 300, + adm: 'content' + }; + const response = { + seatbid: [ + { + seat: 'foo', + bid: [bid] + } + ] + }; + + let bids = spec.interpretResponse({ body: response }, { bidsMap }); + + expect(bids).to.be.lengthOf(1); + + expect(bids[0].cpm).to.equal(bid.price); + expect(bids[0].width).to.equal(bid.w); + expect(bids[0].height).to.equal(bid.h); + expect(bids[0].ad).to.equal(bid.adm); + expect(bids[0].bidderCode).to.equal(spec.code); + }); + }); +}); From 5c37e60363790b690ca94d16aed5e7a4083c0976 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Mon, 5 Feb 2018 19:08:01 -0500 Subject: [PATCH 0089/1594] Fix getUserSync test for ios (#2100) --- test/spec/modules/yieldmoBidAdapter_spec.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index a91c3dd487a..8e4ac81c64f 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -145,8 +145,18 @@ describe('YieldmoAdapter', () => { }; it('should return a tracker with type and url as parameters', () => { - // not ios, so tracker will fail - expect(spec.getUserSync(options)).to.deep.equal([]); + if (/iPhone|iPad|iPod/i.test(window.navigator.userAgent)) { + expect(spec.getUserSync(options)).to.deep.equal([{ + type: 'iframe', + url: SYNC_ENDPOINT + utils.getOrigin() + }]); + + options.iframeEnabled = false; + expect(spec.getUserSync(options)).to.deep.equal([]); + } else { + // not ios, so tracker will fail + expect(spec.getUserSync(options)).to.deep.equal([]); + } }); }); }); From 68b7d8bf5fa3fddd7979e9993b71681af7168552 Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 6 Feb 2018 13:08:37 -0500 Subject: [PATCH 0090/1594] PR / Issue Review process update (#2093) * PR / Issue Review process update * Update pr_review.md * Capitalize filename --- pr_review.md => PR_REVIEW.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) rename pr_review.md => PR_REVIEW.md (52%) diff --git a/pr_review.md b/PR_REVIEW.md similarity index 52% rename from pr_review.md rename to PR_REVIEW.md index 1d8cf0c360c..80d11c35769 100644 --- a/pr_review.md +++ b/PR_REVIEW.md @@ -1,5 +1,9 @@ ## Summary -We take PR review seriously. Please read https://medium.com/@mrjoelkemp/giving-better-code-reviews-16109e0fdd36#.xa8lc4i23 to understand how a PR review should be conducted. Be rational and strict in your review, make sure you understand exactly what the submitter's intent is. Overall 1 person should take ownership of a particular PR. When they are satisfied it's in good condition to merge, they should request 1 additional team member to review as a sanity check. Only when the PR has 2 `LGTM` from the core team should it be merged. +We take PR review seriously. Please read https://medium.com/@mrjoelkemp/giving-better-code-reviews-16109e0fdd36#.xa8lc4i23 to understand how a PR review should be conducted. Be rational and strict in your review, make sure you understand exactly what the submitter's intent is. Anyone in the community can review a PR, but a Prebid Org member is also required. A Prebid Org member should take ownership of a PR and do the initial review. + +If the PR is for a standard bid adapter or a standard analytics adapter, just the one review from a core member is sufficient. The reviewer will check against [required conventions](http://prebid.org/dev-docs/bidder-adaptor.html#required-adapter-conventions) and may merge the PR after approving and confirming that the documentation PR against prebid.org is open and linked to the issue. + +For modules and core platform updates, the initial reviewer should request an additional team member to review as a sanity check. Merge should only happen when the PR has 2 `LGTM` from the core team and a documentation PR if required. ### General PR review Process - Checkout the branch (these instructions are available on the github PR page as well). @@ -13,7 +17,7 @@ We take PR review seriously. Please read https://medium.com/@mrjoelkemp/giving-b - If all above is good, add a `LGTM` comment and request 1 additional core member to review. - Once there is 2 `LGTM` on the PR, merge to master - Ask the submitter to add a PR for documentation if applicable. -- Add a line into the `draft release` notes for this submission. If no draft release is available, create one using this template https://gist.github.com/mkendall07/c3af6f4691bed8a46738b3675cb5a479 +- Add a line into the `draft release` notes for this submission. If no draft release is available, create one using [this template]( https://gist.github.com/mkendall07/c3af6f4691bed8a46738b3675cb5a479) ### New Adapter or updates to adapter process - Follow steps above for general review process. In addition, please verify the following: @@ -23,3 +27,20 @@ We take PR review seriously. Please read https://medium.com/@mrjoelkemp/giving-b - Verify that code re-use is being done properly and that changes introduced by a bidder don't impact other bidders. - If the adapter being submitted is an alias type, check with the bidder contact that is being aliased to make sure it's allowed. - If the adapter is triggering any user syncs make sure they are using the user sync module in the Prebid.js core. +- Requests to the bidder should support HTTPS +- Responses from the bidder should be compressed (such as gzip, compress, deflate) +- Bid responses may not use JSONP: All requests must be AJAX with JSON responses +- All user-sync (aka pixel) activity must be registered via the provided functions +- Adapters may not use the $$PREBID_GLOBAL$$ variable +- All adapters must support the creation of multiple concurrent instances. This means, for example, that adapters cannot rely on mutable global variables. + +## Ticket Coordinator + +Each week, Prebid Org assigns one person to keep an eye on incoming issues and PRs. That person should: +- Review issues and PRs at least once per weekday for new items. +- For PRs: assign PRs to individuals on the PR review list. Try to be equitable -- not all PRs are created equally. Use the "Assigned" field and add the "Needs Review" label. +- For Issues: try to address questions and troubleshooting requests on your own, assigning them to others as needed. +- Issues that are questions or troubleshooting requests may be closed if the originator doesn't respond within a week to requests for confirmation or details. +- Issues that are bug reports should be left open and assigned to someone in PR rotation to confirm or deny the bug status. +- It's polite to check with others before assigning them large tasks. +- If possible, check in on older items and see if they can be unstuck. From d48d7dd2aef822a67b73deab651c241e5f20f3cf Mon Sep 17 00:00:00 2001 From: Nick Narbone Date: Tue, 6 Feb 2018 13:26:33 -0500 Subject: [PATCH 0091/1594] Add hfa and pv parameter to request payload (#2109) --- modules/sonobiBidAdapter.js | 6 ++++++ test/spec/modules/sonobiBidAdapter_spec.js | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 0211f3ad0b8..e453d84d586 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -4,6 +4,7 @@ import * as utils from '../src/utils'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; +const PAGEVIEW_ID = utils.generateUUID(); export const spec = { code: BIDDER_CODE, @@ -43,8 +44,13 @@ export const spec = { 'key_maker': JSON.stringify(Object.assign({}, ...bids)), 'ref': getTopWindowLocation().host, 's': utils.generateUUID(), + 'pv': PAGEVIEW_ID, }; + if (validBidRequests[0].params.hfa) { + payload.hfa = validBidRequests[0].params.hfa; + } + return { method: 'GET', url: STR_ENDPOINT, diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 525a1bde7cd..6a44c817d0b 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -130,11 +130,25 @@ describe('SonobiBidAdapter', () => { it('should return a properly formatted request', () => { const bidRequests = spec.buildRequests(bidRequest) + const bidRequestsPageViewID = spec.buildRequests(bidRequest) expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') expect(bidRequests.method).to.equal('GET') expect(bidRequests.data.key_maker).to.deep.equal(JSON.stringify(keyMakerData)) expect(bidRequests.data.ref).not.to.be.empty expect(bidRequests.data.s).not.to.be.empty + expect(bidRequests.data.pv).to.equal(bidRequestsPageViewID.data.pv) + expect(bidRequests.data.hfa).to.not.exist + }) + + it('should return a properly formatted request with hfa', () => { + bidRequest[0].params.hfa = 'hfakey' + bidRequest[1].params.hfa = 'hfakey' + const bidRequests = spec.buildRequests(bidRequest) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.ref).not.to.be.empty + expect(bidRequests.data.s).not.to.be.empty + expect(bidRequests.data.hfa).to.equal('hfakey') }) }) From 16c9403a87f05bb64a0276de8a40cb74287d2f8a Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Tue, 6 Feb 2018 13:40:03 -0500 Subject: [PATCH 0092/1594] Serverbid Bid Adapter: getUserSyncs and new adsizes (#2106) * serverbid sync wip * Serverbid Bid Adapter: enable getUserSyncs, new ad sizes --- modules/serverbidBidAdapter.js | 26 ++++++++++++++++++- test/spec/modules/serverbidBidAdapter_spec.js | 4 +-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/modules/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index 2b1de9a9a89..24bb5aa6255 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -24,6 +24,9 @@ const CONFIG = { } }; +let siteId = 0; +let bidder = 'serverbid'; + export const spec = { code: BIDDER_CODE, aliases: ['connectad', 'onefiftytwo', 'insticator', 'adsparc', 'automatad'], @@ -62,6 +65,10 @@ export const spec = { let ENDPOINT_URL; + // These variables are used in creating the user sync URL. + siteId = validBidRequests[0].params.siteId; + bidder = validBidRequests[0].params.bidder; + const data = Object.assign({ placements: [], time: Date.now(), @@ -140,7 +147,21 @@ export const spec = { }, getUserSyncs: function(syncOptions) { - return []; + if (syncOptions.iframeEnabled) { + if (bidder === 'connectad') { + return [{ + type: 'iframe', + url: '//cdn.connectad.io/connectmyusers.php' + }]; + } else { + return [{ + type: 'iframe', + url: '//s.zkcdn.net/ss/' + siteId + '.html' + }]; + } + } else { + utils.logWarn(bidder + ': Please enable iframe based user syncing.'); + } } }; @@ -185,6 +206,9 @@ sizeMap[429] = '486x60'; sizeMap[374] = '700x500'; sizeMap[934] = '300x1050'; sizeMap[1578] = '320x100'; +sizeMap[331] = '320x250'; +sizeMap[3301] = '320x267'; +sizeMap[2730] = '728x250'; function getSize(sizes) { const result = []; diff --git a/test/spec/modules/serverbidBidAdapter_spec.js b/test/spec/modules/serverbidBidAdapter_spec.js index fb31f925c6e..d3dc64ae6df 100644 --- a/test/spec/modules/serverbidBidAdapter_spec.js +++ b/test/spec/modules/serverbidBidAdapter_spec.js @@ -245,10 +245,10 @@ describe('Serverbid BidAdapter', () => { expect(opts).to.be.empty; }); - it('should always return empty array', () => { + it('should return a sync url if iframe syncs are enabled', () => { let opts = spec.getUserSyncs(syncOptions); - expect(opts).to.be.empty; + expect(opts.length).to.equal(1); }); }); }); From 8608201d49d729be9f55bffca70fde74ac36e36e Mon Sep 17 00:00:00 2001 From: Pupis Date: Tue, 6 Feb 2018 20:44:13 +0200 Subject: [PATCH 0093/1594] Update adform adapter request (#2107) * bid response adId same as bidId * test * update adform bid adapter * update unit tests * Added adform adapter description file * updated tests * Another tests update * Add auctionId * Update adapter for auctionId * add auctionId to adformBidAdapter * Final updates to fit 1.0 version * update docs and integration example * Do not mutate original validBidRequests * use atob and btoa instead of custom made module * Renaming one query string parameter * XDomainRequest.send exception fix (#1942) * Added YIELDONE Bid Adapter for Prebid.js 1.0 (#1900) * Added YIELDONE Bid Adapter for Prebid.js 1.0 * Update yieldoneBidAdapter.md change placementId to 44082 * Changed to get size from bid.sizes * fix sizes array * Add user-facing docs reminder to PR template (#1956) * allow non-mappable sizes to be passed and used in rubicon adapter (#1893) * Typo correction of YIELDONE md file (#1954) * Added YIELDONE Bid Adapter for Prebid.js 1.0 * Update yieldoneBidAdapter.md change placementId to 44082 * Changed to get size from bid.sizes * fix sizes array * Fix a typo * Serverbid bid adapter: update alias config (#1963) * use auctionId instead of requestId (#1968) * Add freewheel ssp bidder adapter for prebid 1.0 (#1793) * add stickyadsTV bidder adapter * init unit test file * ad some unit tests * fix unit test on ad format with parameters * add some unit tests * add unit tests on getBid method * add some test cases in unit tests * minor fix on component id tag. * remove adapters-sticky.json test file * use top most accessible window instead of window.top * Pass in the bid request in the createBid call. * use top most accessible window instead of window.top * add unit tests * update unit tests * fix unit test. * fix CI build * add alias freewheel-ssp * update unit tests on bidderCode value * fix component id values and add unit tests * allws to use any outstream format. * fix ASLoader on futur outstream format versions * minor: fix code format. * update unit tests * minor fix code format * minor: add missing new line at eof * replace StickyAdsTVAdapter by freewheel ssp bd adapter (for prebid 1.0) * remove old stickyadstv unittest spec. * fix server response parsing if sent as object with 'body' field * use the vastXml field for video mediatype * add user sync pixel in freewheel ssp adapter * remove all console log calls (replaced using util helper) * remove useless bidderCode (automatically added by the bidderFactory) * Return the SYNC pixel to be added in the page by Prebid.js * remove instance level properties to enable concurrent bids with the same adapter instance. * fix the request apss through and corresponding unit tests * fix 'freeheelssp' typo * + fixed endpoint request data property names - width to w and height to h (#1955) + updated unit test for the adapter to comply with the property name changes * Added iQM Bid Adapter for Prebid.js 1.0 (#1880) * Added iQM Bid Adapter for Prebid.js 1.0 * Modified URL from http to https * Removed geo function which was fetching user location. * Remove stray console.log (#1975) * Remove duplicate request id and fix empty response from getHighesCpmBids, getAdserverTargeting (#1970) * Removed requestId and added auctionId * Updated module fixtures to use auctionId and not requestId * remove request id from external bid object and fix bug for empty result in public api * use auctionId instead of requestId * fixed lint errors * [Add BidAdapter] rxrtb adapter for Perbid.js 1.0 (#1950) * Add: rxrtb prebidAdapter * Update: params for test * Update: code format * Update: code format * Update: code format * ServerBid Server BidAdapter (#1819) * ServerBid Server BidAdapter Allow S2S configuration with ServerBid. * Updates to meet 1.0 callBids/config changes. * Fix linting issues. * added hb_source to default keys (#1969) * added hb_source * dropped function to add hb_source since it is now default key * fixed lint error * Prebid 1.1.0 Release * Increment pre version * S2s defaults fix in serverbidServerBidAdapter (#1986) * removed s2s defaults * start timestamp was missing on s2s requests * remove hardcoded localhost port for tests (#1988) * Fixes unit tests in browsers other than chrome (#1987) * Fixes unit tests in browsers other than chrome * fixed lint errors * Prebid 1.1.1 Release * Add note about docs needed before merge (#1959) * Add note about docs needed before merge * Update pr_review.md * Update pr_review.md * Update pr_review.md * Adding optional width and height to display parameters (#1998) * adding optional size * no tabs * TrustX adapter update (#1979) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Serverbid Bid Adapter: Add new ad sizes (#1983) * Added dynamic ttl property for One Display and One Mobile. (#2004) * pin gulp-connect at non-broken version (#2008) * pin gulp-connect at non-broken version * updated yarn.lock to specify pinned gulp-connect * Gjirafa Bidder Adapter (#1944) * Added Gjirafa adapter * Add gjirafa adapter unit test * adapter update * New line * Requested changes * change hello_world.html to one bid * change hello_world.html to one bid * Dropping changes in gitignore and hello_world example * hello_world changes * Drop hello_world and gitignore * multiformat size validation checks (#1964) * initial commit for multiformat size validation checks * adding unit tests and changes to checkBidRequestSizes function * updates to appnexusBidAdapter * Upgrade Admixer adapter for Prebid 1.0 (#1755) * Migrating to Prebid 1.0 * Migrating to Prebid 1.0 * Fix spec * Add NasmediaAdmixer adapter for Perbid.js 1.0 (#1937) * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * Updated stid and unit tests --- modules/adformBidAdapter.js | 3 +-- test/spec/modules/adformBidAdapter_spec.js | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index 6dba55f88a7..4ff37566da9 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -5,7 +5,6 @@ import {registerBidder} from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'adform'; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [], isBidRequestValid: function (bid) { return !!(bid.params.mid); }, @@ -35,7 +34,7 @@ export const spec = { request.unshift('//' + globalParams[0][1] + '/adx/?rp=4'); - request.push('stid=' + validBidRequests[0].requestId); + request.push('stid=' + validBidRequests[0].auctionId); for (i = 1, l = globalParams.length; i < l; i++) { _key = globalParams[i][0]; diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index 72f625d08c6..357e6e67f4d 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -22,7 +22,7 @@ describe('Adform adapter', () => { adxDomain: 'adx.adform.net' }; assert.isFalse(spec.isBidRequestValid(bid)); - }) + }); }); describe('buildRequests', () => { @@ -147,6 +147,7 @@ describe('Adform adapter', () => { bids = [ { adUnitCode: placementCode[0], + auctionId: '7aefb970-2045', bidId: '2a0cf4e', bidder: 'adform', bidderRequestId: '1ab8d9', @@ -154,29 +155,28 @@ describe('Adform adapter', () => { adxDomain: 'newDomain', tid: 45, placementCode: placementCode[0], - requestId: '7aefb970-2045', sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], transactionId: '5f33781f-9552-4ca1' }, { adUnitCode: placementCode[1], + auctionId: '7aefb970-2045', bidId: '2a0cf5b', bidder: 'adform', bidderRequestId: '1ab8d9', params: params[1], placementCode: placementCode[1], - requestId: '7aefb970-2045', sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], transactionId: '5f33781f-9552-4iuy' }, { adUnitCode: placementCode[2], + auctionId: '7aefb970-2045', bidId: '2a0cf6n', bidder: 'adform', bidderRequestId: '1ab8d9', params: params[2], placementCode: placementCode[2], - requestId: '7aefb970-2045', sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], transactionId: '5f33781f-9552-7ev3' } From 4c71e65d58367ac67899562d05edd927427179a7 Mon Sep 17 00:00:00 2001 From: Kit Westneat Date: Tue, 6 Feb 2018 14:04:32 -0500 Subject: [PATCH 0094/1594] Port calling order fix to 1.x (#2067) * * bidmanager: pass closure variables explicitly to helper functions in addBidResponse * bidmanager: move addBidResponse helper functions out of closures * WIP: call doCallbacks from addBidToAuction In order to ensure the calling order is correct, call doCallbacks from within addBidToAuction. XXX: This breaks the test that's removed in this patch. The reason it breaks is that the TIMEOUT event is not emitted if all bids have been returned before the timeout handler is called. Previously the bid manager was rejecting the bid if the bid triggered the timeout handler, which doesn't really make much sense. The test SHOULD work if there are two bidders, as the first response should trigger the timeout. I had a hard time adding a second bidder to the test code, so I was hoping to get some help. --- src/auction.js | 79 ++++++++++++++++---------------- test/spec/auctionmanager_spec.js | 52 +-------------------- 2 files changed, 41 insertions(+), 90 deletions(-) diff --git a/src/auction.js b/src/auction.js index a9701230744..0af6458ac09 100644 --- a/src/auction.js +++ b/src/auction.js @@ -209,6 +209,44 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } +function doCallbacksIfTimedout(auctionInstance, bidResponse) { + if (bidResponse.timeToRespond > auctionInstance.getTimeout() + config.getConfig('timeoutBuffer')) { + auctionInstance.executeCallback(true); + } +} + +// Add a bid to the auction. +function addBidToAuction(auctionInstance, bidResponse) { + events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bidResponse); + auctionInstance.addBidReceived(bidResponse); + + doCallbacksIfTimedout(auctionInstance, bidResponse); +} + +// Video bids may fail if the cache is down, or there's trouble on the network. +function tryAddVideoBid(auctionInstance, bidResponse, bidRequest, vastUrl) { + if (config.getConfig('cache.url')) { + store([bidResponse], function(error, cacheIds) { + if (error) { + utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); + + doCallbacksIfTimedout(auctionInstance, bidResponse); + } else { + bidResponse.videoCacheKey = cacheIds[0].uuid; + if (!vastUrl) { + bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); + } + // only set this prop after the bid has been cached to avoid early ending auction early in bidsBackAll + bidRequest.doneCbCallCount += 1; + addBidToAuction(auctionInstance, bidResponse); + auctionInstance.bidsBackAll(); + } + }); + } else { + addBidToAuction(auctionInstance, bidResponse); + } +} + export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid) { let auctionInstance = this; let bidRequests = auctionInstance.getBidRequests(); @@ -218,46 +256,9 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}); if (bidResponse.mediaType === 'video') { - tryAddVideoBid(bidResponse); + tryAddVideoBid(auctionInstance, bidResponse, bidRequest, bid.vastUrl); } else { - doCallbacksIfNeeded(); - addBidToAuction(bidResponse); - } - - function doCallbacksIfNeeded() { - if (bidResponse.timeToRespond > auctionInstance.getTimeout() + config.getConfig('timeoutBuffer')) { - auctionInstance.executeCallback(true); - } - } - - // Add a bid to the auction. - function addBidToAuction() { - events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bidResponse); - auctionInstance.addBidReceived(bidResponse); - } - - // Video bids may fail if the cache is down, or there's trouble on the network. - function tryAddVideoBid(bidResponse) { - if (config.getConfig('cache.url')) { - store([bidResponse], function(error, cacheIds) { - if (error) { - utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); - } else { - bidResponse.videoCacheKey = cacheIds[0].uuid; - if (!bid.vastUrl) { - bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); - } - // only set this prop after the bid has been cached to avoid early ending auction early in bidsBackAll - bidRequest.doneCbCallCount += 1; - addBidToAuction(bidResponse); - auctionInstance.bidsBackAll(); - } - doCallbacksIfNeeded(); - }); - } else { - addBidToAuction(bidResponse); - doCallbacksIfNeeded(); - } + addBidToAuction(auctionInstance, bidResponse); } }, 'addBidResponse'); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index a1248030c51..c73679c5b8c 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -466,6 +466,7 @@ describe('auctionmanager.js', function () { let auction; let ajaxStub; const BIDDER_CODE = 'sampleBidder'; + const BIDDER_CODE1 = 'sampleBidder1'; let makeRequestsStub; let bids = [{ 'ad': 'creative', @@ -656,57 +657,6 @@ describe('auctionmanager.js', function () { assert.equal(addedBid.renderer.url, 'renderer.js'); }); }); - - describe('with auction timeout 20', () => { - let auction; - let adUnits; - let adUnitCodes; - let createAuctionStub; - let spec; - let getBidderRequestStub; - let eventsEmitSpy; - - beforeEach(() => { - adUnits = [{ - code: 'adUnit-code', - bids: [ - {bidder: BIDDER_CODE, params: {placementId: 'id'}}, - ] - }]; - adUnitCodes = ['adUnit-code']; - auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 20}); - createAuctionStub = sinon.stub(auctionModule, 'newAuction'); - createAuctionStub.returns(auction); - getBidderRequestStub = sinon.stub(utils, 'getBidderRequest'); - - let newBidRequest = Object.assign({}, bidRequests[0], {'start': 1000}); - getBidderRequestStub.returns(newBidRequest); - - spec = { - code: BIDDER_CODE, - isBidRequestValid: sinon.stub(), - buildRequests: sinon.stub(), - interpretResponse: sinon.stub(), - getUserSyncs: sinon.stub() - }; - eventsEmitSpy = sinon.spy(events, 'emit'); - }); - - afterEach(() => { - auctionModule.newAuction.restore(); - utils.getBidderRequest.restore(); - events.emit.restore(); - }); - - it('should emit BID_TIMEOUT for timed out bids', () => { - registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); - auction.callBids(); - assert.ok(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BID_TIMEOUT), 'emitted events BID_TIMEOUT'); - }); - }); }); describe('addBidResponse', () => { From aee2ef025a64111f4c3da8f6b508437e5b1c6a1e Mon Sep 17 00:00:00 2001 From: Aparna Rao-Hegde Date: Tue, 6 Feb 2018 14:08:25 -0500 Subject: [PATCH 0095/1594] 33across Bid Adapter: Bugfix + Refactor (#2024) * Adding 33across adapter * Updated per code review from Prebid. See https://github.com/prebid/Prebid.js/pull/1805#pullrequestreview-75218582 * Added support for test bid and crid. * Removed ability to set test url via params * Incorporated changes requested in https://github.com/prebid/Prebid.js/issues/1855 to fix usage of deprecated method --- modules/33acrossBidAdapter.js | 23 ++- test/spec/modules/33acrossBidAdapter_spec.js | 192 +++++++++++-------- 2 files changed, 122 insertions(+), 93 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 8e73d5c87b4..5a7fa5e2613 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -16,7 +16,7 @@ function _createBidResponse(response) { 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].ext.rp.advid, + creativeId: response.seatbid[0].bid[0].crid, currency: response.cur, netRevenue: true } @@ -27,6 +27,9 @@ function _createServerRequest(bidRequest) { const ttxRequest = {}; const params = bidRequest.params; + /* + * Infer data for the request payload + */ ttxRequest.imp = []; ttxRequest.imp[0] = { banner: { @@ -38,22 +41,27 @@ function _createServerRequest(bidRequest) { } } } - ttxRequest.site = { id: params.siteId }; - // 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; + // Finally, set the openRTB 'test' param if this is to be a test bid + if (params.test === 1) { + ttxRequest.test = 1; + } + /* + * Now construt the full server request + */ const options = { contentType: 'application/json', withCredentials: false }; - // Allow the ability to configure the HB endpoint for testing purposes. const ttxSettings = config.getConfig('ttxSettings'); const url = (ttxSettings && ttxSettings.url) || END_POINT; + // Return the server request return { 'method': 'POST', 'url': url, @@ -93,12 +101,7 @@ function isBidRequestValid(bid) { return false; } - if ((typeof bid.params.site === 'undefined' || typeof bid.params.site.id === 'undefined') && - (typeof bid.params.siteId === 'undefined')) { - return false; - } - - if (typeof bid.params.productId === 'undefined') { + if (typeof bid.params.siteId === 'undefined' || typeof bid.params.productId === 'undefined') { return false; } diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 0b2d65e7db9..9a322821b13 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -2,7 +2,6 @@ const { userSync } = require('../../../src/userSync'); const { config } = require('../../../src/config'); const { expect } = require('chai'); - const { isBidRequestValid, buildRequests, @@ -44,78 +43,71 @@ describe('33acrossBidAdapter:', function () { }); describe('isBidRequestValid:', function () { - context('valid bid request:', function () { - it('returns true when bidder, params.siteId, params.productId are set', function() { - const validBid = { - bidder: BIDDER_CODE, - params: { - siteId: SITE_ID, - productId: PRODUCT_ID - } + it('returns true when valid bid request is sent', function() { + const validBid = { + bidder: BIDDER_CODE, + params: { + siteId: SITE_ID, + productId: PRODUCT_ID } + } - expect(isBidRequestValid(validBid)).to.be.true; - }) + expect(isBidRequestValid(validBid)).to.be.true; }); - context('valid test bid request:', function () { - it('returns true when bidder, params.site.id, params.productId are set', function() { - const validBid = { - bidder: BIDDER_CODE, - params: { - site: { - id: SITE_ID - }, - productId: PRODUCT_ID - } + it('returns true when valid test bid request is sent', function() { + const validBid = { + bidder: BIDDER_CODE, + params: { + siteId: SITE_ID, + productId: PRODUCT_ID, + test: 1 } + } - expect(isBidRequestValid(validBid)).to.be.true; - }); + expect(isBidRequestValid(validBid)).to.be.true; }); - context('invalid bid request:', function () { - it('returns false when bidder not set to "33across"', function () { - const invalidBid = { - bidder: 'foo', - params: { - siteId: SITE_ID, - productId: PRODUCT_ID - } + it('returns false when bidder not set to "33across"', function () { + const invalidBid = { + bidder: 'foo', + params: { + siteId: SITE_ID, + productId: PRODUCT_ID } + } - expect(isBidRequestValid(invalidBid)).to.be.false; - }); + expect(isBidRequestValid(invalidBid)).to.be.false; + }); - it('returns false when params not set', function() { - const invalidBid = { - bidder: 'foo' - } + it('returns false when params not set', function() { + const invalidBid = { + bidder: 'foo' + } - expect(isBidRequestValid(invalidBid)).to.be.false; - }); + expect(isBidRequestValid(invalidBid)).to.be.false; + }); - it('returns false when params.siteId or params.site.id not set', function() { - const invalidBid = { - bidder: 'foo', - params: { - productId: PRODUCT_ID - } + it('returns false when site ID is not set in params', function() { + const invalidBid = { + bidder: 'foo', + params: { + productId: PRODUCT_ID } + } - expect(isBidRequestValid(invalidBid)).to.be.false; - }); + expect(isBidRequestValid(invalidBid)).to.be.false; + }); - it('returns false when params.productId not set', function() { - const invalidBid = { - bidder: 'foo', - params: { - siteId: SITE_ID - } + it('returns false when product ID not set in params', function() { + const invalidBid = { + bidder: 'foo', + params: { + siteId: SITE_ID } + } - expect(isBidRequestValid(invalidBid)).to.be.false; - }); + expect(isBidRequestValid(invalidBid)).to.be.false; }); }); @@ -148,27 +140,76 @@ describe('33acrossBidAdapter:', function () { }, id: 'b1' }; + const serverRequest = { + 'method': 'POST', + 'url': END_POINT, + 'data': JSON.stringify(ttxRequest), + 'options': { + 'contentType': 'application/json', + 'withCredentials': false + } + } + const builtServerRequests = buildRequests(this.bidRequests); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); + expect(builtServerRequests.length).to.equal(1); + }); + + it('returns corresponding test server requests for each valid bidRequest', function() { + this.sandbox.stub(config, 'getConfig', () => { + return { + 'url': 'https://foo.com/hb/' + } + }); + + const ttxRequest = { + imp: [ { + banner: { + format: [ + { + w: 300, + h: 250, + ext: { } + }, + { + w: 728, + h: 90, + ext: { } + } + ] + }, + ext: { + ttx: { + prod: PRODUCT_ID + } + } + } ], + site: { + id: SITE_ID + }, + id: 'b1' + }; const serverRequest = { method: 'POST', - url: END_POINT, + url: 'https://foo.com/hb/', data: JSON.stringify(ttxRequest), options: { contentType: 'application/json', withCredentials: false } - } + }; + const builtServerRequests = buildRequests(this.bidRequests); expect(builtServerRequests).to.deep.equal([ serverRequest ]); expect(builtServerRequests.length).to.equal(1); }); - it('returns corresponding test server requests for each valid bidRequest', function() { + it('returns corresponding test server requests for each valid test bidRequest', function() { this.sandbox.stub(config, 'getConfig', () => { return { 'url': 'https://foo.com/hb/' } }); - + this.bidRequests[0].params.test = 1; const ttxRequest = { imp: [ { banner: { @@ -176,12 +217,12 @@ describe('33acrossBidAdapter:', function () { { w: 300, h: 250, - ext: {} + ext: { } }, { w: 728, h: 90, - ext: {} + ext: { } } ] }, @@ -194,7 +235,8 @@ describe('33acrossBidAdapter:', function () { site: { id: SITE_ID }, - id: 'b1' + id: 'b1', + test: 1 }; const serverRequest = { method: 'POST', @@ -268,11 +310,7 @@ describe('33acrossBidAdapter:', function () { bid: [ { id: '1', adm: '

I am an ad

', - ext: { - rp: { - advid: 1 - } - }, + crid: 1, h: 250, w: 300, price: 0.0938 @@ -322,11 +360,7 @@ describe('33acrossBidAdapter:', function () { bid: [ { id: '1', adm: '

I am an ad

', - ext: { - rp: { - advid: 1 - } - }, + crid: 1, h: 250, w: 300, price: 0.0940 @@ -334,11 +368,7 @@ describe('33acrossBidAdapter:', function () { { id: '2', adm: '

I am an ad

', - ext: { - rp: { - advid: 2 - } - }, + crid: 2, h: 250, w: 300, price: 0.0938 @@ -349,11 +379,7 @@ describe('33acrossBidAdapter:', function () { bid: [ { id: '3', adm: '

I am an ad

', - ext: { - rp: { - advid: 3 - } - }, + crid: 3, h: 250, w: 300, price: 0.0938 @@ -373,7 +399,7 @@ describe('33acrossBidAdapter:', function () { creativeId: 1, currency: 'USD', netRevenue: true - } + }; expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([ bidResponse ]); }); From 620ca80cf27ccc2e866ffe25d7b777228d63d6cd Mon Sep 17 00:00:00 2001 From: nissSK Date: Tue, 6 Feb 2018 21:25:48 +0200 Subject: [PATCH 0096/1594] removing userSync (#2032) * removing userSync * ping to travis --- modules/sekindoUMBidAdapter.js | 8 -------- modules/sekindoUMBidAdapter.md | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/modules/sekindoUMBidAdapter.js b/modules/sekindoUMBidAdapter.js index 09b94be967b..e87f3194ff0 100644 --- a/modules/sekindoUMBidAdapter.js +++ b/modules/sekindoUMBidAdapter.js @@ -104,14 +104,6 @@ export const spec = { bidResponses.push(bidResponse); return bidResponses; - }, - getUserSyncs: function(syncOptions) { - if (syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: 'ADAPTER_SYNC_URL' - }]; - } } } registerBidder(spec); diff --git a/modules/sekindoUMBidAdapter.md b/modules/sekindoUMBidAdapter.md index 24c2aaec6db..05c0227976d 100755 --- a/modules/sekindoUMBidAdapter.md +++ b/modules/sekindoUMBidAdapter.md @@ -19,7 +19,7 @@ Banner, Outstream and Native formats are supported. bidder: 'sekindoUM', params: { spaceId: 14071 - width:300, //optional + width:300, ///optional weight:250, //optional } }] From 85e9451f1c1332804c168c495101d63918c7e13c Mon Sep 17 00:00:00 2001 From: Denis Logachev Date: Tue, 6 Feb 2018 21:27:14 +0200 Subject: [PATCH 0097/1594] adkernel adapter additional bid parameters (#2105) --- modules/adkernelBidAdapter.js | 52 ++++++++++---------- modules/adkernelBidAdapter.md | 1 - src/utils.js | 7 +++ test/spec/modules/adkernelBidAdapter_spec.js | 41 ++++++++------- 4 files changed, 55 insertions(+), 46 deletions(-) diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index c3f34274692..14cd7f70262 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -7,7 +7,7 @@ import includes from 'core-js/library/fn/array/includes'; const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', 'pos', 'api', 'ext']; -const VERSION = '1.0'; +const VERSION = '1.1'; /** * Adapter for requesting bids from AdKernel white-label display platform @@ -76,8 +76,8 @@ export const spec = { }; if ('banner' in imp) { prBid.mediaType = BANNER; - prBid.width = imp.banner.w; - prBid.height = imp.banner.h; + prBid.width = rtbBid.w; + prBid.height = rtbBid.h; prBid.ad = formatAdMarkup(rtbBid); } if ('video' in imp) { @@ -96,12 +96,7 @@ export const spec = { return serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.adk_usersync) .map(rsp => rsp.body.ext.adk_usersync) .reduce((a, b) => a.concat(b), []) - .map(sync_url => { - return { - type: 'iframe', - url: sync_url - } - }); + .map(sync_url => ({type: 'iframe', url: sync_url})); } }; @@ -111,21 +106,24 @@ registerBidder(spec); * Builds parameters object for single impression */ function buildImp(bid) { - const size = getAdUnitSize(bid); + const sizes = bid.sizes; const imp = { 'id': bid.bidId, 'tagid': bid.placementCode }; if (bid.mediaType === 'video') { - imp.video = {w: size[0], h: size[1]}; + imp.video = {w: sizes[0], h: sizes[1]}; if (bid.params.video) { Object.keys(bid.params.video) .filter(param => includes(VIDEO_TARGETING, param)) .forEach(param => imp.video[param] = bid.params.video[param]); } } else { - imp.banner = {w: size[0], h: size[1]}; + imp.banner = { + format: sizes.map(s => ({'w': s[0], 'h': s[1]})), + topframe: 0 + }; } if (utils.getTopWindowLocation().protocol === 'https:') { imp.secure = 1; @@ -133,34 +131,36 @@ function buildImp(bid) { return imp; } -/** - * Return ad unit single size - * @param bid adunit size definition - * @return {*} - */ -function getAdUnitSize(bid) { - if (bid.mediaType === 'video') { - return bid.sizes; - } - return bid.sizes[0]; -} - /** * Builds complete rtb request * @param imps collection of impressions * @param auctionId */ function buildRtbRequest(imps, auctionId) { - return { + let req = { 'id': auctionId, 'imp': imps, 'site': createSite(), 'at': 1, 'device': { 'ip': 'caller', - 'ua': 'caller' + 'ua': 'caller', + 'js': 1, + 'language': getLanguage() + }, + 'ext': { + 'adk_usersync': 1 } }; + if (utils.getDNT()) { + req.device.dnt = 1; + } + return req; +} + +function getLanguage() { + const language = navigator.language ? 'language' : 'userLanguage'; + return navigator[language].split('-')[0]; } /** diff --git a/modules/adkernelBidAdapter.md b/modules/adkernelBidAdapter.md index bc30e6cc8e5..902be481473 100644 --- a/modules/adkernelBidAdapter.md +++ b/modules/adkernelBidAdapter.md @@ -10,7 +10,6 @@ Maintainer: denis@adkernel.com Connects to AdKernel whitelabel platform. Banner and video formats are supported. -The AdKernel adapter doesn't support multiple sizes per ad-unit and will use the first one if multiple sizes are defined. # Test Parameters diff --git a/src/utils.js b/src/utils.js index 0957b4e6c8f..8735f918497 100644 --- a/src/utils.js +++ b/src/utils.js @@ -809,6 +809,13 @@ export function getOrigin() { } } +/** + * Returns Do Not Track state + */ +export function getDNT() { + return navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNotTrack === '1' || navigator.doNotTrack === 'yes'; +} + const compareCodeAndSlot = (slot, adUnitCode) => slot.getAdUnitPath() === adUnitCode || slot.getSlotElementId() === adUnitCode; /** diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index b958e96f656..717027ca4ee 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -8,7 +8,7 @@ describe('Adkernel adapter', () => { bidId: 'Bid_01', params: {zoneId: 1, host: 'rtb.adkernel.com'}, placementCode: 'ad-unit-1', - sizes: [[300, 250]] + sizes: [[300, 250], [300, 200]] }, bid2_zone2 = { bidder: 'adkernel', bidId: 'Bid_02', @@ -63,7 +63,9 @@ describe('Adkernel adapter', () => { crid: '100_001', price: 3.01, nurl: 'https://rtb.com/win?i=ZjKoPYSFI3Y_0', - adm: '' + adm: '', + w: 300, + h: 250 }] }], cur: 'USD', @@ -78,7 +80,9 @@ describe('Adkernel adapter', () => { impid: 'Bid_02', crid: '100_002', price: 1.31, - adm: '' + adm: '', + w: 300, + h: 250 }] }], cur: 'USD' @@ -125,21 +129,19 @@ describe('Adkernel adapter', () => { describe('banner request building', () => { let bidRequest; - let mock; - before(() => { - mock = sinon.stub(utils, 'getTopWindowLocation', () => { - return { - protocol: 'https:', - hostname: 'example.com', - host: 'example.com', - pathname: '/index.html', - href: 'https://example.com/index.html' - }; - }); + let wmock = sinon.stub(utils, 'getTopWindowLocation', () => ({ + protocol: 'https:', + hostname: 'example.com', + host: 'example.com', + pathname: '/index.html', + href: 'https://example.com/index.html' + })); + let dntmock = sinon.stub(utils, 'getDNT', () => true); let request = spec.buildRequests([bid1_zone1])[0]; bidRequest = JSON.parse(request.data.r); - mock.restore(); + wmock.restore(); + dntmock.restore(); }); it('should be a first-price auction', () => { @@ -150,9 +152,9 @@ describe('Adkernel adapter', () => { expect(bidRequest.imp[0]).to.have.property('banner'); }); - it('should have h/w', () => { - expect(bidRequest.imp[0].banner).to.have.property('w', 300); - expect(bidRequest.imp[0].banner).to.have.property('h', 250); + it('should have w/h', () => { + expect(bidRequest.imp[0].banner).to.have.property('format'); + expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); }); it('should respect secure connection', () => { @@ -172,7 +174,8 @@ describe('Adkernel adapter', () => { expect(bidRequest).to.have.property('device'); expect(bidRequest.device).to.have.property('ip', 'caller'); expect(bidRequest.device).to.have.property('ua', 'caller'); - }) + expect(bidRequest.device).to.have.property('dnt', 1); + }); }); describe('video request building', () => { From 3ca1693aa4b398943a8d6d6b1baf5b45ea507b18 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 6 Feb 2018 13:40:03 -0700 Subject: [PATCH 0098/1594] must explicitly list pre1api for it to be included in build (#2097) --- gulpfile.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index 92851bbc192..0fb4a7e1de0 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -71,12 +71,17 @@ function nodeBundle(modules) { }); } +// these modules must be explicitly listed in --modules to be included in the build, won't be part of "all" modules +var explicitModules = [ + 'pre1api' +]; + function bundle(dev, moduleArr) { var modules = moduleArr || helpers.getArgModules(), allModules = helpers.getModuleNames(modules); if(modules.length === 0) { - modules = allModules; + modules = allModules.filter(module => !explicitModules.includes(module)); } else { var diff = _.difference(modules, allModules); if(diff.length !== 0) { From 413abfbb24eb21b85dd061734def057dcc74a571 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 6 Feb 2018 16:34:52 -0500 Subject: [PATCH 0099/1594] Unit test fixes (#2111) --- modules/sonobiBidAdapter.js | 5 +- modules/xendizBidAdapter.js | 2 +- modules/yieldmoBidAdapter.js | 8 +- test/spec/modules/xendizBidAdapter_spec.js | 2 +- test/spec/utils_spec.js | 166 ++++++++++----------- 5 files changed, 93 insertions(+), 90 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index e453d84d586..fb5d9a7f56f 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -40,8 +40,11 @@ export const spec = { } }); + let data = {} + bids.forEach((bid) => { Object.assign(data, bid); }); + const payload = { - 'key_maker': JSON.stringify(Object.assign({}, ...bids)), + 'key_maker': JSON.stringify(data), 'ref': getTopWindowLocation().host, 's': utils.generateUUID(), 'pv': PAGEVIEW_ID, diff --git a/modules/xendizBidAdapter.js b/modules/xendizBidAdapter.js index d40d3ada229..0f1c385a67c 100644 --- a/modules/xendizBidAdapter.js +++ b/modules/xendizBidAdapter.js @@ -11,7 +11,7 @@ const buildURI = () => { } const getDevice = () => { - const lang = navigator.language; + const lang = navigator.language || ''; const width = window.screen.width; const height = window.screen.height; diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 1047224a3b7..ad2aff7dec8 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -40,9 +40,9 @@ export const spec = { w: localWindow.innerWidth, h: localWindow.innerHeight }; - for (var request of bidRequests) { + bidRequests.forEach((request) => { serverRequest.p.push(addPlacement(request)); - } + }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { method: 'GET', @@ -60,11 +60,11 @@ export const spec = { let bids = []; let data = serverResponse.body; if (data.length > 0) { - for (var response of data) { + data.forEach((response) => { if (response.cpm && response.cpm > 0) { bids.push(createNewBid(response)); } - } + }); } return bids; }, diff --git a/test/spec/modules/xendizBidAdapter_spec.js b/test/spec/modules/xendizBidAdapter_spec.js index 1b0ef9c8d4c..66b9dc62b88 100644 --- a/test/spec/modules/xendizBidAdapter_spec.js +++ b/test/spec/modules/xendizBidAdapter_spec.js @@ -78,7 +78,7 @@ describe('xendizBidAdapter', () => { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); expect(payload.device).to.deep.equal([ - navigator.language, + navigator.language || '', window.screen.width, window.screen.height ]); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 522d28b79ad..96d3888015e 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -525,89 +525,89 @@ describe('Utils', function () { }); }); - describe('cookie support', function () { - // store original cookie getter and setter so we can reset later - var origCookieSetter = document.__lookupSetter__('cookie'); - var origCookieGetter = document.__lookupGetter__('cookie'); - - // store original cookieEnabled getter and setter so we can reset later - var origCookieEnabledSetter = window.navigator.__lookupSetter__('cookieEnabled'); - var origCookieEnabledGetter = window.navigator.__lookupGetter__('cookieEnabled'); - - // Replace the document cookie set function with the output of a custom function for testing - let setCookie = (v) => v; - - beforeEach(() => { - // Redefine window.navigator.cookieEnabled such that you can set otherwise "read-only" values - Object.defineProperty(window.navigator, 'cookieEnabled', (function (_value) { - return { - get: function _get() { - return _value; - }, - set: function _set(v) { - _value = v; - }, - configurable: true - }; - })(window.navigator.cookieEnabled)); - - // Reset the setCookie cookie function before each test - setCookie = (v) => v; - // Redefine the document.cookie object such that you can purposefully have it output nothing as if it is disabled - Object.defineProperty(window.document, 'cookie', (function (_value) { - return { - get: function _get() { - return _value; - }, - set: function _set(v) { - _value = setCookie(v); - }, - configurable: true - }; - })(window.navigator.cookieEnabled)); - }); - - afterEach(() => { - // redefine window.navigator.cookieEnabled to original getter and setter - Object.defineProperty(window.navigator, 'cookieEnabled', { - get: origCookieEnabledGetter, - set: origCookieEnabledSetter, - configurable: true - }); - // redefine document.cookie to original getter and setter - Object.defineProperty(document, 'cookie', { - get: origCookieGetter, - set: origCookieSetter, - configurable: true - }); - }); - - it('should be detected', function() { - assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should be enabled by default'); - }); - - it('should be not available', function() { - setCookie = () => ''; - window.navigator.cookieEnabled = false; - window.document.cookie = ''; - assert.equal(utils.cookiesAreEnabled(), false, 'Cookies should be disabled'); - }); - - it('should be available', function() { - window.navigator.cookieEnabled = false; - window.document.cookie = 'key=value'; - assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should already be set'); - window.navigator.cookieEnabled = false; - window.document.cookie = ''; - assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should settable'); - setCookie = () => ''; - window.navigator.cookieEnabled = true; - window.document.cookie = ''; - assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should be on via on window.navigator'); - // Reset the setCookie - setCookie = (v) => v; - }); - }); + // describe('cookie support', function () { + // // store original cookie getter and setter so we can reset later + // var origCookieSetter = document.__lookupSetter__('cookie'); + // var origCookieGetter = document.__lookupGetter__('cookie'); + + // // store original cookieEnabled getter and setter so we can reset later + // var origCookieEnabledSetter = window.navigator.__lookupSetter__('cookieEnabled'); + // var origCookieEnabledGetter = window.navigator.__lookupGetter__('cookieEnabled'); + + // // Replace the document cookie set function with the output of a custom function for testing + // let setCookie = (v) => v; + + // beforeEach(() => { + // // Redefine window.navigator.cookieEnabled such that you can set otherwise "read-only" values + // Object.defineProperty(window.navigator, 'cookieEnabled', (function (_value) { + // return { + // get: function _get() { + // return _value; + // }, + // set: function _set(v) { + // _value = v; + // }, + // configurable: true + // }; + // })(window.navigator.cookieEnabled)); + + // // Reset the setCookie cookie function before each test + // setCookie = (v) => v; + // // Redefine the document.cookie object such that you can purposefully have it output nothing as if it is disabled + // Object.defineProperty(window.document, 'cookie', (function (_value) { + // return { + // get: function _get() { + // return _value; + // }, + // set: function _set(v) { + // _value = setCookie(v); + // }, + // configurable: true + // }; + // })(window.navigator.cookieEnabled)); + // }); + + // afterEach(() => { + // // redefine window.navigator.cookieEnabled to original getter and setter + // Object.defineProperty(window.navigator, 'cookieEnabled', { + // get: origCookieEnabledGetter, + // set: origCookieEnabledSetter, + // configurable: true + // }); + // // redefine document.cookie to original getter and setter + // Object.defineProperty(document, 'cookie', { + // get: origCookieGetter, + // set: origCookieSetter, + // configurable: true + // }); + // }); + + // it('should be detected', function() { + // assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should be enabled by default'); + // }); + + // it('should be not available', function() { + // setCookie = () => ''; + // window.navigator.cookieEnabled = false; + // window.document.cookie = ''; + // assert.equal(utils.cookiesAreEnabled(), false, 'Cookies should be disabled'); + // }); + + // it('should be available', function() { + // window.navigator.cookieEnabled = false; + // window.document.cookie = 'key=value'; + // assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should already be set'); + // window.navigator.cookieEnabled = false; + // window.document.cookie = ''; + // assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should settable'); + // setCookie = () => ''; + // window.navigator.cookieEnabled = true; + // window.document.cookie = ''; + // assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should be on via on window.navigator'); + // // Reset the setCookie + // setCookie = (v) => v; + // }); + // }); describe('delayExecution', function () { it('should execute the core function after the correct number of calls', function () { From 15ad83ab601b4bedf25c8631d390a114ac7ac89c Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 6 Feb 2018 16:51:58 -0500 Subject: [PATCH 0100/1594] Prebid.js 1.3.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fdc8e5b7ea8..55af6331841 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.3.0-pre", + "version": "1.3.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From c053d04483dbb512f8980d5e48715433cab28dc1 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 6 Feb 2018 17:31:32 -0500 Subject: [PATCH 0101/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 55af6331841..839b6113ff1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.3.0", + "version": "1.4.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 77fd5d2a7e55576367a6998c4e800e346f020f67 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 7 Feb 2018 14:06:23 -0700 Subject: [PATCH 0102/1594] Omit app and device if not present rather than send false (#2116) * omit app and device if not present rather than send false * no bang bang! just get and set on request if object --- modules/prebidServerBidAdapter.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index e222ecb446b..7ef83240251 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -210,8 +210,6 @@ 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 isDebug = !!getConfig('debug'); - const app = !!getConfig('app'); - const device = !!getConfig('device'); const adUnits = utils.deepClone(s2sBidRequest.ad_units); adUnits.forEach(adUnit => { let videoMediaType = utils.deepAccess(adUnit, 'mediaTypes.video'); @@ -234,13 +232,19 @@ export function PrebidServer() { url: utils.getTopWindowUrl(), prebid_version: '$prebid.version$', ad_units: adUnits.filter(hasSizes), - is_debug: isDebug, - device: device, - app: app + is_debug: isDebug }; let digiTrust = _getDigiTrustQueryParams(); + // grab some global config and pass it along + ['app', 'device'].forEach(setting => { + let value = getConfig(setting); + if (typeof value === 'object') { + requestJson[setting] = value; + } + }); + if (digiTrust) { requestJson.digiTrust = digiTrust; } From 1611159521a93905603bec41994cde3650541b72 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 7 Feb 2018 17:24:40 -0500 Subject: [PATCH 0103/1594] Prebid 1.3.1 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 839b6113ff1..f97668512bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.4.0-pre", + "version": "1.3.1", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 63f9411990474472dbee93939c6ed6b988ce3bd6 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 7 Feb 2018 17:34:57 -0500 Subject: [PATCH 0104/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f97668512bc..839b6113ff1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.3.1", + "version": "1.4.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From f73db9e6e73b4cda73b59007ddea96e831b68764 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 8 Feb 2018 09:03:56 -0700 Subject: [PATCH 0105/1594] fix bug where hooked functions w/ no hooks weren't ran immediately (#2115) --- src/hook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hook.js b/src/hook.js index 5ba1d4b9bbf..6c6cefdc56c 100644 --- a/src/hook.js +++ b/src/hook.js @@ -68,7 +68,7 @@ export function createHook(type, fn, hookName) { } function hookedFn(...args) { - if (_hooks.length === 0) { + if (_hooks.length === 1 && _hooks[0].fn === fn) { return fn.apply(this, args); } return types[type].apply(this, args); From 8bd9595c50498a301a3e605bef4737773a70b725 Mon Sep 17 00:00:00 2001 From: optimatic58 <33465594+optimatic58@users.noreply.github.com> Date: Thu, 8 Feb 2018 12:10:53 -0500 Subject: [PATCH 0106/1594] Added support for NURL and ADM as backup (#2112) + Updated unit tests to test code updates + Added version number (1.0.4) for optimatic records --- modules/optimaticBidAdapter.js | 11 ++++- test/spec/modules/optimaticBidAdapter_spec.js | 42 ++++++++++++++++++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/modules/optimaticBidAdapter.js b/modules/optimaticBidAdapter.js index 2408eb8cefe..0c8305e6867 100644 --- a/modules/optimaticBidAdapter.js +++ b/modules/optimaticBidAdapter.js @@ -3,6 +3,9 @@ import { registerBidder } from 'src/adapters/bidderFactory'; export const ENDPOINT = '//mg-bid.optimatic.com/adrequest/'; export const spec = { + + version: '1.0.4', + code: 'optimatic', supportedMediaTypes: ['video'], @@ -33,7 +36,7 @@ export const spec = { } catch (e) { response = null; } - if (!response || !bid || !bid.adm || !bid.price) { + if (!response || !bid || (!bid.adm && !bid.nurl) || !bid.price) { utils.logWarn(`No valid bids from ${spec.code} bidder`); return []; } @@ -43,7 +46,6 @@ export const spec = { bidderCode: spec.code, cpm: bid.price, creativeId: bid.id, - vastXml: bid.adm, width: size.width, height: size.height, mediaType: 'video', @@ -51,6 +53,11 @@ export const spec = { ttl: 300, netRevenue: true }; + if (bid.nurl) { + bidResponse.vastUrl = bid.nurl; + } else if (bid.adm) { + bidResponse.vastXml = bid.adm; + } return bidResponse; } }; diff --git a/test/spec/modules/optimaticBidAdapter_spec.js b/test/spec/modules/optimaticBidAdapter_spec.js index 890c0b78613..d701d981f37 100644 --- a/test/spec/modules/optimaticBidAdapter_spec.js +++ b/test/spec/modules/optimaticBidAdapter_spec.js @@ -106,7 +106,7 @@ describe('OptimaticBidAdapter', () => { expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "adm" is missing', () => { + it('should return no bids if the response "nurl" and "adm" are missing', () => { const serverResponse = {seatbid: [{bid: [{price: 5.01}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); @@ -118,7 +118,7 @@ describe('OptimaticBidAdapter', () => { expect(bidResponse.length).to.equal(0); }); - it('should return a valid bid response', () => { + it('should return a valid bid response with just "adm"', () => { const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, adm: ''}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { @@ -136,5 +136,43 @@ describe('OptimaticBidAdapter', () => { }; expect(bidResponse).to.deep.equal(o); }); + + it('should return a valid bid response with just "nurl"', () => { + const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, nurl: 'https://mg-bid-win.optimatic.com/win/134eb262-948a-463e-ad93-bc8b622d399c?wp=${AUCTION_PRICE}'}]}], cur: 'USD'}; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + let o = { + requestId: bidRequest.bidId, + bidderCode: spec.code, + cpm: serverResponse.seatbid[0].bid[0].price, + creativeId: serverResponse.seatbid[0].bid[0].id, + vastUrl: serverResponse.seatbid[0].bid[0].nurl, + width: 640, + height: 480, + mediaType: 'video', + currency: 'USD', + ttl: 300, + netRevenue: true + }; + expect(bidResponse).to.deep.equal(o); + }); + + it('should return a valid bid response with "nurl" when both nurl and adm exist', () => { + const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, adm: '', nurl: 'https://mg-bid-win.optimatic.com/win/134eb262-948a-463e-ad93-bc8b622d399c?wp=${AUCTION_PRICE}'}]}], cur: 'USD'}; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + let o = { + requestId: bidRequest.bidId, + bidderCode: spec.code, + cpm: serverResponse.seatbid[0].bid[0].price, + creativeId: serverResponse.seatbid[0].bid[0].id, + vastUrl: serverResponse.seatbid[0].bid[0].nurl, + width: 640, + height: 480, + mediaType: 'video', + currency: 'USD', + ttl: 300, + netRevenue: true + }; + expect(bidResponse).to.deep.equal(o); + }); }); }); From 7e1abbef2f804f79e9f82cffa2919677d6ee24fa Mon Sep 17 00:00:00 2001 From: rachelrj Date: Thu, 8 Feb 2018 10:27:55 -0700 Subject: [PATCH 0107/1594] Fix sovrn dealid (#2119) --- modules/sovrnBidAdapter.js | 2 +- test/spec/modules/sovrnBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index bf2f7f7b777..13f04395afa 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -66,7 +66,7 @@ export const spec = { width: parseInt(sovrnBid.w), height: parseInt(sovrnBid.h), creativeId: sovrnBid.id, - dealId: sovrnBid.dealId || null, + dealId: sovrnBid.dealid || null, currency: 'USD', netRevenue: true, mediaType: BANNER, diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index c4eadd02738..43307f35527 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -103,7 +103,7 @@ describe('sovrnBidAdapter', function() { }); it('should get correct bid response when dealId is passed', () => { - response.body.dealId = 'baking'; + response.body.dealid = 'baking'; let expectedResponse = [{ 'requestId': '263c448586f5a1', From ace59039b7a122646b084384f7e650d505f03043 Mon Sep 17 00:00:00 2001 From: kat Date: Thu, 8 Feb 2018 13:13:19 -0500 Subject: [PATCH 0108/1594] Add adapter for IAS (#2056) * PET-201: got a working version * PET-201: encoded query string * PET-201: added unit tests * PET-201: added missing keyword * PET-201: corrected coding styles * PET-201: decreased cpm so real bidders could win per code review --- modules/iasBidAdapter.js | 117 +++++++++++++++ modules/iasBidAdapter.md | 30 ++++ test/spec/modules/iasBidAdapter_spec.js | 190 ++++++++++++++++++++++++ 3 files changed, 337 insertions(+) create mode 100644 modules/iasBidAdapter.js create mode 100644 modules/iasBidAdapter.md create mode 100644 test/spec/modules/iasBidAdapter_spec.js diff --git a/modules/iasBidAdapter.js b/modules/iasBidAdapter.js new file mode 100644 index 00000000000..61ba909527a --- /dev/null +++ b/modules/iasBidAdapter.js @@ -0,0 +1,117 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'ias'; + +function isBidRequestValid(bid) { + const { pubId, adUnitPath } = bid.params; + return !!(pubId && adUnitPath); +} + +/** + * Converts GPT-style size array into a string + * @param {Array} sizes: list of GPT-style sizes, e.g. [[300, 250], [300, 300]] + * @return {String} a string containing sizes, e.g. '[300.250,300.300]' + */ +function stringifySlotSizes(sizes) { + let result = ''; + if (utils.isArray(sizes)) { + result = sizes.reduce((acc, size) => { + acc.push(size.join('.')); + return acc; + }, []); + result = '[' + result.join(',') + ']'; + } + return result; +} + +function stringifySlot(bidRequest) { + const id = bidRequest.adUnitCode; + const ss = stringifySlotSizes(bidRequest.sizes); + const p = bidRequest.params.adUnitPath; + const slot = { id, ss, p }; + const keyValues = utils.getKeys(slot).map(function(key) { + return [key, slot[key]].join(':'); + }); + return '{' + keyValues.join(',') + '}'; +} + +function stringifyWindowSize() { + return [window.innerWidth || -1, window.innerHeight || -1].join('.'); +} + +function stringifyScreenSize() { + return [(window.screen && window.screen.width) || -1, (window.screen && window.screen.height) || -1].join('.'); +} + +function buildRequests(bidRequests) { + const IAS_HOST = '//pixel.adsafeprotected.com/services/pub'; + const anId = bidRequests[0].params.pubId; + + let queries = []; + queries.push(['anId', anId]); + queries = queries.concat(bidRequests.reduce(function(acc, request) { + acc.push(['slot', stringifySlot(request)]); + return acc; + }, [])); + + queries.push(['wr', stringifyWindowSize()]); + queries.push(['sr', stringifyScreenSize()]); + + const queryString = encodeURI(queries.map(qs => qs.join('=')).join('&')); + + return { + method: 'GET', + url: IAS_HOST, + data: queryString, + bidRequest: bidRequests[0] + } +} + +function getPageLevelKeywords(response) { + let result = {}; + shallowMerge(result, response.brandSafety); + result.fr = response.fr; + return result; +} + +function shallowMerge(dest, src) { + utils.getKeys(src).reduce((dest, srcKey) => { + dest[srcKey] = src[srcKey]; + return dest; + }, dest); +} + +function interpretResponse(serverResponse, request) { + const iasResponse = serverResponse.body; + const bidResponses = []; + + // Keys in common bid response are not used; + // Necessary to get around with prebid's common bid response check + const commonBidResponse = { + requestId: request.bidRequest.bidId, + cpm: 0.01, + width: 100, + height: 200, + creativeId: 434, + dealId: 42, + currency: 'usd', + netRevenue: true, + ttl: 360 + }; + + shallowMerge(commonBidResponse, getPageLevelKeywords(iasResponse)); + commonBidResponse.slots = iasResponse.slots; + bidResponses.push(commonBidResponse); + return bidResponses; +} + +export const spec = { + code: BIDDER_CODE, + aliases: [], + isBidRequestValid: isBidRequestValid, + buildRequests: buildRequests, + interpretResponse: interpretResponse +}; + +registerBidder(spec); diff --git a/modules/iasBidAdapter.md b/modules/iasBidAdapter.md new file mode 100644 index 00000000000..3224fbf4a26 --- /dev/null +++ b/modules/iasBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +``` +Module Name: Integral Ad Science(IAS) Bidder Adapter +Module Type: Bidder Adapter +Maintainer: kat@integralads.com +``` + +# Description + +This module is an integration with prebid.js with an IAS product, pet.js. It is not a bidder per se but works in a similar way: retrieve data that publishers might be interested in setting keyword targeting. + +# Test Parameters +``` + var adUnits = [ + { + code: 'ias-dfp-test-async', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "ias", + params: { + pubId: '99', + adUnitPath: '/57514611/news.com' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/iasBidAdapter_spec.js b/test/spec/modules/iasBidAdapter_spec.js new file mode 100644 index 00000000000..4f335ab22ba --- /dev/null +++ b/test/spec/modules/iasBidAdapter_spec.js @@ -0,0 +1,190 @@ +import { expect } from 'chai'; +import { spec } from 'modules/iasBidAdapter'; + +describe('iasBidAdapter is an adapter that', () => { + it('has the correct bidder code', () => { + expect(spec.code).to.equal('ias'); + }); + describe('has a method `isBidRequestValid` that', () => { + it('exists', () => { + expect(spec.isBidRequestValid).to.be.a('function'); + }); + it('returns false if bid params misses `pubId`', () => { + expect(spec.isBidRequestValid( + { + params: { + adUnitPath: 'someAdUnitPath' + } + })).to.equal(false); + }); + it('returns false if bid params misses `adUnitPath`', () => { + expect(spec.isBidRequestValid( + { + params: { + pubId: 'somePubId' + } + })).to.equal(false); + }); + it('returns true otherwise', () => { + expect(spec.isBidRequestValid( + { + params: { + adUnitPath: 'someAdUnitPath', + pubId: 'somePubId', + someOtherParam: 'abc' + } + })).to.equal(true); + }); + }); + + describe('has a method `buildRequests` that', () => { + it('exists', () => { + expect(spec.buildRequests).to.be.a('function'); + }); + describe('given bid requests, returns a `ServerRequest` instance that', () => { + let bidRequests, IAS_HOST; + beforeEach(() => { + IAS_HOST = '//pixel.adsafeprotected.com/services/pub'; + bidRequests = [ + { + adUnitCode: 'one-div-id', + auctionId: 'someAuctionId', + bidId: 'someBidId', + bidder: 'ias', + bidderRequestId: 'someBidderRequestId', + params: { + pubId: '1234', + adUnitPath: '/a/b/c' + }, + sizes: [ + [10, 20], + [300, 400] + ], + transactionId: 'someTransactionId' + }, + { + adUnitCode: 'two-div-id', + auctionId: 'someAuctionId', + bidId: 'someBidId', + bidder: 'ias', + bidderRequestId: 'someBidderRequestId', + params: { + pubId: '1234', + adUnitPath: '/d/e/f' + }, + sizes: [ + [50, 60] + ], + transactionId: 'someTransactionId' + } + ]; + }); + it('has property `method` of `GET`', () => { + expect(spec.buildRequests(bidRequests)).to.deep.include({ + method: 'GET' + }); + }); + it('has property `url` to be the correct IAS endpoint', () => { + expect(spec.buildRequests(bidRequests)).to.deep.include({ + url: IAS_HOST + }); + }); + describe('has property `data` that is an encode query string containing information such as', () => { + let val; + const ANID_PARAM = 'anId'; + const SLOT_PARAM = 'slot'; + const SLOT_ID_PARAM = 'id'; + const SLOT_SIZE_PARAM = 'ss'; + const SLOT_AD_UNIT_PATH_PARAM = 'p'; + + beforeEach(() => val = decodeURI(spec.buildRequests(bidRequests).data)); + it('publisher id', () => { + expect(val).to.have.string(`${ANID_PARAM}=1234`); + }); + it('ad slot`s id, size and ad unit path', () => { + expect(val).to.have.string(`${SLOT_PARAM}={${SLOT_ID_PARAM}:one-div-id,${SLOT_SIZE_PARAM}:[10.20,300.400],${SLOT_AD_UNIT_PATH_PARAM}:/a/b/c}`); + expect(val).to.have.string(`${SLOT_PARAM}={${SLOT_ID_PARAM}:two-div-id,${SLOT_SIZE_PARAM}:[50.60],${SLOT_AD_UNIT_PATH_PARAM}:/d/e/f}`); + }); + it('window size', () => { + expect(val).to.match(/.*wr=[0-9]*\.[0-9]*/); + }); + it('screen size', () => { + expect(val).to.match(/.*sr=[0-9]*\.[0-9]*/); + }); + }); + it('has property `bidRequest` that is the first passed in bid request', () => { + expect(spec.buildRequests(bidRequests)).to.deep.include({ + bidRequest: bidRequests[0] + }); + }); + }); + }); + describe('has a method `interpretResponse` that', () => { + it('exists', () => { + expect(spec.interpretResponse).to.be.a('function'); + }); + describe('returns a list of bid response that', () => { + let bidResponse, slots; + beforeEach(() => { + const request = { + bidRequest: { + bidId: '102938' + } + }; + slots = {}; + slots['test-div-id'] = { + id: '1234', + vw: ['60', '70'] + }; + slots['test-div-id-two'] = { + id: '5678', + vw: ['80', '90'] + }; + const serverResponse = { + body: { + brandSafety: { + adt: 'adtVal', + alc: 'alcVal', + dlm: 'dlmVal', + drg: 'drgVal', + hat: 'hatVal', + off: 'offVal', + vio: 'vioVal' + }, + fr: 'false', + slots: slots + }, + headers: {} + }; + bidResponse = spec.interpretResponse(serverResponse, request); + }); + it('has IAS keyword `adt` as property', () => { + expect(bidResponse[0]).to.deep.include({ adt: 'adtVal' }); + }); + it('has IAS keyword `alc` as property', () => { + expect(bidResponse[0]).to.deep.include({ alc: 'alcVal' }); + }); + it('has IAS keyword `dlm` as property', () => { + expect(bidResponse[0]).to.deep.include({ dlm: 'dlmVal' }); + }); + it('has IAS keyword `drg` as property', () => { + expect(bidResponse[0]).to.deep.include({ drg: 'drgVal' }); + }); + it('has IAS keyword `hat` as property', () => { + expect(bidResponse[0]).to.deep.include({ hat: 'hatVal' }); + }); + it('has IAS keyword `off` as property', () => { + expect(bidResponse[0]).to.deep.include({ off: 'offVal' }); + }); + it('has IAS keyword `vio` as property', () => { + expect(bidResponse[0]).to.deep.include({ vio: 'vioVal' }); + }); + it('has IAS keyword `fr` as property', () => { + expect(bidResponse[0]).to.deep.include({ fr: 'false' }); + }); + it('has property `slots`', () => { + expect(bidResponse[0]).to.deep.include({ slots: slots }); + }); + }); + }); +}); From cfe1f72cdb397c6923484943235f3e8de4a9389a Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Fri, 9 Feb 2018 05:34:43 -0800 Subject: [PATCH 0109/1594] Replace event string with constant (#2128) --- src/prebid.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 86fd678ee7e..0225b32191b 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -13,7 +13,7 @@ import includes from 'core-js/library/fn/array/includes'; var $$PREBID_GLOBAL$$ = getGlobal(); -var CONSTANTS = require('./constants.json'); +const CONSTANTS = require('./constants.json'); var utils = require('./utils.js'); var adaptermanager = require('./adaptermanager'); var bidfactory = require('./bidfactory'); @@ -23,9 +23,7 @@ const { triggerUserSyncs } = userSync; /* private variables */ const RENDERED = 'rendered'; -var BID_WON = CONSTANTS.EVENTS.BID_WON; -var SET_TARGETING = CONSTANTS.EVENTS.SET_TARGETING; -var ADD_AD_UNITS = CONSTANTS.EVENTS.ADD_AD_UNITS; +const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING } = CONSTANTS.EVENTS; var eventValidators = { bidWon: checkDefinedPlacement @@ -283,7 +281,7 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { * @alias module:pbjs.requestBids */ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels } = {}) { - events.emit('requestBids'); + events.emit(REQUEST_BIDS); const cbTimeout = timeout || config.getConfig('bidderTimeout'); adUnits = adUnits || $$PREBID_GLOBAL$$.adUnits; From c31cc528c83cae93b6bcb25b5a91c5faf11a5a46 Mon Sep 17 00:00:00 2001 From: Melody Li Date: Fri, 9 Feb 2018 11:00:07 -0500 Subject: [PATCH 0110/1594] Update maintainer email (#2132) --- modules/yieldmoBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index b93f72594bc..8c60202d7ea 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Yieldmo Bid Adapter Module Type: Bidder Adapter -Maintainer: melody@yieldmo.com +Maintainer: opensource@yieldmo.com Note: Our ads will only render in mobile ``` From a2741f0ece059e1c02904df09cda40f2a69d9c9d Mon Sep 17 00:00:00 2001 From: gammassp <35954362+gammassp@users.noreply.github.com> Date: Mon, 12 Feb 2018 22:19:10 +0700 Subject: [PATCH 0111/1594] Add adapter for GAMMA SSP (#2092) * commit gamma adapter * Fixed The Travis CI build failed * fix interpretResponse return empty when server response empty * removed mediaType removed mediaType in bid and return vastXml property if video request * fixed Travis CI build * Travis CI build * add gamma spec * fixed Travis CI build * fix spec * fix spec * Add files via upload * Add files via upload * fix spec * fix Travis CI build * move to module * remove gaxDomain param and move to adapter * remove check isBidRequestValid for gaxDomain * remove gaxDomain param * remove gaxDomain param * remove gaxDomain param * Delete gammaBidAdapter_spec.js --- modules/gammaBidAdapter.js | 90 ++++++++++++++++ modules/gammaBidAdapter.md | 67 ++++++++++++ test/spec/modules/gammaBidAdapter_spec.js | 119 ++++++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 modules/gammaBidAdapter.js create mode 100644 modules/gammaBidAdapter.md create mode 100644 test/spec/modules/gammaBidAdapter_spec.js diff --git a/modules/gammaBidAdapter.js b/modules/gammaBidAdapter.js new file mode 100644 index 00000000000..8240df3d151 --- /dev/null +++ b/modules/gammaBidAdapter.js @@ -0,0 +1,90 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; + +const ENDPOINT = 'hb.gammaplatform.com'; +const BIDDER_CODE = 'gamma'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['gamma'], + + /** + * 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 !!(bid.params.siteId || bid.params.zoneId); + }, + + /** + * 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) { + const gaxObjParams = find(bidRequests, hasParamInfo); + return { + method: 'GET', + url: '//' + ENDPOINT + '/adx/request?wid=' + gaxObjParams.params.siteId + '&zid=' + gaxObjParams.params.zoneId + '&hb=pbjs&bidid=' + gaxObjParams.bidId + '&urf=' + utils.getTopWindowUrl() + }; + }, + + /** + * 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) { + serverResponse = serverResponse.body; + + const bids = []; + + if (serverResponse.id) { + const bid = newBid(serverResponse); + bids.push(bid); + } + + return bids; + } +} + +/** + * Unpack the Server's Bid into a Prebid-compatible one. + * @param serverBid + * @return Bid + */ +function newBid(serverBid) { + const bid = { + ad: serverBid.seatbid[0].bid[0].adm, + cpm: serverBid.seatbid[0].bid[0].price, + creativeId: serverBid.seatbid[0].bid[0].adid, + currency: serverBid.cur, + dealId: serverBid.seatbid[0].bid[0].dealid, + width: serverBid.seatbid[0].bid[0].w, + height: serverBid.seatbid[0].bid[0].h, + mediaType: serverBid.type, + netRevenue: true, + requestId: serverBid.id, + ttl: serverBid.seatbid[0].bid[0].ttl || 300 + }; + + if (serverBid.type == 'video') { + Object.assign(bid, { + vastXml: serverBid.seatbid[0].bid[0].vastXml, + ttl: 3600 + }); + } + + return bid; +} + +function hasParamInfo(bid) { + return !!bid.params; +} + +registerBidder(spec); diff --git a/modules/gammaBidAdapter.md b/modules/gammaBidAdapter.md new file mode 100644 index 00000000000..83c1fdf4853 --- /dev/null +++ b/modules/gammaBidAdapter.md @@ -0,0 +1,67 @@ +# Overview + +``` +Module Name: Gamma Bid Adapter +Module Type: Bidder Adapter +Maintainer: support@gammassp.com +``` + +# Description + +Connects to Gamma exchange for bids. + +Gamma bid adapter supports Banner, Video. + +# Test Parameters +``` +var adUnits = [{ + code: 'gamma-hb-ad-123456-0', + sizes: [[300, 250]], + + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'gamma', + params: { + siteId: '1465446377', + zoneId: '1515999290' + } + }] + + }]; +``` +# Ad Unit and Setup: For Testing +In order to receive bids please map localhost to (any) test domain. + +``` +<--! Prebid Config section > + + ', + 'adid': '1515999070', + 'dealid': 'gax-paj2qarjf2g', + 'h': 250, + 'w': 300 + }] + }] + } + }; + + it('should get the correct bid response', () => { + let expectedResponse = [{ + 'requestId': '23beaa6af6cdde', + 'cpm': 0.45, + 'width': 300, + 'height': 250, + 'creativeId': '1515999070', + 'dealId': 'gax-paj2qarjf2g', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'ad': '' + }]; + let result = spec.interpretResponse(serverResponse); + expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); + }); + + it('handles empty bid response', () => { + let response = { + body: {} + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From ef4354bd8f8136f41d6da7300c1076256b7e32e7 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Mon, 12 Feb 2018 10:11:11 -0800 Subject: [PATCH 0112/1594] Remove unneeded lint exceptions (#2129) --- .eslintrc.js | 3 --- test/.eslintrc.js | 7 ------- 2 files changed, 10 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 56081a88262..dadfb1f0433 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,12 +21,9 @@ module.exports = { // See Issue #1111. "camelcase": "off", "eqeqeq": "off", - "no-control-regex": "off", "no-return-assign": "off", "no-throw-literal": "off", "no-undef": "off", - "no-use-before-define": "off", "no-useless-escape": "off", - "standard/no-callback-literal": "off", } }; diff --git a/test/.eslintrc.js b/test/.eslintrc.js index e41903540a1..c1d36996a40 100644 --- a/test/.eslintrc.js +++ b/test/.eslintrc.js @@ -29,13 +29,7 @@ module.exports = { "no-global-assign": "off", "no-path-concat": "off", "no-redeclare": "off", - "no-new-object": "off", - "no-array-constructor": "off", "node/no-deprecated-api": "off", - "no-cond-assign": "off", - "no-sequences": "off", - "no-eval": "off", - "no-new": "off", "no-return-assign": "off", "no-undef": "off", "no-unused-vars": "off", @@ -43,7 +37,6 @@ module.exports = { "no-useless-escape": "off", "one-var": "off", "standard/array-bracket-even-spacing": "off", - "standard/no-callback-literal": "off", "standard/object-curly-even-spacing": "off" } }; From b16071cf60d4b0c037f7a593107ef3ab3a11b2e2 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 12 Feb 2018 13:11:54 -0500 Subject: [PATCH 0113/1594] Option to use a configurable vendor preset for s2sConfig (#2073) * initial commit to support pbs vendor config options * correcting a value in a test case * adding rubicon config info and updated var names * made changes to unit tests, changed cookieSet default, and fixed small cookieSet issue * tweaking logic of main check to read it better * adjusting rubicon vendor values and default config to fix issue * undoing default config change * additional changes to rubicon defaults --- modules/prebidServerBidAdapter.js | 55 ++++++++++++-- .../modules/prebidServerBidAdapter_spec.js | 75 ++++++++++++++++++- 2 files changed, 121 insertions(+), 9 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 7ef83240251..748d91f9444 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -19,15 +19,38 @@ const DEFAULT_S2S_CURRENCY = 'USD'; const DEFAULT_S2S_NETREVENUE = true; let _s2sConfig; + +const s2sDefaultConfig = { + enabled: false, + timeout: 1000, + maxBids: 1, + adapter: 'prebidServer' +}; + config.setDefaults({ - 's2sConfig': { - enabled: false, - timeout: 1000, - maxBids: 1, - adapter: 'prebidServer' - } + 's2sConfig': s2sDefaultConfig }); +// accountId and bidders params are not included here, should be configured by end-user +const availVendorDefaults = { + 'appnexus': { + adapter: 'prebidServer', + cookieSet: false, + enabled: true, + endpoint: '//prebid.adnxs.com/pbs/v1/auction', + syncEndpoint: '//prebid.adnxs.com/pbs/v1/cookie_sync', + timeout: 1000 + }, + 'rubicon': { + adapter: 'prebidServer', + cookieSet: false, + enabled: true, + endpoint: '//prebid-server.rubiconproject.com/auction', + syncEndpoint: '//prebid-server.rubiconproject.com/cookie_sync', + timeout: 500 + } +}; + /** * Set config for server to server header bidding * @typedef {Object} options - required @@ -42,6 +65,24 @@ config.setDefaults({ * @property {string} [cookieSetUrl] url for cookie set library, if passed then cookieSet is enabled */ function setS2sConfig(options) { + if (options.defaultVendor) { + let vendor = options.defaultVendor; + let optionKeys = Object.keys(options); + + if (availVendorDefaults.hasOwnProperty(vendor)) { + // vendor keys will be set if either: the key was not specified by user + // or if the user did not set their own distinct value (ie using the system default) to override the vendor + Object.keys(availVendorDefaults[vendor]).forEach(function(vendorKey) { + if (s2sDefaultConfig[vendorKey] === options[vendorKey] || !includes(optionKeys, vendorKey)) { + options[vendorKey] = availVendorDefaults[vendor][vendorKey]; + } + }); + } else { + utils.logError('Incorrect or unavailable prebid server default vendor option: ' + vendor); + return false; + } + } + let keys = Object.keys(options); if (['accountId', 'bidders', 'endpoint'].filter(key => { @@ -351,7 +392,7 @@ export function PrebidServer() { }); } } - if (result.status === 'no_cookie' && typeof _s2sConfig.cookieSetUrl === 'string') { + if (result.status === 'no_cookie' && _s2sConfig.cookieSet && typeof _s2sConfig.cookieSetUrl === 'string') { // cookie sync cookieSet(_s2sConfig.cookieSetUrl); } diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 58a71158865..b719171989d 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -464,6 +464,7 @@ describe('S2S Adapter', () => { it('calls cookieSet cookie sync when no_cookie response && opted in', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); let myConfig = Object.assign({ + cookieSet: true, cookieSetUrl: 'https://acdn.adnxs.com/cookieset/cs.js' }, CONFIG); @@ -485,7 +486,7 @@ describe('S2S Adapter', () => { utils.logError.restore(); }); - it('should log error when accountId is missing', () => { + it('should log an error when accountId is missing', () => { const options = { enabled: true, bidders: ['appnexus'], @@ -498,7 +499,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should log error when bidders is missing', () => { + it('should log an error when bidders is missing', () => { const options = { accountId: '1', enabled: true, @@ -510,5 +511,75 @@ describe('S2S Adapter', () => { config.setConfig({ s2sConfig: options }); sinon.assert.calledOnce(logErrorSpy); }); + + it('should log an error when endpoint is missing', () => { + const options = { + accountId: '1', + bidders: ['appnexus'], + timeout: 1000, + enabled: true, + adapter: 'prebidServer' + }; + + config.setConfig({ s2sConfig: options}); + sinon.assert.calledOnce(logErrorSpy); + }); + + it('should log an error when using an unknown vendor', () => { + const options = { + accountId: '1', + bidders: ['appnexus'], + defaultVendor: 'mytest' + }; + + config.setConfig({ s2sConfig: options }); + sinon.assert.calledOnce(logErrorSpy); + }); + + it('should configure the s2sConfig object with appnexus vendor defaults unless specified by user', () => { + const options = { + accountId: '123', + bidders: ['appnexus'], + defaultVendor: 'appnexus', + timeout: 750 + }; + + config.setConfig({ s2sConfig: options }); + sinon.assert.notCalled(logErrorSpy); + + let vendorConfig = config.getConfig('s2sConfig'); + expect(vendorConfig).to.have.property('accountId', '123'); + expect(vendorConfig).to.have.property('adapter', 'prebidServer'); + expect(vendorConfig.bidders).to.deep.equal(['appnexus']); + expect(vendorConfig.cookieSet).to.be.false; + expect(vendorConfig.cookieSetUrl).to.be.undefined; + expect(vendorConfig.enabled).to.be.true; + expect(vendorConfig).to.have.property('endpoint', '//prebid.adnxs.com/pbs/v1/auction'); + expect(vendorConfig).to.have.property('syncEndpoint', '//prebid.adnxs.com/pbs/v1/cookie_sync'); + expect(vendorConfig).to.have.property('timeout', 750); + }); + + it('should configure the s2sConfig object with rubicon vendor defaults unless specified by user', () => { + const options = { + accountId: 'abc', + bidders: ['rubicon'], + defaultVendor: 'rubicon', + timeout: 750 + }; + + config.setConfig({ s2sConfig: options }); + sinon.assert.notCalled(logErrorSpy); + + let vendorConfig = config.getConfig('s2sConfig'); + expect(vendorConfig).to.have.property('accountId', 'abc'); + expect(vendorConfig).to.have.property('adapter', 'prebidServer'); + expect(vendorConfig.bidders).to.deep.equal(['rubicon']); + expect(vendorConfig.cookieSet).to.be.false; + expect(vendorConfig.cookieSetUrl).to.be.undefined; + expect(vendorConfig.enabled).to.be.true; + expect(vendorConfig).to.have.property('endpoint', '//prebid-server.rubiconproject.com/auction'); + expect(vendorConfig).to.have.property('syncEndpoint', '//prebid-server.rubiconproject.com/cookie_sync'); + expect(vendorConfig).to.have.property('timeout', 750); + }); }); }); From 0923c9112ab098dd743d3ec5952e6e3c2dfc3a64 Mon Sep 17 00:00:00 2001 From: hhhjort <31041505+hhhjort@users.noreply.github.com> Date: Mon, 12 Feb 2018 13:14:18 -0500 Subject: [PATCH 0114/1594] remote.html is being deprecated in AMP. Pointer to the Prebid Server solution added in addition to a deprecation warning (#2110) --- integrationExamples/gpt/amp/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/integrationExamples/gpt/amp/README.md b/integrationExamples/gpt/amp/README.md index 48b08fe0de5..1d61fa1f256 100644 --- a/integrationExamples/gpt/amp/README.md +++ b/integrationExamples/gpt/amp/README.md @@ -1,3 +1,10 @@ +##WARNING +The below documented method of deploying prebid on AMP requires remote.html +This is being deprecated on March 29th. A new method the requires Prebid Server +is being developed, see [Prebid Server](http://github.com/prebid/prebid-server). + +## Old method: + This README provides steps to run amp example page. Add following entries to your hosts file From 1899a2b01139475a692ec179b89bdc64a25383bf Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Mon, 12 Feb 2018 10:14:44 -0800 Subject: [PATCH 0115/1594] Remove deprecated method reference (#2130) --- CONTRIBUTING.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5856835f785..dc8d80ec384 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,9 +48,6 @@ When you are adding code to Prebid.js, or modifying code that isn't covered by a - _Assert_: check that the expected results have occurred - e.g., use Chai assertions to check that the expected output is equal to the actual output - Test the public interface, not the internal implementation -- If using global `pbjs` data structures in your test, take care to not completely overwrite them with your own data as that may affect other tests relying on those structures, e.g.: - - **OK**: `pbjs._bidsRequested.push(bidderRequestObject);` - - **NOT OK**: `pbjs._bidsRequested = [bidderRequestObject];` - If you need to check `adloader.loadScript` in a test, use a `stub` rather than a `spy`. `spy`s trigger a network call which can result in a `script error` and cause unrelated unit tests to fail. `stub`s will let you gather information about the `adloader.loadScript` call without affecting external resources - When writing tests you may use ES2015 syntax if desired From dab30a3031611af36d66cd33f9541a781e87ab5c Mon Sep 17 00:00:00 2001 From: Matt Kendall Date: Tue, 13 Feb 2018 11:06:06 -0500 Subject: [PATCH 0116/1594] fix bug with privateSizes (#2141) --- modules/appnexusBidAdapter.js | 2 +- test/spec/modules/appnexusBidAdapter_spec.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 96163518a3a..4afe451f54f 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -281,7 +281,7 @@ function bidToTag(bid) { tag.traffic_source_code = bid.params.trafficSourceCode; } if (bid.params.privateSizes) { - tag.private_sizes = getSizes(bid.params.privateSizes); + tag.private_sizes = transformSizes(bid.params.privateSizes); } if (bid.params.supplyType) { tag.supply_type = bid.params.supplyType; diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 560fcf40acc..2d3d2cb1745 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -67,6 +67,24 @@ describe('AppNexusAdapter', () => { } ]; + it('should parse out private sizes', () => { + 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 source and verison to the tag', () => { const request = spec.buildRequests(bidRequests); const payload = JSON.parse(request.data); From 64bc0381b244e6127d349b67ad652c92b7594119 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 13 Feb 2018 09:18:32 -0700 Subject: [PATCH 0117/1594] added advertiserId and networkId for rubiconBidAdapter (#2086) * added advertiserId and networkId for rubiconBidAdapter * move advertiserId and networkId into custom rubicon property --- modules/rubiconBidAdapter.js | 7 ++++++- test/spec/modules/rubiconBidAdapter_spec.js | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index ee490e55c15..9caffeb54ec 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -270,8 +270,13 @@ export const spec = { cpm: ad.cpm || 0, dealId: ad.deal, ttl: 300, // 5 minutes - netRevenue: config.getConfig('rubicon.netRevenue') || false + netRevenue: config.getConfig('rubicon.netRevenue') || false, + rubicon: { + advertiserId: ad.advertiser, + networkId: ad.network + } }; + if (bidRequest.mediaType === 'video') { bid.width = bidRequest.params.video.playerWidth; bid.height = bidRequest.params.video.playerHeight; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 2ff8d5fe0e3..fedffced081 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -607,6 +607,8 @@ describe('the rubicon adapter', () => { expect(bids[0].cpm).to.equal(0.911); expect(bids[0].ttl).to.equal(300); expect(bids[0].netRevenue).to.equal(false); + expect(bids[0].rubicon.advertiserId).to.equal(7); + expect(bids[0].rubicon.networkId).to.equal(8); expect(bids[0].creativeId).to.equal('crid-9'); expect(bids[0].currency).to.equal('USD'); expect(bids[0].ad).to.contain(`alert('foo')`) @@ -620,6 +622,8 @@ describe('the rubicon adapter', () => { expect(bids[1].cpm).to.equal(0.811); expect(bids[1].ttl).to.equal(300); expect(bids[1].netRevenue).to.equal(false); + expect(bids[1].rubicon.advertiserId).to.equal(7); + expect(bids[1].rubicon.networkId).to.equal(8); expect(bids[1].creativeId).to.equal('crid-9'); expect(bids[1].currency).to.equal('USD'); expect(bids[1].ad).to.contain(`alert('foo')`) From 9cb9f2a66a1bf3ed9f8b9056ac4c7bb0d9c9306b Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 13 Feb 2018 11:29:16 -0500 Subject: [PATCH 0118/1594] Update test stack POC (#2014) * Added Gjirafa adapter * Add gjirafa adapter unit test * adapter update * New line * Requested changes * change hello_world.html to one bid * change hello_world.html to one bid * Update test stack and unit test fixes * remove unwanted code and sinon-ie * updated hello_world back to original * Added missing file * Updated unit tests to support other browsers * Uncomment unit test * Updated chrome and firefox versions * Remove yarn * Added mobile browsers back and removed infinite timeout * remove commented code * removed yarn from README * remove dead code and refactor * removed browser-cookies dep * use config api to reset and update temp test --- README.md | 17 +- browsers.json | 68 +- integrationExamples/gpt/hello_world.html | 4 - karma.conf.maker.js | 15 +- package.json | 7 +- src/userSync.js | 2 +- src/utils.js | 7 +- test/spec/AnalyticsAdapter_spec.js | 212 +- test/spec/auctionmanager_spec.js | 20 +- test/spec/modules/33acrossBidAdapter_spec.js | 8 +- .../adkernelAdnAnalyticsAdapter_spec.js | 14 +- .../modules/adkernelAdnBidAdapter_spec.js | 2 +- test/spec/modules/adkernelBidAdapter_spec.js | 4 +- .../modules/adomikAnalyticsAdapter_spec.js | 20 +- .../modules/adxcgAnalyticsAdapter_spec.js | 2 + test/spec/modules/appnexusBidAdapter_spec.js | 14 + test/spec/modules/eplanningBidAdapter_spec.js | 6 +- .../modules/improvedigitalBidAdapter_spec.js | 13 +- test/spec/modules/kargoBidAdapter_spec.js | 2 +- .../modules/nanointeractiveBidAdapter_spec.js | 2 +- .../modules/prebidServerBidAdapter_spec.js | 6 +- .../modules/pubwiseAnalyticsAdapter_spec.js | 19 + .../modules/roxotAnalyticsAdapter_spec.js | 11 + test/spec/modules/rubiconBidAdapter_spec.js | 24 +- test/spec/modules/s2sTesting_spec.js | 2 +- .../modules/serverbidServerBidAdapter_spec.js | 4 +- test/spec/modules/vidazooBidAdapter_spec.js | 4 +- test/spec/renderer_spec.js | 12 + test/spec/sizeMapping_spec.js | 2 +- test/spec/unit/core/adapterManager_spec.js | 167 +- test/spec/unit/core/bidderFactory_spec.js | 11 +- test/spec/unit/core/targeting_spec.js | 6 +- test/spec/unit/pbjs_api_spec.js | 193 +- test/spec/userSync_spec.js | 24 +- test/spec/utils_spec.js | 85 +- test/test_index.js | 5 + yarn.lock | 9030 ----------------- 37 files changed, 564 insertions(+), 9480 deletions(-) create mode 100644 test/test_index.js delete mode 100644 yarn.lock diff --git a/README.md b/README.md index 4bcf2213f8e..1ec83859b48 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,7 @@ Working examples can be found in [the developer docs](http://prebid.org/dev-docs $ git clone https://github.com/prebid/Prebid.js.git $ cd Prebid.js - $ yarn install - -Prebid supports the `yarn` npm client. This is an alternative to using `npm` for package management, though `npm install` will continue to work as before. - -For more info, see [the Yarn documentation](https://yarnpkg.com). + $ npm install *Note:* You need to have `NodeJS` 4.x or greater installed. @@ -60,11 +56,8 @@ For example, when running the serve command: `gulp serve --modules=openxBidAdapt Building with just these adapters will result in a smaller bundle which should allow your pages to load faster. **Build standalone prebid.js** -Prebid now supports the `yarn` npm client. This is an alternative to using `npm` for package management, though `npm` will continue to work as before. - -For more info about yarn see https://yarnpkg.com -- Clone the repo, run `yarn install` +- Clone the repo, run `npm install` - Then run the build: $ gulp build --modules=openxBidAdapter,rubiconBidAdapter,sovrnBidAdapter @@ -82,11 +75,11 @@ With `modules.json` containing the following ] ``` -**Build prebid.js using Yarn for bundling** +**Build prebid.js using npm for bundling** -In case you'd like to explicitly show that your project uses `prebid.js` and want a reproducible build, consider adding it as an `yarn` dependency. +In case you'd like to explicitly show that your project uses `prebid.js` and want a reproducible build, consider adding it as an `npm` dependency. -- Add `prebid.js` as a `yarn` dependency of your project: `yarn add prebid.js` +- Add `prebid.js` as a `npm` dependency of your project: `npm install prebid.js` - Run the `prebid.js` build under the `node_modules/prebid.js/` folder $ gulp build --modules=path/to/your/list-of-modules.json diff --git a/browsers.json b/browsers.json index 2dc6f1ddf90..ef3f28e95fa 100644 --- a/browsers.json +++ b/browsers.json @@ -1,9 +1,9 @@ { - "bs_ie_13_windows_10": { + "bs_ie_14_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "edge", - "browser_version": "13.0", + "browser_version": "14.0", "device": null, "os": "Windows" }, @@ -15,15 +15,15 @@ "device": null, "os": "Windows" }, - "bs_firefox_46_windows_10": { + "bs_firefox_56_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "firefox", - "browser_version": "46.0", + "browser_version": "56.0", "device": null, "os": "Windows" }, - "bs_chrome_51_windows_10": { + "bs_chrome_62_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", @@ -39,43 +39,35 @@ "device": null, "os": "Windows" }, - "bs_firefox_46_windows_8.1": { + "bs_firefox_56_windows_8.1": { "base": "BrowserStack", "os_version": "8.1", "browser": "firefox", - "browser_version": "46.0", + "browser_version": "56.0", "device": null, "os": "Windows" }, - "bs_chrome_51_windows_8.1": { + "bs_chrome_62_windows_8.1": { "base": "BrowserStack", "os_version": "8.1", "browser": "chrome", - "browser_version": "51.0", - "device": null, - "os": "Windows" - }, - "bs_ie_10_windows_8": { - "base": "BrowserStack", - "os_version": "8", - "browser": "ie", - "browser_version": "10.0", + "browser_version": "62.0", "device": null, "os": "Windows" }, - "bs_firefox_46_windows_8": { + "bs_firefox_56_windows_8": { "base": "BrowserStack", "os_version": "8", "browser": "firefox", - "browser_version": "46.0", + "browser_version": "56.0", "device": null, "os": "Windows" }, - "bs_chrome_51_windows_8": { + "bs_chrome_62_windows_8": { "base": "BrowserStack", "os_version": "8", "browser": "chrome", - "browser_version": "51.0", + "browser_version": "62.0", "device": null, "os": "Windows" }, @@ -87,27 +79,19 @@ "device": null, "os": "Windows" }, - "bs_ie_10_windows_7": { - "base": "BrowserStack", - "os_version": "7", - "browser": "ie", - "browser_version": "10.0", - "device": null, - "os": "Windows" - }, - "bs_firefox_46_windows_7": { + "bs_firefox_56_windows_7": { "base": "BrowserStack", "os_version": "7", "browser": "firefox", - "browser_version": "46.0", + "browser_version": "56.0", "device": null, "os": "Windows" }, - "bs_chrome_51_windows_7": { + "bs_chrome_62_windows_7": { "base": "BrowserStack", "os_version": "7", "browser": "chrome", - "browser_version": "51.0", + "browser_version": "62.0", "device": null, "os": "Windows" }, @@ -127,19 +111,19 @@ "device": null, "os": "OS X" }, - "bs_firefox_46_mac_elcapitan": { + "bs_firefox_56_mac_elcapitan": { "base": "BrowserStack", "os_version": "El Capitan", "browser": "firefox", - "browser_version": "46.0", + "browser_version": "56.0", "device": null, "os": "OS X" }, - "bs_chrome_51_mac_elcapitan": { + "bs_chrome_62_mac_elcapitan": { "base": "BrowserStack", "os_version": "El Capitan", "browser": "chrome", - "browser_version": "51.0", + "browser_version": "62.0", "device": null, "os": "OS X" }, @@ -151,15 +135,15 @@ "device": null, "os": "OS X" }, - "bs_firefox_46_mac_yosemite": { + "bs_firefox_56_mac_yosemite": { "base": "BrowserStack", "os_version": "Yosemite", "browser": "firefox", - "browser_version": "46.0", + "browser_version": "56.0", "device": null, "os": "OS X" }, - "bs_chrome_51_mac_yosemite": { + "bs_chrome_62_mac_yosemite": { "base": "BrowserStack", "os_version": "Yosemite", "browser": "chrome", @@ -175,11 +159,11 @@ "device": null, "os": "OS X" }, - "bs_firefox_46_mac_mavericks": { + "bs_firefox_56_mac_mavericks": { "base": "BrowserStack", "os_version": "Mavericks", "browser": "firefox", - "browser_version": "46.0", + "browser_version": "56.0", "device": null, "os": "OS X" }, diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index aa4bf5ea782..be181db21b2 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -1,14 +1,10 @@ diff --git a/karma.conf.maker.js b/karma.conf.maker.js index d2b1d49e081..6afb5e4cf13 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -35,10 +35,11 @@ function newPluginsArray(browserstack) { 'karma-expect', 'karma-mocha', 'karma-requirejs', - 'karma-sinon-ie', + 'karma-sinon', 'karma-sourcemap-loader', 'karma-spec-reporter', 'karma-webpack', + 'karma-mocha-reporter' ]; if (browserstack) { plugins.push('karma-browserstack-launcher'); @@ -58,6 +59,8 @@ function setReporters(karmaConf, codeCoverage, browserstack) { if (browserstack) { karmaConf.reporters = ['spec']; karmaConf.specReporter = { + maxLogLines: 100, + suppressErrorSummary: false, suppressSkipped: false, suppressPassed: true }; @@ -95,10 +98,8 @@ function setBrowsers(karmaConf, browserstack) { module.exports = function(codeCoverage, browserstack, watchMode, file) { var webpackConfig = newWebpackConfig(codeCoverage); var plugins = newPluginsArray(browserstack); - var files = [ - 'test/helpers/prebidGlobal.js', - file ? file : 'test/**/*_spec.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) { @@ -113,7 +114,6 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) { webpackMiddleware: { noInfo: true }, - // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['es5-shim', 'mocha', 'expect', 'sinon'], @@ -123,8 +123,7 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { - 'test/**/*_spec.js': ['webpack', 'sourcemap'], - 'test/helpers/prebidGlobal.js': ['webpack', 'sourcemap'] + 'test/test_index.js': ['webpack', 'sourcemap'] }, // web server port diff --git a/package.json b/package.json index 839b6113ff1..a3d55389d56 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", "json-loader": "^0.5.1", - "karma": "^1.7.0", + "karma": "^2.0.0", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.0.1", "karma-chai": "^0.1.0", @@ -76,12 +76,13 @@ "karma-firefox-launcher": "^1.0.1", "karma-ie-launcher": "^1.0.0", "karma-mocha": "^1.3.0", + "karma-mocha-reporter": "^2.2.5", "karma-opera-launcher": "^1.0.0", "karma-requirejs": "^1.1.0", "karma-safari-launcher": "^1.0.0", "karma-sauce-launcher": "^1.1.0", "karma-script-launcher": "^1.0.0", - "karma-sinon-ie": "^2.0.0", + "karma-sinon": "^1.0.5", "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "^0.0.31", "karma-webpack": "^2.0.3", @@ -95,7 +96,7 @@ "proxyquire": "^1.7.10", "querystringify": "0.0.3", "requirejs": "^2.1.20", - "sinon": "^1.12.1", + "sinon": "^4.1.3", "string-replace-webpack-plugin": "^0.1.3", "through2": "^2.0.3", "uglify-js": "^2.8.10", diff --git a/src/userSync.js b/src/userSync.js index 939c42c28a0..56641b5cb8e 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -165,7 +165,7 @@ export function newUserSync(userSyncDependencies) { */ publicApi.syncUsers = (timeout = 0) => { if (timeout) { - return window.setTimeout(fireSyncs, Number(timeout)); + return setTimeout(fireSyncs, Number(timeout)); } fireSyncs(); }; diff --git a/src/utils.js b/src/utils.js index 8735f918497..7126f293c02 100644 --- a/src/utils.js +++ b/src/utils.js @@ -671,10 +671,15 @@ export function timestamp() { return new Date().getTime(); } -export function cookiesAreEnabled() { +export function checkCookieSupport() { if (window.navigator.cookieEnabled || !!document.cookie.length) { return true; } +} +export function cookiesAreEnabled() { + if (exports.checkCookieSupport()) { + return true; + } window.document.cookie = 'prebid.cookieTest'; return window.document.cookie.indexOf('prebid.cookieTest') != -1; } diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 3eeb5a9efee..92710d47568 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -21,152 +21,152 @@ FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics GIVEN a global object \`window['testGlobal']\` AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - describe(`WHEN an event occurs that is to be tracked\n`, () => { - const eventType = BID_REQUESTED; - const args = { some: 'data' }; - const adapter = new AnalyticsAdapter(config); + describe(`WHEN an event occurs that is to be tracked\n`, () => { + const eventType = BID_REQUESTED; + const args = { some: 'data' }; + const adapter = new AnalyticsAdapter(config); + var spyTestGlobal = sinon.spy(window, config.global); + + adapter.track({ eventType, args }); + + it(`THEN should call \`window.${config.global}\` function\n`, () => { + assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); + assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + }); + window[config.global].restore(); + }); + + describe(`WHEN an event occurs before tracking library is available\n`, () => { + const eventType = BID_RESPONSE; + const args = { wat: 'wot' }; + const adapter = new AnalyticsAdapter(config); + + window[config.global] = null; + events.emit(BID_RESPONSE, args); + + describe(`AND the adapter is then enabled\n`, () => { + window[config.global] = () => {}; + var spyTestGlobal = sinon.spy(window, config.global); - adapter.track({ eventType, args }); + adapter.enableAnalytics(); - it(`THEN should call \`window.${config.global}\` function\n`, () => { + it(`THEN should queue the event first and then track it\n`, () => { assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); }); + + adapter.disableAnalytics(); window[config.global].restore(); }); + }); - describe(`WHEN an event occurs before tracking library is available\n`, () => { - const eventType = BID_RESPONSE; - const args = { wat: 'wot' }; - const adapter = new AnalyticsAdapter(config); - - window[config.global] = null; - events.emit(BID_RESPONSE, args); - - describe(`AND the adapter is then enabled\n`, () => { - window[config.global] = () => {}; + describe(`WHEN an event occurs after enable analytics\n`, () => { + var spyTestGlobal, + adapter; - var spyTestGlobal = sinon.spy(window, config.global); + beforeEach(() => { + adapter = new AnalyticsAdapter(config); + spyTestGlobal = sinon.spy(window, config.global); - adapter.enableAnalytics(); + sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests + }); - it(`THEN should queue the event first and then track it\n`, () => { - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); - }); + afterEach(() => { + adapter.disableAnalytics(); + window[config.global].restore(); - adapter.disableAnalytics(); - window[config.global].restore(); - }); + events.getEvents.restore(); }); - describe(`WHEN an event occurs after enable analytics\n`, () => { - var spyTestGlobal, - adapter; + it('SHOULD call global when a bidWon event occurs', () => { + const eventType = BID_WON; + const args = { more: 'info' }; - beforeEach(() => { - adapter = new AnalyticsAdapter(config); - spyTestGlobal = sinon.spy(window, config.global); + adapter.enableAnalytics(); + events.emit(eventType, args); - sinon.stub(events, 'getEvents', () => []); // these tests shouldn't be affected by previous tests - }); + assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); + assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + }); - afterEach(() => { - adapter.disableAnalytics(); - window[config.global].restore(); + it('SHOULD call global when a bidRequest event occurs', () => { + const eventType = BID_REQUESTED; + const args = { call: 'request' }; - events.getEvents.restore(); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidWon event occurs', () => { - const eventType = BID_WON; - const args = { more: 'info' }; + assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); + assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidResponse event occurs', () => { + const eventType = BID_RESPONSE; + const args = { call: 'response' }; - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidRequest event occurs', () => { - const eventType = BID_REQUESTED; - const args = { call: 'request' }; + assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); + assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD call global when a bidTimeout event occurs', () => { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); - }); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidResponse event occurs', () => { - const eventType = BID_RESPONSE; - const args = { call: 'response' }; + assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); + assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', () => { + const eventType = BID_TIMEOUT; + const args = { call: 'timeout' }; - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); - }); + events.emit(eventType, args); + adapter.enableAnalytics(); + events.emit(eventType, args); - it('SHOULD call global when a bidTimeout event occurs', () => { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; + assert(spyTestGlobal.calledOnce === true); + }); - adapter.enableAnalytics(); - events.emit(eventType, args); + describe(`AND sampling is enabled\n`, () => { + const eventType = BID_WON; + const args = { more: 'info' }; - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + beforeEach(() => { + sinon.stub(Math, 'random').returns(0.5); }); - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', () => { - const eventType = BID_TIMEOUT; - const args = { call: 'timeout' }; - - events.emit(eventType, args); - adapter.enableAnalytics(); - events.emit(eventType, args); - - assert(spyTestGlobal.calledOnce === true); + afterEach(() => { + Math.random.restore(); }); - describe(`AND sampling is enabled\n`, () => { - const eventType = BID_WON; - const args = { more: 'info' }; - - beforeEach(() => { - sinon.stub(Math, 'random', () => 0.5); - }); - - afterEach(() => { - Math.random.restore(); + it(`THEN should enable analytics when random number is in sample range`, () => { + adapter.enableAnalytics({ + options: { + sampling: 0.75 + } }); + events.emit(eventType, args); - it(`THEN should enable analytics when random number is in sample range`, () => { - adapter.enableAnalytics({ - options: { - sampling: 0.75 - } - }); - events.emit(eventType, args); + assert(spyTestGlobal.called === true); + }); - assert(spyTestGlobal.called === true); + it(`THEN should disable analytics when random number is outside sample range`, () => { + adapter.enableAnalytics({ + options: { + sampling: 0.25 + } }); + events.emit(eventType, args); - it(`THEN should disable analytics when random number is outside sample range`, () => { - adapter.enableAnalytics({ - options: { - sampling: 0.25 - } - }); - events.emit(eventType, args); - - assert(spyTestGlobal.called === false); - }); + assert(spyTestGlobal.called === false); }); }); }); +}); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index c73679c5b8c..167d05f7bef 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -8,6 +8,7 @@ import { config } from 'src/config'; import * as store from 'src/videoCache'; import * as ajaxLib from 'src/ajax'; +const adloader = require('../../src/adloader'); var assert = require('assert'); /* use this method to test individual files instead of the whole prebid.js project */ @@ -24,6 +25,16 @@ function timestamp() { } describe('auctionmanager.js', function () { + let xhr; + + before(() => { + xhr = sinon.useFakeXMLHttpRequest(); + }); + + after(() => { + xhr.restore(); + }); + describe('getKeyValueTargetingPairs', function () { var bid = {}; var bidPriceCpm = 5.578; @@ -506,7 +517,7 @@ describe('auctionmanager.js', function () { makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); makeRequestsStub.returns(bidRequests); - ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(function() { return function(url, callback) { const fakeResponse = sinon.stub(); fakeResponse.returns('headerContent'); @@ -521,6 +532,7 @@ describe('auctionmanager.js', function () { }); describe('when auction timeout is 3000', () => { + let loadScriptStub; beforeEach(() => { adUnits = [{ code: 'adUnit-code', @@ -540,10 +552,14 @@ describe('auctionmanager.js', function () { interpretResponse: sinon.stub(), getUserSyncs: sinon.stub() }; + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); }); afterEach(() => { auctionModule.newAuction.restore(); + loadScriptStub.restore(); }); it('should return proper price bucket increments for dense mode when cpm is in range 0-3', () => { @@ -741,7 +757,7 @@ describe('auctionmanager.js', function () { makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); makeRequestsStub.returns(bidRequests); - ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(function() { return function(url, callback) { const fakeResponse = sinon.stub(); fakeResponse.returns('headerContent'); diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 9a322821b13..a81c92b4a48 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -155,7 +155,7 @@ describe('33acrossBidAdapter:', function () { }); it('returns corresponding test server requests for each valid bidRequest', function() { - this.sandbox.stub(config, 'getConfig', () => { + this.sandbox.stub(config, 'getConfig').callsFake(() => { return { 'url': 'https://foo.com/hb/' } @@ -203,8 +203,8 @@ describe('33acrossBidAdapter:', function () { expect(builtServerRequests.length).to.equal(1); }); - it('returns corresponding test server requests for each valid test bidRequest', function() { - this.sandbox.stub(config, 'getConfig', () => { + it('returns corresponding test server requests for each valid bidRequest', function() { + this.sandbox.stub(config, 'getConfig').callsFake(() => { return { 'url': 'https://foo.com/hb/' } @@ -424,7 +424,7 @@ describe('33acrossBidAdapter:', function () { it('via the test endpoint', function() { const spy = this.sandbox.spy(userSync, 'registerSync'); - this.sandbox.stub(config, 'getConfig', () => { + this.sandbox.stub(config, 'getConfig').callsFake(() => { return { 'syncUrl': 'https://foo.com/deb/v2?m=xch' } diff --git a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js index 282bd62403a..33c2cfc1de0 100644 --- a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js +++ b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js @@ -1,10 +1,11 @@ import analyticsAdapter, {ExpiringQueue, getUmtSource, storage} from 'modules/adkernelAdnAnalyticsAdapter'; import {expect} from 'chai'; import adaptermanager from 'src/adaptermanager'; -import * as events from 'src/events'; import * as ajax from 'src/ajax'; import CONSTANTS from 'src/constants.json'; +const events = require('../../../src/events'); + const DIRECT = { source: '(direct)', medium: '(direct)', @@ -41,6 +42,7 @@ describe('', () => { after(() => { sandbox.restore(); + analyticsAdapter.disableAnalytics(); }); describe('UTM source parser', () => { @@ -191,6 +193,16 @@ describe('', () => { timer = sandbox.useFakeTimers(0); }); + beforeEach(() => { + sandbox.stub(events, 'getEvents').callsFake(() => { + return [] + }); + }); + + afterEach(() => { + events.getEvents.restore(); + }); + it('should be configurable', () => { adaptermanager.registerAnalyticsAdapter({ code: 'adkernelAdn', diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index 3ba4012bd0b..88b5dc0d5ee 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -130,7 +130,7 @@ describe('AdkernelAdn adapter', () => { let tagRequest; before(() => { - let mock = sinon.stub(utils, 'getTopWindowLocation', () => { + let mock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => { return { protocol: 'https:', hostname: 'example.com', diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index 717027ca4ee..b85c2a5b61b 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -130,14 +130,14 @@ describe('Adkernel adapter', () => { describe('banner request building', () => { let bidRequest; before(() => { - let wmock = sinon.stub(utils, 'getTopWindowLocation', () => ({ + let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => ({ protocol: 'https:', hostname: 'example.com', host: 'example.com', pathname: '/index.html', href: 'https://example.com/index.html' })); - let dntmock = sinon.stub(utils, 'getDNT', () => true); + let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => true); let request = spec.buildRequests([bid1_zone1])[0]; bidRequest = JSON.parse(request.data.r); wmock.restore(); diff --git a/test/spec/modules/adomikAnalyticsAdapter_spec.js b/test/spec/modules/adomikAnalyticsAdapter_spec.js index 37a5b46a8a2..59e6dadec96 100644 --- a/test/spec/modules/adomikAnalyticsAdapter_spec.js +++ b/test/spec/modules/adomikAnalyticsAdapter_spec.js @@ -5,16 +5,26 @@ let adaptermanager = require('src/adaptermanager'); let constants = require('src/constants.json'); describe('Adomik Prebid Analytic', function () { + let sendEventStub; + let sendWonEventStub; + describe('enableAnalytics', function () { beforeEach(() => { sinon.spy(adomikAnalytics, 'track'); - sinon.spy(adomikAnalytics, 'sendTypedEvent'); - sinon.spy(adomikAnalytics, 'sendWonEvent'); + sendEventStub = sinon.stub(adomikAnalytics, 'sendTypedEvent'); + sendWonEventStub = sinon.stub(adomikAnalytics, 'sendWonEvent'); + sinon.stub(events, 'getEvents').returns([]); }); afterEach(() => { adomikAnalytics.track.restore(); - adomikAnalytics.sendTypedEvent.restore(); + sendEventStub.restore(); + sendWonEventStub.restore(); + events.getEvents.restore(); + }); + + after(() => { + adomikAnalytics.disableAnalytics(); }); it('should catch all events', function (done) { @@ -114,8 +124,8 @@ describe('Adomik Prebid Analytic', function () { events.emit(constants.EVENTS.AUCTION_END, {}); setTimeout(function() { - sinon.assert.callCount(adomikAnalytics.sendTypedEvent, 1); - sinon.assert.callCount(adomikAnalytics.sendWonEvent, 1); + sinon.assert.callCount(sendEventStub, 1); + sinon.assert.callCount(sendWonEventStub, 1); done(); }, 3000); diff --git a/test/spec/modules/adxcgAnalyticsAdapter_spec.js b/test/spec/modules/adxcgAnalyticsAdapter_spec.js index 46b50214873..e90e7a1f8de 100644 --- a/test/spec/modules/adxcgAnalyticsAdapter_spec.js +++ b/test/spec/modules/adxcgAnalyticsAdapter_spec.js @@ -12,10 +12,12 @@ describe('adxcg analytics adapter', () => { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); + sinon.stub(events, 'getEvents').returns([]); }); afterEach(() => { xhr.restore(); + events.getEvents.restore(); }); describe('track', () => { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 2d3d2cb1745..88e3383b709 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -3,6 +3,8 @@ import { spec } from 'modules/appnexusBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; +const adloader = require('../../../src/adloader'); + const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; describe('AppNexusAdapter', () => { @@ -307,6 +309,18 @@ describe('AppNexusAdapter', () => { }) describe('interpretResponse', () => { + let loadScriptStub; + + beforeEach(() => { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); + + afterEach(() => { + loadScriptStub.restore(); + }); + let response = { 'version': '3.0.0', 'tags': [ diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js index a2583d79dc2..68b9e1b263f 100644 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ b/test/spec/modules/eplanningBidAdapter_spec.js @@ -252,11 +252,11 @@ describe('E-Planning Adapter', () => { it('should return fr parameter when there is a referrer', () => { const referrer = 'thisisafakereferrer'; - const stubGetReferrer = sinon.stub(utils, 'getTopWindowReferrer').returns(referrer); - after(() => stubGetReferrer.restore()); - + const stubGetReferrer = sinon.stub(utils, 'getTopWindowReferrer'); + stubGetReferrer.returns(referrer); const fr = spec.buildRequests(bidRequests).data.fr; expect(fr).to.equal(referrer); + stubGetReferrer.restore() }); it('should return the testing url when the request has the t parameter', () => { diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 2725a6ad101..cd68418d6c7 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -150,6 +150,14 @@ describe('Improve Digital Adapter Tests', function () { }); describe('interpretResponse', () => { + let registerSyncStub; + beforeEach(() => { + registerSyncStub = sinon.stub(userSync, 'registerSync'); + }); + + afterEach(() => { + registerSyncStub.restore(); + }); const serverResponse = { 'body': { 'id': '687a06c541d8d1', @@ -246,10 +254,9 @@ describe('Improve Digital Adapter Tests', function () { }); it('should register user syncs', () => { - const registerSyncSpy = sinon.spy(userSync, 'registerSync'); const bids = spec.interpretResponse(serverResponse); - expect(registerSyncSpy.withArgs('image', 'improvedigital', 'http://link1').calledOnce).to.equal(true); - expect(registerSyncSpy.withArgs('image', 'improvedigital', 'http://link2').calledOnce).to.equal(true); + expect(registerSyncStub.withArgs('image', 'improvedigital', 'http://link1').calledOnce).to.equal(true); + expect(registerSyncStub.withArgs('image', 'improvedigital', 'http://link2').calledOnce).to.equal(true); }); it('should set dealId correctly', () => { diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 87c16dabfae..0e896b4fc04 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -36,7 +36,7 @@ describe('kargo adapter tests', function () { var bids, cookies = [], localStorageItems = []; beforeEach(() => { - sandbox.stub(config, 'getConfig', function(key) { + sandbox.stub(config, 'getConfig').callsFake(function(key) { if (key === 'currency') { return 'USD'; } diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index 14927d929d3..cafe7bf2799 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -79,7 +79,7 @@ describe('nanointeractive adapter tests', function () { expect(nanoBidAdapter.isBidRequestValid(getBid(false))).to.equal(false); }); it('Test buildRequests()', function () { - let stub = sinon.stub(utils, 'getOrigin', () => 'http://localhost'); + let stub = sinon.stub(utils, 'getOrigin').callsFake(() => 'http://localhost'); let request = nanoBidAdapter.buildRequests([getBid(true)]); expect(request.method).to.equal('POST'); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index b719171989d..f403b886b98 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -216,8 +216,8 @@ describe('S2S Adapter', () => { beforeEach(() => adapter = new Adapter()); afterEach(() => { - addBidResponse.reset(); - done.reset(); + addBidResponse.resetHistory(); + done.resetHistory(); }); describe('request function', () => { @@ -393,7 +393,7 @@ describe('S2S Adapter', () => { let rubiconAdapter = { registerSyncs: sinon.spy() }; - sinon.stub(adapterManager, 'getBidAdapter', () => rubiconAdapter); + sinon.stub(adapterManager, 'getBidAdapter').callsFake(() => rubiconAdapter); server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); diff --git a/test/spec/modules/pubwiseAnalyticsAdapter_spec.js b/test/spec/modules/pubwiseAnalyticsAdapter_spec.js index 4c3919172d8..ffb8d3c0570 100644 --- a/test/spec/modules/pubwiseAnalyticsAdapter_spec.js +++ b/test/spec/modules/pubwiseAnalyticsAdapter_spec.js @@ -4,7 +4,26 @@ let adaptermanager = require('src/adaptermanager'); let constants = require('src/constants.json'); describe('PubWise Prebid Analytics', function () { + let xhr; + + before(() => { + xhr = sinon.useFakeXMLHttpRequest(); + }); + + after(() => { + xhr.restore(); + pubwiseAnalytics.disableAnalytics(); + }); + describe('enableAnalytics', function () { + beforeEach(() => { + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(() => { + events.getEvents.restore(); + }); + it('should catch all events', function () { sinon.spy(pubwiseAnalytics, 'track'); diff --git a/test/spec/modules/roxotAnalyticsAdapter_spec.js b/test/spec/modules/roxotAnalyticsAdapter_spec.js index 81faf164434..f2db77892f6 100644 --- a/test/spec/modules/roxotAnalyticsAdapter_spec.js +++ b/test/spec/modules/roxotAnalyticsAdapter_spec.js @@ -5,13 +5,24 @@ let adaptermanager = require('src/adaptermanager'); let constants = require('src/constants.json'); describe('Roxot Prebid Analytic', function () { + let xhr; + before(() => { + xhr = sinon.useFakeXMLHttpRequest(); + }) + after(() => { + roxotAnalytic.disableAnalytics(); + xhr.restore(); + }); + describe('enableAnalytics', function () { beforeEach(() => { sinon.spy(roxotAnalytic, 'track'); + sinon.stub(events, 'getEvents').returns([]); }); afterEach(() => { roxotAnalytic.track.restore(); + events.getEvents.restore(); }); it('should catch all events', function () { adaptermanager.registerAnalyticsAdapter({ diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index fedffced081..0c6c8205a86 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -119,7 +119,7 @@ describe('the rubicon adapter', () => { describe('for requests', () => { describe('to fastlane', () => { it('should make a well-formed request objects', () => { - sandbox.stub(Math, 'random', () => 0.1); + sandbox.stub(Math, 'random').returns(0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -202,7 +202,7 @@ describe('the rubicon adapter', () => { window.DigiTrust = { getUser: function() {} }; - sandbox.stub(window.DigiTrust, 'getUser', () => + sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => ({ success: true, identity: { @@ -247,7 +247,7 @@ describe('the rubicon adapter', () => { window.DigiTrust = { getUser: function() {} }; - sandbox.stub(window.DigiTrust, 'getUser', () => + sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => ({ success: true, identity: { @@ -275,7 +275,7 @@ describe('the rubicon adapter', () => { window.DigiTrust = { getUser: function() {} }; - sandbox.stub(window.DigiTrust, 'getUser', () => + sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => ({ success: false, identity: { @@ -312,7 +312,7 @@ describe('the rubicon adapter', () => { }); it('should send digiTrustId config params', () => { - sandbox.stub(config, 'getConfig', (key) => { + sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { success: true, @@ -345,7 +345,7 @@ describe('the rubicon adapter', () => { }); it('should not send digiTrustId config params due to optout', () => { - sandbox.stub(config, 'getConfig', (key) => { + sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { success: true, @@ -374,7 +374,7 @@ describe('the rubicon adapter', () => { }); it('should not send digiTrustId config params due to failure', () => { - sandbox.stub(config, 'getConfig', (key) => { + sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { success: false, @@ -403,7 +403,7 @@ describe('the rubicon adapter', () => { }); it('should not send digiTrustId config params if they do not exist', () => { - sandbox.stub(config, 'getConfig', (key) => { + sandbox.stub(config, 'getConfig').callsFake((key) => { var config = {}; return config[key]; }); @@ -428,7 +428,7 @@ describe('the rubicon adapter', () => { it('should make a well-formed video request', () => { createVideoBidderRequest(); - sandbox.stub(Date, 'now', () => + sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 ); @@ -489,7 +489,7 @@ describe('the rubicon adapter', () => { it('should allow a floor price override', () => { createVideoBidderRequest(); - sandbox.stub(Date, 'now', () => + sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 ); @@ -508,7 +508,7 @@ describe('the rubicon adapter', () => { it('should not validate bid request when no video object is passed in', () => { createVideoBidderRequestNoVideo(); - sandbox.stub(Date, 'now', () => + sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 ); @@ -521,7 +521,7 @@ describe('the rubicon adapter', () => { it('should get size from bid.sizes too', () => { createVideoBidderRequestNoPlayer(); - sandbox.stub(Date, 'now', () => + sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 ); diff --git a/test/spec/modules/s2sTesting_spec.js b/test/spec/modules/s2sTesting_spec.js index 845947a0b38..33552011aa1 100644 --- a/test/spec/modules/s2sTesting_spec.js +++ b/test/spec/modules/s2sTesting_spec.js @@ -13,7 +13,7 @@ describe('s2sTesting', function () { let randomNumber = 0; beforeEach(() => { - mathRandomStub = sinon.stub(Math, 'random', () => { return randomNumber; }); + mathRandomStub = sinon.stub(Math, 'random').callsFake(() => { return randomNumber; }); }); afterEach(() => { diff --git a/test/spec/modules/serverbidServerBidAdapter_spec.js b/test/spec/modules/serverbidServerBidAdapter_spec.js index 7745d0e407c..29d35b921d6 100644 --- a/test/spec/modules/serverbidServerBidAdapter_spec.js +++ b/test/spec/modules/serverbidServerBidAdapter_spec.js @@ -192,8 +192,8 @@ describe('ServerBid S2S Adapter', () => { beforeEach(() => adapter = new Adapter()); afterEach(() => { - addBidResponse.reset(); - done.reset(); + addBidResponse.resetHistory(); + done.resetHistory(); }); describe('request function', () => { diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index a4f8d0dfdb2..1f154f0a379 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -100,8 +100,8 @@ describe('VidazooBidAdapter', () => { let sandbox; before(() => { sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getTopWindowUrl', () => 'http://www.greatsite.com'); - sandbox.stub(Date, 'now', () => 1000); + sandbox.stub(utils, 'getTopWindowUrl').returns('http://www.greatsite.com'); + sandbox.stub(Date, 'now').returns(1000); }); it('should build request for each size', () => { diff --git a/test/spec/renderer_spec.js b/test/spec/renderer_spec.js index 4761a914bb8..a511a1b214c 100644 --- a/test/spec/renderer_spec.js +++ b/test/spec/renderer_spec.js @@ -1,5 +1,6 @@ import { expect } from 'chai'; import { Renderer } from 'src/Renderer'; +const adloader = require('../../src/adloader'); describe('Renderer: A renderer installed on a bid response', () => { let testRenderer1; @@ -7,7 +8,13 @@ describe('Renderer: A renderer installed on a bid response', () => { let spyRenderFn; let spyEventHandler; + let loadScriptStub; + beforeEach(() => { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + testRenderer1 = Renderer.install({ url: 'https://httpbin.org/post', config: { test: 'config1' }, @@ -23,6 +30,10 @@ describe('Renderer: A renderer installed on a bid response', () => { spyEventHandler = sinon.spy(); }); + afterEach(() => { + loadScriptStub.restore(); + }); + it('is an instance of Renderer', () => { expect(testRenderer1 instanceof Renderer).to.equal(true); }); @@ -59,6 +70,7 @@ describe('Renderer: A renderer installed on a bid response', () => { }); it('pushes commands to queue if renderer is not loaded', () => { + testRenderer1.loaded = false; testRenderer1.push(spyRenderFn); expect(testRenderer1.cmd.length).to.equal(1); diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index 24a6063cf7d..b131c9c964c 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -53,7 +53,7 @@ describe('sizeMapping', () => { matchMediaOverride = {matches: false}; - sandbox.stub(window, 'matchMedia', (...args) => { + sandbox.stub(window, 'matchMedia').callsFake((...args) => { if (typeof matchMediaOverride === 'function') { return matchMediaOverride.apply(window, args); } diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index bba404448a0..824d66305b8 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -11,6 +11,7 @@ import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; var s2sTesting = require('../../../../modules/s2sTesting'); var events = require('../../../../src/events'); +const adloader = require('../../../../src/adloader'); const CONFIG = { enabled: true, @@ -33,17 +34,72 @@ var appnexusAdapterMock = { callBids: sinon.stub() }; +var rubiconAdapterMock = { + bidder: 'rubicon', + callBids: sinon.stub() +}; +let loadScriptStub; + describe('adapterManager tests', () => { + let orgAppnexusAdapter; + let orgAdequantAdapter; + let orgPrebidServerAdapter; + let orgRubiconAdapter; + before(() => { + orgAppnexusAdapter = AdapterManager.bidderRegistry['appnexus']; + orgAdequantAdapter = AdapterManager.bidderRegistry['adequant']; + orgPrebidServerAdapter = AdapterManager.bidderRegistry['prebidServer']; + orgRubiconAdapter = AdapterManager.bidderRegistry['rubicon']; + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); + + after(() => { + AdapterManager.bidderRegistry['appnexus'] = orgAppnexusAdapter; + AdapterManager.bidderRegistry['adequant'] = orgAdequantAdapter; + AdapterManager.bidderRegistry['prebidServer'] = orgPrebidServerAdapter; + AdapterManager.bidderRegistry['rubicon'] = orgRubiconAdapter; + loadScriptStub.restore(); + config.setConfig({s2sConfig: { enabled: false }}); + }); + describe('callBids', () => { + before(() => { + config.setConfig({s2sConfig: { enabled: false }}); + }); + beforeEach(() => { sinon.stub(utils, 'logError'); + appnexusAdapterMock.callBids.reset(); + AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; }); afterEach(() => { utils.logError.restore(); + delete AdapterManager.bidderRegistry['appnexus']; }); it('should log an error if a bidder is used that does not exist', () => { + const adUnits = [{ + code: 'adUnit-code', + sizes: [[728, 90]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}}, + {bidder: 'fakeBidder', params: {placementId: 'id'}} + ] + }]; + + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); + sinon.assert.called(utils.logError); + }); + + it('should emit BID_REQUESTED event', () => { + // function to count BID_REQUESTED events + let cnt = 0; + let count = () => cnt++; + events.on(CONSTANTS.EVENTS.BID_REQUESTED, count); let bidRequests = [{ 'bidderCode': 'appnexus', 'auctionId': '1863e370099523', @@ -65,49 +121,19 @@ describe('adapterManager tests', () => { 'status': 1, 'transactionId': 'fsafsa' }, - { - 'bidder': 'fakeBidder', - 'params': { - 'placementId': '4799418' - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '4dccdc37746135', - 'bidderRequestId': '2946b569352ef2', - 'auctionId': '1863e370099523', - 'startTime': 1462918897463, - 'status': 1, - 'transactionId': 'fsafsa' - } ], 'start': 1462918897460 }]; - const adUnits = [{ + + let adUnits = [{ code: 'adUnit-code', bids: [ {bidder: 'appnexus', params: {placementId: 'id'}}, - {bidder: 'fakeBidder', params: {placementId: 'id'}} ] }]; - - AdapterManager.callBids(adUnits, bidRequests); - - sinon.assert.called(utils.logError); - }); - - it('should emit BID_REQUESTED event', () => { - // function to count BID_REQUESTED events - let cnt = 0; - let count = () => cnt++; - events.on(CONSTANTS.EVENTS.BID_REQUESTED, count); - AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; - let adUnits = getAdUnits(); - let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(1); sinon.assert.calledOnce(appnexusAdapterMock.callBids); - appnexusAdapterMock.callBids.reset(); - delete AdapterManager.bidderRegistry['appnexus']; events.off(CONSTANTS.EVENTS.BID_REQUESTED, count); }); }); @@ -116,7 +142,6 @@ describe('adapterManager tests', () => { beforeEach(() => { config.setConfig({s2sConfig: CONFIG}); AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; - prebidServerAdapterMock.callBids.reset(); }); @@ -435,6 +460,7 @@ describe('adapterManager tests', () => { let cnt, count = () => cnt++; beforeEach(() => { + prebidServerAdapterMock.callBids.reset(); cnt = 0; events.on(CONSTANTS.EVENTS.BID_REQUESTED, count); }); @@ -444,7 +470,10 @@ describe('adapterManager tests', () => { }); it('should fire for s2s requests', () => { - let adUnits = getAdUnits(); + let adUnits = utils.deepClone(getAdUnits()).map(adUnit => { + adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus'], bid.bidder)); + return adUnit; + }) let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(1); @@ -453,7 +482,10 @@ describe('adapterManager tests', () => { it('should fire for simultaneous s2s and client requests', () => { AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; - let adUnits = getAdUnits(); + let adUnits = utils.deepClone(getAdUnits()).map(adUnit => { + adUnit.bids = adUnit.bids.filter(bid => includes(['adequant', 'appnexus'], bid.bidder)); + return adUnit; + }) let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(2); @@ -466,14 +498,21 @@ describe('adapterManager tests', () => { }); // end s2s tests describe('s2sTesting', () => { + let doneStub = sinon.stub(); + let ajaxStub = sinon.stub(); + function getTestAdUnits() { // copy adUnits - return JSON.parse(JSON.stringify(getAdUnits())); + // return JSON.parse(JSON.stringify(getAdUnits())); + return utils.deepClone(getAdUnits()).map(adUnit => { + adUnit.bids = adUnit.bids.filter(bid => includes(['adequant', 'appnexus', 'rubicon'], bid.bidder)); + return adUnit; + }) } function callBids(adUnits = getTestAdUnits()) { let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); - AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); + AdapterManager.callBids(adUnits, bidRequests, doneStub, ajaxStub); } function checkServerCalled(numAdUnits, numBids) { @@ -504,12 +543,14 @@ describe('adapterManager tests', () => { AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; + AdapterManager.bidderRegistry['rubicon'] = rubiconAdapterMock; stubGetSourceBidderMap = sinon.stub(s2sTesting, 'getSourceBidderMap'); prebidServerAdapterMock.callBids.reset(); adequantAdapterMock.callBids.reset(); appnexusAdapterMock.callBids.reset(); + rubiconAdapterMock.callBids.reset(); }); afterEach(() => { @@ -653,33 +694,6 @@ describe('adapterManager tests', () => { describe('aliasBidderAdaptor', function() { const CODE = 'sampleBidder'; - // Note: remove this describe once Prebid is 1.0 - describe('old way', function() { - let originalRegistry; - - function SampleAdapter() { - return Object.assign(this, { - callBids: sinon.stub(), - setBidderCode: sinon.stub() - }); - } - - before(() => { - originalRegistry = AdapterManager.bidderRegistry; - AdapterManager.bidderRegistry[CODE] = new SampleAdapter(); - }); - - after(() => { - AdapterManager.bidderRegistry = originalRegistry; - }); - - it('should add alias to registry', () => { - const alias = 'testalias'; - AdapterManager.aliasBidAdapter(CODE, alias); - expect(AdapterManager.bidderRegistry).to.have.property(alias); - }); - }); - describe('using bidderFactory', function() { let spec; @@ -712,9 +726,32 @@ describe('adapterManager tests', () => { }) }); + describe('setBidderSequence', () => { + beforeEach(() => { + sinon.spy(utils, 'shuffle'); + }); + + afterEach(() => { + config.resetConfig(); + utils.shuffle.restore(); + }); + + it('setting to `random` uses shuffled order of adUnits', () => { + config.setConfig({ bidderSequence: 'random' }); + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + sinon.assert.calledOnce(utils.shuffle); + }); + }); + describe('sizeMapping', () => { beforeEach(() => { - sinon.stub(window, 'matchMedia', () => ({matches: true})); + sinon.stub(window, 'matchMedia').callsFake(() => ({matches: true})); }); afterEach(() => { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index cac3aa85b77..bc9e86c0e0e 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -5,6 +5,7 @@ import { expect } from 'chai'; import { STATUS } from 'src/constants'; import { userSync } from 'src/userSync' import * as utils from 'src/utils'; +import { config } from 'src/config'; const CODE = 'sampleBidder'; const MOCK_BIDS_REQUEST = { @@ -66,7 +67,7 @@ describe('bidders created by newBidder', () => { spec.getUserSyncs.returns([]); bidder.callBids({}); - bidder.callBids({ bids: 'nothing useful' }); + bidder.callBids({ bids: 'nothing useful' }, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.called).to.equal(false); @@ -264,13 +265,13 @@ describe('bidders created by newBidder', () => { let logErrorSpy; beforeEach(() => { - ajaxStub = sinon.stub(ajax, 'ajax', function(url, callbacks) { + ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) { const fakeResponse = sinon.stub(); fakeResponse.returns('headerContent'); callbacks.success('response body', { getResponseHeader: fakeResponse }); }); addBidResponseStub.reset(); - doneStub.reset(); + doneStub.resetBehavior(); userSyncStub = sinon.stub(userSync, 'registerSync') logErrorSpy = sinon.spy(utils, 'logError'); }); @@ -432,7 +433,7 @@ describe('bidders created by newBidder', () => { let ajaxStub; beforeEach(() => { - ajaxStub = sinon.stub(ajax, 'ajax', function(url, callbacks) { + ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) { callbacks.error('ajax call failed.'); }); addBidResponseStub.reset(); @@ -592,7 +593,7 @@ describe('validate bid response: ', () => { addBidResponseStub = sinon.stub(); doneStub = sinon.stub(); - ajaxStub = sinon.stub(ajax, 'ajax', function(url, callbacks) { + ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) { const fakeResponse = sinon.stub(); fakeResponse.returns('headerContent'); callbacks.success('response body', { getResponseHeader: fakeResponse }); diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 4e95139a875..0954dda6325 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -74,13 +74,13 @@ describe('targeting tests', () => { beforeEach(() => { $$PREBID_GLOBAL$$._sendAllBids = false; - amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived', function() { + amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived').callsFake(function() { return [bid1, bid2]; }); - amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes', function() { + amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; }); - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired', () => true); + bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').returns(true); }); afterEach(() => { diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 9605babf3d9..a515a7aa010 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -149,7 +149,7 @@ window.apntag = { describe('Unit: Prebid Module', function () { let bidExpiryStub; before(() => { - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired', () => true); + bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').callsFake(() => true); }); after(function() { @@ -415,7 +415,7 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.bidderSettings = {}; currentPriceBucket = configObj.getConfig('priceGranularity'); configObj.setConfig({ priceGranularity: customConfigObject }); - sinon.stub(adaptermanager, 'makeBidRequests', () => ([{ + sinon.stub(adaptermanager, 'makeBidRequests').callsFake(() => ([{ 'bidderCode': 'appnexus', 'auctionId': '20882439e3238c', 'bidderRequestId': '331f3cf3f1d9c8', @@ -465,7 +465,7 @@ describe('Unit: Prebid Module', function () { }]; let adUnitCodes = ['div-gpt-ad-1460505748561-0']; auction = auctionManagerInstance.createAuction({adUnits, adUnitCodes}); - ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(function() { return function(url, callback) { const fakeResponse = sinon.stub(); fakeResponse.returns('headerContent'); @@ -579,7 +579,7 @@ describe('Unit: Prebid Module', function () { it('should set targeting from googletag data', function () { var slots = createSlotArray(); - slots[0].spySetTargeting.reset(); + slots[0].spySetTargeting.resetHistory(); window.googletag.pubads().setSlots(slots); $$PREBID_GLOBAL$$.setTargetingForGPTAsync(); @@ -718,7 +718,7 @@ describe('Unit: Prebid Module', function () { spyLogMessage = sinon.spy(utils, 'logMessage'); inIframe = true; - sinon.stub(utils, 'inIframe', () => inIframe); + sinon.stub(utils, 'inIframe').callsFake(() => inIframe); }); afterEach(function () { @@ -813,6 +813,115 @@ describe('Unit: Prebid Module', function () { }); describe('requestBids', () => { + let logMessageSpy; + let makeRequestsStub; + let xhr; + let adUnits; + let clock; + + const BIDDER_CODE = 'sampleBidder'; + let bids = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'bidderCode': BIDDER_CODE, + 'requestId': '4d0a6829338a07', + 'creativeId': 'id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + let bidRequests = [{ + 'bidderCode': BIDDER_CODE, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000, + 'start': 1000 + }]; + + beforeEach(() => { + logMessageSpy = sinon.spy(utils, 'logMessage'); + makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + makeRequestsStub.returns(bidRequests); + xhr = sinon.useFakeXMLHttpRequest(); + + adUnits = [{ + code: 'adUnit-code', + bids: [ + {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + ] + }]; + let adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 2000}); + let createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + }); + + afterEach(() => { + clock.restore(); + adaptermanager.makeBidRequests.restore(); + auctionModule.newAuction.restore(); + utils.logMessage.restore(); + xhr.restore(); + }); + + it('should execute callback after timeout', () => { + let spec = { + code: BIDDER_CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + + clock = sinon.useFakeTimers(); + let requestObj = { + bidsBackHandler: function bidsBackHandlerCallback() {}, + timeout: 2000, + adUnits: adUnits + }; + + $$PREBID_GLOBAL$$.requestBids(requestObj); + let re = new RegExp('^Auction [a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12} timedOut$'); + clock.tick(requestObj.timeout - 1); + assert.ok(logMessageSpy.neverCalledWith(sinon.match(re)), 'executeCallback not called'); + + clock.tick(1); + assert.ok(logMessageSpy.calledWith(sinon.match(re)), 'executeCallback called'); + }); + }) + + describe('requestBids', () => { + let xhr; + let requests; + + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + }); + + afterEach(() => xhr.restore()); var adUnitsBackup; var auctionManagerStub; let logMessageSpy @@ -829,7 +938,7 @@ describe('Unit: Prebid Module', function () { describe('part 1', () => { beforeEach(() => { adUnitsBackup = auction.getAdUnits - auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { + auctionManagerStub = sinon.stub(auctionManager, 'createAuction').callsFake(function() { return auction; }); logMessageSpy = sinon.spy(utils, 'logMessage'); @@ -844,30 +953,14 @@ describe('Unit: Prebid Module', function () { it('should log message when adUnits not configured', () => { $$PREBID_GLOBAL$$.adUnits = []; - $$PREBID_GLOBAL$$.requestBids({}); - + try { + $$PREBID_GLOBAL$$.requestBids({}); + } catch (e) { + console.log(e); + } assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); }); - it('should execute callback after timeout', () => { - let clock = sinon.useFakeTimers(); - let requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() {}, - timeout: timeout, - adUnits: auction.getAdUnits() - }; - - $$PREBID_GLOBAL$$.requestBids(requestObj); - let re = new RegExp('^Auction [a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12} timedOut$'); - clock.tick(requestObj.timeout - 1); - assert.ok(logMessageSpy.neverCalledWith(sinon.match(re)), 'executeCallback not called'); - - clock.tick(1); - assert.ok(logMessageSpy.calledWith(sinon.match(re)), 'executeCallback called'); - - clock.restore(); - }); - it('should execute callback immediately if adUnits is empty', () => { var bidsBackHandler = function bidsBackHandlerCallback() {}; var spyExecuteCallback = sinon.spy(bidsBackHandler); @@ -1319,7 +1412,7 @@ describe('Unit: Prebid Module', function () { describe('emit event', () => { let auctionManagerStub; beforeEach(() => { - auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { + auctionManagerStub = sinon.stub(auctionManager, 'createAuction').callsFake(function() { return auction; }); }); @@ -1409,41 +1502,13 @@ describe('Unit: Prebid Module', function () { }); }); - describe('setBidderSequence', () => { - let auctionManagerStub; - beforeEach(() => { - auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { - return auction; - }); - }); - - afterEach(() => { - auctionManager.createAuction.restore(); - }); - - it('setting to `random` uses shuffled order of adUnits', () => { - sinon.spy(utils, 'shuffle'); - const requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() {}, - timeout: 2000 - }; - - $$PREBID_GLOBAL$$.setConfig({ bidderSequence: 'random' }); - $$PREBID_GLOBAL$$.requestBids(requestObj); - - sinon.assert.calledOnce(utils.shuffle); - utils.shuffle.restore(); - resetAuction(); - }); - }); - describe('getHighestCpm', () => { - it('returns an array of winning bid objects for each adUnit', () => { - const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids(); - expect(highestCpmBids.length).to.equal(2); - expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); - expect(highestCpmBids[1]).to.deep.equal(auctionManager.getBidsReceived()[2]); - }); + // it('returns an array of winning bid objects for each adUnit', () => { + // const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids(); + // expect(highestCpmBids.length).to.equal(2); + // expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); + // expect(highestCpmBids[1]).to.deep.equal(auctionManager.getBidsReceived()[2]); + // }); it('returns an array containing the highest bid object for the given adUnitCode', () => { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); @@ -1474,10 +1539,10 @@ describe('Unit: Prebid Module', function () { beforeEach(() => { resetAuction(); auctionManagerInstance = newAuctionManager(); - sinon.stub(auctionManagerInstance, 'getBidsReceived', function() { + sinon.stub(auctionManagerInstance, 'getBidsReceived').callsFake(function() { return [getBidResponses()[1]]; }); - sinon.stub(auctionManagerInstance, 'getAdUnitCodes', function() { + sinon.stub(auctionManagerInstance, 'getAdUnitCodes').callsFake(function() { return ['/19968336/header-bid-tag-0']; }); targeting = newTargeting(auctionManagerInstance); diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index d6ae525f6d7..9a72629c71a 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -10,6 +10,7 @@ describe('user sync', () => { let timeoutStub; let shuffleStub; let getUniqueIdentifierStrStub; + let insertUserSyncIframeStub; let idPrefix = 'test-generated-id-'; let lastId = 0; let defaultUserSyncConfig = config.getConfig('userSync'); @@ -23,13 +24,21 @@ describe('user sync', () => { browserSupportsCookies: !disableBrowserCookies, }) } + let clock; + before(() => { + clock = sinon.useFakeTimers(); + }); + + after(() => { + clock.restore(); + }); beforeEach(() => { triggerPixelStub = sinon.stub(utils, 'triggerPixel'); logWarnStub = sinon.stub(utils, 'logWarn'); - shuffleStub = sinon.stub(utils, 'shuffle', (array) => array.reverse()); - getUniqueIdentifierStrStub = sinon.stub(utils, 'getUniqueIdentifierStr', () => idPrefix + (lastId += 1)); - timeoutStub = sinon.stub(window, 'setTimeout', (callbackFunc) => { callbackFunc(); }); + shuffleStub = sinon.stub(utils, 'shuffle').callsFake((array) => array.reverse()); + getUniqueIdentifierStrStub = sinon.stub(utils, 'getUniqueIdentifierStr').callsFake(() => idPrefix + (lastId += 1)); + insertUserSyncIframeStub = sinon.stub(utils, 'insertUserSyncIframe'); }); afterEach(() => { @@ -37,7 +46,7 @@ describe('user sync', () => { logWarnStub.restore(); shuffleStub.restore(); getUniqueIdentifierStrStub.restore(); - timeoutStub.restore(); + insertUserSyncIframeStub.restore(); }); it('should register and fire a pixel URL', () => { @@ -59,7 +68,8 @@ describe('user sync', () => { userSync.registerSync('image', 'testBidder', 'http://example.com'); // This implicitly tests cookie and browser support userSync.syncUsers(999); - expect(timeoutStub.getCall(0).args[1]).to.equal(999); + clock.tick(1000); + expect(triggerPixelStub.getCall(0)).to.not.be.null; }); it('should register and fires multiple pixel URLs', () => { @@ -85,9 +95,7 @@ describe('user sync', () => { const userSync = newTestUserSync({iframeEnabled: true}); userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); userSync.syncUsers(); - let iframe = window.document.getElementById(idPrefix + lastId); - expect(iframe).to.exist; - expect(iframe.src).to.equal('http://example.com/iframe'); + expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); }); it('should only trigger syncs once per page', () => { diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 96d3888015e..f02b4881be3 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -1,4 +1,5 @@ import { getSlotTargeting, getAdServerTargeting } from 'test/fixtures/fixtures'; +import { cookiesAreEnabled } from '../../src/utils'; var assert = require('assert'); var utils = require('../../src/utils'); @@ -525,90 +526,6 @@ describe('Utils', function () { }); }); - // describe('cookie support', function () { - // // store original cookie getter and setter so we can reset later - // var origCookieSetter = document.__lookupSetter__('cookie'); - // var origCookieGetter = document.__lookupGetter__('cookie'); - - // // store original cookieEnabled getter and setter so we can reset later - // var origCookieEnabledSetter = window.navigator.__lookupSetter__('cookieEnabled'); - // var origCookieEnabledGetter = window.navigator.__lookupGetter__('cookieEnabled'); - - // // Replace the document cookie set function with the output of a custom function for testing - // let setCookie = (v) => v; - - // beforeEach(() => { - // // Redefine window.navigator.cookieEnabled such that you can set otherwise "read-only" values - // Object.defineProperty(window.navigator, 'cookieEnabled', (function (_value) { - // return { - // get: function _get() { - // return _value; - // }, - // set: function _set(v) { - // _value = v; - // }, - // configurable: true - // }; - // })(window.navigator.cookieEnabled)); - - // // Reset the setCookie cookie function before each test - // setCookie = (v) => v; - // // Redefine the document.cookie object such that you can purposefully have it output nothing as if it is disabled - // Object.defineProperty(window.document, 'cookie', (function (_value) { - // return { - // get: function _get() { - // return _value; - // }, - // set: function _set(v) { - // _value = setCookie(v); - // }, - // configurable: true - // }; - // })(window.navigator.cookieEnabled)); - // }); - - // afterEach(() => { - // // redefine window.navigator.cookieEnabled to original getter and setter - // Object.defineProperty(window.navigator, 'cookieEnabled', { - // get: origCookieEnabledGetter, - // set: origCookieEnabledSetter, - // configurable: true - // }); - // // redefine document.cookie to original getter and setter - // Object.defineProperty(document, 'cookie', { - // get: origCookieGetter, - // set: origCookieSetter, - // configurable: true - // }); - // }); - - // it('should be detected', function() { - // assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should be enabled by default'); - // }); - - // it('should be not available', function() { - // setCookie = () => ''; - // window.navigator.cookieEnabled = false; - // window.document.cookie = ''; - // assert.equal(utils.cookiesAreEnabled(), false, 'Cookies should be disabled'); - // }); - - // it('should be available', function() { - // window.navigator.cookieEnabled = false; - // window.document.cookie = 'key=value'; - // assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should already be set'); - // window.navigator.cookieEnabled = false; - // window.document.cookie = ''; - // assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should settable'); - // setCookie = () => ''; - // window.navigator.cookieEnabled = true; - // window.document.cookie = ''; - // assert.equal(utils.cookiesAreEnabled(), true, 'Cookies should be on via on window.navigator'); - // // Reset the setCookie - // setCookie = (v) => v; - // }); - // }); - describe('delayExecution', function () { it('should execute the core function after the correct number of calls', function () { const callback = sinon.spy(); diff --git a/test/test_index.js b/test/test_index.js new file mode 100644 index 00000000000..d17ea25a050 --- /dev/null +++ b/test/test_index.js @@ -0,0 +1,5 @@ +require('test/helpers/prebidGlobal.js'); +require('test/helpers/karma-init.js'); + +var testsContext = require.context('.', true, /_spec$/); +testsContext.keys().forEach(testsContext); diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 28d570aa6fa..00000000000 --- a/yarn.lock +++ /dev/null @@ -1,9030 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@gulp-sourcemaps/identity-map@1.X": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz#cfa23bc5840f9104ce32a65e74db7e7a974bbee1" - dependencies: - acorn "^5.0.3" - css "^2.2.1" - normalize-path "^2.1.1" - source-map "^0.5.6" - through2 "^2.0.3" - -"@gulp-sourcemaps/map-sources@1.X": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" - dependencies: - normalize-path "^2.0.1" - through2 "^2.0.3" - -JSONStream@^1.0.3: - version "1.3.1" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a" - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - -abbrev@1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" - -abbrev@1.0.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - -accepts@1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" - dependencies: - mime-types "~2.1.11" - negotiator "0.6.1" - -accepts@~1.2.12, accepts@~1.2.13: - version "1.2.13" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" - dependencies: - mime-types "~2.1.6" - negotiator "0.5.3" - -accepts@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" - dependencies: - mime-types "~2.1.16" - negotiator "0.6.1" - -acorn-dynamic-import@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" - dependencies: - acorn "^4.0.3" - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - dependencies: - acorn "^3.0.4" - -acorn@4.X, acorn@^4.0.3: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - -acorn@^3.0.0, acorn@^3.0.4, acorn@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - -acorn@^5.0.0, acorn@^5.0.3, acorn@^5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" - -adm-zip@~0.4.3: - version "0.4.7" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" - -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - -agent-base@2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" - dependencies: - extend "~3.0.0" - semver "~5.0.1" - -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" - -ajv-keywords@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.0.tgz#a296e17f7bfae7c1ce4f7e0de53d29cb32162df0" - -ajv@^4.7.0, ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ajv@^5.0.0, ajv@^5.1.5, ajv@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - json-schema-traverse "^0.3.0" - json-stable-stringify "^1.0.1" - -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - -ansi-escapes@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" - -ansi-html@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" - -ansi-regex@^0.2.0, ansi-regex@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" - -ansi-regex@^1.0.0, ansi-regex@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-1.1.1.tgz#41c847194646375e6a1a5d10c3ca054ef9fc980d" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - -ansi-styles@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" - -ansi-styles@^2.0.1, ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-styles@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" - dependencies: - color-convert "^1.9.0" - -anymatch@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - dependencies: - micromatch "^2.1.5" - normalize-path "^2.0.0" - -append-transform@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" - dependencies: - default-require-extensions "^1.0.0" - -aproba@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" - -archiver-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174" - dependencies: - glob "^7.0.0" - graceful-fs "^4.1.0" - lazystream "^1.0.0" - lodash "^4.8.0" - normalize-path "^2.0.0" - readable-stream "^2.0.0" - -archiver@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22" - dependencies: - archiver-utils "^1.3.0" - async "^2.0.0" - buffer-crc32 "^0.2.1" - glob "^7.0.0" - lodash "^4.8.0" - readable-stream "^2.0.0" - tar-stream "^1.5.0" - walkdir "^0.0.11" - zip-stream "^1.1.0" - -archiver@~0.14.3: - version "0.14.4" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-0.14.4.tgz#5b9ddb9f5ee1ceef21cb8f3b020e6240ecb4315c" - dependencies: - async "~0.9.0" - buffer-crc32 "~0.2.1" - glob "~4.3.0" - lazystream "~0.1.0" - lodash "~3.2.0" - readable-stream "~1.0.26" - tar-stream "~1.1.0" - zip-stream "~0.5.0" - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - -are-we-there-yet@~1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - -arr-flatten@^1.0.1, arr-flatten@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - -array-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - -array-iterate@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-1.1.1.tgz#865bf7f8af39d6b0982c60902914ac76bc0108f6" - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - -array-slice@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.0.0.tgz#e73034f00dcc1f40876008fd20feae77bd4b7c2f" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - -array.from@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/array.from/-/array.from-0.2.0.tgz#2c627b1b76dff2def2365fa052b65c3d585e5f6b" - -arraybuffer.slice@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - -asn1.js@^4.0.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.1.tgz#48ba240b45a9280e94748990ba597d216617fd40" - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -asn1@0.1.11: - version "0.1.11" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.1.11.tgz#559be18376d08a4ec4dbe80877d27818639b2df7" - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assert-plus@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -assert@^1.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - dependencies: - util "0.10.3" - -assertion-error@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.0.tgz#c7f85438fdd466bc7ca16ab90c81513797a5d23b" - -assertion-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" - -ast-types@0.x.x: - version "0.9.12" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.12.tgz#b136300d67026625ae15326982ca9918e5db73c9" - -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - -async@1.x, async@^1.3.0, async@^1.4.0, async@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - -async@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.0.1.tgz#b709cc0280a9c36f09f4536be823c838a9049e25" - dependencies: - lodash "^4.8.0" - -async@^0.9.0, async@~0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - -async@^2.0.0, async@^2.1.2, async@^2.1.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d" - dependencies: - lodash "^4.14.0" - -async@~0.2.10, async@~0.2.6: - version "0.2.10" - resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -atob@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" - -atob@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" - -aws-sign2@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.5.0.tgz#c57103f7a17fc037f02d7c2e64b602ea223f7d63" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - -aws4@^1.2.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.22.0.tgz#643deaeb520bcd2b06c11e39945c877e0200d128" - dependencies: - babel-code-frame "^6.22.0" - babel-generator "^6.22.0" - babel-helpers "^6.22.0" - babel-messages "^6.22.0" - babel-register "^6.22.0" - babel-runtime "^6.22.0" - babel-template "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" - babylon "^6.11.0" - convert-source-map "^1.1.0" - debug "^2.1.1" - json5 "^0.5.0" - lodash "^4.2.0" - minimatch "^3.0.2" - path-is-absolute "^1.0.0" - private "^0.1.6" - slash "^1.0.0" - source-map "^0.5.0" - -babel-core@^6.0.0, babel-core@^6.0.14, babel-core@^6.0.2, babel-core@^6.17.0, babel-core@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" - 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.0" - debug "^2.6.8" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.7" - slash "^1.0.0" - source-map "^0.5.6" - -babel-generator@^6.18.0, babel-generator@^6.22.0, babel-generator@^6.25.0, babel-generator@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" - 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.6" - trim-right "^1.0.1" - -babel-helper-bindify-decorators@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-builder-react-jsx@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - esutils "^2.0.2" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-explode-class@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" - dependencies: - babel-helper-bindify-decorators "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.22.0, babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-loader@^7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.2.tgz#f6cbe122710f1aa2af4d881c6d5b54358ca24126" - dependencies: - find-cache-dir "^1.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" - -babel-messages@^6.22.0, babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - -babel-plugin-syntax-async-generators@^6.5.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - -babel-plugin-syntax-class-constructor-call@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416" - -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - -babel-plugin-syntax-decorators@^6.1.18, babel-plugin-syntax-decorators@^6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - -babel-plugin-syntax-do-expressions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d" - -babel-plugin-syntax-dynamic-import@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - -babel-plugin-syntax-export-extensions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721" - -babel-plugin-syntax-flow@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - -babel-plugin-syntax-function-bind@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46" - -babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - -babel-plugin-system-import-transformer@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz#d37f0cae8e61ef39060208331d931b5e630d7c5f" - dependencies: - babel-plugin-syntax-dynamic-import "^6.18.0" - -babel-plugin-transform-async-generator-functions@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-generators "^6.5.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-class-constructor-call@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9" - dependencies: - babel-plugin-syntax-class-constructor-call "^6.18.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-class-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - dependencies: - babel-helper-function-name "^6.24.1" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-decorators-legacy@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz#741b58f6c5bce9e6027e0882d9c994f04f366925" - dependencies: - babel-plugin-syntax-decorators "^6.1.18" - babel-runtime "^6.2.0" - babel-template "^6.3.0" - -babel-plugin-transform-decorators@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" - dependencies: - babel-helper-explode-class "^6.24.1" - babel-plugin-syntax-decorators "^6.13.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-do-expressions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb" - dependencies: - babel-plugin-syntax-do-expressions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.22.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.22.0, babel-plugin-transform-es2015-classes@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.22.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.22.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.22.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.22.0, babel-plugin-transform-es2015-parameters@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-es3-member-expression-literals@6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz#733d3444f3ecc41bef8ed1a6a4e09657b8969ebb" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es3-property-literals@6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz#b2078d5842e22abf40f73e8cde9cd3711abd5758" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-exponentiation-operator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-export-extensions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653" - dependencies: - babel-plugin-syntax-export-extensions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - dependencies: - babel-plugin-syntax-flow "^6.18.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-function-bind@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97" - dependencies: - babel-plugin-syntax-function-bind "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-object-assign@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz#f99d2f66f1a0b0d498e346c5359684740caa20ba" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-object-rest-spread@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" - -babel-plugin-transform-react-display-name@^6.23.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-self@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-source@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" - dependencies: - babel-helper-builder-react-jsx "^6.24.1" - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-preset-es2015@6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz#af5a98ecb35eb8af764ad8a5a05eb36dc4386835" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.22.0" - babel-plugin-transform-es2015-classes "^6.22.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.22.0" - babel-plugin-transform-es2015-modules-systemjs "^6.22.0" - babel-plugin-transform-es2015-modules-umd "^6.22.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.22.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - -babel-preset-es2015@^6.16.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.24.1" - babel-plugin-transform-es2015-classes "^6.24.1" - babel-plugin-transform-es2015-computed-properties "^6.24.1" - babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.24.1" - babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.24.1" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-plugin-transform-es2015-modules-systemjs "^6.24.1" - babel-plugin-transform-es2015-modules-umd "^6.24.1" - babel-plugin-transform-es2015-object-super "^6.24.1" - babel-plugin-transform-es2015-parameters "^6.24.1" - babel-plugin-transform-es2015-shorthand-properties "^6.24.1" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.24.1" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.24.1" - babel-plugin-transform-regenerator "^6.24.1" - -babel-preset-flow@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" - dependencies: - babel-plugin-transform-flow-strip-types "^6.22.0" - -babel-preset-react@^6.16.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" - dependencies: - babel-plugin-syntax-jsx "^6.3.13" - babel-plugin-transform-react-display-name "^6.23.0" - babel-plugin-transform-react-jsx "^6.24.1" - babel-plugin-transform-react-jsx-self "^6.22.0" - babel-plugin-transform-react-jsx-source "^6.22.0" - babel-preset-flow "^6.23.0" - -babel-preset-stage-0@^6.16.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz#5642d15042f91384d7e5af8bc88b1db95b039e6a" - dependencies: - babel-plugin-transform-do-expressions "^6.22.0" - babel-plugin-transform-function-bind "^6.22.0" - babel-preset-stage-1 "^6.24.1" - -babel-preset-stage-1@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0" - dependencies: - babel-plugin-transform-class-constructor-call "^6.24.1" - babel-plugin-transform-export-extensions "^6.22.0" - babel-preset-stage-2 "^6.24.1" - -babel-preset-stage-2@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" - dependencies: - babel-plugin-syntax-dynamic-import "^6.18.0" - babel-plugin-transform-class-properties "^6.24.1" - babel-plugin-transform-decorators "^6.24.1" - babel-preset-stage-3 "^6.24.1" - -babel-preset-stage-3@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - dependencies: - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-generator-functions "^6.24.1" - babel-plugin-transform-async-to-generator "^6.24.1" - babel-plugin-transform-exponentiation-operator "^6.24.1" - babel-plugin-transform-object-rest-spread "^6.22.0" - -babel-register@^6.22.0, babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - 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" - -babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - dependencies: - 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@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - 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" - -babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babelify@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - dependencies: - babel-core "^6.0.14" - object-assign "^4.0.0" - -babylon@^6.11.0, babylon@^6.17.2, babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - -bail@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.2.tgz#f7d6c1731630a9f9f0d4d35ed1f962e2074a1764" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" - -base64-js@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" - -base64-url@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/base64-url/-/base64-url-1.2.1.tgz#199fd661702a0e7b7dcae6e0698bb089c52f6d78" - -base64id@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" - -base@^0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.1.tgz#b36a7f11113853a342a15691d98e2dcc8a6cc270" - dependencies: - arr-union "^3.1.0" - cache-base "^0.8.4" - class-utils "^0.3.4" - component-emitter "^1.2.1" - define-property "^0.2.5" - isobject "^2.1.0" - lazy-cache "^2.0.1" - mixin-deep "^1.1.3" - pascalcase "^0.1.1" - -basic-auth-connect@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz#fdb0b43962ca7b40456a7c2bb48fe173da2d2122" - -basic-auth@~1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" - -batch@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464" - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" - dependencies: - callsite "1.0.0" - -big.js@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978" - -binary-extensions@^1.0.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0" - -"binary@>= 0.3.0 < 1": - version "0.3.0" - resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" - dependencies: - buffers "~0.1.1" - chainsaw "~0.1.0" - -binaryextensions@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-1.0.1.tgz#1e637488b35b58bda5f4774bf96a5212a8c90755" - -bl@^0.9.0, bl@~0.9.0: - version "0.9.5" - resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" - dependencies: - readable-stream "~1.0.26" - -bl@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" - dependencies: - readable-stream "^2.0.5" - -blob@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" - -block-loader@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/block-loader/-/block-loader-2.1.0.tgz#bbb398ad5a843c6c71f79a296f4b6df4b0257312" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -bluebird@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - -body-parser@^1.16.1: - version "1.17.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee" - dependencies: - bytes "2.4.0" - content-type "~1.0.2" - debug "2.6.7" - depd "~1.1.0" - http-errors "~1.6.1" - iconv-lite "0.4.15" - on-finished "~2.3.0" - qs "6.4.0" - raw-body "~2.2.0" - type-is "~1.6.15" - -body-parser@~1.13.3: - version "1.13.3" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.13.3.tgz#c08cf330c3358e151016a05746f13f029c97fa97" - dependencies: - bytes "2.1.0" - content-type "~1.0.1" - debug "~2.2.0" - depd "~1.0.1" - http-errors "~1.3.1" - iconv-lite "0.4.11" - on-finished "~2.3.0" - qs "4.0.0" - raw-body "~2.1.2" - type-is "~1.6.6" - -body-parser@~1.14.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.14.2.tgz#1015cb1fe2c443858259581db53332f8d0cf50f9" - dependencies: - bytes "2.2.0" - content-type "~1.0.1" - debug "~2.2.0" - depd "~1.1.0" - http-errors "~1.3.1" - iconv-lite "0.4.13" - on-finished "~2.3.0" - qs "5.2.0" - raw-body "~2.1.5" - type-is "~1.6.10" - -body@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069" - dependencies: - continuable-cache "^0.3.1" - error "^7.0.0" - raw-body "~1.1.0" - safe-json-parse "~1.0.1" - -boom@0.4.x: - version "0.4.2" - resolved "https://registry.yarnpkg.com/boom/-/boom-0.4.2.tgz#7a636e9ded4efcefb19cef4947a3c67dfaee911b" - dependencies: - hoek "0.9.x" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -brace-expansion@^1.0.0, brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^0.1.2: - version "0.1.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6" - dependencies: - expand-range "^0.1.0" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -braces@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.2.2.tgz#241f868c2b2690d9febeee5a7c83fbbf25d00b1b" - dependencies: - arr-flatten "^1.0.3" - array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.0" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^2.1.0" - to-regex "^3.0.1" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - -browser-resolve@^1.7.0: - version "1.11.2" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" - dependencies: - resolve "1.1.7" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - -browserify-aes@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-0.4.0.tgz#067149b668df31c4b58533e02d01e806d8608e2c" - dependencies: - inherits "^2.0.1" - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.0.8" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.0.8.tgz#c8fa3b1b7585bb7ba77c5560b60996ddec6d5309" - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd" - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -browserify-zlib@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" - dependencies: - pako "~0.2.0" - -browserstack@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.5.0.tgz#b565425ad62ed72c1082a1eb979d5313c7d4754f" - dependencies: - https-proxy-agent "1.0.0" - -browserstacktunnel-wrapper@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.1.tgz#ffe1910d6e39fe86618183e826690041af53edae" - dependencies: - https-proxy-agent "^1.0.0" - unzip "~0.1.9" - -buffer-crc32@^0.2.1, buffer-crc32@~0.2.1: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - -buffer-shims@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - -buffer@^4.3.0, buffer@^4.9.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -buffers@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" - -builtin-modules@^1.0.0, builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - -bytes@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" - -bytes@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.1.0.tgz#ac93c410e2ffc9cc7cf4b464b38289067f5e47b4" - -bytes@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.2.0.tgz#fd35464a403f6f9117c2de3609ecff9cae000588" - -bytes@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" - -bytes@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a" - -cache-base@^0.8.4: - version "0.8.5" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-0.8.5.tgz#60ceb3504021eceec7011fd3384b7f4e95729bfa" - dependencies: - collection-visit "^0.2.1" - component-emitter "^1.2.1" - get-value "^2.0.5" - has-value "^0.3.1" - isobject "^3.0.0" - lazy-cache "^2.0.1" - set-value "^0.4.2" - to-object-path "^0.3.0" - union-value "^0.2.3" - unset-value "^0.1.1" - -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - dependencies: - callsites "^0.2.0" - -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^1.0.2, camelcase@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -caseless@~0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.8.0.tgz#5bca2881d41437f54b2407ebe34888c7b9ad4f7d" - -ccount@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.2.tgz#53b6a2f815bb77b9c2871f7b9a72c3a25f1d8e89" - -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - -chai-nightwatch@~0.1.x: - version "0.1.1" - resolved "https://registry.yarnpkg.com/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz#1ca56de768d3c0868fe7fc2f4d32c2fe894e6be9" - dependencies: - assertion-error "1.0.0" - deep-eql "0.1.3" - -chai@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" - dependencies: - assertion-error "^1.0.1" - deep-eql "^0.1.3" - type-detect "^1.0.0" - -chainsaw@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" - dependencies: - traverse ">=0.3.0 <0.4" - -chalk@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" - 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" - -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - 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" - -chalk@^2.0.0, chalk@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - -character-entities-html4@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.1.tgz#359a2a4a0f7e29d3dc2ac99bdbe21ee39438ea50" - -character-entities-legacy@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz#f40779df1a101872bb510a3d295e1fccf147202f" - -character-entities@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.1.tgz#f76871be5ef66ddb7f8f8e3478ecc374c27d6dca" - -character-reference-invalid@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz#942835f750e4ec61a308e60c2ef8cc1011202efc" - -chokidar@^1.0.0, chokidar@^1.2.0, chokidar@^1.4.1, chokidar@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^2.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - optionalDependencies: - fsevents "^1.0.0" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - -class-utils@^0.3.4: - version "0.3.5" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.5.tgz#17e793103750f9627b2176ea34cfd1b565903c80" - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - lazy-cache "^2.0.2" - static-extend "^0.1.1" - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - dependencies: - restore-cursor "^2.0.0" - -cli-width@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-1.1.1.tgz#a4d293ef67ebb7b88d4a4d42c0ccf00c4d1e366d" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - -cliui@^3.0.3, cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - -clone-stats@^0.0.1, clone-stats@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - -clone@^1.0.0, clone@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" - -clone@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" - -cloneable-readable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117" - dependencies: - inherits "^2.0.1" - process-nextick-args "^1.0.6" - through2 "^2.0.1" - -co@^4.5.4, co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -co@~3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/co/-/co-3.0.6.tgz#1445f226c5eb956138e68c9ac30167ea7d2e6bda" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -collapse-white-space@^1.0.0, collapse-white-space@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.3.tgz#4b906f670e5a963a87b76b0e1689643341b6023c" - -collection-visit@^0.2.1: - version "0.2.3" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-0.2.3.tgz#2f62483caecc95f083b9a454a3ee9e6139ad7957" - dependencies: - lazy-cache "^2.0.1" - map-visit "^0.1.5" - object-visit "^0.3.4" - -color-convert@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" - dependencies: - color-name "^1.1.1" - -color-name@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - -colors@^1.1.0, colors@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - -combine-lists@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6" - dependencies: - lodash "^4.5.0" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - dependencies: - delayed-stream "~1.0.0" - -combined-stream@~0.0.4, combined-stream@~0.0.5: - version "0.0.7" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-0.0.7.tgz#0137e657baa5a7541c57ac37ac5fc07d73b4dc1f" - dependencies: - delayed-stream "0.0.5" - -comma-separated-tokens@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.4.tgz#72083e58d4a462f01866f6617f4d98a3cd3b8a46" - dependencies: - trim "0.0.1" - -commander@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" - -commander@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" - -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - -commander@^2.9.0, commander@~2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - -component-emitter@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" - -component-emitter@1.2.1, component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - -compress-commons@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.0.tgz#58587092ef20d37cb58baf000112c9278ff73b9f" - dependencies: - buffer-crc32 "^0.2.1" - crc32-stream "^2.0.0" - normalize-path "^2.0.0" - readable-stream "^2.0.0" - -compress-commons@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-0.2.9.tgz#422d927430c01abd06cd455b6dfc04cb4cf8003c" - dependencies: - buffer-crc32 "~0.2.1" - crc32-stream "~0.3.1" - node-int64 "~0.3.0" - readable-stream "~1.0.26" - -compressible@~2.0.5: - version "2.0.11" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.11.tgz#16718a75de283ed8e604041625a2064586797d8a" - dependencies: - mime-db ">= 1.29.0 < 2" - -compression@~1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.5.2.tgz#b03b8d86e6f8ad29683cba8df91ddc6ffc77b395" - dependencies: - accepts "~1.2.12" - bytes "2.1.0" - compressible "~2.0.5" - debug "~2.2.0" - on-headers "~1.0.0" - vary "~1.0.1" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" - dependencies: - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -concat-stream@~1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" - dependencies: - inherits "~2.0.1" - readable-stream "~2.0.0" - typedarray "~0.0.5" - -concat-with-sourcemaps@*, concat-with-sourcemaps@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz#f55b3be2aeb47601b10a2d5259ccfb70fd2f1dd6" - dependencies: - source-map "^0.5.1" - -connect-livereload@^0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/connect-livereload/-/connect-livereload-0.5.4.tgz#80157d1371c9f37cc14039ab1895970d119dc3bc" - -connect-timeout@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/connect-timeout/-/connect-timeout-1.6.2.tgz#de9a5ec61e33a12b6edaab7b5f062e98c599b88e" - dependencies: - debug "~2.2.0" - http-errors "~1.3.1" - ms "0.7.1" - on-headers "~1.0.0" - -connect@^2.30.0: - version "2.30.2" - resolved "https://registry.yarnpkg.com/connect/-/connect-2.30.2.tgz#8da9bcbe8a054d3d318d74dfec903b5c39a1b609" - dependencies: - basic-auth-connect "1.0.0" - body-parser "~1.13.3" - bytes "2.1.0" - compression "~1.5.2" - connect-timeout "~1.6.2" - content-type "~1.0.1" - cookie "0.1.3" - cookie-parser "~1.3.5" - cookie-signature "1.0.6" - csurf "~1.8.3" - debug "~2.2.0" - depd "~1.0.1" - errorhandler "~1.4.2" - express-session "~1.11.3" - finalhandler "0.4.0" - fresh "0.3.0" - http-errors "~1.3.1" - method-override "~2.3.5" - morgan "~1.6.1" - multiparty "3.3.2" - on-headers "~1.0.0" - parseurl "~1.3.0" - pause "0.1.0" - qs "4.0.0" - response-time "~2.3.1" - serve-favicon "~2.3.0" - serve-index "~1.7.2" - serve-static "~1.10.0" - type-is "~1.6.6" - utils-merge "1.0.0" - vhost "~3.0.1" - -connect@^3.6.0: - version "3.6.3" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.3.tgz#f7320d46a25b4be7b483a2236517f24b1e27e301" - dependencies: - debug "2.6.8" - finalhandler "1.0.4" - parseurl "~1.3.1" - utils-merge "1.0.0" - -console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - -content-type@~1.0.1, content-type@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" - -continuable-cache@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f" - -convert-source-map@1.X, convert-source-map@^1.1.0, convert-source-map@^1.1.1, convert-source-map@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" - -cookie-parser@~1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.3.5.tgz#9d755570fb5d17890771227a02314d9be7cf8356" - dependencies: - cookie "0.1.3" - cookie-signature "1.0.6" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - -cookie@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.3.tgz#e734a5c1417fce472d5aef82c381cabb64d1a435" - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - -core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -coveralls@^2.11.11: - version "2.13.1" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.1.tgz#d70bb9acc1835ec4f063ff9dac5423c17b11f178" - dependencies: - js-yaml "3.6.1" - lcov-parse "0.0.10" - log-driver "1.2.5" - minimist "1.2.0" - request "2.79.0" - -crc32-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4" - dependencies: - crc "^3.4.4" - readable-stream "^2.0.0" - -crc32-stream@~0.3.1: - version "0.3.4" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-0.3.4.tgz#73bc25b45fac1db6632231a7bfce8927e9f06552" - dependencies: - buffer-crc32 "~0.2.1" - readable-stream "~1.0.24" - -crc@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/crc/-/crc-3.3.0.tgz#fa622e1bc388bf257309082d6b65200ce67090ba" - -crc@^3.4.4: - version "3.4.4" - resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b" - -create-ecdh@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - ripemd160 "^2.0.0" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.6" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06" - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-spawn@^5.0.1, cross-spawn@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cryptiles@0.2.x: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-0.2.2.tgz#ed91ff1f17ad13d3748288594f8a48a0d26f325c" - dependencies: - boom "0.4.x" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -crypto-browserify@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.3.0.tgz#b9fc75bb4a0ed61dcf1cd5dae96eb30c9c3e506c" - dependencies: - browserify-aes "0.4.0" - pbkdf2-compat "2.0.1" - ripemd160 "0.2.0" - sha.js "2.2.6" - -crypto-browserify@^3.11.0: - version "3.11.1" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.1.tgz#948945efc6757a400d6e5e5af47194d10064279f" - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - -csrf@~3.0.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/csrf/-/csrf-3.0.6.tgz#b61120ddceeafc91e76ed5313bb5c0b2667b710a" - dependencies: - rndm "1.2.0" - tsscmp "1.0.5" - uid-safe "2.1.4" - -css-loader@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.9.1.tgz#2e1aa00ce7e30ef2c6a7a4b300a080a7c979e0dc" - dependencies: - csso "1.3.x" - loader-utils "~0.2.2" - source-map "~0.1.38" - -css-parse@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" - dependencies: - css "^2.0.0" - -css-value@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/css-value/-/css-value-0.0.1.tgz#5efd6c2eea5ea1fd6b6ac57ec0427b18452424ea" - -css@2.X, css@^2.0.0, css@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" - dependencies: - inherits "^2.0.1" - source-map "^0.1.38" - source-map-resolve "^0.3.0" - urix "^0.1.0" - -csso@1.3.x: - version "1.3.12" - resolved "https://registry.yarnpkg.com/csso/-/csso-1.3.12.tgz#fc628694a2d38938aaac4996753218fd311cdb9e" - -csurf@~1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.8.3.tgz#23f2a13bf1d8fce1d0c996588394442cba86a56a" - dependencies: - cookie "0.1.3" - cookie-signature "1.0.6" - csrf "~3.0.0" - http-errors "~1.3.1" - -ctype@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f" - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - dependencies: - array-find-index "^1.0.1" - -custom-event@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" - -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - dependencies: - es5-ext "^0.10.9" - -dargs@christian-bromann/dargs: - version "4.0.1" - resolved "https://codeload.github.com/christian-bromann/dargs/tar.gz/7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770" - dependencies: - number-is-nan "^1.0.0" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -data-uri-to-buffer@1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz#77163ea9c20d8641b4707e8f18abdf9a78f34835" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - -dateformat@^1.0.7-1.2.3: - version "1.0.12" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" - dependencies: - get-stdin "^4.0.1" - meow "^3.3.0" - -dateformat@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.0.0.tgz#2743e3abb5c3fc2462e527dca445e04e9f4dee17" - -debug-fabulous@>=0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-0.1.1.tgz#1b970878c9fa4fbd1c88306eab323c830c58f1d6" - dependencies: - debug "2.3.0" - memoizee "^0.4.5" - object-assign "4.1.0" - -debug@2, debug@2.6.8, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.3, debug@^2.6.8, debug@~2.6.7: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - dependencies: - ms "2.0.0" - -debug@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.0.0.tgz#89bd9df6732b51256bc6705342bba02ed12131ef" - dependencies: - ms "0.6.2" - -debug@2.2.0, debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - -debug@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.0.tgz#3912dc55d7167fc3af17d2b85c13f93deaedaa43" - dependencies: - ms "0.7.2" - -debug@2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" - dependencies: - ms "0.7.2" - -debug@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e" - dependencies: - ms "2.0.0" - -decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - -deep-eql@0.1.3, deep-eql@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" - dependencies: - type-detect "0.1.1" - -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - -deepmerge@^0.2.7, deepmerge@~0.2.7: - version "0.2.10" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-0.2.10.tgz#8906bf9e525a4fbf1b203b2afcb4640249821219" - -default-require-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" - dependencies: - strip-bom "^2.0.0" - -defaults@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - dependencies: - clone "^1.0.2" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - dependencies: - is-descriptor "^1.0.0" - -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - -degenerator@~1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-1.0.4.tgz#fcf490a37ece266464d9cc431ab98c5819ced095" - dependencies: - ast-types "0.x.x" - escodegen "1.x.x" - esprima "3.x.x" - -del@^2.0.2, del@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - -delayed-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - -depd@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" - -depd@1.1.1, depd@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - -depd@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" - -deprecated@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" - -des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - -detab@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.1.tgz#531f5e326620e2fd4f03264a905fb3bcc8af4df4" - dependencies: - repeat-string "^1.5.4" - -detect-file@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-0.1.0.tgz#4935dedfd9488648e006b0129566e9386711ea63" - dependencies: - fs-exists-sync "^0.1.0" - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - -detect-newline@2.X: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" - -detective@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/detective/-/detective-4.5.0.tgz#6e5a8c6b26e6c7a254b1c6b6d7490d98ec91edd1" - dependencies: - acorn "^4.0.3" - defined "^1.0.0" - -di@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" - -diff@1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.0.8.tgz#343276308ec991b7bc82267ed55bc1411f971666" - -diff@1.4.0, diff@^1.3.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" - -diffie-hellman@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -disparity@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/disparity/-/disparity-2.0.0.tgz#57ddacb47324ae5f58d2cc0da886db4ce9eeb718" - dependencies: - ansi-styles "^2.0.1" - diff "^1.3.2" - -doctrine-temporary-fork@2.0.0-alpha-allowarrayindex: - version "2.0.0-alpha-allowarrayindex" - resolved "https://registry.yarnpkg.com/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz#40015a867eb27e75b26c828b71524f137f89f9f0" - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - -doctrine@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - -documentation@^5.2.2: - version "5.3.0" - resolved "https://registry.yarnpkg.com/documentation/-/documentation-5.3.0.tgz#6973aa40bd75f065e7def1df51dbbab86637cfa4" - dependencies: - ansi-html "^0.0.7" - babel-core "^6.17.0" - babel-generator "^6.25.0" - babel-plugin-system-import-transformer "3.1.0" - babel-plugin-transform-decorators-legacy "^1.3.4" - babel-preset-es2015 "^6.16.0" - babel-preset-react "^6.16.0" - babel-preset-stage-0 "^6.16.0" - babel-traverse "^6.16.0" - babel-types "^6.16.0" - babelify "^7.3.0" - babylon "^6.17.2" - chalk "^2.0.0" - chokidar "^1.2.0" - concat-stream "^1.5.0" - disparity "^2.0.0" - doctrine-temporary-fork "2.0.0-alpha-allowarrayindex" - get-port "^3.1.0" - git-url-parse "^6.0.1" - github-slugger "1.1.3" - glob "^7.0.0" - globals-docs "^2.3.0" - highlight.js "^9.1.0" - js-yaml "^3.8.4" - lodash "^4.11.1" - mdast-util-inject "^1.1.0" - micromatch "^3.0.0" - mime "^1.3.4" - module-deps-sortable "4.0.6" - parse-filepath "^1.0.1" - pify "^3.0.0" - read-pkg-up "^2.0.0" - remark "^8.0.0" - remark-html "6.0.1" - remark-toc "^4.0.0" - remote-origin-url "0.4.0" - shelljs "^0.7.5" - stream-array "^1.1.0" - strip-json-comments "^2.0.0" - tiny-lr "^1.0.3" - unist-builder "^1.0.0" - unist-util-visit "^1.0.1" - vfile "^2.0.0" - vfile-reporter "^4.0.0" - vfile-sort "^2.0.0" - vinyl "^2.0.0" - vinyl-fs "^2.3.1" - yargs "^6.0.1" - -dom-serialize@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" - dependencies: - custom-event "~1.0.0" - ent "~2.2.0" - extend "^3.0.0" - void-elements "^2.0.0" - -domain-browser@^1.1.1: - version "1.1.7" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - dependencies: - readable-stream "~1.1.9" - -duplexer2@^0.1.2, duplexer2@~0.1.0: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - dependencies: - readable-stream "^2.0.2" - -duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - -duplexify@^3.2.0, duplexify@^3.5.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd" - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - dependencies: - jsbn "~0.1.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - -ejs@0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-0.8.3.tgz#db8aac47ff80a7df82b4c82c126fe8970870626f" - -ejs@^2.3.1, ejs@^2.5.1: - version "2.5.7" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a" - -elliptic@^6.0.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -"emoji-regex@>=6.0.0 <=6.1.1": - version "6.1.1" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - -encodeurl@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" - -end-of-stream@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" - dependencies: - once "^1.4.0" - -end-of-stream@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" - dependencies: - once "~1.3.0" - -engine.io-client@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.3.tgz#1798ed93451246453d4c6f635d7a201fe940d5ab" - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "2.3.3" - engine.io-parser "1.3.2" - has-cors "1.1.0" - indexof "0.0.1" - parsejson "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - ws "1.1.2" - xmlhttprequest-ssl "1.5.3" - yeast "0.1.2" - -engine.io-parser@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a" - dependencies: - after "0.8.2" - arraybuffer.slice "0.0.6" - base64-arraybuffer "0.1.5" - blob "0.0.4" - has-binary "0.1.7" - wtf-8 "1.0.0" - -engine.io@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.3.tgz#8de7f97895d20d39b85f88eeee777b2bd42b13d4" - dependencies: - accepts "1.3.3" - base64id "1.0.0" - cookie "0.3.1" - debug "2.3.3" - engine.io-parser "1.3.2" - ws "1.1.2" - -enhanced-resolve@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - object-assign "^4.0.1" - tapable "^0.2.7" - -enhanced-resolve@~0.9.0: - version "0.9.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.2.0" - tapable "^0.1.8" - -ent@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - -errno@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" - dependencies: - prr "~0.0.0" - -error-ex@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" - dependencies: - is-arrayish "^0.2.1" - -error@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02" - dependencies: - string-template "~0.2.1" - xtend "~4.0.0" - -errorhandler@~1.4.2: - version "1.4.3" - resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.4.3.tgz#b7b70ed8f359e9db88092f2d20c0f831420ad83f" - dependencies: - accepts "~1.3.0" - escape-html "~1.0.3" - -es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: - version "0.10.30" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.30.tgz#7141a16836697dbabfaaaeee41495ce29f52c939" - dependencies: - es6-iterator "2" - es6-symbol "~3.1" - -es5-shim@^4.0.5, es5-shim@^4.5.2: - version "4.5.9" - resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.9.tgz#2a1e2b9e583ff5fed0c20a3ee2cbf3f75230a5c0" - -es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-symbol "^3.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - -escape-html@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.2.tgz#d77d32fa98e38c2f41ae85e9278e0e0e6ba1022c" - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - -escape-string-regexp@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -escodegen@1.8.x, escodegen@1.x.x: - version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-config-standard@^10.2.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" - -eslint-import-resolver-node@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc" - dependencies: - debug "^2.6.8" - resolve "^1.2.0" - -eslint-module-utils@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" - dependencies: - debug "^2.6.8" - pkg-dir "^1.0.0" - -eslint-plugin-import@^2.2.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f" - dependencies: - builtin-modules "^1.1.1" - contains-path "^0.1.0" - debug "^2.6.8" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.1" - eslint-module-utils "^2.1.1" - has "^1.0.1" - lodash.cond "^4.3.0" - minimatch "^3.0.3" - read-pkg-up "^2.0.0" - -eslint-plugin-node@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.1.1.tgz#a7ed956e780c22aef6afd1116005acd82f26eac6" - dependencies: - ignore "^3.3.3" - minimatch "^3.0.4" - resolve "^1.3.3" - semver "5.3.0" - -eslint-plugin-promise@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" - -eslint-plugin-standard@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" - -eslint-scope@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint@^4.0.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.6.1.tgz#ddc7fc7fd70bf93205b0b3449bb16a1e9e7d4950" - dependencies: - ajv "^5.2.0" - babel-code-frame "^6.22.0" - chalk "^2.1.0" - concat-stream "^1.6.0" - cross-spawn "^5.1.0" - debug "^2.6.8" - doctrine "^2.0.0" - eslint-scope "^3.7.1" - espree "^3.5.0" - esquery "^1.0.0" - estraverse "^4.2.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^9.17.0" - 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 "^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 "^4.0.0" - progress "^2.0.0" - require-uncached "^1.0.3" - semver "^5.3.0" - strip-ansi "^4.0.0" - strip-json-comments "~2.0.1" - table "^4.0.1" - text-table "~0.2.0" - -espree@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d" - dependencies: - acorn "^5.1.1" - acorn-jsx "^3.0.0" - -esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - -esprima@3.x.x: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - -esprima@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" - -esquery@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" - dependencies: - estraverse "^4.0.0" - -esrecurse@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" - dependencies: - estraverse "^4.1.0" - object-assign "^4.0.1" - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - -estree-walker@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.3.1.tgz#e6b1a51cf7292524e7237c312e5fe6660c1ce1aa" - -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -etag@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" - -event-emitter@^0.3.5, event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - dependencies: - d "1" - es5-ext "~0.10.14" - -event-stream@*, event-stream@^3.3.2: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - 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" - -event-stream@~3.0.18: - version "3.0.20" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.0.20.tgz#038bbb2ea9ea90385b26fbc1854d0b539f2abea3" - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.0.3" - pause-stream "0.0.11" - split "0.2" - stream-combiner "~0.0.3" - through "~2.3.1" - -eventemitter3@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" - -events@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.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" - -expand-braces@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea" - dependencies: - array-slice "^0.2.3" - array-unique "^0.2.1" - braces "^0.1.2" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - -expand-brackets@^2.0.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - 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" - -expand-range@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" - dependencies: - is-number "^0.1.1" - repeat-string "^0.2.2" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -expand-tilde@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-1.2.2.tgz#0b81eba897e5a3d31d1c3d102f8f01441e559449" - dependencies: - os-homedir "^1.0.1" - -expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - dependencies: - homedir-polyfill "^1.0.1" - -expect.js@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" - -express-session@~1.11.3: - version "1.11.3" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.11.3.tgz#5cc98f3f5ff84ed835f91cbf0aabd0c7107400af" - dependencies: - cookie "0.1.3" - cookie-signature "1.0.6" - crc "3.3.0" - debug "~2.2.0" - depd "~1.0.1" - on-headers "~1.0.0" - parseurl "~1.3.0" - uid-safe "~2.0.0" - utils-merge "1.0.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - dependencies: - is-extendable "^0.1.0" - -extend@3, extend@^3.0.0, extend@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - -external-editor@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" - dependencies: - iconv-lite "^0.4.17" - jschardet "^1.4.2" - tmp "^0.0.31" - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - -extglob@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-1.1.0.tgz#0678b4e2ce45c0e4e50f5e5eafb1b0dab5b4e424" - dependencies: - array-unique "^0.3.2" - define-property "^0.2.5" - expand-brackets "^2.0.1" - extend-shallow "^2.0.1" - fragment-cache "^0.2.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^2.1.0" - -extsprintf@1.3.0, extsprintf@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - -faker@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/faker/-/faker-3.1.0.tgz#0f908faf4e6ec02524e54a57e432c5c013e08c9f" - -fancy-log@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" - dependencies: - chalk "^1.1.1" - time-stamp "^1.0.0" - -fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - -faye-websocket@~0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" - dependencies: - websocket-driver ">=0.5.1" - -figures@^1.3.5: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -file-loader@^0.8.1: - version "0.8.5" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.8.5.tgz#9275d031fe780f27d47f5f4af02bd43713cc151b" - dependencies: - loader-utils "~0.2.5" - -file-uri-to-path@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - -fileset@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" - dependencies: - glob "^7.0.3" - minimatch "^3.0.3" - -fill-keys@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" - dependencies: - is-object "~1.0.1" - merge-descriptors "~1.0.0" - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -finalhandler@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.0.tgz#965a52d9e8d05d2b857548541fb89b53a2497d9b" - dependencies: - debug "~2.2.0" - escape-html "1.0.2" - on-finished "~2.3.0" - unpipe "~1.0.0" - -finalhandler@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7" - dependencies: - debug "2.6.8" - encodeurl "~1.0.1" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.1" - statuses "~1.3.1" - unpipe "~1.0.0" - -find-cache-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^2.0.0" - -find-index@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - dependencies: - locate-path "^2.0.0" - -findup-sync@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.3.tgz#40043929e7bc60adf0b7f4827c4c6e75a0deca12" - dependencies: - detect-file "^0.1.0" - is-glob "^2.0.1" - micromatch "^2.3.7" - resolve-dir "^0.1.0" - -fined@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" - 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" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - -flagged-respawn@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-0.3.2.tgz#ff191eddcd7088a675b2610fffc976be9b8074b5" - -flat-cache@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" - dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" - -for-in@^1.0.1, for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - dependencies: - for-in "^1.0.1" - -foreachasync@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6" - -forever-agent@~0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.5.2.tgz#6d0e09c4921f94a27f63d3b49c5feff1ea4c5130" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -fork-stream@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70" - -form-data@~0.1.0: - version "0.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-0.1.4.tgz#91abd788aba9702b1aabfa8bc01031a2ac9e3b12" - dependencies: - async "~0.9.0" - combined-stream "~0.0.4" - mime "~1.2.11" - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -formatio@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" - dependencies: - samsam "~1.1" - -fragment-cache@^0.2.0, fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - dependencies: - map-cache "^0.2.2" - -fresh@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" - -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - -fs-access@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" - dependencies: - null-check "^1.0.0" - -fs-exists-sync@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" - -fs-extra@~0.6.1: - version "0.6.4" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.6.4.tgz#f46f0c75b7841f8d200b3348cd4d691d5a099d15" - dependencies: - jsonfile "~1.0.1" - mkdirp "0.3.x" - ncp "~0.4.2" - rimraf "~2.2.0" - -fs.extra@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fs.extra/-/fs.extra-1.3.2.tgz#dd023f93013bee24531f1b33514c37b20fd93349" - dependencies: - fs-extra "~0.6.1" - mkdirp "~0.3.5" - walk "^2.3.9" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fsevents@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4" - dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.36" - -fstream-ignore@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -"fstream@>= 0.1.30 < 1": - version "0.1.31" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-0.1.31.tgz#7337f058fbbbbefa8c9f561a28cab0849202c988" - dependencies: - graceful-fs "~3.0.2" - inherits "~2.0.0" - mkdirp "0.5" - rimraf "2" - -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -ftp@~0.3.10: - version "0.3.10" - resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d" - dependencies: - readable-stream "1.1.x" - xregexp "2.0.0" - -function-bind@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gaze@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" - dependencies: - globule "~0.1.0" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - -get-caller-file@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" - -get-port@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - -get-uri@2: - version "2.0.1" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.1.tgz#dbdcacacd8c608a38316869368117697a1631c59" - dependencies: - data-uri-to-buffer "1" - debug "2" - extend "3" - file-uri-to-path "1" - ftp "~0.3.10" - readable-stream "2" - -get-value@^2.0.3, get-value@^2.0.5, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -git-up@^2.0.0: - version "2.0.8" - resolved "https://registry.yarnpkg.com/git-up/-/git-up-2.0.8.tgz#24be049c9f0b193481d2df4e016a16530a5f4ef4" - dependencies: - is-ssh "^1.3.0" - parse-url "^1.3.0" - -git-url-parse@^6.0.1: - version "6.2.2" - resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-6.2.2.tgz#be49024e14b8487553436b4572b8b439532fa871" - dependencies: - git-up "^2.0.0" - -github-slugger@1.1.3, github-slugger@^1.0.0, github-slugger@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.1.3.tgz#314a6e759a18c2b0cc5760d512ccbab549c549a7" - dependencies: - emoji-regex ">=6.0.0 <=6.1.1" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^3.1.5: - version "3.1.18" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" - dependencies: - glob "^4.3.1" - glob2base "^0.0.12" - minimatch "^2.0.1" - ordered-read-streams "^0.1.0" - through2 "^0.6.1" - unique-stream "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob-watcher@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" - dependencies: - gaze "^0.5.1" - -glob2base@^0.0.12: - version "0.0.12" - resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" - dependencies: - find-index "^0.1.1" - -glob@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.3.tgz#e313eeb249c7affaa5c475286b0e115b59839467" - dependencies: - graceful-fs "~2.0.0" - inherits "2" - minimatch "~0.2.11" - -glob@7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^4.3.1: - version "4.5.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "^2.0.1" - once "^1.3.0" - -glob@^5.0.10, glob@^5.0.15, glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - 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" - -glob@~3.1.21: - version "3.1.21" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" - dependencies: - graceful-fs "~1.2.0" - inherits "1" - minimatch "~0.2.11" - -glob@~4.3.0: - version "4.3.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-4.3.5.tgz#80fbb08ca540f238acce5d11d1e9bc41e75173d3" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "^2.0.1" - once "^1.3.0" - -global-modules@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" - dependencies: - global-prefix "^0.1.4" - is-windows "^0.2.0" - -global-prefix@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-0.1.5.tgz#8d3bc6b8da3ca8112a160d8d496ff0462bfef78f" - dependencies: - homedir-polyfill "^1.0.0" - ini "^1.3.4" - is-windows "^0.2.0" - which "^1.2.12" - -globals-docs@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/globals-docs/-/globals-docs-2.3.0.tgz#dca4088af196f7800f4eba783eaeff335cb6759c" - -globals@^9.17.0, globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -globule@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" - dependencies: - glob "~3.1.21" - lodash "~1.0.1" - minimatch "~0.2.11" - -glogg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" - dependencies: - sparkles "^1.0.0" - -graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.0, graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -graceful-fs@^3.0.0, graceful-fs@~3.0.2: - version "3.0.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" - dependencies: - natives "^1.1.0" - -graceful-fs@~1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" - -graceful-fs@~2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-2.0.3.tgz#7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0" - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - -growl@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.8.1.tgz#4b2dec8d907e93db336624dcec0183502f8c9428" - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - -gulp-babel@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-6.1.2.tgz#7c0176e4ba3f244c60588a0c4b320a45d1adefce" - dependencies: - babel-core "^6.0.2" - gulp-util "^3.0.0" - object-assign "^4.0.1" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl-sourcemaps-apply "^0.2.0" - -gulp-clean@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/gulp-clean/-/gulp-clean-0.3.2.tgz#a347d473acea40182f935587a451941671928102" - dependencies: - gulp-util "^2.2.14" - rimraf "^2.2.8" - through2 "^0.4.2" - -gulp-concat@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/gulp-concat/-/gulp-concat-2.6.1.tgz#633d16c95d88504628ad02665663cee5a4793353" - dependencies: - concat-with-sourcemaps "^1.0.0" - through2 "^2.0.0" - vinyl "^2.0.0" - -gulp-connect@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/gulp-connect/-/gulp-connect-5.0.0.tgz#f2fdf306ae911468368c2285f2d782f13eddaf4e" - dependencies: - connect "^2.30.0" - connect-livereload "^0.5.4" - event-stream "^3.3.2" - gulp-util "^3.0.6" - tiny-lr "^0.2.1" - -gulp-documentation@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/gulp-documentation/-/gulp-documentation-3.2.1.tgz#af524abfd72e23e7155f00b2a18a07a3642a8dd5" - dependencies: - through2 "^2.0.3" - vinyl "^2.1.0" - -gulp-eslint@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/gulp-eslint/-/gulp-eslint-4.0.0.tgz#16d9ea4d696e7b7a9d65eeb1aa5bc4ba0a22c7f7" - dependencies: - eslint "^4.0.0" - gulp-util "^3.0.8" - -gulp-footer@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/gulp-footer/-/gulp-footer-1.0.5.tgz#e84ca777e266be7bbc2d45d2df0e7eba8dfa3e54" - dependencies: - event-stream "*" - gulp-util "*" - lodash.assign "*" - -gulp-header@^1.7.1: - version "1.8.9" - resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.9.tgz#c9f10fee0632d81e939789c6ecf45a151bf3098b" - dependencies: - concat-with-sourcemaps "*" - gulp-util "*" - object-assign "*" - through2 "^2.0.0" - -gulp-if@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-2.0.2.tgz#a497b7e7573005041caa2bc8b7dda3c80444d629" - dependencies: - gulp-match "^1.0.3" - ternary-stream "^2.0.1" - through2 "^2.0.1" - -gulp-js-escape@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz#1cd445fbd009e0da76959a03a7f49b3566aff868" - dependencies: - through2 "^0.6.3" - -gulp-match@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.0.3.tgz#91c7c0d7f29becd6606d57d80a7f8776a87aba8e" - dependencies: - minimatch "^3.0.3" - -gulp-optimize-js@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz#5fd15c68b36f6e1e7387784f8578435f75696245" - dependencies: - gulp-util "^3.0.7" - lodash "^4.16.2" - optimize-js "^1.0.0" - through2 "^2.0.1" - -gulp-rename@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817" - -gulp-replace@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-0.4.0.tgz#e22bc9c03e9d051b32881cc589bd3e8c4e54168a" - dependencies: - event-stream "~3.0.18" - istextorbinary "~1.0.0" - replacestream "0.1.3" - -gulp-shell@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/gulp-shell/-/gulp-shell-0.5.2.tgz#a4959ca0651ad1c7bbfe70b2d0adbbb4e1aea98d" - dependencies: - async "^1.5.0" - gulp-util "^3.0.7" - lodash "^4.0.0" - through2 "^2.0.0" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-sourcemaps@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.1.tgz#833a4e28f0b8f4661075032cd782417f7cd8fb0b" - dependencies: - "@gulp-sourcemaps/identity-map" "1.X" - "@gulp-sourcemaps/map-sources" "1.X" - acorn "4.X" - convert-source-map "1.X" - css "2.X" - debug-fabulous ">=0.1.1" - detect-newline "2.X" - graceful-fs "4.X" - source-map "0.X" - strip-bom-string "1.X" - through2 "2.X" - vinyl "1.X" - -gulp-uglify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.0.tgz#0df0331d72a0d302e3e37e109485dddf33c6d1ca" - dependencies: - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash "^4.13.1" - make-error-cause "^1.1.1" - through2 "^2.0.0" - uglify-js "^3.0.5" - vinyl-sourcemaps-apply "^0.2.0" - -gulp-util@*, gulp-util@^3.0.0, gulp-util@^3.0.4, gulp-util@^3.0.6, gulp-util@^3.0.7, gulp-util@^3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - 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" - -gulp-util@^2.2.14: - version "2.2.20" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-2.2.20.tgz#d7146e5728910bd8f047a6b0b1e549bc22dbd64c" - 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" - -gulp-webdriver@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz#98ce81cf9ae06a7a1907b86d10f69386f4383a2d" - dependencies: - dargs christian-bromann/dargs - deepmerge "^0.2.7" - gulp-util "^3.0.4" - through2 "^0.6.5" - webdriverio "^3.4.0" - -gulp@^3.8.7: - version "3.9.1" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" - dependencies: - archy "^1.0.0" - chalk "^1.0.0" - deprecated "^0.0.1" - gulp-util "^3.0.0" - interpret "^1.0.0" - liftoff "^2.1.0" - minimist "^1.1.0" - orchestrator "^0.3.0" - pretty-hrtime "^1.0.0" - semver "^4.1.0" - tildify "^1.0.0" - v8flags "^2.0.2" - vinyl-fs "^0.3.0" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - dependencies: - glogg "^1.0.0" - -handlebars@^4.0.1, handlebars@^4.0.3: - version "4.0.10" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" - dependencies: - async "^1.4.0" - optimist "^0.6.1" - source-map "^0.4.4" - optionalDependencies: - uglify-js "^2.6" - -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - -has-ansi@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" - dependencies: - ansi-regex "^0.2.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-binary@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c" - dependencies: - isarray "0.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - dependencies: - sparkles "^1.0.0" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - -has@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" - dependencies: - function-bind "^1.0.2" - -hash-base@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" - dependencies: - inherits "^2.0.1" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" - -hast-util-is-element@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz#3f7216978b2ae14d98749878782675f33be3ce00" - -hast-util-sanitize@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/hast-util-sanitize/-/hast-util-sanitize-1.1.1.tgz#c439852d9db7ff554ecd6be96435a6a8274ade32" - dependencies: - xtend "^4.0.1" - -hast-util-to-html@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz#882c99849e40130e991c042e456d453d95c36cff" - dependencies: - ccount "^1.0.0" - comma-separated-tokens "^1.0.1" - hast-util-is-element "^1.0.0" - hast-util-whitespace "^1.0.0" - html-void-elements "^1.0.0" - kebab-case "^1.0.0" - property-information "^3.1.0" - space-separated-tokens "^1.0.0" - stringify-entities "^1.0.1" - unist-util-is "^2.0.0" - xtend "^4.0.1" - -hast-util-whitespace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz#bd096919625d2936e1ff17bc4df7fd727f17ece9" - -hawk@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-1.1.1.tgz#87cd491f9b46e4e2aeaca335416766885d2d1ed9" - dependencies: - boom "0.4.x" - cryptiles "0.2.x" - hoek "0.9.x" - sntp "0.2.x" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -highlight.js@^9.1.0: - version "9.12.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -hoek@0.9.x: - version "0.9.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-0.9.1.tgz#3d322462badf07716ea7eb85baf88079cddce505" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - dependencies: - parse-passwd "^1.0.0" - -hosted-git-info@^2.1.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" - -html-void-elements@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.2.tgz#9d22e0ca32acc95b3f45b8d5b4f6fbdc05affd55" - -http-errors@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257" - dependencies: - depd "1.1.0" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" - -http-errors@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" - dependencies: - inherits "~2.0.1" - statuses "1" - -http-errors@~1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" - -http-proxy-agent@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz#cc1ce38e453bf984a0f7702d2dd59c73d081284a" - dependencies: - agent-base "2" - debug "2" - extend "3" - -http-proxy@^1.13.0: - version "1.16.2" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" - dependencies: - eventemitter3 "1.x.x" - requires-port "1.x.x" - -http-signature@~0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-0.10.1.tgz#4fbdac132559aa8323121e540779c0a012b27e66" - dependencies: - asn1 "0.1.11" - assert-plus "^0.1.5" - ctype "0.5.3" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" - -https-proxy-agent@1, https-proxy-agent@1.0.0, https-proxy-agent@^1.0.0, https-proxy-agent@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6" - dependencies: - agent-base "2" - debug "2" - extend "3" - -iconv-lite@0.4.11: - version "0.4.11" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.11.tgz#2ecb42fd294744922209a2e7c404dac8793d8ade" - -iconv-lite@0.4.13: - version "0.4.13" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" - -iconv-lite@0.4.15: - version "0.4.15" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" - -iconv-lite@0.4.18, iconv-lite@^0.4.17: - version "0.4.18" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" - -ieee754@^1.1.4: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" - -ignore-loader@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" - -ignore@^3.3.3: - version "3.3.5" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - dependencies: - repeating "^2.0.0" - -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" - -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - -ini@^1.3.3, ini@^1.3.4, ini@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" - -inquirer@^0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.8.5.tgz#dbd740cf6ca3b731296a63ce6f6d961851f336df" - dependencies: - ansi-regex "^1.1.1" - chalk "^1.0.0" - cli-width "^1.0.1" - figures "^1.3.5" - lodash "^3.3.1" - readline2 "^0.1.1" - rx "^2.4.3" - through "^2.3.6" - -inquirer@^3.0.6: - version "3.2.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.3.tgz#1c7b1731cf77b934ec47d22c9ac5aa8fe7fbe095" - dependencies: - ansi-escapes "^2.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" - -interpret@^0.6.4: - version "0.6.6" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b" - -interpret@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" - -invariant@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - -ip@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.0.1.tgz#c7e356cdea225ae71b36d70f2e71a92ba4e42590" - -ip@^1.1.4: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - -is-absolute@^0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb" - dependencies: - is-relative "^0.2.1" - is-windows "^0.2.0" - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - dependencies: - kind-of "^3.0.2" - -is-alphabetical@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.1.tgz#c77079cc91d4efac775be1034bf2d243f95e6f08" - -is-alphanumeric@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" - -is-alphanumerical@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz#dfb4aa4d1085e33bdb61c2dee9c80e9c6c19f53b" - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.4, is-buffer@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" - -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - dependencies: - builtin-modules "^1.0.0" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - dependencies: - kind-of "^3.0.2" - -is-decimal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.1.tgz#f5fb6a94996ad9e8e3761fbfbd091f1fca8c4e82" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.1.tgz#2c6023599bde2de9d5d2c8b9a9d94082036b6ef2" - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - -is-generator@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-generator/-/is-generator-1.0.3.tgz#c14c21057ed36e328db80347966c693f886389f3" - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - dependencies: - is-extglob "^2.1.0" - -is-hexadecimal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" - -is-my-json-valid@^2.12.4: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-number@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -is-object@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - -is-odd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088" - dependencies: - is-number "^3.0.0" - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - -is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" - dependencies: - path-is-inside "^1.0.1" - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - -is-plain-object@^2.0.1, is-plain-object@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - dependencies: - isobject "^3.0.1" - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - -is-promise@^2.1, is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - -is-relative@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" - dependencies: - is-unc-path "^0.1.1" - -is-resolvable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" - dependencies: - tryit "^1.0.1" - -is-ssh@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.0.tgz#ebea1169a2614da392a63740366c3ce049d8dff6" - dependencies: - protocols "^1.1.0" - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -is-unc-path@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9" - dependencies: - unc-path-regex "^0.1.0" - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - -is-whitespace-character@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz#9ae0176f3282b65457a1992cdb084f8a5f833e3b" - -is-windows@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" - -is-word-character@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isbinaryfile@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - -isobject@^2.0.0, isobject@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -istanbul-api@^1.1.8: - version "1.1.14" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.1.14.tgz#25bc5701f7c680c0ffff913de46e3619a3a6e680" - dependencies: - async "^2.1.4" - fileset "^2.0.2" - istanbul-lib-coverage "^1.1.1" - istanbul-lib-hook "^1.0.7" - istanbul-lib-instrument "^1.8.0" - istanbul-lib-report "^1.1.1" - istanbul-lib-source-maps "^1.2.1" - istanbul-reports "^1.1.2" - js-yaml "^3.7.0" - mkdirp "^0.5.1" - once "^1.4.0" - -istanbul-instrumenter-loader@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz#9f553923b22360bac95e617aaba01add1f7db0b2" - dependencies: - convert-source-map "^1.5.0" - istanbul-lib-instrument "^1.7.3" - loader-utils "^1.1.0" - schema-utils "^0.3.0" - -istanbul-lib-coverage@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" - -istanbul-lib-hook@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc" - dependencies: - append-transform "^0.4.0" - -istanbul-lib-instrument@^1.7.3, istanbul-lib-instrument@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.8.0.tgz#66f6c9421cc9ec4704f76f2db084ba9078a2b532" - dependencies: - babel-generator "^6.18.0" - babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" - babylon "^6.18.0" - istanbul-lib-coverage "^1.1.1" - semver "^5.3.0" - -istanbul-lib-report@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9" - dependencies: - istanbul-lib-coverage "^1.1.1" - mkdirp "^0.5.1" - path-parse "^1.0.5" - supports-color "^3.1.2" - -istanbul-lib-source-maps@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c" - dependencies: - debug "^2.6.3" - istanbul-lib-coverage "^1.1.1" - mkdirp "^0.5.1" - rimraf "^2.6.1" - source-map "^0.5.3" - -istanbul-reports@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.2.tgz#0fb2e3f6aa9922bd3ce45d05d8ab4d5e8e07bd4f" - dependencies: - handlebars "^4.0.3" - -istanbul@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - 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" - -istextorbinary@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-1.0.2.tgz#ace19354d1a9a0173efeb1084ce0f87b0ad7decf" - dependencies: - binaryextensions "~1.0.0" - textextensions "~1.0.0" - -jade@0.26.3: - version "0.26.3" - resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" - dependencies: - commander "0.6.1" - mkdirp "0.3.0" - -js-tokens@^3.0.0, js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - -js-yaml@3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - -js-yaml@3.x, js-yaml@^3.7.0, js-yaml@^3.8.4, js-yaml@^3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -jschardet@^1.4.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.1.tgz#c519f629f86b3a5bedba58a88d311309eec097f9" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - -json-loader@^0.5.1, json-loader@^0.5.4: - version "0.5.7" - resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.0, json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - -json5@^0.5.0, json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - -jsonfile@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-1.0.1.tgz#ea5efe40b83690b98667614a7392fc60e842c0dd" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -just-clone@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/just-clone/-/just-clone-1.0.2.tgz#bfb3faef65aa12a316058712945c326fd8f01434" - -karma-babel-preprocessor@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz#7ae1d3e64950dbe11f421b74040ab08fb5a66c21" - dependencies: - babel-core "^6.0.0" - -karma-browserstack-launcher@^1.0.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz#61fe3d36b1cf10681e40f9d874bf37271fb1c674" - dependencies: - browserstack "1.5.0" - browserstacktunnel-wrapper "~2.0.1" - q "~1.5.0" - -karma-chai@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/karma-chai/-/karma-chai-0.1.0.tgz#bee5ad40400517811ae34bb945f762909108b79a" - -karma-chrome-launcher@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf" - dependencies: - fs-access "^1.0.0" - which "^1.2.1" - -karma-coverage-istanbul-reporter@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.3.0.tgz#d142cd9c55731c9e363ef7374e8ef1a31bebfadb" - dependencies: - istanbul-api "^1.1.8" - minimatch "^3.0.4" - -karma-es5-shim@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz#cdd00333cce77c2e4ce03e3ac93f2f8ecd1fb952" - dependencies: - es5-shim "^4.0.5" - -karma-expect@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/karma-expect/-/karma-expect-1.1.3.tgz#c6b0a56ff18903db11af4f098cc6e7cf198ce275" - dependencies: - expect.js "^0.3.1" - -karma-firefox-launcher@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-1.0.1.tgz#ce58f47c2013a88156d55a5d61337c099cf5bb51" - -karma-ie-launcher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz#497986842c490190346cd89f5494ca9830c6d59c" - dependencies: - lodash "^4.6.1" - -karma-mocha@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-1.3.0.tgz#eeaac7ffc0e201eb63c467440d2b69c7cf3778bf" - dependencies: - minimist "1.2.0" - -karma-opera-launcher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/karma-opera-launcher/-/karma-opera-launcher-1.0.0.tgz#fa51628531a1d0be84b2d8dc0d7ee209fc8ff91a" - -karma-requirejs@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/karma-requirejs/-/karma-requirejs-1.1.0.tgz#fddae2cb87d7ebc16fb0222893564d7fee578798" - -karma-safari-launcher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz#96982a2cc47d066aae71c553babb28319115a2ce" - -karma-sauce-launcher@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/karma-sauce-launcher/-/karma-sauce-launcher-1.2.0.tgz#6f2558ddef3cf56879fa27540c8ae9f8bfd16bca" - dependencies: - q "^1.5.0" - sauce-connect-launcher "^1.2.2" - saucelabs "^1.4.0" - wd "^1.4.0" - -karma-script-launcher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz#cd017c4de5ef09e5a9da793276176108dd4b542d" - -karma-sinon-ie@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/karma-sinon-ie/-/karma-sinon-ie-2.0.0.tgz#d07f05ac911baea5f6dbc95e1404fd9c93f6cc65" - -karma-sourcemap-loader@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8" - dependencies: - graceful-fs "^4.1.2" - -karma-spec-reporter@^0.0.31: - version "0.0.31" - resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz#4830dc7148a155c7d7a186e632339a0d80fadec3" - dependencies: - colors "^1.1.2" - -karma-webpack@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-2.0.4.tgz#3e2d4f48ba94a878e1c66bb8e1ae6128987a175b" - dependencies: - async "~0.9.0" - loader-utils "^0.2.5" - lodash "^3.8.0" - source-map "^0.1.41" - webpack-dev-middleware "^1.0.11" - -karma@^1.7.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/karma/-/karma-1.7.1.tgz#85cc08e9e0a22d7ce9cca37c4a1be824f6a2b1ae" - dependencies: - bluebird "^3.3.0" - body-parser "^1.16.1" - chokidar "^1.4.1" - colors "^1.1.0" - combine-lists "^1.0.0" - connect "^3.6.0" - core-js "^2.2.0" - di "^0.0.1" - dom-serialize "^2.2.0" - expand-braces "^0.1.1" - glob "^7.1.1" - graceful-fs "^4.1.2" - http-proxy "^1.13.0" - isbinaryfile "^3.0.0" - lodash "^3.8.0" - log4js "^0.6.31" - mime "^1.3.4" - minimatch "^3.0.2" - optimist "^0.6.1" - qjobs "^1.1.4" - range-parser "^1.2.0" - rimraf "^2.6.0" - safe-buffer "^5.0.1" - socket.io "1.7.3" - source-map "^0.5.3" - tmp "0.0.31" - useragent "^2.1.12" - -kebab-case@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/kebab-case/-/kebab-case-1.0.0.tgz#3f9e4990adcad0c686c0e701f7645868f75f91eb" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.0.2.tgz#f57bec933d9a2209ffa96c5c08343607b7035fda" - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - -lazy-cache@^2.0.1, lazy-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" - dependencies: - set-getter "^0.1.0" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - dependencies: - readable-stream "^2.0.5" - -lazystream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-0.1.0.tgz#1b25d63c772a4c20f0a5ed0a9d77f484b6e16920" - dependencies: - readable-stream "~1.0.2" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - dependencies: - invert-kv "^1.0.0" - -lcov-parse@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -liftoff@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.3.0.tgz#a98f2ff67183d8ba7cfaca10548bd7ff0550b385" - dependencies: - extend "^3.0.0" - findup-sync "^0.4.2" - fined "^1.0.1" - flagged-respawn "^0.3.2" - lodash.isplainobject "^4.0.4" - lodash.isstring "^4.0.1" - lodash.mapvalues "^4.4.0" - rechoir "^0.6.2" - resolve "^1.1.7" - -livereload-js@^2.2.0, livereload-js@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.2.2.tgz#6c87257e648ab475bc24ea257457edcc1f8d0bc2" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - 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" - -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - -loader-runner@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" - -loader-utils@^0.2.11, loader-utils@^0.2.5, loader-utils@~0.2.2, loader-utils@~0.2.3, loader-utils@~0.2.5: - version "0.2.17" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - object-assign "^4.0.1" - -loader-utils@^1.0.2, loader-utils@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - -localtunnel@^1.3.0: - version "1.8.3" - resolved "https://registry.yarnpkg.com/localtunnel/-/localtunnel-1.8.3.tgz#dcc5922fd85651037d4bde24fd93248d0b24eb05" - dependencies: - debug "2.6.8" - openurl "1.1.1" - request "2.81.0" - yargs "3.29.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -lodash._arraycopy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz#76e7b7c1f1fb92547374878a562ed06a3e50f6e1" - -lodash._arrayeach@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz#bab156b2a90d3f1bbd5c653403349e5e5933ef9e" - -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._baseclone@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz#303519bf6393fe7e42f34d8b630ef7794e3542b7" - dependencies: - lodash._arraycopy "^3.0.0" - lodash._arrayeach "^3.0.0" - lodash._baseassign "^3.0.0" - lodash._basefor "^3.0.0" - lodash.isarray "^3.0.0" - lodash.keys "^3.0.0" - -lodash._baseclone@^4.0.0: - version "4.5.7" - resolved "https://registry.yarnpkg.com/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz#ce42ade08384ef5d62fa77c30f61a46e686f8434" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - -lodash._basefor@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz#7550b4e9218ef09fad24343b612021c79b4c20c2" - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - -lodash._bindcallback@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - -lodash._escapehtmlchar@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d" - dependencies: - lodash._htmlescapes "~2.4.1" - -lodash._escapestringchar@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz#ecfe22618a2ade50bfeea43937e51df66f0edb72" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - -lodash._htmlescapes@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz#32d14bf0844b6de6f8b62a051b4f67c228b624cb" - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - -lodash._isnative@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c" - -lodash._objecttypes@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11" - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - -lodash._reinterpolate@^2.4.1, lodash._reinterpolate@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz#4f1227aa5a8711fc632f5b07a1f4607aab8b3222" - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - -lodash._reunescapedhtml@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz#747c4fc40103eb3bb8a0976e571f7a2659e93ba7" - dependencies: - lodash._htmlescapes "~2.4.1" - lodash.keys "~2.4.1" - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - -lodash._shimkeys@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203" - dependencies: - lodash._objecttypes "~2.4.1" - -lodash._stack@^4.0.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/lodash._stack/-/lodash._stack-4.1.3.tgz#751aa76c1b964b047e76d14fc72a093fcb5e2dd0" - -lodash.assign@*, lodash.assign@^4.0.3, lodash.assign@^4.0.6: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - -lodash.clone@3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-3.0.3.tgz#84688c73d32b5a90ca25616963f189252a997043" - dependencies: - lodash._baseclone "^3.0.0" - lodash._bindcallback "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.clone@^4.3.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" - -lodash.cond@^4.3.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" - -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.defaults@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-2.4.1.tgz#a7e8885f05e68851144b6e12a8f3678026bc4c54" - dependencies: - lodash._objecttypes "~2.4.1" - lodash.keys "~2.4.1" - -lodash.defaultsdeep@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz#6c1a586e6c5647b0e64e2d798141b8836158be8a" - dependencies: - lodash._baseclone "^4.0.0" - lodash._stack "^4.0.0" - lodash.isplainobject "^4.0.0" - lodash.keysin "^4.0.0" - lodash.mergewith "^4.0.0" - lodash.rest "^4.0.0" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - dependencies: - lodash._root "^3.0.0" - -lodash.escape@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-2.4.1.tgz#2ce12c5e084db0a57dda5e5d1eeeb9f5d175a3b4" - dependencies: - lodash._escapehtmlchar "~2.4.1" - lodash._reunescapedhtml "~2.4.1" - lodash.keys "~2.4.1" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - -lodash.isobject@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5" - dependencies: - lodash._objecttypes "~2.4.1" - -lodash.isplainobject@^4.0.0, lodash.isplainobject@^4.0.4: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.keys@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727" - dependencies: - lodash._isnative "~2.4.1" - lodash._shimkeys "~2.4.1" - lodash.isobject "~2.4.1" - -lodash.keysin@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.keysin/-/lodash.keysin-4.2.0.tgz#8cc3fb35c2d94acc443a1863e02fa40799ea6f28" - -lodash.mapvalues@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" - -lodash.mergewith@^4.0.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" - -lodash.rest@^4.0.0: - version "4.0.5" - resolved "https://registry.yarnpkg.com/lodash.rest/-/lodash.rest-4.0.5.tgz#954ef75049262038c96d1fc98b28fdaf9f0772aa" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - -lodash.some@^4.2.2: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - -lodash.template@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-2.4.1.tgz#9e611007edf629129a974ab3c48b817b3e1cf20d" - 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" - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - 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" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - -lodash.templatesettings@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz#ea76c75d11eb86d4dbe89a83893bb861929ac699" - dependencies: - lodash._reinterpolate "~2.4.1" - lodash.escape "~2.4.1" - -lodash.values@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-2.4.1.tgz#abf514436b3cb705001627978cbcf30b1280eea4" - dependencies: - lodash.keys "~2.4.1" - -lodash@4.16.2: - version "4.16.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" - -lodash@^3.3.1, lodash@^3.8.0: - version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - -lodash@^4.0.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.16.2, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@^4.8.0: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - -lodash@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" - -lodash@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.2.0.tgz#4bf50a3243f9aeb0bac41a55d3d5990675a462fb" - -log-driver@1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" - -log4js@^0.6.31: - version "0.6.38" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd" - dependencies: - readable-stream "~1.0.2" - semver "~4.3.3" - -lolex@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" - -longest-streak@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.1.tgz#42d291b5411e40365c00e63193497e2247316e35" - -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - -loose-envify@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" - dependencies: - js-tokens "^3.0.0" - -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - -lru-cache@2.2.x: - version "2.2.4" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" - -lru-cache@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -lru-cache@~2.6.5: - version "2.6.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.5.tgz#e56d6354148ede8d7707b58d143220fd08df0fd5" - -lru-queue@0.1: - version "0.1.0" - resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - dependencies: - es5-ext "~0.10.2" - -magic-string@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.16.0.tgz#970ebb0da7193301285fb1aa650f39bdd81eb45a" - dependencies: - vlq "^0.2.1" - -make-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" - dependencies: - pify "^2.3.0" - -make-error-cause@^1.1.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" - dependencies: - make-error "^1.2.0" - -make-error@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.0.tgz#52ad3a339ccf10ce62b4040b708fe707244b8b96" - -map-cache@^0.2.0, map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - -map-stream@~0.0.3: - version "0.0.7" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - -map-visit@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-0.1.5.tgz#dbe43927ce5525b80dfc1573a44d68c51f26816b" - dependencies: - lazy-cache "^2.0.1" - object-visit "^0.3.4" - -markdown-escapes@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.1.tgz#1994df2d3af4811de59a6714934c2b2292734518" - -markdown-table@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.1.tgz#4b3dd3a133d1518b8ef0dbc709bf2a1b4824bc8c" - -"match-stream@>= 0.0.2 < 1": - version "0.0.2" - resolved "https://registry.yarnpkg.com/match-stream/-/match-stream-0.0.2.tgz#99eb050093b34dffade421b9ac0b410a9cfa17cf" - dependencies: - buffers "~0.1.1" - readable-stream "~1.0.0" - -md5.js@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -mdast-util-compact@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz#cdb5f84e2b6a2d3114df33bd05d9cb32e3c4083a" - dependencies: - unist-util-modify-children "^1.0.0" - unist-util-visit "^1.1.0" - -mdast-util-definitions@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz#673f4377c3e23d3de7af7a4fe2214c0e221c5ac7" - dependencies: - unist-util-visit "^1.0.0" - -mdast-util-inject@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz#db06b8b585be959a2dcd2f87f472ba9b756f3675" - dependencies: - mdast-util-to-string "^1.0.0" - -mdast-util-to-hast@^2.1.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-2.4.2.tgz#f116e8bf3da772ba5a397a92dab090f5ba91caa0" - dependencies: - collapse-white-space "^1.0.0" - detab "^2.0.0" - mdast-util-definitions "^1.2.0" - normalize-uri "^1.0.0" - trim "0.0.1" - trim-lines "^1.0.0" - unist-builder "^1.0.1" - unist-util-generated "^1.1.0" - unist-util-position "^3.0.0" - unist-util-visit "^1.1.0" - xtend "^4.0.1" - -mdast-util-to-string@^1.0.0, mdast-util-to-string@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz#5c455c878c9355f0c1e7f3e8b719cf583691acfb" - -mdast-util-toc@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz#b1d2cb23bfb01f812fa7b55bffe8b0a8bedf6f21" - dependencies: - github-slugger "^1.1.1" - mdast-util-to-string "^1.0.2" - unist-util-visit "^1.1.0" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - dependencies: - mimic-fn "^1.0.0" - -memoizee@^0.4.5: - version "0.4.9" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.9.tgz#ea1c005f5c4c31d89a4a10e24db83fbf61cdd4f3" - dependencies: - d "1" - es5-ext "^0.10.30" - es6-weak-map "^2.0.2" - event-emitter "^0.3.5" - is-promise "^2.1" - lru-queue "0.1" - next-tick "1" - timers-ext "^0.1.2" - -memory-fs@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" - -memory-fs@^0.3.0, memory-fs@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20" - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@^0.4.0, memory-fs@~0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -meow@^3.3.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - 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" - -merge-descriptors@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - dependencies: - readable-stream "^2.0.1" - -method-override@~2.3.5: - version "2.3.9" - resolved "https://registry.yarnpkg.com/method-override/-/method-override-2.3.9.tgz#bd151f2ce34cf01a76ca400ab95c012b102d8f71" - dependencies: - debug "2.6.8" - methods "~1.1.2" - parseurl "~1.3.1" - vary "~1.1.1" - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - -micromatch@^2.1.5, micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -micromatch@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.0.4.tgz#1543f1d04813447ac852001c5f5a933401786d1d" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.2.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - extglob "^1.1.0" - fragment-cache "^0.2.1" - kind-of "^4.0.0" - nanomatch "^1.2.0" - object.pick "^1.2.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -miller-rabin@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.0.tgz#4a62fb1d42933c05583982f4c716f6fb9e6c6d3d" - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -"mime-db@>= 1.29.0 < 2", mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - -mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.6, mime-types@~2.1.7, mime-types@~2.1.9: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - dependencies: - mime-db "~1.30.0" - -mime-types@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-1.0.2.tgz#995ae1392ab8affcbfcb2641dd054e943c0d5dce" - -mime@1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" - -mime@^1.3.4: - version "1.4.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.0.tgz#69e9e0db51d44f2a3b56e48b7817d7d137f1a343" - -mime@~1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" - -mimic-fn@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" - -minimalistic-assert@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimatch@3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" - dependencies: - brace-expansion "^1.0.0" - -minimatch@^2.0.1: - version "2.0.10" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" - dependencies: - brace-expansion "^1.0.0" - -minimatch@~0.2.11: - version "0.2.14" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -minimist@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.0.tgz#4dffe525dae2b864c66c2e23c6271d7afdecefce" - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - -mixin-deep@^1.1.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.2.0.tgz#d02b8c6f8b6d4b8f5982d3fd009c4919851c3fe2" - dependencies: - for-in "^1.0.2" - is-extendable "^0.1.1" - -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" - -mkdirp@0.3.x, mkdirp@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" - -mkdirp@0.5, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mkdirp@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" - dependencies: - minimist "0.0.8" - -mkpath@1.0.0, mkpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mkpath/-/mkpath-1.0.0.tgz#ebb3a977e7af1c683ae6fda12b545a6ba6c5853d" - -mocha-nightwatch@3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz#91bcb9b3bde057dd7677c78125e491e58d66647c" - dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.2.0" - diff "1.4.0" - escape-string-regexp "1.0.5" - glob "7.0.5" - growl "1.9.2" - json3 "3.3.2" - lodash.create "3.1.1" - mkdirp "0.5.1" - supports-color "3.1.2" - -mocha@^1.21.4: - version "1.21.5" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-1.21.5.tgz#7c58b09174df976e434a23b1e8d639873fc529e9" - dependencies: - commander "2.3.0" - debug "2.0.0" - diff "1.0.8" - escape-string-regexp "1.0.2" - glob "3.2.3" - growl "1.8.1" - jade "0.26.3" - mkdirp "0.5.0" - -mock-fs@^3.11.0: - version "3.12.1" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-3.12.1.tgz#ff27824cd6ab263a7eb05a115239d41d3631f5f8" - dependencies: - rewire "2.5.2" - semver "5.3.0" - -module-deps-sortable@4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz#1251a4ba2c44a92df6989bd029da121a4f2109b0" - dependencies: - JSONStream "^1.0.3" - browser-resolve "^1.7.0" - concat-stream "~1.5.0" - defined "^1.0.0" - detective "^4.0.0" - duplexer2 "^0.1.2" - inherits "^2.0.1" - parents "^1.0.0" - readable-stream "^2.0.2" - resolve "^1.1.3" - stream-combiner2 "^1.1.1" - subarg "^1.0.0" - through2 "^2.0.0" - xtend "^4.0.0" - -module-not-found-error@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0" - -morgan@~1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.6.1.tgz#5fd818398c6819cba28a7cd6664f292fe1c0bbf2" - dependencies: - basic-auth "~1.0.3" - debug "~2.2.0" - depd "~1.0.1" - on-finished "~2.3.0" - on-headers "~1.0.0" - -ms@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.6.2.tgz#d89c2124c6fdc1353d65a8b77bf1aac4b193708c" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - -ms@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -multiparty@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/multiparty/-/multiparty-3.3.2.tgz#35de6804dc19643e5249f3d3e3bdc6c8ce301d3f" - dependencies: - readable-stream "~1.1.9" - stream-counter "~0.2.0" - -multipipe@^0.1.0, multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - dependencies: - duplexer2 "0.0.2" - -mute-stream@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.4.tgz#a9219960a6d5d5d046597aee51252c6655f7177e" - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - -nan@^2.3.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" - -nanomatch@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.0.tgz#76fdb3d4ae7617e37719e7a4047b840857c0cb1c" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - is-extglob "^2.1.1" - is-odd "^1.0.0" - kind-of "^4.0.0" - object.pick "^1.2.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -natives@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.0.tgz#e9ff841418a6b2ec7a495e939984f78f163e6e31" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - -ncp@~0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-0.4.2.tgz#abcc6cbd3ec2ed2a729ff6e7c1fa8f01784a8574" - -negotiator@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.5.3.tgz#269d5c476810ec92edbe7b6c2f28316384f9a7e8" - -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - -netmask@~1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35" - -next-tick@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - -nightwatch@^0.9.5: - version "0.9.16" - resolved "https://registry.yarnpkg.com/nightwatch/-/nightwatch-0.9.16.tgz#c4ac3ec711b0ff047c3dca9c6557365ee236519f" - dependencies: - chai-nightwatch "~0.1.x" - ejs "0.8.3" - lodash.clone "3.0.3" - lodash.defaultsdeep "4.3.2" - minimatch "3.0.3" - mkpath "1.0.0" - mocha-nightwatch "3.2.2" - optimist "0.6.1" - proxy-agent "2.0.0" - q "1.4.1" - -node-int64@~0.3.0: - version "0.3.3" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.3.3.tgz#2d6e6b2ece5de8588b43d88d1bc41b26cd1fa84d" - -node-libs-browser@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-0.7.0.tgz#3e272c0819e308935e26674408d7af0e1491b83b" - dependencies: - assert "^1.1.1" - browserify-zlib "^0.1.4" - buffer "^4.9.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "3.3.0" - domain-browser "^1.1.1" - events "^1.0.0" - https-browserify "0.0.1" - os-browserify "^0.2.0" - path-browserify "0.0.0" - process "^0.11.0" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.0.5" - stream-browserify "^2.0.1" - stream-http "^2.3.1" - string_decoder "^0.10.25" - timers-browserify "^2.0.2" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" - -node-libs-browser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646" - dependencies: - assert "^1.1.1" - browserify-zlib "^0.1.4" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^1.0.0" - https-browserify "0.0.1" - os-browserify "^0.2.0" - path-browserify "0.0.0" - process "^0.11.0" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.0.5" - stream-browserify "^2.0.1" - stream-http "^2.3.1" - string_decoder "^0.10.25" - timers-browserify "^2.0.2" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" - -node-pre-gyp@^0.6.36: - version "0.6.36" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786" - dependencies: - mkdirp "^0.5.1" - nopt "^4.0.1" - npmlog "^4.0.2" - rc "^1.1.7" - request "^2.81.0" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" - -node-uuid@~1.4.0: - version "1.4.8" - resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" - -nopt@3.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - dependencies: - abbrev "1" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-uri@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/normalize-uri/-/normalize-uri-1.1.0.tgz#01fb440c7fd059b9d9be8645aac14341efd059dd" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - dependencies: - path-key "^2.0.0" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -null-check@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -oauth-sign@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.5.0.tgz#d767f5169325620eab2e087ef0c472e773db6461" - -oauth-sign@~0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -object-assign@*, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - -object-visit@^0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-0.3.4.tgz#ae15cf86f0b2fdd551771636448452c54c3da829" - dependencies: - isobject "^2.0.0" - -object.defaults@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" - dependencies: - array-each "^1.0.1" - array-slice "^1.0.0" - for-own "^1.0.0" - isobject "^3.0.0" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -object.pick@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - dependencies: - isobject "^3.0.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.0, on-headers@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" - -once@1.x, once@^1.3.0, once@^1.3.3, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -once@~1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - dependencies: - mimic-fn "^1.0.0" - -open@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" - -openurl@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" - -optimist@0.6.1, optimist@^0.6.1, optimist@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optimize-js@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/optimize-js/-/optimize-js-1.0.3.tgz#4326af8657c4a5ff32daf726631754f72ab7fdbc" - dependencies: - acorn "^3.3.0" - concat-stream "^1.5.1" - estree-walker "^0.3.0" - magic-string "^0.16.0" - yargs "^4.8.1" - -optionator@^0.8.1, optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -options@>=0.0.5: - version "0.0.6" - resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" - -orchestrator@^0.3.0: - version "0.3.8" - resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" - dependencies: - end-of-stream "~0.1.5" - sequencify "~0.0.7" - stream-consume "~0.1.0" - -ordered-read-streams@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" - -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -os-browserify@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" - -os-homedir@^1.0.0, os-homedir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - dependencies: - lcid "^1.0.0" - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -osenv@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -"over@>= 0.0.5 < 1": - version "0.0.5" - resolved "https://registry.yarnpkg.com/over/-/over-0.0.5.tgz#f29852e70fd7e25f360e013a8ec44c82aedb5708" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - -p-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - dependencies: - p-limit "^1.1.0" - -pac-proxy-agent@1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz#34a385dfdf61d2f0ecace08858c745d3e791fd4d" - dependencies: - agent-base "2" - debug "2" - extend "3" - get-uri "2" - http-proxy-agent "1" - https-proxy-agent "1" - pac-resolver "~2.0.0" - raw-body "2" - socks-proxy-agent "2" - -pac-resolver@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-2.0.0.tgz#99b88d2f193fbdeefc1c9a529c1f3260ab5277cd" - dependencies: - co "~3.0.6" - degenerator "~1.0.2" - ip "1.0.1" - netmask "~1.0.4" - thunkify "~2.1.1" - -pako@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - -parents@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" - dependencies: - path-platform "~0.11.15" - -parse-asn1@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - -parse-entities@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890" - 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" - -parse-filepath@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.1.tgz#159d6155d43904d16c10ef698911da1e91969b73" - dependencies: - is-absolute "^0.2.3" - map-cache "^0.2.0" - path-root "^0.1.1" - -parse-git-config@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/parse-git-config/-/parse-git-config-0.2.0.tgz#272833fdd15fea146fb75d336d236b963b6ff706" - dependencies: - ini "^1.3.3" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - dependencies: - error-ex "^1.2.0" - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - -parse-url@^1.3.0: - version "1.3.11" - resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-1.3.11.tgz#57c15428ab8a892b1f43869645c711d0e144b554" - dependencies: - is-ssh "^1.3.0" - protocols "^1.4.0" - -parsejson@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" - dependencies: - better-assert "~1.0.0" - -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" - dependencies: - better-assert "~1.0.0" - -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" - dependencies: - better-assert "~1.0.0" - -parseurl@~1.3.0, parseurl@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-is-inside@^1.0.1, path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - -path-key@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - -path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" - -path-platform@~0.11.15: - version "0.11.15" - resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" - -path-root-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" - -path-root@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" - dependencies: - path-root-regex "^0.1.0" - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - dependencies: - pify "^2.0.0" - -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - dependencies: - through "~2.3" - -pause@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/pause/-/pause-0.1.0.tgz#ebc8a4a8619ff0b8a81ac1513c3434ff469fdb74" - -pbkdf2-compat@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288" - -pbkdf2@^3.0.3: - version "3.0.13" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.13.tgz#c37d295531e786b1da3e3eadc840426accb0ae25" - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - dependencies: - find-up "^1.0.0" - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - dependencies: - find-up "^2.1.0" - -pluralize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -pretty-hrtime@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" - -private@^0.1.6, private@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" - -process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - -process@^0.11.0: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - -progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - -property-information@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-3.2.0.tgz#fd1483c8fbac61808f5fe359e7693a1f48a58331" - -protocols@^1.1.0, protocols@^1.4.0: - version "1.4.5" - resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.5.tgz#21de1f441c4ef7094408ed9f1c94f7a114b87557" - -proxy-agent@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-2.0.0.tgz#57eb5347aa805d74ec681cb25649dba39c933499" - dependencies: - agent-base "2" - debug "2" - extend "3" - http-proxy-agent "1" - https-proxy-agent "1" - lru-cache "~2.6.5" - pac-proxy-agent "1" - socks-proxy-agent "2" - -proxyquire@^1.7.10: - version "1.8.0" - resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-1.8.0.tgz#02d514a5bed986f04cbb2093af16741535f79edc" - dependencies: - fill-keys "^1.0.2" - module-not-found-error "^1.0.0" - resolve "~1.1.7" - -prr@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - -public-encrypt@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - -"pullstream@>= 0.4.1 < 1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/pullstream/-/pullstream-0.4.1.tgz#d6fb3bf5aed697e831150eb1002c25a3f8ae1314" - dependencies: - over ">= 0.0.5 < 1" - readable-stream "~1.0.31" - setimmediate ">= 1.0.2 < 2" - slice-stream ">= 1.0.0 < 2" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - -punycode@^1.2.4, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -q@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" - -q@^1.5.0, q@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" - -q@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/q/-/q-1.3.0.tgz#850d79f8cb831d92e103b46483e4e35d34640050" - -qjobs@^1.1.4: - version "1.1.5" - resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73" - -qs@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" - -qs@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-5.2.0.tgz#a9f31142af468cb72b25b30136ba2456834916be" - -qs@6.4.0, qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - -qs@^6.4.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" - -qs@~2.3.1: - version "2.3.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404" - -qs@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-5.1.0.tgz#4d932e5c7ea411cca76a312d39a606200fd50cd9" - -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - -querystringify@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.3.tgz#0c9d36fbf8c7a4f71eb370857763577a63335be7" - -querystringify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" - -random-bytes@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -randombytes@^2.0.0, randombytes@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79" - dependencies: - safe-buffer "^5.1.0" - -range-parser@^1.0.3, range-parser@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - -range-parser@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" - -raw-body@2: - version "2.3.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.0.tgz#f79ce1acacaba5b6362d33454d785d7129f4bc67" - dependencies: - bytes "2.5.0" - http-errors "1.6.1" - iconv-lite "0.4.18" - unpipe "1.0.0" - -raw-body@~1.1.0: - version "1.1.7" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425" - dependencies: - bytes "1" - string_decoder "0.10" - -raw-body@~2.1.2, raw-body@~2.1.5: - version "2.1.7" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" - dependencies: - bytes "2.4.0" - iconv-lite "0.4.13" - unpipe "1.0.0" - -raw-body@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.2.0.tgz#994976cf6a5096a41162840492f0bdc5d6e7fb96" - dependencies: - bytes "2.4.0" - iconv-lite "0.4.15" - unpipe "1.0.0" - -rc@^1.1.7: - version "1.2.1" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" - dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - -readable-stream@1.1.x, readable-stream@~1.1.8, readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.0, readable-stream@~1.0.17, readable-stream@~1.0.2, readable-stream@~1.0.24, readable-stream@~1.0.26, readable-stream@~1.0.31, readable-stream@~1.0.33: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@~2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" - 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" - -readable-stream@~2.1.0: - version "2.1.5" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" - 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" - -readdirp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" - dependencies: - graceful-fs "^4.1.2" - minimatch "^3.0.2" - readable-stream "^2.0.2" - set-immediate-shim "^1.0.1" - -readline2@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-0.1.1.tgz#99443ba6e83b830ef3051bfd7dc241a82728d568" - dependencies: - mute-stream "0.0.4" - strip-ansi "^2.0.1" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - dependencies: - resolve "^1.1.6" - -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - -regenerate@^1.2.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" - -regenerator-runtime@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - dependencies: - is-equal-shallow "^0.1.3" - -regex-not@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-0.1.2.tgz#bc7f1c4944b1188353d07deeb912b94e0ade25db" - -regex-not@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.0.tgz#42f83e39771622df826b02af176525d6a5f157f9" - dependencies: - extend-shallow "^2.0.1" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - dependencies: - jsesc "~0.5.0" - -remark-html@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/remark-html/-/remark-html-6.0.1.tgz#5094d2c71f7941fdb2ae865bac76627757ce09c1" - dependencies: - hast-util-sanitize "^1.0.0" - hast-util-to-html "^3.0.0" - mdast-util-to-hast "^2.1.1" - xtend "^4.0.1" - -remark-parse@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-4.0.0.tgz#99f1f049afac80382366e2e0d0bd55429dd45d8b" - dependencies: - collapse-white-space "^1.0.2" - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - is-word-character "^1.0.0" - markdown-escapes "^1.0.0" - parse-entities "^1.0.2" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - trim "0.0.1" - trim-trailing-lines "^1.0.0" - unherit "^1.0.4" - unist-util-remove-position "^1.0.0" - vfile-location "^2.0.0" - xtend "^4.0.1" - -remark-slug@^4.0.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/remark-slug/-/remark-slug-4.2.3.tgz#8d987d0e5e63d4a49ea37b90fe999a3dcfc81b72" - dependencies: - github-slugger "^1.0.0" - mdast-util-to-string "^1.0.0" - unist-util-visit "^1.0.0" - -remark-stringify@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-4.0.0.tgz#4431884c0418f112da44991b4e356cfe37facd87" - dependencies: - ccount "^1.0.0" - is-alphanumeric "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - longest-streak "^2.0.1" - markdown-escapes "^1.0.0" - markdown-table "^1.1.0" - mdast-util-compact "^1.0.0" - parse-entities "^1.0.2" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - stringify-entities "^1.0.1" - unherit "^1.0.4" - xtend "^4.0.1" - -remark-toc@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/remark-toc/-/remark-toc-4.0.1.tgz#ff36ff6de54ea07dd59e3f5334a4a3aac1e93185" - dependencies: - mdast-util-toc "^2.0.0" - remark-slug "^4.0.0" - -remark@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/remark/-/remark-8.0.0.tgz#287b6df2fe1190e263c1d15e486d3fa835594d6d" - dependencies: - remark-parse "^4.0.0" - remark-stringify "^4.0.0" - unified "^6.0.0" - -remote-origin-url@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/remote-origin-url/-/remote-origin-url-0.4.0.tgz#4d3e2902f34e2d37d1c263d87710b77eb4086a30" - dependencies: - parse-git-config "^0.2.0" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" - -repeat-string@^1.5.0, repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - dependencies: - is-finite "^1.0.0" - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - -replace-ext@1.0.0, replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - -replacestream@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/replacestream/-/replacestream-0.1.3.tgz#e018d3a37724600ccd0c005990d8a21b7b54ff34" - dependencies: - through "~2.3.4" - -request@2.49.0: - version "2.49.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.49.0.tgz#0d4f6348dc3348059b553e4db60fd2478de662a7" - dependencies: - aws-sign2 "~0.5.0" - bl "~0.9.0" - caseless "~0.8.0" - combined-stream "~0.0.5" - forever-agent "~0.5.0" - form-data "~0.1.0" - hawk "1.1.1" - http-signature "~0.10.0" - json-stringify-safe "~5.0.0" - mime-types "~1.0.1" - node-uuid "~1.4.0" - oauth-sign "~0.5.0" - qs "~2.3.1" - stringstream "~0.0.4" - tough-cookie ">=0.12.0" - tunnel-agent "~0.4.0" - -request@2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -request@2.81.0, request@^2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -requirejs@^2.1.20: - version "2.3.5" - resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.5.tgz#617b9acbbcb336540ef4914d790323a8d4b861b0" - -requires-port@1.0.x, requires-port@1.x.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - -resolve-dir@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" - dependencies: - expand-tilde "^1.2.2" - global-modules "^0.2.3" - -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - -resolve-url@^0.2.1, resolve-url@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - -resolve@1.1.7, resolve@1.1.x, resolve@~1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - -resolve@^1.1.3, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" - dependencies: - path-parse "^1.0.5" - -response-time@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a" - dependencies: - depd "~1.1.0" - on-headers "~1.0.1" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -rewire@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/rewire/-/rewire-2.5.2.tgz#6427de7b7feefa7d36401507eb64a5385bc58dc7" - -rgb2hex@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/rgb2hex/-/rgb2hex-0.1.0.tgz#ccd55f860ae0c5c4ea37504b958e442d8d12325b" - -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - dependencies: - align-text "^0.1.1" - -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" - dependencies: - glob "^7.0.5" - -rimraf@~2.2.0: - version "2.2.8" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" - -ripemd160@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" - dependencies: - hash-base "^2.0.0" - inherits "^2.0.1" - -rndm@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c" - -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - dependencies: - is-promise "^2.1.0" - -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - -rx@^2.4.3: - version "2.5.3" - resolved "https://registry.yarnpkg.com/rx/-/rx-2.5.3.tgz#21adc7d80f02002af50dae97fd9dbf248755f566" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - -safe-json-parse@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" - -samsam@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" - -samsam@~1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" - -sauce-connect-launcher@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/sauce-connect-launcher/-/sauce-connect-launcher-1.2.2.tgz#7346cc8fbdc443191323439b0733451f5f3521f2" - dependencies: - adm-zip "~0.4.3" - async "^2.1.2" - https-proxy-agent "~1.0.0" - lodash "^4.16.6" - rimraf "^2.5.4" - -saucelabs@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.4.0.tgz#b934a9af9da2874b3f40aae1fcde50a4466f5f38" - dependencies: - https-proxy-agent "^1.0.0" - -schema-utils@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" - dependencies: - ajv "^5.0.0" - -"semver@2 || 3 || 4 || 5", semver@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - -semver@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - -semver@^4.1.0, semver@~4.3.3: - version "4.3.6" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" - -semver@~5.0.1: - version "5.0.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" - -send@0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" - dependencies: - debug "~2.2.0" - depd "~1.1.0" - destroy "~1.0.4" - escape-html "~1.0.3" - etag "~1.7.0" - fresh "0.3.0" - http-errors "~1.3.1" - mime "1.3.4" - ms "0.7.1" - on-finished "~2.3.0" - range-parser "~1.0.3" - statuses "~1.2.1" - -sequencify@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" - -serve-favicon@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.3.2.tgz#dd419e268de012ab72b319d337f2105013f9381f" - dependencies: - etag "~1.7.0" - fresh "0.3.0" - ms "0.7.2" - parseurl "~1.3.1" - -serve-index@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.7.3.tgz#7a057fc6ee28dc63f64566e5fa57b111a86aecd2" - dependencies: - accepts "~1.2.13" - batch "0.5.3" - debug "~2.2.0" - escape-html "~1.0.3" - http-errors "~1.3.1" - mime-types "~2.1.9" - parseurl "~1.3.1" - -serve-static@~1.10.0: - version "1.10.3" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" - dependencies: - escape-html "~1.0.3" - parseurl "~1.3.1" - send "0.13.2" - -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -set-getter@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" - dependencies: - to-object-path "^0.3.0" - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - -set-value@^0.4.2, set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -"setimmediate@>= 1.0.1 < 2", "setimmediate@>= 1.0.2 < 2", setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - -setprototypeof@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - -sha.js@2.2.6: - version "2.2.6" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba" - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.8" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f" - dependencies: - inherits "^2.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - -shelljs@^0.7.5: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -sinon@^1.12.1: - version "1.17.7" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf" - dependencies: - formatio "1.1.1" - lolex "1.3.2" - samsam "1.1.2" - util ">=0.10.3 <1" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - -"slice-stream@>= 1.0.0 < 2": - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-stream/-/slice-stream-1.0.0.tgz#5b33bd66f013b1a7f86460b03d463dec39ad3ea0" - dependencies: - readable-stream "~1.0.31" - -smart-buffer@^1.0.13: - version "1.1.15" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370" - 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 "^2.0.0" - -sntp@0.2.x: - version "0.2.4" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-0.2.4.tgz#fb885f18b0f3aad189f824862536bceeec750900" - dependencies: - hoek "0.9.x" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -socket.io-adapter@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b" - dependencies: - debug "2.3.3" - socket.io-parser "2.3.1" - -socket.io-client@1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.7.3.tgz#b30e86aa10d5ef3546601c09cde4765e381da377" - dependencies: - backo2 "1.0.2" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "2.3.3" - engine.io-client "1.8.3" - has-binary "0.1.7" - indexof "0.0.1" - object-component "0.0.3" - parseuri "0.0.5" - socket.io-parser "2.3.1" - to-array "0.1.4" - -socket.io-parser@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0" - dependencies: - component-emitter "1.1.2" - debug "2.2.0" - isarray "0.0.1" - json3 "3.3.2" - -socket.io@1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.7.3.tgz#b8af9caba00949e568e369f1327ea9be9ea2461b" - dependencies: - debug "2.3.3" - engine.io "1.8.3" - has-binary "0.1.7" - object-assign "4.1.0" - socket.io-adapter "0.5.0" - socket.io-client "1.7.3" - socket.io-parser "2.3.1" - -socks-proxy-agent@2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz#86ebb07193258637870e13b7bd99f26c663df3d3" - dependencies: - agent-base "2" - extend "3" - socks "~1.1.5" - -socks@~1.1.5: - version "1.1.10" - resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a" - dependencies: - ip "^1.1.4" - smart-buffer "^1.0.13" - -source-list-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" - -source-list-map@~0.1.7: - version "0.1.8" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" - -source-map-resolve@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" - dependencies: - atob "~1.1.0" - resolve-url "~0.2.1" - source-map-url "~0.3.0" - urix "~0.1.0" - -source-map-resolve@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.0.tgz#fcad0b64b70afb27699e425950cb5ebcd410bc20" - dependencies: - atob "^2.0.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@^0.4.15: - version "0.4.17" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.17.tgz#6f2150553e6375375d0ccb3180502b78c18ba430" - dependencies: - source-map "^0.5.6" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - -source-map-url@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" - -source-map@0.X, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - -source-map@^0.1.38, source-map@^0.1.41, source-map@~0.1.38: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - dependencies: - amdefine ">=0.0.4" - -source-map@^0.4.4, source-map@~0.4.1: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - dependencies: - amdefine ">=0.0.4" - -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - dependencies: - amdefine ">=0.0.4" - -space-separated-tokens@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz#9695b9df9e65aec1811d4c3f9ce52520bc2f7e4d" - dependencies: - trim "0.0.1" - -sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" - -spdx-correct@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" - dependencies: - spdx-license-ids "^1.0.2" - -spdx-expression-parse@~1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" - -spdx-license-ids@^1.0.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" - -split-string@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-2.1.1.tgz#af4b06d821560426446c3cd931cda618940d37d0" - dependencies: - extend-shallow "^2.0.1" - -split@0.2: - version "0.2.10" - resolved "https://registry.yarnpkg.com/split/-/split-0.2.10.tgz#67097c601d697ce1368f418f06cd201cf0521a57" - dependencies: - through "2" - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - dependencies: - through "2" - -sprintf-js@^1.0.3: - version "1.1.1" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -state-toggle@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425" - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -statuses@1, "statuses@>= 1.3.1 < 2", statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - -statuses@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.2.1.tgz#dded45cc18256d51ed40aec142489d5c61026d28" - -stream-array@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/stream-array/-/stream-array-1.1.2.tgz#9e5f7345f2137c30ee3b498b9114e80b52bb7eb5" - dependencies: - readable-stream "~2.1.0" - -stream-browserify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-combiner2@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" - dependencies: - duplexer2 "~0.1.0" - readable-stream "^2.0.2" - -stream-combiner@~0.0.3, stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - dependencies: - duplexer "~0.1.1" - -stream-consume@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" - -stream-counter@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-0.2.0.tgz#ded266556319c8b0e222812b9cf3b26fa7d947de" - dependencies: - readable-stream "~1.1.8" - -stream-http@^2.3.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad" - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.2.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - -string-replace-webpack-plugin@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz#73c657e759d66cfe80ae1e0cf091aa256d0e715c" - dependencies: - async "~0.2.10" - loader-utils "~0.2.3" - optionalDependencies: - css-loader "^0.9.1" - file-loader "^0.8.1" - style-loader "^0.8.3" - -string-template@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" - -string-width@^1.0.0, string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.0.0, string-width@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string_decoder@0.10, string_decoder@^0.10.25, string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -stringify-entities@^1.0.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.1.tgz#b150ec2d72ac4c1b5f324b51fb6b28c9cdff058c" - dependencies: - character-entities-html4 "^1.0.0" - character-entities-legacy "^1.0.0" - is-alphanumerical "^1.0.0" - is-hexadecimal "^1.0.0" - -stringstream@~0.0.4: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - -strip-ansi@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" - dependencies: - ansi-regex "^0.2.1" - -strip-ansi@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-2.0.1.tgz#df62c1aa94ed2f114e1d0f21fd1d50482b79a60e" - dependencies: - ansi-regex "^1.0.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom-string@1.X: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - -strip-bom@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" - dependencies: - first-chunk-stream "^1.0.0" - is-utf8 "^0.2.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - dependencies: - is-utf8 "^0.2.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - dependencies: - get-stdin "^4.0.1" - -strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - -style-loader@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.8.3.tgz#f4f92eb7db63768748f15065cd6700f5a1c85357" - dependencies: - loader-utils "^0.2.5" - -subarg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" - dependencies: - minimist "^1.1.0" - -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - dependencies: - has-flag "^1.0.0" - -supports-color@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" - -supports-color@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.3.1.tgz#15758df09d8ff3b4acc307539fabe27095e1042d" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^3.1.0, supports-color@^3.1.2: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - dependencies: - has-flag "^1.0.0" - -supports-color@^4.0.0, supports-color@^4.1.0, supports-color@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - dependencies: - has-flag "^2.0.0" - -table@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" - dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" - -tapable@^0.1.8, tapable@~0.1.8: - version "0.1.10" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" - -tapable@^0.2.7: - version "0.2.8" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" - -tar-pack@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" - dependencies: - debug "^2.2.0" - fstream "^1.0.10" - fstream-ignore "^1.0.5" - once "^1.3.3" - readable-stream "^2.1.4" - rimraf "^2.5.1" - tar "^2.2.1" - uid-number "^0.0.6" - -tar-stream@^1.5.0: - version "1.5.4" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016" - dependencies: - bl "^1.0.0" - end-of-stream "^1.0.0" - readable-stream "^2.0.0" - xtend "^4.0.0" - -tar-stream@~1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.1.5.tgz#be9218c130c20029e107b0f967fb23de0579d13c" - dependencies: - bl "^0.9.0" - end-of-stream "^1.0.0" - readable-stream "~1.0.33" - xtend "^4.0.0" - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -ternary-stream@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-2.0.1.tgz#064e489b4b5bf60ba6a6b7bc7f2f5c274ecf8269" - dependencies: - duplexify "^3.5.0" - fork-stream "^0.0.4" - merge-stream "^1.0.0" - through2 "^2.0.1" - -text-table@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - -textextensions@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-1.0.2.tgz#65486393ee1f2bb039a60cbba05b0b68bd9501d2" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through2@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" - dependencies: - readable-stream "~1.0.17" - xtend "~2.1.1" - -through2@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" - dependencies: - readable-stream "~1.0.17" - xtend "~3.0.0" - -through2@^0.6.0, through2@^0.6.1, through2@^0.6.3, through2@^0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -thunkify@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/thunkify/-/thunkify-2.1.2.tgz#faa0e9d230c51acc95ca13a361ac05ca7e04553d" - -tildify@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" - dependencies: - os-homedir "^1.0.0" - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - -time-stamp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357" - -timers-browserify@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6" - dependencies: - setimmediate "^1.0.4" - -timers-ext@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.2.tgz#61cc47a76c1abd3195f14527f978d58ae94c5204" - dependencies: - es5-ext "~0.10.14" - next-tick "1" - -tiny-lr@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-0.2.1.tgz#b3fdba802e5d56a33c2f6f10794b32e477ac729d" - dependencies: - body-parser "~1.14.0" - debug "~2.2.0" - faye-websocket "~0.10.0" - livereload-js "^2.2.0" - parseurl "~1.3.0" - qs "~5.1.0" - -tiny-lr@^1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-1.0.5.tgz#21f40bf84ebd1f853056680375eef1670c334112" - dependencies: - body "^5.1.0" - debug "~2.6.7" - faye-websocket "~0.10.0" - livereload-js "^2.2.2" - object-assign "^4.1.0" - qs "^6.4.0" - -tmp@0.0.31, tmp@^0.0.31: - version "0.0.31" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" - dependencies: - os-tmpdir "~1.0.1" - -tmp@0.0.x: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - dependencies: - os-tmpdir "~1.0.2" - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - dependencies: - extend-shallow "^2.0.1" - -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-2.1.0.tgz#e3ad3a40cfe119559a05aea43e4caefacc5e901d" - dependencies: - define-property "^0.2.5" - extend-shallow "^2.0.1" - regex-not "^0.1.1" - -to-regex@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.1.tgz#15358bee4a2c83bd76377ba1dc049d0f18837aae" - dependencies: - define-property "^0.2.5" - extend-shallow "^2.0.1" - regex-not "^1.0.0" - -tough-cookie@>=0.12.0, tough-cookie@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" - dependencies: - punycode "^1.4.1" - -"traverse@>=0.3.0 <0.4": - version "0.3.9" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" - -trim-lines@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.0.tgz#9926d03ede13ba18f7d42222631fb04c79ff26fe" - -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - -trim-trailing-lines@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz#7aefbb7808df9d669f6da2e438cac8c46ada7684" - -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - -trough@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.1.tgz#a9fd8b0394b0ae8fff82e0633a0a36ccad5b5f86" - -tryit@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" - -tsscmp@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - dependencies: - safe-buffer "^5.0.1" - -tunnel-agent@~0.4.0, tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - dependencies: - prelude-ls "~1.1.2" - -type-detect@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" - -type-detect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" - -type-is@~1.6.10, type-is@~1.6.15, type-is@~1.6.6: - version "1.6.15" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" - dependencies: - media-typer "0.3.0" - mime-types "~2.1.15" - -typedarray@^0.0.6, typedarray@~0.0.5: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - -uglify-js@^2.6, uglify-js@^2.8.10, uglify-js@^2.8.29: - version "2.8.29" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - dependencies: - source-map "~0.5.1" - yargs "~3.10.0" - optionalDependencies: - uglify-to-browserify "~1.0.0" - -uglify-js@^3.0.5: - version "3.0.28" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.0.28.tgz#96b8495f0272944787b5843a1679aa326640d5f7" - dependencies: - commander "~2.11.0" - source-map "~0.5.1" - -uglify-js@~2.7.3: - version "2.7.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" - dependencies: - async "~0.2.6" - source-map "~0.5.1" - uglify-to-browserify "~1.0.0" - yargs "~3.10.0" - -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - -uglifyjs-webpack-plugin@^0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" - dependencies: - source-map "^0.5.6" - uglify-js "^2.8.29" - webpack-sources "^1.0.1" - -uid-number@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - -uid-safe@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.4.tgz#3ad6f38368c6d4c8c75ec17623fb79aa1d071d81" - dependencies: - random-bytes "~1.0.0" - -uid-safe@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.0.0.tgz#a7f3c6ca64a1f6a5d04ec0ef3e4c3d5367317137" - dependencies: - base64-url "1.2.1" - -ultron@1.0.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" - -unc-path-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - -underscore.string@3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db" - dependencies: - sprintf-js "^1.0.3" - util-deprecate "^1.0.2" - -unherit@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.0.tgz#6b9aaedfbf73df1756ad9e316dd981885840cd7d" - dependencies: - inherits "^2.0.1" - xtend "^4.0.1" - -unified@^6.0.0: - version "6.1.5" - resolved "https://registry.yarnpkg.com/unified/-/unified-6.1.5.tgz#716937872621a63135e62ced2f3ac6a063c6fb87" - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^1.1.0" - trough "^1.0.0" - vfile "^2.0.0" - x-is-function "^1.0.4" - x-is-string "^0.1.0" - -union-value@^0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-0.2.4.tgz#7375152786679057e7b37aa676e83468fc0274f0" - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^0.4.3" - -unique-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" - -unique-stream@^2.0.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" - dependencies: - json-stable-stringify "^1.0.0" - through2-filter "^2.0.0" - -unist-builder@^1.0.0, unist-builder@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-1.0.2.tgz#8c3b9903ef64bcfb117dd7cf6a5d98fc1b3b27b6" - dependencies: - object-assign "^4.1.0" - -unist-util-generated@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.1.tgz#99f16c78959ac854dee7c615c291924c8bf4de7f" - -unist-util-is@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.1.tgz#0c312629e3f960c66e931e812d3d80e77010947b" - -unist-util-modify-children@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz#66d7e6a449e6f67220b976ab3cb8b5ebac39e51d" - dependencies: - array-iterate "^1.0.0" - -unist-util-position@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.0.0.tgz#e6e1e03eeeb81c5e1afe553e8d4adfbd7c0d8f82" - -unist-util-remove-position@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz#5a85c1555fc1ba0c101b86707d15e50fa4c871bb" - dependencies: - unist-util-visit "^1.1.0" - -unist-util-stringify-position@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c" - -unist-util-visit@^1.0.0, unist-util-visit@^1.0.1, unist-util-visit@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.1.3.tgz#ec268e731b9d277a79a5b5aa0643990e405d600b" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - -unset-value@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-0.1.2.tgz#506810b867f27c2a5a6e9b04833631f6de58d310" - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -unzip@~0.1.9: - version "0.1.11" - resolved "https://registry.yarnpkg.com/unzip/-/unzip-0.1.11.tgz#89749c63b058d7d90d619f86b98aa1535d3b97f0" - dependencies: - binary ">= 0.3.0 < 1" - fstream ">= 0.1.30 < 1" - match-stream ">= 0.0.2 < 1" - pullstream ">= 0.4.1 < 1" - readable-stream "~1.0.31" - setimmediate ">= 1.0.1 < 2" - -urix@^0.1.0, urix@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - -url-parse@^1.0.5: - version "1.1.9" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.1.9.tgz#c67f1d775d51f0a18911dd7b3ffad27bb9e5bd19" - dependencies: - querystringify "~1.0.0" - requires-port "1.0.x" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -url@~0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8" - dependencies: - define-property "^0.2.5" - isobject "^3.0.0" - lazy-cache "^2.0.2" - -user-home@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" - -useragent@^2.1.12: - version "2.2.1" - resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e" - dependencies: - lru-cache "2.2.x" - tmp "0.0.x" - -util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -util@0.10.3, "util@>=0.10.3 <1", util@^0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - dependencies: - inherits "2.0.1" - -utils-merge@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" - -uuid@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - -v8flags@^2.0.2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" - dependencies: - user-home "^1.1.1" - -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - -validate-npm-package-license@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" - dependencies: - spdx-correct "~1.0.0" - spdx-expression-parse "~1.0.0" - -vargs@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/vargs/-/vargs-0.1.0.tgz#6b6184da6520cc3204ce1b407cac26d92609ebff" - -vary@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" - -vary@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vfile-location@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.2.tgz#d3675c59c877498e492b4756ff65e4af1a752255" - -vfile-reporter@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vfile-reporter/-/vfile-reporter-4.0.0.tgz#ea6f0ae1342f4841573985e05f941736f27de9da" - dependencies: - repeat-string "^1.5.0" - string-width "^1.0.0" - supports-color "^4.1.0" - unist-util-stringify-position "^1.0.0" - vfile-statistics "^1.1.0" - -vfile-sort@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/vfile-sort/-/vfile-sort-2.1.0.tgz#49501c9e8bbe5adff2e9b3a7671ee1b1e20c5210" - -vfile-statistics@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.1.0.tgz#02104c60fdeed1d11b1f73ad65330b7634b3d895" - -vfile@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.2.0.tgz#ce47a4fb335922b233e535db0f7d8121d8fced4e" - dependencies: - is-buffer "^1.1.4" - replace-ext "1.0.0" - unist-util-stringify-position "^1.0.0" - -vhost@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5" - -vinyl-fs@^0.3.0: - version "0.3.14" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" - dependencies: - defaults "^1.0.0" - glob-stream "^3.1.5" - glob-watcher "^0.0.6" - graceful-fs "^3.0.0" - mkdirp "^0.5.0" - strip-bom "^1.0.0" - through2 "^0.6.1" - vinyl "^0.4.0" - -vinyl-fs@^2.3.1: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-sourcemaps-apply@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" - dependencies: - source-map "^0.5.1" - -vinyl@1.X, vinyl@^1.0.0, vinyl@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^0.2.1: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.2.3.tgz#bca938209582ec5a49ad538a00fa1f125e513252" - dependencies: - clone-stats "~0.0.1" - -vinyl@^0.4.0: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^2.0.0, vinyl@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" - 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" - -vlq@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.2.tgz#e316d5257b40b86bb43cb8d5fea5d7f54d6b0ca1" - -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - dependencies: - indexof "0.0.1" - -void-elements@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - -walk@^2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.9.tgz#31b4db6678f2ae01c39ea9fb8725a9031e558a7b" - dependencies: - foreachasync "^3.0.0" - -walkdir@^0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.11.tgz#a16d025eb931bd03b52f308caed0f40fcebe9532" - -watchpack@^0.2.1: - version "0.2.9" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-0.2.9.tgz#62eaa4ab5e5ba35fdfc018275626e3c0f5e3fb0b" - dependencies: - async "^0.9.0" - chokidar "^1.0.0" - graceful-fs "^4.1.2" - -watchpack@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac" - dependencies: - async "^2.1.2" - chokidar "^1.7.0" - graceful-fs "^4.1.2" - -wd@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/wd/-/wd-1.4.0.tgz#85958787abc32f048d4b3927b2ab3c5fc8c9c9fa" - dependencies: - archiver "1.3.0" - async "2.0.1" - lodash "4.16.2" - mkdirp "^0.5.1" - q "1.4.1" - request "2.79.0" - underscore.string "3.3.4" - vargs "0.1.0" - -webdriverio@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-3.4.0.tgz#d9d4d3c31366f053e10af644b0eaad5e873ab7b5" - dependencies: - archiver "~0.14.3" - array.from "^0.2.0" - co "^4.5.4" - css-parse "~2.0.0" - css-value "~0.0.1" - deepmerge "~0.2.7" - ejs "^2.3.1" - glob "^5.0.10" - inquirer "^0.8.5" - is-generator "^1.0.2" - optimist "^0.6.1" - q "~1.3.0" - request "2.49.0" - rgb2hex "~0.1.0" - supports-color "^1.3.1" - url "~0.10.3" - wgxpath "~1.0.0" - -webpack-core@~0.6.9: - version "0.6.9" - resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" - dependencies: - source-list-map "~0.1.7" - source-map "~0.4.1" - -webpack-dev-middleware@^1.0.11: - version "1.12.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz#d34efefb2edda7e1d3b5dbe07289513219651709" - dependencies: - memory-fs "~0.4.1" - mime "^1.3.4" - path-is-absolute "^1.0.0" - range-parser "^1.0.3" - time-stamp "^2.0.0" - -webpack-sources@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf" - dependencies: - source-list-map "^2.0.0" - source-map "~0.5.3" - -webpack-stream@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/webpack-stream/-/webpack-stream-3.2.0.tgz#3a1d160fb11d41727b7ce6f32f722464f98b2186" - dependencies: - gulp-util "^3.0.7" - lodash.clone "^4.3.2" - lodash.some "^4.2.2" - memory-fs "^0.3.0" - through "^2.3.8" - vinyl "^1.1.0" - webpack "^1.12.9" - -webpack@^1.12.9: - version "1.15.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.15.0.tgz#4ff31f53db03339e55164a9d468ee0324968fe98" - dependencies: - acorn "^3.0.0" - async "^1.3.0" - clone "^1.0.2" - enhanced-resolve "~0.9.0" - interpret "^0.6.4" - loader-utils "^0.2.11" - memory-fs "~0.3.0" - mkdirp "~0.5.0" - node-libs-browser "^0.7.0" - optimist "~0.6.0" - supports-color "^3.1.0" - tapable "~0.1.8" - uglify-js "~2.7.3" - watchpack "^0.2.1" - webpack-core "~0.6.9" - -webpack@^3.0.0: - version "3.5.5" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.5.5.tgz#3226f09fc8b3e435ff781e7af34f82b68b26996c" - dependencies: - acorn "^5.0.0" - acorn-dynamic-import "^2.0.0" - ajv "^5.1.5" - ajv-keywords "^2.0.0" - async "^2.1.2" - enhanced-resolve "^3.4.0" - escope "^3.6.0" - interpret "^1.0.0" - json-loader "^0.5.4" - json5 "^0.5.1" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - mkdirp "~0.5.0" - node-libs-browser "^2.0.0" - source-map "^0.5.3" - supports-color "^4.2.1" - tapable "^0.2.7" - uglifyjs-webpack-plugin "^0.4.6" - watchpack "^1.4.0" - webpack-sources "^1.0.1" - yargs "^8.0.2" - -websocket-driver@>=0.5.1: - version "0.6.5" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" - dependencies: - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.1.tgz#76899499c184b6ef754377c2dbb0cd6cb55d29e7" - -wgxpath@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wgxpath/-/wgxpath-1.0.0.tgz#eef8a4b9d558cc495ad3a9a2b751597ecd9af690" - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - -which@^1.1.1, which@^1.2.1, which@^1.2.12, which@^1.2.9: - version "1.3.0" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" - dependencies: - string-width "^1.0.2" - -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - -window-size@^0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" - -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - -wordwrap@^1.0.0, wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - dependencies: - mkdirp "^0.5.1" - -ws@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f" - dependencies: - options ">=0.0.5" - ultron "1.0.x" - -wtf-8@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" - -x-is-function@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e" - -x-is-string@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" - -xmlhttprequest-ssl@1.5.3: - version "1.5.3" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" - -xregexp@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - dependencies: - object-keys "~0.4.0" - -xtend@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" - -y18n@^3.2.0, y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - -yargs-parser@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - dependencies: - camelcase "^3.0.0" - lodash.assign "^4.0.6" - -yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" - dependencies: - camelcase "^3.0.0" - -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - dependencies: - camelcase "^4.1.0" - -yargs@3.29.0: - version "3.29.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.29.0.tgz#1aab9660eae79d8b8f675bcaeeab6ee34c2cf69c" - dependencies: - camelcase "^1.2.1" - cliui "^3.0.3" - decamelize "^1.0.0" - os-locale "^1.4.0" - window-size "^0.1.2" - y18n "^3.2.0" - -yargs@^1.3.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.3.3.tgz#054de8b61f22eefdb7207059eaef9d6b83fb931a" - -yargs@^4.8.1: - version "4.8.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - dependencies: - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - lodash.assign "^4.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.1" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^2.4.1" - -yargs@^6.0.1: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" - 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 "^4.2.0" - -yargs@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.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.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" - -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - -zip-stream@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04" - dependencies: - archiver-utils "^1.3.0" - compress-commons "^1.2.0" - lodash "^4.8.0" - readable-stream "^2.0.0" - -zip-stream@~0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-0.5.2.tgz#32dcbc506d0dab4d21372625bd7ebaac3c2fff56" - dependencies: - compress-commons "~0.2.0" - lodash "~3.2.0" - readable-stream "~1.0.26" From 2973f76c431a97dca8798e6dbe517cbae710dd26 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 14 Feb 2018 07:33:38 -0700 Subject: [PATCH 0119/1594] size mapping throws warning if mediaQuery missing (#2114) * size mapping throws warning if mediaQuery missing * added unit test for missing mediaQuery in sizeConfig --- src/sizeMapping.js | 22 +++++++++++++--------- test/spec/sizeMapping_spec.js | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/sizeMapping.js b/src/sizeMapping.js index 4a4c9ff77c1..5533c6b4efe 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -1,4 +1,5 @@ import { config } from 'src/config'; +import { logWarn } from 'src/utils'; import includes from 'core-js/library/fn/array/includes'; let sizeConfig = []; @@ -64,17 +65,20 @@ function evaluateSizeConfig(configs) { return configs.reduce((results, config) => { if ( typeof config === 'object' && - typeof config.mediaQuery === 'string' && - matchMedia(config.mediaQuery).matches + typeof config.mediaQuery === 'string' ) { - if (Array.isArray(config.sizesSupported)) { - results.shouldFilter = true; + if (matchMedia(config.mediaQuery).matches) { + if (Array.isArray(config.sizesSupported)) { + results.shouldFilter = true; + } + ['labels', 'sizesSupported'].forEach( + type => (config[type] || []).forEach( + thing => results[type][thing] = true + ) + ); } - ['labels', 'sizesSupported'].forEach( - type => (config[type] || []).forEach( - thing => results[type][thing] = true - ) - ); + } else { + logWarn('sizeConfig rule missing required property "mediaQuery"'); } return results; }, { diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index b131c9c964c..74b86a8c5aa 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -2,6 +2,9 @@ import { expect } from 'chai'; import { resolveStatus, setSizeConfig } from 'src/sizeMapping'; import includes from 'core-js/library/fn/array/includes'; +let utils = require('src/utils'); +let deepClone = utils.deepClone; + describe('sizeMapping', () => { var testSizes = [[970, 90], [728, 90], [300, 250], [300, 100], [80, 80]]; @@ -68,6 +71,17 @@ describe('sizeMapping', () => { }); describe('when handling sizes', () => { + it('should log a warning when mediaQuery property missing from sizeConfig', () => { + let errorConfig = deepClone(sizeConfig); + + delete errorConfig[0].mediaQuery; + + sandbox.stub(utils, 'logWarn'); + + resolveStatus(undefined, testSizes, errorConfig); + expect(utils.logWarn.firstCall.args[0]).to.match(/missing.+?mediaQuery/); + }); + it('when one mediaQuery block matches, it should filter the adUnit.sizes passed in', () => { matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; From f4fd825b67d51dec55ae309faaef7ffe17b37ae6 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 14 Feb 2018 08:37:50 -0700 Subject: [PATCH 0120/1594] Add package-lock.json for node v9 builds (#2144) --- package-lock.json | 18200 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 18200 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000000..f3713a52f53 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,18200 @@ +{ + "name": "prebid.js", + "version": "1.4.0-pre", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@gulp-sourcemaps/identity-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", + "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", + "requires": { + "acorn": "5.4.1", + "css": "2.2.1", + "normalize-path": "2.1.1", + "source-map": "0.5.7", + "through2": "2.0.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@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=", + "requires": { + "normalize-path": "2.1.1", + "through2": "2.0.3" + } + }, + "@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" + } + }, + "JSONStream": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "accepts": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "dev": true, + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.5.3" + } + }, + "acorn": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==" + }, + "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": { + "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": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.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 + } + } + }, + "acorn-node": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.3.0.tgz", + "integrity": "sha512-efP54n3d1aLfjL2UMdaXa6DsswwzJeI5rqhbFvXMrKiJ6eJFpf+7R0zN7t8IC+XKn2YOAFAv6xbBNgHUkoHWLw==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "xtend": "4.0.1" + } + }, + "addressparser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", + "dev": true, + "optional": true + }, + "adm-zip": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz", + "integrity": "sha1-hgbCy/HEJs6MjsABdER/1Jtur8E=", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "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.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.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=" + }, + "amqplib": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", + "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", + "dev": true, + "optional": true, + "requires": { + "bitsyntax": "0.0.4", + "bluebird": "3.5.1", + "buffer-more-ints": "0.0.2", + "readable-stream": "1.1.14", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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, + "optional": true + } + } + }, + "ansi-colors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.0.1.tgz", + "integrity": "sha512-yopkAU0ZD/WQ56Tms3xLn6jRuX3SyUMAVi0FdmDIbmmnHW3jHiI1sQFdUl3gfVddjnrsP3Y6ywFKvCRopvoVIA==", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "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 + }, + "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 + }, + "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 + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.5", + "normalize-path": "2.1.1" + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "1.0.0" + } + }, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "1.0.0" + } + }, + "archiver": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", + "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", + "dev": true, + "requires": { + "async": "0.9.2", + "buffer-crc32": "0.2.13", + "glob": "4.3.5", + "lazystream": "0.1.0", + "lodash": "3.2.0", + "readable-stream": "1.0.34", + "tar-stream": "1.1.5", + "zip-stream": "0.5.2" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "glob": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lazystream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + } + }, + "lodash": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "dev": true, + "requires": { + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lazystream": "1.0.0", + "lodash": "4.17.5", + "normalize-path": "2.1.1", + "readable-stream": "2.3.4" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "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 + }, + "array-iterate": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.1.tgz", + "integrity": "sha1-hlv3+K851rCYLGCQKRSsdrwBCPY=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "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 + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "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 + }, + "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 + }, + "array.from": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", + "integrity": "sha1-LGJ7G3bf8t7yNl+gUrZcPVheX2s=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "asn1.js": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", + "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "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 + }, + "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 + }, + "ast-types": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.2.tgz", + "integrity": "sha512-ufWX953VU1eIuWqxS0nRDMYlGyFH+yxln5CsmIHlpzEt3fdYqUnRtsFt0XAsQot8OaVCwFqxT1RiwvtzYjeYeg==", + "dev": true + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "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 + } + } + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "axios": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", + "dev": true, + "optional": true, + "requires": { + "follow-redirects": "1.0.0" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", + "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "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.5", + "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" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "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.5", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "esutils": "2.0.2" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "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.26.0", + "babel-template": "6.26.0" + } + }, + "babel-loader": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.2.tgz", + "integrity": "sha512-jRwlFbINAeyDStqK6Dd5YuY0k5YuzQUvlz2ZamuXrXmxav3pNqe9vfJ402+2G+OmlJSXxCOpB6Uz0INM7RQe2A==", + "dev": true, + "requires": { + "find-cache-dir": "1.0.0", + "loader-utils": "1.1.0", + "mkdirp": "0.5.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.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", + "dev": true + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", + "dev": true + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", + "dev": true + }, + "babel-plugin-syntax-do-expressions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", + "dev": true + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", + "dev": true + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, + "babel-plugin-syntax-function-bind": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", + "dev": true + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-system-import-transformer": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", + "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0" + } + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "dev": true, + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-decorators-legacy": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", + "integrity": "sha1-dBtY9sW86eYCfgiC2cmU8E82aSU=", + "dev": true, + "requires": { + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-do-expressions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-es3-member-expression-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz", + "integrity": "sha1-cz00RPPsxBvvjtGmpOCWV7iWnrs=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es3-property-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz", + "integrity": "sha1-sgeNWELiKr9A9z6M3pzTcRq9V1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-function-bind": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "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=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "6.26.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-preset-env": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "2.11.3", + "invariant": "2.2.2", + "semver": "5.5.0" + } + }, + "babel-preset-es2015": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz", + "integrity": "sha1-r1qY7LNeuK92StiloF6zbcQ4aDU=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0" + } + }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-self": "6.22.0", + "babel-plugin-transform-react-jsx-source": "6.22.0", + "babel-preset-flow": "6.23.0" + } + }, + "babel-preset-stage-0": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", + "dev": true, + "requires": { + "babel-plugin-transform-do-expressions": "6.22.0", + "babel-plugin-transform-function-bind": "6.22.0", + "babel-preset-stage-1": "6.24.1" + } + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "dev": true, + "requires": { + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.26.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.3", + "home-or-tmp": "2.0.0", + "lodash": "4.17.5", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "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.5", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "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" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "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=", + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "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.5" + } + }, + "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.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.5" + }, + "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" + } + } + } + }, + "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.5", + "to-fast-properties": "1.0.3" + } + }, + "babelify": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", + "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw==", + "dev": true + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "bail": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", + "integrity": "sha1-99bBcxYwqfnw1NNe0fli4gdKF2Q=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "base64-url": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", + "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "basic-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", + "dev": true + }, + "basic-auth-connect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", + "dev": true + }, + "batch": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", + "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "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": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "0.1.1", + "chainsaw": "0.1.0" + } + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "binaryextensions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", + "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", + "dev": true + }, + "bitsyntax": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "dev": true, + "optional": true, + "requires": { + "buffer-more-ints": "0.0.2" + } + }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "blob": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "dev": true + }, + "block-loader": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/block-loader/-/block-loader-2.1.0.tgz", + "integrity": "sha1-u7OYrVqEPGxx95opb0tt9LAlcxI=", + "dev": true + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", + "dev": true, + "requires": { + "continuable-cache": "0.3.1", + "error": "7.0.2", + "raw-body": "1.1.7", + "safe-json-parse": "1.0.1" + } + }, + "body-parser": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", + "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", + "dev": true, + "requires": { + "bytes": "2.1.0", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.0.1", + "http-errors": "1.3.1", + "iconv-lite": "0.4.11", + "on-finished": "2.3.0", + "qs": "4.0.0", + "raw-body": "2.1.7", + "type-is": "1.6.15" + }, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + } + } + } + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "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, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", + "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "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.1.1", + "split-string": "3.1.0", + "to-regex": "3.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-pack": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.4.tgz", + "integrity": "sha512-Q4Rvn7P6ObyWfc4stqLWHtG1MJ8vVtjgT24Zbu+8UTzxYuZouqZsmNRRTFVMY/Ux0eIKv1d+JWzsInTX+fdHPQ==", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "combine-source-map": "0.8.0", + "defined": "1.0.0", + "safe-buffer": "5.1.1", + "through2": "2.0.3", + "umd": "3.0.1" + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "browserify": { + "version": "14.5.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-14.5.0.tgz", + "integrity": "sha512-gKfOsNQv/toWz+60nSPfYzuwSEdzvV2WdxrVPUbPD/qui44rAkB3t3muNtmmGYHqrG56FGwX9SUEQmzNLAeS7g==", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "assert": "1.4.1", + "browser-pack": "6.0.4", + "browser-resolve": "1.11.2", + "browserify-zlib": "0.2.0", + "buffer": "5.0.8", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "defined": "1.0.0", + "deps-sort": "2.0.0", + "domain-browser": "1.1.7", + "duplexer2": "0.1.4", + "events": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "htmlescape": "1.1.1", + "https-browserify": "1.0.0", + "inherits": "2.0.3", + "insert-module-globals": "7.0.1", + "labeled-stream-splicer": "2.0.0", + "module-deps": "4.1.1", + "os-browserify": "0.3.0", + "parents": "1.0.1", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "read-only-stream": "2.0.0", + "readable-stream": "2.3.4", + "resolve": "1.5.0", + "shasum": "1.0.2", + "shell-quote": "1.6.1", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "1.0.3", + "subarg": "1.0.0", + "syntax-error": "1.4.0", + "through2": "2.0.3", + "timers-browserify": "1.4.2", + "tty-browserify": "0.0.1", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4", + "xtend": "4.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "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 + } + } + }, + "module-deps": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "browser-resolve": "1.11.2", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "4.7.1", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "parents": "1.0.1", + "readable-stream": "2.3.4", + "resolve": "1.5.0", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "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 + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + } + } + }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "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.6" + } + }, + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000808", + "electron-to-chromium": "1.3.33" + } + }, + "browserstack": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", + "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", + "dev": true, + "requires": { + "https-proxy-agent": "1.0.0" + } + }, + "browserstacktunnel-wrapper": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.1.tgz", + "integrity": "sha1-/+GRDW45/oZhgYPoJmkAQa9T7a4=", + "dev": true, + "requires": { + "https-proxy-agent": "1.0.0", + "unzip": "0.1.11" + } + }, + "buffer": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", + "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8" + } + }, + "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 + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-more-ints": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "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 + }, + "buildmail": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", + "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", + "dev": true, + "optional": true, + "requires": { + "addressparser": "1.0.1", + "libbase64": "0.1.0", + "libmime": "3.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.6.0", + "nodemailer-shared": "1.1.0", + "punycode": "1.4.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "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": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", + "dev": true + }, + "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, + "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" + } + }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "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.1.1", + "map-obj": "1.0.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caniuse-lite": { + "version": "1.0.30000808", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000808.tgz", + "integrity": "sha512-vT0JLmHdvq1UVbYXioxCXHYdNw55tyvi+IUWyX0Zeh1OFQi2IllYtm38IJnSgHWCv/zUnX1hdhy3vMJvuTNSqw==", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "ccount": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", + "integrity": "sha1-U7ai+BW7d7nChx97mnLDol8djok=", + "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" + }, + "dependencies": { + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + } + } + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + } + }, + "chai-nightwatch": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", + "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", + "dev": true, + "requires": { + "assertion-error": "1.0.0", + "deep-eql": "0.1.3" + }, + "dependencies": { + "assertion-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", + "dev": true + } + } + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "requires": { + "traverse": "0.3.9" + } + }, + "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.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "character-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", + "integrity": "sha1-92hxvl72bdt/j440eOzDdMJ9bco=", + "dev": true + }, + "character-entities-html4": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.1.tgz", + "integrity": "sha1-NZoqSg9+KdPcKsmb2+Ie45Q46lA=", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", + "integrity": "sha1-9Ad53xoQGHK7UQo9KV4fzPFHIC8=", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", + "integrity": "sha1-lCg191Dk7GGjCOYMLvjMEBEgLvw=", + "dev": true + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "chokidar": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.1.tgz", + "integrity": "sha512-rv5iP8ENhpqvDWr677rAXcB+SMoPQ1urd4ch79+PhM4lQwbATdJUQK69t0lJIKNB+VXpqxt5V1gvqs59XEPKnw==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.0", + "fsevents": "1.1.3", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.0.0" + } + }, + "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.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.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" + } + }, + "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" + } + } + } + }, + "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 + } + } + }, + "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, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "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" + } + }, + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "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 + }, + "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 + }, + "cloneable-readable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "1.0.7", + "through2": "2.0.3" + }, + "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 + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "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 + }, + "collapse-white-space": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", + "integrity": "sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "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 + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.6.2", + "lodash.memoize": "3.0.4", + "source-map": "0.5.7" + }, + "dependencies": { + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "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 + } + } + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "comma-separated-tokens": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.4.tgz", + "integrity": "sha1-cgg+WNSkYvAYZvZhf02Yo807ikY=", + "dev": true, + "requires": { + "trim": "0.0.1" + } + }, + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compress-commons": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", + "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "crc32-stream": "0.3.4", + "node-int64": "0.3.3", + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "compressible": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", + "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "compression": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", + "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", + "dev": true, + "requires": { + "accepts": "1.2.13", + "bytes": "2.1.0", + "compressible": "2.0.12", + "debug": "2.2.0", + "on-headers": "1.0.1", + "vary": "1.0.1" + }, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "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 + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "typedarray": "0.0.6" + } + }, + "concat-with-sourcemaps": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", + "integrity": "sha512-YtnS0VEY+e2Khzsey/6mra9EoM6h/5gxaC0e3mcHpA5yfDxafhygytNmcJWodvUgyXzSiL5MSkPO6bQGgfliHw==", + "dev": true, + "requires": { + "source-map": "0.6.1" + } + }, + "connect": { + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", + "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", + "dev": true, + "requires": { + "basic-auth-connect": "1.0.0", + "body-parser": "1.13.3", + "bytes": "2.1.0", + "compression": "1.5.2", + "connect-timeout": "1.6.2", + "content-type": "1.0.4", + "cookie": "0.1.3", + "cookie-parser": "1.3.5", + "cookie-signature": "1.0.6", + "csurf": "1.8.3", + "debug": "2.2.0", + "depd": "1.0.1", + "errorhandler": "1.4.3", + "express-session": "1.11.3", + "finalhandler": "0.4.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "method-override": "2.3.10", + "morgan": "1.6.1", + "multiparty": "3.3.2", + "on-headers": "1.0.1", + "parseurl": "1.3.2", + "pause": "0.1.0", + "qs": "4.0.0", + "response-time": "2.3.2", + "serve-favicon": "2.3.2", + "serve-index": "1.7.3", + "serve-static": "1.10.3", + "type-is": "1.6.15", + "utils-merge": "1.0.0", + "vhost": "3.0.2" + }, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + } + } + }, + "connect-livereload": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", + "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", + "dev": true + }, + "connect-timeout": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", + "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", + "dev": true, + "requires": { + "debug": "2.2.0", + "http-errors": "1.3.1", + "ms": "0.7.1", + "on-headers": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "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==", + "dev": true + }, + "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 + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "cookie": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", + "dev": true + }, + "cookie-parser": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "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=" + }, + "coveralls": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", + "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "dev": true, + "requires": { + "js-yaml": "3.6.1", + "lcov-parse": "0.0.10", + "log-driver": "1.2.5", + "minimist": "1.2.0", + "request": "2.79.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "crc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", + "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", + "dev": true + }, + "crc32-stream": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", + "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.10" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" + } + }, + "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.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "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": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.6", + "randomfill": "1.0.3" + } + }, + "csrf": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "dev": true, + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.5", + "uid-safe": "2.1.4" + } + }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "css-loader": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", + "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", + "dev": true, + "optional": true, + "requires": { + "csso": "1.3.12", + "loader-utils": "0.2.17", + "source-map": "0.1.43" + }, + "dependencies": { + "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, + "optional": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "2.2.1" + } + }, + "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 + }, + "csso": { + "version": "1.3.12", + "resolved": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", + "integrity": "sha1-/GKGlKLTiTiqrEmWdTIY/TEc254=", + "dev": true, + "optional": true + }, + "csurf": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", + "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6", + "csrf": "3.0.6", + "http-errors": "1.3.1" + } + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "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.2" + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "0.10.38" + } + }, + "dargs": { + "version": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", + "dev": true + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "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 + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "debug-fabulous": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", + "integrity": "sha512-dsd50qQ1atDeurcxL7XOjPp4nZCGZzWIONDujDXzl1atSyC3hMbZD+v6440etw+Vt0Pr8ce4TQzHfX3KZM05Mw==", + "requires": { + "debug": "3.1.0", + "memoizee": "0.4.11", + "object-assign": "4.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "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 + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "deep-is": { + "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": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", + "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "2.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.3" + }, + "dependencies": { + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "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" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "dev": true, + "requires": { + "ast-types": "0.10.2", + "escodegen": "1.8.1", + "esprima": "3.1.3" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "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 + }, + "depd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "shasum": "1.0.2", + "subarg": "1.0.0", + "through2": "2.0.3" + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detab": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", + "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", + "dev": true, + "requires": { + "repeat-string": "1.6.1" + } + }, + "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 + }, + "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.1" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "defined": "1.0.0" + } + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "disparity": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", + "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "diff": "1.4.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "doctrine-temporary-fork": { + "version": "2.0.0-alpha-allowarrayindex", + "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", + "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "documentation": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.4.0.tgz", + "integrity": "sha512-4i7nsVLUTIaKRU05op+6LCXosakbmvHdQWTeoj8UM9THbvwaO7Ok2ePgMl+s1Aw+31qeQTZqG5Z5JVgwspJocQ==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "babel-core": "6.26.0", + "babel-generator": "6.26.1", + "babel-plugin-system-import-transformer": "3.1.0", + "babel-plugin-transform-decorators-legacy": "1.3.4", + "babel-preset-env": "1.6.1", + "babel-preset-react": "6.24.1", + "babel-preset-stage-0": "6.24.1", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babelify": "8.0.0", + "babylon": "6.18.0", + "chalk": "2.3.1", + "chokidar": "2.0.1", + "concat-stream": "1.6.0", + "disparity": "2.0.0", + "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", + "get-port": "3.2.0", + "git-url-parse": "8.1.0", + "github-slugger": "1.2.0", + "glob": "7.1.2", + "globals-docs": "2.4.0", + "highlight.js": "9.12.0", + "js-yaml": "3.10.0", + "lodash": "4.17.5", + "mdast-util-inject": "1.1.0", + "micromatch": "3.1.5", + "mime": "2.2.0", + "module-deps-sortable": "4.0.6", + "parse-filepath": "1.0.2", + "pify": "3.0.0", + "read-pkg-up": "3.0.0", + "remark": "9.0.0", + "remark-html": "7.0.0", + "remark-toc": "5.0.0", + "remote-origin-url": "0.4.0", + "shelljs": "0.8.1", + "stream-array": "1.1.2", + "strip-json-comments": "2.0.1", + "tiny-lr": "1.1.0", + "unist-builder": "1.0.2", + "unist-util-visit": "1.3.0", + "vfile": "2.3.0", + "vfile-reporter": "4.0.0", + "vfile-sort": "2.1.0", + "vinyl": "2.1.0", + "vinyl-fs": "3.0.2", + "yargs": "9.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 + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "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.5", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + } + }, + "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" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "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 + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "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.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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.3.1" + } + }, + "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" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "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.4.0", + "path-type": "2.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 + }, + "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" + } + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "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.1", + "yargs-parser": "7.0.0" + }, + "dependencies": { + "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" + } + } + } + } + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "1.0.1", + "ent": "2.2.0", + "extend": "3.0.1", + "void-elements": "2.0.1" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", + "dev": true, + "optional": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "duplexify": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "stream-shift": "1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.33", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.33.tgz", + "integrity": "sha1-vwBwPWKnxlI4E2V4w1LWxcBCpUU=", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "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 + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "engine.io": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.4.tgz", + "integrity": "sha1-PQIRtwpVLOhB/8fahiezAamkFi4=", + "dev": true, + "requires": { + "accepts": "1.3.3", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "2.6.9", + "engine.io-parser": "2.1.2", + "uws": "0.14.5", + "ws": "3.3.3" + }, + "dependencies": { + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "dev": true, + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "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" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + } + } + }, + "engine.io-client": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.4.tgz", + "integrity": "sha1-T88TcLRxY70s6b4nM5ckMDUNTqE=", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "2.6.9", + "engine.io-parser": "2.1.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", + "yeast": "0.1.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" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary2": "1.0.2" + } + }, + "enhanced-resolve": { + "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.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "errno": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", + "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", + "dev": true, + "requires": { + "prr": "1.0.1" + } + }, + "error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "dev": true, + "requires": { + "string-template": "0.2.1", + "xtend": "4.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "errorhandler": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", + "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "escape-html": "1.0.3" + }, + "dependencies": { + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "dev": true, + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + } + } + }, + "es5-ext": { + "version": "0.10.38", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", + "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es5-shim": { + "version": "4.5.10", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", + "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==", + "dev": true + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-symbol": "3.1.1" + } + }, + "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.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "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.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "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 + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "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.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz", + "integrity": "sha512-AyxBUCANU/o/xC0ijGMKavo5Ls3oK6xykiOITlMdjFjrKOsqLrA7Nf5cnrDgcKrHzBirclAZt63XO7YZlVUPwA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.3.1", + "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.3", + "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.3.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.5", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.5.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "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 + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "globals": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "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" + } + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "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 + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "2.6.9", + "resolve": "1.5.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" + } + } + } + }, + "eslint-module-utils": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "pkg-dir": "1.0.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" + } + }, + "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" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", + "dev": true, + "requires": { + "builtin-modules": "1.1.1", + "contains-path": "0.1.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.3.2", + "eslint-module-utils": "2.1.1", + "has": "1.0.1", + "lodash.cond": "4.5.2", + "minimatch": "3.0.4", + "read-pkg-up": "2.0.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" + } + }, + "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.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "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=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "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" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "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.4.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" + } + } + } + }, + "eslint-plugin-node": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "dev": true, + "requires": { + "ignore": "3.3.7", + "minimatch": "3.0.4", + "resolve": "1.5.0", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", + "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", + "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "estree-walker": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", + "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38" + } + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "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.4", + "safe-buffer": "5.1.1" + } + }, + "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.2", + "strip-eof": "1.0.0" + } + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "requires": { + "array-slice": "0.2.3", + "array-unique": "0.2.1", + "braces": "0.1.5" + }, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true, + "requires": { + "expand-range": "0.1.1" + } + }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "requires": { + "is-number": "0.1.1", + "repeat-string": "0.2.2" + } + }, + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, + "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.0", + "snapdragon": "0.8.1", + "to-regex": "3.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" + } + }, + "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" + } + }, + "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" + } + } + } + }, + "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 + } + } + }, + "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.3" + }, + "dependencies": { + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "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.2.2" + } + }, + "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" + } + }, + "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" + } + } + } + }, + "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, + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "expect.js": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", + "integrity": "sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s=", + "dev": true + }, + "express-session": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", + "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6", + "crc": "3.3.0", + "debug": "2.2.0", + "depd": "1.0.1", + "on-headers": "1.0.1", + "parseurl": "1.3.2", + "uid-safe": "2.0.0", + "utils-merge": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "uid-safe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", + "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", + "dev": true, + "requires": { + "base64-url": "1.2.1" + } + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "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" + } + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "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.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "faker": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/faker/-/faker-3.1.0.tgz", + "integrity": "sha1-D5CPr05uwCUk5UpX5DLFwBPgjJ8=", + "dev": true + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "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, + "requires": { + "websocket-driver": "0.7.0" + } + }, + "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" + } + }, + "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, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "file-loader": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", + "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", + "dev": true, + "optional": true, + "requires": { + "loader-utils": "0.2.17" + }, + "dependencies": { + "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, + "optional": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + } + } + }, + "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 + }, + "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 + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "7.1.2", + "minimatch": "3.0.4" + } + }, + "fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "dev": true, + "requires": { + "is-object": "1.0.1", + "merge-descriptors": "1.0.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" + } + }, + "finalhandler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", + "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", + "dev": true, + "requires": { + "debug": "2.2.0", + "escape-html": "1.0.2", + "on-finished": "2.3.0", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "escape-html": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", + "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "make-dir": "1.1.0", + "pkg-dir": "2.0.0" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "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": "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.1.5", + "resolve-dir": "1.0.1" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "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" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "flush-write-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", + "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4" + } + }, + "follow-redirects": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", + "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "foreachasync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", + "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "fork-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.17" + } + }, + "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, + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "dev": true + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "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, + "requires": { + "null-check": "1.0.0" + } + }, + "fs-extra": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", + "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", + "dev": true, + "requires": { + "jsonfile": "1.0.1", + "mkdirp": "0.3.5", + "ncp": "0.4.2", + "rimraf": "2.2.8" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + } + } + }, + "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, + "requires": { + "graceful-fs": "4.1.11", + "through2": "2.0.3" + } + }, + "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, + "requires": { + "fs-extra": "0.6.4", + "mkdirp": "0.3.5", + "walk": "2.3.9" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "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" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "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": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "fstream": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", + "dev": true, + "requires": { + "graceful-fs": "3.0.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.1" + } + } + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "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 + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true + }, + "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 + }, + "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 + }, + "get-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", + "integrity": "sha512-7aelVrYqCLuVjq2kEKRTH8fXPTC0xKTkM+G7UlFkEwCXY3sFbSxvY375JoFowOAYbkaU47SrBvOefUlLZZ+6QA==", + "dev": true, + "requires": { + "data-uri-to-buffer": "1.2.0", + "debug": "2.6.9", + "extend": "3.0.1", + "file-uri-to-path": "1.0.0", + "ftp": "0.3.10", + "readable-stream": "2.3.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" + } + } + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "git-up": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", + "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", + "dev": true, + "requires": { + "is-ssh": "1.3.0", + "parse-url": "1.3.11" + } + }, + "git-url-parse": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.1.0.tgz", + "integrity": "sha512-tSdNasqIc9cjK75DRsirb5sqVJ4V4cCmCuuOyyx2SuYeJx4o9AOx+/ZCSwRrYjZ8zavtuhGjCqXlCo9Db0YIVA==", + "dev": true, + "requires": { + "git-up": "2.0.10" + } + }, + "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, + "requires": { + "emoji-regex": "6.1.1" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "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": { + "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": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.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, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "3.0.1", + "glob": "7.1.2", + "glob-parent": "3.1.0", + "is-negated-glob": "1.0.0", + "ordered-read-streams": "1.0.1", + "pumpify": "1.4.0", + "readable-stream": "2.3.4", + "remove-trailing-separator": "1.1.0", + "to-absolute-glob": "2.0.2", + "unique-stream": "2.2.1" + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.1", + "resolve-dir": "1.0.1" + } + }, + "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, + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.1", + "which": "1.3.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 + }, + "globals-docs": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", + "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", + "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.1.0", + "liftoff": "2.5.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "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 + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + } + } + } + }, + "gulp-babel": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", + "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "object-assign": "4.1.1", + "plugin-error": "1.0.1", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "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.5", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "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" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "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 + } + } + }, + "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.6.2", + "through2": "0.4.2" + }, + "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 + }, + "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.5", + "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.7.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.1", + "dateformat": "1.0.12", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "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" + } + } + } + }, + "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.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "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.escape": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", + "dev": true, + "requires": { + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" + } + }, + "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, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "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" + } + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "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 + }, + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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": "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" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "dev": true, + "requires": { + "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" + } + } + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true, + "requires": { + "clone-stats": "0.0.1" + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.5", + "through2": "2.0.3", + "vinyl": "2.1.0" + } + }, + "gulp-connect": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", + "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", + "dev": true, + "requires": { + "connect": "2.30.2", + "connect-livereload": "0.5.4", + "event-stream": "3.3.4", + "gulp-util": "3.0.8", + "tiny-lr": "0.2.1" + }, + "dependencies": { + "body-parser": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "dev": true, + "requires": { + "bytes": "2.2.0", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.1.2", + "http-errors": "1.3.1", + "iconv-lite": "0.4.13", + "on-finished": "2.3.0", + "qs": "5.2.0", + "raw-body": "2.1.7", + "type-is": "1.6.15" + }, + "dependencies": { + "qs": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "dev": true + } + } + }, + "bytes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + } + } + }, + "tiny-lr": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "dev": true, + "requires": { + "body-parser": "1.14.2", + "debug": "2.2.0", + "faye-websocket": "0.10.0", + "livereload-js": "2.3.0", + "parseurl": "1.3.2", + "qs": "5.1.0" + } + } + } + }, + "gulp-documentation": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", + "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", + "dev": true, + "requires": { + "through2": "2.0.3", + "vinyl": "2.1.0" + } + }, + "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, + "requires": { + "eslint": "4.17.0", + "fancy-log": "1.3.2", + "plugin-error": "1.0.1" + } + }, + "gulp-footer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", + "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", + "dev": true, + "requires": { + "event-stream": "3.3.4", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2" + } + }, + "gulp-header": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.9.tgz", + "integrity": "sha1-yfEP7gYy2B6Tl4nG7PRaFRvzCYs=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.5", + "gulp-util": "3.0.8", + "object-assign": "4.1.1", + "through2": "2.0.3" + } + }, + "gulp-if": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", + "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", + "dev": true, + "requires": { + "gulp-match": "1.0.3", + "ternary-stream": "2.0.1", + "through2": "2.0.3" + } + }, + "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, + "requires": { + "through2": "0.6.5" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulp-match": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", + "dev": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "gulp-optimize-js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", + "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "lodash": "4.17.5", + "optimize-js": "1.0.3", + "through2": "2.0.3" + } + }, + "gulp-rename": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", + "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", + "dev": true + }, + "gulp-replace": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", + "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", + "dev": true, + "requires": { + "event-stream": "3.0.20", + "istextorbinary": "1.0.2", + "replacestream": "0.1.3" + }, + "dependencies": { + "event-stream": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", + "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.0.7", + "pause-stream": "0.0.11", + "split": "0.2.10", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "split": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", + "dev": true, + "requires": { + "through": "2.3.8" + } + } + } + }, + "gulp-shell": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", + "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", + "dev": true, + "requires": { + "async": "1.5.2", + "gulp-util": "3.0.8", + "lodash": "4.17.5", + "through2": "2.0.3" + } + }, + "gulp-sourcemaps": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "requires": { + "@gulp-sourcemaps/identity-map": "1.0.1", + "@gulp-sourcemaps/map-sources": "1.0.0", + "acorn": "5.4.1", + "convert-source-map": "1.5.1", + "css": "2.2.1", + "debug-fabulous": "1.0.0", + "detect-newline": "2.1.0", + "graceful-fs": "4.1.11", + "source-map": "0.6.1", + "strip-bom-string": "1.0.0", + "through2": "2.0.3" + } + }, + "gulp-uglify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", + "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", + "dev": true, + "requires": { + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash": "4.17.5", + "make-error-cause": "1.2.2", + "through2": "2.0.3", + "uglify-js": "3.3.10", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "uglify-js": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.10.tgz", + "integrity": "sha512-dNib7aUDNZFJNTXFyq0CDmLRVOsnY1F+IQgt2FAOdZFx2+LvKVLbbIb/fL+BYKCv3YH3bPCE/6M/JaxChtQLHQ==", + "dev": true, + "requires": { + "commander": "2.14.1", + "source-map": "0.6.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "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.2", + "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.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "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 + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "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 + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-webdriver": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", + "integrity": "sha1-mM6Bz5rganoZB7htEPaThvQ4Oi0=", + "dev": true, + "requires": { + "dargs": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", + "deepmerge": "0.2.10", + "gulp-util": "3.0.8", + "through2": "0.6.5", + "webdriverio": "3.4.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.1" + } + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "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" + } + } + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.14.1", + "is-my-json-valid": "2.17.1", + "pinkie-promise": "2.0.1" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-binary2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", + "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "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.1" + } + }, + "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, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hast-util-is-element": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", + "integrity": "sha1-P3IWl4sq4U2YdJh4eCZ18zvjzgA=", + "dev": true + }, + "hast-util-sanitize": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", + "integrity": "sha1-0QvWdXoh5ZwTq8iuNTDdO219Z54=", + "dev": true, + "requires": { + "xtend": "4.0.1" + } + }, + "hast-util-to-html": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", + "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", + "dev": true, + "requires": { + "ccount": "1.0.2", + "comma-separated-tokens": "1.0.4", + "hast-util-is-element": "1.0.0", + "hast-util-whitespace": "1.0.0", + "html-void-elements": "1.0.2", + "kebab-case": "1.0.0", + "property-information": "3.2.0", + "space-separated-tokens": "1.1.1", + "stringify-entities": "1.3.1", + "unist-util-is": "2.1.1", + "xtend": "4.0.1" + } + }, + "hast-util-whitespace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", + "integrity": "sha1-vQlpGWJdKTbh/xe8Tff9cn8X7Ok=", + "dev": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", + "dev": true + }, + "hipchat-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", + "dev": true, + "optional": true, + "requires": { + "lodash": "4.17.5", + "request": "2.79.0" + } + }, + "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": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "html-void-elements": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.2.tgz", + "integrity": "sha1-nSLgyjKsyVs/RbjVtPb73AWv/VU=", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "http-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "statuses": "1.4.0" + } + }, + "http-parser-js": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", + "dev": true + }, + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } + }, + "http-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", + "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.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" + } + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "httpntlm": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "dev": true, + "requires": { + "httpreq": "0.4.24", + "underscore": "1.7.0" + } + }, + "httpreq": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", + "dev": true + }, + "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": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.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" + } + } + } + }, + "iconv-lite": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", + "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", + "dev": true + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "ignore-loader": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz", + "integrity": "sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflection": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", + "integrity": "sha1-W//LEZetPoEFD44X4hZoCH7p6y8=", + "dev": true, + "optional": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "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, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.5", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "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" + }, + "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 + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "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" + } + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "insert-module-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", + "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "combine-source-map": "0.7.2", + "concat-stream": "1.5.2", + "is-buffer": "1.1.6", + "lexical-scope": "1.2.0", + "process": "0.11.10", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "combine-source-map": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", + "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.6.2", + "lodash.memoize": "3.0.4", + "source-map": "0.5.7" + } + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + } + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "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 + }, + "ip": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", + "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", + "dev": true + }, + "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, + "requires": { + "is-relative": "1.0.0", + "is-windows": "1.0.1" + } + }, + "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.2" + } + }, + "is-alphabetical": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", + "integrity": "sha1-x3B5zJHU76x3W+EDS/LSQ/lebwg=", + "dev": true + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", + "integrity": "sha1-37SqTRCF4zvbYcLe6cgOnGwZ9Ts=", + "dev": true, + "requires": { + "is-alphabetical": "1.0.1", + "is-decimal": "1.0.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "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-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.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.2" + } + }, + "is-decimal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", + "integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI=", + "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.2" + } + }, + "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-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", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "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" + } + }, + "is-generator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", + "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz", + "integrity": "sha1-bghLvJIGH7sJcexYts5tQE4k2mk=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz", + "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "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 + }, + "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" + } + } + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-odd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", + "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=", + "dev": true, + "requires": { + "is-number": "3.0.0" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "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": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "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, + "requires": { + "is-unc-path": "1.0.0" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-ssh": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", + "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", + "dev": true, + "requires": { + "protocols": "1.4.6" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "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, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "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 + }, + "is-whitespace-character": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", + "integrity": "sha1-muAXbzKCtlRXoZks2whPil+DPjs=", + "dev": true + }, + "is-windows": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", + "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=", + "dev": true + }, + "is-word-character": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", + "integrity": "sha1-WgP6HqkazopusMfNdw64bWXIvvs=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "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 + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.6.1", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + }, + "dependencies": { + "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.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-api": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.2.tgz", + "integrity": "sha512-kH5YRdqdbs5hiH4/Rr1Q0cSAGgjh3jTtg8vu9NLebBAoK3adVO4jk81J+TYOkTr2+Q4NLeb1ACvmEt65iG/Vbw==", + "dev": true, + "requires": { + "async": "2.6.0", + "fileset": "2.0.3", + "istanbul-lib-coverage": "1.1.2", + "istanbul-lib-hook": "1.1.0", + "istanbul-lib-instrument": "1.9.2", + "istanbul-lib-report": "1.1.3", + "istanbul-lib-source-maps": "1.2.3", + "istanbul-reports": "1.1.4", + "js-yaml": "3.10.0", + "mkdirp": "0.5.1", + "once": "1.4.0" + }, + "dependencies": { + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + } + } + }, + "istanbul-instrumenter-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz", + "integrity": "sha512-alLSEFX06ApU75sm5oWcaVNaiss/bgMRiWTct3g0P0ZZTKjR+6QiCcuVOKDI1kWJgwHEnIXsv/dWm783kPpmtw==", + "dev": true, + "requires": { + "convert-source-map": "1.5.1", + "istanbul-lib-instrument": "1.9.2", + "loader-utils": "1.1.0", + "schema-utils": "0.3.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", + "integrity": "sha512-tZYA0v5A7qBSsOzcebJJ/z3lk3oSzH62puG78DbBA1+zupipX2CakDyiPV3pOb8He+jBwVimuwB0dTnh38hX0w==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", + "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==", + "dev": true, + "requires": { + "append-transform": "0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz", + "integrity": "sha512-nz8t4HQ2206a/3AXi+NHFWEa844DMpPsgbcUteJbt1j8LX1xg56H9rOMnhvcvVvPbW60qAIyrSk44H8ZDqaSSA==", + "dev": true, + "requires": { + "babel-generator": "6.26.1", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.1.2", + "semver": "5.5.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", + "integrity": "sha512-D4jVbMDtT2dPmloPJS/rmeP626N5Pr3Rp+SovrPn1+zPChGHcggd/0sL29jnbm4oK9W0wHjCRsdch9oLd7cm6g==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.1.2", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" + }, + "dependencies": { + "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 + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", + "integrity": "sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA==", + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.1.2", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.4.tgz", + "integrity": "sha512-DfSTVOTkuO+kRmbO8Gk650Wqm1WRGr6lrdi2EwDK1vxpS71vdlLd613EpzOKdIFioB5f/scJTjeWBnvd1FWejg==", + "dev": true, + "requires": { + "handlebars": "4.0.11" + } + }, + "istextorbinary": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", + "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", + "dev": true, + "requires": { + "binaryextensions": "1.0.1", + "textextensions": "1.0.2" + } + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "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 + }, + "js-yaml": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "2.7.3" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "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.1", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "dev": true + }, + "json-schema": { + "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": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "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 + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", + "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "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.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "just-clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", + "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" + }, + "just-extend": { + "version": "1.1.27", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", + "dev": true + }, + "karma": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.0.tgz", + "integrity": "sha512-K9Kjp8CldLyL9ANSUctDyxC7zH3hpqXj/K09qVf06K3T/kXaHtFZ5tQciK7OzQu68FLvI89Na510kqQ2LCbpIw==", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "body-parser": "1.18.2", + "browserify": "14.5.0", + "chokidar": "1.7.0", + "colors": "1.1.2", + "combine-lists": "1.0.1", + "connect": "3.6.5", + "core-js": "2.5.3", + "di": "0.0.1", + "dom-serialize": "2.2.1", + "expand-braces": "0.1.2", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "http-proxy": "1.16.2", + "isbinaryfile": "3.0.2", + "lodash": "4.17.5", + "log4js": "2.5.3", + "mime": "1.6.0", + "minimatch": "3.0.4", + "optimist": "0.6.1", + "qjobs": "1.1.5", + "range-parser": "1.2.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.1", + "socket.io": "2.0.4", + "source-map": "0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + }, + "dependencies": { + "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 + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.15" + } + }, + "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.2" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "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.1", + "fsevents": "1.1.3", + "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.1.0" + } + }, + "connect": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.5.tgz", + "integrity": "sha1-+43ee6B2OHfQ7J352sC0tA5yx9o=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.0.6", + "parseurl": "1.3.2", + "utils-merge": "1.0.1" + } + }, + "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": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "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" + } + }, + "finalhandler": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", + "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, + "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" + } + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "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 + }, + "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" + } + }, + "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": "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" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + } + } + }, + "karma-babel-preprocessor": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", + "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", + "dev": true, + "requires": { + "babel-core": "6.22.0" + } + }, + "karma-browserstack-launcher": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", + "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", + "dev": true, + "requires": { + "browserstack": "1.5.0", + "browserstacktunnel-wrapper": "2.0.1", + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "karma-chai": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", + "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", + "dev": true + }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true, + "requires": { + "fs-access": "1.0.1", + "which": "1.3.0" + } + }, + "karma-coverage-istanbul-reporter": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.1.tgz", + "integrity": "sha512-5og0toMjgLvsL9+TzGH4Rk1D0nr7pMIRJBg29xP4mHMKy/1KUJ12UzoqI6mBNCRFa4nDvZS2MRrN7p+RkZNWxQ==", + "dev": true, + "requires": { + "istanbul-api": "1.2.2", + "minimatch": "3.0.4" + } + }, + "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, + "requires": { + "es5-shim": "4.5.10" + } + }, + "karma-expect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/karma-expect/-/karma-expect-1.1.3.tgz", + "integrity": "sha1-xrClb/GJA9sRr08JjMbnzxmM4nU=", + "dev": true, + "requires": { + "expect.js": "0.3.1" + } + }, + "karma-firefox-launcher": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", + "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", + "dev": true + }, + "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, + "requires": { + "lodash": "4.17.5" + } + }, + "karma-mocha": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", + "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "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, + "requires": { + "chalk": "2.3.1", + "log-symbols": "2.2.0", + "strip-ansi": "4.0.0" + }, + "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 + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.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" + } + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "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 + }, + "karma-requirejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-1.1.0.tgz", + "integrity": "sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=", + "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 + }, + "karma-sauce-launcher": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/karma-sauce-launcher/-/karma-sauce-launcher-1.2.0.tgz", + "integrity": "sha512-lEhtGRGS+3Yw6JSx/vJY9iQyHNtTjcojrSwNzqNUOaDceKDu9dPZqA/kr69bUO9G2T6GKbu8AZgXqy94qo31Jg==", + "dev": true, + "requires": { + "q": "1.5.1", + "sauce-connect-launcher": "1.2.3", + "saucelabs": "1.4.0", + "wd": "1.5.0" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "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 + }, + "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 + }, + "karma-sourcemap-loader": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", + "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "karma-spec-reporter": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", + "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", + "dev": true, + "requires": { + "colors": "1.1.2" + } + }, + "karma-webpack": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.9.tgz", + "integrity": "sha512-F1j3IG/XhiMzcunAXbWXH95uizjzr3WdTzmVWlta8xqxcCtAu9FByCb4sccIMxaVFAefpgnUW9KlCo0oLvIX6A==", + "dev": true, + "requires": { + "async": "0.9.2", + "loader-utils": "0.2.17", + "lodash": "3.10.1", + "source-map": "0.5.7", + "webpack-dev-middleware": "1.12.2" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "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" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "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 + } + } + }, + "kebab-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", + "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "labeled-stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", + "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "isarray": "0.0.1", + "stream-splicer": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "dev": true, + "requires": { + "set-getter": "0.1.0" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "lcov-parse": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "1.0.2" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "requires": { + "astw": "2.2.0" + } + }, + "libbase64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", + "dev": true + }, + "libmime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", + "dev": true, + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", + "dev": true + } + } + }, + "libqp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", + "dev": true + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.5.0" + } + }, + "livereload-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", + "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", + "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=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "localtunnel": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.8.3.tgz", + "integrity": "sha1-3MWSL9hWUQN9S94k/ZMkjQsk6wU=", + "dev": true, + "requires": { + "debug": "2.6.8", + "openurl": "1.1.1", + "request": "2.81.0", + "yargs": "3.29.0" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "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": { + "safe-buffer": "5.1.1" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true + }, + "yargs": { + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.29.0.tgz", + "integrity": "sha1-GquWYOrnnYuPZ1vK7qtu40ws9pw=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } + }, + "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" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + }, + "lodash._arraycopy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", + "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", + "dev": true + }, + "lodash._arrayeach": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", + "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._baseclone": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", + "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", + "dev": true, + "requires": { + "lodash._arraycopy": "3.0.0", + "lodash._arrayeach": "3.0.0", + "lodash._baseassign": "3.2.0", + "lodash._basefor": "3.0.3", + "lodash.isarray": "3.0.4", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._basefor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", + "dev": true + }, + "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 + }, + "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 + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "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, + "requires": { + "lodash._htmlescapes": "2.4.1" + } + }, + "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 + }, + "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 + }, + "lodash._htmlescapes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "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._reunescapedhtml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" + }, + "dependencies": { + "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, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "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, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash._stack": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", + "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", + "dev": true + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "lodash.clone": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", + "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", + "dev": true, + "requires": { + "lodash._baseclone": "3.3.0", + "lodash._bindcallback": "3.0.1", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "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" + }, + "dependencies": { + "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, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "lodash.defaultsdeep": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", + "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", + "dev": true, + "requires": { + "lodash._baseclone": "4.5.7", + "lodash._stack": "4.1.3", + "lodash.isplainobject": "4.0.6", + "lodash.keysin": "4.2.0", + "lodash.mergewith": "4.6.1", + "lodash.rest": "4.0.5" + }, + "dependencies": { + "lodash._baseclone": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", + "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", + "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.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 + }, + "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 + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "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, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "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 + }, + "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.keysin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", + "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "dev": true + }, + "lodash.rest": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", + "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "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" + } + }, + "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, + "requires": { + "lodash.keys": "2.4.1" + }, + "dependencies": { + "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, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "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.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + } + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "log4js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", + "integrity": "sha512-YL/qpTxYtK0iWWbuKCrevDZz5lh+OjyHHD+mICqpjnYGKdNRBvPeh/1uYjkKUemT1CSO4wwLOwphWMpKAnD9kw==", + "dev": true, + "requires": { + "amqplib": "0.5.2", + "axios": "0.15.3", + "circular-json": "0.5.1", + "date-format": "1.2.0", + "debug": "3.1.0", + "hipchat-notifier": "1.1.0", + "loggly": "1.1.1", + "mailgun-js": "0.7.15", + "nodemailer": "2.7.2", + "redis": "2.8.0", + "semver": "5.5.0", + "slack-node": "0.2.0", + "streamroller": "0.7.0" + }, + "dependencies": { + "circular-json": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.1.tgz", + "integrity": "sha512-UjgcRlTAhAkLeXmDe2wK7ktwy/tgAqxiSndTIPiFZuIPLZmzHzWMwUIe9h9m/OokypG7snxCDEuwJshGBdPvaw==", + "dev": true + } + } + }, + "loggly": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", + "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", + "dev": true, + "optional": true, + "requires": { + "json-stringify-safe": "5.0.1", + "request": "2.75.0", + "timespan": "2.3.0" + }, + "dependencies": { + "bl": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "2.0.6" + } + }, + "form-data": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.17" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true, + "optional": 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, + "optional": true + }, + "qs": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.75.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "bl": "1.1.2", + "caseless": "0.11.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.0.0", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "node-uuid": "1.4.8", + "oauth-sign": "0.8.2", + "qs": "6.2.3", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3" + } + }, + "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, + "optional": true + } + } + }, + "lolex": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==", + "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.2", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "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.2" + } + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "0.10.38" + } + }, + "magic-string": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", + "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", + "dev": true, + "requires": { + "vlq": "0.2.3" + } + }, + "mailcomposer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", + "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", + "dev": true, + "optional": true, + "requires": { + "buildmail": "4.0.1", + "libmime": "3.0.0" + } + }, + "mailgun-js": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", + "integrity": "sha1-7jZqINrGTDwVwD1sGz4O15UlKrs=", + "dev": true, + "optional": true, + "requires": { + "async": "2.1.5", + "debug": "2.2.0", + "form-data": "2.1.4", + "inflection": "1.10.0", + "is-stream": "1.1.0", + "path-proxy": "1.0.0", + "proxy-agent": "2.0.0", + "q": "1.4.1", + "tsscmp": "1.0.5" + }, + "dependencies": { + "async": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", + "integrity": "sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw=", + "dev": true, + "optional": true, + "requires": { + "lodash": "4.17.5" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "optional": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true, + "optional": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true, + "optional": true + } + } + }, + "make-dir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "make-error": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.3.tgz", + "integrity": "sha512-j3dZCri3cCd23wgPqK/0/KvTN8R+W6fXDqQe8BNLbTpONjbA8SPaRr+q0BQq9bx3Q/+g68/gDIh9FW3by702Tg==", + "dev": true + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "dev": true, + "requires": { + "make-error": "1.3.3" + } + }, + "make-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", + "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", + "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" + } + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "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.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "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, + "requires": { + "object-visit": "1.0.1" + } + }, + "markdown-escapes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", + "integrity": "sha1-GZTfLTr0gR3lmmcUk0wrIpJzRRg=", + "dev": true + }, + "markdown-table": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.1.tgz", + "integrity": "sha1-Sz3ToTPRUYuO8NvHCb8qG0gkvIw=", + "dev": true + }, + "match-stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", + "dev": true, + "requires": { + "buffers": "0.1.1", + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "mdast-util-compact": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", + "dev": true, + "requires": { + "unist-util-modify-children": "1.1.1", + "unist-util-visit": "1.3.0" + } + }, + "mdast-util-definitions": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", + "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", + "dev": true, + "requires": { + "unist-util-visit": "1.3.0" + } + }, + "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, + "requires": { + "mdast-util-to-string": "1.0.4" + } + }, + "mdast-util-to-hast": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.0.tgz", + "integrity": "sha512-zvEXH2AUevWfKuBqtEPNcDUPI8UC6yIVvgEgNi1v1dLnzb5Pfm+PZjnZn0FhW1WmHcrGMX059MAoqicEauzjcw==", + "dev": true, + "requires": { + "collapse-white-space": "1.0.3", + "detab": "2.0.1", + "mdast-util-definitions": "1.2.2", + "mdurl": "1.0.1", + "trim": "0.0.1", + "trim-lines": "1.1.0", + "unist-builder": "1.0.2", + "unist-util-generated": "1.1.1", + "unist-util-position": "3.0.0", + "unist-util-visit": "1.3.0", + "xtend": "4.0.1" + } + }, + "mdast-util-to-string": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", + "integrity": "sha1-XEVch4yTVfDB5/PotxnPWDaRrPs=", + "dev": true + }, + "mdast-util-toc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", + "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", + "dev": true, + "requires": { + "github-slugger": "1.2.0", + "mdast-util-to-string": "1.0.4", + "unist-util-visit": "1.3.0" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "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" + } + }, + "memoizee": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", + "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-weak-map": "2.0.2", + "event-emitter": "0.3.5", + "is-promise": "2.1.0", + "lru-queue": "0.1.0", + "next-tick": "1.0.0", + "timers-ext": "0.1.2" + } + }, + "memory-fs": { + "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.6", + "readable-stream": "2.3.4" + } + }, + "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.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.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" + } + }, + "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.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "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.3.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" + } + }, + "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.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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.4.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" + } + }, + "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" + } + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "method-override": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", + "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "methods": "1.1.2", + "parseurl": "1.3.2", + "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==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.5.tgz", + "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.0", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.7", + "object.pick": "1.3.0", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + } + }, + "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.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", + "integrity": "sha512-0Qz9uF1ATtl8RKJG4VRfOymh7PyEor6NbrI/61lRfuRe4vx9SNATrvAeTj2EWVRKjEQGskrzWkJBBY5NbaVHIA==", + "dev": true + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "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 + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "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.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.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "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": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mkpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", + "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", + "dev": true + }, + "mocha": { + "version": "1.21.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.21.5.tgz", + "integrity": "sha1-fFiwkXTfl25DSiOx6NY5hz/FKek=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.0.0", + "diff": "1.0.8", + "escape-string-regexp": "1.0.2", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.5.0" + }, + "dependencies": { + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "debug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", + "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", + "dev": true, + "requires": { + "ms": "0.6.2" + } + }, + "diff": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz", + "integrity": "sha1-NDJ2MI7Jkbe8giZ+1VvBQR+XFmY=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "glob": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "dev": true, + "requires": { + "graceful-fs": "2.0.3", + "inherits": "2.0.3", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", + "dev": true + } + } + }, + "mocha-nightwatch": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", + "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.5", + "glob": "7.0.5", + "growl": "1.9.2", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "glob": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", + "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" + } + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "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 + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "mock-fs": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", + "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", + "dev": true, + "requires": { + "rewire": "2.5.2", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "module-deps-sortable": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", + "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "browser-resolve": "1.11.2", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "4.7.1", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "parents": "1.0.1", + "readable-stream": "2.3.4", + "resolve": "1.5.0", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "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 + }, + "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 + } + } + }, + "module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", + "dev": true + }, + "morgan": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", + "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", + "dev": true, + "requires": { + "basic-auth": "1.0.4", + "debug": "2.2.0", + "depd": "1.0.1", + "on-finished": "2.3.0", + "on-headers": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multiparty": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", + "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "stream-counter": "0.2.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.7.tgz", + "integrity": "sha512-/5ldsnyurvEw7wNpxLFgjVvBLMta43niEYOy0CJ4ntcYSbx6bugRUTQeFb4BR/WanEL1o3aQgHuVLHQaB6tOqg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "is-odd": "1.0.0", + "kind-of": "5.1.0", + "object.pick": "1.3.0", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + }, + "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 + } + } + }, + "natives": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", + "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", + "dev": true + }, + "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 + }, + "ncp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", + "dev": true + }, + "negotiator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", + "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", + "dev": true + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "nightwatch": { + "version": "0.9.19", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.19.tgz", + "integrity": "sha1-S9l1cnPTC4RfBIR6mLcb6bt8Szs=", + "dev": true, + "requires": { + "chai-nightwatch": "0.1.1", + "ejs": "2.5.7", + "lodash.clone": "3.0.3", + "lodash.defaultsdeep": "4.3.2", + "minimatch": "3.0.3", + "mkpath": "1.0.0", + "mocha-nightwatch": "3.2.2", + "optimist": "0.6.1", + "proxy-agent": "2.0.0", + "q": "1.4.1" + }, + "dependencies": { + "minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + } + } + }, + "nise": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.2.5.tgz", + "integrity": "sha512-Es4hGuq3lpip5PckrB+Qpuma282M0UJANJ+jxAgI+0wWTL9X6MtNv+M385JgqsAE8hv6NvD3lv8CQtXgEnvlpQ==", + "dev": true, + "requires": { + "@sinonjs/formatio": "2.0.0", + "just-extend": "1.1.27", + "lolex": "2.3.2", + "path-to-regexp": "1.7.0", + "text-encoding": "0.6.4" + } + }, + "node-int64": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", + "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", + "dev": true + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.1.7", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.4", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.6", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "timers-browserify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "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 + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + } + } + }, + "nodemailer": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", + "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", + "dev": true, + "optional": true, + "requires": { + "libmime": "3.0.0", + "mailcomposer": "4.0.1", + "nodemailer-direct-transport": "3.3.2", + "nodemailer-shared": "1.1.0", + "nodemailer-smtp-pool": "2.8.2", + "nodemailer-smtp-transport": "2.7.2", + "socks": "1.1.9" + }, + "dependencies": { + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true, + "optional": true + }, + "socks": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", + "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", + "dev": true, + "optional": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + } + } + }, + "nodemailer-direct-transport": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", + "dev": true + }, + "nodemailer-shared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", + "dev": true, + "requires": { + "nodemailer-fetch": "1.6.0" + } + }, + "nodemailer-smtp-pool": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-smtp-transport": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "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, + "requires": { + "path-key": "2.0.1" + } + }, + "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 + }, + "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 + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.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" + } + }, + "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" + } + }, + "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" + } + }, + "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" + }, + "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 + } + } + }, + "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" + } + } + } + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "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, + "requires": { + "isobject": "3.0.1" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.0" + } + }, + "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": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "open": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", + "dev": true + }, + "openurl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optimize-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", + "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", + "dev": true, + "requires": { + "acorn": "3.3.0", + "concat-stream": "1.6.0", + "estree-walker": "0.3.1", + "magic-string": "0.16.0", + "yargs": "4.8.1" + }, + "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 + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "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" + } + }, + "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.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "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.3.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" + } + }, + "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.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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.4.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" + } + }, + "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" + } + }, + "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 + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true, + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "lodash.assign": "4.2.0", + "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", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" + } + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "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", + "wordwrap": "1.0.0" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.0" + }, + "dependencies": { + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "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, + "requires": { + "readable-stream": "2.3.4" + } + }, + "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-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "os-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 + }, + "over": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "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.2.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 + }, + "pac-proxy-agent": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", + "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1", + "get-uri": "2.0.1", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "1.0.0", + "pac-resolver": "2.0.0", + "raw-body": "2.3.2", + "socks-proxy-agent": "2.1.1" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "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" + } + }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + } + } + }, + "pac-resolver": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", + "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", + "dev": true, + "requires": { + "co": "3.0.6", + "degenerator": "1.0.4", + "ip": "1.0.1", + "netmask": "1.0.6", + "thunkify": "2.1.2" + }, + "dependencies": { + "co": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", + "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", + "dev": true + } + } + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.2", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", + "integrity": "sha1-gRLYhHExnyerrk1klksSL+ThuJA=", + "dev": true, + "requires": { + "character-entities": "1.2.1", + "character-entities-legacy": "1.1.1", + "character-reference-invalid": "1.1.1", + "is-alphanumerical": "1.0.1", + "is-decimal": "1.0.1", + "is-hexadecimal": "1.0.1" + } + }, + "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, + "requires": { + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-git-config": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", + "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", + "dev": true, + "requires": { + "ini": "1.3.5" + } + }, + "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=", + "dev": true, + "requires": { + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.1" + } + }, + "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 + }, + "parse-url": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", + "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", + "dev": true, + "requires": { + "is-ssh": "1.3.0", + "protocols": "1.4.6" + } + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "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 + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "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 + }, + "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 + }, + "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 + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-proxy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "dev": true, + "optional": true, + "requires": { + "inflection": "1.3.8" + }, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", + "dev": true, + "optional": true + } + } + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "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 + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "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" + } + }, + "pause": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", + "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", + "dev": true + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" + } + }, + "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 + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "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, + "requires": { + "pinkie": "2.0.4" + } + }, + "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" + } + }, + "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, + "requires": { + "ansi-colors": "1.0.1", + "arr-diff": "4.0.0", + "arr-union": "3.1.0", + "extend-shallow": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "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" + } + } + } + }, + "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 + }, + "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 + }, + "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 + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "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 + }, + "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 + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "property-information": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", + "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE=", + "dev": true + }, + "protocols": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", + "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", + "dev": true + }, + "proxy-agent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", + "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "1.0.0", + "lru-cache": "2.6.5", + "pac-proxy-agent": "1.1.0", + "socks-proxy-agent": "2.1.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" + } + }, + "lru-cache": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", + "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", + "dev": true + } + } + }, + "proxyquire": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", + "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", + "dev": true, + "requires": { + "fill-keys": "1.0.2", + "module-not-found-error": "1.0.1", + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.6" + } + }, + "pullstream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", + "dev": true, + "requires": { + "over": "0.0.5", + "readable-stream": "1.0.34", + "setimmediate": "1.0.5", + "slice-stream": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "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.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "dev": true, + "requires": { + "duplexify": "3.5.3", + "inherits": "2.0.3", + "pump": "2.0.1" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", + "integrity": "sha1-hQ15+MuDHZLhA7Rkg+TjXTRkAFA=", + "dev": true + }, + "qjobs": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.1.5.tgz", + "integrity": "sha1-ZZ3p8s+NzCehSBJ28gU3cnI4LnM=", + "dev": true + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "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": "0.0.3", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", + "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", + "dev": true + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", + "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "dev": true, + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.1" + } + }, + "range-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", + "dev": true + }, + "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, + "requires": { + "bytes": "1.0.0", + "string_decoder": "0.10.31" + }, + "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 + } + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "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.4.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": { + "find-up": "2.1.0", + "read-pkg": "3.0.0" + } + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.4", + "set-immediate-shim": "1.0.1" + } + }, + "readline2": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", + "dev": true, + "requires": { + "mute-stream": "0.0.4", + "strip-ansi": "2.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true + }, + "mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", + "dev": true + }, + "strip-ansi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", + "dev": true, + "requires": { + "ansi-regex": "1.1.1" + } + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.5.0" + } + }, + "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" + } + }, + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "dev": true, + "optional": true, + "requires": { + "double-ended-queue": "2.1.0-0", + "redis-commands": "1.3.1", + "redis-parser": "2.6.0" + } + }, + "redis-commands": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz", + "integrity": "sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs=", + "dev": true, + "optional": true + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", + "dev": true, + "optional": true + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "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.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "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.0", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", + "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "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": "9.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", + "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", + "dev": true, + "requires": { + "remark-parse": "5.0.0", + "remark-stringify": "5.0.0", + "unified": "6.1.6" + } + }, + "remark-html": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", + "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", + "dev": true, + "requires": { + "hast-util-sanitize": "1.1.2", + "hast-util-to-html": "3.1.0", + "mdast-util-to-hast": "3.0.0", + "xtend": "4.0.1" + } + }, + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true, + "requires": { + "collapse-white-space": "1.0.3", + "is-alphabetical": "1.0.1", + "is-decimal": "1.0.1", + "is-whitespace-character": "1.0.1", + "is-word-character": "1.0.1", + "markdown-escapes": "1.0.1", + "parse-entities": "1.1.1", + "repeat-string": "1.6.1", + "state-toggle": "1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "1.1.0", + "unherit": "1.1.0", + "unist-util-remove-position": "1.1.1", + "vfile-location": "2.0.2", + "xtend": "4.0.1" + } + }, + "remark-slug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", + "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", + "dev": true, + "requires": { + "github-slugger": "1.2.0", + "mdast-util-to-string": "1.0.4", + "unist-util-visit": "1.3.0" + } + }, + "remark-stringify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", + "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", + "dev": true, + "requires": { + "ccount": "1.0.2", + "is-alphanumeric": "1.0.0", + "is-decimal": "1.0.1", + "is-whitespace-character": "1.0.1", + "longest-streak": "2.0.2", + "markdown-escapes": "1.0.1", + "markdown-table": "1.1.1", + "mdast-util-compact": "1.0.1", + "parse-entities": "1.1.1", + "repeat-string": "1.6.1", + "state-toggle": "1.0.0", + "stringify-entities": "1.3.1", + "unherit": "1.1.0", + "xtend": "4.0.1" + } + }, + "remark-toc": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", + "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", + "dev": true, + "requires": { + "mdast-util-toc": "2.0.1", + "remark-slug": "5.0.0" + } + }, + "remote-origin-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", + "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", + "dev": true, + "requires": { + "parse-git-config": "0.2.0" + } + }, + "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, + "requires": { + "is-buffer": "1.1.6", + "is-utf8": "0.2.1" + } + }, + "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": { + "remove-bom-buffer": "3.0.0", + "safe-buffer": "5.1.1", + "through2": "2.0.3" + } + }, + "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=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "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.2" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replacestream": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", + "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3", + "uuid": "3.2.1" + } + }, + "requestretry": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", + "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", + "dev": true, + "optional": true, + "requires": { + "extend": "3.0.1", + "lodash": "4.17.5", + "request": "2.79.0", + "when": "3.7.8" + } + }, + "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-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 + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "requirejs": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", + "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", + "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.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "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": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "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 + }, + "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": { + "value-or-function": "3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "response-time": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", + "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", + "dev": true, + "requires": { + "depd": "1.1.2", + "on-headers": "1.0.1" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + } + } + }, + "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, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "rewire": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", + "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", + "dev": true + }, + "rgb2hex": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", + "integrity": "sha1-zNVfhgrgxcTqN1BLlY5ELY0SMls=", + "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": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", + "dev": true + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", + "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", + "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": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "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 + }, + "samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "dev": true + }, + "sauce-connect-launcher": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/sauce-connect-launcher/-/sauce-connect-launcher-1.2.3.tgz", + "integrity": "sha1-0vkxrXro/avxlopEDnsgQXrKf4Y=", + "dev": true, + "requires": { + "adm-zip": "0.4.7", + "async": "2.6.0", + "https-proxy-agent": "1.0.0", + "lodash": "4.17.5", + "rimraf": "2.6.2" + }, + "dependencies": { + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + } + } + }, + "saucelabs": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.4.0.tgz", + "integrity": "sha1-uTSpr52ih0s/QKrh/N5QpEZvXzg=", + "dev": true, + "requires": { + "https-proxy-agent": "1.0.0" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "send": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", + "dev": true, + "requires": { + "debug": "2.2.0", + "depd": "1.1.2", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "statuses": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", + "dev": true + } + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "serve-favicon": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", + "dev": true, + "requires": { + "etag": "1.7.0", + "fresh": "0.3.0", + "ms": "0.7.2", + "parseurl": "1.3.2" + }, + "dependencies": { + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true + } + } + }, + "serve-index": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", + "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", + "dev": true, + "requires": { + "accepts": "1.2.13", + "batch": "0.5.3", + "debug": "2.2.0", + "escape-html": "1.0.3", + "http-errors": "1.3.1", + "mime-types": "2.1.17", + "parseurl": "1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "serve-static": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", + "dev": true, + "requires": { + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.13.2" + } + }, + "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 + }, + "set-getter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", + "dev": true, + "requires": { + "to-object-path": "0.3.0" + } + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + }, + "sha.js": { + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", + "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "0.0.1", + "sha.js": "2.4.10" + }, + "dependencies": { + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + } + } + }, + "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 + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "shelljs": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", + "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sinon": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.3.0.tgz", + "integrity": "sha512-pmf05hFgEZUS52AGJcsVjOjqAyJW2yo14cOwVYvzCyw7+inv06YXkLyW75WG6X6p951lzkoKh51L2sNbR9CDvw==", + "dev": true, + "requires": { + "@sinonjs/formatio": "2.0.0", + "diff": "3.4.0", + "lodash.get": "4.4.2", + "lolex": "2.3.2", + "nise": "1.2.5", + "supports-color": "5.2.0", + "type-detect": "4.0.8" + }, + "dependencies": { + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "dev": true + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.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 + } + } + }, + "slack-node": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", + "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", + "dev": true, + "optional": true, + "requires": { + "requestretry": "1.13.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "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 + } + } + }, + "slice-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", + "dev": true + }, + "smtp-connection": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", + "dev": true, + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } + }, + "snapdragon": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", + "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", + "dev": true, + "requires": { + "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.1", + "use": "2.0.2" + }, + "dependencies": { + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "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" + } + }, + "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" + } + }, + "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" + } + } + } + }, + "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 + }, + "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-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, + "requires": { + "atob": "2.0.3", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + } + } + }, + "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": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.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" + } + } + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "socket.io": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "engine.io": "3.1.4", + "socket.io-adapter": "1.1.1", + "socket.io-client": "2.0.4", + "socket.io-parser": "3.1.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" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "2.6.9", + "engine.io-client": "3.1.4", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "3.1.2", + "to-array": "0.1.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" + } + } + } + }, + "socket.io-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.2.tgz", + "integrity": "sha1-28IoIVH8T6675Aru3Ady66YZ9/I=", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "2.6.9", + "has-binary2": "1.0.2", + "isarray": "2.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" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "socks": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", + "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + }, + "dependencies": { + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + } + } + }, + "socks-proxy-agent": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", + "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "extend": "3.0.1", + "socks": "1.1.10" + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "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==" + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "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.7" + }, + "dependencies": { + "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-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=" + }, + "space-separated-tokens": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz", + "integrity": "sha1-lpW5355lrsGBHUw/nOUlILwvfk0=", + "dev": true, + "requires": { + "trim": "0.0.1" + } + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "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" + } + }, + "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": { + "extend-shallow": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "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" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "state-toggle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", + "integrity": "sha1-0g+aYWu08MO5i5GSLSW2QKorxCU=", + "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=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.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.6" + } + }, + "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" + } + } + } + }, + "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 + } + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + }, + "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 + }, + "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": { + "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" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4" + } + }, + "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.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.4", + "readable-stream": "2.3.4" + } + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "stream-counter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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-http": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4" + } + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true, + "requires": { + "date-format": "1.2.0", + "debug": "3.1.0", + "mkdirp": "0.5.1", + "readable-stream": "2.3.4" + } + }, + "string-replace-webpack-plugin": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", + "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", + "dev": true, + "requires": { + "async": "0.2.10", + "css-loader": "0.9.1", + "file-loader": "0.8.5", + "loader-utils": "0.2.17", + "style-loader": "0.8.3" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "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" + } + } + } + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", + "dev": true + }, + "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" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringify-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", + "integrity": "sha1-sVDsLXKsTBtfMktR+2soyc3/BYw=", + "dev": true, + "requires": { + "character-entities-html4": "1.1.1", + "character-entities-legacy": "1.1.1", + "is-alphanumerical": "1.0.1", + "is-hexadecimal": "1.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.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 + }, + "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=" + }, + "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 + }, + "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" + } + }, + "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 + }, + "style-loader": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", + "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", + "dev": true, + "optional": true, + "requires": { + "loader-utils": "0.2.17" + }, + "dependencies": { + "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, + "optional": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + } + } + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "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 + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "1.3.0" + } + }, + "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.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.1", + "lodash": "4.17.5", + "slice-ansi": "1.0.0", + "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 + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "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" + } + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "tar-stream": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", + "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", + "dev": true, + "requires": { + "bl": "0.9.5", + "end-of-stream": "1.4.1", + "readable-stream": "1.0.34", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "ternary-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "dev": true, + "requires": { + "duplexify": "3.5.3", + "fork-stream": "0.0.4", + "merge-stream": "1.0.1", + "through2": "2.0.3" + } + }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "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 + }, + "textextensions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", + "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", + "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 + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", + "dev": true + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "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": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "0.11.10" + } + }, + "timers-ext": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", + "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", + "requires": { + "es5-ext": "0.10.38", + "next-tick": "1.0.0" + } + }, + "timespan": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "dev": true, + "optional": true + }, + "tiny-lr": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.0.tgz", + "integrity": "sha512-f4X68a6KHcCx/XJcZUKAa92APjY9EHxuGOzRFmPRjf+fOp1E7fi4dGJaHMxvRBxwZrHrIvn/AwkFaDS7O1WZDQ==", + "dev": true, + "requires": { + "body": "5.1.0", + "debug": "2.6.9", + "faye-websocket": "0.10.0", + "livereload-js": "2.3.0", + "object-assign": "4.1.1", + "qs": "6.5.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" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + } + } + }, + "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-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "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": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "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-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz", + "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "regex-not": "1.0.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.6" + } + }, + "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" + } + } + } + }, + "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 + } + } + }, + "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" + } + }, + "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": { + "through2": "2.0.3" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-lines": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.0.tgz", + "integrity": "sha1-mSbQPt4Tuhj31CIiYx+wTHn/Jv4=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", + "integrity": "sha1-eu+7eAjfnWafbaLkOMrIxGradoQ=", + "dev": true + }, + "trough": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", + "integrity": "sha1-qf2LA5Swro//guBjOgo2zK1bX4Y=", + "dev": true + }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.17" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "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" + }, + "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" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "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 + }, + "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" + } + } + } + }, + "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 + }, + "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": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "uid-safe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", + "dev": true, + "requires": { + "random-bytes": "1.0.0" + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "umd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", + "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "dev": true + }, + "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 + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + }, + "unherit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", + "integrity": "sha1-a5qu379z3xdWrZ4xbdmBiFhAzX0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "xtend": "4.0.1" + } + }, + "unified": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", + "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", + "dev": true, + "requires": { + "bail": "1.0.2", + "extend": "3.0.1", + "is-plain-obj": "1.1.0", + "trough": "1.0.1", + "vfile": "2.3.0", + "x-is-function": "1.0.4", + "x-is-string": "0.1.0" + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "unist-builder": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", + "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", + "dev": true, + "requires": { + "object-assign": "4.1.1" + } + }, + "unist-util-generated": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.1.tgz", + "integrity": "sha1-mfFseJWayFTe58YVwpGSTIv03n8=", + "dev": true + }, + "unist-util-is": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", + "integrity": "sha1-DDEmKeP5YMZukx6BLT2A53AQlHs=", + "dev": true + }, + "unist-util-modify-children": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", + "integrity": "sha1-ZtfmpEnm9nIguXarPLi166w55R0=", + "dev": true, + "requires": { + "array-iterate": "1.1.1" + } + }, + "unist-util-position": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.0.tgz", + "integrity": "sha1-5uHgPu64HF4a/lU+jUrfvXwNj4I=", + "dev": true + }, + "unist-util-remove-position": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", + "integrity": "sha1-WoXBVV/BugwQG4ZwfRXlD6TIcbs=", + "dev": true, + "requires": { + "unist-util-visit": "1.3.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", + "integrity": "sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=", + "dev": true + }, + "unist-util-visit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", + "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", + "dev": true, + "requires": { + "unist-util-is": "2.1.1" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "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": { + "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 + } + } + }, + "unzip": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", + "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", + "dev": true, + "requires": { + "binary": "0.3.0", + "fstream": "0.1.31", + "match-stream": "0.0.2", + "pullstream": "0.4.1", + "readable-stream": "1.0.34", + "setimmediate": "1.0.5" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + }, + "upath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.0.tgz", + "integrity": "sha1-tHBrlGHKhHOt+JEz0jVonKF/NlY=", + "dev": true, + "requires": { + "lodash": "3.10.1", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", + "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", + "dev": true, + "requires": { + "querystringify": "1.0.0", + "requires-port": "1.0.0" + }, + "dependencies": { + "querystringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", + "dev": true + } + } + }, + "use": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", + "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "isobject": "3.0.1", + "lazy-cache": "2.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" + } + }, + "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" + } + } + } + }, + "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 + } + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "tmp": "0.0.33" + } + }, + "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" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "uws": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/uws/-/uws-0.14.5.tgz", + "integrity": "sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw=", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "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 + }, + "vargs": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/vargs/-/vargs-0.1.0.tgz", + "integrity": "sha1-a2GE2mUgzDIEzhtAfKwm2SYJ6/8=", + "dev": true + }, + "vary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", + "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", + "dev": true + }, + "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" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true, + "requires": { + "is-buffer": "1.1.6", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "1.1.1", + "vfile-message": "1.0.0" + } + }, + "vfile-location": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", + "integrity": "sha1-02dcWch3SY5JK0dW/2Xkrxp1IlU=", + "dev": true + }, + "vfile-message": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", + "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", + "dev": true, + "requires": { + "unist-util-stringify-position": "1.1.1" + } + }, + "vfile-reporter": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", + "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", + "dev": true, + "requires": { + "repeat-string": "1.6.1", + "string-width": "1.0.2", + "supports-color": "4.5.0", + "unist-util-stringify-position": "1.1.1", + "vfile-statistics": "1.1.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "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" + } + } + } + }, + "vfile-sort": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.0.tgz", + "integrity": "sha1-SVAcnou+Wt/y6bOnZx7hseIMUhA=", + "dev": true + }, + "vfile-statistics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.0.tgz", + "integrity": "sha1-AhBMYP3u0dEbH3OtZTMLdjSz2JU=", + "dev": true + }, + "vhost": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", + "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "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.1.0", + "replace-ext": "1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", + "integrity": "sha512-AUSFda1OukBwuLPBTbyuO4IRWgfXmqC4UTW0f8xrCa8Hkv9oyIU+NSqBlgfOLZRoUt7cHdo75hKQghCywpIyIw==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "1.0.0", + "glob-stream": "6.1.0", + "graceful-fs": "4.1.11", + "is-valid-glob": "1.0.0", + "lazystream": "1.0.0", + "lead": "1.0.0", + "object.assign": "4.1.0", + "pumpify": "1.4.0", + "readable-stream": "2.3.4", + "remove-bom-buffer": "3.0.0", + "remove-bom-stream": "1.2.0", + "resolve-options": "1.1.0", + "through2": "2.0.3", + "to-through": "2.0.0", + "value-or-function": "3.0.0", + "vinyl": "2.1.0", + "vinyl-sourcemap": "1.1.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.1", + "graceful-fs": "4.1.11", + "normalize-path": "2.1.1", + "now-and-later": "2.0.0", + "remove-bom-buffer": "3.0.0", + "vinyl": "2.1.0" + } + }, + "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.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "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": { + "indexof": "0.0.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 + }, + "walk": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz", + "integrity": "sha1-MbTbZnjyrgHDnqn7hyWpAx5Vins=", + "dev": true, + "requires": { + "foreachasync": "3.0.0" + } + }, + "walkdir": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", + "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=", + "dev": true + }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + }, + "dependencies": { + "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": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "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.2" + } + }, + "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.1", + "fsevents": "1.1.3", + "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.1.0" + } + }, + "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" + } + }, + "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" + } + }, + "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": "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" + } + } + } + }, + "wd": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/wd/-/wd-1.5.0.tgz", + "integrity": "sha512-e/KpzTlhtSG3Ek0AcRz4G6PhxGsc53Nro+GkI1er9p05tWQ7W9dpGZR5SqQzGUqvbaqJCThDSAGaY7LHgi6MiA==", + "dev": true, + "requires": { + "archiver": "1.3.0", + "async": "2.0.1", + "lodash": "4.16.2", + "mkdirp": "0.5.1", + "q": "1.4.1", + "request": "2.79.0", + "underscore.string": "3.3.4", + "vargs": "0.1.0" + }, + "dependencies": { + "archiver": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz", + "integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=", + "dev": true, + "requires": { + "archiver-utils": "1.3.0", + "async": "2.0.1", + "buffer-crc32": "0.2.13", + "glob": "7.1.2", + "lodash": "4.16.2", + "readable-stream": "2.3.4", + "tar-stream": "1.5.5", + "walkdir": "0.0.11", + "zip-stream": "1.2.0" + } + }, + "async": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.0.1.tgz", + "integrity": "sha1-twnMAoCpw28J9FNr6CPIOKkEniU=", + "dev": true, + "requires": { + "lodash": "4.16.2" + } + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "crc32-stream": "2.0.0", + "normalize-path": "2.1.1", + "readable-stream": "2.3.4" + } + }, + "crc": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.5.0.tgz", + "integrity": "sha1-mLi6fUiWZbo5efWbITgTdBAaGWQ=", + "dev": true + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "dev": true, + "requires": { + "crc": "3.5.0", + "readable-stream": "2.3.4" + } + }, + "lodash": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.2.tgz", + "integrity": "sha1-PmJtuCcEimmSgaihJSJjJs/A5lI=", + "dev": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "tar-stream": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", + "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", + "dev": true, + "requires": { + "bl": "1.2.1", + "end-of-stream": "1.4.1", + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + }, + "underscore.string": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", + "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "dev": true, + "requires": { + "archiver-utils": "1.3.0", + "compress-commons": "1.2.2", + "lodash": "4.16.2", + "readable-stream": "2.3.4" + } + } + } + }, + "webdriverio": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz", + "integrity": "sha1-2dTTwxNm8FPhCvZEsOqtXoc6t7U=", + "dev": true, + "requires": { + "archiver": "0.14.4", + "array.from": "0.2.0", + "co": "4.6.0", + "css-parse": "2.0.0", + "css-value": "0.0.1", + "deepmerge": "0.2.10", + "ejs": "2.5.7", + "glob": "5.0.15", + "inquirer": "0.8.5", + "is-generator": "1.0.3", + "optimist": "0.6.1", + "q": "1.3.0", + "request": "2.49.0", + "rgb2hex": "0.1.0", + "supports-color": "1.3.1", + "url": "0.10.3", + "wgxpath": "1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true + }, + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "caseless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", + "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", + "dev": true + }, + "cli-width": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", + "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "dev": true, + "requires": { + "boom": "0.4.2" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "dev": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime": "1.2.11" + } + }, + "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.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "hawk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "dev": true, + "requires": { + "boom": "0.4.2", + "cryptiles": "0.2.2", + "hoek": "0.9.1", + "sntp": "0.2.4" + } + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "inquirer": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", + "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", + "dev": true, + "requires": { + "ansi-regex": "1.1.1", + "chalk": "1.1.3", + "cli-width": "1.1.1", + "figures": "1.7.0", + "lodash": "3.10.1", + "readline2": "0.1.1", + "rx": "2.5.3", + "through": "2.3.8" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true + }, + "oauth-sign": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", + "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", + "dev": true + }, + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + }, + "request": { + "version": "2.49.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", + "integrity": "sha1-DU9jSNwzSAWbVT5Ntg/SR43mYqc=", + "dev": true, + "requires": { + "aws-sign2": "0.5.0", + "bl": "0.9.5", + "caseless": "0.8.0", + "combined-stream": "0.0.7", + "forever-agent": "0.5.2", + "form-data": "0.1.4", + "hawk": "1.1.1", + "http-signature": "0.10.1", + "json-stringify-safe": "5.0.1", + "mime-types": "1.0.2", + "node-uuid": "1.4.8", + "oauth-sign": "0.5.0", + "qs": "2.3.3", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3" + } + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "supports-color": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", + "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", + "dev": true + } + } + }, + "webpack": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", + "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "acorn-dynamic-import": "2.0.2", + "ajv": "6.1.1", + "ajv-keywords": "3.1.0", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "ajv": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.1.1.tgz", + "integrity": "sha1-l41Zf7wrfQ5aXD3esUmmgvKr+g4=", + "dev": true, + "requires": { + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", + "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "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": "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 + }, + "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.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "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=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "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" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "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.4.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" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "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" + } + }, + "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" + } + }, + "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.2", + "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.1", + "yargs-parser": "7.0.0" + } + } + } + }, + "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": { + "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" + } + } + } + }, + "webpack-dev-middleware": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "dev": true, + "requires": { + "memory-fs": "0.4.1", + "mime": "1.6.0", + "path-is-absolute": "1.0.1", + "range-parser": "1.0.3", + "time-stamp": "2.0.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "time-stamp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", + "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "dev": true + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + } + }, + "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": { + "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 + }, + "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.2" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "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.1", + "fsevents": "1.1.3", + "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.1.0" + } + }, + "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": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "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 + }, + "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" + } + }, + "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.1.11", + "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 + } + } + }, + "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" + } + }, + "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": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "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-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" + } + }, + "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" + } + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "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.6", + "readable-stream": "2.3.4" + } + }, + "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" + } + }, + "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.4.1", + "browserify-zlib": "0.1.4", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "1.1.7", + "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.4", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "0.10.31", + "timers-browserify": "2.0.6", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + } + }, + "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 + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "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 + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + }, + "tapable": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "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 + }, + "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": { + "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 + } + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "watchpack": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", + "dev": true, + "requires": { + "async": "0.9.2", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "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.3", + "enhanced-resolve": "0.9.1", + "interpret": "0.6.6", + "loader-utils": "0.2.17", + "memory-fs": "0.3.0", + "mkdirp": "0.5.1", + "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" + } + }, + "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 + }, + "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" + } + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": "0.4.10", + "websocket-extensions": "0.1.3" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "wgxpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", + "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", + "dev": true + }, + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true, + "optional": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "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 + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "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=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" + } + }, + "x-is-function": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", + "integrity": "sha1-XSlNw9Joy90GJYDgxd93o5HR+h4=", + "dev": true + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", + "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", + "dev": true + }, + "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" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "zip-stream": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", + "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", + "dev": true, + "requires": { + "compress-commons": "0.2.9", + "lodash": "3.2.0", + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lodash": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "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 + } + } + } + } +} From 45154a0406eac198e4c2d5b48619fcf05be6a65d Mon Sep 17 00:00:00 2001 From: Valentin Zhukovsky Date: Thu, 15 Feb 2018 20:07:05 +0300 Subject: [PATCH 0121/1594] AOL adapter: Fixed broken user matching in iframes (#2125) * Fixed broken user matching when creative is delivering like an iframe within a DFP iframe. * Removed unnecessary import. --- modules/aolBidAdapter.js | 137 ++++++++++++------------ test/spec/modules/aolBidAdapter_spec.js | 37 +++++-- 2 files changed, 97 insertions(+), 77 deletions(-) diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 35acb95cdee..0fb5aa1a4d3 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; -import constants from 'src/constants.json'; +import { EVENTS } from 'src/constants.json'; const AOL_BIDDERS_CODES = { AOL: 'aol', @@ -180,55 +180,6 @@ function _buildOneMobileGetUrl(bid) { return nexageApi; } -function _parseBidResponse(response, bidRequest) { - let bidData; - - try { - bidData = response.seatbid[0].bid[0]; - } catch (e) { - return; - } - - let cpm; - - if (bidData.ext && bidData.ext.encp) { - cpm = bidData.ext.encp; - } else { - cpm = bidData.price; - - if (cpm === null || isNaN(cpm)) { - utils.logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bid); - return; - } - } - - let ad = bidData.adm; - if (response.ext && response.ext.pixels) { - if (config.getConfig('aol.userSyncOn') !== constants.EVENTS.BID_RESPONSE) { - let formattedPixels = response.ext.pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, ''); - - ad += ''; - } - } - - return { - bidderCode: bidRequest.bidderCode, - requestId: bidRequest.bidId, - ad: ad, - cpm: cpm, - width: bidData.w, - height: bidData.h, - creativeId: bidData.crid, - pubapiId: response.id, - currency: response.cur, - dealId: bidData.dealid, - netRevenue: true, - ttl: bidRequest.ttl - }; -} - function _isMarketplaceBidder(bidder) { return bidder === AOL_BIDDERS_CODES.AOL || bidder === AOL_BIDDERS_CODES.ONEDISPLAY; } @@ -311,20 +262,6 @@ function formatBidRequest(endpointCode, bid) { return bidRequest; } -function interpretResponse({body}, bidRequest) { - showCpmAdjustmentWarning(); - - if (!body) { - utils.logError('Empty bid response', bidRequest.bidderCode, body); - } else { - let bid = _parseBidResponse(body, bidRequest); - - if (bid) { - return bid; - } - } -} - export const spec = { code: AOL_BIDDERS_CODES.AOL, aliases: [AOL_BIDDERS_CODES.ONEMOBILE, AOL_BIDDERS_CODES.ONEDISPLAY], @@ -340,12 +277,78 @@ export const spec = { } }); }, - interpretResponse: interpretResponse, + interpretResponse: function ({body}, bidRequest) { + showCpmAdjustmentWarning(); + + if (!body) { + utils.logError('Empty bid response', bidRequest.bidderCode, body); + } else { + let bid = this._parseBidResponse(body, bidRequest); + + if (bid) { + return bid; + } + } + }, + _formatPixels: function (pixels) { + let formattedPixels = pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, ''); + + return ''; + }, + _parseBidResponse: function (response, bidRequest) { + let bidData; + + try { + bidData = response.seatbid[0].bid[0]; + } catch (e) { + return; + } + + let cpm; + + if (bidData.ext && bidData.ext.encp) { + cpm = bidData.ext.encp; + } else { + cpm = bidData.price; + + if (cpm === null || isNaN(cpm)) { + utils.logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bid); + return; + } + } + + let ad = bidData.adm; + if (response.ext && response.ext.pixels) { + if (config.getConfig('aol.userSyncOn') !== EVENTS.BID_RESPONSE) { + ad += this._formatPixels(response.ext.pixels); + } + } + + return { + bidderCode: bidRequest.bidderCode, + requestId: bidRequest.bidId, + ad: ad, + cpm: cpm, + width: bidData.w, + height: bidData.h, + creativeId: bidData.crid, + pubapiId: response.id, + currency: response.cur, + dealId: bidData.dealid, + netRevenue: true, + ttl: bidRequest.ttl + }; + }, getUserSyncs: function(options, bidResponses) { let bidResponse = bidResponses[0]; - if (config.getConfig('aol.userSyncOn') === constants.EVENTS.BID_RESPONSE) { - if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse && bidResponse.ext && bidResponse.ext.pixels) { + if (config.getConfig('aol.userSyncOn') === EVENTS.BID_RESPONSE) { + if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse.ext && bidResponse.ext.pixels) { $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; return parsePixelItems(bidResponse.ext.pixels); diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index 109c5bf2a0f..38b36bbaf3d 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -3,6 +3,8 @@ import * as utils from 'src/utils'; import {spec} from 'modules/aolBidAdapter'; import {config} from 'src/config'; +const DEFAULT_AD_CONTENT = ''; + let getDefaultBidResponse = () => { return { id: '245730051428950632', @@ -12,7 +14,7 @@ let getDefaultBidResponse = () => { id: 1, impid: '245730051428950632', price: 0.09, - adm: '', + adm: DEFAULT_AD_CONTENT, crid: 'creative-id', h: 90, w: 728, @@ -95,6 +97,7 @@ describe('AolAdapter', () => { let bidResponse; let bidRequest; let logWarnSpy; + let formatPixelsStub; beforeEach(() => { bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; @@ -107,11 +110,13 @@ describe('AolAdapter', () => { body: getDefaultBidResponse() }; logWarnSpy = sinon.spy(utils, 'logWarn'); + formatPixelsStub = sinon.stub(spec, '_formatPixels'); }); afterEach(() => { $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; logWarnSpy.restore(); + formatPixelsStub.restore(); }); it('should return formatted bid response with required properties', () => { @@ -119,7 +124,7 @@ describe('AolAdapter', () => { expect(formattedBidResponse).to.deep.equal({ bidderCode: bidRequest.bidderCode, requestId: 'bid-id', - ad: '', + ad: DEFAULT_AD_CONTENT, cpm: 0.09, width: 728, height: 90, @@ -132,19 +137,15 @@ describe('AolAdapter', () => { }); }); - it('should return formatted bid response including pixels', () => { + it('should add pixels to ad content when pixels are present in the response', () => { bidResponse.body.ext = { - pixels: '' + pixels: 'pixels-content' }; + formatPixelsStub.returns('pixels-content'); let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - expect(formattedBidResponse.ad).to.equal( - '' + - '' - ); + expect(formattedBidResponse.ad).to.equal(DEFAULT_AD_CONTENT + 'pixels-content'); }); it('should show warning in the console', function() { @@ -532,4 +533,20 @@ describe('AolAdapter', () => { expect(userSyncs).to.deep.equal([]); }); }); + + describe('_formatPixels()', () => { + it('should return pixels wrapped for dropping them once and within nested frames ', () => { + let pixels = ''; + let formattedPixels = spec._formatPixels(pixels); + + expect(formattedPixels).to.equal( + ''); + }); + }) }); From 3b7c0ef03b06c7b4180ad0f3d028bc5f6f04362a Mon Sep 17 00:00:00 2001 From: Omer Koren Date: Thu, 15 Feb 2018 19:11:12 +0200 Subject: [PATCH 0122/1594] Fix bug in UndertoneBidAdapter (#2027) * fix bug in UndertoneBidAdapter Fix bug that caused the page domain to be sent as an array instead of a string. Also added a page url parameter to the request * fix lint error * fix lint error --- modules/undertoneBidAdapter.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index 1fe139d6fbe..ae9abee8e88 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -20,8 +20,13 @@ export const spec = { const payload = { 'x-ut-hb-params': [] }; - const host = utils.getTopWindowLocation().host; - const domain = /[-\w]+\.(?:[-\w]+\.xn--[-\w]+|[-\w]{3,}|[-\w]+\.[-\w]{2})$/i.exec(host); + const location = utils.getTopWindowLocation(); + let domain = /[-\w]+\.(?:[-\w]+\.xn--[-\w]+|[-\w]{3,}|[-\w]+\.[-\w]{2})$/i.exec(location.host); + if (domain == null || domain.length == 0) { + domain = null; + } else { + domain = domain[0]; + } const pubid = validBidRequests[0].params.publisherId; const REQ_URL = `${URL}?pid=${pubid}&domain=${domain}`; @@ -30,6 +35,7 @@ export const spec = { const bid = { bidRequestId: bidReq.bidId, hbadaptor: 'prebid', + url: location.href, domain: domain, placementId: bidReq.params.placementId, publisherId: bidReq.params.publisherId, From e44b1082c12aad6d158fc936791f5375b5ea830b Mon Sep 17 00:00:00 2001 From: aprakash-sovrn Date: Thu, 15 Feb 2018 10:14:25 -0700 Subject: [PATCH 0123/1594] Update to sovrn custom params as well as site object construction (#2149) * fix sovrn dealid * send 'iv' param if present * `page` field in `site` object sends full url --- modules/sovrnBidAdapter.js | 6 +++++- test/spec/modules/sovrnBidAdapter_spec.js | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 13f04395afa..d13331b9179 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -23,7 +23,9 @@ export const spec = { */ buildRequests: function(bidReqs) { let sovrnImps = []; + let iv; utils._each(bidReqs, function (bid) { + iv = iv || utils.getBidIdParameter('iv', bid.params); sovrnImps.push({ id: bid.bidId, banner: { w: 1, h: 1 }, @@ -36,9 +38,11 @@ export const spec = { imp: sovrnImps, site: { domain: window.location.host, - page: window.location.pathname + location.search + location.hash + page: window.location.host + window.location.pathname + location.search + location.hash } }; + if (iv) sovrnBidReq.iv = iv; + return { method: 'POST', url: `//ap.lijit.com/rtb/bid?src=${REPO_AND_VERSION}`, diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 43307f35527..5fc7cb6a62a 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -40,7 +40,7 @@ describe('sovrnBidAdapter', function() { }); describe('buildRequests', () => { - let bidRequests = [{ + const bidRequests = [{ 'bidder': 'sovrn', 'params': { 'tagid': '403370' @@ -63,6 +63,26 @@ describe('sovrnBidAdapter', function() { it('attaches source and version to endpoint URL as query params', () => { expect(request.url).to.equal(ENDPOINT) }); + + it('sends \'iv\' as query param if present', () => { + const ivBidRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': '403370', + 'iv': 'vet' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + const request = spec.buildRequests(ivBidRequests); + + expect(request.data).to.contain('"iv":"vet"') + }) }); describe('interpretResponse', () => { From 2acd3c571779936bc10e141d4c96d95078263b0f Mon Sep 17 00:00:00 2001 From: "Takaaki.Kojima" Date: Fri, 16 Feb 2018 02:22:58 +0900 Subject: [PATCH 0124/1594] Update AdGeneration native impression trackers (#2151) --- modules/adgenerationBidAdapter.js | 3 +++ modules/adgenerationBidAdapter.md | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/adgenerationBidAdapter.js b/modules/adgenerationBidAdapter.js index 8635c684af7..85b87d97a6e 100644 --- a/modules/adgenerationBidAdapter.js +++ b/modules/adgenerationBidAdapter.js @@ -155,6 +155,9 @@ function createNativeAd(body) { native.clickUrl = body.native_ad.link.url; native.clickTrackers = body.native_ad.link.clicktrackers || []; native.impressionTrackers = body.native_ad.imptrackers || []; + if (body.beaconurl && body.beaconurl != '') { + native.impressionTrackers.push(body.beaconurl) + } } return native; } diff --git a/modules/adgenerationBidAdapter.md b/modules/adgenerationBidAdapter.md index d694b376ff9..7d8281be9b2 100644 --- a/modules/adgenerationBidAdapter.md +++ b/modules/adgenerationBidAdapter.md @@ -1,16 +1,16 @@ # Overview ``` -Module Name: Adgeneration Bid Adapter +Module Name: AdGeneration Bid Adapter Module Type: Bidder Adapter Maintainer: ssp-ope@supership.jp ``` # Description -Connects to Adgeneration exchange for bids. +Connects to AdGeneration exchange for bids. -Adgeneration bid adapter supports Banner and Native. +AdGeneration bid adapter supports Banner and Native. # Test Parameters ``` From c38e9a2e2ecf6dd82181b59e4a7f5b5e8bd23ac7 Mon Sep 17 00:00:00 2001 From: harpere Date: Thu, 15 Feb 2018 12:47:18 -0500 Subject: [PATCH 0125/1594] Update PR_REVIEW.md --- PR_REVIEW.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PR_REVIEW.md b/PR_REVIEW.md index 80d11c35769..e8c4559bbf8 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -17,7 +17,7 @@ For modules and core platform updates, the initial reviewer should request an ad - If all above is good, add a `LGTM` comment and request 1 additional core member to review. - Once there is 2 `LGTM` on the PR, merge to master - Ask the submitter to add a PR for documentation if applicable. -- Add a line into the `draft release` notes for this submission. If no draft release is available, create one using [this template]( https://gist.github.com/mkendall07/c3af6f4691bed8a46738b3675cb5a479) +- Add a line into the [draft release](https://github.com/prebid/Prebid.js/releases) notes for this submission. If no draft release is available, create one using [this template]( https://gist.github.com/mkendall07/c3af6f4691bed8a46738b3675cb5a479) ### New Adapter or updates to adapter process - Follow steps above for general review process. In addition, please verify the following: From 513b89ca3e1c740bd2d35190fc1d5d57d63f6adf Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 15 Feb 2018 10:50:50 -0700 Subject: [PATCH 0126/1594] consolidated referrer logic and added pageUrl support from config in rubicon (#2087) --- modules/rubiconBidAdapter.js | 17 ++++++++++---- test/spec/modules/rubiconBidAdapter_spec.js | 26 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 9caffeb54ec..dd796752a54 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -109,13 +109,21 @@ export const spec = { return bidRequests.map(bidRequest => { bidRequest.startTime = new Date().getTime(); + let page_url = config.getConfig('pageUrl'); + if (bidRequest.params.referrer) { + page_url = bidRequest.params.referrer; + } else if (!page_url) { + page_url = utils.getTopWindowUrl(); + } + + page_url = bidRequest.params.secure ? page_url.replace(/^http:/i, 'https:') : page_url; + if (bidRequest.mediaType === 'video') { let params = bidRequest.params; let size = parseSizes(bidRequest); - let page_rf = !params.referrer ? utils.getTopWindowUrl() : params.referrer; let data = { - page_url: params.secure ? page_rf.replace(/^http:/i, 'https:') : page_rf, + page_url, resolution: _getScreenResolution(), account_id: params.accountId, integration: INTEGRATION, @@ -172,8 +180,7 @@ export const spec = { keywords, visitor, inventory, - userId, - referrer: pageUrl + userId } = bidRequest.params; // defaults @@ -210,7 +217,7 @@ export const spec = { data.push( 'rand', Math.random(), - 'rf', !pageUrl ? utils.getTopWindowUrl() : pageUrl + 'rf', page_url ); data = data.concat(_getDigiTrustQueryParams()); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 0c6c8205a86..4d18679e07c 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -5,6 +5,7 @@ import { parse as parseQuery } from 'querystring'; import { newBidder } from 'src/adapters/bidderFactory'; import { userSync } from 'src/userSync'; import { config } from 'src/config'; +import * as utils from 'src/utils'; var CONSTANTS = require('src/constants.json'); @@ -159,6 +160,31 @@ describe('the rubicon adapter', () => { }); }); + it('page_url should use params.referrer, config.getConfig("pageUrl"), utils.getTopWindowUrl() in that order', () => { + sandbox.stub(utils, 'getTopWindowUrl', () => 'http://www.prebid.org'); + + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(parseQuery(request.data).rf).to.equal('localhost'); + + delete bidderRequest.bids[0].params.referrer; + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(parseQuery(request.data).rf).to.equal('http://www.prebid.org'); + + let origGetConfig = config.getConfig; + sandbox.stub(config, 'getConfig', function(key) { + if (key === 'pageUrl') { + return 'http://www.rubiconproject.com'; + } + return origGetConfig.apply(config, arguments); + }); + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(parseQuery(request.data).rf).to.equal('http://www.rubiconproject.com'); + + bidderRequest.bids[0].params.secure = true; + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(parseQuery(request.data).rf).to.equal('https://www.rubiconproject.com'); + }); + it('should use rubicon sizes if present (including non-mappable sizes)', () => { var sizesBidderRequest = clone(bidderRequest); sizesBidderRequest.bids[0].params.sizes = [55, 57, 59, 801]; From 178955eeaa9e23813526f67eeccb841d01a48d38 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Thu, 15 Feb 2018 10:48:17 -0800 Subject: [PATCH 0127/1594] Fix stub syntax to work with test stack update (#2153) --- test/spec/modules/rubiconBidAdapter_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 4d18679e07c..6e27bdb87d8 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -161,7 +161,7 @@ describe('the rubicon adapter', () => { }); it('page_url should use params.referrer, config.getConfig("pageUrl"), utils.getTopWindowUrl() in that order', () => { - sandbox.stub(utils, 'getTopWindowUrl', () => 'http://www.prebid.org'); + sandbox.stub(utils, 'getTopWindowUrl').callsFake(() => 'http://www.prebid.org'); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(parseQuery(request.data).rf).to.equal('localhost'); @@ -171,7 +171,7 @@ describe('the rubicon adapter', () => { expect(parseQuery(request.data).rf).to.equal('http://www.prebid.org'); let origGetConfig = config.getConfig; - sandbox.stub(config, 'getConfig', function(key) { + sandbox.stub(config, 'getConfig').callsFake(function(key) { if (key === 'pageUrl') { return 'http://www.rubiconproject.com'; } From 1b2475e22f9b198b8e3aa8e5b851567ef470e960 Mon Sep 17 00:00:00 2001 From: Matt Kendall Date: Fri, 16 Feb 2018 16:20:01 -0500 Subject: [PATCH 0128/1594] Add debug info to DOM for prebid creatives (#2158) --- src/prebid.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/prebid.js b/src/prebid.js index 0225b32191b..d6b15def53c 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -223,6 +223,9 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { const { height, width, ad, mediaType, adUrl, renderer } = bid; + const creativeComment = document.createComment(`Creative ${bid.creativeId} served by ${bid.bidder} Prebid.js Header Bidding`); + utils.insertElement(creativeComment, doc, 'body'); + if (renderer && renderer.url) { renderer.render(bid); } else if ((doc === document && !utils.inIframe()) || mediaType === 'video') { From 2d1d0e0740c633e1f5974b595286d287f5b7ca74 Mon Sep 17 00:00:00 2001 From: Shimko Date: Sat, 17 Feb 2018 02:57:14 +0300 Subject: [PATCH 0129/1594] Adding Orbitsoft module for Prebid 1.0 (#2108) --- modules/orbitsoftBidAdapter.js | 147 +++++++++++ modules/orbitsoftBidAdapter.md | 60 +++++ test/spec/modules/orbitsoftBidAdapter_spec.js | 248 ++++++++++++++++++ 3 files changed, 455 insertions(+) create mode 100644 modules/orbitsoftBidAdapter.js create mode 100644 modules/orbitsoftBidAdapter.md create mode 100644 test/spec/modules/orbitsoftBidAdapter_spec.js diff --git a/modules/orbitsoftBidAdapter.js b/modules/orbitsoftBidAdapter.js new file mode 100644 index 00000000000..0ad3c150767 --- /dev/null +++ b/modules/orbitsoftBidAdapter.js @@ -0,0 +1,147 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import {config} from 'src/config'; + +const BIDDER_CODE = 'orbitsoft'; +let styleParamsMap = { + 'title.family': 'f1', // headerFont + 'title.size': 'fs1', // headerFontSize + 'title.weight': 'w1', // headerWeight + 'title.style': 's1', // headerStyle + 'title.color': 'c3', // headerColor + 'description.family': 'f2', // descriptionFont + 'description.size': 'fs2', // descriptionFontSize + 'description.weight': 'w2', // descriptionWeight + 'description.style': 's2', // descriptionStyle + 'description.color': 'c4', // descriptionColor + 'url.family': 'f3', // urlFont + 'url.size': 'fs3', // urlFontSize + 'url.weight': 'w3', // urlWeight + 'url.style': 's3', // urlStyle + 'url.color': 'c5', // urlColor + 'colors.background': 'c2', // borderColor + 'colors.border': 'c1', // borderColor + 'colors.link': 'c6', // lnkColor +}; +export const spec = { + code: BIDDER_CODE, + aliases: ['oas', '152media'], // short code and customer aliases + isBidRequestValid: function (bid) { + switch (true) { + case !('params' in bid): + utils.logError(bid.bidder + ': No required params'); + return false; + case !(bid.params.placementId): + utils.logError(bid.bidder + ': No required param placementId'); + return false; + case !(bid.params.requestUrl): + utils.logError(bid.bidder + ': No required param requestUrl'); + return false; + } + return true; + }, + buildRequests: function (validBidRequests) { + let bidRequest; + let serverRequests = []; + for (let i = 0; i < validBidRequests.length; i++) { + bidRequest = validBidRequests[i]; + let bidRequestParams = bidRequest.params; + let callbackId = utils.getUniqueIdentifierStr(); + let placementId = utils.getBidIdParameter('placementId', bidRequestParams); + let requestUrl = utils.getBidIdParameter('requestUrl', bidRequestParams); + let referrer = utils.getBidIdParameter('ref', bidRequestParams); + let location = utils.getBidIdParameter('loc', bidRequestParams); + // Append location & referrer + if (location === '') { + location = utils.getTopWindowUrl(); + } + if (referrer === '') { + referrer = utils.getTopWindowReferrer(); + } + + // Styles params + let stylesParams = utils.getBidIdParameter('style', bidRequestParams); + let stylesParamsArray = {}; + for (let currentValue in stylesParams) { + if (stylesParams.hasOwnProperty(currentValue)) { + let currentStyle = stylesParams[currentValue]; + for (let field in currentStyle) { + if (currentStyle.hasOwnProperty(field)) { + let styleField = styleParamsMap[currentValue + '.' + field]; + if (typeof styleField !== 'undefined') { + stylesParamsArray[styleField] = currentStyle[field]; + } + } + } + } + } + // Custom params + let customParams = utils.getBidIdParameter('customParams', bidRequestParams); + let customParamsArray = {}; + for (let customField in customParams) { + if (customParams.hasOwnProperty(customField)) { + customParamsArray['c.' + customField] = customParams[customField]; + } + } + + // Sizes params (not supports by server, for future features) + let sizesParams = bidRequest.sizes; + let parsedSizes = utils.parseSizesInput(sizesParams); + + serverRequests.push({ + method: 'GET', + url: requestUrl, + data: Object.assign({ + 'scid': placementId, + 'callback_uid': callbackId, + 'loc': location, + 'ref': referrer, + 'size': parsedSizes + }, stylesParamsArray, customParamsArray), + options: {withCredentials: false}, + bidRequest: bidRequest + }); + } + return serverRequests; + }, + interpretResponse: function (serverResponse, request) { + let bidResponses = []; + if (!serverResponse || serverResponse.error) { + utils.logError(BIDDER_CODE + ': Server response error'); + return bidResponses; + } + + const serverBody = serverResponse.body; + if (!serverBody) { + utils.logError(BIDDER_CODE + ': Empty bid response'); + return bidResponses; + } + + const CPM = serverBody.cpm; + const WIDTH = serverBody.width; + const HEIGHT = serverBody.height; + const CREATIVE = serverBody.content_url; + const CALLBACK_UID = serverBody.callback_uid; + const TIME_TO_LIVE = config.getConfig('_bidderTimeout'); + const REFERER = utils.getTopWindowUrl(); + let bidRequest = request.bidRequest; + if (CPM > 0 && WIDTH > 0 && HEIGHT > 0) { + let bidResponse = { + requestId: bidRequest.bidId, + cpm: CPM, + width: WIDTH, + height: HEIGHT, + creativeId: CALLBACK_UID, + ttl: TIME_TO_LIVE, + referrer: REFERER, + currency: 'USD', + netRevenue: true, + adUrl: CREATIVE + }; + bidResponses.push(bidResponse); + } + + return bidResponses; + } +}; +registerBidder(spec); diff --git a/modules/orbitsoftBidAdapter.md b/modules/orbitsoftBidAdapter.md new file mode 100644 index 00000000000..a18f075b6b1 --- /dev/null +++ b/modules/orbitsoftBidAdapter.md @@ -0,0 +1,60 @@ +# Overview + +``` +Module Name: Orbitsoft Bidder Adapter +Module Type: Bidder Adapter +Maintainer: support@orbitsoft.com +``` + +# Description + +Module that connects to Orbitsoft's demand sources. The “sizes” option is not supported, and the size of the ad depends on the placement settings. You can use an optional “style” parameter to set the appearance only for text ad. Specify the “requestUrl” param to your Orbitsoft ad server header bidding endpoint. + +# Test Parameters +``` + var adUnits = [ + { + code: 'orbitsoft-div', + bids: [ + { + bidder: "orbitsoft", + params: { + placementId: '132', + requestUrl: 'https://orbitsoft.com/php/ads/hb.php', + style: { + title: { + family: 'Tahoma', + size: 'medium', + weight: 'normal', + style: 'normal', + color: '0053F9' + }, + description: { + family: 'Tahoma', + size: 'medium', + weight: 'normal', + style: 'normal', + color: '0053F9' + }, + url: { + family: 'Tahoma', + size: 'medium', + weight: 'normal', + style: 'normal', + color: '0053F9' + }, + colors: { + background: 'ffffff', + border: 'E0E0E0', + link: '5B99FE' + } + }, + customParams: { + macro_name: "macro_value" + } + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/orbitsoftBidAdapter_spec.js b/test/spec/modules/orbitsoftBidAdapter_spec.js new file mode 100644 index 00000000000..50145a1e72e --- /dev/null +++ b/test/spec/modules/orbitsoftBidAdapter_spec.js @@ -0,0 +1,248 @@ +import {expect} from 'chai'; +import {spec} from 'modules/orbitsoftBidAdapter'; + +const ENDPOINT_URL = 'https://orbitsoft.com/php/ads/hb.phps'; +describe('Orbitsoft adapter', () => { + describe('implementation', () => { + describe('for requests', () => { + it('should accept valid bid', () => { + let validBid = { + bidder: 'orbitsoft', + params: { + placementId: '123', + requestUrl: ENDPOINT_URL + } + }, + isValid = spec.isBidRequestValid(validBid); + + expect(isValid).to.equal(true); + }); + + it('should reject invalid bid', () => { + let invalidBid = { + bidder: 'orbitsoft' + }, + isValid = spec.isBidRequestValid(invalidBid); + + expect(isValid).to.equal(false); + }); + }); + describe('for requests', () => { + it('should accept valid bid with styles', () => { + let validBid = { + bidder: 'orbitsoft', + params: { + placementId: '123', + requestUrl: ENDPOINT_URL, + style: { + title: { + family: 'Tahoma', + size: 'medium', + weight: 'normal', + style: 'normal', + color: '0053F9' + }, + description: { + family: 'Tahoma', + size: 'medium', + weight: 'normal', + style: 'normal', + color: '0053F9' + }, + url: { + family: 'Tahoma', + size: 'medium', + weight: 'normal', + style: 'normal', + color: '0053F9' + }, + colors: { + background: 'ffffff', + border: 'E0E0E0', + link: '5B99FE' + } + } + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + + let buildRequest = spec.buildRequests([validBid])[0]; + let requestUrl = buildRequest.url; + let requestUrlParams = buildRequest.data; + expect(requestUrl).to.equal(ENDPOINT_URL); + expect(requestUrlParams).have.property('f1', 'Tahoma'); + expect(requestUrlParams).have.property('fs1', 'medium'); + expect(requestUrlParams).have.property('w1', 'normal'); + expect(requestUrlParams).have.property('s1', 'normal'); + expect(requestUrlParams).have.property('c3', '0053F9'); + expect(requestUrlParams).have.property('f2', 'Tahoma'); + expect(requestUrlParams).have.property('fs2', 'medium'); + expect(requestUrlParams).have.property('w2', 'normal'); + expect(requestUrlParams).have.property('s2', 'normal'); + expect(requestUrlParams).have.property('c4', '0053F9'); + expect(requestUrlParams).have.property('f3', 'Tahoma'); + expect(requestUrlParams).have.property('fs3', 'medium'); + expect(requestUrlParams).have.property('w3', 'normal'); + expect(requestUrlParams).have.property('s3', 'normal'); + expect(requestUrlParams).have.property('c5', '0053F9'); + expect(requestUrlParams).have.property('c2', 'ffffff'); + expect(requestUrlParams).have.property('c1', 'E0E0E0'); + expect(requestUrlParams).have.property('c6', '5B99FE'); + }); + + it('should accept valid bid with custom params', () => { + let validBid = { + bidder: 'orbitsoft', + params: { + placementId: '123', + requestUrl: ENDPOINT_URL, + customParams: { + cacheBuster: 'bf4d7c1', + clickUrl: 'http://testclickurl.com' + } + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + + let buildRequest = spec.buildRequests([validBid])[0]; + let requestUrlCustomParams = buildRequest.data; + expect(requestUrlCustomParams).have.property('c.cacheBuster', 'bf4d7c1'); + expect(requestUrlCustomParams).have.property('c.clickUrl', 'http://testclickurl.com'); + }); + + it('should reject invalid bid without requestUrl', () => { + let invalidBid = { + bidder: 'orbitsoft', + params: { + placementId: '123' + } + }, + isValid = spec.isBidRequestValid(invalidBid); + + expect(isValid).to.equal(false); + }); + + it('should reject invalid bid without placementId', () => { + let invalidBid = { + bidder: 'orbitsoft', + params: { + requestUrl: ENDPOINT_URL + } + }, + isValid = spec.isBidRequestValid(invalidBid); + + expect(isValid).to.equal(false); + }); + }); + describe('bid responses', () => { + it('should return complete bid response', () => { + let serverResponse = { + body: { + callback_uid: '265b29b70cc106', + cpm: 0.5, + width: 240, + height: 240, + content_url: 'https://orbitsoft.com/php/ads/hb.html', + } + }; + + let bidRequests = [ + { + bidder: 'orbitsoft', + params: { + placementId: '123', + requestUrl: ENDPOINT_URL + } + } + ]; + let bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(0.5); + expect(bids[0].width).to.equal(240); + expect(bids[0].height).to.equal(240); + expect(bids[0].currency).to.equal('USD'); + expect(bids[0].netRevenue).to.equal(true); + expect(bids[0].adUrl).to.have.length.above(1); + expect(bids[0].adUrl).to.have.string('https://orbitsoft.com/php/ads/hb.html'); + }); + + it('should return empty bid response', () => { + let bidRequests = [ + { + bidder: 'orbitsoft', + params: { + placementId: '123', + requestUrl: ENDPOINT_URL + } + } + ]; + let serverResponse = { + body: { + callback_uid: '265b29b70cc106', + cpm: 0 + } + }, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response on incorrect size', () => { + let bidRequests = [ + { + bidder: 'orbitsoft', + params: { + placementId: '123', + requestUrl: ENDPOINT_URL + } + } + ]; + let serverResponse = { + body: { + callback_uid: '265b29b70cc106', + cpm: 1.5, + width: 0, + height: 0 + } + }, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response with error', () => { + let bidRequests = [ + { + bidder: 'orbitsoft', + params: { + placementId: '123', + requestUrl: ENDPOINT_URL + } + } + ]; + let serverResponse = {error: 'error'}, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response on empty body', () => { + let bidRequests = [ + { + bidder: 'orbitsoft', + params: { + placementId: '123', + requestUrl: ENDPOINT_URL + } + } + ]; + let serverResponse = {}, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + }); + }); +}); From c6f448bcadad3c71540a22d63cdb1b6e5bb60306 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Tue, 20 Feb 2018 09:44:00 -0800 Subject: [PATCH 0130/1594] Add Publisher Common ID module (#2150) * Add Publisher Common ID module * Specify base 10 for parseInt in PubCommonID --- modules/conversantBidAdapter.js | 15 +- modules/pubCommonId.js | 100 ++++++++++ .../spec/modules/conversantBidAdapter_spec.js | 15 ++ test/spec/modules/pubCommonId_spec.js | 188 ++++++++++++++++++ 4 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 modules/pubCommonId.js create mode 100644 test/spec/modules/pubCommonId_spec.js diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index cae64983089..075a8abd5bb 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -5,7 +5,7 @@ import { BANNER, VIDEO } from 'src/mediaTypes'; const BIDDER_CODE = 'conversant'; const URL = '//media.msg.dotomi.com/s2s/header/24'; const SYNC_URL = '//media.msg.dotomi.com/w/user.sync'; -const VERSION = '2.2.1'; +const VERSION = '2.2.2'; export const spec = { code: BIDDER_CODE, @@ -54,6 +54,7 @@ export const spec = { const isPageSecure = (loc.protocol === 'https:') ? 1 : 0; let siteId = ''; let requestId = ''; + let pubcid = null; const conversantImps = validBidRequests.map(function(bid) { const bidfloor = utils.getBidIdParameter('bidfloor', bid.params); @@ -95,6 +96,10 @@ export const spec = { imp.banner = banner; } + if (bid.crumbs && bid.crumbs.pubcid) { + pubcid = bid.crumbs.pubcid; + } + return imp; }); @@ -110,6 +115,14 @@ export const spec = { at: 1 }; + if (pubcid) { + payload.user = { + ext: { + fpc: pubcid + } + }; + } + return { method: 'POST', url: URL, diff --git a/modules/pubCommonId.js b/modules/pubCommonId.js new file mode 100644 index 00000000000..58b91ae956c --- /dev/null +++ b/modules/pubCommonId.js @@ -0,0 +1,100 @@ +/** + * This modules adds Publisher Common ID support to prebid.js. It's a simple numeric id + * 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 * as utils from 'src/utils' +import { config } from 'src/config'; + +const COOKIE_NAME = '_pubcid'; +const DEFAULT_EXPIRES = 2628000; // 5-year worth of minutes +const PUB_COMMON = 'PublisherCommonId'; + +var pubcidEnabled = true; +var interval = DEFAULT_EXPIRES; + +export function isPubcidEnabled() { return pubcidEnabled; } +export function getExpInterval() { return interval; } + +/** + * Decorate ad units with pubcid. This hook function is called before the + * real pbjs.requestBids is invoked, and can modify its parameter. The cookie is + * not updated until this function is called. + * @param {Object} config This is the same parameter as pbjs.requestBids, and config.adUnits will be updated. + * @param {function} next The next function in the chain + */ + +export function requestBidHook(config, next) { + let adUnits = config.adUnits || $$PREBID_GLOBAL$$.adUnits; + let pubcid = null; + + // Pass control to the next function if not enabled + if (!pubcidEnabled) { + return next.apply(this, arguments); + } + + if (typeof window[PUB_COMMON] === 'object') { + // If the page includes its own pubcid object, then use that instead. + pubcid = window[PUB_COMMON].getId(); + utils.logMessage(PUB_COMMON + ': pubcid = ' + pubcid); + } else { + // Otherwise get the existing cookie or create a new id + pubcid = getCookie(COOKIE_NAME) || utils.generateUUID(); + + // Update the cookie with the latest expiration date + setCookie(COOKIE_NAME, pubcid, interval); + 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) => { + unit.bids.forEach((bid) => { + Object.assign(bid, {crumbs: {pubcid}}); + }); + }); + } + return next.apply(this, arguments); +} + +// Helper to set a cookie +export function setCookie(name, value, expires) { + let expTime = new Date(); + expTime.setTime(expTime.getTime() + expires * 1000 * 60); + window.document.cookie = name + '=' + encodeURIComponent(value) + ';path=/;expires=' + + expTime.toGMTString(); +} + +// Helper to read a cookie +export function getCookie(name) { + let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); + return m ? decodeURIComponent(m[2]) : null; +} + +/** + * Configuration function + * @param {boolean} enable Enable or disable pubcid. By default the module is enabled. + * @param {number} expInterval Expiration interval of the cookie in minutes. + */ + +export function setConfig({ enable = true, expInterval = DEFAULT_EXPIRES } = {}) { + pubcidEnabled = enable; + interval = parseInt(expInterval, 10); + if (isNaN(interval)) { + interval = DEFAULT_EXPIRES; + } +} + +/** + * Initialize module by 1) subscribe to configuration changes and 2) register hook + */ +export function initPubcid() { + config.getConfig('pubcid', config => setConfig(config.pubcid)); + + if (utils.cookiesAreEnabled()) { + $$PREBID_GLOBAL$$.requestBids.addHook(requestBidHook); + } +} + +initPubcid(); diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 9f7cb3ff17d..a8e1b41d966 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -227,6 +227,8 @@ describe('Conversant adapter tests', function() { expect(payload.device).to.have.property('h', screen.height); expect(payload.device).to.have.property('dnt').that.is.oneOf([0, 1]); expect(payload.device).to.have.property('ua', navigator.userAgent); + + expect(payload).to.not.have.property('user'); // there should be no user by default }); it('Verify interpretResponse', function() { @@ -279,4 +281,17 @@ describe('Conversant adapter tests', function() { response = spec.interpretResponse({id: '123', seatbid: []}, {}); expect(response).to.be.an('array').with.lengthOf(0); }); + + it('Verify publisher commond id support', function() { + // clone bidRequests + let requests = utils.deepClone(bidRequests) + + // add pubcid to every entry + requests.forEach((unit) => { + Object.assign(unit, {crumbs: {pubcid: 12345}}); + }); + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.have.deep.property('user.ext.fpc', 12345); + }); }) diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js new file mode 100644 index 00000000000..7f7c71543f1 --- /dev/null +++ b/test/spec/modules/pubCommonId_spec.js @@ -0,0 +1,188 @@ +import { + requestBidHook, + getCookie, + setCookie, + setConfig, + isPubcidEnabled, + getExpInterval, + initPubcid } from 'modules/pubCommonId'; +import { getAdUnits } from 'test/fixtures/fixtures'; +import * as auctionModule from 'src/auction'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +var assert = require('chai').assert; +var expect = require('chai').expect; + +const COOKIE_NAME = '_pubcid'; +const TIMEOUT = 2000; + +describe('Publisher Common ID', function () { + describe('Decorate adUnits', function () { + it('Check same cookie', function () { + let adUnits1 = getAdUnits(); + let adUnits2 = getAdUnits(); + let innerAdUnits1; + let innerAdUnits2; + let pubcid = getCookie(COOKIE_NAME); + + expect(pubcid).to.be.null; // there should be no cookie initially + + requestBidHook({adUnits: adUnits1}, (config) => { innerAdUnits1 = config.adUnits }); + pubcid = getCookie(COOKIE_NAME); // cookies is created after requestbidHook + + innerAdUnits1.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid.crumbs.pubcid).to.equal(pubcid); + }); + }); + requestBidHook({adUnits: adUnits2}, (config) => { innerAdUnits2 = config.adUnits }); + assert.deepEqual(innerAdUnits1, innerAdUnits2); + }); + + it('Check different cookies', function () { + let adUnits1 = getAdUnits(); + let adUnits2 = getAdUnits(); + let innerAdUnits1; + let innerAdUnits2; + let pubcid1; + let pubcid2; + + requestBidHook({adUnits: adUnits1}, (config) => { innerAdUnits1 = config.adUnits }); + pubcid1 = getCookie(COOKIE_NAME); // get first cookie + setCookie(COOKIE_NAME, '', -1); // erase cookie + + innerAdUnits1.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid.crumbs.pubcid).to.equal(pubcid1); + }); + }); + + requestBidHook({adUnits: adUnits2}, (config) => { innerAdUnits2 = config.adUnits }); + pubcid2 = getCookie(COOKIE_NAME); // get second cookie + + innerAdUnits2.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid.crumbs.pubcid).to.equal(pubcid2); + }); + }); + + expect(pubcid1).to.not.equal(pubcid2); + }); + + it('Check new cookie', function () { + let adUnits = getAdUnits(); + let innerAdUnits; + let pubcid = utils.generateUUID(); + + setCookie(COOKIE_NAME, pubcid, 600); + requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid.crumbs.pubcid).to.equal(pubcid); + }); + }); + }); + }); + + describe('Configuration', function () { + it('empty config', function () { + // this should work as usual + setConfig({}); + let adUnits = getAdUnits(); + let innerAdUnits; + requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + let pubcid = getCookie(COOKIE_NAME); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid.crumbs.pubcid).to.equal(pubcid); + }); + }); + }); + + it('disable', function () { + setConfig({enable: false}); + setCookie(COOKIE_NAME, '', -1); // erase cookie + let adUnits = getAdUnits(); + let unmodified = getAdUnits(); + let innerAdUnits; + expect(isPubcidEnabled()).to.be.false; + requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + expect(getCookie(COOKIE_NAME)).to.be.null; + assert.deepEqual(innerAdUnits, unmodified); + setConfig({enable: true}); // reset + requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.property('crumbs.pubcid'); + }); + }); + }); + + it('change expiration time', function () { + setConfig({expInterval: 100}); + setCookie(COOKIE_NAME, '', -1); // erase cookie + expect(getExpInterval()).to.equal(100); + let adUnits = getAdUnits(); + let innerAdUnits; + requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + innerAdUnits.every((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.property('crumbs.pubcid'); + }); + }) + }); + }); + + describe('Invoking requestBid', function () { + let createAuctionStub; + let adUnits; + let adUnitCodes; + let capturedReqs; + let sampleSpec = { + code: 'sampleBidder', + isBidRequestValid: () => {}, + buildRequest: (reqs) => {}, + interpretResponse: () => {}, + getUserSyncs: () => {} + }; + + beforeEach(() => { + adUnits = [{ + code: 'adUnit-code', + mediaTypes: { + banner: {}, + native: {}, + }, + sizes: [[300, 200], [300, 600]], + bids: [ + {bidder: 'sampleBidder', params: {placementId: 'banner-only-bidder'}} + ] + }]; + adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: TIMEOUT}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + initPubcid(); + registerBidder(sampleSpec); + }); + + afterEach(() => { + auctionModule.newAuction.restore(); + }); + + it('test hook', function() { + $$PREBID_GLOBAL$$.requestBids({adUnits}); + adUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.property('crumbs.pubcid'); + }); + }); + }); + }); +}); From de9c345b65ad66f66ae9d05b9662ce03821c5e96 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 20 Feb 2018 11:18:08 -0700 Subject: [PATCH 0131/1594] added currency.defaultRates to use when currency file fails to load (#2134) --- modules/currency.js | 42 +++++++++++++++++++++++------- test/spec/modules/currency_spec.js | 25 ++++++++++++++++++ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/modules/currency.js b/modules/currency.js index f5da02d5d72..aeeabc3817c 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -16,6 +16,7 @@ var adServerCurrency = 'USD'; export var currencySupportEnabled = false; export var currencyRates = {}; var bidderCurrencyDefault = {}; +var defaultRates; /** * Configuration function for currency @@ -45,6 +46,9 @@ var bidderCurrencyDefault = {}; * 'GBP': { 'CNY': 8.8282, 'JPY': 141.7, 'USD': 1.2824 }, * 'USD': { 'CNY': 6.8842, 'GBP': 0.7798, 'JPY': 110.49 } * } + * @param {object} [config.defaultRates] + * This optional currency rates definition follows the same format as config.rates, however it is only utilized if + * there is an error loading the config.conversionRateFile. */ export function setConfig(config) { let url = DEFAULT_CURRENCY_RATE_URL; @@ -54,6 +58,10 @@ export function setConfig(config) { currencyRatesLoaded = true; } + if (typeof config.defaultRates === 'object') { + defaultRates = config.defaultRates; + } + if (typeof config.adServerCurrency === 'string') { utils.logInfo('enabling currency support', arguments); @@ -74,6 +82,17 @@ export function setConfig(config) { } config.getConfig('currency', config => setConfig(config.currency)); +function errorSettingsRates(msg) { + if (defaultRates) { + currencyRates.conversions = defaultRates; + currencyRatesLoaded = true; + utils.logWarn(msg); + utils.logWarn('Currency failed loading rates, falling back to currency.defaultRates'); + } else { + utils.logError(msg); + } +} + function initCurrency(url) { conversionCache = {}; currencySupportEnabled = true; @@ -83,16 +102,21 @@ function initCurrency(url) { hooks['addBidResponse'].addHook(addBidResponseHook, 100); if (!currencyRates.conversions) { - ajax(url, function (response) { - try { - currencyRates = JSON.parse(response); - utils.logInfo('currencyRates set to ' + JSON.stringify(currencyRates)); - currencyRatesLoaded = true; - processBidResponseQueue(); - } catch (e) { - utils.logError('failed to parse currencyRates response: ' + response); + ajax(url, + { + success: function (response) { + try { + currencyRates = JSON.parse(response); + utils.logInfo('currencyRates set to ' + JSON.stringify(currencyRates)); + currencyRatesLoaded = true; + processBidResponseQueue(); + } catch (e) { + errorSettingsRates('Failed to parse currencyRates response: ' + response); + } + }, + error: errorSettingsRates } - }); + ); } } diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index 37bb01b7c16..a4ef643fece 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -104,6 +104,31 @@ describe('currency', function () { expect(innerBid.cpm).to.equal('1.0000'); }); + + it('uses default rates when currency file fails to load', () => { + setConfig({}); + + setConfig({ + adServerCurrency: 'USD', + defaultRates: { + USD: { + JPY: 100 + } + } + }); + + // default response is 404 + fakeCurrencyFileServer.respond(); + + var bid = { cpm: 100, currency: 'JPY', bidder: 'rubicon' }; + var innerBid; + + addBidResponseHook('elementId', bid, function(adCodeId, bid) { + innerBid = bid; + }); + + expect(innerBid.cpm).to.equal('1.0000'); + }); }); describe('currency.addBidResponseDecorator bidResponseQueue', () => { From 5c025a183a9e8d1285192050f3179e58d86c8ac5 Mon Sep 17 00:00:00 2001 From: rxRTB <34483140+prebidRxRTB@users.noreply.github.com> Date: Tue, 20 Feb 2018 21:19:09 +0300 Subject: [PATCH 0132/1594] Fix bidfloor param check in rxrtb adapter (#2157) --- modules/rxrtbBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rxrtbBidAdapter.js b/modules/rxrtbBidAdapter.js index 55b6991667a..c82f1f9b1db 100644 --- a/modules/rxrtbBidAdapter.js +++ b/modules/rxrtbBidAdapter.js @@ -100,7 +100,7 @@ function makeImp(req) { 'banner': makeBanner(req) }; - if (req.params.bidfloor && utils.isInteger(req.params.bidfloor)) { + if (req.params.bidfloor && isFinite(req.params.bidfloor)) { imp.bidfloor = req.params.bidfloor } From a455757f7ee8572baf285c234595e06a94e75a76 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 20 Feb 2018 11:38:05 -0800 Subject: [PATCH 0133/1594] Add support for OpenRTB protocol and endpoint (#2102) * Update to use OpenRTB protocol and endpoint * Refactor request and response handlers * Handle adding bids in core response handler * Update openrtb endpoint response interpreter * Refactor variable names, update comments, extract cookie sync to core handler * Update openrtb bid response fields * Match bid ids * Update based on review feedback * Move legacy-specific video code to legcy spec * Add video support to OpenRTB spec * Add digiTrust, app, device to request * Default to banner if mediaTypes not defined * Allow single or double banner.sizes array --- modules/prebidServerBidAdapter.js | 444 +++++++++++++----- .../modules/prebidServerBidAdapter_spec.js | 154 ++++++ 2 files changed, 473 insertions(+), 125 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 748d91f9444..bc9b65cbd5b 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -207,6 +207,27 @@ const paramTypes = { }, }; +/* + * Modify an adunit's bidder parameters to match the expected parameter types + */ +function convertTypes(adUnits) { + adUnits.forEach(adUnit => { + adUnit.bids.forEach(bid => { + const types = paramTypes[bid.bidder] || []; + Object.keys(types).forEach(key => { + if (bid.params[key]) { + bid.params[key] = types[key](bid.params[key]); + + // don't send invalid values + if (isNaN(bid.params[key])) { + delete bid.params.key; + } + } + }); + }); + }); +} + function _getDigiTrustQueryParams() { function getDigiTrustId() { let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); @@ -224,46 +245,26 @@ function _getDigiTrustQueryParams() { }; } -/** - * Bidder adapter for Prebid Server +/* + * Protocol spec for legacy endpoint + * e.g., https:///v1/auction */ -export function PrebidServer() { - let baseAdapter = new Adapter('prebidServer'); +const LEGACY_PROTOCOL = { - function convertTypes(adUnits) { + buildRequest(s2sBidRequest, adUnits) { + // pbs expects an ad_unit.video attribute if the imp is video adUnits.forEach(adUnit => { - adUnit.bids.forEach(bid => { - const types = paramTypes[bid.bidder] || []; - Object.keys(types).forEach(key => { - if (bid.params[key]) { - bid.params[key] = types[key](bid.params[key]); - - // don't send invalid values - if (isNaN(bid.params[key])) { - delete bid.params.key; - } - } - }); - }); - }); - } - - /* Prebid executes this function when the page asks to send out bid requests */ - baseAdapter.callBids = function(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { - const isDebug = !!getConfig('debug'); - const adUnits = utils.deepClone(s2sBidRequest.ad_units); - adUnits.forEach(adUnit => { - let videoMediaType = utils.deepAccess(adUnit, 'mediaTypes.video'); + const videoMediaType = utils.deepAccess(adUnit, 'mediaTypes.video'); if (videoMediaType) { - // pbs expects a ad_unit.video attribute if the imp is video adUnit.video = Object.assign({}, videoMediaType); delete adUnit.mediaTypes; - // default is assumed to be 'banner' so if there is a video type we assume video only until PBS can support multi format auction. + // default is assumed to be 'banner' so if there is a video type + // we assume video only until PBS can support multi-format auction adUnit.media_types = [VIDEO]; } }); - convertTypes(adUnits); - let requestJson = { + + const request = { account_id: _s2sConfig.accountId, tid: s2sBidRequest.tid, max_bids: _s2sConfig.maxBids, @@ -272,126 +273,319 @@ export function PrebidServer() { cache_markup: _s2sConfig.cacheMarkup, url: utils.getTopWindowUrl(), prebid_version: '$prebid.version$', - ad_units: adUnits.filter(hasSizes), - is_debug: isDebug + ad_units: adUnits, + is_debug: !!getConfig('debug'), }; - let digiTrust = _getDigiTrustQueryParams(); - // grab some global config and pass it along ['app', 'device'].forEach(setting => { let value = getConfig(setting); if (typeof value === 'object') { - requestJson[setting] = value; + request[setting] = value; } }); + let digiTrust = _getDigiTrustQueryParams(); if (digiTrust) { - requestJson.digiTrust = digiTrust; - } - - // in case config.bidders contains invalid bidders, we only process those we sent requests for. - const requestedBidders = requestJson.ad_units.map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(utils.uniques)).reduce(utils.flatten).filter(utils.uniques); - function processResponse(response) { - handleResponse(response, requestedBidders, bidRequests, addBidResponse, done); + request.digiTrust = digiTrust; } - const payload = JSON.stringify(requestJson); - ajax(_s2sConfig.endpoint, processResponse, payload, { - contentType: 'text/plain', - withCredentials: true - }); - }; - - // at this point ad units should have a size array either directly or mapped so filter for that - function hasSizes(unit) { - return unit.sizes && unit.sizes.length; - } - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(response, requestedBidders, bidRequests, addBidResponse, done) { - let result; - try { - result = JSON.parse(response); + return request; + }, - if (result.status === 'OK' || result.status === 'no_cookie') { - if (result.bidder_status) { - result.bidder_status.forEach(bidder => { - if (bidder.no_cookie) { - doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder); - } - }); - } + interpretResponse(result, bidRequests, requestedBidders) { + const bids = []; - // do client-side syncs if available - requestedBidders.forEach(bidder => { - let clientAdapter = adaptermanager.getBidAdapter(bidder); - if (clientAdapter && clientAdapter.registerSyncs) { - clientAdapter.registerSyncs([]); + if (result.status === 'OK' || result.status === 'no_cookie') { + if (result.bidder_status) { + result.bidder_status.forEach(bidder => { + if (bidder.no_cookie) { + doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder); } }); + } - if (result.bids) { - result.bids.forEach(bidObj => { - let bidRequest = utils.getBidRequest(bidObj.bid_id, bidRequests); - let cpm = bidObj.price; - let status; - if (cpm !== 0) { - status = STATUS.GOOD; - } else { - status = STATUS.NO_BID; - } + // do client-side syncs if available + requestedBidders.forEach(bidder => { + let clientAdapter = adaptermanager.getBidAdapter(bidder); + if (clientAdapter && clientAdapter.registerSyncs) { + clientAdapter.registerSyncs([]); + } + }); - let bidObject = bidfactory.createBid(status, bidRequest); - bidObject.source = TYPE; - bidObject.creative_id = bidObj.creative_id; - bidObject.bidderCode = bidObj.bidder; - bidObject.cpm = cpm; - if (bidObj.cache_id) { - bidObject.cache_id = bidObj.cache_id; + if (result.bids) { + result.bids.forEach(bidObj => { + const bidRequest = utils.getBidRequest(bidObj.bid_id, bidRequests); + const cpm = bidObj.price; + const status = cpm !== 0 ? STATUS.GOOD : STATUS.NO_BID; + let bidObject = bidfactory.createBid(status, bidRequest); + + bidObject.source = TYPE; + bidObject.creative_id = bidObj.creative_id; + bidObject.bidderCode = bidObj.bidder; + bidObject.cpm = cpm; + if (bidObj.cache_id) { + bidObject.cache_id = bidObj.cache_id; + } + if (bidObj.cache_url) { + bidObject.cache_url = bidObj.cache_url; + } + // From ORTB see section 4.2.3: adm Optional means of conveying ad markup in case the bid wins; supersedes the win notice if markup is included in both. + if (bidObj.media_type === VIDEO) { + bidObject.mediaType = VIDEO; + if (bidObj.adm) { + bidObject.vastXml = bidObj.adm; } - if (bidObj.cache_url) { - bidObject.cache_url = bidObj.cache_url; + if (bidObj.nurl) { + bidObject.vastUrl = bidObj.nurl; } - // From ORTB see section 4.2.3: adm Optional means of conveying ad markup in case the bid wins; supersedes the win notice if markup is included in both. - if (bidObj.media_type === VIDEO) { - bidObject.mediaType = VIDEO; - if (bidObj.adm) { - bidObject.vastXml = bidObj.adm; - } - if (bidObj.nurl) { - bidObject.vastUrl = bidObj.nurl; - } - } else { - if (bidObj.adm && bidObj.nurl) { - bidObject.ad = bidObj.adm; - bidObject.ad += utils.createTrackPixelHtml(decodeURIComponent(bidObj.nurl)); - } else if (bidObj.adm) { - bidObject.ad = bidObj.adm; - } else if (bidObj.nurl) { - bidObject.adUrl = bidObj.nurl - } + } else { + if (bidObj.adm && bidObj.nurl) { + bidObject.ad = bidObj.adm; + bidObject.ad += utils.createTrackPixelHtml(decodeURIComponent(bidObj.nurl)); + } else if (bidObj.adm) { + bidObject.ad = bidObj.adm; + } else if (bidObj.nurl) { + bidObject.adUrl = bidObj.nurl; } + } - bidObject.width = bidObj.width; - bidObject.height = bidObj.height; - bidObject.adserverTargeting = bidObj.ad_server_targeting; - if (bidObj.deal_id) { - bidObject.dealId = bidObj.deal_id; - } - bidObject.requestId = bidObj.bid_id; - bidObject.creativeId = bidObj.creative_id; + bidObject.width = bidObj.width; + bidObject.height = bidObj.height; + bidObject.adserverTargeting = bidObj.ad_server_targeting; + if (bidObj.deal_id) { + bidObject.dealId = bidObj.deal_id; + } + bidObject.requestId = bidObj.bid_id; + bidObject.creativeId = bidObj.creative_id; + + // TODO: Remove when prebid-server returns ttl, currency and netRevenue + bidObject.ttl = (bidObj.ttl) ? bidObj.ttl : DEFAULT_S2S_TTL; + bidObject.currency = (bidObj.currency) ? bidObj.currency : DEFAULT_S2S_CURRENCY; + bidObject.netRevenue = (bidObj.netRevenue) ? bidObj.netRevenue : DEFAULT_S2S_NETREVENUE; + + bids.push({ adUnit: bidObj.code, bid: bidObject }); + }); + } + } + + return bids; + } +}; + +/* + * Protocol spec for OpenRTB endpoint + * e.g., https:///v1/openrtb2/auction + */ +const OPEN_RTB_PROTOCOL = { + + bidMap: {}, + + buildRequest(s2sBidRequest, adUnits) { + let imps = []; + + // transform ad unit into array of OpenRTB impression objects + adUnits.forEach(adUnit => { + // OpenRTB response contains the adunit code and bidder name. These are + // combined to create a unique key for each bid since an id isn't returned + adUnit.bids.forEach(bid => { + const key = `${adUnit.code}${bid.bidder}`; + this.bidMap[key] = bid; + }); + + let banner; + // default to banner if mediaTypes isn't defined + if (utils.isEmpty(adUnit.mediaTypes)) { + const sizeObjects = adUnit.sizes.map(size => ({ w: size.w, h: size.h })); + banner = {format: sizeObjects}; + } - // TODO: Remove when prebid-server returns ttl, currency and netRevenue - bidObject.ttl = (bidObj.ttl) ? bidObj.ttl : DEFAULT_S2S_TTL; - bidObject.currency = (bidObj.currency) ? bidObj.currency : DEFAULT_S2S_CURRENCY; - bidObject.netRevenue = (bidObj.netRevenue) ? bidObj.netRevenue : DEFAULT_S2S_NETREVENUE; + const bannerParams = utils.deepAccess(adUnit, 'mediaTypes.banner'); + if (bannerParams && bannerParams.sizes) { + const sizes = utils.parseSizesInput(bannerParams.sizes); - if (isValid(bidObj.code, bidObject, bidRequests)) { - addBidResponse(bidObj.code, bidObject); + // get banner sizes in form [{ w: , h: }, ...] + const format = sizes.map(size => { + const [ width, height ] = size.split('x'); + const w = parseInt(width, 10); + const h = parseInt(height, 10); + return { w, h }; + }); + + banner = {format}; + } + + let video; + const videoParams = utils.deepAccess(adUnit, 'mediaTypes.video'); + if (!utils.isEmpty(videoParams)) { + video = videoParams; + } + + // get bidder params in form { : {...params} } + const ext = adUnit.bids.reduce((acc, bid) => { + acc[bid.bidder] = bid.params; + return acc; + }, {}); + + const imp = { id: adUnit.code, ext, secure: _s2sConfig.secure }; + + if (banner) { imp.banner = banner; } + if (video) { imp.video = video; } + + imps.push(imp); + }); + + const request = { + id: s2sBidRequest.tid, + site: {publisher: {id: _s2sConfig.accountId}}, + source: {tid: s2sBidRequest.tid}, + tmax: _s2sConfig.timeout, + imp: imps, + test: getConfig('debug') ? 1 : 0, + }; + + ['app', 'device'].forEach(setting => { + let value = getConfig(setting); + if (typeof value === 'object') { + request[setting] = value; + } + }); + + const digiTrust = _getDigiTrustQueryParams(); + if (digiTrust) { + request.user = { ext: { digitrust: digiTrust } }; + } + + return request; + }, + + interpretResponse(response, bidRequests, requestedBidders) { + const bids = []; + + if (response.seatbid) { + // a seatbid object contains a `bid` array and a `seat` string + response.seatbid.forEach(seatbid => { + (seatbid.bid || []).forEach(bid => { + const bidRequest = utils.getBidRequest( + this.bidMap[`${bid.impid}${seatbid.seat}`], + bidRequests + ); + + const cpm = bid.price; + const status = cpm !== 0 ? STATUS.GOOD : STATUS.NO_BID; + let bidObject = bidfactory.createBid(status, bidRequest); + + bidObject.source = TYPE; + bidObject.bidderCode = seatbid.seat; + bidObject.cpm = cpm; + + if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { + bidObject.mediaType = VIDEO; + if (bid.adm) { bidObject.vastXml = bid.adm; } + } else { // banner + if (bid.adm && bid.nurl) { + bidObject.ad = bid.adm; + bidObject.ad += utils.createTrackPixelHtml(decodeURIComponent(bid.nurl)); + } else if (bid.adm) { + bidObject.ad = bid.adm; + } else if (bid.nurl) { + bidObject.adUrl = bid.nurl; } - }); + } + + bidObject.width = bid.w; + bidObject.height = bid.h; + if (bid.dealid) { bidObject.dealId = bid.dealid; } + bidObject.requestId = bid.id; + bidObject.creative_id = bid.crid; + bidObject.creativeId = bid.crid; + + // TODO: Remove when prebid-server returns ttl, currency and netRevenue + bidObject.ttl = (bid.ttl) ? bid.ttl : DEFAULT_S2S_TTL; + bidObject.currency = (bid.currency) ? bid.currency : DEFAULT_S2S_CURRENCY; + bidObject.netRevenue = (bid.netRevenue) ? bid.netRevenue : DEFAULT_S2S_NETREVENUE; + + bids.push({ adUnit: bid.impid, bid: bidObject }); + }); + }); + } + + return bids; + } +}; + +/* + * Returns the required protocol adapter to communicate with the configured + * endpoint. The adapter is an object containing `buildRequest` and + * `interpretResponse` functions. + * + * Usage: + * // build JSON payload to send to server + * const request = protocol().buildRequest(s2sBidRequest, adUnits); + * + * // turn server response into bid object array + * const bids = protocol().interpretResponse(response, bidRequests, requestedBidders); + */ +const protocolAdapter = () => { + const OPEN_RTB_PATH = 'openrtb2/auction'; + + const endpoint = (_s2sConfig && _s2sConfig.endpoint) || ''; + const isOpenRtb = ~endpoint.indexOf(OPEN_RTB_PATH); + + return isOpenRtb ? OPEN_RTB_PROTOCOL : LEGACY_PROTOCOL; +}; + +/** + * Bidder adapter for Prebid Server + */ +export function PrebidServer() { + const baseAdapter = new Adapter('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); + + convertTypes(adUnits); + + // at this point ad units should have a size array either directly or mapped so filter for that + const adUnitsWithSizes = adUnits.filter(unit => unit.sizes && unit.sizes.length); + + // in case config.bidders contains invalid bidders, we only process those we sent requests for + const requestedBidders = adUnitsWithSizes + .map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(utils.uniques)) + .reduce(utils.flatten) + .filter(utils.uniques); + + const request = protocolAdapter().buildRequest(s2sBidRequest, adUnitsWithSizes); + const requestJson = JSON.stringify(request); + + ajax( + _s2sConfig.endpoint, + response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done), + requestJson, + { contentType: 'text/plain', withCredentials: true } + ); + }; + + /* Notify Prebid of bid responses so bids can get in the auction */ + function handleResponse(response, requestedBidders, bidRequests, addBidResponse, done) { + let result; + + try { + result = JSON.parse(response); + + const bids = protocolAdapter().interpretResponse( + result, + bidRequests, + requestedBidders + ); + + bids.forEach(({adUnit, bid}) => { + if (isValid(adUnit, bid, bidRequests)) { + addBidResponse(adUnit, bid); } - } + }); + if (result.status === 'no_cookie' && _s2sConfig.cookieSet && typeof _s2sConfig.cookieSetUrl === 'string') { // cookie sync cookieSet(_s2sConfig.cookieSetUrl); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index f403b886b98..7214e841b54 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -36,6 +36,11 @@ const REQUEST = { 'h': 600 } ], + 'mediaTypes': { + 'banner': { + 'sizes': [[ 300, 250 ], [ 300, 300 ]] + } + }, 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', 'bids': [ { @@ -51,6 +56,36 @@ const REQUEST = { ] }; +const VIDEO_REQUEST = { + 'account_id': '1', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'max_bids': 1, + 'timeout_millis': 1000, + 'secure': 0, + 'url': '', + 'prebid_version': '1.4.0-pre', + 'ad_units': [ + { + 'code': 'div-gpt-ad-1460505748561-0', + 'sizes': [{ 'w': 640, 'h': 480 }], + 'mediaTypes': { + 'video': { + 'playerSize': [[ 640, 480 ]], + 'mimes': ['video/mp4'] + } + }, + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'bids': [ + { + 'bid_id': '123', + 'bidder': 'appnexus', + 'params': { 'placementId': '12349520' } + } + ] + } + ] +}; + const BID_REQUESTS = [ { 'bidderCode': 'appnexus', @@ -208,6 +243,87 @@ const RESPONSE_NO_PBS_COOKIE_ERROR = { }] }; +const RESPONSE_OPENRTB = { + 'id': 'c7dcf14f', + 'seatbid': [ + { + 'bid': [ + { + 'id': '8750901685062148', + 'impid': '123', + 'price': 0.5, + 'adm': '', + 'adid': '29681110', + 'adomain': [ 'appnexus.com' ], + 'iurl': 'http://lax1-ib.adnxs.com/cr?id=2968111', + 'cid': '958', + 'crid': '2968111', + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { 'type': 'banner' }, + 'bidder': { + 'appnexus': { + 'brand_id': 1, + 'auction_id': 3, + 'bidder_id': 2 + } + } + } + } + ], + 'seat': 'appnexus' + }, + ], + 'ext': { + 'responsetimemillis': { + 'appnexus': 8, + } + } +}; + +const RESPONSE_OPENRTB_VIDEO = { + id: 'c7dcf14f', + seatbid: [ + { + bid: [ + { + id: '1987250005171537465', + impid: '/19968336/header-bid-tag-0', + price: 10, + adm: 'adnxs', + adid: '81877115', + adomain: ['appnexus.com'], + iurl: 'http://lax1-ib.adnxs.com/cr?id=81877115', + cid: '3535', + crid: '81877115', + w: 1, + h: 1, + ext: { + prebid: { + type: 'video', + }, + bidder: { + appnexus: { + brand_id: 1, + auction_id: 6673622101799484743, + bidder_id: 2, + bid_ad_type: 1, + }, + }, + }, + }, + ], + seat: 'appnexus', + }, + ], + ext: { + responsetimemillis: { + appnexus: 81, + }, + }, +}; + describe('S2S Adapter', () => { let adapter, addBidResponse = sinon.spy(), @@ -473,6 +589,44 @@ describe('S2S Adapter', () => { server.respond(); sinon.assert.calledOnce(cookie.cookieSet); }); + + it('handles OpenRTB responses', () => { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + config.setConfig({s2sConfig}); + + server.respondWith(JSON.stringify(RESPONSE_OPENRTB)); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(addBidResponse); + const response = addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('bidderCode', 'appnexus'); + expect(response).to.have.property('adId', '123'); + expect(response).to.have.property('cpm', 0.5); + }); + + it('handles OpenRTB video responses', () => { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' + }); + config.setConfig({s2sConfig}); + + server.respondWith(JSON.stringify(RESPONSE_OPENRTB_VIDEO)); + adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(addBidResponse); + const response = addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('vastXml', RESPONSE_OPENRTB_VIDEO.seatbid[0].bid[0].adm); + expect(response).to.have.property('mediaType', 'video'); + expect(response).to.have.property('bidderCode', 'appnexus'); + expect(response).to.have.property('adId', '123'); + expect(response).to.have.property('cpm', 10); + }); }); describe('s2sConfig', () => { From 4bfc9414c73f287c5b06ef18b2fd1d4e2b52aca9 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 20 Feb 2018 15:27:51 -0500 Subject: [PATCH 0134/1594] Prebid 1.4.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a3d55389d56..cb48a772de7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.4.0-pre", + "version": "1.4.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d131109bf258dc225b28d26d9db5534e4ce7509e Mon Sep 17 00:00:00 2001 From: jmfbird Date: Tue, 20 Feb 2018 21:28:26 +0100 Subject: [PATCH 0135/1594] Update appnexusBidAdapter so clients can distinguish between managed and RTB bids (#2161) * Added buyerMemberId to appnexus adapter so clients can distinguish between managed and RTB demand * Moved buyerMemberId to a separate appnexus object within the bid * Corrected indendation --- modules/appnexusBidAdapter.js | 5 ++++- test/spec/modules/appnexusBidAdapter_spec.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 4afe451f54f..034824f6fda 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -189,7 +189,10 @@ function newBid(serverBid, rtbBid, bidderRequest) { dealId: rtbBid.deal_id, currency: 'USD', netRevenue: true, - ttl: 300 + ttl: 300, + appnexus: { + buyerMemberId: rtbBid.buyer_member_id + } }; if (rtbBid.rtb.video) { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 88e3383b709..661d6a63e3d 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -378,7 +378,10 @@ describe('AppNexusAdapter', () => { 'mediaType': 'banner', 'currency': 'USD', 'ttl': 300, - 'netRevenue': true + 'netRevenue': true, + 'appnexus': { + 'buyerMemberId': 958 + } } ]; let bidderRequest; From 1d764296e05b4f589721ba4668b19fe16f1ab97a Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 20 Feb 2018 16:32:05 -0500 Subject: [PATCH 0136/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cb48a772de7..f7cc918892d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.4.0", + "version": "1.5.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 853a762abd074a61c7551e617b636c22751c9b0a Mon Sep 17 00:00:00 2001 From: sami-elasticad <35566930+sami-elasticad@users.noreply.github.com> Date: Thu, 22 Feb 2018 13:56:14 +0200 Subject: [PATCH 0137/1594] Quantum Advertising Adapter (#2051) * quantumBidAdapter initial commit * eslint errors fixed * updating quantumBidAdapter for reviews, fixed tests to work with native * set new prebid location for testing and some fixing * added supportedMediaTypes * Tests fixed * Fixed issues with image assets. Tested with the example provided --- modules/quantumBidAdapter.js | 301 ++++++++++++++++++++ modules/quantumBidAdapter.md | 94 ++++++ test/spec/modules/quantumBidAdapter_spec.js | 267 +++++++++++++++++ 3 files changed, 662 insertions(+) create mode 100644 modules/quantumBidAdapter.js create mode 100644 modules/quantumBidAdapter.md create mode 100644 test/spec/modules/quantumBidAdapter_spec.js diff --git a/modules/quantumBidAdapter.js b/modules/quantumBidAdapter.js new file mode 100644 index 00000000000..242ccc63204 --- /dev/null +++ b/modules/quantumBidAdapter.js @@ -0,0 +1,301 @@ +import * as utils from 'src/utils'; +import { BANNER, NATIVE } from 'src/mediaTypes'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'quantum'; +const ENDPOINT_URL = '//s.sspqns.com/hb'; +export const spec = { + code: BIDDER_CODE, + aliases: ['quantx', 'qtx'], // short 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 (bid) { + return !!(bid.params && 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 (bidRequests) { + return bidRequests.map(bid => { + const qtxRequest = {}; + let bidId = ''; + + const params = bid.params; + let placementId = params.placementId; + + let devEnpoint = false; + if (params.useDev && params.useDev === '1') { + devEnpoint = '//sdev.sspqns.com/hb'; + } + let renderMode = 'native'; + for (let i = 0; i < bid.sizes.length; i++) { + if (bid.sizes[i][0] > 1 && bid.sizes[i][1] > 1) { + renderMode = 'banner'; + break; + } + } + + let mediaType = (bid.mediaType === 'native' || utils.deepAccess(bid, 'mediaTypes.native')) ? 'native' : 'banner'; + + if (mediaType === 'native') { + renderMode = 'native'; + } + + if (!bidId) { + bidId = bid.bidId; + } + qtxRequest.auid = placementId; + const url = devEnpoint || ENDPOINT_URL; + + return { + method: 'GET', + bidId: bidId, + sizes: bid.sizes, + mediaType: mediaType, + renderMode: renderMode, + url: url, + 'data': qtxRequest + }; + }); + }, + /** + * 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 responseCPM; + let bid = {}; + let id = bidRequest.bidId; + + if (serverBody.price && serverBody.price !== 0) { + responseCPM = parseFloat(serverBody.price); + + bid.creativeId = serverBody.creative_id || '0'; + bid.cpm = responseCPM; + bid.requestId = bidRequest.bidId; + bid.width = 1; + bid.height = 1; + bid.ttl = 200; + bid.netRevenue = true; + bid.currency = 'USD'; + + if (serverBody.native) { + bid.native = serverBody.native; + } + if (serverBody.cobj) { + bid.cobj = serverBody.cobj; + } + + bid.nurl = serverBody.nurl; + bid.sync = serverBody.sync; + if (bidRequest.renderMode && bidRequest.renderMode === 'banner') { + bid.width = 300; + bid.height = 225; + if (serverBody.native) { + const adAssetsUrl = '//cdn.elasticad.net/native/serve/js/quantx/quantumAd/'; + let assets = serverBody.native.assets; + let link = serverBody.native.link; + + let trackers = []; + if (serverBody.native.imptrackers) { + trackers = serverBody.native.imptrackers; + } + + let jstracker = ''; + if (serverBody.native.jstracker) { + jstracker = serverBody.native.jstracker; + } + + if (serverBody.nurl) { + trackers.push(serverBody.nurl); + } + + let ad = {}; + ad['trackers'] = trackers; + ad['jstrackers'] = jstracker; + + for (let i = 0; i < assets.length; i++) { + let asset = assets[i]; + switch (asset['id']) { + case 1: + ad['title'] = asset['title']['text']; + break; + case 2: + ad['sponsor_logo'] = asset['img']['url']; + break; + case 3: + ad['content'] = asset['data']['value']; + break; + case 4: + ad['main_image'] = asset['img']['url']; + break; + case 6: + ad['teaser_type'] = 'vast'; + ad['video_url'] = asset['video']['vasttag']; + break; + case 10: + ad['sponsor_name'] = asset['data']['value']; + break; + case 2001: + ad['expanded_content_type'] = 'embed'; + ad['expanded_summary'] = asset['data']['value']; + break; + case 2002: + ad['expanded_content_type'] = 'vast'; + ad['expanded_summary'] = asset['data']['value']; + break; + case 2003: + ad['sponsor_url'] = asset['data']['value']; + break; + case 2004: // prism + ad['content_type'] = 'prism'; + break; + case 2005: // internal_landing_page + ad['content_type'] = 'internal_landing_page'; + ad['internal_content_link'] = asset['data']['value']; + break; + case 2006: // teaser as vast + ad['teaser_type'] = 'vast'; + ad['video_url'] = asset['data']['value']; + break; + case 2007: + ad['autoexpand_content_type'] = asset['data']['value']; + break; + case 2022: // content page + ad['content_type'] = 'full_text'; + ad['full_text'] = asset['data']['value']; + break; + } + } + + ad['action_url'] = link.url; + + if (!ad['sponsor_url']) { + ad['sponsor_url'] = ad['action_url']; + } + + ad['clicktrackers'] = []; + if (link.clicktrackers) { + ad['clicktrackers'] = link.clicktrackers; + } + + ad['main_image'] = '//resize-ssp.elasticad.net/scalecrop-290x130/' + window.btoa(ad['main_image']) + '/external'; + + bid.ad = '
' + + '
' + + '
' + + ' ' + + ' ' + + '
' + + '

' + ad['title'] + '

' + + '

' + ad['content'] + ' 

' + + ' ' + + '
' + + '' + + '' + + '' + + '
'; + } + } else { + // native + if (bidRequest.mediaType === 'native') { + if (serverBody.native) { + let assets = serverBody.native.assets; + let link = serverBody.native.link; + + let trackers = []; + if (serverBody.native.imptrackers) { + trackers = serverBody.native.imptrackers; + } + + if (serverBody.nurl) { + trackers.push(serverBody.nurl); + } + + let native = {}; + + for (let i = 0; i < assets.length; i++) { + let asset = assets[i]; + switch (asset['id']) { + case 1: + native.title = asset['title']['text']; + break; + case 2: + native.icon = asset['img']; + break; + case 3: + native.body = asset['data']['value']; + break; + case 4: + native.image = asset['img']; + break; + case 10: + native.sponsoredBy = asset['data']['value']; + break; + } + } + native.cta = 'read more'; + if (serverBody.language) { + native.cta = 'read more'; + } + + native.clickUrl = link.url; + native.impressionTrackers = trackers; + if (link.clicktrackers) { + native.clickTrackers = link.clicktrackers; + } + + bid.qtx_native = utils.deepClone(serverBody.native); + bid.native = native; + } + } + } + bidResponses.push(bid); + } + + 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) { + const syncs = [] + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' + }); + } + if (syncOptions.pixelEnabled && serverResponses.length > 0) { + syncs.push({ + type: 'image', + url: serverResponses[0].body.sync[0] + }); + } + return syncs; + } +} +registerBidder(spec); diff --git a/modules/quantumBidAdapter.md b/modules/quantumBidAdapter.md new file mode 100644 index 00000000000..ac64ab371c5 --- /dev/null +++ b/modules/quantumBidAdapter.md @@ -0,0 +1,94 @@ +# Overview + +``` +Module Name: Quantum Advertising Bid Adapter +Module Type: Bidder Adapter +Maintainer: sami@elasticad.com +``` + +# Description + +Connects to Quantum's ssp for bids. + +# Sample Ad Unit: For Publishers +``` +var adUnits = [{ + code: 'quantum-adUnit-id-1', + sizes: [[300, 250]], + bids: [{ + bidder: 'quantum', + params: { + placementId: 21546 //quantum adUnit id + } + }] + },{ + code: 'quantum-native-adUnit-id-1', + sizes: [[0, 0]], + mediaTypes: 'native', + bids: [{ + bidder: 'quantum', + params: { + placementId: 21546 //quantum adUnit id + } + }] + }]; +``` + +# Ad Unit and Setup: For Testing + +``` + + + + + + + + + + ``` diff --git a/test/spec/modules/quantumBidAdapter_spec.js b/test/spec/modules/quantumBidAdapter_spec.js new file mode 100644 index 00000000000..2db1c0b0fbd --- /dev/null +++ b/test/spec/modules/quantumBidAdapter_spec.js @@ -0,0 +1,267 @@ +import { expect } from 'chai' +import { spec } from 'modules/quantumBidAdapter' +import { newBidder } from 'src/adapters/bidderFactory' + +const ENDPOINT = '//s.sspqns.com/hb' +const REQUEST = { + 'bidder': 'quantum', + 'sizes': [[300, 225]], + 'renderMode': 'banner', + 'params': { + placementId: 21546 + } +} + +const NATIVE_REQUEST = { + 'bidder': 'quantum', + 'mediaType': 'native', + 'sizes': [[0, 0]], + 'params': { + placementId: 21546 + } +} + +const serverResponse = { + 'price': 0.3, + 'debug': [ + '' + ], + 'is_fallback': false, + 'nurl': 'http://s.sspqns.com/imp/KpQ1WNMHV-9a3HqWL_0JnujJFGo1Hnx9RS3FT_Yy8jW-Z6t_PJYmP2otidJsxE3qcY2EozzcBjRzGM7HEQcxVnjOzq0Th1cxb6A5bSp5BizTwY5SRaxx_0PgF6--8LqaF4LMUgMmhfF5k3gOOzzK6gKdavia4_w3LJ1CRWkMEwABr8bPzeovy1y4MOZsOXv7vXjPGMKJSTgphuZR57fL4u4ZFF4XY70K_TaH5bfXHMRAzE0Q38tfpTvbdFV_u2g-FoF0gjzKjiS88VnetT-Jo3qtrMphWzr52jsg5tH3L7hbymUOm1YkuJP9xrXLoZNVgC5sTMYolKLMSu6dqhS2FXcdfaGAcHweaaAAwJq-pB7DuiVcdnZQphUymhIia_KG2AYweWp6TYEpJbJjf2BcLpm_-KGw4gLh6L3DtEvUZwXZe-JpUJ4/', + 'native': { + 'link': { + 'url': 'http://s.sspqns.com/click/KpQ1WNMHV-9a3HqWL_0JnujJFGo1Hnx9RS3FT_Yy8jW-Z6t_PJYmP2otidJsxE3qcY2EozzcBjRzGM7HEQcxVnjOzq0Th1cxb6A5bSp5BizTwY5SRaxx_0PgF6--8LqaF4LMUgMmhfF5k3gOOzzK6gKdavia4_w3LJ1CRWkMEwABr8bPzeovy1y4MOZsOXv7vXjPGMKJSTgphuZR57fL4u4ZFF4XY70K_TaH5bfXHMRAzE0Q38tfpTvbdFV_u2g-FoF0gjzKjiS88VnetT-Jo3qtrMphWzr52jsg5tH3L7hbymUOm1YkuJP9xrXLoZNVgC5sTMYolKLMSu6dqhS2FXcdfaGAcHweaaAAwJq-pB7DuiVcdnZQphUymhIia_KG2AYweWp6TYEpJbJjf2BcLpm_-KGw4gLh6L3DtEvUZwXZe-JpUJ4///', + 'clicktrackers': ['https://elasticad.net'] + }, + 'assets': [ + { + 'id': 1, + 'title': { + 'text': 'ad.SSP.1x1' + }, + 'required': 1 + }, + { + 'id': 2, + 'img': { + 'w': 15, + 'h': 15, + 'url': 'http://files.ssp.theadtech.com.s3.amazonaws.com/media/image/sxjermpz/scalecrop-15x15' + } + }, + { + 'id': 3, + 'data': { + 'value': 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum is simply dummy text of the printing and typesetting industry.' + }, + 'required': 1 + }, + { + 'id': 4, + 'img': { + 'w': 500, + 'h': 500, + 'url': 'http://files.ssp.theadtech.com.s3.amazonaws.com/media/image/sxjermpz/scalecrop-500x500' + } + }, + { + 'id': 6, + 'video': { + 'vasttag': 'http://elasticad.net/vast.xml' + } + }, + { + 'id': 2001, + 'data': { + 'value': 'http://elasticad.net' + } + }, + { + 'id': 2002, + 'data': { + 'value': 'vast' + } + }, + { + 'id': 2007, + 'data': { + 'value': 'click' + } + }, + { + 'id': 10, + 'data': { + 'value': 'ad.SSP.1x1 sponsor' + } + }, + { + 'id': 2003, + 'data': { + 'value': 'http://elasticad.net' + } + }, + { + 'id': 2004, + 'data': { + 'value': 'prism' + } + }, + { + 'id': 2005, + 'data': { + 'value': '/home' + } + }, + { + 'id': 2006, + 'data': { + 'value': 'http://elasticad.net/vast.xml' + } + }, + { + 'id': 2022, + 'data': { + 'value': 'Lorem ipsum....' + } + } + ], + 'imptrackers': [], + 'ver': '1.1' + }, + 'sync': [ + 'http://match.adsrvr.org/track/cmb/generic?ttd_pid=s6e8ued&ttd_tpi=1' + ] +} + +const nativeServerResponse = { + 'price': 0.3, + 'debug': [ + '' + ], + 'is_fallback': false, + 'nurl': 'http://s.sspqns.com/imp/KpQ1WNMHV-9a3HqWL_0JnujJFGo1Hnx9RS3FT_Yy8jW-Z6t_PJYmP2otidJsxE3qcY2EozzcBjRzGM7HEQcxVnjOzq0Th1cxb6A5bSp5BizTwY5SRaxx_0PgF6--8LqaF4LMUgMmhfF5k3gOOzzK6gKdavia4_w3LJ1CRWkMEwABr8bPzeovy1y4MOZsOXv7vXjPGMKJSTgphuZR57fL4u4ZFF4XY70K_TaH5bfXHMRAzE0Q38tfpTvbdFV_u2g-FoF0gjzKjiS88VnetT-Jo3qtrMphWzr52jsg5tH3L7hbymUOm1YkuJP9xrXLoZNVgC5sTMYolKLMSu6dqhS2FXcdfaGAcHweaaAAwJq-pB7DuiVcdnZQphUymhIia_KG2AYweWp6TYEpJbJjf2BcLpm_-KGw4gLh6L3DtEvUZwXZe-JpUJ4/', + 'native': { + 'link': { + 'url': 'http://s.sspqns.com/click/KpQ1WNMHV-9a3HqWL_0JnujJFGo1Hnx9RS3FT_Yy8jW-Z6t_PJYmP2otidJsxE3qcY2EozzcBjRzGM7HEQcxVnjOzq0Th1cxb6A5bSp5BizTwY5SRaxx_0PgF6--8LqaF4LMUgMmhfF5k3gOOzzK6gKdavia4_w3LJ1CRWkMEwABr8bPzeovy1y4MOZsOXv7vXjPGMKJSTgphuZR57fL4u4ZFF4XY70K_TaH5bfXHMRAzE0Q38tfpTvbdFV_u2g-FoF0gjzKjiS88VnetT-Jo3qtrMphWzr52jsg5tH3L7hbymUOm1YkuJP9xrXLoZNVgC5sTMYolKLMSu6dqhS2FXcdfaGAcHweaaAAwJq-pB7DuiVcdnZQphUymhIia_KG2AYweWp6TYEpJbJjf2BcLpm_-KGw4gLh6L3DtEvUZwXZe-JpUJ4///' + }, + 'assets': [ + { + 'id': 1, + 'title': { + 'text': 'ad.SSP.1x1' + }, + 'required': 1 + }, + { + 'id': 2, + 'img': { + 'w': 15, + 'h': 15, + 'url': 'http://files.ssp.theadtech.com.s3.amazonaws.com/media/image/sxjermpz/scalecrop-15x15' + } + }, + { + 'id': 3, + 'data': { + 'value': 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum is simply dummy text of the printing and typesetting industry.' + }, + 'required': 1 + }, + { + 'id': 4, + 'img': { + 'w': 500, + 'h': 500, + 'url': 'http://files.ssp.theadtech.com.s3.amazonaws.com/media/image/sxjermpz/scalecrop-500x500' + } + }, + { + 'id': 2007, + 'data': { + 'value': 'click' + } + }, + { + 'id': 10, + 'data': { + 'value': 'ad.SSP.1x1 sponsor' + } + }, + + { + 'id': 2003, + 'data': { + 'value': 'http://elasticad.net' + } + } + ], + 'imptrackers': [], + 'ver': '1.1' + }, + 'sync': [ + 'http://match.adsrvr.org/track/cmb/generic?ttd_pid=s6e8ued&ttd_tpi=1' + ] +} + +describe('quantumBidAdapter', () => { + const adapter = newBidder(spec) + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function') + }) + }) + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(REQUEST)).to.equal(true) + }) + + it('should return false when required params are not passed', () => { + let bid = Object.assign({}, REQUEST) + delete bid.params + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + }) + + describe('buildRequests', () => { + let bidRequests = [REQUEST] + + const request = spec.buildRequests(bidRequests, {}) + + it('sends bid request to ENDPOINT via GET', () => { + expect(request[0].method).to.equal('GET') + }) + }) + + describe('interpretResponse', () => { + let bidderRequest = { + bidderCode: 'bidderCode', + bids: [] + } + + it('handles native request : should get correct bid response', () => { + const result = spec.interpretResponse({body: nativeServerResponse}, NATIVE_REQUEST) + expect(result[0]).to.have.property('cpm').equal(0.3) + expect(result[0]).to.have.property('width').to.be.below(2) + expect(result[0]).to.have.property('height').to.be.below(2) + expect(result[0]).to.have.property('native') + }) + + it('should get correct bid response', () => { + const result = spec.interpretResponse({body: serverResponse}, REQUEST) + expect(result[0]).to.have.property('cpm').equal(0.3) + expect(result[0]).to.have.property('width').equal(300) + expect(result[0]).to.have.property('height').equal(225) + // expect(result[0]).to.have.property('native'); + expect(result[0]).to.have.property('ad') + }) + + it('handles nobid responses', () => { + const nobidServerResponse = {bids: []} + const nobidResult = spec.interpretResponse({body: nobidServerResponse}, bidderRequest) + // console.log(nobidResult) + expect(nobidResult.length).to.equal(0) + }) + }) +}) From 448d4db901ec8e646c2a556785bae29ed4ae294d Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 22 Feb 2018 12:30:59 -0700 Subject: [PATCH 0138/1594] only do video caching if we don't already have a videoCacheKey (#2143) * only do video caching if we don't already have a videoCacheKey * log error for missing vastUrl when videoCacheKey specified --- src/auction.js | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/auction.js b/src/auction.js index 0af6458ac09..b8098d1faf4 100644 --- a/src/auction.js +++ b/src/auction.js @@ -224,25 +224,33 @@ function addBidToAuction(auctionInstance, bidResponse) { } // Video bids may fail if the cache is down, or there's trouble on the network. -function tryAddVideoBid(auctionInstance, bidResponse, bidRequest, vastUrl) { +function tryAddVideoBid(auctionInstance, bidResponse, bidRequest) { + let addBid = true; if (config.getConfig('cache.url')) { - store([bidResponse], function(error, cacheIds) { - if (error) { - utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); - - doCallbacksIfTimedout(auctionInstance, bidResponse); - } else { - bidResponse.videoCacheKey = cacheIds[0].uuid; - if (!vastUrl) { - bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); + if (!bidResponse.videoCacheKey) { + addBid = false; + store([bidResponse], function (error, cacheIds) { + if (error) { + utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); + + doCallbacksIfTimedout(auctionInstance, bidResponse); + } else { + bidResponse.videoCacheKey = cacheIds[0].uuid; + if (!bidResponse.vastUrl) { + bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); + } + // only set this prop after the bid has been cached to avoid early ending auction early in bidsBackAll + bidRequest.doneCbCallCount += 1; + addBidToAuction(auctionInstance, bidResponse); + auctionInstance.bidsBackAll(); } - // only set this prop after the bid has been cached to avoid early ending auction early in bidsBackAll - bidRequest.doneCbCallCount += 1; - addBidToAuction(auctionInstance, bidResponse); - auctionInstance.bidsBackAll(); - } - }); - } else { + }); + } else if (!bidResponse.vastUrl) { + utils.logError('videoCacheKey specified but not required vastUrl for video bid'); + addBid = false; + } + } + if (addBid) { addBidToAuction(auctionInstance, bidResponse); } } @@ -256,7 +264,7 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}); if (bidResponse.mediaType === 'video') { - tryAddVideoBid(auctionInstance, bidResponse, bidRequest, bid.vastUrl); + tryAddVideoBid(auctionInstance, bidResponse, bidRequest); } else { addBidToAuction(auctionInstance, bidResponse); } From 32dccd4bd28c1762a88a69fe0750ac1f0356fa18 Mon Sep 17 00:00:00 2001 From: NasmediaWebtech <34228109+NasmediaWebtech@users.noreply.github.com> Date: Fri, 23 Feb 2018 06:32:45 +0900 Subject: [PATCH 0139/1594] Update NasmediaAdmixer adapter (#2164) * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * update NasmediaAdmixer adapter * update NasmediaAdmixer adapter --- modules/nasmediaAdmixerBidAdapter.js | 10 +++++----- modules/nasmediaAdmixerBidAdapter.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/nasmediaAdmixerBidAdapter.js b/modules/nasmediaAdmixerBidAdapter.js index e4892f3d0ed..344bf991610 100644 --- a/modules/nasmediaAdmixerBidAdapter.js +++ b/modules/nasmediaAdmixerBidAdapter.js @@ -59,14 +59,14 @@ export const spec = { function getOsType() { let ua = navigator.userAgent.toLowerCase(); - let os = ['android', 'ios', 'mac', 'linux', 'window', 'etc']; - let regexp_os = [/android/i, /iphone|ipad/i, /mac/i, /linux/i, /window/i, '']; + let os = ['android', 'ios', 'mac', 'linux', 'window']; + let regexp_os = [/android/i, /iphone|ipad/i, /mac/i, /linux/i, /window/i]; - return regexp_os.some((tos, idx) => { - if (ua.match(tos)) { + return os.find((tos, idx) => { + if (ua.match(regexp_os[idx])) { return os[idx]; } - }); + }) || 'etc'; } function getSize(sizes) { diff --git a/modules/nasmediaAdmixerBidAdapter.md b/modules/nasmediaAdmixerBidAdapter.md index aa72b7967f8..44797e413a8 100644 --- a/modules/nasmediaAdmixerBidAdapter.md +++ b/modules/nasmediaAdmixerBidAdapter.md @@ -1,7 +1,7 @@ # Overview ``` -Module Name: NasmeidaAdmixer Bidder Adapter +Module Name: NasmediaAdmixer Bidder Adapter Module Type: Bidder Adapter Maintainer: prebid@nasmedia.co.kr ``` From 27758400f51b2f32f14b81047fcd285dee565fec Mon Sep 17 00:00:00 2001 From: rxRTB <34483140+prebidRxRTB@users.noreply.github.com> Date: Fri, 23 Feb 2018 00:33:19 +0300 Subject: [PATCH 0140/1594] [Edit BidAdapter] rxrtb adapter for Perbid.js 1.0 (#2182) * Add: rxrtb prebidAdapter * Update: params for test * Update: code format * Update: code format * Update: code format * Fix param check * Update rxrtbBidAdapter.js --- modules/rxrtbBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rxrtbBidAdapter.js b/modules/rxrtbBidAdapter.js index c82f1f9b1db..37aa20b68cd 100644 --- a/modules/rxrtbBidAdapter.js +++ b/modules/rxrtbBidAdapter.js @@ -68,7 +68,7 @@ function getDomain(url) { function makePrebidRequest(req) { let host = req.params.host || DEFAULT_HOST; - let url = window.location.protocol + '//' + host + '/dsp?id=' + req.params.id + '&token=' + req.params.token; + let url = '//' + host + '/dsp?id=' + req.params.id + '&token=' + req.params.token; let reqData = makeRtbRequest(req); return { method: 'POST', From 31b0e926488754e22b940b13f6b72fe66cbe68b5 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 22 Feb 2018 17:05:14 -0700 Subject: [PATCH 0141/1594] only count bid timeouts if bidder didn't call done. fixes #2146 (#2154) --- src/auction.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/auction.js b/src/auction.js index b8098d1faf4..5f8d364f855 100644 --- a/src/auction.js +++ b/src/auction.js @@ -488,7 +488,7 @@ function groupByPlacement(bidsByPlacement, bid) { } /** - * Returns a list of bids that we haven't received a response yet + * Returns a list of bids that we haven't received a response yet where the bidder did not call done * @param {BidRequest[]} bidderRequests List of bids requested for auction instance * @param {BidReceived[]} bidsReceived List of bids received for auction instance * @@ -501,7 +501,8 @@ function groupByPlacement(bidsByPlacement, bid) { * @return {Array} List of bids that Prebid hasn't received a response for */ function getTimedOutBids(bidderRequests, bidsReceived) { - const bidRequestedCodes = bidderRequests + const bidRequestedWithoutDoneCodes = bidderRequests + .filter(bidderRequest => !bidderRequest.doneCbCallCount) .map(bid => bid.bidderCode) .filter(uniques); @@ -509,7 +510,7 @@ function getTimedOutBids(bidderRequests, bidsReceived) { .map(bid => bid.bidder) .filter(uniques); - const timedOutBidderCodes = bidRequestedCodes + const timedOutBidderCodes = bidRequestedWithoutDoneCodes .filter(bidder => !includes(bidReceivedCodes, bidder)); const timedOutBids = bidderRequests From 737ca041e3bef6b766c3e4f3d2c608a182376bbe Mon Sep 17 00:00:00 2001 From: danmarketplace <34161426+danmarketplace@users.noreply.github.com> Date: Fri, 23 Feb 2018 03:08:55 +0300 Subject: [PATCH 0142/1594] Change bidderCode for DAN Marketplace Bid Adapter (#2183) * Make Bid Adapter for Dentsu Aegis Network Marketplace * Update DAN_Marketplace adapter * Rename danmarketplaceBidAdapter into danmarketBidAdapter --- ...ceBidAdapter.js => danmarketBidAdapter.js} | 4 ++-- ...ceBidAdapter.md => danmarketBidAdapter.md} | 4 ++-- ...er_spec.js => danmarketBidAdapter_spec.js} | 24 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) rename modules/{danmarketplaceBidAdapter.js => danmarketBidAdapter.js} (97%) rename modules/{danmarketplaceBidAdapter.md => danmarketBidAdapter.md} (90%) rename test/spec/modules/{danmarketplaceBidAdapter_spec.js => danmarketBidAdapter_spec.js} (94%) diff --git a/modules/danmarketplaceBidAdapter.js b/modules/danmarketBidAdapter.js similarity index 97% rename from modules/danmarketplaceBidAdapter.js rename to modules/danmarketBidAdapter.js index 24b3682042e..619bd893ea2 100644 --- a/modules/danmarketplaceBidAdapter.js +++ b/modules/danmarketBidAdapter.js @@ -1,6 +1,6 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; -const BIDDER_CODE = 'danmarketplace'; +const BIDDER_CODE = 'danmarket'; const ENDPOINT_URL = '//ads.danmarketplace.com/hb'; const TIME_TO_LIVE = 360; const ADAPTER_SYNC_URL = '//ads.danmarketplace.com/push_sync'; @@ -24,7 +24,7 @@ const LOG_ERROR_MESS = { export const spec = { code: BIDDER_CODE, - aliases: ['DANMarketplace', 'DAN_Marketplace'], + aliases: ['DANMarketplace', 'DAN_Marketplace', 'danmarketplace'], isBidRequestValid: function(bid) { return !!bid.params.uid; diff --git a/modules/danmarketplaceBidAdapter.md b/modules/danmarketBidAdapter.md similarity index 90% rename from modules/danmarketplaceBidAdapter.md rename to modules/danmarketBidAdapter.md index 263385949bd..8ddc83d2cf6 100755 --- a/modules/danmarketplaceBidAdapter.md +++ b/modules/danmarketBidAdapter.md @@ -16,7 +16,7 @@ Module that connects to DAN Marketplace demand source to fetch bids. sizes: [[300, 250]], bids: [ { - bidder: "danmarketplace", + bidder: "danmarket", params: { uid: '4', priceType: 'gross' // by default is 'net' @@ -28,7 +28,7 @@ Module that connects to DAN Marketplace demand source to fetch bids. sizes: [[728, 90]], bids: [ { - bidder: "danmarketplace", + bidder: "danmarket", params: { uid: 5, priceType: 'gross' diff --git a/test/spec/modules/danmarketplaceBidAdapter_spec.js b/test/spec/modules/danmarketBidAdapter_spec.js similarity index 94% rename from test/spec/modules/danmarketplaceBidAdapter_spec.js rename to test/spec/modules/danmarketBidAdapter_spec.js index ee7f844ae98..d1b86d1bf53 100644 --- a/test/spec/modules/danmarketplaceBidAdapter_spec.js +++ b/test/spec/modules/danmarketBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec } from 'modules/danmarketplaceBidAdapter'; +import { spec } from 'modules/danmarketBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; describe('DAN_Marketplace Adapter', function () { @@ -13,7 +13,7 @@ describe('DAN_Marketplace Adapter', function () { describe('isBidRequestValid', () => { let bid = { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '4' }, @@ -41,7 +41,7 @@ describe('DAN_Marketplace Adapter', function () { describe('buildRequests', () => { let bidRequests = [ { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '5' }, @@ -52,7 +52,7 @@ describe('DAN_Marketplace Adapter', function () { 'auctionId': '1d1a030790a475', }, { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '5' }, @@ -63,7 +63,7 @@ describe('DAN_Marketplace Adapter', function () { 'auctionId': '1d1a030790a475', }, { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '6' }, @@ -130,7 +130,7 @@ describe('DAN_Marketplace Adapter', function () { it('should get correct bid response', () => { const bidRequests = [ { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '4' }, @@ -164,7 +164,7 @@ describe('DAN_Marketplace Adapter', function () { it('should get correct multi bid response', () => { const bidRequests = [ { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '4' }, @@ -175,7 +175,7 @@ describe('DAN_Marketplace Adapter', function () { 'auctionId': '1fa09aee5c8c99', }, { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '5' }, @@ -186,7 +186,7 @@ describe('DAN_Marketplace Adapter', function () { 'auctionId': '1fa09aee5c8c99', }, { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '4' }, @@ -244,7 +244,7 @@ describe('DAN_Marketplace Adapter', function () { it('handles wrong and nobid responses', () => { const bidRequests = [ { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '6' }, @@ -255,7 +255,7 @@ describe('DAN_Marketplace Adapter', function () { 'auctionId': '1fa09aee5c84d34', }, { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '7' }, @@ -266,7 +266,7 @@ describe('DAN_Marketplace Adapter', function () { 'auctionId': '1fa09aee5c84d34', }, { - 'bidder': 'danmarketplace', + 'bidder': 'danmarket', 'params': { 'uid': '8' }, From 0ddebdf7b8033a6a158b8041234fffc6eb125ae7 Mon Sep 17 00:00:00 2001 From: jeremyAdyoulike Date: Fri, 23 Feb 2018 11:09:44 +0100 Subject: [PATCH 0143/1594] Update Adyoulike Adapter to prebid 1.0 (#2077) * feat(adyoulikeAdapter): update adapter * fix(payload): fix height and width request keys * fix(Request): set credentials to false --- modules/adyoulikeBidAdapter.js | 197 ++++++++++++ modules/adyoulikeBidAdapter.md | 29 ++ test/spec/modules/adyoulikeBidAdapter_spec.js | 300 ++++++++++++++++++ 3 files changed, 526 insertions(+) create mode 100644 modules/adyoulikeBidAdapter.js create mode 100644 modules/adyoulikeBidAdapter.md create mode 100644 test/spec/modules/adyoulikeBidAdapter_spec.js diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js new file mode 100644 index 00000000000..a73421f7ca5 --- /dev/null +++ b/modules/adyoulikeBidAdapter.js @@ -0,0 +1,197 @@ +import * as utils from 'src/utils'; +import { format } from 'src/url'; +// import { config } from 'src/config'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const VERSION = '1.0'; +const BIDDER_CODE = 'adyoulike'; +const DEFAULT_DC = 'hb-api'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['ayl'], // 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) { + const sizes = getSize(bid.sizes); + if (!bid.params || !bid.params.placement || !sizes.width || !sizes.height) { + return false; + } + return true; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {bidderRequest} - bidderRequest.bids[] is an array of AdUnits and bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (bidderRequest) { + let dcHostname = getHostname(bidderRequest); + const payload = { + Version: VERSION, + Bids: bidderRequest.reduce((accumulator, bid) => { + let size = getSize(bid.sizes); + accumulator[bid.bidId] = {}; + accumulator[bid.bidId].PlacementID = bid.params.placement; + accumulator[bid.bidId].TransactionID = bid.transactionId; + accumulator[bid.bidId].Width = size.width; + accumulator[bid.bidId].Height = size.height; + return accumulator; + }, {}), + PageRefreshed: getPageRefreshed() + }; + const data = JSON.stringify(payload); + const options = { + withCredentials: false + }; + + return { + method: 'POST', + url: createEndpoint(dcHostname), + data, + options + }; + }, + /** + * 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, bidRequest) { + const bidResponses = []; + // For this adapter, serverResponse is a list + serverResponse.body.forEach(response => { + const bid = createBid(response); + if (bid) { + bidResponses.push(bid); + } + }); + return bidResponses; + } +} + +/* Get hostname from bids */ +function getHostname(bidderRequest) { + let dcHostname = bidderRequest.find(bid => bid.params.DC); + if (dcHostname) { + return ('-' + dcHostname.params.DC); + } + return ''; +} + +/* Get current page referrer url */ +function getReferrerUrl() { + let referer = ''; + if (window.self !== window.top) { + try { + referer = window.top.document.referrer; + } catch (e) { } + } else { + referer = document.referrer; + } + return referer; +} + +/* Get current page canonical url */ +function getCanonicalUrl() { + let link; + if (window.self !== window.top) { + try { + link = window.top.document.head.querySelector('link[rel="canonical"][href]'); + } catch (e) { } + } else { + link = document.head.querySelector('link[rel="canonical"][href]'); + } + + if (link) { + return link.href; + } + return ''; +} + +/* Get information on page refresh */ +function getPageRefreshed() { + try { + if (performance && performance.navigation) { + return performance.navigation.type === performance.navigation.TYPE_RELOAD; + } + } catch (e) { } + return false; +} + +/* Create endpoint url */ +function createEndpoint(host) { + return format({ + protocol: (document.location.protocol === 'https:') ? 'https' : 'http', + host: `${DEFAULT_DC}${host}.omnitagjs.com`, + pathname: '/hb-api/prebid/v1', + search: createEndpointQS() + }); +} + +/* Create endpoint query string */ +function createEndpointQS() { + const qs = {}; + + const ref = getReferrerUrl(); + if (ref) { + qs.RefererUrl = encodeURIComponent(ref); + } + + const can = getCanonicalUrl(); + if (can) { + qs.CanonicalUrl = encodeURIComponent(can); + } + + return qs; +} + +/* Get parsed size from request size */ +function getSize(requestSizes) { + const parsed = {}; + const size = utils.parseSizesInput(requestSizes)[0]; + + if (typeof size !== 'string') { + return parsed; + } + + const parsedSize = size.toUpperCase().split('X'); + const width = parseInt(parsedSize[0], 10); + if (width) { + parsed.width = width; + } + + const height = parseInt(parsedSize[1], 10); + if (height) { + parsed.height = height; + } + + return parsed; +} + +/* Create bid from response */ +function createBid(response) { + if (!response || !response.Ad) { + return + } + + return { + requestId: response.BidID, + bidderCode: spec.code, + width: response.Width, + height: response.Height, + ad: response.Ad, + ttl: 3600, + creativeId: response.CreativeID, + cpm: response.Price, + netRevenue: true, + currency: 'USD' + }; +} + +registerBidder(spec); diff --git a/modules/adyoulikeBidAdapter.md b/modules/adyoulikeBidAdapter.md new file mode 100644 index 00000000000..120bee3bcbb --- /dev/null +++ b/modules/adyoulikeBidAdapter.md @@ -0,0 +1,29 @@ +# Overview + +Module Name: Adyoulike Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@adyoulike.com + +# Description + +Module that connects to Adyoulike demand sources. +Banner formats are supported. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "adyoulike", + params: { + placement: 194f787b85c829fb8822cdaf1ae64435, + DC: 'fra01', // Optional for set the data center name + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js new file mode 100644 index 00000000000..cb9126619f2 --- /dev/null +++ b/test/spec/modules/adyoulikeBidAdapter_spec.js @@ -0,0 +1,300 @@ +import { expect } from 'chai'; +import { parse } from '../../../src/url'; + +import { spec } from 'modules/adyoulikeBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('Adyoulike Adapter', () => { + const canonicalUrl = 'http://canonical.url/?t=%26'; + const defaultDC = 'hb-api'; + const bidderCode = 'adyoulike'; + const bidRequestWithEmptyPlacement = [ + { + 'bidId': 'bid_id_0', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-0', + 'params': {}, + 'sizes': '300x250' + } + ]; + const bidRequestWithEmptySizes = { + 'bidderCode': 'adyoulike', + 'bids': [ + { + 'bidId': 'bid_id_0', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-0', + 'params': { + 'placement': 'placement_0' + }, + 'transactionId': 'bid_id_0_transaction_id' + } + ], + }; + + const bidRequestWithSinglePlacement = [ + { + 'bidId': 'bid_id_0', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-0', + 'params': { + 'placement': 'placement_0' + }, + 'sizes': '300x250', + 'transactionId': 'bid_id_0_transaction_id' + } + ]; + + const bidRequestWithDCPlacement = [ + { + 'bidId': 'bid_id_0', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-0', + 'params': { + 'placement': 'placement_0', + 'DC': 'fra01' + }, + 'sizes': '300x250', + 'transactionId': 'bid_id_0_transaction_id' + } + ]; + + const bidRequestMultiPlacements = [ + { + 'bidId': 'bid_id_0', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-0', + 'params': { + 'placement': 'placement_0' + }, + 'sizes': '300x250', + 'transactionId': 'bid_id_0_transaction_id' + }, + { + 'bidId': 'bid_id_1', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-1', + 'params': { + 'placement': 'placement_1' + }, + 'sizes': [[300, 600]], + 'transactionId': 'bid_id_1_transaction_id' + }, + { + 'bidId': 'bid_id_2', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-2', + 'params': {}, + 'sizes': '300x400', + 'transactionId': 'bid_id_2_transaction_id' + }, + { + 'bidId': 'bid_id_3', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-3', + 'params': { + 'placement': 'placement_3' + }, + 'transactionId': 'bid_id_3_transaction_id' + } + ]; + + const responseWithEmptyPlacement = [ + { + 'Placement': 'placement_0' + } + ]; + const responseWithSinglePlacement = [ + { + 'BidID': 'bid_id_0', + 'Placement': 'placement_0', + 'Ad': 'placement_0', + 'Price': 0.5, + 'Height': 300, + 'Width': 300, + } + ]; + const responseWithMultiplePlacements = [ + { + 'BidID': 'bid_id_0', + 'Placement': 'placement_0', + 'Ad': 'placement_0', + 'Price': 0.5, + 'Height': 300, + 'Width': 300, + }, + { + 'BidID': 'bid_id_1', + 'Placement': 'placement_1', + 'Ad': 'placement_1', + 'Price': 0.6, + 'Height': 300, + 'Width': 300, + } + ]; + const adapter = newBidder(spec); + + let getEndpoint = (dc = defaultDC) => `http://${dc}.omnitagjs.com/hb-api/prebid`; + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidId': 'bid_id_1', + 'bidder': 'adyoulike', + 'placementCode': 'adunit/hb-1', + 'params': { + 'placement': 'placement_1' + }, + 'sizes': [[300, 600]], + 'transactionId': 'bid_id_1_transaction_id' + }; + + 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.size; + + 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 = { + 'placement': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let canonicalQuery; + + beforeEach(() => { + let canonical = document.createElement('link'); + canonical.rel = 'canonical'; + canonical.href = canonicalUrl; + canonicalQuery = sinon.stub(window.top.document.head, 'querySelector'); + canonicalQuery.withArgs('link[rel="canonical"][href]').returns(canonical); + }); + + afterEach(() => { + canonicalQuery.restore(); + }); + + it('sends bid request to endpoint with single placement', () => { + const request = spec.buildRequests(bidRequestWithSinglePlacement); + const payload = JSON.parse(request.data); + + expect(request.url).to.contain(getEndpoint()); + expect(request.method).to.equal('POST'); + expect(request.url).to.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 single placement without canonical', () => { + canonicalQuery.restore(); + const request = spec.buildRequests(bidRequestWithSinglePlacement); + 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', () => { + const request = spec.buildRequests(bidRequestMultiPlacements); + const payload = JSON.parse(request.data); + expect(request.url).to.contain(getEndpoint()); + expect(request.method).to.equal('POST'); + + expect(request.url).to.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.Bids['bid_id_1'].PlacementID).to.be.equal('placement_1'); + expect(payload.Bids['bid_id_3'].PlacementID).to.be.equal('placement_3'); + + expect(payload.Bids['bid_id_0'].TransactionID).to.be.equal('bid_id_0_transaction_id'); + expect(payload.Bids['bid_id_1'].TransactionID).to.be.equal('bid_id_1_transaction_id'); + expect(payload.Bids['bid_id_3'].TransactionID).to.be.equal('bid_id_3_transaction_id'); + expect(payload.PageRefreshed).to.equal(false); + }); + + it('sends bid request to endpoint setted by parameters', () => { + const request = spec.buildRequests(bidRequestWithDCPlacement); + const payload = JSON.parse(request.data); + + expect(request.url).to.contain(getEndpoint(`${defaultDC}-fra01`)); + }); + }); + // + describe('interpretResponse', () => { + let serverResponse; + + beforeEach(() => { + serverResponse = { + body: {} + } + }); + + it('handles nobid responses', () => { + let response = [{ + BidID: '123dfsdf', + Attempt: '32344fdse1', + Placement: '12df1' + }]; + serverResponse.body = response; + let result = spec.interpretResponse(serverResponse, []); + expect(result).deep.equal([]); + }); + + it('receive reponse with single placement', () => { + serverResponse.body = responseWithSinglePlacement; + let result = spec.interpretResponse(serverResponse, bidRequestWithSinglePlacement); + + expect(result.length).to.equal(1); + expect(result[0].cpm).to.equal(0.5); + expect(result[0].ad).to.equal('placement_0'); + expect(result[0].width).to.equal(300); + expect(result[0].height).to.equal(300); + }); + + it('receive reponse with multiple placement', () => { + serverResponse.body = responseWithMultiplePlacements; + let result = spec.interpretResponse(serverResponse, bidRequestMultiPlacements); + + expect(result.length).to.equal(2); + + expect(result[0].bidderCode).to.equal(bidderCode); + expect(result[0].cpm).to.equal(0.5); + expect(result[0].ad).to.equal('placement_0'); + expect(result[0].width).to.equal(300); + expect(result[0].height).to.equal(300); + + expect(result[1].bidderCode).to.equal(bidderCode); + expect(result[1].cpm).to.equal(0.6); + expect(result[1].ad).to.equal('placement_1'); + expect(result[1].width).to.equal(300); + expect(result[1].height).to.equal(300); + }); + }); +}); From 37ead2712e869051c255ed6637b3530f3bb13754 Mon Sep 17 00:00:00 2001 From: Devastator Date: Fri, 23 Feb 2018 22:36:27 +0800 Subject: [PATCH 0144/1594] Update Innity Adapter to Prebid.js v1.0 (#2180) * Innity Adapter for Prebid.js 1.0 * Fix Innity Adapter Test Spec Error (#2180) * Fix utils.timestamp and remove userSyncs (#2180) --- modules/innityBidAdapter.js | 54 +++++++++++ modules/innityBidAdapter.md | 25 ++++++ test/spec/modules/innityBidAdapter_spec.js | 100 +++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 modules/innityBidAdapter.js create mode 100644 modules/innityBidAdapter.md create mode 100644 test/spec/modules/innityBidAdapter_spec.js diff --git a/modules/innityBidAdapter.js b/modules/innityBidAdapter.js new file mode 100644 index 00000000000..880af2b6112 --- /dev/null +++ b/modules/innityBidAdapter.js @@ -0,0 +1,54 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'innity'; +const ENDPOINT = location.protocol + '//as.innity.com/synd/'; + +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: function(bid) { + return !!(bid.params && bid.params.pub && bid.params.zone); + }, + buildRequests: function(validBidRequests) { + return validBidRequests.map(bidRequest => { + let parseSized = utils.parseSizesInput(bidRequest.sizes); + let arrSize = parseSized[0].split('x'); + return { + method: 'GET', + url: ENDPOINT, + data: { + cb: utils.timestamp(), + ver: 2, + hb: 1, + output: 'js', + pub: bidRequest.params.pub, + zone: bidRequest.params.zone, + url: encodeURIComponent(utils.getTopWindowUrl()), + width: arrSize[0], + height: arrSize[1], + vpw: window.screen.width, + vph: window.screen.height, + callback: 'json', + callback_uid: bidRequest.bidId, + auction: bidRequest.auctionId, + }, + }; + }); + }, + interpretResponse: function(serverResponse, request) { + const res = serverResponse.body; + const bidResponse = { + requestId: res.callback_uid, + cpm: parseFloat(res.cpm) / 100, + width: res.width, + height: res.height, + creativeId: res.creative_id, + currency: 'USD', + netRevenue: true, + ttl: 60, + ad: '' + res.tag, + }; + return [bidResponse]; + } +} +registerBidder(spec); diff --git a/modules/innityBidAdapter.md b/modules/innityBidAdapter.md new file mode 100644 index 00000000000..b359a591ce8 --- /dev/null +++ b/modules/innityBidAdapter.md @@ -0,0 +1,25 @@ +# Overview + +**Module Name**: Innity Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: engtat@innity.com + +# Description + +Innity Bidder Adapter for Prebid.js. + +# Test Parameters +``` + var adUnits = [{ + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250]], + bids: [{ + bidder: 'innity', + params: { + pub: 267, + zone: 62546 + } + }] + }]; + +``` \ No newline at end of file diff --git a/test/spec/modules/innityBidAdapter_spec.js b/test/spec/modules/innityBidAdapter_spec.js new file mode 100644 index 00000000000..87042ca6a6d --- /dev/null +++ b/test/spec/modules/innityBidAdapter_spec.js @@ -0,0 +1,100 @@ +import { expect } from 'chai'; +import { spec } from 'modules/innityBidAdapter'; + +describe('innityAdapterTest', () => { + describe('bidRequestValidity', () => { + it('bidRequest with pub ID and zone ID param', () => { + expect(spec.isBidRequestValid({ + bidder: 'innity', + params: { + 'pub': 267, + 'zone': 62546 + }, + })).to.equal(true); + }); + + it('bidRequest with no required params', () => { + expect(spec.isBidRequestValid({ + bidder: 'innity', + params: { + }, + })).to.equal(false); + }); + }); + + describe('bidRequest', () => { + const bidRequests = [{ + 'bidder': 'innity', + 'params': { + 'pub': 267, + 'zone': 62546 + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [300, 250], + 'bidId': '51ef8751f9aead', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }]; + + it('bidRequest HTTP method', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + }); + }); + + it('bidRequest data', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].data.pub).to.equal(267); + expect(requests[0].data.zone).to.equal(62546); + expect(requests[0].data.width).to.equal('300'); + expect(requests[0].data.height).to.equal('250'); + expect(requests[0].data.callback_uid).to.equal('51ef8751f9aead'); + }); + }); + + describe('interpretResponse', () => { + const bidRequest = { + 'method': 'GET', + 'url': 'https://as.innity.com/synd/?', + 'data': { + 'ver': 2, + 'hb': 1, + 'output': 'js', + 'pub': 267, + 'zone': 62546, + 'width': '300', + 'height': '250', + 'callback': 'json', + 'callback_uid': '51ef8751f9aead', + 'url': 'https://example.com', + 'cb': '', + } + }; + + const bidResponse = { + body: { + 'cpm': 100, + 'width': '300', + 'height': '250', + 'creative_id': '148186', + 'callback_uid': '51ef8751f9aead', + 'tag': '', + }, + headers: {} + }; + + it('result is correct', () => { + const result = spec.interpretResponse(bidResponse, bidRequest); + expect(result[0].requestId).to.equal('51ef8751f9aead'); + expect(result[0].cpm).to.equal(1); + expect(result[0].width).to.equal('300'); + expect(result[0].height).to.equal('250'); + expect(result[0].creativeId).to.equal('148186'); + expect(result[0].currency).to.equal('USD'); + expect(result[0].ttl).to.equal(60); + expect(result[0].ad).to.equal(''); + }); + }); +}); From 324d530aed8582b67aa73d9eac427e8e727b2634 Mon Sep 17 00:00:00 2001 From: piwanczak <36727380+piwanczak@users.noreply.github.com> Date: Fri, 23 Feb 2018 16:43:38 +0100 Subject: [PATCH 0145/1594] [NEW Adapter] RTBHouseBidAdapter (#2184) * [NEW Adapter] RTBHouseBidAdapter * remove trailing space in a comment --- modules/rtbhouseBidAdapter.js | 117 +++++++++++++++++ modules/rtbhouseBidAdapter.md | 31 +++++ test/spec/modules/rtbhouseBidAdapter_spec.js | 129 +++++++++++++++++++ 3 files changed, 277 insertions(+) create mode 100644 modules/rtbhouseBidAdapter.js create mode 100644 modules/rtbhouseBidAdapter.md create mode 100644 test/spec/modules/rtbhouseBidAdapter_spec.js diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js new file mode 100644 index 00000000000..181cf80d5e7 --- /dev/null +++ b/modules/rtbhouseBidAdapter.js @@ -0,0 +1,117 @@ +import * as utils from 'src/utils'; +import { BANNER } from 'src/mediaTypes'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'rtbhouse'; +const REGIONS = ['prebid-eu', 'prebid-us', 'prebid-asia']; +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 + +/** + * Helpers + */ + +function buildEndpointUrl(region) { + return 'https://' + region + '.' + ENDPOINT_URL; +} + +/** + * Produces an OpenRTBImpression from a slot config. + */ +function mapImpression(slot) { + return { + id: slot.bidId, + banner: mapBanner(slot), + tagid: slot.adUnitCode.toString(), + }; +} + +/** + * Produces an OpenRTB Banner object for the slot given. + */ +function mapBanner(slot) { + return { + w: slot.sizes[0][0], + h: slot.sizes[0][1], + format: mapSizes(slot.sizes) + }; +} + +/** + * Produce openRTB banner.format object + */ +function mapSizes(slot_sizes) { + const format = []; + slot_sizes.forEach(elem => { + format.push({ + w: elem[0], + h: elem[1] + }); + }); + return format; +} + +/** + * Produces an OpenRTB site object. + */ +function mapSite(validRequest) { + const pubId = validRequest && validRequest.length > 0 ? validRequest[0].params.publisherId : 'unknown'; + return { + publisher: { + id: pubId.toString(), + }, + page: utils.getTopWindowUrl(), + name: utils.getOrigin() + } +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: function (bid) { + return !!(REGIONS.includes(bid.params.region) && bid.params.publisherId); + }, + + buildRequests: function (validBidRequests) { + const request = { + id: validBidRequests[0].auctionId, + imp: validBidRequests.map(slot => mapImpression(slot)), + site: mapSite(validBidRequests), + cur: DEFAULT_CURRENCY_ARR, + test: validBidRequests[0].params.test || 0 + }; + return { + method: 'POST', + url: buildEndpointUrl(validBidRequests[0].params.region), + data: JSON.stringify(request) + }; + }, + interpretResponse: function (serverResponse, originalRequest) { + serverResponse = serverResponse.body; + const bids = []; + + if (utils.isArray(serverResponse)) { + serverResponse.forEach(serverBid => { + if (serverBid.price !== 0) { + const bid = { + requestId: serverBid.impid, + mediaType: BANNER, + cpm: serverBid.price, + creativeId: serverBid.adid, + ad: serverBid.adm, + width: serverBid.w, + height: serverBid.h, + ttl: 55, + netRevenue: true, + currency: 'USD' + }; + bids.push(bid); + } + }); + } + return bids; + } +}; + +registerBidder(spec); diff --git a/modules/rtbhouseBidAdapter.md b/modules/rtbhouseBidAdapter.md new file mode 100644 index 00000000000..47deed1a277 --- /dev/null +++ b/modules/rtbhouseBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +Module Name: RTB House Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@rtbhouse.com + +# Description + +Connects to RTB House unique demand. +Banner formats are supported. +Unique publisherId is required. +Please reach out to pmp@rtbhouse.com to receive your own + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "rtbhouse", + params: { + region: 'prebid-eu', + publisherId: 'PREBID_TEST_ID' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js new file mode 100644 index 00000000000..69bd3f40f72 --- /dev/null +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -0,0 +1,129 @@ +import { expect } from 'chai'; +import { spec } from 'modules/rtbhouseBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const REGIONS = ['prebid-eu', 'prebid-us', 'prebid-asia']; +const ENDPOINT_URL = 'creativecdn.com/bidder/prebid/bids'; + +/** + * Helpers + */ + +function buildEndpointUrl(region) { + return 'https://' + region + '.' + ENDPOINT_URL; +} + +/** + * endof Helpers + */ + +describe('RTBHouseAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'rtbhouse', + 'params': { + 'publisherId': 'PREBID_TEST', + 'region': 'prebid-eu' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }; + + 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 = { + 'someIncorrectParam': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'rtbhouse', + 'params': { + 'publisherId': 'PREBID_TEST', + 'region': 'prebid-eu', + 'test': 1 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + } + ]; + + it('should build test param into the request', () => { + let builtTestRequest = spec.buildRequests(bidRequests).data; + expect(JSON.parse(builtTestRequest).test).to.equal(1); + }); + + it('sends bid request to ENDPOINT via POST', () => { + let bidRequest = Object.assign([], bidRequests); + delete bidRequest[0].params.test; + + const request = spec.buildRequests(bidRequest); + expect(request.url).to.equal(buildEndpointUrl(bidRequest[0].params.region)); + expect(request.method).to.equal('POST'); + }); + }) + + describe('interpretResponse', () => { + let response = [{ + 'id': 'bidder_imp_identifier', + 'impid': '552b8922e28f27', + 'price': 0.5, + 'adid': 'Ad_Identifier', + 'adm': '', + 'adomain': ['rtbhouse.com'], + 'cid': 'Ad_Identifier', + 'w': 300, + 'h': 250 + }]; + + it('should get correct bid response', () => { + let expectedResponse = [ + { + 'requestId': '552b8922e28f27', + 'cpm': 0.5, + 'creativeId': 29681110, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true + } + ]; + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', () => { + let response = ''; + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result.length).to.equal(0); + }); + }); +}); From fd7b24a1c08c08078acf6f7aad648085087d3072 Mon Sep 17 00:00:00 2001 From: Miller Date: Fri, 23 Feb 2018 23:19:49 +0200 Subject: [PATCH 0146/1594] Add multiple bids request (#2136) * Vertamedia prebid.js adapter initial * sync * remove https * add http * remove let * fix typo * fix spaces * add descriptionUrl; remove log * fix getSize * add usege parseSizesInput * Add support for vastTag * Add moulty bid request; set vastUrl for bider; * update for vertamedia adapter to Prebid 1.0 * Add vertamedia md file * Add required fields * Remove defaults; fix md file; * add outstream mediaType support * add outstream mediaType support * Resolve conflicts * fix test * Add Vertamedia display adapter * remove Boolean convert for isBidRequestValid * Remove boolean convert for isBidRequestValid method; fix tests; fix typo * add display support for Vertamedia adapter; documentation update * update tests for VertamediaBidAdapter * add supportedMediaTypes * Add comments * Add moulty mediatypes support * cleanup logs * Add sending multiple sizes * add multiple bids reguest --- modules/vertamediaBidAdapter.js | 92 ++++++++++++------- .../spec/modules/vertamediaBidAdapter_spec.js | 12 +-- 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 238495f3966..5876f0b2e7e 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -5,6 +5,7 @@ import {Renderer} from 'src/Renderer'; import findIndex from 'core-js/library/fn/array/find-index'; const URL = '//hb2.vertamedia.com/auction/'; +const OUTSTREAM_SRC = '//player.vertamedia.com/outstream-unit/2.01/outstream.min.js'; const BIDDER_CODE = 'vertamedia'; const OUTSTREAM = 'outstream'; const DISPLAY = 'display'; @@ -22,14 +23,12 @@ export const spec = { * @param bidderRequest */ buildRequests: function (bidRequests, bidderRequest) { - return bidRequests.map((bid) => { - return { - data: prepareRTBRequestParams(bid), - bidderRequest, - method: 'GET', - url: URL - }; - }); + return { + data: bidToTag(bidRequests), + bidderRequest, + method: 'GET', + url: URL + }; }, /** @@ -40,49 +39,76 @@ export const spec = { */ interpretResponse: function (serverResponse, {bidderRequest}) { serverResponse = serverResponse.body; - const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; - let bids = []; - if (isInvalidValidResp) { - let extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; - let errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; + if (!utils.isArray(serverResponse)) { + return parseRTBResponse(serverResponse, bidderRequest); + } - utils.logError(errorMessage); + serverResponse.forEach(serverBidResponse => { + bids = utils.flatten(bids, parseRTBResponse(serverBidResponse, bidderRequest)); + }); - return bids; - } + return bids; + } +}; - serverResponse.bids.forEach(serverBid => { - const requestId = findIndex(bidderRequest.bids, (bidRequest) => { - return bidRequest.bidId === serverBid.requestId; - }); +function parseRTBResponse(serverResponse, bidderRequest) { + const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; - if (serverBid.cpm !== 0 && requestId !== -1) { - const bid = createBid(serverBid, getMediaType(bidderRequest.bids[requestId])); + let bids = []; - bids.push(bid); - } - }); + if (isInvalidValidResp) { + let extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; + + utils.logError(errorMessage); return bids; } -}; + + serverResponse.bids.forEach(serverBid => { + const requestId = findIndex(bidderRequest.bids, (bidRequest) => { + return bidRequest.bidId === serverBid.requestId; + }); + + if (serverBid.cpm !== 0 && requestId !== -1) { + const bid = createBid(serverBid, getMediaType(bidderRequest.bids[requestId])); + + bids.push(bid); + } + }); + + return bids; +} + +function bidToTag(bidRequests) { + let tag = { + domain: utils.getTopWindowLocation().hostname + }; + + for (let i = 0, length = bidRequests.length; i < length; i++) { + Object.assign(tag, prepareRTBRequestParams(i, bidRequests[i])); + } + + return tag; +} /** * Parse mediaType + * @param _index {number} * @param bid {object} * @returns {object} */ -function prepareRTBRequestParams(bid) { +function prepareRTBRequestParams(_index, bid) { const mediaType = utils.deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY; + const index = !_index ? '' : `${_index + 1}`; return { - domain: utils.getTopWindowLocation().hostname, - callbackId: bid.bidId, - aid: bid.params.aid, - ad_type: mediaType, - sizes: utils.parseSizesInput(bid.sizes).join() + ['callbackId' + index]: bid.bidId, + ['aid' + index]: bid.params.aid, + ['ad_type' + index]: mediaType, + ['sizes' + index]: utils.parseSizesInput(bid.sizes).join() }; } @@ -146,7 +172,7 @@ function createBid(bidResponse, mediaType) { function newRenderer(requestId) { const renderer = Renderer.install({ id: requestId, - url: '//player.vertamedia.com/outstream-unit/2.01/outstream.min.js', + url: OUTSTREAM_SRC, loaded: false }); diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 32353b0097e..271f1f2d04a 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -125,17 +125,17 @@ describe('vertamediaBidAdapter', () => { const videoRequest = spec.buildRequests(videoBidRequests, {}); it('sends bid request to ENDPOINT via GET', () => { - expect(videoRequest[0].method).to.equal('GET'); - expect(displayRequest[0].method).to.equal('GET'); + expect(videoRequest.method).to.equal('GET'); + expect(displayRequest.method).to.equal('GET'); }); it('sends bid request to correct ENDPOINT', () => { - expect(videoRequest[0].url).to.equal(ENDPOINT); - expect(displayRequest[0].url).to.equal(ENDPOINT); + expect(videoRequest.url).to.equal(ENDPOINT); + expect(displayRequest.url).to.equal(ENDPOINT); }); it('sends correct video bid parameters', () => { - const bid = Object.assign({}, videoRequest[0].data); + const bid = Object.assign({}, videoRequest.data); delete bid.domain; const eq = { @@ -149,7 +149,7 @@ describe('vertamediaBidAdapter', () => { }); it('sends correct display bid parameters', () => { - const bid = Object.assign({}, displayRequest[0].data); + const bid = Object.assign({}, displayRequest.data); delete bid.domain; const eq = { From 9d557196ca28d6d587313baee969c55f879aa9bf Mon Sep 17 00:00:00 2001 From: Mohit Patil <13765991+mohit546@users.noreply.github.com> Date: Sat, 24 Feb 2018 05:13:35 +0530 Subject: [PATCH 0147/1594] Update Vertoz adapter for Prebid 1.0 (#2104) --- modules/vertozBidAdapter.js | 86 ++++++++++++++++ modules/vertozBidAdapter.md | 31 ++++++ test/spec/modules/vertozBidAdapter_spec.js | 112 +++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 modules/vertozBidAdapter.js create mode 100644 modules/vertozBidAdapter.md create mode 100644 test/spec/modules/vertozBidAdapter_spec.js diff --git a/modules/vertozBidAdapter.js b/modules/vertozBidAdapter.js new file mode 100644 index 00000000000..f3727714454 --- /dev/null +++ b/modules/vertozBidAdapter.js @@ -0,0 +1,86 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'vertoz'; +const BASE_URI = '//hb.vrtzads.com/vzhbidder/bid?'; + +export const spec = { + code: BIDDER_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 !!(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(bidRequestsArr) { + var bidRequests = bidRequestsArr || []; + return bidRequests.map(bid => { + let slotBidId = utils.getValue(bid, 'bidId'); + let cb = Math.round(new Date().getTime() / 1000); + let vzEndPoint = BASE_URI; + let reqParams = bid.params || {}; + let placementId = utils.getValue(reqParams, 'placementId'); + let cpm = utils.getValue(reqParams, 'cpmFloor'); + + if (utils.isEmptyStr(placementId)) { + utils.logError('missing params:', BIDDER_CODE, 'Enter valid vzPlacementId'); + return; + } + + let reqSrc = utils.getTopWindowLocation().href; + var vzReq = { + _vzPlacementId: placementId, + _rqsrc: reqSrc, + _cb: cb, + _slotBidId: slotBidId, + _cpm: cpm, + _cbn: '$$PREBID_GLOBAL$$' + }; + + let queryParamValue = encodeURIComponent(JSON.stringify(vzReq)); + + return { + method: 'POST', + data: {q: queryParamValue}, + url: vzEndPoint + }; + }) + }, + /** + * 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) { + var bidRespObj = serverResponse.body; + const bidResponses = []; + + if (bidRespObj.cpm) { + const bidResponse = { + requestId: bidRespObj.slotBidId, + cpm: Number(bidRespObj.cpm), + width: Number(bidRespObj.adWidth), + height: Number(bidRespObj.adHeight), + netRevenue: true, + mediaType: 'banner', + currency: 'USD', + dealId: null, + creativeId: null, + ttl: 300, + ad: bidRespObj.ad + utils.createTrackPixelHtml(decodeURIComponent(bidRespObj.nurl)) + }; + bidResponses.push(bidResponse); + } + return bidResponses; + } +} +registerBidder(spec); diff --git a/modules/vertozBidAdapter.md b/modules/vertozBidAdapter.md new file mode 100644 index 00000000000..100492da58b --- /dev/null +++ b/modules/vertozBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +``` +Module Name: Vertoz Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid-team@vertoz.com +``` + +# Description + +Connects to Vertoz exchange for bids. +Vertoz Bidder adapter supports Banner ads. +Use bidder code ```vertoz``` for all Vertoz traffic. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + sizes: [[300, 250], [300,600]], // a display size(s) + bids: [{ + bidder: 'vertoz', + params: { + placementId: 'VZ-HB-B784382V6C6G3C' + } + }] + }, +]; +``` + diff --git a/test/spec/modules/vertozBidAdapter_spec.js b/test/spec/modules/vertozBidAdapter_spec.js new file mode 100644 index 00000000000..a84fc4847f5 --- /dev/null +++ b/test/spec/modules/vertozBidAdapter_spec.js @@ -0,0 +1,112 @@ +import { expect } from 'chai'; +import { spec } from 'modules/vertozBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const BASE_URI = '//hb.vrtzads.com/vzhbidder/bid?'; + +describe('VertozAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'vertoz', + 'params': { + 'placementId': 'VZ-HB-B784382V6C6G3C' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'vertoz', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('sends bid request to ENDPOINT via POST', () => { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal(BASE_URI); + expect(request.method).to.equal('POST'); + }); + }); + + describe('interpretResponse', () => { + let response = { + 'vzhPlacementId': 'VZ-HB-B784382V6C6G3C', + 'bid': '76021e56-adaf-4114-b68d-ccacd1b3e551_1', + 'adWidth': '300', + 'adHeight': '250', + 'cpm': '0.16312590000000002', + 'ad': '', + 'slotBidId': '44b3fcfd24aa93', + 'nurl': '', + 'statusText': 'Vertoz:Success' + }; + + it('should get correct bid response', () => { + let expectedResponse = [ + { + 'requestId': '44b3fcfd24aa93', + 'cpm': 0.16312590000000002, + 'width': 300, + 'height': 250, + 'netRevenue': true, + 'mediaType': 'banner', + 'currency': 'USD', + 'dealId': null, + 'creativeId': null, + 'ttl': 300, + 'ad': '' + } + ]; + let bidderRequest; + let result = spec.interpretResponse({body: response}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + expect(result[0].cpm).to.not.equal(null); + }); + + it('handles nobid responses', () => { + let response = { + 'vzhPlacementId': 'VZ-HB-I617046VBGE3EH', + 'slotBidId': 'f00412ac86b79', + 'statusText': 'NO_BIDS' + }; + let bidderRequest; + + let result = spec.interpretResponse({body: response}); + expect(result.length).to.equal(0); + }); + }); +}); From c0ff4af8fd8d645e4e4d5f8b76ad3e104b9bd2db Mon Sep 17 00:00:00 2001 From: "Takaaki.Kojima" Date: Thu, 1 Mar 2018 08:06:02 +0900 Subject: [PATCH 0148/1594] AdGeneration bugfix (#2191) --- modules/adgenerationBidAdapter.js | 3 +-- test/spec/modules/adgenerationBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/adgenerationBidAdapter.js b/modules/adgenerationBidAdapter.js index 85b87d97a6e..99d69f3115a 100644 --- a/modules/adgenerationBidAdapter.js +++ b/modules/adgenerationBidAdapter.js @@ -110,8 +110,7 @@ export const spec = { function createAd(body, bidRequest) { let ad = body.ad; if (body.vastxml && body.vastxml.length > 0) { - ad = `
` + - appendChildToBody(ad, createAPVTag() + insertVASTMethod(bidRequest.bidId, body.vastxml)); + ad = `
${createAPVTag()}${insertVASTMethod(bidRequest.bidId, body.vastxml)}`; } ad = appendChildToBody(ad, body.beacon); if (removeWrapper(ad)) return removeWrapper(ad); diff --git a/test/spec/modules/adgenerationBidAdapter_spec.js b/test/spec/modules/adgenerationBidAdapter_spec.js index 7718d6fabac..23a48434536 100644 --- a/test/spec/modules/adgenerationBidAdapter_spec.js +++ b/test/spec/modules/adgenerationBidAdapter_spec.js @@ -313,7 +313,7 @@ describe('AdgenerationAdapter', () => { }); it('handles banner responses', () => { - serverResponse.results = [{ad: '↵ ↵ ↵ ↵ ↵
↵ '}]; + serverResponse.results = [{ad: '
'}]; delete serverResponse.native_ad; delete serverResponse.mediaType; delete bidRequests.bidRequest.mediaTypes; From f169a8514d0ae8b3fe70030c82ef545eaa17cac2 Mon Sep 17 00:00:00 2001 From: Cameron Hotchkies Date: Wed, 28 Feb 2018 15:25:00 -0800 Subject: [PATCH 0149/1594] RockYou Adapter: Update for multiple ad unit support (#2198) * RockYou Adapter: Added RockYou Adapter supporting Prebid 1.0 * RockYou Adapter: Removed extraneous imports, replaced a for loop w/ forEach for variable scoping. * RockYou Adapter: Updated the size handling to allow for multiple size definitions to be handled successfully * RockYou Adapter: Ad Size / Multiple Ad Unit update (#1) RockYou Adapter: * Updated to support size coming from the mediaTypes object, multiple AdUnit support * RockYou Adapter: Readme updates * RockYou Adapter: explicitly pass request.bidId in the response object * RockYou Adapter: Updated sync URL --- modules/rockyouBidAdapter.js | 107 +++++++++++--------- modules/rockyouBidAdapter.md | 17 ++-- test/spec/modules/rockyouBidAdapter_spec.js | 87 +++++++++++----- 3 files changed, 129 insertions(+), 82 deletions(-) diff --git a/modules/rockyouBidAdapter.js b/modules/rockyouBidAdapter.js index 975756d18bc..0748d6842a6 100644 --- a/modules/rockyouBidAdapter.js +++ b/modules/rockyouBidAdapter.js @@ -6,9 +6,9 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'rockyou'; const BASE_REQUEST_PATH = 'https://tas.rockyou.net/servlet/rotator/'; -const IFRAME_SYNC_URL = 'https://prebid.tex-sync.rockyou.net/usersync2/tas'; +const IFRAME_SYNC_URL = 'https://prebid.tas-sync.rockyou.net/usersync2/prebid'; const VAST_PLAYER_LOCATION = 'https://rya-static.rockyou.com/rya/js/PreBidPlayer.js'; -export const ROTATION_ZONE = 'openrtbprod'; +export const ROTATION_ZONE = 'prod'; let isBidRequestValid = (bid) => { return !!bid.params && !!bid.params.placementId; @@ -52,17 +52,27 @@ let extractValidSize = (bidRequest) => { let width = null; let height = null; - if (!utils.isEmpty(bidRequest.sizes)) { - // Ensure the size array is normalized - let conformingSize = utils.parseSizesInput(bidRequest.sizes); + let requestedSizes = []; + let mediaTypes = bidRequest.mediaTypes; + if (mediaTypes && ((mediaTypes.banner && mediaTypes.banner.sizes) || (mediaTypes.video && mediaTypes.video.playerSize))) { + if (mediaTypes.banner) { + requestedSizes = mediaTypes.banner.sizes; + } else { + requestedSizes = [mediaTypes.video.playerSize]; + } + } else if (!utils.isEmpty(bidRequest.sizes)) { + requestedSizes = bidRequest.sizes + } - if (!utils.isEmpty(conformingSize) && conformingSize[0] != null) { - // Currently only the first size is utilized - let splitSizes = conformingSize[0].split('x'); + // Ensure the size array is normalized + let conformingSize = utils.parseSizesInput(requestedSizes); - width = parseInt(splitSizes[0]); - height = parseInt(splitSizes[1]); - } + if (!utils.isEmpty(conformingSize) && conformingSize[0] != null) { + // Currently only the first size is utilized + let splitSizes = conformingSize[0].split('x'); + + width = parseInt(splitSizes[0]); + height = parseInt(splitSizes[1]); } return { @@ -109,22 +119,14 @@ let generateImpBody = (bidRequest) => { }; } -let generatePayload = (bidRequests) => { +let generatePayload = (bidRequest) => { // Generate the expected OpenRTB payload - let rootBidRequest = bidRequests[0]; - - let index = 1; - bidRequests.forEach((bidRequest) => { - bidRequest.index = index; - index += 1; - }) - let payload = { - id: determineOptimalRequestId(rootBidRequest), - site: buildSiteComponent(rootBidRequest), - device: buildDeviceComponent(rootBidRequest), - imp: bidRequests.map(generateImpBody) + id: determineOptimalRequestId(bidRequest), + site: buildSiteComponent(bidRequest), + device: buildDeviceComponent(bidRequest), + imp: [generateImpBody(bidRequest)] }; return JSON.stringify(payload); @@ -165,37 +167,42 @@ let buildRequests = (validBidRequests, requestRoot) => { let adUnitCode = null; let rendererOverride = null; + let results = []; // Due to the nature of how URLs are generated, there must // be at least one bid request present for this to function // correctly if (!utils.isEmpty(validBidRequests)) { - let headBidRequest = validBidRequests[0]; - - let serverLocations = overridableProperties(headBidRequest); - - // requestUrl is the full endpoint w/ relevant adspot paramters - let placementId = determineOptimalPlacementId(headBidRequest); - requestUrl = `${serverLocations.baseRequestPath}${placementId}/0/vo?z=${serverLocations.rotationZone}`; - - // requestPayload is the POST body JSON for the OpenRtb request - requestPayload = generatePayload(validBidRequests); - - mediaTypes = headBidRequest.mediaTypes; - adUnitCode = headBidRequest.adUnitCode; - rendererOverride = headBidRequest.rendererOverride; + results = validBidRequests.map( + bidRequest => { + let serverLocations = overridableProperties(bidRequest); + + // requestUrl is the full endpoint w/ relevant adspot paramters + let placementId = determineOptimalPlacementId(bidRequest); + requestUrl = `${serverLocations.baseRequestPath}${placementId}/0/vo?z=${serverLocations.rotationZone}`; + + // requestPayload is the POST body JSON for the OpenRtb request + requestPayload = generatePayload(bidRequest); + + mediaTypes = bidRequest.mediaTypes; + adUnitCode = bidRequest.adUnitCode; + rendererOverride = bidRequest.rendererOverride; + + return { + method: requestType, + type: requestType, + url: requestUrl, + data: requestPayload, + mediaTypes, + requestId: requestRoot.bidderRequestId, + bidId: bidRequest.bidId, + adUnitCode, + rendererOverride + }; + } + ); } - const result = { - method: requestType, - type: requestType, - url: requestUrl, - data: requestPayload, - mediaTypes, - requestId: requestRoot.bidderRequestId, - adUnitCode, - rendererOverride - }; - return result; + return results; }; let outstreamRender = (bid) => { @@ -308,7 +315,7 @@ let interpretResponse = (serverResponse, request) => { } let response = { - requestId: responseBody.id, + requestId: request.bidId, cpm: bid.price, width: bidWidth, height: bidHeight, diff --git a/modules/rockyouBidAdapter.md b/modules/rockyouBidAdapter.md index 8cc9ba371d7..1c6d2708b99 100644 --- a/modules/rockyouBidAdapter.md +++ b/modules/rockyouBidAdapter.md @@ -24,13 +24,16 @@ var adUnits = [ // Banner adUnit { code: 'banner-div', - sizes: [[720, 480]], + mediaTypes: { + banner: { + sizes: [[720, 480]] + } + }, - // Replace this object to test a new Adapter! bids: [{ bidder: 'rockyou', params: { - placementId: '4322' + placementId: '4954' } }] }, @@ -38,18 +41,16 @@ var adUnits = [ // Video (outstream) { code: 'video-outstream', - sizes: [[720, 480]], - - mediaType: 'video', mediaTypes: { video: { - context: 'outstream' + context: 'outstream', + playerSize: [720, 480] } }, bids: [{ bidder: 'rockyou', params: { - placementId: '4307' + placementId: '4957' } }] } diff --git a/test/spec/modules/rockyouBidAdapter_spec.js b/test/spec/modules/rockyouBidAdapter_spec.js index 8b38a333bca..7c06c41485c 100644 --- a/test/spec/modules/rockyouBidAdapter_spec.js +++ b/test/spec/modules/rockyouBidAdapter_spec.js @@ -33,9 +33,14 @@ describe('RockYouAdapter', () => { }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - 'sizes': [[320, 50], [300, 250], [300, 600]], + 'sizes': [[999, 888]], 'bidderRequestId': '418b37f85e772c', - 'auctionId': '18fd8b8b0bd757' + 'auctionId': '18fd8b8b0bd757', + 'mediaTypes': { + banner: { + 'sizes': [[320, 50], [300, 250], [300, 600]] + } + } }; it('successfully generates a URL', () => { @@ -49,9 +54,10 @@ describe('RockYouAdapter', () => { } ]; - let result = spec.buildRequests(bidRequests, { + let results = spec.buildRequests(bidRequests, { bidderRequestId: 'sample' }); + let result = results.pop(); expect(result.url).to.not.be.undefined; expect(result.url).to.not.be.null; @@ -66,9 +72,10 @@ describe('RockYouAdapter', () => { sampleBidRequest ]; - let result = spec.buildRequests(bidRequests, { + let results = spec.buildRequests(bidRequests, { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -82,9 +89,10 @@ describe('RockYouAdapter', () => { sampleBidRequest ]; - let result = spec.buildRequests(bidRequests, { + let results = spec.buildRequests(bidRequests, { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -95,33 +103,57 @@ describe('RockYouAdapter', () => { expect(userData).to.not.be.null; }); - it('generates multiple imp bodies', () => { + it('generates multiple requests with single imp bodies', () => { + const SECOND_PLACEMENT_ID = 'YYYPLACEMENTIDYYY'; + let firstBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + let secondBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + secondBidRequest.params.placementId = SECOND_PLACEMENT_ID; + let bidRequests = [ - sampleBidRequest, - sampleBidRequest + firstBidRequest, + secondBidRequest ]; - let result = spec.buildRequests(bidRequests, { + let results = spec.buildRequests(bidRequests, { bidderRequestId: 'sample' }); + expect(results instanceof Array).to.be.true; + expect(results.length).to.equal(2); + + let firstRequest = results[0]; + // Double encoded JSON - let payload = JSON.parse(result.data); + let firstPayload = JSON.parse(firstRequest.data); - expect(payload).to.not.be.null; - expect(payload.imp).to.not.be.null; - expect(payload.imp.length).to.equal(2); + expect(firstPayload).to.not.be.null; + expect(firstPayload.imp).to.not.be.null; + expect(firstPayload.imp.length).to.equal(1); + + expect(firstRequest.url).to.not.be.null; + expect(firstRequest.url.indexOf('ZZZPLACEMENTZZZ')).to.be.gt(0); + + let secondRequest = results[1]; + + // Double encoded JSON + let secondPayload = JSON.parse(secondRequest.data); + + expect(secondPayload).to.not.be.null; + expect(secondPayload.imp).to.not.be.null; + expect(secondPayload.imp.length).to.equal(1); + + expect(secondRequest.url).to.not.be.null; + expect(secondRequest.url.indexOf(SECOND_PLACEMENT_ID)).to.be.gt(0); }); it('generates a banner request as expected', () => { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); - localBidRequest.mediaTypes = { banner: {} }; - - let result = spec.buildRequests([localBidRequest], { + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -146,9 +178,10 @@ describe('RockYouAdapter', () => { localBidRequest.sizes = [320, 50]; localBidRequest.mediaTypes = { banner: {} }; - let result = spec.buildRequests([localBidRequest], { + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -171,11 +204,13 @@ describe('RockYouAdapter', () => { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.sizes = ['x', 'w']; - localBidRequest.mediaTypes = { banner: {} }; - let result = spec.buildRequests([localBidRequest], { + localBidRequest.mediaTypes = { banner: { sizes: ['y', 'z']} }; + + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -198,11 +233,14 @@ describe('RockYouAdapter', () => { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); - localBidRequest.mediaTypes = { video: {} }; + localBidRequest.mediaTypes = { video: { + playerSize: [326, 56] + } }; - let result = spec.buildRequests([localBidRequest], { + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -217,8 +255,8 @@ describe('RockYouAdapter', () => { let videoData = firstImp.video; - expect(videoData.w).to.equal(320); - expect(videoData.h).to.equal(50); + expect(videoData.w).to.equal(326); + expect(videoData.h).to.equal(56); }); it('propagates the mediaTypes object in the built request', () => { @@ -226,9 +264,10 @@ describe('RockYouAdapter', () => { localBidRequest.mediaTypes = { video: {} }; - let result = spec.buildRequests([localBidRequest], { + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); let mediaTypes = result.mediaTypes; From 1a3eeee6422266129c2f1032bfa07badc2d4cf98 Mon Sep 17 00:00:00 2001 From: moonshells <33766472+moonshells@users.noreply.github.com> Date: Thu, 1 Mar 2018 14:23:17 -0800 Subject: [PATCH 0150/1594] when position is not available, use "unknown" as the default position (#2205) --- modules/rubiconBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index dd796752a54..cbf27a184fd 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -138,7 +138,7 @@ export const spec = { let slotData = { site_id: params.siteId, zone_id: params.zoneId, - position: params.position || 'btf', + position: params.position || 'unknown', floor: parseFloat(params.floor) > 0.01 ? params.floor : 0.01, element_id: bidRequest.adUnitCode, name: bidRequest.adUnitCode, From f40508c15d60ebe8aaa244b5ef1a734e63c549ce Mon Sep 17 00:00:00 2001 From: Anthony Jose Bruscantini Date: Fri, 2 Mar 2018 06:52:55 -0800 Subject: [PATCH 0151/1594] ADSS-169 (#2187) --- modules/gumgumBidAdapter.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 2627b7417f5..3743859e4aa 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -75,6 +75,7 @@ function isBidRequestValid (bid) { switch (true) { case !!(params.inScreen): break; case !!(params.inSlot): break; + case !!(params.ICV): break; default: utils.logWarn(`[GumGum] No product selected for the placement ${adUnitCode}, please check your implementation.`); return false; @@ -107,12 +108,17 @@ function buildRequests (validBidRequests) { data.si = parseInt(params.inSlot, 10); data.pi = 3; } + if (params.ICV) { + data.ni = parseInt(params.ICV, 10); + data.pi = 5; + } bids.push({ id: bidId, tmax: timeout, tId: transactionId, pi: data.pi, + selector: params.selector, sizes: bidRequest.sizes, url: BID_ENDPOINT, method: 'GET', From cf13cc5f80c0ec25b53a68edd84c8e20c0c945f8 Mon Sep 17 00:00:00 2001 From: Anthony Jose Bruscantini Date: Fri, 2 Mar 2018 06:55:54 -0800 Subject: [PATCH 0152/1594] AT-5462 (#2188) * AT-5462 * AT-5462 Set param only if needed --- modules/gumgumBidAdapter.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 3743859e4aa..3ad8dd780ba 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -14,6 +14,8 @@ let browserParams = {}; function _getBrowserParams() { let topWindow let topScreen + let topUrl + let ggad if (browserParams.vw) { // we've already initialized browserParams, just return it. return browserParams @@ -22,6 +24,7 @@ function _getBrowserParams() { try { topWindow = global.top; topScreen = topWindow.screen; + topUrl = utils.getTopWindowUrl() } catch (error) { utils.logError(error); return browserParams @@ -32,10 +35,14 @@ function _getBrowserParams() { vh: topWindow.innerHeight, sw: topScreen.width, sh: topScreen.height, - pu: utils.getTopWindowUrl(), + pu: topUrl, ce: utils.cookiesAreEnabled(), dpr: topWindow.devicePixelRatio || 1 } + ggad = (topUrl.match(/#ggad=(\w+)$/) || [0, 0])[1] + if (ggad) { + browserParams[isNaN(ggad) ? 'eAdBuyId' : 'adBuyId'] = ggad + } return browserParams } From dfc3c8f41999e5a807f2cd6f0476b6d1e2b363a3 Mon Sep 17 00:00:00 2001 From: John Ellis Date: Fri, 2 Mar 2018 11:14:26 -0500 Subject: [PATCH 0153/1594] Yieldbot Prebid.js 1.0 adapter (#2135) * Yieldbot Prebid.js 1.0 adapter * Yieldbot Prebid.js 1.0 adapter - url_prefix protocol * Yieldbot Prebid.js 1.0 adapter - fix test * Yieldbot Prebid.js 1.0 adapter - fix test timeout * Yieldbot Prebid.js 1.0 adapter - refactor constants * Yieldbot Prebid.js 1.0 adapter - formatting * Yieldbot Prebid.js 1.0 adapter - setters --- modules/yieldbotBidAdapter.js | 604 ++++++++ modules/yieldbotBidAdapter.md | 192 +++ test/spec/e2e/gpt-examples/gpt_yieldbot.html | 241 ++++ test/spec/modules/yieldbotBidAdapter_spec.js | 1326 ++++++++++++++++++ 4 files changed, 2363 insertions(+) create mode 100644 modules/yieldbotBidAdapter.js create mode 100644 modules/yieldbotBidAdapter.md create mode 100644 test/spec/e2e/gpt-examples/gpt_yieldbot.html create mode 100644 test/spec/modules/yieldbotBidAdapter_spec.js diff --git a/modules/yieldbotBidAdapter.js b/modules/yieldbotBidAdapter.js new file mode 100644 index 00000000000..4616a31ea3d --- /dev/null +++ b/modules/yieldbotBidAdapter.js @@ -0,0 +1,604 @@ +import * as utils from 'src/utils'; +import { formatQS as buildQueryString } from '../src/url'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +/** + * @module {BidderSpec} YieldbotBidAdapter + * @description Adapter for requesting bids from Yieldbot + * @see BidderSpec + * @author [elljoh]{@link https://github.com/elljoh} + * @private + */ +export const YieldbotAdapter = { + _adapterLoaded: Date.now(), + _navigationStart: 0, + _version: 'pbjs-yb-0.0.1', + _bidRequestCount: 0, + _pageviewDepth: 0, + _lastPageviewId: '', + _sessionBlocked: false, + _isInitialized: false, + _sessionTimeout: 180000, + _userTimeout: 2592000000, + _cookieLabels: ['n', 'u', 'si', 'pvd', 'lpv', 'lpvi', 'c'], + + initialize: function() { + if (!this._isInitialized) { + this._pageviewDepth = this.pageviewDepth; + this._sessionBlocked = this.sessionBlocked; + this._isInitialized = true; + } + }, + + /** + * Adapter version + * pbjs-yb-x.x.x + * @returns {string} The adapter version string + * @memberof module:YieldbotBidAdapter + */ + get version() { + return this._version; + }, + + /** + * Is the user session blocked by the Yieldbot adserver.
+ * The Yieldbot adserver may return "block_session": true in a bid response. + * A session may be blocked for efficiency (i.e. Yieldbot has decided no to bid for the session), + * security and/or fraud detection. + * @returns {boolean} + * @readonly + * @memberof module:YieldbotBidAdapter + * @private + */ + get sessionBlocked() { + const cookieName = '__ybotn'; + const cookieValue = this.getCookie(cookieName); + const sessionBlocked = cookieValue ? parseInt(cookieValue, 10) || 0 : 0; + if (sessionBlocked) { + this.setCookie(cookieName, 1, this._sessionTimeout, '/'); + } + this._sessionBlocked = !!sessionBlocked; + return this._sessionBlocked; + }, + + set sessionBlocked(blockSession) { + const cookieName = '__ybotn'; + const sessionBlocked = blockSession ? 1 : 0; + this.setCookie(cookieName, sessionBlocked, this._sessionTimeout, '/'); + }, + + get userId() { + const cookieName = '__ybotu'; + let cookieValue = this.getCookie(cookieName); + if (!cookieValue) { + cookieValue = this.newId(); + this.setCookie(cookieName, cookieValue, this._userTimeout, '/'); + } + return cookieValue; + }, + + get sessionId() { + const cookieName = '__ybotsi'; + let cookieValue = this.getCookie(cookieName); + if (!cookieValue) { + cookieValue = this.newId(); + this.setCookie(cookieName, cookieValue, this._sessionTimeout, '/'); + } + return cookieValue; + }, + + get pageviewDepth() { + const cookieName = '__ybotpvd'; + let cookieValue = parseInt(this.getCookie(cookieName), 10) || 0; + cookieValue++; + this.setCookie(cookieName, cookieValue, this._sessionTimeout, '/'); + return cookieValue; + }, + + get lastPageviewId() { + const cookieName = '__ybotlpvi'; + let cookieValue = this.getCookie(cookieName); + return cookieValue || ''; + }, + + set lastPageviewId(id) { + const cookieName = '__ybotlpvi'; + this.setCookie(cookieName, id, this._sessionTimeout, '/'); + }, + + get lastPageviewTime() { + const cookieName = '__ybotlpv'; + let cookieValue = this.getCookie(cookieName); + return cookieValue ? parseInt(cookieValue, 10) : 0; + }, + + set lastPageviewTime(ts) { + const cookieName = '__ybotlpv'; + this.setCookie(cookieName, ts, this._sessionTimeout, '/'); + }, + + /** + * Get/set the request base url used to form bid, ad markup and impression requests. + * @param {string} [prefix] the bidder request base url + * @returns {string} the request base Url string + * @memberof module:YieldbotBidAdapter + */ + urlPrefix: function(prefix) { + const cookieName = '__ybotc'; + const pIdx = prefix ? prefix.indexOf(':') : -1; + const url = pIdx !== -1 ? document.location.protocol + prefix.substr(pIdx + 1) : null; + let cookieValue = url || this.getCookie(cookieName); + if (!cookieValue) { + cookieValue = '//i.yldbt.com/m/'; + } + this.setCookie(cookieName, cookieValue, this._sessionTimeout, '/'); + return cookieValue; + }, + + /** + * Bidder identifier code. + * @type {string} + * @constant + * @memberof module:YieldbotBidAdapter + */ + get code() { return 'yieldbot'; }, + + /** + * A list of aliases which should also resolve to this bidder. + * @type {string[]} + * @constant + * @memberof module:YieldbotBidAdapter + */ + get aliases() { return []; }, + + /** + * @property {MediaType[]} [supportedMediaTypes]: A list of Media Types which the adapter supports. + * @constant + * @memberof module:YieldbotBidAdapter + */ + get supportedMediaTypes() { return ['banner']; }, + + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @returns {boolean} True if this is a valid bid, and false otherwise. + * @memberof module:YieldbotBidAdapter + */ + isBidRequestValid: function(bid) { + let invalidSizeArray = false; + if (utils.isArray(bid.sizes)) { + const arr = bid.sizes.reduce((acc, cur) => acc.concat(cur), []).filter((item) => { + return !utils.isNumber(item); + }); + invalidSizeArray = arr.length !== 0; + } + const ret = bid && + bid.params && + utils.isStr(bid.params.psn) && + utils.isStr(bid.params.slot) && + !invalidSizeArray && + !!bid.params.psn && + !!bid.params.slot; + return ret; + }, + + /** + * 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. + * @memberof module:YieldbotBidAdapter + */ + buildRequests: function(bidRequests) { + const requests = []; + if (!this._optOut && !this.sessionBlocked) { + const searchParams = this.initBidRequestParams(); + this._bidRequestCount++; + + const pageviewIdToMap = searchParams['pvi']; + + const yieldbotSlotParams = this.getSlotRequestParams(pageviewIdToMap, bidRequests); + + searchParams['sn'] = yieldbotSlotParams['sn'] || ''; + searchParams['ssz'] = yieldbotSlotParams['ssz'] || ''; + + const bidUrl = this.urlPrefix() + yieldbotSlotParams.psn + '/v1/init'; + + searchParams['cts_ini'] = Date.now(); + requests.push({ + method: 'GET', + url: bidUrl, + data: searchParams, + yieldbotSlotParams: yieldbotSlotParams, + options: { + withCredentials: true, + customHeaders: { + Accept: 'application/json' + } + } + }); + } + return requests; + }, + + /** + * 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. + * @memberof module:YieldbotBidAdapter + */ + getUserSyncs: function(syncOptions, serverResponses) { + const userSyncs = []; + if (syncOptions.pixelEnabled && + serverResponses.length > 0 && + serverResponses[0].body && + serverResponses[0].body.user_syncs && + utils.isArray(serverResponses[0].body.user_syncs)) { + const responseUserSyncs = serverResponses[0].body.user_syncs; + responseUserSyncs.forEach((pixel) => { + userSyncs.push({ + type: 'image', + url: pixel + }); + }); + } + return userSyncs; + }, + + /** + * @typeDef {YieldbotBid} YieldbotBid + * @type {object} + * @property {string} slot Yieldbot config param slot + * @property {string} cpm Yieldbot bid quantity/label + * @property {string} size Slot dimensions of the form <width>x<height> + * @memberof module:YieldbotBidAdapter + */ + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @param {BidRequest} bidRequest Request object submitted which produced the response. + * @return {Bid[]} An array of bids which were nested inside the server. + * @memberof module:YieldbotBidAdapter + */ + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + const responseBody = serverResponse && serverResponse.body ? serverResponse.body : {}; + this._optOut = responseBody.optout || false; + if (this._optOut) { + this.clearAllCookies(); + } + if (!this._optOut && !this._sessionBlocked) { + const slotBids = responseBody.slots && responseBody.slots.length > 0 ? responseBody.slots : []; + slotBids.forEach((bid) => { + if (bid.slot && bid.size && bid.cpm) { + const sizeParts = bid.size ? bid.size.split('x') : [1, 1]; + const width = sizeParts[0] || 1; + const height = sizeParts[1] || 1; + const cpm = parseInt(bid.cpm, 10) / 100.0 || 0; + + const yieldbotSlotParams = bidRequest.yieldbotSlotParams || null; + const ybBidId = bidRequest.data['pvi']; + const paramKey = `${ybBidId}:${bid.slot}:${bid.size || ''}`; + const bidIdMap = yieldbotSlotParams && yieldbotSlotParams.bidIdMap ? yieldbotSlotParams.bidIdMap : {}; + const requestId = bidIdMap[paramKey] || ''; + + const urlPrefix = this.urlPrefix(responseBody.url_prefix); + const tagObject = this.buildAdCreativeTag(urlPrefix, bid, bidRequest); + const bidResponse = { + requestId: requestId, + cpm: cpm, + width: width, + height: height, + creativeId: tagObject.creativeId, + currency: 'USD', + netRevenue: true, + ttl: this._sessionTimeout / 1000, // [s] + ad: tagObject.ad + }; + bidResponses.push(bidResponse); + } + }); + } + return bidResponses; + }, + + /** + * Initializes search parameters common to both ad request and impression Urls. + * @param {string} adRequestId Yieldbot ad request identifier + * @param {BidRequest} bidRequest The request that is the source of the impression + * @returns {object} Search parameter key/value pairs + * @memberof module:YieldbotBidAdapter + */ + initAdRequestParams: function(adRequestId, bidRequest) { + let commonSearchParams = {}; + commonSearchParams['v'] = this._version; + commonSearchParams['vi'] = bidRequest.data.vi || this._version + '-vi'; + commonSearchParams['si'] = bidRequest.data.si || this._version + '-si'; + commonSearchParams['pvi'] = bidRequest.data.pvi || this._version + '-pvi'; + commonSearchParams['ri'] = adRequestId; + return commonSearchParams; + }, + + buildAdUrl: function(urlPrefix, publisherNumber, commonSearchParams, bid) { + const searchParams = Object.assign({}, commonSearchParams); + searchParams['cts_res'] = Date.now(); + searchParams['slot'] = bid.slot + ':' + bid.size; + searchParams['ioa'] = this.intersectionObserverAvailable(window); + + const queryString = buildQueryString(searchParams) || ''; + const adUrl = urlPrefix + + publisherNumber + + '/ad/creative.js?' + + queryString; + return adUrl; + }, + + buildImpressionUrl: function(urlPrefix, publisherNumber, commonSearchParams) { + const searchParams = Object.assign({}, commonSearchParams); + const queryString = buildQueryString(searchParams) || ''; + const impressionUrl = urlPrefix + + publisherNumber + + '/ad/impression.gif?' + + queryString; + return impressionUrl; + }, + + /** + * Object with Yieldbot ad markup representation and unique creative identifier. + * @typeDef {TagObject} TagObject + * @type {object} + * @property {string} creativeId bidder specific creative identifier for tracking at the source + * @property {string} ad ad creative markup + * @memberof module:YieldbotBidAdapter + */ + /** + * Builds the ad creative markup. + * @param {string} urlPrefix base url for Yieldbot requests + * @param {module:YieldbotBidAdapter.YieldbotBid} bid Bidder slot bid object + * @returns {module:YieldbotBidAdapter.TagObject} + * @memberof module:YieldbotBidAdapter + */ + buildAdCreativeTag: function(urlPrefix, bid, bidRequest) { + const ybotAdRequestId = this.newId(); + const commonSearchParams = this.initAdRequestParams(ybotAdRequestId, bidRequest); + const publisherNumber = bidRequest && bidRequest.yieldbotSlotParams ? bidRequest.yieldbotSlotParams.psn || '' : ''; + const adUrl = this.buildAdUrl(urlPrefix, publisherNumber, commonSearchParams, bid); + const impressionUrl = this.buildImpressionUrl(urlPrefix, publisherNumber, commonSearchParams); + + const htmlMarkup = `
`; + return { ad: htmlMarkup, creativeId: ybotAdRequestId }; + }, + + intersectionObserverAvailable: function (win) { + /* Ref: + * https://github.com/w3c/IntersectionObserver/blob/gh-pages/polyfill/intersection-observer.js#L23-L25 + */ + return win && + win.IntersectionObserver && + win.IntersectionObserverEntry && + win.IntersectionObserverEntry.prototype && + 'intersectionRatio' in win.IntersectionObserverEntry.prototype; + }, + + /** + * @typeDef {BidParams} BidParams + * @property {string} psn Yieldbot publisher customer number + * @property {object} searchParams bid request Url search parameters + * @property {object} searchParams.sn slot names + * @property {object} searchParams.szz slot sizes + * @memberof module:YieldbotBidAdapter + * @private + */ + /** + * Builds the common Yieldbot bid request Url query parameters.
+ * Slot bid related parameters are handled separately. The so-called common parameters + * here are request identifiers, page properties and user-agent attributes. + * @returns {object} query parameter key/value items + * @memberof module:YieldbotBidAdapter + */ + initBidRequestParams: function() { + const params = {}; + + params['cts_js'] = this._adapterLoaded; + params['cts_ns'] = this._navigationStart; + params['v'] = this._version; + + const userId = this.userId; + const sessionId = this.sessionId; + const pageviewId = this.newId(); + const currentBidTime = Date.now(); + const lastBidTime = this.lastPageviewTime; + const lastBidId = this.lastPageviewId; + this.lastPageviewTime = currentBidTime; + this.lastPageviewId = pageviewId; + params['vi'] = userId; + params['si'] = sessionId; + params['pvd'] = this._pageviewDepth; + params['pvi'] = pageviewId; + params['lpv'] = lastBidTime; + params['lpvi'] = lastBidId; + params['bt'] = this._bidRequestCount === 0 ? 'init' : 'refresh'; + + params['ua'] = navigator.userAgent; + params['np'] = navigator.platform; + params['la'] = + navigator.browserLanguage ? navigator.browserLanguage : navigator.language; + params['to'] = + (new Date()).getTimezoneOffset() / 60; + params['sd'] = + window.screen.width + 'x' + window.screen.height; + + params['lo'] = utils.getTopWindowUrl(); + params['r'] = utils.getTopWindowReferrer(); + + params['e'] = ''; + + return params; + }, + + /** + * Bid mapping key to the Prebid internal bidRequestId
+ * Format {pageview id}:{slot name}:{width}x{height} + * @typeDef {BidRequestKey} BidRequestKey + * @type {string} + * @example "jbgxsxqxyxvqm2oud7:leaderboard:728x90" + * @memberof module:YieldbotBidAdapter + */ + + /** + * Internal Yieldbot adapter bid and ad markup request state + *
+ * When interpreting a server response, the associated requestId is lookeded up + * in this map when creating a {@link Bid} response object. + * @typeDef {BidRequestMapping} BidRequestMapping + * @type {object} + * @property {Object.} {*} Yieldbot bid to requestId mapping item + * @memberof module:YieldbotBidAdapter + * @example + * { + * "jbgxsxqxyxvqm2oud7:leaderboard:728x90": "2b7e31676ce17", + * "jbgxsxqxyxvqm2oud7:medrec:300x250": "2b7e31676cd89", + * "jcrvvd6eoileb8w8ko:medrec:300x250": "2b7e316788ca7" + * } + * @memberof module:YieldbotBidAdapter + */ + + /** + * Rationalized set of Yieldbot bids for adUnits and mapping to respective Prebid.js bidId. + * @typeDef {BidSlots} BidSlots + * @property {string} psn Yieldbot publisher site identifier taken from bidder params + * @property {string} sn slot names + * @property {string} szz slot sizes + * @property {module:YieldbotBidAdapter.BidRequestMapping} bidIdMap Yieldbot bid to Prebid bidId mapping + * @memberof module:YieldbotBidAdapter + */ + + /** + * Gets unique slot name and sizes for query parameters object + * @param {string} pageviewId The Yieldbot bid request identifier + * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server + * @returns {module:YieldbotBidAdapter.BidSlots} Yieldbot specific bid parameters and bid identifier mapping + * @memberof module:YieldbotBidAdapter + */ + getSlotRequestParams: function(pageviewId, bidRequests) { + const params = {}; + const bidIdMap = {}; + bidRequests = bidRequests || []; + pageviewId = pageviewId || ''; + try { + const slotBids = {}; + bidRequests.forEach((bid) => { + params.psn = params.psn || bid.params.psn || ''; + utils.parseSizesInput(bid.sizes).forEach(sz => { + const slotName = bid.params.slot; + if (sz && (!slotBids[slotName] || !slotBids[slotName].some(existingSize => existingSize === sz))) { + slotBids[slotName] = slotBids[slotName] || []; + slotBids[slotName].push(sz); + const paramKey = pageviewId + ':' + slotName + ':' + sz; + bidIdMap[paramKey] = bid.bidId; + } + }); + }); + + const nm = []; + const sz = []; + for (let idx in slotBids) { + const slotName = idx; + const slotSizes = slotBids[idx]; + nm.push(slotName); + sz.push(slotSizes.join('.')); + } + params['sn'] = nm.join('|'); + params['ssz'] = sz.join('|'); + + params.bidIdMap = bidIdMap; + } catch (err) {} + return params; + }, + + getCookie: function(name) { + const cookies = document.cookie.split(';'); + let value = null; + for (let idx = 0; idx < cookies.length; idx++) { + const item = cookies[idx].split('='); + const itemName = item[0].replace(/^\s+|\s+$/g, ''); + if (itemName == name) { + value = item.length > 1 ? decodeURIComponent(item[1].replace(/^\s+|\s+$/g, '')) : null; + break; + } + } + return value; + }, + + setCookie: function(name, value, expireMillis, path, domain, secure) { + const expireTime = expireMillis ? new Date(Date.now() + expireMillis).toGMTString() : ''; + const dataValue = encodeURIComponent(value); + const docLocation = path || ''; + const pageDomain = domain || ''; + const httpsOnly = secure ? ';secure' : ''; + + const cookieStr = `${name}=${dataValue};expires=${expireTime};path=${docLocation};domain=${pageDomain}${httpsOnly}`; + document.cookie = cookieStr; + }, + + deleteCookie: function(name, path, domain, secure) { + return this.setCookie(name, '', -1, path, domain, secure); + }, + + /** + * Clear all first-party cookies. + */ + clearAllCookies: function() { + const labels = this._cookieLabels; + for (let idx = 0; idx < labels.length; idx++) { + const label = '__ybot' + labels[idx]; + this.deleteCookie(label); + } + }, + + /** + * Generate a new Yieldbot format id
+ * Base 36 and lowercase: <[ms] since epoch><[base36]{10}> + * @example "jbgxsyrlx9fxnr1hbl" + * @private + */ + newId: function() { + return (+new Date()).toString(36) + 'xxxxxxxxxx' + .replace(/[x]/g, function() { + return (0 | Math.random() * 36).toString(36); + }); + }, + + /** + * Create a delegate function with 'this' context of the YieldbotAdapter object. + * @param {object} instance Object for 'this' context in function apply + * @param {function} fn Function to execute in instance context + * @returns {function} the provided function bound to the instance context + * @memberof module:YieldbotBidAdapter + */ + createDelegate: function(instance, fn) { + var outerArgs = Array.prototype.slice.call(arguments, 2); + return function() { + return fn.apply(instance, outerArgs.length > 0 ? Array.prototype.slice.call(arguments, 0).concat(outerArgs) : arguments); + }; + } +}; + +YieldbotAdapter.initialize(); + +export const spec = { + code: YieldbotAdapter.code, + aliases: YieldbotAdapter.aliases, + supportedMediaTypes: YieldbotAdapter.supportedMediaTypes, + isBidRequestValid: YieldbotAdapter.createDelegate(YieldbotAdapter, YieldbotAdapter.isBidRequestValid), + buildRequests: YieldbotAdapter.createDelegate(YieldbotAdapter, YieldbotAdapter.buildRequests), + interpretResponse: YieldbotAdapter.createDelegate(YieldbotAdapter, YieldbotAdapter.interpretResponse), + getUserSyncs: YieldbotAdapter.createDelegate(YieldbotAdapter, YieldbotAdapter.getUserSyncs) +}; + +YieldbotAdapter._navigationStart = Date.now(); +registerBidder(spec); diff --git a/modules/yieldbotBidAdapter.md b/modules/yieldbotBidAdapter.md new file mode 100644 index 00000000000..db6f4dc100b --- /dev/null +++ b/modules/yieldbotBidAdapter.md @@ -0,0 +1,192 @@ +# Overview + +``` +Module Name: Yieldbot Bid Adapter +Module Type: Bidder Adapter +Maintainer: pubops@yieldbot.com +``` + +# Description +The Yieldbot Prebid.js bid adapter integrates Yieldbot demand to publisher inventory. + +# BaseAdapter Settings + +| Setting | Value | +| :-------------------- | :------------ | +| `supportedMediaTypes` | **banner** | +| `getUserSyncs` | **image** pixel | +| `ttl` | **180** [s] | +| `currency` | **USD** | + +# Parameters +The following table lists parameters required for Yieldbot bidder configuration. +See also [Test Parameters](#test-parameters) for an illustration of parameter usage. + +| Name | Scope | Description | Example | +| :------ | :------- | :------------------------------------------------------------------ | :-------------- | +| `psn` | required | The Yieldbot publisher account short name identifier | "7b25" | +| `slot` | required | The Yieldbot slot name associated to the publisher adUnit to bid on | "mobile_REC_2" | + +## Example Bidder Configuration +```javascript +var adUnit0 = { + code: '/00000000/leaderboard', + mediaTypes: { + banner: { + sizes: [728, 90] + } + }, + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '7b25', + slot: 'desktop_LB' + } + } + ] +}; +``` + +# Test Parameters +For integration testing, the Yieldbot Platform can be set to always return a bid for requested slots. + +When Yieldbot testing mode is enabled, a cookie (`__ybot_test`) on the domain `.yldbt.com` tells the Yieldbot ad server to always return a bid. Each bid is associated to a static mock integration testing creative. + +- **Enable** integration testing mode: + - http://i.yldbt.com/integration/start +- **Disable** integration testing mode: + - http://i.yldbt.com/integration/stop + +***Note:*** + +- No ad serving metrics are impacted when integration testing mode is enabled. +- The `__ybot_test` cookie expires in 24 hours. +- It is good practice to click "Stop testing" when testing is complete, to return to normal ad delivery. + +For reference, the test bidder configuration below is included in the following manual test/example file [test/spec/e2e/gpt-examples/gpt_yieldbot.html](../test/spec/e2e/gpt-examples/gpt_yieldbot.html) +- Replace the adUnit `code` values with your respective DFP adUnitCode. +- ***Remember*** to **Enable** Yieldbot testing mode to force a bid to be returned. + +```javascript +var adUnit0 = { + code: '/00000000/leaderboard', + mediaTypes: { + banner: { + sizes: [728, 90] + } + }, + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'leaderboard' + } + } + ] +}; + +var adUnit1 = { + code: '/00000000/medium-rectangle', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'medrec' + } + } + ] +}; + +var adUnit2 = { + code: '/00000000/large-rectangle', + mediaTypes: { + banner: { + sizes: [[300, 600]] + } + }, + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'sidebar' + } + } + ] +}; + +var adUnit3 = { + code: '/00000000/skyscraper', + mediaTypes: { + banner: { + sizes: [[160, 600]] + } + }, + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'skyscraper' + } + } + ] +}; +``` + +# Yieldbot Query Parameters + +| Name | Description | +| :--- | :---------- | +| `apie` | Yieldbot error description parameter | +| `bt` | Yieldbot bid request type: `initial` or `refresh` | +| `cts_ad` | Yieldbot ad creative request sent timestamp, in milliseconds since the UNIX epoch | +| `cts_imp` | Yieldbot ad impression request sent timestamp, in milliseconds since the UNIX epoch | +| `cts_ini` | Yieldbot bid request sent timestamp, in milliseconds since the UNIX epoch | +| `cts_js` | Adapter code interpreting started timestamp, in milliseconds since the UNIX epoch | +| `cts_ns` | Performance timing navigationStart | +| `cts_rend` | Yieldbot ad creative render started timestamp, in milliseconds since the UNIX epoch | +| `cts_res` | Yieldbot bid response processing started timestamp, in milliseconds since the UNIX epoch | +| `e` | Yieldbot search parameters terminator | +| `ioa` | Indicator that the user-agent supports the Intersection Observer API | +| `it` | Indicator to specify Yieldbot creative rendering occured in an iframe: same/cross origin (`so`)/(`co`) or top (`none`) | +| `la` | Language and locale of the user-agent | +| `lo` | The page visit location Url | +| `lpv` | Time in milliseconds since the last page visit | +| `lpvi` | Pageview identifier for the last pageview within the session TTL | +| `np` | User-agent browsing platform | +| `pvd` | Counter for page visits within a session | +| `pvi` | Page visit identifier | +| `r` | The referring page Url | +| `ri` | Yieldbot ad request identifier | +| `sb` | Yieldbot ads blocked by user opt-out or suspicious activity detected during session | +| `sd` | User-agent screen dimensions | +| `si` | Publisher site visit session identifier | +| `slot` | Slot name for Yieldbot ad markup request e.g. `:x` | +| `sn` | Yieldbot bid slot names | +| `ssz` | Dimensions for the respective bid slot names | +| `to` | Number of hours offset from UTC | +| `ua` | User-Agent string | +| `v` | The version of the YieldbotAdapter | +| `vi` | First party user identifier | + + +# First-party Cookies + +| Name | Description | +| :--- | :---------- | +| `__ybotn` | The session is temporarily suspended from the ad server e.g. User-Agent, Geo location or suspicious activity | +| `__ybotu` | The Yieldbot first-party user identifier | +| `__ybotsi` | The user session identifier | +| `__ybotpvd` | The session pageview depth | +| `__ybotlpvi` | The last pageview identifier within the session | +| `__ybotlpv` | The time in **[ms]** since the last visit within the session | +| `__ybotc` | Geo/IP proximity location request Url | diff --git a/test/spec/e2e/gpt-examples/gpt_yieldbot.html b/test/spec/e2e/gpt-examples/gpt_yieldbot.html new file mode 100644 index 00000000000..12766c537f6 --- /dev/null +++ b/test/spec/e2e/gpt-examples/gpt_yieldbot.html @@ -0,0 +1,241 @@ + + + + + + + + + + +
+
+ Yieldbot integration test mode: + +
    +
  • START (i.e.force bids to be returned)
  • +
  • STOP
  • +
+
+ +

Prebid.js Yieldbot Adapter Test

+
+
+ +
+

Lorem ipsum dolor. Sit amet proin. Integer cursus mi mus curabitur euismod vel quos duis bibendum nec interdum porta dolor a viverra nisl fusce. Volutpat sit at. Donec nisl taciti. Eget eu lobortis. Excepteur diam orci lacus nibh pharetra. Justo neque maecenas. Viverra molestie dolor ante rutrum vivamus libero urna suscipit leo praesent ultricies. In dignissim qui ante bibendum in. Habitasse ac arcu non nulla augue. Felis lectus non tempus in aliquam. Sit porttitor nec. Sodales non sit eu duis.

+
+ +
+

Donec feugiat ornare a amet optio. Vitae sit sapien. Vitae nec justo. Fusce ac in semper ligula duis eget vel sit. Augue mauris sit. A adipisicing orci est augue dapibus ullamcorper faucibus fermentum. Et phasellus in tempus vivamus praesent. Nisl dui porttitor. Iaculis vulputate eros ut interdum eu. Lacus quis magna varius in quis. Congue erat porttitor sit eu vitae pharetra scelerisque nec. Dolor dui vel ut velit vestibulum. Lectus ullamcorper mi. Curabitur ipsum pellentesque sed erat est est sapien in tempor sodales viverra. Dui volutpat morbi eleifend fringilla quis. Neque erat erat. Rhoncus sed posuere. Dapibus fusce ut lacus mus est pede sed quisquam. Quis aliquam pellentesque. Wisi ac odio eu wisi amet ut ipsum a erat aliquam nunc.

+

Dis vitae penatibus. Mollis mauris bibendum. Porta orci amet dolor sed felis in neque per cursus molestie pellentesque. Quis accusamus vel sed dapibus orci congue ut eros. Nec faucibus inceptos. Hendrerit in eget nulla tellus lacinia. Fusce ut ut mattis.

+

Vivamus mauris metus. Ridiculus habitant lorem in nulla in quam eros ut. Libero aliquam platea. In enim consectetuer eget mattis accumsan aenean faucibus tincidunt. Amet donec vitae wisi pellentesque magna non lacinia qui. In erat in maecenas amet dui. Aliquam elit vel. Ligula sodales lacus. Nisl a purus. Pharetra velit porttitor vel vel non turpis viverra fringilla lorem arcu pellentesque sed aliquet nonummy quisque dapibus ullamcorper. Mollis ipsum nulla. Tempor tempus vitae. Luctus amet vel. Suspendisse sagittis vestibulum fusce eu.

+

Urna et felis bibendum felis sit vestibulum wisi pharetra quisque ac quis cursus suspendisse quisque aenean luctus curabitur. Eget nec leo. Mi placerat cras nulla et integer eget in sed. Non magni parturient. Egestas iaculis malesuada. Nec a duis. Pede condimentum ullamcorper. Augue arcu tellus. In velit in in duis odio dictum wisi proin quis eget sit. Felis tempus inceptos. Turpis risus eu. Mi vivamus consequat. Lectus dui imperdiet amet orci vehicula in vel pellentesque habitant suscipit aliquam. Proin porttitor vitae ultricies a in. Est duis pede. Tristique velit vestibulum odio sodales morbi magna ut vitae. Elementum imperdiet sodales ultrices tortor mollis vehicula lorem varius pellentesque mi ut sit turpis feugiat. In convallis urna. Justo aliquam sed quis scelerisque nonummy. Lobortis rhoncus ornare. Pellentesque leo quam at beatae in. Erat lorem tempus. Molestie faucibus a id mauris montes. Sed orci vulputate. Libero justo curabitur. Amet orci ante. Non felis est erat cras purus id at id nibh nunc facilisis amet metus sagittis pellentesque eros amet. Vitae sit nulla vitae wisi diam. Tincidunt ipsum eleifend semper tortor non. Tellus amet aliquet.

+

Dis vitae penatibus. Mollis mauris bibendum. Porta orci amet dolor sed felis in neque per cursus molestie pellentesque. Quis accusamus vel sed dapibus orci congue ut eros. Nec faucibus inceptos. Hendrerit in eget nulla tellus lacinia. Fusce ut ut mattis.

+

Vivamus mauris metus. Ridiculus habitant lorem in nulla in quam eros ut. Libero aliquam platea. In enim consectetuer eget mattis accumsan aenean faucibus tincidunt. Amet donec vitae wisi pellentesque magna non lacinia qui. In erat in maecenas amet dui. Aliquam elit vel. Ligula sodales lacus. Nisl a purus. Pharetra velit porttitor vel vel non turpis viverra fringilla lorem arcu pellentesque sed aliquet nonummy quisque dapibus ullamcorper. Mollis ipsum nulla. Tempor tempus vitae. Luctus amet vel. Suspendisse sagittis vestibulum fusce eu.

+

Urna et felis bibendum felis sit vestibulum wisi pharetra quisque ac quis cursus suspendisse quisque aenean luctus curabitur. Eget nec leo. Mi placerat cras nulla et integer eget in sed. Non magni parturient. Egestas iaculis malesuada. Nec a duis. Pede condimentum ullamcorper. Augue arcu tellus. In velit in in duis odio dictum wisi proin quis eget sit. Felis tempus inceptos. Turpis risus eu. Mi vivamus consequat. Lectus dui imperdiet amet orci vehicula in vel pellentesque habitant suscipit aliquam. Proin porttitor vitae ultricies a in. Est duis pede. Tristique velit vestibulum odio sodales morbi magna ut vitae. Elementum imperdiet sodales ultrices tortor mollis vehicula lorem varius pellentesque mi ut sit turpis feugiat. In convallis urna. Justo aliquam sed quis scelerisque nonummy. Lobortis rhoncus ornare. Pellentesque leo quam at beatae in. Erat lorem tempus. Molestie faucibus a id mauris montes. Sed orci vulputate. Libero justo curabitur. Amet orci ante. Non felis est erat cras purus id at id nibh nunc facilisis amet metus sagittis pellentesque eros amet. Vitae sit nulla vitae wisi diam. Tincidunt ipsum eleifend semper tortor non. Tellus amet aliquet.

+
+
+ +
+
+ +
+
+

Dis vitae penatibus. Mollis mauris bibendum. Porta orci amet dolor sed felis in neque per cursus molestie pellentesque. Quis accusamus vel sed dapibus orci congue ut eros. Nec faucibus inceptos. Hendrerit in eget nulla tellus lacinia. Fusce ut ut mattis.

+
+ + diff --git a/test/spec/modules/yieldbotBidAdapter_spec.js b/test/spec/modules/yieldbotBidAdapter_spec.js new file mode 100644 index 00000000000..206645acd95 --- /dev/null +++ b/test/spec/modules/yieldbotBidAdapter_spec.js @@ -0,0 +1,1326 @@ +import { expect } from 'chai'; +import find from 'core-js/library/fn/array/find'; +import { newBidder } from 'src/adapters/bidderFactory'; +import AdapterManager from 'src/adaptermanager'; +import { newAuctionManager } from 'src/auctionManager'; +import * as utils from 'src/utils'; +import * as urlUtils from 'src/url'; +import events from 'src/events'; +import { YieldbotAdapter, spec } from 'modules/yieldbotBidAdapter'; + +before(function() { + YieldbotAdapter.clearAllCookies(); +}); +describe('Yieldbot Adapter Unit Tests', function() { + const ALL_SEARCH_PARAMS = ['apie', 'bt', 'cb', 'cts_ad', 'cts_imp', 'cts_ini', 'cts_js', 'cts_ns', 'cts_rend', 'cts_res', 'e', 'ioa', 'it', 'la', 'lo', 'lpv', 'lpvi', 'mtp', 'np', 'pvd', 'pvi', 'r', 'ri', 'sb', 'sd', 'si', 'slot', 'sn', 'ssz', 'to', 'ua', 'v', 'vi']; + + const BID_LEADERBOARD_728x90 = { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'leaderboard' + }, + adUnitCode: '/0000000/leaderboard', + transactionId: '3bcca099-e22a-4e1e-ab60-365a74a87c19', + sizes: [728, 90], + bidId: '2240b2af6064bb', + bidderRequestId: '1e878e3676fb85', + auctionId: 'c9964bd5-f835-4c91-916e-00295819f932' + }; + + const BID_MEDREC_300x600 = { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'medrec' + }, + adUnitCode: '/0000000/side-bar', + transactionId: '3bcca099-e22a-4e1e-ab60-365a74a87c20', + sizes: [300, 600], + bidId: '332067957eaa33', + bidderRequestId: '1e878e3676fb85', + auctionId: 'c9964bd5-f835-4c91-916e-00295819f932' + }; + + const BID_MEDREC_300x250 = { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'medrec' + }, + adUnitCode: '/0000000/medrec', + transactionId: '3bcca099-e22a-4e1e-ab60-365a74a87c21', + sizes: [[300, 250]], + bidId: '49d7fe5c3a15ed', + bidderRequestId: '1e878e3676fb85', + auctionId: 'c9964bd5-f835-4c91-916e-00295819f932' + }; + + const BID_SKY160x600 = { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'skyscraper' + }, + adUnitCode: '/0000000/side-bar', + transactionId: '3bcca099-e22a-4e1e-ab60-365a74a87c21', + sizes: [160, 600], + bidId: '49d7fe5c3a16ee', + bidderRequestId: '1e878e3676fb85', + auctionId: 'c9964bd5-f835-4c91-916e-00295819f932' + }; + + const AD_UNITS = [ + { + transactionId: '3bcca099-e22a-4e1e-ab60-365a74a87c19', + code: '/00000000/leaderboard', + sizes: [728, 90], + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'leaderboard' + } + } + ] + }, + { + transactionId: '3bcca099-e22a-4e1e-ab60-365a74a87c20', + code: '/00000000/medrec', + sizes: [[300, 250]], + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'medrec' + } + } + ] + }, + { + transactionId: '3bcca099-e22a-4e1e-ab60-365a74a87c21', + code: '/00000000/multi-size', + sizes: [[300, 600]], + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'medrec' + } + } + ] + }, + { + transactionId: '3bcca099-e22a-4e1e-ab60-365a74a87c22', + code: '/00000000/skyscraper', + sizes: [[160, 600]], + bids: [ + { + bidder: 'yieldbot', + params: { + psn: '1234', + slot: 'skyscraper' + } + } + ] + } + ]; + + const INTERPRET_RESPONSE_BID_REQUEST = { + method: 'GET', + url: '//i.yldbt.com/m/1234/v1/init', + data: { + cts_js: 1518184900582, + cts_ns: 1518184900582, + v: 'pbjs-yb-1.0.0', + vi: 'jdg00eijgpvemqlz73', + si: 'jdg00eil9y4mcdo850', + pvd: 6, + pvi: 'jdg03ai5kp9k1rkheh', + lpv: 1518184868108, + lpvi: 'jdg02lfwmdx8n0ncgc', + bt: 'init', + ua: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', + np: 'MacIntel', + la: 'en-US', + to: 5, + sd: '2560x1440', + lo: 'http://localhost:9999/test/spec/e2e/gpt-examples/gpt_yieldbot.html', + r: '', + e: '', + sn: 'leaderboard|medrec|medrec|skyscraper', + ssz: '728x90|300x250|300x600|160x600', + cts_ini: 1518184900591 + }, + yieldbotSlotParams: { + psn: '1234', + sn: 'leaderboard|medrec|medrec|skyscraper', + ssz: '728x90|300x250|300x600|160x600', + bidIdMap: { + 'jdg03ai5kp9k1rkheh:leaderboard:728x90': '2240b2af6064bb', + 'jdg03ai5kp9k1rkheh:medrec:300x250': '49d7fe5c3a15ed', + 'jdg03ai5kp9k1rkheh:medrec:300x600': '332067957eaa33', + 'jdg03ai5kp9k1rkheh:skyscraper:160x600': '49d7fe5c3a16ee' + } + }, + options: { + withCredentials: true, + customHeaders: { + Accept: 'application/json' + } + } + }; + + const INTERPRET_RESPONSE_SERVER_RESPONSE = { + body: { + pvi: 'jdg03ai5kp9k1rkheh', + subdomain_iframe: 'ads-adseast-vpc', + url_prefix: 'http://ads-adseast-vpc.yldbt.com/m/', + slots: [ + { + slot: 'leaderboard', + cpm: '800', + size: '728x90' + }, + { + slot: 'medrec', + cpm: '300', + size: '300x250' + }, + { + slot: 'medrec', + cpm: '800', + size: '300x600' + }, + { + slot: 'skyscraper', + cpm: '300', + size: '160x600' + } + ], + user_syncs: [ + 'https://usersync.dd9693a32aa1.com/00000000.gif?p=a', + 'https://usersync.3b19503b37d8.com/00000000.gif?p=b', + 'https://usersync.5cb389d36d30.com/00000000.gif?p=c' + ] + }, + headers: {} + }; + + let FIXTURE_AD_UNITS, FIXTURE_SERVER_RESPONSE, FIXTURE_BID_REQUEST, FIXTURE_BID_REQUESTS, FIXTURE_BIDS; + beforeEach(function() { + FIXTURE_AD_UNITS = utils.deepClone(AD_UNITS); + FIXTURE_BIDS = { + BID_LEADERBOARD_728x90: utils.deepClone(BID_LEADERBOARD_728x90), + BID_MEDREC_300x600: utils.deepClone(BID_MEDREC_300x600), + BID_MEDREC_300x250: utils.deepClone(BID_MEDREC_300x250), + BID_SKY160x600: utils.deepClone(BID_SKY160x600) + }; + + FIXTURE_BID_REQUEST = utils.deepClone(INTERPRET_RESPONSE_BID_REQUEST); + FIXTURE_SERVER_RESPONSE = utils.deepClone(INTERPRET_RESPONSE_SERVER_RESPONSE); + FIXTURE_BID_REQUESTS = [ + FIXTURE_BIDS.BID_LEADERBOARD_728x90, + FIXTURE_BIDS.BID_MEDREC_300x600, + FIXTURE_BIDS.BID_MEDREC_300x250, + FIXTURE_BIDS.BID_SKY160x600 + ]; + }); + + afterEach(function() { + YieldbotAdapter._optOut = false; + YieldbotAdapter.clearAllCookies(); + YieldbotAdapter._isInitialized = false; + YieldbotAdapter.initialize(); + }); + + describe('Adapter exposes BidderSpec API', function() { + it('code', function() { + expect(spec.code).to.equal('yieldbot'); + }); + it('supportedMediaTypes', function() { + expect(spec.supportedMediaTypes).to.deep.equal(['banner']); + }); + it('isBidRequestValid', function() { + expect(spec.isBidRequestValid).to.be.a('function'); + }); + it('buildRequests', function() { + expect(spec.buildRequests).to.be.a('function'); + }); + it('interpretResponse', function() { + expect(spec.interpretResponse).to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function() { + let bid = { + bidder: 'yieldbot', + 'params': { + psn: 'foo', + slot: 'bar' + }, + sizes: [[300, 250], [300, 600]] + }; + + it('valid parameters', function() { + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + psn: 'foo', + slot: 'bar' + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(true); + }); + + it('undefined parameters', function() { + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + psn: 'foo' + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + slot: 'bar' + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(false); + }); + + it('falsey string parameters', function() { + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + psn: '', + slot: 'bar' + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + psn: 'foo', + slot: '' + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + psn: 'foo', + slot: 0 + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(false); + }); + + it('parameters type invalid', function() { + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + psn: 'foo', + slot: 0 + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + psn: { name: 'foo' }, + slot: 'bar' + }, + sizes: [[300, 250], [300, 600]] + })).to.equal(false); + }); + + it('invalid sizes type', function() { + expect(spec.isBidRequestValid({ + bidder: 'yieldbot', + 'params': { + psn: 'foo', + slot: 'bar' + }, + sizes: {} + })).to.equal(true); + }); + }); + + describe('getSlotRequestParams', function() { + const EMPTY_SLOT_PARAMS = { sn: '', ssz: '', bidIdMap: {} }; + + it('should default to empty slot params', function() { + expect(YieldbotAdapter.getSlotRequestParams('')).to.deep.equal(EMPTY_SLOT_PARAMS); + expect(YieldbotAdapter.getSlotRequestParams()).to.deep.equal(EMPTY_SLOT_PARAMS); + expect(YieldbotAdapter.getSlotRequestParams('', [])).to.deep.equal(EMPTY_SLOT_PARAMS); + expect(YieldbotAdapter.getSlotRequestParams(0, [])).to.deep.equal(EMPTY_SLOT_PARAMS); + }); + + it('should build slot bid request parameters', function() { + const bidRequests = [ + FIXTURE_BIDS.BID_LEADERBOARD_728x90, + FIXTURE_BIDS.BID_MEDREC_300x600, + FIXTURE_BIDS.BID_MEDREC_300x250 + ]; + const slotParams = YieldbotAdapter.getSlotRequestParams('f0e1d2c', bidRequests); + + expect(slotParams.psn).to.equal('1234'); + expect(slotParams.sn).to.equal('leaderboard|medrec'); + expect(slotParams.ssz).to.equal('728x90|300x600.300x250'); + + let bidId = slotParams.bidIdMap['f0e1d2c:leaderboard:728x90']; + expect(bidId).to.equal('2240b2af6064bb'); + + bidId = slotParams.bidIdMap['f0e1d2c:medrec:300x250']; + expect(bidId).to.equal('49d7fe5c3a15ed'); + + bidId = slotParams.bidIdMap['f0e1d2c:medrec:300x600']; + expect(bidId).to.equal('332067957eaa33'); + }); + + it('should build slot bid request parameters in order of bidRequests', function() { + const bidRequests = [ + FIXTURE_BIDS.BID_MEDREC_300x600, + FIXTURE_BIDS.BID_LEADERBOARD_728x90, + FIXTURE_BIDS.BID_MEDREC_300x250 + ]; + + const slotParams = YieldbotAdapter.getSlotRequestParams('f0e1d2c', bidRequests); + + expect(slotParams.psn).to.equal('1234'); + expect(slotParams.sn).to.equal('medrec|leaderboard'); + expect(slotParams.ssz).to.equal('300x600.300x250|728x90'); + + let bidId = slotParams.bidIdMap['f0e1d2c:leaderboard:728x90']; + expect(bidId).to.equal('2240b2af6064bb'); + + bidId = slotParams.bidIdMap['f0e1d2c:medrec:300x250']; + expect(bidId).to.equal('49d7fe5c3a15ed'); + + bidId = slotParams.bidIdMap['f0e1d2c:medrec:300x600']; + expect(bidId).to.equal('332067957eaa33'); + }); + + it('should exclude slot bid requests with malformed sizes', function() { + const bid = FIXTURE_BIDS.BID_MEDREC_300x250; + bid.sizes = ['300x250']; + const bidRequests = [bid, FIXTURE_BIDS.BID_LEADERBOARD_728x90]; + const slotParams = YieldbotAdapter.getSlotRequestParams('affffffe', bidRequests); + expect(slotParams.psn).to.equal('1234'); + expect(slotParams.sn).to.equal('leaderboard'); + expect(slotParams.ssz).to.equal('728x90'); + }); + }); + + describe('getCookie', function() { + it('should return null if cookie name not found', function() { + const cookieName = YieldbotAdapter.newId(); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + }); + + describe('setCookie', function() { + it('should set a root path first-party cookie with temporal expiry', function() { + const cookieName = YieldbotAdapter.newId(); + const cookieValue = YieldbotAdapter.newId(); + + YieldbotAdapter.setCookie(cookieName, cookieValue, 2000, '/'); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(cookieValue); + + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should set a root path first-party cookie with session expiry', function() { + const cookieName = YieldbotAdapter.newId(); + const cookieValue = YieldbotAdapter.newId(); + + YieldbotAdapter.setCookie(cookieName, cookieValue, null, '/'); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(cookieValue); + + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should fail to set a cookie x-domain', function() { + const cookieName = YieldbotAdapter.newId(); + const cookieValue = YieldbotAdapter.newId(); + + YieldbotAdapter.setCookie(cookieName, cookieValue, null, '/', `${cookieName}.com`); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + }); + + describe('clearAllcookies', function() { + it('should delete all first-party cookies', function() { + let idx, cookieLabels = YieldbotAdapter._cookieLabels, cookieName, cookieValue; + for (idx = 0; idx < cookieLabels.length; idx++) { + YieldbotAdapter.deleteCookie('__ybot' + cookieLabels[idx]); + } + + YieldbotAdapter.sessionBlocked = true; + expect(YieldbotAdapter.sessionBlocked, 'sessionBlocked').to.equal(true); + + const userId = YieldbotAdapter.userId; + expect(YieldbotAdapter.userId, 'userId').to.equal(userId); + + const sessionId = YieldbotAdapter.sessionId; + expect(YieldbotAdapter.sessionId, 'sessionId').to.equal(sessionId); + + const pageviewDepth = YieldbotAdapter.pageviewDepth; + expect(pageviewDepth, 'returned pageviewDepth').to.equal(1); + expect(YieldbotAdapter.pageviewDepth, 'get pageviewDepth').to.equal(2); + + const lastPageviewId = YieldbotAdapter.newId(); + YieldbotAdapter.lastPageviewId = lastPageviewId; + expect(YieldbotAdapter.lastPageviewId, 'get lastPageviewId').to.equal(lastPageviewId); + + const lastPageviewTime = Date.now(); + YieldbotAdapter.lastPageviewTime = lastPageviewTime; + expect(YieldbotAdapter.lastPageviewTime, 'lastPageviewTime').to.equal(lastPageviewTime); + + const urlPrefix = YieldbotAdapter.urlPrefix('http://here.there.com/ad/'); + expect(YieldbotAdapter.urlPrefix(), 'urlPrefix').to.equal('http://here.there.com/ad/'); + + for (idx = 0; idx < cookieLabels.length; idx++) { + cookieValue = YieldbotAdapter.getCookie('__ybot' + cookieLabels[idx]); + expect(!!cookieValue, 'setter: ' + cookieLabels[idx]).to.equal(true); + } + + YieldbotAdapter.clearAllCookies(); + + for (idx = 0; idx < cookieLabels.length; idx++) { + cookieName = '__ybot' + cookieLabels[idx]; + cookieValue = YieldbotAdapter.getCookie(cookieName); + expect(cookieValue, cookieName).to.equal(null); + }; + }); + }); + + describe('sessionBlocked', function() { + const cookieName = '__ybotn'; + beforeEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + }); + + afterEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should return true if cookie value is interpreted as non-zero', function() { + YieldbotAdapter.setCookie(cookieName, '1', 2000, '/'); + expect(YieldbotAdapter.sessionBlocked, 'cookie value: the string "1"').to.equal(true); + + YieldbotAdapter.setCookie(cookieName, '10.01', 2000, '/'); + expect(YieldbotAdapter.sessionBlocked, 'cookie value: the string "10.01"').to.equal(true); + + YieldbotAdapter.setCookie(cookieName, '-10.01', 2000, '/'); + expect(YieldbotAdapter.sessionBlocked, 'cookie value: the string "-10.01"').to.equal(true); + + YieldbotAdapter.setCookie(cookieName, 1, 2000, '/'); + expect(YieldbotAdapter.sessionBlocked, 'cookie value: the number 1').to.equal(true); + }); + + it('should return false if cookie name not found', function() { + expect(YieldbotAdapter.sessionBlocked).to.equal(false); + }); + + it('should return false if cookie value is interpreted as zero', function() { + YieldbotAdapter.setCookie(cookieName, '0', 2000, '/'); + expect(YieldbotAdapter.sessionBlocked, 'cookie value: the string "0"').to.equal(false); + + YieldbotAdapter.setCookie(cookieName, '.01', 2000, '/'); + expect(YieldbotAdapter.sessionBlocked, 'cookie value: the string ".01"').to.equal(false); + + YieldbotAdapter.setCookie(cookieName, '-.9', 2000, '/'); + expect(YieldbotAdapter.sessionBlocked, 'cookie value: the string "-.9"').to.equal(false); + + YieldbotAdapter.setCookie(cookieName, 0, 2000, '/'); + expect(YieldbotAdapter.sessionBlocked, 'cookie value: the number 0').to.equal(false); + }); + + it('should return false if cookie value source is a non-numeric string', function() { + YieldbotAdapter.setCookie(cookieName, 'true', 2000, '/'); + expect(YieldbotAdapter.sessionBlocked).to.equal(false); + }); + + it('should return false if cookie value source is a boolean', function() { + YieldbotAdapter.setCookie(cookieName, true, 2000, '/'); + expect(YieldbotAdapter.sessionBlocked).to.equal(false); + }); + + it('should set sessionBlocked', function() { + YieldbotAdapter.sessionBlocked = true; + expect(YieldbotAdapter.sessionBlocked).to.equal(true); + YieldbotAdapter.sessionBlocked = false; + expect(YieldbotAdapter.sessionBlocked).to.equal(false); + + YieldbotAdapter.sessionBlocked = 1; + expect(YieldbotAdapter.sessionBlocked).to.equal(true); + YieldbotAdapter.sessionBlocked = 0; + expect(YieldbotAdapter.sessionBlocked).to.equal(false); + + YieldbotAdapter.sessionBlocked = '1'; + expect(YieldbotAdapter.sessionBlocked).to.equal(true); + YieldbotAdapter.sessionBlocked = ''; + expect(YieldbotAdapter.sessionBlocked).to.equal(false); + }); + }); + + describe('userId', function() { + const cookieName = '__ybotu'; + beforeEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + }); + + afterEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should set a user Id if cookie does not exist', function() { + const userId = YieldbotAdapter.userId; + expect(userId).to.match(/[0-9a-z]{18}/); + }); + + it('should return user Id if cookie exists', function() { + const expectedUserId = YieldbotAdapter.newId(); + YieldbotAdapter.setCookie(cookieName, expectedUserId, 2000, '/'); + const userId = YieldbotAdapter.userId; + expect(userId).to.equal(expectedUserId); + }); + }); + + describe('sessionId', function() { + const cookieName = '__ybotsi'; + beforeEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + }); + + afterEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should set a session Id if cookie does not exist', function() { + const sessionId = YieldbotAdapter.sessionId; + expect(sessionId).to.match(/[0-9a-z]{18}/); + }); + + it('should return session Id if cookie exists', function() { + const expectedSessionId = YieldbotAdapter.newId(); + YieldbotAdapter.setCookie(cookieName, expectedSessionId, 2000, '/'); + const sessionId = YieldbotAdapter.sessionId; + expect(sessionId).to.equal(expectedSessionId); + }); + }); + + describe('lastPageviewId', function() { + const cookieName = '__ybotlpvi'; + + beforeEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + }); + + afterEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should return empty string if cookie does not exist', function() { + const lastBidId = YieldbotAdapter.lastPageviewId; + expect(lastBidId).to.equal(''); + }); + + it('should set an id string', function() { + const id = YieldbotAdapter.newId(); + YieldbotAdapter.lastPageviewId = id; + const lastBidId = YieldbotAdapter.lastPageviewId; + expect(lastBidId).to.equal(id); + }); + }); + + describe('lastPageviewTime', function() { + const cookieName = '__ybotlpv'; + + beforeEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + }); + + afterEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should return zero if cookie does not exist', function() { + const lastBidTime = YieldbotAdapter.lastPageviewTime; + expect(lastBidTime).to.equal(0); + }); + + it('should set a timestamp', function() { + const ts = Date.now(); + YieldbotAdapter.lastPageviewTime = ts; + const lastBidTime = YieldbotAdapter.lastPageviewTime; + expect(lastBidTime).to.equal(ts); + }); + }); + + describe('pageviewDepth', function() { + const cookieName = '__ybotpvd'; + + beforeEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + }); + + afterEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should return one (1) if cookie does not exist', function() { + const pageviewDepth = YieldbotAdapter.pageviewDepth; + expect(pageviewDepth).to.equal(1); + }); + + it('should increment the integer string for depth', function() { + let pageviewDepth = YieldbotAdapter.pageviewDepth; + expect(pageviewDepth).to.equal(1); + + pageviewDepth = YieldbotAdapter.pageviewDepth; + expect(pageviewDepth).to.equal(2); + }); + }); + + describe('urlPrefix', function() { + const cookieName = '__ybotc'; + const protocol = document.location.protocol; + afterEach(function() { + YieldbotAdapter.deleteCookie(cookieName); + expect(YieldbotAdapter.getCookie(cookieName)).to.equal(null); + }); + + it('should set the default prefix if cookie does not exist', function(done) { + const urlPrefix = YieldbotAdapter.urlPrefix(); + expect(urlPrefix).to.equal('//i.yldbt.com/m/'); + done(); + }); + + it('should return prefix if cookie exists', function() { + YieldbotAdapter.setCookie(cookieName, protocol + '//closest.az.com/path/', 2000, '/'); + const urlPrefix = YieldbotAdapter.urlPrefix(); + expect(urlPrefix).to.equal(protocol + '//closest.az.com/path/'); + }); + + it('should reset prefix if default already set', function() { + const defaultUrlPrefix = YieldbotAdapter.urlPrefix(); + const url = protocol + '//close.az.com/path/'; + expect(defaultUrlPrefix).to.equal('//i.yldbt.com/m/'); + + let urlPrefix = YieldbotAdapter.urlPrefix(url); + expect(urlPrefix, 'reset prefix').to.equal(url); + + urlPrefix = YieldbotAdapter.urlPrefix(); + expect(urlPrefix, 'subsequent request').to.equal(url); + }); + + it('should set containing document protocol', function() { + let urlPrefix = YieldbotAdapter.urlPrefix('http://close.az.com/path/'); + expect(urlPrefix, 'http - use: ' + protocol).to.equal(protocol + '//close.az.com/path/'); + + urlPrefix = YieldbotAdapter.urlPrefix('https://close.az.com/path/'); + expect(urlPrefix, 'https - use: ' + protocol).to.equal(protocol + '//close.az.com/path/'); + }); + + it('should fallback to default for invalid argument', function() { + let urlPrefix = YieldbotAdapter.urlPrefix('//close.az.com/path/'); + expect(urlPrefix, 'Url w/o protocol').to.equal('//i.yldbt.com/m/'); + + urlPrefix = YieldbotAdapter.urlPrefix('mumble'); + expect(urlPrefix, 'Invalid Url').to.equal('//i.yldbt.com/m/'); + }); + }); + + describe('initBidRequestParams', function() { + it('should build common bid request state parameters', function() { + const params = YieldbotAdapter.initBidRequestParams( + [ + { + 'params': { + psn: '1234', + slot: 'medrec' + }, + sizes: [[300, 250], [300, 600]] + } + ] + ); + + const expectedParamKeys = [ + 'v', + 'vi', + 'si', + 'pvi', + 'pvd', + 'lpvi', + 'bt', + 'lo', + 'r', + 'sd', + 'to', + 'la', + 'np', + 'ua', + 'lpv', + 'cts_ns', + 'cts_js', + 'e' + ]; + + const missingKeys = []; + expectedParamKeys.forEach((item) => { + if (item in params === false) { + missingKeys.push(item); + } + }); + const extraKeys = []; + Object.keys(params).forEach((item) => { + if (!find(expectedParamKeys, param => param === item)) { + extraKeys.push(item); + } + }); + + expect( + missingKeys.length, + `\nExpected: ${expectedParamKeys}\nMissing keys: ${JSON.stringify(missingKeys)}`) + .to.equal(0); + expect( + extraKeys.length, + `\nExpected: ${expectedParamKeys}\nExtra keys: ${JSON.stringify(extraKeys)}`) + .to.equal(0); + }); + }); + + describe('buildRequests', function() { + it('should not return bid requests if optOut', function() { + YieldbotAdapter._optOut = true; + const requests = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS); + expect(requests.length).to.equal(0); + }); + + it('should not return bid requests if sessionBlocked', function() { + YieldbotAdapter.sessionBlocked = true; + const requests = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS); + expect(requests.length).to.equal(0); + YieldbotAdapter.sessionBlocked = false; + }); + + it('should re-enable requests when sessionBlocked expires', function() { + const cookieName = '__ybotn'; + YieldbotAdapter.setCookie( + cookieName, + 1, + 2000, + '/'); + let requests = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS); + expect(requests.length).to.equal(0); + YieldbotAdapter.deleteCookie(cookieName); + requests = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS); + expect(requests.length).to.equal(1); + }); + + it('should return a single BidRequest object', function() { + const requests = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS); + expect(requests.length).to.equal(1); + }); + + it('should have expected server options', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + const expectedOptions = { + withCredentials: true, + customHeaders: { + Accept: 'application/json' + } + }; + expect(request.options).to.eql(expectedOptions); + }); + + it('should be a GET request', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.method).to.equal('GET'); + }); + + it('should have bid request specific params', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.data).to.not.equal(undefined); + + const expectedParamKeys = [ + 'v', + 'vi', + 'si', + 'pvi', + 'pvd', + 'lpvi', + 'bt', + 'lo', + 'r', + 'sd', + 'to', + 'la', + 'np', + 'ua', + 'sn', + 'ssz', + 'lpv', + 'cts_ns', + 'cts_js', + 'cts_ini', + 'e' + ]; + + const missingKeys = []; + expectedParamKeys.forEach((item) => { + if (item in request.data === false) { + missingKeys.push(item); + } + }); + const extraKeys = []; + Object.keys(request.data).forEach((item) => { + if (!find(expectedParamKeys, param => param === item)) { + extraKeys.push(item); + } + }); + + expect( + missingKeys.length, + `\nExpected: ${expectedParamKeys}\nMissing keys: ${JSON.stringify(missingKeys)}`) + .to.equal(0); + expect( + extraKeys.length, + `\nExpected: ${expectedParamKeys}\nExtra keys: ${JSON.stringify(extraKeys)}`) + .to.equal(0); + }); + + it('should have the correct bidUrl form', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + const bidUrl = '//i.yldbt.com/m/1234/v1/init'; + expect(request.url).to.equal(bidUrl); + }); + + it('should set the bid request slot/bidId mapping', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.yieldbotSlotParams).to.not.equal(undefined); + expect(request.yieldbotSlotParams.bidIdMap).to.not.equal(undefined); + + const map = {}; + map[request.data.pvi + ':leaderboard:728x90'] = '2240b2af6064bb'; + map[request.data.pvi + ':medrec:300x250'] = '49d7fe5c3a15ed'; + map[request.data.pvi + ':medrec:300x600'] = '332067957eaa33'; + map[request.data.pvi + ':skyscraper:160x600'] = '49d7fe5c3a16ee'; + expect(request.yieldbotSlotParams.bidIdMap).to.eql(map); + }); + + it('should set the bid request publisher number', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.yieldbotSlotParams.psn).to.equal('1234'); + }); + + it('should have unique slot name parameter', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.yieldbotSlotParams.sn).to.equal('leaderboard|medrec|skyscraper'); + }); + + it('should have slot sizes parameter', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.yieldbotSlotParams.ssz).to.equal('728x90|300x600.300x250|160x600'); + }); + + it('should use edge server Url prefix if set', function() { + const cookieName = '__ybotc'; + YieldbotAdapter.setCookie( + cookieName, + 'http://close.edge.adserver.com/', + 2000, + '/'); + + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.url).to.match(/^http:\/\/close\.edge\.adserver\.com\//); + }); + + it('should be adapter loaded before navigation start time', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + const timeDiff = request.data.cts_ns - request.data.cts_js; + expect(timeDiff >= 0, 'adapter loaded < nav').to.equal(true); + }); + + it('should be navigation start before bid request time', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + const timeDiff = request.data.cts_ini - request.data.cts_ns; + expect(timeDiff >= 0, 'nav start < request').to.equal(true); + }); + }); + + describe('interpretResponse', function() { + it('should not return Bids if optOut', function() { + YieldbotAdapter._optOut = true; + const responses = YieldbotAdapter.interpretResponse(); + expect(responses.length).to.equal(0); + }); + + it('should not return Bids if no server response slot bids', function() { + FIXTURE_SERVER_RESPONSE.body.slots = []; + const responses = YieldbotAdapter.interpretResponse(FIXTURE_SERVER_RESPONSE, FIXTURE_BID_REQUEST); + expect(responses.length).to.equal(0); + }); + + it('should not include Bid if missing cpm', function() { + delete FIXTURE_SERVER_RESPONSE.body.slots[1].cpm; + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + expect(responses.length).to.equal(3); + }); + + it('should not include Bid if missing size', function() { + delete FIXTURE_SERVER_RESPONSE.body.slots[2].size; + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + expect(responses.length).to.equal(3); + }); + + it('should not include Bid if missing slot', function() { + delete FIXTURE_SERVER_RESPONSE.body.slots[3].slot; + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + expect(responses.length).to.equal(3); + }); + + it('should have a valid creativeId', function() { + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + expect(responses.length).to.equal(4); + responses.forEach((bid) => { + expect(bid.creativeId).to.match(/[0-9a-z]{18}/); + const containerDivId = 'ybot-' + bid.creativeId; + const re = new RegExp(containerDivId); + expect(re.test(bid.ad)).to.equal(true); + }); + }); + + it('should specify Net revenue type for bid', function() { + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + expect(responses[0].netRevenue).to.equal(true); + }); + + it('should specify USD currency for bid', function() { + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + expect(responses[1].currency).to.equal('USD'); + }); + + it('should set edge server Url prefix', function() { + FIXTURE_SERVER_RESPONSE.body.url_prefix = 'http://close.edge.adserver.com/'; + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + const edgeServerUrlPrefix = YieldbotAdapter.getCookie('__ybotc'); + + const protocol = document.location.protocol; + const beginsRegex = new RegExp('^' + protocol + '\/\/close\.edge\.adserver\.com\/'); + const containsRegex = new RegExp(protocol + '\/\/close\.edge\.adserver\.com\/'); + expect(edgeServerUrlPrefix).to.match(beginsRegex); + expect(responses[0].ad).to.match(containsRegex); + }); + }); + + describe('getUserSyncs', function() { + let responses; + beforeEach(function () { + responses = [FIXTURE_SERVER_RESPONSE]; + }); + it('should return empty Array when server response property missing', function() { + delete responses[0].body.user_syncs; + const userSyncs = YieldbotAdapter.getUserSyncs({ pixelEnabled: true }, responses); + expect(userSyncs.length).to.equal(0); + }); + + it('should return empty Array when server response property is empty', function() { + responses[0].body.user_syncs = []; + const userSyncs = YieldbotAdapter.getUserSyncs({ pixelEnabled: true }, responses); + expect(userSyncs.length).to.equal(0); + }); + + it('should return empty Array pixel disabled', function() { + const userSyncs = YieldbotAdapter.getUserSyncs({ pixelEnabled: false }, responses); + expect(userSyncs.length).to.equal(0); + }); + + it('should return empty Array pixel option not provided', function() { + const userSyncs = YieldbotAdapter.getUserSyncs({ pixelNotHere: true }, responses); + expect(userSyncs.length).to.equal(0); + }); + + it('should return image type pixels', function() { + const userSyncs = YieldbotAdapter.getUserSyncs({ pixelEnabled: true }, responses); + expect(userSyncs).to.eql( + [ + { type: 'image', url: 'https://usersync.dd9693a32aa1.com/00000000.gif?p=a' }, + { type: 'image', url: 'https://usersync.3b19503b37d8.com/00000000.gif?p=b' }, + { type: 'image', url: 'https://usersync.5cb389d36d30.com/00000000.gif?p=c' } + ] + ); + }); + }); + + describe('Adapter Auction Behavior', function() { + AdapterManager.bidderRegistry['yieldbot'] = newBidder(spec); + let sandbox, server, auctionManager; + const bidUrlRegexp = /yldbt\.com\/m\/1234\/v1\/init/; + beforeEach(function() { + sandbox = sinon.sandbox.create({ useFakeServer: true }); + server = sandbox.server; + server.respondImmediately = true; + server.respondWith( + 'GET', + bidUrlRegexp, + [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(FIXTURE_SERVER_RESPONSE.body) + ] + ); + FIXTURE_SERVER_RESPONSE.user_syncs = []; + auctionManager = newAuctionManager(); + }); + + afterEach(function() { + auctionManager = null; + sandbox.restore(); + YieldbotAdapter._bidRequestCount = 0; + }); + + it('should provide auction bids', function(done) { + let bidCount = 0; + const firstAuction = auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ); + const bidResponseHandler = (event) => { + bidCount++; + if (bidCount === 4) { + events.off('bidResponse', bidResponseHandler); + done(); + } + }; + events.on('bidResponse', bidResponseHandler); + firstAuction.callBids(); + }); + + it('should provide multiple auctions with correct bid cpms', function(done) { + let bidCount = 0; + let firstAuctionId = ''; + let secondAuctionId = ''; + /* + * 'bidResponse' event handler checks for respective adUnit auctions and bids + */ + const bidResponseHandler = (event) => { + try { + switch (true) { + case event.adUnitCode === '/00000000/leaderboard' && event.auctionId === firstAuctionId: + expect(event.cpm, 'leaderboard, first auction cpm').to.equal(8); + break; + case event.adUnitCode === '/00000000/medrec' && event.auctionId === firstAuctionId: + expect(event.cpm, 'medrec, first auction cpm').to.equal(3); + break; + case event.adUnitCode === '/00000000/multi-size' && event.auctionId === firstAuctionId: + expect(event.cpm, 'multi-size, first auction cpm').to.equal(8); + break; + case event.adUnitCode === '/00000000/skyscraper' && event.auctionId === firstAuctionId: + expect(event.cpm, 'skyscraper, first auction cpm').to.equal(3); + break; + case event.adUnitCode === '/00000000/medrec' && event.auctionId === secondAuctionId: + expect(event.cpm, 'medrec, second auction cpm').to.equal(1.11); + break; + case event.adUnitCode === '/00000000/multi-size' && event.auctionId === secondAuctionId: + expect(event.cpm, 'multi-size, second auction cpm').to.equal(2.22); + break; + case event.adUnitCode === '/00000000/skyscraper' && event.auctionId === secondAuctionId: + expect(event.cpm, 'skyscraper, second auction cpm').to.equal(3.33); + break; + default: + done(new Error(`Bid response to assert not found: ${event.adUnitCode}:${event.size}:${event.auctionId}, [${firstAuctionId}, ${secondAuctionId}]`)); + } + bidCount++; + if (bidCount === 7) { + events.off('bidResponse', bidResponseHandler); + done(); + } + } catch (err) { + done(err); + } + }; + events.on('bidResponse', bidResponseHandler); + + /* + * First auction + */ + const firstAdUnits = FIXTURE_AD_UNITS; + const firstAdUnitCodes = FIXTURE_AD_UNITS.map(unit => unit.code); + const firstAuction = auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ); + firstAuctionId = firstAuction.getAuctionId(); + firstAuction.callBids(); + + /* + * Second auction with different bid values and fewer slots + */ + FIXTURE_AD_UNITS.shift(); + const FIXTURE_SERVER_RESPONSE_2 = utils.deepClone(FIXTURE_SERVER_RESPONSE); + FIXTURE_SERVER_RESPONSE_2.user_syncs = []; + FIXTURE_SERVER_RESPONSE_2.body.slots.shift(); + FIXTURE_SERVER_RESPONSE_2.body.slots.forEach((bid, idx) => { const num = idx + 1; bid.cpm = `${num}${num}${num}`; }); + const secondAuction = auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ); + secondAuctionId = secondAuction.getAuctionId(); + server.respondWith( + 'GET', + bidUrlRegexp, + [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(FIXTURE_SERVER_RESPONSE_2.body) + ] + ); + secondAuction.callBids(); + }); + + it('should have refresh bid type after the first auction', function(done) { + const firstAuction = auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ); + firstAuction.callBids(); + + const secondAuction = auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ); + secondAuction.callBids(); + + const firstRequest = urlUtils.parse(server.firstRequest.url); + expect(firstRequest.search.bt, 'First request bid type').to.equal('init'); + + const secondRequest = urlUtils.parse(server.secondRequest.url); + expect(secondRequest.search.bt, 'Second request bid type').to.equal('refresh'); + + done(); + }); + + it('should use server response url_prefix property value after the first auction', function(done) { + const firstAuction = auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ); + firstAuction.callBids(); + + const secondAuction = auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ); + secondAuction.callBids(); + + expect(server.firstRequest.url, 'Default url prefix').to.match(/i\.yldbt\.com\/m\//); + expect(server.secondRequest.url, 'Locality url prefix').to.match(/ads-adseast-vpc\.yldbt\.com\/m\//); + + done(); + }); + + it('should increment the session page view depth only before the first auction', function(done) { + /* + * First visit: two bid requests + */ + for (let idx = 0; idx < 2; idx++) { + auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ).callBids(); + } + + const firstRequest = urlUtils.parse(server.firstRequest.url); + expect(firstRequest.search.pvd, 'First pvd').to.equal('1'); + + const secondRequest = urlUtils.parse(server.secondRequest.url); + expect(secondRequest.search.pvd, 'Second pvd').to.equal('1'); + + /* + * Next visit: two bid requests + */ + YieldbotAdapter._isInitialized = false; + YieldbotAdapter.initialize(); + for (let idx = 0; idx < 2; idx++) { + auctionManager.createAuction( + { + adUnits: FIXTURE_AD_UNITS, + adUnitCodes: FIXTURE_AD_UNITS.map(unit => unit.code) + } + ).callBids(); + } + + const nextVisitFirstRequest = urlUtils.parse(server.thirdRequest.url); + expect(nextVisitFirstRequest.search.pvd, 'Second visit, first pvd').to.equal('2'); + + const nextVisitSecondRequest = urlUtils.parse(server.lastRequest.url); + expect(nextVisitSecondRequest.search.pvd, 'Second visit, second pvd').to.equal('2'); + + done(); + }); + }); +}); From bc9c29b98623ea409eb06e72340f3ba4982b5b3c Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Fri, 2 Mar 2018 08:35:36 -0800 Subject: [PATCH 0154/1594] Remove bracket and object spacing lint exceptions (#2168) --- test/.eslintrc.js | 2 -- test/helpers/index_adapter_utils.js | 6 +++--- test/spec/auctionmanager_spec.js | 6 +++--- test/spec/modules/a4gBidAdapter_spec.js | 2 +- test/spec/modules/adformBidAdapter_spec.js | 2 +- test/spec/modules/appnexusBidAdapter_spec.js | 6 +++--- test/spec/modules/jcmBidAdapter_spec.js | 8 ++++---- test/spec/modules/prebidServerBidAdapter_spec.js | 2 +- test/spec/modules/pulsepointBidAdapter_spec.js | 12 ++++++------ test/spec/modules/somoaudienceBidAdapter_spec.js | 2 +- test/spec/unit/core/bidderFactory_spec.js | 2 +- test/spec/unit/pbjs_api_spec.js | 2 +- 12 files changed, 25 insertions(+), 27 deletions(-) diff --git a/test/.eslintrc.js b/test/.eslintrc.js index c1d36996a40..4cd5a854ac4 100644 --- a/test/.eslintrc.js +++ b/test/.eslintrc.js @@ -36,7 +36,5 @@ module.exports = { "no-use-before-define": "off", "no-useless-escape": "off", "one-var": "off", - "standard/array-bracket-even-spacing": "off", - "standard/object-curly-even-spacing": "off" } }; diff --git a/test/helpers/index_adapter_utils.js b/test/helpers/index_adapter_utils.js index 716ec1ff4f3..f01145b573d 100644 --- a/test/helpers/index_adapter_utils.js +++ b/test/helpers/index_adapter_utils.js @@ -203,7 +203,7 @@ exports.matchBidsOnSID = function(lhs, rhs) { var compared = compareOnKeys(lstore, rstore); var matched = compared.intersection.map(function(pair) { return { configured: pair.left, sent: pair.right, name: pair.name } }); - return { unmatched: { configured: compared.lhsOnly, sent: compared.rhsOnly }, matched: matched}; + return { unmatched: { configured: compared.lhsOnly, sent: compared.rhsOnly }, matched: matched }; } exports.matchBidsOnSize = function(lhs, rhs) { @@ -220,12 +220,12 @@ exports.matchBidsOnSize = function(lhs, rhs) { } var lstore = createObjectFromArray(configured); - var rstore = createObjectFromArray(rhs.map(bid => [ bid.banner.w + 'x' + bid.banner.h, bid])); + var rstore = createObjectFromArray(rhs.map(bid => [ bid.banner.w + 'x' + bid.banner.h, bid ])); var compared = compareOnKeys(lstore, rstore); var matched = compared.intersection.map(function(pair) { return { configured: pair.left, sent: pair.right, name: pair.name } }); - return { unmatched: { configured: compared.lhsOnly, sent: compared.rhsOnly }, matched: matched}; + return { unmatched: { configured: compared.lhsOnly, sent: compared.rhsOnly }, matched: matched }; } exports.getBidResponse = function(configuredBids, urlJSON, optionalPriceLevel, optionalResponseIdentifier, optionalPassOnBid, optionalResponseParam) { diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 167d05f7bef..c92871e5568 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -853,11 +853,11 @@ describe('auctionmanager.js', function () { }); it('should run auction after video bids have been cached', () => { - sinon.stub(store, 'store').callsArgWith(1, null, [{ uuid: 123}]); + sinon.stub(store, 'store').callsArgWith(1, null, [{ uuid: 123 }]); sinon.stub(config, 'getConfig').withArgs('cache.url').returns('cache-url'); - const bidsCopy = [Object.assign({}, bids[0], { mediaType: 'video'})]; - const bids1Copy = [Object.assign({}, bids1[0], { mediaType: 'video'})]; + const bidsCopy = [Object.assign({}, bids[0], { mediaType: 'video' })]; + const bids1Copy = [Object.assign({}, bids1[0], { mediaType: 'video' })]; registerBidder(spec); registerBidder(spec1); diff --git a/test/spec/modules/a4gBidAdapter_spec.js b/test/spec/modules/a4gBidAdapter_spec.js index 24249cc8c36..60016fbfb9e 100644 --- a/test/spec/modules/a4gBidAdapter_spec.js +++ b/test/spec/modules/a4gBidAdapter_spec.js @@ -1,4 +1,4 @@ -import { expect} from 'chai'; +import { expect } from 'chai'; import { spec } from 'modules/a4gBidAdapter'; describe('a4gAdapterTests', () => { diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index 357e6e67f4d..8d8e8fc5683 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -81,7 +81,7 @@ describe('Adform adapter', () => { describe('interpretResponse', () => { it('should respond with empty response when there is empty serverResponse', () => { - let result = spec.interpretResponse({ body: {}}, {}); + let result = spec.interpretResponse({ body: {} }, {}); assert.deepEqual(result, []); }); it('should respond with empty response when sizes doesn\'t match', () => { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 661d6a63e3d..7038e2e572c 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -181,7 +181,7 @@ describe('AppNexusAdapter', () => { nativeParams: { title: {required: true}, body: {required: true}, - image: {required: true, sizes: [{ width: 100, height: 100 }] }, + image: {required: true, sizes: [{ width: 100, height: 100 }]}, cta: {required: false}, sponsoredBy: {required: true} } @@ -194,7 +194,7 @@ describe('AppNexusAdapter', () => { expect(payload.tags[0].native.layouts[0]).to.deep.equal({ title: {required: true}, description: {required: true}, - main_image: {required: true, sizes: [{ width: 100, height: 100 }] }, + main_image: {required: true, sizes: [{ width: 100, height: 100 }]}, ctatext: {required: false}, sponsored_by: {required: true} }); @@ -215,7 +215,7 @@ describe('AppNexusAdapter', () => { const payload = JSON.parse(request.data); expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: {required: true, sizes: [{}] }, + main_image: {required: true, sizes: [{}]}, }); }); diff --git a/test/spec/modules/jcmBidAdapter_spec.js b/test/spec/modules/jcmBidAdapter_spec.js index 95356a9658e..27784def4f9 100644 --- a/test/spec/modules/jcmBidAdapter_spec.js +++ b/test/spec/modules/jcmBidAdapter_spec.js @@ -119,8 +119,8 @@ describe('jcmAdapter', () => { describe('getUserSyncs', () => { it('Verifies sync iframe option', () => { expect(spec.getUserSyncs({})).to.be.undefined; - expect(spec.getUserSyncs({ iframeEnabled: false})).to.be.undefined; - const options = spec.getUserSyncs({ iframeEnabled: true}); + expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; + const options = spec.getUserSyncs({ iframeEnabled: true }); expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); expect(options[0].type).to.equal('iframe'); @@ -128,8 +128,8 @@ describe('jcmAdapter', () => { }); it('Verifies sync image option', () => { - expect(spec.getUserSyncs({ image: false})).to.be.undefined; - const options = spec.getUserSyncs({ image: true}); + expect(spec.getUserSyncs({ image: false })).to.be.undefined; + const options = spec.getUserSyncs({ image: true }); expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); expect(options[0].type).to.equal('image'); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 7214e841b54..328cc1fa750 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -675,7 +675,7 @@ describe('S2S Adapter', () => { adapter: 'prebidServer' }; - config.setConfig({ s2sConfig: options}); + config.setConfig({ s2sConfig: options }); sinon.assert.calledOnce(logErrorSpy); }); diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 933b65c4574..b4793256ee0 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -182,8 +182,8 @@ describe('PulsePoint Adapter Tests', () => { const nativeResponse = { 'native': { assets: [ - { title: { text: 'Ad Title'} }, - { data: { type: 1, value: 'Sponsored By: Brand' }}, + { title: { text: 'Ad Title' } }, + { data: { type: 1, value: 'Sponsored By: Brand' } }, { img: { type: 3, url: 'http://images.cdn.brand.com/123' } } ], link: { url: 'http://brand.clickme.com/' }, @@ -240,13 +240,13 @@ describe('PulsePoint Adapter Tests', () => { expect(spec.isBidRequestValid({ params: {} })).to.equal(false); expect(spec.isBidRequestValid({ params: { ct: 123 } })).to.equal(false); expect(spec.isBidRequestValid({ params: { cp: 123 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { ct: 123, cp: 234 }})).to.equal(true); + expect(spec.isBidRequestValid({ params: { ct: 123, cp: 234 } })).to.equal(true); }); it('Verifies sync options', () => { expect(spec.getUserSyncs({})).to.be.undefined; - expect(spec.getUserSyncs({ iframeEnabled: false})).to.be.undefined; - const options = spec.getUserSyncs({ iframeEnabled: true}); + expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; + const options = spec.getUserSyncs({ iframeEnabled: true }); expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); expect(options[0].type).to.equal('iframe'); @@ -254,7 +254,7 @@ describe('PulsePoint Adapter Tests', () => { }); it('Verifies image pixel sync', () => { - const options = spec.getUserSyncs({ pixelEnabled: true}); + const options = spec.getUserSyncs({ pixelEnabled: true }); expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); expect(options[0].type).to.equal('image'); diff --git a/test/spec/modules/somoaudienceBidAdapter_spec.js b/test/spec/modules/somoaudienceBidAdapter_spec.js index a6078a9c4dc..2189cacb0ec 100644 --- a/test/spec/modules/somoaudienceBidAdapter_spec.js +++ b/test/spec/modules/somoaudienceBidAdapter_spec.js @@ -51,7 +51,7 @@ describe('Somo Audience Adapter Tests', () => { expect(spec.isBidRequestValid({})).to.equal(false); expect(spec.isBidRequestValid(bidderBadSet[0])).to.equal(false); expect(spec.isBidRequestValid({ params: {} })).to.equal(false); - expect(spec.isBidRequestValid({ params: { placementId: '12345' }})).to.equal(true); + expect(spec.isBidRequestValid({ params: { placementId: '12345' } })).to.equal(true); }); it('Verifies buildRequests', () => { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index bc9e86c0e0e..ca2a9afc103 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -155,7 +155,7 @@ describe('bidders created by newBidder', () => { const bidder = newBidder(spec); const url = 'test.url.com'; const data = { arg: 2 }; - const options = { contentType: 'application/json'}; + const options = { contentType: 'application/json' }; spec.isBidRequestValid.returns(true); spec.buildRequests.returns({ method: 'POST', diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index a515a7aa010..f772802f21f 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -365,7 +365,7 @@ describe('Unit: Prebid Module', function () { const customConfigObject = { 'buckets': [ { 'precision': 2, 'min': 0, 'max': 5, 'increment': 0.01 }, - { 'precision': 2, 'min': 5, 'max': 8, 'increment': 0.05}, + { 'precision': 2, 'min': 5, 'max': 8, 'increment': 0.05 }, { 'precision': 2, 'min': 8, 'max': 20, 'increment': 0.5 }, { 'precision': 2, 'min': 20, 'max': 25, 'increment': 1 } ] From 240fa95e0f07009c4952a70fdbfcb708dd130dcb Mon Sep 17 00:00:00 2001 From: Jurij Sinickij Date: Fri, 2 Mar 2018 18:38:53 +0200 Subject: [PATCH 0155/1594] VAST support in adform adapter (#2173) * support for video ads * updated readme --- modules/adformBidAdapter.js | 17 ++++- modules/adformBidAdapter.md | 2 +- test/spec/modules/adformBidAdapter_spec.js | 76 ++++++++++++++++++++-- 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index 4ff37566da9..9754653cfe4 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -1,10 +1,12 @@ 'use strict'; import {registerBidder} from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; const BIDDER_CODE = 'adform'; export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, VIDEO ], isBidRequestValid: function (bid) { return !!(bid.params.mid); }, @@ -64,14 +66,20 @@ export const spec = { } }, interpretResponse: function (serverResponse, bidRequest) { - var bidObject, response, bid; + const VALID_RESPONSES = { + banner: 1, + vast_content: 1, + vast_url: 1 + }; + var bidObject, response, bid, type; var bidRespones = []; var bids = bidRequest.bids; var responses = serverResponse.body; for (var i = 0; i < responses.length; i++) { response = responses[i]; + type = response.response === 'banner' ? BANNER : VIDEO; bid = bids[i]; - if (response.response === 'banner' && verifySize(response, bid.sizes)) { + if (VALID_RESPONSES[response.response] && (verifySize(response, bid.sizes) || type === VIDEO)) { bidObject = { requestId: bid.bidId, cpm: response.win_bid, @@ -84,7 +92,10 @@ export const spec = { ttl: 360, ad: response.banner, bidderCode: bidRequest.bidder, - transactionId: bid.transactionId + transactionId: bid.transactionId, + vastUrl: response.vast_url, + vastXml: response.vast_content, + mediaType: type }; bidRespones.push(bidObject); } diff --git a/modules/adformBidAdapter.md b/modules/adformBidAdapter.md index 9f357b21729..b2f67273a18 100644 --- a/modules/adformBidAdapter.md +++ b/modules/adformBidAdapter.md @@ -7,7 +7,7 @@ Maintainer: Scope.FL.Scripts@adform.com # Description Module that connects to Adform demand sources to fetch bids. -Banner formats are supported. +Banner and video formats are supported. # Test Parameters ``` diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index 8d8e8fc5683..a330f18e685 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -1,6 +1,7 @@ import {assert, expect} from 'chai'; import * as url from 'src/url'; import {spec} from 'modules/adformBidAdapter'; +import { BANNER, VIDEO } from 'src/mediaTypes'; describe('Adform adapter', () => { let serverResponse, bidRequest, bidResponses; @@ -29,7 +30,7 @@ describe('Adform adapter', () => { it('should pass multiple bids via single request', () => { let request = spec.buildRequests(bids); let parsedUrl = parseUrl(request.url); - assert.lengthOf(parsedUrl.items, 3); + assert.lengthOf(parsedUrl.items, 5); }); it('should handle global request parameters', () => { @@ -64,6 +65,16 @@ describe('Adform adapter', () => { transactionId: '5f33781f-9552-4iuy', priceType: 'gross' }, + { + mid: '3', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + }, + { + mid: '3', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + }, { mid: '3', pdom: 'home', @@ -135,14 +146,31 @@ describe('Adform adapter', () => { it('should create bid response item for every requested item', () => { let result = spec.interpretResponse(serverResponse, bidRequest); - assert.lengthOf(result, 3); + assert.lengthOf(result, 5); + }); + + it('should create bid response with vast xml', () => { + const result = spec.interpretResponse(serverResponse, bidRequest)[3]; + assert.equal(result.vastXml, ''); + }); + + it('should create bid response with vast url', () => { + const result = spec.interpretResponse(serverResponse, bidRequest)[4]; + assert.equal(result.vastUrl, 'vast://url'); + }); + + it('should set mediaType on bid response', () => { + const expected = [ BANNER, BANNER, BANNER, VIDEO, VIDEO ]; + const result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].mediaType, expected[i]); + } }); }); beforeEach(() => { let sizes = [[250, 300], [300, 250], [300, 600]]; - let adUnitCode = ['div-01', 'div-02', 'div-03']; - let placementCode = adUnitCode; + let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; let params = [{ mid: 1, url: 'some// there' }, {adxDomain: null, mid: 2, someVar: 'someValue', priceType: 'gross'}, { adxDomain: null, mid: 3, pdom: 'home' }]; bids = [ { @@ -179,6 +207,28 @@ describe('Adform adapter', () => { placementCode: placementCode[2], sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[3], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'adform', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'adform', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' } ]; serverResponse = { @@ -209,6 +259,24 @@ describe('Adform adapter', () => { width: 600, win_bid: 10, win_cur: 'EUR' + }, + { + deal_id: '123abc', + height: 300, + response: 'vast_content', + width: 600, + win_bid: 10, + win_cur: 'EUR', + vast_content: '' + }, + { + deal_id: '123abc', + height: 300, + response: 'vast_url', + width: 600, + win_bid: 10, + win_cur: 'EUR', + vast_url: 'vast://url' } ], headers: {} From c1d368bd7cea79173b551363fb87fd0ad03cbd8e Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Fri, 2 Mar 2018 08:52:22 -0800 Subject: [PATCH 0156/1594] Fix lint error (#2208) --- test/spec/modules/rockyouBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/rockyouBidAdapter_spec.js b/test/spec/modules/rockyouBidAdapter_spec.js index 7c06c41485c..f929b50d581 100644 --- a/test/spec/modules/rockyouBidAdapter_spec.js +++ b/test/spec/modules/rockyouBidAdapter_spec.js @@ -205,7 +205,7 @@ describe('RockYouAdapter', () => { let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.sizes = ['x', 'w']; - localBidRequest.mediaTypes = { banner: { sizes: ['y', 'z']} }; + localBidRequest.mediaTypes = { banner: { sizes: ['y', 'z'] } }; let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' From f7ee794b9ed2f85997900d6dead21c46f3f685ff Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 2 Mar 2018 13:23:04 -0700 Subject: [PATCH 0157/1594] fix mediaType being overwritten by undefined in rubicon bid adapter (#2209) --- modules/rubiconBidAdapter.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index cbf27a184fd..d314864d0d9 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -273,7 +273,6 @@ export const spec = { requestId: bidRequest.bidId, currency: 'USD', creativeId: ad.creative_id, - mediaType: ad.creative_type, cpm: ad.cpm || 0, dealId: ad.deal, ttl: 300, // 5 minutes @@ -284,6 +283,10 @@ export const spec = { } }; + if (ad.creative_type) { + bid.mediaType = ad.creative_type; + } + if (bidRequest.mediaType === 'video') { bid.width = bidRequest.params.video.playerWidth; bid.height = bidRequest.params.video.playerHeight; From c92a5909008ac069b432b9c3fab2be51c261f654 Mon Sep 17 00:00:00 2001 From: Kit Westneat Date: Fri, 2 Mar 2018 16:39:15 -0500 Subject: [PATCH 0158/1594] Auctionmanager spec refactor pr (#2155) * refactor auctionmanager_spec.js and getKeyValueTargetingPairs consolidate duplicated code into helper functions. * re-add timeout test removed in PR #2067 to auctionmanager_spec.js --- src/auction.js | 16 +- test/spec/auctionmanager_spec.js | 593 ++++++++++++++----------------- 2 files changed, 268 insertions(+), 341 deletions(-) diff --git a/src/auction.js b/src/auction.js index 5f8d364f855..78595aaf244 100644 --- a/src/auction.js +++ b/src/auction.js @@ -389,20 +389,24 @@ export function getStandardBidderSettings() { } export function getKeyValueTargetingPairs(bidderCode, custBidObj) { + if (!custBidObj) { + return {}; + } + var keyValues = {}; var bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; // 1) set the keys from "standard" setting or from prebid defaults - if (custBidObj && bidder_settings) { + if (bidder_settings) { // initialize default if not set const standardSettings = getStandardBidderSettings(); setKeys(keyValues, standardSettings, custBidObj); - } - // 2) set keys from specific bidder setting override if they exist - if (bidderCode && custBidObj && bidder_settings && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - setKeys(keyValues, bidder_settings[bidderCode], custBidObj); - custBidObj.sendStandardTargeting = bidder_settings[bidderCode].sendStandardTargeting; + // 2) set keys from specific bidder setting override if they exist + if (bidderCode && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + setKeys(keyValues, bidder_settings[bidderCode], custBidObj); + custBidObj.sendStandardTargeting = bidder_settings[bidderCode].sendStandardTargeting; + } } // set native key value targeting diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index c92871e5568..cf17ccac705 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -24,6 +24,87 @@ function timestamp() { return new Date().getTime(); } +const BIDDER_CODE = 'sampleBidder'; +const BIDDER_CODE1 = 'sampleBidder1'; + +const ADUNIT_CODE = 'adUnit-code'; +const ADUNIT_CODE1 = 'adUnit-code-1'; + +function mockBid(opts) { + let bidderCode = opts && opts.bidderCode; + + return { + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'bidderCode': bidderCode || BIDDER_CODE, + 'requestId': utils.getUniqueIdentifierStr(), + 'creativeId': 'id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }; +} + +function mockBidRequest(bid, opts) { + if (!bid) { + throw new Error('bid required'); + } + let bidderCode = opts && opts.bidderCode; + let adUnitCode = opts && opts.adUnitCode; + + let requestId = utils.getUniqueIdentifierStr(); + + return { + 'bidderCode': bidderCode || bid.bidderCode, + 'auctionId': '20882439e3238c', + 'bidderRequestId': requestId, + 'bids': [ + { + 'bidder': bidderCode || bid.bidderCode, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': adUnitCode || ADUNIT_CODE, + 'sizes': [[300, 250], [300, 600]], + 'bidId': bid.requestId, + 'bidderRequestId': requestId, + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }; +} + +function mockBidder(bidderCode, bids) { + let spec = { + code: bidderCode, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + + return spec; +} + +const TEST_BIDS = [mockBid()]; +const TEST_BID_REQS = TEST_BIDS.map(mockBidRequest); + +function mockAjaxBuilder() { + return function(url, callback) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callback.success('response body', { getResponseHeader: fakeResponse }); + }; +} + describe('auctionmanager.js', function () { let xhr; @@ -36,49 +117,56 @@ describe('auctionmanager.js', function () { }); describe('getKeyValueTargetingPairs', function () { + const DEFAULT_BID = { + cpm: 5.578, + pbLg: 5.50, + pbMg: 5.50, + pbHg: 5.57, + pbAg: 5.50, + + height: 300, + width: 250, + getSize() { + return this.height + 'x' + this.width; + }, + + adUnitCode: '12345', + bidderCode: 'appnexus', + adId: '1adId', + source: 'client', + mediaType: 'banner', + }; + + /* return the expected response for a given bid, filter by keys if given */ + function getDefaultExpected(bid, keys) { + var expected = { + 'hb_bidder': bid.bidderCode, + 'hb_adid': bid.adId, + 'hb_pb': bid.pbMg, + 'hb_size': bid.getSize(), + 'hb_source': bid.source, + 'hb_format': bid.mediaType, + }; + + if (!keys) { + return expected; + } + + return keys.reduce((map, key) => { + map[key] = expected[key]; + return map; + }, {}); + } + var bid = {}; - var bidPriceCpm = 5.578; - var bidPbLg = 5.50; - var bidPbMg = 5.50; - var bidPbHg = 5.57; - var bidPbAg = 5.50; - - var adUnitCode = '12345'; - var bidderCode = 'appnexus'; - var size = '300x250'; - var adId = '1adId'; - var source = 'client'; - var mediatype = 'banner'; before(function () { - bid.cpm = bidPriceCpm; - bid.pbLg = bidPbLg; - bid.pbMg = bidPbMg; - bid.pbHg = bidPbHg; - bid.pbAg = bidPbAg; - - bid.height = 300; - bid.width = 250; - bid.adUnitCode = adUnitCode; - bid.getSize = function () { - return this.height + 'x' + this.width; - }; - bid.bidderCode = bidderCode; - bid.adId = adId; - bid.source = source; - bid.mediaType = mediatype; + bid = Object.assign({}, DEFAULT_BID); }); it('No bidder level configuration defined - default', function () { - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbMg, - 'hb_size': size, - 'hb_source': source, - 'hb_format': mediatype, - }; - var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + var expected = getDefaultExpected(bid); + var response = getKeyValueTargetingPairs(bid.bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); assert.deepEqual(response, expected); }); @@ -126,15 +214,10 @@ describe('auctionmanager.js', function () { } }; - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbHg, - 'hb_size': size, - 'hb_source': source, - 'hb_format': mediatype, - }; - var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + var expected = getDefaultExpected(bid); + expected.hb_pb = bid.pbHg; + + var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); }); @@ -170,15 +253,10 @@ describe('auctionmanager.js', function () { } }; - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbHg, - 'hb_size': size, - 'hb_source': source, - 'hb_format': mediatype, - }; - var response = getKeyValueTargetingPairs(bidderCode, bid); + var expected = getDefaultExpected(bid); + expected.hb_pb = bid.pbHg; + + var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); }); @@ -213,16 +291,9 @@ describe('auctionmanager.js', function () { } }; + var expected = getDefaultExpected(bid); - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbMg, - 'hb_size': size, - 'hb_source': source, - 'hb_format': mediatype, - }; - var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); }); @@ -260,9 +331,10 @@ describe('auctionmanager.js', function () { } }; + var expected = getDefaultExpected(bid, ['hb_bidder', 'hb_adid']); + expected.hb_pb = 10.0; - var expected = { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': 10.0 }; - var response = getKeyValueTargetingPairs(bidderCode, bid); + var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); }); @@ -343,14 +415,10 @@ describe('auctionmanager.js', function () { } }; + var expected = getDefaultExpected(bid, ['hb_bidder', 'hb_adid', 'hb_size']); + expected.hb_pb = 15.0; - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': 15.0, - 'hb_size': '300x250' - }; - var response = getKeyValueTargetingPairs(bidderCode, bid); + var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); }); @@ -379,16 +447,10 @@ describe('auctionmanager.js', function () { ] } }; + var expected = getDefaultExpected(bid); + expected.hb_pb = 5.57; - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': 5.57, - 'hb_size': '300x250', - 'hb_source': source, - 'hb_format': mediatype, - }; - var response = getKeyValueTargetingPairs(bidderCode, bid); + var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); assert.equal(bid.sendStandardTargeting, false); }); @@ -415,7 +477,7 @@ describe('auctionmanager.js', function () { 'aKeyWithAValue': 42 }; - var response = getKeyValueTargetingPairs(bidderCode, bid); + var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); }); }); @@ -476,54 +538,13 @@ describe('auctionmanager.js', function () { let spec; let auction; let ajaxStub; - const BIDDER_CODE = 'sampleBidder'; - const BIDDER_CODE1 = 'sampleBidder1'; + let bids = TEST_BIDS; let makeRequestsStub; - let bids = [{ - 'ad': 'creative', - 'cpm': '1.99', - 'width': 300, - 'height': 250, - 'bidderCode': BIDDER_CODE, - 'requestId': '4d0a6829338a07', - 'creativeId': 'id', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 360 - }]; - - let bidRequests = [{ - 'bidderCode': BIDDER_CODE, - 'auctionId': '20882439e3238c', - 'bidderRequestId': '331f3cf3f1d9c8', - 'bids': [ - { - 'bidder': BIDDER_CODE, - 'params': { - 'placementId': 'id' - }, - 'adUnitCode': 'adUnit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '4d0a6829338a07', - 'bidderRequestId': '331f3cf3f1d9c8', - 'auctionId': '20882439e3238c' - } - ], - 'auctionStart': 1505250713622, - 'timeout': 3000 - }]; before(() => { makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); - makeRequestsStub.returns(bidRequests); - ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(function() { - return function(url, callback) { - const fakeResponse = sinon.stub(); - fakeResponse.returns('headerContent'); - callback.success('response body', { getResponseHeader: fakeResponse }); - } - }); + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder); }); after(() => { @@ -533,28 +554,27 @@ describe('auctionmanager.js', function () { describe('when auction timeout is 3000', () => { let loadScriptStub; + before(() => { + makeRequestsStub.returns(TEST_BID_REQS); + }); beforeEach(() => { adUnits = [{ - code: 'adUnit-code', + code: ADUNIT_CODE, bids: [ {bidder: BIDDER_CODE, params: {placementId: 'id'}}, ] }]; - adUnitCodes = ['adUnit-code']; + adUnitCodes = [ADUNIT_CODE]; auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000}); createAuctionStub = sinon.stub(auctionModule, 'newAuction'); createAuctionStub.returns(auction); - spec = { - code: BIDDER_CODE, - isBidRequestValid: sinon.stub(), - buildRequests: sinon.stub(), - interpretResponse: sinon.stub(), - getUserSyncs: sinon.stub() - }; loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { args[1](); }); + + spec = mockBidder(BIDDER_CODE, bids); + registerBidder(spec); }); afterEach(() => { @@ -562,57 +582,32 @@ describe('auctionmanager.js', function () { loadScriptStub.restore(); }); - it('should return proper price bucket increments for dense mode when cpm is in range 0-3', () => { - bids[0].cpm = '1.99'; - registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); - auction.callBids(); - let registeredBid = auction.getBidsReceived().pop(); - assert.equal(registeredBid.pbDg, '1.99', '0 - 3 hits at to 1 cent increment'); - }); + function checkPbDg(cpm, expected, msg) { + return function() { + bids[0].cpm = cpm; + auction.callBids(); - it('should return proper price bucket increments for dense mode when cpm is in range 3-8', () => { - bids[0].cpm = '4.39'; - registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); - auction.callBids(); - let registeredBid = auction.getBidsReceived().pop(); - assert.equal(registeredBid.pbDg, '4.35', '3 - 8 hits at 5 cent increment'); - }); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, expected, msg); + }; + }; - it('should return proper price bucket increments for dense mode when cpm is in range 8-20', () => { - bids[0].cpm = '19.99'; - registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); - auction.callBids(); - let registeredBid = auction.getBidsReceived().pop(); - assert.equal(registeredBid.pbDg, '19.50', '8 - 20 hits at 50 cent increment'); - }); + it('should return proper price bucket increments for dense mode when cpm is in range 0-3', + checkPbDg('1.99', '1.99', '0 - 3 hits at to 1 cent increment')); - it('should return proper price bucket increments for dense mode when cpm is 20+', () => { - bids[0].cpm = '73.07'; - registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); - auction.callBids(); - let registeredBid = auction.getBidsReceived().pop(); - assert.equal(registeredBid.pbDg, '20.00', '20+ caps at 20.00'); - }); + it('should return proper price bucket increments for dense mode when cpm is in range 3-8', + checkPbDg('4.39', '4.35', '3 - 8 hits at 5 cent increment')); + + it('should return proper price bucket increments for dense mode when cpm is in range 8-20', + checkPbDg('19.99', '19.50', '8 - 20 hits at 50 cent increment')); + + it('should return proper price bucket increments for dense mode when cpm is 20+', + checkPbDg('73.07', '20.00', '20+ caps at 20.00')); it('should place dealIds in adserver targeting', () => { bids[0].dealId = 'test deal'; - registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); assert.equal(registeredBid.adserverTargeting[`hb_deal`], 'test deal', 'dealId placed in adserverTargeting'); }); @@ -620,43 +615,22 @@ describe('auctionmanager.js', function () { it('should pass through default adserverTargeting sent from adapter', () => { bids[0].adserverTargeting = {}; bids[0].adserverTargeting.extra = 'stuff'; - registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); - assert.equal(registeredBid.adserverTargeting.hb_bidder, 'sampleBidder'); + assert.equal(registeredBid.adserverTargeting.hb_bidder, BIDDER_CODE); assert.equal(registeredBid.adserverTargeting.extra, 'stuff'); }); it('installs publisher-defined renderers on bids', () => { - let bidRequests = [{ - 'bidderCode': BIDDER_CODE, - 'auctionId': '20882439e3238c', - 'bidderRequestId': '331f3cf3f1d9c8', - 'bids': [ - { - 'bidder': BIDDER_CODE, - 'params': { - 'placementId': 'id' - }, - 'adUnitCode': 'adUnit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '4d0a6829338a07', - 'bidderRequestId': '331f3cf3f1d9c8', - 'auctionId': '20882439e3238c', - 'renderer': { - url: 'renderer.js', - render: (bid) => bid - } - } - ], - 'auctionStart': 1505250713622, - 'timeout': 3000 - }]; - + let renderer = { + url: 'renderer.js', + render: (bid) => bid + }; + let bidRequests = [Object.assign({}, TEST_BID_REQS[0])]; + bidRequests[0].bids[0] = Object.assign({ renderer }, bidRequests[0].bids[0]); makeRequestsStub.returns(bidRequests); + let bids1 = Object.assign({}, bids[0], { @@ -664,15 +638,72 @@ describe('auctionmanager.js', function () { mediaType: 'video-outstream', } ); - registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); spec.interpretResponse.returns(bids1); auction.callBids(); const addedBid = auction.getBidsReceived().pop(); assert.equal(addedBid.renderer.url, 'renderer.js'); }); }); + + describe('when auction timeout is 20', () => { + let loadScriptStub; + let eventsEmitSpy; + let getBidderRequestStub; + + before(() => { + bids = [mockBid(), mockBid({ bidderCode: BIDDER_CODE1 })]; + let bidRequests = bids.map(bid => mockBidRequest(bid)); + + makeRequestsStub.returns(bidRequests); + }); + + beforeEach(() => { + adUnits = [{ + code: ADUNIT_CODE, + bids: [ + {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + ] + }]; + adUnitCodes = [ADUNIT_CODE]; + + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 20}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + + spec = mockBidder(BIDDER_CODE, [bids[0]]); + registerBidder(spec); + + // Timeout is checked when bid is received. If that bid is the only one + // auction is waiting for, timeout is not emitted, so we need to add a + // second bidder to get timeout event. + let spec1 = mockBidder(BIDDER_CODE1, [bids[1]]); + registerBidder(spec1); + + eventsEmitSpy = sinon.spy(events, 'emit'); + + let origGBR = utils.getBidderRequest; + getBidderRequestStub = sinon.stub(utils, 'getBidderRequest'); + getBidderRequestStub.callsFake((bidRequests, bidder, adUnitCode) => { + let req = origGBR(bidRequests, bidder, adUnitCode); + req.start = 1000; + return req; + }); + }); + afterEach(() => { + auctionModule.newAuction.restore(); + loadScriptStub.restore(); + events.emit.restore(); + getBidderRequestStub.restore(); + }); + it('should emit BID_TIMEOUT for timed out bids', () => { + auction.callBids(); + assert.ok(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BID_TIMEOUT), 'emitted events BID_TIMEOUT'); + }); + }); }); describe('addBidResponse', () => { @@ -683,87 +714,19 @@ describe('auctionmanager.js', function () { let spec1; let auction; let ajaxStub; - const BIDDER_CODE = 'sampleBidder'; - const BIDDER_CODE1 = 'sampleBidder1'; - let makeRequestsStub; - let bids = [{ - 'ad': 'creative', - 'cpm': '1.99', - 'width': 300, - 'height': 250, - 'bidderCode': BIDDER_CODE, - 'requestId': '4d0a6829338a07', - 'creativeId': 'id', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 360 - }]; - - let bids1 = [{ - 'ad': 'creative', - 'cpm': '1.99', - 'width': 300, - 'height': 250, - 'bidderCode': BIDDER_CODE1, - 'requestId': '5d0a6829338a07', - 'creativeId': 'id', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 360 - }]; - - let bidRequests = [{ - 'bidderCode': BIDDER_CODE, - 'auctionId': '20882439e3238c', - 'bidderRequestId': '331f3cf3f1d9c8', - 'bids': [ - { - 'bidder': BIDDER_CODE, - 'params': { - 'placementId': 'id' - }, - 'adUnitCode': 'adUnit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '4d0a6829338a07', - 'bidderRequestId': '331f3cf3f1d9c8', - 'auctionId': '20882439e3238c' - } - ], - 'auctionStart': 1505250713622, - 'timeout': 3000 - }, { - 'bidderCode': BIDDER_CODE1, - 'auctionId': '20882439e3238c', - 'bidderRequestId': '661f3cf3f1d9c8', - 'bids': [ - { - 'bidder': BIDDER_CODE1, - 'params': { - 'placementId': 'id' - }, - 'adUnitCode': 'adUnit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '5d0a6829338a07', - 'bidderRequestId': '661f3cf3f1d9c8', - 'auctionId': '20882439e3238c' - } - ], - 'auctionStart': 1505250713623, - 'timeout': 3000 - }]; + let bids = TEST_BIDS; + let bids1 = [mockBid({ bidderCode: BIDDER_CODE1 })]; before(() => { - makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + let bidRequests = [ + mockBidRequest(bids[0]), + mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 }) + ]; + let makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); makeRequestsStub.returns(bidRequests); - ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(function() { - return function(url, callback) { - const fakeResponse = sinon.stub(); - fakeResponse.returns('headerContent'); - callback.success('response body', { getResponseHeader: fakeResponse }); - } - }); + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder); }); after(() => { @@ -773,36 +736,26 @@ describe('auctionmanager.js', function () { beforeEach(() => { adUnits = [{ - code: 'adUnit-code', + code: ADUNIT_CODE, bids: [ {bidder: BIDDER_CODE, params: {placementId: 'id'}}, ] }, { - code: 'adUnit-code-1', + code: ADUNIT_CODE1, bids: [ {bidder: BIDDER_CODE1, params: {placementId: 'id'}}, ] }]; - adUnitCodes = ['adUnit-code', 'adUnit-code-1']; + adUnitCodes = adUnits.map(({ code }) => code); auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000}); createAuctionStub = sinon.stub(auctionModule, 'newAuction'); createAuctionStub.returns(auction); - spec = { - code: BIDDER_CODE, - isBidRequestValid: sinon.stub(), - buildRequests: sinon.stub(), - interpretResponse: sinon.stub(), - getUserSyncs: sinon.stub() - }; + spec = mockBidder(BIDDER_CODE, bids); + spec1 = mockBidder(BIDDER_CODE1, bids1); - spec1 = { - code: BIDDER_CODE1, - isBidRequestValid: sinon.stub(), - buildRequests: sinon.stub(), - interpretResponse: sinon.stub(), - getUserSyncs: sinon.stub() - }; + registerBidder(spec); + registerBidder(spec1); }); afterEach(() => { @@ -810,17 +763,6 @@ describe('auctionmanager.js', function () { }); it('should not alter bid adID', () => { - registerBidder(spec); - registerBidder(spec1); - - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); - - spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec1.isBidRequestValid.returns(true); - spec1.interpretResponse.returns(bids1); - auction.callBids(); const addedBid2 = auction.getBidsReceived().pop(); @@ -833,17 +775,6 @@ describe('auctionmanager.js', function () { bids1[0].width = undefined; bids1[0].height = undefined; - registerBidder(spec); - registerBidder(spec1); - - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); - spec.interpretResponse.returns(bids); - - spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec1.isBidRequestValid.returns(true); - spec1.interpretResponse.returns(bids1); - auction.callBids(); let length = auction.getBidsReceived().length; @@ -859,15 +790,7 @@ describe('auctionmanager.js', function () { const bidsCopy = [Object.assign({}, bids[0], { mediaType: 'video' })]; const bids1Copy = [Object.assign({}, bids1[0], { mediaType: 'video' })]; - registerBidder(spec); - registerBidder(spec1); - - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec.isBidRequestValid.returns(true); spec.interpretResponse.returns(bidsCopy); - - spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); - spec1.isBidRequestValid.returns(true); spec1.interpretResponse.returns(bids1Copy); auction.callBids(); From 95fe0a58dca508c6c60da03e55bf28c1d0d1780b Mon Sep 17 00:00:00 2001 From: moonshells <33766472+moonshells@users.noreply.github.com> Date: Fri, 2 Mar 2018 15:04:53 -0800 Subject: [PATCH 0159/1594] Update position default value in rubicon (#2214) --- modules/rubiconBidAdapter.js | 9 ++++- test/spec/modules/rubiconBidAdapter_spec.js | 44 +++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index d314864d0d9..625d34b0648 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -138,7 +138,7 @@ export const spec = { let slotData = { site_id: params.siteId, zone_id: params.zoneId, - position: params.position || 'unknown', + position: parsePosition(params.position), floor: parseFloat(params.floor) > 0.01 ? params.floor : 0.01, element_id: bidRequest.adUnitCode, name: bidRequest.adUnitCode, @@ -393,6 +393,13 @@ function mapSizes(sizes) { }, []); } +function parsePosition(position) { + if (position === 'atf' || position === 'btf') { + return position; + } + return 'unknown'; +} + export function masSizeOrdering(sizes) { const MAS_SIZE_PRIORITY = [15, 2, 9]; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 6e27bdb87d8..1c4bccc69c5 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -512,6 +512,50 @@ describe('the rubicon adapter', () => { expect(slot.visitor).to.have.property('lastsearch').that.equals('iphone'); }); + it('should send request with proper ad position', () => { + createVideoBidderRequest(); + var positionBidderRequest = clone(bidderRequest); + positionBidderRequest.bids[0].params.position = 'atf'; + let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); + let post = request.data; + let slot = post.slots[0]; + + expect(slot.position).to.equal('atf'); + + positionBidderRequest = clone(bidderRequest); + positionBidderRequest.bids[0].params.position = 'btf'; + [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); + post = request.data; + slot = post.slots[0]; + + expect(slot.position).to.equal('btf'); + + positionBidderRequest = clone(bidderRequest); + positionBidderRequest.bids[0].params.position = 'unknown'; + [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); + post = request.data; + slot = post.slots[0]; + + expect(slot.position).to.equal('unknown'); + + positionBidderRequest = clone(bidderRequest); + positionBidderRequest.bids[0].params.position = '123'; + [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); + post = request.data; + slot = post.slots[0]; + + expect(slot.position).to.equal('unknown'); + + positionBidderRequest = clone(bidderRequest); + delete positionBidderRequest.bids[0].params.position; + expect(positionBidderRequest.bids[0].params.position).to.equal(undefined); + [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); + post = request.data; + slot = post.slots[0]; + + expect(slot.position).to.equal('unknown'); + }); + it('should allow a floor price override', () => { createVideoBidderRequest(); From c54a1795c73314db07071e8437681694762e8658 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Tue, 6 Mar 2018 01:43:25 +0000 Subject: [PATCH 0160/1594] Audience Network: allow native bids for non-IAB sizes (#2203) --- modules/audienceNetworkBidAdapter.js | 29 ++++++++++- .../modules/audienceNetworkBidAdapter_spec.js | 49 +++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 3153a64a48d..ed78f336102 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -26,7 +26,8 @@ const isBidRequestValid = bid => typeof bid.params.placementId === 'string' && bid.params.placementId.length > 0 && Array.isArray(bid.sizes) && bid.sizes.length > 0 && - (isVideo(bid.params.format) || bid.sizes.map(flattenSize).some(isValidSize)); + (isFullWidth(bid.params.format) ? bid.sizes.map(flattenSize).every(size => size === '300x250') : true) && + (isValidNonSizedFormat(bid.params.format) || bid.sizes.map(flattenSize).some(isValidSize)); /** * Flattens a 2-element [W, H] array as a 'WxH' string, @@ -51,6 +52,23 @@ const expandSize = size => size.split('x').map(Number); */ const isValidSize = size => includes(['300x250', '320x50'], size); +/** + * Is this a valid, non-sized format? + * @param {String} size + * @returns {Boolean} + */ +const isValidNonSizedFormat = format => includes(['video', 'native'], format); + +/** + * Is this a valid size and format? + * @param {String} size + * @returns {Boolean} + */ +const isValidSizeAndFormat = (size, format) => + (isFullWidth(format) && flattenSize(size) === '300x250') || + isValidNonSizedFormat(format) || + isValidSize(flattenSize(size)); + /** * Is this a video format? * @param {String} format @@ -58,6 +76,13 @@ const isValidSize = size => includes(['300x250', '320x50'], size); */ const isVideo = format => format === 'video'; +/** + * Is this a fullwidth format? + * @param {String} format + * @returns {Boolean} + */ +const isFullWidth = format => format === 'fullwidth'; + /** * Which SDK version should be used for this format? * @param {String} format @@ -120,7 +145,7 @@ const buildRequests = bids => { bids.forEach(bid => bid.sizes .map(flattenSize) - .filter(size => isValidSize(size) || isVideo(bid.params.format)) + .filter(size => isValidSizeAndFormat(size, bid.params.format)) .slice(0, 1) .forEach(size => { placementids.push(bid.params.placementId); diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index 6b21eb459d4..d92597c913c 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -92,6 +92,17 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); + it('native with non-IAB size', () => { + expect(isBidRequestValid({ + bidder, + sizes: [[728, 90]], + params: { + placementId, + format: 'native' + } + })).to.equal(true); + }); + it('video', () => { expect(isBidRequestValid({ bidder, @@ -139,6 +150,44 @@ describe('AudienceNetwork adapter', () => { data: 'placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=&sdk[]=&playerwidth=640&playerheight=480' }]); }); + + it('can build URL for native unit in non-IAB size', () => { + expect(buildRequests([{ + bidder, + bidId: requestId, + sizes: [[728, 90]], + params: { + placementId, + format: 'native' + } + }])).to.deep.equal([{ + adformats: ['native'], + method: 'GET', + requestIds: [requestId], + sizes: ['728x90'], + url: 'https://an.facebook.com/v2/placementbid.json', + data: 'placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=&sdk[]=5.5.web' + }]); + }); + + it('can build URL for fullwidth 300x250 unit', () => { + expect(buildRequests([{ + bidder, + bidId: requestId, + sizes: [[300, 250]], + params: { + placementId, + format: 'fullwidth' + } + }])).to.deep.equal([{ + adformats: ['fullwidth'], + method: 'GET', + requestIds: [requestId], + sizes: ['300x250'], + url: 'https://an.facebook.com/v2/placementbid.json', + data: 'placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=&sdk[]=5.5.web' + }]); + }); }); describe('interpretResponse', () => { From b82f8523e1dceee38ecd445b8ce710b2db58c1ab Mon Sep 17 00:00:00 2001 From: Vladislav Isaiko Date: Tue, 6 Mar 2018 19:26:33 +0200 Subject: [PATCH 0161/1594] Smartyads Adapter 1.x (#2080) * add SmartyAds adapter 1.0 * amendment Smartyads adapter --- modules/smartyadsBidAdapter.js | 91 +++++++ modules/smartyadsBidAdapter.md | 27 ++ package.json | 2 +- test/spec/modules/smartyadsBidAdapter_spec.js | 230 ++++++++++++++++++ 4 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 modules/smartyadsBidAdapter.js create mode 100644 modules/smartyadsBidAdapter.md create mode 100644 test/spec/modules/smartyadsBidAdapter_spec.js diff --git a/modules/smartyadsBidAdapter.js b/modules/smartyadsBidAdapter.js new file mode 100644 index 00000000000..0c553b567ef --- /dev/null +++ b/modules/smartyadsBidAdapter.js @@ -0,0 +1,91 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'smartyads'; +const URL = '//ssp-nj.webtradehub.com/?c=o&m=multi'; +const URL_SYNC = '//ssp-nj.webtradehub.com/?c=o&m=cookie'; + +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.title && bid.image && bid.impressionTrackers); + default: + return false; + } +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + + isBidRequestValid: (bid) => { + return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placementId)); + }, + + buildRequests: (validBidRequests = []) => { + let winTop = window; + try { + window.top.location.toString(); + winTop = window.top; + } catch (e) { + utils.logMessage(e); + } + let location = utils.getTopWindowLocation(); + let placements = []; + let request = { + '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 + }; + const len = validBidRequests.length; + for (let i = 0; i < len; i++) { + let bid = validBidRequests[i]; + placements.push({ + placementId: bid.params.placementId, + bidId: bid.bidId, + traffic: bid.params.traffic || BANNER + }); + } + return { + method: 'POST', + url: 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)) { + delete resItem.mediaType; + response.push(resItem); + } + } + return response; + }, + + getUserSyncs: (syncOptions, serverResponses) => { + return [{ + type: 'image', + url: URL_SYNC + }]; + } + +}; + +registerBidder(spec); diff --git a/modules/smartyadsBidAdapter.md b/modules/smartyadsBidAdapter.md new file mode 100644 index 00000000000..5102a6fd128 --- /dev/null +++ b/modules/smartyadsBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +``` +Module Name: SmartyAds Bidder Adapter +Module Type: Bidder Adapter +Maintainer: supply@smartyads.com +``` + +# Description + +Module that connects to SmartyAds' demand sources + +# Test Parameters +``` + var adUnits = [{ + code: 'placementId_0', + sizes: [[300, 250]], + bids: [{ + bidder: 'smartyads', + params: { + placementId: 0, + traffic: 'banner' + } + }] + } + ]; +``` \ No newline at end of file diff --git a/package.json b/package.json index f7cc918892d..39b3a65de4b 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "eslint-plugin-standard": "^3.0.1", "faker": "^3.1.0", "fs.extra": "^1.3.2", - "gulp": "^3.8.7", + "gulp": "^3.9.1", "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", diff --git a/test/spec/modules/smartyadsBidAdapter_spec.js b/test/spec/modules/smartyadsBidAdapter_spec.js new file mode 100644 index 00000000000..858e8bf37a0 --- /dev/null +++ b/test/spec/modules/smartyadsBidAdapter_spec.js @@ -0,0 +1,230 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/smartyadsBidAdapter'; + +describe('SmartyadsAdapter', () => { + let bid = { + bidId: '23fhj33i987f', + bidder: 'smartyads', + params: { + placementId: 0, + traffic: 'banner' + } + }; + + describe('isBidRequestValid', () => { + it('Should return true if there are bidId, params and placementId parameters present', () => { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false if at least one of parameters is not present', () => { + delete bid.params.placementId; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', () => { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', () => { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', () => { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', () => { + expect(serverRequest.url).to.equal('//ssp-nj.webtradehub.com/?c=o&m=multi'); + }); + it('Returns valid data if array of bids is valid', () => { + 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'); + let placement = data['placements'][0]; + expect(placement).to.have.keys('placementId', 'bidId', 'traffic'); + expect(placement.placementId).to.equal(0); + expect(placement.bidId).to.equal('23fhj33i987f'); + expect(placement.traffic).to.equal('banner'); + }); + it('Returns empty data if no valid requests are passed', () => { + serverRequest = spec.buildRequests([]); + let data = serverRequest.data; + expect(data.placements).to.be.an('array').that.is.empty; + }); + }); + describe('interpretResponse', () => { + it('Should interpret banner response', () => { + 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'); + 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', () => { + 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'); + expect(dataItem.mediaType).to.not.exist; + 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', () => { + const native = { + body: [{ + mediaType: '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', 'clickUrl', 'impressionTrackers', 'title', 'image', 'ttl', 'creativeId', 'netRevenue', 'currency'); + expect(dataItem.mediaType).to.not.exist; + expect(dataItem.requestId).to.equal('23fhj33i987f'); + expect(dataItem.cpm).to.equal(0.4); + expect(dataItem.clickUrl).to.equal('test.com'); + expect(dataItem.title).to.equal('Test'); + expect(dataItem.image).to.equal('test.com'); + expect(dataItem.impressionTrackers).to.be.an('array').that.is.not.empty; + expect(dataItem.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', () => { + 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', () => { + 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', () => { + 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', () => { + 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', () => { + let userSync = spec.getUserSyncs(); + it('Returns valid URL and type', () => { + 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('//ssp-nj.webtradehub.com/?c=o&m=cookie'); + }); + }); +}); From ae341f956755f16fc2ff7d5a6f480008334cfbe9 Mon Sep 17 00:00:00 2001 From: John Salis Date: Tue, 6 Mar 2018 12:29:11 -0500 Subject: [PATCH 0162/1594] Add banner support to Beachfront adapter (#2117) * Update Beachfront adapter for v1.0 * Revert Beachfront test endpoint * Add Beachfront markdown file * Add mediaTypes to example * Fix formatting * Remove descriptionUrl from bid response * Add banner support to Beachfront adapter * Fix bid response validation * Update display endpoint * Update display request and response to support multiple bids * Remove console log * Added display example to doc * Add support for dnt * add os version to bid request * Use size from bid response * Add secure to bid request --- modules/beachfrontBidAdapter.js | 187 +++++++-- modules/beachfrontBidAdapter.md | 12 + .../spec/modules/beachfrontBidAdapter_spec.js | 357 +++++++++++++----- 3 files changed, 424 insertions(+), 132 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index d4fcc3e3578..20d85ac0b22 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -1,89 +1,196 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { VIDEO, BANNER } from 'src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; -export const ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; +const ADAPTER_VERSION = '1.0'; +const ADAPTER_NAME = 'BFIO_PREBID'; + +export const VIDEO_ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; +export const BANNER_ENDPOINT = '//display.bfmio.com/prebid_display'; export const spec = { code: 'beachfront', - supportedMediaTypes: ['video'], + supportedMediaTypes: [ VIDEO, BANNER ], isBidRequestValid(bid) { return !!(bid && bid.params && bid.params.appId && bid.params.bidfloor); }, buildRequests(bids) { - return bids.map(bid => { - return { + let requests = []; + let videoBids = bids.filter(bid => isVideoBid(bid)); + let bannerBids = bids.filter(bid => !isVideoBid(bid)); + videoBids.forEach(bid => { + requests.push({ method: 'POST', - url: ENDPOINT + bid.params.appId, - data: createRequestParams(bid), + url: VIDEO_ENDPOINT + bid.params.appId, + data: createVideoRequestData(bid), bidRequest: bid - }; + }); }); + if (bannerBids.length) { + requests.push({ + method: 'POST', + url: BANNER_ENDPOINT, + data: createBannerRequestData(bannerBids), + bidRequest: bannerBids + }); + } + return requests; }, interpretResponse(response, { bidRequest }) { response = response.body; - if (!response || !response.url || !response.bidPrice) { - utils.logWarn(`No valid bids from ${spec.code} bidder`); - return []; + + if (isVideoBid(bidRequest)) { + if (!response || !response.url || !response.bidPrice) { + utils.logWarn(`No valid video bids from ${spec.code} bidder`); + return []; + } + let size = getFirstSize(bidRequest); + return { + requestId: bidRequest.bidId, + bidderCode: spec.code, + vastUrl: response.url, + cpm: response.bidPrice, + width: size.w, + height: size.h, + creativeId: response.cmpId, + mediaType: VIDEO, + currency: 'USD', + netRevenue: true, + ttl: 300 + }; + } else { + if (!response || !response.length) { + utils.logWarn(`No valid banner bids from ${spec.code} bidder`); + return []; + } + return response.map((bid) => { + let request = find(bidRequest, req => req.adUnitCode === bid.slot); + return { + requestId: request.bidId, + bidderCode: spec.code, + ad: bid.adm, + creativeId: bid.crid, + cpm: bid.price, + width: bid.w, + height: bid.h, + mediaType: BANNER, + currency: 'USD', + netRevenue: true, + ttl: 300 + }; + }); } - let size = getSize(bidRequest.sizes); - return { - requestId: bidRequest.bidId, - bidderCode: spec.code, - cpm: response.bidPrice, - creativeId: response.cmpId, - vastUrl: response.url, - width: size.width, - height: size.height, - mediaType: 'video', - currency: 'USD', - ttl: 300, - netRevenue: true - }; } }; -function getSize(sizes) { - let parsedSizes = utils.parseSizesInput(sizes); - let [ width, height ] = parsedSizes.length ? parsedSizes[0].split('x') : []; - return { - width: parseInt(width, 10) || undefined, - height: parseInt(height, 10) || undefined - }; +function getSizes(bid) { + return utils.parseSizesInput(bid.sizes).map(size => { + let [ width, height ] = size.split('x'); + return { + w: parseInt(width, 10) || undefined, + h: parseInt(height, 10) || undefined + }; + }); +} + +function getFirstSize(bid) { + let sizes = getSizes(bid); + return sizes.length ? sizes[0] : { w: undefined, h: undefined }; +} + +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 isMobile() { - return (/(ios|ipod|ipad|iphone|android)/i).test(global.navigator.userAgent); + 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(global.navigator.userAgent); + 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 isVideoBid(bid) { + return bid.mediaTypes && bid.mediaTypes.video; } -function createRequestParams(bid) { - let size = getSize(bid.sizes); +function createVideoRequestData(bid) { + let size = getFirstSize(bid); + let topLocation = utils.getTopWindowLocation(); return { isPrebid: true, appId: bid.params.appId, domain: document.location.hostname, + id: utils.getUniqueIdentifierStr(), imp: [{ video: { - w: size.width, - h: size.height + w: size.w, + h: size.h }, bidfloor: bid.params.bidfloor }], site: { - page: utils.getTopWindowLocation().host + page: topLocation.host }, device: { - ua: global.navigator.userAgent, - devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2 + ua: navigator.userAgent, + devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, + geo: {} }, cur: ['USD'] }; } +function createBannerRequestData(bids) { + let topLocation = utils.getTopWindowLocation(); + let referrer = utils.getTopWindowReferrer(); + let slots = bids.map(bid => { + return { + slot: bid.adUnitCode, + id: bid.params.appId, + bidfloor: bid.params.bidfloor, + sizes: getSizes(bid) + }; + }); + return { + slots: slots, + page: topLocation.href, + domain: topLocation.hostname, + search: topLocation.search, + secure: topLocation.protocol === 'https:' ? 1 : 0, + referrer: referrer, + ua: navigator.userAgent, + deviceOs: getOsVersion(), + isMobile: isMobile() ? 1 : 0, + dnt: getDoNotTrack() ? 1 : 0, + adapterVersion: ADAPTER_VERSION, + adapterName: ADAPTER_NAME + }; +} + registerBidder(spec); diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index 27c28d6c86e..3ea52c14ab0 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -30,6 +30,18 @@ Module that connects to Beachfront's demand sources } } ] + }, { + code: 'test-banner', + sizes: [300, 250], + bids: [ + { + bidder: 'beachfront', + params: { + bidfloor: 0.01, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + } + } + ] } ]; ``` \ No newline at end of file diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 92e16573972..24b97306388 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,31 +1,46 @@ import { expect } from 'chai'; -import { spec, ENDPOINT } from 'modules/beachfrontBidAdapter'; +import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT } from 'modules/beachfrontBidAdapter'; import * as utils from 'src/utils'; describe('BeachfrontAdapter', () => { - let bidRequest; + let bidRequests; beforeEach(() => { - bidRequest = { - bidder: 'beachfront', - params: { - bidfloor: 5.00, - appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' - }, - adUnitCode: 'adunit-code', - sizes: [ 640, 480 ], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }; + bidRequests = [ + { + bidder: 'beachfront', + params: { + bidfloor: 2.00, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + }, + adUnitCode: 'div-gpt-ad-1460505748561-0', + sizes: [ 300, 250 ], + bidId: '25186806a41eab', + bidderRequestId: '15bdd8d4a0ebaf', + auctionId: 'f17d62d0-e3e3-48d0-9f73-cb4ea358a309' + }, { + bidder: 'beachfront', + params: { + bidfloor: 1.00, + appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' + }, + adUnitCode: 'div-gpt-ad-1460505748561-1', + sizes: [ 300, 600 ], + bidId: '365088ee6d649d', + bidderRequestId: '15bdd8d4a0ebaf', + auctionId: 'f17d62d0-e3e3-48d0-9f73-cb4ea358a309' + } + ]; }); describe('spec.isBidRequestValid', () => { it('should return true when the required params are passed', () => { + const bidRequest = bidRequests[0]; expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); it('should return false when the "bidfloor" param is missing', () => { + const bidRequest = bidRequests[0]; bidRequest.params = { appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' }; @@ -33,6 +48,7 @@ describe('BeachfrontAdapter', () => { }); it('should return false when the "appId" param is missing', () => { + const bidRequest = bidRequests[0]; bidRequest.params = { bidfloor: 5.00 }; @@ -40,6 +56,7 @@ describe('BeachfrontAdapter', () => { }); it('should return false when no bid params are passed', () => { + const bidRequest = bidRequests[0]; bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); @@ -51,98 +68,254 @@ describe('BeachfrontAdapter', () => { }); describe('spec.buildRequests', () => { - it('should create a POST request for every bid', () => { - const requests = spec.buildRequests([ bidRequest ]); - expect(requests[0].method).to.equal('POST'); - expect(requests[0].url).to.equal(ENDPOINT + bidRequest.params.appId); - }); + describe('for video bids', () => { + it('should attach the bid request object', () => { + bidRequests[0].mediaTypes = { video: {} }; + bidRequests[1].mediaTypes = { video: {} }; + const requests = spec.buildRequests(bidRequests); + expect(requests[0].bidRequest).to.equal(bidRequests[0]); + expect(requests[1].bidRequest).to.equal(bidRequests[1]); + }); - it('should attach the bid request object', () => { - const requests = spec.buildRequests([ bidRequest ]); - expect(requests[0].bidRequest).to.equal(bidRequest); - }); + it('should create a POST request for each bid', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + const requests = spec.buildRequests([ bidRequest ]); + expect(requests[0].method).to.equal('POST'); + expect(requests[0].url).to.equal(VIDEO_ENDPOINT + bidRequest.params.appId); + }); - it('should attach request data', () => { - const requests = spec.buildRequests([ bidRequest ]); - const data = requests[0].data; - const [ width, height ] = bidRequest.sizes; - expect(data.isPrebid).to.equal(true); - expect(data.appId).to.equal(bidRequest.params.appId); - expect(data.domain).to.equal(document.location.hostname); - expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); - expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); - expect(data.site).to.deep.equal({ page: utils.getTopWindowLocation().host }); - expect(data.device).to.deep.contain({ ua: navigator.userAgent }); - expect(data.cur).to.deep.equal(['USD']); - }); + it('should attach request data', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + const [ width, height ] = bidRequest.sizes; + expect(data.isPrebid).to.equal(true); + expect(data.appId).to.equal(bidRequest.params.appId); + expect(data.domain).to.equal(document.location.hostname); + expect(data.id).to.be.a('string'); + expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); + expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); + expect(data.site).to.deep.equal({ page: utils.getTopWindowLocation().host }); + expect(data.device).to.deep.contain({ ua: navigator.userAgent }); + expect(data.cur).to.deep.equal(['USD']); + }); - it('must parse bid size from a nested array', () => { - const width = 640; - const height = 480; - bidRequest.sizes = [[ width, height ]]; - const requests = spec.buildRequests([ bidRequest ]); - const data = requests[0].data; - expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); - }); + it('must parse bid size from a nested array', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.sizes = [[ width, height ]]; + bidRequest.mediaTypes = { video: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); + }); - it('must parse bid size from a string', () => { - const width = 640; - const height = 480; - bidRequest.sizes = `${width}x${height}`; - const requests = spec.buildRequests([ bidRequest ]); - const data = requests[0].data; - expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); + it('must parse bid size from a string', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.sizes = `${width}x${height}`; + bidRequest.mediaTypes = { video: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); + }); + + it('must handle an empty bid size', () => { + const bidRequest = bidRequests[0]; + bidRequest.sizes = []; + bidRequest.mediaTypes = { video: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.imp[0].video).to.deep.equal({ w: undefined, h: undefined }); + }); }); - it('must handle an empty bid size', () => { - bidRequest.sizes = []; - const requests = spec.buildRequests([ bidRequest ]); - const data = requests[0].data; - expect(data.imp[0].video).to.deep.equal({ w: undefined, h: undefined }); + describe('for banner bids', () => { + it('should attach the bid requests array', () => { + bidRequests[0].mediaTypes = { banner: {} }; + bidRequests[1].mediaTypes = { banner: {} }; + const requests = spec.buildRequests(bidRequests); + expect(requests[0].bidRequest).to.deep.equal(bidRequests); + }); + + it('should create a single POST request for all bids', () => { + bidRequests[0].mediaTypes = { banner: {} }; + bidRequests[1].mediaTypes = { banner: {} }; + const requests = spec.buildRequests(bidRequests); + expect(requests.length).to.equal(1); + expect(requests[0].method).to.equal('POST'); + expect(requests[0].url).to.equal(BANNER_ENDPOINT); + }); + + it('should attach request data', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { banner: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + const [ width, height ] = bidRequest.sizes; + const topLocation = utils.getTopWindowLocation(); + expect(data.slots).to.deep.equal([ + { + slot: bidRequest.adUnitCode, + id: bidRequest.params.appId, + bidfloor: bidRequest.params.bidfloor, + sizes: [{ w: width, h: height }] + } + ]); + expect(data.page).to.equal(topLocation.href); + expect(data.domain).to.equal(topLocation.hostname); + expect(data.search).to.equal(topLocation.search); + expect(data.ua).to.equal(navigator.userAgent); + }); + + it('must parse bid size from a nested array', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.sizes = [[ width, height ]]; + bidRequest.mediaTypes = { banner: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.slots[0].sizes).to.deep.equal([ + { w: width, h: height } + ]); + }); + + it('must parse bid size from a string', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.sizes = `${width}x${height}`; + bidRequest.mediaTypes = { banner: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.slots[0].sizes).to.deep.equal([ + { w: width, h: height } + ]); + }); + + it('must handle an empty bid size', () => { + const bidRequest = bidRequests[0]; + bidRequest.sizes = []; + bidRequest.mediaTypes = { banner: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.slots[0].sizes).to.deep.equal([]); + }); }); }); describe('spec.interpretResponse', () => { - it('should return no bids if the response is not valid', () => { - const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); - expect(bidResponse.length).to.equal(0); - }); + describe('for video bids', () => { + it('should return no bids if the response is not valid', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); - it('should return no bids if the response "url" is missing', () => { - const serverResponse = { - bidPrice: 5.00 - }; - const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); - expect(bidResponse.length).to.equal(0); - }); + it('should return no bids if the response "url" is missing', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + const serverResponse = { + bidPrice: 5.00 + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); - it('should return no bids if the response "bidPrice" is missing', () => { - const serverResponse = { - url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da' - }; - const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); - expect(bidResponse.length).to.equal(0); + it('should return no bids if the response "bidPrice" is missing', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + const serverResponse = { + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da' + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return a valid video bid response', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + const serverResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + cmpId: '123abc' + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + const [ width, height ] = bidRequest.sizes; + expect(bidResponse).to.deep.equal({ + requestId: bidRequest.bidId, + bidderCode: spec.code, + cpm: serverResponse.bidPrice, + creativeId: serverResponse.cmpId, + vastUrl: serverResponse.url, + width: width, + height: height, + mediaType: 'video', + currency: 'USD', + netRevenue: true, + ttl: 300 + }); + }); }); - it('should return a valid bid response', () => { - const serverResponse = { - bidPrice: 5.00, - url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', - cmpId: '123abc' - }; - const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); - expect(bidResponse).to.deep.equal({ - requestId: bidRequest.bidId, - bidderCode: spec.code, - cpm: serverResponse.bidPrice, - creativeId: serverResponse.cmpId, - vastUrl: serverResponse.url, - width: 640, - height: 480, - mediaType: 'video', - currency: 'USD', - ttl: 300, - netRevenue: true + describe('for banner bids', () => { + it('should return no bids if the response is not valid', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { banner: {} }; + const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return no bids if the response is empty', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { banner: {} }; + const bidResponse = spec.interpretResponse({ body: [] }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return valid banner bid responses', () => { + bidRequests[0].mediaTypes = { banner: {} }; + bidRequests[0].sizes = [[ 300, 250 ], [ 728, 90 ]]; + bidRequests[1].mediaTypes = { banner: {} }; + bidRequests[1].sizes = [[ 300, 600 ], [ 200, 200 ]]; + const serverResponse = [{ + slot: bidRequests[0].adUnitCode, + adm: '
', + crid: 'crid_1', + price: 3.02, + w: 728, + h: 90 + }, { + slot: bidRequests[1].adUnitCode, + adm: '
', + crid: 'crid_2', + price: 3.06, + w: 300, + h: 600 + }]; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest: bidRequests }); + expect(bidResponse.length).to.equal(2); + for (let i = 0; i < bidRequests.length; i++) { + expect(bidResponse[ i ]).to.deep.equal({ + requestId: bidRequests[ i ].bidId, + bidderCode: spec.code, + ad: serverResponse[ i ].adm, + creativeId: serverResponse[ i ].crid, + cpm: serverResponse[ i ].price, + width: serverResponse[ i ].w, + height: serverResponse[ i ].h, + mediaType: 'banner', + currency: 'USD', + netRevenue: true, + ttl: 300 + }); + } }); }); }); From 355a6bfbcec67e1577b766b69ad3db902f53fd6a Mon Sep 17 00:00:00 2001 From: Vatic Digital <34057784+VaticSSP@users.noreply.github.com> Date: Tue, 6 Mar 2018 20:30:40 +0300 Subject: [PATCH 0163/1594] Add FairTrade Bid Adapter (#2147) --- modules/fairtradeBidAdapter.js | 150 +++++++++ modules/fairtradeBidAdapter.md | 28 ++ test/spec/modules/fairtradeBidAdapter_spec.js | 289 ++++++++++++++++++ 3 files changed, 467 insertions(+) create mode 100644 modules/fairtradeBidAdapter.js create mode 100755 modules/fairtradeBidAdapter.md create mode 100644 test/spec/modules/fairtradeBidAdapter_spec.js diff --git a/modules/fairtradeBidAdapter.js b/modules/fairtradeBidAdapter.js new file mode 100644 index 00000000000..dde64d839ca --- /dev/null +++ b/modules/fairtradeBidAdapter.js @@ -0,0 +1,150 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'fairtrade'; +const ENDPOINT_URL = '//pool.fair-trademedia.com/hb'; +const TIME_TO_LIVE = 360; +const ADAPTER_SYNC_URL = '//pool.fair-trademedia.com/push_sync'; +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', + noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', + emptyUids: 'Uids should be not empty', + emptySeatbid: 'Seatbid array from response has empty item', + emptyResponse: 'Response is empty', + hasEmptySeatbidArray: 'Response has empty seatbid array', + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' +}; +export const spec = { + code: BIDDER_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 !!bid.params.uid; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests) { + const auids = []; + const bidsMap = {}; + const bids = validBidRequests || []; + let priceType = 'net'; + let reqId; + + bids.forEach(bid => { + if (bid.params.priceType === 'gross') { + priceType = 'gross'; + } + reqId = bid.bidderRequestId; + if (!bidsMap[bid.params.uid]) { + bidsMap[bid.params.uid] = [bid]; + auids.push(bid.params.uid); + } else { + bidsMap[bid.params.uid].push(bid); + } + }); + + const payload = { + u: utils.getTopWindowUrl(), + pt: priceType, + auids: auids.join(','), + r: reqId + }; + + return { + method: 'GET', + url: ENDPOINT_URL, + data: payload, + bidsMap: bidsMap, + }; + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param {*} bidRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidRequest) { + serverResponse = serverResponse && serverResponse.body + const bidResponses = []; + const bidsMap = bidRequest.bidsMap; + const priceType = bidRequest.data.pt; + + let errorMessage; + + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } + + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses); + }); + } + if (errorMessage) utils.logError(errorMessage); + return bidResponses; + }, + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: ADAPTER_SYNC_URL + }]; + } + } +} + +function _getBidFromResponse(respItem) { + if (!respItem) { + utils.logError(LOG_ERROR_MESS.emptySeatbid); + } else if (!respItem.bid) { + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + } else if (!respItem.bid[0]) { + utils.logError(LOG_ERROR_MESS.noBid); + } + return respItem && respItem.bid && respItem.bid[0]; +} + +function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { + if (!serverBid) return; + let errorMessage; + if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + awaitingBids.forEach(bid => { + const bidResponse = { + requestId: bid.bidId, // bid.bidderRequestId, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, // bid.bidId, + currency: 'USD', + netRevenue: priceType !== 'gross', + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid + }; + bidResponses.push(bidResponse); + }); + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } + if (errorMessage) { + utils.logError(errorMessage); + } +} + +registerBidder(spec); diff --git a/modules/fairtradeBidAdapter.md b/modules/fairtradeBidAdapter.md new file mode 100755 index 00000000000..56abb84d15a --- /dev/null +++ b/modules/fairtradeBidAdapter.md @@ -0,0 +1,28 @@ +# Overview + +Module Name: FairTrade Bidder Adapter +Module Type: Bidder Adapter +Maintainer: Tammy.l@VaticDigital.com + +# Description + +Module that connects to FairTrade demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "fairtrade", + params: { + uid: '166', + priceType: 'gross' // by default is 'net' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/fairtradeBidAdapter_spec.js b/test/spec/modules/fairtradeBidAdapter_spec.js new file mode 100644 index 00000000000..07c26e8f0c1 --- /dev/null +++ b/test/spec/modules/fairtradeBidAdapter_spec.js @@ -0,0 +1,289 @@ +import { expect } from 'chai'; +import { spec } from 'modules/fairtradeBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('FairTradeAdapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'fairtrade', + 'params': { + 'uid': '166' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'uid': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '165' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '165' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '167' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '42dbe3a7168a6a', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should attach valid params to the tag', () => { + const request = spec.buildRequests([bidRequests[0]]); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '165'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + }); + + it('auids must not be duplicated', () => { + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '165,167'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + }); + + it('pt parameter must be "gross" if params.priceType === "gross"', () => { + bidRequests[1].params.priceType = 'gross'; + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'gross'); + expect(payload).to.have.property('auids', '165,167'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + delete bidRequests[1].params.priceType; + }); + + it('pt parameter must be "net" or "gross"', () => { + bidRequests[1].params.priceType = 'some'; + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '165,167'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + delete bidRequests[1].params.priceType; + }); + }); + + describe('interpretResponse', () => { + const responses = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 165, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 166, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 167, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + undefined, + {'bid': [], 'seat': '1'}, + {'seat': '1'}, + ]; + + it('should get correct bid response', () => { + const bidRequests = [ + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '165' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 165, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should get correct multi bid response', () => { + const bidRequests = [ + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '165' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71a5b', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '166' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dff80cc4ee346', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '165' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '5703af74d0472a', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '300bfeb0d71a5b', + 'cpm': 1.15, + 'creativeId': 165, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '5703af74d0472a', + 'cpm': 1.15, + 'creativeId': 165, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 166, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 2
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('handles wrong and nobid responses', () => { + const bidRequests = [ + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '167' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d7190gf', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '168' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71321', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'fairtrade', + 'params': { + 'uid': '169' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '300bfeb0d7183bb', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + } + ]; + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + expect(result.length).to.equal(0); + }); + }); +}); From fa5534279a3b85402ce9c39b09bf0089941e9cb1 Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 6 Mar 2018 12:53:02 -0500 Subject: [PATCH 0164/1594] Adding PR_REVIEW guideline (#2159) * adding PR_REVIEW guideline Adapters may not globally override or default the standard ad server targeting values: hb_adid, hb_bidder, hb_pb, hb_deal, hb_size * Update PR_REVIEW.md * Update PR_REVIEW.md --- PR_REVIEW.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PR_REVIEW.md b/PR_REVIEW.md index e8c4559bbf8..2a870d9e2f6 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -33,6 +33,7 @@ For modules and core platform updates, the initial reviewer should request an ad - All user-sync (aka pixel) activity must be registered via the provided functions - Adapters may not use the $$PREBID_GLOBAL$$ variable - All adapters must support the creation of multiple concurrent instances. This means, for example, that adapters cannot rely on mutable global variables. +- Adapters may not globally override or default the standard ad server targeting values: hb_adid, hb_bidder, hb_pb, hb_deal, or hb_size, hb_source, hb_format. ## Ticket Coordinator From 1454f2b49511f27eb9b9a6c05023cda8033ab517 Mon Sep 17 00:00:00 2001 From: Aparna Rao-Hegde Date: Tue, 6 Mar 2018 13:04:04 -0500 Subject: [PATCH 0165/1594] 33Across Bid Adapter: updated user sync endpoint (#2193) * Adding 33across adapter * Updated per code review from Prebid. See https://github.com/prebid/Prebid.js/pull/1805#pullrequestreview-75218582 * Added support for test bid and crid. * Removed ability to set test url via params * Incorporated changes requested in https://github.com/prebid/Prebid.js/issues/1855 to fix usage of deprecated method * Reverted hack to karma conf maker to make unit tests pass with --file option --- modules/33acrossBidAdapter.js | 2 +- test/spec/modules/33acrossBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 5a7fa5e2613..93fd685ae15 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -4,7 +4,7 @@ const { config } = require('../src/config'); const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; -const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch'; +const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch&rt=html'; // All this assumes that only one bid is ever returned by ttx function _createBidResponse(response) { diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index a81c92b4a48..9c318e4bdd5 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -14,7 +14,7 @@ describe('33acrossBidAdapter:', function () { const SITE_ID = 'pub1234'; const PRODUCT_ID = 'product1'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; - const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch'; + const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch&rt=html'; beforeEach(function() { this.bidRequests = [ From b315a527ed4dbb744c212d656472dfe78d8462cd Mon Sep 17 00:00:00 2001 From: Matt Kendall Date: Tue, 6 Mar 2018 13:04:56 -0500 Subject: [PATCH 0166/1594] Feature/stale bot (#2192) * add a bot to clean up stale issues * add bug --- .github/stale.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000000..41b1c7ba747 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 14 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security + - bug +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From 94c4023a43c421b354df105fc2c3ea67582f1269 Mon Sep 17 00:00:00 2001 From: gammassp <35954362+gammassp@users.noreply.github.com> Date: Wed, 7 Mar 2018 01:27:17 +0700 Subject: [PATCH 0167/1594] Gamma Support UserSync Endpoint (#2216) * commit gamma adapter * Fixed The Travis CI build failed * fix interpretResponse return empty when server response empty * removed mediaType removed mediaType in bid and return vastXml property if video request * fixed Travis CI build * Travis CI build * add gamma spec * fixed Travis CI build * fix spec * fix spec * Add files via upload * Add files via upload * fix spec * fix Travis CI build * move to module * remove gaxDomain param and move to adapter * remove check isBidRequestValid for gaxDomain * remove gaxDomain param * remove gaxDomain param * remove gaxDomain param * Delete gammaBidAdapter_spec.js * add usersync endpoid * add usersync --- modules/gammaBidAdapter.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/gammaBidAdapter.js b/modules/gammaBidAdapter.js index 8240df3d151..516f716fa76 100644 --- a/modules/gammaBidAdapter.js +++ b/modules/gammaBidAdapter.js @@ -50,6 +50,15 @@ export const spec = { } return bids; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//' + ENDPOINT + '/adx/usersync' + }]; + } } } From 2204cf83e538889fffec9b663d8f60b7fbee221f Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Tue, 6 Mar 2018 13:28:23 -0500 Subject: [PATCH 0168/1594] InSkin Bid Adapter: remove referrer field from request body (#2217) --- modules/inskinBidAdapter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js index 5274b5b2ba8..710efc4498c 100644 --- a/modules/inskinBidAdapter.js +++ b/modules/inskinBidAdapter.js @@ -51,7 +51,6 @@ export const spec = { time: Date.now(), user: {}, url: utils.getTopWindowUrl(), - referrer: document.referrer, enableBotFiltering: true, includePricingData: true, parallel: true From 5232bc200eb3a51c661eb1c2acabb5a02d69bf45 Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Tue, 6 Mar 2018 20:30:11 +0200 Subject: [PATCH 0169/1594] Update Vidazoo domain (#2223) update ad server domain --- modules/vidazooBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/vidazooBidAdapter.js b/modules/vidazooBidAdapter.js index 981f5603a0a..411c18f5414 100644 --- a/modules/vidazooBidAdapter.js +++ b/modules/vidazooBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; import {BANNER} from 'src/mediaTypes'; -export const URL = '//prebid.cliipa.com'; +export const URL = '//prebid.nininin.com'; const BIDDER_CODE = 'vidazoo'; const CURRENCY = 'USD'; const TTL_SECONDS = 60 * 5; @@ -85,7 +85,7 @@ function getUserSyncs(syncOptions, responses) { if (iframeEnabled) { return [{ type: 'iframe', - url: '//static.cliipa.com/basev/sync/user_sync.html' + url: '//static.nininin.com/basev/sync/user_sync.html' }]; } From 7904c5b9843c6bf5165133c03bb9d2cbdebeae79 Mon Sep 17 00:00:00 2001 From: Roffray Date: Tue, 6 Mar 2018 19:30:34 +0100 Subject: [PATCH 0170/1594] Add vuble adapter (#2201) * Add: vuble bid adapter * Add: vuble bid adapter unit tests * Fix: getUserSync returns an empty array if no user sync is found * Add: unit tests for getUserSync * Mod vuble unit test use single quotes * Mod: check mediatypes for bid request valid check on vuble adapter * Add: vuble adapter: bid id and env in request data * Fix: vuble adaptor uses bid data in interpret reponse * Del: unused size param anymore --- modules/vubleBidAdapter.js | 135 +++++++++++ modules/vubleBidAdapter.md | 58 +++++ test/spec/modules/vubleBidAdapter_spec.js | 268 ++++++++++++++++++++++ 3 files changed, 461 insertions(+) create mode 100644 modules/vubleBidAdapter.js create mode 100644 modules/vubleBidAdapter.md create mode 100644 test/spec/modules/vubleBidAdapter_spec.js diff --git a/modules/vubleBidAdapter.js b/modules/vubleBidAdapter.js new file mode 100644 index 00000000000..c995705c957 --- /dev/null +++ b/modules/vubleBidAdapter.js @@ -0,0 +1,135 @@ +// Vuble Adapter + +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'vuble'; + +const ENVS = ['com', 'net']; +const CURRENCIES = { + com: 'EUR', + net: 'USD' +}; +const TTL = 60; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['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 (utils.isEmpty(bid.sizes) || utils.parseSizesInput(bid.sizes).length == 0) { + return false; + } + + if (!utils.deepAccess(bid, 'mediaTypes.video.context')) { + return false; + } + + if (!utils.contains(ENVS, bid.params.env)) { + return false; + } + + return !!(bid.params.env && bid.params.pubId && bid.params.zoneId); + }, + + /** + * 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(bid => { + // We take the first size + let size = utils.parseSizesInput(bid.sizes)[0].split('x'); + + // Get the page's url + let referrer = utils.getTopWindowUrl(); + if (bid.params.referrer) { + referrer = bid.params.referrer; + } + + // Get Video Context + let context = utils.deepAccess(bid, 'mediaTypes.video.context'); + + let url = '//player.mediabong.' + bid.params.env + '/prebid/request'; + let data = { + width: size[0], + height: size[1], + pub_id: bid.params.pubId, + zone_id: bid.params.zoneId, + context: context, + floor_price: bid.params.floorPrice ? bid.params.floorPrice : 0, + url: referrer, + env: bid.params.env, + bid_id: bid.bidId + }; + + return { + method: 'POST', + url: url, + data: data + }; + }); + }, + + /** + * 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, bid) { + const responseBody = serverResponse.body; + + if (typeof responseBody !== 'object' || responseBody.status !== 'ok') { + return []; + } + + let responses = []; + let reponse = { + requestId: bid.data.bid_id, + cpm: responseBody.cpm, + width: bid.data.width, + height: bid.data.height, + ttl: TTL, + creativeId: responseBody.creativeId, + netRevenue: true, + currency: CURRENCIES[bid.data.env], + vastUrl: responseBody.url + }; + responses.push(reponse); + + return responses; + }, + + /** + * 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) { + if (syncOptions.iframeEnabled) { + if (serverResponses.length > 0) { + let responseBody = serverResponses[0].body; + if (typeof responseBody !== 'object' || responseBody.iframeSync) { + return [{ + type: 'iframe', + url: responseBody.iframeSync + }]; + } + } + } + return []; + } +}; + +registerBidder(spec); diff --git a/modules/vubleBidAdapter.md b/modules/vubleBidAdapter.md new file mode 100644 index 00000000000..4e066b9dd8a --- /dev/null +++ b/modules/vubleBidAdapter.md @@ -0,0 +1,58 @@ +# Overview + +``` +Module Name: Vuble Bidder Adapter +Module Type: Vuble Adapter +Maintainer: gv@mediabong.com +``` + +# Description + +Module that connects to Vuble's demand sources + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-video-instream', + sizes: [[640, 360]], + mediaTypes: { + video: { + context: 'instream' + } + }, + bids: [ + { + bidder: "vuble", + params: { + env: 'net', + pubId: '3', + zoneId: '12345', + referrer: "http://www.vuble.tv/", // optional + floorPrice: 5.00 // optional + } + } + ] + }, + { + code: 'test-video-outstream', + sizes: [[640, 360]], + mediaTypes: { + video: { + context: 'outstream' + } + }, + bids: [ + { + bidder: "vuble", + params: { + env: 'net', + pubId: '3', + zoneId: '12345', + referrer: "http://www.vuble.tv/", // optional + floorPrice: 5.00 // optional + } + } + ] + } + ]; \ No newline at end of file diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js new file mode 100644 index 00000000000..3ecbd533c5f --- /dev/null +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -0,0 +1,268 @@ +// import or require modules necessary for the test, e.g.: + +import {expect} from 'chai'; +import {spec as adapter} from 'modules/vubleBidAdapter'; +import * as utils from 'src/utils'; + +describe('VubleAdapter', () => { + describe('Check methods existance', () => { + it('exists and is a function', () => { + expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function'); + }); + it('exists and is a function', () => { + expect(adapter.buildRequests).to.exist.and.to.be.a('function'); + }); + it('exists and is a function', () => { + expect(adapter.interpretResponse).to.exist.and.to.be.a('function'); + }); + it('exists and is a function', () => { + expect(adapter.getUserSyncs).to.exist.and.to.be.a('function'); + }); + }); + + describe('Check method isBidRequestValid return', () => { + let bid = { + bidder: 'vuble', + params: { + env: 'net', + pubId: '3', + zoneId: '12345', + floorPrice: 5.00 // optional + }, + sizes: [[640, 360]], + mediaTypes: { + video: { + context: 'instream' + } + }, + }; + + it('should be true', () => { + expect(adapter.isBidRequestValid(bid)).to.be.true; + }); + + it('should be false because the sizes are missing or in the wrong format', () => { + let wrongBid = utils.deepClone(bid); + wrongBid.sizes = '640360'; + expect(adapter.isBidRequestValid(wrongBid)).to.be.false; + + wrongBid = utils.deepClone(bid); + delete wrongBid.sizes; + expect(adapter.isBidRequestValid(wrongBid)).to.be.false; + }); + + it('should be false because the mediaType is missing or wrong', () => { + let wrongBid = utils.deepClone(bid); + wrongBid.mediaTypes = {}; + expect(adapter.isBidRequestValid(wrongBid)).to.be.false; + + wrongBid = utils.deepClone(bid); + delete wrongBid.mediaTypes; + expect(adapter.isBidRequestValid(wrongBid)).to.be.false; + }); + + it('should be false because the env is missing or wrong', () => { + let wrongBid = utils.deepClone(bid); + wrongBid.params.env = 'us'; + expect(adapter.isBidRequestValid(wrongBid)).to.be.false; + + wrongBid = utils.deepClone(bid); + delete wrongBid.params.env; + expect(adapter.isBidRequestValid(wrongBid)).to.be.false; + }); + + it('should be false because params.pubId is missing', () => { + let wrongBid = utils.deepClone(bid); + delete wrongBid.params.pubId; + expect(adapter.isBidRequestValid(wrongBid)).to.be.false; + }); + + it('should be false because params.zoneId is missing', () => { + let wrongBid = utils.deepClone(bid); + delete wrongBid.params.zoneId; + expect(adapter.isBidRequestValid(wrongBid)).to.be.false; + }); + }); + + describe('Check buildRequests method', () => { + let sandbox; + before(() => { + sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getTopWindowUrl').returns('http://www.vuble.tv/'); + }); + + // Bids to be formatted + let bid1 = { + bidder: 'vuble', + params: { + env: 'net', + pubId: '3', + zoneId: '12345', + floorPrice: 5.50 // optional + }, + sizes: [[640, 360]], + mediaTypes: { + video: { + context: 'instream' + } + }, + bidId: 'abdc' + }; + let bid2 = { + bidder: 'vuble', + params: { + env: 'com', + pubId: '8', + zoneId: '2468', + referrer: 'http://www.vuble.fr/' + }, + sizes: '640x360', + mediaTypes: { + video: { + context: 'outstream' + } + }, + bidId: 'efgh' + }; + + // Formatted requets + let request1 = { + method: 'POST', + url: '//player.mediabong.net/prebid/request', + data: { + width: '640', + height: '360', + pub_id: '3', + zone_id: '12345', + context: 'instream', + floor_price: 5.5, + url: 'http://www.vuble.tv/', + env: 'net', + bid_id: 'abdc' + } + }; + let request2 = { + method: 'POST', + url: '//player.mediabong.com/prebid/request', + data: { + width: '640', + height: '360', + pub_id: '8', + zone_id: '2468', + context: 'outstream', + floor_price: 0, + url: 'http://www.vuble.fr/', + env: 'com', + bid_id: 'efgh' + } + }; + + it('must return the right formatted requests', () => { + let rs = adapter.buildRequests([bid1, bid2]); + expect(adapter.buildRequests([bid1, bid2])).to.deep.equal([request1, request2]); + }); + + after(() => { + sandbox.restore(); + }); + }); + + describe('Check interpretResponse method return', () => { + // Server's response + let response = { + body: { + status: 'ok', + cpm: 5.00, + creativeId: '2468', + url: 'https//player.mediabong.net/prebid/ad/a1b2c3d4' + } + }; + // bid Request + let bid = { + data: { + context: 'instream', + env: 'net', + width: '640', + height: '360', + pub_id: '3', + zone_id: '12345', + bid_id: 'abdc', + floor_price: 5.50 // optional + }, + method: 'POST', + url: '//player.mediabong.net/prebid/request' + }; + // Formatted reponse + let result = { + requestId: 'abdc', + cpm: 5.00, + width: '640', + height: '360', + ttl: 60, + creativeId: '2468', + netRevenue: true, + currency: 'USD', + vastUrl: 'https//player.mediabong.net/prebid/ad/a1b2c3d4' + }; + + it('should equal to the expected formatted result', () => { + expect(adapter.interpretResponse(response, bid)).to.deep.equal([result]); + }); + + it('should be empty because the status is missing or wrong', () => { + let wrongResponse = utils.deepClone(response); + wrongResponse.body.status = 'ko'; + expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; + + wrongResponse = utils.deepClone(response); + delete wrongResponse.body.status; + expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; + }); + + it('should be empty because the body is missing or wrong', () => { + let wrongResponse = utils.deepClone(response); + wrongResponse.body = [1, 2, 3]; + expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; + + wrongResponse = utils.deepClone(response); + delete wrongResponse.body; + expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; + }); + }); + + describe('Check getUserSyncs method return', () => { + // Sync options + let syncOptions = { + iframeEnabled: false + }; + // Server's response + let response = { + body: { + status: 'ok', + cpm: 5.00, + creativeId: '2468', + url: 'https//player.mediabong.net/prebid/ad/a1b2c3d4' + } + }; + // Formatted reponse + let result = { + type: 'iframe', + url: 'http://player.mediabong.net/csifr?1234' + }; + + it('should return an empty array', () => { + expect(adapter.getUserSyncs({}, [])).to.be.empty; + expect(adapter.getUserSyncs({}, [])).to.be.empty; + expect(adapter.getUserSyncs(syncOptions, [response])).to.be.empty; + expect(adapter.getUserSyncs(syncOptions, [response])).to.be.empty; + syncOptions.iframeEnabled = true; + expect(adapter.getUserSyncs(syncOptions, [response])).to.be.empty; + expect(adapter.getUserSyncs(syncOptions, [response])).to.be.empty; + }); + + it('should be equal to the expected result', () => { + response.body.iframeSync = 'http://player.mediabong.net/csifr?1234'; + expect(adapter.getUserSyncs(syncOptions, [response])).to.deep.equal([result]); + }) + }); +}); From 768cb62d36ecab5432e2294155ad52db45bfbda6 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 6 Mar 2018 10:33:14 -0800 Subject: [PATCH 0171/1594] Fix uncahced video bids from multi-response array triggering callback early (#2219) --- src/adapters/bidderFactory.js | 5 ++++- test/spec/auctionmanager_spec.js | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 10315241c40..b9930c3f363 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -173,13 +173,16 @@ export function newBidder(spec) { // register any required usersync pixels. const responses = []; function afterAllResponses(bids) { - const videoBid = bids && bids[0] && bids[0].mediaType && bids[0].mediaType === 'video'; + const bidsArray = bids ? (bids[0] ? bids : [bids]) : []; + + const videoBid = bidsArray.some(bid => bid.mediaType === 'video'); const cacheEnabled = config.getConfig('cache.url'); // video bids with cache enabled need to be cached first before they are considered done if (!(videoBid && cacheEnabled)) { done(); } + registerSyncs(responses); } diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index cf17ccac705..ef50d2b6294 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -801,5 +801,30 @@ describe('auctionmanager.js', function () { config.getConfig.restore(); store.store.restore(); }); + + it('runs auction after video responses with multiple bid objects have been cached', () => { + sinon.stub(store, 'store').callsArgWith(1, null, [{ uuid: 123 }]); + sinon.stub(config, 'getConfig').withArgs('cache.url').returns('cache-url'); + + const bidsCopy = [ + Object.assign({}, bids[0], { mediaType: 'video' }), + Object.assign({}, bids[0], { mediaType: 'banner' }), + ]; + const bids1Copy = [ + Object.assign({}, bids1[0], { mediaType: 'video' }), + Object.assign({}, bids1[0], { mediaType: 'video' }), + ]; + + spec.interpretResponse.returns(bidsCopy); + spec1.interpretResponse.returns(bids1Copy); + + auction.callBids(); + + assert.equal(auction.getBidsReceived().length, 4); + assert.equal(auction.getAuctionStatus(), 'completed'); + + config.getConfig.restore(); + store.store.restore(); + }); }); }); From 04cca6e166cc19a10861516d89592baf1973ea67 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 6 Mar 2018 15:52:05 -0800 Subject: [PATCH 0172/1594] Fix cross-platform test failures (#2228) --- modules/adyoulikeBidAdapter.js | 3 +- modules/nasmediaAdmixerBidAdapter.js | 3 +- modules/rtbhouseBidAdapter.js | 3 +- test/spec/modules/peak226BidAdapter_spec.js | 32 ++++++++++----------- test/spec/modules/pubCommonId_spec.js | 4 +++ 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index a73421f7ca5..263f3fa09e9 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -2,6 +2,7 @@ import * as utils from 'src/utils'; import { format } from 'src/url'; // import { config } from 'src/config'; import { registerBidder } from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; const VERSION = '1.0'; const BIDDER_CODE = 'adyoulike'; @@ -77,7 +78,7 @@ export const spec = { /* Get hostname from bids */ function getHostname(bidderRequest) { - let dcHostname = bidderRequest.find(bid => bid.params.DC); + let dcHostname = find(bidderRequest, bid => bid.params.DC); if (dcHostname) { return ('-' + dcHostname.params.DC); } diff --git a/modules/nasmediaAdmixerBidAdapter.js b/modules/nasmediaAdmixerBidAdapter.js index 344bf991610..7de5c638c9e 100644 --- a/modules/nasmediaAdmixerBidAdapter.js +++ b/modules/nasmediaAdmixerBidAdapter.js @@ -1,5 +1,6 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; const ADMIXER_ENDPOINT = 'https://adn.admixer.co.kr:10443/prebid'; const DEFAULT_BID_TTL = 360; @@ -62,7 +63,7 @@ function getOsType() { let os = ['android', 'ios', 'mac', 'linux', 'window']; let regexp_os = [/android/i, /iphone|ipad/i, /mac/i, /linux/i, /window/i]; - return os.find((tos, idx) => { + return find(os, (tos, idx) => { if (ua.match(regexp_os[idx])) { return os[idx]; } diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js index 181cf80d5e7..cd60925b2c7 100644 --- a/modules/rtbhouseBidAdapter.js +++ b/modules/rtbhouseBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from 'src/utils'; import { BANNER } from 'src/mediaTypes'; import { registerBidder } from 'src/adapters/bidderFactory'; +import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'rtbhouse'; const REGIONS = ['prebid-eu', 'prebid-us', 'prebid-asia']; @@ -70,7 +71,7 @@ export const spec = { supportedMediaTypes: [BANNER], isBidRequestValid: function (bid) { - return !!(REGIONS.includes(bid.params.region) && bid.params.publisherId); + return !!(includes(REGIONS, bid.params.region) && bid.params.publisherId); }, buildRequests: function (validBidRequests) { diff --git a/test/spec/modules/peak226BidAdapter_spec.js b/test/spec/modules/peak226BidAdapter_spec.js index 37bbc1b67bd..f85e46c4289 100644 --- a/test/spec/modules/peak226BidAdapter_spec.js +++ b/test/spec/modules/peak226BidAdapter_spec.js @@ -27,22 +27,22 @@ describe('PeakAdapter', () => { }); }); - xdescribe('buildRequests', () => { - const bidRequests = [ - { - params: { - uid: '1234' - } - } - ]; - - it('sends bid request to URL via GET', () => { - const request = spec.buildRequests(bidRequests); - - expect(request.url).to.equal(`${URL}?uids=1234`); - expect(request.method).to.equal('GET'); - }); - }); + // xdescribe('buildRequests', () => { + // const bidRequests = [ + // { + // params: { + // uid: '1234' + // } + // } + // ]; + + // it('sends bid request to URL via GET', () => { + // const request = spec.buildRequests(bidRequests); + + // expect(request.url).to.equal(`${URL}?uids=1234`); + // expect(request.method).to.equal('GET'); + // }); + // }); describe('interpretResponse', () => { it('should handle empty response', () => { diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js index 7f7c71543f1..50ca4616a4b 100644 --- a/test/spec/modules/pubCommonId_spec.js +++ b/test/spec/modules/pubCommonId_spec.js @@ -19,6 +19,10 @@ const TIMEOUT = 2000; describe('Publisher Common ID', function () { describe('Decorate adUnits', function () { + before(function() { + window.document.cookie = COOKIE_NAME + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + }); + it('Check same cookie', function () { let adUnits1 = getAdUnits(); let adUnits2 = getAdUnits(); From f7b752147ae7460c6a8aac337b398e5437614c05 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 6 Mar 2018 16:28:07 -0800 Subject: [PATCH 0173/1594] Prebid 1.5.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 39b3a65de4b..3f279b61d2c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.5.0-pre", + "version": "1.5.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 02ebe3a2b5b0fbb08651a8fcb2e652d8852ed5e0 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 6 Mar 2018 16:41:51 -0800 Subject: [PATCH 0174/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f279b61d2c..663e89ea7e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.5.0", + "version": "1.6.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b0260d594e31c6da0cc1ae0d54a48ad9924cf873 Mon Sep 17 00:00:00 2001 From: rcheptanariu <35690143+rcheptanariu@users.noreply.github.com> Date: Wed, 7 Mar 2018 19:38:16 +0200 Subject: [PATCH 0175/1594] Add Invibes Adapter (#2202) * Added invibes adapter * added domain id & config * invibes bid adapter - auction start and logging * invibes bid adapter refactor * Invibes Bid Adapter - renames * Invibes Bid Adapter - fix typo * Invibes Adapter - test spec * Invibes Adapter - added size to test params * Invibes Bid Adapter - lint fix * Invibes Adapter - lint fix in test spec * Invibes Bid Adapter - review change requests * Invibes Bid Adapter - remove alias according to review change requests * Invibes Bid Adapter - review change request --- modules/invibesBidAdapter.js | 439 ++++++++++++++++++++ modules/invibesBidAdapter.md | 29 ++ test/spec/modules/invibesBidAdapter_spec.js | 249 +++++++++++ 3 files changed, 717 insertions(+) create mode 100644 modules/invibesBidAdapter.js create mode 100644 modules/invibesBidAdapter.md create mode 100644 test/spec/modules/invibesBidAdapter_spec.js diff --git a/modules/invibesBidAdapter.js b/modules/invibesBidAdapter.js new file mode 100644 index 00000000000..ab6f7c4898b --- /dev/null +++ b/modules/invibesBidAdapter.js @@ -0,0 +1,439 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const CONSTANTS = { + BIDDER_CODE: 'invibes', + BID_ENDPOINT: '//bid.videostep.com/Bid/VideoAdContent', + SYNC_ENDPOINT: '//k.r66net.com/GetUserSync', + TIME_TO_LIVE: 300, + DEFAULT_CURRENCY: 'EUR', + PREBID_VERSION: 1, + METHOD: 'GET' +}; + +export const spec = { + code: CONSTANTS.BIDDER_CODE, + /** + * @param {object} bid + * @return boolean + */ + isBidRequestValid: isBidRequestValid, + /** + * @param {BidRequest[]} bidRequests + * @param bidderRequest + * @return ServerRequest[] + */ + buildRequests: function (bidRequests, bidderRequest) { + return buildRequest(bidRequests, bidderRequest != null ? bidderRequest.auctionStart : null); + }, + /** + * @param {*} responseObj + * @param {requestParams} bidRequests + * @return {Bid[]} An array of bids which + */ + interpretResponse: function (responseObj, requestParams) { + return handleResponse(responseObj, requestParams != null ? requestParams.bidRequests : null); + }, + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return { + type: 'iframe', + url: CONSTANTS.SYNC_ENDPOINT + }; + } + } +}; + +registerBidder(spec); + +function isBidRequestValid(bid) { + if (typeof bid.params !== 'object') { + return false; + } + let params = bid.params; + + if (params.placementId == null) { + return false; + } + + return true; +} + +function buildRequest(bidRequests, auctionStart) { + // invibes only responds to 1 bid request for each user visit + const _placementIds = []; + let _loginId, _customEndpoint, _bidContainerId; + let _ivAuctionStart = auctionStart || Date.now(); + + bidRequests.forEach(function (bidRequest) { + bidRequest.startTime = new Date().getTime(); + _placementIds.push(bidRequest.params.placementId); + _loginId = _loginId || bidRequest.params.loginId; + _customEndpoint = _customEndpoint || bidRequest.params.customEndpoint; + _bidContainerId = _bidContainerId || bidRequest.params.adContainerId || bidRequest.params.bidContainerId; + }); + + const topWin = getTopMostWindow(); + const invibes = topWin.invibes = topWin.invibes || {}; + invibes.visitId = invibes.visitId || generateRandomId(); + invibes.bidContainerId = invibes.bidContainerId || _bidContainerId; + + initDomainId(invibes); + + const currentQueryStringParams = parseQueryStringParams(); + + let data = { + location: getDocumentLocation(topWin), + videoAdHtmlId: generateRandomId(), + showFallback: currentQueryStringParams['advs'] === '0', + ivbsCampIdsLocal: getCookie('IvbsCampIdsLocal'), + lId: invibes.dom.id, + + bidParamsJson: JSON.stringify({ + placementIds: _placementIds, + loginId: _loginId, + bidContainerId: _bidContainerId, + auctionStartTime: _ivAuctionStart, + bidVersion: CONSTANTS.PREBID_VERSION + }), + capCounts: getCappedCampaignsAsString(), + + vId: invibes.visitId, + width: topWin.innerWidth, + height: topWin.innerHeight + }; + + const parametersToPassForward = 'videoaddebug,advs,bvci,bvid,istop,trybvid,trybvci'.split(','); + for (let key in currentQueryStringParams) { + if (currentQueryStringParams.hasOwnProperty(key)) { + let value = currentQueryStringParams[key]; + if (parametersToPassForward.indexOf(key) > -1 || /^vs|^invib/i.test(key)) { + data[key] = value; + } + } + } + + return { + method: CONSTANTS.METHOD, + url: _customEndpoint || CONSTANTS.BID_ENDPOINT, + data: data, + options: { withCredentials: true }, + // for POST: { contentType: 'application/json', withCredentials: true } + bidRequests: bidRequests + }; +} + +function handleResponse(responseObj, bidRequests) { + if (bidRequests == null || bidRequests.length === 0) { + utils.logInfo('Invibes Adapter - No bids have been requested'); + return []; + } + + if (!responseObj) { + utils.logInfo('Invibes Adapter - Bid response is empty'); + return []; + } + + responseObj = responseObj.body || responseObj; + responseObj = responseObj.videoAdContentResult || responseObj; + + let bidModel = responseObj.BidModel; + if (typeof bidModel !== 'object') { + utils.logInfo('Invibes Adapter - Bidding is not configured'); + return []; + } + + const topWin = getTopMostWindow(); + const invibes = topWin.invibes = topWin.invibes || {}; + + if (typeof invibes.bidResponse === 'object') { + utils.logInfo('Invibes Adapter - Bid response already received. Invibes only responds to one bid request per user visit'); + return []; + } + + invibes.bidResponse = responseObj; + + let ads = responseObj.Ads; + + if (!Array.isArray(ads) || ads.length < 1) { + if (responseObj.AdReason != null) { + utils.logInfo('Invibes Adapter - ' + responseObj.AdReason); + } + + utils.logInfo('Invibes Adapter - No ads available'); + return []; + } + + let ad = ads[0]; + + if (bidModel.PlacementId == null) { + utils.logInfo('Invibes Adapter - No Placement Id in response'); + return []; + } + + const bidResponses = []; + for (let i = 0; i < bidRequests.length; i++) { + let bidRequest = bidRequests[i]; + + if (bidModel.PlacementId === bidRequest.params.placementId) { + let size = getBiggerSize(bidRequest.sizes); + + bidResponses.push({ + requestId: bidRequest.bidId, + cpm: ad.BidPrice, + width: bidModel.Width || size[0], + height: bidModel.Height || size[1], + creativeId: ad.VideoExposedId, + currency: bidModel.Currency || CONSTANTS.DEFAULT_CURRENCY, + netRevenue: true, + ttl: CONSTANTS.TIME_TO_LIVE, + ad: renderCreative(bidModel) + }); + + const now = Date.now(); + invibes.ivLogger = invibes.ivLogger || initLogger(); + invibes.ivLogger.info('Bid auction started at ' + bidModel.AuctionStartTime + ' . Invibes registered the bid at ' + now + ' ; bid request took a total of ' + (now - bidModel.AuctionStartTime) + ' ms.'); + } else { + utils.logInfo('Invibes Adapter - Incorrect Placement Id: ' + bidRequest.params.placementId); + } + } + + return bidResponses; +} + +function generateRandomId() { + return (Math.round(Math.random() * 1e12)).toString(36).substring(0, 10); +} + +function getDocumentLocation(topWin) { + return topWin.location.href.substring(0, 300).split(/[?#]/)[0]; +} + +function parseQueryStringParams() { + let params = {}; + try { params = JSON.parse(localStorage.ivbs); } catch (e) { } + let re = /[\\?&]([^=]+)=([^\\?&#]+)/g; + let m; + while ((m = re.exec(window.location.href)) != null) { + if (m.index === re.lastIndex) { + re.lastIndex++; + } + params[m[1].toLowerCase()] = m[2]; + } + return params; +} + +function getBiggerSize(array) { + let result = [0, 0]; + for (let i = 0; i < array.length; i++) { + if (array[i][0] * array[i][1] > result[0] * result[1]) { + result = array[i]; + } + } + return result; +} + +function getTopMostWindow() { + let res = window; + + try { + while (top !== res) { + if (res.parent.location.href.length) { res = res.parent; } + } + } catch (e) { } + + return res; +} + +function renderCreative(bidModel) { + return ` + + + creativeHtml + + ` + .replace('creativeHtml', bidModel.CreativeHtml); +} + +function getCappedCampaignsAsString() { + const key = 'ivvcap'; + + let loadData = function () { + try { + return JSON.parse(localStorage.getItem(key)) || {}; + } catch (e) { + return {}; + } + }; + + let saveData = function (data) { + localStorage.setItem(key, JSON.stringify(data)); + }; + + let clearExpired = function () { + let now = new Date().getTime(); + let data = loadData(); + let dirty = false; + Object.keys(data).forEach(function (k) { + let exp = data[k][1]; + if (exp <= now) { + delete data[k]; + dirty = true; + } + }); + if (dirty) { + saveData(data); + } + }; + + let getCappedCampaigns = function () { + clearExpired(); + let data = loadData(); + return Object.keys(data) + .filter(function (k) { return data.hasOwnProperty(k); }) + .sort() + .map(function (k) { return [k, data[k][0]]; }); + }; + + return getCappedCampaigns() + .map(function (record) { return record.join('='); }) + .join(','); +} + +function initLogger() { + const noop = function () { }; + + if (localStorage && localStorage.InvibesDEBUG) { + return window.console; + } + + return { info: noop, error: noop, log: noop, warn: noop, debug: noop }; +} + +/// Local domain cookie management ===================== +let Uid = { + generate: function () { + let date = new Date().getTime(); + if (date > 151 * 10e9) { + let datePart = Math.floor(date / 1000).toString(36); + let maxRand = parseInt('zzzzzz', 36) + let randPart = Math.floor(Math.random() * maxRand).toString(36); + return datePart + '.' + randPart; + } + }, + getCrTime: function (s) { + let toks = s.split('.'); + return parseInt(toks[0] || 0, 36) * 1e3; + } +}; + +let cookieDomain, noCookies; +function getCookie(name) { + let i, x, y; + let cookies = document.cookie.split(';'); + for (i = 0; i < cookies.length; i++) { + x = cookies[i].substr(0, cookies[i].indexOf('=')); + y = cookies[i].substr(cookies[i].indexOf('=') + 1); + x = x.replace(/^\s+|\s+$/g, ''); + if (x === name) { + return unescape(y); + } + } +}; + +function setCookie(name, value, exdays, domain) { + if (noCookies && name != 'ivNoCookie' && (exdays || 0) >= 0) { return; } + if (exdays > 365) { exdays = 365; } + domain = domain || cookieDomain; + let exdate = new Date(); + let exms = exdays * 24 * 60 * 60 * 1000; + exdate.setTime(exdate.getTime() + exms); + let cookieValue = value + ((!exdays) ? '' : '; expires=' + exdate.toUTCString()); + cookieValue += ';domain=' + domain + ';path=/'; + document.cookie = name + '=' + cookieValue; +}; + +let detectTopmostCookieDomain = function () { + let testCookie = Uid.generate(); + let hostParts = location.host.split('.'); + if (hostParts.length === 1) { + return location.host; + } + for (let i = hostParts.length - 1; i >= 0; i--) { + let domain = '.' + hostParts.slice(i).join('.'); + setCookie(testCookie, testCookie, 1, domain); + let val = getCookie(testCookie); + if (val === testCookie) { + setCookie(testCookie, testCookie, -1, domain); + return domain; + } + } +}; +cookieDomain = detectTopmostCookieDomain(); +noCookies = getCookie('ivNoCookie'); + +function initDomainId(invibes, persistence) { + if (typeof invibes.dom === 'object') { + return; + } + + let cookiePersistence = { + cname: 'ivbsdid', + load: function () { + let str = getCookie(this.cname) || ''; + try { + return JSON.parse(str); + } catch (e) { } + }, + save: function (obj) { + setCookie(this.cname, JSON.stringify(obj), 365); + } + }; + + persistence = persistence || cookiePersistence; + let state; + const minHC = 5; + + let validGradTime = function (d) { + const min = 151 * 10e9; + let yesterday = new Date().getTime() - 864 * 10e4 + return d > min && d < yesterday; + }; + + state = persistence.load() || { + id: Uid.generate(), + hc: 1, + temp: 1 + }; + + let graduate; + + let setId = function () { + invibes.dom = { + id: state.temp ? undefined : state.id, + tempId: state.id, + graduate: graduate + }; + }; + + graduate = function () { + if (!state.temp) { return; } + delete state.temp; + delete state.hc; + persistence.save(state); + setId(); + } + + if (state.temp) { + if (state.hc < minHC) { + state.hc++; + } + if (state.hc >= minHC && validGradTime(Uid.getCrTime(state.id))) { + graduate(); + } + } + + persistence.save(state); + setId(); +}; +// ===================== diff --git a/modules/invibesBidAdapter.md b/modules/invibesBidAdapter.md new file mode 100644 index 00000000000..06afba6344d --- /dev/null +++ b/modules/invibesBidAdapter.md @@ -0,0 +1,29 @@ +# Overview + +``` +Module Name: Invibes Bid Adapter +Module Type: Bidder Adapter +Maintainer: system_operations@invibes.com +``` + +# Description + +Connect to Invibes for bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[400, 300]], + bids: [ + { + bidder: 'invibes', + params: { + placementId: '12345' + } + } + ] + } + ] +``` diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js new file mode 100644 index 00000000000..646448bd5a7 --- /dev/null +++ b/test/spec/modules/invibesBidAdapter_spec.js @@ -0,0 +1,249 @@ +import { expect } from 'chai'; +import { spec } from 'modules/invibesBidAdapter'; + +describe('invibesBidAdapter:', function () { + const BIDDER_CODE = 'invibes'; + const PLACEMENT_ID = '12345'; + const ENDPOINT = '//bid.videostep.com/Bid/VideoAdContent'; + const SYNC_ENDPOINT = '//k.r66net.com/GetUserSync'; + + let bidRequests = [ + { + bidId: 'b1', + bidder: BIDDER_CODE, + bidderRequestId: 'r1', + params: { + placementId: PLACEMENT_ID + }, + adUnitCode: 'test-div', + auctionId: 'a1', + sizes: [ + [300, 250], + [400, 300], + [125, 125] + ], + transactionId: 't1' + }, { + bidId: 'b2', + bidder: BIDDER_CODE, + bidderRequestId: 'r2', + params: { + placementId: 'abcde' + }, + adUnitCode: 'test-div', + auctionId: 'a2', + sizes: [ + [300, 250], + [400, 300] + ], + transactionId: 't2' + } + ]; + + beforeEach(function () { + top.window.invibes = null; + document.cookie = ''; + this.cStub1 = sinon.stub(console, 'info'); + }); + + afterEach(function () { + this.cStub1.restore(); + }); + + describe('isBidRequestValid:', function () { + context('valid bid request:', function () { + it('returns true when bidder params.placementId is set', function() { + const validBid = { + bidder: BIDDER_CODE, + params: { + placementId: PLACEMENT_ID + } + } + + expect(spec.isBidRequestValid(validBid)).to.be.true; + }) + }); + + context('invalid bid request:', function () { + it('returns false when no params', function () { + const invalidBid = { + bidder: BIDDER_CODE + } + + expect(spec.isBidRequestValid(invalidBid)).to.be.false; + }); + + it('returns false when placementId is not set', function() { + const invalidBid = { + bidder: BIDDER_CODE, + params: { + id: '5' + } + } + + expect(spec.isBidRequestValid(invalidBid)).to.be.false; + }); + }); + }); + + describe('buildRequests', () => { + it('sends bid request to ENDPOINT via GET', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('GET'); + }); + + it('sends cookies with the bid request', () => { + const request = spec.buildRequests(bidRequests); + expect(request.options.withCredentials).to.equal(true); + }); + + it('has location, html id, placement and width/height', () => { + const request = spec.buildRequests(bidRequests, { auctionStart: Date.now() }); + const parsedData = request.data; + expect(parsedData.location).to.exist; + expect(parsedData.videoAdHtmlId).to.exist; + expect(parsedData.vId).to.exist; + expect(parsedData.width).to.exist; + expect(parsedData.height).to.exist; + }); + + it('sends all Placement Ids', () => { + const request = spec.buildRequests(bidRequests); + expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[0].params.placementId); + expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[1].params.placementId); + }); + + it('uses cookies', () => { + global.document.cookie = 'ivNoCookie=1'; + let request = spec.buildRequests(bidRequests); + expect(request.data.lId).to.be.undefined; + }); + + it('does not overwrite the domain id', () => { + top.window.invibes = window.invibes || {}; + top.window.invibes.dom = {}; + let request = spec.buildRequests(bidRequests); + }); + + it('doesnt send the domain id if not graduated', () => { + global.document.cookie = 'ivbsdid={"id":"p4vauj.4ekt9w","hc":3,"temp":1}'; + let request = spec.buildRequests(bidRequests); + expect(request.data.lId).to.not.exist; + }); + + it('graduate and send the domain id', () => { + global.document.cookie = 'ivbsdid={"id":"p4rrk7.ax2i2s","hc":4,"temp":1}'; + let request = spec.buildRequests(bidRequests); + expect(request.data.lId).to.exist; + }); + + it('send the domain id if already graduated', () => { + global.document.cookie = 'ivbsdid={"id":"p4rrk7.ax2i2s"}'; + let request = spec.buildRequests(bidRequests); + expect(request.data.lId).to.exist; + }); + }) + + describe('interpretResponse', function () { + let response = { + Ads: [{ + BidPrice: 0.5, + VideoExposedId: 123 + }], + BidModel: { + BidVersion: 1, + PlacementId: '12345', + AuctionStartTime: Date.now(), + CreativeHtml: '' + } + }; + + let expectedResponse = [{ + requestId: bidRequests[0].bidId, + cpm: 0.5, + width: 400, + height: 300, + creativeId: 123, + currency: 'EUR', + netRevenue: true, + ttl: 300, + ad: ` + + + + + ` + }]; + + context('when the response is not valid', function () { + it('handles response with no bids requested', () => { + let emptyResult = spec.interpretResponse({ body: response }); + expect(emptyResult).to.be.empty; + }); + + it('handles empty response', () => { + let emptyResult = spec.interpretResponse(null, { bidRequests }); + expect(emptyResult).to.be.empty; + }); + + it('handles response with bidding is not configured', () => { + let emptyResult = spec.interpretResponse({ body: { Ads: [{ BidPrice: 1 }] } }, { bidRequests }); + expect(emptyResult).to.be.empty; + }); + + it('handles response with no ads are received', () => { + let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '12345' }, AdReason: 'No ads' } }, { bidRequests }); + expect(emptyResult).to.be.empty; + }); + + it('handles response with no ads are received - no ad reason', () => { + let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '12345' } } }, { bidRequests }); + expect(emptyResult).to.be.empty; + }); + + it('handles response when no placement Id matches', () => { + let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '123456' }, Ads: [{ BidPrice: 1 }] } }, { bidRequests }); + expect(emptyResult).to.be.empty; + }); + + it('handles response when placement Id is not present', () => { + let emptyResult = spec.interpretResponse({ BidModel: { }, Ads: [{ BidPrice: 1 }] }, { bidRequests }); + expect(emptyResult).to.be.empty; + }); + }); + + context('when the response is valid', function () { + it('responds with a valid bid', () => { + let result = spec.interpretResponse({ body: response }, { bidRequests }); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('responds with a valid bid and uses logger', () => { + localStorage.InvibesDEBUG = true; + let result = spec.interpretResponse({ body: response }, { bidRequests }); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('does not make multiple bids', () => { + localStorage.InvibesDEBUG = false; + let result = spec.interpretResponse({ body: response }, { bidRequests }); + let secondResult = spec.interpretResponse({ body: response }, { bidRequests }); + expect(secondResult).to.be.empty; + }); + }); + }); + + describe('getUserSyncs', function () { + it('returns an iframe if enabled', () => { + let response = spec.getUserSyncs({iframeEnabled: true}); + expect(response.type).to.equal('iframe'); + expect(response.url).to.equal(SYNC_ENDPOINT); + }); + + it('returns undefined if iframe not enabled ', () => { + let response = spec.getUserSyncs({ iframeEnabled: false }); + expect(response).to.equal(undefined); + }); + }); +}); From 3cf73955bba0374dd3ddd9352f8b5fb29f9ec257 Mon Sep 17 00:00:00 2001 From: John Ellis Date: Wed, 7 Mar 2018 13:18:39 -0500 Subject: [PATCH 0176/1594] Fix #2229 - Edge cookie string form (#2236) --- modules/yieldbotBidAdapter.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/yieldbotBidAdapter.js b/modules/yieldbotBidAdapter.js index 4616a31ea3d..bf21613e31f 100644 --- a/modules/yieldbotBidAdapter.js +++ b/modules/yieldbotBidAdapter.js @@ -535,13 +535,13 @@ export const YieldbotAdapter = { }, setCookie: function(name, value, expireMillis, path, domain, secure) { - const expireTime = expireMillis ? new Date(Date.now() + expireMillis).toGMTString() : ''; const dataValue = encodeURIComponent(value); - const docLocation = path || ''; - const pageDomain = domain || ''; - const httpsOnly = secure ? ';secure' : ''; + const cookieStr = name + '=' + dataValue + + (expireMillis ? ';expires=' + new Date(Date.now() + expireMillis).toGMTString() : '') + + (path ? ';path=' + path : '') + + (domain ? ';domain=' + domain : '') + + (secure ? ';secure' : ''); - const cookieStr = `${name}=${dataValue};expires=${expireTime};path=${docLocation};domain=${pageDomain}${httpsOnly}`; document.cookie = cookieStr; }, From 8f20009f091dff0b6ef0ff51a92570e812324017 Mon Sep 17 00:00:00 2001 From: Matt Kendall Date: Thu, 8 Mar 2018 13:19:26 -0500 Subject: [PATCH 0177/1594] PBS adapter not sending app or device (#2206) * Fix issue with PBS app and site not sending. * look in the right location for app and device. Add site.page * fix mysterious linting error --- modules/prebidServerBidAdapter.js | 34 ++++++----- .../modules/prebidServerBidAdapter_spec.js | 59 +++++++++++++++++++ 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index bc9b65cbd5b..7df557971bd 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -245,6 +245,24 @@ function _getDigiTrustQueryParams() { }; } +function _appendSiteAppDevice(request) { + if (!request) return; + + // ORTB specifies app OR site + if (typeof config.getConfig('app') === 'object') { + request.app = config.getConfig('app'); + request.app.publisher = {id: _s2sConfig.accountId} + } else { + request.site = { + publisher: { id: _s2sConfig.accountId }, + page: utils.getTopWindowUrl() + } + } + if (typeof config.getConfig('device') === 'object') { + request.device = config.getConfig('device'); + } +} + /* * Protocol spec for legacy endpoint * e.g., https:///v1/auction @@ -277,13 +295,7 @@ const LEGACY_PROTOCOL = { is_debug: !!getConfig('debug'), }; - // grab some global config and pass it along - ['app', 'device'].forEach(setting => { - let value = getConfig(setting); - if (typeof value === 'object') { - request[setting] = value; - } - }); + _appendSiteAppDevice(request); let digiTrust = _getDigiTrustQueryParams(); if (digiTrust) { @@ -437,19 +449,13 @@ const OPEN_RTB_PROTOCOL = { const request = { id: s2sBidRequest.tid, - site: {publisher: {id: _s2sConfig.accountId}}, source: {tid: s2sBidRequest.tid}, tmax: _s2sConfig.timeout, imp: imps, test: getConfig('debug') ? 1 : 0, }; - ['app', 'device'].forEach(setting => { - let value = getConfig(setting); - if (typeof value === 'object') { - request[setting] = value; - } - }); + _appendSiteAppDevice(request); const digiTrust = _getDigiTrustQueryParams(); if (digiTrust) { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 328cc1fa750..e28d5854ba2 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -344,6 +344,7 @@ describe('S2S Adapter', () => { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); + config.resetConfig(); }); afterEach(() => xhr.restore()); @@ -394,6 +395,64 @@ describe('S2S Adapter', () => { delete window.DigiTrust; }); + + it('adds device and app objects to request', () => { + const _config = { s2sConfig: CONFIG, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.device).to.deep.equal({ + ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC', + }); + expect(requestBid.app).to.deep.equal({ + bundle: 'com.test.app', + publisher: {'id': '1'} + }); + }); + + it('adds device and app objects to request for ORTB', () => { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + + const _config = { + s2sConfig: s2sConfig, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, + } + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.device).to.deep.equal({ + ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC', + }); + expect(requestBid.app).to.deep.equal({ + bundle: 'com.test.app', + publisher: {'id': '1'} + }); + }); + + it('adds site if app is not present', () => { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + + const _config = { + s2sConfig: s2sConfig, + } + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.site).to.exist.and.to.be.a('object'); + expect(requestBid.site.publisher).to.exist.and.to.be.a('object'); + expect(requestBid.site.page).to.exist.and.to.be.a('string'); + }); }); describe('response handler', () => { From f7813d509a023ba0e67e70266f1c94b29f6dfd7b Mon Sep 17 00:00:00 2001 From: LifeStreet Date: Thu, 8 Mar 2018 10:21:48 -0800 Subject: [PATCH 0178/1594] Update Lifestreet adapter to 1.0 (#2197) --- modules/lifestreetBidAdapter.js | 149 ++++++++++++++ modules/lifestreetBidAdapter.md | 47 +++++ .../spec/modules/lifestreetBidAdapter_spec.js | 181 ++++++++++++++++++ 3 files changed, 377 insertions(+) create mode 100644 modules/lifestreetBidAdapter.js create mode 100644 modules/lifestreetBidAdapter.md create mode 100644 test/spec/modules/lifestreetBidAdapter_spec.js diff --git a/modules/lifestreetBidAdapter.js b/modules/lifestreetBidAdapter.js new file mode 100644 index 00000000000..919e83576d3 --- /dev/null +++ b/modules/lifestreetBidAdapter.js @@ -0,0 +1,149 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; + +const BIDDER_CODE = 'lifestreet'; +const ADAPTER_VERSION = 'prebidJS-2.0'; + +const urlTemplate = template`//ads.lfstmedia.com/gate/${'adapter'}/${'slot'}?adkey=${'adkey'}&ad_size=${'ad_size'}&__location=${'location'}&__referrer=${'referrer'}&__wn=${'wn'}&__sf=${'sf'}&__fif=${'fif'}&__if=${'if'}&__stamp=${'stamp'}&__pp=1&__hb=1&_prebid_json=1&__gz=1&deferred_format=vast_2_0,vast_3_0&__hbver=${'hbver'}`; + +/** + * Creates a bid requests for a given bid. + * + * @param {BidRequest} bid The bid params to use for formatting a request + */ +function formatBidRequest(bid) { + let url = urlTemplate({ + adapter: 'prebid', + slot: bid.params.slot, + adkey: bid.params.adkey, + ad_size: bid.params.ad_size, + location: encodeURIComponent(utils.getTopWindowLocation()), + referrer: encodeURIComponent(utils.getTopWindowReferrer()), + wn: boolToString(/fb_http/i.test(window.name)), + sf: boolToString(window['sfAPI'] || window['$sf']), + fif: boolToString(window['inDapIF'] === true), + if: boolToString(window !== window.top), + stamp: new Date().getTime(), + hbver: ADAPTER_VERSION + }); + + return { + method: 'GET', + url: url, + bidId: bid.bidId + }; +} + +/** + * A helper function to form URL from the template + */ +function template(strings, ...keys) { + return function(...values) { + let dict = values[values.length - 1] || {}; + let result = [strings[0]]; + keys.forEach(function(key, i) { + let value = isInteger(key) ? values[key] : dict[key]; + result.push(value, strings[i + 1]); + }); + return result.join(''); + }; +} + +/** + * A helper function for template to generate string from boolean + */ +function boolToString(value) { + return value ? '1' : '0'; +} + +/** + * A helper function for template + */ +function isInteger(value) { + return typeof value === 'number' && + isFinite(value) && Math.floor(value) === value; +} + +/** + * Validates response from Lifestreet AD server + */ +function isResponseValid(response) { + return !/^\s*\{\s*"advertisementAvailable"\s*:\s*false/i.test(response.content) && + response.content.indexOf('') === -1 && (typeof response.cpm !== 'undefined') && + response.status === 1; +} + +export const spec = { + code: BIDDER_CODE, + aliases: ['lsm'], // short code + supportedMediaTypes: [BANNER, VIDEO], // Lifestreet supports banner and video media types + + /** + * 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 !!(bid.params.slot && bid.params.adkey && bid.params.ad_size); + }, + + /** + * 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(bid => { + return formatBidRequest(bid) + }); + }, + + /** + * 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 = []; + let response = serverResponse.body; + if (!isResponseValid(response)) { + return bidResponses; + } + + const bidResponse = { + requestId: bidRequest.bidId, + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.creativeId, + currency: response.currency ? response.currency : 'USD', + netRevenue: response.netRevenue ? response.netRevenue : true, + ttl: response.ttl ? response.ttl : 86400 + }; + + if (response.hasOwnProperty('dealId')) { + bidResponse.dealId = response.dealId; + } + + if (response.content_type.indexOf('vast') > -1) { + if (typeof response.vastUrl !== 'undefined') { + bidResponse.vastUrl = response.vastUrl; + } else { + bidResponse.vastXml = response.content; + } + bidResponse.mediaType = VIDEO; + } else { + bidResponse.ad = response.content; + bidResponse.mediaType = BANNER; + } + + bidResponses.push(bidResponse); + return bidResponses; + } +}; + +registerBidder(spec); diff --git a/modules/lifestreetBidAdapter.md b/modules/lifestreetBidAdapter.md new file mode 100644 index 00000000000..58cf4a533a9 --- /dev/null +++ b/modules/lifestreetBidAdapter.md @@ -0,0 +1,47 @@ +# Overview + +Module Name: Lifestreet Bid Adapter + +Module Type: Lifestreet Adapter + +Maintainer: hb.tech@lifestreet.com + +# Description + +Module that connects to Lifestreet's demand sources + +# Test Parameters +```javascript + var adUnits = [ + // Banner adUnit + { + code: 'test-ad', + sizes: [[160, 600]], + bids: [ + { + bidder: 'lifestreet', + params: { + slot: 'slot166704', + adkey: '78c', + ad_size: '160x600' + } + } + ] + }, + // Video instream adUnit + { + code: 'test-video-ad', + sizes: [[640, 480]], + bids: [ + { + bidder: 'lifestreet', + params: { + slot: 'slot1227631', + adkey: 'a98', + ad_size: '640x480' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/lifestreetBidAdapter_spec.js b/test/spec/modules/lifestreetBidAdapter_spec.js new file mode 100644 index 00000000000..b47c5f949e2 --- /dev/null +++ b/test/spec/modules/lifestreetBidAdapter_spec.js @@ -0,0 +1,181 @@ +import {expect} from 'chai'; +import * as utils from 'src/utils'; +import {spec} from 'modules/lifestreetBidAdapter'; +import {config} from 'src/config'; + +let getDefaultBidRequest = () => { + return { + bidderCode: 'lifestreet', + auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + bidderRequestId: '7101db09af0dg2', + start: new Date().getTime(), + bids: [{ + bidder: 'lifestreet', + bidId: '84ab500420329d', + bidderRequestId: '7101db09af0dg2', + auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + placementCode: 'foo', + params: getBidParams() + }] + }; +}; + +let getVASTAd = () => { + return ` + + + Lifestreet wrapper + + + + + + `; +}; + +let getBidParams = () => { + return { + slot: 'slot166704', + adkey: '78c', + ad_size: '160x600' + }; +}; + +let getDefaultBidResponse = (isBanner, noBid = 0) => { + let noBidContent = isBanner ? '{"advertisementAvailable": false}' : ''; + let content = isBanner ? '' : getVASTAd(); + return { + status: noBid ? 0 : 1, + cpm: 1.0, + width: 160, + height: 600, + creativeId: 'test', + dealId: 'test', + content: noBid ? noBidContent : content, + content_type: isBanner ? 'display' : 'vast_2_0' + }; +}; + +describe('LifestreetAdapter', () => { + const LIFESTREET_URL = '//ads.lfstmedia.com/gate/'; + const ADAPTER_VERSION = 'prebidJS-2.0'; + + describe('buildRequests()', () => { + it('method exists and is a function', () => { + expect(spec.buildRequests).to.exist.and.to.be.a('function'); + }); + + it('should not return request when no bids are present', () => { + let [request] = spec.buildRequests([]); + expect(request).to.be.empty; + }); + + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + it('should return request for Lifestreet endpoint', () => { + expect(request.url).to.contain(LIFESTREET_URL); + }); + + it('should use json adapter', () => { + expect(request.url).to.contain('/prebid/'); + }); + + it('should contain slot', () => { + expect(request.url).to.contain('slot166704'); + }); + it('should contain adkey', () => { + expect(request.url).to.contain('adkey=78c'); + }); + it('should contain ad_size', () => { + expect(request.url).to.contain('ad_size=160x600'); + }); + + it('should contain location and rferrer paramters', () => { + expect(request.url).to.contain('__location='); + expect(request.url).to.contain('__referrer='); + }); + it('should contain info parameters', () => { + expect(request.url).to.contain('__wn='); + expect(request.url).to.contain('__sf='); + expect(request.url).to.contain('__fif='); + expect(request.url).to.contain('__if='); + expect(request.url).to.contain('__stamp='); + expect(request.url).to.contain('__pp='); + }); + + it('should contain HB enabled', () => { + expect(request.url).to.contain('__hb=1'); + }); + it('should include gzip', () => { + expect(request.url).to.contain('__gz=1'); + }); + + it('should contain the right version of adapter', () => { + expect(request.url).to.contain('__hbver=' + ADAPTER_VERSION); + }); + }); + describe('interpretResponse()', () => { + it('should return formatted bid response with required properties', () => { + let bidRequest = getDefaultBidRequest().bids[0]; + let bidResponse = { body: getDefaultBidResponse(true) }; + let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); + expect(formattedBidResponse).to.deep.equal([{ + requestId: bidRequest.bidId, + cpm: 1.0, + width: 160, + height: 600, + ad: '', + creativeId: 'test', + currency: 'USD', + dealId: 'test', + netRevenue: true, + ttl: 86400, + mediaType: 'banner' + }]); + }); + it('should return formatted VAST bid response with required properties', () => { + let bidRequest = getDefaultBidRequest().bids[0]; + let bidResponse = { body: getDefaultBidResponse(false) }; + let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); + expect(formattedBidResponse).to.deep.equal([{ + requestId: bidRequest.bidId, + cpm: 1.0, + width: 160, + height: 600, + vastXml: getVASTAd(), + creativeId: 'test', + currency: 'USD', + dealId: 'test', + netRevenue: true, + ttl: 86400, + mediaType: 'video' + }]); + }); + it('should return formatted VAST bid response with vastUrl', () => { + let bidRequest = getDefaultBidRequest().bids[0]; + let bidResponse = { body: getDefaultBidResponse(false) }; + bidResponse.body.vastUrl = 'http://lifestreet.com'; // set vastUrl + let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); + expect(formattedBidResponse).to.deep.equal([{ + requestId: bidRequest.bidId, + cpm: 1.0, + width: 160, + height: 600, + vastUrl: 'http://lifestreet.com', + creativeId: 'test', + currency: 'USD', + dealId: 'test', + netRevenue: true, + ttl: 86400, + mediaType: 'video' + }]); + }); + + it('should return no-bid', () => { + let bidRequest = getDefaultBidRequest().bids[0]; + let bidResponse = { body: getDefaultBidResponse(true, true) }; + let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); + expect(formattedBidResponse).to.be.empty; + }); + }); +}); From 5486b63d99f064966f1bbd1bb6b30e4135d686c6 Mon Sep 17 00:00:00 2001 From: varashellov Date: Mon, 12 Mar 2018 21:46:07 +0300 Subject: [PATCH 0179/1594] Update Platform.io Adapter (#2230) * Add PlatformioBidAdapter * Update platformioBidAdapter.js * Add files via upload * Update hello_world.html * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Update hello_world.html * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update hello_world.html * Add files via upload * Update platformioBidAdapter ## Type of change - [x] Other ## Description of change 1. RequestURL changes 2. Add placementCode to request params * Update platformioBidAdapter * Update platformioBidAdapter ## Type of change - [x] Other ## Description of change 1. RequestURL changes 2. Add placementCode to request params * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.js Endpoint URL change * Update platformioBidAdapter_spec.js Endpoint URL change * Update platformioBidAdapter_spec.js * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update platformioBidAdapter.md --- modules/platformioBidAdapter.js | 446 +++++++++--------- modules/platformioBidAdapter.md | 4 +- .../spec/modules/platformioBidAdapter_spec.js | 416 ++++++++-------- 3 files changed, 439 insertions(+), 427 deletions(-) diff --git a/modules/platformioBidAdapter.js b/modules/platformioBidAdapter.js index 93907c9bb1a..3c53022189f 100644 --- a/modules/platformioBidAdapter.js +++ b/modules/platformioBidAdapter.js @@ -1,220 +1,226 @@ - -import {logError, getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; - -const NATIVE_DEFAULTS = { - TITLE_LEN: 100, - DESCR_LEN: 200, - SPONSORED_BY_LEN: 50, - IMG_MIN: 150, - ICON_MIN: 50, -}; - -export const spec = { - - code: 'platformio', - supportedMediaTypes: ['native'], - - isBidRequestValid: bid => ( - !!(bid && bid.params && bid.params.pubId && bid.params.siteId) - ), - buildRequests: bidRequests => { - const request = { - id: bidRequests[0].bidderRequestId, - at: 2, - imp: bidRequests.map(slot => impression(slot)), - site: site(bidRequests), - device: device(), - }; - return { - method: 'POST', - url: '//piohbdisp.hb.adx1.com/', - data: JSON.stringify(request), - }; - }, - interpretResponse: (response, request) => ( - bidResponseAvailable(request, response.body) - ), -}; - -function bidResponseAvailable(bidRequest, bidResponse) { - const idToImpMap = {}; - const idToBidMap = {}; - const ortbRequest = parse(bidRequest.data); - ortbRequest.imp.forEach(imp => { - idToImpMap[imp.id] = imp; - }); - if (bidResponse) { - bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { - idToBidMap[bid.impid] = bid; - })); - } - const bids = []; - Object.keys(idToImpMap).forEach(id => { - if (idToBidMap[id]) { - const bid = {}; - bid.requestId = id; - bid.adId = id; - bid.creativeId = id; - bid.cpm = idToBidMap[id].price; - bid.currency = bidResponse.cur; - bid.ttl = 360; - bid.netRevenue = true; - if (idToImpMap[id]['native']) { - bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); - let nurl = idToBidMap[id].nurl; - nurl = nurl.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); - nurl = nurl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); - nurl = nurl.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); - nurl = nurl.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); - bid['native']['impressionTrackers'] = [nurl]; - bid.mediaType = 'native'; - } else { - bid.ad = idToBidMap[id].adm; - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); - bid.width = idToImpMap[id].banner.w; - bid.height = idToImpMap[id].banner.h; - } - bids.push(bid); - } - }); - return bids; -} -function impression(slot) { - return { - id: slot.bidId, - banner: banner(slot), - 'native': nativeImpression(slot), - bidfloor: slot.params.bidFloor || '0.000001', - tagid: slot.params.placementId.toString(), - }; -} -function banner(slot) { - if (!slot.nativeParams) { - const size = slot.params.size.toUpperCase().split('X'); - const width = parseInt(size[0]); - const height = parseInt(size[1]); - return { - w: width, - h: height, - }; - }; -} - -function nativeImpression(slot) { - if (slot.nativeParams) { - const assets = []; - addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); - addAsset(assets, dataAsset(2, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); - addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); - addAsset(assets, imageAsset(4, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); - addAsset(assets, imageAsset(5, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); - return { - request: JSON.stringify({ assets }), - ver: '1.1', - }; - } - return null; -} - -function addAsset(assets, asset) { - if (asset) { - assets.push(asset); - } -} - -function titleAsset(id, params, defaultLen) { - if (params) { - return { - id, - required: params.required ? 1 : 0, - title: { - len: params.len || defaultLen, - }, - }; - } - return null; -} - -function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { - return params ? { - id, - required: params.required ? 1 : 0, - img: { - type, - wmin: params.wmin || defaultMinWidth, - hmin: params.hmin || defaultMinHeight, - } - } : null; -} - -function dataAsset(id, params, type, defaultLen) { - return params ? { - id, - required: params.required ? 1 : 0, - data: { - type, - len: params.len || defaultLen, - } - } : null; -} - -function site(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; - const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; - return { - publisher: { - id: pubId.toString(), - domain: getTopWindowLocation().hostname, - }, - id: siteId.toString(), - ref: getTopWindowReferrer(), - page: getTopWindowLocation().href, - } -} - -function device() { - return { - ua: navigator.userAgent, - language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), - w: (window.screen.width || window.innerWidth), - h: (window.screen.height || window.innerHeigh), - }; -} -function parse(rawResponse) { - try { - if (rawResponse) { - return JSON.parse(rawResponse); - } - } catch (ex) { - logError('platformio.parse', 'ERROR', ex); - } - return null; -} - -function nativeResponse(imp, bid) { - if (imp['native']) { - const nativeAd = parse(bid.adm); - const keys = {}; - if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { - nativeAd['native'].assets.forEach(asset => { - keys.title = asset.title ? asset.title.text : keys.title; - keys.body = asset.data && asset.id === 2 ? asset.data.value : keys.body; - keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy; - keys.icon = asset.img && asset.id === 4 ? asset.img.url : keys.icon; - keys.image = asset.img && asset.id === 5 ? asset.img.url : keys.image; - }); - if (nativeAd['native'].link) { - keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); - } - return keys; - } - } - return null; -} - -registerBidder(spec); + +import {logError, getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const NATIVE_DEFAULTS = { + TITLE_LEN: 100, + DESCR_LEN: 200, + SPONSORED_BY_LEN: 50, + IMG_MIN: 150, + ICON_MIN: 50, +}; + +export const spec = { + + code: 'platformio', + supportedMediaTypes: ['banner', 'native'], + + isBidRequestValid: bid => ( + !!(bid && bid.params && bid.params.pubId && bid.params.siteId) + ), + buildRequests: bidRequests => { + const request = { + id: bidRequests[0].bidderRequestId, + at: 2, + imp: bidRequests.map(slot => impression(slot)), + site: site(bidRequests), + device: device(), + }; + return { + method: 'POST', + url: '//piohbdisp.hb.adx1.com/', + data: JSON.stringify(request), + }; + }, + interpretResponse: (response, request) => ( + bidResponseAvailable(request, response.body) + ), +}; + +function bidResponseAvailable(bidRequest, bidResponse) { + const idToImpMap = {}; + const idToBidMap = {}; + const ortbRequest = parse(bidRequest.data); + ortbRequest.imp.forEach(imp => { + idToImpMap[imp.id] = imp; + }); + if (bidResponse) { + bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { + idToBidMap[bid.impid] = bid; + })); + } + const bids = []; + Object.keys(idToImpMap).forEach(id => { + if (idToBidMap[id]) { + const bid = {}; + bid.requestId = id; + bid.adId = id; + bid.creativeId = id; + bid.cpm = idToBidMap[id].price; + bid.currency = bidResponse.cur; + bid.ttl = 360; + bid.netRevenue = true; + if (idToImpMap[id]['native']) { + bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); + let nurl = idToBidMap[id].nurl; + nurl = nurl.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); + bid['native']['impressionTrackers'] = [nurl]; + bid.mediaType = 'native'; + } else { + bid.ad = idToBidMap[id].adm; + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); + bid.width = idToImpMap[id].banner.w; + bid.height = idToImpMap[id].banner.h; + } + bids.push(bid); + } + }); + return bids; +} +function impression(slot) { + return { + id: slot.bidId, + banner: banner(slot), + 'native': nativeImpression(slot), + bidfloor: slot.params.bidFloor || '0.000001', + tagid: slot.params.placementId.toString(), + }; +} +function banner(slot) { + if (!slot.nativeParams) { + const size = slot.params.size.toUpperCase().split('X'); + const width = parseInt(size[0]); + const height = parseInt(size[1]); + return { + w: width, + h: height, + }; + }; +} + +function nativeImpression(slot) { + if (slot.nativeParams) { + const assets = []; + addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); + addAsset(assets, dataAsset(2, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); + addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); + addAsset(assets, imageAsset(4, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); + addAsset(assets, imageAsset(5, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); + return { + request: JSON.stringify({ assets }), + ver: '1.1', + }; + } + return null; +} + +function addAsset(assets, asset) { + if (asset) { + assets.push(asset); + } +} + +function titleAsset(id, params, defaultLen) { + if (params) { + return { + id, + required: params.required ? 1 : 0, + title: { + len: params.len || defaultLen, + }, + }; + } + return null; +} + +function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { + return params ? { + id, + required: params.required ? 1 : 0, + img: { + type, + wmin: params.wmin || defaultMinWidth, + hmin: params.hmin || defaultMinHeight, + } + } : null; +} + +function dataAsset(id, params, type, defaultLen) { + return params ? { + id, + required: params.required ? 1 : 0, + data: { + type, + len: params.len || defaultLen, + } + } : null; +} + +function site(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; + const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; + return { + publisher: { + id: pubId.toString(), + domain: getTopWindowLocation().hostname, + }, + id: siteId.toString(), + ref: getTopWindowReferrer(), + page: getTopWindowLocation().href, + } +} + +function device() { + return { + ua: navigator.userAgent, + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), + w: (window.screen.width || window.innerWidth), + h: (window.screen.height || window.innerHeigh), + }; +} +function parse(rawResponse) { + try { + if (rawResponse) { + return JSON.parse(rawResponse); + } + } catch (ex) { + logError('platformio.parse', 'ERROR', ex); + } + return null; +} + +function nativeResponse(imp, bid) { + if (imp['native']) { + const nativeAd = parse(bid.adm); + const keys = {}; + keys.image = {}; + keys.icon = {}; + if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { + nativeAd['native'].assets.forEach(asset => { + keys.title = asset.title ? asset.title.text : keys.title; + keys.body = asset.data && asset.id === 2 ? asset.data.value : keys.body; + keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy; + keys.icon.url = asset.img && asset.id === 4 ? asset.img.url : keys.icon.url; + keys.icon.width = asset.img && asset.id === 4 ? asset.img.w : keys.icon.width; + keys.icon.height = asset.img && asset.id === 4 ? asset.img.h : keys.icon.height; + keys.image.url = asset.img && asset.id === 5 ? asset.img.url : keys.image.url; + keys.image.width = asset.img && asset.id === 5 ? asset.img.w : keys.image.width; + keys.image.height = asset.img && asset.id === 5 ? asset.img.h : keys.image.height; + }); + if (nativeAd['native'].link) { + keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); + } + return keys; + } + } + return null; +} + +registerBidder(spec); diff --git a/modules/platformioBidAdapter.md b/modules/platformioBidAdapter.md index 81ac81380b0..4ef0aa755bf 100644 --- a/modules/platformioBidAdapter.md +++ b/modules/platformioBidAdapter.md @@ -21,7 +21,7 @@ Please use ```platformio``` as the bidder code. pubId: '29521', // required siteId: '26047', // required size: '250X250', // required - placementId: '123', + placementId: '123', // required bidFloor: '0.001' } }] @@ -40,7 +40,7 @@ Please use ```platformio``` as the bidder code. params: { pubId: '29521', // required siteId: '26047', // required - placementId: '123', + placementId: '123', // required bidFloor: '0.001' } }] diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index 7caca2e0d17..c69a31f1ec5 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -1,205 +1,211 @@ -import {expect} from 'chai'; -import {spec} from 'modules/platformioBidAdapter'; -import {getTopWindowLocation} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; - -describe('Platform.io Adapter Tests', () => { - const slotConfigs = [{ - placementCode: '/DfpAccount1/slot1', - bidId: 'bid12345', - params: { - pubId: '29521', - siteId: '26047', - placementId: '123', - size: '300x250', - bidFloor: '0.001' - } - }, { - placementCode: '/DfpAccount2/slot2', - bidId: 'bid23456', - params: { - pubId: '29521', - siteId: '26047', - placementId: '1234', - size: '728x90', - bidFloor: '0.000001' - } - }]; - const nativeSlotConfig = [{ - placementCode: '/DfpAccount1/slot3', - bidId: 'bid12345', - nativeParams: { - title: { required: true, len: 200 }, - body: {}, - image: { wmin: 100 }, - sponsoredBy: { }, - icon: { } - }, - params: { - pubId: '29521', - placementId: '123', - siteId: '26047' - } - }]; - - it('Verify build request', () => { - const request = spec.buildRequests(slotConfigs); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // site object - expect(ortbRequest.site).to.not.equal(null); - expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('29521'); - expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); - expect(ortbRequest.imp).to.have.lengthOf(2); - // device object - expect(ortbRequest.device).to.not.equal(null); - expect(ortbRequest.device.ua).to.equal(navigator.userAgent); - // slot 1 - expect(ortbRequest.imp[0].tagid).to.equal('123'); - expect(ortbRequest.imp[0].banner).to.not.equal(null); - expect(ortbRequest.imp[0].banner.w).to.equal(300); - expect(ortbRequest.imp[0].banner.h).to.equal(250); - expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); - // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('1234'); - expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(728); - expect(ortbRequest.imp[1].banner.h).to.equal(90); - expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); - }); - - it('Verify parse response', () => { - const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: 'This is an Ad' - }] - }], - cur: 'USD' - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.ad).to.equal('This is an Ad'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.adId).to.equal('bid12345'); - expect(bid.creativeId).to.equal('bid12345'); - expect(bid.netRevenue).to.equal(true); - expect(bid.currency).to.equal('USD'); - expect(bid.ttl).to.equal(360); - }); - - it('Verify full passback', () => { - const request = spec.buildRequests(slotConfigs); - const bids = spec.interpretResponse({ body: null }, request) - expect(bids).to.have.lengthOf(0); - }); - - it('Verify Native request', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // // native impression - expect(ortbRequest.imp[0].tagid).to.equal('123'); - const nativePart = ortbRequest.imp[0]['native']; - expect(nativePart).to.not.equal(null); - expect(nativePart.ver).to.equal('1.1'); - expect(nativePart.request).to.not.equal(null); - // native request assets - const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); - expect(nativeRequest).to.not.equal(null); - expect(nativeRequest.assets).to.have.lengthOf(5); - expect(nativeRequest.assets[0].id).to.equal(1); - expect(nativeRequest.assets[1].id).to.equal(2); - expect(nativeRequest.assets[2].id).to.equal(3); - expect(nativeRequest.assets[3].id).to.equal(4); - expect(nativeRequest.assets[4].id).to.equal(5); - expect(nativeRequest.assets[0].required).to.equal(1); - expect(nativeRequest.assets[0].title).to.not.equal(null); - expect(nativeRequest.assets[0].title.len).to.equal(200); - expect(nativeRequest.assets[1].title).to.be.undefined; - expect(nativeRequest.assets[1].data).to.not.equal(null); - expect(nativeRequest.assets[1].data.type).to.equal(2); - expect(nativeRequest.assets[1].data.len).to.equal(200); - expect(nativeRequest.assets[2].required).to.equal(0); - expect(nativeRequest.assets[3].img).to.not.equal(null); - expect(nativeRequest.assets[3].img.wmin).to.equal(50); - expect(nativeRequest.assets[3].img.hmin).to.equal(50); - expect(nativeRequest.assets[3].img.type).to.equal(1); - expect(nativeRequest.assets[4].img).to.not.equal(null); - expect(nativeRequest.assets[4].img.wmin).to.equal(100); - expect(nativeRequest.assets[4].img.hmin).to.equal(150); - expect(nativeRequest.assets[4].img.type).to.equal(3); - }); - - it('Verify Native response', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - const nativeResponse = { - 'native': { - assets: [ - { id: 1, title: { text: 'Ad Title' } }, - { id: 2, data: { value: 'Test description' } }, - { id: 3, data: { value: 'Brand' } }, - { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png' } }, - { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png' } } - ], - link: { url: 'http://brand.com/' } - } - }; - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - nurl: 'http://rtb.adx1.com/log', - adm: JSON.stringify(nativeResponse) - }] - }], - cur: 'USD', - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - // verify bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.adId).to.equal('bid12345'); - expect(bid.ad).to.be.undefined; - expect(bid.mediaType).to.equal('native'); - const nativeBid = bid['native']; - expect(nativeBid).to.not.equal(null); - expect(nativeBid.title).to.equal('Ad Title'); - expect(nativeBid.sponsoredBy).to.equal('Brand'); - expect(nativeBid.icon).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); - expect(nativeBid.image).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); - expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); - expect(nativeBid.impressionTrackers).to.have.lengthOf(1); - expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); - }); - - it('Verifies bidder code', () => { - expect(spec.code).to.equal('platformio'); - }); - - it('Verifies supported media types', () => { - expect(spec.supportedMediaTypes).to.have.lengthOf(1); - expect(spec.supportedMediaTypes[0]).to.equal('native'); - }); - - it('Verifies if bid request valid', () => { - expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); - }); -}); + +import {expect} from 'chai'; +import {spec} from 'modules/platformioBidAdapter'; +import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; + +describe('Platform.io Adapter Tests', () => { + const slotConfigs = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + pubId: '29521', + siteId: '26047', + placementId: '123', + size: '300x250', + bidFloor: '0.001' + } + }, { + placementCode: '/DfpAccount2/slot2', + bidId: 'bid23456', + params: { + pubId: '29521', + siteId: '26047', + placementId: '1234', + size: '728x90', + bidFloor: '0.000001' + } + }]; + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + nativeParams: { + title: { required: true, len: 200 }, + body: {}, + image: { wmin: 100 }, + sponsoredBy: { }, + icon: { } + }, + params: { + pubId: '29521', + placementId: '123', + siteId: '26047' + } + }]; + + it('Verify build request', () => { + const request = spec.buildRequests(slotConfigs); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // site object + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.publisher).to.not.equal(null); + expect(ortbRequest.site.publisher.id).to.equal('29521'); + expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); + expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); + expect(ortbRequest.imp).to.have.lengthOf(2); + // device object + expect(ortbRequest.device).to.not.equal(null); + expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(ortbRequest.imp[0].tagid).to.equal('123'); + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); + // slot 2 + expect(ortbRequest.imp[1].tagid).to.equal('1234'); + expect(ortbRequest.imp[1].banner).to.not.equal(null); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); + expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); + }); + + it('Verify parse response', () => { + const request = spec.buildRequests(slotConfigs); + const ortbRequest = JSON.parse(request.data); + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'This is an Ad' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.ad).to.equal('This is an Ad'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.adId).to.equal('bid12345'); + expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + + it('Verify full passback', () => { + const request = spec.buildRequests(slotConfigs); + const bids = spec.interpretResponse({ body: null }, request) + expect(bids).to.have.lengthOf(0); + }); + + it('Verify Native request', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // // native impression + expect(ortbRequest.imp[0].tagid).to.equal('123'); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(5); + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[3].id).to.equal(4); + expect(nativeRequest.assets[4].id).to.equal(5); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(2); + expect(nativeRequest.assets[1].data.len).to.equal(200); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[3].img).to.not.equal(null); + expect(nativeRequest.assets[3].img.wmin).to.equal(50); + expect(nativeRequest.assets[3].img.hmin).to.equal(50); + expect(nativeRequest.assets[3].img.type).to.equal(1); + expect(nativeRequest.assets[4].img).to.not.equal(null); + expect(nativeRequest.assets[4].img.wmin).to.equal(100); + expect(nativeRequest.assets[4].img.hmin).to.equal(150); + expect(nativeRequest.assets[4].img.type).to.equal(3); + }); + + it('Verify Native response', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { id: 1, title: { text: 'Ad Title' } }, + { id: 2, data: { value: 'Test description' } }, + { id: 3, data: { value: 'Brand' } }, + { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + ], + link: { url: 'http://brand.com/' } + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + nurl: 'http://rtb.adx1.com/log', + adm: JSON.stringify(nativeResponse) + }] + }], + cur: 'USD', + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Brand'); + expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.image.width).to.equal(300); + expect(nativeBid.image.height).to.equal(300); + expect(nativeBid.icon.width).to.equal(100); + expect(nativeBid.icon.height).to.equal(100); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(1); + expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); + }); + + it('Verifies bidder code', () => { + expect(spec.code).to.equal('platformio'); + }); + + it('Verifies supported media types', () => { + expect(spec.supportedMediaTypes).to.have.lengthOf(2); + expect(spec.supportedMediaTypes[0]).to.equal('banner'); + expect(spec.supportedMediaTypes[1]).to.equal('native'); + }); + + it('Verifies if bid request valid', () => { + expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + }); +}); From 205b926cdb992ead0f2a534b4374fd33c4c7d460 Mon Sep 17 00:00:00 2001 From: bretg Date: Mon, 12 Mar 2018 16:02:01 -0400 Subject: [PATCH 0180/1594] create RELEASE_SCHEDULE.md (#2255) * create RELEASE_SCHEDULE.md * adding slack channel --- RELEASE_SCHEDULE.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 RELEASE_SCHEDULE.md diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md new file mode 100644 index 00000000000..f1e930b98b6 --- /dev/null +++ b/RELEASE_SCHEDULE.md @@ -0,0 +1,22 @@ +# Release Schedule + +We push a new release of Prebid.js every other week on Tuesday. During the adoption phase for 1.x, we are releasing updates for 1.x and 0.x at the same time. + +While the releases will be available immediately for those using direct Git access, +it will be about a week before the Prebid Org [Download Page](http://prebid.org/download.html) will be updated. + +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 #headerbidding-dev channel in subredditadops.slack.com. + +# FAQs + +**1. Is there flexibility in the 2-week schedule?** + +If a major bug is found in the current release, a maintenance patch will be done as soon as possible. + +It is unlikely that we will put out a maintenance patch at the request of a given bid adapter or module owner. + +**2. What Pull Requests make it into a release?** + +Every PR that's merged into master will be part of a release. Here are the [PR review guidelines](https://github.com/prebid/Prebid.js/blob/master/PR_REVIEW.md). From 58a5af09c6d85e021911652c493a182b5b710802 Mon Sep 17 00:00:00 2001 From: Christopher Nguyen Date: Tue, 13 Mar 2018 08:18:37 -0700 Subject: [PATCH 0181/1594] use b64EncodeUnicode to encode strings with unicode chars in them (#2245) --- modules/sharethroughBidAdapter.js | 11 ++++++++++- test/spec/modules/sharethroughBidAdapter_spec.js | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index ef0cf9619c1..ce4c87be4d3 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -48,7 +48,7 @@ function generateAd(body, req) { return `
- + `; } +// 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); + })); +} + registerBidder(sharethroughAdapterSpec); diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index fdac8a84d8d..d7fa3f728ac 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -40,14 +40,22 @@ const bidderResponse = { 'cpm': 12.34, 'creative': { 'deal_id': 'aDealId', - 'creative_key': 'aCreativeId' + 'creative_key': 'aCreativeId', + 'title': '✓ à la mode' } }], 'stxUserId': '' }, header: { get: (header) => header } }; - +// Mirrors the one in modules/sharethroughBidAdapter.js as the function is unexported +const b64EncodeUnicode = (str) => { + return btoa( + encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, + function toSolidBytes(match, p1) { + return String.fromCharCode('0x' + p1); + })); +} describe('sharethrough adapter spec', () => { describe('.code', () => { it('should return a bidder code of sharethrough', () => { @@ -111,8 +119,10 @@ describe('sharethrough adapter spec', () => { it('correctly sends back a sfp script tag', () => { const adMarkup = spec.interpretResponse(bidderResponse, prebidRequest[0])[0].ad; - const resp = btoa(JSON.stringify(bidderResponse)); + let resp = null; + expect(() => btoa(JSON.stringify(bidderResponse))).to.throw(); + expect(() => resp = 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); From dfcae6be1856e9e0b05f37402d7a376fb734b9d5 Mon Sep 17 00:00:00 2001 From: Roffray Date: Tue, 13 Mar 2018 19:07:24 +0100 Subject: [PATCH 0182/1594] Fix: add mediatype in bid response (#2260) --- modules/vubleBidAdapter.js | 3 ++- test/spec/modules/vubleBidAdapter_spec.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/vubleBidAdapter.js b/modules/vubleBidAdapter.js index c995705c957..764ea293417 100644 --- a/modules/vubleBidAdapter.js +++ b/modules/vubleBidAdapter.js @@ -102,7 +102,8 @@ export const spec = { creativeId: responseBody.creativeId, netRevenue: true, currency: CURRENCIES[bid.data.env], - vastUrl: responseBody.url + vastUrl: responseBody.url, + mediaType: 'video' }; responses.push(reponse); diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 3ecbd533c5f..4f37d1096fc 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -202,7 +202,8 @@ describe('VubleAdapter', () => { creativeId: '2468', netRevenue: true, currency: 'USD', - vastUrl: 'https//player.mediabong.net/prebid/ad/a1b2c3d4' + vastUrl: 'https//player.mediabong.net/prebid/ad/a1b2c3d4', + mediaType: 'video' }; it('should equal to the expected formatted result', () => { From 3b26c3a0a9da7c4e0bc6d789f8e5c4675439a61b Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 13 Mar 2018 11:23:40 -0700 Subject: [PATCH 0183/1594] Add billing url (burl) support (#2246) --- modules/prebidServerBidAdapter.js | 3 +++ src/prebid.js | 2 ++ src/utils.js | 8 +++++++- test/spec/unit/pbjs_api_spec.js | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 7df557971bd..4999c716c98 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -376,6 +376,8 @@ const LEGACY_PROTOCOL = { bidObject.currency = (bidObj.currency) ? bidObj.currency : DEFAULT_S2S_CURRENCY; bidObject.netRevenue = (bidObj.netRevenue) ? bidObj.netRevenue : DEFAULT_S2S_NETREVENUE; + if (result.burl) { bidObject.burl = result.burl; } + bids.push({ adUnit: bidObj.code, bid: bidObject }); }); } @@ -505,6 +507,7 @@ const OPEN_RTB_PROTOCOL = { bidObject.requestId = bid.id; bidObject.creative_id = bid.crid; bidObject.creativeId = bid.crid; + if (bid.burl) { bidObject.burl = bid.burl; } // TODO: Remove when prebid-server returns ttl, currency and netRevenue bidObject.ttl = (bid.ttl) ? bid.ttl : DEFAULT_S2S_TTL; diff --git a/src/prebid.js b/src/prebid.js index d6b15def53c..7fdce6c3cf7 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -234,6 +234,7 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { doc.write(ad); doc.close(); setRenderSize(doc, width, height); + utils.callBurl(bid); } else if (adUrl) { const iframe = utils.createInvisibleIframe(); iframe.height = height; @@ -244,6 +245,7 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { utils.insertElement(iframe, doc, 'body'); setRenderSize(doc, width, height); + utils.callBurl(bid); } else { utils.logError('Error trying to write ad. No ad for bid response id: ' + id); } diff --git a/src/utils.js b/src/utils.js index 7126f293c02..3738d0e7d52 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,7 +2,7 @@ import { config } from './config'; import clone from 'just-clone'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -var CONSTANTS = require('./constants'); +const CONSTANTS = require('./constants'); var _loggingChecked = false; @@ -469,6 +469,12 @@ exports.triggerPixel = function (url) { img.src = url; }; +exports.callBurl = function({ source, burl }) { + if (source === CONSTANTS.S2S.SRC && burl) { + exports.triggerPixel(burl); + } +}; + /** * Inserts empty iframe with the specified `url` for cookie sync * @param {string} url URL to be requested diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index f772802f21f..92b5d7b5a9f 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -680,6 +680,7 @@ describe('Unit: Prebid Module', function () { var spyLogError = null; var spyLogMessage = null; var inIframe = true; + let triggerPixelStub; function pushBidResponseToAuction(obj) { adResponse = Object.assign({ @@ -719,6 +720,7 @@ describe('Unit: Prebid Module', function () { inIframe = true; sinon.stub(utils, 'inIframe').callsFake(() => inIframe); + triggerPixelStub = sinon.stub(utils, 'triggerPixel'); }); afterEach(function () { @@ -726,6 +728,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); utils.logMessage.restore(); utils.inIframe.restore(); + utils.triggerPixel.restore(); }); it('should require doc and id params', function () { @@ -810,6 +813,20 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.renderAd(doc, bidId); assert.deepEqual($$PREBID_GLOBAL$$.getAllWinningBids()[0], adResponse); }); + + it('fires billing url if present on s2s bid', () => { + const burl = 'http://www.example.com/burl'; + pushBidResponseToAuction({ + ad: '
ad
', + source: 's2s', + burl + }); + + $$PREBID_GLOBAL$$.renderAd(doc, bidId); + + sinon.assert.calledOnce(triggerPixelStub); + sinon.assert.calledWith(triggerPixelStub, burl); + }); }); describe('requestBids', () => { From 6ddbfd0b8e8b1bffa7523fb60864b9e2840a1a80 Mon Sep 17 00:00:00 2001 From: Adilet Date: Wed, 14 Mar 2018 00:25:15 +0600 Subject: [PATCH 0184/1594] Added ad id to a4g bid (#2250) * Added ad id to bid * Update a4gBidAdapter_spec.js * Update a4gBidAdapter.js --- modules/a4gBidAdapter.js | 3 ++- test/spec/modules/a4gBidAdapter_spec.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/a4gBidAdapter.js b/modules/a4gBidAdapter.js index ead425c4a47..222dfaa7ce7 100644 --- a/modules/a4gBidAdapter.js +++ b/modules/a4gBidAdapter.js @@ -71,7 +71,8 @@ export const spec = { currency: A4G_CURRENCY, netRevenue: true, ttl: A4G_TTL, - ad: response.ad + ad: response.ad, + adId: response.id }; bidResponses.push(bidResponse); }); diff --git a/test/spec/modules/a4gBidAdapter_spec.js b/test/spec/modules/a4gBidAdapter_spec.js index 60016fbfb9e..861ab5c2281 100644 --- a/test/spec/modules/a4gBidAdapter_spec.js +++ b/test/spec/modules/a4gBidAdapter_spec.js @@ -113,6 +113,7 @@ describe('a4gAdapterTests', () => { 'width', 'height', 'ad', + 'adId', 'ttl', 'creativeId', 'netRevenue', From cd050b624ada521201073b094dfc98415ca00560 Mon Sep 17 00:00:00 2001 From: Jim Naumann Date: Tue, 13 Mar 2018 14:34:53 -0400 Subject: [PATCH 0185/1594] vastUrl is set based on nurl for video. (#2249) --- modules/prebidServerBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 4999c716c98..80157f32344 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -490,6 +490,7 @@ const OPEN_RTB_PROTOCOL = { if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { bidObject.mediaType = VIDEO; if (bid.adm) { bidObject.vastXml = bid.adm; } + if (bid.nurl) { bidObject.vastUrl = bid.nurl; } } else { // banner if (bid.adm && bid.nurl) { bidObject.ad = bid.adm; From 4fee47db07863eed133c3f15bb7929ead507f2b5 Mon Sep 17 00:00:00 2001 From: Adilet Date: Wed, 14 Mar 2018 23:55:15 +0600 Subject: [PATCH 0186/1594] Updated adUnitCode (#2262) --- modules/a4gBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/a4gBidAdapter.js b/modules/a4gBidAdapter.js index 222dfaa7ce7..e93a08e5571 100644 --- a/modules/a4gBidAdapter.js +++ b/modules/a4gBidAdapter.js @@ -36,7 +36,7 @@ export const spec = { if (!bidId) { bidId = bid.bidId; } - idParams.push(bid.placementCode); + idParams.push(bid.adUnitCode); sizeParams.push(bid.sizes.map(size => size.join(SIZE_SEPARATOR)).join(ARRAY_SIZE_SEPARATOR)); zoneIds.push(bid.params.zoneId); }); From 5ed5dcdb548b2ae2fc5ae4097cde93af76949142 Mon Sep 17 00:00:00 2001 From: Miller Date: Thu, 15 Mar 2018 15:30:30 +0200 Subject: [PATCH 0187/1594] update params for test bid (#2267) * update test bid params --- modules/vertamediaBidAdapter.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/vertamediaBidAdapter.md b/modules/vertamediaBidAdapter.md index 2f6faf5c840..6b1265fa792 100644 --- a/modules/vertamediaBidAdapter.md +++ b/modules/vertamediaBidAdapter.md @@ -28,7 +28,7 @@ This adapter provides a solution for accessing Video demand and display demand bids: [{ bidder: 'vertamedia', params: { - aid: 332842 + aid: 331133 } }] }, @@ -45,7 +45,7 @@ This adapter provides a solution for accessing Video demand and display demand bids: [{ bidder: 'vertamedia', params: { - aid: 332842 + aid: 331133 } }] }, @@ -57,7 +57,7 @@ This adapter provides a solution for accessing Video demand and display demand bids: [{ bidder: 'vertamedia', params: { - aid: 324758 + aid: 350975 } }] } From 2f6076eac1dd2a566a22e774eca152baf6ea617f Mon Sep 17 00:00:00 2001 From: gammassp <35954362+gammassp@users.noreply.github.com> Date: Thu, 15 Mar 2018 22:52:48 +0700 Subject: [PATCH 0188/1594] Add vastUrl for Gamma Adapter Video (#2261) * commit gamma adapter * Fixed The Travis CI build failed * fix interpretResponse return empty when server response empty * removed mediaType removed mediaType in bid and return vastXml property if video request * fixed Travis CI build * Travis CI build * add gamma spec * fixed Travis CI build * fix spec * fix spec * Add files via upload * Add files via upload * fix spec * fix Travis CI build * move to module * remove gaxDomain param and move to adapter * remove check isBidRequestValid for gaxDomain * remove gaxDomain param * remove gaxDomain param * remove gaxDomain param * Delete gammaBidAdapter_spec.js * add usersync endpoid * add usersync * add vastUrl * add supportedMediaTypes to bidder spec * add Test Parameters: For Video --- modules/gammaBidAdapter.js | 2 ++ modules/gammaBidAdapter.md | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/modules/gammaBidAdapter.js b/modules/gammaBidAdapter.js index 516f716fa76..1fba73fd6ab 100644 --- a/modules/gammaBidAdapter.js +++ b/modules/gammaBidAdapter.js @@ -8,6 +8,7 @@ const BIDDER_CODE = 'gamma'; export const spec = { code: BIDDER_CODE, aliases: ['gamma'], + supportedMediaTypes: ['banner', 'video'], /** * Determines whether or not the given bid request is valid. @@ -85,6 +86,7 @@ function newBid(serverBid) { if (serverBid.type == 'video') { Object.assign(bid, { vastXml: serverBid.seatbid[0].bid[0].vastXml, + vastUrl: serverBid.seatbid[0].bid[0].vastUrl, ttl: 3600 }); } diff --git a/modules/gammaBidAdapter.md b/modules/gammaBidAdapter.md index 83c1fdf4853..2902be78492 100644 --- a/modules/gammaBidAdapter.md +++ b/modules/gammaBidAdapter.md @@ -12,7 +12,7 @@ Connects to Gamma exchange for bids. Gamma bid adapter supports Banner, Video. -# Test Parameters +# Test Parameters: For Banner ``` var adUnits = [{ code: 'gamma-hb-ad-123456-0', @@ -29,6 +29,23 @@ var adUnits = [{ }]; ``` +# Test Parameters: For Video +``` +var adUnits = [{ + code: 'gamma-hb-ad-78910-0', + sizes: [[640, 480]], + + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'gamma', + params: { + siteId: '1465446377', + zoneId: '1493280341' + } + }] + + }]; +``` # Ad Unit and Setup: For Testing In order to receive bids please map localhost to (any) test domain. From 717b4391d641f14c3875620b06f3e1a8a4e827fb Mon Sep 17 00:00:00 2001 From: matimar <36712443+matimar@users.noreply.github.com> Date: Thu, 15 Mar 2018 14:29:45 -0300 Subject: [PATCH 0189/1594] Add e-planning analytics adapter (#2211) * Add e-planning analytics adapter * fix irregular spacing in braces * Added new ci config option * Fix linting --- modules/eplanningAnalyticsAdapter.js | 131 ++++++++++++++ modules/eplanningAnalyticsAdapter.md | 23 +++ .../modules/eplanningAnalyticsAdapter_spec.js | 162 ++++++++++++++++++ 3 files changed, 316 insertions(+) create mode 100644 modules/eplanningAnalyticsAdapter.js create mode 100644 modules/eplanningAnalyticsAdapter.md create mode 100644 test/spec/modules/eplanningAnalyticsAdapter_spec.js diff --git a/modules/eplanningAnalyticsAdapter.js b/modules/eplanningAnalyticsAdapter.js new file mode 100644 index 00000000000..2fe26488ebe --- /dev/null +++ b/modules/eplanningAnalyticsAdapter.js @@ -0,0 +1,131 @@ +import {ajax} from 'src/ajax'; +import adapter from 'src/AnalyticsAdapter'; +import adaptermanager from 'src/adaptermanager'; +import * as utils from 'src/utils'; + +const CONSTANTS = require('src/constants.json'); + +const analyticsType = 'endpoint'; +const EPL_HOST = 'https://ads.us.e-planning.net/hba/1/'; + +function auctionEndHandler(args) { + return {auctionId: args.auctionId}; +} + +function auctionInitHandler(args) { + return { + auctionId: args.auctionId, + time: args.timestamp + }; +} + +function bidRequestedHandler(args) { + return { + auctionId: args.auctionId, + time: args.start, + bidder: args.bidderCode, + bids: args.bids.map(function(bid) { + return { + time: bid.startTime, + bidder: bid.bidder, + placementCode: bid.placementCode, + auctionId: bid.auctionId, + sizes: bid.sizes + }; + }), + }; +} + +function bidResponseHandler(args) { + return { + bidder: args.bidder, + size: args.size, + auctionId: args.auctionId, + cpm: args.cpm, + time: args.responseTimestamp, + }; +} + +function bidWonHandler(args) { + return { + auctionId: args.auctionId, + size: args.width + 'x' + args.height, + }; +} + +function bidTimeoutHandler(args) { + return args.map(function(bid) { + return { + bidder: bid.bidder, + auctionId: bid.auctionId + }; + }) +} + +function callHandler(evtype, args) { + let handler = null; + + if (evtype === CONSTANTS.EVENTS.AUCTION_INIT) { + handler = auctionInitHandler; + eplAnalyticsAdapter.context.events = []; + } else if (evtype === CONSTANTS.EVENTS.AUCTION_END) { + handler = auctionEndHandler; + } else if (evtype === CONSTANTS.EVENTS.BID_REQUESTED) { + handler = bidRequestedHandler; + } else if (evtype === CONSTANTS.EVENTS.BID_RESPONSE) { + handler = bidResponseHandler + } else if (evtype === CONSTANTS.EVENTS.BID_TIMEOUT) { + handler = bidTimeoutHandler; + } else if (evtype === CONSTANTS.EVENTS.BID_WON) { + handler = bidWonHandler; + } + + if (handler) { + eplAnalyticsAdapter.context.events.push({ec: evtype, p: handler(args)}); + } +} + +var eplAnalyticsAdapter = Object.assign(adapter( + { + EPL_HOST, + analyticsType + }), +{ + track({eventType, args}) { + if (typeof args !== 'undefined') { + callHandler(eventType, args); + } + + if (eventType === CONSTANTS.EVENTS.AUCTION_END) { + try { + let strjson = JSON.stringify(eplAnalyticsAdapter.context.events); + ajax(eplAnalyticsAdapter.context.host + eplAnalyticsAdapter.context.ci + '?d=' + encodeURIComponent(strjson)); + } catch (err) {} + } + } +} +); + +eplAnalyticsAdapter.originEnableAnalytics = eplAnalyticsAdapter.enableAnalytics; + +eplAnalyticsAdapter.enableAnalytics = function (config) { + if (!config.options.ci) { + utils.logError('Client ID (ci) option is not defined. Analytics won\'t work'); + return; + } + + eplAnalyticsAdapter.context = { + events: [], + host: config.options.host || EPL_HOST, + ci: config.options.ci + }; + + eplAnalyticsAdapter.originEnableAnalytics(config); +}; + +adaptermanager.registerAnalyticsAdapter({ + adapter: eplAnalyticsAdapter, + code: 'eplanning' +}); + +export default eplAnalyticsAdapter; diff --git a/modules/eplanningAnalyticsAdapter.md b/modules/eplanningAnalyticsAdapter.md new file mode 100644 index 00000000000..3127b523be0 --- /dev/null +++ b/modules/eplanningAnalyticsAdapter.md @@ -0,0 +1,23 @@ +# Overview + +``` +Module Name: E-Planning Analytics Adapter +Module Type: Analytics Adapter +Maintainer: mmartinho@e-planning.net +``` + +# Description + +Analytics adapter for E-Planning. + +# Test Parameters + +``` +{ + provider: 'eplanning', + options : { + host: 'https://ads.us.e-planning.net/hba/1/', // Host (optional) + ci: "123456" // Client ID (required) + } +} +``` diff --git a/test/spec/modules/eplanningAnalyticsAdapter_spec.js b/test/spec/modules/eplanningAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..04a7d65e12a --- /dev/null +++ b/test/spec/modules/eplanningAnalyticsAdapter_spec.js @@ -0,0 +1,162 @@ +import eplAnalyticsAdapter from 'modules/eplanningAnalyticsAdapter'; +import { expect } from 'chai'; +let adaptermanager = require('src/adaptermanager'); +let events = require('src/events'); +let constants = require('src/constants.json'); + +describe('eplanning analytics adapter', () => { + let xhr; + let requests; + + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => { requests.push(request) }; + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(() => { + xhr.restore(); + events.getEvents.restore(); + }); + + describe('track', () => { + it('builds and sends auction data', () => { + sinon.spy(eplAnalyticsAdapter, 'track'); + + let auctionTimestamp = 1496510254313; + let pauctionId = '5018eb39-f900-4370-b71e-3bb5b48d324f'; + let initOptions = { + host: 'https://ads.ar.e-planning.net/hba/1/', + ci: '12345' + }; + let pbidderCode = 'adapter'; + + const bidRequest = { + bidderCode: pbidderCode, + auctionId: pauctionId, + bidderRequestId: '1a6fc81528d0f6', + bids: [{ + bidder: pbidderCode, + placementCode: 'container-1', + bidId: '208750227436c1', + bidderRequestId: '1a6fc81528d0f6', + auctionId: pauctionId, + startTime: 1509369418389, + sizes: [[300, 250]], + }], + auctionStart: 1509369418387, + timeout: 3000, + start: 1509369418389 + }; + + const bidResponse = { + bidderCode: pbidderCode, + adId: '208750227436c1', + cpm: 0.015, + auctionId: pauctionId, + responseTimestamp: 1509369418832, + requestTimestamp: 1509369418389, + bidder: pbidderCode, + timeToRespond: 443, + size: '300x250', + width: 300, + height: 250, + }; + + let bidTimeout = [ + { + bidId: '208750227436c1', + bidder: pbidderCode, + auctionId: pauctionId + } + ]; + + adaptermanager.registerAnalyticsAdapter({ + code: 'eplanning', + adapter: eplAnalyticsAdapter + }); + + adaptermanager.enableAnalytics({ + provider: 'eplanning', + options: initOptions + }); + + // Emit the events with the "real" arguments + + // Step 1: Send auction init event + events.emit(constants.EVENTS.AUCTION_INIT, { + auctionId: pauctionId, + timestamp: auctionTimestamp + }); + + // Step 2: Send bid requested event + events.emit(constants.EVENTS.BID_REQUESTED, bidRequest); + + // Step 3: Send bid response event + events.emit(constants.EVENTS.BID_RESPONSE, bidResponse); + + // Step 4: Send bid time out event + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeout); + + // Step 5: Send auction bid won event + events.emit(constants.EVENTS.BID_WON, { + adId: 'adIdData', + ad: 'adContent', + auctionId: pauctionId, + width: 300, + height: 250 + }); + + // Step 6: Send auction end event + events.emit(constants.EVENTS.AUCTION_END, {auctionId: pauctionId}); + + // Step 7: Find the request data sent (filtering other hosts) + requests = requests.filter(req => req.url.includes(initOptions.host)); + + expect(requests.length).to.equal(1); + + expect(requests[0].url.includes(initOptions.host + initOptions.ci)); + expect(requests[0].url.includes('https://ads.ar.e-planning.net/hba/1/12345?d=')); + + let info = requests[0].url; + let purl = new URL(info); + let eplData = JSON.parse(decodeURIComponent(purl.searchParams.get('d'))); + + // Step 8 check that 6 events were sent + expect(eplData.length).to.equal(6); + + // Step 9 verify that we only receive the parameters we need + let expectedEventValues = [ + // AUCTION INIT + {ec: constants.EVENTS.AUCTION_INIT, + p: {auctionId: pauctionId, time: auctionTimestamp}}, + // BID REQ + {ec: constants.EVENTS.BID_REQUESTED, + p: {auctionId: pauctionId, time: 1509369418389, bidder: pbidderCode, bids: [{time: 1509369418389, sizes: [[300, 250]], bidder: pbidderCode, placementCode: 'container-1', auctionId: pauctionId}]}}, + // BID RESP + {ec: constants.EVENTS.BID_RESPONSE, + p: {auctionId: pauctionId, bidder: pbidderCode, cpm: 0.015, size: '300x250', time: 1509369418832}}, + // BID T.O. + {ec: constants.EVENTS.BID_TIMEOUT, + p: [{auctionId: pauctionId, bidder: pbidderCode}]}, + // BID WON + {ec: constants.EVENTS.BID_WON, + p: {auctionId: pauctionId, size: '300x250'}}, + // AUCTION END + {ec: constants.EVENTS.AUCTION_END, + p: {auctionId: pauctionId}} + ]; + + for (let evid = 0; evid < eplData.length; evid++) { + expect(eplData[evid]).to.deep.equal(expectedEventValues[evid]); + } + + // Step 10 check that the host to send the ajax request is configurable via options + expect(eplAnalyticsAdapter.context.host).to.equal(initOptions.host); + + // Step 11 verify that we received 6 events + sinon.assert.callCount(eplAnalyticsAdapter.track, 6); + }); + }); +}); From 7d10bc7d258d83d0681d064658dd2cdc2864a97d Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Sat, 17 Mar 2018 00:12:30 +0000 Subject: [PATCH 0190/1594] Audience Network: Add 'pbv' and 'cb' query params (#2252) * 'pbv' is for the Prebid version to aid with debugging * 'cb' is for a Safari-only cachebuster --- modules/audienceNetworkBidAdapter.js | 9 ++++-- .../modules/audienceNetworkBidAdapter_spec.js | 29 ++++++++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index ed78f336102..263edba878a 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -4,7 +4,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; import { formatQS } from 'src/url'; -import { getTopWindowUrl } from 'src/utils'; +import { generateUUID, getTopWindowUrl, isSafariBrowser } from 'src/utils'; import findIndex from 'core-js/library/fn/array/find-index'; import includes from 'core-js/library/fn/array/includes'; @@ -15,6 +15,7 @@ const url = 'https://an.facebook.com/v2/placementbid.json'; const supportedMediaTypes = ['banner', 'video']; const netRevenue = true; const hb_bidder = 'fan'; +const pbv = '$prebid.version$'; /** * Does this bid request contain valid parameters? @@ -164,12 +165,16 @@ const buildRequests = bids => { adformats, testmode, pageurl, - sdk + sdk, + pbv }; const video = findIndex(adformats, isVideo); if (video !== -1) { [search.playerwidth, search.playerheight] = expandSize(sizes[video]); } + if (isSafariBrowser()) { + search.cb = generateUUID(); + } const data = formatQS(search); return [{ adformats, data, method, requestIds, sizes, url }]; diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index d92597c913c..7626780afb3 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -18,6 +18,7 @@ const placementId = 'test-placement-id'; const playerwidth = 320; const playerheight = 180; const requestId = 'test-request-id'; +const pbv = '$prebid.version$'; describe('AudienceNetwork adapter', () => { describe('Public API', () => { @@ -128,7 +129,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: 'placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=&sdk[]=5.5.web' + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` }]); }); @@ -147,7 +148,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['640x480'], url: 'https://an.facebook.com/v2/placementbid.json', - data: 'placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=&sdk[]=&playerwidth=640&playerheight=480' + data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=&sdk[]=&pbv=${pbv}&playerwidth=640&playerheight=480` }]); }); @@ -166,7 +167,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['728x90'], url: 'https://an.facebook.com/v2/placementbid.json', - data: 'placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=&sdk[]=5.5.web' + data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` }]); }); @@ -185,9 +186,29 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: 'placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=&sdk[]=5.5.web' + data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` }]); }); + + it('can build URL on Safari that includes a cachebuster param', () => { + const { userAgent } = navigator; + Object.defineProperty(navigator, 'userAgent', { + value: 'safari', + writable: true + }); + + expect(buildRequests([{ + bidder, + bidId: requestId, + sizes: [[300, 250]], + params: { placementId } + }])[0].data).to.contain('&cb='); + + Object.defineProperty(navigator, 'userAgent', { + value: userAgent, + writable: false + }); + }); }); describe('interpretResponse', () => { From 1c862a8299928fc6c8bfd5aeb5be060f385d202b Mon Sep 17 00:00:00 2001 From: Adilet Date: Mon, 19 Mar 2018 18:11:20 +0600 Subject: [PATCH 0191/1594] Updated Bid params (#2275) * Updated Bid params * Added keys to tests --- modules/a4gBidAdapter.js | 36 +++++++++++-------------- test/spec/modules/a4gBidAdapter_spec.js | 10 +++---- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/modules/a4gBidAdapter.js b/modules/a4gBidAdapter.js index e93a08e5571..f961db718c7 100644 --- a/modules/a4gBidAdapter.js +++ b/modules/a4gBidAdapter.js @@ -24,7 +24,6 @@ export const spec = { buildRequests: function(validBidRequests) { let deliveryUrl = ''; - let bidId = ''; const idParams = []; const sizeParams = []; const zoneIds = []; @@ -33,10 +32,7 @@ export const spec = { if (!deliveryUrl && typeof bid.params.deliveryUrl === 'string') { deliveryUrl = bid.params.deliveryUrl; } - if (!bidId) { - bidId = bid.bidId; - } - idParams.push(bid.adUnitCode); + idParams.push(bid.bidId); sizeParams.push(bid.sizes.map(size => size.join(SIZE_SEPARATOR)).join(ARRAY_SIZE_SEPARATOR)); zoneIds.push(bid.params.zoneId); }); @@ -48,7 +44,6 @@ export const spec = { return { method: 'GET', url: deliveryUrl, - bidId: bidId, data: { [IFRAME_PARAM_NAME]: 0, [LOCATION_PARAM_NAME]: utils.getTopWindowUrl(), @@ -62,21 +57,22 @@ export const spec = { interpretResponse: function(serverResponses, request) { const bidResponses = []; utils._each(serverResponses.body, function(response) { - const bidResponse = { - requestId: request.bidId, - cpm: response.cpm, - width: response.width, - height: response.height, - creativeId: response.zoneid, - currency: A4G_CURRENCY, - netRevenue: true, - ttl: A4G_TTL, - ad: response.ad, - adId: response.id - }; - bidResponses.push(bidResponse); + if (response.cpm > 0) { + const bidResponse = { + requestId: response.id, + creativeId: response.id, + adId: response.id, + cpm: response.cpm, + width: response.width, + height: response.height, + currency: A4G_CURRENCY, + netRevenue: true, + ttl: A4G_TTL, + ad: response.ad + }; + bidResponses.push(bidResponse); + } }); - return bidResponses; } }; diff --git a/test/spec/modules/a4gBidAdapter_spec.js b/test/spec/modules/a4gBidAdapter_spec.js index 861ab5c2281..30fcb2f8497 100644 --- a/test/spec/modules/a4gBidAdapter_spec.js +++ b/test/spec/modules/a4gBidAdapter_spec.js @@ -109,15 +109,15 @@ describe('a4gAdapterTests', () => { let requiredKeys = [ 'requestId', + 'creativeId', + 'adId', 'cpm', 'width', 'height', - 'ad', - 'adId', - 'ttl', - 'creativeId', + 'currency', 'netRevenue', - 'currency' + 'ttl', + 'ad' ]; let resultKeys = Object.keys(result[0]); From 3e7df0de9b23a33953c9f4632a487433cb43139d Mon Sep 17 00:00:00 2001 From: John Ellis Date: Mon, 19 Mar 2018 10:17:51 -0400 Subject: [PATCH 0192/1594] Yieldbot impression image creation fix (#2277) --- modules/yieldbotBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/yieldbotBidAdapter.js b/modules/yieldbotBidAdapter.js index bf21613e31f..43d94220907 100644 --- a/modules/yieldbotBidAdapter.js +++ b/modules/yieldbotBidAdapter.js @@ -369,7 +369,7 @@ export const YieldbotAdapter = { const adUrl = this.buildAdUrl(urlPrefix, publisherNumber, commonSearchParams, bid); const impressionUrl = this.buildImpressionUrl(urlPrefix, publisherNumber, commonSearchParams); - const htmlMarkup = `
`; + const htmlMarkup = `
`; return { ad: htmlMarkup, creativeId: ybotAdRequestId }; }, From 292b5543ec1a84db497982fab1f1188ad2a6a9da Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Mon, 19 Mar 2018 19:54:44 +0530 Subject: [PATCH 0193/1594] message formatting (#2285) --- src/userSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/userSync.js b/src/userSync.js index 56641b5cb8e..059d3ea62c1 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -146,7 +146,7 @@ export function newUserSync(userSyncDependencies) { return utils.logWarn(`Bidder is required for registering sync`); } if (Number(numAdapterBids[bidder]) >= usConfig.syncsPerBidder) { - return utils.logWarn(`Number of user syncs exceeded for "{$bidder}"`); + return utils.logWarn(`Number of user syncs exceeded for "${bidder}"`); } // All bidders are enabled by default. If specified only register for enabled bidders. let hasEnabledBidders = usConfig.enabledBidders && usConfig.enabledBidders.length; From 6aa8c1865d252ef2bcfaa0c8e9f494a7cf0599ba Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Mon, 19 Mar 2018 09:19:48 -0700 Subject: [PATCH 0194/1594] Update to Rubicon Adapter for mediaTypes support (#2272) * Added support for mediaTypes bid requests * Fixed linting errors * Replaced missing test for ad position --- modules/rubiconBidAdapter.js | 32 ++- test/spec/modules/rubiconBidAdapter_spec.js | 243 +++++++++++++++++++- 2 files changed, 252 insertions(+), 23 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 625d34b0648..b60755f2421 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; +import { BANNER, VIDEO } from 'src/mediaTypes'; const INTEGRATION = 'pbjs_lite_v$prebid.version$'; @@ -73,7 +74,7 @@ utils._each(sizeMap, (item, key) => sizeMap[item] = key); export const spec = { code: 'rubicon', aliases: ['rubiconLite'], - supportedMediaTypes: ['banner', 'video'], + supportedMediaTypes: [BANNER, VIDEO], /** * @param {object} bid * @return boolean @@ -93,8 +94,9 @@ export const spec = { return false; } - if (bid.mediaType === 'video') { - if (typeof params.video !== 'object' || !params.video.size_id) { + if (spec.hasVideoMediaType(bid)) { + // support instream only + if ((utils.deepAccess(bid, `mediaTypes.${VIDEO}`) && utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) !== 'instream') || typeof params.video !== 'object' || !params.video.size_id) { return false; } } @@ -118,7 +120,7 @@ export const spec = { page_url = bidRequest.params.secure ? page_url.replace(/^http:/i, 'https:') : page_url; - if (bidRequest.mediaType === 'video') { + if (spec.hasVideoMediaType(bidRequest)) { let params = bidRequest.params; let size = parseSizes(bidRequest); @@ -237,6 +239,15 @@ export const spec = { }; }); }, + /** + * Test if bid has mediaType or mediaTypes set for video. + * note: 'mediaType' has been deprecated, however support will remain for a transitional period + * @param {BidRequest} bidRequest + * @returns {boolean} + */ + hasVideoMediaType: function(bidRequest) { + return bidRequest.mediaType === VIDEO || typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'; + }, /** * @param {*} responseObj * @param {BidRequest} bidRequest @@ -252,7 +263,7 @@ export const spec = { } // video ads array is wrapped in an object - if (typeof bidRequest === 'object' && bidRequest.mediaType === 'video' && typeof ads === 'object') { + if (typeof bidRequest === 'object' && spec.hasVideoMediaType(bidRequest) && typeof ads === 'object') { ads = ads[bidRequest.adUnitCode]; } @@ -287,7 +298,7 @@ export const spec = { bid.mediaType = ad.creative_type; } - if (bidRequest.mediaType === 'video') { + if (ad.creative_type === VIDEO) { bid.width = bidRequest.params.video.playerWidth; bid.height = bidRequest.params.video.playerHeight; bid.vastUrl = ad.creative_depot_url; @@ -360,17 +371,14 @@ function _renderCreative(script, impId) { function parseSizes(bid) { let params = bid.params; - if (bid.mediaType === 'video') { + if (spec.hasVideoMediaType(bid)) { let size = []; - if (params.video.playerWidth && params.video.playerHeight) { + if (typeof params.video === 'object' && params.video.playerWidth && params.video.playerHeight) { size = [ params.video.playerWidth, params.video.playerHeight ]; - } else if ( - Array.isArray(bid.sizes) && bid.sizes.length > 0 && - Array.isArray(bid.sizes[0]) && bid.sizes[0].length > 1 - ) { + } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0 && Array.isArray(bid.sizes[0]) && bid.sizes[0].length > 1) { size = bid.sizes[0]; } return size; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 1c4bccc69c5..107f8d3ea2c 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -17,6 +17,31 @@ describe('the rubicon adapter', () => { function createVideoBidderRequest() { let bid = bidderRequest.bids[0]; + + bid.mediaTypes = { + video: { + context: 'instream' + } + }; + + bid.params.video = { + 'language': 'en', + 'p_aso.video.ext.skip': true, + 'p_aso.video.ext.skipdelay': 15, + 'playerHeight': 320, + 'playerWidth': 640, + 'size_id': 201, + 'aeParams': { + 'p_aso.video.ext.skip': '1', + 'p_aso.video.ext.skipdelay': '15' + } + }; + } + + function createLegacyVideoBidderRequest() { + let bid = bidderRequest.bids[0]; + + // Legacy property (Prebid <1.0) bid.mediaType = 'video'; bid.params.video = { 'language': 'en', @@ -33,12 +58,62 @@ describe('the rubicon adapter', () => { } function createVideoBidderRequestNoVideo() { + let bid = bidderRequest.bids[0]; + bid.mediaTypes = { + video: { + context: 'instream' + }, + }; + bid.params.video = ''; + } + + function createLegacyVideoBidderRequestNoVideo() { let bid = bidderRequest.bids[0]; bid.mediaType = 'video'; bid.params.video = ''; } + function createVideoBidderRequestOutstream() { + let bid = bidderRequest.bids[0]; + bid.mediaTypes = { + video: { + context: 'outstream' + }, + }; + bid.params.video = { + 'language': 'en', + 'p_aso.video.ext.skip': true, + 'p_aso.video.ext.skipdelay': 15, + 'playerHeight': 320, + 'playerWidth': 640, + 'size_id': 201, + 'aeParams': { + 'p_aso.video.ext.skip': '1', + 'p_aso.video.ext.skipdelay': '15' + } + }; + } + function createVideoBidderRequestNoPlayer() { + let bid = bidderRequest.bids[0]; + bid.mediaTypes = { + video: { + context: 'instream' + }, + }; + bid.params.video = { + 'language': 'en', + 'p_aso.video.ext.skip': true, + 'p_aso.video.ext.skipdelay': 15, + 'size_id': 201, + 'aeParams': { + 'p_aso.video.ext.skip': '1', + 'p_aso.video.ext.skipdelay': '15' + } + }; + } + + function createLegacyVideoBidderRequestNoPlayer() { let bid = bidderRequest.bids[0]; bid.mediaType = 'video'; bid.params.video = { @@ -81,6 +156,7 @@ describe('the rubicon adapter', () => { referrer: 'localhost' }, adUnitCode: '/19968336/header-bid-tag-0', + code: 'div-1', sizes: [[300, 250], [320, 50]], bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', @@ -120,8 +196,7 @@ describe('the rubicon adapter', () => { describe('for requests', () => { describe('to fastlane', () => { it('should make a well-formed request objects', () => { - sandbox.stub(Math, 'random').returns(0.1); - + sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -451,6 +526,67 @@ describe('the rubicon adapter', () => { }); describe('for video requests', () => { + it('should make a well-formed video request with legacy mediaType config', () => { + createLegacyVideoBidderRequest(); + + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let post = request.data; + + let url = request.url; + + expect(url).to.equal('//fastlane-adv.rubiconproject.com/v1/auction/video'); + + expect(post).to.have.property('page_url').that.is.a('string'); + expect(post.resolution).to.match(/\d+x\d+/); + expect(post.account_id).to.equal('14062'); + expect(post.integration).to.equal(INTEGRATION); + expect(post['x_source.tid']).to.equal('d45dd707-a418-42ec-b8a7-b70a6c6fab0b'); + expect(post).to.have.property('timeout').that.is.a('number'); + expect(post.timeout < 5000).to.equal(true); + expect(post.stash_creatives).to.equal(true); + + expect(post).to.have.property('ae_pass_through_parameters'); + expect(post.ae_pass_through_parameters) + .to.have.property('p_aso.video.ext.skip') + .that.equals('1'); + expect(post.ae_pass_through_parameters) + .to.have.property('p_aso.video.ext.skipdelay') + .that.equals('15'); + + expect(post).to.have.property('slots') + .with.length.of(1); + + let slot = post.slots[0]; + + expect(slot.site_id).to.equal('70608'); + expect(slot.zone_id).to.equal('335918'); + expect(slot.position).to.equal('atf'); + expect(slot.floor).to.equal(0.01); + expect(slot.element_id).to.equal(bidderRequest.bids[0].adUnitCode); + expect(slot.name).to.equal(bidderRequest.bids[0].adUnitCode); + expect(slot.language).to.equal('en'); + expect(slot.width).to.equal(640); + expect(slot.height).to.equal(320); + expect(slot.size_id).to.equal(201); + + expect(slot).to.have.property('inventory').that.is.an('object'); + expect(slot.inventory).to.have.property('rating').that.equals('5-star'); + expect(slot.inventory).to.have.property('prodtype').that.equals('tech'); + + expect(slot).to.have.property('keywords') + .that.is.an('array') + .of.length(3) + .that.deep.equals(['a', 'b', 'c']); + + expect(slot).to.have.property('visitor').that.is.an('object'); + expect(slot.visitor).to.have.property('ucat').that.equals('new'); + expect(slot.visitor).to.have.property('lastsearch').that.equals('iphone'); + }); + it('should make a well-formed video request', () => { createVideoBidderRequest(); @@ -576,17 +712,60 @@ describe('the rubicon adapter', () => { expect(floor).to.equal(3.25); }); - it('should not validate bid request when no video object is passed in', () => { + it('should not validate bid request when a invalid video object is passed in', () => { createVideoBidderRequestNoVideo(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 ); - var floorBidderRequest = clone(bidderRequest); + const bidRequestCopy = clone(bidderRequest.bids[0]); + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - let result = spec.isBidRequestValid(floorBidderRequest.bids[0]); + bidRequestCopy.params.video = {}; + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - expect(result).to.equal(false); + bidRequestCopy.params.video = undefined; + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); + + bidRequestCopy.params.video = 123; + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); + + bidRequestCopy.params.video = { size_id: '' }; + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); + + delete bidRequestCopy.params.video; + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); + }); + + it('should not validate bid request when an invalid video object is passed in with legacy config mediaType', () => { + createLegacyVideoBidderRequestNoVideo(); + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + + const bidderRequestCopy = clone(bidderRequest); + expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + + bidderRequestCopy.bids[0].params.video = {}; + expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + + bidderRequestCopy.bids[0].params.video = undefined; + expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + + bidderRequestCopy.bids[0].params.video = NaN; + expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + + delete bidderRequestCopy.bids[0].params.video; + expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + }); + + it('should not validate bid request when video is outstream', () => { + createVideoBidderRequestOutstream(); + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); }); it('should get size from bid.sizes too', () => { @@ -595,13 +774,55 @@ describe('the rubicon adapter', () => { bidderRequest.auctionStart + 100 ); - var floorBidderRequest = clone(bidderRequest); + const bidRequestCopy = clone(bidderRequest); - let [request] = spec.buildRequests(floorBidderRequest.bids, floorBidderRequest); - let post = request.data; + let [request] = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); - expect(post.slots[0].width).to.equal(300); - expect(post.slots[0].height).to.equal(250); + expect(request.data.slots[0].width).to.equal(300); + expect(request.data.slots[0].height).to.equal(250); + }); + + it('should get size from bid.sizes too with legacy config mediaType', () => { + createLegacyVideoBidderRequestNoPlayer(); + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + + const bidRequestCopy = clone(bidderRequest); + + let [request] = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); + + expect(request.data.slots[0].width).to.equal(300); + expect(request.data.slots[0].height).to.equal(250); + }); + }); + + describe('hasVideoMediaType', () => { + it('should return true if mediaType is true', () => { + createVideoBidderRequest(); + const legacyVideoTypeBidRequest = spec.hasVideoMediaType(bidderRequest.bids[0]); + expect(legacyVideoTypeBidRequest).is.equal(true); + }); + + it('should return false if bidRequest.mediaType is not equal to video', () => { + expect(spec.hasVideoMediaType({ + mediaType: 'banner' + })).is.equal(false); + }); + + it('should return false if bidRequest.mediaType is not defined', () => { + expect(spec.hasVideoMediaType({})).is.equal(false); + }); + + it('should return true if bidRequest.mediaTypes.video object exists', () => { + expect(spec.hasVideoMediaType({ + mediaTypes: { + video: { + context: 'outstream', + playerSize: [300, 250] + } + } + })).is.equal(true); }); }); }); From b9906c3ccc3984a42868618ff1404bc2e5fb4f1f Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Mon, 19 Mar 2018 23:02:26 +0530 Subject: [PATCH 0195/1594] Update for Media.net adapter (#2232) * Log client-side timeouts * prebid version added in timeout log * removing events.on from adapter * storing cid in global --- modules/medianetBidAdapter.js | 14 +++- test/spec/modules/medianetBidAdapter_spec.js | 78 ++++++++++++++++++-- 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index c0b3fff3c2a..e8a98721e0c 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -1,9 +1,12 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; +import { config } from 'src/config'; const BIDDER_CODE = 'medianet'; const BID_URL = 'https://prebid.media.net/rtb/prebid'; +$$PREBID_GLOBAL$$.medianetGlobals = {}; + function siteDetails(site) { site = site || {}; @@ -35,7 +38,8 @@ function getSize(size) { function configuredParams(params) { return { - customer_id: params.cid + customer_id: params.cid, + prebid_version: $$PREBID_GLOBAL$$.version } } @@ -46,7 +50,8 @@ function slotParams(bidRequest) { ext: { dfp_id: bidRequest.adUnitCode }, - banner: transformSizes(bidRequest.sizes) + banner: transformSizes(bidRequest.sizes), + all: bidRequest.params }; if (bidRequest.params.crid) { @@ -65,7 +70,8 @@ function generatePayload(bidRequests) { site: siteDetails(bidRequests[0].params.site), ext: configuredParams(bidRequests[0].params), id: bidRequests[0].auctionId, - imp: bidRequests.map(request => slotParams(request)) + imp: bidRequests.map(request => slotParams(request)), + tmax: config.getConfig('bidderTimeout') } } @@ -103,6 +109,8 @@ export const spec = { return false; } + Object.assign($$PREBID_GLOBAL$$.medianetGlobals, !$$PREBID_GLOBAL$$.medianetGlobals.cid && {cid: bid.params.cid}); + return true; }, diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index db543eda433..36868e7f993 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -1,5 +1,6 @@ import {expect} from 'chai'; import {spec} from 'modules/medianetBidAdapter'; +import { config } from 'src/config'; let VALID_BID_REQUEST = [{ 'bidder': 'medianet', @@ -68,6 +69,55 @@ let VALID_BID_REQUEST = [{ 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }], + VALID_PAYLOAD_INVALID_BIDFLOOR = { + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + }, + 'ext': { + 'customer_id': 'customer_id', + 'prebid_version': $$PREBID_GLOBAL$$.version + }, + 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'imp': [{ + 'id': '28f8f8130a583e', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-0' + }, + 'banner': [{ + 'w': 300, + 'h': 250 + }], + 'all': { + 'cid': 'customer_id', + 'bidfloor': 'abcdef', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + } + }, { + 'id': '3f97ca71b1e5c2', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-123' + }, + 'banner': [{ + 'w': 300, + 'h': 251 + }], + 'all': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + } + }], + 'tmax': config.getConfig('bidderTimeout') + }, VALID_PAYLOAD = { 'site': { 'page': 'http://media.net/prebidtest', @@ -75,7 +125,8 @@ let VALID_BID_REQUEST = [{ 'ref': 'http://media.net/prebidtest' }, 'ext': { - 'customer_id': 'customer_id' + 'customer_id': 'customer_id', + 'prebid_version': $$PREBID_GLOBAL$$.version }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ @@ -86,7 +137,15 @@ let VALID_BID_REQUEST = [{ 'banner': [{ 'w': 300, 'h': 250 - }] + }], + 'all': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + } }, { 'id': '3f97ca71b1e5c2', 'ext': { @@ -95,8 +154,17 @@ let VALID_BID_REQUEST = [{ 'banner': [{ 'w': 300, 'h': 251 - }] - }] + }], + 'all': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + } + }], + 'tmax': config.getConfig('bidderTimeout') }, VALID_PARAMS = { bidder: 'medianet', @@ -286,7 +354,7 @@ describe('Media.net bid adapter', () => { it('should ignore bidfloor if not a valid number', () => { let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR); - expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD); + expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_INVALID_BIDFLOOR); }); }); From 6382fe6c727cc44d58858ecf98f8f743287be6cf Mon Sep 17 00:00:00 2001 From: Mirko Feddern Date: Mon, 19 Mar 2018 19:45:47 +0100 Subject: [PATCH 0196/1594] Update Yieldlab adapter and add official maintainer (#2231) * Set time to live to 5 minutes Yieldlab auctions are valid for 5 minutes and not 10. A delivery of an adtag would lead to a new auction after the 5 minute expiration time. * Use correct identifer for deals Did stands for demandId which is not a default and not a good identifer for deals. We should use pid (partnershipId) here as a unique identifer for a connection between supply and demand (including deals). * Set revenue to gross-price * Add dynamic adsize for vast url The adsize of a video placement can have a lot of different adsizes and is never "1x1". * Change maintainer to Yieldlab Platform Lunar and Yieldlab agree that the Adapter should be offically maintained by Yieldlab. * Use yieldlab test campaigns Campaigns set up in Yieldlab's test network to deliver all the time. * Use yieldlab naming for params To make it less confusing for customers, we should use the actual naming used in our systems for the params used. * Update test spec for yieldlab adapter * Add test for pid to dealId mapping --- modules/yieldlabBidAdapter.js | 22 +++++++------- modules/yieldlabBidAdapter.md | 22 +++++++------- test/spec/modules/yieldlabBidAdapter_spec.js | 31 ++++++++++---------- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 17c205359de..dde5c70077e 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -5,7 +5,7 @@ import { VIDEO, BANNER } from 'src/mediaTypes' const ENDPOINT = 'https://ad.yieldlab.net' const BIDDER_CODE = 'yieldlab' -const BID_RESPONSE_TTL_SEC = 600 +const BID_RESPONSE_TTL_SEC = 300 const CURRENCY_CODE = 'EUR' export const spec = { @@ -13,7 +13,7 @@ export const spec = { supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { - if (bid && bid.params && bid.params.placementId && bid.params.adSize) { + if (bid && bid.params && bid.params.adslotId && bid.params.adSize) { return true } return false @@ -25,18 +25,18 @@ export const spec = { * @returns {{method: string, url: string}} */ buildRequests: function (validBidRequests) { - const placementIds = [] + const adslotIds = [] const timestamp = Date.now() utils._each(validBidRequests, function (bid) { - placementIds.push(bid.params.placementId) + adslotIds.push(bid.params.adslotId) }) - const placements = placementIds.join(',') + const adslots = adslotIds.join(',') return { method: 'GET', - url: `${ENDPOINT}/yp/${placements}?ts=${timestamp}&json=true`, + url: `${ENDPOINT}/yp/${adslots}?ts=${timestamp}&json=true`, validBidRequests: validBidRequests } }, @@ -56,7 +56,7 @@ export const spec = { } let matchedBid = find(serverResponse.body, function (bidResponse) { - return bidRequest.params.placementId == bidResponse.id + return bidRequest.params.adslotId == bidResponse.id }) if (matchedBid) { @@ -67,16 +67,16 @@ export const spec = { width: sizes[0], height: sizes[1], creativeId: '' + matchedBid.id, - dealId: matchedBid.did, + dealId: matchedBid.pid, currency: CURRENCY_CODE, - netRevenue: true, + netRevenue: false, ttl: BID_RESPONSE_TTL_SEC, referrer: '', - ad: `` + ad: `` } if (isVideo(bidRequest)) { bidResponse.mediaType = VIDEO - bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.accountId}/1x1?ts=${timestamp}` + bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/${sizes[0]}x${sizes[1]}?ts=${timestamp}` } bidResponses.push(bidResponse) diff --git a/modules/yieldlabBidAdapter.md b/modules/yieldlabBidAdapter.md index 0c9183aa4cd..0b11794ac8f 100644 --- a/modules/yieldlabBidAdapter.md +++ b/modules/yieldlabBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Yieldlab Bidder Adapter Module Type: Bidder Adapter -Maintainer: api@platform-lunar.com +Maintainer: solutions@yieldlab.de ``` # Description @@ -14,19 +14,19 @@ Module that connects to Yieldlab's demand sources ``` var adUnits = [ { - code: "test1", - sizes: [[800, 250]] + code: "banner", + sizes: [[728, 90]], bids: [{ bidder: "yieldlab", params: { - placement: "4206978", - accountId: "2358365", - adSize: "800x250" + adslotId: "5220336", + supplyId: "1381604", + adSize: "728x90" } }] }, { - code: "test2", - sizes: [[1, 1]], + code: "video", + sizes: [[640, 480]], mediaTypes: { video: { context: "instream" @@ -35,9 +35,9 @@ Module that connects to Yieldlab's demand sources bids: [{ bidder: "yieldlab", params: { - placementId: "4207034", - accountId: "2358365", - adSize: "1x1" + adslotId: "5220339", + supplyId: "1381604", + adSize: "640x480" } }] } diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index 2a19763b10a..1a5ca59d3a2 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -5,15 +5,15 @@ import { newBidder } from 'src/adapters/bidderFactory' const REQUEST = { 'bidder': 'yieldlab', 'params': { - 'placementId': '1111', - 'accountId': '2222', - 'adSize': '800x250' + 'adslotId': '1111', + 'supplyId': '2222', + 'adSize': '728x90' }, 'bidderRequestId': '143346cf0f1731', 'auctionId': '2e41f65424c87c', 'adUnitCode': 'adunit-code', 'bidId': '2d925f27f5079f', - 'sizes': [1, 1] + 'sizes': [728, 90] } const RESPONSE = { @@ -21,7 +21,8 @@ const RESPONSE = { curl: 'https://www.yieldlab.de', format: 0, id: 1111, - price: 1 + price: 1, + pid: 2222 } describe('yieldlabBidAdapter', () => { @@ -37,9 +38,9 @@ describe('yieldlabBidAdapter', () => { it('should return true when required params found', () => { const request = { 'params': { - 'placementId': '1111', - 'accountId': '2222', - 'adSize': '800x250' + 'adslotId': '1111', + 'supplyId': '2222', + 'adSize': '728x90' } } expect(spec.isBidRequestValid(request)).to.equal(true) @@ -78,15 +79,15 @@ describe('yieldlabBidAdapter', () => { expect(result[0].requestId).to.equal('2d925f27f5079f') expect(result[0].cpm).to.equal(0.01) - expect(result[0].width).to.equal(800) - expect(result[0].height).to.equal(250) + expect(result[0].width).to.equal(728) + expect(result[0].height).to.equal(90) expect(result[0].creativeId).to.equal('1111') - expect(result[0].dealId).to.equal(undefined) + expect(result[0].dealId).to.equal(2222) expect(result[0].currency).to.equal('EUR') - expect(result[0].netRevenue).to.equal(true) - expect(result[0].ttl).to.equal(600) + expect(result[0].netRevenue).to.equal(false) + expect(result[0].ttl).to.equal(300) expect(result[0].referrer).to.equal('') - expect(result[0].ad).to.include('', + tracking_pixels: [] + } + }, + bids = spec.interpretResponse(serverResponse, { + bidRequest: bidRequests[0] + }); + + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(0.1); + 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.have.length.above(1); + }); + + it('should return empty bid response', () => { + const serverResponse = { + status: 'NO_ELIGIBLE_ADS', + zone_id: 299680, + width: 728, + height: 90, + place: 0 + }, + bids = spec.interpretResponse(serverResponse, { + bidRequest: bidRequests[0] + }); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response on incorrect size', () => { + const serverResponse = { + status: 'SUCCESS', + account_id: 168237, + zone_id: 299680, + cpm: 0.1, + width: 300, + height: 250, + place: 0 + }, + bids = spec.interpretResponse(serverResponse, { + bidRequest: bidRequests[0] + }); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response with CPM too low', () => { + const serverResponse = { + status: 'SUCCESS', + account_id: 168237, + zone_id: 299680, + cpm: 0.05, + width: 728, + height: 90, + place: 0 + }, + bids = spec.interpretResponse(serverResponse, { + bidRequest: bidRequests[0] + }); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response with CPM too high', () => { + const serverResponse = { + status: 'SUCCESS', + account_id: 168237, + zone_id: 299680, + cpm: 7.0, + width: 728, + height: 90, + place: 0 + }, + bids = spec.interpretResponse(serverResponse, { + bidRequest: bidRequests[0] + }); + + expect(bids).to.be.lengthOf(0); + }); + }); + }); +}); From a5775216020509a979750af76092687fd0644bda Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Tue, 20 Mar 2018 20:00:15 +0530 Subject: [PATCH 0199/1594] firing new adRenderFailed event when renderAd() fails (#2210) * firing adRenderFailed when ad render fails * test case added * refactored adRenderFail event * Condition changed --- src/AnalyticsAdapter.js | 2 ++ src/constants.json | 10 +++++++++- src/prebid.js | 31 ++++++++++++++++++++++++------ test/spec/AnalyticsAdapter_spec.js | 13 +++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/AnalyticsAdapter.js b/src/AnalyticsAdapter.js index 3a54e1c230e..0d570f14eb0 100644 --- a/src/AnalyticsAdapter.js +++ b/src/AnalyticsAdapter.js @@ -13,6 +13,7 @@ const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; const BID_WON = CONSTANTS.EVENTS.BID_WON; const BID_ADJUSTMENT = CONSTANTS.EVENTS.BID_ADJUSTMENT; const SET_TARGETING = CONSTANTS.EVENTS.SET_TARGETING; +const AD_RENDER_FAILED = CONSTANTS.EVENTS.AD_RENDER_FAILED; const LIBRARY = 'library'; const ENDPOINT = 'endpoint'; @@ -105,6 +106,7 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } [BID_ADJUSTMENT]: args => this.enqueue({ eventType: BID_ADJUSTMENT, args }), [SET_TARGETING]: args => this.enqueue({ eventType: SET_TARGETING, args }), [AUCTION_END]: args => this.enqueue({ eventType: AUCTION_END, args }), + [AD_RENDER_FAILED]: args => this.enqueue({ eventType: AD_RENDER_FAILED, args }), [AUCTION_INIT]: args => { args.config = config.options; // enableAnaltyics configuration object this.enqueue({ eventType: AUCTION_INIT, args }); diff --git a/src/constants.json b/src/constants.json index 9a2639ab83f..ef382b153af 100644 --- a/src/constants.json +++ b/src/constants.json @@ -33,7 +33,15 @@ "BID_WON": "bidWon", "SET_TARGETING": "setTargeting", "REQUEST_BIDS": "requestBids", - "ADD_AD_UNITS": "addAdUnits" + "ADD_AD_UNITS": "addAdUnits", + "AD_RENDER_FAILED" : "adRenderFailed" + }, + "AD_RENDER_FAILED_REASON" : { + "PREVENT_WRITING_ON_MAIN_DOCUMENT": "preventWritingOnMainDocuemnt", + "NO_AD": "noAd", + "EXCEPTION": "exception", + "CANNOT_FIND_AD": "cannotFindAd", + "MISSING_DOC_OR_ADID": "missingDocOrAdid" }, "EVENT_ID_PATHS": { "bidWon": "adUnitCode" diff --git a/src/prebid.js b/src/prebid.js index 7fdce6c3cf7..d5ab040e888 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -23,7 +23,8 @@ const { triggerUserSyncs } = userSync; /* private variables */ const RENDERED = 'rendered'; -const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING } = CONSTANTS.EVENTS; +const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING, AD_RENDER_FAILED } = CONSTANTS.EVENTS; +const { PREVENT_WRITING_ON_MAIN_DOCUMENT, NO_AD, EXCEPTION, CANNOT_FIND_AD, MISSING_DOC_OR_ADID } = CONSTANTS.AD_RENDER_FAILED_REASON; var eventValidators = { bidWon: checkDefinedPlacement @@ -196,6 +197,18 @@ $$PREBID_GLOBAL$$.setTargetingForAst = function() { events.emit(SET_TARGETING); }; +function emitAdRenderFail(reason, message, bid) { + const data = {}; + + data.reason = reason; + data.message = message; + if (bid) { + data.bid = bid; + } + + utils.logError(message); + events.emit(AD_RENDER_FAILED, 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 @@ -206,6 +219,7 @@ $$PREBID_GLOBAL$$.setTargetingForAst = function() { $$PREBID_GLOBAL$$.renderAd = function (doc, id) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.renderAd', arguments); utils.logMessage('Calling renderAd with adId :' + id); + if (doc && id) { try { // lookup ad by ad Id @@ -229,7 +243,8 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { if (renderer && renderer.url) { renderer.render(bid); } else if ((doc === document && !utils.inIframe()) || mediaType === 'video') { - utils.logError(`Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`); + const message = `Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`; + emitAdRenderFail(PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid); } else if (ad) { doc.write(ad); doc.close(); @@ -247,16 +262,20 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { setRenderSize(doc, width, height); utils.callBurl(bid); } else { - utils.logError('Error trying to write ad. No ad for bid response id: ' + id); + const message = `Error trying to write ad. No ad for bid response id: ${id}`; + emitAdRenderFail(NO_AD, message, bid); } } else { - utils.logError('Error trying to write ad. Cannot find ad by given id : ' + id); + const message = `Error trying to write ad. Cannot find ad by given id : ${id}`; + emitAdRenderFail(CANNOT_FIND_AD, message); } } catch (e) { - utils.logError('Error trying to write ad Id :' + id + ' to the page:' + e.message); + const message = `Error trying to write ad Id :${id} to the page:${e.message}`; + emitAdRenderFail(EXCEPTION, message); } } else { - utils.logError('Error trying to write ad Id :' + id + ' to the page. Missing document or adId'); + const message = `Error trying to write ad Id :${id} to the page. Missing document or adId`; + emitAdRenderFail(MISSING_DOC_OR_ADID, message); } }; diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 92710d47568..d6b227e9aac 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -6,6 +6,8 @@ const BID_REQUESTED = CONSTANTS.EVENTS.BID_REQUESTED; const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; const BID_WON = CONSTANTS.EVENTS.BID_WON; const BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; +const AD_RENDER_FAILED = CONSTANTS.EVENTS.AD_RENDER_FAILED; + const AnalyticsAdapter = require('src/AnalyticsAdapter').default; const config = { url: 'http://localhost:9999/src/adapters/analytics/libraries/example.js', @@ -90,6 +92,17 @@ FEATURE: Analytics Adapters API assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); }); + it('SHOULD call global when a adRenderFailed event occurs', () => { + const eventType = AD_RENDER_FAILED; + const args = { call: 'adRenderFailed' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); + assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + }); + it('SHOULD call global when a bidRequest event occurs', () => { const eventType = BID_REQUESTED; const args = { call: 'request' }; From 6ab7b543b7f2ea674a554ed4888919845e2d4d45 Mon Sep 17 00:00:00 2001 From: Vitaly Gridasov Date: Tue, 20 Mar 2018 18:10:21 +0300 Subject: [PATCH 0200/1594] Add Oneplanetonly Bid Adapter (#2269) * New adapter oneplanetonly * Change api for oneplanetonlyBidAdapter --- modules/oneplanetonlyBidAdapter.js | 76 +++++++++++++ modules/oneplanetonlyBidAdapter.md | 50 +++++++++ .../modules/oneplanetonlyBidAdapter_spec.js | 100 ++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 modules/oneplanetonlyBidAdapter.js create mode 100644 modules/oneplanetonlyBidAdapter.md create mode 100644 test/spec/modules/oneplanetonlyBidAdapter_spec.js diff --git a/modules/oneplanetonlyBidAdapter.js b/modules/oneplanetonlyBidAdapter.js new file mode 100644 index 00000000000..a6a3257a28b --- /dev/null +++ b/modules/oneplanetonlyBidAdapter.js @@ -0,0 +1,76 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; + +const BIDDER_CODE = 'oneplanetonly'; +const EDNPOINT = '//show.oneplanetonly.com/prebid'; + +function createEndpoint(siteId) { + return `${EDNPOINT}?siteId=${siteId}`; +} + +function isBidRequestValid (bid) { + return !!(bid.params.siteId && bid.params.adUnitId); +} + +function buildRequests(bidReqs) { + let firstBid = bidReqs[0] || {} + let siteId = utils.getBidIdParameter('siteId', firstBid.params) + let adUnits = bidReqs.map((bid) => { + return { + id: utils.getBidIdParameter('adUnitId', bid.params), + bidId: bid.bidId, + sizes: utils.parseSizesInput(bid.sizes), + }; + }); + + const bidRequest = { + id: firstBid.auctionId, + ver: 1, + prebidVer: `$prebid.version$`, + transactionId: firstBid.transactionId, + currency: config.getConfig('currency.adServerCurrency'), + timeout: config.getConfig('bidderTimeout'), + siteId, + domain: utils.getTopWindowLocation().hostname, + page: config.getConfig('pageUrl') || utils.getTopWindowUrl(), + referrer: utils.getTopWindowReferrer(), + adUnits, + }; + + return { + method: 'POST', + url: createEndpoint(siteId), + data: bidRequest, + options: {contentType: 'application/json', withCredentials: true} + }; +} + +function interpretResponse(serverResponse, request) { + if (!serverResponse.body.bids) { + return []; + } + return serverResponse.body.bids.map((bid) => { + return { + requestId: bid.requestId, + cpm: bid.cpm, + width: bid.width, + height: bid.height, + creativeId: bid.creativeId, + currency: bid.currency, + netRevenue: true, + ad: bid.ad, + ttl: bid.ttl + }; + }); +} + +export const spec = { + code: BIDDER_CODE, + aliases: ['opo'], // short code + isBidRequestValid, + buildRequests, + interpretResponse +} + +registerBidder(spec); diff --git a/modules/oneplanetonlyBidAdapter.md b/modules/oneplanetonlyBidAdapter.md new file mode 100644 index 00000000000..973adb33efd --- /dev/null +++ b/modules/oneplanetonlyBidAdapter.md @@ -0,0 +1,50 @@ +# Overview + +``` +Module Name: OnePlanetOnly Bidder Adapter +Module Type: Bidder Adapter +Maintainer: vitaly@oneplanetonly.com +``` + +# Description + +Module that connects to OnePlanetOnly's demand sources + +# Test Parameters +``` + var adUnits = [ + { + code: 'desktop-banner-ad-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], + } + }, + bids: [ + { + bidder: 'oneplanetonly', + params: { + siteId: '5', + adUnitId: '5-4587544' + } + } + ] + },{ + code: 'mobile-banner-ad-div', + mediaTypes: { + banner: { + sizes: [[320, 50], [320, 100]], + } + }, + bids: [ + { + bidder: "oneplanetonly", + params: { + siteId: '5', + adUnitId: '5-81037880' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/oneplanetonlyBidAdapter_spec.js b/test/spec/modules/oneplanetonlyBidAdapter_spec.js new file mode 100644 index 00000000000..4a42b471b6f --- /dev/null +++ b/test/spec/modules/oneplanetonlyBidAdapter_spec.js @@ -0,0 +1,100 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/oneplanetonlyBidAdapter'; + +describe('OnePlanetOnlyAdapter', () => { + let bid = { + bidId: '51ef8751f9aead', + bidder: 'oneplanetonly', + params: { + siteId: '5', + adUnitId: '5-4587544', + }, + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + sizes: [[300, 250], [300, 600]], + bidderRequestId: '418b37f85e772c', + auctionId: '18fd8b8b0bd757' + }; + + describe('isBidRequestValid', () => { + it('Should return true if there are params.siteId and params.adUnitId parameters present', () => { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false if at least one of parameters is not present', () => { + delete bid.params.adUnitId; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', () => { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', () => { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', () => { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', () => { + expect(serverRequest.url).to.equal('//show.oneplanetonly.com/prebid?siteId=5'); + }); + it('Returns valid data if array of bids is valid', () => { + let data = serverRequest.data; + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('id', 'ver', 'prebidVer', 'transactionId', 'currency', 'timeout', 'siteId', + 'domain', 'page', 'referrer', 'adUnits'); + + let adUnit = data.adUnits[0]; + expect(adUnit).to.have.keys('id', 'bidId', 'sizes'); + expect(adUnit.id).to.equal('5-4587544'); + expect(adUnit.bidId).to.equal('51ef8751f9aead'); + expect(adUnit.sizes).to.have.members(['300x250', '300x600']); + }); + it('Returns empty data if no valid requests are passed', () => { + serverRequest = spec.buildRequests([]); + let data = serverRequest.data; + expect(data.adUnits).to.be.an('array').that.is.empty; + }); + }); + describe('interpretResponse', () => { + it('Should interpret banner response', () => { + const serverResponse = { + body: { + bids: [{ + requestId: '51ef8751f9aead', + cpm: 0.4, + width: 300, + height: 250, + creativeId: '2', + currency: 'USD', + ad: 'Test', + ttl: 120, + }] + } + }; + let bannerResponses = spec.interpretResponse(serverResponse); + expect(bannerResponses).to.be.an('array').that.is.not.empty; + let bidObject = bannerResponses[0]; + expect(bidObject).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', + 'netRevenue', 'currency'); + expect(bidObject.requestId).to.equal('51ef8751f9aead'); + expect(bidObject.cpm).to.equal(0.4); + expect(bidObject.width).to.equal(300); + expect(bidObject.height).to.equal(250); + expect(bidObject.ad).to.equal('Test'); + expect(bidObject.ttl).to.equal(120); + expect(bidObject.creativeId).to.equal('2'); + expect(bidObject.netRevenue).to.be.true; + expect(bidObject.currency).to.equal('USD'); + }); + it('Should return an empty array if invalid response is passed', () => { + const invalid = { + body: {} + }; + let serverResponses = spec.interpretResponse(invalid); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); +}); From 4fbf447ef10f8f5f64d7356f11aed6c6b7f24fca Mon Sep 17 00:00:00 2001 From: moonshells <33766472+moonshells@users.noreply.github.com> Date: Tue, 20 Mar 2018 10:04:06 -0700 Subject: [PATCH 0201/1594] PBS videoCacheKey and vastUrl (#2101) * assign video cache key with cache id then DFP knows the correct hb uuid * add unit test for cache id and video cache key * reformat code * point vastUrl to cache_url as required by method isValidVideoBid in video.js * assign videoCacheKey with cacche_id, vastUrl with cache_url for already cached video bids only * update the bid only if both cache_id and cache_url are available --- modules/prebidServerBidAdapter.js | 5 ++ .../modules/prebidServerBidAdapter_spec.js | 57 ++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 80157f32344..601f80df361 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -351,6 +351,11 @@ const LEGACY_PROTOCOL = { if (bidObj.nurl) { bidObject.vastUrl = bidObj.nurl; } + // when video bid is already cached by Prebid Server, videoCacheKey and vastUrl should be provided properly + if (bidObj.cache_id && bidObj.cache_url) { + bidObject.videoCacheKey = bidObj.cache_id; + bidObject.vastUrl = bidObj.cache_url; + } } else { if (bidObj.adm && bidObj.nurl) { bidObject.ad = bidObj.adm; diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index e28d5854ba2..8bca5e916d3 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -143,7 +143,40 @@ const RESPONSE = { 'deal_id': 'test-dealid', 'ad_server_targeting': { 'foo': 'bar' - } + }, + 'cache_id': '7654321', + 'cache_url': 'http://www.test.com/cache?uuid=7654321', + } + ] +}; + +const VIDEO_RESPONSE = { + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'status': 'OK', + 'bidder_status': [ + { + 'bidder': 'appnexus', + 'response_time_ms': 52, + 'num_bids': 1 + } + ], + 'bids': [ + { + 'bid_id': '123', + 'code': 'div-gpt-ad-1460505748561-0', + 'creative_id': '29681110', + 'bidder': 'appnexus', + 'price': 0.5, + 'adm': '', + 'width': 300, + 'height': 250, + 'deal_id': 'test-dealid', + 'ad_server_targeting': { + 'foo': 'bar' + }, + 'media_type': 'video', + 'cache_id': 'video_cache_id', + 'cache_url': 'video_cache_url', } ] }; @@ -491,6 +524,28 @@ describe('S2S Adapter', () => { expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); expect(response).to.have.property('adId', '123'); + expect(response).to.not.have.property('videoCacheKey'); + expect(response).to.have.property('cache_id', '7654321'); + expect(response).to.have.property('cache_url', 'http://www.test.com/cache?uuid=7654321'); + expect(response).to.not.have.property('vastUrl'); + }); + + it('registers video bids', () => { + server.respondWith(JSON.stringify(VIDEO_RESPONSE)); + + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + sinon.assert.calledOnce(addBidResponse); + + const response = addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('cpm', 0.5); + expect(response).to.have.property('adId', '123'); + expect(response).to.have.property('videoCacheKey', 'video_cache_id'); + expect(response).to.have.property('cache_id', 'video_cache_id'); + expect(response).to.have.property('cache_url', 'video_cache_url'); + expect(response).to.have.property('vastUrl', 'video_cache_url'); }); it('does not call addBidResponse and calls done when ad unit not set', () => { From 8aec36220427606c25bcf1faaa1ca25d95026a38 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 20 Mar 2018 16:46:15 -0400 Subject: [PATCH 0202/1594] Unit test fixes (#2301) --- .../modules/audienceNetworkBidAdapter_spec.js | 22 +++++++++---------- .../modules/eplanningAnalyticsAdapter_spec.js | 15 ++++++++----- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index 7626780afb3..41a6d955c6a 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -4,6 +4,7 @@ import { expect } from 'chai'; import { spec } from 'modules/audienceNetworkBidAdapter'; +import * as utils from 'src/utils'; const { code, @@ -117,6 +118,15 @@ describe('AudienceNetwork adapter', () => { }); describe('buildRequests', () => { + let isSafariBrowserStub; + before(() => { + isSafariBrowserStub = sinon.stub(utils, 'isSafariBrowser'); + }); + + after(() => { + isSafariBrowserStub.restore(); + }); + it('can build URL for IAB unit', () => { expect(buildRequests([{ bidder, @@ -191,23 +201,13 @@ describe('AudienceNetwork adapter', () => { }); it('can build URL on Safari that includes a cachebuster param', () => { - const { userAgent } = navigator; - Object.defineProperty(navigator, 'userAgent', { - value: 'safari', - writable: true - }); - + isSafariBrowserStub.returns(true); expect(buildRequests([{ bidder, bidId: requestId, sizes: [[300, 250]], params: { placementId } }])[0].data).to.contain('&cb='); - - Object.defineProperty(navigator, 'userAgent', { - value: userAgent, - writable: false - }); }); }); diff --git a/test/spec/modules/eplanningAnalyticsAdapter_spec.js b/test/spec/modules/eplanningAnalyticsAdapter_spec.js index 04a7d65e12a..aba68efc27b 100644 --- a/test/spec/modules/eplanningAnalyticsAdapter_spec.js +++ b/test/spec/modules/eplanningAnalyticsAdapter_spec.js @@ -1,5 +1,7 @@ import eplAnalyticsAdapter from 'modules/eplanningAnalyticsAdapter'; +import includes from 'core-js/library/fn/array/includes'; import { expect } from 'chai'; +import {parse as parseURL} from 'src/url'; let adaptermanager = require('src/adaptermanager'); let events = require('src/events'); let constants = require('src/constants.json'); @@ -112,16 +114,17 @@ describe('eplanning analytics adapter', () => { events.emit(constants.EVENTS.AUCTION_END, {auctionId: pauctionId}); // Step 7: Find the request data sent (filtering other hosts) - requests = requests.filter(req => req.url.includes(initOptions.host)); - + requests = requests.filter(req => { + return req.url.indexOf(initOptions.host) > -1; + }); expect(requests.length).to.equal(1); - expect(requests[0].url.includes(initOptions.host + initOptions.ci)); - expect(requests[0].url.includes('https://ads.ar.e-planning.net/hba/1/12345?d=')); + expect(includes([initOptions.host + initOptions.ci], requests[0].url)); + expect(includes(['https://ads.ar.e-planning.net/hba/1/12345?d='], requests[0].url)); let info = requests[0].url; - let purl = new URL(info); - let eplData = JSON.parse(decodeURIComponent(purl.searchParams.get('d'))); + let purl = parseURL(info); + let eplData = JSON.parse(decodeURIComponent(purl.search.d)); // Step 8 check that 6 events were sent expect(eplData.length).to.equal(6); From b8bdfecee5fc198136e0fb25854dd39640a6d899 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 20 Mar 2018 16:49:10 -0400 Subject: [PATCH 0203/1594] Prebid 1.6.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 663e89ea7e0..8545e9a9999 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.6.0-pre", + "version": "1.6.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 07821c7d9d3e0fa0ec6837d05c0abc422ef4db81 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 20 Mar 2018 17:08:28 -0400 Subject: [PATCH 0204/1594] Increment Pre Version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8545e9a9999..f742753c7ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.6.0", + "version": "1.7.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4226643788001bf00dcfc21cd6c3893c2a8aa78e Mon Sep 17 00:00:00 2001 From: LeoWu Date: Wed, 21 Mar 2018 21:09:23 +0800 Subject: [PATCH 0205/1594] add optional param to bridgewellBidAdapter (#2289) * [FEAT] add optional param to bridgewellBidAdapter * [FEAT] reply to comments * [FEAT] rm trailing-spaces * [REFACTOR] rm duplicate code, update md file --- modules/bridgewellBidAdapter.js | 22 +++- modules/bridgewellBidAdapter.md | 3 +- .../spec/modules/bridgewellBidAdapter_spec.js | 122 +++++++++++++++++- 3 files changed, 138 insertions(+), 9 deletions(-) diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index ec70342c964..faf93f1037e 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -15,7 +15,25 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function(bid) { - return bid && bid.params && !!bid.params.ChannelID; + let valid = false; + let typeOfCpmWeight; + + if (bid && bid.params) { + if (bid.params.ChannelID) { + // cpmWeight is optinal parameter and should above than zero + typeOfCpmWeight = typeof bid.params.cpmWeight; + if (typeOfCpmWeight === 'undefined') { + bid.params.cpmWeight = 1; + valid = true; + } else if (typeOfCpmWeight === 'number' && bid.params.cpmWeight > 0) { + valid = true; + } else { + valid = false; + } + } + } + + return valid; }, /** @@ -82,7 +100,7 @@ export const spec = { } bidResponse.requestId = req.bidId; - bidResponse.cpm = matchedResponse.cpm; + bidResponse.cpm = matchedResponse.cpm * req.params.cpmWeight; bidResponse.width = matchedResponse.width; bidResponse.height = matchedResponse.height; bidResponse.ad = matchedResponse.ad; diff --git a/modules/bridgewellBidAdapter.md b/modules/bridgewellBidAdapter.md index b11ce21b095..1ca61ac6c77 100644 --- a/modules/bridgewellBidAdapter.md +++ b/modules/bridgewellBidAdapter.md @@ -18,7 +18,7 @@ Module that connects to Bridgewell demand source to fetch bids. { bidder: 'bridgewell', params: { - ChannelID: 'CgUxMjMzOBIBNiIFcGVubnkqCQisAhD6ARoBOQ', + ChannelID: 'CgUxMjMzOBIBNiIFcGVubnkqCQisAhD6ARoBOQ' } } ] @@ -30,6 +30,7 @@ Module that connects to Bridgewell demand source to fetch bids. bidder: 'bridgewell', params: { ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ', + cpmWeight: 1.5 } } ] diff --git a/test/spec/modules/bridgewellBidAdapter_spec.js b/test/spec/modules/bridgewellBidAdapter_spec.js index 7670d992d0d..cbe4a543816 100644 --- a/test/spec/modules/bridgewellBidAdapter_spec.js +++ b/test/spec/modules/bridgewellBidAdapter_spec.js @@ -37,6 +37,30 @@ describe('bridgewellBidAdapter', function () { 'bidId': '42dbe3a7168a6a', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CgUxMjMzOBIBNiIFcGVubnkqCQisAhD6ARoBOQ', + 'cpmWeight': 0.5 + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250]], + 'bidId': '42dbe3a7168a6a', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ', + 'cpmWeight': -0.5 + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', } ]; const adapter = newBidder(spec); @@ -48,7 +72,7 @@ describe('bridgewellBidAdapter', function () { }); describe('isBidRequestValid', () => { - let bid = { + let bidWithoutCpmWeight = { 'bidder': 'bridgewell', 'params': { 'ChannelID': 'CLJgEAYYvxUiBXBlbm55KgkIrAIQ-gEaATk' @@ -60,17 +84,83 @@ describe('bridgewellBidAdapter', function () { 'auctionId': '1d1a030790a475', }; + let bidWithCorrectCpmWeight = { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CLJgEAYYvxUiBXBlbm55KgkIrAIQ-gEaATk', + 'cpmWeight': 0.5 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + let bidWithUncorrectCpmWeight = { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CLJgEAYYvxUiBXBlbm55KgkIrAIQ-gEaATk', + 'cpmWeight': -1.0 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + let bidWithZeroCpmWeight = { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CLJgEAYYvxUiBXBlbm55KgkIrAIQ-gEaATk', + 'cpmWeight': 0 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bid)).to.equal(true); + expect(spec.isBidRequestValid(bidWithoutCpmWeight)).to.equal(true); + expect(spec.isBidRequestValid(bidWithCorrectCpmWeight)).to.equal(true); + expect(spec.isBidRequestValid(bidWithUncorrectCpmWeight)).to.equal(false); + expect(spec.isBidRequestValid(bidWithZeroCpmWeight)).to.equal(false); }); it('should return false when required params are not passed', () => { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { + let bidWithoutCpmWeight = Object.assign({}, bidWithoutCpmWeight); + let bidWithCorrectCpmWeight = Object.assign({}, bidWithCorrectCpmWeight); + let bidWithUncorrectCpmWeight = Object.assign({}, bidWithUncorrectCpmWeight); + let bidWithZeroCpmWeight = Object.assign({}, bidWithZeroCpmWeight); + + delete bidWithoutCpmWeight.params; + delete bidWithCorrectCpmWeight.params; + delete bidWithUncorrectCpmWeight.params; + delete bidWithZeroCpmWeight.params; + + bidWithoutCpmWeight.params = { 'ChannelID': 0 }; - expect(spec.isBidRequestValid(bid)).to.equal(false); + + bidWithCorrectCpmWeight.params = { + 'ChannelID': 0 + }; + + bidWithUncorrectCpmWeight.params = { + 'ChannelID': 0 + }; + + bidWithZeroCpmWeight.params = { + 'ChannelID': 0 + }; + + expect(spec.isBidRequestValid(bidWithoutCpmWeight)).to.equal(false); + expect(spec.isBidRequestValid(bidWithCorrectCpmWeight)).to.equal(false); + expect(spec.isBidRequestValid(bidWithUncorrectCpmWeight)).to.equal(false); + expect(spec.isBidRequestValid(bidWithZeroCpmWeight)).to.equal(false); }); }); @@ -129,6 +219,26 @@ describe('bridgewellBidAdapter', function () { 'ttl': 360, 'net_revenue': 'true', 'currency': 'NTD' + }, { + 'id': '8f12c646-3b87-4326-a837-c2a76999f168', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 300, + 'height': 250, + 'ad': '
test 300x250
', + 'ttl': 360, + 'net_revenue': 'true', + 'currency': 'NTD' + }, { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 728, + 'height': 90, + 'ad': '
test 728x90
', + 'ttl': 360, + 'net_revenue': 'true', + 'currency': 'NTD' }]; it('should return all required parameters', () => { From 57e248015e7c59094c5440a453195c848e038b7f Mon Sep 17 00:00:00 2001 From: Miller Date: Fri, 23 Mar 2018 01:38:57 +0200 Subject: [PATCH 0206/1594] NEW adapter AdtelligentBidAdapter (#2137) * NEW Adtelligent Bid Adapter * Update MD * add test for multiple request * cleanup * update test bid params --- modules/adtelligentBidAdapter.js | 199 +++++++++++++++ modules/adtelligentBidAdapter.md | 65 +++++ .../modules/adtelligentBidAdapter_spec.js | 240 ++++++++++++++++++ 3 files changed, 504 insertions(+) create mode 100644 modules/adtelligentBidAdapter.js create mode 100644 modules/adtelligentBidAdapter.md create mode 100644 test/spec/modules/adtelligentBidAdapter_spec.js diff --git a/modules/adtelligentBidAdapter.js b/modules/adtelligentBidAdapter.js new file mode 100644 index 00000000000..ed7da360e0b --- /dev/null +++ b/modules/adtelligentBidAdapter.js @@ -0,0 +1,199 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import {VIDEO, BANNER} from 'src/mediaTypes'; +import {Renderer} from 'src/Renderer'; +import findIndex from 'core-js/library/fn/array/find-index'; + +const URL = '//hb.adtelligent.com/auction/'; +const OUTSTREAM_SRC = '//player.adtelligent.com/outstream-unit/2.01/outstream.min.js'; +const BIDDER_CODE = 'adtelligent'; +const OUTSTREAM = 'outstream'; +const DISPLAY = 'display'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [VIDEO, BANNER], + isBidRequestValid: function (bid) { + return bid && bid.params && bid.params.aid; + }, + + /** + * Make a server request from the list of BidRequests + * @param bidRequests + * @param bidderRequest + */ + buildRequests: function (bidRequests, bidderRequest) { + return { + data: bidToTag(bidRequests), + bidderRequest, + method: 'GET', + url: URL + }; + }, + + /** + * Unpack the response from the server into a list of bids + * @param serverResponse + * @param bidderRequest + * @return {Bid[]} An array of bids which were nested inside the server + */ + interpretResponse: function (serverResponse, {bidderRequest}) { + serverResponse = serverResponse.body; + let bids = []; + + if (!utils.isArray(serverResponse)) { + return parseRTBResponse(serverResponse, bidderRequest); + } + + serverResponse.forEach(serverBidResponse => { + bids = utils.flatten(bids, parseRTBResponse(serverBidResponse, bidderRequest)); + }); + + return bids; + } +}; + +function parseRTBResponse(serverResponse, bidderRequest) { + const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; + + let bids = []; + + if (isInvalidValidResp) { + let extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; + + utils.logError(errorMessage); + + return bids; + } + + serverResponse.bids.forEach(serverBid => { + const requestId = findIndex(bidderRequest.bids, (bidRequest) => { + return bidRequest.bidId === serverBid.requestId; + }); + + if (serverBid.cpm !== 0 && requestId !== -1) { + const bid = createBid(serverBid, getMediaType(bidderRequest.bids[requestId])); + + bids.push(bid); + } + }); + + return bids; +} + +function bidToTag(bidRequests) { + let tag = { + domain: utils.getTopWindowLocation().hostname + }; + + for (let i = 0, length = bidRequests.length; i < length; i++) { + Object.assign(tag, prepareRTBRequestParams(i, bidRequests[i])); + } + + return tag; +} + +/** + * Parse mediaType + * @param _index {number} + * @param bid {object} + * @returns {object} + */ +function prepareRTBRequestParams(_index, bid) { + const mediaType = utils.deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY; + const index = !_index ? '' : `${_index + 1}`; + + return { + ['callbackId' + index]: bid.bidId, + ['aid' + index]: bid.params.aid, + ['ad_type' + index]: mediaType, + ['sizes' + index]: utils.parseSizesInput(bid.sizes).join() + }; +} + +/** + * Prepare all parameters for request + * @param bidderRequest {object} + * @returns {object} + */ +function getMediaType(bidderRequest) { + const videoMediaType = utils.deepAccess(bidderRequest, 'mediaTypes.video'); + const context = utils.deepAccess(bidderRequest, 'mediaTypes.video.context'); + + return !videoMediaType ? DISPLAY : context === OUTSTREAM ? OUTSTREAM : VIDEO; +} + +/** + * Configure new bid by response + * @param bidResponse {object} + * @param mediaType {Object} + * @returns {object} + */ +function createBid(bidResponse, mediaType) { + let bid = { + requestId: bidResponse.requestId, + creativeId: bidResponse.cmpId, + height: bidResponse.height, + currency: bidResponse.cur, + width: bidResponse.width, + cpm: bidResponse.cpm, + netRevenue: true, + mediaType, + ttl: 3600 + }; + + if (mediaType === DISPLAY) { + return Object.assign(bid, { + ad: bidResponse.ad + }); + } + + Object.assign(bid, { + vastUrl: bidResponse.vastUrl + }); + + if (mediaType === OUTSTREAM) { + Object.assign(bid, { + mediaType: 'video', + adResponse: bidResponse, + renderer: newRenderer(bidResponse.requestId) + }); + } + + return bid; +} + +/** + * Create Adtelligent renderer + * @param requestId + * @returns {*} + */ +function newRenderer(requestId) { + const renderer = Renderer.install({ + id: requestId, + url: OUTSTREAM_SRC, + loaded: false + }); + + renderer.setRender(outstreamRender); + + return renderer; +} + +/** + * Initialise Adtelligent outstream + * @param bid + */ +function outstreamRender(bid) { + bid.renderer.push(() => { + window.VOutstreamAPI.initOutstreams([{ + width: bid.width, + height: bid.height, + vastUrl: bid.vastUrl, + elId: bid.adUnitCode + }]); + }); +} + +registerBidder(spec); diff --git a/modules/adtelligentBidAdapter.md b/modules/adtelligentBidAdapter.md new file mode 100644 index 00000000000..2b48c9726c9 --- /dev/null +++ b/modules/adtelligentBidAdapter.md @@ -0,0 +1,65 @@ +# Overview + +**Module Name**: Adtelligent Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: support@adtelligent.com + +# Description + +Get access to multiple demand partners across Adtelligent Marketplace and maximize your yield with Adtelligent header bidding adapter. + +Adtelligent header bidding adapter connects with Adtelligent demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand and display demand + + +# Test Parameters +``` + var adUnits = [ + + // Video instream adUnit + { + code: 'div-test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'instream' + } + }, + bids: [{ + bidder: 'adtelligent', + params: { + aid: 331133 + } + }] + }, + + // Video outstream adUnit + { + code: 'outstream-test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'outstream' + } + }, + bids: [{ + bidder: 'adtelligent', + params: { + aid: 331133 + } + }] + }, + + // Banner adUnit + { + code: 'div-test-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'adtelligent', + params: { + aid: 350975 + } + }] + } + ]; +``` diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js new file mode 100644 index 00000000000..fa3e0479372 --- /dev/null +++ b/test/spec/modules/adtelligentBidAdapter_spec.js @@ -0,0 +1,240 @@ +import {expect} from 'chai'; +import {spec} from 'modules/adtelligentBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//hb.adtelligent.com/auction/'; + +const DISPLAY_REQUEST = { + 'bidder': 'adtelligent', + 'params': { + 'aid': 12345 + }, + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '2e41f65424c87c', + 'adUnitCode': 'adunit-code', + 'bidId': '84ab500420319d', + 'sizes': [300, 250] +}; + +const VIDEO_REQUEST = { + 'bidder': 'adtelligent', + 'mediaTypes': { + 'video': {} + }, + 'params': { + 'aid': 12345 + }, + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '2e41f65424c87c', + 'adUnitCode': 'adunit-code', + 'bidId': '84ab500420319d', + 'sizes': [[480, 360], [640, 480]] +}; + +const SERVER_VIDEO_RESPONSE = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'vastUrl': 'http://rtb.adtelligent.com/vast/?adid=44F2AEB9BFC881B3', + 'requestId': '2e41f65424c87c', + 'url': '44F2AEB9BFC881B3', + 'creative_id': 342516, + 'cmpId': 342516, + 'height': 480, + 'cur': 'USD', + 'width': 640, + 'cpm': 0.9 + } + ] +}; +const SERVER_DISPLAY_RESPONSE = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'ad': '', + 'requestId': '2e41f65424c87c', + 'creative_id': 342516, + 'cmpId': 342516, + 'height': 250, + 'cur': 'USD', + 'width': 300, + 'cpm': 0.9 + }] +}; + +const videoBidderRequest = { + bidderCode: 'bidderCode', + bids: [{mediaTypes: {video: {}}, bidId: '2e41f65424c87c'}] +}; + +const displayBidderRequest = { + bidderCode: 'bidderCode', + bids: [{bidId: '2e41f65424c87c'}] +}; + +const videoEqResponse = [{ + vastUrl: 'http://rtb.adtelligent.com/vast/?adid=44F2AEB9BFC881B3', + requestId: '2e41f65424c87c', + creativeId: 342516, + mediaType: 'video', + netRevenue: true, + currency: 'USD', + height: 480, + width: 640, + ttl: 3600, + cpm: 0.9 +}]; + +const displayEqResponse = [{ + requestId: '2e41f65424c87c', + creativeId: 342516, + mediaType: 'display', + netRevenue: true, + currency: 'USD', + ad: '', + height: 250, + width: 300, + ttl: 3600, + cpm: 0.9 +}]; + +describe('adtelligentBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(VIDEO_REQUEST)).to.equal(12345); + }); + + it('should return false when required params are not passed', () => { + let bid = Object.assign({}, VIDEO_REQUEST); + delete bid.params; + expect(spec.isBidRequestValid(bid)).to.equal(undefined); + }); + }); + + describe('buildRequests', () => { + let videoBidRequests = [VIDEO_REQUEST]; + let displayBidRequests = [DISPLAY_REQUEST]; + let videoAndDisplayBidRequests = [DISPLAY_REQUEST, VIDEO_REQUEST]; + + const displayRequest = spec.buildRequests(displayBidRequests, {}); + const videoRequest = spec.buildRequests(videoBidRequests, {}); + const videoAndDisplayRequests = spec.buildRequests(videoAndDisplayBidRequests, {}); + + it('sends bid request to ENDPOINT via GET', () => { + expect(videoRequest.method).to.equal('GET'); + expect(displayRequest.method).to.equal('GET'); + expect(videoAndDisplayRequests.method).to.equal('GET'); + }); + + it('sends bid request to correct ENDPOINT', () => { + expect(videoRequest.url).to.equal(ENDPOINT); + expect(displayRequest.url).to.equal(ENDPOINT); + expect(videoAndDisplayRequests.url).to.equal(ENDPOINT); + }); + + it('sends correct video bid parameters', () => { + const bid = Object.assign({}, videoRequest.data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'video', + aid: 12345, + sizes: '480x360,640x480' + }; + + expect(bid).to.deep.equal(eq); + }); + + it('sends correct display bid parameters', () => { + const bid = Object.assign({}, displayRequest.data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'display', + aid: 12345, + sizes: '300x250' + }; + + expect(bid).to.deep.equal(eq); + }); + + it('sends correct video and display bid parameters', () => { + const bid = Object.assign({}, videoAndDisplayRequests.data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'display', + aid: 12345, + sizes: '300x250', + callbackId2: '84ab500420319d', + ad_type2: 'video', + aid2: 12345, + sizes2: '480x360,640x480' + }; + + expect(bid).to.deep.equal(eq); + }); + }); + + describe('interpretResponse', () => { + let serverResponse; + let bidderRequest; + let eqResponse; + + afterEach(() => { + serverResponse = null; + bidderRequest = null; + eqResponse = null; + }); + + it('should get correct video bid response', () => { + serverResponse = SERVER_VIDEO_RESPONSE; + bidderRequest = videoBidderRequest; + eqResponse = videoEqResponse; + + bidServerResponseCheck(); + }); + + it('should get correct display bid response', () => { + serverResponse = SERVER_DISPLAY_RESPONSE; + bidderRequest = displayBidderRequest; + eqResponse = displayEqResponse; + + bidServerResponseCheck(); + }); + + function bidServerResponseCheck() { + const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); + + expect(result).to.deep.equal(eqResponse); + } + + function nobidServerResponseCheck() { + const noBidServerResponse = {bids: []}; + const noBidResult = spec.interpretResponse({body: noBidServerResponse}, {bidderRequest}); + + expect(noBidResult.length).to.equal(0); + } + + it('handles video nobid responses', () => { + bidderRequest = videoBidderRequest; + + nobidServerResponseCheck(); + }); + + it('handles display nobid responses', () => { + bidderRequest = displayBidderRequest; + + nobidServerResponseCheck(); + }); + }); +}); From 8719aefad0dc91d3789ed858c98997d5521f8ea2 Mon Sep 17 00:00:00 2001 From: Spacedragoon Date: Fri, 23 Mar 2018 01:26:00 +0100 Subject: [PATCH 0207/1594] Smart Ad Server: Fix bug when multi bids (#2170) --- modules/smartadserverBidAdapter.js | 49 ++++++++++--------- .../modules/smartadserverBidAdapter_spec.js | 8 +-- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 4828f3a36a8..3d2eaa4de83 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -31,30 +31,31 @@ export const spec = { // to find which one the ad server needs // pull requested transaction ID from bidderRequest.bids[].transactionId - var bid = validBidRequests[0]; - const payload = { - siteid: bid.params.siteId, - pageid: bid.params.pageId, - formatid: bid.params.formatId, - currencyCode: config.getConfig('currency.adServerCurrency'), - bidfloor: bid.params.bidfloor || 0.0, - targeting: bid.params.target && bid.params.target != '' ? bid.params.target : undefined, - tagId: bid.adUnitCode, - sizes: bid.sizes.map(size => ({ - w: size[0], - h: size[1] - })), - pageDomain: utils.getTopWindowUrl(), - transactionId: bid.transactionId, - timeout: config.getConfig('bidderTimeout'), - bidId: bid.bidId - }; - const payloadString = JSON.stringify(payload); - return { - method: 'POST', - url: bid.params.domain + '/prebid/v1', - data: payloadString, - }; + return validBidRequests.map(bid => { + var payload = { + siteid: bid.params.siteId, + pageid: bid.params.pageId, + formatid: bid.params.formatId, + currencyCode: config.getConfig('currency.adServerCurrency'), + bidfloor: bid.params.bidfloor || 0.0, + targeting: bid.params.target && bid.params.target != '' ? bid.params.target : undefined, + tagId: bid.adUnitCode, + sizes: bid.sizes.map(size => ({ + w: size[0], + h: size[1] + })), + pageDomain: utils.getTopWindowUrl(), + transactionId: bid.transactionId, + timeout: config.getConfig('bidderTimeout'), + bidId: bid.bidId + }; + var payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: bid.params.domain + '/prebid/v1', + data: payloadString, + }; + }); }, /** * Unpack the response from the server into a list of bids. diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 5cb4a1277fb..6e052654685 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -74,9 +74,9 @@ describe('Smart ad server bid adapter tests', () => { } }); const request = spec.buildRequests(DEFAULT_PARAMS); - expect(request).to.have.property('url').and.to.equal('http://prg.smartadserver.com/prebid/v1'); - expect(request).to.have.property('method').and.to.equal('POST'); - const requestContent = JSON.parse(request.data); + expect(request[0]).to.have.property('url').and.to.equal('http://prg.smartadserver.com/prebid/v1'); + expect(request[0]).to.have.property('method').and.to.equal('POST'); + const requestContent = JSON.parse(request[0].data); expect(requestContent).to.have.property('siteid').and.to.equal('1234'); expect(requestContent).to.have.property('pageid').and.to.equal('5678'); expect(requestContent).to.have.property('formatid').and.to.equal('90'); @@ -95,7 +95,7 @@ describe('Smart ad server bid adapter tests', () => { it('Verify parse response', () => { const request = spec.buildRequests(DEFAULT_PARAMS); - const bids = spec.interpretResponse(BID_RESPONSE, request); + const bids = spec.interpretResponse(BID_RESPONSE, request[0]); expect(bids).to.have.lengthOf(1); const bid = bids[0]; expect(bid.cpm).to.equal(12); From 85cdf7b007bd2580a0c1fb80427070be630f5a33 Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Mon, 26 Mar 2018 10:05:17 -0400 Subject: [PATCH 0208/1594] Serverbid Bid Adapter: Added archon alias (#2293) --- modules/serverbidBidAdapter.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index 24bb5aa6255..8497a67f401 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -21,6 +21,9 @@ const CONFIG = { }, 'automatad': { 'BASE_URI': 'https://e.serverbid.com/api/v2' + }, + 'archon': { + 'BASE_URI': 'https://e.serverbid.com/api/v2' } }; @@ -29,7 +32,7 @@ let bidder = 'serverbid'; export const spec = { code: BIDDER_CODE, - aliases: ['connectad', 'onefiftytwo', 'insticator', 'adsparc', 'automatad'], + aliases: ['connectad', 'onefiftytwo', 'insticator', 'adsparc', 'automatad', 'archon'], /** * Determines whether or not the given bid request is valid. From 4012c7ee644bbdaf3b1ccb0ae6b21c8653da608b Mon Sep 17 00:00:00 2001 From: moonshells <33766472+moonshells@users.noreply.github.com> Date: Mon, 26 Mar 2018 07:13:42 -0700 Subject: [PATCH 0209/1594] if cache markup is not enabled, set it to the default value 0 (#2302) * if cache markup is not enabled (1 for Mobile App, 2 for Web), set it to the default value 0 * use triple equals instead of double equals --- modules/prebidServerBidAdapter.js | 2 +- test/spec/modules/prebidServerBidAdapter_spec.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 601f80df361..09fc036c1d1 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -288,7 +288,7 @@ const LEGACY_PROTOCOL = { max_bids: _s2sConfig.maxBids, timeout_millis: _s2sConfig.timeout, secure: _s2sConfig.secure, - cache_markup: _s2sConfig.cacheMarkup, + cache_markup: _s2sConfig.cacheMarkup === 1 || _s2sConfig.cacheMarkup === 2 ? _s2sConfig.cacheMarkup : 0, url: utils.getTopWindowUrl(), prebid_version: '$prebid.version$', ad_units: adUnits, diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 8bca5e916d3..5e1a1ff355c 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -12,6 +12,7 @@ let CONFIG = { enabled: true, bidders: ['appnexus'], timeout: 1000, + cacheMarkup: 2, endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' }; @@ -390,10 +391,21 @@ describe('S2S Adapter', () => { config.setConfig({s2sConfig: CONFIG}); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid).to.have.property('cache_markup', 2); expect(requestBid.ad_units[0].bids[0].params.placementId).to.exist.and.to.be.a('number'); expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); }); + it('sets invalid cacheMarkup value to 0', () => { + const s2sConfig = Object.assign({}, CONFIG, { + cacheMarkup: 999 + }); + config.setConfig({s2sConfig: s2sConfig}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid).to.have.property('cache_markup', 0); + }); + it('adds digitrust id is present and user is not optout', () => { let digiTrustObj = { success: true, From 63159da8a432a410f859811deee5574f276667b1 Mon Sep 17 00:00:00 2001 From: rachelrj Date: Mon, 26 Mar 2018 08:17:43 -0600 Subject: [PATCH 0210/1594] Enhance location detection within utils (#2167) * fix sovrn dealid * send 'iv' param if present * `page` field in `site` object sends full url * Enhance location detection within util function. * fix func call * fix tagid var type * add test for converting tagid to string * CR * Reorg gettopwindowlocation util & add tests. * lint fixes * search param is string in window location objects --- modules/sovrnBidAdapter.js | 7 +- src/url.js | 5 +- src/utils.js | 53 ++++++++++++-- test/spec/modules/sovrnBidAdapter_spec.js | 20 +++++ test/spec/url_spec.js | 13 ++++ test/spec/utils_spec.js | 89 ++++++++++++++++++++++- 6 files changed, 173 insertions(+), 14 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index d13331b9179..564dca85690 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -22,6 +22,7 @@ export const spec = { * @return object of parameters for Prebid AJAX request */ buildRequests: function(bidReqs) { + const loc = utils.getTopWindowLocation(); let sovrnImps = []; let iv; utils._each(bidReqs, function (bid) { @@ -29,7 +30,7 @@ export const spec = { sovrnImps.push({ id: bid.bidId, banner: { w: 1, h: 1 }, - tagid: utils.getBidIdParameter('tagid', bid.params), + tagid: String(utils.getBidIdParameter('tagid', bid.params)), bidfloor: utils.getBidIdParameter('bidfloor', bid.params) }); }); @@ -37,8 +38,8 @@ export const spec = { id: utils.getUniqueIdentifierStr(), imp: sovrnImps, site: { - domain: window.location.host, - page: window.location.host + window.location.pathname + location.search + location.hash + domain: loc.host, + page: loc.host + loc.pathname + loc.search + loc.hash } }; if (iv) sovrnBidReq.iv = iv; diff --git a/src/url.js b/src/url.js index 502245f3abd..c63bca2ca41 100644 --- a/src/url.js +++ b/src/url.js @@ -31,12 +31,15 @@ export function parse(url, options) { } else { parsed.href = decodeURIComponent(url); } + // in window.location 'search' is string, not object + let qsAsString = (options && 'decodeSearchAsString' in options && options.decodeSearchAsString); return { + href: parsed.href, protocol: (parsed.protocol || '').replace(/:$/, ''), hostname: parsed.hostname, port: +parsed.port, pathname: parsed.pathname.replace(/^(?!\/)/, '/'), - search: parseQS(parsed.search || ''), + search: (qsAsString) ? parsed.search : parseQS(parsed.search || ''), hash: (parsed.hash || '').replace(/^#/, ''), host: parsed.host || window.location.host }; diff --git a/src/utils.js b/src/utils.js index 3738d0e7d52..5436a4aa167 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,6 +2,7 @@ import { config } from './config'; import clone from 'just-clone'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; +import { parse } from './url'; const CONSTANTS = require('./constants'); var _loggingChecked = false; @@ -157,17 +158,55 @@ export function parseGPTSingleSizeArray(singleSize) { } }; -exports.getTopWindowLocation = function () { - let location; +exports.getTopWindowLocation = function() { + if (exports.inIframe()) { + let loc; + try { + loc = exports.getAncestorOrigins() || exports.getTopFrameReferrer(); + } catch (e) { + logInfo('could not obtain top window location', e); + } + if (loc) return parse(loc, {'decodeSearchAsString': true}); + } + return exports.getWindowLocation(); +} + +exports.getTopFrameReferrer = function () { try { - // force an exception in x-domain enviornments. #1509 + // force an exception in x-domain environments. #1509 window.top.location.toString(); - location = window.top.location; + let referrerLoc = ''; + let currentWindow; + do { + currentWindow = currentWindow ? currentWindow.parent : window; + if (currentWindow.document && currentWindow.document.referrer) { + referrerLoc = currentWindow.document.referrer; + } + } + while (currentWindow !== window.top); + return referrerLoc; } catch (e) { - location = window.location; + return window.document.referrer; + } +}; + +exports.getAncestorOrigins = function () { + if (window.document.location && window.document.location.ancestorOrigins && + window.document.location.ancestorOrigins.length >= 1) { + return window.document.location.ancestorOrigins[window.document.location.ancestorOrigins.length - 1]; } +}; + +exports.getWindowTop = function () { + return window.top; +}; + +exports.getWindowSelf = function () { + return window.self; +}; - return location; +exports.getWindowLocation = function () { + return window.location; }; exports.getTopWindowUrl = function () { @@ -658,7 +697,7 @@ export function deepClone(obj) { export function inIframe() { try { - return window.self !== window.top; + return exports.getWindowSelf() !== exports.getWindowTop(); } catch (e) { return true; } diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 5fc7cb6a62a..a440b3d43c4 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -83,6 +83,26 @@ describe('sovrnBidAdapter', function() { expect(request.data).to.contain('"iv":"vet"') }) + + it('converts tagid to string', () => { + const ivBidRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': 403370, + 'iv': 'vet' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + const request = spec.buildRequests(ivBidRequests); + + expect(request.data).to.contain('"tagid":"403370"') + }) }); describe('interpretResponse', () => { diff --git a/test/spec/url_spec.js b/test/spec/url_spec.js index 3ffb8ad5ca7..cfa1b0c80b4 100644 --- a/test/spec/url_spec.js +++ b/test/spec/url_spec.js @@ -78,4 +78,17 @@ describe('helpers.url', () => { })).to.equal('http://example.com'); }); }); + + describe('parse(url, {decodeSearchAsString: true})', () => { + let parsed; + + beforeEach(() => { + parsed = parse('http://example.com:3000/pathname/?search=test&foo=bar&bar=foo%26foo%3Dxxx#hash', {decodeSearchAsString: true}); + }); + + it('extracts the search query', () => { + expect(parsed).to.have.property('search'); + expect(parsed.search).to.equal('?search=test&foo=bar&bar=foo&foo=xxx'); + }); + }); }); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index f02b4881be3..7597e389ee9 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -1,8 +1,7 @@ -import { getSlotTargeting, getAdServerTargeting } from 'test/fixtures/fixtures'; -import { cookiesAreEnabled } from '../../src/utils'; +import { getAdServerTargeting } from 'test/fixtures/fixtures'; var assert = require('assert'); -var utils = require('../../src/utils'); +var utils = require('src/utils'); describe('Utils', function () { var obj_string = 's', @@ -623,4 +622,88 @@ describe('Utils', function () { expect(adUnitCopy[0].renderer.render).to.be.a('function'); }); }); + describe('getTopWindowLocation', () => { + let sandbox; + + beforeEach(() => { + sandbox = sinon.sandbox.create(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('returns window.location if not in iFrame', () => { + sandbox.stub(utils, 'getWindowLocation').returns({ + href: 'https://www.google.com/', + ancestorOrigins: {}, + origin: 'https://www.google.com', + protocol: 'https', + host: 'www.google.com', + hostname: 'www.google.com', + port: '', + pathname: '/', + search: '', + hash: '' + }); + let windowSelfAndTopObject = { self: 'is same as top' }; + sandbox.stub(utils, 'getWindowSelf').returns( + windowSelfAndTopObject + ); + sandbox.stub(utils, 'getWindowTop').returns( + windowSelfAndTopObject + ); + var topWindowLocation = utils.getTopWindowLocation(); + expect(topWindowLocation).to.be.a('object'); + expect(topWindowLocation.href).to.equal('https://www.google.com/'); + expect(topWindowLocation.protocol).to.equal('https'); + expect(topWindowLocation.hostname).to.equal('www.google.com'); + expect(topWindowLocation.port).to.equal(''); + expect(topWindowLocation.pathname).to.equal('/'); + expect(topWindowLocation.hash).to.equal(''); + expect(topWindowLocation.search).to.equal(''); + expect(topWindowLocation.host).to.equal('www.google.com'); + }); + + it('returns parsed dom string from ancestorOrigins if in iFrame & ancestorOrigins is populated', () => { + sandbox.stub(utils, 'getWindowSelf').returns( + { self: 'is not same as top' } + ); + sandbox.stub(utils, 'getWindowTop').returns( + { top: 'is not same as self' } + ); + sandbox.stub(utils, 'getAncestorOrigins').returns('https://www.google.com/a/umich.edu/acs'); + var topWindowLocation = utils.getTopWindowLocation(); + expect(topWindowLocation).to.be.a('object'); + expect(topWindowLocation.pathname).to.equal('/a/umich.edu/acs'); + expect(topWindowLocation.href).to.equal('https://www.google.com/a/umich.edu/acs'); + expect(topWindowLocation.protocol).to.equal('https'); + expect(topWindowLocation.hostname).to.equal('www.google.com'); + expect(topWindowLocation.port).to.equal(0); + expect(topWindowLocation.hash).to.equal(''); + expect(topWindowLocation.search).to.equal(''); + expect(topWindowLocation.host).to.equal('www.google.com'); + }); + + it('returns parsed referrer string if in iFrame but no ancestorOrigins', () => { + sandbox.stub(utils, 'getWindowSelf').returns( + { self: 'is not same as top' } + ); + sandbox.stub(utils, 'getWindowTop').returns( + { top: 'is not same as self' } + ); + sandbox.stub(utils, 'getAncestorOrigins').returns(null); + sandbox.stub(utils, 'getTopFrameReferrer').returns('https://www.example.com/'); + var topWindowLocation = utils.getTopWindowLocation(); + expect(topWindowLocation).to.be.a('object'); + expect(topWindowLocation.href).to.equal('https://www.example.com/'); + expect(topWindowLocation.protocol).to.equal('https'); + expect(topWindowLocation.hostname).to.equal('www.example.com'); + expect(topWindowLocation.port).to.equal(0); + expect(topWindowLocation.pathname).to.equal('/'); + expect(topWindowLocation.hash).to.equal(''); + expect(topWindowLocation.search).to.equal(''); + expect(topWindowLocation.host).to.equal('www.example.com'); + }); + }); }); From bae04f43ab0e147ac5ead6ccdee3ccb4add86e3d Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Mon, 26 Mar 2018 12:48:31 -0700 Subject: [PATCH 0211/1594] Update stalebot labels (#2319) --- .github/stale.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/stale.yml b/.github/stale.yml index 41b1c7ba747..0925c69c703 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -7,8 +7,9 @@ exemptLabels: - pinned - security - bug + - feature # Label to use when marking an issue as stale -staleLabel: wontfix +staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had From 469d586b98800cdd0021768efc11fc50da7572d1 Mon Sep 17 00:00:00 2001 From: bretg Date: Mon, 26 Mar 2018 17:23:09 -0400 Subject: [PATCH 0212/1594] Changing default currency file to https (#2306) --- modules/currency.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/currency.js b/modules/currency.js index aeeabc3817c..90941538363 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -5,7 +5,7 @@ import * as utils from 'src/utils'; import { config } from 'src/config'; import { hooks } from 'src/hook.js'; -const DEFAULT_CURRENCY_RATE_URL = 'http://currency.prebid.org/latest.json'; +const DEFAULT_CURRENCY_RATE_URL = 'https://currency.prebid.org/latest.json'; const CURRENCY_RATE_PRECISION = 4; var bidResponseQueue = []; From feafdcf2a13a0a812944a631c4549e602499266a Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Mon, 26 Mar 2018 14:50:34 -0700 Subject: [PATCH 0213/1594] Support aliases in prebidServer (#2257) * Support AppNexus aliases in s2s request * Support dynamic aliases --- modules/prebidServerBidAdapter.js | 19 ++++++- src/adaptermanager.js | 2 + src/adapters/bidderFactory.js | 1 + .../modules/prebidServerBidAdapter_spec.js | 57 +++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 09fc036c1d1..ebb630ceb7a 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -213,7 +213,10 @@ const paramTypes = { function convertTypes(adUnits) { adUnits.forEach(adUnit => { adUnit.bids.forEach(bid => { - const types = paramTypes[bid.bidder] || []; + // aliases use the base bidder's paramTypes + const bidder = adaptermanager.aliasRegistry[bid.bidder] || bid.bidder; + const types = paramTypes[bidder] || []; + Object.keys(types).forEach(key => { if (bid.params[key]) { bid.params[key] = types[key](bid.params[key]); @@ -402,14 +405,20 @@ const OPEN_RTB_PROTOCOL = { buildRequest(s2sBidRequest, adUnits) { let imps = []; + let aliases = {}; // transform ad unit into array of OpenRTB impression objects adUnits.forEach(adUnit => { - // OpenRTB response contains the adunit code and bidder name. These are - // combined to create a unique key for each bid since an id isn't returned adUnit.bids.forEach(bid => { + // OpenRTB response contains the adunit code and bidder name. These are + // combined to create a unique key for each bid since an id isn't returned const key = `${adUnit.code}${bid.bidder}`; this.bidMap[key] = bid; + + // check for and store valid aliases to add to the request + if (adaptermanager.aliasRegistry[bid.bidder]) { + aliases[bid.bidder] = adaptermanager.aliasRegistry[bid.bidder]; + } }); let banner; @@ -469,6 +478,10 @@ const OPEN_RTB_PROTOCOL = { request.user = { ext: { digitrust: digiTrust } }; } + if (!utils.isEmpty(aliases)) { + request.ext = { prebid: { aliases } }; + } + return request; }, diff --git a/src/adaptermanager.js b/src/adaptermanager.js index b4a874a0736..6ff2387cca2 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -15,6 +15,7 @@ let s2sTestingModule; // store s2sTesting module if it's loaded var _bidderRegistry = {}; exports.bidderRegistry = _bidderRegistry; +exports.aliasRegistry = {}; let _s2sConfig = {}; config.getConfig('s2sConfig', config => { @@ -383,6 +384,7 @@ exports.aliasBidAdapter = function (bidderCode, alias) { } else { let spec = bidAdaptor.getSpec(); newAdapter = newBidder(Object.assign({}, spec, { code: alias })); + exports.aliasRegistry[alias] = bidderCode; } this.registerBidAdapter(newAdapter, alias, { supportedMediaTypes diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index b9930c3f363..2497572cd10 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -139,6 +139,7 @@ export function registerBidder(spec) { putBidder(spec); if (Array.isArray(spec.aliases)) { spec.aliases.forEach(alias => { + adaptermanager.aliasRegistry[alias] = spec.code; putBidder(Object.assign({}, spec, { code: alias })); }); } diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 5e1a1ff355c..383c599a133 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -498,6 +498,63 @@ describe('S2S Adapter', () => { expect(requestBid.site.publisher).to.exist.and.to.be.a('object'); expect(requestBid.site.page).to.exist.and.to.be.a('string'); }); + + it('adds appnexus aliases to request', () => { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + config.setConfig({s2sConfig}); + + const aliasBidder = { + bidder: 'brealtime', + params: { placementId: '123456' } + }; + + const request = Object.assign({}, REQUEST); + request.ad_units[0].bids = [aliasBidder]; + + adapter.callBids(request, BID_REQUESTS, addBidResponse, done, ajax); + + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.ext).to.deep.equal({ + prebid: { + aliases: { + brealtime: 'appnexus' + } + } + }); + }); + + it('adds dynamic aliases to request', () => { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + config.setConfig({s2sConfig}); + + const alias = 'foobar'; + const aliasBidder = { + bidder: alias, + params: { placementId: '123456' } + }; + + const request = Object.assign({}, REQUEST); + request.ad_units[0].bids = [aliasBidder]; + + // TODO: stub this + $$PREBID_GLOBAL$$.aliasBidder('appnexus', alias); + adapter.callBids(request, BID_REQUESTS, addBidResponse, done, ajax); + + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.ext).to.deep.equal({ + prebid: { + aliases: { + [alias]: 'appnexus' + } + } + }); + }); }); describe('response handler', () => { From bc94b71a5d19a40110aff1922562c1f32e023959 Mon Sep 17 00:00:00 2001 From: LeoWu Date: Tue, 27 Mar 2018 23:03:04 +0800 Subject: [PATCH 0214/1594] [FEAT] adunit sizes support (#2320) --- modules/bridgewellBidAdapter.js | 7 ++++++- modules/bridgewellBidAdapter.md | 11 ++++++++++ .../spec/modules/bridgewellBidAdapter_spec.js | 21 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index faf93f1037e..2a7dc0b35c3 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -77,9 +77,14 @@ export const spec = { return; } + const anotherFormatSize = []; // for store width and height let matchedResponse = find(serverResponse.body, function(res) { return !!res && !res.consumed && find(req.sizes, function(size) { - return res.width === size[0] && res.height === size[1]; + let width = res.width; + let height = res.height; + if (typeof size === 'number') anotherFormatSize.push(size); // if sizes format is Array[Number], push width and height into anotherFormatSize + return (width === size[0] && height === size[1]) || // for format Array[Array[Number]] check + (width === anotherFormatSize[0] && height === anotherFormatSize[1]); // for foramt Array[Number] check }); }); diff --git a/modules/bridgewellBidAdapter.md b/modules/bridgewellBidAdapter.md index 1ca61ac6c77..b9d065054fa 100644 --- a/modules/bridgewellBidAdapter.md +++ b/modules/bridgewellBidAdapter.md @@ -34,6 +34,17 @@ Module that connects to Bridgewell demand source to fetch bids. } } ] + },{ + code: 'test-div', + sizes: [728, 90], + bids: [ + { + bidder: 'bridgewell', + params: { + ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ' + } + } + ] } ]; ``` diff --git a/test/spec/modules/bridgewellBidAdapter_spec.js b/test/spec/modules/bridgewellBidAdapter_spec.js index cbe4a543816..6b95b44dfe5 100644 --- a/test/spec/modules/bridgewellBidAdapter_spec.js +++ b/test/spec/modules/bridgewellBidAdapter_spec.js @@ -61,6 +61,17 @@ describe('bridgewellBidAdapter', function () { 'bidId': '3150ccb55da321', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ', + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [728, 90], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', } ]; const adapter = newBidder(spec); @@ -239,6 +250,16 @@ describe('bridgewellBidAdapter', function () { 'ttl': 360, 'net_revenue': 'true', 'currency': 'NTD' + }, { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 728, + 'height': 90, + 'ad': '
test 728x90
', + 'ttl': 360, + 'net_revenue': 'true', + 'currency': 'NTD' }]; it('should return all required parameters', () => { From 1b9d022eec7295473813e6fbcec91110536d19b1 Mon Sep 17 00:00:00 2001 From: jlzhangdev Date: Wed, 28 Mar 2018 05:57:38 -0700 Subject: [PATCH 0215/1594] EngageBDR New Bid Adapter (#2309) * ebdr adapter 0.34.1 * ebdrBidAdapter.js 1.x * ebdrAdapter * update md and fix log issue * add video support and test case for EBDR adapter * Fix an issue for EBDR adapter Fix an issue might caused undefined if it is an old bidder * add vastUrl * add video adapter in md * fix test cases --- modules/ebdrBidAdapter.js | 133 +++++++++++++++ modules/ebdrBidAdapter.md | 53 ++++++ test/spec/modules/ebdrBidAdapter_spec.js | 209 +++++++++++++++++++++++ 3 files changed, 395 insertions(+) create mode 100644 modules/ebdrBidAdapter.js create mode 100644 modules/ebdrBidAdapter.md create mode 100644 test/spec/modules/ebdrBidAdapter_spec.js diff --git a/modules/ebdrBidAdapter.js b/modules/ebdrBidAdapter.js new file mode 100644 index 00000000000..63a308f1f62 --- /dev/null +++ b/modules/ebdrBidAdapter.js @@ -0,0 +1,133 @@ +import * as utils from 'src/utils'; +import { VIDEO, BANNER } from 'src/mediaTypes'; +import { registerBidder } from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'ebdr'; +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, VIDEO ], + isBidRequestValid: function(bid) { + return !!(bid && bid.params && bid.params.zoneid); + }, + buildRequests: function(bids) { + const rtbServerDomain = 'dsp.bnmla.com'; + let domain = window.location.host; + let page = window.location.pathname + location.search + location.hash; + let ebdrImps = []; + const ebdrReq = {}; + let ebdrParams = {}; + let zoneid = ''; + let requestId = ''; + bids.forEach(bid => { + utils.logInfo('Log bid', bid); + let bidFloor = utils.getBidIdParameter('bidfloor', bid.params); + let whArr = getWidthAndHeight(bid); + let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video) ? VIDEO : BANNER; + zoneid = utils.getBidIdParameter('zoneid', bid.params); + requestId = bid.bidderRequestId; + ebdrImps.push({ + id: bid.bidId, + [_mediaTypes]: { + w: whArr[0], + h: whArr[1] + }, + bidfloor: bidFloor + }) + ebdrReq[bid.bidId] = {mediaTypes: _mediaTypes, + w: whArr[0], + h: whArr[1] + }; + ebdrParams['latitude'] = utils.getBidIdParameter('latitude', bid.params); + ebdrParams['longitude'] = utils.getBidIdParameter('longitude', bid.params); + ebdrParams['ifa'] = (utils.getBidIdParameter('IDFA', bid.params).length > utils.getBidIdParameter('ADID', bid.params).length) ? utils.getBidIdParameter('IDFA', bid.params) : utils.getBidIdParameter('ADID', bid.params); + }); + let ebdrBidReq = { + id: requestId, + imp: ebdrImps, + site: { + domain: domain, + page: page + }, + device: { + geo: { + lat: ebdrParams.latitude, + log: ebdrParams.longitude + }, + ifa: ebdrParams.ifa + } + }; + return { + method: 'GET', + url: '//' + rtbServerDomain + '/hb?' + '&zoneid=' + zoneid + '&br=' + encodeURIComponent(JSON.stringify(ebdrBidReq)), + bids: ebdrReq + }; + }, + interpretResponse: function(serverResponse, bidRequest) { + utils.logInfo('Log serverResponse', serverResponse); + utils.logInfo('Log bidRequest', bidRequest); + let ebdrResponseImps = []; + const ebdrResponseObj = serverResponse.body; + if (!ebdrResponseObj || !ebdrResponseObj.seatbid || ebdrResponseObj.seatbid.length === 0 || !ebdrResponseObj.seatbid[0].bid || ebdrResponseObj.seatbid[0].bid.length === 0) { + return []; + } + ebdrResponseObj.seatbid[0].bid.forEach(ebdrBid => { + let responseCPM; + responseCPM = parseFloat(ebdrBid.price); + let adm; + let type; + let _mediaTypes; + let vastURL; + if (bidRequest.bids[ebdrBid.id].mediaTypes == BANNER) { + adm = decodeURIComponent(ebdrBid.adm) + type = 'ad'; + _mediaTypes = BANNER; + } else { + adm = ebdrBid.adm + type = 'vastXml' + _mediaTypes = VIDEO; + if (ebdrBid.nurl) { + vastURL = ebdrBid.nurl; + } + } + let response = { + requestId: ebdrBid.id, + [type]: adm, + mediaType: _mediaTypes, + creativeId: ebdrBid.crid, + cpm: responseCPM, + width: ebdrBid.w, + height: ebdrBid.h, + currency: 'USD', + netRevenue: true, + ttl: 3600 } + if (vastURL) { + response.vastUrl = vastURL; + } + ebdrResponseImps.push(response); + }); + return ebdrResponseImps; + } +} +function getWidthAndHeight(bid) { + let adW = null; + let adH = null; + // Handing old bidder only has size object + if (bid.sizes && bid.sizes.length) { + let sizeArrayLength = bid.sizes.length; + if (sizeArrayLength === 2 && typeof bid.sizes[0] === 'number' && typeof bid.sizes[1] === 'number') { + adW = bid.sizes[0]; + adH = bid.sizes[1]; + } + } + let _mediaTypes = bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER; + if (bid.mediaTypes && bid.mediaTypes[_mediaTypes]) { + if (_mediaTypes == BANNER && bid.mediaTypes[_mediaTypes].sizes && bid.mediaTypes[_mediaTypes].sizes[0] && bid.mediaTypes[_mediaTypes].sizes[0].length === 2) { + adW = bid.mediaTypes[_mediaTypes].sizes[0][0]; + adH = bid.mediaTypes[_mediaTypes].sizes[0][1]; + } else if (_mediaTypes == VIDEO && bid.mediaTypes[_mediaTypes].playerSize && bid.mediaTypes[_mediaTypes].playerSize.length === 2) { + adW = bid.mediaTypes[_mediaTypes].playerSize[0]; + adH = bid.mediaTypes[_mediaTypes].playerSize[1]; + } + } + return [adW, adH]; +} +registerBidder(spec); diff --git a/modules/ebdrBidAdapter.md b/modules/ebdrBidAdapter.md new file mode 100644 index 00000000000..64483797b25 --- /dev/null +++ b/modules/ebdrBidAdapter.md @@ -0,0 +1,53 @@ +# Overview + +``` +Module Name: EngageBDR Bid Adapter +Module Type: Bidder Adapter +Maintainer: tech@engagebdr.com +``` + +# Description + +Adapter that connects to EngageBDR's demand sources. + +# Test Parameters +``` + var adUnits = [{ + code: 'div-gpt-ad-1460505748561-0', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + }, + bids: [{ + bidder: 'ebdr', + params: { + zoneid: '99999', + bidfloor: '1.00', + IDFA:'xxx-xxx', + ADID:'xxx-xxx', + latitude:'34.089811', + longitude:'-118.392805' + } + }] + },{ + code: 'test-video', + mediaTypes: { + video: { + context: 'instream', + playerSize: [300, 250] + } + }, + bids: [{ + bidder: 'ebdr', + params: { + zoneid: '99998', + bidfloor: '1.00', + IDFA:'xxx-xxx', + ADID:'xxx-xxx', + latitude:'34.089811', + longitude:'-118.392805' + } + }] + }]; +``` diff --git a/test/spec/modules/ebdrBidAdapter_spec.js b/test/spec/modules/ebdrBidAdapter_spec.js new file mode 100644 index 00000000000..c5328f9ebb9 --- /dev/null +++ b/test/spec/modules/ebdrBidAdapter_spec.js @@ -0,0 +1,209 @@ +import { expect } from 'chai'; +import { spec } from 'modules/ebdrBidAdapter'; +import { VIDEO, BANNER } from 'src/mediaTypes'; +import * as utils from 'src/utils'; + +describe('ebdrBidAdapter', () => { + let bidRequests; + + beforeEach(() => { + bidRequests = [ + { + code: 'div-gpt-ad-1460505748561-0', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], + } + }, + bidder: 'ebdr', + params: { + zoneid: '99999', + bidfloor: '1.00', + IDFA: 'xxx-xxx', + ADID: 'xxx-xxx', + latitude: '34.089811', + longitude: '-118.392805' + }, + bidId: '2c5e8a1a84522d', + bidderRequestId: '1d0c4017f02458', + auctionId: '9adc85ed-43ee-4a78-816b-52b7e578f314' + }, { + adUnitCode: 'div-gpt-ad-1460505748561-1', + mediaTypes: { + video: { + context: 'instream', + playerSize: [300, 250] + } + }, + bidder: 'ebdr', + params: { + zoneid: '99998', + bidfloor: '1.00', + IDFA: 'xxx-xxx', + ADID: 'xxx-xxx', + latitude: '34.089811', + longitude: '-118.392805' + }, + bidId: '23a01e95856577', + bidderRequestId: '1d0c4017f02458', + auctionId: '9adc85ed-43ee-4a78-816b-52b7e578f314' + } + ]; + }); + + describe('spec.isBidRequestValid', () => { + it('should return true when the required params are passed', () => { + const bidRequest = bidRequests[0]; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return true when the only required param is missing', () => { + const bidRequest = bidRequests[0]; + bidRequest.params = { + zoneid: '99998', + bidfloor: '1.00', + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return true when the "bidfloor" param is missing', () => { + const bidRequest = bidRequests[0]; + bidRequest.params = { + zoneid: '99998', + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return false when no bid params are passed', () => { + const bidRequest = bidRequests[0]; + bidRequest.params = {}; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + + it('should return false when a bid request is not passed', () => { + expect(spec.isBidRequestValid()).to.equal(false); + expect(spec.isBidRequestValid({})).to.equal(false); + }); + }); + + describe('spec.buildRequests', () => { + describe('for banner bids', () => { + it('must handle an empty bid size', () => { + bidRequests[0].mediaTypes = { banner: {} }; + const requests = spec.buildRequests(bidRequests); + const bidRequest = {}; + bidRequest['2c5e8a1a84522d'] = { mediaTypes: BANNER, w: null, h: null }; + expect(requests.bids['2c5e8a1a84522d']).to.deep.equals(bidRequest['2c5e8a1a84522d']); + }); + it('should create a single GET', () => { + bidRequests[0].mediaTypes = { banner: {} }; + bidRequests[1].mediaTypes = { banner: {} }; + const requests = spec.buildRequests(bidRequests); + expect(requests.method).to.equal('GET'); + }); + it('must parse bid size from a nested array', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { banner: {sizes: [[ width, height ]]} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = {}; + data['2c5e8a1a84522d'] = { mediaTypes: BANNER, w: width, h: height }; + expect(requests.bids['2c5e8a1a84522d']).to.deep.equal(data['2c5e8a1a84522d']); + }); + }); + describe('for video bids', () => { + it('must handle an empty bid size', () => { + bidRequests[1].mediaTypes = { video: {} }; + const requests = spec.buildRequests(bidRequests); + const bidRequest = {}; + bidRequest['23a01e95856577'] = { mediaTypes: VIDEO, w: null, h: null }; + expect(requests.bids['23a01e95856577']).to.deep.equals(bidRequest['23a01e95856577']); + }); + + it('should create a GET request for each bid', () => { + const bidRequest = bidRequests[1]; + const requests = spec.buildRequests([ bidRequest ]); + expect(requests.method).to.equal('GET'); + }); + }); + }); + + describe('spec.interpretResponse', () => { + describe('for video bids', () => { + it('should return no bids if the response is not valid', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return a valid video bid response', () => { + const ebdrReq = {bids: {}}; + bidRequests.forEach(bid => { + let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); + ebdrReq.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: '1d0c4017f02458', seatbid: [{bid: [{id: '23a01e95856577', impid: '23a01e95856577', price: 0.81, adid: 'abcde-12345', nurl: 'https://cdn0.bnmla.com/vtest.xml', adm: '\nStatic VASTStatic VAST Tag00:00:15http://www.engagebdr.com/c', adomain: ['advertiserdomain.com'], iurl: '', cid: 'campaign1', crid: 'abcde-12345', w: 300, h: 250}], seat: '19513bcfca8006'}], bidid: '19513bcfca8006', cur: 'USD'}; + const bidResponse = spec.interpretResponse({ body: serverResponse }, ebdrReq); + expect(bidResponse[0]).to.deep.equal({ + requestId: bidRequests[1].bidId, + vastXml: serverResponse.seatbid[0].bid[0].adm, + mediaType: 'video', + 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, + currency: 'USD', + netRevenue: true, + ttl: 3600, + vastUrl: serverResponse.seatbid[0].bid[0].nurl + }); + }); + }); + + describe('for banner bids', () => { + it('should return no bids if the response is not valid', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { banner: {} }; + const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return no bids if the response is empty', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { banner: {} }; + const bidResponse = spec.interpretResponse({ body: [] }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return valid banner bid responses', () => { + const ebdrReq = {bids: {}}; + bidRequests.forEach(bid => { + let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); + ebdrReq.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: '1d0c4017f02458', seatbid: [{bid: [{id: '2c5e8a1a84522d', impid: '2c5e8a1a84522d', price: 0.81, adid: 'abcde-12345', nurl: '', adm: '
', adomain: ['advertiserdomain.com'], iurl: '', cid: 'campaign1', crid: 'abcde-12345', w: 300, h: 250}], seat: '19513bcfca8006'}], bidid: '19513bcfca8006', cur: 'USD', w: 300, h: 250}; + const bidResponse = spec.interpretResponse({ body: serverResponse }, ebdrReq); + expect(bidResponse[0]).to.deep.equal({ + requestId: bidRequests[ 0 ].bidId, + ad: serverResponse.seatbid[0].bid[0].adm, + mediaType: 'banner', + 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, + currency: 'USD', + netRevenue: true, + ttl: 3600 + }); + }); + }); + }); +}); From a34dbe2bf8206ebdaca19bc87e4d36cbdb803444 Mon Sep 17 00:00:00 2001 From: John Salis Date: Thu, 29 Mar 2018 12:26:16 -0400 Subject: [PATCH 0216/1594] Add video targeting to Beachfront adapter (#2321) * Update Beachfront adapter for v1.0 * Revert Beachfront test endpoint * Add Beachfront markdown file * Add mediaTypes to example * Fix formatting * Remove descriptionUrl from bid response * Add banner support to Beachfront adapter * Fix bid response validation * Update display endpoint * Update display request and response to support multiple bids * Remove console log * Added display example to doc * Add support for dnt * add os version to bid request * Use size from bid response * Add secure to bid request * Added display example to doc * fix conflict * Add bidder param for mime types * Bump adapter version * Update test cases * Add mimes param to example --- modules/beachfrontBidAdapter.js | 32 +++++++++++++++---- modules/beachfrontBidAdapter.md | 5 ++- .../spec/modules/beachfrontBidAdapter_spec.js | 25 +++++++++++---- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 20d85ac0b22..ee46195b766 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -2,13 +2,17 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { VIDEO, BANNER } from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.0'; +const ADAPTER_VERSION = '1.1'; const ADAPTER_NAME = 'BFIO_PREBID'; export const VIDEO_ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; export const BANNER_ENDPOINT = '//display.bfmio.com/prebid_display'; +export const VIDEO_TARGETING = ['mimes']; +export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; + export const spec = { code: 'beachfront', supportedMediaTypes: [ VIDEO, BANNER ], @@ -139,8 +143,18 @@ function isVideoBid(bid) { return bid.mediaTypes && bid.mediaTypes.video; } +function getVideoParams(bid) { + return Object.keys(Object(bid.params.video)) + .filter(param => includes(VIDEO_TARGETING, param)) + .reduce((obj, param) => { + obj[ param ] = bid.params.video[ param ]; + return obj; + }, {}); +} + function createVideoRequestData(bid) { let size = getFirstSize(bid); + let video = getVideoParams(bid); let topLocation = utils.getTopWindowLocation(); return { isPrebid: true, @@ -148,18 +162,24 @@ function createVideoRequestData(bid) { domain: document.location.hostname, id: utils.getUniqueIdentifierStr(), imp: [{ - video: { + video: Object.assign({ w: size.w, - h: size.h - }, - bidfloor: bid.params.bidfloor + h: size.h, + mimes: DEFAULT_MIMES + }, video), + bidfloor: bid.params.bidfloor, + secure: topLocation.protocol === 'https:' ? 1 : 0 }], site: { - page: topLocation.host + page: topLocation.href, + domain: topLocation.hostname }, device: { ua: navigator.userAgent, + language: navigator.language, devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, + dnt: getDoNotTrack() ? 1 : 0, + js: 1, geo: {} }, cur: ['USD'] diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index 3ea52c14ab0..6e50737dd98 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -26,7 +26,10 @@ Module that connects to Beachfront's demand sources bidder: 'beachfront', params: { bidfloor: 0.01, - appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' + appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76', + video: { + mimes: ['video/mp4', 'application/javascript'] + } } } ] diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 24b97306388..9ca375d7e20 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT } from 'modules/beachfrontBidAdapter'; +import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import * as utils from 'src/utils'; describe('BeachfrontAdapter', () => { @@ -91,14 +91,15 @@ describe('BeachfrontAdapter', () => { const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; const [ width, height ] = bidRequest.sizes; + const topLocation = utils.getTopWindowLocation(); expect(data.isPrebid).to.equal(true); expect(data.appId).to.equal(bidRequest.params.appId); expect(data.domain).to.equal(document.location.hostname); expect(data.id).to.be.a('string'); - expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); + expect(data.imp[0].video).to.deep.contain({ w: width, h: height, mimes: DEFAULT_MIMES }); expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); - expect(data.site).to.deep.equal({ page: utils.getTopWindowLocation().host }); - expect(data.device).to.deep.contain({ ua: navigator.userAgent }); + expect(data.site).to.deep.equal({ page: topLocation.href, domain: topLocation.hostname }); + expect(data.device).to.deep.contain({ ua: navigator.userAgent, language: navigator.language, js: 1 }); expect(data.cur).to.deep.equal(['USD']); }); @@ -110,7 +111,7 @@ describe('BeachfrontAdapter', () => { bidRequest.mediaTypes = { video: {} }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); + expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); }); it('must parse bid size from a string', () => { @@ -121,7 +122,7 @@ describe('BeachfrontAdapter', () => { bidRequest.mediaTypes = { video: {} }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video).to.deep.equal({ w: width, h: height }); + expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); }); it('must handle an empty bid size', () => { @@ -130,7 +131,17 @@ describe('BeachfrontAdapter', () => { bidRequest.mediaTypes = { video: {} }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video).to.deep.equal({ w: undefined, h: undefined }); + expect(data.imp[0].video).to.deep.contain({ w: undefined, h: undefined }); + }); + + it('must override video targeting params', () => { + const bidRequest = bidRequests[0]; + const mimes = ['video/webm']; + bidRequest.mediaTypes = { video: {} }; + bidRequest.params.video = { mimes }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.imp[0].video).to.deep.contain({ mimes }); }); }); From 7407a44fa8408c8c59a0638aefd77863f91d0cf4 Mon Sep 17 00:00:00 2001 From: varashellov Date: Fri, 30 Mar 2018 19:27:46 +0300 Subject: [PATCH 0217/1594] Platform.io video support (#2318) * Add PlatformioBidAdapter * Update platformioBidAdapter.js * Add files via upload * Update hello_world.html * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Update hello_world.html * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update hello_world.html * Add files via upload * Update platformioBidAdapter ## Type of change - [x] Other ## Description of change 1. RequestURL changes 2. Add placementCode to request params * Update platformioBidAdapter * Update platformioBidAdapter ## Type of change - [x] Other ## Description of change 1. RequestURL changes 2. Add placementCode to request params * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.js Endpoint URL change * Update platformioBidAdapter_spec.js Endpoint URL change * Update platformioBidAdapter_spec.js * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update platformioBidAdapter.md * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.md * Update platformioBidAdapter.md * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.md * Add files via upload * Add files via upload * Delete hello_world.html * Add files via upload --- integrationExamples/gpt/hello_world.html | 194 +++++++++--------- modules/platformioBidAdapter.js | 73 +++++-- modules/platformioBidAdapter.md | 133 +++++++----- .../spec/modules/platformioBidAdapter_spec.js | 76 ++++++- 4 files changed, 312 insertions(+), 164 deletions(-) diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index be181db21b2..a5949b87c56 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -1,98 +1,98 @@ - - - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
-
- -
- + + + + + + + + + + + + + + + +

Prebid.js Test

+
Div-1
+
+ +
+ \ No newline at end of file diff --git a/modules/platformioBidAdapter.js b/modules/platformioBidAdapter.js index 3c53022189f..abb0cf50722 100644 --- a/modules/platformioBidAdapter.js +++ b/modules/platformioBidAdapter.js @@ -1,6 +1,7 @@ - -import {logError, getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; +import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import includes from 'core-js/library/fn/array/includes'; const NATIVE_DEFAULTS = { TITLE_LEN: 100, @@ -10,10 +11,15 @@ const NATIVE_DEFAULTS = { ICON_MIN: 50, }; +const DEFAULT_MIMES = ['video/mp4', 'video/webm', 'application/x-shockwave-flash', 'application/javascript']; +const VIDEO_TARGETING = ['mimes', 'skippable', 'playback_method', 'protocols', 'api']; +const DEFAULT_PROTOCOLS = [2, 3, 5, 6]; +const DEFAULT_APIS = [1, 2]; + export const spec = { code: 'platformio', - supportedMediaTypes: ['banner', 'native'], + supportedMediaTypes: [BANNER, NATIVE, VIDEO], isBidRequestValid: bid => ( !!(bid && bid.params && bid.params.pubId && bid.params.siteId) @@ -69,7 +75,14 @@ function bidResponseAvailable(bidRequest, bidResponse) { nurl = nurl.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); bid['native']['impressionTrackers'] = [nurl]; bid.mediaType = 'native'; - } else { + } else if (idToImpMap[id]['video']) { + bid.vastUrl = idToBidMap[id].adm; + bid.vastUrl = bid.vastUrl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + bid.crid = idToBidMap[id].crid; + bid.width = idToImpMap[id].video.w; + bid.height = idToImpMap[id].video.h; + bid.mediaType = 'video'; + } else if (idToImpMap[id]['banner']) { bid.ad = idToBidMap[id].adm; bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); @@ -78,6 +91,7 @@ function bidResponseAvailable(bidRequest, bidResponse) { bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); bid.width = idToImpMap[id].banner.w; bid.height = idToImpMap[id].banner.h; + bid.mediaType = 'banner'; } bids.push(bid); } @@ -87,26 +101,53 @@ function bidResponseAvailable(bidRequest, bidResponse) { function impression(slot) { return { id: slot.bidId, - banner: banner(slot), + 'banner': banner(slot), 'native': nativeImpression(slot), + 'video': videoImpression(slot), bidfloor: slot.params.bidFloor || '0.000001', tagid: slot.params.placementId.toString(), }; } + +function getSizes(slot) { + const size = slot.params.size.toUpperCase().split('X'); + return { + width: parseInt(size[0]), + height: parseInt(size[1]), + }; +} + function banner(slot) { - if (!slot.nativeParams) { - const size = slot.params.size.toUpperCase().split('X'); - const width = parseInt(size[0]); - const height = parseInt(size[1]); + if (slot.mediaType === 'banner' || utils.deepAccess(slot, 'mediaTypes.banner')) { + const sizes = getSizes(slot); return { - w: width, - h: height, + w: sizes.width, + h: sizes.height, }; - }; + } + return null; +} + +function videoImpression(slot) { + if (slot.mediaType === 'video' || utils.deepAccess(slot, 'mediaTypes.video')) { + const sizes = getSizes(slot); + const video = { + w: sizes.width, + h: sizes.height, + mimes: DEFAULT_MIMES, + protocols: DEFAULT_PROTOCOLS, + api: DEFAULT_APIS, + }; + if (slot.params.video) { + Object.keys(slot.params.video).filter(param => includes(VIDEO_TARGETING, param)).forEach(param => video[param] = slot.params.video[param]); + } + return video; + } + return null; } function nativeImpression(slot) { - if (slot.nativeParams) { + if (slot.mediaType === 'native' || utils.deepAccess(slot, 'mediaTypes.native')) { const assets = []; addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); addAsset(assets, dataAsset(2, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); @@ -169,11 +210,11 @@ function site(bidderRequest) { return { publisher: { id: pubId.toString(), - domain: getTopWindowLocation().hostname, + domain: utils.getTopWindowLocation().hostname, }, id: siteId.toString(), - ref: getTopWindowReferrer(), - page: getTopWindowLocation().href, + ref: utils.getTopWindowReferrer(), + page: utils.getTopWindowLocation().href, } } diff --git a/modules/platformioBidAdapter.md b/modules/platformioBidAdapter.md index 4ef0aa755bf..8233d5cd545 100644 --- a/modules/platformioBidAdapter.md +++ b/modules/platformioBidAdapter.md @@ -1,48 +1,85 @@ -# Overview - -**Module Name**: Platform.io Bidder Adapter -**Module Type**: Bidder Adapter -**Maintainer**: siarhei.kasukhin@platform.io - -# Description - -Connects to Platform.io demand source to fetch bids. -Banner and Native formats are supported. -Please use ```platformio``` as the bidder code. - -# Test Parameters -``` - var adUnits = [{ - code: 'banner-ad-div', - sizes: [[300, 250]], - bids: [{ - bidder: 'platformio', - params: { - pubId: '29521', // required - siteId: '26047', // required - size: '250X250', // required - placementId: '123', // required - bidFloor: '0.001' - } - }] - },{ - code: 'native-ad-div', - sizes: [[1, 1]], - nativeParams: { - title: { required: true, len: 75 }, - image: { required: true }, - body: { len: 200 }, - sponsoredBy: { len: 20 }, - icon: { required: false } - }, - bids: [{ - bidder: 'platformio', - params: { - pubId: '29521', // required - siteId: '26047', // required - placementId: '123', // required - bidFloor: '0.001' - } - }] - }]; -``` +# Overview + +**Module Name**: Platform.io Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: siarhei.kasukhin@platform.io + +# Description + +Connects to Platform.io demand source to fetch bids. +Banner, Native, Video formats are supported. +Please use ```platformio``` as the bidder code. + +# Test Parameters +``` + var adUnits = [{ + code: 'dfp-native-div', + mediaType: 'native', + mediaTypes: { + native: { + title: { + required: true, + len: 75 + }, + image: { + required: true + }, + body: { + len: 200 + }, + icon: { + required: false + } + } + }, + bids: [{ + bidder: 'platformio', + params: { + pubId: '29521', + siteId: '26048', + placementId: '123', + } + }] + }, + { + code: 'dfp-banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250] + ], + } + }, + bids: [{ + bidder: 'platformio', + params: { + pubId: '29521', + siteId: '26049', + size: '300X250', + placementId: '123', + } + }] + }, + { + code: 'dfp-video-div', + sizes: [640, 480], + mediaTypes: { + video: { + context: "instream" + } + }, + bids: [{ + bidder: 'platformio', + params: { + pubId: '29521', + siteId: '26049', + size: '640X480', + placementId: '123', + video: { + skippable: true, + } + } + }] + } + ]; +``` diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index c69a31f1ec5..c9954d4531a 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -1,4 +1,3 @@ - import {expect} from 'chai'; import {spec} from 'modules/platformioBidAdapter'; import {getTopWindowLocation} from 'src/utils'; @@ -8,6 +7,7 @@ describe('Platform.io Adapter Tests', () => { const slotConfigs = [{ placementCode: '/DfpAccount1/slot1', bidId: 'bid12345', + mediaType: 'banner', params: { pubId: '29521', siteId: '26047', @@ -18,6 +18,7 @@ describe('Platform.io Adapter Tests', () => { }, { placementCode: '/DfpAccount2/slot2', bidId: 'bid23456', + mediaType: 'banner', params: { pubId: '29521', siteId: '26047', @@ -29,6 +30,7 @@ describe('Platform.io Adapter Tests', () => { const nativeSlotConfig = [{ placementCode: '/DfpAccount1/slot3', bidId: 'bid12345', + mediaType: 'native', nativeParams: { title: { required: true, len: 200 }, body: {}, @@ -42,6 +44,20 @@ describe('Platform.io Adapter Tests', () => { siteId: '26047' } }]; + const videoSlotConfig = [{ + placementCode: '/DfpAccount1/slot4', + bidId: 'bid12345678', + mediaType: 'video', + video: { + skippable: true + }, + params: { + pubId: '29521', + placementId: '1234567', + siteId: '26047', + size: '640x480' + } + }]; it('Verify build request', () => { const request = spec.buildRequests(slotConfigs); @@ -111,7 +127,7 @@ describe('Platform.io Adapter Tests', () => { expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); expect(request.method).to.equal('POST'); const ortbRequest = JSON.parse(request.data); - // // native impression + // native impression expect(ortbRequest.imp[0].tagid).to.equal('123'); const nativePart = ortbRequest.imp[0]['native']; expect(nativePart).to.not.equal(null); @@ -194,18 +210,72 @@ describe('Platform.io Adapter Tests', () => { expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); }); + it('Verify Video request', () => { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const videoRequest = JSON.parse(request.data); + // site object + expect(videoRequest.site).to.not.equal(null); + expect(videoRequest.site.publisher.id).to.equal('29521'); + expect(videoRequest.site.ref).to.equal(window.top.document.referrer); + expect(videoRequest.site.page).to.equal(getTopWindowLocation().href); + // device object + expect(videoRequest.device).to.not.equal(null); + expect(videoRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(videoRequest.imp[0].tagid).to.equal('1234567'); + expect(videoRequest.imp[0].video).to.not.equal(null); + expect(videoRequest.imp[0].video.w).to.equal(640); + expect(videoRequest.imp[0].video.h).to.equal(480); + expect(videoRequest.imp[0].banner).to.equal(null); + expect(videoRequest.imp[0].native).to.equal(null); + }); + + it('Verify parse video response', () => { + const request = spec.buildRequests(videoSlotConfig); + const videoRequest = JSON.parse(request.data); + const videoResponse = { + seatbid: [{ + bid: [{ + impid: videoRequest.imp[0].id, + price: 1.90, + adm: 'http://vid.example.com/9876', + crid: '510511_754567308' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: videoResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.90); + expect(bid.vastUrl).to.equal('http://vid.example.com/9876'); + expect(bid.crid).to.equal('510511_754567308'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.adId).to.equal('bid12345678'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + it('Verifies bidder code', () => { expect(spec.code).to.equal('platformio'); }); it('Verifies supported media types', () => { - expect(spec.supportedMediaTypes).to.have.lengthOf(2); + expect(spec.supportedMediaTypes).to.have.lengthOf(3); expect(spec.supportedMediaTypes[0]).to.equal('banner'); expect(spec.supportedMediaTypes[1]).to.equal('native'); + expect(spec.supportedMediaTypes[2]).to.equal('video'); }); it('Verifies if bid request valid', () => { expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); + expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); }); }); From e6d1fa81f3280633745a6c038274742ef746dc87 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Fri, 30 Mar 2018 19:38:47 -0400 Subject: [PATCH 0218/1594] Fixes #2258 - cpm bucketing error (#2305) * Fixes #2258 - cpm bucketing error * dealing with imprecise decimal/binary conversions in getCpmTarget() * just added a comment --- src/cpmBucketManager.js | 19 ++++++++++++------- test/spec/cpmBucketManager_spec.js | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/cpmBucketManager.js b/src/cpmBucketManager.js index 0061d35f483..c2250838bcb 100644 --- a/src/cpmBucketManager.js +++ b/src/cpmBucketManager.js @@ -100,7 +100,7 @@ function getCpmStringValue(cpm, config, granularityMultiplier) { } }); if (bucket) { - cpmStr = getCpmTarget(cpm, bucket.increment, bucket.precision, granularityMultiplier); + cpmStr = getCpmTarget(cpm, bucket, granularityMultiplier); } return cpmStr; } @@ -118,12 +118,17 @@ function isValidPriceConfig(config) { return isValid; } -function getCpmTarget(cpm, increment, precision, granularityMultiplier) { - if (typeof precision === 'undefined') { - precision = _defaultPrecision; - } - let bucketSize = 1 / (increment * granularityMultiplier); - return (Math.floor(cpm * bucketSize) / bucketSize).toFixed(precision); +function getCpmTarget(cpm, bucket, granularityMultiplier) { + const precision = typeof bucket.precision !== 'undefined' ? bucket.precision : _defaultPrecision; + const increment = bucket.increment * granularityMultiplier; + const bucketMin = bucket.min * granularityMultiplier; + + // start increments at the bucket min and then add bucket min back to arrive at the correct rounding + let cpmTarget = ((Math.floor((cpm - bucketMin) / increment)) * increment) + bucketMin; + // force to 10 decimal places to deal with imprecise decimal/binary conversions + // (for example 0.1 * 3 = 0.30000000000000004) + cpmTarget = Number(cpmTarget.toFixed(10)); + return cpmTarget.toFixed(precision); } export { getPriceBucketString, isValidPriceConfig }; diff --git a/test/spec/cpmBucketManager_spec.js b/test/spec/cpmBucketManager_spec.js index e5e2d03c66c..3d56299ebfd 100644 --- a/test/spec/cpmBucketManager_spec.js +++ b/test/spec/cpmBucketManager_spec.js @@ -35,6 +35,29 @@ describe('cpmBucketManager', () => { expect(JSON.stringify(output)).to.deep.equal(expected); }); + it('gets the correct custom bucket strings with irregular increment', () => { + let cpm = 14.50908; + let customConfig = { + 'buckets': [{ + 'precision': 4, + 'min': 0, + 'max': 4, + 'increment': 0.01, + }, + { + 'precision': 4, + 'min': 4, + 'max': 18, + 'increment': 0.3, + 'cap': true + } + ] + }; + let expected = '{"low":"5.00","med":"14.50","high":"14.50","auto":"14.50","dense":"14.50","custom":"14.5000"}'; + let output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + }); + it('gets the correct custom bucket strings in non-USD currency', () => { let cpm = 16.50908 * 110.49; let customConfig = { From 0397649764d2ebb0189ca0ebe55f63d6bda8eace Mon Sep 17 00:00:00 2001 From: MIGOdanis Date: Tue, 3 Apr 2018 02:02:09 +0800 Subject: [PATCH 0219/1594] Add CLICKFORCE Bid Adapter (updated to new spec) (#2053) * Add CLICKFORCE Bid Adapter to modules * bug fix * change adapter to Prebid 1.0 spec * bug fix * change ENDPOINT_URL --- modules/clickforceBidAdapter.js | 66 +++++++++++++++++++++++++++++++++ modules/clickforceBidAdapter.md | 31 ++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 modules/clickforceBidAdapter.js create mode 100644 modules/clickforceBidAdapter.md diff --git a/modules/clickforceBidAdapter.js b/modules/clickforceBidAdapter.js new file mode 100644 index 00000000000..9267540cb61 --- /dev/null +++ b/modules/clickforceBidAdapter.js @@ -0,0 +1,66 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'clickforce'; +const ENDPOINT_URL = '//ad.doublemax.net/adserver/prebid.json?cb=' + new Date().getTime() + '&hb=1&ver=1.21'; + +export const spec = { + code: BIDDER_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 bid && bid.params && !!bid.params.zone; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests) { + const bidParams = []; + utils._each(validBidRequests, function(bid) { + bidParams.push({ + z: bid.params.zone, + bidId: bid.bidId + }); + }); + return { + method: 'POST', + url: ENDPOINT_URL, + data: bidParams + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param {*} bidRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidRequest) { + const cfResponses = []; + utils._each(serverResponse.body, function(response) { + cfResponses.push({ + requestId: response.requestId, + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.creativeId, + currency: response.currency, + netRevenue: response.netRevenue, + ttl: response.ttl, + ad: response.tag + }); + }); + return cfResponses; + } +}; +registerBidder(spec); diff --git a/modules/clickforceBidAdapter.md b/modules/clickforceBidAdapter.md new file mode 100644 index 00000000000..912f9132331 --- /dev/null +++ b/modules/clickforceBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +``` +Module Name: CLICKFORCE Bid Adapter +Module Type: Bidder Adapter +Maintainer: danis@clickforce.com.tw +``` + +# Description + +You can use this adapter to get a bid from clickforce. + +About us : http://www.clickforce.com.tw/en/ + +It requires adapters to start bidding and no extra setting is needed. If you'd like to apply for placements, please contact: + +joey@clickforce.com.tw (MR. Joey) + +# Test Parameters +``` + var adUnits = [{ + code: 'banner-ad-div', + sizes: [[300, 250]], + bids: [{ + bidder: "clickforce", + params: { + zone: "6682", + } + }] + }]; +``` From 4bdc91c9d4e875028d87acc5a289915f64ea93d5 Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Tue, 3 Apr 2018 01:28:01 +0530 Subject: [PATCH 0220/1594] Adding onTimeout function in Adapter Spec (#2279) * timeout bidder spec init * refactored * refactored * test case added for getUserConfiguredParams * added more test cases * timeout added as param * minor changes * replacing for..of with forEach * Update utils_spec.js * trailing spaces removed --- src/adaptermanager.js | 23 +++++++++++++++++++++++ src/auction.js | 7 ++++++- src/utils.js | 16 +++++++++++++++- test/spec/utils_spec.js | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 6ff2387cca2..0ac8ad46911 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -437,3 +437,26 @@ exports.getBidAdapter = function(bidder) { exports.setS2STestingModule = function (module) { s2sTestingModule = module; }; + +exports.callTimedOutBidders = function(adUnits, timedOutBidders, cbTimeout) { + timedOutBidders = timedOutBidders.map((timedOutBidder) => { + // Adding user configured params & timeout to timeout event data + timedOutBidder.params = utils.getUserConfiguredParams(adUnits, timedOutBidder.adUnitCode, timedOutBidder.bidder); + timedOutBidder.timeout = cbTimeout; + return timedOutBidder; + }); + timedOutBidders = utils.groupBy(timedOutBidders, 'bidder'); + + Object.keys(timedOutBidders).forEach((bidder) => { + try { + const adapter = _bidderRegistry[bidder]; + const spec = adapter.getSpec(); + if (spec && spec.onTimeout && typeof spec.onTimeout === 'function') { + utils.logInfo(`Invoking ${bidder}.onTimeout`); + spec.onTimeout(timedOutBidders[bidder]); + } + } catch (e) { + utils.logWarn(`Error calling onTimeout of ${bidder}`); + } + }); +} diff --git a/src/auction.js b/src/auction.js index 78595aaf244..3c9e9bf86f1 100644 --- a/src/auction.js +++ b/src/auction.js @@ -114,9 +114,10 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } if (_callback != null) { + let timedOutBidders = []; if (timedOut) { utils.logMessage(`Auction ${_auctionId} timedOut`); - const timedOutBidders = getTimedOutBids(_bidderRequests, _bidsReceived); + timedOutBidders = getTimedOutBids(_bidderRequests, _bidsReceived); if (timedOutBidders.length) { events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); } @@ -134,6 +135,10 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } catch (e) { utils.logError('Error executing bidsBackHandler', null, e); } finally { + // Calling timed out bidders + if (timedOutBidders.length) { + adaptermanager.callTimedOutBidders(adUnits, timedOutBidders, _timeout); + } // Only automatically sync if the publisher has not chosen to "enableOverride" let userSyncConfig = config.getConfig('userSync') || {}; if (!userSyncConfig.enableOverride) { diff --git a/src/utils.js b/src/utils.js index 5436a4aa167..701fd37115a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -846,7 +846,21 @@ export function getBidderRequest(bidRequests, bidder, adUnitCode) { .filter(bid => bid.bidder === bidder && bid.adUnitCode === adUnitCode).length > 0; }) || { start: null, auctionId: null }; } - +/** + * Returns user configured bidder params from adunit + * @param {object} adunits + * @param {string} adunit code + * @param {string} bidder code + * @return {Array} user configured param for the given bidder adunit configuration + */ +export function getUserConfiguredParams(adUnits, adUnitCode, bidder) { + return adUnits + .filter(adUnit => adUnit.code === adUnitCode) + .map((adUnit) => adUnit.bids) + .reduce(flatten, []) + .filter((bidderData) => bidderData.bidder === bidder) + .map((bidderData) => bidderData.params || {}); +} /** * Returns the origin */ diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 7597e389ee9..12980307272 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -622,6 +622,47 @@ describe('Utils', function () { expect(adUnitCopy[0].renderer.render).to.be.a('function'); }); }); + + describe('getUserConfiguredParams', () => { + const adUnits = [{ + code: 'adUnit1', + bids: [{ + bidder: 'bidder1', + params: { + key1: 'value1' + } + }, { + bidder: 'bidder2' + }] + }]; + + it('should return params configured', () => { + const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder1'); + const expected = [{ + key1: 'value1' + }]; + assert.deepEqual(output, expected); + }); + + it('should return array containting empty object, if bidder present and no params are configured', () => { + const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder2'); + const expected = [{}]; + assert.deepEqual(output, expected); + }); + + it('should return empty array, if bidder is not present', () => { + const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder3'); + const expected = []; + assert.deepEqual(output, expected); + }); + + it('should return empty array, if adUnit is not present', () => { + const output = utils.getUserConfiguredParams(adUnits, 'adUnit2', 'bidder3'); + const expected = []; + assert.deepEqual(output, expected); + }); + }); + describe('getTopWindowLocation', () => { let sandbox; From 4930622a2ee192c7782c761ec9b9b1b8f1fa2da8 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 2 Apr 2018 16:15:21 -0400 Subject: [PATCH 0221/1594] Log error returned by PBS (#2335) --- modules/prebidServerBidAdapter.js | 3 ++ .../modules/prebidServerBidAdapter_spec.js | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index ebb630ceb7a..39e3b906b47 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -317,6 +317,9 @@ const LEGACY_PROTOCOL = { if (bidder.no_cookie) { doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder); } + if (bidder.error) { + utils.logWarn(`Prebid Server returned error: '${bidder.error}' for ${bidder.bidder}`); + } }); } diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 383c599a133..837b5ca60e8 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -358,6 +358,15 @@ const RESPONSE_OPENRTB_VIDEO = { }, }; +const RESPONSE_UNSUPPORTED_BIDDER = { + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'status': 'OK', + 'bidder_status': [{ + 'bidder': '33Across', + 'error': 'Unsupported bidder' + }] +}; + describe('S2S Adapter', () => { let adapter, addBidResponse = sinon.spy(), @@ -559,6 +568,7 @@ describe('S2S Adapter', () => { describe('response handler', () => { let server; + let logWarnSpy; beforeEach(() => { server = sinon.fakeServer.create(); @@ -569,6 +579,7 @@ describe('S2S Adapter', () => { sinon.stub(utils, 'getBidRequest').returns({ bidId: '123' }); + logWarnSpy = sinon.spy(utils, 'logWarn'); }); afterEach(() => { @@ -578,6 +589,7 @@ describe('S2S Adapter', () => { utils.insertUserSyncIframe.restore(); utils.logError.restore(); cookie.cookieSet.restore(); + logWarnSpy.restore(); }); // TODO: test dependent on pbjs_api_spec. Needs to be isolated @@ -810,6 +822,25 @@ describe('S2S Adapter', () => { expect(response).to.have.property('adId', '123'); expect(response).to.have.property('cpm', 10); }); + + it('should log warning for unsupported bidder', () => { + server.respondWith(JSON.stringify(RESPONSE_UNSUPPORTED_BIDDER)); + + const s2sConfig = Object.assign({}, CONFIG, { + bidders: ['33Across'] + }); + + const _config = { + s2sConfig: s2sConfig, + } + + config.setConfig(_config); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(logWarnSpy); + }); }); describe('s2sConfig', () => { From a6b42d4d1e5300fb52d342496fb723f2433dfd6f Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 3 Apr 2018 09:18:49 -0400 Subject: [PATCH 0222/1594] Fixes #2276 - video.playerSize and Size Mapping not working together (#2311) * initial commit - fix to make playerSize and sizeConfig work * removed commented from testing * adding support to use [300, 600] syntax in video.playerSize field --- src/adaptermanager.js | 15 ++++-- test/spec/unit/core/adapterManager_spec.js | 53 ++++++++++++---------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 0ac8ad46911..bb638985684 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -216,7 +216,11 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, }; exports.checkBidRequestSizes = (adUnits) => { - Array.prototype.forEach.call(adUnits, adUnit => { + function isArrayOfNums(val) { + return Array.isArray(val) && val.length === 2 && utils.isInteger(val[0]) && utils.isInteger(val[1]); + } + + adUnits.forEach((adUnit) => { if (adUnit.sizes) { utils.logWarn('Usage of adUnits.sizes will eventually be deprecated. Please define size dimensions within the corresponding area of the mediaTypes. (eg mediaTypes.banner.sizes).'); } @@ -235,10 +239,15 @@ exports.checkBidRequestSizes = (adUnits) => { if (mediaTypes && mediaTypes.video) { const video = mediaTypes.video; if (video.playerSize) { - if (Array.isArray(video.playerSize) && video.playerSize.length === 2 && utils.isInteger(video.playerSize[0]) && utils.isInteger(video.playerSize[1])) { + if (Array.isArray(video.playerSize) && video.playerSize.length === 1 && video.playerSize.every(isArrayOfNums)) { adUnit.sizes = video.playerSize; + } else if (isArrayOfNums(video.playerSize)) { + let newPlayerSize = []; + newPlayerSize.push(video.playerSize); + utils.logInfo(`Transforming video.playerSize from ${video.playerSize} to ${newPlayerSize} so it's in the proper format.`); + adUnit.sizes = video.playerSize = newPlayerSize; } else { - 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.'); + 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 adUnit.mediaTypes.video.playerSize; } } diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 824d66305b8..d11dfc02c4c 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -857,10 +857,15 @@ describe('adapterManager tests', () => { describe('isValidBidRequest', () => { describe('positive tests for validating bid request', () => { - beforeEach(() => {}); + beforeEach(() => { + sinon.stub(utils, 'logInfo'); + }); - afterEach(() => {}); - it('should main adUnit structure and adUnits.sizes is replaced', () => { + afterEach(() => { + utils.logInfo.restore(); + }); + + it('should maintain adUnit structure and adUnits.sizes is replaced', () => { let fullAdUnit = [{ sizes: [[300, 250], [300, 600]], mediaTypes: { @@ -868,7 +873,7 @@ describe('adapterManager tests', () => { sizes: [[300, 250]] }, video: { - playerSize: [640, 480] + playerSize: [[640, 480]] }, native: { image: { @@ -882,8 +887,8 @@ describe('adapterManager tests', () => { } }]; let result = checkBidRequestSizes(fullAdUnit); - expect(result[0].sizes).to.deep.equal([640, 480]); - expect(result[0].mediaTypes.video.playerSize).to.deep.equal([640, 480]); + expect(result[0].sizes).to.deep.equal([[640, 480]]); + expect(result[0].mediaTypes.video.playerSize).to.deep.equal([[640, 480]]); expect(result[0].mediaTypes.native.image.sizes).to.deep.equal([150, 150]); expect(result[0].mediaTypes.native.icon.sizes).to.deep.equal([75, 75]); expect(result[0].mediaTypes.native.image.aspect_ratios).to.deep.equal([140, 140]); @@ -916,7 +921,7 @@ describe('adapterManager tests', () => { mediaTypes: { video: { context: 'outstream', - playerSize: [400, 350] + playerSize: [[400, 350]] }, native: { image: { @@ -927,8 +932,22 @@ describe('adapterManager tests', () => { } }]; result = checkBidRequestSizes(mixedAdUnit); - expect(result[0].sizes).to.deep.equal([400, 350]); + expect(result[0].sizes).to.deep.equal([[400, 350]]); + expect(result[0].mediaTypes.video).to.exist; + + let altVideoPlayerSize = [{ + sizes: [[600, 600]], + mediaTypes: { + video: { + playerSize: [640, 480] + } + } + }]; + result = checkBidRequestSizes(altVideoPlayerSize); + expect(result[0].sizes).to.deep.equal([[640, 480]]); + expect(result[0].mediaTypes.video.playerSize).to.deep.equal([[640, 480]]); expect(result[0].mediaTypes.video).to.exist; + sinon.assert.calledOnce(utils.logInfo); }); }); @@ -959,7 +978,7 @@ describe('adapterManager tests', () => { sizes: [[600, 600]], mediaTypes: { video: { - playerSize: '600x400' + playerSize: ['600x400'] } } }]; @@ -973,7 +992,7 @@ describe('adapterManager tests', () => { sizes: [[600, 600]], mediaTypes: { video: { - playerSize: ['300', '200'] + playerSize: [['300', '200']] } } }]; @@ -983,20 +1002,6 @@ describe('adapterManager tests', () => { expect(result[0].mediaTypes.video).to.exist; sinon.assert.called(utils.logError); - let badVideo3 = [{ - sizes: [[600, 600]], - mediaTypes: { - video: { - playerSize: [[640, 480]] - } - } - }]; - result = checkBidRequestSizes(badVideo3); - expect(result[0].sizes).to.deep.equal([[600, 600]]); - expect(result[0].mediaTypes.video.playerSize).to.be.undefined; - expect(result[0].mediaTypes.video).to.exist; - sinon.assert.called(utils.logError); - let badNativeImgSize = [{ mediaTypes: { native: { From 749e3c426df865e95024982b7ef834ae6a587008 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 3 Apr 2018 12:22:16 -0400 Subject: [PATCH 0223/1594] fix issue #2315 sizeMapping not working with s2s requests (#2332) * initial commit to fix issue #2315 * moved transformHeightWidth function to prebidServerBidAdapter --- modules/prebidServerBidAdapter.js | 15 +++++++++++ src/adaptermanager.js | 27 ++++++++----------- .../modules/prebidServerBidAdapter_spec.js | 20 +++----------- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 39e3b906b47..06e5cff6503 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -266,6 +266,20 @@ function _appendSiteAppDevice(request) { } } +function transformHeightWidth(adUnit) { + let sizesObj = []; + let sizes = utils.parseSizesInput(adUnit.sizes); + sizes.forEach(size => { + let heightWidth = size.split('x'); + let sizeObj = { + 'w': parseInt(heightWidth[0]), + 'h': parseInt(heightWidth[1]) + }; + sizesObj.push(sizeObj); + }); + return sizesObj; +} + /* * Protocol spec for legacy endpoint * e.g., https:///v1/auction @@ -275,6 +289,7 @@ const LEGACY_PROTOCOL = { buildRequest(s2sBidRequest, adUnits) { // pbs expects an ad_unit.video attribute if the imp is video adUnits.forEach(adUnit => { + adUnit.sizes = transformHeightWidth(adUnit); const videoMediaType = utils.deepAccess(adUnit, 'mediaTypes.video'); if (videoMediaType) { adUnit.video = Object.assign({}, videoMediaType); diff --git a/src/adaptermanager.js b/src/adaptermanager.js index bb638985684..58d9c3b79d8 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -94,27 +94,11 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { }, []).reduce(flatten, []).filter(val => val !== ''); } -function transformHeightWidth(adUnit) { - let sizesObj = []; - let sizes = utils.parseSizesInput(adUnit.sizes); - sizes.forEach(size => { - let heightWidth = size.split('x'); - let sizeObj = { - 'w': parseInt(heightWidth[0]), - 'h': parseInt(heightWidth[1]) - }; - sizesObj.push(sizeObj); - }); - return sizesObj; -} - function getAdUnitCopyForPrebidServer(adUnits) { let adaptersServerSide = _s2sConfig.bidders; let adUnitsCopy = utils.deepClone(adUnits); adUnitsCopy.forEach((adUnit) => { - adUnit.sizes = transformHeightWidth(adUnit); - // filter out client side bids adUnit.bids = adUnit.bids.filter((bid) => { return includes(adaptersServerSide, bid.bidder) && (!doingS2STesting() || bid.finalSource !== s2sTestingModule.CLIENT); @@ -290,6 +274,17 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { const s2sAdapter = _bidderRegistry[_s2sConfig.adapter]; let tid = serverBidRequests[0].tid; let adUnitsS2SCopy = serverBidRequests[0].adUnitsS2SCopy; + adUnitsS2SCopy.forEach((adUnitCopy) => { + let validBids = adUnitCopy.bids.filter((bid) => { + return serverBidRequests.find(request => { + return request.bidderCode === bid.bidder && + request.bids.find((reqBid) => reqBid.adUnitCode === adUnitCopy.code); + }); + }); + adUnitCopy.bids = validBids; + }); + + adUnitsS2SCopy = adUnitsS2SCopy.filter(adUnitCopy => adUnitCopy.bids.length > 0); if (s2sAdapter) { let s2sBidRequest = {tid, 'ad_units': adUnitsS2SCopy}; diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 837b5ca60e8..d525db857bc 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -27,16 +27,7 @@ const REQUEST = { 'ad_units': [ { 'code': 'div-gpt-ad-1460505748561-0', - 'sizes': [ - { - 'w': 300, - 'h': 250 - }, - { - 'w': 300, - 'h': 600 - } - ], + 'sizes': [[300, 250], [300, 600]], 'mediaTypes': { 'banner': { 'sizes': [[ 300, 250 ], [ 300, 300 ]] @@ -68,7 +59,7 @@ const VIDEO_REQUEST = { 'ad_units': [ { 'code': 'div-gpt-ad-1460505748561-0', - 'sizes': [{ 'w': 640, 'h': 480 }], + 'sizes': [640, 480], 'mediaTypes': { 'video': { 'playerSize': [[ 640, 480 ]], @@ -103,12 +94,7 @@ const BID_REQUESTS = [ 'bid_id': '123', 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', - 'sizes': [ - { - 'w': 300, - 'h': 250 - } - ], + 'sizes': [300, 250], 'bidId': '259fb43aaa06c1', 'bidderRequestId': '3d1063078dfcc8', 'auctionId': '173afb6d132ba3' From 61c0beea4a563efecb1b0e663d64c8d10a63e88a Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Tue, 3 Apr 2018 12:47:50 -0400 Subject: [PATCH 0224/1594] InSkin Bid Adapter: add user syncing (#2287) --- modules/inskinBidAdapter.js | 22 +++++++++++++++++++++- test/spec/modules/inskinBidAdapter_spec.js | 14 ++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js index 710efc4498c..abd94f71a94 100644 --- a/modules/inskinBidAdapter.js +++ b/modules/inskinBidAdapter.js @@ -151,7 +151,27 @@ export const spec = { }, getUserSyncs: function(syncOptions) { - return []; + const userSyncs = []; + + if (syncOptions.pixelEnabled) { + userSyncs.push({ + type: 'image', + url: 'https://e.serverbid.com/udb/9969/match?redir=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fpool%2Fset%2Fi.gif%3FpoolId%3D9969%26poolKey%3D' + }); + userSyncs.push({ + type: 'image', + url: 'https://ssum.casalemedia.com/usermatchredir?s=185638&cb=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fsync%2Fi.gif%3FpartnerId%3D1%26userId%3D' + }); + } + + if (syncOptions.iframeEnabled) { + userSyncs.push({ + type: 'iframe', + url: 'https://ssum-sec.casalemedia.com/usermatch?s=184665&cb=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fsync%2Fi.gif%3FpartnerId%3D1%26userId%3D' + }); + } + + return userSyncs; } }; diff --git a/test/spec/modules/inskinBidAdapter_spec.js b/test/spec/modules/inskinBidAdapter_spec.js index ee5064dca5a..f22e6242d53 100644 --- a/test/spec/modules/inskinBidAdapter_spec.js +++ b/test/spec/modules/inskinBidAdapter_spec.js @@ -236,18 +236,24 @@ describe('InSkin BidAdapter', () => { }); }); describe('getUserSyncs', () => { - let syncOptions = {'iframeEnabled': true}; - it('handles empty sync options', () => { let opts = spec.getUserSyncs({}); expect(opts).to.be.empty; }); - it('should always return empty array', () => { + it('should return two sync urls if pixel syncs are enabled', () => { + let syncOptions = {'pixelEnabled': true}; let opts = spec.getUserSyncs(syncOptions); - expect(opts).to.be.empty; + expect(opts.length).to.equal(2); + }); + + it('should return three sync urls if pixel and iframe syncs are enabled', () => { + let syncOptions = {'iframeEnabled': true, 'pixelEnabled': true}; + let opts = spec.getUserSyncs(syncOptions); + + expect(opts.length).to.equal(3); }); }); }); From f4635450e8147babc4f834a6ec87372eb397b7ea Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 3 Apr 2018 12:49:36 -0400 Subject: [PATCH 0225/1594] Fixes issue #2327 - getBidLandScapeTargeting not using adUnitCode argument (#2336) * initial commit to fix issue 2327 * switched to different include function --- src/targeting.js | 6 ++++- test/spec/unit/core/targeting_spec.js | 37 ++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index 54324265a21..852a45b6bac 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -328,7 +328,11 @@ export function newTargeting(auctionManager) { }); // populate targeting keys for the remaining bids return bids.map(bid => { - if (bid.adserverTargeting) { + if ( + bid.adserverTargeting && adUnitCodes && + ((utils.isArray(adUnitCodes) && includes(adUnitCodes, bid.adUnitCode)) || + (typeof adUnitCodes === 'string' && bid.adUnitCode === adUnitCodes)) + ) { return { [bid.adUnitCode]: getTargetingMap(bid, standardKeys.filter( key => typeof bid.adserverTargeting[key] !== 'undefined') diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 0954dda6325..c7eb3623e08 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -66,6 +66,36 @@ const bid2 = { 'ttl': 300 }; +const bid3 = { + 'bidderCode': 'rubicon', + 'width': '300', + 'height': '600', + 'statusMessage': 'Bid available', + 'adId': '48747745', + 'cpm': 0.75, + 'ad': 'markup', + 'ad_id': '3163950', + 'sizeId': '15', + 'requestTimestamp': 1454535718610, + 'responseTimestamp': 1454535724863, + 'timeToRespond': 123, + 'pbLg': '0.75', + 'pbMg': '0.75', + 'pbHg': '0.75', + 'adUnitCode': '/123456/header-bid-tag-1', + 'bidder': 'rubicon', + 'size': '300x600', + 'adserverTargeting': { + 'hb_bidder': 'rubicon', + 'hb_adid': '48747745', + 'hb_pb': '0.75', + 'foobar': '300x600' + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 +}; + describe('targeting tests', () => { describe('getAllTargeting', () => { let amBidsReceivedStub; @@ -75,7 +105,7 @@ describe('targeting tests', () => { beforeEach(() => { $$PREBID_GLOBAL$$._sendAllBids = false; amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived').callsFake(function() { - return [bid1, bid2]; + return [bid1, bid2, bid3]; }); amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; @@ -92,9 +122,14 @@ describe('targeting tests', () => { it('selects the top bid when _sendAllBids true', () => { config.setConfig({ enableSendAllBids: true }); let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // we should only get the targeting data for the one requested adunit + expect(Object.keys(targeting).length).to.equal(1); + let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf('hb_pb_') != -1) // we shouldn't get more than 1 key for hb_pb_${bidder} expect(sendAllBidCpm.length).to.equal(1); + // expect the winning CPM to be equal to the sendAllBidCPM expect(targeting['/123456/header-bid-tag-0']['hb_pb_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0']['hb_pb']); }); From d8c2a4890fcb67a42c112f33daef96cd3bf23790 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 3 Apr 2018 12:50:56 -0400 Subject: [PATCH 0226/1594] initial commit to fix issue #2291 (#2308) --- modules/dfpAdServerVideo.js | 5 +++-- test/spec/modules/dfpAdServerVideo_spec.js | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index d029c6d07a0..cc285ca4aa7 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -70,7 +70,7 @@ export default function buildDfpVideoUrl(options) { if (options.url) { // when both `url` and `params` are given, parsed url will be overwriten // with any matching param components - urlComponents = parse(options.url); + urlComponents = parse(options.url, {noDecodeWholeURL: true}); if (isEmpty(options.params)) { return buildUrlFromAdserverUrlComponents(urlComponents, bid); @@ -126,7 +126,8 @@ function buildUrlFromAdserverUrlComponents(components, bid) { const customParams = Object.assign({}, adserverTargeting, ); - components.search.cust_params = encodeURIComponent(formatQS(customParams)); + const encodedCustomParams = encodeURIComponent(formatQS(customParams)); + components.search.cust_params = (components.search.cust_params) ? components.search.cust_params + '%26' + encodedCustomParams : encodedCustomParams; return buildUrl(components); } diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 4cc6f3b93bd..be51953169c 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -130,6 +130,26 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('my_targeting', 'foo'); }); + it('should merge the user-provided cust-params with the default ones when using url object', () => { + const bidCopy = Object.assign({ }, bid); + bidCopy.adserverTargeting = { + hb_adid: 'ad_id', + }; + + const url = parse(buildDfpVideoUrl({ + adUnit: adUnit, + bid: bidCopy, + url: 'https://video.adserver.example/ads?sz=640x480&iu=/123/aduniturl&impl=s&cust_params=section%3dblog%26mykey%3dmyvalue' + })); + + const queryObject = parseQS(url.query); + const customParams = parseQS('?' + decodeURIComponent(queryObject.cust_params)); + + expect(customParams).to.have.property('hb_adid', 'ad_id'); + expect(customParams).to.have.property('section', 'blog'); + expect(customParams).to.have.property('mykey', 'myvalue'); + }); + it('should not overwrite an existing description_url for object input and cache disabled', () => { const bidCopy = Object.assign({}, bid); bidCopy.vastUrl = 'vastUrl.example'; From b633478f3100158adc78b4730892d0ee4f73d66e Mon Sep 17 00:00:00 2001 From: Roffray Date: Tue, 3 Apr 2018 19:46:16 +0200 Subject: [PATCH 0227/1594] Add: vuble adapter handles dealId (#2322) * Add: vuble adapter handles dealId * Fix: new publihser id vuble --- modules/vubleBidAdapter.js | 1 + modules/vubleBidAdapter.md | 4 ++-- test/spec/modules/vubleBidAdapter_spec.js | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/vubleBidAdapter.js b/modules/vubleBidAdapter.js index 764ea293417..a61b80777fc 100644 --- a/modules/vubleBidAdapter.js +++ b/modules/vubleBidAdapter.js @@ -100,6 +100,7 @@ export const spec = { height: bid.data.height, ttl: TTL, creativeId: responseBody.creativeId, + dealId: responseBody.dealId, netRevenue: true, currency: CURRENCIES[bid.data.env], vastUrl: responseBody.url, diff --git a/modules/vubleBidAdapter.md b/modules/vubleBidAdapter.md index 4e066b9dd8a..6bd8d3f779a 100644 --- a/modules/vubleBidAdapter.md +++ b/modules/vubleBidAdapter.md @@ -26,7 +26,7 @@ Module that connects to Vuble's demand sources bidder: "vuble", params: { env: 'net', - pubId: '3', + pubId: '18', zoneId: '12345', referrer: "http://www.vuble.tv/", // optional floorPrice: 5.00 // optional @@ -47,7 +47,7 @@ Module that connects to Vuble's demand sources bidder: "vuble", params: { env: 'net', - pubId: '3', + pubId: '18', zoneId: '12345', referrer: "http://www.vuble.tv/", // optional floorPrice: 5.00 // optional diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 4f37d1096fc..61f00ef2c3d 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -174,7 +174,8 @@ describe('VubleAdapter', () => { status: 'ok', cpm: 5.00, creativeId: '2468', - url: 'https//player.mediabong.net/prebid/ad/a1b2c3d4' + url: 'https//player.mediabong.net/prebid/ad/a1b2c3d4', + dealId: 'MDB-TEST-1357' } }; // bid Request @@ -200,6 +201,7 @@ describe('VubleAdapter', () => { height: '360', ttl: 60, creativeId: '2468', + dealId: 'MDB-TEST-1357', netRevenue: true, currency: 'USD', vastUrl: 'https//player.mediabong.net/prebid/ad/a1b2c3d4', From f2d15b6382cf70293b6e1f9fe2f514c191027dc1 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 3 Apr 2018 14:08:33 -0400 Subject: [PATCH 0228/1594] change utils.js unit tests to fix browserstack errors (#2337) * alter utils unit tests * added comment to clarify the change --- test/spec/utils_spec.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 12980307272..d44028e7554 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -1,4 +1,5 @@ import { getAdServerTargeting } from 'test/fixtures/fixtures'; +import { expect } from 'chai'; var assert = require('assert'); var utils = require('src/utils'); @@ -720,10 +721,11 @@ describe('Utils', function () { expect(topWindowLocation.href).to.equal('https://www.google.com/a/umich.edu/acs'); expect(topWindowLocation.protocol).to.equal('https'); expect(topWindowLocation.hostname).to.equal('www.google.com'); - expect(topWindowLocation.port).to.equal(0); expect(topWindowLocation.hash).to.equal(''); expect(topWindowLocation.search).to.equal(''); - expect(topWindowLocation.host).to.equal('www.google.com'); + // note IE11 returns the default secure port, so we look for this alternate value as well in these tests + expect(topWindowLocation.port).to.be.oneOf([0, 443]); + expect(topWindowLocation.host).to.be.oneOf(['www.google.com', 'www.google.com:443']); }); it('returns parsed referrer string if in iFrame but no ancestorOrigins', () => { @@ -740,11 +742,12 @@ describe('Utils', function () { expect(topWindowLocation.href).to.equal('https://www.example.com/'); expect(topWindowLocation.protocol).to.equal('https'); expect(topWindowLocation.hostname).to.equal('www.example.com'); - expect(topWindowLocation.port).to.equal(0); expect(topWindowLocation.pathname).to.equal('/'); expect(topWindowLocation.hash).to.equal(''); expect(topWindowLocation.search).to.equal(''); - expect(topWindowLocation.host).to.equal('www.example.com'); + // note IE11 returns the default secure port, so we look for this alternate value as well in these tests + expect(topWindowLocation.port).to.be.oneOf([0, 443]); + expect(topWindowLocation.host).to.be.oneOf(['www.example.com', 'www.example.com:443']); }); }); }); From 3d21e42c220e97e3ce1c649fafd2adde92981814 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 3 Apr 2018 14:55:43 -0400 Subject: [PATCH 0229/1594] change find method to polyfill version (#2338) --- src/adaptermanager.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 58d9c3b79d8..cef1635f100 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -7,6 +7,7 @@ import { newBidder } from './adapters/bidderFactory'; import { ajaxBuilder } from 'src/ajax'; import { config, RANDOM } from 'src/config'; import includes from 'core-js/library/fn/array/includes'; +import find from 'core-js/library/fn/array/find'; var utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); @@ -276,9 +277,9 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { let adUnitsS2SCopy = serverBidRequests[0].adUnitsS2SCopy; adUnitsS2SCopy.forEach((adUnitCopy) => { let validBids = adUnitCopy.bids.filter((bid) => { - return serverBidRequests.find(request => { + return find(serverBidRequests, request => { return request.bidderCode === bid.bidder && - request.bids.find((reqBid) => reqBid.adUnitCode === adUnitCopy.code); + find(request.bids, (reqBid) => reqBid.adUnitCode === adUnitCopy.code); }); }); adUnitCopy.bids = validBids; From e57969b1a8ef6d67fde6c32503c8576fcae9f973 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 3 Apr 2018 15:42:39 -0400 Subject: [PATCH 0230/1594] Prebid 1.7.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f742753c7ae..99904cc76d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.7.0-pre", + "version": "1.7.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 216f01cf88b752ccf303dd6cd01ca33766327e7a Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 3 Apr 2018 15:54:37 -0400 Subject: [PATCH 0231/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 99904cc76d0..1c9d1d91edd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.7.0", + "version": "1.8.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From bd5aaef131b0e9b04b63b27257ae16476ae80e54 Mon Sep 17 00:00:00 2001 From: NLopezMad <22349934+NLopezMad@users.noreply.github.com> Date: Wed, 4 Apr 2018 21:01:16 +0200 Subject: [PATCH 0232/1594] New adapter madvertise (#2163) * New adapter madvertise * Update madvertiseBidAdapter.js remove aliases * Update madvertiseBidAdapter.js use parseSizesInput method * fix test parseSizesInput * fix lint parseSizesInput * remove seeanAd feature * remove console.log --- modules/madvertiseBidAdapter.js | 90 ++++++++++ modules/madvertiseBidAdapter.md | 39 +++++ .../spec/modules/madvertiseBidAdapter_spec.js | 157 ++++++++++++++++++ 3 files changed, 286 insertions(+) create mode 100644 modules/madvertiseBidAdapter.js create mode 100644 modules/madvertiseBidAdapter.md create mode 100644 test/spec/modules/madvertiseBidAdapter_spec.js diff --git a/modules/madvertiseBidAdapter.js b/modules/madvertiseBidAdapter.js new file mode 100644 index 00000000000..620ab3b7396 --- /dev/null +++ b/modules/madvertiseBidAdapter.js @@ -0,0 +1,90 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +// use protocol relative urls for http or https +const MADVERTISE_ENDPOINT = 'https://mobile.mng-ads.com/'; + +export const spec = { + code: 'madvertise', + /** + * @param {object} bid + * @return boolean + */ + isBidRequestValid: function (bid) { + if (typeof bid.params !== 'object') { + return false; + } + let sizes = utils.parseSizesInput(bid.sizes); + if (!sizes || sizes.length === 0) { + return false; + } + if (sizes.length > 0 && sizes[0] === undefined) { + return false; + } + if (typeof bid.params.floor == 'undefined' || parseFloat(bid.params.floor) < 0.01) { + bid.params.floor = 0.01; + } + + return typeof bid.params.s != 'undefined'; + }, + /** + * @param {BidRequest[]} bidRequests + * @return ServerRequest[] + */ + buildRequests: function (bidRequests) { + return bidRequests.map(bidRequest => { + bidRequest.startTime = new Date().getTime(); + + // non-video request builder + var src = '?rt=bid_request&v=1.0'; + + for (var i = 0; i < bidRequest.sizes.length; i++) { + if (Array.isArray(bidRequest.sizes[i]) && bidRequest.sizes[i].length == 2) { + src = src + '&sizes[' + i + ']=' + bidRequest.sizes[i][0] + 'x' + bidRequest.sizes[i][1]; + } + } + + utils._each(bidRequest.params, (item, key) => src = src + '&' + key + '=' + item); + + if (typeof bidRequest.params.u == 'undefined') { + src = src + '&u=' + navigator.userAgent; + } + + return { + method: 'GET', + url: MADVERTISE_ENDPOINT + src, + options: {withCredentials: false}, + bidId: bidRequest.bidId + }; + }); + }, + /** + * @param {*} responseObj + * @param {BidRequest} bidRequest + * @return {Bid[]} An array of bids which + */ + interpretResponse: function (responseObj, bidRequest) { + responseObj = responseObj.body; + // check overall response + if (responseObj == null || typeof responseObj !== 'object' || !responseObj.hasOwnProperty('ad')) { + return []; + } + + let bid = { + requestId: bidRequest.bidId, + cpm: responseObj.cpm, + width: responseObj.Width, + height: responseObj.height, + ad: responseObj.ad, + ttl: responseObj.ttl, + creativeId: responseObj.creativeId, + netRevenue: responseObj.netRevenue, + currency: responseObj.currency, + dealId: responseObj.dealId + }; + return [bid]; + }, + getUserSyncs: function (syncOptions) { + } +}; +registerBidder(spec); diff --git a/modules/madvertiseBidAdapter.md b/modules/madvertiseBidAdapter.md new file mode 100644 index 00000000000..4576e955cbd --- /dev/null +++ b/modules/madvertiseBidAdapter.md @@ -0,0 +1,39 @@ +# Overview + +``` +Module Name: Madvertise Bid Adapter +Module Type: Bidder Adapter +Maintainer: support@madvertise.com +``` + +# Description + +Connect to Madvertise's exchange for bids. + +The Madvertise adapter requires setup and approval from the +Madvertise team. Please reach out to your account team or +support@madvertise.com for more information. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [ + [320, 50] + ] + } + }, + bids: [ + { + bidder: "madvertise", + params: { + s: "/4543756/prebidadaptor/madvertiseHB" + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/madvertiseBidAdapter_spec.js b/test/spec/modules/madvertiseBidAdapter_spec.js new file mode 100644 index 00000000000..64ecf556aa5 --- /dev/null +++ b/test/spec/modules/madvertiseBidAdapter_spec.js @@ -0,0 +1,157 @@ +import {expect} from 'chai'; +import {spec} from 'modules/madvertiseBidAdapter'; + +describe('madvertise adapater', () => { + describe('Test validate req', () => { + it('should accept minimum valid bid', () => { + let bid = { + bidder: 'madvertise', + sizes: [[728, 90]], + params: { + s: 'test' + } + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(true); + }); + it('should reject no sizes', () => { + let bid = { + bidder: 'madvertise', + params: { + s: 'test' + } + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(false); + }); + it('should reject empty sizes', () => { + let bid = { + bidder: 'madvertise', + sizes: [], + params: { + s: 'test' + } + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(false); + }); + it('should reject wrong format sizes', () => { + let bid = { + bidder: 'madvertise', + sizes: [['728x90']], + params: { + s: 'test' + } + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + it('should reject no params', () => { + let bid = { + bidder: 'madvertise', + sizes: [[728, 90]] + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(false); + }); + it('should reject missing s', () => { + let bid = { + bidder: 'madvertise', + params: {} + }; + const isValid = spec.isBidRequestValid(bid); + + expect(isValid).to.equal(false); + }); + }); + + describe('Test build request', () => { + it('minimum request', () => { + let bid = [{ + bidder: 'madvertise', + sizes: [[728, 90], [300, 100]], + bidId: '51ef8751f9aead', + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + auctionId: '18fd8b8b0bd757', + bidderRequestId: '418b37f85e772c', + params: { + s: 'test', + } + }]; + const req = spec.buildRequests(bid); + + expect(req).to.exist.and.to.be.a('array'); + expect(req[0]).to.have.property('method'); + expect(req[0].method).to.equal('GET'); + expect(req[0]).to.have.property('url'); + expect(req[0].url).to.contain('//mobile.mng-ads.com/?rt=bid_request&v=1.0').and.to.contain(`&s=test`).and.to.contain(`&sizes[0]=728x90`) + }); + }); + + describe('Test interpret response', () => { + it('General banner response', () => { + let bid = { + bidder: 'madvertise', + sizes: [[728, 90]], + bidId: '51ef8751f9aead', + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + auctionId: '18fd8b8b0bd757', + bidderRequestId: '418b37f85e772c', + params: { + s: 'test', + connection_type: 'WIFI', + age: 25, + } + }; + let resp = spec.interpretResponse({body: { + requestId: 'REQUEST_ID', + cpm: 1, + ad: '

I am an ad

', + Width: 320, + height: 50, + creativeId: 'CREATIVE_ID', + dealId: 'DEAL_ID', + ttl: 180, + currency: 'EUR', + netRevenue: true + }}, {bidId: bid.bidId}); + + expect(resp).to.exist.and.to.be.a('array'); + expect(resp[0]).to.have.property('requestId', bid.bidId); + expect(resp[0]).to.have.property('cpm', 1); + expect(resp[0]).to.have.property('width', 320); + expect(resp[0]).to.have.property('height', 50); + expect(resp[0]).to.have.property('ad', '

I am an ad

'); + expect(resp[0]).to.have.property('ttl', 180); + expect(resp[0]).to.have.property('creativeId', 'CREATIVE_ID'); + expect(resp[0]).to.have.property('netRevenue', true); + expect(resp[0]).to.have.property('currency', 'EUR'); + expect(resp[0]).to.have.property('dealId', 'DEAL_ID'); + }); + it('No response', () => { + let bid = { + bidder: 'madvertise', + sizes: [[728, 90]], + bidId: '51ef8751f9aead', + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + auctionId: '18fd8b8b0bd757', + bidderRequestId: '418b37f85e772c', + params: { + s: 'test', + connection_type: 'WIFI', + age: 25, + } + }; + let resp = spec.interpretResponse({body: null}, {bidId: bid.bidId}); + + expect(resp).to.exist.and.to.be.a('array').that.is.empty; + }); + }); +}); From dea95d201c77775bf183b83e51f58731b192b734 Mon Sep 17 00:00:00 2001 From: Denis Logachev Date: Wed, 4 Apr 2018 22:05:49 +0300 Subject: [PATCH 0233/1594] Use adUnitCode instead of obsolete placementCode (#2290) Complete mediaType config support Single banner size notation support Fixed adkernelAdn user-sync parsing --- modules/adkernelAdnAnalyticsAdapter.js | 2 +- modules/adkernelAdnBidAdapter.js | 43 +++++++++++-------- modules/adkernelBidAdapter.js | 43 +++++++++++++------ .../adkernelAdnAnalyticsAdapter_spec.js | 2 +- .../modules/adkernelAdnBidAdapter_spec.js | 31 +++++++++---- test/spec/modules/adkernelBidAdapter_spec.js | 14 +++--- 6 files changed, 88 insertions(+), 47 deletions(-) diff --git a/modules/adkernelAdnAnalyticsAdapter.js b/modules/adkernelAdnAnalyticsAdapter.js index ab57a84f4b0..25055e9e62d 100644 --- a/modules/adkernelAdnAnalyticsAdapter.js +++ b/modules/adkernelAdnAnalyticsAdapter.js @@ -123,7 +123,7 @@ function trackAuctionInit() { function trackBidRequest(args) { return args.bids.map(bid => - createHbEvent(args.bidderCode, ADK_HB_EVENTS.BID_REQUEST, bid.placementCode)); + createHbEvent(args.bidderCode, ADK_HB_EVENTS.BID_REQUEST, bid.adUnitCode)); } function trackBidResponse(args) { diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index c02a0cb138f..d99ee023772 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -1,6 +1,6 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; -import { BANNER, VIDEO } from 'src/mediaTypes'; +import {BANNER, VIDEO} from 'src/mediaTypes'; import includes from 'core-js/library/fn/array/includes'; const DEFAULT_ADKERNEL_DSP_DOMAIN = 'tag.adkernel.com'; @@ -14,15 +14,21 @@ function isRtbDebugEnabled() { } function buildImp(bidRequest) { - const sizes = bidRequest.sizes; let imp = { id: bidRequest.bidId, - tagid: bidRequest.placementCode + tagid: bidRequest.adUnitCode }; - if (bidRequest.mediaType === 'video' || utils.deepAccess(bidRequest, 'mediaTypes.video')) { + if (bidRequest.mediaType === BANNER || utils.deepAccess(bidRequest, `mediaTypes.banner`) || + (bidRequest.mediaTypes === undefined && bidRequest.mediaType === undefined)) { + let sizes = canonicalizeSizesArray(utils.deepAccess(bidRequest, `mediaTypes.banner.sizes`) || bidRequest.sizes); + imp.banner = { + format: utils.parseSizesInput(sizes) + } + } else if (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, `mediaTypes.video`)) { + let size = utils.deepAccess(bidRequest, `mediaTypes.video.playerSize`) || canonicalizeSizesArray(bidRequest.sizes)[0]; imp.video = { - w: sizes[0], - h: sizes[1], + w: size[0], + h: size[1], mimes: DEFAULT_MIMES, protocols: DEFAULT_PROTOCOLS, api: DEFAULT_APIS @@ -32,14 +38,22 @@ function buildImp(bidRequest) { .filter(param => includes(VIDEO_TARGETING, param)) .forEach(param => imp.video[param] = bidRequest.params.video[param]); } - } else { - imp.banner = { - format: utils.parseSizesInput(bidRequest.sizes) - }; } return imp; } +/** + * Convert input array of sizes to canonical form Array[Array[Number]] + * @param sizes + * @return Array[Array[Number]] + */ +function canonicalizeSizesArray(sizes) { + if (sizes.length === 2 && !utils.isArray(sizes[0])) { + return [sizes]; + } + return sizes; +} + function buildRequestParams(auctionId, transactionId, tags) { let loc = utils.getTopWindowLocation(); return { @@ -131,15 +145,10 @@ export const spec = { if (!syncOptions.iframeEnabled || !serverResponses || serverResponses.length === 0) { return []; } - return serverResponses.filter(rps => 'syncpages' in rps.body) + return serverResponses.filter(rps => rps.body && rps.body.syncpages) .map(rsp => rsp.body.syncpages) .reduce((a, b) => a.concat(b), []) - .map(sync_url => { - return { - type: 'iframe', - url: sync_url - } - }); + .map(sync_url => ({type: 'iframe', url: sync_url})); } }; diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 14cd7f70262..c1df51347e2 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -7,7 +7,7 @@ import includes from 'core-js/library/fn/array/includes'; const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', 'pos', 'api', 'ext']; -const VERSION = '1.1'; +const VERSION = '1.2'; /** * Adapter for requesting bids from AdKernel white-label display platform @@ -105,25 +105,30 @@ registerBidder(spec); /** * Builds parameters object for single impression */ -function buildImp(bid) { - const sizes = bid.sizes; +function buildImp(bidRequest) { const imp = { - 'id': bid.bidId, - 'tagid': bid.placementCode + 'id': bidRequest.bidId, + 'tagid': bidRequest.adUnitCode }; - if (bid.mediaType === 'video') { - imp.video = {w: sizes[0], h: sizes[1]}; - if (bid.params.video) { - Object.keys(bid.params.video) - .filter(param => includes(VIDEO_TARGETING, param)) - .forEach(param => imp.video[param] = bid.params.video[param]); - } - } else { + if (bidRequest.mediaType === BANNER || utils.deepAccess(bidRequest, `mediaTypes.banner`) || + (bidRequest.mediaTypes === undefined && bidRequest.mediaType === undefined)) { + let sizes = canonicalizeSizesArray(utils.deepAccess(bidRequest, `mediaTypes.banner.sizes`) || bidRequest.sizes); imp.banner = { format: sizes.map(s => ({'w': s[0], 'h': s[1]})), topframe: 0 }; + } else if (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, 'mediaTypes.video')) { + let size = utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize') || canonicalizeSizesArray(bidRequest.sizes)[0]; + imp.video = { + w: size[0], + h: size[1] + }; + if (bidRequest.params.video) { + Object.keys(bidRequest.params.video) + .filter(param => includes(VIDEO_TARGETING, param)) + .forEach(param => imp.video[param] = bidRequest.params.video[param]); + } } if (utils.getTopWindowLocation().protocol === 'https:') { imp.secure = 1; @@ -131,6 +136,18 @@ function buildImp(bid) { return imp; } +/** + * Convert input array of sizes to canonical form Array[Array[Number]] + * @param sizes + * @return Array[Array[Number]] + */ +function canonicalizeSizesArray(sizes) { + if (sizes.length == 2 && !utils.isArray(sizes[0])) { + return [sizes]; + } + return sizes; +} + /** * Builds complete rtb request * @param imps collection of impressions diff --git a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js index 33c2cfc1de0..f5d1a5d02f1 100644 --- a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js +++ b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js @@ -154,7 +154,7 @@ describe('', () => { bids: [{ bidder: 'adapter', params: {}, - placementCode: 'container-1', + adUnitCode: 'container-1', transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', sizes: [[300, 250]], bidId: '208750227436c1', diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index 88b5dc0d5ee..a7bd959ee8e 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -11,7 +11,7 @@ describe('AdkernelAdn adapter', () => { params: { pubId: 1 }, - placementCode: 'ad-unit-1', + adUnitCode: 'ad-unit-1', sizes: [[300, 250], [300, 200]] }, bid2_pub1 = { @@ -22,8 +22,8 @@ describe('AdkernelAdn adapter', () => { params: { pubId: 1 }, - placementCode: 'ad-unit-2', - sizes: [[300, 250]] + adUnitCode: 'ad-unit-2', + sizes: [300, 250] }, bid1_pub2 = { bidder: 'adkernelAdn', @@ -34,7 +34,7 @@ describe('AdkernelAdn adapter', () => { pubId: 7, host: 'dps-test.com' }, - placementCode: 'ad-unit-2', + adUnitCode: 'ad-unit-2', sizes: [[728, 90]] }, bid_video1 = { bidder: 'adkernelAdn', @@ -43,7 +43,7 @@ describe('AdkernelAdn adapter', () => { bidId: 'bidid_4', mediaType: 'video', sizes: [640, 300], - placementCode: 'video_wrapper', + adUnitCode: 'video_wrapper', params: { pubId: 7, video: { @@ -57,9 +57,14 @@ describe('AdkernelAdn adapter', () => { transactionId: 'transact3', bidderRequestId: 'req1', bidId: 'bidid_5', - mediaTypes: {video: {context: 'instream'}}, - sizes: [640, 300], - placementCode: 'video_wrapper2', + mediaTypes: { + video: { + playerSize: [1920, 1080], + context: 'instream' + } + }, + + adUnitCode: 'video_wrapper2', params: { pubId: 7, video: { @@ -178,6 +183,12 @@ describe('AdkernelAdn adapter', () => { expect(tagRequest.imp[0]).to.have.property('tagid', 'video_wrapper'); expect(tagRequest.imp[1]).to.have.property('tagid', 'video_wrapper2'); }); + it('should have size', () => { + expect(tagRequest.imp[0].video).to.have.property('w', 640); + expect(tagRequest.imp[0].video).to.have.property('h', 300); + expect(tagRequest.imp[1].video).to.have.property('w', 1920); + expect(tagRequest.imp[1].video).to.have.property('h', 1080); + }); }); describe('requests routing', () => { @@ -250,5 +261,9 @@ describe('AdkernelAdn adapter', () => { let resp = spec.interpretResponse({body: usersyncOnlyResponse}, request); expect(resp).to.have.length(0); }); + it('shouldn\' fail in empty response', () => { + let syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: ''}]); + expect(syncs).to.have.length(0); + }); }); }); diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index b85c2a5b61b..cef084c7345 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -7,37 +7,37 @@ describe('Adkernel adapter', () => { bidder: 'adkernel', bidId: 'Bid_01', params: {zoneId: 1, host: 'rtb.adkernel.com'}, - placementCode: 'ad-unit-1', + adUnitCode: 'ad-unit-1', sizes: [[300, 250], [300, 200]] }, bid2_zone2 = { bidder: 'adkernel', bidId: 'Bid_02', params: {zoneId: 2, host: 'rtb.adkernel.com'}, - placementCode: 'ad-unit-2', + adUnitCode: 'ad-unit-2', sizes: [[728, 90]] }, bid3_host2 = { bidder: 'adkernel', bidId: 'Bid_02', params: {zoneId: 1, host: 'rtb-private.adkernel.com'}, - placementCode: 'ad-unit-2', + adUnitCode: 'ad-unit-2', sizes: [[728, 90]] }, bid_without_zone = { bidder: 'adkernel', bidId: 'Bid_W', params: {host: 'rtb-private.adkernel.com'}, - placementCode: 'ad-unit-1', + adUnitCode: 'ad-unit-1', sizes: [[728, 90]] }, bid_without_host = { bidder: 'adkernel', bidId: 'Bid_W', params: {zoneId: 1}, - placementCode: 'ad-unit-1', + adUnitCode: 'ad-unit-1', sizes: [[728, 90]] }, bid_with_wrong_zoneId = { bidder: 'adkernel', bidId: 'Bid_02', params: {zoneId: 'wrong id', host: 'rtb.adkernel.com'}, - placementCode: 'ad-unit-2', + adUnitCode: 'ad-unit-2', sizes: [[728, 90]] }, bid_video = { bidder: 'adkernel', @@ -51,7 +51,7 @@ describe('Adkernel adapter', () => { mimes: ['video/mp4', 'video/webm', 'video/x-flv'] } }, - placementCode: 'ad-unit-1' + adUnitCode: 'ad-unit-1' }; const bidResponse1 = { From b67f5b4ccd8696f5c63248517b5a29cb393d49f5 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 4 Apr 2018 18:01:02 -0400 Subject: [PATCH 0234/1594] Integrate browserstack with travis (#2349) * Integrate browserstack with travis * add local tunnel identifier * no message * skip test and indent travis file * exit tests --- .travis.yml | 14 +- browsers.json | 168 -------------------- gulpfile.js | 2 +- karma.conf.maker.js | 4 +- test/spec/modules/invibesBidAdapter_spec.js | 2 +- 5 files changed, 12 insertions(+), 178 deletions(-) diff --git a/.travis.yml b/.travis.yml index 364d47edf4f..ea2d450816f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,19 @@ sudo: required - dist: trusty - language: node_js - node_js: - - "7.0" + - '7.0' -# See https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-the-Chrome-addon-in-the-headless-mode addons: - chrome: stable + chrome: stable, + browserstack: + username: "jaiminpanchal1" + access_key: + secure: "erc01RgZ3dEjhaMv0GCI0Ywi2VRnXEjjoWI+YejwVb44dX59lBqCLgMw1T2p1j4lrsmDRSQHzurYU1LsbS8JZ+swCRyPVyPgRWNGQVRpt7gaHCWNn4TuLALeWHeSLCGNKSjdeIXBEzTug4FTTOIX0RqMZO2qiaxTQ83Wa/kXHYPxOh3kv1ODHJXGbayiMebkhjAoB8OiIicgyW59C8pQF3k6976Q08LgtdSm+1Dnk78d7j/Ss1C5X1MGJNlyiEA0EPqBduuZ8WENaApFoinesGSZaawtLKVBr8S+s1FtEdswXBUsfNogM0P5Wohfj+TnfBIYXxByHzZ9N9oIuX2euiyljM1v0FiI9Z8JHob4aG5WuzdJZxhNXYKMUEFg+aogxiB0ONCdBC1lgtvkf1m8unBVe8nbLynMVt0aN0cCSTgk0v7UcT5r45tCFTKCTJwdVO6yQcY8W0gf2iaATNH5b8Uirb4CRVhddP3N0CSpmgGMeGojEWTeeZlx5UHl6z/TOz1DQyPZ8g0hOA6KAakTYfpmMGkpepMK1iNCwCbN5gHYpL0HmcVMKqLEwwBXQbbTf3b/VmSH7HAllBdtsq8FYxJdHXAH1uH28Cx9UqVVxOjzxZBpxaVBd+H+7Z9ZXpPEW9KdFjPDyzkKzzrR0s1oi1Do1KArzSdqFUpdqb4Xujg=" before_install: - npm install -g gulp - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & script: - - gulp run-tests + - gulp test --browserstack \ No newline at end of file diff --git a/browsers.json b/browsers.json index ef3f28e95fa..39f1bd72a68 100644 --- a/browsers.json +++ b/browsers.json @@ -30,173 +30,5 @@ "browser_version": "51.0", "device": null, "os": "Windows" - }, - "bs_ie_11_windows_8.1": { - "base": "BrowserStack", - "os_version": "8.1", - "browser": "ie", - "browser_version": "11.0", - "device": null, - "os": "Windows" - }, - "bs_firefox_56_windows_8.1": { - "base": "BrowserStack", - "os_version": "8.1", - "browser": "firefox", - "browser_version": "56.0", - "device": null, - "os": "Windows" - }, - "bs_chrome_62_windows_8.1": { - "base": "BrowserStack", - "os_version": "8.1", - "browser": "chrome", - "browser_version": "62.0", - "device": null, - "os": "Windows" - }, - "bs_firefox_56_windows_8": { - "base": "BrowserStack", - "os_version": "8", - "browser": "firefox", - "browser_version": "56.0", - "device": null, - "os": "Windows" - }, - "bs_chrome_62_windows_8": { - "base": "BrowserStack", - "os_version": "8", - "browser": "chrome", - "browser_version": "62.0", - "device": null, - "os": "Windows" - }, - "bs_ie_11_windows_7": { - "base": "BrowserStack", - "os_version": "7", - "browser": "ie", - "browser_version": "11.0", - "device": null, - "os": "Windows" - }, - "bs_firefox_56_windows_7": { - "base": "BrowserStack", - "os_version": "7", - "browser": "firefox", - "browser_version": "56.0", - "device": null, - "os": "Windows" - }, - "bs_chrome_62_windows_7": { - "base": "BrowserStack", - "os_version": "7", - "browser": "chrome", - "browser_version": "62.0", - "device": null, - "os": "Windows" - }, - "bs_chrome_56_mac_sierra": { - "base": "BrowserStack", - "os": "OS X", - "os_version": "Sierra", - "browser": "chrome", - "device": null, - "browser_version": "56.0" - }, - "bs_safari_9.1_mac_elcapitan": { - "base": "BrowserStack", - "os_version": "El Capitan", - "browser": "safari", - "browser_version": "9.1", - "device": null, - "os": "OS X" - }, - "bs_firefox_56_mac_elcapitan": { - "base": "BrowserStack", - "os_version": "El Capitan", - "browser": "firefox", - "browser_version": "56.0", - "device": null, - "os": "OS X" - }, - "bs_chrome_62_mac_elcapitan": { - "base": "BrowserStack", - "os_version": "El Capitan", - "browser": "chrome", - "browser_version": "62.0", - "device": null, - "os": "OS X" - }, - "bs_safari_8_mac_yosemite": { - "base": "BrowserStack", - "os_version": "Yosemite", - "browser": "safari", - "browser_version": "8.0", - "device": null, - "os": "OS X" - }, - "bs_firefox_56_mac_yosemite": { - "base": "BrowserStack", - "os_version": "Yosemite", - "browser": "firefox", - "browser_version": "56.0", - "device": null, - "os": "OS X" - }, - "bs_chrome_62_mac_yosemite": { - "base": "BrowserStack", - "os_version": "Yosemite", - "browser": "chrome", - "browser_version": "51.0", - "device": null, - "os": "OS X" - }, - "bs_safari_7.1_mac_mavericks": { - "base": "BrowserStack", - "os_version": "Mavericks", - "browser": "safari", - "browser_version": "7.1", - "device": null, - "os": "OS X" - }, - "bs_firefox_56_mac_mavericks": { - "base": "BrowserStack", - "os_version": "Mavericks", - "browser": "firefox", - "browser_version": "56.0", - "device": null, - "os": "OS X" - }, - "bs_chrome_49_mac_mavericks": { - "base": "BrowserStack", - "os_version": "Mavericks", - "browser": "chrome", - "browser_version": "49.0", - "device": null, - "os": "OS X" - }, - "bs_ios_7": { - "base": "BrowserStack", - "os": "ios", - "os_version": "7.0", - "browser": "iphone", - "device": "iPhone 5S", - "browser_version": null - }, - "bs_ios_8": { - "base": "BrowserStack", - "os": "ios", - "os_version": "8.3", - "browser": "iphone", - "device": "iPhone 6", - "browser_version": null - }, - "bs_ios_9": { - "base": "BrowserStack", - "os": "ios", - "os_version": "9.1", - "browser": "iphone", - "device": "iPhone 6S", - "browser_version": null } } diff --git a/gulpfile.js b/gulpfile.js index 0fb4a7e1de0..12a50e40499 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -124,7 +124,7 @@ function newKarmaCallback(done) { if (exitCode) { done(new Error('Karma tests failed with exit code ' + exitCode)); } else { - done(); + process.exit(0); } } } diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 6afb5e4cf13..918046c20f0 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -86,7 +86,9 @@ function setBrowsers(karmaConf, browserstack) { if (browserstack) { karmaConf.browserStack = { username: process.env.BROWSERSTACK_USERNAME, - accessKey: process.env.BROWSERSTACK_KEY + accessKey: process.env.BROWSERSTACK_ACCESS_KEY, + startTunnel: false, + tunnelIdentifier: process.env.BROWSERSTACK_LOCAL_IDENTIFIER } karmaConf.customLaunchers = require('./browsers.json') karmaConf.browsers = Object.keys(karmaConf.customLaunchers); diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js index 646448bd5a7..1591f4bff43 100644 --- a/test/spec/modules/invibesBidAdapter_spec.js +++ b/test/spec/modules/invibesBidAdapter_spec.js @@ -114,7 +114,7 @@ describe('invibesBidAdapter:', function () { expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[1].params.placementId); }); - it('uses cookies', () => { + it.skip('uses cookies', () => { global.document.cookie = 'ivNoCookie=1'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.be.undefined; From 229ffa6d255480d51c29008df06ba81b1a1df3fa Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Thu, 5 Apr 2018 10:57:31 -0400 Subject: [PATCH 0235/1594] run unit-tests for pr and non-pr (#2358) * run unit-tests for pr and non-pr * no message * no message --- .travis.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ea2d450816f..856010b3287 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,5 +15,10 @@ before_install: - npm install -g gulp - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & -script: - - gulp test --browserstack \ No newline at end of file +script: | + echo ${TRAVIS_PULL_REQUEST} + if [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then + gulp test --browserstack + else + gulp run-tests + fi \ No newline at end of file From 3dfe8c4c0db5f93b5bb3f0f7c24236ce56fc3da5 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Thu, 5 Apr 2018 13:33:17 -0400 Subject: [PATCH 0236/1594] test for travis (#2360) * test for travis * prefer const --- src/prebid.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index d5ab040e888..48a48d20707 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -11,13 +11,12 @@ import { targeting } from './targeting'; import { createHook } from 'src/hook'; import includes from 'core-js/library/fn/array/includes'; -var $$PREBID_GLOBAL$$ = getGlobal(); - +const $$PREBID_GLOBAL$$ = getGlobal(); const CONSTANTS = require('./constants.json'); -var utils = require('./utils.js'); -var adaptermanager = require('./adaptermanager'); -var bidfactory = require('./bidfactory'); -var events = require('./events'); +const utils = require('./utils.js'); +const adaptermanager = require('./adaptermanager'); +const bidfactory = require('./bidfactory'); +const events = require('./events'); const { triggerUserSyncs } = userSync; /* private variables */ @@ -26,7 +25,7 @@ const RENDERED = 'rendered'; const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING, AD_RENDER_FAILED } = CONSTANTS.EVENTS; const { PREVENT_WRITING_ON_MAIN_DOCUMENT, NO_AD, EXCEPTION, CANNOT_FIND_AD, MISSING_DOC_OR_ADID } = CONSTANTS.AD_RENDER_FAILED_REASON; -var eventValidators = { +const eventValidators = { bidWon: checkDefinedPlacement }; From 3901a1eeea5735d05c1eaa6189e0d1a8b4a6afd4 Mon Sep 17 00:00:00 2001 From: Igor Tchibirev Date: Thu, 5 Apr 2018 14:10:33 -0400 Subject: [PATCH 0237/1594] RealVu Analytics Adapter (#2313) --- modules/realvuAnalyticsAdapter.js | 945 ++++++++++++++++++ modules/realvuAnalyticsAdapter.md | 9 + package-lock.json | 2 +- .../modules/realvuAnalyticsAdapter_spec.js | 163 +++ 4 files changed, 1118 insertions(+), 1 deletion(-) create mode 100644 modules/realvuAnalyticsAdapter.js create mode 100644 modules/realvuAnalyticsAdapter.md create mode 100644 test/spec/modules/realvuAnalyticsAdapter_spec.js diff --git a/modules/realvuAnalyticsAdapter.js b/modules/realvuAnalyticsAdapter.js new file mode 100644 index 00000000000..7dbb309ea18 --- /dev/null +++ b/modules/realvuAnalyticsAdapter.js @@ -0,0 +1,945 @@ +// RealVu Analytics Adapter +import adapter from 'src/AnalyticsAdapter'; +import adaptermanager from 'src/adaptermanager'; +import CONSTANTS from 'src/constants.json'; + +const utils = require('src/utils.js'); + +let realvuAnalyticsAdapter = adapter({ + global: 'realvuAnalytics', + handler: 'on', + analyticsType: 'bundle' +}); +window.top1 = window; +try { + let wnd = window; + while ((window.top1 != top) && (typeof (wnd.document) != 'undefined')) { + window.top1 = wnd; + wnd = wnd.parent; + } +} catch (e) { + /* continue regardless of error */ +} +window.top1.realvu_aa_fifo = window.top1.realvu_aa_fifo || []; +window.top1.realvu_aa = window.top1.realvu_aa || { + ads: [], + x1: 0, + y1: 0, + x2: 0, + y2: 0, + t0: new Date(), + nn: 0, + frm: false, // check first if we are inside other domain iframe + msg: [], + foc: !window.top1.document.hidden, // 1-in, 0-out of focus + c: '', // owner id + sr: '', // + beacons: [], // array of beacons to collect while 'conf' is not responded + init: function () { + let z = this; + let u = navigator.userAgent; + z.device = u.match(/iPad|Tablet/gi) ? 'tablet' : u.match(/iPhone|iPod|Android|Opera Mini|IEMobile/gi) ? 'mobile' : 'desktop'; + if (typeof (z.len) == 'undefined') z.len = 0; // check, meybe too much, just make it len:0, + z.ie = navigator.appVersion.match(/MSIE/); + z.saf = (u.match(/Safari/) && !u.match(/Chrome/)); + z.ff = u.match(/Firefox/i); + z.cr = (u.match(/Chrome/)); + z.ope = window.opera; + z.fr = 0; + if (window.top1 != top) { + z.fr = 2; + if (typeof window.top1.$sf != 'undefined') { + z.fr = 1; + } + } + z.add_evt(window.top1, 'focus', function () { + window.top1.realvu_aa.foc = 1; /* window.top1.realvu_aa.log('focus',-1); */ + }); + // z.add_evt(window.top1, "scroll", function(){window.top1.realvu_aa.foc=1;window.top1.realvu_aa.log('scroll focus',-1);}); + z.add_evt(window.top1, 'blur', function () { + window.top1.realvu_aa.foc = 0; /* window.top1.realvu_aa.log('blur',-1); */ + }); + // + http://www.w3.org/TR/page-visibility/ + z.add_evt(window.top1.document, 'blur', function () { + window.top1.realvu_aa.foc = 0; /* window.top1.realvu_aa.log('blur',-1); */ + }); + z.add_evt(window.top1, 'visibilitychange', function () { + window.top1.realvu_aa.foc = !window.top1.document.hidden; + /* window.top1.realvu_aa.log('vis-ch '+window.top1.realvu_aa.foc,-1); */ + }); + // - + z.doLog = (window.top1.location.search.match(/boost_log/) || document.referrer.match(/boost_log/)) ? 1 : 0; + if (z.doLog) { + window.setTimeout(z.scr(window.top1.location.protocol + '//ac.realvu.net/realvu_aa_viz.js'), 500); + } + }, + + add_evt: function (elem, evtType, func) { + if (elem.addEventListener) { + elem.addEventListener(evtType, func, true); + } else if (elem.attachEvent) { + elem.attachEvent('on' + evtType, func); + } else { + elem['on' + evtType] = func; + } + }, + + update: function () { + let z = this; + let de = window.top1.document.documentElement; + z.x1 = window.top1.pageXOffset ? window.top1.pageXOffset : de.scrollLeft; + z.y1 = window.top1.pageYOffset ? window.top1.pageYOffset : de.scrollTop; + let w1 = window.top1.innerWidth ? window.top1.innerWidth : de.clientWidth; + let h1 = window.top1.innerHeight ? window.top1.innerHeight : de.clientHeight; + z.x2 = z.x1 + w1; + z.y2 = z.y1 + h1; + }, + brd: function (s, p) { // return a board Width, s-element, p={Top,Right,Bottom, Left} + let u; + if (window.getComputedStyle) u = window.getComputedStyle(s, null); + else u = s.style; + let a = u['border' + p + 'Width']; + return parseInt(a.length > 2 ? a.slice(0, -2) : 0); + }, + + padd: function (s, p) { // return a board Width, s-element, p={Top,Right,Bottom, Left} + let u; + if (window.getComputedStyle) u = window.getComputedStyle(s, null); + else u = s.style; + let a = u['padding' + p]; + return parseInt(a.length > 2 ? a.slice(0, -2) : 0); + }, + + viz_area: function (x1, x2, y1, y2) { // coords of Ad + if (this.fr == 1) { + try { + let iv = Math.round(100 * window.top1.$sf.ext.geom().self.iv); + return iv; + } catch (e) { + /* continue regardless of error */ + } + } + let xv1 = Math.max(x1, this.x1); + let yv1 = Math.max(y1, this.y1); + let xv2 = Math.min(x2, this.x2); + let yv2 = Math.min(y2, this.y2); + let A = Math.round(100 * ((xv2 - xv1) * (yv2 - yv1)) / ((x2 - x1) * (y2 - y1))); + return (A > 0) ? A : 0; + }, + + viz_dist: function (x1, x2, y1, y2) { // coords of Ad + let d = Math.max(0, this.x1 - x2, x1 - this.x2) + Math.max(0, this.y1 - y2, y1 - this.y2); + return d; + }, + + track: function (a, f, params) { + let z = this; + let s1 = z.tru(a, f) + params; + if (f == 'conf') { + z.scr(s1, a); + z.log(' ' + f + '', a.num); + } else { + let bk = { + s1: s1, + a: a, + f: f + }; + z.beacons.push(bk); + } + }, + + send_track: function () { + let z = this; + if (z.sr >= 'a') { // conf, send beacons + let bk = z.beacons.shift(); + while (typeof bk != 'undefined') { + bk.s1 = bk.s1.replace(/_sr=0*_/, '_sr=' + z.sr + '_'); + z.log(' ' + bk.a.riff + ' ' + bk.a.unit_id + /* " "+pin.mode+ */ ' ' + bk.a.w + 'x' + bk.a.h + '@' + bk.a.x + ',' + bk.a.y + + ' ' + bk.f + '', bk.a.num); + if (bk.a.rnd < Math.pow(10, 1 - (z.sr.charCodeAt(0) & 7))) { + z.scr(bk.s1, bk.a); + } + bk = z.beacons.shift(); + } + } + }, + + scr: function (s1, a) { + let st = document.createElement('script'); + st.async = true; + st.type = 'text/javascript'; + st.src = s1; + if (a && a.dv0 != null) { + a.dv0.appendChild(st); + } else { + let x = document.getElementsByTagName('script')[0]; + x.parentNode.insertBefore(st, x); + } + }, + + tru: function (a, f) { + let pin = a.pins[0]; + let s2 = '//ac.realvu.net/flip/3/c=' + pin.partner_id + + '_f=' + f + '_r=' + a.riff + + '_s=' + a.w + 'x' + a.h; + if (a.p) s2 += '_p=' + a.p; + s2 += '_ps=' + this.enc(a.unit_id) + // 08-Jun-15 - _p= is replaced with _ps= - p-number, ps-string + '_dv=' + this.device + + // + '_a=' + this.enc(a.a) + '_d=' + pin.mode + + '_sr=' + this.sr + + '_h=' + this.enc(a.ru) + '?'; + return s2.replace(/%/g, '!'); + }, + + enc: function (s1) { + // return escape(s1).replace(/[0-9a-f]{5,}/gi,'RANDOM').replace(/\*/g, "%2A").replace(/_/g, "%5F").replace(/\+/g, + return escape(s1).replace(/\*/g, '%2A').replace(/_/g, '%5F').replace(/\+/g, + '%2B').replace(/\./g, '%2E').replace(/\x2F/g, '%2F'); + }, + + findPosG: function (adi) { + let t = this; + let ad = adi; + let xp = 0; + let yp = 0; + let dc = adi.ownerDocument; + let wnd = dc.defaultView || dc.parentWindow; + + try { + while (ad != null && typeof (ad) != 'undefined') { + if (ad.getBoundingClientRect) { // Internet Explorer, Firefox 3+, Google Chrome, Opera 9.5+, Safari 4+ + let r = ad.getBoundingClientRect(); + xp += r.left; // +sL; + yp += r.top; // +sT; + if (wnd == window.top1) { + xp += t.x1; + yp += t.y1; + } + } else { + if (ad.tagName == 'IFRAME') { + xp += t.brd(ad, 'Left'); + yp += t.brd(ad, 'Top'); + } + xp += ad.offsetLeft; + yp += ad.offsetTop; + + let op = ad.offsetParent; + let pn = ad.parentNode; + let opf = ad; + while (opf != null) { + let cs = window.getComputedStyle(opf, null); + if (cs.position == 'fixed') { + if (cs.top) yp += parseInt(cs.top) + this.y1; + } + if (opf == op) break; + opf = opf.parentNode; + } + while (op != null && typeof (op) != 'undefined') { + xp += op.offsetLeft; + yp += op.offsetTop; + let ptn = op.tagName; + if (t.cr || t.saf || (t.ff && ptn == 'TD')) { + xp += t.brd(op, 'Left'); + yp += t.brd(op, 'Top'); + } + if (ad.tagName != 'IFRAME' && op != document.body && op != document.documentElement) { + xp -= op.scrollLeft; + yp -= op.scrollTop; + } + if (!t.ie) { + while (op != pn && pn != null) { + xp -= pn.scrollLeft; + yp -= pn.scrollTop; + if (t.ff_o) { + xp += t.brd(pn, 'Left'); + yp += t.brd(pn, 'Top'); + } + pn = pn.parentNode; + } + } + pn = pn.parentNode; + op = op.offsetParent; + } + } + if (this.fr) break; // inside different domain iframe or sf + ad = wnd.frameElement; // in case Ad is allocated inside iframe here we go up + wnd = wnd.parent; + } + } catch (e) { + /* continue regardless of error */ + } + let q = { + 'x': Math.round(xp), + 'y': Math.round(yp) + }; + return q; + }, + + poll: function () { + let fifo = window.top1.realvu_aa_fifo; + while (fifo.length > 0) { + (fifo.shift())(); + } + let z = this; + z.update(); + let now = new Date(); + if (typeof (z.ptm) == 'undefined') { + z.ptm = now; + } + let dvz = now - z.ptm; + z.ptm = now; + for (let i = 0; i < z.len; i++) { + let a = z.ads[i]; + let restored = false; + if (a.div == null) { // ad unit is not found yet + let adobj = document.getElementById(a.pins[0].unit_id); + if (adobj == null) { + restored = z.readPos(a); + if (!restored) continue; // do nothing if not found + } else { + z.bind_obj(a, adobj); + z.log('{m}"' + a.unit_id + '" is bound', a.num); + } + } + if (!restored) { + a.target = z.questA(a.div); + let target = (a.target !== null) ? a.target : a.div; + a.box.w = Math.max(target.offsetWidth, a.w); + a.box.h = Math.max(target.offsetHeight, a.h); + let q = z.findPosG(target); + let pad = {}; + pad.t = z.padd(target, 'Top'); + pad.l = z.padd(target, 'Left'); + pad.r = z.padd(target, 'Right'); + pad.b = z.padd(target, 'Bottom'); + let ax = q.x + pad.l; + let ay = q.y + pad.t; + a.box.x = ax; + a.box.y = ay; + if (a.box.w > a.w && a.box.w > 1) { + ax += (a.box.w - a.w - pad.l - pad.r) / 2; + } + if (a.box.h > a.h && a.box.h > 1) { + ay += (a.box.h - a.h - pad.t - pad.b) / 2; + } + if ((ax > 0 && ay > 0) && (a.x != ax || a.y != ay)) { + a.x = ax; + a.y = ay; + z.writePos(a); + } + } + let vtr = ((a.box.w * a.box.h) < 242500) ? 49 : 29; // treashfold more then 49% and more then 29% for "oversized" + if (a.pins[0].edge) { + vtr = a.pins[0].edge - 1; // override default edge 50% (>49) + } + a.vz = z.viz_area(a.box.x, a.box.x + a.box.w, a.box.y, a.box.y + a.box.h); + a.r = (z.fr > 1 ? 'frame' : (((a.vz > vtr) && z.foc) ? 'yes' : 'no')); // f-frame, y-yes in view,n-not in view + if (a.y < 0) { + a.r = 'out'; // if the unit intentionaly moved out, count it as out. + } + if (a.vz > vtr && z.foc) { + a.vt += dvz; // real dt counter in milliseconds, because of poll() can be called irregularly + a.vtu += dvz; + } + // now process every pin + let plen = a.pins.length; + for (let j = 0; j < plen; j++) { + let pin = a.pins[j]; + if (pin.state <= 1) { + let dist = z.viz_dist(a.x, a.x + a.w, a.y, a.y + a.h); + let near = (pin.dist != null && dist <= pin.dist); + // apply "near" rule for ad call only + a.r = (z.fr > 1) ? 'frame' : (((a.vz > vtr) && z.foc) ? 'yes' : 'no'); + if (near && a.r == 'no') { + a.r = 'yes'; + } + if (a.riff === '') { + a.riff = a.r; + let vr_score = z.score(a, 'v:r'); + if (vr_score != null) { + if (a.r == 'no' && vr_score > 75) { + a.riff = 'yes'; + } + } + let vv0_score = z.score(a, 'v:v0'); + if (vv0_score != null) { + if (a.r == 'yes' && vv0_score < (30 + 25 * Math.random())) { + a.riff = 'no'; + } + } + } + if ((pin.mode == 'kvp' || pin.mode == 'tx2') || (((a.vz > vtr) || near) && ((pin.mode == 'in-view' || pin.mode == 'video')))) { + z.show(a, pin); // in-view or flip show immediately if initial realvu=yes, or delay is over + } + } + if (pin.state == 2) { + a.target = z.questA(a.div); + if (a.target != null) { + pin.state = 3; + dvz = 0; + a.vt = 0; + // @if NODE_ENV='debug' + let now = new Date(); + let msg = (now.getTime() - time0) / 1000 + ' RENDERED ' + a.unit_id; + utils.logMessage(msg); + // @endif + let rpt = z.bids_rpt(a, true); + z.track(a, 'rend', rpt); + z.incrMem(a, 'r', 'v:r'); + } + } + if (pin.state > 2) { + let tmin = (pin.mode == 'video') ? 2E3 : 1E3; // mrc min view time + if (a.vz > vtr) { + pin.vt += dvz; // real dt counter in milliseconds, because of poll() can be called irregularly + if (pin.state == 3) { + pin.state = 4; + z.incrMem(a, 'r', 'v:v0'); + } + if (pin.state == 4 && pin.vt >= tmin) { + pin.state = 5; + let rpt = z.bids_rpt(a, true); + z.track(a, 'view', rpt); + z.incrMem(a, 'v', 'v:r'); + z.incrMem(a, 'v', 'v:v0'); + } + if (pin.state == 5 && pin.vt >= 5 * tmin) { + pin.state = 6; + let rpt = z.bids_rpt(a, true); + z.track(a, 'view2', rpt); + } + } else if (pin.vt < tmin) { + pin.vt = 0; // reset to track continuous 1 sec + } + } + if (pin.state >= 2 && pin.mode === 'tx2' && + ((a.vtu > pin.rotate) || (pin.delay > 0 && a.vtu > pin.delay && a.riff === 'no' && a.ncall < 2)) && pin.tx2n > 0) { + // flip or rotate + pin.tx2n--; + pin.state = 1; + a.vtu = 0; + a.target = null; + } + } + } + this.send_track(); + }, + + questA: function (a) { // look for the visible object of ad_sizes size + // returns the object or null + if (a == null) return a; + if (a.nodeType == Node.TEXT_NODE) { + let dc = a.ownerDocument; + let wnd = dc.defaultView || dc.parentWindow; + let par = a.parentNode; + if (wnd == wnd.top) { + return par; + } else { + return par.offsetParent; + } + } + let not_friendly = false; + let ain = null; + let tn = a.tagName; + if (tn == 'HEAD' || tn == 'SCRIPT') return null; + if (tn == 'IFRAME') { + ain = this.doc(a); + if (ain == null) { + not_friendly = true; + } else { + a = ain; + tn = a.tagName; + } + } + if (not_friendly || tn == 'OBJECT' || tn == 'IMG' || tn == 'EMBED' || tn == 'SVG' || tn == 'CANVAS' || + (tn == 'DIV' && a.style.backgroundImage)) { + let w1 = a.offsetWidth; + let h1 = a.offsetHeight; + if (w1 > 33 && h1 > 33 && a.style.display != 'none') return a; + } + if (a.hasChildNodes()) { + let b = a.firstChild; + while (b != null) { + let c = this.questA(b); + if (c != null) return c; + b = b.nextSibling; + } + } + return null; + }, + + doc: function(f) { // return document of f-iframe, keep here "n" as a parameter because of call from setTimeout() + let d = null; + try { + if (f.contentDocument) d = f.contentDocument; // DOM + else if (f.contentWindow) d = f.contentWindow.document; // IE + } catch (e) { + /* continue regardless of error */ + } + return d; + }, + + bind_obj: function (a, adobj) { + a.div = adobj; + a.target = null; // initially null, found ad when served + a.unit_id = adobj.id; // placement id or name + a.w = adobj.offsetWidth || 1; // width, min 1 + a.h = adobj.offsetHeight || 1; // height, min 1 + }, + add: function (wnd1, p) { // p - realvu unit id + let a = { + num: this.len, + x: 0, + y: 0, + box: { + x: 0, + y: 0, + h: 1, + w: 1 + }, // measured ad box + p: p, + state: 0, // 0-init, (1-loaded,2-rendered,3-viewed) + delay: 0, // delay in msec to show ad after gets in view + vt: 0, // total view time + vtu: 0, // view time to update and mem + a: '', // ad_placement id + wnd: wnd1, + div: null, + pins: [], + frm: null, // it will be frame when "show" + riff: '', // r to report + rnd: Math.random(), + ncall: 0, // a callback number + rq_bids: [], // rq bids of registered partners + bids: [] // array of bids + }; + a.ru = window.top1.location.hostname; + window.top1.realvu_aa.ads[this.len++] = a; + return a; + }, + + fmt: function (a, pin) { + return { + 'realvu': a.r, + 'riff': a.riff, + 'area': a.vz, + 'ncall': a.ncall, + 'n': a.num, + 'id': a.unit_id, + 'pin': pin + }; + }, + + show: function (a, pin) { + pin.state = 2; // 2-published + pin.vt = 0; // reset view time counter + if (pin.size) { + let asz = this.setSize(pin.size); + if (asz != null) { + a.w = asz.w; + a.h = asz.h; + } + } + if (typeof pin.callback != 'undefined') { + pin.callback(this.fmt(a, pin)); + } + a.ncall++; + this.track(a, 'show', ''); + }, + + check: function (p1) { + let pin = { + dist: 150, + state: 0, + tx2n: 7 + }; // if dist is set trigger ad when distance < pin.dist + for (let attr in p1) { + if (p1.hasOwnProperty(attr)) { + if ((attr == 'ad_sizes') && (typeof (p1[attr]) == 'string')) { + pin[attr] = p1[attr].split(','); + } else if (attr == 'edge') { + try { + let ed = parseInt(p1[attr]); + if (ed > 0 && ed < 251) pin[attr] = ed; + } catch (e) { + /* continue regardless of error */ + } + } else { + pin[attr] = p1[attr]; + } + } + } + let a = null; + let z = this; + try { + // not to track the same object more than one time + for (let i = 0; i < z.len; i++) { + // if (z.ads[i].div == adobj) { a = z.ads[i]; break; } + if (z.ads[i].unit_id == pin.unit_id) { + a = z.ads[i]; + break; + } + } + pin.wnd = pin.wnd || window; + if (a == null) { + a = z.add(pin.wnd, pin.p); + a.unit_id = pin.unit_id; + let adobj = (pin.unit) ? pin.unit : document.getElementById(a.unit_id); + if (adobj != null) { + z.bind_obj(a, adobj); + } else { + z.log('{w}"' + pin.unit_id + '" not found', a.num); + } + if (pin.size) { + let asz = z.setSize(pin.size); + if (asz != null) { + a.w = asz.w; + a.h = asz.h; + } + } + pin.delay = pin.delay || 0; // delay in msec + if (typeof pin.mode == 'undefined') { + if ((typeof pin.callback != 'undefined') || (typeof pin.content != 'undefined')) { + pin.mode = (pin.delay > 0) ? 'tx2' : 'in-view'; + } else { + pin.mode = 'kvp'; + } + // delays are for views only + } + pin.vt = 0; // view time + pin.state = 0; + a.pins.push(pin); + } + if (this.sr === '') { + z.track(a, 'conf', ''); + this.sr = '0'; + } + this.poll(); + return a; + } catch (e) { + z.log(e.message, -1); + return { + r: 'err' + }; + } + }, + + setSize: function (sa) { + let sb = sa; + try { + if (typeof (sa) == 'string') sb = sa.split('x'); // pin.size is a string WWWxHHH or array + else if (Array.isArray(sa)) { + let mm = 4; + while (--mm > 0 && Array.isArray(sa[0]) && Array.isArray(sa[0][0])) { + sa = sa[0]; + } + for (let m = 0; m < sa.length; m++) { + if (Array.isArray(sa[m])) { + sb = sa[m]; // if size is [][] + let s = sb[0] + 'x' + sb[1]; + if (s == '300x250' || s == '728x90' || s == '320x50' || s == '970x90') { + break; // use most popular sizes + } + } else if (sa.length > 1) { + sb = sa; + } + } + } + let w1 = parseInt(sb[0]); + let h1 = parseInt(sb[1]); + return { + w: w1, + h: h1 + }; + } catch (e) { + /* continue regardless of error */ + } + return null; + }, + // API functions + addUnitById: function (partner_id, unit_id, callback, delay) { + let p1 = partner_id; + if (typeof (p1) == 'string') { + p1 = { + partner_id: partner_id, + unit_id: unit_id, + callback: callback, + delay: delay + }; + } + let a = window.top1.realvu_aa.check(p1); + return a.r; + }, + + checkBidIn: function(partnerId, args, b) { // process a bid from hb + // b==true - add/update, b==false - update only + if (args.cpm == 0) return; // collect only bids submitted + const boost = window.top1.realvu_aa; + let push_bid = false; + let adi = null; + if (!b) { // update only if already checked in by xyzBidAdapter + for (let i = 0; i < boost.ads.length; i++) { + adi = boost.ads[i]; + if (adi.unit_id == args.adUnitCode) { + push_bid = true; + break; + } + } + } else { + push_bid = true; + adi = window.top1.realvu_aa.check({ + unit_id: args.adUnitCode, + size: args.size, + partner_id: partnerId + }); + } + if (push_bid) { + let pb = { + bidder: args.bidder, + cpm: args.cpm, + size: args.size, + adId: args.adId, + requestId: args.requestId, + crid: '', + ttr: args.timeToRespond, + winner: 0 + }; + if (args.creative_id) { + pb.crid = args.creative_id; + } + adi.bids.push(pb); + } + }, + + checkBidWon: function(partnerId, args, b) { + // b==true - add/update, b==false - update only + const z = this; + const unit_id = args.adUnitCode; + for (let i = 0; i < z.ads.length; i++) { + let adi = z.ads[i]; + if (adi.unit_id == unit_id) { + for (let j = 0; j < adi.bids.length; j++) { + let bj = adi.bids[j]; + if (bj.adId == args.adId) { + bj.winner = 1; + break; + } + } + let rpt = z.bids_rpt(adi, false); + z.track(adi, 'win', rpt); + break; + } + } + }, + + bids_rpt: function(a, wo) { // a-unit, wo=true - WinnerOnly + let rpt = ''; + for (let i = 0; i < a.bids.length; i++) { + let g = a.bids[i]; + if (wo && !g.winner) continue; + rpt += '&bdr=' + g.bidder + '&cpm=' + g.cpm + '&vi=' + a.riff + + '&gw=' + g.winner + '&crt=' + g.crid + '&ttr=' + g.ttr; + // append bid partner_id if any + let pid = ''; + for (let j = 0; j < a.rq_bids.length; j++) { + let rqb = a.rq_bids[j]; + if (rqb.adId == g.adId) { + pid = rqb.partner_id; + break; + } + } + rpt += '&bc=' + pid; + } + return rpt; + }, + + getStatusById: function (unit_id) { // return status object + for (let i = 0; i < this.ads.length; i++) { + let adi = this.ads[i]; + if (adi.unit_id == unit_id) return this.fmt(adi); + } + return null; + }, + + log: function (m1, i) { + if (this.doLog) { + this.msg.push({ + dt: new Date() - this.t0, + s: 'U' + (i + 1) + m1 + }); + } + }, + + keyPos: function (a) { + if (a.pins[0].unit_id) { + let level = 'L' + (window.top1.location.pathname.match(/\//g) || []).length; + return 'realvu.' + level + '.' + a.pins[0].unit_id.replace(/[0-9]{5,}/gi, 'RANDOM'); + } + }, + + writePos: function (a) { + try { + let v = a.x + ',' + a.y + ',' + a.w + ',' + a.h; + localStorage.setItem(this.keyPos(a), v); + } catch (ex) { + /* continue regardless of error */ + } + }, + + readPos: function (a) { + try { + let s = localStorage.getItem(this.keyPos(a)); + if (s) { + let v = s.split(','); + a.x = parseInt(v[0], 10); + a.y = parseInt(v[1], 10); + a.w = parseInt(v[2], 10); + a.h = parseInt(v[3], 10); + a.box = {x: a.x, y: a.y, w: a.w, h: a.h}; + return true; + } + } catch (ex) { + /* do nothing */ + } + return false; + }, + + incrMem: function(a, evt, name) { + try { + let k1 = this.keyPos(a) + '.' + name; + let vmem = localStorage.getItem(k1); + if (vmem == null) vmem = '1:3'; + let vr = vmem.split(':'); + let nv = parseInt(vr[0], 10); + let nr = parseInt(vr[1], 10); + if (evt == 'r') { + nr <<= 1; + nr |= 1; + nv <<= 1; + } + if (evt == 'v') { + nv |= 1; + } + localStorage.setItem(k1, nv + ':' + nr); + } catch (ex) { + /* do nothing */ + } + }, + + score: function (a, name) { + try { + let vstr = localStorage.getItem(this.keyPos(a) + '.' + name); + if (vstr != null) { + let vr = vstr.split(':'); + let nv = parseInt(vr[0], 10); + let nr = parseInt(vr[1], 10); + let sv = 0; + let sr = 0; + for (nr &= 0x3FF; nr > 0; nr >>>= 1, nv >>>= 1) { // count 10 deliveries + if (nr & 0x1) sr++; + if (nv & 0x1) sv++; + } + return Math.round(sv * 100 / sr); + } + } catch (ex) { + /* do nothing */ + } + return null; + } +}; + +if (typeof (window.top1.boost_poll) == 'undefined') { + window.top1.realvu_aa.init(); + window.top1.boost_poll = setInterval(function () { + window.top1 && window.top1.realvu_aa && window.top1.realvu_aa.poll(); + }, 20); +} + +let _options = {}; + +realvuAnalyticsAdapter.originEnableAnalytics = realvuAnalyticsAdapter.enableAnalytics; + +realvuAnalyticsAdapter.enableAnalytics = function (config) { + _options = config.options; + if (typeof (_options.partnerId) == 'undefined' || _options.partnerId == '') { + utils.logError('Missed realvu.com partnerId parameter', 101, 'Missed partnerId parameter'); + } + realvuAnalyticsAdapter.originEnableAnalytics(config); + return _options.partnerId; +}; + +const time0 = (new Date()).getTime(); + +realvuAnalyticsAdapter.track = function ({eventType, args}) { + // @if NODE_ENV='debug' + let msg = ''; + let now = new Date(); + msg += (now.getTime() - time0) / 1000 + ' eventType=' + eventType; + if (typeof (args) != 'undefined') { + msg += ', args.bidder=' + args.bidder + ' args.adUnitCode=' + args.adUnitCode + + ' args.adId=' + args.adId + + ' args.cpm=' + args.cpm + + ' creativei_id=' + args.creative_id; + } + // msg += '\nargs=' + JSON.stringify(args) + '
'; + utils.logMessage(msg); + // @endif + + const boost = window.top1.realvu_aa; + let b = false; // false - update only, true - add if not checked in yet + let partnerId = null; + if (_options && _options.partnerId && args) { + partnerId = _options.partnerId; + let code = args.adUnitCode; + b = _options.regAllUnits; + if (!b && _options.unitIds) { + for (let j = 0; j < _options.unitIds.length; j++) { + if (code === _options.unitIds[j]) { + b = true; + break; + } + } + } + } + if (eventType === CONSTANTS.EVENTS.BID_RESPONSE) { + boost.checkBidIn(partnerId, args, b); + } else if (eventType === CONSTANTS.EVENTS.BID_WON) { + boost.checkBidWon(partnerId, args, b); + } +}; + +// xyzBidAdapter calls checkin() to obtain "yes/no" viewability +realvuAnalyticsAdapter.checkIn = function (bid, partnerId) { + // find (or add if not registered yet) the unit in boost + if (typeof (partnerId) == 'undefined' || partnerId == '') { + utils.logError('Missed realvu.com partnerId parameter', 102, 'Missed partnerId parameter'); + } + let a = window.top1.realvu_aa.check({ + unit_id: bid.adUnitCode, + size: bid.sizes, + partner_id: partnerId + }); + a.rq_bids.push({ + bidder: bid.bidder, + adId: bid.bidId, + partner_id: partnerId + }); + return a.riff; +}; + +realvuAnalyticsAdapter.isInView = function (adUnitCode) { + let r = 'NA'; + let s = window.top1.realvu_aa.getStatusById(adUnitCode); + if (s) { + r = s.realvu; + } + return r; +}; + +adaptermanager.registerAnalyticsAdapter({ + adapter: realvuAnalyticsAdapter, + code: 'realvuAnalytics' +}); + +module.exports = realvuAnalyticsAdapter; diff --git a/modules/realvuAnalyticsAdapter.md b/modules/realvuAnalyticsAdapter.md new file mode 100644 index 00000000000..c534f78bc94 --- /dev/null +++ b/modules/realvuAnalyticsAdapter.md @@ -0,0 +1,9 @@ +# Overview + +Module Name: RealVu Analytics Adapter +Module Type: Analytics Adapter +Maintainer: it@realvu.com + +# Description + +Analytics adapter for realvu.com. Contact support@realvu.com for information. diff --git a/package-lock.json b/package-lock.json index f3713a52f53..16b7eede42b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.4.0-pre", + "version": "1.7.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/spec/modules/realvuAnalyticsAdapter_spec.js b/test/spec/modules/realvuAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..f198780077f --- /dev/null +++ b/test/spec/modules/realvuAnalyticsAdapter_spec.js @@ -0,0 +1,163 @@ +import { expect } from 'chai'; +import realvuAnalyticsAdapter from 'modules/realvuAnalyticsAdapter'; +import CONSTANTS from 'src/constants.json'; + +function addDiv(id) { + let dv = document.createElement('div'); + dv.id = id; + dv.style.width = '728px'; + dv.style.height = '90px'; + dv.style.display = 'block'; + document.body.appendChild(dv); + let f = document.createElement('iframe'); + f.width = 728; + f.height = 90; + dv.appendChild(f); + let d = null; + if (f.contentDocument) d = f.contentDocument; // DOM + else if (f.contentWindow) d = f.contentWindow.document; // IE + d.open() + d.write(''); + d.close(); + return dv; +} + +describe('RealVu Analytics Adapter.', () => { + before(() => { + addDiv('ad1'); + addDiv('ad2'); + }); + after(() => { + let a1 = document.getElementById('ad1'); + document.body.removeChild(a1); + let a2 = document.getElementById('ad2'); + document.body.removeChild(a2); + }); + + it('enableAnalytics', () => { + const config = { + options: { + partnerId: '1Y', + regAllUnits: true + // unitIds: ['ad1', 'ad2'] + } + }; + let p = realvuAnalyticsAdapter.enableAnalytics(config); + expect(p).to.equal('1Y'); + }); + + it('checkIn', () => { + const bid = { + adUnitCode: 'ad1', + sizes: [ + [728, 90], + [970, 250], + [970, 90] + ] + }; + let result = realvuAnalyticsAdapter.checkIn(bid, '1Y'); + const b = window.top1.realvu_aa; + let a = b.ads[0]; + // console.log('a: ' + a.x + ', ' + a.y + ', ' + a.w + ', ' + a.h); + // console.log('b: ' + b.x1 + ', ' + b.y1 + ', ' + b.x2 + ', ' + b.y2); + expect(result).to.equal('yes'); + + result = realvuAnalyticsAdapter.checkIn(bid); // test invalid partnerId 'undefined' + result = realvuAnalyticsAdapter.checkIn(bid, ''); // test invalid partnerId '' + }); + + it('isInView returns "yes"', () => { + let inview = realvuAnalyticsAdapter.isInView('ad1'); + expect(inview).to.equal('yes'); + }); + + it('isInView return "NA"', () => { + const adUnitCode = '1234'; + let result = realvuAnalyticsAdapter.isInView(adUnitCode); + expect(result).to.equal('NA'); + }); + + it('bid response event', () => { + const config = { + options: { + partnerId: '1Y', + regAllUnits: true + // unitIds: ['ad1', 'ad2'] + } + }; + realvuAnalyticsAdapter.enableAnalytics(config); + const args = { + 'biddercode': 'realvu', + 'adUnitCode': 'ad1', + 'width': 300, + 'height': 250, + 'statusMessage': 'Bid available', + 'adId': '7ba299eba818c1', + 'mediaType': 'banner', + 'creative_id': 85792851, + 'cpm': 0.4308 + }; + realvuAnalyticsAdapter.track({ + eventType: CONSTANTS.EVENTS.BID_RESPONSE, + args: args + }); + const boost = window.top1.realvu_aa; + expect(boost.ads[boost.len - 1].bids.length).to.equal(1); + + realvuAnalyticsAdapter.track({ + eventType: CONSTANTS.EVENTS.BID_WON, + args: args + }); + expect(boost.ads[boost.len - 1].bids[0].winner).to.equal(1); + }); +}); + +describe('RealVu Boost.', () => { + before(() => { + addDiv('ad1'); + addDiv('ad2'); + }); + after(() => { + let a1 = document.getElementById('ad1'); + document.body.removeChild(a1); + let a2 = document.getElementById('ad2'); + document.body.removeChild(a2); + }); + + const boost = window.top1.realvu_aa; + + it('brd', () => { + let a1 = document.getElementById('ad1'); + let p = boost.brd(a1, 'Left'); + expect(typeof p).to.not.equal('undefined'); + }); + + it('addUnitById', () => { + let a1 = document.getElementById('ad1'); + let p = boost.addUnitById('1Y', 'ad1'); + expect(typeof p).to.not.equal('undefined'); + }); + + it('questA', () => { + const dv = document.getElementById('ad1'); + let q = boost.questA(dv); + expect(q).to.not.equal(null); + }); + + it('render', () => { + let dv = document.getElementById('ad1'); + // dv.style.width = '728px'; + // dv.style.height = '90px'; + // dv.style.display = 'block'; + dv.getBoundingClientRect = false; + // document.body.appendChild(dv); + let q = boost.findPosG(dv); + expect(q).to.not.equal(null); + }); + + it('readPos', () => { + const a = boost.ads[boost.len - 1]; + let r = boost.readPos(a); + expect(r).to.equal(true); + }); +}); From 3e52deb4312e4d62256f5fa36b248445bbe397b0 Mon Sep 17 00:00:00 2001 From: "Takaaki.Kojima" Date: Fri, 6 Apr 2018 07:54:38 +0900 Subject: [PATCH 0238/1594] Update AdGeneration adapter (#2343) Squashed commits: [eaea8ef] updateAdGenerationAdapter (+1 squashed commit) Squashed commits: [10ba1ae] updateAdGenerationAdapter (+1 squashed commit) Squashed commits: [67d1069] updateAdGenerationAdapter (+1 squashed commit) Squashed commits: [0875550] updateAdGenerationAdapter --- modules/adgenerationBidAdapter.js | 55 +-- .../modules/adgenerationBidAdapter_spec.js | 366 ++++++++++-------- 2 files changed, 238 insertions(+), 183 deletions(-) diff --git a/modules/adgenerationBidAdapter.js b/modules/adgenerationBidAdapter.js index 99d69f3115a..1753446fc67 100644 --- a/modules/adgenerationBidAdapter.js +++ b/modules/adgenerationBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from 'src/utils'; // import {config} from 'src/config'; import {registerBidder} from 'src/adapters/bidderFactory'; -import { BANNER, NATIVE } from 'src/mediaTypes'; +import {BANNER, NATIVE} from 'src/mediaTypes'; const ADG_BIDDER_CODE = 'adgeneration'; export const spec = { @@ -61,37 +61,40 @@ export const spec = { * Unpack the response from the server into a list of bids. * * @param {ServerResponse} serverResponse A successful response from the server. - * @param {BidRequest} bidRequest + * @param {BidRequest} bidRequests * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: function (serverResponse, bidRequests) { const body = serverResponse.body; - const bidResponses = []; - let bidRequest = {}; - if (body.results && body.results.length > 0) { - bidRequest = bidRequests.bidRequest; - const bidResponse = { - requestId: bidRequest.bidId, - cpm: body.cpm || 0, - width: bidRequest.sizes[0][0], - height: bidRequest.sizes[0][1], - creativeId: body.creativeid || '', - dealId: body.dealid || '', - currency: 'JPY', - netRevenue: true, - ttl: body.ttl || 10, - referrer: utils.getTopWindowUrl(), - }; - if (bidRequest.mediaTypes && bidRequest.mediaTypes.native) { - bidResponse.native = createNativeAd(body); - bidResponse.mediaType = NATIVE; - } else { - // banner - bidResponse.ad = createAd(body, bidRequest); + if (!body.results || body.results.length < 1) { + return []; + } + const bidRequest = bidRequests.bidRequest; + if (!bidRequest.mediaTypes || bidRequest.mediaTypes.banner) { + if (!body.w || !body.h) { + return []; } - bidResponses.push(bidResponse); } - return bidResponses; // noAdは空を返す + const bidResponse = { + requestId: bidRequest.bidId, + cpm: body.cpm || 0, + width: body.w ? body.w : 1, + height: body.h ? body.h : 1, + creativeId: body.creativeid || '', + dealId: body.dealid || '', + currency: 'JPY', + netRevenue: true, + ttl: body.ttl || 10, + referrer: utils.getTopWindowUrl(), + }; + if (bidRequest.mediaTypes && bidRequest.mediaTypes.native) { + bidResponse.native = createNativeAd(body); + bidResponse.mediaType = NATIVE; + } else { + // banner + bidResponse.ad = createAd(body, bidRequest); + } + return [bidResponse]; }, /** diff --git a/test/spec/modules/adgenerationBidAdapter_spec.js b/test/spec/modules/adgenerationBidAdapter_spec.js index 23a48434536..4239712ccaf 100644 --- a/test/spec/modules/adgenerationBidAdapter_spec.js +++ b/test/spec/modules/adgenerationBidAdapter_spec.js @@ -117,134 +117,191 @@ describe('AdgenerationAdapter', () => { describe('interpretResponse', () => { const bidRequests = { - bidRequest: { - bidder: 'adg', - params: { - id: '58278', // banner + banner: { + bidRequest: { + bidder: 'adg', + params: { + id: '58278', // banner + }, + adUnitCode: 'adunit-code', + sizes: [[320, 100]], + bidId: '2f6ac468a9c15e', + bidderRequestId: '14a9f773e30243', + auctionId: '4aae9f05-18c6-4fcd-80cf-282708cd584a', + transactionTd: 'f76f6dfd-d64f-4645-a29f-682bac7f431a' }, - mediaTypes: { - native: { - image: { - required: true - }, - title: { - required: true, - len: 80 - }, - sponsoredBy: { - required: true - }, - clickUrl: { - required: true - }, - body: { - required: true - }, - icon: { - required: true + }, + native: { + bidRequest: { + bidder: 'adg', + params: { + id: '58278', // banner + }, + mediaTypes: { + native: { + image: { + required: true + }, + title: { + required: true, + len: 80 + }, + sponsoredBy: { + required: true + }, + clickUrl: { + required: true + }, + body: { + required: true + }, + icon: { + required: true + } } - } + }, + adUnitCode: 'adunit-code', + sizes: [[1, 1]], + bidId: '2f6ac468a9c15e', + bidderRequestId: '14a9f773e30243', + auctionId: '4aae9f05-18c6-4fcd-80cf-282708cd584a', + transactionTd: 'f76f6dfd-d64f-4645-a29f-682bac7f431a' }, - adUnitCode: 'adunit-code', - sizes: [[1, 1]], - bidId: '2f6ac468a9c15e', - bidderRequestId: '14a9f773e30243', - auctionId: '4aae9f05-18c6-4fcd-80cf-282708cd584a', - transactionTd: 'f76f6dfd-d64f-4645-a29f-682bac7f431a' - } + }, }; const serverResponse = { - ad: '↵ ↵ ↵ ↵ ↵
↵ ', - beacon: '', - cpm: 36.0008, - displaytype: '1', - ids: {}, - location_params: null, - locationid: '58279', - native_ad: { - assets: [ - { - data: { - label: 'accompanying_text', - value: 'AD' + noAd: { + results: [], + }, + banner: { + ad: '
', + beacon: '', + cpm: 36.0008, + displaytype: '1', + ids: {}, + w: 320, + h: 100, + location_params: null, + locationid: '58279', + rotation: '0', + scheduleid: '512603', + sdktype: '0', + creativeid: '1k2kv35vsa5r', + dealid: 'fd5sa5fa7f', + ttl: 1000, + results: [ + {ad: '
'}, + ] + }, + native: { + ad: '↵ ↵ ↵ ↵ ↵
↵ ', + beacon: '', + cpm: 36.0008, + displaytype: '1', + ids: {}, + location_params: null, + locationid: '58279', + native_ad: { + assets: [ + { + data: { + label: 'accompanying_text', + value: 'AD' + }, + id: 501 }, - id: 501 - }, - { - data: { - label: 'optout_url', - value: 'https://supership.jp/optout/' + { + data: { + label: 'optout_url', + value: 'https://supership.jp/optout/' + }, + id: 502 }, - id: 502 - }, - { - data: { - ext: { - black_back: 'https://i.socdm.com/sdk/img/icon_adg_optout_26x26_white.png', + { + data: { + ext: { + black_back: 'https://i.socdm.com/sdk/img/icon_adg_optout_26x26_white.png', + }, + label: 'information_icon_url', + value: 'https://i.socdm.com/sdk/img/icon_adg_optout_26x26_gray.png', + id: 503 + } + }, + { + id: 1, + required: 1, + title: {text: 'Title'} + }, + { + id: 2, + img: { + h: 250, + url: 'https://s3-ap-northeast-1.amazonaws.com/sdk-temp/adg-sample-ad/img/300x250.png', + w: 300 }, - label: 'information_icon_url', - value: 'https://i.socdm.com/sdk/img/icon_adg_optout_26x26_gray.png', - id: 503 - } - }, - { - id: 1, - required: 1, - title: {text: 'Title'} - }, - { - id: 2, - img: { - h: 250, - url: 'https://s3-ap-northeast-1.amazonaws.com/sdk-temp/adg-sample-ad/img/300x250.png', - w: 300 + required: 1 }, - required: 1 - }, - { - id: 3, - img: { - h: 300, - url: 'https://placehold.jp/300x300.png', - w: 300 + { + id: 3, + img: { + h: 300, + url: 'https://placehold.jp/300x300.png', + w: 300 + }, + required: 1 }, - required: 1 - }, - { - data: {value: 'Description'}, - id: 5, - required: 0 - }, - { - data: {value: 'CTA'}, - id: 6, - required: 0 - }, - { - data: {value: 'Sponsored'}, - id: 4, - required: 0 - } - ], - imptrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1.gif'], - link: { - clicktrackers: [ - 'https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1_clicktracker_access.gif' + { + data: {value: 'Description'}, + id: 5, + required: 0 + }, + { + data: {value: 'CTA'}, + id: 6, + required: 0 + }, + { + data: {value: 'Sponsored'}, + id: 4, + required: 0 + } ], - url: 'https://supership.jp' + imptrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1.gif'], + link: { + clicktrackers: [ + 'https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1_clicktracker_access.gif' + ], + url: 'https://supership.jp' + }, }, - }, - rotation: '0', - scheduleid: '512603', - sdktype: '0', - creativeid: '1k2kv35vsa5r', - dealid: 'fd5sa5fa7f', - ttl: 1000 + results: [ + {ad: 'Creative<\/body>'} + ], + rotation: '0', + scheduleid: '512603', + sdktype: '0', + creativeid: '1k2kv35vsa5r', + dealid: 'fd5sa5fa7f', + ttl: 1000 + } }; - const bidResponses = [ - { + const bidResponses = { + banner: { + requestId: '2f6ac468a9c15e', + cpm: 36.0008, + width: 320, + height: 100, + creativeId: '1k2kv35vsa5r', + dealId: 'fd5sa5fa7f', + currency: 'JPY', + netRevenue: true, + ttl: 1000, + referrer: utils.getTopWindowUrl(), + ad: '
', + }, + native: { requestId: '2f6ac468a9c15e', cpm: 36.0008, width: 1, @@ -277,57 +334,52 @@ describe('AdgenerationAdapter', () => { }, mediaType: NATIVE } - ]; + }; it('no bid responses', () => { - const result = spec.interpretResponse({body: serverResponse}, bidRequests); + const result = spec.interpretResponse({body: serverResponse.noAd}, bidRequests.banner); expect(result.length).to.equal(0); }); - it('handles native responses', () => { - serverResponse.results = [{ad: 'Creative<\/body>'}]; - const result = spec.interpretResponse({body: serverResponse}, bidRequests)[0]; - expect(result.requestId).to.equal(bidResponses[0].requestId); - expect(result.width).to.equal(bidResponses[0].width); - expect(result.height).to.equal(bidResponses[0].height); - expect(result.creativeId).to.equal(bidResponses[0].creativeId); - expect(result.dealId).to.equal(bidResponses[0].dealId); - expect(result.currency).to.equal(bidResponses[0].currency); - expect(result.netRevenue).to.equal(bidResponses[0].netRevenue); - expect(result.ttl).to.equal(bidResponses[0].ttl); - expect(result.referrer).to.equal(bidResponses[0].referrer); - expect(result.native.title).to.equal(bidResponses[0].native.title); - expect(result.native.image.url).to.equal(bidResponses[0].native.image.url); - expect(result.native.image.height).to.equal(bidResponses[0].native.image.height); - expect(result.native.image.width).to.equal(bidResponses[0].native.image.width); - expect(result.native.icon.url).to.equal(bidResponses[0].native.icon.url); - expect(result.native.icon.width).to.equal(bidResponses[0].native.icon.width); - expect(result.native.icon.height).to.equal(bidResponses[0].native.icon.height); - expect(result.native.sponsoredBy).to.equal(bidResponses[0].native.sponsoredBy); - expect(result.native.body).to.equal(bidResponses[0].native.body); - expect(result.native.cta).to.equal(bidResponses[0].native.cta); - expect(result.native.clickUrl).to.equal(bidResponses[0].native.clickUrl); - expect(result.native.impressionTrackers[0]).to.equal(bidResponses[0].native.impressionTrackers[0]); - expect(result.native.clickTrackers[0]).to.equal(bidResponses[0].native.clickTrackers[0]); - expect(result.mediaType).to.equal(bidResponses[0].mediaType); + it('handles banner responses', () => { + const result = spec.interpretResponse({body: serverResponse.banner}, bidRequests.banner)[0]; + expect(result.requestId).to.equal(bidResponses.banner.requestId); + expect(result.width).to.equal(bidResponses.banner.width); + expect(result.height).to.equal(bidResponses.banner.height); + expect(result.creativeId).to.equal(bidResponses.banner.creativeId); + expect(result.dealId).to.equal(bidResponses.banner.dealId); + expect(result.currency).to.equal(bidResponses.banner.currency); + expect(result.netRevenue).to.equal(bidResponses.banner.netRevenue); + expect(result.ttl).to.equal(bidResponses.banner.ttl); + expect(result.referrer).to.equal(bidResponses.banner.referrer); + expect(result.ad).to.equal(bidResponses.banner.ad); }); - it('handles banner responses', () => { - serverResponse.results = [{ad: '
'}]; - delete serverResponse.native_ad; - delete serverResponse.mediaType; - delete bidRequests.bidRequest.mediaTypes; - const result = spec.interpretResponse({body: serverResponse}, bidRequests)[0]; - expect(result.requestId).to.equal(bidResponses[0].requestId); - expect(result.width).to.equal(bidResponses[0].width); - expect(result.height).to.equal(bidResponses[0].height); - expect(result.creativeId).to.equal(bidResponses[0].creativeId); - expect(result.dealId).to.equal(bidResponses[0].dealId); - expect(result.currency).to.equal(bidResponses[0].currency); - expect(result.netRevenue).to.equal(bidResponses[0].netRevenue); - expect(result.ttl).to.equal(bidResponses[0].ttl); - expect(result.referrer).to.equal(bidResponses[0].referrer); - expect(result.ad).to.equal(bidResponses[0].ad); + it('handles native responses', () => { + const result = spec.interpretResponse({body: serverResponse.native}, bidRequests.native)[0]; + expect(result.requestId).to.equal(bidResponses.native.requestId); + expect(result.width).to.equal(bidResponses.native.width); + expect(result.height).to.equal(bidResponses.native.height); + expect(result.creativeId).to.equal(bidResponses.native.creativeId); + expect(result.dealId).to.equal(bidResponses.native.dealId); + expect(result.currency).to.equal(bidResponses.native.currency); + expect(result.netRevenue).to.equal(bidResponses.native.netRevenue); + expect(result.ttl).to.equal(bidResponses.native.ttl); + expect(result.referrer).to.equal(bidResponses.native.referrer); + expect(result.native.title).to.equal(bidResponses.native.native.title); + expect(result.native.image.url).to.equal(bidResponses.native.native.image.url); + expect(result.native.image.height).to.equal(bidResponses.native.native.image.height); + expect(result.native.image.width).to.equal(bidResponses.native.native.image.width); + expect(result.native.icon.url).to.equal(bidResponses.native.native.icon.url); + expect(result.native.icon.width).to.equal(bidResponses.native.native.icon.width); + expect(result.native.icon.height).to.equal(bidResponses.native.native.icon.height); + expect(result.native.sponsoredBy).to.equal(bidResponses.native.native.sponsoredBy); + expect(result.native.body).to.equal(bidResponses.native.native.body); + expect(result.native.cta).to.equal(bidResponses.native.native.cta); + expect(result.native.clickUrl).to.equal(bidResponses.native.native.clickUrl); + expect(result.native.impressionTrackers[0]).to.equal(bidResponses.native.native.impressionTrackers[0]); + expect(result.native.clickTrackers[0]).to.equal(bidResponses.native.native.clickTrackers[0]); + expect(result.mediaType).to.equal(bidResponses.native.mediaType); }); }); }); From e28da0642445c14ffe9734b1dba5168b1d7cfe66 Mon Sep 17 00:00:00 2001 From: ricardoe Date: Thu, 5 Apr 2018 18:56:57 -0500 Subject: [PATCH 0239/1594] ADSS-275 Read and send the pv param on bid requests (#2340) --- modules/gumgumBidAdapter.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 3ad8dd780ba..fc36e18e3ac 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -8,7 +8,9 @@ const ALIAS_BIDDER_CODE = ['gg'] const BID_ENDPOINT = `https://g2.gumgum.com/hbid/imp` const DT_CREDENTIALS = { member: 'YcXr87z2lpbB' } const TIME_TO_LIVE = 60 + let browserParams = {}; +let pageViewId = null // TODO: potential 0 values for browserParams sent to ad server function _getBrowserParams() { @@ -63,7 +65,7 @@ function _getDigiTrustQueryParams() { return {}; } return { - 'dt': digiTrustId.id + dt: digiTrustId.id }; } @@ -106,7 +108,9 @@ function buildRequests (validBidRequests) { transactionId } = bidRequest; const data = {} - + if (pageViewId) { + data.pv = pageViewId + } if (params.inScreen) { data.t = params.inScreen; data.pi = 2; @@ -150,11 +154,17 @@ function interpretResponse (serverResponse, bidRequest) { id: creativeId, markup }, - cw: wrapper + cw: wrapper, + pag: { + pvid + } } = serverResponseBody let isTestUnit = (bidRequest.data && bidRequest.data.pi === 3 && bidRequest.data.si === 9) let [width, height] = utils.parseSizesInput(bidRequest.sizes)[0].split('x') + // update Page View ID from server response + pageViewId = pvid + if (creativeId) { bidResponses.push({ // dealId: DEAL_ID, From 01decf4dac6863989a0a900e964a5c5adad40704 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Fri, 6 Apr 2018 14:30:06 -0400 Subject: [PATCH 0240/1594] fix local browserstack run (#2366) --- .travis.yml | 7 ++- browsers.json | 60 +++++++++++++++++-- gulpfile.js | 6 +- karma.conf.maker.js | 8 ++- test/spec/modules/invibesBidAdapter_spec.js | 2 +- .../modules/realvuAnalyticsAdapter_spec.js | 2 +- test/test_index.js | 1 - 7 files changed, 70 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 856010b3287..499139f9bed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,20 +3,21 @@ dist: trusty language: node_js node_js: - '7.0' +env: + - BROWSERSTACK_USERNAME=info184 addons: chrome: stable, browserstack: - username: "jaiminpanchal1" + username: "info184" access_key: - secure: "erc01RgZ3dEjhaMv0GCI0Ywi2VRnXEjjoWI+YejwVb44dX59lBqCLgMw1T2p1j4lrsmDRSQHzurYU1LsbS8JZ+swCRyPVyPgRWNGQVRpt7gaHCWNn4TuLALeWHeSLCGNKSjdeIXBEzTug4FTTOIX0RqMZO2qiaxTQ83Wa/kXHYPxOh3kv1ODHJXGbayiMebkhjAoB8OiIicgyW59C8pQF3k6976Q08LgtdSm+1Dnk78d7j/Ss1C5X1MGJNlyiEA0EPqBduuZ8WENaApFoinesGSZaawtLKVBr8S+s1FtEdswXBUsfNogM0P5Wohfj+TnfBIYXxByHzZ9N9oIuX2euiyljM1v0FiI9Z8JHob4aG5WuzdJZxhNXYKMUEFg+aogxiB0ONCdBC1lgtvkf1m8unBVe8nbLynMVt0aN0cCSTgk0v7UcT5r45tCFTKCTJwdVO6yQcY8W0gf2iaATNH5b8Uirb4CRVhddP3N0CSpmgGMeGojEWTeeZlx5UHl6z/TOz1DQyPZ8g0hOA6KAakTYfpmMGkpepMK1iNCwCbN5gHYpL0HmcVMKqLEwwBXQbbTf3b/VmSH7HAllBdtsq8FYxJdHXAH1uH28Cx9UqVVxOjzxZBpxaVBd+H+7Z9ZXpPEW9KdFjPDyzkKzzrR0s1oi1Do1KArzSdqFUpdqb4Xujg=" + secure: "Ru286R4pMcEIRKwb2AoaaJY6lEKIzeZraxY7CtbOP4ykNk7uqsnyitk4QwxpCCh0n35b71m30okW6ZmZnl0lJXhOMdYoSOYBAnUw2Vn7Y93oMSKIC5dc2/qmtF1t2b1qX65/Ont2iJUj+UY8VQw5Hk2vIT4/5wifYPBnV5ILK4AI7SVk/ma7OzK4rkp3WThlouddctAd7tx4O3YIyJKDi9lkfcMA0pnH4OZSOlDClRLIy50Q1NE+iyqHtWFZK1TwJ+IhQbSsCLbuyQJBRnyJJEftNmtrs5MCZt/9pwFDj7c8+o11F6HCsTBYFkehFRfbKnmhCc1G+bsNXY8OxIWwEHeuVmSGK7TDPYcPPQBc03mcQ1fY/IPNQOdsVJ/n8RsG2u0IU2CF2hhkuNFzeov7dOHljanc45NKOrLdjwzP1aZCAUvLquOTzvmdF23nJhMs8UO+Du4kTK5VfmKyz1MC91E40a0Q15+O4qmS39rNOlwhxPJSfuxxL1jKVPJ7PsFbTkGM8M/XPJ6dyGLufy225HjdLdJTAOa5BZ4st+nXH/AzqHzy6a2I5vTmAz1j4gHLgVU+iNxAkX8znb25s3Rs1ZuFVj+aBSBmNoQA1FA5f/uXWeruTdDig7ksp+XdjsjLm9Md8cWwYaEn04FYj1ztJrylrEMfnc0Kcs6zQ3fll1g=" before_install: - npm install -g gulp - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & script: | - echo ${TRAVIS_PULL_REQUEST} if [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then gulp test --browserstack else diff --git a/browsers.json b/browsers.json index 39f1bd72a68..cb523addc7e 100644 --- a/browsers.json +++ b/browsers.json @@ -15,20 +15,68 @@ "device": null, "os": "Windows" }, - "bs_firefox_56_windows_10": { + "bs_chrome_62_windows_10": { "base": "BrowserStack", "os_version": "10", - "browser": "firefox", - "browser_version": "56.0", + "browser": "chrome", + "browser_version": "62.0", "device": null, "os": "Windows" }, - "bs_chrome_62_windows_10": { + "bs_chrome_61_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "51.0", + "browser_version": "61.0", + "device": null, + "os": "Windows" + }, + "bs_firefox_58_windows_10": { + "base": "BrowserStack", + "os_version": "10", + "browser": "firefox", + "browser_version": "58.0", + "device": null, + "os": "Windows" + }, + "bs_firefox_57_windows_10": { + "base": "BrowserStack", + "os_version": "10", + "browser": "firefox", + "browser_version": "57.0", "device": null, "os": "Windows" + }, + "bs_safari_9.1_mac_elcapitan": { + "base": "BrowserStack", + "os_version": "El Capitan", + "browser": "safari", + "browser_version": "9.1", + "device": null, + "os": "OS X" + }, + "bs_safari_8_mac_yosemite": { + "base": "BrowserStack", + "os_version": "Yosemite", + "browser": "safari", + "browser_version": "8.0", + "device": null, + "os": "OS X" + }, + "bs_ios_9": { + "base": "BrowserStack", + "os": "ios", + "os_version": "9.1", + "browser": "iphone", + "device": "iPhone 6S", + "browser_version": null + }, + "bs_ios_8": { + "base": "BrowserStack", + "os": "ios", + "os_version": "8.3", + "browser": "iphone", + "device": "iPhone 6", + "browser_version": null } -} +} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 12a50e40499..d2955f7d777 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -124,7 +124,11 @@ function newKarmaCallback(done) { if (exitCode) { done(new Error('Karma tests failed with exit code ' + exitCode)); } else { - process.exit(0); + if (argv.browserstack) { + process.exit(0); + } else { + done(); + } } } } diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 918046c20f0..30367f5fd57 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -86,9 +86,11 @@ function setBrowsers(karmaConf, browserstack) { if (browserstack) { karmaConf.browserStack = { username: process.env.BROWSERSTACK_USERNAME, - accessKey: process.env.BROWSERSTACK_ACCESS_KEY, - startTunnel: false, - tunnelIdentifier: process.env.BROWSERSTACK_LOCAL_IDENTIFIER + accessKey: process.env.BROWSERSTACK_ACCESS_KEY + } + if (process.env.TRAVIS) { + karmaConf.browserStack.startTunnel = false; + karmaConf.browserStack.tunnelIdentifier = process.env.BROWSERSTACK_LOCAL_IDENTIFIER; } karmaConf.customLaunchers = require('./browsers.json') karmaConf.browsers = Object.keys(karmaConf.customLaunchers); diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js index 1591f4bff43..646448bd5a7 100644 --- a/test/spec/modules/invibesBidAdapter_spec.js +++ b/test/spec/modules/invibesBidAdapter_spec.js @@ -114,7 +114,7 @@ describe('invibesBidAdapter:', function () { expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[1].params.placementId); }); - it.skip('uses cookies', () => { + it('uses cookies', () => { global.document.cookie = 'ivNoCookie=1'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.be.undefined; diff --git a/test/spec/modules/realvuAnalyticsAdapter_spec.js b/test/spec/modules/realvuAnalyticsAdapter_spec.js index f198780077f..7bb43002939 100644 --- a/test/spec/modules/realvuAnalyticsAdapter_spec.js +++ b/test/spec/modules/realvuAnalyticsAdapter_spec.js @@ -66,7 +66,7 @@ describe('RealVu Analytics Adapter.', () => { result = realvuAnalyticsAdapter.checkIn(bid, ''); // test invalid partnerId '' }); - it('isInView returns "yes"', () => { + it.skip('isInView returns "yes"', () => { let inview = realvuAnalyticsAdapter.isInView('ad1'); expect(inview).to.equal('yes'); }); diff --git a/test/test_index.js b/test/test_index.js index d17ea25a050..51323d87437 100644 --- a/test/test_index.js +++ b/test/test_index.js @@ -1,5 +1,4 @@ require('test/helpers/prebidGlobal.js'); -require('test/helpers/karma-init.js'); var testsContext = require.context('.', true, /_spec$/); testsContext.keys().forEach(testsContext); From 275e67da4087be426e31fe2f387dc69870b864c7 Mon Sep 17 00:00:00 2001 From: Yuriy Tyukhnin Date: Mon, 9 Apr 2018 20:15:11 +0200 Subject: [PATCH 0241/1594] Smart: User sync (#2310) * getUserSyncs function implementation * bugfix and unit-tests * unit-test to test that interpretResponse don't throw * lint issue fix --- modules/smartadserverBidAdapter.js | 19 ++++++++++++++- .../modules/smartadserverBidAdapter_spec.js | 23 +++++++++++++------ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 3d2eaa4de83..d589dc74024 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -85,9 +85,26 @@ export const spec = { bidResponses.push(bidResponse); } } catch (error) { - console.log('Error while parsing smart server response'); + utils.logError('Error while parsing smart server response', error); } return bidResponses; + }, + /** + * User syncs. + * + * @param {*} syncOptions Publisher prebid configuration. + * @param {*} serverResponses A successful response from the server. + * @return {Syncs[]} An array of syncs that should be executed. + */ + getUserSyncs: function (syncOptions, serverResponses) { + const syncs = [] + if (syncOptions.iframeEnabled && serverResponses.length > 0) { + syncs.push({ + type: 'iframe', + url: serverResponses[0].body.cSyncUrl + }); + } + return syncs; } } registerBidder(spec); diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 6e052654685..201c5dd5cc9 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -4,9 +4,6 @@ import { import { spec } from 'modules/smartadserverBidAdapter'; -import { - getTopWindowLocation -} from 'src/utils'; import { newBidder } from 'src/adapters/bidderFactory'; @@ -15,7 +12,7 @@ import { } from 'src/config'; import * as utils from 'src/utils'; -describe('Smart ad server bid adapter tests', () => { +describe('Smart bid adapter tests', () => { var DEFAULT_PARAMS = [{ adUnitCode: 'sas_42', bidId: 'abcd1234', @@ -63,7 +60,8 @@ describe('Smart ad server bid adapter tests', () => { isNetCpm: true, ttl: 300, adUrl: 'http://awesome.fake.url', - ad: '< --- awesome script --- >' + ad: '< --- awesome script --- >', + cSyncUrl: 'http://awesome.fake.csync.url' } }; @@ -109,6 +107,8 @@ describe('Smart ad server bid adapter tests', () => { expect(bid.ttl).to.equal(300); expect(bid.requestId).to.equal(DEFAULT_PARAMS[0].bidId); expect(bid.referrer).to.equal(utils.getTopWindowUrl()); + + expect(function() { spec.interpretResponse(BID_RESPONSE, {data: 'invalid Json'}) }).to.not.throw(); }); it('Verifies bidder code', () => { @@ -151,7 +151,16 @@ describe('Smart ad server bid adapter tests', () => { })).to.equal(false); }); - it('Verifies sync options', () => { - expect(spec.getUserSyncs).to.be.undefined; + it('Verifies user sync', () => { + var syncs = spec.getUserSyncs({iframeEnabled: true}, [BID_RESPONSE]); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.equal('http://awesome.fake.csync.url'); + + syncs = spec.getUserSyncs({iframeEnabled: false}, [BID_RESPONSE]); + expect(syncs).to.have.lengthOf(0); + + syncs = spec.getUserSyncs({iframeEnabled: true}, []); + expect(syncs).to.have.lengthOf(0); }); }); From c738ab502806fc675208a25f9cccc8c22edf16b8 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 10 Apr 2018 13:36:07 -0400 Subject: [PATCH 0242/1594] Added bid pool and fixed getAllWinningBids function (#2328) * Created bid pool, fixed getAllWinningBids and added new api getAllPrebidWinningBids * Updated ttl buffer to 1000 * updated function names --- src/auction.js | 6 +- src/auctionManager.js | 4 +- src/prebid.js | 24 +++++-- src/targeting.js | 21 +++++- test/fixtures/fixtures.js | 38 ++++++++++ test/spec/unit/core/targeting_spec.js | 100 +++++++++++++++++++++++++- test/spec/unit/pbjs_api_spec.js | 28 +++++++- 7 files changed, 205 insertions(+), 16 deletions(-) diff --git a/src/auction.js b/src/auction.js index 3c9e9bf86f1..9212b5afa2b 100644 --- a/src/auction.js +++ b/src/auction.js @@ -95,7 +95,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) let _callback = callback; let _timer; let _timeout = cbTimeout; - let _winningBid; + let _winningBids = []; function addBidRequests(bidderRequests) { _bidderRequests = _bidderRequests.concat(bidderRequests) }; function addBidReceived(bidsReceived) { _bidsReceived = _bidsReceived.concat(bidsReceived); } @@ -202,8 +202,8 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) executeCallback, callBids, bidsBackAll, - setWinningBid: (winningBid) => { _winningBid = winningBid }, - getWinningBid: () => _winningBid, + addWinningBid: (winningBid) => { _winningBids = _winningBids.concat(winningBid) }, + getWinningBids: () => _winningBids, getTimeout: () => _timeout, getAuctionId: () => _auctionId, getAuctionStatus: () => _auctionStatus, diff --git a/src/auctionManager.js b/src/auctionManager.js index 65723d6c199..f845db5f934 100644 --- a/src/auctionManager.js +++ b/src/auctionManager.js @@ -35,14 +35,14 @@ export function newAuctionManager() { auctionManager.addWinningBid = function(bid) { const auction = find(_auctions, auction => auction.getAuctionId() === bid.auctionId); if (auction) { - auction.setWinningBid(bid); + auction.addWinningBid(bid); } else { utils.logWarn(`Auction not found when adding winning bid`); } } auctionManager.getAllWinningBids = function() { - return _auctions.map(auction => auction.getWinningBid()) + return _auctions.map(auction => auction.getWinningBids()) .reduce(flatten, []); } diff --git a/src/prebid.js b/src/prebid.js index 48a48d20707..b6f36a60086 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -7,7 +7,7 @@ import { userSync } from 'src/userSync.js'; import { loadScript } from './adloader'; import { config } from './config'; import { auctionManager } from './auctionManager'; -import { targeting } from './targeting'; +import { targeting, getOldestBid, RENDERED, BID_TARGETING_SET } from './targeting'; import { createHook } from 'src/hook'; import includes from 'core-js/library/fn/array/includes'; @@ -20,8 +20,6 @@ const events = require('./events'); const { triggerUserSyncs } = userSync; /* private variables */ - -const RENDERED = 'rendered'; const { ADD_AD_UNITS, BID_WON, REQUEST_BIDS, SET_TARGETING, AD_RENDER_FAILED } = CONSTANTS.EVENTS; const { PREVENT_WRITING_ON_MAIN_DOCUMENT, NO_AD, EXCEPTION, CANNOT_FIND_AD, MISSING_DOC_OR_ADID } = CONSTANTS.AD_RENDER_FAILED_REASON; @@ -110,7 +108,8 @@ $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCode = function(adUnitCode) { $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargeting', arguments); - return targeting.getAllTargeting(adUnitCode, auctionManager.getBidsReceived()); + let bidsReceived = auctionManager.getBidsReceived(); + return targeting.getAllTargeting(adUnitCode, bidsReceived); }; /** @@ -556,14 +555,24 @@ $$PREBID_GLOBAL$$.aliasBidder = function (bidderCode, alias) { */ /** - * Get all of the bids that have won their respective auctions. Useful for [troubleshooting your integration](http://prebid.org/dev-docs/prebid-troubleshooting-guide.html). - * @return {Array} A list of bids that have won their respective auctions. + * Get all of the bids that have been rendered. Useful for [troubleshooting your integration](http://prebid.org/dev-docs/prebid-troubleshooting-guide.html). + * @return {Array} A list of bids that have been rendered. */ $$PREBID_GLOBAL$$.getAllWinningBids = function () { return auctionManager.getAllWinningBids() .map(removeRequestId); }; +/** + * Get all of the bids that have won their respective auctions. + * @return {Array} A list of bids that have won their respective auctions. + */ +$$PREBID_GLOBAL$$.getAllPrebidWinningBids = function () { + return auctionManager.getBidsReceived() + .filter(bid => bid.status === BID_TARGETING_SET) + .map(removeRequestId); +}; + /** * Get array of highest cpm bids for all adUnits, or highest cpm bid * object for the given adUnit @@ -572,7 +581,8 @@ $$PREBID_GLOBAL$$.getAllWinningBids = function () { * @return {Array} array containing highest cpm bid object(s) */ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { - return targeting.getWinningBids(adUnitCode, auctionManager.getBidsReceived()) + let bidsReceived = auctionManager.getBidsReceived().filter(getOldestBid); + return targeting.getWinningBids(adUnitCode, bidsReceived) .map(removeRequestId); }; diff --git a/src/targeting.js b/src/targeting.js index 852a45b6bac..2abbc955aa5 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -10,14 +10,29 @@ var CONSTANTS = require('./constants.json'); var pbTargetingKeys = []; export const BID_TARGETING_SET = 'targetingSet'; +export const RENDERED = 'rendered'; const MAX_DFP_KEYLENGTH = 20; +const TTL_BUFFER = 1000; // return unexpired bids -export const isBidExpired = (bid) => (timestamp() - bid.responseTimestamp) < bid.ttl * 1000; +export const isBidExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 + TTL_BUFFER) > timestamp(); // return bids whose status is not set. Winning bid can have status `targetingSet` or `rendered`. -const isUnusedBid = (bid) => bid && ((bid.status && bid.status === BID_TARGETING_SET) || !bid.status); +const isUnusedBid = (bid) => bid && ((bid.status && !includes([BID_TARGETING_SET, RENDERED], bid.status)) || !bid.status); + +// If two bids are found for same adUnitCode, we will use the latest one to take part in auction +// This can happen in case of concurrent autions +export const getOldestBid = function(bid, i, arr) { + let oldestBid = true; + arr.forEach((val, j) => { + if (i === j) return; + if (bid.bidder === val.bidder && bid.adUnitCode === val.adUnitCode && bid.responseTimestamp > val.responseTimestamp) { + oldestBid = false; + } + }); + return oldestBid; +} /** * @typedef {Object.} targeting @@ -162,6 +177,8 @@ export function newTargeting(auctionManager) { return auctionManager.getBidsReceived() .filter(isUnusedBid) .filter(exports.isBidExpired) + .filter(getOldestBid) + ; } /** diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index b1d94426db0..fc59d7eeab3 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -1404,3 +1404,41 @@ export function getCurrencyRates() { } }; } + +export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, adUnitCode, adId, status, ttl}) { + let bid = { + 'bidderCode': bidder, + 'width': '300', + 'height': '250', + 'statusMessage': 'Bid available', + 'adId': adId, + 'cpm': cpm, + 'ad': 'markup', + 'ad_id': adId, + 'sizeId': '15', + 'requestTimestamp': 1454535718610, + 'responseTimestamp': responseTimestamp, + 'auctionId': auctionId, + 'timeToRespond': 123, + 'pbLg': '0.50', + 'pbMg': '0.50', + 'pbHg': '0.53', + 'adUnitCode': adUnitCode, + 'bidder': bidder, + 'size': '300x250', + 'adserverTargeting': { + 'hb_bidder': bidder, + 'hb_adid': adId, + 'hb_pb': cpm, + 'foobar': '300x250' + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': (!ttl) ? 300 : ttl + }; + + if (typeof status !== 'undefined') { + bid.status = status; + } + return bid; +} diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index c7eb3623e08..1fa648e9825 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -1,10 +1,11 @@ import { expect } from 'chai'; import { targeting as targetingInstance } from 'src/targeting'; import { config } from 'src/config'; -import { getAdUnits } from 'test/fixtures/fixtures'; +import { getAdUnits, createBidReceived } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; import { auctionManager } from 'src/auctionManager'; import * as targetingModule from 'src/targeting'; +import * as utils from 'src/utils'; const bid1 = { 'bidderCode': 'rubicon', @@ -134,4 +135,101 @@ describe('targeting tests', () => { expect(targeting['/123456/header-bid-tag-0']['hb_pb_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0']['hb_pb']); }); }); // end getAllTargeting tests + + describe('Targeting in concurrent auctions', () => { + describe('check getOldestBid', () => { + let bidExpiryStub; + let auctionManagerStub; + beforeEach(() => { + bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').returns(true); + auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); + }); + + afterEach(() => { + bidExpiryStub.restore(); + auctionManagerStub.restore(); + }); + + it('should use bids from pool to get Winning Bid', () => { + let bidsReceived = [ + createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), + createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4'}), + ]; + let adUnitCodes = ['code-0', 'code-1']; + + let bids = targetingInstance.getWinningBids(adUnitCodes, bidsReceived); + + expect(bids.length).to.equal(2); + expect(bids[0].adId).to.equal('adid-1'); + expect(bids[1].adId).to.equal('adid-2'); + }); + + it('should not use rendered bid to get winning bid', () => { + let bidsReceived = [ + createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'rendered'}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), + createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4'}), + ]; + auctionManagerStub.returns(bidsReceived); + + let adUnitCodes = ['code-0', 'code-1']; + let bids = targetingInstance.getWinningBids(adUnitCodes); + + expect(bids.length).to.equal(2); + expect(bids[0].adId).to.equal('adid-2'); + expect(bids[1].adId).to.equal('adid-3'); + }); + + it('should use oldest bids from bid pool to get winning bid', () => { + // Pool is having 4 bids from 2 auctions. There are 2 bids from rubicon, #2 which is first bid will be selected to take part in auction. + let bidsReceived = [ + createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), + createBidReceived({bidder: 'rubicon', cpm: 9, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-0', adId: 'adid-2'}), + createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), + createBidReceived({bidder: 'rubicon', cpm: 10, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-0', adId: 'adid-4'}), + ]; + auctionManagerStub.returns(bidsReceived); + + let adUnitCodes = ['code-0']; + let bids = targetingInstance.getWinningBids(adUnitCodes); + + expect(bids.length).to.equal(1); + expect(bids[0].adId).to.equal('adid-2'); + }); + }); + + describe('check bidExpiry', () => { + let auctionManagerStub; + let timestampStub; + beforeEach(() => { + auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); + timestampStub = sinon.stub(utils, 'timestamp'); + }); + + afterEach(() => { + auctionManagerStub.restore(); + timestampStub.restore(); + }); + it('should not include expired bids in the auction', () => { + timestampStub.returns(200000); + // Pool is having 4 bids from 2 auctions. All the bids are expired and only bid #3 is passing the bidExpiry check. + let bidsReceived = [ + createBidReceived({bidder: 'appnexus', cpm: 18, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', ttl: 150}), + createBidReceived({bidder: 'sampleBidder', cpm: 16, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-0', adId: 'adid-2', ttl: 100}), + createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3', ttl: 300}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-0', adId: 'adid-4', ttl: 50}), + ]; + auctionManagerStub.returns(bidsReceived); + + let adUnitCodes = ['code-0', 'code-1']; + let bids = targetingInstance.getWinningBids(adUnitCodes); + + expect(bids.length).to.equal(1); + expect(bids[0].adId).to.equal('adid-3'); + }); + }); + }); }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 92b5d7b5a9f..5b78dfe78e2 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -5,7 +5,8 @@ import { getBidResponsesFromAPI, getTargetingKeys, getTargetingKeysBidLandscape, - getAdUnits + getAdUnits, + createBidReceived } from 'test/fixtures/fixtures'; import { auctionManager, newAuctionManager } from 'src/auctionManager'; import { targeting, newTargeting } from 'src/targeting'; @@ -1628,4 +1629,29 @@ describe('Unit: Prebid Module', function () { assert.equal($$PREBID_GLOBAL$$.que.push, $$PREBID_GLOBAL$$.cmd.push); }); }); + + describe('getAllPrebidWinningBids', () => { + let auctionManagerStub; + beforeEach(() => { + auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); + }); + + afterEach(() => { + auctionManagerStub.restore(); + }); + + it('should return prebid auction winning bids', () => { + let bidsReceived = [ + createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'targetingSet'}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), + createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4'}), + ]; + auctionManagerStub.returns(bidsReceived) + let bids = $$PREBID_GLOBAL$$.getAllPrebidWinningBids(); + + expect(bids.length).to.equal(1); + expect(bids[0].adId).to.equal('adid-1'); + }); + }); }); From d8a81fc5a332f64d4da581e7ee5c02313e9d0272 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 10 Apr 2018 10:49:29 -0700 Subject: [PATCH 0243/1594] Rubicon Adapter - Multiple media types bug fix (#2347) * Removed validation for video mediaTypes; unsupported/malformed video mediaTypes fallback to banner type * Updated warning text for mediaTypes actions * Linting fixes * Added validation for mediaTypes requiring a banner property if video is malformed to fallback without invalidating * fixed typo and some spacing * Added invalidation case for invalid legacy video definition * Linting fix for space after comma in spec file --- modules/rubiconBidAdapter.js | 32 ++++++++--- test/spec/modules/rubiconBidAdapter_spec.js | 61 +++++++++++++++++++-- 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index b60755f2421..9cb4b0ab6cc 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -89,17 +89,31 @@ export const spec = { return false; } + // Log warning if context is 'outstream', is not currently supported + if (utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream') { + utils.logWarn('Warning: outstream video for Rubicon Client Adapter is not supported yet'); + } + + // Log warning if mediaTypes contains both 'banner' and 'video' + if (spec.hasVideoMediaType(bid) && typeof utils.deepAccess(bid, `mediaTypes.${BANNER}`) !== 'undefined') { + utils.logWarn('Warning: instream video and banner requested for same ad unit, continuing with video instream request'); + } + + // Bid is invalid if legacy video is set but params video is missing size_id + if (bid.mediaType === 'video' && typeof utils.deepAccess(bid, 'params.video.size_id') === 'undefined') { + return false; + } + + // Bid is invalid if mediaTypes video is invalid and a mediaTypes banner property is not defined + if (bid.mediaTypes && !spec.hasVideoMediaType(bid) && typeof bid.mediaTypes.banner === 'undefined') { + return false; + } + let parsedSizes = parseSizes(bid); if (parsedSizes.length < 1) { return false; } - if (spec.hasVideoMediaType(bid)) { - // support instream only - if ((utils.deepAccess(bid, `mediaTypes.${VIDEO}`) && utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) !== 'instream') || typeof params.video !== 'object' || !params.video.size_id) { - return false; - } - } return true; }, /** @@ -246,7 +260,8 @@ export const spec = { * @returns {boolean} */ hasVideoMediaType: function(bidRequest) { - return bidRequest.mediaType === VIDEO || typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'; + return (typeof utils.deepAccess(bidRequest, 'params.video.size_id') !== 'undefined' && + (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}.context`) === 'instream')); }, /** * @param {*} responseObj @@ -373,7 +388,7 @@ function parseSizes(bid) { let params = bid.params; if (spec.hasVideoMediaType(bid)) { let size = []; - if (typeof params.video === 'object' && params.video.playerWidth && params.video.playerHeight) { + if (params.video && params.video.playerWidth && params.video.playerHeight) { size = [ params.video.playerWidth, params.video.playerHeight @@ -384,6 +399,7 @@ function parseSizes(bid) { return size; } + // deprecated: temp legacy support let sizes = Array.isArray(params.sizes) ? params.sizes : mapSizes(bid.sizes) return masSizeOrdering(sizes); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 107f8d3ea2c..954348935df 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -712,7 +712,29 @@ describe('the rubicon adapter', () => { expect(floor).to.equal(3.25); }); - it('should not validate bid request when a invalid video object is passed in', () => { + it('should validate bid request with invalid video if a mediaTypes banner property is defined', () => { + const bidRequest = { + mediaTypes: { + video: { + context: 'instream' + }, + banner: { + sizes: [[300, 250]] + } + }, + params: { + accountId: 1001, + video: {} + }, + sizes: [[300, 250]] + } + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should not validate bid request when a invalid video object and no banner object is passed in', () => { createVideoBidderRequestNoVideo(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -730,7 +752,7 @@ describe('the rubicon adapter', () => { bidRequestCopy.params.video = 123; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - bidRequestCopy.params.video = { size_id: '' }; + bidRequestCopy.params.video = { size_id: undefined }; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); delete bidRequestCopy.params.video; @@ -798,12 +820,22 @@ describe('the rubicon adapter', () => { }); describe('hasVideoMediaType', () => { - it('should return true if mediaType is true', () => { + it('should return true if mediaType is video and size_id is set', () => { createVideoBidderRequest(); const legacyVideoTypeBidRequest = spec.hasVideoMediaType(bidderRequest.bids[0]); expect(legacyVideoTypeBidRequest).is.equal(true); }); + it('should return false if mediaType is video and size_id is not defined', () => { + expect(spec.hasVideoMediaType({ + bid: 99, + mediaType: 'video', + params: { + video: {} + } + })).is.equal(false); + }); + it('should return false if bidRequest.mediaType is not equal to video', () => { expect(spec.hasVideoMediaType({ mediaType: 'banner' @@ -814,16 +846,33 @@ describe('the rubicon adapter', () => { expect(spec.hasVideoMediaType({})).is.equal(false); }); - it('should return true if bidRequest.mediaTypes.video object exists', () => { + it('should return true if bidRequest.mediaTypes.video.context is instream and size_id is defined', () => { expect(spec.hasVideoMediaType({ mediaTypes: { video: { - context: 'outstream', - playerSize: [300, 250] + context: 'instream' + } + }, + params: { + video: { + size_id: 7 } } })).is.equal(true); }); + + it('should return false if bidRequest.mediaTypes.video.context is instream but size_id is not defined', () => { + expect(spec.hasVideoMediaType({ + mediaTypes: { + video: { + context: 'instream' + } + }, + params: { + video: {} + } + })).is.equal(false); + }); }); }); From 684ad75dfd9f31b505ccfc344a2fcbd193564adc Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 10 Apr 2018 14:37:42 -0400 Subject: [PATCH 0244/1594] uppercase all keys for AST macros (#2373) --- src/targeting.js | 4 +--- test/spec/unit/pbjs_api_spec.js | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index 2abbc955aa5..498335b598c 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -210,9 +210,7 @@ export function newTargeting(auctionManager) { // setKeywords supports string and array as value if (utils.isStr(astTargeting[targetId][key]) || utils.isArray(astTargeting[targetId][key])) { let keywordsObj = {}; - let input = 'hb_adid'; - let nKey = (key.substring(0, input.length) === input) ? key.toUpperCase() : key; - keywordsObj[nKey] = astTargeting[targetId][key]; + keywordsObj[key.toUpperCase()] = astTargeting[targetId][key]; window.apntag.setKeywords(targetId, keywordsObj); } }) diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 5b78dfe78e2..ff7b261117c 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1579,8 +1579,7 @@ describe('Unit: Prebid Module', function () { var expectedAdserverTargeting = bids[0].adserverTargeting; var newAdserverTargeting = {}; for (var key in expectedAdserverTargeting) { - var nkey = (key === 'hb_adid') ? key.toUpperCase() : key; - newAdserverTargeting[nkey] = expectedAdserverTargeting[key]; + newAdserverTargeting[key.toUpperCase()] = expectedAdserverTargeting[key]; } targeting.setTargetingForAst(); From 0bf6c7d1377adfbd0e2d5670c87a29931902ae3a Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 10 Apr 2018 15:20:23 -0600 Subject: [PATCH 0245/1594] Rubicon analytics (#2278) rubicon analytics adapter --- karma.conf.maker.js | 12 +- modules/currency.js | 32 +- modules/rubiconAnalyticsAdapter.js | 448 + package-lock.json | 12651 +++++++--------- package.json | 6 +- src/AnalyticsAdapter.js | 28 +- src/adapters/bidderFactory.js | 8 + src/ajax.js | 2 +- src/auction.js | 2 +- src/constants.json | 1 + src/prebid.js | 4 +- .../modules/adxcgAnalyticsAdapter_spec.js | 33 +- .../modules/eplanningAnalyticsAdapter_spec.js | 1 + .../modules/rubiconAnalyticsAdapter_spec.js | 635 + test/spec/modules/rubiconAnalyticsSchema.json | 357 + test/spec/video_spec.js | 10 +- 16 files changed, 6942 insertions(+), 7288 deletions(-) create mode 100644 modules/rubiconAnalyticsAdapter.js create mode 100644 test/spec/modules/rubiconAnalyticsAdapter_spec.js create mode 100644 test/spec/modules/rubiconAnalyticsSchema.json diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 30367f5fd57..2ff1d7d0880 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -32,8 +32,8 @@ function newPluginsArray(browserstack) { 'karma-chrome-launcher', 'karma-coverage-istanbul-reporter', 'karma-es5-shim', - 'karma-expect', 'karma-mocha', + 'karma-chai', 'karma-requirejs', 'karma-sinon', 'karma-sourcemap-loader', @@ -43,7 +43,6 @@ function newPluginsArray(browserstack) { ]; if (browserstack) { plugins.push('karma-browserstack-launcher'); - plugins.push('karma-sauce-launcher'); plugins.push('karma-firefox-launcher'); plugins.push('karma-opera-launcher'); plugins.push('karma-safari-launcher'); @@ -64,8 +63,6 @@ function setReporters(karmaConf, codeCoverage, browserstack) { suppressSkipped: false, suppressPassed: true }; - } else { - karmaConf.reporters = ['progress']; } if (codeCoverage) { karmaConf.reporters.push('coverage-istanbul'); @@ -120,7 +117,7 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) { }, // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['es5-shim', 'mocha', 'expect', 'sinon'], + frameworks: ['es5-shim', 'mocha', 'chai', 'sinon'], files: files, @@ -143,7 +140,10 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) { // enable / disable watching file and executing tests whenever any file changes autoWatch: true, - reporters: ['progress'], + reporters: ['mocha'], + mochaReporter: { + showDiff: true + }, // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits diff --git a/modules/currency.js b/modules/currency.js index 90941538363..25eddc5b993 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -173,17 +173,21 @@ function processBidResponseQueue() { function wrapFunction(fn, context, params) { return function() { - var bid = params[1]; + let bid = params[1]; if (bid !== undefined && 'currency' in bid && 'cpm' in bid) { - var fromCurrency = bid.currency; + let fromCurrency = bid.currency; try { - var conversion = getCurrencyConversion(fromCurrency); - bid.originalCpm = bid.cpm; + let conversion = getCurrencyConversion(fromCurrency); + let cpm = bid.originalCpm = bid.cpm; bid.originalCurrency = bid.currency; if (conversion !== 1) { bid.cpm = (parseFloat(bid.cpm) * conversion).toFixed(4); bid.currency = adServerCurrency; } + // used for analytics + bid.getCpmInNewCurrency = function(toCurrency) { + return (parseFloat(cpm) * getCurrencyConversion(fromCurrency, toCurrency)).toFixed(3); + }; } catch (e) { utils.logWarn('Returning NO_BID, getCurrencyConversion threw error: ', e); params[1] = bidfactory.createBid(STATUS.NO_BID, { @@ -196,24 +200,22 @@ function wrapFunction(fn, context, params) { }; } -function getCurrencyConversion(fromCurrency) { +function getCurrencyConversion(fromCurrency, toCurrency = adServerCurrency) { var conversionRate = null; var rates; - - if (fromCurrency in conversionCache) { - conversionRate = conversionCache[fromCurrency]; - utils.logMessage('Using conversionCache value ' + conversionRate + ' for fromCurrency ' + fromCurrency); + let cacheKey = `${fromCurrency}->${toCurrency}`; + if (cacheKey in conversionCache) { + conversionRate = conversionCache[cacheKey]; + utils.logMessage('Using conversionCache value ' + conversionRate + ' for ' + cacheKey); } else if (currencySupportEnabled === false) { if (fromCurrency === 'USD') { conversionRate = 1; } else { throw new Error('Prebid currency support has not been enabled and fromCurrency is not USD'); } - } else if (fromCurrency === adServerCurrency) { + } else if (fromCurrency === toCurrency) { conversionRate = 1; } else { - var toCurrency = adServerCurrency; - if (fromCurrency in currencyRates.conversions) { // using direct conversion rate from fromCurrency to toCurrency rates = currencyRates.conversions[fromCurrency]; @@ -252,9 +254,9 @@ function getCurrencyConversion(fromCurrency) { utils.logInfo('getCurrencyConversion using intermediate ' + fromCurrency + ' thru ' + anyBaseCurrency + ' to ' + toCurrency + ' conversionRate ' + conversionRate); } } - if (!(fromCurrency in conversionCache)) { - utils.logMessage('Adding conversionCache value ' + conversionRate + ' for fromCurrency ' + fromCurrency); - conversionCache[fromCurrency] = conversionRate; + if (!(cacheKey in conversionCache)) { + utils.logMessage('Adding conversionCache value ' + conversionRate + ' for ' + cacheKey); + conversionCache[cacheKey] = conversionRate; } return conversionRate; } diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js new file mode 100644 index 00000000000..32d1a79af5c --- /dev/null +++ b/modules/rubiconAnalyticsAdapter.js @@ -0,0 +1,448 @@ +import adapter from 'src/AnalyticsAdapter'; +import adaptermanager from 'src/adaptermanager'; +import CONSTANTS from 'src/constants.json'; +import { ajax } from 'src/ajax'; +import { config } from 'src/config'; +import * as utils from 'src/utils'; + +const { + EVENTS: { + AUCTION_INIT, + AUCTION_END, + BID_REQUESTED, + BID_RESPONSE, + BIDDER_DONE, + BID_TIMEOUT, + BID_WON, + SET_TARGETING + }, + STATUS: { + GOOD, + NO_BID + } +} = CONSTANTS; + +let serverConfig; +config.getConfig('s2sConfig', ({s2sConfig}) => { + serverConfig = s2sConfig; +}); + +export const SEND_TIMEOUT = 3000; +const INTEGRATION = 'pbjs'; + +const cache = { + auctions: {}, + targeting: {}, + timeouts: {}, +}; + +// basically lodash#pick that also allows transformation functions and property renaming +function _pick(obj, properties) { + return properties.reduce((newObj, prop, i) => { + if (typeof prop === 'function') { + return newObj; + } + + let newProp = prop; + let match = prop.match(/^(.+?)\sas\s(.+?)$/i); + + if (match) { + prop = match[1]; + newProp = match[2]; + } + + let value = obj[prop]; + if (typeof properties[i + 1] === 'function') { + value = properties[i + 1](value, newObj); + } + if (typeof value !== 'undefined') { + newObj[newProp] = value; + } + + return newObj; + }, {}); +} + +function stringProperties(obj) { + return Object.keys(obj).reduce((newObj, prop) => { + let value = obj[prop]; + if (typeof value === 'number') { + value = value.toFixed(3); + } else if (typeof value !== 'string') { + value = String(value); + } + newObj[prop] = value; + return newObj; + }, {}); +} + +function sizeToDimensions(size) { + return { + width: size.w || size[0], + height: size.h || size[1] + }; +} + +function validMediaType(type) { + return ['banner', 'native', 'video'].indexOf(type) !== -1; +} + +function formatSource(src) { + if (typeof src === 'undefined') { + src = 'client'; + } else if (src === 's2s') { + src = 'server'; + } + return src.toLowerCase(); +} + +function sendMessage(auctionId, bidWonId) { + function formatBid(bid) { + return _pick(bid, [ + 'bidder', + 'bidId', + 'status', + 'error', + 'source', (source, bid) => { + if (source) { + return source; + } + return serverConfig && Array.isArray(serverConfig.bidders) && serverConfig.bidders.indexOf(bid.bidder) !== -1 + ? 'server' : 'client' + }, + 'clientLatencyMillis', + 'params', + 'bidResponse', bidResponse => bidResponse ? _pick(bidResponse, [ + 'bidPriceUSD', + 'dealId', + 'dimensions', + 'mediaType' + ]) : undefined + ]); + } + function formatBidWon(bid) { + return Object.assign(formatBid(bid), _pick(bid.adUnit, [ + 'adUnitCode', + 'transactionId', + 'videoAdFormat', () => bid.videoAdFormat, + 'mediaTypes' + ]), { + adserverTargeting: stringProperties(cache.targeting[bid.adUnit.adUnitCode] || {}), + bidwonStatus: 'success', // hard-coded for now + accountId, + samplingFactor + }); + } + let referrer = config.getConfig('pageUrl') || utils.getTopWindowUrl(); + let message = { + eventTimeMillis: Date.now(), + integration: INTEGRATION, + version: '$prebid.version$', + referrerUri: referrer + }; + let auctionCache = cache.auctions[auctionId]; + 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, [ + 'adUnitCode', + 'transactionId', + 'mediaTypes', + 'dimensions', + 'adserverTargeting', () => stringProperties(cache.targeting[bid.adUnit.adUnitCode] || {}) + ]); + adUnit.bids = []; + } + + if (bid.videoAdFormat && !adUnit.videoAdFormat) { + adUnit.videoAdFormat = bid.videoAdFormat; + } + + // determine adUnit.status from its bid statuses. Use priority below to determine, higher index is better + let statusPriority = ['error', 'no-bid', 'success']; + if (statusPriority.indexOf(bid.status) > statusPriority.indexOf(adUnit.status)) { + adUnit.status = bid.status; + } + + adUnit.bids.push(formatBid(bid)); + + return adUnits; + }, {}); + + let auction = { + clientTimeoutMillis: auctionCache.timeout, + samplingFactor, + accountId, + adUnits: Object.keys(adUnitMap).map(i => adUnitMap[i]) + }; + + if (serverConfig) { + auction.serverTimeoutMillis = serverConfig.timeout; + } + + message.auctions = [auction]; + + let bidsWon = Object.keys(auctionCache.bidsWon).reduce((memo, adUnitCode) => { + let bidId = auctionCache.bidsWon[adUnitCode]; + if (bidId) { + memo.push(formatBidWon(auctionCache.bids[bidId])); + } + return memo; + }, []); + + if (bidsWon.length > 0) { + message.bidsWon = bidsWon; + } + + auctionCache.sent = true; + } else if (bidWonId && auctionCache && auctionCache.bids[bidWonId]) { + message.bidsWon = [ + formatBidWon(auctionCache.bids[bidWonId]) + ]; + } + + ajax( + this.getUrl(), + null, + JSON.stringify(message), + { + contentType: 'application/json' + } + ); +} + +function parseBidResponse(bid) { + return _pick(bid, [ + 'getCpmInNewCurrency as bidPriceUSD', (fn) => { + if (bid.currency === 'USD') { + return Number(bid.cpm); + } + // use currency conversion function if present + if (typeof fn === 'function') { + return Number(fn('USD')); + } + // TODO: throw error or something if not USD and currency module wasn't present? + }, + 'dealId', + 'status', + 'mediaType', + 'dimensions', () => _pick(bid, [ + 'width', + 'height' + ]) + ]); +} + +let samplingFactor = 1; +let accountId; + +let baseAdapter = adapter({analyticsType: 'endpoint'}); +let rubiconAdapter = Object.assign({}, baseAdapter, { + enableAnalytics(config = {}) { + let error = false; + samplingFactor = 1; + + if (typeof config.options === 'object') { + if (config.options.accountId) { + accountId = Number(config.options.accountId); + } + if (config.options.endpoint) { + this.getUrl = () => config.options.endpoint; + } else { + utils.logError('required endpoint missing from rubicon analytics'); + error = true; + } + if (typeof config.options.sampling !== 'undefined') { + samplingFactor = 1 / parseFloat(config.options.sampling); + } + if (typeof config.options.samplingFactor !== 'undefined') { + if (typeof config.options.sampling !== 'undefined') { + 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; + } + } + + let validSamplingFactors = [1, 10, 20, 40, 100]; + if (validSamplingFactors.indexOf(samplingFactor) === -1) { + error = true; + utils.logError('invalid samplingFactor for rubicon analytics: ' + samplingFactor + ', must be one of ' + validSamplingFactors.join(', ')); + } else if (!accountId) { + error = true; + utils.logError('required accountId missing for rubicon analytics'); + } + + if (!error) { + baseAdapter.enableAnalytics.call(this, config); + } + }, + disableAnalytics() { + this.getUrl = baseAdapter.getUrl; + accountId = null; + baseAdapter.disableAnalytics.apply(this, arguments); + }, + track({eventType, args}) { + switch (eventType) { + case AUCTION_INIT: + let cacheEntry = _pick(args, [ + 'timestamp', + 'timeout' + ]); + cacheEntry.bids = {}; + cacheEntry.bidsWon = {}; + cache.auctions[args.auctionId] = cacheEntry; + break; + case BID_REQUESTED: + 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; + + memo[bid.bidId] = _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 + 'finalSource as source', + 'params', (params, bid) => { + switch (bid.bidder) { + // specify bidder params we want here + case 'rubicon': + return _pick(params, [ + 'accountId', + 'siteId', + 'zoneId' + ]); + } + }, + 'videoAdFormat', (_, cachedBid) => { + if (cachedBid.bidder === 'rubicon') { + return ({ + 201: 'pre-roll', + 202: 'interstitial', + 203: 'outstream', + 204: 'mid-roll', + 205: 'post-roll', + 207: 'vertical' + })[utils.deepAccess(bid, 'params.video.size_id')]; + } else { + let startdelay = parseInt(utils.deepAccess(bid, 'params.video.startdelay'), 10); + if (!isNaN(startdelay)) { + if (startdelay > 0) { + return 'mid-roll'; + } + return ({ + '0': 'pre-roll', + '-1': 'mid-roll', + '-2': 'post-roll' + })[startdelay] + } + } + }, + 'adUnit', () => _pick(bid, [ + 'adUnitCode', + 'transactionId', + 'sizes as dimensions', sizes => sizes.map(sizeToDimensions), + 'mediaTypes', (types) => { + if (bid.mediaType && validMediaType(bid.mediaType)) { + return [bid.mediaType]; + } + if (Array.isArray(types)) { + return types.filter(validMediaType); + } + if (typeof types === 'object') { + if (!bid.sizes) { + bid.dimensions = []; + utils._each(types, (type) => + bid.dimensions = bid.dimensions.concat( + type.sizes.map(sizeToDimensions) + ) + ); + } + return Object.keys(types).filter(validMediaType); + } + return ['banner']; + } + ]) + ]); + return memo; + }, {})); + break; + case BID_RESPONSE: + let bid = cache.auctions[args.auctionId].bids[args.adId]; + bid.source = formatSource(bid.source || args.source); + switch (args.getStatusCode()) { + case GOOD: + bid.status = 'success'; + break; + case NO_BID: + bid.status = 'no-bid'; + break; + default: + bid.status = 'error'; + bid.error = { + code: 'request-error' + }; + } + bid.clientLatencyMillis = Date.now() - cache.auctions[args.auctionId].timestamp; + bid.bidResponse = parseBidResponse(args); + break; + case BIDDER_DONE: + args.bids.forEach(bid => { + let cachedBid = cache.auctions[bid.auctionId].bids[bid.bidId]; + if (!cachedBid.status) { + cachedBid.status = 'no-bid'; + } + if (!cachedBid.clientLatencyMillis) { + cachedBid.clientLatencyMillis = Date.now() - cache.auctions[bid.auctionId].timestamp; + } + }); + break; + case SET_TARGETING: + Object.assign(cache.targeting, args); + break; + case BID_WON: + let auctionCache = cache.auctions[args.auctionId]; + auctionCache.bidsWon[args.adUnitCode] = args.adId; + + // check if this BID_WON missed the boat, if so send by itself + if (auctionCache.sent === true) { + sendMessage.call(this, args.auctionId, args.adId); + } else if (Object.keys(auctionCache.bidsWon).reduce((memo, adUnitCode) => { + // only send if we've received bidWon events for all adUnits in auction + memo = memo && auctionCache.bidsWon[adUnitCode]; + return memo; + }, true)) { + clearTimeout(cache.timeouts[args.auctionId]); + delete cache.timeouts[args.auctionId]; + + sendMessage.call(this, args.auctionId); + } + break; + case AUCTION_END: + // start timer to send batched payload just in case we don't hear any BID_WON events + cache.timeouts[args.auctionId] = setTimeout(() => { + sendMessage.call(this, args.auctionId); + }, SEND_TIMEOUT); + break; + case BID_TIMEOUT: + args.forEach(badBid => { + let auctionCache = cache.auctions[badBid.auctionId]; + let bid = auctionCache.bids[badBid.bidId]; + bid.status = 'error'; + bid.error = { + code: 'timeout-error' + }; + }); + break; + } + } +}); + +adaptermanager.registerAnalyticsAdapter({ + adapter: rubiconAdapter, + code: 'rubicon' +}); + +export default rubiconAdapter; diff --git a/package-lock.json b/package-lock.json index 16b7eede42b..5ecab0de841 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,70 +1,63 @@ { "name": "prebid.js", - "version": "1.7.0-pre", + "version": "1.8.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { "@gulp-sourcemaps/identity-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", + "version": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", "requires": { "acorn": "5.4.1", - "css": "2.2.1", - "normalize-path": "2.1.1", - "source-map": "0.5.7", - "through2": "2.0.3" + "css": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "version": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", "requires": { - "normalize-path": "2.1.1", - "through2": "2.0.3" + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "@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==", + "version": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha1-hNt+nrVTHfGKjF4L+25EnlXmVLI=", "dev": true, "requires": { - "samsam": "1.3.0" + "samsam": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz" } }, "JSONStream": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "version": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", "dev": true, "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" + "jsonparse": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" } }, "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", "dev": true }, "accepts": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "version": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", "dev": true, "requires": { "mime-types": "2.1.17", - "negotiator": "0.5.3" + "negotiator": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz" } }, "acorn": { @@ -73,168 +66,145 @@ "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==" }, "acorn-dynamic-import": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "version": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", "dev": true, "requires": { - "acorn": "4.0.13" + "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" }, "dependencies": { "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "version": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", "dev": true } } }, "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "version": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz" }, "dependencies": { "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "version": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true } } }, "acorn-node": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.3.0.tgz", - "integrity": "sha512-efP54n3d1aLfjL2UMdaXa6DsswwzJeI5rqhbFvXMrKiJ6eJFpf+7R0zN7t8IC+XKn2YOAFAv6xbBNgHUkoHWLw==", + "version": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.3.0.tgz", + "integrity": "sha1-X4bXM0Z0OBDvEmm5AdvL3tAghhs=", "dev": true, "requires": { "acorn": "5.4.1", - "xtend": "4.0.1" + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "version": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", "dev": true, "optional": true }, - "adm-zip": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz", - "integrity": "sha1-hgbCy/HEJs6MjsABdER/1Jtur8E=", - "dev": true - }, "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "version": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", "dev": true }, "agent-base": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "version": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", "dev": true, "requires": { - "extend": "3.0.1", - "semver": "5.0.3" + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz" }, "dependencies": { "semver": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "version": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", "dev": true } } }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.1.tgz", + "integrity": "sha1-KKarxJOiq+D7TIUHrK7bQ/pVBnE=", "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.1" + "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" } }, "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", + "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", "dev": true }, "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "longest": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "amqplib": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", + "version": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", + "integrity": "sha1-0tcxPH/6pNELzx5iUt5FkbbMe2M=", "dev": true, "optional": true, "requires": { - "bitsyntax": "0.0.4", - "bluebird": "3.5.1", - "buffer-more-ints": "0.0.2", - "readable-stream": "1.1.14", - "safe-buffer": "5.1.1" + "bitsyntax": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "bluebird": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "buffer-more-ints": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true, "optional": true }, "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "optional": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true, "optional": true @@ -247,177 +217,144 @@ "integrity": "sha512-yopkAU0ZD/WQ56Tms3xLn6jRuX3SyUMAVi0FdmDIbmmnHW3jHiI1sQFdUl3gfVddjnrsP3Y6ywFKvCRopvoVIA==", "dev": true, "requires": { - "ansi-wrap": "0.1.0" + "ansi-wrap": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" } }, "ansi-escapes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "version": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha1-7D6LTp+AZPwCw6ybZfHCdb2o75I=", "dev": true }, "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "version": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", "dev": true, "requires": { - "ansi-wrap": "0.1.0" + "ansi-wrap": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" } }, "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "version": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "version": "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", + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "version": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "version": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", "dev": true, "requires": { "micromatch": "3.1.5", - "normalize-path": "2.1.1" + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" } }, "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "version": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", "dev": true, "requires": { - "buffer-equal": "1.0.0" + "buffer-equal": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz" } }, "append-transform": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "version": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", "dev": true, "requires": { - "default-require-extensions": "1.0.0" + "default-require-extensions": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz" } }, "archiver": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", + "version": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", "dev": true, "requires": { - "async": "0.9.2", - "buffer-crc32": "0.2.13", - "glob": "4.3.5", - "lazystream": "0.1.0", - "lodash": "3.2.0", - "readable-stream": "1.0.34", - "tar-stream": "1.1.5", - "zip-stream": "0.5.2" + "async": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "buffer-crc32": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "lazystream": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "tar-stream": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", + "zip-stream": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz" }, "dependencies": { "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "version": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true }, "glob": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "version": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" } }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "lazystream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "version": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", "dev": true, "requires": { - "readable-stream": "1.0.34" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" } }, "lodash": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "version": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", "dev": true }, "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" } }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, - "archiver-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", - "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", - "dev": true, - "requires": { - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "lazystream": "1.0.0", - "lodash": "4.17.5", - "normalize-path": "2.1.1", - "readable-stream": "2.3.4" - } - }, "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "version": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, @@ -427,117 +364,99 @@ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" } }, "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, "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==", + "version": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "version": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "version": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", "dev": true }, "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "version": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, "array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "version": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", "dev": true }, "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "version": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, "array-iterate": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.1.tgz", + "version": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.1.tgz", "integrity": "sha1-hlv3+K851rCYLGCQKRSsdrwBCPY=", "dev": true }, "array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "version": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", "dev": true }, "array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "version": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", "dev": true }, "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "version": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", "dev": true }, "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "version": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" } }, "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "version": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "array.from": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", + "version": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", "integrity": "sha1-LGJ7G3bf8t7yNl+gUrZcPVheX2s=", "dev": true }, "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "version": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", "dev": true }, "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "version": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", "dev": true }, @@ -547,35 +466,31 @@ "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", "dev": true, "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" + "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" } }, "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "version": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "dev": true, "requires": { - "util": "0.10.3" + "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz" } }, "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true }, "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", "dev": true }, "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "version": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, @@ -586,321 +501,290 @@ "dev": true }, "astw": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "version": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", "dev": true, "requires": { - "acorn": "4.0.13" + "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" }, "dependencies": { "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "version": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", "dev": true } } }, "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "version": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "version": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "version": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=", "dev": true }, "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, "atob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "version": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=" }, "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", "dev": true }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true }, "axios": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "version": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", "dev": true, "optional": true, "requires": { - "follow-redirects": "1.0.0" + "follow-redirects": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz" } }, "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "js-tokens": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz" } }, "babel-core": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "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.5", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" + "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "babel-helpers": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "babel-register": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "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.5", - "source-map": "0.5.7", - "trim-right": "1.0.1" + "version": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha1-GERAjTuPDTWkBOp6wYDwh6YBvZA=", + "dev": true, + "requires": { + "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "detect-indent": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "jsesc": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "trim-right": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", "dev": true, "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-explode-assignable-expression": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "esutils": "2.0.2" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" } }, "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", "dev": true, "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-hoist-variables": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" + "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", "dev": true, "requires": { - "babel-helper-bindify-decorators": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-bindify-decorators": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", "dev": true, "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-get-function-arity": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", "dev": true, "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-optimise-call-expression": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" } }, "babel-loader": { @@ -909,880 +793,796 @@ "integrity": "sha512-jRwlFbINAeyDStqK6Dd5YuY0k5YuzQUvlz2ZamuXrXmxav3pNqe9vfJ402+2G+OmlJSXxCOpB6Uz0INM7RQe2A==", "dev": true, "requires": { - "find-cache-dir": "1.0.0", - "loader-utils": "1.1.0", - "mkdirp": "0.5.1" + "find-cache-dir": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" } }, "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "version": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", "dev": true }, "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", "dev": true }, "babel-plugin-syntax-class-constructor-call": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", "dev": true }, "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", "dev": true }, "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", "dev": true }, "babel-plugin-syntax-do-expressions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", "dev": true }, "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", "dev": true }, "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", "dev": true }, "babel-plugin-syntax-export-extensions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", "dev": true }, "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", "dev": true }, "babel-plugin-syntax-function-bind": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", "dev": true }, "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", "dev": true }, "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", "dev": true }, "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", "dev": true }, "babel-plugin-system-import-transformer": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", "dev": true, "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0" + "babel-plugin-syntax-dynamic-import": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz" } }, "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-generators": "6.13.0", - "babel-runtime": "6.26.0" + "babel-helper-remap-async-to-generator": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "babel-plugin-syntax-async-generators": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.26.0" + "babel-helper-remap-async-to-generator": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "babel-plugin-syntax-async-functions": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-class-constructor-call": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", "dev": true, "requires": { - "babel-plugin-syntax-class-constructor-call": "6.18.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-plugin-syntax-class-constructor-call": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" } }, "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "babel-plugin-syntax-class-properties": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" } }, "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", "dev": true, "requires": { - "babel-helper-explode-class": "6.24.1", - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-explode-class": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "babel-plugin-syntax-decorators": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-plugin-transform-decorators-legacy": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", "integrity": "sha1-dBtY9sW86eYCfgiC2cmU8E82aSU=", "dev": true, "requires": { - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-plugin-syntax-decorators": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" } }, "babel-plugin-transform-do-expressions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", "dev": true, "requires": { - "babel-plugin-syntax-do-expressions": "6.13.0", - "babel-runtime": "6.26.0" + "babel-plugin-syntax-do-expressions": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.5" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", "dev": true, "requires": { - "babel-helper-define-map": "6.26.0", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-define-map": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "babel-helper-optimise-call-expression": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "babel-helper-replace-supers": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" } }, "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-plugin-transform-es2015-modules-commonjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" } }, "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", "dev": true, "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" + "babel-plugin-transform-strict-mode": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", "dev": true, "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-helper-hoist-variables": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" } }, "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-plugin-transform-es2015-modules-amd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" } }, "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", "dev": true, "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.26.0" + "babel-helper-replace-supers": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", "dev": true, "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-call-delegate": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "babel-helper-get-function-arity": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", "dev": true, "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-helper-regex": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "regexpu-core": "2.0.0" + "babel-helper-regex": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "regexpu-core": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz" } }, "babel-plugin-transform-es3-member-expression-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz", "integrity": "sha1-cz00RPPsxBvvjtGmpOCWV7iWnrs=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-es3-property-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz", "integrity": "sha1-sgeNWELiKr9A9z6M3pzTcRq9V1g=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", "dev": true, "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.26.0" + "babel-helper-builder-binary-assignment-operator-visitor": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "babel-plugin-syntax-exponentiation-operator": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-export-extensions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", "dev": true, "requires": { - "babel-plugin-syntax-export-extensions": "6.13.0", - "babel-runtime": "6.26.0" + "babel-plugin-syntax-export-extensions": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", "dev": true, "requires": { - "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.26.0" + "babel-plugin-syntax-flow": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-function-bind": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", "dev": true, "requires": { - "babel-plugin-syntax-function-bind": "6.13.0", - "babel-runtime": "6.26.0" + "babel-plugin-syntax-function-bind": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "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", + "version": "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.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", "dev": true, "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.26.0" + "babel-plugin-syntax-object-rest-spread": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", "dev": true, "requires": { - "babel-helper-builder-react-jsx": "6.26.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" + "babel-helper-builder-react-jsx": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "babel-plugin-syntax-jsx": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", "dev": true, "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" + "babel-plugin-syntax-jsx": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", "dev": true, "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" + "babel-plugin-syntax-jsx": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" } }, "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", "dev": true, "requires": { - "regenerator-transform": "0.10.1" + "regenerator-transform": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz" } }, "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" } }, "babel-preset-env": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", - "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0", - "browserslist": "2.11.3", + "version": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha1-oYtWTMm5r99KrleuPBsNmRiOb0g=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "babel-plugin-syntax-trailing-function-commas": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "babel-plugin-transform-async-to-generator": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "babel-plugin-transform-es2015-arrow-functions": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "babel-plugin-transform-es2015-block-scoped-functions": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "babel-plugin-transform-es2015-block-scoping": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "babel-plugin-transform-es2015-classes": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "babel-plugin-transform-es2015-computed-properties": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "babel-plugin-transform-es2015-destructuring": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "babel-plugin-transform-es2015-duplicate-keys": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "babel-plugin-transform-es2015-for-of": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "babel-plugin-transform-es2015-function-name": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "babel-plugin-transform-es2015-literals": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "babel-plugin-transform-es2015-modules-amd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "babel-plugin-transform-es2015-modules-commonjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "babel-plugin-transform-es2015-modules-systemjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "babel-plugin-transform-es2015-modules-umd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "babel-plugin-transform-es2015-object-super": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "babel-plugin-transform-es2015-parameters": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "babel-plugin-transform-es2015-shorthand-properties": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "babel-plugin-transform-es2015-spread": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "babel-plugin-transform-es2015-sticky-regex": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "babel-plugin-transform-es2015-template-literals": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "babel-plugin-transform-es2015-typeof-symbol": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "babel-plugin-transform-es2015-unicode-regex": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "babel-plugin-transform-exponentiation-operator": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "babel-plugin-transform-regenerator": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "browserslist": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", "invariant": "2.2.2", - "semver": "5.5.0" + "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz" } }, "babel-preset-es2015": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz", + "version": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz", "integrity": "sha1-r1qY7LNeuK92StiloF6zbcQ4aDU=", "dev": true, "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0" + "babel-plugin-check-es2015-constants": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "babel-plugin-transform-es2015-arrow-functions": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "babel-plugin-transform-es2015-block-scoped-functions": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "babel-plugin-transform-es2015-block-scoping": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "babel-plugin-transform-es2015-classes": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "babel-plugin-transform-es2015-computed-properties": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "babel-plugin-transform-es2015-destructuring": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "babel-plugin-transform-es2015-duplicate-keys": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "babel-plugin-transform-es2015-for-of": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "babel-plugin-transform-es2015-function-name": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "babel-plugin-transform-es2015-literals": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "babel-plugin-transform-es2015-modules-amd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "babel-plugin-transform-es2015-modules-commonjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "babel-plugin-transform-es2015-modules-systemjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "babel-plugin-transform-es2015-modules-umd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "babel-plugin-transform-es2015-object-super": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "babel-plugin-transform-es2015-parameters": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "babel-plugin-transform-es2015-shorthand-properties": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "babel-plugin-transform-es2015-spread": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "babel-plugin-transform-es2015-sticky-regex": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "babel-plugin-transform-es2015-template-literals": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "babel-plugin-transform-es2015-typeof-symbol": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "babel-plugin-transform-es2015-unicode-regex": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "babel-plugin-transform-regenerator": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz" } }, "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "version": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", "dev": true, "requires": { - "babel-plugin-transform-flow-strip-types": "6.22.0" + "babel-plugin-transform-flow-strip-types": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz" } }, "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", "dev": true, "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-react-jsx-self": "6.22.0", - "babel-plugin-transform-react-jsx-source": "6.22.0", - "babel-preset-flow": "6.23.0" + "babel-plugin-syntax-jsx": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "babel-plugin-transform-react-display-name": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "babel-plugin-transform-react-jsx": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "babel-plugin-transform-react-jsx-self": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "babel-plugin-transform-react-jsx-source": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "babel-preset-flow": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz" } }, "babel-preset-stage-0": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", "dev": true, "requires": { - "babel-plugin-transform-do-expressions": "6.22.0", - "babel-plugin-transform-function-bind": "6.22.0", - "babel-preset-stage-1": "6.24.1" + "babel-plugin-transform-do-expressions": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "babel-plugin-transform-function-bind": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "babel-preset-stage-1": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz" } }, "babel-preset-stage-1": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", "dev": true, "requires": { - "babel-plugin-transform-class-constructor-call": "6.24.1", - "babel-plugin-transform-export-extensions": "6.22.0", - "babel-preset-stage-2": "6.24.1" + "babel-plugin-transform-class-constructor-call": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "babel-plugin-transform-export-extensions": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "babel-preset-stage-2": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz" } }, "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", "dev": true, "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-decorators": "6.24.1", - "babel-preset-stage-3": "6.24.1" + "babel-plugin-syntax-dynamic-import": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "babel-plugin-transform-class-properties": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "babel-plugin-transform-decorators": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "babel-preset-stage-3": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz" } }, "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "version": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", "dev": true, "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-generator-functions": "6.24.1", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-object-rest-spread": "6.26.0" + "babel-plugin-syntax-trailing-function-commas": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "babel-plugin-transform-async-generator-functions": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "babel-plugin-transform-async-to-generator": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "babel-plugin-transform-exponentiation-operator": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "babel-plugin-transform-object-rest-spread": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz" } }, "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "version": "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.3", - "home-or-tmp": "2.0.0", - "lodash": "4.17.5", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" + "babel-core": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "core-js": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "home-or-tmp": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "source-map-support": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz" }, "dependencies": { "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "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.5", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" + "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "babel-helpers": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "babel-register": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" } }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "requires": { - "core-js": "2.5.3", - "regenerator-runtime": "0.11.1" + "core-js": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "regenerator-runtime": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz" } }, "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "version": "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.5" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "version": "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.9", - "globals": "9.18.0", + "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "globals": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", "invariant": "2.2.2", - "lodash": "4.17.5" + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } }, "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "version": "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.5", - "to-fast-properties": "1.0.3" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "to-fast-properties": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz" } }, "babelify": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", - "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw==", + "version": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", + "integrity": "sha1-b2D18GK/52lXVO8kA7hCAUpYDtM=", "dev": true }, "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "version": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", "dev": true }, "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "version": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", "dev": true }, "bail": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", + "version": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", "integrity": "sha1-99bBcxYwqfnw1NNe0fli4gdKF2Q=", "dev": true }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "version": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", + "cache-base": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "class-utils": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "mixin-deep": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "pascalcase": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" } }, "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "version": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", "dev": true }, @@ -1793,234 +1593,204 @@ "dev": true }, "base64-url": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", + "version": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", "dev": true }, "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "version": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", "dev": true }, "basic-auth": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "version": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", "dev": true }, "basic-auth-connect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "version": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", "dev": true }, "batch": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", + "version": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", "dev": true }, "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" } }, "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "version": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", "dev": true }, "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "version": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", "dev": true, "requires": { - "callsite": "1.0.0" + "callsite": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } }, "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==", + "version": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=", "dev": true }, "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "version": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", "dev": true, "requires": { - "buffers": "0.1.1", - "chainsaw": "0.1.0" + "buffers": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "chainsaw": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz" } }, "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "version": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, "binaryextensions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", + "version": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", "dev": true }, "bitsyntax": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "version": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", "dev": true, "optional": true, "requires": { - "buffer-more-ints": "0.0.2" + "buffer-more-ints": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz" } }, "bl": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "version": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", "dev": true, "requires": { - "readable-stream": "1.0.34" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "version": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", "dev": true }, "block-loader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/block-loader/-/block-loader-2.1.0.tgz", + "version": "https://registry.npmjs.org/block-loader/-/block-loader-2.1.0.tgz", "integrity": "sha1-u7OYrVqEPGxx95opb0tt9LAlcxI=", "dev": true }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "version": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=", "dev": true }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "version": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", "dev": true }, "body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "version": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", "dev": true, "requires": { - "continuable-cache": "0.3.1", - "error": "7.0.2", - "raw-body": "1.1.7", - "safe-json-parse": "1.0.1" + "continuable-cache": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "error": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "safe-json-parse": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz" } }, "body-parser": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", + "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", "dev": true, "requires": { - "bytes": "2.1.0", - "content-type": "1.0.4", - "debug": "2.2.0", - "depd": "1.0.1", - "http-errors": "1.3.1", - "iconv-lite": "0.4.11", - "on-finished": "2.3.0", - "qs": "4.0.0", - "raw-body": "2.1.7", + "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", "type-is": "1.6.15" }, "dependencies": { "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", "dev": true }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "qs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "version": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", "dev": true }, "raw-body": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", "dev": true, "requires": { - "bytes": "2.4.0", - "iconv-lite": "0.4.13", - "unpipe": "1.0.0" + "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" }, "dependencies": { "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", "dev": true }, "iconv-lite": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true } @@ -2029,22 +1799,20 @@ } }, "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" } }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "dev": true, "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" + "balanced-match": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "concat-map": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } }, "braces": { @@ -2053,192 +1821,179 @@ "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==", "dev": true, "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", + "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "define-property": "1.0.0", "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.1.1", - "split-string": "3.1.0", + "fill-range": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", + "snapdragon-node": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "split-string": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "to-regex": "3.0.1" } }, "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "version": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, "browser-pack": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.4.tgz", - "integrity": "sha512-Q4Rvn7P6ObyWfc4stqLWHtG1MJ8vVtjgT24Zbu+8UTzxYuZouqZsmNRRTFVMY/Ux0eIKv1d+JWzsInTX+fdHPQ==", + "version": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.4.tgz", + "integrity": "sha1-mnO+s7SPnjaGi+AHtkQAECwEqZ8=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "combine-source-map": "0.8.0", - "defined": "1.0.0", - "safe-buffer": "5.1.1", - "through2": "2.0.3", - "umd": "3.0.1" + "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "combine-source-map": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "umd": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz" } }, "browser-resolve": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "version": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", "dev": true, "requires": { - "resolve": "1.1.7" + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" }, "dependencies": { "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true } } }, "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "version": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", "dev": true }, "browserify": { - "version": "14.5.0", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-14.5.0.tgz", - "integrity": "sha512-gKfOsNQv/toWz+60nSPfYzuwSEdzvV2WdxrVPUbPD/qui44rAkB3t3muNtmmGYHqrG56FGwX9SUEQmzNLAeS7g==", + "version": "https://registry.npmjs.org/browserify/-/browserify-14.5.0.tgz", + "integrity": "sha1-C7vOUhrNbk0dVNjpNlAI77hanMU=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "assert": "1.4.1", - "browser-pack": "6.0.4", - "browser-resolve": "1.11.2", - "browserify-zlib": "0.2.0", + "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "assert": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "browser-pack": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.4.tgz", + "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "buffer": "5.0.8", - "cached-path-relative": "1.0.1", - "concat-stream": "1.5.2", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "defined": "1.0.0", - "deps-sort": "2.0.0", - "domain-browser": "1.1.7", - "duplexer2": "0.1.4", - "events": "1.1.1", - "glob": "7.1.2", - "has": "1.0.1", - "htmlescape": "1.1.1", - "https-browserify": "1.0.0", - "inherits": "2.0.3", + "cached-path-relative": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "deps-sort": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "has": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "htmlescape": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "insert-module-globals": "7.0.1", - "labeled-stream-splicer": "2.0.0", - "module-deps": "4.1.1", - "os-browserify": "0.3.0", - "parents": "1.0.1", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "read-only-stream": "2.0.0", - "readable-stream": "2.3.4", - "resolve": "1.5.0", - "shasum": "1.0.2", - "shell-quote": "1.6.1", - "stream-browserify": "2.0.1", - "stream-http": "2.8.0", - "string_decoder": "1.0.3", - "subarg": "1.0.0", - "syntax-error": "1.4.0", - "through2": "2.0.3", - "timers-browserify": "1.4.2", - "tty-browserify": "0.0.1", - "url": "0.11.0", - "util": "0.10.3", - "vm-browserify": "0.0.4", - "xtend": "4.0.1" + "labeled-stream-splicer": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", + "module-deps": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "read-only-stream": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "shasum": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "shell-quote": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "syntax-error": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" }, "dependencies": { "concat-stream": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.0.6", - "typedarray": "0.0.6" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" }, "dependencies": { "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "module-deps": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "version": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "browser-resolve": "1.11.2", - "cached-path-relative": "1.0.1", - "concat-stream": "1.5.2", - "defined": "1.0.0", - "detective": "4.7.1", - "duplexer2": "0.1.4", - "inherits": "2.0.3", - "parents": "1.0.1", - "readable-stream": "2.3.4", - "resolve": "1.5.0", - "stream-combiner2": "1.1.1", - "subarg": "1.0.0", - "through2": "2.0.3", - "xtend": "4.0.1" + "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "cached-path-relative": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "detective": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "stream-combiner2": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "version": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" }, "dependencies": { "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } @@ -2247,79 +2002,72 @@ } }, "browserify-aes": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "version": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha1-OLerVe24Bv8tzaGn8WIHc6R3xJ8=", "dev": true, "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "buffer-xor": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, "browserify-cipher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "version": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", "dev": true, "requires": { - "browserify-aes": "1.1.1", - "browserify-des": "1.0.0", - "evp_bytestokey": "1.0.3" + "browserify-aes": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "browserify-des": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" } }, "browserify-des": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "version": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3" + "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "des.js": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" } }, "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "version": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { - "bn.js": "4.11.8", - "randombytes": "2.0.6" + "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz" } }, "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "version": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.0" + "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "browserify-rsa": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "elliptic": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "parse-asn1": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz" } }, "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==", + "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", "dev": true, "requires": { - "pako": "1.0.6" + "pako": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz" } }, "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "version": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha1-/jYWeu0bvN5IJ+v+cTR6LMcLmbI=", "dev": true, "requires": { "caniuse-lite": "1.0.30000808", @@ -2327,22 +2075,20 @@ } }, "browserstack": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", + "version": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", "dev": true, "requires": { - "https-proxy-agent": "1.0.0" + "https-proxy-agent": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz" } }, "browserstacktunnel-wrapper": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.1.tgz", + "version": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.1.tgz", "integrity": "sha1-/+GRDW45/oZhgYPoJmkAQa9T7a4=", "dev": true, "requires": { - "https-proxy-agent": "1.0.0", - "unzip": "0.1.11" + "https-proxy-agent": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "unzip": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz" } }, "buffer": { @@ -2352,142 +2098,124 @@ "dev": true, "requires": { "base64-js": "1.2.1", - "ieee754": "1.1.8" + "ieee754": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz" } }, "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "version": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "version": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", "dev": true }, "buffer-more-ints": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "version": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", "dev": true }, "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "version": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "version": "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", + "version": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", "dev": true }, "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", + "version": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", "dev": true, "optional": true, "requires": { - "addressparser": "1.0.1", - "libbase64": "0.1.0", - "libmime": "3.0.0", - "libqp": "1.1.0", - "nodemailer-fetch": "1.6.0", - "nodemailer-shared": "1.1.0", - "punycode": "1.4.1" + "addressparser": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "libbase64": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "libmime": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "libqp": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "nodemailer-fetch": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" } }, "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "version": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, "bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "version": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "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": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "has-value": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "set-value": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "union-value": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "unset-value": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" } }, "cached-path-relative": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "version": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", "dev": true }, "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "version": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz" } }, "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "version": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", "dev": true }, "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "version": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "version": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "version": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "map-obj": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" }, "dependencies": { "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "version": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true } @@ -2500,113 +2228,99 @@ "dev": true }, "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "version": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true }, "ccount": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", + "version": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", "integrity": "sha1-U7ai+BW7d7nChx97mnLDol8djok=", "dev": true }, "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "version": "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" + "align-text": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "lazy-cache": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz" }, "dependencies": { "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true } } }, "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "version": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", "dev": true, "requires": { - "assertion-error": "1.1.0", - "deep-eql": "0.1.3", - "type-detect": "1.0.0" + "assertion-error": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "deep-eql": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz" } }, "chai-nightwatch": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", + "version": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", "dev": true, "requires": { - "assertion-error": "1.0.0", - "deep-eql": "0.1.3" + "assertion-error": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "deep-eql": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz" }, "dependencies": { "assertion-error": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", "dev": true } } }, "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "version": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", "dev": true, "requires": { - "traverse": "0.3.9" + "traverse": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" } }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "version": "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.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "has-ansi": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" } }, "character-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", + "version": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", "integrity": "sha1-92hxvl72bdt/j440eOzDdMJ9bco=", "dev": true }, "character-entities-html4": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.1.tgz", + "version": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.1.tgz", "integrity": "sha1-NZoqSg9+KdPcKsmb2+Ie45Q46lA=", "dev": true }, "character-entities-legacy": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", + "version": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", "integrity": "sha1-9Ad53xoQGHK7UQo9KV4fzPFHIC8=", "dev": true }, "character-reference-invalid": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", + "version": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", "integrity": "sha1-lCg191Dk7GGjCOYMLvjMEBEgLvw=", "dev": true }, "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "version": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, @@ -2616,350 +2330,309 @@ "integrity": "sha512-rv5iP8ENhpqvDWr677rAXcB+SMoPQ1urd4ch79+PhM4lQwbATdJUQK69t0lJIKNB+VXpqxt5V1gvqs59XEPKnw==", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", + "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", "braces": "2.3.0", - "fsevents": "1.1.3", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", + "fsevents": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "upath": "1.0.0" } }, "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==", + "version": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "version": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", "dev": true }, "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==", + "version": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" + "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "static-extend": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" }, "dependencies": { "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "version": "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" + "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" } }, "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" } }, "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": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } }, "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "version": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "2.0.0" + "restore-cursor": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz" } }, "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "version": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "version": "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" + "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "wrap-ansi": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz" } }, "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "version": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", "dev": true }, "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "version": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", "dev": true }, "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", "dev": true }, "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "version": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", "dev": true, "requires": { - "inherits": "2.0.3", - "process-nextick-args": "1.0.7", - "through2": "2.0.3" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" }, "dependencies": { "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true } } }, "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "collapse-white-space": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", + "version": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", "integrity": "sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw=", "dev": true }, "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "version": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" + "map-visit": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "object-visit": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" } }, "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "version": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "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==", + "version": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", "dev": true }, "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "version": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true }, "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "version": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "combine-source-map": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "version": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", "dev": true, "requires": { - "convert-source-map": "1.1.3", - "inline-source-map": "0.6.2", - "lodash.memoize": "3.0.4", - "source-map": "0.5.7" + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "inline-source-map": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "lodash.memoize": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" }, "dependencies": { "convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", "dev": true }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" } }, "comma-separated-tokens": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.4.tgz", + "version": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.4.tgz", "integrity": "sha1-cgg+WNSkYvAYZvZhf02Yo807ikY=", "dev": true, "requires": { - "trim": "0.0.1" + "trim": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" } }, "commander": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", - "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "version": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha1-IjUSPjevjKPGXfRbAm29NXsBuao=", "dev": true }, "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "version": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "version": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", "dev": true }, "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "version": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "version": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", "dev": true }, "compress-commons": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", + "version": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", "dev": true, "requires": { - "buffer-crc32": "0.2.13", - "crc32-stream": "0.3.4", - "node-int64": "0.3.3", - "readable-stream": "1.0.34" + "buffer-crc32": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "crc32-stream": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", + "node-int64": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -2975,669 +2648,588 @@ } }, "compression": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", + "version": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", "dev": true, "requires": { - "accepts": "1.2.13", - "bytes": "2.1.0", + "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", "compressible": "2.0.12", - "debug": "2.2.0", - "on-headers": "1.0.1", - "vary": "1.0.1" + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "vary": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz" }, "dependencies": { "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", "dev": true }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.4", - "typedarray": "0.0.6" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" } }, "concat-with-sourcemaps": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", - "integrity": "sha512-YtnS0VEY+e2Khzsey/6mra9EoM6h/5gxaC0e3mcHpA5yfDxafhygytNmcJWodvUgyXzSiL5MSkPO6bQGgfliHw==", + "version": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", + "integrity": "sha1-iWS8I0fQWBm2N5gQTYfW4AG+2NA=", "dev": true, "requires": { - "source-map": "0.6.1" + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" } }, "connect": { - "version": "2.30.2", - "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", + "version": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", "dev": true, "requires": { - "basic-auth-connect": "1.0.0", - "body-parser": "1.13.3", - "bytes": "2.1.0", - "compression": "1.5.2", - "connect-timeout": "1.6.2", - "content-type": "1.0.4", - "cookie": "0.1.3", - "cookie-parser": "1.3.5", - "cookie-signature": "1.0.6", - "csurf": "1.8.3", - "debug": "2.2.0", - "depd": "1.0.1", - "errorhandler": "1.4.3", - "express-session": "1.11.3", - "finalhandler": "0.4.0", - "fresh": "0.3.0", - "http-errors": "1.3.1", - "method-override": "2.3.10", - "morgan": "1.6.1", - "multiparty": "3.3.2", - "on-headers": "1.0.1", - "parseurl": "1.3.2", - "pause": "0.1.0", - "qs": "4.0.0", - "response-time": "2.3.2", - "serve-favicon": "2.3.2", - "serve-index": "1.7.3", - "serve-static": "1.10.3", + "basic-auth-connect": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "body-parser": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", + "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "compression": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", + "connect-timeout": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", + "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "cookie-parser": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "csurf": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "errorhandler": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", + "express-session": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", + "finalhandler": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", + "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "method-override": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", + "morgan": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", + "multiparty": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", + "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "pause": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "response-time": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", + "serve-favicon": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "serve-index": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", + "serve-static": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", "type-is": "1.6.15", - "utils-merge": "1.0.0", - "vhost": "3.0.2" + "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "vhost": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz" }, "dependencies": { "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", "dev": true }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "qs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "version": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", "dev": true } } }, "connect-livereload": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", + "version": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", "dev": true }, "connect-timeout": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", + "version": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", "dev": true, "requires": { - "debug": "2.2.0", - "http-errors": "1.3.1", - "ms": "0.7.1", - "on-headers": "1.0.1" + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "version": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "requires": { - "date-now": "0.1.4" + "date-now": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz" } }, "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "version": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "version": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, "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==", + "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", "dev": true }, "continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "version": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", "dev": true }, "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" }, "cookie": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "version": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", "dev": true }, "cookie-parser": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "version": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", "dev": true, "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6" + "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" } }, "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "version": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "version": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, "core-js": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "version": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "coveralls": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "version": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", + "integrity": "sha1-mtfCrlJ0F/Nh6LYmSD9I7pLdK8c=", "dev": true, "requires": { - "js-yaml": "3.6.1", - "lcov-parse": "0.0.10", - "log-driver": "1.2.5", - "minimist": "1.2.0", - "request": "2.79.0" + "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "lcov-parse": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "log-driver": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "request": "https://registry.npmjs.org/request/-/request-2.79.0.tgz" }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "crc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", + "version": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", "dev": true }, "crc32-stream": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", + "version": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", "dev": true, "requires": { - "buffer-crc32": "0.2.13", - "readable-stream": "1.0.34" + "buffer-crc32": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "create-ecdh": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "version": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", "dev": true, "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0" + "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "elliptic": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz" } }, "create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "version": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "sha.js": "2.4.10" + "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz" } }, "create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "version": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.10" + "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz" } }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "version": "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.1", - "shebang-command": "1.2.0", - "which": "1.3.0" + "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "shebang-command": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" } }, "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, "requires": { - "boom": "2.10.1" + "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" } }, "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": { - "browserify-cipher": "1.0.0", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.0", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "diffie-hellman": "5.0.2", - "inherits": "2.0.3", - "pbkdf2": "3.0.14", - "public-encrypt": "4.0.0", - "randombytes": "2.0.6", + "version": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", + "dev": true, + "requires": { + "browserify-cipher": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "browserify-sign": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "create-ecdh": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "diffie-hellman": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "pbkdf2": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "public-encrypt": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "randomfill": "1.0.3" } }, "csrf": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "version": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", "dev": true, "requires": { - "rndm": "1.2.0", - "tsscmp": "1.0.5", - "uid-safe": "2.1.4" + "rndm": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "tsscmp": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "uid-safe": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz" } }, "css": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "version": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", "requires": { - "inherits": "2.0.3", - "source-map": "0.1.43", - "source-map-resolve": "0.3.1", - "urix": "0.1.0" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "source-map-resolve": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "urix": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" }, "dependencies": { "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "requires": { - "amdefine": "1.0.1" + "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" } } } }, "css-loader": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", + "version": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", "dev": true, "optional": true, "requires": { - "csso": "1.3.12", - "loader-utils": "0.2.17", - "source-map": "0.1.43" + "csso": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", + "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz" }, "dependencies": { "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, "optional": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" + "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } }, "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" } } } }, "css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "version": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", "dev": true, "requires": { - "css": "2.2.1" + "css": "https://registry.npmjs.org/css/-/css-2.2.1.tgz" } }, "css-value": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "version": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", "dev": true }, "csso": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", + "version": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", "integrity": "sha1-/GKGlKLTiTiqrEmWdTIY/TEc254=", "dev": true, "optional": true }, "csurf": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", + "version": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", "dev": true, "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6", - "csrf": "3.0.6", - "http-errors": "1.3.1" + "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "csrf": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz" } }, "ctype": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "version": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", "dev": true }, "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "version": "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.2" + "array-find-index": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz" } }, "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "version": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "version": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "requires": { "es5-ext": "0.10.38" } }, - "dargs": { - "version": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" }, "dependencies": { "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", + "version": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha1-dxY+qcINhkG0cH6PGKvfmnjzSDU=", "dev": true }, "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "version": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "version": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "version": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "debug-fabulous": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", - "integrity": "sha512-dsd50qQ1atDeurcxL7XOjPp4nZCGZzWIONDujDXzl1atSyC3hMbZD+v6440etw+Vt0Pr8ce4TQzHfX3KZM05Mw==", + "version": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", + "integrity": "sha1-V/ZkhkYJexsISdzaABc2LB7AD4s=", "requires": { - "debug": "3.1.0", + "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "memoizee": "0.4.11", - "object-assign": "4.1.1" + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } }, "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "version": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "version": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", "dev": true, "requires": { - "type-detect": "0.1.1" + "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz" }, "dependencies": { "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "version": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", "dev": true } } }, "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "version": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, "deepmerge": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", + "version": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", "dev": true }, "default-require-extensions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "version": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, "requires": { - "strip-bom": "2.0.0" + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" }, "dependencies": { "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" } } } }, "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "version": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "1.0.3" + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz" }, "dependencies": { "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "version": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", "dev": true } } }, "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "version": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", "dev": true, "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" + "foreach": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "object-keys": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz" } }, "define-property": { @@ -3646,455 +3238,412 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" } }, "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "version": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "version": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", "dev": true, "requires": { "ast-types": "0.10.2", - "escodegen": "1.8.1", - "esprima": "3.1.3" + "escodegen": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "esprima": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz" }, "dependencies": { "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "version": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true } } }, "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "version": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "globby": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "is-path-cwd": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "is-path-in-cwd": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" }, "dependencies": { "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "depd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "version": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", "dev": true }, "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "version": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", "dev": true }, "deps-sort": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "version": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "shasum": "1.0.2", - "subarg": "1.0.0", - "through2": "2.0.3" + "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "shasum": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "version": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" } }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "version": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, "detab": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", - "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", + "version": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", + "integrity": "sha1-Ux9eMmYg4v1PAyZKkF+zvMivTfQ=", "dev": true, "requires": { - "repeat-string": "1.6.1" + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" } }, "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "version": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "version": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" } }, "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "version": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" }, "detective": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "version": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha1-DspzFDOEQv67bWXaVMELscgrJG4=", "dev": true, "requires": { "acorn": "5.4.1", - "defined": "1.0.0" + "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz" } }, "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "version": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", "dev": true }, "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "version": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", "dev": true }, "diffie-hellman": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "version": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", "dev": true, "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" + "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "miller-rabin": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz" } }, "disparity": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", + "version": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "diff": "1.4.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "diff": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz" } }, "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "version": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" } }, "doctrine-temporary-fork": { - "version": "2.0.0-alpha-allowarrayindex", - "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", + "version": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" } }, "documentation": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.4.0.tgz", - "integrity": "sha512-4i7nsVLUTIaKRU05op+6LCXosakbmvHdQWTeoj8UM9THbvwaO7Ok2ePgMl+s1Aw+31qeQTZqG5Z5JVgwspJocQ==", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "babel-core": "6.26.0", - "babel-generator": "6.26.1", - "babel-plugin-system-import-transformer": "3.1.0", - "babel-plugin-transform-decorators-legacy": "1.3.4", - "babel-preset-env": "1.6.1", - "babel-preset-react": "6.24.1", - "babel-preset-stage-0": "6.24.1", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babelify": "8.0.0", - "babylon": "6.18.0", - "chalk": "2.3.1", + "version": "https://registry.npmjs.org/documentation/-/documentation-5.4.0.tgz", + "integrity": "sha1-SQBqjKRE6DXwOpkP6MOT4Vy0+FM=", + "dev": true, + "requires": { + "ansi-html": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "babel-core": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "babel-plugin-system-import-transformer": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", + "babel-plugin-transform-decorators-legacy": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", + "babel-preset-env": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "babel-preset-react": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "babel-preset-stage-0": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "babelify": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", + "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", "chokidar": "2.0.1", - "concat-stream": "1.6.0", - "disparity": "2.0.0", - "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", - "get-port": "3.2.0", - "git-url-parse": "8.1.0", - "github-slugger": "1.2.0", - "glob": "7.1.2", - "globals-docs": "2.4.0", - "highlight.js": "9.12.0", - "js-yaml": "3.10.0", - "lodash": "4.17.5", - "mdast-util-inject": "1.1.0", + "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "disparity": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", + "doctrine-temporary-fork": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", + "get-port": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "git-url-parse": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.1.0.tgz", + "github-slugger": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "globals-docs": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", + "highlight.js": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "mdast-util-inject": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", "micromatch": "3.1.5", - "mime": "2.2.0", - "module-deps-sortable": "4.0.6", - "parse-filepath": "1.0.2", - "pify": "3.0.0", - "read-pkg-up": "3.0.0", - "remark": "9.0.0", - "remark-html": "7.0.0", - "remark-toc": "5.0.0", - "remote-origin-url": "0.4.0", - "shelljs": "0.8.1", - "stream-array": "1.1.2", - "strip-json-comments": "2.0.1", + "mime": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", + "module-deps-sortable": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", + "parse-filepath": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "remark": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", + "remark-html": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", + "remark-toc": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", + "remote-origin-url": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", + "shelljs": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", + "stream-array": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", + "strip-json-comments": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "tiny-lr": "1.1.0", - "unist-builder": "1.0.2", - "unist-util-visit": "1.3.0", - "vfile": "2.3.0", - "vfile-reporter": "4.0.0", - "vfile-sort": "2.1.0", - "vinyl": "2.1.0", - "vinyl-fs": "3.0.2", - "yargs": "9.0.1" + "unist-builder": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", + "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", + "vfile": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "vfile-reporter": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", + "vfile-sort": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.0.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", + "yargs": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" } }, "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "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.5", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" + "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "babel-helpers": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "babel-register": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" } }, "chalk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "5.2.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" } }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "version": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", "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", + "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", "dev": true, "requires": { "argparse": "1.0.9", - "esprima": "4.0.0" + "esprima": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz" } }, "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "version": "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.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" }, "dependencies": { "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" } }, "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "version": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "pify": "2.3.0" + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" }, "dependencies": { "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "version": "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.4.0", - "path-type": "2.0.0" + "load-json-file": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "path-type": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz" } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "version": "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" } }, "supports-color": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" } }, "yargs": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "version": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "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.1", - "yargs-parser": "7.0.0" + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "get-caller-file": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "require-directory": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "require-main-filename": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "which-module": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "yargs-parser": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz" }, "dependencies": { "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "version": "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" + "find-up": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz" } } } @@ -4102,76 +3651,67 @@ } }, "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "version": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { - "custom-event": "1.0.1", - "ent": "2.2.0", - "extend": "3.0.1", - "void-elements": "2.0.1" + "custom-event": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "ent": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "void-elements": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz" } }, "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "version": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", "dev": true }, "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "version": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", "dev": true, "optional": true }, "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "version": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { - "readable-stream": "2.3.4" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "duplexify": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", - "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", + "version": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "integrity": "sha1-i1gYgA35L9ASWyeriWSRkShYJD4=", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.4", - "stream-shift": "1.0.0" + "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "stream-shift": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz" } }, "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" } }, "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, "ejs": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "version": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", "dev": true }, @@ -4182,45 +3722,40 @@ "dev": true }, "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "version": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "brorand": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "hash.js": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "hmac-drbg": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "minimalistic-crypto-utils": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" } }, "emoji-regex": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", + "version": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", "dev": true }, "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "version": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "version": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", "dev": true, "requires": { - "once": "1.4.0" + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" } }, "engine.io": { @@ -4230,12 +3765,12 @@ "dev": true, "requires": { "accepts": "1.3.3", - "base64id": "1.0.0", + "base64id": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", "cookie": "0.3.1", "debug": "2.6.9", - "engine.io-parser": "2.1.2", + "engine.io-parser": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", "uws": "0.14.5", - "ws": "3.3.3" + "ws": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz" }, "dependencies": { "accepts": { @@ -4260,7 +3795,7 @@ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "negotiator": { @@ -4277,17 +3812,17 @@ "integrity": "sha1-T88TcLRxY70s6b4nM5ckMDUNTqE=", "dev": true, "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", + "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "component-inherit": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", "debug": "2.6.9", - "engine.io-parser": "2.1.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "3.3.3", - "xmlhttprequest-ssl": "1.5.5", - "yeast": "0.1.2" + "engine.io-parser": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "has-cors": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "indexof": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "parseqs": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "parseuri": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "ws": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "xmlhttprequest-ssl": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "yeast": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz" }, "dependencies": { "debug": { @@ -4296,39 +3831,36 @@ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } }, "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "version": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha1-TA9M/3mq7su9z96maoI8YIVAkZY=", "dev": true, "requires": { - "after": "0.8.2", - "arraybuffer.slice": "0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary2": "1.0.2" + "after": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "arraybuffer.slice": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "base64-arraybuffer": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "blob": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "has-binary2": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz" } }, "enhanced-resolve": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "version": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "object-assign": "4.1.1", - "tapable": "0.2.8" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz" } }, "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "version": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", "dev": true }, @@ -4338,51 +3870,46 @@ "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", "dev": true, "requires": { - "prr": "1.0.1" + "prr": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" } }, "error": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "version": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", "dev": true, "requires": { - "string-template": "0.2.1", - "xtend": "4.0.1" + "string-template": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" } }, "errorhandler": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", + "version": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", "dev": true, "requires": { - "accepts": "1.3.4", - "escape-html": "1.0.3" + "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" }, "dependencies": { "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "version": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", "dev": true, "requires": { "mime-types": "2.1.17", - "negotiator": "0.6.1" + "negotiator": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" } }, "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true } @@ -4393,126 +3920,114 @@ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" } }, "es5-shim": { - "version": "4.5.10", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", - "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==", + "version": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", + "integrity": "sha1-t+F+9N8qFFuCHxSXtQwlz5QCYgU=", "dev": true }, "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "version": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "requires": { - "d": "1.0.0", + "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "es5-ext": "0.10.38", - "es6-symbol": "3.1.1" + "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" } }, "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "version": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "dev": true, "requires": { - "d": "1.0.0", + "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "es5-ext": "0.10.38", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "es6-set": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "event-emitter": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" } }, "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "version": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "dev": true, "requires": { - "d": "1.0.0", + "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "es5-ext": "0.10.38", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "event-emitter": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" } }, "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "version": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "requires": { - "d": "1.0.0", + "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "es5-ext": "0.10.38" } }, "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "version": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "requires": { - "d": "1.0.0", + "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "es5-ext": "0.10.38", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" } }, "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", "dev": true }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "version": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" + "esprima": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "optionator": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz" }, "dependencies": { "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "version": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", "dev": true }, "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" } } } }, "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "version": "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.2", + "es6-map": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "es6-weak-map": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", "esrecurse": "4.2.0", - "estraverse": "4.2.0" + "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz" } }, "eslint": { @@ -4521,100 +4036,105 @@ "integrity": "sha512-AyxBUCANU/o/xC0ijGMKavo5Ls3oK6xykiOITlMdjFjrKOsqLrA7Nf5cnrDgcKrHzBirclAZt63XO7YZlVUPwA==", "dev": true, "requires": { - "ajv": "5.5.2", - "babel-code-frame": "6.26.0", - "chalk": "2.3.1", - "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.3", - "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.3.0", - "ignore": "3.3.7", - "imurmurhash": "0.1.4", - "inquirer": "3.3.0", - "is-resolvable": "1.1.0", - "js-yaml": "3.10.0", - "json-stable-stringify-without-jsonify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.5", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "7.0.0", - "progress": "2.0.0", - "require-uncached": "1.0.3", - "semver": "5.5.0", + "ajv": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "cross-spawn": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "doctrine": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "eslint-scope": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "eslint-visitor-keys": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "espree": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", + "esquery": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "file-entry-cache": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "functional-red-black-tree": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "globals": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "ignore": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "imurmurhash": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "inquirer": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "is-resolvable": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "json-stable-stringify-without-jsonify": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "levn": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "natural-compare": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "optionator": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "path-is-inside": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "pluralize": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "progress": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "require-uncached": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", + "strip-json-comments": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "table": "4.0.2", - "text-table": "0.2.0" + "text-table": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "ajv": { + "version": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" } }, "chalk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "5.2.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" } }, "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "version": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", "dev": true, "requires": { - "esutils": "2.0.2" + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" } }, "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "version": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", "dev": true }, "globals": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", - "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==", + "version": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "integrity": "sha1-4E/be5eW2K2snI9kwUg3sjEzeLA=", "dev": true }, "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", "dev": true, "requires": { "argparse": "1.0.9", - "esprima": "4.0.0" + "esprima": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz" } }, "strip-ansi": { @@ -4627,88 +4147,79 @@ } }, "supports-color": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" } } } }, "eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "version": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "version": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha1-WPFfuDm40FdsqYBBNHaqskcttmo=", "dev": true, "requires": { - "debug": "2.6.9", - "resolve": "1.5.0" + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } }, "eslint-module-utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", - "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "version": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "integrity": "sha1-q67IJBd2E7ipWymWOeG2+s9HNEk=", "dev": true, "requires": { - "debug": "2.6.9", - "pkg-dir": "1.0.0" + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "pkg-dir": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "version": "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": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "version": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { - "find-up": "1.1.2" + "find-up": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz" } } } @@ -4719,25 +4230,24 @@ "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", "dev": true, "requires": { - "builtin-modules": "1.1.1", - "contains-path": "0.1.0", - "debug": "2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "0.3.2", - "eslint-module-utils": "2.1.1", - "has": "1.0.1", + "builtin-modules": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "contains-path": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "doctrine": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "eslint-import-resolver-node": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "eslint-module-utils": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "has": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", "lodash.cond": "4.5.2", - "minimatch": "3.0.4", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "read-pkg-up": "2.0.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "load-json-file": { @@ -4746,10 +4256,10 @@ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "parse-json": "2.2.0", "pify": "2.3.0", - "strip-bom": "3.0.0" + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" } }, "parse-json": { @@ -4758,7 +4268,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" } }, "path-type": { @@ -4783,7 +4293,7 @@ "dev": true, "requires": { "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", + "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "path-type": "2.0.0" } }, @@ -4793,83 +4303,74 @@ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "find-up": "2.1.0", + "find-up": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "read-pkg": "2.0.0" } } } }, "eslint-plugin-node": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", - "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "version": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha1-gN8yU8TXkBBF7If6ZgooTjK9yik=", "dev": true, "requires": { - "ignore": "3.3.7", - "minimatch": "3.0.4", - "resolve": "1.5.0", - "semver": "5.3.0" + "ignore": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" }, "dependencies": { "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } } }, "eslint-plugin-promise": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", - "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", + "version": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", + "integrity": "sha1-VLdljI9FSBPcKocK/4FS7ElpunU=", "dev": true }, "eslint-plugin-standard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "version": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", "dev": true }, "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "version": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { "esrecurse": "4.2.0", - "estraverse": "4.2.0" + "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz" } }, "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "version": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", "dev": true }, "espree": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", - "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==", + "version": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", + "integrity": "sha1-kx4K9k5/u+0msFCinarR/GR5n6Y=", "dev": true, "requires": { "acorn": "5.4.1", - "acorn-jsx": "3.0.1" + "acorn-jsx": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz" } }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true }, "esquery": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "version": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz" } }, "esrecurse": { @@ -4878,355 +4379,312 @@ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } }, "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, "estree-walker": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", + "version": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", "dev": true }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "version": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, "etag": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "version": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", "dev": true }, "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "version": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "requires": { - "d": "1.0.0", + "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "es5-ext": "0.10.38" } }, "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "version": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", - "pause-stream": "0.0.11", - "split": "0.3.3", - "stream-combiner": "0.0.4", - "through": "2.3.8" + "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "from": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "pause-stream": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "split": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "stream-combiner": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" } }, "eventemitter3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "version": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", "dev": true }, "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "version": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", "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==", + "version": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", "dev": true, "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.1" + "md5.js": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "version": "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.2", - "strip-eof": "1.0.0" + "cross-spawn": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "get-stream": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "npm-run-path": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "p-finally": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "strip-eof": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" } }, "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "version": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, "requires": { - "array-slice": "0.2.3", - "array-unique": "0.2.1", - "braces": "0.1.5" + "array-slice": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "braces": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz" }, "dependencies": { "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "version": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", "dev": true }, "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "version": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", "dev": true, "requires": { - "expand-range": "0.1.1" + "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz" } }, "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "version": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { - "is-number": "0.1.1", - "repeat-string": "0.2.2" + "is-number": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz" } }, "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "version": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", "dev": true }, "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", "dev": true } } }, "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "version": "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", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", + "posix-character-classes": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "regex-not": "1.0.0", - "snapdragon": "0.8.1", + "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", "to-regex": "3.0.1" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "version": "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" + "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" } }, "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" } }, "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": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } }, "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "version": "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.3" + "fill-range": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz" }, "dependencies": { "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "version": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "is-number": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "randomatic": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" } }, "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "version": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" } }, "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "version": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { - "isarray": "1.0.0" + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" } }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "version": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1" + "homedir-polyfill": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz" } }, - "expect.js": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", - "integrity": "sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s=", - "dev": true - }, "express-session": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", + "version": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", "dev": true, "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6", - "crc": "3.3.0", - "debug": "2.2.0", - "depd": "1.0.1", - "on-headers": "1.0.1", - "parseurl": "1.3.2", - "uid-safe": "2.0.0", - "utils-merge": "1.0.0" + "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "crc": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "uid-safe": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", + "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "uid-safe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", + "version": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", "dev": true, "requires": { - "base64-url": "1.2.1" + "base64-url": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz" } } } }, "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "version": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, @@ -5236,65 +4694,59 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" } }, "external-editor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "version": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha1-PQJqIbf5W1cmOH1CAKwWDTcsO0g=", "dev": true, "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.19", - "tmp": "0.0.33" + "chardet": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "tmp": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" }, "dependencies": { "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", "dev": true } } }, "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "version": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { - "array-unique": "0.3.2", + "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "define-property": "1.0.0", - "expand-brackets": "2.1.4", + "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", + "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "regex-not": "1.0.0", - "snapdragon": "0.8.1", + "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", "to-regex": "3.0.1" } }, "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, "faker": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-3.1.0.tgz", + "version": "https://registry.npmjs.org/faker/-/faker-3.1.0.tgz", "integrity": "sha1-D5CPr05uwCUk5UpX5DLFwBPgjJ8=", "dev": true }, "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "version": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" + "ansi-gray": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "color-support": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "time-stamp": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz" } }, "fast-deep-equal": { @@ -5304,412 +4756,365 @@ "dev": true }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "version": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "version": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": "0.7.0" + "websocket-driver": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz" } }, "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "version": "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": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" } }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "version": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } }, "file-loader": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", + "version": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", "dev": true, "optional": true, "requires": { - "loader-utils": "0.2.17" + "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz" }, "dependencies": { "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, "optional": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" + "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } } } }, "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==", + "version": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", "dev": true }, "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "version": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, "fileset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "version": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", "dev": true, "requires": { - "glob": "7.1.2", - "minimatch": "3.0.4" + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" } }, "fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "version": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", "dev": true, "requires": { - "is-object": "1.0.1", - "merge-descriptors": "1.0.1" + "is-object": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "merge-descriptors": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" } }, "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "version": "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" + "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "to-regex-range": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" } }, "finalhandler": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", + "version": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", "dev": true, "requires": { - "debug": "2.2.0", - "escape-html": "1.0.2", - "on-finished": "2.3.0", - "unpipe": "1.0.0" + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "escape-html": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", + "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", "dev": true }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "version": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", "dev": true, "requires": { - "commondir": "1.0.1", + "commondir": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "make-dir": "1.1.0", - "pkg-dir": "2.0.0" + "pkg-dir": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz" } }, "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "version": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", "dev": true }, "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "version": "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": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" } }, "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "version": "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", + "detect-file": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "micromatch": "3.1.5", - "resolve-dir": "1.0.1" + "resolve-dir": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" }, "dependencies": { "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" } } } }, "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "version": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, "requires": { - "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" + "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "object.defaults": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "parse-filepath": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz" } }, "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "version": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", "dev": true }, "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "version": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", "dev": true }, "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "version": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "del": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "write": "https://registry.npmjs.org/write/-/write-0.2.1.tgz" } }, "flush-write-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", + "version": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.4" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "follow-redirects": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", + "version": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", "dev": true, "optional": true, "requires": { - "debug": "2.6.9" + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "optional": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } }, "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "version": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "version": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" } }, "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "version": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, "foreachasync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", + "version": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", "dev": true }, "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true }, "fork-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "version": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", "dev": true }, "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "version": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", + "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "mime-types": "2.1.17" } }, "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "version": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "0.2.2" + "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" } }, "fresh": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "version": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", "dev": true }, "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "version": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, "fs-access": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "version": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", "dev": true, "requires": { - "null-check": "1.0.0" + "null-check": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz" } }, "fs-extra": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", + "version": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, "requires": { - "jsonfile": "1.0.1", - "mkdirp": "0.3.5", - "ncp": "0.4.2", - "rimraf": "2.2.8" + "jsonfile": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "ncp": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" }, "dependencies": { "mkdirp": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true }, "rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", "dev": true } } }, "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "version": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "through2": "2.0.3" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "fs.extra": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", + "version": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", "integrity": "sha1-3QI/kwE77iRTHxszUUw3sg/ZM0k=", "dev": true, "requires": { - "fs-extra": "0.6.4", - "mkdirp": "0.3.5", - "walk": "2.3.9" + "fs-extra": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "walk": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz" }, "dependencies": { "mkdirp": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true } } }, "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "fsevents": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "version": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha1-EfgjGPX+e7LNIpZaEI6TBiCCFtg=", "dev": true, "optional": true, "requires": { @@ -5719,13 +5124,15 @@ "dependencies": { "abbrev": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", "dev": true, "optional": true }, "ajv": { "version": "4.11.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "optional": true, "requires": { @@ -5735,18 +5142,21 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "aproba": { "version": "1.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", + "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "dev": true, "optional": true, "requires": { @@ -5756,42 +5166,49 @@ }, "asn1": { "version": "0.2.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", "dev": true, "optional": true }, "assert-plus": { "version": "0.2.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true, "optional": true }, "asynckit": { "version": "0.4.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true, "optional": true }, "aws-sign2": { "version": "0.6.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", "dev": true, "optional": true }, "aws4": { "version": "1.6.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true, "optional": true }, "balanced-match": { "version": "0.4.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", "dev": true }, "bcrypt-pbkdf": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "dev": true, "optional": true, "requires": { @@ -5800,7 +5217,8 @@ }, "block-stream": { "version": "0.0.9", - "bundled": true, + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "dev": true, "requires": { "inherits": "2.0.3" @@ -5808,7 +5226,8 @@ }, "boom": { "version": "2.10.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { "hoek": "2.16.3" @@ -5816,7 +5235,8 @@ }, "brace-expansion": { "version": "1.1.7", - "bundled": true, + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", "dev": true, "requires": { "balanced-match": "0.4.2", @@ -5825,29 +5245,34 @@ }, "buffer-shims": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, "caseless": { "version": "0.12.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true, "optional": true }, "co": { "version": "4.6.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "combined-stream": { "version": "1.0.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", "dev": true, "requires": { "delayed-stream": "1.0.0" @@ -5855,22 +5280,26 @@ }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, "core-util-is": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "cryptiles": { "version": "2.0.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, "requires": { "boom": "2.10.1" @@ -5878,7 +5307,8 @@ }, "dashdash": { "version": "1.14.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "optional": true, "requires": { @@ -5887,7 +5317,8 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true, "optional": true } @@ -5895,7 +5326,8 @@ }, "debug": { "version": "2.6.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", "dev": true, "optional": true, "requires": { @@ -5904,30 +5336,35 @@ }, "deep-extend": { "version": "0.4.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", "dev": true, "optional": true }, "delayed-stream": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.2.tgz", + "integrity": "sha1-ca1dIEvxempsqPRQxhRUBm70YeE=", "dev": true, "optional": true }, "ecc-jsbn": { "version": "0.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "dev": true, "optional": true, "requires": { @@ -5936,24 +5373,28 @@ }, "extend": { "version": "3.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true, "optional": true }, "extsprintf": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", "dev": true }, "forever-agent": { "version": "0.6.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true, "optional": true }, "form-data": { "version": "2.1.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, "optional": true, "requires": { @@ -5964,12 +5405,14 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "fstream": { "version": "1.0.11", - "bundled": true, + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "dev": true, "requires": { "graceful-fs": "4.1.11", @@ -5980,7 +5423,8 @@ }, "fstream-ignore": { "version": "1.0.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", "dev": true, "optional": true, "requires": { @@ -5991,7 +5435,8 @@ }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, "requires": { @@ -6007,7 +5452,8 @@ }, "getpass": { "version": "0.1.7", - "bundled": true, + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "optional": true, "requires": { @@ -6016,7 +5462,8 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true, "optional": true } @@ -6024,7 +5471,8 @@ }, "glob": { "version": "7.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -6037,18 +5485,21 @@ }, "graceful-fs": { "version": "4.1.11", - "bundled": true, + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, "har-schema": { "version": "1.0.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", "dev": true, "optional": true }, "har-validator": { "version": "4.2.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true, "optional": true, "requires": { @@ -6058,13 +5509,15 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "hawk": { "version": "3.1.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { "boom": "2.10.1", @@ -6075,12 +5528,14 @@ }, "hoek": { "version": "2.16.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, "http-signature": { "version": "1.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "optional": true, "requires": { @@ -6091,7 +5546,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { "once": "1.4.0", @@ -6100,18 +5556,21 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "ini": { "version": "1.3.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "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" @@ -6119,24 +5578,28 @@ }, "is-typedarray": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true, "optional": true }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isstream": { "version": "0.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true, "optional": true }, "jodid25519": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", "dev": true, "optional": true, "requires": { @@ -6145,19 +5608,22 @@ }, "jsbn": { "version": "0.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true, "optional": true }, "json-schema": { "version": "0.2.3", - "bundled": true, + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true, "optional": true }, "json-stable-stringify": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "optional": true, "requires": { @@ -6166,19 +5632,22 @@ }, "json-stringify-safe": { "version": "5.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true, "optional": true }, "jsonify": { "version": "0.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true, "optional": true }, "jsprim": { "version": "1.4.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", "dev": true, "optional": true, "requires": { @@ -6190,7 +5659,8 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true, "optional": true } @@ -6198,12 +5668,14 @@ }, "mime-db": { "version": "1.27.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", "dev": true }, "mime-types": { "version": "2.1.15", - "bundled": true, + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", "dev": true, "requires": { "mime-db": "1.27.0" @@ -6211,7 +5683,8 @@ }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.7" @@ -6219,12 +5692,14 @@ }, "minimist": { "version": "0.0.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mkdirp": { "version": "0.5.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { "minimist": "0.0.8" @@ -6232,13 +5707,15 @@ }, "ms": { "version": "2.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "optional": true }, "node-pre-gyp": { "version": "0.6.39", - "bundled": true, + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz", + "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", "dev": true, "optional": true, "requires": { @@ -6257,7 +5734,8 @@ }, "nopt": { "version": "4.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, "requires": { @@ -6267,7 +5745,8 @@ }, "npmlog": { "version": "4.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", + "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", "dev": true, "optional": true, "requires": { @@ -6279,24 +5758,28 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "oauth-sign": { "version": "0.8.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1.0.2" @@ -6304,19 +5787,22 @@ }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", "dev": true, "optional": true, "requires": { @@ -6326,35 +5812,41 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "performance-now": { "version": "0.2.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", "dev": true, "optional": true }, "process-nextick-args": { "version": "1.0.7", - "bundled": true, + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, "punycode": { "version": "1.4.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true, "optional": true }, "qs": { "version": "6.4.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", "dev": true, "optional": true }, "rc": { "version": "1.2.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", "dev": true, "optional": true, "requires": { @@ -6366,7 +5858,8 @@ "dependencies": { "minimist": { "version": "1.2.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true } @@ -6374,7 +5867,8 @@ }, "readable-stream": { "version": "2.2.9", - "bundled": true, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", "dev": true, "requires": { "buffer-shims": "1.0.0", @@ -6388,7 +5882,8 @@ }, "request": { "version": "2.81.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "dev": true, "optional": true, "requires": { @@ -6418,7 +5913,8 @@ }, "rimraf": { "version": "2.6.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", "dev": true, "requires": { "glob": "7.1.2" @@ -6426,30 +5922,35 @@ }, "safe-buffer": { "version": "5.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", "dev": true }, "semver": { "version": "5.3.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "sntp": { "version": "1.0.9", - "bundled": true, + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, "requires": { "hoek": "2.16.3" @@ -6457,7 +5958,8 @@ }, "sshpk": { "version": "1.13.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", + "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", "dev": true, "optional": true, "requires": { @@ -6474,7 +5976,8 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true, "optional": true } @@ -6482,7 +5985,8 @@ }, "string-width": { "version": "1.0.2", - "bundled": true, + "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", @@ -6492,7 +5996,8 @@ }, "string_decoder": { "version": "1.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", + "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=", "dev": true, "requires": { "safe-buffer": "5.0.1" @@ -6500,13 +6005,15 @@ }, "stringstream": { "version": "0.0.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", "dev": true, "optional": true }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "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" @@ -6514,13 +6021,15 @@ }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "2.2.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { "block-stream": "0.0.9", @@ -6530,7 +6039,8 @@ }, "tar-pack": { "version": "3.4.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", + "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", "dev": true, "optional": true, "requires": { @@ -6546,7 +6056,8 @@ }, "tough-cookie": { "version": "2.3.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", "dev": true, "optional": true, "requires": { @@ -6555,7 +6066,8 @@ }, "tunnel-agent": { "version": "0.6.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "optional": true, "requires": { @@ -6564,30 +6076,35 @@ }, "tweetnacl": { "version": "0.14.5", - "bundled": true, + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true, "optional": true }, "uid-number": { "version": "0.0.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", "dev": true, "optional": true }, "util-deprecate": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, "uuid": { "version": "3.0.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", "dev": true, "optional": true }, "verror": { "version": "1.3.6", - "bundled": true, + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", "dev": true, "optional": true, "requires": { @@ -6596,7 +6113,8 @@ }, "wide-align": { "version": "1.1.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "optional": true, "requires": { @@ -6605,446 +6123,398 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true } } }, "fstream": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "version": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", "dev": true, "requires": { - "graceful-fs": "3.0.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" }, "dependencies": { "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "1.1.1" + "natives": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz" } } } }, "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "version": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", "dev": true, "requires": { - "readable-stream": "1.1.14", - "xregexp": "2.0.0" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "xregexp": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", "dev": true }, "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", + "version": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "version": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", "dev": true, "requires": { - "globule": "0.1.0" + "globule": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz" } }, "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "version": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", "dev": true }, "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "version": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, "requires": { - "is-property": "1.0.2" + "is-property": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" } }, "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "version": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, "get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "version": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", "dev": true }, "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "version": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, "get-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", - "integrity": "sha512-7aelVrYqCLuVjq2kEKRTH8fXPTC0xKTkM+G7UlFkEwCXY3sFbSxvY375JoFowOAYbkaU47SrBvOefUlLZZ+6QA==", + "version": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", + "integrity": "sha1-29ysrNjGCKODFoaTaBF2l6FjHFk=", "dev": true, "requires": { - "data-uri-to-buffer": "1.2.0", - "debug": "2.6.9", - "extend": "3.0.1", - "file-uri-to-path": "1.0.0", - "ftp": "0.3.10", - "readable-stream": "2.3.4" + "data-uri-to-buffer": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "file-uri-to-path": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "ftp": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } }, "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "version": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" }, "dependencies": { "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "git-up": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", - "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", + "version": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", + "integrity": "sha1-IP5rr770OEyuJT3E9GPEmgw70uw=", "dev": true, "requires": { - "is-ssh": "1.3.0", - "parse-url": "1.3.11" + "is-ssh": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", + "parse-url": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz" } }, "git-url-parse": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.1.0.tgz", - "integrity": "sha512-tSdNasqIc9cjK75DRsirb5sqVJ4V4cCmCuuOyyx2SuYeJx4o9AOx+/ZCSwRrYjZ8zavtuhGjCqXlCo9Db0YIVA==", + "version": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.1.0.tgz", + "integrity": "sha1-0e4JIT785djceiG7A/F8/gwRESI=", "dev": true, "requires": { - "git-up": "2.0.10" + "git-up": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz" } }, "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==", + "version": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", + "integrity": "sha1-itoyhv0EbYlRw8lSqNeFTP2Q/Zo=", "dev": true, "requires": { - "emoji-regex": "6.1.1" + "emoji-regex": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz" } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "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" + "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" } }, "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "version": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" }, "dependencies": { "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" } }, "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "version": "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", + "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" } } } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "path-dirname": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" }, "dependencies": { "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" } } } }, "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", "dev": true, "requires": { - "extend": "3.0.1", - "glob": "7.1.2", - "glob-parent": "3.1.0", - "is-negated-glob": "1.0.0", - "ordered-read-streams": "1.0.1", - "pumpify": "1.4.0", - "readable-stream": "2.3.4", - "remove-trailing-separator": "1.1.0", - "to-absolute-glob": "2.0.2", - "unique-stream": "2.2.1" + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "is-negated-glob": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "pumpify": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "to-absolute-glob": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz" } }, "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "version": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", "dev": true, "requires": { - "gaze": "0.5.2" + "gaze": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz" } }, "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "version": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", "dev": true, "requires": { - "find-index": "0.1.1" + "find-index": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz" } }, "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "version": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { - "global-prefix": "1.0.2", + "global-prefix": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "is-windows": "1.0.1", - "resolve-dir": "1.0.1" + "resolve-dir": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" } }, "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "version": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", + "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "homedir-polyfill": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "ini": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "is-windows": "1.0.1", - "which": "1.3.0" + "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" } }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "version": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", "dev": true }, "globals-docs": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", - "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", + "version": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", + "integrity": "sha1-8sZHVE62Fhx8OEUoCOFuaTwtr7s=", "dev": true }, "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "version": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "arrify": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" }, "dependencies": { "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "version": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" + "glob": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" }, "dependencies": { "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "version": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", "dev": true, "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" } }, "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", "dev": true }, "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "version": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", "dev": true }, "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "version": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", "dev": true }, "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", "dev": true }, "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "version": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" } } } }, "glogg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "version": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha1-3PdY5EeJzD89MsHzVio2duajSBA=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, @@ -7055,812 +6525,731 @@ "dev": true }, "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "version": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.1.0", - "liftoff": "2.5.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" + "archy": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "deprecated": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "liftoff": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "orchestrator": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "pretty-hrtime": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "tildify": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "v8flags": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz" }, "dependencies": { "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "version": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", "dev": true }, "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "version": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" } }, "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" + "glob": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "glob2base": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" } }, "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "1.1.1" + "natives": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz" } }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "version": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", "dev": true }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", "dev": true, "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" + "first-chunk-stream": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" } }, "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", "dev": true }, "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" + "clone": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } }, "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" + "defaults": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "glob-watcher": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz" } } } }, "gulp-babel": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", - "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", + "version": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", + "integrity": "sha1-Wq2Kyw22t/Lwvhnu7pUo8gZN9jE=", "dev": true, "requires": { - "babel-core": "6.26.0", - "object-assign": "4.1.1", - "plugin-error": "1.0.1", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" + "babel-core": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "plugin-error": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl-sourcemaps-apply": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz" }, "dependencies": { "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "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.5", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" + "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "babel-helpers": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "babel-register": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" } }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "gulp-clean": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", + "version": "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.6.2", - "through2": "0.4.2" + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz" }, "dependencies": { "ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "version": "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", + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", "dev": true }, "chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "version": "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.5", - "has-ansi": "0.1.0", - "strip-ansi": "0.3.0", - "supports-color": "0.2.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "has-ansi": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } }, "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "version": "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", + "version": "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.7.0" + "get-stdin": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "meow": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz" } }, "gulp-util": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "version": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", "dev": true, "requires": { - "chalk": "0.5.1", - "dateformat": "1.0.12", - "lodash._reinterpolate": "2.4.1", - "lodash.template": "2.4.1", - "minimist": "0.2.0", - "multipipe": "0.1.2", - "through2": "0.5.1", - "vinyl": "0.2.3" + "chalk": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "dateformat": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "multipipe": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz" }, "dependencies": { "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "version": "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" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" } } } }, "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", "dev": true, "requires": { - "ansi-regex": "0.2.1" + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "lodash._reinterpolate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", "dev": true }, "lodash.escape": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", "dev": true, "requires": { - "lodash._escapehtmlchar": "2.4.1", - "lodash._reunescapedhtml": "2.4.1", - "lodash.keys": "2.4.1" + "lodash._escapehtmlchar": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "lodash._reunescapedhtml": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" } }, "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" + "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" } }, "lodash.template": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "version": "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._escapestringchar": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "lodash.defaults": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "lodash.templatesettings": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "lodash.values": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz" } }, "lodash.templatesettings": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "version": "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" + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz" } }, "minimist": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "version": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", "dev": true }, "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "version": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "strip-ansi": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", "dev": true, "requires": { - "ansi-regex": "0.2.1" + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } }, "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", "dev": true }, "through2": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "version": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "2.1.2" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz" }, "dependencies": { "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "version": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", "dev": true, "requires": { - "object-keys": "0.4.0" + "object-keys": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" } } } }, "vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", "dev": true, "requires": { - "clone-stats": "0.0.1" + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } }, "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "version": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", "dev": true } } }, "gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "version": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, "requires": { - "concat-with-sourcemaps": "1.0.5", - "through2": "2.0.3", - "vinyl": "2.1.0" + "concat-with-sourcemaps": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz" } }, "gulp-connect": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", + "version": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", "dev": true, "requires": { - "connect": "2.30.2", - "connect-livereload": "0.5.4", - "event-stream": "3.3.4", - "gulp-util": "3.0.8", - "tiny-lr": "0.2.1" + "connect": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", + "connect-livereload": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", + "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "tiny-lr": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz" }, "dependencies": { "body-parser": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", "dev": true, "requires": { - "bytes": "2.2.0", - "content-type": "1.0.4", - "debug": "2.2.0", - "depd": "1.1.2", - "http-errors": "1.3.1", - "iconv-lite": "0.4.13", - "on-finished": "2.3.0", - "qs": "5.2.0", - "raw-body": "2.1.7", + "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", "type-is": "1.6.15" }, "dependencies": { "qs": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "version": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", "dev": true } } }, "bytes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", "dev": true }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "version": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "iconv-lite": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "qs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "version": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", "dev": true }, "raw-body": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", "dev": true, "requires": { - "bytes": "2.4.0", - "iconv-lite": "0.4.13", - "unpipe": "1.0.0" + "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" }, "dependencies": { "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", "dev": true } } }, "tiny-lr": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "version": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", "dev": true, "requires": { - "body-parser": "1.14.2", - "debug": "2.2.0", - "faye-websocket": "0.10.0", - "livereload-js": "2.3.0", - "parseurl": "1.3.2", - "qs": "5.1.0" + "body-parser": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "faye-websocket": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "livereload-js": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz" } } } }, "gulp-documentation": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", + "version": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", "dev": true, "requires": { - "through2": "2.0.3", - "vinyl": "2.1.0" + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz" } }, "gulp-eslint": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", - "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", + "version": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", + "integrity": "sha1-GKKmdo5EBMvz4gMjnLV0dBaPpgY=", "dev": true, "requires": { "eslint": "4.17.0", - "fancy-log": "1.3.2", - "plugin-error": "1.0.1" + "fancy-log": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "plugin-error": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz" } }, "gulp-footer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", - "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", + "version": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", + "integrity": "sha1-f+KDJOxn49YY0x4PXqLuW0VPaHc=", "dev": true, "requires": { - "event-stream": "3.3.4", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2" + "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "lodash._reescape": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "lodash._reevaluate": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz" } }, "gulp-header": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.9.tgz", + "version": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.9.tgz", "integrity": "sha1-yfEP7gYy2B6Tl4nG7PRaFRvzCYs=", "dev": true, "requires": { - "concat-with-sourcemaps": "1.0.5", - "gulp-util": "3.0.8", - "object-assign": "4.1.1", - "through2": "2.0.3" + "concat-with-sourcemaps": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "gulp-if": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", + "version": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", "dev": true, "requires": { - "gulp-match": "1.0.3", - "ternary-stream": "2.0.1", - "through2": "2.0.3" + "gulp-match": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "ternary-stream": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "gulp-js-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz", + "version": "https://registry.npmjs.org/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz", "integrity": "sha1-HNRF+9AJ4Np2lZoDp/SbNWav+Gg=", "dev": true, "requires": { - "through2": "0.6.5" + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } } } }, "gulp-match": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "version": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", "dev": true, "requires": { - "minimatch": "3.0.4" + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" } }, "gulp-optimize-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", + "version": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", "dev": true, "requires": { - "gulp-util": "3.0.8", - "lodash": "4.17.5", - "optimize-js": "1.0.3", - "through2": "2.0.3" + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "optimize-js": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "gulp-rename": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", + "version": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", "dev": true }, "gulp-replace": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", + "version": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", "dev": true, "requires": { - "event-stream": "3.0.20", - "istextorbinary": "1.0.2", - "replacestream": "0.1.3" + "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", + "istextorbinary": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", + "replacestream": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz" }, "dependencies": { "event-stream": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", + "version": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", "dev": true, "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.0.7", - "pause-stream": "0.0.11", - "split": "0.2.10", - "stream-combiner": "0.0.4", - "through": "2.3.8" + "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "from": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "pause-stream": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "split": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "stream-combiner": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" } }, "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "version": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, "split": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "version": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", "dev": true, "requires": { - "through": "2.3.8" + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" } } } }, "gulp-shell": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", + "version": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", "dev": true, "requires": { - "async": "1.5.2", - "gulp-util": "3.0.8", - "lodash": "4.17.5", - "through2": "2.0.3" + "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "gulp-sourcemaps": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "version": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", "requires": { - "@gulp-sourcemaps/identity-map": "1.0.1", - "@gulp-sourcemaps/map-sources": "1.0.0", + "@gulp-sourcemaps/identity-map": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", + "@gulp-sourcemaps/map-sources": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", "acorn": "5.4.1", - "convert-source-map": "1.5.1", - "css": "2.2.1", - "debug-fabulous": "1.0.0", - "detect-newline": "2.1.0", - "graceful-fs": "4.1.11", - "source-map": "0.6.1", - "strip-bom-string": "1.0.0", - "through2": "2.0.3" + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "css": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "debug-fabulous": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", + "detect-newline": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "strip-bom-string": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "gulp-uglify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", + "version": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", "dev": true, "requires": { - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash": "4.17.5", - "make-error-cause": "1.2.2", - "through2": "2.0.3", + "gulplog": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "has-gulplog": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "make-error-cause": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "uglify-js": "3.3.10", - "vinyl-sourcemaps-apply": "0.2.1" + "vinyl-sourcemaps-apply": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz" }, "dependencies": { "uglify-js": { @@ -7869,689 +7258,620 @@ "integrity": "sha512-dNib7aUDNZFJNTXFyq0CDmLRVOsnY1F+IQgt2FAOdZFx2+LvKVLbbIb/fL+BYKCv3YH3bPCE/6M/JaxChtQLHQ==", "dev": true, "requires": { - "commander": "2.14.1", - "source-map": "0.6.1" + "commander": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" } } } }, "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "version": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "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.2", - "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.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" + "array-differ": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "array-uniq": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "beeper": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dateformat": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "fancy-log": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "gulplog": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "has-gulplog": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "lodash._reescape": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "lodash._reevaluate": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "multipipe": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz" }, "dependencies": { "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "version": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", "dev": true }, "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "version": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", "dev": true }, "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" } } } }, "gulp-webdriver": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", + "version": "https://registry.npmjs.org/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", "integrity": "sha1-mM6Bz5rganoZB7htEPaThvQ4Oi0=", "dev": true, "requires": { - "dargs": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", - "deepmerge": "0.2.10", - "gulp-util": "3.0.8", - "through2": "0.6.5", - "webdriverio": "3.4.0" + "dargs": "git://github.com/christian-bromann/dargs.git#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", + "deepmerge": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "webdriverio": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz" }, "dependencies": { + "dargs": { + "version": "git://github.com/christian-bromann/dargs.git#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", + "dev": true, + "requires": { + "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + } + }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } } } }, "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "version": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.1" + "glogg": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz" } }, "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "version": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" + "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz" }, "dependencies": { "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" } } } }, "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "version": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", "dev": true }, "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "version": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", "dev": true, "requires": { - "chalk": "1.1.3", - "commander": "2.14.1", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "commander": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", "is-my-json-valid": "2.17.1", - "pinkie-promise": "2.0.1" + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "version": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "function-bind": "1.1.1" + "function-bind": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" } }, "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" } }, "has-binary2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", + "version": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", "dev": true, "requires": { - "isarray": "2.0.1" + "isarray": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz" }, "dependencies": { "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true } } }, "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "version": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", "dev": true }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "version": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "version": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" } }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "version": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "version": "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.1" + "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "has-values": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" } }, "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "version": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" }, "dependencies": { "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "version": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" } }, "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "version": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha1-NA3tvmKQGHFRweodd3o0SJNd+EY=", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" } }, "hast-util-is-element": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", + "version": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", "integrity": "sha1-P3IWl4sq4U2YdJh4eCZ18zvjzgA=", "dev": true }, "hast-util-sanitize": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", + "version": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", "integrity": "sha1-0QvWdXoh5ZwTq8iuNTDdO219Z54=", "dev": true, "requires": { - "xtend": "4.0.1" + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "hast-util-to-html": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", + "version": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", "dev": true, "requires": { - "ccount": "1.0.2", - "comma-separated-tokens": "1.0.4", - "hast-util-is-element": "1.0.0", - "hast-util-whitespace": "1.0.0", - "html-void-elements": "1.0.2", - "kebab-case": "1.0.0", - "property-information": "3.2.0", - "space-separated-tokens": "1.1.1", - "stringify-entities": "1.3.1", - "unist-util-is": "2.1.1", - "xtend": "4.0.1" + "ccount": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", + "comma-separated-tokens": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.4.tgz", + "hast-util-is-element": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", + "hast-util-whitespace": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", + "html-void-elements": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.2.tgz", + "kebab-case": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", + "property-information": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", + "space-separated-tokens": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz", + "stringify-entities": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", + "unist-util-is": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "hast-util-whitespace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", + "version": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", "integrity": "sha1-vQlpGWJdKTbh/xe8Tff9cn8X7Ok=", "dev": true }, "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "sntp": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" } }, "highlight.js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "version": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", "dev": true }, "hipchat-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "version": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", "dev": true, "optional": true, "requires": { - "lodash": "4.17.5", - "request": "2.79.0" + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "request": "https://registry.npmjs.org/request/-/request-2.79.0.tgz" } }, "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "version": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "hash.js": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "minimalistic-crypto-utils": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" } }, "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "version": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "os-tmpdir": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" } }, "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "version": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "1.0.0" + "parse-passwd": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" } }, "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", "dev": true }, "html-void-elements": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.2.tgz", + "version": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.2.tgz", "integrity": "sha1-nSLgyjKsyVs/RbjVtPb73AWv/VU=", "dev": true }, "htmlescape": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "version": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", "dev": true }, "http-errors": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", "dev": true, "requires": { - "inherits": "2.0.3", - "statuses": "1.4.0" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz" } }, "http-parser-js": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "version": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", "dev": true }, "http-proxy": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "version": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", "dev": true, "requires": { - "eventemitter3": "1.2.0", - "requires-port": "1.0.0" + "eventemitter3": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "requires-port": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" } }, "http-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", + "version": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", "dev": true, "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" + "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } }, "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "jsprim": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "sshpk": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz" } }, "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "version": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", "dev": true, "requires": { - "httpreq": "0.4.24", - "underscore": "1.7.0" + "httpreq": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "underscore": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" } }, "httpreq": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "version": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", "dev": true }, "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "version": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "version": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", "dev": true, "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" + "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } }, "iconv-lite": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", "dev": true }, "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "version": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", "dev": true }, "ignore": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "version": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha1-YSKJv7PCIOGGpYEYYY1b6MG6sCE=", "dev": true }, "ignore-loader": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz", + "version": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz", "integrity": "sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM=", "dev": true }, "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "version": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "version": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" } }, "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "version": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, "inflection": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", + "version": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", "integrity": "sha1-W//LEZetPoEFD44X4hZoCH7p6y8=", "dev": true, "optional": true }, "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", "dev": true }, "inline-source-map": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "version": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "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, - "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.1", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.5", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "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" + "version": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", + "dev": true, + "requires": { + "ansi-escapes": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "cli-cursor": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "cli-width": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "external-editor": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "figures": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "mute-stream": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "run-async": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "rx-lite": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "rx-lite-aggregates": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" } }, "chalk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "5.2.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" } }, "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", + "version": "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==", + "version": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "version": "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" } }, "supports-color": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" } } } @@ -8562,14 +7882,14 @@ "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", "dev": true, "requires": { - "JSONStream": "1.3.2", + "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", "combine-source-map": "0.7.2", "concat-stream": "1.5.2", - "is-buffer": "1.1.6", - "lexical-scope": "1.2.0", - "process": "0.11.10", - "through2": "2.0.3", - "xtend": "4.0.1" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "lexical-scope": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" }, "dependencies": { "combine-source-map": { @@ -8579,8 +7899,8 @@ "dev": true, "requires": { "convert-source-map": "1.1.3", - "inline-source-map": "0.6.2", - "lodash.memoize": "3.0.4", + "inline-source-map": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "lodash.memoize": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", "source-map": "0.5.7" } }, @@ -8590,9 +7910,9 @@ "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, "requires": { - "inherits": "2.0.3", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "readable-stream": "2.0.6", - "typedarray": "0.0.6" + "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" } }, "convert-source-map": { @@ -8613,12 +7933,12 @@ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "process-nextick-args": "1.0.7", "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" } }, "source-map": { @@ -8636,8 +7956,7 @@ } }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "version": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, @@ -8647,181 +7966,158 @@ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", "dev": true, "requires": { - "loose-envify": "1.3.1" + "loose-envify": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz" } }, "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "version": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, "ip": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", + "version": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", "dev": true }, "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==", + "version": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", "dev": true, "requires": { - "is-relative": "1.0.0", + "is-relative": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", "is-windows": "1.0.1" } }, "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": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz" } }, "is-alphabetical": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", "integrity": "sha1-x3B5zJHU76x3W+EDS/LSQ/lebwg=", "dev": true }, "is-alphanumeric": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "version": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", "dev": true }, "is-alphanumerical": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", "integrity": "sha1-37SqTRCF4zvbYcLe6cgOnGwZ9Ts=", "dev": true, "requires": { - "is-alphabetical": "1.0.1", - "is-decimal": "1.0.1" + "is-alphabetical": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", + "is-decimal": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz" } }, "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "1.11.0" + "binary-extensions": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz" } }, "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", "dev": true }, "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" } }, "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": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz" } }, "is-decimal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", "integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI=", "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": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz" } }, "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "version": "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", + "version": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "2.0.0" + "is-primitive": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz" } }, "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "version": "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", + "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" } }, "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", + "version": "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" + "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" } }, "is-generator": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", + "version": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", "dev": true }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "version": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" } }, "is-hexadecimal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz", "integrity": "sha1-bghLvJIGH7sJcexYts5tQE4k2mk=", "dev": true }, @@ -8831,41 +8127,37 @@ "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", "dev": true, "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" + "generate-function": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "generate-object-property": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "jsonpointer": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "version": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", "dev": true }, "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "version": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", "dev": true }, @@ -8875,131 +8167,113 @@ "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=", "dev": true, "requires": { - "is-number": "3.0.0" + "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" } }, "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "version": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", "dev": true }, "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "version": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "is-path-inside": "1.0.1" + "is-path-inside": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz" } }, "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" } }, "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "version": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "version": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" } }, "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "version": "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", + "version": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "version": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "version": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", "dev": true }, "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==", + "version": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", "dev": true, "requires": { - "is-unc-path": "1.0.0" + "is-unc-path": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz" } }, "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "version": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", "dev": true }, "is-ssh": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", + "version": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", "dev": true, "requires": { - "protocols": "1.4.6" + "protocols": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz" } }, "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, "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==", + "version": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", "dev": true, "requires": { - "unc-path-regex": "0.1.2" + "unc-path-regex": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz" } }, "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "version": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", "dev": true }, "is-whitespace-character": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", "integrity": "sha1-muAXbzKCtlRXoZks2whPil+DPjs=", "dev": true }, @@ -9010,253 +8284,227 @@ "dev": true }, "is-word-character": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", + "version": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", "integrity": "sha1-WgP6HqkazopusMfNdw64bWXIvvs=", "dev": true }, "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "version": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", "dev": true }, "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "version": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "version": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "glob": "5.0.15", - "handlebars": "4.0.11", - "js-yaml": "3.6.1", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.0", - "wordwrap": "1.0.0" + "abbrev": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "escodegen": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "esprima": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "handlebars": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "nopt": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" }, "dependencies": { "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" } }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" } } } }, "istanbul-api": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.2.tgz", - "integrity": "sha512-kH5YRdqdbs5hiH4/Rr1Q0cSAGgjh3jTtg8vu9NLebBAoK3adVO4jk81J+TYOkTr2+Q4NLeb1ACvmEt65iG/Vbw==", - "dev": true, - "requires": { - "async": "2.6.0", - "fileset": "2.0.3", - "istanbul-lib-coverage": "1.1.2", - "istanbul-lib-hook": "1.1.0", - "istanbul-lib-instrument": "1.9.2", - "istanbul-lib-report": "1.1.3", - "istanbul-lib-source-maps": "1.2.3", - "istanbul-reports": "1.1.4", - "js-yaml": "3.10.0", - "mkdirp": "0.5.1", - "once": "1.4.0" + "version": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.2.tgz", + "integrity": "sha1-4XzVGd1exBQRl/JG/fOAt1SH87E=", + "dev": true, + "requires": { + "async": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "fileset": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "istanbul-lib-coverage": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", + "istanbul-lib-hook": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", + "istanbul-lib-instrument": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz", + "istanbul-lib-report": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", + "istanbul-lib-source-maps": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", + "istanbul-reports": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.4.tgz", + "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" }, "dependencies": { "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "version": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "version": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", "dev": true }, "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", "dev": true, "requires": { "argparse": "1.0.9", - "esprima": "4.0.0" + "esprima": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz" } } } }, "istanbul-instrumenter-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz", - "integrity": "sha512-alLSEFX06ApU75sm5oWcaVNaiss/bgMRiWTct3g0P0ZZTKjR+6QiCcuVOKDI1kWJgwHEnIXsv/dWm783kPpmtw==", + "version": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz", + "integrity": "sha1-n1U5I7IjYLrJXmF6q6Aa3R99sLI=", "dev": true, "requires": { - "convert-source-map": "1.5.1", - "istanbul-lib-instrument": "1.9.2", - "loader-utils": "1.1.0", - "schema-utils": "0.3.0" + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "istanbul-lib-instrument": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz", + "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "schema-utils": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz" } }, "istanbul-lib-coverage": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", - "integrity": "sha512-tZYA0v5A7qBSsOzcebJJ/z3lk3oSzH62puG78DbBA1+zupipX2CakDyiPV3pOb8He+jBwVimuwB0dTnh38hX0w==", + "version": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", + "integrity": "sha1-QRPI/2t6QKHvc1CwEBYzH2Ov3hQ=", "dev": true }, "istanbul-lib-hook": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", - "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==", + "version": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", + "integrity": "sha1-hTjZcDcss3FtU+VVI91UtVeo2Js=", "dev": true, "requires": { - "append-transform": "0.4.0" + "append-transform": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz" } }, "istanbul-lib-instrument": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz", - "integrity": "sha512-nz8t4HQ2206a/3AXi+NHFWEa844DMpPsgbcUteJbt1j8LX1xg56H9rOMnhvcvVvPbW60qAIyrSk44H8ZDqaSSA==", + "version": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz", + "integrity": "sha1-hJBb9H9+C0Ada4QNp7rWcIa0qrY=", "dev": true, "requires": { - "babel-generator": "6.26.1", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "istanbul-lib-coverage": "1.1.2", - "semver": "5.5.0" + "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "istanbul-lib-coverage": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz" } }, "istanbul-lib-report": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", - "integrity": "sha512-D4jVbMDtT2dPmloPJS/rmeP626N5Pr3Rp+SovrPn1+zPChGHcggd/0sL29jnbm4oK9W0wHjCRsdch9oLd7cm6g==", + "version": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", + "integrity": "sha1-LfEhiMD6d5kMDSF20tC6M5QYglk=", "dev": true, "requires": { - "istanbul-lib-coverage": "1.1.2", - "mkdirp": "0.5.1", - "path-parse": "1.0.5", - "supports-color": "3.2.3" + "istanbul-lib-coverage": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "path-parse": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz" }, "dependencies": { "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" } } } }, "istanbul-lib-source-maps": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", - "integrity": "sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA==", + "version": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", + "integrity": "sha1-IPtUsU4Us/tu22rKNXH9IUPbROY=", "dev": true, "requires": { - "debug": "3.1.0", - "istanbul-lib-coverage": "1.1.2", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "source-map": "0.5.7" + "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "istanbul-lib-coverage": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "istanbul-reports": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.4.tgz", - "integrity": "sha512-DfSTVOTkuO+kRmbO8Gk650Wqm1WRGr6lrdi2EwDK1vxpS71vdlLd613EpzOKdIFioB5f/scJTjeWBnvd1FWejg==", + "version": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.4.tgz", + "integrity": "sha1-XMul4it7Wl2R1eCoMPib4zS/l70=", "dev": true, "requires": { - "handlebars": "4.0.11" + "handlebars": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz" } }, "istextorbinary": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", + "version": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", "dev": true, "requires": { - "binaryextensions": "1.0.1", - "textextensions": "1.0.2" + "binaryextensions": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", + "textextensions": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz" } }, "jade": { @@ -9284,257 +8532,228 @@ } }, "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "version": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, "js-yaml": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", "dev": true, "requires": { "argparse": "1.0.9", - "esprima": "2.7.3" + "esprima": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" } }, "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true, "optional": true }, "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "version": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "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==", + "version": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=", "dev": true }, "json-parse-better-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "version": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", + "integrity": "sha1-UBg80bLSUnXeBp6ecbRnrJ6rlzo=", "dev": true }, "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "version": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" } }, "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", + "version": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "version": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", "dev": true }, "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "version": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, "jsonfile": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", + "version": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", "dev": true }, "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "version": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "version": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "version": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "version": "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.2.3", - "verror": "1.10.0" + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "json-schema": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "verror": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" }, "dependencies": { "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "just-clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", + "version": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" }, "just-extend": { - "version": "1.1.27", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", - "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", + "version": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha1-7G55QQ/5FORyZSq/oOYDwD1g6QU=", "dev": true }, "karma": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.0.tgz", - "integrity": "sha512-K9Kjp8CldLyL9ANSUctDyxC7zH3hpqXj/K09qVf06K3T/kXaHtFZ5tQciK7OzQu68FLvI89Na510kqQ2LCbpIw==", + "version": "https://registry.npmjs.org/karma/-/karma-2.0.0.tgz", + "integrity": "sha1-oCaY3X8PBf9etmq49lWCSQtRLlg=", "dev": true, "requires": { - "bluebird": "3.5.1", - "body-parser": "1.18.2", - "browserify": "14.5.0", - "chokidar": "1.7.0", - "colors": "1.1.2", - "combine-lists": "1.0.1", + "bluebird": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "body-parser": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "browserify": "https://registry.npmjs.org/browserify/-/browserify-14.5.0.tgz", + "chokidar": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "colors": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "combine-lists": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", "connect": "3.6.5", - "core-js": "2.5.3", - "di": "0.0.1", - "dom-serialize": "2.2.1", - "expand-braces": "0.1.2", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "http-proxy": "1.16.2", - "isbinaryfile": "3.0.2", - "lodash": "4.17.5", - "log4js": "2.5.3", - "mime": "1.6.0", - "minimatch": "3.0.4", - "optimist": "0.6.1", + "core-js": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "di": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "dom-serialize": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "expand-braces": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "http-proxy": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "isbinaryfile": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "log4js": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", + "mime": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "qjobs": "1.1.5", - "range-parser": "1.2.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.1", - "socket.io": "2.0.4", - "source-map": "0.6.1", - "tmp": "0.0.33", - "useragent": "2.3.0" + "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "socket.io": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "tmp": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "useragent": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz" }, "dependencies": { "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "version": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", "dev": true, "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" + "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" } }, "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" } }, "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", "dev": true, "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", - "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", + "bytes": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "type-is": "1.6.15" } }, "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "version": "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.2" + "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" } }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "version": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.1.3", - "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.1.0" + "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "fsevents": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" } }, "connect": { @@ -9543,43 +8762,39 @@ "integrity": "sha1-+43ee6B2OHfQ7J352sC0tA5yx9o=", "dev": true, "requires": { - "debug": "2.6.9", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "finalhandler": "1.0.6", - "parseurl": "1.3.2", - "utils-merge": "1.0.1" + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" } }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "version": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" } }, "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "version": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" } }, "finalhandler": { @@ -9588,13 +8803,13 @@ "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=", "dev": true, "requires": { - "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "encodeurl": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "statuses": "1.3.1", - "unpipe": "1.0.0" + "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" }, "dependencies": { "statuses": { @@ -9606,350 +8821,284 @@ } }, "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" } }, "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", "dev": true, "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.4.0" + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "setprototypeof": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz" }, "dependencies": { "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", "dev": true } } }, "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", "dev": true }, "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "version": "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", + "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" } }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } }, "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "version": "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" + "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "braces": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "extglob": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "filename-regex": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" } }, "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "version": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", "dev": true }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", "dev": true }, "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "version": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", "dev": true }, "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" + "bytes": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" } }, "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true } } }, "karma-babel-preprocessor": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", + "version": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", "dev": true, "requires": { - "babel-core": "6.22.0" + "babel-core": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz" } }, "karma-browserstack-launcher": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", - "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", + "version": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", + "integrity": "sha1-Yf49NrHPEGgeQPnYdL83Jx+xxnQ=", "dev": true, "requires": { - "browserstack": "1.5.0", - "browserstacktunnel-wrapper": "2.0.1", - "q": "1.5.1" + "browserstack": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", + "browserstacktunnel-wrapper": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.1.tgz", + "q": "https://registry.npmjs.org/q/-/q-1.5.1.tgz" }, "dependencies": { "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "version": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true } } }, "karma-chai": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", + "version": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", "dev": true }, "karma-chrome-launcher": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "version": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha1-zxudBxNswY/iOTJ9JGVMPbw2is8=", "dev": true, "requires": { - "fs-access": "1.0.1", - "which": "1.3.0" + "fs-access": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" } }, "karma-coverage-istanbul-reporter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.1.tgz", - "integrity": "sha512-5og0toMjgLvsL9+TzGH4Rk1D0nr7pMIRJBg29xP4mHMKy/1KUJ12UzoqI6mBNCRFa4nDvZS2MRrN7p+RkZNWxQ==", + "version": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.1.tgz", + "integrity": "sha1-K0LRRd27SGjYXVKIjElaIcYdhzw=", "dev": true, "requires": { - "istanbul-api": "1.2.2", - "minimatch": "3.0.4" + "istanbul-api": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.2.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" } }, "karma-es5-shim": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", + "version": "https://registry.npmjs.org/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", "integrity": "sha1-zdADM8znfC5M4D46yT8vjs0fuVI=", "dev": true, "requires": { - "es5-shim": "4.5.10" - } - }, - "karma-expect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/karma-expect/-/karma-expect-1.1.3.tgz", - "integrity": "sha1-xrClb/GJA9sRr08JjMbnzxmM4nU=", - "dev": true, - "requires": { - "expect.js": "0.3.1" + "es5-shim": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz" } }, "karma-firefox-launcher": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", + "version": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", + "integrity": "sha1-LEcDBFLwRTHrfRPU/HZpYwu5Mzk=", "dev": true }, "karma-ie-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", + "version": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "karma-mocha": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", + "version": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "karma-mocha-reporter": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", + "version": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", "dev": true, "requires": { - "chalk": "2.3.1", - "log-symbols": "2.2.0", - "strip-ansi": "4.0.0" + "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "log-symbols": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" } }, "chalk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "5.2.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "version": "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" } }, "supports-color": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" } } } }, "karma-opera-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/karma-opera-launcher/-/karma-opera-launcher-1.0.0.tgz", + "version": "https://registry.npmjs.org/karma-opera-launcher/-/karma-opera-launcher-1.0.0.tgz", "integrity": "sha1-+lFihTGh0L6EstjcDX7iCfyP+Ro=", "dev": true }, "karma-requirejs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-1.1.0.tgz", + "version": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-1.1.0.tgz", "integrity": "sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=", "dev": true }, "karma-safari-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz", + "version": "https://registry.npmjs.org/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz", "integrity": "sha1-lpgqLMR9BmquccVTursoMZEVos4=", "dev": true }, - "karma-sauce-launcher": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/karma-sauce-launcher/-/karma-sauce-launcher-1.2.0.tgz", - "integrity": "sha512-lEhtGRGS+3Yw6JSx/vJY9iQyHNtTjcojrSwNzqNUOaDceKDu9dPZqA/kr69bUO9G2T6GKbu8AZgXqy94qo31Jg==", - "dev": true, - "requires": { - "q": "1.5.1", - "sauce-connect-launcher": "1.2.3", - "saucelabs": "1.4.0", - "wd": "1.5.0" - }, - "dependencies": { - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - } - } - }, "karma-script-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz", + "version": "https://registry.npmjs.org/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz", "integrity": "sha1-zQF8TeXvCeWp2nkydhdhCN1LVC0=", "dev": true }, "karma-sinon": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/karma-sinon/-/karma-sinon-1.0.5.tgz", + "version": "https://registry.npmjs.org/karma-sinon/-/karma-sinon-1.0.5.tgz", "integrity": "sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo=", "dev": true }, "karma-sourcemap-loader": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", + "version": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" } }, "karma-spec-reporter": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", + "version": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", "dev": true, "requires": { - "colors": "1.1.2" + "colors": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz" } }, "karma-webpack": { @@ -9962,7 +9111,7 @@ "loader-utils": "0.2.17", "lodash": "3.10.1", "source-map": "0.5.7", - "webpack-dev-middleware": "1.12.2" + "webpack-dev-middleware": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz" }, "dependencies": { "async": { @@ -9977,10 +9126,10 @@ "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" + "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } }, "lodash": { @@ -9998,518 +9147,457 @@ } }, "kebab-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", + "version": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=", "dev": true }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", "dev": true }, "labeled-stream-splicer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", + "version": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", "dev": true, "requires": { - "inherits": "2.0.3", - "isarray": "0.0.1", - "stream-splicer": "2.0.0" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "stream-splicer": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true } } }, "lazy-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", "dev": true, "requires": { - "set-getter": "0.1.0" + "set-getter": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz" } }, "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "version": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "dev": true, "requires": { - "readable-stream": "2.3.4" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "version": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "1.0.0" + "invert-kv": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" } }, "lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "version": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", "dev": true }, "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "version": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", "dev": true, "requires": { - "flush-write-stream": "1.0.2" + "flush-write-stream": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz" } }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "version": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "type-check": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" } }, "lexical-scope": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "version": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", "dev": true, "requires": { - "astw": "2.2.0" + "astw": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz" } }, "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "version": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", "dev": true }, "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "version": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, "requires": { - "iconv-lite": "0.4.15", - "libbase64": "0.1.0", - "libqp": "1.1.0" + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "libbase64": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "libqp": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz" }, "dependencies": { "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", "dev": true } } }, "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "version": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", "dev": true }, "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "version": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { - "extend": "3.0.1", - "findup-sync": "2.0.0", - "fined": "1.1.0", - "flagged-respawn": "1.0.0", - "is-plain-object": "2.0.4", - "object.map": "1.0.1", - "rechoir": "0.6.2", - "resolve": "1.5.0" + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "findup-sync": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "fined": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "flagged-respawn": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "object.map": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "rechoir": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" } }, "livereload-js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", - "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", + "version": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", + "integrity": "sha1-w6si6Kr1vzUF2A0JjLrWdyZUjJo=", "dev": true }, "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "4.0.0", - "pify": "3.0.0", - "strip-bom": "3.0.0" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" } }, "loader-runner": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "version": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", "dev": true }, "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "dev": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" + "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz" } }, "localtunnel": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.8.3.tgz", + "version": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.8.3.tgz", "integrity": "sha1-3MWSL9hWUQN9S94k/ZMkjQsk6wU=", "dev": true, "requires": { - "debug": "2.6.8", - "openurl": "1.1.1", - "request": "2.81.0", - "yargs": "3.29.0" + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "openurl": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "request": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.29.0.tgz" }, "dependencies": { "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "version": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" } }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true }, "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "version": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true, "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "ajv": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "har-schema": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz" } }, "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "version": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "1.0.0" + "lcid": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" } }, "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "version": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", "dev": true }, "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "version": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "dev": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "performance-now": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz" } }, "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", "dev": true }, "yargs": { - "version": "3.29.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.29.0.tgz", + "version": "https://registry.npmjs.org/yargs/-/yargs-3.29.0.tgz", "integrity": "sha1-GquWYOrnnYuPZ1vK7qtu40ws9pw=", "dev": true, "requires": { - "camelcase": "1.2.1", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "os-locale": "1.4.0", - "window-size": "0.1.4", - "y18n": "3.2.1" + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz" } } } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "version": "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-locate": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "path-exists": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" } }, "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha1-maktZcAnLevoyWtgV7yPv6O+1RE=", "dev": true }, "lodash._arraycopy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", + "version": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", "dev": true }, "lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", + "version": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", "dev": true }, "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "version": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" + "lodash._basecopy": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" } }, "lodash._baseclone": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", + "version": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", "dev": true, "requires": { - "lodash._arraycopy": "3.0.0", - "lodash._arrayeach": "3.0.0", - "lodash._baseassign": "3.2.0", - "lodash._basefor": "3.0.3", - "lodash.isarray": "3.0.4", - "lodash.keys": "3.1.2" + "lodash._arraycopy": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", + "lodash._arrayeach": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", + "lodash._baseassign": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "lodash._basefor": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "lodash.isarray": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" } }, "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "version": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", "dev": true }, "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "version": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", "dev": true }, "lodash._basefor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "version": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", "dev": true }, "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "version": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", "dev": true }, "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "version": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", "dev": true }, "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "version": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", "dev": true }, "lodash._escapehtmlchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", "dev": true, "requires": { - "lodash._htmlescapes": "2.4.1" + "lodash._htmlescapes": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } }, "lodash._escapestringchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", "dev": true }, "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "version": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", "dev": true }, "lodash._htmlescapes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", "dev": true }, "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "version": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", "dev": true }, "lodash._isnative": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", "dev": true }, "lodash._objecttypes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", "dev": true }, "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "version": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", "dev": true }, "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "version": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", "dev": true }, "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "version": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, "lodash._reunescapedhtml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, "requires": { - "lodash._htmlescapes": "2.4.1", - "lodash.keys": "2.4.1" + "lodash._htmlescapes": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" }, "dependencies": { "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" + "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" } } } }, "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "version": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", "dev": true }, "lodash._shimkeys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", "dev": true, "requires": { - "lodash._objecttypes": "2.4.1" + "lodash._objecttypes": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } }, "lodash._stack": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", + "version": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", "dev": true }, "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "version": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", "dev": true }, "lodash.clone": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", + "version": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", "dev": true, "requires": { - "lodash._baseclone": "3.3.0", - "lodash._bindcallback": "3.0.1", - "lodash._isiterateecall": "3.0.9" + "lodash._baseclone": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", + "lodash._bindcallback": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz" } }, "lodash.cond": { @@ -10519,377 +9607,339 @@ "dev": true }, "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "version": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", "dev": true, "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" + "lodash._baseassign": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "lodash._basecreate": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz" } }, "lodash.defaults": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "version": "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._objecttypes": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" }, "dependencies": { "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" + "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" } } } }, "lodash.defaultsdeep": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", + "version": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", "dev": true, "requires": { - "lodash._baseclone": "4.5.7", - "lodash._stack": "4.1.3", - "lodash.isplainobject": "4.0.6", - "lodash.keysin": "4.2.0", - "lodash.mergewith": "4.6.1", - "lodash.rest": "4.0.5" + "lodash._baseclone": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", + "lodash._stack": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", + "lodash.isplainobject": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "lodash.keysin": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", + "lodash.mergewith": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "lodash.rest": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz" }, "dependencies": { "lodash._baseclone": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", + "version": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", "dev": true } } }, "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "version": "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._root": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz" } }, "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "version": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", "dev": true }, "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", "dev": true }, "lodash.isobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", "dev": true, "requires": { - "lodash._objecttypes": "2.4.1" + "lodash._objecttypes": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } }, "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "version": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", "dev": true }, "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "version": "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._getnative": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "lodash.isarguments": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "lodash.isarray": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz" } }, "lodash.keysin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", + "version": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", "dev": true }, "lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "version": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", "dev": true }, "lodash.mergewith": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "version": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha1-Y5BX5ybDr72z59QnQcqo1uQzWSc=", "dev": true }, "lodash.rest": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", + "version": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", "dev": true }, "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "version": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", "dev": true }, "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "version": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", "dev": true }, "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "version": "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._basecopy": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "lodash._basetostring": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "lodash._basevalues": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "lodash.restparam": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "lodash.templatesettings": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz" } }, "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "version": "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" + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz" } }, "lodash.values": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", "dev": true, "requires": { - "lodash.keys": "2.4.1" + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" }, "dependencies": { "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" + "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" } } } }, "log-driver": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "version": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", "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": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", "dev": true, "requires": { - "chalk": "2.3.1" + "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz" }, "dependencies": { "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" } }, "chalk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "5.2.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" } }, "supports-color": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" } } } }, "log4js": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", - "integrity": "sha512-YL/qpTxYtK0iWWbuKCrevDZz5lh+OjyHHD+mICqpjnYGKdNRBvPeh/1uYjkKUemT1CSO4wwLOwphWMpKAnD9kw==", - "dev": true, - "requires": { - "amqplib": "0.5.2", - "axios": "0.15.3", - "circular-json": "0.5.1", - "date-format": "1.2.0", - "debug": "3.1.0", - "hipchat-notifier": "1.1.0", - "loggly": "1.1.1", - "mailgun-js": "0.7.15", - "nodemailer": "2.7.2", - "redis": "2.8.0", - "semver": "5.5.0", - "slack-node": "0.2.0", - "streamroller": "0.7.0" + "version": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", + "integrity": "sha1-OLt73l6cHBgb116LwSjFzQQJyvE=", + "dev": true, + "requires": { + "amqplib": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", + "axios": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "circular-json": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.1.tgz", + "date-format": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "hipchat-notifier": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "loggly": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", + "mailgun-js": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", + "nodemailer": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", + "redis": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "slack-node": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", + "streamroller": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz" }, "dependencies": { "circular-json": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.1.tgz", - "integrity": "sha512-UjgcRlTAhAkLeXmDe2wK7ktwy/tgAqxiSndTIPiFZuIPLZmzHzWMwUIe9h9m/OokypG7snxCDEuwJshGBdPvaw==", + "version": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.1.tgz", + "integrity": "sha1-uJQqCeU1hj3CGwRBepGXHh2c2R8=", "dev": true } } }, "loggly": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", + "version": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", "dev": true, "optional": true, "requires": { - "json-stringify-safe": "5.0.1", - "request": "2.75.0", - "timespan": "2.3.0" + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "request": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "timespan": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz" }, "dependencies": { "bl": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "version": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", "dev": true, "optional": true, "requires": { - "readable-stream": "2.0.6" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" } }, "form-data": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "version": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", "dev": true, "optional": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", + "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "mime-types": "2.1.17" } }, "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "version": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true, "optional": true }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true, "optional": true }, "qs": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "version": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", "dev": true, "optional": true }, "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "optional": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" } }, "request": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "version": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", "dev": true, "optional": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "bl": "1.1.2", - "caseless": "0.11.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.0.0", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "bl": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "mime-types": "2.1.17", - "node-uuid": "1.4.8", - "oauth-sign": "0.8.2", - "qs": "6.2.3", - "stringstream": "0.0.5", + "node-uuid": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3" + "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true, "optional": true @@ -10897,128 +9947,114 @@ } }, "lolex": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", - "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==", + "version": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "integrity": "sha1-hflFBCUQO/nnpgZo6iXcQydMqAc=", "dev": true }, "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "version": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", "dev": true }, "longest-streak": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "version": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha1-JCG2upOaRDu5/+v1llhaULTDji4=", "dev": true }, "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "version": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { - "js-tokens": "3.0.2" + "js-tokens": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz" } }, "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "version": "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.2" + "currently-unhandled": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz" } }, "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "yallist": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz" } }, "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "version": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", "requires": { "es5-ext": "0.10.38" } }, "magic-string": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", + "version": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", "dev": true, "requires": { - "vlq": "0.2.3" + "vlq": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz" } }, "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", + "version": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", "dev": true, "optional": true, "requires": { - "buildmail": "4.0.1", - "libmime": "3.0.0" + "buildmail": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", + "libmime": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz" } }, "mailgun-js": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", + "version": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", "integrity": "sha1-7jZqINrGTDwVwD1sGz4O15UlKrs=", "dev": true, "optional": true, "requires": { - "async": "2.1.5", - "debug": "2.2.0", - "form-data": "2.1.4", - "inflection": "1.10.0", - "is-stream": "1.1.0", - "path-proxy": "1.0.0", - "proxy-agent": "2.0.0", - "q": "1.4.1", - "tsscmp": "1.0.5" + "async": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "inflection": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", + "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "path-proxy": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "proxy-agent": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", + "q": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "tsscmp": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz" }, "dependencies": { "async": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", + "version": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", "integrity": "sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw=", "dev": true, "optional": true, "requires": { - "lodash": "4.17.5" + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "optional": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true, "optional": true }, "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "version": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", "dev": true, "optional": true @@ -11031,7 +10067,7 @@ "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", "dev": true, "requires": { - "pify": "3.0.0" + "pify": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" } }, "make-error": { @@ -11041,8 +10077,7 @@ "dev": true }, "make-error-cause": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "version": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", "dev": true, "requires": { @@ -11050,205 +10085,182 @@ } }, "make-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", + "version": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "version": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "version": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true }, "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "version": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", "dev": true }, "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "version": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "1.0.1" + "object-visit": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" } }, "markdown-escapes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", + "version": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", "integrity": "sha1-GZTfLTr0gR3lmmcUk0wrIpJzRRg=", "dev": true }, "markdown-table": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.1.tgz", + "version": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.1.tgz", "integrity": "sha1-Sz3ToTPRUYuO8NvHCb8qG0gkvIw=", "dev": true }, "match-stream": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "version": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", "dev": true, "requires": { - "buffers": "0.1.1", - "readable-stream": "1.0.34" + "buffers": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "version": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" + "hash-base": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" }, "dependencies": { "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "version": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } } } }, "mdast-util-compact": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "version": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", "dev": true, "requires": { - "unist-util-modify-children": "1.1.1", - "unist-util-visit": "1.3.0" + "unist-util-modify-children": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", + "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" } }, "mdast-util-definitions": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", - "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", + "version": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", + "integrity": "sha1-Zz9Dd8PiPT3nr3pP4iFMDiIcWsc=", "dev": true, "requires": { - "unist-util-visit": "1.3.0" + "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" } }, "mdast-util-inject": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", + "version": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", "integrity": "sha1-2wa4tYW+lZotzS+H9HK6m3VvNnU=", "dev": true, "requires": { - "mdast-util-to-string": "1.0.4" + "mdast-util-to-string": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz" } }, "mdast-util-to-hast": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.0.tgz", - "integrity": "sha512-zvEXH2AUevWfKuBqtEPNcDUPI8UC6yIVvgEgNi1v1dLnzb5Pfm+PZjnZn0FhW1WmHcrGMX059MAoqicEauzjcw==", + "version": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.0.tgz", + "integrity": "sha1-aeNn+yqesCR038AXczuP0nLVXTo=", "dev": true, "requires": { - "collapse-white-space": "1.0.3", - "detab": "2.0.1", - "mdast-util-definitions": "1.2.2", - "mdurl": "1.0.1", - "trim": "0.0.1", - "trim-lines": "1.1.0", - "unist-builder": "1.0.2", - "unist-util-generated": "1.1.1", - "unist-util-position": "3.0.0", - "unist-util-visit": "1.3.0", - "xtend": "4.0.1" + "collapse-white-space": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", + "detab": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", + "mdast-util-definitions": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", + "mdurl": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "trim": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "trim-lines": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.0.tgz", + "unist-builder": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", + "unist-util-generated": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.1.tgz", + "unist-util-position": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.0.tgz", + "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "mdast-util-to-string": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", + "version": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", "integrity": "sha1-XEVch4yTVfDB5/PotxnPWDaRrPs=", "dev": true }, "mdast-util-toc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", + "version": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", "dev": true, "requires": { - "github-slugger": "1.2.0", - "mdast-util-to-string": "1.0.4", - "unist-util-visit": "1.3.0" + "github-slugger": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", + "mdast-util-to-string": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", + "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" } }, "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "version": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "version": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz" } }, "memoizee": { @@ -11256,187 +10268,169 @@ "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", "requires": { - "d": "1.0.0", + "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "es5-ext": "0.10.38", - "es6-weak-map": "2.0.2", - "event-emitter": "0.3.5", - "is-promise": "2.1.0", - "lru-queue": "0.1.0", - "next-tick": "1.0.0", - "timers-ext": "0.1.2" + "es6-weak-map": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "event-emitter": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "is-promise": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "lru-queue": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "next-tick": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "timers-ext": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz" } }, "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "version": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { "errno": "0.1.6", - "readable-stream": "2.3.4" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "version": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" + "camelcase-keys": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "loud-rejection": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "map-obj": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "redent": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "trim-newlines": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz" }, "dependencies": { "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "version": "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": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" } }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "version": "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.4.0", - "path-type": "1.1.0" + "load-json-file": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "path-type": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" } }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "version": "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" + "find-up": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" } }, "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" } } } }, "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "version": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "version": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "2.3.4" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "method-override": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", + "version": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", "dev": true, "requires": { - "debug": "2.6.9", - "methods": "1.1.2", - "parseurl": "1.3.2", - "vary": "1.1.2" + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "methods": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "vary": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "version": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true } } }, "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "version": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "dev": true }, @@ -11446,35 +10440,33 @@ "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", + "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "braces": "2.3.0", "define-property": "1.0.0", "extend-shallow": "2.0.1", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", + "extglob": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "nanomatch": "1.2.7", - "object.pick": "1.3.0", + "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "regex-not": "1.0.0", - "snapdragon": "0.8.1", + "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", "to-regex": "3.0.1" } }, "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "version": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" + "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "brorand": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" } }, "mime": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", - "integrity": "sha512-0Qz9uF1ATtl8RKJG4VRfOymh7PyEor6NbrI/61lRfuRe4vx9SNATrvAeTj2EWVRKjEQGskrzWkJBBY5NbaVHIA==", + "version": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", + "integrity": "sha1-Fh5UGWVVHTtUn6ERQ5Hjo9Vbkjs=", "dev": true }, "mime-db": { @@ -11493,88 +10485,79 @@ } }, "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==", + "version": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", "dev": true }, "minimalistic-assert": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "version": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", "dev": true }, "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "version": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", "dev": true, "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" + "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" }, "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==", + "version": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" } } } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } }, "mkpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", + "version": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", "dev": true }, "mocha": { - "version": "1.21.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.21.5.tgz", - "integrity": "sha1-fFiwkXTfl25DSiOx6NY5hz/FKek=", + "version": "https://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", + "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", "dev": true, "requires": { "commander": "2.3.0", "debug": "2.0.0", - "diff": "1.0.8", + "diff": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", "escape-string-regexp": "1.0.2", "glob": "3.2.3", "growl": "1.8.1", "jade": "0.26.3", - "mkdirp": "0.5.0" + "mkdirp": "0.5.0", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz" }, "dependencies": { "commander": { @@ -11592,12 +10575,6 @@ "ms": "0.6.2" } }, - "diff": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz", - "integrity": "sha1-NDJ2MI7Jkbe8giZ+1VvBQR+XFmY=", - "dev": true - }, "escape-string-regexp": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", @@ -11611,7 +10588,7 @@ "dev": true, "requires": { "graceful-fs": "2.0.3", - "inherits": "2.0.3", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "minimatch": "0.2.14" } }, @@ -11634,7 +10611,7 @@ "dev": true, "requires": { "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" } }, "mkdirp": { @@ -11643,7 +10620,7 @@ "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } }, "ms": { @@ -11651,294 +10628,269 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", "dev": true + }, + "supports-color": { + "version": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz", + "integrity": "sha1-Eu4hUHCGzZjBBY2ewPSsR2t687I=", + "dev": true } } }, "mocha-nightwatch": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", + "version": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", "dev": true, "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.5", - "glob": "7.0.5", - "growl": "1.9.2", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" + "browser-stdout": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "commander": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "diff": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "growl": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "json3": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "lodash.create": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz" }, "dependencies": { "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { - "graceful-readlink": "1.0.1" + "graceful-readlink": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" } }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "glob": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", "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" + "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" } }, "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "version": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", "dev": true }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" } } } }, "mock-fs": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", + "version": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", "dev": true, "requires": { - "rewire": "2.5.2", - "semver": "5.3.0" + "rewire": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" }, "dependencies": { "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } } }, "module-deps-sortable": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", + "version": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "browser-resolve": "1.11.2", - "concat-stream": "1.5.2", - "defined": "1.0.0", - "detective": "4.7.1", - "duplexer2": "0.1.4", - "inherits": "2.0.3", - "parents": "1.0.1", - "readable-stream": "2.3.4", - "resolve": "1.5.0", - "stream-combiner2": "1.1.1", - "subarg": "1.0.0", - "through2": "2.0.3", - "xtend": "4.0.1" + "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "detective": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "stream-combiner2": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" }, "dependencies": { "concat-stream": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.0.6", - "typedarray": "0.0.6" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" }, "dependencies": { "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" } } } }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "version": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", "dev": true }, "morgan": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", + "version": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", "dev": true, "requires": { - "basic-auth": "1.0.4", - "debug": "2.2.0", - "depd": "1.0.1", - "on-finished": "2.3.0", - "on-headers": "1.0.1" + "basic-auth": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multiparty": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", + "version": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", "dev": true, "requires": { - "readable-stream": "1.1.14", - "stream-counter": "0.2.0" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "stream-counter": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "version": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, "requires": { - "duplexer2": "0.0.2" + "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz" }, "dependencies": { "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" } }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "version": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, @@ -11955,16 +10907,16 @@ "integrity": "sha512-/5ldsnyurvEw7wNpxLFgjVvBLMta43niEYOy0CJ4ntcYSbx6bugRUTQeFb4BR/WanEL1o3aQgHuVLHQaB6tOqg==", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", + "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "define-property": "1.0.0", "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", + "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "is-odd": "1.0.0", "kind-of": "5.1.0", - "object.pick": "1.3.0", + "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "regex-not": "1.0.0", - "snapdragon": "0.8.1", + "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", "to-regex": "3.0.1" }, "dependencies": { @@ -11977,70 +10929,61 @@ } }, "natives": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", - "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", + "version": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", + "integrity": "sha1-ARrM4ffL2H97prMJPWzZOSvhxXQ=", "dev": true }, "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "version": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, "ncp": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "version": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", "dev": true }, "negotiator": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", + "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", "dev": true }, "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "version": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", "dev": true }, "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "version": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nightwatch": { - "version": "0.9.19", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.19.tgz", + "version": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.19.tgz", "integrity": "sha1-S9l1cnPTC4RfBIR6mLcb6bt8Szs=", "dev": true, "requires": { - "chai-nightwatch": "0.1.1", - "ejs": "2.5.7", - "lodash.clone": "3.0.3", - "lodash.defaultsdeep": "4.3.2", - "minimatch": "3.0.3", - "mkpath": "1.0.0", - "mocha-nightwatch": "3.2.2", - "optimist": "0.6.1", - "proxy-agent": "2.0.0", - "q": "1.4.1" + "chai-nightwatch": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", + "ejs": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "lodash.clone": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", + "lodash.defaultsdeep": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "mkpath": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", + "mocha-nightwatch": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", + "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "proxy-agent": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", + "q": "https://registry.npmjs.org/q/-/q-1.4.1.tgz" }, "dependencies": { "minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" } }, "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "version": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", "dev": true } @@ -12052,89 +10995,82 @@ "integrity": "sha512-Es4hGuq3lpip5PckrB+Qpuma282M0UJANJ+jxAgI+0wWTL9X6MtNv+M385JgqsAE8hv6NvD3lv8CQtXgEnvlpQ==", "dev": true, "requires": { - "@sinonjs/formatio": "2.0.0", - "just-extend": "1.1.27", - "lolex": "2.3.2", - "path-to-regexp": "1.7.0", - "text-encoding": "0.6.4" + "@sinonjs/formatio": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "just-extend": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "lolex": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "path-to-regexp": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "text-encoding": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz" } }, "node-int64": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", + "version": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", "dev": true }, "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.2.0", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.1.7", - "events": "1.1.1", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.4", - "stream-browserify": "2.0.1", - "stream-http": "2.8.0", - "string_decoder": "1.0.3", - "timers-browserify": "2.0.6", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", - "vm-browserify": "0.0.4" + "version": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=", + "dev": true, + "requires": { + "assert": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "buffer": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz" }, "dependencies": { "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "version": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { "base64-js": "1.2.1", - "ieee754": "1.1.8", - "isarray": "1.0.0" + "ieee754": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" } }, "timers-browserify": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", - "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", + "version": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "integrity": "sha1-JB52kn2coF9NlZgZAi9bNmS2S64=", "dev": true, "requires": { - "setimmediate": "1.0.5" + "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" } }, "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "version": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "version": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" }, "dependencies": { "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } @@ -12143,963 +11079,856 @@ } }, "nodemailer": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", + "version": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", "dev": true, "optional": true, "requires": { - "libmime": "3.0.0", - "mailcomposer": "4.0.1", - "nodemailer-direct-transport": "3.3.2", - "nodemailer-shared": "1.1.0", - "nodemailer-smtp-pool": "2.8.2", - "nodemailer-smtp-transport": "2.7.2", - "socks": "1.1.9" + "libmime": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "mailcomposer": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", + "nodemailer-direct-transport": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "nodemailer-smtp-pool": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "nodemailer-smtp-transport": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "socks": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz" }, "dependencies": { "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "version": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true, "optional": true }, "socks": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", + "version": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", "dev": true, "optional": true, "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" + "ip": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "smart-buffer": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz" } } } }, "nodemailer-direct-transport": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "version": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", "dev": true, "optional": true, "requires": { - "nodemailer-shared": "1.1.0", - "smtp-connection": "2.12.0" + "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "smtp-connection": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz" } }, "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "version": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", "dev": true }, "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "version": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", "dev": true, "requires": { - "nodemailer-fetch": "1.6.0" + "nodemailer-fetch": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz" } }, "nodemailer-smtp-pool": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "version": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", "dev": true, "optional": true, "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" + "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "nodemailer-wellknown": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "smtp-connection": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz" } }, "nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "version": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", "dev": true, "optional": true, "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" + "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "nodemailer-wellknown": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "smtp-connection": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz" } }, "nodemailer-wellknown": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "version": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", "dev": true }, "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "version": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.0.9" + "abbrev": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" } }, "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", + "hosted-git-info": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "is-builtin-module": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", "validate-npm-package-license": "3.0.1" } }, "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "version": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" } }, "now-and-later": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "version": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", "dev": true, "requires": { - "once": "1.4.0" + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" } }, "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "version": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "2.0.1" + "path-key": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" } }, "null-check": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "version": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", "dev": true }, "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "version": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", "dev": true }, "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "version": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "copy-descriptor": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "version": "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" + "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" } }, "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" } }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" }, "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==", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "version": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", "dev": true }, "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "version": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", "dev": true, "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "has-symbols": "1.0.0", - "object-keys": "1.0.11" + "define-properties": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "function-bind": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "has-symbols": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "object-keys": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz" } }, "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "version": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" + "array-each": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "array-slice": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "for-own": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" } }, "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "version": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.0" + "for-own": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "make-iterator": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz" } }, "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "version": "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" + "for-own": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" }, "dependencies": { "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "version": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" } } } }, "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "version": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" } }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, "requires": { - "ee-first": "1.1.1" + "ee-first": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" } }, "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "version": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", "dev": true }, "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" } }, "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "version": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz" } }, "open": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "version": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", "dev": true }, "openurl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "version": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", "dev": true }, "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "version": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" + "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" }, "dependencies": { "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true } } }, "optimize-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", + "version": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", "dev": true, "requires": { - "acorn": "3.3.0", - "concat-stream": "1.6.0", - "estree-walker": "0.3.1", - "magic-string": "0.16.0", - "yargs": "4.8.1" + "acorn": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "estree-walker": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", + "magic-string": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", + "yargs": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz" }, "dependencies": { "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "version": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "version": "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": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" } }, "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "version": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "1.0.0" + "lcid": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" } }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" } }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "version": "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.4.0", - "path-type": "1.1.0" + "load-json-file": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "path-type": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" } }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "version": "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" + "find-up": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" } }, "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" } }, "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "version": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, "yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "version": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "dev": true, "requires": { - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "lodash.assign": "4.2.0", - "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", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" + "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "get-caller-file": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "lodash.assign": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "require-directory": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "require-main-filename": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "which-module": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "yargs-parser": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz" } }, "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "dev": true, "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "lodash.assign": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz" } } } }, "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "version": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "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", - "wordwrap": "1.0.0" + "deep-is": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "fast-levenshtein": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "levn": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "type-check": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" } }, "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "version": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", + "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "sequencify": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", "stream-consume": "0.1.0" }, "dependencies": { "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", "dev": true, "requires": { - "once": "1.3.3" + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" } }, "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" } } } }, "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", "dev": true, "requires": { - "readable-stream": "2.3.4" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "version": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "version": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", "dev": true, "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "lcid": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "mem": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz" } }, "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, "over": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "version": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", "dev": true }, "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "version": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "version": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha1-DpK2vty1nwIsE9DxlJ3ILRWQnxw=", "dev": true, "requires": { - "p-try": "1.0.0" + "p-try": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "version": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.2.0" + "p-limit": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz" } }, "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "version": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, "pac-proxy-agent": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", - "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", - "dev": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1", - "get-uri": "2.0.1", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "1.0.0", - "pac-resolver": "2.0.0", - "raw-body": "2.3.2", - "socks-proxy-agent": "2.1.1" + "version": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", + "integrity": "sha1-NKOF399h0vDsrOCIWMdF0+eR/U0=", + "dev": true, + "requires": { + "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "get-uri": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", + "http-proxy-agent": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", + "https-proxy-agent": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "pac-resolver": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", + "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "socks-proxy-agent": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz" }, "dependencies": { "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "version": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", "dev": true }, "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", "dev": true, "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.4.0" + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "setprototypeof": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz" } }, "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", "dev": true }, "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" + "bytes": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" } } } }, "pac-resolver": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", + "version": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", "dev": true, "requires": { - "co": "3.0.6", - "degenerator": "1.0.4", - "ip": "1.0.1", - "netmask": "1.0.6", - "thunkify": "2.1.2" + "co": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", + "degenerator": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "ip": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", + "netmask": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "thunkify": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz" }, "dependencies": { "co": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", + "version": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", "dev": true } } }, "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "version": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg=", "dev": true }, "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "version": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", "dev": true, "requires": { - "path-platform": "0.11.15" + "path-platform": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz" } }, "parse-asn1": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "version": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", "dev": true, "requires": { "asn1.js": "4.9.2", - "browserify-aes": "1.1.1", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.14" + "browserify-aes": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "pbkdf2": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz" } }, "parse-entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", + "version": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", "integrity": "sha1-gRLYhHExnyerrk1klksSL+ThuJA=", "dev": true, "requires": { - "character-entities": "1.2.1", - "character-entities-legacy": "1.1.1", - "character-reference-invalid": "1.1.1", - "is-alphanumerical": "1.0.1", - "is-decimal": "1.0.1", - "is-hexadecimal": "1.0.1" + "character-entities": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", + "character-entities-legacy": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", + "character-reference-invalid": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", + "is-alphanumerical": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", + "is-decimal": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", + "is-hexadecimal": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz" } }, "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "version": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" + "is-absolute": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "path-root": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz" } }, "parse-git-config": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", + "version": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", "dev": true, "requires": { - "ini": "1.3.5" + "ini": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz" } }, "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "version": "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" + "glob-base": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "is-dotfile": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" }, "dependencies": { "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "version": "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", + "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" } } } }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "version": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "1.3.1", - "json-parse-better-errors": "1.0.1" + "error-ex": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "json-parse-better-errors": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz" } }, "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "version": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, "parse-url": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", + "version": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", "dev": true, "requires": { - "is-ssh": "1.3.0", - "protocols": "1.4.6" + "is-ssh": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", + "protocols": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz" } }, "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "version": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz" } }, "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "version": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz" } }, "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true }, "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "version": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "version": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "version": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "version": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "version": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "version": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "version": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, "path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "version": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", "dev": true }, "path-proxy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "version": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", "dev": true, "optional": true, "requires": { - "inflection": "1.3.8" + "inflection": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz" }, "dependencies": { "inflection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "version": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", "dev": true, "optional": true @@ -13107,125 +11936,110 @@ } }, "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "version": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "0.1.2" + "path-root-regex": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz" } }, "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "version": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true }, "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, "requires": { - "isarray": "0.0.1" + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "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==", + "version": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", "dev": true, "requires": { - "pify": "3.0.0" + "pify": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" } }, "pause": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", + "version": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", "dev": true }, "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "version": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { - "through": "2.3.8" + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" } }, "pbkdf2": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "version": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha1-o14TxkeZsGzhUyD0WcIw5o5zut4=", "dev": true, "requires": { - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.10" + "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz" } }, "pbkdf2-compat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "version": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", "dev": true }, "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "version": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", "dev": true }, "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "version": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" } }, "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "version": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "2.1.0" + "find-up": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" } }, "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "version": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha1-dwFr2JGdCsN3/c3QMiMolTyleBw=", "dev": true, "requires": { "ansi-colors": "1.0.1", - "arr-diff": "4.0.0", - "arr-union": "3.1.0", + "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "extend-shallow": "3.0.2" }, "dependencies": { @@ -13235,7 +12049,7 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", + "assign-symbols": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "is-extendable": "1.0.1" } }, @@ -13245,221 +12059,194 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" } } } }, "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "version": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", "dev": true }, "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "version": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "version": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "version": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "version": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "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==", + "version": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", "dev": true }, "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "version": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" }, "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "version": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, "property-information": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", + "version": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE=", "dev": true }, "protocols": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", + "version": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", "dev": true }, "proxy-agent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", + "version": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", "dev": true, "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "1.0.0", - "lru-cache": "2.6.5", - "pac-proxy-agent": "1.1.0", - "socks-proxy-agent": "2.1.1" + "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "http-proxy-agent": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", + "https-proxy-agent": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", + "pac-proxy-agent": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", + "socks-proxy-agent": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "lru-cache": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", + "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", "dev": true } } }, "proxyquire": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", + "version": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", "dev": true, "requires": { - "fill-keys": "1.0.2", - "module-not-found-error": "1.0.1", - "resolve": "1.1.7" + "fill-keys": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "module-not-found-error": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" }, "dependencies": { "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true } } }, "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "version": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "version": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, "public-encrypt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "version": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "parse-asn1": "5.1.0", - "randombytes": "2.0.6" + "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "browserify-rsa": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "parse-asn1": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz" } }, "pullstream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "version": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", "dev": true, "requires": { - "over": "0.0.5", - "readable-stream": "1.0.34", - "setimmediate": "1.0.5", - "slice-stream": "1.0.0" + "over": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "slice-stream": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "version": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" + "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" } }, "pumpify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", - "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "version": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha1-gLfF334kFT0D8OesigWl0Gi9B/s=", "dev": true, "requires": { - "duplexify": "3.5.3", - "inherits": "2.0.3", - "pump": "2.0.1" + "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "pump": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz" } }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, "q": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", + "version": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", "integrity": "sha1-hQ15+MuDHZLhA7Rkg+TjXTRkAFA=", "dev": true }, @@ -13470,63 +12257,55 @@ "dev": true }, "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "version": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", "dev": true }, "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "version": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "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", + "version": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, "querystringify": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", + "version": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "dev": true }, "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "version": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", "dev": true }, "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "version": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" }, "dependencies": { "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "version": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha1-0wLFIpSFiISKjTAMkytEwkIx2oA=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, "randomfill": { @@ -13535,152 +12314,137 @@ "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", "dev": true, "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.1" + "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, "range-parser": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "version": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", "dev": true }, "raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "version": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, "requires": { - "bytes": "1.0.0", - "string_decoder": "0.10.31" + "bytes": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "dependencies": { "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "read-only-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "version": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", "dev": true, "requires": { - "readable-stream": "2.3.4" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "version": "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.4.0", - "path-type": "3.0.0" + "load-json-file": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "path-type": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz" } }, "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { - "find-up": "2.1.0", - "read-pkg": "3.0.0" + "find-up": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz" } }, "readable-stream": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha1-yUbD9H+n2Oq8C2FQ9KEvaaRXQHE=", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" } }, "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "version": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.4", - "set-immediate-shim": "1.0.1" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "set-immediate-shim": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" } }, "readline2": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "version": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", "dev": true, "requires": { - "mute-stream": "0.0.4", - "strip-ansi": "2.0.1" + "mute-stream": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz" }, "dependencies": { "ansi-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", "dev": true }, "mute-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "version": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", "dev": true }, "strip-ansi": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", "dev": true, "requires": { - "ansi-regex": "1.1.1" + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" } } } }, "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "version": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.5.0" + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" } }, "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "version": "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" + "indent-string": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "strip-indent": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz" } }, "redis": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "version": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha1-ICKI4/WMSfYHnZevehDhMDrhSwI=", "dev": true, "optional": true, "requires": { - "double-ended-queue": "2.1.0-0", + "double-ended-queue": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", "redis-commands": "1.3.1", - "redis-parser": "2.6.0" + "redis-parser": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz" } }, "redis-commands": { @@ -13691,41 +12455,36 @@ "optional": true }, "redis-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "version": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", "dev": true, "optional": true }, "regenerate": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "version": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha1-DDNtOYBVPXVcObWGrjsgqknIK38=", "dev": true }, "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + "version": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" }, "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "version": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "private": "0.1.8" + "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz" } }, "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "version": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", "dev": true, "requires": { - "is-equal-shallow": "0.1.3" + "is-equal-shallow": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" } }, "regex-not": { @@ -13738,729 +12497,633 @@ } }, "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "version": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, "requires": { - "regenerate": "1.3.3", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" + "regenerate": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "regjsgen": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "regjsparser": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz" } }, "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "version": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "version": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { - "jsesc": "0.5.0" + "jsesc": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" }, "dependencies": { "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "version": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } } }, "remark": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", - "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", + "version": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", + "integrity": "sha1-xc+o7FNcc6Z8Sw8Sv9vTpn2LL2A=", "dev": true, "requires": { - "remark-parse": "5.0.0", - "remark-stringify": "5.0.0", - "unified": "6.1.6" + "remark-parse": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "remark-stringify": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", + "unified": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz" } }, "remark-html": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", - "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", + "version": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", + "integrity": "sha1-0T3BupNS4lf86IAMQsdpDZ42kMg=", "dev": true, "requires": { - "hast-util-sanitize": "1.1.2", - "hast-util-to-html": "3.1.0", - "mdast-util-to-hast": "3.0.0", - "xtend": "4.0.1" + "hast-util-sanitize": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", + "hast-util-to-html": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", + "mdast-util-to-hast": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.0.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "remark-parse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "1.0.3", - "is-alphabetical": "1.0.1", - "is-decimal": "1.0.1", - "is-whitespace-character": "1.0.1", - "is-word-character": "1.0.1", - "markdown-escapes": "1.0.1", - "parse-entities": "1.1.1", - "repeat-string": "1.6.1", - "state-toggle": "1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "1.1.0", - "unherit": "1.1.0", - "unist-util-remove-position": "1.1.1", - "vfile-location": "2.0.2", - "xtend": "4.0.1" + "version": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha1-TAd/nkmQRNHVwT+A16mM97koXZU=", + "dev": true, + "requires": { + "collapse-white-space": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", + "is-alphabetical": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", + "is-decimal": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", + "is-whitespace-character": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", + "is-word-character": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", + "markdown-escapes": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", + "parse-entities": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "state-toggle": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", + "trim": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "trim-trailing-lines": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", + "unherit": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", + "unist-util-remove-position": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", + "vfile-location": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "remark-slug": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", - "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", + "version": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", + "integrity": "sha1-necfzcK/rjPrtKQeuDA1KIqCmYA=", "dev": true, "requires": { - "github-slugger": "1.2.0", - "mdast-util-to-string": "1.0.4", - "unist-util-visit": "1.3.0" + "github-slugger": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", + "mdast-util-to-string": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", + "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" } }, "remark-stringify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", - "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true, - "requires": { - "ccount": "1.0.2", - "is-alphanumeric": "1.0.0", - "is-decimal": "1.0.1", - "is-whitespace-character": "1.0.1", - "longest-streak": "2.0.2", - "markdown-escapes": "1.0.1", - "markdown-table": "1.1.1", - "mdast-util-compact": "1.0.1", - "parse-entities": "1.1.1", - "repeat-string": "1.6.1", - "state-toggle": "1.0.0", - "stringify-entities": "1.3.1", - "unherit": "1.1.0", - "xtend": "4.0.1" + "version": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", + "integrity": "sha1-M206TUpqM5DZM+66YujeS9KAr7o=", + "dev": true, + "requires": { + "ccount": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", + "is-alphanumeric": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "is-decimal": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", + "is-whitespace-character": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", + "longest-streak": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "markdown-escapes": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", + "markdown-table": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.1.tgz", + "mdast-util-compact": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "parse-entities": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "state-toggle": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", + "stringify-entities": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", + "unherit": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "remark-toc": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", - "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", + "version": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", + "integrity": "sha1-8eE+0RBirU0QKwLnAWi9hQFb8Sk=", "dev": true, "requires": { - "mdast-util-toc": "2.0.1", - "remark-slug": "5.0.0" + "mdast-util-toc": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", + "remark-slug": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz" } }, "remote-origin-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", + "version": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", "dev": true, "requires": { - "parse-git-config": "0.2.0" + "parse-git-config": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz" } }, "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==", + "version": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha1-wr8eN3Ug0yT2I4kuM8EMrCwlK1M=", "dev": true, "requires": { - "is-buffer": "1.1.6", - "is-utf8": "0.2.1" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" } }, "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "version": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", "dev": true, "requires": { - "remove-bom-buffer": "3.0.0", - "safe-buffer": "5.1.1", - "through2": "2.0.3" + "remove-bom-buffer": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "version": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "version": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", "dev": true }, "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "version": "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", + "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz" } }, "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", "dev": true }, "replacestream": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", + "version": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", "dev": true, "requires": { - "through": "2.3.8" + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" } }, "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "version": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", "dev": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3", - "uuid": "3.2.1" + "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz" } }, "requestretry": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", - "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", + "version": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", + "integrity": "sha1-IT7BAG7rdQ6LjOVBdig9FajVXZQ=", "dev": true, "optional": true, "requires": { - "extend": "3.0.1", - "lodash": "4.17.5", - "request": "2.79.0", - "when": "3.7.8" + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "request": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "when": "https://registry.npmjs.org/when/-/when-3.7.8.tgz" } }, "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "version": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "version": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "version": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "resolve-from": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz" } }, "requirejs": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", - "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", + "version": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", + "integrity": "sha1-YXuay7yzNlQO9JFNeQMjqNS4YbA=", "dev": true }, "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "version": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "version": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz" } }, "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "version": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" + "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "global-modules": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz" } }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "version": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", "dev": true }, "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "version": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", "dev": true, "requires": { - "value-or-function": "3.0.0" + "value-or-function": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz" } }, "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "version": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "response-time": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", + "version": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", "dev": true, "requires": { - "depd": "1.1.2", - "on-headers": "1.0.1" + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" }, "dependencies": { "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "version": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true } } }, "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "version": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" + "onetime": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz" } }, "rewire": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", + "version": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", "dev": true }, "rgb2hex": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", + "version": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", "integrity": "sha1-zNVfhgrgxcTqN1BLlY5ELY0SMls=", "dev": true }, "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "version": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "0.1.4" + "align-text": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz" } }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" } }, "ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "version": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", "dev": true, "requires": { - "hash-base": "2.0.2", - "inherits": "2.0.3" + "hash-base": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" } }, "rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "version": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", "dev": true }, "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "version": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "2.1.0" + "is-promise": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz" } }, "rx": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", + "version": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", "dev": true }, "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "version": "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", + "version": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "requires": { - "rx-lite": "4.0.8" + "rx-lite": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz" } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" }, "safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "version": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", "dev": true }, "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "version": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha1-jR2TUOJWItow3j5EumkrUiGrfFA=", "dev": true }, - "sauce-connect-launcher": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/sauce-connect-launcher/-/sauce-connect-launcher-1.2.3.tgz", - "integrity": "sha1-0vkxrXro/avxlopEDnsgQXrKf4Y=", + "schema-utils": { + "version": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", "dev": true, "requires": { - "adm-zip": "0.4.7", - "async": "2.6.0", - "https-proxy-agent": "1.0.0", - "lodash": "4.17.5", - "rimraf": "2.6.2" + "ajv": "5.5.2" }, "dependencies": { - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "lodash": "4.17.5" + "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" } } } }, - "saucelabs": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.4.0.tgz", - "integrity": "sha1-uTSpr52ih0s/QKrh/N5QpEZvXzg=", - "dev": true, - "requires": { - "https-proxy-agent": "1.0.0" - } - }, - "schema-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true, - "requires": { - "ajv": "5.5.2" - } - }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=", "dev": true }, "send": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "version": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", "dev": true, "requires": { - "debug": "2.2.0", - "depd": "1.1.2", - "destroy": "1.0.4", - "escape-html": "1.0.3", - "etag": "1.7.0", - "fresh": "0.3.0", - "http-errors": "1.3.1", - "mime": "1.3.4", - "ms": "0.7.1", - "on-finished": "2.3.0", - "range-parser": "1.0.3", - "statuses": "1.2.1" + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "depd": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "destroy": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "etag": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "mime": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "version": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "version": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", "dev": true }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "statuses": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "version": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", "dev": true } } }, "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "version": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", "dev": true }, "serve-favicon": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "version": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", "dev": true, "requires": { - "etag": "1.7.0", - "fresh": "0.3.0", - "ms": "0.7.2", - "parseurl": "1.3.2" + "etag": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz" }, "dependencies": { "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", "dev": true } } }, "serve-index": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", + "version": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", "dev": true, "requires": { - "accepts": "1.2.13", - "batch": "0.5.3", - "debug": "2.2.0", - "escape-html": "1.0.3", - "http-errors": "1.3.1", + "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "batch": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "mime-types": "2.1.17", - "parseurl": "1.3.2" + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz" }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } }, "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "serve-static": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "version": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", "dev": true, "requires": { - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.13.2" + "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "send": "https://registry.npmjs.org/send/-/send-0.13.2.tgz" } }, "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-getter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "version": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", "dev": true, "requires": { - "to-object-path": "0.3.0" + "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" } }, "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "version": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", "dev": true }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", "dev": true, "requires": { "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" + "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "split-string": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" } }, "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "version": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "version": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", "dev": true }, "sha.js": { - "version": "2.4.10", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", - "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", + "version": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", + "integrity": "sha1-sf3lzX0RpWJmOKB8YEq5Cc+jH5s=", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, "shasum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "version": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", "dev": true, "requires": { - "json-stable-stringify": "0.0.1", - "sha.js": "2.4.10" + "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz" }, "dependencies": { "json-stable-stringify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" } } } }, "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "version": "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": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" } }, "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "version": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "version": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", "dev": true, "requires": { - "array-filter": "0.0.1", - "array-map": "0.0.0", - "array-reduce": "0.0.0", - "jsonify": "0.0.0" + "array-filter": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "array-map": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "array-reduce": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" } }, "shelljs": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", - "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", + "version": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", + "integrity": "sha1-cp4DjEE6IlTEB4uV7UbgOXFUqfE=", "dev": true, "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "rechoir": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" } }, "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "version": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", "dev": true }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, @@ -14470,344 +13133,309 @@ "integrity": "sha512-pmf05hFgEZUS52AGJcsVjOjqAyJW2yo14cOwVYvzCyw7+inv06YXkLyW75WG6X6p951lzkoKh51L2sNbR9CDvw==", "dev": true, "requires": { - "@sinonjs/formatio": "2.0.0", - "diff": "3.4.0", - "lodash.get": "4.4.2", - "lolex": "2.3.2", + "@sinonjs/formatio": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "diff": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "lodash.get": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "lolex": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", "nise": "1.2.5", - "supports-color": "5.2.0", - "type-detect": "4.0.8" + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" }, "dependencies": { "diff": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", - "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "version": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha1-sdhVB9rzlkgo3lSzfQ1zumfdpWw=", "dev": true }, "supports-color": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" } }, "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==", + "version": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=", "dev": true } } }, "slack-node": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", + "version": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", "dev": true, "optional": true, "requires": { - "requestretry": "1.13.0" + "requestretry": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz" } }, "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "version": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true }, "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "version": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0" + "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" }, "dependencies": { "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", + "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true } } }, "slice-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "version": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", "dev": true, "requires": { - "readable-stream": "1.0.34" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "version": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", "dev": true }, "smtp-connection": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "version": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", "dev": true, "requires": { - "httpntlm": "1.6.1", - "nodemailer-shared": "1.1.0" + "httpntlm": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz" } }, "snapdragon": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", + "version": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", "dev": true, "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", + "base": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.1", - "use": "2.0.2" + "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "source-map-resolve": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "use": "https://registry.npmjs.org/use/-/use-2.0.2.tgz" }, "dependencies": { "atob": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "version": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "version": "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" + "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" } }, "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" } }, "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": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "version": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha1-etD1k/IoFZjoVN+A8ZquS5LXoRo=", "dev": true, "requires": { - "atob": "2.0.3", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" + "atob": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "decode-uri-component": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "resolve-url": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "source-map-url": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "urix": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" } }, "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "version": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true } } }, "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==", + "version": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "snapdragon-util": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" } }, "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "version": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" } }, "socket.io": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "version": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", "dev": true, "requires": { - "debug": "2.6.9", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "engine.io": "3.1.4", - "socket.io-adapter": "1.1.1", - "socket.io-client": "2.0.4", + "socket.io-adapter": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "socket.io-client": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", "socket.io-parser": "3.1.2" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } }, "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "version": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", "dev": true }, "socket.io-client": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "version": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", "dev": true, "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "2.6.9", + "backo2": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "base64-arraybuffer": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "component-bind": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "engine.io-client": "3.1.4", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", + "has-cors": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "indexof": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "object-component": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "parseqs": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "parseuri": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "socket.io-parser": "3.1.2", - "to-array": "0.1.4" + "to-array": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } } } @@ -14818,9 +13446,9 @@ "integrity": "sha1-28IoIVH8T6675Aru3Ady66YZ9/I=", "dev": true, "requires": { - "component-emitter": "1.2.1", + "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "debug": "2.6.9", - "has-binary2": "1.0.2", + "has-binary2": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", "isarray": "2.0.1" }, "dependencies": { @@ -14830,7 +13458,7 @@ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "isarray": { @@ -14842,90 +13470,79 @@ } }, "socks": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", + "version": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", "dev": true, "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" + "ip": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "smart-buffer": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz" }, "dependencies": { "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "version": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true } } }, "socks-proxy-agent": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", - "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", + "version": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", + "integrity": "sha1-huuwcZMlhjeHDhO3vZnybGY989M=", "dev": true, "requires": { - "agent-base": "2.1.1", - "extend": "3.0.1", - "socks": "1.1.10" + "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "socks": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz" } }, "source-list-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "version": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha1-qqR0A/eyRakvvJfqCPJQ1gh+0IU=", "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==" + "version": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" }, "source-map-resolve": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "version": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", "requires": { - "atob": "1.1.3", - "resolve-url": "0.2.1", - "source-map-url": "0.3.0", - "urix": "0.1.0" + "atob": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "resolve-url": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "source-map-url": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "urix": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" } }, "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==", + "version": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "source-map-url": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "version": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=" }, "space-separated-tokens": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz", + "version": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz", "integrity": "sha1-lpW5355lrsGBHUw/nOUlILwvfk0=", "dev": true, "requires": { - "trim": "0.0.1" + "trim": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" } }, "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "version": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", "dev": true }, @@ -14951,18 +13568,16 @@ "dev": true }, "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "version": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { - "through": "2.3.8" + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" } }, "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==", + "version": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { "extend-shallow": "3.0.2" @@ -14974,7 +13589,7 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", + "assign-symbols": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "is-extendable": "1.0.1" } }, @@ -14984,196 +13599,176 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" } } } }, "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", "dev": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "bcrypt-pbkdf": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "dashdash": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "ecc-jsbn": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "getpass": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" }, "dependencies": { "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "state-toggle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", + "version": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", "integrity": "sha1-0g+aYWu08MO5i5GSLSW2QKorxCU=", "dev": true }, "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "version": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" + "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "object-copy": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" }, "dependencies": { "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "version": "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" + "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" } }, "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" } }, "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": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } }, "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "version": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=", "dev": true }, "stream-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", + "version": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", "dev": true, "requires": { - "readable-stream": "2.1.5" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz" }, "dependencies": { "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "version": "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", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", "dev": true, "requires": { - "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" + "buffer-shims": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "version": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.4" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "version": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { - "duplexer": "0.1.1" + "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" } }, "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "version": "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.4" + "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "stream-consume": { @@ -15183,253 +13778,225 @@ "dev": true }, "stream-counter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "version": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "stream-http": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", - "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", + "version": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha1-/YZUbaybHJGv+PxdKHuY+vtBvBA=", "dev": true, "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.4", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" + "builtin-status-codes": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "to-arraybuffer": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "version": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, "stream-splicer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "version": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.4" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "version": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", "dev": true, "requires": { - "date-format": "1.2.0", - "debug": "3.1.0", - "mkdirp": "0.5.1", - "readable-stream": "2.3.4" + "date-format": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "string-replace-webpack-plugin": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", + "version": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", "dev": true, "requires": { - "async": "0.2.10", - "css-loader": "0.9.1", - "file-loader": "0.8.5", - "loader-utils": "0.2.17", - "style-loader": "0.8.3" + "async": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "css-loader": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", + "file-loader": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", + "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "style-loader": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz" }, "dependencies": { "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "version": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true }, "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "version": "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" + "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } } } }, "string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "version": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "version": "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" + "code-point-at": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, "stringify-entities": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", + "version": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", "integrity": "sha1-sVDsLXKsTBtfMktR+2soyc3/BYw=", "dev": true, "requires": { - "character-entities-html4": "1.1.1", - "character-entities-legacy": "1.1.1", - "is-alphanumerical": "1.0.1", - "is-hexadecimal": "1.0.1" + "character-entities-html4": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.1.tgz", + "character-entities-legacy": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", + "is-alphanumerical": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", + "is-hexadecimal": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz" } }, "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", "dev": true }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" } }, "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "version": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" }, "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "version": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "version": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "4.0.1" + "get-stdin": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" } }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, "style-loader": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", + "version": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", "dev": true, "optional": true, "requires": { - "loader-utils": "0.2.17" + "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz" }, "dependencies": { "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, "optional": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" + "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } } } }, "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "version": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, "syntax-error": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "version": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha1-LZ1P9cBkrLcRWUo+O5UFStUdkHw=", "dev": true, "requires": { - "acorn-node": "1.3.0" + "acorn-node": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.3.0.tgz" } }, "table": { @@ -15438,14 +14005,31 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "5.5.2", + "ajv": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "ajv-keywords": "2.1.1", - "chalk": "2.3.1", - "lodash": "4.17.5", - "slice-ansi": "1.0.0", - "string-width": "2.1.1" + "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "slice-ansi": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" }, "dependencies": { + "ajv": { + "version": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" + } + }, + "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 + }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -15453,23 +14037,21 @@ "dev": true }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" } }, "chalk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "5.2.0" + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" } }, "is-fullwidth-code-point": { @@ -15479,9 +14061,8 @@ "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", @@ -15498,157 +14079,138 @@ } }, "supports-color": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" } } } }, "tapable": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "version": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", "dev": true }, "tar-stream": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", + "version": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", "dev": true, "requires": { - "bl": "0.9.5", - "end-of-stream": "1.4.1", - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "bl": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "ternary-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "version": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", "dev": true, "requires": { - "duplexify": "3.5.3", - "fork-stream": "0.0.4", - "merge-stream": "1.0.1", - "through2": "2.0.3" + "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "fork-stream": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "merge-stream": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "version": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", "dev": true }, "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "version": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "textextensions": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", + "version": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", "dev": true }, "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "version": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "version": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", "dev": true, "requires": { - "through2": "2.0.3", - "xtend": "4.0.1" + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "version": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", "dev": true }, "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "version": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" } }, "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "version": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, "timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "version": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", "dev": true, "requires": { - "process": "0.11.10" + "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz" } }, "timers-ext": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", + "version": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", "requires": { "es5-ext": "0.10.38", - "next-tick": "1.0.0" + "next-tick": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz" } }, "timespan": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "version": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", "dev": true, "optional": true @@ -15659,12 +14221,12 @@ "integrity": "sha512-f4X68a6KHcCx/XJcZUKAa92APjY9EHxuGOzRFmPRjf+fOp1E7fi4dGJaHMxvRBxwZrHrIvn/AwkFaDS7O1WZDQ==", "dev": true, "requires": { - "body": "5.1.0", + "body": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "debug": "2.6.9", - "faye-websocket": "0.10.0", - "livereload-js": "2.3.0", - "object-assign": "4.1.1", - "qs": "6.5.1" + "faye-websocket": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "livereload-js": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz" }, "dependencies": { "debug": { @@ -15673,70 +14235,62 @@ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", "dev": true } } }, "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "version": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" } }, "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "version": "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" + "is-absolute": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "is-negated-glob": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz" } }, "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "version": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "version": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "version": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } @@ -15776,7 +14330,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } @@ -15796,7 +14350,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } @@ -15821,22 +14375,20 @@ } }, "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "version": "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" + "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" } }, "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "version": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", "dev": true, "requires": { - "through2": "2.0.3" + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, "tough-cookie": { @@ -15845,88 +14397,75 @@ "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", "dev": true, "requires": { - "punycode": "1.4.1" + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" } }, "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "version": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", "dev": true }, "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "version": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", "dev": true }, "trim-lines": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.0.tgz", + "version": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.0.tgz", "integrity": "sha1-mSbQPt4Tuhj31CIiYx+wTHn/Jv4=", "dev": true }, "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "version": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, "trim-trailing-lines": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", + "version": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", "integrity": "sha1-eu+7eAjfnWafbaLkOMrIxGradoQ=", "dev": true }, "trough": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", + "version": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", "integrity": "sha1-qf2LA5Swro//guBjOgo2zK1bX4Y=", "dev": true }, "tsscmp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "version": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", "dev": true }, "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "version": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha1-PwUlHuF5BN/QZ3VGZw25ZRaCuBE=", "dev": true }, "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", "dev": true }, "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true, "optional": true }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "version": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" } }, "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "version": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, @@ -15936,131 +14475,115 @@ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", "dev": true, "requires": { - "media-typer": "0.3.0", + "media-typer": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "mime-types": "2.1.17" } }, "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "version": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "version": "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" + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "uglify-to-browserify": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz" }, "dependencies": { "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "version": "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", + "version": "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" + "center-align": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "right-align": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true }, "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "version": "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", + "version": "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" + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "cliui": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" } } } }, "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "version": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "dev": true }, "uglifyjs-webpack-plugin": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "version": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, "requires": { - "source-map": "0.5.7", - "uglify-js": "2.8.29", - "webpack-sources": "1.1.0" + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "webpack-sources": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "uid-safe": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "version": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", "dev": true, "requires": { - "random-bytes": "1.0.0" + "random-bytes": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" } }, "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "version": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", "dev": true }, "umd": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", + "version": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", "dev": true }, "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "version": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "version": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", "dev": true }, @@ -16071,207 +14594,185 @@ "dev": true }, "unherit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", + "version": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", "integrity": "sha1-a5qu379z3xdWrZ4xbdmBiFhAzX0=", "dev": true, "requires": { - "inherits": "2.0.3", - "xtend": "4.0.1" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, "unified": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", - "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", + "version": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", + "integrity": "sha1-Xqf4B6CJjx+Kze7+XyX6oBDMQrE=", "dev": true, "requires": { - "bail": "1.0.2", - "extend": "3.0.1", - "is-plain-obj": "1.1.0", - "trough": "1.0.1", - "vfile": "2.3.0", - "x-is-function": "1.0.4", - "x-is-string": "0.1.0" + "bail": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "is-plain-obj": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "trough": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", + "vfile": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "x-is-function": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", + "x-is-string": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz" } }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "version": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" + "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "set-value": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz" }, "dependencies": { "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "version": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" + "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" } } } }, "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", "dev": true, "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" + "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "through2-filter": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz" } }, "unist-builder": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", + "version": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", "dev": true, "requires": { - "object-assign": "4.1.1" + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } }, "unist-util-generated": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.1.tgz", + "version": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.1.tgz", "integrity": "sha1-mfFseJWayFTe58YVwpGSTIv03n8=", "dev": true }, "unist-util-is": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", + "version": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", "integrity": "sha1-DDEmKeP5YMZukx6BLT2A53AQlHs=", "dev": true }, "unist-util-modify-children": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", + "version": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", "integrity": "sha1-ZtfmpEnm9nIguXarPLi166w55R0=", "dev": true, "requires": { - "array-iterate": "1.1.1" + "array-iterate": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.1.tgz" } }, "unist-util-position": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.0.tgz", + "version": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.0.tgz", "integrity": "sha1-5uHgPu64HF4a/lU+jUrfvXwNj4I=", "dev": true }, "unist-util-remove-position": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", + "version": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", "integrity": "sha1-WoXBVV/BugwQG4ZwfRXlD6TIcbs=", "dev": true, "requires": { - "unist-util-visit": "1.3.0" + "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" } }, "unist-util-stringify-position": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", + "version": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", "integrity": "sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=", "dev": true }, "unist-util-visit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", - "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", + "version": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", + "integrity": "sha1-Qcp8gpgf0c5sdiqsOX/CTjVxFEQ=", "dev": true, "requires": { - "unist-util-is": "2.1.1" + "unist-util-is": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz" } }, "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "version": "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.1" + "has-value": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" }, "dependencies": { "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "version": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" + "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "has-values": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" }, "dependencies": { "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "version": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { - "isarray": "1.0.0" + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" } } } }, "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "version": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true } } }, "unzip": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", + "version": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", "dev": true, "requires": { - "binary": "0.3.0", - "fstream": "0.1.31", - "match-stream": "0.0.2", - "pullstream": "0.4.1", - "readable-stream": "1.0.34", - "setimmediate": "1.0.5" + "binary": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "fstream": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "match-stream": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "pullstream": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -16296,173 +14797,153 @@ } }, "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "version": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "version": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", "dev": true, "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" }, "dependencies": { "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } } }, "url-parse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", + "version": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", + "integrity": "sha1-OhnoqqbQI93SfcxEy0/I9/7COYY=", "dev": true, "requires": { - "querystringify": "1.0.0", - "requires-port": "1.0.0" + "querystringify": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "requires-port": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" }, "dependencies": { "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "version": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", "dev": true } } }, "use": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", + "version": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", "dev": true, "requires": { - "define-property": "0.2.5", - "isobject": "3.0.1", - "lazy-cache": "2.0.2" + "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "lazy-cache": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz" }, "dependencies": { "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "version": "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" + "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" } }, "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "version": "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" + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } } } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" } }, "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": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } }, "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "version": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", "dev": true }, "useragent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "version": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { - "lru-cache": "4.1.1", - "tmp": "0.0.33" + "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "tmp": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" } }, "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "version": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { - "inherits": "2.0.1" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "dependencies": { "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", "dev": true } } }, "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", "dev": true }, "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "version": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ=", "dev": true }, "uws": { @@ -16473,12 +14954,11 @@ "optional": true }, "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "version": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "user-home": "1.1.1" + "user-home": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" } }, "validate-npm-package-license": { @@ -16492,224 +14972,190 @@ } }, "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "version": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, - "vargs": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/vargs/-/vargs-0.1.0.tgz", - "integrity": "sha1-a2GE2mUgzDIEzhtAfKwm2SYJ6/8=", - "dev": true - }, "vary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", + "version": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", "dev": true }, "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "version": "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" + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" }, "dependencies": { "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "vfile": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "version": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha1-5i2OcrIOg8MkvGxnJ47ickiL+Eo=", "dev": true, "requires": { - "is-buffer": "1.1.6", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "1.1.1", - "vfile-message": "1.0.0" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "unist-util-stringify-position": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", + "vfile-message": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz" } }, "vfile-location": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", + "version": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", "integrity": "sha1-02dcWch3SY5JK0dW/2Xkrxp1IlU=", "dev": true }, "vfile-message": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", - "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", + "version": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", + "integrity": "sha1-pq2wR06kAPol2Snx1nOr6moX41k=", "dev": true, "requires": { - "unist-util-stringify-position": "1.1.1" + "unist-util-stringify-position": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz" } }, "vfile-reporter": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", + "version": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, "requires": { - "repeat-string": "1.6.1", - "string-width": "1.0.2", - "supports-color": "4.5.0", - "unist-util-stringify-position": "1.1.1", - "vfile-statistics": "1.1.0" + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "unist-util-stringify-position": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", + "vfile-statistics": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.0.tgz" }, "dependencies": { "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "version": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz" } } } }, "vfile-sort": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.0.tgz", + "version": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.0.tgz", "integrity": "sha1-SVAcnou+Wt/y6bOnZx7hseIMUhA=", "dev": true }, "vfile-statistics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.0.tgz", + "version": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.0.tgz", "integrity": "sha1-AhBMYP3u0dEbH3OtZTMLdjSz2JU=", "dev": true }, "vhost": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", + "version": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", "dev": true }, "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "version": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "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.1.0", - "replace-ext": "1.0.0" + "clone": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "clone-buffer": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "cloneable-readable": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz" } }, "vinyl-fs": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", - "integrity": "sha512-AUSFda1OukBwuLPBTbyuO4IRWgfXmqC4UTW0f8xrCa8Hkv9oyIU+NSqBlgfOLZRoUt7cHdo75hKQghCywpIyIw==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "1.0.0", - "glob-stream": "6.1.0", - "graceful-fs": "4.1.11", - "is-valid-glob": "1.0.0", - "lazystream": "1.0.0", - "lead": "1.0.0", - "object.assign": "4.1.0", - "pumpify": "1.4.0", - "readable-stream": "2.3.4", - "remove-bom-buffer": "3.0.0", - "remove-bom-stream": "1.2.0", - "resolve-options": "1.1.0", - "through2": "2.0.3", - "to-through": "2.0.0", - "value-or-function": "3.0.0", - "vinyl": "2.1.0", - "vinyl-sourcemap": "1.1.0" + "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", + "integrity": "sha1-G4YliEQ4P1dYH8qsCB/gnvbW11I=", + "dev": true, + "requires": { + "fs-mkdirp-stream": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "is-valid-glob": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "lazystream": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "lead": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "object.assign": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "pumpify": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "remove-bom-buffer": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "remove-bom-stream": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "resolve-options": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "to-through": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "value-or-function": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "vinyl-sourcemap": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz" } }, "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "version": "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.1", - "graceful-fs": "4.1.11", - "normalize-path": "2.1.1", - "now-and-later": "2.0.0", - "remove-bom-buffer": "3.0.0", - "vinyl": "2.1.0" + "append-buffer": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "now-and-later": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "remove-bom-buffer": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz" } }, "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "version": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "version": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha1-jz5DKM9jsVQMDWfhsneDhviXWyY=", "dev": true }, "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "version": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", "dev": true, "requires": { - "indexof": "0.0.1" + "indexof": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" } }, "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "version": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, "walk": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz", + "version": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz", "integrity": "sha1-MbTbZnjyrgHDnqn7hyWpAx5Vins=", "dev": true, "requires": { - "foreachasync": "3.0.0" + "foreachasync": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz" } }, - "walkdir": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", - "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=", - "dev": true - }, "watchpack": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", @@ -16718,7 +15164,7 @@ "requires": { "async": "2.6.0", "chokidar": "1.7.0", - "graceful-fs": "4.1.11" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" }, "dependencies": { "anymatch": { @@ -16728,7 +15174,7 @@ "dev": true, "requires": { "micromatch": "2.3.11", - "normalize-path": "2.1.1" + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" } }, "arr-diff": { @@ -16737,7 +15183,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" } }, "array-unique": { @@ -16752,7 +15198,7 @@ "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "braces": { @@ -16761,9 +15207,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" } }, "chokidar": { @@ -16773,14 +15219,14 @@ "dev": true, "requires": { "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.1.3", + "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "fsevents": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" } }, "expand-brackets": { @@ -16789,7 +15235,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" } }, "extglob": { @@ -16831,7 +15277,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } }, "micromatch": { @@ -16845,435 +15291,278 @@ "braces": "1.8.5", "expand-brackets": "0.1.5", "extglob": "0.3.2", - "filename-regex": "2.0.1", + "filename-regex": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "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" - } - } - } - }, - "wd": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/wd/-/wd-1.5.0.tgz", - "integrity": "sha512-e/KpzTlhtSG3Ek0AcRz4G6PhxGsc53Nro+GkI1er9p05tWQ7W9dpGZR5SqQzGUqvbaqJCThDSAGaY7LHgi6MiA==", - "dev": true, - "requires": { - "archiver": "1.3.0", - "async": "2.0.1", - "lodash": "4.16.2", - "mkdirp": "0.5.1", - "q": "1.4.1", - "request": "2.79.0", - "underscore.string": "3.3.4", - "vargs": "0.1.0" - }, - "dependencies": { - "archiver": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz", - "integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=", - "dev": true, - "requires": { - "archiver-utils": "1.3.0", - "async": "2.0.1", - "buffer-crc32": "0.2.13", - "glob": "7.1.2", - "lodash": "4.16.2", - "readable-stream": "2.3.4", - "tar-stream": "1.5.5", - "walkdir": "0.0.11", - "zip-stream": "1.2.0" - } - }, - "async": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.0.1.tgz", - "integrity": "sha1-twnMAoCpw28J9FNr6CPIOKkEniU=", - "dev": true, - "requires": { - "lodash": "4.16.2" - } - }, - "bl": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", - "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", - "dev": true, - "requires": { - "readable-stream": "2.3.4" - } - }, - "compress-commons": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", - "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13", - "crc32-stream": "2.0.0", - "normalize-path": "2.1.1", - "readable-stream": "2.3.4" - } - }, - "crc": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.5.0.tgz", - "integrity": "sha1-mLi6fUiWZbo5efWbITgTdBAaGWQ=", - "dev": true - }, - "crc32-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", - "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", - "dev": true, - "requires": { - "crc": "3.5.0", - "readable-stream": "2.3.4" - } - }, - "lodash": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.2.tgz", - "integrity": "sha1-PmJtuCcEimmSgaihJSJjJs/A5lI=", - "dev": true - }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", - "dev": true - }, - "tar-stream": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", - "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", - "dev": true, - "requires": { - "bl": "1.2.1", - "end-of-stream": "1.4.1", - "readable-stream": "2.3.4", - "xtend": "4.0.1" - } - }, - "underscore.string": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", - "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=", - "dev": true, - "requires": { - "sprintf-js": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "zip-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", - "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", - "dev": true, - "requires": { - "archiver-utils": "1.3.0", - "compress-commons": "1.2.2", - "lodash": "4.16.2", - "readable-stream": "2.3.4" + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" } } } }, "webdriverio": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz", + "version": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz", "integrity": "sha1-2dTTwxNm8FPhCvZEsOqtXoc6t7U=", "dev": true, "requires": { - "archiver": "0.14.4", - "array.from": "0.2.0", - "co": "4.6.0", - "css-parse": "2.0.0", - "css-value": "0.0.1", - "deepmerge": "0.2.10", - "ejs": "2.5.7", - "glob": "5.0.15", - "inquirer": "0.8.5", - "is-generator": "1.0.3", - "optimist": "0.6.1", - "q": "1.3.0", - "request": "2.49.0", - "rgb2hex": "0.1.0", - "supports-color": "1.3.1", - "url": "0.10.3", - "wgxpath": "1.0.0" + "archiver": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", + "array.from": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", + "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "css-parse": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "css-value": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "deepmerge": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", + "ejs": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "inquirer": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", + "is-generator": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", + "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "q": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", + "request": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", + "rgb2hex": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", + "url": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "wgxpath": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz" }, "dependencies": { "ansi-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", "dev": true }, "asn1": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "version": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", "dev": true }, "assert-plus": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", "dev": true }, "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "version": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true }, "aws-sign2": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", "dev": true }, "boom": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "version": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", "dev": true, "requires": { - "hoek": "0.9.1" + "hoek": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" } }, "caseless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", + "version": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", "dev": true }, "cli-width": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", + "version": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", "dev": true }, "combined-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", "dev": true, "requires": { - "delayed-stream": "0.0.5" + "delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } }, "cryptiles": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", "dev": true, "requires": { - "boom": "0.4.2" + "boom": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" } }, "delayed-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", "dev": true }, "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "version": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } }, "forever-agent": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", "dev": true }, "form-data": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "version": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", "dev": true, "requires": { - "async": "0.9.2", - "combined-stream": "0.0.7", - "mime": "1.2.11" + "async": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "mime": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" } }, "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" } }, "hawk": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "version": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", "dev": true, "requires": { - "boom": "0.4.2", - "cryptiles": "0.2.2", - "hoek": "0.9.1", - "sntp": "0.2.4" + "boom": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "hoek": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "sntp": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } }, "hoek": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "version": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", "dev": true }, "http-signature": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "version": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", "dev": true, "requires": { - "asn1": "0.1.11", - "assert-plus": "0.1.5", - "ctype": "0.5.3" + "asn1": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "ctype": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" } }, "inquirer": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", + "version": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", "dev": true, "requires": { - "ansi-regex": "1.1.1", - "chalk": "1.1.3", - "cli-width": "1.1.1", - "figures": "1.7.0", - "lodash": "3.10.1", - "readline2": "0.1.1", - "rx": "2.5.3", - "through": "2.3.8" + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "cli-width": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", + "figures": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "readline2": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "rx": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" } }, "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true }, "mime": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "version": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", "dev": true }, "mime-types": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "version": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", "dev": true }, "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "version": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, "oauth-sign": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", + "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", "dev": true }, "qs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "version": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", "dev": true }, "request": { - "version": "2.49.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", + "version": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", "integrity": "sha1-DU9jSNwzSAWbVT5Ntg/SR43mYqc=", "dev": true, "requires": { - "aws-sign2": "0.5.0", - "bl": "0.9.5", - "caseless": "0.8.0", - "combined-stream": "0.0.7", - "forever-agent": "0.5.2", - "form-data": "0.1.4", - "hawk": "1.1.1", - "http-signature": "0.10.1", - "json-stringify-safe": "5.0.1", - "mime-types": "1.0.2", - "node-uuid": "1.4.8", - "oauth-sign": "0.5.0", - "qs": "2.3.3", - "stringstream": "0.0.5", + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "bl": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "node-uuid": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3" + "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" } }, "sntp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "version": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", "dev": true, "requires": { - "hoek": "0.9.1" + "hoek": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" } }, "supports-color": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", "dev": true } } }, "webpack": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", - "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", + "version": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", + "integrity": "sha1-d9pFGx17SxF62vQaGpO1dC8k2JQ=", "dev": true, "requires": { "acorn": "5.4.1", - "acorn-dynamic-import": "2.0.2", + "acorn-dynamic-import": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", "ajv": "6.1.1", "ajv-keywords": "3.1.0", - "async": "2.6.0", - "enhanced-resolve": "3.4.1", - "escope": "3.6.0", - "interpret": "1.1.0", - "json-loader": "0.5.7", - "json5": "0.5.1", - "loader-runner": "2.3.0", - "loader-utils": "1.1.0", - "memory-fs": "0.4.1", - "mkdirp": "0.5.1", - "node-libs-browser": "2.1.0", - "source-map": "0.5.7", - "supports-color": "4.5.0", - "tapable": "0.2.8", - "uglifyjs-webpack-plugin": "0.4.6", + "async": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "enhanced-resolve": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "escope": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "json-loader": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "loader-runner": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "node-libs-browser": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "uglifyjs-webpack-plugin": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "watchpack": "1.4.0", - "webpack-sources": "1.1.0", - "yargs": "8.0.2" + "webpack-sources": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "yargs": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz" }, "dependencies": { "ajv": { @@ -17283,8 +15572,8 @@ "dev": true, "requires": { "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" } }, "ajv-keywords": { @@ -17294,903 +15583,801 @@ "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "version": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "version": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "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", + "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "version": "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.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" } }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" } }, "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "version": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "pify": "2.3.0" + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" } }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "version": "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.4.0", - "path-type": "2.0.0" + "load-json-file": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "path-type": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz" } }, "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "version": "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" + "find-up": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz" } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "version": "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" } }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz" } }, "yargs": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "version": "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.2", - "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.1", - "yargs-parser": "7.0.0" + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "get-caller-file": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "require-directory": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "require-main-filename": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "which-module": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "yargs-parser": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz" } } } }, "webpack-core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", + "version": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, "requires": { - "source-list-map": "0.1.8", - "source-map": "0.4.4" + "source-list-map": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz" }, "dependencies": { "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", + "version": "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", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" } } } }, "webpack-dev-middleware": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", - "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "version": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha1-+PwRIM47T8VoDO7LQ9d3lmshEF4=", "dev": true, "requires": { - "memory-fs": "0.4.1", - "mime": "1.6.0", - "path-is-absolute": "1.0.1", - "range-parser": "1.0.3", - "time-stamp": "2.0.0" + "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "mime": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "time-stamp": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz" }, "dependencies": { "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "version": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", "dev": true }, "time-stamp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", + "version": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", "dev": true } } }, "webpack-sources": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "version": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha1-oQHrrlnWUHNU1x2AE5UKOot6WlQ=", "dev": true, "requires": { - "source-list-map": "2.0.0", - "source-map": "0.6.1" + "source-list-map": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" } }, "webpack-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "version": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", "dev": true, "requires": { - "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" + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "lodash.clone": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "lodash.some": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "webpack": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz" }, "dependencies": { "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "version": "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==", + "version": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", "dev": true, "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" + "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" } }, "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" } }, "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "version": "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.2" + "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" } }, "browserify-aes": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "version": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" } }, "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", "dev": true, "requires": { - "pako": "0.2.9" + "pako": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz" } }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "version": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { "base64-js": "1.2.1", - "ieee754": "1.1.8", - "isarray": "1.0.0" + "ieee754": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" } }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "version": "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", + "version": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.1.3", - "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.1.0" + "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "fsevents": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" } }, "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "version": "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" + "center-align": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "right-align": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" } }, "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "version": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", "dev": true }, "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "version": "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", + "version": "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" + "browserify-aes": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "pbkdf2-compat": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz" } }, "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", + "version": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.2.0", - "tapable": "0.1.10" + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", + "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz" }, "dependencies": { "memory-fs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", + "version": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", "dev": true } } }, "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" } }, "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "version": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" } }, "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" } }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "https-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "version": "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", + "version": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", "dev": true }, "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "version": "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", + "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" } }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" } }, "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "version": "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" + "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" } }, "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "version": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", "dev": true }, "memory-fs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "version": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", "dev": true, "requires": { "errno": "0.1.6", - "readable-stream": "2.3.4" + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" } }, "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "version": "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" + "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "braces": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "extglob": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "filename-regex": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" } }, "node-libs-browser": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", + "version": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", "dev": true, "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.1.4", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.3.0", - "domain-browser": "1.1.7", - "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.4", - "stream-browserify": "2.0.1", - "stream-http": "2.8.0", - "string_decoder": "0.10.31", - "timers-browserify": "2.0.6", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", - "vm-browserify": "0.0.4" + "assert": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "buffer": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", + "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz" } }, "os-browserify": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "version": "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", + "version": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, "ripemd160": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "version": "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", + "version": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", "dev": true }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" } }, "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "version": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", "dev": true }, "timers-browserify": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", - "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", + "version": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "integrity": "sha1-JB52kn2coF9NlZgZAi9bNmS2S64=", "dev": true, "requires": { - "setimmediate": "1.0.5" + "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" } }, "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "version": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, "requires": { - "async": "0.2.10", - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "async": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "uglify-to-browserify": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz" }, "dependencies": { "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "version": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true } } }, "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "version": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" }, "dependencies": { "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } } }, "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" } }, "watchpack": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "version": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, "requires": { - "async": "0.9.2", - "chokidar": "1.7.0", - "graceful-fs": "4.1.11" + "async": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "chokidar": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" }, "dependencies": { "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "version": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true } } }, "webpack": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", + "version": "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.3", - "enhanced-resolve": "0.9.1", - "interpret": "0.6.6", - "loader-utils": "0.2.17", - "memory-fs": "0.3.0", - "mkdirp": "0.5.1", - "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" + "acorn": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "enhanced-resolve": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", + "interpret": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", + "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "node-libs-browser": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", + "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "watchpack": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "webpack-core": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz" } }, "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true }, "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "version": "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", + "version": "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" + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "cliui": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" } } } }, "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": "0.4.10", - "websocket-extensions": "0.1.3" + "http-parser-js": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "websocket-extensions": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz" } }, "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", "dev": true }, "wgxpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", + "version": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", "dev": true }, "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "version": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", "dev": true, "optional": true }, "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "version": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" } }, "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "version": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "version": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", "dev": true }, "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "version": "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" + "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" } }, "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "version": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" } }, "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "version": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", "dev": true, "requires": { - "async-limiter": "1.0.0", - "safe-buffer": "5.1.1", - "ultron": "1.1.1" + "async-limiter": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "ultron": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz" } }, "x-is-function": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", + "version": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", "integrity": "sha1-XSlNw9Joy90GJYDgxd93o5HR+h4=", "dev": true }, "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "version": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", "dev": true }, "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "version": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "version": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "version": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "version": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yargs": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", + "version": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", "dev": true }, "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", "dev": true, "requires": { - "camelcase": "4.1.0" + "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz" } }, "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "version": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", "dev": true }, "zip-stream": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", + "version": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", "dev": true, "requires": { - "compress-commons": "0.2.9", - "lodash": "3.2.0", - "readable-stream": "1.0.34" + "compress-commons": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "lodash": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "version": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } diff --git a/package.json b/package.json index 1c9d1d91edd..640fb2b1455 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "node": ">=4.0" }, "devDependencies": { + "ajv": "^6.2.0", + "ajv-keywords": "^3.1.0", "babel-core": "6.22.0", "babel-loader": "^7.1.1", "babel-plugin-transform-es3-member-expression-literals": "6.22.0", @@ -72,7 +74,6 @@ "karma-chrome-launcher": "^2.2.0", "karma-coverage-istanbul-reporter": "^1.3.0", "karma-es5-shim": "^0.0.4", - "karma-expect": "^1.1.0", "karma-firefox-launcher": "^1.0.1", "karma-ie-launcher": "^1.0.0", "karma-mocha": "^1.3.0", @@ -80,7 +81,6 @@ "karma-opera-launcher": "^1.0.0", "karma-requirejs": "^1.1.0", "karma-safari-launcher": "^1.0.0", - "karma-sauce-launcher": "^1.1.0", "karma-script-launcher": "^1.0.0", "karma-sinon": "^1.0.5", "karma-sourcemap-loader": "^0.3.7", @@ -89,7 +89,7 @@ "localtunnel": "^1.3.0", "lodash": "^4.17.4", "mkpath": "^1.0.0", - "mocha": "^1.21.4", + "mocha": "2.2.5", "mock-fs": "^3.11.0", "nightwatch": "^0.9.5", "open": "0.0.5", diff --git a/src/AnalyticsAdapter.js b/src/AnalyticsAdapter.js index 0d570f14eb0..30848b341d8 100644 --- a/src/AnalyticsAdapter.js +++ b/src/AnalyticsAdapter.js @@ -5,15 +5,20 @@ import { ajax } from './ajax'; const events = require('./events'); const utils = require('./utils'); -const AUCTION_INIT = CONSTANTS.EVENTS.AUCTION_INIT; -const AUCTION_END = CONSTANTS.EVENTS.AUCTION_END; -const BID_REQUESTED = CONSTANTS.EVENTS.BID_REQUESTED; -const BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; -const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; -const BID_WON = CONSTANTS.EVENTS.BID_WON; -const BID_ADJUSTMENT = CONSTANTS.EVENTS.BID_ADJUSTMENT; -const SET_TARGETING = CONSTANTS.EVENTS.SET_TARGETING; -const AD_RENDER_FAILED = CONSTANTS.EVENTS.AD_RENDER_FAILED; +const { + EVENTS: { + AUCTION_INIT, + AUCTION_END, + BID_REQUESTED, + BID_TIMEOUT, + BID_RESPONSE, + BID_WON, + BID_ADJUSTMENT, + BIDDER_DONE, + SET_TARGETING, + AD_RENDER_FAILED + } +} = CONSTANTS; const LIBRARY = 'library'; const ENDPOINT = 'endpoint'; @@ -104,11 +109,12 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } [BID_TIMEOUT]: args => this.enqueue({ eventType: BID_TIMEOUT, args }), [BID_WON]: args => this.enqueue({ eventType: BID_WON, args }), [BID_ADJUSTMENT]: args => this.enqueue({ eventType: BID_ADJUSTMENT, args }), + [BIDDER_DONE]: args => this.enqueue({ eventType: BIDDER_DONE, args }), [SET_TARGETING]: args => this.enqueue({ eventType: SET_TARGETING, args }), [AUCTION_END]: args => this.enqueue({ eventType: AUCTION_END, args }), [AD_RENDER_FAILED]: args => this.enqueue({ eventType: AD_RENDER_FAILED, args }), [AUCTION_INIT]: args => { - args.config = config.options; // enableAnaltyics configuration object + args.config = typeof config === 'object' ? config.options || {} : {}; // enableAnaltyics configuration object this.enqueue({ eventType: AUCTION_INIT, args }); } }; @@ -121,6 +127,7 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } } // finally set this function to return log message, prevents multiple adapter listeners + this._oldEnable = this.enableAnalytics; this.enableAnalytics = function _enable() { return utils.logMessage(`Analytics adapter for "${global}" already enabled, unnecessary call to \`enableAnalytics\`.`); }; @@ -130,6 +137,7 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } utils._each(_handlers, (handler, event) => { events.off(event, handler); }); + this.enableAnalytics = this._oldEnable ? this._oldEnable : _enable; } function _emptyQueue() { diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 2497572cd10..2cf0a8f7253 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -6,6 +6,8 @@ import { STATUS } from 'src/constants'; import { userSync } from 'src/userSync'; import { nativeBidIsValid } from 'src/native'; import { isValidVideoBid } from 'src/video'; +import CONSTANTS from 'src/constants.json'; +import events from 'src/events'; import includes from 'core-js/library/fn/array/includes'; import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest } from 'src/utils'; @@ -184,6 +186,12 @@ export function newBidder(spec) { done(); } + // TODO: the code above needs to be refactored. We should always call done when we're done. if the auction + // needs to do cleanup before _it_ can be done it should handle that itself in the auction. It should _not_ + // require us, the bidders, to conditionally call done. That makes the whole done API very flaky. + // As soon as that is refactored, we can move this emit event where it should be, within the done function. + events.emit(CONSTANTS.EVENTS.BIDDER_DONE, bidderRequest); + registerSyncs(responses); } diff --git a/src/ajax.js b/src/ajax.js index df52ac949da..ded2f95f8a5 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -22,7 +22,7 @@ export function ajaxBuilder(timeout = 3000) { let useXDomainRequest = false; let method = options.method || (data ? 'POST' : 'GET'); - let callbacks = typeof callback === 'object' ? callback : { + let callbacks = typeof callback === 'object' && callback !== null ? callback : { success: function() { utils.logMessage('xhr success'); }, diff --git a/src/auction.js b/src/auction.js index 9212b5afa2b..8a23605bf0e 100644 --- a/src/auction.js +++ b/src/auction.js @@ -157,7 +157,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) return innerBidRequestId === bidRequest.bidderRequestId; }); - // this is done for cache-enabled video bids in tryAddVideoBids, after the cache is stored + // this is done for cache-enabled video bids in tryAddVideoBid, after the cache is stored request.doneCbCallCount += 1; bidsBackAll(); }, 1); diff --git a/src/constants.json b/src/constants.json index ef382b153af..c8a7c3ebefc 100644 --- a/src/constants.json +++ b/src/constants.json @@ -31,6 +31,7 @@ "BID_REQUESTED": "bidRequested", "BID_RESPONSE": "bidResponse", "BID_WON": "bidWon", + "BIDDER_DONE": "bidderDone", "SET_TARGETING": "setTargeting", "REQUEST_BIDS": "requestBids", "ADD_AD_UNITS": "addAdUnits", diff --git a/src/prebid.js b/src/prebid.js index b6f36a60086..935860acf35 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -175,7 +175,7 @@ $$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit) { targeting.setTargetingForGPT(targetingSet); // emit event - events.emit(SET_TARGETING); + events.emit(SET_TARGETING, targetingSet); }; /** @@ -192,7 +192,7 @@ $$PREBID_GLOBAL$$.setTargetingForAst = function() { targeting.setTargetingForAst(); // emit event - events.emit(SET_TARGETING); + events.emit(SET_TARGETING, targeting.getAllTargeting()); }; function emitAdRenderFail(reason, message, bid) { diff --git a/test/spec/modules/adxcgAnalyticsAdapter_spec.js b/test/spec/modules/adxcgAnalyticsAdapter_spec.js index e90e7a1f8de..edd09fdf54e 100644 --- a/test/spec/modules/adxcgAnalyticsAdapter_spec.js +++ b/test/spec/modules/adxcgAnalyticsAdapter_spec.js @@ -21,11 +21,28 @@ describe('adxcg analytics adapter', () => { }); describe('track', () => { + let initOptions = { + publisherId: '42' + }; + + adaptermanager.registerAnalyticsAdapter({ + code: 'adxcg', + adapter: adxcgAnalyticsAdapter + }); + + beforeEach(() => { + adaptermanager.enableAnalytics({ + provider: 'adxcg', + options: initOptions + }); + }); + + afterEach(() => { + adxcgAnalyticsAdapter.disableAnalytics(); + }); + it('builds and sends auction data', () => { let auctionTimestamp = 1496510254313; - let initOptions = { - publisherId: '42' - }; let bidRequest = { auctionId: 'requestIdData' }; @@ -49,16 +66,6 @@ describe('adxcg analytics adapter', () => { } ]; - adaptermanager.registerAnalyticsAdapter({ - code: 'adxcg', - adapter: adxcgAnalyticsAdapter - }); - - adaptermanager.enableAnalytics({ - provider: 'adxcg', - options: initOptions - }); - // Step 1: Send auction init event events.emit(constants.EVENTS.AUCTION_INIT, { timestamp: auctionTimestamp diff --git a/test/spec/modules/eplanningAnalyticsAdapter_spec.js b/test/spec/modules/eplanningAnalyticsAdapter_spec.js index aba68efc27b..cd538815954 100644 --- a/test/spec/modules/eplanningAnalyticsAdapter_spec.js +++ b/test/spec/modules/eplanningAnalyticsAdapter_spec.js @@ -20,6 +20,7 @@ describe('eplanning analytics adapter', () => { afterEach(() => { xhr.restore(); events.getEvents.restore(); + eplAnalyticsAdapter.disableAnalytics(); }); describe('track', () => { diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..8ba8541c833 --- /dev/null +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -0,0 +1,635 @@ +import adaptermanager from 'src/adaptermanager'; +import rubiconAnalyticsAdapter, { SEND_TIMEOUT } from 'modules/rubiconAnalyticsAdapter'; +import CONSTANTS from 'src/constants.json'; +import { config } from 'src/config'; + +let Ajv = require('ajv'); +let schema = require('./rubiconAnalyticsSchema.json'); +let ajv = new Ajv({ + allErrors: true +}); + +let validator = ajv.compile(schema); + +function validate(message) { + validator(message); + expect(validator.errors).to.deep.equal(null); +} + +// 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'); + +const { + EVENTS: { + AUCTION_INIT, + AUCTION_END, + BID_REQUESTED, + BID_RESPONSE, + BID_WON, + BID_TIMEOUT, + SET_TARGETING + } +} = CONSTANTS; + +const BID = { + 'bidder': 'rubicon', + 'width': 640, + 'height': 480, + 'mediaType': 'video', + 'statusMessage': 'Bid available', + 'adId': '2ecff0db240757', + 'source': 'client', + 'requestId': '2ecff0db240757', + 'currency': 'USD', + 'creativeId': '3571560', + 'cpm': 1.22752, + 'ttl': 300, + 'netRevenue': false, + 'ad': '', + 'rubiconTargeting': { + 'rpfl_elemid': '/19968336/header-bid-tag-0', + 'rpfl_14062': '2_tier0100' + }, + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', + 'responseTimestamp': 1519149629415, + 'requestTimestamp': 1519149628471, + 'adUnitCode': '/19968336/header-bid-tag-0', + 'timeToRespond': 944, + 'pbLg': '1.00', + 'pbMg': '1.20', + 'pbHg': '1.22', + 'pbAg': '1.20', + 'pbDg': '1.22', + 'pbCg': '', + 'size': '640x480', + 'adserverTargeting': { + 'hb_bidder': 'rubicon', + 'hb_adid': '2ecff0db240757', + 'hb_pb': 1.20, + 'hb_size': '640x480', + 'hb_source': 'client' + }, + getStatusCode() { + return 1; + } +}; + +const BID2 = Object.assign({}, BID, { + adUnitCode: '/19968336/header-bid-tag1', + adId: '3bd4ebb1c900e2', + requestId: '3bd4ebb1c900e2', + width: 728, + height: 90, + mediaType: 'banner', + cpm: 1.52, + rubiconTargeting: { + 'rpfl_elemid': '/19968336/header-bid-tag1', + 'rpfl_14062': '2_tier0100' + }, + adserverTargeting: { + 'hb_bidder': 'rubicon', + 'hb_adid': '3bd4ebb1c900e2', + 'hb_pb': '1.500', + 'hb_size': '728x90', + 'hb_source': 'client' + } +}); + +const MOCK = { + SET_TARGETING: { + [BID.adUnitCode]: BID.adserverTargeting, + [BID2.adUnitCode]: BID2.adserverTargeting + }, + AUCTION_INIT: { + 'timestamp': 1519149536560, + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', + 'timeout': 3000 + }, + BID_REQUESTED: { + 'bidder': 'rubicon', + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', + 'bidderRequestId': '1be65d7958826a', + 'bids': [ + { + 'bidder': 'rubicon', + 'params': { + 'accountId': '14062', + 'siteId': '70608', + 'zoneId': '335918', + 'userId': '12346', + 'keywords': ['a', 'b', 'c'], + 'inventory': 'test', + 'visitor': {'ucat': 'new', 'lastsearch': 'iphone'}, + 'position': 'btf', + 'video': { + 'language': 'en', + 'playerHeight': 480, + 'playerWidth': 640, + 'size_id': 203, + 'skip': 1, + 'skipdelay': 15, + 'aeParams': { + 'p_aso.video.ext.skip': '1', + 'p_aso.video.ext.skipdelay': '15' + } + } + }, + 'mediaType': 'video', + 'adUnitCode': '/19968336/header-bid-tag-0', + 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014', + 'sizes': [[640, 480]], + 'bidId': '2ecff0db240757', + 'bidderRequestId': '1be65d7958826a', + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' + }, + { + 'bidder': 'rubicon', + 'params': { + 'accountId': '14062', + 'siteId': '70608', + 'zoneId': '335918', + 'userId': '12346', + 'keywords': ['a', 'b', 'c'], + 'inventory': {'rating': '4-star', 'prodtype': 'tech'}, + 'visitor': {'ucat': 'new', 'lastsearch': 'iphone'}, + 'position': 'atf' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[1000, 300], [970, 250], [728, 90]] + } + }, + 'adUnitCode': '/19968336/header-bid-tag1', + 'transactionId': 'c116413c-9e3f-401a-bee1-d56aec29a1d4', + 'sizes': [[1000, 300], [970, 250], [728, 90]], + 'bidId': '3bd4ebb1c900e2', + 'bidderRequestId': '1be65d7958826a', + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' + } + ], + 'auctionStart': 1519149536560, + 'timeout': 5000, + 'start': 1519149562216 + }, + BID_RESPONSE: [ + BID, + BID2 + ], + AUCTION_END: { + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' + }, + BID_WON: [ + Object.assign({}, BID, { + 'status': 'rendered' + }), + Object.assign({}, BID2, { + 'status': 'rendered' + }) + ], + BID_TIMEOUT: [ + { + 'bidId': '2ecff0db240757', + 'bidder': 'rubicon', + 'adUnitCode': '/19968336/header-bid-tag-0', + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' + } + ] +}; + +const ANALYTICS_MESSAGE = { + 'eventTimeMillis': 1519767013781, + 'integration': 'pbjs', + 'version': '$prebid.version$', + 'referrerUri': 'http://www.test.com/page.html', + 'auctions': [ + { + 'clientTimeoutMillis': 3000, + 'serverTimeoutMillis': 1000, + 'accountId': 1001, + 'samplingFactor': 1, + 'adUnits': [ + { + 'adUnitCode': '/19968336/header-bid-tag-0', + 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014', + 'videoAdFormat': 'outstream', + 'mediaTypes': [ + 'video' + ], + 'dimensions': [ + { + 'width': 640, + 'height': 480 + } + ], + 'status': 'success', + 'adserverTargeting': { + 'hb_bidder': 'rubicon', + 'hb_adid': '2ecff0db240757', + 'hb_pb': '1.200', + 'hb_size': '640x480', + 'hb_source': 'client' + }, + 'bids': [ + { + 'bidder': 'rubicon', + 'bidId': '2ecff0db240757', + 'status': 'success', + 'source': 'client', + 'clientLatencyMillis': 617477221, + 'params': { + 'accountId': '14062', + 'siteId': '70608', + 'zoneId': '335918' + }, + 'bidResponse': { + 'bidPriceUSD': 1.22752, + 'dimensions': { + 'width': 640, + 'height': 480 + }, + 'mediaType': 'video' + } + } + ] + }, + { + 'adUnitCode': '/19968336/header-bid-tag1', + 'transactionId': 'c116413c-9e3f-401a-bee1-d56aec29a1d4', + 'mediaTypes': [ + 'banner' + ], + 'dimensions': [ + { + 'width': 1000, + 'height': 300 + }, + { + 'width': 970, + 'height': 250 + }, + { + 'width': 728, + 'height': 90 + } + ], + 'status': 'success', + 'adserverTargeting': { + 'hb_bidder': 'rubicon', + 'hb_adid': '3bd4ebb1c900e2', + 'hb_pb': '1.500', + 'hb_size': '728x90', + 'hb_source': 'client' + }, + 'bids': [ + { + 'bidder': 'rubicon', + 'bidId': '3bd4ebb1c900e2', + 'status': 'success', + 'source': 'client', + 'clientLatencyMillis': 617477221, + 'params': { + 'accountId': '14062', + 'siteId': '70608', + 'zoneId': '335918' + }, + 'bidResponse': { + 'bidPriceUSD': 1.52, + 'dimensions': { + 'width': 728, + 'height': 90 + }, + 'mediaType': 'banner' + } + } + ] + } + ] + } + ], + 'bidsWon': [ + { + 'bidder': 'rubicon', + 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014', + 'adUnitCode': '/19968336/header-bid-tag-0', + 'bidId': '2ecff0db240757', + 'status': 'success', + 'source': 'client', + 'clientLatencyMillis': 617477221, + 'samplingFactor': 1, + 'accountId': 1001, + 'params': { + 'accountId': '14062', + 'siteId': '70608', + 'zoneId': '335918' + }, + 'videoAdFormat': 'outstream', + 'mediaTypes': [ + 'video' + ], + 'adserverTargeting': { + 'hb_bidder': 'rubicon', + 'hb_adid': '2ecff0db240757', + 'hb_pb': '1.200', + 'hb_size': '640x480', + 'hb_source': 'client' + }, + 'bidResponse': { + 'bidPriceUSD': 1.22752, + 'dimensions': { + 'width': 640, + 'height': 480 + }, + 'mediaType': 'video' + }, + 'bidwonStatus': 'success' + }, + { + 'bidder': 'rubicon', + 'transactionId': 'c116413c-9e3f-401a-bee1-d56aec29a1d4', + 'adUnitCode': '/19968336/header-bid-tag1', + 'bidId': '3bd4ebb1c900e2', + 'status': 'success', + 'source': 'client', + 'clientLatencyMillis': 617477221, + 'samplingFactor': 1, + 'accountId': 1001, + 'params': { + 'accountId': '14062', + 'siteId': '70608', + 'zoneId': '335918' + }, + 'mediaTypes': [ + 'banner' + ], + 'adserverTargeting': { + 'hb_bidder': 'rubicon', + 'hb_adid': '3bd4ebb1c900e2', + 'hb_pb': '1.500', + 'hb_size': '728x90', + 'hb_source': 'client' + }, + 'bidResponse': { + 'bidPriceUSD': 1.52, + 'dimensions': { + 'width': 728, + 'height': 90 + }, + 'mediaType': 'banner' + }, + 'bidwonStatus': 'success' + } + ] +}; + +function performStandardAuction() { + 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(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]); +} + +describe('rubicon analytics adapter', () => { + let sandbox; + let xhr; + let requests; + let oldScreen; + let clock; + + beforeEach(() => { + sandbox = sinon.sandbox.create(); + + xhr = sandbox.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + + sandbox.stub(events, 'getEvents').returns([]); + + sandbox.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); + + oldScreen = window.screen; + window.screen = { + width: '375', + height: '812' + }; + + clock = sandbox.useFakeTimers(1519767013781); + + config.setConfig({ + s2sConfig: { + timeout: 1000, + accountId: 10000, + } + }) + }); + + afterEach(() => { + window.screen = oldScreen; + sandbox.restore(); + config.resetConfig(); + }); + + it('should require accountId', () => { + sandbox.stub(utils, 'logError'); + + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event' + } + }); + + expect(utils.logError.called).to.equal(true); + }); + + it('should require endpoint', () => { + sandbox.stub(utils, 'logError'); + + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + accountId: 1001 + } + }); + + expect(utils.logError.called).to.equal(true); + }); + + describe('sampling', () => { + beforeEach(() => { + sandbox.stub(Math, 'random').returns(0.08); + sandbox.stub(utils, 'logError'); + }); + + afterEach(() => { + rubiconAnalyticsAdapter.disableAnalytics(); + }); + + describe('with options.samplingFactor', () => { + it('should sample', () => { + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001, + samplingFactor: 10 + } + }); + + performStandardAuction(); + + expect(requests.length).to.equal(1); + }); + + it('should unsample', () => { + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001, + samplingFactor: 20 + } + }); + + performStandardAuction(); + + expect(requests.length).to.equal(0); + }); + + it('should throw errors for invalid samplingFactor', () => { + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001, + samplingFactor: 30 + } + }); + + performStandardAuction(); + + expect(requests.length).to.equal(0); + expect(utils.logError.called).to.equal(true); + }); + }); + describe('with options.sampling', () => { + it('should sample', () => { + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001, + sampling: 0.1 + } + }); + + performStandardAuction(); + + expect(requests.length).to.equal(1); + }); + + it('should unsample', () => { + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001, + sampling: 0.05 + } + }); + + performStandardAuction(); + + expect(requests.length).to.equal(0); + }); + + it('should throw errors for invalid samplingFactor', () => { + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001, + sampling: 1 / 30 + } + }); + + performStandardAuction(); + + expect(requests.length).to.equal(0); + expect(utils.logError.called).to.equal(true); + }); + }); + }); + + describe('when handling events', () => { + beforeEach(() => { + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: '1001' + } + }); + }); + + afterEach(() => { + rubiconAnalyticsAdapter.disableAnalytics(); + }); + + it('should build a batched message from prebid events', () => { + performStandardAuction(); + + expect(requests.length).to.equal(1); + let request = requests[0]; + + expect(request.url).to.equal('//localhost:9999/event'); + + let message = JSON.parse(request.requestBody); + validate(message); + + expect(message).to.deep.equal(ANALYTICS_MESSAGE); + }); + + it('should send batched message without BID_WON if necessary and further BID_WON events individually', () => { + 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(AUCTION_END, MOCK.AUCTION_END); + events.emit(SET_TARGETING, MOCK.SET_TARGETING); + events.emit(BID_WON, MOCK.BID_WON[0]); + + clock.tick(SEND_TIMEOUT + 1000); + + events.emit(BID_WON, MOCK.BID_WON[1]); + + expect(requests.length).to.equal(2); + + let message = JSON.parse(requests[0].requestBody); + validate(message); + expect(message.bidsWon.length).to.equal(1); + expect(message.auctions).to.deep.equal(ANALYTICS_MESSAGE.auctions); + expect(message.bidsWon[0]).to.deep.equal(ANALYTICS_MESSAGE.bidsWon[0]); + + message = JSON.parse(requests[1].requestBody); + validate(message); + expect(message.bidsWon.length).to.equal(1); + expect(message).to.not.have.property('auctions'); + expect(message.bidsWon[0]).to.deep.equal(ANALYTICS_MESSAGE.bidsWon[1]); + }); + + it('should properly mark bids as timed out', () => { + events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); + events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); + events.emit(BID_TIMEOUT, MOCK.BID_TIMEOUT); + events.emit(AUCTION_END, MOCK.AUCTION_END); + + clock.tick(SEND_TIMEOUT + 1000); + + expect(requests.length).to.equal(1); + + let message = JSON.parse(requests[0].requestBody); + validate(message); + 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).to.not.have.property('bidResponse'); + }); + }); +}); diff --git a/test/spec/modules/rubiconAnalyticsSchema.json b/test/spec/modules/rubiconAnalyticsSchema.json new file mode 100644 index 00000000000..cc4ad20db19 --- /dev/null +++ b/test/spec/modules/rubiconAnalyticsSchema.json @@ -0,0 +1,357 @@ +{ + "$schema": "http://json-schema.org/draft-07/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", + "required": [ + "eventTimeMillis", + "integration", + "version" + ], + "anyOf": [ + { + "required": [ + "auctions" + ] + }, + { + "required": [ + "bidsWon" + ] + } + ], + "properties": { + "eventTimeMillis": { + "type": "integer", + "description": "Unix timestamp of time of creation for this batched event in milliseconds." + }, + "integration": { + "type": "string", + "description": "Integration type that generated this event.", + "default": "pbjs" + }, + "version": { + "type": "string", + "description": "Version of Prebid.js responsible for the auctions contained within." + }, + "auctions": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "adUnits", + "samplingFactor" + ], + "properties": { + "clientTimeoutMillis": { + "type": "integer", + "description": "Timeout given in client for given auction in milliseconds (if applicable)." + }, + "serverTimeoutMillis": { + "type": "integer", + "description": "Timeout configured for server adapter request in milliseconds (if applicable)." + }, + "accountId": { + "type": "number", + "description": "The account id for prebid server (if applicable)." + }, + "samplingFactor": { + "$ref": "#/definitions/samplingFactor" + }, + "adUnits": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "description": "An array of adUnits involved in this auction.", + "required": [ + "status", + "adUnitCode", + "transactionId", + "mediaTypes", + "dimensions", + "bids" + ], + "properties": { + "status": { + "type": "string", + "description": "The status of the adUnit" + }, + "adUnitCode": { + "type": "string", + "description": "The adUnit.code identifier" + }, + "transactionId": { + "type": "string", + "description": "The UUID generated id to represent this adunit in this auction." + }, + "adSlot": { + "type": "string" + }, + "mediaTypes": { + "$ref": "#/definitions/mediaTypes" + }, + "videoAdFormat": { + "$ref": "#/definitions/videoAdFormat" + }, + "dimensions": { + "type": "array", + "description": "All valid sizes included in this auction (note: may be sizeConfig filtered).", + "minItems": 1, + "items": { + "$ref": "#/definitions/dimensions" + } + }, + "adserverTargeting": { + "$ref": "#/definitions/adserverTargeting" + }, + "bids": { + "type": "array", + "description": "An array that contains a combination of the bids from the adUnit combined with their responses.", + "minItems": 1, + "items": { + "$ref": "#/definitions/bid" + } + } + } + } + } + } + } + }, + "bidsWon": { + "type": "array", + "minItems": 1, + "items": { + "allOf": [ + { + "$ref": "#/definitions/bid" + }, + { + "required": [ + "transactionId", + "accountId", + "samplingFactor", + "mediaTypes", + "adUnitCode", + "bidwonStatus" + ], + "properties": { + "transactionId": { + "type": "string" + }, + "accountId": { + "type": "number" + }, + "samplingFactor": { + "$ref": "#/definitions/samplingFactor" + }, + "adUnitCode": { + "type": "string" + }, + "videoAdFormat": { + "$ref": "#/definitions/videoAdFormat" + }, + "mediaTypes": { + "$ref": "#/definitions/mediaTypes" + }, + "adserverTargeting": { + "$ref": "#/definitions/adserverTargeting" + }, + "bidwonStatus": { + "description": "Whether the bid was successfully rendered or not", + "type": "string", + "enum": [ + "success", + "error" + ] + } + } + } + ] + } + } + }, + "definitions": { + "adserverTargeting": { + "type": "object", + "description": "The adserverTargeting key/value pairs", + "patternProperties": { + ".+": { + "type": "string" + } + } + }, + "samplingFactor": { + "type": "integer", + "description": "An integer value representing the factor to multiply event count by to receive unsampled count.", + "enum": [ + 1, + 10, + 20, + 40, + 100 + ] + }, + "videoAdFormat": { + "type": "string", + "description": "This value only provided for video specifies the ad format", + "enum": [ + "pre-roll", + "interstitial", + "outstream", + "mid-roll", + "post-roll", + "vertical" + ] + }, + "mediaTypes": { + "type": "array", + "uniqueItems": true, + "minItems": 1, + "items": { + "type": "string", + "enum": [ + "native", + "video", + "banner" + ] + } + }, + "dimensions": { + "type": "object", + "description": "Size object representing the dimensions of creative in pixels.", + "required": [ + "width", + "height" + ], + "properties": { + "width": { + "type": "integer", + "minimum": 1 + }, + "height": { + "type": "integer", + "minimum": 1 + } + } + }, + "bid": { + "type": "object", + "required": [ + "bidder", + "bidId", + "status", + "source" + ], + "properties": { + "bidder": { + "type": "string" + }, + "bidId": { + "type": "string", + "description": "UUID representing this individual bid request in this auction." + }, + "params": { + "description": "A copy of the bid.params from the adUnit.bids", + "anyOf": [ + { + "type": "object" + }, + { + "$ref": "#/definitions/params/rubicon" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "success", + "no-bid", + "error" + ] + }, + "error": { + "type": "object", + "required": [ + "code" + ], + "properties": { + "code": { + "type": "string", + "enum": [ + "request-error", + "connect-error", + "timeout-error" + ] + }, + "description": { + "type": "string" + } + } + }, + "source": { + "type": "string", + "enum": [ + "client", + "server" + ] + }, + "clientLatencyMillis": { + "type": "integer", + "description": "Latency from auction start to bid response recieved in milliseconds." + }, + "serverLatencyMillis": { + "type": "integer", + "description": "Latency returned by prebid server (response_time_ms)." + }, + "bidResponse": { + "type": "object", + "required": [ + "dimensions", + "mediaType", + "bidPriceUSD" + ], + "properties": { + "dimensions": { + "$ref": "#/definitions/dimensions" + }, + "mediaType": { + "type": "string", + "enum": [ + "native", + "video", + "banner" + ] + }, + "bidPriceUSD": { + "type": "number", + "description": "The bid value denoted in USD" + }, + "dealId": { + "type": "integer", + "description": "The id associated with any potential deals" + } + } + } + } + }, + "params": { + "rubicon": { + "type": "object", + "properties": { + "accountId": { + "type": "number" + }, + "siteId": { + "type": "number" + }, + "zoneId": { + "type": "number" + } + } + } + } + } +} diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js index 5ad9b662e7f..06cd653f444 100644 --- a/test/spec/video_spec.js +++ b/test/spec/video_spec.js @@ -16,7 +16,7 @@ describe('video.js', () => { }] }]; const valid = isValidVideoBid(bid, bidRequests); - expect(valid).to.be(true); + expect(valid).to.equal(true); }); it('catches invalid instream bids', () => { @@ -33,7 +33,7 @@ describe('video.js', () => { }] }]; const valid = isValidVideoBid(bid, bidRequests); - expect(valid).to.be(false); + expect(valid).to.equal(false); }); it('catches invalid bids when prebid-cache is disabled', () => { @@ -46,7 +46,7 @@ describe('video.js', () => { const valid = isValidVideoBid({ vastXml: 'vast' }, bidRequests); - expect(valid).to.be(false); + expect(valid).to.equal(false); }); it('validates valid outstream bids', () => { @@ -67,7 +67,7 @@ describe('video.js', () => { }] }]; const valid = isValidVideoBid(bid, bidRequests); - expect(valid).to.be(true); + expect(valid).to.equal(true); }); it('catches invalid outstream bids', () => { @@ -84,6 +84,6 @@ describe('video.js', () => { }] }]; const valid = isValidVideoBid(bid, bidRequests); - expect(valid).to.be(false); + expect(valid).to.equal(false); }); }); From f7202e4011477aeb09280ea59d0da28c6ae6c961 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 10 Apr 2018 16:35:20 -0600 Subject: [PATCH 0246/1594] remove unneeded window.screen test from rubicon analytics --- test/spec/modules/rubiconAnalyticsAdapter_spec.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 8ba8541c833..d8f0811e81c 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -412,12 +412,6 @@ describe('rubicon analytics adapter', () => { sandbox.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); - oldScreen = window.screen; - window.screen = { - width: '375', - height: '812' - }; - clock = sandbox.useFakeTimers(1519767013781); config.setConfig({ @@ -429,7 +423,6 @@ describe('rubicon analytics adapter', () => { }); afterEach(() => { - window.screen = oldScreen; sandbox.restore(); config.resetConfig(); }); From bbcdba5c2f527059c58d4304dc6618fa2d8b04e8 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 10 Apr 2018 17:39:21 -0600 Subject: [PATCH 0247/1594] pin ajv as its new uri-js dependency causes issues in safari --- package-lock.json | 12 +++--------- package.json | 3 +-- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ecab0de841..83511e0dc28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -132,9 +132,9 @@ } }, "ajv": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.1.tgz", - "integrity": "sha1-KKarxJOiq+D7TIUHrK7bQ/pVBnE=", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", + "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", "dev": true, "requires": { "fast-deep-equal": "1.0.0", @@ -142,12 +142,6 @@ "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" } }, - "ajv-keywords": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", - "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", - "dev": true - }, "align-text": { "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", diff --git a/package.json b/package.json index 640fb2b1455..a31a5998788 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,7 @@ "node": ">=4.0" }, "devDependencies": { - "ajv": "^6.2.0", - "ajv-keywords": "^3.1.0", + "ajv": "6.2.0", "babel-core": "6.22.0", "babel-loader": "^7.1.1", "babel-plugin-transform-es3-member-expression-literals": "6.22.0", From 9dd928081b8bb10ed899d7007be8436052c61b96 Mon Sep 17 00:00:00 2001 From: rtbdemand <33991103+rtbdemand@users.noreply.github.com> Date: Wed, 11 Apr 2018 08:03:22 -0700 Subject: [PATCH 0248/1594] Create rtbdemandAdkBidAdapter.js (#2323) --- modules/rtbdemandAdkBidAdapter.js | 187 ++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 modules/rtbdemandAdkBidAdapter.js diff --git a/modules/rtbdemandAdkBidAdapter.js b/modules/rtbdemandAdkBidAdapter.js new file mode 100644 index 00000000000..a7ec8463c17 --- /dev/null +++ b/modules/rtbdemandAdkBidAdapter.js @@ -0,0 +1,187 @@ +import * as utils from 'src/utils'; +import { BANNER, VIDEO } from 'src/mediaTypes'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; + +const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', + 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', + 'pos', 'api', 'ext']; +const VERSION = '1.1'; + +/** + * Adapter for requesting bids from RtbdemandAdk white-label display platform + */ +export const spec = { + + code: 'rtbdemandadk', + aliases: ['headbidding'], + supportedMediaTypes: [BANNER, VIDEO], + isBidRequestValid: function(bidRequest) { + return 'params' in bidRequest && typeof bidRequest.params.host !== 'undefined' && + 'zoneId' in bidRequest.params && !isNaN(Number(bidRequest.params.zoneId)); + }, + buildRequests: function(bidRequests) { + let auctionId; + let dispatch = bidRequests.map(buildImp) + .reduce((acc, curr, index) => { + let bidRequest = bidRequests[index]; + let zoneId = bidRequest.params.zoneId; + let host = bidRequest.params.host; + acc[host] = acc[host] || {}; + acc[host][zoneId] = acc[host][zoneId] || []; + acc[host][zoneId].push(curr); + auctionId = bidRequest.bidderRequestId; + return acc; + }, {}); + let requests = []; + Object.keys(dispatch).forEach(host => { + Object.keys(dispatch[host]).forEach(zoneId => { + const request = buildRtbRequest(dispatch[host][zoneId], auctionId); + requests.push({ + method: 'GET', + url: `${window.location.protocol}//${host}/rtbg`, + data: { + zone: Number(zoneId), + ad_type: 'rtb', + v: VERSION, + r: JSON.stringify(request) + } + }); + }); + }); + return requests; + }, + interpretResponse: function(serverResponse, request) { + let response = serverResponse.body; + if (!response.seatbid) { + return []; + } + + let rtbRequest = JSON.parse(request.data.r); + let rtbImps = rtbRequest.imp; + let rtbBids = response.seatbid + .map(seatbid => seatbid.bid) + .reduce((a, b) => a.concat(b), []); + + return rtbBids.map(rtbBid => { + let imp = find(rtbImps, imp => imp.id === rtbBid.impid); + let prBid = { + requestId: rtbBid.impid, + cpm: rtbBid.price, + creativeId: rtbBid.crid, + currency: 'USD', + ttl: 360, + netRevenue: true + }; + if ('banner' in imp) { + prBid.mediaType = BANNER; + prBid.width = rtbBid.w; + prBid.height = rtbBid.h; + prBid.ad = formatAdMarkup(rtbBid); + } + if ('video' in imp) { + prBid.mediaType = VIDEO; + prBid.vastUrl = rtbBid.nurl; + prBid.width = imp.video.w; + prBid.height = imp.video.h; + } + return prBid; + }); + }, + getUserSyncs: function(syncOptions, serverResponses) { + if (!syncOptions.iframeEnabled || !serverResponses || serverResponses.length === 0) { + return []; + } + return serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.adk_usersync) + .map(rsp => rsp.body.ext.adk_usersync) + .reduce((a, b) => a.concat(b), []) + .map(sync_url => ({type: 'iframe', url: sync_url})); + } +}; + +registerBidder(spec); + +/** + * Builds parameters object for single impression + */ +function buildImp(bid) { + const sizes = bid.sizes; + const imp = { + 'id': bid.bidId, + 'tagid': bid.placementCode + }; + + if (bid.mediaType === 'video') { + imp.video = {w: sizes[0], h: sizes[1]}; + if (bid.params.video) { + Object.keys(bid.params.video) + .filter(param => includes(VIDEO_TARGETING, param)) + .forEach(param => imp.video[param] = bid.params.video[param]); + } + } else { + imp.banner = { + format: sizes.map(s => ({'w': s[0], 'h': s[1]})), + topframe: 0 + }; + } + if (utils.getTopWindowLocation().protocol === 'https:') { + imp.secure = 1; + } + return imp; +} + +/** + * Builds complete rtb request + * @param imps collection of impressions + * @param auctionId + */ +function buildRtbRequest(imps, auctionId) { + let req = { + 'id': auctionId, + 'imp': imps, + 'site': createSite(), + 'at': 1, + 'device': { + 'ip': 'caller', + 'ua': 'caller', + 'js': 1, + 'language': getLanguage() + }, + 'ext': { + 'adk_usersync': 1 + } + }; + if (utils.getDNT()) { + req.device.dnt = 1; + } + return req; +} + +function getLanguage() { + const language = navigator.language ? 'language' : 'userLanguage'; + return navigator[language].split('-')[0]; +} + +/** + * Creates site description object + */ +function createSite() { + var location = utils.getTopWindowLocation(); + return { + 'domain': location.hostname, + 'page': location.href.split('?')[0] + }; +} + +/** + * Format creative with optional nurl call + * @param bid rtb Bid object + */ +function formatAdMarkup(bid) { + var adm = bid.adm; + if ('nurl' in bid) { + adm += utils.createTrackPixelHtml(`${bid.nurl}&px=1`); + } + return `${adm}`; +} From cea9243969c96062df08960b68a0a835f9ddb666 Mon Sep 17 00:00:00 2001 From: rtbdemand <33991103+rtbdemand@users.noreply.github.com> Date: Wed, 11 Apr 2018 08:08:20 -0700 Subject: [PATCH 0249/1594] Create rtbdemandAdkBidAdapter.md (#2324) --- modules/rtbdemandAdkBidAdapter.md | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 modules/rtbdemandAdkBidAdapter.md diff --git a/modules/rtbdemandAdkBidAdapter.md b/modules/rtbdemandAdkBidAdapter.md new file mode 100644 index 00000000000..d75df08f167 --- /dev/null +++ b/modules/rtbdemandAdkBidAdapter.md @@ -0,0 +1,45 @@ +# Overview + +``` +Module Name: RtbdemandAdk Bidder Adapter +Module Type: Bidder Adapter +Maintainer: shreyanschopra@rtbdemand.com +``` + +# Description + +Connects to RtbdemandAdk whitelabel platform. +Banner and video formats are supported. + + +# Test Parameters +``` + var adUnits = [ + { + code: 'banner-ad-div', + sizes: [[300, 250]], // banner size + bids: [ + { + bidder: 'rtbdemandadk', + params: { + zoneId: '30164', //required parameter + host: 'cpm.metaadserving.com' //required parameter + } + } + ] + }, { + code: 'video-ad-player', + sizes: [640, 480], // video player size + bids: [ + { + bidder: 'rtbdemandadk', + mediaType : 'video', + params: { + zoneId: '30164', //required parameter + host: 'cpm.metaadserving.com' //required parameter + } + } + ] + } + ]; +``` From 1f7c17745ee2dd186b0af31319d836ce75e3b633 Mon Sep 17 00:00:00 2001 From: Max Crawford Date: Thu, 12 Apr 2018 09:45:58 -0400 Subject: [PATCH 0250/1594] Added LKQD prebid adapter with associated documentation and tests (#2333) * Added LKQD prebid adapter with associated documentation and tests * Updated conditional logic to correct unreachable block * Syntax changes to conform with Travis CI checks * Additional try...catch for greater clarity of error handling, updated all variable declarations to let/const style guide * Fixed improper error handling for DOMParser and added unit test for invalid XML response --- modules/lkqdBidAdapter.js | 212 ++++++++++++++ modules/lkqdBidAdapter.md | 33 +++ test/spec/modules/lkqdBidAdapter_spec.js | 343 +++++++++++++++++++++++ 3 files changed, 588 insertions(+) create mode 100644 modules/lkqdBidAdapter.js create mode 100644 modules/lkqdBidAdapter.md create mode 100644 test/spec/modules/lkqdBidAdapter_spec.js diff --git a/modules/lkqdBidAdapter.js b/modules/lkqdBidAdapter.js new file mode 100644 index 00000000000..fadefd57645 --- /dev/null +++ b/modules/lkqdBidAdapter.js @@ -0,0 +1,212 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { VIDEO } from 'src/mediaTypes'; + +const BIDDER_CODE = 'lkqd'; +const BID_TTL_DEFAULT = 300; +const ENDPOINT = 'https://ssp.lkqd.net/ad?pid=[PLACEMENT_ID]&sid=[SITE_ID]&output=[OUTPUT]&execution=[EXECUTION]&placement=[PLACEMENT]&playinit=[PLAY_INIT]&volume=[VOLUME]&timeout=[TIMEOUT]&width=[WIDTH]‌&height=[HEIGHT]&pbt=[PREBID_TOKEN]‌&dnt=[DO_NOT_TRACK]‌&pageurl=[PAGEURL]‌&contentid=[CONTENT_ID]‌&contenttitle=[CONTENT_TITLE]‌&contentlength=[CONTENT_LENGTH]‌&contenturl=[CONTENT_URL]&prebid=true'; + +const PID_KEY = '[PLACEMENT_ID]'; +const SID_KEY = '[SITE_ID]'; +const OUTPUT_KEY = '[OUTPUT]'; +const EXECUTION_KEY = '[EXECUTION]'; +const PLACEMENT_KEY = '[PLACEMENT]'; +const PLAYINIT_KEY = '[PLAY_INIT]'; +const VOLUME_KEY = '[VOLUME]'; +const TIMEOUT_KEY = '[TIMEOUT]'; +const WIDTH_KEY = '[WIDTH]'; +const HEIGHT_KEY = '[HEIGHT]'; +const DNT_KEY = '[DO_NOT_TRACK]'; +const PAGEURL_KEY = '[PAGEURL]'; +const CONTENTID_KEY = '[CONTENT_ID]'; +const CONTENTTITLE_KEY = '[CONTENT_TITLE]'; +const CONTENTLENGTH_KEY = '[CONTENT_LENGTH]'; +const CONTENTURL_KEY = '[CONTENT_URL]'; + +const PID_DEFAULT = null; +const SID_DEFAULT = null; +const OUTPUT_DEFAULT = 'vast'; +const EXECUTION_DEFAULT = 'any'; +const PLACEMENT_DEFAULT = ''; +const PLAYINIT_DEFAULT = 'auto'; +const VOLUME_DEFAULT = '100'; +const TIMEOUT_DEFAULT = ''; +const WIDTH_DEFAULT = null; +const HEIGHT_DEFAULT = null; +const DNT_DEFAULT = null; +const PAGEURL_DEFAULT = null; +const CONTENTID_DEFAULT = null; +const CONTENTTITLE_DEFAULT = null; +const CONTENTLENGTH_DEFAULT = null; +const CONTENTURL_DEFAULT = null; + +function _validateId(id) { + if (id && typeof id !== 'undefined' && parseInt(id) > 0) { + return true; + } + + return false; +} + +function isBidRequestValid(bidRequest) { + if (bidRequest.bidder === BIDDER_CODE && typeof bidRequest.params !== 'undefined') { + if (_validateId(bidRequest.params.siteId) && _validateId(bidRequest.params.placementId)) { + return true; + } + } + + return false; +} + +function _replaceMacro(key, paramValue, defaultValue, url) { + if (url && typeof url === 'string' && url !== '' && url.indexOf(key) > 0) { + if (paramValue) { + url = url.replace(key, paramValue); + } else if (defaultValue || defaultValue == '') { + url = url.replace(key, defaultValue); + } + } + + return url; +} + +function buildRequests(validBidRequests) { + let bidRequests = []; + + for (let i = 0; i < validBidRequests.length; i++) { + let bidRequest = validBidRequests[i]; + + // if width/height not provided to the ad unit for some reason then attempt request with default 640x480 size + if (!bidRequest.sizes || !bidRequest.sizes.length) { + utils.logWarn('Warning: Could not find valid width/height parameters on the provided adUnit'); + bidRequest.sizes = [[640, 480]]; + } + + // JWPlayer demo page uses sizes: [640,480] instead of sizes: [[640,480]] so need to handle single-layer array as well as nested arrays + if (bidRequest.sizes.length === 2 && typeof bidRequest.sizes[0] === 'number' && typeof bidRequest.sizes[1] === 'number') { + let adWidth = bidRequest.sizes[0]; + let adHeight = bidRequest.sizes[1]; + bidRequest.sizes = [[adWidth, adHeight]]; + } + + for (let j = 0; j < bidRequest.sizes.length; j++) { + let size = bidRequest.sizes[j]; + let playerWidth; + let playerHeight; + if (size && size.length == 2) { + playerWidth = size[0]; + playerHeight = size[1]; + } else { + utils.logWarn('Warning: Could not determine width/height from the provided adUnit'); + } + + let sspUrl = ENDPOINT.concat(); + + // required parameters + sspUrl = _replaceMacro(PID_KEY, bidRequest.params.placementId, PID_DEFAULT, sspUrl); + sspUrl = _replaceMacro(SID_KEY, bidRequest.params.siteId, SID_DEFAULT, sspUrl); + // optional parameters + sspUrl = _replaceMacro(OUTPUT_KEY, bidRequest.params.output, OUTPUT_DEFAULT, sspUrl); + sspUrl = _replaceMacro(EXECUTION_KEY, bidRequest.params.execution, EXECUTION_DEFAULT, sspUrl); + sspUrl = _replaceMacro(PLACEMENT_KEY, bidRequest.params.placement, PLACEMENT_DEFAULT, sspUrl); + sspUrl = _replaceMacro(PLAYINIT_KEY, bidRequest.params.playinit, PLAYINIT_DEFAULT, sspUrl); + sspUrl = _replaceMacro(VOLUME_KEY, bidRequest.params.volume, VOLUME_DEFAULT, sspUrl); + sspUrl = _replaceMacro(TIMEOUT_KEY, bidRequest.params.timeout, TIMEOUT_DEFAULT, sspUrl); + sspUrl = _replaceMacro(WIDTH_KEY, playerWidth, WIDTH_DEFAULT, sspUrl); + sspUrl = _replaceMacro(HEIGHT_KEY, playerHeight, HEIGHT_DEFAULT, sspUrl); + sspUrl = _replaceMacro(DNT_KEY, bidRequest.params.dnt, DNT_DEFAULT, sspUrl); + sspUrl = _replaceMacro(PAGEURL_KEY, bidRequest.params.pageurl, PAGEURL_DEFAULT, sspUrl); + sspUrl = _replaceMacro(CONTENTID_KEY, bidRequest.params.contentId, CONTENTID_DEFAULT, sspUrl); + sspUrl = _replaceMacro(CONTENTTITLE_KEY, bidRequest.params.contentTitle, CONTENTTITLE_DEFAULT, sspUrl); + sspUrl = _replaceMacro(CONTENTLENGTH_KEY, bidRequest.params.contentLength, CONTENTLENGTH_DEFAULT, sspUrl); + sspUrl = _replaceMacro(CONTENTURL_KEY, bidRequest.params.contentUrl, CONTENTURL_DEFAULT, sspUrl); + // random number to prevent caching + sspUrl = sspUrl + '‌&rnd=' + Math.floor(Math.random() * 999999999); + + let sspData = {}; + sspData.bidId = bidRequest.bidId; + sspData.bidWidth = playerWidth; + sspData.bidHeight = playerHeight; + + bidRequests.push({ + method: 'GET', + url: sspUrl, + data: sspData + }); + } + } + + return bidRequests; +} + +function interpretResponse(serverResponse, bidRequest) { + let bidResponses = []; + if (serverResponse && serverResponse.body) { + if (serverResponse.error) { + utils.logError('Error: ' + serverResponse.error); + return bidResponses; + } else { + try { + let bidResponse = {}; + if (bidRequest && bidRequest.data && bidRequest.data.bidId && bidRequest.data.bidId !== '') { + let sspXml = new window.DOMParser().parseFromString(serverResponse.body, 'text/xml'); + if (sspXml && sspXml.getElementsByTagName('parsererror').length == 0) { + let sspUrl = bidRequest.url.concat(); + let prebidToken; + let extensions = sspXml.getElementsByTagName('Extension'); + + if (extensions && extensions.length) { + for (let i = 0; i < extensions.length; i++) { + if (extensions[i].getAttribute('id') === 'prebidToken') { + prebidToken = extensions[i] + } + } + if (prebidToken) { + sspUrl = sspUrl + '&pbt' + prebidToken; + } else { + utils.logWarn('Warning: Could not determine token, cannot guarantee same ad will be received after auctionEnd'); + } + } else { + utils.logWarn('Warning: Response did not contain a token, cannot guarantee same ad will be received after auctionEnd'); + } + + bidResponse.requestId = bidRequest.data.bidId; + bidResponse.bidderCode = BIDDER_CODE; + bidResponse.ad = ''; + bidResponse.cpm = parseFloat(sspXml.getElementsByTagName('Pricing')[0].innerHTML); + bidResponse.width = bidRequest.data.bidWidth; + bidResponse.height = bidRequest.data.bidHeight; + bidResponse.ttl = BID_TTL_DEFAULT; + bidResponse.creativeId = sspXml.getElementsByTagName('Ad')[0].getAttribute('id'); + bidResponse.currency = sspXml.getElementsByTagName('Pricing')[0].getAttribute('currency'); + bidResponse.netRevenue = true; + bidResponse.vastUrl = sspUrl; + bidResponse.mediaType = VIDEO; + + bidResponses.push(bidResponse); + } else { + utils.logError('Error: Server response contained invalid XML'); + } + } else { + utils.logError('Error: Could not associate bid request to server response'); + } + } catch (e) { + utils.logError('Error: Could not interpret server response'); + } + } + } else { + utils.logError('Error: No server response or server response was empty for the requested URL'); + } + + return bidResponses; +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [VIDEO], + isBidRequestValid, + buildRequests, + interpretResponse +} + +registerBidder(spec); diff --git a/modules/lkqdBidAdapter.md b/modules/lkqdBidAdapter.md new file mode 100644 index 00000000000..22bff449bef --- /dev/null +++ b/modules/lkqdBidAdapter.md @@ -0,0 +1,33 @@ +# Overview + +``` +Module Name: LKQD Bidder Adapter +Module Type: Bidder Adapter +Maintainer: support@lkqd.com +``` + +# Description + +Connects to LKQD exchange for bids. + +LKQD bid adapter supports Video ads currently. + +For more information about [LKQD Ad Serving and Management](http://www.lkqd.com/ad-serving-and-management/), please contact [info@lkqd.com](info@lkqd.com). + +# Sample Ad Unit: For Publishers +``` +var videoAdUnit = [ +{ + code: 'video1', + sizes: [ + [300, 250], + [640, 480] + ], + bids: [{ + bidder: 'lkqd', + params: { + siteId: '662921', + placementId: '263' + } + }] +}]; diff --git a/test/spec/modules/lkqdBidAdapter_spec.js b/test/spec/modules/lkqdBidAdapter_spec.js new file mode 100644 index 00000000000..d3e16f0c99a --- /dev/null +++ b/test/spec/modules/lkqdBidAdapter_spec.js @@ -0,0 +1,343 @@ +import { spec } from 'modules/lkqdBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +const { expect } = require('chai'); + +describe('LKQD Bid Adapter Test', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'lkqd', + 'params': { + 'siteId': '662921', + 'placementId': '263' + }, + 'adUnitCode': 'video1', + 'sizes': [[300, 250], [640, 480]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'requestId': 'a09c66c3-53e3-4428-b296-38fc08e7cd2a', + 'transactionId': 'd6f6b392-54a9-454c-85fb-a2fd882c4a2d', + }; + + 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 zone id' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const ENDPOINT = 'https://ssp.lkqd.net/ad?'; + let bidRequests = [ + { + 'bidder': 'lkqd', + 'params': { + 'siteId': '662921', + 'placementId': '263' + }, + 'adUnitCode': 'lkqd', + 'sizes': [[300, 250], [640, 480]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'requestId': 'a09c66c3-53e3-4428-b296-38fc08e7cd2a', + 'transactionId': 'd6f6b392-54a9-454c-85fb-a2fd882c4a2d', + } + ]; + let bidRequest = [ + { + 'bidder': 'lkqd', + 'params': { + 'siteId': '662921', + 'placementId': '263' + }, + 'adUnitCode': 'lkqd', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'requestId': 'a09c66c3-53e3-4428-b296-38fc08e7cd2a', + 'transactionId': 'd6f6b392-54a9-454c-85fb-a2fd882c4a2d', + } + ]; + + it('should populate available parameters', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests.length).to.equal(2); + const r1 = requests[0].url; + expect(r1).to.contain('?pid=263'); + expect(r1).to.contain('&sid=662921'); + expect(r1).to.contain('&width=300'); + expect(r1).to.contain('&height=250'); + const r2 = requests[1].url; + expect(r2).to.contain('?pid=263'); + expect(r2).to.contain('&sid=662921'); + expect(r2).to.contain('&width=640'); + expect(r2).to.contain('&height=480'); + }); + + it('should not populate unspecified parameters', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests.length).to.equal(2); + const r1 = requests[0].url; + expect(r1).to.contain('‌&contentid=[CONTENT_ID]'); + expect(r1).to.contain('‌&contenttitle=[CONTENT_TITLE]'); + expect(r1).to.contain('‌&contentlength=[CONTENT_LENGTH]'); + expect(r1).to.contain('&height=250'); + const r2 = requests[1].url; + expect(r2).to.contain('‌&contentid=[CONTENT_ID]'); + expect(r2).to.contain('‌&contenttitle=[CONTENT_TITLE]'); + expect(r2).to.contain('‌&contentlength=[CONTENT_LENGTH]'); + expect(r2).to.contain('‌&contenturl=[CONTENT_URL]'); + }); + + it('should handle single size request', () => { + const requests = spec.buildRequests(bidRequest); + expect(requests.length).to.equal(1); + const r1 = requests[0].url; + expect(r1).to.contain('?pid=263'); + expect(r1).to.contain('&sid=662921'); + expect(r1).to.contain('&width=640'); + expect(r1).to.contain('&height=480'); + }); + + it('sends bid request to ENDPOINT via GET', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests.length).to.equal(2); + const r1 = requests[0]; + expect(r1.url).to.contain(ENDPOINT); + expect(r1.method).to.equal('GET'); + const r2 = requests[1] + expect(r2.url).to.contain(ENDPOINT); + expect(r2.method).to.equal('GET'); + }); + }); + + describe('interpretResponse', () => { + let bidRequest = { + 'url': 'https://ssp.lkqd.net/ad?pid=263&sid=662921&output=vast&execution=any&placement=&playinit=auto&volume=100&timeout=&width=300%E2%80%8C&height=250&pbt=[PREBID_TOKEN]%E2%80%8C&dnt=[DO_NOT_TRACK]%E2%80%8C&pageurl=[PAGEURL]%E2%80%8C&contentid=[CONTENT_ID]%E2%80%8C&contenttitle=[CONTENT_TITLE]%E2%80%8C&contentlength=[CONTENT_LENGTH]%E2%80%8C&contenturl=[CONTENT_URL]&prebid=true%E2%80%8C&rnd=874313435?bidId=253dcb69fb2577&bidWidth=300&bidHeight=250&', + 'data': { + 'bidId': '253dcb69fb2577', + 'bidWidth': '640', + 'bidHeight': '480' + } + }; + let serverResponse = {}; + serverResponse.body = ` + + +LKQD + + + +2.87 + + + + + + + + + + + + + + + + + + + + + + + + +00:00:30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + + + + + + + + +`; + + it('should correctly parse valid bid response', () => { + const BIDDER_CODE = 'lkqd'; + let bidResponses = spec.interpretResponse(serverResponse, bidRequest); + expect(bidResponses.length).to.equal(1); + let bidResponse = bidResponses[0]; + expect(bidResponse.requestId).to.equal(bidRequest.data.bidId); + expect(bidResponse.bidderCode).to.equal(BIDDER_CODE); + expect(bidResponse.ad).to.equal(''); + expect(bidResponse.cpm).to.equal(2.87); + expect(bidResponse.width).to.equal('640'); + expect(bidResponse.height).to.equal('480'); + expect(bidResponse.ttl).to.equal(300); + expect(bidResponse.creativeId).to.equal('677477'); + expect(bidResponse.currency).to.equal('USD'); + expect(bidResponse.netRevenue).to.equal(true); + expect(bidResponse.mediaType).to.equal('video'); + }); + + it('safely handles XML parsing failure from invalid bid response', () => { + let invalidServerResponse = {}; + invalidServerResponse.body = ''; + + let result = spec.interpretResponse(invalidServerResponse, bidRequest); + expect(result.length).to.equal(0); + }); + + it('handles nobid responses', () => { + let nobidResponse = {}; + nobidResponse.body = ''; + + let result = spec.interpretResponse(nobidResponse, bidRequest); + expect(result.length).to.equal(0); + }); + }); +}); From 188f78d7d2d0112b09b5e8d1975e9d19bd65c16c Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Thu, 12 Apr 2018 11:24:57 -0400 Subject: [PATCH 0251/1594] fix undefined value (#2387) --- modules/lkqdBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lkqdBidAdapter.js b/modules/lkqdBidAdapter.js index fadefd57645..cb4ffef73ee 100644 --- a/modules/lkqdBidAdapter.js +++ b/modules/lkqdBidAdapter.js @@ -173,7 +173,7 @@ function interpretResponse(serverResponse, bidRequest) { bidResponse.requestId = bidRequest.data.bidId; bidResponse.bidderCode = BIDDER_CODE; bidResponse.ad = ''; - bidResponse.cpm = parseFloat(sspXml.getElementsByTagName('Pricing')[0].innerHTML); + bidResponse.cpm = parseFloat(sspXml.getElementsByTagName('Pricing')[0].textContent); bidResponse.width = bidRequest.data.bidWidth; bidResponse.height = bidRequest.data.bidHeight; bidResponse.ttl = BID_TTL_DEFAULT; From 76e079a2a756c395468b45701abdf459cd7374f0 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Thu, 12 Apr 2018 08:38:21 -0700 Subject: [PATCH 0252/1594] Video Support Update (#2342) Added beacon tracking for video requests via user sync Added test coverage for user syncing and beaconing for banner and video responses Fixed bug in video where request is always in http instead of using current protocol Removed unnecessary query parameter 'ef' Switched custom functions with utility functions Refactored codebase for easier readability --- modules/openxBidAdapter.js | 300 ++++++++------- test/spec/modules/openxBidAdapter_spec.js | 422 ++++++++++++++-------- 2 files changed, 445 insertions(+), 277 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 9ed4f1250f8..7cbfd459e2d 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -1,111 +1,63 @@ -import { config } from 'src/config'; +import {config} from 'src/config'; import {registerBidder} from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; import {userSync} from 'src/userSync'; -import { BANNER, VIDEO } from 'src/mediaTypes'; +import {BANNER, VIDEO} from 'src/mediaTypes'; +import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.0.0'; +const BIDDER_VERSION = '2.0.1'; export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, - isBidRequestValid: function(bid) { - if (bid.mediaType === VIDEO) { - if (typeof bid.params.video !== 'object' || !bid.params.video.url) { + isBidRequestValid: function (bidRequest) { + if (isVideoRequest(bidRequest)) { + if (!utils.deepAccess(bidRequest, 'params.video.url')) { return false; } } - return !!(bid.params.unit && bid.params.delDomain); + return !!(bidRequest.params.unit && bidRequest.params.delDomain); }, - buildRequests: function(bids) { - let isIfr = utils.inIframe(); - let currentURL = (window.parent !== window) ? document.referrer : window.location.href; - if (bids.length === 0) { - return; + buildRequests: function (bidRequests) { + if (bidRequests.length === 0) { + return []; } let requests = []; - let bannerRequests = []; - let videoRequests = []; - const {bannerBids, videoBids} = bids.reduce(function(acc, curBid) { - // Fallback to banner ads if nothing specified - if (!curBid.mediaTypes || utils.isEmpty(curBid.mediaTypes)) { - if (curBid.mediaType && curBid.mediaType == VIDEO) { - acc.videoBids.push(curBid); - } else { - acc.bannerBids.push(curBid); - } - } else if (curBid.mediaTypes.video) { - acc.videoBids.push(curBid); - } else if (curBid.mediaTypes.banner) { - acc.bannerBids.push(curBid); - } - return acc; - }, {bannerBids: [], videoBids: []}); + let [videoBids, bannerBids] = partitionByVideoBids(bidRequests); // build banner requests - if (bannerBids.length !== 0) { - let delDomain = bannerBids[0].params.delDomain; - let configuredBc = bannerBids[0].params.bc; - let bc = configuredBc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`; - bannerRequests = [ buildOXRequest(bannerBids, { - ju: currentURL, - jr: currentURL, - ch: document.charSet || document.characterSet, - res: `${screen.width}x${screen.height}x${screen.colorDepth}`, - ifr: isIfr, - tz: new Date().getTimezoneOffset(), - tws: getViewportDimensions(isIfr), - ef: 'bt%2Cdb', - be: 1, - bc: bc, - nocache: new Date().getTime() - }, - delDomain)]; + if (bannerBids.length > 0) { + requests.push(buildOXBannerRequest(bannerBids)); } // build video requests - if (videoBids.length !== 0) { - videoRequests = buildOXVideoRequest(videoBids); + if (videoBids.length > 0) { + videoBids.forEach(videoBid => { + requests.push(buildOXVideoRequest(videoBid)) + }); } - requests = bannerRequests.concat(videoRequests); return requests; }, - interpretResponse: function({body: oxResponseObj}, bidRequest) { - let bidResponses = []; - let mediaType = BANNER; - if (bidRequest && bidRequest.payload) { - if (bidRequest.payload.bids) { - mediaType = bidRequest.payload.bids[0].mediaType; - } else if (bidRequest.payload.bid) { - mediaType = bidRequest.payload.bid.mediaType; - } - } + interpretResponse: function ({body: oxResponseObj}, serverRequest) { + let mediaType = getMediaTypeFromRequest(serverRequest); - if (mediaType === VIDEO) { - if (oxResponseObj && oxResponseObj.pixels) { - userSync.registerSync('iframe', 'openx', oxResponseObj.pixels); - } - bidResponses = createVideoBidResponses(oxResponseObj, bidRequest.payload); - return bidResponses; - } + registerUserSync(mediaType, oxResponseObj); - let adUnits = oxResponseObj.ads.ad; - if (oxResponseObj.ads && oxResponseObj.ads.pixels) { - userSync.registerSync('iframe', BIDDER_CODE, oxResponseObj.ads.pixels); - } - if (!adUnits) { - adUnits = []; - } - bidResponses = createBidResponses(adUnits, bidRequest.payload); - return bidResponses; + return mediaType === VIDEO ? createVideoBidResponses(oxResponseObj, serverRequest.payload) + : createBannerBidResponses(oxResponseObj, serverRequest.payload); } }; -function createBidResponses(adUnits, {bids, startTime}) { +function isVideoRequest(bidRequest) { + return utils.deepAccess(bidRequest, 'mediaTypes.video') || bidRequest.mediaType === VIDEO; +} + +function createBannerBidResponses(oxResponseObj, {bids, startTime}) { + let adUnits = oxResponseObj.ads.ad; let bidResponses = []; let shouldSendBoPixel = bids[0].params.sendBoPixel; if (shouldSendBoPixel === undefined) { @@ -115,14 +67,14 @@ function createBidResponses(adUnits, {bids, startTime}) { for (let i = 0; i < adUnits.length; i++) { let adUnit = adUnits[i]; let bidResponse = {}; - if (adUnits.length == bids.length) { + if (adUnits.length === bids.length) { // request and response length match, directly assign the request id based on positioning bidResponse.requestId = bids[i].bidId; } else { for (let j = i; j < bids.length; j++) { let bid = bids[j]; if (String(bid.params.unit) === String(adUnit.adunitid) && adUnitHasValidSizeFromBid(adUnit, bid) && !bid.matched) { - // ad unit and size match, this is the correct bid response to bid + // ad unit and size match, this is the correct bid response to bid bidResponse.requestId = bid.bidId; bid.matched = true; break; @@ -158,41 +110,14 @@ function createBidResponses(adUnits, {bids, startTime}) { } bidResponse.ts = adUnit.ts; - let bt = config.getConfig('bidderTimeout'); - if (window.PREBID_TIMEOUT) { - bt = Math.min(window.PREBID_TIMEOUT, bt); - } - let beaconParams = { - bd: +(new Date()) - startTime, - br: '0', // may be 0, t, or p - bt: bt, - bs: window.location.hostname - }; - - beaconParams.br = beaconParams.bt < beaconParams.bd ? 't' : 'p'; - beaconParams.bp = adUnit.pub_rev; - beaconParams.ts = adUnit.ts; - let boUrl; - if (shouldSendBoPixel) { - boUrl = getBoUrl(adUnit.creative[0], beaconParams); - } - if (boUrl) { - userSync.registerSync('image', BIDDER_CODE, boUrl); + if (shouldSendBoPixel && adUnit.ts) { + registerBeacon(BANNER, adUnit, startTime); } bidResponses.push(bidResponse); } return bidResponses; } -function getBoUrl(creative, params) { - let recordPixel = creative.tracking.impression; - let boBase = recordPixel.match(/([^?]+\/)ri\?/); - - if (boBase) { - return `${boBase[1]}bo?${buildQueryStringFromParams(params)}`; - } -} - function buildQueryStringFromParams(params) { for (let key in params) { if (params.hasOwnProperty(key)) { @@ -265,16 +190,48 @@ function formatCustomParms(customKey, customParams) { return (customKey.toLowerCase() + '=' + value.toLowerCase()).replace('+', '.').replace('/', '_') } -function buildOXRequest(bids, oxParams, delDomain) { - if (!utils.isArray(bids)) { - return; +function partitionByVideoBids(bidRequests) { + return bidRequests.reduce(function (acc, bid) { + // Fallback to banner ads if nothing specified + if (isVideoRequest(bid)) { + acc[0].push(bid); + } else { + acc[1].push(bid); + } + return acc; + }, [[], []]); +} + +function getMediaTypeFromRequest(serverRequest) { + return /avjp$/.test(serverRequest.url) ? VIDEO : BANNER; +} + +function registerUserSync(mediaType, responseObj) { + if (mediaType === VIDEO && responseObj.pixels) { + userSync.registerSync('iframe', BIDDER_CODE, responseObj.pixels); + } else if (utils.deepAccess(responseObj, 'ads.pixels')) { + userSync.registerSync('iframe', BIDDER_CODE, responseObj.ads.pixels); } +} - oxParams.auid = utils._map(bids, bid => bid.params.unit).join(','); - oxParams.dddid = utils._map(bids, bid => bid.transactionId).join(','); - oxParams.aus = utils._map(bids, bid => { - return utils.parseSizesInput(bid.sizes).join(','); - }).join('|'); +function buildOXBannerRequest(bids) { + const isInIframe = utils.inIframe(); + + let queryParams = { + ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), + jr: utils.getTopWindowReferrer(), + ch: document.charSet || document.characterSet, + res: `${screen.width}x${screen.height}x${screen.colorDepth}`, + ifr: isInIframe, + tz: new Date().getTimezoneOffset(), + tws: getViewportDimensions(isInIframe), + be: 1, + bc: bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, + nocache: new Date().getTime(), + auid: utils._map(bids, bid => bid.params.unit).join(','), + dddid: utils._map(bids, bid => bid.transactionId).join(','), + aus: utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|') + }; let customParamsForAllBids = []; let hasCustomParam = false; @@ -289,7 +246,7 @@ function buildOXRequest(bids, oxParams, delDomain) { } }); if (hasCustomParam) { - oxParams.tps = customParamsForAllBids.join(','); + queryParams.tps = customParamsForAllBids.join(','); } let customFloorsForAllBids = []; @@ -303,50 +260,81 @@ function buildOXRequest(bids, oxParams, delDomain) { } }); if (hasCustomFloor) { - oxParams.aumfs = customFloorsForAllBids.join(','); + queryParams.aumfs = customFloorsForAllBids.join(','); } - let url = `//${delDomain}/w/1.0/arj`; + let url = `//${bids[0].params.delDomain}/w/1.0/arj`; return { method: 'GET', url: url, - data: oxParams, + data: queryParams, payload: {'bids': bids, 'startTime': new Date()} }; } -function buildOXVideoRequest(bids) { - return bids.map(function(bid) { - let url = 'http://' + bid.params.delDomain + '/v/1.0/avjp'; - let oxVideoParams = generateVideoParameters(bid); - return { - method: 'GET', - url: url, - data: oxVideoParams, - payload: {'bid': bid, 'startTime': new Date()} - }; - }); +function buildOXVideoRequest(bid) { + let url = `//${bid.params.delDomain}/v/1.0/avjp`; + let oxVideoParams = generateVideoParameters(bid); + return { + method: 'GET', + url: url, + data: oxVideoParams, + payload: {'bid': bid, 'startTime': new Date()} + }; } function generateVideoParameters(bid) { let oxVideo = bid.params.video; - let oxVideoParams = { auid: bid.params.unit }; + let context = utils.deepAccess(bid, 'mediaTypes.video.context'); + let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); + let oxVideoParams = {auid: bid.params.unit}; + let width; + let height; + + // normalize config for video size + 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 (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 (utils.isArray(playerSize) && playerSize.length === 2) { + width = parseInt(playerSize[0], 10); + height = parseInt(playerSize[1], 10); + } - Object.keys(oxVideo).forEach(function(key) { + Object.keys(oxVideo).forEach(function (key) { if (key === 'openrtb') { oxVideoParams[key] = JSON.stringify(oxVideo[key]); } else { oxVideoParams[key] = oxVideo[key]; } }); - oxVideoParams['be'] = 'true'; + + // defaults + oxVideoParams.be = '1'; + + // override prebid config with openx config if available + oxVideoParams.vwd = width || oxVideo.vwd; + oxVideoParams.vht = height || oxVideo.vht; + + if (context === 'outstream') { + oxVideoParams.vos = '101'; + } + return oxVideoParams; } function createVideoBidResponses(response, {bid, startTime}) { + let shouldSendBoPixel = bid.params.sendBoPixel; + if (shouldSendBoPixel === undefined) { + // Not specified, default to turned on + shouldSendBoPixel = true; + } let bidResponses = []; if (response !== undefined && response.vastUrl !== '' && response.pub_rev !== '') { + let vastQueryParams = parse(response.vastUrl).search || {}; let bidResponse = {}; bidResponse.requestId = bid.bidId; bidResponse.bidderCode = BIDDER_CODE; @@ -362,10 +350,54 @@ function createVideoBidResponses(response, {bid, startTime}) { bidResponse.vastUrl = response.vastUrl; bidResponse.mediaType = VIDEO; + // enrich adunit with vast parameters + response.ph = vastQueryParams.ph; + response.colo = vastQueryParams.colo; + response.ts = vastQueryParams.ts; + + if (shouldSendBoPixel && response.ts) { + registerBeacon(VIDEO, response, startTime) + } bidResponses.push(bidResponse); } return bidResponses; } +function registerBeacon(mediaType, adUnit, startTime) { + let bt = config.getConfig('bidderTimeout'); + let beaconUrl; + if (window.PREBID_TIMEOUT) { + bt = Math.min(window.PREBID_TIMEOUT, bt); + } + + let beaconParams = { + bd: +(new Date()) - startTime, + bp: adUnit.pub_rev, + br: '0', // may be 0, t, or p + bs: utils.getTopWindowLocation().hostname, + bt: bt, + ts: adUnit.ts + }; + + beaconParams.br = beaconParams.bt < beaconParams.bd ? 't' : 'p'; + + if (mediaType === VIDEO) { + let url = parse(adUnit.colo); + beaconParams.ph = adUnit.ph; + beaconUrl = `//${url.hostname}/w/1.0/bo?${buildQueryStringFromParams(beaconParams)}` + } else { + let recordPixel = utils.deepAccess(adUnit, 'creative.0.tracking.impression'); + let boBase = recordPixel.match(/([^?]+\/)ri\?/); + + if (boBase && boBase.length > 1) { + beaconUrl = `${boBase[1]}bo?${buildQueryStringFromParams(beaconParams)}`; + } + } + + if (beaconUrl) { + userSync.registerSync('image', BIDDER_CODE, beaconUrl); + } +} + registerBidder(spec); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 0b0e8e54ebb..d780cb3d3e9 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1,6 +1,8 @@ -import { expect } from 'chai'; -import { spec } from 'modules/openxBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; +import {expect} from 'chai'; +import {spec} from 'modules/openxBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +import {BANNER, VIDEO} from 'src/mediaTypes'; +import {userSync} from 'src/userSync'; const URLBASE = '/w/1.0/arj'; const URLBASEVIDEO = '/v/1.0/avjp'; @@ -15,76 +17,100 @@ describe('OpenxAdapter', () => { }); describe('isBidRequestValid', () => { - const bid = { - 'bidder': 'openx', - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'mediaType': 'banner', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - - const videoBid = { - 'bidder': 'openx', - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain', - 'video': { - 'be': 'true', - 'url': 'abc.com', - 'vtest': '1' - } - }, - 'adUnitCode': 'adunit-code', - 'mediaType': 'video', - 'sizes': [640, 480], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' - }; - - it('should return true when required params found for a banner ad', () => { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); + describe('when request is for a banner ad', () => { + const bannerBid = { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: {banner: {}}, + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475' + }; - it('should return false when required params are not passed for a banner ad', () => { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = {'unit': '12345678'}; - expect(spec.isBidRequestValid(bid)).to.equal(false); + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + }); + + it('should return false when there is no delivery domain', () => { + let bid = Object.assign({}, bannerBid); + bid.params = {'unit': '12345678'}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when there is no ad unit id ', () => { + let bid = Object.assign({}, bannerBid); + bid.params = {delDomain: 'test-del-domain'}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); }); - it('should return true when required params found for a video ad', () => { - expect(spec.isBidRequestValid(videoBid)).to.equal(true); - }); + describe('when request is for a video ad', function () { + const videoBidWithMediaTypes = { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain', + video: { + be: 'true', + url: 'abc.com' + } + }, + adUnitCode: 'adunit-code', + mediaTypes: {video: {}}, + sizes: [640, 480], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; - it('should return false when required params are not passed for a video ad', () => { - let videoBid = Object.assign({}, videoBid); - delete videoBid.params; - videoBid.params = {}; - expect(spec.isBidRequestValid(videoBid)).to.equal(false); + const videoBidWithMediaType = { + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain', + 'video': { + 'be': 'true', + 'url': 'abc.com' + } + }, + 'adUnitCode': 'adunit-code', + 'mediaTypes': 'video', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(true); + }); + + it('should return false when required params are not passed', () => { + let videoBidWithMediaTypes = Object.assign({}, videoBidWithMediaTypes); + videoBidWithMediaTypes.params = {}; + expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); + }); + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(true); + }); + + it('should return false when required params are not passed', () => { + let videoBidWithMediaType = Object.assign({}, videoBidWithMediaType); + delete videoBidWithMediaType.params; + videoBidWithMediaType.params = {}; + expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(false); + }); }); }); describe('buildRequests for banner ads', () => { - const bidRequestsWithNoMediaType = [{ - 'bidder': 'openx', - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }]; const bidRequestsWithMediaType = [{ 'bidder': 'openx', 'params': { @@ -96,7 +122,7 @@ describe('OpenxAdapter', () => { 'sizes': [[300, 250], [300, 600]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', + 'auctionId': '1d1a030790a475' }]; const bidRequestsWithMediaTypes = [{ 'bidder': 'openx', @@ -105,39 +131,55 @@ describe('OpenxAdapter', () => { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', - 'mediaTypes': {banner: {}}, - 'sizes': [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', + 'auctionId': '1d1a030790a475' }]; - it('should send bid request to openx url via GET, even without mediaType specified', () => { - const request = spec.buildRequests(bidRequestsWithNoMediaType); - expect(request[0].url).to.equal('//' + bidRequestsWithNoMediaType[0].params.delDomain + URLBASE); - expect(request[0].method).to.equal('GET'); - }); - it('should send bid request to openx url via GET, with mediaType specified as banner', () => { const request = spec.buildRequests(bidRequestsWithMediaType); - expect(request[0].url).to.equal('//' + bidRequestsWithNoMediaType[0].params.delDomain + URLBASE); + expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); }); it('should send bid request to openx url via GET, with mediaTypes specified with banner type', () => { const request = spec.buildRequests(bidRequestsWithMediaTypes); - expect(request[0].url).to.equal('//' + bidRequestsWithNoMediaType[0].params.delDomain + URLBASE); + expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); }); - it('should have the correct parameters', () => { - const request = spec.buildRequests(bidRequestsWithNoMediaType); - const dataParams = request[0].data; - - expect(dataParams.auid).to.exist; - expect(dataParams.auid).to.equal('12345678'); - expect(dataParams.aus).to.exist; - expect(dataParams.aus).to.equal('300x250,300x600'); + describe('when there is a legacy request with no media type', function () { + const deprecatedBidRequestsFormatWithNoMediaType = [{ + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + let requestData; + + beforeEach(function () { + requestData = spec.buildRequests(deprecatedBidRequestsFormatWithNoMediaType)[0].data; + }); + + it('should have an ad unit id', () => { + expect(requestData.auid).to.equal('12345678'); + }); + + it('should have ad sizes', function () { + expect(requestData.aus).to.equal('300x250,300x600'); + }); }); it('should send out custom params on bids that have customParams specified', () => { @@ -201,16 +243,20 @@ describe('OpenxAdapter', () => { describe('buildRequests for video', () => { const bidRequestsWithMediaTypes = [{ 'bidder': 'openx', - 'mediaTypes': {video: {}}, + 'mediaTypes': { + video: { + playerSize: [640, 480] + } + }, 'params': { 'unit': '12345678', 'delDomain': 'test-del-domain', 'video': { - 'url': 'abc.com', + 'url': 'abc.com' } }, 'adUnitCode': 'adunit-code', - 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', @@ -224,7 +270,7 @@ describe('OpenxAdapter', () => { 'unit': '12345678', 'delDomain': 'test-del-domain', 'video': { - 'url': 'abc.com', + 'url': 'abc.com' } }, 'adUnitCode': 'adunit-code', @@ -237,13 +283,13 @@ describe('OpenxAdapter', () => { it('should send bid request to openx url via GET, with mediaType as video', () => { const request = spec.buildRequests(bidRequestsWithMediaType); - expect(request[0].url).to.equal('http://' + bidRequestsWithMediaType[0].params.delDomain + URLBASEVIDEO); + expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); it('should send bid request to openx url via GET, with mediaTypes having video parameter', () => { const request = spec.buildRequests(bidRequestsWithMediaTypes); - expect(request[0].url).to.equal('http://' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASEVIDEO); + expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); @@ -251,14 +297,22 @@ describe('OpenxAdapter', () => { const request = spec.buildRequests(bidRequestsWithMediaTypes); const dataParams = request[0].data; - expect(dataParams.auid).to.exist; expect(dataParams.auid).to.equal('12345678'); - expect(dataParams.url).to.exist; expect(dataParams.url).to.equal('abc.com'); + expect(dataParams.vht).to.equal(480); + expect(dataParams.vwd).to.equal(640); }); }); describe('interpretResponse for banner ads', () => { + beforeEach(() => { + sinon.spy(userSync, 'registerSync'); + }); + + afterEach(function () { + userSync.registerSync.restore(); + }); + const bids = [{ 'bidder': 'openx', 'params': { @@ -270,49 +324,51 @@ describe('OpenxAdapter', () => { 'sizes': [[300, 250], [300, 600]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', + 'auctionId': '1d1a030790a475' }]; const bidRequest = { method: 'GET', - url: 'url', + url: '//openx-d.openx.net/v/1.0/arj', data: {}, payload: {'bids': bids, 'startTime': new Date()} }; + const bidResponse = { 'ads': - { - 'version': 1, - 'count': 1, - 'pixels': 'http://testpixels.net', - 'ad': [ - { - 'adunitid': 12345678, - 'adid': 5678, - 'type': 'html', - 'html': 'test_html', - 'framed': 1, - 'is_fallback': 0, - 'ts': 'ts', - 'cpipc': 1000, - 'pub_rev': '1000', - 'adv_id': 'adv_id', - 'brand_id': '', - 'creative': [ - { - 'width': '300', - 'height': '250', - 'target': '_blank', - 'mime': 'text/html', - 'media': 'test_media', - 'tracking': { - 'impression': 'test_impression', - 'inview': 'test_inview', - 'click': 'test_click' + { + 'version': 1, + 'count': 1, + 'pixels': 'http://testpixels.net', + 'ad': [ + { + 'adunitid': 12345678, + 'adid': 5678, + 'type': 'html', + 'html': 'test_html', + 'framed': 1, + 'is_fallback': 0, + 'ts': 'ts', + 'cpipc': 1000, + 'pub_rev': '1000', + 'adv_id': 'adv_id', + 'brand_id': '', + 'creative': [ + { + 'width': '300', + 'height': '250', + 'target': '_blank', + 'mime': 'text/html', + 'media': 'test_media', + 'tracking': { + 'impression': 'http://openx-d.openx.net/v/1.0/ri?ts=ts', + 'inview': 'test_inview', + 'click': 'test_click' + } } - } - ] - }] - } + ] + }] + } + }; it('should return correct bid response', () => { const expectedResponse = [ @@ -337,28 +393,63 @@ describe('OpenxAdapter', () => { it('handles nobid responses', () => { const bidResponse = { 'ads': - { - 'version': 1, - 'count': 1, - 'pixels': 'http://testpixels.net', - 'ad': [] - } + { + 'version': 1, + 'count': 1, + 'pixels': 'http://testpixels.net', + 'ad': [] + } }; const result = spec.interpretResponse({body: bidResponse}, bidRequest); expect(result.length).to.equal(0); }); + + it('should register a user sync', () => { + spec.interpretResponse({body: bidResponse}, bidRequest); + sinon.assert.calledWith(userSync.registerSync, 'iframe', 'openx', 'http://testpixels.net'); + }); + + it('should register a beacon', () => { + spec.interpretResponse({body: bidResponse}, bidRequest); + sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/\/\/openx-d\.openx\.net.*\/bo\?.*ts=ts/)); + }); }); describe('interpretResponse for video ads', () => { - const bids = [{ + beforeEach(() => { + sinon.spy(userSync, 'registerSync'); + }); + + afterEach(function () { + userSync.registerSync.restore(); + }); + + const bidsWithMediaTypes = [{ + 'bidder': 'openx', + 'mediaTypes': {video: {}}, + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain', + 'video': { + 'url': 'abc.com' + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' + }]; + const bidsWithMediaType = [{ 'bidder': 'openx', 'mediaType': 'video', 'params': { 'unit': '12345678', 'delDomain': 'test-del-domain', 'video': { - 'url': 'abc.com', + 'url': 'abc.com' } }, 'adUnitCode': 'adunit-code', @@ -368,22 +459,28 @@ describe('OpenxAdapter', () => { 'auctionId': '1d1a030790a475', 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' }]; - const bidRequest = { + const bidRequestsWithMediaTypes = { method: 'GET', - url: 'url', + url: '//openx-d.openx.net/v/1.0/avjp', data: {}, - payload: {'bid': bids[0], 'startTime': new Date()} + payload: {'bid': bidsWithMediaTypes[0], 'startTime': new Date()} + }; + const bidRequestsWithMediaType = { + method: 'GET', + url: '//openx-d.openx.net/v/1.0/avjp', + data: {}, + payload: {'bid': bidsWithMediaType[0], 'startTime': new Date()} }; const bidResponse = { 'pub_rev': '1', 'width': '640', 'height': '480', 'adid': '5678', - 'vastUrl': 'http://testvast.com', + 'vastUrl': 'http://testvast.com/vastpath?colo=http://test-colo.com&ph=test-ph&ts=test-ts', 'pixels': 'http://testpixels.net' }; - it('should return correct bid response', () => { + it('should return correct bid response with MediaTypes', () => { const expectedResponse = [ { 'requestId': '30b31c1838de1e', @@ -400,14 +497,53 @@ describe('OpenxAdapter', () => { } ]; - const result = spec.interpretResponse({body: bidResponse}, bidRequest); + const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); expect(JSON.stringify(Object.keys(result[0]).sort())).to.eql(JSON.stringify(Object.keys(expectedResponse[0]).sort())); }); - it('handles nobid responses', () => { + it('should return correct bid response with MediaType', () => { + const expectedResponse = [ + { + 'requestId': '30b31c1838de1e', + 'bidderCode': 'openx', + 'cpm': 1, + 'width': '640', + 'height': '480', + 'mediaType': 'video', + 'creativeId': '5678', + 'vastUrl': 'http://testvast.com', + 'ttl': 300, + 'netRevenue': true, + 'currency': 'USD' + } + ]; + + const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaType); + expect(JSON.stringify(Object.keys(result[0]).sort())).to.eql(JSON.stringify(Object.keys(expectedResponse[0]).sort())); + }); + + it('should handle nobid responses for bidRequests with MediaTypes', () => { const bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; - const result = spec.interpretResponse({body: bidResponse}, bidRequest); + const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); expect(result.length).to.equal(0); }); + + it('should handle nobid responses for bidRequests with MediaType', () => { + const bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; + const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaType); + expect(result.length).to.equal(0); + }); + + it('should register a user sync', () => { + spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); + sinon.assert.calledWith(userSync.registerSync, 'iframe', 'openx', 'http://testpixels.net'); + }); + + it('should register a beacon', () => { + spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); + sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/^\/\/test-colo\.com/)) + sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/ph=test-ph/)); + sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/ts=test-ts/)); + }); }); }); From 95bd54d8bb083b2b78e8f9e549a32281fd020886 Mon Sep 17 00:00:00 2001 From: Stephen Johnston Date: Thu, 12 Apr 2018 13:41:18 -0400 Subject: [PATCH 0253/1594] Update pubwiseAnalyticsAdapter.js (#2379) --- modules/pubwiseAnalyticsAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubwiseAnalyticsAdapter.js b/modules/pubwiseAnalyticsAdapter.js index 69227cd154a..33c8483d16b 100644 --- a/modules/pubwiseAnalyticsAdapter.js +++ b/modules/pubwiseAnalyticsAdapter.js @@ -88,9 +88,9 @@ function sendEvent(eventType, data) { debug: configOptions.debug ? 1 : 0, }; + dataBag = enrichWithMetrics(dataBag); // for certain events, track additional info if (eventType == CONSTANTS.EVENTS.AUCTION_INIT) { - dataBag = enrichWithMetrics(dataBag); dataBag = enrichWithUTM(dataBag); } From 9303d578aa33246043ad41c11d67c81c88bdb527 Mon Sep 17 00:00:00 2001 From: Aparna Rao-Hegde Date: Thu, 12 Apr 2018 15:38:42 -0400 Subject: [PATCH 0254/1594] 33Across: Complete user sync implementation (#2334) * Adding 33across adapter * Updated per code review from Prebid. See https://github.com/prebid/Prebid.js/pull/1805#pullrequestreview-75218582 * Added support for test bid and crid. * Removed ability to set test url via params * Incorporated changes requested in https://github.com/prebid/Prebid.js/issues/1855 to fix usage of deprecated method * Reverted hack to karma conf maker to make unit tests pass with --file option * Enabling POST withCredentials to send userSync cookies --- modules/33acrossBidAdapter.js | 2 +- test/spec/modules/33acrossBidAdapter_spec.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 93fd685ae15..15792240fdd 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -55,7 +55,7 @@ function _createServerRequest(bidRequest) { */ const options = { contentType: 'application/json', - withCredentials: false + withCredentials: true }; // Allow the ability to configure the HB endpoint for testing purposes. const ttxSettings = config.getConfig('ttxSettings'); diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 9c318e4bdd5..ff701d265a7 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -146,7 +146,7 @@ describe('33acrossBidAdapter:', function () { 'data': JSON.stringify(ttxRequest), 'options': { 'contentType': 'application/json', - 'withCredentials': false + 'withCredentials': true } } const builtServerRequests = buildRequests(this.bidRequests); @@ -194,7 +194,7 @@ describe('33acrossBidAdapter:', function () { data: JSON.stringify(ttxRequest), options: { contentType: 'application/json', - withCredentials: false + withCredentials: true } }; @@ -244,7 +244,7 @@ describe('33acrossBidAdapter:', function () { data: JSON.stringify(ttxRequest), options: { contentType: 'application/json', - withCredentials: false + withCredentials: true } }; From c8055074e4b0237ea67ad88bea6986031e0efecf Mon Sep 17 00:00:00 2001 From: Yuriy Tyukhnin Date: Fri, 13 Apr 2018 16:04:16 +0200 Subject: [PATCH 0255/1594] Smart: New parameters for in-app ads (#2325) * Fix bug when multi bids * New fields: bundleId, uid, appName * Uid fix according to its type * Params names changed for consistency * adapter docs update --- modules/smartadserverBidAdapter.js | 3 ++ modules/smartadserverBidAdapter.md | 5 +- .../modules/smartadserverBidAdapter_spec.js | 47 ++++++++++++++++--- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index d589dc74024..02ebbbe06ae 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -39,6 +39,9 @@ export const spec = { currencyCode: config.getConfig('currency.adServerCurrency'), bidfloor: bid.params.bidfloor || 0.0, targeting: bid.params.target && bid.params.target != '' ? bid.params.target : undefined, + buid: bid.params.buId && bid.params.buId != '' ? bid.params.buId : undefined, + appname: bid.params.appName && bid.params.appName != '' ? bid.params.appName : undefined, + ckid: bid.params.ckId || 0, tagId: bid.adUnitCode, sizes: bid.sizes.map(size => ({ w: size[0], diff --git a/modules/smartadserverBidAdapter.md b/modules/smartadserverBidAdapter.md index f904aa40b3a..679bead441d 100644 --- a/modules/smartadserverBidAdapter.md +++ b/modules/smartadserverBidAdapter.md @@ -26,7 +26,10 @@ Please reach out to your Technical account manager for more information. domain: 'http://prg.smartadserver.com', siteId: 207435, pageId: 896536, - formatId: 62913 + formatId: 62913, + buId: "com.smartadserver.android.dashboard", // optional + ckId: 1234567890123456789, // optional + appName: "Smart AdServer Preview" // optional } } ] diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 201c5dd5cc9..82c2098f234 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -12,6 +12,7 @@ import { } from 'src/config'; import * as utils from 'src/utils'; +// Default params with optional ones describe('Smart bid adapter tests', () => { var DEFAULT_PARAMS = [{ adUnitCode: 'sas_42', @@ -27,12 +28,16 @@ describe('Smart bid adapter tests', () => { pageId: '5678', formatId: '90', target: 'test=prebid', - bidfloor: 0.420 + bidfloor: 0.420, + buId: '7569', + appName: 'Mozilla', + ckId: 42 }, requestId: 'efgh5678', transactionId: 'zsfgzzg' }]; + // Default params without optional ones var DEFAULT_PARAMS_WO_OPTIONAL = [{ adUnitCode: 'sas_42', bidId: 'abcd1234', @@ -89,6 +94,9 @@ describe('Smart bid adapter tests', () => { expect(requestContent.sizes[1]).to.have.property('h').and.to.equal(200); expect(requestContent).to.have.property('pageDomain').and.to.equal(utils.getTopWindowUrl()); expect(requestContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; + expect(requestContent).to.have.property('buid').and.to.equal('7569'); + expect(requestContent).to.have.property('appname').and.to.equal('Mozilla'); + expect(requestContent).to.have.property('ckid').and.to.equal(42); }); it('Verify parse response', () => { @@ -129,24 +137,51 @@ describe('Smart bid adapter tests', () => { })).to.equal(false); expect(spec.isBidRequestValid({ params: { - pageid: 123 + pageId: 123 } })).to.equal(false); expect(spec.isBidRequestValid({ params: { - siteid: 123 + siteId: 123 } })).to.equal(false); expect(spec.isBidRequestValid({ params: { - formatid: 123, - pageid: 234 + formatId: 123, + pageId: 234 } })).to.equal(false); expect(spec.isBidRequestValid({ params: { domain: 'www.test.com', - pageid: 234 + pageId: 234 + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + domain: 'www.test.com', + formatId: 123, + siteId: 456, + pageId: 234 + } + })).to.equal(true); + expect(spec.isBidRequestValid({ + params: { + domain: 'www.test.com', + formatId: 123, + siteId: 456, + pageId: 234, + buId: 789, + appName: 'Mozilla' + } + })).to.equal(true); + expect(spec.isBidRequestValid({ + params: { + domain: 'www.test.com', + formatId: 123, + pageId: 234, + buId: 789, + appName: 'Mozilla' } })).to.equal(false); }); From f5900ff669c75ab11379b1c1991e052ab57b498c Mon Sep 17 00:00:00 2001 From: SARA-HB <36306795+SARA-HB@users.noreply.github.com> Date: Fri, 13 Apr 2018 18:29:57 +0300 Subject: [PATCH 0256/1594] Add SARA-HB Bid Adapter (#2172) * Add SARA-HB Bid Adapter * Update SARA-HB bid adapter --- modules/saraBidAdapter.js | 141 +++++++++++ modules/saraBidAdapter.md | 40 ++++ test/spec/modules/saraBidAdapter_spec.js | 293 +++++++++++++++++++++++ 3 files changed, 474 insertions(+) create mode 100644 modules/saraBidAdapter.js create mode 100755 modules/saraBidAdapter.md create mode 100644 test/spec/modules/saraBidAdapter_spec.js diff --git a/modules/saraBidAdapter.js b/modules/saraBidAdapter.js new file mode 100644 index 00000000000..233fba65cc7 --- /dev/null +++ b/modules/saraBidAdapter.js @@ -0,0 +1,141 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'sara'; +const ENDPOINT_URL = '//ad.sara.media/hb'; +const ADAPTER_SYNC_URL = '//ad.sara.media/push_sync'; +const TIME_TO_LIVE = 360; +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', + noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', + emptyUids: 'Uids should be not empty', + emptySeatbid: 'Seatbid array from response has empty item', + emptyResponse: 'Response is empty', + hasEmptySeatbidArray: 'Response has empty seatbid array', + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' +}; + +/** + * Dentsu Aegis Network Marketplace Bid Adapter. + * Contact: niels@baarsma.net + * + */ +export const spec = { + code: BIDDER_CODE, + + isBidRequestValid: function(bid) { + return !!bid.params.uid; + }, + + buildRequests: function(validBidRequests) { + const auids = []; + const bidsMap = {}; + const bids = validBidRequests || []; + let priceType = 'net'; + let reqId; + + bids.forEach(bid => { + if (bid.params.priceType === 'gross') { + priceType = 'gross'; + } + if (!bidsMap[bid.params.uid]) { + bidsMap[bid.params.uid] = [bid]; + auids.push(bid.params.uid); + } else { + bidsMap[bid.params.uid].push(bid); + } + reqId = bid.bidderRequestId; + }); + + const payload = { + u: utils.getTopWindowUrl(), + pt: priceType, + auids: auids.join(','), + r: reqId, + }; + + return { + method: 'GET', + url: ENDPOINT_URL, + data: utils.parseQueryStringParameters(payload).replace(/\&$/, ''), + bidsMap: bidsMap, + }; + }, + + interpretResponse: function(serverResponse, bidRequest) { + serverResponse = serverResponse && serverResponse.body + const bidResponses = []; + const bidsMap = bidRequest.bidsMap; + const priceType = bidRequest.data.pt; + + let errorMessage; + + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } + + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses); + }); + } + if (errorMessage) utils.logError(errorMessage); + return bidResponses; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: ADAPTER_SYNC_URL + }]; + } + } +} + +function _getBidFromResponse(respItem) { + if (!respItem) { + utils.logError(LOG_ERROR_MESS.emptySeatbid); + } else if (!respItem.bid) { + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + } else if (!respItem.bid[0]) { + utils.logError(LOG_ERROR_MESS.noBid); + } + return respItem && respItem.bid && respItem.bid[0]; +} + +function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { + if (!serverBid) return; + let errorMessage; + if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + awaitingBids.forEach(bid => { + const bidResponse = { + requestId: bid.bidId, // bid.bidderRequestId, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, // bid.bidId, + currency: 'USD', + netRevenue: priceType !== 'gross', + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid + }; + bidResponses.push(bidResponse); + }); + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } + if (errorMessage) { + utils.logError(errorMessage); + } +} + +registerBidder(spec); diff --git a/modules/saraBidAdapter.md b/modules/saraBidAdapter.md new file mode 100755 index 00000000000..65572528181 --- /dev/null +++ b/modules/saraBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +Module Name: Sara Bidder Adapter +Module Type: Bidder Adapter +Maintainer: github@sara.media + +# Description + +Module that connects to Sara demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "sara", + params: { + uid: '5', + priceType: 'gross' // by default is 'net' + } + } + ] + },{ + code: 'test-div', + sizes: [[728, 90]], + bids: [ + { + bidder: "sara", + params: { + uid: 6, + priceType: 'gross' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/saraBidAdapter_spec.js b/test/spec/modules/saraBidAdapter_spec.js new file mode 100644 index 00000000000..1b5d75170ae --- /dev/null +++ b/test/spec/modules/saraBidAdapter_spec.js @@ -0,0 +1,293 @@ +import { expect } from 'chai'; +import { spec } from 'modules/saraBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('Sara Adapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'sara', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'uid': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + function parseRequest(url) { + const res = {}; + url.split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } + let bidRequests = [ + { + 'bidder': 'sara', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'sara', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'sara', + 'params': { + 'uid': '6' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '42dbe3a7168a6a', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should attach valid params to the tag', () => { + const request = spec.buildRequests([bidRequests[0]]); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5'); + }); + + it('auids must not be duplicated', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5,6'); + }); + + it('pt parameter must be "gross" if params.priceType === "gross"', () => { + bidRequests[1].params.priceType = 'gross'; + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'gross'); + expect(payload).to.have.property('auids', '5,6'); + delete bidRequests[1].params.priceType; + }); + + it('pt parameter must be "net" or "gross"', () => { + bidRequests[1].params.priceType = 'some'; + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5,6'); + delete bidRequests[1].params.priceType; + }); + }); + + describe('interpretResponse', () => { + const responses = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 6, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + undefined, + {'bid': [], 'seat': '1'}, + {'seat': '1'}, + ]; + + it('should get correct bid response', () => { + const bidRequests = [ + { + 'bidder': 'sara', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should get correct multi bid response', () => { + const bidRequests = [ + { + 'bidder': 'sara', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71a5b', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'sara', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dff80cc4ee346', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'sara', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '5703af74d0472a', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '300bfeb0d71a5b', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '5703af74d0472a', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 5, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 2
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('handles wrong and nobid responses', () => { + const bidRequests = [ + { + 'bidder': 'sara', + 'params': { + 'uid': '6' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d7190gf', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'sara', + 'params': { + 'uid': '7' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71321', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'sara', + 'params': { + 'uid': '8' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '300bfeb0d7183bb', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + } + ]; + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + expect(result.length).to.equal(0); + }); + }); +}); From 055d3fb76eff338d7fe2de8c404b7e3d845675c5 Mon Sep 17 00:00:00 2001 From: Anthony Jose Bruscantini Date: Fri, 13 Apr 2018 08:33:52 -0700 Subject: [PATCH 0257/1594] ADSS-281 implement getUserSyncs and putting checks for empty ad server response (#2377) --- modules/gumgumBidAdapter.js | 38 ++++++++++++++++++++-- test/spec/modules/gumgumBidAdapter_spec.js | 22 +++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index fc36e18e3ac..0b7a4223063 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -148,6 +148,16 @@ function buildRequests (validBidRequests) { function interpretResponse (serverResponse, bidRequest) { const bidResponses = [] const serverResponseBody = serverResponse.body + const defaultResponse = { + ad: { + price: 0, + id: 0, + markup: '' + }, + pag: { + pvid: 0 + } + } const { ad: { price: cpm, @@ -158,7 +168,7 @@ function interpretResponse (serverResponse, bidRequest) { pag: { pvid } - } = serverResponseBody + } = Object.assign(defaultResponse, serverResponseBody) let isTestUnit = (bidRequest.data && bidRequest.data.pi === 3 && bidRequest.data.si === 9) let [width, height] = utils.parseSizesInput(bidRequest.sizes)[0].split('x') @@ -183,11 +193,35 @@ function interpretResponse (serverResponse, bidRequest) { 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. + */ +function getUserSyncs (syncOptions, serverResponses) { + const responses = serverResponses.map((response) => { + return (response.body && response.body.pxs && response.body.pxs.scr) || [] + }) + const userSyncs = responses.reduce(function (usersyncs, response) { + return usersyncs.concat(response) + }, []) + const syncs = userSyncs.map((sync) => { + return { + type: sync.t === 'f' ? 'iframe' : 'image', + url: sync.u + } + }) + return syncs; +} + export const spec = { code: BIDDER_CODE, aliases: ALIAS_BIDDER_CODE, isBidRequestValid, buildRequests, - interpretResponse + interpretResponse, + getUserSyncs } registerBidder(spec) diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 30627d4d12d..276972a163f 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -135,4 +135,26 @@ describe('gumgumAdapter', () => { expect(result.length).to.equal(0); }); }) + describe('getUserSyncs', () => { + const syncOptions = { + 'iframeEnabled': 'true' + } + const response = { + 'pxs': { + 'scr': [ + { + 't': 'i', + 'u': 'https://c.gumgum.com/images/pixel.gif' + }, + { + 't': 'f', + 'u': 'https://www.nytimes.com/' + } + ] + } + } + let result = spec.getUserSyncs(syncOptions, [{ body: response }]); + expect(result[0].type).to.equal('image') + expect(result[1].type).to.equal('iframe') + }) }); From 74559766971623429e008861d8cacd4d8a0f1baa Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Fri, 13 Apr 2018 13:34:27 -0400 Subject: [PATCH 0258/1594] Sonobi Video Support (#2297) * added support for setting vastUrl * removed unsed param * some refactoring around detecting the media type and forming the creative * changed let to const * added ref param to sbi.js. fixed lint issues * added video test params to sonobi readme. * sbi_ct only comes back in a trinity response if the creative is a video. So only check if it is a video if sbi_ct exists --- modules/sonobiBidAdapter.js | 54 +++++++++--- modules/sonobiBidAdapter.md | 38 +++++++++ test/spec/modules/sonobiBidAdapter_spec.js | 99 ++++++++++++++++------ 3 files changed, 153 insertions(+), 38 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index fb5d9a7f56f..042aaf7cd14 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -1,6 +1,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { getTopWindowLocation, parseSizesInput } from 'src/utils'; import * as utils from '../src/utils'; +import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; @@ -8,7 +9,7 @@ const PAGEVIEW_ID = utils.generateUUID(); export const spec = { code: BIDDER_CODE, - + supportedMediaTypes: [BANNER, VIDEO], /** * Determines whether or not the given bid request is valid. * @@ -25,7 +26,7 @@ export const spec = { */ buildRequests: (validBidRequests) => { const bids = validBidRequests.map(bid => { - let slotIdentifier = _validateSlot(bid) + let slotIdentifier = _validateSlot(bid); if (/^[\/]?[\d]+[[\/].+[\/]?]?$/.test(slotIdentifier)) { slotIdentifier = slotIdentifier.charAt(0) === '/' ? slotIdentifier : '/' + slotIdentifier return { @@ -58,16 +59,18 @@ export const spec = { method: 'GET', url: STR_ENDPOINT, withCredentials: true, - data: payload + data: payload, + bidderRequests: validBidRequests }; }, /** * Unpack the response from the server into a list of bids. * * @param {*} serverResponse A successful response from the server. + * @param {*} bidderRequests - Info describing the request to the server. * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse: (serverResponse) => { + interpretResponse: (serverResponse, { bidderRequests }) => { const bidResponse = serverResponse.body; const bidsReturned = []; @@ -76,25 +79,41 @@ export const spec = { } Object.keys(bidResponse.slots).forEach(slot => { + const bidId = _getBidIdFromTrinityKey(slot); + const bidRequest = bidderRequests.find(bidReqest => bidReqest.bidId === bidId); + const videoMediaType = utils.deepAccess(bidRequest, 'mediaTypes.video'); + const mediaType = bidRequest.mediaType || (videoMediaType ? 'video' : null); + const createCreative = _creative(mediaType); const bid = bidResponse.slots[slot]; - if (bid.sbi_aid && bid.sbi_mouse && bid.sbi_size) { + const [ + width = 1, + height = 1 + ] = bid.sbi_size.split('x'); const bids = { - requestId: slot.split('|').slice(-1)[0], + requestId: bidId, cpm: Number(bid.sbi_mouse), - width: Number(bid.sbi_size.split('x')[0]) || 1, - height: Number(bid.sbi_size.split('x')[1]) || 1, - ad: _creative(bidResponse.sbi_dc, bid.sbi_aid), + width: Number(width), + height: Number(height), + ad: createCreative(bidResponse.sbi_dc, bid.sbi_aid), ttl: 500, creativeId: bid.sbi_aid, netRevenue: true, - currency: 'USD', + currency: 'USD' }; if (bid.sbi_dozer) { bids.dealId = bid.sbi_dozer; } + const creativeType = bid.sbi_ct; + if (creativeType && (creativeType === 'video' || creativeType === 'outstream')) { + bids.mediaType = 'video'; + bids.vastUrl = createCreative(bidResponse.sbi_dc, bid.sbi_aid); + delete bids.ad; + delete bids.width; + delete bids.height; + } bidsReturned.push(bids); } }); @@ -138,9 +157,20 @@ function _validateFloor (bid) { return ''; } -function _creative (sbi_dc, sbi_aid) { - const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null'; +const _creative = (mediaType) => (sbi_dc, sbi_aid) => { + if (mediaType === 'video') { + return _videoCreative(sbi_dc, sbi_aid) + } + const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null' + '&ref=' + getTopWindowLocation().host; return ''; } +function _videoCreative(sbi_dc, sbi_aid) { + return `https://${sbi_dc}apex.go.sonobi.com/vast.xml?vid=${sbi_aid}&ref=${getTopWindowLocation().host}` +} + +function _getBidIdFromTrinityKey (key) { + return key.split('|').slice(-1)[0] +} + registerBidder(spec); diff --git a/modules/sonobiBidAdapter.md b/modules/sonobiBidAdapter.md index 91e4a0e2b2e..cc4dd8733d4 100644 --- a/modules/sonobiBidAdapter.md +++ b/modules/sonobiBidAdapter.md @@ -30,3 +30,41 @@ Module that connects to Sonobi's demand sources. } ]; ``` + +# Video Test Parameters +``` + var videoAdUnit = { + code: 'adUnit_af', + sizes: [640,480], + mediaTypes: { + video: {context: 'instream'} + }, + bids: [ + { + bidder: 'sonobi', + params: { + placement_id: '92e95368e86639dbd86d', + } + } + ] + }; +``` + +Example bidsBackHandler for video bids +``` +pbjs.requestBids({ + timeout : 700, + bidsBackHandler : function(bids) { + var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ + adUnit: videoAdUnit, + params: { + cust_params: { + hb_vid: bids.adUnit_af.bids[0].creativeId + }, + iu: '/7780971/apex_jwplayer_video' + } + }); + invokeVideoPlayer(videoUrl); + } + }); +``` diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 6a44c817d0b..4fd5c13e65c 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -138,6 +138,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.s).not.to.be.empty expect(bidRequests.data.pv).to.equal(bidRequestsPageViewID.data.pv) expect(bidRequests.data.hfa).to.not.exist + expect(bidRequests.bidderRequests).to.eql(bidRequest); }) it('should return a properly formatted request with hfa', () => { @@ -153,23 +154,66 @@ describe('SonobiBidAdapter', () => { }) describe('.interpretResponse', () => { + const bidRequests = { + 'method': 'GET', + 'url': 'https://apex.go.sonobi.com/trinity.json', + 'withCredentials': true, + 'data': { + 'key_maker': '{"30b31c1838de1f":"1a2b3c4d5e6f1a2b3c4d|300x250,300x600|f=1.25","/7780971/sparks_prebid_LB|30b31c1838de1e":"300x250,300x600"}', 'ref': 'localhost:9876', 's': '2474372d-c0ff-4f46-aef4-a173058403d9', 'pv': 'c9cfc207-cd83-4a01-b591-8bb29389d4b0' + }, + 'bidderRequests': [ + { + 'bidder': 'sonobi', + 'params': { + 'ad_unit': '/7780971/sparks_prebid_LB', + 'sizes': [[300, 250], [300, 600]], + 'floor': '1.25' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1f' + }, + { + 'bidder': 'sonobi', + 'params': { + 'placement_id': '1a2b3c4d5e6f1a2b3c4d', + 'sizes': [[300, 250], [300, 600]] + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[120, 600], [300, 600], [160, 600]], + 'bidId': '30b31c1838de1e', + 'mediaType': 'video' + }, + { + 'bidder': 'sonobi', + 'params': { + 'ad_unit': '/7780971/sparks_prebid_LB', + 'sizes': [[300, 250], [300, 600]] + }, + 'adUnitCode': 'adunit-code-3', + 'sizes': [[120, 600], [300, 600], [160, 600]], + 'bidId': '30b31c1838de1g' + } + ] + }; + let bidResponse = { 'body': { 'slots': { - '/7780971/sparks_prebid_LB|30b31c1838de1d': { + '/7780971/sparks_prebid_LB|30b31c1838de1f': { 'sbi_size': '300x600', 'sbi_apoc': 'remnant', 'sbi_aid': '30292e432662bd5f86d90774b944b039', 'sbi_mouse': 1.07, }, - '30b31c1838de1f': { + '30b31c1838de1e': { 'sbi_size': '300x250', 'sbi_apoc': 'remnant', 'sbi_aid': '30292e432662bd5f86d90774b944b038', 'sbi_mouse': 1.25, 'sbi_dozer': 'dozerkey', }, - '30b31c1838de1e': {}, + '/7780971/sparks_prebid_LB|30b31c1838de1g': {}, }, 'sbi_dc': 'mco-1-', 'sbi_px': [{ @@ -182,31 +226,34 @@ describe('SonobiBidAdapter', () => { } }; - let prebidResponse = [{ - 'requestId': '30b31c1838de1d', - 'cpm': 1.07, - 'width': 300, - 'height': 600, - 'ad': '', - 'ttl': 500, - 'creativeId': '30292e432662bd5f86d90774b944b039', - 'netRevenue': true, - 'currency': 'USD' - }, { - 'requestId': '30b31c1838de1f', - 'cpm': 1.25, - 'width': 300, - 'height': 250, - 'ad': '', - 'ttl': 500, - 'creativeId': '30292e432662bd5f86d90774b944b038', - 'netRevenue': true, - 'currency': 'USD', - 'dealId': 'dozerkey' - }]; + let prebidResponse = [ + { + 'requestId': '30b31c1838de1f', + 'cpm': 1.07, + 'width': 300, + 'height': 600, + 'ad': '', + 'ttl': 500, + 'creativeId': '30292e432662bd5f86d90774b944b039', + 'netRevenue': true, + 'currency': 'USD' + }, + { + 'requestId': '30b31c1838de1e', + 'cpm': 1.25, + 'width': 300, + 'height': 250, + 'ad': 'https://mco-1-apex.go.sonobi.com/vast.xml?vid=30292e432662bd5f86d90774b944b038&ref=localhost:9876', + 'ttl': 500, + 'creativeId': '30292e432662bd5f86d90774b944b038', + 'netRevenue': true, + 'currency': 'USD', + 'dealId': 'dozerkey' + } + ]; it('should map bidResponse to prebidResponse', () => { - const response = spec.interpretResponse(bidResponse); + const response = spec.interpretResponse(bidResponse, bidRequests); expect(response).to.deep.equal(prebidResponse); }) }) From 335f59a3a377ec92371a34f2fe587accf11fda33 Mon Sep 17 00:00:00 2001 From: Pupis Date: Fri, 13 Apr 2018 22:32:59 +0300 Subject: [PATCH 0259/1594] Dynamic priceType at adform adapter (#2384) * bid response adId same as bidId * test * update adform bid adapter * update unit tests * Added adform adapter description file * updated tests * Another tests update * Add auctionId * Update adapter for auctionId * add auctionId to adformBidAdapter * Final updates to fit 1.0 version * update docs and integration example * Do not mutate original validBidRequests * use atob and btoa instead of custom made module * Renaming one query string parameter * XDomainRequest.send exception fix (#1942) * Added YIELDONE Bid Adapter for Prebid.js 1.0 (#1900) * Added YIELDONE Bid Adapter for Prebid.js 1.0 * Update yieldoneBidAdapter.md change placementId to 44082 * Changed to get size from bid.sizes * fix sizes array * Add user-facing docs reminder to PR template (#1956) * allow non-mappable sizes to be passed and used in rubicon adapter (#1893) * Typo correction of YIELDONE md file (#1954) * Added YIELDONE Bid Adapter for Prebid.js 1.0 * Update yieldoneBidAdapter.md change placementId to 44082 * Changed to get size from bid.sizes * fix sizes array * Fix a typo * Serverbid bid adapter: update alias config (#1963) * use auctionId instead of requestId (#1968) * Add freewheel ssp bidder adapter for prebid 1.0 (#1793) * add stickyadsTV bidder adapter * init unit test file * ad some unit tests * fix unit test on ad format with parameters * add some unit tests * add unit tests on getBid method * add some test cases in unit tests * minor fix on component id tag. * remove adapters-sticky.json test file * use top most accessible window instead of window.top * Pass in the bid request in the createBid call. * use top most accessible window instead of window.top * add unit tests * update unit tests * fix unit test. * fix CI build * add alias freewheel-ssp * update unit tests on bidderCode value * fix component id values and add unit tests * allws to use any outstream format. * fix ASLoader on futur outstream format versions * minor: fix code format. * update unit tests * minor fix code format * minor: add missing new line at eof * replace StickyAdsTVAdapter by freewheel ssp bd adapter (for prebid 1.0) * remove old stickyadstv unittest spec. * fix server response parsing if sent as object with 'body' field * use the vastXml field for video mediatype * add user sync pixel in freewheel ssp adapter * remove all console log calls (replaced using util helper) * remove useless bidderCode (automatically added by the bidderFactory) * Return the SYNC pixel to be added in the page by Prebid.js * remove instance level properties to enable concurrent bids with the same adapter instance. * fix the request apss through and corresponding unit tests * fix 'freeheelssp' typo * + fixed endpoint request data property names - width to w and height to h (#1955) + updated unit test for the adapter to comply with the property name changes * Added iQM Bid Adapter for Prebid.js 1.0 (#1880) * Added iQM Bid Adapter for Prebid.js 1.0 * Modified URL from http to https * Removed geo function which was fetching user location. * Remove stray console.log (#1975) * Remove duplicate request id and fix empty response from getHighesCpmBids, getAdserverTargeting (#1970) * Removed requestId and added auctionId * Updated module fixtures to use auctionId and not requestId * remove request id from external bid object and fix bug for empty result in public api * use auctionId instead of requestId * fixed lint errors * [Add BidAdapter] rxrtb adapter for Perbid.js 1.0 (#1950) * Add: rxrtb prebidAdapter * Update: params for test * Update: code format * Update: code format * Update: code format * ServerBid Server BidAdapter (#1819) * ServerBid Server BidAdapter Allow S2S configuration with ServerBid. * Updates to meet 1.0 callBids/config changes. * Fix linting issues. * added hb_source to default keys (#1969) * added hb_source * dropped function to add hb_source since it is now default key * fixed lint error * Prebid 1.1.0 Release * Increment pre version * S2s defaults fix in serverbidServerBidAdapter (#1986) * removed s2s defaults * start timestamp was missing on s2s requests * remove hardcoded localhost port for tests (#1988) * Fixes unit tests in browsers other than chrome (#1987) * Fixes unit tests in browsers other than chrome * fixed lint errors * Prebid 1.1.1 Release * Add note about docs needed before merge (#1959) * Add note about docs needed before merge * Update pr_review.md * Update pr_review.md * Update pr_review.md * Adding optional width and height to display parameters (#1998) * adding optional size * no tabs * TrustX adapter update (#1979) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Serverbid Bid Adapter: Add new ad sizes (#1983) * Added dynamic ttl property for One Display and One Mobile. (#2004) * pin gulp-connect at non-broken version (#2008) * pin gulp-connect at non-broken version * updated yarn.lock to specify pinned gulp-connect * Gjirafa Bidder Adapter (#1944) * Added Gjirafa adapter * Add gjirafa adapter unit test * adapter update * New line * Requested changes * change hello_world.html to one bid * change hello_world.html to one bid * Dropping changes in gitignore and hello_world example * hello_world changes * Drop hello_world and gitignore * multiformat size validation checks (#1964) * initial commit for multiformat size validation checks * adding unit tests and changes to checkBidRequestSizes function * updates to appnexusBidAdapter * Upgrade Admixer adapter for Prebid 1.0 (#1755) * Migrating to Prebid 1.0 * Migrating to Prebid 1.0 * Fix spec * Add NasmediaAdmixer adapter for Perbid.js 1.0 (#1937) * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * Added price type global param, changed default value to gross. * Updated tests * some console.logs * Keep the same names * Update description --- modules/adformBidAdapter.js | 8 ++++---- modules/adformBidAdapter.md | 2 +- test/spec/modules/adformBidAdapter_spec.js | 16 ++++++++++++---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index 9754653cfe4..1da6042f63a 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -13,13 +13,13 @@ export const spec = { buildRequests: function (validBidRequests) { var i, l, j, k, bid, _key, _value, reqParams; var request = []; - var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ] ]; - var netRevenue = 'net'; + var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ], [ 'pt', null ] ]; + var netRevenue = 'gross'; var bids = JSON.parse(JSON.stringify(validBidRequests)); for (i = 0, l = bids.length; i < l; i++) { bid = bids[i]; - if (bid.params.priceType === 'gross') { - netRevenue = 'gross'; + if (bid.params.priceType === 'net') { + bid.params.pt = netRevenue = 'net'; } for (j = 0, k = globalParams.length; j < k; j++) { _key = globalParams[j][0]; diff --git a/modules/adformBidAdapter.md b/modules/adformBidAdapter.md index b2f67273a18..10ebec37e08 100644 --- a/modules/adformBidAdapter.md +++ b/modules/adformBidAdapter.md @@ -21,7 +21,7 @@ Banner and video formats are supported. params: { adxDomain: 'adx.adform.net', //optional mid: '292063', - priceType: 'gross' // default is 'net' + priceType: 'net' // default is 'gross' } } ] diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index a330f18e685..f3aa735be00 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -62,8 +62,7 @@ describe('Adform adapter', () => { { mid: '2', someVar: 'someValue', - transactionId: '5f33781f-9552-4iuy', - priceType: 'gross' + transactionId: '5f33781f-9552-4iuy' }, { mid: '3', @@ -166,12 +165,20 @@ describe('Adform adapter', () => { assert.equal(result[i].mediaType, expected[i]); } }); + + it('should set default netRevenue as gross', () => { + bidRequest.netRevenue = 'gross'; + const result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].netRevenue, false); + } + }); }); beforeEach(() => { let sizes = [[250, 300], [300, 250], [300, 600]]; let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; - let params = [{ mid: 1, url: 'some// there' }, {adxDomain: null, mid: 2, someVar: 'someValue', priceType: 'gross'}, { adxDomain: null, mid: 3, pdom: 'home' }]; + let params = [{ mid: 1, url: 'some// there' }, {adxDomain: null, mid: 2, someVar: 'someValue', pt: 'gross'}, { adxDomain: null, mid: 3, pdom: 'home' }]; bids = [ { adUnitCode: placementCode[0], @@ -285,7 +292,8 @@ describe('Adform adapter', () => { bidder: 'adform', bids: bids, method: 'GET', - url: 'url' + url: 'url', + netRevenue: 'net' }; }); }); From 2ed32dbeddc56729e2c38ec9ab0d1cf021a48e86 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 13 Apr 2018 14:13:56 -0600 Subject: [PATCH 0260/1594] fiix size in prebidserver (#2364) --- modules/prebidServerBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 06e5cff6503..e12f569b3b2 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -442,7 +442,7 @@ const OPEN_RTB_PROTOCOL = { let banner; // default to banner if mediaTypes isn't defined if (utils.isEmpty(adUnit.mediaTypes)) { - const sizeObjects = adUnit.sizes.map(size => ({ w: size.w, h: size.h })); + const sizeObjects = adUnit.sizes.map(size => ({ w: size[0], h: size[1] })); banner = {format: sizeObjects}; } From 6d2ed31248c0a3eab42fc83d161e59db1e3f4564 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 13 Apr 2018 14:40:21 -0600 Subject: [PATCH 0261/1594] fix sonobi adapter to use polyfilled Object find --- modules/sonobiBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 042aaf7cd14..4db35807edd 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -2,6 +2,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { getTopWindowLocation, parseSizesInput } from 'src/utils'; import * as utils from '../src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; @@ -80,7 +81,7 @@ export const spec = { Object.keys(bidResponse.slots).forEach(slot => { const bidId = _getBidIdFromTrinityKey(slot); - const bidRequest = bidderRequests.find(bidReqest => bidReqest.bidId === bidId); + const bidRequest = find(bidderRequests, bidReqest => bidReqest.bidId === bidId); const videoMediaType = utils.deepAccess(bidRequest, 'mediaTypes.video'); const mediaType = bidRequest.mediaType || (videoMediaType ? 'video' : null); const createCreative = _creative(mediaType); From 49ee97db922e96d37b4e9f9a93522a343b508e1f Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Fri, 13 Apr 2018 16:57:29 -0400 Subject: [PATCH 0262/1594] fixes #2353 - not appending hb_uuid and hb_cache_id (#2363) --- modules/dfpAdServerVideo.js | 37 +++++++++++++--------- src/utils.js | 3 ++ test/spec/modules/dfpAdServerVideo_spec.js | 2 ++ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index cc285ca4aa7..d1c66833104 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -82,22 +82,14 @@ export default function buildDfpVideoUrl(options) { sz: parseSizesInput(adUnit.sizes).join('|'), url: location.href, }; - - const adserverTargeting = (bid && bid.adserverTargeting) || {}; - - const customParams = Object.assign({}, - adserverTargeting, - { hb_uuid: bid && bid.videoCacheKey }, - // hb_uuid will be deprecated and replaced by hb_cache_id - {hb_cache_id: bid && bid.videoCacheKey}, - options.params.cust_params); + const encodedCustomParams = getCustParams(bid, options); const queryParams = Object.assign({}, defaultParamConstants, urlComponents.search, derivedParams, options.params, - { cust_params: encodeURIComponent(formatQS(customParams)) } + { cust_params: encodedCustomParams } ); const descriptionUrl = getDescriptionUrl(bid, options, 'params'); @@ -122,11 +114,7 @@ function buildUrlFromAdserverUrlComponents(components, bid) { const descriptionUrl = getDescriptionUrl(bid, components, 'search'); if (descriptionUrl) { components.search.description_url = descriptionUrl; } - const adserverTargeting = (bid && bid.adserverTargeting) || {}; - const customParams = Object.assign({}, - adserverTargeting, - ); - const encodedCustomParams = encodeURIComponent(formatQS(customParams)); + const encodedCustomParams = getCustParams(bid); components.search.cust_params = (components.search.cust_params) ? components.search.cust_params + '%26' + encodedCustomParams : encodedCustomParams; return buildUrl(components); @@ -151,6 +139,25 @@ function getDescriptionUrl(bid, components, prop) { } } +/** + * Returns the encoded `cust_params` from the bid.adserverTargeting and adds the `hb_uuid`, and `hb_cache_id`. Optionally the options.params.cust_params + * @param {AdapterBidResponse} bid + * @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) { + const adserverTargeting = (bid && bid.adserverTargeting) || {}; + const optCustParams = deepAccess(options, 'params.cust_params'); + let customParams = Object.assign({}, + adserverTargeting, + { hb_uuid: bid && bid.videoCacheKey }, + // hb_uuid will be deprecated and replaced by hb_cache_id + {hb_cache_id: bid && bid.videoCacheKey}, + optCustParams, + ); + return encodeURIComponent(formatQS(customParams)); +} + registerVideoSupport('dfp', { buildVideoUrl: buildDfpVideoUrl }); diff --git a/src/utils.js b/src/utils.js index 701fd37115a..b192cf2fef6 100644 --- a/src/utils.js +++ b/src/utils.js @@ -775,6 +775,9 @@ export function groupBy(xs, key) { * @returns {*} The value found at the specified object path, or undefined if path is not found. */ export function deepAccess(obj, path) { + if (!obj) { + return; + } path = String(path).split('.'); for (let i = 0; i < path.length; i++) { obj = obj[path[i]]; diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index be51953169c..c4a799b0b0a 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -148,6 +148,8 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('hb_adid', 'ad_id'); expect(customParams).to.have.property('section', 'blog'); expect(customParams).to.have.property('mykey', 'myvalue'); + expect(customParams).to.have.property('hb_uuid', 'abc'); + expect(customParams).to.have.property('hb_cache_id', 'abc'); }); it('should not overwrite an existing description_url for object input and cache disabled', () => { From 395ceb15800132e9c488ed7845cb87b38dcdfb56 Mon Sep 17 00:00:00 2001 From: Allan BRUYERE Date: Sat, 14 Apr 2018 01:50:08 +0200 Subject: [PATCH 0263/1594] Add: Vuble Analytics Adapter (#2331) * Add: Vuble Analytics Adapter --- modules/vubleAnalyticsAdapter.js | 258 ++++++++++++++++++ modules/vubleAnalyticsAdapter.md | 23 ++ .../modules/vubleAnalyticsAdapter_spec.js | 122 +++++++++ 3 files changed, 403 insertions(+) create mode 100644 modules/vubleAnalyticsAdapter.js create mode 100644 modules/vubleAnalyticsAdapter.md create mode 100644 test/spec/modules/vubleAnalyticsAdapter_spec.js diff --git a/modules/vubleAnalyticsAdapter.js b/modules/vubleAnalyticsAdapter.js new file mode 100644 index 00000000000..5bd27b1c0de --- /dev/null +++ b/modules/vubleAnalyticsAdapter.js @@ -0,0 +1,258 @@ +/** + * vuble.js - Vuble Prebid Analytics Adapter + */ + +import adapter from 'src/AnalyticsAdapter'; +import adaptermanager from 'src/adaptermanager'; +import CONSTANTS from 'src/constants.json'; +import {ajax} from '../src/ajax'; +import * as utils from '../src/utils'; + +const ANALYTICS_VERSION = '1.0.0'; +const DEFAULT_QUEUE_TIMEOUT = 4000; +const DEFAULT_HOST = 'player.mediabong'; +const analyticsType = 'endpoint'; + +const EVENTS = [ + CONSTANTS.EVENTS.AUCTION_INIT, + CONSTANTS.EVENTS.AUCTION_END, + CONSTANTS.EVENTS.BID_REQUESTED, + CONSTANTS.EVENTS.BID_RESPONSE, + CONSTANTS.EVENTS.BID_WON, + CONSTANTS.EVENTS.BID_TIMEOUT, +]; + +var vubleAnalytics = Object.assign(adapter({ analyticsType: analyticsType, }), + { + track: function({ eventType, args }) { + if (!vubleAnalytics.context) { + return; + } + if (EVENTS.indexOf(eventType) !== -1) { + if (eventType === CONSTANTS.EVENTS.AUCTION_INIT && + vubleAnalytics.context.queue) { + vubleAnalytics.context.queue.init(); + } + + let events = deal[eventType](args); + + if (vubleAnalytics.context.queue) { + vubleAnalytics.context.queue.push(events); + } + if (eventType === CONSTANTS.EVENTS.AUCTION_END) { + sendAll(); + } + } + } + }); + +vubleAnalytics.context = {}; + +vubleAnalytics.originEnableAnalytics = vubleAnalytics.enableAnalytics; + +vubleAnalytics.enableAnalytics = config => { + if (!config.options.pubId) { + utils.logError('The publisher id is not defined. Analytics won\'t work'); + + return; + } + + if (!config.options.host) { + if (!config.options.env) { + utils.logError('The environement is not defined. Analytics won\'t work'); + + return; + } + config.options.host = DEFAULT_HOST + '.' + config.options.env + '/t'; + } + + vubleAnalytics.context = { + host: config.options.host, + pubId: config.options.pubId, + requestTemplate: buildRequestTemplate(config.options.pubId), + queue: new ExpiringQueue( + sendAll, + config.options.queueTimeout || DEFAULT_QUEUE_TIMEOUT + ), + }; + vubleAnalytics.originEnableAnalytics(config); +}; + +adaptermanager.registerAnalyticsAdapter({ + adapter: vubleAnalytics, + code: 'vuble' +}); + +export default vubleAnalytics; + +function sendAll() { + let events = vubleAnalytics.context.queue.popAll(); + if (events.length !== 0) { + let req = Object.assign( + {}, + vubleAnalytics.context.requestTemplate, + {rtb: events} + ); + ajax( + `//${vubleAnalytics.context.host}/rtb.php`, + undefined, + JSON.stringify(req) + ); + } +} + +var deal = +{ + auctionInit() { + vubleAnalytics.context.auctionTimeStart = Date.now(); + return [{ + event: CONSTANTS.EVENTS.AUCTION_INIT, + date: vubleAnalytics.context.auctionTimeStart, + }]; + }, + + bidRequested(args) { + return args.bids.map( + function(bid) { + let vubleEvent = { event: CONSTANTS.EVENTS.BID_REQUESTED }; + + if (typeof args.bidderCode !== 'undefined') { + vubleEvent.adapter = args.bidderCode + } + if (typeof bid.bidId !== 'undefined') { + vubleEvent.bidder = bid.bidId; + } + if (typeof bid.bidderRequestId !== 'undefined') { + vubleEvent.id = bid.bidderRequestId; + } + if (typeof bid.params.floorPrice !== 'undefined') { + vubleEvent.floor = bid.params.floorPrice; + } + if (typeof bid.params.zoneId !== 'undefined') { + vubleEvent.zoneId = bid.params.zoneId; + } + if (typeof bid.mediaTypes !== 'undefined' && + typeof bid.mediaTypes.videos !== 'undefined' && + typeof bid.mediaTypes.videos.context !== 'undefined') { + vubleEvent.context = bid.mediaTypes.videos.context; + } + if (typeof bid.sizes !== 'undefined') { + vubleEvent.size = bid.sizes; + } + + return vubleEvent; + } + ); + }, + + bidResponse(args) { + const event = formalizeBidEvent( + args.bidderCode, + CONSTANTS.EVENTS.BID_RESPONSE, + args.cpm, + args.dealId, + args.adId + ); + + return [event]; + }, + + bidWon(args) { + const event = formalizeBidEvent( + args.bidderCode, + CONSTANTS.EVENTS.BID_WON, + args.cpm, + args.dealId, + ); + + return [event]; + }, + + auctionEnd() { + return [{ + event: CONSTANTS.EVENTS.AUCTION_END, + time: (Date.now() - vubleAnalytics.context.auctionTimeStart) / 1000, + }]; + }, + + bidTimeout(args) { + return args.map((bid) => { + return { + adapter: bid, + event: CONSTANTS.EVENTS.BID_TIMEOUT, + }; + }); + } +}; + +function formalizeBidEvent(adapter, event, value = 0, dealId = 0, id = 0) { + let vubleEvent = { event: event }; + + if (adapter) { + vubleEvent.adapter = adapter + } + if (value) { + vubleEvent.val = value; + } + if (dealId) { + vubleEvent.id = dealId; + } + if (id) { + vubleEvent.id = id; + } + + return vubleEvent; +} + +function buildRequestTemplate(pubId) { + const topLocation = utils.getTopWindowLocation(); + + return { + ver: ANALYTICS_VERSION, + domain: topLocation.hostname, + path: topLocation.pathname, + pubid: pubId, + width: window.screen.width, + height: window.screen.height, + lang: navigator.language, + } +} + +/** + * Expiring queue implementation + * @param callback + * @param time + */ +export function ExpiringQueue(callback, time) { + let queue = []; + let timeoutId; + + this.push = event => { + if (event instanceof Array) { + queue.push.apply(queue, event); + } else { + queue.push(event); + } + reset(); + }; + + this.popAll = () => { + let result = queue; + queue = []; + reset(); + return result; + }; + + this.init = reset; + + function reset() { + if (timeoutId) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(() => { + if (queue.length) { + callback(); + } + }, time); + } +} diff --git a/modules/vubleAnalyticsAdapter.md b/modules/vubleAnalyticsAdapter.md new file mode 100644 index 00000000000..dfe0a8d8eb0 --- /dev/null +++ b/modules/vubleAnalyticsAdapter.md @@ -0,0 +1,23 @@ +# Overview + +Module Name: Vuble Analytics Adapter + +Module Type: Vuble Analytics Adapter + +Maintainer: abruyere@mediabong.com + +# Description + +Analytics adapter for vuble.tv Contact contact@mediabong.com for information. + +# Test Parameters + +``` +{ + provider: 'vuble', + options: { + pubId: 18, // require + env: 'net', // require + } +} +``` diff --git a/test/spec/modules/vubleAnalyticsAdapter_spec.js b/test/spec/modules/vubleAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..896f6e4ee87 --- /dev/null +++ b/test/spec/modules/vubleAnalyticsAdapter_spec.js @@ -0,0 +1,122 @@ +import vubleAnalytics from 'modules/vubleAnalyticsAdapter'; +import { expect } from 'chai'; +let events = require('src/events'); +let adaptermanager = require('src/adaptermanager'); +let constants = require('src/constants.json'); + +describe('Vuble Prebid Analytic', function () { + let xhr; + before(() => { + xhr = sinon.useFakeXMLHttpRequest(); + }); + after(() => { + vubleAnalytics.disableAnalytics(); + xhr.restore(); + }); + + describe('enableAnalytics', function () { + beforeEach(() => { + sinon.spy(vubleAnalytics, 'track'); + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(() => { + vubleAnalytics.track.restore(); + events.getEvents.restore(); + }); + it('should catch all events', function () { + adaptermanager.registerAnalyticsAdapter({ + code: 'vuble', + adapter: vubleAnalytics + }); + + adaptermanager.enableAnalytics({ + provider: 'vuble', + options: { + pubId: 18, + env: 'net' + } + }); + + let auction_id = 'test'; + + // Step 1: Auction init + events.emit(constants.EVENTS.AUCTION_INIT, { + auctionId: auction_id, + timestamp: 1496510254313, + }); + + // Step 2: Bid request + events.emit(constants.EVENTS.BID_REQUESTED, { + auctionId: auction_id, + auctionStart: 1509369418387, + timeout: 3000, + bids: [ + { + bidder: 'vuble', + params: { + env: 'net', + pubId: '3', + zoneId: '12345', + floorPrice: 5.50 // optional + }, + sizes: [[640, 360]], + mediaTypes: { + video: { + context: 'instream' + } + }, + bidId: 'abdc' + }, + { + bidder: 'vuble', + params: { + env: 'com', + pubId: '8', + zoneId: '2468', + referrer: 'http://www.vuble.fr/' + }, + sizes: '640x360', + mediaTypes: { + video: { + context: 'outstream' + } + }, + bidId: 'efgh', + }, + ], + }); + + // Step 3: Bid response + events.emit(constants.EVENTS.BID_RESPONSE, { + width: '640', + height: '360', + pub_id: '3', + dealId: 'aDealId', + zone_id: '12345', + context: 'instream', + floor_price: 5.5, + url: 'http://www.vuble.tv/', + env: 'net', + bid_id: 'abdc' + }); + + // Step 4: Bid won + events.emit(constants.EVENTS.BID_WON, { + adId: 'adIdTestWin', + ad: 'adContentTestWin', + auctionId: auction_id, + width: 640, + height: 360 + }); + + // Step 4: Auction end + events.emit(constants.EVENTS.AUCTION_END, { + auctionId: auction_id + }); + + // Step 5: Check if the number of call is good (5) + sinon.assert.callCount(vubleAnalytics.track, 5); + }); + }); +}); From 033d73351859fc96da338222ee3f540249c0e524 Mon Sep 17 00:00:00 2001 From: Muhammad Usman Date: Sat, 14 Apr 2018 01:54:36 +0200 Subject: [PATCH 0264/1594] Widespace adapter (#2283) Update WideSpce Adapter for Prebid 1.x --- modules/widespaceBidAdapter.js | 239 ++++++++++++++++++ modules/widespaceBidAdapter.md | 40 +++ test/spec/modules/widespaceBidAdapter_spec.js | 213 ++++++++++++++++ 3 files changed, 492 insertions(+) create mode 100644 modules/widespaceBidAdapter.js create mode 100644 modules/widespaceBidAdapter.md create mode 100644 test/spec/modules/widespaceBidAdapter_spec.js diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js new file mode 100644 index 00000000000..9493428cec7 --- /dev/null +++ b/modules/widespaceBidAdapter.js @@ -0,0 +1,239 @@ +import { version } from '../package.json'; +import { config } from 'src/config'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { + cookiesAreEnabled, + parseQueryStringParameters, + parseSizesInput, + getTopWindowReferrer +} from 'src/utils'; + +const BIDDER_CODE = 'widespace'; +const WS_ADAPTER_VERSION = '2.0.0'; +const LOCAL_STORAGE_AVAILABLE = window.localStorage; +const COOKIE_ENABLED = cookiesAreEnabled(); +const LS_KEYS = { + PERF_DATA: 'wsPerfData', + LC_UID: 'wsLcuid', + CUST_DATA: 'wsCustomData' +}; + +let preReqTime = 0; + +export const spec = { + code: BIDDER_CODE, + + supportedMediaTypes: ['banner'], + + isBidRequestValid: function(bid) { + if (bid.params && bid.params.sid) { + return true; + } + return false; + }, + + buildRequests: function(validBidRequests) { + let serverRequests = []; + const REQUEST_SERVER_URL = getEngineUrl(); + const DEMO_DATA_PARAMS = ['gender', 'country', 'region', 'postal', 'city', 'yob']; + const PERF_DATA = getData(LS_KEYS.PERF_DATA).map(perf_data => JSON.parse(perf_data)); + const CUST_DATA = getData(LS_KEYS.CUST_DATA, false)[0]; + const LC_UID = getLcuid(); + + let isInHostileIframe = false; + try { + window.top.location.toString(); + isInHostileIframe = false; + } catch (e) { + isInHostileIframe = true; + } + + validBidRequests.forEach((bid, i) => { + let data = { + 'screenWidthPx': screen && screen.width, + 'screenHeightPx': screen && screen.height, + 'adSpaceHttpRefUrl': getTopWindowReferrer(), + 'referer': (isInHostileIframe ? window : window.top).location.href.split('#')[0], + 'inFrame': 1, + 'sid': bid.params.sid, + 'lcuid': LC_UID, + 'vol': isInHostileIframe ? '' : visibleOnLoad(document.getElementById(bid.adUnitCode)), + 'hb': '1', + 'hb.cd': CUST_DATA ? encodedParamValue(CUST_DATA) : '', + 'hb.floor': bid.bidfloor || '', + 'hb.spb': i === 0 ? pixelSyncPossibility() : -1, + 'hb.ver': WS_ADAPTER_VERSION, + 'hb.name': `prebidjs-${version}`, + 'hb.bidId': bid.bidId, + 'hb.sizes': parseSizesInput(bid.sizes).join(','), + 'hb.currency': bid.params.cur || bid.params.currency || '' + }; + + // Include demo data + if (bid.params.demo) { + DEMO_DATA_PARAMS.forEach((key) => { + if (bid.params.demo[key]) { + data[key] = bid.params.demo[key]; + } + }); + } + + // Include performance data + if (PERF_DATA[i]) { + Object.keys(PERF_DATA[i]).forEach((perfDataKey) => { + data[perfDataKey] = PERF_DATA[i][perfDataKey]; + }); + } + + // Include connection info if available + const CONNECTION = navigator.connection || navigator.webkitConnection; + if (CONNECTION && CONNECTION.type && CONNECTION.downlinkMax) { + data['netinfo.type'] = CONNECTION.type; + data['netinfo.downlinkMax'] = CONNECTION.downlinkMax; + } + + // Include debug data when available + if (!isInHostileIframe) { + const DEBUG_AD = (window.top.location.hash.split('&').find((val) => { + return val.includes('WS_DEBUG_FORCEADID'); + }) || '').split('=')[1]; + data.forceAdId = DEBUG_AD; + } + + // Remove empty params + Object.keys(data).forEach((key) => { + if (data[key] === '' || data[key] === undefined) { + delete data[key]; + } + }); + + serverRequests.push({ + method: 'POST', + options: { + contentType: 'application/x-www-form-urlencoded' + }, + url: REQUEST_SERVER_URL, + data: parseQueryStringParameters(data) + }); + }); + preReqTime = Date.now(); + return serverRequests; + }, + + interpretResponse: function(serverResponse, request) { + const responseTime = Date.now() - preReqTime; + const successBids = serverResponse.body || []; + let bidResponses = []; + successBids.forEach((bid) => { + storeData({ + 'perf_status': 'OK', + 'perf_reqid': bid.reqId, + 'perf_ms': responseTime + }, `${LS_KEYS.PERF_DATA}${bid.reqId}`); + if (bid.status === 'ad') { + bidResponses.push({ + requestId: bid.bidId, + cpm: bid.cpm, + width: bid.width, + height: bid.height, + creativeId: bid.adId, + currency: bid.currency, + netRevenue: Boolean(bid.netRev), + ttl: bid.ttl, + referrer: getTopWindowReferrer(), + ad: bid.code + }); + } + }); + + return bidResponses + }, + + getUserSyncs: function(syncOptions, serverResponses = []) { + let userSyncs = []; + userSyncs = serverResponses.reduce((allSyncPixels, response) => { + if (response && response.body && response.body[0]) { + (response.body[0].syncPixels || []).forEach((url) => { + allSyncPixels.push({type: 'image', url}); + }); + } + return allSyncPixels; + }, []); + return userSyncs; + } +}; + +function storeData(data, name, stringify = true) { + const value = stringify ? JSON.stringify(data) : data; + if (LOCAL_STORAGE_AVAILABLE) { + localStorage.setItem(name, value); + return true; + } else if (COOKIE_ENABLED) { + const theDate = new Date(); + const expDate = new Date(theDate.setMonth(theDate.getMonth() + 12)).toGMTString(); + window.document.cookie = `${name}=${value};path=/;expires=${expDate}`; + return true; + } +} + +function getData(name, remove = true) { + let data = []; + if (LOCAL_STORAGE_AVAILABLE) { + Object.keys(localStorage).filter((key) => { + if (key.includes(name)) { + data.push(localStorage.getItem(key)); + if (remove) { + localStorage.removeItem(key); + } + } + }); + } + + if (COOKIE_ENABLED) { + document.cookie.split(';').forEach((item) => { + let value = item.split('='); + if (value[0].includes(name)) { + data.push(value[1]); + if (remove) { + document.cookie = `${value[0]}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`; + } + } + }); + } + return data; +} + +function pixelSyncPossibility() { + const userSync = config.getConfig('userSync'); + return userSync && userSync.pixelEnabled && userSync.syncEnabled ? userSync.syncsPerBidder : -1; +} + +function visibleOnLoad(element) { + if (element && element.getBoundingClientRect) { + const topPos = element.getBoundingClientRect().top; + return topPos < screen.height && topPos >= window.top.pageYOffset ? 1 : 0; + }; + return ''; +} + +function getLcuid() { + let lcuid = getData(LS_KEYS.LC_UID, false)[0]; + if (!lcuid) { + const random = ('4' + new Date().getTime() + String(Math.floor(Math.random() * 1000000000))).substring(0, 18); + storeData(random, LS_KEYS.LC_UID, false); + lcuid = getData(LS_KEYS.LC_UID, false)[0]; + } + return lcuid; +} + +function encodedParamValue(value) { + const requiredStringify = typeof JSON.parse(JSON.stringify(value)) === 'object'; + return encodeURIComponent(requiredStringify ? JSON.stringify(value) : value); +} + +function getEngineUrl() { + const ENGINE_URL = 'https://engine.widespace.com/map/engine/dynadreq'; + return window.wisp && window.wisp.ENGINE_URL ? window.wisp.ENGINE_URL : ENGINE_URL; +} + +registerBidder(spec); diff --git a/modules/widespaceBidAdapter.md b/modules/widespaceBidAdapter.md new file mode 100644 index 00000000000..1ca2b61d406 --- /dev/null +++ b/modules/widespaceBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + + +**Module Name:** Widespace Bidder Adapter. +**Module Type:** Bidder Adapter. +**Maintainer:** support@widespace.com + + +# Description + +Widespace Bidder Adapter for Prebid.js. +Banner and video formats are supported. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250], [300, 300]], + bids: [ + { + bidder: 'widespace', + params: { + sid: '7b6589bf-95c8-4656-90b9-af9737bb9ad3', // Required + currency: 'EUR', // Optional + bidfloor: '0.5', // Optional + demo: { // Optional + gender: 'M', + country: 'Sweden', + region: 'Stockholm', + postal: '15115', + city: 'Stockholm', + yob: '1984' + } + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js new file mode 100644 index 00000000000..3df5b6bfff2 --- /dev/null +++ b/test/spec/modules/widespaceBidAdapter_spec.js @@ -0,0 +1,213 @@ +import { expect } from 'chai'; +import { spec } from 'modules/widespaceBidAdapter'; + +describe('+widespaceAdatperTest', () => { + // Dummy bid request + const bidRequest = [{ + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'auctionId': 'bf1e57ee-fff2-4304-8143-91aaf423a948', + 'bidId': '4045696e2278cd', + 'bidder': 'widespace', + 'params': { + sid: '7b6589bf-95c8-4656-90b9-af9737bb9ad3', + currency: 'EUR', + demo: { + gender: 'M', + country: 'Sweden', + region: 'Stockholm', + postal: '15115', + city: 'Stockholm', + yob: '1984' + } + }, + 'bidderRequestId': '37a5f053efef34', + 'sizes': [[320, 320], [300, 250], [300, 300]], + 'transactionId': '4f68b713-04ba-4d7f-8df9-643bcdab5efb' + }, { + 'adUnitCode': 'div-gpt-ad-1460505748561-1', + 'auctionId': 'bf1e57ee-fff2-4304-8143-91aaf423a944', + 'bidId': '4045696e2278ab', + 'bidder': 'widespace', + 'params': { + sid: '7b6589bf-95c8-4656-90b9-af9737bb9ad4', + demo: { + gender: 'M', + country: 'Sweden', + region: 'Stockholm', + postal: '15115', + city: 'Stockholm', + yob: '1984' + } + }, + 'bidderRequestId': '37a5f053efef34', + 'sizes': [[300, 300]], + 'transactionId': '4f68b713-04ba-4d7f-8df9-643bcdab5efv' + }]; + + // Dummy bid response with ad code + const bidResponse = { + body: [{ + 'adId': '12345', + 'bidId': '67890', + 'code': '
', + 'cpm': 6.6, + 'currency': 'EUR', + 'height': 300, + 'netRev': true, + 'reqId': '224804081406', + 'status': 'ad', + 'ttl': 30, + 'width': 300, + 'syncPixels': ['https://url1.com/url', 'https://url2.com/url'] + }], + headers: {} + }; + + // Dummy bid response of noad + const bidResponseNoAd = { + body: [{ + 'status': 'noad', + }], + headers: {} + }; + + // Appending a div with id of adUnitCode so we can calculate vol + const div1 = document.createElement('div'); + div1.id = bidRequest[0].adUnitCode; + document.body.appendChild(div1); + const div2 = document.createElement('div'); + div2.id = bidRequest[0].adUnitCode; + document.body.appendChild(div2); + + // Adding custom data cookie se we can test cookie is readable + const theDate = new Date(); + const expDate = new Date(theDate.setMonth(theDate.getMonth() + 1)).toGMTString(); + window.document.cookie = `wsCustomData1={id: test};path=/;expires=${expDate};`; + const PERF_DATA = JSON.stringify({perf_status: 'OK', perf_reqid: '226920425154', perf_ms: '747'}); + window.document.cookie = `wsPerfData123=${PERF_DATA};path=/;expires=${expDate};`; + + // Connect dummy data test + navigator.connection.downlinkMax = 80; + navigator.connection.type = 'wifi'; + + describe('+bidRequestValidity', () => { + it('bidRequest with sid and currency params', () => { + expect(spec.isBidRequestValid({ + bidder: 'widespace', + params: { + sid: '7b6589bf-95c8-4656-90b9-af9737bb9ad3', + currency: 'EUR' + } + })).to.equal(true); + }); + + it('-bidRequest with missing sid', () => { + expect(spec.isBidRequestValid({ + bidder: 'widespace', + params: { + currency: 'EUR' + } + })).to.equal(false); + }); + + it('-bidRequest with missing currency', () => { + expect(spec.isBidRequestValid({ + bidder: 'widespace', + params: { + sid: '7b6589bf-95c8-4656-90b9-af9737bb9ad3' + } + })).to.equal(true); + }); + }); + + describe('+bidRequest', () => { + const request = spec.buildRequests(bidRequest); + const UrlRegExp = /^((ftp|http|https):)?\/\/[^ "]+$/; + + it('-bidRequest method is POST', () => { + expect(request[0].method).to.equal('POST'); + }); + + it('-bidRequest url is valid', () => { + expect(UrlRegExp.test(request[0].url)).to.equal(true); + }); + + it('-bidRequest data exist', () => { + expect(request[0].data).to.exists; + }); + + it('-bidRequest data is form data', () => { + expect(typeof request[0].data).to.equal('string'); + }); + + it('-bidRequest options have header type', () => { + expect(request[0].options.contentType).to.exists; + }); + + it('-cookie test for wsCustomData ', () => { + expect(request[0].data.includes('hb.cd')).to.equal(true); + }); + }); + + describe('+interpretResponse', () => { + it('-required params available in response', () => { + const result = spec.interpretResponse(bidResponse, bidRequest); + let requiredKeys = [ + 'requestId', + 'cpm', + 'width', + 'height', + 'creativeId', + 'currency', + 'netRevenue', + 'ttl', + 'referrer', + 'ad' + ]; + const resultKeys = Object.keys(result[0]); + requiredKeys.forEach((key) => { + expect(resultKeys.includes(key)).to.equal(true); + }); + + // Each value except referrer should not be empty|null|undefined + result.forEach((res) => { + Object.keys(res).forEach((resKey) => { + if (resKey !== 'referrer') { + expect(res[resKey]).to.not.be.null; + expect(res[resKey]).to.not.be.undefined; + expect(res[resKey]).to.not.equal(''); + } + }); + }); + }); + + it('-empty result if noad responded', () => { + const noAdResult = spec.interpretResponse(bidResponseNoAd, bidRequest); + expect(noAdResult.length).to.equal(0); + }); + + it('-empty response should not breake anything in adapter', () => { + const noResponse = spec.interpretResponse({}, bidRequest); + expect(noResponse.length).to.equal(0); + }); + }); + + describe('+getUserSyncs', () => { + it('-always return an array', () => { + const userSync_test1 = spec.getUserSyncs({}, [bidResponse]); + expect(Array.isArray(userSync_test1)).to.equal(true); + + const userSync_test2 = spec.getUserSyncs({}, [bidResponseNoAd]); + expect(Array.isArray(userSync_test2)).to.equal(true); + + const userSync_test3 = spec.getUserSyncs({}, [bidResponse, bidResponseNoAd]); + expect(Array.isArray(userSync_test3)).to.equal(true); + + const userSync_test4 = spec.getUserSyncs(); + expect(Array.isArray(userSync_test4)).to.equal(true); + + const userSync_test5 = spec.getUserSyncs({}, []); + expect(Array.isArray(userSync_test5)).to.equal(true); + }); + }); +}); From 77b57f1f4ca3d99c122705525978ea9371a8ab86 Mon Sep 17 00:00:00 2001 From: rtbdemand <33991103+rtbdemand@users.noreply.github.com> Date: Mon, 16 Apr 2018 05:33:14 -0700 Subject: [PATCH 0265/1594] Create rtbdemandAdkBidAdapter_spec.js (#2352) * Create rtbdemandAdkBidAdapter_spec.js * Update rtbdemandAdkBidAdapter_spec.js --- .../modules/rtbdemandAdkBidAdapter_spec.js | 268 ++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 test/spec/modules/rtbdemandAdkBidAdapter_spec.js diff --git a/test/spec/modules/rtbdemandAdkBidAdapter_spec.js b/test/spec/modules/rtbdemandAdkBidAdapter_spec.js new file mode 100644 index 00000000000..2bd4ea4ce98 --- /dev/null +++ b/test/spec/modules/rtbdemandAdkBidAdapter_spec.js @@ -0,0 +1,268 @@ +import {expect} from 'chai'; +import {spec} from 'modules/rtbdemandAdkBidAdapter'; +import * as utils from 'src/utils'; + +describe('RtbdemandAdk adapter', () => { + const bid1_zone1 = { + bidder: 'rtbdemandadk', + bidId: 'Bid_01', + params: {zoneId: 1, host: 'rtb.rtbdemand.com'}, + placementCode: 'ad-unit-1', + sizes: [[300, 250], [300, 200]] + }, bid2_zone2 = { + bidder: 'rtbdemandadk', + bidId: 'Bid_02', + params: {zoneId: 2, host: 'rtb.rtbdemand.com'}, + placementCode: 'ad-unit-2', + sizes: [[728, 90]] + }, bid3_host2 = { + bidder: 'rtbdemandadk', + bidId: 'Bid_02', + params: {zoneId: 1, host: 'rtb-private.rtbdemand.com'}, + placementCode: 'ad-unit-2', + sizes: [[728, 90]] + }, bid_without_zone = { + bidder: 'rtbdemandadk', + bidId: 'Bid_W', + params: {host: 'rtb-private.rtbdemand.com'}, + placementCode: 'ad-unit-1', + sizes: [[728, 90]] + }, bid_without_host = { + bidder: 'rtbdemandadk', + bidId: 'Bid_W', + params: {zoneId: 1}, + placementCode: 'ad-unit-1', + sizes: [[728, 90]] + }, bid_with_wrong_zoneId = { + bidder: 'rtbdemandadk', + bidId: 'Bid_02', + params: {zoneId: 'wrong id', host: 'rtb.rtbdemand.com'}, + placementCode: 'ad-unit-2', + sizes: [[728, 90]] + }, bid_video = { + bidder: 'rtbdemandadk', + bidId: 'Bid_Video', + sizes: [640, 480], + mediaType: 'video', + params: { + zoneId: 1, + host: 'rtb.rtbdemand.com', + video: { + mimes: ['video/mp4', 'video/webm', 'video/x-flv'] + } + }, + placementCode: 'ad-unit-1' + }; + + const bidResponse1 = { + id: 'bid1', + seatbid: [{ + bid: [{ + id: '1', + impid: 'Bid_01', + crid: '100_001', + price: 3.01, + nurl: 'https://rtb.com/win?i=ZjKoPYSFI3Y_0', + adm: '', + w: 300, + h: 250 + }] + }], + cur: 'USD', + ext: { + adk_usersync: ['http://adk.sync.com/sync'] + } + }, bidResponse2 = { + id: 'bid2', + seatbid: [{ + bid: [{ + id: '2', + impid: 'Bid_02', + crid: '100_002', + price: 1.31, + adm: '', + w: 300, + h: 250 + }] + }], + cur: 'USD' + }, videoBidResponse = { + id: '47ce4badcf7482', + seatbid: [{ + bid: [{ + id: 'sZSYq5zYMxo_0', + impid: 'Bid_Video', + crid: '100_003', + price: 0.00145, + adid: '158801', + nurl: 'https://rtb.com/win?i=sZSYq5zYMxo_0&f=nurl', + cid: '16855' + }] + }], + cur: 'USD' + }, usersyncOnlyResponse = { + id: 'nobid1', + ext: { + adk_usersync: ['http://adk.sync.com/sync'] + } + }; + + describe('input parameters validation', () => { + it('empty request shouldn\'t generate exception', () => { + expect(spec.isBidRequestValid({ + bidderCode: 'rtbdemandadk' + })).to.be.equal(false); + }); + + it('request without zone shouldn\'t issue a request', () => { + expect(spec.isBidRequestValid(bid_without_zone)).to.be.equal(false); + }); + + it('request without host shouldn\'t issue a request', () => { + expect(spec.isBidRequestValid(bid_without_host)).to.be.equal(false); + }); + + it('empty request shouldn\'t generate exception', () => { + expect(spec.isBidRequestValid(bid_with_wrong_zoneId)).to.be.equal(false); + }); + }); + + describe('banner request building', () => { + let bidRequest; + before(() => { + let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => ({ + protocol: 'https:', + hostname: 'example.com', + host: 'example.com', + pathname: '/index.html', + href: 'https://example.com/index.html' + })); + let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => true); + let request = spec.buildRequests([bid1_zone1])[0]; + bidRequest = JSON.parse(request.data.r); + wmock.restore(); + dntmock.restore(); + }); + + it('should be a first-price auction', () => { + expect(bidRequest).to.have.property('at', 1); + }); + + it('should have banner object', () => { + expect(bidRequest.imp[0]).to.have.property('banner'); + }); + + it('should have w/h', () => { + expect(bidRequest.imp[0].banner).to.have.property('format'); + expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); + }); + + it('should respect secure connection', () => { + expect(bidRequest.imp[0]).to.have.property('secure', 1); + }); + + it('should have tagid', () => { + expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); + }); + + it('should create proper site block', () => { + expect(bidRequest.site).to.have.property('domain', 'example.com'); + expect(bidRequest.site).to.have.property('page', 'https://example.com/index.html'); + }); + + it('should fill device with caller macro', () => { + expect(bidRequest).to.have.property('device'); + expect(bidRequest.device).to.have.property('ip', 'caller'); + expect(bidRequest.device).to.have.property('ua', 'caller'); + expect(bidRequest.device).to.have.property('dnt', 1); + }); + }); + + describe('video request building', () => { + let bidRequest; + + before(() => { + let request = spec.buildRequests([bid_video])[0]; + bidRequest = JSON.parse(request.data.r); + }); + + it('should have video object', () => { + expect(bidRequest.imp[0]).to.have.property('video'); + }); + + it('should have h/w', () => { + expect(bidRequest.imp[0].video).to.have.property('w', 640); + expect(bidRequest.imp[0].video).to.have.property('h', 480); + }); + + it('should have tagid', () => { + expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); + }); + }); + + describe('requests routing', () => { + it('should issue a request for each host', () => { + let pbRequests = spec.buildRequests([bid1_zone1, bid3_host2]); + expect(pbRequests).to.have.length(2); + expect(pbRequests[0].url).to.have.string(`//${bid1_zone1.params.host}/`); + expect(pbRequests[1].url).to.have.string(`//${bid3_host2.params.host}/`); + }); + + it('should issue a request for each zone', () => { + let pbRequests = spec.buildRequests([bid1_zone1, bid2_zone2]); + expect(pbRequests).to.have.length(2); + expect(pbRequests[0].data.zone).to.be.equal(bid1_zone1.params.zoneId); + expect(pbRequests[1].data.zone).to.be.equal(bid2_zone2.params.zoneId); + }); + }); + + describe('responses processing', () => { + it('should return fully-initialized banner bid-response', () => { + let request = spec.buildRequests([bid1_zone1])[0]; + let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; + expect(resp).to.have.property('requestId', 'Bid_01'); + expect(resp).to.have.property('cpm', 3.01); + expect(resp).to.have.property('width', 300); + expect(resp).to.have.property('height', 250); + expect(resp).to.have.property('creativeId', '100_001'); + expect(resp).to.have.property('currency'); + expect(resp).to.have.property('ttl'); + expect(resp).to.have.property('mediaType', 'banner'); + expect(resp).to.have.property('ad'); + expect(resp.ad).to.have.string(''); + }); + + it('should return fully-initialized video bid-response', () => { + let request = spec.buildRequests([bid_video])[0]; + let resp = spec.interpretResponse({body: videoBidResponse}, request)[0]; + expect(resp).to.have.property('requestId', 'Bid_Video'); + expect(resp.mediaType).to.equal('video'); + expect(resp.cpm).to.equal(0.00145); + expect(resp.vastUrl).to.equal('https://rtb.com/win?i=sZSYq5zYMxo_0&f=nurl'); + expect(resp.width).to.equal(640); + expect(resp.height).to.equal(480); + }); + + it('should add nurl as pixel for banner response', () => { + let request = spec.buildRequests([bid1_zone1])[0]; + let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; + let expectedNurl = bidResponse1.seatbid[0].bid[0].nurl + '&px=1'; + expect(resp.ad).to.have.string(expectedNurl); + }); + + it('should handle bidresponse with user-sync only', () => { + let request = spec.buildRequests([bid1_zone1])[0]; + let resp = spec.interpretResponse({body: usersyncOnlyResponse}, request); + expect(resp).to.have.length(0); + }); + + it('should perform usersync', () => { + let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: bidResponse1}]); + expect(syncs).to.have.length(0); + syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: bidResponse1}]); + expect(syncs).to.have.length(1); + expect(syncs[0]).to.have.property('type', 'iframe'); + expect(syncs[0]).to.have.property('url', 'http://adk.sync.com/sync'); + }); + }); +}); From a32070e88c641b0e5ed3a4059c1f1f8d51ed11ed Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 16 Apr 2018 11:31:11 -0400 Subject: [PATCH 0266/1594] add support for video bids to use an impression tracking URL (#2365) * initial commit - place AN notify url in vast wrapper imp field * add unit test for appnexusBidAdapter * small change in unit test --- modules/appnexusBidAdapter.js | 1 + src/videoCache.js | 8 +++++--- test/spec/modules/appnexusBidAdapter_spec.js | 2 ++ test/spec/videoCache_spec.js | 14 ++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 034824f6fda..75e48d1ee0b 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -200,6 +200,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { width: rtbBid.rtb.video.player_width, height: rtbBid.rtb.video.player_height, vastUrl: rtbBid.rtb.video.asset_url, + vastImpUrl: rtbBid.notify_url, ttl: 3600 }); // This supports Outstream Video diff --git a/src/videoCache.js b/src/videoCache.js index 2af980316fa..cec2a3ec864 100644 --- a/src/videoCache.js +++ b/src/videoCache.js @@ -32,18 +32,20 @@ import { config } from '../src/config'; * Function which wraps a URI that serves VAST XML, so that it can be loaded. * * @param {string} uri The URI where the VAST content can be found. + * @param {string} impUrl An impression tracker URL for the delivery of the video ad * @return A VAST URL which loads XML from the given URI. */ -function wrapURI(uri) { +function wrapURI(uri, impUrl) { // Technically, this is vulnerable to cross-script injection by sketchy vastUrl bids. // We could make sure it's a valid URI... but since we're loading VAST XML from the // URL they provide anyway, that's probably not a big deal. + let vastImp = (impUrl) ? `` : ``; return ` prebid.org wrapper - + ${vastImp} @@ -57,7 +59,7 @@ function wrapURI(uri) { * @param {CacheableBid} bid */ function toStorageRequest(bid) { - const vastValue = bid.vastXml ? bid.vastXml : wrapURI(bid.vastUrl); + const vastValue = bid.vastXml ? bid.vastXml : wrapURI(bid.vastUrl, bid.vastImpUrl); return { type: 'xml', value: vastValue diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 7038e2e572c..1ba4edfa4ea 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -412,6 +412,7 @@ describe('AppNexusAdapter', () => { 'ads': [{ 'ad_type': 'video', 'cpm': 0.500000, + 'notify_url': 'imptracker.com', 'rtb': { 'video': { 'content': '' @@ -424,6 +425,7 @@ describe('AppNexusAdapter', () => { 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'); }); diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index ab52b3be145..b853da708fc 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -101,6 +101,20 @@ describe('The video cache', () => { assertRequestMade({ vastUrl: 'my-mock-url.com' }, expectedValue) }); + it('should make the expected request when store() is called on an ad with a vastUrl and a vastImpUrl', () => { + const expectedValue = ` + + + prebid.org wrapper + + + + + + `; + assertRequestMade({ vastUrl: 'my-mock-url.com', vastImpUrl: 'imptracker.com' }, expectedValue) + }); + it('should make the expected request when store() is called on an ad with vastXml', () => { const vastXml = ''; assertRequestMade({ vastXml: vastXml }, vastXml); From 825ab8324d78d3cd95f9a493903c0ede1b487afc Mon Sep 17 00:00:00 2001 From: Spacedragoon Date: Mon, 16 Apr 2018 17:40:21 +0200 Subject: [PATCH 0267/1594] Smart: Add prebid version in the data payload (#2394) * Add prebid version in the data payload * Changing the doc to include the in-app test params * fixing url --- modules/smartadserverBidAdapter.js | 3 ++- modules/smartadserverBidAdapter.md | 32 ++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 02ebbbe06ae..7db4747927a 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -50,7 +50,8 @@ export const spec = { pageDomain: utils.getTopWindowUrl(), transactionId: bid.transactionId, timeout: config.getConfig('bidderTimeout'), - bidId: bid.bidId + bidId: bid.bidId, + prebidVersion: '$prebid.version$' }; var payloadString = JSON.stringify(payload); return { diff --git a/modules/smartadserverBidAdapter.md b/modules/smartadserverBidAdapter.md index 679bead441d..1200c0961a0 100644 --- a/modules/smartadserverBidAdapter.md +++ b/modules/smartadserverBidAdapter.md @@ -14,6 +14,8 @@ The Smart adapter requires setup and approval from the Smart team. Please reach out to your Technical account manager for more information. # Test Parameters + +## Web ``` var adUnits = [ { @@ -23,13 +25,35 @@ Please reach out to your Technical account manager for more information. { bidder: "smart", params: { - domain: 'http://prg.smartadserver.com', + domain: 'http://ww251.smartadserver.com', siteId: 207435, pageId: 896536, formatId: 62913, - buId: "com.smartadserver.android.dashboard", // optional - ckId: 1234567890123456789, // optional - appName: "Smart AdServer Preview" // optional + ckId: 1122334455 // optional + } + } + ] + } + ]; +``` + +## In-app +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "smart", + params: { + domain: 'http://ww251.smartadserver.com', + siteId: 207435, + pageId: 896536, + formatId: 65906, + buId: "com.smartadserver.android.dashboard", // in-app only + appName: "Smart AdServer Preview", // in-app only + ckId: 1122334455 // optional } } ] From fa6e221ede4b00714fc902d07a44ee4dd2e00e47 Mon Sep 17 00:00:00 2001 From: Dorian Wojda Date: Mon, 16 Apr 2018 17:50:39 +0200 Subject: [PATCH 0268/1594] Added VIS.X Bidder Adapter (#2359) --- modules/visxBidAdapter.js | 140 +++++++++ modules/visxBidAdapter.md | 43 +++ test/spec/modules/visxBidAdapter_spec.js | 356 +++++++++++++++++++++++ 3 files changed, 539 insertions(+) create mode 100755 modules/visxBidAdapter.js create mode 100755 modules/visxBidAdapter.md create mode 100755 test/spec/modules/visxBidAdapter_spec.js diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js new file mode 100755 index 00000000000..1fad6cd8337 --- /dev/null +++ b/modules/visxBidAdapter.js @@ -0,0 +1,140 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; +const BIDDER_CODE = 'visx'; +const ENDPOINT_URL = '//t.visx.net/hb'; +const TIME_TO_LIVE = 360; +const DEFAULT_CUR = 'EUR'; +const ADAPTER_SYNC_URL = '//t.visx.net/push_sync'; +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', + 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', + emptyResponse: 'Response is empty', + hasEmptySeatbidArray: 'Response has empty seatbid array', + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' +}; +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: function(bid) { + return !!bid.params.uid; + }, + buildRequests: function(validBidRequests) { + const auids = []; + const bidsMap = {}; + const bids = validBidRequests || []; + const currency = + config.getConfig(`currency.bidderCurrencyDefault.${BIDDER_CODE}`) || + config.getConfig('currency.adServerCurrency') || + DEFAULT_CUR; + let priceType = 'net'; + let reqId; + + bids.forEach(bid => { + if (bid.params.priceType === 'gross') { + priceType = 'gross'; + } + if (!bidsMap[bid.params.uid]) { + bidsMap[bid.params.uid] = [bid]; + auids.push(bid.params.uid); + } else { + bidsMap[bid.params.uid].push(bid); + } + reqId = bid.bidderRequestId; + }); + + const payload = { + u: utils.getTopWindowUrl(), + pt: priceType, + auids: auids.join(','), + test: 1, + r: reqId, + cur: currency, + }; + + return { + method: 'GET', + url: ENDPOINT_URL, + data: payload, + bidsMap: bidsMap, + }; + }, + interpretResponse: function(serverResponse, bidRequest) { + serverResponse = serverResponse && serverResponse.body; + const bidResponses = []; + const bidsMap = bidRequest.bidsMap; + const priceType = bidRequest.data.pt; + const currency = bidRequest.data.cur; + + let errorMessage; + + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } + + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, currency, bidResponses); + }); + } + if (errorMessage) utils.logError(errorMessage); + return bidResponses; + }, + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: ADAPTER_SYNC_URL + }]; + } + } +}; + +function _getBidFromResponse(respItem) { + if (!respItem) { + utils.logError(LOG_ERROR_MESS.emptySeatbid); + } else if (!respItem.bid) { + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + } else if (!respItem.bid[0]) { + utils.logError(LOG_ERROR_MESS.noBid); + } + return respItem && respItem.bid && respItem.bid[0]; +} + +function _addBidResponse(serverBid, bidsMap, priceType, currency, bidResponses) { + if (!serverBid) return; + let errorMessage; + if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + awaitingBids.forEach(bid => { + const bidResponse = { + requestId: bid.bidId, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, + currency: currency || DEFAULT_CUR, + netRevenue: priceType !== 'gross', + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid + }; + bidResponses.push(bidResponse); + }); + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } + if (errorMessage) { + utils.logError(errorMessage); + } +} + +registerBidder(spec); diff --git a/modules/visxBidAdapter.md b/modules/visxBidAdapter.md new file mode 100755 index 00000000000..7d5981132c2 --- /dev/null +++ b/modules/visxBidAdapter.md @@ -0,0 +1,43 @@ +# Overview + +``` +Module Name: VIS.X Bidder Adapter +Module Type: Bidder Adapter +Maintainer: service@yoc.com +``` + +# Description + +Module that connects to VIS.X demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [ + // YOC Mystery Ad adUnit + { + code: 'yma-test-div', + sizes: [[1, 1]], + bids: [ + { + bidder: 'visx', + params: { + uid: '903535' + } + } + ] + }, + // YOC Understitial Ad adUnit + { + code: 'yua-test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: 'visx', + params: { + uid: '903536' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js new file mode 100755 index 00000000000..20b056adf6d --- /dev/null +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -0,0 +1,356 @@ +import { expect } from 'chai'; +import { spec } from 'modules/visxBidAdapter'; +import { config } from 'src/config'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('VisxAdapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'visx', + 'params': { + 'uid': '903536' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'uid': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903536' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '42dbe3a7168a6a', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should attach valid params to the tag', () => { + const request = spec.buildRequests([bidRequests[0]]); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'EUR'); + }); + + it('auids must not be duplicated', () => { + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'EUR'); + }); + + it('pt parameter must be "gross" if params.priceType === "gross"', () => { + bidRequests[1].params.priceType = 'gross'; + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'gross'); + expect(payload).to.have.property('auids', '903535,903536'); + 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" or "gross"', () => { + bidRequests[1].params.priceType = 'some'; + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535,903536'); + 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', () => { + const getConfigStub = sinon.stub(config, 'getConfig').callsFake( + arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'JPY' : 'USD'); + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'JPY'); + getConfigStub.restore(); + }); + it('should add currency from currency.adServerCurrency', () => { + const getConfigStub = sinon.stub(config, 'getConfig').callsFake( + arg => arg === 'currency.bidderCurrencyDefault.visx' ? '' : 'USD'); + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('cur', 'USD'); + getConfigStub.restore(); + }); + }); + + describe('interpretResponse', () => { + const responses = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 903536, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + undefined, + {'bid': [], 'seat': '1'}, + {'seat': '1'}, + ]; + + it('should get correct bid response', () => { + const bidRequests = [ + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should get correct multi bid response', () => { + const bidRequests = [ + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71a5b', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903536' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dff80cc4ee346', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '5703af74d0472a', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '300bfeb0d71a5b', + 'cpm': 1.15, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '5703af74d0472a', + 'cpm': 1.15, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 903536, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 2
', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should return right currency', () => { + const bidRequests = [ + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const getConfigStub = sinon.stub(config, 'getConfig').returns('JPY'); + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'JPY', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + getConfigStub.restore(); + }); + + it('handles wrong and nobid responses', () => { + const bidRequests = [ + { + 'bidder': 'visx', + 'params': { + 'uid': '903536' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d7190gf', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903538' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71321', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903539' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '300bfeb0d7183bb', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + } + ]; + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + expect(result.length).to.equal(0); + }); + }); +}); From 1557315f3f4cb44987c17cd486fef3c401e32b41 Mon Sep 17 00:00:00 2001 From: Unruly Developers Date: Mon, 16 Apr 2018 18:02:08 +0100 Subject: [PATCH 0269/1594] Add Unruly Bid Adapter (#2326) * Add Unruly Bid Adapter * Replace placementCode with adUnitCode --- integrationExamples/gpt/unruly_example.html | 120 ++++++++++++ modules/unrulyBidAdapter.js | 101 ++++++++++ modules/unrulyBidAdapter.md | 31 +++ test/spec/modules/unrulyBidAdapter_spec.js | 206 ++++++++++++++++++++ 4 files changed, 458 insertions(+) create mode 100644 integrationExamples/gpt/unruly_example.html create mode 100644 modules/unrulyBidAdapter.js create mode 100644 modules/unrulyBidAdapter.md create mode 100644 test/spec/modules/unrulyBidAdapter_spec.js diff --git a/integrationExamples/gpt/unruly_example.html b/integrationExamples/gpt/unruly_example.html new file mode 100644 index 00000000000..77a9b02b3dd --- /dev/null +++ b/integrationExamples/gpt/unruly_example.html @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + test + + + +
+ +
+ + + diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js new file mode 100644 index 00000000000..94fa716799a --- /dev/null +++ b/modules/unrulyBidAdapter.js @@ -0,0 +1,101 @@ +import * as utils from 'src/utils' +import { Renderer } from 'src/Renderer' +import { registerBidder } from 'src/adapters/bidderFactory' +import { VIDEO } from 'src/mediaTypes' + +function configureUniversalTag (exchangeRenderer) { + parent.window.unruly = parent.window.unruly || {}; + parent.window.unruly['native'] = parent.window.unruly['native'] || {}; + parent.window.unruly['native'].siteId = parent.window.unruly['native'].siteId || exchangeRenderer.siteId; + parent.window.unruly['native'].supplyMode = 'prebid'; +} + +function configureRendererQueue () { + parent.window.unruly['native'].prebid = parent.window.unruly['native'].prebid || {}; + parent.window.unruly['native'].prebid.uq = parent.window.unruly['native'].prebid.uq || []; +} + +function notifyRenderer (bidResponseBid) { + parent.window.unruly['native'].prebid.uq.push(['render', bidResponseBid]); +} + +const serverResponseToBid = (bid, rendererInstance) => ({ + requestId: bid.bidId, + cpm: bid.cpm, + width: bid.width, + height: bid.height, + vastUrl: bid.vastUrl, + netRevenue: true, + creativeId: bid.bidId, + ttl: 360, + currency: 'USD', + renderer: rendererInstance +}); + +const buildPrebidResponseAndInstallRenderer = bids => + bids + .filter(serverBid => !!utils.deepAccess(serverBid, 'ext.renderer')) + .map(serverBid => { + const exchangeRenderer = utils.deepAccess(serverBid, 'ext.renderer'); + configureUniversalTag(exchangeRenderer); + configureRendererQueue(); + + const rendererInstance = Renderer.install(Object.assign({}, exchangeRenderer, { callback: () => {} })); + return { rendererInstance, serverBid }; + }) + .map( + ({rendererInstance, serverBid}) => { + const prebidBid = serverResponseToBid(serverBid, rendererInstance); + + const rendererConfig = Object.assign( + {}, + prebidBid, + { + renderer: rendererInstance, + adUnitCode: serverBid.ext.adUnitCode + } + ); + + rendererInstance.setRender(() => { notifyRenderer(rendererConfig) }); + + return prebidBid; + } + ); + +export const adapter = { + code: 'unruly', + supportedMediaTypes: [ VIDEO ], + isBidRequestValid: function(bid) { + if (!bid) return false; + + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + + return bid.mediaType === 'video' || context === 'outstream'; + }, + + buildRequests: function(validBidRequests) { + const url = 'https://targeting.unrulymedia.com/prebid'; + const method = 'POST'; + const data = { bidRequests: validBidRequests }; + const options = { contentType: 'application/json' }; + + return { + url, + method, + data, + options, + }; + }, + + interpretResponse: function(serverResponse = {}) { + const serverResponseBody = serverResponse.body; + const noBidsResponse = []; + const isInvalidResponse = !serverResponseBody || !serverResponseBody.bids; + + return isInvalidResponse + ? noBidsResponse + : buildPrebidResponseAndInstallRenderer(serverResponseBody.bids); + } +}; + +registerBidder(adapter); diff --git a/modules/unrulyBidAdapter.md b/modules/unrulyBidAdapter.md new file mode 100644 index 00000000000..fc3c6c264be --- /dev/null +++ b/modules/unrulyBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +**Module Name**: Unruly Bid Adapter +**Module Type**: Bidder Adapter +**Maintainer**: prodev@unrulymedia.com + +# Description + +Module that connects to UnrulyX for bids. + +# Test Parameters + +```js + const adUnits = [{ + code: 'ad-slot', + sizes: [[728, 90], [300, 250]], + mediaTypes: { + video: { + context: 'outstream' + } + }, + bids: [{ + bidder: 'unruly', + params: { + targetingUUID: '6f15e139-5f18-49a1-b52f-87e5e69ee65e', + siteId: 1081534 + } + } + ] + }]; +``` diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js new file mode 100644 index 00000000000..e4eaa35d662 --- /dev/null +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -0,0 +1,206 @@ +/* globals describe, it, beforeEach, afterEach, sinon */ +import { expect } from 'chai' +import * as utils from 'src/utils' +import { STATUS } from 'src/constants' +import { VIDEO } from 'src/mediaTypes' +import { Renderer } from 'src/Renderer' +import { adapter } from 'modules/unrulyBidAdapter' + +describe('UnrulyAdapter', () => { + function createOutStreamExchangeBid({ + adUnitCode = 'placement2', + statusCode = 1, + bidId = 'foo', + vastUrl = 'https://targeting.unrulymedia.com/in_article?uuid=74544e00-d43b-4f3a-a799-69d22ce979ce&supported_mime_type=application/javascript&supported_mime_type=video/mp4&tj=%7B%22site%22%3A%7B%22lang%22%3A%22en-GB%22%2C%22ref%22%3A%22%22%2C%22page%22%3A%22http%3A%2F%2Fdemo.unrulymedia.com%2FinArticle%2Finarticle_nypost_upbeat%2Ftravel_magazines.html%22%2C%22domain%22%3A%22demo.unrulymedia.com%22%7D%2C%22user%22%3A%7B%22profile%22%3A%7B%22quantcast%22%3A%7B%22segments%22%3A%5B%7B%22id%22%3A%22D%22%7D%2C%7B%22id%22%3A%22T%22%7D%5D%7D%7D%7D%7D&video_width=618&video_height=347' + }) { + return { + 'ext': { + 'statusCode': statusCode, + 'renderer': { + 'id': 'unruly_inarticle', + 'config': {}, + 'url': 'https://video.unrulymedia.com/native/prebid-loader.js' + }, + 'adUnitCode': adUnitCode + }, + 'cpm': 20, + 'bidderCode': 'unruly', + 'width': 323, + 'vastUrl': vastUrl, + 'bidId': bidId, + 'height': 323 + } + } + + const createExchangeResponse = (...bids) => ({ + body: { bids } + }); + + let sandbox; + let fakeRenderer; + + beforeEach(() => { + sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'logError'); + sandbox.stub(Renderer, 'install'); + + fakeRenderer = { + setRender: sinon.stub() + }; + Renderer.install.returns(fakeRenderer) + }); + + afterEach(() => { + sandbox.restore(); + delete parent.window.unruly + }); + + it('should expose Unruly Bidder code', () => { + expect(adapter.code).to.equal('unruly') + }); + + it('should contain the VIDEO mediaType', function () { + expect(adapter.supportedMediaTypes).to.deep.equal([ VIDEO ]) + }); + + describe('isBidRequestValid', () => { + it('should be a function', () => { + expect(typeof adapter.isBidRequestValid).to.equal('function') + }); + + it('should return false if bid is falsey', () => { + expect(adapter.isBidRequestValid()).to.be.false; + }); + + it('should return true if bid.mediaType is "video"', () => { + const mockBid = { mediaType: 'video' }; + + expect(adapter.isBidRequestValid(mockBid)).to.be.true; + }); + + it('should return true if bid.mediaTypes.video.context is "outstream"', () => { + const mockBid = { + mediaTypes: { + video: { + context: 'outstream' + } + } + }; + + expect(adapter.isBidRequestValid(mockBid)).to.be.true; + }); + }); + + describe('buildRequests', () => { + it('should be a function', () => { + expect(typeof adapter.buildRequests).to.equal('function'); + }); + it('should return an object', () => { + const mockBidRequests = ['mockBid']; + expect(typeof adapter.buildRequests(mockBidRequests)).to.equal('object') + }); + it('should return a server request with a valid exchange url', () => { + const mockBidRequests = ['mockBid']; + expect(adapter.buildRequests(mockBidRequests).url).to.equal('https://targeting.unrulymedia.com/prebid') + }); + it('should return a server request with method === POST', () => { + const mockBidRequests = ['mockBid']; + expect(adapter.buildRequests(mockBidRequests).method).to.equal('POST'); + }); + it('should ensure contentType is `application/json`', function () { + const mockBidRequests = ['mockBid']; + expect(adapter.buildRequests(mockBidRequests).options).to.deep.equal({ + contentType: 'application/json' + }); + }); + it('should return a server request with valid payload', () => { + const mockBidRequests = ['mockBid']; + expect(adapter.buildRequests(mockBidRequests).data).to.deep.equal({bidRequests: mockBidRequests}) + }) + }); + + describe('interpretResponse', () => { + it('should be a function', () => { + expect(typeof adapter.interpretResponse).to.equal('function'); + }); + it('should return empty array when serverResponse is undefined', () => { + expect(adapter.interpretResponse()).to.deep.equal([]); + }); + it('should return empty array when serverResponse has no bids', () => { + const mockServerResponse = { body: { bids: [] } }; + expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]) + }); + it('should return array of bids when receive a successful response from server', () => { + const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); + const mockServerResponse = createExchangeResponse(mockExchangeBid); + expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([ + { + requestId: 'mockBidId', + cpm: 20, + width: 323, + height: 323, + vastUrl: 'https://targeting.unrulymedia.com/in_article?uuid=74544e00-d43b-4f3a-a799-69d22ce979ce&supported_mime_type=application/javascript&supported_mime_type=video/mp4&tj=%7B%22site%22%3A%7B%22lang%22%3A%22en-GB%22%2C%22ref%22%3A%22%22%2C%22page%22%3A%22http%3A%2F%2Fdemo.unrulymedia.com%2FinArticle%2Finarticle_nypost_upbeat%2Ftravel_magazines.html%22%2C%22domain%22%3A%22demo.unrulymedia.com%22%7D%2C%22user%22%3A%7B%22profile%22%3A%7B%22quantcast%22%3A%7B%22segments%22%3A%5B%7B%22id%22%3A%22D%22%7D%2C%7B%22id%22%3A%22T%22%7D%5D%7D%7D%7D%7D&video_width=618&video_height=347', + netRevenue: true, + creativeId: 'mockBidId', + ttl: 360, + currency: 'USD', + renderer: fakeRenderer + } + ]) + }); + + it('should initialize and set the renderer', () => { + expect(Renderer.install).not.to.have.been.called; + expect(fakeRenderer.setRender).not.to.have.been.called; + + const mockReturnedBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); + const mockRenderer = { url: 'value: mockRendererURL' }; + mockReturnedBid.ext.renderer = mockRenderer; + const mockServerResponse = createExchangeResponse(mockReturnedBid); + + adapter.interpretResponse(mockServerResponse); + + expect(Renderer.install).to.have.been.calledOnce; + sinon.assert.calledWithExactly( + Renderer.install, + Object.assign({}, mockRenderer, {callback: sinon.match.func}) + ); + + sinon.assert.calledOnce(fakeRenderer.setRender); + sinon.assert.calledWithExactly(fakeRenderer.setRender, sinon.match.func) + }); + + it('bid is placed on the bid queue when render is called', () => { + const exchangeBid = createOutStreamExchangeBid({ adUnitCode: 'video', vastUrl: 'value: vastUrl' }); + const exchangeResponse = createExchangeResponse(exchangeBid); + + adapter.interpretResponse(exchangeResponse); + + sinon.assert.calledOnce(fakeRenderer.setRender); + fakeRenderer.setRender.firstCall.args[0](); + + expect(window.top).to.have.deep.property('unruly.native.prebid.uq'); + + const uq = window.top.unruly.native.prebid.uq; + const sentRendererConfig = uq[0][1]; + + expect(uq[0][0]).to.equal('render'); + expect(sentRendererConfig.vastUrl).to.equal('value: vastUrl'); + expect(sentRendererConfig.renderer).to.equal(fakeRenderer); + expect(sentRendererConfig.adUnitCode).to.equal('video') + }) + + it('should ensure that renderer is placed in Prebid supply mode', () => { + const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); + const mockServerResponse = createExchangeResponse(mockExchangeBid); + + expect('unruly' in window.parent).to.equal(false); + + adapter.interpretResponse(mockServerResponse); + + const supplyMode = window.parent.unruly.native.supplyMode; + + expect(supplyMode).to.equal('prebid'); + }); + }); +}); From 4d1249c2bd6b6c097668e78a7919025a611fa2f5 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 16 Apr 2018 16:50:23 -0400 Subject: [PATCH 0270/1594] Unit test failures (#2405) --- modules/widespaceBidAdapter.js | 12 +++++++----- test/spec/modules/widespaceBidAdapter_spec.js | 12 ++++++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js index 9493428cec7..7905bd8d28c 100644 --- a/modules/widespaceBidAdapter.js +++ b/modules/widespaceBidAdapter.js @@ -7,6 +7,8 @@ import { parseSizesInput, getTopWindowReferrer } from 'src/utils'; +import includes from 'core-js/library/fn/array/includes'; +import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'widespace'; const WS_ADAPTER_VERSION = '2.0.0'; @@ -94,9 +96,9 @@ export const spec = { // Include debug data when available if (!isInHostileIframe) { - const DEBUG_AD = (window.top.location.hash.split('&').find((val) => { - return val.includes('WS_DEBUG_FORCEADID'); - }) || '').split('=')[1]; + const DEBUG_AD = (find(window.top.location.hash.split('&'), + val => includes(val, 'WS_DEBUG_FORCEADID') + ) || '').split('=')[1]; data.forceAdId = DEBUG_AD; } @@ -180,7 +182,7 @@ function getData(name, remove = true) { let data = []; if (LOCAL_STORAGE_AVAILABLE) { Object.keys(localStorage).filter((key) => { - if (key.includes(name)) { + if (key.indexOf(name) > -1) { data.push(localStorage.getItem(key)); if (remove) { localStorage.removeItem(key); @@ -192,7 +194,7 @@ function getData(name, remove = true) { if (COOKIE_ENABLED) { document.cookie.split(';').forEach((item) => { let value = item.split('='); - if (value[0].includes(name)) { + if (value[0].indexOf(name) > -1) { data.push(value[1]); if (remove) { document.cookie = `${value[0]}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`; diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js index 3df5b6bfff2..e1c922c2b9c 100644 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ b/test/spec/modules/widespaceBidAdapter_spec.js @@ -1,5 +1,6 @@ import { expect } from 'chai'; import { spec } from 'modules/widespaceBidAdapter'; +import includes from 'core-js/library/fn/array/includes'; describe('+widespaceAdatperTest', () => { // Dummy bid request @@ -87,8 +88,11 @@ describe('+widespaceAdatperTest', () => { window.document.cookie = `wsPerfData123=${PERF_DATA};path=/;expires=${expDate};`; // Connect dummy data test - navigator.connection.downlinkMax = 80; - navigator.connection.type = 'wifi'; + const CONNECTION = navigator.connection || navigator.webkitConnection; + if (CONNECTION && CONNECTION.type && CONNECTION.downlinkMax) { + navigator.connection.downlinkMax = 80; + navigator.connection.type = 'wifi'; + } describe('+bidRequestValidity', () => { it('bidRequest with sid and currency params', () => { @@ -145,7 +149,7 @@ describe('+widespaceAdatperTest', () => { }); it('-cookie test for wsCustomData ', () => { - expect(request[0].data.includes('hb.cd')).to.equal(true); + expect(request[0].data.indexOf('hb.cd') > -1).to.equal(true); }); }); @@ -166,7 +170,7 @@ describe('+widespaceAdatperTest', () => { ]; const resultKeys = Object.keys(result[0]); requiredKeys.forEach((key) => { - expect(resultKeys.includes(key)).to.equal(true); + expect(includes(resultKeys, key)).to.equal(true); }); // Each value except referrer should not be empty|null|undefined From a589ac2dbae041b4d5d727571a73dcd98ad251c0 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Mon, 16 Apr 2018 14:34:33 -0700 Subject: [PATCH 0271/1594] Removed the ability for to override any standard query parameters (#2402) --- modules/openxBidAdapter.js | 55 +++++----- test/spec/modules/openxBidAdapter_spec.js | 123 +++++++++++++++++----- 2 files changed, 124 insertions(+), 54 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 7cbfd459e2d..4a1e1f1451b 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,17 +8,12 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.0.1'; +const BIDDER_VERSION = '2.0.2'; export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { - if (isVideoRequest(bidRequest)) { - if (!utils.deepAccess(bidRequest, 'params.video.url')) { - return false; - } - } return !!(bidRequest.params.unit && bidRequest.params.delDomain); }, buildRequests: function (bidRequests) { @@ -214,10 +209,10 @@ function registerUserSync(mediaType, responseObj) { } } -function buildOXBannerRequest(bids) { +function buildCommonQueryParamsFromBids(bids) { const isInIframe = utils.inIframe(); - let queryParams = { + return { ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), jr: utils.getTopWindowReferrer(), ch: document.charSet || document.characterSet, @@ -226,12 +221,17 @@ function buildOXBannerRequest(bids) { tz: new Date().getTimezoneOffset(), tws: getViewportDimensions(isInIframe), be: 1, - bc: bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, - nocache: new Date().getTime(), - auid: utils._map(bids, bid => bid.params.unit).join(','), dddid: utils._map(bids, bid => bid.transactionId).join(','), - aus: utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|') + nocache: new Date().getTime(), }; +} + +function buildOXBannerRequest(bids) { + let queryParams = buildCommonQueryParamsFromBids(bids); + + queryParams.auid = utils._map(bids, bid => bid.params.unit).join(','); + queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); + queryParams.bc = bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`; let customParamsForAllBids = []; let hasCustomParam = false; @@ -284,10 +284,10 @@ function buildOXVideoRequest(bid) { } function generateVideoParameters(bid) { - let oxVideo = bid.params.video; + let queryParams = buildCommonQueryParamsFromBids([bid]); + let oxVideoConfig = utils.deepAccess(bid, 'params.video') || {}; let context = utils.deepAccess(bid, 'mediaTypes.video.context'); let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); - let oxVideoParams = {auid: bid.params.unit}; let width; let height; @@ -303,26 +303,31 @@ function generateVideoParameters(bid) { height = parseInt(playerSize[1], 10); } - Object.keys(oxVideo).forEach(function (key) { + Object.keys(oxVideoConfig).forEach(function (key) { if (key === 'openrtb') { - oxVideoParams[key] = JSON.stringify(oxVideo[key]); - } else { - oxVideoParams[key] = oxVideo[key]; + oxVideoConfig[key].w = width || oxVideoConfig[key].w; + oxVideoConfig[key].v = height || oxVideoConfig[key].v; + queryParams[key] = JSON.stringify(oxVideoConfig[key]); + } else if (!(key in queryParams) && key !== 'url') { + // only allow video-related attributes + queryParams[key] = oxVideoConfig[key]; } }); - // defaults - oxVideoParams.be = '1'; - + queryParams.auid = bid.params.unit; // override prebid config with openx config if available - oxVideoParams.vwd = width || oxVideo.vwd; - oxVideoParams.vht = height || oxVideo.vht; + queryParams.vwd = width || oxVideoConfig.vwd; + queryParams.vht = height || oxVideoConfig.vht; if (context === 'outstream') { - oxVideoParams.vos = '101'; + queryParams.vos = '101'; + } + + if (oxVideoConfig.mimes) { + queryParams.vmimes = oxVideoConfig.mimes; } - return oxVideoParams; + return queryParams; } function createVideoBidResponses(response, {bid, startTime}) { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index d780cb3d3e9..1fb7e6f600b 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1,7 +1,6 @@ import {expect} from 'chai'; import {spec} from 'modules/openxBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -import {BANNER, VIDEO} from 'src/mediaTypes'; import {userSync} from 'src/userSync'; const URLBASE = '/w/1.0/arj'; @@ -55,14 +54,11 @@ describe('OpenxAdapter', () => { params: { unit: '12345678', delDomain: 'test-del-domain', - video: { - be: 'true', - url: 'abc.com' - } }, adUnitCode: 'adunit-code', - mediaTypes: {video: {}}, - sizes: [640, 480], + mediaTypes: {video: { + playerSize: [640, 480] + }}, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', @@ -73,11 +69,7 @@ describe('OpenxAdapter', () => { 'bidder': 'openx', 'params': { 'unit': '12345678', - 'delDomain': 'test-del-domain', - 'video': { - 'be': 'true', - 'url': 'abc.com' - } + 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', 'mediaTypes': 'video', @@ -250,10 +242,7 @@ describe('OpenxAdapter', () => { }, 'params': { 'unit': '12345678', - 'delDomain': 'test-del-domain', - 'video': { - 'url': 'abc.com' - } + 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', @@ -268,10 +257,7 @@ describe('OpenxAdapter', () => { 'mediaType': 'video', 'params': { 'unit': '12345678', - 'delDomain': 'test-del-domain', - 'video': { - 'url': 'abc.com' - } + 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', 'sizes': [640, 480], @@ -298,10 +284,95 @@ describe('OpenxAdapter', () => { const dataParams = request[0].data; expect(dataParams.auid).to.equal('12345678'); - expect(dataParams.url).to.equal('abc.com'); expect(dataParams.vht).to.equal(480); expect(dataParams.vwd).to.equal(640); }); + + describe('when using the video param', function () { + let videoBidRequest; + + beforeEach(function () { + videoBidRequest = { + 'bidder': 'openx', + 'mediaTypes': { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain', + }, + 'adUnitCode': 'adunit-code', + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' + } + }); + + it('should not allow you to set a url', function () { + videoBidRequest.params.video = { + url: 'test-url' + }; + const request = spec.buildRequests([videoBidRequest]); + + expect(request[0].data.url).to.be.undefined; + }); + + it('should not allow you to override the javascript url', function () { + let myUrl = 'my-url'; + videoBidRequest.params.video = { + ju: myUrl + }; + const request = spec.buildRequests([videoBidRequest]); + + expect(request[0].data.ju).to.not.equal(myUrl); + }); + + describe('when using the openRtb param', function () { + it('should covert the param to a JSON string', function () { + let myOpenRTBObject = {}; + videoBidRequest.params.video = { + openrtb: myOpenRTBObject + }; + const request = spec.buildRequests([videoBidRequest]); + + expect(request[0].data.openrtb).to.equal(JSON.stringify(myOpenRTBObject)); + }); + + it("should use the bidRequest's playerSize when it is available", function () { + const width = 200; + const height = 100; + const myOpenRTBObject = {v: height, w: width}; + videoBidRequest.params.video = { + openrtb: myOpenRTBObject + }; + const request = spec.buildRequests([videoBidRequest]); + const openRtbRequestParams = JSON.parse(request[0].data.openrtb); + + expect(openRtbRequestParams.w).to.not.equal(width); + expect(openRtbRequestParams.v).to.not.equal(height); + }); + + it('should use the the openRTB\'s sizing when the bidRequest\'s playerSize is not available', function () { + const width = 200; + const height = 100; + const myOpenRTBObject = {v: height, w: width}; + videoBidRequest.params.video = { + openrtb: myOpenRTBObject + }; + videoBidRequest.mediaTypes.video.playerSize = undefined; + + const request = spec.buildRequests([videoBidRequest]); + const openRtbRequestParams = JSON.parse(request[0].data.openrtb); + + expect(openRtbRequestParams.w).to.equal(width); + expect(openRtbRequestParams.v).to.equal(height); + }); + }); + }); }); describe('interpretResponse for banner ads', () => { @@ -430,10 +501,7 @@ describe('OpenxAdapter', () => { 'mediaTypes': {video: {}}, 'params': { 'unit': '12345678', - 'delDomain': 'test-del-domain', - 'video': { - 'url': 'abc.com' - } + 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', 'sizes': [640, 480], @@ -447,10 +515,7 @@ describe('OpenxAdapter', () => { 'mediaType': 'video', 'params': { 'unit': '12345678', - 'delDomain': 'test-del-domain', - 'video': { - 'url': 'abc.com' - } + 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', 'sizes': [640, 480], From a76420cda9b62c19b2c93dbdd1966af40b84729e Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 17 Apr 2018 10:49:32 -0400 Subject: [PATCH 0272/1594] deprecate loadScript and add loadExternalScript (#2391) --- src/adloader.js | 30 +++++++++++++++++++++++++++++- src/prebid.js | 2 +- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/adloader.js b/src/adloader.js index db95f27569d..6f2bd112712 100644 --- a/src/adloader.js +++ b/src/adloader.js @@ -1,7 +1,35 @@ var utils = require('./utils'); let _requestCache = {}; -// add a script tag to the page, used to add /jpt call to page +/** + * Loads external javascript. Can only be used if external JS is approved by Prebid. See https://github.com/prebid/prebid-js-external-js-template#policy + * @param {string} url the url to load + * @param {string} moduleCode bidderCode or module code of the module requesting this resource + */ +exports.loadExternalScript = function(url, moduleCode) { + if (!moduleCode || !url) { + utils.logError('cannot load external script without url and moduleCode'); + return; + } + utils.logWarn(`module ${moduleCode} is loading external JavaScript`); + const script = document.createElement('script'); + script.type = 'text/javascript'; + script.async = true; + + script.src = url; + + // add the new script tag to the page + const target = document.head || document.body; + if (target) { + target.appendChild(script); + } +}; + +/** + * + * @deprecated + * Do not use this function. Will be removed in the next release. If external resources are required, use #loadExternalScript instead. + */ exports.loadScript = function (tagSrc, callback, cacheRequest) { // var noop = () => {}; // diff --git a/src/prebid.js b/src/prebid.js index 935860acf35..0dcf286c3bf 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -474,7 +474,7 @@ $$PREBID_GLOBAL$$.createBid = function (statusCode) { }; /** - * Wrapper to adloader.loadScript + * @deprecated this function will be removed in the next release. Prebid has deprected external JS loading. * @param {string} tagSrc [description] * @param {Function} callback [description] * @alias module:pbjs.loadScript From 1b29d1f9404c5a61458659f81ecb85d14222b957 Mon Sep 17 00:00:00 2001 From: Sigmoid Date: Tue, 17 Apr 2018 21:08:47 +0530 Subject: [PATCH 0273/1594] Add analytics adapter by Sigmoid (#2316) * Add analytics adapter and tests * Linting code * +Linting code * Date change * ++Linting code * +++Fix Linting * Add docs * Remove dead code and alert * Change let to const and typo fix * use includes by importing from core-js * +use includes by importing from core-js * Increase test coverage to 75% * Fix travis build error * +Fix travis build error --- modules/sigmoidAnalyticsAdapter.js | 285 ++++++++++++++++++ modules/sigmoidAnalyticsAdapter.md | 23 ++ .../modules/sigmoidAnalyticsAdapter_spec.js | 67 ++++ 3 files changed, 375 insertions(+) create mode 100644 modules/sigmoidAnalyticsAdapter.js create mode 100644 modules/sigmoidAnalyticsAdapter.md create mode 100644 test/spec/modules/sigmoidAnalyticsAdapter_spec.js diff --git a/modules/sigmoidAnalyticsAdapter.js b/modules/sigmoidAnalyticsAdapter.js new file mode 100644 index 00000000000..c8c5cc70c53 --- /dev/null +++ b/modules/sigmoidAnalyticsAdapter.js @@ -0,0 +1,285 @@ +/* Sigmoid Analytics Adapter for prebid.js v1.1.0-pre +Updated : 2018-03-28 */ +import includes from 'core-js/library/fn/array/includes'; +import adapter from 'src/AnalyticsAdapter'; +import CONSTANTS from 'src/constants.json'; +import adaptermanager from 'src/adaptermanager'; + +const utils = require('src/utils'); + +const url = 'https://kinesis.us-east-1.amazonaws.com/'; +const analyticsType = 'endpoint'; + +const auctionInitConst = CONSTANTS.EVENTS.AUCTION_INIT; +const auctionEndConst = CONSTANTS.EVENTS.AUCTION_END; +const bidWonConst = CONSTANTS.EVENTS.BID_WON; +const bidRequestConst = CONSTANTS.EVENTS.BID_REQUESTED; +const bidAdjustmentConst = CONSTANTS.EVENTS.BID_ADJUSTMENT; +const bidResponseConst = CONSTANTS.EVENTS.BID_RESPONSE; + +let initOptions = { publisherIds: [], utmTagData: [], adUnits: [] }; +let bidWon = {options: {}, events: []}; +let eventStack = {options: {}, events: []}; + +let auctionStatus = 'not_started'; + +let localStoragePrefix = 'sigmoid_analytics_'; +let utmTags = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']; +let utmTimeoutKey = 'utm_timeout'; +let utmTimeout = 60 * 60 * 1000; +let sessionTimeout = 60 * 60 * 1000; +let sessionIdStorageKey = 'session_id'; +let sessionTimeoutKey = 'session_timeout'; + +function getParameterByName(param) { + let vars = {}; + window.location.href.replace(location.hash, '').replace( + /[?&]+([^=&]+)=?([^&]*)?/gi, + function(m, key, value) { + vars[key] = value !== undefined ? value : ''; + } + ); + + return vars[param] ? vars[param] : ''; +} + +function buildSessionIdLocalStorageKey() { + return localStoragePrefix.concat(sessionIdStorageKey); +} + +function buildSessionIdTimeoutLocalStorageKey() { + return localStoragePrefix.concat(sessionTimeoutKey); +} + +function updateSessionId() { + if (isSessionIdTimeoutExpired()) { + let newSessionId = utils.generateUUID(); + localStorage.setItem(buildSessionIdLocalStorageKey(), newSessionId); + } + initOptions.sessionId = getSessionId(); + updateSessionIdTimeout(); +} + +function updateSessionIdTimeout() { + localStorage.setItem(buildSessionIdTimeoutLocalStorageKey(), Date.now()); +} + +function isSessionIdTimeoutExpired() { + let cpmSessionTimestamp = localStorage.getItem(buildSessionIdTimeoutLocalStorageKey()); + return Date.now() - cpmSessionTimestamp > sessionTimeout; +} + +function getSessionId() { + return localStorage.getItem(buildSessionIdLocalStorageKey()) ? localStorage.getItem(buildSessionIdLocalStorageKey()) : ''; +} + +function updateUtmTimeout() { + localStorage.setItem(buildUtmLocalStorageTimeoutKey(), Date.now()); +} + +function isUtmTimeoutExpired() { + let utmTimestamp = localStorage.getItem(buildUtmLocalStorageTimeoutKey()); + return (Date.now() - utmTimestamp) > utmTimeout; +} + +function buildUtmLocalStorageTimeoutKey() { + return localStoragePrefix.concat(utmTimeoutKey); +} + +function buildUtmLocalStorageKey(utmMarkKey) { + return localStoragePrefix.concat(utmMarkKey); +} + +function checkOptions() { + if (typeof initOptions.publisherIds === 'undefined') { + return false; + } + + return initOptions.publisherIds.length > 0; +} + +function checkAdUnitConfig() { + if (typeof initOptions.adUnits === 'undefined') { + return false; + } + + return initOptions.adUnits.length > 0; +} + +function buildBidWon(eventType, args) { + bidWon.options = initOptions; + if (checkAdUnitConfig()) { + if (includes(initOptions.adUnits, args.adUnitCode)) { + bidWon.events = [{ args: args, eventType: eventType }]; + } + } else { + bidWon.events = [{ args: args, eventType: eventType }]; + } +} + +function buildEventStack() { + eventStack.options = initOptions; +} + +function filterBidsByAdUnit(bids) { + var filteredBids = []; + bids.forEach(function (bid) { + if (includes(initOptions.adUnits, bid.placementCode)) { + filteredBids.push(bid); + } + }); + return filteredBids; +} + +function isValidEvent(eventType, adUnitCode) { + if (checkAdUnitConfig()) { + let validationEvents = [bidAdjustmentConst, bidResponseConst, bidWonConst]; + if (!includes(initOptions.adUnits, adUnitCode) && includes(validationEvents, eventType)) { + return false; + } + } + return true; +} + +function isValidEventStack() { + if (eventStack.events.length > 0) { + return eventStack.events.some(function(event) { + return bidRequestConst === event.eventType || bidWonConst === event.eventType; + }); + } + return false; +} + +function isValidBidWon() { + return bidWon.events.length > 0; +} + +function flushEventStack() { + eventStack.events = []; +} + +let sigmoidAdapter = Object.assign(adapter({url, analyticsType}), + { + track({eventType, args}) { + if (!checkOptions()) { + return; + } + + let info = Object.assign({}, args); + + if (info && info.ad) { + info.ad = ''; + } + + if (eventType === auctionInitConst) { + auctionStatus = 'started'; + } + + if (eventType === bidWonConst && auctionStatus === 'not_started') { + updateSessionId(); + buildBidWon(eventType, info); + if (isValidBidWon()) { + send(eventType, bidWon, 'bidWon'); + } + return; + } + + if (eventType === auctionEndConst) { + updateSessionId(); + buildEventStack(); + if (isValidEventStack()) { + send(eventType, eventStack, 'eventStack'); + } + auctionStatus = 'not_started'; + } else { + pushEvent(eventType, info); + } + }, + + }); + +sigmoidAdapter.originEnableAnalytics = sigmoidAdapter.enableAnalytics; + +sigmoidAdapter.enableAnalytics = function (config) { + initOptions = config.options; + initOptions.utmTagData = this.buildUtmTagData(); + utils.logInfo('Sigmoid Analytics enabled with config', initOptions); + sigmoidAdapter.originEnableAnalytics(config); +}; + +sigmoidAdapter.buildUtmTagData = function () { + let utmTagData = {}; + let utmTagsDetected = false; + utmTags.forEach(function(utmTagKey) { + let utmTagValue = getParameterByName(utmTagKey); + if (utmTagValue !== '') { + utmTagsDetected = true; + } + utmTagData[utmTagKey] = utmTagValue; + }); + utmTags.forEach(function(utmTagKey) { + if (utmTagsDetected) { + localStorage.setItem(buildUtmLocalStorageKey(utmTagKey), utmTagData[utmTagKey]); + updateUtmTimeout(); + } else { + if (!isUtmTimeoutExpired()) { + utmTagData[utmTagKey] = localStorage.getItem(buildUtmLocalStorageKey(utmTagKey)) ? localStorage.getItem(buildUtmLocalStorageKey(utmTagKey)) : ''; + updateUtmTimeout(); + } + } + }); + return utmTagData; +}; + +function send(eventType, data, sendDataType) { + AWS.config.credentials = new AWS.Credentials({ + accessKeyId: 'accesskey', secretAccessKey: 'secretkey' + }); + + AWS.config.region = 'us-east-1'; + AWS.config.credentials.get(function(err) { + // attach event listener + if (err) { + utils.logError(err); + return; + } + // create kinesis service object + var kinesis = new AWS.Kinesis({ + apiVersion: '2013-12-02' + }); + var dataList = []; + var jsonData = {}; + jsonData['Data'] = JSON.stringify(data) + '\n'; + jsonData['PartitionKey'] = 'partition-' + Math.random().toString(36).substring(7); + dataList.push(jsonData); + kinesis.putRecords({ + Records: dataList, + StreamName: 'sample-stream' + }); + if (sendDataType === 'eventStack') { + flushEventStack(); + } + }); +}; + +function pushEvent(eventType, args) { + if (eventType === bidRequestConst) { + if (checkAdUnitConfig()) { + args.bids = filterBidsByAdUnit(args.bids); + } + if (args.bids.length > 0) { + eventStack.events.push({ eventType: eventType, args: args }); + } + } else { + if (isValidEvent(eventType, args.adUnitCode)) { + eventStack.events.push({ eventType: eventType, args: args }); + } + } +} + +adaptermanager.registerAnalyticsAdapter({ + adapter: sigmoidAdapter, + code: 'sigmoid' +}); + +export default sigmoidAdapter; diff --git a/modules/sigmoidAnalyticsAdapter.md b/modules/sigmoidAnalyticsAdapter.md new file mode 100644 index 00000000000..8ff46c7f2be --- /dev/null +++ b/modules/sigmoidAnalyticsAdapter.md @@ -0,0 +1,23 @@ +# Overview +Module Name: Sigmoid Analytics Adapter + +Module Type: Analytics Adapter + +Maintainer: ramees@sigmoidanalytics.com + +# Description + +Analytics adapter for Sigmoid. We are an advanced analytical solutions company. +https://www.sigmoid.com/ + +# Test Parameters + +``` +{ + provider: 'sigmoid', + options : { + publisherIds: ["3gxdf18d32"] + } +} + +``` diff --git a/test/spec/modules/sigmoidAnalyticsAdapter_spec.js b/test/spec/modules/sigmoidAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..115c296d489 --- /dev/null +++ b/test/spec/modules/sigmoidAnalyticsAdapter_spec.js @@ -0,0 +1,67 @@ +import sigmoidAnalytic from 'modules/sigmoidAnalyticsAdapter'; +import { expect } from 'chai'; +let events = require('src/events'); +let adaptermanager = require('src/adaptermanager'); +let constants = require('src/constants.json'); + +describe('sigmoid Prebid Analytic', function () { + let xhr; + before(() => { + xhr = sinon.useFakeXMLHttpRequest(); + }) + after(() => { + sigmoidAnalytic.disableAnalytics(); + xhr.restore(); + }); + + describe('enableAnalytics', function () { + beforeEach(() => { + sinon.spy(sigmoidAnalytic, 'track'); + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(() => { + sigmoidAnalytic.track.restore(); + events.getEvents.restore(); + }); + it('should catch all events', function () { + adaptermanager.registerAnalyticsAdapter({ + code: 'sigmoid', + adapter: sigmoidAnalytic + }); + + adaptermanager.enableAnalytics({ + provider: 'sigmoid', + options: { + publisherIds: ['test_sigmoid_prebid_analytid_publisher_id'] + } + }); + + events.emit(constants.EVENTS.AUCTION_INIT, {}); + events.emit(constants.EVENTS.AUCTION_END, {}); + events.emit(constants.EVENTS.BID_REQUESTED, {}); + events.emit(constants.EVENTS.BID_RESPONSE, {}); + events.emit(constants.EVENTS.BID_WON, {}); + + sinon.assert.callCount(sigmoidAnalytic.track, 5); + }); + }); + describe('build utm tag data', () => { + beforeEach(() => { + localStorage.setItem('sigmoid_analytics_utm_source', 'utm_source'); + localStorage.setItem('sigmoid_analytics_utm_medium', 'utm_medium'); + localStorage.setItem('sigmoid_analytics_utm_campaign', ''); + localStorage.setItem('sigmoid_analytics_utm_term', ''); + localStorage.setItem('sigmoid_analytics_utm_content', ''); + localStorage.setItem('sigmoid_analytics_utm_timeout', Date.now()); + }); + it('should build utm data from local storage', () => { + let utmTagData = sigmoidAnalytic.buildUtmTagData(); + expect(utmTagData.utm_source).to.equal('utm_source'); + expect(utmTagData.utm_medium).to.equal('utm_medium'); + expect(utmTagData.utm_campaign).to.equal(''); + expect(utmTagData.utm_term).to.equal(''); + expect(utmTagData.utm_content).to.equal(''); + }); + }); +}); From bddef91b853c29ef3c2e028eaff93b3cd4fdaa2c Mon Sep 17 00:00:00 2001 From: John Salis Date: Tue, 17 Apr 2018 12:20:10 -0400 Subject: [PATCH 0274/1594] Add outstream renderer to Beachfront adapter (#2403) * Added renderer to bidder adapter * Start playback immediately * Fix test case --- modules/beachfrontBidAdapter.js | 29 +++++++++++++++++++ .../spec/modules/beachfrontBidAdapter_spec.js | 18 +++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index ee46195b766..fc191e306d4 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -1,14 +1,17 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { Renderer } from 'src/Renderer'; import { VIDEO, BANNER } from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; const ADAPTER_VERSION = '1.1'; const ADAPTER_NAME = 'BFIO_PREBID'; +const OUTSTREAM = 'outstream'; export const VIDEO_ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; export const BANNER_ENDPOINT = '//display.bfmio.com/prebid_display'; +export const OUTSTREAM_SRC = '//player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; export const VIDEO_TARGETING = ['mimes']; export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; @@ -53,6 +56,7 @@ export const spec = { return []; } let size = getFirstSize(bidRequest); + let context = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); return { requestId: bidRequest.bidId, bidderCode: spec.code, @@ -61,6 +65,7 @@ export const spec = { width: size.w, height: size.h, creativeId: response.cmpId, + renderer: context === OUTSTREAM ? createRenderer(bidRequest) : null, mediaType: VIDEO, currency: 'USD', netRevenue: true, @@ -91,6 +96,30 @@ export const spec = { } }; +function createRenderer(bidRequest) { + const renderer = Renderer.install({ + id: bidRequest.bidId, + url: OUTSTREAM_SRC, + loaded: false + }); + + renderer.setRender(outstreamRender); + + return renderer; +} + +function outstreamRender(bid) { + bid.renderer.push(() => { + window.Beachfront.Player(bid.adUnitCode, { + ad_tag_url: bid.vastUrl, + width: bid.width, + height: bid.height, + expand_in_view: false, + collapse_on_complete: true + }); + }); +} + function getSizes(bid) { return utils.parseSizesInput(bid.sizes).map(size => { let [ width, height ] = size.split('x'); diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 9ca375d7e20..ddd93f8406d 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; +import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import * as utils from 'src/utils'; describe('BeachfrontAdapter', () => { @@ -267,12 +267,28 @@ describe('BeachfrontAdapter', () => { vastUrl: serverResponse.url, width: width, height: height, + renderer: null, mediaType: 'video', currency: 'USD', netRevenue: true, ttl: 300 }); }); + + it('should return a renderer for outstream video bids', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: { context: 'outstream' } }; + const serverResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + cmpId: '123abc' + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + expect(bidResponse.renderer).to.deep.contain({ + id: bidRequest.bidId, + url: OUTSTREAM_SRC + }); + }); }); describe('for banner bids', () => { From a2035a2ec028075af3aee4776bb8d5b75cb0d0db Mon Sep 17 00:00:00 2001 From: jlzhangdev Date: Tue, 17 Apr 2018 09:33:04 -0700 Subject: [PATCH 0275/1594] EbdrAdapter add usersync (#2407) * ebdr adapter 0.34.1 * ebdrBidAdapter.js 1.x * ebdrAdapter * update md and fix log issue * add video support and test case for EBDR adapter * Fix an issue for EBDR adapter Fix an issue might caused undefined if it is an old bidder * add vastUrl * add video adapter in md * fix test cases * ebdrAdapter add usersync --- modules/ebdrBidAdapter.js | 18 ++++++++++++++++ test/spec/modules/ebdrBidAdapter_spec.js | 26 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/modules/ebdrBidAdapter.js b/modules/ebdrBidAdapter.js index 63a308f1f62..f0f3d614a7d 100644 --- a/modules/ebdrBidAdapter.js +++ b/modules/ebdrBidAdapter.js @@ -105,6 +105,24 @@ export const spec = { ebdrResponseImps.push(response); }); return ebdrResponseImps; + }, + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = [] + if (syncOptions.pixelEnabled) { + const ebdrResponseObj = serverResponses.body; + if (!ebdrResponseObj || !ebdrResponseObj.seatbid || ebdrResponseObj.seatbid.length === 0 || !ebdrResponseObj.seatbid[0].bid || ebdrResponseObj.seatbid[0].bid.length === 0) { + return []; + } + ebdrResponseObj.seatbid[0].bid.forEach(ebdrBid => { + if (ebdrBid.iurl && ebdrBid.iurl.length > 0) { + syncs.push({ + type: 'image', + url: ebdrBid.iurl + }); + } + }); + } + return syncs; } } function getWidthAndHeight(bid) { diff --git a/test/spec/modules/ebdrBidAdapter_spec.js b/test/spec/modules/ebdrBidAdapter_spec.js index c5328f9ebb9..3ec5a4f0a81 100644 --- a/test/spec/modules/ebdrBidAdapter_spec.js +++ b/test/spec/modules/ebdrBidAdapter_spec.js @@ -206,4 +206,30 @@ describe('ebdrBidAdapter', () => { }); }); }); + describe('spec.getUserSyncs', () => { + let syncOptions + beforeEach(() => { + syncOptions = { + enabledBidders: ['ebdr'], // only these bidders are allowed to sync + pixelEnabled: true + } + }); + it('sucess with usersync url', () => { + const serverResponse = {id: '1d0c4017f02458', seatbid: [{bid: [{id: '2c5e8a1a84522d', impid: '2c5e8a1a84522d', price: 0.81, adid: 'abcde-12345', nurl: '', adm: '
', adomain: ['advertiserdomain.com'], iurl: '//match.bnmla.com/usersync?sspid=59&redir=', cid: 'campaign1', crid: 'abcde-12345', w: 300, h: 250}], seat: '19513bcfca8006'}], bidid: '19513bcfca8006', cur: 'USD', w: 300, h: 250}; + const result = []; + result.push({type: 'image', url: '//match.bnmla.com/usersync?sspid=59&redir='}); + expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); + }); + + it('sucess without usersync url', () => { + const serverResponse = {id: '1d0c4017f02458', seatbid: [{bid: [{id: '2c5e8a1a84522d', impid: '2c5e8a1a84522d', price: 0.81, adid: 'abcde-12345', nurl: '', adm: '
', adomain: ['advertiserdomain.com'], iurl: '', cid: 'campaign1', crid: 'abcde-12345', w: 300, h: 250}], seat: '19513bcfca8006'}], bidid: '19513bcfca8006', cur: 'USD', w: 300, h: 250}; + const result = []; + expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); + }); + it('empty response', () => { + const serverResponse = {}; + const result = []; + expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); + }); + }); }); From 9954c6fc59072e0bb32df603e1e3953be9fa6db4 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 17 Apr 2018 12:45:19 -0400 Subject: [PATCH 0276/1594] convert AN bid params to underscore formatting for pbs (#2385) * initial commit - convert AN bid params to underscore for pbs * removed breakpoint in unit test * added TODO comment to move this code to somewhere else at later date --- modules/prebidServerBidAdapter.js | 11 ++++++++++ src/utils.js | 8 ++++++++ .../modules/prebidServerBidAdapter_spec.js | 20 +++++++++++++++++-- test/spec/utils_spec.js | 12 +++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index e12f569b3b2..8e1a5a07560 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -469,6 +469,17 @@ const OPEN_RTB_PROTOCOL = { // get bidder params in form { : {...params} } const ext = adUnit.bids.reduce((acc, bid) => { + // TODO: move this bidder specific out to a more ideal location (submodule?); issue# pending + // convert all AppNexus keys to underscore format for pbs + if (bid.bidder === 'appnexus') { + Object.keys(bid.params).forEach(paramKey => { + let convertedKey = utils.convertCamelToUnderscore(paramKey); + if (convertedKey !== paramKey) { + bid.params[convertedKey] = bid.params[paramKey]; + delete bid.params[paramKey]; + } + }); + } acc[bid.bidder] = bid.params; return acc; }, {}); diff --git a/src/utils.js b/src/utils.js index b192cf2fef6..5b8508e52e4 100644 --- a/src/utils.js +++ b/src/utils.js @@ -952,3 +952,11 @@ export function isInteger(value) { return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; } } + +/** + * Converts a string value in camel-case to underscore eg 'placementId' becomes 'placement_id' + * @param {string} value string value to convert + */ +export function convertCamelToUnderscore(value) { + return value.replace(/(?:^|\.?)([A-Z])/g, function (x, y) { return '_' + y.toLowerCase() }).replace(/^_/, ''); +} diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index d525db857bc..a1392989ad7 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -505,7 +505,7 @@ describe('S2S Adapter', () => { params: { placementId: '123456' } }; - const request = Object.assign({}, REQUEST); + const request = utils.deepClone(REQUEST); request.ad_units[0].bids = [aliasBidder]; adapter.callBids(request, BID_REQUESTS, addBidResponse, done, ajax); @@ -533,7 +533,7 @@ describe('S2S Adapter', () => { params: { placementId: '123456' } }; - const request = Object.assign({}, REQUEST); + const request = utils.deepClone(REQUEST); request.ad_units[0].bids = [aliasBidder]; // TODO: stub this @@ -550,6 +550,22 @@ describe('S2S Adapter', () => { } }); }); + + it('converts appnexus params to underscore syntax', () => { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + config.setConfig({s2sConfig}); + + const myRequest = utils.deepClone(REQUEST); + + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.imp[0].ext.appnexus).to.exist; + expect(requestBid.imp[0].ext.appnexus.placement_id).to.exist.and.to.equal(10433394); + expect(requestBid.imp[0].ext.appnexus.member).to.exist; + }); }); describe('response handler', () => { diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index d44028e7554..f86840dbdba 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -750,4 +750,16 @@ describe('Utils', function () { expect(topWindowLocation.host).to.be.oneOf(['www.example.com', 'www.example.com:443']); }); }); + + describe('convertCamelToUnderscore', () => { + it('returns converted string value using underscore syntax instead of camelCase', () => { + let var1 = 'placementIdTest'; + let test1 = utils.convertCamelToUnderscore(var1); + expect(test1).to.equal('placement_id_test'); + + let var2 = 'my_test_value'; + let test2 = utils.convertCamelToUnderscore(var2); + expect(test2).to.equal(var2); + }); + }); }); From c21f82d2ec42305a921d140e3d0a117fba0327d8 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 17 Apr 2018 13:42:56 -0400 Subject: [PATCH 0277/1594] send appnexus usePaymentRule info to prebid-server ortb request (#2351) * initial commit - send usePaymentRule info to pbs * move code changes to pbs adapter * removed commented unit test --- modules/prebidServerBidAdapter.js | 3 +++ test/spec/modules/prebidServerBidAdapter_spec.js | 6 ++++-- test/spec/unit/core/adapterManager_spec.js | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 8e1a5a07560..a7ad11babe7 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -472,6 +472,9 @@ const OPEN_RTB_PROTOCOL = { // TODO: move this bidder specific out to a more ideal location (submodule?); issue# pending // convert all AppNexus keys to underscore format for pbs if (bid.bidder === 'appnexus') { + bid.params.use_pmt_rule = (typeof bid.params.usePaymentRule === 'boolean') ? bid.params.usePaymentRule : false; + if (bid.params.usePaymentRule) { delete bid.params.usePaymentRule; } + Object.keys(bid.params).forEach(paramKey => { let convertedKey = utils.convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index a1392989ad7..eef8a266b68 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -551,19 +551,21 @@ describe('S2S Adapter', () => { }); }); - it('converts appnexus params to underscore syntax', () => { + it('converts appnexus params to expected format for PBS', () => { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); config.setConfig({s2sConfig}); const myRequest = utils.deepClone(REQUEST); + myRequest.ad_units[0].bids[0].params.usePaymentRule = true; - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids(myRequest, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid.imp[0].ext.appnexus).to.exist; expect(requestBid.imp[0].ext.appnexus.placement_id).to.exist.and.to.equal(10433394); + expect(requestBid.imp[0].ext.appnexus.use_pmt_rule).to.exist.and.to.be.true; expect(requestBid.imp[0].ext.appnexus.member).to.exist; }); }); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index d11dfc02c4c..39e468d4959 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -851,7 +851,7 @@ describe('adapterManager tests', () => { expect(bidRequests[0].bids.length).to.equal(1); expect(bidRequests[0].bids[0].adUnitCode).to.equal(adUnits[1].code); }); - }) + }); }); }); From eed065522c89208a9b8ca0bf631bdc59517f4913 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 17 Apr 2018 13:48:10 -0400 Subject: [PATCH 0278/1594] send travis-ci notifications to slack (#2404) * send travis-ci notifications to slack * only send on failure * try again * wtf.. * test again * test again * test again * test again * test again * one last time * remove newline. --- .travis.yml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 499139f9bed..912f3de8b56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,24 +2,27 @@ sudo: required dist: trusty language: node_js node_js: - - '7.0' +- '7.0' env: - - BROWSERSTACK_USERNAME=info184 - +- BROWSERSTACK_USERNAME=info184 addons: chrome: stable, browserstack: - username: "info184" + username: info184 access_key: - secure: "Ru286R4pMcEIRKwb2AoaaJY6lEKIzeZraxY7CtbOP4ykNk7uqsnyitk4QwxpCCh0n35b71m30okW6ZmZnl0lJXhOMdYoSOYBAnUw2Vn7Y93oMSKIC5dc2/qmtF1t2b1qX65/Ont2iJUj+UY8VQw5Hk2vIT4/5wifYPBnV5ILK4AI7SVk/ma7OzK4rkp3WThlouddctAd7tx4O3YIyJKDi9lkfcMA0pnH4OZSOlDClRLIy50Q1NE+iyqHtWFZK1TwJ+IhQbSsCLbuyQJBRnyJJEftNmtrs5MCZt/9pwFDj7c8+o11F6HCsTBYFkehFRfbKnmhCc1G+bsNXY8OxIWwEHeuVmSGK7TDPYcPPQBc03mcQ1fY/IPNQOdsVJ/n8RsG2u0IU2CF2hhkuNFzeov7dOHljanc45NKOrLdjwzP1aZCAUvLquOTzvmdF23nJhMs8UO+Du4kTK5VfmKyz1MC91E40a0Q15+O4qmS39rNOlwhxPJSfuxxL1jKVPJ7PsFbTkGM8M/XPJ6dyGLufy225HjdLdJTAOa5BZ4st+nXH/AzqHzy6a2I5vTmAz1j4gHLgVU+iNxAkX8znb25s3Rs1ZuFVj+aBSBmNoQA1FA5f/uXWeruTdDig7ksp+XdjsjLm9Md8cWwYaEn04FYj1ztJrylrEMfnc0Kcs6zQ3fll1g=" - + secure: Ru286R4pMcEIRKwb2AoaaJY6lEKIzeZraxY7CtbOP4ykNk7uqsnyitk4QwxpCCh0n35b71m30okW6ZmZnl0lJXhOMdYoSOYBAnUw2Vn7Y93oMSKIC5dc2/qmtF1t2b1qX65/Ont2iJUj+UY8VQw5Hk2vIT4/5wifYPBnV5ILK4AI7SVk/ma7OzK4rkp3WThlouddctAd7tx4O3YIyJKDi9lkfcMA0pnH4OZSOlDClRLIy50Q1NE+iyqHtWFZK1TwJ+IhQbSsCLbuyQJBRnyJJEftNmtrs5MCZt/9pwFDj7c8+o11F6HCsTBYFkehFRfbKnmhCc1G+bsNXY8OxIWwEHeuVmSGK7TDPYcPPQBc03mcQ1fY/IPNQOdsVJ/n8RsG2u0IU2CF2hhkuNFzeov7dOHljanc45NKOrLdjwzP1aZCAUvLquOTzvmdF23nJhMs8UO+Du4kTK5VfmKyz1MC91E40a0Q15+O4qmS39rNOlwhxPJSfuxxL1jKVPJ7PsFbTkGM8M/XPJ6dyGLufy225HjdLdJTAOa5BZ4st+nXH/AzqHzy6a2I5vTmAz1j4gHLgVU+iNxAkX8znb25s3Rs1ZuFVj+aBSBmNoQA1FA5f/uXWeruTdDig7ksp+XdjsjLm9Md8cWwYaEn04FYj1ztJrylrEMfnc0Kcs6zQ3fll1g= before_install: - - npm install -g gulp - - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & - -script: | +- npm install -g gulp +- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & +script: |- if [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then gulp test --browserstack else gulp run-tests - fi \ No newline at end of file + fi +notifications: + slack: + on_success: never + on_failure: always + on_pull_requests: false + secure: C4O77VtABLE5DiPDeKGqUcsBdTBMNjQRLc8iBfSp231e95K1rA/JXJJEQN/lVhhiFJyPhxueE0i6cR0zD8uAMC8HRShGGfPjEZ7f6glawPzap2wFwjAyVkknYV+BMKcX0jvn7CiSKBj+zTbHQfn/Uj3nMSbDZQIdbNDiFGh4NuDr3/Yd/efhsw/miExlSPSWqGVCKV3WPpTrU3BRpLNDq4sZMXP9ORZxGK7ER3tsMiD2z05YpvC+mibESJxaY0qsuQu1y1Gu65QLPe5ocw405btJwqYn+b4YFpUd2GbLNhjtLzsc+OKrD0DWuEI0bxePQUYDga5wR6g4cdZaXU3ixDjee7sJbDeVJAuykGlfZ4A1k+fQIgPs3s9XMHaeG9AfDhFiZ/UoNdonzos1iSa/Y1TzHIXp1wnbHKT5HUWWPFNb5PzJxHEtHbm3jwOH4iK8VAq94ec16M2aqUAj7muiqcrTlYa5rs6jRlXo/TRymFnbQRdBT7eLmLNDQD35yR1Y+4mxHqKi+3189yG9RE+uwIlB+9HZFgNbioOApB+jarKC6M0qEgn0bHxkpJBP8JmNCA84U0ZUzyPvuMGsRbisAmKoUsU8C6cq59QDfBTcCTvKXK6r+6f23iRGieoGSbTxYQj46QkykpbWU0WstQDQsZL3L316uZecOVZmWKBRxPs= From a67da48ef0e7df7c9957dfdb5cdfe53f7f3ef35d Mon Sep 17 00:00:00 2001 From: Dan Caragea Date: Tue, 17 Apr 2018 23:03:26 +0300 Subject: [PATCH 0279/1594] Make eslint aware of the custom import paths (#2292) * Make eslint aware of the custom import paths By default eslint doesn't know what `src/Renderer` means in the following import: `import { Renderer } from 'src/Renderer';` This changes makes it aware that `src/Renderer` means `/src/Renderer.js` * fix: fix import paths in sonobiBidAdapter.js * fix: imports in bidderFactory.js --- .eslintrc.js | 7 +++++++ modules/sonobiBidAdapter.js | 13 ++++++------- src/adapters/bidderFactory.js | 3 +-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index dadfb1f0433..e6975951f06 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,6 +3,13 @@ module.exports = { "browser": true, "commonjs": true }, + "settings": { + "import/resolver": { + "node": { + "moduleDirectory": ["node_modules", "./"] + } + } + }, "extends": "standard", "globals": { "$$PREBID_GLOBAL$$": false diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 4db35807edd..170228dde7a 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -1,6 +1,5 @@ import { registerBidder } from 'src/adapters/bidderFactory'; -import { getTopWindowLocation, parseSizesInput } from 'src/utils'; -import * as utils from '../src/utils'; +import * as utils from 'src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; @@ -47,7 +46,7 @@ export const spec = { const payload = { 'key_maker': JSON.stringify(data), - 'ref': getTopWindowLocation().host, + 'ref': utils.getTopWindowLocation().host, 's': utils.generateUUID(), 'pv': PAGEVIEW_ID, }; @@ -139,9 +138,9 @@ export const spec = { function _validateSize (bid) { if (bid.params.sizes) { - return parseSizesInput(bid.params.sizes).join(','); + return utils.parseSizesInput(bid.params.sizes).join(','); } - return parseSizesInput(bid.sizes).join(','); + return utils.parseSizesInput(bid.sizes).join(','); } function _validateSlot (bid) { @@ -162,12 +161,12 @@ const _creative = (mediaType) => (sbi_dc, sbi_aid) => { if (mediaType === 'video') { return _videoCreative(sbi_dc, sbi_aid) } - const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null' + '&ref=' + getTopWindowLocation().host; + const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null' + '&ref=' + utils.getTopWindowLocation().host; return ''; } function _videoCreative(sbi_dc, sbi_aid) { - return `https://${sbi_dc}apex.go.sonobi.com/vast.xml?vid=${sbi_aid}&ref=${getTopWindowLocation().host}` + return `https://${sbi_dc}apex.go.sonobi.com/vast.xml?vid=${sbi_aid}&ref=${utils.getTopWindowLocation().host}` } function _getBidIdFromTrinityKey (key) { diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 2cf0a8f7253..7540a3a3398 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -2,7 +2,6 @@ import Adapter from 'src/adapter'; import adaptermanager from 'src/adaptermanager'; import { config } from 'src/config'; import bidfactory from 'src/bidfactory'; -import { STATUS } from 'src/constants'; import { userSync } from 'src/userSync'; import { nativeBidIsValid } from 'src/native'; import { isValidVideoBid } from 'src/video'; @@ -304,7 +303,7 @@ export function newBidder(spec) { function addBidUsingRequestMap(bid) { const bidRequest = bidRequestMap[bid.requestId]; if (bidRequest) { - const prebidBid = Object.assign(bidfactory.createBid(STATUS.GOOD, bidRequest), bid); + const prebidBid = Object.assign(bidfactory.createBid(CONSTANTS.STATUS.GOOD, bidRequest), bid); addBidWithCode(bidRequest.adUnitCode, prebidBid); } else { logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bid.requestId}. Ignoring.`); From 8633be2708583bc6bbda030dac4885c7076a125e Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 17 Apr 2018 16:38:11 -0400 Subject: [PATCH 0280/1594] Prebid 1.8.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a31a5998788..e417db5e22d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.8.0-pre", + "version": "1.8.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 13585d9a663359bba8d8780ae5501f920e97a1bd Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 17 Apr 2018 16:53:20 -0400 Subject: [PATCH 0281/1594] Increment Pre Version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e417db5e22d..bb8afc62998 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.8.0", + "version": "1.9.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4a8c8c2282bb604b9f11f8e3f536b0cef903cebf Mon Sep 17 00:00:00 2001 From: haohany Date: Wed, 18 Apr 2018 10:11:22 -0700 Subject: [PATCH 0282/1594] Add user sync callback for OpenX adaptor (#2409) * OpenX user sync callback * bump version * Get user sync url from responses if available * Missing semicolon * Add user sync tests --- modules/openxBidAdapter.js | 23 +++++++------- test/spec/modules/openxBidAdapter_spec.js | 38 +++++++++++++++++------ 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 4a1e1f1451b..bc00242b3e3 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.0.2'; +const BIDDER_VERSION = '2.1.0'; export const spec = { code: BIDDER_CODE, @@ -40,10 +40,19 @@ export const spec = { interpretResponse: function ({body: oxResponseObj}, serverRequest) { let mediaType = getMediaTypeFromRequest(serverRequest); - registerUserSync(mediaType, oxResponseObj); - return mediaType === VIDEO ? createVideoBidResponses(oxResponseObj, serverRequest.payload) : createBannerBidResponses(oxResponseObj, serverRequest.payload); + }, + getUserSyncs: function(syncOptions, responses) { + if (syncOptions.iframeEnabled) { + let url = utils.deepAccess(responses, '0.body.ads.pixels') || + utils.deepAccess(responses, '0.body.pixels') || + '//u.openx.net/w/1.0/pd'; + return [{ + type: 'iframe', + url: url, + }]; + } } }; @@ -201,14 +210,6 @@ function getMediaTypeFromRequest(serverRequest) { return /avjp$/.test(serverRequest.url) ? VIDEO : BANNER; } -function registerUserSync(mediaType, responseObj) { - if (mediaType === VIDEO && responseObj.pixels) { - userSync.registerSync('iframe', BIDDER_CODE, responseObj.pixels); - } else if (utils.deepAccess(responseObj, 'ads.pixels')) { - userSync.registerSync('iframe', BIDDER_CODE, responseObj.ads.pixels); - } -} - function buildCommonQueryParamsFromBids(bids) { const isInIframe = utils.inIframe(); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 1fb7e6f600b..35146542375 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -476,11 +476,6 @@ describe('OpenxAdapter', () => { expect(result.length).to.equal(0); }); - it('should register a user sync', () => { - spec.interpretResponse({body: bidResponse}, bidRequest); - sinon.assert.calledWith(userSync.registerSync, 'iframe', 'openx', 'http://testpixels.net'); - }); - it('should register a beacon', () => { spec.interpretResponse({body: bidResponse}, bidRequest); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/\/\/openx-d\.openx\.net.*\/bo\?.*ts=ts/)); @@ -599,11 +594,6 @@ describe('OpenxAdapter', () => { expect(result.length).to.equal(0); }); - it('should register a user sync', () => { - spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); - sinon.assert.calledWith(userSync.registerSync, 'iframe', 'openx', 'http://testpixels.net'); - }); - it('should register a beacon', () => { spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/^\/\/test-colo\.com/)) @@ -611,4 +601,32 @@ describe('OpenxAdapter', () => { sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/ts=test-ts/)); }); }); + + describe('user sync', () => { + const syncUrl = 'http://testpixels.net'; + + it('should register the pixel iframe from banner ad response', () => { + let syncs = spec.getUserSyncs( + { iframeEnabled: true }, + [{ body: { ads: { pixels: syncUrl } } }] + ); + expect(syncs).to.deep.equal([{ type: 'iframe', url: syncUrl }]); + }); + + it('should register the pixel iframe from video ad response', () => { + let syncs = spec.getUserSyncs( + { iframeEnabled: true }, + [{ body: { pixels: syncUrl } }] + ); + expect(syncs).to.deep.equal([{ type: 'iframe', url: syncUrl }]); + }); + + it('should register the default iframe if no pixels available', () => { + let syncs = spec.getUserSyncs( + { iframeEnabled: true }, + [] + ); + expect(syncs).to.deep.equal([{ type: 'iframe', url: '//u.openx.net/w/1.0/pd' }]); + }); + }); }); From c1e6e1d27f9fb86818ec89d6ded75698d08696a9 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 18 Apr 2018 11:11:50 -0600 Subject: [PATCH 0283/1594] add server response time to bids in prebid server (#2398) --- modules/prebidServerBidAdapter.js | 11 +++++++++ modules/rubiconAnalyticsAdapter.js | 4 ++++ .../modules/prebidServerBidAdapter_spec.js | 3 +++ .../modules/rubiconAnalyticsAdapter_spec.js | 24 +++++++++++-------- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index a7ad11babe7..1ef1d325379 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -325,6 +325,7 @@ const LEGACY_PROTOCOL = { interpretResponse(result, bidRequests, requestedBidders) { const bids = []; + let responseTimes = {}; if (result.status === 'OK' || result.status === 'no_cookie') { if (result.bidder_status) { @@ -335,6 +336,8 @@ const LEGACY_PROTOCOL = { if (bidder.error) { utils.logWarn(`Prebid Server returned error: '${bidder.error}' for ${bidder.bidder}`); } + + responseTimes[bidder.bidder] = bidder.response_time_ms; }); } @@ -357,6 +360,9 @@ const LEGACY_PROTOCOL = { bidObject.creative_id = bidObj.creative_id; bidObject.bidderCode = bidObj.bidder; bidObject.cpm = cpm; + if (responseTimes[bidObj.bidder]) { + bidObject.serverResponseTimeMs = responseTimes[bidObj.bidder]; + } if (bidObj.cache_id) { bidObject.cache_id = bidObj.cache_id; } @@ -537,6 +543,11 @@ const OPEN_RTB_PROTOCOL = { bidObject.bidderCode = seatbid.seat; bidObject.cpm = cpm; + let serverResponseTimeMs = utils.deepAccess(response, ['ext', 'responsetimemillis', seatbid.seat].join('.')); + if (serverResponseTimeMs) { + bidObject.serverResponseTimeMs = serverResponseTimeMs; + } + if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { bidObject.mediaType = VIDEO; if (bid.adm) { bidObject.vastXml = bid.adm; } diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index 32d1a79af5c..dd111efe03c 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -111,6 +111,7 @@ function sendMessage(auctionId, bidWonId) { ? 'server' : 'client' }, 'clientLatencyMillis', + 'serverLatencyMillis', 'params', 'bidResponse', bidResponse => bidResponse ? _pick(bidResponse, [ 'bidPriceUSD', @@ -386,6 +387,9 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { }; } bid.clientLatencyMillis = Date.now() - cache.auctions[args.auctionId].timestamp; + if (typeof args.serverResponseTimeMs !== 'undefined') { + bid.serverLatencyMillis = args.serverResponseTimeMs; + } bid.bidResponse = parseBidResponse(args); break; case BIDDER_DONE: diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index eef8a266b68..63055620dde 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -613,6 +613,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('cache_id', '7654321'); expect(response).to.have.property('cache_url', 'http://www.test.com/cache?uuid=7654321'); expect(response).to.not.have.property('vastUrl'); + expect(response).to.have.property('serverResponseTimeMs', 52); }); it('registers video bids', () => { @@ -805,6 +806,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('bidderCode', 'appnexus'); expect(response).to.have.property('adId', '123'); expect(response).to.have.property('cpm', 0.5); + expect(response).to.have.property('serverResponseTimeMs', 8); }); it('handles OpenRTB video responses', () => { @@ -825,6 +827,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('bidderCode', 'appnexus'); expect(response).to.have.property('adId', '123'); expect(response).to.have.property('cpm', 10); + expect(response).to.have.property('serverResponseTimeMs', 81); }); it('should log warning for unsupported bidder', () => { diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index d8f0811e81c..38f8b726cd1 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -84,6 +84,8 @@ const BID2 = Object.assign({}, BID, { height: 90, mediaType: 'banner', cpm: 1.52, + source: 'server', + serverResponseTimeMs: 42, rubiconTargeting: { 'rpfl_elemid': '/19968336/header-bid-tag1', 'rpfl_14062': '2_tier0100' @@ -93,7 +95,7 @@ const BID2 = Object.assign({}, BID, { 'hb_adid': '3bd4ebb1c900e2', 'hb_pb': '1.500', 'hb_size': '728x90', - 'hb_source': 'client' + 'hb_source': 'server' } }); @@ -103,7 +105,7 @@ const MOCK = { [BID2.adUnitCode]: BID2.adserverTargeting }, AUCTION_INIT: { - 'timestamp': 1519149536560, + 'timestamp': 1519767010567, 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', 'timeout': 3000 }, @@ -237,7 +239,7 @@ const ANALYTICS_MESSAGE = { 'bidId': '2ecff0db240757', 'status': 'success', 'source': 'client', - 'clientLatencyMillis': 617477221, + 'clientLatencyMillis': 3214, 'params': { 'accountId': '14062', 'siteId': '70608', @@ -280,15 +282,16 @@ const ANALYTICS_MESSAGE = { 'hb_adid': '3bd4ebb1c900e2', 'hb_pb': '1.500', 'hb_size': '728x90', - 'hb_source': 'client' + 'hb_source': 'server' }, 'bids': [ { 'bidder': 'rubicon', 'bidId': '3bd4ebb1c900e2', 'status': 'success', - 'source': 'client', - 'clientLatencyMillis': 617477221, + 'source': 'server', + 'clientLatencyMillis': 3214, + 'serverLatencyMillis': 42, 'params': { 'accountId': '14062', 'siteId': '70608', @@ -316,7 +319,7 @@ const ANALYTICS_MESSAGE = { 'bidId': '2ecff0db240757', 'status': 'success', 'source': 'client', - 'clientLatencyMillis': 617477221, + 'clientLatencyMillis': 3214, 'samplingFactor': 1, 'accountId': 1001, 'params': { @@ -351,8 +354,9 @@ const ANALYTICS_MESSAGE = { 'adUnitCode': '/19968336/header-bid-tag1', 'bidId': '3bd4ebb1c900e2', 'status': 'success', - 'source': 'client', - 'clientLatencyMillis': 617477221, + 'source': 'server', + 'clientLatencyMillis': 3214, + 'serverLatencyMillis': 42, 'samplingFactor': 1, 'accountId': 1001, 'params': { @@ -368,7 +372,7 @@ const ANALYTICS_MESSAGE = { 'hb_adid': '3bd4ebb1c900e2', 'hb_pb': '1.500', 'hb_size': '728x90', - 'hb_source': 'client' + 'hb_source': 'server' }, 'bidResponse': { 'bidPriceUSD': 1.52, From 2e27a335d4477584e4325d3c4229d8ed0e0d65b7 Mon Sep 17 00:00:00 2001 From: Shrikant Patwari Date: Wed, 18 Apr 2018 22:49:45 +0530 Subject: [PATCH 0284/1594] Analytic Adaptor by YuktaMedia (#2392) * Analytic Adaptor by YuktaMedia * removed optional bid request params * test case modified --- modules/yuktamediaAnalyticsAdapter.js | 144 ++++++++++++++ modules/yuktamediaAnalyticsAdapter.md | 22 +++ .../yuktamediaAnalyticsAdaptor_spec.js | 177 ++++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 modules/yuktamediaAnalyticsAdapter.js create mode 100644 modules/yuktamediaAnalyticsAdapter.md create mode 100644 test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js diff --git a/modules/yuktamediaAnalyticsAdapter.js b/modules/yuktamediaAnalyticsAdapter.js new file mode 100644 index 00000000000..2801ec3afb8 --- /dev/null +++ b/modules/yuktamediaAnalyticsAdapter.js @@ -0,0 +1,144 @@ +import { ajax } from 'src/ajax'; +import adapter from 'src/AnalyticsAdapter'; +import adaptermanager from 'src/adaptermanager'; +import CONSTANTS from 'src/constants.json'; +import * as url from 'src/url'; +import * as utils from 'src/utils'; + +const emptyUrl = ''; +const analyticsType = 'endpoint'; +const yuktamediaAnalyticsVersion = 'v1.0.0'; + +let initOptions; +let auctionTimestamp; +let events = { + bids: [] +}; + +var yuktamediaAnalyticsAdapter = Object.assign(adapter( + { + emptyUrl, + analyticsType + }), { + track({ eventType, args }) { + if (typeof args !== 'undefined') { + if (eventType === CONSTANTS.EVENTS.BID_TIMEOUT) { + args.forEach(item => { mapBidResponse(item, 'timeout'); }); + } else if (eventType === CONSTANTS.EVENTS.AUCTION_INIT) { + events.auctionInit = args; + auctionTimestamp = args.timestamp; + } else if (eventType === CONSTANTS.EVENTS.BID_REQUESTED) { + mapBidRequests(args).forEach(item => { events.bids.push(item) }); + } else if (eventType === CONSTANTS.EVENTS.BID_RESPONSE) { + mapBidResponse(args, 'response'); + } else if (eventType === CONSTANTS.EVENTS.BID_WON) { + send({ + bidWon: mapBidResponse(args, 'win') + }, 'won'); + } + } + + if (eventType === CONSTANTS.EVENTS.AUCTION_END) { + send(events, 'auctionEnd'); + } + } +}); + +function mapBidRequests(params) { + let arr = []; + if (typeof params.bids !== 'undefined' && params.bids.length) { + params.bids.forEach(function (bid) { + arr.push({ + bidderCode: bid.bidder, + bidId: bid.bidId, + adUnitCode: bid.adUnitCode, + requestId: bid.bidderRequestId, + auctionId: bid.auctionId, + transactionId: bid.transactionId, + sizes: utils.parseSizesInput(bid.sizes).toString(), + renderStatus: 1, + requestTimestamp: params.auctionStart + }); + }); + } + return arr; +} + +function mapBidResponse(bidResponse, status) { + if (status !== 'win') { + let bid = events.bids.filter(o => o.bidId == bidResponse.bidId || o.bidId == bidResponse.requestId)[0]; + Object.assign(bid, { + bidderCode: bidResponse.bidder, + bidId: status == 'timeout' ? bidResponse.bidId : bidResponse.requestId, + adUnitCode: bidResponse.adUnitCode, + auctionId: bidResponse.auctionId, + creativeId: bidResponse.creativeId, + transactionId: bidResponse.transactionId, + currency: bidResponse.currency, + cpm: bidResponse.cpm, + netRevenue: bidResponse.netRevenue, + mediaType: bidResponse.mediaType, + statusMessage: bidResponse.statusMessage, + status: bidResponse.status, + renderStatus: status == 'timeout' ? 3 : 2, + timeToRespond: bidResponse.timeToRespond, + requestTimestamp: bidResponse.requestTimestamp, + responseTimestamp: bidResponse.responseTimestamp + }); + } else if (status == 'win') { + return { + bidderCode: bidResponse.bidder, + bidId: bidResponse.requestId, + adUnitCode: bidResponse.adUnitCode, + auctionId: bidResponse.auctionId, + creativeId: bidResponse.creativeId, + transactionId: bidResponse.transactionId, + currency: bidResponse.currency, + cpm: bidResponse.cpm, + netRevenue: bidResponse.netRevenue, + renderedSize: bidResponse.size, + mediaType: bidResponse.mediaType, + statusMessage: bidResponse.statusMessage, + status: bidResponse.status, + renderStatus: 4, + timeToRespond: bidResponse.timeToRespond, + requestTimestamp: bidResponse.requestTimestamp, + responseTimestamp: bidResponse.responseTimestamp + } + } +} + +function send(data, status) { + let location = utils.getTopWindowLocation(); + let secure = location.protocol == 'https:'; + if (typeof data !== 'undefined' && typeof data.auctionInit !== 'undefined') { + data.auctionInit = Object.assign({ host: location.host, path: location.pathname, hash: location.hash, search: location.search }, data.auctionInit); + } + data.initOptions = initOptions; + + let yuktamediaAnalyticsRequestUrl = url.format({ + protocol: secure ? 'https' : 'http', + hostname: 'analytics-prebid.yuktamedia.com', + pathname: status == 'auctionEnd' ? '/api/bids' : '/api/bid/won', + search: { + auctionTimestamp: auctionTimestamp, + yuktamediaAnalyticsVersion: yuktamediaAnalyticsVersion, + prebidVersion: $$PREBID_GLOBAL$$.version + } + }); + + ajax(yuktamediaAnalyticsRequestUrl, undefined, JSON.stringify(data), { method: 'POST', contentType: 'application/json' }); +} + +yuktamediaAnalyticsAdapter.originEnableAnalytics = yuktamediaAnalyticsAdapter.enableAnalytics; +yuktamediaAnalyticsAdapter.enableAnalytics = function (config) { + initOptions = config.options; + yuktamediaAnalyticsAdapter.originEnableAnalytics(config); +}; + +adaptermanager.registerAnalyticsAdapter({ + adapter: yuktamediaAnalyticsAdapter, + code: 'yuktamedia' +}); + +export default yuktamediaAnalyticsAdapter; diff --git a/modules/yuktamediaAnalyticsAdapter.md b/modules/yuktamediaAnalyticsAdapter.md new file mode 100644 index 00000000000..a21675b6b1d --- /dev/null +++ b/modules/yuktamediaAnalyticsAdapter.md @@ -0,0 +1,22 @@ +# Overview +Module Name: YuktaMedia Analytics Adapter + +Module Type: Analytics Adapter + +Maintainer: info@yuktamedia.com + +# Description + +Analytics adapter for prebid provided by YuktaMedia. Contact info@yuktamedia.com for information. + +# Test Parameters + +``` +{ + provider: 'yuktamedia', + options : { + pubId : 50357 //id provided by YuktaMedia LLP + pubKey: 'xxx' //key provided by YuktaMedia LLP + } +} +``` diff --git a/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js b/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js new file mode 100644 index 00000000000..29d23d66bd2 --- /dev/null +++ b/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js @@ -0,0 +1,177 @@ +import yuktamediaAnalyticsAdapter from 'modules/yuktamediaAnalyticsAdapter'; +import { expect } from 'chai'; +let adaptermanager = require('src/adaptermanager'); +let events = require('src/events'); +let constants = require('src/constants.json'); + +describe('YuktaMedia analytics adapter', () => { + let xhr; + let requests; + + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(() => { + xhr.restore(); + events.getEvents.restore(); + }); + + describe('track', () => { + let initOptions = { + pubId: '1', + pubKey: 'ZXlKaGJHY2lPaUpJVXpJMU5pSjkuT==' + }; + + adaptermanager.registerAnalyticsAdapter({ + code: 'yuktamedia', + adapter: yuktamediaAnalyticsAdapter + }); + + beforeEach(() => { + adaptermanager.enableAnalytics({ + provider: 'yuktamedia', + options: initOptions + }); + }); + + afterEach(() => { + yuktamediaAnalyticsAdapter.disableAnalytics(); + }); + + it('builds and sends auction data', () => { + let auctionTimestamp = 1496510254313; + let bidRequest = { + 'bidderCode': 'appnexus', + 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7', + 'bidderRequestId': '173209942f8bdd', + 'bids': [{ + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394' + }, + 'crumbs': { + 'pubcid': '9a2a4e71-f39b-405f-aecc-19efc22b618d' + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '2eddfdc0c791dc', + 'bidderRequestId': '173209942f8bdd', + 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7' + } + ], + 'auctionStart': 1522265863591, + 'timeout': 3000, + 'start': 1522265863600, + 'doneCbCallCount': 1 + }; + let bidResponse = { + 'height': 250, + 'statusMessage': 'Bid available', + 'adId': '2eddfdc0c791dc', + 'mediaType': 'banner', + 'source': 'client', + 'requestId': '2eddfdc0c791dc', + 'cpm': 0.5, + 'creativeId': 29681110, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7', + 'responseTimestamp': 1522265866110, + 'requestTimestamp': 1522265863600, + 'bidder': 'appnexus', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'timeToRespond': 2510, + 'size': '300x250' + }; + let bidTimeoutArgsV1 = [ + { + bidId: '2baa51527bd015', + bidder: 'bidderOne', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + }, + { + bidId: '6fe3b4c2c23092', + bidder: 'bidderTwo', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + } + ]; + let bid = { + 'bidderCode': 'appnexus', + 'bidId': '2eddfdc0c791dc', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'requestId': '173209942f8bdd', + 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7', + 'renderStatus': 2, + 'cpm': 0.5, + 'creativeId': 29681110, + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': true, + 'requestTimestamp': 1522265863600, + 'responseTimestamp': 1522265866110, + 'sizes': '300x250,300x600', + 'statusMessage': 'Bid available', + 'timeToRespond': 2510 + } + + // Step 1: Send auction init event + events.emit(constants.EVENTS.AUCTION_INIT, { + timestamp: auctionTimestamp + }); + + // Step 2: Send bid requested event + events.emit(constants.EVENTS.BID_REQUESTED, bidRequest); + + // Step 3: Send bid response event + events.emit(constants.EVENTS.BID_RESPONSE, bidResponse); + + // Step 4: Send bid time out event + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeoutArgsV1); + + // Step 5: Send auction end event + events.emit(constants.EVENTS.AUCTION_END, {}, 'auctionEnd'); + + expect(requests.length).to.equal(1); + + let auctionEventData = JSON.parse(requests[0].requestBody); + + expect(auctionEventData.bids.length).to.equal(1); + expect(auctionEventData.bids[0]).to.deep.equal(bid); + + expect(auctionEventData.initOptions).to.deep.equal(initOptions); + + // Step 6: Send auction bid won event + events.emit(constants.EVENTS.BID_WON, { + 'bidderCode': 'appnexus', + 'statusMessage': 'Bid available', + 'adId': '108abedd106b669', + 'auctionId': '6355d610-7cdc-4009-a866-f91997fd24bb', + 'responseTimestamp': 1522144433058, + 'requestTimestamp': 1522144432923, + 'bidder': 'appnexus', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'timeToRespond': 135, + 'size': '300x250', + 'status': 'rendered' + }, 'won'); + + expect(requests.length).to.equal(2); + + let winEventData = JSON.parse(requests[1].requestBody); + + expect(winEventData.bidWon.status).to.equal('rendered'); + expect(winEventData.initOptions).to.deep.equal(initOptions); + }); + }); +}); From 1a7dac7b99220d367fbbd041202341897f1f3b52 Mon Sep 17 00:00:00 2001 From: haohany Date: Fri, 20 Apr 2018 08:52:39 -0700 Subject: [PATCH 0285/1594] Add type conversion for openx parameters (#2408) --- modules/prebidServerBidAdapter.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 1ef1d325379..7bded03f3fb 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -205,6 +205,10 @@ const paramTypes = { 'secure': tryConvertNumber, 'mobile': tryConvertNumber }, + 'openx': { + 'unit': tryConvertString, + 'customFloor': tryConvertNumber + }, }; /* From a48df1ef8fc9bfff5744e70e0a75b8f0a4084a78 Mon Sep 17 00:00:00 2001 From: Zhaoyong Ma <33766472+moonshells@users.noreply.github.com> Date: Fri, 20 Apr 2018 12:05:20 -0700 Subject: [PATCH 0286/1594] add gdpr support to rubicon video in rubiconBidAdapter (#2426) --- modules/rubiconBidAdapter.js | 25 +++++++---- test/spec/modules/rubiconBidAdapter_spec.js | 50 ++++++++++++++------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 9cb4b0ab6cc..dd716e6903b 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { config } from 'src/config'; -import { BANNER, VIDEO } from 'src/mediaTypes'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import {config} from 'src/config'; +import {BANNER, VIDEO} from 'src/mediaTypes'; const INTEGRATION = 'pbjs_lite_v$prebid.version$'; @@ -79,7 +79,7 @@ export const spec = { * @param {object} bid * @return boolean */ - isBidRequestValid: function(bid) { + isBidRequestValid: function (bid) { if (typeof bid.params !== 'object') { return false; } @@ -121,7 +121,7 @@ export const spec = { * @param bidderRequest * @return ServerRequest[] */ - buildRequests: function(bidRequests, bidderRequest) { + buildRequests: function (bidRequests, bidderRequest) { return bidRequests.map(bidRequest => { bidRequest.startTime = new Date().getTime(); @@ -178,6 +178,11 @@ export const spec = { data.slots.push(slotData); + if (bidderRequest && bidRequest.gdprConsent) { + data.gdpr = bidRequest.gdprConsent.consentRequired ? 1 : 0; + data.gdpr_consent = bidRequest.gdprConsent.consentString; + } + return { method: 'POST', url: VIDEO_ENDPOINT, @@ -259,7 +264,7 @@ export const spec = { * @param {BidRequest} bidRequest * @returns {boolean} */ - hasVideoMediaType: function(bidRequest) { + hasVideoMediaType: function (bidRequest) { return (typeof utils.deepAccess(bidRequest, 'params.video.size_id') !== 'undefined' && (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}.context`) === 'instream')); }, @@ -268,7 +273,7 @@ export const spec = { * @param {BidRequest} bidRequest * @return {Bid[]} An array of bids which */ - interpretResponse: function(responseObj, {bidRequest}) { + interpretResponse: function (responseObj, {bidRequest}) { responseObj = responseObj.body let ads = responseObj.ads; @@ -336,7 +341,7 @@ export const spec = { return bids; }, []); }, - getUserSyncs: function(syncOptions) { + getUserSyncs: function (syncOptions) { if (!hasSynced && syncOptions.iframeEnabled) { hasSynced = true; return { @@ -360,6 +365,7 @@ function _getDigiTrustQueryParams() { let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; } + let digiTrustId = getDigiTrustId(); // Verify there is an ID and this user has not opted out if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { @@ -407,7 +413,7 @@ function parseSizes(bid) { function mapSizes(sizes) { return utils.parseSizesInput(sizes) - // map sizes while excluding non-matches + // map sizes while excluding non-matches .reduce((result, size) => { let mappedSize = parseInt(sizeMap[size], 10); if (mappedSize) { @@ -448,6 +454,7 @@ export function masSizeOrdering(sizes) { } var hasSynced = false; + export function resetUserSync() { hasSynced = false; } diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 954348935df..971ce7848e6 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1,10 +1,10 @@ -import { expect } from 'chai'; +import {expect} from 'chai'; import adapterManager from 'src/adaptermanager'; -import { spec, masSizeOrdering, resetUserSync } from 'modules/rubiconBidAdapter'; -import { parse as parseQuery } from 'querystring'; -import { newBidder } from 'src/adapters/bidderFactory'; -import { userSync } from 'src/userSync'; -import { config } from 'src/config'; +import {spec, masSizeOrdering, resetUserSync} from 'modules/rubiconBidAdapter'; +import {parse as parseQuery} from 'querystring'; +import {newBidder} from 'src/adapters/bidderFactory'; +import {userSync} from 'src/userSync'; +import {config} from 'src/config'; import * as utils from 'src/utils'; var CONSTANTS = require('src/constants.json'); @@ -24,6 +24,11 @@ describe('the rubicon adapter', () => { } }; + bid.gdprConsent = { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'consentRequired': true + }; + bid.params.video = { 'language': 'en', 'p_aso.video.ext.skip': true, @@ -43,6 +48,10 @@ describe('the rubicon adapter', () => { // Legacy property (Prebid <1.0) bid.mediaType = 'video'; + bid.gdprConsent = { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'consentRequired': true + }; bid.params.video = { 'language': 'en', 'p_aso.video.ext.skip': true, @@ -246,7 +255,7 @@ describe('the rubicon adapter', () => { expect(parseQuery(request.data).rf).to.equal('http://www.prebid.org'); let origGetConfig = config.getConfig; - sandbox.stub(config, 'getConfig').callsFake(function(key) { + sandbox.stub(config, 'getConfig').callsFake(function (key) { if (key === 'pageUrl') { return 'http://www.rubiconproject.com'; } @@ -301,7 +310,8 @@ describe('the rubicon adapter', () => { it('should send digitrust params', () => { window.DigiTrust = { - getUser: function() {} + getUser: function () { + } }; sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => ({ @@ -346,7 +356,8 @@ describe('the rubicon adapter', () => { it('should not send digitrust params due to optout', () => { window.DigiTrust = { - getUser: function() {} + getUser: function () { + } }; sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => ({ @@ -374,7 +385,8 @@ describe('the rubicon adapter', () => { it('should not send digitrust params due to failure', () => { window.DigiTrust = { - getUser: function() {} + getUser: function () { + } }; sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => ({ @@ -548,6 +560,8 @@ describe('the rubicon adapter', () => { expect(post).to.have.property('timeout').that.is.a('number'); expect(post.timeout < 5000).to.equal(true); expect(post.stash_creatives).to.equal(true); + expect(post.gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + expect(post.gdpr).to.equal(1); expect(post).to.have.property('ae_pass_through_parameters'); expect(post.ae_pass_through_parameters) @@ -609,6 +623,8 @@ describe('the rubicon adapter', () => { expect(post).to.have.property('timeout').that.is.a('number'); expect(post.timeout < 5000).to.equal(true); expect(post.stash_creatives).to.equal(true); + expect(post.gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + expect(post.gdpr).to.equal(1); expect(post).to.have.property('ae_pass_through_parameters'); expect(post.ae_pass_through_parameters) @@ -752,7 +768,7 @@ describe('the rubicon adapter', () => { bidRequestCopy.params.video = 123; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - bidRequestCopy.params.video = { size_id: undefined }; + bidRequestCopy.params.video = {size_id: undefined}; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); delete bidRequestCopy.params.video; @@ -936,7 +952,7 @@ describe('the rubicon adapter', () => { ] }; - let bids = spec.interpretResponse({ body: response }, { + let bids = spec.interpretResponse({body: response}, { bidRequest: bidderRequest.bids[0] }); @@ -992,7 +1008,7 @@ describe('the rubicon adapter', () => { }] }; - let bids = spec.interpretResponse({ body: response }, { + let bids = spec.interpretResponse({body: response}, { bidRequest: bidderRequest.bids[0] }); @@ -1015,7 +1031,7 @@ describe('the rubicon adapter', () => { 'ads': [] }; - let bids = spec.interpretResponse({ body: response }, { + let bids = spec.interpretResponse({body: response}, { bidRequest: bidderRequest.bids[0] }); @@ -1039,7 +1055,7 @@ describe('the rubicon adapter', () => { }] }; - let bids = spec.interpretResponse({ body: response }, { + let bids = spec.interpretResponse({body: response}, { bidRequest: bidderRequest.bids[0] }); @@ -1049,7 +1065,7 @@ describe('the rubicon adapter', () => { it('should handle an error because of malformed json response', () => { let response = '{test{'; - let bids = spec.interpretResponse({ body: response }, { + let bids = spec.interpretResponse({body: response}, { bidRequest: bidderRequest.bids[0] }); @@ -1090,7 +1106,7 @@ describe('the rubicon adapter', () => { 'account_id': 7780 }; - let bids = spec.interpretResponse({ body: response }, { + let bids = spec.interpretResponse({body: response}, { bidRequest: bidderRequest.bids[0] }); From 204daaeff195cac6c68ef137106311163e15418e Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Sat, 21 Apr 2018 02:00:48 +0530 Subject: [PATCH 0287/1594] Media.net Adapter Improvements (#2344) * onTimeout added to spec * adding test cases file * passing canonical,og, and twitter urls to server * reverted all changes related to onTimeout and logging pixels --- modules/medianetBidAdapter.js | 52 +++++++++++++++++--- test/spec/modules/medianetBidAdapter_spec.js | 39 +++++++++++++-- 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index e8a98721e0c..8fe09ab74e6 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -3,18 +3,53 @@ import * as utils from 'src/utils'; import { config } from 'src/config'; const BIDDER_CODE = 'medianet'; -const BID_URL = 'https://prebid.media.net/rtb/prebid'; +const BID_URL = '//prebid.media.net/rtb/prebid'; $$PREBID_GLOBAL$$.medianetGlobals = {}; function siteDetails(site) { site = site || {}; - - return { + let siteData = { domain: site.domain || utils.getTopWindowLocation().host, page: site.page || utils.getTopWindowUrl(), ref: site.ref || utils.getTopWindowReferrer() - } + }; + + return Object.assign(siteData, getPageMeta()); +} + +function getPageMeta() { + let canonicalUrl = getUrlFromSelector('link[rel="canonical"]', 'href'); + let ogUrl = getUrlFromSelector('meta[property="og:url"]', 'content'); + let twitterUrl = getUrlFromSelector('meta[name="twitter:url"]', 'content'); + + return Object.assign({}, + canonicalUrl && { 'canonical_url': canonicalUrl }, + ogUrl && { 'og_url': ogUrl }, + twitterUrl && { 'twitter_url': twitterUrl } + ); +} + +function getUrlFromSelector(selector, attribute) { + let attr = getAttributeFromSelector(selector, attribute); + return attr && getAbsoluteUrl(attr); +} + +function getAttributeFromSelector(selector, attribute) { + try { + let doc = utils.getWindowTop().document; + let element = doc.querySelector(selector); + if (element !== null && element[attribute]) { + return element[attribute]; + } + } catch (e) {} +} + +function getAbsoluteUrl(url) { + let aTag = utils.getWindowTop().document.createElement('a'); + aTag.href = url; + + return aTag.href; } function filterUrlsByType(urls, type) { @@ -65,13 +100,13 @@ function slotParams(bidRequest) { return params; } -function generatePayload(bidRequests) { +function generatePayload(bidRequests, timeout) { return { site: siteDetails(bidRequests[0].params.site), ext: configuredParams(bidRequests[0].params), id: bidRequests[0].auctionId, imp: bidRequests.map(request => slotParams(request)), - tmax: config.getConfig('bidderTimeout') + tmax: timeout } } @@ -120,8 +155,9 @@ export const spec = { * @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) { - let payload = generatePayload(bidRequests); + buildRequests: function(bidRequests, auctionData) { + let timeout = auctionData.timeout || config.getConfig('bidderTimeout'); + let payload = generatePayload(bidRequests, timeout); return { method: 'POST', diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 36868e7f993..520ec34fc7d 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -69,6 +69,9 @@ let VALID_BID_REQUEST = [{ 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }], + VALID_AUCTIONDATA = { + 'timeout': config.getConfig('bidderTimeout'), + }, VALID_PAYLOAD_INVALID_BIDFLOOR = { 'site': { 'page': 'http://media.net/prebidtest', @@ -166,6 +169,18 @@ let VALID_BID_REQUEST = [{ }], 'tmax': config.getConfig('bidderTimeout') }, + VALID_PAYLOAD_PAGE_META = (() => { + let PAGE_META; + try { + PAGE_META = JSON.parse(JSON.stringify(VALID_PAYLOAD)); + } catch (e) {} + PAGE_META.site = Object.assign(PAGE_META.site, { + 'canonical_url': 'http://localhost:9999/canonical-test', + 'twitter_url': 'http://localhost:9999/twitter-test', + 'og_url': 'http://localhost:9999/fb-test' + }); + return PAGE_META; + })(), VALID_PARAMS = { bidder: 'medianet', params: { @@ -343,19 +358,37 @@ describe('Media.net bid adapter', () => { describe('buildRequests', () => { it('should build valid payload on bid', () => { - let requestObj = spec.buildRequests(VALID_BID_REQUEST); + let requestObj = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); expect(JSON.parse(requestObj.data)).to.deep.equal(VALID_PAYLOAD); }); it('should accept size as a one dimensional array', () => { - let bidReq = spec.buildRequests(BID_REQUEST_SIZE_AS_1DARRAY); + let bidReq = spec.buildRequests(BID_REQUEST_SIZE_AS_1DARRAY, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD); }); it('should ignore bidfloor if not a valid number', () => { - let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR); + let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_INVALID_BIDFLOOR); }); + describe('build requests: when page meta-data is available', () => { + it('should pass canonical, twitter and fb paramters if available', () => { + let sandbox = sinon.sandbox.create(); + let documentStub = sandbox.stub(window.top.document, 'querySelector'); + documentStub.withArgs('link[rel="canonical"]').returns({ + href: 'http://localhost:9999/canonical-test' + }); + documentStub.withArgs('meta[property="og:url"]').returns({ + content: 'http://localhost:9999/fb-test' + }); + documentStub.withArgs('meta[name="twitter:url"]').returns({ + content: 'http://localhost:9999/twitter-test' + }); + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_PAGE_META); + sandbox.restore(); + }); + }); }); describe('getUserSyncs', () => { From 372899b96de0887b5704632fc75ba07fe2f39a85 Mon Sep 17 00:00:00 2001 From: r-sato Date: Tue, 24 Apr 2018 23:58:04 +0900 Subject: [PATCH 0288/1594] Add New Adapter dgadsBidAdapter (#2429) * Add dgads adapter * Add dgads adapter * Add spec file for dgads * Add spec file for dgads * Add dgads bid adapter * Add dgads bid adapter * fix * fix * fix email * remove semi-colon * Add mediaType native * Add import medaTypes --- modules/dgadsBidAdapter.js | 88 +++++++ modules/dgadsBidAdapter.md | 65 +++++ test/spec/modules/dgadsBidAdapter_spec.js | 291 ++++++++++++++++++++++ 3 files changed, 444 insertions(+) create mode 100644 modules/dgadsBidAdapter.js create mode 100644 modules/dgadsBidAdapter.md create mode 100644 test/spec/modules/dgadsBidAdapter_spec.js diff --git a/modules/dgadsBidAdapter.js b/modules/dgadsBidAdapter.js new file mode 100644 index 00000000000..7d47cc7acf6 --- /dev/null +++ b/modules/dgadsBidAdapter.js @@ -0,0 +1,88 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; +import { BANNER, NATIVE } from 'src/mediaTypes'; + +const BIDDER_CODE = 'dgads'; +const ENDPOINT = 'https://ads-tr.bigmining.com/ad/p/bid'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, NATIVE ], + isBidRequestValid: function(bid) { + const params = bid.params; + if (!/^\d+$/.test(params.location_id)) { + return false; + } + if (!/^\d+$/.test(params.site_id)) { + return false; + } + return true; + }, + buildRequests: function(bidRequests) { + if (bidRequests.length === 0) { + return {}; + } + + return bidRequests.map(bidRequest => { + const params = bidRequest.params; + const data = {}; + + data['location_id'] = params.location_id; + data['site_id'] = params.site_id; + data['transaction_id'] = bidRequest.transactionId; + data['bid_id'] = bidRequest.bidId; + + return { + method: 'POST', + url: ENDPOINT, + data, + }; + }); + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + const responseObj = serverResponse.body; + const ads = responseObj.bids; + let bidResponse = {}; + if (utils.isEmpty(ads)) { + return []; + } + utils._each(ads, function(ad) { + bidResponse.requestId = ad.bidId; + bidResponse.bidderCode = BIDDER_CODE; + bidResponse.cpm = ad.cpm; + bidResponse.creativeId = ad.creativeId; + bidResponse.currency = 'JPY'; + bidResponse.netRevenue = true; + bidResponse.ttl = ad.ttl; + bidResponse.referrer = utils.getTopWindowUrl(); + if (ad.isNative == 1) { + bidResponse.mediaType = NATIVE; + bidResponse.native = setNativeResponse(ad); + } else { + bidResponse.width = parseInt(ad.w); + bidResponse.height = parseInt(ad.h); + bidResponse.ad = ad.ad; + } + bidResponses.push(bidResponse); + }); + return bidResponses; + } +}; +function setNativeResponse(ad) { + let nativeResponce = {}; + nativeResponce.image = { + url: ad.image, + width: parseInt(ad.w), + height: parseInt(ad.h) + } + nativeResponce.title = ad.title; + nativeResponce.body = ad.desc; + nativeResponce.sponsoredBy = ad.sponsoredBy; + nativeResponce.clickUrl = ad.clickUrl; + nativeResponce.clickTrackers = ad.clickTrackers || []; + nativeResponce.impressionTrackers = ad.impressionTrackers || []; + return nativeResponce; +} + +registerBidder(spec); diff --git a/modules/dgadsBidAdapter.md b/modules/dgadsBidAdapter.md new file mode 100644 index 00000000000..b1544007a43 --- /dev/null +++ b/modules/dgadsBidAdapter.md @@ -0,0 +1,65 @@ +# Overview + +``` +Module Name: Digital Garage Ads Platform Bidder Adapter +Module Type: Bidder Adapter +Maintainer:dgads-support@garage.co.jp +``` + +# Description + +Connect to Digital Garage Ads Platform for bids. +This adapter supports Banner and Native. + +# Test Parameters +``` + var adUnits = [ + // Banner + { + code: 'banner-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'dgads', + mediaTypes: 'banner', + params: { + location_id: '1', + site_id: '1' + } + }] + }, + // Native + { + code: 'native-div', + sizes: [[300, 250]], + mediaTypes: { + native: { + title: { + required: true, + len: 25 + }, + body: { + required: true, + len: 140 + }, + sponsoredBy: { + required: true, + len: 40 + }, + image: { + required: true + }, + clickUrl: { + required: true + }, + } + }, + bids: [{ + bidder: 'dgads', + params: { + location_id: '10', + site_id: '1' + } + }] + }, + ]; +``` diff --git a/test/spec/modules/dgadsBidAdapter_spec.js b/test/spec/modules/dgadsBidAdapter_spec.js new file mode 100644 index 00000000000..89affd94880 --- /dev/null +++ b/test/spec/modules/dgadsBidAdapter_spec.js @@ -0,0 +1,291 @@ +import {expect} from 'chai'; +import * as utils from 'src/utils'; +import {spec} from 'modules/dgadsBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE } from 'src/mediaTypes'; + +describe('dgadsBidAdapter', () => { + const adapter = newBidder(spec); + const VALID_ENDPOINT = 'https://ads-tr.bigmining.com/ad/p/bid'; + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'dgads', + params: { + site_id: '1', + location_id: '1' + } + }; + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params(location_id) are not passed', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + site_id: '1' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when required params(site_id) are not passed', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + location_id: '1' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const bidRequests = [ + { // banner + bidder: 'dgads', + mediaType: 'banner', + params: { + site_id: '1', + location_id: '1' + }, + adUnitCode: 'adunit-code', + sizes: [[300, 250]], + bidId: '2db3101abaec66', + bidderRequestId: '14a9f773e30243', + auctionId: 'c0cd37c5-af11-464d-b83e-35863e533b1f', + transactionId: 'c1f1eff6-23c6-4844-a321-575212939e37' + }, + { // native + bidder: 'dgads', + sizes: [[300, 250]], + params: { + site_id: '1', + location_id: '10' + }, + mediaTypes: { + native: { + image: { + required: true + }, + title: { + required: true, + len: 25 + }, + clickUrl: { + required: true + }, + body: { + required: true, + len: 140 + }, + sponsoredBy: { + required: true, + len: 40 + } + }, + }, + adUnitCode: 'adunit-code', + bidId: '2db3101abaec66', + bidderRequestId: '14a9f773e30243', + auctionId: 'c0cd37c5-af11-464d-b83e-35863e533b1f', + transactionId: 'c1f1eff6-23c6-4844-a321-575212939e37' + } + ]; + it('no bidRequests', () => { + const noBidRequests = []; + expect(Object.keys(spec.buildRequests(noBidRequests)).length).to.equal(0); + }); + const data = { + location_id: '1', + site_id: '1', + transaction_id: 'c1f1eff6-23c6-4844-a321-575212939e37', + bid_id: '2db3101abaec66' + }; + it('sends bid request to VALID_ENDPOINT via POST', () => { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal(VALID_ENDPOINT); + expect(request.method).to.equal('POST'); + }); + it('should attache params to the request', () => { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.data['location_id']).to.equal(data['location_id']); + expect(request.data['site_id']).to.equal(data['site_id']); + expect(request.data['transaction_id']).to.equal(data['transaction_id']); + expect(request.data['bid_id']).to.equal(data['bid_id']); + }); + }); + + describe('interpretResponse', () => { + const bidRequests = { + banner: { + bidRequest: { + bidder: 'dgads', + params: { + location_id: '1', + site_id: '1' + }, + transactionId: 'c1f1eff6-23c6-4844-a321-575212939e37', + bidId: '2db3101abaec66', + adUnitCode: 'adunit-code', + sizes: [[300, 250]], + bidderRequestId: '14a9f773e30243', + auctionId: 'c0cd37c5-af11-464d-b83e-35863e533b1f' + }, + }, + native: { + bidRequest: { + bidder: 'adg', + params: { + site_id: '1', + location_id: '10' + }, + mediaTypes: { + native: { + image: { + required: true + }, + title: { + required: true, + len: 25 + }, + body: { + required: true, + len: 140 + }, + sponsoredBy: { + required: true, + len: 40 + } + } + }, + transactionId: 'f76f6dfd-d64f-4645-a29f-682bac7f431a', + bidId: '2f6ac468a9c15e', + adUnitCode: 'adunit-code', + sizes: [[1, 1]], + bidderRequestId: '14a9f773e30243', + auctionId: '4aae9f05-18c6-4fcd-80cf-282708cd584a', + }, + }, + }; + + const serverResponse = { + noAd: { + results: [], + }, + banner: { + bids: { + ads: { + ad: '', + cpm: 1.22, + w: 300, + h: 250, + creativeId: 'xuidx62944aab4fx37f', + ttl: 60, + bidId: '2f6ac468a9c15e' + } + } + }, + native: { + bids: { + ads: { + cpm: 1.22, + title: 'title', + desc: 'description', + sponsoredBy: 'sponsoredBy', + image: 'https://ads-tr.bigmining.com/img/300_250_1.jpg', + w: 300, + h: 250, + ttl: 60, + bidId: '2f6ac468a9c15e', + creativeId: 'xuidx62944aab4fx37f', + isNative: 1, + impressionTrackers: ['https://ads-tr.bigmining.com/ad/view/beacon.gif'], + clickTrackers: ['https://ads-tr.bigmining.com/ad/view/beacon.png'], + clickUrl: 'http://www.garage.co.jp/ja/' + }, + } + } + }; + + const bidResponses = { + banner: { + requestId: '2f6ac468a9c15e', + cpm: 1.22, + width: 300, + height: 250, + creativeId: 'xuidx62944aab4fx37f', + currency: 'JPY', + netRevenue: true, + ttl: 60, + referrer: utils.getTopWindowUrl(), + ad: '', + }, + native: { + requestId: '2f6ac468a9c15e', + cpm: 1.22, + creativeId: 'xuidx62944aab4fx37f', + currency: 'JPY', + netRevenue: true, + ttl: 60, + native: { + image: { + url: 'https://ads-tr.bigmining.com/img/300_250_1.jpg', + width: 300, + height: 250 + }, + title: 'title', + body: 'description', + sponsoredBy: 'sponsoredBy', + clickUrl: 'http://www.garage.co.jp/ja/', + impressionTrackers: ['https://ads-tr.bigmining.com/ad/view/beacon.gif'], + clickTrackers: ['https://ads-tr.bigmining.com/ad/view/beacon.png'] + }, + referrer: utils.getTopWindowUrl(), + creativeid: 'xuidx62944aab4fx37f', + mediaType: NATIVE + } + }; + + it('no bid responses', () => { + const result = spec.interpretResponse({body: serverResponse.noAd}, bidRequests.banner); + expect(result.length).to.equal(0); + }); + it('handles banner responses', () => { + const result = spec.interpretResponse({body: serverResponse.banner}, bidRequests.banner)[0]; + expect(result.requestId).to.equal(bidResponses.banner.requestId); + expect(result.width).to.equal(bidResponses.banner.width); + expect(result.height).to.equal(bidResponses.banner.height); + expect(result.creativeId).to.equal(bidResponses.banner.creativeId); + expect(result.currency).to.equal(bidResponses.banner.currency); + expect(result.netRevenue).to.equal(bidResponses.banner.netRevenue); + expect(result.ttl).to.equal(bidResponses.banner.ttl); + expect(result.referrer).to.equal(bidResponses.banner.referrer); + expect(result.ad).to.equal(bidResponses.banner.ad); + }); + + it('handles native responses', () => { + const result = spec.interpretResponse({body: serverResponse.native}, bidRequests.native)[0]; + expect(result.requestId).to.equal(bidResponses.native.requestId); + expect(result.creativeId).to.equal(bidResponses.native.creativeId); + expect(result.currency).to.equal(bidResponses.native.currency); + expect(result.netRevenue).to.equal(bidResponses.native.netRevenue); + expect(result.ttl).to.equal(bidResponses.native.ttl); + expect(result.referrer).to.equal(bidResponses.native.referrer); + expect(result.native.title).to.equal(bidResponses.native.native.title); + expect(result.native.body).to.equal(bidResponses.native.native.body); + expect(result.native.sponsoredBy).to.equal(bidResponses.native.native.sponsoredBy); + expect(result.native.image.url).to.equal(bidResponses.native.native.image.url); + expect(result.native.image.width).to.equal(bidResponses.native.native.image.width); + expect(result.native.image.height).to.equal(bidResponses.native.native.image.height); + expect(result.native.clickUrl).to.equal(bidResponses.native.native.clickUrl); + expect(result.native.impressionTrackers[0]).to.equal(bidResponses.native.native.impressionTrackers[0]); + expect(result.native.clickTrackers[0]).to.equal(bidResponses.native.native.clickTrackers[0]); + }); + }); +}); From d94404c6e4dca98e81dbb37986d17793cc19985e Mon Sep 17 00:00:00 2001 From: sami-elasticad <35566930+sami-elasticad@users.noreply.github.com> Date: Tue, 24 Apr 2018 18:15:07 +0300 Subject: [PATCH 0289/1594] Size Bugfix (#2414) * quantumBidAdapter initial commit * eslint errors fixed * updating quantumBidAdapter for reviews, fixed tests to work with native * set new prebid location for testing and some fixing * added supportedMediaTypes * Tests fixed * Fixed issues with image assets. Tested with the example provided * Size and tests fixed * Modify tests * hello world revert changes * package-lock reverted * hello world reverted CRLF/LF Conversion * hello world reverted LF/CRLF Conversion * hello world reverted * hello world reverted * hello world reverted * removed hardcoded bid sizes --- modules/quantumBidAdapter.js | 8 ++++++-- test/spec/modules/quantumBidAdapter_spec.js | 7 ++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/quantumBidAdapter.js b/modules/quantumBidAdapter.js index 242ccc63204..f6df8a2ff61 100644 --- a/modules/quantumBidAdapter.js +++ b/modules/quantumBidAdapter.js @@ -99,12 +99,15 @@ export const spec = { if (serverBody.cobj) { bid.cobj = serverBody.cobj; } + if (bidRequest.sizes) { + bid.width = bidRequest.sizes[0][0]; + bid.height = bidRequest.sizes[0][1]; + } bid.nurl = serverBody.nurl; bid.sync = serverBody.sync; if (bidRequest.renderMode && bidRequest.renderMode === 'banner') { - bid.width = 300; - bid.height = 225; + bid.mediaType = 'banner'; if (serverBody.native) { const adAssetsUrl = '//cdn.elasticad.net/native/serve/js/quantx/quantumAd/'; let assets = serverBody.native.assets; @@ -216,6 +219,7 @@ export const spec = { } } else { // native + bid.mediaType = 'native'; if (bidRequest.mediaType === 'native') { if (serverBody.native) { let assets = serverBody.native.assets; diff --git a/test/spec/modules/quantumBidAdapter_spec.js b/test/spec/modules/quantumBidAdapter_spec.js index 2db1c0b0fbd..053ec98ffaa 100644 --- a/test/spec/modules/quantumBidAdapter_spec.js +++ b/test/spec/modules/quantumBidAdapter_spec.js @@ -5,7 +5,7 @@ import { newBidder } from 'src/adapters/bidderFactory' const ENDPOINT = '//s.sspqns.com/hb' const REQUEST = { 'bidder': 'quantum', - 'sizes': [[300, 225]], + 'sizes': [[300, 250]], 'renderMode': 'banner', 'params': { placementId: 21546 @@ -245,6 +245,7 @@ describe('quantumBidAdapter', () => { expect(result[0]).to.have.property('cpm').equal(0.3) expect(result[0]).to.have.property('width').to.be.below(2) expect(result[0]).to.have.property('height').to.be.below(2) + expect(result[0]).to.have.property('mediaType').equal('native') expect(result[0]).to.have.property('native') }) @@ -252,8 +253,8 @@ describe('quantumBidAdapter', () => { const result = spec.interpretResponse({body: serverResponse}, REQUEST) expect(result[0]).to.have.property('cpm').equal(0.3) expect(result[0]).to.have.property('width').equal(300) - expect(result[0]).to.have.property('height').equal(225) - // expect(result[0]).to.have.property('native'); + expect(result[0]).to.have.property('height').equal(250) + expect(result[0]).to.have.property('mediaType').equal('banner') expect(result[0]).to.have.property('ad') }) From 34f34d8431d33e4b0bae4db910214d055259e47b Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 24 Apr 2018 11:25:57 -0700 Subject: [PATCH 0290/1594] Rubicon adapter GDPR support (#2406) * Merged gdpr tests for banner bid requests * Renamed the gdprConsent.consentRequired to gdprConsent.gdprApplies. Changed containing object used to access gdprConsent values (bidRequest -> bidderRequest) --- modules/rubiconBidAdapter.js | 15 +++- test/spec/modules/rubiconBidAdapter_spec.js | 97 ++++++++++++++++++--- 2 files changed, 97 insertions(+), 15 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index dd716e6903b..d3735f01d62 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -178,9 +178,9 @@ export const spec = { data.slots.push(slotData); - if (bidderRequest && bidRequest.gdprConsent) { - data.gdpr = bidRequest.gdprConsent.consentRequired ? 1 : 0; - data.gdpr_consent = bidRequest.gdprConsent.consentString; + if (bidderRequest && bidderRequest.gdprConsent) { + data.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; + data.gdpr_consent = bidderRequest.gdprConsent.consentString; } return { @@ -228,6 +228,15 @@ export const spec = { 'tk_user_key', userId ]; + // add GDPR properties if enabled + if (config.getConfig('consentManagement') && + bidderRequest && bidderRequest.gdprConsent && typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { + data.push( + 'gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0, + 'gdpr_consent', bidderRequest.gdprConsent.consentString + ); + } + if (visitor !== null && typeof visitor === 'object') { utils._each(visitor, (item, key) => data.push(`tg_v.${key}`, item)); } diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 971ce7848e6..cc996041aac 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -15,20 +15,22 @@ describe('the rubicon adapter', () => { let sandbox, bidderRequest; + function addConsentManagement() { + bidderRequest.gdprConsent = { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'gdprApplies': true + } + } + function createVideoBidderRequest() { - let bid = bidderRequest.bids[0]; + addConsentManagement(); + let bid = bidderRequest.bids[0]; bid.mediaTypes = { video: { context: 'instream' } }; - - bid.gdprConsent = { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'consentRequired': true - }; - bid.params.video = { 'language': 'en', 'p_aso.video.ext.skip': true, @@ -44,14 +46,11 @@ describe('the rubicon adapter', () => { } function createLegacyVideoBidderRequest() { - let bid = bidderRequest.bids[0]; + addConsentManagement(); + let bid = bidderRequest.bids[0]; // Legacy property (Prebid <1.0) bid.mediaType = 'video'; - bid.gdprConsent = { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'consentRequired': true - }; bid.params.video = { 'language': 'en', 'p_aso.video.ext.skip': true, @@ -535,6 +534,80 @@ describe('the rubicon adapter', () => { expect(window.DigiTrust.getUser.calledOnce).to.equal(true); }); }); + + it('should send GDPR params when enabled', () => { + addConsentManagement(); + + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + consentManagement: { + cmp: 'iab', + waitForConsentTimeout: 4000, + lookUpFailureResolution: 'cancel' + } + }; + return config[key]; + }); + + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); + let expectedQuery = { + 'gdpr': '1', + 'gdpr_consent': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' + }; + + // test that all values above are both present and correct + Object.keys(expectedQuery).forEach(key => { + let value = expectedQuery[key]; + expect(data[key]).to.equal(value); + }); + }); + + it('should not send GDPR params if not enabled', () => { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = {}; + return config[key]; + }); + + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); + let expectedQuery = { + 'gdpr': undefined, + 'gdpr_consent': undefined + }; + + // test that all values above are both present and correct + Object.keys(expectedQuery).forEach(key => { + let value = expectedQuery[key]; + expect(data[key]).to.equal(value); + }); + }); + + it('should not send GDPR params if gdprConsent is not set in config', () => { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + consentManagement: { + cmp: 'iab', + waitForConsentTimeout: 4000, + lookUpFailureResolution: 'cancel' + } + }; + return config[key]; + }); + + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); + let expectedQuery = { + 'gdpr': undefined, + 'gdpr_consent': undefined + }; + + // test that all values above are both present and correct + Object.keys(expectedQuery).forEach(key => { + let value = expectedQuery[key]; + expect(data[key]).to.equal(value); + }); + }); }); describe('for video requests', () => { From 28f6795d24afe0cf46f5743374c61361fc1cd566 Mon Sep 17 00:00:00 2001 From: sekindo Date: Tue, 24 Apr 2018 22:48:18 +0300 Subject: [PATCH 0291/1594] typo (#2441) --- modules/sekindoUMBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/sekindoUMBidAdapter.md b/modules/sekindoUMBidAdapter.md index 05c0227976d..eeffff928eb 100755 --- a/modules/sekindoUMBidAdapter.md +++ b/modules/sekindoUMBidAdapter.md @@ -20,7 +20,7 @@ Banner, Outstream and Native formats are supported. params: { spaceId: 14071 width:300, ///optional - weight:250, //optional + height:250, //optional } }] }, From bb9bc187e2bb8b7478907d0d69ef63c50a72ba38 Mon Sep 17 00:00:00 2001 From: Dave Naffis Date: Thu, 26 Apr 2018 12:04:08 -0400 Subject: [PATCH 0292/1594] Initial Consumable Bidder Adapter commit (#2381) * Initial Consumable Bidder Adapter commit * fix tests and lint errors for Consumable bidder adapter and specs * changes based on reviews by @snapwich and @mkendall07 --- modules/consumableBidAdapter.js | 177 ++++++++++++++ modules/consumableBidAdapter.md | 32 +++ .../spec/modules/consumableBidAdapter_spec.js | 215 ++++++++++++++++++ 3 files changed, 424 insertions(+) create mode 100644 modules/consumableBidAdapter.js create mode 100644 modules/consumableBidAdapter.md create mode 100644 test/spec/modules/consumableBidAdapter_spec.js diff --git a/modules/consumableBidAdapter.js b/modules/consumableBidAdapter.js new file mode 100644 index 00000000000..e6df1daedbd --- /dev/null +++ b/modules/consumableBidAdapter.js @@ -0,0 +1,177 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; +import { EVENTS } from 'src/constants.json'; + +const CONSUMABLE_BIDDER_CODE = 'consumable' + +const SYNC_TYPES = { + IFRAME: { + TAG: 'iframe', + TYPE: 'iframe' + }, + IMAGE: { + TAG: 'img', + TYPE: 'image' + } +}; + +const pubapiTemplate = ({host, network, placement, alias}) => `//${host}/pubapi/3.0/${network}/${placement}/0/0/ADTECH;v=2;cmd=bid;cors=yes;alias=${alias};misc=${new Date().getTime()}` +const CONSUMABLE_URL = 'adserver-us.adtech.advertising.com'; +const CONSUMABLE_TTL = 60; +const CONSUMABLE_NETWORK = '10947.1'; + +$$PREBID_GLOBAL$$.consumableGlobals = { + pixelsDropped: false +}; + +function parsePixelItems(pixels) { + let itemsRegExp = /<(img|iframe)[\s\S]*?src\s*=\s*("|')(.*?)\2/gi; + let tagNameRegExp = /\w*(?=\s)/; + let srcRegExp = /src=("|')(.*?)\1/; + let pixelsItems = []; + + if (pixels) { + let matchedItems = pixels.match(itemsRegExp); + if (matchedItems) { + matchedItems.forEach(item => { + let tagName = item.match(tagNameRegExp)[0]; + let url = item.match(srcRegExp)[2]; + + if (tagName && url) { + pixelsItems.push({ + type: tagName === SYNC_TYPES.IMAGE.TAG ? SYNC_TYPES.IMAGE.TYPE : SYNC_TYPES.IFRAME.TYPE, + url: url + }); + } + }); + } + } + + return pixelsItems; +} + +function _buildConsumableUrl(bid) { + const params = bid.params; + + return pubapiTemplate({ + host: CONSUMABLE_URL, + network: params.network || CONSUMABLE_NETWORK, + placement: parseInt(params.placement, 10) + }); +} + +function formatBidRequest(bid) { + let bidRequest; + + bidRequest = { + url: _buildConsumableUrl(bid), + method: 'GET' + }; + + bidRequest.bidderCode = bid.bidder; + bidRequest.bidId = bid.bidId; + bidRequest.userSyncOn = bid.params.userSyncOn; + bidRequest.unitId = bid.params.unitId; + bidRequest.unitName = bid.params.unitName; + bidRequest.zoneId = bid.params.zoneId; + bidRequest.network = bid.params.network || CONSUMABLE_NETWORK; + + return bidRequest; +} + +function _parseBidResponse (response, bidRequest) { + let bidData; + try { + bidData = response.seatbid[0].bid[0]; + } catch (e) { + return; + } + + let cpm; + + if (bidData.ext && bidData.ext.encp) { + cpm = bidData.ext.encp; + } else { + cpm = bidData.price; + + if (cpm === null || isNaN(cpm)) { + utils.logError('Invalid cpm in bid response', CONSUMABLE_BIDDER_CODE, bid); + return; + } + } + cpm = cpm * (parseFloat(bidRequest.zoneId) / parseFloat(bidRequest.network)); + + let oad = bidData.adm; + let cb = bidRequest.network === '9599.1' ? 7654321 : Math.round(new Date().getTime()); + let ad = '' + oad; + ad += ''; + ad += ''; + ad += '' + if (response.ext && response.ext.pixels) { + if (config.getConfig('consumable.userSyncOn') !== EVENTS.BID_RESPONSE) { + ad += _formatPixels(response.ext.pixels); + } + } + + return { + bidderCode: bidRequest.bidderCode, + requestId: bidRequest.bidId, + ad: ad, + cpm: cpm, + width: bidData.w, + height: bidData.h, + creativeId: bidData.crid, + pubapiId: response.id, + currency: response.cur, + dealId: bidData.dealid, + netRevenue: true, + ttl: CONSUMABLE_TTL + }; +} + +function _formatPixels (pixels) { + let formattedPixels = pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, ''); + + return ''; +} + +export const spec = { + code: CONSUMABLE_BIDDER_CODE, + isBidRequestValid: function(bid) { + return bid.params && bid.params.placement + }, + buildRequests: function (bids) { + return bids.map(formatBidRequest); + }, + interpretResponse: function ({body}, bidRequest) { + if (!body) { + utils.logError('Empty bid response', bidRequest.bidderCode, body); + } else { + let bid = _parseBidResponse(body, bidRequest); + if (bid) { + return bid; + } + } + }, + getUserSyncs: function(options, bidResponses) { + let bidResponse = bidResponses[0]; + + if (config.getConfig('consumable.userSyncOn') === EVENTS.BID_RESPONSE) { + if (!$$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped && bidResponse.ext && bidResponse.ext.pixels) { + $$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped = true; + + return parsePixelItems(bidResponse.ext.pixels); + } + } + + return []; + } +}; + +registerBidder(spec); diff --git a/modules/consumableBidAdapter.md b/modules/consumableBidAdapter.md new file mode 100644 index 00000000000..f6dfe8131c6 --- /dev/null +++ b/modules/consumableBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +Module Name: Consumable Bid Adapter + +Module Type: Consumable Adapter + +Maintainer: naffis@consumable.com + +# Description + +Module that connects to Consumable's demand sources + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'test-ad-div', + sizes: [[300, 250]], + bids: [ + { + bidder: 'consumable', + params: { + placement: '1234567', + unitId: '1234', + unitName: 'cnsmbl-300x250', + zoneId: '13136.52' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js new file mode 100644 index 00000000000..b87ce6634f6 --- /dev/null +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -0,0 +1,215 @@ +import {expect} from 'chai'; +import * as utils from 'src/utils'; +import {spec} from 'modules/consumableBidAdapter'; +import {config} from 'src/config'; + +const DEFAULT_OAD_CONTENT = ''; +const DEFAULT_AD_CONTENT = '' + +let getDefaultBidResponse = () => { + return { + id: '245730051428950632', + cur: 'USD', + seatbid: [{ + bid: [{ + id: 1, + impid: '245730051428950632', + price: 0.09, + adm: DEFAULT_OAD_CONTENT, + crid: 'creative-id', + h: 90, + w: 728, + dealid: 'deal-id', + ext: {sizeid: 225} + }] + }] + }; +}; + +let getBidParams = () => { + return { + placement: 1234567, + network: '9599.1', + unitId: '987654', + unitName: 'unitname', + zoneId: '9599.1' + }; +}; + +let getDefaultBidRequest = () => { + return { + bidderCode: 'consumable', + auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + bidderRequestId: '7101db09af0db2', + start: new Date().getTime(), + bids: [{ + bidder: 'consumable', + bidId: '84ab500420319d', + bidderRequestId: '7101db09af0db2', + auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + placementCode: 'foo', + params: getBidParams() + }] + }; +}; + +let getPixels = () => { + return ''; +}; + +describe('ConsumableAdapter', () => { + const CONSUMABLE_URL = '//adserver-us.adtech.advertising.com/pubapi/3.0/'; + const CONSUMABLE_TTL = 60; + + function createCustomBidRequest({bids, params} = {}) { + var bidderRequest = getDefaultBidRequest(); + if (bids && Array.isArray(bids)) { + bidderRequest.bids = bids; + } + if (params) { + bidderRequest.bids.forEach(bid => bid.params = params); + } + return bidderRequest; + } + + describe('interpretResponse()', () => { + let bidderSettingsBackup; + let bidResponse; + let bidRequest; + let logWarnSpy; + + beforeEach(() => { + bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; + bidRequest = { + bidderCode: 'test-bidder-code', + bidId: 'bid-id', + unitName: 'unitname', + unitId: '987654', + zoneId: '9599.1', + network: '9599.1' + }; + bidResponse = { + body: getDefaultBidResponse() + }; + logWarnSpy = sinon.spy(utils, 'logWarn'); + }); + + afterEach(() => { + $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; + logWarnSpy.restore(); + }); + + it('should return formatted bid response with required properties', () => { + let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); + expect(formattedBidResponse).to.deep.equal({ + bidderCode: bidRequest.bidderCode, + requestId: 'bid-id', + ad: DEFAULT_AD_CONTENT, + cpm: 0.09, + width: 728, + height: 90, + creativeId: 'creative-id', + pubapiId: '245730051428950632', + currency: 'USD', + dealId: 'deal-id', + netRevenue: true, + ttl: 60 + }); + }); + + it('should add formatted pixels to ad content when pixels are present in the response', () => { + bidResponse.body.ext = { + pixels: 'pixels-content' + }; + + let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); + + expect(formattedBidResponse.ad).to.equal(DEFAULT_AD_CONTENT + ''); + return true; + }); + }); + + describe('buildRequests()', () => { + it('method exists and is a function', () => { + expect(spec.buildRequests).to.exist.and.to.be.a('function'); + }); + + describe('Consumable', () => { + it('should not return request when no bids are present', () => { + let [request] = spec.buildRequests([]); + expect(request).to.be.empty; + }); + + it('should return request for endpoint', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(CONSUMABLE_URL); + }); + + it('should return url with pubapi bid option', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('cmd=bid;'); + }); + + it('should return url with version 2 of pubapi', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('v=2;'); + }); + + it('should return url with cache busting option', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.match(/misc=\d+/); + }); + }); + }); + + describe('getUserSyncs()', () => { + let bidResponse; + let bidRequest; + + beforeEach(() => { + $$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped = false; + config.setConfig({ + consumable: { + userSyncOn: 'bidResponse' + }, + }); + bidResponse = getDefaultBidResponse(); + bidResponse.ext = { + pixels: getPixels() + }; + }); + + it('should return user syncs only if userSyncOn equals to "bidResponse"', () => { + let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + + expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.true; + expect(userSyncs).to.deep.equal([ + {type: 'image', url: 'img.org'}, + {type: 'iframe', url: 'pixels1.org'} + ]); + }); + + it('should not return user syncs if it has already been returned', () => { + $$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped = true; + + let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + + expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.true; + expect(userSyncs).to.deep.equal([]); + }); + + it('should not return user syncs if pixels are not present', () => { + bidResponse.ext.pixels = null; + + let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + + expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.false; + expect(userSyncs).to.deep.equal([]); + }); + }); +}); From 96878ef0a16da1e96efa6d5a759820f9546c9e80 Mon Sep 17 00:00:00 2001 From: Richard Lee <14349+dlackty@users.noreply.github.com> Date: Fri, 27 Apr 2018 00:17:19 +0800 Subject: [PATCH 0293/1594] Audience Network: Fix bid request validation for fullwidth (#2417) --- modules/audienceNetworkBidAdapter.js | 2 +- test/spec/modules/audienceNetworkBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 263edba878a..612357e0e4a 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -27,7 +27,7 @@ const isBidRequestValid = bid => typeof bid.params.placementId === 'string' && bid.params.placementId.length > 0 && Array.isArray(bid.sizes) && bid.sizes.length > 0 && - (isFullWidth(bid.params.format) ? bid.sizes.map(flattenSize).every(size => size === '300x250') : true) && + (isFullWidth(bid.params.format) ? bid.sizes.map(flattenSize).some(size => size === '300x250') : true) && (isValidNonSizedFormat(bid.params.format) || bid.sizes.map(flattenSize).some(isValidSize)); /** diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index 41a6d955c6a..f9d46e100b1 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -75,7 +75,7 @@ describe('AudienceNetwork adapter', () => { it('fullwidth', () => { expect(isBidRequestValid({ bidder, - sizes: [[300, 250]], + sizes: [[300, 250], [336, 280]], params: { placementId, format: 'fullwidth' From baea84010f11941428fd175b8cb9927247739760 Mon Sep 17 00:00:00 2001 From: harpere Date: Thu, 26 Apr 2018 13:20:32 -0400 Subject: [PATCH 0294/1594] updated rubicon adapter sync endpoint (#2454) --- modules/rubiconBidAdapter.js | 2 +- test/spec/modules/rubiconBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index d3735f01d62..88e45bb42cc 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -12,7 +12,7 @@ function isSecure() { // use protocol relative urls for http or https const FASTLANE_ENDPOINT = '//fastlane.rubiconproject.com/a/api/fastlane.json'; const VIDEO_ENDPOINT = '//fastlane-adv.rubiconproject.com/v1/auction/video'; -const SYNC_ENDPOINT = 'https://tap-secure.rubiconproject.com/partner/scripts/rubicon/emily.html?rtb_ext=1'; +const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html'; const TIMEOUT_BUFFER = 500; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index cc996041aac..032ed7714fe 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1201,7 +1201,7 @@ describe('the rubicon adapter', () => { }); describe('user sync', () => { - const emilyUrl = 'https://tap-secure.rubiconproject.com/partner/scripts/rubicon/emily.html?rtb_ext=1'; + const emilyUrl = 'https://eus.rubiconproject.com/usync.html'; beforeEach(() => { resetUserSync(); From 5c14e9c92c05bd8df0862c8a1704690cffd57c72 Mon Sep 17 00:00:00 2001 From: Bill Newman Date: Thu, 26 Apr 2018 21:56:51 +0300 Subject: [PATCH 0295/1594] Added new types of traffic Colossus SSP adapter (#2281) * add video&native traffic colossus ssp * Native obj validation * Native obj validation #2 * Added size field in requests * fixed test --- modules/colossussspBidAdapter.js | 71 +++++++------------ modules/colossussspBidAdapter.md | 3 +- .../modules/colossussspBidAdapter_spec.js | 13 ++-- 3 files changed, 33 insertions(+), 54 deletions(-) diff --git a/modules/colossussspBidAdapter.js b/modules/colossussspBidAdapter.js index df011bc102d..22b0415936c 100644 --- a/modules/colossussspBidAdapter.js +++ b/modules/colossussspBidAdapter.js @@ -1,44 +1,31 @@ import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; import * as utils from 'src/utils'; const BIDDER_CODE = 'colossusssp'; const URL = '//colossusssp.com/?c=o&m=multi'; const URL_SYNC = '//colossusssp.com/?c=o&m=cookie'; -let sizeObj = { - '468x60': 1, - '728x90': 2, - '300x600': 10, - '300x250': 15, - '300x100': 19, - '320x50': 43, - '300x50': 44, - '300x300': 48, - '300x1050': 54, - '970x90': 55, - '970x250': 57, - '1000x90': 58, - '320x80': 59, - '640x480': 65, - '320x480': 67, - '320x320': 72, - '320x160': 73, - '480x300': 83, - '970x310': 94, - '970x210': 96, - '480x320': 101, - '768x1024': 102, - '1000x300': 113, - '320x100': 117, - '800x250': 118, - '200x600': 119 -}; +function isBidResponseValid(bid) { + if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency) { + return false; + } -utils._each(sizeObj, (item, key) => sizeObj[item] = key); + 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); + default: + return false; + } +} export const spec = { code: BIDDER_CODE, - + supportedMediaTypes: [BANNER, VIDEO, NATIVE], /** * Determines whether or not the given bid request is valid. * @@ -46,9 +33,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: (bid) => { - return (!isNaN(bid.params.placement_id) && - ((bid.params.sizes !== undefined && bid.params.sizes.length > 0 && bid.params.sizes.some((sizeIndex) => sizeObj[sizeIndex] !== undefined)) || - (bid.sizes !== undefined && bid.sizes.length > 0 && bid.sizes.map((size) => `${size[0]}x${size[1]}`).some((size) => sizeObj[size] !== undefined)))); + return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placement_id)); }, /** @@ -78,10 +63,12 @@ export const spec = { }; for (let i = 0; i < validBidRequests.length; i++) { let bid = validBidRequests[i]; - let placement = {}; - placement['placementId'] = bid.params.placement_id; - placement['bidId'] = bid.bidId; - placement['sizes'] = bid.sizes; + let placement = { + placementId: bid.params.placement_id, + bidId: bid.bidId, + sizes: bid.sizes, + traffic: bid.params.traffic || BANNER + }; placements.push(placement); } return { @@ -103,15 +90,7 @@ export const spec = { serverResponse = serverResponse.body; for (let i = 0; i < serverResponse.length; i++) { let resItem = serverResponse[i]; - if (resItem.width && !isNaN(resItem.width) && - resItem.height && !isNaN(resItem.height) && - resItem.requestId && typeof resItem.requestId === 'string' && - resItem.cpm && !isNaN(resItem.cpm) && - resItem.ad && typeof resItem.ad === 'string' && - resItem.ttl && !isNaN(resItem.ttl) && - resItem.creativeId && typeof resItem.creativeId === 'string' && - resItem.netRevenue && typeof resItem.netRevenue === 'boolean' && - resItem.currency && typeof resItem.currency === 'string') { + if (isBidResponseValid(resItem)) { response.push(resItem); } } diff --git a/modules/colossussspBidAdapter.md b/modules/colossussspBidAdapter.md index 9a5b9a0fe39..4760002f0db 100644 --- a/modules/colossussspBidAdapter.md +++ b/modules/colossussspBidAdapter.md @@ -18,7 +18,8 @@ Module that connects to Colossus SSP demand sources bids: [{ bidder: 'colossusssp', params: { - placement_id: 0 + placement_id: 0, + traffic: 'banner' } }] } diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js index e14d2f27b42..54952fbf4b5 100644 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ b/test/spec/modules/colossussspBidAdapter_spec.js @@ -16,17 +16,13 @@ describe('ColossussspAdapter', () => { }; describe('isBidRequestValid', () => { - it('Should return true when placement_id can be cast to a number, and when at least one of the sizes passed is allowed', () => { + it('Should return true when placement_id can be cast to a number', () => { expect(spec.isBidRequestValid(bid)).to.be.true; }); it('Should return false when placement_id is not a number', () => { bid.params.placement_id = 'aaa'; expect(spec.isBidRequestValid(bid)).to.be.false; }); - it('Should return false when the sizes are not allowed', () => { - bid.sizes = [[1, 1]]; - expect(spec.isBidRequestValid(bid)).to.be.false; - }); }); describe('buildRequests', () => { @@ -56,9 +52,10 @@ describe('ColossussspAdapter', () => { let placements = data['placements']; for (let i = 0; i < placements.length; i++) { let placement = placements[i]; - expect(placement).to.have.all.keys('placementId', 'bidId', 'sizes'); + expect(placement).to.have.all.keys('placementId', 'bidId', 'traffic', 'sizes'); 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'); } }); @@ -72,6 +69,7 @@ describe('ColossussspAdapter', () => { let resObject = { body: [ { requestId: '123', + mediaType: 'banner', cpm: 0.3, width: 320, height: 50, @@ -88,7 +86,7 @@ describe('ColossussspAdapter', () => { 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'); + 'netRevenue', 'currency', 'mediaType'); expect(dataItem.requestId).to.be.a('string'); expect(dataItem.cpm).to.be.a('number'); expect(dataItem.width).to.be.a('number'); @@ -98,6 +96,7 @@ describe('ColossussspAdapter', () => { 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'); } it('Returns an empty array if invalid response is passed', () => { serverResponses = spec.interpretResponse('invalid_response'); From fae4048156520e766c7ccf826be2ca0fd4ced5ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kurre=20St=C3=A5hlberg?= Date: Fri, 27 Apr 2018 03:01:53 +0300 Subject: [PATCH 0296/1594] Update ReadPeak adapter (#2369) * Update ReadPeak adapter * Replace $$PREBID_GLOBAL$$.version with $prebid.version$ * Fix test * Use utils.getTopWindowReferrer() instead of custom function --- modules/readpeakBidAdapter.js | 50 ++++++++++++-------- modules/readpeakBidAdapter.md | 5 +- test/spec/modules/readpeakBidAdapter_spec.js | 17 ++++--- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/modules/readpeakBidAdapter.js b/modules/readpeakBidAdapter.js index d19570d16ca..6c0773d1f7c 100644 --- a/modules/readpeakBidAdapter.js +++ b/modules/readpeakBidAdapter.js @@ -1,5 +1,7 @@ -import {logError, getTopWindowLocation} from 'src/utils'; +import { logError, getTopWindowLocation, replaceAuctionPrice, getTopWindowReferrer } from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; +import { NATIVE } from 'src/mediaTypes'; export const ENDPOINT = '//app.readpeak.com/header/prebid'; @@ -18,7 +20,7 @@ export const spec = { code: BIDDER_CODE, - supportedMediaTypes: ['native'], + supportedMediaTypes: [NATIVE], isBidRequestValid: bid => ( !!(bid && bid.params && bid.params.publisherId && bid.nativeParams) @@ -31,7 +33,14 @@ export const spec = { site: site(bidRequests), app: app(bidRequests), device: device(), - isPrebid: true, + cur: config.getConfig('currency') || ['USD'], + source: { + fd: 1, + tid: bidRequests[0].transactionId, + ext: { + prebid: '$prebid.version$', + }, + }, } return { @@ -70,7 +79,7 @@ function bidResponseAvailable(bidRequest, bidResponse) { creativeId: idToBidMap[id].crid, ttl: 300, netRevenue: true, - mediaType: 'native', + mediaType: NATIVE, currency: bidResponse.cur, native: nativeResponse(idToImpMap[id], idToBidMap[id]), }; @@ -93,7 +102,7 @@ function nativeImpression(slot) { if (slot.nativeParams) { const assets = []; addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); - addAsset(assets, imageAsset(2, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); + addAsset(assets, imageAsset(2, slot.nativeParams.image, 3, slot.nativeParams.wmin || NATIVE_DEFAULTS.IMG_MIN, slot.nativeParams.hmin || NATIVE_DEFAULTS.IMG_MIN)); addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); addAsset(assets, dataAsset(4, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); addAsset(assets, dataAsset(5, slot.nativeParams.cta, 12, NATIVE_DEFAULTS.CTA_LEN)); @@ -149,19 +158,21 @@ function dataAsset(id, params, type, defaultLen) { function site(bidderRequest) { const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.publisherId : '0'; + const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; const appParams = bidderRequest[0].params.app; if (!appParams) { return { publisher: { id: pubId.toString(), + domain: config.getConfig('publisherDomain'), }, - id: pubId.toString(), - ref: referrer(), - page: getTopWindowLocation().href, + id: siteId ? siteId.toString() : pubId.toString(), + ref: getTopWindowReferrer(), + page: config.getConfig('pageUrl') || getTopWindowLocation().href, domain: getTopWindowLocation().hostname } } - return null; + return undefined; } function app(bidderRequest) { @@ -177,21 +188,14 @@ function app(bidderRequest) { domain: appParams.domain, } } - return null; -} - -function referrer() { - try { - return window.top.document.referrer; - } catch (e) { - return document.referrer; - } + return undefined; } function device() { return { ua: navigator.userAgent, language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), + devicetype: 1 }; } @@ -219,13 +223,19 @@ function nativeResponse(imp, bid) { keys.title = asset.title ? asset.title.text : keys.title; keys.body = asset.data && asset.id === 4 ? asset.data.value : keys.body; keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy; - keys.image = asset.img && asset.id === 2 ? asset.img.url : keys.image; + keys.image = asset.img && asset.id === 2 ? { + url: asset.img.url, + width: asset.img.w || 750, + height: asset.img.h || 500, + } : keys.image; keys.cta = asset.data && asset.id === 5 ? asset.data.value : keys.cta; }); if (nativeAd.link) { keys.clickUrl = encodeURIComponent(nativeAd.link.url); } - keys.impressionTrackers = nativeAd.imptrackers; + const trackers = nativeAd.imptrackers || []; + trackers.unshift(replaceAuctionPrice(bid.burl, bid.price)); + keys.impressionTrackers = trackers; return keys; } } diff --git a/modules/readpeakBidAdapter.md b/modules/readpeakBidAdapter.md index f8e01027793..a15767f29a7 100644 --- a/modules/readpeakBidAdapter.md +++ b/modules/readpeakBidAdapter.md @@ -16,13 +16,14 @@ Please reach out to your account team or hello@readpeak.com for more information # Test Parameters ```javascript var adUnits = [{ - code: 'test-native', + code: '/19968336/prebid_native_example_2', mediaTypes: { native: { type: 'image' } }, bids: [{ bidder: 'readpeak', params: { bidfloor: 5.00, - publisherId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' + publisherId: 'test', + siteId: 'test' }, }] }]; diff --git a/test/spec/modules/readpeakBidAdapter_spec.js b/test/spec/modules/readpeakBidAdapter_spec.js index 7da3450f16c..776261c8db2 100644 --- a/test/spec/modules/readpeakBidAdapter_spec.js +++ b/test/spec/modules/readpeakBidAdapter_spec.js @@ -19,7 +19,8 @@ describe('ReadPeakAdapter', () => { }, params: { bidfloor: 5.00, - publisherId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' + publisherId: '11bc5dd5-7421-4dd8-c926-40fa653bec76', + siteId: '11bc5dd5-7421-4dd8-c926-40fa653bec77' }, bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', @@ -63,8 +64,8 @@ describe('ReadPeakAdapter', () => { img: { type: 3, url: 'http://url.to/image', - w: 320, - h: 200, + w: 750, + h: 500, }, }], link: { @@ -97,7 +98,7 @@ describe('ReadPeakAdapter', () => { 'publisher': { 'id': '11bc5dd5-7421-4dd8-c926-40fa653bec76' }, - 'id': '11bc5dd5-7421-4dd8-c926-40fa653bec76', + 'id': '11bc5dd5-7421-4dd8-c926-40fa653bec77', 'ref': '', 'page': 'http://localhost', 'domain': 'localhost' @@ -151,15 +152,17 @@ describe('ReadPeakAdapter', () => { const request = spec.buildRequests([ bidRequest ]); const data = JSON.parse(request.data); - expect(data.isPrebid).to.equal(true); + + 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.site).to.deep.equal({ publisher: { id: bidRequest.params.publisherId, + domain: 'http://localhost:9876', }, - id: bidRequest.params.publisherId, + id: bidRequest.params.siteId, ref: window.top.document.referrer, page: utils.getTopWindowLocation().href, domain: utils.getTopWindowLocation().hostname, @@ -188,7 +191,7 @@ describe('ReadPeakAdapter', () => { expect(bidResponse.native.title).to.equal('Title') expect(bidResponse.native.body).to.equal('Description') - expect(bidResponse.native.image).to.equal('http://url.to/image') + 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') }); From e82c58a0a4f0f872deccf90be7159af8e6d86731 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Fri, 27 Apr 2018 06:01:42 -0700 Subject: [PATCH 0297/1594] Rubicon Adapter GDPR Update for gdprApplies flag (#2456) * Merged gdpr tests for banner bid requests * Renamed the gdprConsent.consentRequired to gdprConsent.gdprApplies. Changed containing object used to access gdprConsent values (bidRequest -> bidderRequest) * Added compatibility for CMP 1.0 and 1.1 --- modules/rubiconBidAdapter.js | 25 +++-- test/spec/modules/rubiconBidAdapter_spec.js | 109 ++++++++------------ 2 files changed, 57 insertions(+), 77 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 88e45bb42cc..ea88886b753 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -134,6 +134,9 @@ export const spec = { page_url = bidRequest.params.secure ? page_url.replace(/^http:/i, 'https:') : page_url; + // GDPR reference, for use by 'banner' and 'video' + const gdprConsent = bidderRequest.gdprConsent; + if (spec.hasVideoMediaType(bidRequest)) { let params = bidRequest.params; let size = parseSizes(bidRequest); @@ -178,9 +181,12 @@ export const spec = { data.slots.push(slotData); - if (bidderRequest && bidderRequest.gdprConsent) { - data.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; - data.gdpr_consent = bidderRequest.gdprConsent.consentString; + if (gdprConsent) { + // add 'gdpr' only if 'gdprApplies' is defined + if (typeof gdprConsent.gdprApplies === 'boolean') { + data.gdpr = Number(gdprConsent.gdprApplies); + } + data.gdpr_consent = gdprConsent.consentString; } return { @@ -228,13 +234,12 @@ export const spec = { 'tk_user_key', userId ]; - // add GDPR properties if enabled - if (config.getConfig('consentManagement') && - bidderRequest && bidderRequest.gdprConsent && typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { - data.push( - 'gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0, - 'gdpr_consent', bidderRequest.gdprConsent.consentString - ); + if (gdprConsent) { + // add 'gdpr' only if 'gdprApplies' is defined + if (typeof gdprConsent.gdprApplies === 'boolean') { + data.push('gdpr', Number(gdprConsent.gdprApplies)); + } + data.push('gdpr_consent', gdprConsent.consentString); } if (visitor !== null && typeof visitor === 'object') { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 032ed7714fe..e3ffef9997e 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -15,15 +15,24 @@ describe('the rubicon adapter', () => { let sandbox, bidderRequest; - function addConsentManagement() { - bidderRequest.gdprConsent = { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'gdprApplies': true + /** + * @param {boolean} [gdprApplies] + */ + function createGdprBidderRequest(gdprApplies) { + if (typeof gdprApplies === 'boolean') { + bidderRequest.gdprConsent = { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'gdprApplies': gdprApplies + }; + } else { + bidderRequest.gdprConsent = { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' + }; } } function createVideoBidderRequest() { - addConsentManagement(); + createGdprBidderRequest(true); let bid = bidderRequest.bids[0]; bid.mediaTypes = { @@ -46,7 +55,7 @@ describe('the rubicon adapter', () => { } function createLegacyVideoBidderRequest() { - addConsentManagement(); + createGdprBidderRequest(true); let bid = bidderRequest.bids[0]; // Legacy property (Prebid <1.0) @@ -535,77 +544,43 @@ describe('the rubicon adapter', () => { }); }); - it('should send GDPR params when enabled', () => { - addConsentManagement(); + describe('GDPR consent config', () => { + it('should send "gdpr" and "gdpr_consent", when gdprConsent defines consentString and gdprApplies', () => { + createGdprBidderRequest(true); + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - consentManagement: { - cmp: 'iab', - waitForConsentTimeout: 4000, - lookUpFailureResolution: 'cancel' - } - }; - return config[key]; + expect(data['gdpr']).to.equal('1'); + expect(data['gdpr_consent']).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); - let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - let data = parseQuery(request.data); - let expectedQuery = { - 'gdpr': '1', - 'gdpr_consent': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' - }; - - // test that all values above are both present and correct - Object.keys(expectedQuery).forEach(key => { - let value = expectedQuery[key]; - expect(data[key]).to.equal(value); - }); - }); + it('should send only "gdpr_consent", when gdprConsent defines only consentString', () => { + createGdprBidderRequest(); + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); - it('should not send GDPR params if not enabled', () => { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = {}; - return config[key]; + expect(data['gdpr_consent']).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + expect(data['gdpr']).to.equal(undefined); }); - let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - let data = parseQuery(request.data); - let expectedQuery = { - 'gdpr': undefined, - 'gdpr_consent': undefined - }; - - // test that all values above are both present and correct - Object.keys(expectedQuery).forEach(key => { - let value = expectedQuery[key]; - expect(data[key]).to.equal(value); - }); - }); + it('should not send GDPR params if gdprConsent is not defined', () => { + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); - it('should not send GDPR params if gdprConsent is not set in config', () => { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - consentManagement: { - cmp: 'iab', - waitForConsentTimeout: 4000, - lookUpFailureResolution: 'cancel' - } - }; - return config[key]; + expect(data['gdpr']).to.equal(undefined); + expect(data['gdpr_consent']).to.equal(undefined); }); - let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - let data = parseQuery(request.data); - let expectedQuery = { - 'gdpr': undefined, - 'gdpr_consent': undefined - }; + it('should set "gdpr" value as 1 or 0, using "gdprApplies" value of either true/false', () => { + createGdprBidderRequest(true); + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); + expect(data['gdpr']).to.equal('1'); - // test that all values above are both present and correct - Object.keys(expectedQuery).forEach(key => { - let value = expectedQuery[key]; - expect(data[key]).to.equal(value); + createGdprBidderRequest(false); + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + data = parseQuery(request.data); + expect(data['gdpr']).to.equal('0'); }); }); }); From ebf5e61ec885b0ea92b0b1f29e8d9e4345b08279 Mon Sep 17 00:00:00 2001 From: Pupis Date: Fri, 27 Apr 2018 16:34:54 +0300 Subject: [PATCH 0298/1594] Update adform adapter's dynamic price type (#2460) * updated priceType logic * Fix --- modules/adformBidAdapter.js | 12 +++--- test/spec/modules/adformBidAdapter_spec.js | 49 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index 1da6042f63a..10a4696d755 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -11,15 +11,14 @@ export const spec = { return !!(bid.params.mid); }, buildRequests: function (validBidRequests) { - var i, l, j, k, bid, _key, _value, reqParams; + var i, l, j, k, bid, _key, _value, reqParams, netRevenue; var request = []; - var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ], [ 'pt', null ] ]; - var netRevenue = 'gross'; + var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ] ]; var bids = JSON.parse(JSON.stringify(validBidRequests)); for (i = 0, l = bids.length; i < l; i++) { bid = bids[i]; - if (bid.params.priceType === 'net') { - bid.params.pt = netRevenue = 'net'; + if ((bid.params.priceType === 'net') || (bid.params.pt === 'net')) { + netRevenue = 'net'; } for (j = 0, k = globalParams.length; j < k; j++) { _key = globalParams[j][0]; @@ -35,7 +34,8 @@ export const spec = { } request.unshift('//' + globalParams[0][1] + '/adx/?rp=4'); - + netRevenue = netRevenue || 'gross'; + request.push('pt=' + netRevenue); request.push('stid=' + validBidRequests[0].auctionId); for (i = 1, l = globalParams.length; i < l; i++) { diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index f3aa735be00..d631234d6d5 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -30,7 +30,7 @@ describe('Adform adapter', () => { it('should pass multiple bids via single request', () => { let request = spec.buildRequests(bids); let parsedUrl = parseUrl(request.url); - assert.lengthOf(parsedUrl.items, 5); + assert.lengthOf(parsedUrl.items, 7); }); it('should handle global request parameters', () => { @@ -62,6 +62,7 @@ describe('Adform adapter', () => { { mid: '2', someVar: 'someValue', + pt: 'gross', transactionId: '5f33781f-9552-4iuy' }, { @@ -78,6 +79,16 @@ describe('Adform adapter', () => { mid: '3', pdom: 'home', transactionId: '5f33781f-9552-7ev3' + }, + { + mid: '5', + pt: 'net', + transactionId: '5f33781f-9552-7ev3', + }, + { + mid: '6', + pt: 'gross', + transactionId: '5f33781f-9552-7ev3' } ]); }); @@ -87,6 +98,18 @@ describe('Adform adapter', () => { let request = spec.buildRequests([bids[0]]); assert.deepEqual(resultBids, bids[0]); }); + + it('should set gross to the request, if there is any gross priceType', () => { + let request = spec.buildRequests([bids[5], bids[5]]); + let parsedUrl = parseUrl(request.url); + + assert.equal(parsedUrl.query.pt, 'net'); + + request = spec.buildRequests([bids[4], bids[3]]); + parsedUrl = parseUrl(request.url); + + assert.equal(parsedUrl.query.pt, 'gross'); + }); }); describe('interpretResponse', () => { @@ -178,7 +201,7 @@ describe('Adform adapter', () => { beforeEach(() => { let sizes = [[250, 300], [300, 250], [300, 600]]; let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; - let params = [{ mid: 1, url: 'some// there' }, {adxDomain: null, mid: 2, someVar: 'someValue', pt: 'gross'}, { adxDomain: null, mid: 3, pdom: 'home' }]; + let params = [{ mid: 1, url: 'some// there' }, {adxDomain: null, mid: 2, someVar: 'someValue', pt: 'gross'}, { adxDomain: null, mid: 3, pdom: 'home' }, {mid: 5, pt: 'net'}, {mid: 6, pt: 'gross'}]; bids = [ { adUnitCode: placementCode[0], @@ -236,6 +259,28 @@ describe('Adform adapter', () => { placementCode: placementCode[2], sizes: [], transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'adform', + bidderRequestId: '1ab8d9', + params: params[3], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'adform', + bidderRequestId: '1ab8d9', + params: params[4], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' } ]; serverResponse = { From e558950744e349025a380622ee16dfbd9a9cee7b Mon Sep 17 00:00:00 2001 From: John Salis Date: Fri, 27 Apr 2018 11:42:21 -0400 Subject: [PATCH 0299/1594] Parse bid sizes on the `mediaTypes` object (#2435) --- modules/beachfrontBidAdapter.js | 5 +- modules/beachfrontBidAdapter.md | 12 +- .../spec/modules/beachfrontBidAdapter_spec.js | 121 +++++++++++++----- 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index fc191e306d4..6f92bc0d976 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -121,7 +121,10 @@ function outstreamRender(bid) { } function getSizes(bid) { - return utils.parseSizesInput(bid.sizes).map(size => { + let sizes = (isVideoBid(bid) + ? utils.deepAccess(bid, 'mediaTypes.video.playerSize') + : utils.deepAccess(bid, 'mediaTypes.banner.sizes')) || bid.sizes; + return utils.parseSizesInput(sizes).map(size => { let [ width, height ] = size.split('x'); return { w: parseInt(width, 10) || undefined, diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index 6e50737dd98..5804cb8dc0d 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -15,10 +15,10 @@ Module that connects to Beachfront's demand sources var adUnits = [ { code: 'test-video', - sizes: [[640, 360]], mediaTypes: { video: { - context: 'instream' + context: 'instream', + playerSize: [ 640, 360 ] } }, bids: [ @@ -28,14 +28,18 @@ Module that connects to Beachfront's demand sources bidfloor: 0.01, appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76', video: { - mimes: ['video/mp4', 'application/javascript'] + mimes: [ 'video/mp4', 'application/javascript' ] } } } ] }, { code: 'test-banner', - sizes: [300, 250], + mediaTypes: { + banner: { + sizes: [ 300, 250 ] + } + }, bids: [ { bidder: 'beachfront', diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index ddd93f8406d..5a0345ee6e2 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -14,7 +14,6 @@ describe('BeachfrontAdapter', () => { appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' }, adUnitCode: 'div-gpt-ad-1460505748561-0', - sizes: [ 300, 250 ], bidId: '25186806a41eab', bidderRequestId: '15bdd8d4a0ebaf', auctionId: 'f17d62d0-e3e3-48d0-9f73-cb4ea358a309' @@ -25,7 +24,6 @@ describe('BeachfrontAdapter', () => { appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' }, adUnitCode: 'div-gpt-ad-1460505748561-1', - sizes: [ 300, 600 ], bidId: '365088ee6d649d', bidderRequestId: '15bdd8d4a0ebaf', auctionId: 'f17d62d0-e3e3-48d0-9f73-cb4ea358a309' @@ -86,11 +84,16 @@ describe('BeachfrontAdapter', () => { }); it('should attach request data', () => { + const width = 640; + const height = 480; const bidRequest = bidRequests[0]; - bidRequest.mediaTypes = { video: {} }; + bidRequest.mediaTypes = { + video: { + playerSize: [ width, height ] + } + }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - const [ width, height ] = bidRequest.sizes; const topLocation = utils.getTopWindowLocation(); expect(data.isPrebid).to.equal(true); expect(data.appId).to.equal(bidRequest.params.appId); @@ -107,8 +110,11 @@ describe('BeachfrontAdapter', () => { const width = 640; const height = 480; const bidRequest = bidRequests[0]; - bidRequest.sizes = [[ width, height ]]; - bidRequest.mediaTypes = { video: {} }; + bidRequest.mediaTypes = { + video: { + playerSize: [[ width, height ]] + } + }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); @@ -118,8 +124,11 @@ describe('BeachfrontAdapter', () => { const width = 640; const height = 480; const bidRequest = bidRequests[0]; - bidRequest.sizes = `${width}x${height}`; - bidRequest.mediaTypes = { video: {} }; + bidRequest.mediaTypes = { + video: { + playerSize: `${width}x${height}` + } + }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); @@ -127,13 +136,27 @@ describe('BeachfrontAdapter', () => { it('must handle an empty bid size', () => { const bidRequest = bidRequests[0]; - bidRequest.sizes = []; - bidRequest.mediaTypes = { video: {} }; + bidRequest.mediaTypes = { + video: { + playerSize: [] + } + }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; expect(data.imp[0].video).to.deep.contain({ w: undefined, h: undefined }); }); + it('must fall back to the size on the bid object', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.sizes = [ width, height ]; + bidRequest.mediaTypes = { video: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); + }); + it('must override video targeting params', () => { const bidRequest = bidRequests[0]; const mimes = ['video/webm']; @@ -163,11 +186,16 @@ describe('BeachfrontAdapter', () => { }); it('should attach request data', () => { + const width = 300; + const height = 250; const bidRequest = bidRequests[0]; - bidRequest.mediaTypes = { banner: {} }; + bidRequest.mediaTypes = { + banner: { + sizes: [ width, height ] + } + }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - const [ width, height ] = bidRequest.sizes; const topLocation = utils.getTopWindowLocation(); expect(data.slots).to.deep.equal([ { @@ -184,11 +212,14 @@ describe('BeachfrontAdapter', () => { }); it('must parse bid size from a nested array', () => { - const width = 640; - const height = 480; + const width = 300; + const height = 250; const bidRequest = bidRequests[0]; - bidRequest.sizes = [[ width, height ]]; - bidRequest.mediaTypes = { banner: {} }; + bidRequest.mediaTypes = { + banner: { + sizes: [[ width, height ]] + } + }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; expect(data.slots[0].sizes).to.deep.equal([ @@ -197,11 +228,14 @@ describe('BeachfrontAdapter', () => { }); it('must parse bid size from a string', () => { - const width = 640; - const height = 480; + const width = 300; + const height = 250; const bidRequest = bidRequests[0]; - bidRequest.sizes = `${width}x${height}`; - bidRequest.mediaTypes = { banner: {} }; + bidRequest.mediaTypes = { + banner: { + sizes: `${width}x${height}` + } + }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; expect(data.slots[0].sizes).to.deep.equal([ @@ -211,12 +245,26 @@ describe('BeachfrontAdapter', () => { it('must handle an empty bid size', () => { const bidRequest = bidRequests[0]; - bidRequest.sizes = []; - bidRequest.mediaTypes = { banner: {} }; + bidRequest.mediaTypes = { + banner: { + sizes: [] + } + }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; expect(data.slots[0].sizes).to.deep.equal([]); }); + + it('must fall back to the size on the bid object', () => { + const width = 300; + const height = 250; + const bidRequest = bidRequests[0]; + bidRequest.sizes = [ width, height ]; + bidRequest.mediaTypes = { banner: {} }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.slots[0].sizes).to.deep.contain({ w: width, h: height }); + }); }); }); @@ -250,15 +298,20 @@ describe('BeachfrontAdapter', () => { }); it('should return a valid video bid response', () => { + const width = 640; + const height = 480; const bidRequest = bidRequests[0]; - bidRequest.mediaTypes = { video: {} }; + bidRequest.mediaTypes = { + video: { + playerSize: [ width, height ] + } + }; const serverResponse = { bidPrice: 5.00, url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', cmpId: '123abc' }; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); - const [ width, height ] = bidRequest.sizes; expect(bidResponse).to.deep.equal({ requestId: bidRequest.bidId, bidderCode: spec.code, @@ -277,7 +330,11 @@ describe('BeachfrontAdapter', () => { it('should return a renderer for outstream video bids', () => { const bidRequest = bidRequests[0]; - bidRequest.mediaTypes = { video: { context: 'outstream' } }; + bidRequest.mediaTypes = { + video: { + context: 'outstream' + } + }; const serverResponse = { bidPrice: 5.00, url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', @@ -307,10 +364,16 @@ describe('BeachfrontAdapter', () => { }); it('should return valid banner bid responses', () => { - bidRequests[0].mediaTypes = { banner: {} }; - bidRequests[0].sizes = [[ 300, 250 ], [ 728, 90 ]]; - bidRequests[1].mediaTypes = { banner: {} }; - bidRequests[1].sizes = [[ 300, 600 ], [ 200, 200 ]]; + bidRequests[0].mediaTypes = { + banner: { + sizes: [[ 300, 250 ], [ 728, 90 ]] + } + }; + bidRequests[1].mediaTypes = { + banner: { + sizes: [[ 300, 600 ], [ 200, 200 ]] + } + }; const serverResponse = [{ slot: bidRequests[0].adUnitCode, adm: '
', From 1ed012a0954c42fd8a899600f74dabbf641e639c Mon Sep 17 00:00:00 2001 From: MIGOdanis Date: Fri, 27 Apr 2018 14:06:15 -0700 Subject: [PATCH 0300/1594] add getUserSyncs function in clickforceBidAdapter (#2383) * add getUserSyncs function * bug fix * add test spec * fix of docment format * fix of end line * add getUserSyncs function into test file and updated test parameters --- modules/clickforceBidAdapter.js | 13 ++ modules/clickforceBidAdapter.md | 10 ++ .../spec/modules/clickforceBidAdapter_spec.js | 127 ++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 test/spec/modules/clickforceBidAdapter_spec.js diff --git a/modules/clickforceBidAdapter.js b/modules/clickforceBidAdapter.js index 9267540cb61..fbcd5f2685c 100644 --- a/modules/clickforceBidAdapter.js +++ b/modules/clickforceBidAdapter.js @@ -61,6 +61,19 @@ export const spec = { }); }); return cfResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: 'https://cdn.doublemax.net/js/capmapping.htm' + }] + } else if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: 'https://c.doublemax.net/cm' + }] + } } }; registerBidder(spec); diff --git a/modules/clickforceBidAdapter.md b/modules/clickforceBidAdapter.md index 912f9132331..5d8a5ac8119 100644 --- a/modules/clickforceBidAdapter.md +++ b/modules/clickforceBidAdapter.md @@ -29,3 +29,13 @@ joey@clickforce.com.tw (MR. Joey) }] }]; ``` +### Configuration + +CLICKFORCE recommend the UserSync configuration below. It's can be optimize the CPM for the request. +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + syncDelay: 1000 +}}); +``` \ No newline at end of file diff --git a/test/spec/modules/clickforceBidAdapter_spec.js b/test/spec/modules/clickforceBidAdapter_spec.js new file mode 100644 index 00000000000..8b0955590a0 --- /dev/null +++ b/test/spec/modules/clickforceBidAdapter_spec.js @@ -0,0 +1,127 @@ +import { expect } from 'chai'; +import { spec } from 'modules/clickforceBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('ClickforceAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'clickforce', + 'params': { + 'zone': '6682' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }; + + 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 = { + 'someIncorrectParam': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [{ + 'bidder': 'clickforce', + 'params': { + 'zone': '6682' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + const request = spec.buildRequests(bidRequests); + + it('sends bid request to our endpoint via POST', () => { + expect(request.method).to.equal('POST'); + }); + }); + + describe('interpretResponse', () => { + let response = [{ + 'cpm': 0.5, + 'width': '300', + 'height': '250', + 'callback_uid': '220ed41385952a', + 'type': 'Default Ad', + 'tag': '', + 'creativeId': '1f99ac5c3ef10a4097499a5686b30aff-6682', + 'requestId': '220ed41385952a', + 'currency': 'USD', + 'ttl': 60, + 'netRevenue': true, + 'zone': '6682' + }]; + + it('should get the correct bid response', () => { + let expectedResponse = [{ + 'requestId': '220ed41385952a', + 'cpm': 0.5, + 'width': '300', + 'height': '250', + 'creativeId': '1f99ac5c3ef10a4097499a5686b30aff-6682', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 60, + 'ad': '' + }]; + + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles empty bid response', () => { + let response = { + body: {} + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs function', () => { + it('should register type is iframe', () => { + const syncOptions = { + 'iframeEnabled': 'true' + } + let userSync = spec.getUserSyncs(syncOptions); + expect(userSync[0].type).to.equal('iframe'); + expect(userSync[0].url).to.equal('https://cdn.doublemax.net/js/capmapping.htm'); + }); + + it('should register type is image', () => { + const syncOptions = { + 'pixelEnabled': 'true' + } + let userSync = spec.getUserSyncs(syncOptions); + expect(userSync[0].type).to.equal('image'); + expect(userSync[0].url).to.equal('https://c.doublemax.net/cm'); + }); + }); +}); From b1f043def656b00bdaa5ef83ea9638cecddfe7bf Mon Sep 17 00:00:00 2001 From: Slind14 Date: Mon, 30 Apr 2018 15:53:40 +0200 Subject: [PATCH 0301/1594] =?UTF-8?q?added=20missing=20dfpAdServerVideo.js?= =?UTF-8?q?=20dfp=20vast=20tag=20generation=20uri=20compone=E2=80=A6=20(#2?= =?UTF-8?q?440)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added missing dfpAdServerVideo.js dfp vast tag generation uri component encoding * fixed buildDfpVideoUrl not returning empty targeting * reverted last commits change because it broke display targeting --- modules/dfpAdServerVideo.js | 4 ++-- src/targeting.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index d1c66833104..1c9dbe1fac4 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -80,7 +80,7 @@ export default function buildDfpVideoUrl(options) { const derivedParams = { correlator: Date.now(), sz: parseSizesInput(adUnit.sizes).join('|'), - url: location.href, + url: encodeURIComponent(location.href), }; const encodedCustomParams = getCustParams(bid, options); @@ -152,7 +152,7 @@ function getCustParams(bid, options) { adserverTargeting, { hb_uuid: bid && bid.videoCacheKey }, // hb_uuid will be deprecated and replaced by hb_cache_id - {hb_cache_id: bid && bid.videoCacheKey}, + { hb_cache_id: bid && bid.videoCacheKey }, optCustParams, ); return encodeURIComponent(formatQS(customParams)); diff --git a/src/targeting.js b/src/targeting.js index 498335b598c..0ca9f949a64 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -22,7 +22,7 @@ export const isBidExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 + T const isUnusedBid = (bid) => bid && ((bid.status && !includes([BID_TARGETING_SET, RENDERED], bid.status)) || !bid.status); // If two bids are found for same adUnitCode, we will use the latest one to take part in auction -// This can happen in case of concurrent autions +// This can happen in case of concurrent auctions export const getOldestBid = function(bid, i, arr) { let oldestBid = true; arr.forEach((val, j) => { From 2d0f6ca70b71895f20c99269cd94a642acb17da5 Mon Sep 17 00:00:00 2001 From: haohany Date: Mon, 30 Apr 2018 10:51:40 -0700 Subject: [PATCH 0302/1594] Do client-side user syncs when using the OpenRTB endpoint (#2410) --- modules/prebidServerBidAdapter.js | 23 ++++++++++++------- .../modules/prebidServerBidAdapter_spec.js | 20 ++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 7bded03f3fb..22529def0a9 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -149,6 +149,20 @@ function doBidderSync(type, url, bidder) { } } +/** + * Do client-side syncs for bidders. + * + * @param {Array} bidders a list of bidder names + */ +function doClientSideSyncs(bidders) { + bidders.forEach(bidder => { + let clientAdapter = adaptermanager.getBidAdapter(bidder); + if (clientAdapter && clientAdapter.registerSyncs) { + clientAdapter.registerSyncs([]); + } + }); +} + /** * Try to convert a value to a type. * If it can't be done, the value will be returned. @@ -345,14 +359,6 @@ const LEGACY_PROTOCOL = { }); } - // do client-side syncs if available - requestedBidders.forEach(bidder => { - let clientAdapter = adaptermanager.getBidAdapter(bidder); - if (clientAdapter && clientAdapter.registerSyncs) { - clientAdapter.registerSyncs([]); - } - }); - if (result.bids) { result.bids.forEach(bidObj => { const bidRequest = utils.getBidRequest(bidObj.bid_id, bidRequests); @@ -674,6 +680,7 @@ export function PrebidServer() { } done(); + doClientSideSyncs(requestedBidders); } return Object.assign(this, { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 63055620dde..eb14c300e33 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -722,6 +722,26 @@ describe('S2S Adapter', () => { adapterManager.getBidAdapter.restore(); }); + it('registers client user syncs when using OpenRTB endpoint', () => { + let rubiconAdapter = { + registerSyncs: sinon.spy() + }; + sinon.stub(adapterManager, 'getBidAdapter').returns(rubiconAdapter); + + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + config.setConfig({s2sConfig}); + + server.respondWith(JSON.stringify(RESPONSE_OPENRTB)); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(rubiconAdapter.registerSyncs); + + adapterManager.getBidAdapter.restore(); + }); + it('registers bid responses when server requests cookie sync', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); From 9ac6ddd7fb09b8767f020cd38e1eda8ecce50879 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Mon, 30 Apr 2018 13:57:26 -0400 Subject: [PATCH 0303/1594] Sonobi Adapter - Added debugging and analytics query params. (#2463) * added vp param to trinity request * added lib_name and lib_v to trinity * return null from buildRequests if there is no keymakers * added test case for empty keymaker * only importing functions we need from utils * changed window.pbjs.version to use the gulp repalced macro .version$ * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * fixed lint issue --- modules/sonobiBidAdapter.js | 57 +++++++++++++++++----- test/spec/modules/sonobiBidAdapter_spec.js | 18 ++++++- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 170228dde7a..dd684bf8767 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -1,11 +1,10 @@ import { registerBidder } from 'src/adapters/bidderFactory'; -import * as utils from 'src/utils'; +import { getTopWindowLocation, parseSizesInput, logError, generateUUID, deepAccess, isEmpty } from '../src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; -import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; -const PAGEVIEW_ID = utils.generateUUID(); +const PAGEVIEW_ID = generateUUID(); export const spec = { code: BIDDER_CODE, @@ -37,7 +36,7 @@ export const spec = { [bid.bidId]: `${slotIdentifier}|${_validateSize(bid)}${_validateFloor(bid)}` } } else { - utils.logError(`The ad unit code or Sonobi Placement id for slot ${bid.bidId} is invalid`); + logError(`The ad unit code or Sonobi Placement id for slot ${bid.bidId} is invalid`); } }); @@ -46,15 +45,23 @@ export const spec = { const payload = { 'key_maker': JSON.stringify(data), - 'ref': utils.getTopWindowLocation().host, - 's': utils.generateUUID(), + 'ref': getTopWindowLocation().host, + 's': generateUUID(), 'pv': PAGEVIEW_ID, + 'vp': _getPlatform(), + 'lib_name': 'prebid', + 'lib_v': '$prebid.version$' }; if (validBidRequests[0].params.hfa) { payload.hfa = validBidRequests[0].params.hfa; } + // If there is no key_maker data, then dont make the request. + if (isEmpty(data)) { + return null; + } + return { method: 'GET', url: STR_ENDPOINT, @@ -80,8 +87,8 @@ export const spec = { Object.keys(bidResponse.slots).forEach(slot => { const bidId = _getBidIdFromTrinityKey(slot); - const bidRequest = find(bidderRequests, bidReqest => bidReqest.bidId === bidId); - const videoMediaType = utils.deepAccess(bidRequest, 'mediaTypes.video'); + const bidRequest = bidderRequests.find(bidReqest => bidReqest.bidId === bidId); + const videoMediaType = deepAccess(bidRequest, 'mediaTypes.video'); const mediaType = bidRequest.mediaType || (videoMediaType ? 'video' : null); const createCreative = _creative(mediaType); const bid = bidResponse.slots[slot]; @@ -138,9 +145,9 @@ export const spec = { function _validateSize (bid) { if (bid.params.sizes) { - return utils.parseSizesInput(bid.params.sizes).join(','); + return parseSizesInput(bid.params.sizes).join(','); } - return utils.parseSizesInput(bid.sizes).join(','); + return parseSizesInput(bid.sizes).join(','); } function _validateSlot (bid) { @@ -161,16 +168,42 @@ const _creative = (mediaType) => (sbi_dc, sbi_aid) => { if (mediaType === 'video') { return _videoCreative(sbi_dc, sbi_aid) } - const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null' + '&ref=' + utils.getTopWindowLocation().host; + const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null' + '&ref=' + getTopWindowLocation().host; return ''; } function _videoCreative(sbi_dc, sbi_aid) { - return `https://${sbi_dc}apex.go.sonobi.com/vast.xml?vid=${sbi_aid}&ref=${utils.getTopWindowLocation().host}` + return `https://${sbi_dc}apex.go.sonobi.com/vast.xml?vid=${sbi_aid}&ref=${getTopWindowLocation().host}` } function _getBidIdFromTrinityKey (key) { return key.split('|').slice(-1)[0] } +/** + * @param context - the window to determine the innerWidth from. This is purely for test purposes as it should always be the current window + */ +export const _isInbounds = (context = window) => (lowerBound = 0, upperBound = Number.MAX_SAFE_INTEGER) => context.innerWidth >= lowerBound && context.innerWidth < upperBound; + +/** + * @param context - the window to determine the innerWidth from. This is purely for test purposes as it should always be the current window + */ +export function _getPlatform(context = window) { + const isInBounds = _isInbounds(context); + const MOBILE_VIEWPORT = { + lt: 768 + }; + const TABLET_VIEWPORT = { + lt: 992, + ge: 768 + }; + if (isInBounds(0, MOBILE_VIEWPORT.lt)) { + return 'mobile' + } + if (isInBounds(TABLET_VIEWPORT.ge, TABLET_VIEWPORT.lt)) { + return 'tablet' + } + return 'desktop'; +} + registerBidder(spec); diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 4fd5c13e65c..874c92e518e 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import { spec } from 'modules/sonobiBidAdapter' +import { spec, _getPlatform } from 'modules/sonobiBidAdapter' import { newBidder } from 'src/adapters/bidderFactory' describe('SonobiBidAdapter', () => { @@ -139,6 +139,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.pv).to.equal(bidRequestsPageViewID.data.pv) expect(bidRequests.data.hfa).to.not.exist expect(bidRequests.bidderRequests).to.eql(bidRequest); + expect(bidRequests.data.vp).to.equal('tablet'); }) it('should return a properly formatted request with hfa', () => { @@ -151,6 +152,10 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.s).not.to.be.empty expect(bidRequests.data.hfa).to.equal('hfakey') }) + it('should return null if there is nothing to bid on', () => { + const bidRequests = spec.buildRequests([{params: {}}]) + expect(bidRequests).to.equal(null); + }) }) describe('.interpretResponse', () => { @@ -287,4 +292,15 @@ describe('SonobiBidAdapter', () => { expect(spec.getUserSyncs({ pixelEnabled: false }, bidResponse)).to.have.length(0); }) }) + describe('_getPlatform', () => { + it('should return mobile', () => { + expect(_getPlatform({innerWidth: 767})).to.equal('mobile') + }) + it('should return tablet', () => { + expect(_getPlatform({innerWidth: 800})).to.equal('tablet') + }) + it('should return desktop', () => { + expect(_getPlatform({innerWidth: 1000})).to.equal('desktop') + }) + }) }) From 12cf6621db3cc255bf2f7ae4cd3371e30574fd79 Mon Sep 17 00:00:00 2001 From: hakanarik Date: Mon, 30 Apr 2018 21:27:11 +0300 Subject: [PATCH 0304/1594] Add New Adapter admaticBidAdapter (#2390) * Create admaticBidAdapter.js * Create admaticBidAdapter.md * Update admaticBidAdapter.js * Update admaticBidAdapter.js * Update admaticBidAdapter.js * Update admaticBidAdapter.js --- modules/admaticBidAdapter.js | 147 +++++++++++++++++++++++++++++++++++ modules/admaticBidAdapter.md | 54 +++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 modules/admaticBidAdapter.js create mode 100644 modules/admaticBidAdapter.md diff --git a/modules/admaticBidAdapter.js b/modules/admaticBidAdapter.js new file mode 100644 index 00000000000..28858aceaa1 --- /dev/null +++ b/modules/admaticBidAdapter.js @@ -0,0 +1,147 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'admatic'; +const ENDPOINT_URL = '//ads4.admatic.com.tr/prebid/v3/bidrequest'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['admatic'], // 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 !!(bid.params.pid && bid.params.wid && bid.params.url); + }, + /** + * 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) { + const payload = { + request: [] + }; + + for (var i = 0; i < validBidRequests.length; i++) { + var validBidRequest = validBidRequests[i]; + payload.auctionId = validBidRequest.auctionId; + payload.bidder = validBidRequest.bidder; + payload.bidderRequestId = validBidRequest.bidderRequestId; + payload.pid = validBidRequest.params.pid; + payload.wid = validBidRequest.params.wid; + payload.url = validBidRequest.params.url; + + var request = { + adUnitCode: validBidRequest.adUnitCode, + bidId: validBidRequest.bidId, + transactionId: validBidRequest.transactionId, + priceType: validBidRequest.params.priceType, + sizes: transformSizes(validBidRequest.sizes) + } + + payload.request.push(request); + } + + const payloadString = JSON.stringify(payload); + + return { + method: 'POST', + url: ENDPOINT_URL, + data: payloadString, + bidder: 'admatic', + bids: validBidRequests + }; + }, + + /** + * 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) { + if (serverBody.tags && serverBody.tags.length > 0) { + serverBody.tags.forEach(serverBid => { + if (serverBid != null) { + if (serverBid.cpm !== 0) { + const bidResponse = { + requestId: serverBid.bidId, + cpm: serverBid.cpm, + width: serverBid.width, + height: serverBid.height, + creativeId: serverBid.creativeId, + dealId: serverBid.dealId, + currency: serverBid.currency, + netRevenue: serverBid.netRevenue, + ttl: serverBid.ttl, + referrer: serverBid.referrer, + ad: serverBid.ad + }; + + 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) { + const syncs = []; + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: '//ads4.admatic.com.tr/prebid/static/usersync/v3/async_usersync.html' + }); + } + + if (syncOptions.pixelEnabled && serverResponses.length > 0) { + syncs.push({ + type: 'image', + url: 'https://ads5.admatic.com.tr/prebid/v3/bidrequest/usersync' + }); + } + return syncs; + } +} + +/* Turn bid request sizes into ut-compatible format */ +function transformSizes(requestSizes) { + let sizes = []; + let sizeObj = {}; + + 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); + } 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; +} + +registerBidder(spec); diff --git a/modules/admaticBidAdapter.md b/modules/admaticBidAdapter.md new file mode 100644 index 00000000000..f6e822b9c06 --- /dev/null +++ b/modules/admaticBidAdapter.md @@ -0,0 +1,54 @@ +# Overview + +``` +Module Name: AdMatic Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@admatic.com.tr +``` + +# Description + +Module that connects to AdMatic demand sources + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, + bids: [ + { + bidder: "admatic", + params: { + pid: 193937152158, // publisher id without "adm-pub-" prefix + wid: 104276324971, // website id + priceType: 'gross', // default is net + url: window.location.href || window.top.location.href //page url from js + } + } + ] + },{ + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[320, 50]], // a mobile size + } + }, + bids: [ + { + bidder: "admatic", + params: { + pid: 193937152158, // publisher id without "adm-pub-" prefix + wid: 104276324971, // website id + priceType: 'gross', // default is net + url: window.location.href || window.top.location.href //page url from js + } + } + ] + } + ]; +``` From b1f87414e5ec20d1bcf9127d99f34b21c88df1a4 Mon Sep 17 00:00:00 2001 From: Konstantin Prokopchik Date: Mon, 30 Apr 2018 21:38:45 +0300 Subject: [PATCH 0305/1594] Getintent adapter: support multisize bids (#2453) * GetIntent adapter - added support for multi size bids * GetIntent adapter - add test case * GetIntent adapter - check malformed sizes in bid request --- modules/getintentBidAdapter.js | 27 ++++++++++++++----- test/spec/modules/getintentBidAdapter_spec.js | 13 ++++++++- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/modules/getintentBidAdapter.js b/modules/getintentBidAdapter.js index f677b107529..0bee2734d01 100644 --- a/modules/getintentBidAdapter.js +++ b/modules/getintentBidAdapter.js @@ -49,7 +49,7 @@ export const spec = { * Callback for bids, after the call to DSP completes. * Parse the response from the server into a list of bids. * - * @param {object} serverResponse A response from the server. + * @param {object} serverResponse A response from the GetIntent's server. * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: function(serverResponse) { @@ -127,16 +127,31 @@ function addOptional(params, request, props) { } } +/** + * @param {String} s The string representing a size (e.g. "300x250"). + * @return {Number[]} An array with two elements: [width, height] (e.g.: [300, 250]). + * */ function parseSize(s) { return s.split('x').map(Number); } -function produceSize(sizes) { - // TODO: add support for multiple sizes - if (Array.isArray(sizes[0])) { - return sizes[0].join('x'); +/** + * @param {Array} sizes An array of sizes/numbers to be joined into single string. + * May be an array (e.g. [300, 250]) or array of arrays (e.g. [[300, 250], [640, 480]]. + * @return {String} The string with sizes, e.g. array of sizes [[50, 50], [80, 80]] becomes "50x50,80x80" string. + * */ +function produceSize (sizes) { + function sizeToStr(s) { + if (Array.isArray(s) && s.length === 2 && Number.isInteger(s[0]) && Number.isInteger(s[1])) { + return s.join('x'); + } else { + throw "Malformed parameter 'sizes'"; + } + } + if (Array.isArray(sizes) && Array.isArray(sizes[0])) { + return sizes.map(sizeToStr).join(','); } else { - return sizes.join('x'); + return sizeToStr(sizes); } } diff --git a/test/spec/modules/getintentBidAdapter_spec.js b/test/spec/modules/getintentBidAdapter_spec.js index 1b76c4852b4..17f9a95fec4 100644 --- a/test/spec/modules/getintentBidAdapter_spec.js +++ b/test/spec/modules/getintentBidAdapter_spec.js @@ -9,7 +9,15 @@ describe('GetIntent Adapter Tests:', () => { tid: 't1000' }, sizes: [[300, 250]] - }]; + }, + { + bidId: 'bid54321', + params: { + pid: 'p1000', + tid: 't1000' + }, + sizes: [[50, 50], [100, 100]] + }] const videoBidRequest = { bidId: 'bid789', params: { @@ -36,6 +44,8 @@ describe('GetIntent Adapter Tests:', () => { expect(serverRequest.data.tid).to.equal('t1000'); expect(serverRequest.data.size).to.equal('300x250'); expect(serverRequest.data.is_video).to.equal(false); + serverRequest = serverRequests[1]; + expect(serverRequest.data.size).to.equal('50x50,100x100'); }); it('Verify build video request', () => { @@ -123,6 +133,7 @@ describe('GetIntent Adapter Tests:', () => { it('Verify if bid request valid', () => { expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); + expect(spec.isBidRequestValid(bidRequests[1])).to.equal(true); expect(spec.isBidRequestValid({})).to.equal(false); expect(spec.isBidRequestValid({ params: {} })).to.equal(false); expect(spec.isBidRequestValid({ params: { test: 123 } })).to.equal(false); From 59e0042ca23fe22be6e079956195c5b230c3ff36 Mon Sep 17 00:00:00 2001 From: LeoWu Date: Tue, 1 May 2018 02:42:28 +0800 Subject: [PATCH 0306/1594] [FEAT] support mediaTypes.banner.sizes (#2444) --- modules/bridgewellBidAdapter.js | 60 ++-- modules/bridgewellBidAdapter.md | 83 +++--- .../spec/modules/bridgewellBidAdapter_spec.js | 275 ++++++++++++------ 3 files changed, 281 insertions(+), 137 deletions(-) diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index 2a7dc0b35c3..712b00ec51a 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'bridgewell'; -const REQUEST_ENDPOINT = '//rec.scupio.com/recweb/prebid.aspx'; +const REQUEST_ENDPOINT = '//rec.scupio.com/recweb/prebid.aspx?cb=' + Math.random(); export const spec = { code: BIDDER_CODE, @@ -43,17 +43,23 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function(validBidRequests) { - const channelIDs = []; - + const adUnits = []; utils._each(validBidRequests, function(bid) { - channelIDs.push(bid.params.ChannelID); + adUnits.push({ + ChannelID: bid.params.ChannelID, + mediaTypes: bid.mediaTypes || { + banner: { + sizes: bid.sizes + } + } + }); }); return { - method: 'GET', + method: 'POST', url: REQUEST_ENDPOINT, data: { - 'ChannelID': channelIDs.join(',') + adUnits: adUnits }, validBidRequests: validBidRequests }; @@ -77,15 +83,35 @@ export const spec = { return; } - const anotherFormatSize = []; // for store width and height let matchedResponse = find(serverResponse.body, function(res) { - return !!res && !res.consumed && find(req.sizes, function(size) { - let width = res.width; - let height = res.height; - if (typeof size === 'number') anotherFormatSize.push(size); // if sizes format is Array[Number], push width and height into anotherFormatSize - return (width === size[0] && height === size[1]) || // for format Array[Array[Number]] check - (width === anotherFormatSize[0] && height === anotherFormatSize[1]); // for foramt Array[Number] check - }); + let valid = false; + + if (!!res && !res.consumed) { // response exists and not consumed + if (res.width && res.height) { + let mediaTypes = req.mediaTypes; + // for prebid 1.0 and later usage, mediaTypes.banner.sizes + let sizes = mediaTypes && mediaTypes.banner && mediaTypes.banner.sizes ? mediaTypes.banner.sizes : req.sizes; + if (sizes) { + let sizeValid; + let width = res.width; + let height = res.height; + // check response size validation + if (typeof sizes[0] === 'number') { // for foramt Array[Number] check + sizeValid = width === sizes[0] && height === sizes[1]; + } else { // for format Array[Array[Number]] check + sizeValid = find(sizes, function(size) { + return (width === size[0] && height === size[1]); + }); + } + + if (sizeValid) { // dont care native sizes + valid = true; + } + } + } + } + + return valid; }); if (matchedResponse) { @@ -94,11 +120,9 @@ export const spec = { // check required parameters if (typeof matchedResponse.cpm !== 'number') { return; - } else if (typeof matchedResponse.width !== 'number' || typeof matchedResponse.height !== 'number') { - return; } else if (typeof matchedResponse.ad !== 'string') { return; - } else if (typeof matchedResponse.net_revenue === 'undefined') { + } else if (typeof matchedResponse.netRevenue !== 'boolean') { return; } else if (typeof matchedResponse.currency !== 'string') { return; @@ -111,7 +135,7 @@ export const spec = { bidResponse.ad = matchedResponse.ad; bidResponse.ttl = matchedResponse.ttl; bidResponse.creativeId = matchedResponse.id; - bidResponse.netRevenue = matchedResponse.net_revenue === 'true'; + bidResponse.netRevenue = matchedResponse.netRevenue; bidResponse.currency = matchedResponse.currency; bidResponses.push(bidResponse); diff --git a/modules/bridgewellBidAdapter.md b/modules/bridgewellBidAdapter.md index b9d065054fa..6e542af18a7 100644 --- a/modules/bridgewellBidAdapter.md +++ b/modules/bridgewellBidAdapter.md @@ -10,41 +10,50 @@ Module that connects to Bridgewell demand source to fetch bids. # Test Parameters ``` - var adUnits = [ - { - code: 'test-div', - sizes: [[300, 250]], - bids: [ - { - bidder: 'bridgewell', - params: { - ChannelID: 'CgUxMjMzOBIBNiIFcGVubnkqCQisAhD6ARoBOQ' - } - } - ] - },{ - code: 'test-div', - sizes: [[728, 90]], - bids: [ - { - bidder: 'bridgewell', - params: { - ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ', - cpmWeight: 1.5 - } - } - ] - },{ - code: 'test-div', - sizes: [728, 90], - bids: [ - { - bidder: 'bridgewell', - params: { - ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ' - } - } - ] - } - ]; + var adUnits = [{ + code: 'test-div', + sizes: [ + [300, 250] + ], + bids: [{ + bidder: 'bridgewell', + params: { + ChannelID: 'CgUxMjMzOBIBNiIFcGVubnkqCQisAhD6ARoBOQ' + } + }] + }, { + code: 'test-div', + sizes: [ + [728, 90] + ], + bids: [{ + bidder: 'bridgewell', + params: { + ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ', + cpmWeight: 1.5 + } + }] + }, { + code: 'test-div', + sizes: [728, 90], + bids: [{ + bidder: 'bridgewell', + params: { + ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ' + } + }] + }, { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [728, 90] + } + }, + bids: [{ + bidder: 'bridgewell', + params: { + ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ' + } + }] + }]; ``` diff --git a/test/spec/modules/bridgewellBidAdapter_spec.js b/test/spec/modules/bridgewellBidAdapter_spec.js index 6b95b44dfe5..8615531f88f 100644 --- a/test/spec/modules/bridgewellBidAdapter_spec.js +++ b/test/spec/modules/bridgewellBidAdapter_spec.js @@ -72,6 +72,21 @@ describe('bridgewellBidAdapter', function () { 'bidId': '3150ccb55da321', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ', + }, + 'adUnitCode': 'adunit-code-2', + 'mediaTypes': { + 'banner': { + 'sizes': [728, 90] + } + }, + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', } ]; const adapter = newBidder(spec); @@ -141,6 +156,10 @@ describe('bridgewellBidAdapter', function () { expect(spec.isBidRequestValid(bidWithZeroCpmWeight)).to.equal(false); }); + it('should return false when required params not found', () => { + expect(spec.isBidRequestValid({})).to.equal(false); + }); + it('should return false when required params are not passed', () => { let bidWithoutCpmWeight = Object.assign({}, bidWithoutCpmWeight); let bidWithCorrectCpmWeight = Object.assign({}, bidWithCorrectCpmWeight); @@ -177,10 +196,16 @@ describe('bridgewellBidAdapter', function () { describe('buildRequests', () => { it('should attach valid params to the tag', () => { - const request = spec.buildRequests([bidRequests[0]]); + const request = spec.buildRequests(bidRequests); const payload = request.data; + const adUnits = payload.adUnits; + expect(payload).to.be.an('object'); - expect(payload).to.have.property('ChannelID').that.is.a('string'); + expect(adUnits).to.be.an('array'); + for (let i = 0, max_i = adUnits.length; i < max_i; i++) { + let adUnit = adUnits[i]; + expect(adUnit).to.have.property('ChannelID').that.is.a('string'); + } }); it('should attach validBidRequests to the tag', () => { @@ -188,79 +213,89 @@ describe('bridgewellBidAdapter', function () { const validBidRequests = request.validBidRequests; expect(validBidRequests).to.deep.equal(bidRequests); }); - - it('should attach valid params to the tag if multiple ChannelIDs are presented', () => { - const request = spec.buildRequests(bidRequests); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('ChannelID').that.is.a('string'); - expect(payload.ChannelID.split(',')).to.have.lengthOf(bidRequests.length); - }); }); describe('interpretResponse', () => { const request = spec.buildRequests(bidRequests); - const serverResponses = [{ - 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', - 'bidder_code': 'bridgewell', - 'cpm': 5.0, - 'width': 300, - 'height': 250, - 'ad': '
test 300x250
', - 'ttl': 360, - 'net_revenue': 'true', - 'currency': 'NTD' - }, { - 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', - 'bidder_code': 'bridgewell', - 'cpm': 5.0, - 'width': 728, - 'height': 90, - 'ad': '
test 728x90
', - 'ttl': 360, - 'net_revenue': 'true', - 'currency': 'NTD' - }, { - 'id': '8f12c646-3b87-4326-a837-c2a76999f168', - 'bidder_code': 'bridgewell', - 'cpm': 5.0, - 'width': 300, - 'height': 250, - 'ad': '
test 300x250
', - 'ttl': 360, - 'net_revenue': 'true', - 'currency': 'NTD' - }, { - 'id': '8f12c646-3b87-4326-a837-c2a76999f168', - 'bidder_code': 'bridgewell', - 'cpm': 5.0, - 'width': 300, - 'height': 250, - 'ad': '
test 300x250
', - 'ttl': 360, - 'net_revenue': 'true', - 'currency': 'NTD' - }, { - 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', - 'bidder_code': 'bridgewell', - 'cpm': 5.0, - 'width': 728, - 'height': 90, - 'ad': '
test 728x90
', - 'ttl': 360, - 'net_revenue': 'true', - 'currency': 'NTD' - }, { - 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', - 'bidder_code': 'bridgewell', - 'cpm': 5.0, - 'width': 728, - 'height': 90, - 'ad': '
test 728x90
', - 'ttl': 360, - 'net_revenue': 'true', - 'currency': 'NTD' - }]; + const serverResponses = [ + { + 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 300, + 'height': 250, + 'ad': '
test 300x250
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }, + { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 728, + 'height': 90, + 'ad': '
test 728x90
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }, + { + 'id': '8f12c646-3b87-4326-a837-c2a76999f168', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 300, + 'height': 250, + 'ad': '
test 300x250
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }, + { + 'id': '8f12c646-3b87-4326-a837-c2a76999f168', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 300, + 'height': 250, + 'ad': '
test 300x250
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }, + { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 728, + 'height': 90, + 'ad': '
test 728x90
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }, + { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 728, + 'height': 90, + 'ad': '
test 728x90
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }, + { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 728, + 'height': 90, + 'ad': '
test 728x90
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + } + ]; it('should return all required parameters', () => { const result = spec.interpretResponse({'body': serverResponses}, request); @@ -278,38 +313,114 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if cpm is missing', () => { + it('should give up bid if request sizes is missing', () => { let target = Object.assign({}, serverResponses[0]); - delete target.cpm; + target.consumed = false; + const result = spec.interpretResponse({'body': [target]}, spec.buildRequests([{ + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CLJgEAYYvxUiBXBlbm55KgkIrAIQ-gEaATk' + }, + 'adUnitCode': 'adunit-code-1', + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }])); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if response sizes is invalid', () => { + let target = { + 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'ad': '
test 300x250
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if cpm is missing', () => { + let target = { + 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', + 'bidder_code': 'bridgewell', + 'width': 300, + 'height': 250, + 'ad': '
test 300x250
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + const result = spec.interpretResponse({'body': [target]}, request); expect(result).to.deep.equal([]); }); it('should give up bid if width or height is missing', () => { - let target = Object.assign({}, serverResponses[0]); - delete target.height; - delete target.width; + let target = { + 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'ad': '
test 300x250
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + const result = spec.interpretResponse({'body': [target]}, request); expect(result).to.deep.equal([]); }); it('should give up bid if ad is missing', () => { - let target = Object.assign({}, serverResponses[0]); - delete target.ad; + let target = { + 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 300, + 'height': 250, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + const result = spec.interpretResponse({'body': [target]}, request); expect(result).to.deep.equal([]); }); it('should give up bid if revenue mode is missing', () => { - let target = Object.assign({}, serverResponses[0]); - delete target.net_revenue; + let target = { + 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 300, + 'height': 250, + 'ad': '
test 300x250
', + 'ttl': 360, + 'currency': 'NTD' + }; + const result = spec.interpretResponse({'body': [target]}, request); expect(result).to.deep.equal([]); }); it('should give up bid if currency is missing', () => { - let target = Object.assign({}, serverResponses[0]); - delete target.currency; + let target = { + 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 300, + 'height': 250, + 'ad': '
test 300x250
', + 'ttl': 360, + 'netRevenue': true + }; + const result = spec.interpretResponse({'body': [target]}, request); expect(result).to.deep.equal([]); }); From 37671298f93ec1f073dee3d1afcbe15d417875ad Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 30 Apr 2018 12:50:24 -0600 Subject: [PATCH 0307/1594] fix sonobi tests for device size so it works in browserstack --- test/spec/modules/sonobiBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 874c92e518e..791d07ba91a 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -139,7 +139,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.pv).to.equal(bidRequestsPageViewID.data.pv) expect(bidRequests.data.hfa).to.not.exist expect(bidRequests.bidderRequests).to.eql(bidRequest); - expect(bidRequests.data.vp).to.equal('tablet'); + expect(['mobile', 'tablet', 'desktop']).to.contain(bidRequests.data.vp); }) it('should return a properly formatted request with hfa', () => { From 603f5f0b6ecda015ab3cd3ddb3df7e19d5ad2cf2 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 30 Apr 2018 12:53:54 -0600 Subject: [PATCH 0308/1594] fix sonobi to use polyfilled find to correct browserstack tests --- modules/sonobiBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index dd684bf8767..438ab7f3a74 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -1,6 +1,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { getTopWindowLocation, parseSizesInput, logError, generateUUID, deepAccess, isEmpty } from '../src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; @@ -87,7 +88,7 @@ export const spec = { Object.keys(bidResponse.slots).forEach(slot => { const bidId = _getBidIdFromTrinityKey(slot); - const bidRequest = bidderRequests.find(bidReqest => bidReqest.bidId === bidId); + const bidRequest = find(bidderRequests, bidReqest => bidReqest.bidId === bidId); const videoMediaType = deepAccess(bidRequest, 'mediaTypes.video'); const mediaType = bidRequest.mediaType || (videoMediaType ? 'video' : null); const createCreative = _creative(mediaType); From 77d0e0610dbc1ed3e2bece1c59b1da8632d5ef2b Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 30 Apr 2018 13:19:39 -0600 Subject: [PATCH 0309/1594] fixing getintent to use utils.isInteger to fix browserstack tests --- modules/getintentBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/getintentBidAdapter.js b/modules/getintentBidAdapter.js index 0bee2734d01..611e8eebd6e 100644 --- a/modules/getintentBidAdapter.js +++ b/modules/getintentBidAdapter.js @@ -1,4 +1,5 @@ import { registerBidder } from 'src/adapters/bidderFactory'; +import { isInteger } from 'src/utils'; const BIDDER_CODE = 'getintent'; const IS_NET_REVENUE = true; @@ -142,7 +143,7 @@ function parseSize(s) { * */ function produceSize (sizes) { function sizeToStr(s) { - if (Array.isArray(s) && s.length === 2 && Number.isInteger(s[0]) && Number.isInteger(s[1])) { + if (Array.isArray(s) && s.length === 2 && isInteger(s[0]) && isInteger(s[1])) { return s.join('x'); } else { throw "Malformed parameter 'sizes'"; From d28c4a8310b600bca24f0b83e70c080942be2cac Mon Sep 17 00:00:00 2001 From: aprakash-sovrn Date: Mon, 30 Apr 2018 18:11:23 -0600 Subject: [PATCH 0310/1594] [1.x] Populate crid with values from demand if present (#2424) * fix sovrn dealid * send 'iv' param if present * `page` field in `site` object sends full url * Enhance location detection within util function. * fix func call * fix tagid var type * add test for converting tagid to string * CR * Reorg gettopwindowlocation util & add tests. * lint fixes * search param is string in window location objects * set creativeId to crid if present in response --- modules/sovrnBidAdapter.js | 2 +- test/spec/modules/sovrnBidAdapter_spec.js | 58 ++++++++++++++++------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 564dca85690..3a70a0ed433 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -70,7 +70,7 @@ export const spec = { cpm: parseFloat(sovrnBid.price), width: parseInt(sovrnBid.w), height: parseInt(sovrnBid.h), - creativeId: sovrnBid.id, + creativeId: sovrnBid.crid || sovrnBid.id, dealId: sovrnBid.dealid || null, currency: 'USD', netRevenue: true, diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index a440b3d43c4..9ad25753186 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -106,22 +106,26 @@ describe('sovrnBidAdapter', function() { }); describe('interpretResponse', () => { - let response = { - body: { - 'id': '37386aade21a71', - 'seatbid': [{ - 'bid': [{ - 'id': 'a_403370_332fdb9b064040ddbec05891bd13ab28', - 'impid': '263c448586f5a1', - 'price': 0.45882675, - 'nurl': '', - 'adm': '', - 'h': 90, - 'w': 728 + let response; + beforeEach(() => { + response = { + body: { + 'id': '37386aade21a71', + 'seatbid': [{ + 'bid': [{ + 'id': 'a_403370_332fdb9b064040ddbec05891bd13ab28', + 'crid': 'creativelycreatedcreativecreative', + 'impid': '263c448586f5a1', + 'price': 0.45882675, + 'nurl': '', + 'adm': '', + 'h': 90, + 'w': 728 + }] }] - }] - } - }; + } + }; + }); it('should get the correct bid response', () => { let expectedResponse = [{ @@ -129,7 +133,27 @@ describe('sovrnBidAdapter', function() { 'cpm': 0.45882675, 'width': 728, 'height': 90, - 'creativeId': 'a_403370_332fdb9b064040ddbec05891bd13ab28', + 'creativeId': 'creativelycreatedcreativecreative', + 'dealId': null, + 'currency': 'USD', + 'netRevenue': true, + 'mediaType': 'banner', + 'ad': decodeURIComponent(`>`), + 'ttl': 60000 + }]; + + let result = spec.interpretResponse(response); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('crid should default to the bid id if not on the response', () => { + delete response.body.seatbid[0].bid[0].crid; + let expectedResponse = [{ + 'requestId': '263c448586f5a1', + 'cpm': 0.45882675, + 'width': 728, + 'height': 90, + 'creativeId': response.body.seatbid[0].bid[0].id, 'dealId': null, 'currency': 'USD', 'netRevenue': true, @@ -150,7 +174,7 @@ describe('sovrnBidAdapter', function() { 'cpm': 0.45882675, 'width': 728, 'height': 90, - 'creativeId': 'a_403370_332fdb9b064040ddbec05891bd13ab28', + 'creativeId': 'creativelycreatedcreativecreative', 'dealId': 'baking', 'currency': 'USD', 'netRevenue': true, From a0fee37b476df8dc2a3ab411049853e6d2d8a87f Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Tue, 1 May 2018 19:00:08 +0530 Subject: [PATCH 0311/1594] PulsePoint Adapter GDPR support (#2471) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * Pulsepoint Bid Adapter - GDPR support * minor update * minor update * Fixing review comment --- modules/pulsepointBidAdapter.js | 13 +++++++++++- .../spec/modules/pulsepointBidAdapter_spec.js | 21 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index fc637cc9fff..94733ad7805 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -34,7 +34,7 @@ export const spec = { !!(bid && bid.params && bid.params.cp && bid.params.ct) ), - buildRequests: bidRequests => { + buildRequests: (bidRequests, bidderRequest) => { const request = { id: bidRequests[0].bidderRequestId, imp: bidRequests.map(slot => impression(slot)), @@ -42,6 +42,7 @@ export const spec = { app: app(bidRequests), device: device(), }; + applyGdpr(bidderRequest, request); return { method: 'POST', url: '//bid.contextweb.com/header/ortb', @@ -304,6 +305,16 @@ function adSize(slot) { return [1, 1]; } +/** + * Applies GDPR parameters to request. + */ +function applyGdpr(bidderRequest, ortbRequest) { + if (bidderRequest && bidderRequest.gdprConsent) { + ortbRequest.regs = { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0 } }; + ortbRequest.user = { ext: { consent: bidderRequest.gdprConsent.consentString } }; + } +} + /** * Parses the native response from the Bid given. */ diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index b4793256ee0..709dbeb76a2 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -273,4 +273,25 @@ describe('PulsePoint Adapter Tests', () => { expect(ortbRequest.app.storeurl).to.equal('http://pulsepoint.com/apps'); expect(ortbRequest.app.domain).to.equal('pulsepoint.com'); }); + + it('Verify GDPR', () => { + const bidderRequest = { + gdprConsent: { + gdprApplies: true, + consentString: 'serialized_gpdr_data' + } + }; + const request = spec.buildRequests(slotConfigs, bidderRequest); + expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // user object + expect(ortbRequest.user).to.not.equal(null); + expect(ortbRequest.user.ext).to.not.equal(null); + expect(ortbRequest.user.ext.consent).to.equal('serialized_gpdr_data'); + // regs object + expect(ortbRequest.regs).to.not.equal(null); + expect(ortbRequest.regs.ext).to.not.equal(null); + expect(ortbRequest.regs.ext.gdpr).to.equal(1); + }); }); From 027abc72e9735e92030106fc8427fcc8c79aaaf5 Mon Sep 17 00:00:00 2001 From: sekindo Date: Tue, 1 May 2018 17:02:36 +0300 Subject: [PATCH 0312/1594] getting publisher url fix (#2472) --- modules/sekindoUMBidAdapter.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/modules/sekindoUMBidAdapter.js b/modules/sekindoUMBidAdapter.js index e87f3194ff0..cf8ba9e23f0 100644 --- a/modules/sekindoUMBidAdapter.js +++ b/modules/sekindoUMBidAdapter.js @@ -25,11 +25,17 @@ export const spec = { */ buildRequests: function(validBidRequests, bidderRequest) { var pubUrl = null; - if (parent !== window) { - pubUrl = document.referrer; - } else { - pubUrl = window.location.href; - } + try { + if (window.top == window) { + pubUrl = window.location.href; + } else { + try { + pubUrl = window.top.location.href; + } catch (e2) { + pubUrl = document.referrer; + } + } + } catch (e1) {} return validBidRequests.map(bidRequest => { var subId = utils.getBidIdParameter('subId', bidRequest.params); From 4a149cf39e88522cc414c1606871c2777c52b3c4 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Tue, 1 May 2018 07:06:14 -0700 Subject: [PATCH 0313/1594] OpenX Adapter: Support out of order bids. (#2452) * OpenX Adapter: Support out of order bids. * OpenX Adapter Spec: Updated overrideKeyCheck to use Chai assertion, which throws an AssertionError, so that it will be caught properly by test suite when an invalid override is provided. --- modules/openxBidAdapter.js | 38 +- test/spec/modules/openxBidAdapter_spec.js | 549 ++++++++++++++++++---- 2 files changed, 456 insertions(+), 131 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index bc00242b3e3..1cc312da273 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -70,21 +70,10 @@ function createBannerBidResponses(oxResponseObj, {bids, startTime}) { } for (let i = 0; i < adUnits.length; i++) { let adUnit = adUnits[i]; + let adUnitIdx = parseInt(adUnit.idx, 10); let bidResponse = {}; - if (adUnits.length === bids.length) { - // request and response length match, directly assign the request id based on positioning - bidResponse.requestId = bids[i].bidId; - } else { - for (let j = i; j < bids.length; j++) { - let bid = bids[j]; - if (String(bid.params.unit) === String(adUnit.adunitid) && adUnitHasValidSizeFromBid(adUnit, bid) && !bid.matched) { - // ad unit and size match, this is the correct bid response to bid - bidResponse.requestId = bid.bidId; - bid.matched = true; - break; - } - } - } + + bidResponse.requestId = bids[adUnitIdx].bidId; if (adUnit.pub_rev) { bidResponse.cpm = Number(adUnit.pub_rev) / 1000; @@ -134,27 +123,6 @@ function buildQueryStringFromParams(params) { .join('&'); } -function adUnitHasValidSizeFromBid(adUnit, bid) { - let sizes = utils.parseSizesInput(bid.sizes); - if (!sizes) { - return false; - } - let found = false; - let creative = adUnit.creative && adUnit.creative[0]; - let creative_size = String(creative.width) + 'x' + String(creative.height); - - if (utils.isArray(sizes)) { - for (let i = 0; i < sizes.length; i++) { - let size = sizes[i]; - if (String(size) === String(creative_size)) { - found = true; - break; - } - } - } - return found; -} - function getViewportDimensions(isIfr) { let width; let height; diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 35146542375..b763c111998 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -2,6 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/openxBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import {userSync} from 'src/userSync'; +import * as utils from 'src/utils'; const URLBASE = '/w/1.0/arj'; const URLBASEVIDEO = '/v/1.0/avjp'; @@ -9,6 +10,116 @@ const URLBASEVIDEO = '/v/1.0/avjp'; describe('OpenxAdapter', () => { const adapter = newBidder(spec); + /** + * Type Definitions + */ + + /** + * @typedef {{ + * impression: string, + * inview: string, + * click: string + * }} + */ + let OxArjTracking; + /** + * @typedef {{ + * ads: { + * version: number, + * count: number, + * pixels: string, + * ad: Array + * } + * }} + */ + let OxArjResponse; + /** + * @typedef {{ + * adunitid: number, + * adid:number, + * type: string, + * htmlz: string, + * framed: number, + * is_fallback: number, + * ts: string, + * cpipc: number, + * pub_rev: string, + * tbd: ?string, + * adv_id: string, + * deal_id: string, + * auct_win_is_deal: number, + * brand_id: string, + * currency: string, + * idx: string, + * creative: Array + * }} + */ + let OxArjAdUnit; + /** + * @typedef {{ + * id: string, + * width: string, + * height: string, + * target: string, + * mime: string, + * media: string, + * tracking: OxArjTracking + * }} + */ + let OxArjCreative; + + // HELPER METHODS + /** + * @type {OxArjCreative} + */ + const DEFAULT_TEST_ARJ_CREATIVE = { + id: '0', + width: 'test-width', + height: 'test-height', + target: 'test-target', + mime: 'test-mime', + media: 'test-media', + tracking: { + impression: 'test-impression', + inview: 'test-inview', + click: 'test-click' + } + }; + + /** + * @type {OxArjAdUnit} + */ + const DEFAULT_TEST_ARJ_AD_UNIT = { + adunitid: 0, + type: 'test-type', + html: 'test-html', + framed: 0, + is_fallback: 0, + ts: 'test-ts', + tbd: 'NaN', + deal_id: undefined, + auct_win_is_deal: undefined, + cpipc: 0, + pub_rev: 'test-pub_rev', + adv_id: 'test-adv_id', + brand_id: 'test-brand_id', + currency: 'test-currency', + idx: '0', + creative: [DEFAULT_TEST_ARJ_CREATIVE] + }; + + /** + * @type {OxArjResponse} + */ + const DEFAULT_ARJ_RESPONSE = { + ads: { + version: 0, + count: 1, + pixels: 'http://testpixels.net', + ad: [DEFAULT_TEST_ARJ_AD_UNIT] + } + }; + describe('inherited functions', () => { it('exists and is a function', () => { expect(adapter.callBids).to.exist.and.to.be.a('function'); @@ -53,12 +164,14 @@ describe('OpenxAdapter', () => { bidder: 'openx', params: { unit: '12345678', - delDomain: 'test-del-domain', + delDomain: 'test-del-domain' }, adUnitCode: 'adunit-code', - mediaTypes: {video: { - playerSize: [640, 480] - }}, + mediaTypes: { + video: { + playerSize: [640, 480] + } + }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', @@ -302,7 +415,7 @@ describe('OpenxAdapter', () => { }, 'params': { 'unit': '12345678', - 'delDomain': 'test-del-domain', + 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', 'bidId': '30b31c1838de1e', @@ -384,101 +497,275 @@ describe('OpenxAdapter', () => { userSync.registerSync.restore(); }); - const bids = [{ - 'bidder': 'openx', - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'mediaType': 'banner', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475' - }]; - const bidRequest = { - method: 'GET', - url: '//openx-d.openx.net/v/1.0/arj', - data: {}, - payload: {'bids': bids, 'startTime': new Date()} - }; - - const bidResponse = { - 'ads': - { - 'version': 1, - 'count': 1, - 'pixels': 'http://testpixels.net', - 'ad': [ - { - 'adunitid': 12345678, - 'adid': 5678, - 'type': 'html', - 'html': 'test_html', - 'framed': 1, - 'is_fallback': 0, - 'ts': 'ts', - 'cpipc': 1000, - 'pub_rev': '1000', - 'adv_id': 'adv_id', - 'brand_id': '', - 'creative': [ - { - 'width': '300', - 'height': '250', - 'target': '_blank', - 'mime': 'text/html', - 'media': 'test_media', - 'tracking': { - 'impression': 'http://openx-d.openx.net/v/1.0/ri?ts=ts', - 'inview': 'test_inview', - 'click': 'test_click' - } - } - ] - }] + describe('when there is a standard response', function () { + const creativeOverride = { + id: 234, + width: '300', + height: '250', + tracking: { + impression: 'http://openx-d.openx.net/v/1.0/ri?ts=ts' } + }; - }; - it('should return correct bid response', () => { - const expectedResponse = [ - { - 'requestId': '30b31c1838de1e', - 'cpm': 1, - 'width': '300', - 'height': '250', - 'creativeId': 5678, - 'ad': 'test_html', - 'ttl': 300, - 'netRevenue': true, - 'currency': 'USD', - 'ts': 'ts' - } - ]; + const adUnitOverride = { + ts: 'test-1234567890-ts', + idx: '0', + currency: 'USD', + pub_rev: '10000', + html: '
OpenX Ad
' + }; + let adUnit; + let bidResponse; + + let bid; + let bidRequest; + let bidRequestConfigs; + + beforeEach(function () { + bidRequestConfigs = [{ + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + 'mediaType': 'banner', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + bidRequest = { + method: 'GET', + url: '//openx-d.openx.net/v/1.0/arj', + data: {}, + payload: {'bids': bidRequestConfigs, 'startTime': new Date()} + }; + + adUnit = mockAdUnit(adUnitOverride, creativeOverride); + bidResponse = mockArjResponse(undefined, [adUnit]); + bid = spec.interpretResponse({body: bidResponse}, bidRequest)[0]; + }); + + it('should return a price', function () { + expect(bid.cpm).to.equal(parseInt(adUnitOverride.pub_rev, 10) / 1000); + }); + + it('should return a request id', function () { + expect(bid.requestId).to.equal(bidRequest.payload.bids[0].bidId); + }); + + it('should return width and height for the creative', function () { + expect(bid.width).to.equal(creativeOverride.width); + expect(bid.height).to.equal(creativeOverride.height); + }); + + it('should return a creativeId', function () { + expect(bid.creativeId).to.equal(creativeOverride.id); + }); + + it('should return an ad', function () { + expect(bid.ad).to.equal(adUnitOverride.html); + }); + + it('should have a time-to-live of 5 minutes', function () { + expect(bid.ttl).to.equal(300); + }); - const result = spec.interpretResponse({body: bidResponse}, bidRequest); - expect(Object.keys(result[0])).to.eql(Object.keys(expectedResponse[0])); + it('should always return net revenue', function () { + expect(bid.netRevenue).to.equal(true); + }); + + it('should return a currency', function () { + expect(bid.currency).to.equal(adUnitOverride.currency); + }); + + it('should return a transaction state', function () { + expect(bid.ts).to.equal(adUnitOverride.ts); + }); + + it('should register a beacon', () => { + spec.interpretResponse({body: bidResponse}, bidRequest); + sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(new RegExp(`\/\/openx-d\.openx\.net.*\/bo\?.*ts=${adUnitOverride.ts}`))); + }); }); - it('handles nobid responses', () => { - const bidResponse = { - 'ads': - { - 'version': 1, - 'count': 1, - 'pixels': 'http://testpixels.net', - 'ad': [] - } + describe('when there is a deal', function () { + const adUnitOverride = { + deal_id: 'ox-1000' }; + let adUnit; + let bidResponse; - const result = spec.interpretResponse({body: bidResponse}, bidRequest); - expect(result.length).to.equal(0); + let bid; + let bidRequestConfigs; + let bidRequest; + + beforeEach(function () { + bidRequestConfigs = [{ + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + 'mediaType': 'banner', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + bidRequest = { + method: 'GET', + url: '//openx-d.openx.net/v/1.0/arj', + data: {}, + payload: {'bids': bidRequestConfigs, 'startTime': new Date()} + }; + adUnit = mockAdUnit(adUnitOverride); + bidResponse = mockArjResponse(null, [adUnit]); + bid = spec.interpretResponse({body: bidResponse}, bidRequest)[0]; + mockArjResponse(); + }); + + it('should return a deal id', function () { + expect(bid.dealId).to.equal(adUnitOverride.deal_id); + }); }); - it('should register a beacon', () => { - spec.interpretResponse({body: bidResponse}, bidRequest); - sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/\/\/openx-d\.openx\.net.*\/bo\?.*ts=ts/)); + describe('when there is no bids in the response', function () { + let bidRequest; + let bidRequestConfigs; + + beforeEach(function () { + bidRequestConfigs = [{ + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + 'mediaType': 'banner', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + bidRequest = { + method: 'GET', + url: '//openx-d.openx.net/v/1.0/arj', + data: {}, + payload: {'bids': bidRequestConfigs, 'startTime': new Date()} + }; + }); + + it('handles nobid responses', () => { + const bidResponse = { + 'ads': + { + 'version': 1, + 'count': 1, + 'pixels': 'http://testpixels.net', + 'ad': [] + } + }; + + const result = spec.interpretResponse({body: bidResponse}, bidRequest); + expect(result.length).to.equal(0); + }); + }); + + describe('when adunits return out of order', function () { + const bidRequests = [{ + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[100, 111]] + } + }, + bidId: 'test-bid-request-id-1', + bidderRequestId: 'test-request-1', + auctionId: 'test-auction-id-1' + }, { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[200, 222]] + } + }, + bidId: 'test-bid-request-id-2', + bidderRequestId: 'test-request-1', + auctionId: 'test-auction-id-1' + }, { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 333]] + } + }, + 'bidId': 'test-bid-request-id-3', + 'bidderRequestId': 'test-request-1', + 'auctionId': 'test-auction-id-1' + }]; + const bidRequest = { + method: 'GET', + url: '//openx-d.openx.net/v/1.0/arj', + data: {}, + payload: {'bids': bidRequests, 'startTime': new Date()} + }; + + let outOfOrderAdunits = [ + mockAdUnit({ + idx: '1' + }, { + width: bidRequests[1].mediaTypes.banner.sizes[0][0], + height: bidRequests[1].mediaTypes.banner.sizes[0][1] + }), + mockAdUnit({ + idx: '2' + }, { + width: bidRequests[2].mediaTypes.banner.sizes[0][0], + height: bidRequests[2].mediaTypes.banner.sizes[0][1] + }), + mockAdUnit({ + idx: '0' + }, { + width: bidRequests[0].mediaTypes.banner.sizes[0][0], + height: bidRequests[0].mediaTypes.banner.sizes[0][1] + }) + ]; + + let bidResponse = mockArjResponse(undefined, outOfOrderAdunits); + + it('should return map adunits back to the proper request', function () { + const bids = spec.interpretResponse({body: bidResponse}, bidRequest); + expect(bids[0].requestId).to.equal(bidRequests[1].bidId); + expect(bids[0].width).to.equal(bidRequests[1].mediaTypes.banner.sizes[0][0]); + expect(bids[0].height).to.equal(bidRequests[1].mediaTypes.banner.sizes[0][1]); + expect(bids[1].requestId).to.equal(bidRequests[2].bidId); + expect(bids[1].width).to.equal(bidRequests[2].mediaTypes.banner.sizes[0][0]); + expect(bids[1].height).to.equal(bidRequests[2].mediaTypes.banner.sizes[0][1]); + expect(bids[2].requestId).to.equal(bidRequests[0].bidId); + expect(bids[2].width).to.equal(bidRequests[0].mediaTypes.banner.sizes[0][0]); + expect(bids[2].height).to.equal(bidRequests[0].mediaTypes.banner.sizes[0][1]); + }); }); }); @@ -615,18 +902,88 @@ describe('OpenxAdapter', () => { it('should register the pixel iframe from video ad response', () => { let syncs = spec.getUserSyncs( - { iframeEnabled: true }, - [{ body: { pixels: syncUrl } }] + {iframeEnabled: true}, + [{body: {pixels: syncUrl}}] ); - expect(syncs).to.deep.equal([{ type: 'iframe', url: syncUrl }]); + expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); }); it('should register the default iframe if no pixels available', () => { let syncs = spec.getUserSyncs( - { iframeEnabled: true }, + {iframeEnabled: true}, [] ); - expect(syncs).to.deep.equal([{ type: 'iframe', url: '//u.openx.net/w/1.0/pd' }]); + expect(syncs).to.deep.equal([{type: 'iframe', url: '//u.openx.net/w/1.0/pd'}]); }); }); + + /** + * Makes sure the override object does not introduce + * new fields against the contract + * + * This does a shallow check in order to make key checking simple + * with respect to what a helper handles. For helpers that have + * nested fields, either check your design on maybe breaking it up + * to smaller, manageable pieces + * + * OR just call this on your nth level field if necessary. + * + * @param {Object} override Object with keys that overrides the default + * @param {Object} contract Original object contains the default fields + * @param {string} typeName Name of the type we're checking for error messages + * @throws {AssertionError} + */ + function overrideKeyCheck(override, contract, typeName) { + expect(contract).to.include.all.keys(Object.keys(override)); + } + + /** + * Creates a mock ArjResponse + * @param {OxArjResponse=} response + * @param {Array=} adUnits + * @throws {AssertionError} + * @return {OxArjResponse} + */ + function mockArjResponse(response, adUnits = []) { + let mockedArjResponse = utils.deepClone(DEFAULT_ARJ_RESPONSE); + + if (response) { + overrideKeyCheck(response, DEFAULT_ARJ_RESPONSE, 'OxArjResponse'); + overrideKeyCheck(response.ads, DEFAULT_ARJ_RESPONSE.ads, 'OxArjResponse'); + Object.assign(mockedArjResponse, response); + } + + if (adUnits.length) { + mockedArjResponse.ads.count = adUnits.length; + mockedArjResponse.ads.ad = adUnits.map((adUnit, index) => { + overrideKeyCheck(adUnit, DEFAULT_TEST_ARJ_AD_UNIT, 'OxArjAdUnit'); + return Object.assign(utils.deepClone(DEFAULT_TEST_ARJ_AD_UNIT), adUnit); + }); + } + + return mockedArjResponse; + } + + /** + * Creates a mock ArjAdUnit + * @param {OxArjAdUnit=} adUnit + * @param {OxArjCreative=} creative + * @throws {AssertionError} + * @return {OxArjAdUnit} + */ + function mockAdUnit(adUnit, creative) { + overrideKeyCheck(adUnit, DEFAULT_TEST_ARJ_AD_UNIT, 'OxArjAdUnit'); + + let mockedAdUnit = Object.assign(utils.deepClone(DEFAULT_TEST_ARJ_AD_UNIT), adUnit); + + if (creative) { + overrideKeyCheck(creative, DEFAULT_TEST_ARJ_CREATIVE); + if (creative.tracking) { + overrideKeyCheck(creative.tracking, DEFAULT_TEST_ARJ_CREATIVE.tracking, 'OxArjCreative'); + } + Object.assign(mockedAdUnit.creative[0], creative); + } + + return mockedAdUnit; + } }); From 247ea80e7f1da07d2847db64248f949de35a9ef4 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 1 May 2018 10:07:26 -0400 Subject: [PATCH 0314/1594] GDPR consentManagement module (#2213) * initial commit * wip update 2 * wip update 3 * example * clean up * wip update 3 * hook setup for callBids * wip update 4 * changed gdpr code to be async-like * cleaned up the callback chain * added iab cmp detection logic * moved hook, reverted unit test changes, and restructed gdpr module * renaming module from gdpr to consentManagement * prebidserver adatper update, additional changes in module * updated unit tests for all areas, updates to module logic and structure of consent data * adding missing default value * removing accidentally committed load time testing code * changes to layout of consentManagement code and other items based on feedback * moved unit test to different location * finished incomplete unit test in appnexusBidAdapter_spec file * altered CMP function call logic * refactored consentManagement AN lookup function and added gdprDataHandler to help transfer data in auction * some minor cleanup from previous commit * change spacing to try to fix travis issue * added scenario to support consentTimeout=0 skip setTimeout * updated some comments * refactored exit logic for module * added support for consentRequired field in config * remove internal consentRequired default * minor comment fixes * comment fixes that should be have part of last commit * fix includes issue and added gdprConsent to getUserSyncs function * renamed default CMP and config field to cmpApi * wip - using postmessage to call cmp * postMessage workflow added, removed CMP eventlistener check * removed if statement * cleanup; removed variable and unneeded comments * add gdpr tests pages * updates for 1.1 CMP spec * remove rogue debugger in unit test * restructured 1.1 CMP iframe code, renamed utils function, cleaned up unit tests * GDPR support in adform adapter (#2396) * bid response adId same as bidId * test * update adform bid adapter * update unit tests * Added adform adapter description file * updated tests * Another tests update * Add auctionId * Update adapter for auctionId * add auctionId to adformBidAdapter * Final updates to fit 1.0 version * update docs and integration example * Do not mutate original validBidRequests * use atob and btoa instead of custom made module * Renaming one query string parameter * XDomainRequest.send exception fix (#1942) * Added YIELDONE Bid Adapter for Prebid.js 1.0 (#1900) * Added YIELDONE Bid Adapter for Prebid.js 1.0 * Update yieldoneBidAdapter.md change placementId to 44082 * Changed to get size from bid.sizes * fix sizes array * Add user-facing docs reminder to PR template (#1956) * allow non-mappable sizes to be passed and used in rubicon adapter (#1893) * Typo correction of YIELDONE md file (#1954) * Added YIELDONE Bid Adapter for Prebid.js 1.0 * Update yieldoneBidAdapter.md change placementId to 44082 * Changed to get size from bid.sizes * fix sizes array * Fix a typo * Serverbid bid adapter: update alias config (#1963) * use auctionId instead of requestId (#1968) * Add freewheel ssp bidder adapter for prebid 1.0 (#1793) * add stickyadsTV bidder adapter * init unit test file * ad some unit tests * fix unit test on ad format with parameters * add some unit tests * add unit tests on getBid method * add some test cases in unit tests * minor fix on component id tag. * remove adapters-sticky.json test file * use top most accessible window instead of window.top * Pass in the bid request in the createBid call. * use top most accessible window instead of window.top * add unit tests * update unit tests * fix unit test. * fix CI build * add alias freewheel-ssp * update unit tests on bidderCode value * fix component id values and add unit tests * allws to use any outstream format. * fix ASLoader on futur outstream format versions * minor: fix code format. * update unit tests * minor fix code format * minor: add missing new line at eof * replace StickyAdsTVAdapter by freewheel ssp bd adapter (for prebid 1.0) * remove old stickyadstv unittest spec. * fix server response parsing if sent as object with 'body' field * use the vastXml field for video mediatype * add user sync pixel in freewheel ssp adapter * remove all console log calls (replaced using util helper) * remove useless bidderCode (automatically added by the bidderFactory) * Return the SYNC pixel to be added in the page by Prebid.js * remove instance level properties to enable concurrent bids with the same adapter instance. * fix the request apss through and corresponding unit tests * fix 'freeheelssp' typo * + fixed endpoint request data property names - width to w and height to h (#1955) + updated unit test for the adapter to comply with the property name changes * Added iQM Bid Adapter for Prebid.js 1.0 (#1880) * Added iQM Bid Adapter for Prebid.js 1.0 * Modified URL from http to https * Removed geo function which was fetching user location. * Remove stray console.log (#1975) * Remove duplicate request id and fix empty response from getHighesCpmBids, getAdserverTargeting (#1970) * Removed requestId and added auctionId * Updated module fixtures to use auctionId and not requestId * remove request id from external bid object and fix bug for empty result in public api * use auctionId instead of requestId * fixed lint errors * [Add BidAdapter] rxrtb adapter for Perbid.js 1.0 (#1950) * Add: rxrtb prebidAdapter * Update: params for test * Update: code format * Update: code format * Update: code format * ServerBid Server BidAdapter (#1819) * ServerBid Server BidAdapter Allow S2S configuration with ServerBid. * Updates to meet 1.0 callBids/config changes. * Fix linting issues. * added hb_source to default keys (#1969) * added hb_source * dropped function to add hb_source since it is now default key * fixed lint error * Prebid 1.1.0 Release * Increment pre version * S2s defaults fix in serverbidServerBidAdapter (#1986) * removed s2s defaults * start timestamp was missing on s2s requests * remove hardcoded localhost port for tests (#1988) * Fixes unit tests in browsers other than chrome (#1987) * Fixes unit tests in browsers other than chrome * fixed lint errors * Prebid 1.1.1 Release * Add note about docs needed before merge (#1959) * Add note about docs needed before merge * Update pr_review.md * Update pr_review.md * Update pr_review.md * Adding optional width and height to display parameters (#1998) * adding optional size * no tabs * TrustX adapter update (#1979) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Serverbid Bid Adapter: Add new ad sizes (#1983) * Added dynamic ttl property for One Display and One Mobile. (#2004) * pin gulp-connect at non-broken version (#2008) * pin gulp-connect at non-broken version * updated yarn.lock to specify pinned gulp-connect * Gjirafa Bidder Adapter (#1944) * Added Gjirafa adapter * Add gjirafa adapter unit test * adapter update * New line * Requested changes * change hello_world.html to one bid * change hello_world.html to one bid * Dropping changes in gitignore and hello_world example * hello_world changes * Drop hello_world and gitignore * multiformat size validation checks (#1964) * initial commit for multiformat size validation checks * adding unit tests and changes to checkBidRequestSizes function * updates to appnexusBidAdapter * Upgrade Admixer adapter for Prebid 1.0 (#1755) * Migrating to Prebid 1.0 * Migrating to Prebid 1.0 * Fix spec * Add NasmediaAdmixer adapter for Perbid.js 1.0 (#1937) * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * add NasmediaAdmixer adapter for Perbid.js 1.0 * Added gdpr to adform adapter * Added unit tests * Updated spacing * Update gdprConsent object due to changes in spec * Add gdpr support for PubMaticBidAdapter (#2469) * GDPR support for AOL adapter (#2443) * Added GDPR support for AOL adapter. * Added unit tests for AOL GDPR changes. * Added utils for resolving object type and undefined. * Fixed issues caused by merge. * Made changes in AOL adapter to support gdprApplies flag. * Removed bid floor value from test bid config. * removing iframe example pages * comment updates --- integrationExamples/gpt/gdpr_hello_world.html | 103 ++++++ modules/adformBidAdapter.js | 7 +- modules/aolBidAdapter.js | 335 ++++++++++-------- modules/aolBidAdapter.md | 1 - modules/appnexusBidAdapter.js | 9 + modules/consentManagement.js | 278 +++++++++++++++ modules/pre1api.js | 2 +- modules/prebidServerBidAdapter.js | 35 +- modules/pubmaticBidAdapter.js | 42 ++- src/adaptermanager.js | 16 + src/adapters/bidderFactory.js | 6 +- src/utils.js | 5 + test/spec/modules/adformBidAdapter_spec.js | 9 + test/spec/modules/aolBidAdapter_spec.js | 128 ++++++- test/spec/modules/appnexusBidAdapter_spec.js | 26 +- test/spec/modules/consentManagement_spec.js | 292 +++++++++++++++ .../modules/prebidServerBidAdapter_spec.js | 33 ++ test/spec/modules/pubmaticBidAdapter_spec.js | 63 +++- test/spec/unit/core/adapterManager_spec.js | 260 ++++++++------ test/spec/utils_spec.js | 27 ++ 20 files changed, 1390 insertions(+), 287 deletions(-) create mode 100644 integrationExamples/gpt/gdpr_hello_world.html create mode 100644 modules/consentManagement.js create mode 100644 test/spec/modules/consentManagement_spec.js diff --git a/integrationExamples/gpt/gdpr_hello_world.html b/integrationExamples/gpt/gdpr_hello_world.html new file mode 100644 index 00000000000..9f6194edb16 --- /dev/null +++ b/integrationExamples/gpt/gdpr_hello_world.html @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + +

Prebid.js Test

+
Div-1
+
+ +
+ + \ No newline at end of file diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index 10a4696d755..a84def819c1 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -10,7 +10,7 @@ export const spec = { isBidRequestValid: function (bid) { return !!(bid.params.mid); }, - buildRequests: function (validBidRequests) { + buildRequests: function (validBidRequests, bidderRequest) { var i, l, j, k, bid, _key, _value, reqParams, netRevenue; var request = []; var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ] ]; @@ -38,6 +38,11 @@ export const spec = { request.push('pt=' + netRevenue); request.push('stid=' + validBidRequests[0].auctionId); + if (bidderRequest && bidderRequest.gdprConsent) { + request.push('gdpr=' + bidderRequest.gdprConsent.gdprApplies); + request.push('gdpr_consent=' + bidderRequest.gdprConsent.consentString); + } + for (i = 1, l = globalParams.length; i < l; i++) { _key = globalParams[i][0]; _value = globalParams[i][1]; diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 0fb5aa1a4d3..18d30685c56 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -2,6 +2,7 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; import { EVENTS } from 'src/constants.json'; +import { BANNER } from 'src/mediaTypes'; const AOL_BIDDERS_CODES = { AOL: 'aol', @@ -30,9 +31,9 @@ const SYNC_TYPES = { } }; -const pubapiTemplate = template`//${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'}${'bidfloor'}${'keyValues'};misc=${'misc'}`; +const pubapiTemplate = template`//${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'}${'bidfloor'}${'keyValues'}${'consentData'}`; const nexageBaseApiTemplate = template`//${'host'}/bidRequest?`; -const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'ext'}`; +const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'dynamicParams'}`; const MP_SERVER_MAP = { us: 'adserver-us.adtech.advertising.com', eu: 'adserver-eu.adtech.advertising.com', @@ -46,10 +47,10 @@ $$PREBID_GLOBAL$$.aolGlobals = { pixelsDropped: false }; -let showCpmAdjustmentWarning = (function () { +let showCpmAdjustmentWarning = (function() { let showCpmWarning = true; - return function () { + return function() { let bidderSettings = $$PREBID_GLOBAL$$.bidderSettings; if (showCpmWarning && bidderSettings && bidderSettings.aol && typeof bidderSettings.aol.bidCpmAdjustment === 'function') { @@ -62,28 +63,18 @@ let showCpmAdjustmentWarning = (function () { }; })(); -function isInteger(value) { - return typeof value === 'number' && - isFinite(value) && - Math.floor(value) === value; -} - function template(strings, ...keys) { return function(...values) { 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(''); }; } -function isSecureProtocol() { - return document.location.protocol === 'https:'; -} - function parsePixelItems(pixels) { let itemsRegExp = /(img|iframe)[\s\S]*?src\s*=\s*("|')(.*?)\2/gi; let tagNameRegExp = /\w*(?=\s)/; @@ -110,39 +101,6 @@ function parsePixelItems(pixels) { return pixelsItems; } -function _buildMarketplaceUrl(bid) { - const params = bid.params; - const serverParam = params.server; - let regionParam = params.region || 'us'; - let server; - - if (!MP_SERVER_MAP.hasOwnProperty(regionParam)) { - utils.logWarn(`Unknown region '${regionParam}' for AOL bidder.`); - regionParam = 'us'; // Default region. - } - - if (serverParam) { - server = serverParam; - } else { - server = MP_SERVER_MAP[regionParam]; - } - - // Set region param, used by AOL analytics. - params.region = regionParam; - - return pubapiTemplate({ - host: server, - network: params.network, - placement: parseInt(params.placement), - pageid: params.pageId || 0, - sizeid: params.sizeId || 0, - alias: params.alias || utils.getUniqueIdentifierStr(), - bidfloor: formatMarketplaceBidFloor(params.bidFloor), - keyValues: formatMarketplaceKeyValues(params.keyValues), - misc: new Date().getTime() // cache busting - }); -} - function formatMarketplaceBidFloor(bidFloor) { return (typeof bidFloor !== 'undefined') ? `;bidfloor=${bidFloor.toString()}` : ''; } @@ -157,39 +115,16 @@ function formatMarketplaceKeyValues(keyValues) { return formattedKeyValues; } -function _buildOneMobileBaseUrl(bid) { - return nexageBaseApiTemplate({ - host: bid.params.host || NEXAGE_SERVER - }); -} - -function _buildOneMobileGetUrl(bid) { - let {dcn, pos} = bid.params; - let nexageApi = _buildOneMobileBaseUrl(bid); - if (dcn && pos) { - let ext = ''; - if (isSecureProtocol()) { - bid.params.ext = bid.params.ext || {}; - bid.params.ext.secure = 1; - } - utils._each(bid.params.ext, (value, key) => { - ext += `&${key}=${encodeURIComponent(value)}`; - }); - nexageApi += nexageGetApiTemplate({dcn, pos, ext}); - } - return nexageApi; -} - function _isMarketplaceBidder(bidder) { return bidder === AOL_BIDDERS_CODES.AOL || bidder === AOL_BIDDERS_CODES.ONEDISPLAY; } -function _isNexageBidder(bidder) { - return bidder === AOL_BIDDERS_CODES.AOL || bidder === AOL_BIDDERS_CODES.ONEMOBILE; +function _isOneMobileBidder(bidderCode) { + return bidderCode === AOL_BIDDERS_CODES.AOL || bidderCode === AOL_BIDDERS_CODES.ONEMOBILE; } function _isNexageRequestPost(bid) { - if (_isNexageBidder(bid.bidder) && bid.params.id && bid.params.imp && bid.params.imp[0]) { + if (_isOneMobileBidder(bid.bidder) && bid.params.id && bid.params.imp && bid.params.imp[0]) { let imp = bid.params.imp[0]; return imp.id && imp.tagid && ((imp.banner && imp.banner.w && imp.banner.h) || @@ -198,7 +133,7 @@ function _isNexageRequestPost(bid) { } function _isNexageRequestGet(bid) { - return _isNexageBidder(bid.bidder) && bid.params.dcn && bid.params.pos; + return _isOneMobileBidder(bid.bidder) && bid.params.dcn && bid.params.pos; } function isMarketplaceBid(bid) { @@ -219,65 +154,25 @@ function resolveEndpointCode(bid) { } } -function formatBidRequest(endpointCode, bid) { - let bidRequest; - - switch (endpointCode) { - case AOL_ENDPOINTS.DISPLAY.GET: - bidRequest = { - url: _buildMarketplaceUrl(bid), - method: 'GET', - ttl: ONE_DISPLAY_TTL - }; - break; - - case AOL_ENDPOINTS.MOBILE.GET: - bidRequest = { - url: _buildOneMobileGetUrl(bid), - method: 'GET', - ttl: ONE_MOBILE_TTL - }; - break; - - case AOL_ENDPOINTS.MOBILE.POST: - bidRequest = { - url: _buildOneMobileBaseUrl(bid), - method: 'POST', - ttl: ONE_MOBILE_TTL, - data: bid.params, - options: { - contentType: 'application/json', - customHeaders: { - 'x-openrtb-version': '2.2' - } - } - }; - break; - } - - bidRequest.bidderCode = bid.bidder; - bidRequest.bidId = bid.bidId; - bidRequest.userSyncOn = bid.params.userSyncOn; - - return bidRequest; -} - export const spec = { code: AOL_BIDDERS_CODES.AOL, aliases: [AOL_BIDDERS_CODES.ONEMOBILE, AOL_BIDDERS_CODES.ONEDISPLAY], - isBidRequestValid: function(bid) { + supportedMediaTypes: [BANNER], + isBidRequestValid(bid) { return isMarketplaceBid(bid) || isMobileBid(bid); }, - buildRequests: function (bids) { + buildRequests(bids, bidderRequest) { + let consentData = bidderRequest ? bidderRequest.gdprConsent : null; + return bids.map(bid => { const endpointCode = resolveEndpointCode(bid); if (endpointCode) { - return formatBidRequest(endpointCode, bid); + return this.formatBidRequest(endpointCode, bid, consentData); } }); }, - interpretResponse: function ({body}, bidRequest) { + interpretResponse({body}, bidRequest) { showCpmAdjustmentWarning(); if (!body) { @@ -290,17 +185,157 @@ export const spec = { } } }, - _formatPixels: function (pixels) { - let formattedPixels = pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, ''); + getUserSyncs(options, bidResponses) { + let bidResponse = bidResponses[0]; - return ''; + if (config.getConfig('aol.userSyncOn') === EVENTS.BID_RESPONSE) { + if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse && bidResponse.ext && bidResponse.ext.pixels) { + $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; + + return parsePixelItems(bidResponse.ext.pixels); + } + } + + return []; + }, + + formatBidRequest(endpointCode, bid, consentData) { + let bidRequest; + + switch (endpointCode) { + case AOL_ENDPOINTS.DISPLAY.GET: + bidRequest = { + url: this.buildMarketplaceUrl(bid, consentData), + method: 'GET', + ttl: ONE_DISPLAY_TTL + }; + break; + + case AOL_ENDPOINTS.MOBILE.GET: + bidRequest = { + url: this.buildOneMobileGetUrl(bid, consentData), + method: 'GET', + ttl: ONE_MOBILE_TTL + }; + break; + + case AOL_ENDPOINTS.MOBILE.POST: + bidRequest = { + url: this.buildOneMobileBaseUrl(bid), + method: 'POST', + ttl: ONE_MOBILE_TTL, + data: this.buildOpenRtbRequestData(bid, consentData), + options: { + contentType: 'application/json', + customHeaders: { + 'x-openrtb-version': '2.2' + } + } + }; + break; + } + + bidRequest.bidderCode = bid.bidder; + bidRequest.bidId = bid.bidId; + bidRequest.userSyncOn = bid.params.userSyncOn; + + return bidRequest; }, - _parseBidResponse: function (response, bidRequest) { + buildMarketplaceUrl(bid, consentData) { + const params = bid.params; + const serverParam = params.server; + let regionParam = params.region || 'us'; + let server; + + if (!MP_SERVER_MAP.hasOwnProperty(regionParam)) { + utils.logWarn(`Unknown region '${regionParam}' for AOL bidder.`); + regionParam = 'us'; // Default region. + } + + if (serverParam) { + server = serverParam; + } else { + server = MP_SERVER_MAP[regionParam]; + } + + // Set region param, used by AOL analytics. + params.region = regionParam; + + return pubapiTemplate({ + host: server, + network: params.network, + placement: parseInt(params.placement), + pageid: params.pageId || 0, + sizeid: params.sizeId || 0, + alias: params.alias || utils.getUniqueIdentifierStr(), + misc: new Date().getTime(), // cache busting, + bidfloor: formatMarketplaceBidFloor(params.bidFloor), + keyValues: formatMarketplaceKeyValues(params.keyValues), + consentData: this.formatMarketplaceConsentData(consentData) + }); + }, + buildOneMobileGetUrl(bid, consentData) { + let {dcn, pos, ext} = bid.params; + let nexageApi = this.buildOneMobileBaseUrl(bid); + if (dcn && pos) { + let dynamicParams = this.formatOneMobileDynamicParams(ext, consentData); + nexageApi += nexageGetApiTemplate({dcn, pos, dynamicParams}); + } + return nexageApi; + }, + buildOneMobileBaseUrl(bid) { + return nexageBaseApiTemplate({ + host: bid.params.host || NEXAGE_SERVER + }); + }, + formatOneMobileDynamicParams(params = {}, consentData) { + if (this.isSecureProtocol()) { + params.secure = 1; + } + + if (this.isConsentRequired(consentData)) { + params.euconsent = consentData.consentString; + params.gdpr = 1; + } + + let paramsFormatted = ''; + utils._each(params, (value, key) => { + paramsFormatted += `&${key}=${encodeURIComponent(value)}`; + }); + + return paramsFormatted; + }, + buildOpenRtbRequestData(bid, consentData) { + let openRtbObject = { + id: bid.params.id, + imp: bid.params.imp + }; + + if (this.isConsentRequired(consentData)) { + openRtbObject.user = { + ext: { + consent: consentData.consentString + } + }; + openRtbObject.regs = { + ext: { + gdpr: 1 + } + }; + } + + return openRtbObject; + }, + isConsentRequired(consentData) { + return !!(consentData && consentData.consentString && consentData.gdprApplies); + }, + formatMarketplaceConsentData(consentData) { + let consentRequired = this.isConsentRequired(consentData); + + return consentRequired ? `;euconsent=${consentData.consentString};gdpr=1` : ''; + }, + + _parseBidResponse(response, bidRequest) { let bidData; try { @@ -322,17 +357,10 @@ export const spec = { } } - let ad = bidData.adm; - if (response.ext && response.ext.pixels) { - if (config.getConfig('aol.userSyncOn') !== EVENTS.BID_RESPONSE) { - ad += this._formatPixels(response.ext.pixels); - } - } - - return { + let bidResponse = { bidderCode: bidRequest.bidderCode, requestId: bidRequest.bidId, - ad: ad, + ad: bidData.adm, cpm: cpm, width: bidData.w, height: bidData.h, @@ -343,19 +371,28 @@ export const spec = { netRevenue: true, ttl: bidRequest.ttl }; - }, - getUserSyncs: function(options, bidResponses) { - let bidResponse = bidResponses[0]; - if (config.getConfig('aol.userSyncOn') === EVENTS.BID_RESPONSE) { - if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse.ext && bidResponse.ext.pixels) { - $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; - - return parsePixelItems(bidResponse.ext.pixels); + if (response.ext && response.ext.pixels) { + if (config.getConfig('aol.userSyncOn') !== EVENTS.BID_RESPONSE) { + bidResponse.ad += this.formatPixels(response.ext.pixels); } } - return []; + return bidResponse; + }, + formatPixels(pixels) { + let formattedPixels = pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, ''); + + return ''; + }, + isOneMobileBidder: _isOneMobileBidder, + isSecureProtocol() { + return document.location.protocol === 'https:'; } }; diff --git a/modules/aolBidAdapter.md b/modules/aolBidAdapter.md index a92e933bd36..8a9d1e3291d 100644 --- a/modules/aolBidAdapter.md +++ b/modules/aolBidAdapter.md @@ -22,7 +22,6 @@ Module that connects to AOL's demand sources params: { placement: '3611253', network: '9599.1', - bidFloor: '0.80', keyValues: { test: 'key' } diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 75e48d1ee0b..82743974994 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -73,6 +73,15 @@ export const spec = { if (member > 0) { payload.member_id = member; } + + 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 + }; + } + const payloadString = JSON.stringify(payload); return { method: 'POST', diff --git a/modules/consentManagement.js b/modules/consentManagement.js new file mode 100644 index 00000000000..c7b6ac4df92 --- /dev/null +++ b/modules/consentManagement.js @@ -0,0 +1,278 @@ +/** + * This module adds GDPR consentManagement support to prebid.js. It interacts with + * supported CMPs (Consent Management Platforms) to grab the user's consent information + * and make it available for any GDPR supported adapters to read/pass this information to + * their system. + */ +import * as utils from 'src/utils'; +import { config } from 'src/config'; +import { gdprDataHandler } from 'src/adaptermanager'; +import includes from 'core-js/library/fn/array/includes'; + +const DEFAULT_CMP = 'iab'; +const DEFAULT_CONSENT_TIMEOUT = 10000; +const DEFAULT_ALLOW_AUCTION_WO_CONSENT = true; + +export let userCMP; +export let consentTimeout; +export let allowAuction; + +let consentData; + +let context; +let args; +let nextFn; + +let timer; +let haveExited; + +// add new CMPs here, with their dedicated lookup function +const cmpCallMap = { + 'iab': lookupIabConsent +}; + +/** + * This function handles interacting with an IAB compliant CMP to obtain the consentObject value 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(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) + */ +function lookupIabConsent(cmpSuccess, cmpError) { + let cmpCallbacks; + + // check if the CMP is located on the same window level as the prebid code. + // if it's found, directly call the CMP via it's API and call the cmpSuccess callback. + // if it's not found, assume the prebid code may be inside an iframe and the CMP code is located in a higher parent window. + // in this case, use the IAB's iframe locator sample code (which is slightly cutomized) to try to find the CMP and use postMessage() to communicate with the CMP. + if (utils.isFn(window.__cmp)) { + window.__cmp('getVendorConsents', null, cmpSuccess); + } else { + callCmpWhileInIframe(); + } + + function callCmpWhileInIframe() { + /** + * START OF STOCK CODE FROM IAB 1.1 CMP SPEC + */ + + // find the CMP frame + let f = window; + let cmpFrame; + while (!cmpFrame) { + try { + if (f.frames['__cmpLocator']) cmpFrame = f; + } catch (e) {} + if (f === window.top) break; + f = f.parent; + } + + cmpCallbacks = {}; + + /* Setup up a __cmp function to do the postMessage and stash the callback. + This function behaves (from the caller's perspective identicially to the in-frame __cmp call */ + window.__cmp = function(cmd, arg, callback) { + if (!cmpFrame) { + removePostMessageListener(); + + let errmsg = 'CMP not found'; + // small customization to properly return error + return cmpError(errmsg); + } + let callId = Math.random() + ''; + let msg = {__cmpCall: { + command: cmd, + parameter: arg, + callId: callId + }}; + cmpCallbacks[callId] = callback; + cmpFrame.postMessage(msg, '*'); + } + + /** when we get the return message, call the stashed callback */ + // small customization to remove this eventListener later in module + window.addEventListener('message', readPostMessageResponse, false); + + /** + * END OF STOCK CODE FROM IAB 1.1 CMP SPEC + */ + + // call CMP + window.__cmp('getVendorConsents', null, cmpIframeCallback); + } + + function readPostMessageResponse(event) { + // small customization to prevent reading strings from other sources that aren't JSON.stringified + let json = (typeof event.data === 'string' && includes(event.data, 'cmpReturn')) ? JSON.parse(event.data) : event.data; + if (json.__cmpReturn) { + let i = json.__cmpReturn; + cmpCallbacks[i.callId](i.returnValue, i.success); + delete cmpCallbacks[i.callId]; + } + } + + function removePostMessageListener() { + window.removeEventListener('message', readPostMessageResponse, false); + } + + function cmpIframeCallback(consentObject) { + removePostMessageListener(); + cmpSuccess(consentObject); + } +} + +/** + * 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 + * data as part of a gdprConsent object which gets transferred to adaptermanager's gdprDataHandler object. + * This information is later added into the bidRequest object for any supported adapters to read/pass along to their system. + * @param {object} config 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(config, fn) { + context = this; + args = arguments; + nextFn = fn; + haveExited = false; + + // in case we already have consent (eg during bid refresh) + if (consentData) { + return exitModule(); + } + + if (!includes(Object.keys(cmpCallMap), userCMP)) { + utils.logWarn(`CMP framework (${userCMP}) is not a supported framework. Aborting consentManagement module and resuming auction.`); + return nextFn.apply(context, args); + } + + cmpCallMap[userCMP].call(this, processCmpData, cmpFailed); + + // only let this code run if module is still active (ie if the callbacks used by CMPs haven't already finished) + if (!haveExited) { + if (consentTimeout === 0) { + processCmpData(undefined); + } else { + timer = setTimeout(cmpTimedOut, consentTimeout); + } + } +} + +/** + * This function checks the consent data provided by CMP 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 CMP that contains user's consent choices + */ +function processCmpData(consentObject) { + if (!utils.isPlainObject(consentObject) || !utils.isStr(consentObject.metadata) || consentObject.metadata === '') { + cmpFailed(`CMP returned unexpected value during lookup process; returned value was (${consentObject}).`); + } else { + clearTimeout(timer); + storeConsentData(consentObject); + + exitModule(); + } +} + +/** + * General timeout callback when interacting with CMP takes too long. + */ +function cmpTimedOut() { + cmpFailed('CMP workflow exceeded timeout threshold.'); +} + +/** + * 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. +*/ +function cmpFailed(errMsg) { + clearTimeout(timer); + + // still set the consentData to undefined when there is a problem as per config options + if (allowAuction) { + storeConsentData(undefined); + } + exitModule(errMsg); +} + +/** + * Stores CMP data locally in module and then invokes gdprDataHandler.setConsentData() to make information available in adaptermanger.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) { + consentData = { + consentString: (cmpConsentObject) ? cmpConsentObject.metadata : undefined, + vendorData: cmpConsentObject, + gdprApplies: (cmpConsentObject) ? cmpConsentObject.gdprApplies : undefined + }; + gdprDataHandler.setConsentData(consentData); +} + +/** + * This function handles the exit logic for the module. + * There are several paths in the module's logic to call this function and 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. + */ +function exitModule(errMsg) { + if (haveExited === false) { + haveExited = true; + + if (errMsg) { + if (allowAuction) { + utils.logWarn(errMsg + ' Resuming auction without consent data as per consentManagement config.'); + nextFn.apply(context, args); + } else { + utils.logError(errMsg + ' Canceling auction as per consentManagement config.'); + } + } else { + nextFn.apply(context, args); + } + } +} + +/** + * Simply resets the module's consentData variable back to undefined, mainly for testing purposes + */ +export function resetConsentData() { + consentData = undefined; +} + +/** + * A configuration function that initializes some module variables, as well as add a hook into the requestBids function + * @param {object} config required; consentManagement module config settings; cmp (string), timeout (int), allowAuctionWithoutConsent (boolean) + */ +export function setConfig(config) { + if (utils.isStr(config.cmpApi)) { + userCMP = config.cmpApi; + } else { + userCMP = DEFAULT_CMP; + utils.logInfo(`consentManagement config did not specify cmp. Using system default setting (${DEFAULT_CMP}).`); + } + + if (utils.isNumber(config.timeout)) { + consentTimeout = config.timeout; + } else { + consentTimeout = DEFAULT_CONSENT_TIMEOUT; + utils.logInfo(`consentManagement config did not specify timeout. Using system default setting (${DEFAULT_CONSENT_TIMEOUT}).`); + } + + if (typeof config.allowAuctionWithoutConsent === 'boolean') { + allowAuction = config.allowAuctionWithoutConsent; + } else { + allowAuction = DEFAULT_ALLOW_AUCTION_WO_CONSENT; + utils.logInfo(`consentManagement config did not specify allowAuctionWithoutConsent. Using system default setting (${DEFAULT_ALLOW_AUCTION_WO_CONSENT}).`); + } + + $$PREBID_GLOBAL$$.requestBids.addHook(requestBidsHook, 50); +} +config.getConfig('consentManagement', config => setConfig(config.consentManagement)); diff --git a/modules/pre1api.js b/modules/pre1api.js index 707d10fbfd8..a8aa1f31e70 100644 --- a/modules/pre1api.js +++ b/modules/pre1api.js @@ -124,7 +124,7 @@ pbjs.requestBids.addHook((config, next = config) => { } else { logWarn(`${MODULE_NAME} module: concurrency has been disabled and "$$PREBID_GLOBAL$$.requestBids" call was queued`); } -}, 100); +}, 5); Object.keys(auctionPropMap).forEach(prop => { if (prop === 'allBidsAvailable') { diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 22529def0a9..f499f5a0ae4 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -304,7 +304,7 @@ function transformHeightWidth(adUnit) { */ const LEGACY_PROTOCOL = { - buildRequest(s2sBidRequest, adUnits) { + buildRequest(s2sBidRequest, bidRequests, adUnits) { // pbs expects an ad_unit.video attribute if the imp is video adUnits.forEach(adUnit => { adUnit.sizes = transformHeightWidth(adUnit); @@ -437,7 +437,7 @@ const OPEN_RTB_PROTOCOL = { bidMap: {}, - buildRequest(s2sBidRequest, adUnits) { + buildRequest(s2sBidRequest, bidRequests, adUnits) { let imps = []; let aliases = {}; @@ -530,6 +530,35 @@ const OPEN_RTB_PROTOCOL = { request.ext = { prebid: { aliases } }; } + if (bidRequests && bidRequests[0].gdprConsent) { + // note - gdprApplies & consentString may be undefined in certain use-cases for consentManagement module + let gdprApplies; + if (typeof bidRequests[0].gdprConsent.gdprApplies === 'boolean') { + gdprApplies = bidRequests[0].gdprConsent.gdprApplies ? 1 : 0; + } + + if (request.regs) { + if (request.regs.ext) { + request.regs.ext.gdpr = gdprApplies; + } else { + request.regs.ext = { gdpr: gdprApplies }; + } + } else { + request.regs = { ext: { gdpr: gdprApplies } }; + } + + let consentString = bidRequests[0].gdprConsent.consentString; + if (request.user) { + if (request.user.ext) { + request.user.ext.consent = consentString; + } else { + request.user.ext = { consent: consentString }; + } + } else { + request.user = { ext: { consent: consentString } }; + } + } + return request; }, @@ -637,7 +666,7 @@ export function PrebidServer() { .reduce(utils.flatten) .filter(utils.uniques); - const request = protocolAdapter().buildRequest(s2sBidRequest, adUnitsWithSizes); + const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, adUnitsWithSizes); const requestJson = JSON.stringify(request); ajax( diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index dfcde047580..1f056bf0eff 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -19,6 +19,11 @@ const CUSTOM_PARAMS = { 'verId': '' // OpenWrap Legacy: version ID }; const NET_REVENUE = false; +const dealChannelValues = { + 1: 'PMP', + 5: 'PREF', + 6: 'PMPG' +}; let publisherId = 0; @@ -195,7 +200,7 @@ export const spec = { * @param {validBidRequests[]} - an array of bids * @return ServerRequest Info describing the request to the server. */ - buildRequests: validBidRequests => { + buildRequests: (validBidRequests, bidderRequest) => { var conf = _initConf(); var payload = _createOrtbTemplate(conf); validBidRequests.forEach(bid => { @@ -217,14 +222,28 @@ export const spec = { payload.site.publisher.id = conf.pubId.trim(); publisherId = conf.pubId.trim(); payload.ext.wrapper = {}; - payload.ext.wrapper.profile = conf.profId || UNDEFINED; - payload.ext.wrapper.version = conf.verId || UNDEFINED; + payload.ext.wrapper.profile = parseInt(conf.profId) || UNDEFINED; + payload.ext.wrapper.version = parseInt(conf.verId) || UNDEFINED; payload.ext.wrapper.wiid = conf.wiid || UNDEFINED; payload.ext.wrapper.wv = constants.REPO_AND_VERSION; payload.ext.wrapper.transactionId = conf.transactionId; payload.ext.wrapper.wp = 'pbjs'; payload.user.gender = (conf.gender ? conf.gender.trim() : UNDEFINED); payload.user.geo = {}; + + // Attaching GDPR Consent Params + if (bidderRequest && bidderRequest.gdprConsent) { + payload.user.ext = { + consent: bidderRequest.gdprConsent.consentString + }; + + payload.regs = { + ext: { + gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) + } + }; + } + payload.user.geo.lat = _parseSlotParam('lat', conf.lat); payload.user.geo.lon = _parseSlotParam('lon', conf.lon); payload.user.yob = _parseSlotParam('yob', conf.yob); @@ -264,6 +283,11 @@ export const spec = { referrer: utils.getTopWindowUrl(), ad: bid.adm }; + + if (bid.ext && bid.ext.deal_channel) { + newBid['dealChannel'] = dealChannelValues[bid.ext.deal_channel] || null; + } + bidResponses.push(newBid); }); } @@ -276,11 +300,19 @@ export const spec = { /** * Register User Sync. */ - getUserSyncs: syncOptions => { + getUserSyncs: (syncOptions, responses, gdprConsent) => { + let syncurl = USYNCURL + publisherId; + + // Attaching GDPR Consent Params in UserSync url + if (gdprConsent) { + syncurl += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); + syncurl += '&consent=' + encodeURIComponent(gdprConsent.consentString || ''); + } + if (syncOptions.iframeEnabled) { return [{ type: 'iframe', - url: USYNCURL + publisherId + url: syncurl }]; } else { utils.logWarn('PubMatic: Please enable iframe based user sync.'); diff --git a/src/adaptermanager.js b/src/adaptermanager.js index cef1635f100..98d9d5fb426 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -133,6 +133,16 @@ function getAdUnitCopyForClientAdapters(adUnits) { return adUnitsClientCopy; } +exports.gdprDataHandler = { + consentData: null, + setConsentData: function(consentInfo) { + this.consentData = consentInfo; + }, + getConsentData: function() { + return this.consentData; + } +}; + exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, labels) { let bidRequests = []; @@ -197,6 +207,12 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, bidRequests.push(bidderRequest); } }); + + if (exports.gdprDataHandler.getConsentData()) { + bidRequests.forEach(bidRequest => { + bidRequest['gdprConsent'] = exports.gdprDataHandler.getConsentData(); + }); + } return bidRequests; }; diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 7540a3a3398..958173a0965 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -191,7 +191,7 @@ export function newBidder(spec) { // As soon as that is refactored, we can move this emit event where it should be, within the done function. events.emit(CONSTANTS.EVENTS.BIDDER_DONE, bidderRequest); - registerSyncs(responses); + registerSyncs(responses, bidderRequest.gdprConsent); } const validBidRequests = bidderRequest.bids.filter(filterAndWarn); @@ -327,12 +327,12 @@ export function newBidder(spec) { } }); - function registerSyncs(responses) { + function registerSyncs(responses, gdprConsent) { if (spec.getUserSyncs) { let syncs = spec.getUserSyncs({ iframeEnabled: config.getConfig('userSync.iframeEnabled'), pixelEnabled: config.getConfig('userSync.pixelEnabled'), - }, responses); + }, responses, gdprConsent); if (syncs) { if (!Array.isArray(syncs)) { syncs = [syncs]; diff --git a/src/utils.js b/src/utils.js index 5b8508e52e4..169c578a356 100644 --- a/src/utils.js +++ b/src/utils.js @@ -11,6 +11,7 @@ var t_Arr = 'Array'; var t_Str = 'String'; var t_Fn = 'Function'; var t_Numb = 'Number'; +var t_Object = 'Object'; var toString = Object.prototype.toString; let infoLogger = null; try { @@ -382,6 +383,10 @@ exports.isNumber = function(object) { return this.isA(object, t_Numb); }; +exports.isPlainObject = function(object) { + return this.isA(object, t_Object); +} + /** * Return if the object is "empty"; * this includes falsey, no keys, or no items at indices diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index d631234d6d5..21ff84bdad5 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -99,6 +99,15 @@ describe('Adform adapter', () => { assert.deepEqual(resultBids, bids[0]); }); + it('should send GDPR Consent data to adform', () => { + var resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: 1, consentString: 'concentDataString'}}); + let parsedUrl = parseUrl(request.url).query; + + assert.equal(parsedUrl.gdpr, 1); + assert.equal(parsedUrl.gdpr_consent, 'concentDataString'); + }); + it('should set gross to the request, if there is any gross priceType', () => { let request = spec.buildRequests([bids[5], bids[5]]); let parsedUrl = parseUrl(request.url); diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index 38b36bbaf3d..d69b9e6e3d8 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -98,6 +98,7 @@ describe('AolAdapter', () => { let bidRequest; let logWarnSpy; let formatPixelsStub; + let isOneMobileBidderStub; beforeEach(() => { bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; @@ -110,13 +111,15 @@ describe('AolAdapter', () => { body: getDefaultBidResponse() }; logWarnSpy = sinon.spy(utils, 'logWarn'); - formatPixelsStub = sinon.stub(spec, '_formatPixels'); + formatPixelsStub = sinon.stub(spec, 'formatPixels'); + isOneMobileBidderStub = sinon.stub(spec, 'isOneMobileBidder'); }); afterEach(() => { $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; logWarnSpy.restore(); formatPixelsStub.restore(); + isOneMobileBidderStub.restore(); }); it('should return formatted bid response with required properties', () => { @@ -534,10 +537,10 @@ describe('AolAdapter', () => { }); }); - describe('_formatPixels()', () => { + describe('formatPixels()', () => { it('should return pixels wrapped for dropping them once and within nested frames ', () => { let pixels = ''; - let formattedPixels = spec._formatPixels(pixels); + let formattedPixels = spec.formatPixels(pixels); expect(formattedPixels).to.equal( ''); }); - }) + }); + + describe('isOneMobileBidder()', () => { + it('should return false when when bidderCode is not present', () => { + expect(spec.isOneMobileBidder(null)).to.be.false; + }); + + it('should return false for unknown bidder code', () => { + expect(spec.isOneMobileBidder('unknownBidder')).to.be.false; + }); + + it('should return true for aol bidder code', () => { + expect(spec.isOneMobileBidder('aol')).to.be.true; + }); + + it('should return true for one mobile bidder code', () => { + expect(spec.isOneMobileBidder('onemobile')).to.be.true; + }); + }); + + describe('isConsentRequired()', () => { + it('should return false when consentData object is not present', () => { + expect(spec.isConsentRequired(null)).to.be.false; + }); + + it('should return false when gdprApplies equals true and consentString is not present', () => { + let consentData = { + consentString: null, + gdprApplies: true + }; + + expect(spec.isConsentRequired(consentData)).to.be.false; + }); + + it('should return false when consentString is present and gdprApplies equals false', () => { + let consentData = { + consentString: 'consent-string', + gdprApplies: false + }; + + expect(spec.isConsentRequired(consentData)).to.be.false; + }); + + it('should return true when consentString is present and gdprApplies equals true', () => { + let consentData = { + consentString: 'consent-string', + gdprApplies: true + }; + + expect(spec.isConsentRequired(consentData)).to.be.true; + }); + }); + + describe('formatMarketplaceConsentData()', () => { + let consentRequiredStub; + + beforeEach(() => { + consentRequiredStub = sinon.stub(spec, 'isConsentRequired'); + }); + + afterEach(() => { + consentRequiredStub.restore(); + }); + + it('should return empty string when consent is not required', () => { + consentRequiredStub.returns(false); + expect(spec.formatMarketplaceConsentData()).to.be.equal(''); + }); + + it('should return formatted consent data when consent is required', () => { + consentRequiredStub.returns(true); + let formattedConsentData = spec.formatMarketplaceConsentData({ + consentString: 'test-consent' + }); + expect(formattedConsentData).to.be.equal(';euconsent=test-consent;gdpr=1'); + }); + }); + + describe('formatOneMobileDynamicParams()', () => { + let consentRequiredStub; + let secureProtocolStub; + + beforeEach(() => { + consentRequiredStub = sinon.stub(spec, 'isConsentRequired'); + secureProtocolStub = sinon.stub(spec, 'isSecureProtocol'); + }); + + afterEach(() => { + consentRequiredStub.restore(); + secureProtocolStub.restore(); + }); + + it('should return empty string when params are not present', () => { + expect(spec.formatOneMobileDynamicParams()).to.be.equal(''); + }); + + it('should return formatted params when params are present', () => { + let params = { + param1: 'val1', + param2: 'val2', + param3: 'val3' + }; + expect(spec.formatOneMobileDynamicParams(params)).to.contain('¶m1=val1¶m2=val2¶m3=val3'); + }); + + it('should return formatted gdpr params when isConsentRequired returns true', () => { + let consentData = { + consentString: 'test-consent' + }; + consentRequiredStub.returns(true); + expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&euconsent=test-consent&gdpr=1'); + }); + + it('should return formatted secure param when isSecureProtocol returns true', () => { + secureProtocolStub.returns(true); + expect(spec.formatOneMobileDynamicParams()).to.be.equal('&secure=1'); + }); + }); }); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 1ba4edfa4ea..53fbf390a6e 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -173,7 +173,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should attache native params to the request', () => { + it('should attach native params to the request', () => { let bidRequest = Object.assign({}, bidRequests[0], { @@ -290,7 +290,7 @@ describe('AppNexusAdapter', () => { }]); }); - it('should should add payment rules to the request', () => { + it('should add payment rules to the request', () => { let bidRequest = Object.assign({}, bidRequests[0], { @@ -306,6 +306,28 @@ describe('AppNexusAdapter', () => { expect(payload.tags[0].use_pmt_rule).to.equal(true); }); + + it('should add gdpr consent information to the request', () => { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'appnexus', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + bidderRequest.bids = bidRequests; + + const request = spec.buildRequests(bidRequests, bidderRequest); + 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; + }); }) describe('interpretResponse', () => { diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js new file mode 100644 index 00000000000..5974ac79324 --- /dev/null +++ b/test/spec/modules/consentManagement_spec.js @@ -0,0 +1,292 @@ +import {setConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, allowAuction} from 'modules/consentManagement'; +import {gdprDataHandler} from 'src/adaptermanager'; +import * as utils from 'src/utils'; +import { config } from 'src/config'; + +let assert = require('chai').assert; +let expect = require('chai').expect; + +describe('consentManagement', function () { + describe('setConfig tests:', () => { + describe('empty setConfig value', () => { + beforeEach(() => { + sinon.stub(utils, 'logInfo'); + }); + + afterEach(() => { + utils.logInfo.restore(); + config.resetConfig(); + }); + + it('should use system default values', () => { + setConfig({}); + expect(userCMP).to.be.equal('iab'); + expect(consentTimeout).to.be.equal(10000); + expect(allowAuction).to.be.true; + sinon.assert.callCount(utils.logInfo, 3); + }); + }); + + describe('valid setConfig value', () => { + afterEach(() => { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + }); + it('results in all user settings overriding system defaults', () => { + let allConfig = { + cmpApi: 'iab', + timeout: 7500, + allowAuctionWithoutConsent: false + }; + + setConfig(allConfig); + expect(userCMP).to.be.equal('iab'); + expect(consentTimeout).to.be.equal(7500); + expect(allowAuction).to.be.false; + }); + }); + }); + + describe('requestBidsHook tests:', () => { + let goodConfigWithCancelAuction = { + cmpApi: 'iab', + timeout: 7500, + allowAuctionWithoutConsent: false + }; + + let goodConfigWithAllowAuction = { + cmpApi: 'iab', + timeout: 7500, + allowAuctionWithoutConsent: true + }; + + let didHookReturn; + + afterEach(() => { + gdprDataHandler.consentData = null; + resetConsentData(); + }); + + describe('error checks:', () => { + describe('unknown CMP framework ID:', () => { + beforeEach(() => { + sinon.stub(utils, 'logWarn'); + }); + + afterEach(() => { + utils.logWarn.restore(); + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + gdprDataHandler.consentData = null; + }); + + it('should return Warning message and return to hooked function', () => { + let badCMPConfig = { + cmpApi: 'bad' + }; + setConfig(badCMPConfig); + expect(userCMP).to.be.equal(badCMPConfig.cmpApi); + + didHookReturn = false; + + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + sinon.assert.calledOnce(utils.logWarn); + expect(didHookReturn).to.be.true; + expect(consent).to.be.null; + }); + }); + }); + + describe('already known consentData:', () => { + let cmpStub = sinon.stub(); + + beforeEach(() => { + didHookReturn = false; + window.__cmp = function() {}; + }); + + afterEach(() => { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + cmpStub.restore(); + delete window.__cmp; + gdprDataHandler.consentData = null; + }); + + it('should bypass CMP and simply use previously stored consentData', () => { + let testConsentData = { + gdprApplies: true, + metadata: 'xyz' + }; + + cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { + args[2](testConsentData); + }); + setConfig(goodConfigWithAllowAuction); + requestBidsHook({}, () => {}); + cmpStub.restore(); + + // reset the stub to ensure it wasn't called during the second round of calls + cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { + args[2](testConsentData); + }); + + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + + expect(didHookReturn).to.be.true; + expect(consent.consentString).to.equal(testConsentData.metadata); + expect(consent.gdprApplies).to.be.true; + sinon.assert.notCalled(cmpStub); + }); + }); + + describe('CMP workflow for iframed page', () => { + let eventStub = sinon.stub(); + let cmpStub = sinon.stub(); + + beforeEach(() => { + didHookReturn = false; + resetConsentData(); + window.__cmp = function() {}; + sinon.stub(utils, 'logError'); + sinon.stub(utils, 'logWarn'); + }); + + afterEach(() => { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + eventStub.restore(); + cmpStub.restore(); + delete window.__cmp; + utils.logError.restore(); + utils.logWarn.restore(); + gdprDataHandler.consentData = null; + }); + + it('should return the consent string from a postmessage + addEventListener response', () => { + let testConsentData = { + data: { + __cmpReturn: { + returnValue: { + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + } + } + } + }; + eventStub = sinon.stub(window, 'addEventListener').callsFake((...args) => { + args[1](testConsentData); + }); + cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { + args[2]({ + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + }); + }); + + setConfig(goodConfigWithAllowAuction); + + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + + sinon.assert.notCalled(utils.logWarn); + sinon.assert.notCalled(utils.logError); + expect(didHookReturn).to.be.true; + expect(consent.consentString).to.equal('BOJy+UqOJy+UqABAB+AAAAAZ+A=='); + expect(consent.gdprApplies).to.be.true; + }); + }); + + describe('CMP workflow for normal pages:', () => { + let cmpStub = sinon.stub(); + + beforeEach(() => { + didHookReturn = false; + resetConsentData(); + sinon.stub(utils, 'logError'); + sinon.stub(utils, 'logWarn'); + window.__cmp = function() {}; + }); + + afterEach(() => { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + cmpStub.restore(); + utils.logError.restore(); + utils.logWarn.restore(); + delete window.__cmp; + gdprDataHandler.consentData = null; + }); + + it('performs lookup check and stores consentData for a valid existing user', () => { + let testConsentData = { + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + }; + cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { + args[2](testConsentData); + }); + + setConfig(goodConfigWithAllowAuction); + + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + + sinon.assert.notCalled(utils.logWarn); + sinon.assert.notCalled(utils.logError); + expect(didHookReturn).to.be.true; + expect(consent.consentString).to.equal(testConsentData.metadata); + expect(consent.gdprApplies).to.be.true; + }); + + it('throws an error when processCmpData check failed while config had allowAuction set to false', () => { + let testConsentData = null; + + cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { + args[2](testConsentData); + }); + + setConfig(goodConfigWithCancelAuction); + + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + + sinon.assert.calledOnce(utils.logError); + expect(didHookReturn).to.be.false; + expect(consent).to.be.null; + }); + + it('throws a warning + stores consentData + calls callback when processCmpData check failed while config had allowAuction set to true', () => { + let testConsentData = null; + + cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { + args[2](testConsentData); + }); + + setConfig(goodConfigWithAllowAuction); + + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + + sinon.assert.calledOnce(utils.logWarn); + expect(didHookReturn).to.be.true; + expect(consent.consentString).to.be.undefined; + expect(consent.gdprApplies).to.be.undefined; + }); + }); + }); +}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index eb14c300e33..cdb3113c205 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -6,6 +6,7 @@ import cookie from 'src/cookie'; import { userSync } from 'src/userSync'; import { ajax } from 'src/ajax'; import { config } from 'src/config'; +import { requestBidsHook } from 'modules/consentManagement'; let CONFIG = { accountId: '1', @@ -391,6 +392,38 @@ describe('S2S Adapter', () => { expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); }); + it('adds gdpr consent information to ortb2 request depending on module use', () => { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + + let consentConfig = { consentManagement: { cmp: 'iab' }, s2sConfig: ortb2Config }; + config.setConfig(consentConfig); + + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: 'abc123', + gdprApplies: true + }; + + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.regs.ext.gdpr).is.equal(1); + expect(requestBid.user.ext.consent).is.equal('abc123'); + + config.resetConfig(); + config.setConfig({s2sConfig: CONFIG}); + + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + requestBid = JSON.parse(requests[1].requestBody); + + expect(requestBid.regs).to.not.exist; + expect(requestBid.user).to.not.exist; + + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + }); + it('sets invalid cacheMarkup value to 0', () => { const s2sConfig = Object.assign({}, CONFIG, { cacheMarkup: 999 diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index cbf17f9478a..7ea10315a4e 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -44,7 +44,10 @@ describe('PubMatic adapter', () => { 'price': 1.3, 'adm': 'image3.pubmatic.com Layer based creative', 'h': 250, - 'w': 300 + 'w': 300, + 'ext': { + 'deal_channel': 6 + } }] }] } @@ -136,8 +139,44 @@ describe('PubMatic adapter', () => { expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID - expect(data.ext.wrapper.profile).to.equal(bidRequests[0].params.profId); // OpenWrap: Wrapper Profile ID - expect(data.ext.wrapper.version).to.equal(bidRequests[0].params.verId); // OpenWrap: Wrapper Profile Version ID + expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID + expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID + + expect(data.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id + expect(data.imp[0].bidfloor).to.equal(parseFloat(bidRequests[0].params.kadfloor)); // kadfloor + expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid + }); + + it('Request params check with GDPR Consent', () => { + let bidRequest = { + gdprConsent: { + consentString: 'kjfdniwjnifwenrif3', + gdprApplies: true + } + }; + let request = spec.buildRequests(bidRequests, bidRequest); + let data = JSON.parse(request.data); + expect(data.user.ext.consent).to.equal('kjfdniwjnifwenrif3'); + expect(data.regs.ext.gdpr).to.equal(1); + expect(data.at).to.equal(1); // auction type + expect(data.cur[0]).to.equal('USD'); // currency + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.page).to.equal(bidRequests[0].params.kadpageurl); // forced pageURL + expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id + expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB + expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender + expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID + expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID + expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID expect(data.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id expect(data.imp[0].bidfloor).to.equal(parseFloat(bidRequests[0].params.kadfloor)); // kadfloor @@ -175,6 +214,24 @@ describe('PubMatic adapter', () => { expect(response[0].referrer).to.include(utils.getTopWindowUrl()); expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm); }); + + it('should check for dealChannel value selection', () => { + let request = spec.buildRequests(bidRequests); + let response = spec.interpretResponse(bidResponses, request); + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].dealChannel).to.equal('PMPG'); + }); + + it('should check for unexpected dealChannel value selection', () => { + let request = spec.buildRequests(bidRequests); + let updateBiResponse = bidResponses; + updateBiResponse.body.seatbid[0].bid[0].ext.deal_channel = 11; + + let response = spec.interpretResponse(updateBiResponse, request); + + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].dealChannel).to.equal(null); + }); }); }); }); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 39e468d4959..8b1c164a804 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -716,141 +716,171 @@ describe('adapterManager tests', () => { expect(AdapterManager.videoAdapters).to.include(alias); }); }); + }); + + describe('makeBidRequests', () => { + let adUnits; + beforeEach(() => { + adUnits = utils.deepClone(getAdUnits()).map(adUnit => { + adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus', 'rubicon'], bid.bidder)); + return adUnit; + }) + }); - describe('makeBidRequests', () => { - let adUnits; + describe('setBidderSequence', () => { beforeEach(() => { - adUnits = utils.deepClone(getAdUnits()).map(adUnit => { - adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus', 'rubicon'], bid.bidder)); - return adUnit; - }) + sinon.spy(utils, 'shuffle'); }); - describe('setBidderSequence', () => { - beforeEach(() => { - sinon.spy(utils, 'shuffle'); - }); - - afterEach(() => { - config.resetConfig(); - utils.shuffle.restore(); - }); + afterEach(() => { + config.resetConfig(); + utils.shuffle.restore(); + }); - it('setting to `random` uses shuffled order of adUnits', () => { - config.setConfig({ bidderSequence: 'random' }); - let bidRequests = AdapterManager.makeBidRequests( - adUnits, - Date.now(), - utils.getUniqueIdentifierStr(), - function callback() {}, - [] - ); - sinon.assert.calledOnce(utils.shuffle); - }); + it('setting to `random` uses shuffled order of adUnits', () => { + config.setConfig({ bidderSequence: 'random' }); + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + sinon.assert.calledOnce(utils.shuffle); }); + }); - describe('sizeMapping', () => { - beforeEach(() => { - sinon.stub(window, 'matchMedia').callsFake(() => ({matches: true})); - }); + describe('sizeMapping', () => { + beforeEach(() => { + sinon.stub(window, 'matchMedia').callsFake(() => ({matches: true})); + }); - afterEach(() => { - matchMedia.restore(); - setSizeConfig([]); - }); + afterEach(() => { + matchMedia.restore(); + setSizeConfig([]); + }); - it('should not filter bids w/ no labels', () => { - let bidRequests = AdapterManager.makeBidRequests( - adUnits, - Date.now(), - utils.getUniqueIdentifierStr(), - function callback() {}, - [] - ); - - expect(bidRequests.length).to.equal(2); - let rubiconBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'rubicon'); - expect(rubiconBidRequests.bids.length).to.equal(1); - expect(rubiconBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === rubiconBidRequests.bids[0].adUnitCode).sizes); - - let appnexusBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'appnexus'); - expect(appnexusBidRequests.bids.length).to.equal(2); - expect(appnexusBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[0].adUnitCode).sizes); - expect(appnexusBidRequests.bids[1].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).sizes); - }); + it('should not filter bids w/ no labels', () => { + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + expect(bidRequests.length).to.equal(2); + let rubiconBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'rubicon'); + expect(rubiconBidRequests.bids.length).to.equal(1); + expect(rubiconBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === rubiconBidRequests.bids[0].adUnitCode).sizes); + + let appnexusBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'appnexus'); + expect(appnexusBidRequests.bids.length).to.equal(2); + expect(appnexusBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[0].adUnitCode).sizes); + expect(appnexusBidRequests.bids[1].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).sizes); + }); - it('should filter sizes using size config', () => { - let validSizes = [ - [728, 90], - [300, 250] - ]; - - let validSizeMap = validSizes.map(size => size.toString()).reduce((map, size) => { - map[size] = true; - return map; - }, {}); - - setSizeConfig([{ - 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', - 'sizesSupported': validSizes, - 'labels': ['tablet', 'phone'] - }]); - - let bidRequests = AdapterManager.makeBidRequests( - adUnits, - Date.now(), - utils.getUniqueIdentifierStr(), - function callback() {}, - [] - ); + it('should filter sizes using size config', () => { + let validSizes = [ + [728, 90], + [300, 250] + ]; + + let validSizeMap = validSizes.map(size => size.toString()).reduce((map, size) => { + map[size] = true; + return map; + }, {}); + + setSizeConfig([{ + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': validSizes, + 'labels': ['tablet', 'phone'] + }]); + + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); // only valid sizes as specified in size config should show up in bidRequests - bidRequests.forEach(bidRequest => { - bidRequest.bids.forEach(bid => { - bid.sizes.forEach(size => { - expect(validSizeMap[size]).to.equal(true); - }); + bidRequests.forEach(bidRequest => { + bidRequest.bids.forEach(bid => { + bid.sizes.forEach(size => { + expect(validSizeMap[size]).to.equal(true); }); }); - - setSizeConfig([{ - 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', - 'sizesSupported': [], - 'labels': ['tablet', 'phone'] - }]); - - bidRequests = AdapterManager.makeBidRequests( - adUnits, - Date.now(), - utils.getUniqueIdentifierStr(), - function callback() {}, - [] - ); - - // if no valid sizes, all bidders should be filtered out - expect(bidRequests.length).to.equal(0); }); - it('should filter adUnits/bidders based on applied labels', () => { - adUnits[0].labelAll = ['visitor-uk', 'mobile']; - adUnits[1].labelAny = ['visitor-uk', 'desktop']; - adUnits[1].bids[0].labelAny = ['mobile']; - adUnits[1].bids[1].labelAll = ['desktop']; + setSizeConfig([{ + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [], + 'labels': ['tablet', 'phone'] + }]); + + bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + // if no valid sizes, all bidders should be filtered out + expect(bidRequests.length).to.equal(0); + }); + + it('should filter adUnits/bidders based on applied labels', () => { + adUnits[0].labelAll = ['visitor-uk', 'mobile']; + adUnits[1].labelAny = ['visitor-uk', 'desktop']; + adUnits[1].bids[0].labelAny = ['mobile']; + adUnits[1].bids[1].labelAll = ['desktop']; - let bidRequests = AdapterManager.makeBidRequests( - adUnits, - Date.now(), - utils.getUniqueIdentifierStr(), - function callback() {}, - ['visitor-uk', 'desktop'] - ); + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + ['visitor-uk', 'desktop'] + ); // 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); - expect(bidRequests[0].bids[0].adUnitCode).to.equal(adUnits[1].code); + expect(bidRequests.length).to.equal(1); + expect(bidRequests[0].bidderCode).to.equal('rubicon'); + expect(bidRequests[0].bids.length).to.equal(1); + expect(bidRequests[0].bids[0].adUnitCode).to.equal(adUnits[1].code); + }); + }); + + describe('gdpr consent module', () => { + it('inserts gdprConsent object to bidRequest only when module was enabled', () => { + AdapterManager.gdprDataHandler.setConsentData({ + consentString: 'abc123def456', + consentRequired: true }); + + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + expect(bidRequests[0].gdprConsent.consentString).to.equal('abc123def456'); + expect(bidRequests[0].gdprConsent.consentRequired).to.be.true; + + AdapterManager.gdprDataHandler.setConsentData(null); + + bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + expect(bidRequests[0].gdprConsent).to.be.undefined; }); }); }); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index f86840dbdba..9218409c46c 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -359,6 +359,33 @@ describe('Utils', function () { }); }); + describe('isPlainObject', function () { + it('should return false with input string', function () { + var output = utils.isPlainObject(obj_string); + assert.deepEqual(output, false); + }); + + it('should return false with input number', function () { + var output = utils.isPlainObject(obj_number); + assert.deepEqual(output, false); + }); + + it('should return true with input object', function () { + var output = utils.isPlainObject(obj_object); + assert.deepEqual(output, true); + }); + + it('should return false with input array', function () { + var output = utils.isPlainObject(obj_array); + assert.deepEqual(output, false); + }); + + it('should return false with input function', function () { + var output = utils.isPlainObject(obj_function); + assert.deepEqual(output, false); + }); + }); + describe('isEmpty', function () { it('should return true with empty object', function () { var output = utils.isEmpty(obj_object); From 4dcb04667e614e71893f3b5c917e6b6f0d14ab2e Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 1 May 2018 11:44:26 -0400 Subject: [PATCH 0315/1594] added whitelist for loading external JS + tests (#2430) * added whitelist for loading external JS + tests * fixed import * remove unused import --- src/adloader.js | 27 ++++++++++++----- test/spec/adloader_spec.js | 31 ++++++++++++++++++-- test/spec/modules/appnexusBidAdapter_spec.js | 14 --------- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/adloader.js b/src/adloader.js index 6f2bd112712..e0f2ba46cff 100644 --- a/src/adloader.js +++ b/src/adloader.js @@ -1,8 +1,14 @@ -var utils = require('./utils'); -let _requestCache = {}; +import includes from 'core-js/library/fn/array/includes'; +import * as utils from './utils'; + +const _requestCache = {}; +const _vendorWhitelist = [ + 'criteo', +] /** * Loads external javascript. Can only be used if external JS is approved by Prebid. See https://github.com/prebid/prebid-js-external-js-template#policy + * 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 */ @@ -11,18 +17,23 @@ exports.loadExternalScript = function(url, moduleCode) { utils.logError('cannot load external script without url and moduleCode'); return; } + if (!includes(_vendorWhitelist, moduleCode)) { + utils.logError(`${moduleCode} not whitelisted for loading external JavaScript`); + return; + } + // only load each asset once + if (_requestCache[url]) { + return; + } + utils.logWarn(`module ${moduleCode} is loading external JavaScript`); const script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; - script.src = url; - // add the new script tag to the page - const target = document.head || document.body; - if (target) { - target.appendChild(script); - } + utils.insertElement(script); + _requestCache[url] = true; }; /** diff --git a/test/spec/adloader_spec.js b/test/spec/adloader_spec.js index 951631d7eac..55224cb0aab 100644 --- a/test/spec/adloader_spec.js +++ b/test/spec/adloader_spec.js @@ -1,4 +1,31 @@ +import * as utils from 'src/utils'; +import * as adLoader from 'src/adloader'; + describe('adLoader', function () { - var assert = require('chai').assert, - adLoader = require('../../src/adloader'); + let utilsinsertElementStub; + let utilsLogErrorStub; + + beforeEach(() => { + utilsinsertElementStub = sinon.stub(utils, 'insertElement'); + utilsLogErrorStub = sinon.stub(utils, 'logError'); + }); + + afterEach(() => { + utilsinsertElementStub.restore(); + utilsLogErrorStub.restore(); + }); + + describe('loadExternalScript', () => { + it('requires moduleCode to be included on the request', () => { + adLoader.loadExternalScript('someURL'); + expect(utilsLogErrorStub.called).to.be.true; + expect(utilsinsertElementStub.called).to.be.false; + }); + + it('only allows whitelisted vendors to load scripts', () => { + adLoader.loadExternalScript('someURL', 'criteo'); + expect(utilsLogErrorStub.called).to.be.false; + expect(utilsinsertElementStub.called).to.be.true; + }); + }); }); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 53fbf390a6e..abfd50d1746 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -3,8 +3,6 @@ import { spec } from 'modules/appnexusBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; -const adloader = require('../../../src/adloader'); - const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; describe('AppNexusAdapter', () => { @@ -331,18 +329,6 @@ describe('AppNexusAdapter', () => { }) describe('interpretResponse', () => { - let loadScriptStub; - - beforeEach(() => { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); - - afterEach(() => { - loadScriptStub.restore(); - }); - let response = { 'version': '3.0.0', 'tags': [ From 64f342abea047152dde37a1a386097dcf5477b50 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 1 May 2018 09:13:06 -0700 Subject: [PATCH 0316/1594] Add note about headerbid expert (#2367) --- PR_REVIEW.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PR_REVIEW.md b/PR_REVIEW.md index 2a870d9e2f6..012a2d8b501 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -34,6 +34,7 @@ For modules and core platform updates, the initial reviewer should request an ad - Adapters may not use the $$PREBID_GLOBAL$$ variable - All adapters must support the creation of multiple concurrent instances. This means, for example, that adapters cannot rely on mutable global variables. - Adapters may not globally override or default the standard ad server targeting values: hb_adid, hb_bidder, hb_pb, hb_deal, or hb_size, hb_source, hb_format. +- After a new adapter is approved, let the submitter know they may open a PR in the [headerbid-expert repository](https://github.com/prebid/headerbid-expert) to have their adapter recognized by the [Headerbid Expert extension](https://chrome.google.com/webstore/detail/headerbid-expert/cgfkddgbnfplidghapbbnngaogeldmop). The PR should be to the [bidder patterns file](https://github.com/prebid/headerbid-expert/blob/master/bidderPatterns.js), adding an entry with their adapter's name and the url the adapter uses to send and receive bid responses. ## Ticket Coordinator From a4913ead842cd40bb5a3d384a5bd184a61be8ea4 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 1 May 2018 15:18:41 -0400 Subject: [PATCH 0317/1594] Prebid 1.9.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bb8afc62998..92d79cdd7ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.9.0-pre", + "version": "1.9.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From ab0386decead1b70afc9dc46aa7d6930bc360fae Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 1 May 2018 16:19:03 -0400 Subject: [PATCH 0318/1594] Increment Prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 92d79cdd7ea..44c54b468f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.9.0", + "version": "1.10.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 9416e7500064136fa4f3b48bf8f2ddc98613ca32 Mon Sep 17 00:00:00 2001 From: rachelrj Date: Tue, 1 May 2018 15:14:13 -0600 Subject: [PATCH 0319/1594] GDPR support for Sovrn Adapter (#2475) * fix sovrn dealid * send 'iv' param if present * `page` field in `site` object sends full url * Enhance location detection within util function. * fix func call * fix tagid var type * add test for converting tagid to string * CR * Reorg gettopwindowlocation util & add tests. * lint fixes * search param is string in window location objects * set creativeId to crid if present in response * send gdpr info --- modules/sovrnBidAdapter.js | 13 +++++++++++- test/spec/modules/sovrnBidAdapter_spec.js | 25 ++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 3a70a0ed433..6d67288cf09 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -21,7 +21,7 @@ export const spec = { * @param {BidRequest[]} bidRequests Array of Sovrn bidders * @return object of parameters for Prebid AJAX request */ - buildRequests: function(bidReqs) { + buildRequests: function(bidReqs, bidderRequest) { const loc = utils.getTopWindowLocation(); let sovrnImps = []; let iv; @@ -44,6 +44,17 @@ export const spec = { }; if (iv) sovrnBidReq.iv = iv; + if (bidderRequest && bidderRequest.gdprConsent) { + sovrnBidReq.regs = { + ext: { + gdpr: +bidderRequest.gdprConsent.gdprApplies + }}; + sovrnBidReq.user = { + ext: { + consent: bidderRequest.gdprConsent.consentString + }}; + } + return { method: 'POST', url: `//ap.lijit.com/rtb/bid?src=${REPO_AND_VERSION}`, diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 9ad25753186..b19b79c7886 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -82,7 +82,30 @@ describe('sovrnBidAdapter', function() { const request = spec.buildRequests(ivBidRequests); expect(request.data).to.contain('"iv":"vet"') - }) + }); + + it('sends gdpr info if exists', () => { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'sovrn', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + bidderRequest.bids = bidRequests; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.regs.ext.gdpr).to.exist.and.to.be.a('number'); + expect(payload.regs.ext.gdpr).to.equal(1); + expect(payload.user.ext.consent).to.exist.and.to.be.a('string'); + expect(payload.user.ext.consent).to.equal(consentString); + }); it('converts tagid to string', () => { const ivBidRequests = [{ From 06544745313159c3dbc5d5211754bb579e596736 Mon Sep 17 00:00:00 2001 From: Zhaoyong Ma <33766472+moonshells@users.noreply.github.com> Date: Tue, 1 May 2018 14:22:12 -0700 Subject: [PATCH 0320/1594] send rp_secure to frank for video bids (#2476) * send rp_secure to frank for video bids * remove the workaround * update unit test --- modules/rubiconBidAdapter.js | 3 +-- test/spec/modules/rubiconBidAdapter_spec.js | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index ea88886b753..bf2930e5684 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -132,8 +132,6 @@ export const spec = { page_url = utils.getTopWindowUrl(); } - page_url = bidRequest.params.secure ? page_url.replace(/^http:/i, 'https:') : page_url; - // GDPR reference, for use by 'banner' and 'video' const gdprConsent = bidderRequest.gdprConsent; @@ -150,6 +148,7 @@ export const spec = { timeout: bidderRequest.timeout - (Date.now() - bidderRequest.auctionStart + TIMEOUT_BUFFER), stash_creatives: true, ae_pass_through_parameters: params.video.aeParams, + rp_secure: bidRequest.params.secure !== false, slots: [] }; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index e3ffef9997e..e6f4d873ca5 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -72,6 +72,7 @@ describe('the rubicon adapter', () => { 'p_aso.video.ext.skipdelay': '15' } }; + bid.params.secure = false; } function createVideoBidderRequestNoVideo() { @@ -274,7 +275,7 @@ describe('the rubicon adapter', () => { bidderRequest.bids[0].params.secure = true; [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - expect(parseQuery(request.data).rf).to.equal('https://www.rubiconproject.com'); + expect(parseQuery(request.data).rf).to.equal('http://www.rubiconproject.com'); }); it('should use rubicon sizes if present (including non-mappable sizes)', () => { @@ -608,6 +609,7 @@ describe('the rubicon adapter', () => { expect(post).to.have.property('timeout').that.is.a('number'); expect(post.timeout < 5000).to.equal(true); expect(post.stash_creatives).to.equal(true); + expect(post.rp_secure).to.equal(false); expect(post.gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); expect(post.gdpr).to.equal(1); @@ -671,6 +673,7 @@ describe('the rubicon adapter', () => { expect(post).to.have.property('timeout').that.is.a('number'); expect(post.timeout < 5000).to.equal(true); expect(post.stash_creatives).to.equal(true); + expect(post.rp_secure).to.equal(true); expect(post.gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); expect(post.gdpr).to.equal(1); From bea6ab011b7a1f503f1a5d20336052c2887890ba Mon Sep 17 00:00:00 2001 From: LeoWu Date: Thu, 3 May 2018 20:33:19 +0800 Subject: [PATCH 0321/1594] add feature to bridgewellBidAdapter (#2480) * [FEAT] support mediaTypes.banner.sizes * [FEAT] init native * [FEAT] init bw version * [FEAT] hoist bidder version --- modules/bridgewellBidAdapter.js | 125 ++- modules/bridgewellBidAdapter.md | 37 + .../spec/modules/bridgewellBidAdapter_spec.js | 738 +++++++++++++++++- 3 files changed, 895 insertions(+), 5 deletions(-) diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index 712b00ec51a..c57ac85bc09 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -1,12 +1,15 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; +import {BANNER, NATIVE} from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'bridgewell'; const REQUEST_ENDPOINT = '//rec.scupio.com/recweb/prebid.aspx?cb=' + Math.random(); +const BIDDER_VERSION = '0.0.1'; export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [BANNER, NATIVE], /** * Determines whether or not the given bid request is valid. @@ -59,6 +62,10 @@ export const spec = { method: 'POST', url: REQUEST_ENDPOINT, data: { + version: { + prebid: '$prebid.version$', + bridgewell: BIDDER_VERSION + }, adUnits: adUnits }, validBidRequests: validBidRequests @@ -104,7 +111,7 @@ export const spec = { }); } - if (sizeValid) { // dont care native sizes + if (sizeValid || (mediaTypes && mediaTypes.native)) { // dont care native sizes valid = true; } } @@ -120,23 +127,133 @@ export const spec = { // check required parameters if (typeof matchedResponse.cpm !== 'number') { return; - } else if (typeof matchedResponse.ad !== 'string') { - return; } else if (typeof matchedResponse.netRevenue !== 'boolean') { return; } else if (typeof matchedResponse.currency !== 'string') { return; + } else if (typeof matchedResponse.mediaType !== 'string') { + return; } bidResponse.requestId = req.bidId; bidResponse.cpm = matchedResponse.cpm * req.params.cpmWeight; bidResponse.width = matchedResponse.width; bidResponse.height = matchedResponse.height; - bidResponse.ad = matchedResponse.ad; bidResponse.ttl = matchedResponse.ttl; bidResponse.creativeId = matchedResponse.id; bidResponse.netRevenue = matchedResponse.netRevenue; bidResponse.currency = matchedResponse.currency; + bidResponse.mediaType = matchedResponse.mediaType; + + // check required parameters by matchedResponse.mediaType + switch (matchedResponse.mediaType) { + case BANNER: + // check banner required parameters + if (typeof matchedResponse.ad !== 'string') { + return; + } + + bidResponse.ad = matchedResponse.ad; + break; + case NATIVE: + // check native required parameters + if (!matchedResponse.native) { + return; + } + + let req_nativeLayout = req.mediaTypes.native; + let res_native = matchedResponse.native; + + // check title + let title = req_nativeLayout.title; + if (title && title.required) { + if (typeof res_native.title !== 'string') { + return; + } else if (title.len && title.len < res_native.title.length) { + return; + } + } + + // check body + let body = req_nativeLayout.body; + if (body && body.required) { + if (typeof res_native.body !== 'string') { + return; + } + } + + // check image + let image = req_nativeLayout.image; + if (image && image.required) { + if (res_native.image) { + if (typeof res_native.image.url !== 'string') { // check image url + return; + } else { + if (res_native.image.width !== image.sizes[0] || res_native.image.height !== image.sizes[1]) { // check image sizes + return; + } + } + } else { + return; + } + } + + // check sponsoredBy + let sponsoredBy = req_nativeLayout.sponsoredBy; + if (sponsoredBy && sponsoredBy.required) { + if (typeof res_native.sponsoredBy !== 'string') { + return; + } + } + + // check icon + let icon = req_nativeLayout.icon; + if (icon && icon.required) { + if (res_native.icon) { + if (typeof res_native.icon.url !== 'string') { // check icon url + return; + } else { + if (res_native.icon.width !== icon.sizes[0] || res_native.icon.height !== icon.sizes[0]) { // check image sizes + return; + } + } + } else { + return; + } + } + + // check clickUrl + if (typeof res_native.clickUrl !== 'string') { + return; + } + + // check clickTracker + let clickTrackers = res_native.clickTrackers; + if (clickTrackers) { + if (clickTrackers.length === 0) { + return; + } + } else { + return; + } + + // check impressionTrackers + let impressionTrackers = res_native.impressionTrackers; + if (impressionTrackers) { + if (impressionTrackers.length === 0) { + return; + } + } else { + return; + } + + bidResponse.native = matchedResponse.native; + + break; + + default: // response mediaType is not supported + return; + } bidResponses.push(bidResponse); } diff --git a/modules/bridgewellBidAdapter.md b/modules/bridgewellBidAdapter.md index 6e542af18a7..014be62ccef 100644 --- a/modules/bridgewellBidAdapter.md +++ b/modules/bridgewellBidAdapter.md @@ -55,5 +55,42 @@ Module that connects to Bridgewell demand source to fetch bids. ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ' } }] + }, { + code: 'test-div', + sizes: [1, 1], + mediaTypes: { + native: { + title: { + required: true, + len: 80 + }, + body: { + required: true + }, + image: { + required: true, + sizes: [150, 50] + }, + icon: { + required: false, + sizes: [50, 50] + }, + clickUrl: { + required: true + }, + cta: { + required: false + }, + sponsoredBy: { + required: false + } + } + }, + bids: [{ + bidder: 'bridgewell', + params: { + ChannelID: 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ' + } + }] }]; ``` diff --git a/test/spec/modules/bridgewellBidAdapter_spec.js b/test/spec/modules/bridgewellBidAdapter_spec.js index 8615531f88f..5dae3c474ac 100644 --- a/test/spec/modules/bridgewellBidAdapter_spec.js +++ b/test/spec/modules/bridgewellBidAdapter_spec.js @@ -87,6 +87,84 @@ describe('bridgewellBidAdapter', function () { 'bidId': '3150ccb55da321', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ', + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [1, 1], + 'mediaTypes': { + 'native': { + 'title': { + 'required': true, + 'len': 15 + }, + 'body': { + 'required': true + }, + 'image': { + 'required': true, + 'sizes': [150, 150] + }, + 'icon': { + 'required': true, + 'sizes': [50, 50] + }, + 'clickUrl': { + 'required': true + }, + 'cta': { + 'required': true + }, + 'sponsoredBy': { + 'required': true + } + } + }, + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'bridgewell', + 'params': { + 'ChannelID': 'CgUxMjMzOBIBNiIGcGVubnkzKggI2AUQWhoBOQ', + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [1, 1], + 'mediaTypes': { + 'native': { + 'title': { + 'required': false, + 'len': 15 + }, + 'body': { + 'required': false + }, + 'image': { + 'required': false, + 'sizes': [150, 150] + }, + 'icon': { + 'required': false, + 'sizes': [50, 50] + }, + 'clickUrl': { + 'required': false + }, + 'cta': { + 'required': false + }, + 'sponsoredBy': { + 'required': false + } + } + }, + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', } ]; const adapter = newBidder(spec); @@ -224,6 +302,7 @@ describe('bridgewellBidAdapter', function () { 'cpm': 5.0, 'width': 300, 'height': 250, + 'mediaType': 'banner', 'ad': '
test 300x250
', 'ttl': 360, 'netRevenue': true, @@ -235,6 +314,7 @@ describe('bridgewellBidAdapter', function () { 'cpm': 5.0, 'width': 728, 'height': 90, + 'mediaType': 'banner', 'ad': '
test 728x90
', 'ttl': 360, 'netRevenue': true, @@ -246,6 +326,7 @@ describe('bridgewellBidAdapter', function () { 'cpm': 5.0, 'width': 300, 'height': 250, + 'mediaType': 'banner', 'ad': '
test 300x250
', 'ttl': 360, 'netRevenue': true, @@ -257,6 +338,7 @@ describe('bridgewellBidAdapter', function () { 'cpm': 5.0, 'width': 300, 'height': 250, + 'mediaType': 'banner', 'ad': '
test 300x250
', 'ttl': 360, 'netRevenue': true, @@ -268,6 +350,7 @@ describe('bridgewellBidAdapter', function () { 'cpm': 5.0, 'width': 728, 'height': 90, + 'mediaType': 'banner', 'ad': '
test 728x90
', 'ttl': 360, 'netRevenue': true, @@ -279,6 +362,7 @@ describe('bridgewellBidAdapter', function () { 'cpm': 5.0, 'width': 728, 'height': 90, + 'mediaType': 'banner', 'ad': '
test 728x90
', 'ttl': 360, 'netRevenue': true, @@ -290,10 +374,69 @@ describe('bridgewellBidAdapter', function () { 'cpm': 5.0, 'width': 728, 'height': 90, + 'mediaType': 'banner', 'ad': '
test 728x90
', 'ttl': 360, 'netRevenue': true, 'currency': 'NTD' + }, + { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }, + { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' } ]; @@ -305,7 +448,13 @@ describe('bridgewellBidAdapter', function () { result.every(res => expect(res.ttl).to.be.a('number')); result.every(res => expect(res.netRevenue).to.be.a('boolean')); result.every(res => expect(res.currency).to.be.a('string')); - result.every(res => expect(res.ad).to.be.a('string')); + result.every(res => { + if (res.ad) { + expect(res.ad).to.be.an('string'); + } else if (res.native) { + expect(res.native).to.be.an('object'); + } + }); }); it('should give up bid if server response is undefiend', () => { @@ -384,6 +533,7 @@ describe('bridgewellBidAdapter', function () { 'cpm': 5.0, 'width': 300, 'height': 250, + 'mediaType': 'banner', 'ttl': 360, 'netRevenue': true, 'currency': 'NTD' @@ -424,5 +574,591 @@ describe('bridgewellBidAdapter', function () { const result = spec.interpretResponse({'body': [target]}, request); expect(result).to.deep.equal([]); }); + + it('should give up bid if mediaType is missing', () => { + let target = { + 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 300, + 'height': 250, + 'ad': '
test 300x250
', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if property native of mediaType native is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native title is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native title is too long', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-titletest-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native body is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + + it('should give up bid if native image url is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + }); + + it('should give up bid if native image is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native image url is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native image sizes is unmatch', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg' + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native sponsoredBy is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native icon is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native icon url is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native icon sizes is unmatch', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg' + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native clickUrl is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native clickTrackers is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native clickTrackers is empty', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': [], + 'impressionTrackers': ['https://img.scupio.com/test-impressionTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native impressionTrackers is missing', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if native impressionTrackers is empty', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'https://img.scupio.com/test/test-image.jpg', + 'width': 150, + 'height': 150 + }, + 'title': 'test-title', + 'sponsoredBy': 'test-sponsoredBy', + 'body': 'test-body', + 'icon': { + 'url': 'https://img.scupio.com/test/test-icon.jpg', + 'width': 50, + 'height': 50 + }, + 'clickUrl': 'https://img.scupio.com/test-clickUrl', + 'clickTrackers': ['https://img.scupio.com/test-clickTracker'], + 'impressionTrackers': [] + }, + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); + + it('should give up bid if mediaType is not support', () => { + let target = { + 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', + 'bidder_code': 'bridgewell', + 'cpm': 5.0, + 'width': 1, + 'height': 1, + 'mediaType': 'superNiceAd', + 'ttl': 360, + 'netRevenue': true, + 'currency': 'NTD' + }; + + const result = spec.interpretResponse({'body': [target]}, request); + expect(result).to.deep.equal([]); + }); }); }); From 59db2fe00dbd3cd00c79da0477e16548366ccbb9 Mon Sep 17 00:00:00 2001 From: varashellov Date: Thu, 3 May 2018 15:55:21 +0300 Subject: [PATCH 0322/1594] Update Platformio Adapter (#2468) * Add PlatformioBidAdapter * Update platformioBidAdapter.js * Add files via upload * Update hello_world.html * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Update hello_world.html * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update hello_world.html * Add files via upload * Update platformioBidAdapter ## Type of change - [x] Other ## Description of change 1. RequestURL changes 2. Add placementCode to request params * Update platformioBidAdapter * Update platformioBidAdapter ## Type of change - [x] Other ## Description of change 1. RequestURL changes 2. Add placementCode to request params * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.js Endpoint URL change * Update platformioBidAdapter_spec.js Endpoint URL change * Update platformioBidAdapter_spec.js * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.js * Update platformioBidAdapter.md * Add files via upload * Add files via upload * Add files via upload * Update platformioBidAdapter.md * Update platformioBidAdapter.md * Update platformioBidAdapter.js * Update platformioBidAdapter_spec.js * Update platformioBidAdapter.md * Add files via upload * Add files via upload * Delete hello_world.html * Add files via upload * Add files via upload * Add files via upload * Add files via upload --- modules/platformioBidAdapter.js | 69 +++++++++++++++---- modules/platformioBidAdapter.md | 6 +- .../spec/modules/platformioBidAdapter_spec.js | 39 ++++++++++- 3 files changed, 96 insertions(+), 18 deletions(-) diff --git a/modules/platformioBidAdapter.js b/modules/platformioBidAdapter.js index abb0cf50722..b33aeab8f88 100644 --- a/modules/platformioBidAdapter.js +++ b/modules/platformioBidAdapter.js @@ -10,7 +10,6 @@ const NATIVE_DEFAULTS = { IMG_MIN: 150, ICON_MIN: 50, }; - const DEFAULT_MIMES = ['video/mp4', 'video/webm', 'application/x-shockwave-flash', 'application/javascript']; const VIDEO_TARGETING = ['mimes', 'skippable', 'playback_method', 'protocols', 'api']; const DEFAULT_PROTOCOLS = [2, 3, 5, 6]; @@ -22,7 +21,7 @@ export const spec = { supportedMediaTypes: [BANNER, NATIVE, VIDEO], isBidRequestValid: bid => ( - !!(bid && bid.params && bid.params.pubId && bid.params.siteId) + !!(bid && bid.params && bid.params.pubId && bid.params.placementId) ), buildRequests: bidRequests => { const request = { @@ -30,7 +29,8 @@ export const spec = { at: 2, imp: bidRequests.map(slot => impression(slot)), site: site(bidRequests), - device: device(), + app: app(bidRequests), + device: device(bidRequests), }; return { method: 'POST', @@ -101,6 +101,7 @@ function bidResponseAvailable(bidRequest, bidResponse) { function impression(slot) { return { id: slot.bidId, + secure: window.location.protocol === 'https:' ? 1 : 0, 'banner': banner(slot), 'native': nativeImpression(slot), 'video': videoImpression(slot), @@ -110,10 +111,16 @@ function impression(slot) { } function getSizes(slot) { - const size = slot.params.size.toUpperCase().split('X'); + if (slot.params.size) { + const size = slot.params.size.toUpperCase().split('X'); + return { + width: parseInt(size[0]), + height: parseInt(size[1]), + }; + } return { - width: parseInt(size[0]), - height: parseInt(size[1]), + width: 1, + height: 1, }; } @@ -207,25 +214,57 @@ function dataAsset(id, params, type, defaultLen) { function site(bidderRequest) { const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; - return { - publisher: { - id: pubId.toString(), - domain: utils.getTopWindowLocation().hostname, - }, - id: siteId.toString(), - ref: utils.getTopWindowReferrer(), - page: utils.getTopWindowLocation().href, + const appParams = bidderRequest[0].params.app; + if (!appParams) { + return { + publisher: { + id: pubId.toString(), + domain: utils.getTopWindowLocation().hostname, + }, + id: siteId.toString(), + ref: utils.getTopWindowReferrer(), + page: utils.getTopWindowLocation().href, + } + } + return null; +} + +function app(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; + const appParams = bidderRequest[0].params.app; + if (appParams) { + return { + publisher: { + id: pubId.toString(), + }, + id: appParams.id, + name: appParams.name, + bundle: appParams.bundle, + storeurl: appParams.storeUrl, + domain: appParams.domain, + } } + return null; } -function device() { +function device(bidderRequest) { + const lat = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.latitude : ''; + const lon = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.longitude : ''; + const ifa = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.ifa : ''; return { + dnt: utils.getDNT() ? 1 : 0, ua: navigator.userAgent, language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), w: (window.screen.width || window.innerWidth), h: (window.screen.height || window.innerHeigh), + geo: { + lat: lat, + lon: lon, + }, + ifa: ifa, }; } + function parse(rawResponse) { try { if (rawResponse) { diff --git a/modules/platformioBidAdapter.md b/modules/platformioBidAdapter.md index 8233d5cd545..ff6335d1d70 100644 --- a/modules/platformioBidAdapter.md +++ b/modules/platformioBidAdapter.md @@ -38,6 +38,10 @@ Please use ```platformio``` as the bidder code. pubId: '29521', siteId: '26048', placementId: '123', + bidFloor: '0.001', // optional + ifa: 'XXX-XXX', // optional + latitude: '40.712775', // optional + longitude: '-74.005973', // optional } }] }, @@ -76,7 +80,7 @@ Please use ```platformio``` as the bidder code. size: '640X480', placementId: '123', video: { - skippable: true, + skipppable: true, } } }] diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index c9954d4531a..fc8ba5bf45e 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -13,7 +13,10 @@ describe('Platform.io Adapter Tests', () => { siteId: '26047', placementId: '123', size: '300x250', - bidFloor: '0.001' + bidFloor: '0.001', + ifa: 'IFA', + latitude: '40.712775', + longitude: '-74.005973' } }, { placementCode: '/DfpAccount2/slot2', @@ -24,7 +27,7 @@ describe('Platform.io Adapter Tests', () => { siteId: '26047', placementId: '1234', size: '728x90', - bidFloor: '0.000001' + bidFloor: '0.000001', } }]; const nativeSlotConfig = [{ @@ -58,6 +61,21 @@ describe('Platform.io Adapter Tests', () => { size: '640x480' } }]; + const appSlotConfig = [{ + placementCode: '/DfpAccount1/slot5', + bidId: 'bid12345', + params: { + pubId: '29521', + placementId: '1234', + app: { + id: '1111', + name: 'app name', + bundle: 'io.platform.apps', + storeUrl: 'http://platform.io/apps', + domain: 'platform.io' + } + } + }]; it('Verify build request', () => { const request = spec.buildRequests(slotConfigs); @@ -74,6 +92,9 @@ describe('Platform.io Adapter Tests', () => { // device object expect(ortbRequest.device).to.not.equal(null); expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + expect(ortbRequest.device.ifa).to.equal('IFA'); + expect(ortbRequest.device.geo.lat).to.equal('40.712775'); + expect(ortbRequest.device.geo.lon).to.equal('-74.005973'); // slot 1 expect(ortbRequest.imp[0].tagid).to.equal('123'); expect(ortbRequest.imp[0].banner).to.not.equal(null); @@ -278,4 +299,18 @@ describe('Platform.io Adapter Tests', () => { expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); }); + + it('Verify app requests', () => { + const request = spec.buildRequests(appSlotConfig); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.publisher).to.not.equal(null); + expect(ortbRequest.app.publisher.id).to.equal('29521'); + expect(ortbRequest.app.id).to.equal('1111'); + expect(ortbRequest.app.name).to.equal('app name'); + expect(ortbRequest.app.bundle).to.equal('io.platform.apps'); + expect(ortbRequest.app.storeurl).to.equal('http://platform.io/apps'); + expect(ortbRequest.app.domain).to.equal('platform.io'); + }); }); From e247211ab64348bfcb7c62d3fa80b9471169d55d Mon Sep 17 00:00:00 2001 From: haohany Date: Thu, 3 May 2018 07:11:29 -0700 Subject: [PATCH 0323/1594] Only send OpenX BO beacon once per page load (#2484) --- modules/openxBidAdapter.js | 31 +++++++++++------------ test/spec/modules/openxBidAdapter_spec.js | 4 ++- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 1cc312da273..b425b80149a 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -10,6 +10,11 @@ const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; const BIDDER_VERSION = '2.1.0'; +let shouldSendBoPixel = true; +export function resetBoPixel() { + shouldSendBoPixel = true; +} + export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, @@ -63,11 +68,6 @@ function isVideoRequest(bidRequest) { function createBannerBidResponses(oxResponseObj, {bids, startTime}) { let adUnits = oxResponseObj.ads.ad; let bidResponses = []; - let shouldSendBoPixel = bids[0].params.sendBoPixel; - if (shouldSendBoPixel === undefined) { - // Not specified, default to turned on - shouldSendBoPixel = true; - } for (let i = 0; i < adUnits.length; i++) { let adUnit = adUnits[i]; let adUnitIdx = parseInt(adUnit.idx, 10); @@ -103,10 +103,9 @@ function createBannerBidResponses(oxResponseObj, {bids, startTime}) { } bidResponse.ts = adUnit.ts; - if (shouldSendBoPixel && adUnit.ts) { - registerBeacon(BANNER, adUnit, startTime); - } bidResponses.push(bidResponse); + + registerBeacon(BANNER, adUnit, startTime); } return bidResponses; } @@ -300,11 +299,6 @@ function generateVideoParameters(bid) { } function createVideoBidResponses(response, {bid, startTime}) { - let shouldSendBoPixel = bid.params.sendBoPixel; - if (shouldSendBoPixel === undefined) { - // Not specified, default to turned on - shouldSendBoPixel = true; - } let bidResponses = []; if (response !== undefined && response.vastUrl !== '' && response.pub_rev !== '') { @@ -329,16 +323,21 @@ function createVideoBidResponses(response, {bid, startTime}) { response.colo = vastQueryParams.colo; response.ts = vastQueryParams.ts; - if (shouldSendBoPixel && response.ts) { - registerBeacon(VIDEO, response, startTime) - } bidResponses.push(bidResponse); + + registerBeacon(VIDEO, response, startTime) } return bidResponses; } function registerBeacon(mediaType, adUnit, startTime) { + // only register beacon once + if (!shouldSendBoPixel) { + return; + } + shouldSendBoPixel = false; + let bt = config.getConfig('bidderTimeout'); let beaconUrl; if (window.PREBID_TIMEOUT) { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index b763c111998..e4a1c9a979d 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import {spec} from 'modules/openxBidAdapter'; +import {spec, resetBoPixel} from 'modules/openxBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import {userSync} from 'src/userSync'; import * as utils from 'src/utils'; @@ -586,6 +586,7 @@ describe('OpenxAdapter', () => { }); it('should register a beacon', () => { + resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequest); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(new RegExp(`\/\/openx-d\.openx\.net.*\/bo\?.*ts=${adUnitOverride.ts}`))); }); @@ -882,6 +883,7 @@ describe('OpenxAdapter', () => { }); it('should register a beacon', () => { + resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/^\/\/test-colo\.com/)) sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/ph=test-ph/)); From 04d66013aef421d83430feb6708f55aefc7daa05 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Fri, 4 May 2018 18:06:23 +0530 Subject: [PATCH 0324/1594] Update the consent param in userSync as per IAB Spec (#2494) --- modules/pubmaticBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 1f056bf0eff..14da2c45164 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -306,7 +306,7 @@ export const spec = { // Attaching GDPR Consent Params in UserSync url if (gdprConsent) { syncurl += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); - syncurl += '&consent=' + encodeURIComponent(gdprConsent.consentString || ''); + syncurl += '&gdpr_consent=' + encodeURIComponent(gdprConsent.consentString || ''); } if (syncOptions.iframeEnabled) { From 723669a0f07fd0b63637505bc6b52cfb012ca556 Mon Sep 17 00:00:00 2001 From: Preston Skupinski Date: Fri, 4 May 2018 07:39:53 -0500 Subject: [PATCH 0325/1594] Fix typos in comment, cosolidated -> consolidated (#2493) --- src/auctionManager.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/auctionManager.js b/src/auctionManager.js index f845db5f934..494421b7785 100644 --- a/src/auctionManager.js +++ b/src/auctionManager.js @@ -7,10 +7,10 @@ /** * @typedef {Object} AuctionManager * - * @property {function(): Array} getBidsRequested - returns cosolidated bid requests - * @property {function(): Array} getBidsReceived - returns cosolidated bid received - * @property {function(): Array} getAdUnits - returns cosolidated adUnits - * @property {function(): Array} getAdUnitCodes - returns cosolidated adUnitCodes + * @property {function(): Array} getBidsRequested - returns consolidated bid requests + * @property {function(): Array} getBidsReceived - returns consolidated bid received + * @property {function(): Array} getAdUnits - returns consolidated adUnits + * @property {function(): Array} getAdUnitCodes - returns consolidated adUnitCodes * @property {function(): Object} createAuction - creates auction instance and stores it for future reference * @property {function(): Object} findBidByAdId - find bid received by adId. This function will be called by $$PREBID_GLOBAL$$.renderAd * @property {function(): Object} getStandardBidderAdServerTargeting - returns standard bidder targeting for all the adapters. Refer http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.bidderSettings for more details From 4e80a29fa6a85f1b1d0ad44ccf10c3a170fe414f Mon Sep 17 00:00:00 2001 From: Preston Skupinski Date: Fri, 4 May 2018 11:41:40 -0500 Subject: [PATCH 0326/1594] Add LockerDome bid adapter (#2477) --- modules/lockerdomeBidAdapter.js | 50 ++++++ modules/lockerdomeBidAdapter.md | 29 ++++ .../spec/modules/lockerdomeBidAdapter_spec.js | 142 ++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 modules/lockerdomeBidAdapter.js create mode 100644 modules/lockerdomeBidAdapter.md create mode 100644 test/spec/modules/lockerdomeBidAdapter_spec.js diff --git a/modules/lockerdomeBidAdapter.js b/modules/lockerdomeBidAdapter.js new file mode 100644 index 00000000000..dd63d00b356 --- /dev/null +++ b/modules/lockerdomeBidAdapter.js @@ -0,0 +1,50 @@ +import * as utils from 'src/utils'; +import {BANNER} from 'src/mediaTypes'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +export const spec = { + code: 'lockerdome', + supportedMediaTypes: [BANNER], + isBidRequestValid: function(bid) { + return !!bid.params.adUnitId; + }, + buildRequests: function(bidRequests) { + const adUnitBidRequests = bidRequests.map(function (bid) { + return { + requestId: bid.bidId, + adUnitId: utils.getBidIdParameter('adUnitId', bid.params), + sizes: bid.sizes + } + }); + const payload = { + bidRequests: adUnitBidRequests, + url: utils.getTopWindowLocation().href, + referrer: utils.getTopWindowReferrer() + }; + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: 'https://lockerdome.com/ladbid/prebid', + data: payloadString + }; + }, + interpretResponse: function(serverResponse, bidRequest) { + if (!serverResponse || !serverResponse.body || !serverResponse.body.bids) { + return []; + } + return serverResponse.body.bids.map(function(bid) { + return { + requestId: bid.requestId, + cpm: bid.cpm, + width: bid.width, + height: bid.height, + creativeId: bid.creativeId, + currency: bid.currency, + netRevenue: bid.netRevenue, + ad: bid.ad, + ttl: bid.ttl + }; + }); + }, +} +registerBidder(spec); diff --git a/modules/lockerdomeBidAdapter.md b/modules/lockerdomeBidAdapter.md new file mode 100644 index 00000000000..2e2e69a7557 --- /dev/null +++ b/modules/lockerdomeBidAdapter.md @@ -0,0 +1,29 @@ +# Overview + +``` +Module Name: LockerDome Bidder Adapter +Module Type: Bidder Adapter +Maintainer: bidding@lockerdome.com +``` + +#Description +Connects to LockerDome Ad Server for bids. + +# Test Parameters +``` +var adUnits = [{ + code: 'ad-div', + sizes: [[300, 250]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'lockerdome', + params: { + adUnitId: 10809467961050726 + } + }] +}]; +``` diff --git a/test/spec/modules/lockerdomeBidAdapter_spec.js b/test/spec/modules/lockerdomeBidAdapter_spec.js new file mode 100644 index 00000000000..1ad26af24c1 --- /dev/null +++ b/test/spec/modules/lockerdomeBidAdapter_spec.js @@ -0,0 +1,142 @@ +import { expect } from 'chai'; +import { spec } from '../../../modules/lockerdomeBidAdapter'; +import * as utils from 'src/utils'; + +describe('LockerDomeAdapter', () => { + const bidRequests = [{ + bidder: 'lockerdome', + params: { + adUnitId: 10809467961050726 + }, + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + adUnitCode: 'ad-1', + transactionId: 'b55e97d7-792c-46be-95a5-3df40b115734', + sizes: [[300, 250]], + bidId: '2652ca954bce9', + bidderRequestId: '14a54fade69854', + auctionId: 'd4c83108-615d-4c2c-9384-dac9ffd4fd72' + }, { + bidder: 'lockerdome', + params: { + adUnitId: 9434769725128806 + }, + mediaTypes: { + banner: { + sizes: [[300, 600]] + } + }, + adUnitCode: 'ad-2', + transactionId: '73459f05-c482-4706-b2b7-72e6f6264ce6', + sizes: [[300, 600]], + bidId: '4510f2834773ce', + bidderRequestId: '14a54fade69854', + auctionId: 'd4c83108-615d-4c2c-9384-dac9ffd4fd72' + }]; + + describe('isBidRequestValid', () => { + it('should return true if the adUnitId parameter is present', () => { + expect(spec.isBidRequestValid(bidRequests[0])).to.be.true; + expect(spec.isBidRequestValid(bidRequests[1])).to.be.true; + }); + it('should return false if the adUnitId parameter is not present', () => { + let bidRequest = utils.deepClone(bidRequests[0]); + delete bidRequest.params.adUnitId; + expect(spec.isBidRequestValid(bidRequest)).to.be.false; + }); + }); + + describe('buildRequests', () => { + it('should generate a valid single POST request for multiple bid requests', () => { + const request = spec.buildRequests(bidRequests); + expect(request.method).to.equal('POST'); + // TODO: Update to production URL + expect(request.url).to.equal('https://lockerdome.com/ladbid/prebid'); + expect(request.data).to.exist; + + const requestData = JSON.parse(request.data); + + expect(requestData.url).to.equal(utils.getTopWindowLocation().href); + expect(requestData.referrer).to.equal(utils.getTopWindowReferrer()); + + const bids = requestData.bidRequests; + expect(bids).to.have.lengthOf(2); + + expect(bids[0].requestId).to.equal('2652ca954bce9'); + expect(bids[0].adUnitId).to.equal(10809467961050726); + expect(bids[0].sizes).to.have.lengthOf(1); + expect(bids[0].sizes[0][0]).to.equal(300); + expect(bids[0].sizes[0][1]).to.equal(250); + + expect(bids[1].requestId).to.equal('4510f2834773ce'); + expect(bids[1].adUnitId).to.equal(9434769725128806); + expect(bids[1].sizes).to.have.lengthOf(1); + expect(bids[1].sizes[0][0]).to.equal(300); + expect(bids[1].sizes[0][1]).to.equal(600); + }); + }); + + describe('interpretResponse', () => { + it('should return an empty array if an invalid response is passed', () => { + const interpretedResponse = spec.interpretResponse({ body: {} }); + expect(interpretedResponse).to.be.an('array').that.is.empty; + }); + + it('should return valid response when passed valid server response', () => { + const serverResponse = { + body: { + bids: [{ + requestId: '2652ca954bce9', + cpm: 1.00, + width: 300, + height: 250, + creativeId: '12345', + currency: 'USD', + netRevenue: true, + ad: '', + ttl: 300 + }, + { + requestId: '4510f2834773ce', + cpm: 1.10, + width: 300, + height: 600, + creativeId: '45678', + currency: 'USD', + netRevenue: true, + ad: '', + ttl: 300 + }] + } + }; + + const request = spec.buildRequests(bidRequests); + const interpretedResponse = spec.interpretResponse(serverResponse, request); + + expect(interpretedResponse).to.have.lengthOf(2); + + expect(interpretedResponse[0].requestId).to.equal(serverResponse.body.bids[0].requestId); + expect(interpretedResponse[0].cpm).to.equal(serverResponse.body.bids[0].cpm); + expect(interpretedResponse[0].width).to.equal(serverResponse.body.bids[0].width); + expect(interpretedResponse[0].height).to.equal(serverResponse.body.bids[0].height); + expect(interpretedResponse[0].creativeId).to.equal(serverResponse.body.bids[0].creativeId); + expect(interpretedResponse[0].currency).to.equal(serverResponse.body.bids[0].currency); + expect(interpretedResponse[0].netRevenue).to.equal(serverResponse.body.bids[0].netRevenue); + expect(interpretedResponse[0].ad).to.equal(serverResponse.body.bids[0].ad); + expect(interpretedResponse[0].ttl).to.equal(serverResponse.body.bids[0].ttl); + + expect(interpretedResponse[1].requestId).to.equal(serverResponse.body.bids[1].requestId); + expect(interpretedResponse[1].cpm).to.equal(serverResponse.body.bids[1].cpm); + expect(interpretedResponse[1].width).to.equal(serverResponse.body.bids[1].width); + expect(interpretedResponse[1].height).to.equal(serverResponse.body.bids[1].height); + expect(interpretedResponse[1].creativeId).to.equal(serverResponse.body.bids[1].creativeId); + expect(interpretedResponse[1].currency).to.equal(serverResponse.body.bids[1].currency); + expect(interpretedResponse[1].netRevenue).to.equal(serverResponse.body.bids[1].netRevenue); + expect(interpretedResponse[1].ad).to.equal(serverResponse.body.bids[1].ad); + expect(interpretedResponse[1].ttl).to.equal(serverResponse.body.bids[1].ttl); + }); + }); +}); From 3116d7f557587b2cf981b384e961e8dd831eea43 Mon Sep 17 00:00:00 2001 From: ankur-modi <38654685+ankur-modi@users.noreply.github.com> Date: Sat, 5 May 2018 00:01:11 +0530 Subject: [PATCH 0327/1594] One Video Adapter (#2445) * One Video Adapter * adding more test cases --- modules/oneVideoBidAdapter.js | 189 +++++++++++++++++++ modules/oneVideoBidAdapter.md | 47 +++++ test/spec/modules/oneVideoBidAdapter_spec.js | 135 +++++++++++++ 3 files changed, 371 insertions(+) create mode 100644 modules/oneVideoBidAdapter.js create mode 100755 modules/oneVideoBidAdapter.md create mode 100644 test/spec/modules/oneVideoBidAdapter_spec.js diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js new file mode 100644 index 00000000000..c56669b8b0c --- /dev/null +++ b/modules/oneVideoBidAdapter.js @@ -0,0 +1,189 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'oneVideo'; +export const spec = { + code: 'oneVideo', + ENDPOINT: '//ads.adaptv.advertising.com/rtb/openrtb?ext_id=', + SYNC_ENDPOINT1: 'https://cm.g.doubleclick.net/pixel?google_nid=adaptv_dbm&google_cm&google_sc', + SYNC_ENDPOINT2: 'https://pr-bh.ybp.yahoo.com/sync/adaptv_ortb/{combo_uid}', + SYNC_ENDPOINT3: 'https://sync-tm.everesttech.net/upi/pid/m7y5t93k?redir=https%3A%2F%2Fsync.adap.tv%2Fsync%3Ftype%3Dgif%26key%3Dtubemogul%26uid%3D%24%7BUSER_ID%7D', + SYNC_ENDPOINT4: 'https://match.adsrvr.org/track/cmf/generic?ttd_pid=adaptv&ttd_tpi=1', + supportedMediaTypes: ['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.bidder !== BIDDER_CODE || typeof bid.params === 'undefined') { + return false; + } + + // Video validations + if (typeof bid.params.video === 'undefined' || typeof bid.params.video.playerWidth === 'undefined' || typeof bid.params.video.playerHeight == 'undefined' || typeof bid.params.video.mimes == 'undefined') { + return false; + } + + // Pub Id validation + if (typeof bid.params.pubId === 'undefined') { + return false; + } + + return true; + }, + /** + * 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(bids) { + return bids.map(bid => { + return { + method: 'POST', + url: location.protocol + spec.ENDPOINT + bid.params.pubId, + data: getRequestData(bid), + options: {contentType: 'application/json'}, + bidRequest: bid + } + }) + }, + /** + * 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(response, { bidRequest }) { + let bid; + let size; + let bidResponse; + try { + response = response.body; + bid = response.seatbid[0].bid[0]; + } catch (e) { + response = null; + } + if (!response || !bid || (!bid.adm && !bid.nurl) || !bid.price) { + utils.logWarn(`No valid bids from ${spec.code} bidder`); + return []; + } + size = getSize(bidRequest.sizes); + bidResponse = { + requestId: bidRequest.bidId, + bidderCode: spec.code, + cpm: bid.price, + creativeId: bid.id, + width: size.width, + height: size.height, + mediaType: 'video', + currency: response.cur, + ttl: 100, + netRevenue: true + }; + if (bid.nurl) { + bidResponse.vastUrl = bid.nurl; + } else if (bid.adm) { + bidResponse.vastXml = bid.adm; + } + return bidResponse; + }, + /** + * 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) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: spec.SYNC_ENDPOINT1 + }, + { + type: 'image', + url: spec.SYNC_ENDPOINT2 + }, + { + type: 'image', + url: spec.SYNC_ENDPOINT3 + }, + { + type: 'image', + url: spec.SYNC_ENDPOINT4 + }]; + } + } +}; + +function getSize(sizes) { + let parsedSizes = utils.parseSizesInput(sizes); + let [ width, height ] = parsedSizes.length ? parsedSizes[0].split('x') : []; + return { + width: parseInt(width, 10) || undefined, + height: parseInt(height, 10) || undefined + }; +} + +function getRequestData(bid) { + let loc = utils.getTopWindowLocation(); + let global = (window.top) ? window.top : window; + let page = (bid.params.site.page) ? (bid.params.site.page) : (loc.href); + let ref = (bid.params.site.referrer) ? bid.params.site.referrer : utils.getTopWindowReferrer(); + let bidData = { + id: utils.generateUUID(), + at: 2, + cur: bid.cur || 'USD', + imp: [{ + id: '1', + secure: isSecure(), + bidfloor: bid.params.bidfloor, + video: { + mimes: bid.params.video.mimes, + w: bid.params.video.playerWidth, + h: bid.params.video.playerHeight, + linearity: 1, + protocols: bid.params.video.protocols || [2, 5] + } + }], + site: { + page: page, + ref: ref + }, + device: { + ua: global.navigator.userAgent + }, + tmax: 200 + }; + + if (bid.params.video.maxbitrate) { + bidData.imp[0].video.maxbitrate = bid.params.video.maxbitrate + } + if (bid.params.video.maxduration) { + bidData.imp[0].video.maxduration = bid.params.video.maxduration + } + if (bid.params.video.minduration) { + bidData.imp[0].video.minduration = bid.params.video.minduration + } + if (bid.params.video.api) { + bidData.imp[0].video.api = bid.params.video.api + } + if (bid.params.video.delivery) { + bidData.imp[0].video.delivery = bid.params.video.delivery + } + if (bid.params.video.position) { + bidData.imp[0].video.pos = bid.params.video.position + } + if (bid.params.site.id) { + bidData.site.id = bid.params.site.id + } + return bidData; +} + +function isSecure() { + return document.location.protocol === 'https:'; +} + +registerBidder(spec); diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md new file mode 100755 index 00000000000..96399221315 --- /dev/null +++ b/modules/oneVideoBidAdapter.md @@ -0,0 +1,47 @@ +# Overview + +**Module Name**: One Video Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: ankur.modi@oath.com + +# Description + +Connects to One Video demand source to fetch bids. + + +# Test Parameters +``` + var adUnits = [ + { + code: 'video1', + sizes: [640,480], + mediaTypes: { + video: { + context: "instream" + } + }, + bids: [ + { + bidder: 'oneVideo', + params: { + video: { + playerWidth: 480, + playerHeight: 640, + mimes: ['video/mp4', 'application/javascript'], + protocols: [2,5], + api: [2], + position: 1, + delivery: [2] + }, + site: { + id: 1, + page: 'http://abhi12345.com', + referrer: 'http://abhi12345.com' + }, + pubId: 'brxd' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js new file mode 100644 index 00000000000..3d7bba417f9 --- /dev/null +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -0,0 +1,135 @@ +import { expect } from 'chai'; +import { spec } from 'modules/oneVideoBidAdapter'; +import * as utils from 'src/utils'; + +describe('OneVideoBidAdapter', () => { + let bidRequest; + + beforeEach(() => { + bidRequest = { + bidder: 'oneVideo', + sizes: [640, 480], + bidId: '30b3efwfwe1e', + params: { + video: { + playerWidth: 640, + playerHeight: 480, + mimes: ['video/mp4', 'application/javascript'], + protocols: [2, 5], + api: [2], + position: 1, + delivery: [2] + }, + site: { + id: 1, + page: 'https://news.yahoo.com/portfolios', + referrer: 'http://www.yahoo.com' + }, + pubId: 'brxd' + } + }; + }); + + describe('spec.isBidRequestValid', () => { + it('should return true when the required params are passed', () => { + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return false when the "video" param is missing', () => { + bidRequest.params = { + pubId: 'brxd' + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + + it('should return false when the "pubId" param is missing', () => { + bidRequest.params = { + video: { + playerWidth: 480, + playerHeight: 640, + mimes: ['video/mp4', 'application/javascript'], + protocols: [2, 5], + api: [2], + position: 1, + delivery: [2] + } + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + + it('should return false when no bid params are passed', () => { + bidRequest.params = {}; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + }); + + describe('spec.buildRequests', () => { + it('should create a POST request for every bid', () => { + const requests = spec.buildRequests([ bidRequest ]); + expect(requests[0].method).to.equal('POST'); + expect(requests[0].url).to.equal(location.protocol + spec.ENDPOINT + bidRequest.params.pubId); + }); + + it('should attach the bid request object', () => { + const requests = spec.buildRequests([ bidRequest ]); + expect(requests[0].bidRequest).to.equal(bidRequest); + }); + + it('should attach request data', () => { + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + const [ width, height ] = bidRequest.sizes; + expect(data.imp[0].video.w).to.equal(width); + expect(data.imp[0].video.h).to.equal(height); + expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); + }); + + it('must parse bid size from a nested array', () => { + const width = 640; + const height = 480; + bidRequest.sizes = [[ width, height ]]; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.imp[0].video.w).to.equal(width); + expect(data.imp[0].video.h).to.equal(height); + }); + }); + + describe('spec.interpretResponse', () => { + it('should return no bids if the response is not valid', () => { + const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return no bids if the response "nurl" and "adm" are missing', () => { + const serverResponse = {seatbid: [{bid: [{price: 6.01}]}]}; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return no bids if the response "price" is missing', () => { + const serverResponse = {seatbid: [{bid: [{adm: ''}]}]}; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + expect(bidResponse.length).to.equal(0); + }); + + it('should return a valid bid response with just "adm"', () => { + const serverResponse = {seatbid: [{bid: [{id: 1, price: 6.01, adm: ''}]}], cur: 'USD'}; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + let o = { + requestId: bidRequest.bidId, + bidderCode: spec.code, + cpm: serverResponse.seatbid[0].bid[0].price, + creativeId: serverResponse.seatbid[0].bid[0].id, + vastXml: serverResponse.seatbid[0].bid[0].adm, + width: 640, + height: 480, + mediaType: 'video', + currency: 'USD', + ttl: 100, + netRevenue: true + }; + expect(bidResponse).to.deep.equal(o); + }); + }); +}); From cf1dc798d942acd806aba9c046f47013006f2efa Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 7 May 2018 09:43:25 -0400 Subject: [PATCH 0328/1594] Update babel plugins (#2447) * Update babel plugins * Targeting browsers --- .babelrc | 19 +- package-lock.json | 14902 +++++++++++++++----------------------------- package.json | 4 +- webpack.conf.js | 6 - 4 files changed, 5084 insertions(+), 9847 deletions(-) diff --git a/.babelrc b/.babelrc index b366d78478e..5d42055cabb 100644 --- a/.babelrc +++ b/.babelrc @@ -1,8 +1,19 @@ { - "presets": ["es2015"], + "presets": [ + ["env", { + "targets": { + "browsers": [ + "chrome >= 61", + "safari >=8", + "edge >= 14", + "ff >= 57", + "ie >= 10", + "ios >= 8" + ] + } + }] + ], "plugins": [ - "transform-object-assign", - "transform-es3-property-literals", - "transform-es3-member-expression-literals" + "transform-object-assign" ] } diff --git a/package-lock.json b/package-lock.json index 83511e0dc28..bd684f6406b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,131 +1,98 @@ { "name": "prebid.js", - "version": "1.8.0-pre", + "version": "1.9.0-pre", "lockfileVersion": 1, - "requires": true, "dependencies": { "@gulp-sourcemaps/identity-map": { - "version": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", - "requires": { - "acorn": "5.4.1", - "css": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - }, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, "@gulp-sourcemaps/map-sources": { - "version": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "requires": { - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=" }, "@sinonjs/formatio": { - "version": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", - "integrity": "sha1-hNt+nrVTHfGKjF4L+25EnlXmVLI=", - "dev": true, - "requires": { - "samsam": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz" - } - }, - "JSONStream": { - "version": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", - "dev": true, - "requires": { - "jsonparse": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "dev": true }, "abbrev": { - "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", "dev": true }, "accepts": { - "version": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", - "dev": true, - "requires": { - "mime-types": "2.1.17", - "negotiator": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz" - } + "dev": true }, "acorn": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", - "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==" + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==" }, "acorn-dynamic-import": { - "version": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "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": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" - }, "dependencies": { "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", "dev": true } } }, "acorn-jsx": { - "version": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, - "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz" - }, "dependencies": { "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true } } }, - "acorn-node": { - "version": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.3.0.tgz", - "integrity": "sha1-X4bXM0Z0OBDvEmm5AdvL3tAghhs=", - "dev": true, - "requires": { - "acorn": "5.4.1", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, "addressparser": { - "version": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", "dev": true, "optional": true }, "after": { - "version": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", "dev": true }, "agent-base": { - "version": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz" - }, "dependencies": { "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", "dev": true } @@ -135,70 +102,57 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", - "dev": true, - "requires": { - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" - } + "dev": true + }, + "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 }, "align-text": { - "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "longest": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - }, "dependencies": { "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true } } }, "amdefine": { - "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "amqplib": { - "version": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha1-0tcxPH/6pNELzx5iUt5FkbbMe2M=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", + "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", "dev": true, "optional": true, - "requires": { - "bitsyntax": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", - "bluebird": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "buffer-more-ints": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true, "optional": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, - "optional": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "optional": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true, "optional": true @@ -206,1585 +160,1160 @@ } }, "ansi-colors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.0.1.tgz", - "integrity": "sha512-yopkAU0ZD/WQ56Tms3xLn6jRuX3SyUMAVi0FdmDIbmmnHW3jHiI1sQFdUl3gfVddjnrsP3Y6ywFKvCRopvoVIA==", - "dev": true, - "requires": { - "ansi-wrap": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true }, "ansi-escapes": { - "version": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha1-7D6LTp+AZPwCw6ybZfHCdb2o75I=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, "ansi-gray": { - "version": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" - } + "dev": true }, "ansi-html": { - "version": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", "dev": true }, "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "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": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, "ansi-wrap": { - "version": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, "anymatch": { - "version": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", - "dev": true, - "requires": { - "micromatch": "3.1.5", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true }, "append-buffer": { - "version": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz" - } + "dev": true }, "append-transform": { - "version": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz" - } + "dev": true }, "archiver": { - "version": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "buffer-crc32": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", - "lazystream": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "tar-stream": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", - "zip-stream": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz" - }, "dependencies": { "async": { - "version": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true }, "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } + "dev": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "lazystream": { - "version": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - } + "dev": true }, "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", "dev": true }, "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - } + "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "archy": { - "version": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, - "requires": { - "sprintf-js": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" - } + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true }, "arr-diff": { - "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, "arr-flatten": { - "version": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "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 }, "arr-union": { - "version": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, "array-differ": { - "version": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", "dev": true }, "array-each": { - "version": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, - "array-filter": { - "version": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, "array-find-index": { - "version": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "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 }, "array-iterate": { - "version": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.1.tgz", - "integrity": "sha1-hlv3+K851rCYLGCQKRSsdrwBCPY=", - "dev": true - }, - "array-map": { - "version": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "array-reduce": { - "version": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", + "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", "dev": true }, "array-slice": { - "version": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true }, "array-union": { - "version": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" - } + "dev": true }, "array-uniq": { - "version": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, "array-unique": { - "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "array.from": { - "version": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", "integrity": "sha1-LGJ7G3bf8t7yNl+gUrZcPVheX2s=", "dev": true }, "arraybuffer.slice": { - "version": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, "arrify": { - "version": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "asn1": { - "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", "dev": true }, "asn1.js": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", - "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", - "dev": true, - "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - } + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true }, "assert": { - "version": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz" - } + "dev": true }, "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true }, "assertion-error": { - "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, "assign-symbols": { - "version": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, "ast-types": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.2.tgz", - "integrity": "sha512-ufWX953VU1eIuWqxS0nRDMYlGyFH+yxln5CsmIHlpzEt3fdYqUnRtsFt0XAsQot8OaVCwFqxT1RiwvtzYjeYeg==", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", + "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==", "dev": true }, - "astw": { - "version": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", - "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", - "dev": true, - "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" - }, - "dependencies": { - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - } - } - }, "async": { - "version": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "async-each": { - "version": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, "async-limiter": { - "version": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", "dev": true }, "asynckit": { - "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, "atob": { - "version": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=" }, "aws-sign2": { - "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", "dev": true }, "aws4": { - "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", "dev": true }, "axios": { - "version": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", "dev": true, "optional": true, - "requires": { - "follow-redirects": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz" + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true + }, + "follow-redirects": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", + "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", + "dev": true, + "optional": true + } } }, "babel-code-frame": { - "version": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "js-tokens": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz" - } + "dev": true }, "babel-core": { - "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", "dev": true, - "requires": { - "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "babel-helpers": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "babel-register": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "babel-generator": { - "version": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha1-GERAjTuPDTWkBOp6wYDwh6YBvZA=", - "dev": true, - "requires": { - "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "detect-indent": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "jsesc": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "trim-right": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz" - }, + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "babel-helper-bindify-decorators": { - "version": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-builder-react-jsx": { - "version": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" - } + "dev": true }, "babel-helper-call-delegate": { - "version": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-define-map": { - "version": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } + "dev": true }, "babel-helper-explode-assignable-expression": { - "version": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-explode-class": { - "version": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-function-name": { - "version": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-get-function-arity": { - "version": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-hoist-variables": { - "version": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-optimise-call-expression": { - "version": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-regex": { - "version": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } + "dev": true }, "babel-helper-remap-async-to-generator": { - "version": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helper-replace-supers": { - "version": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-helpers": { - "version": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "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": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" - } + "dev": true }, "babel-loader": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.2.tgz", - "integrity": "sha512-jRwlFbINAeyDStqK6Dd5YuY0k5YuzQUvlz2ZamuXrXmxav3pNqe9vfJ402+2G+OmlJSXxCOpB6Uz0INM7RQe2A==", - "dev": true, - "requires": { - "find-cache-dir": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" - } + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", + "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", + "dev": true }, "babel-messages": { - "version": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "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": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-check-es2015-constants": { - "version": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-syntax-async-functions": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", "dev": true }, "babel-plugin-syntax-async-generators": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", "dev": true }, "babel-plugin-syntax-class-constructor-call": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", "dev": true }, "babel-plugin-syntax-class-properties": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", "dev": true }, "babel-plugin-syntax-decorators": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", "dev": true }, "babel-plugin-syntax-do-expressions": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", "dev": true }, "babel-plugin-syntax-dynamic-import": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", "dev": true }, "babel-plugin-syntax-exponentiation-operator": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", "dev": true }, "babel-plugin-syntax-export-extensions": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", "dev": true }, "babel-plugin-syntax-flow": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", "dev": true }, "babel-plugin-syntax-function-bind": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", "dev": true }, "babel-plugin-syntax-jsx": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", "dev": true }, "babel-plugin-syntax-object-rest-spread": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", "dev": true }, "babel-plugin-syntax-trailing-function-commas": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", "dev": true }, "babel-plugin-system-import-transformer": { - "version": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz" - } + "dev": true }, "babel-plugin-transform-async-generator-functions": { - "version": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "babel-plugin-syntax-async-generators": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-async-to-generator": { - "version": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "babel-plugin-syntax-async-functions": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-class-constructor-call": { - "version": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, - "requires": { - "babel-plugin-syntax-class-constructor-call": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-class-properties": { - "version": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "babel-plugin-syntax-class-properties": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-decorators": { - "version": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "babel-plugin-syntax-decorators": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-decorators-legacy": { - "version": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", "integrity": "sha1-dBtY9sW86eYCfgiC2cmU8E82aSU=", - "dev": true, - "requires": { - "babel-plugin-syntax-decorators": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-do-expressions": { - "version": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true, - "requires": { - "babel-plugin-syntax-do-expressions": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-arrow-functions": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-block-scoping": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-classes": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "babel-helper-optimise-call-expression": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "babel-helper-replace-supers": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-computed-properties": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-destructuring": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-duplicate-keys": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-for-of": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-function-name": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-literals": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-modules-amd": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-modules-commonjs": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-modules-systemjs": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-modules-umd": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-object-super": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-parameters": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "babel-helper-get-function-arity": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-shorthand-properties": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-spread": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-sticky-regex": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-template-literals": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-typeof-symbol": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-es2015-unicode-regex": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "regexpu-core": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz" - } - }, - "babel-plugin-transform-es3-member-expression-literals": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz", - "integrity": "sha1-cz00RPPsxBvvjtGmpOCWV7iWnrs=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } - }, - "babel-plugin-transform-es3-property-literals": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz", - "integrity": "sha1-sgeNWELiKr9A9z6M3pzTcRq9V1g=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-exponentiation-operator": { - "version": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "babel-plugin-syntax-exponentiation-operator": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-export-extensions": { - "version": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, - "requires": { - "babel-plugin-syntax-export-extensions": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-flow-strip-types": { - "version": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-function-bind": { - "version": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true, - "requires": { - "babel-plugin-syntax-function-bind": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-object-assign": { - "version": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", - "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "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=" }, "babel-plugin-transform-object-rest-spread": { - "version": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-react-display-name": { - "version": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-react-jsx": { - "version": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "babel-plugin-syntax-jsx": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-react-jsx-self": { - "version": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-react-jsx-source": { - "version": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" - } + "dev": true }, "babel-plugin-transform-regenerator": { - "version": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz" - } + "dev": true }, "babel-plugin-transform-strict-mode": { - "version": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" - } + "dev": true }, "babel-preset-env": { - "version": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", - "integrity": "sha1-oYtWTMm5r99KrleuPBsNmRiOb0g=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "babel-plugin-syntax-trailing-function-commas": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "babel-plugin-transform-async-to-generator": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "babel-plugin-transform-es2015-arrow-functions": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "babel-plugin-transform-es2015-block-scoped-functions": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "babel-plugin-transform-es2015-block-scoping": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "babel-plugin-transform-es2015-classes": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "babel-plugin-transform-es2015-computed-properties": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "babel-plugin-transform-es2015-destructuring": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "babel-plugin-transform-es2015-duplicate-keys": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "babel-plugin-transform-es2015-for-of": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "babel-plugin-transform-es2015-function-name": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "babel-plugin-transform-es2015-literals": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "babel-plugin-transform-es2015-modules-amd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "babel-plugin-transform-es2015-modules-commonjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "babel-plugin-transform-es2015-modules-systemjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "babel-plugin-transform-es2015-modules-umd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "babel-plugin-transform-es2015-object-super": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "babel-plugin-transform-es2015-parameters": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "babel-plugin-transform-es2015-shorthand-properties": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "babel-plugin-transform-es2015-spread": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "babel-plugin-transform-es2015-sticky-regex": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "babel-plugin-transform-es2015-template-literals": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "babel-plugin-transform-es2015-typeof-symbol": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "babel-plugin-transform-es2015-unicode-regex": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "babel-plugin-transform-exponentiation-operator": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "babel-plugin-transform-regenerator": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "browserslist": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "invariant": "2.2.2", - "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz" - } - }, - "babel-preset-es2015": { - "version": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz", - "integrity": "sha1-r1qY7LNeuK92StiloF6zbcQ4aDU=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "babel-plugin-transform-es2015-arrow-functions": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "babel-plugin-transform-es2015-block-scoped-functions": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "babel-plugin-transform-es2015-block-scoping": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "babel-plugin-transform-es2015-classes": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "babel-plugin-transform-es2015-computed-properties": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "babel-plugin-transform-es2015-destructuring": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "babel-plugin-transform-es2015-duplicate-keys": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "babel-plugin-transform-es2015-for-of": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "babel-plugin-transform-es2015-function-name": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "babel-plugin-transform-es2015-literals": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "babel-plugin-transform-es2015-modules-amd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "babel-plugin-transform-es2015-modules-commonjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "babel-plugin-transform-es2015-modules-systemjs": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "babel-plugin-transform-es2015-modules-umd": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "babel-plugin-transform-es2015-object-super": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "babel-plugin-transform-es2015-parameters": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "babel-plugin-transform-es2015-shorthand-properties": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "babel-plugin-transform-es2015-spread": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "babel-plugin-transform-es2015-sticky-regex": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "babel-plugin-transform-es2015-template-literals": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "babel-plugin-transform-es2015-typeof-symbol": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "babel-plugin-transform-es2015-unicode-regex": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "babel-plugin-transform-regenerator": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz" - } + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "dev": true }, "babel-preset-flow": { - "version": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz" - } + "dev": true }, "babel-preset-react": { - "version": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "babel-plugin-transform-react-display-name": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "babel-plugin-transform-react-jsx": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "babel-plugin-transform-react-jsx-self": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "babel-plugin-transform-react-jsx-source": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "babel-preset-flow": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz" - } + "dev": true }, "babel-preset-stage-0": { - "version": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true, - "requires": { - "babel-plugin-transform-do-expressions": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", - "babel-plugin-transform-function-bind": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", - "babel-preset-stage-1": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz" - } + "dev": true }, "babel-preset-stage-1": { - "version": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, - "requires": { - "babel-plugin-transform-class-constructor-call": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", - "babel-plugin-transform-export-extensions": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", - "babel-preset-stage-2": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz" - } + "dev": true }, "babel-preset-stage-2": { - "version": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "babel-plugin-transform-class-properties": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "babel-plugin-transform-decorators": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "babel-preset-stage-3": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz" - } + "dev": true }, "babel-preset-stage-3": { - "version": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "babel-plugin-transform-async-generator-functions": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "babel-plugin-transform-async-to-generator": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "babel-plugin-transform-exponentiation-operator": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "babel-plugin-transform-object-rest-spread": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz" - } + "dev": true }, "babel-register": { - "version": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "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": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "core-js": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "home-or-tmp": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "source-map-support": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz" - }, "dependencies": { "babel-core": { - "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true, - "requires": { - "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "babel-helpers": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "babel-register": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - } + "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "babel-runtime": { - "version": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "regenerator-runtime": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz" - } + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=" }, "babel-template": { - "version": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "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": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } + "dev": true }, "babel-traverse": { - "version": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "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": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "globals": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "invariant": "2.2.2", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true } } }, "babel-types": { - "version": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "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": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "to-fast-properties": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz" - } + "dev": true }, "babelify": { - "version": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", - "integrity": "sha1-b2D18GK/52lXVO8kA7hCAUpYDtM=", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", + "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw==", "dev": true }, "babylon": { - "version": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, "backo2": { - "version": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", "dev": true }, "bail": { - "version": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", - "integrity": "sha1-99bBcxYwqfnw1NNe0fli4gdKF2Q=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", "dev": true }, "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "base": { - "version": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, - "requires": { - "cache-base": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "class-utils": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "define-property": "1.0.0", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "mixin-deep": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "pascalcase": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" + "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 + }, + "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 + }, + "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 + }, + "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 + } } }, "base64-arraybuffer": { - "version": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", "dev": true }, "base64-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, "base64-url": { - "version": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", "dev": true }, "base64id": { - "version": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", "dev": true }, "basic-auth": { - "version": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", "dev": true }, "basic-auth-connect": { - "version": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", "dev": true }, "batch": { - "version": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", "dev": true }, "bcrypt-pbkdf": { - "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "dev": true, - "optional": true, - "requires": { - "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" - } + "optional": true }, "beeper": { - "version": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", "dev": true }, "better-assert": { - "version": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" - } + "dev": true }, "big.js": { - "version": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=", + "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": { - "version": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "chainsaw": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz" - } + "dev": true }, "binary-extensions": { - "version": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, "binaryextensions": { - "version": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", "dev": true }, "bitsyntax": { - "version": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", "dev": true, - "optional": true, - "requires": { - "buffer-more-ints": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz" - } + "optional": true }, "bl": { - "version": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "blob": { - "version": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", "dev": true }, "block-loader": { - "version": "https://registry.npmjs.org/block-loader/-/block-loader-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/block-loader/-/block-loader-2.1.0.tgz", "integrity": "sha1-u7OYrVqEPGxx95opb0tt9LAlcxI=", "dev": true }, "bluebird": { - "version": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", "dev": true }, "bn.js": { - "version": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "body": { - "version": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true, - "requires": { - "continuable-cache": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "error": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", - "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "safe-json-parse": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz" - } + "dev": true }, "body-parser": { - "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "type-is": "1.6.15" - }, "dependencies": { "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", "dev": true }, "raw-body": { - "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, "dependencies": { "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", "dev": true }, "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true } @@ -1793,1989 +1322,1380 @@ } }, "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" - } + "dev": true }, "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", - "dev": true, - "requires": { - "balanced-match": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "concat-map": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - } + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true }, "braces": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", - "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==", - "dev": true, - "requires": { - "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fill-range": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "snapdragon-node": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "split-string": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "to-regex": "3.0.1" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "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 + } } }, "brorand": { - "version": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, - "browser-pack": { - "version": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.4.tgz", - "integrity": "sha1-mnO+s7SPnjaGi+AHtkQAECwEqZ8=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "combine-source-map": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "umd": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz" - } - }, "browser-resolve": { - "version": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", "dev": true, - "requires": { - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" - }, "dependencies": { "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true } } }, "browser-stdout": { - "version": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", "dev": true }, - "browserify": { - "version": "https://registry.npmjs.org/browserify/-/browserify-14.5.0.tgz", - "integrity": "sha1-C7vOUhrNbk0dVNjpNlAI77hanMU=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "assert": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "browser-pack": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.4.tgz", - "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "buffer": "5.0.8", - "cached-path-relative": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "deps-sort": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", - "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "has": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "htmlescape": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "insert-module-globals": "7.0.1", - "labeled-stream-splicer": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", - "module-deps": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", - "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "read-only-stream": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "shasum": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "shell-quote": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "syntax-error": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - }, - "dependencies": { - "concat-stream": { - "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" - }, - "dependencies": { - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "module-deps": { - "version": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", - "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "cached-path-relative": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "detective": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "stream-combiner2": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, - "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "url": { - "version": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" - }, - "dependencies": { - "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - } - } - }, "browserify-aes": { - "version": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "integrity": "sha1-OLerVe24Bv8tzaGn8WIHc6R3xJ8=", - "dev": true, - "requires": { - "buffer-xor": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true }, "browserify-cipher": { - "version": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", - "dev": true, - "requires": { - "browserify-aes": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "browserify-des": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" - } + "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 }, "browserify-des": { - "version": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", - "dev": true, - "requires": { - "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "des.js": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", + "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", + "dev": true }, "browserify-rsa": { - "version": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz" - } + "dev": true }, "browserify-sign": { - "version": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "browserify-rsa": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "elliptic": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "parse-asn1": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz" - } + "dev": true }, "browserify-zlib": { - "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", - "dev": true, - "requires": { - "pako": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz" - } + "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 }, "browserslist": { - "version": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha1-/jYWeu0bvN5IJ+v+cTR6LMcLmbI=", - "dev": true, - "requires": { - "caniuse-lite": "1.0.30000808", - "electron-to-chromium": "1.3.33" - } + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true }, "browserstack": { - "version": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", - "dev": true, - "requires": { - "https-proxy-agent": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz" - } + "dev": true }, "browserstacktunnel-wrapper": { - "version": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.1.tgz", - "integrity": "sha1-/+GRDW45/oZhgYPoJmkAQa9T7a4=", - "dev": true, - "requires": { - "https-proxy-agent": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "unzip": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz" - } + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.2.tgz", + "integrity": "sha512-7w7HYA00qjBtuQH0c5rqW7RbWPHyRROqTZofwNp5G0sKc2fYChsTfbHz3ul8Yd+ffkQvR81m+iPjEB004P6kxQ==", + "dev": true }, "buffer": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", - "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==", - "dev": true, - "requires": { - "base64-js": "1.2.1", - "ieee754": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz" - } + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true }, "buffer-crc32": { - "version": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, "buffer-equal": { - "version": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", "dev": true }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, "buffer-more-ints": { - "version": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", "dev": true }, "buffer-shims": { - "version": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, "buffer-xor": { - "version": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, "buffers": { - "version": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", "dev": true }, "buildmail": { - "version": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", "dev": true, - "optional": true, - "requires": { - "addressparser": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "libbase64": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "libmime": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "libqp": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "nodemailer-fetch": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" - } + "optional": true }, "builtin-modules": { - "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, "builtin-status-codes": { - "version": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "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": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, "cache-base": { - "version": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", - "dev": true, - "requires": { - "collection-visit": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "has-value": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "set-value": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "union-value": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "unset-value": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" - } - }, - "cached-path-relative": { - "version": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", - "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true }, "caller-path": { - "version": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz" - } + "dev": true }, "callsite": { - "version": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", "dev": true }, "callsites": { - "version": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "camelcase-keys": { - "version": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "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": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "map-obj": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" - }, "dependencies": { "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true } } }, "caniuse-lite": { - "version": "1.0.30000808", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000808.tgz", - "integrity": "sha512-vT0JLmHdvq1UVbYXioxCXHYdNw55tyvi+IUWyX0Zeh1OFQi2IllYtm38IJnSgHWCv/zUnX1hdhy3vMJvuTNSqw==", + "version": "1.0.30000830", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000830.tgz", + "integrity": "sha512-yMqGkujkoOIZfvOYiWdqPALgY/PVGiqCHUJb6yNq7xhI/pR+gQO0U2K6lRDqAiJv4+CIU3CtTLblNGw0QGnr6g==", "dev": true }, "caseless": { - "version": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true }, "ccount": { - "version": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", - "integrity": "sha1-U7ai+BW7d7nChx97mnLDol8djok=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", "dev": true }, "center-align": { - "version": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "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": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "lazy-cache": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz" - }, - "dependencies": { - "lazy-cache": { - "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - } - } + "dev": true }, "chai": { - "version": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "deep-eql": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz" - } + "dev": true }, "chai-nightwatch": { - "version": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", "dev": true, - "requires": { - "assertion-error": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", - "deep-eql": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz" - }, "dependencies": { "assertion-error": { - "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", "dev": true } } }, "chainsaw": { - "version": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" - } + "dev": true }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "has-ansi": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" - } + "dev": true }, "character-entities": { - "version": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", - "integrity": "sha1-92hxvl72bdt/j440eOzDdMJ9bco=", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", "dev": true }, "character-entities-html4": { - "version": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.1.tgz", - "integrity": "sha1-NZoqSg9+KdPcKsmb2+Ie45Q46lA=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", + "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", "dev": true }, "character-entities-legacy": { - "version": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", - "integrity": "sha1-9Ad53xoQGHK7UQo9KV4fzPFHIC8=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", "dev": true }, "character-reference-invalid": { - "version": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", - "integrity": "sha1-lCg191Dk7GGjCOYMLvjMEBEgLvw=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", "dev": true }, "chardet": { - "version": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, "chokidar": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.1.tgz", - "integrity": "sha512-rv5iP8ENhpqvDWr677rAXcB+SMoPQ1urd4ch79+PhM4lQwbATdJUQK69t0lJIKNB+VXpqxt5V1gvqs59XEPKnw==", - "dev": true, - "requires": { - "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "braces": "2.3.0", - "fsevents": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "upath": "1.0.0" - } + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", + "dev": true }, "cipher-base": { - "version": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } + "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 }, "circular-json": { - "version": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, "class-utils": { - "version": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "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, - "requires": { - "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "static-extend": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" - }, "dependencies": { "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "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": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-accessor-descriptor": { - "version": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-data-descriptor": { - "version": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } }, "cli-cursor": { - "version": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "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, - "requires": { - "restore-cursor": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz" - } + "dev": true }, "cli-width": { - "version": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, "cliui": { - "version": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "wrap-ansi": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz" - } + "dev": true }, "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, "clone-buffer": { - "version": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", "dev": true }, "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "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 }, "cloneable-readable": { - "version": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - }, - "dependencies": { - "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - } - } + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true }, "co": { - "version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "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 }, "collapse-white-space": { - "version": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", - "integrity": "sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", "dev": true }, "collection-visit": { - "version": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "object-visit": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" - } + "dev": true }, "color-convert": { - "version": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", - "dev": true, - "requires": { - "color-name": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - } + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true }, "color-name": { - "version": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "color-support": { - "version": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", + "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 }, "colors": { - "version": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz", + "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==", "dev": true }, "combine-lists": { - "version": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } - }, - "combine-source-map": { - "version": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", - "dev": true, - "requires": { - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "inline-source-map": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "lodash.memoize": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - }, - "dependencies": { - "convert-source-map": { - "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", - "dev": true - }, - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } + "dev": true }, "combined-stream": { - "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, - "requires": { - "delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - } + "dev": true }, "comma-separated-tokens": { - "version": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.4.tgz", - "integrity": "sha1-cgg+WNSkYvAYZvZhf02Yo807ikY=", - "dev": true, - "requires": { - "trim": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" - } + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", + "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", + "dev": true }, "commander": { - "version": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", - "integrity": "sha1-IjUSPjevjKPGXfRbAm29NXsBuao=", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, "commondir": { - "version": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-versions": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.1.0.tgz", + "integrity": "sha512-4hAxDSBypT/yp2ySFD346So6Ragw5xmBn/e/agIGl3bZr6DLUqnoRZPusxKrXdYRZpgexO9daejmIenlq/wrIQ==", + "dev": true + }, "component-bind": { - "version": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", "dev": true }, "component-emitter": { - "version": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, "component-inherit": { - "version": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", "dev": true }, "compress-commons": { - "version": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", "dev": true, - "requires": { - "buffer-crc32": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "crc32-stream": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", - "node-int64": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "compressible": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", - "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", + "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", + "dev": true }, "compression": { - "version": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/compression/-/compression-1.5.2.tgz", "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", "dev": true, - "requires": { - "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "compressible": "2.0.12", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "vary": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz" - }, "dependencies": { "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "concat-map": { - "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "concat-stream": { - "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" - } + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true }, "concat-with-sourcemaps": { - "version": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", - "integrity": "sha1-iWS8I0fQWBm2N5gQTYfW4AG+2NA=", - "dev": true, - "requires": { - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - } + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", + "integrity": "sha512-YtnS0VEY+e2Khzsey/6mra9EoM6h/5gxaC0e3mcHpA5yfDxafhygytNmcJWodvUgyXzSiL5MSkPO6bQGgfliHw==", + "dev": true }, "connect": { - "version": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", "dev": true, - "requires": { - "basic-auth-connect": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "body-parser": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "compression": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", - "connect-timeout": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", - "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "cookie-parser": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", - "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "csurf": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "errorhandler": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", - "express-session": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", - "finalhandler": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", - "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "method-override": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", - "morgan": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", - "multiparty": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "pause": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "response-time": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", - "serve-favicon": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", - "serve-index": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", - "serve-static": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", - "type-is": "1.6.15", - "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "vhost": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz" - }, "dependencies": { "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", "dev": true } } }, "connect-livereload": { - "version": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", "dev": true }, "connect-timeout": { - "version": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "console-browserify": { - "version": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz" - } + "dev": true }, "constants-browserify": { - "version": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, "contains-path": { - "version": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, "content-type": { - "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true }, "continuable-cache": { - "version": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", "dev": true }, "convert-source-map": { - "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" }, "cookie": { - "version": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", "dev": true }, "cookie-parser": { - "version": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", - "dev": true, - "requires": { - "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - } + "dev": true }, "cookie-signature": { - "version": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, "copy-descriptor": { - "version": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, "core-js": { - "version": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", + "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=" }, "core-util-is": { - "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "coveralls": { - "version": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha1-mtfCrlJ0F/Nh6LYmSD9I7pLdK8c=", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", + "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", "dev": true, - "requires": { - "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "lcov-parse": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "log-driver": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "request": "https://registry.npmjs.org/request/-/request-2.79.0.tgz" - }, "dependencies": { "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "crc": { - "version": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", "dev": true }, "crc32-stream": { - "version": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", "dev": true, - "requires": { - "buffer-crc32": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "create-ecdh": { - "version": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", - "dev": true, - "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "elliptic": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz" - } + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.1.tgz", + "integrity": "sha512-iZvCCg8XqHQZ1ioNBTzXS/cQSkqkqcPs8xSX4upNB+DAk9Ht3uzQf2J32uAHNCne8LDmKr29AgZrEs4oIrwLuQ==", + "dev": true }, "create-hash": { - "version": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "dev": true, - "requires": { - "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz" - } + "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 }, "create-hmac": { - "version": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "dev": true, - "requires": { - "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz" - } + "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 }, "cross-spawn": { - "version": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "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": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "shebang-command": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" - } + "dev": true }, "cryptiles": { - "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" - } + "dev": true }, "crypto-browserify": { - "version": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", - "dev": true, - "requires": { - "browserify-cipher": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "browserify-sign": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "create-ecdh": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "diffie-hellman": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "pbkdf2": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "public-encrypt": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "randomfill": "1.0.3" - } + "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 }, "csrf": { - "version": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", - "dev": true, - "requires": { - "rndm": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "tsscmp": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", - "uid-safe": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz" - } + "dev": true }, "css": { - "version": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "source-map-resolve": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "urix": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" - }, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "requires": { - "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" - } + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=" } } }, "css-loader": { - "version": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", "dev": true, "optional": true, - "requires": { - "csso": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz" - }, "dependencies": { "loader-utils": { - "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, - "optional": true, - "requires": { - "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "optional": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, - "optional": true, - "requires": { - "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" - } + "optional": true } } }, "css-parse": { - "version": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true, - "requires": { - "css": "https://registry.npmjs.org/css/-/css-2.2.1.tgz" - } + "dev": true }, "css-value": { - "version": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", "dev": true }, "csso": { - "version": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", + "version": "1.3.12", + "resolved": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", "integrity": "sha1-/GKGlKLTiTiqrEmWdTIY/TEc254=", "dev": true, "optional": true }, "csurf": { - "version": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", - "dev": true, - "requires": { - "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "csrf": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz" - } + "dev": true }, "ctype": { - "version": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", "dev": true }, "currently-unhandled": { - "version": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "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": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz" - } + "dev": true }, "custom-event": { - "version": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, "d": { - "version": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "0.10.38" - } + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=" + }, + "dargs": { + "version": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", + "dev": true }, "dashdash": { - "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - }, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "data-uri-to-buffer": { - "version": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha1-dxY+qcINhkG0cH6PGKvfmnjzSDU=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", "dev": true }, "date-format": { - "version": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, "date-now": { - "version": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, "dateformat": { - "version": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==" }, "debug-fabulous": { - "version": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", - "integrity": "sha1-V/ZkhkYJexsISdzaABc2LB7AD4s=", - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "memoizee": "0.4.11", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==" }, "decamelize": { - "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decode-uri-component": { - "version": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "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 }, "deep-eql": { - "version": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", "dev": true, - "requires": { - "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz" - }, "dependencies": { "type-detect": { - "version": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", "dev": true } } }, "deep-is": { - "version": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "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": { - "version": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", "dev": true }, "default-require-extensions": { - "version": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, - "requires": { - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" - }, "dependencies": { "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "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": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } + "dev": true } } }, "defaults": { - "version": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz" - }, "dependencies": { "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true } } }, "define-properties": { - "version": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "object-keys": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz" - } + "dev": true }, "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, - "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" + "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 + }, + "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 + }, + "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 + } } }, "defined": { - "version": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, "degenerator": { - "version": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", "dev": true, - "requires": { - "ast-types": "0.10.2", - "escodegen": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "esprima": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz" - }, "dependencies": { "esprima": { - "version": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true } } }, "del": { - "version": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, - "requires": { - "globby": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "is-path-cwd": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "is-path-in-cwd": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" - }, "dependencies": { "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "delayed-stream": { - "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", "dev": true }, "deprecated": { - "version": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", "dev": true }, - "deps-sort": { - "version": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", - "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "shasum": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } - }, "des.js": { - "version": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - } + "dev": true }, "destroy": { - "version": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, "detab": { - "version": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", - "integrity": "sha1-Ux9eMmYg4v1PAyZKkF+zvMivTfQ=", - "dev": true, - "requires": { - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", + "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", + "dev": true }, "detect-file": { - "version": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, "detect-indent": { - "version": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" - } + "dev": true }, "detect-newline": { - "version": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" }, "detective": { - "version": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "integrity": "sha1-DspzFDOEQv67bWXaVMELscgrJG4=", - "dev": true, - "requires": { - "acorn": "5.4.1", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz" - } + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true }, "di": { - "version": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", "dev": true }, "diff": { - "version": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", "dev": true }, "diffie-hellman": { - "version": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", - "dev": true, - "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "miller-rabin": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz" - } + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true }, "disparity": { - "version": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "diff": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz" - } + "dev": true }, "doctrine": { - "version": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - } + "dev": true }, "doctrine-temporary-fork": { - "version": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", + "version": "2.0.0-alpha-allowarrayindex", + "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true, - "requires": { - "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - } + "dev": true }, "documentation": { - "version": "https://registry.npmjs.org/documentation/-/documentation-5.4.0.tgz", - "integrity": "sha1-SQBqjKRE6DXwOpkP6MOT4Vy0+FM=", - "dev": true, - "requires": { - "ansi-html": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "babel-core": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "babel-plugin-system-import-transformer": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", - "babel-plugin-transform-decorators-legacy": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", - "babel-preset-env": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", - "babel-preset-react": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "babel-preset-stage-0": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "babelify": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", - "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "chokidar": "2.0.1", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "disparity": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", - "doctrine-temporary-fork": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", - "get-port": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "git-url-parse": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.1.0.tgz", - "github-slugger": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "globals-docs": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", - "highlight.js": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", - "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "mdast-util-inject": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", - "micromatch": "3.1.5", - "mime": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", - "module-deps-sortable": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", - "parse-filepath": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "remark": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", - "remark-html": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", - "remark-toc": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", - "remote-origin-url": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", - "shelljs": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", - "stream-array": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", - "strip-json-comments": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "tiny-lr": "1.1.0", - "unist-builder": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", - "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", - "vfile": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "vfile-reporter": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", - "vfile-sort": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.0.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz" - }, + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", + "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", + "dev": true, "dependencies": { "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", - "dev": true, - "requires": { - "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" - } + "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 }, "babel-core": { - "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true, - "requires": { - "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "babel-helpers": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "babel-register": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - } + "dev": true }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" - } + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "esprima": { - "version": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "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 }, "js-yaml": { - "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz" - } + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "dev": true }, "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" - }, "dependencies": { "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "parse-json": { - "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "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": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" - } + "dev": true }, "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, - "requires": { - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" - }, "dependencies": { "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "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": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "path-type": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz" - } + "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", - "dev": true, - "requires": { - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" - } + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" - } + "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - } + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, - "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "get-caller-file": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "require-directory": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "require-main-filename": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "which-module": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "yargs-parser": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz" - }, "dependencies": { "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "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": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz" - } + "dev": true } } } } }, "dom-serialize": { - "version": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "ent": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "void-elements": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz" - } + "dev": true }, "domain-browser": { - "version": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "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 }, "double-ended-queue": { - "version": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", "dev": true, "optional": true }, "duplexer": { - "version": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, "duplexer2": { - "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "dev": true }, "duplexify": { - "version": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", - "integrity": "sha1-i1gYgA35L9ASWyeriWSRkShYJD4=", - "dev": true, - "requires": { - "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "stream-shift": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz" - } + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", + "dev": true }, "ecc-jsbn": { - "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "dev": true, - "optional": true, - "requires": { - "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" - } + "optional": true }, "ee-first": { - "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, "ejs": { - "version": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", + "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", "dev": true }, "electron-to-chromium": { - "version": "1.3.33", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.33.tgz", - "integrity": "sha1-vwBwPWKnxlI4E2V4w1LWxcBCpUU=", + "version": "1.3.42", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz", + "integrity": "sha1-lcM78B0MxAVVauyJn+Yf1NduoPk=", "dev": true }, "elliptic": { - "version": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true, - "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "brorand": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "hash.js": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "hmac-drbg": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "minimalistic-crypto-utils": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" - } + "dev": true }, "emoji-regex": { - "version": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", "dev": true }, "emojis-list": { - "version": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, "encodeurl": { - "version": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, "end-of-stream": { - "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", - "dev": true, - "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true }, "engine.io": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.4.tgz", - "integrity": "sha1-PQIRtwpVLOhB/8fahiezAamkFi4=", - "dev": true, - "requires": { - "accepts": "1.3.3", - "base64id": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "cookie": "0.3.1", - "debug": "2.6.9", - "engine.io-parser": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "uws": "0.14.5", - "ws": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz" - }, + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", + "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", + "dev": true, "dependencies": { "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", - "dev": true, - "requires": { - "mime-types": "2.1.17", - "negotiator": "0.6.1" - } + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true }, "cookie": { "version": "0.3.1", @@ -3783,15 +2703,6 @@ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", "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": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -3801,284 +2712,155 @@ } }, "engine.io-client": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.4.tgz", - "integrity": "sha1-T88TcLRxY70s6b4nM5ckMDUNTqE=", - "dev": true, - "requires": { - "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "component-inherit": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "debug": "2.6.9", - "engine.io-parser": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "has-cors": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "indexof": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "parseqs": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "parseuri": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "ws": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "xmlhttprequest-ssl": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "yeast": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz" - }, - "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": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - } - } + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", + "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", + "dev": true }, "engine.io-parser": { - "version": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha1-TA9M/3mq7su9z96maoI8YIVAkZY=", - "dev": true, - "requires": { - "after": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "arraybuffer.slice": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "base64-arraybuffer": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "blob": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "has-binary2": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz" - } + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "dev": true }, "enhanced-resolve": { - "version": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz" - } + "dev": true }, "ent": { - "version": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", "dev": true }, "errno": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", - "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", - "dev": true, - "requires": { - "prr": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" - } + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true }, "error": { - "version": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true, - "requires": { - "string-template": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "dev": true }, "error-ex": { - "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, - "requires": { - "is-arrayish": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" - } + "dev": true }, "errorhandler": { - "version": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", "dev": true, - "requires": { - "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - }, "dependencies": { "accepts": { - "version": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", - "dev": true, - "requires": { - "mime-types": "2.1.17", - "negotiator": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" - } + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true }, "negotiator": { - "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true } } }, "es5-ext": { - "version": "0.10.38", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", - "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", - "requires": { - "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" - } + "version": "0.10.42", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.42.tgz", + "integrity": "sha512-AJxO1rmPe1bDEfSR6TJ/FgMFYuTBhR5R57KW58iCkYACMyFbrkqVyzXSurYoScDGvgyMpk7uRF/lPUPPTmsRSA==" }, "es5-shim": { - "version": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", - "integrity": "sha1-t+F+9N8qFFuCHxSXtQwlz5QCYgU=", + "version": "4.5.10", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", + "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==", "dev": true }, "es6-iterator": { - "version": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "0.10.38", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" - } + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=" }, "es6-map": { - "version": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "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": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "0.10.38", - "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "es6-set": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "event-emitter": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" - } + "dev": true }, "es6-set": { - "version": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "0.10.38", - "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "event-emitter": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" - } + "dev": true }, "es6-symbol": { - "version": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "0.10.38" - } + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=" }, "es6-weak-map": { - "version": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "0.10.38", - "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" - } + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=" }, "escape-html": { - "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", "dev": true }, "escape-string-regexp": { - "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "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 }, "escodegen": { - "version": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, - "requires": { - "esprima": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "optionator": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz" - }, "dependencies": { "estraverse": { - "version": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, - "optional": true, - "requires": { - "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" - } + "optional": true } } }, "escope": { - "version": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "es6-weak-map": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "esrecurse": "4.2.0", - "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz" - } + "dev": true }, "eslint": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz", - "integrity": "sha512-AyxBUCANU/o/xC0ijGMKavo5Ls3oK6xykiOITlMdjFjrKOsqLrA7Nf5cnrDgcKrHzBirclAZt63XO7YZlVUPwA==", - "dev": true, - "requires": { - "ajv": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "cross-spawn": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "doctrine": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "eslint-scope": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "eslint-visitor-keys": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "espree": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", - "esquery": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "file-entry-cache": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "functional-red-black-tree": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "globals": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", - "ignore": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "imurmurhash": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "inquirer": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "is-resolvable": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "json-stable-stringify-without-jsonify": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "levn": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "natural-compare": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "optionator": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "path-is-inside": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "pluralize": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "progress": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "require-uncached": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "strip-ansi": "4.0.0", - "strip-json-comments": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "table": "4.0.2", - "text-table": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - }, + "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": { - "version": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" - } + "dev": true }, "ansi-regex": { "version": "3.0.0", @@ -4087,192 +2869,136 @@ "dev": true }, "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", - "dev": true, - "requires": { - "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" - } + "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 }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" - } + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true }, "doctrine": { - "version": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", - "dev": true, - "requires": { - "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" - } + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true }, "esprima": { - "version": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, "globals": { - "version": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", - "integrity": "sha1-4E/be5eW2K2snI9kwUg3sjEzeLA=", + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.4.0.tgz", + "integrity": "sha512-Dyzmifil8n/TmSqYDEXbm+C8yitzJQqQIlJQLNRMwa+BOUJpRC19pyVeN12JAjt61xonvXjtff+hJruTRXn5HA==", "dev": true }, "js-yaml": { - "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz" - } + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "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": { - "ansi-regex": "3.0.0" - } + "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - } + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true } } }, "eslint-config-standard": { - "version": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", "dev": true }, "eslint-import-resolver-node": { - "version": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha1-WPFfuDm40FdsqYBBNHaqskcttmo=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true } } }, "eslint-module-utils": { - "version": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", - "integrity": "sha1-q67IJBd2E7ipWymWOeG2+s9HNEk=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "pkg-dir": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "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": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "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": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "pkg-dir": { - "version": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz" - } + "dev": true } } }, "eslint-plugin-import": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", - "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", - "dev": true, - "requires": { - "builtin-modules": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "contains-path": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "doctrine": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "eslint-import-resolver-node": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "eslint-module-utils": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", - "has": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "lodash.cond": "4.5.2", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "read-pkg-up": "2.0.0" - }, + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.11.0.tgz", + "integrity": "sha1-Fa7qN6Z0mdhI6OmBgG1GJ7VQOBY=", + "dev": true, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" - } + "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": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" - } + "dev": true }, "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" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -4284,2231 +3010,1351 @@ "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": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "path-type": "2.0.0" - } + "dev": true }, "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": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "read-pkg": "2.0.0" - } + "dev": true } } }, "eslint-plugin-node": { - "version": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", - "integrity": "sha1-gN8yU8TXkBBF7If6ZgooTjK9yik=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, - "requires": { - "ignore": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" - }, "dependencies": { "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } } }, "eslint-plugin-promise": { - "version": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", - "integrity": "sha1-VLdljI9FSBPcKocK/4FS7ElpunU=", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz", + "integrity": "sha512-2WO+ZFh7vxUKRfR0cOIMrWgYKdR6S1AlOezw6pC52B6oYpd5WFghN+QHxvrRdZMtbo8h3dfUZ2o1rWb0UPbKtg==", "dev": true }, "eslint-plugin-standard": { - "version": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", "dev": true }, "eslint-scope": { - "version": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true, - "requires": { - "esrecurse": "4.2.0", - "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz" - } + "dev": true }, "eslint-visitor-keys": { - "version": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", "dev": true }, "espree": { - "version": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", - "integrity": "sha1-kx4K9k5/u+0msFCinarR/GR5n6Y=", - "dev": true, - "requires": { - "acorn": "5.4.1", - "acorn-jsx": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz" - } + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true }, "esprima": { - "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true }, "esquery": { - "version": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", - "dev": true, - "requires": { - "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz" - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true }, "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true, - "requires": { - "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true }, "estraverse": { - "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, "estree-walker": { - "version": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", "dev": true }, "esutils": { - "version": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, "etag": { - "version": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", "dev": true }, "event-emitter": { - "version": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "0.10.38" - } + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=" }, "event-stream": { - "version": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "version": "3.3.4", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "from": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "pause-stream": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "split": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "stream-combiner": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } + "dev": true }, "eventemitter3": { - "version": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.0.1.tgz", + "integrity": "sha512-QOCPu979MMWX9XNlfRZoin+Wm+bK1SP7vv3NGUniYwuSJK/+cPA10blMaeRgzg31RvoSFk6FsCDVa4vNryBTGA==", "dev": true }, "events": { - "version": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", "dev": true }, "evp_bytestokey": { - "version": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", - "dev": true, - "requires": { - "md5.js": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } + "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 }, "execa": { - "version": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "get-stream": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "npm-run-path": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "p-finally": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "strip-eof": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" - } + "dev": true }, "expand-braces": { - "version": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, - "requires": { - "array-slice": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "braces": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz" - }, "dependencies": { "array-slice": { - "version": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", "dev": true }, "array-unique": { - "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, "braces": { - "version": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz" - } + "dev": true }, "expand-range": { - "version": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz" - } + "dev": true }, "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", "dev": true }, "repeat-string": { - "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", "dev": true } } }, "expand-brackets": { - "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "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": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "extend-shallow": "2.0.1", - "posix-character-classes": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "regex-not": "1.0.0", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "to-regex": "3.0.1" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "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": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-accessor-descriptor": { - "version": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-data-descriptor": { - "version": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - } + "dev": true }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true } } }, "expand-range": { - "version": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "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": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz" - }, "dependencies": { "fill-range": { - "version": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "randomatic": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - } + "dev": true }, "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "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": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - } + "dev": true }, "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - } + "dev": true }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true } } }, "expand-tilde": { - "version": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz" - } + "dev": true }, "express-session": { - "version": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", "dev": true, - "requires": { - "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "crc": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "uid-safe": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", - "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "uid-safe": { - "version": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", - "dev": true, - "requires": { - "base64-url": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz" - } + "dev": true } } }, "extend": { - "version": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, - "requires": { - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + "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 + } } }, "external-editor": { - "version": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha1-PQJqIbf5W1cmOH1CAKwWDTcsO0g=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, - "requires": { - "chardet": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "tmp": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" - }, "dependencies": { "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", + "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", "dev": true } } }, "extglob": { - "version": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "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": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "define-property": "1.0.0", - "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "extend-shallow": "2.0.1", - "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "regex-not": "1.0.0", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "to-regex": "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 + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "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 + }, + "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 + }, + "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 + } } }, "extsprintf": { - "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, "faker": { - "version": "https://registry.npmjs.org/faker/-/faker-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/faker/-/faker-3.1.0.tgz", "integrity": "sha1-D5CPr05uwCUk5UpX5DLFwBPgjJ8=", "dev": true }, "fancy-log": { - "version": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "color-support": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "time-stamp": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz" - } + "dev": true }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { - "version": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, "fast-levenshtein": { - "version": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, "faye-websocket": { - "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz" - } + "dev": true }, "figures": { - "version": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "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": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - } + "dev": true }, "file-entry-cache": { - "version": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "dev": true }, "file-loader": { - "version": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", "dev": true, "optional": true, - "requires": { - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz" - }, "dependencies": { "loader-utils": { - "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, - "optional": true, - "requires": { - "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "optional": true } } }, "file-uri-to-path": { - "version": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", + "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 }, "filename-regex": { - "version": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, "fileset": { - "version": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, - "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - } + "dev": true }, "fill-keys": { - "version": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "merge-descriptors": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - } + "dev": true }, "fill-range": { - "version": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "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": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "to-regex-range": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" + "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 + } } }, "finalhandler": { - "version": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "escape-html": { - "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "find-cache-dir": { - "version": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "make-dir": "1.1.0", - "pkg-dir": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz" - } + "dev": true }, "find-index": { - "version": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", "dev": true }, "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "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": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" - } + "dev": true }, "findup-sync": { - "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "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": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "micromatch": "3.1.5", - "resolve-dir": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" - }, "dependencies": { "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - } + "dev": true } } }, "fined": { - "version": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "object.defaults": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "parse-filepath": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz" - } + "dev": true }, "first-chunk-stream": { - "version": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", "dev": true }, "flagged-respawn": { - "version": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", "dev": true }, "flat-cache": { - "version": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "del": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "write": "https://registry.npmjs.org/write/-/write-0.2.1.tgz" - } + "dev": true }, "flush-write-stream": { - "version": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", - "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true }, "follow-redirects": { - "version": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", - "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", - "dev": true, - "optional": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" - }, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "optional": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - } - } + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", + "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "dev": true }, "for-in": { - "version": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, "for-own": { - "version": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" - } + "dev": true }, "foreach": { - "version": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, "foreachasync": { - "version": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", "dev": true }, "forever-agent": { - "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true }, "fork-stream": { - "version": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", "dev": true }, "form-data": { - "version": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "mime-types": "2.1.17" - } + "dev": true }, "fragment-cache": { - "version": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" - } + "dev": true }, "fresh": { - "version": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", "dev": true }, "from": { - "version": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, "fs-access": { - "version": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "requires": { - "null-check": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz" - } + "dev": true }, "fs-extra": { - "version": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, - "requires": { - "jsonfile": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", - "ncp": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" - }, "dependencies": { "mkdirp": { - "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true }, "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", "dev": true } } }, "fs-mkdirp-stream": { - "version": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "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, - "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "dev": true }, "fs.extra": { - "version": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", "integrity": "sha1-3QI/kwE77iRTHxszUUw3sg/ZM0k=", "dev": true, - "requires": { - "fs-extra": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", - "walk": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz" - }, "dependencies": { "mkdirp": { - "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true } } }, "fs.realpath": { - "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "fsevents": { - "version": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "integrity": "sha1-EfgjGPX+e7LNIpZaEI6TBiCCFtg=", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.2.tgz", + "integrity": "sha512-iownA+hC4uHFp+7gwP/y5SzaiUo7m2vpa0dhpzw8YuKtiZsz7cIXsFbXpLEeBM6WuCQyw1MH4RRe6XI8GFUctQ==", "dev": true, "optional": true, - "requires": { - "nan": "2.8.0", - "node-pre-gyp": "0.6.39" - }, "dependencies": { "abbrev": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", - "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "version": "1.1.1", + "bundled": true, "dev": true, "optional": true }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "dev": true }, "aproba": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", - "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", + "version": "1.2.0", + "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" - } - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "bundled": true, "dev": true, "optional": true }, "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "version": "1.0.0", + "bundled": true, "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, "brace-expansion": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", - "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", - "dev": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "version": "1.1.11", + "bundled": true, "dev": true }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "chownr": { + "version": "1.0.1", + "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "dev": true }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "bundled": true, "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } + "optional": true }, "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "version": "2.6.9", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } + "optional": true }, "deep-extend": { "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "bundled": true, "dev": true, "optional": true }, - "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 - }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true, "optional": true }, "detect-libc": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.2.tgz", - "integrity": "sha1-ca1dIEvxempsqPRQxhRUBm70YeE=", - "dev": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "version": "1.0.3", + "bundled": true, "dev": true, "optional": true }, - "extsprintf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "fs-minipass": { + "version": "1.2.5", + "bundled": true, "dev": true, "optional": true }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" - } - }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "bundled": true, "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", - "dev": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } + "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } + "optional": true }, "glob": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "bundled": true, "dev": true, "optional": true }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true, "optional": true }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "iconv-lite": { + "version": "0.4.21", + "bundled": true, "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true + "optional": true }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "ignore-walk": { + "version": "3.0.1", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" - } + "optional": true }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } + "optional": true }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, "dev": true }, "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "version": "1.3.5", + "bundled": true, "dev": true, "optional": 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" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true, - "optional": true + "bundled": true, + "dev": true }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "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, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", - "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "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, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "bundled": true, "dev": true, "optional": true }, - "jsprim": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", - "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", - "dev": true - }, - "mime-types": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", - "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", - "dev": true, - "requires": { - "mime-db": "1.27.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" - } + "bundled": true, + "dev": true }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "bundled": true, "dev": true }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } + "bundled": true, + "dev": true }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, "dev": true, "optional": true }, "node-pre-gyp": { - "version": "0.6.39", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz", - "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", + "version": "0.9.1", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.2", - "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" - } + "optional": true }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" - } + "optional": true + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true }, "npmlog": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", - "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", + "version": "4.1.2", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } + "optional": true }, "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=", + "bundled": true, "dev": true }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true, - "optional": true - }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } + "bundled": true, + "dev": true }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true, "optional": true }, "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=", + "bundled": true, "dev": true, "optional": true }, "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "version": "0.1.5", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } + "optional": true }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "bundled": true, "dev": true, "optional": 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 - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "version": "2.0.0", + "bundled": true, "dev": true, "optional": true }, "rc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "version": "1.2.6", + "bundled": true, "dev": true, "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "dev": true, "optional": true } } }, "readable-stream": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "version": "2.3.6", + "bundled": true, "dev": true, - "requires": { - "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": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" - } + "optional": true }, "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "version": "2.6.2", + "bundled": true, "dev": true, - "requires": { - "glob": "7.1.2" - } + "optional": true }, "safe-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", + "version": "5.1.1", + "bundled": true, "dev": true }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "version": "5.5.0", + "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true, "optional": true }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", - "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", + "string_decoder": { + "version": "1.1.1", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } + "optional": true }, "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" - } - }, - "string_decoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", - "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=", - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true, - "optional": true + "bundled": true, + "dev": true }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } + "bundled": true, + "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=", + "bundled": true, "dev": true, "optional": true }, "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", - "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", - "dev": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "version": "4.4.1", + "bundled": true, "dev": true, "optional": true }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", + "bundled": true, "dev": true, "optional": true }, - "verror": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", - "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", - "dev": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, "wide-align": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } + "optional": true }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, "dev": true } } }, "fstream": { - "version": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", "dev": true, - "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" - }, "dependencies": { "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz" - } + "dev": true } } }, "ftp": { - "version": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "xregexp": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "function-bind": { - "version": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "functional-red-black-tree": { - "version": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "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 }, "gaze": { - "version": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz" - } + "dev": true }, "generate-function": { - "version": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", "dev": true }, "generate-object-property": { - "version": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" - } + "dev": true }, "get-caller-file": { - "version": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, "get-port": { - "version": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", "dev": true }, "get-stdin": { - "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, "get-stream": { - "version": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, "get-uri": { - "version": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", - "integrity": "sha1-29ysrNjGCKODFoaTaBF2l6FjHFk=", - "dev": true, - "requires": { - "data-uri-to-buffer": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "file-uri-to-path": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "ftp": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - }, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", + "integrity": "sha512-7aelVrYqCLuVjq2kEKRTH8fXPTC0xKTkM+G7UlFkEwCXY3sFbSxvY375JoFowOAYbkaU47SrBvOefUlLZZ+6QA==", + "dev": true, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true } } }, "get-value": { - "version": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, "getpass": { - "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - }, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "git-up": { - "version": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", - "integrity": "sha1-IP5rr770OEyuJT3E9GPEmgw70uw=", - "dev": true, - "requires": { - "is-ssh": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", - "parse-url": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz" - } + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", + "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", + "dev": true }, "git-url-parse": { - "version": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.1.0.tgz", - "integrity": "sha1-0e4JIT785djceiG7A/F8/gwRESI=", - "dev": true, - "requires": { - "git-up": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz" - } + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", + "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", + "dev": true }, "github-slugger": { - "version": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", - "integrity": "sha1-itoyhv0EbYlRw8lSqNeFTP2Q/Zo=", - "dev": true, - "requires": { - "emoji-regex": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz" - } + "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 }, "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "dev": true, - "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true }, "glob-base": { - "version": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, - "requires": { - "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - }, "dependencies": { "glob-parent": { - "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "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": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } + "dev": true }, "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "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": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "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": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } + "dev": true } } }, "glob-parent": { - "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "requires": { - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "path-dirname": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" - }, "dependencies": { "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - } + "dev": true } } }, "glob-stream": { - "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "is-negated-glob": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "pumpify": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "to-absolute-glob": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz" - } + "dev": true }, "glob-watcher": { - "version": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz" - } + "dev": true }, "glob2base": { - "version": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz" - } + "dev": true }, "global-modules": { - "version": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", - "dev": true, - "requires": { - "global-prefix": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "is-windows": "1.0.1", - "resolve-dir": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" - } + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true }, "global-prefix": { - "version": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "homedir-polyfill": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "ini": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "is-windows": "1.0.1", - "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" - } + "dev": true }, "globals": { - "version": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, "globals-docs": { - "version": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", - "integrity": "sha1-8sZHVE62Fhx8OEUoCOFuaTwtr7s=", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", + "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", "dev": true }, "globby": { - "version": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, - "requires": { - "array-union": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "arrify": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - }, "dependencies": { "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "globule": { - "version": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, - "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" - }, "dependencies": { "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" - } + "dev": true }, "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", "dev": true }, "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", "dev": true }, "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", "dev": true }, "lru-cache": { - "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", "dev": true }, "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" - } + "dev": true } } }, "glogg": { - "version": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha1-3PdY5EeJzD89MsHzVio2duajSBA=", - "dev": true, - "requires": { - "sparkles": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true }, "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "graceful-readlink": { - "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, @@ -6519,1997 +4365,1488 @@ "dev": true }, "gulp": { - "version": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, - "requires": { - "archy": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "deprecated": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "liftoff": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "orchestrator": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "pretty-hrtime": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "tildify": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "v8flags": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz" - }, "dependencies": { "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", "dev": true }, "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } + "dev": true }, "glob-stream": { - "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "glob2base": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" - } + "dev": true }, "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz" - } + "dev": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - } + "dev": true }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "ordered-read-streams": { - "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } + "dev": true }, "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "dev": true }, "unique-stream": { - "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", "dev": true }, "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" - } + "dev": true }, "vinyl-fs": { - "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "glob-watcher": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz" - } + "dev": true } } }, "gulp-babel": { - "version": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", - "integrity": "sha1-Wq2Kyw22t/Lwvhnu7pUo8gZN9jE=", - "dev": true, - "requires": { - "babel-core": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "plugin-error": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl-sourcemaps-apply": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz" - }, + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", + "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", + "dev": true, "dependencies": { "babel-core": { - "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true, - "requires": { - "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "babel-helpers": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "babel-messages": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "babel-register": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - } + "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "replace-ext": { - "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "gulp-clean": { - "version": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", + "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": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz" - }, "dependencies": { "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "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": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", "dev": true }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "has-ansi": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" - } + "dev": true }, "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "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": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "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": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "meow": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz" - } + "dev": true }, "gulp-util": { - "version": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", "dev": true, - "requires": { - "chalk": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "dateformat": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "multipipe": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz" - }, "dependencies": { "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" - } + "dev": true } } }, "has-ansi": { - "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" - } + "dev": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "lodash._reinterpolate": { - "version": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", "dev": true }, "lodash.escape": { - "version": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", - "lodash._reunescapedhtml": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" - } + "dev": true }, "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" - } + "dev": true }, "lodash.template": { - "version": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "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": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "lodash.defaults": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "lodash.templatesettings": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "lodash.values": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz" - } + "dev": true }, "lodash.templatesettings": { - "version": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "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": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz" - } + "dev": true }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", "dev": true }, "object-keys": { - "version": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "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": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" - } + "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", "dev": true }, "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz" - }, "dependencies": { "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "requires": { - "object-keys": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" - } + "dev": true } } }, "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" - } + "dev": true }, "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", "dev": true } } }, "gulp-concat": { - "version": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz" - } + "dev": true }, "gulp-connect": { - "version": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", "dev": true, - "requires": { - "connect": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", - "connect-livereload": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", - "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "tiny-lr": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz" - }, "dependencies": { "body-parser": { - "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", - "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "type-is": "1.6.15" - }, "dependencies": { "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", "dev": true } } }, "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", "dev": true }, "raw-body": { - "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, "dependencies": { "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", "dev": true } } }, "tiny-lr": { - "version": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", - "dev": true, - "requires": { - "body-parser": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "faye-websocket": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "livereload-js": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz" - } + "dev": true } } }, "gulp-documentation": { - "version": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", - "dev": true, - "requires": { - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz" - } + "dev": true }, "gulp-eslint": { - "version": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", - "integrity": "sha1-GKKmdo5EBMvz4gMjnLV0dBaPpgY=", - "dev": true, - "requires": { - "eslint": "4.17.0", - "fancy-log": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "plugin-error": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz" - } + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", + "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", + "dev": true }, "gulp-footer": { - "version": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", - "integrity": "sha1-f+KDJOxn49YY0x4PXqLuW0VPaHc=", - "dev": true, - "requires": { - "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "lodash._reescape": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "lodash._reevaluate": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz" - } + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", + "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", + "dev": true }, "gulp-header": { - "version": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.9.tgz", - "integrity": "sha1-yfEP7gYy2B6Tl4nG7PRaFRvzCYs=", + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, - "requires": { - "concat-with-sourcemaps": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" + "dependencies": { + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true + } } }, "gulp-if": { - "version": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true, - "requires": { - "gulp-match": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", - "ternary-stream": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "dev": true }, "gulp-js-escape": { - "version": "https://registry.npmjs.org/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz", + "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, - "requires": { - "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "dev": true } } }, "gulp-match": { - "version": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true, - "requires": { - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - } + "dev": true }, "gulp-optimize-js": { - "version": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", - "dev": true, - "requires": { - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "optimize-js": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "dev": true }, "gulp-rename": { - "version": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", "dev": true }, "gulp-replace": { - "version": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", "dev": true, - "requires": { - "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", - "istextorbinary": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", - "replacestream": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz" - }, "dependencies": { "event-stream": { - "version": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", + "version": "3.0.20", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", - "dev": true, - "requires": { - "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "from": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "pause-stream": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "split": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", - "stream-combiner": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } + "dev": true }, "map-stream": { - "version": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, "split": { - "version": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "dev": true, - "requires": { - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } + "dev": true } } }, "gulp-shell": { - "version": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "dev": true }, "gulp-sourcemaps": { - "version": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", - "requires": { - "@gulp-sourcemaps/identity-map": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", - "@gulp-sourcemaps/map-sources": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "acorn": "5.4.1", - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "css": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "debug-fabulous": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", - "detect-newline": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "strip-bom-string": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=" }, "gulp-uglify": { - "version": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", "dev": true, - "requires": { - "gulplog": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "has-gulplog": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "make-error-cause": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "uglify-js": "3.3.10", - "vinyl-sourcemaps-apply": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz" - }, "dependencies": { "uglify-js": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.10.tgz", - "integrity": "sha512-dNib7aUDNZFJNTXFyq0CDmLRVOsnY1F+IQgt2FAOdZFx2+LvKVLbbIb/fL+BYKCv3YH3bPCE/6M/JaxChtQLHQ==", - "dev": true, - "requires": { - "commander": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - } + "version": "3.3.22", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.22.tgz", + "integrity": "sha512-tqw96rL6/BG+7LM5VItdhDjTQmL5zG/I0b2RqWytlgeHe2eydZHuBHdA9vuGpCDhH/ZskNGcqDhivoR2xt8RIw==", + "dev": true } } }, "gulp-util": { - "version": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, - "requires": { - "array-differ": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "array-uniq": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "beeper": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "dateformat": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "fancy-log": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "gulplog": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "has-gulplog": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "lodash._reescape": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "lodash._reevaluate": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "multipipe": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz" - }, "dependencies": { "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "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 }, "replace-ext": { - "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" - } + "dev": true } } }, "gulp-webdriver": { - "version": "https://registry.npmjs.org/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", "integrity": "sha1-mM6Bz5rganoZB7htEPaThvQ4Oi0=", "dev": true, - "requires": { - "dargs": "git://github.com/christian-bromann/dargs.git#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", - "deepmerge": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "webdriverio": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz" - }, "dependencies": { - "dargs": { - "version": "git://github.com/christian-bromann/dargs.git#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", - "dev": true, - "requires": { - "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - } - }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "dev": true } } }, "gulplog": { - "version": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz" - } + "dev": true }, "handlebars": { - "version": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz" - }, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" - } + "dev": true } } }, - "har-schema": { - "version": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true - }, "har-validator": { - "version": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "commander": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", - "is-my-json-valid": "2.17.1", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "has": { - "version": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true, - "requires": { - "function-bind": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" - } + "dev": true }, "has-ansi": { - "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - } + "dev": true }, "has-binary2": { - "version": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", "dev": true, - "requires": { - "isarray": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true } } }, "has-cors": { - "version": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", "dev": true }, "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "has-gulplog": { - "version": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" - } + "dev": true }, "has-symbols": { - "version": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, "has-value": { - "version": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "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": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "has-values": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - } + "dev": true }, "has-values": { - "version": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "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, - "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" - }, "dependencies": { "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true } } }, "hash-base": { - "version": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true }, "hash.js": { - "version": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha1-NA3tvmKQGHFRweodd3o0SJNd+EY=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - } + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true }, "hast-util-is-element": { - "version": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", "integrity": "sha1-P3IWl4sq4U2YdJh4eCZ18zvjzgA=", "dev": true }, "hast-util-sanitize": { - "version": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", "integrity": "sha1-0QvWdXoh5ZwTq8iuNTDdO219Z54=", - "dev": true, - "requires": { - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "dev": true }, "hast-util-to-html": { - "version": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", - "dev": true, - "requires": { - "ccount": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", - "comma-separated-tokens": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.4.tgz", - "hast-util-is-element": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", - "hast-util-whitespace": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", - "html-void-elements": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.2.tgz", - "kebab-case": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", - "property-information": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", - "space-separated-tokens": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz", - "stringify-entities": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", - "unist-util-is": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "dev": true }, "hast-util-whitespace": { - "version": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", "integrity": "sha1-vQlpGWJdKTbh/xe8Tff9cn8X7Ok=", "dev": true }, "hawk": { - "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "sntp": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" - } + "dev": true }, "highlight.js": { - "version": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", "dev": true }, "hipchat-notifier": { - "version": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", "dev": true, - "optional": true, - "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "request": "https://registry.npmjs.org/request/-/request-2.79.0.tgz" - } + "optional": true }, "hmac-drbg": { - "version": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "minimalistic-crypto-utils": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" - } + "dev": true }, "hoek": { - "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, "home-or-tmp": { - "version": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "os-tmpdir": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" - } + "dev": true }, "homedir-polyfill": { - "version": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" - } + "dev": true }, "hosted-git-info": { - "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", "dev": true }, "html-void-elements": { - "version": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.2.tgz", - "integrity": "sha1-nSLgyjKsyVs/RbjVtPb73AWv/VU=", - "dev": true - }, - "htmlescape": { - "version": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.3.tgz", + "integrity": "sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==", "dev": true }, "http-errors": { - "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz" - } + "dev": true }, "http-parser-js": { - "version": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz", + "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==", "dev": true }, "http-proxy": { - "version": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", - "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", - "dev": true, - "requires": { - "eventemitter3": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "requires-port": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" - } + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true }, "http-proxy-agent": { - "version": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", "dev": true, - "requires": { - "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true } } }, "http-signature": { - "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "jsprim": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "sshpk": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz" - } + "dev": true }, "httpntlm": { - "version": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true, - "requires": { - "httpreq": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", - "underscore": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" - } + "dev": true }, "httpreq": { - "version": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", "dev": true }, "https-browserify": { - "version": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "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": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", "dev": true, - "requires": { - "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true } } }, "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", "dev": true }, "ieee754": { - "version": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", + "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", "dev": true }, "ignore": { - "version": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha1-YSKJv7PCIOGGpYEYYY1b6MG6sCE=", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, "ignore-loader": { - "version": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz", "integrity": "sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM=", "dev": true }, "imurmurhash": { - "version": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "indent-string": { - "version": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" - } + "dev": true }, "indexof": { - "version": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, "inflection": { - "version": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", "integrity": "sha1-W//LEZetPoEFD44X4hZoCH7p6y8=", "dev": true, "optional": true }, "inflight": { - "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } + "dev": true }, "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { - "version": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, - "inline-source-map": { - "version": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", - "dev": true, - "requires": { - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - }, - "dependencies": { - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, "inquirer": { - "version": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", - "dev": true, - "requires": { - "ansi-escapes": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "cli-cursor": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "cli-width": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "external-editor": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "figures": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "mute-stream": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "run-async": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "rx-lite": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "rx-lite-aggregates": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - }, + "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-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", - "dev": true, - "requires": { - "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" - } + "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 }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" - } + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true }, "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "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": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", - "dev": true, - "requires": { - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" - } + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" - } - }, - "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - } - } - } - }, - "insert-module-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", - "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "combine-source-map": "0.7.2", - "concat-stream": "1.5.2", - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "lexical-scope": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - }, - "dependencies": { - "combine-source-map": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", - "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", - "dev": true, - "requires": { - "convert-source-map": "1.1.3", - "inline-source-map": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "lodash.memoize": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "source-map": "0.5.7" - } - }, - "concat-stream": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "2.0.6", - "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" - } - }, - "convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "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 } } }, "interpret": { - "version": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, "invariant": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", - "dev": true, - "requires": { - "loose-envify": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz" - } + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true }, "invert-kv": { - "version": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "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 }, "ip": { - "version": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", "dev": true }, "is-absolute": { - "version": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", - "dev": true, - "requires": { - "is-relative": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "is-windows": "1.0.1" - } + "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 }, "is-accessor-descriptor": { - "version": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "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": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz" + "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 + } } }, "is-alphabetical": { - "version": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", - "integrity": "sha1-x3B5zJHU76x3W+EDS/LSQ/lebwg=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", + "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", "dev": true }, "is-alphanumeric": { - "version": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", "dev": true }, "is-alphanumerical": { - "version": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", - "integrity": "sha1-37SqTRCF4zvbYcLe6cgOnGwZ9Ts=", - "dev": true, - "requires": { - "is-alphabetical": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", - "is-decimal": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz" - } + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", + "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "dev": true }, "is-arrayish": { - "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-binary-path": { - "version": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz" - } + "dev": true }, "is-buffer": { - "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "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-builtin-module": { - "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" - } + "dev": true }, "is-data-descriptor": { - "version": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "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": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz" + "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 + } } }, "is-decimal": { - "version": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", - "integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", "dev": true }, "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "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": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz" + "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-dotfile": { - "version": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "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": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "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-primitive": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz" - } + "dev": true }, "is-extendable": { - "version": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "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": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-finite": { - "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - } + "dev": true }, "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "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": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - } + "dev": true }, "is-generator": { - "version": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", "dev": true }, "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - } + "dev": true }, "is-hexadecimal": { - "version": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz", - "integrity": "sha1-bghLvJIGH7sJcexYts5tQE4k2mk=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", + "dev": true + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", "dev": true }, "is-my-json-valid": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz", - "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", - "dev": true, - "requires": { - "generate-function": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "generate-object-property": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "jsonpointer": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "dev": true }, "is-negated-glob": { - "version": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "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 }, "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "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": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, "dependencies": { "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true } } }, "is-object": { - "version": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", "dev": true }, "is-odd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", - "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", "dev": true, - "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" + "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 + } } }, "is-path-cwd": { - "version": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", "dev": true }, "is-path-in-cwd": { - "version": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, - "requires": { - "is-path-inside": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz" - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true }, "is-path-inside": { - "version": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" - } + "dev": true }, "is-plain-obj": { - "version": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, "is-plain-object": { - "version": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", - "dev": true, - "requires": { - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - } + "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 }, "is-posix-bracket": { - "version": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "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": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, "is-promise": { - "version": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, "is-property": { - "version": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", "dev": true }, "is-relative": { - "version": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", - "dev": true, - "requires": { - "is-unc-path": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz" - } + "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 }, "is-resolvable": { - "version": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, "is-ssh": { - "version": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", - "dev": true, - "requires": { - "protocols": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz" - } + "dev": true }, "is-stream": { - "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "is-typedarray": { - "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, "is-unc-path": { - "version": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", - "dev": true, - "requires": { - "unc-path-regex": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz" - } + "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 }, "is-utf8": { - "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, "is-valid-glob": { - "version": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "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 }, "is-whitespace-character": { - "version": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", - "integrity": "sha1-muAXbzKCtlRXoZks2whPil+DPjs=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", + "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", "dev": true }, "is-windows": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", - "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=", + "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 }, "is-word-character": { - "version": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", "integrity": "sha1-WgP6HqkazopusMfNdw64bWXIvvs=", "dev": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isbinaryfile": { - "version": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", "dev": true }, "isexe": { - "version": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "isstream": { - "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, "istanbul": { - "version": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, - "requires": { - "abbrev": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "escodegen": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "esprima": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "handlebars": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "nopt": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" - }, "dependencies": { "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } + "dev": true }, "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" - } + "dev": true } } }, "istanbul-api": { - "version": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.2.tgz", - "integrity": "sha1-4XzVGd1exBQRl/JG/fOAt1SH87E=", - "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "fileset": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", - "istanbul-lib-coverage": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", - "istanbul-lib-hook": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", - "istanbul-lib-instrument": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz", - "istanbul-lib-report": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", - "istanbul-lib-source-maps": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", - "istanbul-reports": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.4.tgz", - "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - }, + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", + "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", + "dev": true, "dependencies": { "async": { - "version": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", - "dev": true, - "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true }, "esprima": { - "version": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, "js-yaml": { - "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz" - } + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "dev": true } } }, "istanbul-instrumenter-loader": { - "version": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz", - "integrity": "sha1-n1U5I7IjYLrJXmF6q6Aa3R99sLI=", - "dev": true, - "requires": { - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "istanbul-lib-instrument": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz", - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "schema-utils": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz" - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", + "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", + "dev": true }, "istanbul-lib-coverage": { - "version": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", - "integrity": "sha1-QRPI/2t6QKHvc1CwEBYzH2Ov3hQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", "dev": true }, "istanbul-lib-hook": { - "version": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", - "integrity": "sha1-hTjZcDcss3FtU+VVI91UtVeo2Js=", - "dev": true, - "requires": { - "append-transform": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.0.tgz", + "integrity": "sha512-p3En6/oGkFQV55Up8ZPC2oLxvgSxD8CzA0yBrhRZSh3pfv3OFj9aSGVC0yoerAi/O4u7jUVnOGVX1eVFM+0tmQ==", + "dev": true }, "istanbul-lib-instrument": { - "version": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz", - "integrity": "sha1-hJBb9H9+C0Ada4QNp7rWcIa0qrY=", - "dev": true, - "requires": { - "babel-generator": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "babel-template": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "babel-traverse": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "babylon": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "istanbul-lib-coverage": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz" - } + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", + "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", + "dev": true }, "istanbul-lib-report": { - "version": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", - "integrity": "sha1-LfEhiMD6d5kMDSF20tC6M5QYglk=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", + "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", "dev": true, - "requires": { - "istanbul-lib-coverage": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "path-parse": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz" - }, "dependencies": { "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "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": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" - } + "dev": true } } }, "istanbul-lib-source-maps": { - "version": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", - "integrity": "sha1-IPtUsU4Us/tu22rKNXH9IUPbROY=", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.4.tgz", + "integrity": "sha512-UzuK0g1wyQijiaYQxj/CdNycFhAd2TLtO2obKQMTZrZ1jzEMRY3rvpASEKkaxbRR6brvdovfA03znPa/pXcejg==", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "istanbul-lib-coverage": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - }, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "istanbul-reports": { - "version": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.4.tgz", - "integrity": "sha1-XMul4it7Wl2R1eCoMPib4zS/l70=", - "dev": true, - "requires": { - "handlebars": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz" - } + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", + "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", + "dev": true }, "istextorbinary": { - "version": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", - "dev": true, - "requires": { - "binaryextensions": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", - "textextensions": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz" - } + "dev": true }, "jade": { "version": "0.26.3", "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", "dev": true, - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" - }, "dependencies": { "commander": { "version": "0.6.1", @@ -8526,285 +5863,222 @@ } }, "js-tokens": { - "version": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, "js-yaml": { - "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" - } + "dev": true }, "jsbn": { - "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true, "optional": true }, "jsesc": { - "version": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, "json-loader": { - "version": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=", + "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": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha1-UBg80bLSUnXeBp6ecbRnrJ6rlzo=", + "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 }, "json-schema": { - "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "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": { - "version": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, "json-stable-stringify": { - "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" - } + "dev": true }, "json-stable-stringify-without-jsonify": { - "version": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "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 }, "json-stringify-safe": { - "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "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 }, "json3": { - "version": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", "dev": true }, "json5": { - "version": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, "jsonfile": { - "version": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", "dev": true }, "jsonify": { - "version": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, "jsonparse": { - "version": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "jsonpointer": { - "version": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, + "JSONStream": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "dev": true + }, "jsprim": { - "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "json-schema": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "verror": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" - }, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "just-clone": { - "version": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" }, "just-extend": { - "version": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", - "integrity": "sha1-7G55QQ/5FORyZSq/oOYDwD1g6QU=", + "version": "1.1.27", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", "dev": true }, "karma": { - "version": "https://registry.npmjs.org/karma/-/karma-2.0.0.tgz", - "integrity": "sha1-oCaY3X8PBf9etmq49lWCSQtRLlg=", - "dev": true, - "requires": { - "bluebird": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "body-parser": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "browserify": "https://registry.npmjs.org/browserify/-/browserify-14.5.0.tgz", - "chokidar": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "colors": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "combine-lists": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "connect": "3.6.5", - "core-js": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "di": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "dom-serialize": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "expand-braces": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "http-proxy": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", - "isbinaryfile": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "log4js": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", - "mime": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "qjobs": "1.1.5", - "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "socket.io": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "tmp": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "useragent": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz" - }, + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.2.tgz", + "integrity": "sha1-TS25QChQpmVR+nhLAWT7CCTtjEs=", + "dev": true, "dependencies": { "anymatch": { - "version": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", - "dev": true, - "requires": { - "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" - } + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true }, "arr-diff": { - "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "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": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" - } + "dev": true }, "array-unique": { - "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, "body-parser": { - "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "type-is": "1.6.15" - } + "dev": true }, "braces": { - "version": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" - } + "dev": true }, "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, "chokidar": { - "version": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "fsevents": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" - } + "dev": true }, "connect": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.5.tgz", - "integrity": "sha1-+43ee6B2OHfQ7J352sC0tA5yx9o=", - "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "finalhandler": "1.0.6", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" - } + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "expand-brackets": { - "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "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": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" - } + "dev": true }, "extglob": { - "version": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } + "dev": true }, "finalhandler": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", - "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "encodeurl": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "statuses": "1.3.1", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, "dependencies": { "statuses": { "version": "1.3.1", @@ -8815,321 +6089,253 @@ } }, "glob-parent": { - "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "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": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } + "dev": true }, "http-errors": { - "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, - "requires": { - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "setprototypeof": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz" - }, - "dependencies": { - "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - } - } + "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 }, "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", "dev": true }, "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "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": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "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": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } + "dev": true }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true }, "micromatch": { - "version": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "braces": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "extglob": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "filename-regex": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" - } - }, - "mime": { - "version": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", "dev": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", "dev": true }, "range-parser": { - "version": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", "dev": true }, "raw-body": { - "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } } }, "utils-merge": { - "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true } } }, "karma-babel-preprocessor": { - "version": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true, - "requires": { - "babel-core": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz" - } + "dev": true }, "karma-browserstack-launcher": { - "version": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", - "integrity": "sha1-Yf49NrHPEGgeQPnYdL83Jx+xxnQ=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", + "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", "dev": true, - "requires": { - "browserstack": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", - "browserstacktunnel-wrapper": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.1.tgz", - "q": "https://registry.npmjs.org/q/-/q-1.5.1.tgz" - }, "dependencies": { "q": { - "version": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true } } }, "karma-chai": { - "version": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", "dev": true }, "karma-chrome-launcher": { - "version": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha1-zxudBxNswY/iOTJ9JGVMPbw2is8=", - "dev": true, - "requires": { - "fs-access": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", - "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" - } + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true }, "karma-coverage-istanbul-reporter": { - "version": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.1.tgz", - "integrity": "sha1-K0LRRd27SGjYXVKIjElaIcYdhzw=", - "dev": true, - "requires": { - "istanbul-api": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.2.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - } + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.2.tgz", + "integrity": "sha512-sQHexslLF+QHzaKfK8+onTYMyvSwv+p5cDayVxhpEELGa3z0QuB+l0IMsicIkkBNMOJKQaqueiRoW7iuo7lsog==", + "dev": true }, "karma-es5-shim": { - "version": "https://registry.npmjs.org/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", "integrity": "sha1-zdADM8znfC5M4D46yT8vjs0fuVI=", - "dev": true, - "requires": { - "es5-shim": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz" - } + "dev": true }, "karma-firefox-launcher": { - "version": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha1-LEcDBFLwRTHrfRPU/HZpYwu5Mzk=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", + "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", "dev": true }, "karma-ie-launcher": { - "version": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true, - "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } + "dev": true }, "karma-mocha": { - "version": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", "dev": true, - "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" - }, "dependencies": { "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "karma-mocha-reporter": { - "version": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", "dev": true, - "requires": { - "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "log-symbols": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" - }, "dependencies": { "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", - "dev": true, - "requires": { - "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" - } + "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 }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" - } + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" - } + "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - } + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true } } }, "karma-opera-launcher": { - "version": "https://registry.npmjs.org/karma-opera-launcher/-/karma-opera-launcher-1.0.0.tgz", + "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 }, "karma-requirejs": { - "version": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-1.1.0.tgz", "integrity": "sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=", "dev": true }, "karma-safari-launcher": { - "version": "https://registry.npmjs.org/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz", "integrity": "sha1-lpgqLMR9BmquccVTursoMZEVos4=", "dev": true }, "karma-script-launcher": { - "version": "https://registry.npmjs.org/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz", "integrity": "sha1-zQF8TeXvCeWp2nkydhdhCN1LVC0=", "dev": true }, "karma-sinon": { - "version": "https://registry.npmjs.org/karma-sinon/-/karma-sinon-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/karma-sinon/-/karma-sinon-1.0.5.tgz", "integrity": "sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo=", "dev": true }, "karma-sourcemap-loader": { - "version": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true, - "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" - } + "dev": true }, "karma-spec-reporter": { - "version": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true, - "requires": { - "colors": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz" - } + "dev": true }, "karma-webpack": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.9.tgz", - "integrity": "sha512-F1j3IG/XhiMzcunAXbWXH95uizjzr3WdTzmVWlta8xqxcCtAu9FByCb4sccIMxaVFAefpgnUW9KlCo0oLvIX6A==", - "dev": true, - "requires": { - "async": "0.9.2", - "loader-utils": "0.2.17", - "lodash": "3.10.1", - "source-map": "0.5.7", - "webpack-dev-middleware": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz" - }, + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", + "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", + "dev": true, "dependencies": { "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "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": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", "dev": true }, "source-map": { @@ -9141,799 +6347,626 @@ } }, "kebab-case": { - "version": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=", "dev": true }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "labeled-stream-splicer": { - "version": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", - "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "stream-splicer": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz" - }, - "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, "lazy-cache": { - "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", - "dev": true, - "requires": { - "set-getter": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true }, "lazystream": { - "version": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "dev": true }, "lcid": { - "version": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" - } + "dev": true }, "lcov-parse": { - "version": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", "dev": true }, "lead": { - "version": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz" - } + "dev": true }, "levn": { - "version": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "type-check": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" - } - }, - "lexical-scope": { - "version": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", - "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", - "dev": true, - "requires": { - "astw": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz" - } + "dev": true }, "libbase64": { - "version": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", "dev": true }, "libmime": { - "version": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, - "requires": { - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "libbase64": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "libqp": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz" - }, "dependencies": { "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", "dev": true } } }, "libqp": { - "version": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", "dev": true }, "liftoff": { - "version": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "findup-sync": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "fined": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "flagged-respawn": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "object.map": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "rechoir": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" - } + "dev": true }, "livereload-js": { - "version": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", - "integrity": "sha1-w6si6Kr1vzUF2A0JjLrWdyZUjJo=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", + "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", "dev": true }, "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" - } + "dev": true }, "loader-runner": { - "version": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", "dev": true }, "loader-utils": { - "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz" - } + "dev": true }, "localtunnel": { - "version": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.8.3.tgz", - "integrity": "sha1-3MWSL9hWUQN9S94k/ZMkjQsk6wU=", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.0.tgz", + "integrity": "sha512-wCIiIHJ8kKIcWkTQE3m1VRABvsH2ZuOkiOpZUofUCf6Q42v3VIZ+Q0YfX1Z4sYDRj0muiKL1bLvz1FeoxsPO0w==", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "openurl": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", - "request": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.29.0.tgz" - }, "dependencies": { - "ajv": { - "version": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" - } + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "dev": true }, "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "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 + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true }, - "caseless": { - "version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true }, - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "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 }, - "har-validator": { - "version": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true, - "requires": { - "ajv": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "har-schema": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz" - } + "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 }, - "os-locale": { - "version": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" - } + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true }, - "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "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 }, - "request": { - "version": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "dev": true, - "requires": { - "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "mime-types": "2.1.17", - "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "performance-now": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "tough-cookie": "2.3.3", - "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz" - } + "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 }, - "tunnel-agent": { - "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } + "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 }, - "window-size": { - "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "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 }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-3.29.0.tgz", - "integrity": "sha1-GquWYOrnnYuPZ1vK7qtu40ws9pw=", - "dev": true, - "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz" - } + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true } } }, "locate-path": { - "version": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "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": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "path-exists": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" - } + "dev": true }, "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha1-maktZcAnLevoyWtgV7yPv6O+1RE=", + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", "dev": true }, "lodash._arraycopy": { - "version": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", "dev": true }, "lodash._arrayeach": { - "version": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", "dev": true }, "lodash._baseassign": { - "version": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" - } + "dev": true }, "lodash._baseclone": { - "version": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "dev": true, - "requires": { - "lodash._arraycopy": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", - "lodash._arrayeach": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "lodash._baseassign": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "lodash._basefor": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", - "lodash.isarray": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" - } + "dev": true }, "lodash._basecopy": { - "version": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", "dev": true }, "lodash._basecreate": { - "version": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", "dev": true }, "lodash._basefor": { - "version": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", "dev": true }, "lodash._basetostring": { - "version": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", "dev": true }, "lodash._basevalues": { - "version": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", "dev": true }, "lodash._bindcallback": { - "version": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", "dev": true }, "lodash._escapehtmlchar": { - "version": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "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, - "requires": { - "lodash._htmlescapes": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" - } + "dev": true }, "lodash._escapestringchar": { - "version": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", "dev": true }, "lodash._getnative": { - "version": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", "dev": true }, "lodash._htmlescapes": { - "version": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", "dev": true }, "lodash._isiterateecall": { - "version": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", "dev": true }, "lodash._isnative": { - "version": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", "dev": true }, "lodash._objecttypes": { - "version": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", "dev": true }, "lodash._reescape": { - "version": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", "dev": true }, "lodash._reevaluate": { - "version": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", "dev": true }, "lodash._reinterpolate": { - "version": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, "lodash._reunescapedhtml": { - "version": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, - "requires": { - "lodash._htmlescapes": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" - }, "dependencies": { "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" - } + "dev": true } } }, "lodash._root": { - "version": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", "dev": true }, "lodash._shimkeys": { - "version": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" - } + "dev": true }, "lodash._stack": { - "version": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", "dev": true }, "lodash.assign": { - "version": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", "dev": true }, "lodash.clone": { - "version": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true, - "requires": { - "lodash._baseclone": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", - "lodash._bindcallback": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz" - } - }, - "lodash.cond": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", - "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", "dev": true }, "lodash.create": { - "version": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "lodash._basecreate": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz" - } + "dev": true }, "lodash.defaults": { - "version": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "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": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" - }, "dependencies": { "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" - } + "dev": true } } }, "lodash.defaultsdeep": { - "version": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", "dev": true, - "requires": { - "lodash._baseclone": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", - "lodash._stack": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", - "lodash.isplainobject": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "lodash.keysin": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", - "lodash.mergewith": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "lodash.rest": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz" - }, "dependencies": { "lodash._baseclone": { - "version": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", "dev": true } } }, "lodash.escape": { - "version": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "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": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz" - } + "dev": true }, "lodash.get": { - "version": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, "lodash.isarguments": { - "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", "dev": true }, "lodash.isarray": { - "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", "dev": true }, "lodash.isobject": { - "version": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" - } + "dev": true }, "lodash.isplainobject": { - "version": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", "dev": true }, "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "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": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "lodash.isarguments": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "lodash.isarray": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz" - } + "dev": true }, "lodash.keysin": { - "version": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", "dev": true }, - "lodash.memoize": { - "version": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", - "dev": true - }, "lodash.mergewith": { - "version": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha1-Y5BX5ybDr72z59QnQcqo1uQzWSc=", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", "dev": true }, "lodash.rest": { - "version": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", "dev": true }, "lodash.restparam": { - "version": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", "dev": true }, "lodash.some": { - "version": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", "dev": true }, "lodash.template": { - "version": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "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": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "lodash._basetostring": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "lodash._basevalues": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "lodash.restparam": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "lodash.templatesettings": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz" - } + "dev": true }, "lodash.templatesettings": { - "version": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "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": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz" - } + "dev": true }, "lodash.values": { - "version": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", "dev": true, - "requires": { - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" - }, "dependencies": { "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" - } + "dev": true } } }, "log-driver": { - "version": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", "dev": true }, "log-symbols": { - "version": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", + "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": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz" - }, "dependencies": { "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", - "dev": true, - "requires": { - "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" - } + "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 }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" - } + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - } + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true } } }, "log4js": { - "version": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", - "integrity": "sha1-OLt73l6cHBgb116LwSjFzQQJyvE=", - "dev": true, - "requires": { - "amqplib": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "axios": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", - "circular-json": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.1.tgz", - "date-format": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "hipchat-notifier": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", - "loggly": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", - "mailgun-js": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", - "nodemailer": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", - "redis": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "slack-node": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", - "streamroller": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz" - }, + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", + "integrity": "sha512-YL/qpTxYtK0iWWbuKCrevDZz5lh+OjyHHD+mICqpjnYGKdNRBvPeh/1uYjkKUemT1CSO4wwLOwphWMpKAnD9kw==", + "dev": true, "dependencies": { "circular-json": { - "version": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.1.tgz", - "integrity": "sha1-uJQqCeU1hj3CGwRBepGXHh2c2R8=", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.3.tgz", + "integrity": "sha512-YlxLOimeIoQGHnMe3kbf8qIV2Bj7uXLbljMPRguNT49GmSAzooNfS9EJ91rSJKbLBOOzM5agvtx0WyechZN/Hw==", "dev": true } } }, "loggly": { - "version": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", "dev": true, "optional": true, - "requires": { - "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "request": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", - "timespan": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz" - }, "dependencies": { "bl": { - "version": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", "dev": true, - "optional": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" - } + "optional": true }, "form-data": { - "version": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", "dev": true, - "optional": true, - "requires": { - "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "mime-types": "2.1.17" - } + "optional": true }, "node-uuid": { - "version": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true, "optional": true }, "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "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, "optional": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", "dev": true, "optional": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, - "optional": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } + "optional": true }, "request": { - "version": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "version": "2.75.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", "dev": true, - "optional": true, - "requires": { - "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "bl": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", - "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "mime-types": "2.1.17", - "node-uuid": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", - "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "tough-cookie": "2.3.3", - "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" - } + "optional": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true, "optional": true @@ -9941,114 +6974,90 @@ } }, "lolex": { - "version": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", - "integrity": "sha1-hflFBCUQO/nnpgZo6iXcQydMqAc=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==", "dev": true }, "longest": { - "version": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", "dev": true }, "longest-streak": { - "version": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha1-JCG2upOaRDu5/+v1llhaULTDji4=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", "dev": true }, "loose-envify": { - "version": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, - "requires": { - "js-tokens": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz" - } + "dev": true }, "loud-rejection": { - "version": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "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": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz" - } + "dev": true }, "lru-cache": { - "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", - "dev": true, - "requires": { - "pseudomap": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "yallist": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz" - } + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "dev": true }, "lru-queue": { - "version": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "requires": { - "es5-ext": "0.10.38" - } + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=" }, "magic-string": { - "version": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", - "dev": true, - "requires": { - "vlq": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz" - } + "dev": true }, "mailcomposer": { - "version": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", "dev": true, - "optional": true, - "requires": { - "buildmail": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "libmime": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz" - } + "optional": true }, "mailgun-js": { - "version": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", "integrity": "sha1-7jZqINrGTDwVwD1sGz4O15UlKrs=", "dev": true, "optional": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "inflection": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", - "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "path-proxy": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", - "proxy-agent": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", - "q": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "tsscmp": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz" - }, "dependencies": { "async": { - "version": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", "integrity": "sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw=", "dev": true, - "optional": true, - "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } + "optional": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, - "optional": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "optional": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true, "optional": true }, "q": { - "version": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", "dev": true, "optional": true @@ -10056,503 +7065,359 @@ } }, "make-dir": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", - "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", - "dev": true, - "requires": { - "pify": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", + "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", + "dev": true }, "make-error": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.3.tgz", - "integrity": "sha512-j3dZCri3cCd23wgPqK/0/KvTN8R+W6fXDqQe8BNLbTpONjbA8SPaRr+q0BQq9bx3Q/+g68/gDIh9FW3by702Tg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", "dev": true }, "make-error-cause": { - "version": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "1.3.3" - } + "dev": true }, "make-iterator": { - "version": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", - "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true }, "map-cache": { - "version": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-obj": { - "version": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "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": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", "dev": true }, "map-visit": { - "version": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" - } + "dev": true }, "markdown-escapes": { - "version": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", - "integrity": "sha1-GZTfLTr0gR3lmmcUk0wrIpJzRRg=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", "dev": true }, "markdown-table": { - "version": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.1.tgz", - "integrity": "sha1-Sz3ToTPRUYuO8NvHCb8qG0gkvIw=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", + "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", "dev": true }, "match-stream": { - "version": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", "dev": true, - "requires": { - "buffers": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "md5.js": { - "version": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true, - "requires": { - "hash-base": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "dependencies": { - "hash-base": { - "version": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } + "dev": true }, "mdast-util-compact": { - "version": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", - "dev": true, - "requires": { - "unist-util-modify-children": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", - "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" - } + "dev": true }, "mdast-util-definitions": { - "version": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", - "integrity": "sha1-Zz9Dd8PiPT3nr3pP4iFMDiIcWsc=", - "dev": true, - "requires": { - "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" - } + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", + "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", + "dev": true }, "mdast-util-inject": { - "version": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", + "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, - "requires": { - "mdast-util-to-string": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz" - } + "dev": true }, "mdast-util-to-hast": { - "version": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.0.tgz", - "integrity": "sha1-aeNn+yqesCR038AXczuP0nLVXTo=", - "dev": true, - "requires": { - "collapse-white-space": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", - "detab": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", - "mdast-util-definitions": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", - "mdurl": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "trim": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "trim-lines": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.0.tgz", - "unist-builder": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", - "unist-util-generated": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.1.tgz", - "unist-util-position": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.0.tgz", - "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.0.tgz", + "integrity": "sha512-zvEXH2AUevWfKuBqtEPNcDUPI8UC6yIVvgEgNi1v1dLnzb5Pfm+PZjnZn0FhW1WmHcrGMX059MAoqicEauzjcw==", + "dev": true }, "mdast-util-to-string": { - "version": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", "integrity": "sha1-XEVch4yTVfDB5/PotxnPWDaRrPs=", "dev": true }, "mdast-util-toc": { - "version": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", - "dev": true, - "requires": { - "github-slugger": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", - "mdast-util-to-string": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", - "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" - } + "dev": true }, "mdurl": { - "version": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, "media-typer": { - "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, "mem": { - "version": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz" - } + "dev": true }, "memoizee": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", - "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "0.10.38", - "es6-weak-map": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "event-emitter": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "is-promise": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "lru-queue": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "next-tick": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "timers-ext": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz" - } + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz", + "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==" }, "memory-fs": { - "version": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "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.6", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "dev": true }, "meow": { - "version": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, - "requires": { - "camelcase-keys": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "loud-rejection": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "map-obj": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "redent": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "trim-newlines": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz" - }, "dependencies": { "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "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": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" - } + "dev": true }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "parse-json": { - "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "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": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" - } + "dev": true }, "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "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": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "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": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "path-type": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" - } + "dev": true }, "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "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": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" - } + "dev": true }, "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "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": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } + "dev": true } } }, "merge-descriptors": { - "version": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, "merge-stream": { - "version": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "dev": true }, "method-override": { - "version": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "methods": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "vary": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "vary": { - "version": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true } } }, "methods": { - "version": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "dev": true }, "micromatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.5.tgz", - "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==", - "dev": true, - "requires": { - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "braces": "2.3.0", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "extglob": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "nanomatch": "1.2.7", - "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "regex-not": "1.0.0", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "to-regex": "3.0.1" - } + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true }, "miller-rabin": { - "version": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", - "dev": true, - "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "brorand": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" - } + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true }, "mime": { - "version": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", - "integrity": "sha1-Fh5UGWVVHTtUn6ERQ5Hjo9Vbkjs=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", "dev": true }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true }, "mimic-fn": { - "version": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", + "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 }, "minimalistic-assert": { - "version": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "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": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "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": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "dev": true, - "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - } + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mixin-deep": { - "version": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, - "requires": { - "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" - }, "dependencies": { "is-extendable": { - "version": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", - "dev": true, - "requires": { - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" - } + "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 } } }, "mkdirp": { - "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" - } + "dev": true }, "mkpath": { - "version": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", "dev": true }, "mocha": { - "version": "https://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", "dev": true, - "requires": { - "commander": "2.3.0", - "debug": "2.0.0", - "diff": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "escape-string-regexp": "1.0.2", - "glob": "3.2.3", - "growl": "1.8.1", - "jade": "0.26.3", - "mkdirp": "0.5.0", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz" - }, "dependencies": { "commander": { "version": "2.3.0", @@ -10564,10 +7429,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", - "dev": true, - "requires": { - "ms": "0.6.2" - } + "dev": true }, "escape-string-regexp": { "version": "1.0.2", @@ -10579,12 +7441,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", - "dev": true, - "requires": { - "graceful-fs": "2.0.3", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "0.2.14" - } + "dev": true }, "graceful-fs": { "version": "2.0.3", @@ -10602,20 +7459,13 @@ "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" - } + "dev": true }, "mkdirp": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", - "dev": true, - "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" - } + "dev": true }, "ms": { "version": "0.6.2", @@ -10624,447 +7474,313 @@ "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz", "integrity": "sha1-Eu4hUHCGzZjBBY2ewPSsR2t687I=", "dev": true } } }, "mocha-nightwatch": { - "version": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", "dev": true, - "requires": { - "browser-stdout": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "commander": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "diff": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", - "growl": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "json3": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "lodash.create": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz" - }, "dependencies": { "commander": { - "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" - } + "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", - "dev": true, - "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } + "dev": true }, "growl": { - "version": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", "dev": true }, "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" - } + "dev": true } } }, "mock-fs": { - "version": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", "dev": true, - "requires": { - "rewire": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" - }, "dependencies": { "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } } }, "module-deps-sortable": { - "version": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "detective": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "stream-combiner2": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - }, "dependencies": { "concat-stream": { - "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" - }, "dependencies": { "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } + "dev": true } } }, "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "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 }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "module-not-found-error": { - "version": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", "dev": true }, "morgan": { - "version": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", "dev": true, - "requires": { - "basic-auth": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multiparty": { - "version": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "stream-counter": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "multipipe": { - "version": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, - "requires": { - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz" - }, "dependencies": { "duplexer2": { - "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" - } + "dev": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "mute-stream": { - "version": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, "nan": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", "dev": true, "optional": true }, "nanomatch": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.7.tgz", - "integrity": "sha512-/5ldsnyurvEw7wNpxLFgjVvBLMta43niEYOy0CJ4ntcYSbx6bugRUTQeFb4BR/WanEL1o3aQgHuVLHQaB6tOqg==", - "dev": true, - "requires": { - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "is-odd": "1.0.0", - "kind-of": "5.1.0", - "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "regex-not": "1.0.0", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "to-regex": "3.0.1" - }, - "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 - } - } + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true }, "natives": { - "version": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", - "integrity": "sha1-ARrM4ffL2H97prMJPWzZOSvhxXQ=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.3.tgz", + "integrity": "sha512-BZGSYV4YOLxzoTK73l0/s/0sH9l8SHs2ocReMH1f8JYSh5FUWu4ZrKCpJdRkWXV6HFR/pZDz7bwWOVAY07q77g==", "dev": true }, "natural-compare": { - "version": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, "ncp": { - "version": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", "dev": true }, "negotiator": { - "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", "dev": true }, + "neo-async": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", + "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", + "dev": true + }, "netmask": { - "version": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", "dev": true }, "next-tick": { - "version": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nightwatch": { - "version": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.19.tgz", - "integrity": "sha1-S9l1cnPTC4RfBIR6mLcb6bt8Szs=", - "dev": true, - "requires": { - "chai-nightwatch": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", - "ejs": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "lodash.clone": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", - "lodash.defaultsdeep": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "mkpath": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", - "mocha-nightwatch": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", - "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "proxy-agent": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", - "q": "https://registry.npmjs.org/q/-/q-1.4.1.tgz" - }, + "version": "0.9.20", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.20.tgz", + "integrity": "sha1-FW0XzQWMvDH0OrGOkV9+wpf7U+A=", + "dev": true, "dependencies": { + "ejs": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", + "dev": true + }, "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "dev": true, - "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - } + "dev": true }, "q": { - "version": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", "dev": true } } }, "nise": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.2.5.tgz", - "integrity": "sha512-Es4hGuq3lpip5PckrB+Qpuma282M0UJANJ+jxAgI+0wWTL9X6MtNv+M385JgqsAE8hv6NvD3lv8CQtXgEnvlpQ==", - "dev": true, - "requires": { - "@sinonjs/formatio": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", - "just-extend": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", - "lolex": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", - "path-to-regexp": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "text-encoding": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz" - } + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.3.3.tgz", + "integrity": "sha512-v1J/FLUB9PfGqZLGDBhQqODkbLotP0WtLo9R4EJY2PPu5f5Xg4o0rA8FDlmrjFSv9vBBKcfnOSpfYYuu5RTHqg==", + "dev": true }, "node-int64": { - "version": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", "dev": true }, "node-libs-browser": { - "version": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=", - "dev": true, - "requires": { - "assert": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "buffer": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", - "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz" - }, - "dependencies": { - "buffer": { - "version": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "1.2.1", - "ieee754": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - } - }, - "timers-browserify": { - "version": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", - "integrity": "sha1-JB52kn2coF9NlZgZAi9bNmS2S64=", - "dev": true, - "requires": { - "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" - } - }, - "tty-browserify": { - "version": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "dependencies": { "url": { - "version": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, - "requires": { - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" - }, "dependencies": { "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } @@ -11073,856 +7789,655 @@ } }, "nodemailer": { - "version": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", "dev": true, "optional": true, - "requires": { - "libmime": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "mailcomposer": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "nodemailer-direct-transport": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", - "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "nodemailer-smtp-pool": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", - "nodemailer-smtp-transport": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", - "socks": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz" - }, "dependencies": { "ip": { - "version": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true, "optional": true }, "socks": { - "version": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", "dev": true, - "optional": true, - "requires": { - "ip": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "smart-buffer": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz" - } + "optional": true } } }, "nodemailer-direct-transport": { - "version": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "smtp-connection": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz" - } + "optional": true }, "nodemailer-fetch": { - "version": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", "dev": true }, "nodemailer-shared": { - "version": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true, - "requires": { - "nodemailer-fetch": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz" - } + "dev": true }, "nodemailer-smtp-pool": { - "version": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "nodemailer-wellknown": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "smtp-connection": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz" - } + "optional": true }, "nodemailer-smtp-transport": { - "version": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "nodemailer-wellknown": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "smtp-connection": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz" - } + "optional": true }, "nodemailer-wellknown": { - "version": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", "dev": true }, "nopt": { - "version": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" - } + "dev": true }, "normalize-package-data": { - "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", - "dev": true, - "requires": { - "hosted-git-info": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "is-builtin-module": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "validate-npm-package-license": "3.0.1" - } + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true }, "normalize-path": { - "version": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" - } + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=" }, "now-and-later": { - "version": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", - "dev": true, - "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } + "dev": true }, "npm-run-path": { - "version": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" - } + "dev": true }, "null-check": { - "version": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", "dev": true }, "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "oauth-sign": { - "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-component": { - "version": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", "dev": true }, "object-copy": { - "version": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, - "requires": { - "copy-descriptor": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, "dependencies": { "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "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": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-accessor-descriptor": { - "version": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - } - }, - "is-data-descriptor": { - "version": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", - "dev": true - } - } + "dev": true }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true } } }, "object-keys": { - "version": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", "dev": true }, "object-visit": { - "version": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - } + "dev": true }, "object.assign": { - "version": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", - "dev": true, - "requires": { - "define-properties": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "function-bind": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "has-symbols": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "object-keys": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz" - } + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true }, "object.defaults": { - "version": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "array-slice": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "for-own": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - } + "dev": true }, "object.map": { - "version": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "make-iterator": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz" - } + "dev": true }, "object.omit": { - "version": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "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": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" - }, "dependencies": { "for-own": { - "version": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "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": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" - } + "dev": true } } }, "object.pick": { - "version": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - } + "dev": true }, "on-finished": { - "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - } + "dev": true }, "on-headers": { - "version": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", "dev": true }, "once": { - "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } + "dev": true }, "onetime": { - "version": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz" - } + "dev": true }, "open": { - "version": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", "dev": true }, "openurl": { - "version": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", "dev": true }, "optimist": { - "version": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, - "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" - }, "dependencies": { "wordwrap": { - "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true } } }, "optimize-js": { - "version": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", "dev": true, - "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "estree-walker": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", - "magic-string": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz" - }, "dependencies": { "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "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": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" - } + "dev": true }, "os-locale": { - "version": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" - } + "dev": true }, "parse-json": { - "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "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": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" - } + "dev": true }, "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "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": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "dev": true }, "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "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": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "path-type": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" - } + "dev": true }, "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "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": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" - } + "dev": true }, "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "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": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } + "dev": true }, "which-module": { - "version": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, - "requires": { - "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "get-caller-file": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "lodash.assign": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "require-directory": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "require-main-filename": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "which-module": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "yargs-parser": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz" - } + "dev": true }, "yargs-parser": { - "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, - "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "lodash.assign": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz" - } + "dev": true } } }, "optionator": { - "version": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "fast-levenshtein": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "levn": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "type-check": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" - } + "dev": true }, "orchestrator": { - "version": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, - "requires": { - "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "sequencify": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "stream-consume": "0.1.0" - }, "dependencies": { "end-of-stream": { - "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" - } + "dev": true }, "once": { - "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } + "dev": true } } }, "ordered-read-streams": { - "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "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, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "dev": true }, "os-browserify": { - "version": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "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-homedir": { - "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { - "version": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", - "dev": true, - "requires": { - "execa": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "lcid": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "mem": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz" - } + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true }, "os-tmpdir": { - "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "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 }, "over": { - "version": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", "dev": true }, "p-finally": { - "version": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-limit": { - "version": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha1-DpK2vty1nwIsE9DxlJ3ILRWQnxw=", - "dev": true, - "requires": { - "p-try": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true }, "p-locate": { - "version": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "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": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz" - } + "dev": true }, "p-try": { - "version": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, "pac-proxy-agent": { - "version": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", - "integrity": "sha1-NKOF399h0vDsrOCIWMdF0+eR/U0=", - "dev": true, - "requires": { - "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "get-uri": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", - "http-proxy-agent": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", - "https-proxy-agent": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "pac-resolver": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", - "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "socks-proxy-agent": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz" - }, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", + "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", + "dev": true, "dependencies": { "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", "dev": true }, "http-errors": { - "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, - "requires": { - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "setprototypeof": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz" - } + "dev": true }, "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", "dev": true }, "raw-body": { - "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - } + "dev": true + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true } } }, "pac-resolver": { - "version": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", "dev": true, - "requires": { - "co": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", - "degenerator": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "ip": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", - "netmask": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "thunkify": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz" - }, "dependencies": { "co": { - "version": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", "dev": true } } }, "pako": { - "version": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", "dev": true }, "parents": { - "version": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true, - "requires": { - "path-platform": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz" - } + "dev": true }, "parse-asn1": { - "version": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", - "dev": true, - "requires": { - "asn1.js": "4.9.2", - "browserify-aes": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "pbkdf2": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz" - } + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true + }, + "parse-domain": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.0.0.tgz", + "integrity": "sha512-09LkZIoBmYFj5Ty0oO1cjevbc42/knoiWURPUgKjJHlnK+75KDaF8+DNyEM5IYozO4Ssh6mNVOhrAKRWrwZbqQ==", + "dev": true }, "parse-entities": { - "version": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", "integrity": "sha1-gRLYhHExnyerrk1klksSL+ThuJA=", - "dev": true, - "requires": { - "character-entities": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", - "character-entities-legacy": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", - "character-reference-invalid": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", - "is-alphanumerical": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", - "is-decimal": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", - "is-hexadecimal": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz" - } + "dev": true }, "parse-filepath": { - "version": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "path-root": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz" - } + "dev": true }, "parse-git-config": { - "version": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", - "dev": true, - "requires": { - "ini": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz" - } + "dev": true }, "parse-glob": { - "version": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "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": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "is-dotfile": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - }, "dependencies": { "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "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": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "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": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } + "dev": true } } }, "parse-json": { - "version": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "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": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "json-parse-better-errors": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz" - } + "dev": true }, "parse-passwd": { - "version": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, "parse-url": { - "version": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", - "dev": true, - "requires": { - "is-ssh": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", - "protocols": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz" - } + "dev": true }, "parseqs": { - "version": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz" - } + "dev": true }, "parseuri": { - "version": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz" - } + "dev": true }, "parseurl": { - "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true }, "pascalcase": { - "version": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, "path-browserify": { - "version": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, "path-dirname": { - "version": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "path-is-absolute": { - "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "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 }, "path-is-inside": { - "version": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "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 }, "path-key": { - "version": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { - "version": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, "path-platform": { - "version": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", "dev": true }, "path-proxy": { - "version": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", "dev": true, "optional": true, - "requires": { - "inflection": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz" - }, "dependencies": { "inflection": { - "version": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", "dev": true, "optional": true @@ -11930,1531 +8445,1176 @@ } }, "path-root": { - "version": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz" - } + "dev": true }, "path-root-regex": { - "version": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true }, "path-to-regexp": { - "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, - "requires": { - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true } } }, "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", - "dev": true, - "requires": { - "pify": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true }, "pause": { - "version": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", "dev": true }, "pause-stream": { - "version": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } + "dev": true }, "pbkdf2": { - "version": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "integrity": "sha1-o14TxkeZsGzhUyD0WcIw5o5zut4=", - "dev": true, - "requires": { - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz" - } + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "dev": true }, "pbkdf2-compat": { - "version": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", "dev": true }, - "performance-now": { - "version": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "dev": true - }, "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "pinkie": { - "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, "pinkie-promise": { - "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" - } + "dev": true }, "pkg-dir": { - "version": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "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": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" - } + "dev": true }, "plugin-error": { - "version": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha1-dwFr2JGdCsN3/c3QMiMolTyleBw=", - "dev": true, - "requires": { - "ansi-colors": "1.0.1", - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "extend-shallow": "3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "is-extendable": "1.0.1" - } - }, - "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": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" - } - } - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true }, "pluralize": { - "version": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", + "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 }, "posix-character-classes": { - "version": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "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 }, "prelude-ls": { - "version": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, "preserve": { - "version": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, "pretty-hrtime": { - "version": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "dev": true }, "private": { - "version": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", + "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 }, "process": { - "version": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true }, "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { - "version": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, "property-information": { - "version": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE=", "dev": true }, "protocols": { - "version": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", "dev": true }, "proxy-agent": { - "version": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", "dev": true, - "requires": { - "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "http-proxy-agent": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", - "https-proxy-agent": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", - "pac-proxy-agent": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", - "socks-proxy-agent": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "lru-cache": { - "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", "dev": true } } }, "proxyquire": { - "version": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", "dev": true, - "requires": { - "fill-keys": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "module-not-found-error": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" - }, "dependencies": { "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true } } }, "prr": { - "version": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, "pseudomap": { - "version": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, "public-encrypt": { - "version": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", - "dev": true, - "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "browserify-rsa": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "parse-asn1": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz" - } + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "dev": true }, "pullstream": { - "version": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", "dev": true, - "requires": { - "over": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "slice-stream": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "pump": { - "version": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", - "dev": true, - "requires": { - "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true }, "pumpify": { - "version": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", - "integrity": "sha1-gLfF334kFT0D8OesigWl0Gi9B/s=", - "dev": true, - "requires": { - "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "pump": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz" - } + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "dev": true }, "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, "q": { - "version": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", "integrity": "sha1-hQ15+MuDHZLhA7Rkg+TjXTRkAFA=", "dev": true }, "qjobs": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.1.5.tgz", - "integrity": "sha1-ZZ3p8s+NzCehSBJ28gU3cnI4LnM=", + "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 }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", "dev": true }, "querystring": { - "version": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, "querystring-es3": { - "version": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, "querystringify": { - "version": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "dev": true }, "random-bytes": { - "version": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", "dev": true }, "randomatic": { - "version": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "dev": true, - "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" - }, "dependencies": { "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true } } }, "randombytes": { - "version": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha1-0wLFIpSFiISKjTAMkytEwkIx2oA=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true }, "randomfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", - "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", - "dev": true, - "requires": { - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true }, "range-parser": { - "version": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", "dev": true }, "raw-body": { - "version": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, "dependencies": { "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, - "read-only-stream": { - "version": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } - }, "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "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": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "path-type": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz" - } + "dev": true }, "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "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": { - "find-up": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz" - } + "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha1-yUbD9H+n2Oq8C2FQ9KEvaaRXQHE=", - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==" }, "readdirp": { - "version": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "set-immediate-shim": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" - } + "dev": true }, "readline2": { - "version": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", "dev": true, - "requires": { - "mute-stream": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz" - }, "dependencies": { "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", "dev": true }, "mute-stream": { - "version": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", "dev": true }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", - "dev": true, - "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" - } + "dev": true } } }, "rechoir": { - "version": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" - } + "dev": true }, "redent": { - "version": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "strip-indent": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz" - } + "dev": true }, "redis": { - "version": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "integrity": "sha1-ICKI4/WMSfYHnZevehDhMDrhSwI=", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", "dev": true, - "optional": true, - "requires": { - "double-ended-queue": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "redis-commands": "1.3.1", - "redis-parser": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz" - } + "optional": true }, "redis-commands": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz", - "integrity": "sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", + "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==", "dev": true, "optional": true }, "redis-parser": { - "version": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", "dev": true, "optional": true }, "regenerate": { - "version": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha1-DDNtOYBVPXVcObWGrjsgqknIK38=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", "dev": true }, "regenerator-runtime": { - "version": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", - "dev": true, - "requires": { - "babel-runtime": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "babel-types": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "private": "https://registry.npmjs.org/private/-/private-0.1.8.tgz" - } + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true }, "regex-cache": { - "version": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", - "dev": true, - "requires": { - "is-equal-shallow": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" - } + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true }, "regex-not": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1" - } + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true }, "regexpu-core": { - "version": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "regjsgen": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "regjsparser": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz" - } + "dev": true }, "regjsgen": { - "version": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, "regjsparser": { - "version": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, - "requires": { - "jsesc": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" - }, "dependencies": { "jsesc": { - "version": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } } }, "remark": { - "version": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", - "integrity": "sha1-xc+o7FNcc6Z8Sw8Sv9vTpn2LL2A=", - "dev": true, - "requires": { - "remark-parse": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "remark-stringify": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", - "unified": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz" - } + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", + "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", + "dev": true }, "remark-html": { - "version": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", - "integrity": "sha1-0T3BupNS4lf86IAMQsdpDZ42kMg=", - "dev": true, - "requires": { - "hast-util-sanitize": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", - "hast-util-to-html": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", - "mdast-util-to-hast": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.0.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", + "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", + "dev": true }, "remark-parse": { - "version": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha1-TAd/nkmQRNHVwT+A16mM97koXZU=", - "dev": true, - "requires": { - "collapse-white-space": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", - "is-alphabetical": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", - "is-decimal": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", - "is-whitespace-character": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", - "is-word-character": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", - "markdown-escapes": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", - "parse-entities": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "state-toggle": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", - "trim": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "trim-trailing-lines": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", - "unherit": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", - "unist-util-remove-position": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", - "vfile-location": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true + }, + "remark-reference-links": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.1.tgz", + "integrity": "sha1-AhrtHFXBh9cSs8dtAFe/UQ0wC6c=", + "dev": true }, "remark-slug": { - "version": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", - "integrity": "sha1-necfzcK/rjPrtKQeuDA1KIqCmYA=", - "dev": true, - "requires": { - "github-slugger": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", - "mdast-util-to-string": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", - "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", + "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", + "dev": true }, "remark-stringify": { - "version": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", - "integrity": "sha1-M206TUpqM5DZM+66YujeS9KAr7o=", - "dev": true, - "requires": { - "ccount": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", - "is-alphanumeric": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", - "is-decimal": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", - "is-whitespace-character": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", - "longest-streak": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "markdown-escapes": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", - "markdown-table": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.1.tgz", - "mdast-util-compact": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", - "parse-entities": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "state-toggle": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", - "stringify-entities": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", - "unherit": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", + "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", + "dev": true }, "remark-toc": { - "version": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", - "integrity": "sha1-8eE+0RBirU0QKwLnAWi9hQFb8Sk=", - "dev": true, - "requires": { - "mdast-util-toc": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", - "remark-slug": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", + "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", + "dev": true }, "remote-origin-url": { - "version": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true, - "requires": { - "parse-git-config": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz" - } + "dev": true }, "remove-bom-buffer": { - "version": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha1-wr8eN3Ug0yT2I4kuM8EMrCwlK1M=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } + "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 }, "remove-bom-stream": { - "version": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "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": { - "remove-bom-buffer": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "dev": true }, "remove-trailing-separator": { - "version": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { - "version": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", "dev": true }, "repeat-string": { - "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "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": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz" - } + "dev": true }, "replace-ext": { - "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", "dev": true }, "replacestream": { - "version": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", - "dev": true, - "requires": { - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } + "dev": true }, "request": { - "version": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "mime-types": "2.1.17", - "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "tough-cookie": "2.3.3", - "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz" - } + "dev": true }, "requestretry": { - "version": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", - "integrity": "sha1-IT7BAG7rdQ6LjOVBdig9FajVXZQ=", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", + "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", "dev": true, - "optional": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "request": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "when": "https://registry.npmjs.org/when/-/when-3.7.8.tgz" - } + "optional": true }, "require-directory": { - "version": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { - "version": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "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 }, "require-uncached": { - "version": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "resolve-from": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz" - } + "dev": true }, "requirejs": { - "version": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", - "integrity": "sha1-YXuay7yzNlQO9JFNeQMjqNS4YbA=", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", + "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", "dev": true }, "requires-port": { - "version": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", - "dev": true, - "requires": { - "path-parse": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz" - } + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "dev": true }, "resolve-dir": { - "version": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "global-modules": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz" - } + "dev": true }, "resolve-from": { - "version": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", "dev": true }, "resolve-options": { - "version": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz" - } + "dev": true }, "resolve-url": { - "version": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "response-time": { - "version": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", "dev": true, - "requires": { - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, "dependencies": { "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true } } }, "restore-cursor": { - "version": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz" - } + "dev": true + }, + "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 }, "rewire": { - "version": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", "dev": true }, "rgb2hex": { - "version": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", "integrity": "sha1-zNVfhgrgxcTqN1BLlY5ELY0SMls=", "dev": true }, "right-align": { - "version": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "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": { - "align-text": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz" - } + "dev": true }, "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", - "dev": true, - "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" - } + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true }, "ripemd160": { - "version": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", - "dev": true, - "requires": { - "hash-base": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true }, "rndm": { - "version": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", "dev": true }, "run-async": { - "version": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz" - } + "dev": true }, "rx": { - "version": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", "dev": true }, "rx-lite": { - "version": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "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": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "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": { - "rx-lite": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz" - } + "dev": true }, "safe-buffer": { - "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safe-json-parse": { - "version": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "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 + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "samsam": { - "version": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha1-jR2TUOJWItow3j5EumkrUiGrfFA=", + "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": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", "dev": true, - "requires": { - "ajv": "5.5.2" - }, "dependencies": { "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" - } + "dev": true } } }, "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true }, "send": { - "version": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "destroy": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "etag": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "mime": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", - "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "mime": { - "version": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "statuses": { - "version": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", "dev": true } } }, "sequencify": { - "version": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", "dev": true }, "serve-favicon": { - "version": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", "dev": true, - "requires": { - "etag": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz" - }, "dependencies": { "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", "dev": true } } }, "serve-index": { - "version": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", "dev": true, - "requires": { - "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", - "batch": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "mime-types": "2.1.17", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } + "dev": true }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "serve-static": { - "version": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", - "dev": true, - "requires": { - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "send": "https://registry.npmjs.org/send/-/send-0.13.2.tgz" - } + "dev": true }, "set-blocking": { - "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-getter": { - "version": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", - "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", - "dev": true, - "requires": { - "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" - } - }, "set-immediate-shim": { - "version": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", "dev": true }, "set-value": { - "version": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "split-string": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" + "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 + } } }, "setimmediate": { - "version": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, "setprototypeof": { - "version": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, "sha.js": { - "version": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", - "integrity": "sha1-sf3lzX0RpWJmOKB8YEq5Cc+jH5s=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - }, - "shasum": { - "version": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", - "dev": true, - "requires": { - "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz" - }, - "dependencies": { - "json-stable-stringify": { - "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", - "dev": true, - "requires": { - "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" - } - } - } + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true }, "shebang-command": { - "version": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "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": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" - } + "dev": true }, "shebang-regex": { - "version": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shell-quote": { - "version": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "array-map": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "array-reduce": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" - } - }, "shelljs": { - "version": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", - "integrity": "sha1-cp4DjEE6IlTEB4uV7UbgOXFUqfE=", - "dev": true, - "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "rechoir": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" - } + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", + "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", + "dev": true }, "sigmund": { - "version": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", "dev": true }, "signal-exit": { - "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "sinon": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.3.0.tgz", - "integrity": "sha512-pmf05hFgEZUS52AGJcsVjOjqAyJW2yo14cOwVYvzCyw7+inv06YXkLyW75WG6X6p951lzkoKh51L2sNbR9CDvw==", - "dev": true, - "requires": { - "@sinonjs/formatio": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", - "diff": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", - "lodash.get": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "lolex": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", - "nise": "1.2.5", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" - }, + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", + "dev": true, "dependencies": { "diff": { - "version": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", - "integrity": "sha1-sdhVB9rzlkgo3lSzfQ1zumfdpWw=", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - } + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true }, "type-detect": { - "version": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=", + "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 } } }, "slack-node": { - "version": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", "dev": true, - "optional": true, - "requires": { - "requestretry": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz" - } + "optional": true }, "slash": { - "version": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true }, "slice-ansi": { - "version": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", + "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, - "requires": { - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" - }, "dependencies": { "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "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 } } }, "slice-stream": { - "version": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "smart-buffer": { - "version": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", "dev": true }, "smtp-connection": { - "version": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true, - "requires": { - "httpntlm": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "nodemailer-shared": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz" - } + "dev": true }, "snapdragon": { - "version": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", - "dev": true, - "requires": { - "base": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "extend-shallow": "2.0.1", - "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "source-map-resolve": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "use": "https://registry.npmjs.org/use/-/use-2.0.2.tgz" - }, + "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": { "atob": { - "version": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.0.tgz", + "integrity": "sha512-SuiKH8vbsOyCALjA/+EINmt/Kdl+TQPrtFgW7XZZcwtryFu9e5kQoX3bjCW6mIvGH1fbeAZZuvwGR5IlBRznGw==", "dev": true }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "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": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-accessor-descriptor": { - "version": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-data-descriptor": { - "version": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - } + "dev": true }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { - "version": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha1-etD1k/IoFZjoVN+A8ZquS5LXoRo=", - "dev": true, - "requires": { - "atob": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "decode-uri-component": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "resolve-url": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "source-map-url": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "urix": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" - } + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true }, "source-map-url": { - "version": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true } } }, "snapdragon-node": { - "version": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "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": { - "define-property": "1.0.0", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "snapdragon-util": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" + "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 + }, + "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 + }, + "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 + }, + "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 + } } }, "snapdragon-util": { - "version": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, "dependencies": { "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true } } }, "sntp": { - "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" - } + "dev": true }, "socket.io": { - "version": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "engine.io": "3.1.4", - "socket.io-adapter": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "socket.io-client": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", - "socket.io-parser": "3.1.2" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true } } }, "socket.io-adapter": { - "version": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", "dev": true }, "socket.io-client": { - "version": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", "dev": true, - "requires": { - "backo2": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "base64-arraybuffer": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "component-bind": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "engine.io-client": "3.1.4", - "has-cors": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "indexof": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "object-component": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "parseqs": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "parseuri": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "socket.io-parser": "3.1.2", - "to-array": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" - }, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true } } }, "socket.io-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.2.tgz", - "integrity": "sha1-28IoIVH8T6675Aru3Ady66YZ9/I=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", + "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", "dev": true, - "requires": { - "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "debug": "2.6.9", - "has-binary2": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", - "isarray": "2.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": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - }, "isarray": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", @@ -13464,564 +9624,378 @@ } }, "socks": { - "version": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", "dev": true, - "requires": { - "ip": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "smart-buffer": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz" - }, "dependencies": { "ip": { - "version": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true } } }, "socks-proxy-agent": { - "version": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", - "integrity": "sha1-huuwcZMlhjeHDhO3vZnybGY989M=", - "dev": true, - "requires": { - "agent-base": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "socks": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz" - } + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", + "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", + "dev": true }, "source-list-map": { - "version": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha1-qqR0A/eyRakvvJfqCPJQ1gh+0IU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-resolve": { - "version": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", - "requires": { - "atob": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", - "resolve-url": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "source-map-url": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", - "urix": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" - } + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=" }, "source-map-support": { - "version": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", + "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": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - }, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "source-map-url": { - "version": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=" }, "space-separated-tokens": { - "version": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz", - "integrity": "sha1-lpW5355lrsGBHUw/nOUlILwvfk0=", - "dev": true, - "requires": { - "trim": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz" - } + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", + "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", + "dev": true }, "sparkles": { - "version": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", "dev": true }, "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true, - "requires": { - "spdx-license-ids": "1.2.2" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true }, "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true }, "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, "split": { - "version": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } + "dev": true }, "split-string": { - "version": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", - "dev": true, - "requires": { - "extend-shallow": "3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "is-extendable": "1.0.1" - } - }, - "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": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" - } - } - } + "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 }, "sprintf-js": { - "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "sshpk": { - "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, - "requires": { - "asn1": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "bcrypt-pbkdf": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "dashdash": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "ecc-jsbn": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "getpass": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" - }, + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "dev": true, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "state-toggle": { - "version": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", - "integrity": "sha1-0g+aYWu08MO5i5GSLSW2QKorxCU=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", "dev": true }, "static-extend": { - "version": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, - "requires": { - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "object-copy": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" - }, "dependencies": { "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "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": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-accessor-descriptor": { - "version": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-data-descriptor": { - "version": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } }, "statuses": { - "version": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, "stream-array": { - "version": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", + "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": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz" - }, "dependencies": { "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "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": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true, - "requires": { - "buffer-shims": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "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": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "dev": true }, "stream-combiner": { - "version": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "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": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" - } + "dev": true }, "stream-combiner2": { - "version": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "requires": { - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "dev": true }, "stream-consume": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", "dev": true }, "stream-counter": { - "version": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "stream-http": { - "version": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", - "integrity": "sha1-/YZUbaybHJGv+PxdKHuY+vtBvBA=", - "dev": true, - "requires": { - "builtin-status-codes": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "to-arraybuffer": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz", + "integrity": "sha512-cQ0jo17BLca2r0GfRdZKYAGLU6JRoIWxqSOakUMuKOT6MOK7AAlE856L33QuDmAy/eeOrhLee3dZKX0Uadu93A==", + "dev": true }, "stream-shift": { - "version": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "stream-splicer": { - "version": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", - "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } - }, "streamroller": { - "version": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", - "dev": true, - "requires": { - "date-format": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "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==" }, "string-replace-webpack-plugin": { - "version": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "css-loader": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", - "file-loader": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "style-loader": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz" - }, "dependencies": { "async": { - "version": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true }, "loader-utils": { - "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "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": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "dev": true } } }, "string-template": { - "version": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", "dev": true }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "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": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } + "dev": true }, "stringify-entities": { - "version": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", "integrity": "sha1-sVDsLXKsTBtfMktR+2soyc3/BYw=", - "dev": true, - "requires": { - "character-entities-html4": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.1.tgz", - "character-entities-legacy": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", - "is-alphanumerical": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", - "is-hexadecimal": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz" - } + "dev": true }, "stringstream": { - "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", "dev": true }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - } + "dev": true }, "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-bom-string": { - "version": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" }, "strip-eof": { - "version": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-indent": { - "version": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "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": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" - } + "dev": true }, "strip-json-comments": { - "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, "style-loader": { - "version": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", "dev": true, "optional": true, - "requires": { - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz" - }, "dependencies": { "loader-utils": { - "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, - "optional": true, - "requires": { - "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "optional": true } } }, "subarg": { - "version": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, - "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" - }, "dependencies": { "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, - "syntax-error": { - "version": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "integrity": "sha1-LZ1P9cBkrLcRWUo+O5UFStUdkHw=", - "dev": true, - "requires": { - "acorn-node": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.3.0.tgz" - } - }, "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, - "requires": { - "ajv": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "ajv-keywords": "2.1.1", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "slice-ansi": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" - }, "dependencies": { "ajv": { - "version": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" - } - }, - "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 }, "ansi-regex": { @@ -14031,22 +10005,16 @@ "dev": true }, "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", - "dev": true, - "requires": { - "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" - } + "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 }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", - "integrity": "sha1-Uj/iZ4rsewToBBkJKS/osXBZt5Y=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" - } + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -14055,1521 +10023,982 @@ "dev": true }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "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": { - "ansi-regex": "3.0.0" - } + "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", - "integrity": "sha1-sNUzOxGE3TZmy+WqC0XFrHrBeko=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - } + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true } } }, "tapable": { - "version": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", "dev": true }, "tar-stream": { - "version": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", "dev": true, - "requires": { - "bl": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", - "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "ternary-stream": { - "version": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true, - "requires": { - "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", - "fork-stream": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", - "merge-stream": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "dev": true }, "text-encoding": { - "version": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", "dev": true }, "text-table": { - "version": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "textextensions": { - "version": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", "dev": true }, "through": { - "version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=" }, "through2-filter": { - "version": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "dev": true }, "thunkify": { - "version": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", "dev": true }, "tildify": { - "version": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" - } + "dev": true }, "time-stamp": { - "version": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "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": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", - "dev": true, - "requires": { - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz" - } + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true }, "timers-ext": { - "version": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", - "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", - "requires": { - "es5-ext": "0.10.38", - "next-tick": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz" - } + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", + "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==" }, "timespan": { - "version": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", "dev": true, "optional": true }, "tiny-lr": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.0.tgz", - "integrity": "sha512-f4X68a6KHcCx/XJcZUKAa92APjY9EHxuGOzRFmPRjf+fOp1E7fi4dGJaHMxvRBxwZrHrIvn/AwkFaDS7O1WZDQ==", - "dev": true, - "requires": { - "body": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "debug": "2.6.9", - "faye-websocket": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "livereload-js": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz" - }, + "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": { - "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": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", "dev": true } } }, "tmp": { - "version": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", - "dev": true, - "requires": { - "os-tmpdir": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" - } + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true }, "to-absolute-glob": { - "version": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "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": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "is-negated-glob": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz" - } + "dev": true }, "to-array": { - "version": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, "to-arraybuffer": { - "version": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "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": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, "to-object-path": { - "version": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "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": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, "dependencies": { "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true } } }, "to-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz", - "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "regex-not": "1.0.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.6" - } - }, - "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "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 - } - } + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true }, "to-regex-range": { - "version": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "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": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - } + "dev": true }, "to-through": { - "version": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } + "dev": true }, "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "dev": true, - "requires": { - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" - } + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true }, "traverse": { - "version": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", "dev": true }, "trim": { - "version": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", "dev": true }, "trim-lines": { - "version": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.0.tgz", - "integrity": "sha1-mSbQPt4Tuhj31CIiYx+wTHn/Jv4=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.1.tgz", + "integrity": "sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==", "dev": true }, "trim-newlines": { - "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, "trim-right": { - "version": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, "trim-trailing-lines": { - "version": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", "integrity": "sha1-eu+7eAjfnWafbaLkOMrIxGradoQ=", "dev": true }, "trough": { - "version": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", - "integrity": "sha1-qf2LA5Swro//guBjOgo2zK1bX4Y=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.2.tgz", + "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", "dev": true }, "tsscmp": { - "version": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", "dev": true }, "tty-browserify": { - "version": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha1-PwUlHuF5BN/QZ3VGZw25ZRaCuBE=", + "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": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", "dev": true }, "tweetnacl": { - "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true, "optional": true }, "type-check": { - "version": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" - } + "dev": true }, "type-detect": { - "version": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", - "dev": true, - "requires": { - "media-typer": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "mime-types": "2.1.17" - } + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true }, "typedarray": { - "version": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "uglify-js": { - "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "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": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "uglify-to-browserify": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz" - }, "dependencies": { "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true }, "cliui": { - "version": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "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": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "right-align": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" - } + "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "window-size": { - "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true }, "wordwrap": { - "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "cliui": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" - } + "dev": true } } }, "uglify-to-browserify": { - "version": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "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 }, "uglifyjs-webpack-plugin": { - "version": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "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": { - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "webpack-sources": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz" - }, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "uid-safe": { - "version": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", - "dev": true, - "requires": { - "random-bytes": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" - } - }, - "ultron": { - "version": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", "dev": true }, - "umd": { - "version": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", - "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", "dev": true }, "unc-path-regex": { - "version": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "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 }, "underscore": { - "version": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", "dev": true }, - "underscore.string": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", - "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", - "dev": true - }, "unherit": { - "version": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", "integrity": "sha1-a5qu379z3xdWrZ4xbdmBiFhAzX0=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "dev": true }, "unified": { - "version": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", - "integrity": "sha1-Xqf4B6CJjx+Kze7+XyX6oBDMQrE=", - "dev": true, - "requires": { - "bail": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "is-plain-obj": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "trough": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", - "vfile": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "x-is-function": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", - "x-is-string": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz" - } + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", + "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", + "dev": true }, "union-value": { - "version": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, - "requires": { - "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "set-value": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz" - }, "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 + }, "set-value": { - "version": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" - } + "dev": true } } }, "unique-stream": { - "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "through2-filter": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz" - } + "dev": true }, "unist-builder": { - "version": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", - "dev": true, - "requires": { - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "dev": true }, "unist-util-generated": { - "version": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.1.tgz", "integrity": "sha1-mfFseJWayFTe58YVwpGSTIv03n8=", "dev": true }, "unist-util-is": { - "version": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", "integrity": "sha1-DDEmKeP5YMZukx6BLT2A53AQlHs=", "dev": true }, "unist-util-modify-children": { - "version": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", "integrity": "sha1-ZtfmpEnm9nIguXarPLi166w55R0=", - "dev": true, - "requires": { - "array-iterate": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.1.tgz" - } + "dev": true }, "unist-util-position": { - "version": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.0.tgz", "integrity": "sha1-5uHgPu64HF4a/lU+jUrfvXwNj4I=", "dev": true }, "unist-util-remove-position": { - "version": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", "integrity": "sha1-WoXBVV/BugwQG4ZwfRXlD6TIcbs=", - "dev": true, - "requires": { - "unist-util-visit": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz" - } + "dev": true }, "unist-util-stringify-position": { - "version": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", "integrity": "sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=", "dev": true }, "unist-util-visit": { - "version": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", - "integrity": "sha1-Qcp8gpgf0c5sdiqsOX/CTjVxFEQ=", - "dev": true, - "requires": { - "unist-util-is": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz" - } + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", + "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", + "dev": true }, "unpipe": { - "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, "unset-value": { - "version": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "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": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - }, "dependencies": { "has-value": { - "version": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, - "requires": { - "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "has-values": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" - }, "dependencies": { "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - } + "dev": true } } }, "has-values": { - "version": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true } } }, "unzip": { - "version": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", "dev": true, - "requires": { - "binary": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "fstream": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", - "match-stream": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", - "pullstream": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "upath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.0.tgz", - "integrity": "sha1-tHBrlGHKhHOt+JEz0jVonKF/NlY=", - "dev": true, - "requires": { - "lodash": "3.10.1", - "underscore.string": "2.3.3" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - } - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.4.tgz", + "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==", + "dev": true }, "urix": { - "version": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url": { - "version": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", "dev": true, - "requires": { - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" - }, "dependencies": { "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } } }, "url-parse": { - "version": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha1-OhnoqqbQI93SfcxEy0/I9/7COYY=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz", + "integrity": "sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==", "dev": true, - "requires": { - "querystringify": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "requires-port": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" - }, "dependencies": { "querystringify": { - "version": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", "dev": true } } }, "use": { - "version": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", - "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", - "dev": true, - "requires": { - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "lazy-cache": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz" - }, - "dependencies": { - "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-accessor-descriptor": { - "version": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-data-descriptor": { - "version": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", - "dev": true - } - } + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true }, "user-home": { - "version": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", "dev": true }, "useragent": { - "version": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", + "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "dev": true, - "requires": { - "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "tmp": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" + "dependencies": { + "lru-cache": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "dev": true + } } }, "util": { - "version": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, "dependencies": { "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", "dev": true } } }, "util-deprecate": { - "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { - "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", "dev": true }, "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ=", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", "dev": true }, "uws": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/uws/-/uws-0.14.5.tgz", - "integrity": "sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw=", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", + "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", "dev": true, "optional": true }, "v8flags": { - "version": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" - } + "dev": true }, "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true, - "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" - } + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true }, "value-or-function": { - "version": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "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": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", "dev": true }, "verror": { - "version": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" - }, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "vfile": { - "version": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha1-5i2OcrIOg8MkvGxnJ47ickiL+Eo=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "unist-util-stringify-position": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", - "vfile-message": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz" - } + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true }, "vfile-location": { - "version": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", "integrity": "sha1-02dcWch3SY5JK0dW/2Xkrxp1IlU=", "dev": true }, "vfile-message": { - "version": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", - "integrity": "sha1-pq2wR06kAPol2Snx1nOr6moX41k=", - "dev": true, - "requires": { - "unist-util-stringify-position": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz" - } + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", + "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", + "dev": true }, "vfile-reporter": { - "version": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, - "requires": { - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "unist-util-stringify-position": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", - "vfile-statistics": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.0.tgz" - }, "dependencies": { "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "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": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz" - } + "dev": true } } }, "vfile-sort": { - "version": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.0.tgz", "integrity": "sha1-SVAcnou+Wt/y6bOnZx7hseIMUhA=", "dev": true }, "vfile-statistics": { - "version": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.0.tgz", "integrity": "sha1-AhBMYP3u0dEbH3OtZTMLdjSz2JU=", "dev": true }, "vhost": { - "version": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", "dev": true }, "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "clone-buffer": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "cloneable-readable": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz" - } + "dev": true }, "vinyl-fs": { - "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", - "integrity": "sha1-G4YliEQ4P1dYH8qsCB/gnvbW11I=", - "dev": true, - "requires": { - "fs-mkdirp-stream": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "is-valid-glob": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "lazystream": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "lead": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "object.assign": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "pumpify": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "remove-bom-buffer": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "remove-bom-stream": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "resolve-options": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "to-through": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "value-or-function": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "vinyl-sourcemap": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz" - } + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", + "integrity": "sha512-AUSFda1OukBwuLPBTbyuO4IRWgfXmqC4UTW0f8xrCa8Hkv9oyIU+NSqBlgfOLZRoUt7cHdo75hKQghCywpIyIw==", + "dev": true }, "vinyl-sourcemap": { - "version": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "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": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "now-and-later": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", - "remove-bom-buffer": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz" - } + "dev": true }, "vinyl-sourcemaps-apply": { - "version": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "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": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - }, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "vlq": { - "version": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha1-jz5DKM9jsVQMDWfhsneDhviXWyY=", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", "dev": true }, "vm-browserify": { - "version": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" - } + "dev": true }, "void-elements": { - "version": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, "walk": { - "version": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz", - "integrity": "sha1-MbTbZnjyrgHDnqn7hyWpAx5Vins=", - "dev": true, - "requires": { - "foreachasync": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz" - } + "version": "2.3.13", + "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.13.tgz", + "integrity": "sha512-78SMe7To9U7kqVhSoGho3GfspA089ZDBIj2f8jElg2hi6lUCoagtDJ8sSMFNlpAh5Ib8Jt1gQ6Y7gh9mzHtFng==", + "dev": true }, "watchpack": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", - "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", - "dev": true, - "requires": { - "async": "2.6.0", - "chokidar": "1.7.0", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" - }, - "dependencies": { - "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": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" - } - }, - "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": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" - } - }, - "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": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true, - "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } - }, - "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": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" - } - }, - "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": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "fsevents": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "glob-parent": "2.0.0", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "is-glob": "2.0.1", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" - } - }, - "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": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" - } - }, - "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" - } - }, - "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" - } - }, - "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - }, - "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": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" - } - } - } + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz", + "integrity": "sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==", + "dev": true }, "webdriverio": { - "version": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz", "integrity": "sha1-2dTTwxNm8FPhCvZEsOqtXoc6t7U=", "dev": true, - "requires": { - "archiver": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", - "array.from": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", - "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "css-parse": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "css-value": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", - "deepmerge": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", - "ejs": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "inquirer": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", - "is-generator": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", - "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "q": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", - "request": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", - "rgb2hex": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", - "url": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "wgxpath": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz" - }, "dependencies": { "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", "dev": true }, "asn1": { - "version": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", "dev": true }, "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", "dev": true }, "async": { - "version": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true }, "aws-sign2": { - "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", "dev": true }, "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", - "dev": true, - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" - } + "dev": true }, "caseless": { - "version": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", "dev": true }, "cli-width": { - "version": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", "dev": true }, "combined-stream": { - "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", - "dev": true, - "requires": { - "delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" - } + "dev": true }, "cryptiles": { - "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", - "dev": true, - "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" - } + "dev": true }, "delayed-stream": { - "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", "dev": true }, "figures": { - "version": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "dev": true }, "forever-agent": { - "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", "dev": true }, "form-data": { - "version": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", - "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", - "mime": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" - } + "dev": true }, "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } + "dev": true }, "hawk": { - "version": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", - "dev": true, - "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", - "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", - "hoek": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", - "sntp": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" - } + "dev": true }, "hoek": { - "version": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", "dev": true }, "http-signature": { - "version": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", - "dev": true, - "requires": { - "asn1": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "ctype": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" - } + "dev": true }, "inquirer": { - "version": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", - "dev": true, - "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "cli-width": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", - "figures": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "readline2": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", - "rx": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } + "dev": true }, "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true }, "mime": { - "version": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", "dev": true }, "mime-types": { - "version": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", "dev": true }, "node-uuid": { - "version": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, "oauth-sign": { - "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", "dev": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", "dev": true }, "request": { - "version": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", + "version": "2.49.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", "integrity": "sha1-DU9jSNwzSAWbVT5Ntg/SR43mYqc=", - "dev": true, - "requires": { - "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", - "bl": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", - "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", - "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", - "form-data": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", - "hawk": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", - "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", - "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", - "node-uuid": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", - "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "tough-cookie": "2.3.3", - "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" - } + "dev": true }, "sntp": { - "version": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", - "dev": true, - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" - } + "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", "dev": true } } }, "webpack": { - "version": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", - "integrity": "sha1-d9pFGx17SxF62vQaGpO1dC8k2JQ=", - "dev": true, - "requires": { - "acorn": "5.4.1", - "acorn-dynamic-import": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", - "ajv": "6.1.1", - "ajv-keywords": "3.1.0", - "async": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "enhanced-resolve": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", - "escope": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "json-loader": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "loader-runner": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "node-libs-browser": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", - "uglifyjs-webpack-plugin": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", - "watchpack": "1.4.0", - "webpack-sources": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz" - }, + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", + "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", + "dev": true, "dependencies": { - "ajv": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.1.1.tgz", - "integrity": "sha1-l41Zf7wrfQ5aXD3esUmmgvKr+g4=", - "dev": true, - "requires": { - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" - } - }, "ajv-keywords": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", @@ -15577,801 +11006,606 @@ "dev": true }, "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "async": { - "version": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", - "dev": true, - "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" - } + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true }, "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "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": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "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 }, "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" - } + "dev": true }, "parse-json": { - "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "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": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" - } + "dev": true }, "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" - } + "dev": true }, "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "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": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "path-type": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz" - } + "dev": true }, "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "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": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz" - } + "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", - "dev": true, - "requires": { - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" - } + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "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": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" - } + "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "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": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz" - } + "dev": true }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true, - "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "get-caller-file": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "require-directory": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "require-main-filename": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "which-module": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "yargs-parser": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz" - } + "dev": true } } }, "webpack-core": { - "version": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, - "requires": { - "source-list-map": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz" - }, "dependencies": { "source-list-map": { - "version": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", + "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": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" - } + "dev": true } } }, "webpack-dev-middleware": { - "version": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", - "integrity": "sha1-+PwRIM47T8VoDO7LQ9d3lmshEF4=", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", "dev": true, - "requires": { - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "mime": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", - "time-stamp": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz" - }, "dependencies": { - "mime": { - "version": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", - "dev": true - }, "time-stamp": { - "version": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", "dev": true } } }, "webpack-sources": { - "version": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha1-oQHrrlnWUHNU1x2AE5UKOot6WlQ=", - "dev": true, - "requires": { - "source-list-map": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true }, "webpack-stream": { - "version": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", "dev": true, - "requires": { - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "lodash.clone": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "lodash.some": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "webpack": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz" - }, "dependencies": { "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "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": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", - "dev": true, - "requires": { - "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" - } + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true }, "arr-diff": { - "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "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": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" - } + "dev": true }, "array-unique": { - "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, "braces": { - "version": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" - } + "dev": true }, "browserify-aes": { - "version": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } + "dev": true }, "browserify-zlib": { - "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "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": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz" - } - }, - "buffer": { - "version": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "1.2.1", - "ieee754": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - } + "dev": true }, "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true }, "chokidar": { - "version": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "fsevents": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" - } + "dev": true }, "cliui": { - "version": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "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": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "right-align": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" - } + "dev": true }, "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "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": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", + "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": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", - "pbkdf2-compat": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", - "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz" - } + "dev": true }, "enhanced-resolve": { - "version": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", - "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz" - }, "dependencies": { "memory-fs": { - "version": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", "dev": true } } }, "expand-brackets": { - "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "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": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" - } + "dev": true }, "extglob": { - "version": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } + "dev": true }, "glob-parent": { - "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "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": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } + "dev": true }, "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "https-browserify": { - "version": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", "dev": true }, "interpret": { - "version": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", "dev": true }, "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "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": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "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": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } + "dev": true }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "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": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "dev": true }, "loader-utils": { - "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "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": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - } + "dev": true }, "lodash.clone": { - "version": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", "dev": true }, "memory-fs": { - "version": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "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.6", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" - } + "dev": true }, "micromatch": { - "version": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "braces": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "extglob": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "filename-regex": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" - } + "dev": true }, "node-libs-browser": { - "version": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", + "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": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "buffer": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", - "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", - "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", - "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz" - } + "dev": true }, "os-browserify": { - "version": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "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": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, "replace-ext": { - "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, "ripemd160": { - "version": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "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": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" - } + "dev": true }, "tapable": { - "version": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", "dev": true }, - "timers-browserify": { - "version": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", - "integrity": "sha1-JB52kn2coF9NlZgZAi9bNmS2S64=", - "dev": true, - "requires": { - "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" - } - }, - "tty-browserify": { - "version": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, "uglify-js": { - "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "uglify-to-browserify": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz" - }, "dependencies": { "async": { - "version": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true } } }, "url": { - "version": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, - "requires": { - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" - }, "dependencies": { "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } } }, "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" - } + "dev": true }, "watchpack": { - "version": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "chokidar": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" - }, "dependencies": { "async": { - "version": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true } } }, "webpack": { - "version": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "dev": true, - "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "async": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "enhanced-resolve": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "interpret": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "node-libs-browser": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", - "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "watchpack": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", - "webpack-core": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz" - } + "dev": true }, "window-size": { - "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true }, "wordwrap": { - "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "cliui": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" - } + "dev": true } } }, "websocket-driver": { - "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true, - "requires": { - "http-parser-js": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "websocket-extensions": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz" - } + "dev": true }, "websocket-extensions": { - "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", "dev": true }, "wgxpath": { - "version": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", "dev": true }, "when": { - "version": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", "dev": true, "optional": true }, "which": { - "version": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", - "dev": true, - "requires": { - "isexe": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - } + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true }, "which-module": { - "version": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "window-size": { - "version": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", "dev": true }, "wordwrap": { - "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "wrap-ansi": { - "version": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "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": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - } + "dev": true }, "wrappy": { - "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "write": { - "version": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" - } + "dev": true }, "ws": { - "version": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", - "dev": true, - "requires": { - "async-limiter": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "ultron": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz" - } + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true }, "x-is-function": { - "version": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", "integrity": "sha1-XSlNw9Joy90GJYDgxd93o5HR+h4=", "dev": true }, "x-is-string": { - "version": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", "dev": true }, "xmlhttprequest-ssl": { - "version": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, "xregexp": { - "version": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", "dev": true }, "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { - "version": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, "yallist": { - "version": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", "dev": true }, "yargs-parser": { - "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "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": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz" - } + "dev": true }, "yeast": { - "version": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", "dev": true }, "zip-stream": { - "version": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", "dev": true, - "requires": { - "compress-commons": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - }, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } + "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } diff --git a/package.json b/package.json index 44c54b468f6..36374cd5f22 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,7 @@ "ajv": "6.2.0", "babel-core": "6.22.0", "babel-loader": "^7.1.1", - "babel-plugin-transform-es3-member-expression-literals": "6.22.0", - "babel-plugin-transform-es3-property-literals": "6.22.0", - "babel-preset-es2015": "6.22.0", + "babel-preset-env": "^1.6.1", "block-loader": "^2.1.0", "chai": "^3.3.0", "coveralls": "^2.11.11", diff --git a/webpack.conf.js b/webpack.conf.js index 38f4e5dadd7..4b53aabef22 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -29,9 +29,6 @@ module.exports = { use: [ { loader: 'babel-loader', - options: { - presets: ['es2015'] - } } ] }, @@ -41,9 +38,6 @@ module.exports = { use: [ { loader: 'babel-loader', - options: { - presets: ['es2015'] - } } ], }, From 53fbc7dc6c573ada6ac4a760555876e34e28e819 Mon Sep 17 00:00:00 2001 From: John Salis Date: Mon, 7 May 2018 09:53:33 -0400 Subject: [PATCH 0329/1594] Add GDPR support to Beachfront adapter (#2474) * add GDPR consent data to the bid requests * add GDPR consent data to the bid requests --- modules/beachfrontBidAdapter.js | 32 +++++++++++++++---- .../spec/modules/beachfrontBidAdapter_spec.js | 32 +++++++++++++++++++ 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 6f92bc0d976..4e528896e72 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -24,7 +24,7 @@ export const spec = { return !!(bid && bid.params && bid.params.appId && bid.params.bidfloor); }, - buildRequests(bids) { + buildRequests(bids, bidderRequest) { let requests = []; let videoBids = bids.filter(bid => isVideoBid(bid)); let bannerBids = bids.filter(bid => !isVideoBid(bid)); @@ -32,7 +32,7 @@ export const spec = { requests.push({ method: 'POST', url: VIDEO_ENDPOINT + bid.params.appId, - data: createVideoRequestData(bid), + data: createVideoRequestData(bid, bidderRequest), bidRequest: bid }); }); @@ -40,7 +40,7 @@ export const spec = { requests.push({ method: 'POST', url: BANNER_ENDPOINT, - data: createBannerRequestData(bannerBids), + data: createBannerRequestData(bannerBids, bidderRequest), bidRequest: bannerBids }); } @@ -184,11 +184,11 @@ function getVideoParams(bid) { }, {}); } -function createVideoRequestData(bid) { +function createVideoRequestData(bid, bidderRequest) { let size = getFirstSize(bid); let video = getVideoParams(bid); let topLocation = utils.getTopWindowLocation(); - return { + let payload = { isPrebid: true, appId: bid.params.appId, domain: document.location.hostname, @@ -214,11 +214,21 @@ function createVideoRequestData(bid) { js: 1, geo: {} }, + regs: {}, + user: {}, cur: ['USD'] }; + + if (bidderRequest && bidderRequest.gdprConsent) { + let { consentRequired, consentString } = bidderRequest.gdprConsent; + payload.regs.ext = { gdpr: consentRequired ? 1 : 0 }; + payload.user.ext = { consent: consentString }; + } + + return payload; } -function createBannerRequestData(bids) { +function createBannerRequestData(bids, bidderRequest) { let topLocation = utils.getTopWindowLocation(); let referrer = utils.getTopWindowReferrer(); let slots = bids.map(bid => { @@ -229,7 +239,7 @@ function createBannerRequestData(bids) { sizes: getSizes(bid) }; }); - return { + let payload = { slots: slots, page: topLocation.href, domain: topLocation.hostname, @@ -243,6 +253,14 @@ function createBannerRequestData(bids) { adapterVersion: ADAPTER_VERSION, adapterName: ADAPTER_NAME }; + + if (bidderRequest && bidderRequest.gdprConsent) { + let { consentRequired, consentString } = bidderRequest.gdprConsent; + payload.gdpr = consentRequired ? 1 : 0; + payload.gdprConsent = consentString; + } + + return payload; } registerBidder(spec); diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 5a0345ee6e2..65bc0818a6c 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -166,6 +166,22 @@ describe('BeachfrontAdapter', () => { const data = requests[0].data; expect(data.imp[0].video).to.deep.contain({ mimes }); }); + + it('must add GDPR consent data to the request', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + const bidderRequest = { + gdprConsent: { + consentRequired: true, + consentString + } + }; + const requests = spec.buildRequests([ bidRequest ], bidderRequest); + const data = requests[0].data; + expect(data.regs.ext.gdpr).to.equal(1); + expect(data.user.ext.consent).to.equal(consentString); + }); }); describe('for banner bids', () => { @@ -265,6 +281,22 @@ describe('BeachfrontAdapter', () => { const data = requests[0].data; expect(data.slots[0].sizes).to.deep.contain({ w: width, h: height }); }); + + it('must add GDPR consent data to the request', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { banner: {} }; + const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + const bidderRequest = { + gdprConsent: { + consentRequired: true, + consentString + } + }; + const requests = spec.buildRequests([ bidRequest ], bidderRequest); + const data = requests[0].data; + expect(data.gdpr).to.equal(1); + expect(data.gdprConsent).to.equal(consentString); + }); }); }); From a348d8fbed853b06cef43605bf7020ee59660b53 Mon Sep 17 00:00:00 2001 From: OneTagDevOps <38786435+OneTagDevOps@users.noreply.github.com> Date: Mon, 7 May 2018 17:47:25 +0200 Subject: [PATCH 0330/1594] New Adapter onetagBidAdapter (#2461) * Add New Adapter onetagBidAdapter * Test for new adapter onetagBidAdapter * Update onetagBidAdapter.js * Update onetagBidAdapter_spec.js --- modules/onetagBidAdapter.js | 170 +++++++++++++++++++++ modules/onetagBidAdapter.md | 34 +++++ test/spec/modules/onetagBidAdapter_spec.js | 129 ++++++++++++++++ 3 files changed, 333 insertions(+) create mode 100644 modules/onetagBidAdapter.js create mode 100644 modules/onetagBidAdapter.md create mode 100644 test/spec/modules/onetagBidAdapter_spec.js diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js new file mode 100644 index 00000000000..96a85a6070d --- /dev/null +++ b/modules/onetagBidAdapter.js @@ -0,0 +1,170 @@ +'use strict'; + +const { registerBidder } = require('../src/adapters/bidderFactory'); + +const ENDPOINT = 'https://onetag-sys.com/prebid-request'; +const BIDDER_CODE = 'onetag'; +const BANNER = 'banner'; + +// ======= +// Object BidRequest +// +// .params +// required .pubId: string +// optional .type: "BANNER" | "VIDEO" | "NATIVE" --> only BANNER at present + +/** + * 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. + */ +function isBidRequestValid(bid) { + if (typeof bid === 'undefined' || bid.bidder !== BIDDER_CODE || typeof bid.params === 'undefined') { + return false; + } + + if (typeof bid.params.pubId !== 'string' || bid.sizes === 'undefined' || bid.sizes.length === 0) { + return false; + } + + return true; +} + +/** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + +function buildRequests(validBidRequests) { + const bids = validBidRequests.map(requestsToBids); + const bidObject = {'bids': bids}; + const pageInfo = getPageInfo(); + + const payload = Object.assign(bidObject, pageInfo); + const payloadString = JSON.stringify(payload); + + return { + method: 'POST', + url: ENDPOINT, + data: payloadString + } +} + +function interpretResponse(serverResponse, request) { + var body = serverResponse.body; + const bids = []; + + if (typeof serverResponse === 'string') { + try { + body = JSON.parse(serverResponse); + } catch (e) { + return bids; + } + } + + if (!body || (body.nobid && body.nobid === true)) { + return bids; + } + + if (body.bids) { + body.bids.forEach(function(bid) { + bids.push({ + requestId: bid.requestId, + cpm: bid.cpm, + width: bid.width, + height: bid.height, + creativeId: bid.creativeId, + dealId: bid.dealId ? bid.dealId : '', + currency: bid.currency, + netRevenue: false, + mediaType: bids.type ? bids.type : BANNER, + ad: bid.ad, + ttl: bid.ttl || 6000 + }); + }); + } + + return bids; +} + +/** + * Returns information about the page needed by the server in an object to be converted in JSON + * @returns {{location: *, referrer: (*|string), masked: *, wWidth: (*|Number), wHeight: (*|Number), sWidth, sHeight, date: string, timeOffset: number}} + */ +function getPageInfo() { + var w, d, l, r, m, p, e, t, s; + for (w = window, d = w.document, l = d.location.href, r = d.referrer, m = 0, e = encodeURIComponent, t = new Date(), s = screen; 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 + } + } + + const params = { + + location: e(l), + referrer: e(r) || '0', + masked: m, + wWidth: w.innerWidth, + wHeight: w.innerHeight, + sWidth: s.width, + sHeight: s.height, + date: t.toUTCString(), + timeOffset: t.getTimezoneOffset() + }; + + return params; +} + +function requestsToBids(bid) { + const toRet = {}; + + const params = bid.params; + + toRet['adUnitCode'] = bid.adUnitCode; + toRet['bidId'] = bid.bidId; + toRet['bidderRequestId'] = bid.bidderRequestId; + toRet['auctionId'] = bid.auctionId; + toRet['transactionId'] = bid.transactionId; + toRet['sizes'] = []; + const sizes = bid.sizes; + for (let i = 0, lenght = sizes.length; i < lenght; i++) { + const size = sizes[i]; + toRet['sizes'].push({width: size[0], height: size[1]}) + } + + toRet['pubId'] = params.pubId; + if (params.type) { + toRet['type'] = params.type; + } + + if (params.pubClick) { + toRet['click'] = params.pubClick; + } + + if (params.dealId) { + toRet['dealId'] = params.dealId; + } + + return toRet; +} + +// Va bene così, questo file va aggiunto a prebidmaster +export const spec = { + + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: isBidRequestValid, + buildRequests: buildRequests, + interpretResponse: interpretResponse, + +}; + +// Starting point +registerBidder(spec); diff --git a/modules/onetagBidAdapter.md b/modules/onetagBidAdapter.md new file mode 100644 index 00000000000..38872ad8280 --- /dev/null +++ b/modules/onetagBidAdapter.md @@ -0,0 +1,34 @@ +# Overview + +``` +Module Name: OneTag Bid Adapter +Module Type: Bidder Adapter +Maintainer: devops@onetag.com +``` + +# Description + +OneTag Bid Adapter supports only banner at present. + +# Test Parameters +``` + var adUnits = [ + { + code: "test-div", + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: "onetag", + params: { + pubId: "your_publisher_id", // required + type: "banner" // optional. Default "banner" + }, + } + ] + }]; + +``` diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js new file mode 100644 index 00000000000..dfd3254fd75 --- /dev/null +++ b/test/spec/modules/onetagBidAdapter_spec.js @@ -0,0 +1,129 @@ +import { spec } from 'modules/onetagBidAdapter'; +import { expect } from 'chai'; + +describe('onetag', () => { + let bid = { + 'bidder': 'onetag', + 'params': { + 'pubId': '386276e072', + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': 'qwerty123' + }; + + describe('isBidRequestValid', () => { + it('Should return true when required params are found', () => { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when pubId is not a string', () => { + bid.params.pubId = 30; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + it('Should return false when pubId is undefined', () => { + bid.params.pubId = undefined; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + it('Should return false when the sizes array is empty', () => { + bid.sizes = []; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', () => { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', () => { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', () => { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', () => { + expect(serverRequest.url).to.equal('https://onetag-sys.com/prebid-request'); + }); + + const d = serverRequest.data; + try { + const data = JSON.parse(d); + it('Should contains all keys', () => { + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('location', 'masked', 'referrer', 'sHeight', 'sWidth', 'timeOffset', 'date', 'wHeight', 'wWidth', 'bids'); + expect(data.location).to.be.a('string'); + expect(data.masked).to.be.a('number'); + expect(data.referrer).to.be.a('string'); + expect(data.sHeight).to.be.a('number'); + expect(data.sWidth).to.be.a('number'); + expect(data.wWidth).to.be.a('number'); + expect(data.wHeight).to.be.a('number'); + expect(data.timeOffset).to.be.a('number'); + expect(data.date).to.be.a('string'); + expect(data.bids).to.be.an('array'); + + const bids = data['bids']; + for (let i = 0; i < bids.length; i++) { + const bid = bids[i]; + expect(bid).to.have.all.keys('adUnitCode', 'auctionId', 'bidId', 'bidderRequestId', 'pubId', 'transactionId', 'sizes'); + expect(bid.bidId).to.be.a('string'); + expect(bid.pubId).to.be.a('string'); + } + }); + } catch (e) { + console.log('Error while parsing'); + } + it('Returns empty data if no valid requests are passed', () => { + serverRequest = spec.buildRequests([]); + let dataString = serverRequest.data; + try { + let dataObj = JSON.parse(dataString); + expect(dataObj.bids).to.be.an('array').that.is.empty; + } catch (e) { + console.log('Error while parsing'); + } + }); + }); + describe('interpretResponse', () => { + const resObject = { + body: { + nobid: false, + bids: [{ + ad: '
Advertising
', + cpm: 13, + width: 300, + height: 250, + creativeId: '1820', + dealId: 'dishfo', + currency: 'USD', + requestId: 'sdiceobxcw' + }] + } + }; + it('Returns an array of valid server responses if response object is valid', () => { + const serverResponses = spec.interpretResponse(resObject); + + 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', 'dealId'); + 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'); + } + it('Returns an empty array if invalid response is passed', () => { + const serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); +}); From 95291857fe98ce8b6efc78db1c7e690f36c467c5 Mon Sep 17 00:00:00 2001 From: Rade Popovic <32302052+nanointeractive@users.noreply.github.com> Date: Mon, 7 May 2018 17:54:01 +0200 Subject: [PATCH 0331/1594] New optional parameter - subId (#2495) * nanointeractive bid adapter * nanointeractive bid adapter * - using utils.getParameterByName instead of utils.getTopWindowLocation().href - bidderCode is removed - Default ALG changed to 'ihr' - added protocol to 'cors' param * markdown file * enabling localhost for bid requests * Bugfix interpretResponse - added body; Removed unnecessary parameters; Adjusted tests; * New feature - subId * Fixed lint errors --- modules/nanointeractiveBidAdapter.js | 6 +++++ modules/nanointeractiveBidAdapter.md | 26 +++++++++++++++---- .../modules/nanointeractiveBidAdapter_spec.js | 4 ++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index 225859a4360..549695369c8 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -9,6 +9,7 @@ export const DATA_PARTNER_PIXEL_ID = 'pid'; export const NQ = 'nq'; export const NQ_NAME = 'name'; export const CATEGORY = 'category'; +export const SUB_ID = 'subId'; export const spec = { @@ -43,6 +44,7 @@ function createSingleBidRequest(bid) { return { [DATA_PARTNER_PIXEL_ID]: bid.params[DATA_PARTNER_PIXEL_ID], [NQ]: [createNqParam(bid), createCategoryParam(bid)], + [SUB_ID]: createSubIdParam(bid), sizes: bid.sizes.map(value => value[0] + 'x' + value[1]), bidId: bid.bidId, cors: utils.getOrigin() @@ -71,6 +73,10 @@ function createCategoryParam(bid) { return bid.params[CATEGORY] || null; } +function createSubIdParam(bid) { + return bid.params[SUB_ID] || null; +} + function isEngineResponseValid(response) { return !!response.cpm && !!response.ad; } diff --git a/modules/nanointeractiveBidAdapter.md b/modules/nanointeractiveBidAdapter.md index 0df49999492..0813a461493 100644 --- a/modules/nanointeractiveBidAdapter.md +++ b/modules/nanointeractiveBidAdapter.md @@ -8,7 +8,7 @@ Maintainer: rade@nanointeractive.com # Description -Connects to NanoInteractive search retargeting Ad Server for bids. +Connects to Nano Interactive search retargeting Ad Server for bids. Besides standard params, please provide, if exist, user search params. @@ -20,7 +20,6 @@ Three examples calling the Ad Server. **Third** is with the search query param name of the current url - # Test Parameters ``` var adUnits = [ @@ -31,7 +30,11 @@ var adUnits = [ bids: [{ bidder: 'nanointeractive', params: { - pid: '58bfec94eb0a1916fa380163' + // required + pid: '58bfec94eb0a1916fa380163', + // optional parameters + category: 'some category', + subId: '123' } }] }, @@ -42,8 +45,12 @@ var adUnits = [ bids: [{ bidder: 'nanointeractive', params: { + // required pid: '58bfec94eb0a1916fa380163', - nq: 'user search' + // optional parameters + nq: 'user search', + category: 'some category', + subId: '123' } }] }, @@ -54,10 +61,19 @@ var adUnits = [ bids: [{ bidder: 'nanointeractive', params: { + // required pid: '58bfec94eb0a1916fa380163', - name: 'search' + // optional parameters + name: 'search', + category: 'some category', + subId: '123' } }] } ]; ``` + +### Requirements: +To be able to get identification key (`pid`), you must register at
+`https://audiencemanager.de/public/data-partners-register`
+and follow further instructions. \ No newline at end of file diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index cafe7bf2799..92b6fe8d797 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as utils from 'src/utils'; import { - BIDDER_CODE, CATEGORY, DATA_PARTNER_PIXEL_ID, ENGINE_BASE_URL, NQ, NQ_NAME, + BIDDER_CODE, CATEGORY, DATA_PARTNER_PIXEL_ID, ENGINE_BASE_URL, NQ, NQ_NAME, SUB_ID, spec } from '../../../modules/nanointeractiveBidAdapter'; @@ -23,6 +23,7 @@ describe('nanointeractive adapter tests', function () { [NQ]: SEARCH_QUERY, [NQ_NAME]: null, [CATEGORY]: null, + [SUB_ID]: null, } })(), placementCode: 'div-gpt-ad-1460505748561-0', @@ -37,6 +38,7 @@ describe('nanointeractive adapter tests', function () { const SINGLE_BID_REQUEST = { [DATA_PARTNER_PIXEL_ID]: 'pid1', [NQ]: [SEARCH_QUERY, null], + [SUB_ID]: null, sizes: [WIDTH + 'x' + HEIGHT], bidId: '24a1c9ec270973', cors: 'http://localhost' From 9bbd122b0cbe041ef04574d20d014df2acb874da Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 7 May 2018 16:00:50 -0400 Subject: [PATCH 0332/1594] add support to handle native js pixels for AN adapter (#2487) --- modules/appnexusBidAdapter.js | 1 + src/native.js | 6 +++++- src/utils.js | 34 +++++++++++++++++++++++++++++++++- test/spec/native_spec.js | 8 ++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 82743974994..3f0bf3a4826 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -236,6 +236,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { clickUrl: nativeAd.link.url, clickTrackers: nativeAd.link.click_trackers, impressionTrackers: nativeAd.impression_trackers, + javascriptTrackers: nativeAd.javascript_trackers, }; if (nativeAd.main_img) { bid['native'].image = { diff --git a/src/native.js b/src/native.js index 6c8ac266471..3d2ec2fe688 100644 --- a/src/native.js +++ b/src/native.js @@ -1,4 +1,4 @@ -import { deepAccess, getBidRequest, logError, triggerPixel } from './utils'; +import { deepAccess, getBidRequest, logError, triggerPixel, insertHtmlIntoIframe } from './utils'; import includes from 'core-js/library/fn/array/includes'; export const nativeAdapters = []; @@ -145,6 +145,10 @@ export function fireNativeTrackers(message, adObject) { trackers = adObject['native'] && adObject['native'].clickTrackers; } else { trackers = adObject['native'] && adObject['native'].impressionTrackers; + + if (adObject['native'] && adObject['native'].javascriptTrackers) { + insertHtmlIntoIframe(adObject['native'].javascriptTrackers); + } } (trackers || []).forEach(triggerPixel); diff --git a/src/utils.js b/src/utils.js index 169c578a356..cf977124dd1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -519,6 +519,38 @@ exports.callBurl = function({ source, burl }) { } }; +/** + * Inserts an empty iframe with the specified `html`, primarily used for tracking purposes + * (though could be for other purposes) + * @param {string} htmlCode snippet of HTML code used for tracking purposes + */ +exports.insertHtmlIntoIframe = function(htmlCode) { + if (!htmlCode) { + return; + } + + let iframe = document.createElement('iframe'); + iframe.id = exports.getUniqueIdentifierStr(); + iframe.width = 0; + iframe.height = 0; + iframe.hspace = '0'; + iframe.vspace = '0'; + iframe.marginWidth = '0'; + iframe.marginHeight = '0'; + iframe.style.display = 'none'; + iframe.style.height = '0px'; + iframe.style.width = '0px'; + iframe.scrolling = 'no'; + iframe.frameBorder = '0'; + iframe.allowtransparency = 'true'; + + exports.insertElement(iframe, document, 'body'); + + iframe.contentWindow.document.open(); + iframe.contentWindow.document.write(htmlCode); + iframe.contentWindow.document.close(); +} + /** * Inserts empty iframe with the specified `url` for cookie sync * @param {string} url URL to be requested @@ -571,7 +603,7 @@ exports.createTrackPixelIframeHtml = function (url, encodeUri = true, sandbox = allowtransparency="true" marginheight="0" marginwidth="0" width="0" hspace="0" vspace="0" height="0" - style="height:0p;width:0p;display:none;" + style="height:0px;width:0px;display:none;" scrolling="no" src="${url}"> `; diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index fa57ceed5f5..653f858576f 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -11,18 +11,22 @@ const bid = { clickUrl: 'https://www.link.example', clickTrackers: ['https://tracker.example'], impressionTrackers: ['https://impression.example'], + javascriptTrackers: '' } }; describe('native.js', () => { let triggerPixelStub; + let insertHtmlIntoIframeStub; beforeEach(() => { triggerPixelStub = sinon.stub(utils, 'triggerPixel'); + insertHtmlIntoIframeStub = sinon.stub(utils, 'insertHtmlIntoIframe'); }); afterEach(() => { utils.triggerPixel.restore(); + utils.insertHtmlIntoIframe.restore(); }); it('gets native targeting keys', () => { @@ -36,6 +40,7 @@ describe('native.js', () => { fireNativeTrackers({}, bid); sinon.assert.calledOnce(triggerPixelStub); sinon.assert.calledWith(triggerPixelStub, bid.native.impressionTrackers[0]); + sinon.assert.calledWith(insertHtmlIntoIframeStub, bid.native.javascriptTrackers); }); it('fires click trackers', () => { @@ -91,6 +96,7 @@ describe('validate native', () => { }, clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html', impressionTrackers: ['http://my.imp.tracker/url'], + javascriptTrackers: '', title: 'This is an example Prebid Native creative' } }; @@ -114,6 +120,7 @@ describe('validate native', () => { }, clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html', impressionTrackers: ['http://my.imp.tracker/url'], + javascriptTrackers: '', title: 'This is an example Prebid Native creative' } }; @@ -137,6 +144,7 @@ describe('validate native', () => { }, clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html', impressionTrackers: ['http://my.imp.tracker/url'], + javascriptTrackers: '', title: 'This is an example Prebid Native creative' } }; From 2dd6e1a1d052fc419e771a73e870686de764ef8d Mon Sep 17 00:00:00 2001 From: Adilet Date: Tue, 8 May 2018 22:28:55 +0600 Subject: [PATCH 0333/1594] A4G Adapter GDPR support (#2501) * A4G Adapter GDPR support * Resolve formatting errors --- modules/a4gBidAdapter.js | 25 +++++++++++++++++-------- test/spec/modules/a4gBidAdapter_spec.js | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/modules/a4gBidAdapter.js b/modules/a4gBidAdapter.js index f961db718c7..d6c0fa0b303 100644 --- a/modules/a4gBidAdapter.js +++ b/modules/a4gBidAdapter.js @@ -22,7 +22,7 @@ export const spec = { return bid.params && !!bid.params.zoneId; }, - buildRequests: function(validBidRequests) { + buildRequests: function(validBidRequests, bidderRequest) { let deliveryUrl = ''; const idParams = []; const sizeParams = []; @@ -41,16 +41,25 @@ export const spec = { deliveryUrl = A4G_DEFAULT_BID_URL; } + let data = { + [IFRAME_PARAM_NAME]: 0, + [LOCATION_PARAM_NAME]: utils.getTopWindowUrl(), + [SIZE_PARAM_NAME]: sizeParams.join(ARRAY_PARAM_SEPARATOR), + [ID_PARAM_NAME]: idParams.join(ARRAY_PARAM_SEPARATOR), + [ZONE_ID_PARAM_NAME]: zoneIds.join(ARRAY_PARAM_SEPARATOR) + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + data.gdpr = { + applies: bidderRequest.gdprConsent.gdprApplies, + consent: bidderRequest.gdprConsent.consentString + }; + } + return { method: 'GET', url: deliveryUrl, - data: { - [IFRAME_PARAM_NAME]: 0, - [LOCATION_PARAM_NAME]: utils.getTopWindowUrl(), - [SIZE_PARAM_NAME]: sizeParams.join(ARRAY_PARAM_SEPARATOR), - [ID_PARAM_NAME]: idParams.join(ARRAY_PARAM_SEPARATOR), - [ZONE_ID_PARAM_NAME]: zoneIds.join(ARRAY_PARAM_SEPARATOR) - } + data: data }; }, diff --git a/test/spec/modules/a4gBidAdapter_spec.js b/test/spec/modules/a4gBidAdapter_spec.js index 30fcb2f8497..84346a1149f 100644 --- a/test/spec/modules/a4gBidAdapter_spec.js +++ b/test/spec/modules/a4gBidAdapter_spec.js @@ -77,6 +77,26 @@ describe('a4gAdapterTests', () => { const request = spec.buildRequests(bidRequests); expect(request.data.zoneId).to.equal('59304;59354'); }); + + it('bidRequest gdpr consent', () => { + const consentString = 'consentString'; + const bidderRequest = { + bidderCode: 'a4g', + auctionId: '18fd8b8b0bd757', + bidderRequestId: '418b37f85e772c', + timeout: 3000, + gdprConsent: { + consentString: consentString, + gdprApplies: true + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.gdpr).to.exist; + expect(request.data.gdpr.applies).to.exist.and.to.be.true; + expect(request.data.gdpr.consent).to.exist.and.to.equal(consentString); + }); }); describe('interpretResponse', () => { From b1b969f1f72338a30ea5e86bbadd7a8931064e42 Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Tue, 8 May 2018 19:34:56 +0300 Subject: [PATCH 0334/1594] support extra params (#2502) --- modules/vidazooBidAdapter.js | 8 ++++++-- modules/vidazooBidAdapter.md | 6 +++++- test/spec/modules/vidazooBidAdapter_spec.js | 14 +++++++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/modules/vidazooBidAdapter.js b/modules/vidazooBidAdapter.js index 411c18f5414..c0d25af9d65 100644 --- a/modules/vidazooBidAdapter.js +++ b/modules/vidazooBidAdapter.js @@ -21,11 +21,11 @@ function isBidRequestValid(bid) { function buildRequest(bid, topWindowUrl, size) { const {params, bidId} = bid; - const {bidFloor, cId, pId} = params; + const {bidFloor, cId, pId, ext} = params; // Prebid's util function returns AppNexus style sizes (i.e. 300x250) const [width, height] = size.split('x'); - return { + const dto = { method: 'GET', url: `${URL}/prebid/${cId}`, data: { @@ -38,6 +38,10 @@ function buildRequest(bid, topWindowUrl, size) { height } } + + Object.entries(ext).forEach(entry => dto.data['ext.' + entry[0]] = entry[1]); + + return dto; } function buildRequests(validBidRequests) { diff --git a/modules/vidazooBidAdapter.md b/modules/vidazooBidAdapter.md index 972a99a1445..1e9dc47dd51 100644 --- a/modules/vidazooBidAdapter.md +++ b/modules/vidazooBidAdapter.md @@ -22,7 +22,11 @@ var adUnits = [ params: { cId: '5a1c419d95fce900044c334e', pId: '59ac17c192832d0011283fe3', - bidFloor: 0.0001 + bidFloor: 0.0001, + ext: { + param1: 'loremipsum', + param2: 'dolorsitamet' + } } } ] diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index 1f154f0a379..d88e5a718ed 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -6,7 +6,11 @@ const BID = { 'params': { 'cId': '59db6b3b4ffaa70004f45cdc', 'pId': '59ac17c192832d0011283fe3', - 'bidFloor': 0.1 + 'bidFloor': 0.1, + 'ext': { + 'param1': 'loremipsum', + 'param2': 'dolorsitamet' + } }, 'placementCode': 'div-gpt-ad-1460505748561-0', 'transactionId': 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf', @@ -117,7 +121,9 @@ describe('VidazooBidAdapter', () => { cb: 1000, bidFloor: 0.1, bidId: '2d52001cabd527', - publisherId: '59ac17c192832d0011283fe3' + publisherId: '59ac17c192832d0011283fe3', + 'ext.param1': 'loremipsum', + 'ext.param2': 'dolorsitamet', } }); expect(requests[1]).to.deep.equal({ @@ -130,7 +136,9 @@ describe('VidazooBidAdapter', () => { cb: 1000, bidFloor: 0.1, bidId: '2d52001cabd527', - publisherId: '59ac17c192832d0011283fe3' + publisherId: '59ac17c192832d0011283fe3', + 'ext.param1': 'loremipsum', + 'ext.param2': 'dolorsitamet', } }); }); From e638efc6e6d4945a1150c86201e670158c7c1fdb Mon Sep 17 00:00:00 2001 From: ix-prebid-support <38486470+ix-prebid-support@users.noreply.github.com> Date: Tue, 8 May 2018 12:41:03 -0400 Subject: [PATCH 0335/1594] IndexExchange Display Bid Adapter + GDPR Support (#2496) --- modules/ixBidAdapter.js | 300 ++++++++++++++++++ modules/ixBidAdapter.md | 277 +++++++++++++++++ test/spec/modules/ixBidAdapter_spec.js | 412 +++++++++++++++++++++++++ 3 files changed, 989 insertions(+) create mode 100644 modules/ixBidAdapter.js create mode 100644 modules/ixBidAdapter.md create mode 100644 test/spec/modules/ixBidAdapter_spec.js diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js new file mode 100644 index 00000000000..3384bb8f41b --- /dev/null +++ b/modules/ixBidAdapter.js @@ -0,0 +1,300 @@ +import * as utils from 'src/utils'; +import { BANNER } from 'src/mediaTypes'; +import { config } from 'src/config'; +import isArray from 'core-js/library/fn/array/is-array'; +import isInteger from 'core-js/library/fn/number/is-integer'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'ix'; +const BANNER_SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; +const BANNER_INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; +const SUPPORTED_AD_TYPES = [BANNER]; +const ENDPOINT_VERSION = 7.2; +const CENT_TO_DOLLAR_FACTOR = 100; +const TIME_TO_LIVE = 60; +const NET_REVENUE = true; + +// Always start by assuming the protocol is HTTPS. This way, it will work +// whether the page protocol is HTTP or HTTPS. Then check if the page is +// actually HTTP.If we can guarantee it is, then, and only then, set protocol to +// HTTP. +let isSecureWeb = true; +if (utils.getTopWindowLocation().protocol.indexOf('https') !== 0) { + isSecureWeb = false; +} +const baseUrl = isSecureWeb ? BANNER_SECURE_BID_URL : BANNER_INSECURE_BID_URL; + +const PRICE_TO_DOLLAR_FACTOR = { + JPY: 1 +}; + +/** + * Transform valid bid request config object to impression object that will be sent to ad server. + * + * @param {object} bid A valid bid request config object. + * @return {object} A impression object that will be sent to ad server. + */ +function bidToBannerImp(bid) { + const imp = {}; + + imp.id = bid.bidId; + + imp.banner = {}; + imp.banner.w = bid.params.size[0]; + imp.banner.h = bid.params.size[1]; + imp.banner.topframe = utils.inIframe() ? 0 : 1; + + imp.ext = {}; + imp.ext.sid = `${bid.params.size[0]}x${bid.params.size[1]}`; + imp.ext.siteID = bid.params.siteId; + + if (bid.params.hasOwnProperty('bidFloor') && bid.params.hasOwnProperty('bidFloorCur')) { + imp.bidfloor = bid.params.bidFloor; + imp.bidfloorcur = bid.params.bidFloorCur; + } + + return imp; +} + +/** + * Parses a raw bid for the relevant information. + * + * @param {object} rawBid The bid to be parsed. + * @param {string} currency Global currency in bid response. + * @return {object} bid The parsed bid. + */ +function parseBid(rawBid, currency) { + const bid = {}; + + if (PRICE_TO_DOLLAR_FACTOR.hasOwnProperty(currency)) { + bid.cpm = rawBid.price / PRICE_TO_DOLLAR_FACTOR[currency]; + } else { + bid.cpm = rawBid.price / CENT_TO_DOLLAR_FACTOR; + } + + bid.requestId = rawBid.impid; + bid.width = rawBid.w; + bid.height = rawBid.h; + bid.ad = rawBid.adm; + bid.dealId = utils.deepAccess(rawBid, 'ext.dealid'); + bid.ttl = TIME_TO_LIVE; + bid.netRevenue = NET_REVENUE; + bid.currency = currency; + bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-'; + + return bid; +} + +/** + * Determines whether or not the given object is valid size format. + * + * @param {*} size The object to be validated. + * @return {boolean} True if this is a valid size format, and false otherwise. + */ +function isValidSize(size) { + return isArray(size) && size.length === 2 && isInteger(size[0]) && isInteger(size[1]); +} + +/** + * Determines whether or not the given size object is an element of the size + * array. + * + * @param {array} sizeArray The size array. + * @param {object} size The size object. + * @return {boolean} True if the size object is an element of the size array, and false + * otherwise. + */ +function includesSize(sizeArray, size) { + if (isValidSize(sizeArray)) { + return sizeArray[0] === size[0] && sizeArray[1] === size[1]; + } + + for (let i = 0; i < sizeArray.length; i++) { + if (sizeArray[i][0] === size[0] && sizeArray[i][1] === size[1]) { + return true; + } + } + + return false; +} + +/** + * Determines whether or not the given bidFloor parameters are valid. + * + * @param {*} bidFloor The bidFloor parameter inside bid request config. + * @param {*} bidFloorCur The bidFloorCur parameter inside bid request config. + * @return {boolean} True if this is a valid biFfloor parameters format, and false + * otherwise. + */ +function isValidBidFloorParams(bidFloor, bidFloorCur) { + const curRegex = /^[A-Z]{3}$/; + + return Boolean(typeof bidFloor === 'number' && typeof bidFloorCur === 'string' && + bidFloorCur.match(curRegex)); +} + +export const spec = { + + code: BIDDER_CODE, + supportedMediaTypes: SUPPORTED_AD_TYPES, + + /** + * 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 (!isValidSize(bid.params.size)) { + return false; + } + + if (!includesSize(bid.sizes, bid.params.size)) { + return false; + } + + if (typeof bid.params.siteId !== 'string') { + return false; + } + + const hasBidFloor = bid.params.hasOwnProperty('bidFloor'); + const hasBidFloorCur = bid.params.hasOwnProperty('bidFloorCur'); + + if (hasBidFloor || hasBidFloorCur) { + return hasBidFloor && hasBidFloorCur && + isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur); + } + + return true; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {array} validBidRequests A list of valid bid request config objects. + * @param {object} options A object contains bids and other info like gdprConsent. + * @return {object} Info describing the request to the server. + */ + buildRequests: function (validBidRequests, options) { + const bannerImps = []; + let validBidRequest = null; + let bannerImp = null; + + for (let i = 0; i < validBidRequests.length; i++) { + validBidRequest = validBidRequests[i]; + + // If the bid request is for banner, then transform the bid request based on banner format. + if (utils.deepAccess(validBidRequest, 'mediaTypes.banner') || + validBidRequest.mediaType === 'banner') { + bannerImp = bidToBannerImp(validBidRequest); + bannerImps.push(bannerImp); + } + } + + const r = {}; + + // Since bidderRequestId are the same for different bid request, just use the first one. + r.id = validBidRequests[0].bidderRequestId; + + r.imp = bannerImps; + r.site = {}; + r.site.page = utils.getTopWindowUrl(); + r.site.ref = utils.getTopWindowReferrer(); + r.ext = {}; + r.ext.source = 'prebid'; + + // Apply GDPR information to the request if GDPR is enabled. + if (options && options.gdprConsent) { + const gdprConsent = options.gdprConsent; + + if (gdprConsent.hasOwnProperty('gdprApplies')) { + r.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + }; + } + + if (gdprConsent.hasOwnProperty('consentString')) { + r.user = { + ext: { + consent: gdprConsent.consentString || '' + } + }; + } + } + + const payload = {}; + + // Parse additional runtime configs. + const otherIxConfig = config.getConfig('ix'); + if (otherIxConfig) { + // Append firstPartyData to r.site.page if firstPartyData exists. + if (typeof otherIxConfig.firstPartyData === 'object') { + const firstPartyData = otherIxConfig.firstPartyData; + let firstPartyString = '?'; + for (const key in firstPartyData) { + if (firstPartyData.hasOwnProperty(key)) { + firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; + } + } + firstPartyString = firstPartyString.slice(0, -1); + + r.site.page += firstPartyString; + } + + // Create t in payload if timeout is configured. + if (typeof otherIxConfig.timeout === 'number') { + payload.t = otherIxConfig.timeout; + } + } + + // Use the siteId in the first bid request as the main siteId. + payload.s = validBidRequests[0].params.siteId; + + payload.v = ENDPOINT_VERSION; + payload.r = JSON.stringify(r); + payload.ac = 'j'; + payload.sd = 1; + + return { + method: 'GET', + url: baseUrl, + data: payload + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {object} serverResponse A successful response from the server. + * @return {array} An array of bids which were nested inside the server. + */ + interpretResponse: function (serverResponse) { + const bids = []; + let bid = null; + + if (!serverResponse.hasOwnProperty('body') || !serverResponse.body.hasOwnProperty('seatbid')) { + return bids; + } + + const responseBody = serverResponse.body; + const seatbid = responseBody.seatbid; + for (let i = 0; i < seatbid.length; i++) { + if (!seatbid[i].hasOwnProperty('bid')) { + continue; + } + + // Transform rawBid in bid response to the format that will be accepted by prebid. + const innerBids = seatbid[i].bid; + for (let j = 0; j < innerBids.length; j++) { + bid = parseBid(innerBids[j], responseBody.cur); + bids.push(bid); + } + } + + return bids; + } +}; + +registerBidder(spec); diff --git a/modules/ixBidAdapter.md b/modules/ixBidAdapter.md new file mode 100644 index 00000000000..75950432d54 --- /dev/null +++ b/modules/ixBidAdapter.md @@ -0,0 +1,277 @@ +Overview +======== + +``` +Module Name: Index Exchange Adapter +Module Type: Bidder Adapter +Maintainer: prebid.support@indexexchange.com +``` + +Description +=========== + +This module connects publishers to Index Exchange's (IX) network of demand +sources through Prebid.js. This module is GDPR compliant. + +It is compatible with both the older ad unit format where the `sizes` and +`mediaType` properties are placed at the top-level of the ad unit, and the newer +format where this information is encapsulated within the `mediaTypes` object. We +recommend that you use the newer format when possible as it will be better able +to accommodate new feature additions. + +If a mix of properties from both formats are present within an ad unit, the +newer format's properties will take precedence. + +Here are examples of both formats. + +##### Older Format +```javascript +var adUnits = [{ + // ... + + mediaType: 'banner', + + sizes: [ + [300, 250], + [300, 600] + ] + + // ... +}]; +``` + +##### Newer Format +```javascript +var adUnits = [{ + // ... + + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + } + + // ... +}]; +``` + +### Supported Media Types + +| Type | Support +| --- | --- +| Banner | Fully supported for all IX approved sizes. +| Video | Only in-stream supported. +| Native | Not supported. + +# Bid Parameters + +Each of the IX-specific parameters provided under the `adUnits[].bids[].params` +object are detailed here. + +### Banner + +| Key | Scope | Type | Description +| --- | --- | --- | --- +| siteId | Required | String |

An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have.

Examples:

  • `'3723'`
  • `'6482'`
  • `'3639'`

+| size | Required | Number[] |

The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.banner.sizes`.

Examples:

  • `[300, 250]`
  • `[300, 600]`
  • `[728, 90]`

+| bidFloor | Optional1 | Number |

The minimum bid required to participate in an auction for this ad unit. Assuming the bid floor currency that is set has a main unit (e.g. dollars, pounds) and a sub-unit (e.g. cents, pence), the bid floor should be in decimal-point format. If the currency only has main a unit (e.g. JPY), then the bid floor should be a whole number.

Examples:

  • 10.26 USD => `bidFloor: 10.26`
  • 13.41 GBP => `bidFloor: 13.41`
  • 600 JPY => `bidFloor: 600`

| N/A +| bidFloorCur | Optional1 | String |

The currency of the bid floor.

Examples:

  • `'USD'`
  • `'GBP'`
  • `'JPY'`

+ +

+ 1 bidFloor and bidFloorCur must + both be set when a bid floor is being configured. +

+ +Setup Guide +=========== + +Follow these steps to configure and add the IX module to your Prebid.js +integration. + +The examples in this guide assume the following starting configuration: + +```javascript +var adUnits = [{ + code: 'banner-div-a', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [] +}]; +``` + +##### 1. Add IX to the appropriate ad units + +For each size in an ad unit that IX will be bidding on, add one of the following +bid objects under `adUnits[].bids`: + +```javascript +{ + bidder: 'ix', + params: { + siteId: '', + size: [] + } +} +``` + +Set `params.siteId` and `params.size` in each bid object to the values provided +by your IX representative. + +**Example** +```javascript +var adUnits = [{ + code: 'banner-div-a', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '4622', + size: [300, 250] + } + }, { + bidder: 'ix', + params: { + siteId: '6242', + size: [300, 600] + } + }] +}]; +``` + +##### 2. Include `ixBidAdapter` in your build process + +When running the build command, include `ixBidAdapter` as a module. + +``` +gulp build --modules=ixBidAdapter,fooBidAdapter,bazBidAdapter +``` + +If a JSON file is being used to specify the bidder modules, add `"ixBidAdapter"` +to the top-level array in that file. + +```json +[ + "ixBidAdapter", + "fooBidAdapter", + "bazBidAdapter" +] +``` + +And then build. + +``` +gulp build --modules=bidderModules.json +``` + +Setting First Party Data (FPD) +============================== + +FPD allows you to specify key-value pairs which will be passed as part of the +query string to IX for use in Private Marketplace Deals which rely on query +string targeting for activation. For example, if a user is viewing a +news-related page, you can pass on that information by sending `category=news`. +Then in the IX Private Marketplace setup screens you can create Deals which +activate only on pages which contain `category=news`. Please reach out to your +IX representative if you have any questions or need help setting this up. + +To include FPD in a bid request, it must be set before `pbjs.requestBids` is +called. To set it, call `pbjs.setConfig` and provide it with a map of FPD keys +to values as such: + +```javascript +pbjs.setConfig({ + ix: { + firstPartyData: { + '': '', + '': '', + // ... + } + } +}); +``` + +The values can be updated at any time by calling `pbjs.setConfig` again. The +changes will be reflected in any proceeding bid requests. + +Setting a Server Side Timeout +============================= + +Setting a server-side timeout allows you to control the max length of time the +servers will wait on DSPs to respond before generating the final bid response +and returning it to this module. + +This is distinctly different from the global bidder timeout that can be set in +Prebid.js in the browser. + +To add a server-side timeout, it must be set before `pbjs.requestBids` is +called. To set it, call `pbjs.setConfig` and provide it with a timeout value as +such: + +```javascript +pbjs.setConfig({ + ix: { + timeout: 500 + } +}); +``` + +The timeout value must be a positive whole number in milliseconds. + +Additional Information +====================== + +### Bid Request Limit + +If a single bid request to IX contains more than 20 impression requests (i.e. +more than 20 objects in `bidRequest.imp`), only the first 20 will be accepted, +the rest will be ignored. + +To avoid this situation, ensure that when `pbjs.requestBid` is invoked, that the +number of bid objects (i.e. `adUnits[].bids`) with `adUnits[].bids[].bidder` set +to `'ix'` across all ad units that bids are being requested for does not exceed +20. + +### Time-To-Live (TTL) + +All bids received from IX have a TTL of 60 seconds, after which time they become +invalid. + +If an invalid bid wins, and its associated ad is rendered, it will not count +towards total impressions on IX's side. + +FAQs +==== + +### Why do I have to input size in `adUnits[].bids[].params` for IX when the size is already in the ad unit? + +There are two important reasons why we require it: + +1. An IX site ID maps to a single size, whereas an ad unit can have multiple +sizes. To ensure that the right site ID is mapped to the correct size in the ad +unit we require the size to be explicitly stated. + +2. An ad unit may have sizes that IX does not support. By explicitly stating the +size, you can choose not to have IX bid on certain sizes that are invalid. + +### How do I view IX's bid request in the network? + +In your browser of choice, create a new tab and open the developer tools. In +developer tools, select the network tab. Then, navigate to a page where IX is +setup to bid. Now, in the network tab, search for requests to +`casalemedia.com/cygnus`. These are the bid requests. diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js new file mode 100644 index 00000000000..0e00a64aab4 --- /dev/null +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -0,0 +1,412 @@ +import * as utils from 'src/utils'; +import { config } from 'src/config'; +import { expect } from 'chai'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { spec } from 'modules/ixBidAdapter'; + +describe('IndexexchangeAdapter', () => { + const IX_ENDPOINT = 'http://as.casalemedia.com/cygnus'; + const BIDDER_VERSION = 7.2; + + const DEFAULT_BANNER_VALID_BID = [ + { + bidder: 'ix', + params: { + siteId: '123', + size: [300, 250] + }, + sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: '173f49a8-7549-4218-a23c-e7ba59b47229', + bidId: '1a2b3c4d', + bidderRequestId: '11a22b33c44d', + auctionId: '1aa2bb3cc4dd' + } + ]; + const DEFAULT_BANNER_BID_RESPONSE = { + cur: 'USD', + id: '11a22b33c44d', + seatbid: [ + { + bid: [ + { + crid: '12345', + adomain: ['www.abc.com'], + adid: '14851455', + impid: '1a2b3c4d', + cid: '3051266', + price: 100, + w: 300, + h: 250, + id: '1', + ext: { + dspid: 50, + pricelevel: '_100', + advbrandid: 303325, + advbrand: 'OECTA' + }, + adm: '' + } + ], + seat: '3970' + } + ] + }; + + describe('inherited functions', () => { + it('should exists and is a function', () => { + const adapter = newBidder(spec); + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when required params found for a banner ad', () => { + expect(spec.isBidRequestValid(DEFAULT_BANNER_VALID_BID[0])).to.equal(true); + }); + + it('should return true when optional params found for a banner ad', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.bidFloor = 50; + bid.params.bidFloorCur = 'USD'; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when siteID is number', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.siteId = 123; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when siteID is missing', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.siteId; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when size is missing', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.size; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when size array is wrong length', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.size = [ + 300, + 250, + 250 + ]; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when size array is array of strings', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.size = ['300', '250']; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when there is only bidFloor', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.bidFloor = 50; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when there is only bidFloorCur', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.bidFloorCur = 'USD'; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when bidFloor is string', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.bidFloor = '50'; + bid.params.bidFloorCur = 'USD'; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when bidFloorCur is number', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.bidFloor = 50; + bid.params.bidFloorCur = 70; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequestsBanner', () => { + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestUrl = request.url; + const requestMethod = request.method; + const query = request.data; + + it('request should be made to IX endpoint with GET method', () => { + expect(requestMethod).to.equal('GET'); + expect(requestUrl).to.equal(IX_ENDPOINT); + }); + + it('query object (version, siteID and request) should be correct', () => { + expect(query.v).to.equal(BIDDER_VERSION); + expect(query.s).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId); + expect(query.r).to.exist; + expect(query.ac).to.equal('j'); + expect(query.sd).to.equal(1); + }); + + it('payload should have correct format and value', () => { + const payload = JSON.parse(query.r); + + expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); + expect(payload.site).to.exist; + expect(payload.site.page).to.exist; + expect(payload.site.page).to.contain('http'); + expect(payload.site.ref).to.exist; + expect(payload.site.ref).to.be.a('string'); + expect(payload.ext).to.exist; + expect(payload.ext.source).to.equal('prebid'); + expect(payload.imp).to.exist; + expect(payload.imp).to.be.an('array'); + expect(payload.imp).to.have.lengthOf(1); + }); + + it('impression should have correct format and value', () => { + const impression = JSON.parse(query.r).imp[0]; + const sidValue = `${DEFAULT_BANNER_VALID_BID[0].params.size[0].toString()}x${DEFAULT_BANNER_VALID_BID[0].params.size[1].toString()}`; + + expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(impression.banner).to.exist; + expect(impression.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); + expect(impression.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); + expect(impression.banner.topframe).to.exist; + expect(impression.banner.topframe).to.be.oneOf([0, 1]); + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal(sidValue); + }); + + it('impression should have bidFloor and bidFloorCur if configured', () => { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.bidFloor = 50; + bid.params.bidFloorCur = 'USD'; + const requestBidFloor = spec.buildRequests([bid]); + const impression = JSON.parse(requestBidFloor.data.r).imp[0]; + + expect(impression.bidfloor).to.equal(bid.params.bidFloor); + expect(impression.bidfloorcur).to.equal(bid.params.bidFloorCur); + }); + + it('should add first party data to page url in bid request if it exists in config', () => { + config.setConfig({ + ix: { + firstPartyData: { + ab: 123, + cd: '123#ab', + 'e/f': 456, + 'h?g': '456#cd' + } + } + }); + + const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; + const expectedPageUrl = `${utils.getTopWindowUrl()}?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd`; + + expect(pageUrl).to.equal(expectedPageUrl); + }); + + it('should not set first party data if it is not an object', () => { + config.setConfig({ + ix: { + firstPartyData: 500 + } + }); + + const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const pageUrl = JSON.parse(requestFirstPartyDataNumber.data.r).site.page; + + expect(pageUrl).to.equal(utils.getTopWindowUrl()); + }); + + it('should not set first party or timeout if it is not present', () => { + config.setConfig({ + ix: {} + }); + + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; + + expect(pageUrl).to.equal(utils.getTopWindowUrl()); + expect(requestWithoutConfig.data.t).to.be.undefined; + }); + + it('should not set first party or timeout if it is setConfig is not called', () => { + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; + + expect(pageUrl).to.equal(utils.getTopWindowUrl()); + expect(requestWithoutConfig.data.t).to.be.undefined; + }); + + it('should set timeout if publisher set it through setConfig', () => { + config.setConfig({ + ix: { + timeout: 500 + } + }); + const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + + expect(requestWithTimeout.data.t).to.equal(500); + }); + + it('should set timeout if timeout is a string', () => { + config.setConfig({ + ix: { + timeout: '500' + } + }); + const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + + expect(requestStringTimeout.data.t).to.be.undefined; + }); + }); + + describe('interpretResponseBanner', () => { + it('should get correct bid response', () => { + const expectedParse = [ + { + requestId: '1a2b3c4d', + cpm: 1, + creativeId: '12345', + width: 300, + height: 250, + ad: '', + currency: 'USD', + ttl: 60, + netRevenue: true, + dealId: undefined + } + ]; + const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }); + expect(result[0]).to.deep.equal(expectedParse[0]); + }); + + it('should set creativeId to default value if not provided', () => { + const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); + delete bidResponse.seatbid[0].bid[0].crid; + const expectedParse = [ + { + requestId: '1a2b3c4d', + cpm: 1, + creativeId: '-', + width: 300, + height: 250, + ad: '', + currency: 'USD', + ttl: 60, + netRevenue: true, + dealId: undefined + } + ]; + const result = spec.interpretResponse({ body: bidResponse }); + expect(result[0]).to.deep.equal(expectedParse[0]); + }); + + it('should set Japanese price correctly', () => { + const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); + bidResponse.cur = 'JPY'; + const expectedParse = [ + { + requestId: '1a2b3c4d', + cpm: 100, + creativeId: '12345', + width: 300, + height: 250, + ad: '', + currency: 'JPY', + ttl: 60, + netRevenue: true, + dealId: undefined + } + ]; + const result = spec.interpretResponse({ body: bidResponse }); + expect(result[0]).to.deep.equal(expectedParse[0]); + }); + + it('should set dealId correctly', () => { + const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); + bidResponse.seatbid[0].bid[0].ext.dealid = 'deal'; + const expectedParse = [ + { + requestId: '1a2b3c4d', + cpm: 1, + creativeId: '12345', + width: 300, + height: 250, + ad: '', + currency: 'USD', + ttl: 60, + netRevenue: true, + dealId: 'deal' + } + ]; + const result = spec.interpretResponse({ body: bidResponse }); + expect(result[0]).to.deep.equal(expectedParse[0]); + }); + + it('bidrequest should have consent info if gdprApplies and consentString exist', () => { + const options = { + gdprConsent: { + gdprApplies: true, + consentString: '3huaa11=qu3198ae', + vendorData: {} + } + }; + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + + expect(requestWithConsent.regs.ext.gdpr).to.equal(1); + expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); + }); + + it('bidrequest should not have consent field if consentString is undefined', () => { + const options = { + gdprConsent: { + gdprApplies: true, + vendorData: {} + } + }; + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + + expect(requestWithConsent.regs.ext.gdpr).to.equal(1); + expect(requestWithConsent.user).to.be.undefined; + }); + + it('bidrequest should not have gdpr field if gdprApplies is undefined', () => { + const options = { + gdprConsent: { + consentString: '3huaa11=qu3198ae', + vendorData: {} + } + }; + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + + expect(requestWithConsent.regs).to.be.undefined; + expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); + }); + + it('bidrequest should not have consent info if options.gdprConsent is undefined', () => { + const options = {}; + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + + expect(requestWithConsent.regs).to.be.undefined; + expect(requestWithConsent.user).to.be.undefined; + }); + }); +}); From ea91035c1e4962357e739c3cfe47a6040f307e57 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 8 May 2018 10:33:15 -0700 Subject: [PATCH 0336/1594] Sharethrough: GDPR compliance + getUserSyncs (#2503) --- modules/sharethroughBidAdapter.js | 36 ++++++++++++---- .../modules/sharethroughBidAdapter_spec.js | 42 +++++++++++++++++++ 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index ce4c87be4d3..f8cb2c99400 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -7,23 +7,32 @@ const STR_ENDPOINT = document.location.protocol + '//btlr.sharethrough.com/heade export const sharethroughAdapterSpec = { code: BIDDER_CODE, isBidRequestValid: bid => !!bid.params.pkey && bid.bidder === BIDDER_CODE, - buildRequests: (bidRequests) => { + buildRequests: (bidRequests, bidderRequest) => { return bidRequests.map(bid => { + let query = { + bidId: bid.bidId, + placement_key: bid.params.pkey, + hbVersion: '$prebid.version$', + strVersion: VERSION, + hbSource: 'prebid' + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + query.consent_string = bidderRequest.gdprConsent.consentString; + query.consent_required = bidderRequest.gdprConsent.gdprApplies; + } + return { method: 'GET', url: STR_ENDPOINT, - data: { - bidId: bid.bidId, - placement_key: bid.params.pkey, - hbVersion: '$prebid.version$', - strVersion: VERSION, - hbSource: 'prebid' - } + data: query }; }) }, interpretResponse: ({ body }, req) => { - if (!Object.keys(body).length) return []; + if (!body || !Object.keys(body).length || !body.creatives.length) { + return []; + } const creative = body.creatives[0]; @@ -39,6 +48,15 @@ export const sharethroughAdapterSpec = { ttl: 360, ad: generateAd(body, req) }]; + }, + getUserSyncs: (syncOptions, serverResponses) => { + const syncs = []; + if (syncOptions.pixelEnabled && serverResponses.length > 0) { + serverResponses[0].body.cookieSyncUrls.forEach(url => { + syncs.push({ type: 'image', url: url }); + }); + } + return syncs; } } diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index d7fa3f728ac..aa9477d2557 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -100,6 +100,14 @@ describe('sharethrough adapter spec', () => { 'http://btlr.sharethrough.com/header-bid/v1') expect(bidRequests[0].method).to.eq('GET'); }); + + it('should add consent parameters if gdprConsent is present', () => { + const gdprConsent = { consentString: 'consent_string123', gdprApplies: true }; + const fakeBidRequest = { gdprConsent: gdprConsent }; + const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; + expect(bidRequest.data.consent_string).to.eq('consent_string123'); + expect(bidRequest.data.consent_required).to.eq(true); + }); }); describe('.interpretResponse', () => { @@ -117,6 +125,21 @@ describe('sharethrough adapter spec', () => { }); }); + it('returns a blank array if there are no creatives', () => { + const bidResponse = { body: { creatives: [] } }; + expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + }); + + it('returns a blank array if body object is empty', () => { + const bidResponse = { body: {} }; + expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + }); + + it('returns a blank array if body is null', () => { + const bidResponse = { body: null }; + expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + }); + it('correctly sends back a sfp script tag', () => { const adMarkup = spec.interpretResponse(bidderResponse, prebidRequest[0])[0].ad; let resp = null; @@ -134,4 +157,23 @@ describe('sharethrough adapter spec', () => { /window.top.document.getElementsByTagName\('body'\)\[0\].appendChild\(sfp_js\);/) }); }); + + describe('.getUserSyncs', () => { + const cookieSyncs = ['cookieUrl1', 'cookieUrl2', 'cookieUrl3']; + const serverResponses = [{ body: { cookieSyncUrls: cookieSyncs } }]; + + it('returns an array of correctly formatted user syncs', () => { + const syncArray = spec.getUserSyncs({ pixelEnabled: true }, serverResponses); + expect(syncArray).to.deep.equal([ + { type: 'image', url: 'cookieUrl1' }, + { type: 'image', url: 'cookieUrl2' }, + { type: 'image', url: 'cookieUrl3' }] + ); + }); + + it('returns an empty array if pixels are not enabled', () => { + const syncArray = spec.getUserSyncs({ pixelEnabled: false }, serverResponses); + expect(syncArray).to.be.an('array').that.is.empty; + }); + }); }); From a81ef7206782a14a0f6b3da474ff465cd2bbdf15 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 8 May 2018 17:13:52 -0400 Subject: [PATCH 0337/1594] bugfix (#2510) --- modules/vidazooBidAdapter.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/vidazooBidAdapter.js b/modules/vidazooBidAdapter.js index c0d25af9d65..bcf8856e049 100644 --- a/modules/vidazooBidAdapter.js +++ b/modules/vidazooBidAdapter.js @@ -39,7 +39,9 @@ function buildRequest(bid, topWindowUrl, size) { } } - Object.entries(ext).forEach(entry => dto.data['ext.' + entry[0]] = entry[1]); + utils._each(ext, (value, key) => { + dto.data['ext.' + key] = value; + }); return dto; } From 208960c29daa3c84cafeb0eb495c8bc284919ce5 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 8 May 2018 17:17:39 -0400 Subject: [PATCH 0338/1594] Prebid 1.10.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 36374cd5f22..fc249d17a84 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.10.0-pre", + "version": "1.10.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From eadfd86e5e9f5b77b2992d39acf5e278aaa748fb Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 8 May 2018 17:26:00 -0400 Subject: [PATCH 0339/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fc249d17a84..28cb310599e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.10.0", + "version": "1.11.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3d96d9ebbb5ba9a23feb7f14a87bbe0c6a10adc5 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Thu, 10 May 2018 12:01:39 -0400 Subject: [PATCH 0340/1594] Sonobi Adapter - Added referrer param. Fixed timeout error in userSync (#2497) --- modules/sonobiBidAdapter.js | 27 ++++++++++++++-------- test/spec/modules/sonobiBidAdapter_spec.js | 6 +++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 438ab7f3a74..a8b5bd13e05 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -28,7 +28,7 @@ export const spec = { const bids = validBidRequests.map(bid => { let slotIdentifier = _validateSlot(bid); if (/^[\/]?[\d]+[[\/].+[\/]?]?$/.test(slotIdentifier)) { - slotIdentifier = slotIdentifier.charAt(0) === '/' ? slotIdentifier : '/' + slotIdentifier + slotIdentifier = slotIdentifier.charAt(0) === '/' ? slotIdentifier : '/' + slotIdentifier; return { [`${slotIdentifier}|${bid.bidId}`]: `${_validateSize(bid)}${_validateFloor(bid)}` } @@ -41,7 +41,7 @@ export const spec = { } }); - let data = {} + let data = {}; bids.forEach((bid) => { Object.assign(data, bid); }); const payload = { @@ -57,6 +57,9 @@ export const spec = { if (validBidRequests[0].params.hfa) { payload.hfa = validBidRequests[0].params.hfa; } + if (validBidRequests[0].params.referrer) { + payload.ref = validBidRequests[0].params.referrer; + } // If there is no key_maker data, then dont make the request. if (isEmpty(data)) { @@ -132,17 +135,21 @@ export const spec = { */ getUserSyncs: (syncOptions, serverResponses) => { const syncs = []; - if (syncOptions.pixelEnabled && serverResponses[0].body.sbi_px) { - serverResponses[0].body.sbi_px.forEach(pixel => { - syncs.push({ - type: pixel.type, - url: pixel.url + try { + if (syncOptions.pixelEnabled) { + serverResponses[0].body.sbi_px.forEach(pixel => { + syncs.push({ + type: pixel.type, + url: pixel.url + }); }); - }); + } + } catch (e) { + logError(e) } return syncs; } -} +}; function _validateSize (bid) { if (bid.params.sizes) { @@ -171,7 +178,7 @@ const _creative = (mediaType) => (sbi_dc, sbi_aid) => { } const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null' + '&ref=' + getTopWindowLocation().host; return ''; -} +}; function _videoCreative(sbi_dc, sbi_aid) { return `https://${sbi_dc}apex.go.sonobi.com/vast.xml?vid=${sbi_aid}&ref=${getTopWindowLocation().host}` diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 791d07ba91a..431bf134349 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -107,6 +107,7 @@ describe('SonobiBidAdapter', () => { 'placement_id': '1a2b3c4d5e6f1a2b3c4d', 'sizes': [[300, 250], [300, 600]], 'floor': '1.25', + 'referrer': 'overrides_top_window_location' }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -117,6 +118,7 @@ describe('SonobiBidAdapter', () => { 'params': { 'ad_unit': '/7780971/sparks_prebid_LB', 'sizes': [[300, 250], [300, 600]], + 'referrer': 'overrides_top_window_location' }, 'adUnitCode': 'adunit-code-2', 'sizes': [[120, 600], [300, 600], [160, 600]], @@ -139,6 +141,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.pv).to.equal(bidRequestsPageViewID.data.pv) expect(bidRequests.data.hfa).to.not.exist expect(bidRequests.bidderRequests).to.eql(bidRequest); + expect(bidRequests.data.ref).to.equal('overrides_top_window_location'); expect(['mobile', 'tablet', 'desktop']).to.contain(bidRequests.data.vp); }) @@ -281,6 +284,9 @@ describe('SonobiBidAdapter', () => { url: 'https://pixel-test' }]); }) + it('should return an empty array when sync is enabled but there are no bidResponses', () => { + expect(spec.getUserSyncs({ pixelEnabled: true }, [])).to.have.length(0); + }) it('should return an empty array when sync is enabled but no sync pixel returned', () => { const pixel = Object.assign({}, bidResponse); From 877a58c70fdf33077bad4b821364a4c413cfc733 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 11 May 2018 10:08:26 -0600 Subject: [PATCH 0341/1594] add support for latLong in rubicon adapter (#2508) --- modules/rubiconBidAdapter.js | 16 ++++++++++++---- test/spec/modules/rubiconBidAdapter_spec.js | 7 +++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index bf2930e5684..d6a69fda625 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -206,7 +206,8 @@ export const spec = { keywords, visitor, inventory, - userId + userId, + latLong: [latitude, longitude] = [], } = bidRequest.params; // defaults @@ -230,7 +231,9 @@ export const spec = { 'x_source.tid', bidRequest.transactionId, 'p_screen_res', _getScreenResolution(), 'kw', keywords, - 'tk_user_key', userId + 'tk_user_key', userId, + 'p_geo.latitude', parseFloat(latitude).toFixed(4), + 'p_geo.longitude', parseFloat(longitude).toFixed(4) ]; if (gdprConsent) { @@ -258,7 +261,7 @@ export const spec = { data = data.reduce( (memo, curr, index) => - index % 2 === 0 && data[index + 1] !== undefined + index % 2 === 0 && data[index + 1] !== undefined && !isNaN(data[index + 1]) ? memo + curr + '=' + encodeURIComponent(data[index + 1]) + '&' : memo, '' ).slice(0, -1); // remove trailing & @@ -287,7 +290,7 @@ export const spec = { * @return {Bid[]} An array of bids which */ interpretResponse: function (responseObj, {bidRequest}) { - responseObj = responseObj.body + responseObj = responseObj.body; let ads = responseObj.ads; // check overall response @@ -472,4 +475,9 @@ export function resetUserSync() { hasSynced = false; } +function isNaN(value) { + // eslint-disable-next-line no-self-compare + return value !== value; +} + registerBidder(spec); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index e6f4d873ca5..7dcb5e3bbe6 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -171,7 +171,8 @@ describe('the rubicon adapter', () => { lastsearch: 'iphone' }, position: 'atf', - referrer: 'localhost' + referrer: 'localhost', + latLong: [40.7608, '111.8910'] }, adUnitCode: '/19968336/header-bid-tag-0', code: 'div-1', @@ -239,7 +240,9 @@ describe('the rubicon adapter', () => { 'tg_v.lastsearch': 'iphone', 'tg_i.rating': '5-star', 'tg_i.prodtype': 'tech', - 'rf': 'localhost' + 'rf': 'localhost', + 'p_geo.latitude': '40.7608', + 'p_geo.longitude': '111.8910' }; // test that all values above are both present and correct From fdadd141667eba92b7c3c2df705222e7ea98b843 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Fri, 11 May 2018 09:13:27 -0700 Subject: [PATCH 0342/1594] OpenX Adapter: GDPR Support (#2504) --- modules/openxBidAdapter.js | 43 +++-- test/spec/modules/openxBidAdapter_spec.js | 181 ++++++++++++++++++++++ 2 files changed, 212 insertions(+), 12 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index b425b80149a..2f116323a42 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -21,7 +21,7 @@ export const spec = { isBidRequestValid: function (bidRequest) { return !!(bidRequest.params.unit && bidRequest.params.delDomain); }, - buildRequests: function (bidRequests) { + buildRequests: function (bidRequests, bidderRequest) { if (bidRequests.length === 0) { return []; } @@ -31,12 +31,12 @@ export const spec = { // build banner requests if (bannerBids.length > 0) { - requests.push(buildOXBannerRequest(bannerBids)); + requests.push(buildOXBannerRequest(bannerBids, bidderRequest)); } // build video requests if (videoBids.length > 0) { videoBids.forEach(videoBid => { - requests.push(buildOXVideoRequest(videoBid)) + requests.push(buildOXVideoRequest(videoBid, bidderRequest)) }); } @@ -177,10 +177,11 @@ function getMediaTypeFromRequest(serverRequest) { return /avjp$/.test(serverRequest.url) ? VIDEO : BANNER; } -function buildCommonQueryParamsFromBids(bids) { +function buildCommonQueryParamsFromBids(bids, bidderRequest) { const isInIframe = utils.inIframe(); + let defaultParams; - return { + defaultParams = { ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), jr: utils.getTopWindowReferrer(), ch: document.charSet || document.characterSet, @@ -190,12 +191,30 @@ function buildCommonQueryParamsFromBids(bids) { tws: getViewportDimensions(isInIframe), be: 1, dddid: utils._map(bids, bid => bid.transactionId).join(','), - nocache: new Date().getTime(), + nocache: new Date().getTime() }; + + if (utils.deepAccess(bidderRequest, 'gdprConsent')) { + let gdprConsentConfig = bidderRequest.gdprConsent; + + if (gdprConsentConfig.consentString !== undefined) { + defaultParams.gdpr_consent = gdprConsentConfig.consentString; + } + + if (gdprConsentConfig.gdprApplies !== undefined) { + defaultParams.gdpr = gdprConsentConfig.gdprApplies ? 1 : 0; + } + + if (config.getConfig('consentManagement.cmpApi') === 'iab') { + defaultParams.x_gdpr_f = 1; + } + } + + return defaultParams; } -function buildOXBannerRequest(bids) { - let queryParams = buildCommonQueryParamsFromBids(bids); +function buildOXBannerRequest(bids, bidderRequest) { + let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); queryParams.auid = utils._map(bids, bid => bid.params.unit).join(','); queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); @@ -240,9 +259,9 @@ function buildOXBannerRequest(bids) { }; } -function buildOXVideoRequest(bid) { +function buildOXVideoRequest(bid, bidderRequest) { let url = `//${bid.params.delDomain}/v/1.0/avjp`; - let oxVideoParams = generateVideoParameters(bid); + let oxVideoParams = generateVideoParameters(bid, bidderRequest); return { method: 'GET', url: url, @@ -251,8 +270,8 @@ function buildOXVideoRequest(bid) { }; } -function generateVideoParameters(bid) { - let queryParams = buildCommonQueryParamsFromBids([bid]); +function generateVideoParameters(bid, bidderRequest) { + let queryParams = buildCommonQueryParamsFromBids([bid], bidderRequest); let oxVideoConfig = utils.deepAccess(bid, 'params.video') || {}; let context = utils.deepAccess(bid, 'mediaTypes.video.context'); let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index e4a1c9a979d..3585987e045 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -2,6 +2,7 @@ import {expect} from 'chai'; import {spec, resetBoPixel} from 'modules/openxBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import {userSync} from 'src/userSync'; +import {config} from 'src/config'; import * as utils from 'src/utils'; const URLBASE = '/w/1.0/arj'; @@ -343,6 +344,186 @@ describe('OpenxAdapter', () => { expect(dataParams.bc).to.exist; expect(dataParams.bc).to.equal('hb_override'); }); + + it('should not send any consent management properties', function () { + const request = spec.buildRequests(bidRequestsWithMediaTypes); + expect(request[0].data.gdpr).to.equal(undefined); + expect(request[0].data.gdpr_consent).to.equal(undefined); + expect(request[0].data.x_gdpr_f).to.equal(undefined); + }); + + describe('when there is a consent management framework', () => { + let bidRequests; + let mockConfig; + let bidderRequest; + const IAB_CONSENT_FRAMEWORK_CODE = 1; + + beforeEach(() => { + bidRequests = [{ + bidder: 'openx', + params: { + unit: '12345678-banner', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id', + bidderRequestId: 'test-bidder-request-id', + auctionId: 'test-auction-id' + }, { + 'bidder': 'openx', + 'mediaTypes': { + video: { + playerSize: [640, 480] + } + }, + 'params': { + 'unit': '12345678-video', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + + bidId: 'test-bid-id', + bidderRequestId: 'test-bidder-request-id', + auctionId: 'test-auction-id', + transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' + }]; + }); + + afterEach(function () { + config.getConfig.restore(); + }); + + describe('when GDPR applies', function () { + beforeEach(function () { + bidderRequest = { + gdprConsent: { + consentString: 'test-gdpr-consent-string', + gdprApplies: true + } + }; + + mockConfig = { + consentManagement: { + cmpApi: 'iab', + timeout: 1111, + allowAuctionWithoutConsent: 'cancel' + } + }; + + sinon.stub(config, 'getConfig').callsFake((key) => { + return utils.deepAccess(mockConfig, key); + }); + }); + + it('should send a signal to specify that GDPR applies to this request', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data.gdpr).to.equal(1); + expect(request[1].data.gdpr).to.equal(1); + }); + + it('should send the consent string', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data.gdpr_consent).to.equal(bidderRequest.gdprConsent.consentString); + expect(request[1].data.gdpr_consent).to.equal(bidderRequest.gdprConsent.consentString); + }); + + it('should send the consent management framework code', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data.x_gdpr_f).to.equal(IAB_CONSENT_FRAMEWORK_CODE); + expect(request[1].data.x_gdpr_f).to.equal(IAB_CONSENT_FRAMEWORK_CODE); + }); + }); + + describe('when GDPR does not apply', function () { + beforeEach(function () { + bidderRequest = { + gdprConsent: { + consentString: 'test-gdpr-consent-string', + gdprApplies: false + } + }; + + mockConfig = { + consentManagement: { + cmpApi: 'iab', + timeout: 1111, + allowAuctionWithoutConsent: 'cancel' + } + }; + + sinon.stub(config, 'getConfig').callsFake((key) => { + return utils.deepAccess(mockConfig, key); + }); + }); + + it('should not send a signal to specify that GDPR does not apply to this request', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data.gdpr).to.equal(0); + expect(request[1].data.gdpr).to.equal(0); + }); + + it('should send the consent string', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data.gdpr_consent).to.equal(bidderRequest.gdprConsent.consentString); + expect(request[1].data.gdpr_consent).to.equal(bidderRequest.gdprConsent.consentString); + }); + + it('should send the consent management framework code', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data.x_gdpr_f).to.equal(IAB_CONSENT_FRAMEWORK_CODE); + expect(request[1].data.x_gdpr_f).to.equal(IAB_CONSENT_FRAMEWORK_CODE); + }); + }); + + describe('when GDPR consent has undefined data', function () { + beforeEach(function () { + bidderRequest = { + gdprConsent: { + consentString: 'test-gdpr-consent-string', + gdprApplies: true + } + }; + + mockConfig = { + consentManagement: { + cmpApi: 'iab', + timeout: 1111, + allowAuctionWithoutConsent: 'cancel' + } + }; + + sinon.stub(config, 'getConfig').callsFake((key) => { + return utils.deepAccess(mockConfig, key); + }); + }); + + it('should not send a signal to specify whether GDPR applies to this request, when GDPR application is undefined', function () { + delete bidderRequest.gdprConsent.gdprApplies; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data).to.not.have.property('gdpr'); + expect(request[1].data).to.not.have.property('gdpr'); + }); + + it('should not send the consent string, when consent string is undefined', function () { + delete bidderRequest.gdprConsent.consentString; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data).to.not.have.property('gdpr_consent'); + expect(request[1].data).to.not.have.property('gdpr_consent'); + }); + + it('should not send the consent management framework code, when format is undefined', function () { + delete mockConfig.consentManagement.cmpApi; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data).to.not.have.property('x_gdpr_f'); + expect(request[1].data).to.not.have.property('x_gdpr_f'); + }); + }); + }); }); describe('buildRequests for video', () => { From 22497787bc57281f93aa2089509c240d1e371dd4 Mon Sep 17 00:00:00 2001 From: brainymisio Date: Sat, 12 May 2018 02:15:44 +0900 Subject: [PATCH 0343/1594] Add new Adapter brainyBidAdapter (#2458) --- modules/brainyBidAdapter.js | 131 +++++++++++++++++++++ modules/brainyBidAdapter.md | 31 +++++ test/spec/modules/brainyBidAdapter_spec.js | 80 +++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 modules/brainyBidAdapter.js create mode 100644 modules/brainyBidAdapter.md create mode 100644 test/spec/modules/brainyBidAdapter_spec.js diff --git a/modules/brainyBidAdapter.js b/modules/brainyBidAdapter.js new file mode 100644 index 00000000000..e8beb20573f --- /dev/null +++ b/modules/brainyBidAdapter.js @@ -0,0 +1,131 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'brainy'; +const BASE_URL = '//proparm.co.jp/ssp/p/pbjs'; + +/** + * Check if the browser supports flash + * 0 is return if it dosen't support flash + * @return {int} Flash version + */ +/** + * 接続元のブラウザがフラッシュに対応しているか判定 + * 対応していなければ0を返す + * @return {int} フラッシュのバージョン + */ +function _getFlash() { + try { + var _mac = (navigator.userAgent.indexOf('Mac') != -1); + if (document.all) { + if (_mac) { + if (window['sample']) { + return ((window['sample'].FlashVersion() & 0xffff0000) >> 16); + } + } else { + var _axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); + return Math.floor(_axo.FlashVersion() / 0x10000); + } + } else { + if (navigator.plugins && navigator.plugins['Shockwave Flash']) { + var info = navigator.plugins['Shockwave Flash'].description.split(' '); + var _v = parseInt(info[2]); + if (!isNaN(_v)) { + return _v; + } + } + } + } catch (e) {} + return 0; +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + /** + * Check if the bid account ID and slotID is valid + * @param {object} bid the brainy bid to validate + * @return {boolean} + */ + /** + * adUnits.bidに値が入っているかを判断する + * @param {object} bid 検証する入札リクエスト + * @return {boolean} + */ + isBidRequestValid: function(bid) { + return !!(bid && bid.params && bid.params.accountID && bid.params.slotID); + }, + + /** + * Format the bid request object for our endpoint + * @param {BidRequest[]} bidRequests Array of brainy bidders + * @return object of parameters for Prebid AJAX request + */ + /** + * 入札リクエストをbrainyに対応するように整形する + * @param {BidRequest[]} bidRequests 入札のための配列 + * @return Prebid AJAX用に整形したオブジェクト + */ + buildRequests: function(validBidRequests) { + var bidRequests = []; + for (var i = 0, len = validBidRequests.length; i < len; i++) { + var bid = validBidRequests[i]; + var accountID = utils.getBidIdParameter('accountID', bid.params); + var slotID = utils.getBidIdParameter('slotID', bid.params); + var url = utils.getTopWindowUrl(); + var flash = _getFlash(); + var nocache = new Date().getTime() + Math.floor(Math.random() * 100000000); + var requestURL; + + requestURL = '_aid=' + accountID + '&'; + requestURL += '_slot=' + slotID + '&'; + requestURL += '_url=' + url + '&'; + requestURL += '_flash=' + flash + '&'; + requestURL += '_nocache=' + nocache; + + bidRequests.push({ + method: 'GET', + url: BASE_URL, + data: requestURL, + bidRequest: bid + }) + } + return bidRequests; + }, + + /** + * Format brainy responses as Prebid bid responses + * @param {String} brainyResponseObj A successful response from brainy. + * @param {object} request Object received from web page + * @return {object} An array of formatted bids. + */ + /** + * brainySSPからのレスポンスを解釈するメソッド + * @param {String} brainyResponseObj SSPから受け取った文字列 + * @param {object} request メディアから受け取ったオブジェクト + * @return {object} 分解、再格納したbidResponses + */ + interpretResponse: function (brainyResponseObj, request) { + var bidResponses = []; + var bidRequest = request.bidRequest; + var responseBody = brainyResponseObj ? brainyResponseObj.body : {}; + + bidResponses.push({ + requestId: bidRequest.bidId, + cpm: responseBody.cpm || 0, + width: responseBody.width, + height: responseBody.height, + creativeId: responseBody.adID, + currency: 'USD', + netRevenue: true, + ttl: 1000, + mediaType: BANNER, + ad: responseBody.src + }); + + return bidResponses; + } +}; +registerBidder(spec); diff --git a/modules/brainyBidAdapter.md b/modules/brainyBidAdapter.md new file mode 100644 index 00000000000..0f8308f6cc3 --- /dev/null +++ b/modules/brainyBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +``` +Module Name: brainy Bid Adapter +Module Type: Bidder Adapter +Maintainer: support@mg.brainy-inc.co.jp +``` + +# Description +This module connects to brainy's demand sources. It supports display, and rich media formats. +brainy will provide ``accountID`` and ``slotID`` that are specific to your ad type. +Please reach out to ``support@mg.brainy-inc.co.jp`` to set up an brainy account and above ids. +Use bidder code ```brainy``` for all brainy traffic. + + +# Test Parameters + +``` + var adUnits = [{ + code: 'test-div', + sizes: [[300, 250], + bids: [{ + bidder: 'brainy', + params: { + accountID: "3481", + slotID: "5569" + } + }] + } + ]; +``` diff --git a/test/spec/modules/brainyBidAdapter_spec.js b/test/spec/modules/brainyBidAdapter_spec.js new file mode 100644 index 00000000000..4f619323d7d --- /dev/null +++ b/test/spec/modules/brainyBidAdapter_spec.js @@ -0,0 +1,80 @@ +import { expect } from 'chai'; +import { spec } from 'modules/brainyBidAdapter'; + +const URL = '//proparm.co.jp/ssp/p/pbjs'; +const BIDDER_CODE = 'brainy'; + +const validBidReq = { + bidder: BIDDER_CODE, + params: { + accountID: '12345', + slotID: '12345' + } +}; + +const invalidBidReq = { + bidder: BIDDER_CODE, + params: { + accountID: '', + slotID: '' + } +}; + +const bidReq = [{ + bidder: BIDDER_CODE, + params: { + accountID: '12345', + slotID: '12345' + } +}]; + +const correctReq = { + accountID: '12345', + slotID: '12345' +} + +const bidResponse = { + ad_id: '1036e9746c-d186-49ae-90cb-2796d0f9b223', + adm: '', + cpm: 100, + height: 250, + width: 300 +}; + +describe('brainy Adapter', () => { + describe('request', () => { + it('should validate bid request', () => { + expect(spec.isBidRequestValid(validBidReq)).to.equal(true); + }); + it('should not validate incorrect bid request', () => { + expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); + }); + }); + describe('build request', () => { + it('Verify bid request', () => { + const request = spec.buildRequests(bidReq); + expect(request[0].method).to.equal('GET'); + expect(request[0].url).to.equal(URL); + expect(request[0].data).to.match(new RegExp(`${correctReq.accountID}`)); + expect(request[0].data).to.match(new RegExp(`${correctReq.slotID}`)); + }); + }); + + describe('interpretResponse', () => { + it('should build bid array', () => { + const request = spec.buildRequests(bidReq); + const result = spec.interpretResponse({body: bidResponse}, request[0]); + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', () => { + const request = spec.buildRequests(bidReq); + const result = spec.interpretResponse({body: bidResponse}, request[0]); + const bid = result[0]; + + expect(bid.cpm).to.equal(bidResponse.cpm); + expect(bid.width).to.equal(bidResponse.width); + expect(bid.height).to.equal(bidResponse.height); + }); + }); +}); From 1f2a7fb310007f5406cf1beb816a6ccf05e1b6c0 Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Mon, 14 May 2018 15:16:18 +0100 Subject: [PATCH 0344/1594] Add 1024x768 (size_id = 53) in sizeMap (#2527) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index d6a69fda625..fe8142b9061 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -37,6 +37,7 @@ var sizeMap = { 43: '320x50', 44: '300x50', 48: '300x300', + 53: '1024x768', 54: '300x1050', 55: '970x90', 57: '970x250', From 119e590dbb2976f7f770612da174347da65dadc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dejan=20=C5=A0trbac?= Date: Mon, 14 May 2018 20:22:05 +0200 Subject: [PATCH 0345/1594] Aardvark v1.0 (#2507) * Aardvark v1.0 + Add GDPR support * required modifications * cover case where gdprConsent data is not present * demo auction update * ignore empty bids * accept empty bids --- modules/aardvarkBidAdapter.js | 159 +++++++++++ modules/aardvarkBidAdapter.md | 30 +++ test/spec/modules/aardvarkBidAdapter_spec.js | 264 +++++++++++++++++++ 3 files changed, 453 insertions(+) create mode 100644 modules/aardvarkBidAdapter.js create mode 100644 modules/aardvarkBidAdapter.md create mode 100644 test/spec/modules/aardvarkBidAdapter_spec.js diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js new file mode 100644 index 00000000000..7d358864b35 --- /dev/null +++ b/modules/aardvarkBidAdapter.js @@ -0,0 +1,159 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'aardvark'; +const DEFAULT_ENDPOINT = 'bidder.rtk.io'; +const SYNC_ENDPOINT = 'sync.rtk.io'; +const AARDVARK_TTL = 300; +const AARDVARK_CURRENCY = 'USD'; + +let hasSynced = false; + +export function resetUserSync() { + hasSynced = false; +} + +export const spec = { + code: BIDDER_CODE, + + isBidRequestValid: function(bid) { + return ((typeof bid.params.ai === 'string') && !!bid.params.ai.length && + (typeof bid.params.sc === 'string') && !!bid.params.sc.length); + }, + + buildRequests: function(validBidRequests, bidderRequest) { + var auctionCodes = []; + var requests = []; + var requestsMap = {}; + var referer = utils.getTopWindowUrl(); + var pageCategories = []; + + if (window.top.rtkcategories && Array.isArray(window.top.rtkcategories)) { + pageCategories = window.top.rtkcategories; + } + + utils._each(validBidRequests, function(b) { + var rMap = requestsMap[b.params.ai]; + if (!rMap) { + rMap = { + shortCodes: [], + payload: { + version: 1, + jsonp: false, + rtkreferer: referer + }, + endpoint: DEFAULT_ENDPOINT + }; + + if (pageCategories && pageCategories.length) { + rMap.payload.categories = pageCategories.slice(0); + } + + if (b.params.categories && b.params.categories.length) { + rMap.payload.categories = rMap.payload.categories || [] + utils._each(b.params.categories, function(cat) { + rMap.payload.categories.push(cat); + }); + } + + if (bidderRequest && bidderRequest.gdprConsent) { + rMap.payload.gdpr = false; + if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { + rMap.payload.gdpr = bidderRequest.gdprConsent.gdprApplies; + } + if (rMap.payload.gdpr) { + rMap.payload.consent = bidderRequest.gdprConsent.consentString; + } + } + + requestsMap[b.params.ai] = rMap; + auctionCodes.push(b.params.ai); + } + + rMap.shortCodes.push(b.params.sc); + rMap.payload[b.params.sc] = b.bidId; + + if ((typeof b.params.host === 'string') && b.params.host.length && + (b.params.host !== rMap.endpoint)) { + rMap.endpoint = b.params.host; + } + }); + + utils._each(auctionCodes, function(auctionId) { + var req = requestsMap[auctionId]; + requests.push({ + method: 'GET', + url: `//${req.endpoint}/${auctionId}/${req.shortCodes.join('_')}/aardvark`, + data: req.payload, + bidderRequest + }); + }); + + return requests; + }, + + interpretResponse: function(serverResponse, bidRequest) { + var bidResponses = []; + + if (!Array.isArray(serverResponse.body)) { + serverResponse.body = [serverResponse.body]; + } + + utils._each(serverResponse.body, function(rawBid) { + var bidResponse = { + requestId: rawBid.cid, + cpm: rawBid.cpm || 0, + width: rawBid.width || 0, + height: rawBid.height || 0, + currency: rawBid.currency ? rawBid.currency : AARDVARK_CURRENCY, + netRevenue: rawBid.netRevenue ? rawBid.netRevenue : true, + ttl: rawBid.ttl ? rawBid.ttl : AARDVARK_TTL, + creativeId: rawBid.creativeId || 0 + }; + + if (rawBid.hasOwnProperty('dealId')) { + bidResponse.dealId = rawBid.dealId + } + + switch (rawBid.media) { + case 'banner': + bidResponse.ad = rawBid.adm + utils.createTrackPixelHtml(decodeURIComponent(rawBid.nurl)); + break; + + default: + return utils.logError('bad Aardvark response (media)', rawBid); + } + + bidResponses.push(bidResponse); + }); + + return bidResponses; + }, + + getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + const syncs = []; + var url = '//' + SYNC_ENDPOINT + '/cs'; + var gdprApplies = false; + if (gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean')) { + gdprApplies = gdprConsent.gdprApplies; + } + + if (syncOptions.iframeEnabled) { + if (!hasSynced) { + hasSynced = true; + if (gdprApplies) { + url = url + '?g=1&c=' + encodeURIComponent(gdprConsent.consentString); + } + syncs.push({ + type: 'iframe', + url: url + }); + } + } else { + utils.logWarn('Aardvark: Please enable iframe based user sync.'); + } + return syncs; + } +}; + +registerBidder(spec); diff --git a/modules/aardvarkBidAdapter.md b/modules/aardvarkBidAdapter.md new file mode 100644 index 00000000000..9f7a128b6f3 --- /dev/null +++ b/modules/aardvarkBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +**Module Name**: Aardvark Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: chris@rtk.io + +# Description + +Module that connects to a RTK.io Ad Units to fetch bids. + +# Test Parameters +``` + var adUnits = [{ + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + code: 'div-gpt-ad-1460505748561-0', + + bids: [{ + bidder: 'aardvark', + params: { + ai: '0000', + sc: '1234' + } + }] + + }]; +``` diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js new file mode 100644 index 00000000000..d2b9cbc0fa8 --- /dev/null +++ b/test/spec/modules/aardvarkBidAdapter_spec.js @@ -0,0 +1,264 @@ +import { expect } from 'chai'; +import { spec } from 'modules/aardvarkBidAdapter'; + +describe('aardvarkAdapterTest', () => { + describe('forming valid bidRequests', () => { + it('should accept valid bidRequests', () => { + expect(spec.isBidRequestValid({ + bidder: 'aardvark', + params: { + ai: 'xiby', + sc: 'TdAx', + }, + sizes: [[300, 250]] + })).to.equal(true); + }); + + it('should reject invalid bidRequests', () => { + expect(spec.isBidRequestValid({ + bidder: 'aardvark', + params: { + ai: 'xiby', + }, + sizes: [[300, 250]] + })).to.equal(false); + }); + }); + + describe('executing network requests', () => { + const bidRequests = [{ + bidder: 'aardvark', + params: { + ai: 'xiby', + sc: 'TdAx', + }, + adUnitCode: 'aaa', + transactionId: '1b8389fe-615c-482d-9f1a-177fb8f7d5b0', + sizes: [300, 250], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + }, + { + bidder: 'aardvark', + params: { + ai: 'xiby', + sc: 'RAZd', + host: 'adzone.pub.com' + }, + adUnitCode: 'bbb', + transactionId: '193995b4-7122-4739-959b-2463282a138b', + sizes: [[800, 600]], + bidId: '22aidtbx5eabd9', + bidderRequestId: '70deaff71c281d', + auctionId: 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' + }]; + + it('should use HTTP GET method', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + }); + }); + + it('should call the correct bidRequest url', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests.length).to.equal(1); + expect(requests[0].url).to.match(new RegExp('^\/\/adzone.pub.com/xiby/TdAx_RAZd/aardvark\?')); + }); + + it('should have correct data', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests.length).to.equal(1); + expect(requests[0].data.version).to.equal(1); + expect(requests[0].data.jsonp).to.equal(false); + expect(requests[0].data.TdAx).to.equal('1abgs362e0x48a8'); + expect(requests[0].data.rtkreferer).to.not.be.undefined; + expect(requests[0].data.RAZd).to.equal('22aidtbx5eabd9'); + }); + }); + + describe('splitting multi-auction ad units into own requests', () => { + const bidRequests = [{ + bidder: 'aardvark', + params: { + ai: 'Toby', + sc: 'TdAx', + categories: ['cat1', 'cat2'] + }, + adUnitCode: 'aaa', + transactionId: '1b8389fe-615c-482d-9f1a-177fb8f7d5b0', + sizes: [300, 250], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + }, + { + bidder: 'aardvark', + params: { + ai: 'xiby', + sc: 'RAZd', + host: 'adzone.pub.com' + }, + adUnitCode: 'bbb', + transactionId: '193995b4-7122-4739-959b-2463282a138b', + sizes: [[800, 600]], + bidId: '22aidtbx5eabd9', + bidderRequestId: '70deaff71c281d', + auctionId: 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' + }]; + + it('should use HTTP GET method', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + }); + }); + + it('should call the correct bidRequest urls for each auction', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].url).to.match(new RegExp('^\/\/bidder.rtk.io/Toby/TdAx/aardvark\?')); + expect(requests[0].data.categories.length).to.equal(2); + expect(requests[1].url).to.match(new RegExp('^\/\/adzone.pub.com/xiby/RAZd/aardvark\?')); + }); + + it('should have correct data', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests.length).to.equal(2); + expect(requests[0].data.version).to.equal(1); + expect(requests[0].data.jsonp).to.equal(false); + expect(requests[0].data.TdAx).to.equal('1abgs362e0x48a8'); + expect(requests[0].data.rtkreferer).to.not.be.undefined; + expect(requests[0].data.RAZd).to.be.undefined; + expect(requests[1].data.version).to.equal(1); + expect(requests[1].data.jsonp).to.equal(false); + expect(requests[1].data.TdAx).to.be.undefined; + expect(requests[1].data.rtkreferer).to.not.be.undefined; + expect(requests[1].data.RAZd).to.equal('22aidtbx5eabd9'); + }); + }); + + describe('GDPR conformity', () => { + const bidRequests = [{ + bidder: 'aardvark', + params: { + ai: 'xiby', + sc: 'TdAx', + }, + adUnitCode: 'aaa', + transactionId: '1b8389fe-615c-482d-9f1a-177fb8f7d5b0', + sizes: [300, 250], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + }]; + + const bidderRequest = { + gdprConsent: { + consentString: 'awefasdfwefasdfasd', + gdprApplies: true + } + }; + + it('should transmit correct data', () => { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests.length).to.equal(1); + expect(requests[0].data.gdpr).to.equal(true); + expect(requests[0].data.consent).to.equal('awefasdfwefasdfasd'); + }); + }); + + describe('GDPR absence conformity', () => { + const bidRequests = [{ + bidder: 'aardvark', + params: { + ai: 'xiby', + sc: 'TdAx', + }, + adUnitCode: 'aaa', + transactionId: '1b8389fe-615c-482d-9f1a-177fb8f7d5b0', + sizes: [300, 250], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + }]; + + const bidderRequest = { + gdprConsent: undefined + }; + + it('should transmit correct data', () => { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests.length).to.equal(1); + expect(requests[0].data.gdpr).to.be.undefined; + expect(requests[0].data.consent).to.be.undefined; + }); + }); + + describe('interpretResponse', () => { + it('should handle bid responses', () => { + const serverResponse = { + body: [ + { + media: 'banner', + nurl: 'http://www.nurl.com/0', + cpm: 0.09, + width: 300, + height: 250, + cid: '22aidtbx5eabd9', + adm: '', + dealId: 'dealing', + ttl: 200, + }, + { + media: 'banner', + nurl: 'http://www.nurl.com/1', + cpm: 0.19, + width: 300, + height: 250, + cid: '1abgs362e0x48a8', + adm: '', + ttl: 200, + } + ], + headers: {} + }; + + const result = spec.interpretResponse(serverResponse, {}); + expect(result.length).to.equal(2); + + expect(result[0].requestId).to.equal('22aidtbx5eabd9'); + expect(result[0].cpm).to.equal(0.09); + expect(result[0].width).to.equal(300); + expect(result[0].height).to.equal(250); + expect(result[0].currency).to.equal('USD'); + expect(result[0].ttl).to.equal(200); + expect(result[0].dealId).to.equal('dealing'); + expect(result[0].ad).to.not.be.undefined; + + expect(result[1].requestId).to.equal('1abgs362e0x48a8'); + expect(result[1].cpm).to.equal(0.19); + expect(result[1].width).to.equal(300); + expect(result[1].height).to.equal(250); + expect(result[1].currency).to.equal('USD'); + expect(result[1].ttl).to.equal(200); + expect(result[1].ad).to.not.be.undefined; + }); + + it('should handle nobid responses', () => { + var emptyResponse = [{ + nurl: '', + cid: '9e5a09319e18f1', + media: 'banner', + error: 'No bids received for 9DgF', + adm: '', + id: '9DgF', + cpm: 0.00 + }]; + + var result = spec.interpretResponse({ body: emptyResponse }, {}); + expect(result.length).to.equal(1); + expect(result[0].cpm).to.equal(0.0); + }); + }); +}); From c5a3d127b4b78ab7f6510d36f15db0dd8643e5eb Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 14 May 2018 17:09:33 -0400 Subject: [PATCH 0346/1594] Show only summary and errors (#2514) --- karma.conf.maker.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 2ff1d7d0880..5d075b6929c 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -142,7 +142,8 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) { reporters: ['mocha'], mochaReporter: { - showDiff: true + showDiff: true, + output: 'minimal' }, // Continuous Integration mode From ab5ca4d9ffc3b67956a40e1396bd9cdf7f168caa Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Mon, 14 May 2018 14:49:16 -0700 Subject: [PATCH 0347/1594] added gdpr support to userSync in rubicon adapter (#2531) * added gdpr support to userSync in rubicon adapter * added test for consentString * added unit test for undefined consentString * changed undefined test for consentString * changed undefined test for consentString type of string * added test for consentString type of number, obj, and null --- modules/rubiconBidAdapter.js | 16 +++++- test/spec/modules/rubiconBidAdapter_spec.js | 60 +++++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index fe8142b9061..f91c76d6afa 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -358,12 +358,24 @@ export const spec = { return bids; }, []); }, - getUserSyncs: function (syncOptions) { + getUserSyncs: function (syncOptions, responses, gdprConsent) { if (!hasSynced && syncOptions.iframeEnabled) { + // data is only assigned if params are available to pass to SYNC_ENDPOINT + 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}`; + } + } + hasSynced = true; return { type: 'iframe', - url: SYNC_ENDPOINT + url: SYNC_ENDPOINT + params }; } } diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 7dcb5e3bbe6..20bd1f3b99c 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1206,6 +1206,66 @@ describe('the rubicon adapter', () => { syncs = spec.getUserSyncs(); expect(syncs).to.equal(undefined); }); + + it('should pass gdpr params if consent is true', () => { + expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { + gdprApplies: true, consentString: 'foo' + })).to.deep.equal({ + type: 'iframe', url: `${emilyUrl}?gdpr=1&gdpr_consent=foo` + }); + }); + + it('should pass gdpr params if consent is false', () => { + expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { + gdprApplies: false, consentString: 'foo' + })).to.deep.equal({ + type: 'iframe', url: `${emilyUrl}?gdpr=0&gdpr_consent=foo` + }); + }); + + it('should pass gdpr param gdpr_consent only when gdprApplies is undefined', () => { + expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { + consentString: 'foo' + })).to.deep.equal({ + type: 'iframe', url: `${emilyUrl}?gdpr_consent=foo` + }); + }); + + it('should pass no params if gdpr consentString is not defined', () => { + expect(spec.getUserSyncs({ iframeEnabled: true }, {}, {})).to.deep.equal({ + type: 'iframe', url: `${emilyUrl}` + }); + }); + + it('should pass no params if gdpr consentString is a number', () => { + expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { + consentString: 0 + })).to.deep.equal({ + type: 'iframe', url: `${emilyUrl}` + }); + }); + + it('should pass no params if gdpr consentString is null', () => { + expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { + consentString: null + })).to.deep.equal({ + type: 'iframe', url: `${emilyUrl}` + }); + }); + + it('should pass no params if gdpr consentString is a object', () => { + expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { + consentString: {} + })).to.deep.equal({ + type: 'iframe', url: `${emilyUrl}` + }); + }); + + it('should pass no params if gdpr is not defined', () => { + expect(spec.getUserSyncs({ iframeEnabled: true }, {}, undefined)).to.deep.equal({ + type: 'iframe', url: `${emilyUrl}` + }); + }); }); }); From 6785bc5be3a25d8bdfe47a3a20d4c221bab24806 Mon Sep 17 00:00:00 2001 From: harpere Date: Mon, 14 May 2018 23:09:07 -0400 Subject: [PATCH 0348/1594] fixed bug when latitute/longitue are not provided (#2533) --- modules/rubiconBidAdapter.js | 4 +- test/spec/modules/rubiconBidAdapter_spec.js | 62 ++++++++++++++++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index f91c76d6afa..061440e7c0e 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -233,8 +233,8 @@ export const spec = { 'p_screen_res', _getScreenResolution(), 'kw', keywords, 'tk_user_key', userId, - 'p_geo.latitude', parseFloat(latitude).toFixed(4), - 'p_geo.longitude', parseFloat(longitude).toFixed(4) + 'p_geo.latitude', isNaN(parseFloat(latitude)) ? undefined : parseFloat(latitude).toFixed(4), + 'p_geo.longitude', isNaN(parseFloat(longitude)) ? undefined : parseFloat(longitude).toFixed(4) ]; if (gdprConsent) { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 20bd1f3b99c..f0ffee12806 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -172,7 +172,7 @@ describe('the rubicon adapter', () => { }, position: 'atf', referrer: 'localhost', - latLong: [40.7608, '111.8910'] + latLong: [40.7607823, '111.8910325'] }, adUnitCode: '/19968336/header-bid-tag-0', code: 'div-1', @@ -256,6 +256,66 @@ describe('the rubicon adapter', () => { }); }); + it('should make a well-formed request object without latLong', () => { + let expectedQuery = { + 'account_id': '14062', + 'site_id': '70608', + 'zone_id': '335918', + 'size_id': '15', + 'alt_size_ids': '43', + 'p_pos': 'atf', + 'rp_floor': '0.01', + 'rp_secure': /[01]/, + 'rand': '0.1', + 'tk_flint': INTEGRATION, + 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'p_screen_res': /\d+x\d+/, + 'tk_user_key': '12346', + 'kw': 'a,b,c', + 'tg_v.ucat': 'new', + 'tg_v.lastsearch': 'iphone', + 'tg_i.rating': '5-star', + 'tg_i.prodtype': 'tech', + 'rf': 'localhost', + 'p_geo.latitude': undefined, + 'p_geo.longitude': undefined + }; + + sandbox.stub(Math, 'random').callsFake(() => 0.1); + + delete bidderRequest.bids[0].params.latLong; + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + data = parseQuery(request.data); + + expect(request.url).to.equal('//fastlane.rubiconproject.com/a/api/fastlane.json'); + + // test that all values above are both present and correct + Object.keys(expectedQuery).forEach(key => { + let value = expectedQuery[key]; + if (value instanceof RegExp) { + expect(data[key]).to.match(value); + } else { + expect(data[key]).to.equal(value); + } + }); + + bidderRequest.bids[0].params.latLong = []; + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); + + expect(request.url).to.equal('//fastlane.rubiconproject.com/a/api/fastlane.json'); + + // test that all values above are both present and correct + Object.keys(expectedQuery).forEach(key => { + let value = expectedQuery[key]; + if (value instanceof RegExp) { + expect(data[key]).to.match(value); + } else { + expect(data[key]).to.equal(value); + } + }); + }); + it('page_url should use params.referrer, config.getConfig("pageUrl"), utils.getTopWindowUrl() in that order', () => { sandbox.stub(utils, 'getTopWindowUrl').callsFake(() => 'http://www.prebid.org'); From 2607bccd5b1ff48587ad0d12f9f9e6e8d2ebd76d Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 15 May 2018 08:39:20 -0400 Subject: [PATCH 0349/1594] change AppNexus endpoint to use ORTB (#2532) --- modules/prebidServerBidAdapter.js | 4 ++-- test/spec/modules/prebidServerBidAdapter_spec.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index f499f5a0ae4..2fd9c18eb06 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -37,7 +37,7 @@ const availVendorDefaults = { adapter: 'prebidServer', cookieSet: false, enabled: true, - endpoint: '//prebid.adnxs.com/pbs/v1/auction', + endpoint: '//prebid.adnxs.com/pbs/v1/openrtb2/auction', syncEndpoint: '//prebid.adnxs.com/pbs/v1/cookie_sync', timeout: 1000 }, @@ -637,7 +637,7 @@ const OPEN_RTB_PROTOCOL = { * const bids = protocol().interpretResponse(response, bidRequests, requestedBidders); */ const protocolAdapter = () => { - const OPEN_RTB_PATH = 'openrtb2/auction'; + const OPEN_RTB_PATH = '/openrtb2/'; const endpoint = (_s2sConfig && _s2sConfig.endpoint) || ''; const isOpenRtb = ~endpoint.indexOf(OPEN_RTB_PATH); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index cdb3113c205..857105c3b40 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -982,7 +982,7 @@ describe('S2S Adapter', () => { expect(vendorConfig.cookieSet).to.be.false; expect(vendorConfig.cookieSetUrl).to.be.undefined; expect(vendorConfig.enabled).to.be.true; - expect(vendorConfig).to.have.property('endpoint', '//prebid.adnxs.com/pbs/v1/auction'); + expect(vendorConfig).to.have.property('endpoint', '//prebid.adnxs.com/pbs/v1/openrtb2/auction'); expect(vendorConfig).to.have.property('syncEndpoint', '//prebid.adnxs.com/pbs/v1/cookie_sync'); expect(vendorConfig).to.have.property('timeout', 750); }); From 735bf76b7d91723a7d2608184286cf0e7771207a Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Tue, 15 May 2018 20:04:19 +0530 Subject: [PATCH 0350/1594] -GDPR support added in media net bidder (#2538) --- modules/medianetBidAdapter.js | 22 +++--- test/spec/modules/medianetBidAdapter_spec.js | 71 +++++++++++++++++++- 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 8fe09ab74e6..08232231417 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -71,11 +71,16 @@ function getSize(size) { } } -function configuredParams(params) { - return { +function extParams(params, gdpr) { + let ext = { customer_id: params.cid, prebid_version: $$PREBID_GLOBAL$$.version + }; + ext.gdpr_applies = !!(gdpr && gdpr.gdprApplies); + if (ext.gdpr_applies) { + ext.gdpr_consent_string = gdpr.consentString || ''; } + return ext; } function slotParams(bidRequest) { @@ -100,13 +105,13 @@ function slotParams(bidRequest) { return params; } -function generatePayload(bidRequests, timeout) { +function generatePayload(bidRequests, bidderRequests) { return { site: siteDetails(bidRequests[0].params.site), - ext: configuredParams(bidRequests[0].params), + ext: extParams(bidRequests[0].params, bidderRequests.gdprConsent), id: bidRequests[0].auctionId, imp: bidRequests.map(request => slotParams(request)), - tmax: timeout + tmax: bidderRequests.timeout || config.getConfig('bidderTimeout') } } @@ -153,12 +158,11 @@ 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 {BidderRequests} bidderRequests * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(bidRequests, auctionData) { - let timeout = auctionData.timeout || config.getConfig('bidderTimeout'); - let payload = generatePayload(bidRequests, timeout); - + buildRequests: function(bidRequests, bidderRequests) { + let payload = generatePayload(bidRequests, bidderRequests); return { method: 'POST', url: BID_URL, diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 520ec34fc7d..a10dcb2624d 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -80,7 +80,8 @@ let VALID_BID_REQUEST = [{ }, 'ext': { 'customer_id': 'customer_id', - 'prebid_version': $$PREBID_GLOBAL$$.version + 'prebid_version': $$PREBID_GLOBAL$$.version, + 'gdpr_applies': false, }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ @@ -129,7 +130,8 @@ let VALID_BID_REQUEST = [{ }, 'ext': { 'customer_id': 'customer_id', - 'prebid_version': $$PREBID_GLOBAL$$.version + 'prebid_version': $$PREBID_GLOBAL$$.version, + 'gdpr_applies': false }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ @@ -331,7 +333,64 @@ let VALID_BID_REQUEST = [{ 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' - }]; + }], + VALID_BIDDER_REQUEST_WITH_GDPR = { + 'gdprConsent': { + 'consentString': 'consentString', + 'gdprApplies': true, + }, + 'timeout': 3000, + }, + VALID_PAYLOAD_FOR_GDPR = { + 'site': { + 'domain': 'media.net', + 'page': 'http://media.net/prebidtest', + 'ref': 'http://media.net/prebidtest' + }, + 'ext': { + 'customer_id': 'customer_id', + 'prebid_version': $$PREBID_GLOBAL$$.version, + 'gdpr_consent_string': 'consentString', + 'gdpr_applies': true, + }, + 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'imp': [{ + 'id': '28f8f8130a583e', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-0' + }, + 'banner': [{ + 'w': 300, + 'h': 250 + }], + 'all': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + } + }, { + 'id': '3f97ca71b1e5c2', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-123' + }, + 'banner': [{ + 'w': 300, + 'h': 251 + }], + 'all': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + } + }], + 'tmax': 3000, + }; describe('Media.net bid adapter', () => { describe('isBidRequestValid', () => { @@ -371,6 +430,12 @@ describe('Media.net bid adapter', () => { let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_INVALID_BIDFLOOR); }); + + it('should add gdpr to response ext', () => { + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_BIDDER_REQUEST_WITH_GDPR); + expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_FOR_GDPR); + }); + describe('build requests: when page meta-data is available', () => { it('should pass canonical, twitter and fb paramters if available', () => { let sandbox = sinon.sandbox.create(); From 6bfed30739f8c2e066101fbded3fe4f486a760f5 Mon Sep 17 00:00:00 2001 From: LifeStreet Date: Tue, 15 May 2018 18:08:40 +0300 Subject: [PATCH 0351/1594] Lifestreet: gdpr and consent string parameters (#2537) * GDPR support for Lifestreet bid adapter * removed trailing spaces --- modules/lifestreetBidAdapter.js | 16 ++++++-- .../spec/modules/lifestreetBidAdapter_spec.js | 41 +++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/modules/lifestreetBidAdapter.js b/modules/lifestreetBidAdapter.js index 919e83576d3..17aeeb56f2e 100644 --- a/modules/lifestreetBidAdapter.js +++ b/modules/lifestreetBidAdapter.js @@ -12,7 +12,7 @@ const urlTemplate = template`//ads.lfstmedia.com/gate/${'adapter'}/${'slot'}?adk * * @param {BidRequest} bid The bid params to use for formatting a request */ -function formatBidRequest(bid) { +function formatBidRequest(bid, bidderRequest) { let url = urlTemplate({ adapter: 'prebid', slot: bid.params.slot, @@ -28,6 +28,16 @@ function formatBidRequest(bid) { hbver: ADAPTER_VERSION }); + if (bidderRequest && bidderRequest.gdprConsent) { + if (bidderRequest.gdprConsent.gdprApplies !== undefined) { + const gdpr = '&__gdpr=' + (bidderRequest.gdprConsent.gdprApplies ? '1' : '0'); + url += gdpr; + } + if (bidderRequest.gdprConsent.consentString !== undefined) { + url += '&__consent=' + bidderRequest.gdprConsent.consentString; + } + } + return { method: 'GET', url: url, @@ -95,9 +105,9 @@ export const spec = { * @param {validBidRequests[]} - an array of bids * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(validBidRequests) { + buildRequests: function(validBidRequests, bidderRequest) { return validBidRequests.map(bid => { - return formatBidRequest(bid) + return formatBidRequest(bid, bidderRequest) }); }, diff --git a/test/spec/modules/lifestreetBidAdapter_spec.js b/test/spec/modules/lifestreetBidAdapter_spec.js index b47c5f949e2..2c48a0f1892 100644 --- a/test/spec/modules/lifestreetBidAdapter_spec.js +++ b/test/spec/modules/lifestreetBidAdapter_spec.js @@ -109,10 +109,51 @@ describe('LifestreetAdapter', () => { it('should include gzip', () => { expect(request.url).to.contain('__gz=1'); }); + it('should not contain __gdpr parameter', () => { + expect(request.url).to.not.contain('__gdpr'); + }); + it('should not contain __concent parameter', () => { + expect(request.url).to.not.contain('__consent'); + }); it('should contain the right version of adapter', () => { expect(request.url).to.contain('__hbver=' + ADAPTER_VERSION); }); + + it('should contain __gdpr and __consent parameters', () => { + const options = { + gdprConsent: { + gdprApplies: true, + consentString: 'test', + vendorData: {} + } + }; + let [request] = spec.buildRequests(bidRequest.bids, options); + expect(request.url).to.contain('__gdpr=1'); + expect(request.url).to.contain('__consent=test'); + }); + it('should contain __gdpr parameters', () => { + const options = { + gdprConsent: { + gdprApplies: true, + vendorData: {} + } + }; + let [request] = spec.buildRequests(bidRequest.bids, options); + expect(request.url).to.contain('__gdpr=1'); + expect(request.url).to.not.contain('__consent'); + }); + it('should contain __consent parameters', () => { + const options = { + gdprConsent: { + consentString: 'test', + vendorData: {} + } + }; + let [request] = spec.buildRequests(bidRequest.bids, options); + expect(request.url).to.not.contain('__gdpr'); + expect(request.url).to.contain('__consent=test'); + }); }); describe('interpretResponse()', () => { it('should return formatted bid response with required properties', () => { From 3436a132a67922f5c81e2cf6d8248c2c8657f90e Mon Sep 17 00:00:00 2001 From: GeronimoGXOne <38340784+GeronimoGXOne@users.noreply.github.com> Date: Tue, 15 May 2018 18:50:20 +0300 Subject: [PATCH 0352/1594] Create GXOne Bid Adapter and tests for it (#2540) --- modules/gxoneBidAdapter.js | 141 +++++++++++ modules/gxoneBidAdapter.md | 40 +++ test/spec/modules/gxoneBidAdapter_spec.js | 293 ++++++++++++++++++++++ 3 files changed, 474 insertions(+) create mode 100644 modules/gxoneBidAdapter.js create mode 100755 modules/gxoneBidAdapter.md create mode 100644 test/spec/modules/gxoneBidAdapter_spec.js diff --git a/modules/gxoneBidAdapter.js b/modules/gxoneBidAdapter.js new file mode 100644 index 00000000000..77c5ae2b1b7 --- /dev/null +++ b/modules/gxoneBidAdapter.js @@ -0,0 +1,141 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'gxone'; +const ENDPOINT_URL = '//ads.gx1as.com/hb'; +const TIME_TO_LIVE = 360; +const ADAPTER_SYNC_URL = '//ads.gx1as.com/push_sync'; +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', + noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', + emptyUids: 'Uids should be not empty', + emptySeatbid: 'Seatbid array from response has empty item', + emptyResponse: 'Response is empty', + hasEmptySeatbidArray: 'Response has empty seatbid array', + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' +}; + +/** + * GXOne Bid Adapter. + * Contact: olivier@geronimo.co + * + */ +export const spec = { + code: BIDDER_CODE, + + isBidRequestValid: function(bid) { + return !!bid.params.uid; + }, + + buildRequests: function(validBidRequests) { + const auids = []; + const bidsMap = {}; + const bids = validBidRequests || []; + let priceType = 'net'; + let reqId; + + bids.forEach(bid => { + if (bid.params.priceType === 'gross') { + priceType = 'gross'; + } + if (!bidsMap[bid.params.uid]) { + bidsMap[bid.params.uid] = [bid]; + auids.push(bid.params.uid); + } else { + bidsMap[bid.params.uid].push(bid); + } + reqId = bid.bidderRequestId; + }); + + const payload = { + u: utils.getTopWindowUrl(), + pt: priceType, + auids: auids.join(','), + r: reqId, + }; + + return { + method: 'GET', + url: ENDPOINT_URL, + data: utils.parseQueryStringParameters(payload).replace(/\&$/, ''), + bidsMap: bidsMap, + }; + }, + + interpretResponse: function(serverResponse, bidRequest) { + serverResponse = serverResponse && serverResponse.body + const bidResponses = []; + const bidsMap = bidRequest.bidsMap; + const priceType = bidRequest.data.pt; + + let errorMessage; + + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } + + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses); + }); + } + if (errorMessage) utils.logError(errorMessage); + return bidResponses; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: ADAPTER_SYNC_URL + }]; + } + } +} + +function _getBidFromResponse(respItem) { + if (!respItem) { + utils.logError(LOG_ERROR_MESS.emptySeatbid); + } else if (!respItem.bid) { + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + } else if (!respItem.bid[0]) { + utils.logError(LOG_ERROR_MESS.noBid); + } + return respItem && respItem.bid && respItem.bid[0]; +} + +function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { + if (!serverBid) return; + let errorMessage; + if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + awaitingBids.forEach(bid => { + const bidResponse = { + requestId: bid.bidId, // bid.bidderRequestId, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, // bid.bidId, + currency: 'USD', + netRevenue: priceType !== 'gross', + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid + }; + bidResponses.push(bidResponse); + }); + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } + if (errorMessage) { + utils.logError(errorMessage); + } +} + +registerBidder(spec); diff --git a/modules/gxoneBidAdapter.md b/modules/gxoneBidAdapter.md new file mode 100755 index 00000000000..3168d297da3 --- /dev/null +++ b/modules/gxoneBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +Module Name: GXOne Bidder Adapter +Module Type: Bidder Adapter +Maintainer: olivier@geronimo.co + +# Description + +Module that connects to GXOne demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "gxone", + params: { + uid: '2', + priceType: 'gross' // by default is 'net' + } + } + ] + },{ + code: 'test-div', + sizes: [[728, 90]], + bids: [ + { + bidder: "gxone", + params: { + uid: 9, + priceType: 'gross' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/gxoneBidAdapter_spec.js b/test/spec/modules/gxoneBidAdapter_spec.js new file mode 100644 index 00000000000..f34f4358490 --- /dev/null +++ b/test/spec/modules/gxoneBidAdapter_spec.js @@ -0,0 +1,293 @@ +import { expect } from 'chai'; +import { spec } from 'modules/gxoneBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('GXOne Adapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'gxone', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'uid': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + function parseRequest(url) { + const res = {}; + url.split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } + let bidRequests = [ + { + 'bidder': 'gxone', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'gxone', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'gxone', + 'params': { + 'uid': '6' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '42dbe3a7168a6a', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should attach valid params to the tag', () => { + const request = spec.buildRequests([bidRequests[0]]); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5'); + }); + + it('auids must not be duplicated', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5,6'); + }); + + it('pt parameter must be "gross" if params.priceType === "gross"', () => { + bidRequests[1].params.priceType = 'gross'; + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'gross'); + expect(payload).to.have.property('auids', '5,6'); + delete bidRequests[1].params.priceType; + }); + + it('pt parameter must be "net" or "gross"', () => { + bidRequests[1].params.priceType = 'some'; + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '5,6'); + delete bidRequests[1].params.priceType; + }); + }); + + describe('interpretResponse', () => { + const responses = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 6, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + undefined, + {'bid': [], 'seat': '1'}, + {'seat': '1'}, + ]; + + it('should get correct bid response', () => { + const bidRequests = [ + { + 'bidder': 'gxone', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should get correct multi bid response', () => { + const bidRequests = [ + { + 'bidder': 'gxone', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71a5b', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'gxone', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dff80cc4ee346', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'gxone', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '5703af74d0472a', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '300bfeb0d71a5b', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '5703af74d0472a', + 'cpm': 1.15, + 'creativeId': 4, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 5, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 2
', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('handles wrong and nobid responses', () => { + const bidRequests = [ + { + 'bidder': 'gxone', + 'params': { + 'uid': '6' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d7190gf', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'gxone', + 'params': { + 'uid': '7' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71321', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'gxone', + 'params': { + 'uid': '8' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '300bfeb0d7183bb', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + } + ]; + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + expect(result.length).to.equal(0); + }); + }); +}); From 27dca0fca2d746b929a4a25d25e9f4563efb9ad6 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Tue, 15 May 2018 09:03:53 -0700 Subject: [PATCH 0353/1594] PubMatic Adapter: Bug fix to read all bids from seatBid array (#2520) * Support multiple bids for same adSize * Add isArray check for seatbids --- modules/pubmaticBidAdapter.js | 47 +++++++++++--------- test/spec/modules/pubmaticBidAdapter_spec.js | 29 ++++++++++++ 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 14da2c45164..989ce180463 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -268,27 +268,32 @@ export const spec = { interpretResponse: (response, request) => { const bidResponses = []; try { - if (response.body && response.body.seatbid && response.body.seatbid[0] && response.body.seatbid[0].bid) { - response.body.seatbid[0].bid.forEach(bid => { - let newBid = { - requestId: bid.impid, - cpm: (parseFloat(bid.price) || 0).toFixed(2), - width: bid.w, - height: bid.h, - creativeId: bid.crid || bid.id, - dealId: bid.dealid, - currency: CURRENCY, - netRevenue: NET_REVENUE, - ttl: 300, - referrer: utils.getTopWindowUrl(), - ad: bid.adm - }; - - if (bid.ext && bid.ext.deal_channel) { - newBid['dealChannel'] = dealChannelValues[bid.ext.deal_channel] || null; - } - - bidResponses.push(newBid); + if (response.body && response.body.seatbid && utils.isArray(response.body.seatbid)) { + // Supporting multiple bid responses for same adSize + response.body.seatbid.forEach(seatbidder => { + seatbidder.bid && + utils.isArray(seatbidder.bid) && + seatbidder.bid.forEach(bid => { + let newBid = { + requestId: bid.impid, + cpm: (parseFloat(bid.price) || 0).toFixed(2), + width: bid.w, + height: bid.h, + creativeId: bid.crid || bid.id, + dealId: bid.dealid, + currency: CURRENCY, + netRevenue: NET_REVENUE, + ttl: 300, + referrer: utils.getTopWindowUrl(), + ad: bid.adm + }; + + if (bid.ext && bid.ext.deal_channel) { + newBid['dealChannel'] = dealChannelValues[bid.ext.deal_channel] || null; + } + + bidResponses.push(newBid); + }); }); } } catch (error) { diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 7ea10315a4e..09acbbe95a0 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -49,6 +49,18 @@ describe('PubMatic adapter', () => { 'deal_channel': 6 } }] + }, { + 'bid': [{ + 'id': '74858439-49D7-4169-BA5D-44A046315BEF', + 'impid': '22bddb28db77e', + 'price': 1.7, + 'adm': 'image3.pubmatic.com Layer based creative', + 'h': 250, + 'w': 300, + 'ext': { + 'deal_channel': 5 + } + }] }] } }; @@ -213,6 +225,22 @@ describe('PubMatic adapter', () => { expect(response[0].ttl).to.equal(300); expect(response[0].referrer).to.include(utils.getTopWindowUrl()); expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm); + + expect(response[1].requestId).to.equal(bidResponses.body.seatbid[1].bid[0].impid); + expect(response[1].cpm).to.equal((bidResponses.body.seatbid[1].bid[0].price).toFixed(2)); + expect(response[1].width).to.equal(bidResponses.body.seatbid[1].bid[0].w); + expect(response[1].height).to.equal(bidResponses.body.seatbid[1].bid[0].h); + if (bidResponses.body.seatbid[1].bid[0].crid) { + expect(response[1].creativeId).to.equal(bidResponses.body.seatbid[1].bid[0].crid); + } else { + expect(response[1].creativeId).to.equal(bidResponses.body.seatbid[1].bid[0].id); + } + expect(response[1].dealId).to.equal(bidResponses.body.seatbid[1].bid[0].dealid); + expect(response[1].currency).to.equal('USD'); + expect(response[1].netRevenue).to.equal(false); + expect(response[1].ttl).to.equal(300); + expect(response[1].referrer).to.include(utils.getTopWindowUrl()); + expect(response[1].ad).to.equal(bidResponses.body.seatbid[1].bid[0].adm); }); it('should check for dealChannel value selection', () => { @@ -220,6 +248,7 @@ describe('PubMatic adapter', () => { let response = spec.interpretResponse(bidResponses, request); expect(response).to.be.an('array').with.length.above(0); expect(response[0].dealChannel).to.equal('PMPG'); + expect(response[1].dealChannel).to.equal('PREF'); }); it('should check for unexpected dealChannel value selection', () => { From 7848901f14969da0da6b0a359fd8cd75e4aece02 Mon Sep 17 00:00:00 2001 From: Kit Westneat Date: Tue, 15 May 2018 12:33:22 -0400 Subject: [PATCH 0354/1594] fix getPreparedBidForAuction to look for renderer on correct bid (#2505) * add test for renderer on second bid in bidrequest * fix getPreparedBidForAuction to look for renderer on correct bid getPreparedBidForAuction was just looking on the first bid in the bidder request regardless of whether or not it was for the given ad unit. --- src/auction.js | 4 ++-- test/spec/auctionmanager_spec.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/auction.js b/src/auction.js index 8a23605bf0e..df87641b5fc 100644 --- a/src/auction.js +++ b/src/auction.js @@ -298,8 +298,8 @@ function getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}) { events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bidObject); // a publisher-defined renderer can be used to render bids - const adUnitRenderer = - bidRequest.bids && bidRequest.bids[0] && bidRequest.bids[0].renderer; + const bidReq = bidRequest.bids && bidRequest.bids.find(bid => bid.adUnitCode == adUnitCode); + const adUnitRenderer = bidReq && bidReq.renderer; if (adUnitRenderer && adUnitRenderer.url) { bidObject.renderer = Renderer.install({ url: adUnitRenderer.url }); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index ef50d2b6294..fff0150adb0 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -643,6 +643,35 @@ describe('auctionmanager.js', function () { const addedBid = auction.getBidsReceived().pop(); assert.equal(addedBid.renderer.url, 'renderer.js'); }); + + it('bid for a regular unit and a video unit', function() { + let renderer = { + url: 'renderer.js', + render: (bid) => bid + }; + + // make sure that if the renderer is only on the second ad unit, prebid + // still correctly uses it + let bid = mockBid(); + let bidRequests = [mockBidRequest(bid)]; + + bidRequests[0].bids[1] = Object.assign({ + renderer, + bidId: utils.getUniqueIdentifierStr() + }, bidRequests[0].bids[0]); + bidRequests[0].bids[0].adUnitCode = ADUNIT_CODE1; + + makeRequestsStub.returns(bidRequests); + + // this should correspond with the second bid in the bidReq because of the ad unit code + bid.mediaType = 'video-outstream'; + spec.interpretResponse.returns(bid); + + auction.callBids(); + + const addedBid = auction.getBidsReceived().find(bid => bid.adUnitCode == ADUNIT_CODE); + assert.equal(addedBid.renderer.url, 'renderer.js'); + }); }); describe('when auction timeout is 20', () => { From b746bf11c732e784e62913189fdfcfe72db8f7bd Mon Sep 17 00:00:00 2001 From: Yuriy Tyukhnin Date: Tue, 15 May 2018 18:48:20 +0200 Subject: [PATCH 0355/1594] Smart: GDPR support (#2528) * adding gdpr support * lint issues fix * more lints * taking the gdpr from bidderRequest * removing useless comma --- modules/smartadserverBidAdapter.js | 9 ++- .../modules/smartadserverBidAdapter_spec.js | 63 +++++++++++++++++-- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 7db4747927a..0767a51e545 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -22,9 +22,10 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {validBidRequests[]} - an array of bids + * @param {bidderRequest} - bidder request object * @return ServerRequest Info describing the request to the server. */ - buildRequests: function (validBidRequests) { + buildRequests: function (validBidRequests, bidderRequest) { // use bidderRequest.bids[] to get bidder-dependent request info // if your bidder supports multiple currencies, use config.getConfig(currency) @@ -53,6 +54,12 @@ export const spec = { bidId: bid.bidId, prebidVersion: '$prebid.version$' }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr_consent = bidderRequest.gdprConsent.consentString; + payload.gdpr = bidderRequest.gdprConsent.gdprApplies; // we're handling the undefined case server side + } + var payloadString = JSON.stringify(payload); return { method: 'POST', diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 82c2098f234..57c070e9748 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -99,6 +99,51 @@ describe('Smart bid adapter tests', () => { expect(requestContent).to.have.property('ckid').and.to.equal(42); }); + it('Verify build request with GDPR', () => { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + }, + consentManagement: { + cmp: 'iab', + consentRequired: true, + timeout: 1000, + allowAuctionWithoutConsent: true + } + }); + const request = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL, { + gdprConsent: { + consentString: 'BOKAVy4OKAVy4ABAB8AAAAAZ+A==', + gdprApplies: true + } + }); + const requestContent = JSON.parse(request[0].data); + expect(requestContent).to.have.property('gdpr').and.to.equal(true); + expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOKAVy4OKAVy4ABAB8AAAAAZ+A=='); + }); + + it('Verify build request with GDPR without gdprApplies', () => { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + }, + consentManagement: { + cmp: 'iab', + consentRequired: true, + timeout: 1000, + allowAuctionWithoutConsent: true + } + }); + const request = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL, { + gdprConsent: { + consentString: 'BOKAVy4OKAVy4ABAB8AAAAAZ+A==' + } + }); + const requestContent = JSON.parse(request[0].data); + expect(requestContent).to.not.have.property('gdpr'); + expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOKAVy4OKAVy4ABAB8AAAAAZ+A=='); + }); + it('Verify parse response', () => { const request = spec.buildRequests(DEFAULT_PARAMS); const bids = spec.interpretResponse(BID_RESPONSE, request[0]); @@ -116,7 +161,11 @@ describe('Smart bid adapter tests', () => { expect(bid.requestId).to.equal(DEFAULT_PARAMS[0].bidId); expect(bid.referrer).to.equal(utils.getTopWindowUrl()); - expect(function() { spec.interpretResponse(BID_RESPONSE, {data: 'invalid Json'}) }).to.not.throw(); + expect(function () { + spec.interpretResponse(BID_RESPONSE, { + data: 'invalid Json' + }) + }).to.not.throw(); }); it('Verifies bidder code', () => { @@ -187,15 +236,21 @@ describe('Smart bid adapter tests', () => { }); it('Verifies user sync', () => { - var syncs = spec.getUserSyncs({iframeEnabled: true}, [BID_RESPONSE]); + var syncs = spec.getUserSyncs({ + iframeEnabled: true + }, [BID_RESPONSE]); expect(syncs).to.have.lengthOf(1); expect(syncs[0].type).to.equal('iframe'); expect(syncs[0].url).to.equal('http://awesome.fake.csync.url'); - syncs = spec.getUserSyncs({iframeEnabled: false}, [BID_RESPONSE]); + syncs = spec.getUserSyncs({ + iframeEnabled: false + }, [BID_RESPONSE]); expect(syncs).to.have.lengthOf(0); - syncs = spec.getUserSyncs({iframeEnabled: true}, []); + syncs = spec.getUserSyncs({ + iframeEnabled: true + }, []); expect(syncs).to.have.lengthOf(0); }); }); From 07e711cd2c0ecefc9f68d3d7abe6e58ecde7d0e0 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 15 May 2018 12:54:36 -0400 Subject: [PATCH 0356/1594] add support for safeframe workflow and new utils method to read adunit sizes (#2523) --- modules/consentManagement.js | 34 ++++++++++- src/utils.js | 29 ++++++++++ test/spec/modules/consentManagement_spec.js | 64 +++++++++++++++++++-- test/spec/utils_spec.js | 28 +++++++++ 4 files changed, 147 insertions(+), 8 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index c7b6ac4df92..09eb938f314 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -37,8 +37,9 @@ const cmpCallMap = { * based on the appropriate result. * @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 {[objects]} adUnits used in the safeframe workflow to know what sizes to include in the $sf.ext.register call */ -function lookupIabConsent(cmpSuccess, cmpError) { +function lookupIabConsent(cmpSuccess, cmpError, adUnits) { let cmpCallbacks; // check if the CMP is located on the same window level as the prebid code. @@ -47,10 +48,37 @@ function lookupIabConsent(cmpSuccess, cmpError) { // in this case, use the IAB's iframe locator sample code (which is slightly cutomized) to try to find the CMP and use postMessage() to communicate with the CMP. if (utils.isFn(window.__cmp)) { window.__cmp('getVendorConsents', null, cmpSuccess); + } else if (inASafeFrame() && typeof window.$sf.ext.cmp === 'function') { + callCmpWhileInSafeFrame(); } else { callCmpWhileInIframe(); } + function inASafeFrame() { + return !!(window.$sf && window.$sf.ext); + } + + function callCmpWhileInSafeFrame() { + function sfCallback(msgName, data) { + if (msgName === 'cmpReturn') { + cmpSuccess(data.vendorConsents); + } + } + + // find sizes from adUnits object + 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('getVendorConsents'); + } + function callCmpWhileInIframe() { /** * START OF STOCK CODE FROM IAB 1.1 CMP SPEC @@ -134,6 +162,7 @@ export function requestBidsHook(config, fn) { args = arguments; nextFn = fn; haveExited = false; + let adUnits = config.adUnits || $$PREBID_GLOBAL$$.adUnits; // in case we already have consent (eg during bid refresh) if (consentData) { @@ -145,7 +174,7 @@ export function requestBidsHook(config, fn) { return nextFn.apply(context, args); } - cmpCallMap[userCMP].call(this, processCmpData, cmpFailed); + cmpCallMap[userCMP].call(this, processCmpData, cmpFailed, adUnits); // only let this code run if module is still active (ie if the callbacks used by CMPs haven't already finished) if (!haveExited) { @@ -245,6 +274,7 @@ function exitModule(errMsg) { */ export function resetConsentData() { consentData = undefined; + gdprDataHandler.setConsentData(null); } /** diff --git a/src/utils.js b/src/utils.js index cf977124dd1..c595101bae1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -107,6 +107,35 @@ exports.transformAdServerTargetingObj = function (targeting) { } }; +/** + * Read an adUnit object and return the sizes used in an [[728, 90]] format (even if they had [728, 90] defined) + * Preference is given to the `adUnit.mediaTypes.banner.sizes` object over the `adUnit.sizes` + * @param {object} adUnit one adUnit object from the normal list of adUnits + * @returns {array[array[number]]} array of arrays containing numeric sizes + */ +export function getAdUnitSizes(adUnit) { + if (!adUnit) { + return; + } + + let sizes = []; + if (adUnit.mediaTypes && adUnit.mediaTypes.banner && Array.isArray(adUnit.mediaTypes.banner.sizes)) { + let bannerSizes = adUnit.mediaTypes.banner.sizes; + if (Array.isArray(bannerSizes[0])) { + sizes = bannerSizes; + } else { + sizes.push(bannerSizes); + } + } else if (Array.isArray(adUnit.sizes)) { + if (Array.isArray(adUnit.sizes[0])) { + sizes = adUnit.sizes; + } else { + sizes.push(adUnit.sizes); + } + } + return sizes; +} + /** * Parse a GPT-Style general size Array like `[[300, 250]]` or `"300x250,970x90"` into an array of sizes `["300x250"]` or '['300x250', '970x90']' * @param {array[array|number]} sizeObj Input array or double array [300,250] or [[300,250], [728,90]] diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index 5974ac79324..a837a0cce8a 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -77,7 +77,7 @@ describe('consentManagement', function () { utils.logWarn.restore(); config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); - gdprDataHandler.consentData = null; + resetConsentData(); }); it('should return Warning message and return to hooked function', () => { @@ -113,7 +113,7 @@ describe('consentManagement', function () { $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); cmpStub.restore(); delete window.__cmp; - gdprDataHandler.consentData = null; + resetConsentData(); }); it('should bypass CMP and simply use previously stored consentData', () => { @@ -146,13 +146,66 @@ describe('consentManagement', function () { }); }); + describe('CMP workflow for safeframe page', () => { + let registerStub = sinon.stub(); + + beforeEach(() => { + didHookReturn = false; + window.$sf = { + ext: { + register: function() {}, + cmp: function() {} + } + }; + sinon.stub(utils, 'logError'); + sinon.stub(utils, 'logWarn'); + }); + + afterEach(() => { + delete window.$sf; + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + registerStub.restore(); + utils.logError.restore(); + utils.logWarn.restore(); + resetConsentData(); + }); + + it('should return the consent data from a safeframe callback', () => { + var testConsentData = { + data: { + msgName: 'cmpReturn', + vendorConsents: { + metadata: 'abc123def', + gdprApplies: true + } + } + }; + registerStub = sinon.stub(window.$sf.ext, 'register').callsFake((...args) => { + args[2](testConsentData.data.msgName, testConsentData.data); + }); + + setConfig(goodConfigWithAllowAuction); + debugger; //eslint-disable-line + requestBidsHook({adUnits: [{ sizes: [[300, 250]] }]}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + + sinon.assert.notCalled(utils.logWarn); + sinon.assert.notCalled(utils.logError); + expect(didHookReturn).to.be.true; + expect(consent.consentString).to.equal('abc123def'); + expect(consent.gdprApplies).to.be.true; + }); + }); + describe('CMP workflow for iframed page', () => { let eventStub = sinon.stub(); let cmpStub = sinon.stub(); beforeEach(() => { didHookReturn = false; - resetConsentData(); window.__cmp = function() {}; sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); @@ -166,7 +219,7 @@ describe('consentManagement', function () { delete window.__cmp; utils.logError.restore(); utils.logWarn.restore(); - gdprDataHandler.consentData = null; + resetConsentData(); }); it('should return the consent string from a postmessage + addEventListener response', () => { @@ -210,7 +263,6 @@ describe('consentManagement', function () { beforeEach(() => { didHookReturn = false; - resetConsentData(); sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); window.__cmp = function() {}; @@ -223,7 +275,7 @@ describe('consentManagement', function () { utils.logError.restore(); utils.logWarn.restore(); delete window.__cmp; - gdprDataHandler.consentData = null; + resetConsentData(); }); it('performs lookup check and stores consentData for a valid existing user', () => { diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 9218409c46c..6860605d343 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -789,4 +789,32 @@ describe('Utils', function () { expect(test2).to.equal(var2); }); }); + + describe('getAdUnitSizes', () => { + it('returns an empty response when adUnits is undefined', () => { + let sizes = utils.getAdUnitSizes(); + expect(sizes).to.be.undefined; + }); + + it('returns an empty array when invalid data is present in adUnit object', () => { + let sizes = utils.getAdUnitSizes({ sizes: 300 }); + expect(sizes).to.deep.equal([]); + }); + + it('retuns an array of arrays when reading from adUnit.sizes', () => { + let sizes = utils.getAdUnitSizes({ sizes: [300, 250] }); + expect(sizes).to.deep.equal([[300, 250]]); + + sizes = utils.getAdUnitSizes({ sizes: [[300, 250], [300, 600]] }); + expect(sizes).to.deep.equal([[300, 250], [300, 600]]); + }); + + it('returns an array of arrays when reading from adUnit.mediaTypes.banner.sizes', () => { + let sizes = utils.getAdUnitSizes({ mediaTypes: { banner: { sizes: [300, 250] } } }); + expect(sizes).to.deep.equal([[300, 250]]); + + sizes = utils.getAdUnitSizes({ mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] } } }); + expect(sizes).to.deep.equal([[300, 250], [300, 600]]); + }); + }); }); From e61024726b1b0e5523dd47f039702d7e475f6342 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 15 May 2018 14:33:39 -0400 Subject: [PATCH 0357/1594] GDPR - add consent information to PBS cookie_sync request (#2530) * add consent information to cookie_sync request * restructured unit tests and other minor changes --- modules/prebidServerBidAdapter.js | 62 +++++++++---- .../modules/prebidServerBidAdapter_spec.js | 93 +++++++++++++------ 2 files changed, 107 insertions(+), 48 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 2fd9c18eb06..58a95ea366e 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -96,36 +96,56 @@ function setS2sConfig(options) { } _s2sConfig = options; - if (options.syncEndpoint) { - queueSync(options.bidders); - } } getConfig('s2sConfig', ({s2sConfig}) => setS2sConfig(s2sConfig)); +/** + * resets the _synced variable back to false, primiarily used for testing purposes +*/ +export function resetSyncedStatus() { + _synced = false; +} + /** * @param {Array} bidderCodes list of bidders to request user syncs for. */ -function queueSync(bidderCodes) { +function queueSync(bidderCodes, gdprConsent) { if (_synced) { return; } _synced = true; - const payload = JSON.stringify({ + + const payload = { uuid: utils.generateUUID(), bidders: bidderCodes - }); - ajax(_s2sConfig.syncEndpoint, (response) => { - try { - response = JSON.parse(response); - response.bidder_status.forEach(bidder => doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder)); - } catch (e) { - utils.logError(e); + }; + + if (gdprConsent) { + // only populate gdpr field if we know CMP returned consent information (ie didn't timeout or have an error) + if (gdprConsent.consentString) { + payload.gdpr = (gdprConsent.gdprApplies) ? 1 : 0; } - }, - payload, { - contentType: 'text/plain', - withCredentials: true - }); + // attempt to populate gdpr_consent if we know gdprApplies or it may apply + if (gdprConsent.gdprApplies !== false) { + payload.gdpr_consent = gdprConsent.consentString; + } + } + const jsonPayload = JSON.stringify(payload); + + ajax(_s2sConfig.syncEndpoint, + (response) => { + try { + response = JSON.parse(response); + response.bidder_status.forEach(bidder => doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder)); + } catch (e) { + utils.logError(e); + } + }, + jsonPayload, + { + contentType: 'text/plain', + withCredentials: true + }); } /** @@ -348,9 +368,6 @@ const LEGACY_PROTOCOL = { if (result.status === 'OK' || result.status === 'no_cookie') { if (result.bidder_status) { result.bidder_status.forEach(bidder => { - if (bidder.no_cookie) { - doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder); - } if (bidder.error) { utils.logWarn(`Prebid Server returned error: '${bidder.error}' for ${bidder.bidder}`); } @@ -666,6 +683,11 @@ export function PrebidServer() { .reduce(utils.flatten) .filter(utils.uniques); + if (_s2sConfig && _s2sConfig.syncEndpoint) { + let consent = (Array.isArray(bidRequests) && bidRequests.length > 0) ? bidRequests[0].gdprConsent : undefined; + queueSync(_s2sConfig.bidders, consent); + } + const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, adUnitsWithSizes); const requestJson = JSON.stringify(request); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 857105c3b40..9c25e0439b3 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { PrebidServer as Adapter } from 'modules/prebidServerBidAdapter'; +import { PrebidServer as Adapter, resetSyncedStatus } from 'modules/prebidServerBidAdapter'; import adapterManager from 'src/adaptermanager'; import * as utils from 'src/utils'; import cookie from 'src/cookie'; @@ -375,6 +375,7 @@ describe('S2S Adapter', () => { requests = []; xhr.onCreate = request => requests.push(request); config.resetConfig(); + resetSyncedStatus(); }); afterEach(() => xhr.restore()); @@ -392,11 +393,11 @@ describe('S2S Adapter', () => { expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); }); - it('adds gdpr consent information to ortb2 request depending on module use', () => { + it('adds gdpr consent information to ortb2 request depending on presence of module', () => { let ortb2Config = utils.deepClone(CONFIG); ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' - let consentConfig = { consentManagement: { cmp: 'iab' }, s2sConfig: ortb2Config }; + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: ortb2Config }; config.setConfig(consentConfig); let gdprBidRequest = utils.deepClone(BID_REQUESTS); @@ -424,6 +425,67 @@ describe('S2S Adapter', () => { $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); }); + it('check gdpr info gets added into cookie_sync request: have consent data', () => { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); + + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + + gdprBidRequest[0].gdprConsent = { + consentString: 'abc123def', + gdprApplies: true + }; + + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.gdpr).is.equal(1); + expect(requestBid.gdpr_consent).is.equal('abc123def'); + }); + + it('check gdpr info gets added into cookie_sync request: have consent data but gdprApplies is false', () => { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); + + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: 'xyz789abcc', + gdprApplies: false + }; + + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.gdpr).is.equal(0); + expect(requestBid.gdpr_consent).is.undefined; + }); + + it('checks gdpr info gets added to cookie_sync request: consent data unknown', () => { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); + + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: undefined, + gdprApplies: undefined + }; + + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.gdpr).is.undefined; + expect(requestBid.gdpr_consent).is.undefined; + }); + it('sets invalid cacheMarkup value to 0', () => { const s2sConfig = Object.assign({}, CONFIG, { cacheMarkup: 999 @@ -794,31 +856,6 @@ describe('S2S Adapter', () => { expect(bid_request_passed).to.have.property('adId', '123'); }); - it('does cookie sync when no_cookie response', () => { - server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - - config.setConfig({s2sConfig: CONFIG}); - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - server.respond(); - - sinon.assert.calledOnce(utils.triggerPixel); - sinon.assert.calledWith(utils.triggerPixel, 'https://pixel.rubiconproject.com/exchange/sync.php?p=prebid'); - sinon.assert.calledOnce(utils.insertUserSyncIframe); - sinon.assert.calledWith(utils.insertUserSyncIframe, '//ads.pubmatic.com/AdServer/js/user_sync.html?predirect=https%3A%2F%2Fprebid.adnxs.com%2Fpbs%2Fv1%2Fsetuid%3Fbidder%3Dpubmatic%26uid%3D'); - }); - - it('logs error when no_cookie response is missing type or url', () => { - server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE_ERROR)); - - config.setConfig({s2sConfig: CONFIG}); - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - server.respond(); - - sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(utils.insertUserSyncIframe); - sinon.assert.calledTwice(utils.logError); - }); - it('does not call cookieSet cookie sync when no_cookie response && not opted in', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); From 103c015b3595383849184d8bb7b0f0be6289e5a1 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 15 May 2018 14:34:10 -0400 Subject: [PATCH 0358/1594] replace find reference with imported version (#2542) --- src/auction.js | 2 +- test/spec/auctionmanager_spec.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/auction.js b/src/auction.js index df87641b5fc..654b6dbb189 100644 --- a/src/auction.js +++ b/src/auction.js @@ -298,7 +298,7 @@ function getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}) { events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bidObject); // a publisher-defined renderer can be used to render bids - const bidReq = bidRequest.bids && bidRequest.bids.find(bid => bid.adUnitCode == adUnitCode); + const bidReq = bidRequest.bids && find(bidRequest.bids, bid => bid.adUnitCode == adUnitCode); const adUnitRenderer = bidReq && bidReq.renderer; if (adUnitRenderer && adUnitRenderer.url) { diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index fff0150adb0..6fbc48b3cdc 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -7,6 +7,7 @@ import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; import * as store from 'src/videoCache'; import * as ajaxLib from 'src/ajax'; +import find from 'core-js/library/fn/array/find'; const adloader = require('../../src/adloader'); var assert = require('assert'); @@ -669,7 +670,7 @@ describe('auctionmanager.js', function () { auction.callBids(); - const addedBid = auction.getBidsReceived().find(bid => bid.adUnitCode == ADUNIT_CODE); + const addedBid = find(auction.getBidsReceived(), bid => bid.adUnitCode == ADUNIT_CODE); assert.equal(addedBid.renderer.url, 'renderer.js'); }); }); From 849fdf184c19b44e54b502a8e0873f6102f553dc Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 15 May 2018 15:32:33 -0400 Subject: [PATCH 0359/1594] Prebid 1.11.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28cb310599e..e6f1e3a18b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.11.0-pre", + "version": "1.11.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4be6420ad1d641130dc87b797a5226910ddce62b Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 15 May 2018 15:47:25 -0400 Subject: [PATCH 0360/1594] increment prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e6f1e3a18b3..7e036004973 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.11.0", + "version": "1.12.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From ada85ba52693f80efb92bfc3dbd19e398eedbda9 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 16 May 2018 14:34:14 -0600 Subject: [PATCH 0361/1594] prebid server should fire BIDDER_DONE event (#2552) --- modules/prebidServerBidAdapter.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 58a95ea366e..5501eff30ca 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -2,12 +2,13 @@ import Adapter from 'src/adapter'; import bidfactory from 'src/bidfactory'; import * as utils from 'src/utils'; import { ajax } from 'src/ajax'; -import { STATUS, S2S } from 'src/constants'; +import { STATUS, S2S, EVENTS } from 'src/constants'; import { cookieSet } from 'src/cookie.js'; import adaptermanager from 'src/adaptermanager'; import { config } from 'src/config'; import { VIDEO } from 'src/mediaTypes'; import { isValid } from 'src/adapters/bidderFactory'; +import events from 'src/events'; import includes from 'core-js/library/fn/array/includes'; const getConfig = config.getConfig; @@ -718,6 +719,10 @@ export function PrebidServer() { } }); + bidRequests.forEach((bidRequest) => { + events.emit(EVENTS.BIDDER_DONE, bidRequest); + }); + if (result.status === 'no_cookie' && _s2sConfig.cookieSet && typeof _s2sConfig.cookieSetUrl === 'string') { // cookie sync cookieSet(_s2sConfig.cookieSetUrl); From 82fdbf64c5f8350855c32fa9809faee2e6e61874 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Wed, 16 May 2018 13:45:27 -0700 Subject: [PATCH 0362/1594] Support price granularity per mediaType (#2348) * Add config support for mediaTypePriceGranularity * Update to set default granularity to use config default * Formatting change, comment updated * Formatting change * Added test for mediaTypePriceGranularity enabled * Added test for mediaTypePriceGranularity video type * Changed double quotes to single in config_spec * Linting fixes for indentation and spacing --- src/auction.js | 14 +- src/config.js | 20 +++ test/spec/config_spec.js | 23 +++ test/spec/unit/pbjs_api_spec.js | 254 ++++++++++++++++++++++++++++++++ 4 files changed, 307 insertions(+), 4 deletions(-) diff --git a/src/auction.js b/src/auction.js index 654b6dbb189..8992f16218e 100644 --- a/src/auction.js +++ b/src/auction.js @@ -306,9 +306,12 @@ function getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}) { bidObject.renderer.setRender(adUnitRenderer.render); } + // Use the config value 'mediaTypeGranularity' if it has been defined for mediaType, else use 'customPriceBucket' + const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${bid.mediaType}`); + const priceStringsObj = getPriceBucketString( bidObject.cpm, - config.getConfig('customPriceBucket'), + (typeof mediaTypeGranularity === 'object') ? mediaTypeGranularity : config.getConfig('customPriceBucket'), config.getConfig('currency.granularityMultiplier') ); bidObject.pbLg = priceStringsObj.low; @@ -330,8 +333,11 @@ function getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}) { return bidObject; } -export function getStandardBidderSettings() { - let granularity = config.getConfig('priceGranularity'); +export function getStandardBidderSettings(mediaType) { + // Use the config value 'mediaTypeGranularity' if it has been set for mediaType, else use 'priceGranularity' + const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${mediaType}`); + const granularity = (typeof mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); + let bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; @@ -404,7 +410,7 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj) { // 1) set the keys from "standard" setting or from prebid defaults if (bidder_settings) { // initialize default if not set - const standardSettings = getStandardBidderSettings(); + const standardSettings = getStandardBidderSettings(custBidObj.mediaType); setKeys(keyValues, standardSettings, custBidObj); // 2) set keys from specific bidder setting override if they exist diff --git a/src/config.js b/src/config.js index ff68fc7bfff..c4be2cd552b 100644 --- a/src/config.js +++ b/src/config.js @@ -114,6 +114,26 @@ export function newConfig() { return this._customPriceBucket; }, + _mediaTypePriceGranularity: {}, + get mediaTypePriceGranularity() { + return this._mediaTypePriceGranularity; + }, + set mediaTypePriceGranularity(val) { + this._mediaTypePriceGranularity = Object.keys(val).reduce((aggregate, item) => { + if (validatePriceGranularity(val[item])) { + if (typeof val === 'string') { + aggregate[item] = (hasGranularity(val[item])) ? val[item] : this._priceGranularity; + } else if (typeof val === 'object') { + aggregate[item] = val[item]; + utils.logMessage(`Using custom price granularity for ${item}`); + } + } else { + utils.logWarn(`Invalid price granularity for media type: ${item}`); + } + return aggregate; + }, {}); + }, + _sendAllBids: DEFAULT_ENABLE_SEND_ALL_BIDS, get enableSendAllBids() { return this._sendAllBids; diff --git a/test/spec/config_spec.js b/test/spec/config_spec.js index 342319b472f..6b26d7da76a 100644 --- a/test/spec/config_spec.js +++ b/test/spec/config_spec.js @@ -135,6 +135,29 @@ describe('config API', () => { expect(getConfig('priceGranularity')).to.be.equal('low'); }); + it('set mediaTypePriceGranularity', () => { + const customPriceGranularity = { + 'buckets': [{ + 'min': 0, + 'max': 3, + 'increment': 0.01, + 'cap': true + }] + }; + setConfig({ + 'mediaTypePriceGranularity': { + 'banner': 'medium', + 'video': customPriceGranularity, + 'native': 'medium' + } + }); + + const configResult = getConfig('mediaTypePriceGranularity'); + expect(configResult.banner).to.be.equal('medium'); + expect(configResult.video).to.be.equal(customPriceGranularity); + expect(configResult.native).to.be.equal('medium'); + }); + it('sets priceGranularity and customPriceBucket', () => { const goodConfig = { 'buckets': [{ diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index ff7b261117c..4c72917d7a7 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -508,6 +508,260 @@ describe('Unit: Prebid Module', function () { }); }); + describe('getAdserverTargeting with `mediaTypePriceGranularity` set for media type', function() { + let currentPriceBucket; + let auction; + let ajaxStub; + let response; + let cbTimeout = 3000; + let auctionManagerInstance; + let targeting; + + const bannerResponse = { + 'version': '0.0.1', + 'tags': [{ + 'uuid': '4d0a6829338a07', + 'tag_id': 4799418, + 'auction_id': '2256922143947979797', + 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', + 'timeout_ms': 2500, + 'ads': [{ + 'content_source': 'rtb', + 'ad_type': 'banner', + 'buyer_member_id': 958, + 'creative_id': 33989846, + 'media_type_id': 1, + 'media_subtype_id': 1, + 'cpm': 1.99, + 'cpm_publisher_currency': 0.500000, + 'publisher_currency_code': '$', + 'client_initiated_ad_counting': true, + 'rtb': { + 'banner': { + 'width': 300, + 'height': 250, + 'content': '' + }, + 'trackers': [{ + 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] + }] + } + }] + }] + }; + const videoResponse = { + 'version': '0.0.1', + 'tags': [{ + 'uuid': '4d0a6829338a07', + 'tag_id': 4799418, + 'auction_id': '2256922143947979797', + 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', + 'timeout_ms': 2500, + 'ads': [{ + 'content_source': 'rtb', + 'ad_type': 'video', + 'buyer_member_id': 958, + 'creative_id': 33989846, + 'media_type_id': 1, + 'media_subtype_id': 1, + 'cpm': 1.99, + 'cpm_publisher_currency': 0.500000, + 'publisher_currency_code': '$', + 'client_initiated_ad_counting': true, + 'rtb': { + 'video': { + 'width': 300, + 'height': 250, + 'content': '' + }, + 'trackers': [{ + 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] + }] + } + }] + }] + }; + + const createAdUnit = (code, mediaTypes) => { + if (!mediaTypes) { + mediaTypes = ['banner']; + } else if (typeof mediaTypes === 'string') { + mediaTypes = [mediaTypes]; + } + + const adUnit = { + code: code, + sizes: [[300, 250], [300, 600]], + bids: [{ + bidder: 'appnexus', + params: { + placementId: '10433394' + } + }] + }; + + let _mediaTypes = {}; + if (mediaTypes.indexOf('banner') !== -1) { + _mediaTypes['banner'] = { + 'banner': {} + }; + } + if (mediaTypes.indexOf('video') !== -1) { + _mediaTypes['video'] = { + 'video': { + context: 'instream', + playerSize: [300, 250] + } + }; + } + if (mediaTypes.indexOf('native') !== -1) { + _mediaTypes['native'] = { + 'native': {} + }; + } + + if (Object.keys(_mediaTypes).length > 0) { + adUnit['mediaTypes'] = _mediaTypes; + // if video type, add video to every bid.param object + if (_mediaTypes.video) { + adUnit.bids.forEach(bid => { + bid.params['video'] = { + width: 300, + height: 250, + vastUrl: '', + ttl: 3600 + }; + }); + } + } + return adUnit; + } + const initTestConfig = (data) => { + $$PREBID_GLOBAL$$.bidderSettings = {}; + + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(function() { + return function(url, callback) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callback.success(JSON.stringify(response), { getResponseHeader: fakeResponse }); + } + }); + auctionManagerInstance = newAuctionManager(); + targeting = newTargeting(auctionManagerInstance) + + configObj.setConfig({ + 'priceGranularity': { + 'buckets': [ + { 'precision': 2, 'min': 0, 'max': 5, 'increment': 0.01 }, + { 'precision': 2, 'min': 5, 'max': 8, 'increment': 0.05 }, + { 'precision': 2, 'min': 8, 'max': 20, 'increment': 0.5 }, + { 'precision': 2, 'min': 20, 'max': 25, 'increment': 1 } + ] + }, + 'mediaTypePriceGranularity': { + 'banner': { + 'buckets': [ + { 'precision': 2, 'min': 0, 'max': 5, 'increment': 0.25 }, + { 'precision': 2, 'min': 6, 'max': 20, 'increment': 0.5 }, + { 'precision': 2, 'min': 21, 'max': 100, 'increment': 1 } + ] + }, + 'video': 'low', + 'native': 'high' + } + }); + + auction = auctionManagerInstance.createAuction({ + adUnits: data.adUnits, + adUnitCodes: data.adUnitCodes + }); + }; + + before(() => { + currentPriceBucket = configObj.getConfig('priceGranularity'); + 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 + ], + [ + 300, + 600 + ] + ], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }])); + }); + + after(() => { + configObj.setConfig({ priceGranularity: currentPriceBucket }); + adaptermanager.makeBidRequests.restore(); + }) + + afterEach(() => { + ajaxStub.restore(); + }); + + it('should get correct hb_pb with cpm between 0 - 5', () => { + initTestConfig({ + adUnits: [createAdUnit('div-gpt-ad-1460505748561-0')], + adUnitCodes: ['div-gpt-ad-1460505748561-0'] + }); + + response = bannerResponse; + response.tags[0].ads[0].cpm = 3.4288; + + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('3.25'); + }); + + it('should get correct hb_pb with cpm between 21 - 100', () => { + initTestConfig({ + adUnits: [createAdUnit('div-gpt-ad-1460505748561-0')], + adUnitCodes: ['div-gpt-ad-1460505748561-0'] + }); + + response = bannerResponse; + response.tags[0].ads[0].cpm = 43.4288; + + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('43.00'); + }); + + it('should only apply price granularity if bid media type matches', () => { + initTestConfig({ + adUnits: [ createAdUnit('div-gpt-ad-1460505748561-0', 'video') ], + adUnitCodes: ['div-gpt-ad-1460505748561-0'] + }); + + response = videoResponse; + response.tags[0].ads[0].cpm = 3.4288; + + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('3.00'); + }); + }); + describe('getBidResponses', function () { it('should return expected bid responses when not passed an adunitCode', function () { var result = $$PREBID_GLOBAL$$.getBidResponses(); From 6e3c27d82ecdf638d12417ed223f238200bcd4a5 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 17 May 2018 09:13:21 -0600 Subject: [PATCH 0363/1594] removed an errant debugger statement (#2557) --- test/spec/modules/consentManagement_spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index a837a0cce8a..7607dfd2e4b 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -186,7 +186,6 @@ describe('consentManagement', function () { }); setConfig(goodConfigWithAllowAuction); - debugger; //eslint-disable-line requestBidsHook({adUnits: [{ sizes: [[300, 250]] }]}, () => { didHookReturn = true; }); From 10f923e6da9b5c406419ac4eade6da7d3db2a22c Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Thu, 17 May 2018 11:19:06 -0400 Subject: [PATCH 0364/1594] Added Release Process (#2451) * Add release steps * Remove single test command * Updated some steps after feedback * Fixed env key * some more polishing --- README.md | 5 --- RELEASE_SCHEDULE.md | 87 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1ec83859b48..946d6755774 100644 --- a/README.md +++ b/README.md @@ -106,11 +106,6 @@ To run the unit tests: ```bash gulp test ``` -To run tests for a single file: - -```bash -gulp test --file "path/to/spec/file.js" -``` To generate and view the code coverage reports: diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index f1e930b98b6..efdc45f7f9f 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -1,4 +1,9 @@ -# Release Schedule +**Table of Contents** +- [Release Schedule](#release-schedule) +- [Release Process](#release-process) +- [FAQs](#faqs) + +## Release Schedule We push a new release of Prebid.js every other week on Tuesday. During the adoption phase for 1.x, we are releasing updates for 1.x and 0.x at the same time. @@ -9,7 +14,85 @@ You can determine what is in a given build using the [releases page](https://git Announcements regarding releases will be made to the #headerbidding-dev channel in subredditadops.slack.com. -# FAQs +## Release Process + +1. Make Sure all browserstack tests are passing. On PR merge to master travis will run unit tests on browserstack. Checking the last travis build [here](https://travis-ci.org/prebid/Prebid.js/branches) for master branch will show you detailed results. + + In case of failure do following, + - Try to fix the failing tests. + - If you are not able to fix tests in time. Skip the test, create issue and tag contributor. + + #### How to run tests in browserstack + + Set the environment variables. You may want to add these to your `~/.bashrc` for convenience. + + ``` + export BROWSERSTACK_USERNAME="my browserstack username" + export BROWSERSTACK_ACCESS_KEY="my browserstack access key" + ``` + + ``` + gulp test --browserstack >> prebid_test.log + + vim prebid_test.log // Will show the test results + ``` + + +2. Prepare Prebid Code + + Update the package.json version to become the current release. Then commit your changes. + + ``` + git commit -m "Prebid 1.x.x Release" + git push + ``` + +3. Verify Release + + Make sure your there are no more merges to master branch. Prebid code is clean and up to date. + +4. Create a GitHub release + + Edit the most recent [release notes](https://github.com/prebid/Prebid.js/releases) draft and make sure the correct tag is in the dropdown. Click `Publish`. GitHub will create release tag. + + Pull these changes locally by running command + ``` + git pull + ``` + + and verify the tag. + +5. Update coveralls + + 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. + +6. Distribute the code + + 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. + +7. Post Release Steps + + Update the version + Manually edit Prebid's package.json to become "1.x.x-pre" (using the values for the next release). Then commit your changes. + ``` + git commit -m "Increment pre version" + git push + ``` + + +## FAQs **1. Is there flexibility in the 2-week schedule?** From b9ee826c0f5339e222c7db054a38127c10e01267 Mon Sep 17 00:00:00 2001 From: brainymisio Date: Sat, 19 May 2018 00:41:24 +0900 Subject: [PATCH 0365/1594] Fix endpoint for brainy (#2534) * Fix endpoint * Correction corresponding to CORS * Revert "Correction corresponding to CORS" This reverts commit 16832915b119595c996bd0a66a1fbb4de2276c4d. --- modules/brainyBidAdapter.js | 2 +- test/spec/modules/brainyBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/brainyBidAdapter.js b/modules/brainyBidAdapter.js index e8beb20573f..3274b10b97d 100644 --- a/modules/brainyBidAdapter.js +++ b/modules/brainyBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import { BANNER } from 'src/mediaTypes'; const BIDDER_CODE = 'brainy'; -const BASE_URL = '//proparm.co.jp/ssp/p/pbjs'; +const BASE_URL = '//proparm.jp/ssp/p/pbjs'; /** * Check if the browser supports flash diff --git a/test/spec/modules/brainyBidAdapter_spec.js b/test/spec/modules/brainyBidAdapter_spec.js index 4f619323d7d..8dc74435263 100644 --- a/test/spec/modules/brainyBidAdapter_spec.js +++ b/test/spec/modules/brainyBidAdapter_spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import { spec } from 'modules/brainyBidAdapter'; -const URL = '//proparm.co.jp/ssp/p/pbjs'; +const URL = '//proparm.jp/ssp/p/pbjs'; const BIDDER_CODE = 'brainy'; const validBidReq = { From ce367d1e55b43f3c032f15df4082ccb3e9a6e531 Mon Sep 17 00:00:00 2001 From: John Salis Date: Fri, 18 May 2018 12:51:15 -0400 Subject: [PATCH 0366/1594] Add multi-format ad unit support to Beachfront adapter (#2541) * Add support for multi-format ad units * add test case * parse bid sizes for each bid format * fix duplicate import --- modules/beachfrontBidAdapter.js | 78 ++++++++---- modules/beachfrontBidAdapter.md | 34 ++++++ .../spec/modules/beachfrontBidAdapter_spec.js | 113 ++++++++++++++++++ 3 files changed, 200 insertions(+), 25 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 4e528896e72..8f8288011e6 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -21,17 +21,17 @@ export const spec = { supportedMediaTypes: [ VIDEO, BANNER ], isBidRequestValid(bid) { - return !!(bid && bid.params && bid.params.appId && bid.params.bidfloor); + return !!(isVideoBidValid(bid) || isBannerBidValid(bid)); }, buildRequests(bids, bidderRequest) { let requests = []; - let videoBids = bids.filter(bid => isVideoBid(bid)); - let bannerBids = bids.filter(bid => !isVideoBid(bid)); + let videoBids = bids.filter(bid => isVideoBidValid(bid)); + let bannerBids = bids.filter(bid => isBannerBidValid(bid)); videoBids.forEach(bid => { requests.push({ method: 'POST', - url: VIDEO_ENDPOINT + bid.params.appId, + url: VIDEO_ENDPOINT + getVideoBidParam(bid, 'appId'), data: createVideoRequestData(bid, bidderRequest), bidRequest: bid }); @@ -55,15 +55,16 @@ export const spec = { utils.logWarn(`No valid video bids from ${spec.code} bidder`); return []; } - let size = getFirstSize(bidRequest); + let sizes = getVideoSizes(bidRequest); + let firstSize = getFirstSize(sizes); let context = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); return { requestId: bidRequest.bidId, bidderCode: spec.code, vastUrl: response.url, cpm: response.bidPrice, - width: size.w, - height: size.h, + width: firstSize.w, + height: firstSize.h, creativeId: response.cmpId, renderer: context === OUTSTREAM ? createRenderer(bidRequest) : null, mediaType: VIDEO, @@ -120,10 +121,11 @@ function outstreamRender(bid) { }); } -function getSizes(bid) { - let sizes = (isVideoBid(bid) - ? utils.deepAccess(bid, 'mediaTypes.video.playerSize') - : utils.deepAccess(bid, 'mediaTypes.banner.sizes')) || bid.sizes; +function getFirstSize(sizes) { + return (sizes && sizes.length) ? sizes[0] : { w: undefined, h: undefined }; +} + +function parseSizes(sizes) { return utils.parseSizesInput(sizes).map(size => { let [ width, height ] = size.split('x'); return { @@ -133,9 +135,12 @@ function getSizes(bid) { }); } -function getFirstSize(bid) { - let sizes = getSizes(bid); - return sizes.length ? sizes[0] : { w: undefined, h: undefined }; +function getVideoSizes(bid) { + return parseSizes(utils.deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes); +} + +function getBannerSizes(bid) { + return parseSizes(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes); } function getOsVersion() { @@ -172,10 +177,30 @@ function getDoNotTrack() { } function isVideoBid(bid) { - return bid.mediaTypes && bid.mediaTypes.video; + return utils.deepAccess(bid, 'mediaTypes.video'); +} + +function isBannerBid(bid) { + return utils.deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid); +} + +function getVideoBidParam(bid, key) { + return utils.deepAccess(bid, 'params.video.' + key) || utils.deepAccess(bid, 'params.' + key); +} + +function getBannerBidParam(bid, key) { + return utils.deepAccess(bid, 'params.banner.' + key) || utils.deepAccess(bid, 'params.' + key); +} + +function isVideoBidValid(bid) { + return isVideoBid(bid) && getVideoBidParam(bid, 'appId') && getVideoBidParam(bid, 'bidfloor'); +} + +function isBannerBidValid(bid) { + return isBannerBid(bid) && getBannerBidParam(bid, 'appId') && getBannerBidParam(bid, 'bidfloor'); } -function getVideoParams(bid) { +function getVideoTargetingParams(bid) { return Object.keys(Object(bid.params.video)) .filter(param => includes(VIDEO_TARGETING, param)) .reduce((obj, param) => { @@ -185,21 +210,24 @@ function getVideoParams(bid) { } function createVideoRequestData(bid, bidderRequest) { - let size = getFirstSize(bid); - let video = getVideoParams(bid); + let sizes = getVideoSizes(bid); + let firstSize = getFirstSize(sizes); + let video = getVideoTargetingParams(bid); + let appId = getVideoBidParam(bid, 'appId'); + let bidfloor = getVideoBidParam(bid, 'bidfloor'); let topLocation = utils.getTopWindowLocation(); let payload = { isPrebid: true, - appId: bid.params.appId, + appId: appId, domain: document.location.hostname, id: utils.getUniqueIdentifierStr(), imp: [{ video: Object.assign({ - w: size.w, - h: size.h, + w: firstSize.w, + h: firstSize.h, mimes: DEFAULT_MIMES }, video), - bidfloor: bid.params.bidfloor, + bidfloor: bidfloor, secure: topLocation.protocol === 'https:' ? 1 : 0 }], site: { @@ -234,9 +262,9 @@ function createBannerRequestData(bids, bidderRequest) { let slots = bids.map(bid => { return { slot: bid.adUnitCode, - id: bid.params.appId, - bidfloor: bid.params.bidfloor, - sizes: getSizes(bid) + id: getBannerBidParam(bid, 'appId'), + bidfloor: getBannerBidParam(bid, 'bidfloor'), + sizes: getBannerSizes(bid) }; }); let payload = { diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index 5804cb8dc0d..90c726633b8 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -51,4 +51,38 @@ Module that connects to Beachfront's demand sources ] } ]; +``` + +# Multi-Format Ad Unit Example +```javascript + var adUnits = [ + { + code: 'test-video-banner', + mediaTypes: { + video: { + context: 'instream', + playerSize: [ 640, 360 ] + }, + banner: { + sizes: [ 300, 250 ] + } + }, + bids: [ + { + bidder: 'beachfront', + params: { + video: { + bidfloor: 0.01, + appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76', + mimes: [ 'video/mp4', 'application/javascript' ] + }, + banner: { + bidfloor: 0.01, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + } + } + } + ] + } + ]; ``` \ No newline at end of file diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 65bc0818a6c..a3ecccba6cb 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -63,6 +63,64 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid()).to.equal(false); expect(spec.isBidRequestValid({})).to.equal(false); }); + + describe('for multi-format bids', () => { + it('should return true when the required params are passed for video', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: {} + }; + bidRequest.params = { + video: { + bidfloor: 1.00, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + } + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return false when the required params are missing for video', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: {} + }; + bidRequest.params = { + banner: { + bidfloor: 1.00, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + } + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + + it('should return true when the required params are passed for banner', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + banner: {} + }; + bidRequest.params = { + banner: { + bidfloor: 1.00, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + } + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return false when the required params are missing for banner', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + banner: {} + }; + bidRequest.params = { + video: { + bidfloor: 1.00, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + } + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + }); }); describe('spec.buildRequests', () => { @@ -298,6 +356,61 @@ describe('BeachfrontAdapter', () => { expect(data.gdprConsent).to.equal(consentString); }); }); + + describe('for multi-format bids', () => { + it('should create a POST request for each bid format', () => { + const width = 300; + const height = 250; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: { + playerSize: [ width, height ] + }, + banner: { + sizes: [ width, height ] + } + }; + bidRequest.params = { + video: { + bidfloor: 2.00, + appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' + }, + banner: { + bidfloor: 1.00, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + } + }; + const requests = spec.buildRequests([ bidRequest ]); + expect(requests.length).to.equal(2); + expect(requests[0].url).to.contain(VIDEO_ENDPOINT); + expect(requests[1].url).to.contain(BANNER_ENDPOINT); + }); + + it('must parse bid sizes for each bid format', () => { + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: { + playerSize: [ 640, 360 ] + }, + banner: { + sizes: [ 300, 250 ] + } + }; + bidRequest.params = { + video: { + bidfloor: 2.00, + appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' + }, + banner: { + bidfloor: 1.00, + appId: '3b16770b-17af-4d22-daff-9606bdf2c9c3' + } + }; + const requests = spec.buildRequests([ bidRequest ]); + expect(requests[0].data.imp[0].video).to.deep.contain({ w: 640, h: 360 }); + expect(requests[1].data.slots[0].sizes).to.deep.equal([{ w: 300, h: 250 }]); + }); + }); }); describe('spec.interpretResponse', () => { From af28478d3bad1b6b2dd395edf7b2d28a478c0aca Mon Sep 17 00:00:00 2001 From: Jeremy Hernandez Date: Mon, 21 May 2018 23:21:38 +0200 Subject: [PATCH 0367/1594] feat(adyoulikeAdapter): adapt adapter to gdpr (#2518) * feat(adyoulikeAdapter): adapt adapter to gdpr * fix(constentRequired): prevent undefined --- modules/adyoulikeBidAdapter.js | 16 ++++++++++---- test/spec/modules/adyoulikeBidAdapter_spec.js | 22 +++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index 263f3fa09e9..a61719fe495 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -27,14 +27,14 @@ export const spec = { /** * Make a server request from the list of BidRequests. * - * @param {bidderRequest} - bidderRequest.bids[] is an array of AdUnits and bids + * @param {bidRequests} - bidRequests.bids[] is an array of AdUnits and bids * @return ServerRequest Info describing the request to the server. */ - buildRequests: function (bidderRequest) { - let dcHostname = getHostname(bidderRequest); + buildRequests: function (bidRequests, bidderRequest) { + let dcHostname = getHostname(bidRequests); const payload = { Version: VERSION, - Bids: bidderRequest.reduce((accumulator, bid) => { + Bids: bidRequests.reduce((accumulator, bid) => { let size = getSize(bid.sizes); accumulator[bid.bidId] = {}; accumulator[bid.bidId].PlacementID = bid.params.placement; @@ -45,6 +45,14 @@ export const spec = { }, {}), PageRefreshed: getPageRefreshed() }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdprConsent = { + consentString: bidderRequest.gdprConsent.consentString, + consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true + }; + } + const data = JSON.stringify(payload); const options = { withCredentials: false diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js index cb9126619f2..d7a5b1a87b7 100644 --- a/test/spec/modules/adyoulikeBidAdapter_spec.js +++ b/test/spec/modules/adyoulikeBidAdapter_spec.js @@ -190,6 +190,28 @@ describe('Adyoulike Adapter', () => { canonicalQuery.restore(); }); + it('should add gdpr consent information to the request', () => { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'adyoulike', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + bidderRequest.bids = bidRequestWithSinglePlacement; + + const request = spec.buildRequests(bidRequestWithSinglePlacement, bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.gdprConsent).to.exist; + expect(payload.gdprConsent.consentString).to.exist.and.to.equal(consentString); + expect(payload.gdprConsent.consentRequired).to.exist.and.to.be.true; + }); + it('sends bid request to endpoint with single placement', () => { const request = spec.buildRequests(bidRequestWithSinglePlacement); const payload = JSON.parse(request.data); From 2eb32fe68257ef3cb84421bac12f2127977afc7b Mon Sep 17 00:00:00 2001 From: Preston Skupinski Date: Mon, 21 May 2018 16:43:48 -0500 Subject: [PATCH 0368/1594] LockerDome adapter GDPR support (#2572) --- modules/lockerdomeBidAdapter.js | 10 +++++++++- test/spec/modules/lockerdomeBidAdapter_spec.js | 16 +++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/modules/lockerdomeBidAdapter.js b/modules/lockerdomeBidAdapter.js index dd63d00b356..43c8a15c37b 100644 --- a/modules/lockerdomeBidAdapter.js +++ b/modules/lockerdomeBidAdapter.js @@ -8,7 +8,7 @@ export const spec = { isBidRequestValid: function(bid) { return !!bid.params.adUnitId; }, - buildRequests: function(bidRequests) { + buildRequests: function(bidRequests, bidderRequest) { const adUnitBidRequests = bidRequests.map(function (bid) { return { requestId: bid.bidId, @@ -21,6 +21,14 @@ export const spec = { url: utils.getTopWindowLocation().href, referrer: utils.getTopWindowReferrer() }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr = { + applies: bidderRequest.gdprConsent.gdprApplies, + consent: bidderRequest.gdprConsent.consentString + }; + } + const payloadString = JSON.stringify(payload); return { method: 'POST', diff --git a/test/spec/modules/lockerdomeBidAdapter_spec.js b/test/spec/modules/lockerdomeBidAdapter_spec.js index 1ad26af24c1..84f0dd43e72 100644 --- a/test/spec/modules/lockerdomeBidAdapter_spec.js +++ b/test/spec/modules/lockerdomeBidAdapter_spec.js @@ -53,7 +53,6 @@ describe('LockerDomeAdapter', () => { it('should generate a valid single POST request for multiple bid requests', () => { const request = spec.buildRequests(bidRequests); expect(request.method).to.equal('POST'); - // TODO: Update to production URL expect(request.url).to.equal('https://lockerdome.com/ladbid/prebid'); expect(request.data).to.exist; @@ -77,6 +76,21 @@ describe('LockerDomeAdapter', () => { expect(bids[1].sizes[0][0]).to.equal(300); expect(bids[1].sizes[0][1]).to.equal(600); }); + + it('should add GDPR data to request if available', () => { + const bidderRequest = { + gdprConsent: { + consentString: 'AAABBB', + gdprApplies: true + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest); + const requestData = JSON.parse(request.data); + + expect(requestData.gdpr).to.be.an('object'); + expect(requestData.gdpr).to.have.property('applies', true); + expect(requestData.gdpr).to.have.property('consent', 'AAABBB'); + }); }); describe('interpretResponse', () => { From 71503a77bc1235c73327c31d5cd8fd19beff0bb0 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Mon, 21 May 2018 14:54:00 -0700 Subject: [PATCH 0369/1594] Conversant GDPR support (#2571) * Conversant adapter GDPR support * Change conversant adapter to use new domain --- modules/conversantBidAdapter.js | 49 ++++++++++--------- .../spec/modules/conversantBidAdapter_spec.js | 40 ++++++++++----- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index 075a8abd5bb..b5171b6c9ad 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -3,9 +3,8 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import { BANNER, VIDEO } from 'src/mediaTypes'; const BIDDER_CODE = 'conversant'; -const URL = '//media.msg.dotomi.com/s2s/header/24'; -const SYNC_URL = '//media.msg.dotomi.com/w/user.sync'; -const VERSION = '2.2.2'; +const URL = '//web.hb.ad.cpe.dotomi.com/s2s/header/24'; +const VERSION = '2.2.3'; export const spec = { code: BIDDER_CODE, @@ -48,7 +47,7 @@ export const spec = { * @param {BidRequest[]} validBidRequests - an array of bids * @return {ServerRequest} Info describing the request to the server. */ - buildRequests: function(validBidRequests) { + buildRequests: function(validBidRequests, bidderRequest) { const loc = utils.getTopWindowLocation(); const page = loc.href; const isPageSecure = (loc.protocol === 'https:') ? 1 : 0; @@ -115,12 +114,29 @@ export const spec = { at: 1 }; + let userExt = {}; + + // Add GDPR flag and consent string + if (bidderRequest && bidderRequest.gdprConsent) { + userExt.consent = bidderRequest.gdprConsent.consentString; + + if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { + payload.regs = { + ext: { + gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) + } + }; + } + } + + // Add common id if available if (pubcid) { - payload.user = { - ext: { - fpc: pubcid - } - }; + userExt.fpc = pubcid; + } + + // Only add the user object if it's not empty + if (!utils.isEmpty(userExt)) { + payload.user = {ext: userExt}; } return { @@ -180,21 +196,6 @@ export const spec = { } return bidResponses; - }, - - /** - * Return use sync info - * - * @param {SyncOptions} syncOptions - Info about usersyncs that the adapter should obey - * @return {UserSync} Adapter sync type and url - */ - getUserSyncs: function(syncOptions) { - if (syncOptions.pixelEnabled) { - return [{ - type: 'image', - url: SYNC_URL - }]; - } } }; diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index a8e1b41d966..91b3ed6892b 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -120,17 +120,6 @@ describe('Conversant adapter tests', function() { expect(spec.supportedMediaTypes[1]).to.equal('video'); }); - it('Verify user syncs', function() { - expect(spec.getUserSyncs({})).to.be.undefined; - expect(spec.getUserSyncs({iframeEnabled: true})).to.be.undefined; - expect(spec.getUserSyncs({pixelEnabled: false})).to.be.undefined; - - const syncs = spec.getUserSyncs({pixelEnabled: true}); - expect(syncs).to.be.an('array').with.lengthOf(1); - expect(syncs[0].type).to.equal('image'); - expect(syncs[0].url).to.equal('//media.msg.dotomi.com/w/user.sync'); - }); - it('Verify isBidRequestValid', function() { expect(spec.isBidRequestValid({})).to.be.false; expect(spec.isBidRequestValid({params: {}})).to.be.false; @@ -155,7 +144,7 @@ describe('Conversant adapter tests', function() { it('Verify buildRequest', function() { const request = spec.buildRequests(bidRequests); expect(request.method).to.equal('POST'); - expect(request.url).to.equal('//media.msg.dotomi.com/s2s/header/24'); + expect(request.url).to.equal('//web.hb.ad.cpe.dotomi.com/s2s/header/24'); const payload = request.data; expect(payload).to.have.property('id', 'req000'); @@ -294,4 +283,31 @@ describe('Conversant adapter tests', function() { const payload = spec.buildRequests(requests).data; expect(payload).to.have.deep.property('user.ext.fpc', 12345); }); + + it('Verify GDPR bid request', function() { + // add gdpr info + const bidRequest = { + gdprConsent: { + consentString: 'BOJObISOJObISAABAAENAA4AAAAAoAAA', + gdprApplies: true + } + }; + + const payload = spec.buildRequests(bidRequests, bidRequest).data; + expect(payload).to.have.deep.property('user.ext.consent', 'BOJObISOJObISAABAAENAA4AAAAAoAAA'); + expect(payload).to.have.deep.property('regs.ext.gdpr', 1); + }); + + it('Verify GDPR bid request without gdprApplies', function() { + // add gdpr info + const bidRequest = { + gdprConsent: { + consentString: '' + } + }; + + const payload = spec.buildRequests(bidRequests, bidRequest).data; + expect(payload).to.have.deep.property('user.ext.consent', ''); + expect(payload).to.not.have.deep.property('regs.ext.gdpr'); + }); }) From 18b9fbc6d365e4785df3dcb9018b5d9875a24df1 Mon Sep 17 00:00:00 2001 From: PWyrembak Date: Tue, 22 May 2018 18:28:35 +0300 Subject: [PATCH 0370/1594] Update TrustX Bid Adapter to support gdpr (#2565) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Add support of gdpr to Trustx Bid Adapter --- modules/trustxBidAdapter.js | 12 ++++++++++- test/spec/modules/trustxBidAdapter_spec.js | 24 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index ec1f0247455..3688aa3b976 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -30,9 +30,10 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {BidRequest[]} validBidRequests - an array of bids + * @param {bidderRequest} - bidder request object * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(validBidRequests) { + buildRequests: function(validBidRequests, bidderRequest) { const auids = []; const bidsMap = {}; const bids = validBidRequests || []; @@ -59,6 +60,15 @@ export const spec = { r: reqId }; + if (bidderRequest && 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; + } + return { method: 'GET', url: ENDPOINT_URL, diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index 6149545d59f..75405850d7a 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -118,6 +118,30 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('r', '22edbae2733bf6'); delete bidRequests[1].params.priceType; }); + + it('if gdprConsent is present payload must have gdpr params', () => { + 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', () => { + 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', () => { + 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); + }); }); describe('interpretResponse', () => { From 60cabb7841fcd02bea4dd900763b7eabb512e8a9 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 22 May 2018 11:35:06 -0400 Subject: [PATCH 0371/1594] execute bidsBackHandler when auction is canceled by consent module (#2555) * add support to execute bidsBackHandler when auction is canceled by consent module * rename config variable --- modules/consentManagement.js | 13 ++++++++++--- test/spec/modules/consentManagement_spec.js | 4 +++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index 09eb938f314..2a47bb25899 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -22,6 +22,7 @@ let consentData; let context; let args; let nextFn; +let bidsBackHandler; let timer; let haveExited; @@ -154,15 +155,16 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { * user's encoded consent string from the supported CMP. Once obtained, the module will store this * data as part of a gdprConsent object which gets transferred to adaptermanager's gdprDataHandler object. * This information is later added into the bidRequest object for any supported adapters to read/pass along to their system. - * @param {object} config required; This is the same param that's used in pbjs.requestBids. + * @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(config, fn) { +export function requestBidsHook(reqBidsConfigObj, fn) { context = this; args = arguments; nextFn = fn; haveExited = false; - let adUnits = config.adUnits || $$PREBID_GLOBAL$$.adUnits; + let adUnits = reqBidsConfigObj.adUnits || $$PREBID_GLOBAL$$.adUnits; + bidsBackHandler = reqBidsConfigObj.bidsBackHandler; // in case we already have consent (eg during bid refresh) if (consentData) { @@ -262,6 +264,11 @@ function exitModule(errMsg) { nextFn.apply(context, args); } else { utils.logError(errMsg + ' Canceling auction as per consentManagement config.'); + if (typeof bidsBackHandler === 'function') { + bidsBackHandler(); + } else { + utils.logError('Error executing bidsBackHandler'); + } } } else { nextFn.apply(context, args); diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index 7607dfd2e4b..eb1614e4965 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -302,6 +302,7 @@ describe('consentManagement', function () { it('throws an error when processCmpData check failed while config had allowAuction set to false', () => { let testConsentData = null; + let bidsBackHandlerReturn = false; cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { args[2](testConsentData); @@ -309,13 +310,14 @@ describe('consentManagement', function () { setConfig(goodConfigWithCancelAuction); - requestBidsHook({}, () => { + requestBidsHook({ bidsBackHandler: () => bidsBackHandlerReturn = true }, () => { didHookReturn = true; }); let consent = gdprDataHandler.getConsentData(); sinon.assert.calledOnce(utils.logError); expect(didHookReturn).to.be.false; + expect(bidsBackHandlerReturn).to.be.true; expect(consent).to.be.null; }); From 74b8b743dc588ce6c03356297e50d1a3d3b2512a Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Tue, 22 May 2018 11:37:07 -0400 Subject: [PATCH 0372/1594] InSkin Bid Adapter: support passing GDPR consent string on bid requests (#2578) --- modules/inskinBidAdapter.js | 11 ++++++++++- test/spec/modules/inskinBidAdapter_spec.js | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js index abd94f71a94..0e7e28b9b6b 100644 --- a/modules/inskinBidAdapter.js +++ b/modules/inskinBidAdapter.js @@ -26,10 +26,11 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {validBidRequests[]} - an array of bids + * @param {bidderRequest} - the full bidder request object * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(validBidRequests) { + buildRequests: function(validBidRequests, bidderRequest) { // Do we need to group by bidder? i.e. to make multiple requests for // different endpoints. @@ -56,6 +57,14 @@ export const spec = { parallel: true }, validBidRequests[0].params); + if (bidderRequest && bidderRequest.gdprConsent) { + data.consent = { + gdprConsentString: 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 + gdprConsentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true + }; + } + validBidRequests.map(bid => { let config = CONFIG[bid.bidder]; ENDPOINT_URL = config.BASE_URI; diff --git a/test/spec/modules/inskinBidAdapter_spec.js b/test/spec/modules/inskinBidAdapter_spec.js index f22e6242d53..40a84525ffa 100644 --- a/test/spec/modules/inskinBidAdapter_spec.js +++ b/test/spec/modules/inskinBidAdapter_spec.js @@ -189,6 +189,26 @@ describe('InSkin BidAdapter', () => { expect(request.method).to.have.string('POST'); }); + + it('should add gdpr consent information to the request', () => { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'inskin', + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + bidderRequest.bids = bidRequests; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.consent.gdprConsentString).to.exist; + expect(payload.consent.gdprConsentRequired).to.exist; + expect(payload.consent.gdprConsentString).to.exist.and.to.equal(consentString); + expect(payload.consent.gdprConsentRequired).to.exist.and.to.be.true; + }); }); describe('interpretResponse validation', () => { it('response should have valid bidderCode', () => { From 94745990a9ae9b2e20a4e33aaa09207aa75ebf18 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Tue, 22 May 2018 08:38:21 -0700 Subject: [PATCH 0373/1594] chore: update adapter version number (#2573) --- modules/openxBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 2f116323a42..6a8783a662a 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.0'; +const BIDDER_VERSION = '2.1.1'; let shouldSendBoPixel = true; export function resetBoPixel() { From b5927bb13f1931423f1270d836510a254ce6cad7 Mon Sep 17 00:00:00 2001 From: agon-qurdina <34247167+agon-qurdina@users.noreply.github.com> Date: Tue, 22 May 2018 17:41:00 +0200 Subject: [PATCH 0374/1594] GjirafaBidAdapter - Added GDPR support (#2581) * Added GDPR support * Fix test * Fixed GDPR tests * Fix test * Fix tests --- modules/gjirafaBidAdapter.js | 4 ++++ test/spec/modules/gjirafaBidAdapter_spec.js | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/gjirafaBidAdapter.js b/modules/gjirafaBidAdapter.js index 3fbc7d772fa..4299295ff31 100644 --- a/modules/gjirafaBidAdapter.js +++ b/modules/gjirafaBidAdapter.js @@ -45,6 +45,10 @@ export const spec = { if (document.referrer) { body.referrer = document.referrer; } + if (bidderRequest && bidderRequest.gdprConsent) { + body.consent_string = bidderRequest.gdprConsent.consentString; + body.consent_required = (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true; + } return { method: 'GET', url: ENDPOINT_URL, diff --git a/test/spec/modules/gjirafaBidAdapter_spec.js b/test/spec/modules/gjirafaBidAdapter_spec.js index 17fbdc33591..542e8185db5 100644 --- a/test/spec/modules/gjirafaBidAdapter_spec.js +++ b/test/spec/modules/gjirafaBidAdapter_spec.js @@ -53,7 +53,9 @@ describe('gjirafaAdapterTest', () => { 'sizes': [[728, 90], [980, 200], [980, 150], [970, 90], [970, 250]], 'bidId': '10bdc36fe0b48c8', 'bidderRequestId': '70deaff71c281d', - 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc' + 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc', + 'consent_string': 'consentString', + 'consent_required': 'true' }, { 'bidder': 'gjirafa', @@ -67,7 +69,9 @@ describe('gjirafaAdapterTest', () => { 'sizes': [[300, 250]], 'bidId': '81a6dcb65e2bd9', 'bidderRequestId': '70deaff71c281d', - 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc' + 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc', + 'consent_string': 'consentString', + 'consent_required': 'true' }]; it('bidRequest HTTP method', () => { @@ -97,6 +101,14 @@ describe('gjirafaAdapterTest', () => { expect(requests[0].data.sizes).to.equal('728x90;980x200;980x150;970x90;970x250'); expect(requests[1].data.sizes).to.equal('300x250'); }); + + it('should add GDPR data', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].data.consent_string).to.exists; + expect(requests[0].data.consent_required).to.exists; + expect(requests[1].data.consent_string).to.exists; + expect(requests[1].data.consent_required).to.exists; + }); }); describe('interpretResponse', () => { From 663149bf34da79062680bec764af0ffb8c262a8f Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Tue, 22 May 2018 17:23:05 +0100 Subject: [PATCH 0375/1594] Added sizes 580x500 and 580x400 (#2594) --- modules/rubiconBidAdapter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 061440e7c0e..cb5d257231a 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -45,6 +45,7 @@ var sizeMap = { 59: '320x80', 60: '320x150', 61: '1000x1000', + 64: '580x500', 65: '640x480', 67: '320x480', 68: '1800x1000', @@ -69,6 +70,7 @@ var sizeMap = { 199: '640x200', 213: '1030x590', 214: '980x360', + 232: '580x400' }; utils._each(sizeMap, (item, key) => sizeMap[item] = key); From 461642f50f63ca139054c1f60344d92c1fc7b6dd Mon Sep 17 00:00:00 2001 From: Rajeshk08 Date: Tue, 22 May 2018 22:17:48 +0530 Subject: [PATCH 0376/1594] RhythmOne Adapter - Added GDPR Support (#2576) * RhythmOne Adapter - Added GDPR Support * Updated GDPR unit test case * Adapter version updated --- modules/rhythmoneBidAdapter.js | 15 ++++++-- test/spec/modules/rhythmoneBidAdapter_spec.js | 38 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 6b4b5e7d4e6..f16e797af7d 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -11,7 +11,7 @@ function RhythmOneBidAdapter() { return true; }; - this.getUserSyncs = function (syncOptions) { + this.getUserSyncs = function (syncOptions, responses, gdprConsent) { let slots = []; let placementIds = []; @@ -51,6 +51,10 @@ function RhythmOneBidAdapter() { data.response_ms = Date.now() - loadStart; data.placement_codes = slots.join(','); data.bidder_version = version; + if (gdprConsent) { + data.gdpr_consent = gdprConsent.consentString; + data.gdpr = (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : true; + } for (let k in data) { q.push(encodeURIComponent(k) + '=' + encodeURIComponent((typeof data[k] === 'object' ? JSON.stringify(data[k]) : data[k]))); @@ -76,10 +80,10 @@ function RhythmOneBidAdapter() { let slotsToBids = {}; let that = this; - let version = '1.0.0.0'; + let version = '1.0.1.0'; let loadStart = Date.now(); - this.buildRequests = function (BRs) { + this.buildRequests = function (BRs, bidderRequest) { let fallbackPlacementId = getFirstParam('placementId', BRs); if (fallbackPlacementId === undefined || BRs.length < 1) { return []; @@ -198,7 +202,10 @@ function RhythmOneBidAdapter() { p('h', heights); p('floor', floors); p('t', mediaTypes); - + if (bidderRequest && bidderRequest.gdprConsent) { + p('gdpr_consent', bidderRequest.gdprConsent.consentString); + p('gdpr', (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true); + } url += '&' + query.join('&') + '&'; return url; diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index ad113b9021a..dd7ce4c379d 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -61,6 +61,30 @@ describe('rhythmone adapter tests', function () { assert.equal(mangoRequest.length, 1); }); + it('should send GDPR Consent data to RhythmOne tag', () => { + let _consentString = 'testConsentString'; + var request = z.buildRequests( + [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'xyz', + 'keywords': '', + 'categories': [], + 'trace': true, + 'method': 'get', + 'api': 'mango', + 'endpoint': 'http://fakedomain.com?' + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]] + } + ], {gdprConsent: {gdprApplies: 1, consentString: _consentString}} + ); + assert.equal(getURLParam(request[0].url, 'gdpr'), 'true'); + assert.equal(getURLParam(request[0].url, 'gdpr_consent'), 'testConsentString'); + }); + var bids = z.interpretResponse({ body: [ { @@ -77,5 +101,19 @@ describe('rhythmone adapter tests', function () { it('should register one bid', function() { assert.equal(bids.length, 1); }); + function getURLParam(url, key) { + let val = ''; + if (url.indexOf('?') > -1) { + let qs = url.substr(url.indexOf('?')); + let qsArr = qs.split('&'); + for (let i = 0; i < qsArr.length; i++) { + if (qsArr[i].indexOf(key.toLowerCase() + '=') > -1) { + val = qsArr[i].split('=')[1] + break; + } + } + } + return val; + } }); }); From 7da68eecb7eb65a9f9cd010106f1020293b75137 Mon Sep 17 00:00:00 2001 From: nwlosinski Date: Wed, 23 May 2018 15:49:04 +0200 Subject: [PATCH 0377/1594] GDPR support (#2601) * Justpremium adapter and unit tests. * Fix test suit. * Performance improvements. * Changes requested in pull request review. * Register justpremium adapter in adaptermanager * pass through bid from request * fix linting errors * Load polyfills for older browsers * Load polyfills if older browser * Remove package-lock.json * Copy new Justpremium adapter from feature/1.0 branch * #1881 Requested changes applied * #1892 Use `filter` instead `...new Set` to get unique values * JSD-2248 update for adapter and tests * JSD-2248 added transactionId in json array * JSD-2248 adapter changes * JSD-2248 adapter changes * Update docs * Remove unnecessary return statement * Support for gdpr_consent in bid adapter * new cookie link and endpoint * back to old endpoint version * sending version of prebid and adapter * sending version of prebid and adapter * without version * update for tests * changes for getUserSyncs method * return gulpfile changes --- modules/justpremiumBidAdapter.js | 20 +++++++++++++++---- modules/justpremiumBidAdapter.md | 2 +- .../modules/justpremiumBidAdapter_spec.js | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 93ad9117695..6e044c42640 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -13,7 +13,7 @@ export const spec = { return !!(bid && bid.params && bid.params.zone) }, - buildRequests: (validBidRequests) => { + buildRequests: (validBidRequests, bidderRequest) => { const c = preparePubCond(validBidRequests) const dim = getWebsiteDim() const payload = { @@ -38,6 +38,14 @@ export const spec = { sizes[zone] = sizes[zone] || [] sizes[zone].push.apply(sizes[zone], b.sizes) }) + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr_consent = { + consent_string: bidderRequest.gdprConsent.consentString, + consent_required: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true + }; + } + const payloadString = JSON.stringify(payload) return { @@ -73,12 +81,16 @@ export const spec = { return bidResponses }, - getUserSyncs: (syncOptions) => { + getUserSyncs: function getUserSyncs(syncOptions, responses, gdprConsent) { + let url = '//pre.ads.justpremium.com/v/1.0/t/sync' + if (gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean')) { + url = url + '?consentString=' + encodeURIComponent(gdprConsent.consentString) + } if (syncOptions.iframeEnabled) { pixels.push({ type: 'iframe', - src: '//us-u.openx.net/w/1.0/pd?plm=10&ph=26e53f82-d199-49df-9eca-7b350c0f9646' - }) + url: url + }); } return pixels } diff --git a/modules/justpremiumBidAdapter.md b/modules/justpremiumBidAdapter.md index bc81f2f17b1..c3e17abfec5 100644 --- a/modules/justpremiumBidAdapter.md +++ b/modules/justpremiumBidAdapter.md @@ -2,7 +2,7 @@ **Module Name**: Justpremium Bidder Adapter **Module Type**: Bidder Adapter -**Maintainer**: info@justpremium.com +**Maintainer**: headerbidding-dev@justpremium.com # Description diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index 226a5788cef..769810a3f3f 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -121,7 +121,7 @@ describe('justpremium adapter', () => { const options = spec.getUserSyncs({iframeEnabled: true}) expect(options).to.not.be.undefined expect(options[0].type).to.equal('iframe') - expect(options[0].src).to.match(/\/\/us-u.openx.net\/w\/1.0/) + expect(options[0].url).to.match(/\/\/pre.ads.justpremium.com\/v\/1.0\/t\/sync/) }) }) }) From 3e4d70025c789adcd7220165bbba79d282b9aeb5 Mon Sep 17 00:00:00 2001 From: nissSK Date: Wed, 23 May 2018 20:42:12 +0300 Subject: [PATCH 0378/1594] GDPR support (#2602) --- modules/sekindoUMBidAdapter.js | 4 ++++ test/spec/modules/sekindoUMBidAdapter_spec.js | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/modules/sekindoUMBidAdapter.js b/modules/sekindoUMBidAdapter.js index cf8ba9e23f0..7b24e03408a 100644 --- a/modules/sekindoUMBidAdapter.js +++ b/modules/sekindoUMBidAdapter.js @@ -55,6 +55,10 @@ export const spec = { queryString = utils.tryAppendQueryString(queryString, 'protocol', protocol); queryString = utils.tryAppendQueryString(queryString, 'x', bidRequest.params.width); queryString = utils.tryAppendQueryString(queryString, 'y', bidRequest.params.height); + if (bidderRequest && bidderRequest.gdprConsent) { + queryString = utils.tryAppendQueryString(queryString, 'gdprConsentString', bidderRequest.gdprConsent.consentString); + queryString = utils.tryAppendQueryString(queryString, 'gdprApplies', (bidderRequest.gdprConsent.gdprApplies) ? '1' : '0'); + } if (bidRequest.mediaType === 'video' || (typeof bidRequest.mediaTypes == 'object' && typeof bidRequest.mediaTypes.video == 'object')) { queryString = utils.tryAppendQueryString(queryString, 'x', bidRequest.params.playerWidth); queryString = utils.tryAppendQueryString(queryString, 'y', bidRequest.params.playerHeight); diff --git a/test/spec/modules/sekindoUMBidAdapter_spec.js b/test/spec/modules/sekindoUMBidAdapter_spec.js index a5731da0789..8f275d7fc05 100644 --- a/test/spec/modules/sekindoUMBidAdapter_spec.js +++ b/test/spec/modules/sekindoUMBidAdapter_spec.js @@ -64,6 +64,14 @@ describe('sekindoUMAdapter', () => { expect(request[0].method).to.equal('GET'); }); + it('with gdprConsent, banner data should be a query string and method = GET', () => { + bidRequests.mediaType = 'banner'; + bidRequests.params = bannerParams; + const request = spec.buildRequests([bidRequests], {'gdprConsent': {'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', 'vendorData': {}, 'gdprApplies': true}}); + expect(request[0].data).to.be.a('string'); + expect(request[0].method).to.equal('GET'); + }); + it('video data should be a query string and method = GET', () => { bidRequests.mediaType = 'video'; bidRequests.params = videoParams; From fc95a5257e500832e2d6b1ac7bf9cd5c3dd5210c Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Wed, 23 May 2018 23:24:56 +0530 Subject: [PATCH 0379/1594] Consent Management module bug fix. (#2588) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * GDPR Bug Fix with String response * minor --- modules/consentManagement.js | 3 +- test/spec/modules/consentManagement_spec.js | 97 ++++++++++++++------- 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index 2a47bb25899..f4eedd57cfd 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -8,6 +8,7 @@ import * as utils from 'src/utils'; import { config } from 'src/config'; import { gdprDataHandler } from 'src/adaptermanager'; import includes from 'core-js/library/fn/array/includes'; +import strIncludes from 'core-js/library/fn/string/includes'; const DEFAULT_CMP = 'iab'; const DEFAULT_CONSENT_TIMEOUT = 10000; @@ -132,7 +133,7 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { function readPostMessageResponse(event) { // small customization to prevent reading strings from other sources that aren't JSON.stringified - let json = (typeof event.data === 'string' && includes(event.data, 'cmpReturn')) ? JSON.parse(event.data) : event.data; + let json = (typeof event.data === 'string' && strIncludes(event.data, 'cmpReturn')) ? JSON.parse(event.data) : event.data; if (json.__cmpReturn) { let i = json.__cmpReturn; cmpCallbacks[i.callId](i.returnValue, i.success); diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index eb1614e4965..18df72f044d 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -201,60 +201,95 @@ describe('consentManagement', function () { describe('CMP workflow for iframed page', () => { let eventStub = sinon.stub(); - let cmpStub = sinon.stub(); + let postMessageStub = sinon.stub(); + let ifr = null; beforeEach(() => { didHookReturn = false; - window.__cmp = function() {}; sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); + ifr = createIFrameMarker(); }); afterEach(() => { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); eventStub.restore(); - cmpStub.restore(); + postMessageStub.restore(); delete window.__cmp; utils.logError.restore(); utils.logWarn.restore(); resetConsentData(); + document.body.removeChild(ifr); }); - it('should return the consent string from a postmessage + addEventListener response', () => { - let testConsentData = { - data: { - __cmpReturn: { - returnValue: { - gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' - } + function createIFrameMarker() { + var ifr = document.createElement('iframe'); + ifr.width = 0; + ifr.height = 0; + ifr.name = '__cmpLocator'; + document.body.appendChild(ifr); + return ifr; + } + + testIFramedPage('with/JSON response', { + data: { + __cmpReturn: { + returnValue: { + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' } } - }; - eventStub = sinon.stub(window, 'addEventListener').callsFake((...args) => { - args[1](testConsentData); - }); - cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { - args[2]({ - gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + } + }, false); + + testIFramedPage('with/String response', { + data: { + __cmpReturn: { + returnValue: { + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + } + } + } + }, true); + + function testIFramedPage(testName, testConsentData, messageFormatString) { + it(`should return the consent string from a postmessage + addEventListener response - ${testName}`, () => { + let messageListener; + eventStub = sinon.stub(window, 'addEventListener').callsFake((...args) => { + // save reference to event listener for message + // so we can return the data when the message arrives via 'postMessage' + messageListener = args[1]; + }); + // when the iframed window sends a message to the window + // containing the CMP, intercept it and respond back with data + // on the message listener. + postMessageStub = sinon.stub(window, 'postMessage').callsFake((...args) => { + if (messageListener && args[0] && args[0].__cmpCall) { + // take the callId from request and stamp it on the response. + testConsentData.data.__cmpReturn.callId = args[0].__cmpCall.callId; + // serialize the data part to String if requested + messageListener(messageFormatString ? { + data: JSON.stringify(testConsentData.data) + } : testConsentData); + } }); - }); - setConfig(goodConfigWithAllowAuction); + setConfig(goodConfigWithAllowAuction); - requestBidsHook({}, () => { - didHookReturn = true; - }); - let consent = gdprDataHandler.getConsentData(); + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); - sinon.assert.notCalled(utils.logWarn); - sinon.assert.notCalled(utils.logError); - expect(didHookReturn).to.be.true; - expect(consent.consentString).to.equal('BOJy+UqOJy+UqABAB+AAAAAZ+A=='); - expect(consent.gdprApplies).to.be.true; - }); + sinon.assert.notCalled(utils.logWarn); + sinon.assert.notCalled(utils.logError); + expect(didHookReturn).to.be.true; + expect(consent.consentString).to.equal('BOJy+UqOJy+UqABAB+AAAAAZ+A=='); + expect(consent.gdprApplies).to.be.true; + }); + } }); describe('CMP workflow for normal pages:', () => { From ebf0d306008efb53f2aaa895b3bf4585e1150af1 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 23 May 2018 12:08:55 -0600 Subject: [PATCH 0380/1594] put server latency on bidder timeout event for NO_BIDs (#2561) --- modules/prebidServerBidAdapter.js | 34 ++++--- modules/rubiconAnalyticsAdapter.js | 12 +-- src/utils.js | 12 ++- .../modules/prebidServerBidAdapter_spec.js | 88 +++++++++++-------- .../modules/rubiconAnalyticsAdapter_spec.js | 15 +++- 5 files changed, 96 insertions(+), 65 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 5501eff30ca..fff1331e572 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -362,10 +362,8 @@ const LEGACY_PROTOCOL = { return request; }, - interpretResponse(result, bidRequests, requestedBidders) { + interpretResponse(result, bidderRequests, requestedBidders) { const bids = []; - let responseTimes = {}; - if (result.status === 'OK' || result.status === 'no_cookie') { if (result.bidder_status) { result.bidder_status.forEach(bidder => { @@ -373,13 +371,18 @@ const LEGACY_PROTOCOL = { utils.logWarn(`Prebid Server returned error: '${bidder.error}' for ${bidder.bidder}`); } - responseTimes[bidder.bidder] = bidder.response_time_ms; + bidderRequests.filter(bidderRequest => bidderRequest.bidderCode === bidder.bidder) + .forEach(bidderRequest => + (bidderRequest.bids || []).forEach(bid => + bid.serverResponseTimeMs = bidder.response_time_ms + ) + ) }); } if (result.bids) { result.bids.forEach(bidObj => { - const bidRequest = utils.getBidRequest(bidObj.bid_id, bidRequests); + const bidRequest = utils.getBidRequest(bidObj.bid_id, bidderRequests); const cpm = bidObj.price; const status = cpm !== 0 ? STATUS.GOOD : STATUS.NO_BID; let bidObject = bidfactory.createBid(status, bidRequest); @@ -388,9 +391,6 @@ const LEGACY_PROTOCOL = { bidObject.creative_id = bidObj.creative_id; bidObject.bidderCode = bidObj.bidder; bidObject.cpm = cpm; - if (responseTimes[bidObj.bidder]) { - bidObject.serverResponseTimeMs = responseTimes[bidObj.bidder]; - } if (bidObj.cache_id) { bidObject.cache_id = bidObj.cache_id; } @@ -580,7 +580,7 @@ const OPEN_RTB_PROTOCOL = { return request; }, - interpretResponse(response, bidRequests, requestedBidders) { + interpretResponse(response, bidderRequests, requestedBidders) { const bids = []; if (response.seatbid) { @@ -589,7 +589,7 @@ const OPEN_RTB_PROTOCOL = { (seatbid.bid || []).forEach(bid => { const bidRequest = utils.getBidRequest( this.bidMap[`${bid.impid}${seatbid.seat}`], - bidRequests + bidderRequests ); const cpm = bid.price; @@ -601,8 +601,8 @@ const OPEN_RTB_PROTOCOL = { bidObject.cpm = cpm; let serverResponseTimeMs = utils.deepAccess(response, ['ext', 'responsetimemillis', seatbid.seat].join('.')); - if (serverResponseTimeMs) { - bidObject.serverResponseTimeMs = serverResponseTimeMs; + if (bidRequest && serverResponseTimeMs) { + bidRequest.serverResponseTimeMs = serverResponseTimeMs; } if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { @@ -701,7 +701,7 @@ export function PrebidServer() { }; /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(response, requestedBidders, bidRequests, addBidResponse, done) { + function handleResponse(response, requestedBidders, bidderRequests, addBidResponse, done) { let result; try { @@ -709,19 +709,17 @@ export function PrebidServer() { const bids = protocolAdapter().interpretResponse( result, - bidRequests, + bidderRequests, requestedBidders ); bids.forEach(({adUnit, bid}) => { - if (isValid(adUnit, bid, bidRequests)) { + if (isValid(adUnit, bid, bidderRequests)) { addBidResponse(adUnit, bid); } }); - bidRequests.forEach((bidRequest) => { - events.emit(EVENTS.BIDDER_DONE, bidRequest); - }); + bidderRequests.forEach(bidderRequest => events.emit(EVENTS.BIDDER_DONE, bidderRequest)); if (result.status === 'no_cookie' && _s2sConfig.cookieSet && typeof _s2sConfig.cookieSetUrl === 'string') { // cookie sync diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index dd111efe03c..613cc703eb9 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -376,9 +376,11 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { switch (args.getStatusCode()) { case GOOD: bid.status = 'success'; + delete bid.error; // it's possible for this to be set by a previous timeout break; case NO_BID: bid.status = 'no-bid'; + delete bid.error; break; default: bid.status = 'error'; @@ -387,14 +389,14 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { }; } bid.clientLatencyMillis = Date.now() - cache.auctions[args.auctionId].timestamp; - if (typeof args.serverResponseTimeMs !== 'undefined') { - bid.serverLatencyMillis = args.serverResponseTimeMs; - } bid.bidResponse = parseBidResponse(args); break; case BIDDER_DONE: args.bids.forEach(bid => { - let cachedBid = cache.auctions[bid.auctionId].bids[bid.bidId]; + let cachedBid = cache.auctions[bid.auctionId].bids[bid.bidId || bid.adId]; + if (typeof bid.serverResponseTimeMs !== 'undefined') { + cachedBid.serverLatencyMillis = bid.serverResponseTimeMs; + } if (!cachedBid.status) { cachedBid.status = 'no-bid'; } @@ -433,7 +435,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { case BID_TIMEOUT: args.forEach(badBid => { let auctionCache = cache.auctions[badBid.auctionId]; - let bid = auctionCache.bids[badBid.bidId]; + let bid = auctionCache.bids[badBid.bidId || badBid.adId]; bid.status = 'error'; bid.error = { code: 'timeout-error' diff --git a/src/utils.js b/src/utils.js index c595101bae1..2b93fc0902d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -685,8 +685,16 @@ export function flatten(a, b) { return a.concat(b); } -export function getBidRequest(id, bidsRequested) { - return find(bidsRequested.map(bidSet => find(bidSet.bids, bid => bid.bidId === id)), bid => bid); +export function getBidRequest(id, bidderRequests) { + let bidRequest; + bidderRequests.some(bidderRequest => { + let result = find(bidderRequest.bids, bid => ['bidId', 'adId', 'bid_id'].some(type => bid[type] === id)); + if (result) { + bidRequest = result; + } + return result; + }); + return bidRequest; } export function getKeys(obj) { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 9c25e0439b3..d528c9a3191 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -7,6 +7,8 @@ import { userSync } from 'src/userSync'; import { ajax } from 'src/ajax'; import { config } from 'src/config'; import { requestBidsHook } from 'modules/consentManagement'; +import events from 'src/events'; +import CONSTANTS from 'src/constants'; let CONFIG = { accountId: '1', @@ -79,34 +81,7 @@ const VIDEO_REQUEST = { ] }; -const BID_REQUESTS = [ - { - 'bidderCode': 'appnexus', - 'auctionId': '173afb6d132ba3', - 'bidderRequestId': '3d1063078dfcc8', - 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', - 'bids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': '10433394', - 'member': 123 - }, - 'bid_id': '123', - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', - 'sizes': [300, 250], - 'bidId': '259fb43aaa06c1', - 'bidderRequestId': '3d1063078dfcc8', - 'auctionId': '173afb6d132ba3' - } - ], - 'auctionStart': 1510852447530, - 'timeout': 5000, - 'src': 's2s', - 'doneCbCallCount': 0 - } -]; +let BID_REQUESTS; const RESPONSE = { 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', @@ -359,7 +334,37 @@ describe('S2S Adapter', () => { addBidResponse = sinon.spy(), done = sinon.spy(); - beforeEach(() => adapter = new Adapter()); + beforeEach(() => { + adapter = new Adapter(); + BID_REQUESTS = [ + { + 'bidderCode': 'appnexus', + 'auctionId': '173afb6d132ba3', + 'bidderRequestId': '3d1063078dfcc8', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394', + 'member': 123 + }, + 'bid_id': '123', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'sizes': [300, 250], + 'bidId': '123', + 'bidderRequestId': '3d1063078dfcc8', + 'auctionId': '173afb6d132ba3' + } + ], + 'auctionStart': 1510852447530, + 'timeout': 5000, + 'src': 's2s', + 'doneCbCallCount': 0 + } + ]; + }); afterEach(() => { addBidResponse.resetHistory(); @@ -558,7 +563,7 @@ describe('S2S Adapter', () => { s2sConfig: s2sConfig, device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, app: { bundle: 'com.test.app' }, - } + }; config.setConfig(_config); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -675,24 +680,22 @@ describe('S2S Adapter', () => { sinon.stub(utils, 'insertUserSyncIframe'); sinon.stub(utils, 'logError'); sinon.stub(cookie, 'cookieSet'); - sinon.stub(utils, 'getBidRequest').returns({ - bidId: '123' - }); + sinon.stub(events, 'emit'); logWarnSpy = sinon.spy(utils, 'logWarn'); }); afterEach(() => { server.restore(); - utils.getBidRequest.restore(); utils.triggerPixel.restore(); utils.insertUserSyncIframe.restore(); utils.logError.restore(); + events.emit.restore(); cookie.cookieSet.restore(); logWarnSpy.restore(); }); // TODO: test dependent on pbjs_api_spec. Needs to be isolated - it('registers bids', () => { + it('registers bids and calls BIDDER_DONE', () => { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -700,6 +703,11 @@ describe('S2S Adapter', () => { server.respond(); sinon.assert.calledOnce(addBidResponse); + sinon.assert.calledOnce(events.emit); + const event = events.emit.firstCall.args; + expect(event[0]).to.equal(CONSTANTS.EVENTS.BIDDER_DONE); + expect(event[1].bids[0]).to.have.property('serverResponseTimeMs', 52); + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); @@ -708,7 +716,6 @@ describe('S2S Adapter', () => { expect(response).to.have.property('cache_id', '7654321'); expect(response).to.have.property('cache_url', 'http://www.test.com/cache?uuid=7654321'); expect(response).to.not.have.property('vastUrl'); - expect(response).to.have.property('serverResponseTimeMs', 52); }); it('registers video bids', () => { @@ -880,7 +887,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(cookie.cookieSet); }); - it('handles OpenRTB responses', () => { + it('handles OpenRTB responses and call BIDDER_DONE', () => { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -890,13 +897,17 @@ describe('S2S Adapter', () => { adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); + sinon.assert.calledOnce(events.emit); + const event = events.emit.firstCall.args; + expect(event[0]).to.equal(CONSTANTS.EVENTS.BIDDER_DONE); + expect(event[1].bids[0]).to.have.property('serverResponseTimeMs', 8); + sinon.assert.calledOnce(addBidResponse); const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('bidderCode', 'appnexus'); expect(response).to.have.property('adId', '123'); expect(response).to.have.property('cpm', 0.5); - expect(response).to.have.property('serverResponseTimeMs', 8); }); it('handles OpenRTB video responses', () => { @@ -917,7 +928,6 @@ describe('S2S Adapter', () => { expect(response).to.have.property('bidderCode', 'appnexus'); expect(response).to.have.property('adId', '123'); expect(response).to.have.property('cpm', 10); - expect(response).to.have.property('serverResponseTimeMs', 81); }); it('should log warning for unsupported bidder', () => { diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 38f8b726cd1..21ed1cfa522 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -27,6 +27,7 @@ const { AUCTION_END, BID_REQUESTED, BID_RESPONSE, + BIDDER_DONE, BID_WON, BID_TIMEOUT, SET_TARGETING @@ -39,6 +40,7 @@ const BID = { 'height': 480, 'mediaType': 'video', 'statusMessage': 'Bid available', + 'bidId': '2ecff0db240757', 'adId': '2ecff0db240757', 'source': 'client', 'requestId': '2ecff0db240757', @@ -78,6 +80,7 @@ const BID = { const BID2 = Object.assign({}, BID, { adUnitCode: '/19968336/header-bid-tag1', + bidId: '3bd4ebb1c900e2', adId: '3bd4ebb1c900e2', requestId: '3bd4ebb1c900e2', width: 728, @@ -85,7 +88,6 @@ const BID2 = Object.assign({}, BID, { mediaType: 'banner', cpm: 1.52, source: 'server', - serverResponseTimeMs: 42, rubiconTargeting: { 'rpfl_elemid': '/19968336/header-bid-tag1', 'rpfl_14062': '2_tier0100' @@ -190,6 +192,15 @@ const MOCK = { 'status': 'rendered' }) ], + BIDDER_DONE: { + 'bidderCode': 'rubicon', + 'bids': [ + BID, + Object.assign({}, BID2, { + 'serverResponseTimeMs': 42, + }) + ] + }, BID_TIMEOUT: [ { 'bidId': '2ecff0db240757', @@ -392,6 +403,7 @@ function performStandardAuction() { 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); events.emit(SET_TARGETING, MOCK.SET_TARGETING); events.emit(BID_WON, MOCK.BID_WON[0]); @@ -588,6 +600,7 @@ describe('rubicon analytics adapter', () => { 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); events.emit(SET_TARGETING, MOCK.SET_TARGETING); events.emit(BID_WON, MOCK.BID_WON[0]); From da8bb948d602963ad129843bf8a548892673287b Mon Sep 17 00:00:00 2001 From: Pupis Date: Wed, 23 May 2018 21:10:44 +0300 Subject: [PATCH 0381/1594] Updated gdpr in adform adapter (#2589) --- modules/adformBidAdapter.js | 19 +++++-- test/spec/modules/adformBidAdapter_spec.js | 64 +++++++++++++++++++--- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index a84def819c1..2814f587965 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -11,7 +11,7 @@ export const spec = { return !!(bid.params.mid); }, buildRequests: function (validBidRequests, bidderRequest) { - var i, l, j, k, bid, _key, _value, reqParams, netRevenue; + var i, l, j, k, bid, _key, _value, reqParams, netRevenue, gdprObject; var request = []; var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ] ]; var bids = JSON.parse(JSON.stringify(validBidRequests)); @@ -38,9 +38,13 @@ export const spec = { request.push('pt=' + netRevenue); request.push('stid=' + validBidRequests[0].auctionId); - if (bidderRequest && bidderRequest.gdprConsent) { - request.push('gdpr=' + bidderRequest.gdprConsent.gdprApplies); - request.push('gdpr_consent=' + bidderRequest.gdprConsent.consentString); + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { + gdprObject = { + gdpr: bidderRequest.gdprConsent.gdprApplies, + gdpr_consent: bidderRequest.gdprConsent.consentString + }; + request.push('gdpr=' + gdprObject.gdpr); + request.push('gdpr_consent=' + gdprObject.gdpr_consent); } for (i = 1, l = globalParams.length; i < l; i++) { @@ -56,7 +60,8 @@ export const spec = { url: request.join('&'), bids: validBidRequests, netRevenue: netRevenue, - bidder: 'adform' + bidder: 'adform', + gdpr: gdprObject }; function formRequestUrl(reqData) { @@ -102,6 +107,10 @@ export const spec = { vastXml: response.vast_content, mediaType: type }; + if (bidRequest.gdpr) { + bidObject.gdpr = bidRequest.gdpr.gdpr; + bidObject.gdpr_consent = bidRequest.gdpr.gdpr_consent; + } bidRespones.push(bidObject); } } diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index 21ff84bdad5..90de34b990d 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -99,15 +99,6 @@ describe('Adform adapter', () => { assert.deepEqual(resultBids, bids[0]); }); - it('should send GDPR Consent data to adform', () => { - var resultBids = JSON.parse(JSON.stringify(bids[0])); - let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: 1, consentString: 'concentDataString'}}); - let parsedUrl = parseUrl(request.url).query; - - assert.equal(parsedUrl.gdpr, 1); - assert.equal(parsedUrl.gdpr_consent, 'concentDataString'); - }); - it('should set gross to the request, if there is any gross priceType', () => { let request = spec.buildRequests([bids[5], bids[5]]); let parsedUrl = parseUrl(request.url); @@ -119,6 +110,42 @@ describe('Adform adapter', () => { assert.equal(parsedUrl.query.pt, 'gross'); }); + + describe('gdpr', () => { + it('should send GDPR Consent data to adform if gdprApplies', () => { + let resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); + let parsedUrl = parseUrl(request.url).query; + + assert.equal(parsedUrl.gdpr, 'true'); + assert.equal(parsedUrl.gdpr_consent, 'concentDataString'); + }); + + it('should not send GDPR Consent data to adform if gdprApplies is false or undefined', () => { + let resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: false, consentString: 'concentDataString'}}); + let parsedUrl = parseUrl(request.url).query; + + assert.ok(!parsedUrl.gdpr); + assert.ok(!parsedUrl.gdpr_consent); + + request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: undefined, consentString: 'concentDataString'}}); + assert.ok(!parsedUrl.gdpr); + assert.ok(!parsedUrl.gdpr_consent); + }); + + it('should return GDPR Consent data with request data', () => { + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); + + assert.deepEqual(request.gdpr, { + gdpr: true, + gdpr_consent: 'concentDataString' + }); + + request = spec.buildRequests([bids[0]]); + assert.ok(!request.gdpr); + }); + }); }); describe('interpretResponse', () => { @@ -205,6 +232,25 @@ describe('Adform adapter', () => { assert.equal(result[i].netRevenue, false); } }); + + it('should set gdpr if it exist in bidRequest', () => { + bidRequest.gdpr = { + gdpr: true, + gdpr_consent: 'ERW342EIOWT34234KMGds' + }; + let result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].gdpr, true); + assert.equal(result[i].gdpr_consent, 'ERW342EIOWT34234KMGds'); + }; + + bidRequest.gdpr = undefined; + result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.ok(!result[i].gdpr); + assert.ok(!result[i].gdpr_consent); + }; + }) }); beforeEach(() => { From 41f4c6bb351c971f98690c49a9320b7dd61c3946 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Wed, 23 May 2018 20:30:57 +0200 Subject: [PATCH 0382/1594] Adding GDPR support (#2599) --- modules/improvedigitalBidAdapter.js | 38 +++++++++---------- .../modules/improvedigitalBidAdapter_spec.js | 29 +++++++++----- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 2dcdcb2a808..c99e496f17c 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -6,7 +6,7 @@ import { userSync } from 'src/userSync'; const BIDDER_CODE = 'improvedigital'; export const spec = { - version: '4.1.0', + version: '4.2.0', code: BIDDER_CODE, aliases: ['id'], @@ -26,7 +26,7 @@ export const spec = { * @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) { + buildRequests: function (bidRequests, bidderRequest) { let normalizedBids = bidRequests.map((bidRequest) => { return getNormalizedBidRequest(bidRequest); }); @@ -34,11 +34,14 @@ export const spec = { let idClient = new ImproveDigitalAdServerJSClient('hb'); let requestParameters = { singleRequestMode: false, - httpRequestType: idClient.CONSTANTS.HTTP_REQUEST_TYPE.GET, - returnObjType: idClient.CONSTANTS.RETURN_OBJ_TYPE.PREBID, + returnObjType: idClient.CONSTANTS.RETURN_OBJ_TYPE.URL_PARAMS_SPLIT, libVersion: this.version }; + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) { + requestParameters.gdpr = bidderRequest.gdprConsent.consentString; + } + let requestObj = idClient.createRequest( normalizedBids, // requestObject requestParameters @@ -154,10 +157,6 @@ registerBidder(spec); function ImproveDigitalAdServerJSClient(endPoint) { this.CONSTANTS = { - HTTP_REQUEST_TYPE: { - GET: 0, - POST: 1 - }, HTTP_SECURITY: { STANDARD: 0, SECURE: 1 @@ -165,16 +164,15 @@ function ImproveDigitalAdServerJSClient(endPoint) { AD_SERVER_BASE_URL: 'ad.360yield.com', END_POINT: endPoint || 'hb', AD_SERVER_URL_PARAM: 'jsonp=', - CLIENT_VERSION: 'JS-4.3.3', + CLIENT_VERSION: 'JS-5.1', MAX_URL_LENGTH: 2083, ERROR_CODES: { - BAD_HTTP_REQUEST_TYPE_PARAM: 1, MISSING_PLACEMENT_PARAMS: 2, LIB_VERSION_MISSING: 3 }, RETURN_OBJ_TYPE: { DEFAULT: 0, - PREBID: 1 + URL_PARAMS_SPLIT: 1 } }; @@ -187,9 +185,6 @@ function ImproveDigitalAdServerJSClient(endPoint) { }; this.createRequest = function(requestObject, requestParameters, extraRequestParameters) { - if (requestParameters.httpRequestType !== this.CONSTANTS.HTTP_REQUEST_TYPE.GET) { - return this.getErrorReturn(this.CONSTANTS.ERROR_CODES.BAD_HTTP_REQUEST_TYPE_PARAM); - } if (!requestParameters.libVersion) { return this.getErrorReturn(this.CONSTANTS.ERROR_CODES.LIB_VERSION_MISSING); } @@ -198,9 +193,8 @@ function ImproveDigitalAdServerJSClient(endPoint) { let impressionObjects = []; let impressionObject; - let counter; if (utils.isArray(requestObject)) { - for (counter = 0; counter < requestObject.length; counter++) { + for (let counter = 0; counter < requestObject.length; counter++) { impressionObject = this.createImpressionObject(requestObject[counter]); impressionObjects.push(impressionObject); } @@ -210,7 +204,7 @@ function ImproveDigitalAdServerJSClient(endPoint) { } let returnIdMappings = true; - if (requestParameters.returnObjType === this.CONSTANTS.RETURN_OBJ_TYPE.PREBID) { + if (requestParameters.returnObjType === this.CONSTANTS.RETURN_OBJ_TYPE.URL_PARAMS_SPLIT) { returnIdMappings = false; } @@ -226,7 +220,7 @@ function ImproveDigitalAdServerJSClient(endPoint) { let bidRequestObject = { bid_request: this.createBasicBidRequestObject(requestParameters, extraRequestParameters) }; - for (counter = 0; counter < impressionObjects.length; counter++) { + for (let counter = 0; counter < impressionObjects.length; counter++) { impressionObject = impressionObjects[counter]; if (impressionObject.errorCode) { @@ -279,7 +273,7 @@ function ImproveDigitalAdServerJSClient(endPoint) { this.formatRequest = function(requestParameters, bidRequestObject) { switch (requestParameters.returnObjType) { - case this.CONSTANTS.RETURN_OBJ_TYPE.PREBID: + case this.CONSTANTS.RETURN_OBJ_TYPE.URL_PARAMS_SPLIT: return { method: 'GET', url: `//${this.CONSTANTS.AD_SERVER_BASE_URL}/${this.CONSTANTS.END_POINT}`, @@ -320,6 +314,12 @@ function ImproveDigitalAdServerJSClient(endPoint) { if (requestParameters.libVersion) { impressionBidRequestObject.version = requestParameters.libVersion + '-' + this.CONSTANTS.CLIENT_VERSION; } + if (requestParameters.referrer) { + impressionBidRequestObject.referrer = requestParameters.referrer; + } + if (requestParameters.gdpr) { + impressionBidRequestObject.gdpr = requestParameters.gdpr; + } if (extraRequestParameters) { for (let prop in extraRequestParameters) { impressionBidRequestObject[prop] = extraRequestParameters[prop]; diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index cd68418d6c7..d7595934194 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -32,6 +32,14 @@ describe('Improve Digital Adapter Tests', function () { } }; + const bidderRequest = { + 'gdprConsent': { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'vendorData': {}, + 'gdprApplies': true + }, + }; + describe('isBidRequestValid', () => { it('should return false when no bid', () => { expect(spec.isBidRequestValid()).to.equal(false); @@ -139,6 +147,13 @@ describe('Improve Digital Adapter Tests', function () { getConfigStub.restore(); }); + it('should add GDPR consent string', () => { + const bidRequest = Object.assign({}, simpleBidRequest); + const request = spec.buildRequests([bidRequest], bidderRequest)[0]; + const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); + expect(params.bid_request.gdpr).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + }); + it('should return 2 requests', () => { const requests = spec.buildRequests([ simpleBidRequest, @@ -150,14 +165,6 @@ describe('Improve Digital Adapter Tests', function () { }); describe('interpretResponse', () => { - let registerSyncStub; - beforeEach(() => { - registerSyncStub = sinon.stub(userSync, 'registerSync'); - }); - - afterEach(() => { - registerSyncStub.restore(); - }); const serverResponse = { 'body': { 'id': '687a06c541d8d1', @@ -254,9 +261,11 @@ describe('Improve Digital Adapter Tests', function () { }); it('should register user syncs', () => { + const registerSyncSpy = sinon.spy(userSync, 'registerSync'); const bids = spec.interpretResponse(serverResponse); - expect(registerSyncStub.withArgs('image', 'improvedigital', 'http://link1').calledOnce).to.equal(true); - expect(registerSyncStub.withArgs('image', 'improvedigital', 'http://link2').calledOnce).to.equal(true); + expect(registerSyncSpy.withArgs('image', 'improvedigital', 'http://link1').calledOnce).to.equal(true); + expect(registerSyncSpy.withArgs('image', 'improvedigital', 'http://link2').calledOnce).to.equal(true); + registerSyncSpy.restore(); }); it('should set dealId correctly', () => { From a637b4ba58e3b6cfdb3eb52936f28c55e42d3763 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 23 May 2018 15:46:34 -0400 Subject: [PATCH 0383/1594] Gdpr fix unit test (#2604) * Revert "Consent Management module bug fix. (#2588)" This reverts commit fc95a5257e500832e2d6b1ac7bf9cd5c3dd5210c. * use new file for string includes --- test/spec/modules/consentManagement_spec.js | 97 +++++++-------------- 1 file changed, 31 insertions(+), 66 deletions(-) diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index 18df72f044d..eb1614e4965 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -201,95 +201,60 @@ describe('consentManagement', function () { describe('CMP workflow for iframed page', () => { let eventStub = sinon.stub(); - let postMessageStub = sinon.stub(); - let ifr = null; + let cmpStub = sinon.stub(); beforeEach(() => { didHookReturn = false; + window.__cmp = function() {}; sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); - ifr = createIFrameMarker(); }); afterEach(() => { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); eventStub.restore(); - postMessageStub.restore(); + cmpStub.restore(); delete window.__cmp; utils.logError.restore(); utils.logWarn.restore(); resetConsentData(); - document.body.removeChild(ifr); }); - function createIFrameMarker() { - var ifr = document.createElement('iframe'); - ifr.width = 0; - ifr.height = 0; - ifr.name = '__cmpLocator'; - document.body.appendChild(ifr); - return ifr; - } - - testIFramedPage('with/JSON response', { - data: { - __cmpReturn: { - returnValue: { - gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' - } - } - } - }, false); - - testIFramedPage('with/String response', { - data: { - __cmpReturn: { - returnValue: { - gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + it('should return the consent string from a postmessage + addEventListener response', () => { + let testConsentData = { + data: { + __cmpReturn: { + returnValue: { + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + } } } - } - }, true); - - function testIFramedPage(testName, testConsentData, messageFormatString) { - it(`should return the consent string from a postmessage + addEventListener response - ${testName}`, () => { - let messageListener; - eventStub = sinon.stub(window, 'addEventListener').callsFake((...args) => { - // save reference to event listener for message - // so we can return the data when the message arrives via 'postMessage' - messageListener = args[1]; - }); - // when the iframed window sends a message to the window - // containing the CMP, intercept it and respond back with data - // on the message listener. - postMessageStub = sinon.stub(window, 'postMessage').callsFake((...args) => { - if (messageListener && args[0] && args[0].__cmpCall) { - // take the callId from request and stamp it on the response. - testConsentData.data.__cmpReturn.callId = args[0].__cmpCall.callId; - // serialize the data part to String if requested - messageListener(messageFormatString ? { - data: JSON.stringify(testConsentData.data) - } : testConsentData); - } + }; + eventStub = sinon.stub(window, 'addEventListener').callsFake((...args) => { + args[1](testConsentData); + }); + cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { + args[2]({ + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' }); + }); - setConfig(goodConfigWithAllowAuction); - - requestBidsHook({}, () => { - didHookReturn = true; - }); - let consent = gdprDataHandler.getConsentData(); + setConfig(goodConfigWithAllowAuction); - sinon.assert.notCalled(utils.logWarn); - sinon.assert.notCalled(utils.logError); - expect(didHookReturn).to.be.true; - expect(consent.consentString).to.equal('BOJy+UqOJy+UqABAB+AAAAAZ+A=='); - expect(consent.gdprApplies).to.be.true; + requestBidsHook({}, () => { + didHookReturn = true; }); - } + let consent = gdprDataHandler.getConsentData(); + + sinon.assert.notCalled(utils.logWarn); + sinon.assert.notCalled(utils.logError); + expect(didHookReturn).to.be.true; + expect(consent.consentString).to.equal('BOJy+UqOJy+UqABAB+AAAAAZ+A=='); + expect(consent.gdprApplies).to.be.true; + }); }); describe('CMP workflow for normal pages:', () => { From 74d04b22bf1db3595ce1415a658c2acf056fc21f Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 23 May 2018 13:10:01 -0700 Subject: [PATCH 0384/1594] Sharethrough GDPR updates (#2563) --- modules/sharethroughBidAdapter.js | 12 ++++++++---- test/spec/modules/sharethroughBidAdapter_spec.js | 14 +++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index f8cb2c99400..bb7f778089a 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -14,12 +14,16 @@ export const sharethroughAdapterSpec = { placement_key: bid.params.pkey, hbVersion: '$prebid.version$', strVersion: VERSION, - hbSource: 'prebid' + hbSource: 'prebid', + consent_required: false }; - if (bidderRequest && bidderRequest.gdprConsent) { + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) { query.consent_string = bidderRequest.gdprConsent.consentString; - query.consent_required = bidderRequest.gdprConsent.gdprApplies; + } + + if (bidderRequest && bidderRequest.gdprConsent) { + query.consent_required = !!bidderRequest.gdprConsent.gdprApplies; } return { @@ -51,7 +55,7 @@ export const sharethroughAdapterSpec = { }, getUserSyncs: (syncOptions, serverResponses) => { const syncs = []; - if (syncOptions.pixelEnabled && serverResponses.length > 0) { + if (syncOptions.pixelEnabled && serverResponses.length > 0 && serverResponses[0].body) { serverResponses[0].body.cookieSyncUrls.forEach(url => { syncs.push({ type: 'image', url: url }); }); diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index aa9477d2557..2aef88fe7eb 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -105,8 +105,15 @@ describe('sharethrough adapter spec', () => { const gdprConsent = { consentString: 'consent_string123', gdprApplies: true }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; - expect(bidRequest.data.consent_string).to.eq('consent_string123'); expect(bidRequest.data.consent_required).to.eq(true); + expect(bidRequest.data.consent_string).to.eq('consent_string123'); + }); + + it('should handle gdprConsent is present but values are undefined case', () => { + const gdprConsent = { consent_string: undefined, gdprApplies: undefined }; + const fakeBidRequest = { gdprConsent: gdprConsent }; + const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; + expect(bidRequest.data).to.not.include.any.keys('consent_string') }); }); @@ -171,6 +178,11 @@ describe('sharethrough adapter spec', () => { ); }); + it('returns an empty array if the body is null', () => { + const syncArray = spec.getUserSyncs({ pixelEnabled: true }, [{ body: null }]); + expect(syncArray).to.be.an('array').that.is.empty; + }); + it('returns an empty array if pixels are not enabled', () => { const syncArray = spec.getUserSyncs({ pixelEnabled: false }, serverResponses); expect(syncArray).to.be.an('array').that.is.empty; From bc2e73beb521f140d0d1325aab36f240567cf92e Mon Sep 17 00:00:00 2001 From: OneTagDevOps <38786435+OneTagDevOps@users.noreply.github.com> Date: Wed, 23 May 2018 22:12:49 +0200 Subject: [PATCH 0385/1594] Added GDPR feature (#2569) --- modules/onetagBidAdapter.js | 11 +++++++++-- test/spec/modules/onetagBidAdapter_spec.js | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index 96a85a6070d..72a88039fed 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -38,12 +38,20 @@ function isBidRequestValid(bid) { * @return ServerRequest Info describing the request to the server. */ -function buildRequests(validBidRequests) { +function buildRequests(validBidRequests, bidderRequest) { const bids = validBidRequests.map(requestsToBids); const bidObject = {'bids': bids}; const pageInfo = getPageInfo(); const payload = Object.assign(bidObject, pageInfo); + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdprConsent = { + consentString: bidderRequest.gdprConsent.consentString, + consentRequired: bidderRequest.gdprConsent.gdprApplies + }; + } + const payloadString = JSON.stringify(payload); return { @@ -154,7 +162,6 @@ function requestsToBids(bid) { return toRet; } -// Va bene così, questo file va aggiunto a prebidmaster export const spec = { code: BIDDER_CODE, diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js index dfd3254fd75..85597a0c6c6 100644 --- a/test/spec/modules/onetagBidAdapter_spec.js +++ b/test/spec/modules/onetagBidAdapter_spec.js @@ -86,6 +86,26 @@ describe('onetag', () => { console.log('Error while parsing'); } }); + it('should send GDPR consent data', () => { + let consentString = 'consentString'; + let bidderRequest = { + 'bidderCode': 'onetag', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + let serverRequest = spec.buildRequests([bid], bidderRequest); + const payload = JSON.parse(serverRequest.data); + + expect(payload).to.exist; + expect(payload.gdprConsent).to.exist; + expect(payload.gdprConsent.consentString).to.exist.and.to.equal(consentString); + expect(payload.gdprConsent.consentRequired).to.exist.and.to.be.true; + }); }); describe('interpretResponse', () => { const resObject = { From 66ac3e4f0043e2444362014674b3240e959b8edc Mon Sep 17 00:00:00 2001 From: Roffray Date: Wed, 23 May 2018 17:32:06 -0400 Subject: [PATCH 0386/1594] Add renderer on vuble adapter (#2543) * mod var name bids vuble adaptor * mod vuble adaptor vid request var name * Add: renderer for vuble outstream ads * mod vuble progress outstream player is bar * add vuble unit test for adUnitCode * no volume vuble adapter renderer --- modules/vubleBidAdapter.js | 92 ++++++++++++++++++----- test/spec/modules/vubleBidAdapter_spec.js | 22 ++++-- 2 files changed, 89 insertions(+), 25 deletions(-) diff --git a/modules/vubleBidAdapter.js b/modules/vubleBidAdapter.js index a61b80777fc..7d50c4bc201 100644 --- a/modules/vubleBidAdapter.js +++ b/modules/vubleBidAdapter.js @@ -2,6 +2,7 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; +import { Renderer } from 'src/Renderer'; const BIDDER_CODE = 'vuble'; @@ -12,6 +13,39 @@ const CURRENCIES = { }; const TTL = 60; +const outstreamRender = bid => { + bid.renderer.push(() => { + window.ANOutstreamVideo.renderAd({ + sizes: [bid.width, bid.height], + targetId: bid.adUnitCode, + adResponse: bid.adResponse, + rendererOptions: { + showBigPlayButton: false, + showProgressBar: 'bar', + showVolume: false, + allowFullscreen: false, + skippable: false, + } + }); + }); +} + +const createRenderer = (bid, serverResponse) => { + const renderer = Renderer.install({ + id: serverResponse.renderer_id, + url: serverResponse.renderer_url, + loaded: false, + }); + + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + + return renderer; +} + export const spec = { code: BIDDER_CODE, supportedMediaTypes: ['video'], @@ -45,30 +79,31 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (validBidRequests) { - return validBidRequests.map(bid => { + return validBidRequests.map(bidRequest => { // We take the first size - let size = utils.parseSizesInput(bid.sizes)[0].split('x'); + let size = utils.parseSizesInput(bidRequest.sizes)[0].split('x'); // Get the page's url let referrer = utils.getTopWindowUrl(); - if (bid.params.referrer) { - referrer = bid.params.referrer; + if (bidRequest.params.referrer) { + referrer = bidRequest.params.referrer; } // Get Video Context - let context = utils.deepAccess(bid, 'mediaTypes.video.context'); + let context = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); - let url = '//player.mediabong.' + bid.params.env + '/prebid/request'; + let url = '//player.mediabong.' + bidRequest.params.env + '/prebid/request'; let data = { width: size[0], height: size[1], - pub_id: bid.params.pubId, - zone_id: bid.params.zoneId, + pub_id: bidRequest.params.pubId, + zone_id: bidRequest.params.zoneId, context: context, - floor_price: bid.params.floorPrice ? bid.params.floorPrice : 0, + floor_price: bidRequest.params.floorPrice ? bidRequest.params.floorPrice : 0, url: referrer, - env: bid.params.env, - bid_id: bid.bidId + env: bidRequest.params.env, + bid_id: bidRequest.bidId, + adUnitCode: bidRequest.adUnitCode }; return { @@ -85,30 +120,47 @@ export const spec = { * @param {ServerResponse} serverResponse A successful response from the server. * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse, bid) { + interpretResponse: function (serverResponse, bidRequest) { const responseBody = serverResponse.body; if (typeof responseBody !== 'object' || responseBody.status !== 'ok') { return []; } - let responses = []; - let reponse = { - requestId: bid.data.bid_id, + let bids = []; + let bid = { + requestId: bidRequest.data.bid_id, cpm: responseBody.cpm, - width: bid.data.width, - height: bid.data.height, + width: bidRequest.data.width, + height: bidRequest.data.height, ttl: TTL, creativeId: responseBody.creativeId, dealId: responseBody.dealId, netRevenue: true, - currency: CURRENCIES[bid.data.env], + currency: CURRENCIES[bidRequest.data.env], vastUrl: responseBody.url, mediaType: 'video' }; - responses.push(reponse); - return responses; + if (responseBody.renderer_url) { + let adResponse = { + ad: { + video: { + content: responseBody.content + } + } + }; + + Object.assign(bid, { + adResponse: adResponse, + adUnitCode: bidRequest.data.adUnitCode, + renderer: createRenderer(bid, responseBody) + }); + } + + bids.push(bid); + + return bids; }, /** diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 61f00ef2c3d..6d266ca465e 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -106,7 +106,8 @@ describe('VubleAdapter', () => { context: 'instream' } }, - bidId: 'abdc' + bidId: 'abdc', + adUnitCode: '' }; let bid2 = { bidder: 'vuble', @@ -122,7 +123,8 @@ describe('VubleAdapter', () => { context: 'outstream' } }, - bidId: 'efgh' + bidId: 'efgh', + adUnitCode: 'code' }; // Formatted requets @@ -138,7 +140,8 @@ describe('VubleAdapter', () => { floor_price: 5.5, url: 'http://www.vuble.tv/', env: 'net', - bid_id: 'abdc' + bid_id: 'abdc', + adUnitCode: '' } }; let request2 = { @@ -153,7 +156,8 @@ describe('VubleAdapter', () => { floor_price: 0, url: 'http://www.vuble.fr/', env: 'com', - bid_id: 'efgh' + bid_id: 'efgh', + adUnitCode: 'code' } }; @@ -188,7 +192,8 @@ describe('VubleAdapter', () => { pub_id: '3', zone_id: '12345', bid_id: 'abdc', - floor_price: 5.50 // optional + floor_price: 5.50, // optional + adUnitCode: 'code' }, method: 'POST', url: '//player.mediabong.net/prebid/request' @@ -231,6 +236,13 @@ describe('VubleAdapter', () => { delete wrongResponse.body; expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; }); + + it('should equal to the expected formatted result', () => { + response.body.renderer_url = 'vuble_renderer.js'; + result.adUnitCode = 'code'; + let formattedResponses = adapter.interpretResponse(response, bid); + expect(formattedResponses[0].adUnitCode).to.equal(result.adUnitCode); + }); }); describe('Check getUserSyncs method return', () => { From 1d5c8ee9875e8e4d1ea4c58a3e11902a512cd768 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Wed, 23 May 2018 15:50:25 -0700 Subject: [PATCH 0387/1594] Rubicon Adapter - SRA support (#2478) * Updated the SRA support branch with changes from current prebid master * linting fixes * merged remote changes * removed isNaN leftover from merge mistake with master --- modules/rubiconBidAdapter.js | 444 +++++++++------ test/spec/modules/rubiconBidAdapter_spec.js | 599 +++++++++++++++++++- 2 files changed, 851 insertions(+), 192 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index cb5d257231a..1a89ca5e3e4 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -125,158 +125,220 @@ export const spec = { * @return ServerRequest[] */ buildRequests: function (bidRequests, bidderRequest) { - return bidRequests.map(bidRequest => { + // separate video bids because the requests are structured differently + let requests = []; + const videoRequests = bidRequests.filter(spec.hasVideoMediaType).map(bidRequest => { bidRequest.startTime = new Date().getTime(); - let page_url = config.getConfig('pageUrl'); - if (bidRequest.params.referrer) { - page_url = bidRequest.params.referrer; - } else if (!page_url) { - page_url = utils.getTopWindowUrl(); - } - - // GDPR reference, for use by 'banner' and 'video' - const gdprConsent = bidderRequest.gdprConsent; - - if (spec.hasVideoMediaType(bidRequest)) { - let params = bidRequest.params; - let size = parseSizes(bidRequest); - - let data = { - page_url, - resolution: _getScreenResolution(), - account_id: params.accountId, - integration: INTEGRATION, - 'x_source.tid': bidRequest.transactionId, - timeout: bidderRequest.timeout - (Date.now() - bidderRequest.auctionStart + TIMEOUT_BUFFER), - stash_creatives: true, - ae_pass_through_parameters: params.video.aeParams, - rp_secure: bidRequest.params.secure !== false, - slots: [] - }; + let params = bidRequest.params; + let size = parseSizes(bidRequest); + + let data = { + page_url: _getPageUrl(bidRequest), + resolution: _getScreenResolution(), + account_id: params.accountId, + integration: INTEGRATION, + 'x_source.tid': bidRequest.transactionId, + timeout: bidderRequest.timeout - (Date.now() - bidderRequest.auctionStart + TIMEOUT_BUFFER), + stash_creatives: true, + ae_pass_through_parameters: params.video.aeParams, + slots: [] + }; - // Define the slot object - let slotData = { - site_id: params.siteId, - zone_id: params.zoneId, - position: parsePosition(params.position), - floor: parseFloat(params.floor) > 0.01 ? params.floor : 0.01, - element_id: bidRequest.adUnitCode, - name: bidRequest.adUnitCode, - language: params.video.language, - width: size[0], - height: size[1], - size_id: params.video.size_id - }; + // Define the slot object + let slotData = { + site_id: params.siteId, + zone_id: params.zoneId, + position: parsePosition(params.position), + floor: parseFloat(params.floor) > 0.01 ? params.floor : 0.01, + element_id: bidRequest.adUnitCode, + name: bidRequest.adUnitCode, + language: params.video.language, + width: size[0], + height: size[1], + size_id: params.video.size_id + }; - if (params.inventory && typeof params.inventory === 'object') { - slotData.inventory = params.inventory; - } + if (params.inventory && typeof params.inventory === 'object') { + slotData.inventory = params.inventory; + } - if (params.keywords && Array.isArray(params.keywords)) { - slotData.keywords = params.keywords; - } + if (params.keywords && Array.isArray(params.keywords)) { + slotData.keywords = params.keywords; + } - if (params.visitor && typeof params.visitor === 'object') { - slotData.visitor = params.visitor; - } + if (params.visitor && typeof params.visitor === 'object') { + slotData.visitor = params.visitor; + } - data.slots.push(slotData); + data.slots.push(slotData); - if (gdprConsent) { - // add 'gdpr' only if 'gdprApplies' is defined - if (typeof gdprConsent.gdprApplies === 'boolean') { - data.gdpr = Number(gdprConsent.gdprApplies); - } - data.gdpr_consent = gdprConsent.consentString; + if (bidderRequest.gdprConsent) { + // add 'gdpr' only if 'gdprApplies' is defined + if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { + data.gdpr = Number(bidderRequest.gdprConsent.gdprApplies); } + data.gdpr_consent = bidderRequest.gdprConsent.consentString; + } + + return { + method: 'POST', + url: VIDEO_ENDPOINT, + data, + bidRequest + } + }); + if (config.getConfig('rubicon.singleRequest') !== true) { + // bids are not grouped if single request mode is not enabled + requests = videoRequests.concat(bidRequests.filter(bidRequest => !spec.hasVideoMediaType(bidRequest)).map(bidRequest => { + const bidParams = spec.createSlotParams(bidRequest, bidderRequest); return { - method: 'POST', - url: VIDEO_ENDPOINT, - data, + method: 'GET', + url: FASTLANE_ENDPOINT, + data: Object.keys(bidParams).reduce((paramString, key) => { + const propValue = bidParams[key]; + return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${key}=${encodeURIComponent(propValue)}&` : paramString; + }, '') + `slots=1&rand=${Math.random()}`, bidRequest + }; + })); + } else { + // single request requires bids to be grouped by site id into a single request + // note: utils.groupBy wasn't used because deep property access was needed + const nonVideoRequests = bidRequests.filter(bidRequest => !spec.hasVideoMediaType(bidRequest)); + const groupedBidRequests = nonVideoRequests.reduce((groupedBids, bid) => { + (groupedBids[bid.params['siteId']] = groupedBids[bid.params['siteId']] || []).push(bid); + return groupedBids; + }, {}); + + requests = videoRequests.concat(Object.keys(groupedBidRequests).map(bidGroupKey => { + let bidsInGroup = groupedBidRequests[bidGroupKey]; + + // fastlane SRA has a limit of 10 slots + if (bidsInGroup.length > 10) { + utils.logWarn(`single request mode has a limit of 10 bids: ${bidsInGroup.length - 10} bids were not sent`); + bidsInGroup = bidsInGroup.slice(0, 10); } - } - // non-video request builder - let { - accountId, - siteId, - zoneId, - position, - floor, - keywords, - visitor, - inventory, - userId, - latLong: [latitude, longitude] = [], - } = bidRequest.params; - - // defaults - floor = (floor = parseFloat(floor)) > 0.01 ? floor : 0.01; - position = position || 'btf'; - - // use rubicon sizes if provided, otherwise adUnit.sizes - let parsedSizes = parseSizes(bidRequest); - - // using array to honor ordering. if order isn't important (it shouldn't be), an object would probably be preferable - let data = [ - 'account_id', accountId, - 'site_id', siteId, - 'zone_id', zoneId, - 'size_id', parsedSizes[0], - 'alt_size_ids', parsedSizes.slice(1).join(',') || undefined, - 'p_pos', position, - 'rp_floor', floor, - 'rp_secure', isSecure() ? '1' : '0', - 'tk_flint', INTEGRATION, - 'x_source.tid', bidRequest.transactionId, - 'p_screen_res', _getScreenResolution(), - 'kw', keywords, - 'tk_user_key', userId, - 'p_geo.latitude', isNaN(parseFloat(latitude)) ? undefined : parseFloat(latitude).toFixed(4), - 'p_geo.longitude', isNaN(parseFloat(longitude)) ? undefined : parseFloat(longitude).toFixed(4) - ]; + const combinedSlotParams = spec.combineSlotUrlParams(bidsInGroup.map(bidRequest => { + return spec.createSlotParams(bidRequest, bidderRequest); + })); + // SRA request returns grouped bidRequest arrays not a plain bidRequest + return { + method: 'GET', + url: FASTLANE_ENDPOINT, + data: Object.keys(combinedSlotParams).reduce((paramString, key) => { + const propValue = combinedSlotParams[key]; + return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${key}=${encodeURIComponent(propValue)}&` : paramString; + }, '') + `slots=${bidsInGroup.length}&rand=${Math.random()}`, + bidRequest: bidsInGroup, + }; + })); + } + return requests; + }, - if (gdprConsent) { - // add 'gdpr' only if 'gdprApplies' is defined - if (typeof gdprConsent.gdprApplies === 'boolean') { - data.push('gdpr', Number(gdprConsent.gdprApplies)); + /** + * @summary combines param values from an array of slots into a single semicolon delineated value + * or just one value if they are all the same. + * @param {Object[]} aSlotUrlParams - example [{p1: 'foo', p2: 'test'}, {p2: 'test'}, {p1: 'bar', p2: 'test'}] + * @return {Object} - example {p1: 'foo;;bar', p2: 'test'} + */ + combineSlotUrlParams: function(aSlotUrlParams) { + // if only have params for one slot, return those params + if (aSlotUrlParams.length === 1) { + return aSlotUrlParams[0]; + } + + // reduce param values from all slot objects into an array of values in a single object + const oCombinedSlotUrlParams = aSlotUrlParams.reduce(function(oCombinedParams, oSlotUrlParams, iIndex) { + Object.keys(oSlotUrlParams).forEach(function(param) { + if (!oCombinedParams.hasOwnProperty(param)) { + oCombinedParams[param] = new Array(aSlotUrlParams.length); // initialize array; } - data.push('gdpr_consent', gdprConsent.consentString); - } + // insert into the proper element of the array + oCombinedParams[param].splice(iIndex, 1, oSlotUrlParams[param]); + }); - if (visitor !== null && typeof visitor === 'object') { - utils._each(visitor, (item, key) => data.push(`tg_v.${key}`, item)); - } + return oCombinedParams; + }, {}); - if (inventory !== null && typeof inventory === 'object') { - utils._each(inventory, (item, key) => data.push(`tg_i.${key}`, item)); - } + // convert arrays into semicolon delimited strings + const re = new RegExp('^([^;]*)(;\\1)+$'); // regex to test for duplication - data.push( - 'rand', Math.random(), - 'rf', page_url - ); + Object.keys(oCombinedSlotUrlParams).forEach(function(param) { + const sValues = oCombinedSlotUrlParams[param].join(';'); + // consolidate param values into one value if they are all the same + const match = sValues.match(re); + oCombinedSlotUrlParams[param] = match ? match[1] : sValues; + }); - data = data.concat(_getDigiTrustQueryParams()); + return oCombinedSlotUrlParams; + }, - data = data.reduce( - (memo, curr, index) => - index % 2 === 0 && data[index + 1] !== undefined && !isNaN(data[index + 1]) - ? memo + curr + '=' + encodeURIComponent(data[index + 1]) + '&' : memo, - '' - ).slice(0, -1); // remove trailing & + /** + * @param {BidRequest} bidRequest + * @param {Object} bidderRequest + * @returns {Object} - object key values named and formatted as slot params + */ + createSlotParams: function(bidRequest, bidderRequest) { + bidRequest.startTime = new Date().getTime(); + + const params = bidRequest.params; + + // use rubicon sizes if provided, otherwise adUnit.sizes + const parsedSizes = parseSizes(bidRequest); + + const data = { + 'account_id': params.accountId, + 'site_id': params.siteId, + 'zone_id': params.zoneId, + 'size_id': parsedSizes[0], + 'alt_size_ids': parsedSizes.slice(1).join(',') || undefined, + 'p_pos': parsePosition(params.position), + 'rp_floor': (params.floor = parseFloat(params.floor)) > 0.01 ? params.floor : 0.01, + 'rp_secure': isSecure() ? '1' : '0', + 'tk_flint': INTEGRATION, + 'x_source.tid': bidRequest.transactionId, + 'p_screen_res': _getScreenResolution(), + 'kw': Array.isArray(params.keywords) ? params.keywords.join(',') : '', + 'tk_user_key': params.userId, + 'tg_fl.eid': bidRequest.code, + 'rf': _getPageUrl(bidRequest) + }; + + if (bidderRequest.gdprConsent) { + // add 'gdpr' only if 'gdprApplies' is defined + if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { + data['gdpr'] = Number(bidderRequest.gdprConsent.gdprApplies); + } + data['gdpr_consent'] = bidderRequest.gdprConsent.consentString; + } - return { - method: 'GET', - url: FASTLANE_ENDPOINT, - data, - bidRequest - }; + // visitor properties + if (params.visitor !== null && typeof params.visitor === 'object') { + Object.keys(params.visitor).forEach((key) => { + data[`tg_v.${key}`] = params.visitor[key]; + }); + } + + // inventory properties + if (params.inventory !== null && typeof params.inventory === 'object') { + Object.keys(params.inventory).forEach((key) => { + data[`tg_i.${key}`] = params.inventory[key]; + }); + } + + // digitrust properties + const digitrustParams = _getDigiTrustQueryParams(); + Object.keys(digitrustParams).forEach(paramKey => { + data[paramKey] = digitrustParams[paramKey]; }); + + return data; }, + /** * Test if bid has mediaType or mediaTypes set for video. * note: 'mediaType' has been deprecated, however support will remain for a transitional period @@ -287,22 +349,25 @@ export const spec = { return (typeof utils.deepAccess(bidRequest, 'params.video.size_id') !== 'undefined' && (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}.context`) === 'instream')); }, + /** * @param {*} responseObj - * @param {BidRequest} bidRequest + * @param {BidRequest|Object.} bidRequest - if request was SRA the bidRequest argument will be a keyed BidRequest array object, + * non-SRA responses return a plain BidRequest object * @return {Bid[]} An array of bids which */ interpretResponse: function (responseObj, {bidRequest}) { responseObj = responseObj.body; - let ads = responseObj.ads; // check overall response - if (typeof responseObj !== 'object' || responseObj.status !== 'ok') { + if (!responseObj || typeof responseObj !== 'object') { return []; } + let ads = responseObj.ads; + // video ads array is wrapped in an object - if (typeof bidRequest === 'object' && spec.hasVideoMediaType(bidRequest) && typeof ads === 'object') { + if (typeof bidRequest === 'object' && !Array.isArray(bidRequest) && spec.hasVideoMediaType(bidRequest) && typeof ads === 'object') { ads = ads[bidRequest.adUnitCode]; } @@ -311,54 +376,60 @@ export const spec = { return []; } - // if there are multiple ads, sort by CPM - ads = ads.sort(_adCpmSort); - - return ads.reduce((bids, ad) => { + return ads.reduce((bids, ad, i) => { if (ad.status !== 'ok') { - return []; + return bids; } - let bid = { - requestId: bidRequest.bidId, - currency: 'USD', - creativeId: ad.creative_id, - cpm: ad.cpm || 0, - dealId: ad.deal, - ttl: 300, // 5 minutes - netRevenue: config.getConfig('rubicon.netRevenue') || false, - rubicon: { - advertiserId: ad.advertiser, - networkId: ad.network + // associate bidRequests; assuming ads matches bidRequest + const associatedBidRequest = Array.isArray(bidRequest) ? bidRequest[i] : bidRequest; + + if (associatedBidRequest && typeof associatedBidRequest === 'object') { + let bid = { + requestId: associatedBidRequest.bidId, + currency: 'USD', + creativeId: ad.creative_id, + mediaType: ad.creative_type, + cpm: ad.cpm || 0, + dealId: ad.deal, + ttl: 300, // 5 minutes + netRevenue: config.getConfig('rubicon.netRevenue') || false, + rubicon: { + advertiserId: ad.advertiser, networkId: ad.network + } + }; + + if (ad.creative_type) { + bid.mediaType = ad.creative_type; } - }; - if (ad.creative_type) { - bid.mediaType = ad.creative_type; - } + if (ad.creative_type === VIDEO) { + bid.width = associatedBidRequest.params.video.playerWidth; + bid.height = associatedBidRequest.params.video.playerHeight; + bid.vastUrl = ad.creative_depot_url; + bid.impression_id = ad.impression_id; + bid.videoCacheKey = ad.impression_id; + } else { + bid.ad = _renderCreative(ad.script, ad.impression_id); + [bid.width, bid.height] = sizeMap[ad.size_id].split('x').map(num => Number(num)); + } + + // add server-side targeting + bid.rubiconTargeting = (Array.isArray(ad.targeting) ? ad.targeting : []) + .reduce((memo, item) => { + memo[item.key] = item.values[0]; + return memo; + }, {'rpfl_elemid': associatedBidRequest.adUnitCode}); - if (ad.creative_type === VIDEO) { - bid.width = bidRequest.params.video.playerWidth; - bid.height = bidRequest.params.video.playerHeight; - bid.vastUrl = ad.creative_depot_url; - bid.impression_id = ad.impression_id; - bid.videoCacheKey = ad.impression_id; + bids.push(bid); } else { - bid.ad = _renderCreative(ad.script, ad.impression_id); - [bid.width, bid.height] = sizeMap[ad.size_id].split('x').map(num => Number(num)); + utils.logError(`bidRequest undefined at index position:${i}`, bidRequest, responseObj); } - // add server-side targeting - bid.rubiconTargeting = (Array.isArray(ad.targeting) ? ad.targeting : []) - .reduce((memo, item) => { - memo[item.key] = item.values[0]; - return memo; - }, {'rpfl_elemid': bidRequest.adUnitCode}); - - bids.push(bid); - return bids; - }, []); + }, []).sort((adA, adB) => { + return (adB.cpm || 0.0) - (adA.cpm || 0.0); + }); }, getUserSyncs: function (syncOptions, responses, gdprConsent) { if (!hasSynced && syncOptions.iframeEnabled) { @@ -383,10 +454,6 @@ export const spec = { } }; -function _adCpmSort(adA, adB) { - return (adB.cpm || 0.0) - (adA.cpm || 0.0); -} - function _getScreenResolution() { return [window.screen.width, window.screen.height].join('x'); } @@ -402,11 +469,25 @@ function _getDigiTrustQueryParams() { if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { return []; } - return [ - 'dt.id', digiTrustId.id, - 'dt.keyv', digiTrustId.keyv, - 'dt.pref', 0 - ]; + return { + 'dt.id': digiTrustId.id, + 'dt.keyv': digiTrustId.keyv, + 'dt.pref': 0 + }; +} + +/** + * @param {BidRequest} bidRequest + * @returns {string} + */ +function _getPageUrl(bidRequest) { + let page_url = config.getConfig('pageUrl'); + if (bidRequest.params.referrer) { + page_url = bidRequest.params.referrer; + } else if (!page_url) { + page_url = utils.getTopWindowUrl(); + } + return bidRequest.params.secure ? page_url.replace(/^http:/i, 'https:') : page_url; } function _renderCreative(script, impId) { @@ -490,9 +571,4 @@ export function resetUserSync() { hasSynced = false; } -function isNaN(value) { - // eslint-disable-next-line no-self-compare - return value !== value; -} - registerBidder(spec); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index f0ffee12806..54bb92022a2 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -13,7 +13,118 @@ const INTEGRATION = `pbjs_lite_v$prebid.version$`; // $prebid.version$ will be s describe('the rubicon adapter', () => { let sandbox, - bidderRequest; + bidderRequest, + sizeMap; + + /** + * @typedef {Object} sizeMapConverted + * @property {string} sizeId + * @property {string} size + * @property {Array.} sizeAsArray + * @property {number} width + * @property {number} height + */ + + /** + * @param {Array.} sizesMapConverted + * @param {Object} bid + * @return {sizeMapConverted} + */ + function getSizeIdForBid(sizesMapConverted, bid) { + return sizesMapConverted.find(item => (item.width === bid.width && item.height === bid.height)); + } + + /** + * @param {Array.} ads + * @param {sizeMapConverted} size + * @return {Object} + */ + function getResponseAdBySize(ads, size) { + return ads.find(item => item.size_id === size.sizeId); + } + + /** + * @param {Array.} bidRequests + * @param {sizeMapConverted} size + * @return {BidRequest} + */ + function getBidRequestBySize(bidRequests, size) { + return bidRequests.find(item => item.sizes[0][0] === size.width && item.sizes[0][1] === size.height); + } + + /** + * @typedef {Object} overrideProps + * @property {string} status + * @property {number} cpm + * @property {number} zone_id + * @property {number} ad_id + * @property {string} creative_id + * @property {string} targeting_key - rpfl_{id} + */ + /** + * @param {number} i - index + * @param {string} sizeId - id that maps to size + * @param {Array.} [indexOverMap] + * @return {{status: string, cpm: number, zone_id: *, size_id: *, impression_id: *, ad_id: *, creative_id: string, type: string, targeting: *[]}} + */ + function createResponseAdByIndex(i, sizeId, indexOverMap) { + const overridePropMap = (indexOverMap && indexOverMap[i] && typeof indexOverMap[i] === 'object') ? indexOverMap[i] : {}; + const overrideProps = Object.keys(overridePropMap).reduce((aggregate, key) => { + aggregate[key] = overridePropMap[key]; + return aggregate; + }, {}); + + const getProp = (propName, defaultValue) => { + return (overrideProps[propName]) ? overridePropMap[propName] : defaultValue; + }; + + return { + 'status': getProp('status', 'ok'), + 'cpm': getProp('cpm', i / 100), + 'zone_id': getProp('zone_id', i + 1), + 'size_id': sizeId, + 'impression_id': getProp('impression_id', `1-${i}`), + 'ad_id': getProp('ad_id', i + 1), + 'advertiser': i + 1, + 'network': i + 1, + 'creative_id': getProp('creative_id', `crid-${i}`), + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': i + 1, + 'targeting': [ + { + 'key': getProp('targeting_key', `rpfl_${i}`), + 'values': [ '43_tier_all_test' ] + } + ] + }; + } + + /** + * @param {number} i + * @param {Array.} size + * @return {{ params: {accountId: string, siteId: string, zoneId: string }, adUnitCode: string, code: string, sizes: *[], bidId: string, bidderRequestId: string }} + */ + function createBidRequestByIndex(i, size) { + return { + bidder: 'rubicon', + params: { + accountId: '14062', + siteId: '70608', + zoneId: (i + 1).toString(), + userId: '12346', + position: 'atf', + referrer: 'localhost' + }, + adUnitCode: `/19968336/header-bid-tag-${i}`, + code: `div-${i}`, + sizes: [size], + bidId: i.toString(), + bidderRequestId: i.toString(), + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' + }; + } /** * @param {boolean} [gdprApplies] @@ -72,7 +183,6 @@ describe('the rubicon adapter', () => { 'p_aso.video.ext.skipdelay': '15' } }; - bid.params.secure = false; } function createVideoBidderRequestNoVideo() { @@ -187,6 +297,32 @@ describe('the rubicon adapter', () => { auctionStart: 1472239426000, timeout: 5000 }; + + sizeMap = [ + {sizeId: 1, size: '468x60'}, + {sizeId: 2, size: '728x90'}, + {sizeId: 5, size: '120x90'}, + {sizeId: 8, size: '120x600'}, + {sizeId: 9, size: '160x600'}, + {sizeId: 10, size: '300x600'}, + {sizeId: 13, size: '200x200'}, + {sizeId: 14, size: '250x250'}, + {sizeId: 15, size: '300x250'}, + {sizeId: 16, size: '336x280'}, + {sizeId: 19, size: '300x100'}, + {sizeId: 31, size: '980x120'}, + {sizeId: 32, size: '250x360'} + // Create convenience properties for [sizeAsArray, width, height] by parsing the size string + ].map(item => { + const sizeAsArray = item.size.split('x').map(s => parseInt(s)); + return { + sizeId: item.sizeId, + size: item.size, + sizeAsArray: sizeAsArray.slice(), + width: sizeAsArray[0], + height: sizeAsArray[1] + }; + }); }); afterEach(() => { @@ -240,9 +376,8 @@ describe('the rubicon adapter', () => { 'tg_v.lastsearch': 'iphone', 'tg_i.rating': '5-star', 'tg_i.prodtype': 'tech', - 'rf': 'localhost', - 'p_geo.latitude': '40.7608', - 'p_geo.longitude': '111.8910' + 'tg_fl.eid': 'div-1', + 'rf': 'localhost' }; // test that all values above are both present and correct @@ -338,7 +473,7 @@ describe('the rubicon adapter', () => { bidderRequest.bids[0].params.secure = true; [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - expect(parseQuery(request.data).rf).to.equal('http://www.rubiconproject.com'); + expect(parseQuery(request.data).rf).to.equal('https://www.rubiconproject.com'); }); it('should use rubicon sizes if present (including non-mappable sizes)', () => { @@ -647,6 +782,215 @@ describe('the rubicon adapter', () => { expect(data['gdpr']).to.equal('0'); }); }); + + describe('singleRequest config', () => { + it('should group all bid requests with the same site id', () => { + sandbox.stub(Math, 'random').callsFake(() => 0.1); + + sandbox.stub(config, 'getConfig').callsFake((key) => { + const config = { + 'rubicon.singleRequest': true + }; + return config[key]; + }); + + const expectedQuery = { + 'account_id': '14062', + 'site_id': '70608', + 'zone_id': '335918', + 'size_id': '15', + 'alt_size_ids': '43', + 'p_pos': 'atf', + 'rp_floor': '0.01', + 'rp_secure': /[01]/, + 'rand': '0.1', + 'tk_flint': INTEGRATION, + 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'p_screen_res': /\d+x\d+/, + 'tk_user_key': '12346', + 'kw': 'a,b,c', + 'tg_v.ucat': 'new', + 'tg_v.lastsearch': 'iphone', + 'tg_i.rating': '5-star', + 'tg_i.prodtype': 'tech', + 'tg_fl.eid': 'div-1', + 'rf': 'localhost' + }; + + const bidCopy = clone(bidderRequest.bids[0]); + bidCopy.params.siteId = '70608'; + bidCopy.params.zoneId = '1111'; + bidderRequest.bids.push(bidCopy); + + const bidCopy2 = clone(bidderRequest.bids[0]); + bidCopy2.params.siteId = '99999'; + bidCopy2.params.zoneId = '2222'; + bidderRequest.bids.push(bidCopy2); + + const bidCopy3 = clone(bidderRequest.bids[0]); + bidCopy3.params.siteId = '99999'; + bidCopy3.params.zoneId = '3333'; + bidderRequest.bids.push(bidCopy3); + + const serverRequests = spec.buildRequests(bidderRequest.bids, bidderRequest); + + // array length should match the num of unique 'siteIds' + expect(serverRequests).to.be.a('array'); + expect(serverRequests).to.have.lengthOf(2); + + // collect all bidRequests so order can be checked against the url param slot order + const bidRequests = serverRequests.reduce((aggregator, item) => aggregator.concat(item.bidRequest), []); + let bidRequestIndex = 0; + + serverRequests.forEach(item => { + expect(item).to.be.a('object'); + expect(item).to.have.property('method'); + expect(item).to.have.property('url'); + expect(item).to.have.property('data'); + expect(item).to.have.property('bidRequest'); + + expect(item.method).to.equal('GET'); + expect(item.url).to.equal('//fastlane.rubiconproject.com/a/api/fastlane.json'); + expect(item.data).to.be.a('string'); + + // 'bidRequest' type must be 'array' if SRA enabled + expect(item.bidRequest).to.be.a('array').to.have.lengthOf(2); + + item.bidRequest.forEach((bidRequestItem, i, array) => { + expect(bidRequestItem).to.be.a('object'); + // every 'siteId' values need to match + expect(bidRequestItem.params.siteId).to.equal(array[0].params.siteId); + }); + + const data = parseQuery(item.data); + + Object.keys(expectedQuery).forEach(key => { + expect(data).to.have.property(key); + + // extract semicolon delineated values + const params = data[key].split(';'); + + // skip value test for site and zone ids + if (key !== 'site_id' && key !== 'zone_id') { + if (expectedQuery[key] instanceof RegExp) { + params.forEach(paramItem => { + expect(paramItem).to.match(expectedQuery[key]); + }); + } else { + expect(params).to.contain(expectedQuery[key]); + } + } + + // check parsed url data list order with requestBid list, items must have same index in both lists + if (key === 'zone_id') { + params.forEach((p) => { + expect(bidRequests[bidRequestIndex]).to.be.a('object'); + expect(bidRequests[bidRequestIndex].params).to.be.a('object'); + + // 'zone_id' is used to verify so each bid must have a unique 'zone_id' + expect(p).to.equal(bidRequests[bidRequestIndex].params.zoneId); + + // increment to next bidRequest index having verified that item positions match in url params and bidRequest lists + bidRequestIndex++; + }); + } + }); + }); + }); + + it('should not send more than 10 bids in a request', () => { + sandbox.stub(config, 'getConfig').callsFake((key) => { + const config = { + 'rubicon.singleRequest': true + }; + return config[key]; + }); + + for (let i = 0; i < 20; i++) { + let bidCopy = clone(bidderRequest.bids[0]); + bidCopy.params.zoneId = `${i}0000`; + bidderRequest.bids.push(bidCopy); + } + + const serverRequests = spec.buildRequests(bidderRequest.bids, bidderRequest); + + // if bids are greater than 10, additional bids are dropped + expect(serverRequests[0].bidRequest).to.have.lengthOf(10); + + // check that slots param value matches + const foundSlotsCount = serverRequests[0].data.indexOf('&slots=10&'); + expect(foundSlotsCount !== -1).to.equal(true); + + // check that zone_id has 10 values (since all zone_ids are unique all should exist in get param) + const data = parseQuery(serverRequests[0].data); + + expect(data).to.be.a('object'); + expect(data).to.have.property('zone_id'); + expect(data.zone_id.split(';')).to.have.lengthOf(10); + }); + + it('should not group bid requests if singleRequest does not equal true', () => { + sandbox.stub(config, 'getConfig').callsFake((key) => { + const config = { + 'rubicon.singleRequest': false + }; + return config[key]; + }); + + const bidCopy = clone(bidderRequest.bids[0]); + bidderRequest.bids.push(bidCopy); + + const bidCopy2 = clone(bidderRequest.bids[0]); + bidCopy2.params.siteId = '32001'; + bidderRequest.bids.push(bidCopy2); + + const bidCopy3 = clone(bidderRequest.bids[0]); + bidCopy3.params.siteId = '32001'; + bidderRequest.bids.push(bidCopy3); + + let serverRequests = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(serverRequests).that.is.an('array').of.length(4); + }); + + it('should not group video bid requests', () => { + sandbox.stub(config, 'getConfig').callsFake((key) => { + const config = { + 'rubicon.singleRequest': true + }; + return config[key]; + }); + + const bidCopy = clone(bidderRequest.bids[0]); + bidderRequest.bids.push(bidCopy); + + const bidCopy2 = clone(bidderRequest.bids[0]); + bidCopy2.params.siteId = '32001'; + bidderRequest.bids.push(bidCopy2); + + const bidCopy3 = clone(bidderRequest.bids[0]); + bidCopy3.params.siteId = '32001'; + bidderRequest.bids.push(bidCopy3); + + const bidCopy4 = clone(bidderRequest.bids[0]); + bidCopy4.mediaType = 'video'; + bidCopy4.params.video = { + 'language': 'en', + 'p_aso.video.ext.skip': true, + 'p_aso.video.ext.skipdelay': 15, + 'playerHeight': 320, + 'playerWidth': 640, + 'size_id': 201, + 'aeParams': { + 'p_aso.video.ext.skip': '1', + 'p_aso.video.ext.skipdelay': '15' + } + }; + bidderRequest.bids.push(bidCopy4); + + let serverRequests = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(serverRequests).that.is.an('array').of.length(3); + }); + }); }); describe('for video requests', () => { @@ -672,7 +1016,6 @@ describe('the rubicon adapter', () => { expect(post).to.have.property('timeout').that.is.a('number'); expect(post.timeout < 5000).to.equal(true); expect(post.stash_creatives).to.equal(true); - expect(post.rp_secure).to.equal(false); expect(post.gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); expect(post.gdpr).to.equal(1); @@ -736,7 +1079,6 @@ describe('the rubicon adapter', () => { expect(post).to.have.property('timeout').that.is.a('number'); expect(post.timeout < 5000).to.equal(true); expect(post.stash_creatives).to.equal(true); - expect(post.rp_secure).to.equal(true); expect(post.gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); expect(post.gdpr).to.equal(1); @@ -949,6 +1291,70 @@ describe('the rubicon adapter', () => { }); }); + describe('combineSlotUrlParams', () => { + it('should combine an array of slot url params', () => { + expect(spec.combineSlotUrlParams([])).to.deep.equal({}); + + expect(spec.combineSlotUrlParams([{p1: 'foo', p2: 'test', p3: ''}])).to.deep.equal({p1: 'foo', p2: 'test', p3: ''}); + + expect(spec.combineSlotUrlParams([{}, {p1: 'foo', p2: 'test'}])).to.deep.equal({p1: ';foo', p2: ';test'}); + + expect(spec.combineSlotUrlParams([{}, {}, {p1: 'foo', p2: ''}, {}])).to.deep.equal({p1: ';;foo;', p2: ''}); + + expect(spec.combineSlotUrlParams([{}, {p1: 'foo'}, {p1: ''}])).to.deep.equal({p1: ';foo;'}); + + expect(spec.combineSlotUrlParams([ + {p1: 'foo', p2: 'test'}, + {p2: 'test', p3: 'bar'}, + {p1: 'bar', p2: 'test', p4: 'bar'} + ])).to.deep.equal({p1: 'foo;;bar', p2: 'test', p3: ';bar;', p4: ';;bar'}); + + expect(spec.combineSlotUrlParams([ + {p1: 'foo', p2: 'test', p3: 'baz'}, + {p1: 'foo', p2: 'bar'}, + {p2: 'test'} + ])).to.deep.equal({p1: 'foo;foo;', p2: 'test;bar;test', p3: 'baz;;'}); + }); + }); + + describe('createSlotParams', () => { + it('should return a valid slot params object', () => { + let expectedQuery = { + 'account_id': '14062', + 'site_id': '70608', + 'zone_id': '335918', + 'size_id': 15, + 'alt_size_ids': '43', + 'p_pos': 'atf', + 'rp_floor': 0.01, + 'rp_secure': /[01]/, + 'tk_flint': INTEGRATION, + 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'p_screen_res': /\d+x\d+/, + 'tk_user_key': '12346', + 'kw': 'a,b,c', + 'tg_v.ucat': 'new', + 'tg_v.lastsearch': 'iphone', + 'tg_i.rating': '5-star', + 'tg_i.prodtype': 'tech', + 'tg_fl.eid': 'div-1', + 'rf': 'localhost' + }; + + const slotParams = spec.createSlotParams(bidderRequest.bids[0], bidderRequest); + + // test that all values above are both present and correct + Object.keys(expectedQuery).forEach(key => { + const value = expectedQuery[key]; + if (value instanceof RegExp) { + expect(slotParams[key]).to.match(value); + } else { + expect(slotParams[key]).to.equal(value); + } + }); + }); + }); + describe('hasVideoMediaType', () => { it('should return true if mediaType is video and size_id is set', () => { createVideoBidderRequest(); @@ -1185,6 +1591,183 @@ describe('the rubicon adapter', () => { expect(bids).to.be.lengthOf(0); }); + + it('should handle a bidRequest argument of type Array', () => { + let response = { + 'status': 'ok', + 'account_id': 14062, + 'site_id': 70608, + 'zone_id': 530022, + 'size_id': 15, + 'alt_size_ids': [ + 43 + ], + 'tracking': '', + 'inventory': {}, + 'ads': [{ + 'status': 'ok', + 'cpm': 0, + 'size_id': 15 + }] + }; + + let bids = spec.interpretResponse({ body: response }, { + bidRequest: [clone(bidderRequest.bids[0])] + }); + + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.be.equal(0); + }); + + describe('singleRequest enabled', () => { + it('handles bidRequest of type Array and returns associated adUnits', () => { + const overrideMap = []; + overrideMap[0] = { impression_id: '1' }; + + const stubAds = []; + for (let i = 0; i < 10; i++) { + stubAds.push(createResponseAdByIndex(i, sizeMap[i].sizeId, overrideMap)); + } + + const stubBids = []; + for (let i = 0; i < 10; i++) { + stubBids.push(createBidRequestByIndex(i, sizeMap[i].sizeAsArray.slice())); + } + + const bids = spec.interpretResponse({ + body: { + 'status': 'ok', + 'site_id': '1100', + 'account_id': 14062, + 'zone_id': 2100, + 'size_id': '1', + 'tracking': '', + 'inventory': {}, + 'ads': stubAds + }}, { bidRequest: stubBids }); + expect(bids).to.be.a('array').with.lengthOf(10); + + bids.forEach((bid) => { + expect(bid).to.be.a('object'); + expect(bid).to.have.property('cpm').that.is.a('number'); + expect(bid).to.have.property('width').that.is.a('number'); + expect(bid).to.have.property('height').that.is.a('number'); + + // verify that result bid 'sizeId' links to a size from the sizeMap + const size = getSizeIdForBid(sizeMap, bid); + expect(size).to.be.a('object'); + + // use 'size' to verify that result bid links to the 'response.ad' passed to function + const associateAd = getResponseAdBySize(stubAds, size); + expect(associateAd).to.be.a('object'); + expect(associateAd).to.have.property('creative_id').that.is.a('string'); + + // use 'size' to verify that result bid links to the 'bidRequest' passed to function + const associateBidRequest = getBidRequestBySize(stubBids, size); + expect(associateBidRequest).to.be.a('object'); + expect(associateBidRequest).to.have.property('bidId').that.is.a('string'); + + // verify all bid properties set using 'ad' and 'bidRequest' match + // 'ad.creative_id === bid.creativeId' + expect(bid.requestId).to.equal(associateBidRequest.bidId); + // 'bid.requestId === bidRequest.bidId' + expect(bid.creativeId).to.equal(associateAd.creative_id); + }); + }); + + it('handles incorrect adUnits length by returning all bids with matching ads', () => { + const overrideMap = []; + overrideMap[0] = { impression_id: '1' }; + + const stubAds = []; + for (let i = 0; i < 6; i++) { + stubAds.push(createResponseAdByIndex(i, sizeMap[i].sizeId, overrideMap)); + } + + const stubBids = []; + for (let i = 0; i < 10; i++) { + stubBids.push(createBidRequestByIndex(i, sizeMap[i].sizeAsArray.slice())); + } + + const bids = spec.interpretResponse({ + body: { + 'status': 'ok', + 'site_id': '1100', + 'account_id': 14062, + 'zone_id': 2100, + 'size_id': '1', + 'tracking': '', + 'inventory': {}, + 'ads': stubAds + }}, { bidRequest: stubBids }); + + // no bids expected because response didn't match requested bid number + expect(bids).to.be.a('array').with.lengthOf(6); + }); + + it('skips adUnits with error status and returns all bids with ok status', () => { + const stubAds = []; + // Create overrides to break associations between bids and ads + // Each override should cause one less bid to be returned by interpretResponse + const overrideMap = []; + overrideMap[0] = { impression_id: '1' }; + overrideMap[2] = { status: 'error' }; + overrideMap[4] = { status: 'error' }; + overrideMap[7] = { status: 'error' }; + overrideMap[8] = { status: 'error' }; + + for (let i = 0; i < 10; i++) { + stubAds.push(createResponseAdByIndex(i, sizeMap[i].sizeId, overrideMap)); + } + + const stubBids = []; + for (let i = 0; i < 10; i++) { + stubBids.push(createBidRequestByIndex(i, sizeMap[i].sizeAsArray.slice())); + } + + const bids = spec.interpretResponse({ + body: { + 'status': 'error', + 'site_id': '1100', + 'account_id': 14062, + 'zone_id': 2100, + 'size_id': '1', + 'tracking': '', + 'inventory': {}, + 'ads': stubAds + }}, { bidRequest: stubBids }); + expect(bids).to.be.a('array').with.lengthOf(6); + + bids.forEach((bid) => { + expect(bid).to.be.a('object'); + expect(bid).to.have.property('cpm').that.is.a('number'); + expect(bid).to.have.property('width').that.is.a('number'); + expect(bid).to.have.property('height').that.is.a('number'); + + // verify that result bid 'sizeId' links to a size from the sizeMap + const size = getSizeIdForBid(sizeMap, bid); + expect(size).to.be.a('object'); + + // use 'size' to verify that result bid links to the 'response.ad' passed to function + const associateAd = getResponseAdBySize(stubAds, size); + expect(associateAd).to.be.a('object'); + expect(associateAd).to.have.property('creative_id').that.is.a('string'); + expect(associateAd).to.have.property('status').that.is.a('string'); + expect(associateAd.status).to.equal('ok'); + + // use 'size' to verify that result bid links to the 'bidRequest' passed to function + const associateBidRequest = getBidRequestBySize(stubBids, size); + expect(associateBidRequest).to.be.a('object'); + expect(associateBidRequest).to.have.property('bidId').that.is.a('string'); + + // verify all bid properties set using 'ad' and 'bidRequest' match + // 'ad.creative_id === bid.creativeId' + expect(bid.requestId).to.equal(associateBidRequest.bidId); + // 'bid.requestId === bidRequest.bidId' + expect(bid.creativeId).to.equal(associateAd.creative_id); + }); + }); + }); }); describe('for video', () => { From 44305d2cd360495834133ba8ad96aab2b610dc20 Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 23 May 2018 18:55:47 -0400 Subject: [PATCH 0388/1594] Sonobi Adapter GDPR Support (#2582) * return null from buildRequests if there is no keymakers * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * Add gdpr support --- modules/sonobiBidAdapter.js | 10 +++++++-- test/spec/modules/sonobiBidAdapter_spec.js | 26 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index a8b5bd13e05..e66a1aa2606 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -24,7 +24,7 @@ export const spec = { * @param {BidRequest[]} validBidRequests - an array of bids * @return {object} ServerRequest - Info describing the request to the server. */ - buildRequests: (validBidRequests) => { + buildRequests: (validBidRequests, bidderRequest) => { const bids = validBidRequests.map(bid => { let slotIdentifier = _validateSlot(bid); if (/^[\/]?[\d]+[[\/].+[\/]?]?$/.test(slotIdentifier)) { @@ -61,7 +61,13 @@ export const spec = { payload.ref = validBidRequests[0].params.referrer; } - // If there is no key_maker data, then dont make the request. + // Apply GDPR parameters to request. + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr = bidderRequest.gdprConsent.gdprApplies ? 'true' : 'false'; + payload.consent_string = bidderRequest.gdprConsent.consentString; + } + + // If there is no key_maker data, then don't make the request. if (isEmpty(data)) { return null; } diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 431bf134349..d92553d6661 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -130,6 +130,14 @@ describe('SonobiBidAdapter', () => { '/7780971/sparks_prebid_LB|30b31c1838de1e': '300x250,300x600', }; + let bidderRequests = { + 'gdprConsent': { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'vendorData': {}, + 'gdprApplies': true + }, + }; + it('should return a properly formatted request', () => { const bidRequests = spec.buildRequests(bidRequest) const bidRequestsPageViewID = spec.buildRequests(bidRequest) @@ -145,6 +153,23 @@ describe('SonobiBidAdapter', () => { expect(['mobile', 'tablet', 'desktop']).to.contain(bidRequests.data.vp); }) + it('should return a properly formatted request with GDPR applies set to true', () => { + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.gdpr).to.equal('true') + expect(bidRequests.data.consent_string).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==') + }) + + it('should return a properly formatted request with GDPR applies set to false', () => { + bidderRequests.gdprConsent.gdprApplies = false; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.gdpr).to.equal('false') + expect(bidRequests.data.consent_string).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==') + }) + it('should return a properly formatted request with hfa', () => { bidRequest[0].params.hfa = 'hfakey' bidRequest[1].params.hfa = 'hfakey' @@ -155,6 +180,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.s).not.to.be.empty expect(bidRequests.data.hfa).to.equal('hfakey') }) + it('should return null if there is nothing to bid on', () => { const bidRequests = spec.buildRequests([{params: {}}]) expect(bidRequests).to.equal(null); From ee0ff04e87cf2de37e1822317fbe2782f4e2898b Mon Sep 17 00:00:00 2001 From: rcheptanariu <35690143+rcheptanariu@users.noreply.github.com> Date: Thu, 24 May 2018 02:09:36 +0300 Subject: [PATCH 0389/1594] Invibes Bid Adapter - cookies update & user sync (#2512) --- modules/invibesBidAdapter.js | 182 +++++++++++++------- test/spec/modules/invibesBidAdapter_spec.js | 54 ++++-- 2 files changed, 162 insertions(+), 74 deletions(-) diff --git a/modules/invibesBidAdapter.js b/modules/invibesBidAdapter.js index ab6f7c4898b..eefe63034bd 100644 --- a/modules/invibesBidAdapter.js +++ b/modules/invibesBidAdapter.js @@ -34,11 +34,14 @@ export const spec = { interpretResponse: function (responseObj, requestParams) { return handleResponse(responseObj, requestParams != null ? requestParams.bidRequests : null); }, - getUserSyncs: function(syncOptions) { + getUserSyncs: function (syncOptions) { if (syncOptions.iframeEnabled) { + handlePostMessage(); + const syncUrl = buildSyncUrl(); + return { type: 'iframe', - url: CONSTANTS.SYNC_ENDPOINT + url: syncUrl }; } } @@ -46,6 +49,11 @@ export const spec = { registerBidder(spec); +// some state info is required: cookie info, unique user visit id +const topWin = getTopMostWindow(); +let invibes = topWin.invibes = topWin.invibes || {}; +let _customUserSync; + function isBidRequestValid(bid) { if (typeof bid.params !== 'object') { return false; @@ -62,7 +70,7 @@ function isBidRequestValid(bid) { function buildRequest(bidRequests, auctionStart) { // invibes only responds to 1 bid request for each user visit const _placementIds = []; - let _loginId, _customEndpoint, _bidContainerId; + let _loginId, _customEndpoint; let _ivAuctionStart = auctionStart || Date.now(); bidRequests.forEach(function (bidRequest) { @@ -70,15 +78,16 @@ function buildRequest(bidRequests, auctionStart) { _placementIds.push(bidRequest.params.placementId); _loginId = _loginId || bidRequest.params.loginId; _customEndpoint = _customEndpoint || bidRequest.params.customEndpoint; - _bidContainerId = _bidContainerId || bidRequest.params.adContainerId || bidRequest.params.bidContainerId; + _customUserSync = _customUserSync || bidRequest.params.customUserSync; }); - const topWin = getTopMostWindow(); - const invibes = topWin.invibes = topWin.invibes || {}; invibes.visitId = invibes.visitId || generateRandomId(); - invibes.bidContainerId = invibes.bidContainerId || _bidContainerId; - initDomainId(invibes); + cookieDomain = detectTopmostCookieDomain(); + invibes.noCookies = invibes.noCookies || invibes.getCookie('ivNoCookie'); + invibes.optIn = invibes.optIn || invibes.getCookie('ivOptIn'); + + initDomainId(); const currentQueryStringParams = parseQueryStringParams(); @@ -86,13 +95,12 @@ function buildRequest(bidRequests, auctionStart) { location: getDocumentLocation(topWin), videoAdHtmlId: generateRandomId(), showFallback: currentQueryStringParams['advs'] === '0', - ivbsCampIdsLocal: getCookie('IvbsCampIdsLocal'), + ivbsCampIdsLocal: invibes.getCookie('IvbsCampIdsLocal'), lId: invibes.dom.id, bidParamsJson: JSON.stringify({ placementIds: _placementIds, loginId: _loginId, - bidContainerId: _bidContainerId, auctionStartTime: _ivAuctionStart, bidVersion: CONSTANTS.PREBID_VERSION }), @@ -100,9 +108,15 @@ function buildRequest(bidRequests, auctionStart) { vId: invibes.visitId, width: topWin.innerWidth, - height: topWin.innerHeight + height: topWin.innerHeight, + + noc: !cookieDomain }; + if (invibes.optIn) { + data.oi = 1; + } + const parametersToPassForward = 'videoaddebug,advs,bvci,bvid,istop,trybvid,trybvci'.split(','); for (let key in currentQueryStringParams) { if (currentQueryStringParams.hasOwnProperty(key)) { @@ -143,9 +157,6 @@ function handleResponse(responseObj, bidRequests) { return []; } - const topWin = getTopMostWindow(); - const invibes = topWin.invibes = topWin.invibes || {}; - if (typeof invibes.bidResponse === 'object') { utils.logInfo('Invibes Adapter - Bid response already received. Invibes only responds to one bid request per user visit'); return []; @@ -191,8 +202,7 @@ function handleResponse(responseObj, bidRequests) { }); const now = Date.now(); - invibes.ivLogger = invibes.ivLogger || initLogger(); - invibes.ivLogger.info('Bid auction started at ' + bidModel.AuctionStartTime + ' . Invibes registered the bid at ' + now + ' ; bid request took a total of ' + (now - bidModel.AuctionStartTime) + ' ms.'); + ivLogger.info('Bid auction started at ' + bidModel.AuctionStartTime + ' . Invibes registered the bid at ' + now + ' ; bid request took a total of ' + (now - bidModel.AuctionStartTime) + ' ms.'); } else { utils.logInfo('Invibes Adapter - Incorrect Placement Id: ' + bidRequest.params.placementId); } @@ -300,9 +310,9 @@ function getCappedCampaignsAsString() { .join(','); } -function initLogger() { - const noop = function () { }; +const noop = function () { }; +function initLogger() { if (localStorage && localStorage.InvibesDEBUG) { return window.console; } @@ -310,25 +320,59 @@ function initLogger() { return { info: noop, error: noop, log: noop, warn: noop, debug: noop }; } +function buildSyncUrl() { + let syncUrl = _customUserSync || CONSTANTS.SYNC_ENDPOINT; + syncUrl += '?visitId=' + invibes.visitId; + + if (invibes.optIn) { + syncUrl += '&optIn=1'; + } + + const did = invibes.getCookie('ivbsdid'); + if (did) { + syncUrl += '&ivbsdid=' + encodeURIComponent(did); + } + + const bks = invibes.getCookie('ivvbks'); + if (bks) { + syncUrl += '&ivvbks=' + encodeURIComponent(bks); + } + + return syncUrl; +} + +function handlePostMessage() { + try { + if (window.addEventListener) { + window.addEventListener('message', acceptPostMessage); + } + } catch (e) { } +} + +function acceptPostMessage(e) { + let msg = e.data || {}; + if (msg.ivbscd === 1) { + invibes.setCookie(msg.name, msg.value, msg.exdays, msg.domain); + } else if (msg.ivbscd === 2) { + invibes.dom.graduate(); + } +} + +const ivLogger = initLogger(); + /// Local domain cookie management ===================== -let Uid = { +invibes.Uid = { generate: function () { - let date = new Date().getTime(); - if (date > 151 * 10e9) { - let datePart = Math.floor(date / 1000).toString(36); - let maxRand = parseInt('zzzzzz', 36) - let randPart = Math.floor(Math.random() * maxRand).toString(36); - return datePart + '.' + randPart; - } - }, - getCrTime: function (s) { - let toks = s.split('.'); - return parseInt(toks[0] || 0, 36) * 1e3; + let maxRand = parseInt('zzzzzz', 36) + let mkRand = function () { return Math.floor(Math.random() * maxRand).toString(36); }; + let rand1 = mkRand(); + let rand2 = mkRand(); + return rand1 + rand2; } }; -let cookieDomain, noCookies; -function getCookie(name) { +let cookieDomain; +invibes.getCookie = function (name) { let i, x, y; let cookies = document.cookie.split(';'); for (i = 0; i < cookies.length; i++) { @@ -341,8 +385,9 @@ function getCookie(name) { } }; -function setCookie(name, value, exdays, domain) { - if (noCookies && name != 'ivNoCookie' && (exdays || 0) >= 0) { return; } +invibes.setCookie = function (name, value, exdays, domain) { + let whiteListed = name == 'ivNoCookie' || name == 'IvbsCampIdsLocal'; + if (invibes.noCookies && !whiteListed && (exdays || 0) >= 0) { return; } if (exdays > 365) { exdays = 365; } domain = domain || cookieDomain; let exdate = new Date(); @@ -354,86 +399,101 @@ function setCookie(name, value, exdays, domain) { }; let detectTopmostCookieDomain = function () { - let testCookie = Uid.generate(); + let testCookie = invibes.Uid.generate(); let hostParts = location.host.split('.'); if (hostParts.length === 1) { return location.host; } for (let i = hostParts.length - 1; i >= 0; i--) { let domain = '.' + hostParts.slice(i).join('.'); - setCookie(testCookie, testCookie, 1, domain); - let val = getCookie(testCookie); + invibes.setCookie(testCookie, testCookie, 1, domain); + let val = invibes.getCookie(testCookie); if (val === testCookie) { - setCookie(testCookie, testCookie, -1, domain); + invibes.setCookie(testCookie, testCookie, -1, domain); return domain; } } }; -cookieDomain = detectTopmostCookieDomain(); -noCookies = getCookie('ivNoCookie'); -function initDomainId(invibes, persistence) { - if (typeof invibes.dom === 'object') { - return; - } +let initDomainId = function (options) { + if (invibes.dom) { return; } + + options = options || {}; let cookiePersistence = { cname: 'ivbsdid', load: function () { - let str = getCookie(this.cname) || ''; + let str = invibes.getCookie(this.cname) || ''; try { return JSON.parse(str); } catch (e) { } }, save: function (obj) { - setCookie(this.cname, JSON.stringify(obj), 365); + invibes.setCookie(this.cname, JSON.stringify(obj), 365); } }; - persistence = persistence || cookiePersistence; + let persistence = options.persistence || cookiePersistence; let state; - const minHC = 5; + let minHC = 7; - let validGradTime = function (d) { - const min = 151 * 10e9; - let yesterday = new Date().getTime() - 864 * 10e4 - return d > min && d < yesterday; + let validGradTime = function (state) { + if (!state.cr) { return false; } + let min = 151 * 10e9; + if (state.cr < min) { + return false; + } + let now = new Date().getTime(); + let age = now - state.cr; + let minAge = 24 * 60 * 60 * 1000; + return age > minAge; }; state = persistence.load() || { - id: Uid.generate(), + id: invibes.Uid.generate(), + cr: new Date().getTime(), hc: 1, - temp: 1 }; + if (state.id.match(/\./)) { + state.id = invibes.Uid.generate(); + } + let graduate; let setId = function () { invibes.dom = { - id: state.temp ? undefined : state.id, - tempId: state.id, + id: !state.cr && invibes.optIn ? state.id : undefined, + tempId: invibes.optIn ? state.id : undefined, graduate: graduate }; }; graduate = function () { - if (!state.temp) { return; } - delete state.temp; + if (!state.cr) { return; } + delete state.cr; delete state.hc; persistence.save(state); setId(); } - if (state.temp) { + if (state.cr && !options.noVisit) { if (state.hc < minHC) { state.hc++; } - if (state.hc >= minHC && validGradTime(Uid.getCrTime(state.id))) { + if (state.hc >= minHC && validGradTime(state)) { graduate(); } } - persistence.save(state); setId(); + ivLogger.info('Did=' + invibes.dom.id); }; // ===================== + +export function resetInvibes() { + invibes.optIn = undefined; + invibes.noCookies = undefined; + invibes.dom = undefined; + invibes.bidResponse = undefined; +} diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js index 646448bd5a7..f6f601e0efc 100644 --- a/test/spec/modules/invibesBidAdapter_spec.js +++ b/test/spec/modules/invibesBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec } from 'modules/invibesBidAdapter'; +import { spec, resetInvibes } from 'modules/invibesBidAdapter'; describe('invibesBidAdapter:', function () { const BIDDER_CODE = 'invibes'; @@ -41,7 +41,7 @@ describe('invibesBidAdapter:', function () { ]; beforeEach(function () { - top.window.invibes = null; + resetInvibes(); document.cookie = ''; this.cStub1 = sinon.stub(console, 'info'); }); @@ -120,30 +120,47 @@ describe('invibesBidAdapter:', function () { expect(request.data.lId).to.be.undefined; }); - it('does not overwrite the domain id', () => { - top.window.invibes = window.invibes || {}; - top.window.invibes.dom = {}; - let request = spec.buildRequests(bidRequests); - }); - it('doesnt send the domain id if not graduated', () => { - global.document.cookie = 'ivbsdid={"id":"p4vauj.4ekt9w","hc":3,"temp":1}'; + global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1522929537626,"hc":1}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.not.exist; }); it('graduate and send the domain id', () => { - global.document.cookie = 'ivbsdid={"id":"p4rrk7.ax2i2s","hc":4,"temp":1}'; + top.window.invibes.optIn = 1; + global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":7}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.exist; }); it('send the domain id if already graduated', () => { - global.document.cookie = 'ivbsdid={"id":"p4rrk7.ax2i2s"}'; + top.window.invibes.optIn = 1; + global.document.cookie = 'ivbsdid={"id":"f8zoh044p9oi"}'; + let request = spec.buildRequests(bidRequests); + expect(request.data.lId).to.exist; + }); + + it('send the domain id after replacing it with new format', () => { + top.window.invibes.optIn = 1; + global.document.cookie = 'ivbsdid={"id":"f8zoh044p9oi.8537626"}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.exist; }); - }) + + it('try to graduate but not enough count - doesnt send the domain id', () => { + top.window.invibes.optIn = 1; + global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":5}'; + let request = spec.buildRequests(bidRequests); + expect(request.data.lId).to.not.exist; + }); + + it('try to graduate but not old enough - doesnt send the domain id', () => { + top.window.invibes.optIn = 1; + global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":' + Date.now() + ',"hc":5}'; + let request = spec.buildRequests(bidRequests); + expect(request.data.lId).to.not.exist; + }); + }); describe('interpretResponse', function () { let response = { @@ -238,7 +255,18 @@ describe('invibesBidAdapter:', function () { it('returns an iframe if enabled', () => { let response = spec.getUserSyncs({iframeEnabled: true}); expect(response.type).to.equal('iframe'); - expect(response.url).to.equal(SYNC_ENDPOINT); + expect(response.url).to.include(SYNC_ENDPOINT); + }); + + it('returns an iframe with params if enabled', () => { + top.window.invibes.optIn = 1; + global.document.cookie = 'ivvbks=17639.0,1,2'; + let response = spec.getUserSyncs({ iframeEnabled: true }); + expect(response.type).to.equal('iframe'); + expect(response.url).to.include(SYNC_ENDPOINT); + expect(response.url).to.include('optIn'); + expect(response.url).to.include('ivvbks'); + expect(response.url).to.include('ivbsdid'); }); it('returns undefined if iframe not enabled ', () => { From 2a6e5f49a17ca72eab82536aa926b8b043f687fb Mon Sep 17 00:00:00 2001 From: reynold-cox Date: Wed, 23 May 2018 16:28:42 -0700 Subject: [PATCH 0390/1594] Update Cox Bid Adapter For 1.0+ (#2446) * Bid adapter for 1.0+ * Tests for cox bid adapter * Corrected how state is handled * Added test for multiple bids --- modules/coxBidAdapter.js | 165 +++++++++++++++++ modules/coxBidAdapter.md | 41 +++++ test/spec/modules/coxBidAdapter_spec.js | 233 ++++++++++++++++++++++++ 3 files changed, 439 insertions(+) create mode 100644 modules/coxBidAdapter.js create mode 100644 modules/coxBidAdapter.md create mode 100644 test/spec/modules/coxBidAdapter_spec.js diff --git a/modules/coxBidAdapter.js b/modules/coxBidAdapter.js new file mode 100644 index 00000000000..eac1b2081d2 --- /dev/null +++ b/modules/coxBidAdapter.js @@ -0,0 +1,165 @@ +'use strict'; + +import * as utils from 'src/utils'; +import { BANNER } from 'src/mediaTypes'; +import { config } from 'src/config'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const helper = (() => { + let srTestCapabilities = () => { // Legacy + let plugins = navigator.plugins; + let flashVer = -1; + let sf = 'Shockwave Flash'; + + if (plugins && plugins.length > 0) { + if (plugins[sf + ' 2.0'] || plugins[sf]) { + var swVer2 = plugins[sf + ' 2.0'] ? ' 2.0' : ''; + var flashDescription = plugins[sf + swVer2].description; + flashVer = flashDescription.split(' ')[2].split('.')[0]; + } + } + if (flashVer > 4) return 15; else return 7; + }; + + let getRand = () => { + return Math.round(Math.random() * 100000000); + }; + + return { + ingest: function(rawBids = []) { + const adZoneAttributeKeys = ['id', 'size', 'thirdPartyClickUrl', 'dealId']; + const otherKeys = ['siteId', 'wrapper', 'referrerUrl']; + let state = this.createState(); + + rawBids.forEach(oneBid => { + let params = oneBid.params || {}; + + state.tag.auctionId = oneBid.auctionId; + state.tag.responseJSON = true; + + if (params.id && (/^\d+x\d+$/).test(params.size)) { + let adZoneKey = 'as' + params.id; + let zone = {}; + + zone.transactionId = oneBid.transactionId; + zone.bidId = oneBid.bidId; + state.tag.zones = state.tag.zones || {}; + state.tag.zones[adZoneKey] = zone; + + adZoneAttributeKeys.forEach(key => { if (params[key]) zone[key] = params[key]; }); + otherKeys.forEach(key => { if (params[key]) state.tag[key] = params[key]; }); + + // Check for an environment setting + if (params.env) state.env = params.env; + + // Update the placement map + let [x, y] = (params.size).split('x'); + state.placementMap[adZoneKey] = { + 'b': oneBid.bidId, + 'w': x, + 'h': y + }; + } + }); + return state; + }, + + transform: function(coxRawBids = {}, state) { + const pbjsBids = []; + + for (let adZoneKey in state.placementMap) { + let responded = coxRawBids[adZoneKey] + let ingested = state.placementMap[adZoneKey]; + + utils.logInfo('coxBidAdapter.transform', adZoneKey, responded, ingested); + + if (ingested && responded && responded['ad'] && responded['price'] > 0) { + pbjsBids.push({ + requestId: ingested['b'], + cpm: responded['price'], + width: ingested['w'], + height: ingested['h'], + creativeId: responded['adid'], + dealId: responded['dealid'], + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: responded['ad'] + }); + } + } + return pbjsBids; + }, + + getUrl: state => { + // Bounce if the tag is invalid + if (!state.tag.zones) return null; + + let src = (document.location.protocol === 'https:' ? 'https://' : 'http://') + + (!state.env || state.env === 'PRD' ? '' : state.env === 'PPE' ? 'ppe-' : state.env === 'STG' ? 'staging-' : '') + + 'ad.afy11.net/ad?mode=11&nif=0&sf=0&sfd=0&ynw=0&hb=1' + + '&ct=' + srTestCapabilities() + + '&rand=' + getRand() + + '&rk1=' + getRand() + + '&rk2=' + new Date().valueOf() / 1000; + + state.tag.pageUrl = config.getConfig('pageUrl') || utils.getTopWindowUrl(); + state.tag.puTop = true; + + // Attach the serialized tag to our string + src += '&ab=' + encodeURIComponent(JSON.stringify(state.tag)); + + return src; + }, + + createState: () => ({ + env: '', + tag: {}, + placementMap: {} + }) + }; +})(); + +export const spec = { + code: 'cox', + supportedMediaTypes: [BANNER], + + isBidRequestValid: function(bid) { + return !!(bid.params && bid.params.id && bid.params.size); + }, + + buildRequests: function(validBidReqs) { + let state = helper.ingest(validBidReqs); + let url = helper.getUrl(state); + + return !url ? {} : { + method: 'GET', + url: url, + state + }; + }, + + interpretResponse: function({ body: { zones: coxRawBids } }, { state }) { + let bids = helper.transform(coxRawBids, state); + + utils.logInfo('coxBidAdapter.interpretResponse', bids); + return bids; + }, + + getUserSyncs: function(syncOptions, thing) { + try { + var [{ body: { tpCookieSync: urls = [] } }] = thing; + } catch (ignore) { + return []; + } + + let syncs = []; + if (syncOptions.pixelEnabled && urls.length > 0) { + syncs = urls.map((url) => ({ type: 'image', url: url })) + } + utils.logInfo('coxBidAdapter.getuserSyncs', syncs); + return syncs; + } +}; + +registerBidder(spec); diff --git a/modules/coxBidAdapter.md b/modules/coxBidAdapter.md new file mode 100644 index 00000000000..f4460b969ed --- /dev/null +++ b/modules/coxBidAdapter.md @@ -0,0 +1,41 @@ +# Overview + +``` +Module Name: Cox/COMET Bid Adapter +Module Type: Bidder Adapter +Maintainer: reynold@coxds.com +``` + +# Description + +Cox/COMET's adapter integration to the Prebid library. + +# Test Parameters + +``` +var adUnits = [ + { + code: 'test-leaderboard', + sizes: [[728, 90]], + bids: [{ + bidder: 'cox', + params: { + size: '728x90', + id: 2000005991607, + siteId: 2000100948180, + } + }] + }, { + code: 'test-banner', + sizes: [[300, 250]], + bids: [{ + bidder: 'cox', + params: { + size: '300x250', + id: 2000005991707, + siteId: 2000100948180, + } + }] + } +] +``` \ No newline at end of file diff --git a/test/spec/modules/coxBidAdapter_spec.js b/test/spec/modules/coxBidAdapter_spec.js new file mode 100644 index 00000000000..9dd5a5a92b4 --- /dev/null +++ b/test/spec/modules/coxBidAdapter_spec.js @@ -0,0 +1,233 @@ +import { expect } from 'chai'; +import { spec } from 'modules/coxBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +describe('CoxBidAdapter', () => { + const adapter = newBidder(spec); + + describe('isBidRequestValid', () => { + const CONFIG = { + 'bidder': 'cox', + 'params': { + 'id': '8888', + 'siteId': '1000', + 'size': '300x250' + } + }; + + it('should return true when required params present', () => { + expect(spec.isBidRequestValid(CONFIG)).to.equal(true); + }); + + it('should return false when id param is missing', () => { + let config = deepClone(CONFIG); + config.params.id = null; + + expect(spec.isBidRequestValid(config)).to.equal(false); + }); + + it('should return false when size param is missing', () => { + let config = deepClone(CONFIG); + config.params.size = null; + + expect(spec.isBidRequestValid(config)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const PROD_DOMAIN = 'ad.afy11.net'; + const PPE_DOMAIN = 'ppe-ad.afy11.net'; + const STG_DOMAIN = 'staging-ad.afy11.net'; + + const BID_INFO = [{ + 'bidder': 'cox', + 'params': { + 'id': '8888', + 'siteId': '1000', + 'size': '300x250' + }, + 'sizes': [[300, 250]], + 'transactionId': 'tId-foo', + 'bidId': 'bId-bar' + }]; + + it('should send bid request to PROD_DOMAIN via GET', () => { + let request = spec.buildRequests(BID_INFO); + expect(request.url).to.have.string(PROD_DOMAIN); + expect(request.method).to.equal('GET'); + }); + + it('should send bid request to PPE_DOMAIN when configured', () => { + let clone = deepClone(BID_INFO); + clone[0].params.env = 'PPE'; + + let request = spec.buildRequests(clone); + expect(request.url).to.have.string(PPE_DOMAIN); + }); + + it('should send bid request to STG_DOMAIN when configured', () => { + let clone = deepClone(BID_INFO); + clone[0].params.env = 'STG'; + + let request = spec.buildRequests(clone); + expect(request.url).to.have.string(STG_DOMAIN); + }); + + it('should return empty when id is invalid', () => { + let clone = deepClone(BID_INFO); + clone[0].params.id = null; + + let request = spec.buildRequests(clone); + expect(request).to.be.an('object').that.is.empty; + }); + + it('should return empty when size is invalid', () => { + let clone = deepClone(BID_INFO); + clone[0].params.size = 'FOO'; + + let request = spec.buildRequests(clone); + expect(request).to.be.an('object').that.is.empty; + }); + }) + + describe('interpretResponse', () => { + const BID_INFO_1 = [{ + 'bidder': 'cox', + 'params': { + 'id': '2000005657007', + 'siteId': '2000101880180', + 'size': '728x90' + }, + 'transactionId': 'foo_1', + 'bidId': 'bar_1' + }]; + + const BID_INFO_2 = [{ + 'bidder': 'cox', + 'params': { + 'id': '2000005658887', + 'siteId': '2000101880180', + 'size': '300x250' + }, + 'transactionId': 'foo_2', + 'bidId': 'bar_2' + }]; + + const RESPONSE_1 = { body: { + 'zones': { + 'as2000005657007': { + 'price': 1.88, + 'dealid': 'AA128460', + 'ad': '

2000005657007
728x90

', + 'adid': '7007-728-90' + }}}}; + + const RESPONSE_2 = { body: { + 'zones': { + 'as2000005658887': { + 'price': 2.88, + 'ad': '

2000005658887
300x250

', + 'adid': '888-88' + }}}}; + + const PBJS_BID_1 = { + 'requestId': 'bar_1', + 'cpm': 1.88, + 'width': '728', + 'height': '90', + 'creativeId': '7007-728-90', + 'dealId': 'AA128460', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'ad': '

2000005657007
728x90

' + }; + + const PBJS_BID_2 = { + 'requestId': 'bar_2', + 'cpm': 2.88, + 'width': '300', + 'height': '250', + 'creativeId': '888-88', + 'dealId': undefined, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'ad': '

2000005658887
300x250

' + }; + + it('should return correct pbjs bid', () => { + let result = spec.interpretResponse(RESPONSE_2, spec.buildRequests(BID_INFO_2)); + expect(result[0]).to.eql(PBJS_BID_2); + }); + + it('should handle multiple bid instances', () => { + let request1 = spec.buildRequests(BID_INFO_1); + let request2 = spec.buildRequests(BID_INFO_2); + + let result2 = spec.interpretResponse(RESPONSE_2, request2); + expect(result2[0]).to.eql(PBJS_BID_2); + + let result1 = spec.interpretResponse(RESPONSE_1, request1); + expect(result1[0]).to.eql(PBJS_BID_1); + }); + + it('should return empty when price is zero', () => { + let clone = deepClone(RESPONSE_1); + clone.body.zones.as2000005657007.price = 0; + + let result = spec.interpretResponse(clone, spec.buildRequests(BID_INFO_1)); + expect(result).to.be.an('array').that.is.empty; + }); + + it('should return empty when there is no ad', () => { + let clone = deepClone(RESPONSE_1); + clone.body.zones.as2000005657007.ad = null; + + let result = spec.interpretResponse(clone, spec.buildRequests(BID_INFO_1)); + expect(result).to.be.an('array').that.is.empty; + }); + + it('should return empty when there is no ad unit info', () => { + let clone = deepClone(RESPONSE_1); + delete (clone.body.zones.as2000005657007); + + let result = spec.interpretResponse(clone, spec.buildRequests(BID_INFO_1)); + expect(result).to.be.an('array').that.is.empty; + }); + }); + + describe('getUserSyncs', () => { + const RESPONSE = [{ body: { + 'zones': {}, + 'tpCookieSync': ['http://pixel.foo.com/', 'http://pixel.bar.com/'] + }}]; + + it('should return correct pbjs syncs when pixels are enabled', () => { + let syncs = spec.getUserSyncs({ pixelEnabled: true }, RESPONSE); + + expect(syncs.map(x => x.type)).to.eql(['image', 'image']); + expect(syncs.map(x => x.url)).to.have.members(['http://pixel.bar.com/', 'http://pixel.foo.com/']); + }); + + it('should return empty when pixels are not enabled', () => { + let syncs = spec.getUserSyncs({ pixelEnabled: false }, RESPONSE); + + expect(syncs).to.be.an('array').that.is.empty; + }); + + it('should return empty when response has no sync data', () => { + let clone = deepClone(RESPONSE); + delete (clone[0].body.tpCookieSync); + + let syncs = spec.getUserSyncs({ pixelEnabled: true }, clone); + expect(syncs).to.be.an('array').that.is.empty; + }); + + it('should return empty when response is empty', () => { + let syncs = spec.getUserSyncs({ pixelEnabled: true }, [{}]); + expect(syncs).to.be.an('array').that.is.empty; + }); + }); +}); From 7570a6b9c0c2a671bd93106da3b381a8c7803c07 Mon Sep 17 00:00:00 2001 From: Nick Date: Thu, 24 May 2018 09:55:59 -0400 Subject: [PATCH 0391/1594] Sonobi Adapter creativeId support (#2584) * return null from buildRequests if there is no keymakers * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * Adding creativeId support * removed duplicate check for empty keymaker data --- modules/sonobiBidAdapter.js | 2 +- test/spec/modules/sonobiBidAdapter_spec.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index e66a1aa2606..d1d0949f6a0 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -114,7 +114,7 @@ export const spec = { height: Number(height), ad: createCreative(bidResponse.sbi_dc, bid.sbi_aid), ttl: 500, - creativeId: bid.sbi_aid, + creativeId: bid.sbi_crid || bid.sbi_aid, netRevenue: true, currency: 'USD' }; diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index d92553d6661..d7097f4927d 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -237,6 +237,7 @@ describe('SonobiBidAdapter', () => { '/7780971/sparks_prebid_LB|30b31c1838de1f': { 'sbi_size': '300x600', 'sbi_apoc': 'remnant', + 'sbi_crid': '1234abcd', 'sbi_aid': '30292e432662bd5f86d90774b944b039', 'sbi_mouse': 1.07, }, @@ -268,7 +269,7 @@ describe('SonobiBidAdapter', () => { 'height': 600, 'ad': '', 'ttl': 500, - 'creativeId': '30292e432662bd5f86d90774b944b039', + 'creativeId': '1234abcd', 'netRevenue': true, 'currency': 'USD' }, From f022c16aab2ec67349b9d8a6868f6a465e96386d Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 24 May 2018 12:39:54 -0400 Subject: [PATCH 0392/1594] fix find issue in rubiconBidAdapter_spec.js file (#2613) --- test/spec/modules/rubiconBidAdapter_spec.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 54bb92022a2..e6418d715e1 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -6,6 +6,7 @@ import {newBidder} from 'src/adapters/bidderFactory'; import {userSync} from 'src/userSync'; import {config} from 'src/config'; import * as utils from 'src/utils'; +import find from 'core-js/library/fn/array/find'; var CONSTANTS = require('src/constants.json'); @@ -31,7 +32,7 @@ describe('the rubicon adapter', () => { * @return {sizeMapConverted} */ function getSizeIdForBid(sizesMapConverted, bid) { - return sizesMapConverted.find(item => (item.width === bid.width && item.height === bid.height)); + return find(sizesMapConverted, item => (item.width === bid.width && item.height === bid.height)); } /** @@ -40,7 +41,7 @@ describe('the rubicon adapter', () => { * @return {Object} */ function getResponseAdBySize(ads, size) { - return ads.find(item => item.size_id === size.sizeId); + return find(ads, item => item.size_id === size.sizeId); } /** @@ -49,7 +50,7 @@ describe('the rubicon adapter', () => { * @return {BidRequest} */ function getBidRequestBySize(bidRequests, size) { - return bidRequests.find(item => item.sizes[0][0] === size.width && item.sizes[0][1] === size.height); + return find(bidRequests, item => item.sizes[0][0] === size.width && item.sizes[0][1] === size.height); } /** From 1dc17b0e88e47676f9f76e313ab0178a5385c080 Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Thu, 24 May 2018 17:40:37 +0100 Subject: [PATCH 0393/1594] Added new size 320x250 (#2600) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 1a89ca5e3e4..a43c7b504f0 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -66,6 +66,7 @@ var sizeMap = { 125: '800x250', 126: '200x600', 144: '980x600', + 159: '320x250', 195: '600x300', 199: '640x200', 213: '1030x590', From 8010ba5ebb48eb484faf5774ab2d402c619c3181 Mon Sep 17 00:00:00 2001 From: korys Date: Thu, 24 May 2018 18:58:23 +0200 Subject: [PATCH 0394/1594] added ccxAdapter (#2575) * added ccxAdapter * add ccxAdapter - lint formatting fixes --- modules/ccxBidAdapter.js | 192 ++++++++++++++ modules/ccxBidAdapter.md | 57 +++++ test/spec/modules/ccxBidAdapter_spec.js | 318 ++++++++++++++++++++++++ 3 files changed, 567 insertions(+) create mode 100644 modules/ccxBidAdapter.js create mode 100644 modules/ccxBidAdapter.md create mode 100644 test/spec/modules/ccxBidAdapter_spec.js diff --git a/modules/ccxBidAdapter.js b/modules/ccxBidAdapter.js new file mode 100644 index 00000000000..cab5fe2e412 --- /dev/null +++ b/modules/ccxBidAdapter.js @@ -0,0 +1,192 @@ +import * as utils from 'src/utils' +import { registerBidder } from 'src/adapters/bidderFactory' +import { config } from 'src/config' +const BIDDER_CODE = 'ccx' +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'] +const SUPPORTED_VIDEO_PLAYBACK_METHODS = [1, 2, 3, 4] + +function _getDeviceObj () { + let device = {} + device.w = screen.width + device.y = screen.height + device.ua = navigator.userAgent + return device +} + +function _getSiteObj () { + let site = {} + let url = config.getConfig('pageUrl') || utils.getTopWindowUrl() + if (url.length > 0) { + url = url.split('?')[0] + } + site.page = url + + return site +} + +function _validateSizes (sizeObj, type) { + if (!utils.isArray(sizeObj)) { + return false + } + + if (type === 'video' && (typeof sizeObj[0] === 'undefined' || !utils.isArray(sizeObj[0]) || sizeObj[0].length !== 2)) { + return false + } + + if (type === 'banner') { + if (typeof sizeObj[0] === 'undefined') { + return false + } else { + let result = true + utils._each(sizeObj, function (size) { + if (!utils.isArray(size) || (size.length !== 2)) { + result = false + } + }) + return result + } + } + + return true +} + +function _buildBid (bid) { + let placement = {} + placement.id = bid.bidId + placement.secure = 1 + + if (utils.deepAccess(bid, 'mediaTypes.banner')) { + placement.banner = {'format': []} + let sizes = utils.deepAccess(bid, 'mediaTypes.banner.sizes') + utils._each(sizes, function (size) { + placement.banner.format.push({'w': size[0], 'h': size[1]}) + }) + } else if (utils.deepAccess(bid, 'mediaTypes.video')) { + placement.video = {} + + let size = utils.deepAccess(bid, 'mediaTypes.video.playerSize') + + if (typeof size !== 'undefined') { + placement.video.w = size[0][0] + placement.video.h = size[0][1] + } + + placement.video.protocols = utils.deepAccess(bid, 'params.video.protocols') || SUPPORTED_VIDEO_PROTOCOLS + placement.video.mimes = utils.deepAccess(bid, 'params.video.mimes') || SUPPORTED_VIDEO_MIMES + placement.video.playbackmethod = utils.deepAccess(bid, 'params.video.playbackmethod') || SUPPORTED_VIDEO_PLAYBACK_METHODS + placement.video.skip = utils.deepAccess(bid, 'params.video.skip') || 0 + if (placement.video.skip === 1 && utils.deepAccess(bid, 'params.video.skipafter')) { + placement.video.skipafter = utils.deepAccess(bid, 'params.video.skipafter') + } + } + + placement.ext = {'pid': bid.params.placementId} + + return placement +} + +function _buildResponse (bid, currency, ttl) { + let resp = { + requestId: bid.impid, + cpm: bid.price, + width: bid.w, + height: bid.h, + creativeId: bid.crid, + netRevenue: false, + ttl: ttl, + currency: currency + } + + if (bid.ext.type === 'video') { + resp.vastXml = bid.adm + } else { + resp.ad = bid.adm + } + + if (utils.deepAccess(bid, 'dealid')) { + resp.dealId = bid.dealid + } + + return resp +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['banner', 'video'], + + isBidRequestValid: function (bid) { + if (!utils.deepAccess(bid, 'params.placementId')) { + utils.logWarn('placementId param is reqeuired.') + return false + } + if (utils.deepAccess(bid, 'mediaTypes.banner.sizes')) { + let isValid = _validateSizes(bid.mediaTypes.banner.sizes, 'banner') + if (!isValid) { + utils.logWarn('Bid sizes are invalid.') + } + return isValid + } else if (utils.deepAccess(bid, 'mediaTypes.video.playerSize')) { + let isValid = _validateSizes(bid.mediaTypes.video.playerSize, 'video') + if (!isValid) { + utils.logWarn('Bid sizes are invalid.') + } + return isValid + } else { + utils.logWarn('Bid sizes are required.') + return false + } + }, + buildRequests: function (validBidRequests, bidderRequest) { + // check if validBidRequests is not empty + if (validBidRequests.length > 0) { + let requestBody = {} + requestBody.imp = [] + requestBody.site = _getSiteObj() + requestBody.device = _getDeviceObj() + requestBody.id = bidderRequest.bids[0].auctionId + requestBody.ext = {'ce': (utils.cookiesAreEnabled() ? 1 : 0)} + utils._each(validBidRequests, function (bid) { + requestBody.imp.push(_buildBid(bid)) + }) + // Return the server request + return { + 'method': 'POST', + 'url': BID_URL, + 'data': JSON.stringify(requestBody) + } + } + }, + interpretResponse: function (serverResponse, request) { + const bidResponses = [] + + // response is not empty (HTTP 204) + 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)) + }) + }) + } + + return bidResponses + }, + getUserSyncs: function (syncOptions, serverResponses) { + const syncs = [] + + 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, + url: match.url + }) + } + }) + } + + return syncs + } +} +registerBidder(spec) diff --git a/modules/ccxBidAdapter.md b/modules/ccxBidAdapter.md new file mode 100644 index 00000000000..24c10ff4cfa --- /dev/null +++ b/modules/ccxBidAdapter.md @@ -0,0 +1,57 @@ +# Overview + +Module Name: Clickonometrics Bidder Adapter +Module Type: Bidder Adapter +Maintainer: it@clickonometrics.pl + +# Description + +Module that connects to Clickonometrics's demand sources + +# Test Parameters + + var adUnits = [ + { + code: 'test-banner', + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + bids: [ + { + bidder: "ccx", + params: { + placementId: 3286844 + } + } + ] + }, + { + code: 'test-video', + mediaTypes: { + video: { + playerSize: [1920, 1080] + + } + }, + bids: [ + { + bidder: "ccx", + params: { + placementId: 3287742, + //following options are not required, default values will be used. Uncomment if you want to use custom values + /*video: { + //check OpenRTB documentation for following options description + protocols: [2, 3, 5, 6], //default + mimes: ["video/mp4", "video/x-flv"], //default + playbackmethod: [1, 2, 3, 4], //default + skip: 1, //default 0 + skipafter: 5 //delete this key if skip = 0 + }*/ + } + } + ] + } + + ]; \ No newline at end of file diff --git a/test/spec/modules/ccxBidAdapter_spec.js b/test/spec/modules/ccxBidAdapter_spec.js new file mode 100644 index 00000000000..8b715439df6 --- /dev/null +++ b/test/spec/modules/ccxBidAdapter_spec.js @@ -0,0 +1,318 @@ +import { expect } from 'chai'; +import { spec } from 'modules/ccxBidAdapter'; +import * as utils from 'src/utils'; + +describe('ccxAdapter', () => { + let bids = [{ + adUnitCode: 'banner', + auctionId: '0b9de793-8eda-481e-a548-c187d58b28d9', + bidId: '2e56e1af51a5d7', + bidder: 'ccx', + bidderRequestId: '17e7b9f58a607e', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + params: { + placementId: 607 + }, + sizes: [[300, 250]], + transactionId: 'aefddd38-cfa0-48ab-8bdd-325de4bab5f9' + }, + { + adUnitCode: 'video', + auctionId: '0b9de793-8eda-481e-a548-c187d58b28d9', + bidId: '3u94t90ut39tt3t', + bidder: 'ccx', + bidderRequestId: '23ur20r239r2r', + mediaTypes: { + video: { + playerSize: [[640, 480]] + } + }, + params: { + placementId: 608 + }, + sizes: [[640, 480]], + transactionId: 'aefddd38-cfa0-48ab-8bdd-325de4bab5f9' + }]; + describe('isBidRequestValid', () => { + it('Valid bid requests', () => { + expect(spec.isBidRequestValid(bids[0])).to.be.true; + expect(spec.isBidRequestValid(bids[1])).to.be.true; + }); + it('Invalid bid reqeusts - no placementId', () => { + let bidsClone = utils.deepClone(bids); + bidsClone[0].params = undefined; + expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; + }); + it('Invalid bid reqeusts - invalid banner sizes', () => { + let bidsClone = utils.deepClone(bids); + bidsClone[0].mediaTypes.banner.sizes = [300, 250]; + expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; + bidsClone[0].mediaTypes.banner.sizes = [[300, 250], [750]]; + expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; + bidsClone[0].mediaTypes.banner.sizes = []; + expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; + }); + it('Invalid bid reqeusts - invalid video sizes', () => { + let bidsClone = utils.deepClone(bids); + bidsClone[1].mediaTypes.video.playerSize = []; + expect(spec.isBidRequestValid(bidsClone[1])).to.be.false; + bidsClone[1].mediaTypes.video.sizes = [640, 480]; + expect(spec.isBidRequestValid(bidsClone[1])).to.be.false; + }); + }); + + describe('buildRequests', function () { + it('No valid bids', function () { + expect(spec.buildRequests([])).to.be.empty; + }); + + it('Valid bid request - default', function () { + let response = spec.buildRequests(bids, {bids}); + expect(response).to.be.not.empty; + expect(response.data).to.be.not.empty; + + let data = JSON.parse(response.data); + + expect(data).to.be.an('object'); + expect(data).to.have.keys('site', 'imp', 'id', 'ext', 'device'); + + let imps = [ + { + banner: { + format: [ + { + w: 300, + h: 250 + } + ] + }, + ext: { + pid: 607 + }, + id: '2e56e1af51a5d7', + secure: 1 + }, + { + video: { + w: 640, + h: 480, + protocols: [2, 3, 5, 6], + mimes: ['video/mp4', 'video/x-flv'], + playbackmethod: [1, 2, 3, 4], + skip: 0 + }, + id: '3u94t90ut39tt3t', + secure: 1, + ext: { + pid: 608 + } + } + ]; + expect(data.imp).to.deep.have.same.members(imps); + }); + + it('Valid bid request - custom', function () { + let bidsClone = utils.deepClone(bids); + let imps = [ + { + banner: { + format: [ + { + w: 300, + h: 250 + } + ] + }, + ext: { + pid: 607 + }, + id: '2e56e1af51a5d7', + secure: 1 + }, + { + video: { + w: 640, + h: 480, + protocols: [5, 6], + mimes: ['video/mp4'], + playbackmethod: [3], + skip: 1, + skipafter: 5 + }, + id: '3u94t90ut39tt3t', + secure: 1, + ext: { + pid: 608 + } + } + ]; + + bidsClone[1].params.video = {}; + bidsClone[1].params.video.protocols = [5, 6]; + bidsClone[1].params.video.mimes = ['video/mp4']; + bidsClone[1].params.video.playbackmethod = [3]; + bidsClone[1].params.video.skip = 1; + bidsClone[1].params.video.skipafter = 5; + + let response = spec.buildRequests(bidsClone, {'bids': bidsClone}); + let data = JSON.parse(response.data); + + expect(data.imp).to.deep.have.same.members(imps); + }); + }); + + let response = { + id: '0b9de793-8eda-481e-a548-c187d58b28d9', + seatbid: [ + {bid: [ + { + id: '2e56e1af51a5d7_221', + impid: '2e56e1af51a5d7', + price: 8.1, + adid: '221', + adm: '', + adomain: ['clickonometrics.com'], + crid: '221', + w: 300, + h: 250, + ext: { + type: 'standard' + } + }, + { + id: '2e56e1af51a5d8_222', + impid: '2e56e1af51a5d8', + price: 5.68, + adid: '222', + adm: '', + adomain: ['clickonometrics.com'], + crid: '222', + w: 640, + h: 480, + ext: { + type: 'video' + } + } + ]} + ], + cur: 'PLN', + ext: { + ttl: 5, + usersync: [ + { + type: 'image', + url: 'http://foo.sync?param=1' + }, + { + type: 'iframe', + url: 'http://foo.sync?param=2' + } + ] + } + }; + + describe('interpretResponse', function () { + it('Valid bid response - multi', function () { + let bidResponses = [ + { + requestId: '2e56e1af51a5d7', + cpm: 8.1, + width: 300, + height: 250, + creativeId: '221', + netRevenue: false, + ttl: 5, + currency: 'PLN', + ad: '' + }, + { + requestId: '2e56e1af51a5d8', + cpm: 5.68, + width: 640, + height: 480, + creativeId: '222', + netRevenue: false, + ttl: 5, + currency: 'PLN', + vastXml: '' + } + ]; + expect(spec.interpretResponse({body: response})).to.deep.have.same.members(bidResponses); + }); + + it('Valid bid response - single', function () { + delete response.seatbid[0].bid[1]; + let bidResponses = [ + { + requestId: '2e56e1af51a5d7', + cpm: 8.1, + width: 300, + height: 250, + creativeId: '221', + netRevenue: false, + ttl: 5, + currency: 'PLN', + ad: '' + } + ]; + expect(spec.interpretResponse({body: response})).to.deep.have.same.members(bidResponses); + }); + + it('Empty bid response', function () { + expect(spec.interpretResponse({})).to.be.empty; + }); + }); + describe('getUserSyncs', function () { + it('Valid syncs - all', function () { + let syncOptions = { + iframeEnabled: true, + pixelEnabled: true + }; + + let expectedSyncs = [ + { + type: 'image', + url: 'http://foo.sync?param=1' + }, + { + type: 'iframe', + url: 'http://foo.sync?param=2' + } + ]; + expect(spec.getUserSyncs(syncOptions, [{body: response}])).to.deep.have.same.members(expectedSyncs); + }); + + it('Valid syncs - only image', function () { + let syncOptions = { + iframeEnabled: false, + pixelEnabled: true + }; + let expectedSyncs = [ + { + type: 'image', url: 'http://foo.sync?param=1' + } + ]; + expect(spec.getUserSyncs(syncOptions, [{body: response}])).to.deep.have.same.members(expectedSyncs); + }); + + it('Valid syncs - only iframe', function () { + let syncOptions = {iframeEnabled: true, pixelEnabled: false}; + let expectedSyncs = [ + { + type: 'iframe', url: 'http://foo.sync?param=2' + } + ]; + expect(spec.getUserSyncs(syncOptions, [{body: response}])).to.deep.have.same.members(expectedSyncs); + }); + + it('Valid syncs - empty', function () { + let syncOptions = {iframeEnabled: true, pixelEnabled: true}; + response.ext.usersync = {}; + expect(spec.getUserSyncs(syncOptions, [{body: response}])).to.be.empty; + }); + }); +}); From ad1507b9b98d005c1f12c75404a8a9bc54053540 Mon Sep 17 00:00:00 2001 From: "N. Faure" Date: Thu, 24 May 2018 19:13:42 +0200 Subject: [PATCH 0395/1594] Update Criteo bid adapter to Prebid 1.x (#2370) * Convert Criteo adapter to bidderFactory * Add documentation for Prebid 1.0 Criteo adapter * Add support for zone-matching bids on Prebid 1.0 Criteo adapter * Add unit tests to the Prebid 1.0 Criteo adapter * Explicit the fact that Criteo bids are net revenue * Pass currency in Criteo 1.0 adapter * Update Criteo adapter to use PublisherTag if present * Implement fastbid in prebid 1.0 criteo adapter * Pass the bid requests to the Criteo interpret method * Add missing ttl and creativeId fields to Criteo bids * Add 'native' support to the Criteo adapter * Check that the Criteo adapter returned by PublisherTag is not empty * Update criteo prebid adapter to reload publisher tag once auction is finished * Fix 'assign to const' IE errors in Criteo native adapter * Disable the PublisherTag event queue * Fix Criteo adapter on older Prebid versions not using response.body * Fix TypeError if FastBid is outdated * Remove the success variable in tryGetCriteoFastBid * Fix events being overwritten with FastBid * Update PublisherTag loading comment * Use adUnitCode as impid * Add events handlers in Criteo adapter to fix timeouts not treated as such * Add handler for setTargeting event * Move the registeredEvents set higher up to reduce the chances of race conditions * Fix UTests following recent Criteo adapter changes * Add comment linking to the PublisherTag unminified source * Do not return a request in buildRequests on error In some cases, the buildCdbRequest function might return a falsy value, in case of error in creating the request or if we know in advance that this request will return a no-bid. In this case, the buildRequests() method should not return a request, causing a no-bid. * Use loadExternalScript instead of loadScript * Use spec.onTimeout instead of registering an event handler * GDPR support in Criteo adapter (#4) GDPR support in Criteo adapter * Remove BID_WON and SET_TARGETING events from Criteo adapter * Update adapter version * Add support for multi-size in Criteo adapter * Fix support for multi size in Criteo adapter * Update adapterVersion to 7 --- modules/criteoBidAdapter.js | 262 ++++++++++++++++++++ modules/criteoBidAdapter.md | 27 ++ test/spec/modules/criteoBidAdapter_spec.js | 274 +++++++++++++++++++++ 3 files changed, 563 insertions(+) create mode 100755 modules/criteoBidAdapter.js create mode 100755 modules/criteoBidAdapter.md create mode 100755 test/spec/modules/criteoBidAdapter_spec.js diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js new file mode 100755 index 00000000000..ee74141f0bc --- /dev/null +++ b/modules/criteoBidAdapter.js @@ -0,0 +1,262 @@ +import { loadExternalScript } from 'src/adloader'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { parse } from 'src/url'; +import * as utils from 'src/utils'; + +const ADAPTER_VERSION = 7; +const BIDDER_CODE = 'criteo'; +const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; +const CRITEO_VENDOR_ID = 91; +const INTEGRATION_MODES = { + 'amp': 1, +}; +const PROFILE_ID = 207; + +// Unminified source code can be found in: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js +const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js'; + +/** @type {BidderSpec} */ +export const spec = { + code: BIDDER_CODE, + + /** + * @param {object} bid + * @return {boolean} + */ + isBidRequestValid: bid => ( + !!(bid && bid.params && (bid.params.zoneId || bid.params.networkId)) + ), + + /** + * @param {BidRequest[]} bidRequests + * @param {*} bidderRequest + * @return {ServerRequest} + */ + buildRequests: (bidRequests, bidderRequest) => { + let url; + let data; + + // If publisher tag not already loaded try to get it from fast bid + if (!publisherTagAvailable()) { + window.Criteo = window.Criteo || {}; + window.Criteo.usePrebidEvents = false; + + tryGetCriteoFastBid(); + + // Reload the PublisherTag after the timeout to ensure FastBid is up-to-date and tracking done properly + setTimeout(() => { + loadExternalScript(PUBLISHER_TAG_URL, BIDDER_CODE); + }, bidderRequest.timeout); + } + + if (publisherTagAvailable()) { + const adapter = new Criteo.PubTag.Adapters.Prebid(PROFILE_ID, ADAPTER_VERSION, bidRequests, bidderRequest); + url = adapter.buildCdbUrl(); + data = adapter.buildCdbRequest(); + } else { + const context = buildContext(bidRequests); + url = buildCdbUrl(context); + data = buildCdbRequest(context, bidRequests, bidderRequest); + } + + if (data) { + return { method: 'POST', url, data, bidRequests }; + } + }, + + /** + * @param {*} response + * @param {ServerRequest} request + * @return {Bid[]} + */ + interpretResponse: (response, request) => { + const body = response.body || response; + + if (publisherTagAvailable()) { + const adapter = Criteo.PubTag.Adapters.Prebid.GetAdapter(request); + if (adapter) { + return adapter.interpretResponse(body, request); + } + } + + const bids = []; + + if (body && body.slots && utils.isArray(body.slots)) { + body.slots.forEach(slot => { + const bidRequest = request.bidRequests.find(b => b.adUnitCode === slot.impid && (!b.params.zoneId || parseInt(b.params.zoneId) === slot.zoneid)); + const bidId = bidRequest.bidId; + const bid = { + requestId: bidId, + cpm: slot.cpm, + currency: slot.currency, + netRevenue: true, + ttl: slot.ttl || 60, + creativeId: bidId, + width: slot.width, + height: slot.height, + } + if (slot.native) { + bid.ad = createNativeAd(bidId, slot.native, bidRequest.params.nativeCallback); + } else { + bid.ad = slot.creative; + } + bids.push(bid); + }); + } + + return bids; + }, + + /** + * @param {TimedOutBid} timeoutData + */ + onTimeout: (timeoutData) => { + if (publisherTagAvailable()) { + const adapter = Criteo.PubTag.Adapters.Prebid.GetAdapter(timeoutData.auctionId); + adapter.handleBidTimeout(); + } + }, +}; + +/** + * @return {boolean} + */ +function publisherTagAvailable() { + return typeof Criteo !== 'undefined' && Criteo.PubTag && Criteo.PubTag.Adapters && Criteo.PubTag.Adapters.Prebid; +} + +/** + * @param {BidRequest[]} bidRequests + * @return {CriteoContext} + */ +function buildContext(bidRequests) { + const url = utils.getTopWindowUrl(); + const queryString = parse(url).search; + + const context = { + url: url, + debug: queryString['pbt_debug'] === '1', + noLog: queryString['pbt_nolog'] === '1', + integrationMode: undefined, + }; + + bidRequests.forEach(bidRequest => { + if (bidRequest.params.integrationMode) { + context.integrationMode = bidRequest.params.integrationMode; + } + }) + + return context; +} + +/** + * @param {CriteoContext} context + * @return {string} + */ +function buildCdbUrl(context) { + let url = CDB_ENDPOINT; + url += '?profileId=' + PROFILE_ID; + url += '&av=' + String(ADAPTER_VERSION); + url += '&cb=' + String(Math.floor(Math.random() * 99999999999)); + + if (context.integrationMode in INTEGRATION_MODES) { + url += '&im=' + INTEGRATION_MODES[context.integrationMode]; + } + if (context.debug) { + url += '&debug=1'; + } + if (context.noLog) { + url += '&nolog=1'; + } + + return url; +} + +/** + * @param {CriteoContext} context + * @param {BidRequest[]} bidRequests + * @return {*} + */ +function buildCdbRequest(context, bidRequests, bidderRequest) { + let networkId; + const request = { + publisher: { + url: context.url, + }, + slots: bidRequests.map(bidRequest => { + networkId = bidRequest.params.networkId || networkId; + const slot = { + impid: bidRequest.adUnitCode, + transactionid: bidRequest.transactionId, + auctionId: bidRequest.auctionId, + sizes: bidRequest.sizes.map(size => size[0] + 'x' + size[1]), + }; + if (bidRequest.params.zoneId) { + slot.zoneid = bidRequest.params.zoneId; + } + if (bidRequest.params.publisherSubId) { + slot.publishersubid = bidRequest.params.publisherSubId; + } + if (bidRequest.params.nativeCallback) { + slot.native = true; + } + return slot; + }), + }; + if (networkId) { + request.publisher.networkid = networkId; + } + if (bidderRequest && bidderRequest.gdprConsent) { + request.gdprConsent = { + gdprApplies: !!(bidderRequest.gdprConsent.gdprApplies), + consentData: bidderRequest.gdprConsent.consentString, + consentGiven: !!(bidderRequest.gdprConsent.vendorData && bidderRequest.gdprConsent.vendorData.vendorConsents && + bidderRequest.gdprConsent.vendorData.vendorConsents[ CRITEO_VENDOR_ID.toString(10) ]), + }; + } + return request; +} + +/** + * @param {string} id + * @param {*} payload + * @param {*} callback + * @return {string} + */ +function createNativeAd(id, payload, callback) { + // Store the callback and payload in a global object to be later accessed from the creative + window.criteo_prebid_native_slots = window.criteo_prebid_native_slots || {}; + window.criteo_prebid_native_slots[id] = { callback, payload }; + + // The creative is in an iframe so we have to get the callback and payload + // from the parent window (doesn't work with safeframes) + return ``; +} + +/** + * @return {boolean} + */ +function tryGetCriteoFastBid() { + try { + const fastBid = localStorage.getItem('criteo_fast_bid'); + if (fastBid !== null) { + eval(fastBid); // eslint-disable-line no-eval + return true; + } + } catch (e) { + // Unable to get fast bid + } + return false; +} + +registerBidder(spec); diff --git a/modules/criteoBidAdapter.md b/modules/criteoBidAdapter.md new file mode 100755 index 00000000000..796c70a980f --- /dev/null +++ b/modules/criteoBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +Module Name: Criteo Bidder Adapter +Module Type: Bidder Adapter +Maintainer: pi-direct@criteo.com + +# Description + +Module that connects to Criteo's demand sources. + +# Test Parameters +``` + var adUnits = [ + { + code: 'banner-ad-div', + sizes: [[300, 250], [728, 90]], + bids: [ + { + bidder: 'criteo', + params: { + zoneId: 497747 + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js new file mode 100755 index 00000000000..ccf683dc4ca --- /dev/null +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -0,0 +1,274 @@ +import { expect } from 'chai'; +import { spec } from 'modules/criteoBidAdapter'; +import * as utils from 'src/utils'; + +describe('The Criteo bidding adapter', () => { + describe('isBidRequestValid', () => { + it('should return false when given an invalid bid', () => { + const bid = { + bidder: 'criteo', + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + + it('should return true when given a zoneId bid', () => { + const bid = { + bidder: 'criteo', + params: { + zoneId: 123, + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + + it('should return true when given a networkId bid', () => { + const bid = { + bidder: 'criteo', + params: { + networkId: 456, + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + + it('should return true when given a mixed bid with both a zoneId and a networkId', () => { + const bid = { + bidder: 'criteo', + params: { + zoneId: 123, + networkId: 456, + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + }); + + describe('buildRequests', () => { + const bidderRequest = { timeout: 3000, + gdprConsent: { + gdprApplies: 1, + consentString: 'concentDataString', + vendorData: { + vendorConsents: { + '91': 1 + }, + }, + }, + }; + + it('should properly build a zoneId request', () => { + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + params: { + zoneId: 123, + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.slots).to.have.lengthOf(1); + expect(ortbRequest.slots[0].impid).to.equal('bid-123'); + expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); + expect(ortbRequest.slots[0].sizes).to.have.lengthOf(1); + expect(ortbRequest.slots[0].sizes[0]).to.equal('728x90'); + expect(ortbRequest.slots[0].zoneid).to.equal(123); + expect(ortbRequest.gdprConsent.consentData).to.equal('concentDataString'); + expect(ortbRequest.gdprConsent.gdprApplies).to.equal(true); + expect(ortbRequest.gdprConsent.consentGiven).to.equal(true); + }); + + it('should properly build a networkId request', () => { + const bidderRequest = { + timeout: 3000, + gdprConsent: { + gdprApplies: 0, + consentString: undefined, + vendorData: { + vendorConsents: { + '1': 0 + }, + }, + }, + }; + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[300, 250], [728, 90]], + params: { + networkId: 456, + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.networkid).to.equal(456); + expect(ortbRequest.slots).to.have.lengthOf(1); + expect(ortbRequest.slots[0].impid).to.equal('bid-123'); + expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); + expect(ortbRequest.slots[0].sizes).to.have.lengthOf(2); + expect(ortbRequest.slots[0].sizes[0]).to.equal('300x250'); + expect(ortbRequest.slots[0].sizes[1]).to.equal('728x90'); + expect(ortbRequest.gdprConsent.consentData).to.equal(undefined); + expect(ortbRequest.gdprConsent.gdprApplies).to.equal(false); + expect(ortbRequest.gdprConsent.consentGiven).to.equal(false); + }); + + it('should properly build a mixed request', () => { + const bidderRequest = { timeout: 3000 }; + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + params: { + zoneId: 123, + }, + }, + { + bidder: 'criteo', + adUnitCode: 'bid-234', + transactionId: 'transaction-234', + sizes: [[300, 250], [728, 90]], + params: { + networkId: 456, + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.networkid).to.equal(456); + expect(ortbRequest.slots).to.have.lengthOf(2); + expect(ortbRequest.slots[0].impid).to.equal('bid-123'); + expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); + expect(ortbRequest.slots[0].sizes).to.have.lengthOf(1); + expect(ortbRequest.slots[0].sizes[0]).to.equal('728x90'); + expect(ortbRequest.slots[1].impid).to.equal('bid-234'); + expect(ortbRequest.slots[1].transactionid).to.equal('transaction-234'); + expect(ortbRequest.slots[1].sizes).to.have.lengthOf(2); + expect(ortbRequest.slots[1].sizes[0]).to.equal('300x250'); + expect(ortbRequest.slots[1].sizes[1]).to.equal('728x90'); + expect(ortbRequest.gdprConsent).to.equal(undefined); + }); + }); + + describe('interpretResponse', () => { + it('should return an empty array when parsing a no bid response', () => { + const response = {}; + const request = { bidRequests: [] }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(0); + }); + + it('should properly parse a bid response with a networkId', () => { + const response = { + body: { + slots: [{ + impid: 'test-requestId', + cpm: 1.23, + creative: 'test-ad', + width: 728, + height: 90, + }], + }, + }; + const request = { + bidRequests: [{ + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + networkId: 456, + } + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('test-bidId'); + expect(bids[0].cpm).to.equal(1.23); + expect(bids[0].ad).to.equal('test-ad'); + expect(bids[0].width).to.equal(728); + expect(bids[0].height).to.equal(90); + }); + + it('should properly parse a bid responsewith with a zoneId', () => { + const response = { + body: { + slots: [{ + impid: 'test-requestId', + cpm: 1.23, + creative: 'test-ad', + width: 728, + height: 90, + zoneid: 123, + }], + }, + }; + const request = { + bidRequests: [{ + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + zoneId: 123, + }, + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('test-bidId'); + expect(bids[0].cpm).to.equal(1.23); + expect(bids[0].ad).to.equal('test-ad'); + expect(bids[0].width).to.equal(728); + expect(bids[0].height).to.equal(90); + }); + + it('should properly parse a bid responsewith with a zoneId passed as a string', () => { + const response = { + body: { + slots: [{ + impid: 'test-requestId', + cpm: 1.23, + creative: 'test-ad', + width: 728, + height: 90, + zoneid: 123, + }], + }, + }; + const request = { + bidRequests: [{ + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + zoneId: '123', + }, + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('test-bidId'); + expect(bids[0].cpm).to.equal(1.23); + expect(bids[0].ad).to.equal('test-ad'); + expect(bids[0].width).to.equal(728); + expect(bids[0].height).to.equal(90); + }); + }); +}); From 8b6ff71327a97e48104f427e7d148fa0e52cd7df Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 24 May 2018 14:05:58 -0400 Subject: [PATCH 0396/1594] GDPR use getConsentData CMP call to get consentString (#2603) * use getConsentData cmp to get consent info * add changes for safeframe and iframe workflows * update logic to execute CMP calls in parallel --- modules/consentManagement.js | 138 ++++++++++++-------- test/spec/modules/consentManagement_spec.js | 20 +-- 2 files changed, 92 insertions(+), 66 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index f4eedd57cfd..3dd2d77610f 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -34,7 +34,7 @@ const cmpCallMap = { }; /** - * This function handles interacting with an IAB compliant CMP to obtain the consentObject value of the user. + * 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(string)} cmpSuccess acts as a success callback when CMP returns a value; pass along consentObject (string) from CMP @@ -42,35 +42,75 @@ const cmpCallMap = { * @param {[objects]} adUnits used in the safeframe workflow to know what sizes to include in the $sf.ext.register call */ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { - let cmpCallbacks; + function handleCmpResponseCallbacks() { + const cmpResponse = {}; - // check if the CMP is located on the same window level as the prebid code. - // if it's found, directly call the CMP via it's API and call the cmpSuccess callback. - // if it's not found, assume the prebid code may be inside an iframe and the CMP code is located in a higher parent window. - // in this case, use the IAB's iframe locator sample code (which is slightly cutomized) to try to find the CMP and use postMessage() to communicate with the CMP. + function afterEach() { + if (cmpResponse.getConsentData && cmpResponse.getVendorConsents) { + cmpSuccess(cmpResponse); + } + } + + return { + consentDataCallback: function(consentResponse) { + cmpResponse.getConsentData = consentResponse; + afterEach(); + }, + vendorConsentsCallback: function(consentResponse) { + cmpResponse.getVendorConsents = consentResponse; + afterEach(); + } + } + } + let callbackHandler = handleCmpResponseCallbacks(); + let cmpCallbacks = {}; + + // 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) + // second to collect the user's full unparsed consent information (via getVendorConsents) + + // the following code also determines where the CMP is located and uses the proper workflow to communicate with it: + // check to see if CMP is found on the same window level as prebid and call it directly if so + // check to see if prebid is in a safeframe (with CMP support) + // 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 (utils.isFn(window.__cmp)) { - window.__cmp('getVendorConsents', null, cmpSuccess); + window.__cmp('getConsentData', null, callbackHandler.consentDataCallback); + window.__cmp('getVendorConsents', null, callbackHandler.vendorConsentsCallback); } else if (inASafeFrame() && typeof window.$sf.ext.cmp === 'function') { - callCmpWhileInSafeFrame(); + callCmpWhileInSafeFrame('getConsentData', callbackHandler.consentDataCallback); + callCmpWhileInSafeFrame('getVendorConsents', callbackHandler.vendorConsentsCallback); } else { - callCmpWhileInIframe(); + // find the CMP frame + let f = window; + let cmpFrame; + while (!cmpFrame) { + try { + if (f.frames['__cmpLocator']) cmpFrame = f; + } catch (e) {} + if (f === window.top) break; + f = f.parent; + } + + callCmpWhileInIframe('getConsentData', cmpFrame, callbackHandler.consentDataCallback); + callCmpWhileInIframe('getVendorConsents', cmpFrame, callbackHandler.vendorConsentsCallback); } function inASafeFrame() { return !!(window.$sf && window.$sf.ext); } - function callCmpWhileInSafeFrame() { + function callCmpWhileInSafeFrame(commandName, callback) { function sfCallback(msgName, data) { if (msgName === 'cmpReturn') { - cmpSuccess(data.vendorConsents); + let responseObj = (commandName === 'getConsentData') ? data.vendorConsentData : data.vendorConsents; + callback(responseObj); } } // find sizes from adUnits object let width = 1; let height = 1; - if (Array.isArray(adUnits) && adUnits.length > 0) { let sizes = utils.getAdUnitSizes(adUnits[0]); width = sizes[0][0]; @@ -78,27 +118,10 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { } window.$sf.ext.register(width, height, sfCallback); - window.$sf.ext.cmp('getVendorConsents'); + window.$sf.ext.cmp(commandName); } - function callCmpWhileInIframe() { - /** - * START OF STOCK CODE FROM IAB 1.1 CMP SPEC - */ - - // find the CMP frame - let f = window; - let cmpFrame; - while (!cmpFrame) { - try { - if (f.frames['__cmpLocator']) cmpFrame = f; - } catch (e) {} - if (f === window.top) break; - f = f.parent; - } - - cmpCallbacks = {}; - + function callCmpWhileInIframe(commandName, cmpFrame, moduleCallback) { /* Setup up a __cmp function to do the postMessage and stash the callback. This function behaves (from the caller's perspective identicially to the in-frame __cmp call */ window.__cmp = function(cmd, arg, callback) { @@ -106,7 +129,6 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { removePostMessageListener(); let errmsg = 'CMP not found'; - // small customization to properly return error return cmpError(errmsg); } let callId = Math.random() + ''; @@ -120,34 +142,31 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { } /** when we get the return message, call the stashed callback */ - // small customization to remove this eventListener later in module window.addEventListener('message', readPostMessageResponse, false); - /** - * END OF STOCK CODE FROM IAB 1.1 CMP SPEC - */ - // call CMP - window.__cmp('getVendorConsents', null, cmpIframeCallback); - } - - function readPostMessageResponse(event) { - // small customization to prevent reading strings from other sources that aren't JSON.stringified - let json = (typeof event.data === 'string' && strIncludes(event.data, 'cmpReturn')) ? JSON.parse(event.data) : event.data; - if (json.__cmpReturn) { - let i = json.__cmpReturn; - cmpCallbacks[i.callId](i.returnValue, i.success); - delete cmpCallbacks[i.callId]; + window.__cmp(commandName, null, cmpIframeCallback); + + function readPostMessageResponse(event) { + let json = (typeof event.data === 'string' && strIncludes(event.data, 'cmpReturn')) ? JSON.parse(event.data) : event.data; + if (json.__cmpReturn && json.__cmpReturn.callId) { + let i = json.__cmpReturn; + // 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 + if (typeof cmpCallbacks[i.callId] !== 'undefined') { + cmpCallbacks[i.callId](i.returnValue, i.success); + delete cmpCallbacks[i.callId]; + } + } } - } - function removePostMessageListener() { - window.removeEventListener('message', readPostMessageResponse, false); - } + function removePostMessageListener() { + window.removeEventListener('message', readPostMessageResponse, false); + } - function cmpIframeCallback(consentObject) { - removePostMessageListener(); - cmpSuccess(consentObject); + function cmpIframeCallback(consentObject) { + removePostMessageListener(); + moduleCallback(consentObject); + } } } @@ -196,7 +215,10 @@ export function requestBidsHook(reqBidsConfigObj, fn) { * @param {object} consentObject required; object returned by CMP that contains user's consent choices */ function processCmpData(consentObject) { - if (!utils.isPlainObject(consentObject) || !utils.isStr(consentObject.metadata) || consentObject.metadata === '') { + if ( + !utils.isPlainObject(consentObject) || + (!utils.isPlainObject(consentObject.getVendorConsents) || Object.keys(consentObject.getVendorConsents).length === 0) || + (!utils.isPlainObject(consentObject.getConsentData) || Object.keys(consentObject.getConsentData).length === 0)) { cmpFailed(`CMP returned unexpected value during lookup process; returned value was (${consentObject}).`); } else { clearTimeout(timer); @@ -233,9 +255,9 @@ function cmpFailed(errMsg) { */ function storeConsentData(cmpConsentObject) { consentData = { - consentString: (cmpConsentObject) ? cmpConsentObject.metadata : undefined, - vendorData: cmpConsentObject, - gdprApplies: (cmpConsentObject) ? cmpConsentObject.gdprApplies : undefined + consentString: (cmpConsentObject) ? cmpConsentObject.getConsentData.consentData : undefined, + vendorData: (cmpConsentObject) ? cmpConsentObject.getVendorConsents : undefined, + gdprApplies: (cmpConsentObject) ? cmpConsentObject.getConsentData.gdprApplies : undefined }; gdprDataHandler.setConsentData(consentData); } diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index eb1614e4965..2bb444a71aa 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -119,7 +119,7 @@ describe('consentManagement', function () { it('should bypass CMP and simply use previously stored consentData', () => { let testConsentData = { gdprApplies: true, - metadata: 'xyz' + consentData: 'xyz' }; cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { @@ -140,7 +140,7 @@ describe('consentManagement', function () { let consent = gdprDataHandler.getConsentData(); expect(didHookReturn).to.be.true; - expect(consent.consentString).to.equal(testConsentData.metadata); + expect(consent.consentString).to.equal(testConsentData.consentData); expect(consent.gdprApplies).to.be.true; sinon.assert.notCalled(cmpStub); }); @@ -178,6 +178,10 @@ describe('consentManagement', function () { vendorConsents: { metadata: 'abc123def', gdprApplies: true + }, + vendorConsentData: { + consentData: 'abc123def', + gdprApplies: true } } }; @@ -227,7 +231,7 @@ describe('consentManagement', function () { __cmpReturn: { returnValue: { gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + consentData: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' } } } @@ -238,7 +242,7 @@ describe('consentManagement', function () { cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { args[2]({ gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + consentData: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' }); }); @@ -280,7 +284,7 @@ describe('consentManagement', function () { it('performs lookup check and stores consentData for a valid existing user', () => { let testConsentData = { gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + consentData: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' }; cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { args[2](testConsentData); @@ -296,12 +300,12 @@ describe('consentManagement', function () { sinon.assert.notCalled(utils.logWarn); sinon.assert.notCalled(utils.logError); expect(didHookReturn).to.be.true; - expect(consent.consentString).to.equal(testConsentData.metadata); + expect(consent.consentString).to.equal(testConsentData.consentData); expect(consent.gdprApplies).to.be.true; }); it('throws an error when processCmpData check failed while config had allowAuction set to false', () => { - let testConsentData = null; + let testConsentData = {}; let bidsBackHandlerReturn = false; cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { @@ -322,7 +326,7 @@ describe('consentManagement', function () { }); it('throws a warning + stores consentData + calls callback when processCmpData check failed while config had allowAuction set to true', () => { - let testConsentData = null; + let testConsentData = {}; cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { args[2](testConsentData); From fb2f178faadd774aebb5dd75532d7cac6f119dd8 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Thu, 24 May 2018 14:07:22 -0400 Subject: [PATCH 0397/1594] use imported find (#2614) --- modules/criteoBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index ee74141f0bc..320d8526244 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -2,6 +2,7 @@ import { loadExternalScript } from 'src/adloader'; import { registerBidder } from 'src/adapters/bidderFactory'; import { parse } from 'src/url'; import * as utils from 'src/utils'; +import find from 'core-js/library/fn/array/find'; const ADAPTER_VERSION = 7; const BIDDER_CODE = 'criteo'; @@ -83,7 +84,7 @@ export const spec = { if (body && body.slots && utils.isArray(body.slots)) { body.slots.forEach(slot => { - const bidRequest = request.bidRequests.find(b => b.adUnitCode === slot.impid && (!b.params.zoneId || parseInt(b.params.zoneId) === slot.zoneid)); + 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, From cf795e62465b0a850e314b11c4bb4c2c66d16e7c Mon Sep 17 00:00:00 2001 From: nissSK Date: Thu, 24 May 2018 21:18:48 +0300 Subject: [PATCH 0398/1594] GDPR - change parameters name (#2608) * GDPR support * GDPR - change parameters name --- modules/sekindoUMBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/sekindoUMBidAdapter.js b/modules/sekindoUMBidAdapter.js index 7b24e03408a..ffaaa2c1c62 100644 --- a/modules/sekindoUMBidAdapter.js +++ b/modules/sekindoUMBidAdapter.js @@ -56,8 +56,8 @@ export const spec = { queryString = utils.tryAppendQueryString(queryString, 'x', bidRequest.params.width); queryString = utils.tryAppendQueryString(queryString, 'y', bidRequest.params.height); if (bidderRequest && bidderRequest.gdprConsent) { - queryString = utils.tryAppendQueryString(queryString, 'gdprConsentString', bidderRequest.gdprConsent.consentString); - queryString = utils.tryAppendQueryString(queryString, 'gdprApplies', (bidderRequest.gdprConsent.gdprApplies) ? '1' : '0'); + queryString = utils.tryAppendQueryString(queryString, 'gdprConsent', bidderRequest.gdprConsent.consentString); + queryString = utils.tryAppendQueryString(queryString, 'gdpr', (bidderRequest.gdprConsent.gdprApplies) ? '1' : '0'); } if (bidRequest.mediaType === 'video' || (typeof bidRequest.mediaTypes == 'object' && typeof bidRequest.mediaTypes.video == 'object')) { queryString = utils.tryAppendQueryString(queryString, 'x', bidRequest.params.playerWidth); From 090ae4f3eb59f0ee8d756e54b56ef924b2936693 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 24 May 2018 15:07:59 -0400 Subject: [PATCH 0399/1594] fix issue with GDPR module in concurrent auctions (#2612) --- modules/consentManagement.js | 80 +++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index 3dd2d77610f..fd961eeb17f 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -20,14 +20,6 @@ export let allowAuction; let consentData; -let context; -let args; -let nextFn; -let bidsBackHandler; - -let timer; -let haveExited; - // add new CMPs here, with their dedicated lookup function const cmpCallMap = { 'iab': lookupIabConsent @@ -39,15 +31,15 @@ const cmpCallMap = { * based on the appropriate result. * @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 {[objects]} adUnits used in the safeframe workflow to know what sizes to include in the $sf.ext.register call + * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) */ -function lookupIabConsent(cmpSuccess, cmpError, adUnits) { +function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { function handleCmpResponseCallbacks() { const cmpResponse = {}; function afterEach() { if (cmpResponse.getConsentData && cmpResponse.getVendorConsents) { - cmpSuccess(cmpResponse); + cmpSuccess(cmpResponse, hookConfig); } } @@ -109,6 +101,7 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { } // find sizes from adUnits object + let adUnits = hookConfig.adUnits; let width = 1; let height = 1; if (Array.isArray(adUnits) && adUnits.length > 0) { @@ -129,7 +122,7 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { removePostMessageListener(); let errmsg = 'CMP not found'; - return cmpError(errmsg); + return cmpError(errmsg, hookConfig); } let callId = Math.random() + ''; let msg = {__cmpCall: { @@ -179,31 +172,35 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { * @param {function} fn required; The next function in the chain, used by hook.js */ export function requestBidsHook(reqBidsConfigObj, fn) { - context = this; - args = arguments; - nextFn = fn; - haveExited = false; - let adUnits = reqBidsConfigObj.adUnits || $$PREBID_GLOBAL$$.adUnits; - bidsBackHandler = reqBidsConfigObj.bidsBackHandler; + // preserves all module related variables for the current auction instance (used primiarily for concurrent auctions) + const hookConfig = { + context: this, + args: arguments, + 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) { - return exitModule(); + return exitModule(null, hookConfig); } if (!includes(Object.keys(cmpCallMap), userCMP)) { utils.logWarn(`CMP framework (${userCMP}) is not a supported framework. Aborting consentManagement module and resuming auction.`); - return nextFn.apply(context, args); + return hookConfig.nextFn.apply(hookConfig.context, hookConfig.args); } - cmpCallMap[userCMP].call(this, processCmpData, cmpFailed, adUnits); + cmpCallMap[userCMP].call(this, processCmpData, cmpFailed, hookConfig); // only let this code run if module is still active (ie if the callbacks used by CMPs haven't already finished) - if (!haveExited) { + if (!hookConfig.haveExited) { if (consentTimeout === 0) { - processCmpData(undefined); + processCmpData(undefined, hookConfig); } else { - timer = setTimeout(cmpTimedOut, consentTimeout); + hookConfig.timer = setTimeout(cmpTimedOut.bind(null, hookConfig), consentTimeout); } } } @@ -213,40 +210,42 @@ export function requestBidsHook(reqBidsConfigObj, fn) { * 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) { +function processCmpData(consentObject, hookConfig) { if ( !utils.isPlainObject(consentObject) || (!utils.isPlainObject(consentObject.getVendorConsents) || Object.keys(consentObject.getVendorConsents).length === 0) || (!utils.isPlainObject(consentObject.getConsentData) || Object.keys(consentObject.getConsentData).length === 0)) { - cmpFailed(`CMP returned unexpected value during lookup process; returned value was (${consentObject}).`); + cmpFailed(`CMP returned unexpected value during lookup process; returned value was (${consentObject}).`, hookConfig); } else { - clearTimeout(timer); + clearTimeout(hookConfig.timer); storeConsentData(consentObject); - exitModule(); + exitModule(null, hookConfig); } } /** * General timeout callback when interacting with CMP takes too long. */ -function cmpTimedOut() { - cmpFailed('CMP workflow exceeded timeout threshold.'); +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) */ -function cmpFailed(errMsg) { - clearTimeout(timer); +function cmpFailed(errMsg, hookConfig) { + clearTimeout(hookConfig.timer); // still set the consentData to undefined when there is a problem as per config options if (allowAuction) { storeConsentData(undefined); } - exitModule(errMsg); + exitModule(errMsg, hookConfig); } /** @@ -276,10 +275,15 @@ function storeConsentData(cmpConsentObject) { * 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) */ -function exitModule(errMsg) { - if (haveExited === false) { - haveExited = true; +function exitModule(errMsg, hookConfig) { + if (hookConfig.haveExited === false) { + hookConfig.haveExited = true; + + let context = hookConfig.context; + let args = hookConfig.args; + let nextFn = hookConfig.nextFn; if (errMsg) { if (allowAuction) { @@ -287,8 +291,8 @@ function exitModule(errMsg) { nextFn.apply(context, args); } else { utils.logError(errMsg + ' Canceling auction as per consentManagement config.'); - if (typeof bidsBackHandler === 'function') { - bidsBackHandler(); + if (typeof hookConfig.bidsBackHandler === 'function') { + hookConfig.bidsBackHandler(); } else { utils.logError('Error executing bidsBackHandler'); } From 20c7968863446ff7823c2512fd97db47b08e4bec Mon Sep 17 00:00:00 2001 From: ricardoe Date: Thu, 24 May 2018 14:19:58 -0500 Subject: [PATCH 0400/1594] Add GDPR support to GumGum Adapter (#2595) --- modules/gumgumBidAdapter.js | 7 ++++++- test/spec/modules/gumgumBidAdapter_spec.js | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 0b7a4223063..6a5575d74fe 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -98,8 +98,9 @@ function isBidRequestValid (bid) { * @param {validBidRequests[]} - an array of bids * @return ServerRequest Info describing the request to the server. */ -function buildRequests (validBidRequests) { +function buildRequests (validBidRequests, bidderRequest) { const bids = []; + const gdprConsent = Object.assign({ consentString: null, gdprApplies: true }, bidderRequest && bidderRequest.gdprConsent) utils._each(validBidRequests, bidRequest => { const timeout = config.getConfig('bidderTimeout'); const { @@ -123,6 +124,10 @@ function buildRequests (validBidRequests) { data.ni = parseInt(params.ICV, 10); data.pi = 5; } + data.gdprApplies = gdprConsent.gdprApplies; + if (gdprConsent.gdprApplies) { + data.gdprConsent = gdprConsent.consentString; + } bids.push({ id: bidId, diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 276972a163f..8a59d61e2bc 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -64,12 +64,24 @@ describe('gumgumAdapter', () => { ]; it('sends bid request to ENDPOINT via GET', () => { - const requests = spec.buildRequests(bidRequests); - const request = requests[0]; + const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET'); expect(request.id).to.equal('30b31c1838de1e'); }); + it('should add consent parameters if gdprConsent is present', () => { + const gdprConsent = { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', gdprApplies: true }; + const fakeBidRequest = { gdprConsent: gdprConsent }; + const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; + expect(bidRequest.data.gdprApplies).to.eq(true); + expect(bidRequest.data.gdprConsent).to.eq('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + }); + it('should handle gdprConsent is present but values are undefined case', () => { + const gdprConsent = { consent_string: undefined, gdprApplies: undefined }; + const fakeBidRequest = { gdprConsent: gdprConsent }; + const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; + expect(bidRequest.data).to.not.include.any.keys('gdprConsent') + }); }) describe('interpretResponse', () => { From e9192abd14449529aa3285d5ac0366df9720813a Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 24 May 2018 15:49:32 -0400 Subject: [PATCH 0401/1594] update gdpr test page to use CMP stub setup code (#2616) * upadte gdpr test page to use proper CMP setup code * remove test comment --- integrationExamples/gpt/gdpr_hello_world.html | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/integrationExamples/gpt/gdpr_hello_world.html b/integrationExamples/gpt/gdpr_hello_world.html index 9f6194edb16..084310b57d2 100644 --- a/integrationExamples/gpt/gdpr_hello_world.html +++ b/integrationExamples/gpt/gdpr_hello_world.html @@ -1,7 +1,81 @@ - - + ', - adomain: ['clickonometrics.com'], - crid: '221', - w: 300, - h: 250, + banner: { + format: [ + { + w: 300, + h: 250 + } + ] + }, ext: { - type: 'standard' - } + pid: 607 + }, + id: '2e56e1af51a5d7', + secure: 1 }, { - id: '2e56e1af51a5d8_222', - impid: '2e56e1af51a5d8', - price: 5.68, - adid: '222', - adm: '', - adomain: ['clickonometrics.com'], - crid: '222', - w: 640, - h: 480, + video: { + w: 640, + h: 480, + protocols: [2, 3, 5, 6], + mimes: ['video/mp4', 'video/x-flv'], + playbackmethod: [1, 2, 3, 4], + skip: 0 + }, + id: '3u94t90ut39tt3t', + secure: 1, ext: { - type: 'video' + pid: 608 } } - ]} + ]; + + let response = spec.buildRequests(bidsClone, {'bids': bidsClone}); + let data = JSON.parse(response.data); + + expect(data.imp).to.deep.have.same.members(imps); + }); + it('Valid bid request - sizes old style - no media type', function () { + let bidsClone = utils.deepClone(bids); + delete (bidsClone[0].mediaTypes); + delete (bidsClone[1]); + + let imps = [ + { + banner: { + format: [ + { + w: 300, + h: 250 + } + ] + }, + ext: { + pid: 607 + }, + id: '2e56e1af51a5d7', + secure: 1 + } + ]; + + let response = spec.buildRequests(bidsClone, {'bids': bidsClone}); + let data = JSON.parse(response.data); + + expect(data.imp).to.deep.have.same.members(imps); + }); + }); + + let response = { + id: '0b9de793-8eda-481e-a548-c187d58b28d9', + seatbid: [ + { + bid: [ + { + id: '2e56e1af51a5d7_221', + impid: '2e56e1af51a5d7', + price: 8.1, + adid: '221', + adm: '', + adomain: ['clickonometrics.com'], + crid: '221', + w: 300, + h: 250, + ext: { + type: 'standard' + } + }, + { + id: '2e56e1af51a5d8_222', + impid: '2e56e1af51a5d8', + price: 5.68, + adid: '222', + adm: '', + adomain: ['clickonometrics.com'], + crid: '222', + w: 640, + h: 480, + ext: { + type: 'video' + } + } + ] + } ], cur: 'PLN', ext: { From 897155a4e0d83dc796d3a01f12cc8b587ae1b97c Mon Sep 17 00:00:00 2001 From: gammassp <35954362+gammassp@users.noreply.github.com> Date: Thu, 31 May 2018 00:15:46 +0700 Subject: [PATCH 0421/1594] Add encodeURIComponent to referer url (getTopWindowUrl) (#2609) * commit gamma adapter * Fixed The Travis CI build failed * fix interpretResponse return empty when server response empty * removed mediaType removed mediaType in bid and return vastXml property if video request * fixed Travis CI build * Travis CI build * add gamma spec * fixed Travis CI build * fix spec * fix spec * Add files via upload * Add files via upload * fix spec * fix Travis CI build * move to module * remove gaxDomain param and move to adapter * remove check isBidRequestValid for gaxDomain * remove gaxDomain param * remove gaxDomain param * remove gaxDomain param * Delete gammaBidAdapter_spec.js * add usersync endpoid * add usersync * add vastUrl * add supportedMediaTypes to bidder spec * add Test Parameters: For Video * Add encodeURIComponent for referer url --- modules/gammaBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gammaBidAdapter.js b/modules/gammaBidAdapter.js index 1fba73fd6ab..ce5c4ef2544 100644 --- a/modules/gammaBidAdapter.js +++ b/modules/gammaBidAdapter.js @@ -30,7 +30,7 @@ export const spec = { const gaxObjParams = find(bidRequests, hasParamInfo); return { method: 'GET', - url: '//' + ENDPOINT + '/adx/request?wid=' + gaxObjParams.params.siteId + '&zid=' + gaxObjParams.params.zoneId + '&hb=pbjs&bidid=' + gaxObjParams.bidId + '&urf=' + utils.getTopWindowUrl() + url: '//' + ENDPOINT + '/adx/request?wid=' + gaxObjParams.params.siteId + '&zid=' + gaxObjParams.params.zoneId + '&hb=pbjs&bidid=' + gaxObjParams.bidId + '&urf=' + encodeURIComponent(utils.getTopWindowUrl()) }; }, From 6d071f50d7bed44dbaeb21a3f72073e0efef5704 Mon Sep 17 00:00:00 2001 From: HolodovAlexander Date: Wed, 30 May 2018 20:20:20 +0300 Subject: [PATCH 0422/1594] Added Papyrus Bidder Adapter (#2620) --- modules/papyrusBidAdapter.js | 77 +++++++++++++ modules/papyrusBidAdapter.md | 41 +++++++ test/spec/modules/papyrusBidAdapter_spec.js | 115 ++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 modules/papyrusBidAdapter.js create mode 100644 modules/papyrusBidAdapter.md create mode 100644 test/spec/modules/papyrusBidAdapter_spec.js diff --git a/modules/papyrusBidAdapter.js b/modules/papyrusBidAdapter.js new file mode 100644 index 00000000000..1ece7fc7460 --- /dev/null +++ b/modules/papyrusBidAdapter.js @@ -0,0 +1,77 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const PAPYRUS_ENDPOINT = '//prebid.papyrus.global'; +const PAPYRUS_CODE = 'papyrus'; + +export const spec = { + code: PAPYRUS_CODE, + + /** + * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: bid => { + return !!(bid && bid.params && bid.params.address && bid.params.placementId); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests) { + const bidParams = []; + utils._each(validBidRequests, function(bid) { + bidParams.push({ + address: bid.params.address, + placementId: bid.params.placementId, + bidId: bid.bidId, + transactionId: bid.transactionId, + sizes: utils.parseSizesInput(bid.sizes) + }); + }); + + return { + method: 'POST', + url: PAPYRUS_ENDPOINT, + data: bidParams + }; + }, + + /** + * 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 = []; + + if (serverResponse && serverResponse.body && serverResponse.body.bids) { + serverResponse.body.bids.forEach(bid => { + const bidResponse = { + requestId: bid.id, + creativeId: bid.id, + adId: bid.id, + transactionId: bid.transactionId, + cpm: bid.cpm, + width: bid.width, + height: bid.height, + currency: bid.currency, + netRevenue: true, + ttl: 300, + ad: bid.ad + } + bidResponses.push(bidResponse); + }); + } + + return bidResponses; + } +}; + +registerBidder(spec); diff --git a/modules/papyrusBidAdapter.md b/modules/papyrusBidAdapter.md new file mode 100644 index 00000000000..98a42e542ec --- /dev/null +++ b/modules/papyrusBidAdapter.md @@ -0,0 +1,41 @@ +# Overview + +``` +Module Name: Papyrus Bid Adapter +Module Type: Bidder Adapter +Maintainer: alexander.holodov@papyrus.global +``` + +# Description + +Connect to Papyrus system for bids. + +Papyrus bid adapter supports Banner. + +Please contact to info@papyrus.global for +further details + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [ + [320, 50] + ] + } + }, + bids: [ + { + bidder: 'papyrus', + params: { + address: '0xd7e2a771c5dcd5df7f789477356aecdaeee6c985', + placementId: 'b57e55fd18614b0591893e9fff41fbea' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/papyrusBidAdapter_spec.js b/test/spec/modules/papyrusBidAdapter_spec.js new file mode 100644 index 00000000000..a61a1c55269 --- /dev/null +++ b/test/spec/modules/papyrusBidAdapter_spec.js @@ -0,0 +1,115 @@ +import { expect } from 'chai'; +import { spec } from 'modules/papyrusBidAdapter'; + +const ENDPOINT = '//prebid.papyrus.global'; +const BIDDER_CODE = 'papyrus'; + +describe('papyrus Adapter', () => { + describe('isBidRequestValid', () => { + let validBidReq = { + bidder: BIDDER_CODE, + params: { + address: '0xd7e2a771c5dcd5df7f789477356aecdaeee6c985', + placementId: 'b57e55fd18614b0591893e9fff41fbea' + } + }; + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(validBidReq)).to.equal(true); + }); + + let invalidBidReq = { + bidder: BIDDER_CODE, + params: { + 'placementId': '' + } + }; + + it('should not validate incorrect bid request', () => { + expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + bidder: BIDDER_CODE, + params: { + address: '0xd7e2a771c5dcd5df7f789477356aecdaeee6c985', + placementId: 'b57e55fd18614b0591893e9fff41fbea' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('sends bid request to ENDPOINT via POST', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('POST'); + }); + + it('sends valid bids count', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data.length).to.equal(1); + }); + + it('sends all bid parameters', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data[0]).to.have.all.keys(['address', 'placementId', 'sizes', 'bidId', 'transactionId']); + }); + + it('sedns valid sizes parameter', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data[0].sizes[0]).to.equal('300x250'); + }); + }); + + describe('interpretResponse', () => { + let bidRequests = [ + { + bidder: BIDDER_CODE, + params: { + address: '0xd7e2a771c5dcd5df7f789477356aecdaeee6c985', + placementId: 'b57e55fd18614b0591893e9fff41fbea' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + let bidResponse = { + bids: [ + { + id: '1036e9746c-d186-49ae-90cb-2796d0f9b223', + adm: 'test adm', + cpm: 100, + height: 250, + width: 300 + } + ] + }; + + it('should build bid array', () => { + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({body: bidResponse}, request[0]); + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', () => { + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({body: bidResponse}, request[0]); + const bid = result[0]; + + expect(bid.cpm).to.equal(bidResponse.bids[0].cpm); + expect(bid.width).to.equal(bidResponse.bids[0].width); + expect(bid.height).to.equal(bidResponse.bids[0].height); + }); + }); +}); From 4bde2a1507b8f82c32bd8ceb70bc1fa6c521698b Mon Sep 17 00:00:00 2001 From: Old Tiger Date: Wed, 30 May 2018 15:57:37 -0400 Subject: [PATCH 0423/1594] Arteebee adapter GDPR integration (#2643) * add arteebee adapter * set log * basic structure * basic structure * send caller as placeholder for ip and user agent * send caller as placeholder for ip and user agent * send caller as placeholder for ip and user agent * first version of adapter * add unit testing for arteebee bid adapter * fix indent * fix lint complain * Add consent manager support * fix requestId missing --- modules/arteebeeBidAdapter.js | 26 +++++++++++++----- test/spec/modules/arteebeeBidAdapter_spec.js | 28 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/modules/arteebeeBidAdapter.js b/modules/arteebeeBidAdapter.js index 65510b43bc0..e8d319c8845 100644 --- a/modules/arteebeeBidAdapter.js +++ b/modules/arteebeeBidAdapter.js @@ -16,11 +16,11 @@ export const spec = { return 'params' in bidRequest && bidRequest.params.pub !== undefined && bidRequest.params.source !== undefined; }, - buildRequests: function (validBidRequests) { + buildRequests: function (validBidRequests, bidderRequest) { var requests = []; for (let i = 0; i < validBidRequests.length; i++) { - let prebidReq = makePrebidRequest(validBidRequests[i]); + let prebidReq = makePrebidRequest(validBidRequests[i], bidderRequest); if (prebidReq) { requests.push(prebidReq); } @@ -58,20 +58,20 @@ export const spec = { } return bidResponses; }, - getUserSyncs: function (syncOptions, serverResponses) { + getUserSyncs: function (syncOptions, serverResponses, gdprConsent) { return []; } } registerBidder(spec); -function makePrebidRequest(req) { +function makePrebidRequest(req, bidderRequest) { var host = req.params.host || DEFAULT_HOST; var ssp = req.params.ssp || DEFAULT_SSP; var url = window.location.protocol + '//' + host + '/rtb/bid/' + ssp + '?type=json®ister=0'; - const payload = makeRtbRequest(req); + const payload = makeRtbRequest(req, bidderRequest); const payloadString = JSON.stringify(payload); return { @@ -81,8 +81,8 @@ function makePrebidRequest(req) { }; } -function makeRtbRequest(req) { - var auctionId = req.requestId; +function makeRtbRequest(req, bidderRequest) { + var auctionId = req.bidderRequestId; var imp = []; imp.push(makeImp(req)); @@ -100,6 +100,18 @@ function makeRtbRequest(req) { rtbReq.regs = {coppa: 1}; } + if (bidderRequest && bidderRequest.gdprConsent) { + if ((typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') && bidderRequest.gdprConsent.gdprApplies) { + if (!rtbReq.regs) { + rtbReq.regs = {}; + } + rtbReq.regs['ext'] = {'gdpr': 1}; + } + if ((typeof bidderRequest.gdprConsent.consentString === 'string') && bidderRequest.gdprConsent.consentString) { + rtbReq['user'] = {'ext': {'consent': bidderRequest.gdprConsent.consentString}}; + } + } + if (req.params.test) { rtbReq.test = 1; } diff --git a/test/spec/modules/arteebeeBidAdapter_spec.js b/test/spec/modules/arteebeeBidAdapter_spec.js index fe5bbf7ff25..041b48b0bc9 100644 --- a/test/spec/modules/arteebeeBidAdapter_spec.js +++ b/test/spec/modules/arteebeeBidAdapter_spec.js @@ -94,6 +94,34 @@ describe('Arteebee adapater', () => { expect(req).to.not.have.property('test'); expect(req.imp[0]).to.not.have.property('secure'); }); + + it('test gdpr', () => { + let bid = { + bidder: 'arteebee', + params: { + pub: 'prebidtest', + source: 'prebidtest' + }, + sizes: [[300, 250]] + }; + let consentString = 'ABCD'; + let bidderRequest = { + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + + const req = JSON.parse(spec.buildRequests([bid], bidderRequest)[0].data); + + expect(req.regs).to.exist; + expect(req.regs.ext).to.exist; + expect(req.regs.ext).to.have.property('gdpr', 1); + + expect(req.user).to.exist; + expect(req.user.ext).to.exist; + expect(req.user.ext).to.have.property('consent', consentString); + }); }); describe('Test interpret response', () => { From ca48109395217d2f14b70ef656f2e77de5be2220 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 30 May 2018 13:52:57 -0700 Subject: [PATCH 0424/1594] fix gambidBidAdapter with startsWith polyfill and stubbing getTopWindowUrl --- modules/gambidBidAdapter.js | 18 +++---------- test/spec/modules/gambidBidAdapter_spec.js | 30 ++++++++++++---------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/modules/gambidBidAdapter.js b/modules/gambidBidAdapter.js index f925c2a5b14..e87c28acc77 100644 --- a/modules/gambidBidAdapter.js +++ b/modules/gambidBidAdapter.js @@ -10,22 +10,12 @@ function getTopFrame() { } } -function getTopWindowUrl() { - try { - return window.top.location.href; - } catch (e) { - utils.logMessage('Failed obtaining top window\'s URL: ', e); - try { - return window.location.href; - } catch (e) { - utils.logMessage('Failed obtaining current window\'s URL: ', e); - return ''; - } - } +function startsWith(str, search) { + return str.substr(0, search.length) === search; } function getTopWindowDomain() { - const url = getTopWindowUrl(); + const url = utils.getTopWindowUrl(); const domainStart = url.indexOf('://') + '://'.length; return url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)); } @@ -89,7 +79,7 @@ export const spec = { 'tagid': adUnitCode, 'bidfloor': params.bidfloor || 0, 'bidfloorcur': 'USD', - 'secure': getTopWindowUrl().toLowerCase().startsWith('http://') ? 0 : 1 + 'secure': startsWith(utils.getTopWindowUrl().toLowerCase(), 'http://') ? 0 : 1 }; if (!mediaTypes || mediaTypes.banner) { diff --git a/test/spec/modules/gambidBidAdapter_spec.js b/test/spec/modules/gambidBidAdapter_spec.js index 13a208641f7..54b9c518e2b 100644 --- a/test/spec/modules/gambidBidAdapter_spec.js +++ b/test/spec/modules/gambidBidAdapter_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { spec } from 'modules/gambidBidAdapter'; -import { deepClone } from 'src/utils'; +import * as utils from 'src/utils'; const supplyPartnerId = '123'; @@ -60,8 +60,8 @@ describe('GambidAdapter', () => { expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); - const adUnit1 = Object.assign({}, deepClone(bidRequest), { auctionId: '1', adUnitCode: 'a' }); - const adUnit2 = Object.assign({}, deepClone(bidRequest), { auctionId: '1', adUnitCode: 'b' }); + const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'a' }); + const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'b' }); response = spec.buildRequests([adUnit1, adUnit2]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); @@ -75,17 +75,19 @@ describe('GambidAdapter', () => { expect(response.url).to.match(new RegExp(`^https://rtb\\.gambid\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&bidder=prebid$`, 'g')); expect(response.data.id).to.equal(bidRequest.auctionId); - const bidRequestWithEndpoint = deepClone(bidRequest); + const bidRequestWithEndpoint = utils.deepClone(bidRequest); bidRequestWithEndpoint.params.rtbEndpoint = 'https://rtb2.gambid.io/a12'; response = spec.buildRequests([ bidRequestWithEndpoint ])[ 0 ]; expect(response.url).to.match(new RegExp(`^https://rtb2\\.gambid\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&bidder=prebid$`, 'g')); }); it('builds request correctly', () => { + let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); + let response; response = spec.buildRequests([ bidRequest ])[ 0 ]; - expect(response.data.site.domain).to.match(new RegExp(`^localhost:\\d+$`)); - expect(response.data.site.page).to.match(new RegExp(`^http://localhost:\\d+/$`)); + expect(response.data.site.domain).to.equal('www.test.com'); + expect(response.data.site.page).to.equal('http://www.test.com/page.html'); expect(response.data.site.ref).to.equal(''); expect(response.data.imp.length).to.equal(1); expect(response.data.imp[ 0 ].id).to.equal(bidRequest.transactionId); @@ -94,26 +96,28 @@ describe('GambidAdapter', () => { expect(response.data.imp[ 0 ].bidfloor).to.equal(0); expect(response.data.imp[ 0 ].bidfloorcur).to.equal('USD'); - const bidRequestWithInstlEquals1 = deepClone(bidRequest); + const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); bidRequestWithInstlEquals1.params.instl = 1; response = spec.buildRequests([ bidRequestWithInstlEquals1 ])[ 0 ]; expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals1.params.instl); - const bidRequestWithInstlEquals0 = deepClone(bidRequest); + const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); bidRequestWithInstlEquals0.params.instl = 1; response = spec.buildRequests([ bidRequestWithInstlEquals0 ])[ 0 ]; expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals0.params.instl); - const bidRequestWithBidfloorEquals1 = deepClone(bidRequest); + const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); bidRequestWithBidfloorEquals1.params.bidfloor = 1; response = spec.buildRequests([ bidRequestWithBidfloorEquals1 ])[ 0 ]; expect(response.data.imp[ 0 ].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); + + stub.restore(); }); it('builds request banner object correctly', () => { let response; - const bidRequestWithBanner = deepClone(bidRequest); + const bidRequestWithBanner = utils.deepClone(bidRequest); bidRequestWithBanner.mediaTypes = { banner: { sizes: [ [ 300, 250 ], [ 120, 600 ] ] @@ -126,7 +130,7 @@ describe('GambidAdapter', () => { expect(response.data.imp[ 0 ].banner.pos).to.equal(0); expect(response.data.imp[ 0 ].banner.topframe).to.equal(0); - const bidRequestWithPosEquals1 = deepClone(bidRequestWithBanner); + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); bidRequestWithPosEquals1.params.pos = 1; response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; expect(response.data.imp[ 0 ].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); @@ -135,7 +139,7 @@ describe('GambidAdapter', () => { it('builds request video object correctly', () => { let response; - const bidRequestWithVideo = deepClone(bidRequest); + const bidRequestWithVideo = utils.deepClone(bidRequest); bidRequestWithVideo.mediaTypes = { video: { sizes: [ [ 300, 250 ], [ 120, 600 ] ] @@ -148,7 +152,7 @@ describe('GambidAdapter', () => { expect(response.data.imp[ 0 ].video.pos).to.equal(0); expect(response.data.imp[ 0 ].video.topframe).to.equal(0); - const bidRequestWithPosEquals1 = deepClone(bidRequestWithVideo); + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); bidRequestWithPosEquals1.params.pos = 1; response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; expect(response.data.imp[ 0 ].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); From e81384b63df25866310868b939d1140fab1062e3 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 30 May 2018 13:53:31 -0700 Subject: [PATCH 0425/1594] Revert "New debugging functionality with bid overrides (#2492)" This reverts commit 48bd7b8ca643f62f79f103b0766c0154a0044e92. --- src/debugging.js | 89 ----------------------- src/hook.js | 3 - src/prebid.js | 4 - test/spec/debugging_spec.js | 141 ------------------------------------ 4 files changed, 237 deletions(-) delete mode 100644 src/debugging.js delete mode 100644 test/spec/debugging_spec.js diff --git a/src/debugging.js b/src/debugging.js deleted file mode 100644 index 39ddc92beee..00000000000 --- a/src/debugging.js +++ /dev/null @@ -1,89 +0,0 @@ - -import { config } from 'src/config'; -import { logMessage as utilsLogMessage, logWarn as utilsLogWarn } from 'src/utils'; -import { addBidResponse } from 'src/auction'; - -const OVERRIDE_KEY = '$$PREBID_GLOBAL$$:debugging'; - -export let boundHook; - -function logMessage(msg) { - utilsLogMessage('DEBUG: ' + msg); -} - -function logWarn(msg) { - utilsLogWarn('DEBUG: ' + msg); -} - -function enableOverrides(overrides, fromSession = false) { - config.setConfig({'debug': true}); - logMessage(`bidder overrides enabled${fromSession ? ' from session' : ''}`); - - if (boundHook) { - addBidResponse.removeHook(boundHook); - } - - boundHook = addBidResponseHook.bind(null, overrides); - addBidResponse.addHook(boundHook, 5); -} - -export function disableOverrides() { - if (boundHook) { - addBidResponse.removeHook(boundHook); - logMessage('bidder overrides disabled'); - } -} - -export function addBidResponseHook(overrides, adUnitCode, bid, next) { - if (Array.isArray(overrides.bidders) && overrides.bidders.indexOf(bid.bidderCode) === -1) { - logWarn(`bidder '${bid.bidderCode}' excluded from auction by bidder overrides`); - return; - } - - if (Array.isArray(overrides.bids)) { - overrides.bids.forEach(overrideBid => { - if (overrideBid.bidder && overrideBid.bidder !== bid.bidderCode) { - return; - } - if (overrideBid.adUnitCode && overrideBid.adUnitCode !== adUnitCode) { - return; - } - - bid = Object.assign({}, bid); - - Object.keys(overrideBid).filter(key => ['bidder', 'adUnitCode'].indexOf(key) === -1).forEach((key) => { - let value = overrideBid[key]; - logMessage(`bidder overrides changed '${adUnitCode}/${bid.bidderCode}' bid.${key} from '${bid[key]}' to '${value}'`); - bid[key] = value; - }); - }); - } - - next(adUnitCode, bid); -} - -export function getConfig(debugging) { - if (!debugging.enabled) { - disableOverrides(); - try { - window.sessionStorage.removeItem(OVERRIDE_KEY); - } catch (e) {} - } else { - try { - window.sessionStorage.setItem(OVERRIDE_KEY, JSON.stringify(debugging)); - } catch (e) {} - enableOverrides(debugging); - } -} -config.getConfig('debugging', ({debugging}) => getConfig(debugging)); - -export function sessionLoader() { - let overrides; - try { - overrides = JSON.parse(window.sessionStorage.getItem(OVERRIDE_KEY)); - } catch (e) { - } - if (overrides) { - enableOverrides(overrides, true); - } -} diff --git a/src/hook.js b/src/hook.js index fef62a37c3d..6c6cefdc56c 100644 --- a/src/hook.js +++ b/src/hook.js @@ -60,9 +60,6 @@ export function createHook(type, fn, hookName) { }, removeHook: function(removeFn) { _hooks = _hooks.filter(hook => hook.fn === fn || hook.fn !== removeFn); - }, - hasHook: function(fn) { - return _hooks.some(hook => hook.fn === fn); } }; diff --git a/src/prebid.js b/src/prebid.js index d4fbe17a501..d703df43bf5 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -9,7 +9,6 @@ import { config } from './config'; import { auctionManager } from './auctionManager'; import { targeting, getOldestBid, RENDERED, BID_TARGETING_SET } from './targeting'; import { createHook } from 'src/hook'; -import { sessionLoader } from 'src/debugging'; import includes from 'core-js/library/fn/array/includes'; const $$PREBID_GLOBAL$$ = getGlobal(); @@ -28,9 +27,6 @@ const eventValidators = { bidWon: checkDefinedPlacement }; -// initialize existing debugging sessions if present -sessionLoader(); - /* Public vars */ $$PREBID_GLOBAL$$.bidderSettings = $$PREBID_GLOBAL$$.bidderSettings || {}; diff --git a/test/spec/debugging_spec.js b/test/spec/debugging_spec.js deleted file mode 100644 index 39b08075e06..00000000000 --- a/test/spec/debugging_spec.js +++ /dev/null @@ -1,141 +0,0 @@ - -import { expect } from 'chai'; -import { sessionLoader, addBidResponseHook, getConfig, disableOverrides, boundHook } from 'src/debugging'; -import { addBidResponse } from 'src/auction'; -import { config } from 'src/config'; - -describe('bid overrides', () => { - let sandbox; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('initialization', () => { - beforeEach(() => { - sandbox.stub(config, 'setConfig'); - sandbox.stub(window.sessionStorage, 'setItem'); - sandbox.stub(window.sessionStorage, 'removeItem'); - }); - - afterEach(() => { - disableOverrides(); - }); - - it('should happen when enabled with setConfig', () => { - getConfig({ - enabled: true - }); - - expect(addBidResponse.hasHook(boundHook)).to.equal(true); - }); - - it('should happen when configuration found in sessionStorage', () => { - sandbox.stub(window.sessionStorage, 'getItem').returns('{"enabled": true}'); - - sessionLoader(); - expect(addBidResponse.hasHook(boundHook)).to.equal(true); - }); - - it('should not throw if sessionStorage is inaccessible', () => { - sandbox.stub(window.sessionStorage, 'getItem').throws(); - - expect(() => { - sessionLoader(); - }).not.to.throw(); - }); - }); - - describe('hook', () => { - let mockBids; - let bids; - - beforeEach(() => { - let baseBid = { - 'bidderCode': 'rubicon', - 'width': 970, - 'height': 250, - 'statusMessage': 'Bid available', - 'mediaType': 'banner', - 'source': 'client', - 'currency': 'USD', - 'cpm': 0.5, - 'ttl': 300, - 'netRevenue': false, - 'adUnitCode': '/19968336/header-bid-tag-0' - }; - mockBids = []; - mockBids.push(baseBid); - mockBids.push(Object.assign({}, baseBid, { - bidderCode: 'appnexus' - })); - - bids = []; - }); - - function run(overrides) { - mockBids.forEach(bid => { - addBidResponseHook(overrides, bid.adUnitCode, bid, (adUnitCode, bid) => { - bids.push(bid); - }) - }); - } - - it('should allow us to exclude bidders', () => { - run({ - enabled: true, - bidders: ['appnexus'] - }); - - expect(bids.length).to.equal(1); - expect(bids[0].bidderCode).to.equal('appnexus'); - }); - - it('should allow us to override all bids', () => { - run({ - enabled: true, - bids: [{ - cpm: 2 - }] - }); - - expect(bids.length).to.equal(2); - expect(bids[0].cpm).to.equal(2); - expect(bids[1].cpm).to.equal(2); - }); - - it('should allow us to override bids by bidder', () => { - run({ - enabled: true, - bids: [{ - bidder: 'rubicon', - cpm: 2 - }] - }); - - expect(bids.length).to.equal(2); - expect(bids[0].cpm).to.equal(2); - expect(bids[1].cpm).to.equal(0.5); - }); - - it('should allow us to override bids by adUnitCode', () => { - mockBids[1].adUnitCode = 'test'; - - run({ - enabled: true, - bids: [{ - adUnitCode: 'test', - cpm: 2 - }] - }); - - expect(bids.length).to.equal(2); - expect(bids[0].cpm).to.equal(0.5); - expect(bids[1].cpm).to.equal(2); - }); - }); -}); From 64ecd564e5d6540d52892d4286e37815f996ccb1 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 30 May 2018 15:34:48 -0600 Subject: [PATCH 0426/1594] fix mediaType regression in rubicon adapter (#2658) --- modules/rubiconBidAdapter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index a43c7b504f0..46d53e22ab7 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -390,7 +390,6 @@ export const spec = { requestId: associatedBidRequest.bidId, currency: 'USD', creativeId: ad.creative_id, - mediaType: ad.creative_type, cpm: ad.cpm || 0, dealId: ad.deal, ttl: 300, // 5 minutes From 0f14b96e58159f6bbd000f28f75bc4e748a9d80c Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 30 May 2018 18:16:20 -0400 Subject: [PATCH 0427/1594] Update bid pool logic to use highest cpm bid (#2654) * update bid pool logic to use highest cpm bid * updates to cover https://github.com/prebid/Prebid.js/issues/2539 * typo in property name --- src/prebid.js | 6 +-- src/targeting.js | 54 +++++++++++++-------------- src/utils.js | 22 ++++++++--- test/spec/unit/core/targeting_spec.js | 6 +-- test/spec/utils_spec.js | 40 +++++++++++++++++--- 5 files changed, 83 insertions(+), 45 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index d703df43bf5..7d84ffa5554 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -1,13 +1,13 @@ /** @module pbjs */ import { getGlobal } from './prebidGlobal'; -import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId } from './utils'; +import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId, getLatestHighestCpmBid } from './utils'; import { listenMessagesFromCreative } from './secureCreatives'; import { userSync } from 'src/userSync.js'; import { loadScript } from './adloader'; import { config } from './config'; import { auctionManager } from './auctionManager'; -import { targeting, getOldestBid, RENDERED, BID_TARGETING_SET } from './targeting'; +import { targeting, getHighestCpmBidsFromBidPool, RENDERED, BID_TARGETING_SET } from './targeting'; import { createHook } from 'src/hook'; import includes from 'core-js/library/fn/array/includes'; @@ -589,7 +589,7 @@ $$PREBID_GLOBAL$$.getAllPrebidWinningBids = function () { * @return {Array} array containing highest cpm bid object(s) */ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { - let bidsReceived = auctionManager.getBidsReceived().filter(getOldestBid); + let bidsReceived = getHighestCpmBidsFromBidPool(auctionManager.getBidsReceived(), getLatestHighestCpmBid); return targeting.getWinningBids(adUnitCode, bidsReceived) .map(removeRequestId); }; diff --git a/src/targeting.js b/src/targeting.js index 2d449153b26..7a301472823 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -1,4 +1,4 @@ -import { uniques, isGptPubadsDefined, getHighestCpm, groupBy, isAdUnitCodeMatchingSlot, timestamp } from './utils'; +import { uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp } from './utils'; import { config } from './config'; import { NATIVE_TARGETING_KEYS } from './native'; import { auctionManager } from './auctionManager'; @@ -21,17 +21,27 @@ export const isBidExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 + T // return bids whose status is not set. Winning bid can have status `targetingSet` or `rendered`. const isUnusedBid = (bid) => bid && ((bid.status && !includes([BID_TARGETING_SET, RENDERED], bid.status)) || !bid.status); -// If two bids are found for same adUnitCode, we will use the latest one to take part in auction +// If two bids are found for same adUnitCode, we will use the highest one to take part in auction // This can happen in case of concurrent auctions -export const getOldestBid = function(bid, i, arr) { - let oldestBid = true; - arr.forEach((val, j) => { - if (i === j) return; - if (bid.bidder === val.bidder && bid.adUnitCode === val.adUnitCode && bid.responseTimestamp > val.responseTimestamp) { - oldestBid = false; - } +export function getHighestCpmBidsFromBidPool(bidsReceived, highestCpmCallback) { + const bids = []; + // bucket by adUnitcode + let buckets = groupBy(bidsReceived, 'adUnitCode'); + // filter top bid for each bucket by bidder + Object.keys(buckets).forEach(bucketKey => { + let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); + Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(highestCpmCallback, getEmptyBid()))); }); - return oldestBid; + return bids; +} + +function getEmptyBid(adUnitCode) { + return { + adUnitCode: adUnitCode, + cpm: 0, + adserverTargeting: {}, + timeToRespond: 0 + }; } /** @@ -174,11 +184,12 @@ export function newTargeting(auctionManager) { } function getBidsReceived() { - return auctionManager.getBidsReceived() + const bidsReceived = auctionManager.getBidsReceived() .filter(isUnusedBid) .filter(exports.isBidExpired) - .filter(getOldestBid) ; + + return getHighestCpmBidsFromBidPool(bidsReceived, getOldestHighestCpmBid); } /** @@ -334,14 +345,9 @@ export function newTargeting(auctionManager) { */ function getBidLandscapeTargeting(adUnitCodes, bidsReceived) { const standardKeys = CONSTANTS.TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); - const bids = []; - // bucket by adUnitcode - let buckets = groupBy(bidsReceived, 'adUnitCode'); - // filter top bid for each bucket by bidder - Object.keys(buckets).forEach(bucketKey => { - let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); - Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(getHighestCpm, getEmptyBid()))); - }); + + const bids = getHighestCpmBidsFromBidPool(bidsReceived, getHighestCpm); + // populate targeting keys for the remaining bids return bids.map(bid => { if ( @@ -372,14 +378,6 @@ export function newTargeting(auctionManager) { } }; - function getEmptyBid(adUnitCode) { - return { - adUnitCode: adUnitCode, - cpm: 0, - adserverTargeting: {}, - timeToRespond: 0 - }; - } return targeting; } diff --git a/src/utils.js b/src/utils.js index 2b93fc0902d..678f61de87e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -717,12 +717,24 @@ export function isGptPubadsDefined() { } } -export function getHighestCpm(previous, current) { - if (previous.cpm === current.cpm) { - return previous.timeToRespond > current.timeToRespond ? current : previous; - } +// This function will get highest cpm value bid, in case of tie it will return the bid with lowest timeToRespond +export const getHighestCpm = getHighestCpmCallback('timeToRespond', (previous, current) => previous > current); + +// This function will get the oldest hightest cpm value bid, in case of tie it will return the bid which came in first +// Use case for tie: https://github.com/prebid/Prebid.js/issues/2448 +export const getOldestHighestCpmBid = getHighestCpmCallback('responseTimestamp', (previous, current) => previous > current); + +// This function will get the latest hightest cpm value bid, in case of tie it will return the bid which came in last +// Use case for tie: https://github.com/prebid/Prebid.js/issues/2539 +export const getLatestHighestCpmBid = getHighestCpmCallback('responseTimestamp', (previous, current) => previous < current); - return previous.cpm < current.cpm ? current : previous; +function getHighestCpmCallback(useTieBreakerProperty, tieBreakerCallback) { + return (previous, current) => { + if (previous.cpm === current.cpm) { + return tieBreakerCallback(previous[useTieBreakerProperty], current[useTieBreakerProperty]) ? current : previous; + } + return previous.cpm < current.cpm ? current : previous; + } } /** diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 1fa648e9825..048e19a6177 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -183,13 +183,13 @@ describe('targeting tests', () => { expect(bids[1].adId).to.equal('adid-3'); }); - it('should use oldest bids from bid pool to get winning bid', () => { - // Pool is having 4 bids from 2 auctions. There are 2 bids from rubicon, #2 which is first bid will be selected to take part in auction. + it('should use highest cpm bid from bid pool to get winning bid', () => { + // Pool is having 4 bids from 2 auctions. There are 2 bids from rubicon, #2 which is highest cpm bid will be selected to take part in auction. let bidsReceived = [ createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), createBidReceived({bidder: 'rubicon', cpm: 9, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-0', adId: 'adid-2'}), createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), - createBidReceived({bidder: 'rubicon', cpm: 10, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-0', adId: 'adid-4'}), + createBidReceived({bidder: 'rubicon', cpm: 8, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-0', adId: 'adid-4'}), ]; auctionManagerStub.returns(bidsReceived); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 6860605d343..454d6ed4136 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -506,11 +506,11 @@ describe('Utils', function () { describe('getHighestCpm', function () { it('should pick the existing highest cpm', function () { - var previous = { + let previous = { cpm: 2, timeToRespond: 100 }; - var current = { + let current = { cpm: 1, timeToRespond: 100 }; @@ -518,11 +518,11 @@ describe('Utils', function () { }); it('should pick the new highest cpm', function () { - var previous = { + let previous = { cpm: 1, timeToRespond: 100 }; - var current = { + let current = { cpm: 2, timeToRespond: 100 }; @@ -530,16 +530,44 @@ describe('Utils', function () { }); it('should pick the fastest cpm in case of tie', function () { - var previous = { + let previous = { cpm: 1, timeToRespond: 100 }; - var current = { + let current = { cpm: 1, timeToRespond: 50 }; assert.equal(utils.getHighestCpm(previous, current), current); }); + + it('should pick the oldest in case of tie using responseTimeStamp', function () { + let previous = { + cpm: 1, + timeToRespond: 100, + responseTimestamp: 1000 + }; + let current = { + cpm: 1, + timeToRespond: 50, + responseTimestamp: 2000 + }; + assert.equal(utils.getOldestHighestCpmBid(previous, current), previous); + }); + + it('should pick the latest in case of tie using responseTimeStamp', function () { + let previous = { + cpm: 1, + timeToRespond: 100, + responseTimestamp: 1000 + }; + let current = { + cpm: 1, + timeToRespond: 50, + responseTimestamp: 2000 + }; + assert.equal(utils.getLatestHighestCpmBid(previous, current), current); + }); }); describe('polyfill test', function () { From a417697ed0f7efedfcb0c2cda92889e4e442475a Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 30 May 2018 20:33:02 -0400 Subject: [PATCH 0428/1594] fix cpm floor issue in price bucket formula (#2644) * fix cpm rounding issue in price bucket formula * switch logic to exponent variant instead of precision rounding * update min precision to 2 for exponent * fixed addition --- src/cpmBucketManager.js | 8 +++- test/fixtures/cpmInputsOutputs.json | 4 +- test/spec/cpmBucketManager_spec.js | 74 +++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/cpmBucketManager.js b/src/cpmBucketManager.js index c2250838bcb..a435f356a53 100644 --- a/src/cpmBucketManager.js +++ b/src/cpmBucketManager.js @@ -124,7 +124,13 @@ function getCpmTarget(cpm, bucket, granularityMultiplier) { const bucketMin = bucket.min * granularityMultiplier; // start increments at the bucket min and then add bucket min back to arrive at the correct rounding - let cpmTarget = ((Math.floor((cpm - bucketMin) / increment)) * increment) + bucketMin; + // note - we're padding the values to avoid using decimals in the math prior to flooring + // this is done as JS can return values slightly below the expected mark which would skew the price bucket target + // (eg 4.01 / 0.01 = 400.99999999999994) + // min precison should be 2 to move decimal place over. + let pow = Math.pow(10, precision + 2); + let cpmToFloor = ((cpm * pow) - (bucketMin * pow)) / (increment * pow); + let cpmTarget = ((Math.floor(cpmToFloor)) * increment) + bucketMin; // force to 10 decimal places to deal with imprecise decimal/binary conversions // (for example 0.1 * 3 = 0.30000000000000004) cpmTarget = Number(cpmTarget.toFixed(10)); diff --git a/test/fixtures/cpmInputsOutputs.json b/test/fixtures/cpmInputsOutputs.json index b24b0c00c8d..7569eef6e97 100644 --- a/test/fixtures/cpmInputsOutputs.json +++ b/test/fixtures/cpmInputsOutputs.json @@ -1,4 +1,4 @@ { - "cpmInputs": ["17.638", "19.836", "11.501", "14.384", "23.224", "21.279", "8.886", "16.555", "10.579", "1.331", "1.998", "14.988", "14.864", "10.369", "0.262", "5.269", "6.874", "5.598", "7.191", "15.218", "10.958", "4.420", "17.749", "23.808", "12.353", "21.726", "1.562", "18.085", "1.184", "15.470", "13.841", "17.966", "22.150", "9.088", "13.613", "18.384", "13.690", "23.639", "5.085", "5.779", "11.456", "0.315", "18.557", "20.813", "18.813", "10.202", "10.143", "2.483", "16.147", "2.909", "0.652"], - "priceStringOutputs": [{"low":"5.00","med":"17.60","high":"17.63","auto":"17.50","dense":"17.50","custom":""},{"low":"5.00","med":"19.80","high":"19.83","auto":"19.50","dense":"19.50","custom":""},{"low":"5.00","med":"11.50","high":"11.50","auto":"11.50","dense":"11.50","custom":""},{"low":"5.00","med":"14.30","high":"14.38","auto":"14.00","dense":"14.00","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"8.80","high":"8.88","auto":"8.80","dense":"8.50","custom":""},{"low":"5.00","med":"16.50","high":"16.55","auto":"16.50","dense":"16.50","custom":""},{"low":"5.00","med":"10.50","high":"10.57","auto":"10.50","dense":"10.50","custom":""},{"low":"1.00","med":"1.30","high":"1.33","auto":"1.30","dense":"1.33","custom":""},{"low":"1.50","med":"1.90","high":"1.99","auto":"1.95","dense":"1.99","custom":""},{"low":"5.00","med":"14.90","high":"14.98","auto":"14.50","dense":"14.50","custom":""},{"low":"5.00","med":"14.80","high":"14.86","auto":"14.50","dense":"14.50","custom":""},{"low":"5.00","med":"10.30","high":"10.36","auto":"10.00","dense":"10.00","custom":""},{"low":"0.00","med":"0.20","high":"0.26","auto":"0.25","dense":"0.26","custom":""},{"low":"5.00","med":"5.20","high":"5.26","auto":"5.20","dense":"5.25","custom":""},{"low":"5.00","med":"6.80","high":"6.87","auto":"6.80","dense":"6.85","custom":""},{"low":"5.00","med":"5.50","high":"5.59","auto":"5.50","dense":"5.55","custom":""},{"low":"5.00","med":"7.10","high":"7.19","auto":"7.10","dense":"7.15","custom":""},{"low":"5.00","med":"15.20","high":"15.21","auto":"15.00","dense":"15.00","custom":""},{"low":"5.00","med":"10.90","high":"10.95","auto":"10.50","dense":"10.50","custom":""},{"low":"4.00","med":"4.40","high":"4.42","auto":"4.40","dense":"4.40","custom":""},{"low":"5.00","med":"17.70","high":"17.74","auto":"17.50","dense":"17.50","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"12.30","high":"12.35","auto":"12.00","dense":"12.00","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"1.50","med":"1.50","high":"1.56","auto":"1.55","dense":"1.56","custom":""},{"low":"5.00","med":"18.00","high":"18.08","auto":"18.00","dense":"18.00","custom":""},{"low":"1.00","med":"1.10","high":"1.18","auto":"1.15","dense":"1.18","custom":""},{"low":"5.00","med":"15.40","high":"15.47","auto":"15.00","dense":"15.00","custom":""},{"low":"5.00","med":"13.80","high":"13.84","auto":"13.50","dense":"13.50","custom":""},{"low":"5.00","med":"17.90","high":"17.96","auto":"17.50","dense":"17.50","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"9.00","high":"9.08","auto":"9.00","dense":"9.00","custom":""},{"low":"5.00","med":"13.60","high":"13.61","auto":"13.50","dense":"13.50","custom":""},{"low":"5.00","med":"18.30","high":"18.38","auto":"18.00","dense":"18.00","custom":""},{"low":"5.00","med":"13.60","high":"13.69","auto":"13.50","dense":"13.50","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"5.00","high":"5.08","auto":"5.00","dense":"5.05","custom":""},{"low":"5.00","med":"5.70","high":"5.77","auto":"5.70","dense":"5.75","custom":""},{"low":"5.00","med":"11.40","high":"11.45","auto":"11.00","dense":"11.00","custom":""},{"low":"0.00","med":"0.30","high":"0.31","auto":"0.30","dense":"0.31","custom":""},{"low":"5.00","med":"18.50","high":"18.55","auto":"18.50","dense":"18.50","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"18.80","high":"18.81","auto":"18.50","dense":"18.50","custom":""},{"low":"5.00","med":"10.20","high":"10.20","auto":"10.00","dense":"10.00","custom":""},{"low":"5.00","med":"10.10","high":"10.14","auto":"10.00","dense":"10.00","custom":""},{"low":"2.00","med":"2.40","high":"2.48","auto":"2.45","dense":"2.48","custom":""},{"low":"5.00","med":"16.10","high":"16.14","auto":"16.00","dense":"16.00","custom":""},{"low":"2.50","med":"2.90","high":"2.90","auto":"2.90","dense":"2.90","custom":""},{"low":"0.50","med":"0.60","high":"0.65","auto":"0.65","dense":"0.65","custom":""}] + "cpmInputs": ["17.638", "19.836", "11.501", "14.384", "23.224", "21.279", "8.886", "16.555", "10.579", "1.331", "1.998", "14.988", "14.864", "10.369", "0.262", "5.269", "6.874", "5.598", "7.191", "15.218", "10.958", "4.420", "17.749", "23.808", "12.353", "21.726", "1.562", "18.085", "1.184", "15.470", "13.841", "17.966", "22.150", "9.088", "13.613", "18.384", "13.690", "23.639", "5.085", "5.779", "11.456", "0.315", "18.557", "20.813", "18.813", "10.202", "10.143", "2.483", "16.147", "2.909", "0.652","2.21","3.15","4.89","2.98","2.99","4.01","4.68","4.69"], + "priceStringOutputs": [{"low":"5.00","med":"17.60","high":"17.63","auto":"17.50","dense":"17.50","custom":""},{"low":"5.00","med":"19.80","high":"19.83","auto":"19.50","dense":"19.50","custom":""},{"low":"5.00","med":"11.50","high":"11.50","auto":"11.50","dense":"11.50","custom":""},{"low":"5.00","med":"14.30","high":"14.38","auto":"14.00","dense":"14.00","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"8.80","high":"8.88","auto":"8.80","dense":"8.50","custom":""},{"low":"5.00","med":"16.50","high":"16.55","auto":"16.50","dense":"16.50","custom":""},{"low":"5.00","med":"10.50","high":"10.57","auto":"10.50","dense":"10.50","custom":""},{"low":"1.00","med":"1.30","high":"1.33","auto":"1.30","dense":"1.33","custom":""},{"low":"1.50","med":"1.90","high":"1.99","auto":"1.95","dense":"1.99","custom":""},{"low":"5.00","med":"14.90","high":"14.98","auto":"14.50","dense":"14.50","custom":""},{"low":"5.00","med":"14.80","high":"14.86","auto":"14.50","dense":"14.50","custom":""},{"low":"5.00","med":"10.30","high":"10.36","auto":"10.00","dense":"10.00","custom":""},{"low":"0.00","med":"0.20","high":"0.26","auto":"0.25","dense":"0.26","custom":""},{"low":"5.00","med":"5.20","high":"5.26","auto":"5.20","dense":"5.25","custom":""},{"low":"5.00","med":"6.80","high":"6.87","auto":"6.80","dense":"6.85","custom":""},{"low":"5.00","med":"5.50","high":"5.59","auto":"5.50","dense":"5.55","custom":""},{"low":"5.00","med":"7.10","high":"7.19","auto":"7.10","dense":"7.15","custom":""},{"low":"5.00","med":"15.20","high":"15.21","auto":"15.00","dense":"15.00","custom":""},{"low":"5.00","med":"10.90","high":"10.95","auto":"10.50","dense":"10.50","custom":""},{"low":"4.00","med":"4.40","high":"4.42","auto":"4.40","dense":"4.40","custom":""},{"low":"5.00","med":"17.70","high":"17.74","auto":"17.50","dense":"17.50","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"12.30","high":"12.35","auto":"12.00","dense":"12.00","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"1.50","med":"1.50","high":"1.56","auto":"1.55","dense":"1.56","custom":""},{"low":"5.00","med":"18.00","high":"18.08","auto":"18.00","dense":"18.00","custom":""},{"low":"1.00","med":"1.10","high":"1.18","auto":"1.15","dense":"1.18","custom":""},{"low":"5.00","med":"15.40","high":"15.47","auto":"15.00","dense":"15.00","custom":""},{"low":"5.00","med":"13.80","high":"13.84","auto":"13.50","dense":"13.50","custom":""},{"low":"5.00","med":"17.90","high":"17.96","auto":"17.50","dense":"17.50","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"9.00","high":"9.08","auto":"9.00","dense":"9.00","custom":""},{"low":"5.00","med":"13.60","high":"13.61","auto":"13.50","dense":"13.50","custom":""},{"low":"5.00","med":"18.30","high":"18.38","auto":"18.00","dense":"18.00","custom":""},{"low":"5.00","med":"13.60","high":"13.69","auto":"13.50","dense":"13.50","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"5.00","high":"5.08","auto":"5.00","dense":"5.05","custom":""},{"low":"5.00","med":"5.70","high":"5.77","auto":"5.70","dense":"5.75","custom":""},{"low":"5.00","med":"11.40","high":"11.45","auto":"11.00","dense":"11.00","custom":""},{"low":"0.00","med":"0.30","high":"0.31","auto":"0.30","dense":"0.31","custom":""},{"low":"5.00","med":"18.50","high":"18.55","auto":"18.50","dense":"18.50","custom":""},{"low":"5.00","med":"20.00","high":"20.00","auto":"20.00","dense":"20.00","custom":""},{"low":"5.00","med":"18.80","high":"18.81","auto":"18.50","dense":"18.50","custom":""},{"low":"5.00","med":"10.20","high":"10.20","auto":"10.00","dense":"10.00","custom":""},{"low":"5.00","med":"10.10","high":"10.14","auto":"10.00","dense":"10.00","custom":""},{"low":"2.00","med":"2.40","high":"2.48","auto":"2.45","dense":"2.48","custom":""},{"low":"5.00","med":"16.10","high":"16.14","auto":"16.00","dense":"16.00","custom":""},{"low":"2.50","med":"2.90","high":"2.90","auto":"2.90","dense":"2.90","custom":""},{"low":"0.50","med":"0.60","high":"0.65","auto":"0.65","dense":"0.65","custom":""},{"low":"2.00","med":"2.20","high":"2.21","auto":"2.20","dense":"2.21","custom":""},{"low":"3.00","med":"3.10","high":"3.15","auto":"3.15","dense":"3.15","custom":""},{"low":"4.50","med":"4.80","high":"4.89","auto":"4.85","dense":"4.85","custom":""},{"low":"2.50","med":"2.90","high":"2.98","auto":"2.95","dense":"2.98","custom":""},{"low":"2.50","med":"2.90","high":"2.99","auto":"2.95","dense":"2.99","custom":""},{"low":"4.00","med":"4.00","high":"4.01","auto":"4.00","dense":"4.00","custom":""},{"low":"4.50","med":"4.60","high":"4.68","auto":"4.65","dense":"4.65","custom":""},{"low":"4.50","med":"4.60","high":"4.69","auto":"4.65","dense":"4.65","custom":""}] } diff --git a/test/spec/cpmBucketManager_spec.js b/test/spec/cpmBucketManager_spec.js index 3d56299ebfd..55fae3bb869 100644 --- a/test/spec/cpmBucketManager_spec.js +++ b/test/spec/cpmBucketManager_spec.js @@ -81,6 +81,80 @@ describe('cpmBucketManager', () => { expect(JSON.stringify(output)).to.deep.equal(expected); }); + it('gets the correct custom bucket strings with specific cpms that round oddly with certain increments', () => { + let customConfig = { + 'buckets': [{ + 'precision': 4, + 'min': 0, + 'max': 4, + 'increment': 0.10, + }] + }; + let cpm = 2.21; + let expected = '{"low":"2.00","med":"2.20","high":"2.21","auto":"2.20","dense":"2.21","custom":"2.2000"}'; + let output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + + cpm = 3.15; + expected = '{"low":"3.00","med":"3.10","high":"3.15","auto":"3.15","dense":"3.15","custom":"3.1000"}'; + output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + + customConfig = { + 'buckets': [{ + 'precision': 3, + 'min': 0, + 'max': 6, + 'increment': 0.08, + }] + }; + cpm = 4.89; + expected = '{"low":"4.50","med":"4.80","high":"4.89","auto":"4.85","dense":"4.85","custom":"4.880"}'; + output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + + customConfig = { + 'buckets': [{ + 'precision': 3, + 'min': 0, + 'max': 6, + 'increment': 0.05, + }] + }; + cpm = 2.98; + expected = '{"low":"2.50","med":"2.90","high":"2.98","auto":"2.95","dense":"2.98","custom":"2.950"}'; + output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + + cpm = 2.99; + expected = '{"low":"2.50","med":"2.90","high":"2.99","auto":"2.95","dense":"2.99","custom":"2.950"}'; + output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + + customConfig = { + 'buckets': [{ + 'precision': 2, + 'min': 0, + 'max': 6, + 'increment': 0.01, + }] + }; + cpm = 4.01; + expected = '{"low":"4.00","med":"4.00","high":"4.01","auto":"4.00","dense":"4.00","custom":"4.01"}'; + output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + + cpm = 4.68; + expected = '{"low":"4.50","med":"4.60","high":"4.68","auto":"4.65","dense":"4.65","custom":"4.68"}'; + output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + + cpm = 4.69; + expected = '{"low":"4.50","med":"4.60","high":"4.69","auto":"4.65","dense":"4.65","custom":"4.69"}'; + output = getPriceBucketString(cpm, customConfig); + expect(JSON.stringify(output)).to.deep.equal(expected); + }); + it('gets custom bucket strings and it should honor 0', () => { let cpm = 16.50908; let customConfig = { From 1399da7bb1d933a1c0928d83e3fce3de6e419ef1 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 30 May 2018 20:45:59 -0400 Subject: [PATCH 0429/1594] Prebid 1.13.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d71ac6f9830..b1bfb7d870c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.13.0-pre", + "version": "1.13.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 476cad8d9287beb2c5054d9b164a05717e4437a5 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 30 May 2018 20:55:42 -0400 Subject: [PATCH 0430/1594] Increment pre-release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1bfb7d870c..466e9bb1fc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.13.0", + "version": "1.14.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 05199026866ec595752c43d04485b404448bb848 Mon Sep 17 00:00:00 2001 From: sami-elasticad <35566930+sami-elasticad@users.noreply.github.com> Date: Thu, 31 May 2018 23:59:15 +0300 Subject: [PATCH 0431/1594] Add GDPR support for Quantum Adapter (#2621) * quantumBidAdapter initial commit * eslint errors fixed * updating quantumBidAdapter for reviews, fixed tests to work with native * set new prebid location for testing and some fixing * added supportedMediaTypes * Tests fixed * Fixed issues with image assets. Tested with the example provided * Size and tests fixed * Modify tests * hello world revert changes * package-lock reverted * hello world reverted CRLF/LF Conversion * hello world reverted LF/CRLF Conversion * hello world reverted * hello world reverted * hello world reverted * removed hardcoded bid sizes * GDPR integration * GDPR support - change quantx_gdpr to (0,1) values accepted * restored package-lock * GDPR tests * GDPR tests fixed * Send width/height with native assets --- modules/quantumBidAdapter.js | 23 +++++++-- test/spec/modules/quantumBidAdapter_spec.js | 57 +++++++++++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/modules/quantumBidAdapter.js b/modules/quantumBidAdapter.js index f6df8a2ff61..19f9fbe07e2 100644 --- a/modules/quantumBidAdapter.js +++ b/modules/quantumBidAdapter.js @@ -25,7 +25,7 @@ export const spec = { * @param {validBidRequests[]} - an array of bids * @return ServerRequest Info describing the request to the server. */ - buildRequests: function (bidRequests) { + buildRequests: function (bidRequests, bidderRequest) { return bidRequests.map(bid => { const qtxRequest = {}; let bidId = ''; @@ -55,6 +55,12 @@ export const spec = { bidId = bid.bidId; } qtxRequest.auid = placementId; + + if (bidderRequest && bidderRequest.gdprConsent) { + qtxRequest.quantx_user_consent_string = bidderRequest.gdprConsent.consentString; + qtxRequest.quantx_gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; + }; + const url = devEnpoint || ENDPOINT_URL; return { @@ -64,7 +70,8 @@ export const spec = { mediaType: mediaType, renderMode: renderMode, url: url, - 'data': qtxRequest + 'data': qtxRequest, + bidderRequest }; }); }, @@ -243,13 +250,21 @@ export const spec = { native.title = asset['title']['text']; break; case 2: - native.icon = asset['img']; + native.icon = { + url: asset['img'], + width: asset['w'], + height: asset['h'] + }; break; case 3: native.body = asset['data']['value']; break; case 4: - native.image = asset['img']; + native.image = { + url: asset['img'], + width: asset['w'], + height: asset['h'] + }; break; case 10: native.sponsoredBy = asset['data']['value']; diff --git a/test/spec/modules/quantumBidAdapter_spec.js b/test/spec/modules/quantumBidAdapter_spec.js index 053ec98ffaa..f45b9ed37e7 100644 --- a/test/spec/modules/quantumBidAdapter_spec.js +++ b/test/spec/modules/quantumBidAdapter_spec.js @@ -234,6 +234,63 @@ describe('quantumBidAdapter', () => { }) }) + describe('GDPR conformity', () => { + const bidRequests = [{ + 'bidder': 'quantum', + 'mediaType': 'native', + 'params': { + placementId: 21546 + }, + adUnitCode: 'aaa', + transactionId: '2b8389fe-615c-482d-9f1a-376fb8f7d6b0', + sizes: [[0, 0]], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + }]; + + const bidderRequest = { + gdprConsent: { + consentString: 'awefasdfwefasdfasd', + gdprApplies: true + } + }; + + it('should transmit correct data', () => { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests.length).to.equal(1); + expect(requests[0].data.quantx_gdpr).to.equal(1); + expect(requests[0].data.quantx_user_consent_string).to.equal('awefasdfwefasdfasd'); + }); + }); + + describe('GDPR absence conformity', () => { + const bidRequests = [{ + 'bidder': 'quantum', + 'mediaType': 'native', + 'params': { + placementId: 21546 + }, + adUnitCode: 'aaa', + transactionId: '2b8389fe-615c-482d-9f1a-376fb8f7d6b0', + sizes: [[0, 0]], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + }]; + + const bidderRequest = { + gdprConsent: undefined + }; + + it('should transmit correct data', () => { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests.length).to.equal(1); + expect(requests[0].data.quantx_gdpr).to.be.undefined; + expect(requests[0].data.quantx_user_consent_string).to.be.undefined; + }); + }); + describe('interpretResponse', () => { let bidderRequest = { bidderCode: 'bidderCode', From 2e045a1b6bd527746543abb456d459ea423f9c17 Mon Sep 17 00:00:00 2001 From: Paris Holley Date: Fri, 1 Jun 2018 12:07:47 -0400 Subject: [PATCH 0432/1594] Bug fix - mantisBidAdapter.js (#2509) * Update mantisBidAdapter.js * tests for uuid storage * typo --- modules/mantisBidAdapter.js | 2 +- test/spec/modules/mantisBidAdapter_spec.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/mantisBidAdapter.js b/modules/mantisBidAdapter.js index 7247a236e71..ddbd849d1fd 100644 --- a/modules/mantisBidAdapter.js +++ b/modules/mantisBidAdapter.js @@ -170,7 +170,7 @@ const spec = { }; }, interpretResponse: function (serverResponse) { - storeUuid(serverResponse.uuid); + storeUuid(serverResponse.body.uuid); return serverResponse.body.ads.map(function (ad) { return { requestId: ad.bid, diff --git a/test/spec/modules/mantisBidAdapter_spec.js b/test/spec/modules/mantisBidAdapter_spec.js index e2cd4df9a07..46cb413597e 100644 --- a/test/spec/modules/mantisBidAdapter_spec.js +++ b/test/spec/modules/mantisBidAdapter_spec.js @@ -131,6 +131,7 @@ describe('MantisAdapter', () => { it('display ads returned', () => { let response = { body: { + uuid: 'uuid', ads: [ { bid: 'bid', @@ -161,6 +162,8 @@ describe('MantisAdapter', () => { let result = spec.interpretResponse(response, {bidderRequest}); expect(result[0]).to.deep.equal(expectedResponse[0]); + expect(window.mantis_uuid).to.equal(response.body.uuid); + expect(window.localStorage.getItem('mantis:uuid')).to.equal(response.body.uuid); }); it('no ads returned', () => { From 00dce50eac32beb7d4a5d9fa2913b614337430b2 Mon Sep 17 00:00:00 2001 From: Denis Logachev Date: Fri, 1 Jun 2018 21:42:51 +0300 Subject: [PATCH 0433/1594] AdKernelADN adapter GDPR support (#2624) Ad units size issue fix --- modules/adkernelAdnBidAdapter.js | 32 ++++-- .../modules/adkernelAdnBidAdapter_spec.js | 104 ++++++++++++------ 2 files changed, 88 insertions(+), 48 deletions(-) diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index d99ee023772..16b2efce901 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -20,12 +20,12 @@ function buildImp(bidRequest) { }; if (bidRequest.mediaType === BANNER || utils.deepAccess(bidRequest, `mediaTypes.banner`) || (bidRequest.mediaTypes === undefined && bidRequest.mediaType === undefined)) { - let sizes = canonicalizeSizesArray(utils.deepAccess(bidRequest, `mediaTypes.banner.sizes`) || bidRequest.sizes); + let sizes = canonicalizeSizesArray(bidRequest.sizes); imp.banner = { format: utils.parseSizesInput(sizes) } } else if (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, `mediaTypes.video`)) { - let size = utils.deepAccess(bidRequest, `mediaTypes.video.playerSize`) || canonicalizeSizesArray(bidRequest.sizes)[0]; + let size = canonicalizeSizesArray(bidRequest.sizes)[0]; imp.video = { w: size[0], h: size[1], @@ -54,9 +54,9 @@ function canonicalizeSizesArray(sizes) { return sizes; } -function buildRequestParams(auctionId, transactionId, tags) { +function buildRequestParams(tags, auctionId, transactionId, gdprConsent) { let loc = utils.getTopWindowLocation(); - return { + let req = { id: auctionId, tid: transactionId, site: { @@ -66,6 +66,17 @@ function buildRequestParams(auctionId, transactionId, tags) { }, imp: tags }; + + if (gdprConsent && (gdprConsent.gdprApplies !== undefined || gdprConsent.consentString !== undefined)) { + req.user = {}; + if (gdprConsent.gdprApplies !== undefined) { + req.user.gdpr = ~~(gdprConsent.gdprApplies); + } + if (gdprConsent.consentString !== undefined) { + req.user.consent = gdprConsent.consentString; + } + } + return req; } function buildBid(tag) { @@ -91,9 +102,7 @@ function buildBid(tag) { } export const spec = { - code: 'adkernelAdn', - supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bidRequest) { @@ -101,9 +110,7 @@ export const spec = { typeof bidRequest.params.pubId === 'number'; }, - buildRequests: function(bidRequests) { - let transactionId; - let auctionId; + buildRequests: function(bidRequests, bidderRequest) { let dispatch = bidRequests.map(buildImp) .reduce((acc, curr, index) => { let bidRequest = bidRequests[index]; @@ -112,14 +119,15 @@ export const spec = { acc[host] = acc[host] || {}; acc[host][pubId] = acc[host][pubId] || []; acc[host][pubId].push(curr); - transactionId = bidRequest.transactionId; - auctionId = bidRequest.bidderRequestId; return acc; }, {}); + let auctionId = bidderRequest.auctionId; + let gdprConsent = bidderRequest.gdprConsent; + let transactionId = bidderRequest.transactionId; let requests = []; Object.keys(dispatch).forEach(host => { Object.keys(dispatch[host]).forEach(pubId => { - let request = buildRequestParams(auctionId, transactionId, dispatch[host][pubId]); + let request = buildRequestParams(dispatch[host][pubId], auctionId, transactionId, gdprConsent); requests.push({ method: 'POST', url: `//${host}/tag?account=${pubId}&pb=1${isRtbDebugEnabled() ? '&debug=1' : ''}`, diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index a7bd959ee8e..af9ccfd78ed 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -7,6 +7,7 @@ describe('AdkernelAdn adapter', () => { bidder: 'adkernelAdn', transactionId: 'transact0', bidderRequestId: 'req0', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337', bidId: 'bidid_1', params: { pubId: 1 @@ -16,8 +17,9 @@ describe('AdkernelAdn adapter', () => { }, bid2_pub1 = { bidder: 'adkernelAdn', - transactionId: 'transact1', - bidderRequestId: 'req1', + transactionId: 'transact0', + bidderRequestId: 'req0', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337', bidId: 'bidid_2', params: { pubId: 1 @@ -29,6 +31,7 @@ describe('AdkernelAdn adapter', () => { bidder: 'adkernelAdn', transactionId: 'transact2', bidderRequestId: 'req1', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337', bidId: 'bidid_3', params: { pubId: 7, @@ -40,6 +43,7 @@ describe('AdkernelAdn adapter', () => { bidder: 'adkernelAdn', transactionId: 'transact3', bidderRequestId: 'req1', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337', bidId: 'bidid_4', mediaType: 'video', sizes: [640, 300], @@ -56,7 +60,9 @@ describe('AdkernelAdn adapter', () => { bidder: 'adkernelAdn', transactionId: 'transact3', bidderRequestId: 'req1', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337', bidId: 'bidid_5', + sizes: [[1920, 1080]], mediaTypes: { video: { playerSize: [1920, 1080], @@ -106,8 +112,7 @@ describe('AdkernelAdn adapter', () => { describe('input parameters validation', () => { it('empty request shouldn\'t generate exception', () => { - expect(spec.isBidRequestValid({ - bidderCode: 'adkernelAdn' + expect(spec.isBidRequestValid({bidderCode: 'adkernelAdn' })).to.be.equal(false); }); it('request without pubid should be ignored', () => { @@ -130,25 +135,32 @@ describe('AdkernelAdn adapter', () => { }); }); - describe('banner request building', () => { - let pbRequest; - let tagRequest; - - before(() => { - let mock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => { - return { - protocol: 'https:', - hostname: 'example.com', - host: 'example.com', - pathname: '/index.html', - href: 'https://example.com/index.html' - }; - }); - pbRequest = spec.buildRequests([bid1_pub1])[0]; - tagRequest = JSON.parse(pbRequest.data); - mock.restore(); + function buildRequest(bidRequests, bidderRequest = {}) { + let mock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => { + return { + protocol: 'https:', + hostname: 'example.com', + host: 'example.com', + pathname: '/index.html', + href: 'https://example.com/index.html' + }; }); + bidderRequest.auctionId = bidRequests[0].auctionId; + bidderRequest.transactionId = bidRequests[0].transactionId; + bidderRequest.bidderRequestId = bidRequests[0].bidderRequestId; + + let pbRequests = spec.buildRequests(bidRequests, bidderRequest); + let tagRequests = pbRequests.map(r => JSON.parse(r.data)); + mock.restore(); + + return [pbRequests, tagRequests]; + } + + describe('banner request building', () => { + let [_, tagRequests] = buildRequest([bid1_pub1]); + let tagRequest = tagRequests[0]; + it('should have request id', () => { expect(tagRequest).to.have.property('id'); }); @@ -169,11 +181,35 @@ describe('AdkernelAdn adapter', () => { expect(tagRequest.site).to.have.property('page', 'https://example.com/index.html'); expect(tagRequest.site).to.have.property('secure', 1); }); + + it('should not have user object', () => { + expect(tagRequest).to.not.have.property('user'); + }); + + it('shouldn\'t contain gdpr-related information for default request', () => { + let [_, tagRequests] = buildRequest([bid1_pub1]); + expect(tagRequests[0]).to.not.have.property('user'); + }); + + it('should contain gdpr-related information if consent is configured', () => { + let [_, bidRequests] = buildRequest([bid1_pub1], + {gdprConsent: {gdprApplies: true, consentString: 'test-consent-string'}}); + expect(bidRequests[0]).to.have.property('user'); + expect(bidRequests[0].user).to.have.property('gdpr', 1); + expect(bidRequests[0].user).to.have.property('consent', 'test-consent-string'); + }); + + it('should\'t contain consent string if gdpr isn\'t applied', () => { + let [_, bidRequests] = buildRequest([bid1_pub1], {gdprConsent: {gdprApplies: false}}); + expect(bidRequests[0]).to.have.property('user'); + expect(bidRequests[0].user).to.have.property('gdpr', 0); + expect(bidRequests[0].user).to.not.have.property('consent'); + }); }); describe('video request building', () => { - let pbRequest = spec.buildRequests([bid_video1, bid_video2])[0]; - let tagRequest = JSON.parse(pbRequest.data); + let [_, tagRequests] = buildRequest([bid_video1, bid_video2]); + let tagRequest = tagRequests[0]; it('should have video object', () => { expect(tagRequest.imp[0]).to.have.property('video'); @@ -193,24 +229,20 @@ describe('AdkernelAdn adapter', () => { describe('requests routing', () => { it('should issue a request for each publisher', () => { - let pbRequests = spec.buildRequests([bid1_pub1, bid_video1]); + let [pbRequests, tagRequests] = buildRequest([bid1_pub1, bid_video1]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string(`account=${bid1_pub1.params.pubId}`); expect(pbRequests[1].url).to.have.string(`account=${bid1_pub2.params.pubId}`); - let tagRequest1 = JSON.parse(pbRequests[0].data); - let tagRequest2 = JSON.parse(pbRequests[1].data); - expect(tagRequest1.imp).to.have.length(1); - expect(tagRequest2.imp).to.have.length(1); + expect(tagRequests[0].imp).to.have.length(1); + expect(tagRequests[1].imp).to.have.length(1); }); it('should issue a request for each host', () => { - let pbRequests = spec.buildRequests([bid1_pub1, bid1_pub2]); + let [pbRequests, tagRequests] = buildRequest([bid1_pub1, bid1_pub2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string('//tag.adkernel.com/tag'); expect(pbRequests[1].url).to.have.string(`//${bid1_pub2.params.host}/tag`); - let tagRequest1 = JSON.parse(pbRequests[0].data); - let tagRequest2 = JSON.parse(pbRequests[1].data); - expect(tagRequest1.imp).to.have.length(1); - expect(tagRequest2.imp).to.have.length(1); + expect(tagRequests[0].imp).to.have.length(1); + expect(tagRequests[1].imp).to.have.length(1); }); }); @@ -257,11 +289,11 @@ describe('AdkernelAdn adapter', () => { expect(syncs[0]).to.have.property('url', 'https://dsp.adkernel.com/sync'); }); it('should handle user-sync only response', () => { - let request = spec.buildRequests([bid1_pub1])[0]; - let resp = spec.interpretResponse({body: usersyncOnlyResponse}, request); + let [pbRequests, tagRequests] = buildRequest([bid1_pub1]); + let resp = spec.interpretResponse({body: usersyncOnlyResponse}, pbRequests[0]); expect(resp).to.have.length(0); }); - it('shouldn\' fail in empty response', () => { + it('shouldn\' fail on empty response', () => { let syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: ''}]); expect(syncs).to.have.length(0); }); From 5683f8e5f5cbcf042852c4d0576221ab7ee25e54 Mon Sep 17 00:00:00 2001 From: Denis Logachev Date: Fri, 1 Jun 2018 21:44:33 +0300 Subject: [PATCH 0434/1594] AdKernel adapter GDPR support (#2610) Video ad unit size issue fix --- modules/adkernelBidAdapter.js | 56 ++++++---- test/spec/modules/adkernelBidAdapter_spec.js | 109 +++++++++++++------ 2 files changed, 108 insertions(+), 57 deletions(-) diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index c1df51347e2..e9f88e9a3ef 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -7,7 +7,7 @@ import includes from 'core-js/library/fn/array/includes'; const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', 'pos', 'api', 'ext']; -const VERSION = '1.2'; +const VERSION = '1.3'; /** * Adapter for requesting bids from AdKernel white-label display platform @@ -21,23 +21,14 @@ export const spec = { return 'params' in bidRequest && typeof bidRequest.params.host !== 'undefined' && 'zoneId' in bidRequest.params && !isNaN(Number(bidRequest.params.zoneId)); }, - buildRequests: function(bidRequests) { - let auctionId; - let dispatch = bidRequests.map(buildImp) - .reduce((acc, curr, index) => { - let bidRequest = bidRequests[index]; - let zoneId = bidRequest.params.zoneId; - let host = bidRequest.params.host; - acc[host] = acc[host] || {}; - acc[host][zoneId] = acc[host][zoneId] || []; - acc[host][zoneId].push(curr); - auctionId = bidRequest.bidderRequestId; - return acc; - }, {}); - let requests = []; - Object.keys(dispatch).forEach(host => { - Object.keys(dispatch[host]).forEach(zoneId => { - const request = buildRtbRequest(dispatch[host][zoneId], auctionId); + buildRequests: function(bidRequests, bidderRequest) { + let impDispatch = dispatchImps(bidRequests); + const gdprConsent = bidderRequest.gdprConsent; + const auctionId = bidderRequest.auctionId; + const requests = []; + Object.keys(impDispatch).forEach(host => { + Object.keys(impDispatch[host]).forEach(zoneId => { + const request = buildRtbRequest(impDispatch[host][zoneId], auctionId, gdprConsent); requests.push({ method: 'GET', url: `${window.location.protocol}//${host}/rtbg`, @@ -102,6 +93,22 @@ export const spec = { registerBidder(spec); +/** + * Dispatch impressions by ad network host and zone + */ +function dispatchImps(bidRequests) { + return bidRequests.map(buildImp) + .reduce((acc, curr, index) => { + let bidRequest = bidRequests[index]; + let zoneId = bidRequest.params.zoneId; + let host = bidRequest.params.host; + acc[host] = acc[host] || {}; + acc[host][zoneId] = acc[host][zoneId] || []; + acc[host][zoneId].push(curr); + return acc; + }, {}); +} + /** * Builds parameters object for single impression */ @@ -113,13 +120,13 @@ function buildImp(bidRequest) { if (bidRequest.mediaType === BANNER || utils.deepAccess(bidRequest, `mediaTypes.banner`) || (bidRequest.mediaTypes === undefined && bidRequest.mediaType === undefined)) { - let sizes = canonicalizeSizesArray(utils.deepAccess(bidRequest, `mediaTypes.banner.sizes`) || bidRequest.sizes); + let sizes = canonicalizeSizesArray(bidRequest.sizes); imp.banner = { format: sizes.map(s => ({'w': s[0], 'h': s[1]})), topframe: 0 }; } else if (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, 'mediaTypes.video')) { - let size = utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize') || canonicalizeSizesArray(bidRequest.sizes)[0]; + let size = canonicalizeSizesArray(bidRequest.sizes)[0]; imp.video = { w: size[0], h: size[1] @@ -152,8 +159,9 @@ function canonicalizeSizesArray(sizes) { * Builds complete rtb request * @param imps collection of impressions * @param auctionId + * @param gdprConsent */ -function buildRtbRequest(imps, auctionId) { +function buildRtbRequest(imps, auctionId, gdprConsent) { let req = { 'id': auctionId, 'imp': imps, @@ -172,6 +180,12 @@ function buildRtbRequest(imps, auctionId) { if (utils.getDNT()) { req.device.dnt = 1; } + if (gdprConsent && gdprConsent.gdprApplies !== undefined) { + req.regs = {ext: {gdpr: Number(gdprConsent.gdprApplies)}}; + } + if (gdprConsent && gdprConsent.consentString !== undefined) { + req.user = {ext: {consent: gdprConsent.consentString}}; + } return req; } diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index cef084c7345..0f5596b8b23 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec} from 'modules/adkernelBidAdapter'; import * as utils from 'src/utils'; +import {parse as parseUrl} from 'src/url'; describe('Adkernel adapter', () => { const bid1_zone1 = { @@ -14,7 +15,7 @@ describe('Adkernel adapter', () => { bidId: 'Bid_02', params: {zoneId: 2, host: 'rtb.adkernel.com'}, adUnitCode: 'ad-unit-2', - sizes: [[728, 90]] + sizes: [728, 90] }, bid3_host2 = { bidder: 'adkernel', bidId: 'Bid_02', @@ -41,14 +42,19 @@ describe('Adkernel adapter', () => { sizes: [[728, 90]] }, bid_video = { bidder: 'adkernel', + transactionId: '866394b8-5d37-4d49-803e-f1bdb595f73e', bidId: 'Bid_Video', - sizes: [640, 480], - mediaType: 'video', + bidderRequestId: '18b2a61ea5d9a7', + auctionId: 'de45acf1-9109-4e52-8013-f2b7cf5f6766', + sizes: [[640, 480]], params: { zoneId: 1, - host: 'rtb.adkernel.com', + host: 'rtb.adkernel.com' + }, + mediaTypes: { video: { - mimes: ['video/mp4', 'video/webm', 'video/x-flv'] + context: 'instream', + playerSize: [[640, 480]] } }, adUnitCode: 'ad-unit-1' @@ -107,6 +113,20 @@ describe('Adkernel adapter', () => { } }; + function buildRequest(bidRequests, bidderRequest = {}, url = 'https://example.com/index.html', dnt = true) { + let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => { + let loc = parseUrl(url); + loc.protocol += ':'; + return loc; + }); + let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => dnt); + let pbRequests = spec.buildRequests(bidRequests, bidderRequest); + wmock.restore(); + dntmock.restore(); + let rtbRequests = pbRequests.map(r => JSON.parse(r.data.r)); + return [pbRequests, rtbRequests]; + } + describe('input parameters validation', () => { it('empty request shouldn\'t generate exception', () => { expect(spec.isBidRequestValid({ @@ -128,20 +148,10 @@ describe('Adkernel adapter', () => { }); describe('banner request building', () => { - let bidRequest; + let bidRequest, bidRequests, _; before(() => { - let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => ({ - protocol: 'https:', - hostname: 'example.com', - host: 'example.com', - pathname: '/index.html', - href: 'https://example.com/index.html' - })); - let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => true); - let request = spec.buildRequests([bid1_zone1])[0]; - bidRequest = JSON.parse(request.data.r); - wmock.restore(); - dntmock.restore(); + [_, bidRequests] = buildRequest([bid1_zone1]); + bidRequest = bidRequests[0]; }); it('should be a first-price auction', () => { @@ -176,40 +186,67 @@ describe('Adkernel adapter', () => { expect(bidRequest.device).to.have.property('ua', 'caller'); expect(bidRequest.device).to.have.property('dnt', 1); }); + + it('shouldn\'t contain gdpr-related information for default request', () => { + let [_, bidRequests] = buildRequest([bid1_zone1]); + expect(bidRequests[0]).to.not.have.property('regs'); + expect(bidRequests[0]).to.not.have.property('user'); + }); + + it('should contain gdpr-related information if consent is configured', () => { + let [_, bidRequests] = buildRequest([bid1_zone1], + {gdprConsent: {gdprApplies: true, consentString: 'test-consent-string', vendorData: {}}}); + let bidRequest = bidRequests[0]; + expect(bidRequest).to.have.property('regs'); + expect(bidRequest.regs.ext).to.be.eql({'gdpr': 1}); + expect(bidRequest).to.have.property('user'); + expect(bidRequest.user.ext).to.be.eql({'consent': 'test-consent-string'}); + }); + + it('should\'t contain consent string if gdpr isn\'t applied', () => { + let [_, bidRequests] = buildRequest([bid1_zone1], {gdprConsent: {gdprApplies: false}}); + let bidRequest = bidRequests[0]; + expect(bidRequest).to.have.property('regs'); + expect(bidRequest.regs.ext).to.be.eql({'gdpr': 0}); + expect(bidRequest).to.not.have.property('user'); + }); + + it('should\'t pass dnt if state is unknown', () => { + let [_, bidRequests] = buildRequest([bid1_zone1], {}, 'https://example.com/index.html', false); + expect(bidRequests[0].device).to.not.have.property('dnt'); + }); }); describe('video request building', () => { - let bidRequest; - + let _, bidRequests; before(() => { - let request = spec.buildRequests([bid_video])[0]; - bidRequest = JSON.parse(request.data.r); + [_, bidRequests] = buildRequest([bid_video]); }); it('should have video object', () => { - expect(bidRequest.imp[0]).to.have.property('video'); + expect(bidRequests[0].imp[0]).to.have.property('video'); }); it('should have h/w', () => { - expect(bidRequest.imp[0].video).to.have.property('w', 640); - expect(bidRequest.imp[0].video).to.have.property('h', 480); + expect(bidRequests[0].imp[0].video).to.have.property('w', 640); + expect(bidRequests[0].imp[0].video).to.have.property('h', 480); }); it('should have tagid', () => { - expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); + expect(bidRequests[0].imp[0]).to.have.property('tagid', 'ad-unit-1'); }); }); describe('requests routing', () => { it('should issue a request for each host', () => { - let pbRequests = spec.buildRequests([bid1_zone1, bid3_host2]); + let [pbRequests, _] = buildRequest([bid1_zone1, bid3_host2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string(`//${bid1_zone1.params.host}/`); expect(pbRequests[1].url).to.have.string(`//${bid3_host2.params.host}/`); }); it('should issue a request for each zone', () => { - let pbRequests = spec.buildRequests([bid1_zone1, bid2_zone2]); + let [pbRequests, _] = buildRequest([bid1_zone1, bid2_zone2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].data.zone).to.be.equal(bid1_zone1.params.zoneId); expect(pbRequests[1].data.zone).to.be.equal(bid2_zone2.params.zoneId); @@ -218,8 +255,8 @@ describe('Adkernel adapter', () => { describe('responses processing', () => { it('should return fully-initialized banner bid-response', () => { - let request = spec.buildRequests([bid1_zone1])[0]; - let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; + let [pbRequests, _] = buildRequest([bid1_zone1]); + let resp = spec.interpretResponse({body: bidResponse1}, pbRequests[0])[0]; expect(resp).to.have.property('requestId', 'Bid_01'); expect(resp).to.have.property('cpm', 3.01); expect(resp).to.have.property('width', 300); @@ -233,8 +270,8 @@ describe('Adkernel adapter', () => { }); it('should return fully-initialized video bid-response', () => { - let request = spec.buildRequests([bid_video])[0]; - let resp = spec.interpretResponse({body: videoBidResponse}, request)[0]; + let [pbRequests, _] = buildRequest([bid_video]); + let resp = spec.interpretResponse({body: videoBidResponse}, pbRequests[0])[0]; expect(resp).to.have.property('requestId', 'Bid_Video'); expect(resp.mediaType).to.equal('video'); expect(resp.cpm).to.equal(0.00145); @@ -244,15 +281,15 @@ describe('Adkernel adapter', () => { }); it('should add nurl as pixel for banner response', () => { - let request = spec.buildRequests([bid1_zone1])[0]; - let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; + let [pbRequests, _] = buildRequest([bid1_zone1]); + let resp = spec.interpretResponse({body: bidResponse1}, pbRequests[0])[0]; let expectedNurl = bidResponse1.seatbid[0].bid[0].nurl + '&px=1'; expect(resp.ad).to.have.string(expectedNurl); }); it('should handle bidresponse with user-sync only', () => { - let request = spec.buildRequests([bid1_zone1])[0]; - let resp = spec.interpretResponse({body: usersyncOnlyResponse}, request); + let [pbRequests, _] = buildRequest([bid1_zone1]); + let resp = spec.interpretResponse({body: usersyncOnlyResponse}, pbRequests[0]); expect(resp).to.have.length(0); }); From 6e7b32432c4c98ec2649187c2c99cb4d3370e71d Mon Sep 17 00:00:00 2001 From: Omer Koren Date: Fri, 1 Jun 2018 22:00:08 +0300 Subject: [PATCH 0435/1594] UndertoneAdapter - change placementId parameter to optional (#2649) * * Update undertone adapter - change parameters - placementId parameter is now optional and not mandatory - undertoneBidAdapter.js * Updated undertone bid adapter tests accordingly - undertoneBidAdapter_spec.js * * Update undertone adapter - change parameters - placementId parameter is now optional and not mandatory - undertoneBidAdapter.js * Updated undertone bid adapter tests accordingly - undertoneBidAdapter_spec.js * fix lint issue in undertone adapter spec --- modules/undertoneBidAdapter.js | 4 +-- test/spec/modules/undertoneBidAdapter_spec.js | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index ae9abee8e88..1f32fe0347a 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -11,7 +11,7 @@ const URL = '//hb.undertone.com/hb'; export const spec = { code: BIDDER_CODE, isBidRequestValid: function(bid) { - if (bid && bid.params && bid.params.publisherId && bid.params.placementId) { + if (bid && bid.params && bid.params.publisherId) { bid.params.publisherId = parseInt(bid.params.publisherId); return true; } @@ -37,7 +37,7 @@ export const spec = { hbadaptor: 'prebid', url: location.href, domain: domain, - placementId: bidReq.params.placementId, + placementId: bidReq.params.placementId != undefined ? bidReq.params.placementId : null, publisherId: bidReq.params.publisherId, sizes: bidReq.sizes, params: bidReq.params diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index d86a1dc5735..4a621fb4465 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -33,6 +33,15 @@ const bidReq = [{ sizes: [[300, 250], [300, 600]], bidId: '263be71e91dd9d', auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' +}, +{ + bidder: BIDDER_CODE, + params: { + publisherId: 12345 + }, + sizes: [[1, 1]], + bidId: '453cf42d72bb3c', + auctionId: '6c22f5a5-59df-4dc6-b92c-f433bcf0a874' }]; const validBidRes = { @@ -97,12 +106,18 @@ describe('Undertone Adapter', () => { }); it('should have all relevant fields', () => { const request = spec.buildRequests(bidReq); - const bid = JSON.parse(request.data)['x-ut-hb-params'][0]; - expect(bid.bidRequestId).to.equal('263be71e91dd9d'); - expect(bid.sizes.length > 0).to.equal(true); - expect(bid.placementId).to.equal('10433394'); - expect(bid.publisherId).to.equal(12345); - expect(bid.params).to.be.an('object'); + const bid1 = JSON.parse(request.data)['x-ut-hb-params'][0]; + expect(bid1.bidRequestId).to.equal('263be71e91dd9d'); + expect(bid1.sizes.length).to.equal(2); + expect(bid1.placementId).to.equal('10433394'); + expect(bid1.publisherId).to.equal(12345); + expect(bid1.params).to.be.an('object'); + const bid2 = JSON.parse(request.data)['x-ut-hb-params'][1]; + expect(bid2.bidRequestId).to.equal('453cf42d72bb3c'); + expect(bid2.sizes.length).to.equal(1); + expect(bid2.placementId === null).to.equal(true); + expect(bid2.publisherId).to.equal(12345); + expect(bid2.params).to.be.an('object'); }); }); From 6f0a2dbf6f827a3b0a1ecdc82643d82b50138207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dejan=20=C5=A0trbac?= Date: Fri, 1 Jun 2018 21:39:24 +0200 Subject: [PATCH 0436/1594] update aardvark to not return zero bids (#2651) * update aardvark to not return zero bids * update test for aardvarkBidAdapter --- modules/aardvarkBidAdapter.js | 8 +++++++- test/spec/modules/aardvarkBidAdapter_spec.js | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index 7d358864b35..6a4c8b99572 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -100,9 +100,15 @@ export const spec = { } utils._each(serverResponse.body, function(rawBid) { + var cpm = +(rawBid.cpm || 0); + + if (!cpm) { + return; + } + var bidResponse = { requestId: rawBid.cid, - cpm: rawBid.cpm || 0, + cpm: cpm, width: rawBid.width || 0, height: rawBid.height || 0, currency: rawBid.currency ? rawBid.currency : AARDVARK_CURRENCY, diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js index d2b9cbc0fa8..6d4649ea107 100644 --- a/test/spec/modules/aardvarkBidAdapter_spec.js +++ b/test/spec/modules/aardvarkBidAdapter_spec.js @@ -257,8 +257,7 @@ describe('aardvarkAdapterTest', () => { }]; var result = spec.interpretResponse({ body: emptyResponse }, {}); - expect(result.length).to.equal(1); - expect(result[0].cpm).to.equal(0.0); + expect(result.length).to.equal(0); }); }); }); From 2fb487894271ad15a66d22505d84c9314df6e13a Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Fri, 1 Jun 2018 15:45:19 -0400 Subject: [PATCH 0437/1594] Sonobi - Fixed issue where consent_string param could be set as undefined (#2656) * added vp param to trinity request * added lib_name and lib_v to trinity * return null from buildRequests if there is no keymakers * added test case for empty keymaker * only importing functions we need from utils * changed window.pbjs.version to use the gulp repalced macro .version$ * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * fixed lint issue * fixed issue where sonobi getUserSync was throwing an error on timeout * sonobi support referrer param * fixed unit test for testing the ref param on bid request * return null from buildRequests if there is no keymakers * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * Add gdpr support * only sending consent string if it exists --- modules/sonobiBidAdapter.js | 4 ++- test/spec/modules/sonobiBidAdapter_spec.js | 29 +++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index ef3353e0271..11fa4d72daf 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -64,7 +64,9 @@ export const spec = { // Apply GDPR parameters to request. if (bidderRequest && bidderRequest.gdprConsent) { payload.gdpr = bidderRequest.gdprConsent.gdprApplies ? 'true' : 'false'; - payload.consent_string = bidderRequest.gdprConsent.consentString; + if (bidderRequest.gdprConsent.consentString) { + payload.consent_string = bidderRequest.gdprConsent.consentString; + } } // If there is no key_maker data, then don't make the request. diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index f2aacb00c0c..9162354d95b 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -169,7 +169,34 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.gdpr).to.equal('false') expect(bidRequests.data.consent_string).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==') }) - + it('should return a properly formatted request with GDPR applies set to false with no consent_string param', () => { + let bidderRequests = { + 'gdprConsent': { + 'consentString': undefined, + 'vendorData': {}, + 'gdprApplies': false + }, + }; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.gdpr).to.equal('false') + expect(bidRequests.data).to.not.include.keys('consent_string') + }) + it('should return a properly formatted request with GDPR applies set to true with no consent_string param', () => { + let bidderRequests = { + 'gdprConsent': { + 'consentString': undefined, + 'vendorData': {}, + 'gdprApplies': true + }, + }; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.gdpr).to.equal('true') + expect(bidRequests.data).to.not.include.keys('consent_string') + }) it('should return a properly formatted request with hfa', () => { bidRequest[0].params.hfa = 'hfakey' bidRequest[1].params.hfa = 'hfakey' From 03c9bbbf349493fad62078bfd234b19097c73b76 Mon Sep 17 00:00:00 2001 From: andbeyondmedia <38574037+andbeyondmedia@users.noreply.github.com> Date: Mon, 4 Jun 2018 08:00:06 -0700 Subject: [PATCH 0438/1594] Adding new Bidder Andbeyond (#2671) * Create andbeyondBidAdapter.js * Create andbeyondBidAdapter_spec.js * Create andbeyondBidAdapter.md * Update andbeyondBidAdapter.md * Update andbeyondBidAdapter_spec.js * Update andbeyondBidAdapter_spec.js * Update andbeyondBidAdapter.js * Update andbeyondBidAdapter_spec.js --- modules/andbeyondBidAdapter.js | 168 ++++++++++++++ modules/andbeyondBidAdapter.md | 32 +++ test/spec/modules/andbeyondBidAdapter_spec.js | 208 ++++++++++++++++++ 3 files changed, 408 insertions(+) create mode 100644 modules/andbeyondBidAdapter.js create mode 100644 modules/andbeyondBidAdapter.md create mode 100644 test/spec/modules/andbeyondBidAdapter_spec.js diff --git a/modules/andbeyondBidAdapter.js b/modules/andbeyondBidAdapter.js new file mode 100644 index 00000000000..1a3535f4704 --- /dev/null +++ b/modules/andbeyondBidAdapter.js @@ -0,0 +1,168 @@ +import * as utils from 'src/utils'; +import { BANNER } from 'src/mediaTypes'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; + +const VERSION = '1.1'; + +/** + * Adapter for requesting bids from andbeyond white-label display platform + */ +export const spec = { + + code: 'andbeyond', + aliases: ['headbidding'], + supportedMediaTypes: [BANNER], + isBidRequestValid: function(bidRequest) { + return 'params' in bidRequest && typeof bidRequest.params.host !== 'undefined' && + 'zoneId' in bidRequest.params && !isNaN(Number(bidRequest.params.zoneId)); + }, + buildRequests: function(bidRequests) { + let auctionId; + let dispatch = bidRequests.map(buildImp) + .reduce((acc, curr, index) => { + let bidRequest = bidRequests[index]; + let zoneId = bidRequest.params.zoneId; + let host = bidRequest.params.host; + acc[host] = acc[host] || {}; + acc[host][zoneId] = acc[host][zoneId] || []; + acc[host][zoneId].push(curr); + auctionId = bidRequest.bidderRequestId; + return acc; + }, {}); + let requests = []; + Object.keys(dispatch).forEach(host => { + Object.keys(dispatch[host]).forEach(zoneId => { + const request = buildRtbRequest(dispatch[host][zoneId], auctionId); + requests.push({ + method: 'GET', + url: `${window.location.protocol}//${host}/rtbg`, + data: { + zone: Number(zoneId), + ad_type: 'rtb', + v: VERSION, + r: JSON.stringify(request) + } + }); + }); + }); + return requests; + }, + interpretResponse: function(serverResponse, request) { + let response = serverResponse.body; + if (!response.seatbid) { + return []; + } + + let rtbRequest = JSON.parse(request.data.r); + let rtbImps = rtbRequest.imp; + let rtbBids = response.seatbid + .map(seatbid => seatbid.bid) + .reduce((a, b) => a.concat(b), []); + + return rtbBids.map(rtbBid => { + let imp = find(rtbImps, imp => imp.id === rtbBid.impid); + let prBid = { + requestId: rtbBid.impid, + cpm: rtbBid.price, + creativeId: rtbBid.crid, + currency: 'USD', + ttl: 360, + netRevenue: true + }; + if ('banner' in imp) { + prBid.mediaType = BANNER; + prBid.width = rtbBid.w; + prBid.height = rtbBid.h; + prBid.ad = formatAdMarkup(rtbBid); + } + return prBid; + }); + }, + getUserSyncs: function(syncOptions, serverResponses) { + if (!syncOptions.iframeEnabled || !serverResponses || serverResponses.length === 0) { + return []; + } + return serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.adk_usersync) + .map(rsp => rsp.body.ext.adk_usersync) + .reduce((a, b) => a.concat(b), []) + .map(sync_url => ({type: 'iframe', url: sync_url})); + } +}; + +registerBidder(spec); + +/** + * Builds parameters object for single impression + */ +function buildImp(bid) { + const sizes = bid.sizes; + const imp = { + 'id': bid.bidId, + 'tagid': bid.placementCode + }; + + imp.banner = { + format: sizes.map(s => ({'w': s[0], 'h': s[1]})), + topframe: 0 + }; + if (utils.getTopWindowLocation().protocol === 'https:') { + imp.secure = 1; + } + return imp; +} + +/** + * Builds complete rtb request + * @param imps collection of impressions + * @param auctionId + */ +function buildRtbRequest(imps, auctionId) { + let req = { + 'id': auctionId, + 'imp': imps, + 'site': createSite(), + 'at': 1, + 'device': { + 'ip': 'caller', + 'ua': 'caller', + 'js': 1, + 'language': getLanguage() + }, + 'ext': { + 'adk_usersync': 1 + } + }; + if (utils.getDNT()) { + req.device.dnt = 1; + } + return req; +} + +function getLanguage() { + const language = navigator.language ? 'language' : 'userLanguage'; + return navigator[language].split('-')[0]; +} + +/** + * Creates site description object + */ +function createSite() { + var location = utils.getTopWindowLocation(); + return { + 'domain': location.hostname, + 'page': location.href.split('?')[0] + }; +} + +/** + * Format creative with optional nurl call + * @param bid rtb Bid object + */ +function formatAdMarkup(bid) { + var adm = bid.adm; + if ('nurl' in bid) { + adm += utils.createTrackPixelHtml(`${bid.nurl}&px=1`); + } + return `${adm}`; +} diff --git a/modules/andbeyondBidAdapter.md b/modules/andbeyondBidAdapter.md new file mode 100644 index 00000000000..7d58bac0abc --- /dev/null +++ b/modules/andbeyondBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +``` +Module Name: andbeyond Bidder Adapter +Module Type: Bidder Adapter +Maintainer: shreyanschopra@rtbdemand.com +``` + +# Description + +Connects to andbeyond whitelabel platform. +Banner formats are supported. + + +# Test Parameters +``` + var adUnits = [ + { + code: 'banner-ad-div', + sizes: [[300, 250]], // banner size + bids: [ + { + bidder: 'andbeyond', + params: { + zoneId: '30164', //required parameter + host: 'cpm.metaadserving.com' //required parameter + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/andbeyondBidAdapter_spec.js b/test/spec/modules/andbeyondBidAdapter_spec.js new file mode 100644 index 00000000000..5e58101ef66 --- /dev/null +++ b/test/spec/modules/andbeyondBidAdapter_spec.js @@ -0,0 +1,208 @@ +import {expect} from 'chai'; +import {spec} from 'modules/andbeyondBidAdapter'; +import * as utils from 'src/utils'; + +describe('andbeyond adapter', () => { + const bid1_zone1 = { + bidder: 'andbeyond', + bidId: 'Bid_01', + params: {zoneId: 1, host: 'rtb.andbeyond.com'}, + placementCode: 'ad-unit-1', + sizes: [[300, 250], [300, 200]] + }, bid2_zone2 = { + bidder: 'andbeyond', + bidId: 'Bid_02', + params: {zoneId: 2, host: 'rtb.andbeyond.com'}, + placementCode: 'ad-unit-2', + sizes: [[728, 90]] + }, bid3_host2 = { + bidder: 'andbeyond', + bidId: 'Bid_02', + params: {zoneId: 1, host: 'rtb-private.andbeyond.com'}, + placementCode: 'ad-unit-2', + sizes: [[728, 90]] + }, bid_without_zone = { + bidder: 'andbeyond', + bidId: 'Bid_W', + params: {host: 'rtb-private.andbeyond.com'}, + placementCode: 'ad-unit-1', + sizes: [[728, 90]] + }, bid_without_host = { + bidder: 'andbeyond', + bidId: 'Bid_W', + params: {zoneId: 1}, + placementCode: 'ad-unit-1', + sizes: [[728, 90]] + }, bid_with_wrong_zoneId = { + bidder: 'andbeyond', + bidId: 'Bid_02', + params: {zoneId: 'wrong id', host: 'rtb.andbeyond.com'}, + placementCode: 'ad-unit-2', + sizes: [[728, 90]] + }, usersyncOnlyResponse = { + id: 'nobid1', + ext: { + adk_usersync: ['http://adk.sync.com/sync'] + } + }; + + const bidResponse1 = { + id: 'bid1', + seatbid: [{ + bid: [{ + id: '1', + impid: 'Bid_01', + crid: '100_001', + price: 3.01, + nurl: 'https://rtb.com/win?i=ZjKoPYSFI3Y_0', + adm: '', + w: 300, + h: 250 + }] + }], + cur: 'USD', + ext: { + adk_usersync: ['http://adk.sync.com/sync'] + } + }, bidResponse2 = { + id: 'bid2', + seatbid: [{ + bid: [{ + id: '2', + impid: 'Bid_02', + crid: '100_002', + price: 1.31, + adm: '', + w: 300, + h: 250 + }] + }], + cur: 'USD' + }; + + describe('input parameters validation', () => { + it('empty request shouldn\'t generate exception', () => { + expect(spec.isBidRequestValid({ + bidderCode: 'andbeyond' + })).to.be.equal(false); + }); + + it('request without zone shouldn\'t issue a request', () => { + expect(spec.isBidRequestValid(bid_without_zone)).to.be.equal(false); + }); + + it('request without host shouldn\'t issue a request', () => { + expect(spec.isBidRequestValid(bid_without_host)).to.be.equal(false); + }); + + it('empty request shouldn\'t generate exception', () => { + expect(spec.isBidRequestValid(bid_with_wrong_zoneId)).to.be.equal(false); + }); + }); + + describe('banner request building', () => { + let bidRequest; + before(() => { + let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => ({ + protocol: 'https:', + hostname: 'example.com', + host: 'example.com', + pathname: '/index.html', + href: 'https://example.com/index.html' + })); + let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => true); + let request = spec.buildRequests([bid1_zone1])[0]; + bidRequest = JSON.parse(request.data.r); + wmock.restore(); + dntmock.restore(); + }); + + it('should be a first-price auction', () => { + expect(bidRequest).to.have.property('at', 1); + }); + + it('should have banner object', () => { + expect(bidRequest.imp[0]).to.have.property('banner'); + }); + + it('should have w/h', () => { + expect(bidRequest.imp[0].banner).to.have.property('format'); + expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); + }); + + it('should respect secure connection', () => { + expect(bidRequest.imp[0]).to.have.property('secure', 1); + }); + + it('should have tagid', () => { + expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); + }); + + it('should create proper site block', () => { + expect(bidRequest.site).to.have.property('domain', 'example.com'); + expect(bidRequest.site).to.have.property('page', 'https://example.com/index.html'); + }); + + it('should fill device with caller macro', () => { + expect(bidRequest).to.have.property('device'); + expect(bidRequest.device).to.have.property('ip', 'caller'); + expect(bidRequest.device).to.have.property('ua', 'caller'); + expect(bidRequest.device).to.have.property('dnt', 1); + }); + }); + + describe('requests routing', () => { + it('should issue a request for each host', () => { + let pbRequests = spec.buildRequests([bid1_zone1, bid3_host2]); + expect(pbRequests).to.have.length(2); + expect(pbRequests[0].url).to.have.string(`//${bid1_zone1.params.host}/`); + expect(pbRequests[1].url).to.have.string(`//${bid3_host2.params.host}/`); + }); + + it('should issue a request for each zone', () => { + let pbRequests = spec.buildRequests([bid1_zone1, bid2_zone2]); + expect(pbRequests).to.have.length(2); + expect(pbRequests[0].data.zone).to.be.equal(bid1_zone1.params.zoneId); + expect(pbRequests[1].data.zone).to.be.equal(bid2_zone2.params.zoneId); + }); + }); + + describe('responses processing', () => { + it('should return fully-initialized banner bid-response', () => { + let request = spec.buildRequests([bid1_zone1])[0]; + let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; + expect(resp).to.have.property('requestId', 'Bid_01'); + expect(resp).to.have.property('cpm', 3.01); + expect(resp).to.have.property('width', 300); + expect(resp).to.have.property('height', 250); + expect(resp).to.have.property('creativeId', '100_001'); + expect(resp).to.have.property('currency'); + expect(resp).to.have.property('ttl'); + expect(resp).to.have.property('mediaType', 'banner'); + expect(resp).to.have.property('ad'); + expect(resp.ad).to.have.string(''); + }); + + it('should add nurl as pixel for banner response', () => { + let request = spec.buildRequests([bid1_zone1])[0]; + let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; + let expectedNurl = bidResponse1.seatbid[0].bid[0].nurl + '&px=1'; + expect(resp.ad).to.have.string(expectedNurl); + }); + + it('should handle bidresponse with user-sync only', () => { + let request = spec.buildRequests([bid1_zone1])[0]; + let resp = spec.interpretResponse({body: usersyncOnlyResponse}, request); + expect(resp).to.have.length(0); + }); + + it('should perform usersync', () => { + let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: bidResponse1}]); + expect(syncs).to.have.length(0); + syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: bidResponse1}]); + expect(syncs).to.have.length(1); + expect(syncs[0]).to.have.property('type', 'iframe'); + expect(syncs[0]).to.have.property('url', 'http://adk.sync.com/sync'); + }); + }); +}); From f6575d8eb3694bf8b7bcd789397731cf4c40834c Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 4 Jun 2018 12:22:46 -0400 Subject: [PATCH 0439/1594] convert appnexus keywords to style needed for pbs (#2667) --- modules/appnexusBidAdapter.js | 28 +----------- modules/prebidServerBidAdapter.js | 5 ++- src/utils.js | 33 ++++++++++++++ .../modules/prebidServerBidAdapter_spec.js | 44 +++++++++++++++++-- 4 files changed, 77 insertions(+), 33 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 3f0bf3a4826..1480bc164b5 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -157,32 +157,6 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { return renderer; } -/* Turn keywords parameter into ut-compatible format */ -function getKeywords(keywords) { - let arrs = []; - - utils._each(keywords, (v, k) => { - if (utils.isArray(v)) { - let values = []; - utils._each(v, (val) => { - val = utils.getValueString('keywords.' + k, val); - if (val) { values.push(val); } - }); - v = values; - } else { - v = utils.getValueString('keywords.' + k, v); - if (utils.isStr(v)) { - v = [v]; - } else { - return; - } // unsuported types - don't send a key - } - arrs.push({key: k, value: v}); - }); - - return arrs; -} - /** * Unpack the Server's Bid into a Prebid-compatible one. * @param serverBid @@ -310,7 +284,7 @@ function bidToTag(bid) { tag.external_imp_id = bid.params.externalImpId; } if (!utils.isEmpty(bid.params.keywords)) { - tag.keywords = getKeywords(bid.params.keywords); + tag.keywords = utils.transformBidderParamKeywords(bid.params.keywords); } if (bid.mediaType === NATIVE || utils.deepAccess(bid, `mediaTypes.${NATIVE}`)) { diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index fff1331e572..6533d9d00ee 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -208,7 +208,8 @@ const paramTypes = { 'appnexus': { 'member': tryConvertString, 'invCode': tryConvertString, - 'placementId': tryConvertNumber + 'placementId': tryConvertNumber, + 'keywords': utils.transformBidderParamKeywords }, 'rubicon': { 'accountId': tryConvertNumber, @@ -503,7 +504,7 @@ const OPEN_RTB_PROTOCOL = { // get bidder params in form { : {...params} } const ext = adUnit.bids.reduce((acc, bid) => { - // TODO: move this bidder specific out to a more ideal location (submodule?); issue# pending + // TODO: move this bidder specific out to a more ideal location (submodule?); https://github.com/prebid/Prebid.js/issues/2420 // convert all AppNexus keys to underscore format for pbs if (bid.bidder === 'appnexus') { bid.params.use_pmt_rule = (typeof bid.params.usePaymentRule === 'boolean') ? bid.params.usePaymentRule : false; diff --git a/src/utils.js b/src/utils.js index 678f61de87e..5675ace6bf8 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1046,3 +1046,36 @@ export function isInteger(value) { export function convertCamelToUnderscore(value) { return value.replace(/(?:^|\.?)([A-Z])/g, function (x, y) { return '_' + y.toLowerCase() }).replace(/^_/, ''); } + +/** + * Converts an object of arrays (either strings or numbers) into an array of objects containing key and value properties + * normally read from bidder params + * eg { foo: ['bar', 'baz'], fizz: ['buzz'] } + * becomes [{ key: 'foo', value: ['bar', 'baz']}, {key: 'fizz', value: ['buzz']}] + * @param {Object{Arrays}} keywords object of arrays representing keyvalue pairs + * @param {string} paramName name of parent object (eg 'keywords') containing keyword data, used in error handling + */ +export function transformBidderParamKeywords(keywords, paramName = 'keywords') { + let arrs = []; + + exports._each(keywords, (v, k) => { + if (exports.isArray(v)) { + let values = []; + exports._each(v, (val) => { + val = exports.getValueString(paramName + '.' + k, val); + if (val) { values.push(val); } + }); + v = values; + } else { + v = exports.getValueString(paramName + '.' + k, v); + if (exports.isStr(v)) { + v = [v]; + } else { + return; + } // unsuported types - don't send a key + } + arrs.push({key: k, value: v}); + }); + + return arrs; +} diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index d528c9a3191..b155d61d8e5 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -347,7 +347,11 @@ describe('S2S Adapter', () => { 'bidder': 'appnexus', 'params': { 'placementId': '10433394', - 'member': 123 + 'member': 123, + 'keywords': { + 'foo': ['bar', 'baz'], + 'fizz': ['buzz'] + } }, 'bid_id': '123', 'adUnitCode': 'div-gpt-ad-1460505748561-0', @@ -598,7 +602,7 @@ describe('S2S Adapter', () => { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({s2sConfig: s2sConfig}); const aliasBidder = { bidder: 'brealtime', @@ -625,7 +629,7 @@ describe('S2S Adapter', () => { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({s2sConfig: s2sConfig}); const alias = 'foobar'; const aliasBidder = { @@ -655,10 +659,14 @@ describe('S2S Adapter', () => { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({s2sConfig: s2sConfig}); const myRequest = utils.deepClone(REQUEST); myRequest.ad_units[0].bids[0].params.usePaymentRule = true; + myRequest.ad_units[0].bids[0].params.keywords = { + foo: ['bar', 'baz'], + fizz: ['buzz'] + }; adapter.callBids(myRequest, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); @@ -667,6 +675,34 @@ describe('S2S Adapter', () => { expect(requestBid.imp[0].ext.appnexus.placement_id).to.exist.and.to.equal(10433394); expect(requestBid.imp[0].ext.appnexus.use_pmt_rule).to.exist.and.to.be.true; expect(requestBid.imp[0].ext.appnexus.member).to.exist; + expect(requestBid.imp[0].ext.appnexus.keywords).to.exist.and.to.deep.equal([{ + key: 'foo', + value: ['bar', 'baz'] + }, { + key: 'fizz', + value: ['buzz'] + }]); + + config.resetConfig(); + const oldS2sConfig = Object.assign({}, CONFIG); + config.setConfig({s2sConfig: oldS2sConfig}); + + const myRequest2 = utils.deepClone(REQUEST); + myRequest2.ad_units[0].bids[0].params.keywords = { + foo: ['bar', 'baz'], + fizz: ['buzz'] + }; + + adapter.callBids(myRequest2, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid2 = JSON.parse(requests[1].requestBody); + + expect(requestBid2.ad_units[0].bids[0].params.keywords).to.exist.and.to.deep.equal([{ + key: 'foo', + value: ['bar', 'baz'] + }, { + key: 'fizz', + value: ['buzz'] + }]); }); }); From f81a0bd1557cc20fc92c103859d769eb85f6e623 Mon Sep 17 00:00:00 2001 From: SpreeGorilla <31438227+SpreeGorilla@users.noreply.github.com> Date: Mon, 4 Jun 2018 19:39:04 +0200 Subject: [PATCH 0440/1594] AdSpirit Bid Adapter (#2419) * renewed everything in hope to make progress * - * - * - * - * - * - * - * - * - * - * updated test params * updated test params * - --- integrationExamples/gpt/hello_world.html | 194 +++++++++--------- .../gpt/pbjs_ucfunnel_gpt.html | 194 +++++++++--------- modules/adspiritBidAdapter.js | 72 +++++++ modules/adspiritBidAdapter.md | 28 +++ test/spec/modules/adspiritBidAdapter_spec.js | 142 +++++++++++++ 5 files changed, 436 insertions(+), 194 deletions(-) create mode 100644 modules/adspiritBidAdapter.js create mode 100644 modules/adspiritBidAdapter.md create mode 100644 test/spec/modules/adspiritBidAdapter_spec.js diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index a5949b87c56..be181db21b2 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -1,98 +1,98 @@ - - - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
-
- -
- + + + + + + + + + + + + + + + +

Prebid.js Test

+
Div-1
+
+ +
+ \ No newline at end of file diff --git a/integrationExamples/gpt/pbjs_ucfunnel_gpt.html b/integrationExamples/gpt/pbjs_ucfunnel_gpt.html index cda2af03b18..cb33a887c23 100644 --- a/integrationExamples/gpt/pbjs_ucfunnel_gpt.html +++ b/integrationExamples/gpt/pbjs_ucfunnel_gpt.html @@ -1,97 +1,97 @@ - - - - - - - - - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
- - -
- -
- - - + + + + + + + + + + + + + + + + + + + + + +

Prebid.js Test

+
Div-1
+ + +
+ +
+ + + diff --git a/modules/adspiritBidAdapter.js b/modules/adspiritBidAdapter.js new file mode 100644 index 00000000000..eeff89923ca --- /dev/null +++ b/modules/adspiritBidAdapter.js @@ -0,0 +1,72 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const RTB_URL = '/rtb/getbid.php?rtbprovider=prebid'; +const SCRIPT_URL = '/adasync.min.js'; +export const spec = { + code: 'adspirit', + aliases: ['xapadsmedia', 'connectad'], + isBidRequestValid: function(bid) { + let host = spec.getBidderHost(bid); + if (!host) return false; + if (!bid.params.placementId) return false; + return true; + }, + buildRequests: function(validBidRequests) { + let requests = []; + let bidRequest; + let reqUrl; + let placementId; + for (let i = 0; i < validBidRequests.length; i++) { + bidRequest = validBidRequests[i]; + bidRequest.adspiritConId = spec.genAdConId(bidRequest); + reqUrl = spec.getBidderHost(bidRequest); + placementId = utils.getBidIdParameter('placementId', bidRequest.params); + reqUrl = '//' + reqUrl + RTB_URL + '&pid=' + placementId + '&ref=' + encodeURIComponent(utils.getTopWindowUrl()) + '&scx=' + (screen.width) + '&scy=' + (screen.height) + '&wcx=' + ('innerWidth' in window ? window.innerWidth : page.clientWidth) + '&wcy=' + ('innerHeight' in window ? window.innerHeight : page.clientHeight) + '&async=' + bidRequest.adspiritConId + '&t=' + Math.round(Math.random() * 100000); + requests.push({ + method: 'GET', + url: reqUrl, + data: {}, + bidRequest: bidRequest + }); + } + return requests; + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + let bidObj = bidRequest.bidRequest; + + if (!serverResponse || !serverResponse.body || !bidObj) { + utils.logWarn(`No valid bids from ${spec.code} bidder!`); + return []; + } + let adData = serverResponse.body; + let cpm = adData.cpm; + if (!cpm) return []; + + let host = spec.getBidderHost(bidObj); + let adm = 'window.inDapIF=false' + '' + adData.adm; + const bidResponse = { + requestId: bidObj.bidId, + cpm: cpm, + width: adData.w, + height: adData.h, + creativeId: bidObj.params.placementId, + currency: 'EUR', + netRevenue: true, + ttl: 300, + ad: adm + }; + bidResponses.push(bidResponse); + return bidResponses; + }, + getBidderHost: function(bid) { + if (bid.bidder === 'adspirit') return utils.getBidIdParameter('host', bid.params); + if (bid.bidder === 'connectad') return 'connected-by.connectad.io'; + if (bid.bidder === 'xapadsmedia') return 'dsp.xapads.com'; + return null; + }, + genAdConId: function(bid) { + return bid.bidder + Math.round(Math.random() * 100000); + } +} +registerBidder(spec); diff --git a/modules/adspiritBidAdapter.md b/modules/adspiritBidAdapter.md new file mode 100644 index 00000000000..688d0814882 --- /dev/null +++ b/modules/adspiritBidAdapter.md @@ -0,0 +1,28 @@ +# Overview + +**Module Name**: AdSpirit Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: prebid@adspirit.de + +# Description + +Module that connects to an AdSpirit zone to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'display-div', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "adspirit", + params: { + placementId: '5', + host: 'n1test.adspirit.de' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/adspiritBidAdapter_spec.js b/test/spec/modules/adspiritBidAdapter_spec.js new file mode 100644 index 00000000000..5c8400a8cbc --- /dev/null +++ b/test/spec/modules/adspiritBidAdapter_spec.js @@ -0,0 +1,142 @@ +import {expect} from 'chai'; +import {spec} from 'modules/adspiritBidAdapter'; + +describe('Adspirit adapter tests', () => { + let bidRequests, serverResponses; + + beforeEach(() => { + bidRequests = [ + // valid for adspirit + { + bidder: 'adspirit', + placementCode: 'ad-1', + params: { + placementId: '1', + host: 'test.adspirit.de' + }, + }, + // valid for xapadsmedia + { + bidder: 'xapadsmedia', + placementCode: 'ad-1', + params: { + placementId: '1' + }, + }, + // valid for connectad + { + bidder: 'connectad', + placementCode: 'ad-1', + params: { + placementId: '1' + }, + }, + // invalid 1 + { + bidder: 'adspirit', + placementCode: 'ad-1', + params: { + }, + }, + // invalid 2 + { + bidder: 'adspirit', + placementCode: 'ad-1', + params: { + host: 'test.adspirit.de' + }, + }, + // invalid 3 + { + bidder: '-', + placementCode: 'ad-1', + params: { + host: 'test.adspirit.de' + }, + } + ]; + serverResponses = [ + { + headers: {}, + body: { + cpm: 1.5, + w: 300, + h: 250, + placement_id: 1, + adm: '' + } + }, + { + headers: {}, + body: { + cpm: 0, + w: 0, + h: 0, + placement_id: 1, + adm: '' + } + }, + { + headers: {}, + body: { + cpm: 0, + w: 0, + h: 0, + placement_id: 0, + adm: '' + } + } + ] + }); + + describe('test bid request', () => { + it('with valid data 1', () => { + expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); + }); + it('with valid data 2', () => { + expect(spec.isBidRequestValid(bidRequests[1])).to.equal(true); + }); + it('with valid data 3', () => { + expect(spec.isBidRequestValid(bidRequests[2])).to.equal(true); + }); + it('with invalid data 1 (no host)', () => { + expect(spec.isBidRequestValid(bidRequests[3])).to.equal(false); + }); + it('with invalid data 2 (no placementId)', () => { + expect(spec.isBidRequestValid(bidRequests[4])).to.equal(false); + }); + it('with invalid data 3 (no bidder code)', () => { + expect(spec.isBidRequestValid(bidRequests[5])).to.equal(false); + }); + }); + + describe('test request build', () => { + it('normal', () => { + var requests = spec.buildRequests([bidRequests[0]]); + expect(requests).to.be.lengthOf(1); + }); + }); + + describe('test bid responses', () => { + it('success 1', () => { + var bids = spec.interpretResponse(serverResponses[0], {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(1.5); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(250); + expect(bids[0].ad).to.have.length.above(1); + }); + it('fail 1 (cpm=0)', () => { + var bids = spec.interpretResponse(serverResponses[1], {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(0); + }); + it('fail 2 (no response)', () => { + var bids = spec.interpretResponse([], {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(0); + }); + it('fail 3 (status fail)', () => { + var bids = spec.interpretResponse(serverResponses[2], {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(0); + }); + }); +}); From 646a971219779f752a798e172c8bf0a590779f84 Mon Sep 17 00:00:00 2001 From: NLopezMad <22349934+NLopezMad@users.noreply.github.com> Date: Tue, 5 Jun 2018 13:11:17 +0200 Subject: [PATCH 0441/1594] GDPR consent management for madvertise bidder adapter (#2655) * New adapter madvertise * Update madvertiseBidAdapter.js remove aliases * Update madvertiseBidAdapter.js use parseSizesInput method * fix test parseSizesInput * fix lint parseSizesInput * remove seeanAd feature * remove console.log * Add gdpr consent management to madvertise module --- modules/madvertiseBidAdapter.js | 8 +- .../spec/modules/madvertiseBidAdapter_spec.js | 74 +++++++++++++++---- 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/modules/madvertiseBidAdapter.js b/modules/madvertiseBidAdapter.js index 620ab3b7396..af4919c96bc 100644 --- a/modules/madvertiseBidAdapter.js +++ b/modules/madvertiseBidAdapter.js @@ -1,4 +1,5 @@ import * as utils from 'src/utils'; +import {config} from 'src/config'; import {registerBidder} from 'src/adapters/bidderFactory'; // use protocol relative urls for http or https @@ -29,9 +30,10 @@ export const spec = { }, /** * @param {BidRequest[]} bidRequests + * @param bidderRequest * @return ServerRequest[] */ - buildRequests: function (bidRequests) { + buildRequests: function (bidRequests, bidderRequest) { return bidRequests.map(bidRequest => { bidRequest.startTime = new Date().getTime(); @@ -50,6 +52,10 @@ export const spec = { src = src + '&u=' + navigator.userAgent; } + if (bidderRequest && bidderRequest.gdprConsent) { + src = src + '&gdpr=' + (bidderRequest.gdprConsent.gdprApplies ? '1' : '0') + '&consent[0][format]=' + config.getConfig('consentManagement.cmpApi') + '&consent[0][value]=' + bidderRequest.gdprConsent.consentString; + } + return { method: 'GET', url: MADVERTISE_ENDPOINT + src, diff --git a/test/spec/modules/madvertiseBidAdapter_spec.js b/test/spec/modules/madvertiseBidAdapter_spec.js index 64ecf556aa5..c391ca1d39f 100644 --- a/test/spec/modules/madvertiseBidAdapter_spec.js +++ b/test/spec/modules/madvertiseBidAdapter_spec.js @@ -1,4 +1,6 @@ import {expect} from 'chai'; +import {config} from 'src/config'; +import * as utils from 'src/utils'; import {spec} from 'modules/madvertiseBidAdapter'; describe('madvertise adapater', () => { @@ -70,26 +72,70 @@ describe('madvertise adapater', () => { }); describe('Test build request', () => { - it('minimum request', () => { - let bid = [{ - bidder: 'madvertise', - sizes: [[728, 90], [300, 100]], - bidId: '51ef8751f9aead', - adUnitCode: 'div-gpt-ad-1460505748561-0', - transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - auctionId: '18fd8b8b0bd757', - bidderRequestId: '418b37f85e772c', - params: { - s: 'test', + beforeEach(function () { + let mockConfig = { + consentManagement: { + cmpApi: 'IAB', + timeout: 1111, + allowAuctionWithoutConsent: 'cancel' } - }]; - const req = spec.buildRequests(bid); + }; + + sinon.stub(config, 'getConfig').callsFake((key) => { + return utils.deepAccess(mockConfig, key); + }); + }); + afterEach(function () { + config.getConfig.restore(); + }); + let bid = [{ + bidder: 'madvertise', + sizes: [[728, 90], [300, 100]], + bidId: '51ef8751f9aead', + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + auctionId: '18fd8b8b0bd757', + bidderRequestId: '418b37f85e772c', + params: { + s: 'test', + } + }]; + it('minimum request with gdpr consent', () => { + let bidderRequest = { + gdprConsent: { + consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + vendorData: {}, + gdprApplies: true + } + }; + const req = spec.buildRequests(bid, bidderRequest); + + expect(req).to.exist.and.to.be.a('array'); + expect(req[0]).to.have.property('method'); + expect(req[0].method).to.equal('GET'); + expect(req[0]).to.have.property('url'); + expect(req[0].url).to.contain('//mobile.mng-ads.com/?rt=bid_request&v=1.0'); + expect(req[0].url).to.contain(`&s=test`); + expect(req[0].url).to.contain(`&sizes[0]=728x90`); + expect(req[0].url).to.contain(`&gdpr=1`); + expect(req[0].url).to.contain(`&consent[0][format]=IAB`); + expect(req[0].url).to.contain(`&consent[0][value]=BOJ/P2HOJ/P2HABABMAAAAAZ+A==`) + }); + + it('minimum request without gdpr consent', () => { + let bidderRequest = {}; + const req = spec.buildRequests(bid, bidderRequest); expect(req).to.exist.and.to.be.a('array'); expect(req[0]).to.have.property('method'); expect(req[0].method).to.equal('GET'); expect(req[0]).to.have.property('url'); - expect(req[0].url).to.contain('//mobile.mng-ads.com/?rt=bid_request&v=1.0').and.to.contain(`&s=test`).and.to.contain(`&sizes[0]=728x90`) + expect(req[0].url).to.contain('//mobile.mng-ads.com/?rt=bid_request&v=1.0'); + expect(req[0].url).to.contain(`&s=test`); + expect(req[0].url).to.contain(`&sizes[0]=728x90`); + expect(req[0].url).not.to.contain(`&gdpr=1`); + expect(req[0].url).not.to.contain(`&consent[0][format]=`); + expect(req[0].url).not.to.contain(`&consent[0][value]=`) }); }); From 6fbc404697c7e49f3dc9d345c25b100ee1bd1d44 Mon Sep 17 00:00:00 2001 From: Tomas Roos Date: Tue, 5 Jun 2018 16:29:04 +0200 Subject: [PATCH 0442/1594] Consistent targeting set (#2592) * Populate adUnitCode's even though there's no bid available * Add new targeting test for no bids, and upgrade old implicit getAdserverTargeting calls * Updated to a more simplex generation method --- src/targeting.js | 9 ++++++++ test/spec/unit/core/targeting_spec.js | 30 +++++++++++++++++++++++++++ test/spec/unit/pbjs_api_spec.js | 18 ++++++++-------- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index 7a301472823..f81949f6d04 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -100,6 +100,15 @@ export function newTargeting(auctionManager) { }); targeting = flattenTargeting(targeting); + + // make sure at least there is a entry per adUnit code in the targetingSet so receivers of SET_TARGETING call's can know what ad units are being invoked + + adUnitCodes.forEach(code => { + if (!targeting[code]) { + targeting[code] = {}; + } + }); + return targeting; }; diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 048e19a6177..cf08c65d1fb 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -136,6 +136,36 @@ describe('targeting tests', () => { }); }); // end getAllTargeting tests + describe('getAllTargeting without bids return empty object', () => { + let amBidsReceivedStub; + let amGetAdUnitsStub; + let bidExpiryStub; + + beforeEach(() => { + $$PREBID_GLOBAL$$._sendAllBids = false; + amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived').callsFake(function() { + return []; + }); + amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { + return ['/123456/header-bid-tag-0']; + }); + bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').returns(true); + }); + + afterEach(() => { + auctionManager.getBidsReceived.restore(); + auctionManager.getAdUnitCodes.restore(); + targetingModule.isBidExpired.restore(); + }); + + it('returns targetingSet correctly', () => { + let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // we should only get the targeting data for the one requested adunit to at least exist even though it has no keys to set + expect(Object.keys(targeting).length).to.equal(1); + }); + }); // end getAllTargeting without bids return empty object + describe('Targeting in concurrent auctions', () => { describe('check getOldestBid', () => { let bidExpiryStub; diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index ca4e5e7e5f9..5f77d0e5bf7 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -202,13 +202,13 @@ describe('Unit: Prebid Module', function () { it('should return current targeting data for slots', function () { $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - const targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); - const expected = getAdServerTargeting(); + const targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); + const expected = getAdServerTargeting(['/19968336/header-bid-tag-0, /19968336/header-bid-tag1']); assert.deepEqual(targeting, expected, 'targeting ok'); }); it('should return correct targeting with default settings', () => { - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); var expected = { '/19968336/header-bid-tag-0': { foobar: '0x0,300x250,300x600', @@ -230,8 +230,8 @@ describe('Unit: Prebid Module', function () { it('should return correct targeting with bid landscape targeting on', () => { $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); - var expected = getAdServerTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); + var expected = getAdServerTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); assert.deepEqual(targeting, expected); }); @@ -248,7 +248,7 @@ describe('Unit: Prebid Module', function () { auction.getBidsReceived = function() { return _bidsReceived }; - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); // Ensure targeting for both ad placements includes the custom key. assert.equal( @@ -312,7 +312,7 @@ describe('Unit: Prebid Module', function () { } }; - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); var expected = { '/19968336/header-bid-tag-0': { @@ -346,7 +346,7 @@ describe('Unit: Prebid Module', function () { auction.getBidsReceived = function() { return _bidsReceived }; - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); var expected = { '/19968336/header-bid-tag-0': { @@ -1488,7 +1488,7 @@ describe('Unit: Prebid Module', function () { assert.ok(spyCallBids.calledTwice, 'When two requests for bids are made both should be' + ' callBids immediately'); - let result = targeting.getAllTargeting(); // $$PREBID_GLOBAL$$.getAdserverTargeting(); + let result = targeting.getAllTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); // $$PREBID_GLOBAL$$.getAdserverTargeting(); let expected = { '/19968336/header-bid-tag-0': { 'foobar': '0x0,300x250,300x600', From 36ea98722e05fc6604dc9aabeb356a5899706a75 Mon Sep 17 00:00:00 2001 From: Valentin Zhukovsky Date: Tue, 5 Jun 2018 18:36:16 +0300 Subject: [PATCH 0443/1594] Added passing GDPR applies flag without consent string for AOL adapter. (#2611) --- modules/aolBidAdapter.js | 91 ++++++++++++++++--------- test/spec/modules/aolBidAdapter_spec.js | 48 +++++++++---- 2 files changed, 90 insertions(+), 49 deletions(-) diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 18d30685c56..28e8cb0b46e 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -31,7 +31,7 @@ const SYNC_TYPES = { } }; -const pubapiTemplate = template`//${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'}${'bidfloor'}${'keyValues'}${'consentData'}`; +const pubapiTemplate = template`//${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'};${'dynamicParams'}`; const nexageBaseApiTemplate = template`//${'host'}/bidRequest?`; const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'dynamicParams'}`; const MP_SERVER_MAP = { @@ -47,6 +47,11 @@ $$PREBID_GLOBAL$$.aolGlobals = { pixelsDropped: false }; +const NUMERIC_VALUES = { + TRUE: 1, + FALSE: 0 +}; + let showCpmAdjustmentWarning = (function() { let showCpmWarning = true; @@ -101,20 +106,6 @@ function parsePixelItems(pixels) { return pixelsItems; } -function formatMarketplaceBidFloor(bidFloor) { - return (typeof bidFloor !== 'undefined') ? `;bidfloor=${bidFloor.toString()}` : ''; -} - -function formatMarketplaceKeyValues(keyValues) { - let formattedKeyValues = ''; - - utils._each(keyValues, (value, key) => { - formattedKeyValues += `;kv${key}=${encodeURIComponent(value)}`; - }); - - return formattedKeyValues; -} - function _isMarketplaceBidder(bidder) { return bidder === AOL_BIDDERS_CODES.AOL || bidder === AOL_BIDDERS_CODES.ONEDISPLAY; } @@ -268,10 +259,8 @@ export const spec = { pageid: params.pageId || 0, sizeid: params.sizeId || 0, alias: params.alias || utils.getUniqueIdentifierStr(), - misc: new Date().getTime(), // cache busting, - bidfloor: formatMarketplaceBidFloor(params.bidFloor), - keyValues: formatMarketplaceKeyValues(params.keyValues), - consentData: this.formatMarketplaceConsentData(consentData) + misc: new Date().getTime(), // cache busting + dynamicParams: this.formatMarketplaceDynamicParams(params, consentData) }); }, buildOneMobileGetUrl(bid, consentData) { @@ -288,15 +277,29 @@ export const spec = { host: bid.params.host || NEXAGE_SERVER }); }, + formatMarketplaceDynamicParams(params = {}, consentData) { + let queryParams = {}; + + if (params.bidFloor) { + queryParams.bidfloor = params.bidFloor; + } + + Object.assign(queryParams, this.formatKeyValues(params.keyValues)); + Object.assign(queryParams, this.formatConsentData(consentData)); + + let paramsFormatted = ''; + utils._each(queryParams, (value, key) => { + paramsFormatted += `${key}=${encodeURIComponent(value)};`; + }); + + return paramsFormatted; + }, formatOneMobileDynamicParams(params = {}, consentData) { if (this.isSecureProtocol()) { - params.secure = 1; + params.secure = NUMERIC_VALUES.TRUE; } - if (this.isConsentRequired(consentData)) { - params.euconsent = consentData.consentString; - params.gdpr = 1; - } + Object.assign(params, this.formatConsentData(consentData)); let paramsFormatted = ''; utils._each(params, (value, key) => { @@ -312,27 +315,47 @@ export const spec = { }; if (this.isConsentRequired(consentData)) { - openRtbObject.user = { - ext: { - consent: consentData.consentString - } - }; openRtbObject.regs = { ext: { - gdpr: 1 + gdpr: NUMERIC_VALUES.TRUE } }; + + if (consentData.consentString) { + openRtbObject.user = { + ext: { + consent: consentData.consentString + } + }; + } } return openRtbObject; }, isConsentRequired(consentData) { - return !!(consentData && consentData.consentString && consentData.gdprApplies); + return !!(consentData && consentData.gdprApplies); }, - formatMarketplaceConsentData(consentData) { - let consentRequired = this.isConsentRequired(consentData); + formatKeyValues(keyValues) { + let keyValuesHash = {}; + + utils._each(keyValues, (value, key) => { + keyValuesHash[`kv${key}`] = value; + }); + + return keyValuesHash; + }, + formatConsentData(consentData) { + let params = {}; + + if (this.isConsentRequired(consentData)) { + params.gdpr = NUMERIC_VALUES.TRUE; + + if (consentData.consentString) { + params.euconsent = consentData.consentString; + } + } - return consentRequired ? `;euconsent=${consentData.consentString};gdpr=1` : ''; + return params; }, _parseBidResponse(response, bidRequest) { diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index d69b9e6e3d8..bc42f69ce63 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -576,13 +576,13 @@ describe('AolAdapter', () => { expect(spec.isConsentRequired(null)).to.be.false; }); - it('should return false when gdprApplies equals true and consentString is not present', () => { + it('should return true when gdprApplies equals true and consentString is not present', () => { let consentData = { consentString: null, gdprApplies: true }; - expect(spec.isConsentRequired(consentData)).to.be.false; + expect(spec.isConsentRequired(consentData)).to.be.true; }); it('should return false when consentString is present and gdprApplies equals false', () => { @@ -604,28 +604,46 @@ describe('AolAdapter', () => { }); }); - describe('formatMarketplaceConsentData()', () => { - let consentRequiredStub; + describe('formatMarketplaceDynamicParams()', () => { + let formatConsentDataStub; + let formatKeyValuesStub; beforeEach(() => { - consentRequiredStub = sinon.stub(spec, 'isConsentRequired'); + formatConsentDataStub = sinon.stub(spec, 'formatConsentData'); + formatKeyValuesStub = sinon.stub(spec, 'formatKeyValues'); }); afterEach(() => { - consentRequiredStub.restore(); + formatConsentDataStub.restore(); + formatKeyValuesStub.restore(); }); - it('should return empty string when consent is not required', () => { - consentRequiredStub.returns(false); - expect(spec.formatMarketplaceConsentData()).to.be.equal(''); + it('should return empty string when params are not present', () => { + expect(spec.formatMarketplaceDynamicParams()).to.be.equal(''); }); - it('should return formatted consent data when consent is required', () => { - consentRequiredStub.returns(true); - let formattedConsentData = spec.formatMarketplaceConsentData({ - consentString: 'test-consent' + it('should return formatted params when formatConsentData returns data', () => { + formatConsentDataStub.returns({ + euconsent: 'test-consent', + gdpr: 1 + }); + expect(spec.formatMarketplaceDynamicParams()).to.be.equal('euconsent=test-consent;gdpr=1;'); + }); + + it('should return formatted params when formatKeyValues returns data', () => { + formatKeyValuesStub.returns({ + param1: 'val1', + param2: 'val2', + param3: 'val3' }); - expect(formattedConsentData).to.be.equal(';euconsent=test-consent;gdpr=1'); + expect(spec.formatMarketplaceDynamicParams()).to.be.equal('param1=val1;param2=val2;param3=val3;'); + }); + + it('should return formatted bid floor param when it is present', () => { + let params = { + bidFloor: 0.45 + }; + expect(spec.formatMarketplaceDynamicParams(params)).to.be.equal('bidfloor=0.45;'); }); }); @@ -661,7 +679,7 @@ describe('AolAdapter', () => { consentString: 'test-consent' }; consentRequiredStub.returns(true); - expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&euconsent=test-consent&gdpr=1'); + expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&gdpr=1&euconsent=test-consent'); }); it('should return formatted secure param when isSecureProtocol returns true', () => { From 60f93149e7fe677cdd2501e5c21e5b38cc7738df Mon Sep 17 00:00:00 2001 From: Jake Miller Date: Tue, 5 Jun 2018 13:03:18 -0700 Subject: [PATCH 0444/1594] Added GDPR consent management to UnderdogMedia Bid Adapter (#2679) * updated underdogmedia adapter for prebid 1.0 * updated with recommended changes * UnderdogMedia Adapter - Added GDPR Support --- modules/underdogmediaBidAdapter.js | 43 ++++-- .../modules/underdogmediaBidAdapter_spec.js | 144 ++++++++++++++++-- 2 files changed, 168 insertions(+), 19 deletions(-) diff --git a/modules/underdogmediaBidAdapter.js b/modules/underdogmediaBidAdapter.js index 0b2009d8133..a4531968d31 100644 --- a/modules/underdogmediaBidAdapter.js +++ b/modules/underdogmediaBidAdapter.js @@ -2,7 +2,10 @@ import * as utils from 'src/utils'; import { config } from 'src/config'; import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'underdogmedia'; -const UDM_ADAPTER_VERSION = '1.0'; +const UDM_ADAPTER_VERSION = '1.13V'; +const UDM_VENDOR_ID = '159'; + +utils.logMessage(`Initializing UDM Adapter. PBJS Version: ${$$PREBID_GLOBAL$$.version} with adapter version: ${UDM_ADAPTER_VERSION} Updated 20180604`); export const spec = { code: BIDDER_CODE, @@ -12,7 +15,7 @@ export const spec = { return !!((bid.params && bid.params.siteId) && (bid.sizes && bid.sizes.length > 0)); }, - buildRequests: function (validBidRequests) { + buildRequests: function (validBidRequests, bidderRequest) { var sizes = []; var siteId = 0; @@ -21,12 +24,34 @@ export const spec = { siteId = bidParam.params.siteId; }); - return { - method: 'GET', - url: `${window.location.protocol}//udmserve.net/udm/img.fetch`, - data: `tid=1;dt=10;sid=${siteId};sizes=${sizes.join(',')}`, - bidParams: validBidRequests - }; + let data = { + tid: 1, + dt: 10, + sid: siteId, + sizes: sizes.join(',') + } + + if (bidderRequest && bidderRequest.gdprConsent) { + if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { + data.gdprApplies = !!(bidderRequest.gdprConsent.gdprApplies); + } + if (bidderRequest.gdprConsent.vendorData && bidderRequest.gdprConsent.vendorData.vendorConsents && + typeof bidderRequest.gdprConsent.vendorData.vendorConsents[UDM_VENDOR_ID] !== 'undefined') { + data.consentGiven = !!(bidderRequest.gdprConsent.vendorData.vendorConsents[UDM_VENDOR_ID]); + } + if (typeof bidderRequest.gdprConsent.consentString !== 'undefined') { + data.consentData = bidderRequest.gdprConsent.consentString; + } + } + + if (!data.gdprApplies || data.consentGiven) { + return { + method: 'GET', + url: `${window.location.protocol}//udmserve.net/udm/img.fetch`, + data: data, + bidParams: validBidRequests + }; + } }, interpretResponse: function (serverResponse, bidRequest) { @@ -84,7 +109,7 @@ export const spec = { }, }; -function makeNotification (bid, mid, bidParam) { +function makeNotification(bid, mid, bidParam) { var url = mid.notification_url; url += UDM_ADAPTER_VERSION; diff --git a/test/spec/modules/underdogmediaBidAdapter_spec.js b/test/spec/modules/underdogmediaBidAdapter_spec.js index 5dc2a65399f..8ccac8d4f08 100644 --- a/test/spec/modules/underdogmediaBidAdapter_spec.js +++ b/test/spec/modules/underdogmediaBidAdapter_spec.js @@ -3,6 +3,7 @@ import { spec } from 'modules/underdogmediaBidAdapter'; describe('UnderdogMedia adapter', () => { let bidRequests; + let bidderRequest; beforeEach(() => { bidRequests = [ @@ -19,6 +20,19 @@ describe('UnderdogMedia adapter', () => { transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' } ]; + + bidderRequest = { + timeout: 3000, + gdprConsent: { + gdprApplies: 1, + consentString: 'consentDataString', + vendorData: { + vendorConsents: { + '159': 1 + }, + }, + }, + } }); describe('implementation', () => { @@ -72,9 +86,9 @@ describe('UnderdogMedia adapter', () => { adUnitCode: '/123456/header-bid-tag-1' } ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data).to.have.string('sid=12143'); + expect(request.data.sid).to.equal('12143'); }); it('request data should contain sizes', () => { @@ -90,9 +104,119 @@ describe('UnderdogMedia adapter', () => { adUnitCode: '/123456/header-bid-tag-1' } ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.sizes).to.equal('300x250,728x90'); + }); + + it('request data should contain gdpr info', () => { + let bidRequests = [ + { + bidId: '3c9408cdbf2f68', + sizes: [[300, 250], [728, 90]], + bidder: 'underdogmedia', + params: { + siteId: '12143' + }, + auctionId: '10b327aa396609', + adUnitCode: '/123456/header-bid-tag-1' + } + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.gdprApplies).to.equal(true); + expect(request.data.consentGiven).to.equal(true); + expect(request.data.consentData).to.equal('consentDataString'); + }); + + it('should not build a request if no vendorConsent', () => { + let bidRequests = [ + { + bidId: '3c9408cdbf2f68', + sizes: [[300, 250], [728, 90]], + bidder: 'underdogmedia', + params: { + siteId: '12143' + }, + auctionId: '10b327aa396609', + adUnitCode: '/123456/header-bid-tag-1' + } + ]; + + let bidderRequest = { + timeout: 3000, + gdprConsent: { + gdprApplies: 1, + consentString: 'consentDataString', + vendorData: { + vendorConsents: { + '159': 0 + }, + }, + }, + } + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request).to.equal(undefined); + }); + + it('should properly build a request if no vendorConsent but no gdprApplies', () => { + let bidRequests = [ + { + bidId: '3c9408cdbf2f68', + sizes: [[300, 250], [728, 90]], + bidder: 'underdogmedia', + params: { + siteId: '12143' + }, + auctionId: '10b327aa396609', + adUnitCode: '/123456/header-bid-tag-1' + } + ]; + + let bidderRequest = { + timeout: 3000, + gdprConsent: { + gdprApplies: 0, + consentString: 'consentDataString', + vendorData: { + vendorConsents: { + '159': 0 + }, + }, + }, + } + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.sizes).to.equal('300x250,728x90'); + expect(request.data.sid).to.equal('12143'); + expect(request.data.gdprApplies).to.equal(false); + expect(request.data.consentGiven).to.equal(false); + expect(request.data.consentData).to.equal('consentDataString'); + }); + + it('should properly build a request if gdprConsent empty', () => { + let bidRequests = [ + { + bidId: '3c9408cdbf2f68', + sizes: [[300, 250], [728, 90]], + bidder: 'underdogmedia', + params: { + siteId: '12143' + }, + auctionId: '10b327aa396609', + adUnitCode: '/123456/header-bid-tag-1' + } + ]; + + let bidderRequest = { + timeout: 3000, + gdprConsent: {} + } + const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data).to.have.string('sizes=300x250,728x90'); + expect(request.data.sizes).to.equal('300x250,728x90'); + expect(request.data.sid).to.equal('12143'); }); }); @@ -122,7 +246,7 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(2); @@ -142,7 +266,7 @@ describe('UnderdogMedia adapter', () => { mids: [] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(0); @@ -164,7 +288,7 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(0); @@ -186,7 +310,7 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(0); @@ -208,7 +332,7 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(0); @@ -230,7 +354,7 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids[0].ad).to.have.string('notification_url'); From 4bdce3500f2efe70e7a0e1b3db27a710c5a16be5 Mon Sep 17 00:00:00 2001 From: brainymisio Date: Wed, 6 Jun 2018 23:12:43 +0900 Subject: [PATCH 0445/1594] Add user sync for brainyAdapter (#2666) --- modules/brainyBidAdapter.js | 23 ++++++++++ test/spec/modules/brainyBidAdapter_spec.js | 50 +++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/modules/brainyBidAdapter.js b/modules/brainyBidAdapter.js index 3274b10b97d..e8e5bda9f37 100644 --- a/modules/brainyBidAdapter.js +++ b/modules/brainyBidAdapter.js @@ -126,6 +126,29 @@ export const spec = { }); return bidResponses; + }, + + /** + * SyncURLがある場合にレスポンスを解析してURLを返す + * @param {object} syncOptions Syncの設定 + * @param {object} serverResponses SSPからのレスポンス + * @return {object} 表示タイプとURLが入ったオブジェクト + */ + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = []; + if (syncOptions.pixelEnabled) { + const brainyResponseObj = serverResponses[0].body; + if (!brainyResponseObj) { + return []; + } + if (brainyResponseObj.syncUrl && brainyResponseObj.syncUrl != 'null' && brainyResponseObj.syncUrl.length > 0) { + syncs.push({ + type: 'image', + url: brainyResponseObj.syncUrl + }); + } + } + return syncs; } }; registerBidder(spec); diff --git a/test/spec/modules/brainyBidAdapter_spec.js b/test/spec/modules/brainyBidAdapter_spec.js index 8dc74435263..157356e82db 100644 --- a/test/spec/modules/brainyBidAdapter_spec.js +++ b/test/spec/modules/brainyBidAdapter_spec.js @@ -31,16 +31,39 @@ const bidReq = [{ const correctReq = { accountID: '12345', slotID: '12345' -} +}; const bidResponse = { ad_id: '1036e9746c-d186-49ae-90cb-2796d0f9b223', adm: '', + syncUrl: '//testparm.com/ssp-sync/p/sync?uid=2110180601155125000059&buyer=2&slot=34', cpm: 100, height: 250, width: 300 }; +const bidSyncResponse = [{ + body: { + ad_id: '1036e9746c-d186-49ae-90cb-2796d0f9b223', + adm: '', + syncUrl: '//testparm.com/ssp-sync/p/sync?uid=2110180601155125000059&buyer=2&slot=34', + cpm: 100, + height: 250, + width: 300 + } +}]; + +const invalidSyncBidResponse = [{ + body: { + ad_id: '1036e9746c-d186-49ae-90cb-2796d0f9b223', + adm: '', + syncUrl: 'null', + cpm: 100, + height: 250, + width: 300 + } +}]; + describe('brainy Adapter', () => { describe('request', () => { it('should validate bid request', () => { @@ -77,4 +100,29 @@ describe('brainy Adapter', () => { expect(bid.height).to.equal(bidResponse.height); }); }); + + describe('spec.getUserSyncs', () => { + let syncOptions + beforeEach(() => { + syncOptions = { + enabledBidders: ['brainy'], + pixelEnabled: true + } + }); + it('sucess with usersync url', () => { + const result = []; + result.push({type: 'image', url: '//testparm.com/ssp-sync/p/sync?uid=2110180601155125000059&buyer=2&slot=34'}); + expect(spec.getUserSyncs(syncOptions, bidSyncResponse)).to.deep.equal(result); + }); + + it('sucess without usersync url', () => { + const result = []; + expect(spec.getUserSyncs(syncOptions, invalidSyncBidResponse)).to.deep.equal(result); + }); + it('empty response', () => { + const serverResponse = [{body: {}}]; + const result = []; + expect(spec.getUserSyncs(syncOptions, serverResponse)).to.deep.equal(result); + }); + }); }); From 6fd97d6a23803d8b54393ffb74e8bb821e426265 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Wed, 6 Jun 2018 10:36:43 -0400 Subject: [PATCH 0446/1594] Sonobi - suppress user sync error (#2686) * added vp param to trinity request * added lib_name and lib_v to trinity * return null from buildRequests if there is no keymakers * added test case for empty keymaker * only importing functions we need from utils * changed window.pbjs.version to use the gulp repalced macro .version$ * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * fixed lint issue * fixed issue where sonobi getUserSync was throwing an error on timeout * sonobi support referrer param * fixed unit test for testing the ref param on bid request * return null from buildRequests if there is no keymakers * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * Add gdpr support * no longer logging error when getUserSync fails to parse a serverResponse --- modules/sonobiBidAdapter.js | 4 +--- test/spec/modules/sonobiBidAdapter_spec.js | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 11fa4d72daf..4b7c5fc1221 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -153,9 +153,7 @@ export const spec = { }); }); } - } catch (e) { - logError(e) - } + } catch (e) {} return syncs; } }; diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 9162354d95b..8903f3375f0 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -352,7 +352,8 @@ describe('SonobiBidAdapter', () => { it('should return an empty array', () => { expect(spec.getUserSyncs({ pixelEnabled: false }, bidResponse)).to.have.length(0); - }) + expect(spec.getUserSyncs({ pixelEnabled: true }, [])).to.have.length(0); + }); }) describe('_getPlatform', () => { it('should return mobile', () => { From ee4074e40f625e2b438579f73b99c471d1690edc Mon Sep 17 00:00:00 2001 From: sami-elasticad <35566930+sami-elasticad@users.noreply.github.com> Date: Wed, 6 Jun 2018 17:42:55 +0300 Subject: [PATCH 0447/1594] Native images bug fixed (#2681) * quantumBidAdapter initial commit * eslint errors fixed * updating quantumBidAdapter for reviews, fixed tests to work with native * set new prebid location for testing and some fixing * added supportedMediaTypes * Tests fixed * Fixed issues with image assets. Tested with the example provided * Size and tests fixed * Modify tests * hello world revert changes * package-lock reverted * hello world reverted CRLF/LF Conversion * hello world reverted LF/CRLF Conversion * hello world reverted * hello world reverted * hello world reverted * removed hardcoded bid sizes * GDPR integration * GDPR support - change quantx_gdpr to (0,1) values accepted * restored package-lock * GDPR tests * GDPR tests fixed * Send width/height with native assets * Fixed native images bug --- modules/quantumBidAdapter.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/quantumBidAdapter.js b/modules/quantumBidAdapter.js index 19f9fbe07e2..57e732dfc51 100644 --- a/modules/quantumBidAdapter.js +++ b/modules/quantumBidAdapter.js @@ -251,9 +251,9 @@ export const spec = { break; case 2: native.icon = { - url: asset['img'], - width: asset['w'], - height: asset['h'] + url: asset['img']['url'], + width: asset['img']['w'], + height: asset['img']['h'] }; break; case 3: @@ -261,9 +261,9 @@ export const spec = { break; case 4: native.image = { - url: asset['img'], - width: asset['w'], - height: asset['h'] + url: asset['img']['url'], + width: asset['img']['w'], + height: asset['img']['h'] }; break; case 10: From 86b848c1f51f33e3a3c6937c9ca85f16b3837684 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 6 Jun 2018 15:57:10 -0400 Subject: [PATCH 0448/1594] Prebid 1.14.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 466e9bb1fc4..42a0be0c8a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.14.0-pre", + "version": "1.14.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 1646c0bb5dc86202d091c8675e47c8d739034633 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 6 Jun 2018 16:08:31 -0400 Subject: [PATCH 0449/1594] increment prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 42a0be0c8a2..f2628096af7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.14.0", + "version": "1.15.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 322ebfeeecc9dc22b364f1e215f61dc9a259ff8b Mon Sep 17 00:00:00 2001 From: Mikhail Necheporenko Date: Thu, 7 Jun 2018 20:51:10 +0300 Subject: [PATCH 0450/1594] Refactoring Prebid Analytics by Roxot (#2688) * Refactoring Prebid Analytics by Roxot * remove adaptermanager from analytics adapter tests --- modules/roxotAnalyticsAdapter.js | 568 +++++++++++++----- .../modules/roxotAnalyticsAdapter_spec.js | 431 ++++++++++++- .../modules/rubiconAnalyticsAdapter_spec.js | 1 - 3 files changed, 811 insertions(+), 189 deletions(-) diff --git a/modules/roxotAnalyticsAdapter.js b/modules/roxotAnalyticsAdapter.js index 65771ad245d..31239776982 100644 --- a/modules/roxotAnalyticsAdapter.js +++ b/modules/roxotAnalyticsAdapter.js @@ -2,233 +2,365 @@ import adapter from 'src/AnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import adaptermanager from 'src/adaptermanager'; import includes from 'core-js/library/fn/array/includes'; +import {ajaxBuilder} from 'src/ajax'; const utils = require('src/utils'); +let ajax = ajaxBuilder(0); -const url = '//pa.rxthdr.com/analytic'; +const DEFAULT_EVENT_URL = 'pa.rxthdr.com/v3'; +const DEFAULT_SERVER_CONFIG_URL = 'pa.rxthdr.com/v3'; const analyticsType = 'endpoint'; -let auctionInitConst = CONSTANTS.EVENTS.AUCTION_INIT; -let auctionEndConst = CONSTANTS.EVENTS.AUCTION_END; -let bidWonConst = CONSTANTS.EVENTS.BID_WON; -let bidRequestConst = CONSTANTS.EVENTS.BID_REQUESTED; -let bidAdjustmentConst = CONSTANTS.EVENTS.BID_ADJUSTMENT; -let bidResponseConst = CONSTANTS.EVENTS.BID_RESPONSE; +const { + EVENTS: { + AUCTION_INIT, + AUCTION_END, + BID_REQUESTED, + BID_ADJUSTMENT, + BIDDER_DONE, + BID_WON + } +} = CONSTANTS; -let initOptions = { publisherIds: [], utmTagData: [], adUnits: [] }; -let bidWon = {options: {}, events: []}; -let eventStack = {options: {}, events: []}; +const AUCTION_STATUS = { + 'RUNNING': 'running', + 'FINISHED': 'finished' +}; +const BIDDER_STATUS = { + 'REQUESTED': 'requested', + 'BID': 'bid', + 'NO_BID': 'noBid', + 'TIMEOUT': 'timeout' +}; +const ROXOT_EVENTS = { + 'AUCTION': 'a', + 'IMPRESSION': 'i', + 'BID_AFTER_TIMEOUT': 'bat' +}; -let auctionStatus = 'not_started'; +let initOptions = {}; let localStoragePrefix = 'roxot_analytics_'; + let utmTags = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']; -let utmTimeoutKey = 'utm_timeout'; -let utmTimeout = 60 * 60 * 1000; -let sessionTimeout = 60 * 60 * 1000; -let sessionIdStorageKey = 'session_id'; -let sessionTimeoutKey = 'session_timeout'; - -function getParameterByName(param) { - let vars = {}; - window.location.href.replace(location.hash, '').replace( - /[?&]+([^=&]+)=?([^&]*)?/gi, - function(m, key, value) { - vars[key] = value !== undefined ? value : ''; - } - ); +let utmTtlKey = 'utm_ttl'; +let utmTtl = 60 * 60 * 1000; - return vars[param] ? vars[param] : ''; -} +let isNewKey = 'is_new_flag'; +let isNewTtl = 60 * 60 * 1000; -function buildSessionIdLocalStorageKey() { - return localStoragePrefix.concat(sessionIdStorageKey); -} +let auctionCache = {}; +let auctionTtl = 60 * 60 * 1000; -function buildSessionIdTimeoutLocalStorageKey() { - return localStoragePrefix.concat(sessionTimeoutKey); -} +let sendEventCache = []; +let sendEventTimeoutId = null; +let sendEventTimeoutTime = 1000; -function updateSessionId() { - if (isSessionIdTimeoutExpired()) { - let newSessionId = utils.generateUUID(); - localStorage.setItem(buildSessionIdLocalStorageKey(), newSessionId); +function detectDevice() { + if ((/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(navigator.userAgent.toLowerCase()))) { + return 'tablet'; + } + if ((/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(navigator.userAgent.toLowerCase()))) { + return 'mobile'; } - initOptions.sessionId = getSessionId(); - updateSessionIdTimeout(); + return 'desktop'; +} + +function checkIsNewFlag() { + let key = buildLocalStorageKey(isNewKey); + let lastUpdate = Number(localStorage.getItem(key)); + localStorage.setItem(key, Date.now()); + return Date.now() - lastUpdate > isNewTtl; } -function updateSessionIdTimeout() { - localStorage.setItem(buildSessionIdTimeoutLocalStorageKey(), Date.now()); +function updateUtmTimeout() { + localStorage.setItem(buildLocalStorageKey(utmTtlKey), Date.now()); } -function isSessionIdTimeoutExpired() { - let cpmSessionTimestamp = localStorage.getItem(buildSessionIdTimeoutLocalStorageKey()); - return Date.now() - cpmSessionTimestamp > sessionTimeout; +function isUtmTimeoutExpired() { + let utmTimestamp = localStorage.getItem(buildLocalStorageKey(utmTtlKey)); + return (Date.now() - utmTimestamp) > utmTtl; } -function getSessionId() { - return localStorage.getItem(buildSessionIdLocalStorageKey()) ? localStorage.getItem(buildSessionIdLocalStorageKey()) : ''; +function buildLocalStorageKey(key) { + return localStoragePrefix.concat(key); } -function updateUtmTimeout() { - localStorage.setItem(buildUtmLocalStorageTimeoutKey(), Date.now()); +function isSupportedAdUnit(adUnit) { + if (!initOptions.adUnits.length) { + return true; + } + + return includes(initOptions.adUnits, adUnit); } -function isUtmTimeoutExpired() { - let utmTimestamp = localStorage.getItem(buildUtmLocalStorageTimeoutKey()); - return (Date.now() - utmTimestamp) > utmTimeout; +function deleteOldAuctions() { + for (let auctionId in auctionCache) { + let auction = auctionCache[auctionId]; + if (Date.now() - auction.start > auctionTtl) { + delete auctionCache[auctionId]; + } + } } -function buildUtmLocalStorageTimeoutKey() { - return localStoragePrefix.concat(utmTimeoutKey); +function buildAuctionEntity(args) { + return { + 'id': args.auctionId, + 'start': args.timestamp, + 'timeout': args.timeout, + 'adUnits': {} + }; } -function buildUtmLocalStorageKey(utmMarkKey) { - return localStoragePrefix.concat(utmMarkKey); +function extractAdUnitCode(args) { + return args.adUnitCode.toLowerCase(); } -function checkOptions() { - if (typeof initOptions.publisherIds === 'undefined') { - return false; - } +function extractBidder(args) { + return args.bidder.toLowerCase(); +} - return initOptions.publisherIds.length > 0; +function buildAdUnitAuctionEntity(auction, bidRequest) { + return { + 'adUnit': extractAdUnitCode(bidRequest), + 'start': auction.start, + 'timeout': auction.timeout, + 'finish': 0, + 'status': AUCTION_STATUS.RUNNING, + 'bidders': {} + }; } -function checkAdUnitConfig() { - if (typeof initOptions.adUnits === 'undefined') { - return false; - } +function buildBidderRequest(auction, bidRequest) { + return { + 'bidder': extractBidder(bidRequest), + 'isAfterTimeout': auction.status === AUCTION_STATUS.FINISHED ? 1 : 0, + 'start': bidRequest.startTime || Date.now(), + 'finish': 0, + 'status': BIDDER_STATUS.REQUESTED, + 'cpm': -1, + 'size': { + 'width': 0, + 'height': 0 + }, + 'mediaType': '-', + 'source': bidRequest.source || 'client' + }; +} - return initOptions.adUnits.length > 0; +function buildBidAfterTimeout(adUnitAuction, args) { + return { + 'auction': utils.deepClone(adUnitAuction), + 'adUnit': extractAdUnitCode(args), + 'bidder': extractBidder(args), + 'cpm': args.cpm, + 'size': { + 'width': args.width || 0, + 'height': args.height || 0 + }, + 'mediaType': args.mediaType || '-', + 'start': args.requestTimestamp, + 'finish': args.responseTimestamp, + }; } -function buildBidWon(eventType, args) { - bidWon.options = initOptions; - if (checkAdUnitConfig()) { - if (includes(initOptions.adUnits, args.adUnitCode)) { - bidWon.events = [{ args: args, eventType: eventType }]; - } - } else { - bidWon.events = [{ args: args, eventType: eventType }]; - } +function buildImpression(adUnitAuction, args) { + return { + 'isNew': checkIsNewFlag() ? 1 : 0, + 'auction': utils.deepClone(adUnitAuction), + 'adUnit': extractAdUnitCode(args), + 'bidder': extractBidder(args), + 'cpm': args.cpm, + 'size': { + 'width': args.width, + 'height': args.height + }, + 'mediaType': args.mediaType, + 'source': args.source || 'client' + }; } -function buildEventStack() { - eventStack.options = initOptions; +function handleAuctionInit(args) { + auctionCache[args.auctionId] = buildAuctionEntity(args); + deleteOldAuctions(); } -function filterBidsByAdUnit(bids) { - var filteredBids = []; - bids.forEach(function (bid) { - if (includes(initOptions.adUnits, bid.placementCode)) { - filteredBids.push(bid); +function handleBidRequested(args) { + let auction = auctionCache[args.auctionId]; + args.bids.forEach(function (bidRequest) { + let adUnitCode = extractAdUnitCode(bidRequest); + let bidder = extractBidder(bidRequest); + if (!isSupportedAdUnit(adUnitCode)) { + return; } + auction['adUnits'][adUnitCode] = auction['adUnits'][adUnitCode] || buildAdUnitAuctionEntity(auction, bidRequest); + let adUnitAuction = auction['adUnits'][adUnitCode]; + adUnitAuction['bidders'][bidder] = adUnitAuction['bidders'][bidder] || buildBidderRequest(auction, bidRequest); }); - return filteredBids; } -function isValidEvent(eventType, adUnitCode) { - if (checkAdUnitConfig()) { - let validationEvents = [bidAdjustmentConst, bidResponseConst, bidWonConst]; - if (!includes(initOptions.adUnits, adUnitCode) && includes(validationEvents, eventType)) { - return false; - } +function handleBidAdjustment(args) { + let adUnitCode = extractAdUnitCode(args); + let bidder = extractBidder(args); + if (!isSupportedAdUnit(adUnitCode)) { + return; } - return true; -} -function isValidEventStack() { - if (eventStack.events.length > 0) { - return eventStack.events.some(function(event) { - return bidRequestConst === event.eventType || bidWonConst === event.eventType; - }); + let adUnitAuction = auctionCache[args.auctionId]['adUnits'][adUnitCode]; + if (adUnitAuction.status === AUCTION_STATUS.FINISHED) { + handleBidAfterTimeout(adUnitAuction, args); + return; } - return false; -} -function isValidBidWon() { - return bidWon.events.length > 0; + let bidderRequest = adUnitAuction['bidders'][bidder]; + if (bidderRequest.cpm < args.cpm) { + bidderRequest.cpm = args.cpm; + bidderRequest.finish = args.responseTimestamp; + bidderRequest.status = args.cpm === 0 ? BIDDER_STATUS.NO_BID : BIDDER_STATUS.BID; + bidderRequest.size.width = args.width || 0; + bidderRequest.size.height = args.height || 0; + bidderRequest.mediaType = args.mediaType || '-'; + bidderRequest.source = args.source || 'client'; + } } -function flushEventStack() { - eventStack.events = []; +function handleBidAfterTimeout(adUnitAuction, args) { + let bidder = extractBidder(args); + let bidderRequest = adUnitAuction['bidders'][bidder]; + let bidAfterTimeout = buildBidAfterTimeout(adUnitAuction, args); + + if (bidAfterTimeout.cpm > bidderRequest.cpm) { + bidderRequest.cpm = bidAfterTimeout.cpm; + bidderRequest.isAfterTimeout = 1; + bidderRequest.finish = bidAfterTimeout.finish; + bidderRequest.size = bidAfterTimeout.size; + bidderRequest.mediaType = bidAfterTimeout.mediaType; + bidderRequest.status = bidAfterTimeout.cpm === 0 ? BIDDER_STATUS.NO_BID : BIDDER_STATUS.BID; + } + + registerEvent(ROXOT_EVENTS.BID_AFTER_TIMEOUT, 'Bid After Timeout', bidAfterTimeout); } -function flushBidWon() { - bidWon.events = []; +function handleBidderDone(args) { + let auction = auctionCache[args.auctionId]; + + args.bids.forEach(function (bidDone) { + let adUnitCode = extractAdUnitCode(bidDone); + let bidder = extractBidder(bidDone); + if (!isSupportedAdUnit(adUnitCode)) { + return; + } + + let adUnitAuction = auction['adUnits'][adUnitCode]; + if (adUnitAuction.status === AUCTION_STATUS.FINISHED) { + return; + } + let bidderRequest = adUnitAuction['bidders'][bidder]; + if (bidderRequest.status !== BIDDER_STATUS.REQUESTED) { + return; + } + + bidderRequest.finish = Date.now(); + bidderRequest.status = BIDDER_STATUS.NO_BID; + bidderRequest.cpm = 0; + }); } -let roxotAdapter = Object.assign(adapter({url, analyticsType}), - { - track({eventType, args}) { - if (!checkOptions()) { - return; +function handleAuctionEnd(args) { + let auction = auctionCache[args.auctionId]; + if (!Object.keys(auction.adUnits).length) { + delete auctionCache[args.auctionId]; + } + + let finish = Date.now(); + auction.finish = finish; + for (let adUnit in auction.adUnits) { + let adUnitAuction = auction.adUnits[adUnit]; + adUnitAuction.finish = finish; + adUnitAuction.status = AUCTION_STATUS.FINISHED; + + for (let bidder in adUnitAuction.bidders) { + let bidderRequest = adUnitAuction.bidders[bidder]; + if (bidderRequest.status !== BIDDER_STATUS.REQUESTED) { + continue; } - let info = Object.assign({}, args); + bidderRequest.status = BIDDER_STATUS.TIMEOUT; + } + } - if (info && info.ad) { - info.ad = ''; - } + registerEvent(ROXOT_EVENTS.AUCTION, 'Auction', auction); +} - if (eventType === auctionInitConst) { - auctionStatus = 'started'; - flushEventStack(); - } +function handleBidWon(args) { + let adUnitCode = extractAdUnitCode(args); + if (!isSupportedAdUnit(adUnitCode)) { + return; + } + let adUnitAuction = auctionCache[args.auctionId]['adUnits'][adUnitCode]; + let impression = buildImpression(adUnitAuction, args); + registerEvent(ROXOT_EVENTS.IMPRESSION, 'Bid won', impression); +} - if (eventType === bidWonConst && auctionStatus === 'not_started') { - updateSessionId(); - buildBidWon(eventType, info); - if (isValidBidWon()) { - send(eventType, bidWon, 'bidWon'); - } - flushBidWon(); - return; - } +function handleOtherEvents(eventType, args) { + registerEvent(eventType, eventType, args); +} - if (eventType === auctionEndConst) { - updateSessionId(); - buildEventStack(eventType); - if (isValidEventStack()) { - send(eventType, eventStack, 'eventStack'); - } - flushEventStack(); - auctionStatus = 'not_started'; - } else { - pushEvent(eventType, info); - } - }, +let roxotAdapter = Object.assign(adapter({url: DEFAULT_EVENT_URL, analyticsType}), { + track({eventType, args}) { + switch (eventType) { + case AUCTION_INIT: + handleAuctionInit(args); + break; + case BID_REQUESTED: + handleBidRequested(args); + break; + case BID_ADJUSTMENT: + handleBidAdjustment(args); + break; + case BIDDER_DONE: + handleBidderDone(args); + break; + case AUCTION_END: + handleAuctionEnd(args); + break; + case BID_WON: + handleBidWon(args); + break; + default: + handleOtherEvents(eventType, args); + break; + } + }, - }); +}); roxotAdapter.originEnableAnalytics = roxotAdapter.enableAnalytics; roxotAdapter.enableAnalytics = function (config) { - initOptions = config.options; - initOptions.utmTagData = this.buildUtmTagData(); - utils.logInfo('Roxot Analytics enabled with config', initOptions); - roxotAdapter.originEnableAnalytics(config); + if (this.initConfig(config)) { + logInfo('Analytics adapter enabled', initOptions); + roxotAdapter.originEnableAnalytics(config); + } }; roxotAdapter.buildUtmTagData = function () { let utmTagData = {}; let utmTagsDetected = false; - utmTags.forEach(function(utmTagKey) { - let utmTagValue = getParameterByName(utmTagKey); + utmTags.forEach(function (utmTagKey) { + let utmTagValue = utils.getParameterByName(utmTagKey); if (utmTagValue !== '') { utmTagsDetected = true; } utmTagData[utmTagKey] = utmTagValue; }); - utmTags.forEach(function(utmTagKey) { + utmTags.forEach(function (utmTagKey) { if (utmTagsDetected) { - localStorage.setItem(buildUtmLocalStorageKey(utmTagKey), utmTagData[utmTagKey]); + localStorage.setItem(buildLocalStorageKey(utmTagKey), utmTagData[utmTagKey]); updateUtmTimeout(); } else { if (!isUtmTimeoutExpired()) { - utmTagData[utmTagKey] = localStorage.getItem(buildUtmLocalStorageKey(utmTagKey)) ? localStorage.getItem(buildUtmLocalStorageKey(utmTagKey)) : ''; + utmTagData[utmTagKey] = localStorage.getItem(buildLocalStorageKey(utmTagKey)) ? localStorage.getItem(buildLocalStorageKey(utmTagKey)) : ''; updateUtmTimeout(); } } @@ -236,33 +368,135 @@ roxotAdapter.buildUtmTagData = function () { return utmTagData; }; -function send(eventType, data, sendDataType) { - let fullUrl = url + '?publisherIds[]=' + initOptions.publisherIds.join('&publisherIds[]=') + '&host=' + window.location.hostname; - let xhr = new XMLHttpRequest(); - xhr.open('POST', fullUrl, true); - xhr.setRequestHeader('Content-Type', 'text/plain'); - xhr.withCredentials = true; - xhr.onreadystatechange = function(result) { - if (this.readyState != 4) return; +roxotAdapter.initConfig = function (config) { + let isCorrectConfig = true; + initOptions = {}; + initOptions.options = utils.deepClone(config.options); - utils.logInfo('Event ' + eventType + ' sent ' + sendDataType + ' to roxot prebid analytic with result' + result); + initOptions.publisherId = initOptions.options.publisherId || (initOptions.options.publisherIds[0]) || null; + if (!initOptions.publisherId) { + logError('"options.publisherId" is empty'); + isCorrectConfig = false; } - xhr.send(JSON.stringify(data)); + + initOptions.adUnits = initOptions.options.adUnits || []; + initOptions.adUnits = initOptions.adUnits.map(value => value.toLowerCase()); + initOptions.server = initOptions.options.server || DEFAULT_EVENT_URL; + initOptions.configServer = initOptions.options.configServer || (initOptions.options.server || DEFAULT_SERVER_CONFIG_URL); + initOptions.utmTagData = this.buildUtmTagData(); + initOptions.host = initOptions.options.host || window.location.hostname; + initOptions.device = detectDevice(); + + loadServerConfig(); + return isCorrectConfig; +}; + +roxotAdapter.getOptions = function () { + return initOptions; }; -function pushEvent(eventType, args) { - if (eventType === bidRequestConst) { - if (checkAdUnitConfig()) { - args.bids = filterBidsByAdUnit(args.bids); +function registerEvent(eventType, eventName, data) { + let eventData = { + eventType: eventType, + eventName: eventName, + data: data + }; + + sendEventCache.push(eventData); + + logInfo('Register event', eventData); + + (typeof initOptions.serverConfig === 'undefined') ? checkEventAfterTimeout() : checkSendEvent(); +} + +function checkSendEvent() { + if (sendEventTimeoutId) { + clearTimeout(sendEventTimeoutId); + sendEventTimeoutId = null; + } + + if (typeof initOptions.serverConfig === 'undefined') { + checkEventAfterTimeout(); + return; + } + + while (sendEventCache.length) { + let event = sendEventCache.shift(); + let isNeedSend = initOptions.serverConfig[event.eventType] || 0; + if (Number(isNeedSend) === 0) { + logInfo('Skip event ' + event.eventName, event); + continue; } - if (args.bids.length > 0) { - eventStack.events.push({ eventType: eventType, args: args }); + sendEvent(event.eventType, event.eventName, event.data); + } +} + +function checkEventAfterTimeout() { + if (sendEventTimeoutId) { + return; + } + + sendEventTimeoutId = setTimeout(checkSendEvent, sendEventTimeoutTime); +} + +function sendEvent(eventType, eventName, data) { + let url = '//' + initOptions.server + '/' + eventType + '?publisherId=' + initOptions.publisherId + '&host=' + initOptions.host; + let eventData = { + 'event': eventType, + 'eventName': eventName, + 'options': initOptions, + 'data': data + }; + + ajax( + url, + function () { + logInfo(eventName + ' sent', eventData); + }, + JSON.stringify(eventData), + { + contentType: 'text/plain', + method: 'POST', + withCredentials: true } - } else { - if (isValidEvent(eventType, args.adUnitCode)) { - eventStack.events.push({ eventType: eventType, args: args }); + ); +} + +function loadServerConfig() { + let url = '//' + initOptions.configServer + '/c' + '?publisherId=' + initOptions.publisherId + '&host=' + initOptions.host; + ajax( + url, + { + 'success': function (data) { + initOptions.serverConfig = JSON.parse(data); + }, + 'error': function () { + initOptions.serverConfig = {}; + initOptions.serverConfig[ROXOT_EVENTS.AUCTION] = 1; + initOptions.serverConfig[ROXOT_EVENTS.IMPRESSION] = 1; + initOptions.serverConfig[ROXOT_EVENTS.BID_AFTER_TIMEOUT] = 1; + initOptions.serverConfig['isError'] = 1; + } + }, + null, + { + contentType: 'text/json', + method: 'GET', + withCredentials: true } - } + ); +} + +function logInfo(message, meta) { + utils.logInfo(buildLogMessage(message), meta); +} + +function logError(message) { + utils.logError(buildLogMessage(message)); +} + +function buildLogMessage(message) { + return 'Roxot Prebid Analytics: ' + message; } adaptermanager.registerAnalyticsAdapter({ diff --git a/test/spec/modules/roxotAnalyticsAdapter_spec.js b/test/spec/modules/roxotAnalyticsAdapter_spec.js index f2db77892f6..9a80d2d0597 100644 --- a/test/spec/modules/roxotAnalyticsAdapter_spec.js +++ b/test/spec/modules/roxotAnalyticsAdapter_spec.js @@ -1,51 +1,432 @@ import roxotAnalytic from 'modules/roxotAnalyticsAdapter'; -import { expect } from 'chai'; +import {expect} from 'chai'; + let events = require('src/events'); -let adaptermanager = require('src/adaptermanager'); let constants = require('src/constants.json'); describe('Roxot Prebid Analytic', function () { let xhr; + let requests; + + let roxotConfigServerUrl = 'config-server'; + let roxotEventServerUrl = 'event-server'; + let publisherId = 'test_roxot_prebid_analytics_publisher_id'; + + let auctionId = '0ea14159-2058-4b87-a966-9d7652176a56'; + let timeout = 3000; + let auctionStartTimestamp = Date.now(); + let bidder = 'rubicon'; + + let bidAdUnit = 'div_with_bid'; + let noBidAdUnit = 'div_no_bid'; + let bidAfterTimeoutAdUnit = 'div_after_timeout'; + + let auctionInit = { + timestamp: auctionStartTimestamp, + auctionId: auctionId, + timeout: timeout + }; + + let bidRequested = { + auctionId: auctionId, + auctionStart: auctionStartTimestamp, + bidderCode: bidder, + bidderRequestId: '10340af0c7dc72', + bids: [ + { + adUnitCode: bidAdUnit, + auctionId: auctionId, + bidId: '298bf14ecbafb', + bidder: bidder, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 50, + transactionId: '7aafa3ee-a80a-46d7-a4a0-cbcba463d97a' + }, + { + adUnitCode: bidAfterTimeoutAdUnit, + auctionId: auctionId, + bidId: '36c6375e2dceba', + bidder: bidder, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 70, + transactionId: 'cf627df3-5828-4d3e-9dd0-c1733d328142' + }, + { + adUnitCode: noBidAdUnit, + auctionId: auctionId, + bidId: '36c6375e2dce21', + bidder: bidder, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 90, + transactionId: 'cf627df3-5828-4d3e-9dd0-c1737aafa3ee' + } + ], + doneCbCallCount: 1, + start: auctionStartTimestamp, + timeout: timeout + }; + + let bidAdjustmentWithBid = { + ad: 'html', + adId: '298bf14ecbafb', + adUnitCode: bidAdUnit, + auctionId: auctionId, + bidder: bidder, + bidderCode: bidder, + cpm: 1.01, + creativeId: '2249:92806132', + currency: 'USD', + height: 250, + mediaType: 'banner', + requestId: '298bf14ecbafb', + requestTimestamp: auctionStartTimestamp + 50, + responseTimestamp: auctionStartTimestamp + 50 + 421, + size: '300x250', + source: 'client', + status: 'rendered', + statusMessage: 'Bid available', + timeToRespond: 421, + ttl: 300, + width: 300 + }; + + let bidAdjustmentAfterTimeout = { + ad: 'html', + adId: '36c6375e2dceba', + adUnitCode: bidAfterTimeoutAdUnit, + auctionId: auctionId, + bidder: bidder, + bidderCode: bidder, + cpm: 2.02, + creativeId: '2249:92806132', + currency: 'USD', + height: 250, + mediaType: 'banner', + requestId: '36c6375e2dceba', + requestTimestamp: auctionStartTimestamp + 70, + responseTimestamp: auctionStartTimestamp + 70 + 6141, + size: '300x250', + source: 'client', + status: 'rendered', + statusMessage: 'Bid available', + timeToRespond: 6141, + ttl: 300, + width: 300 + }; + + let bidAdjustmentNoBid = { + ad: 'html', + adId: '36c6375e2dce21', + adUnitCode: noBidAdUnit, + auctionId: auctionId, + bidder: bidder, + bidderCode: bidder, + cpm: 0, + creativeId: '2249:92806132', + currency: 'USD', + height: 0, + mediaType: 'banner', + requestId: '36c6375e2dce21', + requestTimestamp: auctionStartTimestamp + 90, + responseTimestamp: auctionStartTimestamp + 90 + 215, + size: '300x250', + source: 'client', + status: 'rendered', + statusMessage: 'Bid available', + timeToRespond: 215, + ttl: 300, + width: 0 + }; + + let auctionEnd = { + auctionId: auctionId + }; + + let bidTimeout = [ + { + adUnitCode: bidAfterTimeoutAdUnit, + auctionId: auctionId, + bidId: '389444beed7361', + bidder: bidder, + timeout: timeout + } + ]; + + let bidResponseWithBid = bidAdjustmentWithBid; + let bidResponseAfterTimeout = bidAdjustmentAfterTimeout; + let bidResponseNoBid = bidAdjustmentNoBid; + let bidderDone = bidRequested; + let bidWon = bidAdjustmentWithBid; + before(() => { xhr = sinon.useFakeXMLHttpRequest(); - }) + xhr.onCreate = request => requests.push(request); + }); after(() => { - roxotAnalytic.disableAnalytics(); xhr.restore(); }); - describe('enableAnalytics', function () { + describe('correct build and send events', function () { beforeEach(() => { - sinon.spy(roxotAnalytic, 'track'); + requests = []; sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { - roxotAnalytic.track.restore(); + roxotAnalytic.disableAnalytics(); events.getEvents.restore(); }); - it('should catch all events', function () { - adaptermanager.registerAnalyticsAdapter({ - code: 'roxot', - adapter: roxotAnalytic + it('should send prepared events to backend', function () { + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: { + publisherId: publisherId, + configServer: roxotConfigServerUrl, + server: roxotEventServerUrl + } }); - adaptermanager.enableAnalytics({ + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal('//' + roxotConfigServerUrl + '/c?publisherId=' + publisherId + '&host=localhost'); + requests[0].respond(200, {'Content-Type': 'application/json'}, '{"a": 1, "i": 1, "bat": 1}'); + + events.emit(constants.EVENTS.AUCTION_INIT, auctionInit); + events.emit(constants.EVENTS.BID_REQUESTED, bidRequested); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentWithBid); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseWithBid); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentNoBid); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseNoBid); + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeout); + events.emit(constants.EVENTS.AUCTION_END, auctionEnd); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentAfterTimeout); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseAfterTimeout); + events.emit(constants.EVENTS.BIDDER_DONE, bidderDone); + events.emit(constants.EVENTS.BID_WON, bidWon); + + expect(requests.length).to.equal(4); + + expect(requests[1].url).to.equal('//' + roxotEventServerUrl + '/a?publisherId=' + publisherId + '&host=localhost'); + expect(requests[2].url).to.equal('//' + roxotEventServerUrl + '/bat?publisherId=' + publisherId + '&host=localhost'); + expect(requests[3].url).to.equal('//' + roxotEventServerUrl + '/i?publisherId=' + publisherId + '&host=localhost'); + + let auction = JSON.parse(requests[1].requestBody); + expect(auction).to.include.all.keys('event', 'eventName', 'options', 'data'); + expect(auction.event).to.equal('a'); + + expect(auction.data).to.include.all.keys('id', 'start', 'finish', 'timeout', 'adUnits'); + expect(auction.data.id).to.equal(auctionId); + expect(auction.data.timeout).to.equal(timeout); + + expect(auction.data.adUnits).to.include.all.keys(bidAdUnit, bidAfterTimeoutAdUnit, noBidAdUnit); + expect(auction.data.adUnits[bidAdUnit].bidders).to.have.property(bidder); + expect(auction.data.adUnits[bidAfterTimeoutAdUnit].bidders).to.have.property(bidder); + expect(auction.data.adUnits[noBidAdUnit].bidders).to.have.property(bidder); + + expect(auction.data.adUnits[bidAdUnit].bidders[bidder].status).to.equal('bid'); + expect(auction.data.adUnits[bidAfterTimeoutAdUnit].bidders[bidder].status).to.equal('timeout'); + expect(auction.data.adUnits[noBidAdUnit].bidders[bidder].status).to.equal('noBid'); + + let bidAfterTimeout = JSON.parse(requests[2].requestBody); + expect(bidAfterTimeout).to.include.all.keys('event', 'eventName', 'options', 'data'); + expect(bidAfterTimeout.event).to.equal('bat'); + + expect(bidAfterTimeout.data).to.include.all.keys('start', 'finish', 'mediaType', 'adUnit', 'bidder', 'cpm', 'size', 'auction'); + expect(bidAfterTimeout.data.adUnit).to.equal(bidAfterTimeoutAdUnit); + expect(bidAfterTimeout.data.bidder).to.equal(bidder); + expect(bidAfterTimeout.data.cpm).to.equal(bidAdjustmentAfterTimeout.cpm); + + let impression = JSON.parse(requests[3].requestBody); + expect(impression).to.include.all.keys('event', 'eventName', 'options', 'data'); + expect(impression.event).to.equal('i'); + + expect(impression.data).to.include.all.keys('mediaType', 'adUnit', 'bidder', 'cpm', 'size', 'auction', 'isNew'); + expect(impression.data.adUnit).to.equal(bidAdUnit); + expect(impression.data.bidder).to.equal(bidder); + expect(impression.data.cpm).to.equal(bidAdjustmentWithBid.cpm); + }); + }); + + describe('support ad unit filter', function () { + beforeEach(() => { + requests = []; + sinon.stub(events, 'getEvents').returns([]); + }); + afterEach(() => { + roxotAnalytic.disableAnalytics(); + events.getEvents.restore(); + }); + it('should not send event for blocked ad unit', function () { + roxotAnalytic.enableAnalytics({ provider: 'roxot', options: { - publisherIds: ['test_roxot_prebid_analytid_publisher_id'] + publisherId: publisherId, + configServer: roxotConfigServerUrl, + server: roxotEventServerUrl, + adUnits: [noBidAdUnit, bidAfterTimeoutAdUnit] } }); - events.emit(constants.EVENTS.AUCTION_INIT, {}); - events.emit(constants.EVENTS.AUCTION_END, {}); - events.emit(constants.EVENTS.BID_REQUESTED, {}); - events.emit(constants.EVENTS.BID_RESPONSE, {}); - events.emit(constants.EVENTS.BID_WON, {}); + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal('//' + roxotConfigServerUrl + '/c?publisherId=' + publisherId + '&host=localhost'); + requests[0].respond(200, {'Content-Type': 'application/json'}, '{"a": 1, "i": 1, "bat": 1}'); + + events.emit(constants.EVENTS.AUCTION_INIT, auctionInit); + events.emit(constants.EVENTS.BID_REQUESTED, bidRequested); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentWithBid); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseWithBid); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentNoBid); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseNoBid); + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeout); + events.emit(constants.EVENTS.AUCTION_END, auctionEnd); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentAfterTimeout); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseAfterTimeout); + events.emit(constants.EVENTS.BIDDER_DONE, bidderDone); + events.emit(constants.EVENTS.BID_WON, bidWon); + + expect(requests.length).to.equal(3); + + expect(requests[1].url).to.equal('//' + roxotEventServerUrl + '/a?publisherId=' + publisherId + '&host=localhost'); + expect(requests[2].url).to.equal('//' + roxotEventServerUrl + '/bat?publisherId=' + publisherId + '&host=localhost'); + + let auction = JSON.parse(requests[1].requestBody); + expect(auction.data.adUnits).to.include.all.keys(noBidAdUnit, bidAfterTimeoutAdUnit); + expect(auction.data.adUnits).to.not.include.all.keys(bidAdUnit); + }); + }); + + describe('should correct parse config', function () { + beforeEach(() => { + requests = []; + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(() => { + roxotAnalytic.disableAnalytics(); + events.getEvents.restore(); + }); + + it('correct parse publisher config', function () { + let publisherOptions = { + publisherId: publisherId, + configServer: roxotConfigServerUrl, + server: roxotEventServerUrl, + anything: 'else', + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().options).to.deep.equal(publisherOptions); + }); + + it('support deprecated options', function () { + let publisherOptions = { + publisherIds: [publisherId], + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().options).to.deep.equal(publisherOptions); + expect(roxotAnalytic.getOptions().publisherId).to.equal(publisherId); + }); + + it('support default end-points', function () { + let publisherOptions = { + publisherId: publisherId, + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().configServer).to.equal('pa.rxthdr.com/v3'); + expect(roxotAnalytic.getOptions().server).to.equal('pa.rxthdr.com/v3'); + }); + + it('support custom config end-point', function () { + let publisherOptions = { + publisherId: publisherId, + configServer: roxotConfigServerUrl + }; - sinon.assert.callCount(roxotAnalytic.track, 5); + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().configServer).to.equal(roxotConfigServerUrl); + expect(roxotAnalytic.getOptions().server).to.equal('pa.rxthdr.com/v3'); + }); + + it('support custom config and event end-point', function () { + let publisherOptions = { + publisherId: publisherId, + server: roxotEventServerUrl + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().configServer).to.equal(roxotEventServerUrl); + expect(roxotAnalytic.getOptions().server).to.equal(roxotEventServerUrl); + }); + + it('support different config and event end-points', function () { + let publisherOptions = { + publisherId: publisherId, + configServer: roxotConfigServerUrl, + server: roxotEventServerUrl + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().configServer).to.equal(roxotConfigServerUrl); + expect(roxotAnalytic.getOptions().server).to.equal(roxotEventServerUrl); + }); + + it('support adUnit filter', function () { + let publisherOptions = { + publisherId: publisherId, + adUnits: ['div1', 'div2'] + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().adUnits).to.deep.equal(['div1', 'div2']); + }); + + it('support fail loading server config', function () { + let publisherOptions = { + publisherId: publisherId + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + requests[0].respond(500); + + expect(roxotAnalytic.getOptions().serverConfig).to.deep.equal({a: 1, i: 1, bat: 1, isError: 1}); }); }); + describe('build utm tag data', () => { beforeEach(() => { localStorage.setItem('roxot_analytics_utm_source', 'utm_source'); @@ -53,7 +434,15 @@ describe('Roxot Prebid Analytic', function () { localStorage.setItem('roxot_analytics_utm_campaign', ''); localStorage.setItem('roxot_analytics_utm_term', ''); localStorage.setItem('roxot_analytics_utm_content', ''); - localStorage.setItem('roxot_analytics_utm_timeout', Date.now()); + localStorage.setItem('roxot_analytics_utm_ttl', Date.now()); + }); + afterEach(() => { + localStorage.removeItem('roxot_analytics_utm_source'); + localStorage.removeItem('roxot_analytics_utm_medium'); + localStorage.removeItem('roxot_analytics_utm_campaign'); + localStorage.removeItem('roxot_analytics_utm_term'); + localStorage.removeItem('roxot_analytics_utm_content'); + localStorage.removeItem('roxot_analytics_utm_ttl'); }); it('should build utm data from local storage', () => { let utmTagData = roxotAnalytic.buildUtmTagData(); diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 21ed1cfa522..3af82a1fb62 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -1,4 +1,3 @@ -import adaptermanager from 'src/adaptermanager'; import rubiconAnalyticsAdapter, { SEND_TIMEOUT } from 'modules/rubiconAnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import { config } from 'src/config'; From f7f07079ca5def12c85460630e7c0937924796ad Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Fri, 8 Jun 2018 03:30:28 +0800 Subject: [PATCH 0451/1594] Fix getTopWindowUrl (#2673) * Fix getTopWindowUrl getTopWindowUrl error, it should be exports.function not this.function * Update utils.js Fix to pass FB test * Update audienceNetworkBidAdapter_spec.js * Update utils.js * Update utils.js * Update utils.js --- src/utils.js | 45 +++++++++---------- .../modules/audienceNetworkBidAdapter_spec.js | 12 ++--- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/utils.js b/src/utils.js index 5675ace6bf8..5135a1df21d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -29,7 +29,7 @@ try { * console.log(replaceTokenInString(str, map, '%%')); => "text it was subbed this text with something else" */ exports.replaceTokenInString = function (str, map, token) { - this._each(map, function (value, key) { + exports._each(map, function (value, key) { value = (value === undefined) ? '' : value; var keyString = token + key.toUpperCase() + token; @@ -242,11 +242,10 @@ exports.getWindowLocation = function () { exports.getTopWindowUrl = function () { let href; try { - href = this.getTopWindowLocation().href; + href = exports.getTopWindowLocation().href; } catch (e) { href = ''; } - return href; }; @@ -366,10 +365,10 @@ exports.hasValidBidRequest = function (paramObj, requiredParamsArr, adapter) { for (var i = 0; i < requiredParamsArr.length; i++) { found = false; - this._each(paramObj, findParam); + exports._each(paramObj, findParam); if (!found) { - this.logError('Params are missing for bid request. One of these required paramaters are missing: ' + requiredParamsArr, adapter); + exports.logError('Params are missing for bid request. One of these required paramaters are missing: ' + requiredParamsArr, adapter); return false; } } @@ -397,23 +396,23 @@ exports.isA = function (object, _t) { }; exports.isFn = function (object) { - return this.isA(object, t_Fn); + return exports.isA(object, t_Fn); }; exports.isStr = function (object) { - return this.isA(object, t_Str); + return exports.isA(object, t_Str); }; exports.isArray = function (object) { - return this.isA(object, t_Arr); + return exports.isA(object, t_Arr); }; exports.isNumber = function(object) { - return this.isA(object, t_Numb); + return exports.isA(object, t_Numb); }; exports.isPlainObject = function(object) { - return this.isA(object, t_Object); + return exports.isA(object, t_Object); } /** @@ -441,7 +440,7 @@ exports.isEmpty = function (object) { * @returns {boolean} if string is empty */ exports.isEmptyStr = function(str) { - return this.isStr(str) && (!str || str.length === 0); + return exports.isStr(str) && (!str || str.length === 0); }; /** @@ -451,8 +450,8 @@ exports.isEmptyStr = function(str) { * @param {Function(value, key, object)} fn */ exports._each = function (object, fn) { - if (this.isEmpty(object)) return; - if (this.isFn(object.forEach)) return object.forEach(fn, this); + if (exports.isEmpty(object)) return; + if (exports.isFn(object.forEach)) return object.forEach(fn, this); var k = 0; var l = object.length; @@ -467,11 +466,11 @@ exports._each = function (object, fn) { }; exports.contains = function (a, obj) { - if (this.isEmpty(a)) { + if (exports.isEmpty(a)) { return false; } - if (this.isFn(a.indexOf)) { + if (exports.isFn(a.indexOf)) { return a.indexOf(obj) !== -1; } @@ -502,10 +501,10 @@ exports.indexOf = (function () { * @return {Array} */ exports._map = function (object, callback) { - if (this.isEmpty(object)) return []; - if (this.isFn(object.map)) return object.map(callback); + if (exports.isEmpty(object)) return []; + if (exports.isFn(object.map)) return object.map(callback); var output = []; - this._each(object, function (value, key) { + exports._each(object, function (value, key) { output.push(callback(value, key, object)); }); @@ -586,7 +585,7 @@ exports.insertHtmlIntoIframe = function(htmlCode) { * @param {string} encodeUri boolean if URL should be encoded before inserted. Defaults to true */ exports.insertUserSyncIframe = function(url) { - let iframeHtml = this.createTrackPixelIframeHtml(url, false, 'allow-scripts allow-same-origin'); + let iframeHtml = exports.createTrackPixelIframeHtml(url, false, 'allow-scripts allow-same-origin'); let div = document.createElement('div'); div.innerHTML = iframeHtml; let iframe = div.firstChild; @@ -658,7 +657,7 @@ exports.getIframeDocument = function (iframe) { doc = iframe.contentDocument; } } catch (e) { - this.logError('Cannot get iframe document', e); + exports.logError('Cannot get iframe document', e); } return doc; @@ -668,13 +667,13 @@ exports.getValueString = function(param, val, defaultValue) { if (val === undefined || val === null) { return defaultValue; } - if (this.isStr(val)) { + if (exports.isStr(val)) { return val; } - if (this.isNumber(val)) { + if (exports.isNumber(val)) { return val.toString(); } - this.logWarn('Unsuported type for param: ' + param + ' required type: String'); + exports.logWarn('Unsuported type for param: ' + param + ' required type: String'); }; export function uniques(value, index, arry) { diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index f9d46e100b1..8a72b2ba658 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -139,7 +139,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&sdk[]=5.5.web&pbv=${pbv}` }]); }); @@ -158,7 +158,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['640x480'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=&sdk[]=&pbv=${pbv}&playerwidth=640&playerheight=480` + data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&sdk[]=&pbv=${pbv}&playerwidth=640&playerheight=480` }]); }); @@ -177,7 +177,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['728x90'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&sdk[]=5.5.web&pbv=${pbv}` }]); }); @@ -196,7 +196,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&sdk[]=5.5.web&pbv=${pbv}` }]); }); @@ -410,7 +410,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.cpm).to.equal(1.23); expect(bidResponse.requestId).to.equal(requestId); expect(bidResponse.mediaType).to.equal('video'); - expect(bidResponse.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${placementId}&pageurl=&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${bidId}`); + expect(bidResponse.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${placementId}&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${bidId}`); expect(bidResponse.width).to.equal(playerwidth); expect(bidResponse.height).to.equal(playerheight); }); @@ -450,7 +450,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseVideo.cpm).to.equal(1.23); expect(bidResponseVideo.requestId).to.equal(requestId); expect(bidResponseVideo.mediaType).to.equal('video'); - expect(bidResponseVideo.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${videoPlacementId}&pageurl=&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${videoBidId}`); + expect(bidResponseVideo.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${videoPlacementId}&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${videoBidId}`); expect(bidResponseVideo.width).to.equal(playerwidth); expect(bidResponseVideo.height).to.equal(playerheight); From af35a11fe2a653b2f502d730ec41b33d1bf13bf8 Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 8 Jun 2018 05:33:23 +1000 Subject: [PATCH 0452/1594] Playground XYZ - new adapter (#2606) * add playground adapters * clean up * update with upstream master * add test file clean up adapter by removing native referecnes * test file * replace appnexus with playground reference in error logs * remove commented code * change key in response object from appnexus to playgroundxyz * change tests so we test for ordering by cpm as well * dont drop other bids, just set cpm to 0 and send it through * clean up * restore glulp file * fix documentation * remove cpm logic from adapter * change application type to application\json for playground adapter * update adaptor to use openRtb * add device and site to bid * add extra space on error msg * remove package-lock * update pg details * Update playgroundxyzBidAdapter.md --- modules/playgroundxyzBidAdapter.js | 160 + modules/playgroundxyzBidAdapter.md | 72 + package-lock.json | 11615 ---------------- .../modules/playgroundxyzBidAdapter_spec.js | 136 + 4 files changed, 368 insertions(+), 11615 deletions(-) create mode 100644 modules/playgroundxyzBidAdapter.js create mode 100644 modules/playgroundxyzBidAdapter.md delete mode 100644 package-lock.json create mode 100644 test/spec/modules/playgroundxyzBidAdapter_spec.js diff --git a/modules/playgroundxyzBidAdapter.js b/modules/playgroundxyzBidAdapter.js new file mode 100644 index 00000000000..75861bd63f1 --- /dev/null +++ b/modules/playgroundxyzBidAdapter.js @@ -0,0 +1,160 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'playgroundxyz'; +const URL = 'https://ads.playground.xyz/host-config/prebid'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['playgroundxyz'], + 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 !!(bid.params.placementId); + }, + + /** + * 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) { + const topLocation = utils.getTopWindowLocation(); + const payload = JSON.stringify({ + id: bidRequests[0].auctionId, + site: { + domain: window.location.protocol + '//' + topLocation.hostname, + name: topLocation.hostname, + page: topLocation.href, + }, + device: { + ua: navigator.userAgent, + language: navigator.language, + devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, + }, + imp: bidRequests.map(mapImpression) + }); + + const options = { + contentType: 'application/json', + withCredentials: false + }; + + return { + method: 'POST', + url: URL, + data: payload, + options, + 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, { bidderRequest }) { + serverResponse = serverResponse.body; + const bids = []; + + if (!serverResponse || serverResponse.error) { + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; + if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } + utils.logError(errorMessage); + return bids; + } + + if (!utils.isArray(serverResponse.seatbid)) { + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter `; + utils.logError(errorMessage += 'Malformed seatbid response'); + return bids; + } + + serverResponse.seatbid.forEach(sBid => { + if (sBid.hasOwnProperty('bid')) { + sBid.bid.forEach(iBid => { + if (iBid.price !== 0) { + const bid = newBid(iBid); + bids.push(bid); + } + }); + } + }); + return bids; + }, + + getUserSyncs: function (syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' + }]; + } + } +} + +function newBid(bid) { + return { + requestId: bid.impid, + mediaType: BANNER, + cpm: bid.price, + creativeId: bid.adid, + ad: bid.adm, + width: bid.w, + height: bid.h, + ttl: 300, + netRevenue: true, + currency: 'USD', + }; +} + +function mapImpression(bid) { + return { + id: bid.bidId, + banner: mapBanner(bid), + ext: { + appnexus: { + placement_id: parseInt(bid.params.placementId, 10) + } + } + }; +} + +function mapBanner(bid) { + return { + w: parseInt(bid.sizes[0][0], 10), + h: parseInt(bid.sizes[0][1], 10), + format: mapSizes(bid.sizes) + }; +} + +function mapSizes(bidSizes) { + const format = []; + bidSizes.forEach(size => { + format.push({ + w: parseInt(size[0], 10), + h: parseInt(size[1], 10) + }); + }); + return format; +} + +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(global.navigator.userAgent); +} + +registerBidder(spec); diff --git a/modules/playgroundxyzBidAdapter.md b/modules/playgroundxyzBidAdapter.md new file mode 100644 index 00000000000..345bf7d0693 --- /dev/null +++ b/modules/playgroundxyzBidAdapter.md @@ -0,0 +1,72 @@ +# Overview + +``` +Module Name: Playground XYZ Bid Adapter +Module Type: Bidder Adapter +Maintainer: tech+prebid@playgroundxyz.com +``` + +# Description + +Connects to playgroundxyz ad server for bids. + +Playground XYZ bid adapter supports Banner. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'playgroundxyz', + params: { + placementId: '10433394' + } + }] + }, + // Video instream adUnit + { + code: 'video-instream', + sizes: [640, 480], + mediaTypes: { + video: { + context: 'instream' + }, + }, + bids: [{ + bidder: 'playgroundxyz', + params: { + placementId: '9333431', + video: { + skippable: true, + playback_methods: ['auto_play_sound_off'] + } + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'outstream' + } + }, + bids: [ + { + bidder: 'playgroundxyz', + params: { + placementId: '5768085', + video: { + skippable: true, + playback_method: ['auto_play_sound_off'] + } + } + } + ] + } +]; +``` diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index bd684f6406b..00000000000 --- a/package-lock.json +++ /dev/null @@ -1,11615 +0,0 @@ -{ - "name": "prebid.js", - "version": "1.9.0-pre", - "lockfileVersion": 1, - "dependencies": { - "@gulp-sourcemaps/identity-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", - "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } - } - }, - "@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=" - }, - "@sinonjs/formatio": { - "version": "2.0.0", - "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", - "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "dev": true - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "accepts": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", - "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", - "dev": true - }, - "acorn": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==" - }, - "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, - "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": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "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 - } - } - }, - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", - "dev": true, - "optional": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "agent-base": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, - "dependencies": { - "semver": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - } - } - }, - "ajv": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", - "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", - "dev": true - }, - "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 - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "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 - } - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" - }, - "amqplib": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", - "dev": true, - "optional": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "optional": true - }, - "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, - "optional": true - } - } - }, - "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 - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true - }, - "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 - }, - "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 - }, - "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 - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true - }, - "append-transform": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", - "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true - }, - "archiver": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", - "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", - "dev": true, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "glob": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", - "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lazystream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", - "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", - "dev": true - }, - "lodash": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", - "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", - "dev": true - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "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 - }, - "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 - } - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true - }, - "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 - }, - "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 - }, - "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 - }, - "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 - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "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 - }, - "array-iterate": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", - "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", - "dev": true - }, - "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 - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true - }, - "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 - }, - "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 - }, - "array.from": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", - "integrity": "sha1-LGJ7G3bf8t7yNl+gUrZcPVheX2s=", - "dev": true - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true - }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "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 - }, - "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 - }, - "ast-types": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", - "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", - "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=" - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "aws4": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", - "dev": true - }, - "axios": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", - "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", - "dev": true, - "optional": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true - }, - "follow-redirects": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", - "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", - "dev": true, - "optional": true - } - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true - }, - "babel-core": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", - "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "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 - } - } - }, - "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": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true - }, - "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "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 - }, - "babel-loader": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", - "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", - "dev": true - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true - }, - "babel-plugin-syntax-class-constructor-call": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", - "dev": true - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true - }, - "babel-plugin-syntax-do-expressions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", - "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", - "dev": true - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-export-extensions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", - "dev": true - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true - }, - "babel-plugin-syntax-function-bind": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", - "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-system-import-transformer": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", - "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true - }, - "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true - }, - "babel-plugin-transform-class-constructor-call": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", - "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true - }, - "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true - }, - "babel-plugin-transform-decorators-legacy": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", - "integrity": "sha1-dBtY9sW86eYCfgiC2cmU8E82aSU=", - "dev": true - }, - "babel-plugin-transform-do-expressions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", - "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", - "dev": true - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true - }, - "babel-plugin-transform-export-extensions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", - "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true - }, - "babel-plugin-transform-function-bind": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", - "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true - }, - "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=" - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true - }, - "babel-preset-env": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", - "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", - "dev": true - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true - }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true - }, - "babel-preset-stage-0": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", - "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true - }, - "babel-preset-stage-1": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", - "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true - }, - "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true - }, - "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true - }, - "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": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "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 - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "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=" - }, - "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 - }, - "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": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "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 - }, - "babelify": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", - "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw==", - "dev": true - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "bail": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "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 - }, - "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 - }, - "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 - }, - "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 - } - } - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "base64-url": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", - "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true - }, - "basic-auth": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", - "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", - "dev": true - }, - "basic-auth-connect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", - "dev": true - }, - "batch": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", - "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "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": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true - }, - "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true - }, - "binaryextensions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", - "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", - "dev": true - }, - "bitsyntax": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", - "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", - "dev": true, - "optional": true - }, - "bl": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", - "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", - "dev": true - }, - "block-loader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/block-loader/-/block-loader-2.1.0.tgz", - "integrity": "sha1-u7OYrVqEPGxx95opb0tt9LAlcxI=", - "dev": true - }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true - }, - "body-parser": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", - "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", - "dev": true, - "dependencies": { - "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", - "dev": true - }, - "raw-body": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", - "dev": true, - "dependencies": { - "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - } - } - } - } - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true - }, - "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 - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "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 - } - } - }, - "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.2", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", - "dev": true, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "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 - }, - "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 - }, - "browserify-des": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", - "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", - "dev": true - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "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 - }, - "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", - "dev": true - }, - "browserstack": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", - "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", - "dev": true - }, - "browserstacktunnel-wrapper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.2.tgz", - "integrity": "sha512-7w7HYA00qjBtuQH0c5rqW7RbWPHyRROqTZofwNp5G0sKc2fYChsTfbHz3ul8Yd+ffkQvR81m+iPjEB004P6kxQ==", - "dev": true - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true - }, - "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 - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-from": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", - "dev": true - }, - "buffer-more-ints": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", - "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", - "dev": true - }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "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 - }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", - "dev": true, - "optional": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "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": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", - "dev": true - }, - "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 - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "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": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } - }, - "caniuse-lite": { - "version": "1.0.30000830", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000830.tgz", - "integrity": "sha512-yMqGkujkoOIZfvOYiWdqPALgY/PVGiqCHUJb6yNq7xhI/pR+gQO0U2K6lRDqAiJv4+CIU3CtTLblNGw0QGnr6g==", - "dev": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "ccount": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", - "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 - }, - "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true - }, - "chai-nightwatch": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", - "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", - "dev": true, - "dependencies": { - "assertion-error": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", - "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", - "dev": true - } - } - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true - }, - "character-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", - "dev": true - }, - "character-entities-html4": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", - "dev": true - }, - "character-entities-legacy": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", - "dev": true - }, - "character-reference-invalid": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", - "dev": true - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "chokidar": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", - "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", - "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 - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "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 - } - } - }, - "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 - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "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 - }, - "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 - }, - "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "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 - }, - "collapse-white-space": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "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 - }, - "colors": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz", - "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==", - "dev": true - }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true - }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true - }, - "comma-separated-tokens": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", - "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "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==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "compare-versions": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.1.0.tgz", - "integrity": "sha512-4hAxDSBypT/yp2ySFD346So6Ragw5xmBn/e/agIGl3bZr6DLUqnoRZPusxKrXdYRZpgexO9daejmIenlq/wrIQ==", - "dev": true - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "compress-commons": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", - "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "compressible": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", - "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", - "dev": true - }, - "compression": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/compression/-/compression-1.5.2.tgz", - "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", - "dev": true, - "dependencies": { - "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "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 - }, - "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 - }, - "concat-with-sourcemaps": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", - "integrity": "sha512-YtnS0VEY+e2Khzsey/6mra9EoM6h/5gxaC0e3mcHpA5yfDxafhygytNmcJWodvUgyXzSiL5MSkPO6bQGgfliHw==", - "dev": true - }, - "connect": { - "version": "2.30.2", - "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", - "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", - "dev": true, - "dependencies": { - "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", - "dev": true - } - } - }, - "connect-livereload": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", - "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", - "dev": true - }, - "connect-timeout": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", - "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true - }, - "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 - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "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==", - "dev": true - }, - "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 - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" - }, - "cookie": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", - "dev": true - }, - "cookie-parser": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", - "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", - "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=" - }, - "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=" - }, - "coveralls": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", - "dev": true, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "crc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", - "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", - "dev": true - }, - "crc32-stream": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", - "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "create-ecdh": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.1.tgz", - "integrity": "sha512-iZvCCg8XqHQZ1ioNBTzXS/cQSkqkqcPs8xSX4upNB+DAk9Ht3uzQf2J32uAHNCne8LDmKr29AgZrEs4oIrwLuQ==", - "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 - }, - "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 - }, - "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 - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true - }, - "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 - }, - "csrf": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", - "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", - "dev": true - }, - "css": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=" - } - } - }, - "css-loader": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", - "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", - "dev": true, - "optional": true, - "dependencies": { - "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, - "optional": true - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "optional": true - } - } - }, - "css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true - }, - "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 - }, - "csso": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", - "integrity": "sha1-/GKGlKLTiTiqrEmWdTIY/TEc254=", - "dev": true, - "optional": true - }, - "csurf": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", - "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", - "dev": true - }, - "ctype": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", - "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", - "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 - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=" - }, - "dargs": { - "version": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", - "dev": true - }, - "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": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true - }, - "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", - "dev": true - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "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 - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==" - }, - "debug-fabulous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==" - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "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 - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "deep-is": { - "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": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", - "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", - "dev": true - }, - "default-require-extensions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", - "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", - "dev": true, - "dependencies": { - "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 - } - } - }, - "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": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - } - } - }, - "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true - }, - "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-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 - }, - "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 - }, - "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 - } - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "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 - }, - "depd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", - "dev": true - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detab": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", - "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", - "dev": true - }, - "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 - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "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=" - }, - "detective": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true - }, - "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", - "dev": true - }, - "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "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 - }, - "disparity": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", - "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", - "dev": true - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true - }, - "doctrine-temporary-fork": { - "version": "2.0.0-alpha-allowarrayindex", - "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", - "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true - }, - "documentation": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", - "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", - "dev": true, - "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 - }, - "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 - }, - "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true - }, - "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", - "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 - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "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 - }, - "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "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, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "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 - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "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 - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "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 - }, - "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 - }, - "yargs": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", - "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", - "dev": true, - "dependencies": { - "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 - } - } - } - } - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true - }, - "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 - }, - "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", - "dev": true, - "optional": true - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true - }, - "duplexify": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", - "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "ejs": { - "version": "2.5.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", - "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.42", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz", - "integrity": "sha1-lcM78B0MxAVVauyJn+Yf1NduoPk=", - "dev": true - }, - "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "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=", - "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 - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true - }, - "engine.io": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", - "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", - "dev": true, - "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } - } - }, - "engine.io-client": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", - "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", - "dev": true - }, - "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", - "dev": true - }, - "enhanced-resolve": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", - "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true - }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true - }, - "error": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", - "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true - }, - "errorhandler": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", - "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", - "dev": true, - "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } - } - }, - "es5-ext": { - "version": "0.10.42", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.42.tgz", - "integrity": "sha512-AJxO1rmPe1bDEfSR6TJ/FgMFYuTBhR5R57KW58iCkYACMyFbrkqVyzXSurYoScDGvgyMpk7uRF/lPUPPTmsRSA==" - }, - "es5-shim": { - "version": "4.5.10", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", - "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==", - "dev": true - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=" - }, - "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 - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=" - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "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 - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "dependencies": { - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true - } - } - }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true - }, - "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": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, - "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", - "dev": true - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "globals": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.4.0.tgz", - "integrity": "sha512-Dyzmifil8n/TmSqYDEXbm+C8yitzJQqQIlJQLNRMwa+BOUJpRC19pyVeN12JAjt61xonvXjtff+hJruTRXn5HA==", - "dev": true - }, - "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "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 - }, - "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 - } - } - }, - "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 - }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - } - } - }, - "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true - }, - "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 - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true - } - } - }, - "eslint-plugin-import": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.11.0.tgz", - "integrity": "sha1-Fa7qN6Z0mdhI6OmBgG1GJ7VQOBY=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "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 - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true - }, - "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 - } - } - }, - "eslint-plugin-node": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", - "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", - "dev": true, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "eslint-plugin-promise": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz", - "integrity": "sha512-2WO+ZFh7vxUKRfR0cOIMrWgYKdR6S1AlOezw6pC52B6oYpd5WFghN+QHxvrRdZMtbo8h3dfUZ2o1rWb0UPbKtg==", - "dev": true - }, - "eslint-plugin-standard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", - "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", - "dev": true - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "estree-walker": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", - "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "etag": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=" - }, - "event-stream": { - "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true - }, - "eventemitter3": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.0.1.tgz", - "integrity": "sha512-QOCPu979MMWX9XNlfRZoin+Wm+bK1SP7vv3NGUniYwuSJK/+cPA10blMaeRgzg31RvoSFk6FsCDVa4vNryBTGA==", - "dev": true - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "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 - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true - }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "dependencies": { - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true - }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true - }, - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, - "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": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "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 - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true - } - } - }, - "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, - "dependencies": { - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "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 - } - } - }, - "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 - }, - "express-session": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", - "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "uid-safe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", - "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", - "dev": true - } - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "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": { - "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 - } - } - }, - "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": { - "iconv-lite": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", - "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", - "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, - "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 - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "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 - }, - "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 - }, - "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 - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "faker": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-3.1.0.tgz", - "integrity": "sha1-D5CPr05uwCUk5UpX5DLFwBPgjJ8=", - "dev": true - }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true - }, - "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 - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "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 - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true - }, - "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 - }, - "file-loader": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", - "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", - "dev": true, - "optional": true, - "dependencies": { - "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, - "optional": true - } - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, - "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 - }, - "fileset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", - "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true - }, - "fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "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, - "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 - } - } - }, - "finalhandler": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", - "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "escape-html": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", - "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true - }, - "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": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true - } - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true - }, - "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true - }, - "follow-redirects": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", - "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "foreachasync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", - "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "fork-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", - "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true - }, - "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 - }, - "fresh": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", - "dev": true - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "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 - }, - "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": { - "mkdirp": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", - "dev": true - }, - "rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true - } - } - }, - "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 - }, - "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": { - "mkdirp": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", - "dev": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.2.tgz", - "integrity": "sha512-iownA+hC4uHFp+7gwP/y5SzaiUo7m2vpa0dhpzw8YuKtiZsz7cIXsFbXpLEeBM6WuCQyw1MH4RRe6XI8GFUctQ==", - "dev": true, - "optional": true, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.9.1", - "bundled": true, - "dev": true, - "optional": true - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.6", - "bundled": true, - "dev": true, - "optional": true, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } - }, - "fstream": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", - "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", - "dev": true, - "dependencies": { - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true - } - } - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "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 - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", - "dev": true - }, - "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 - }, - "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 - }, - "get-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", - "integrity": "sha512-7aelVrYqCLuVjq2kEKRTH8fXPTC0xKTkM+G7UlFkEwCXY3sFbSxvY375JoFowOAYbkaU47SrBvOefUlLZZ+6QA==", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - } - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "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": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "git-up": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", - "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", - "dev": true - }, - "git-url-parse": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", - "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true - }, - "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 - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "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 - }, - "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 - } - } - }, - "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": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true - }, - "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 - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globals-docs": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", - "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", - "dev": true - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true - } - } - }, - "glogg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", - "dev": true - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", - "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "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 - }, - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "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 - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true - } - } - }, - "gulp-babel": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", - "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", - "dev": true, - "dependencies": { - "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "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 - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "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 - } - } - }, - "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": { - "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 - }, - "chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "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": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "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, - "dependencies": { - "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "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 - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "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.escape": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true - }, - "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 - }, - "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 - }, - "lodash.templatesettings": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true - }, - "minimist": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", - "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 - }, - "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 - }, - "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": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true - }, - "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", - "dev": true - }, - "through2": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", - "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", - "dev": true, - "dependencies": { - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true - } - } - }, - "vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - } - } - }, - "gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true - }, - "gulp-connect": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", - "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", - "dev": true, - "dependencies": { - "body-parser": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", - "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", - "dev": true, - "dependencies": { - "qs": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", - "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", - "dev": true - } - } - }, - "bytes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", - "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", - "dev": true - }, - "raw-body": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", - "dev": true, - "dependencies": { - "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true - } - } - }, - "tiny-lr": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", - "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", - "dev": true - } - } - }, - "gulp-documentation": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", - "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", - "dev": true - }, - "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 - }, - "gulp-footer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", - "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", - "dev": true - }, - "gulp-header": { - "version": "1.8.12", - "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", - "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", - "dev": true, - "dependencies": { - "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true - } - } - }, - "gulp-if": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", - "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true - }, - "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": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true - } - } - }, - "gulp-match": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", - "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true - }, - "gulp-optimize-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", - "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", - "dev": true - }, - "gulp-rename": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", - "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", - "dev": true - }, - "gulp-replace": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", - "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", - "dev": true, - "dependencies": { - "event-stream": { - "version": "3.0.20", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", - "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "split": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", - "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "dev": true - } - } - }, - "gulp-shell": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", - "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=" - }, - "gulp-uglify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", - "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", - "dev": true, - "dependencies": { - "uglify-js": { - "version": "3.3.22", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.22.tgz", - "integrity": "sha512-tqw96rL6/BG+7LM5VItdhDjTQmL5zG/I0b2RqWytlgeHe2eydZHuBHdA9vuGpCDhH/ZskNGcqDhivoR2xt8RIw==", - "dev": true - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "dependencies": { - "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 - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "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 - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true - } - } - }, - "gulp-webdriver": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", - "integrity": "sha1-mM6Bz5rganoZB7htEPaThvQ4Oi0=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true - } - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true - }, - "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true - }, - "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 - }, - "has-binary2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", - "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", - "dev": true, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true - }, - "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": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true - } - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true - }, - "hast-util-is-element": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", - "integrity": "sha1-P3IWl4sq4U2YdJh4eCZ18zvjzgA=", - "dev": true - }, - "hast-util-sanitize": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", - "integrity": "sha1-0QvWdXoh5ZwTq8iuNTDdO219Z54=", - "dev": true - }, - "hast-util-to-html": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", - "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", - "dev": true - }, - "hast-util-whitespace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", - "integrity": "sha1-vQlpGWJdKTbh/xe8Tff9cn8X7Ok=", - "dev": true - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true - }, - "highlight.js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", - "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", - "dev": true - }, - "hipchat-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", - "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", - "dev": true, - "optional": true - }, - "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 - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true - }, - "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", - "dev": true - }, - "html-void-elements": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.3.tgz", - "integrity": "sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==", - "dev": true - }, - "http-errors": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "dev": true - }, - "http-parser-js": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz", - "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==", - "dev": true - }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true - }, - "http-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", - "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - } - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true - }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true - }, - "httpreq": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", - "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true - }, - "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": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - } - } - }, - "iconv-lite": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", - "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", - "dev": true - }, - "ieee754": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", - "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", - "dev": true - }, - "ignore": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", - "dev": true - }, - "ignore-loader": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz", - "integrity": "sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "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 - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflection": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", - "integrity": "sha1-W//LEZetPoEFD44X4hZoCH7p6y8=", - "dev": true, - "optional": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "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-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, - "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", - "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 - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "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 - } - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true - }, - "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 - }, - "ip": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", - "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", - "dev": true - }, - "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 - }, - "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": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - } - } - }, - "is-alphabetical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", - "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", - "dev": true - }, - "is-alphanumeric": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", - "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", - "dev": true - }, - "is-alphanumerical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", - "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true - }, - "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-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true - }, - "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": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - } - } - }, - "is-decimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", - "dev": true - }, - "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": { - "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-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 - }, - "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", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true - }, - "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 - }, - "is-generator": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", - "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true - }, - "is-hexadecimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", - "dev": true - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", - "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", - "dev": true - }, - "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 - }, - "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": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - } - } - }, - "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true - }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, - "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 - } - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "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=", - "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 - }, - "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": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "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 - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "is-ssh": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", - "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "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 - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "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 - }, - "is-whitespace-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", - "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", - "dev": true - }, - "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 - }, - "is-word-character": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", - "integrity": "sha1-WgP6HqkazopusMfNdw64bWXIvvs=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "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 - }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true - } - } - }, - "istanbul-api": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", - "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", - "dev": true, - "dependencies": { - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "dev": true - } - } - }, - "istanbul-instrumenter-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", - "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", - "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.0.tgz", - "integrity": "sha512-p3En6/oGkFQV55Up8ZPC2oLxvgSxD8CzA0yBrhRZSh3pfv3OFj9aSGVC0yoerAi/O4u7jUVnOGVX1eVFM+0tmQ==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", - "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", - "dev": true - }, - "istanbul-lib-report": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", - "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", - "dev": true, - "dependencies": { - "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 - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true - } - } - }, - "istanbul-lib-source-maps": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.4.tgz", - "integrity": "sha512-UzuK0g1wyQijiaYQxj/CdNycFhAd2TLtO2obKQMTZrZ1jzEMRY3rvpASEKkaxbRR6brvdovfA03znPa/pXcejg==", - "dev": true, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", - "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", - "dev": true - }, - "istextorbinary": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", - "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", - "dev": true - }, - "jade": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", - "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", - "dev": true, - "dependencies": { - "commander": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", - "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", - "dev": true - }, - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", - "dev": true - } - } - }, - "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 - }, - "js-yaml": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "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", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "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": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true - }, - "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 - }, - "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 - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonfile": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", - "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", - "dev": true - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "JSONStream": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "just-clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", - "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" - }, - "just-extend": { - "version": "1.1.27", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", - "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", - "dev": true - }, - "karma": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.2.tgz", - "integrity": "sha1-TS25QChQpmVR+nhLAWT7CCTtjEs=", - "dev": true, - "dependencies": { - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true - }, - "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", - "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 - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "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 - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true - }, - "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "dev": true, - "dependencies": { - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - } - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true - }, - "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 - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "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 - }, - "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 - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true - } - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - } - } - }, - "karma-babel-preprocessor": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", - "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true - }, - "karma-browserstack-launcher": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", - "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", - "dev": true, - "dependencies": { - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - } - } - }, - "karma-chai": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", - "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", - "dev": true - }, - "karma-chrome-launcher": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true - }, - "karma-coverage-istanbul-reporter": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.2.tgz", - "integrity": "sha512-sQHexslLF+QHzaKfK8+onTYMyvSwv+p5cDayVxhpEELGa3z0QuB+l0IMsicIkkBNMOJKQaqueiRoW7iuo7lsog==", - "dev": true - }, - "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 - }, - "karma-firefox-launcher": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", - "dev": true - }, - "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 - }, - "karma-mocha": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", - "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "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": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, - "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", - "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 - }, - "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 - } - } - }, - "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 - }, - "karma-requirejs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-1.1.0.tgz", - "integrity": "sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=", - "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 - }, - "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 - }, - "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 - }, - "karma-sourcemap-loader": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", - "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true - }, - "karma-spec-reporter": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", - "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true - }, - "karma-webpack": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", - "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", - "dev": true, - "dependencies": { - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "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 - } - } - }, - "kebab-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", - "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "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.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true - }, - "lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true - }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", - "dev": true, - "dependencies": { - "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true - } - } - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true - }, - "livereload-js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", - "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", - "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=", - "dev": true - }, - "loader-runner": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", - "dev": true - }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true - }, - "localtunnel": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.0.tgz", - "integrity": "sha512-wCIiIHJ8kKIcWkTQE3m1VRABvsH2ZuOkiOpZUofUCf6Q42v3VIZ+Q0YfX1Z4sYDRj0muiKL1bLvz1FeoxsPO0w==", - "dev": true, - "dependencies": { - "axios": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", - "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", - "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 - }, - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "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 - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "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 - }, - "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 - }, - "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 - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "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 - }, - "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 - }, - "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 - }, - "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 - }, - "yargs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "dev": true - }, - "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true - } - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true - }, - "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", - "dev": true - }, - "lodash._arraycopy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", - "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", - "dev": true - }, - "lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true - }, - "lodash._baseclone": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", - "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "dev": true - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._basefor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", - "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", - "dev": true - }, - "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 - }, - "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 - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "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 - }, - "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 - }, - "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 - }, - "lodash._htmlescapes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", - "dev": true - }, - "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 - }, - "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 - }, - "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 - }, - "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 - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "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._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.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true - } - } - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "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 - }, - "lodash._stack": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", - "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", - "dev": true - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "lodash.clone": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", - "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "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, - "dependencies": { - "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 - } - } - }, - "lodash.defaultsdeep": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", - "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", - "dev": true, - "dependencies": { - "lodash._baseclone": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", - "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", - "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 - }, - "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 - }, - "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 - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "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 - }, - "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 - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true - }, - "lodash.keysin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", - "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", - "dev": true - }, - "lodash.mergewith": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", - "dev": true - }, - "lodash.rest": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", - "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true - }, - "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": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true - } - } - }, - "log-driver": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", - "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, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, - "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", - "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 - } - } - }, - "log4js": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", - "integrity": "sha512-YL/qpTxYtK0iWWbuKCrevDZz5lh+OjyHHD+mICqpjnYGKdNRBvPeh/1uYjkKUemT1CSO4wwLOwphWMpKAnD9kw==", - "dev": true, - "dependencies": { - "circular-json": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.3.tgz", - "integrity": "sha512-YlxLOimeIoQGHnMe3kbf8qIV2Bj7uXLbljMPRguNT49GmSAzooNfS9EJ91rSJKbLBOOzM5agvtx0WyechZN/Hw==", - "dev": true - } - } - }, - "loggly": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", - "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", - "dev": true, - "optional": true, - "dependencies": { - "bl": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", - "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", - "dev": true, - "optional": true - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true, - "optional": 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, - "optional": true - }, - "qs": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "optional": true - }, - "request": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", - "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", - "dev": true, - "optional": true - }, - "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, - "optional": true - } - } - }, - "lolex": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", - "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==", - "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.2", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", - "dev": true - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true - }, - "lru-cache": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", - "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "dev": true - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=" - }, - "magic-string": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", - "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", - "dev": true - }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", - "dev": true, - "optional": true - }, - "mailgun-js": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", - "integrity": "sha1-7jZqINrGTDwVwD1sGz4O15UlKrs=", - "dev": true, - "optional": true, - "dependencies": { - "async": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", - "integrity": "sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw=", - "dev": true, - "optional": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "optional": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true, - "optional": true - }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", - "dev": true, - "optional": true - } - } - }, - "make-dir": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", - "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", - "dev": true - }, - "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", - "dev": true - }, - "make-error-cause": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true - }, - "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 - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "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.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "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 - }, - "markdown-escapes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", - "dev": true - }, - "markdown-table": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", - "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", - "dev": true - }, - "match-stream": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", - "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true - }, - "mdast-util-compact": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", - "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", - "dev": true - }, - "mdast-util-definitions": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", - "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", - "dev": true - }, - "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 - }, - "mdast-util-to-hast": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.0.tgz", - "integrity": "sha512-zvEXH2AUevWfKuBqtEPNcDUPI8UC6yIVvgEgNi1v1dLnzb5Pfm+PZjnZn0FhW1WmHcrGMX059MAoqicEauzjcw==", - "dev": true - }, - "mdast-util-to-string": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", - "integrity": "sha1-XEVch4yTVfDB5/PotxnPWDaRrPs=", - "dev": true - }, - "mdast-util-toc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", - "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", - "dev": true - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true - }, - "memoizee": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz", - "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==" - }, - "memory-fs": { - "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 - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "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 - }, - "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 - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "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 - }, - "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 - }, - "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 - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "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 - }, - "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 - }, - "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 - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true - }, - "method-override": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", - "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - } - } - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "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 - }, - "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 - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true - }, - "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 - }, - "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.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "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 - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true - }, - "mkpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", - "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", - "dev": true - }, - "mocha": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", - "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", - "dev": true, - "dependencies": { - "commander": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", - "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", - "dev": true - }, - "debug": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", - "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", - "dev": true - }, - "glob": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", - "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", - "dev": true - }, - "graceful-fs": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", - "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true - }, - "mkdirp": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", - "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", - "dev": true - }, - "ms": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", - "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", - "dev": true - }, - "supports-color": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz", - "integrity": "sha1-Eu4hUHCGzZjBBY2ewPSsR2t687I=", - "dev": true - } - } - }, - "mocha-nightwatch": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", - "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", - "dev": true, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "glob": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", - "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "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 - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true - } - } - }, - "mock-fs": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", - "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", - "dev": true, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "module-deps-sortable": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", - "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", - "dev": true, - "dependencies": { - "concat-stream": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", - "dev": true, - "dependencies": { - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "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 - }, - "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 - } - } - }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, - "morgan": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", - "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multiparty": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", - "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true - }, - "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 - } - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "dependencies": { - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true - }, - "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 - } - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "dev": true - }, - "natives": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.3.tgz", - "integrity": "sha512-BZGSYV4YOLxzoTK73l0/s/0sH9l8SHs2ocReMH1f8JYSh5FUWu4ZrKCpJdRkWXV6HFR/pZDz7bwWOVAY07q77g==", - "dev": true - }, - "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 - }, - "ncp": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", - "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", - "dev": true - }, - "negotiator": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", - "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", - "dev": true - }, - "neo-async": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", - "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", - "dev": true - }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "nightwatch": { - "version": "0.9.20", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.20.tgz", - "integrity": "sha1-FW0XzQWMvDH0OrGOkV9+wpf7U+A=", - "dev": true, - "dependencies": { - "ejs": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", - "dev": true - }, - "minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "dev": true - }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", - "dev": true - } - } - }, - "nise": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.3.3.tgz", - "integrity": "sha512-v1J/FLUB9PfGqZLGDBhQqODkbLotP0WtLo9R4EJY2PPu5f5Xg4o0rA8FDlmrjFSv9vBBKcfnOSpfYYuu5RTHqg==", - "dev": true - }, - "node-int64": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", - "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", - "dev": true - }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "dependencies": { - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - } - } - }, - "nodemailer": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", - "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", - "dev": true, - "optional": true, - "dependencies": { - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true, - "optional": true - }, - "socks": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", - "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", - "dev": true, - "optional": true - } - } - }, - "nodemailer-direct-transport": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", - "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", - "dev": true, - "optional": true - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true - }, - "nodemailer-smtp-pool": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", - "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", - "dev": true, - "optional": true - }, - "nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", - "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", - "dev": true, - "optional": true - }, - "nodemailer-wellknown": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "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=" - }, - "now-and-later": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", - "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", - "dev": true - }, - "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 - }, - "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 - }, - "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 - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "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": { - "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 - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - } - } - }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true - }, - "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 - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true - }, - "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 - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "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 - } - } - }, - "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 - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true - }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true - }, - "open": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", - "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", - "dev": true - }, - "openurl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", - "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optimize-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", - "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", - "dev": true, - "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 - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "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 - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "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 - }, - "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 - }, - "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 - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "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 - }, - "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 - }, - "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 - }, - "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 - }, - "yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "dependencies": { - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true - }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true - } - } - }, - "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 - }, - "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-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true - }, - "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 - }, - "over": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", - "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "dev": true - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true - }, - "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 - }, - "pac-proxy-agent": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", - "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", - "dev": true, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "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 - }, - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true - } - } - }, - "pac-resolver": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", - "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", - "dev": true, - "dependencies": { - "co": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", - "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", - "dev": true - } - } - }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", - "dev": true - }, - "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true - }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true - }, - "parse-domain": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.0.0.tgz", - "integrity": "sha512-09LkZIoBmYFj5Ty0oO1cjevbc42/knoiWURPUgKjJHlnK+75KDaF8+DNyEM5IYozO4Ssh6mNVOhrAKRWrwZbqQ==", - "dev": true - }, - "parse-entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", - "integrity": "sha1-gRLYhHExnyerrk1klksSL+ThuJA=", - "dev": true - }, - "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 - }, - "parse-git-config": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", - "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", - "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, - "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 - } - } - }, - "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 - }, - "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 - }, - "parse-url": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", - "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", - "dev": true - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "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 - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "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 - }, - "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 - }, - "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 - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", - "dev": true - }, - "path-proxy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "dev": true, - "optional": true, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", - "dev": true, - "optional": true - } - } - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true - }, - "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 - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "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 - }, - "pause": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", - "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true - }, - "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "dev": true - }, - "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 - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "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 - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true - }, - "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 - }, - "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 - }, - "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 - }, - "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 - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "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 - }, - "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 - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", - "dev": true - }, - "property-information": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", - "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE=", - "dev": true - }, - "protocols": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", - "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", - "dev": true - }, - "proxy-agent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", - "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "lru-cache": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", - "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", - "dev": true - } - } - }, - "proxyquire": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", - "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", - "dev": true, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", - "dev": true - }, - "pullstream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", - "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true - }, - "pumpify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", - "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "q": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", - "integrity": "sha1-hQ15+MuDHZLhA7Rkg+TjXTRkAFA=", - "dev": true - }, - "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 - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "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": "0.0.3", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", - "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", - "dev": true - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", - "dev": true - }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true - } - } - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true - }, - "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 - }, - "range-parser": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", - "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", - "dev": true - }, - "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": { - "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 - } - } - }, - "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 - }, - "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 - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==" - }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true - }, - "readline2": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", - "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", - "dev": true, - "dependencies": { - "ansi-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", - "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", - "dev": true - }, - "mute-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", - "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", - "dev": true - }, - "strip-ansi": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", - "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", - "dev": true - } - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true - }, - "redis": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", - "dev": true, - "optional": true - }, - "redis-commands": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", - "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==", - "dev": true, - "optional": true - }, - "redis-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", - "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", - "dev": true, - "optional": true - }, - "regenerate": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", - "dev": true - }, - "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.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true - }, - "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 - }, - "regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", - "dev": true - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "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": "9.0.0", - "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", - "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true - }, - "remark-html": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", - "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true - }, - "remark-parse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true - }, - "remark-reference-links": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.1.tgz", - "integrity": "sha1-AhrtHFXBh9cSs8dtAFe/UQ0wC6c=", - "dev": true - }, - "remark-slug": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", - "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", - "dev": true - }, - "remark-stringify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", - "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true - }, - "remark-toc": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", - "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", - "dev": true - }, - "remote-origin-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", - "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true - }, - "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 - }, - "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 - }, - "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=" - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "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 - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replacestream": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", - "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", - "dev": true - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true - }, - "requestretry": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", - "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", - "dev": true, - "optional": 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-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 - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true - }, - "requirejs": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", - "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", - "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.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", - "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 - }, - "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 - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "response-time": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", - "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", - "dev": true, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - } - } - }, - "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 - }, - "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 - }, - "rewire": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", - "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", - "dev": true - }, - "rgb2hex": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", - "integrity": "sha1-zNVfhgrgxcTqN1BLlY5ELY0SMls=", - "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 - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true - }, - "rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", - "dev": true - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true - }, - "rx": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", - "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", - "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 - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "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 - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "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": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true - } - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - }, - "send": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", - "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "statuses": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", - "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", - "dev": true - } - } - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "serve-favicon": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", - "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", - "dev": true, - "dependencies": { - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "serve-index": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", - "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "serve-static": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", - "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", - "dev": true - }, - "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 - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "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 - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "sha.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 - }, - "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 - }, - "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 - }, - "shelljs": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", - "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "sinon": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", - "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", - "dev": true, - "dependencies": { - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "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 - }, - "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 - } - } - }, - "slack-node": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", - "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", - "dev": true, - "optional": true - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "dependencies": { - "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 - } - } - }, - "slice-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", - "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true - }, - "smtp-connection": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", - "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true - }, - "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": { - "atob": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.0.tgz", - "integrity": "sha512-SuiKH8vbsOyCALjA/+EINmt/Kdl+TQPrtFgW7XZZcwtryFu9e5kQoX3bjCW6mIvGH1fbeAZZuvwGR5IlBRznGw==", - "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 - }, - "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 - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "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-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "dev": true - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - } - } - }, - "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": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "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 - }, - "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 - }, - "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 - } - } - }, - "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": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - } - } - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true - }, - "socket.io": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", - "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - } - } - }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", - "dev": true - }, - "socket.io-client": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", - "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - } - } - }, - "socket.io-parser": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", - "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", - "dev": true, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "socks": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "dev": true, - "dependencies": { - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - } - } - }, - "socks-proxy-agent": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", - "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", - "dev": true - }, - "source-list-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", - "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==" - }, - "source-map-resolve": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=" - }, - "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": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "source-map-url": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", - "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=" - }, - "space-separated-tokens": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", - "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "dev": true - }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "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 - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", - "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", - "dev": true, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "state-toggle": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", - "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=", - "dev": true, - "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 - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "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": { - "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=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "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 - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true - }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", - "dev": true - }, - "stream-counter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", - "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true - }, - "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-http": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz", - "integrity": "sha512-cQ0jo17BLca2r0GfRdZKYAGLU6JRoIWxqSOakUMuKOT6MOK7AAlE856L33QuDmAy/eeOrhLee3dZKX0Uadu93A==", - "dev": true - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", - "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==" - }, - "string-replace-webpack-plugin": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", - "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", - "dev": true, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - }, - "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 - } - } - }, - "string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true - }, - "stringify-entities": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", - "integrity": "sha1-sVDsLXKsTBtfMktR+2soyc3/BYw=", - "dev": true - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true - }, - "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-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" - }, - "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 - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "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 - }, - "style-loader": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", - "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", - "dev": true, - "optional": true, - "dependencies": { - "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, - "optional": true - } - } - }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "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 - }, - "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, - "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", - "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 - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "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 - } - } - }, - "tapable": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", - "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", - "dev": true - }, - "tar-stream": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", - "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "ternary-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", - "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true - }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "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 - }, - "textextensions": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", - "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", - "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 - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=" - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true - }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true - }, - "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.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true - }, - "timers-ext": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", - "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==" - }, - "timespan": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", - "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", - "dev": true, - "optional": 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==", - "dev": true, - "dependencies": { - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true - } - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true - }, - "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 - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "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": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "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 - } - } - }, - "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 - }, - "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 - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "dev": true - }, - "trim-lines": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.1.tgz", - "integrity": "sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==", - "dev": true - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "trim-trailing-lines": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", - "integrity": "sha1-eu+7eAjfnWafbaLkOMrIxGradoQ=", - "dev": true - }, - "trough": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.2.tgz", - "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", - "dev": true - }, - "tsscmp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", - "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.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true - }, - "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "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, - "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 - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "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 - }, - "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 - } - } - }, - "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 - }, - "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, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "uid-safe": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", - "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", - "dev": true - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, - "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 - }, - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true - }, - "unherit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", - "integrity": "sha1-a5qu379z3xdWrZ4xbdmBiFhAzX0=", - "dev": true - }, - "unified": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", - "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "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 - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true - } - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true - }, - "unist-builder": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", - "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", - "dev": true - }, - "unist-util-generated": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.1.tgz", - "integrity": "sha1-mfFseJWayFTe58YVwpGSTIv03n8=", - "dev": true - }, - "unist-util-is": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", - "integrity": "sha1-DDEmKeP5YMZukx6BLT2A53AQlHs=", - "dev": true - }, - "unist-util-modify-children": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", - "integrity": "sha1-ZtfmpEnm9nIguXarPLi166w55R0=", - "dev": true - }, - "unist-util-position": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.0.tgz", - "integrity": "sha1-5uHgPu64HF4a/lU+jUrfvXwNj4I=", - "dev": true - }, - "unist-util-remove-position": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", - "integrity": "sha1-WoXBVV/BugwQG4ZwfRXlD6TIcbs=", - "dev": true - }, - "unist-util-stringify-position": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", - "integrity": "sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=", - "dev": true - }, - "unist-util-visit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", - "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "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": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true - } - } - }, - "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 - } - } - }, - "unzip": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", - "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "upath": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.4.tgz", - "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==", - "dev": true - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", - "dev": true, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-parse": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz", - "integrity": "sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==", - "dev": true, - "dependencies": { - "querystringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", - "dev": true - } - } - }, - "use": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", - "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "dev": true - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "useragent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", - "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", - "dev": true, - "dependencies": { - "lru-cache": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", - "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", - "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, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", - "dev": true - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true - }, - "uws": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", - "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", - "dev": true, - "optional": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "dev": true - }, - "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.0.1", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", - "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "vfile": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true - }, - "vfile-location": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", - "integrity": "sha1-02dcWch3SY5JK0dW/2Xkrxp1IlU=", - "dev": true - }, - "vfile-message": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", - "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", - "dev": true - }, - "vfile-reporter": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", - "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", - "dev": true, - "dependencies": { - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true - } - } - }, - "vfile-sort": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.0.tgz", - "integrity": "sha1-SVAcnou+Wt/y6bOnZx7hseIMUhA=", - "dev": true - }, - "vfile-statistics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.0.tgz", - "integrity": "sha1-AhBMYP3u0dEbH3OtZTMLdjSz2JU=", - "dev": true - }, - "vhost": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", - "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", - "dev": true - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true - }, - "vinyl-fs": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", - "integrity": "sha512-AUSFda1OukBwuLPBTbyuO4IRWgfXmqC4UTW0f8xrCa8Hkv9oyIU+NSqBlgfOLZRoUt7cHdo75hKQghCywpIyIw==", - "dev": true - }, - "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 - }, - "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": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true - }, - "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 - }, - "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 - }, - "walk": { - "version": "2.3.13", - "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.13.tgz", - "integrity": "sha512-78SMe7To9U7kqVhSoGho3GfspA089ZDBIj2f8jElg2hi6lUCoagtDJ8sSMFNlpAh5Ib8Jt1gQ6Y7gh9mzHtFng==", - "dev": true - }, - "watchpack": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz", - "integrity": "sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==", - "dev": true - }, - "webdriverio": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz", - "integrity": "sha1-2dTTwxNm8FPhCvZEsOqtXoc6t7U=", - "dev": true, - "dependencies": { - "ansi-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", - "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", - "dev": true - }, - "asn1": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", - "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", - "dev": true - }, - "assert-plus": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", - "dev": true - }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "aws-sign2": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", - "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", - "dev": true - }, - "boom": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", - "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", - "dev": true - }, - "caseless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", - "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", - "dev": true - }, - "cli-width": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", - "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", - "dev": true - }, - "combined-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", - "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", - "dev": true - }, - "cryptiles": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", - "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", - "dev": true - }, - "delayed-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", - "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", - "dev": true - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true - }, - "forever-agent": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", - "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", - "dev": true - }, - "form-data": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", - "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true - }, - "hawk": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", - "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", - "dev": true - }, - "hoek": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", - "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", - "dev": true - }, - "http-signature": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", - "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", - "dev": true - }, - "inquirer": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", - "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", - "dev": true - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "mime": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", - "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", - "dev": true - }, - "mime-types": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", - "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", - "dev": true - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true - }, - "oauth-sign": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", - "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", - "dev": true - }, - "qs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", - "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", - "dev": true - }, - "request": { - "version": "2.49.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", - "integrity": "sha1-DU9jSNwzSAWbVT5Ntg/SR43mYqc=", - "dev": true - }, - "sntp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", - "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", - "dev": true - }, - "supports-color": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", - "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", - "dev": true - } - } - }, - "webpack": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", - "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", - "dev": true, - "dependencies": { - "ajv-keywords": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", - "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "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": "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 - }, - "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 - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true - }, - "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 - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "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 - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true - }, - "yargs": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true - } - } - }, - "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, - "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 - } - } - }, - "webpack-dev-middleware": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", - "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", - "dev": true, - "dependencies": { - "time-stamp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", - "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", - "dev": true - } - } - }, - "webpack-sources": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", - "dev": true - }, - "webpack-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", - "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", - "dev": true, - "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 - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true - }, - "browserify-aes": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", - "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true - }, - "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 - }, - "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 - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true - }, - "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 - }, - "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 - }, - "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, - "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 - } - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true - }, - "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 - }, - "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-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 - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - }, - "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 - }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, - "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 - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true - }, - "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 - }, - "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 - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "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 - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true - }, - "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", - "dev": true - }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", - "dev": true, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - } - } - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true - }, - "watchpack": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", - "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", - "dev": true, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "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 - }, - "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 - }, - "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 - } - } - }, - "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true - }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", - "dev": true - }, - "wgxpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", - "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", - "dev": true - }, - "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true, - "optional": true - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true - }, - "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 - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "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=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true - }, - "x-is-function": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", - "integrity": "sha1-XSlNw9Joy90GJYDgxd93o5HR+h4=", - "dev": true - }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", - "dev": true - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", - "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", - "dev": true - }, - "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 - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - }, - "zip-stream": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", - "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lodash": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", - "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", - "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 - }, - "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 - } - } - } - } -} diff --git a/test/spec/modules/playgroundxyzBidAdapter_spec.js b/test/spec/modules/playgroundxyzBidAdapter_spec.js new file mode 100644 index 00000000000..72cd1205c45 --- /dev/null +++ b/test/spec/modules/playgroundxyzBidAdapter_spec.js @@ -0,0 +1,136 @@ +import { expect } from 'chai'; +import { spec } from 'modules/playgroundxyzBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +const URL = 'https://ads.playground.xyz/host-config/prebid'; + +describe('playgroundxyzBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'playgroundxyz', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [320, 50]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'playgroundxyz', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('sends bid request to ENDPOINT via POST', () => { + let bidRequest = Object.assign([], bidRequests); + + const request = spec.buildRequests(bidRequest); + const data = JSON.parse(request.data); + const banner = data.imp[0].banner; + + expect(Object.keys(data.imp[0].ext)).to.have.members(['appnexus']); + expect([banner.w, banner.h]).to.deep.equal([300, 250]); + expect(banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + expect(request.url).to.equal(URL); + expect(request.method).to.equal('POST'); + }); + }) + + describe('interpretResponse', () => { + let response = { + 'id': 'bidd_id', + 'seatbid': [ { + 'bid': [ + { + 'id': '4434762738980910431', + 'impid': '221f2bdc1fbc31', + 'price': 1, + 'adid': '91673066', + 'adm': '', + 'adomain': [ 'pg.xyz' ], + 'iurl': 'http://pgxyz.com/cr?id=91673066', + 'cid': 'c_id', + 'crid': 'c_rid', + 'h': 50, + 'w': 320, + 'ext': { + 'appnexus': { + 'brand_id': 1, + 'auction_id': 1087655594852566000, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + ], + 'seat': '4321' + }], + 'bidid': '6894227111893743356', + 'cur': 'USD' + }; + + let bidderRequest = { + 'bidderCode': 'playgroundxyz' + }; + + it('should get correct bid response', () => { + let expectedResponse = [ + { + 'requestId': '221f2bdc1fbc31', + 'cpm': 1, + 'creativeId': 91673066, + 'width': 300, + 'height': 50, + 'ad': '', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true + } + ]; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', () => { + let response = ''; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result.length).to.equal(0); + }); + }); +}); From d04127afc41f6d9680ab90aca2805fb4835f84a5 Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Fri, 8 Jun 2018 04:48:58 +0800 Subject: [PATCH 0453/1594] Rubicon able to read mediaTypes.size (#2607) * Rubicon able to read mediaTypes.size checkBidRequestSizes is normally present in adaptermanager.js to add the mediaTypes.banner.sizes to bid.sizes. However our adapter need to be able to read these fields in case the method is deprecated. Same for the Video. --- modules/rubiconBidAdapter.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 46d53e22ab7..acb9f2eeec5 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -506,7 +506,9 @@ function parseSizes(bid) { let params = bid.params; if (spec.hasVideoMediaType(bid)) { let size = []; - if (params.video && params.video.playerWidth && params.video.playerHeight) { + if (typeof utils.deepAccess(bid, 'mediaTypes.video.playerSize') !== 'undefined') { + size = bid.mediaTypes.video.playerSize; + } else if (params.video && params.video.playerWidth && params.video.playerHeight) { size = [ params.video.playerWidth, params.video.playerHeight @@ -518,7 +520,16 @@ function parseSizes(bid) { } // deprecated: temp legacy support - let sizes = Array.isArray(params.sizes) ? params.sizes : mapSizes(bid.sizes) + let sizes = []; + if (Array.isArray(params.sizes)) { + sizes = params.sizes; + } 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 { + utils.logWarn('Warning: no sizes are setup or found'); + } return masSizeOrdering(sizes); } From 1c53a2ad3f9bc9753a021d47d9f5fa187b8f1c70 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Thu, 7 Jun 2018 14:19:49 -0700 Subject: [PATCH 0454/1594] Rubicon Bid Adapter - ordered auction query params (#2665) * ordered ae query params * updated tg_v and tg_i filter strings * linting fix * extracted ordering code to a function * fixed param names for lat long * Added unit test to check AE param ordering * changed test for tg_i and tg_v * fix removed duplicated 'rf' in order params function --- modules/rubiconBidAdapter.js | 43 ++++++++++++++++++++- test/spec/modules/rubiconBidAdapter_spec.js | 11 ++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index acb9f2eeec5..f517f864061 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -197,7 +197,7 @@ export const spec = { return { method: 'GET', url: FASTLANE_ENDPOINT, - data: Object.keys(bidParams).reduce((paramString, key) => { + data: spec.getOrderedParams(bidParams).reduce((paramString, key) => { const propValue = bidParams[key]; return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${key}=${encodeURIComponent(propValue)}&` : paramString; }, '') + `slots=1&rand=${Math.random()}`, @@ -225,11 +225,12 @@ export const spec = { const combinedSlotParams = spec.combineSlotUrlParams(bidsInGroup.map(bidRequest => { return spec.createSlotParams(bidRequest, bidderRequest); })); + // SRA request returns grouped bidRequest arrays not a plain bidRequest return { method: 'GET', url: FASTLANE_ENDPOINT, - data: Object.keys(combinedSlotParams).reduce((paramString, key) => { + data: spec.getOrderedParams(combinedSlotParams).reduce((paramString, key) => { const propValue = combinedSlotParams[key]; return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${key}=${encodeURIComponent(propValue)}&` : paramString; }, '') + `slots=${bidsInGroup.length}&rand=${Math.random()}`, @@ -240,6 +241,40 @@ export const spec = { return requests; }, + getOrderedParams: function(params) { + const containsTgV = /^tg_v/ + const containsTgI = /^tg_i/ + + const orderedParams = [ + 'account_id', + 'site_id', + 'zone_id', + 'size_id', + 'alt_size_ids', + 'p_pos', + 'gdpr', + 'gdpr_consent', + 'rf', + 'dt.id', + 'dt.keyv', + 'dt.pref', + 'p_geo.latitude', + 'p_geo.longitude', + 'kw' + ].concat(Object.keys(params).filter(item => containsTgV.test(item))) + .concat(Object.keys(params).filter(item => containsTgI.test(item))) + .concat([ + 'tk_flint', + 'x_source.tid', + 'p_screen_res', + 'rp_floor', + 'rp_secure', + 'tk_user_key' + ]); + + return orderedParams.concat(Object.keys(params).filter(item => (orderedParams.indexOf(item) === -1))); + }, + /** * @summary combines param values from an array of slots into a single semicolon delineated value * or just one value if they are all the same. @@ -291,6 +326,8 @@ export const spec = { // use rubicon sizes if provided, otherwise adUnit.sizes const parsedSizes = parseSizes(bidRequest); + const [latitude, longitude] = params.latLong || []; + const data = { 'account_id': params.accountId, 'site_id': params.siteId, @@ -305,6 +342,8 @@ export const spec = { 'p_screen_res': _getScreenResolution(), 'kw': Array.isArray(params.keywords) ? params.keywords.join(',') : '', 'tk_user_key': params.userId, + 'p_geo.latitude': isNaN(parseFloat(latitude)) ? undefined : parseFloat(latitude).toFixed(4), + 'p_geo.longitude': isNaN(parseFloat(longitude)) ? undefined : parseFloat(longitude).toFixed(4), 'tg_fl.eid': bidRequest.code, 'rf': _getPageUrl(bidRequest) }; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index e6418d715e1..d254423bb0b 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -392,6 +392,17 @@ describe('the rubicon adapter', () => { }); }); + it('ad engine query params should be ordered correctly', () => { + 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_i.rating', 'tg_i.prodtype', 'tk_flint', 'x_source.tid', 'p_screen_res', 'rp_floor', 'rp_secure', 'tk_user_key', 'tg_fl.eid', 'slots', 'rand']; + + request.data.split('&').forEach((item, i) => { + expect(item.split('=')[0]).to.equal(referenceOrdering[i]); + }); + }); + it('should make a well-formed request object without latLong', () => { let expectedQuery = { 'account_id': '14062', From 0885ae007ddcd5cf06f5f8148ba728d13acfbfbe Mon Sep 17 00:00:00 2001 From: Rade Popovic <32302052+nanointeractive@users.noreply.github.com> Date: Thu, 7 Jun 2018 23:40:32 +0200 Subject: [PATCH 0455/1594] nanointeractive - new optional bid parameter (#2694) * nanointeractive bid adapter * nanointeractive bid adapter * - using utils.getParameterByName instead of utils.getTopWindowLocation().href - bidderCode is removed - Default ALG changed to 'ihr' - added protocol to 'cors' param * markdown file * enabling localhost for bid requests * Bugfix interpretResponse - added body; Removed unnecessary parameters; Adjusted tests; * New feature - subId * Fixed lint errors * Nano Interactive Bid Adapter New Bid params: - categoryName - name Getting referrer information * Fixed documentation * Removed unnecessary parameter from documentation * Cleaning up documentation --- modules/nanointeractiveBidAdapter.js | 32 +- modules/nanointeractiveBidAdapter.md | 197 +++-- .../modules/nanointeractiveBidAdapter_spec.js | 830 ++++++++++++++++-- 3 files changed, 910 insertions(+), 149 deletions(-) diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index 549695369c8..afcfef1f5b6 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -9,18 +9,20 @@ export const DATA_PARTNER_PIXEL_ID = 'pid'; export const NQ = 'nq'; export const NQ_NAME = 'name'; export const CATEGORY = 'category'; +export const CATEGORY_NAME = 'categoryName'; export const SUB_ID = 'subId'; +export const REF = 'ref'; export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], - isBidRequestValid(bid) { + isBidRequestValid (bid) { const pid = bid.params[DATA_PARTNER_PIXEL_ID]; return !!(pid); }, - buildRequests(bidRequests) { + buildRequests (bidRequests) { let payload = []; bidRequests.forEach(bid => payload.push(createSingleBidRequest(bid))); return { @@ -29,7 +31,7 @@ export const spec = { data: JSON.stringify(payload) }; }, - interpretResponse(serverResponse) { + interpretResponse (serverResponse) { const bids = []; serverResponse.body.forEach(serverBid => { if (isEngineResponseValid(serverBid)) { @@ -40,18 +42,20 @@ export const spec = { } }; -function createSingleBidRequest(bid) { +function createSingleBidRequest (bid) { return { [DATA_PARTNER_PIXEL_ID]: bid.params[DATA_PARTNER_PIXEL_ID], - [NQ]: [createNqParam(bid), createCategoryParam(bid)], + [NQ]: [createNqParam(bid)], + [CATEGORY]: [createCategoryParam(bid)], [SUB_ID]: createSubIdParam(bid), + [REF]: createRefParam(bid), sizes: bid.sizes.map(value => value[0] + 'x' + value[1]), bidId: bid.bidId, - cors: utils.getOrigin() + cors: utils.getOrigin(), }; } -function createSingleBidResponse(serverBid) { +function createSingleBidResponse (serverBid) { return { requestId: serverBid.id, cpm: serverBid.cpm, @@ -65,19 +69,23 @@ function createSingleBidResponse(serverBid) { }; } -function createNqParam(bid) { +function createNqParam (bid) { return bid.params[NQ_NAME] ? utils.getParameterByName(bid.params[NQ_NAME]) : bid.params[NQ] || null; } -function createCategoryParam(bid) { - return bid.params[CATEGORY] || null; +function createCategoryParam (bid) { + return bid.params[CATEGORY_NAME] ? utils.getParameterByName(bid.params[CATEGORY_NAME]) : bid.params[CATEGORY] || null; } -function createSubIdParam(bid) { +function createSubIdParam (bid) { return bid.params[SUB_ID] || null; } -function isEngineResponseValid(response) { +function createRefParam (bid) { + return bid.params[REF] ? null : utils.getTopWindowReferrer() || null; +} + +function isEngineResponseValid (response) { return !!response.cpm && !!response.ad; } diff --git a/modules/nanointeractiveBidAdapter.md b/modules/nanointeractiveBidAdapter.md index 0813a461493..c1790ff6337 100644 --- a/modules/nanointeractiveBidAdapter.md +++ b/modules/nanointeractiveBidAdapter.md @@ -1,7 +1,7 @@ # Overview ``` -Module Name: NanoInteractive Bid Adapter +Module Name: Nano Interactive Bid Adapter Module Type: Bidder Adapter Maintainer: rade@nanointeractive.com ``` @@ -10,70 +10,143 @@ Maintainer: rade@nanointeractive.com Connects to Nano Interactive search retargeting Ad Server for bids. -Besides standard params, please provide, if exist, user search params. -Three examples calling the Ad Server. -**First** is basic +
+### Requirements: +To be able to get identification key (`pid`), please contact us at
+`https://www.nanointeractive.com/publishers`
+


-**Second** is with hardcoded nq (user search) params +#### Send All Bids Ad Server Keys: +(truncated to 20 chars due to [DFP limit](https://support.google.com/dfp_premium/answer/1628457?hl=en#Key-values)) -**Third** is with the search query param name of the current url +`hb_adid_nanointeract` +`hb_bidder_nanointera` +`hb_pb_nanointeractiv` +`hb_format_nanointera` +`hb_size_nanointeract` +`hb_source_nanointera` -# Test Parameters -``` -var adUnits = [ - // Basic call - { - code: 'basic-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - // required - pid: '58bfec94eb0a1916fa380163', - // optional parameters - category: 'some category', - subId: '123' - } - }] - }, - // Hardcoded user search - { - code: 'nq-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - // required - pid: '58bfec94eb0a1916fa380163', - // optional parameters - nq: 'user search', - category: 'some category', - subId: '123' - } - }] - }, - // URL user search - { - code: 'url-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - // required - pid: '58bfec94eb0a1916fa380163', - // optional parameters - name: 'search', - category: 'some category', - subId: '123' - } - }] - } -]; -``` +#### Default Deal ID Keys: +`hb_deal_nanointeract` -### Requirements: -To be able to get identification key (`pid`), you must register at
-`https://audiencemanager.de/public/data-partners-register`
-and follow further instructions. \ No newline at end of file +### bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | +| :------------- | :------- | :----------------------------------------------- | :--------------------------- | +| `pid` | required | Identification key, provided by Nano Interactive | `'5afaa0280ae8996eb578de53'` | +| `category` | optional | Contextual taxonomy | `'automotive'` | +| `categoryName` | optional | Contextual taxonomy (from URL query param) | `'cat_name'` | +| `nq` | optional | User search query | `'automobile search query'` | +| `name` | optional | User search query (from URL query param) | `'search_param'` | +| `subId` | optional | Channel - used to separate traffic sources | `'123'` | + +#### Configuration +The `category` and `categoryName` are mutually exclusive. If you pass both, `categoryName` takes precedence. +
+The `nq` and `name` are mutually exclusive. If you pass both, `name` takes precedence. + +#### Example with only required field `pid` + var adUnits = [{ + code: 'nano-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'nanointeractive', + params: { + pid: '5afaa0280ae8996eb578de53' + } + }] + }]; + +#### Example with `category` + var adUnits = [{ + code: 'nano-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'nanointeractive', + params: { + pid: '5afaa0280ae8996eb578de53', + category: 'automotive', + subId: '123' + } + }] + }]; + +#### Example with `categoryName` + var adUnits = [{ + code: 'nano-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'nanointeractive', + params: { + pid: '5afaa0280ae8996eb578de53', + // Category "automotive" is in the URL like: + // https://www....?cat_name=automotive&... + categoryName: 'cat_name', + subId: '123' + } + }] + }]; + +#### Example with `nq` + var adUnits = [{ + code: 'nano-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'nanointeractive', + params: { + pid: '5afaa0280ae8996eb578de53', + // User searched "automobile search query" (extracted from search text field) + nq: 'automobile search query', + subId: '123' + } + }] + }]; + +#### Example with `name` + var adUnits = [{ + code: 'nano-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'nanointeractive', + params: { + pid: '5afaa0280ae8996eb578de53', + // User searched "automobile search query" and it is in the URL like: + // https://www....?search_param=automobile%20search%20query&... + name: 'search_param', + subId: '123' + } + }] + }]; + +#### Example with `category` and `nq` + var adUnits = [{ + code: 'nano-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'nanointeractive', + params: { + pid: '5afaa0280ae8996eb578de53', + category: 'automotive', + nq: 'automobile search query', + subId: '123' + } + }] + }]; + +#### Example with `categoryName` and `name` + var adUnits = [{ + code: 'nano-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'nanointeractive', + params: { + pid: '5afaa0280ae8996eb578de53', + categoryName: 'cat_name', + name: 'search_param', + subId: '123' + } + }] + }]; \ No newline at end of file diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index 92b6fe8d797..f93cc546859 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -1,109 +1,789 @@ import { expect } from 'chai'; import * as utils from 'src/utils'; +import * as sinon from 'sinon'; import { - BIDDER_CODE, CATEGORY, DATA_PARTNER_PIXEL_ID, ENGINE_BASE_URL, NQ, NQ_NAME, SUB_ID, - spec + BIDDER_CODE, + CATEGORY, + CATEGORY_NAME, + DATA_PARTNER_PIXEL_ID, + ENGINE_BASE_URL, + NQ, + NQ_NAME, + REF, + spec, + SUB_ID } from '../../../modules/nanointeractiveBidAdapter'; describe('nanointeractive adapter tests', function () { - const SEARCH_QUERY = 'rumpelstiltskin'; - const WIDTH = 300; - const HEIGHT = 250; - const SIZES = [[WIDTH, HEIGHT]]; + const SIZES_PARAM = 'sizes'; + const BID_ID_PARAM = 'bidId'; + const BID_ID_VALUE = '24a1c9ec270973'; + const CORS_PARAM = 'cors'; + const DATA_PARTNER_PIXEL_ID_VALUE = 'pid1'; + const NQ_VALUE = 'rumpelstiltskin'; + const NQ_NAME_QUERY_PARAM = 'nqName'; + const CATEGORY_VALUE = 'some category'; + const CATEGORY_NAME_QUERY_PARAM = 'catName'; + const SUB_ID_VALUE = '123'; + const REF_NO_VALUE = 'none'; + const REF_OTHER_VALUE = 'other'; + const WIDTH1 = 300; + const HEIGHT1 = 250; + const WIDTH2 = 468; + const HEIGHT2 = 60; + const SIZES_VALUE = [[WIDTH1, HEIGHT1], [WIDTH2, HEIGHT2]]; const AD = ' '; const CPM = 1; - function getBid(isValid) { + function getBidResponse (pid, nq, category, subId, cors, ref) { + return { + [DATA_PARTNER_PIXEL_ID]: pid, + [NQ]: nq, + [CATEGORY]: category, + [SUB_ID]: subId, + [REF]: ref, + [SIZES_PARAM]: [WIDTH1 + 'x' + HEIGHT1, WIDTH2 + 'x' + HEIGHT2], + [BID_ID_PARAM]: BID_ID_VALUE, + [CORS_PARAM]: cors, + }; + } + function getBidRequest (params) { return { bidder: BIDDER_CODE, - params: (function () { - return { - [DATA_PARTNER_PIXEL_ID]: isValid === true ? 'pid1' : null, - [NQ]: SEARCH_QUERY, - [NQ_NAME]: null, - [CATEGORY]: null, - [SUB_ID]: null, - } - })(), + params: params, placementCode: 'div-gpt-ad-1460505748561-0', transactionId: 'ee335735-ddd3-41f2-b6c6-e8aa99f81c0f', - sizes: SIZES, - bidId: '24a1c9ec270973', + [SIZES_PARAM]: SIZES_VALUE, + [BID_ID_PARAM]: BID_ID_VALUE, bidderRequestId: '189135372acd55', auctionId: 'ac15bb68-4ef0-477f-93f4-de91c47f00a9' - } - } - - const SINGLE_BID_REQUEST = { - [DATA_PARTNER_PIXEL_ID]: 'pid1', - [NQ]: [SEARCH_QUERY, null], - [SUB_ID]: null, - sizes: [WIDTH + 'x' + HEIGHT], - bidId: '24a1c9ec270973', - cors: 'http://localhost' - }; - - function getSingleBidResponse(isValid) { - return { - id: '24a1c9ec270973', - cpm: isValid === true ? CPM : null, - width: WIDTH, - height: HEIGHT, - ad: AD, - ttl: 360, - creativeId: 'TEST_ID', - netRevenue: false, - currency: 'EUR', - } + }; } - const VALID_BID = { - requestId: '24a1c9ec270973', - cpm: CPM, - width: WIDTH, - height: HEIGHT, - ad: AD, - ttl: 360, - creativeId: 'TEST_ID', - netRevenue: false, - currency: 'EUR', - }; - describe('NanoAdapter', () => { let nanoBidAdapter = spec; describe('Methods', () => { - it('Test isBidRequestValid() with valid param', function () { - expect(nanoBidAdapter.isBidRequestValid(getBid(true))).to.equal(true); + it('Test isBidRequestValid() with valid param(s): pid', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + }))).to.equal(true); }); - it('Test isBidRequestValid() with invalid param', function () { - expect(nanoBidAdapter.isBidRequestValid(getBid(false))).to.equal(false); + it('Test isBidRequestValid() with valid param(s): pid, nq', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ, + }))).to.equal(true); }); - it('Test buildRequests()', function () { - let stub = sinon.stub(utils, 'getOrigin').callsFake(() => 'http://localhost'); - - let request = nanoBidAdapter.buildRequests([getBid(true)]); + it('Test isBidRequestValid() with valid param(s): pid, nq, category', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ, + [CATEGORY]: CATEGORY_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, categoryName', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ, + [CATEGORY_NAME_QUERY_PARAM]: CATEGORY_NAME_QUERY_PARAM, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName, category', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY]: CATEGORY_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName, categoryName', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY_NAME_QUERY_PARAM]: CATEGORY_NAME_QUERY_PARAM, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, category', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, category, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName, categoryName, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId, ref (value none)', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_NO_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId, ref (value other)', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_OTHER_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with invalid param(s): empty', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({}))).to.equal(false); + }); + it('Test isBidRequestValid() with invalid param(s): pid missing', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(false); + }); + it('Test buildRequest() - pid', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [null], + expectedCategory: [null], + expectedSubId: null, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); expect(request.method).to.equal('POST'); expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([SINGLE_BID_REQUEST])); - - stub.restore(); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, nq', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [NQ_VALUE], + expectedCategory: [null], + expectedSubId: null, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, nq, category', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [NQ_VALUE], + expectedCategory: [CATEGORY_VALUE], + expectedSubId: null, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, nq, categoryName', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [NQ_VALUE], + expectedCategory: [CATEGORY_VALUE], + expectedSubId: null, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, nq, subId', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [NQ_VALUE], + expectedCategory: [null], + expectedSubId: SUB_ID_VALUE, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, category', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [null], + expectedCategory: [CATEGORY_VALUE], + expectedSubId: null, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, category, subId', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [null], + expectedCategory: [CATEGORY_VALUE], + expectedSubId: SUB_ID_VALUE, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, subId', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [null], + expectedCategory: [null], + expectedSubId: SUB_ID_VALUE, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, nq, category, subId', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [NQ_VALUE], + expectedCategory: [CATEGORY_VALUE], + expectedSubId: SUB_ID_VALUE, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, nqName, categoryName, subId', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, + [SUB_ID]: SUB_ID_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [NQ_VALUE], + expectedCategory: [CATEGORY_VALUE], + expectedSubId: SUB_ID_VALUE, + expectedCors: mockOriginAddress, + expectedRef: mockRefAddress, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, nq, category, subId, ref (value none)', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_NO_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [NQ_VALUE], + expectedCategory: [CATEGORY_VALUE], + expectedSubId: SUB_ID_VALUE, + expectedCors: mockOriginAddress, + expectedRef: null, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); + }); + it('Test buildRequest() - pid, nq, category, subId, ref (value other)', function () { + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + let sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + let testInput = + { + requestParams: { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_OTHER_VALUE, + }, + expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, + expectedNq: [NQ_VALUE], + expectedCategory: [CATEGORY_VALUE], + expectedSubId: SUB_ID_VALUE, + expectedCors: mockOriginAddress, + expectedRef: null, + }; + let request = nanoBidAdapter.buildRequests([ + getBidRequest(testInput.requestParams)]); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENGINE_BASE_URL); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + testInput.expectedPid, + testInput.expectedNq, + testInput.expectedCategory, + testInput.expectedSubId, + testInput.expectedCors, + testInput.expectedRef + ), + ])); + sandbox.restore(); }); it('Test interpretResponse() length', function () { - let bids = nanoBidAdapter.interpretResponse({body: [getSingleBidResponse(true), getSingleBidResponse(false)]}); + let bids = nanoBidAdapter.interpretResponse({ + body: [ + // valid + { + id: '24a1c9ec270973', + cpm: CPM, + width: WIDTH1, + height: HEIGHT1, + ad: AD, + ttl: 360, + creativeId: 'TEST_ID', + netRevenue: false, + currency: 'EUR', + }, + // invalid + { + id: '24a1c9ec270973', + cpm: null, + width: WIDTH1, + height: HEIGHT1, + ad: AD, + ttl: 360, + creativeId: 'TEST_ID', + netRevenue: false, + currency: 'EUR', + } + ] + }); expect(bids.length).to.equal(1); }); it('Test interpretResponse() bids', function () { - let bid = nanoBidAdapter.interpretResponse({body: [getSingleBidResponse(true), getSingleBidResponse(false)]})[0]; - expect(bid.requestId).to.equal(VALID_BID.requestId); - expect(bid.cpm).to.equal(VALID_BID.cpm); - expect(bid.width).to.equal(VALID_BID.width); - expect(bid.height).to.equal(VALID_BID.height); - expect(bid.ad).to.equal(VALID_BID.ad); - expect(bid.ttl).to.equal(VALID_BID.ttl); - expect(bid.creativeId).to.equal(VALID_BID.creativeId); - expect(bid.currency).to.equal(VALID_BID.currency); + let bid = nanoBidAdapter.interpretResponse({ + body: [ + // valid + { + id: '24a1c9ec270973', + cpm: CPM, + width: WIDTH1, + height: HEIGHT1, + ad: AD, + ttl: 360, + creativeId: 'TEST_ID', + netRevenue: false, + currency: 'EUR', + }, + // invalid + { + id: '24a1c9ec270973', + cpm: null, + width: WIDTH1, + height: HEIGHT1, + ad: AD, + ttl: 360, + creativeId: 'TEST_ID', + netRevenue: false, + currency: 'EUR', + } + ] + })[0]; + expect(bid.requestId).to.equal('24a1c9ec270973'); + expect(bid.cpm).to.equal(CPM); + expect(bid.width).to.equal(WIDTH1); + expect(bid.height).to.equal(HEIGHT1); + expect(bid.ad).to.equal(AD); + expect(bid.ttl).to.equal(360); + expect(bid.creativeId).to.equal('TEST_ID'); + expect(bid.currency).to.equal('EUR'); }); }); }); From 043a3722656b836308fadf96f7c288f49380d26a Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 7 Jun 2018 17:57:37 -0600 Subject: [PATCH 0456/1594] fix the audienceNetwork tests comparison for pageurl (#2698) --- karma.conf.maker.js | 10 +++++----- test/spec/modules/audienceNetworkBidAdapter_spec.js | 13 +++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 5d075b6929c..0a4e10d9792 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -43,12 +43,12 @@ function newPluginsArray(browserstack) { ]; if (browserstack) { plugins.push('karma-browserstack-launcher'); - plugins.push('karma-firefox-launcher'); - plugins.push('karma-opera-launcher'); - plugins.push('karma-safari-launcher'); - plugins.push('karma-script-launcher'); - plugins.push('karma-ie-launcher'); } + plugins.push('karma-firefox-launcher'); + plugins.push('karma-opera-launcher'); + plugins.push('karma-safari-launcher'); + plugins.push('karma-script-launcher'); + plugins.push('karma-ie-launcher'); return plugins; } diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index 8a72b2ba658..2b4f87450e8 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -20,6 +20,7 @@ const playerwidth = 320; const playerheight = 180; const requestId = 'test-request-id'; const pbv = '$prebid.version$'; +const pageUrl = encodeURIComponent(utils.getTopWindowUrl()); describe('AudienceNetwork adapter', () => { describe('Public API', () => { @@ -139,7 +140,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&pbv=${pbv}` }]); }); @@ -158,7 +159,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['640x480'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&sdk[]=&pbv=${pbv}&playerwidth=640&playerheight=480` + data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=${pageUrl}&sdk[]=&pbv=${pbv}&playerwidth=640&playerheight=480` }]); }); @@ -177,7 +178,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['728x90'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&pbv=${pbv}` }]); }); @@ -196,7 +197,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&pbv=${pbv}` }]); }); @@ -410,7 +411,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.cpm).to.equal(1.23); expect(bidResponse.requestId).to.equal(requestId); expect(bidResponse.mediaType).to.equal('video'); - expect(bidResponse.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${placementId}&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${bidId}`); + expect(bidResponse.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${placementId}&pageurl=${pageUrl}&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${bidId}`); expect(bidResponse.width).to.equal(playerwidth); expect(bidResponse.height).to.equal(playerheight); }); @@ -450,7 +451,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseVideo.cpm).to.equal(1.23); expect(bidResponseVideo.requestId).to.equal(requestId); expect(bidResponseVideo.mediaType).to.equal('video'); - expect(bidResponseVideo.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${videoPlacementId}&pageurl=http%3A%2F%2Flocalhost%3A9876%2F&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${videoBidId}`); + expect(bidResponseVideo.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${videoPlacementId}&pageurl=${pageUrl}&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${videoBidId}`); expect(bidResponseVideo.width).to.equal(playerwidth); expect(bidResponseVideo.height).to.equal(playerheight); From 12c68056e16036ace2177e32d356291ac7182754 Mon Sep 17 00:00:00 2001 From: Pupis Date: Fri, 8 Jun 2018 16:42:13 +0300 Subject: [PATCH 0457/1594] Adform adapter supports string type sizes (#2692) * Allow to compare strings too. * Fixed lint errors --- modules/adformBidAdapter.js | 5 +- test/spec/modules/adformBidAdapter_spec.js | 58 +++++++++++++++++----- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index 2814f587965..889c8ba4813 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -114,13 +114,12 @@ export const spec = { bidRespones.push(bidObject); } } - return bidRespones; function verifySize(adItem, validSizes) { for (var j = 0, k = validSizes.length; j < k; j++) { - if (adItem.width === validSizes[j][0] && - adItem.height === validSizes[j][1]) { + if (adItem.width == validSizes[j][0] && + adItem.height == validSizes[j][1]) { return true; } } diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index 90de34b990d..d888b4b7a5b 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -153,19 +153,6 @@ describe('Adform adapter', () => { let result = spec.interpretResponse({ body: {} }, {}); assert.deepEqual(result, []); }); - it('should respond with empty response when sizes doesn\'t match', () => { - serverResponse.body[0].response = 'banner'; - serverResponse.body[0].width = 100; - serverResponse.body[0].height = 150; - - serverResponse.body = [serverResponse.body[0]]; - bidRequest.bids = [bidRequest.bids[0]]; - let result = spec.interpretResponse(serverResponse, bidRequest); - - assert.equal(serverResponse.body.length, 1); - assert.equal(serverResponse.body[0].response, 'banner'); - assert.deepEqual(result, []); - }); it('should respond with empty response when response from server is not banner', () => { serverResponse.body[0].response = 'not banner'; serverResponse.body = [serverResponse.body[0]]; @@ -250,6 +237,51 @@ describe('Adform adapter', () => { assert.ok(!result[i].gdpr); assert.ok(!result[i].gdpr_consent); }; + }); + + describe('verifySizes', () => { + it('should respond with empty response when sizes doesn\'t match', () => { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 100; + serverResponse.body[0].height = 150; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(serverResponse.body.length, 1); + assert.equal(serverResponse.body[0].response, 'banner'); + assert.deepEqual(result, []); + }); + it('should respond with empty response when sizes as a strings doesn\'t match', () => { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 100; + serverResponse.body[0].height = 150; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + + bidRequest.bids[0].sizes = [['101', '150']]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(serverResponse.body.length, 1); + assert.equal(serverResponse.body[0].response, 'banner'); + assert.deepEqual(result, []); + }); + it('should support size dimensions as a strings', () => { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 300; + serverResponse.body[0].height = 600; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + + bidRequest.bids[0].sizes = [['300', '250'], ['250', '300'], ['300', '600'], ['600', '300']] + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(result[0].width, 300); + assert.equal(result[0].height, 600); + }); }) }); From 15b017b1b21e177d16d9017cc5dbeaaa9fddc7af Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Fri, 8 Jun 2018 11:30:24 -0400 Subject: [PATCH 0458/1594] typo in yml file (#2703) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4501da64c99..bd4df66b5b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ node_js: env: - BROWSERSTACK_USERNAME=info184 addons: - chrome: stable, + chrome: stable browserstack: username: info184 access_key: From 1d318f9cd29bac9e5818f434e3abf250f105e8e4 Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Fri, 8 Jun 2018 21:41:31 +0530 Subject: [PATCH 0459/1594] Media.net Adapter Improvements (#2634) * Media.net adapter: passing slot visibility to server * Media.net adapter: changed slot visibility logic and removed mocks on window properties * Media.net adapter: refactored slot-visibility tests to use beforeEach and afterEach hooks * create only one sandbox and restore for medianet --- modules/medianetBidAdapter.js | 93 ++++++++- test/spec/modules/medianetBidAdapter_spec.js | 207 ++++++++++++++++++- 2 files changed, 288 insertions(+), 12 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 08232231417..4ff7bfd000e 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -4,6 +4,11 @@ import { config } from 'src/config'; const BIDDER_CODE = 'medianet'; const BID_URL = '//prebid.media.net/rtb/prebid'; +const SLOT_VISIBILITY = { + NOT_DETERMINED: 0, + ABOVE_THE_FOLD: 1, + BELOW_THE_FOLD: 2 +}; $$PREBID_GLOBAL$$.medianetGlobals = {}; @@ -71,6 +76,31 @@ function getSize(size) { } } +function getWindowSize() { + return { + w: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || -1, + h: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || -1 + } +} + +function getCoordinates(id) { + const element = document.getElementById(id); + if (element && element.getBoundingClientRect) { + const rect = element.getBoundingClientRect(); + let coordinates = {}; + coordinates.top_left = { + y: rect.top, + x: rect.left + }; + coordinates.bottom_right = { + y: rect.bottom, + x: rect.right + }; + return coordinates + } + return null; +} + function extParams(params, gdpr) { let ext = { customer_id: params.cid, @@ -80,6 +110,10 @@ function extParams(params, gdpr) { if (ext.gdpr_applies) { ext.gdpr_consent_string = gdpr.consentString || ''; } + let windowSize = spec.getWindowSize(); + if (windowSize.w !== -1 && windowSize.h !== -1) { + ext.screen = windowSize; + } return ext; } @@ -102,9 +136,64 @@ function slotParams(bidRequest) { if (bidFloor) { params.bidfloor = bidFloor; } + const coordinates = getCoordinates(bidRequest.adUnitCode); + if (coordinates) { + let normCoordinates = normalizeCoordinates(coordinates); + params.ext.coordinates = normCoordinates; + params.ext.viewability = getSlotVisibility(coordinates.top_left, getMinSize(params.banner)); + if (getSlotVisibility(normCoordinates.top_left, getMinSize(params.banner)) > 0.5) { + params.ext.visibility = SLOT_VISIBILITY.ABOVE_THE_FOLD; + } else { + params.ext.visibility = SLOT_VISIBILITY.BELOW_THE_FOLD; + } + } else { + params.ext.visibility = SLOT_VISIBILITY.NOT_DETERMINED; + } + return params; } +function getMinSize(sizes) { + return sizes.reduce((min, size) => size.h * size.w < min.h * min.w ? size : min); +} + +function getSlotVisibility(topLeft, size) { + let maxArea = size.w * size.h; + let windowSize = spec.getWindowSize(); + let bottomRight = { + x: topLeft.x + size.w, + y: topLeft.y + size.h + }; + if (maxArea === 0 || windowSize.w === -1 || windowSize.h === -1) { + return 0; + } + + return getOverlapArea(topLeft, bottomRight, {x: 0, y: 0}, {x: windowSize.w, y: windowSize.h}) / maxArea; +} + +// find the overlapping area between two rectangles +function getOverlapArea(topLeft1, bottomRight1, topLeft2, bottomRight2) { + // If no overlap, return 0 + if ((topLeft1.x > bottomRight2.x || bottomRight1.x < topLeft2.x) || (topLeft1.y > bottomRight2.y || bottomRight1.y < topLeft2.y)) { + return 0; + } + // return overlapping area : [ min of rightmost/bottommost co-ordinates ] - [ max of leftmost/topmost co-ordinates ] + return ((Math.min(bottomRight1.x, bottomRight2.x) - Math.max(topLeft1.x, topLeft2.x)) * (Math.min(bottomRight1.y, bottomRight2.y) - Math.max(topLeft1.y, topLeft2.y))); +} + +function normalizeCoordinates(coordinates) { + return { + top_left: { + x: coordinates.top_left.x + window.pageXOffset, + y: coordinates.top_left.y + window.pageYOffset, + }, + bottom_right: { + x: coordinates.bottom_right.x + window.pageXOffset, + y: coordinates.bottom_right.y + window.pageYOffset, + } + } +} + function generatePayload(bidRequests, bidderRequests) { return { site: siteDetails(bidRequests[0].params.site), @@ -204,6 +293,8 @@ export const spec = { if (syncOptions.pixelEnabled) { return filterUrlsByType(cookieSyncUrls, 'image'); } - } + }, + + getWindowSize, }; registerBidder(spec); diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index a10dcb2624d..d94cb64c145 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -82,12 +82,28 @@ let VALID_BID_REQUEST = [{ 'customer_id': 'customer_id', 'prebid_version': $$PREBID_GLOBAL$$.version, 'gdpr_applies': false, + 'screen': { + 'w': 1000, + 'h': 1000 + } }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-0' + 'dfp_id': 'div-gpt-ad-1460505748561-0', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + } }, 'banner': [{ 'w': 300, @@ -105,7 +121,19 @@ let VALID_BID_REQUEST = [{ }, { 'id': '3f97ca71b1e5c2', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-123' + 'dfp_id': 'div-gpt-ad-1460505748561-123', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + } }, 'banner': [{ 'w': 300, @@ -131,13 +159,29 @@ let VALID_BID_REQUEST = [{ 'ext': { 'customer_id': 'customer_id', 'prebid_version': $$PREBID_GLOBAL$$.version, - 'gdpr_applies': false + 'gdpr_applies': false, + 'screen': { + 'w': 1000, + 'h': 1000 + } }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-0' + 'dfp_id': 'div-gpt-ad-1460505748561-0', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + } }, 'banner': [{ 'w': 300, @@ -154,7 +198,19 @@ let VALID_BID_REQUEST = [{ }, { 'id': '3f97ca71b1e5c2', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-123' + 'dfp_id': 'div-gpt-ad-1460505748561-123', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + } }, 'banner': [{ 'w': 300, @@ -339,7 +395,7 @@ let VALID_BID_REQUEST = [{ 'consentString': 'consentString', 'gdprApplies': true, }, - 'timeout': 3000, + 'timeout': 3000 }, VALID_PAYLOAD_FOR_GDPR = { 'site': { @@ -352,12 +408,28 @@ let VALID_BID_REQUEST = [{ 'prebid_version': $$PREBID_GLOBAL$$.version, 'gdpr_consent_string': 'consentString', 'gdpr_applies': true, + 'screen': { + 'w': 1000, + 'h': 1000 + } }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-0' + 'dfp_id': 'div-gpt-ad-1460505748561-0', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + } }, 'banner': [{ 'w': 300, @@ -374,7 +446,19 @@ let VALID_BID_REQUEST = [{ }, { 'id': '3f97ca71b1e5c2', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-123' + 'dfp_id': 'div-gpt-ad-1460505748561-123', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + } }, 'banner': [{ 'w': 300, @@ -393,6 +477,15 @@ let VALID_BID_REQUEST = [{ }; describe('Media.net bid adapter', () => { + let sandbox; + beforeEach(() => { + sandbox = sinon.sandbox.create(); + }); + + afterEach(() => { + sandbox.restore(); + }); + describe('isBidRequestValid', () => { it('should accept valid bid params', () => { let isValid = spec.isBidRequestValid(VALID_PARAMS); @@ -416,6 +509,27 @@ describe('Media.net bid adapter', () => { }); describe('buildRequests', () => { + beforeEach(() => { + let documentStub = sandbox.stub(document, 'getElementById'); + let boundingRect = { + top: 50, + left: 50, + bottom: 100, + right: 100 + }; + documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ + getBoundingClientRect: () => boundingRect + }); + documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + getBoundingClientRect: () => boundingRect + }); + let windowSizeStub = sandbox.stub(spec, 'getWindowSize'); + windowSizeStub.returns({ + w: 1000, + h: 1000 + }); + }); + it('should build valid payload on bid', () => { let requestObj = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); expect(JSON.parse(requestObj.data)).to.deep.equal(VALID_PAYLOAD); @@ -438,7 +552,6 @@ describe('Media.net bid adapter', () => { describe('build requests: when page meta-data is available', () => { it('should pass canonical, twitter and fb paramters if available', () => { - let sandbox = sinon.sandbox.create(); let documentStub = sandbox.stub(window.top.document, 'querySelector'); documentStub.withArgs('link[rel="canonical"]').returns({ href: 'http://localhost:9999/canonical-test' @@ -451,11 +564,83 @@ describe('Media.net bid adapter', () => { }); let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_PAGE_META); - sandbox.restore(); }); }); }); + describe('slot visibility', () => { + let documentStub; + beforeEach(() => { + let windowSizeStub = sandbox.stub(spec, 'getWindowSize'); + windowSizeStub.returns({ + w: 1000, + h: 1000 + }); + documentStub = sandbox.stub(document, 'getElementById'); + }); + it('slot visibility should be 2 and ratio 0 when ad unit is BTF', () => { + let boundingRect = { + top: 1010, + left: 1010, + bottom: 1050, + right: 1050 + }; + documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ + getBoundingClientRect: () => boundingRect + }); + documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + getBoundingClientRect: () => boundingRect + }); + + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + let data = JSON.parse(bidReq.data); + expect(data.imp[0].ext.visibility).to.equal(2); + expect(data.imp[0].ext.viewability).to.equal(0); + }); + it('slot visibility should be 2 and ratio < 0.5 when ad unit is partially inside viewport', () => { + let boundingRect = { + top: 990, + left: 990, + bottom: 1050, + right: 1050 + }; + documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ + getBoundingClientRect: () => boundingRect + }); + documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + getBoundingClientRect: () => boundingRect + }); + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + let data = JSON.parse(bidReq.data); + expect(data.imp[0].ext.visibility).to.equal(2); + expect(data.imp[0].ext.viewability).to.equal(100 / 75000); + }); + it('slot visibility should be 1 and ratio > 0.5 when ad unit mostly in viewport', () => { + let boundingRect = { + top: 800, + left: 800, + bottom: 1050, + right: 1050 + }; + documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ + getBoundingClientRect: () => boundingRect + }); + documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + getBoundingClientRect: () => boundingRect + }); + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + let data = JSON.parse(bidReq.data); + expect(data.imp[0].ext.visibility).to.equal(1); + expect(data.imp[0].ext.viewability).to.equal(40000 / 75000); + }); + it('co-ordinates should not be sent and slot visibility should be 0 when ad unit is not present', () => { + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + let data = JSON.parse(bidReq.data); + expect(data.imp[1].ext).to.not.have.ownPropertyDescriptor('viewability'); + expect(data.imp[1].ext.visibility).to.equal(0); + }); + }); + describe('getUserSyncs', () => { it('should exclude iframe syncs if iframe is disabled', () => { let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_PIXEL_ENABLED, SERVER_CSYNC_RESPONSE); @@ -489,7 +674,7 @@ describe('Media.net bid adapter', () => { it('should not push response if no-bid', () => { let validBids = []; let bids = spec.interpretResponse(SERVER_RESPONSE_NOBID, []); - expect(bids).to.deep.equal(validBids) + expect(bids).to.deep.equal(validBids); }); }); }); From 0a503660a4d4606c1a90ccc9a6e68076c9a5cacd Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Fri, 8 Jun 2018 13:06:36 -0400 Subject: [PATCH 0460/1594] reupload package-lock.json file (#2701) * reupload package-lock.json file * commit to fix travis build * merge 'master' branch into 'upload_package-lock-json_file' branch --- package-lock.json | 17334 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 17334 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000000..3ba5921d852 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,17334 @@ +{ + "name": "prebid.js", + "version": "1.15.0-pre", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@gulp-sourcemaps/identity-map": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/@gulp-sourcemaps%2fidentity-map/-/identity-map-1.0.1.tgz", + "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", + "requires": { + "acorn": "5.6.2", + "css": "2.2.3", + "normalize-path": "2.1.1", + "source-map": "0.5.7", + "through2": "2.0.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/@gulp-sourcemaps%2fmap-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "requires": { + "normalize-path": "2.1.1", + "through2": "2.0.3" + } + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://npm.corp.appnexus.com/@sindresorhus%2fis/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "dev": true + }, + "@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/@sinonjs%2fformatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "dev": true, + "requires": { + "samsam": "1.3.0" + } + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://npm.corp.appnexus.com/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "accepts": { + "version": "1.2.13", + "resolved": "https://npm.corp.appnexus.com/accepts/-/accepts-1.2.13.tgz", + "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "dev": true, + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.5.3" + } + }, + "acorn": { + "version": "5.6.2", + "resolved": "https://npm.corp.appnexus.com/acorn/-/acorn-5.6.2.tgz", + "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw==" + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://npm.corp.appnexus.com/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://npm.corp.appnexus.com/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "addressparser": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/addressparser/-/addressparser-1.0.1.tgz", + "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", + "dev": true, + "optional": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://npm.corp.appnexus.com/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.2.0", + "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-4.2.0.tgz", + "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", + "dev": true, + "requires": { + "es6-promisify": "5.0.0" + } + }, + "ajv": { + "version": "6.2.0", + "resolved": "https://npm.corp.appnexus.com/ajv/-/ajv-6.2.0.tgz", + "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", + "dev": true, + "requires": { + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://npm.corp.appnexus.com/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "amqplib": { + "version": "0.5.2", + "resolved": "https://npm.corp.appnexus.com/amqplib/-/amqplib-0.5.2.tgz", + "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", + "dev": true, + "optional": true, + "requires": { + "bitsyntax": "0.0.4", + "bluebird": "3.5.1", + "buffer-more-ints": "0.0.2", + "readable-stream": "1.1.14", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true, + "optional": true + } + } + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://npm.corp.appnexus.com/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "1.0.0" + } + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "2.0.0" + } + }, + "archiver": { + "version": "0.14.4", + "resolved": "https://npm.corp.appnexus.com/archiver/-/archiver-0.14.4.tgz", + "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", + "dev": true, + "requires": { + "async": "0.9.2", + "buffer-crc32": "0.2.13", + "glob": "4.3.5", + "lazystream": "0.1.0", + "lodash": "3.2.0", + "readable-stream": "1.0.34", + "tar-stream": "1.1.5", + "zip-stream": "0.5.2" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://npm.corp.appnexus.com/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "glob": { + "version": "4.3.5", + "resolved": "https://npm.corp.appnexus.com/glob/-/glob-4.3.5.tgz", + "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lazystream": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/lazystream/-/lazystream-0.1.0.tgz", + "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + } + }, + "lodash": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://npm.corp.appnexus.com/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-iterate": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/array-iterate/-/array-iterate-1.1.2.tgz", + "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://npm.corp.appnexus.com/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "array.from": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/array.from/-/array.from-0.2.0.tgz", + "integrity": "sha1-LGJ7G3bf8t7yNl+gUrZcPVheX2s=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://npm.corp.appnexus.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://npm.corp.appnexus.com/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://npm.corp.appnexus.com/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://npm.corp.appnexus.com/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://npm.corp.appnexus.com/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.11.5", + "resolved": "https://npm.corp.appnexus.com/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://npm.corp.appnexus.com/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://npm.corp.appnexus.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://npm.corp.appnexus.com/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://npm.corp.appnexus.com/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", + "dev": true + }, + "axios": { + "version": "0.15.3", + "resolved": "https://npm.corp.appnexus.com/axios/-/axios-0.15.3.tgz", + "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", + "dev": true, + "optional": true, + "requires": { + "follow-redirects": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/follow-redirects/-/follow-redirects-1.0.0.tgz", + "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9" + } + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-core/-/babel-core-6.22.0.tgz", + "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "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.10", + "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://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://npm.corp.appnexus.com/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.10", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "esutils": "2.0.2" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-loader": { + "version": "7.1.4", + "resolved": "https://npm.corp.appnexus.com/babel-loader/-/babel-loader-7.1.4.tgz", + "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", + "dev": true, + "requires": { + "find-cache-dir": "1.0.0", + "loader-utils": "1.1.0", + "mkdirp": "0.5.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://npm.corp.appnexus.com/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", + "dev": true + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", + "dev": true + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", + "dev": true + }, + "babel-plugin-syntax-do-expressions": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", + "dev": true + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", + "dev": true + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, + "babel-plugin-syntax-function-bind": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", + "dev": true + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-system-import-transformer": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", + "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0" + } + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "dev": true, + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-decorators-legacy": { + "version": "1.3.5", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", + "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", + "dev": true, + "requires": { + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-do-expressions": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.10" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-function-bind": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-assign": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "6.26.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://npm.corp.appnexus.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "3.2.8", + "invariant": "2.2.4", + "semver": "5.5.0" + } + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://npm.corp.appnexus.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0" + } + }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-self": "6.22.0", + "babel-plugin-transform-react-jsx-source": "6.22.0", + "babel-preset-flow": "6.23.0" + } + }, + "babel-preset-stage-0": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", + "dev": true, + "requires": { + "babel-plugin-transform-do-expressions": "6.22.0", + "babel-plugin-transform-function-bind": "6.22.0", + "babel-preset-stage-1": "6.24.1" + } + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "dev": true, + "requires": { + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://npm.corp.appnexus.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "home-or-tmp": "2.0.0", + "lodash": "4.17.10", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "babel-core": { + "version": "6.26.3", + "resolved": "https://npm.corp.appnexus.com/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.1", + "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.10", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/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.10" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/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.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.10" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://npm.corp.appnexus.com/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.10", + "to-fast-properties": "1.0.3" + } + }, + "babelify": { + "version": "8.0.0", + "resolved": "https://npm.corp.appnexus.com/babelify/-/babelify-8.0.0.tgz", + "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw==", + "dev": true + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://npm.corp.appnexus.com/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "bail": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/bail/-/bail-1.0.3.tgz", + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://npm.corp.appnexus.com/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "base64-url": { + "version": "1.2.1", + "resolved": "https://npm.corp.appnexus.com/base64-url/-/base64-url-1.2.1.tgz", + "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "basic-auth": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/basic-auth/-/basic-auth-1.0.4.tgz", + "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", + "dev": true + }, + "basic-auth-connect": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", + "dev": true + }, + "batch": { + "version": "0.5.3", + "resolved": "https://npm.corp.appnexus.com/batch/-/batch-0.5.3.tgz", + "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "0.1.1", + "chainsaw": "0.1.0" + } + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://npm.corp.appnexus.com/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "binaryextensions": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/binaryextensions/-/binaryextensions-1.0.1.tgz", + "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", + "dev": true + }, + "bitsyntax": { + "version": "0.0.4", + "resolved": "https://npm.corp.appnexus.com/bitsyntax/-/bitsyntax-0.0.4.tgz", + "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "dev": true, + "optional": true, + "requires": { + "buffer-more-ints": "0.0.2" + } + }, + "bl": { + "version": "0.9.5", + "resolved": "https://npm.corp.appnexus.com/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "blob": { + "version": "0.0.4", + "resolved": "https://npm.corp.appnexus.com/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "dev": true + }, + "block-loader": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/block-loader/-/block-loader-2.1.0.tgz", + "integrity": "sha1-u7OYrVqEPGxx95opb0tt9LAlcxI=", + "dev": true + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://npm.corp.appnexus.com/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://npm.corp.appnexus.com/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body": { + "version": "5.1.0", + "resolved": "https://npm.corp.appnexus.com/body/-/body-5.1.0.tgz", + "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", + "dev": true, + "requires": { + "continuable-cache": "0.3.1", + "error": "7.0.2", + "raw-body": "1.1.7", + "safe-json-parse": "1.0.1" + } + }, + "body-parser": { + "version": "1.13.3", + "resolved": "https://npm.corp.appnexus.com/body-parser/-/body-parser-1.13.3.tgz", + "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", + "dev": true, + "requires": { + "bytes": "2.1.0", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.0.1", + "http-errors": "1.3.1", + "iconv-lite": "0.4.11", + "on-finished": "2.3.0", + "qs": "4.0.0", + "raw-body": "2.1.7", + "type-is": "1.6.16" + }, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "2.4.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + } + } + } + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://npm.corp.appnexus.com/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://npm.corp.appnexus.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://npm.corp.appnexus.com/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.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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://npm.corp.appnexus.com/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://npm.corp.appnexus.com/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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.1", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/browserify-des/-/browserify-des-1.0.1.tgz", + "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://npm.corp.appnexus.com/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.1" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://npm.corp.appnexus.com/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000851", + "electron-to-chromium": "1.3.48" + } + }, + "browserstack": { + "version": "1.5.0", + "resolved": "https://npm.corp.appnexus.com/browserstack/-/browserstack-1.5.0.tgz", + "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", + "dev": true, + "requires": { + "https-proxy-agent": "1.0.0" + }, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "semver": { + "version": "5.0.3", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "browserstacktunnel-wrapper": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.2.tgz", + "integrity": "sha512-7w7HYA00qjBtuQH0c5rqW7RbWPHyRROqTZofwNp5G0sKc2fYChsTfbHz3ul8Yd+ffkQvR81m+iPjEB004P6kxQ==", + "dev": true, + "requires": { + "https-proxy-agent": "1.0.0", + "unzip": "0.1.11" + }, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "semver": { + "version": "5.0.3", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://npm.corp.appnexus.com/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.3.0", + "ieee754": "1.1.11", + "isarray": "1.0.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://npm.corp.appnexus.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "dev": true + }, + "buffer-more-ints": { + "version": "0.0.2", + "resolved": "https://npm.corp.appnexus.com/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true + }, + "buildmail": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/buildmail/-/buildmail-4.0.1.tgz", + "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", + "dev": true, + "optional": true, + "requires": { + "addressparser": "1.0.1", + "libbase64": "0.1.0", + "libmime": "3.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.6.0", + "nodemailer-shared": "1.1.0", + "punycode": "1.4.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "bytes": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/cache-base/-/cache-base-1.0.1.tgz", + "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" + } + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://npm.corp.appnexus.com/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "dev": true, + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + } + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caniuse-lite": { + "version": "1.0.30000851", + "resolved": "https://npm.corp.appnexus.com/caniuse-lite/-/caniuse-lite-1.0.30000851.tgz", + "integrity": "sha512-Y1ecA1cL9wg0vni8t33nBw/poX8ypm+2c3fbwAESj8cm4ufK9CBFQ1+nUK8Dp5dtFo5Fc3JzkI5DKmQbuIo6hQ==", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://npm.corp.appnexus.com/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "ccount": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/ccount/-/ccount-1.0.3.tgz", + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/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": "3.5.0", + "resolved": "https://npm.corp.appnexus.com/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + } + }, + "chai-nightwatch": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", + "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", + "dev": true, + "requires": { + "assertion-error": "1.0.0", + "deep-eql": "0.1.3" + }, + "dependencies": { + "assertion-error": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/assertion-error/-/assertion-error-1.0.0.tgz", + "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", + "dev": true + } + } + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "requires": { + "traverse": "0.3.9" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "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" + } + }, + "character-entities": { + "version": "1.2.2", + "resolved": "https://npm.corp.appnexus.com/character-entities/-/character-entities-1.2.2.tgz", + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", + "dev": true + }, + "character-entities-html4": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz", + "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", + "dev": true + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://npm.corp.appnexus.com/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "2.0.3", + "resolved": "https://npm.corp.appnexus.com/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/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", + "resolved": "https://npm.corp.appnexus.com/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://npm.corp.appnexus.com/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://npm.corp.appnexus.com/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "clone": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "1.0.0" + } + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://npm.corp.appnexus.com/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collapse-white-space": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz", + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://npm.corp.appnexus.com/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://npm.corp.appnexus.com/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://npm.corp.appnexus.com/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colors": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/colors/-/colors-1.3.0.tgz", + "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==", + "dev": true + }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true, + "requires": { + "lodash": "4.17.10" + } + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://npm.corp.appnexus.com/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "comma-separated-tokens": { + "version": "1.0.5", + "resolved": "https://npm.corp.appnexus.com/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", + "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", + "dev": true, + "requires": { + "trim": "0.0.1" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compare-versions": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/compare-versions/-/compare-versions-3.2.1.tgz", + "integrity": "sha512-2y2nHcopMG/NAyk6vWXlLs86XeM9sik4jmx1tKIgzMi9/RQ2eo758RGpxQO3ErihHmg0RlQITPqgz73y6s7quA==", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://npm.corp.appnexus.com/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://npm.corp.appnexus.com/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compress-commons": { + "version": "0.2.9", + "resolved": "https://npm.corp.appnexus.com/compress-commons/-/compress-commons-0.2.9.tgz", + "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "crc32-stream": "0.3.4", + "node-int64": "0.3.3", + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "compressible": { + "version": "2.0.14", + "resolved": "https://npm.corp.appnexus.com/compressible/-/compressible-2.0.14.tgz", + "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", + "dev": true, + "requires": { + "mime-db": "1.34.0" + }, + "dependencies": { + "mime-db": { + "version": "1.34.0", + "resolved": "https://npm.corp.appnexus.com/mime-db/-/mime-db-1.34.0.tgz", + "integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o=", + "dev": true + } + } + }, + "compression": { + "version": "1.5.2", + "resolved": "https://npm.corp.appnexus.com/compression/-/compression-1.5.2.tgz", + "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", + "dev": true, + "requires": { + "accepts": "1.2.13", + "bytes": "2.1.0", + "compressible": "2.0.14", + "debug": "2.2.0", + "on-headers": "1.0.1", + "vary": "1.0.1" + }, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://npm.corp.appnexus.com/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "0.6.1" + } + }, + "connect": { + "version": "2.30.2", + "resolved": "https://npm.corp.appnexus.com/connect/-/connect-2.30.2.tgz", + "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", + "dev": true, + "requires": { + "basic-auth-connect": "1.0.0", + "body-parser": "1.13.3", + "bytes": "2.1.0", + "compression": "1.5.2", + "connect-timeout": "1.6.2", + "content-type": "1.0.4", + "cookie": "0.1.3", + "cookie-parser": "1.3.5", + "cookie-signature": "1.0.6", + "csurf": "1.8.3", + "debug": "2.2.0", + "depd": "1.0.1", + "errorhandler": "1.4.3", + "express-session": "1.11.3", + "finalhandler": "0.4.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "method-override": "2.3.10", + "morgan": "1.6.1", + "multiparty": "3.3.2", + "on-headers": "1.0.1", + "parseurl": "1.3.2", + "pause": "0.1.0", + "qs": "4.0.0", + "response-time": "2.3.2", + "serve-favicon": "2.3.2", + "serve-index": "1.7.3", + "serve-static": "1.10.3", + "type-is": "1.6.16", + "utils-merge": "1.0.0", + "vhost": "3.0.2" + }, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + } + } + }, + "connect-livereload": { + "version": "0.5.4", + "resolved": "https://npm.corp.appnexus.com/connect-livereload/-/connect-livereload-0.5.4.tgz", + "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", + "dev": true + }, + "connect-timeout": { + "version": "1.6.2", + "resolved": "https://npm.corp.appnexus.com/connect-timeout/-/connect-timeout-1.6.2.tgz", + "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", + "dev": true, + "requires": { + "debug": "2.2.0", + "http-errors": "1.3.1", + "ms": "0.7.1", + "on-headers": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "continuable-cache": { + "version": "0.3.1", + "resolved": "https://npm.corp.appnexus.com/continuable-cache/-/continuable-cache-0.3.1.tgz", + "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://npm.corp.appnexus.com/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "cookie": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/cookie/-/cookie-0.1.3.tgz", + "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", + "dev": true + }, + "cookie-parser": { + "version": "1.3.5", + "resolved": "https://npm.corp.appnexus.com/cookie-parser/-/cookie-parser-1.3.5.tgz", + "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://npm.corp.appnexus.com/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://npm.corp.appnexus.com/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "coveralls": { + "version": "2.13.3", + "resolved": "https://npm.corp.appnexus.com/coveralls/-/coveralls-2.13.3.tgz", + "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "dev": true, + "requires": { + "js-yaml": "3.6.1", + "lcov-parse": "0.0.10", + "log-driver": "1.2.5", + "minimist": "1.2.0", + "request": "2.79.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "crc": { + "version": "3.3.0", + "resolved": "https://npm.corp.appnexus.com/crc/-/crc-3.3.0.tgz", + "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", + "dev": true + }, + "crc32-stream": { + "version": "0.3.4", + "resolved": "https://npm.corp.appnexus.com/crc32-stream/-/crc32-stream-0.3.4.tgz", + "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://npm.corp.appnexus.com/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/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.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://npm.corp.appnexus.com/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://npm.corp.appnexus.com/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://npm.corp.appnexus.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.1", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.3", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.0.16", + "public-encrypt": "4.0.2", + "randombytes": "2.0.6", + "randomfill": "1.0.4" + } + }, + "csrf": { + "version": "3.0.6", + "resolved": "https://npm.corp.appnexus.com/csrf/-/csrf-3.0.6.tgz", + "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "dev": true, + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.5", + "uid-safe": "2.1.4" + } + }, + "css": { + "version": "2.2.3", + "resolved": "https://npm.corp.appnexus.com/css/-/css-2.2.3.tgz", + "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.5.2", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "css-loader": { + "version": "0.9.1", + "resolved": "https://npm.corp.appnexus.com/css-loader/-/css-loader-0.9.1.tgz", + "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", + "dev": true, + "optional": true, + "requires": { + "csso": "1.3.12", + "loader-utils": "0.2.17", + "source-map": "0.1.43" + }, + "dependencies": { + "loader-utils": { + "version": "0.2.17", + "resolved": "https://npm.corp.appnexus.com/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "optional": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "2.2.3" + } + }, + "css-value": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/css-value/-/css-value-0.0.1.tgz", + "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", + "dev": true + }, + "csso": { + "version": "1.3.12", + "resolved": "https://npm.corp.appnexus.com/csso/-/csso-1.3.12.tgz", + "integrity": "sha1-/GKGlKLTiTiqrEmWdTIY/TEc254=", + "dev": true, + "optional": true + }, + "csurf": { + "version": "1.8.3", + "resolved": "https://npm.corp.appnexus.com/csurf/-/csurf-1.8.3.tgz", + "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6", + "csrf": "3.0.6", + "http-errors": "1.3.1" + } + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://npm.corp.appnexus.com/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://npm.corp.appnexus.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "d": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "0.10.45" + } + }, + "dargs": { + "version": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://npm.corp.appnexus.com/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", + "dev": true + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://npm.corp.appnexus.com/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "debug-fabulous": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "requires": { + "debug": "3.1.0", + "memoizee": "0.4.12", + "object-assign": "4.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://npm.corp.appnexus.com/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "1.0.0" + } + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "deepmerge": { + "version": "0.2.10", + "resolved": "https://npm.corp.appnexus.com/deepmerge/-/deepmerge-0.2.10.tgz", + "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", + "dev": true + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "3.0.0" + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.4" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "dev": true, + "requires": { + "ast-types": "0.11.5", + "escodegen": "1.8.1", + "esprima": "3.1.3" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://npm.corp.appnexus.com/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.0.1.tgz", + "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detab": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/detab/-/detab-2.0.1.tgz", + "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", + "dev": true, + "requires": { + "repeat-string": "1.6.1" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + }, + "detective": { + "version": "4.7.1", + "resolved": "https://npm.corp.appnexus.com/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true, + "requires": { + "acorn": "5.6.2", + "defined": "1.0.0" + } + }, + "di": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "1.4.0", + "resolved": "https://npm.corp.appnexus.com/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://npm.corp.appnexus.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "disparity": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/disparity/-/disparity-2.0.0.tgz", + "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "diff": "1.4.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://npm.corp.appnexus.com/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "doctrine-temporary-fork": { + "version": "2.0.0-alpha-allowarrayindex", + "resolved": "https://npm.corp.appnexus.com/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", + "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "documentation": { + "version": "5.5.0", + "resolved": "https://npm.corp.appnexus.com/documentation/-/documentation-5.5.0.tgz", + "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "babel-core": "6.26.3", + "babel-generator": "6.26.1", + "babel-plugin-system-import-transformer": "3.1.0", + "babel-plugin-transform-decorators-legacy": "1.3.5", + "babel-preset-env": "1.7.0", + "babel-preset-react": "6.24.1", + "babel-preset-stage-0": "6.24.1", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babelify": "8.0.0", + "babylon": "6.18.0", + "chalk": "2.4.1", + "chokidar": "2.0.3", + "concat-stream": "1.6.2", + "disparity": "2.0.0", + "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", + "get-port": "3.2.0", + "git-url-parse": "8.3.1", + "github-slugger": "1.2.0", + "glob": "7.1.2", + "globals-docs": "2.4.0", + "highlight.js": "9.12.0", + "js-yaml": "3.12.0", + "lodash": "4.17.10", + "mdast-util-inject": "1.1.0", + "micromatch": "3.1.10", + "mime": "1.6.0", + "module-deps-sortable": "4.0.6", + "parse-filepath": "1.0.2", + "pify": "3.0.0", + "read-pkg-up": "3.0.0", + "remark": "9.0.0", + "remark-html": "7.0.0", + "remark-reference-links": "4.0.1", + "remark-toc": "5.0.0", + "remote-origin-url": "0.4.0", + "shelljs": "0.8.2", + "stream-array": "1.1.2", + "strip-json-comments": "2.0.1", + "tiny-lr": "1.1.1", + "unist-builder": "1.0.2", + "unist-util-visit": "1.3.1", + "vfile": "2.3.0", + "vfile-reporter": "4.0.0", + "vfile-sort": "2.1.1", + "vinyl": "2.1.0", + "vinyl-fs": "3.0.3", + "yargs": "9.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://npm.corp.appnexus.com/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.1", + "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.10", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://npm.corp.appnexus.com/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "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.1", + "yargs-parser": "7.0.0" + }, + "dependencies": { + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + } + } + } + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://npm.corp.appnexus.com/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "1.0.1", + "ent": "2.2.0", + "extend": "3.0.1", + "void-elements": "2.0.1" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://npm.corp.appnexus.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", + "dev": true, + "optional": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://npm.corp.appnexus.com/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://npm.corp.appnexus.com/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://npm.corp.appnexus.com/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.48", + "resolved": "https://npm.corp.appnexus.com/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz", + "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://npm.corp.appnexus.com/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emoji-regex": { + "version": "6.1.1", + "resolved": "https://npm.corp.appnexus.com/emoji-regex/-/emoji-regex-6.1.1.tgz", + "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://npm.corp.appnexus.com/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "engine.io": { + "version": "3.1.5", + "resolved": "https://npm.corp.appnexus.com/engine.io/-/engine.io-3.1.5.tgz", + "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", + "dev": true, + "requires": { + "accepts": "1.3.5", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "3.1.0", + "engine.io-parser": "2.1.2", + "uws": "9.14.0", + "ws": "3.3.3" + }, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://npm.corp.appnexus.com/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://npm.corp.appnexus.com/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://npm.corp.appnexus.com/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + } + } + }, + "engine.io-client": { + "version": "3.1.6", + "resolved": "https://npm.corp.appnexus.com/engine.io-client/-/engine.io-client-3.1.6.tgz", + "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "3.1.0", + "engine.io-parser": "2.1.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", + "yeast": "0.1.2" + } + }, + "engine.io-parser": { + "version": "2.1.2", + "resolved": "https://npm.corp.appnexus.com/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary2": "1.0.3" + } + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://npm.corp.appnexus.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://npm.corp.appnexus.com/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "1.0.1" + } + }, + "error": { + "version": "7.0.2", + "resolved": "https://npm.corp.appnexus.com/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "dev": true, + "requires": { + "string-template": "0.2.1", + "xtend": "4.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "errorhandler": { + "version": "1.4.3", + "resolved": "https://npm.corp.appnexus.com/errorhandler/-/errorhandler-1.4.3.tgz", + "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", + "dev": true, + "requires": { + "accepts": "1.3.5", + "escape-html": "1.0.3" + }, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://npm.corp.appnexus.com/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://npm.corp.appnexus.com/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + } + } + }, + "es5-ext": { + "version": "0.10.45", + "resolved": "https://npm.corp.appnexus.com/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" + } + }, + "es5-shim": { + "version": "4.5.10", + "resolved": "https://npm.corp.appnexus.com/es5-shim/-/es5-shim-4.5.10.tgz", + "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==", + "dev": true + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://npm.corp.appnexus.com/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://npm.corp.appnexus.com/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://npm.corp.appnexus.com/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "4.2.4" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://npm.corp.appnexus.com/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://npm.corp.appnexus.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://npm.corp.appnexus.com/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "estraverse": { + "version": "1.9.3", + "resolved": "https://npm.corp.appnexus.com/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://npm.corp.appnexus.com/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://npm.corp.appnexus.com/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.4.1", + "concat-stream": "1.6.2", + "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.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.5.0", + "ignore": "3.3.8", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.5.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://npm.corp.appnexus.com/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.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "globals": { + "version": "11.5.0", + "resolved": "https://npm.corp.appnexus.com/globals/-/globals-11.5.0.tgz", + "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "eslint-config-standard": { + "version": "10.2.1", + "resolved": "https://npm.corp.appnexus.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://npm.corp.appnexus.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "2.6.9", + "resolve": "1.7.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "eslint-module-utils": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "dev": true, + "requires": { + "debug": "2.6.9", + "pkg-dir": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.12.0", + "resolved": "https://npm.corp.appnexus.com/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz", + "integrity": "sha1-2tMXgSktZmSyUxf9BJ0uKy8CIF0=", + "dev": true, + "requires": { + "contains-path": "0.1.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.3.2", + "eslint-module-utils": "2.2.0", + "has": "1.0.3", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "read-pkg-up": "2.0.0", + "resolve": "1.7.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + } + } + }, + "eslint-plugin-node": { + "version": "5.2.1", + "resolved": "https://npm.corp.appnexus.com/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "dev": true, + "requires": { + "ignore": "3.3.8", + "minimatch": "3.0.4", + "resolve": "1.7.1", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "3.8.0", + "resolved": "https://npm.corp.appnexus.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", + "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", + "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://npm.corp.appnexus.com/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.4", + "resolved": "https://npm.corp.appnexus.com/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "5.6.2", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://npm.corp.appnexus.com/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://npm.corp.appnexus.com/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "estree-walker": { + "version": "0.3.1", + "resolved": "https://npm.corp.appnexus.com/estree-walker/-/estree-walker-0.3.1.tgz", + "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.7.0", + "resolved": "https://npm.corp.appnexus.com/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://npm.corp.appnexus.com/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45" + } + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://npm.corp.appnexus.com/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.2" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://npm.corp.appnexus.com/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.2", + "strip-eof": "1.0.0" + } + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://npm.corp.appnexus.com/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "requires": { + "array-slice": "0.2.3", + "array-unique": "0.2.1", + "braces": "0.1.5" + }, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://npm.corp.appnexus.com/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true, + "requires": { + "expand-range": "0.1.1" + } + }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "requires": { + "is-number": "0.1.1", + "repeat-string": "0.2.2" + } + }, + "is-number": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://npm.corp.appnexus.com/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://npm.corp.appnexus.com/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": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.0.0", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "express-session": { + "version": "1.11.3", + "resolved": "https://npm.corp.appnexus.com/express-session/-/express-session-1.11.3.tgz", + "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6", + "crc": "3.3.0", + "debug": "2.2.0", + "depd": "1.0.1", + "on-headers": "1.0.1", + "parseurl": "1.3.2", + "uid-safe": "2.0.0", + "utils-merge": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "uid-safe": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/uid-safe/-/uid-safe-2.0.0.tgz", + "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", + "dev": true, + "requires": { + "base64-url": "1.2.1" + } + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/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": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.23", + "tmp": "0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "faker": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/faker/-/faker-3.1.0.tgz", + "integrity": "sha1-D5CPr05uwCUk5UpX5DLFwBPgjJ8=", + "dev": true + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://npm.corp.appnexus.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://npm.corp.appnexus.com/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "file-loader": { + "version": "0.8.5", + "resolved": "https://npm.corp.appnexus.com/file-loader/-/file-loader-0.8.5.tgz", + "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", + "dev": true, + "optional": true, + "requires": { + "loader-utils": "0.2.17" + }, + "dependencies": { + "loader-utils": { + "version": "0.2.17", + "resolved": "https://npm.corp.appnexus.com/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "optional": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://npm.corp.appnexus.com/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "7.1.2", + "minimatch": "3.0.4" + } + }, + "fill-keys": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "dev": true, + "requires": { + "is-object": "1.0.1", + "merge-descriptors": "1.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "finalhandler": { + "version": "0.4.0", + "resolved": "https://npm.corp.appnexus.com/finalhandler/-/finalhandler-0.4.0.tgz", + "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", + "dev": true, + "requires": { + "debug": "2.2.0", + "escape-html": "1.0.2", + "on-finished": "2.3.0", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "escape-html": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/escape-html/-/escape-html-1.0.2.tgz", + "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "make-dir": "1.3.0", + "pkg-dir": "2.0.0" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/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.1.10", + "resolve-dir": "1.0.1" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "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" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "follow-redirects": { + "version": "1.5.0", + "resolved": "https://npm.corp.appnexus.com/follow-redirects/-/follow-redirects-1.5.0.tgz", + "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", + "dev": true, + "requires": { + "debug": "3.1.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://npm.corp.appnexus.com/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "foreachasync": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/foreachasync/-/foreachasync-3.0.0.tgz", + "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://npm.corp.appnexus.com/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "fork-stream": { + "version": "0.0.4", + "resolved": "https://npm.corp.appnexus.com/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "dev": true + }, + "from": { + "version": "0.1.7", + "resolved": "https://npm.corp.appnexus.com/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "1.0.0" + } + }, + "fs-copy-file-sync": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz", + "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==", + "dev": true + }, + "fs-extra": { + "version": "0.6.4", + "resolved": "https://npm.corp.appnexus.com/fs-extra/-/fs-extra-0.6.4.tgz", + "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", + "dev": true, + "requires": { + "jsonfile": "1.0.1", + "mkdirp": "0.3.5", + "ncp": "0.4.2", + "rimraf": "2.2.8" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://npm.corp.appnexus.com/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + } + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "through2": "2.0.3" + } + }, + "fs.extra": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/fs.extra/-/fs.extra-1.3.2.tgz", + "integrity": "sha1-3QI/kwE77iRTHxszUUw3sg/ZM0k=", + "dev": true, + "requires": { + "fs-extra": "0.6.4", + "mkdirp": "0.3.5", + "walk": "2.3.13" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://npm.corp.appnexus.com/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": 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" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "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.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "fstream": { + "version": "0.1.31", + "resolved": "https://npm.corp.appnexus.com/fstream/-/fstream-0.1.31.tgz", + "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", + "dev": true, + "requires": { + "graceful-fs": "3.0.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.4" + } + } + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://npm.corp.appnexus.com/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://npm.corp.appnexus.com/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-port": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-uri": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/get-uri/-/get-uri-2.0.2.tgz", + "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", + "dev": true, + "requires": { + "data-uri-to-buffer": "1.2.0", + "debug": "2.6.9", + "extend": "3.0.1", + "file-uri-to-path": "1.0.0", + "ftp": "0.3.10", + "readable-stream": "2.3.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://npm.corp.appnexus.com/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://npm.corp.appnexus.com/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "git-up": { + "version": "2.0.10", + "resolved": "https://npm.corp.appnexus.com/git-up/-/git-up-2.0.10.tgz", + "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", + "dev": true, + "requires": { + "is-ssh": "1.3.0", + "parse-url": "1.3.11" + } + }, + "git-url-parse": { + "version": "8.3.1", + "resolved": "https://npm.corp.appnexus.com/git-url-parse/-/git-url-parse-8.3.1.tgz", + "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", + "dev": true, + "requires": { + "git-up": "2.0.10", + "parse-domain": "2.1.1" + } + }, + "github-slugger": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/github-slugger/-/github-slugger-1.2.0.tgz", + "integrity": "sha512-wIaa75k1vZhyPm9yWrD08A5Xnx/V+RmzGrpjQuLemGKSb77Qukiaei58Bogrl/LZSADDfPzKJX8jhLs4CRTl7Q==", + "dev": true, + "requires": { + "emoji-regex": "6.1.1" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://npm.corp.appnexus.com/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://npm.corp.appnexus.com/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "3.0.1", + "glob": "7.1.2", + "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.6", + "remove-trailing-separator": "1.1.0", + "to-absolute-glob": "2.0.2", + "unique-stream": "2.2.1" + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://npm.corp.appnexus.com/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://npm.corp.appnexus.com/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://npm.corp.appnexus.com/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globals-docs": { + "version": "2.4.0", + "resolved": "https://npm.corp.appnexus.com/globals-docs/-/globals-docs-2.4.0.tgz", + "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://npm.corp.appnexus.com/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://npm.corp.appnexus.com/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true, + "requires": { + "sparkles": "1.0.1" + } + }, + "got": { + "version": "8.3.1", + "resolved": "https://npm.corp.appnexus.com/got/-/got-8.3.1.tgz", + "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", + "dev": true, + "requires": { + "@sindresorhus/is": "0.7.0", + "cacheable-request": "2.1.4", + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "into-stream": "3.1.0", + "is-retry-allowed": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "mimic-response": "1.0.0", + "p-cancelable": "0.4.1", + "p-timeout": "2.0.1", + "pify": "3.0.0", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "3.0.0", + "url-to-options": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.10.3", + "resolved": "https://npm.corp.appnexus.com/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://npm.corp.appnexus.com/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.1.0", + "liftoff": "2.5.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "glob": { + "version": "4.5.3", + "resolved": "https://npm.corp.appnexus.com/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://npm.corp.appnexus.com/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.4" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://npm.corp.appnexus.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + } + } + } + }, + "gulp-babel": { + "version": "6.1.3", + "resolved": "https://npm.corp.appnexus.com/gulp-babel/-/gulp-babel-6.1.3.tgz", + "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "object-assign": "4.1.1", + "plugin-error": "1.0.1", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "babel-core": { + "version": "6.26.3", + "resolved": "https://npm.corp.appnexus.com/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.1", + "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.10", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "gulp-clean": { + "version": "0.3.2", + "resolved": "https://npm.corp.appnexus.com/gulp-clean/-/gulp-clean-0.3.2.tgz", + "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", + "dev": true, + "requires": { + "gulp-util": "2.2.20", + "rimraf": "2.6.2", + "through2": "0.4.2" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "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" + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://npm.corp.appnexus.com/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "gulp-util": { + "version": "2.2.20", + "resolved": "https://npm.corp.appnexus.com/gulp-util/-/gulp-util-2.2.20.tgz", + "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", + "dev": true, + "requires": { + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" + }, + "dependencies": { + "through2": { + "version": "0.5.1", + "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "3.0.0" + } + } + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", + "dev": true + }, + "lodash.escape": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", + "dev": true, + "requires": { + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" + } + }, + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + }, + "lodash.template": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", + "dev": true, + "requires": { + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" + } + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "dev": true + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://npm.corp.appnexus.com/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.4.2", + "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "xtend": { + "version": "2.1.2", + "resolved": "https://npm.corp.appnexus.com/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true, + "requires": { + "clone-stats": "0.0.1" + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.1.0", + "through2": "2.0.3", + "vinyl": "2.1.0" + } + }, + "gulp-connect": { + "version": "5.0.0", + "resolved": "https://npm.corp.appnexus.com/gulp-connect/-/gulp-connect-5.0.0.tgz", + "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", + "dev": true, + "requires": { + "connect": "2.30.2", + "connect-livereload": "0.5.4", + "event-stream": "3.3.4", + "gulp-util": "3.0.8", + "tiny-lr": "0.2.1" + }, + "dependencies": { + "body-parser": { + "version": "1.14.2", + "resolved": "https://npm.corp.appnexus.com/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "dev": true, + "requires": { + "bytes": "2.2.0", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.1.2", + "http-errors": "1.3.1", + "iconv-lite": "0.4.13", + "on-finished": "2.3.0", + "qs": "5.2.0", + "raw-body": "2.1.7", + "type-is": "1.6.16" + }, + "dependencies": { + "qs": { + "version": "5.2.0", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "dev": true + } + } + }, + "bytes": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "5.1.0", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "2.4.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + } + } + }, + "tiny-lr": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/tiny-lr/-/tiny-lr-0.2.1.tgz", + "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "dev": true, + "requires": { + "body-parser": "1.14.2", + "debug": "2.2.0", + "faye-websocket": "0.10.0", + "livereload-js": "2.3.0", + "parseurl": "1.3.2", + "qs": "5.1.0" + } + } + } + }, + "gulp-documentation": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/gulp-documentation/-/gulp-documentation-3.2.1.tgz", + "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", + "dev": true, + "requires": { + "through2": "2.0.3", + "vinyl": "2.1.0" + } + }, + "gulp-eslint": { + "version": "4.0.2", + "resolved": "https://npm.corp.appnexus.com/gulp-eslint/-/gulp-eslint-4.0.2.tgz", + "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", + "dev": true, + "requires": { + "eslint": "4.19.1", + "fancy-log": "1.3.2", + "plugin-error": "1.0.1" + } + }, + "gulp-footer": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/gulp-footer/-/gulp-footer-1.1.2.tgz", + "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", + "dev": true, + "requires": { + "event-stream": "3.3.4", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2" + } + }, + "gulp-header": { + "version": "1.8.12", + "resolved": "https://npm.corp.appnexus.com/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.1.0", + "lodash.template": "4.4.0", + "through2": "2.0.3" + }, + "dependencies": { + "lodash.template": { + "version": "4.4.0", + "resolved": "https://npm.corp.appnexus.com/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.templatesettings": "4.1.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://npm.corp.appnexus.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0" + } + } + } + }, + "gulp-if": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/gulp-if/-/gulp-if-2.0.2.tgz", + "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", + "dev": true, + "requires": { + "gulp-match": "1.0.3", + "ternary-stream": "2.0.1", + "through2": "2.0.3" + } + }, + "gulp-js-escape": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz", + "integrity": "sha1-HNRF+9AJ4Np2lZoDp/SbNWav+Gg=", + "dev": true, + "requires": { + "through2": "0.6.5" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulp-match": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/gulp-match/-/gulp-match-1.0.3.tgz", + "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", + "dev": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "gulp-optimize-js": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", + "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "lodash": "4.17.10", + "optimize-js": "1.0.3", + "through2": "2.0.3" + } + }, + "gulp-rename": { + "version": "1.2.3", + "resolved": "https://npm.corp.appnexus.com/gulp-rename/-/gulp-rename-1.2.3.tgz", + "integrity": "sha512-CmdPM0BjJ105QCX1fk+j7NGhiN/1rCl9HLGss+KllBS/tdYadpjTxqdKyh/5fNV+M3yjT1MFz5z93bXdrTyzAw==", + "dev": true + }, + "gulp-replace": { + "version": "0.4.0", + "resolved": "https://npm.corp.appnexus.com/gulp-replace/-/gulp-replace-0.4.0.tgz", + "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", + "dev": true, + "requires": { + "event-stream": "3.0.20", + "istextorbinary": "1.0.2", + "replacestream": "0.1.3" + }, + "dependencies": { + "event-stream": { + "version": "3.0.20", + "resolved": "https://npm.corp.appnexus.com/event-stream/-/event-stream-3.0.20.tgz", + "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.0.7", + "pause-stream": "0.0.11", + "split": "0.2.10", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://npm.corp.appnexus.com/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "split": { + "version": "0.2.10", + "resolved": "https://npm.corp.appnexus.com/split/-/split-0.2.10.tgz", + "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", + "dev": true, + "requires": { + "through": "2.3.8" + } + } + } + }, + "gulp-shell": { + "version": "0.5.2", + "resolved": "https://npm.corp.appnexus.com/gulp-shell/-/gulp-shell-0.5.2.tgz", + "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", + "dev": true, + "requires": { + "async": "1.5.2", + "gulp-util": "3.0.8", + "lodash": "4.17.10", + "through2": "2.0.3" + } + }, + "gulp-sourcemaps": { + "version": "2.6.4", + "resolved": "https://npm.corp.appnexus.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "requires": { + "@gulp-sourcemaps/identity-map": "1.0.1", + "@gulp-sourcemaps/map-sources": "1.0.0", + "acorn": "5.6.2", + "convert-source-map": "1.5.1", + "css": "2.2.3", + "debug-fabulous": "1.1.0", + "detect-newline": "2.1.0", + "graceful-fs": "4.1.11", + "source-map": "0.6.1", + "strip-bom-string": "1.0.0", + "through2": "2.0.3" + } + }, + "gulp-uglify": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/gulp-uglify/-/gulp-uglify-3.0.0.tgz", + "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", + "dev": true, + "requires": { + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash": "4.17.10", + "make-error-cause": "1.2.2", + "through2": "2.0.3", + "uglify-js": "3.4.0", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "uglify-js": { + "version": "3.4.0", + "resolved": "https://npm.corp.appnexus.com/uglify-js/-/uglify-js-3.4.0.tgz", + "integrity": "sha512-Jcf5naPkX3rVPSQpRn9Vm6Rr572I1gTtR9LnqKgXjmOgfYQ/QS0V2WRStFR53Bdj520M66aCZqt9uzYXgtGrJQ==", + "dev": true, + "requires": { + "commander": "2.15.1", + "source-map": "0.6.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://npm.corp.appnexus.com/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "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.2", + "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.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-webdriver": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", + "integrity": "sha1-mM6Bz5rganoZB7htEPaThvQ4Oi0=", + "dev": true, + "requires": { + "dargs": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", + "deepmerge": "0.2.10", + "gulp-util": "3.0.8", + "through2": "0.6.5", + "webdriverio": "3.4.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.1" + } + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://npm.corp.appnexus.com/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://npm.corp.appnexus.com/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.15.1", + "is-my-json-valid": "2.17.2", + "pinkie-promise": "2.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.1" + } + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://npm.corp.appnexus.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://npm.corp.appnexus.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "requires": { + "has-symbol-support-x": "1.4.2" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/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.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://npm.corp.appnexus.com/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://npm.corp.appnexus.com/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "hast-util-is-element": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", + "integrity": "sha1-P3IWl4sq4U2YdJh4eCZ18zvjzgA=", + "dev": true + }, + "hast-util-sanitize": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", + "integrity": "sha1-0QvWdXoh5ZwTq8iuNTDdO219Z54=", + "dev": true, + "requires": { + "xtend": "4.0.1" + } + }, + "hast-util-to-html": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", + "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", + "dev": true, + "requires": { + "ccount": "1.0.3", + "comma-separated-tokens": "1.0.5", + "hast-util-is-element": "1.0.0", + "hast-util-whitespace": "1.0.0", + "html-void-elements": "1.0.3", + "kebab-case": "1.0.0", + "property-information": "3.2.0", + "space-separated-tokens": "1.1.2", + "stringify-entities": "1.3.2", + "unist-util-is": "2.1.2", + "xtend": "4.0.1" + } + }, + "hast-util-whitespace": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", + "integrity": "sha1-vQlpGWJdKTbh/xe8Tff9cn8X7Ok=", + "dev": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://npm.corp.appnexus.com/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://npm.corp.appnexus.com/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", + "dev": true + }, + "hipchat-notifier": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", + "dev": true, + "optional": true, + "requires": { + "lodash": "4.17.10", + "request": "2.79.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://npm.corp.appnexus.com/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.6.0", + "resolved": "https://npm.corp.appnexus.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "dev": true + }, + "html-void-elements": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/html-void-elements/-/html-void-elements-1.0.3.tgz", + "integrity": "sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==", + "dev": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://npm.corp.appnexus.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "http-errors": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "statuses": "1.5.0" + } + }, + "http-parser-js": { + "version": "0.4.13", + "resolved": "https://npm.corp.appnexus.com/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", + "dev": true + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://npm.corp.appnexus.com/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "3.1.0", + "follow-redirects": "1.5.0", + "requires-port": "1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "httpntlm": { + "version": "1.6.1", + "resolved": "https://npm.corp.appnexus.com/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "dev": true, + "requires": { + "httpreq": "0.4.24", + "underscore": "1.7.0" + } + }, + "httpreq": { + "version": "0.4.24", + "resolved": "https://npm.corp.appnexus.com/httpreq/-/httpreq-0.4.24.tgz", + "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", + "dev": true + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "dev": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "iconv-lite": { + "version": "0.4.11", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.11.tgz", + "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", + "dev": true + }, + "ieee754": { + "version": "1.1.11", + "resolved": "https://npm.corp.appnexus.com/ieee754/-/ieee754-1.1.11.tgz", + "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", + "dev": true + }, + "ignore": { + "version": "3.3.8", + "resolved": "https://npm.corp.appnexus.com/ignore/-/ignore-3.3.8.tgz", + "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", + "dev": true + }, + "ignore-loader": { + "version": "0.1.2", + "resolved": "https://npm.corp.appnexus.com/ignore-loader/-/ignore-loader-0.1.2.tgz", + "integrity": "sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://npm.corp.appnexus.com/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://npm.corp.appnexus.com/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", + "dev": true, + "optional": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://npm.corp.appnexus.com/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://npm.corp.appnexus.com/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://npm.corp.appnexus.com/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://npm.corp.appnexus.com/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "dev": true, + "requires": { + "from2": "2.3.0", + "p-is-promise": "1.1.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://npm.corp.appnexus.com/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://npm.corp.appnexus.com/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "1.0.0", + "is-windows": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-alphabetical": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz", + "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", + "dev": true + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", + "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "dev": true, + "requires": { + "is-alphabetical": "1.0.2", + "is-decimal": "1.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://npm.corp.appnexus.com/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-decimal": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-decimal/-/is-decimal-1.0.2.tgz", + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://npm.corp.appnexus.com/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" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-generator": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/is-generator/-/is-generator-1.0.3.tgz", + "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", + "dev": true + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "https://npm.corp.appnexus.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "1.0.0" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-ssh": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/is-ssh/-/is-ssh-1.3.0.tgz", + "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", + "dev": true, + "requires": { + "protocols": "1.4.6" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-whitespace-character": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", + "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-word-character": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-word-character/-/is-word-character-1.0.2.tgz", + "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://npm.corp.appnexus.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://npm.corp.appnexus.com/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://npm.corp.appnexus.com/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.6.1", + "mkdirp": "0.5.1", + "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": { + "glob": { + "version": "5.0.15", + "resolved": "https://npm.corp.appnexus.com/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "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": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://npm.corp.appnexus.com/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-api": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/istanbul-api/-/istanbul-api-1.3.1.tgz", + "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", + "dev": true, + "requires": { + "async": "2.6.1", + "compare-versions": "3.2.1", + "fileset": "2.0.3", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-hook": "1.2.1", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-report": "1.1.4", + "istanbul-lib-source-maps": "1.2.5", + "istanbul-reports": "1.3.0", + "js-yaml": "3.12.0", + "mkdirp": "0.5.1", + "once": "1.4.0" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "4.17.10" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + } + } + }, + "istanbul-instrumenter-loader": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", + "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", + "dev": true, + "requires": { + "convert-source-map": "1.5.1", + "istanbul-lib-instrument": "1.10.1", + "loader-utils": "1.1.0", + "schema-utils": "0.3.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.1", + "resolved": "https://npm.corp.appnexus.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz", + "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==", + "dev": true, + "requires": { + "append-transform": "1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.1", + "resolved": "https://npm.corp.appnexus.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", + "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", + "dev": true, + "requires": { + "babel-generator": "6.26.1", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.2.0", + "semver": "5.5.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.4", + "resolved": "https://npm.corp.appnexus.com/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", + "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.5", + "resolved": "https://npm.corp.appnexus.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz", + "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==", + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/istanbul-reports/-/istanbul-reports-1.3.0.tgz", + "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", + "dev": true, + "requires": { + "handlebars": "4.0.11" + } + }, + "istextorbinary": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/istextorbinary/-/istextorbinary-1.0.2.tgz", + "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", + "dev": true, + "requires": { + "binaryextensions": "1.0.1", + "textextensions": "1.0.2" + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "jade": { + "version": "0.26.3", + "resolved": "https://npm.corp.appnexus.com/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://npm.corp.appnexus.com/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://npm.corp.appnexus.com/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.6.1", + "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "2.7.3" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://npm.corp.appnexus.com/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://npm.corp.appnexus.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://npm.corp.appnexus.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://npm.corp.appnexus.com/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://npm.corp.appnexus.com/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/jsonfile/-/jsonfile-1.0.1.tgz", + "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://npm.corp.appnexus.com/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "JSONStream": { + "version": "1.3.3", + "resolved": "https://npm.corp.appnexus.com/JSONStream/-/JSONStream-1.3.3.tgz", + "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://npm.corp.appnexus.com/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "just-clone": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/just-clone/-/just-clone-1.0.2.tgz", + "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" + }, + "just-extend": { + "version": "1.1.27", + "resolved": "https://npm.corp.appnexus.com/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", + "dev": true + }, + "karma": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/karma/-/karma-2.0.2.tgz", + "integrity": "sha1-TS25QChQpmVR+nhLAWT7CCTtjEs=", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "body-parser": "1.18.3", + "chokidar": "1.7.0", + "colors": "1.3.0", + "combine-lists": "1.0.1", + "connect": "3.6.6", + "core-js": "2.5.7", + "di": "0.0.1", + "dom-serialize": "2.2.1", + "expand-braces": "0.1.2", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "http-proxy": "1.17.0", + "isbinaryfile": "3.0.2", + "lodash": "4.17.10", + "log4js": "2.8.0", + "mime": "1.6.0", + "minimatch": "3.0.4", + "optimist": "0.6.1", + "qjobs": "1.2.0", + "range-parser": "1.2.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "socket.io": "2.0.4", + "source-map": "0.6.1", + "tmp": "0.0.33", + "useragent": "2.2.1" + }, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://npm.corp.appnexus.com/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "1.6.16" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://npm.corp.appnexus.com/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.2" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://npm.corp.appnexus.com/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "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.1.0" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://npm.corp.appnexus.com/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "1.3.2", + "utils-merge": "1.0.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + } + } + }, + "karma-babel-preprocessor": { + "version": "6.0.1", + "resolved": "https://npm.corp.appnexus.com/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", + "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", + "dev": true, + "requires": { + "babel-core": "6.22.0" + } + }, + "karma-browserstack-launcher": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", + "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", + "dev": true, + "requires": { + "browserstack": "1.5.0", + "browserstacktunnel-wrapper": "2.0.2", + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://npm.corp.appnexus.com/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "karma-chai": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/karma-chai/-/karma-chai-0.1.0.tgz", + "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", + "dev": true + }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true, + "requires": { + "fs-access": "1.0.1", + "which": "1.3.1" + } + }, + "karma-coverage-istanbul-reporter": { + "version": "1.4.3", + "resolved": "https://npm.corp.appnexus.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", + "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", + "dev": true, + "requires": { + "istanbul-api": "1.3.1", + "minimatch": "3.0.4" + } + }, + "karma-es5-shim": { + "version": "0.0.4", + "resolved": "https://npm.corp.appnexus.com/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", + "integrity": "sha1-zdADM8znfC5M4D46yT8vjs0fuVI=", + "dev": true, + "requires": { + "es5-shim": "4.5.10" + } + }, + "karma-firefox-launcher": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", + "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", + "dev": true + }, + "karma-ie-launcher": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", + "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", + "dev": true, + "requires": { + "lodash": "4.17.10" + } + }, + "karma-mocha": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/karma-mocha/-/karma-mocha-1.3.0.tgz", + "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "karma-mocha-reporter": { + "version": "2.2.5", + "resolved": "https://npm.corp.appnexus.com/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", + "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", + "dev": true, + "requires": { + "chalk": "2.4.1", + "log-symbols": "2.2.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "karma-opera-launcher": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/karma-opera-launcher/-/karma-opera-launcher-1.0.0.tgz", + "integrity": "sha1-+lFihTGh0L6EstjcDX7iCfyP+Ro=", + "dev": true + }, + "karma-requirejs": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/karma-requirejs/-/karma-requirejs-1.1.0.tgz", + "integrity": "sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=", + "dev": true + }, + "karma-safari-launcher": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz", + "integrity": "sha1-lpgqLMR9BmquccVTursoMZEVos4=", + "dev": true + }, + "karma-script-launcher": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz", + "integrity": "sha1-zQF8TeXvCeWp2nkydhdhCN1LVC0=", + "dev": true + }, + "karma-sinon": { + "version": "1.0.5", + "resolved": "https://npm.corp.appnexus.com/karma-sinon/-/karma-sinon-1.0.5.tgz", + "integrity": "sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo=", + "dev": true + }, + "karma-sourcemap-loader": { + "version": "0.3.7", + "resolved": "https://npm.corp.appnexus.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", + "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "karma-spec-reporter": { + "version": "0.0.31", + "resolved": "https://npm.corp.appnexus.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", + "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", + "dev": true, + "requires": { + "colors": "1.3.0" + } + }, + "karma-webpack": { + "version": "2.0.13", + "resolved": "https://npm.corp.appnexus.com/karma-webpack/-/karma-webpack-2.0.13.tgz", + "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", + "dev": true, + "requires": { + "async": "2.6.1", + "babel-runtime": "6.26.0", + "loader-utils": "1.1.0", + "lodash": "4.17.10", + "source-map": "0.5.7", + "webpack-dev-middleware": "1.12.2" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "4.17.10" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "kebab-case": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/kebab-case/-/kebab-case-1.0.0.tgz", + "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=", + "dev": true + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "lcov-parse": { + "version": "0.0.10", + "resolved": "https://npm.corp.appnexus.com/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true + }, + "lead": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "1.0.3" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "libbase64": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/libbase64/-/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", + "dev": true + }, + "libmime": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/libmime/-/libmime-3.0.0.tgz", + "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", + "dev": true, + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", + "dev": true + } + } + }, + "libqp": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", + "dev": true + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://npm.corp.appnexus.com/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.7.1" + } + }, + "livereload-js": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/livereload-js/-/livereload-js-2.3.0.tgz", + "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "localtunnel": { + "version": "1.9.0", + "resolved": "https://npm.corp.appnexus.com/localtunnel/-/localtunnel-1.9.0.tgz", + "integrity": "sha512-wCIiIHJ8kKIcWkTQE3m1VRABvsH2ZuOkiOpZUofUCf6Q42v3VIZ+Q0YfX1Z4sYDRj0muiKL1bLvz1FeoxsPO0w==", + "dev": true, + "requires": { + "axios": "0.17.1", + "debug": "2.6.8", + "openurl": "1.1.1", + "yargs": "6.6.0" + }, + "dependencies": { + "axios": { + "version": "0.17.1", + "resolved": "https://npm.corp.appnexus.com/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "dev": true, + "requires": { + "follow-redirects": "1.5.0", + "is-buffer": "1.1.6" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "debug": { + "version": "2.6.8", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://npm.corp.appnexus.com/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/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.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://npm.corp.appnexus.com/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "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": "4.2.1" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://npm.corp.appnexus.com/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + } + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "lodash._arraycopy": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", + "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", + "dev": true + }, + "lodash._arrayeach": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", + "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._baseclone": { + "version": "3.3.0", + "resolved": "https://npm.corp.appnexus.com/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", + "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", + "dev": true, + "requires": { + "lodash._arraycopy": "3.0.0", + "lodash._arrayeach": "3.0.0", + "lodash._baseassign": "3.2.0", + "lodash._basefor": "3.0.3", + "lodash.isarray": "3.0.4", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://npm.corp.appnexus.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._basefor": { + "version": "3.0.3", + "resolved": "https://npm.corp.appnexus.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._escapehtmlchar": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1" + } + }, + "lodash._escapestringchar": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://npm.corp.appnexus.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._htmlescapes": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://npm.corp.appnexus.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", + "dev": true + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._reunescapedhtml": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash._shimkeys": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash._stack": { + "version": "4.1.3", + "resolved": "https://npm.corp.appnexus.com/lodash._stack/-/lodash._stack-4.1.3.tgz", + "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", + "dev": true + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://npm.corp.appnexus.com/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "lodash.clone": { + "version": "3.0.3", + "resolved": "https://npm.corp.appnexus.com/lodash.clone/-/lodash.clone-3.0.3.tgz", + "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", + "dev": true, + "requires": { + "lodash._baseclone": "3.3.0", + "lodash._bindcallback": "3.0.1", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://npm.corp.appnexus.com/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/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" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "lodash.defaultsdeep": { + "version": "4.3.2", + "resolved": "https://npm.corp.appnexus.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", + "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", + "dev": true, + "requires": { + "lodash._baseclone": "4.5.7", + "lodash._stack": "4.1.3", + "lodash.isplainobject": "4.0.6", + "lodash.keysin": "4.2.0", + "lodash.mergewith": "4.6.1", + "lodash.rest": "4.0.5" + }, + "dependencies": { + "lodash._baseclone": { + "version": "4.5.7", + "resolved": "https://npm.corp.appnexus.com/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", + "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", + "dev": true + } + } + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://npm.corp.appnexus.com/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://npm.corp.appnexus.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://npm.corp.appnexus.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://npm.corp.appnexus.com/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.keysin": { + "version": "4.2.0", + "resolved": "https://npm.corp.appnexus.com/lodash.keysin/-/lodash.keysin-4.2.0.tgz", + "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", + "dev": true + }, + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://npm.corp.appnexus.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "dev": true + }, + "lodash.rest": { + "version": "4.0.5", + "resolved": "https://npm.corp.appnexus.com/lodash.rest/-/lodash.rest-4.0.5.tgz", + "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://npm.corp.appnexus.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://npm.corp.appnexus.com/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lodash.values": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash.values/-/lodash.values-2.4.1.tgz", + "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", + "dev": true, + "requires": { + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://npm.corp.appnexus.com/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "2.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "log4js": { + "version": "2.8.0", + "resolved": "https://npm.corp.appnexus.com/log4js/-/log4js-2.8.0.tgz", + "integrity": "sha512-PjsaE4ElS0e2jWOY14Ef2PrC1Y+fny4AWPPT3xD6+2k2Aa5golhqJ4DSzP+5kXRL5bSw/5j1ocU5A9ceaxZeGA==", + "dev": true, + "requires": { + "amqplib": "0.5.2", + "axios": "0.15.3", + "circular-json": "0.5.4", + "date-format": "1.2.0", + "debug": "3.1.0", + "hipchat-notifier": "1.1.0", + "loggly": "1.1.1", + "mailgun-js": "0.18.0", + "nodemailer": "2.7.2", + "redis": "2.8.0", + "semver": "5.5.0", + "slack-node": "0.2.0", + "streamroller": "0.7.0" + }, + "dependencies": { + "circular-json": { + "version": "0.5.4", + "resolved": "https://npm.corp.appnexus.com/circular-json/-/circular-json-0.5.4.tgz", + "integrity": "sha512-vnJA8KS0BfOihugYEUkLRcnmq21FbuivbxgzDLXNs3zIk4KllV4Mx4UuTzBXht9F00C7QfD1YqMXg1zP6EXpig==", + "dev": true + } + } + }, + "loggly": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/loggly/-/loggly-1.1.1.tgz", + "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", + "dev": true, + "optional": true, + "requires": { + "json-stringify-safe": "5.0.1", + "request": "2.75.0", + "timespan": "2.3.0" + }, + "dependencies": { + "bl": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "2.0.6" + } + }, + "form-data": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-2.0.0.tgz", + "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://npm.corp.appnexus.com/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://npm.corp.appnexus.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.2.3", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.75.0", + "resolved": "https://npm.corp.appnexus.com/request/-/request-2.75.0.tgz", + "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.7.0", + "bl": "1.1.2", + "caseless": "0.11.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.0.0", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "node-uuid": "1.4.8", + "oauth-sign": "0.8.2", + "qs": "6.2.3", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.4.3" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true, + "optional": true + } + } + }, + "lolex": { + "version": "2.7.0", + "resolved": "https://npm.corp.appnexus.com/lolex/-/lolex-2.7.0.tgz", + "integrity": "sha512-uJkH2e0BVfU5KOJUevbTOtpDduooSarH5PopO+LfM/vZf8Z9sJzODqKev804JYM2i++ktJfUmC1le4LwFQ1VMg==", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "longest-streak": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://npm.corp.appnexus.com/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "0.10.45" + } + }, + "magic-string": { + "version": "0.16.0", + "resolved": "https://npm.corp.appnexus.com/magic-string/-/magic-string-0.16.0.tgz", + "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", + "dev": true, + "requires": { + "vlq": "0.2.3" + } + }, + "mailcomposer": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/mailcomposer/-/mailcomposer-4.0.1.tgz", + "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", + "dev": true, + "optional": true, + "requires": { + "buildmail": "4.0.1", + "libmime": "3.0.0" + } + }, + "mailgun-js": { + "version": "0.18.0", + "resolved": "https://npm.corp.appnexus.com/mailgun-js/-/mailgun-js-0.18.0.tgz", + "integrity": "sha512-o0P6jjZlx5CQj12tvVgDTbgjTqVN0+5h6/6P1+3c6xmozVKBwniQ6Qt3MkCSF0+ueVTbobAfWyGpWRZMJu8t1g==", + "dev": true, + "optional": true, + "requires": { + "async": "2.6.1", + "debug": "3.1.0", + "form-data": "2.3.2", + "inflection": "1.12.0", + "is-stream": "1.1.0", + "path-proxy": "1.0.0", + "promisify-call": "2.0.4", + "proxy-agent": "3.0.0", + "tsscmp": "1.0.5" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "optional": true, + "requires": { + "lodash": "4.17.10" + } + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + } + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "make-error": { + "version": "1.3.4", + "resolved": "https://npm.corp.appnexus.com/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "dev": true + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://npm.corp.appnexus.com/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "dev": true, + "requires": { + "make-error": "1.3.4" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://npm.corp.appnexus.com/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "markdown-escapes": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz", + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", + "dev": true + }, + "markdown-table": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/markdown-table/-/markdown-table-1.1.2.tgz", + "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", + "dev": true + }, + "match-stream": { + "version": "0.0.2", + "resolved": "https://npm.corp.appnexus.com/match-stream/-/match-stream-0.0.2.tgz", + "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", + "dev": true, + "requires": { + "buffers": "0.1.1", + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://npm.corp.appnexus.com/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "mdast-util-compact": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", + "dev": true, + "requires": { + "unist-util-modify-children": "1.1.2", + "unist-util-visit": "1.3.1" + } + }, + "mdast-util-definitions": { + "version": "1.2.2", + "resolved": "https://npm.corp.appnexus.com/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", + "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", + "dev": true, + "requires": { + "unist-util-visit": "1.3.1" + } + }, + "mdast-util-inject": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", + "integrity": "sha1-2wa4tYW+lZotzS+H9HK6m3VvNnU=", + "dev": true, + "requires": { + "mdast-util-to-string": "1.0.4" + } + }, + "mdast-util-to-hast": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/mdast-util-to-hast/-/mdast-util-to-hast-3.0.1.tgz", + "integrity": "sha512-+eimV/12kdg0/T0EEfcK7IsDbSu2auVm92z5jdSEQ3DHF2HiU4OHmX9ir5wpQajr73nwabdxrUoxREvW2zVFFw==", + "dev": true, + "requires": { + "collapse-white-space": "1.0.4", + "detab": "2.0.1", + "mdast-util-definitions": "1.2.2", + "mdurl": "1.0.1", + "trim": "0.0.1", + "trim-lines": "1.1.1", + "unist-builder": "1.0.2", + "unist-util-generated": "1.1.2", + "unist-util-position": "3.0.1", + "unist-util-visit": "1.3.1", + "xtend": "4.0.1" + } + }, + "mdast-util-to-string": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", + "integrity": "sha1-XEVch4yTVfDB5/PotxnPWDaRrPs=", + "dev": true + }, + "mdast-util-toc": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", + "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", + "dev": true, + "requires": { + "github-slugger": "1.2.0", + "mdast-util-to-string": "1.0.4", + "unist-util-visit": "1.3.1" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "memoizee": { + "version": "0.4.12", + "resolved": "https://npm.corp.appnexus.com/memoizee/-/memoizee-0.4.12.tgz", + "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45", + "es6-weak-map": "2.0.2", + "event-emitter": "0.3.5", + "is-promise": "2.1.0", + "lru-queue": "0.1.0", + "next-tick": "1.0.0", + "timers-ext": "0.1.5" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://npm.corp.appnexus.com/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.7", + "readable-stream": "2.3.6" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://npm.corp.appnexus.com/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/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.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "method-override": { + "version": "2.3.10", + "resolved": "https://npm.corp.appnexus.com/method-override/-/method-override-2.3.10.tgz", + "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "methods": "1.1.2", + "parseurl": "1.3.2", + "vary": "1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://npm.corp.appnexus.com/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.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://npm.corp.appnexus.com/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://npm.corp.appnexus.com/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://npm.corp.appnexus.com/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mkpath": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/mkpath/-/mkpath-1.0.0.tgz", + "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", + "dev": true + }, + "mocha": { + "version": "2.2.5", + "resolved": "https://npm.corp.appnexus.com/mocha/-/mocha-2.2.5.tgz", + "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.0.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.5.0", + "supports-color": "1.2.1" + }, + "dependencies": { + "commander": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "debug": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.0.0.tgz", + "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", + "dev": true, + "requires": { + "ms": "0.6.2" + } + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "glob": { + "version": "3.2.3", + "resolved": "https://npm.corp.appnexus.com/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "dev": true, + "requires": { + "graceful-fs": "2.0.3", + "inherits": "2.0.3", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + }, + "growl": { + "version": "1.8.1", + "resolved": "https://npm.corp.appnexus.com/growl/-/growl-1.8.1.tgz", + "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "0.6.2", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.6.2.tgz", + "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", + "dev": true + }, + "supports-color": { + "version": "1.2.1", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-1.2.1.tgz", + "integrity": "sha1-Eu4hUHCGzZjBBY2ewPSsR2t687I=", + "dev": true + } + } + }, + "mocha-nightwatch": { + "version": "3.2.2", + "resolved": "https://npm.corp.appnexus.com/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", + "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.5", + "glob": "7.0.5", + "growl": "1.9.2", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "glob": { + "version": "7.0.5", + "resolved": "https://npm.corp.appnexus.com/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", + "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" + } + }, + "growl": { + "version": "1.9.2", + "resolved": "https://npm.corp.appnexus.com/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "mock-fs": { + "version": "3.12.1", + "resolved": "https://npm.corp.appnexus.com/mock-fs/-/mock-fs-3.12.1.tgz", + "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", + "dev": true, + "requires": { + "rewire": "2.5.2", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "module-deps-sortable": { + "version": "4.0.6", + "resolved": "https://npm.corp.appnexus.com/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", + "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", + "dev": true, + "requires": { + "browser-resolve": "1.11.2", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "4.7.1", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "JSONStream": "1.3.3", + "parents": "1.0.1", + "readable-stream": "2.3.6", + "resolve": "1.7.1", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.5.2", + "resolved": "https://npm.corp.appnexus.com/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://npm.corp.appnexus.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "module-not-found-error": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", + "dev": true + }, + "morgan": { + "version": "1.6.1", + "resolved": "https://npm.corp.appnexus.com/morgan/-/morgan-1.6.1.tgz", + "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", + "dev": true, + "requires": { + "basic-auth": "1.0.4", + "debug": "2.2.0", + "depd": "1.0.1", + "on-finished": "2.3.0", + "on-headers": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multiparty": { + "version": "3.3.2", + "resolved": "https://npm.corp.appnexus.com/multiparty/-/multiparty-3.3.2.tgz", + "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "stream-counter": "0.2.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://npm.corp.appnexus.com/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "resolved": "https://npm.corp.appnexus.com/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://npm.corp.appnexus.com/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.10.0", + "resolved": "https://npm.corp.appnexus.com/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://npm.corp.appnexus.com/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "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-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "natives": { + "version": "1.1.4", + "resolved": "https://npm.corp.appnexus.com/natives/-/natives-1.1.4.tgz", + "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://npm.corp.appnexus.com/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ncp": { + "version": "0.4.2", + "resolved": "https://npm.corp.appnexus.com/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", + "dev": true + }, + "negotiator": { + "version": "0.5.3", + "resolved": "https://npm.corp.appnexus.com/negotiator/-/negotiator-0.5.3.tgz", + "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", + "dev": true + }, + "neo-async": { + "version": "2.5.1", + "resolved": "https://npm.corp.appnexus.com/neo-async/-/neo-async-2.5.1.tgz", + "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", + "dev": true + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://npm.corp.appnexus.com/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "nightwatch": { + "version": "0.9.21", + "resolved": "https://npm.corp.appnexus.com/nightwatch/-/nightwatch-0.9.21.tgz", + "integrity": "sha1-nnlKdRS0/V9GYC02jlBRUjKrnpA=", + "dev": true, + "requires": { + "chai-nightwatch": "0.1.1", + "ejs": "2.5.7", + "lodash.clone": "3.0.3", + "lodash.defaultsdeep": "4.3.2", + "minimatch": "3.0.3", + "mkpath": "1.0.0", + "mocha-nightwatch": "3.2.2", + "optimist": "0.6.1", + "proxy-agent": "2.0.0", + "q": "1.4.1" + }, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "co": { + "version": "3.0.6", + "resolved": "https://npm.corp.appnexus.com/co/-/co-3.0.6.tgz", + "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "ejs": { + "version": "2.5.7", + "resolved": "https://npm.corp.appnexus.com/ejs/-/ejs-2.5.7.tgz", + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "http-proxy-agent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", + "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ip": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/ip/-/ip-1.0.1.tgz", + "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", + "dev": true + }, + "lru-cache": { + "version": "2.6.5", + "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.6.5.tgz", + "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", + "dev": true + }, + "minimatch": { + "version": "3.0.3", + "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "pac-proxy-agent": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", + "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1", + "get-uri": "2.0.2", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "1.0.0", + "pac-resolver": "2.0.0", + "raw-body": "2.3.3", + "socks-proxy-agent": "2.1.1" + } + }, + "pac-resolver": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/pac-resolver/-/pac-resolver-2.0.0.tgz", + "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", + "dev": true, + "requires": { + "co": "3.0.6", + "degenerator": "1.0.4", + "ip": "1.0.1", + "netmask": "1.0.6", + "thunkify": "2.1.2" + } + }, + "proxy-agent": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/proxy-agent/-/proxy-agent-2.0.0.tgz", + "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "1.0.0", + "lru-cache": "2.6.5", + "pac-proxy-agent": "1.1.0", + "socks-proxy-agent": "2.1.1" + } + }, + "q": { + "version": "1.4.1", + "resolved": "https://npm.corp.appnexus.com/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "semver": { + "version": "5.0.3", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + }, + "socks-proxy-agent": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", + "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "extend": "3.0.1", + "socks": "1.1.10" + } + } + } + }, + "nise": { + "version": "1.4.1", + "resolved": "https://npm.corp.appnexus.com/nise/-/nise-1.4.1.tgz", + "integrity": "sha512-9JX3YwoIt3kS237scmSSOpEv7vCukVzLfwK0I0XhocDSHUANid8ZHnLEULbbSkfeMn98B2y5kphIWzZUylESRQ==", + "dev": true, + "requires": { + "@sinonjs/formatio": "2.0.0", + "just-extend": "1.1.27", + "lolex": "2.7.0", + "path-to-regexp": "1.7.0", + "text-encoding": "0.6.4" + } + }, + "node-int64": { + "version": "0.3.3", + "resolved": "https://npm.corp.appnexus.com/node-int64/-/node-int64-0.3.3.tgz", + "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", + "dev": true + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.2.0", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.6", + "stream-browserify": "2.0.1", + "stream-http": "2.8.3", + "string_decoder": "1.1.1", + "timers-browserify": "2.0.10", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.4", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "url": { + "version": "0.11.0", + "resolved": "https://npm.corp.appnexus.com/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + } + } + }, + "nodemailer": { + "version": "2.7.2", + "resolved": "https://npm.corp.appnexus.com/nodemailer/-/nodemailer-2.7.2.tgz", + "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", + "dev": true, + "optional": true, + "requires": { + "libmime": "3.0.0", + "mailcomposer": "4.0.1", + "nodemailer-direct-transport": "3.3.2", + "nodemailer-shared": "1.1.0", + "nodemailer-smtp-pool": "2.8.2", + "nodemailer-smtp-transport": "2.7.2", + "socks": "1.1.9" + }, + "dependencies": { + "socks": { + "version": "1.1.9", + "resolved": "https://npm.corp.appnexus.com/socks/-/socks-1.1.9.tgz", + "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", + "dev": true, + "optional": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + } + } + }, + "nodemailer-direct-transport": { + "version": "3.3.2", + "resolved": "https://npm.corp.appnexus.com/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://npm.corp.appnexus.com/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", + "dev": true + }, + "nodemailer-shared": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", + "dev": true, + "requires": { + "nodemailer-fetch": "1.6.0" + } + }, + "nodemailer-smtp-pool": { + "version": "2.8.2", + "resolved": "https://npm.corp.appnexus.com/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-smtp-transport": { + "version": "2.7.2", + "resolved": "https://npm.corp.appnexus.com/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "https://npm.corp.appnexus.com/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://npm.corp.appnexus.com/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://npm.corp.appnexus.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "requires": { + "prepend-http": "2.0.0", + "query-string": "5.1.1", + "sort-keys": "2.0.0" + } + }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "null-check": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://npm.corp.appnexus.com/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://npm.corp.appnexus.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://npm.corp.appnexus.com/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://npm.corp.appnexus.com/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://npm.corp.appnexus.com/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://npm.corp.appnexus.com/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.1" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://npm.corp.appnexus.com/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "open": { + "version": "0.0.5", + "resolved": "https://npm.corp.appnexus.com/open/-/open-0.0.5.tgz", + "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", + "dev": true + }, + "openurl": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/openurl/-/openurl-1.1.1.tgz", + "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://npm.corp.appnexus.com/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://npm.corp.appnexus.com/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optimize-js": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/optimize-js/-/optimize-js-1.0.3.tgz", + "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", + "dev": true, + "requires": { + "acorn": "3.3.0", + "concat-stream": "1.6.2", + "estree-walker": "0.3.1", + "magic-string": "0.16.0", + "yargs": "4.8.1" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://npm.corp.appnexus.com/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://npm.corp.appnexus.com/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/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.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://npm.corp.appnexus.com/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true, + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "lodash.assign": "4.2.0", + "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", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" + } + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://npm.corp.appnexus.com/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "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", + "wordwrap": "1.0.0" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://npm.corp.appnexus.com/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.1" + }, + "dependencies": { + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://npm.corp.appnexus.com/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "over": { + "version": "0.0.5", + "resolved": "https://npm.corp.appnexus.com/over/-/over-0.0.5.tgz", + "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", + "dev": true + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://npm.corp.appnexus.com/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.3.0" + } + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dev": true, + "requires": { + "p-finally": "1.0.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pac-proxy-agent": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", + "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", + "dev": true, + "optional": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0", + "get-uri": "2.0.2", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "pac-resolver": "3.0.0", + "raw-body": "2.3.3", + "socks-proxy-agent": "3.0.1" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true, + "optional": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "optional": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://npm.corp.appnexus.com/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "optional": true, + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.5.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "optional": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + } + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "degenerator": "1.0.4", + "ip": "1.1.5", + "netmask": "1.0.6", + "thunkify": "2.1.2" + } + }, + "pako": { + "version": "1.0.6", + "resolved": "https://npm.corp.appnexus.com/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://npm.corp.appnexus.com/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true, + "requires": { + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" + } + }, + "parse-domain": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/parse-domain/-/parse-domain-2.1.1.tgz", + "integrity": "sha512-xOQ/B+pnS8uzqFMHcS7VS9J7Cn+rFyPlGIoDMFL2e5g/tPhlpa8MSHQmFAlABHBKPCXgOOxFt5PFNdEmwtwvqQ==", + "dev": true, + "requires": { + "chai": "4.1.2", + "fs-copy-file-sync": "1.1.1", + "got": "8.3.1", + "mkdirp": "0.5.1", + "mocha": "4.1.0" + }, + "dependencies": { + "chai": { + "version": "4.1.2", + "resolved": "https://npm.corp.appnexus.com/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "diff": { + "version": "3.3.1", + "resolved": "https://npm.corp.appnexus.com/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://npm.corp.appnexus.com/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + } + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + } + } + }, + "parse-entities": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/parse-entities/-/parse-entities-1.1.2.tgz", + "integrity": "sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg==", + "dev": true, + "requires": { + "character-entities": "1.2.2", + "character-entities-legacy": "1.1.2", + "character-reference-invalid": "1.1.2", + "is-alphanumerical": "1.0.2", + "is-decimal": "1.0.2", + "is-hexadecimal": "1.0.2" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-git-config": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/parse-git-config/-/parse-git-config-0.2.0.tgz", + "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", + "dev": true, + "requires": { + "ini": "1.3.5" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.2" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parse-url": { + "version": "1.3.11", + "resolved": "https://npm.corp.appnexus.com/parse-url/-/parse-url-1.3.11.tgz", + "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", + "dev": true, + "requires": { + "is-ssh": "1.3.0", + "protocols": "1.4.6" + } + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://npm.corp.appnexus.com/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://npm.corp.appnexus.com/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://npm.corp.appnexus.com/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://npm.corp.appnexus.com/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://npm.corp.appnexus.com/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-proxy": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/path-proxy/-/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "dev": true, + "optional": true, + "requires": { + "inflection": "1.3.8" + }, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "https://npm.corp.appnexus.com/inflection/-/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", + "dev": true, + "optional": true + } + } + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://npm.corp.appnexus.com/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://npm.corp.appnexus.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pause": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/pause/-/pause-0.1.0.tgz", + "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", + "dev": true + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://npm.corp.appnexus.com/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://npm.corp.appnexus.com/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "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://npm.corp.appnexus.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://npm.corp.appnexus.com/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "2.1.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "1.1.0", + "arr-diff": "4.0.0", + "arr-union": "3.1.0", + "extend-shallow": "3.0.2" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://npm.corp.appnexus.com/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://npm.corp.appnexus.com/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://npm.corp.appnexus.com/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "promisify-call": { + "version": "2.0.4", + "resolved": "https://npm.corp.appnexus.com/promisify-call/-/promisify-call-2.0.4.tgz", + "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", + "dev": true, + "optional": true, + "requires": { + "with-callback": "1.0.2" + } + }, + "property-information": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/property-information/-/property-information-3.2.0.tgz", + "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE=", + "dev": true + }, + "protocols": { + "version": "1.4.6", + "resolved": "https://npm.corp.appnexus.com/protocols/-/protocols-1.4.6.tgz", + "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", + "dev": true + }, + "proxy-agent": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/proxy-agent/-/proxy-agent-3.0.0.tgz", + "integrity": "sha512-g6n6vnk8fRf705ShN+FEXFG/SDJaW++lSs0d9KaJh4uBWW/wi7en4Cpo5VYQW3SZzAE121lhB/KLQrbURoubZw==", + "dev": true, + "optional": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "pac-proxy-agent": "2.0.2", + "proxy-from-env": "1.0.0", + "socks-proxy-agent": "3.0.1" + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true, + "optional": true + }, + "proxyquire": { + "version": "1.8.0", + "resolved": "https://npm.corp.appnexus.com/proxyquire/-/proxyquire-1.8.0.tgz", + "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", + "dev": true, + "requires": { + "fill-keys": "1.0.2", + "module-not-found-error": "1.0.1", + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://npm.corp.appnexus.com/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://npm.corp.appnexus.com/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" + } + }, + "pullstream": { + "version": "0.4.1", + "resolved": "https://npm.corp.appnexus.com/pullstream/-/pullstream-0.4.1.tgz", + "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", + "dev": true, + "requires": { + "over": "0.0.5", + "readable-stream": "1.0.34", + "setimmediate": "1.0.5", + "slice-stream": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://npm.corp.appnexus.com/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://npm.corp.appnexus.com/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/q/-/q-1.3.0.tgz", + "integrity": "sha1-hQ15+MuDHZLhA7Rkg+TjXTRkAFA=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.3.2", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://npm.corp.appnexus.com/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "requires": { + "decode-uri-component": "0.2.0", + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "0.0.3", + "resolved": "https://npm.corp.appnexus.com/querystringify/-/querystringify-0.0.3.tgz", + "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", + "dev": true + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "dev": true + }, + "randomatic": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "dev": true, + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://npm.corp.appnexus.com/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.2" + } + }, + "range-parser": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/range-parser/-/range-parser-1.0.3.tgz", + "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", + "dev": true + }, + "raw-body": { + "version": "1.1.7", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", + "dev": true, + "requires": { + "bytes": "1.0.0", + "string_decoder": "0.10.31" + }, + "dependencies": { + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/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.4.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "3.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.6", + "set-immediate-shim": "1.0.1" + } + }, + "readline2": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/readline2/-/readline2-0.1.1.tgz", + "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", + "dev": true, + "requires": { + "mute-stream": "0.0.4", + "strip-ansi": "2.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true + }, + "mute-stream": { + "version": "0.0.4", + "resolved": "https://npm.corp.appnexus.com/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", + "dev": true + }, + "strip-ansi": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", + "dev": true, + "requires": { + "ansi-regex": "1.1.1" + } + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://npm.corp.appnexus.com/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.7.1" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "redis": { + "version": "2.8.0", + "resolved": "https://npm.corp.appnexus.com/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "dev": true, + "optional": true, + "requires": { + "double-ended-queue": "2.1.0-0", + "redis-commands": "1.3.5", + "redis-parser": "2.6.0" + } + }, + "redis-commands": { + "version": "1.3.5", + "resolved": "https://npm.corp.appnexus.com/redis-commands/-/redis-commands-1.3.5.tgz", + "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==", + "dev": true, + "optional": true + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://npm.corp.appnexus.com/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", + "dev": true, + "optional": true + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://npm.corp.appnexus.com/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://npm.corp.appnexus.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://npm.corp.appnexus.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.4.0", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://npm.corp.appnexus.com/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remark": { + "version": "9.0.0", + "resolved": "https://npm.corp.appnexus.com/remark/-/remark-9.0.0.tgz", + "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", + "dev": true, + "requires": { + "remark-parse": "5.0.0", + "remark-stringify": "5.0.0", + "unified": "6.2.0" + } + }, + "remark-html": { + "version": "7.0.0", + "resolved": "https://npm.corp.appnexus.com/remark-html/-/remark-html-7.0.0.tgz", + "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", + "dev": true, + "requires": { + "hast-util-sanitize": "1.1.2", + "hast-util-to-html": "3.1.0", + "mdast-util-to-hast": "3.0.1", + "xtend": "4.0.1" + } + }, + "remark-parse": { + "version": "5.0.0", + "resolved": "https://npm.corp.appnexus.com/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true, + "requires": { + "collapse-white-space": "1.0.4", + "is-alphabetical": "1.0.2", + "is-decimal": "1.0.2", + "is-whitespace-character": "1.0.2", + "is-word-character": "1.0.2", + "markdown-escapes": "1.0.2", + "parse-entities": "1.1.2", + "repeat-string": "1.6.1", + "state-toggle": "1.0.1", + "trim": "0.0.1", + "trim-trailing-lines": "1.1.1", + "unherit": "1.1.1", + "unist-util-remove-position": "1.1.2", + "vfile-location": "2.0.3", + "xtend": "4.0.1" + } + }, + "remark-reference-links": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/remark-reference-links/-/remark-reference-links-4.0.1.tgz", + "integrity": "sha1-AhrtHFXBh9cSs8dtAFe/UQ0wC6c=", + "dev": true, + "requires": { + "unist-util-visit": "1.3.1" + } + }, + "remark-slug": { + "version": "5.0.0", + "resolved": "https://npm.corp.appnexus.com/remark-slug/-/remark-slug-5.0.0.tgz", + "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", + "dev": true, + "requires": { + "github-slugger": "1.2.0", + "mdast-util-to-string": "1.0.4", + "unist-util-visit": "1.3.1" + } + }, + "remark-stringify": { + "version": "5.0.0", + "resolved": "https://npm.corp.appnexus.com/remark-stringify/-/remark-stringify-5.0.0.tgz", + "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", + "dev": true, + "requires": { + "ccount": "1.0.3", + "is-alphanumeric": "1.0.0", + "is-decimal": "1.0.2", + "is-whitespace-character": "1.0.2", + "longest-streak": "2.0.2", + "markdown-escapes": "1.0.2", + "markdown-table": "1.1.2", + "mdast-util-compact": "1.0.1", + "parse-entities": "1.1.2", + "repeat-string": "1.6.1", + "state-toggle": "1.0.1", + "stringify-entities": "1.3.2", + "unherit": "1.1.1", + "xtend": "4.0.1" + } + }, + "remark-toc": { + "version": "5.0.0", + "resolved": "https://npm.corp.appnexus.com/remark-toc/-/remark-toc-5.0.0.tgz", + "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", + "dev": true, + "requires": { + "mdast-util-toc": "2.0.1", + "remark-slug": "5.0.0" + } + }, + "remote-origin-url": { + "version": "0.4.0", + "resolved": "https://npm.corp.appnexus.com/remote-origin-url/-/remote-origin-url-0.4.0.tgz", + "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", + "dev": true, + "requires": { + "parse-git-config": "0.2.0" + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "1.1.6", + "is-utf8": "0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "3.0.0", + "safe-buffer": "5.1.2", + "through2": "2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://npm.corp.appnexus.com/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replacestream": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/replacestream/-/replacestream-0.1.3.tgz", + "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "request": { + "version": "2.79.0", + "resolved": "https://npm.corp.appnexus.com/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.7.0", + "caseless": "0.11.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.4.3", + "uuid": "3.2.1" + } + }, + "requestretry": { + "version": "1.13.0", + "resolved": "https://npm.corp.appnexus.com/requestretry/-/requestretry-1.13.0.tgz", + "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", + "dev": true, + "optional": true, + "requires": { + "extend": "3.0.1", + "lodash": "4.17.10", + "request": "2.79.0", + "when": "3.7.8" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "requirejs": { + "version": "2.3.5", + "resolved": "https://npm.corp.appnexus.com/requirejs/-/requirejs-2.3.5.tgz", + "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.7.1", + "resolved": "https://npm.corp.appnexus.com/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "response-time": { + "version": "2.3.2", + "resolved": "https://npm.corp.appnexus.com/response-time/-/response-time-2.3.2.tgz", + "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", + "dev": true, + "requires": { + "depd": "1.1.2", + "on-headers": "1.0.1" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + } + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "1.0.1" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://npm.corp.appnexus.com/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rewire": { + "version": "2.5.2", + "resolved": "https://npm.corp.appnexus.com/rewire/-/rewire-2.5.2.tgz", + "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", + "dev": true + }, + "rgb2hex": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/rgb2hex/-/rgb2hex-0.1.1.tgz", + "integrity": "sha512-icFtYF9bLbxRZ6zYlp28622lBM7Ae0ylPT+ob0SBZdd2p1FN5MoOClpwPcjT9TgXDLS8jyXlw3yVtHQZU3/vvg==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://npm.corp.appnexus.com/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://npm.corp.appnexus.com/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "rndm": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", + "dev": true + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx": { + "version": "2.5.3", + "resolved": "https://npm.corp.appnexus.com/rx/-/rx-2.5.3.tgz", + "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", + "dev": true + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://npm.corp.appnexus.com/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://npm.corp.appnexus.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://npm.corp.appnexus.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-json-parse": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://npm.corp.appnexus.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "samsam": { + "version": "1.3.0", + "resolved": "https://npm.corp.appnexus.com/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "dev": true + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://npm.corp.appnexus.com/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.0.0", + "json-schema-traverse": "0.3.1" + } + } + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "send": { + "version": "0.13.2", + "resolved": "https://npm.corp.appnexus.com/send/-/send-0.13.2.tgz", + "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", + "dev": true, + "requires": { + "debug": "2.2.0", + "depd": "1.1.2", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "mime": { + "version": "1.3.4", + "resolved": "https://npm.corp.appnexus.com/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "statuses": { + "version": "1.2.1", + "resolved": "https://npm.corp.appnexus.com/statuses/-/statuses-1.2.1.tgz", + "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", + "dev": true + } + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://npm.corp.appnexus.com/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "serve-favicon": { + "version": "2.3.2", + "resolved": "https://npm.corp.appnexus.com/serve-favicon/-/serve-favicon-2.3.2.tgz", + "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", + "dev": true, + "requires": { + "etag": "1.7.0", + "fresh": "0.3.0", + "ms": "0.7.2", + "parseurl": "1.3.2" + }, + "dependencies": { + "ms": { + "version": "0.7.2", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true + } + } + }, + "serve-index": { + "version": "1.7.3", + "resolved": "https://npm.corp.appnexus.com/serve-index/-/serve-index-1.7.3.tgz", + "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", + "dev": true, + "requires": { + "accepts": "1.2.13", + "batch": "0.5.3", + "debug": "2.2.0", + "escape-html": "1.0.3", + "http-errors": "1.3.1", + "mime-types": "2.1.18", + "parseurl": "1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "serve-static": { + "version": "1.10.3", + "resolved": "https://npm.corp.appnexus.com/serve-static/-/serve-static-1.10.3.tgz", + "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", + "dev": true, + "requires": { + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.13.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://npm.corp.appnexus.com/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://npm.corp.appnexus.com/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.8.2", + "resolved": "https://npm.corp.appnexus.com/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://npm.corp.appnexus.com/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sinon": { + "version": "4.5.0", + "resolved": "https://npm.corp.appnexus.com/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", + "dev": true, + "requires": { + "@sinonjs/formatio": "2.0.0", + "diff": "3.5.0", + "lodash.get": "4.4.2", + "lolex": "2.7.0", + "nise": "1.4.1", + "supports-color": "5.4.0", + "type-detect": "4.0.8" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://npm.corp.appnexus.com/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + } + } + }, + "slack-node": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/slack-node/-/slack-node-0.2.0.tgz", + "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", + "dev": true, + "optional": true, + "requires": { + "requestretry": "1.13.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "slice-stream": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/slice-stream/-/slice-stream-1.0.0.tgz", + "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://npm.corp.appnexus.com/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", + "dev": true + }, + "smtp-connection": { + "version": "2.12.0", + "resolved": "https://npm.corp.appnexus.com/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", + "dev": true, + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://npm.corp.appnexus.com/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "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.2", + "use": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://npm.corp.appnexus.com/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "socket.io": { + "version": "2.0.4", + "resolved": "https://npm.corp.appnexus.com/socket.io/-/socket.io-2.0.4.tgz", + "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "engine.io": "3.1.5", + "socket.io-adapter": "1.1.1", + "socket.io-client": "2.0.4", + "socket.io-parser": "3.1.3" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.0.4", + "resolved": "https://npm.corp.appnexus.com/socket.io-client/-/socket.io-client-2.0.4.tgz", + "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "2.6.9", + "engine.io-client": "3.1.6", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "3.1.3", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-parser": { + "version": "3.1.3", + "resolved": "https://npm.corp.appnexus.com/socket.io-parser/-/socket.io-parser-3.1.3.tgz", + "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "3.1.0", + "has-binary2": "1.0.3", + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "socks": { + "version": "1.1.10", + "resolved": "https://npm.corp.appnexus.com/socks/-/socks-1.1.10.tgz", + "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", + "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", + "dev": true, + "requires": { + "agent-base": "4.2.0", + "socks": "1.1.10" + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://npm.corp.appnexus.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://npm.corp.appnexus.com/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://npm.corp.appnexus.com/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "space-separated-tokens": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", + "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", + "dev": true, + "requires": { + "trim": "0.0.1" + } + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, + "split": { + "version": "0.3.3", + "resolved": "https://npm.corp.appnexus.com/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://npm.corp.appnexus.com/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "state-toggle": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/state-toggle/-/state-toggle-1.0.1.tgz", + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://npm.corp.appnexus.com/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://npm.corp.appnexus.com/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://npm.corp.appnexus.com/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stream-array": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.1.5", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://npm.corp.appnexus.com/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "0.1.1" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.3.6" + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://npm.corp.appnexus.com/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "dev": true + }, + "stream-counter": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/stream-counter/-/stream-counter-0.2.0.tgz", + "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://npm.corp.appnexus.com/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://npm.corp.appnexus.com/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true, + "requires": { + "date-format": "1.2.0", + "debug": "3.1.0", + "mkdirp": "0.5.1", + "readable-stream": "2.3.6" + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "string-replace-webpack-plugin": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", + "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", + "dev": true, + "requires": { + "async": "0.2.10", + "css-loader": "0.9.1", + "file-loader": "0.8.5", + "loader-utils": "0.2.17", + "style-loader": "0.8.3" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://npm.corp.appnexus.com/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://npm.corp.appnexus.com/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" + } + } + } + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "stringify-entities": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/stringify-entities/-/stringify-entities-1.3.2.tgz", + "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", + "dev": true, + "requires": { + "character-entities-html4": "1.1.2", + "character-entities-legacy": "1.1.2", + "is-alphanumerical": "1.0.2", + "is-hexadecimal": "1.0.2" + } + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://npm.corp.appnexus.com/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "style-loader": { + "version": "0.8.3", + "resolved": "https://npm.corp.appnexus.com/style-loader/-/style-loader-0.8.3.tgz", + "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", + "dev": true, + "optional": true, + "requires": { + "loader-utils": "0.2.17" + }, + "dependencies": { + "loader-utils": { + "version": "0.2.17", + "resolved": "https://npm.corp.appnexus.com/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "optional": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + } + } + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://npm.corp.appnexus.com/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.4.1", + "lodash": "4.17.10", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://npm.corp.appnexus.com/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.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://npm.corp.appnexus.com/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "tar-stream": { + "version": "1.1.5", + "resolved": "https://npm.corp.appnexus.com/tar-stream/-/tar-stream-1.1.5.tgz", + "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", + "dev": true, + "requires": { + "bl": "0.9.5", + "end-of-stream": "1.4.1", + "readable-stream": "1.0.34", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "ternary-stream": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/ternary-stream/-/ternary-stream-2.0.1.tgz", + "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "dev": true, + "requires": { + "duplexify": "3.6.0", + "fork-stream": "0.0.4", + "merge-stream": "1.0.1", + "through2": "2.0.3" + } + }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://npm.corp.appnexus.com/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "textextensions": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/textextensions/-/textextensions-1.0.2.tgz", + "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://npm.corp.appnexus.com/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://npm.corp.appnexus.com/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://npm.corp.appnexus.com/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", + "dev": true + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://npm.corp.appnexus.com/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "timers-ext": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/timers-ext/-/timers-ext-0.1.5.tgz", + "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==", + "requires": { + "es5-ext": "0.10.45", + "next-tick": "1.0.0" + } + }, + "timespan": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "dev": true, + "optional": true + }, + "tiny-lr": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/tiny-lr/-/tiny-lr-1.1.1.tgz", + "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "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.1", + "qs": "6.5.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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-array": { + "version": "0.1.4", + "resolved": "https://npm.corp.appnexus.com/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://npm.corp.appnexus.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "2.0.3" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://npm.corp.appnexus.com/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://npm.corp.appnexus.com/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-lines": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/trim-lines/-/trim-lines-1.1.1.tgz", + "integrity": "sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", + "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", + "dev": true + }, + "trough": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/trough/-/trough-1.0.2.tgz", + "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", + "dev": true + }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://npm.corp.appnexus.com/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://npm.corp.appnexus.com/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://npm.corp.appnexus.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://npm.corp.appnexus.com/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://npm.corp.appnexus.com/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://npm.corp.appnexus.com/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://npm.corp.appnexus.com/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://npm.corp.appnexus.com/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" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://npm.corp.appnexus.com/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://npm.corp.appnexus.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "uid-safe": { + "version": "2.1.4", + "resolved": "https://npm.corp.appnexus.com/uid-safe/-/uid-safe-2.1.4.tgz", + "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", + "dev": true, + "requires": { + "random-bytes": "1.0.0" + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://npm.corp.appnexus.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://npm.corp.appnexus.com/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "unherit": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/unherit/-/unherit-1.1.1.tgz", + "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "xtend": "4.0.1" + } + }, + "unified": { + "version": "6.2.0", + "resolved": "https://npm.corp.appnexus.com/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "dev": true, + "requires": { + "bail": "1.0.3", + "extend": "3.0.1", + "is-plain-obj": "1.1.0", + "trough": "1.0.2", + "vfile": "2.3.0", + "x-is-string": "0.1.0" + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://npm.corp.appnexus.com/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://npm.corp.appnexus.com/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "unist-builder": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/unist-builder/-/unist-builder-1.0.2.tgz", + "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", + "dev": true, + "requires": { + "object-assign": "4.1.1" + } + }, + "unist-util-generated": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/unist-util-generated/-/unist-util-generated-1.1.2.tgz", + "integrity": "sha512-1HcwiEO62dr0XWGT+abVK4f0aAm8Ik8N08c5nAYVmuSxfvpA9rCcNyX/le8xXj1pJK5nBrGlZefeWB6bN8Pstw==", + "dev": true + }, + "unist-util-is": { + "version": "2.1.2", + "resolved": "https://npm.corp.appnexus.com/unist-util-is/-/unist-util-is-2.1.2.tgz", + "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", + "dev": true + }, + "unist-util-modify-children": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", + "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", + "dev": true, + "requires": { + "array-iterate": "1.1.2" + } + }, + "unist-util-position": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/unist-util-position/-/unist-util-position-3.0.1.tgz", + "integrity": "sha512-05QfJDPI7PE1BIUtAxeSV+cDx21xP7+tUZgSval5CA7tr0pHBwybF7OnEa1dOFqg6BfYH/qiMUnWwWj+Frhlww==", + "dev": true + }, + "unist-util-remove-position": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", + "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", + "dev": true, + "requires": { + "unist-util-visit": "1.3.1" + } + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", + "dev": true + }, + "unist-util-visit": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/unist-util-visit/-/unist-util-visit-1.3.1.tgz", + "integrity": "sha512-0fdB9EQJU0tho5tK0VzOJzAQpPv2LyLZ030b10GxuzAWEfvd54mpY7BMjQ1L69k2YNvL+SvxRzH0yUIehOO8aA==", + "dev": true, + "requires": { + "unist-util-is": "2.1.2" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://npm.corp.appnexus.com/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "unzip": { + "version": "0.1.11", + "resolved": "https://npm.corp.appnexus.com/unzip/-/unzip-0.1.11.tgz", + "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", + "dev": true, + "requires": { + "binary": "0.3.0", + "fstream": "0.1.31", + "match-stream": "0.0.2", + "pullstream": "0.4.1", + "readable-stream": "1.0.34", + "setimmediate": "1.0.5" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.10.3", + "resolved": "https://npm.corp.appnexus.com/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.4.1", + "resolved": "https://npm.corp.appnexus.com/url-parse/-/url-parse-1.4.1.tgz", + "integrity": "sha512-x95Td74QcvICAA0+qERaVkRpTGKyBHHYdwL2LXZm5t/gBtCB9KQSO/0zQgSTYEV1p0WcvSg79TLNPSvd5IDJMQ==", + "dev": true, + "requires": { + "querystringify": "2.0.0", + "requires-port": "1.0.0" + }, + "dependencies": { + "querystringify": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", + "dev": true + } + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "2.0.0" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true + }, + "use": { + "version": "3.1.0", + "resolved": "https://npm.corp.appnexus.com/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "useragent": { + "version": "2.2.1", + "resolved": "https://npm.corp.appnexus.com/useragent/-/useragent-2.2.1.tgz", + "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", + "dev": true, + "requires": { + "lru-cache": "2.2.4", + "tmp": "0.0.33" + }, + "dependencies": { + "lru-cache": { + "version": "2.2.4", + "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.2.4.tgz", + "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "dev": true + } + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://npm.corp.appnexus.com/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "uws": { + "version": "9.14.0", + "resolved": "https://npm.corp.appnexus.com/uws/-/uws-9.14.0.tgz", + "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://npm.corp.appnexus.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "vary": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/vary/-/vary-1.0.1.tgz", + "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://npm.corp.appnexus.com/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" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vfile": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true, + "requires": { + "is-buffer": "1.1.6", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "1.1.2", + "vfile-message": "1.0.1" + } + }, + "vfile-location": { + "version": "2.0.3", + "resolved": "https://npm.corp.appnexus.com/vfile-location/-/vfile-location-2.0.3.tgz", + "integrity": "sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==", + "dev": true + }, + "vfile-message": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/vfile-message/-/vfile-message-1.0.1.tgz", + "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", + "dev": true, + "requires": { + "unist-util-stringify-position": "1.1.2" + } + }, + "vfile-reporter": { + "version": "4.0.0", + "resolved": "https://npm.corp.appnexus.com/vfile-reporter/-/vfile-reporter-4.0.0.tgz", + "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", + "dev": true, + "requires": { + "repeat-string": "1.6.1", + "string-width": "1.0.2", + "supports-color": "4.5.0", + "unist-util-stringify-position": "1.1.2", + "vfile-statistics": "1.1.1" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "vfile-sort": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/vfile-sort/-/vfile-sort-2.1.1.tgz", + "integrity": "sha512-+fpTWKkVHwI6VF2xtkDTuCA6cH4UPLAxh+KxfU8g8pC0do5RSZCk1HXTTtMJguW0t5jC0PC19owjUZX9SGQ9tw==", + "dev": true + }, + "vfile-statistics": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/vfile-statistics/-/vfile-statistics-1.1.1.tgz", + "integrity": "sha512-dxUM6IYvGChHuwMT3dseyU5BHprNRXzAV0OHx1A769lVGsTiT50kU7BbpRFV+IE6oWmU+PwHdsTKfXhnDIRIgQ==", + "dev": true + }, + "vhost": { + "version": "3.0.2", + "resolved": "https://npm.corp.appnexus.com/vhost/-/vhost-3.0.2.tgz", + "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://npm.corp.appnexus.com/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.1.11", + "is-valid-glob": "1.0.0", + "lazystream": "1.0.0", + "lead": "1.0.0", + "object.assign": "4.1.0", + "pumpify": "1.5.1", + "readable-stream": "2.3.6", + "remove-bom-buffer": "3.0.0", + "remove-bom-stream": "1.2.0", + "resolve-options": "1.1.0", + "through2": "2.0.3", + "to-through": "2.0.0", + "value-or-function": "3.0.0", + "vinyl": "2.1.0", + "vinyl-sourcemap": "1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/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.1", + "graceful-fs": "4.1.11", + "normalize-path": "2.1.1", + "now-and-later": "2.0.0", + "remove-bom-buffer": "3.0.0", + "vinyl": "2.1.0" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://npm.corp.appnexus.com/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://npm.corp.appnexus.com/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "walk": { + "version": "2.3.13", + "resolved": "https://npm.corp.appnexus.com/walk/-/walk-2.3.13.tgz", + "integrity": "sha512-78SMe7To9U7kqVhSoGho3GfspA089ZDBIj2f8jElg2hi6lUCoagtDJ8sSMFNlpAh5Ib8Jt1gQ6Y7gh9mzHtFng==", + "dev": true, + "requires": { + "foreachasync": "3.0.0" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://npm.corp.appnexus.com/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "2.0.3", + "graceful-fs": "4.1.11", + "neo-async": "2.5.1" + } + }, + "webdriverio": { + "version": "3.4.0", + "resolved": "https://npm.corp.appnexus.com/webdriverio/-/webdriverio-3.4.0.tgz", + "integrity": "sha1-2dTTwxNm8FPhCvZEsOqtXoc6t7U=", + "dev": true, + "requires": { + "archiver": "0.14.4", + "array.from": "0.2.0", + "co": "4.6.0", + "css-parse": "2.0.0", + "css-value": "0.0.1", + "deepmerge": "0.2.10", + "ejs": "2.6.1", + "glob": "5.0.15", + "inquirer": "0.8.5", + "is-generator": "1.0.3", + "optimist": "0.6.1", + "q": "1.3.0", + "request": "2.49.0", + "rgb2hex": "0.1.1", + "supports-color": "1.3.1", + "url": "0.10.3", + "wgxpath": "1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true + }, + "asn1": { + "version": "0.1.11", + "resolved": "https://npm.corp.appnexus.com/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://npm.corp.appnexus.com/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://npm.corp.appnexus.com/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true + }, + "boom": { + "version": "0.4.2", + "resolved": "https://npm.corp.appnexus.com/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "caseless": { + "version": "0.8.0", + "resolved": "https://npm.corp.appnexus.com/caseless/-/caseless-0.8.0.tgz", + "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", + "dev": true + }, + "cli-width": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/cli-width/-/cli-width-1.1.1.tgz", + "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://npm.corp.appnexus.com/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://npm.corp.appnexus.com/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "dev": true, + "requires": { + "boom": "0.4.2" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://npm.corp.appnexus.com/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://npm.corp.appnexus.com/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://npm.corp.appnexus.com/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "dev": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime": "1.2.11" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://npm.corp.appnexus.com/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "hawk": { + "version": "1.1.1", + "resolved": "https://npm.corp.appnexus.com/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "dev": true, + "requires": { + "boom": "0.4.2", + "cryptiles": "0.2.2", + "hoek": "0.9.1", + "sntp": "0.2.4" + } + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://npm.corp.appnexus.com/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://npm.corp.appnexus.com/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "inquirer": { + "version": "0.8.5", + "resolved": "https://npm.corp.appnexus.com/inquirer/-/inquirer-0.8.5.tgz", + "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", + "dev": true, + "requires": { + "ansi-regex": "1.1.1", + "chalk": "1.1.3", + "cli-width": "1.1.1", + "figures": "1.7.0", + "lodash": "3.10.1", + "readline2": "0.1.1", + "rx": "2.5.3", + "through": "2.3.8" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "mime": { + "version": "1.2.11", + "resolved": "https://npm.corp.appnexus.com/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://npm.corp.appnexus.com/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true + }, + "oauth-sign": { + "version": "0.5.0", + "resolved": "https://npm.corp.appnexus.com/oauth-sign/-/oauth-sign-0.5.0.tgz", + "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", + "dev": true + }, + "qs": { + "version": "2.3.3", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + }, + "request": { + "version": "2.49.0", + "resolved": "https://npm.corp.appnexus.com/request/-/request-2.49.0.tgz", + "integrity": "sha1-DU9jSNwzSAWbVT5Ntg/SR43mYqc=", + "dev": true, + "requires": { + "aws-sign2": "0.5.0", + "bl": "0.9.5", + "caseless": "0.8.0", + "combined-stream": "0.0.7", + "forever-agent": "0.5.2", + "form-data": "0.1.4", + "hawk": "1.1.1", + "http-signature": "0.10.1", + "json-stringify-safe": "5.0.1", + "mime-types": "1.0.2", + "node-uuid": "1.4.8", + "oauth-sign": "0.5.0", + "qs": "2.3.3", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.4.3" + } + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://npm.corp.appnexus.com/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "supports-color": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-1.3.1.tgz", + "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", + "dev": true + } + } + }, + "webpack": { + "version": "3.12.0", + "resolved": "https://npm.corp.appnexus.com/webpack/-/webpack-3.12.0.tgz", + "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", + "dev": true, + "requires": { + "acorn": "5.6.2", + "acorn-dynamic-import": "2.0.2", + "ajv": "6.2.0", + "ajv-keywords": "3.2.0", + "async": "2.6.1", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.6.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "async": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "4.17.10" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://npm.corp.appnexus.com/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.2", + "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.1", + "yargs-parser": "7.0.0" + } + } + } + }, + "webpack-core": { + "version": "0.6.9", + "resolved": "https://npm.corp.appnexus.com/webpack-core/-/webpack-core-0.6.9.tgz", + "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", + "dev": true, + "requires": { + "source-list-map": "0.1.8", + "source-map": "0.4.4" + }, + "dependencies": { + "source-list-map": { + "version": "0.1.8", + "resolved": "https://npm.corp.appnexus.com/source-list-map/-/source-list-map-0.1.8.tgz", + "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "webpack-dev-middleware": { + "version": "1.12.2", + "resolved": "https://npm.corp.appnexus.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "dev": true, + "requires": { + "memory-fs": "0.4.1", + "mime": "1.6.0", + "path-is-absolute": "1.0.1", + "range-parser": "1.0.3", + "time-stamp": "2.0.0" + }, + "dependencies": { + "time-stamp": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/time-stamp/-/time-stamp-2.0.0.tgz", + "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "dev": true + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + } + }, + "webpack-stream": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/webpack-stream/-/webpack-stream-3.2.0.tgz", + "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", + "dev": true, + "requires": { + "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://npm.corp.appnexus.com/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://npm.corp.appnexus.com/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.2" + } + }, + "browserify-aes": { + "version": "0.4.0", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://npm.corp.appnexus.com/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "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.1.0" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/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": { + "version": "1.0.4", + "resolved": "https://npm.corp.appnexus.com/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "crypto-browserify": { + "version": "3.3.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "enhanced-resolve": { + "version": "0.9.1", + "resolved": "https://npm.corp.appnexus.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", + "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.2.0", + "tapable": "0.1.10" + }, + "dependencies": { + "memory-fs": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/memory-fs/-/memory-fs-0.2.0.tgz", + "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", + "dev": true + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "interpret": { + "version": "0.6.6", + "resolved": "https://npm.corp.appnexus.com/interpret/-/interpret-0.6.6.tgz", + "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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" + } + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://npm.corp.appnexus.com/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "memory-fs": { + "version": "0.3.0", + "resolved": "https://npm.corp.appnexus.com/memory-fs/-/memory-fs-0.3.0.tgz", + "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", + "dev": true, + "requires": { + "errno": "0.1.7", + "readable-stream": "2.3.6" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "node-libs-browser": { + "version": "0.7.0", + "resolved": "https://npm.corp.appnexus.com/node-libs-browser/-/node-libs-browser-0.7.0.tgz", + "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.1.4", + "buffer": "4.9.1", + "console-browserify": "1.1.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.6", + "stream-browserify": "2.0.1", + "stream-http": "2.8.3", + "string_decoder": "0.10.31", + "timers-browserify": "2.0.10", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.4", + "vm-browserify": "0.0.4" + } + }, + "os-browserify": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/os-browserify/-/os-browserify-0.2.1.tgz", + "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://npm.corp.appnexus.com/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "ripemd160": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/ripemd160/-/ripemd160-0.2.0.tgz", + "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", + "dev": true + }, + "sha.js": { + "version": "2.2.6", + "resolved": "https://npm.corp.appnexus.com/sha.js/-/sha.js-2.2.6.tgz", + "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + }, + "tapable": { + "version": "0.1.10", + "resolved": "https://npm.corp.appnexus.com/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "dev": true + }, + "uglify-js": { + "version": "2.7.5", + "resolved": "https://npm.corp.appnexus.com/uglify-js/-/uglify-js-2.7.5.tgz", + "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", + "dev": true, + "requires": { + "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://npm.corp.appnexus.com/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://npm.corp.appnexus.com/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://npm.corp.appnexus.com/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "watchpack": { + "version": "0.2.9", + "resolved": "https://npm.corp.appnexus.com/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", + "dev": true, + "requires": { + "async": "0.9.2", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://npm.corp.appnexus.com/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, + "webpack": { + "version": "1.15.0", + "resolved": "https://npm.corp.appnexus.com/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.1", + "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" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://npm.corp.appnexus.com/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://npm.corp.appnexus.com/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": "0.4.13", + "websocket-extensions": "0.1.3" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://npm.corp.appnexus.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "wgxpath": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/wgxpath/-/wgxpath-1.0.0.tgz", + "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", + "dev": true + }, + "when": { + "version": "3.7.8", + "resolved": "https://npm.corp.appnexus.com/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true, + "optional": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://npm.corp.appnexus.com/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://npm.corp.appnexus.com/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "dev": true + }, + "with-callback": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/with-callback/-/with-callback-1.0.2.tgz", + "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://npm.corp.appnexus.com/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" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://npm.corp.appnexus.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://npm.corp.appnexus.com/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://npm.corp.appnexus.com/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2", + "ultron": "1.1.1" + } + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://npm.corp.appnexus.com/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://npm.corp.appnexus.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://npm.corp.appnexus.com/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://npm.corp.appnexus.com/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://npm.corp.appnexus.com/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "1.3.3", + "resolved": "https://npm.corp.appnexus.com/yargs/-/yargs-1.3.3.tgz", + "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", + "dev": true + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://npm.corp.appnexus.com/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://npm.corp.appnexus.com/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "zip-stream": { + "version": "0.5.2", + "resolved": "https://npm.corp.appnexus.com/zip-stream/-/zip-stream-0.5.2.tgz", + "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", + "dev": true, + "requires": { + "compress-commons": "0.2.9", + "lodash": "3.2.0", + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lodash": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + } + } +} From 6be49803b4740bc27b2e6134246fe0671c66d7f4 Mon Sep 17 00:00:00 2001 From: Jeremy Scheff Date: Fri, 8 Jun 2018 15:15:48 -0400 Subject: [PATCH 0461/1594] In ix bid adapter, default to assuming media type is banner (#2632) --- modules/ixBidAdapter.js | 3 ++- test/spec/modules/ixBidAdapter_spec.js | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index 3384bb8f41b..f3ac8185f17 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -185,7 +185,8 @@ export const spec = { // If the bid request is for banner, then transform the bid request based on banner format. if (utils.deepAccess(validBidRequest, 'mediaTypes.banner') || - validBidRequest.mediaType === 'banner') { + validBidRequest.mediaType === 'banner' || + (validBidRequest.mediaType === undefined && utils.deepAccess(validBidRequest, 'mediaTypes.banner') === undefined)) { bannerImp = bidToBannerImp(validBidRequest); bannerImps.push(bannerImp); } diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 0e00a64aab4..92a7190bcb6 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -272,6 +272,21 @@ describe('IndexexchangeAdapter', () => { expect(requestStringTimeout.data.t).to.be.undefined; }); + + it('should default to assuming media type is banner', () => { + const bidsWithoutMediaType = [ + Object.assign({}, DEFAULT_BANNER_VALID_BID[0]) + ]; + delete bidsWithoutMediaType[0].mediaTypes; + + const request = spec.buildRequests(bidsWithoutMediaType); + const payload = JSON.parse(request.data.r); + + expect(payload.id).to.equal(bidsWithoutMediaType[0].bidderRequestId); + expect(payload.imp).to.exist; + expect(payload.imp).to.be.an('array'); + expect(payload.imp).to.have.lengthOf(1); + }); }); describe('interpretResponseBanner', () => { From f7c7905638a37b478b85f0e64971d3d24ddb55fe Mon Sep 17 00:00:00 2001 From: Paris Holley Date: Sat, 9 Jun 2018 11:39:19 -0700 Subject: [PATCH 0462/1594] MANTIS bidder: support tracking viewability of ad (#2696) * support tracking viewability of ad * safeframe support --- modules/mantisBidAdapter.js | 117 +++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 10 deletions(-) diff --git a/modules/mantisBidAdapter.js b/modules/mantisBidAdapter.js index ddbd849d1fd..daf1ab02cf2 100644 --- a/modules/mantisBidAdapter.js +++ b/modules/mantisBidAdapter.js @@ -7,7 +7,12 @@ function inIframe() { return true; } } - +function pixel(url, parent) { + var img = document.createElement('img'); + img.src = url; + img.style.cssText = 'display:none !important;'; + (parent || document.body).appendChild(img); +} function isDesktop(ignoreTouch) { var supportsTouch = !ignoreTouch && ('ontouchstart' in window || navigator.msMaxTouchPoints); if (inIframe()) { @@ -16,7 +21,72 @@ function isDesktop(ignoreTouch) { var width = window.innerWidth || window.document.documentElement.clientWidth || window.document.body.clientWidth; return !supportsTouch && (!width || width >= (window.mantis_breakpoint || 768)); } - +function onVisible(element, doOnVisible, time, pct) { + var started = null; + var notified = false; + var onNotVisible = null; + var whenNotVisible = function () { + if (notified && onNotVisible) { + onNotVisible(); + } + notified = false; + }; + var interval; + var listener; + var doCheck = function (winWidth, winHeight, rect) { + var hidden = typeof document.hidden !== 'undefined' && document.hidden; + if (rect.width == 0 || rect.height == 0 || hidden) { + return whenNotVisible(); + } + var minHeight = (rect.height * pct); + var minWidth = (rect.width * pct); + var inView = ( + ( + (rect.top < 0 && rect.bottom >= minHeight) || + (rect.top > 0 && (winHeight - rect.top) >= minHeight) + ) && + ( + (rect.left < 0 && rect.right >= minWidth) || + (rect.left > 0 && (winWidth - rect.left) >= minWidth) + ) + ); + if (!inView) { + return whenNotVisible(); + } + if (!started && time) { + started = Date.now(); + return whenNotVisible(); + } + if (time && Date.now() - started < time) { + return whenNotVisible(); + } + if (notified) { + return; + } + doOnVisible(function (ack) { + if (ack) { + notified = true; + } else { + interval && clearInterval(interval); + listener && listener(); + } + }, function (onHidden) { + onNotVisible = onHidden; + }); + }; + if (isAmp()) { + listener = window.context.observeIntersection(function (changes) { + changes.forEach(function (change) { + doCheck(change.rootBounds.width, change.rootBounds.height, change.boundingClientRect); + }); + }); + } + interval = setInterval(function () { + var winHeight = (window.innerHeight || document.documentElement.clientHeight); + var winWidth = (window.innerWidth || document.documentElement.clientWidth); + doCheck(winWidth, winHeight, element.getBoundingClientRect()); + }, 100); +} function storeUuid(uuid) { if (window.mantis_uuid) { return false; @@ -30,6 +100,13 @@ function storeUuid(uuid) { } } +function onMessage(type, callback) { + window.addEventListener('message', function (event) { + if (event.data.mantis && event.data.type == type) { + callback(event.data.data); + } + }, false); +} function isSendable(val) { if (val === null || val === undefined) { return false; @@ -42,19 +119,15 @@ function isSendable(val) { } return true; } - function isObject(value) { return Object.prototype.toString.call(value) === '[object Object]'; } - function isAmp() { return typeof window.context === 'object' && (window.context.tagName === 'AMP-AD' || window.context.tagName === 'AMP-EMBED'); } - function isSecure() { return document.location.protocol === 'https:'; } - function isArray(value) { return Object.prototype.toString.call(value) === '[object Array]'; } @@ -94,7 +167,8 @@ function buildMantisUrl(path, data, domain) { referrer: document.referrer, tz: new Date().getTimezoneOffset(), buster: new Date().getTime(), - secure: isSecure() + secure: isSecure(), + version: 8 }; if (!inIframe() || isAmp()) { params.mobile = !isAmp() && isDesktop(true) ? 'false' : 'true'; @@ -151,6 +225,7 @@ const spec = { } }); const query = { + measurable: true, bids: validBidRequests.map(function (bid) { return { bidId: bid.bidId, @@ -160,8 +235,7 @@ const spec = { }) }; }), - property: property, - version: 2 + property: property }; return { method: 'GET', @@ -200,7 +274,30 @@ const spec = { } } }; +onMessage('iframe', function (data) { + if (window.$sf) { + var viewed = false; + $sf.ext.register(data.width, data.height, function () { + if ($sf.ext.inViewPercentage() < 50 || viewed) { + return; + } + viewed = true; + pixel(data.pixel); + }); + } else { + var frames = document.getElementsByTagName('iframe'); + for (var i = 0; i < frames.length; i++) { + var frame = frames[i]; + if (frame.name == data.frame) { + onVisible(frame, function (stop) { + pixel(data.pixel); + stop(); + }, 1000, 0.50); + } + } + } +}); -export {spec}; +export { spec }; registerBidder(spec); From cbe67a3cf3aba6170425ecbd0745355070e84f07 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Mon, 11 Jun 2018 15:41:58 +0100 Subject: [PATCH 0463/1594] Update to XHB adapter (#2536) * xhb adapter added - use AppNexus test ad unit * adjusted adapter to set responseCPM to 0 and add in dealId * implemented suggested changes * implemented suggested changes * ran jscs fixer for xhb.js and added it to adapters.json * Xhb adapter: adding alias support * minor changes as per request * re-added default bidder settings * Bugfix: getBidRequest was missing utils * minor fix to _defaultBidderSettings * added size to defaultBidderSettings * XHB adapter updated to work with prebid 1.0 * XHB adapter updated to work with prebid 1.0 * updated xhb adapter to incorporate latest AN adapter changes * further fixes for 1.0 adapter * updated Adapter to latest version * indentation fixed * unit tests for xhb Adapter * xhbBidAdapter: removed brand from md file --- modules/xhbBidAdapter.js | 457 ++++++++++++++++++++++ modules/xhbBidAdapter.md | 100 +++++ test/spec/modules/xhbBidAdapter_spec.js | 495 ++++++++++++++++++++++++ 3 files changed, 1052 insertions(+) create mode 100644 modules/xhbBidAdapter.js create mode 100644 modules/xhbBidAdapter.md create mode 100644 test/spec/modules/xhbBidAdapter_spec.js diff --git a/modules/xhbBidAdapter.js b/modules/xhbBidAdapter.js new file mode 100644 index 00000000000..a372f14e96b --- /dev/null +++ b/modules/xhbBidAdapter.js @@ -0,0 +1,457 @@ +import { Renderer } from 'src/Renderer'; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; + +const BIDDER_CODE = 'xhb'; +const URL = '//ib.adnxs.com/ut/v3/prebid'; +const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', + 'startdelay', 'skippable', 'playback_method', 'frameworks']; +const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'language']; +const NATIVE_MAPPING = { + body: 'description', + cta: 'ctatext', + image: { + serverName: 'main_image', + requiredParams: { required: true }, + minimumParams: { sizes: [{}] }, + }, + icon: { + serverName: 'icon', + requiredParams: { required: true }, + minimumParams: { sizes: [{}] }, + }, + sponsoredBy: 'sponsored_by', +}; +const SOURCE = 'pbjs'; + +export const spec = { + code: BIDDER_CODE, + aliases: [], + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + + /** + * 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 !!(bid.params.placementId || (bid.params.member && bid.params.invCode)); + }, + + /** + * 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) { + const tags = bidRequests.map(bidToTag); + const userObjBid = find(bidRequests, hasUserInfo); + let userObj; + if (userObjBid) { + userObj = {}; + Object.keys(userObjBid.params.user) + .filter(param => includes(USER_PARAMS, param)) + .forEach(param => userObj[param] = userObjBid.params.user[param]); + } + + const memberIdBid = find(bidRequests, hasMemberId); + const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; + + const payload = { + tags: [...tags], + user: userObj, + sdk: { + source: SOURCE, + version: '$prebid.version$' + } + }; + if (member > 0) { + payload.member_id = member; + } + + 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 + }; + } + + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: URL, + data: payloadString, + 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, {bidderRequest}) { + serverResponse = serverResponse.body; + const bids = []; + if (!serverResponse || serverResponse.error) { + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; + if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } + utils.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); + } + } + }); + } + return bids; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' + }]; + } + } +}; + +function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { + const renderer = Renderer.install({ + id: rtbBid.renderer_id, + url: rtbBid.renderer_url, + config: rendererOptions, + loaded: false, + }); + + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + + renderer.setEventHandlers({ + impression: () => utils.logMessage('xhb outstream video impression event'), + loaded: () => utils.logMessage('xhb outstream video loaded event'), + ended: () => { + utils.logMessage('xhb outstream renderer video event'); + document.querySelector(`#${adUnitCode}`).style.display = 'none'; + } + }); + return renderer; +} + +/* Turn keywords parameter into ut-compatible format */ +function getKeywords(keywords) { + let arrs = []; + + utils._each(keywords, (v, k) => { + if (utils.isArray(v)) { + let values = []; + utils._each(v, (val) => { + val = utils.getValueString('keywords.' + k, val); + if (val) { values.push(val); } + }); + v = values; + } else { + v = utils.getValueString('keywords.' + k, v); + if (utils.isStr(v)) { + v = [v]; + } else { + return; + } // unsuported types - don't send a key + } + arrs.push({key: k, value: v}); + }); + + return arrs; +} + +/** + * Unpack the Server's Bid into a Prebid-compatible one. + * @param serverBid + * @param rtbBid + * @param bidderRequest + * @return Bid + */ +function newBid(serverBid, rtbBid, bidderRequest) { + const bid = { + requestId: serverBid.uuid, + cpm: 0.00, + creativeId: rtbBid.creative_id, + dealId: 99999999, + currency: 'USD', + netRevenue: true, + ttl: 300, + appnexus: { + buyerMemberId: rtbBid.buyer_member_id + } + }; + + if (rtbBid.rtb.video) { + Object.assign(bid, { + width: rtbBid.rtb.video.player_width, + height: rtbBid.rtb.video.player_height, + vastUrl: rtbBid.rtb.video.asset_url, + vastImpUrl: rtbBid.notify_url, + ttl: 3600 + }); + // This supports Outstream Video + if (rtbBid.renderer_url) { + const rendererOptions = utils.deepAccess( + bidderRequest.bids[0], + 'renderer.options' + ); + + Object.assign(bid, { + adResponse: serverBid, + renderer: newRenderer(bid.adUnitCode, rtbBid, rendererOptions) + }); + bid.adResponse.ad = bid.adResponse.ads[0]; + bid.adResponse.ad.video = bid.adResponse.ad.rtb.video; + } + } else if (rtbBid.rtb[NATIVE]) { + const nativeAd = rtbBid.rtb[NATIVE]; + bid[NATIVE] = { + title: nativeAd.title, + body: nativeAd.desc, + cta: nativeAd.ctatext, + sponsoredBy: nativeAd.sponsored, + clickUrl: nativeAd.link.url, + clickTrackers: nativeAd.link.click_trackers, + impressionTrackers: nativeAd.impression_trackers, + javascriptTrackers: nativeAd.javascript_trackers, + }; + 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 { + const url = rtbBid.rtb.trackers[0].impression_urls[0]; + const tracker = utils.createTrackPixelHtml(url); + bid.ad += tracker; + } catch (error) { + utils.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; + if (bid.params.reserve) { + tag.reserve = bid.params.reserve; + } + 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.externalImpId) { + tag.external_imp_id = bid.params.externalImpId; + } + if (!utils.isEmpty(bid.params.keywords)) { + tag.keywords = getKeywords(bid.params.keywords); + } + + if (bid.mediaType === NATIVE || utils.deepAccess(bid, `mediaTypes.${NATIVE}`)) { + tag.ad_types.push(NATIVE); + + if (bid.nativeParams) { + const nativeRequest = buildNativeRequest(bid.nativeParams); + tag[NATIVE] = {layouts: [nativeRequest]}; + } + } + + const videoMediaType = utils.deepAccess(bid, `mediaTypes.${VIDEO}`); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + + 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 => tag.video[param] = bid.params.video[param]); + } + + if ( + (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) || + (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER])) + ) { + tag.ad_types.push(BANNER); + } + + return tag; +} + +/* Turn bid request sizes into ut-compatible format */ +function transformSizes(requestSizes) { + let sizes = []; + let sizeObj = {}; + + 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); + } 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 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]); + + // minimum params are passed if no non-required params given on adunit + const minimumParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].minimumParams; + + if (requiredParams && minimumParams) { + // subtract required keys from adunit keys + const adunitKeys = Object.keys(params[key]); + const requiredKeys = Object.keys(requiredParams); + const remaining = adunitKeys.filter(key => !includes(requiredKeys, key)); + + // if none are left over, the minimum params needs to be sent + if (remaining.length === 0) { + request[requestKey] = Object.assign({}, request[requestKey], minimumParams); + } + } + }); + + return request; +} + +function outstreamRender(bid) { + // 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; + } +} + +registerBidder(spec); diff --git a/modules/xhbBidAdapter.md b/modules/xhbBidAdapter.md new file mode 100644 index 00000000000..bb95f4f499c --- /dev/null +++ b/modules/xhbBidAdapter.md @@ -0,0 +1,100 @@ +# Overview + +``` +Module Name: XHB Bid Adapter +Module Type: Bidder Adapter +Maintainer: daniel.hoffmann@xaxis.com +``` + +# Description + +Connects to Appnexus exchange for bids. + +XHB bid adapter supports Banner, Video (instream and outstream) and Native. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'xhb', + params: { + placementId: '10433394' + } + }] + }, + // Native adUnit + { + code: 'native-div', + sizes: [[300, 250], [300,600]], + mediaTypes: { + native: { + title: { + required: true, + len: 80 + }, + body: { + required: true + }, + image: { + required: true + }, + clickUrl: { + required: true + }, + } + }, + bids: [{ + bidder: 'xhb', + params: { + placementId: '9880618' + } + }] + }, + // Video instream adUnit + { + code: 'video-instream', + sizes: [640, 480], + mediaTypes: { + video: { + context: 'instream' + }, + }, + bids: [{ + bidder: 'xhb', + params: { + placementId: '9333431', + video: { + skippable: true, + playback_methods: ['auto_play_sound_off'] + } + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'outstream' + } + }, + bids: [ + { + bidder: 'xhb', + params: { + placementId: '5768085', + video: { + skippable: true, + playback_method: ['auto_play_sound_off'] + } + } + } + ] + } +]; +``` diff --git a/test/spec/modules/xhbBidAdapter_spec.js b/test/spec/modules/xhbBidAdapter_spec.js new file mode 100644 index 00000000000..98bc744224c --- /dev/null +++ b/test/spec/modules/xhbBidAdapter_spec.js @@ -0,0 +1,495 @@ +import { expect } from 'chai'; +import { spec } from 'modules/xhbBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; + +describe('xhbAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'xhb', + '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', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', () => { + 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', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'xhb', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should parse out private sizes', () => { + 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 source and verison to the tag', () => { + 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', () => { + ['banner', 'video', 'native'].forEach(type => { + 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]); + }); + }); + + it('should populate the ad_types array on outstream requests', () => { + 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']); + }); + + it('sends bid request to ENDPOINT via POST', () => { + 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', () => { + 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 + }); + }); + + it('should attach valid user params to the tag', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + user: { + external_uid: '123', + 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', + }); + }); + + it('should attach native params to the request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + title: {required: true}, + body: {required: true}, + image: {required: true, sizes: [{ width: 100, height: 100 }]}, + cta: {required: false}, + sponsoredBy: {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}, + main_image: {required: true, sizes: [{ width: 100, height: 100 }]}, + ctatext: {required: false}, + sponsored_by: {required: true} + }); + }); + + it('sets minimum native asset params when not provided on adunit', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: {required: true}, + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: {required: true, sizes: [{}]}, + }); + }); + + it('does not overwrite native ad unit params with mimimum params', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: { + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: { + required: true, + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + }, + }); + }); + + it('should convert keyword params to proper form and attaches to request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + 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'] + }]); + }); + + it('should add payment rules to the request', () => { + 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 gdpr consent information to the request', () => { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'xhb', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + bidderRequest.bids = bidRequests; + + const request = spec.buildRequests(bidRequests, bidderRequest); + 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; + }); + }); + + describe('interpretResponse', () => { + let response = { + 'version': '3.0.0', + 'tags': [ + { + 'uuid': '3db3773286ee59', + 'tag_id': 10433394, + 'auction_id': '4534722592064951574', + 'nobid': false, + 'no_ad_url': 'http://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, + 'rtb': { + 'banner': { + 'content': '', + 'width': 300, + 'height': 250 + }, + 'trackers': [ + { + 'impression_urls': [ + 'http://lax1-ib.adnxs.com/impression' + ], + 'video_events': {} + } + ] + } + } + ] + } + ] + }; + + it('should get correct bid response', () => { + let expectedResponse = [ + { + 'requestId': '3db3773286ee59', + 'cpm': 0.5, + 'creativeId': 29681110, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true, + 'appnexus': { + 'buyerMemberId': 958 + } + } + ]; + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', () => { + 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 non-banner media responses', () => { + let response = { + 'tags': [{ + 'uuid': '84ab500420319d', + 'ads': [{ + 'ad_type': 'video', + 'cpm': 0.500000, + 'notify_url': 'imptracker.com', + 'rtb': { + 'video': { + 'content': '' + } + } + }] + }] + }; + let bidderRequest; + + 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 native responses', () => { + 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', + 'ctatext': 'Do it', + 'sponsored': 'AppNexus', + 'icon': { + 'width': 0, + 'height': 0, + 'url': 'http://cdn.adnxs.com/icon.png' + }, + 'main_img': { + 'width': 2352, + 'height': 1516, + 'url': 'http://cdn.adnxs.com/img.png' + }, + 'link': { + 'url': 'https://www.appnexus.com', + 'fallback_url': '', + 'click_trackers': ['http://nym1-ib.adnxs.com/click'] + }, + 'impression_trackers': ['http://example.com'], + }; + let bidderRequest; + + 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('http://cdn.adnxs.com/img.png'); + }); + + it('supports configuring outstream renderers', () => { + const outstreamResponse = deepClone(response); + outstreamResponse.tags[0].ads[0].rtb.video = {}; + outstreamResponse.tags[0].ads[0].renderer_url = 'renderer.js'; + + const bidderRequest = { + bids: [{ + renderer: { + options: { + adText: 'configured' + } + } + }] + }; + + const result = spec.interpretResponse({ body: outstreamResponse }, {bidderRequest}); + expect(result[0].renderer.config).to.deep.equal( + bidderRequest.bids[0].renderer.options + ); + }); + }); +}); From a95a8c6ec1c74fe3b4c4891c997efd6ddd9807b9 Mon Sep 17 00:00:00 2001 From: gammassp <35954362+gammassp@users.noreply.github.com> Date: Tue, 12 Jun 2018 06:51:50 +0700 Subject: [PATCH 0464/1594] Support send multi request (#2684) * support multi request --- modules/gammaBidAdapter.js | 19 ++-- test/spec/modules/gammaBidAdapter_spec.js | 106 ++++++++++------------ 2 files changed, 55 insertions(+), 70 deletions(-) diff --git a/modules/gammaBidAdapter.js b/modules/gammaBidAdapter.js index ce5c4ef2544..add3aad520b 100644 --- a/modules/gammaBidAdapter.js +++ b/modules/gammaBidAdapter.js @@ -1,6 +1,5 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; -import find from 'core-js/library/fn/array/find'; const ENDPOINT = 'hb.gammaplatform.com'; const BIDDER_CODE = 'gamma'; @@ -27,11 +26,15 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function(bidRequests) { - const gaxObjParams = find(bidRequests, hasParamInfo); - return { - method: 'GET', - url: '//' + ENDPOINT + '/adx/request?wid=' + gaxObjParams.params.siteId + '&zid=' + gaxObjParams.params.zoneId + '&hb=pbjs&bidid=' + gaxObjParams.bidId + '&urf=' + encodeURIComponent(utils.getTopWindowUrl()) - }; + const serverRequests = []; + for (var i = 0, len = bidRequests.length; i < len; i++) { + const gaxObjParams = bidRequests[i]; + serverRequests.push({ + method: 'GET', + url: '//' + ENDPOINT + '/adx/request?wid=' + gaxObjParams.params.siteId + '&zid=' + gaxObjParams.params.zoneId + '&hb=pbjs&bidid=' + gaxObjParams.bidId + '&urf=' + encodeURIComponent(utils.getTopWindowUrl()) + }); + } + return serverRequests; }, /** @@ -94,8 +97,4 @@ function newBid(serverBid) { return bid; } -function hasParamInfo(bid) { - return !!bid.params; -} - registerBidder(spec); diff --git a/test/spec/modules/gammaBidAdapter_spec.js b/test/spec/modules/gammaBidAdapter_spec.js index 1f3f225336e..5ff959cfb21 100644 --- a/test/spec/modules/gammaBidAdapter_spec.js +++ b/test/spec/modules/gammaBidAdapter_spec.js @@ -6,22 +6,23 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('gammaBidAdapter', function() { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { - let bid = { - 'bidder': 'gamma', - 'params': { - siteId: '1465446377', - zoneId: '1515999290' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250] - ], - 'bidId': '23beaa6af6cdde', - 'bidderRequestId': '19c0c1efdf37e7', - 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', - }; + let bid = { + 'bidder': 'gamma', + 'params': { + siteId: '1465446377', + zoneId: '1515999290' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }; + let bidArray = [bid]; + describe('isBidRequestValid', () => { it('should return true when required params found', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); @@ -40,56 +41,41 @@ describe('gammaBidAdapter', function() { }); describe('buildRequests', () => { - let bidRequests = [ - { - 'bidder': 'gamma', - 'params': { - siteId: '1465446377', - zoneId: '1515999290' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250] - ], - 'bidId': '23beaa6af6cdde', - 'bidderRequestId': '19c0c1efdf37e7', - 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1' - } - ]; - - const request = spec.buildRequests(bidRequests); - - it('sends bid request to our endpoint via GET', () => { - expect(request.method).to.equal('GET'); - }); - - it('bidRequest url', () => { - expect(request.url).to.match(new RegExp(`hb.gammaplatform.com`)); + it('should attempt to send bid requests to the endpoint via GET', () => { + const requests = spec.buildRequests(bidArray); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + expect(requestItem.url).to.match(new RegExp(`hb.gammaplatform.com`)); + }); }); }); describe('interpretResponse', () => { - let serverResponse = { - body: { - 'id': '23beaa6af6cdde', - 'bid': '5611802021800040585', - 'type': 'banner', - 'cur': 'USD', - 'seatbid': [{ - 'seat': '5611802021800040585', - 'bid': [{ - 'id': '1515999070', - 'impid': '1', - 'price': 0.45, - 'adm': '', - 'adid': '1515999070', - 'dealid': 'gax-paj2qarjf2g', - 'h': 250, - 'w': 300 + let serverResponse; + + beforeEach(() => { + serverResponse = { + body: { + 'id': '23beaa6af6cdde', + 'bid': '5611802021800040585', + 'type': 'banner', + 'cur': 'USD', + 'seatbid': [{ + 'seat': '5611802021800040585', + 'bid': [{ + 'id': '1515999070', + 'impid': '1', + 'price': 0.45, + 'adm': '', + 'adid': '1515999070', + 'dealid': 'gax-paj2qarjf2g', + 'h': 250, + 'w': 300 + }] }] - }] - } - }; + } + }; + }) it('should get the correct bid response', () => { let expectedResponse = [{ From 0bad4071290ee125b9dfc3d1c4be5662e3c5f2dd Mon Sep 17 00:00:00 2001 From: nwlosinski Date: Tue, 12 Jun 2018 01:59:37 +0200 Subject: [PATCH 0465/1594] Just Premium: add format parameter (issue #2691) (#2693) * add format parameter to bid response --- modules/justpremiumBidAdapter.js | 3 ++- test/spec/modules/justpremiumBidAdapter_spec.js | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 6e044c42640..db15598a0e6 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -72,7 +72,8 @@ export const spec = { cpm: bid.price, netRevenue: true, currency: bid.currency || 'USD', - ttl: bid.ttl || spec.time + ttl: bid.ttl || spec.time, + format: bid.format } bidResponses.push(bidResponse) } diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index 769810a3f3f..17961f04c7b 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -83,7 +83,8 @@ describe('justpremium adapter', () => { cpm: 0.52, netRevenue: true, currency: 'USD', - ttl: 60000 + ttl: 60000, + format: 'lb' } ] @@ -99,6 +100,7 @@ describe('justpremium adapter', () => { expect(result[0].ttl).to.equal(60000) expect(result[0].creativeId).to.equal(3213123) expect(result[0].netRevenue).to.equal(true) + expect(result[0].format).to.equal('lb') }) it('Verify wrong server response', () => { From be614dbf44137252a69d5a18343ba87d7428d295 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 12 Jun 2018 11:55:18 -0600 Subject: [PATCH 0466/1594] add some fixes to rubicon inventory and visitor data for arrays in SRA (#2718) --- modules/rubiconBidAdapter.js | 4 ++-- test/spec/modules/rubiconBidAdapter_spec.js | 25 +++++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index f517f864061..5f4250352a5 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -359,14 +359,14 @@ export const spec = { // visitor properties if (params.visitor !== null && typeof params.visitor === 'object') { Object.keys(params.visitor).forEach((key) => { - data[`tg_v.${key}`] = params.visitor[key]; + data[`tg_v.${key}`] = params.visitor[key].toString(); }); } // inventory properties if (params.inventory !== null && typeof params.inventory === 'object') { Object.keys(params.inventory).forEach((key) => { - data[`tg_i.${key}`] = params.inventory[key]; + data[`tg_i.${key}`] = params.inventory[key].toString(); }); } diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index d254423bb0b..721758b6a00 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -275,11 +275,12 @@ describe('the rubicon adapter', () => { keywords: ['a', 'b', 'c'], inventory: { rating: '5-star', - prodtype: 'tech' + prodtype: ['tech', 'mobile'] }, visitor: { ucat: 'new', - lastsearch: 'iphone' + lastsearch: 'iphone', + likes: ['sports', 'video games'] }, position: 'atf', referrer: 'localhost', @@ -375,8 +376,9 @@ describe('the rubicon adapter', () => { 'kw': 'a,b,c', 'tg_v.ucat': 'new', 'tg_v.lastsearch': 'iphone', + 'tg_v.likes': 'sports,video games', 'tg_i.rating': '5-star', - 'tg_i.prodtype': 'tech', + 'tg_i.prodtype': 'tech,mobile', 'tg_fl.eid': 'div-1', 'rf': 'localhost' }; @@ -396,7 +398,7 @@ describe('the rubicon adapter', () => { 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_i.rating', 'tg_i.prodtype', 'tk_flint', 'x_source.tid', 'p_screen_res', 'rp_floor', 'rp_secure', 'tk_user_key', 'tg_fl.eid', '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', 'p_screen_res', 'rp_floor', 'rp_secure', 'tk_user_key', 'tg_fl.eid', 'slots', 'rand']; request.data.split('&').forEach((item, i) => { expect(item.split('=')[0]).to.equal(referenceOrdering[i]); @@ -421,8 +423,9 @@ describe('the rubicon adapter', () => { 'kw': 'a,b,c', 'tg_v.ucat': 'new', 'tg_v.lastsearch': 'iphone', + 'tg_v.likes': 'sports,video games', 'tg_i.rating': '5-star', - 'tg_i.prodtype': 'tech', + 'tg_i.prodtype': 'tech,mobile', 'rf': 'localhost', 'p_geo.latitude': undefined, 'p_geo.longitude': undefined @@ -823,8 +826,9 @@ describe('the rubicon adapter', () => { 'kw': 'a,b,c', 'tg_v.ucat': 'new', 'tg_v.lastsearch': 'iphone', + 'tg_v.likes': 'sports,video games', 'tg_i.rating': '5-star', - 'tg_i.prodtype': 'tech', + 'tg_i.prodtype': 'tech,mobile', 'tg_fl.eid': 'div-1', 'rf': 'localhost' }; @@ -1057,7 +1061,7 @@ describe('the rubicon adapter', () => { expect(slot).to.have.property('inventory').that.is.an('object'); expect(slot.inventory).to.have.property('rating').that.equals('5-star'); - expect(slot.inventory).to.have.property('prodtype').that.equals('tech'); + expect(slot.inventory).to.have.property('prodtype').that.deep.equals(['tech', 'mobile']); expect(slot).to.have.property('keywords') .that.is.an('array') @@ -1067,6 +1071,7 @@ describe('the rubicon adapter', () => { expect(slot).to.have.property('visitor').that.is.an('object'); expect(slot.visitor).to.have.property('ucat').that.equals('new'); expect(slot.visitor).to.have.property('lastsearch').that.equals('iphone'); + expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); }); it('should make a well-formed video request', () => { @@ -1120,7 +1125,7 @@ describe('the rubicon adapter', () => { expect(slot).to.have.property('inventory').that.is.an('object'); expect(slot.inventory).to.have.property('rating').that.equals('5-star'); - expect(slot.inventory).to.have.property('prodtype').that.equals('tech'); + expect(slot.inventory).to.have.property('prodtype').that.deep.equals(['tech', 'mobile']); expect(slot).to.have.property('keywords') .that.is.an('array') @@ -1130,6 +1135,7 @@ describe('the rubicon adapter', () => { expect(slot).to.have.property('visitor').that.is.an('object'); expect(slot.visitor).to.have.property('ucat').that.equals('new'); expect(slot.visitor).to.have.property('lastsearch').that.equals('iphone'); + expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); }); it('should send request with proper ad position', () => { @@ -1347,8 +1353,9 @@ describe('the rubicon adapter', () => { 'kw': 'a,b,c', 'tg_v.ucat': 'new', 'tg_v.lastsearch': 'iphone', + 'tg_v.likes': 'sports,video games', 'tg_i.rating': '5-star', - 'tg_i.prodtype': 'tech', + 'tg_i.prodtype': 'tech,mobile', 'tg_fl.eid': 'div-1', 'rf': 'localhost' }; From d1e2ffa72f8c5d955bedbfb6b3ccf91d6a1afeea Mon Sep 17 00:00:00 2001 From: yehonatanshac Date: Mon, 18 Jun 2018 15:28:35 +0300 Subject: [PATCH 0467/1594] in-app support in kumma adapter (#2631) --- modules/kummaBidAdapter.js | 247 ++++++++++++++++++--- modules/kummaBidAdapter.md | 94 ++++++-- test/spec/modules/kummaBidAdapter_spec.js | 251 ++++++++++++++++++++-- 3 files changed, 529 insertions(+), 63 deletions(-) diff --git a/modules/kummaBidAdapter.js b/modules/kummaBidAdapter.js index 40b96a9ea39..1d2df149fe9 100644 --- a/modules/kummaBidAdapter.js +++ b/modules/kummaBidAdapter.js @@ -1,13 +1,27 @@ - -import {logError, getTopWindowLocation, getTopWindowReferrer, parseSizesInput} from 'src/utils'; +import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import includes from 'core-js/library/fn/array/includes'; + +const NATIVE_DEFAULTS = { + TITLE_LEN: 100, + DESCR_LEN: 200, + SPONSORED_BY_LEN: 50, + IMG_MIN: 150, + ICON_MIN: 50, +}; +const DEFAULT_MIMES = ['video/mp4', 'video/webm', 'application/x-shockwave-flash', 'application/javascript']; +const VIDEO_TARGETING = ['mimes', 'skippable', 'playback_method', 'protocols', 'api']; +const DEFAULT_PROTOCOLS = [2, 3, 5, 6]; +const DEFAULT_APIS = [1, 2]; export const spec = { code: 'kumma', + supportedMediaTypes: [BANNER, NATIVE, VIDEO], isBidRequestValid: bid => ( - !!(bid && bid.params && bid.params.pubId && bid.params.siteId) + !!(bid && bid.params && bid.params.pubId && bid.params.placementId) ), buildRequests: bidRequests => { const request = { @@ -15,7 +29,8 @@ export const spec = { at: 2, imp: bidRequests.map(slot => impression(slot)), site: site(bidRequests), - device: device(), + app: app(bidRequests), + device: device(bidRequests), }; return { method: 'POST', @@ -27,15 +42,11 @@ export const spec = { bidResponseAvailable(request, response.body) ), }; + function bidResponseAvailable(bidRequest, bidResponse) { const idToImpMap = {}; const idToBidMap = {}; - let ortbRequest = null; - try { - ortbRequest = JSON.parse(bidRequest.data); - } catch (ex) { - logError('kumma.parse', 'ERROR', ex); - } + const ortbRequest = parse(bidRequest.data); ortbRequest.imp.forEach(imp => { idToImpMap[imp.id] = imp; }); @@ -49,19 +60,39 @@ function bidResponseAvailable(bidRequest, bidResponse) { if (idToBidMap[id]) { const bid = {}; bid.requestId = id; - bid.creativeId = idToBidMap[id].adid; + bid.adId = id; + bid.creativeId = id; bid.cpm = idToBidMap[id].price; bid.currency = bidResponse.cur; bid.ttl = 360; bid.netRevenue = true; - bid.ad = idToBidMap[id].adm; - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); - bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); - bid.width = idToImpMap[id].banner.w; - bid.height = idToImpMap[id].banner.h; + if (idToImpMap[id]['native']) { + bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); + let nurl = idToBidMap[id].nurl; + nurl = nurl.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); + nurl = nurl.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); + bid['native']['impressionTrackers'] = [nurl]; + bid.mediaType = 'native'; + } else if (idToImpMap[id]['video']) { + bid.vastUrl = idToBidMap[id].adm; + bid.vastUrl = bid.vastUrl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + bid.crid = idToBidMap[id].crid; + bid.width = idToImpMap[id].video.w; + bid.height = idToImpMap[id].video.h; + bid.mediaType = 'video'; + } else if (idToImpMap[id]['banner']) { + bid.ad = idToBidMap[id].adm; + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur); + bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid); + bid.width = idToImpMap[id].banner.w; + bid.height = idToImpMap[id].banner.h; + bid.mediaType = 'banner'; + } bids.push(bid); } }); @@ -70,20 +101,110 @@ function bidResponseAvailable(bidRequest, bidResponse) { function impression(slot) { return { id: slot.bidId, - banner: banner(slot), + secure: window.location.protocol === 'https:' ? 1 : 0, + 'banner': banner(slot), + 'native': nativeImpression(slot), + 'video': videoImpression(slot), bidfloor: slot.params.bidFloor || '0.000001', tagid: slot.params.placementId.toString(), }; } -function banner(slot) { - const size = parseSizesInput(slot.sizes)[0].split('x'); - const width = parseInt(size[0]); - const height = parseInt(size[1]); + +function getSizes(slot) { + const size = utils.parseSizesInput(slot.sizes)[0].split('x'); return { - w: width, - h: height, + width: parseInt(size[0]), + height: parseInt(size[1]), }; } + +function banner(slot) { + if (slot.mediaType === 'banner' || utils.deepAccess(slot, 'mediaTypes.banner')) { + const sizes = getSizes(slot); + return { + w: sizes.width, + h: sizes.height, + }; + } + return null; +} + +function videoImpression(slot) { + if (slot.mediaType === 'video' || utils.deepAccess(slot, 'mediaTypes.video')) { + const sizes = getSizes(slot); + const video = { + w: sizes.width, + h: sizes.height, + mimes: DEFAULT_MIMES, + protocols: DEFAULT_PROTOCOLS, + api: DEFAULT_APIS, + }; + if (slot.params.video) { + Object.keys(slot.params.video).filter(param => includes(VIDEO_TARGETING, param)).forEach(param => video[param] = slot.params.video[param]); + } + return video; + } + return null; +} + +function nativeImpression(slot) { + if (slot.mediaType === 'native' || utils.deepAccess(slot, 'mediaTypes.native')) { + const assets = []; + addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); + addAsset(assets, dataAsset(2, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); + addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); + addAsset(assets, imageAsset(4, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); + addAsset(assets, imageAsset(5, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); + return { + request: JSON.stringify({ assets }), + ver: '1.1', + }; + } + return null; +} + +function addAsset(assets, asset) { + if (asset) { + assets.push(asset); + } +} + +function titleAsset(id, params, defaultLen) { + if (params) { + return { + id, + required: params.required ? 1 : 0, + title: { + len: params.len || defaultLen, + }, + }; + } + return null; +} + +function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { + return params ? { + id, + required: params.required ? 1 : 0, + img: { + type, + wmin: params.wmin || defaultMinWidth, + hmin: params.hmin || defaultMinHeight, + } + } : null; +} + +function dataAsset(id, params, type, defaultLen) { + return params ? { + id, + required: params.required ? 1 : 0, + data: { + type, + len: params.len || defaultLen, + } + } : null; +} + function site(bidderRequest) { const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0'; @@ -92,22 +213,88 @@ function site(bidderRequest) { return { publisher: { id: pubId.toString(), - domain: getTopWindowLocation().hostname, + domain: utils.getTopWindowLocation().hostname, }, id: siteId.toString(), - ref: getTopWindowReferrer(), - page: getTopWindowLocation().href, + ref: utils.getTopWindowReferrer(), + page: utils.getTopWindowLocation().href, } } return null; } -function device() { + +function app(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0'; + const appParams = bidderRequest[0].params.app; + if (appParams) { + return { + publisher: { + id: pubId.toString(), + }, + id: appParams.id, + name: appParams.name, + bundle: appParams.bundle, + storeurl: appParams.storeUrl, + domain: appParams.domain, + } + } + return null; +} + +function device(bidderRequest) { + const lat = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.latitude : ''; + const lon = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.longitude : ''; + const ifa = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.ifa : ''; return { + dnt: utils.getDNT() ? 1 : 0, ua: navigator.userAgent, language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), w: (window.screen.width || window.innerWidth), h: (window.screen.height || window.innerHeigh), + geo: { + lat: lat, + lon: lon, + }, + ifa: ifa, }; } +function parse(rawResponse) { + try { + if (rawResponse) { + return JSON.parse(rawResponse); + } + } catch (ex) { + logError('kumma.parse', 'ERROR', ex); + } + return null; +} + +function nativeResponse(imp, bid) { + if (imp['native']) { + const nativeAd = parse(bid.adm); + const keys = {}; + keys.image = {}; + keys.icon = {}; + if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { + nativeAd['native'].assets.forEach(asset => { + keys.title = asset.title ? asset.title.text : keys.title; + keys.body = asset.data && asset.id === 2 ? asset.data.value : keys.body; + keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy; + keys.icon.url = asset.img && asset.id === 4 ? asset.img.url : keys.icon.url; + keys.icon.width = asset.img && asset.id === 4 ? asset.img.w : keys.icon.width; + keys.icon.height = asset.img && asset.id === 4 ? asset.img.h : keys.icon.height; + keys.image.url = asset.img && asset.id === 5 ? asset.img.url : keys.image.url; + keys.image.width = asset.img && asset.id === 5 ? asset.img.w : keys.image.width; + keys.image.height = asset.img && asset.id === 5 ? asset.img.h : keys.image.height; + }); + if (nativeAd['native'].link) { + keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); + } + return keys; + } + } + return null; +} + registerBidder(spec); diff --git a/modules/kummaBidAdapter.md b/modules/kummaBidAdapter.md index b533c349bee..639e0c97d08 100644 --- a/modules/kummaBidAdapter.md +++ b/modules/kummaBidAdapter.md @@ -1,27 +1,87 @@ # Overview -**Module Name**: Kumma Bidder Adapter -**Module Type**: Bidder Adapter -**Maintainer**: yehonatan@kumma.com +**Module Name**: Kumma Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: yehonatan@kumma.com # Description -Connects to Kumma demand source to fetch bids. +Connects to Kumma demand source to fetch bids. +Banner, Native, Video formats are supported. Please use ```kumma``` as the bidder code. # Test Parameters ``` - var adUnits = [{ - code: 'banner-ad-div', - sizes: [[300, 250]], - bids: [{ - bidder: 'kumma', - params: { - pubId: '55879', // required - siteId: '26047', // required - placementId: '123', // optional - bidFloor: '0.001' // optional - } - }] - }]; + var adUnits = [{ + code: 'dfp-native-div', + mediaType: 'native', + mediaTypes: { + native: { + title: { + required: true, + len: 75 + }, + image: { + required: true + }, + body: { + len: 200 + }, + icon: { + required: false + } + } + }, + bids: [{ + bidder: 'kumma', + params: { + pubId: '29521', + siteId: '26047', + placementId: '123', + bidFloor: '0.001', // optional + ifa: 'XXX-XXX', // optional + latitude: '40.712775', // optional + longitude: '-74.005973', // optional + } + }] + }, + { + code: 'dfp-banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250] + ], + } + }, + bids: [{ + bidder: 'kumma', + params: { + pubId: '29521', + siteId: '26049', + placementId: '123', + } + }] + }, + { + code: 'dfp-video-div', + sizes: [640, 480], + mediaTypes: { + video: { + context: "instream" + } + }, + bids: [{ + bidder: 'kumma', + params: { + pubId: '29521', + siteId: '26049', + placementId: '123', + video: { + skipppable: true, + } + } + }] + } + ]; ``` diff --git a/test/spec/modules/kummaBidAdapter_spec.js b/test/spec/modules/kummaBidAdapter_spec.js index d90063820b7..36c77a736d4 100644 --- a/test/spec/modules/kummaBidAdapter_spec.js +++ b/test/spec/modules/kummaBidAdapter_spec.js @@ -1,28 +1,82 @@ import {expect} from 'chai'; import {spec} from 'modules/kummaBidAdapter'; -import {getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; +import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; describe('Kumma Adapter Tests', () => { const slotConfigs = [{ placementCode: '/DfpAccount1/slot1', sizes: [[300, 250]], bidId: 'bid12345', + mediaType: 'banner', params: { - pubId: '55879', + pubId: '29521', siteId: '26047', placementId: '123', - bidFloor: '0.001' + bidFloor: '0.001', + ifa: 'IFA', + latitude: '40.712775', + longitude: '-74.005973' } }, { placementCode: '/DfpAccount2/slot2', - sizes: [[250, 250]], + sizes: [[728, 90]], bidId: 'bid23456', + mediaType: 'banner', params: { - pubId: '55879', + pubId: '29521', siteId: '26047', - placementId: '456' + placementId: '1234', + bidFloor: '0.000001', } }]; + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + mediaType: 'native', + nativeParams: { + title: { required: true, len: 200 }, + body: {}, + image: { wmin: 100 }, + sponsoredBy: { }, + icon: { } + }, + params: { + pubId: '29521', + placementId: '123', + siteId: '26047' + } + }]; + const videoSlotConfig = [{ + placementCode: '/DfpAccount1/slot4', + sizes: [[640, 480]], + bidId: 'bid12345678', + mediaType: 'video', + video: { + skippable: true + }, + params: { + pubId: '29521', + placementId: '1234567', + siteId: '26047', + } + }]; + const appSlotConfig = [{ + placementCode: '/DfpAccount1/slot5', + bidId: 'bid12345', + params: { + pubId: '29521', + placementId: '1234', + app: { + id: '1111', + name: 'app name', + bundle: 'com.kumma.apps', + storeUrl: 'http://kumma.com/apps', + domain: 'kumma.com' + } + } + }]; + it('Verify build request', () => { const request = spec.buildRequests(slotConfigs); expect(request.url).to.equal('//hb.kumma.com/'); @@ -31,13 +85,16 @@ describe('Kumma Adapter Tests', () => { // site object expect(ortbRequest.site).to.not.equal(null); expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('55879'); - expect(ortbRequest.site.ref).to.equal(getTopWindowReferrer()); + expect(ortbRequest.site.publisher.id).to.equal('29521'); + expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); expect(ortbRequest.imp).to.have.lengthOf(2); // device object expect(ortbRequest.device).to.not.equal(null); expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + expect(ortbRequest.device.ifa).to.equal('IFA'); + expect(ortbRequest.device.geo.lat).to.equal('40.712775'); + expect(ortbRequest.device.geo.lon).to.equal('-74.005973'); // slot 1 expect(ortbRequest.imp[0].tagid).to.equal('123'); expect(ortbRequest.imp[0].banner).to.not.equal(null); @@ -45,10 +102,10 @@ describe('Kumma Adapter Tests', () => { expect(ortbRequest.imp[0].banner.h).to.equal(250); expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('456'); + expect(ortbRequest.imp[1].tagid).to.equal('1234'); expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(250); - expect(ortbRequest.imp[1].banner.h).to.equal(250); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); }); @@ -60,8 +117,7 @@ describe('Kumma Adapter Tests', () => { bid: [{ impid: ortbRequest.imp[0].id, price: 1.25, - adm: 'This is an Ad', - adid: '471810', + adm: 'This is an Ad' }] }], cur: 'USD' @@ -74,7 +130,9 @@ describe('Kumma Adapter Tests', () => { expect(bid.ad).to.equal('This is an Ad'); expect(bid.width).to.equal(300); expect(bid.height).to.equal(250); - expect(bid.creativeId).to.equal('471810'); + expect(bid.adId).to.equal('bid12345'); + expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); expect(bid.currency).to.equal('USD'); expect(bid.ttl).to.equal(360); }); @@ -85,13 +143,174 @@ describe('Kumma Adapter Tests', () => { expect(bids).to.have.lengthOf(0); }); + it('Verify Native request', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//hb.kumma.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // native impression + expect(ortbRequest.imp[0].tagid).to.equal('123'); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(5); + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[3].id).to.equal(4); + expect(nativeRequest.assets[4].id).to.equal(5); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(2); + expect(nativeRequest.assets[1].data.len).to.equal(200); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[3].img).to.not.equal(null); + expect(nativeRequest.assets[3].img.wmin).to.equal(50); + expect(nativeRequest.assets[3].img.hmin).to.equal(50); + expect(nativeRequest.assets[3].img.type).to.equal(1); + expect(nativeRequest.assets[4].img).to.not.equal(null); + expect(nativeRequest.assets[4].img.wmin).to.equal(100); + expect(nativeRequest.assets[4].img.hmin).to.equal(150); + expect(nativeRequest.assets[4].img.type).to.equal(3); + }); + + it('Verify Native response', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//hb.kumma.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { id: 1, title: { text: 'Ad Title' } }, + { id: 2, data: { value: 'Test description' } }, + { id: 3, data: { value: 'Brand' } }, + { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + ], + link: { url: 'http://brand.com/' } + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + nurl: 'http://rtb.adx1.com/log', + adm: JSON.stringify(nativeResponse) + }] + }], + cur: 'USD', + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Brand'); + expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.image.width).to.equal(300); + expect(nativeBid.image.height).to.equal(300); + expect(nativeBid.icon.width).to.equal(100); + expect(nativeBid.icon.height).to.equal(100); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(1); + expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); + }); + + it('Verify Video request', () => { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('//hb.kumma.com/'); + expect(request.method).to.equal('POST'); + const videoRequest = JSON.parse(request.data); + // site object + expect(videoRequest.site).to.not.equal(null); + expect(videoRequest.site.publisher.id).to.equal('29521'); + expect(videoRequest.site.ref).to.equal(window.top.document.referrer); + expect(videoRequest.site.page).to.equal(getTopWindowLocation().href); + // device object + expect(videoRequest.device).to.not.equal(null); + expect(videoRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(videoRequest.imp[0].tagid).to.equal('1234567'); + expect(videoRequest.imp[0].video).to.not.equal(null); + expect(videoRequest.imp[0].video.w).to.equal(640); + expect(videoRequest.imp[0].video.h).to.equal(480); + expect(videoRequest.imp[0].banner).to.equal(null); + expect(videoRequest.imp[0].native).to.equal(null); + }); + + it('Verify parse video response', () => { + const request = spec.buildRequests(videoSlotConfig); + const videoRequest = JSON.parse(request.data); + const videoResponse = { + seatbid: [{ + bid: [{ + impid: videoRequest.imp[0].id, + price: 1.90, + adm: 'http://vid.example.com/9876', + crid: '510511_754567308' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: videoResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.90); + expect(bid.vastUrl).to.equal('http://vid.example.com/9876'); + expect(bid.crid).to.equal('510511_754567308'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.adId).to.equal('bid12345678'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + it('Verifies bidder code', () => { expect(spec.code).to.equal('kumma'); }); + it('Verifies supported media types', () => { + expect(spec.supportedMediaTypes).to.have.lengthOf(3); + expect(spec.supportedMediaTypes[0]).to.equal('banner'); + expect(spec.supportedMediaTypes[1]).to.equal('native'); + expect(spec.supportedMediaTypes[2]).to.equal('video'); + }); + it('Verifies if bid request valid', () => { expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid({})).to.equal(false); - expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); + expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); + }); + + it('Verify app requests', () => { + const request = spec.buildRequests(appSlotConfig); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.publisher).to.not.equal(null); + expect(ortbRequest.app.publisher.id).to.equal('29521'); + expect(ortbRequest.app.id).to.equal('1111'); + expect(ortbRequest.app.name).to.equal('app name'); + expect(ortbRequest.app.bundle).to.equal('com.kumma.apps'); + expect(ortbRequest.app.storeurl).to.equal('http://kumma.com/apps'); + expect(ortbRequest.app.domain).to.equal('kumma.com'); }); }); From 51228f2a5d4129b3fcef851fe2e5ef1660f7b997 Mon Sep 17 00:00:00 2001 From: adxcgcom <31470944+adxcgcom@users.noreply.github.com> Date: Mon, 18 Jun 2018 14:35:04 +0200 Subject: [PATCH 0468/1594] updated adxcg bidAdapter for gdpr (#2713) --- modules/adxcgBidAdapter.js | 31 +++++++++++++-------- test/spec/modules/adxcgBidAdapter_spec.js | 34 ++++++++++++++++++++++- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/modules/adxcgBidAdapter.js b/modules/adxcgBidAdapter.js index 91bf0746afc..c6f35445a46 100644 --- a/modules/adxcgBidAdapter.js +++ b/modules/adxcgBidAdapter.js @@ -6,6 +6,7 @@ import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes'; /** * 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 */ const BIDDER_CODE = 'adxcg'; @@ -51,21 +52,28 @@ export const spec = { requestUrl.search = null; requestUrl.hash = null; + let beaconParams = { + renderformat: 'javascript', + ver: 'r20180522PB10', + adzoneid: adZoneIds.join(','), + format: sizes.join(','), + prebidBidIds: prebidBidIds.join(','), + url: encodeURIComponent(url.format(requestUrl)), + secure: secure ? '1' : '0', + source: SOURCE, + pbjs: '$prebid.version$' + }; + + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { + beaconParams.gdpr = bidderRequest.gdprConsent.gdprApplies ? '1' : '0'; + beaconParams.gdpr_consent = bidderRequest.gdprConsent.consentString; + } + let adxcgRequestUrl = url.format({ protocol: secure ? 'https' : 'http', hostname: secure ? 'hbps.adxcg.net' : 'hbp.adxcg.net', pathname: '/get/adi', - search: { - renderformat: 'javascript', - ver: 'r20171102PB10', - adzoneid: adZoneIds.join(','), - format: sizes.join(','), - prebidBidIds: prebidBidIds.join(','), - url: encodeURIComponent(url.format(requestUrl)), - secure: secure ? '1' : '0', - source: SOURCE, - pbjs: '$prebid.version$' - } + search: beaconParams }); return { @@ -151,4 +159,5 @@ export const spec = { } } }; + registerBidder(spec); diff --git a/test/spec/modules/adxcgBidAdapter_spec.js b/test/spec/modules/adxcgBidAdapter_spec.js index 99f07aa4d53..64b4805ca9f 100644 --- a/test/spec/modules/adxcgBidAdapter_spec.js +++ b/test/spec/modules/adxcgBidAdapter_spec.js @@ -54,7 +54,7 @@ describe('AdxcgAdapter', () => { let query = parsedRequestUrl.search; expect(query.renderformat).to.equal('javascript'); - expect(query.ver).to.equal('r20171102PB10'); + expect(query.ver).to.equal('r20180522PB10'); expect(query.source).to.equal('pbjs10'); expect(query.pbjs).to.equal('$prebid.version$'); expect(query.adzoneid).to.equal('1'); @@ -64,6 +64,38 @@ describe('AdxcgAdapter', () => { }); }); + describe('gdpr compliance', () => { + let bid = { + 'bidder': 'adxcg', + 'params': { + 'adzoneid': '1' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [640, 360], [1, 1]], + 'bidId': '84ab500420319d', + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '1d1a030790a475', + }; + + it('should send GDPR Consent data if gdprApplies', () => { + let request = spec.buildRequests([bid], {gdprConsent: {gdprApplies: true, consentString: 'consentDataString'}}); + let parsedRequestUrl = url.parse(request.url); + let query = parsedRequestUrl.search; + + expect(query.gdpr).to.equal('1'); + expect(query.gdpr_consent).to.equal('consentDataString'); + }); + + it('should not send GDPR Consent data if gdprApplies is false or undefined', () => { + let request = spec.buildRequests([bid], {gdprConsent: {gdprApplies: false, consentString: 'consentDataString'}}); + let parsedRequestUrl = url.parse(request.url); + let query = parsedRequestUrl.search; + + expect(query.gdpr).to.be.empty; + expect(query.gdpr_consent).to.be.empty; + }); + }); + describe('response handler', () => { let BIDDER_REQUEST = { 'bidder': 'adxcg', From f18afb1e25a70ef7f9d3dd8474d8af6b397677c9 Mon Sep 17 00:00:00 2001 From: John Salis Date: Mon, 18 Jun 2018 09:03:59 -0400 Subject: [PATCH 0469/1594] fix gdpr consent required (#2734) --- modules/beachfrontBidAdapter.js | 8 ++++---- test/spec/modules/beachfrontBidAdapter_spec.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 8f8288011e6..4f214c1b3e5 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -248,8 +248,8 @@ function createVideoRequestData(bid, bidderRequest) { }; if (bidderRequest && bidderRequest.gdprConsent) { - let { consentRequired, consentString } = bidderRequest.gdprConsent; - payload.regs.ext = { gdpr: consentRequired ? 1 : 0 }; + let { gdprApplies, consentString } = bidderRequest.gdprConsent; + payload.regs.ext = { gdpr: gdprApplies ? 1 : 0 }; payload.user.ext = { consent: consentString }; } @@ -283,8 +283,8 @@ function createBannerRequestData(bids, bidderRequest) { }; if (bidderRequest && bidderRequest.gdprConsent) { - let { consentRequired, consentString } = bidderRequest.gdprConsent; - payload.gdpr = consentRequired ? 1 : 0; + let { gdprApplies, consentString } = bidderRequest.gdprConsent; + payload.gdpr = gdprApplies ? 1 : 0; payload.gdprConsent = consentString; } diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index a3ecccba6cb..b0860547e3f 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -231,7 +231,7 @@ describe('BeachfrontAdapter', () => { const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; const bidderRequest = { gdprConsent: { - consentRequired: true, + gdprApplies: true, consentString } }; @@ -346,7 +346,7 @@ describe('BeachfrontAdapter', () => { const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; const bidderRequest = { gdprConsent: { - consentRequired: true, + gdprApplies: true, consentString } }; From c739338793392bc9441b3e720695925e385705dd Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 18 Jun 2018 23:12:41 +1000 Subject: [PATCH 0470/1594] Playground xyz - GDPR integration. (#2699) * add playground adapters * clean up * update with upstream master * add test file clean up adapter by removing native referecnes * test file * replace appnexus with playground reference in error logs * remove commented code * change key in response object from appnexus to playgroundxyz * change tests so we test for ordering by cpm as well * dont drop other bids, just set cpm to 0 and send it through * clean up * restore glulp file * fix documentation * remove cpm logic from adapter * change application type to application\json for playground adapter * update adaptor to use openRtb * add device and site to bid * add extra space on error msg * remove package-lock * update pg details * Update playgroundxyzBidAdapter.md * add GDPR remove video sample config form .md file --- modules/playgroundxyzBidAdapter.js | 12 +++-- modules/playgroundxyzBidAdapter.md | 42 ---------------- .../modules/playgroundxyzBidAdapter_spec.js | 49 +++++++++++++++++++ 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/modules/playgroundxyzBidAdapter.js b/modules/playgroundxyzBidAdapter.js index 75861bd63f1..0e0da35b66f 100644 --- a/modules/playgroundxyzBidAdapter.js +++ b/modules/playgroundxyzBidAdapter.js @@ -28,7 +28,7 @@ export const spec = { */ buildRequests: function (bidRequests, bidderRequest) { const topLocation = utils.getTopWindowLocation(); - const payload = JSON.stringify({ + const payload = { id: bidRequests[0].auctionId, site: { domain: window.location.protocol + '//' + topLocation.hostname, @@ -41,17 +41,23 @@ export const spec = { devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, }, imp: bidRequests.map(mapImpression) - }); + }; const options = { contentType: 'application/json', withCredentials: false }; + if (bidderRequest && bidderRequest.gdprConsent) { + payload.user = {ext: {consent: bidderRequest.gdprConsent.consentString}}; + const gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; + payload.regs = {ext: {gdpr: gdpr}}; + } + return { method: 'POST', url: URL, - data: payload, + data: JSON.stringify(payload), options, bidderRequest }; diff --git a/modules/playgroundxyzBidAdapter.md b/modules/playgroundxyzBidAdapter.md index 345bf7d0693..c72b9f34dd3 100644 --- a/modules/playgroundxyzBidAdapter.md +++ b/modules/playgroundxyzBidAdapter.md @@ -25,48 +25,6 @@ var adUnits = [ placementId: '10433394' } }] - }, - // Video instream adUnit - { - code: 'video-instream', - sizes: [640, 480], - mediaTypes: { - video: { - context: 'instream' - }, - }, - bids: [{ - bidder: 'playgroundxyz', - params: { - placementId: '9333431', - video: { - skippable: true, - playback_methods: ['auto_play_sound_off'] - } - } - }] - }, - // Video outstream adUnit - { - code: 'video-outstream', - sizes: [[640, 480]], - mediaTypes: { - video: { - context: 'outstream' - } - }, - bids: [ - { - bidder: 'playgroundxyz', - params: { - placementId: '5768085', - video: { - skippable: true, - playback_method: ['auto_play_sound_off'] - } - } - } - ] } ]; ``` diff --git a/test/spec/modules/playgroundxyzBidAdapter_spec.js b/test/spec/modules/playgroundxyzBidAdapter_spec.js index 72cd1205c45..becd8612a9c 100644 --- a/test/spec/modules/playgroundxyzBidAdapter_spec.js +++ b/test/spec/modules/playgroundxyzBidAdapter_spec.js @@ -4,6 +4,7 @@ import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; const URL = 'https://ads.playground.xyz/host-config/prebid'; +const GDPR_CONSENT = 'XYZ-CONSENT'; describe('playgroundxyzBidAdapter', () => { const adapter = newBidder(spec); @@ -133,4 +134,52 @@ describe('playgroundxyzBidAdapter', () => { expect(result.length).to.equal(0); }); }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'playgroundxyz', + 'params': { + 'publisherId': 'PUB_FAKE' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '321db112312as', + 'bidderRequestId': '23edabce2731sd6', + 'auctionId': '12as040790a475' + } + ]; + + it('should not populate GDPR', () => { + let bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest); + let data = JSON.parse(request.data); + expect(data).to.not.have.property('user'); + expect(data).to.not.have.property('regs'); + }); + + it('should populate GDPR and consent string when consetString is presented but not gdpApplies', () => { + let bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest, {gdprConsent: {consentString: GDPR_CONSENT}}); + let data = JSON.parse(request.data); + expect(data.regs.ext.gdpr).to.equal(0); + expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); + }); + + it('should populate GDPR and consent string when gdpr is set to true', () => { + let bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true, consentString: GDPR_CONSENT}}); + let data = JSON.parse(request.data); + expect(data.regs.ext.gdpr).to.equal(1); + expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); + }); + + it('should populate GDPR and consent string when gdpr is set to false', () => { + let bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: false, consentString: GDPR_CONSENT}}); + let data = JSON.parse(request.data); + expect(data.regs.ext.gdpr).to.equal(0); + expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); + }); + }); }); From 2c190324380a40b88b374bc07e8cc92c0660dcab Mon Sep 17 00:00:00 2001 From: guillaume-sticky Date: Mon, 18 Jun 2018 15:59:06 +0200 Subject: [PATCH 0471/1594] Add GDPR parameters in ad request (#2522) * add stickyadsTV bidder adapter * init unit test file * ad some unit tests * fix unit test on ad format with parameters * add some unit tests * add unit tests on getBid method * add some test cases in unit tests * minor fix on component id tag. * remove adapters-sticky.json test file * use top most accessible window instead of window.top * Pass in the bid request in the createBid call. * use top most accessible window instead of window.top * add unit tests * update unit tests * fix unit test. * fix CI build * add alias freewheel-ssp * update unit tests on bidderCode value * fix component id values and add unit tests * allws to use any outstream format. * fix ASLoader on futur outstream format versions * minor: fix code format. * update unit tests * minor fix code format * minor: add missing new line at eof * replace StickyAdsTVAdapter by freewheel ssp bd adapter (for prebid 1.0) * remove old stickyadstv unittest spec. * fix server response parsing if sent as object with 'body' field * use the vastXml field for video mediatype * add user sync pixel in freewheel ssp adapter * remove all console log calls (replaced using util helper) * remove useless bidderCode (automatically added by the bidderFactory) * Return the SYNC pixel to be added in the page by Prebid.js * remove instance level properties to enable concurrent bids with the same adapter instance. * fix the request apss through and corresponding unit tests * fix 'freeheelssp' typo * add vast parameters feature and GDPR params in VAST request * fix lint issues * add gdpr parameter support on freewheelSSPBidAdapter * use bidderrequest to read gdpr parameters and update unit tests * fix lint errors * fix lint errors * fix typo and bidderRequest reference. * fix bidderRequest reference. * add missing declaration for 'key' variable --- modules/freewheelSSPBidAdapter.js | 20 ++++++++++++++++++- .../modules/freewheelSSPBidAdapter_spec.js | 16 ++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/modules/freewheelSSPBidAdapter.js b/modules/freewheelSSPBidAdapter.js index 632df8fe93c..87c1979ac5d 100644 --- a/modules/freewheelSSPBidAdapter.js +++ b/modules/freewheelSSPBidAdapter.js @@ -208,7 +208,7 @@ export const spec = { * @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) { + buildRequests: function(bidRequests, bidderRequest) { // var currency = config.getConfig(currency); var currentBidRequest = bidRequests[0]; @@ -223,6 +223,24 @@ export const spec = { componentId: getComponentId(currentBidRequest.params.format) }; + // Add GDPR flag and consent string + if (bidderRequest.gdprConsent) { + requestParams._fw_gdpr_consent = bidderRequest.gdprConsent.consentString; + + if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { + requestParams._fw_gdpr = bidderRequest.gdprConsent.gdprApplies; + } + } + + var vastParams = currentBidRequest.params.vastUrlParams; + if (typeof vastParams === 'object') { + for (var key in vastParams) { + if (vastParams.hasOwnProperty(key)) { + requestParams[key] = vastParams[key]; + } + } + } + var location = utils.getTopWindowUrl(); if (isValidUrl(location)) { requestParams.loc = location; diff --git a/test/spec/modules/freewheelSSPBidAdapter_spec.js b/test/spec/modules/freewheelSSPBidAdapter_spec.js index 33bd647efaa..ec4483fafed 100644 --- a/test/spec/modules/freewheelSSPBidAdapter_spec.js +++ b/test/spec/modules/freewheelSSPBidAdapter_spec.js @@ -52,21 +52,27 @@ describe('freewheelSSP BidAdapter Test', () => { 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', + 'gdprConsent': { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'gdprApplies': true + } } ]; it('should add parameters to the tag', () => { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidRequests[0]); const payload = request.data; expect(payload.reqType).to.equal('AdsSetup'); expect(payload.protocolVersion).to.equal('2.0'); expect(payload.zoneId).to.equal('277225'); expect(payload.componentId).to.equal('mustang'); expect(payload.playerSize).to.equal('300x600'); + expect(payload._fw_gdpr).to.equal(true); + expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); it('sends bid request to ENDPOINT via GET', () => { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidRequests[0]); expect(request.url).to.contain(ENDPOINT); expect(request.method).to.equal('GET'); }); @@ -139,7 +145,7 @@ describe('freewheelSSP BidAdapter Test', () => { let formattedAd = '
'; it('should get correct bid response', () => { - var request = spec.buildRequests(bidRequests); + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); let expectedResponse = [ { @@ -160,7 +166,7 @@ describe('freewheelSSP BidAdapter Test', () => { }); it('should get correct bid response with formated ad', () => { - var request = spec.buildRequests(formattedBidRequests); + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); let expectedResponse = [ { @@ -181,7 +187,7 @@ describe('freewheelSSP BidAdapter Test', () => { }); it('handles nobid responses', () => { - var reqest = spec.buildRequests(formattedBidRequests); + var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); let response = ''; let result = spec.interpretResponse(response, reqest); From 429d5b4cdc982b94c926a5554fe1477cf19fddbe Mon Sep 17 00:00:00 2001 From: sami-elasticad <35566930+sami-elasticad@users.noreply.github.com> Date: Mon, 18 Jun 2018 18:27:45 +0300 Subject: [PATCH 0472/1594] QuantumBidAdapter usersync bugfix (#2700) * quantumBidAdapter initial commit * eslint errors fixed * updating quantumBidAdapter for reviews, fixed tests to work with native * set new prebid location for testing and some fixing * added supportedMediaTypes * Tests fixed * Fixed issues with image assets. Tested with the example provided * Size and tests fixed * Modify tests * hello world revert changes * package-lock reverted * hello world reverted CRLF/LF Conversion * hello world reverted LF/CRLF Conversion * hello world reverted * hello world reverted * hello world reverted * removed hardcoded bid sizes * GDPR integration * GDPR support - change quantx_gdpr to (0,1) values accepted * restored package-lock * GDPR tests * GDPR tests fixed * Send width/height with native assets * Fixed native images bug * usersync bugfixed * usersync bugfixed * usersync bugfixed * send user sync pixels as images all the time --- modules/quantumBidAdapter.js | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/modules/quantumBidAdapter.js b/modules/quantumBidAdapter.js index 57e732dfc51..966a559f3b2 100644 --- a/modules/quantumBidAdapter.js +++ b/modules/quantumBidAdapter.js @@ -297,23 +297,21 @@ export const spec = { * 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 {ServerResponse} serverResponse A successful response from the server * @return {UserSync[]} The user syncs which should be dropped. */ - getUserSyncs: function (syncOptions, serverResponses) { - const syncs = [] - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' - }); - } - if (syncOptions.pixelEnabled && serverResponses.length > 0) { - syncs.push({ - type: 'image', - url: serverResponses[0].body.sync[0] - }); - } + getUserSyncs: function (syncOptions, serverResponse) { + const syncs = []; + utils._each(serverResponse, function(serverResponse) { + if (serverResponse.body && serverResponse.body.sync) { + utils._each(serverResponse.body.sync, function (pixel) { + syncs.push({ + type: 'image', + url: pixel + }); + }); + } + }); return syncs; } } From 38fd90cd25a5fc9d6fe2931cd53d3b212a41c9b7 Mon Sep 17 00:00:00 2001 From: LeoWu Date: Tue, 19 Jun 2018 00:57:05 +0800 Subject: [PATCH 0473/1594] [FEAT] modify data to bw (#2732) --- modules/bridgewellBidAdapter.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index c57ac85bc09..222f904f276 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -5,7 +5,7 @@ import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'bridgewell'; const REQUEST_ENDPOINT = '//rec.scupio.com/recweb/prebid.aspx?cb=' + Math.random(); -const BIDDER_VERSION = '0.0.1'; +const BIDDER_VERSION = '0.0.2'; export const spec = { code: BIDDER_CODE, @@ -66,6 +66,9 @@ export const spec = { prebid: '$prebid.version$', bridgewell: BIDDER_VERSION }, + inIframe: utils.inIframe(), + url: utils.getTopWindowUrl(), + referrer: utils.getTopWindowReferrer(), adUnits: adUnits }, validBidRequests: validBidRequests From c82572e0d2c9d4530c67fa9e0a8c9490c07c3e1e Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 18 Jun 2018 15:09:44 -0400 Subject: [PATCH 0474/1594] getAdservertargeting fix (#2702) --- src/prebid.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 7d84ffa5554..c00ff1dd499 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -108,8 +108,7 @@ $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCode = function(adUnitCode) { $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargeting', arguments); - let bidsReceived = auctionManager.getBidsReceived(); - return targeting.getAllTargeting(adUnitCode, bidsReceived); + return targeting.getAllTargeting(adUnitCode); }; /** From 6e946d8ec0a66ee1186f7b718700da9c7caeceba Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 18 Jun 2018 15:21:48 -0400 Subject: [PATCH 0475/1594] updated logic for userSync - new field filterSettings (#2499) * initial commit - add filterSettings config option for userSync * remove commented code * refactored filterSettings logic, added filter default and changed bidders wildcard * update logic to support all config type --- src/adapters/bidderFactory.js | 5 +- src/userSync.js | 94 +++++++++++++++++++-- test/spec/userSync_spec.js | 149 ++++++++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+), 8 deletions(-) diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 958173a0965..d8b55f94f9c 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -329,9 +329,10 @@ export function newBidder(spec) { function registerSyncs(responses, gdprConsent) { if (spec.getUserSyncs) { + let filterConfig = config.getConfig('userSync.filterSettings'); let syncs = spec.getUserSyncs({ - iframeEnabled: config.getConfig('userSync.iframeEnabled'), - pixelEnabled: config.getConfig('userSync.pixelEnabled'), + iframeEnabled: !!(config.getConfig('userSync.iframeEnabled') || (filterConfig && (filterConfig.iframe || filterConfig.all))), + pixelEnabled: !!(config.getConfig('userSync.pixelEnabled') || (filterConfig && (filterConfig.image || filterConfig.all))), }, responses, gdprConsent); if (syncs) { if (!Array.isArray(syncs)) { diff --git a/src/userSync.js b/src/userSync.js index 059d3ea62c1..20563d447a2 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -1,5 +1,6 @@ import * as utils from 'src/utils'; import { config } from 'src/config'; +import includes from 'core-js/library/fn/array/includes'; // Set userSync default values config.setDefaults({ @@ -28,6 +29,12 @@ export function newUserSync(userSyncDependencies) { // How many bids for each adapter let numAdapterBids = {}; + // for now - default both to false in case filterSettings config is absent/misconfigured + let permittedPixels = { + image: false, + iframe: false + } + // Use what is in config by default let usConfig = userSyncDependencies.config; // Update if it's (re)set @@ -77,7 +84,7 @@ export function newUserSync(userSyncDependencies) { * @private */ function fireImagePixels() { - if (!usConfig.pixelEnabled) { + if (!(usConfig.pixelEnabled || permittedPixels.image)) { return; } // Randomize the order of the pixels before firing @@ -97,7 +104,7 @@ export function newUserSync(userSyncDependencies) { * @private */ function loadIframes() { - if (!usConfig.iframeEnabled) { + if (!(usConfig.iframeEnabled || permittedPixels.iframe)) { return; } // Randomize the order of these syncs just like the pixels above @@ -148,15 +155,89 @@ export function newUserSync(userSyncDependencies) { if (Number(numAdapterBids[bidder]) >= usConfig.syncsPerBidder) { return utils.logWarn(`Number of user syncs exceeded for "${bidder}"`); } - // All bidders are enabled by default. If specified only register for enabled bidders. - let hasEnabledBidders = usConfig.enabledBidders && usConfig.enabledBidders.length; - if (hasEnabledBidders && usConfig.enabledBidders.indexOf(bidder) < 0) { - return utils.logWarn(`Bidder "${bidder}" not supported`); + + if (usConfig.filterSettings) { + if (shouldBidderBeBlocked(type, bidder)) { + return utils.logWarn(`Bidder '${bidder}' is not permitted to register their userSync ${type} pixels as per filterSettings config.`); + } + // TODO remove this else if code that supports deprecated fields (sometime in 2.x); for now - only run if filterSettings config is not present + } else if (usConfig.enabledBidders && usConfig.enabledBidders.length && usConfig.enabledBidders.indexOf(bidder) < 0) { + return utils.logWarn(`Bidder "${bidder}" not permitted to register their userSync pixels.`); } + + // the bidder's pixel has passed all checks and is allowed to register queue[type].push([bidder, url]); numAdapterBids = incrementAdapterBids(numAdapterBids, bidder); }; + /** + * @function shouldBidderBeBlocked + * @summary Check filterSettings logic to determine if the bidder should be prevented from registering their userSync tracker + * @private + * @param {string} type The type of the sync; either image or iframe + * @param {string} bidder The name of the adapter. e.g. "rubicon" + * @returns {boolean} true => bidder is not allowed to register; false => bidder can register + */ + function shouldBidderBeBlocked(type, bidder) { + let filterConfig = usConfig.filterSettings; + + // apply the filter check if the config object is there (eg filterSettings.iframe exists) and if the config object is properly setup + if (isFilterConfigValid(filterConfig, type)) { + permittedPixels[type] = true; + + let activeConfig = (filterConfig.all) ? filterConfig.all : filterConfig[type]; + let biddersToFilter = (activeConfig.bidders === '*') ? [bidder] : activeConfig.bidders; + let filterType = activeConfig.filter || 'include'; // set default if undefined + + // return true if the bidder is either: not part of the include (ie outside the whitelist) or part of the exclude (ie inside the blacklist) + const checkForFiltering = { + 'include': (bidders, bidder) => !includes(bidders, bidder), + 'exclude': (bidders, bidder) => includes(bidders, bidder) + } + return checkForFiltering[filterType](biddersToFilter, bidder); + } + return false; + } + + /** + * @function isFilterConfigValid + * @summary Check if the filterSettings object in the userSync config is setup properly + * @private + * @param {object} filterConfig sub-config object taken from filterSettings + * @param {string} type The type of the sync; either image or iframe + * @returns {boolean} true => config is setup correctly, false => setup incorrectly or filterConfig[type] is not present + */ + function isFilterConfigValid(filterConfig, type) { + if (filterConfig.all && filterConfig[type]) { + 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; + } + + let activeConfig = (filterConfig.all) ? filterConfig.all : filterConfig[type]; + let activeConfigName = (filterConfig.all) ? 'all' : type; + + // if current pixel type isn't part of the config's logic, skip rest of the config checks... + // we return false to skip subsequent filter checks in shouldBidderBeBlocked() function + if (!activeConfig) { + return false; + } + + let filterField = activeConfig.filter; + let biddersField = activeConfig.bidders; + + if (filterField && filterField !== 'include' && filterField !== '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 => 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; + } + + return true; + } + /** * @function syncUsers * @summary Trigger all the user syncs based on publisher-defined timeout @@ -207,4 +288,5 @@ export const userSync = newUserSync({ * @property {boolean} iframeEnabled * @property {int} syncsPerBidder * @property {string[]} enabledBidders + * @property {Object} filterSettings */ diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index 9a72629c71a..60e07441e0c 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -192,4 +192,153 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0)).to.not.be.null; expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com'); }); + + it('should register both image and iframe pixels with filterSettings.all config', () => { + const userSync = newTestUserSync({ + filterSettings: { + all: { + bidders: ['atestBidder', 'testBidder'], + filter: 'include' + }, + } + }); + userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync.syncUsers(); + expect(triggerPixelStub.getCall(0)).to.not.be.null; + expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.not.be.null; + expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); + }); + + it('should register iframe and not register image pixels based on filterSettings config', () => { + const userSync = newTestUserSync({ + filterSettings: { + image: { + bidders: '*', + filter: 'exclude' + }, + iframe: { + bidders: ['testBidder'] + } + } + }); + userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync.syncUsers(); + expect(triggerPixelStub.getCall(0)).to.be.null; + expect(insertUserSyncIframeStub.getCall(0)).to.not.be.null; + expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); + }); + + it('should throw a warning and default to basic resgistration rules when filterSettings config is invalid', () => { + // invalid config - passed invalid filter option + const userSync1 = newTestUserSync({ + filterSettings: { + iframe: { + bidders: ['testBidder'], + filter: 'includes' + } + } + }); + userSync1.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync1.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync1.syncUsers(); + expect(logWarnStub.getCall(0).args[0]).to.exist; + expect(triggerPixelStub.getCall(0)).to.not.be.null; + expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + + // invalid config - bidders is not an array of strings + const userSync2 = newTestUserSync({ + filterSettings: { + iframe: { + bidders: ['testBidder', 0], + filter: 'include' + } + } + }); + userSync2.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync2.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync2.syncUsers(); + expect(logWarnStub.getCall(1).args[0]).to.exist; + expect(triggerPixelStub.getCall(1)).to.not.be.null; + expect(triggerPixelStub.getCall(1).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + + // invalid config - bidders list includes wildcard + const userSync3 = newTestUserSync({ + filterSettings: { + iframe: { + bidders: ['testBidder', '*'], + filter: 'include' + } + } + }); + userSync3.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync3.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync3.syncUsers(); + expect(logWarnStub.getCall(2).args[0]).to.exist; + expect(triggerPixelStub.getCall(2)).to.not.be.null; + expect(triggerPixelStub.getCall(2).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + + // invalid config - incorrect wildcard + const userSync4 = newTestUserSync({ + filterSettings: { + iframe: { + bidders: '***', + filter: 'include' + } + } + }); + userSync4.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync4.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync4.syncUsers(); + expect(logWarnStub.getCall(3).args[0]).to.exist; + expect(triggerPixelStub.getCall(3)).to.not.be.null; + expect(triggerPixelStub.getCall(3).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + + // invalid config - missing bidders field + const userSync5 = newTestUserSync({ + filterSettings: { + iframe: { + filter: 'include' + } + } + }); + userSync5.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync5.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync5.syncUsers(); + expect(logWarnStub.getCall(4).args[0]).to.exist; + expect(triggerPixelStub.getCall(4)).to.not.be.null; + expect(triggerPixelStub.getCall(4).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + }); + + it('should overwrite logic of deprecated fields when filterSettings is defined', () => { + const userSync = newTestUserSync({ + pixelsEnabled: false, + iframeEnabled: true, + enabledBidders: ['ctestBidder'], + filterSettings: { + image: { + bidders: '*', + filter: 'include' + }, + iframe: { + bidders: ['testBidder'], + filter: 'exclude' + } + } + }); + userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync.syncUsers(); + expect(logWarnStub.getCall(0).args[0]).to.exist; + expect(triggerPixelStub.getCall(0)).to.not.be.null; + expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + }); }); From 620ec9cf3f235723932ba8f82b702f5da4016b6c Mon Sep 17 00:00:00 2001 From: Anthony Jose Bruscantini Date: Mon, 18 Jun 2018 13:50:23 -0700 Subject: [PATCH 0476/1594] ADSS-358 returning size 1x1 when product is 2 or 5 and 1x1 is available in bidrequest sizes array (#2716) --- modules/gumgumBidAdapter.js | 13 +++++-- test/spec/modules/gumgumBidAdapter_spec.js | 41 ++++++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 6a5575d74fe..9f8d131f462 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -174,8 +174,17 @@ function interpretResponse (serverResponse, bidRequest) { pvid } } = Object.assign(defaultResponse, serverResponseBody) - let isTestUnit = (bidRequest.data && bidRequest.data.pi === 3 && bidRequest.data.si === 9) - let [width, height] = utils.parseSizesInput(bidRequest.sizes)[0].split('x') + let data = bidRequest.data || {} + let product = data.pi + let isTestUnit = (product === 3 && data.si === 9) + let sizes = utils.parseSizesInput(bidRequest.sizes) + let [width, height] = sizes[0].split('x') + + // return 1x1 when breakout expected + if ((product === 2 || product === 5) && sizes.includes('1x1')) { + width = '1' + height = '1' + } // update Page View ID from server response pageViewId = pvid diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 8a59d61e2bc..23ad392ff1b 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -20,7 +20,7 @@ describe('gumgumAdapter', () => { 'inScreen': '10433394' }, 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], + 'sizes': [[300, 250], [300, 600], [1, 1]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', @@ -109,7 +109,7 @@ describe('gumgumAdapter', () => { } let bidRequest = { id: 12345, - sizes: [[300, 250]], + sizes: [[300, 250], [1, 1]], url: ENDPOINT, method: 'GET', pi: 3 @@ -146,6 +146,43 @@ describe('gumgumAdapter', () => { let result = spec.interpretResponse({ body: response }, bidRequest); expect(result.length).to.equal(0); }); + + it('returns 1x1 when eligible product and size available', () => { + let inscreenBidRequest = { + id: 12346, + sizes: [[300, 250], [1, 1]], + url: ENDPOINT, + method: 'GET', + data: { + pi: 2, + t: 'ggumtest' + } + } + let inscreenServerResponse = { + 'ad': { + 'id': 2065333, + 'height': 90, + 'ipd': 2000, + 'markup': '

I am an inscreen ad

', + 'ii': true, + 'du': null, + 'price': 1, + 'zi': 0, + 'impurl': 'http://g2.gumgum.com/ad/view', + 'clsurl': 'http://g2.gumgum.com/ad/close' + }, + 'pag': { + 't': 'ggumtest', + 'pvid': 'aa8bbb65-427f-4689-8cee-e3eed0b89eec', + 'css': 'html { overflow-y: auto }', + 'js': 'console.log("environment", env);' + }, + 'thms': 10000 + } + let result = spec.interpretResponse({ body: inscreenServerResponse }, inscreenBidRequest); + expect(result[0].width).to.equal('1'); + expect(result[0].height).to.equal('1'); + }) }) describe('getUserSyncs', () => { const syncOptions = { From 94d3c711d6d96e107d44a271966c17e91e879541 Mon Sep 17 00:00:00 2001 From: Tomas Roos Date: Mon, 18 Jun 2018 22:58:32 +0200 Subject: [PATCH 0477/1594] Allow user to override which gpt slots should be targeted at invocation (#2562) * Allow user to override which gpt slots should be targeted at invocation time * Added filter example --- src/prebid.js | 5 +++-- src/targeting.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index c00ff1dd499..16284115220 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -155,9 +155,10 @@ $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode = function (adUnitCode) { /** * Set query string targeting on one or more GPT ad units. * @param {(string|string[])} adUnit a single `adUnit.code` or multiple. + * @param {function(object)} customSlotMatching gets a GoogleTag slot and returns a filter function for adUnitCode, so you can decide to match on either eg. return slot => { return adUnitCode => { return slot.getSlotElementId() === 'myFavoriteDivId'; } }; * @alias module:pbjs.setTargetingForGPTAsync */ -$$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit) { +$$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit, customSlotMatching) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.setTargetingForGPTAsync', arguments); if (!isGptPubadsDefined()) { utils.logError('window.googletag is not defined on the page'); @@ -171,7 +172,7 @@ $$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit) { targeting.resetPresetTargeting(adUnit); // now set new targeting keys - targeting.setTargetingForGPT(targetingSet); + targeting.setTargetingForGPT(targetingSet, customSlotMatching); Object.keys(targetingSet).forEach((adUnitCode) => { Object.keys(targetingSet[adUnitCode]).forEach((targetingKey) => { diff --git a/src/targeting.js b/src/targeting.js index f81949f6d04..e33f1a88f10 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -160,9 +160,9 @@ export function newTargeting(auctionManager) { * Sets targeting for DFP * @param {Object.>} targetingConfig */ - targeting.setTargetingForGPT = function(targetingConfig) { + targeting.setTargetingForGPT = function(targetingConfig, customSlotMatching) { window.googletag.pubads().getSlots().forEach(slot => { - Object.keys(targetingConfig).filter(isAdUnitCodeMatchingSlot(slot)) + Object.keys(targetingConfig).filter(customSlotMatching ? customSlotMatching(slot) : isAdUnitCodeMatchingSlot(slot)) .forEach(targetId => Object.keys(targetingConfig[targetId]).forEach(key => { let valueArr = targetingConfig[targetId][key].split(','); From 618358ba43bcc5629c90b6c271543a20304ff1a7 Mon Sep 17 00:00:00 2001 From: uriw-fyber <35529969+uriw-fyber@users.noreply.github.com> Date: Tue, 19 Jun 2018 02:41:28 +0300 Subject: [PATCH 0478/1594] Fyber Bid Adapter (#2709) * Fyber Bid Adapter * Jenkins build file * Updates based on PR - https://github.com/prebid/Prebid.js/pull/2709 * Removing test Jenkinsfile --- modules/fyberBidAdapter.js | 378 ++++++++++++++++++++++ modules/fyberBidAdapter.md | 56 ++++ test/spec/modules/fyberBidAdapter_spec.js | 154 +++++++++ 3 files changed, 588 insertions(+) create mode 100644 modules/fyberBidAdapter.js create mode 100644 modules/fyberBidAdapter.md create mode 100644 test/spec/modules/fyberBidAdapter_spec.js diff --git a/modules/fyberBidAdapter.js b/modules/fyberBidAdapter.js new file mode 100644 index 00000000000..8309b1996c3 --- /dev/null +++ b/modules/fyberBidAdapter.js @@ -0,0 +1,378 @@ +import {logError, getTopWindowUrl, getTopWindowReferrer, getTopWindowLocation, createTrackPixelHtml} from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { formatQS } from 'src/url'; +import { config } from 'src/config'; + +/** + * @type {{CODE: string, V: string, RECTANGLE_SIZE: {W: number, H: number}, SPOT_TYPES: {INTERSTITIAL: string, RECTANGLE: string, FLOATING: string, BANNER: string}, DISPLAY_AD: number, ENDPOINT_URL: string, EVENTS_ENDPOINT_URL: string, RESPONSE_HEADERS_NAME: {PRICING_VALUE: string, AD_H: string, AD_W: string}}} + */ +const CONSTANTS = { + CODE: 'fyber', + V: 'FY-JS-HB-PBJS-1.0', + RECTANGLE_SIZE: {W: 300, H: 250}, + + SPOT_TYPES: { + INTERSTITIAL: 'interstitial', + RECTANGLE: 'rectangle', + FLOATING: 'floating', + BANNER: 'banner' + }, + + DISPLAY_AD: 20, + ENDPOINT_URL: '//ad-tag.inner-active.mobi/simpleM2M/requestJsonAd', + EVENTS_ENDPOINT_URL: '//vast-events.inner-active.mobi/Event', + RESPONSE_HEADERS_NAME: { + PRICING_VALUE: 'X-IA-Pricing-Value', + AD_H: 'X-IA-Ad-Height', + AD_W: 'X-IA-Ad-Width', + CREATIVE_ID: 'X-IA-Creative-ID', + CURRENCY: 'X-IA-Pricing-Currency', + TIMEOUT: 'X-IA-SESSION-TIMEOUT' + } +}; + +/** + * gloable util functions + * @type {{defaultsQsParams: {v: (string|string), page: string, mw: boolean, hb: string}, stringToCamel: (function(*)), objectToCamel: (function(*=))}} + */ +const Helpers = { + defaultsQsParams: {v: CONSTANTS.V, page: encodeURIComponent(getTopWindowUrl()), mw: true, hb: 'prebidjs'}, + /** + * Returns the ad HTML template + * @param adHtml: string {ad server creative} + * @param tracking: object {impressions, clicks} + * @param bidParams: object + * @returns {string}: create template + */ + getAd(adHtml, tracking, bidParams) { + let impressionsHtml = ''; + if (tracking && Array.isArray(tracking.impressions)) { + let impressions = tracking.impressions; + impressions.push(Reporter.getEventUrl('HBPreBidImpression', bidParams, false)); + impressions.forEach(impression => impression && (impressionsHtml += createTrackPixelHtml(impression))); + } + adHtml = impressionsHtml + adHtml.replace(/ + + + + +
${adHtml}
+ + + `; + return adTemplate; + }, + + /** + * Change string format from underscore to camelcase (e.g., APP_ID to appId) + * @param {string} str + * @return string + */ + stringToCamel(str) { + if (str.indexOf('_') === -1) { + const first = str.charAt(0); + if (first !== first.toLowerCase()) { + str = str.toLowerCase(); + } + return str; + } + + str = str.toLowerCase(); + return str.replace(/(\_[a-z])/g, $1 => $1.toUpperCase().replace('_', '')); + }, + + /** + * Change all object keys string format from underscore to camelcase (e.g., {'APP_ID' : ...} to {'appId' : ...}) + * @param params: object + * @returns object + */ + objectToCamel(params) { + Object.keys(params).forEach(key => { + const keyCamelCase = this.stringToCamel(key); + if (keyCamelCase !== key) { + params[keyCamelCase] = params[key]; + delete params[key]; + } + }); + return params; + }, + + /** + * @param {Object} params + * @return {string} url + */ + getEndpointUrl(params) { + return (params && params.qa && params.qa.url) || (Reporter.getPageProtocol() + CONSTANTS.ENDPOINT_URL); + }, + + /** + * Adjust bid params to fyber-ad-server params + * @param {Object} bid + * @return {Object} bid + */ + toBidParams(bid) { + const bidParamsWithCustomParams = Object.assign({}, bid.params, bid.params.customParams); + delete bidParamsWithCustomParams.customParams; + bid.params = this.objectToCamel(bidParamsWithCustomParams); + return bid; + }, + + /** + * Validate if response is valid + * @param responseAsJson : object + * @param headersData: {} + * @returns {boolean} + * @private + */ + isValidBidResponse(responseAsJson, headersData) { + return (responseAsJson && responseAsJson.ad && responseAsJson.ad.html && headersData && headersData[CONSTANTS.RESPONSE_HEADERS_NAME.PRICING_VALUE] > 0); + } +}; + +/** + * Url generator - generates a request URL + * @type {{defaultsParams: *, serverParamNameBySettingParamName: {referrer: string, keywords: string, appId: string, portal: string, age: string, gender: string, isSecured: (boolean|null)}, toServerParams: (function(*)), unwantedValues: *[], getUrlParams: (function(*=))}} + */ +const Url = { + defaultsParams: Object.assign({}, Helpers.defaultsQsParams, {f: CONSTANTS.DISPLAY_AD, fs: false, ref: getTopWindowReferrer()}), + serverParamNameBySettingParamName: { + referrer: 'ref', + keywords: 'k', + appId: 'aid', + portal: 'po', + age: 'a', + gender: 'g', + gdprPrivacyConsent: 'gdpr_privacy_consent', + consentString: 'consent_string', + gdprConsentData: 'gdpr_consent_data' + }, + unwantedValues: ['', null, undefined], + + /** + * Maps publisher params to server params + * @param params: object {k:v} + * @returns object {k:v} + */ + toServerParams(params) { + const serverParams = {}; + for (const paramName in params) { + if (params.hasOwnProperty(paramName) && this.serverParamNameBySettingParamName.hasOwnProperty(paramName)) { + serverParams[this.serverParamNameBySettingParamName[paramName]] = params[paramName]; + } else { + serverParams[paramName] = params[paramName]; + } + } + + serverParams.isSecured = Reporter.getPageProtocol() === 'https:' || null; + return serverParams; + }, + + handleGDPR(params) { + if (params.hasOwnProperty('gdprPrivacyConsent')) { + if (['true', true, '1', 1].indexOf(params.gdprPrivacyConsent) !== -1) { + params.gdprPrivacyConsent = 1; + } else { + params.gdprPrivacyConsent = 0; + } + } + }, + + /** + * Prepare querty string to ad server + * @param params: object {k:v} + * @returns : object {k:v} + */ + getUrlParams(params) { + this.handleGDPR(params); + const serverParams = this.toServerParams(params); + const toQueryString = Object.assign({}, this.defaultsParams, serverParams); + for (const paramName in toQueryString) { + if (toQueryString.hasOwnProperty(paramName) && this.unwantedValues.indexOf(toQueryString[paramName]) !== -1) { + delete toQueryString[paramName]; + } + } + toQueryString.fs = params.spotType === CONSTANTS.SPOT_TYPES.INTERSTITIAL; + + if (params.spotType === CONSTANTS.SPOT_TYPES.RECTANGLE) { + toQueryString.rw = CONSTANTS.RECTANGLE_SIZE.W; + toQueryString.rh = CONSTANTS.RECTANGLE_SIZE.H; + } + toQueryString.bco = config.getConfig('cbTimeout') || config.getConfig('bidderTimeout'); + toQueryString.timestamp = Date.now(); + delete toQueryString.qa; + return toQueryString; + } +}; + +/** + * Analytics + * @type {{errorEventName: string, pageProtocol: string, getPageProtocol: (function(): string), getEventUrl: (function(*, *=)), defaults: {v: (string|string), page: string, mw: boolean, hb: string}, eventQueryStringParams: (function(Object): string)}} + */ +const Reporter = { + /** + * @private + */ + errorEventName: 'HBPreBidError', + pageProtocol: '', + defaults: Helpers.defaultsQsParams, + + /** + * Gets the page protocol based on the document.location.protocol + * The returned string is either http:// or https:// + * @return {string} + */ + getPageProtocol() { + if (!this.pageProtocol) { + this.pageProtocol = (getTopWindowLocation().protocol === 'http:' ? 'http:' : 'https:'); + } + return this.pageProtocol; + }, + + getEventUrl(evtName, extraDetails) { + let eventsEndpoint = CONSTANTS.EVENTS_ENDPOINT_URL + '?table=' + ((evtName === this.errorEventName) ? 'mbwError' : 'mbwEvent'); + let queryStringParams = this.eventQueryStringParams(extraDetails); + const appId = extraDetails && extraDetails.appId; + let queryStringParamsWithAID = `${queryStringParams}&aid=${appId}_${evtName}_other&evtName=${evtName}`; + return eventsEndpoint + '&' + queryStringParamsWithAID; + }, + + /** + * Fyber Event Reporting Query String Parameters, not including App Id. + * @param {object} extraDetails - e.g., a JS exception JSON object. + * @return {string} Fyber event contcatenated queryString parameters. + */ + eventQueryStringParams(extraDetails) { + const toQS = Object.assign({}, this.defaults, {realAppId: extraDetails && extraDetails.appId, timestamp: Date.now()}); + Url.handleGDPR(toQS); + return formatQS(toQS); + } +}; +const {PRICING_VALUE, AD_W, AD_H, CREATIVE_ID, CURRENCY, TIMEOUT} = CONSTANTS.RESPONSE_HEADERS_NAME; +/** + * Http helper to extract metadata + * @type {{headers: *[], getBidHeaders: (function(*))}} + */ +const Http = { + headerNames: [PRICING_VALUE, AD_W, AD_H, CREATIVE_ID, CURRENCY, TIMEOUT], + + /** + * Extract headers data + * @param responseHeaders: XMLHttpRequest + * @return {} + */ + getBidHeaders(responseHeaders) { + const headersData = {}; + this.headerNames.forEach(headerName => headersData[headerName] = responseHeaders.get(headerName)); + return headersData; + } +}; + +const bidByBidId = {}; +class FyberBid { + constructor(headersData, response, bid) { + this.handleGDPR(response.config.tracking, bid.params); + const [w, h] = bid.sizes[0]; + this.cpm = ((bid.params.qa && bid.params.qa.cpm) || headersData[PRICING_VALUE]) * 1000; + this.requestId = bid.bidId; + this.width = parseFloat(headersData[AD_W]) || w; + this.ad = Helpers.getAd(response.ad.html, response.config.tracking, bid.params); + this.height = parseFloat(headersData[AD_H]) || h; + this.creativeId = headersData[CREATIVE_ID]; + this.currency = headersData[CURRENCY] || 'USD'; + this.netRevenue = true; + this.ttl = 60 * (headersData[TIMEOUT] || 20); + this.dealId = null; + } + + handleGDPR(tracking, params) { + if (params.hasOwnProperty('gdprPrivacyConsent')) { + if (['true', true, '1', 1].indexOf(params.gdprPrivacyConsent) !== -1) { + params.gdprPrivacyConsent = 1; + } else { + params.gdprPrivacyConsent = 0; + } + Object.keys(tracking).forEach((trackName) => { + if (Array.isArray(tracking[trackName])) { + tracking[trackName].forEach((url, index) => { + if (url) { + if (url.indexOf('?') === -1) { + url += '?'; + } + url += '&gdpr_privacy_consent=' + params.gdprPrivacyConsent; + tracking[trackName][index] = url; + } + }); + } + }); + } + } +} + +export const spec = { + code: CONSTANTS.CODE, + + /** + * Determines whether or not the given bid request is valid. + * Valid bid request must have appId and spotType + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid(bid) { + const {appId, spotType} = Helpers.objectToCamel(bid.params); + const isValid = !!(appId && spotType); + if (!isValid) { + logError(`bid requires appId = ${appId} , spotType = ${spotType}`); + } + return isValid; + }, + + buildRequests(bidRequests) { + let requests = []; + bidRequests.forEach((bid) => { + bid = Helpers.toBidParams(bid); + bidByBidId[bid.bidId] = bid; + requests.push({ + method: 'GET', + url: Helpers.getEndpointUrl(bid.params), + data: Url.getUrlParams(bid.params), + bidId: bid.bidId + }); + }); + return requests; + }, + + interpretResponse(response, request) { + const isValid = response.body && response.body.ad; + const headersData = (isValid && Http.getBidHeaders(response.headers)) || {}; + const bid = bidByBidId[request.bidId]; + const bidResponse = []; + if (!isValid || !Helpers.isValidBidResponse(response.body, headersData)) { + logError(`response failed for ${CONSTANTS.CODE} adapter`); + return bidResponse; + } + bidResponse.push(new FyberBid(headersData, response.body, bid)); + return bidResponse; + } +}; +registerBidder(spec); diff --git a/modules/fyberBidAdapter.md b/modules/fyberBidAdapter.md new file mode 100644 index 00000000000..c394addadfe --- /dev/null +++ b/modules/fyberBidAdapter.md @@ -0,0 +1,56 @@ +# Overview + +``` +Module Name: Fyber Bidder Adapter +Module Type: Bidder Adapter +Maintainer: uri@inner-active.com +``` + +# Description + +Module that connects to Fyber's demand sources + +# Test Parameters +``` +var adUnits = [ +{ +code: 'test-div', +mediaTypes: { +banner: { +sizes: [[300, 250]], // a display rectangle size +} +}, +bids: [ +{ +bidder: 'fyber', + params: { + APP_ID: 'MyCompany_MyApp', + spotType: 'rectangle', + customParams: { + portal: 7002 + } + } +} +] +},{ +code: 'test-div', +mediaTypes: { +banner: { +sizes: [[320, 50]], // a banner size +} +}, +bids: [ +{ +bidder: 'fyber', + params: { + APP_ID: 'MyCompany_MyApp', + spotType: 'banner', + customParams: { + portal: 7001 + } + } +} +] +} +]; +``` diff --git a/test/spec/modules/fyberBidAdapter_spec.js b/test/spec/modules/fyberBidAdapter_spec.js new file mode 100644 index 00000000000..c6b49916519 --- /dev/null +++ b/test/spec/modules/fyberBidAdapter_spec.js @@ -0,0 +1,154 @@ +import { expect } from 'chai'; +import { spec } from 'modules/fyberBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import bidRequest from '../../fixtures/video/bidRequest.json'; + +const bidId = '21b2499bf34cf8'; +const mock = { + bid: { + bidder: 'fyber', + params: { + appId: 'MyCompany_MyApp', + spotType: 'rectangle', + gdprPrivacyConsent: true, + qa: { + // url: 'http://ia-test08.inner-active.mobi:8080/simpleM2M/requestJsonAd', + cpm: 10 + }, + customParams: { + // referrer: 'referrer', + // page: 'aaaa', + portal: 7002 + // KEYWORDS: 'bbb' + } + } + }, + bidsRequest: [ + { + adUnitCode: '/19968336/header-bid-tag-1', + auctionId: 'f270d8dd-29c6-4aca-8648-7d722590b899', + bidId, + bidder: 'fyber', + bidderRequestId: '1bcd667e09f48e', + params: { + spotType: 'rectangle', + gdprPrivacyConsent: true, + qa: {cpm: 10}, + customParams: {portal: 7002}, + appId: 'MyCompany_MyApp' + }, + sizes: [[300, 250], [300, 600]], + transactionId: 'a0253346-df4e-4f1a-b004-1f50e8e6af69' + } + ], + validResponse: { + body: { + ad: { + html: '

Fyber Ad

' + }, + config: { + tracking: { + clicks: ['c1'], + impressions: ['i1'] + } + } + }, + headers: { + get(headerName) { + if (headerName === 'X-IA-Pricing-Value') { + return 10; + } + return headerName; + } + } + }, + invalidResponse: { + body: {}, + headers: { + get(headerName) { + return headerName; + } + } + } +}; + +describe('FyberAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('callBids exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('Verifies bidder code', () => { + it('Verifies bidder code', () => { + expect(spec.code).to.equal('fyber'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + const bid = Object.assign({}, mock.bid); + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params{spotType} not found', () => { + const bid = Object.assign({}, mock.bid); + delete bid.params.spotType; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when required{appId} params not found', () => { + const bid = Object.assign({}, mock.bid); + delete bid.params.appId; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const bidsRequest = Object.assign([], mock.bidsRequest); + const requests = spec.buildRequests(bidsRequest); + + it('Verify only one build request', () => { + expect(requests.length).to.equal(1); + }); + + const request = requests[0]; + + it('Verify build request http method', () => { + expect(request.method).to.equal('GET'); + }); + + it('Verify build request bidId', () => { + expect(request.bidId).to.equal(bidId); + }); + }); + + describe('interpretResponse', () => { + const request = Object.assign([], mock.bidsRequest)[0]; + const validResponse = Object.assign({}, mock.validResponse); + const validResult = spec.interpretResponse(validResponse, request); + + it('Verify only one bid response', () => { + expect(validResult.length).to.equal(1); + }); + + const bidResponse = validResult[0]; + + it('Verify CPM', () => { + expect(bidResponse.cpm).to.equal(10000); + }); + + it('Verify requestId', () => { + expect(bidResponse.requestId).to.equal(bidId); + }); + + const invalidResponse = Object.assign({}, mock.invalidResponse); + const invalidResult = spec.interpretResponse(invalidResponse, request); + + it('Verify empty bid response', () => { + expect(invalidResult.length).to.equal(0); + }); + }); +}); From 3760b87474650161f0c21b1fe63e0bf08149ab7e Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 19 Jun 2018 08:34:49 -0400 Subject: [PATCH 0479/1594] Unit test fix (#2739) --- modules/gumgumBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 9f8d131f462..d8881f56f0d 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -2,6 +2,7 @@ import * as utils from 'src/utils' import { config } from 'src/config' import { registerBidder } from 'src/adapters/bidderFactory' +import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'gumgum' const ALIAS_BIDDER_CODE = ['gg'] @@ -181,7 +182,7 @@ function interpretResponse (serverResponse, bidRequest) { let [width, height] = sizes[0].split('x') // return 1x1 when breakout expected - if ((product === 2 || product === 5) && sizes.includes('1x1')) { + if ((product === 2 || product === 5) && includes(sizes, '1x1')) { width = '1' height = '1' } From 4cfb3bcbd3876c758dedb489579c8aded570a65b Mon Sep 17 00:00:00 2001 From: Dorian Wojda Date: Tue, 19 Jun 2018 14:42:14 +0200 Subject: [PATCH 0480/1594] Added GDPR consent management to YOC VIS.X Bid Adapter (#2737) - Added GDPR consent management support - Description updated --- modules/visxBidAdapter.js | 24 +++++++++++++++++++++--- modules/visxBidAdapter.md | 4 ++-- test/spec/modules/visxBidAdapter_spec.js | 23 +++++++++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 1fad6cd8337..39bfe7eca4e 100755 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -22,7 +22,7 @@ export const spec = { isBidRequestValid: function(bid) { return !!bid.params.uid; }, - buildRequests: function(validBidRequests) { + buildRequests: function(validBidRequests, bidderRequest) { const auids = []; const bidsMap = {}; const bids = validBidRequests || []; @@ -55,6 +55,15 @@ export const spec = { cur: currency, }; + if (bidderRequest && 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; + } + return { method: 'GET', url: ENDPOINT_URL, @@ -84,11 +93,20 @@ export const spec = { if (errorMessage) utils.logError(errorMessage); return bidResponses; }, - getUserSyncs: function(syncOptions) { + getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { 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)); + } return [{ type: 'image', - url: ADAPTER_SYNC_URL + url: ADAPTER_SYNC_URL + (query.length ? '?' + query.join('&') : '') }]; } } diff --git a/modules/visxBidAdapter.md b/modules/visxBidAdapter.md index 7d5981132c2..41e45622481 100755 --- a/modules/visxBidAdapter.md +++ b/modules/visxBidAdapter.md @@ -1,14 +1,14 @@ # Overview ``` -Module Name: VIS.X Bidder Adapter +Module Name: YOC VIS.X Bidder Adapter Module Type: Bidder Adapter Maintainer: service@yoc.com ``` # Description -Module that connects to VIS.X demand source to fetch bids. +Module that connects to YOC VIS.X® demand source to fetch bids. # Test Parameters ``` diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 20b056adf6d..67b747b5130 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -149,6 +149,29 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'USD'); getConfigStub.restore(); }); + it('if gdprConsent is present payload must have gdpr params', () => { + 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', () => { + 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', () => { + 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); + }); }); describe('interpretResponse', () => { From 069c4e3cd1999895e8dbd07b849fa084317f240e Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 19 Jun 2018 07:17:41 -0600 Subject: [PATCH 0481/1594] move generation of transactionIds to requestBids over addAdUnits (#2706) * move generation of transactionIds to requestBids over addAdUnits * remove transactionId generation for arrays as well * move transactionId check in tests * remove errant debugger statement --- src/prebid.js | 11 +++++------ test/spec/adUnits_spec.js | 7 ------- test/spec/unit/pbjs_api_spec.js | 23 +++++++++++++++++++++++ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 16284115220..e1691c20f79 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -339,9 +339,13 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa const bidders = adUnit.bids.map(bid => bid.bidder); const bidderRegistry = adaptermanager.bidderRegistry; + if (!adUnit.transactionId) { + adUnit.transactionId = utils.generateUUID(); + } + bidders.forEach(bidder => { const adapter = bidderRegistry[bidder]; - const spec = adapter && adapter.getSpec && adapter.getSpec() + const spec = adapter && adapter.getSpec && adapter.getSpec(); // banner is default if not specified in spec const bidderMediaTypes = (spec && spec.supportedMediaTypes) || ['banner']; @@ -382,13 +386,8 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa $$PREBID_GLOBAL$$.addAdUnits = function (adUnitArr) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.addAdUnits', arguments); if (utils.isArray(adUnitArr)) { - // generate transactionid for each new adUnits - // Append array to existing - adUnitArr.forEach(adUnit => adUnit.transactionId = utils.generateUUID()); $$PREBID_GLOBAL$$.adUnits.push.apply($$PREBID_GLOBAL$$.adUnits, adUnitArr); } else if (typeof adUnitArr === 'object') { - // Generate the transaction id for the adunit - adUnitArr.transactionId = utils.generateUUID(); $$PREBID_GLOBAL$$.adUnits.push(adUnitArr); } // emit event diff --git a/test/spec/adUnits_spec.js b/test/spec/adUnits_spec.js index f15ba41eb23..7dd48a13208 100644 --- a/test/spec/adUnits_spec.js +++ b/test/spec/adUnits_spec.js @@ -82,13 +82,6 @@ describe('Publisher API _ AdUnits', function () { assert.strictEqual(bids2[1].params.placementId, '827326', 'adUnit2 bids2 params.placementId'); }); - it('both add unit should contains a transactionId', function() { - assert.isString(adUnit1.transactionId); - assert.isString(adUnit2.transactionId); - - assert.strictEqual(false, adUnit1.transactionId === adUnit2.transactionId); - }); - it('the second adUnits value should be same with the adUnits that is added by $$PREBID_GLOBAL$$.addAdUnits();', function () { assert.strictEqual(adUnit2.code, '/1996833/slot-2', 'adUnit2 code'); assert.deepEqual(adUnit2.sizes, [[468, 60]], 'adUnit2 sizes'); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 5f77d0e5bf7..93904dcfaf8 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1209,9 +1209,12 @@ describe('Unit: Prebid Module', function () { registerBidder(spec); describe('part 1', () => { + let auctionArgs; + beforeEach(() => { adUnitsBackup = auction.getAdUnits auctionManagerStub = sinon.stub(auctionManager, 'createAuction').callsFake(function() { + auctionArgs = arguments[0]; return auction; }); logMessageSpy = sinon.spy(utils, 'logMessage'); @@ -1234,6 +1237,26 @@ describe('Unit: Prebid Module', function () { assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); }); + it('should attach transactionIds to ads (or pass through transactionId if it already exists)', () => { + $$PREBID_GLOBAL$$.requestBids({ + adUnits: [ + { + code: 'test1', + transactionId: 'd0676a3c-ff32-45a5-af65-8175a8e7ddca', + bids: [] + }, { + code: 'test2', + bids: [] + } + ] + }); + + expect(auctionArgs.adUnits[0]).to.have.property('transactionId') + .and.to.equal('d0676a3c-ff32-45a5-af65-8175a8e7ddca'); + expect(auctionArgs.adUnits[1]).to.have.property('transactionId') + .and.to.match(/[a-f0-9\-]{36}/i); + }); + it('should execute callback immediately if adUnits is empty', () => { var bidsBackHandler = function bidsBackHandlerCallback() {}; var spyExecuteCallback = sinon.spy(bidsBackHandler); From d9032d2f4cb8e285b8ae24c17545da91be9f5dc2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 19 Jun 2018 11:34:38 -0400 Subject: [PATCH 0482/1594] Separate ajax for client side and s2s requests (#2735) * bugfix: separate ajax for client side and s2s requests * Fix lint error --- src/adaptermanager.js | 6 +++--- test/spec/unit/core/adapterManager_spec.js | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 98d9d5fb426..f6c0d5c421e 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -279,14 +279,13 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { return; } - let ajax = ajaxBuilder(bidRequests[0].timeout); - let [clientBidRequests, serverBidRequests] = bidRequests.reduce((partitions, bidRequest) => { partitions[Number(typeof bidRequest.src !== 'undefined' && bidRequest.src === CONSTANTS.S2S.SRC)].push(bidRequest); return partitions; }, [[], []]); if (serverBidRequests.length) { + const s2sAjax = ajaxBuilder(serverBidRequests[0].timeout); let adaptersServerSide = _s2sConfig.bidders; const s2sAdapter = _bidderRegistry[_s2sConfig.adapter]; let tid = serverBidRequests[0].tid; @@ -331,12 +330,13 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { serverBidRequests, addBidResponse, () => doneCbs.forEach(done => done()), - ajax + s2sAjax ); } } } + const ajax = (clientBidRequests.length) ? ajaxBuilder(clientBidRequests[0].timeout) : null; // handle client adapter requests clientBidRequests.forEach(bidRequest => { bidRequest.start = timestamp(); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 8b1c164a804..df03af5f354 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -151,6 +151,7 @@ describe('adapterManager tests', () => { 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', + 'timeout': 1000, 'src': 's2s', 'adUnitsS2SCopy': [ { @@ -315,6 +316,7 @@ describe('adapterManager tests', () => { 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', 'src': 's2s', + 'timeout': 1000, 'adUnitsS2SCopy': [ { 'code': '/19968336/header-bid-tag1', @@ -444,6 +446,7 @@ describe('adapterManager tests', () => { ], 'start': 1462918897460 }]; + AdapterManager.callBids( adUnits, bidRequests, From b60a7529f8e91f5d74b053a812e2b3dc45cfc34a Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 20 Jun 2018 13:21:19 -0400 Subject: [PATCH 0483/1594] update some unit tests to clean-up consentManagement hooks (#2711) * update some unit tests to clean-up gdpr module hooks * add cleanup for pubCommonId requestBids hook --- .../modules/prebidServerBidAdapter_spec.js | 138 +++++++++--------- test/spec/modules/pubCommonId_spec.js | 3 + .../modules/smartadserverBidAdapter_spec.js | 86 ++++++----- 3 files changed, 121 insertions(+), 106 deletions(-) diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index b155d61d8e5..8bc3d577ede 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -402,97 +402,101 @@ describe('S2S Adapter', () => { expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); }); - it('adds gdpr consent information to ortb2 request depending on presence of module', () => { - let ortb2Config = utils.deepClone(CONFIG); - ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + describe('gdpr tests', () => { + afterEach(() => { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + }); - let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: ortb2Config }; - config.setConfig(consentConfig); + it('adds gdpr consent information to ortb2 request depending on presence of module', () => { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' - let gdprBidRequest = utils.deepClone(BID_REQUESTS); - gdprBidRequest[0].gdprConsent = { - consentString: 'abc123', - gdprApplies: true - }; + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: ortb2Config }; + config.setConfig(consentConfig); - adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); - let requestBid = JSON.parse(requests[0].requestBody); + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: 'abc123', + gdprApplies: true + }; - expect(requestBid.regs.ext.gdpr).is.equal(1); - expect(requestBid.user.ext.consent).is.equal('abc123'); + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); - config.resetConfig(); - config.setConfig({s2sConfig: CONFIG}); + expect(requestBid.regs.ext.gdpr).is.equal(1); + expect(requestBid.user.ext.consent).is.equal('abc123'); - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - requestBid = JSON.parse(requests[1].requestBody); + config.resetConfig(); + config.setConfig({s2sConfig: CONFIG}); - expect(requestBid.regs).to.not.exist; - expect(requestBid.user).to.not.exist; + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + requestBid = JSON.parse(requests[1].requestBody); - config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); - }); + expect(requestBid.regs).to.not.exist; + expect(requestBid.user).to.not.exist; + }); - it('check gdpr info gets added into cookie_sync request: have consent data', () => { - let cookieSyncConfig = utils.deepClone(CONFIG); - cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + it('check gdpr info gets added into cookie_sync request: have consent data', () => { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; - let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; - config.setConfig(consentConfig); + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); - let gdprBidRequest = utils.deepClone(BID_REQUESTS); + let gdprBidRequest = utils.deepClone(BID_REQUESTS); - gdprBidRequest[0].gdprConsent = { - consentString: 'abc123def', - gdprApplies: true - }; + gdprBidRequest[0].gdprConsent = { + consentString: 'abc123def', + gdprApplies: true + }; - adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); - let requestBid = JSON.parse(requests[0].requestBody); + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); - expect(requestBid.gdpr).is.equal(1); - expect(requestBid.gdpr_consent).is.equal('abc123def'); - }); + expect(requestBid.gdpr).is.equal(1); + expect(requestBid.gdpr_consent).is.equal('abc123def'); + }); - it('check gdpr info gets added into cookie_sync request: have consent data but gdprApplies is false', () => { - let cookieSyncConfig = utils.deepClone(CONFIG); - cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + it('check gdpr info gets added into cookie_sync request: have consent data but gdprApplies is false', () => { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; - let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; - config.setConfig(consentConfig); + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); - let gdprBidRequest = utils.deepClone(BID_REQUESTS); - gdprBidRequest[0].gdprConsent = { - consentString: 'xyz789abcc', - gdprApplies: false - }; + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: 'xyz789abcc', + gdprApplies: false + }; - adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); - let requestBid = JSON.parse(requests[0].requestBody); + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); - expect(requestBid.gdpr).is.equal(0); - expect(requestBid.gdpr_consent).is.undefined; - }); + expect(requestBid.gdpr).is.equal(0); + expect(requestBid.gdpr_consent).is.undefined; + }); - it('checks gdpr info gets added to cookie_sync request: consent data unknown', () => { - let cookieSyncConfig = utils.deepClone(CONFIG); - cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + it('checks gdpr info gets added to cookie_sync request: consent data unknown', () => { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; - let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; - config.setConfig(consentConfig); + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); - let gdprBidRequest = utils.deepClone(BID_REQUESTS); - gdprBidRequest[0].gdprConsent = { - consentString: undefined, - gdprApplies: undefined - }; + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: undefined, + gdprApplies: undefined + }; - adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); - let requestBid = JSON.parse(requests[0].requestBody); + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); - expect(requestBid.gdpr).is.undefined; - expect(requestBid.gdpr_consent).is.undefined; + expect(requestBid.gdpr).is.undefined; + expect(requestBid.gdpr_consent).is.undefined; + }); }); it('sets invalid cacheMarkup value to 0', () => { diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js index 50ca4616a4b..bdb9d4f0545 100644 --- a/test/spec/modules/pubCommonId_spec.js +++ b/test/spec/modules/pubCommonId_spec.js @@ -18,6 +18,9 @@ const COOKIE_NAME = '_pubcid'; const TIMEOUT = 2000; describe('Publisher Common ID', function () { + afterEach(() => { + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidHook); + }); describe('Decorate adUnits', function () { before(function() { window.document.cookie = COOKIE_NAME + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 57c070e9748..e6364de94a9 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -11,6 +11,7 @@ import { config } from 'src/config'; import * as utils from 'src/utils'; +import { requestBidsHook } from 'modules/consentManagement'; // Default params with optional ones describe('Smart bid adapter tests', () => { @@ -99,49 +100,56 @@ describe('Smart bid adapter tests', () => { expect(requestContent).to.have.property('ckid').and.to.equal(42); }); - it('Verify build request with GDPR', () => { - config.setConfig({ - 'currency': { - 'adServerCurrency': 'EUR' - }, - consentManagement: { - cmp: 'iab', - consentRequired: true, - timeout: 1000, - allowAuctionWithoutConsent: true - } + describe('gdpr tests', () => { + afterEach(() => { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); }); - const request = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL, { - gdprConsent: { - consentString: 'BOKAVy4OKAVy4ABAB8AAAAAZ+A==', - gdprApplies: true - } - }); - const requestContent = JSON.parse(request[0].data); - expect(requestContent).to.have.property('gdpr').and.to.equal(true); - expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOKAVy4OKAVy4ABAB8AAAAAZ+A=='); - }); - it('Verify build request with GDPR without gdprApplies', () => { - config.setConfig({ - 'currency': { - 'adServerCurrency': 'EUR' - }, - consentManagement: { - cmp: 'iab', - consentRequired: true, - timeout: 1000, - allowAuctionWithoutConsent: true - } + it('Verify build request with GDPR', () => { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + }, + consentManagement: { + cmp: 'iab', + consentRequired: true, + timeout: 1000, + allowAuctionWithoutConsent: true + } + }); + const request = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL, { + gdprConsent: { + consentString: 'BOKAVy4OKAVy4ABAB8AAAAAZ+A==', + gdprApplies: true + } + }); + const requestContent = JSON.parse(request[0].data); + expect(requestContent).to.have.property('gdpr').and.to.equal(true); + expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOKAVy4OKAVy4ABAB8AAAAAZ+A=='); }); - const request = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL, { - gdprConsent: { - consentString: 'BOKAVy4OKAVy4ABAB8AAAAAZ+A==' - } + + it('Verify build request with GDPR without gdprApplies', () => { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + }, + consentManagement: { + cmp: 'iab', + consentRequired: true, + timeout: 1000, + allowAuctionWithoutConsent: true + } + }); + const request = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL, { + gdprConsent: { + consentString: 'BOKAVy4OKAVy4ABAB8AAAAAZ+A==' + } + }); + const requestContent = JSON.parse(request[0].data); + expect(requestContent).to.not.have.property('gdpr'); + expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOKAVy4OKAVy4ABAB8AAAAAZ+A=='); }); - const requestContent = JSON.parse(request[0].data); - expect(requestContent).to.not.have.property('gdpr'); - expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOKAVy4OKAVy4ABAB8AAAAAZ+A=='); }); it('Verify parse response', () => { From b90f12d79948c1720d0444c93e1c1828eb18ef80 Mon Sep 17 00:00:00 2001 From: Jeremy Hernandez Date: Wed, 20 Jun 2018 21:36:45 +0200 Subject: [PATCH 0484/1594] fix(AdyoulikeAdapter): set withCredentials option to true (#2661) --- modules/adyoulikeBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index a61719fe495..b9f57115e21 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -55,7 +55,7 @@ export const spec = { const data = JSON.stringify(payload); const options = { - withCredentials: false + withCredentials: true }; return { From 44fb86607209b6ba21ad96f4aa249893f1830aca Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 20 Jun 2018 16:17:32 -0400 Subject: [PATCH 0485/1594] update consentManagement error logic/handling (#2723) --- modules/consentManagement.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index af668523fa4..fcaeab81544 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -219,11 +219,17 @@ export function requestBidsHook(reqBidsConfigObj, fn) { * @param {object} hookConfig contains module related variables (see comment in requestBidsHook function) */ function processCmpData(consentObject, hookConfig) { + let gdprApplies = consentObject && consentObject.getConsentData && consentObject.getConsentData.gdprApplies; if ( - !utils.isPlainObject(consentObject) || - (!utils.isPlainObject(consentObject.getVendorConsents) || Object.keys(consentObject.getVendorConsents).length === 0) || - (!utils.isPlainObject(consentObject.getConsentData) || Object.keys(consentObject.getConsentData).length === 0)) { - cmpFailed(`CMP returned unexpected value during lookup process; returned value was (${consentObject}).`, hookConfig); + (typeof gdprApplies !== 'boolean') || + (gdprApplies === true && + !(utils.isStr(consentObject.getConsentData.consentData) && + utils.isPlainObject(consentObject.getVendorConsents) && + Object.keys(consentObject.getVendorConsents).length > 1 + ) + ) + ) { + cmpFailed(`CMP returned unexpected value during lookup process.`, hookConfig, consentObject); } else { clearTimeout(hookConfig.timer); storeConsentData(consentObject); @@ -243,15 +249,16 @@ function cmpTimedOut(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) { +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) { storeConsentData(undefined); } - exitModule(errMsg, hookConfig); + exitModule(errMsg, hookConfig, extraArgs); } /** @@ -282,8 +289,9 @@ function storeConsentData(cmpConsentObject) { * 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) { +function exitModule(errMsg, hookConfig, extraArgs) { if (hookConfig.haveExited === false) { hookConfig.haveExited = true; @@ -293,10 +301,10 @@ function exitModule(errMsg, hookConfig) { if (errMsg) { if (allowAuction) { - utils.logWarn(errMsg + ' Resuming auction without consent data as per consentManagement config.'); + utils.logWarn(errMsg + ' Resuming auction without consent data as per consentManagement config.', extraArgs); nextFn.apply(context, args); } else { - utils.logError(errMsg + ' Canceling auction as per consentManagement config.'); + utils.logError(errMsg + ' Canceling auction as per consentManagement config.', extraArgs); if (typeof hookConfig.bidsBackHandler === 'function') { hookConfig.bidsBackHandler(); } else { From f60e239366c629039c0340b7e723f4fa2fde6402 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 20 Jun 2018 16:20:37 -0400 Subject: [PATCH 0486/1594] enhance logWarn message (#2724) --- src/utils.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/utils.js b/src/utils.js index 5135a1df21d..09a52660796 100644 --- a/src/utils.js +++ b/src/utils.js @@ -14,8 +14,10 @@ var t_Numb = 'Number'; var t_Object = 'Object'; var toString = Object.prototype.toString; let infoLogger = null; +let warnLogger = null; try { infoLogger = console.info.bind(window.console); + warnLogger = console.warn.bind(window.console); } catch (e) { } @@ -257,9 +259,15 @@ exports.getTopWindowReferrer = function() { } }; -exports.logWarn = function (msg) { +exports.logWarn = function (msg, args) { if (debugTurnedOn() && console.warn) { - console.warn('WARNING: ' + msg); + if (warnLogger) { + if (!args || args.length === 0) { + args = ''; + } + + warnLogger('WARNING: ' + msg + ((args === '') ? '' : ' : params : '), args); + } } }; From 960ffddf6df7056035bc7ba77447b6448bbae20c Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 20 Jun 2018 14:29:49 -0600 Subject: [PATCH 0487/1594] Debugging (#2687) * new debugging functionality with bid overrides * update name from bidderOverrides to debugging * change sessionStorage to window.sessionStorage * solve sinon stubbing sessionStorage issue with dependency injection --- src/debugging.js | 89 ++++++++++++++++++++++ src/hook.js | 3 + src/prebid.js | 4 + test/spec/debugging_spec.js | 142 ++++++++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+) create mode 100644 src/debugging.js create mode 100644 test/spec/debugging_spec.js diff --git a/src/debugging.js b/src/debugging.js new file mode 100644 index 00000000000..fe5c269a18d --- /dev/null +++ b/src/debugging.js @@ -0,0 +1,89 @@ + +import { config } from 'src/config'; +import { logMessage as utilsLogMessage, logWarn as utilsLogWarn } from 'src/utils'; +import { addBidResponse } from 'src/auction'; + +const OVERRIDE_KEY = '$$PREBID_GLOBAL$$:debugging'; + +export let boundHook; + +function logMessage(msg) { + utilsLogMessage('DEBUG: ' + msg); +} + +function logWarn(msg) { + utilsLogWarn('DEBUG: ' + msg); +} + +function enableOverrides(overrides, fromSession = false) { + config.setConfig({'debug': true}); + logMessage(`bidder overrides enabled${fromSession ? ' from session' : ''}`); + + if (boundHook) { + addBidResponse.removeHook(boundHook); + } + + boundHook = addBidResponseHook.bind(null, overrides); + addBidResponse.addHook(boundHook, 5); +} + +export function disableOverrides() { + if (boundHook) { + addBidResponse.removeHook(boundHook); + logMessage('bidder overrides disabled'); + } +} + +export function addBidResponseHook(overrides, adUnitCode, bid, next) { + if (Array.isArray(overrides.bidders) && overrides.bidders.indexOf(bid.bidderCode) === -1) { + logWarn(`bidder '${bid.bidderCode}' excluded from auction by bidder overrides`); + return; + } + + if (Array.isArray(overrides.bids)) { + overrides.bids.forEach(overrideBid => { + if (overrideBid.bidder && overrideBid.bidder !== bid.bidderCode) { + return; + } + if (overrideBid.adUnitCode && overrideBid.adUnitCode !== adUnitCode) { + return; + } + + bid = Object.assign({}, bid); + + Object.keys(overrideBid).filter(key => ['bidder', 'adUnitCode'].indexOf(key) === -1).forEach((key) => { + let value = overrideBid[key]; + logMessage(`bidder overrides changed '${adUnitCode}/${bid.bidderCode}' bid.${key} from '${bid[key]}' to '${value}'`); + bid[key] = value; + }); + }); + } + + next(adUnitCode, bid); +} + +export function getConfig(debugging) { + if (!debugging.enabled) { + disableOverrides(); + try { + window.sessionStorage.removeItem(OVERRIDE_KEY); + } catch (e) {} + } else { + try { + window.sessionStorage.setItem(OVERRIDE_KEY, JSON.stringify(debugging)); + } catch (e) {} + enableOverrides(debugging); + } +} +config.getConfig('debugging', ({debugging}) => getConfig(debugging)); + +export function sessionLoader(storage = window.sessionStorage) { + let overrides; + try { + overrides = JSON.parse(storage.getItem(OVERRIDE_KEY)); + } catch (e) { + } + if (overrides) { + enableOverrides(overrides, true); + } +} diff --git a/src/hook.js b/src/hook.js index 6c6cefdc56c..fef62a37c3d 100644 --- a/src/hook.js +++ b/src/hook.js @@ -60,6 +60,9 @@ export function createHook(type, fn, hookName) { }, removeHook: function(removeFn) { _hooks = _hooks.filter(hook => hook.fn === fn || hook.fn !== removeFn); + }, + hasHook: function(fn) { + return _hooks.some(hook => hook.fn === fn); } }; diff --git a/src/prebid.js b/src/prebid.js index e1691c20f79..56c9d1d0c7c 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -9,6 +9,7 @@ import { config } from './config'; import { auctionManager } from './auctionManager'; import { targeting, getHighestCpmBidsFromBidPool, RENDERED, BID_TARGETING_SET } from './targeting'; import { createHook } from 'src/hook'; +import { sessionLoader } from 'src/debugging'; import includes from 'core-js/library/fn/array/includes'; const $$PREBID_GLOBAL$$ = getGlobal(); @@ -27,6 +28,9 @@ const eventValidators = { bidWon: checkDefinedPlacement }; +// initialize existing debugging sessions if present +sessionLoader(); + /* Public vars */ $$PREBID_GLOBAL$$.bidderSettings = $$PREBID_GLOBAL$$.bidderSettings || {}; diff --git a/test/spec/debugging_spec.js b/test/spec/debugging_spec.js new file mode 100644 index 00000000000..286df26f7ba --- /dev/null +++ b/test/spec/debugging_spec.js @@ -0,0 +1,142 @@ + +import { expect } from 'chai'; +import { sessionLoader, addBidResponseHook, getConfig, disableOverrides, boundHook } from 'src/debugging'; +import { addBidResponse } from 'src/auction'; +import { config } from 'src/config'; + +describe('bid overrides', () => { + let sandbox; + + beforeEach(() => { + sandbox = sinon.sandbox.create(); + }); + + afterEach(() => { + window.sessionStorage.clear(); + sandbox.restore(); + }); + + describe('initialization', () => { + beforeEach(() => { + sandbox.stub(config, 'setConfig'); + }); + + afterEach(() => { + disableOverrides(); + }); + + it('should happen when enabled with setConfig', () => { + getConfig({ + enabled: true + }); + + expect(addBidResponse.hasHook(boundHook)).to.equal(true); + }); + + it('should happen when configuration found in sessionStorage', () => { + sessionLoader({ + getItem: () => ('{"enabled": true}') + }); + expect(addBidResponse.hasHook(boundHook)).to.equal(true); + }); + + it('should not throw if sessionStorage is inaccessible', () => { + expect(() => { + sessionLoader({ + getItem() { + throw new Error('test'); + } + }); + }).not.to.throw(); + }); + }); + + describe('hook', () => { + let mockBids; + let bids; + + beforeEach(() => { + let baseBid = { + 'bidderCode': 'rubicon', + 'width': 970, + 'height': 250, + 'statusMessage': 'Bid available', + 'mediaType': 'banner', + 'source': 'client', + 'currency': 'USD', + 'cpm': 0.5, + 'ttl': 300, + 'netRevenue': false, + 'adUnitCode': '/19968336/header-bid-tag-0' + }; + mockBids = []; + mockBids.push(baseBid); + mockBids.push(Object.assign({}, baseBid, { + bidderCode: 'appnexus' + })); + + bids = []; + }); + + function run(overrides) { + mockBids.forEach(bid => { + addBidResponseHook(overrides, bid.adUnitCode, bid, (adUnitCode, bid) => { + bids.push(bid); + }) + }); + } + + it('should allow us to exclude bidders', () => { + run({ + enabled: true, + bidders: ['appnexus'] + }); + + expect(bids.length).to.equal(1); + expect(bids[0].bidderCode).to.equal('appnexus'); + }); + + it('should allow us to override all bids', () => { + run({ + enabled: true, + bids: [{ + cpm: 2 + }] + }); + + expect(bids.length).to.equal(2); + expect(bids[0].cpm).to.equal(2); + expect(bids[1].cpm).to.equal(2); + }); + + it('should allow us to override bids by bidder', () => { + run({ + enabled: true, + bids: [{ + bidder: 'rubicon', + cpm: 2 + }] + }); + + expect(bids.length).to.equal(2); + expect(bids[0].cpm).to.equal(2); + expect(bids[1].cpm).to.equal(0.5); + }); + + it('should allow us to override bids by adUnitCode', () => { + mockBids[1].adUnitCode = 'test'; + + run({ + enabled: true, + bids: [{ + adUnitCode: 'test', + cpm: 2 + }] + }); + + expect(bids.length).to.equal(2); + expect(bids[0].cpm).to.equal(0.5); + expect(bids[1].cpm).to.equal(2); + }); + }); +}); From 8873b21569ea562177f4ba214908f2c423e5ac28 Mon Sep 17 00:00:00 2001 From: AdmixerTech <35560933+AdmixerTech@users.noreply.github.com> Date: Wed, 20 Jun 2018 23:58:39 +0300 Subject: [PATCH 0488/1594] add encodeURIComponent (#2660) --- modules/admixerBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/admixerBidAdapter.js b/modules/admixerBidAdapter.js index 6851a7d3bd5..679e11270ab 100644 --- a/modules/admixerBidAdapter.js +++ b/modules/admixerBidAdapter.js @@ -25,7 +25,7 @@ export const spec = { buildRequests: function (bidderRequest) { const payload = { imps: [], - referrer: utils.getTopWindowUrl(), + referrer: encodeURIComponent(utils.getTopWindowUrl()), }; bidderRequest.forEach((bid) => { if (bid.bidder === BIDDER_CODE) { From 4daab3d229e4268a062f4e3919d5f639642c1933 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 20 Jun 2018 17:06:29 -0400 Subject: [PATCH 0489/1594] Function name was not logical (#2751) --- src/targeting.js | 4 ++-- test/spec/unit/core/targeting_spec.js | 10 +++++----- test/spec/unit/pbjs_api_spec.js | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index e33f1a88f10..d645a8ed20d 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -16,7 +16,7 @@ const MAX_DFP_KEYLENGTH = 20; const TTL_BUFFER = 1000; // return unexpired bids -export const isBidExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 + TTL_BUFFER) > timestamp(); +export const isBidNotExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 + TTL_BUFFER) > timestamp(); // return bids whose status is not set. Winning bid can have status `targetingSet` or `rendered`. const isUnusedBid = (bid) => bid && ((bid.status && !includes([BID_TARGETING_SET, RENDERED], bid.status)) || !bid.status); @@ -195,7 +195,7 @@ export function newTargeting(auctionManager) { function getBidsReceived() { const bidsReceived = auctionManager.getBidsReceived() .filter(isUnusedBid) - .filter(exports.isBidExpired) + .filter(exports.isBidNotExpired) ; return getHighestCpmBidsFromBidPool(bidsReceived, getOldestHighestCpmBid); diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index cf08c65d1fb..0ba5e23159f 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -111,13 +111,13 @@ describe('targeting tests', () => { amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; }); - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').returns(true); + bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); }); afterEach(() => { auctionManager.getBidsReceived.restore(); auctionManager.getAdUnitCodes.restore(); - targetingModule.isBidExpired.restore(); + targetingModule.isBidNotExpired.restore(); }); it('selects the top bid when _sendAllBids true', () => { @@ -149,13 +149,13 @@ describe('targeting tests', () => { amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; }); - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').returns(true); + bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); }); afterEach(() => { auctionManager.getBidsReceived.restore(); auctionManager.getAdUnitCodes.restore(); - targetingModule.isBidExpired.restore(); + targetingModule.isBidNotExpired.restore(); }); it('returns targetingSet correctly', () => { @@ -171,7 +171,7 @@ describe('targeting tests', () => { let bidExpiryStub; let auctionManagerStub; beforeEach(() => { - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').returns(true); + bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 93904dcfaf8..ab5da55f420 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -150,12 +150,12 @@ window.apntag = { describe('Unit: Prebid Module', function () { let bidExpiryStub; before(() => { - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').callsFake(() => true); + bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').callsFake(() => true); }); after(function() { $$PREBID_GLOBAL$$.adUnits = []; - targetingModule.isBidExpired.restore(); + targetingModule.isBidNotExpired.restore(); }); describe('getAdserverTargetingForAdUnitCodeStr', function () { From 050494e0cb3a7310c690651e2348e9f747fdcbbf Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 20 Jun 2018 15:06:41 -0600 Subject: [PATCH 0490/1594] Max origin concurrent auctions (#2743) * initial attempt at limiting concurrenet auctions by origin * fix queueing of auctions for max origin * don't decrement on timeout as it is already called by onreadystatechange * move auction timer so it doesn't start until queued auction starts * set default max concurrent origin requests to 4 and make configurable * fix tests to not queue for auction.callBids * change MAX_REQUEST_PER_ORIGIN to local var --- src/adaptermanager.js | 12 +++- src/ajax.js | 84 ++++++++++---------------- src/auction.js | 104 ++++++++++++++++++++++++++++---- test/spec/unit/pbjs_api_spec.js | 1 + 4 files changed, 136 insertions(+), 65 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index f6c0d5c421e..3d5d56d6ee2 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -273,7 +273,7 @@ exports.checkBidRequestSizes = (adUnits) => { return adUnits; } -exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { +exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbacks) => { if (!bidRequests.length) { utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); return; @@ -285,7 +285,10 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { }, [[], []]); if (serverBidRequests.length) { - const s2sAjax = ajaxBuilder(serverBidRequests[0].timeout); + const s2sAjax = ajaxBuilder(serverBidRequests[0].timeout, requestCallbacks ? { + request: requestCallbacks.request.bind(null, 's2s'), + done: requestCallbacks.done + } : undefined); let adaptersServerSide = _s2sConfig.bidders; const s2sAdapter = _bidderRegistry[_s2sConfig.adapter]; let tid = serverBidRequests[0].tid; @@ -336,7 +339,6 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { } } - const ajax = (clientBidRequests.length) ? ajaxBuilder(clientBidRequests[0].timeout) : null; // handle client adapter requests clientBidRequests.forEach(bidRequest => { bidRequest.start = timestamp(); @@ -347,6 +349,10 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); bidRequest.doneCbCallCount = 0; let done = doneCb(bidRequest.bidderRequestId); + let ajax = ajaxBuilder(clientBidRequests[0].timeout, requestCallbacks ? { + request: requestCallbacks.request.bind(null, bidRequest.bidderCode), + done: requestCallbacks.done + } : undefined); adapter.callBids(bidRequest, addBidResponse, done, ajax); } else { utils.logError(`Adapter trying to be called which does not exist: ${bidRequest.bidderCode} adaptermanager.callBids`); diff --git a/src/ajax.js b/src/ajax.js index ded2f95f8a5..e17f782ac30 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -15,12 +15,13 @@ const XHR_DONE = 4; */ export const ajax = ajaxBuilder(); -export function ajaxBuilder(timeout = 3000) { +export function ajaxBuilder(timeout = 3000, {request, done} = {}) { return function(url, callback, data, options = {}) { try { let x; - let useXDomainRequest = false; let method = options.method || (data ? 'POST' : 'GET'); + let parser = document.createElement('a'); + parser.href = url; let callbacks = typeof callback === 'object' && callback !== null ? callback : { success: function() { @@ -35,46 +36,24 @@ export function ajaxBuilder(timeout = 3000) { callbacks.success = callback; } - if (!window.XMLHttpRequest) { - useXDomainRequest = true; - } else { - x = new window.XMLHttpRequest(); - if (x.responseType === undefined) { - useXDomainRequest = true; - } - } - - if (useXDomainRequest) { - x = new window.XDomainRequest(); - x.onload = function () { - callbacks.success(x.responseText, x); - }; + x = new window.XMLHttpRequest(); - // http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 - x.onerror = function () { - callbacks.error('error', x); - }; - x.ontimeout = function () { - callbacks.error('timeout', x); - }; - x.onprogress = function() { - utils.logMessage('xhr onprogress'); - }; - } else { - x.onreadystatechange = function () { - if (x.readyState === XHR_DONE) { - let status = x.status; - if ((status >= 200 && status < 300) || status === 304) { - callbacks.success(x.responseText, x); - } else { - callbacks.error(x.statusText, x); - } + x.onreadystatechange = function () { + if (x.readyState === XHR_DONE) { + if (typeof done === 'function') { + done(parser.origin); } - }; - x.ontimeout = function () { - utils.logError(' xhr timeout after ', x.timeout, 'ms'); - }; - } + let status = x.status; + if ((status >= 200 && status < 300) || status === 304) { + callbacks.success(x.responseText, x); + } else { + callbacks.error(x.statusText, x); + } + } + }; + x.ontimeout = function () { + utils.logError(' xhr timeout after ', x.timeout, 'ms'); + }; if (method === 'GET' && data) { let urlInfo = parseURL(url, options); @@ -86,18 +65,21 @@ export function ajaxBuilder(timeout = 3000) { // IE needs timoeut to be set after open - see #1410 x.timeout = timeout; - if (!useXDomainRequest) { - if (options.withCredentials) { - x.withCredentials = true; - } - utils._each(options.customHeaders, (value, header) => { - x.setRequestHeader(header, value); - }); - if (options.preflight) { - x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - } - x.setRequestHeader('Content-Type', options.contentType || 'text/plain'); + if (options.withCredentials) { + x.withCredentials = true; } + utils._each(options.customHeaders, (value, header) => { + x.setRequestHeader(header, value); + }); + if (options.preflight) { + x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + } + x.setRequestHeader('Content-Type', options.contentType || 'text/plain'); + + if (typeof request === 'function') { + request(parser.origin); + } + if (method === 'POST' && data) { x.send(data); } else { diff --git a/src/auction.js b/src/auction.js index 8992f16218e..5722bcc6990 100644 --- a/src/auction.js +++ b/src/auction.js @@ -74,6 +74,11 @@ events.on(CONSTANTS.EVENTS.BID_ADJUSTMENT, function (bid) { adjustBids(bid); }); +const MAX_REQUESTS_PER_ORIGIN = 4; +const outstandingRequests = {}; +const sourceInfo = {}; +const queuedCalls = []; + /** * Creates new auction instance * @@ -176,26 +181,103 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } function callBids() { - startAuctionTimer(); _auctionStatus = AUCTION_STARTED; _auctionStart = Date.now(); - const auctionInit = { - timestamp: _auctionStart, - auctionId: _auctionId, - timeout: _timeout - }; - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); - let bidRequests = adaptermanager.makeBidRequests(_adUnits, _auctionStart, _auctionId, _timeout, _labels); utils.logInfo(`Bids Requested for Auction with id: ${_auctionId}`, bidRequests); bidRequests.forEach(bidRequest => { addBidRequests(bidRequest); }); - _auctionStatus = AUCTION_IN_PROGRESS; - adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(this), done.bind(this)); - }; + let requests = {}; + + let call = { + bidRequests, + run: () => { + startAuctionTimer(); + + _auctionStatus = AUCTION_IN_PROGRESS; + + const auctionInit = { + timestamp: _auctionStart, + auctionId: _auctionId, + timeout: _timeout + }; + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); + + adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(this), done.bind(this), { + request(source, origin) { + increment(outstandingRequests, origin); + increment(requests, source); + + if (!sourceInfo[source]) { + sourceInfo[source] = { + SRA: true, + origin + }; + } + if (requests[source] > 1) { + sourceInfo[source].SRA = false; + } + }, + done(origin) { + outstandingRequests[origin]--; + if (queuedCalls[0]) { + if (runIfOriginHasCapacity(queuedCalls[0])) { + queuedCalls.shift(); + } + } + } + }); + } + }; + + if (!runIfOriginHasCapacity(call)) { + utils.logWarn('queueing auction due to limited endpoint capacity'); + queuedCalls.push(call); + } + + function runIfOriginHasCapacity(call) { + let hasCapacity = true; + + let maxRequests = config.getConfig('maxRequestsPerOrigin') || MAX_REQUESTS_PER_ORIGIN; + + call.bidRequests.some(bidRequest => { + let requests = 1; + let source = (typeof bidRequest.src !== 'undefined' && bidRequest.src === CONSTANTS.S2S.SRC) ? 's2s' + : bidRequest.bidderCode; + // if we have no previous info on this source just let them through + if (sourceInfo[source]) { + if (sourceInfo[source].SRA === false) { + // some bidders might use more than the MAX_REQUESTS_PER_ORIGIN in a single auction. In those cases + // set their request count to MAX_REQUESTS_PER_ORIGIN so the auction isn't permanently queued waiting + // for capacity for that bidder + requests = Math.min(bidRequest.bids.length, maxRequests); + } + if (outstandingRequests[sourceInfo[source].origin] + requests > maxRequests) { + hasCapacity = false; + } + } + // return only used for terminating this .some() iteration early if it is determined we don't have capacity + return !hasCapacity; + }); + + if (hasCapacity) { + call.run(); + } + + return hasCapacity; + } + + function increment(obj, prop) { + if (typeof obj[prop] === 'undefined') { + obj[prop] = 1 + } else { + obj[prop]++; + } + } + } return { addBidReceived, diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index ab5da55f420..3156ea671f7 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1305,6 +1305,7 @@ describe('Unit: Prebid Module', function () { ] }]; adUnitCodes = ['adUnit-code']; + configObj.setConfig({maxRequestsPerOrigin: Number.MAX_SAFE_INTEGER || 99999999}); let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); spyCallBids = sinon.spy(adaptermanager, 'callBids'); createAuctionStub = sinon.stub(auctionModule, 'newAuction'); From 80368385479e15a38d11df01741a54ee036a83eb Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 20 Jun 2018 17:07:00 -0400 Subject: [PATCH 0491/1594] allow s2s bidders call pbs without need of a client adapter file (#2704) * allow s2s adapters call pbs without client adapter file * add support in aliasBidAdapter for s2s-only bidders --- modules/prebidServerBidAdapter.js | 13 ++++++-- src/adaptermanager.js | 14 ++++++-- src/constants.json | 1 + src/prebid.js | 8 ++++- .../modules/prebidServerBidAdapter_spec.js | 4 +-- test/spec/unit/core/adapterManager_spec.js | 33 ++++++++++++++++++- 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 6533d9d00ee..c217b2934ed 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -589,7 +589,7 @@ const OPEN_RTB_PROTOCOL = { response.seatbid.forEach(seatbid => { (seatbid.bid || []).forEach(bid => { const bidRequest = utils.getBidRequest( - this.bidMap[`${bid.impid}${seatbid.seat}`], + this.bidMap[`${bid.impid}${seatbid.seat}`].bid_id, bidderRequests ); @@ -704,11 +704,12 @@ export function PrebidServer() { /* Notify Prebid of bid responses so bids can get in the auction */ function handleResponse(response, requestedBidders, bidderRequests, addBidResponse, done) { let result; + let bids = []; try { result = JSON.parse(response); - const bids = protocolAdapter().interpretResponse( + bids = protocolAdapter().interpretResponse( result, bidderRequests, requestedBidders @@ -734,7 +735,13 @@ export function PrebidServer() { utils.logError('error parsing response: ', result.status); } - done(); + const videoBid = bids.some(bidResponse => bidResponse.bid.mediaType === 'video'); + const cacheEnabled = config.getConfig('cache.url'); + + // video bids with cache enabled need to be cached first before they are considered done + if (!(videoBid && cacheEnabled)) { + done(); + } doClientSideSyncs(requestedBidders); } diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 3d5d56d6ee2..4c60b01d8fa 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -393,12 +393,20 @@ exports.registerBidAdapter = function (bidAdaptor, bidderCode, {supportedMediaTy }; exports.aliasBidAdapter = function (bidderCode, alias) { - var existingAlias = _bidderRegistry[alias]; + let existingAlias = _bidderRegistry[alias]; if (typeof existingAlias === 'undefined') { - var bidAdaptor = _bidderRegistry[bidderCode]; + let bidAdaptor = _bidderRegistry[bidderCode]; if (typeof bidAdaptor === 'undefined') { - utils.logError('bidderCode "' + bidderCode + '" is not an existing bidder.', 'adaptermanager.aliasBidAdapter'); + // check if alias is part of s2sConfig and allow them to register if so (as base bidder may be s2s-only) + const s2sConfig = config.getConfig('s2sConfig'); + const s2sBidders = s2sConfig && s2sConfig.bidders; + + if (!(s2sBidders && includes(s2sBidders, alias))) { + utils.logError('bidderCode "' + bidderCode + '" is not an existing bidder.', 'adaptermanager.aliasBidAdapter'); + } else { + exports.aliasRegistry[alias] = bidderCode; + } } else { try { let newAdapter; diff --git a/src/constants.json b/src/constants.json index c8a7c3ebefc..3bbad70585a 100644 --- a/src/constants.json +++ b/src/constants.json @@ -66,6 +66,7 @@ ], "S2S" : { "SRC" : "s2s", + "DEFAULT_ENDPOINT" : "https://prebid.adnxs.com/pbs/v1/openrtb2/auction", "SYNCED_BIDDERS_KEY": "pbjsSyncs" } } diff --git a/src/prebid.js b/src/prebid.js index 56c9d1d0c7c..767180f3286 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -340,9 +340,15 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa const adUnitMediaTypes = Object.keys(adUnit.mediaTypes || {'banner': 'banner'}); // get the bidder's mediaTypes - const bidders = adUnit.bids.map(bid => bid.bidder); + const allBidders = adUnit.bids.map(bid => bid.bidder); const bidderRegistry = adaptermanager.bidderRegistry; + const s2sConfig = config.getConfig('s2sConfig'); + const s2sBidders = s2sConfig && s2sConfig.bidders; + const bidders = (s2sBidders) ? allBidders.filter(bidder => { + return !includes(s2sBidders, bidder); + }) : allBidders; + if (!adUnit.transactionId) { adUnit.transactionId = utils.generateUUID(); } diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 8bc3d577ede..cd2022bcab7 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -246,7 +246,7 @@ const RESPONSE_OPENRTB = { 'bid': [ { 'id': '8750901685062148', - 'impid': '123', + 'impid': 'div-gpt-ad-1460505748561-0', 'price': 0.5, 'adm': '', 'adid': '29681110', @@ -285,7 +285,7 @@ const RESPONSE_OPENRTB_VIDEO = { bid: [ { id: '1987250005171537465', - impid: '/19968336/header-bid-tag-0', + impid: 'div-gpt-ad-1460505748561-0', price: 10, adm: 'adnxs', adid: '81877115', diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index df03af5f354..0e33fc005d5 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -19,7 +19,8 @@ const CONFIG = { timeout: 1000, maxBids: 1, adapter: 'prebidServer', - bidders: ['appnexus'] + bidders: ['appnexus'], + accountId: 'abc' }; var prebidServerAdapterMock = { bidder: 'prebidServer', @@ -719,6 +720,36 @@ describe('adapterManager tests', () => { expect(AdapterManager.videoAdapters).to.include(alias); }); }); + + describe('special case for s2s-only bidders', () => { + beforeEach(() => { + sinon.stub(utils, 'logError'); + }); + + afterEach(() => { + config.resetConfig(); + utils.logError.restore(); + }); + + it('should allow an alias if alias is part of s2sConfig.bidders', () => { + let testS2sConfig = utils.deepClone(CONFIG); + testS2sConfig.bidders = ['s2sAlias']; + config.setConfig({s2sConfig: testS2sConfig}); + + AdapterManager.aliasBidAdapter('s2sBidder', 's2sAlias'); + expect(AdapterManager.aliasRegistry).to.have.property('s2sAlias'); + }); + + it('should throw an error if alias + bidder are unknown and not part of s2sConfig.bidders', () => { + let testS2sConfig = utils.deepClone(CONFIG); + testS2sConfig.bidders = ['s2sAlias']; + config.setConfig({s2sConfig: testS2sConfig}); + + AdapterManager.aliasBidAdapter('s2sBidder1', 's2sAlias1'); + sinon.assert.calledOnce(utils.logError); + expect(AdapterManager.aliasRegistry).to.not.have.property('s2sAlias1'); + }); + }); }); describe('makeBidRequests', () => { From 64f8e01e88358810bafe55b70a04fa6de3fa5372 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 20 Jun 2018 17:20:51 -0400 Subject: [PATCH 0492/1594] Prebid 1.15.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f2628096af7..d107cdd66a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.15.0-pre", + "version": "1.15.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 0dda32f4fa633109c1fb75e62bf9c240d5a71930 Mon Sep 17 00:00:00 2001 From: Igor Soarez Date: Thu, 21 Jun 2018 00:54:19 +0100 Subject: [PATCH 0493/1594] Add GDPR support for Quantcast adapter (#2733) * Add GDPR support for Quantcast adapter * Fix lint error --- modules/quantcastBidAdapter.js | 9 +++++++-- modules/quantcastBidAdapter.md | 4 ++-- test/spec/modules/quantcastBidAdapter_spec.js | 11 ++++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index f10fd48502f..3639a5a6bb7 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -41,9 +41,10 @@ export const spec = { * `BidRequests`. * * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be send to Quantcast server + * @param bidderRequest * @return ServerRequest information describing the request to the server. */ - buildRequests(bidRequests) { + buildRequests(bidRequests, bidderRequest) { const bids = bidRequests || []; const referrer = utils.getTopWindowUrl(); @@ -75,6 +76,8 @@ export const spec = { }); }); + const gdprConsent = bidderRequest ? bidderRequest.gdprConsent : {}; + // Request Data Format can be found at https://wiki.corp.qc/display/adinf/QCX const requestData = { publisherId: bid.params.publisherId, @@ -94,7 +97,9 @@ export const spec = { referrer, domain }, - bidId: bid.bidId + bidId: bid.bidId, + gdprSignal: gdprConsent.gdprApplies ? 1 : 0, + gdprConsent: gdprConsent.consentString }; const data = JSON.stringify(requestData); diff --git a/modules/quantcastBidAdapter.md b/modules/quantcastBidAdapter.md index 20cf25bffbf..efc21466c75 100644 --- a/modules/quantcastBidAdapter.md +++ b/modules/quantcastBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Quantcast Bidder Adapter Module Type: Bidder Adapter -Maintainer: xli@quantcast.com +Maintainer: igor.soarez@quantcast.com ``` # Description @@ -28,4 +28,4 @@ const adUnits = [{ } ] }]; -``` \ No newline at end of file +``` diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 6fd5c3abdf9..f6e2924515c 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -129,13 +129,22 @@ describe('Quantcast adapter', () => { referrer, domain }, - bidId: '2f7b179d443f14' + bidId: '2f7b179d443f14', + gdprSignal: 0 }; expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); }); }); + it('propagates GDPR consent string and signal', () => { + const gdprConsent = { gdprApplies: true, consentString: 'consentString' } + const requests = qcSpec.buildRequests([bidRequest], { gdprConsent }); + const parsed = JSON.parse(requests[0].data) + expect(parsed.gdprSignal).to.equal(1); + expect(parsed.gdprConsent).to.equal(gdprConsent.consentString); + }); + describe('`interpretResponse`', () => { // The sample response is from https://wiki.corp.qc/display/adinf/QCX const body = { From ae287c38373dbb7ff0d52aadc02bf08a1d1446cd Mon Sep 17 00:00:00 2001 From: Jesse Date: Wed, 20 Jun 2018 16:56:12 -0700 Subject: [PATCH 0494/1594] ixBidAdapter.js: allow siteId param to be number (#2729) * ixBidAdapter.js: allow siteId param to be number In v0.x, the siteID param would be string or number. Somehow, this was restricted to just a string in v1.x. * ixBidAdapter.js logical error (not enough coffee) * ixBidAdapter_spec.js: allow number for backwards compat --- modules/ixBidAdapter.js | 2 +- test/spec/modules/ixBidAdapter_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index f3ac8185f17..89506a5659b 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -153,7 +153,7 @@ export const spec = { return false; } - if (typeof bid.params.siteId !== 'string') { + if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') { return false; } diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 92a7190bcb6..36b2b0e9629 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -77,10 +77,10 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when siteID is number', () => { + it('should return true when siteID is number', () => { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.siteId = 123; - expect(spec.isBidRequestValid(bid)).to.equal(false); + expect(spec.isBidRequestValid(bid)).to.equal(true); }); it('should return false when siteID is missing', () => { From 341866517ed874978e1553cc94c08607377049a5 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Thu, 21 Jun 2018 00:57:08 +0100 Subject: [PATCH 0495/1594] Audience Network: add debug params to bid requests (#2657) Remove deprecated pbv param --- modules/audienceNetworkBidAdapter.js | 8 ++++++-- test/spec/modules/audienceNetworkBidAdapter_spec.js | 10 +++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 612357e0e4a..7256ce99e73 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -15,7 +15,9 @@ const url = 'https://an.facebook.com/v2/placementbid.json'; const supportedMediaTypes = ['banner', 'video']; const netRevenue = true; const hb_bidder = 'fan'; -const pbv = '$prebid.version$'; +const platver = '$prebid.version$'; +const platform = '241394079772386'; +const adapterver = '1.0.0'; /** * Does this bid request contain valid parameters? @@ -166,7 +168,9 @@ const buildRequests = bids => { testmode, pageurl, sdk, - pbv + adapterver, + platform, + platver }; const video = findIndex(adformats, isVideo); if (video !== -1) { diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index 2b4f87450e8..c61cd04c422 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -19,7 +19,7 @@ const placementId = 'test-placement-id'; const playerwidth = 320; const playerheight = 180; const requestId = 'test-request-id'; -const pbv = '$prebid.version$'; +const debug = 'adapterver=1.0.0&platform=241394079772386&platver=$prebid.version$'; const pageUrl = encodeURIComponent(utils.getTopWindowUrl()); describe('AudienceNetwork adapter', () => { @@ -140,7 +140,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debug}` }]); }); @@ -159,7 +159,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['640x480'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=${pageUrl}&sdk[]=&pbv=${pbv}&playerwidth=640&playerheight=480` + data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=${pageUrl}&sdk[]=&${debug}&playerwidth=640&playerheight=480` }]); }); @@ -178,7 +178,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['728x90'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debug}` }]); }); @@ -197,7 +197,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debug}` }]); }); From 9fc70451401f87c9951adfb1c5bed8b78298d3cb Mon Sep 17 00:00:00 2001 From: Pascal S Date: Thu, 21 Jun 2018 15:11:15 +0200 Subject: [PATCH 0496/1594] Update CONTRIBUTING.md (#2757) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dc8d80ec384..7f4127cf3ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,7 +55,7 @@ When you are adding code to Prebid.js, or modifying code that isn't covered by a Prebid.js already has many tests. Read them to see how Prebid.js is tested, and for inspiration: - Look in `test/spec` and its subdirectories -- Tests for bidder adaptors are located in `test/spec/adapters` +- Tests for bidder adaptors are located in `test/spec/modules` A test module might have the following general structure: From 2507f4bceb548473959c0883307758b039a37352 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Thu, 21 Jun 2018 11:06:19 -0400 Subject: [PATCH 0497/1594] Increment Pre Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d107cdd66a3..1223fc5f6ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.15.0", + "version": "1.16.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3868077184afa49100924646fee8d535e648ebdd Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 21 Jun 2018 11:10:46 -0400 Subject: [PATCH 0498/1594] Temporarily remove ios browsers from browserstack testing (#2759) * update ios browsers * removing ios browsers --- browsers.json | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/browsers.json b/browsers.json index cb523addc7e..703bf44d41d 100644 --- a/browsers.json +++ b/browsers.json @@ -62,21 +62,5 @@ "browser_version": "8.0", "device": null, "os": "OS X" - }, - "bs_ios_9": { - "base": "BrowserStack", - "os": "ios", - "os_version": "9.1", - "browser": "iphone", - "device": "iPhone 6S", - "browser_version": null - }, - "bs_ios_8": { - "base": "BrowserStack", - "os": "ios", - "os_version": "8.3", - "browser": "iphone", - "device": "iPhone 6", - "browser_version": null } } \ No newline at end of file From d30de3275b657dc1cfd5a30dcc55100c520a9546 Mon Sep 17 00:00:00 2001 From: bretg Date: Thu, 21 Jun 2018 11:57:27 -0400 Subject: [PATCH 0499/1594] Rubicon adapter: add support for new size (#2760) --- modules/rubiconBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 5f4250352a5..e75c8df083a 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -71,7 +71,8 @@ var sizeMap = { 199: '640x200', 213: '1030x590', 214: '980x360', - 232: '580x400' + 232: '580x400', + 257: '400x600' }; utils._each(sizeMap, (item, key) => sizeMap[item] = key); From 0c25ef60b665a2667736d79cb8d7081affbacd96 Mon Sep 17 00:00:00 2001 From: bretg Date: Thu, 21 Jun 2018 15:31:39 -0400 Subject: [PATCH 0500/1594] Update RELEASE_SCHEDULE.md (#2749) --- RELEASE_SCHEDULE.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index efdc45f7f9f..4f5c7fc4e9a 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -91,6 +91,21 @@ Announcements regarding releases will be made to the #headerbidding-dev channel git push ``` +## Beta Releases + +Prebid.js features may be released as Beta or as Generally Available (GA). + +Characteristics of a `Beta` release: +- May be a partial implementation (e.g. more work needed to flesh out the feature) +- May not be fully tested with other features +- Limited documentation, focused on technical aspects +- Few users + +Characteristics of a `GA` release: +- Complete set of functionality +- Significant user base with no major issues for at least a month +- Decent documentation that includes business need, use cases, and examples + ## FAQs From 7e53e83af643cb06d1dac6d2c5eb08cf322eea69 Mon Sep 17 00:00:00 2001 From: devweborama <39480777+devweborama@users.noreply.github.com> Date: Thu, 21 Jun 2018 23:51:12 +0300 Subject: [PATCH 0501/1594] Added Weborama bid adapter (#2710) --- integrationExamples/gpt/pbjs_example_gpt.html | 7 ++ modules/weboramaBidAdapter.js | 117 +++++++++++++++++ modules/weboramaBidAdapter.md | 27 ++++ test/spec/modules/weboramaBidAdapter_spec.js | 118 ++++++++++++++++++ 4 files changed, 269 insertions(+) create mode 100644 modules/weboramaBidAdapter.js create mode 100644 modules/weboramaBidAdapter.md create mode 100644 test/spec/modules/weboramaBidAdapter_spec.js diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index f1ec912fd26..e54a604e281 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -269,6 +269,13 @@ placement_id: 0 } }, + { + bidder: 'weborama', + params: { + placementId: 0, + traffic: 'banner' + } + }, { bidder: 'pollux', params: { diff --git a/modules/weboramaBidAdapter.js b/modules/weboramaBidAdapter.js new file mode 100644 index 00000000000..2fe6f30b361 --- /dev/null +++ b/modules/weboramaBidAdapter.js @@ -0,0 +1,117 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'weborama'; +const URL = '//supply.nl.weborama.fr/?c=o&m=multi'; +const URL_SYNC = '//supply.nl.weborama.fr/?c=o&m=cookie'; + +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); + default: + return false; + } +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + + /** + * 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: (bid) => { + return Boolean(bid.bidId && + bid.params && + !isNaN(bid.params.placementId) && + spec.supportedMediaTypes.indexOf(bid.params.traffic) !== -1 + ); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: (validBidRequests) => { + let winTop; + try { + winTop = utils.getWindowTop(); + winTop.location.toString(); + } catch (e) { + utils.logMessage(e); + winTop = window; + }; + + const location = utils.getTopWindowLocation(); + const placements = []; + const request = { + 'secure': (location.protocol === 'https:') ? 1 : 0, + 'deviceWidth': winTop.screen.width, + 'deviceHeight': winTop.screen.height, + 'host': location.host, + 'page': location.pathname, + 'placements': placements + }; + + for (let i = 0; i < validBidRequests.length; i++) { + const bid = validBidRequests[i]; + const params = bid.params; + placements.push({ + placementId: params.placementId, + bidId: bid.bidId, + sizes: bid.sizes, + traffic: params.traffic + }); + } + return { + method: 'POST', + url: URL, + data: request + }; + }, + + /** + * 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: (serverResponse) => { + let response = []; + try { + serverResponse = serverResponse.body; + for (let i = 0; i < serverResponse.length; i++) { + let resItem = serverResponse[i]; + if (isBidResponseValid(resItem)) { + response.push(resItem); + } + } + } catch (e) { + utils.logMessage(e); + }; + return response; + }, + + getUserSyncs: () => { + return [{ + type: 'image', + url: URL_SYNC + }]; + } +}; + +registerBidder(spec); 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/test/spec/modules/weboramaBidAdapter_spec.js b/test/spec/modules/weboramaBidAdapter_spec.js new file mode 100644 index 00000000000..ef8414eb487 --- /dev/null +++ b/test/spec/modules/weboramaBidAdapter_spec.js @@ -0,0 +1,118 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/weboramaBidAdapter'; + +describe('WeboramaAdapter', () => { + let bid = { + bidId: '2dd581a2b6281d', + bidder: 'weborama', + bidderRequestId: '145e1d6a7837c9', + params: { + placementId: 123, + traffic: 'banner' + }, + placementCode: 'placement_0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' + }; + + describe('isBidRequestValid', () => { + it('Should return true when placementId can be cast to a number', () => { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when placementId is not a number', () => { + bid.params.placementId = 'aaa'; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', () => { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', () => { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', () => { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', () => { + expect(serverRequest.url).to.equal('//supply.nl.weborama.fr/?c=o&m=multi'); + }); + it('Returns valid data if array of bids is valid', () => { + let data = serverRequest.data; + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'secure', 'host', 'page', 'placements'); + expect(data.deviceWidth).to.be.a('number'); + expect(data.deviceHeight).to.be.a('number'); + 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', 'bidId', 'traffic', 'sizes'); + 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'); + } + }); + it('Returns empty data if no valid requests are passed', () => { + serverRequest = spec.buildRequests([]); + let data = serverRequest.data; + expect(data.placements).to.be.an('array').that.is.empty; + }); + }); + describe('interpretResponse', () => { + let resObject = { + body: [ { + requestId: '123', + mediaType: 'banner', + cpm: 0.3, + width: 320, + height: 50, + ad: '

Hello ad

', + ttl: 1000, + creativeId: '123asd', + netRevenue: true, + currency: 'USD' + } ] + }; + let serverResponses = spec.interpretResponse(resObject); + it('Returns an array of valid server responses if response object is valid', () => { + 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'); + 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'); + } + it('Returns an empty array if invalid response is passed', () => { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); + + describe('getUserSyncs', () => { + let userSync = spec.getUserSyncs(); + it('Returns valid URL and `', () => { + 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('//supply.nl.weborama.fr/?c=o&m=cookie'); + }); + }); +}); From 4723710b6103622b3b31514e15b085a5c8390824 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 21 Jun 2018 16:53:48 -0400 Subject: [PATCH 0502/1594] move logic to check if CMP frame is not found (#2715) --- modules/consentManagement.js | 10 ++-- test/spec/modules/consentManagement_spec.js | 60 ++++++++++++--------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index fcaeab81544..5f040c63051 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -90,6 +90,10 @@ function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { f = f.parent; } + if (!cmpFrame) { + return cmpError('CMP not found.', hookConfig); + } + callCmpWhileInIframe('getConsentData', cmpFrame, callbackHandler.consentDataCallback); callCmpWhileInIframe('getVendorConsents', cmpFrame, callbackHandler.vendorConsentsCallback); } @@ -124,12 +128,6 @@ function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { /* Setup up a __cmp function to do the postMessage and stash the callback. This function behaves (from the caller's perspective identicially to the in-frame __cmp call */ window.__cmp = function(cmd, arg, callback) { - if (!cmpFrame) { - removePostMessageListener(); - - let errmsg = 'CMP not found'; - return cmpError(errmsg, hookConfig); - } let callId = Math.random() + ''; let msg = {__cmpCall: { command: cmd, diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index e825de2a184..46ab6c46777 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -68,35 +68,47 @@ describe('consentManagement', function () { }); describe('error checks:', () => { - describe('unknown CMP framework ID:', () => { - beforeEach(() => { - sinon.stub(utils, 'logWarn'); - }); + beforeEach(() => { + didHookReturn = false; + sinon.stub(utils, 'logWarn'); + sinon.stub(utils, 'logError'); + }); - afterEach(() => { - utils.logWarn.restore(); - config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); - resetConsentData(); - }); + afterEach(() => { + utils.logWarn.restore(); + utils.logError.restore(); + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + resetConsentData(); + }); + + it('should throw a warning and return to hooked function when an unknown CMP framework ID is used', () => { + let badCMPConfig = { + cmpApi: 'bad' + }; + setConfig(badCMPConfig); + expect(userCMP).to.be.equal(badCMPConfig.cmpApi); - it('should return Warning message and return to hooked function', () => { - let badCMPConfig = { - cmpApi: 'bad' - }; - setConfig(badCMPConfig); - expect(userCMP).to.be.equal(badCMPConfig.cmpApi); + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + sinon.assert.calledOnce(utils.logWarn); + expect(didHookReturn).to.be.true; + expect(consent).to.be.null; + }); - didHookReturn = false; + it('should throw proper errors when CMP is not found', () => { + setConfig(goodConfigWithCancelAuction); - requestBidsHook({}, () => { - didHookReturn = true; - }); - let consent = gdprDataHandler.getConsentData(); - sinon.assert.calledOnce(utils.logWarn); - expect(didHookReturn).to.be.true; - expect(consent).to.be.null; + requestBidsHook({}, () => { + didHookReturn = true; }); + let consent = gdprDataHandler.getConsentData(); + // throw 2 errors; one for no bidsBackHandler and for CMP not being found (this is an error due to gdpr config) + sinon.assert.calledTwice(utils.logError); + expect(didHookReturn).to.be.false; + expect(consent).to.be.null; }); }); From af9b294b39d452c24cd4d4c1f3932e01851f1b57 Mon Sep 17 00:00:00 2001 From: matimar <36712443+matimar@users.noreply.github.com> Date: Thu, 21 Jun 2018 18:05:24 -0300 Subject: [PATCH 0503/1594] Add crs parameter to eplanning adapter (#2682) --- modules/eplanningBidAdapter.js | 16 ++++++++++++++++ test/spec/modules/eplanningBidAdapter_spec.js | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js index dfc5f514cf3..6ead42d4b2d 100644 --- a/modules/eplanningBidAdapter.js +++ b/modules/eplanningBidAdapter.js @@ -17,6 +17,7 @@ export const spec = { isBidRequestValid: function(bid) { return Boolean(bid.params.ci) || Boolean(bid.params.t); }, + buildRequests: function(bidRequests) { const method = 'GET'; const dfpClientId = '1'; @@ -24,6 +25,7 @@ export const spec = { let url; let params; const urlConfig = getUrlConfig(bidRequests); + const pcrs = getCharset(); if (urlConfig.t) { url = urlConfig.isv + '/layers/t_pbjs_2.json'; @@ -40,6 +42,11 @@ export const spec = { pbv: '$prebid.version$', ncb: '1' }; + + if (pcrs) { + params.crs = pcrs; + } + if (referrerUrl) { params.fr = referrerUrl; } @@ -147,6 +154,15 @@ function getSpacesString(bids) { return spacesString; } + +function getCharset() { + try { + return window.top.document.charset || window.top.document.characterSet; + } catch (e) { + return document.charset || document.characterSet; + } +} + function getBidIdMap(bidRequests) { let map = {}; bidRequests.forEach(bid => map[cleanName(bid.adUnitCode)] = bid.bidId); diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js index 68b9e1b263f..a56bff42285 100644 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ b/test/spec/modules/eplanningBidAdapter_spec.js @@ -259,6 +259,19 @@ describe('E-Planning Adapter', () => { stubGetReferrer.restore() }); + it('should return crs parameter with document charset', () => { + let expected; + try { + expected = window.top.document.characterSet; + } catch (e) { + expected = document.characterSet; + } + + const chset = spec.buildRequests(bidRequests).data.crs; + + expect(chset).to.equal(expected); + }); + it('should return the testing url when the request has the t parameter', () => { const url = spec.buildRequests([testBid]).url; const expectedUrl = '//' + TEST_ISV + '/layers/t_pbjs_2.json'; From ead7aa93a1ce9978e63ad0140ca468dccb6c2261 Mon Sep 17 00:00:00 2001 From: tegner Date: Thu, 21 Jun 2018 23:20:22 +0200 Subject: [PATCH 0504/1594] extracted bidder from recieved object in timeout event (#2741) --- modules/googleAnalyticsAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/googleAnalyticsAdapter.js b/modules/googleAnalyticsAdapter.js index 2993697c09d..901159b14a8 100644 --- a/modules/googleAnalyticsAdapter.js +++ b/modules/googleAnalyticsAdapter.js @@ -235,7 +235,8 @@ function sendBidTimeouts(timedOutBidders) { _analyticsQueue.push(function () { utils._each(timedOutBidders, function (bidderCode) { _eventCount++; - window[_gaGlobal](_trackerSend, 'event', _category, 'Timeouts', bidderCode, _disableInteraction); + var bidderName = bidderCode.bidder; + window[_gaGlobal](_trackerSend, 'event', _category, 'Timeouts', bidderName, _disableInteraction); }); }); From 0c578b0eed2b8ac9eb8270397bc1abe0883d6a66 Mon Sep 17 00:00:00 2001 From: bretg Date: Thu, 21 Jun 2018 22:03:54 -0400 Subject: [PATCH 0505/1594] adding beta-releases to TOC (#2763) --- RELEASE_SCHEDULE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index 4f5c7fc4e9a..0c424e76ed4 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -1,6 +1,7 @@ **Table of Contents** - [Release Schedule](#release-schedule) - [Release Process](#release-process) +- [Beta Releases](#beta-releases) - [FAQs](#faqs) ## Release Schedule From cdbd9cfb6dc5efac1cac6bf4d4624aa29695bc46 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Fri, 22 Jun 2018 10:53:15 -0400 Subject: [PATCH 0506/1594] Feature/normalize size (#2738) * Fix for incorrectly uppercased keys * normalized the banner sizes param to always be [[h,w]] --- src/adaptermanager.js | 5 ++++- test/spec/unit/core/adapterManager_spec.js | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 4c60b01d8fa..1c8a2ff4a3e 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -230,7 +230,10 @@ exports.checkBidRequestSizes = (adUnits) => { if (mediaTypes && mediaTypes.banner) { const banner = mediaTypes.banner; if (banner.sizes) { - adUnit.sizes = banner.sizes; + // make sure we always send [[h,w]] format + const normalizedSize = utils.getAdUnitSizes(adUnit); + banner.sizes = normalizedSize; + adUnit.sizes = normalizedSize; } else { utils.logError('Detected a mediaTypes.banner object did not include sizes. This is a required field for the mediaTypes.banner object. Removing invalid mediaTypes.banner object from request.'); delete adUnit.mediaTypes.banner; diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 0e33fc005d5..c4dcc87198b 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -1013,6 +1013,20 @@ describe('adapterManager tests', () => { expect(result[0].mediaTypes.video).to.exist; sinon.assert.calledOnce(utils.logInfo); }); + + it('should normalize adUnit.sizes and adUnit.mediaTypes.banner.sizes', () => { + let fullAdUnit = [{ + sizes: [300, 250], + mediaTypes: { + banner: { + sizes: [300, 250] + } + } + }]; + let result = checkBidRequestSizes(fullAdUnit); + expect(result[0].sizes).to.deep.equal([[300, 250]]); + expect(result[0].mediaTypes.banner.sizes).to.deep.equal([[300, 250]]); + }); }); describe('negative tests for validating bid requests', () => { From 33a502bdf1420157898ab594ddbeab42b3d35199 Mon Sep 17 00:00:00 2001 From: Johnny Chau Date: Fri, 22 Jun 2018 08:29:16 -0700 Subject: [PATCH 0507/1594] Sharethrough - handle iframe bid param, safeframe support (#2762) - if true, Sharethrough ad markup will not break out of iframe - this also adds safeframe support --- modules/sharethroughBidAdapter.js | 95 ++++++++++++++----- modules/sharethroughBidAdapter.md | 5 +- .../modules/sharethroughBidAdapter_spec.js | 87 +++++++++++++---- 3 files changed, 145 insertions(+), 42 deletions(-) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index bb7f778089a..9aabca9518a 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -1,12 +1,14 @@ import { registerBidder } from 'src/adapters/bidderFactory'; +const VERSION = '3.0.0'; const BIDDER_CODE = 'sharethrough'; -const VERSION = '2.0.0'; const STR_ENDPOINT = document.location.protocol + '//btlr.sharethrough.com/header-bid/v1'; export const sharethroughAdapterSpec = { code: BIDDER_CODE, + isBidRequestValid: bid => !!bid.params.pkey && bid.bidder === BIDDER_CODE, + buildRequests: (bidRequests, bidderRequest) => { return bidRequests.map(bid => { let query = { @@ -26,67 +28,112 @@ export const sharethroughAdapterSpec = { query.consent_required = !!bidderRequest.gdprConsent.gdprApplies; } + // Data that does not need to go to the server, + // but we need as part of interpretResponse() + const strData = { + stayInIframe: bid.params.iframe, + sizes: bid.sizes + } + return { method: 'GET', url: STR_ENDPOINT, - data: query + data: query, + strData: strData }; }) }, + interpretResponse: ({ body }, req) => { - if (!body || !Object.keys(body).length || !body.creatives.length) { + if (!body || !body.creatives || !body.creatives.length) { return []; } const creative = body.creatives[0]; + let size = [0, 0]; + if (req.strData.stayInIframe) { + size = getLargestSize(req.strData.sizes); + } return [{ requestId: req.data.bidId, - width: 0, - height: 0, + width: size[0], + height: size[1], cpm: creative.cpm, creativeId: creative.creative.creative_key, - deal_id: creative.creative.deal_id, + dealId: creative.creative.deal_id, currency: 'USD', netRevenue: true, ttl: 360, ad: generateAd(body, req) }]; }, + getUserSyncs: (syncOptions, serverResponses) => { const syncs = []; - if (syncOptions.pixelEnabled && serverResponses.length > 0 && serverResponses[0].body) { + const shouldCookieSync = syncOptions.pixelEnabled && + serverResponses.length > 0 && + serverResponses[0].body && + serverResponses[0].body.cookieSyncUrls; + + if (shouldCookieSync) { serverResponses[0].body.cookieSyncUrls.forEach(url => { syncs.push({ type: 'image', url: url }); }); } + return syncs; } } +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 + } + }, [0, 0]); +} + function generateAd(body, req) { const strRespId = `str_response_${req.data.bidId}`; - return ` + let adMarkup = `
- - `; + ` + + if (req.strData.stayInIframe) { + // Don't break out of iframe + adMarkup = adMarkup + `` + } else { + // Break out of iframe + adMarkup = adMarkup + ` + + ` + } + + return adMarkup; } // See https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem diff --git a/modules/sharethroughBidAdapter.md b/modules/sharethroughBidAdapter.md index 8ab44f2a0f2..d2d8030c5f7 100644 --- a/modules/sharethroughBidAdapter.md +++ b/modules/sharethroughBidAdapter.md @@ -26,12 +26,13 @@ Module that connects to Sharethrough's demand sources ] },{ code: 'test-div', - sizes: [[1, 1]], // a mobile size + sizes: [[300,250], [1, 1]], // a mobile size bids: [ { bidder: "sharethrough", params: { - pkey: 'LuB3vxGGFrBZJa6tifXW4xgK' + pkey: 'LuB3vxGGFrBZJa6tifXW4xgK', + iframe: true } } ] diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index 2aef88fe7eb..a599ce6cdc8 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -19,17 +19,38 @@ const bidderRequest = [ sizes: [[700, 400]], placementCode: 'bar', params: { - pkey: 'bbbb2222' + pkey: 'bbbb2222', + iframe: true } }]; -const prebidRequest = [{ - method: 'GET', - url: document.location.protocol + '//btlr.sharethrough.com' + '/header-bid/v1', - data: { - bidId: 'bidId', - placement_key: 'pKey' - } -}]; + +const prebidRequests = [ + { + method: 'GET', + url: document.location.protocol + '//btlr.sharethrough.com' + '/header-bid/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + stayInIframe: false, + sizes: [] + } + }, + { + method: 'GET', + url: document.location.protocol + '//btlr.sharethrough.com' + '/header-bid/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + stayInIframe: true, + sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] + } + }, +]; + const bidderResponse = { body: { 'adserverRequestId': '40b6afd5-6134-4fbb-850a-bb8972a46994', @@ -48,6 +69,7 @@ const bidderResponse = { }, header: { get: (header) => header } }; + // Mirrors the one in modules/sharethroughBidAdapter.js as the function is unexported const b64EncodeUnicode = (str) => { return btoa( @@ -56,6 +78,7 @@ const b64EncodeUnicode = (str) => { return String.fromCharCode('0x' + p1); })); } + describe('sharethrough adapter spec', () => { describe('.code', () => { it('should return a bidder code of sharethrough', () => { @@ -119,13 +142,27 @@ describe('sharethrough adapter spec', () => { describe('.interpretResponse', () => { it('returns a correctly parsed out response', () => { - expect(spec.interpretResponse(bidderResponse, prebidRequest[0])[0]).to.include( + expect(spec.interpretResponse(bidderResponse, prebidRequests[0])[0]).to.include( { width: 0, height: 0, cpm: 12.34, creativeId: 'aCreativeId', - deal_id: 'aDealId', + dealId: 'aDealId', + currency: 'USD', + netRevenue: true, + ttl: 360, + }); + }); + + it('returns a correctly parsed out response with largest size when strData.stayInIframe is true', () => { + 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, @@ -134,21 +171,21 @@ describe('sharethrough adapter spec', () => { it('returns a blank array if there are no creatives', () => { const bidResponse = { body: { creatives: [] } }; - expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; }); it('returns a blank array if body object is empty', () => { const bidResponse = { body: {} }; - expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; }); it('returns a blank array if body is null', () => { const bidResponse = { body: null }; - expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; }); - it('correctly sends back a sfp script tag', () => { - const adMarkup = spec.interpretResponse(bidderResponse, prebidRequest[0])[0].ad; + it('correctly generates ad markup', () => { + const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[0])[0].ad; let resp = null; expect(() => btoa(JSON.stringify(bidderResponse))).to.throw(); @@ -163,6 +200,19 @@ describe('sharethrough adapter spec', () => { expect(adMarkup).to.match( /window.top.document.getElementsByTagName\('body'\)\[0\].appendChild\(sfp_js\);/) }); + + it('correctly generates ad markup for staying in iframe', () => { + const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[1])[0].ad; + let resp = null; + + expect(() => btoa(JSON.stringify(bidderResponse))).to.throw(); + expect(() => resp = 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( + / - - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
- - -
- -
- - - diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index c9548a280a0..d0ed7044242 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -1,21 +1,38 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import {BANNER, VIDEO, NATIVE} from 'src/mediaTypes'; const VER = 'ADGENT_PREBID-2018011501'; -const BID_REQUEST_BASE_URL = '//hb.aralego.com/header'; -const UCFUNNEL_BIDDER_CODE = 'ucfunnel'; +const BIDDER_CODE = 'ucfunnel'; + +const VIDEO_CONTEXT = { + INSTREAM: 0, + OUSTREAM: 2 +} export const spec = { - code: UCFUNNEL_BIDDER_CODE, - supportedMediaTypes: [BANNER], + code: BIDDER_CODE, + ENDPOINT: '//hb.aralego.com/header', + supportedMediaTypes: [BANNER, VIDEO, NATIVE], /** * Check if the bid is a valid zone ID in either number or string form * @param {object} bid the ucfunnel bid to validate * @return boolean for whether or not a bid is valid */ isBidRequestValid: function(bid) { - return !!(bid && bid.params && bid.params.adid && typeof bid.params.adid === 'string'); + const isVideoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); + + if (typeof bid.params !== 'object' || typeof bid.params.adid != 'string') { + return false; + } + + if (isVideoMediaType && videoContext === 'outstream') { + utils.logWarn('Warning: outstream video is not supported yet'); + return false; + } + + return true; }, /** @@ -23,21 +40,15 @@ export const spec = { * @param {*} bidderRequest * @return {ServerRequest} */ - buildRequests: function(validBidRequests, bidderRequest) { - var bidRequests = []; - for (var i = 0; i < validBidRequests.length; i++) { - var bid = validBidRequests[i]; - - var ucfunnelUrlParams = buildUrlParams(bid, bidderRequest); - - bidRequests.push({ + buildRequests: function(bids, bidderRequest) { + return bids.map(bid => { + return { method: 'GET', - url: BID_REQUEST_BASE_URL, - bidRequest: bid, - data: ucfunnelUrlParams - }); - } - return bidRequests; + url: location.protocol + spec.ENDPOINT, + data: getRequestData(bid, bidderRequest), + bidRequest: bid + } + }); }, /** @@ -46,55 +57,151 @@ export const spec = { * @return {Bid[]} An array of formatted bids. */ interpretResponse: function (ucfunnelResponseObj, request) { - var bidResponses = []; - var bidRequest = request.bidRequest; - var responseBody = ucfunnelResponseObj ? ucfunnelResponseObj.body : {}; + const bidRequest = request.bidRequest; + const ad = ucfunnelResponseObj ? ucfunnelResponseObj.body : {}; + const videoPlayerSize = parseSizes(bidRequest); - bidResponses.push({ + let bid = { requestId: bidRequest.bidId, - cpm: responseBody.cpm || 0, - width: responseBody.width, - height: responseBody.height, - creativeId: responseBody.ad_id, - dealId: responseBody.deal || null, + cpm: ad.cpm || 0, + creativeId: ad.ad_id, + dealId: ad.deal || null, currency: 'USD', netRevenue: true, - ttl: 1000, - mediaType: BANNER, - ad: responseBody.adm - }); + ttl: 1000 + }; + + if (ad.creative_type) { + bid.mediaType = ad.creative_type; + } + + switch (ad.creative_type) { + case NATIVE: + let nativeAd = ad.native; + Object.assign(bid, { + width: 1, + height: 1, + native: { + title: nativeAd.title, + body: nativeAd.desc, + cta: nativeAd.ctatext, + sponsoredBy: nativeAd.sponsored, + image: nativeAd.image || nativeAd.image.url, + icon: nativeAd.icon || nativeAd.icon.url, + clickUrl: nativeAd.clickUrl, + impressionTrackers: nativeAd.impressionTrackers, + } + }); + break; + case VIDEO: + Object.assign(bid, { + vastUrl: ad.vastUrl, + vastXml: ad.vastXml + }); + + if (videoPlayerSize && videoPlayerSize.length === 2) { + Object.assign(bid, { + width: videoPlayerSize[0], + height: videoPlayerSize[1] + }); + } + break; + case BANNER: + default: + Object.assign(bid, { + width: ad.width, + height: ad.height, + ad: ad.adm + }); + } + + return [bid]; + }, - return bidResponses; + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//cdn.aralego.com/ucfad/cookie/sync.html' + }]; + } else if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: '//sync.aralego.com/idSync' + }]; + } } }; registerBidder(spec); -function buildUrlParams(bid, bidderRequest) { - const host = utils.getTopWindowLocation().host; - const page = utils.getTopWindowLocation().pathname; - const refer = document.referrer; +function transformSizes(requestSizes) { + if (utils.isArray(requestSizes) && requestSizes.length === 2 && !utils.isArray(requestSizes[0])) { + return [parseInt(requestSizes[0], 10), parseInt(requestSizes[1], 10)]; + } else if (typeof requestSizes === 'object' && requestSizes.length) { + return requestSizes[0]; + } +} + +function parseSizes(bid) { + let params = bid.params; + if (bid.mediaType === VIDEO) { + let size = []; + if (params.video && params.video.playerWidth && params.video.playerHeight) { + size = [ + params.video.playerWidth, + params.video.playerHeight + ]; + return size; + } + } + + return transformSizes(bid.sizes); +} + +function getRequestData(bid, bidderRequest) { + const size = parseSizes(bid); + const loc = utils.getTopWindowLocation(); + const host = loc.host; + const page = loc.href; + const ref = utils.getTopWindowReferrer(); const language = navigator.language; const dnt = (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0; + const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - let queryString = [ - 'ifr', '0', - 'bl', language, - 'je', '1', - 'dnt', dnt, - 'host', host, - 'u', page, - 'ru', refer, - 'adid', utils.getBidIdParameter('adid', bid.params), - 'ver', VER - ]; + // general bid data + let bidData = { + ver: VER, + ifr: 0, + bl: language, + je: 1, + dnt: dnt, + host: host, + u: page, + ru: ref, + adid: utils.getBidIdParameter('adid', bid.params), + w: size[0], + h: size[1] + }; + + if (bid.mediaType === 'video' || videoMediaType) { + switch (videoContext) { + case 'outstream': + bidData.atype = VIDEO_CONTEXT.OUSTREAM; + break; + case 'instream': + default: + bidData.atype = VIDEO_CONTEXT.INSTREAM; + break; + } + } if (bidderRequest && bidderRequest.gdprConsent) { - queryString.push('gdpr', bidderRequest.gdprConsent.gdprApplies ? 1 : 0); - queryString.push('euconsent', bidderRequest.gdprConsent.consentString); + Object.assign(bidData, { + gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0, + euconsent: bidderRequest.gdprConsent.consentString + }); } - return queryString.reduce( - (memo, curr, index) => - index % 2 === 0 && queryString[index + 1] !== undefined ? memo + curr + '=' + encodeURIComponent(queryString[index + 1]) + '&' : memo, '' - ).slice(0, -1); + return bidData; } diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js index 152c7c39b1e..e8a4624bf16 100644 --- a/test/spec/modules/ucfunnelBidAdapter_spec.js +++ b/test/spec/modules/ucfunnelBidAdapter_spec.js @@ -1,19 +1,20 @@ import { expect } from 'chai'; import { spec } from 'modules/ucfunnelBidAdapter'; +import {BANNER, VIDEO, NATIVE} from 'src/mediaTypes'; const URL = '//hb.aralego.com/header'; const BIDDER_CODE = 'ucfunnel'; -const validBidReq = { +const validBannerBidReq = { bidder: BIDDER_CODE, params: { - adid: 'test-ad-83444226E44368D1E32E49EEBE6D29' + adid: 'ad-34BBD2AA24B678BBFD4E7B9EE3B872D' }, sizes: [[300, 250]], bidId: '263be71e91dd9d', auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', }; -const invalidBidReq = { +const invalidBannerBidReq = { bidder: BIDDER_CODE, params: { adid: 123456789 @@ -23,86 +24,166 @@ const invalidBidReq = { auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' }; -const bidReq = [{ +const validBannerBidRes = { + creative_type: BANNER, + ad_id: 'ad-34BBD2AA24B678BBFD4E7B9EE3B872D', + adm: '
', + cpm: 0.01, + height: 250, + width: 300 +}; + +const validVideoBidReq = { bidder: BIDDER_CODE, params: { - adid: 'test-ad-83444226E44368D1E32E49EEBE6D29' + adid: 'ad-9A22D466494297EAC443D967B2622DA9' }, - sizes: [[300, 250]], - bidId: '263be71e91dd9d', - auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' -}]; + sizes: [[640, 360]], + bidId: '263be71e91dd9f', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', +}; -const validBidRes = { - ad_id: 'ad-83444226E44368D1E32E49EEBE6D29', - adm: '
', +const validVideoBidRes = { + creative_type: VIDEO, + ad_id: 'ad-9A22D466494297EAC443D967B2622DA9', + vastUrl: 'https://ads.aralego.com/ads/58f9749f-0553-4993-8d9a-013a38b29e55', + vastXml: 'ucX I-Primo 00:00:30', cpm: 0.01, - height: 250, - width: 300 + width: 640, + height: 360 }; -const bidResponse = validBidRes; - -const bidResArray = [ - validBidRes, - { - ad: '', - bidRequestId: '263be71e91dd9d', - cpm: 100, - adId: '123abc', - currency: 'USD', - netRevenue: true, - width: 300, - height: 250, - ttl: 360 +const validNativeBidReq = { + bidder: BIDDER_CODE, + params: { + adid: 'ad-627736446B2BD3A60E8AEABDB7BD833E' }, - { - ad: '
Hello
', - bidRequestId: '', - cpm: 0, - adId: '123abc', - currency: 'USD', - netRevenue: true, - width: 300, - height: 250, - ttl: 360 - } -]; + sizes: [[1, 1]], + bidId: '263be71e91dda0', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', +}; + +const validNativeBidRes = { + creative_type: NATIVE, + ad_id: 'ad-9A22D466494297EAC443D967B2622DA9', + native: { + title: 'ucfunnel adExchange', + body: 'We monetize your traffic via historic data driven protocol', + cta: 'Learn more', + sponsoredBy: 'ucfunnel Co., Ltd.', + image: { + url: 'https://cdn.aralego.net/img/main/AdGent-1200x627.jpg', + width: 1200, + height: 627 + }, + icon: { + url: 'https://cdn.aralego.net/img/logo/logo-84x84.jpg', + widt: 84, + heigh: 84 + }, + clickUrl: 'https://www.ucfunnel.com', + impressionTrackers: ['https://www.aralego.net/imp?mf=native&adid=ad-9A22D466494297EAC443D967B2622DA9&auc=9ad1fa8d-2297-4660-a018-b39945054746'], + }, + cpm: 0.01, + height: 1, + width: 1 +}; describe('ucfunnel Adapter', () => { describe('request', () => { it('should validate bid request', () => { - expect(spec.isBidRequestValid(validBidReq)).to.equal(true); + expect(spec.isBidRequestValid(validBannerBidReq)).to.equal(true); }); it('should not validate incorrect bid request', () => { - expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); + expect(spec.isBidRequestValid(invalidBannerBidReq)).to.equal(false); }); }); describe('build request', () => { - it('Verify bid request', () => { - const request = spec.buildRequests(bidReq); + const request = spec.buildRequests([validBannerBidReq]); + it('should create a POST request for every bid', () => { expect(request[0].method).to.equal('GET'); - expect(request[0].url).to.equal(URL); - expect(request[0].data).to.match(new RegExp(`${bidReq[0].params.adid}`)); + expect(request[0].url).to.equal(location.protocol + spec.ENDPOINT); + }); + + it('should attach the bid request object', () => { + expect(request[0].bidRequest).to.equal(validBannerBidReq); + }); + + it('should attach request data', () => { + const data = request[0].data; + const [ width, height ] = validBannerBidReq.sizes[0]; + expect(data.w).to.equal(width); + expect(data.h).to.equal(height); + }); + + it('must parse bid size from a nested array', () => { + const width = 640; + const height = 480; + validBannerBidReq.sizes = [[ width, height ]]; + const requests = spec.buildRequests([ validBannerBidReq ]); + const data = requests[0].data; + expect(data.w).to.equal(width); + expect(data.h).to.equal(height); }); }); describe('interpretResponse', () => { - it('should build bid array', () => { - const request = spec.buildRequests(bidReq); - const result = spec.interpretResponse({body: bidResponse}, request[0]); - expect(result.length).to.equal(1); + describe('should support banner', () => { + const request = spec.buildRequests([ validBannerBidReq ]); + const result = spec.interpretResponse({body: validBannerBidRes}, request[0]); + it('should build bid array for banner', () => { + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', () => { + const bid = result[0]; + + expect(bid.mediaType).to.equal(BANNER); + expect(bid.ad).to.exist; + expect(bid.requestId).to.equal('263be71e91dd9d'); + expect(bid.cpm).to.equal(0.01); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + }); + }); + + describe('should support video', () => { + const request = spec.buildRequests([ validVideoBidReq ]); + const result = spec.interpretResponse({body: validVideoBidRes}, request[0]); + it('should build bid array', () => { + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', () => { + const bid = result[0]; + + expect(bid.mediaType).to.equal(VIDEO); + expect(bid.vastUrl).to.exist; + expect(bid.vastXml).to.exist; + expect(bid.requestId).to.equal('263be71e91dd9f'); + expect(bid.cpm).to.equal(0.01); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(360); + }); }); - it('should have all relevant fields', () => { - const request = spec.buildRequests(bidReq); - const result = spec.interpretResponse({body: bidResponse}, request[0]); - const bid = result[0]; + describe('should support native', () => { + const request = spec.buildRequests([ validNativeBidReq ]); + const result = spec.interpretResponse({body: validNativeBidRes}, request[0]); + it('should build bid array', () => { + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', () => { + const bid = result[0]; - expect(bid.requestId).to.equal('263be71e91dd9d'); - expect(bid.cpm).to.equal(0.01); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); + expect(bid.mediaType).to.equal(NATIVE); + expect(bid.native).to.exist; + expect(bid.requestId).to.equal('263be71e91dda0'); + expect(bid.cpm).to.equal(0.01); + expect(bid.width).to.equal(1); + expect(bid.height).to.equal(1); + }); }); }); }); From 8995c8043e3e5219d4aa11abfe69d061089e5854 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Mon, 9 Jul 2018 17:01:58 -0400 Subject: [PATCH 0530/1594] give s2s request the same amount of time from the client side (#2790) * give s2s request the same amount of time from the client side, ie do not abort early * missed auctionjs --- src/adaptermanager.js | 7 ++++--- src/auction.js | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 0dc5a9177db..83ca7acc587 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -281,7 +281,7 @@ exports.checkBidRequestSizes = (adUnits) => { return adUnits; } -exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbacks) => { +exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbacks, requestBidsTimeout) => { if (!bidRequests.length) { utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); return; @@ -293,7 +293,8 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbac }, [[], []]); if (serverBidRequests.length) { - const s2sAjax = ajaxBuilder(serverBidRequests[0].timeout, requestCallbacks ? { + // s2s should get the same client side timeout as other client side requests. + const s2sAjax = ajaxBuilder(requestBidsTimeout, requestCallbacks ? { request: requestCallbacks.request.bind(null, 's2s'), done: requestCallbacks.done } : undefined); @@ -356,7 +357,7 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbac events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); bidRequest.doneCbCallCount = 0; let done = doneCb(bidRequest.bidderRequestId); - let ajax = ajaxBuilder(clientBidRequests[0].timeout, requestCallbacks ? { + let ajax = ajaxBuilder(requestBidsTimeout, requestCallbacks ? { request: requestCallbacks.request.bind(null, bidRequest.bidderCode), done: requestCallbacks.done } : undefined); diff --git a/src/auction.js b/src/auction.js index 3c727bf1003..fe57de38de1 100644 --- a/src/auction.js +++ b/src/auction.js @@ -229,7 +229,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } } - }); + }, _timeout); } }; From 4ffc421d306c408f299af8717e730152ccf291c7 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Tue, 10 Jul 2018 20:49:21 +0530 Subject: [PATCH 0531/1594] Video support in PubMatic adapter (#2807) * merging latest prebid master with video changes * fixed linting errors * moved data types to constants * fixes for code review comments on PR --- modules/pubmaticBidAdapter.js | 132 +++++++++++-- modules/pubmaticBidAdapter.md | 52 ++++- src/utils.js | 5 + test/spec/modules/pubmaticBidAdapter_spec.js | 193 +++++++++++++++++++ 4 files changed, 368 insertions(+), 14 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 989ce180463..0c1062458c4 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -1,5 +1,6 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; const constants = require('src/constants.json'); const BIDDER_CODE = 'pubmatic'; @@ -18,6 +19,28 @@ const CUSTOM_PARAMS = { 'profId': '', // OpenWrap Legacy: Profile ID 'verId': '' // OpenWrap Legacy: version ID }; +const DATA_TYPES = { + 'NUMBER': 'number', + 'STRING': 'string', + 'BOOLEAN': 'boolean', + 'ARRAY': 'array' +}; +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 +} const NET_REVENUE = false; const dealChannelValues = { 1: 'PMP', @@ -152,27 +175,90 @@ function _createOrtbTemplate(conf) { }; } +// similar functionality as parseSlotParam. Check if the 2 functions can be clubbed. +function _checkParamDataType(key, value, datatype) { + var errMsg = 'PubMatic: Ignoring param key: ' + key + ', expects ' + datatype + ', found ' + typeof value; + switch (datatype) { + case DATA_TYPES.BOOLEAN: + if (!utils.isBoolean(value)) { + utils.logWarn(errMsg); + return UNDEFINED; + } + return value; + case DATA_TYPES.NUMBER: + if (!utils.isNumber(value)) { + utils.logWarn(errMsg); + return UNDEFINED; + } + return value; + case DATA_TYPES.STRING: + if (!utils.isStr(value)) { + utils.logWarn(errMsg); + return UNDEFINED; + } + return value; + case DATA_TYPES.ARRAY: + if (!utils.isArray(value)) { + utils.logWarn(errMsg); + return UNDEFINED; + } + return value; + } +} + function _createImpressionObject(bid, conf) { - return { + var impObj = {}; + var bannerObj = {}; + var videoObj = {}; + + impObj = { id: bid.bidId, tagid: bid.params.adUnit, bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor), secure: window.location.protocol === 'https:' ? 1 : 0, - banner: { + ext: { + pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) + } + }; + + if (bid.params.hasOwnProperty('video')) { + var videoData = bid.params.video; + + 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 (utils.isArray(bid.mediaTypes.video.playerSize[0])) { + videoObj.w = bid.mediaTypes.video.playerSize[0][0]; + videoObj.h = bid.mediaTypes.video.playerSize[0][1]; + } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { + videoObj.w = bid.mediaTypes.video.playerSize[0]; + videoObj.h = bid.mediaTypes.video.playerSize[1]; + } + if (bid.params.video.hasOwnProperty('skippable')) { + videoObj.ext = { + 'video_skippable': bid.params.video.skippable ? 1 : 0 + } + } + + impObj.video = videoObj; + } else { + bannerObj = { pos: 0, w: bid.params.width, h: bid.params.height, topframe: utils.inIframe() ? 0 : 1, - }, - ext: { - pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) } - }; + impObj.banner = bannerObj; + } + return impObj; } export const spec = { code: BIDDER_CODE, - + supportedMediaTypes: [BANNER, VIDEO], /** * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid * @@ -189,6 +275,13 @@ export const spec = { utils.logWarn('PubMatic: adSlotId is mandatory and cannot be numeric. Call to OpenBid will not be sent.'); return false; } + // video ad validation + if (bid.params.hasOwnProperty('video')) { + if (!bid.params.video.hasOwnProperty('mimes') || !utils.isArray(bid.params.video.mimes) || bid.params.video.mimes.length === 0) { + utils.logWarn('PubMatic: For video ads, mimes is mandatory and must specify atlease 1 mime value. Call to OpenBid will not be sent.'); + return false; + } + } return true; } return false; @@ -205,9 +298,16 @@ export const spec = { var payload = _createOrtbTemplate(conf); validBidRequests.forEach(bid => { _parseAdSlot(bid); - if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height)) { - utils.logWarn('PubMatic: Skipping the non-standard adslot:', bid.params.adSlot, bid); - return; + if (bid.params.hasOwnProperty('video')) { + if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex)) { + utils.logWarn('PubMatic: Skipping the non-standard adslot: ', bid.params.adSlot, bid); + return; + } + } else { + if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height)) { + utils.logWarn('PubMatic: Skipping the non-standard adslot: ', bid.params.adSlot, bid); + return; + } } conf.pubId = conf.pubId || bid.params.publisherId; conf = _handleCustomParams(bid.params, conf); @@ -287,7 +387,17 @@ export const spec = { referrer: utils.getTopWindowUrl(), ad: bid.adm }; - + let parsedRequest = JSON.parse(request.data); + if (parsedRequest.imp && parsedRequest.imp.length > 0) { + parsedRequest.imp.forEach(req => { + if (bid.impid === req.id && req.hasOwnProperty('video')) { + newBid.mediaType = 'video'; + newBid.width = bid.hasOwnProperty('w') ? bid.w : req.video.w; + newBid.height = bid.hasOwnProperty('h') ? bid.h : req.video.h; + newBid.vastXml = bid.adm; + } + }); + } if (bid.ext && bid.ext.deal_channel) { newBid['dealChannel'] = dealChannelValues[bid.ext.deal_channel] || null; } diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 768b3c541f6..eb02d3039fb 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -10,9 +10,9 @@ Maintainer: header-bidding@pubmatic.com Connects to PubMatic exchange for bids. -PubMatic bid adapter supports Banner currently. +PubMatic bid adapter supports Video and Banner currently. -# Sample Ad Unit: For Publishers +# Sample Banner Ad Unit: For Publishers ``` var adUnits = [ { @@ -35,7 +35,43 @@ var adUnits = [ kadfloor: '0.50' // optional } }] -} +}]; +``` + +# Sample Video Ad Unit: For Publishers +``` +var adVideoAdUnits = [ +{ + code: 'test-div-video', + mediaTypes: { + video: { + playerSize: [640, 480], // required + context: 'instream' + } + }, + bids: [{ + bidder: 'pubmatic', + params: { + publisherId: '351', // required + adSlot: '1363568@300x250', // 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 + } + } + }] +}] ``` ### Configuration @@ -49,5 +85,15 @@ pbjs.setConfig({ enabledBidders: ['pubmatic'], syncDelay: 6000 }}); + + +For Video ads, prebid cache needs to be enabled for PubMatic adapter. +pbjs.setConfig({ + debug: true, + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } +}); + ``` Note: Combine the above the configuration with any other UserSync configuration. Multiple setConfig() calls overwrite each other and only last call for a given attribute will take effect. diff --git a/src/utils.js b/src/utils.js index 09a52660796..be1b3fbf5e2 100644 --- a/src/utils.js +++ b/src/utils.js @@ -12,6 +12,7 @@ var t_Str = 'String'; var t_Fn = 'Function'; var t_Numb = 'Number'; var t_Object = 'Object'; +var t_Boolean = 'Boolean'; var toString = Object.prototype.toString; let infoLogger = null; let warnLogger = null; @@ -423,6 +424,10 @@ exports.isPlainObject = function(object) { return exports.isA(object, t_Object); } +exports.isBoolean = function(object) { + return exports.isA(object, t_Boolean); +} + /** * Return if the object is "empty"; * this includes falsey, no keys, or no items at indices diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 09acbbe95a0..0e94d2d9a30 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -5,6 +5,8 @@ const constants = require('src/constants.json'); describe('PubMatic adapter', () => { let bidRequests; + let videoBidRequests; + let multipleMediaRequests; let bidResponses; beforeEach(() => { @@ -34,6 +36,91 @@ describe('PubMatic adapter', () => { } ]; + videoBidRequests = + [ + { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bidder: 'pubmatic', + params: { + publisherId: '5890', + adSlot: 'Div1@0x0', // ad_id or tagid + 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 + } + } + } + ]; + + multipleMediaRequests = + [ + { + 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' + } + }, + { + code: 'div-instream', + mediaTypes: { + video: { + context: 'instream', + playerSize: [300, 250] + }, + }, + bidder: 'pubmatic', + params: { + publisherId: '5890', + adSlot: 'Div1@640x480', // ad_id or tagid + video: { + mimes: ['video/mp4', 'video/x-flv'], + skippable: true, + minduration: 5, + maxduration: 30, + startdelay: 15, + playbackmethod: [1, 3], + api: [1, 2], + protocols: [2, 3], + w: 640, + h: 480, + battr: [13, 14], + linearity: 1, + placement: 2, + minbitrate: 100, + maxbitrate: 4096 + } + } + } + ]; + bidResponses = { 'body': { 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', @@ -198,6 +285,112 @@ describe('PubMatic adapter', () => { expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid }); + it('Request params check for video ad', () => { + let request = spec.buildRequests(videoBidRequests); + let data = JSON.parse(request.data); + expect(data.imp[0].video).to.exist; + expect(data.imp[0].tagid).to.equal('Div1'); + expect(data.imp[0].video.ext['video_skippable']).to.equal(videoBidRequests[0].params.video.skippable ? 1 : 0); + expect(data.imp[0]['video']['mimes']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['mimes'][0]).to.equal(videoBidRequests[0].params.video['mimes'][0]); + expect(data.imp[0]['video']['mimes'][1]).to.equal(videoBidRequests[0].params.video['mimes'][1]); + expect(data.imp[0]['video']['minduration']).to.equal(videoBidRequests[0].params.video['minduration']); + expect(data.imp[0]['video']['maxduration']).to.equal(videoBidRequests[0].params.video['maxduration']); + expect(data.imp[0]['video']['startdelay']).to.equal(videoBidRequests[0].params.video['startdelay']); + + expect(data.imp[0]['video']['playbackmethod']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['playbackmethod'][0]).to.equal(videoBidRequests[0].params.video['playbackmethod'][0]); + expect(data.imp[0]['video']['playbackmethod'][1]).to.equal(videoBidRequests[0].params.video['playbackmethod'][1]); + + expect(data.imp[0]['video']['api']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['api'][0]).to.equal(videoBidRequests[0].params.video['api'][0]); + expect(data.imp[0]['video']['api'][1]).to.equal(videoBidRequests[0].params.video['api'][1]); + + expect(data.imp[0]['video']['protocols']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['protocols'][0]).to.equal(videoBidRequests[0].params.video['protocols'][0]); + expect(data.imp[0]['video']['protocols'][1]).to.equal(videoBidRequests[0].params.video['protocols'][1]); + + expect(data.imp[0]['video']['battr']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['battr'][0]).to.equal(videoBidRequests[0].params.video['battr'][0]); + expect(data.imp[0]['video']['battr'][1]).to.equal(videoBidRequests[0].params.video['battr'][1]); + + expect(data.imp[0]['video']['linearity']).to.equal(videoBidRequests[0].params.video['linearity']); + expect(data.imp[0]['video']['placement']).to.equal(videoBidRequests[0].params.video['placement']); + expect(data.imp[0]['video']['minbitrate']).to.equal(videoBidRequests[0].params.video['minbitrate']); + expect(data.imp[0]['video']['maxbitrate']).to.equal(videoBidRequests[0].params.video['maxbitrate']); + + 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]); + }); + + it('Request params check for 1 banner and 1 video ad', () => { + let request = spec.buildRequests(multipleMediaRequests); + let data = JSON.parse(request.data); + + expect(data.imp).to.be.an('array') + expect(data.imp).with.length.above(1); + + expect(data.at).to.equal(1); // auction type + expect(data.cur[0]).to.equal('USD'); // currency + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.page).to.equal(multipleMediaRequests[0].params.kadpageurl); // forced pageURL + expect(data.site.publisher.id).to.equal(multipleMediaRequests[0].params.publisherId); // publisher Id + expect(data.user.yob).to.equal(parseInt(multipleMediaRequests[0].params.yob)); // YOB + expect(data.user.gender).to.equal(multipleMediaRequests[0].params.gender); // Gender + expect(data.device.geo.lat).to.equal(parseFloat(multipleMediaRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.equal(parseFloat(multipleMediaRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.equal(parseFloat(multipleMediaRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.equal(parseFloat(multipleMediaRequests[0].params.lon)); // Lognitude + expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version + expect(data.ext.wrapper.transactionId).to.equal(multipleMediaRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.wiid).to.equal(multipleMediaRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID + expect(data.ext.wrapper.profile).to.equal(parseInt(multipleMediaRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID + expect(data.ext.wrapper.version).to.equal(parseInt(multipleMediaRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID + + // banner imp object check + expect(data.imp[0].id).to.equal(multipleMediaRequests[0].bidId); // Prebid bid id is passed as id + expect(data.imp[0].bidfloor).to.equal(parseFloat(multipleMediaRequests[0].params.kadfloor)); // kadfloor + expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].ext.pmZoneId).to.equal(multipleMediaRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid + + // video imp object check + expect(data.imp[1].video).to.exist; + expect(data.imp[1].tagid).to.equal('Div1'); + expect(data.imp[1].video.ext['video_skippable']).to.equal(multipleMediaRequests[1].params.video.skippable ? 1 : 0); + expect(data.imp[1]['video']['mimes']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['mimes'][0]).to.equal(multipleMediaRequests[1].params.video['mimes'][0]); + expect(data.imp[1]['video']['mimes'][1]).to.equal(multipleMediaRequests[1].params.video['mimes'][1]); + expect(data.imp[1]['video']['minduration']).to.equal(multipleMediaRequests[1].params.video['minduration']); + expect(data.imp[1]['video']['maxduration']).to.equal(multipleMediaRequests[1].params.video['maxduration']); + expect(data.imp[1]['video']['startdelay']).to.equal(multipleMediaRequests[1].params.video['startdelay']); + + expect(data.imp[1]['video']['playbackmethod']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['playbackmethod'][0]).to.equal(multipleMediaRequests[1].params.video['playbackmethod'][0]); + expect(data.imp[1]['video']['playbackmethod'][1]).to.equal(multipleMediaRequests[1].params.video['playbackmethod'][1]); + + expect(data.imp[1]['video']['api']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['api'][0]).to.equal(multipleMediaRequests[1].params.video['api'][0]); + expect(data.imp[1]['video']['api'][1]).to.equal(multipleMediaRequests[1].params.video['api'][1]); + + expect(data.imp[1]['video']['protocols']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['protocols'][0]).to.equal(multipleMediaRequests[1].params.video['protocols'][0]); + expect(data.imp[1]['video']['protocols'][1]).to.equal(multipleMediaRequests[1].params.video['protocols'][1]); + + expect(data.imp[1]['video']['battr']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['battr'][0]).to.equal(multipleMediaRequests[1].params.video['battr'][0]); + expect(data.imp[1]['video']['battr'][1]).to.equal(multipleMediaRequests[1].params.video['battr'][1]); + + expect(data.imp[1]['video']['linearity']).to.equal(multipleMediaRequests[1].params.video['linearity']); + expect(data.imp[1]['video']['placement']).to.equal(multipleMediaRequests[1].params.video['placement']); + expect(data.imp[1]['video']['minbitrate']).to.equal(multipleMediaRequests[1].params.video['minbitrate']); + expect(data.imp[1]['video']['maxbitrate']).to.equal(multipleMediaRequests[1].params.video['maxbitrate']); + + expect(data.imp[1]['video']['w']).to.equal(multipleMediaRequests[1].mediaTypes.video.playerSize[0]); + expect(data.imp[1]['video']['h']).to.equal(multipleMediaRequests[1].mediaTypes.video.playerSize[1]); + }); + it('invalid adslot', () => { bidRequests[0].params.adSlot = '/15671365/DMDemo'; let request = spec.buildRequests(bidRequests); From b5842ebb02472553d670cfe834d763ffa73f3b79 Mon Sep 17 00:00:00 2001 From: Arik Kfir Date: Tue, 10 Jul 2018 18:32:15 +0300 Subject: [PATCH 0532/1594] Gambid adapter: Provide "mediaType" for all bids, and "vastUrl" property for video bids (#2825) --- modules/gambidBidAdapter.js | 6 +++--- test/spec/modules/gambidBidAdapter_spec.js | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/gambidBidAdapter.js b/modules/gambidBidAdapter.js index e87c28acc77..ca711f6e1eb 100644 --- a/modules/gambidBidAdapter.js +++ b/modules/gambidBidAdapter.js @@ -126,9 +126,9 @@ export const spec = { currency: bid.cur || response.cur }; if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { - outBids.push(Object.assign({}, outBid, { ad: bid.adm })); - } else if (bidRequest.bidRequest.mediaTypes && bidRequest.bidRequest.mediaTypes.video) { - outBids.push(Object.assign({}, outBid, { vastXml: bid.adm })); + outBids.push(Object.assign({}, outBid, { mediaType: 'banner', ad: bid.adm })); + } else if (bidRequest.bidRequest.mediaTypes.video) { + outBids.push(Object.assign({}, outBid, { mediaType: 'video', vastUrl: bid.ext.vast_url, vastXml: bid.adm })); } }); return outBids; diff --git a/test/spec/modules/gambidBidAdapter_spec.js b/test/spec/modules/gambidBidAdapter_spec.js index 54b9c518e2b..0498de8790e 100644 --- a/test/spec/modules/gambidBidAdapter_spec.js +++ b/test/spec/modules/gambidBidAdapter_spec.js @@ -214,6 +214,7 @@ describe('GambidAdapter', () => { 'h': 600, 'w': 120, 'ext': { + 'vast_url': 'http://my.vast.com', 'utrk': [ { 'type': 'iframe', 'url': '//p.partner1.io/user/sync/1' } ] @@ -306,6 +307,7 @@ describe('GambidAdapter', () => { expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); expect(ad0.ad).to.be.an('undefined'); expect(ad0.vastXml).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); + expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.vast_url); expect(ad1.requestId).to.equal(videoBidRequest.bidId); expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); @@ -317,6 +319,7 @@ describe('GambidAdapter', () => { expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); expect(ad1.ad).to.be.an('undefined'); expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.vast_url); }); it('aggregates user-sync pixels', () => { const response = spec.getUserSyncs({}, [ { body: rtbResponse } ]); From 902792174a28ce277c1c04b5b4f624df214d0618 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 10 Jul 2018 11:32:31 -0400 Subject: [PATCH 0533/1594] PBS Adapter: call done when ajax request fails (#2794) * call done when ajax request fails * no need to wrap function here --- modules/prebidServerBidAdapter.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 7b6b2b9ed7e..28d7dcb54c4 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -695,7 +695,10 @@ export function PrebidServer() { ajax( _s2sConfig.endpoint, - response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done), + { + success: response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done), + error: done + }, requestJson, { contentType: 'text/plain', withCredentials: true } ); From 4319b1f247290d4f522d2efbd965eb94a366b3ae Mon Sep 17 00:00:00 2001 From: Brittany Zellman <33695402+brittanyzellman@users.noreply.github.com> Date: Tue, 10 Jul 2018 11:37:31 -0400 Subject: [PATCH 0534/1594] Include gdpr TripleLift (#2663) * added triplelift bid adapter to modules * need to host * updated adapter to 1.12 * removed useless conditional * fixed unused-variable error * fixed flash method * had two versions of the consent method, initially pushed the wrong one * added tmax to query string * fixed linter error * fixed linter error * tested for valid bid request * finished writing tests * added markdown file * slight change to md file * removed single quotes * deleted commented out import statement * small changes requested by MK * removed an from testing --- modules/tripleliftBidAdapter.js | 140 ++++++++++++ modules/tripleliftBidAdapter.md | 62 ++++++ .../spec/modules/tripleliftBidAdapter_spec.js | 207 ++++++++++++++++++ 3 files changed, 409 insertions(+) create mode 100644 modules/tripleliftBidAdapter.js create mode 100644 modules/tripleliftBidAdapter.md create mode 100644 test/spec/modules/tripleliftBidAdapter_spec.js diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js new file mode 100644 index 00000000000..5114444be3c --- /dev/null +++ b/modules/tripleliftBidAdapter.js @@ -0,0 +1,140 @@ +import { BANNER } from 'src/mediaTypes'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'triplelift'; +const STR_ENDPOINT = document.location.protocol + '//tlx.3lift.com/header/auction?'; +let gdprApplies = true; +let consentString = null; + +export const tripleliftAdapterSpec = { + + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + isBidRequestValid: function(bid) { + return (typeof bid.params.inventoryCode !== 'undefined'); + }, + + buildRequests: function(bidRequests, bidderRequest) { + let tlCall = STR_ENDPOINT; + let referrer = utils.getTopWindowUrl(); + let data = _buildPostBody(bidRequests); + + tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); + tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); + tlCall = utils.tryAppendQueryString(tlCall, 'fe', _isFlashEnabled().toString()); + tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer); + + if (bidderRequest && bidderRequest.timeout) { + tlCall = utils.tryAppendQueryString(tlCall, 'tmax', bidderRequest.timeout); + } + + if (bidderRequest && bidderRequest.gdprConsent) { + if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { + gdprApplies = bidderRequest.gdprConsent.gdprApplies; + tlCall = utils.tryAppendQueryString(tlCall, 'gdpr', gdprApplies.toString()); + } + if (typeof bidderRequest.gdprConsent.consentString !== 'undefined') { + consentString = bidderRequest.gdprConsent.consentString; + tlCall = utils.tryAppendQueryString(tlCall, 'cmp_cs', consentString); + } + } + + if (tlCall.lastIndexOf('&') === tlCall.length - 1) { + tlCall = tlCall.substring(0, tlCall.length - 1); + } + utils.logMessage('tlCall request built: ' + tlCall); + + return { + method: 'POST', + url: tlCall, + data, + bidderRequest + }; + }, + + interpretResponse: function(serverResponse, {bidderRequest}) { + let bids = serverResponse.body.bids || []; + return bids.map(function(bid) { + return _buildResponseObject(bidderRequest, bid); + }); + }, + + getUserSyncs: function(syncOptions) { + let ibCall = '//ib.3lift.com/sync?'; + if (consentString !== null) { + ibCall = utils.tryAppendQueryString(ibCall, 'gdpr', gdprApplies); + ibCall = utils.tryAppendQueryString(ibCall, 'cmp_cs', consentString); + } + + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: ibCall + }]; + } + } +} + +function _buildPostBody(bidRequests) { + let data = {}; + data.imp = bidRequests.map(function(bid, index) { + return { + id: index, + tagid: bid.params.inventoryCode, + floor: bid.params.floor, + banner: { + format: _sizes(bid.sizes) + } + } + }); + + return data; +} + +function _sizes(sizeArray) { + return sizeArray.map(function(size) { + return { + w: size[0], + h: size[1] + }; + }); +} + +function _buildResponseObject(bidderRequest, bid) { + let bidResponse = {}; + let width = bid.width || 1; + let height = bid.height || 1; + let dealId = bid.deal_id || ''; + let creativeId = bid.imp_id; + + if (bid.cpm != 0 && bid.ad) { + bidResponse = { + requestId: bidderRequest.bids[creativeId].bidId, + cpm: bid.cpm, + width: width, + height: height, + netRevenue: true, + ad: bid.ad, + creativeId: creativeId, + dealId: dealId, + currency: 'USD', + ttl: 33, + }; + }; + return bidResponse; +} + +function _isFlashEnabled() { + let flash; + try { + flash = Boolean(new ActiveXObject('ShockwaveFlash.ShockwaveFlash')); + } catch (e) { + flash = navigator.mimeTypes && + navigator.mimeTypes['application/x-shockwave-flash'] !== undefined && + navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin ? 1 : 0 + } + return flash ? 1 : 0; +} + +registerBidder(tripleliftAdapterSpec); diff --git a/modules/tripleliftBidAdapter.md b/modules/tripleliftBidAdapter.md new file mode 100644 index 00000000000..ad153cdece7 --- /dev/null +++ b/modules/tripleliftBidAdapter.md @@ -0,0 +1,62 @@ +# Overview + +``` +Module Name: Triplelift Bid Adapter +Module Type: Bidder Adapter +Maintainer: bzellman@triplelift.com +``` + +# Description + +Connects to Triplelift Exchange for bids. +Triplelift bid adapter supports Banner format only. + +# Test Parameters +``` +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 600], [300, 250], [320, 90]], + } + }, + bids: [ + { + bidder: 'triplelift', + params: { + inventoryCode: 'forbes_main', + floor: 1.009 + } + }] +}, { + code: 'banner-div-2', + mediaTypes: { + banner: { + sizes: [[300, 300]], + } + }, + bids: [ + { + bidder: 'triplelift', + params: { + inventoryCode: 'foodgawker', + floor: 0.00 + } + }] +}, { + code: 'banner-div-3', + mediaTypes: { + banner: { + sizes: [[300, 600], [300, 250]], + } + }, + bids: [ + { + bidder: 'triplelift', + params: { + inventoryCode: 'forbes_main', + floor: 0 + } + }] +}]; +``` diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js new file mode 100644 index 00000000000..3d5b7d2dcba --- /dev/null +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -0,0 +1,207 @@ +import { expect } from 'chai'; +import { tripleliftAdapterSpec } from 'modules/tripleliftBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +const ENDPOINT = document.location.protocol + '//tlx.3lift.com/header/auction?'; + +describe('triplelift adapter', () => { + const adapter = newBidder(tripleliftAdapterSpec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + bidder: 'triplelift', + params: { + inventoryCode: '12345', + floor: 1.0, + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true for valid bid request', () => { + expect(tripleliftAdapterSpec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + inventoryCode: 'another_inv_code', + floor: 0.05 + }; + expect(tripleliftAdapterSpec.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 = { + floor: 1.0 + }; + expect(tripleliftAdapterSpec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + bidder: 'triplelift', + params: { + inventoryCode: '12345', + floor: 1.0, + }, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + } + ]; + + it('exists and is an object', () => { + const request = tripleliftAdapterSpec.buildRequests(bidRequests); + expect(request).to.exist.and.to.be.a('object'); + }); + + it('should be a post request and populate the payload', () => { + const request = tripleliftAdapterSpec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.exist; + expect(payload.imp[0].tagid).to.equal('12345'); + expect(payload.imp[0].floor).to.equal(1.0); + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + }); + + it('should return a query string for TL call', () => { + const request = tripleliftAdapterSpec.buildRequests(bidRequests); + const url = request.url; + expect(url).to.exist; + expect(url).to.be.a('string'); + expect(url).to.match(/(?:tlx.3lift.com\/header\/auction)/) + expect(url).to.match(/(?:lib=prebid)/) + expect(url).to.match(/(?:prebid.version)/) + expect(url).to.match(/(?:fe=)/) + expect(url).to.match(/(?:referrer)/) + }) + }); + + describe('interpretResponse', () => { + let response = { + body: { + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 250, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ] + } + }; + let bidderRequest = { + bidderCode: 'triplelift', + auctionId: 'a7ebcd1d-66ff-4b5c-a82c-6a21a6ee5a18', + bidderRequestId: '5c55612f99bc11', + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 250, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ], + gdprConsent: { + consentString: 'BOONm0NOONma-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVOQ6gEaY', + gdprApplies: true + } + }; + + it('should get correct bid response', () => { + let expectedResponse = [ + { + requestId: '3db3773286ee59', + cpm: 1.062, + width: 300, + height: 250, + netRevenue: true, + ad: 'ad-markup', + creativeId: 29681110, + dealId: '', + currency: 'USD', + ttl: 33, + } + ]; + let result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + expect(result).to.have.length(1); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('should return multile responses to support SRA', () => { + let response = { + body: { + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 250, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + }, + { + imp_id: 0, + cpm: 1.9, + width: 300, + height: 600, + ad: 'ad-markup-2', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ] + } + }; + let bidderRequest = { + bidderCode: 'triplelift', + auctionId: 'a7ebcd1d-66ff-4b5c-a82c-6a21a6ee5a18', + bidderRequestId: '5c55612f99bc11', + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 600, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + }, + { + imp_id: 0, + cpm: 1.9, + width: 300, + height: 250, + ad: 'ad-markup-2', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ], + gdprConsent: { + consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', + gdprApplies: true + } + }; + let result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + expect(result).to.have.length(2); + }); + }); +}); From d212b8bc37030de4750d7e4ab2a0692ecd23f153 Mon Sep 17 00:00:00 2001 From: yehonatanshac Date: Tue, 10 Jul 2018 18:41:23 +0300 Subject: [PATCH 0535/1594] Kumma adapter: GDPR support (#2799) --- modules/kummaBidAdapter.js | 10 +++++++++- test/spec/modules/kummaBidAdapter_spec.js | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/modules/kummaBidAdapter.js b/modules/kummaBidAdapter.js index 1d2df149fe9..f9a8c6fd143 100644 --- a/modules/kummaBidAdapter.js +++ b/modules/kummaBidAdapter.js @@ -23,7 +23,7 @@ export const spec = { isBidRequestValid: bid => ( !!(bid && bid.params && bid.params.pubId && bid.params.placementId) ), - buildRequests: bidRequests => { + buildRequests: (bidRequests, bidderRequest) => { const request = { id: bidRequests[0].bidderRequestId, at: 2, @@ -32,6 +32,7 @@ export const spec = { app: app(bidRequests), device: device(bidRequests), }; + applyGdpr(bidderRequest, request); return { method: 'POST', url: '//hb.kumma.com/', @@ -270,6 +271,13 @@ function parse(rawResponse) { return null; } +function applyGdpr(bidderRequest, ortbRequest) { + if (bidderRequest && bidderRequest.gdprConsent) { + ortbRequest.regs = { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0 } }; + ortbRequest.user = { ext: { consent: bidderRequest.gdprConsent.consentString } }; + } +} + function nativeResponse(imp, bid) { if (imp['native']) { const nativeAd = parse(bid.adm); diff --git a/test/spec/modules/kummaBidAdapter_spec.js b/test/spec/modules/kummaBidAdapter_spec.js index 36c77a736d4..84efa032cec 100644 --- a/test/spec/modules/kummaBidAdapter_spec.js +++ b/test/spec/modules/kummaBidAdapter_spec.js @@ -313,4 +313,23 @@ describe('Kumma Adapter Tests', () => { expect(ortbRequest.app.storeurl).to.equal('http://kumma.com/apps'); expect(ortbRequest.app.domain).to.equal('kumma.com'); }); + + it('Verify GDPR', () => { + const bidderRequest = { + gdprConsent: { + gdprApplies: true, + consentString: 'serialized_gpdr_data' + } + }; + const request = spec.buildRequests(slotConfigs, bidderRequest); + expect(request.url).to.equal('//hb.kumma.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.user).to.not.equal(null); + expect(ortbRequest.user.ext).to.not.equal(null); + expect(ortbRequest.user.ext.consent).to.equal('serialized_gpdr_data'); + expect(ortbRequest.regs).to.not.equal(null); + expect(ortbRequest.regs.ext).to.not.equal(null); + expect(ortbRequest.regs.ext.gdpr).to.equal(1); + }); }); From e087cd2a01c2495943645482ecd91e9a5ad974c0 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 10 Jul 2018 12:24:26 -0400 Subject: [PATCH 0536/1594] include targeting data in buildVideoUrl function (#2826) --- modules/dfpAdServerVideo.js | 16 ++++- test/spec/modules/dfpAdServerVideo_spec.js | 76 ++++++++++++++++++++++ 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 1c9dbe1fac4..1b5f8509559 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -73,7 +73,7 @@ export default function buildDfpVideoUrl(options) { urlComponents = parse(options.url, {noDecodeWholeURL: true}); if (isEmpty(options.params)) { - return buildUrlFromAdserverUrlComponents(urlComponents, bid); + return buildUrlFromAdserverUrlComponents(urlComponents, bid, options); } } @@ -108,13 +108,14 @@ export default function buildDfpVideoUrl(options) { * Prebid-specific key-values. * @param {Object} components base video adserver url parsed into components object * @param {AdapterBidResponse} bid winning bid object to append parameters from + * @param {Object} options Options which should be used to construct the URL (used for custom params). * @return {string} video url */ -function buildUrlFromAdserverUrlComponents(components, bid) { +function buildUrlFromAdserverUrlComponents(components, bid, options) { const descriptionUrl = getDescriptionUrl(bid, components, 'search'); if (descriptionUrl) { components.search.description_url = descriptionUrl; } - const encodedCustomParams = getCustParams(bid); + const encodedCustomParams = getCustParams(bid, options); components.search.cust_params = (components.search.cust_params) ? components.search.cust_params + '%26' + encodedCustomParams : encodedCustomParams; return buildUrl(components); @@ -147,8 +148,17 @@ function getDescriptionUrl(bid, components, prop) { */ function getCustParams(bid, options) { const adserverTargeting = (bid && bid.adserverTargeting) || {}; + + let allTargetingData = {}; + const adUnit = options && options.adUnit; + if (adUnit) { + let allTargeting = targeting.getAllTargeting(adUnit.code); + allTargetingData = (allTargeting) ? allTargeting[adUnit.code] : {}; + } + const optCustParams = deepAccess(options, 'params.cust_params'); let customParams = Object.assign({}, + allTargetingData, adserverTargeting, { hb_uuid: bid && bid.videoCacheKey }, // hb_uuid will be deprecated and replaced by hb_cache_id diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index c4a799b0b0a..8f779412c80 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -4,6 +4,9 @@ import parse from 'url-parse'; import buildDfpVideoUrl from 'modules/dfpAdServerVideo'; import { parseQS } from 'src/url'; import adUnit from 'test/fixtures/video/adUnit'; +import * as utils from 'src/utils'; +import { config } from 'src/config'; +import { targeting } from 'src/targeting'; const bid = { videoCacheKey: 'abc', @@ -107,6 +110,79 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('hb_cache_id', bid.videoCacheKey); }); + describe('special targeting unit test', () => { + const allTargetingData = { + 'hb_format': 'video', + 'hb_source': 'client', + 'hb_size': '640x480', + 'hb_pb': '5.00', + 'hb_adid': '2c4f6cc3ba128a', + 'hb_bidder': 'testBidder2', + 'hb_format_testBidder2': 'video', + 'hb_source_testBidder2': 'client', + 'hb_size_testBidder2': '640x480', + 'hb_pb_testBidder2': '5.00', + 'hb_adid_testBidder2': '2c4f6cc3ba128a', + 'hb_bidder_testBidder2': 'testBidder2', + 'hb_format_appnexus': 'video', + 'hb_source_appnexus': 'client', + 'hb_size_appnexus': '640x480', + 'hb_pb_appnexus': '5.00', + 'hb_adid_appnexus': '44e0b5f2e5cace', + 'hb_bidder_appnexus': 'appnexus' + }; + let targetingStub; + + before(() => { + targetingStub = sinon.stub(targeting, 'getAllTargeting'); + targetingStub.returns({'video1': allTargetingData}); + + config.setConfig({ + enableSendAllBids: true + }); + }); + + after(() => { + config.resetConfig(); + targetingStub.restore(); + }); + + it('should include all adserver targeting in cust_params if pbjs.enableSendAllBids is true', () => { + const adUnitsCopy = utils.deepClone(adUnit); + adUnitsCopy.bids.push({ + 'bidder': 'testBidder2', + 'params': { + 'placementId': '9333431', + 'video': { + 'skipppable': false, + 'playback_methods': ['auto_play_sound_off'] + } + } + }); + + const bidCopy = Object.assign({ }, bid); + bidCopy.adserverTargeting = { + hb_adid: 'ad_id', + }; + + const url = parse(buildDfpVideoUrl({ + adUnit: adUnitsCopy, + bid: bidCopy, + params: { + 'iu': 'my/adUnit' + } + })); + const queryObject = parseQS(url.query); + const customParams = parseQS('?' + decodeURIComponent(queryObject.cust_params)); + + expect(customParams).to.have.property('hb_adid', 'ad_id'); + expect(customParams).to.have.property('hb_uuid', bid.videoCacheKey); + expect(customParams).to.have.property('hb_cache_id', bid.videoCacheKey); + expect(customParams).to.have.property('hb_bidder_appnexus', 'appnexus'); + expect(customParams).to.have.property('hb_bidder_testBidder2', 'testBidder2'); + }); + }); + it('should merge the user-provided cust_params with the default ones', () => { const bidCopy = Object.assign({ }, bid); bidCopy.adserverTargeting = { From 43301e08b0ff7ed3da7b751a95f713c2bf5fb0a5 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 10 Jul 2018 12:32:51 -0400 Subject: [PATCH 0537/1594] remove library analyticsAdapter type (#2779) * remove library analyticsAdapter type * remove unused imports in test file --- src/AnalyticsAdapter.js | 8 +-- test/spec/AnalyticsAdapter_spec.js | 99 +++++++++++++----------------- 2 files changed, 43 insertions(+), 64 deletions(-) diff --git a/src/AnalyticsAdapter.js b/src/AnalyticsAdapter.js index 30848b341d8..3cb64f1b911 100644 --- a/src/AnalyticsAdapter.js +++ b/src/AnalyticsAdapter.js @@ -1,5 +1,4 @@ import CONSTANTS from './constants'; -import { loadScript } from './adloader'; import { ajax } from './ajax'; const events = require('./events'); @@ -20,7 +19,6 @@ const { } } = CONSTANTS; -const LIBRARY = 'library'; const ENDPOINT = 'endpoint'; const BUNDLE = 'bundle'; @@ -32,10 +30,6 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } var _enableCheck = true; var _handlers; - if (analyticsType === LIBRARY) { - loadScript(url, _emptyQueue); - } - if (analyticsType === ENDPOINT || BUNDLE) { _emptyQueue(); } @@ -52,7 +46,7 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } }; function _track({ eventType, args }) { - if (this.getAdapterType() === LIBRARY || BUNDLE) { + if (this.getAdapterType() === BUNDLE) { window[global](handler, eventType, args); } diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index d6b227e9aac..c6c50f76ecd 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -1,4 +1,4 @@ -import { assert } from 'chai'; +import { expect } from 'chai'; import events from 'src/events'; import CONSTANTS from 'src/constants.json'; @@ -10,74 +10,57 @@ const AD_RENDER_FAILED = CONSTANTS.EVENTS.AD_RENDER_FAILED; const AnalyticsAdapter = require('src/AnalyticsAdapter').default; const config = { - url: 'http://localhost:9999/src/adapters/analytics/libraries/example.js', - analyticsType: 'library', - global: 'ExampleAnalyticsGlobalObject', - handler: 'on' + url: 'http://localhost:9999/endpoint', + analyticsType: 'endpoint' }; -window[config.global] = () => {}; - describe(` FEATURE: Analytics Adapters API SCENARIO: A publisher enables analytics - GIVEN a global object \`window['testGlobal']\` AND an \`example\` instance of \`AnalyticsAdapter\`\n`, () => { - describe(`WHEN an event occurs that is to be tracked\n`, () => { + let xhr; + let requests; + let adapter; + + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + adapter = new AnalyticsAdapter(config); + }); + + afterEach(() => { + xhr.restore(); + adapter.disableAnalytics(); + }); + + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, () => { const eventType = BID_REQUESTED; const args = { some: 'data' }; - const adapter = new AnalyticsAdapter(config); - var spyTestGlobal = sinon.spy(window, config.global); adapter.track({ eventType, args }); - it(`THEN should call \`window.${config.global}\` function\n`, () => { - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); - }); - window[config.global].restore(); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); }); - describe(`WHEN an event occurs before tracking library is available\n`, () => { + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, () => { const eventType = BID_RESPONSE; const args = { wat: 'wot' }; - const adapter = new AnalyticsAdapter(config); - - window[config.global] = null; - events.emit(BID_RESPONSE, args); - - describe(`AND the adapter is then enabled\n`, () => { - window[config.global] = () => {}; - var spyTestGlobal = sinon.spy(window, config.global); + events.emit(eventType, args); + adapter.enableAnalytics(); - adapter.enableAnalytics(); - - it(`THEN should queue the event first and then track it\n`, () => { - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); - }); - - adapter.disableAnalytics(); - window[config.global].restore(); - }); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); }); describe(`WHEN an event occurs after enable analytics\n`, () => { - var spyTestGlobal, - adapter; - beforeEach(() => { - adapter = new AnalyticsAdapter(config); - spyTestGlobal = sinon.spy(window, config.global); - sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests }); afterEach(() => { - adapter.disableAnalytics(); - window[config.global].restore(); - events.getEvents.restore(); }); @@ -88,8 +71,8 @@ FEATURE: Analytics Adapters API adapter.enableAnalytics(); events.emit(eventType, args); - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); it('SHOULD call global when a adRenderFailed event occurs', () => { @@ -99,8 +82,8 @@ FEATURE: Analytics Adapters API adapter.enableAnalytics(); events.emit(eventType, args); - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); it('SHOULD call global when a bidRequest event occurs', () => { @@ -110,8 +93,8 @@ FEATURE: Analytics Adapters API adapter.enableAnalytics(); events.emit(eventType, args); - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); }); it('SHOULD call global when a bidResponse event occurs', () => { @@ -121,8 +104,8 @@ FEATURE: Analytics Adapters API adapter.enableAnalytics(); events.emit(eventType, args); - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); }); it('SHOULD call global when a bidTimeout event occurs', () => { @@ -132,8 +115,8 @@ FEATURE: Analytics Adapters API adapter.enableAnalytics(); events.emit(eventType, args); - assert.ok(spyTestGlobal.args[0][1] === eventType, `with expected event type\n`); - assert.deepEqual(spyTestGlobal.args[0][2], args, `with expected event data\n`); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); }); it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', () => { @@ -144,7 +127,7 @@ FEATURE: Analytics Adapters API adapter.enableAnalytics(); events.emit(eventType, args); - assert(spyTestGlobal.calledOnce === true); + expect(requests.length).to.equal(1); }); describe(`AND sampling is enabled\n`, () => { @@ -167,7 +150,9 @@ FEATURE: Analytics Adapters API }); events.emit(eventType, args); - assert(spyTestGlobal.called === true); + expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); it(`THEN should disable analytics when random number is outside sample range`, () => { @@ -178,7 +163,7 @@ FEATURE: Analytics Adapters API }); events.emit(eventType, args); - assert(spyTestGlobal.called === false); + expect(requests.length).to.equal(0); }); }); }); From 35ad532dcba9b878f519a07ddce849472c02c135 Mon Sep 17 00:00:00 2001 From: Steve Alliance Date: Tue, 10 Jul 2018 13:44:31 -0400 Subject: [PATCH 0538/1594] districtmDMX new adapter (#2765) * adding DMX test @97%, two files added one updated * Update districtm_spec.js * Update districtmDMX.js * adding all districtm needed file * remove legacy file * remove typo || 0 in the test method * force default to return a valid width and height * update unit test code for failing test * changed class for an object * remove package-lock.json --- modules/districtmDmxAdapter.js | 155 + modules/districtmDmxAdapter.md | 31 + package-lock.json | 17334 ---------------- test/spec/modules/districtmDmxAdapter_spec.js | 533 + 4 files changed, 719 insertions(+), 17334 deletions(-) create mode 100644 modules/districtmDmxAdapter.js create mode 100644 modules/districtmDmxAdapter.md delete mode 100644 package-lock.json create mode 100644 test/spec/modules/districtmDmxAdapter_spec.js diff --git a/modules/districtmDmxAdapter.js b/modules/districtmDmxAdapter.js new file mode 100644 index 00000000000..3ec0b72649e --- /dev/null +++ b/modules/districtmDmxAdapter.js @@ -0,0 +1,155 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import {config} from 'src/config'; + +const BIDDER_CODE = 'districtmDMX'; + +const DMXURI = 'https://dmx.districtm.io/b/v1'; + +export const spec = { + code: BIDDER_CODE, + supportedFormat: ['banner'], + isBidRequestValid(bid) { + return !!(bid.params.dmxid && bid.params.memberid); + }, + interpretResponse(response, bidRequest) { + response = response.body || {}; + if (response.seatbid) { + if (utils.isArray(response.seatbid)) { + const {seatbid} = response; + let winners = seatbid.reduce((bid, ads) => { + let ad = ads.bid.reduce(function(oBid, nBid) { + if (oBid.price < nBid.price) { + const bid = matchRequest(nBid.impid, bidRequest); + const {width, height} = defaultSize(bid); + nBid.cpm = nBid.price; + nBid.bidId = nBid.impid; + nBid.requestId = nBid.impid; + nBid.width = nBid.w || width; + nBid.height = nBid.h || height; + nBid.ad = nBid.adm; + nBid.netRevenue = true; + nBid.creativeId = nBid.crid; + nBid.currency = 'USD'; + nBid.ttl = 60; + + return nBid; + } else { + oBid.cpm = oBid.price; + return oBid; + } + }, {price: 0}); + if (ad.adm) { + bid.push(ad) + } + return bid; + }, []) + let winnersClean = winners.filter(w => { + if (w.bidId) { + return true; + } + return false; + }); + return winnersClean; + } else { + return []; + } + } else { + return []; + } + }, + buildRequests(bidRequest, bidderRequest) { + let timeout = config.getConfig('bidderTimeout'); + let dmxRequest = { + id: utils.generateUUID(), + cur: ['USD'], + tmax: (timeout - 300), + test: this.test() || 0, + site: { + publisher: { id: String(bidRequest[0].params.memberid) || null } + } + } + if (!dmxRequest.test) { + delete dmxRequest.test; + } + if (bidderRequest.gdprConsent) { + dmxRequest.regs = {}; + dmxRequest.regs.ext = {}; + dmxRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; + if (dmxRequest.regs.ext.gdpr) { + dmxRequest.regs.ext.consent = bidderRequest.gdprConsent.consentString; + } + } + let tosendtags = bidRequest.map(dmx => { + var obj = {}; + obj.id = dmx.bidId; + obj.tagid = String(dmx.params.dmxid); + obj.secure = window.location.protocol === 'https:' ? 1 : 0; + obj.banner = { + topframe: 1, + w: dmx.sizes[0][0] || 0, + h: dmx.sizes[0][1] || 0, + format: dmx.sizes.map(s => { + return {w: s[0], h: s[1]}; + }) + }; + return obj; + }); + dmxRequest.imp = tosendtags; + return { + method: 'POST', + url: DMXURI, + data: JSON.stringify(dmxRequest), + options: { + contentType: 'application/json', + withCredentials: true + }, + bidderRequest + } + }, + test() { + return window.location.href.indexOf('dmTest=true') !== -1 ? 1 : 0; + }, + getUserSyncs(optionsType) { + if (optionsType.iframeEnabled) { + return [{ + type: 'iframe', + url: 'https://cdn.districtm.io/ids/index.html' + }]; + } + } +} + +/** + * Function matchRequest(id: string, BidRequest: object) + * @param id + * @type string + * @param bidRequest + * @type Object + * @returns Object + * + */ +export function matchRequest(id, bidRequest) { + const {bids} = bidRequest.bidderRequest; + const [returnValue] = bids.filter(bid => bid.bidId === id); + return returnValue; +} +export function checkDeepArray(Arr) { + if (Array.isArray(Arr)) { + if (Array.isArray(Arr[0])) { + return Arr[0]; + } else { + return Arr; + } + } else { + return Arr; + } +} +export function defaultSize(thebidObj) { + const {sizes} = thebidObj; + const returnObject = {}; + returnObject.width = checkDeepArray(sizes)[0]; + returnObject.height = checkDeepArray(sizes)[1]; + return returnObject; +} +registerBidder(spec); diff --git a/modules/districtmDmxAdapter.md b/modules/districtmDmxAdapter.md new file mode 100644 index 00000000000..a096029963c --- /dev/null +++ b/modules/districtmDmxAdapter.md @@ -0,0 +1,31 @@ +# Overview + +``` +Module Name: DistrictM Bid Adapter +Module Type: Bidder Adapter +Maintainer: steve@districtm.net +``` + +# Description + +Adapter that connects to DistrictM's demand sources. +This version only support banner + +# Test Parameters +``` + var adUnits = [{ + code: 'div-gpt-ad-1460505748561-0', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + }, + bids: [{ + bidder: 'districtmDMX', + params: { + dmxid: 100001, + memberid: 100003 + } + }] + }]; +``` diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 3ba5921d852..00000000000 --- a/package-lock.json +++ /dev/null @@ -1,17334 +0,0 @@ -{ - "name": "prebid.js", - "version": "1.15.0-pre", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@gulp-sourcemaps/identity-map": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/@gulp-sourcemaps%2fidentity-map/-/identity-map-1.0.1.tgz", - "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", - "requires": { - "acorn": "5.6.2", - "css": "2.2.3", - "normalize-path": "2.1.1", - "source-map": "0.5.7", - "through2": "2.0.3" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/@gulp-sourcemaps%2fmap-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "requires": { - "normalize-path": "2.1.1", - "through2": "2.0.3" - } - }, - "@sindresorhus/is": { - "version": "0.7.0", - "resolved": "https://npm.corp.appnexus.com/@sindresorhus%2fis/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", - "dev": true - }, - "@sinonjs/formatio": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/@sinonjs%2fformatio/-/formatio-2.0.0.tgz", - "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "dev": true, - "requires": { - "samsam": "1.3.0" - } - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://npm.corp.appnexus.com/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "accepts": { - "version": "1.2.13", - "resolved": "https://npm.corp.appnexus.com/accepts/-/accepts-1.2.13.tgz", - "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", - "dev": true, - "requires": { - "mime-types": "2.1.18", - "negotiator": "0.5.3" - } - }, - "acorn": { - "version": "5.6.2", - "resolved": "https://npm.corp.appnexus.com/acorn/-/acorn-5.6.2.tgz", - "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw==" - }, - "acorn-dynamic-import": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", - "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", - "dev": true, - "requires": { - "acorn": "4.0.13" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://npm.corp.appnexus.com/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - } - } - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "3.3.0" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://npm.corp.appnexus.com/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "addressparser": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/addressparser/-/addressparser-1.0.1.tgz", - "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", - "dev": true, - "optional": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://npm.corp.appnexus.com/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "agent-base": { - "version": "4.2.0", - "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-4.2.0.tgz", - "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", - "dev": true, - "requires": { - "es6-promisify": "5.0.0" - } - }, - "ajv": { - "version": "6.2.0", - "resolved": "https://npm.corp.appnexus.com/ajv/-/ajv-6.2.0.tgz", - "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", - "dev": true, - "requires": { - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", - "dev": true - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://npm.corp.appnexus.com/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" - }, - "amqplib": { - "version": "0.5.2", - "resolved": "https://npm.corp.appnexus.com/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", - "dev": true, - "optional": true, - "requires": { - "bitsyntax": "0.0.4", - "bluebird": "3.5.1", - "buffer-more-ints": "0.0.2", - "readable-stream": "1.1.14", - "safe-buffer": "5.1.2" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://npm.corp.appnexus.com/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "3.1.10", - "normalize-path": "2.1.1" - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "1.0.0" - } - }, - "append-transform": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", - "dev": true, - "requires": { - "default-require-extensions": "2.0.0" - } - }, - "archiver": { - "version": "0.14.4", - "resolved": "https://npm.corp.appnexus.com/archiver/-/archiver-0.14.4.tgz", - "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", - "dev": true, - "requires": { - "async": "0.9.2", - "buffer-crc32": "0.2.13", - "glob": "4.3.5", - "lazystream": "0.1.0", - "lodash": "3.2.0", - "readable-stream": "1.0.34", - "tar-stream": "1.1.5", - "zip-stream": "0.5.2" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://npm.corp.appnexus.com/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "glob": { - "version": "4.3.5", - "resolved": "https://npm.corp.appnexus.com/glob/-/glob-4.3.5.tgz", - "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lazystream": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/lazystream/-/lazystream-0.1.0.tgz", - "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", - "dev": true, - "requires": { - "readable-stream": "1.0.34" - } - }, - "lodash": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-3.2.0.tgz", - "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", - "dev": true - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://npm.corp.appnexus.com/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-iterate": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/array-iterate/-/array-iterate-1.1.2.tgz", - "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", - "dev": true - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://npm.corp.appnexus.com/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "array.from": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/array.from/-/array.from-0.2.0.tgz", - "integrity": "sha1-LGJ7G3bf8t7yNl+gUrZcPVheX2s=", - "dev": true - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://npm.corp.appnexus.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://npm.corp.appnexus.com/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://npm.corp.appnexus.com/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" - } - }, - "assert": { - "version": "1.4.1", - "resolved": "https://npm.corp.appnexus.com/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://npm.corp.appnexus.com/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "ast-types": { - "version": "0.11.5", - "resolved": "https://npm.corp.appnexus.com/ast-types/-/ast-types-0.11.5.tgz", - "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://npm.corp.appnexus.com/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://npm.corp.appnexus.com/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://npm.corp.appnexus.com/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "aws4": { - "version": "1.7.0", - "resolved": "https://npm.corp.appnexus.com/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", - "dev": true - }, - "axios": { - "version": "0.15.3", - "resolved": "https://npm.corp.appnexus.com/axios/-/axios-0.15.3.tgz", - "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", - "dev": true, - "optional": true, - "requires": { - "follow-redirects": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "follow-redirects": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/follow-redirects/-/follow-redirects-1.0.0.tgz", - "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.9" - } - } - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "babel-core": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-core/-/babel-core-6.22.0.tgz", - "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "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.10", - "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://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://npm.corp.appnexus.com/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.10", - "source-map": "0.5.7", - "trim-right": "1.0.1" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "esutils": "2.0.2" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.10" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.10" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-loader": { - "version": "7.1.4", - "resolved": "https://npm.corp.appnexus.com/babel-loader/-/babel-loader-7.1.4.tgz", - "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", - "dev": true, - "requires": { - "find-cache-dir": "1.0.0", - "loader-utils": "1.1.0", - "mkdirp": "0.5.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://npm.corp.appnexus.com/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true - }, - "babel-plugin-syntax-class-constructor-call": { - "version": "6.18.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", - "dev": true - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true - }, - "babel-plugin-syntax-do-expressions": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", - "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", - "dev": true - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-export-extensions": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", - "dev": true - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true - }, - "babel-plugin-syntax-function-bind": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", - "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-system-import-transformer": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", - "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0" - } - }, - "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-generators": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-class-constructor-call": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", - "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, - "requires": { - "babel-plugin-syntax-class-constructor-call": "6.18.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "6.24.1", - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-decorators-legacy": { - "version": "1.3.5", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", - "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", - "dev": true, - "requires": { - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-do-expressions": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", - "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true, - "requires": { - "babel-plugin-syntax-do-expressions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.10" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "6.26.0", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "regexpu-core": "2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-export-extensions": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", - "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, - "requires": { - "babel-plugin-syntax-export-extensions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-function-bind": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", - "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true, - "requires": { - "babel-plugin-syntax-function-bind": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-object-assign": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", - "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "6.26.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "0.10.1" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-preset-env": { - "version": "1.7.0", - "resolved": "https://npm.corp.appnexus.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0", - "browserslist": "3.2.8", - "invariant": "2.2.4", - "semver": "5.5.0" - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://npm.corp.appnexus.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "6.22.0" - } - }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-react-jsx-self": "6.22.0", - "babel-plugin-transform-react-jsx-source": "6.22.0", - "babel-preset-flow": "6.23.0" - } - }, - "babel-preset-stage-0": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", - "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true, - "requires": { - "babel-plugin-transform-do-expressions": "6.22.0", - "babel-plugin-transform-function-bind": "6.22.0", - "babel-preset-stage-1": "6.24.1" - } - }, - "babel-preset-stage-1": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", - "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, - "requires": { - "babel-plugin-transform-class-constructor-call": "6.24.1", - "babel-plugin-transform-export-extensions": "6.22.0", - "babel-preset-stage-2": "6.24.1" - } - }, - "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-decorators": "6.24.1", - "babel-preset-stage-3": "6.24.1" - } - }, - "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://npm.corp.appnexus.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-generator-functions": "6.24.1", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-object-rest-spread": "6.26.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "6.26.3", - "babel-runtime": "6.26.0", - "core-js": "2.5.7", - "home-or-tmp": "2.0.0", - "lodash": "4.17.10", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" - }, - "dependencies": { - "babel-core": { - "version": "6.26.3", - "resolved": "https://npm.corp.appnexus.com/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.1", - "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.10", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "2.5.7", - "regenerator-runtime": "0.11.1" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/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.10" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/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.9", - "globals": "9.18.0", - "invariant": "2.2.4", - "lodash": "4.17.10" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://npm.corp.appnexus.com/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.10", - "to-fast-properties": "1.0.3" - } - }, - "babelify": { - "version": "8.0.0", - "resolved": "https://npm.corp.appnexus.com/babelify/-/babelify-8.0.0.tgz", - "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw==", - "dev": true - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://npm.corp.appnexus.com/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "bail": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://npm.corp.appnexus.com/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "base64-url": { - "version": "1.2.1", - "resolved": "https://npm.corp.appnexus.com/base64-url/-/base64-url-1.2.1.tgz", - "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true - }, - "basic-auth": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/basic-auth/-/basic-auth-1.0.4.tgz", - "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", - "dev": true - }, - "basic-auth-connect": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", - "dev": true - }, - "batch": { - "version": "0.5.3", - "resolved": "https://npm.corp.appnexus.com/batch/-/batch-0.5.3.tgz", - "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, - "big.js": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "0.1.1", - "chainsaw": "0.1.0" - } - }, - "binary-extensions": { - "version": "1.11.0", - "resolved": "https://npm.corp.appnexus.com/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true - }, - "binaryextensions": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/binaryextensions/-/binaryextensions-1.0.1.tgz", - "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", - "dev": true - }, - "bitsyntax": { - "version": "0.0.4", - "resolved": "https://npm.corp.appnexus.com/bitsyntax/-/bitsyntax-0.0.4.tgz", - "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", - "dev": true, - "optional": true, - "requires": { - "buffer-more-ints": "0.0.2" - } - }, - "bl": { - "version": "0.9.5", - "resolved": "https://npm.corp.appnexus.com/bl/-/bl-0.9.5.tgz", - "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", - "dev": true, - "requires": { - "readable-stream": "1.0.34" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "blob": { - "version": "0.0.4", - "resolved": "https://npm.corp.appnexus.com/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", - "dev": true - }, - "block-loader": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/block-loader/-/block-loader-2.1.0.tgz", - "integrity": "sha1-u7OYrVqEPGxx95opb0tt9LAlcxI=", - "dev": true - }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://npm.corp.appnexus.com/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://npm.corp.appnexus.com/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "body": { - "version": "5.1.0", - "resolved": "https://npm.corp.appnexus.com/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true, - "requires": { - "continuable-cache": "0.3.1", - "error": "7.0.2", - "raw-body": "1.1.7", - "safe-json-parse": "1.0.1" - } - }, - "body-parser": { - "version": "1.13.3", - "resolved": "https://npm.corp.appnexus.com/body-parser/-/body-parser-1.13.3.tgz", - "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", - "dev": true, - "requires": { - "bytes": "2.1.0", - "content-type": "1.0.4", - "debug": "2.2.0", - "depd": "1.0.1", - "http-errors": "1.3.1", - "iconv-lite": "0.4.11", - "on-finished": "2.3.0", - "qs": "4.0.0", - "raw-body": "2.1.7", - "type-is": "1.6.16" - }, - "dependencies": { - "bytes": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", - "dev": true - }, - "raw-body": { - "version": "2.1.7", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", - "dev": true, - "requires": { - "bytes": "2.4.0", - "iconv-lite": "0.4.13", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "2.4.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - } - } - } - } - }, - "boom": { - "version": "2.10.1", - "resolved": "https://npm.corp.appnexus.com/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://npm.corp.appnexus.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://npm.corp.appnexus.com/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.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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-resolve": { - "version": "1.11.2", - "resolved": "https://npm.corp.appnexus.com/browser-resolve/-/browser-resolve-1.11.2.tgz", - "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", - "dev": true, - "requires": { - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://npm.corp.appnexus.com/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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.1", - "evp_bytestokey": "1.0.3" - } - }, - "browserify-des": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/browserify-des/-/browserify-des-1.0.1.tgz", - "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", - "dev": true, - "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "randombytes": "2.0.6" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://npm.corp.appnexus.com/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.1" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "1.0.6" - } - }, - "browserslist": { - "version": "3.2.8", - "resolved": "https://npm.corp.appnexus.com/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "1.0.30000851", - "electron-to-chromium": "1.3.48" - } - }, - "browserstack": { - "version": "1.5.0", - "resolved": "https://npm.corp.appnexus.com/browserstack/-/browserstack-1.5.0.tgz", - "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", - "dev": true, - "requires": { - "https-proxy-agent": "1.0.0" - }, - "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, - "requires": { - "extend": "3.0.1", - "semver": "5.0.3" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "semver": { - "version": "5.0.3", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - } - } - }, - "browserstacktunnel-wrapper": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.2.tgz", - "integrity": "sha512-7w7HYA00qjBtuQH0c5rqW7RbWPHyRROqTZofwNp5G0sKc2fYChsTfbHz3ul8Yd+ffkQvR81m+iPjEB004P6kxQ==", - "dev": true, - "requires": { - "https-proxy-agent": "1.0.0", - "unzip": "0.1.11" - }, - "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, - "requires": { - "extend": "3.0.1", - "semver": "5.0.3" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "semver": { - "version": "5.0.3", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - } - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://npm.corp.appnexus.com/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "1.3.0", - "ieee754": "1.1.11", - "isarray": "1.0.0" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://npm.corp.appnexus.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-from": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", - "dev": true - }, - "buffer-more-ints": { - "version": "0.0.2", - "resolved": "https://npm.corp.appnexus.com/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", - "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", - "dev": true - }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/buildmail/-/buildmail-4.0.1.tgz", - "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", - "dev": true, - "optional": true, - "requires": { - "addressparser": "1.0.1", - "libbase64": "0.1.0", - "libmime": "3.0.0", - "libqp": "1.1.0", - "nodemailer-fetch": "1.6.0", - "nodemailer-shared": "1.1.0", - "punycode": "1.4.1" - } - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "bytes": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/cache-base/-/cache-base-1.0.1.tgz", - "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" - } - }, - "cacheable-request": { - "version": "2.1.4", - "resolved": "https://npm.corp.appnexus.com/cacheable-request/-/cacheable-request-2.1.4.tgz", - "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", - "dev": true, - "requires": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - }, - "dependencies": { - "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true - } - } - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "0.2.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } - }, - "caniuse-lite": { - "version": "1.0.30000851", - "resolved": "https://npm.corp.appnexus.com/caniuse-lite/-/caniuse-lite-1.0.30000851.tgz", - "integrity": "sha512-Y1ecA1cL9wg0vni8t33nBw/poX8ypm+2c3fbwAESj8cm4ufK9CBFQ1+nUK8Dp5dtFo5Fc3JzkI5DKmQbuIo6hQ==", - "dev": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://npm.corp.appnexus.com/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "ccount": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/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": "3.5.0", - "resolved": "https://npm.corp.appnexus.com/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "1.1.0", - "deep-eql": "0.1.3", - "type-detect": "1.0.0" - } - }, - "chai-nightwatch": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", - "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", - "dev": true, - "requires": { - "assertion-error": "1.0.0", - "deep-eql": "0.1.3" - }, - "dependencies": { - "assertion-error": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/assertion-error/-/assertion-error-1.0.0.tgz", - "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", - "dev": true - } - } - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": "0.3.9" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "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" - } - }, - "character-entities": { - "version": "1.2.2", - "resolved": "https://npm.corp.appnexus.com/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", - "dev": true - }, - "character-entities-html4": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", - "dev": true - }, - "character-entities-legacy": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", - "dev": true - }, - "character-reference-invalid": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", - "dev": true - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://npm.corp.appnexus.com/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "2.0.3", - "resolved": "https://npm.corp.appnexus.com/chokidar/-/chokidar-2.0.3.tgz", - "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", - "dev": true, - "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.4", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", - "upath": "1.1.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/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", - "resolved": "https://npm.corp.appnexus.com/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://npm.corp.appnexus.com/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://npm.corp.appnexus.com/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - } - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "clone": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "1.0.0" - } - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "process-nextick-args": "2.0.0", - "readable-stream": "2.3.6" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://npm.corp.appnexus.com/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collapse-white-space": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" - } - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://npm.corp.appnexus.com/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://npm.corp.appnexus.com/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://npm.corp.appnexus.com/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colors": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/colors/-/colors-1.3.0.tgz", - "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==", - "dev": true - }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "4.17.10" - } - }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://npm.corp.appnexus.com/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "comma-separated-tokens": { - "version": "1.0.5", - "resolved": "https://npm.corp.appnexus.com/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", - "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "dev": true, - "requires": { - "trim": "0.0.1" - } - }, - "commander": { - "version": "2.15.1", - "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "compare-versions": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/compare-versions/-/compare-versions-3.2.1.tgz", - "integrity": "sha512-2y2nHcopMG/NAyk6vWXlLs86XeM9sik4jmx1tKIgzMi9/RQ2eo758RGpxQO3ErihHmg0RlQITPqgz73y6s7quA==", - "dev": true - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://npm.corp.appnexus.com/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://npm.corp.appnexus.com/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "compress-commons": { - "version": "0.2.9", - "resolved": "https://npm.corp.appnexus.com/compress-commons/-/compress-commons-0.2.9.tgz", - "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13", - "crc32-stream": "0.3.4", - "node-int64": "0.3.3", - "readable-stream": "1.0.34" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "compressible": { - "version": "2.0.14", - "resolved": "https://npm.corp.appnexus.com/compressible/-/compressible-2.0.14.tgz", - "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", - "dev": true, - "requires": { - "mime-db": "1.34.0" - }, - "dependencies": { - "mime-db": { - "version": "1.34.0", - "resolved": "https://npm.corp.appnexus.com/mime-db/-/mime-db-1.34.0.tgz", - "integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o=", - "dev": true - } - } - }, - "compression": { - "version": "1.5.2", - "resolved": "https://npm.corp.appnexus.com/compression/-/compression-1.5.2.tgz", - "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", - "dev": true, - "requires": { - "accepts": "1.2.13", - "bytes": "2.1.0", - "compressible": "2.0.14", - "debug": "2.2.0", - "on-headers": "1.0.1", - "vary": "1.0.1" - }, - "dependencies": { - "bytes": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://npm.corp.appnexus.com/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "1.1.0", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" - } - }, - "concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", - "dev": true, - "requires": { - "source-map": "0.6.1" - } - }, - "connect": { - "version": "2.30.2", - "resolved": "https://npm.corp.appnexus.com/connect/-/connect-2.30.2.tgz", - "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", - "dev": true, - "requires": { - "basic-auth-connect": "1.0.0", - "body-parser": "1.13.3", - "bytes": "2.1.0", - "compression": "1.5.2", - "connect-timeout": "1.6.2", - "content-type": "1.0.4", - "cookie": "0.1.3", - "cookie-parser": "1.3.5", - "cookie-signature": "1.0.6", - "csurf": "1.8.3", - "debug": "2.2.0", - "depd": "1.0.1", - "errorhandler": "1.4.3", - "express-session": "1.11.3", - "finalhandler": "0.4.0", - "fresh": "0.3.0", - "http-errors": "1.3.1", - "method-override": "2.3.10", - "morgan": "1.6.1", - "multiparty": "3.3.2", - "on-headers": "1.0.1", - "parseurl": "1.3.2", - "pause": "0.1.0", - "qs": "4.0.0", - "response-time": "2.3.2", - "serve-favicon": "2.3.2", - "serve-index": "1.7.3", - "serve-static": "1.10.3", - "type-is": "1.6.16", - "utils-merge": "1.0.0", - "vhost": "3.0.2" - }, - "dependencies": { - "bytes": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", - "dev": true - } - } - }, - "connect-livereload": { - "version": "0.5.4", - "resolved": "https://npm.corp.appnexus.com/connect-livereload/-/connect-livereload-0.5.4.tgz", - "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", - "dev": true - }, - "connect-timeout": { - "version": "1.6.2", - "resolved": "https://npm.corp.appnexus.com/connect-timeout/-/connect-timeout-1.6.2.tgz", - "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", - "dev": true, - "requires": { - "debug": "2.2.0", - "http-errors": "1.3.1", - "ms": "0.7.1", - "on-headers": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "0.1.4" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "continuable-cache": { - "version": "0.3.1", - "resolved": "https://npm.corp.appnexus.com/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", - "dev": true - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://npm.corp.appnexus.com/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" - }, - "cookie": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/cookie/-/cookie-0.1.3.tgz", - "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", - "dev": true - }, - "cookie-parser": { - "version": "1.3.5", - "resolved": "https://npm.corp.appnexus.com/cookie-parser/-/cookie-parser-1.3.5.tgz", - "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", - "dev": true, - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://npm.corp.appnexus.com/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js": { - "version": "2.5.7", - "resolved": "https://npm.corp.appnexus.com/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "coveralls": { - "version": "2.13.3", - "resolved": "https://npm.corp.appnexus.com/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", - "dev": true, - "requires": { - "js-yaml": "3.6.1", - "lcov-parse": "0.0.10", - "log-driver": "1.2.5", - "minimist": "1.2.0", - "request": "2.79.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "crc": { - "version": "3.3.0", - "resolved": "https://npm.corp.appnexus.com/crc/-/crc-3.3.0.tgz", - "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", - "dev": true - }, - "crc32-stream": { - "version": "0.3.4", - "resolved": "https://npm.corp.appnexus.com/crc32-stream/-/crc32-stream-0.3.4.tgz", - "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13", - "readable-stream": "1.0.34" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://npm.corp.appnexus.com/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/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.4", - "ripemd160": "2.0.2", - "sha.js": "2.4.11" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://npm.corp.appnexus.com/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "4.1.3", - "shebang-command": "1.2.0", - "which": "1.3.1" - } - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://npm.corp.appnexus.com/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://npm.corp.appnexus.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "1.0.1", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.3", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "diffie-hellman": "5.0.3", - "inherits": "2.0.3", - "pbkdf2": "3.0.16", - "public-encrypt": "4.0.2", - "randombytes": "2.0.6", - "randomfill": "1.0.4" - } - }, - "csrf": { - "version": "3.0.6", - "resolved": "https://npm.corp.appnexus.com/csrf/-/csrf-3.0.6.tgz", - "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", - "dev": true, - "requires": { - "rndm": "1.2.0", - "tsscmp": "1.0.5", - "uid-safe": "2.1.4" - } - }, - "css": { - "version": "2.2.3", - "resolved": "https://npm.corp.appnexus.com/css/-/css-2.2.3.tgz", - "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", - "requires": { - "inherits": "2.0.3", - "source-map": "0.1.43", - "source-map-resolve": "0.5.2", - "urix": "0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "css-loader": { - "version": "0.9.1", - "resolved": "https://npm.corp.appnexus.com/css-loader/-/css-loader-0.9.1.tgz", - "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", - "dev": true, - "optional": true, - "requires": { - "csso": "1.3.12", - "loader-utils": "0.2.17", - "source-map": "0.1.43" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://npm.corp.appnexus.com/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "optional": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "optional": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "css-parse": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true, - "requires": { - "css": "2.2.3" - } - }, - "css-value": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/css-value/-/css-value-0.0.1.tgz", - "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", - "dev": true - }, - "csso": { - "version": "1.3.12", - "resolved": "https://npm.corp.appnexus.com/csso/-/csso-1.3.12.tgz", - "integrity": "sha1-/GKGlKLTiTiqrEmWdTIY/TEc254=", - "dev": true, - "optional": true - }, - "csurf": { - "version": "1.8.3", - "resolved": "https://npm.corp.appnexus.com/csurf/-/csurf-1.8.3.tgz", - "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", - "dev": true, - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6", - "csrf": "3.0.6", - "http-errors": "1.3.1" - } - }, - "ctype": { - "version": "0.5.3", - "resolved": "https://npm.corp.appnexus.com/ctype/-/ctype-0.5.3.tgz", - "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", - "dev": true - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://npm.corp.appnexus.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "1.0.2" - } - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "d": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "0.10.45" - } - }, - "dargs": { - "version": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://npm.corp.appnexus.com/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true - }, - "date-format": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", - "dev": true - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://npm.corp.appnexus.com/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "debug-fabulous": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", - "requires": { - "debug": "3.1.0", - "memoizee": "0.4.12", - "object-assign": "4.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://npm.corp.appnexus.com/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "1.0.0" - } - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepmerge": { - "version": "0.2.10", - "resolved": "https://npm.corp.appnexus.com/deepmerge/-/deepmerge-0.2.10.tgz", - "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", - "dev": true - }, - "default-require-extensions": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", - "dev": true, - "requires": { - "strip-bom": "3.0.0" - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "1.0.4" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - } - } - }, - "define-properties": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "requires": { - "ast-types": "0.11.5", - "escodegen": "1.8.1", - "esprima": "3.1.3" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, - "del": { - "version": "2.2.2", - "resolved": "https://npm.corp.appnexus.com/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.1", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.0.1.tgz", - "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", - "dev": true - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detab": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/detab/-/detab-2.0.1.tgz", - "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", - "dev": true, - "requires": { - "repeat-string": "1.6.1" - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "2.0.1" - } - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" - }, - "detective": { - "version": "4.7.1", - "resolved": "https://npm.corp.appnexus.com/detective/-/detective-4.7.1.tgz", - "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true, - "requires": { - "acorn": "5.6.2", - "defined": "1.0.0" - } - }, - "di": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", - "dev": true - }, - "diff": { - "version": "1.4.0", - "resolved": "https://npm.corp.appnexus.com/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://npm.corp.appnexus.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" - } - }, - "disparity": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/disparity/-/disparity-2.0.0.tgz", - "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "diff": "1.4.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://npm.corp.appnexus.com/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" - } - }, - "doctrine-temporary-fork": { - "version": "2.0.0-alpha-allowarrayindex", - "resolved": "https://npm.corp.appnexus.com/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", - "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true, - "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" - } - }, - "documentation": { - "version": "5.5.0", - "resolved": "https://npm.corp.appnexus.com/documentation/-/documentation-5.5.0.tgz", - "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "babel-core": "6.26.3", - "babel-generator": "6.26.1", - "babel-plugin-system-import-transformer": "3.1.0", - "babel-plugin-transform-decorators-legacy": "1.3.5", - "babel-preset-env": "1.7.0", - "babel-preset-react": "6.24.1", - "babel-preset-stage-0": "6.24.1", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babelify": "8.0.0", - "babylon": "6.18.0", - "chalk": "2.4.1", - "chokidar": "2.0.3", - "concat-stream": "1.6.2", - "disparity": "2.0.0", - "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", - "get-port": "3.2.0", - "git-url-parse": "8.3.1", - "github-slugger": "1.2.0", - "glob": "7.1.2", - "globals-docs": "2.4.0", - "highlight.js": "9.12.0", - "js-yaml": "3.12.0", - "lodash": "4.17.10", - "mdast-util-inject": "1.1.0", - "micromatch": "3.1.10", - "mime": "1.6.0", - "module-deps-sortable": "4.0.6", - "parse-filepath": "1.0.2", - "pify": "3.0.0", - "read-pkg-up": "3.0.0", - "remark": "9.0.0", - "remark-html": "7.0.0", - "remark-reference-links": "4.0.1", - "remark-toc": "5.0.0", - "remote-origin-url": "0.4.0", - "shelljs": "0.8.2", - "stream-array": "1.1.2", - "strip-json-comments": "2.0.1", - "tiny-lr": "1.1.1", - "unist-builder": "1.0.2", - "unist-util-visit": "1.3.1", - "vfile": "2.3.0", - "vfile-reporter": "4.0.0", - "vfile-sort": "2.1.1", - "vinyl": "2.1.0", - "vinyl-fs": "3.0.3", - "yargs": "9.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://npm.corp.appnexus.com/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.1", - "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.10", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.1" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - }, - "yargs": { - "version": "9.0.1", - "resolved": "https://npm.corp.appnexus.com/yargs/-/yargs-9.0.1.tgz", - "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", - "dev": true, - "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "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.1", - "yargs-parser": "7.0.0" - }, - "dependencies": { - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - } - } - } - } - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://npm.corp.appnexus.com/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "1.0.1", - "ent": "2.2.0", - "extend": "3.0.1", - "void-elements": "2.0.1" - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://npm.corp.appnexus.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", - "dev": true, - "optional": true - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://npm.corp.appnexus.com/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "2.3.6" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://npm.corp.appnexus.com/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "duplexify": { - "version": "3.6.0", - "resolved": "https://npm.corp.appnexus.com/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", - "dev": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "ejs": { - "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/ejs/-/ejs-2.6.1.tgz", - "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.48", - "resolved": "https://npm.corp.appnexus.com/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz", - "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=", - "dev": true - }, - "elliptic": { - "version": "6.4.0", - "resolved": "https://npm.corp.appnexus.com/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "emoji-regex": { - "version": "6.1.1", - "resolved": "https://npm.corp.appnexus.com/emoji-regex/-/emoji-regex-6.1.1.tgz", - "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", - "dev": true - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://npm.corp.appnexus.com/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "engine.io": { - "version": "3.1.5", - "resolved": "https://npm.corp.appnexus.com/engine.io/-/engine.io-3.1.5.tgz", - "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", - "dev": true, - "requires": { - "accepts": "1.3.5", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "3.1.0", - "engine.io-parser": "2.1.2", - "uws": "9.14.0", - "ws": "3.3.3" - }, - "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://npm.corp.appnexus.com/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "2.1.18", - "negotiator": "0.6.1" - } - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://npm.corp.appnexus.com/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://npm.corp.appnexus.com/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } - } - }, - "engine.io-client": { - "version": "3.1.6", - "resolved": "https://npm.corp.appnexus.com/engine.io-client/-/engine.io-client-3.1.6.tgz", - "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "3.1.0", - "engine.io-parser": "2.1.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "3.3.3", - "xmlhttprequest-ssl": "1.5.5", - "yeast": "0.1.2" - } - }, - "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://npm.corp.appnexus.com/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary2": "1.0.3" - } - }, - "enhanced-resolve": { - "version": "3.4.1", - "resolved": "https://npm.corp.appnexus.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", - "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "object-assign": "4.1.1", - "tapable": "0.2.8" - } - }, - "ent": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://npm.corp.appnexus.com/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "1.0.1" - } - }, - "error": { - "version": "7.0.2", - "resolved": "https://npm.corp.appnexus.com/error/-/error-7.0.2.tgz", - "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true, - "requires": { - "string-template": "0.2.1", - "xtend": "4.0.1" - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, - "requires": { - "is-arrayish": "0.2.1" - } - }, - "errorhandler": { - "version": "1.4.3", - "resolved": "https://npm.corp.appnexus.com/errorhandler/-/errorhandler-1.4.3.tgz", - "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", - "dev": true, - "requires": { - "accepts": "1.3.5", - "escape-html": "1.0.3" - }, - "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://npm.corp.appnexus.com/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "2.1.18", - "negotiator": "0.6.1" - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://npm.corp.appnexus.com/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } - } - }, - "es5-ext": { - "version": "0.10.45", - "resolved": "https://npm.corp.appnexus.com/es5-ext/-/es5-ext-0.10.45.tgz", - "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "next-tick": "1.0.0" - } - }, - "es5-shim": { - "version": "4.5.10", - "resolved": "https://npm.corp.appnexus.com/es5-shim/-/es5-shim-4.5.10.tgz", - "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==", - "dev": true - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://npm.corp.appnexus.com/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.45", - "es6-symbol": "3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.45", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-promise": { - "version": "4.2.4", - "resolved": "https://npm.corp.appnexus.com/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://npm.corp.appnexus.com/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "4.2.4" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.45", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://npm.corp.appnexus.com/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.45" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.45", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://npm.corp.appnexus.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://npm.corp.appnexus.com/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" - }, - "dependencies": { - "estraverse": { - "version": "1.9.3", - "resolved": "https://npm.corp.appnexus.com/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "escope": { - "version": "3.6.0", - "resolved": "https://npm.corp.appnexus.com/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.1", - "estraverse": "4.2.0" - } - }, - "eslint": { - "version": "4.19.1", - "resolved": "https://npm.corp.appnexus.com/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", - "dev": true, - "requires": { - "ajv": "5.5.2", - "babel-code-frame": "6.26.0", - "chalk": "2.4.1", - "concat-stream": "1.6.2", - "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.1", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.2", - "globals": "11.5.0", - "ignore": "3.3.8", - "imurmurhash": "0.1.4", - "inquirer": "3.3.0", - "is-resolvable": "1.1.0", - "js-yaml": "3.12.0", - "json-stable-stringify-without-jsonify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.10", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "7.0.0", - "progress": "2.0.0", - "regexpp": "1.1.0", - "require-uncached": "1.0.3", - "semver": "5.5.0", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", - "table": "4.0.2", - "text-table": "0.2.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://npm.corp.appnexus.com/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.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "2.0.2" - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "globals": { - "version": "11.5.0", - "resolved": "https://npm.corp.appnexus.com/globals/-/globals-11.5.0.tgz", - "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://npm.corp.appnexus.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", - "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", - "dev": true - }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://npm.corp.appnexus.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", - "dev": true, - "requires": { - "debug": "2.6.9", - "resolve": "1.7.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", - "dev": true, - "requires": { - "debug": "2.6.9", - "pkg-dir": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "1.1.2" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.12.0", - "resolved": "https://npm.corp.appnexus.com/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz", - "integrity": "sha1-2tMXgSktZmSyUxf9BJ0uKy8CIF0=", - "dev": true, - "requires": { - "contains-path": "0.1.0", - "debug": "2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "0.3.2", - "eslint-module-utils": "2.2.0", - "has": "1.0.3", - "lodash": "4.17.10", - "minimatch": "3.0.4", - "read-pkg-up": "2.0.0", - "resolve": "1.7.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.1" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "2.3.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - } - } - }, - "eslint-plugin-node": { - "version": "5.2.1", - "resolved": "https://npm.corp.appnexus.com/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", - "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", - "dev": true, - "requires": { - "ignore": "3.3.8", - "minimatch": "3.0.4", - "resolve": "1.7.1", - "semver": "5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "eslint-plugin-promise": { - "version": "3.8.0", - "resolved": "https://npm.corp.appnexus.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", - "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", - "dev": true - }, - "eslint-plugin-standard": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", - "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", - "dev": true - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://npm.corp.appnexus.com/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true, - "requires": { - "esrecurse": "4.2.1", - "estraverse": "4.2.0" - } - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://npm.corp.appnexus.com/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "5.6.2", - "acorn-jsx": "3.0.1" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "4.2.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://npm.corp.appnexus.com/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "4.2.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://npm.corp.appnexus.com/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "estree-walker": { - "version": "0.3.1", - "resolved": "https://npm.corp.appnexus.com/estree-walker/-/estree-walker-0.3.1.tgz", - "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "etag": { - "version": "1.7.0", - "resolved": "https://npm.corp.appnexus.com/etag/-/etag-1.7.0.tgz", - "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://npm.corp.appnexus.com/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.45" - } - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://npm.corp.appnexus.com/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", - "pause-stream": "0.0.11", - "split": "0.3.3", - "stream-combiner": "0.0.4", - "through": "2.3.8" - } - }, - "eventemitter3": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", - "dev": true - }, - "events": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.2" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://npm.corp.appnexus.com/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.2", - "strip-eof": "1.0.0" - } - }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://npm.corp.appnexus.com/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "0.2.3", - "array-unique": "0.2.1", - "braces": "0.1.5" - }, - "dependencies": { - "array-slice": { - "version": "0.2.3", - "resolved": "https://npm.corp.appnexus.com/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "0.1.1" - } - }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "0.1.1", - "repeat-string": "0.2.2" - } - }, - "is-number": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://npm.corp.appnexus.com/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://npm.corp.appnexus.com/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": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "3.0.0", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - }, - "express-session": { - "version": "1.11.3", - "resolved": "https://npm.corp.appnexus.com/express-session/-/express-session-1.11.3.tgz", - "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", - "dev": true, - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6", - "crc": "3.3.0", - "debug": "2.2.0", - "depd": "1.0.1", - "on-headers": "1.0.1", - "parseurl": "1.3.2", - "uid-safe": "2.0.0", - "utils-merge": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "uid-safe": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/uid-safe/-/uid-safe-2.0.0.tgz", - "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", - "dev": true, - "requires": { - "base64-url": "1.2.1" - } - } - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/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": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.23", - "tmp": "0.0.33" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": "2.1.2" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "faker": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/faker/-/faker-3.1.0.tgz", - "integrity": "sha1-D5CPr05uwCUk5UpX5DLFwBPgjJ8=", - "dev": true - }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://npm.corp.appnexus.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://npm.corp.appnexus.com/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": "0.7.0" - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" - } - }, - "file-loader": { - "version": "0.8.5", - "resolved": "https://npm.corp.appnexus.com/file-loader/-/file-loader-0.8.5.tgz", - "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", - "dev": true, - "optional": true, - "requires": { - "loader-utils": "0.2.17" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://npm.corp.appnexus.com/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "optional": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - } - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fileset": { - "version": "2.0.3", - "resolved": "https://npm.corp.appnexus.com/fileset/-/fileset-2.0.3.tgz", - "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, - "requires": { - "glob": "7.1.2", - "minimatch": "3.0.4" - } - }, - "fill-keys": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "1.0.1", - "merge-descriptors": "1.0.1" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "finalhandler": { - "version": "0.4.0", - "resolved": "https://npm.corp.appnexus.com/finalhandler/-/finalhandler-0.4.0.tgz", - "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", - "dev": true, - "requires": { - "debug": "2.2.0", - "escape-html": "1.0.2", - "on-finished": "2.3.0", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "escape-html": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/escape-html/-/escape-html-1.0.2.tgz", - "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "1.0.1", - "make-dir": "1.3.0", - "pkg-dir": "2.0.0" - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/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.1.10", - "resolve-dir": "1.0.1" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - } - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "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" - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" - } - }, - "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "follow-redirects": { - "version": "1.5.0", - "resolved": "https://npm.corp.appnexus.com/follow-redirects/-/follow-redirects-1.5.0.tgz", - "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", - "dev": true, - "requires": { - "debug": "3.1.0" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://npm.corp.appnexus.com/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "foreachasync": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/foreachasync/-/foreachasync-3.0.0.tgz", - "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://npm.corp.appnexus.com/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "fork-stream": { - "version": "0.0.4", - "resolved": "https://npm.corp.appnexus.com/fork-stream/-/fork-stream-0.0.4.tgz", - "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "0.2.2" - } - }, - "fresh": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/fresh/-/fresh-0.3.0.tgz", - "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", - "dev": true - }, - "from": { - "version": "0.1.7", - "resolved": "https://npm.corp.appnexus.com/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "from2": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "fs-access": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/fs-access/-/fs-access-1.0.1.tgz", - "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "requires": { - "null-check": "1.0.0" - } - }, - "fs-copy-file-sync": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz", - "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==", - "dev": true - }, - "fs-extra": { - "version": "0.6.4", - "resolved": "https://npm.corp.appnexus.com/fs-extra/-/fs-extra-0.6.4.tgz", - "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", - "dev": true, - "requires": { - "jsonfile": "1.0.1", - "mkdirp": "0.3.5", - "ncp": "0.4.2", - "rimraf": "2.2.8" - }, - "dependencies": { - "mkdirp": { - "version": "0.3.5", - "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", - "dev": true - }, - "rimraf": { - "version": "2.2.8", - "resolved": "https://npm.corp.appnexus.com/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true - } - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "through2": "2.0.3" - } - }, - "fs.extra": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/fs.extra/-/fs.extra-1.3.2.tgz", - "integrity": "sha1-3QI/kwE77iRTHxszUUw3sg/ZM0k=", - "dev": true, - "requires": { - "fs-extra": "0.6.4", - "mkdirp": "0.3.5", - "walk": "2.3.13" - }, - "dependencies": { - "mkdirp": { - "version": "0.3.5", - "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", - "dev": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://npm.corp.appnexus.com/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "2.10.0", - "node-pre-gyp": "0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.2.0", - "nopt": "4.0.1", - "npm-packlist": "1.1.10", - "npmlog": "4.1.2", - "rc": "1.2.7", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar": "4.4.1" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "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.2" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "1.0.1", - "fs-minipass": "1.2.5", - "minipass": "2.2.4", - "minizlib": "1.1.0", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } - }, - "fstream": { - "version": "0.1.31", - "resolved": "https://npm.corp.appnexus.com/fstream/-/fstream-0.1.31.tgz", - "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", - "dev": true, - "requires": { - "graceful-fs": "3.0.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - }, - "dependencies": { - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.4" - } - } - } - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://npm.corp.appnexus.com/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "requires": { - "readable-stream": "1.1.14", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://npm.corp.appnexus.com/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-port": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "get-uri": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", - "dev": true, - "requires": { - "data-uri-to-buffer": "1.2.0", - "debug": "2.6.9", - "extend": "3.0.1", - "file-uri-to-path": "1.0.0", - "ftp": "0.3.10", - "readable-stream": "2.3.6" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://npm.corp.appnexus.com/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://npm.corp.appnexus.com/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "git-up": { - "version": "2.0.10", - "resolved": "https://npm.corp.appnexus.com/git-up/-/git-up-2.0.10.tgz", - "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", - "dev": true, - "requires": { - "is-ssh": "1.3.0", - "parse-url": "1.3.11" - } - }, - "git-url-parse": { - "version": "8.3.1", - "resolved": "https://npm.corp.appnexus.com/git-url-parse/-/git-url-parse-8.3.1.tgz", - "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true, - "requires": { - "git-up": "2.0.10", - "parse-domain": "2.1.1" - } - }, - "github-slugger": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/github-slugger/-/github-slugger-1.2.0.tgz", - "integrity": "sha512-wIaa75k1vZhyPm9yWrD08A5Xnx/V+RmzGrpjQuLemGKSb77Qukiaei58Bogrl/LZSADDfPzKJX8jhLs4CRTl7Q==", - "dev": true, - "requires": { - "emoji-regex": "6.1.1" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://npm.corp.appnexus.com/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://npm.corp.appnexus.com/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "3.0.1", - "glob": "7.1.2", - "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.6", - "remove-trailing-separator": "1.1.0", - "to-absolute-glob": "2.0.2", - "unique-stream": "2.2.1" - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://npm.corp.appnexus.com/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "0.5.2" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://npm.corp.appnexus.com/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "0.1.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "1.0.2", - "which": "1.3.1" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://npm.corp.appnexus.com/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globals-docs": { - "version": "2.4.0", - "resolved": "https://npm.corp.appnexus.com/globals-docs/-/globals-docs-2.4.0.tgz", - "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", - "dev": true - }, - "globby": { - "version": "5.0.0", - "resolved": "https://npm.corp.appnexus.com/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://npm.corp.appnexus.com/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, - "glogg": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", - "dev": true, - "requires": { - "sparkles": "1.0.1" - } - }, - "got": { - "version": "8.3.1", - "resolved": "https://npm.corp.appnexus.com/got/-/got-8.3.1.tgz", - "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", - "dev": true, - "requires": { - "@sindresorhus/is": "0.7.0", - "cacheable-request": "2.1.4", - "decompress-response": "3.3.0", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "into-stream": "3.1.0", - "is-retry-allowed": "1.1.0", - "isurl": "1.0.0", - "lowercase-keys": "1.0.1", - "mimic-response": "1.0.0", - "p-cancelable": "0.4.1", - "p-timeout": "2.0.1", - "pify": "3.0.0", - "safe-buffer": "5.1.2", - "timed-out": "4.0.1", - "url-parse-lax": "3.0.0", - "url-to-options": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.10.3", - "resolved": "https://npm.corp.appnexus.com/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://npm.corp.appnexus.com/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.1.0", - "liftoff": "2.5.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "glob": { - "version": "4.5.3", - "resolved": "https://npm.corp.appnexus.com/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://npm.corp.appnexus.com/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" - } - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.4" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://npm.corp.appnexus.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - } - } - } - }, - "gulp-babel": { - "version": "6.1.3", - "resolved": "https://npm.corp.appnexus.com/gulp-babel/-/gulp-babel-6.1.3.tgz", - "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", - "dev": true, - "requires": { - "babel-core": "6.26.3", - "object-assign": "4.1.1", - "plugin-error": "1.0.1", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "babel-core": { - "version": "6.26.3", - "resolved": "https://npm.corp.appnexus.com/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.1", - "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.10", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "gulp-clean": { - "version": "0.3.2", - "resolved": "https://npm.corp.appnexus.com/gulp-clean/-/gulp-clean-0.3.2.tgz", - "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", - "dev": true, - "requires": { - "gulp-util": "2.2.20", - "rimraf": "2.6.2", - "through2": "0.4.2" - }, - "dependencies": { - "ansi-regex": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", - "dev": true - }, - "ansi-styles": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", - "dev": true - }, - "chalk": { - "version": "0.5.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "requires": { - "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" - } - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://npm.corp.appnexus.com/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" - } - }, - "gulp-util": { - "version": "2.2.20", - "resolved": "https://npm.corp.appnexus.com/gulp-util/-/gulp-util-2.2.20.tgz", - "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", - "dev": true, - "requires": { - "chalk": "0.5.1", - "dateformat": "1.0.12", - "lodash._reinterpolate": "2.4.1", - "lodash.template": "2.4.1", - "minimist": "0.2.0", - "multipipe": "0.1.2", - "through2": "0.5.1", - "vinyl": "0.2.3" - }, - "dependencies": { - "through2": { - "version": "0.5.1", - "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "3.0.0" - } - } - } - }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true, - "requires": { - "ansi-regex": "0.2.1" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", - "dev": true - }, - "lodash.escape": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "2.4.1", - "lodash._reunescapedhtml": "2.4.1", - "lodash.keys": "2.4.1" - } - }, - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - }, - "lodash.template": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true, - "requires": { - "lodash._reinterpolate": "2.4.1", - "lodash.escape": "2.4.1" - } - }, - "minimist": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", - "dev": true - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://npm.corp.appnexus.com/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "0.2.1" - } - }, - "supports-color": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", - "dev": true - }, - "through2": { - "version": "0.4.2", - "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.4.2.tgz", - "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "2.1.2" - }, - "dependencies": { - "xtend": { - "version": "2.1.2", - "resolved": "https://npm.corp.appnexus.com/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "requires": { - "object-keys": "0.4.0" - } - } - } - }, - "vinyl": { - "version": "0.2.3", - "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "0.0.1" - } - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - } - } - }, - "gulp-concat": { - "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "1.1.0", - "through2": "2.0.3", - "vinyl": "2.1.0" - } - }, - "gulp-connect": { - "version": "5.0.0", - "resolved": "https://npm.corp.appnexus.com/gulp-connect/-/gulp-connect-5.0.0.tgz", - "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", - "dev": true, - "requires": { - "connect": "2.30.2", - "connect-livereload": "0.5.4", - "event-stream": "3.3.4", - "gulp-util": "3.0.8", - "tiny-lr": "0.2.1" - }, - "dependencies": { - "body-parser": { - "version": "1.14.2", - "resolved": "https://npm.corp.appnexus.com/body-parser/-/body-parser-1.14.2.tgz", - "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", - "dev": true, - "requires": { - "bytes": "2.2.0", - "content-type": "1.0.4", - "debug": "2.2.0", - "depd": "1.1.2", - "http-errors": "1.3.1", - "iconv-lite": "0.4.13", - "on-finished": "2.3.0", - "qs": "5.2.0", - "raw-body": "2.1.7", - "type-is": "1.6.16" - }, - "dependencies": { - "qs": { - "version": "5.2.0", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-5.2.0.tgz", - "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", - "dev": true - } - } - }, - "bytes": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.2.0.tgz", - "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "5.1.0", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-5.1.0.tgz", - "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", - "dev": true - }, - "raw-body": { - "version": "2.1.7", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", - "dev": true, - "requires": { - "bytes": "2.4.0", - "iconv-lite": "0.4.13", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "2.4.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true - } - } - }, - "tiny-lr": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/tiny-lr/-/tiny-lr-0.2.1.tgz", - "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", - "dev": true, - "requires": { - "body-parser": "1.14.2", - "debug": "2.2.0", - "faye-websocket": "0.10.0", - "livereload-js": "2.3.0", - "parseurl": "1.3.2", - "qs": "5.1.0" - } - } - } - }, - "gulp-documentation": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/gulp-documentation/-/gulp-documentation-3.2.1.tgz", - "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", - "dev": true, - "requires": { - "through2": "2.0.3", - "vinyl": "2.1.0" - } - }, - "gulp-eslint": { - "version": "4.0.2", - "resolved": "https://npm.corp.appnexus.com/gulp-eslint/-/gulp-eslint-4.0.2.tgz", - "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", - "dev": true, - "requires": { - "eslint": "4.19.1", - "fancy-log": "1.3.2", - "plugin-error": "1.0.1" - } - }, - "gulp-footer": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/gulp-footer/-/gulp-footer-1.1.2.tgz", - "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2" - } - }, - "gulp-header": { - "version": "1.8.12", - "resolved": "https://npm.corp.appnexus.com/gulp-header/-/gulp-header-1.8.12.tgz", - "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", - "dev": true, - "requires": { - "concat-with-sourcemaps": "1.1.0", - "lodash.template": "4.4.0", - "through2": "2.0.3" - }, - "dependencies": { - "lodash.template": { - "version": "4.4.0", - "resolved": "https://npm.corp.appnexus.com/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.templatesettings": "4.1.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://npm.corp.appnexus.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0" - } - } - } - }, - "gulp-if": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/gulp-if/-/gulp-if-2.0.2.tgz", - "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true, - "requires": { - "gulp-match": "1.0.3", - "ternary-stream": "2.0.1", - "through2": "2.0.3" - } - }, - "gulp-js-escape": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz", - "integrity": "sha1-HNRF+9AJ4Np2lZoDp/SbNWav+Gg=", - "dev": true, - "requires": { - "through2": "0.6.5" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "gulp-match": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/gulp-match/-/gulp-match-1.0.3.tgz", - "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "gulp-optimize-js": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", - "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "lodash": "4.17.10", - "optimize-js": "1.0.3", - "through2": "2.0.3" - } - }, - "gulp-rename": { - "version": "1.2.3", - "resolved": "https://npm.corp.appnexus.com/gulp-rename/-/gulp-rename-1.2.3.tgz", - "integrity": "sha512-CmdPM0BjJ105QCX1fk+j7NGhiN/1rCl9HLGss+KllBS/tdYadpjTxqdKyh/5fNV+M3yjT1MFz5z93bXdrTyzAw==", - "dev": true - }, - "gulp-replace": { - "version": "0.4.0", - "resolved": "https://npm.corp.appnexus.com/gulp-replace/-/gulp-replace-0.4.0.tgz", - "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", - "dev": true, - "requires": { - "event-stream": "3.0.20", - "istextorbinary": "1.0.2", - "replacestream": "0.1.3" - }, - "dependencies": { - "event-stream": { - "version": "3.0.20", - "resolved": "https://npm.corp.appnexus.com/event-stream/-/event-stream-3.0.20.tgz", - "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", - "dev": true, - "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.0.7", - "pause-stream": "0.0.11", - "split": "0.2.10", - "stream-combiner": "0.0.4", - "through": "2.3.8" - } - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://npm.corp.appnexus.com/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "split": { - "version": "0.2.10", - "resolved": "https://npm.corp.appnexus.com/split/-/split-0.2.10.tgz", - "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "dev": true, - "requires": { - "through": "2.3.8" - } - } - } - }, - "gulp-shell": { - "version": "0.5.2", - "resolved": "https://npm.corp.appnexus.com/gulp-shell/-/gulp-shell-0.5.2.tgz", - "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true, - "requires": { - "async": "1.5.2", - "gulp-util": "3.0.8", - "lodash": "4.17.10", - "through2": "2.0.3" - } - }, - "gulp-sourcemaps": { - "version": "2.6.4", - "resolved": "https://npm.corp.appnexus.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", - "requires": { - "@gulp-sourcemaps/identity-map": "1.0.1", - "@gulp-sourcemaps/map-sources": "1.0.0", - "acorn": "5.6.2", - "convert-source-map": "1.5.1", - "css": "2.2.3", - "debug-fabulous": "1.1.0", - "detect-newline": "2.1.0", - "graceful-fs": "4.1.11", - "source-map": "0.6.1", - "strip-bom-string": "1.0.0", - "through2": "2.0.3" - } - }, - "gulp-uglify": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/gulp-uglify/-/gulp-uglify-3.0.0.tgz", - "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", - "dev": true, - "requires": { - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash": "4.17.10", - "make-error-cause": "1.2.2", - "through2": "2.0.3", - "uglify-js": "3.4.0", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "uglify-js": { - "version": "3.4.0", - "resolved": "https://npm.corp.appnexus.com/uglify-js/-/uglify-js-3.4.0.tgz", - "integrity": "sha512-Jcf5naPkX3rVPSQpRn9Vm6Rr572I1gTtR9LnqKgXjmOgfYQ/QS0V2WRStFR53Bdj520M66aCZqt9uzYXgtGrJQ==", - "dev": true, - "requires": { - "commander": "2.15.1", - "source-map": "0.6.1" - } - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://npm.corp.appnexus.com/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "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.2", - "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.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulp-webdriver": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", - "integrity": "sha1-mM6Bz5rganoZB7htEPaThvQ4Oi0=", - "dev": true, - "requires": { - "dargs": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", - "deepmerge": "0.2.10", - "gulp-util": "3.0.8", - "through2": "0.6.5", - "webdriverio": "3.4.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://npm.corp.appnexus.com/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "1.0.1" - } - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://npm.corp.appnexus.com/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, - "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://npm.corp.appnexus.com/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.15.1", - "is-my-json-valid": "2.17.2", - "pinkie-promise": "2.0.1" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dev": true, - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "1.0.1" - } - }, - "has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://npm.corp.appnexus.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://npm.corp.appnexus.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "requires": { - "has-symbol-support-x": "1.4.2" - } - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/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.1" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://npm.corp.appnexus.com/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://npm.corp.appnexus.com/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" - } - }, - "hast-util-is-element": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", - "integrity": "sha1-P3IWl4sq4U2YdJh4eCZ18zvjzgA=", - "dev": true - }, - "hast-util-sanitize": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", - "integrity": "sha1-0QvWdXoh5ZwTq8iuNTDdO219Z54=", - "dev": true, - "requires": { - "xtend": "4.0.1" - } - }, - "hast-util-to-html": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", - "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", - "dev": true, - "requires": { - "ccount": "1.0.3", - "comma-separated-tokens": "1.0.5", - "hast-util-is-element": "1.0.0", - "hast-util-whitespace": "1.0.0", - "html-void-elements": "1.0.3", - "kebab-case": "1.0.0", - "property-information": "3.2.0", - "space-separated-tokens": "1.1.2", - "stringify-entities": "1.3.2", - "unist-util-is": "2.1.2", - "xtend": "4.0.1" - } - }, - "hast-util-whitespace": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", - "integrity": "sha1-vQlpGWJdKTbh/xe8Tff9cn8X7Ok=", - "dev": true - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://npm.corp.appnexus.com/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "highlight.js": { - "version": "9.12.0", - "resolved": "https://npm.corp.appnexus.com/highlight.js/-/highlight.js-9.12.0.tgz", - "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", - "dev": true - }, - "hipchat-notifier": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", - "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", - "dev": true, - "optional": true, - "requires": { - "lodash": "4.17.10", - "request": "2.79.0" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://npm.corp.appnexus.com/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "1.0.0" - } - }, - "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://npm.corp.appnexus.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", - "dev": true - }, - "html-void-elements": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/html-void-elements/-/html-void-elements-1.0.3.tgz", - "integrity": "sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==", - "dev": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://npm.corp.appnexus.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true - }, - "http-errors": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/http-errors/-/http-errors-1.3.1.tgz", - "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "statuses": "1.5.0" - } - }, - "http-parser-js": { - "version": "0.4.13", - "resolved": "https://npm.corp.appnexus.com/http-parser-js/-/http-parser-js-0.4.13.tgz", - "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", - "dev": true - }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://npm.corp.appnexus.com/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "3.1.0", - "follow-redirects": "1.5.0", - "requires-port": "1.0.0" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.14.2" - } - }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://npm.corp.appnexus.com/httpntlm/-/httpntlm-1.6.1.tgz", - "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true, - "requires": { - "httpreq": "0.4.24", - "underscore": "1.7.0" - } - }, - "httpreq": { - "version": "0.4.24", - "resolved": "https://npm.corp.appnexus.com/httpreq/-/httpreq-0.4.24.tgz", - "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "dev": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - } - }, - "iconv-lite": { - "version": "0.4.11", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.11.tgz", - "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", - "dev": true - }, - "ieee754": { - "version": "1.1.11", - "resolved": "https://npm.corp.appnexus.com/ieee754/-/ieee754-1.1.11.tgz", - "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", - "dev": true - }, - "ignore": { - "version": "3.3.8", - "resolved": "https://npm.corp.appnexus.com/ignore/-/ignore-3.3.8.tgz", - "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", - "dev": true - }, - "ignore-loader": { - "version": "0.1.2", - "resolved": "https://npm.corp.appnexus.com/ignore-loader/-/ignore-loader-0.1.2.tgz", - "integrity": "sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://npm.corp.appnexus.com/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "2.0.1" - } - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://npm.corp.appnexus.com/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "dev": true, - "optional": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://npm.corp.appnexus.com/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://npm.corp.appnexus.com/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://npm.corp.appnexus.com/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://npm.corp.appnexus.com/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "requires": { - "ansi-escapes": "3.1.0", - "chalk": "2.4.1", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.2.0", - "figures": "2.0.0", - "lodash": "4.17.10", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "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" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "into-stream": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/into-stream/-/into-stream-3.1.0.tgz", - "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, - "requires": { - "from2": "2.3.0", - "p-is-promise": "1.1.0" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://npm.corp.appnexus.com/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "1.3.1" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://npm.corp.appnexus.com/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "1.0.0", - "is-windows": "1.0.2" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-alphabetical": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz", - "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", - "dev": true - }, - "is-alphanumeric": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", - "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", - "dev": true - }, - "is-alphanumerical": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", - "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true, - "requires": { - "is-alphabetical": "1.0.2", - "is-decimal": "1.0.2" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "1.11.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://npm.corp.appnexus.com/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "1.1.1" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-decimal": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://npm.corp.appnexus.com/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" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-generator": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/is-generator/-/is-generator-1.0.3.tgz", - "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "is-hexadecimal": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", - "dev": true - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.17.2", - "resolved": "https://npm.corp.appnexus.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", - "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "is-my-ip-valid": "1.0.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-object": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true - }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, - "requires": { - "is-number": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "1.0.1" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "1.0.0" - } - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, - "is-ssh": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/is-ssh/-/is-ssh-1.3.0.tgz", - "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", - "dev": true, - "requires": { - "protocols": "1.4.6" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-whitespace-character": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", - "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-word-character": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-word-character/-/is-word-character-1.0.2.tgz", - "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://npm.corp.appnexus.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://npm.corp.appnexus.com/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://npm.corp.appnexus.com/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "glob": "5.0.15", - "handlebars": "4.0.11", - "js-yaml": "3.6.1", - "mkdirp": "0.5.1", - "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": { - "glob": { - "version": "5.0.15", - "resolved": "https://npm.corp.appnexus.com/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "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": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://npm.corp.appnexus.com/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "istanbul-api": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/istanbul-api/-/istanbul-api-1.3.1.tgz", - "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", - "dev": true, - "requires": { - "async": "2.6.1", - "compare-versions": "3.2.1", - "fileset": "2.0.3", - "istanbul-lib-coverage": "1.2.0", - "istanbul-lib-hook": "1.2.1", - "istanbul-lib-instrument": "1.10.1", - "istanbul-lib-report": "1.1.4", - "istanbul-lib-source-maps": "1.2.5", - "istanbul-reports": "1.3.0", - "js-yaml": "3.12.0", - "mkdirp": "0.5.1", - "once": "1.4.0" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.10" - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" - } - } - } - }, - "istanbul-instrumenter-loader": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", - "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true, - "requires": { - "convert-source-map": "1.5.1", - "istanbul-lib-instrument": "1.10.1", - "loader-utils": "1.1.0", - "schema-utils": "0.3.0" - } - }, - "istanbul-lib-coverage": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", - "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "1.2.1", - "resolved": "https://npm.corp.appnexus.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz", - "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==", - "dev": true, - "requires": { - "append-transform": "1.0.0" - } - }, - "istanbul-lib-instrument": { - "version": "1.10.1", - "resolved": "https://npm.corp.appnexus.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", - "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", - "dev": true, - "requires": { - "babel-generator": "6.26.1", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "istanbul-lib-coverage": "1.2.0", - "semver": "5.5.0" - } - }, - "istanbul-lib-report": { - "version": "1.1.4", - "resolved": "https://npm.corp.appnexus.com/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", - "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "1.2.0", - "mkdirp": "0.5.1", - "path-parse": "1.0.5", - "supports-color": "3.2.3" - }, - "dependencies": { - "has-flag": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "1.2.5", - "resolved": "https://npm.corp.appnexus.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz", - "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==", - "dev": true, - "requires": { - "debug": "3.1.0", - "istanbul-lib-coverage": "1.2.0", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/istanbul-reports/-/istanbul-reports-1.3.0.tgz", - "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", - "dev": true, - "requires": { - "handlebars": "4.0.11" - } - }, - "istextorbinary": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/istextorbinary/-/istextorbinary-1.0.2.tgz", - "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", - "dev": true, - "requires": { - "binaryextensions": "1.0.1", - "textextensions": "1.0.2" - } - }, - "isurl": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "requires": { - "has-to-string-tag-x": "1.4.1", - "is-object": "1.0.1" - } - }, - "jade": { - "version": "0.26.3", - "resolved": "https://npm.corp.appnexus.com/jade/-/jade-0.26.3.tgz", - "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", - "dev": true, - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" - }, - "dependencies": { - "commander": { - "version": "0.6.1", - "resolved": "https://npm.corp.appnexus.com/commander/-/commander-0.6.1.tgz", - "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", - "dev": true - }, - "mkdirp": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", - "dev": true - } - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://npm.corp.appnexus.com/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.6.1", - "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.6.1.tgz", - "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", - "dev": true, - "requires": { - "argparse": "1.0.10", - "esprima": "2.7.3" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "json-loader": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://npm.corp.appnexus.com/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://npm.corp.appnexus.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://npm.corp.appnexus.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json3": { - "version": "3.3.2", - "resolved": "https://npm.corp.appnexus.com/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "https://npm.corp.appnexus.com/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonfile": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/jsonfile/-/jsonfile-1.0.1.tgz", - "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", - "dev": true - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://npm.corp.appnexus.com/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "JSONStream": { - "version": "1.3.3", - "resolved": "https://npm.corp.appnexus.com/JSONStream/-/JSONStream-1.3.3.tgz", - "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==", - "dev": true, - "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://npm.corp.appnexus.com/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "just-clone": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/just-clone/-/just-clone-1.0.2.tgz", - "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" - }, - "just-extend": { - "version": "1.1.27", - "resolved": "https://npm.corp.appnexus.com/just-extend/-/just-extend-1.1.27.tgz", - "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", - "dev": true - }, - "karma": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/karma/-/karma-2.0.2.tgz", - "integrity": "sha1-TS25QChQpmVR+nhLAWT7CCTtjEs=", - "dev": true, - "requires": { - "bluebird": "3.5.1", - "body-parser": "1.18.3", - "chokidar": "1.7.0", - "colors": "1.3.0", - "combine-lists": "1.0.1", - "connect": "3.6.6", - "core-js": "2.5.7", - "di": "0.0.1", - "dom-serialize": "2.2.1", - "expand-braces": "0.1.2", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "http-proxy": "1.17.0", - "isbinaryfile": "3.0.2", - "lodash": "4.17.10", - "log4js": "2.8.0", - "mime": "1.6.0", - "minimatch": "3.0.4", - "optimist": "0.6.1", - "qjobs": "1.2.0", - "range-parser": "1.2.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.2", - "socket.io": "2.0.4", - "source-map": "0.6.1", - "tmp": "0.0.33", - "useragent": "2.2.1" - }, - "dependencies": { - "anymatch": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://npm.corp.appnexus.com/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", - "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "1.6.16" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://npm.corp.appnexus.com/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.2" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://npm.corp.appnexus.com/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.2.4", - "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.1.0" - } - }, - "connect": { - "version": "3.6.6", - "resolved": "https://npm.corp.appnexus.com/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "1.3.2", - "utils-merge": "1.0.1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "finalhandler": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" - }, - "dependencies": { - "statuses": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - } - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "qs": { - "version": "6.5.2", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - } - } - }, - "karma-babel-preprocessor": { - "version": "6.0.1", - "resolved": "https://npm.corp.appnexus.com/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", - "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true, - "requires": { - "babel-core": "6.22.0" - } - }, - "karma-browserstack-launcher": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", - "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", - "dev": true, - "requires": { - "browserstack": "1.5.0", - "browserstacktunnel-wrapper": "2.0.2", - "q": "1.5.1" - }, - "dependencies": { - "q": { - "version": "1.5.1", - "resolved": "https://npm.corp.appnexus.com/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - } - } - }, - "karma-chai": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/karma-chai/-/karma-chai-0.1.0.tgz", - "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", - "dev": true - }, - "karma-chrome-launcher": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true, - "requires": { - "fs-access": "1.0.1", - "which": "1.3.1" - } - }, - "karma-coverage-istanbul-reporter": { - "version": "1.4.3", - "resolved": "https://npm.corp.appnexus.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", - "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", - "dev": true, - "requires": { - "istanbul-api": "1.3.1", - "minimatch": "3.0.4" - } - }, - "karma-es5-shim": { - "version": "0.0.4", - "resolved": "https://npm.corp.appnexus.com/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", - "integrity": "sha1-zdADM8znfC5M4D46yT8vjs0fuVI=", - "dev": true, - "requires": { - "es5-shim": "4.5.10" - } - }, - "karma-firefox-launcher": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", - "dev": true - }, - "karma-ie-launcher": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", - "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true, - "requires": { - "lodash": "4.17.10" - } - }, - "karma-mocha": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/karma-mocha/-/karma-mocha-1.3.0.tgz", - "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true, - "requires": { - "minimist": "1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "karma-mocha-reporter": { - "version": "2.2.5", - "resolved": "https://npm.corp.appnexus.com/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", - "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", - "dev": true, - "requires": { - "chalk": "2.4.1", - "log-symbols": "2.2.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "karma-opera-launcher": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/karma-opera-launcher/-/karma-opera-launcher-1.0.0.tgz", - "integrity": "sha1-+lFihTGh0L6EstjcDX7iCfyP+Ro=", - "dev": true - }, - "karma-requirejs": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/karma-requirejs/-/karma-requirejs-1.1.0.tgz", - "integrity": "sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=", - "dev": true - }, - "karma-safari-launcher": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz", - "integrity": "sha1-lpgqLMR9BmquccVTursoMZEVos4=", - "dev": true - }, - "karma-script-launcher": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/karma-script-launcher/-/karma-script-launcher-1.0.0.tgz", - "integrity": "sha1-zQF8TeXvCeWp2nkydhdhCN1LVC0=", - "dev": true - }, - "karma-sinon": { - "version": "1.0.5", - "resolved": "https://npm.corp.appnexus.com/karma-sinon/-/karma-sinon-1.0.5.tgz", - "integrity": "sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo=", - "dev": true - }, - "karma-sourcemap-loader": { - "version": "0.3.7", - "resolved": "https://npm.corp.appnexus.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", - "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11" - } - }, - "karma-spec-reporter": { - "version": "0.0.31", - "resolved": "https://npm.corp.appnexus.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", - "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true, - "requires": { - "colors": "1.3.0" - } - }, - "karma-webpack": { - "version": "2.0.13", - "resolved": "https://npm.corp.appnexus.com/karma-webpack/-/karma-webpack-2.0.13.tgz", - "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", - "dev": true, - "requires": { - "async": "2.6.1", - "babel-runtime": "6.26.0", - "loader-utils": "1.1.0", - "lodash": "4.17.10", - "source-map": "0.5.7", - "webpack-dev-middleware": "1.12.2" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.10" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "kebab-case": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/kebab-case/-/kebab-case-1.0.0.tgz", - "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=", - "dev": true - }, - "keyv": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/keyv/-/keyv-3.0.0.tgz", - "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "2.3.6" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "1.0.0" - } - }, - "lcov-parse": { - "version": "0.0.10", - "resolved": "https://npm.corp.appnexus.com/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true - }, - "lead": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "1.0.3" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" - } - }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/libbase64/-/libbase64-0.1.0.tgz", - "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/libmime/-/libmime-3.0.0.tgz", - "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", - "dev": true, - "requires": { - "iconv-lite": "0.4.15", - "libbase64": "0.1.0", - "libqp": "1.1.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.15", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true - } - } - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/libqp/-/libqp-1.1.0.tgz", - "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://npm.corp.appnexus.com/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "3.0.1", - "findup-sync": "2.0.0", - "fined": "1.1.0", - "flagged-respawn": "1.0.0", - "is-plain-object": "2.0.4", - "object.map": "1.0.1", - "rechoir": "0.6.2", - "resolve": "1.7.1" - } - }, - "livereload-js": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/livereload-js/-/livereload-js-2.3.0.tgz", - "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", - "dev": true - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "4.0.0", - "pify": "3.0.0", - "strip-bom": "3.0.0" - } - }, - "loader-runner": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", - "dev": true - }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" - } - }, - "localtunnel": { - "version": "1.9.0", - "resolved": "https://npm.corp.appnexus.com/localtunnel/-/localtunnel-1.9.0.tgz", - "integrity": "sha512-wCIiIHJ8kKIcWkTQE3m1VRABvsH2ZuOkiOpZUofUCf6Q42v3VIZ+Q0YfX1Z4sYDRj0muiKL1bLvz1FeoxsPO0w==", - "dev": true, - "requires": { - "axios": "0.17.1", - "debug": "2.6.8", - "openurl": "1.1.1", - "yargs": "6.6.0" - }, - "dependencies": { - "axios": { - "version": "0.17.1", - "resolved": "https://npm.corp.appnexus.com/axios/-/axios-0.17.1.tgz", - "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", - "dev": true, - "requires": { - "follow-redirects": "1.5.0", - "is-buffer": "1.1.6" - } - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "debug": { - "version": "2.6.8", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://npm.corp.appnexus.com/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "1.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.1" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/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.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "yargs": { - "version": "6.6.0", - "resolved": "https://npm.corp.appnexus.com/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "dev": true, - "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "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": "4.2.1" - } - }, - "yargs-parser": { - "version": "4.2.1", - "resolved": "https://npm.corp.appnexus.com/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true, - "requires": { - "camelcase": "3.0.0" - } - } - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - } - }, - "lodash": { - "version": "4.17.10", - "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - }, - "lodash._arraycopy": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", - "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", - "dev": true - }, - "lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._baseclone": { - "version": "3.3.0", - "resolved": "https://npm.corp.appnexus.com/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", - "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "dev": true, - "requires": { - "lodash._arraycopy": "3.0.0", - "lodash._arrayeach": "3.0.0", - "lodash._baseassign": "3.2.0", - "lodash._basefor": "3.0.3", - "lodash.isarray": "3.0.4", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://npm.corp.appnexus.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._basefor": { - "version": "3.0.3", - "resolved": "https://npm.corp.appnexus.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz", - "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "lodash._escapehtmlchar": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", - "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true, - "requires": { - "lodash._htmlescapes": "2.4.1" - } - }, - "lodash._escapestringchar": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", - "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://npm.corp.appnexus.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._htmlescapes": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://npm.corp.appnexus.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._isnative": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", - "dev": true - }, - "lodash._objecttypes": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._reunescapedhtml": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", - "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "requires": { - "lodash._htmlescapes": "2.4.1", - "lodash.keys": "2.4.1" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - } - } - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash._shimkeys": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1" - } - }, - "lodash._stack": { - "version": "4.1.3", - "resolved": "https://npm.corp.appnexus.com/lodash._stack/-/lodash._stack-4.1.3.tgz", - "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", - "dev": true - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://npm.corp.appnexus.com/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "lodash.clone": { - "version": "3.0.3", - "resolved": "https://npm.corp.appnexus.com/lodash.clone/-/lodash.clone-3.0.3.tgz", - "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true, - "requires": { - "lodash._baseclone": "3.3.0", - "lodash._bindcallback": "3.0.1", - "lodash._isiterateecall": "3.0.9" - } - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://npm.corp.appnexus.com/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, - "lodash.defaults": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/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" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - } - } - }, - "lodash.defaultsdeep": { - "version": "4.3.2", - "resolved": "https://npm.corp.appnexus.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", - "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", - "dev": true, - "requires": { - "lodash._baseclone": "4.5.7", - "lodash._stack": "4.1.3", - "lodash.isplainobject": "4.0.6", - "lodash.keysin": "4.2.0", - "lodash.mergewith": "4.6.1", - "lodash.rest": "4.0.5" - }, - "dependencies": { - "lodash._baseclone": { - "version": "4.5.7", - "resolved": "https://npm.corp.appnexus.com/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", - "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", - "dev": true - } - } - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://npm.corp.appnexus.com/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://npm.corp.appnexus.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isobject": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz", - "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1" - } - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://npm.corp.appnexus.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://npm.corp.appnexus.com/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.keysin": { - "version": "4.2.0", - "resolved": "https://npm.corp.appnexus.com/lodash.keysin/-/lodash.keysin-4.2.0.tgz", - "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", - "dev": true - }, - "lodash.mergewith": { - "version": "4.6.1", - "resolved": "https://npm.corp.appnexus.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", - "dev": true - }, - "lodash.rest": { - "version": "4.0.5", - "resolved": "https://npm.corp.appnexus.com/lodash.rest/-/lodash.rest-4.0.5.tgz", - "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://npm.corp.appnexus.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://npm.corp.appnexus.com/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, - "lodash.values": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash.values/-/lodash.values-2.4.1.tgz", - "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", - "dev": true, - "requires": { - "lodash.keys": "2.4.1" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - } - } - }, - "log-driver": { - "version": "1.2.5", - "resolved": "https://npm.corp.appnexus.com/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "2.4.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "log4js": { - "version": "2.8.0", - "resolved": "https://npm.corp.appnexus.com/log4js/-/log4js-2.8.0.tgz", - "integrity": "sha512-PjsaE4ElS0e2jWOY14Ef2PrC1Y+fny4AWPPT3xD6+2k2Aa5golhqJ4DSzP+5kXRL5bSw/5j1ocU5A9ceaxZeGA==", - "dev": true, - "requires": { - "amqplib": "0.5.2", - "axios": "0.15.3", - "circular-json": "0.5.4", - "date-format": "1.2.0", - "debug": "3.1.0", - "hipchat-notifier": "1.1.0", - "loggly": "1.1.1", - "mailgun-js": "0.18.0", - "nodemailer": "2.7.2", - "redis": "2.8.0", - "semver": "5.5.0", - "slack-node": "0.2.0", - "streamroller": "0.7.0" - }, - "dependencies": { - "circular-json": { - "version": "0.5.4", - "resolved": "https://npm.corp.appnexus.com/circular-json/-/circular-json-0.5.4.tgz", - "integrity": "sha512-vnJA8KS0BfOihugYEUkLRcnmq21FbuivbxgzDLXNs3zIk4KllV4Mx4UuTzBXht9F00C7QfD1YqMXg1zP6EXpig==", - "dev": true - } - } - }, - "loggly": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/loggly/-/loggly-1.1.1.tgz", - "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", - "dev": true, - "optional": true, - "requires": { - "json-stringify-safe": "5.0.1", - "request": "2.75.0", - "timespan": "2.3.0" - }, - "dependencies": { - "bl": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/bl/-/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "2.0.6" - } - }, - "form-data": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-2.0.0.tgz", - "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - } - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://npm.corp.appnexus.com/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://npm.corp.appnexus.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true, - "optional": true - }, - "qs": { - "version": "6.2.3", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.75.0", - "resolved": "https://npm.corp.appnexus.com/request/-/request-2.75.0.tgz", - "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.7.0", - "bl": "1.1.2", - "caseless": "0.11.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.0.0", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "node-uuid": "1.4.8", - "oauth-sign": "0.8.2", - "qs": "6.2.3", - "stringstream": "0.0.6", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.4.3" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, - "lolex": { - "version": "2.7.0", - "resolved": "https://npm.corp.appnexus.com/lolex/-/lolex-2.7.0.tgz", - "integrity": "sha512-uJkH2e0BVfU5KOJUevbTOtpDduooSarH5PopO+LfM/vZf8Z9sJzODqKev804JYM2i++ktJfUmC1le4LwFQ1VMg==", - "dev": true - }, - "longest": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "longest-streak": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", - "dev": true - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, - "requires": { - "js-tokens": "3.0.2" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://npm.corp.appnexus.com/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "requires": { - "es5-ext": "0.10.45" - } - }, - "magic-string": { - "version": "0.16.0", - "resolved": "https://npm.corp.appnexus.com/magic-string/-/magic-string-0.16.0.tgz", - "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", - "dev": true, - "requires": { - "vlq": "0.2.3" - } - }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/mailcomposer/-/mailcomposer-4.0.1.tgz", - "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", - "dev": true, - "optional": true, - "requires": { - "buildmail": "4.0.1", - "libmime": "3.0.0" - } - }, - "mailgun-js": { - "version": "0.18.0", - "resolved": "https://npm.corp.appnexus.com/mailgun-js/-/mailgun-js-0.18.0.tgz", - "integrity": "sha512-o0P6jjZlx5CQj12tvVgDTbgjTqVN0+5h6/6P1+3c6xmozVKBwniQ6Qt3MkCSF0+ueVTbobAfWyGpWRZMJu8t1g==", - "dev": true, - "optional": true, - "requires": { - "async": "2.6.1", - "debug": "3.1.0", - "form-data": "2.3.2", - "inflection": "1.12.0", - "is-stream": "1.1.0", - "path-proxy": "1.0.0", - "promisify-call": "2.0.4", - "proxy-agent": "3.0.0", - "tsscmp": "1.0.5" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "optional": true, - "requires": { - "lodash": "4.17.10" - } - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - } - } - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "3.0.0" - } - }, - "make-error": { - "version": "1.3.4", - "resolved": "https://npm.corp.appnexus.com/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", - "dev": true - }, - "make-error-cause": { - "version": "1.2.2", - "resolved": "https://npm.corp.appnexus.com/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "1.3.4" - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://npm.corp.appnexus.com/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "1.0.1" - } - }, - "markdown-escapes": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", - "dev": true - }, - "markdown-table": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/markdown-table/-/markdown-table-1.1.2.tgz", - "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", - "dev": true - }, - "match-stream": { - "version": "0.0.2", - "resolved": "https://npm.corp.appnexus.com/match-stream/-/match-stream-0.0.2.tgz", - "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", - "dev": true, - "requires": { - "buffers": "0.1.1", - "readable-stream": "1.0.34" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "math-random": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", - "dev": true - }, - "md5.js": { - "version": "1.3.4", - "resolved": "https://npm.corp.appnexus.com/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true, - "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" - } - }, - "mdast-util-compact": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", - "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", - "dev": true, - "requires": { - "unist-util-modify-children": "1.1.2", - "unist-util-visit": "1.3.1" - } - }, - "mdast-util-definitions": { - "version": "1.2.2", - "resolved": "https://npm.corp.appnexus.com/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", - "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", - "dev": true, - "requires": { - "unist-util-visit": "1.3.1" - } - }, - "mdast-util-inject": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", - "integrity": "sha1-2wa4tYW+lZotzS+H9HK6m3VvNnU=", - "dev": true, - "requires": { - "mdast-util-to-string": "1.0.4" - } - }, - "mdast-util-to-hast": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/mdast-util-to-hast/-/mdast-util-to-hast-3.0.1.tgz", - "integrity": "sha512-+eimV/12kdg0/T0EEfcK7IsDbSu2auVm92z5jdSEQ3DHF2HiU4OHmX9ir5wpQajr73nwabdxrUoxREvW2zVFFw==", - "dev": true, - "requires": { - "collapse-white-space": "1.0.4", - "detab": "2.0.1", - "mdast-util-definitions": "1.2.2", - "mdurl": "1.0.1", - "trim": "0.0.1", - "trim-lines": "1.1.1", - "unist-builder": "1.0.2", - "unist-util-generated": "1.1.2", - "unist-util-position": "3.0.1", - "unist-util-visit": "1.3.1", - "xtend": "4.0.1" - } - }, - "mdast-util-to-string": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", - "integrity": "sha1-XEVch4yTVfDB5/PotxnPWDaRrPs=", - "dev": true - }, - "mdast-util-toc": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", - "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", - "dev": true, - "requires": { - "github-slugger": "1.2.0", - "mdast-util-to-string": "1.0.4", - "unist-util-visit": "1.3.1" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "mem": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "1.2.0" - } - }, - "memoizee": { - "version": "0.4.12", - "resolved": "https://npm.corp.appnexus.com/memoizee/-/memoizee-0.4.12.tgz", - "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.45", - "es6-weak-map": "2.0.2", - "event-emitter": "0.3.5", - "is-promise": "2.1.0", - "lru-queue": "0.1.0", - "next-tick": "1.0.0", - "timers-ext": "0.1.5" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://npm.corp.appnexus.com/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "0.1.7", - "readable-stream": "2.3.6" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://npm.corp.appnexus.com/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.1" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/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.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "2.3.6" - } - }, - "method-override": { - "version": "2.3.10", - "resolved": "https://npm.corp.appnexus.com/method-override/-/method-override-2.3.10.tgz", - "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", - "dev": true, - "requires": { - "debug": "2.6.9", - "methods": "1.1.2", - "parseurl": "1.3.2", - "vary": "1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - } - } - }, - "methods": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://npm.corp.appnexus.com/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.2", - "nanomatch": "1.2.9", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://npm.corp.appnexus.com/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.33.0", - "resolved": "https://npm.corp.appnexus.com/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.18", - "resolved": "https://npm.corp.appnexus.com/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true, - "requires": { - "mime-db": "1.33.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "mimic-response": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/mimic-response/-/mimic-response-1.0.0.tgz", - "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=", - "dev": true - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mkpath": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/mkpath/-/mkpath-1.0.0.tgz", - "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", - "dev": true - }, - "mocha": { - "version": "2.2.5", - "resolved": "https://npm.corp.appnexus.com/mocha/-/mocha-2.2.5.tgz", - "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", - "dev": true, - "requires": { - "commander": "2.3.0", - "debug": "2.0.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.3", - "growl": "1.8.1", - "jade": "0.26.3", - "mkdirp": "0.5.0", - "supports-color": "1.2.1" - }, - "dependencies": { - "commander": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.3.0.tgz", - "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", - "dev": true - }, - "debug": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.0.0.tgz", - "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", - "dev": true, - "requires": { - "ms": "0.6.2" - } - }, - "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", - "dev": true - }, - "glob": { - "version": "3.2.3", - "resolved": "https://npm.corp.appnexus.com/glob/-/glob-3.2.3.tgz", - "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", - "dev": true, - "requires": { - "graceful-fs": "2.0.3", - "inherits": "2.0.3", - "minimatch": "0.2.14" - } - }, - "graceful-fs": { - "version": "2.0.3", - "resolved": "https://npm.corp.appnexus.com/graceful-fs/-/graceful-fs-2.0.3.tgz", - "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", - "dev": true - }, - "growl": { - "version": "1.8.1", - "resolved": "https://npm.corp.appnexus.com/growl/-/growl-1.8.1.tgz", - "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - }, - "mkdirp": { - "version": "0.5.0", - "resolved": "https://npm.corp.appnexus.com/mkdirp/-/mkdirp-0.5.0.tgz", - "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "0.6.2", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.6.2.tgz", - "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", - "dev": true - }, - "supports-color": { - "version": "1.2.1", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-1.2.1.tgz", - "integrity": "sha1-Eu4hUHCGzZjBBY2ewPSsR2t687I=", - "dev": true - } - } - }, - "mocha-nightwatch": { - "version": "3.2.2", - "resolved": "https://npm.corp.appnexus.com/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", - "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.5", - "glob": "7.0.5", - "growl": "1.9.2", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "glob": { - "version": "7.0.5", - "resolved": "https://npm.corp.appnexus.com/glob/-/glob-7.0.5.tgz", - "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", - "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" - } - }, - "growl": { - "version": "1.9.2", - "resolved": "https://npm.corp.appnexus.com/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "mock-fs": { - "version": "3.12.1", - "resolved": "https://npm.corp.appnexus.com/mock-fs/-/mock-fs-3.12.1.tgz", - "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", - "dev": true, - "requires": { - "rewire": "2.5.2", - "semver": "5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "module-deps-sortable": { - "version": "4.0.6", - "resolved": "https://npm.corp.appnexus.com/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", - "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", - "dev": true, - "requires": { - "browser-resolve": "1.11.2", - "concat-stream": "1.5.2", - "defined": "1.0.0", - "detective": "4.7.1", - "duplexer2": "0.1.4", - "inherits": "2.0.3", - "JSONStream": "1.3.3", - "parents": "1.0.1", - "readable-stream": "2.3.6", - "resolve": "1.7.1", - "stream-combiner2": "1.1.1", - "subarg": "1.0.0", - "through2": "2.0.3", - "xtend": "4.0.1" - }, - "dependencies": { - "concat-stream": { - "version": "1.5.2", - "resolved": "https://npm.corp.appnexus.com/concat-stream/-/concat-stream-1.5.2.tgz", - "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.0.6", - "typedarray": "0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.0.6", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" - } - } - } - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://npm.corp.appnexus.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, - "morgan": { - "version": "1.6.1", - "resolved": "https://npm.corp.appnexus.com/morgan/-/morgan-1.6.1.tgz", - "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", - "dev": true, - "requires": { - "basic-auth": "1.0.4", - "debug": "2.2.0", - "depd": "1.0.1", - "on-finished": "2.3.0", - "on-headers": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multiparty": { - "version": "3.3.2", - "resolved": "https://npm.corp.appnexus.com/multiparty/-/multiparty-3.3.2.tgz", - "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", - "dev": true, - "requires": { - "readable-stream": "1.1.14", - "stream-counter": "0.2.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://npm.corp.appnexus.com/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - }, - "dependencies": { - "duplexer2": { - "version": "0.0.2", - "resolved": "https://npm.corp.appnexus.com/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://npm.corp.appnexus.com/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nan": { - "version": "2.10.0", - "resolved": "https://npm.corp.appnexus.com/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.9", - "resolved": "https://npm.corp.appnexus.com/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "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-odd": "2.0.0", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - }, - "natives": { - "version": "1.1.4", - "resolved": "https://npm.corp.appnexus.com/natives/-/natives-1.1.4.tgz", - "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://npm.corp.appnexus.com/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "ncp": { - "version": "0.4.2", - "resolved": "https://npm.corp.appnexus.com/ncp/-/ncp-0.4.2.tgz", - "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", - "dev": true - }, - "negotiator": { - "version": "0.5.3", - "resolved": "https://npm.corp.appnexus.com/negotiator/-/negotiator-0.5.3.tgz", - "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", - "dev": true - }, - "neo-async": { - "version": "2.5.1", - "resolved": "https://npm.corp.appnexus.com/neo-async/-/neo-async-2.5.1.tgz", - "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", - "dev": true - }, - "netmask": { - "version": "1.0.6", - "resolved": "https://npm.corp.appnexus.com/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "nightwatch": { - "version": "0.9.21", - "resolved": "https://npm.corp.appnexus.com/nightwatch/-/nightwatch-0.9.21.tgz", - "integrity": "sha1-nnlKdRS0/V9GYC02jlBRUjKrnpA=", - "dev": true, - "requires": { - "chai-nightwatch": "0.1.1", - "ejs": "2.5.7", - "lodash.clone": "3.0.3", - "lodash.defaultsdeep": "4.3.2", - "minimatch": "3.0.3", - "mkpath": "1.0.0", - "mocha-nightwatch": "3.2.2", - "optimist": "0.6.1", - "proxy-agent": "2.0.0", - "q": "1.4.1" - }, - "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, - "requires": { - "extend": "3.0.1", - "semver": "5.0.3" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "co": { - "version": "3.0.6", - "resolved": "https://npm.corp.appnexus.com/co/-/co-3.0.6.tgz", - "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "ejs": { - "version": "2.5.7", - "resolved": "https://npm.corp.appnexus.com/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "http-proxy-agent": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", - "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", - "dev": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "ip": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/ip/-/ip-1.0.1.tgz", - "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", - "dev": true - }, - "lru-cache": { - "version": "2.6.5", - "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.6.5.tgz", - "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", - "dev": true - }, - "minimatch": { - "version": "3.0.3", - "resolved": "https://npm.corp.appnexus.com/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "pac-proxy-agent": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", - "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", - "dev": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1", - "get-uri": "2.0.2", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "1.0.0", - "pac-resolver": "2.0.0", - "raw-body": "2.3.3", - "socks-proxy-agent": "2.1.1" - } - }, - "pac-resolver": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/pac-resolver/-/pac-resolver-2.0.0.tgz", - "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", - "dev": true, - "requires": { - "co": "3.0.6", - "degenerator": "1.0.4", - "ip": "1.0.1", - "netmask": "1.0.6", - "thunkify": "2.1.2" - } - }, - "proxy-agent": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/proxy-agent/-/proxy-agent-2.0.0.tgz", - "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", - "dev": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "1.0.0", - "lru-cache": "2.6.5", - "pac-proxy-agent": "1.1.0", - "socks-proxy-agent": "2.1.1" - } - }, - "q": { - "version": "1.4.1", - "resolved": "https://npm.corp.appnexus.com/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", - "dev": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "semver": { - "version": "5.0.3", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - }, - "socks-proxy-agent": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", - "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", - "dev": true, - "requires": { - "agent-base": "2.1.1", - "extend": "3.0.1", - "socks": "1.1.10" - } - } - } - }, - "nise": { - "version": "1.4.1", - "resolved": "https://npm.corp.appnexus.com/nise/-/nise-1.4.1.tgz", - "integrity": "sha512-9JX3YwoIt3kS237scmSSOpEv7vCukVzLfwK0I0XhocDSHUANid8ZHnLEULbbSkfeMn98B2y5kphIWzZUylESRQ==", - "dev": true, - "requires": { - "@sinonjs/formatio": "2.0.0", - "just-extend": "1.1.27", - "lolex": "2.7.0", - "path-to-regexp": "1.7.0", - "text-encoding": "0.6.4" - } - }, - "node-int64": { - "version": "0.3.3", - "resolved": "https://npm.corp.appnexus.com/node-int64/-/node-int64-0.3.3.tgz", - "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", - "dev": true - }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.2.0", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.2.0", - "events": "1.1.1", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.6", - "stream-browserify": "2.0.1", - "stream-http": "2.8.3", - "string_decoder": "1.1.1", - "timers-browserify": "2.0.10", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.4", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "url": { - "version": "0.11.0", - "resolved": "https://npm.corp.appnexus.com/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - } - } - }, - "nodemailer": { - "version": "2.7.2", - "resolved": "https://npm.corp.appnexus.com/nodemailer/-/nodemailer-2.7.2.tgz", - "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", - "dev": true, - "optional": true, - "requires": { - "libmime": "3.0.0", - "mailcomposer": "4.0.1", - "nodemailer-direct-transport": "3.3.2", - "nodemailer-shared": "1.1.0", - "nodemailer-smtp-pool": "2.8.2", - "nodemailer-smtp-transport": "2.7.2", - "socks": "1.1.9" - }, - "dependencies": { - "socks": { - "version": "1.1.9", - "resolved": "https://npm.corp.appnexus.com/socks/-/socks-1.1.9.tgz", - "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", - "dev": true, - "optional": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - } - } - } - }, - "nodemailer-direct-transport": { - "version": "3.3.2", - "resolved": "https://npm.corp.appnexus.com/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", - "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://npm.corp.appnexus.com/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true, - "requires": { - "nodemailer-fetch": "1.6.0" - } - }, - "nodemailer-smtp-pool": { - "version": "2.8.2", - "resolved": "https://npm.corp.appnexus.com/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", - "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "https://npm.corp.appnexus.com/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", - "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-wellknown": { - "version": "0.1.10", - "resolved": "https://npm.corp.appnexus.com/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://npm.corp.appnexus.com/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1.0.9" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://npm.corp.appnexus.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "2.6.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.3" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "1.1.0" - } - }, - "normalize-url": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, - "requires": { - "prepend-http": "2.0.0", - "query-string": "5.1.1", - "sort-keys": "2.0.0" - } - }, - "now-and-later": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/now-and-later/-/now-and-later-2.0.0.tgz", - "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "2.0.1" - } - }, - "null-check": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/null-check/-/null-check-1.0.0.tgz", - "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://npm.corp.appnexus.com/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://npm.corp.appnexus.com/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://npm.corp.appnexus.com/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://npm.corp.appnexus.com/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://npm.corp.appnexus.com/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://npm.corp.appnexus.com/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "has-symbols": "1.0.0", - "object-keys": "1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.1" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - } - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://npm.corp.appnexus.com/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "1.2.0" - } - }, - "open": { - "version": "0.0.5", - "resolved": "https://npm.corp.appnexus.com/open/-/open-0.0.5.tgz", - "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", - "dev": true - }, - "openurl": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/openurl/-/openurl-1.1.1.tgz", - "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://npm.corp.appnexus.com/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://npm.corp.appnexus.com/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optimize-js": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/optimize-js/-/optimize-js-1.0.3.tgz", - "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", - "dev": true, - "requires": { - "acorn": "3.3.0", - "concat-stream": "1.6.2", - "estree-walker": "0.3.1", - "magic-string": "0.16.0", - "yargs": "4.8.1" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://npm.corp.appnexus.com/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://npm.corp.appnexus.com/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "1.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.1" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/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.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "yargs": { - "version": "4.8.1", - "resolved": "https://npm.corp.appnexus.com/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, - "requires": { - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "lodash.assign": "4.2.0", - "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", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" - } - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, - "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" - } - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://npm.corp.appnexus.com/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "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", - "wordwrap": "1.0.0" - } - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://npm.corp.appnexus.com/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.1" - }, - "dependencies": { - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "1.3.3" - } - }, - "once": { - "version": "1.3.3", - "resolved": "https://npm.corp.appnexus.com/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - } - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "2.3.6" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "over": { - "version": "0.0.5", - "resolved": "https://npm.corp.appnexus.com/over/-/over-0.0.5.tgz", - "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", - "dev": true - }, - "p-cancelable": { - "version": "0.4.1", - "resolved": "https://npm.corp.appnexus.com/p-cancelable/-/p-cancelable-0.4.1.tgz", - "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "1.3.0" - } - }, - "p-timeout": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/p-timeout/-/p-timeout-2.0.1.tgz", - "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, - "requires": { - "p-finally": "1.0.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pac-proxy-agent": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", - "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0", - "get-uri": "2.0.2", - "http-proxy-agent": "2.1.0", - "https-proxy-agent": "2.2.1", - "pac-resolver": "3.0.0", - "raw-body": "2.3.3", - "socks-proxy-agent": "3.0.1" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true, - "optional": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "optional": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://npm.corp.appnexus.com/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "optional": true, - "requires": { - "depd": "1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": "1.5.0" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "optional": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "optional": true, - "requires": { - "co": "4.6.0", - "degenerator": "1.0.4", - "ip": "1.1.5", - "netmask": "1.0.6", - "thunkify": "2.1.2" - } - }, - "pako": { - "version": "1.0.6", - "resolved": "https://npm.corp.appnexus.com/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", - "dev": true - }, - "parents": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true, - "requires": { - "path-platform": "0.11.15" - } - }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "https://npm.corp.appnexus.com/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true, - "requires": { - "asn1.js": "4.10.1", - "browserify-aes": "1.2.0", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.16" - } - }, - "parse-domain": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/parse-domain/-/parse-domain-2.1.1.tgz", - "integrity": "sha512-xOQ/B+pnS8uzqFMHcS7VS9J7Cn+rFyPlGIoDMFL2e5g/tPhlpa8MSHQmFAlABHBKPCXgOOxFt5PFNdEmwtwvqQ==", - "dev": true, - "requires": { - "chai": "4.1.2", - "fs-copy-file-sync": "1.1.1", - "got": "8.3.1", - "mkdirp": "0.5.1", - "mocha": "4.1.0" - }, - "dependencies": { - "chai": { - "version": "4.1.2", - "resolved": "https://npm.corp.appnexus.com/chai/-/chai-4.1.2.tgz", - "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", - "dev": true, - "requires": { - "assertion-error": "1.1.0", - "check-error": "1.0.2", - "deep-eql": "3.0.1", - "get-func-name": "2.0.0", - "pathval": "1.1.0", - "type-detect": "4.0.8" - } - }, - "commander": { - "version": "2.11.0", - "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "diff": { - "version": "3.3.1", - "resolved": "https://npm.corp.appnexus.com/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "mocha": { - "version": "4.1.0", - "resolved": "https://npm.corp.appnexus.com/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" - } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - } - } - }, - "parse-entities": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/parse-entities/-/parse-entities-1.1.2.tgz", - "integrity": "sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg==", - "dev": true, - "requires": { - "character-entities": "1.2.2", - "character-entities-legacy": "1.1.2", - "character-reference-invalid": "1.1.2", - "is-alphanumerical": "1.0.2", - "is-decimal": "1.0.2", - "is-hexadecimal": "1.0.2" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, - "parse-git-config": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/parse-git-config/-/parse-git-config-0.2.0.tgz", - "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", - "dev": true, - "requires": { - "ini": "1.3.5" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "1.3.1", - "json-parse-better-errors": "1.0.2" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-url": { - "version": "1.3.11", - "resolved": "https://npm.corp.appnexus.com/parse-url/-/parse-url-1.3.11.tgz", - "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", - "dev": true, - "requires": { - "is-ssh": "1.3.0", - "protocols": "1.4.6" - } - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://npm.corp.appnexus.com/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "1.0.2" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://npm.corp.appnexus.com/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "1.0.2" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://npm.corp.appnexus.com/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://npm.corp.appnexus.com/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-platform": { - "version": "0.11.15", - "resolved": "https://npm.corp.appnexus.com/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", - "dev": true - }, - "path-proxy": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/path-proxy/-/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "dev": true, - "optional": true, - "requires": { - "inflection": "1.3.8" - }, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "https://npm.corp.appnexus.com/inflection/-/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", - "dev": true, - "optional": true - } - } - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "0.1.2" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://npm.corp.appnexus.com/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://npm.corp.appnexus.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "3.0.0" - } - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true - }, - "pause": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/pause/-/pause-0.1.0.tgz", - "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://npm.corp.appnexus.com/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "pbkdf2": { - "version": "3.0.16", - "resolved": "https://npm.corp.appnexus.com/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "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://npm.corp.appnexus.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", - "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://npm.corp.appnexus.com/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "2.1.0" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "1.1.0", - "arr-diff": "4.0.0", - "arr-union": "3.1.0", - "extend-shallow": "3.0.2" - } - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://npm.corp.appnexus.com/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "private": { - "version": "0.1.8", - "resolved": "https://npm.corp.appnexus.com/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://npm.corp.appnexus.com/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "progress": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", - "dev": true - }, - "promisify-call": { - "version": "2.0.4", - "resolved": "https://npm.corp.appnexus.com/promisify-call/-/promisify-call-2.0.4.tgz", - "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", - "dev": true, - "optional": true, - "requires": { - "with-callback": "1.0.2" - } - }, - "property-information": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/property-information/-/property-information-3.2.0.tgz", - "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE=", - "dev": true - }, - "protocols": { - "version": "1.4.6", - "resolved": "https://npm.corp.appnexus.com/protocols/-/protocols-1.4.6.tgz", - "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", - "dev": true - }, - "proxy-agent": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/proxy-agent/-/proxy-agent-3.0.0.tgz", - "integrity": "sha512-g6n6vnk8fRf705ShN+FEXFG/SDJaW++lSs0d9KaJh4uBWW/wi7en4Cpo5VYQW3SZzAE121lhB/KLQrbURoubZw==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0", - "http-proxy-agent": "2.1.0", - "https-proxy-agent": "2.2.1", - "lru-cache": "4.1.3", - "pac-proxy-agent": "2.0.2", - "proxy-from-env": "1.0.0", - "socks-proxy-agent": "3.0.1" - } - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true, - "optional": true - }, - "proxyquire": { - "version": "1.8.0", - "resolved": "https://npm.corp.appnexus.com/proxyquire/-/proxyquire-1.8.0.tgz", - "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", - "dev": true, - "requires": { - "fill-keys": "1.0.2", - "module-not-found-error": "1.0.1", - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://npm.corp.appnexus.com/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.2", - "resolved": "https://npm.corp.appnexus.com/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "parse-asn1": "5.1.1", - "randombytes": "2.0.6" - } - }, - "pullstream": { - "version": "0.4.1", - "resolved": "https://npm.corp.appnexus.com/pullstream/-/pullstream-0.4.1.tgz", - "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", - "dev": true, - "requires": { - "over": "0.0.5", - "readable-stream": "1.0.34", - "setimmediate": "1.0.5", - "slice-stream": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://npm.corp.appnexus.com/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "3.6.0", - "inherits": "2.0.3", - "pump": "2.0.1" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://npm.corp.appnexus.com/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "q": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/q/-/q-1.3.0.tgz", - "integrity": "sha1-hQ15+MuDHZLhA7Rkg+TjXTRkAFA=", - "dev": true - }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true - }, - "qs": { - "version": "6.3.2", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "query-string": { - "version": "5.1.1", - "resolved": "https://npm.corp.appnexus.com/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "requires": { - "decode-uri-component": "0.2.0", - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "querystringify": { - "version": "0.0.3", - "resolved": "https://npm.corp.appnexus.com/querystringify/-/querystringify-0.0.3.tgz", - "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", - "dev": true - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", - "dev": true - }, - "randomatic": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/randomatic/-/randomatic-3.0.0.tgz", - "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", - "dev": true, - "requires": { - "is-number": "4.0.0", - "kind-of": "6.0.2", - "math-random": "1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://npm.corp.appnexus.com/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.2" - } - }, - "range-parser": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/range-parser/-/range-parser-1.0.3.tgz", - "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", - "dev": true - }, - "raw-body": { - "version": "1.1.7", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", - "dev": true, - "requires": { - "bytes": "1.0.0", - "string_decoder": "0.10.31" - }, - "dependencies": { - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/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.4.0", - "path-type": "3.0.0" - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "requires": { - "find-up": "2.1.0", - "read-pkg": "3.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.6", - "set-immediate-shim": "1.0.1" - } - }, - "readline2": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/readline2/-/readline2-0.1.1.tgz", - "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", - "dev": true, - "requires": { - "mute-stream": "0.0.4", - "strip-ansi": "2.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-1.1.1.tgz", - "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", - "dev": true - }, - "mute-stream": { - "version": "0.0.4", - "resolved": "https://npm.corp.appnexus.com/mute-stream/-/mute-stream-0.0.4.tgz", - "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", - "dev": true - }, - "strip-ansi": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-2.0.1.tgz", - "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", - "dev": true, - "requires": { - "ansi-regex": "1.1.1" - } - } - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://npm.corp.appnexus.com/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.7.1" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" - } - }, - "redis": { - "version": "2.8.0", - "resolved": "https://npm.corp.appnexus.com/redis/-/redis-2.8.0.tgz", - "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", - "dev": true, - "optional": true, - "requires": { - "double-ended-queue": "2.1.0-0", - "redis-commands": "1.3.5", - "redis-parser": "2.6.0" - } - }, - "redis-commands": { - "version": "1.3.5", - "resolved": "https://npm.corp.appnexus.com/redis-commands/-/redis-commands-1.3.5.tgz", - "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==", - "dev": true, - "optional": true - }, - "redis-parser": { - "version": "2.6.0", - "resolved": "https://npm.corp.appnexus.com/redis-parser/-/redis-parser-2.6.0.tgz", - "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", - "dev": true, - "optional": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://npm.corp.appnexus.com/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://npm.corp.appnexus.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://npm.corp.appnexus.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "private": "0.1.8" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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" - } - }, - "regexpp": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", - "dev": true - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "1.4.0", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://npm.corp.appnexus.com/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "remark": { - "version": "9.0.0", - "resolved": "https://npm.corp.appnexus.com/remark/-/remark-9.0.0.tgz", - "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true, - "requires": { - "remark-parse": "5.0.0", - "remark-stringify": "5.0.0", - "unified": "6.2.0" - } - }, - "remark-html": { - "version": "7.0.0", - "resolved": "https://npm.corp.appnexus.com/remark-html/-/remark-html-7.0.0.tgz", - "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true, - "requires": { - "hast-util-sanitize": "1.1.2", - "hast-util-to-html": "3.1.0", - "mdast-util-to-hast": "3.0.1", - "xtend": "4.0.1" - } - }, - "remark-parse": { - "version": "5.0.0", - "resolved": "https://npm.corp.appnexus.com/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "1.0.4", - "is-alphabetical": "1.0.2", - "is-decimal": "1.0.2", - "is-whitespace-character": "1.0.2", - "is-word-character": "1.0.2", - "markdown-escapes": "1.0.2", - "parse-entities": "1.1.2", - "repeat-string": "1.6.1", - "state-toggle": "1.0.1", - "trim": "0.0.1", - "trim-trailing-lines": "1.1.1", - "unherit": "1.1.1", - "unist-util-remove-position": "1.1.2", - "vfile-location": "2.0.3", - "xtend": "4.0.1" - } - }, - "remark-reference-links": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/remark-reference-links/-/remark-reference-links-4.0.1.tgz", - "integrity": "sha1-AhrtHFXBh9cSs8dtAFe/UQ0wC6c=", - "dev": true, - "requires": { - "unist-util-visit": "1.3.1" - } - }, - "remark-slug": { - "version": "5.0.0", - "resolved": "https://npm.corp.appnexus.com/remark-slug/-/remark-slug-5.0.0.tgz", - "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", - "dev": true, - "requires": { - "github-slugger": "1.2.0", - "mdast-util-to-string": "1.0.4", - "unist-util-visit": "1.3.1" - } - }, - "remark-stringify": { - "version": "5.0.0", - "resolved": "https://npm.corp.appnexus.com/remark-stringify/-/remark-stringify-5.0.0.tgz", - "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true, - "requires": { - "ccount": "1.0.3", - "is-alphanumeric": "1.0.0", - "is-decimal": "1.0.2", - "is-whitespace-character": "1.0.2", - "longest-streak": "2.0.2", - "markdown-escapes": "1.0.2", - "markdown-table": "1.1.2", - "mdast-util-compact": "1.0.1", - "parse-entities": "1.1.2", - "repeat-string": "1.6.1", - "state-toggle": "1.0.1", - "stringify-entities": "1.3.2", - "unherit": "1.1.1", - "xtend": "4.0.1" - } - }, - "remark-toc": { - "version": "5.0.0", - "resolved": "https://npm.corp.appnexus.com/remark-toc/-/remark-toc-5.0.0.tgz", - "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", - "dev": true, - "requires": { - "mdast-util-toc": "2.0.1", - "remark-slug": "5.0.0" - } - }, - "remote-origin-url": { - "version": "0.4.0", - "resolved": "https://npm.corp.appnexus.com/remote-origin-url/-/remote-origin-url-0.4.0.tgz", - "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true, - "requires": { - "parse-git-config": "0.2.0" - } - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "1.1.6", - "is-utf8": "0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "3.0.0", - "safe-buffer": "5.1.2", - "through2": "2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://npm.corp.appnexus.com/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "1.0.2" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replacestream": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/replacestream/-/replacestream-0.1.3.tgz", - "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "request": { - "version": "2.79.0", - "resolved": "https://npm.corp.appnexus.com/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.7.0", - "caseless": "0.11.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.6", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.4.3", - "uuid": "3.2.1" - } - }, - "requestretry": { - "version": "1.13.0", - "resolved": "https://npm.corp.appnexus.com/requestretry/-/requestretry-1.13.0.tgz", - "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", - "dev": true, - "optional": true, - "requires": { - "extend": "3.0.1", - "lodash": "4.17.10", - "request": "2.79.0", - "when": "3.7.8" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" - } - }, - "requirejs": { - "version": "2.3.5", - "resolved": "https://npm.corp.appnexus.com/requirejs/-/requirejs-2.3.5.tgz", - "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.7.1", - "resolved": "https://npm.corp.appnexus.com/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "response-time": { - "version": "2.3.2", - "resolved": "https://npm.corp.appnexus.com/response-time/-/response-time-2.3.2.tgz", - "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", - "dev": true, - "requires": { - "depd": "1.1.2", - "on-headers": "1.0.1" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - } - } - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "1.0.1" - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://npm.corp.appnexus.com/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rewire": { - "version": "2.5.2", - "resolved": "https://npm.corp.appnexus.com/rewire/-/rewire-2.5.2.tgz", - "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", - "dev": true - }, - "rgb2hex": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/rgb2hex/-/rgb2hex-0.1.1.tgz", - "integrity": "sha512-icFtYF9bLbxRZ6zYlp28622lBM7Ae0ylPT+ob0SBZdd2p1FN5MoOClpwPcjT9TgXDLS8jyXlw3yVtHQZU3/vvg==", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "0.1.4" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://npm.corp.appnexus.com/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "7.1.2" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://npm.corp.appnexus.com/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" - } - }, - "rndm": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", - "dev": true - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "2.1.0" - } - }, - "rx": { - "version": "2.5.3", - "resolved": "https://npm.corp.appnexus.com/rx/-/rx-2.5.3.tgz", - "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", - "dev": true - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://npm.corp.appnexus.com/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://npm.corp.appnexus.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "4.0.8" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://npm.corp.appnexus.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-json-parse": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "0.1.15" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://npm.corp.appnexus.com/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "samsam": { - "version": "1.3.0", - "resolved": "https://npm.corp.appnexus.com/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - }, - "schema-utils": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true, - "requires": { - "ajv": "5.5.2" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://npm.corp.appnexus.com/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.0.0", - "json-schema-traverse": "0.3.1" - } - } - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - }, - "send": { - "version": "0.13.2", - "resolved": "https://npm.corp.appnexus.com/send/-/send-0.13.2.tgz", - "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", - "dev": true, - "requires": { - "debug": "2.2.0", - "depd": "1.1.2", - "destroy": "1.0.4", - "escape-html": "1.0.3", - "etag": "1.7.0", - "fresh": "0.3.0", - "http-errors": "1.3.1", - "mime": "1.3.4", - "ms": "0.7.1", - "on-finished": "2.3.0", - "range-parser": "1.0.3", - "statuses": "1.2.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "mime": { - "version": "1.3.4", - "resolved": "https://npm.corp.appnexus.com/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "statuses": { - "version": "1.2.1", - "resolved": "https://npm.corp.appnexus.com/statuses/-/statuses-1.2.1.tgz", - "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", - "dev": true - } - } - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://npm.corp.appnexus.com/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "serve-favicon": { - "version": "2.3.2", - "resolved": "https://npm.corp.appnexus.com/serve-favicon/-/serve-favicon-2.3.2.tgz", - "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", - "dev": true, - "requires": { - "etag": "1.7.0", - "fresh": "0.3.0", - "ms": "0.7.2", - "parseurl": "1.3.2" - }, - "dependencies": { - "ms": { - "version": "0.7.2", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "serve-index": { - "version": "1.7.3", - "resolved": "https://npm.corp.appnexus.com/serve-index/-/serve-index-1.7.3.tgz", - "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", - "dev": true, - "requires": { - "accepts": "1.2.13", - "batch": "0.5.3", - "debug": "2.2.0", - "escape-html": "1.0.3", - "http-errors": "1.3.1", - "mime-types": "2.1.18", - "parseurl": "1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://npm.corp.appnexus.com/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "serve-static": { - "version": "1.10.3", - "resolved": "https://npm.corp.appnexus.com/serve-static/-/serve-static-1.10.3.tgz", - "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", - "dev": true, - "requires": { - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.13.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://npm.corp.appnexus.com/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://npm.corp.appnexus.com/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shelljs": { - "version": "0.8.2", - "resolved": "https://npm.corp.appnexus.com/shelljs/-/shelljs-0.8.2.tgz", - "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", - "dev": true, - "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" - } - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://npm.corp.appnexus.com/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "sinon": { - "version": "4.5.0", - "resolved": "https://npm.corp.appnexus.com/sinon/-/sinon-4.5.0.tgz", - "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", - "dev": true, - "requires": { - "@sinonjs/formatio": "2.0.0", - "diff": "3.5.0", - "lodash.get": "4.4.2", - "lolex": "2.7.0", - "nise": "1.4.1", - "supports-color": "5.4.0", - "type-detect": "4.0.8" - }, - "dependencies": { - "diff": { - "version": "3.5.0", - "resolved": "https://npm.corp.appnexus.com/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - } - } - }, - "slack-node": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/slack-node/-/slack-node-0.2.0.tgz", - "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", - "dev": true, - "optional": true, - "requires": { - "requestretry": "1.13.0" - } - }, - "slash": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - } - } - }, - "slice-stream": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/slice-stream/-/slice-stream-1.0.0.tgz", - "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", - "dev": true, - "requires": { - "readable-stream": "1.0.34" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://npm.corp.appnexus.com/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true - }, - "smtp-connection": { - "version": "2.12.0", - "resolved": "https://npm.corp.appnexus.com/smtp-connection/-/smtp-connection-2.12.0.tgz", - "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true, - "requires": { - "httpntlm": "1.6.1", - "nodemailer-shared": "1.1.0" - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://npm.corp.appnexus.com/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "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.2", - "use": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://npm.corp.appnexus.com/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "socket.io": { - "version": "2.0.4", - "resolved": "https://npm.corp.appnexus.com/socket.io/-/socket.io-2.0.4.tgz", - "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", - "dev": true, - "requires": { - "debug": "2.6.9", - "engine.io": "3.1.5", - "socket.io-adapter": "1.1.1", - "socket.io-client": "2.0.4", - "socket.io-parser": "3.1.3" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", - "dev": true - }, - "socket.io-client": { - "version": "2.0.4", - "resolved": "https://npm.corp.appnexus.com/socket.io-client/-/socket.io-client-2.0.4.tgz", - "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "2.6.9", - "engine.io-client": "3.1.6", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "3.1.3", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "socket.io-parser": { - "version": "3.1.3", - "resolved": "https://npm.corp.appnexus.com/socket.io-parser/-/socket.io-parser-3.1.3.tgz", - "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "3.1.0", - "has-binary2": "1.0.3", - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "socks": { - "version": "1.1.10", - "resolved": "https://npm.corp.appnexus.com/socks/-/socks-1.1.10.tgz", - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "dev": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", - "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", - "dev": true, - "requires": { - "agent-base": "4.2.0", - "socks": "1.1.10" - } - }, - "sort-keys": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, - "requires": { - "is-plain-obj": "1.1.0" - } - }, - "source-list-map": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://npm.corp.appnexus.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "requires": { - "atob": "2.1.1", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" - } - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://npm.corp.appnexus.com/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://npm.corp.appnexus.com/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "space-separated-tokens": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", - "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "dev": true, - "requires": { - "trim": "0.0.1" - } - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, - "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://npm.corp.appnexus.com/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.14.2", - "resolved": "https://npm.corp.appnexus.com/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", - "dev": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "safer-buffer": "2.1.2", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "state-toggle": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://npm.corp.appnexus.com/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://npm.corp.appnexus.com/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://npm.corp.appnexus.com/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stream-array": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "readable-stream": { - "version": "2.1.5", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-2.1.5.tgz", - "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true, - "requires": { - "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" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://npm.corp.appnexus.com/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "0.1.1" - } - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "requires": { - "duplexer2": "0.1.4", - "readable-stream": "2.3.6" - } - }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://npm.corp.appnexus.com/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", - "dev": true - }, - "stream-counter": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/stream-counter/-/stream-counter-0.2.0.tgz", - "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://npm.corp.appnexus.com/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamroller": { - "version": "0.7.0", - "resolved": "https://npm.corp.appnexus.com/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", - "dev": true, - "requires": { - "date-format": "1.2.0", - "debug": "3.1.0", - "mkdirp": "0.5.1", - "readable-stream": "2.3.6" - } - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "string-replace-webpack-plugin": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", - "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", - "dev": true, - "requires": { - "async": "0.2.10", - "css-loader": "0.9.1", - "file-loader": "0.8.5", - "loader-utils": "0.2.17", - "style-loader": "0.8.3" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://npm.corp.appnexus.com/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://npm.corp.appnexus.com/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" - } - } - } - }, - "string-template": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "stringify-entities": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/stringify-entities/-/stringify-entities-1.3.2.tgz", - "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, - "requires": { - "character-entities-html4": "1.1.2", - "character-entities-legacy": "1.1.2", - "is-alphanumerical": "1.0.2", - "is-hexadecimal": "1.0.2" - } - }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://npm.corp.appnexus.com/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "4.0.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "style-loader": { - "version": "0.8.3", - "resolved": "https://npm.corp.appnexus.com/style-loader/-/style-loader-0.8.3.tgz", - "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", - "dev": true, - "optional": true, - "requires": { - "loader-utils": "0.2.17" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://npm.corp.appnexus.com/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "optional": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - } - } - }, - "subarg": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "requires": { - "minimist": "1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "table": { - "version": "4.0.2", - "resolved": "https://npm.corp.appnexus.com/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "requires": { - "ajv": "5.5.2", - "ajv-keywords": "2.1.1", - "chalk": "2.4.1", - "lodash": "4.17.10", - "slice-ansi": "1.0.0", - "string-width": "2.1.1" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://npm.corp.appnexus.com/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.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "tapable": { - "version": "0.2.8", - "resolved": "https://npm.corp.appnexus.com/tapable/-/tapable-0.2.8.tgz", - "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", - "dev": true - }, - "tar-stream": { - "version": "1.1.5", - "resolved": "https://npm.corp.appnexus.com/tar-stream/-/tar-stream-1.1.5.tgz", - "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", - "dev": true, - "requires": { - "bl": "0.9.5", - "end-of-stream": "1.4.1", - "readable-stream": "1.0.34", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "ternary-stream": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/ternary-stream/-/ternary-stream-2.0.1.tgz", - "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true, - "requires": { - "duplexify": "3.6.0", - "fork-stream": "0.0.4", - "merge-stream": "1.0.1", - "through2": "2.0.3" - } - }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://npm.corp.appnexus.com/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "textextensions": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/textextensions/-/textextensions-1.0.2.tgz", - "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://npm.corp.appnexus.com/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://npm.corp.appnexus.com/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "2.0.3", - "xtend": "4.0.1" - } - }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://npm.corp.appnexus.com/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://npm.corp.appnexus.com/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "1.0.5" - } - }, - "timers-ext": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/timers-ext/-/timers-ext-0.1.5.tgz", - "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==", - "requires": { - "es5-ext": "0.10.45", - "next-tick": "1.0.0" - } - }, - "timespan": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/timespan/-/timespan-2.3.0.tgz", - "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", - "dev": true, - "optional": true - }, - "tiny-lr": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", - "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.1", - "qs": "6.5.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - } - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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-array": { - "version": "0.1.4", - "resolved": "https://npm.corp.appnexus.com/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://npm.corp.appnexus.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "2.0.3" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://npm.corp.appnexus.com/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "requires": { - "punycode": "1.4.1" - } - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://npm.corp.appnexus.com/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "trim": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "dev": true - }, - "trim-lines": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/trim-lines/-/trim-lines-1.1.1.tgz", - "integrity": "sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==", - "dev": true - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "trim-trailing-lines": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", - "dev": true - }, - "trough": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/trough/-/trough-1.0.2.tgz", - "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", - "dev": true - }, - "tsscmp": { - "version": "1.0.5", - "resolved": "https://npm.corp.appnexus.com/tsscmp/-/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://npm.corp.appnexus.com/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://npm.corp.appnexus.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://npm.corp.appnexus.com/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://npm.corp.appnexus.com/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "1.1.2" - } - }, - "type-detect": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://npm.corp.appnexus.com/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "2.1.18" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://npm.corp.appnexus.com/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://npm.corp.appnexus.com/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" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://npm.corp.appnexus.com/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, - "uglifyjs-webpack-plugin": { - "version": "0.4.6", - "resolved": "https://npm.corp.appnexus.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", - "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", - "dev": true, - "requires": { - "source-map": "0.5.7", - "uglify-js": "2.8.29", - "webpack-sources": "1.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "uid-safe": { - "version": "2.1.4", - "resolved": "https://npm.corp.appnexus.com/uid-safe/-/uid-safe-2.1.4.tgz", - "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", - "dev": true, - "requires": { - "random-bytes": "1.0.0" - } - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://npm.corp.appnexus.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.7.0", - "resolved": "https://npm.corp.appnexus.com/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true - }, - "unherit": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/unherit/-/unherit-1.1.1.tgz", - "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "xtend": "4.0.1" - } - }, - "unified": { - "version": "6.2.0", - "resolved": "https://npm.corp.appnexus.com/unified/-/unified-6.2.0.tgz", - "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true, - "requires": { - "bail": "1.0.3", - "extend": "3.0.1", - "is-plain-obj": "1.1.0", - "trough": "1.0.2", - "vfile": "2.3.0", - "x-is-string": "0.1.0" - } - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://npm.corp.appnexus.com/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" - } - } - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://npm.corp.appnexus.com/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "unist-builder": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/unist-builder/-/unist-builder-1.0.2.tgz", - "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", - "dev": true, - "requires": { - "object-assign": "4.1.1" - } - }, - "unist-util-generated": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/unist-util-generated/-/unist-util-generated-1.1.2.tgz", - "integrity": "sha512-1HcwiEO62dr0XWGT+abVK4f0aAm8Ik8N08c5nAYVmuSxfvpA9rCcNyX/le8xXj1pJK5nBrGlZefeWB6bN8Pstw==", - "dev": true - }, - "unist-util-is": { - "version": "2.1.2", - "resolved": "https://npm.corp.appnexus.com/unist-util-is/-/unist-util-is-2.1.2.tgz", - "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", - "dev": true - }, - "unist-util-modify-children": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", - "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", - "dev": true, - "requires": { - "array-iterate": "1.1.2" - } - }, - "unist-util-position": { - "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/unist-util-position/-/unist-util-position-3.0.1.tgz", - "integrity": "sha512-05QfJDPI7PE1BIUtAxeSV+cDx21xP7+tUZgSval5CA7tr0pHBwybF7OnEa1dOFqg6BfYH/qiMUnWwWj+Frhlww==", - "dev": true - }, - "unist-util-remove-position": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", - "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", - "dev": true, - "requires": { - "unist-util-visit": "1.3.1" - } - }, - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, - "unist-util-visit": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/unist-util-visit/-/unist-util-visit-1.3.1.tgz", - "integrity": "sha512-0fdB9EQJU0tho5tK0VzOJzAQpPv2LyLZ030b10GxuzAWEfvd54mpY7BMjQ1L69k2YNvL+SvxRzH0yUIehOO8aA==", - "dev": true, - "requires": { - "unist-util-is": "2.1.2" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://npm.corp.appnexus.com/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "unzip": { - "version": "0.1.11", - "resolved": "https://npm.corp.appnexus.com/unzip/-/unzip-0.1.11.tgz", - "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", - "dev": true, - "requires": { - "binary": "0.3.0", - "fstream": "0.1.31", - "match-stream": "0.0.2", - "pullstream": "0.4.1", - "readable-stream": "1.0.34", - "setimmediate": "1.0.5" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "upath": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true - }, - "urix": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "url": { - "version": "0.10.3", - "resolved": "https://npm.corp.appnexus.com/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-parse": { - "version": "1.4.1", - "resolved": "https://npm.corp.appnexus.com/url-parse/-/url-parse-1.4.1.tgz", - "integrity": "sha512-x95Td74QcvICAA0+qERaVkRpTGKyBHHYdwL2LXZm5t/gBtCB9KQSO/0zQgSTYEV1p0WcvSg79TLNPSvd5IDJMQ==", - "dev": true, - "requires": { - "querystringify": "2.0.0", - "requires-port": "1.0.0" - }, - "dependencies": { - "querystringify": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", - "dev": true - } - } - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "requires": { - "prepend-http": "2.0.0" - } - }, - "url-to-options": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true - }, - "use": { - "version": "3.1.0", - "resolved": "https://npm.corp.appnexus.com/use/-/use-3.1.0.tgz", - "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "useragent": { - "version": "2.2.1", - "resolved": "https://npm.corp.appnexus.com/useragent/-/useragent-2.2.1.tgz", - "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", - "dev": true, - "requires": { - "lru-cache": "2.2.4", - "tmp": "0.0.33" - }, - "dependencies": { - "lru-cache": { - "version": "2.2.4", - "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.2.4.tgz", - "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", - "dev": true - } - } - }, - "util": { - "version": "0.10.4", - "resolved": "https://npm.corp.appnexus.com/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", - "dev": true - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true - }, - "uws": { - "version": "9.14.0", - "resolved": "https://npm.corp.appnexus.com/uws/-/uws-9.14.0.tgz", - "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", - "dev": true, - "optional": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://npm.corp.appnexus.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "dev": true, - "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vary": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/vary/-/vary-1.0.1.tgz", - "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://npm.corp.appnexus.com/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" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "vfile": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true, - "requires": { - "is-buffer": "1.1.6", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "1.1.2", - "vfile-message": "1.0.1" - } - }, - "vfile-location": { - "version": "2.0.3", - "resolved": "https://npm.corp.appnexus.com/vfile-location/-/vfile-location-2.0.3.tgz", - "integrity": "sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==", - "dev": true - }, - "vfile-message": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/vfile-message/-/vfile-message-1.0.1.tgz", - "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", - "dev": true, - "requires": { - "unist-util-stringify-position": "1.1.2" - } - }, - "vfile-reporter": { - "version": "4.0.0", - "resolved": "https://npm.corp.appnexus.com/vfile-reporter/-/vfile-reporter-4.0.0.tgz", - "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", - "dev": true, - "requires": { - "repeat-string": "1.6.1", - "string-width": "1.0.2", - "supports-color": "4.5.0", - "unist-util-stringify-position": "1.1.2", - "vfile-statistics": "1.1.1" - }, - "dependencies": { - "has-flag": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "vfile-sort": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/vfile-sort/-/vfile-sort-2.1.1.tgz", - "integrity": "sha512-+fpTWKkVHwI6VF2xtkDTuCA6cH4UPLAxh+KxfU8g8pC0do5RSZCk1HXTTtMJguW0t5jC0PC19owjUZX9SGQ9tw==", - "dev": true - }, - "vfile-statistics": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/vfile-statistics/-/vfile-statistics-1.1.1.tgz", - "integrity": "sha512-dxUM6IYvGChHuwMT3dseyU5BHprNRXzAV0OHx1A769lVGsTiT50kU7BbpRFV+IE6oWmU+PwHdsTKfXhnDIRIgQ==", - "dev": true - }, - "vhost": { - "version": "3.0.2", - "resolved": "https://npm.corp.appnexus.com/vhost/-/vhost-3.0.2.tgz", - "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", - "dev": true - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.1.2", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://npm.corp.appnexus.com/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.1.11", - "is-valid-glob": "1.0.0", - "lazystream": "1.0.0", - "lead": "1.0.0", - "object.assign": "4.1.0", - "pumpify": "1.5.1", - "readable-stream": "2.3.6", - "remove-bom-buffer": "3.0.0", - "remove-bom-stream": "1.2.0", - "resolve-options": "1.1.0", - "through2": "2.0.3", - "to-through": "2.0.0", - "value-or-function": "3.0.0", - "vinyl": "2.1.0", - "vinyl-sourcemap": "1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/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.1", - "graceful-fs": "4.1.11", - "normalize-path": "2.1.1", - "now-and-later": "2.0.0", - "remove-bom-buffer": "3.0.0", - "vinyl": "2.1.0" - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "vlq": { - "version": "0.2.3", - "resolved": "https://npm.corp.appnexus.com/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://npm.corp.appnexus.com/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", - "dev": true - }, - "walk": { - "version": "2.3.13", - "resolved": "https://npm.corp.appnexus.com/walk/-/walk-2.3.13.tgz", - "integrity": "sha512-78SMe7To9U7kqVhSoGho3GfspA089ZDBIj2f8jElg2hi6lUCoagtDJ8sSMFNlpAh5Ib8Jt1gQ6Y7gh9mzHtFng==", - "dev": true, - "requires": { - "foreachasync": "3.0.0" - } - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://npm.corp.appnexus.com/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "2.0.3", - "graceful-fs": "4.1.11", - "neo-async": "2.5.1" - } - }, - "webdriverio": { - "version": "3.4.0", - "resolved": "https://npm.corp.appnexus.com/webdriverio/-/webdriverio-3.4.0.tgz", - "integrity": "sha1-2dTTwxNm8FPhCvZEsOqtXoc6t7U=", - "dev": true, - "requires": { - "archiver": "0.14.4", - "array.from": "0.2.0", - "co": "4.6.0", - "css-parse": "2.0.0", - "css-value": "0.0.1", - "deepmerge": "0.2.10", - "ejs": "2.6.1", - "glob": "5.0.15", - "inquirer": "0.8.5", - "is-generator": "1.0.3", - "optimist": "0.6.1", - "q": "1.3.0", - "request": "2.49.0", - "rgb2hex": "0.1.1", - "supports-color": "1.3.1", - "url": "0.10.3", - "wgxpath": "1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-1.1.1.tgz", - "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", - "dev": true - }, - "asn1": { - "version": "0.1.11", - "resolved": "https://npm.corp.appnexus.com/asn1/-/asn1-0.1.11.tgz", - "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", - "dev": true - }, - "assert-plus": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", - "dev": true - }, - "async": { - "version": "0.9.2", - "resolved": "https://npm.corp.appnexus.com/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "aws-sign2": { - "version": "0.5.0", - "resolved": "https://npm.corp.appnexus.com/aws-sign2/-/aws-sign2-0.5.0.tgz", - "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", - "dev": true - }, - "boom": { - "version": "0.4.2", - "resolved": "https://npm.corp.appnexus.com/boom/-/boom-0.4.2.tgz", - "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", - "dev": true, - "requires": { - "hoek": "0.9.1" - } - }, - "caseless": { - "version": "0.8.0", - "resolved": "https://npm.corp.appnexus.com/caseless/-/caseless-0.8.0.tgz", - "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", - "dev": true - }, - "cli-width": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/cli-width/-/cli-width-1.1.1.tgz", - "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", - "dev": true - }, - "combined-stream": { - "version": "0.0.7", - "resolved": "https://npm.corp.appnexus.com/combined-stream/-/combined-stream-0.0.7.tgz", - "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", - "dev": true, - "requires": { - "delayed-stream": "0.0.5" - } - }, - "cryptiles": { - "version": "0.2.2", - "resolved": "https://npm.corp.appnexus.com/cryptiles/-/cryptiles-0.2.2.tgz", - "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", - "dev": true, - "requires": { - "boom": "0.4.2" - } - }, - "delayed-stream": { - "version": "0.0.5", - "resolved": "https://npm.corp.appnexus.com/delayed-stream/-/delayed-stream-0.0.5.tgz", - "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", - "dev": true - }, - "figures": { - "version": "1.7.0", - "resolved": "https://npm.corp.appnexus.com/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "forever-agent": { - "version": "0.5.2", - "resolved": "https://npm.corp.appnexus.com/forever-agent/-/forever-agent-0.5.2.tgz", - "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", - "dev": true - }, - "form-data": { - "version": "0.1.4", - "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-0.1.4.tgz", - "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", - "dev": true, - "requires": { - "async": "0.9.2", - "combined-stream": "0.0.7", - "mime": "1.2.11" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://npm.corp.appnexus.com/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "hawk": { - "version": "1.1.1", - "resolved": "https://npm.corp.appnexus.com/hawk/-/hawk-1.1.1.tgz", - "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", - "dev": true, - "requires": { - "boom": "0.4.2", - "cryptiles": "0.2.2", - "hoek": "0.9.1", - "sntp": "0.2.4" - } - }, - "hoek": { - "version": "0.9.1", - "resolved": "https://npm.corp.appnexus.com/hoek/-/hoek-0.9.1.tgz", - "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", - "dev": true - }, - "http-signature": { - "version": "0.10.1", - "resolved": "https://npm.corp.appnexus.com/http-signature/-/http-signature-0.10.1.tgz", - "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", - "dev": true, - "requires": { - "asn1": "0.1.11", - "assert-plus": "0.1.5", - "ctype": "0.5.3" - } - }, - "inquirer": { - "version": "0.8.5", - "resolved": "https://npm.corp.appnexus.com/inquirer/-/inquirer-0.8.5.tgz", - "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", - "dev": true, - "requires": { - "ansi-regex": "1.1.1", - "chalk": "1.1.3", - "cli-width": "1.1.1", - "figures": "1.7.0", - "lodash": "3.10.1", - "readline2": "0.1.1", - "rx": "2.5.3", - "through": "2.3.8" - } - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "mime": { - "version": "1.2.11", - "resolved": "https://npm.corp.appnexus.com/mime/-/mime-1.2.11.tgz", - "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", - "dev": true - }, - "mime-types": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/mime-types/-/mime-types-1.0.2.tgz", - "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", - "dev": true - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://npm.corp.appnexus.com/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true - }, - "oauth-sign": { - "version": "0.5.0", - "resolved": "https://npm.corp.appnexus.com/oauth-sign/-/oauth-sign-0.5.0.tgz", - "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", - "dev": true - }, - "qs": { - "version": "2.3.3", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-2.3.3.tgz", - "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", - "dev": true - }, - "request": { - "version": "2.49.0", - "resolved": "https://npm.corp.appnexus.com/request/-/request-2.49.0.tgz", - "integrity": "sha1-DU9jSNwzSAWbVT5Ntg/SR43mYqc=", - "dev": true, - "requires": { - "aws-sign2": "0.5.0", - "bl": "0.9.5", - "caseless": "0.8.0", - "combined-stream": "0.0.7", - "forever-agent": "0.5.2", - "form-data": "0.1.4", - "hawk": "1.1.1", - "http-signature": "0.10.1", - "json-stringify-safe": "5.0.1", - "mime-types": "1.0.2", - "node-uuid": "1.4.8", - "oauth-sign": "0.5.0", - "qs": "2.3.3", - "stringstream": "0.0.6", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.4.3" - } - }, - "sntp": { - "version": "0.2.4", - "resolved": "https://npm.corp.appnexus.com/sntp/-/sntp-0.2.4.tgz", - "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", - "dev": true, - "requires": { - "hoek": "0.9.1" - } - }, - "supports-color": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-1.3.1.tgz", - "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", - "dev": true - } - } - }, - "webpack": { - "version": "3.12.0", - "resolved": "https://npm.corp.appnexus.com/webpack/-/webpack-3.12.0.tgz", - "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", - "dev": true, - "requires": { - "acorn": "5.6.2", - "acorn-dynamic-import": "2.0.2", - "ajv": "6.2.0", - "ajv-keywords": "3.2.0", - "async": "2.6.1", - "enhanced-resolve": "3.4.1", - "escope": "3.6.0", - "interpret": "1.1.0", - "json-loader": "0.5.7", - "json5": "0.5.1", - "loader-runner": "2.3.0", - "loader-utils": "1.1.0", - "memory-fs": "0.4.1", - "mkdirp": "0.5.1", - "node-libs-browser": "2.1.0", - "source-map": "0.5.7", - "supports-color": "4.5.0", - "tapable": "0.2.8", - "uglifyjs-webpack-plugin": "0.4.6", - "watchpack": "1.6.0", - "webpack-sources": "1.1.0", - "yargs": "8.0.2" - }, - "dependencies": { - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "async": { - "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.10" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://npm.corp.appnexus.com/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.1" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "2.3.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://npm.corp.appnexus.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - }, - "yargs": { - "version": "8.0.2", - "resolved": "https://npm.corp.appnexus.com/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.2", - "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.1", - "yargs-parser": "7.0.0" - } - } - } - }, - "webpack-core": { - "version": "0.6.9", - "resolved": "https://npm.corp.appnexus.com/webpack-core/-/webpack-core-0.6.9.tgz", - "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", - "dev": true, - "requires": { - "source-list-map": "0.1.8", - "source-map": "0.4.4" - }, - "dependencies": { - "source-list-map": { - "version": "0.1.8", - "resolved": "https://npm.corp.appnexus.com/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "webpack-dev-middleware": { - "version": "1.12.2", - "resolved": "https://npm.corp.appnexus.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", - "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", - "dev": true, - "requires": { - "memory-fs": "0.4.1", - "mime": "1.6.0", - "path-is-absolute": "1.0.1", - "range-parser": "1.0.3", - "time-stamp": "2.0.0" - }, - "dependencies": { - "time-stamp": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/time-stamp/-/time-stamp-2.0.0.tgz", - "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", - "dev": true - } - } - }, - "webpack-sources": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", - "dev": true, - "requires": { - "source-list-map": "2.0.0", - "source-map": "0.6.1" - } - }, - "webpack-stream": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/webpack-stream/-/webpack-stream-3.2.0.tgz", - "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", - "dev": true, - "requires": { - "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://npm.corp.appnexus.com/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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://npm.corp.appnexus.com/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://npm.corp.appnexus.com/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.2" - } - }, - "browserify-aes": { - "version": "0.4.0", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true, - "requires": { - "pako": "0.2.9" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://npm.corp.appnexus.com/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://npm.corp.appnexus.com/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.2.4", - "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.1.0" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/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": { - "version": "1.0.4", - "resolved": "https://npm.corp.appnexus.com/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "crypto-browserify": { - "version": "3.3.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://npm.corp.appnexus.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.2.0", - "tapable": "0.1.10" - }, - "dependencies": { - "memory-fs": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/memory-fs/-/memory-fs-0.2.0.tgz", - "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", - "dev": true - } - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "https-browserify": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", - "dev": true - }, - "interpret": { - "version": "0.6.6", - "resolved": "https://npm.corp.appnexus.com/interpret/-/interpret-0.6.6.tgz", - "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://npm.corp.appnexus.com/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://npm.corp.appnexus.com/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" - } - }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://npm.corp.appnexus.com/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, - "memory-fs": { - "version": "0.3.0", - "resolved": "https://npm.corp.appnexus.com/memory-fs/-/memory-fs-0.3.0.tgz", - "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", - "dev": true, - "requires": { - "errno": "0.1.7", - "readable-stream": "2.3.6" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "node-libs-browser": { - "version": "0.7.0", - "resolved": "https://npm.corp.appnexus.com/node-libs-browser/-/node-libs-browser-0.7.0.tgz", - "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", - "dev": true, - "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.1.4", - "buffer": "4.9.1", - "console-browserify": "1.1.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.6", - "stream-browserify": "2.0.1", - "stream-http": "2.8.3", - "string_decoder": "0.10.31", - "timers-browserify": "2.0.10", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.4", - "vm-browserify": "0.0.4" - } - }, - "os-browserify": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/os-browserify/-/os-browserify-0.2.1.tgz", - "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", - "dev": true - }, - "pako": { - "version": "0.2.9", - "resolved": "https://npm.corp.appnexus.com/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "ripemd160": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/ripemd160/-/ripemd160-0.2.0.tgz", - "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", - "dev": true - }, - "sha.js": { - "version": "2.2.6", - "resolved": "https://npm.corp.appnexus.com/sha.js/-/sha.js-2.2.6.tgz", - "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://npm.corp.appnexus.com/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - }, - "tapable": { - "version": "0.1.10", - "resolved": "https://npm.corp.appnexus.com/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", - "dev": true - }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://npm.corp.appnexus.com/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", - "dev": true, - "requires": { - "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://npm.corp.appnexus.com/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - } - } - }, - "url": { - "version": "0.11.0", - "resolved": "https://npm.corp.appnexus.com/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://npm.corp.appnexus.com/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://npm.corp.appnexus.com/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "watchpack": { - "version": "0.2.9", - "resolved": "https://npm.corp.appnexus.com/watchpack/-/watchpack-0.2.9.tgz", - "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", - "dev": true, - "requires": { - "async": "0.9.2", - "chokidar": "1.7.0", - "graceful-fs": "4.1.11" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://npm.corp.appnexus.com/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - } - } - }, - "webpack": { - "version": "1.15.0", - "resolved": "https://npm.corp.appnexus.com/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.1", - "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" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://npm.corp.appnexus.com/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - } - } - }, - "websocket-driver": { - "version": "0.7.0", - "resolved": "https://npm.corp.appnexus.com/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true, - "requires": { - "http-parser-js": "0.4.13", - "websocket-extensions": "0.1.3" - } - }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://npm.corp.appnexus.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", - "dev": true - }, - "wgxpath": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/wgxpath/-/wgxpath-1.0.0.tgz", - "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", - "dev": true - }, - "when": { - "version": "3.7.8", - "resolved": "https://npm.corp.appnexus.com/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true, - "optional": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://npm.corp.appnexus.com/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://npm.corp.appnexus.com/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true - }, - "with-callback": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/with-callback/-/with-callback-1.0.2.tgz", - "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://npm.corp.appnexus.com/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" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://npm.corp.appnexus.com/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://npm.corp.appnexus.com/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "0.5.1" - } - }, - "ws": { - "version": "3.3.3", - "resolved": "https://npm.corp.appnexus.com/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "1.0.0", - "safe-buffer": "5.1.2", - "ultron": "1.1.1" - } - }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://npm.corp.appnexus.com/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", - "dev": true - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://npm.corp.appnexus.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://npm.corp.appnexus.com/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://npm.corp.appnexus.com/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://npm.corp.appnexus.com/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "1.3.3", - "resolved": "https://npm.corp.appnexus.com/yargs/-/yargs-1.3.3.tgz", - "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", - "dev": true - }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "https://npm.corp.appnexus.com/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true, - "requires": { - "camelcase": "4.1.0" - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://npm.corp.appnexus.com/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - }, - "zip-stream": { - "version": "0.5.2", - "resolved": "https://npm.corp.appnexus.com/zip-stream/-/zip-stream-0.5.2.tgz", - "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", - "dev": true, - "requires": { - "compress-commons": "0.2.9", - "lodash": "3.2.0", - "readable-stream": "1.0.34" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://npm.corp.appnexus.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lodash": { - "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/lodash/-/lodash-3.2.0.tgz", - "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://npm.corp.appnexus.com/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://npm.corp.appnexus.com/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - } - } -} diff --git a/test/spec/modules/districtmDmxAdapter_spec.js b/test/spec/modules/districtmDmxAdapter_spec.js new file mode 100644 index 00000000000..d3ab685e20c --- /dev/null +++ b/test/spec/modules/districtmDmxAdapter_spec.js @@ -0,0 +1,533 @@ +import {expect} from 'chai'; +import * as _ from 'lodash'; +import {spec, matchRequest, checkDeepArray, defaultSize} from '../../../modules/districtmDmxAdapter'; + +const bidRequest = [{ + 'bidder': 'districtmDMX', + 'params': { + 'dmxid': 100001, + 'memberid': 100003 + }, + 'adUnitCode': 'div-gpt-ad-12345678-1', + 'transactionId': 'f6d13fa6-ebc1-41ac-9afa-d8171d22d2c2', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '29a28a1bbc8a8d', + 'bidderRequestId': '124b579a136515', + 'auctionId': '3d62f2d3-56a2-4991-888e-f7754619ddcf' +}]; + +const bidderRequest = { + 'bidderCode': 'districtmDMX', + 'auctionId': '3d62f2d3-56a2-4991-888e-f7754619ddcf', + 'bidderRequestId': '124b579a136515', + 'bids': [{ + 'bidder': 'districtmDMX', + 'params': { + 'dmxid': 100001, + 'memberid': 100003 + }, + 'adUnitCode': 'div-gpt-ad-12345678-1', + 'transactionId': 'f6d13fa6-ebc1-41ac-9afa-d8171d22d2c2', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '29a28a1bbc8a8d', + 'bidderRequestId': '124b579a136515', + 'auctionId': '3d62f2d3-56a2-4991-888e-f7754619ddcf' + }], + 'auctionStart': 1529511035677, + 'timeout': 700, + 'gdprConsent': { + 'consentString': 'BOPqNzUOPqNzUAHABBAAA5AAAAAAAA', + 'vendorData': { + 'metadata': 'BOPqNzUOPqNzUAHABBAAA5AAAAAAAA', + 'hasGlobalScope': false, + 'gdprApplies': true, + 'purposeConsents': { + '1': false, + '2': false, + '3': false, + '4': false, + '5': false + }, + 'vendorConsents': { + '1': false, + '2': false, + '3': false, + '4': false, + '6': false, + '7': false, + '8': false, + '9': false, + '10': false, + '11': false, + '12': false, + '13': false, + '14': false, + '15': false, + '16': false, + '17': false, + '18': false, + '19': false, + '20': false, + '21': false, + '22': false, + '23': false, + '24': false, + '25': false, + '26': false, + '27': false, + '28': false, + '29': false, + '30': false, + '31': false, + '32': false, + '33': false, + '34': false, + '35': false, + '36': false, + '37': false, + '38': false, + '39': false, + '40': false, + '41': false, + '42': false, + '43': false, + '44': false, + '45': false, + '46': false, + '47': false, + '48': false, + '49': false, + '50': false, + '51': false, + '52': false, + '53': false, + '55': false, + '56': false, + '57': false, + '58': false, + '59': false, + '60': false, + '61': false, + '62': false, + '63': false, + '64': false, + '65': false, + '66': false, + '67': false, + '68': false, + '69': false, + '70': false, + '71': false, + '72': false, + '73': false, + '74': false, + '75': false, + '76': false, + '77': false, + '78': false, + '79': false, + '80': false, + '81': false, + '82': false, + '83': false, + '84': false, + '85': false, + '86': false, + '87': false, + '88': false, + '89': false, + '90': false, + '91': false, + '92': false, + '93': false, + '94': false, + '95': false, + '97': false, + '98': false, + '100': false, + '101': false, + '102': false, + '104': false, + '105': false, + '108': false, + '109': false, + '110': false, + '111': false, + '112': false, + '113': false, + '114': false, + '115': false, + '119': false, + '120': false, + '122': false, + '124': false, + '125': false, + '126': false, + '127': false, + '128': false, + '129': false, + '130': false, + '131': false, + '132': false, + '133': false, + '134': false, + '136': false, + '138': false, + '139': false, + '140': false, + '141': false, + '142': false, + '143': false, + '144': false, + '145': false, + '147': false, + '148': false, + '149': false, + '150': false, + '151': false, + '152': false, + '153': false, + '154': false, + '155': false, + '156': false, + '157': false, + '158': false, + '159': false, + '160': false, + '161': false, + '162': false, + '163': false, + '164': false, + '165': false, + '167': false, + '168': false, + '169': false, + '170': false, + '171': false, + '173': false, + '174': false, + '175': false, + '177': false, + '178': false, + '179': false, + '180': false, + '182': false, + '183': false, + '184': false, + '185': false, + '188': false, + '189': false, + '190': false, + '191': false, + '192': false, + '193': false, + '194': false, + '195': false, + '197': false, + '198': false, + '199': false, + '200': false, + '201': false, + '202': false, + '203': false, + '205': false, + '206': false, + '208': false, + '209': false, + '210': false, + '211': false, + '212': false, + '213': false, + '214': false, + '215': false, + '216': false, + '217': false, + '218': false, + '223': false, + '224': false, + '225': false, + '226': false, + '227': false, + '228': false, + '229': false, + '230': false, + '231': false, + '232': false, + '234': false, + '235': false, + '236': false, + '237': false, + '238': false, + '239': false, + '240': false, + '241': false, + '242': false, + '244': false, + '245': false, + '246': false, + '248': false, + '249': false, + '250': false, + '251': false, + '252': false, + '253': false, + '254': false, + '255': false, + '256': false, + '257': false, + '258': false, + '259': false, + '260': false, + '261': false, + '262': false, + '263': false, + '264': false, + '265': false, + '266': false, + '269': false, + '270': false, + '272': false, + '273': false, + '274': false, + '275': false, + '276': false, + '277': false, + '278': false, + '279': false, + '280': false, + '281': false, + '282': false, + '284': false, + '285': false, + '288': false, + '289': false, + '290': false, + '291': false, + '294': false, + '295': false, + '297': false, + '299': false, + '301': false, + '302': false, + '303': false, + '304': false, + '308': false, + '309': false, + '310': false, + '311': false, + '312': false, + '314': false, + '315': false, + '316': false, + '317': false, + '318': false, + '319': false, + '320': false, + '323': false, + '325': false, + '326': false, + '328': false, + '329': false, + '330': false, + '331': false, + '333': false, + '337': false, + '339': false, + '341': false, + '343': false, + '344': false, + '345': false, + '347': false, + '349': false, + '350': false, + '351': false, + '354': false, + '358': false, + '359': false, + '360': false, + '361': false, + '368': false, + '369': false, + '371': false, + '373': false, + '376': false, + '377': false, + '378': false, + '380': false, + '382': false, + '384': false, + '385': false, + '387': false, + '388': false, + '389': false, + '390': false, + '391': false, + '398': false, + '400': false, + '402': false, + '403': false, + '404': false, + '413': false, + '415': false, + '421': false, + '422': false + } + }, + 'gdprApplies': true + }, + 'start': 1529511035686, + 'doneCbCallCount': 0 +}; + +const responses = { + 'body': { + 'id': '1f45b37c-5298-4934-b517-4d911aadabfd', + 'cur': 'USD', + 'seatbid': [{ + 'bid': [{ + 'id': '29a28a1bbc8a8d', + 'impid': '29a28a1bbc8a8d', + 'price': '6.42', + 'adm': '
' + }] + }] + }, + 'headers': {} +}; + +const responsesNegative = { + 'body': { + 'id': '1f45b37c-5298-4934-b517-4d911aadabfd', + 'cur': 'USD', + 'seatbid': [{ + 'bid': [{ + 'id': '29a28a1bbc8a8d', + 'impid': '29a28a1bbc8a8d', + 'price': '-0.10', + 'adm': '
' + }] + }] + }, + 'headers': {} +}; + +const emptyResponse = { body: {} }; +const emptyResponseSeatBid = { body: { seatbid: [] } }; + +describe('DistrictM Adaptor', () => { + const districtm = spec; + describe('All needed functions are available', () => { + it(`isBidRequestValid is present and type function`, () => { + expect(districtm.isBidRequestValid).to.exist.and.to.be.a('function') + }); + + it(`BuildRequests is present and type function`, () => { + expect(districtm.buildRequests).to.exist.and.to.be.a('function') + }); + + it(`interpretResponse is present and type function`, () => { + expect(districtm.interpretResponse).to.exist.and.to.be.a('function') + }); + + it(`getUserSyncs is present and type function`, () => { + expect(districtm.getUserSyncs).to.exist.and.to.be.a('function') + }); + }); + + describe(`these properties are available or not`, () => { + it(`code should have a value of districtmDMX`, () => { + expect(districtm.code).to.be.equal('districtmDMX'); + }); + + it(`timeout should not be defined`, () => { + expect(districtm.onTimeout).to.be.an('undefined'); + }); + }); + + describe(`isBidRequestValid test response`, () => { + let params = { + dmxid: 10001, + memberid: 10003, + }; + it(`function should return true`, () => { + expect(districtm.isBidRequestValid({params})).to.be.equal(true); + }); + it(`function should return false`, () => { + expect(districtm.isBidRequestValid({ params: { memberid: 12345 } })).to.be.equal(false); + }); + it(`expect to have two property available dmxid and memberid`, () => { + expect(params).to.have.property('dmxid'); + expect(params).to.have.property('memberid'); + }); + }); + + describe(`getUserSyncs test usage`, () => { + it(`return value should be an array`, () => { + expect(districtm.getUserSyncs({ iframeEnabled: true })).to.be.an('array'); + }); + it(`array should have only one object and it should have a property type = 'iframe'`, () => { + expect(districtm.getUserSyncs({ iframeEnabled: true }).length).to.be.equal(1); + let [userSync] = districtm.getUserSyncs({ iframeEnabled: true }); + expect(userSync).to.have.property('type'); + expect(userSync.type).to.be.equal('iframe'); + }); + }); + + describe(`buildRequests test usage`, () => { + const buildRequestResults = districtm.buildRequests(bidRequest, bidderRequest); + it(`the function should return an array`, () => { + expect(buildRequestResults).to.be.an('object'); + }); + it(`the function should return array length of 1`, () => { + expect(buildRequestResults.data).to.be.a('string'); + }); + }); + + describe(`interpretResponse test usage`, () => { + const responseResults = districtm.interpretResponse(responses, {bidderRequest}); + const emptyResponseResults = districtm.interpretResponse(emptyResponse, {bidderRequest}); + const emptyResponseResultsNegation = districtm.interpretResponse(responsesNegative, {bidderRequest}); + const emptyResponseResultsEmptySeat = districtm.interpretResponse(emptyResponseSeatBid, {bidderRequest}); + it(`the function should return an array`, () => { + expect(responseResults).to.be.an('array'); + }); + it(`the function should return array length of 1`, () => { + expect(responseResults.length).to.be.equal(1); + }); + it(`the response return nothing`, () => { + expect(emptyResponseResults.length).to.be.equal(0); + }); + it(`the response seatbid return nothing`, () => { + expect(emptyResponseResultsEmptySeat.length).to.be.equal(0); + }); + + it(`on invalid CPM`, () => { + expect(emptyResponseResultsNegation.length).to.be.equal(0); + }); + }); + + describe(`Helper function testing`, () => { + const bid = matchRequest('29a28a1bbc8a8d', {bidderRequest}); + const {width, height} = defaultSize(bid); + it(`test matchRequest`, () => { + expect(matchRequest('29a28a1bbc8a8d', {bidderRequest})).to.be.an('object'); + }); + it(`test checkDeepArray`, () => { + expect(_.isEqual(checkDeepArray([728, 90]), [728, 90])).to.be.equal(true); + expect(_.isEqual(checkDeepArray([[728, 90]]), [728, 90])).to.be.equal(true); + expect(_.isEqual(checkDeepArray([[728, 90], [300, 250]]), [728, 90])).to.be.equal(true); + expect(_.isEqual(checkDeepArray([[300, 250], [300, 250]]), [728, 90])).to.be.equal(false); + expect(_.isEqual(checkDeepArray([300, 250]), [300, 250])).to.be.equal(true); + }); + it(`test defaultSize`, () => { + expect(width).to.be.equal(300); + expect(height).to.be.equal(250); + }); + }); +}); From c2649de095b17e9612273eacfd1ecf85ed115ef6 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 10 Jul 2018 13:54:32 -0400 Subject: [PATCH 0539/1594] Adding package-lock file --- package-lock.json | 12024 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 12024 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000000..08fc89fbd73 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12024 @@ +{ + "name": "prebid.js", + "version": "1.16.0-pre", + "lockfileVersion": 1, + "dependencies": { + "@gulp-sourcemaps/identity-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", + "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@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=" + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "dev": true + }, + "@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "dev": true + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "accepts": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "dev": true + }, + "acorn": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.2.tgz", + "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw==" + }, + "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, + "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": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "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 + } + } + }, + "addressparser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", + "dev": true, + "optional": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", + "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", + "dev": true + }, + "ajv": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", + "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", + "dev": true + }, + "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 + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "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 + } + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "amqplib": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", + "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", + "dev": true, + "optional": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "optional": true + }, + "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, + "optional": true + } + } + }, + "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 + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true + }, + "archiver": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", + "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", + "dev": true, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "glob": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lazystream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", + "dev": true + }, + "lodash": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "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 + }, + "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 + } + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "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 + }, + "array-iterate": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", + "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", + "dev": true + }, + "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 + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true + }, + "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 + }, + "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 + }, + "array.from": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", + "integrity": "sha1-LGJ7G3bf8t7yNl+gUrZcPVheX2s=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://npm.corp.appnexus.com/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://npm.corp.appnexus.com/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true + } + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "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 + }, + "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 + }, + "ast-types": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", + "dev": true + }, + "axios": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", + "dev": true, + "optional": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true + }, + "follow-redirects": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", + "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", + "dev": true, + "optional": true + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true + }, + "babel-core": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", + "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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 + } + } + }, + "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": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "dev": true + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "dev": true + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "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 + }, + "babel-loader": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", + "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", + "dev": true + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", + "dev": true + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", + "dev": true + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", + "dev": true + }, + "babel-plugin-syntax-do-expressions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", + "dev": true + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", + "dev": true + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, + "babel-plugin-syntax-function-bind": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", + "dev": true + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-system-import-transformer": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", + "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", + "dev": true + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "dev": true + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "dev": true + }, + "babel-plugin-transform-decorators-legacy": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", + "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", + "dev": true + }, + "babel-plugin-transform-do-expressions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", + "dev": true + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "dev": true + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true + }, + "babel-plugin-transform-function-bind": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", + "dev": true + }, + "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=" + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "dev": true + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "dev": true + }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "dev": true + }, + "babel-preset-stage-0": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", + "dev": true + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "dev": true + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "dev": true + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "dev": true + }, + "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": { + "version": "6.26.3", + "resolved": "https://npm.corp.appnexus.com/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "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 + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "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=" + }, + "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 + }, + "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": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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 + }, + "babelify": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", + "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw==", + "dev": true + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "bail": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "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 + }, + "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 + }, + "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 + }, + "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 + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "base64-url": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", + "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "basic-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", + "dev": true + }, + "basic-auth-connect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", + "dev": true + }, + "batch": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", + "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "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": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "binaryextensions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", + "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", + "dev": true + }, + "bitsyntax": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "dev": true, + "optional": true + }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "blob": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "dev": true + }, + "block-loader": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/block-loader/-/block-loader-2.1.0.tgz", + "integrity": "sha1-u7OYrVqEPGxx95opb0tt9LAlcxI=", + "dev": true + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", + "dev": true + }, + "body-parser": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", + "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", + "dev": true, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "dependencies": { + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + } + } + } + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true + }, + "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 + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "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 + } + } + }, + "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.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "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 + }, + "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 + }, + "browserify-des": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", + "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", + "dev": true + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "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 + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true + }, + "browserstack": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", + "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", + "dev": true, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true + }, + "semver": { + "version": "5.0.3", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "browserstacktunnel-wrapper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.2.tgz", + "integrity": "sha512-7w7HYA00qjBtuQH0c5rqW7RbWPHyRROqTZofwNp5G0sKc2fYChsTfbHz3ul8Yd+ffkQvR81m+iPjEB004P6kxQ==", + "dev": true, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true + }, + "semver": { + "version": "5.0.3", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true + }, + "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 + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "dev": true + }, + "buffer-more-ints": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "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 + }, + "buildmail": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", + "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", + "dev": true, + "optional": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "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": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", + "dev": true + }, + "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 + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "dev": true, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + } + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "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": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caniuse-lite": { + "version": "1.0.30000851", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000851.tgz", + "integrity": "sha512-Y1ecA1cL9wg0vni8t33nBw/poX8ypm+2c3fbwAESj8cm4ufK9CBFQ1+nUK8Dp5dtFo5Fc3JzkI5DKmQbuIo6hQ==", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "ccount": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", + "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 + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true + }, + "chai-nightwatch": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", + "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", + "dev": true, + "dependencies": { + "assertion-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", + "dev": true + } + } + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true + }, + "character-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", + "dev": true + }, + "character-entities-html4": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", + "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", + "dev": true + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", + "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 + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "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 + } + } + }, + "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 + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true + }, + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "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 + }, + "collapse-white-space": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true + }, + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "dev": true + }, + "color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", + "dev": true + }, + "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 + }, + "colors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", + "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==", + "dev": true + }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true + }, + "comma-separated-tokens": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", + "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", + "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==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compare-versions": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.2.1.tgz", + "integrity": "sha512-2y2nHcopMG/NAyk6vWXlLs86XeM9sik4jmx1tKIgzMi9/RQ2eo758RGpxQO3ErihHmg0RlQITPqgz73y6s7quA==", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compress-commons": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", + "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "compressible": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz", + "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", + "dev": true, + "dependencies": { + "mime-db": { + "version": "1.34.0", + "resolved": "https://npm.corp.appnexus.com/mime-db/-/mime-db-1.34.0.tgz", + "integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o=", + "dev": true + } + } + }, + "compression": { + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/compression/-/compression-1.5.2.tgz", + "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", + "dev": true, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "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 + }, + "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 + }, + "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 + }, + "connect": { + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", + "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", + "dev": true, + "dependencies": { + "bytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + } + } + }, + "connect-livereload": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", + "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", + "dev": true + }, + "connect-timeout": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", + "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true + }, + "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 + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "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==", + "dev": true + }, + "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 + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "cookie": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", + "dev": true + }, + "cookie-parser": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "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=" + }, + "coveralls": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", + "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "dev": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "crc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", + "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", + "dev": true + }, + "crc32-stream": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", + "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "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 + }, + "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 + }, + "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 + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true + }, + "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 + }, + "csrf": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "dev": true + }, + "css": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", + "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=" + } + } + }, + "css-loader": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", + "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", + "dev": true, + "optional": true, + "dependencies": { + "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, + "optional": true + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "optional": true + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true + }, + "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 + }, + "csso": { + "version": "1.3.12", + "resolved": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", + "integrity": "sha1-/GKGlKLTiTiqrEmWdTIY/TEc254=", + "dev": true, + "optional": true + }, + "csurf": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", + "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", + "dev": true + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "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 + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=" + }, + "dargs": { + "version": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", + "dev": true + }, + "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": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", + "dev": true + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "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 + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==" + }, + "debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==" + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "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=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "deep-is": { + "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": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", + "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", + "dev": true + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true + }, + "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": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true + }, + "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-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 + }, + "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 + }, + "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 + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "dev": true, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "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 + }, + "depd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detab": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", + "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", + "dev": true + }, + "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 + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "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=" + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "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 + }, + "disparity": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", + "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", + "dev": true + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true + }, + "doctrine-temporary-fork": { + "version": "2.0.0-alpha-allowarrayindex", + "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", + "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", + "dev": true + }, + "documentation": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", + "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", + "dev": true, + "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 + }, + "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 + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://npm.corp.appnexus.com/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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 + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "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 + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "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, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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 + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "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 + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "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 + }, + "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 + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "dev": true, + "dependencies": { + "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 + } + } + } + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true + }, + "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 + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", + "dev": true, + "optional": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.48", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz", + "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "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=", + "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 + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true + }, + "engine.io": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", + "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", + "dev": true, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + } + } + }, + "engine.io-client": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", + "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", + "dev": true + }, + "engine.io-parser": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "dev": true + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true + }, + "error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true + }, + "errorhandler": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", + "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", + "dev": true, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + } + } + }, + "es5-ext": { + "version": "0.10.45", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==" + }, + "es5-shim": { + "version": "4.5.10", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", + "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==", + "dev": true + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=" + }, + "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 + }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=" + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "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 + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "dependencies": { + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true + }, + "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": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "globals": { + "version": "11.5.0", + "resolved": "https://npm.corp.appnexus.com/globals/-/globals-11.5.0.tgz", + "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "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 + }, + "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 + } + } + }, + "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 + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true + }, + "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 + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz", + "integrity": "sha1-2tMXgSktZmSyUxf9BJ0uKy8CIF0=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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 + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true + }, + "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 + } + } + }, + "eslint-plugin-node": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "dev": true, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", + "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", + "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 + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "estree-walker": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", + "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=" + }, + "event-stream": { + "version": "3.3.4", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "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 + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true + }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true + }, + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, + "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": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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 + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true + } + } + }, + "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, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://npm.corp.appnexus.com/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "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 + } + } + }, + "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 + }, + "express-session": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", + "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "uid-safe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", + "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", + "dev": true + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "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": { + "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 + } + } + }, + "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": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "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, + "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 + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "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 + }, + "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 + }, + "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 + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "faker": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/faker/-/faker-3.1.0.tgz", + "integrity": "sha1-D5CPr05uwCUk5UpX5DLFwBPgjJ8=", + "dev": true + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true + }, + "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 + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "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 + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true + }, + "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 + }, + "file-loader": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", + "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", + "dev": true, + "optional": true, + "dependencies": { + "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, + "optional": true + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "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 + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true + }, + "fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "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, + "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 + } + } + }, + "finalhandler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", + "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "escape-html": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", + "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true + }, + "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": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true + } + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true + }, + "follow-redirects": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz", + "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "foreachasync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", + "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "fork-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true + }, + "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 + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "dev": true + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true + }, + "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 + }, + "fs-copy-file-sync": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz", + "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==", + "dev": true + }, + "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": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + } + } + }, + "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 + }, + "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": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "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 + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true + }, + "deep-extend": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", + "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "dev": true, + "optional": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "optional": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "optional": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", + "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "dev": true, + "optional": true + }, + "ignore-walk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "dev": true, + "optional": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "optional": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true, + "optional": 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 + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "minipass": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", + "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", + "dev": true + }, + "minizlib": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", + "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "dev": true, + "optional": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", + "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", + "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", + "dev": true, + "optional": true + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "optional": true + }, + "npm-bundled": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", + "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", + "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "dev": true, + "optional": true + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "optional": true + }, + "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 + }, + "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, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true + }, + "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, + "optional": true + }, + "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, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "optional": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", + "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "dev": true, + "optional": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "optional": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "optional": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true, + "optional": true + }, + "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, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true, + "optional": 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, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true + }, + "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, + "optional": true + }, + "tar": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", + "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "optional": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "dev": true + } + } + }, + "fstream": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", + "dev": true, + "dependencies": { + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true + } + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "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 + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "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 + }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true + }, + "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 + }, + "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 + }, + "get-uri": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", + "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + } + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "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": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "git-up": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", + "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", + "dev": true + }, + "git-url-parse": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", + "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", + "dev": true + }, + "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 + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "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 + }, + "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 + } + } + }, + "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": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true + }, + "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 + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globals-docs": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", + "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true + } + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true + }, + "got": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.1.tgz", + "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "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 + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "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 + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true + } + } + }, + "gulp-babel": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", + "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", + "dev": true, + "dependencies": { + "babel-core": { + "version": "6.26.3", + "resolved": "https://npm.corp.appnexus.com/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "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 + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "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 + } + } + }, + "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": { + "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 + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "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": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "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, + "dependencies": { + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "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 + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "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.escape": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", + "dev": true + }, + "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 + }, + "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 + }, + "lodash.templatesettings": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", + "dev": true + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "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 + }, + "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 + }, + "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": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "dev": true, + "dependencies": { + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true + } + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true + }, + "gulp-connect": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", + "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", + "dev": true, + "dependencies": { + "body-parser": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "dev": true, + "dependencies": { + "qs": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "dev": true + } + } + }, + "bytes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "dependencies": { + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + } + } + }, + "tiny-lr": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "dev": true + } + } + }, + "gulp-documentation": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", + "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", + "dev": true + }, + "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 + }, + "gulp-footer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", + "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", + "dev": true + }, + "gulp-header": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "dev": true, + "dependencies": { + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true + } + } + }, + "gulp-if": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", + "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", + "dev": true + }, + "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": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + } + } + }, + "gulp-match": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", + "dev": true + }, + "gulp-optimize-js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", + "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", + "dev": true + }, + "gulp-rename": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.3.tgz", + "integrity": "sha512-CmdPM0BjJ105QCX1fk+j7NGhiN/1rCl9HLGss+KllBS/tdYadpjTxqdKyh/5fNV+M3yjT1MFz5z93bXdrTyzAw==", + "dev": true + }, + "gulp-replace": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", + "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", + "dev": true, + "dependencies": { + "event-stream": { + "version": "3.0.20", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", + "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", + "dev": true + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "split": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", + "dev": true + } + } + }, + "gulp-shell": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", + "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", + "dev": true + }, + "gulp-sourcemaps": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=" + }, + "gulp-uglify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", + "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", + "dev": true, + "dependencies": { + "uglify-js": { + "version": "3.4.0", + "resolved": "https://npm.corp.appnexus.com/uglify-js/-/uglify-js-3.4.0.tgz", + "integrity": "sha512-Jcf5naPkX3rVPSQpRn9Vm6Rr572I1gTtR9LnqKgXjmOgfYQ/QS0V2WRStFR53Bdj520M66aCZqt9uzYXgtGrJQ==", + "dev": true + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "dependencies": { + "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 + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "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 + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true + } + } + }, + "gulp-webdriver": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", + "integrity": "sha1-mM6Bz5rganoZB7htEPaThvQ4Oi0=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true + } + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true + }, + "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 + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true + }, + "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": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true + }, + "hast-util-is-element": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", + "integrity": "sha1-P3IWl4sq4U2YdJh4eCZ18zvjzgA=", + "dev": true + }, + "hast-util-sanitize": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", + "integrity": "sha1-0QvWdXoh5ZwTq8iuNTDdO219Z54=", + "dev": true + }, + "hast-util-to-html": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", + "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", + "dev": true + }, + "hast-util-whitespace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", + "integrity": "sha1-vQlpGWJdKTbh/xe8Tff9cn8X7Ok=", + "dev": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", + "dev": true + }, + "hipchat-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", + "dev": true, + "optional": true + }, + "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 + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true + }, + "hosted-git-info": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "dev": true + }, + "html-void-elements": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.3.tgz", + "integrity": "sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==", + "dev": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "http-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true + }, + "http-parser-js": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", + "dev": true + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true + }, + "httpntlm": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "dev": true + }, + "httpreq": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", + "dev": true + }, + "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": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", + "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", + "dev": true + }, + "ieee754": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", + "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", + "dev": true + }, + "ignore": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", + "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", + "dev": true + }, + "ignore-loader": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz", + "integrity": "sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "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 + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", + "dev": true, + "optional": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "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-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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 + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "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 + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "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 + }, + "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 + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "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 + }, + "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": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + } + } + }, + "is-alphabetical": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", + "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", + "dev": true + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", + "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true + }, + "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-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true + }, + "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": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + } + } + }, + "is-decimal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", + "dev": true + }, + "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": { + "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-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 + }, + "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", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true + }, + "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 + }, + "is-generator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", + "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true + }, + "is-hexadecimal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", + "dev": true + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "dev": true + }, + "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 + }, + "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": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + } + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "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 + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "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=", + "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 + }, + "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": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "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 + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-ssh": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", + "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "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 + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "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 + }, + "is-whitespace-character": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", + "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", + "dev": true + }, + "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 + }, + "is-word-character": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", + "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "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 + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true + } + } + }, + "istanbul-api": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", + "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", + "dev": true, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true + } + } + }, + "istanbul-instrumenter-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", + "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz", + "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", + "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", + "dev": true + }, + "istanbul-lib-report": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", + "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", + "dev": true, + "dependencies": { + "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 + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz", + "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==", + "dev": true, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", + "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", + "dev": true + }, + "istextorbinary": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", + "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", + "dev": true + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "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 + }, + "js-yaml": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "json-loader": { + "version": "0.5.7", + "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", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "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": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true + }, + "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 + }, + "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 + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", + "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "JSONStream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz", + "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "just-clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", + "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" + }, + "just-extend": { + "version": "1.1.27", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", + "dev": true + }, + "karma": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.2.tgz", + "integrity": "sha1-TS25QChQpmVR+nhLAWT7CCTtjEs=", + "dev": true, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://npm.corp.appnexus.com/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "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 + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "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 + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "dependencies": { + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true + }, + "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 + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "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 + }, + "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 + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + } + } + }, + "karma-babel-preprocessor": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", + "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", + "dev": true + }, + "karma-browserstack-launcher": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", + "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", + "dev": true, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "karma-chai": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", + "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", + "dev": true + }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true + }, + "karma-coverage-istanbul-reporter": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", + "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", + "dev": true + }, + "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 + }, + "karma-firefox-launcher": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", + "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", + "dev": true + }, + "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 + }, + "karma-mocha": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", + "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", + "dev": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "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": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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 + }, + "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 + } + } + }, + "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 + }, + "karma-requirejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-1.1.0.tgz", + "integrity": "sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=", + "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 + }, + "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 + }, + "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 + }, + "karma-sourcemap-loader": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", + "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", + "dev": true + }, + "karma-spec-reporter": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", + "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", + "dev": true + }, + "karma-webpack": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", + "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", + "dev": true, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "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 + } + } + }, + "kebab-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz", + "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=", + "dev": true + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "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.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true + }, + "lcov-parse": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true + }, + "libbase64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", + "dev": true + }, + "libmime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", + "dev": true, + "dependencies": { + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", + "dev": true + } + } + }, + "libqp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", + "dev": true + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true + }, + "livereload-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", + "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", + "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=", + "dev": true + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true + }, + "localtunnel": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.0.tgz", + "integrity": "sha512-wCIiIHJ8kKIcWkTQE3m1VRABvsH2ZuOkiOpZUofUCf6Q42v3VIZ+Q0YfX1Z4sYDRj0muiKL1bLvz1FeoxsPO0w==", + "dev": true, + "dependencies": { + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "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 + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "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 + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "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 + }, + "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 + }, + "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 + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "lodash._arraycopy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", + "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", + "dev": true + }, + "lodash._arrayeach": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", + "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true + }, + "lodash._baseclone": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", + "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._basefor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", + "dev": true + }, + "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 + }, + "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 + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "lodash._htmlescapes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "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._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.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true + } + } + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "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 + }, + "lodash._stack": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", + "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", + "dev": true + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "lodash.clone": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", + "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "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, + "dependencies": { + "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 + } + } + }, + "lodash.defaultsdeep": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", + "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", + "dev": true, + "dependencies": { + "lodash._baseclone": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", + "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", + "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 + }, + "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 + }, + "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 + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "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 + }, + "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 + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true + }, + "lodash.keysin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", + "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", + "dev": true + }, + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "dev": true + }, + "lodash.rest": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", + "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true + }, + "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": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true + } + } + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "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, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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 + } + } + }, + "log4js": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.8.0.tgz", + "integrity": "sha512-PjsaE4ElS0e2jWOY14Ef2PrC1Y+fny4AWPPT3xD6+2k2Aa5golhqJ4DSzP+5kXRL5bSw/5j1ocU5A9ceaxZeGA==", + "dev": true, + "dependencies": { + "circular-json": { + "version": "0.5.4", + "resolved": "https://npm.corp.appnexus.com/circular-json/-/circular-json-0.5.4.tgz", + "integrity": "sha512-vnJA8KS0BfOihugYEUkLRcnmq21FbuivbxgzDLXNs3zIk4KllV4Mx4UuTzBXht9F00C7QfD1YqMXg1zP6EXpig==", + "dev": true + } + } + }, + "loggly": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", + "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", + "dev": true, + "optional": true, + "dependencies": { + "bl": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", + "dev": true, + "optional": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true, + "optional": 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, + "optional": true + }, + "qs": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "optional": true + }, + "request": { + "version": "2.75.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", + "dev": true, + "optional": true + }, + "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, + "optional": true + } + } + }, + "lolex": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.0.tgz", + "integrity": "sha512-uJkH2e0BVfU5KOJUevbTOtpDduooSarH5PopO+LfM/vZf8Z9sJzODqKev804JYM2i++ktJfUmC1le4LwFQ1VMg==", + "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.2", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=" + }, + "magic-string": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", + "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", + "dev": true + }, + "mailcomposer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", + "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", + "dev": true, + "optional": true + }, + "mailgun-js": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.0.tgz", + "integrity": "sha512-o0P6jjZlx5CQj12tvVgDTbgjTqVN0+5h6/6P1+3c6xmozVKBwniQ6Qt3MkCSF0+ueVTbobAfWyGpWRZMJu8t1g==", + "dev": true, + "optional": true, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "optional": true + } + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true + }, + "make-error": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "dev": true + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "dev": true + }, + "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 + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "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.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "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 + }, + "markdown-escapes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", + "dev": true + }, + "markdown-table": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", + "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", + "dev": true + }, + "match-stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true + }, + "mdast-util-compact": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", + "dev": true + }, + "mdast-util-definitions": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", + "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", + "dev": true + }, + "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 + }, + "mdast-util-to-hast": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.1.tgz", + "integrity": "sha512-+eimV/12kdg0/T0EEfcK7IsDbSu2auVm92z5jdSEQ3DHF2HiU4OHmX9ir5wpQajr73nwabdxrUoxREvW2zVFFw==", + "dev": true + }, + "mdast-util-to-string": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", + "integrity": "sha1-XEVch4yTVfDB5/PotxnPWDaRrPs=", + "dev": true + }, + "mdast-util-toc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", + "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", + "dev": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true + }, + "memoizee": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz", + "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==" + }, + "memory-fs": { + "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 + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "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 + }, + "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 + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "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 + }, + "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 + }, + "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 + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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 + }, + "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 + }, + "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 + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true + }, + "method-override": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", + "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "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 + }, + "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 + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true + }, + "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 + }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=", + "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.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "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 + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true + }, + "mkpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", + "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", + "dev": true + }, + "mocha": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", + "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", + "dev": true, + "dependencies": { + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "debug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", + "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "glob": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "dev": true + }, + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + }, + "growl": { + "version": "1.8.1", + "resolved": "https://npm.corp.appnexus.com/growl/-/growl-1.8.1.tgz", + "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true + }, + "ms": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", + "dev": true + }, + "supports-color": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz", + "integrity": "sha1-Eu4hUHCGzZjBBY2ewPSsR2t687I=", + "dev": true + } + } + }, + "mocha-nightwatch": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", + "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", + "dev": true, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "glob": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "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 + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true + } + } + }, + "mock-fs": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", + "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", + "dev": true, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "module-deps-sortable": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", + "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", + "dev": true, + "dependencies": { + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "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 + }, + "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 + } + } + }, + "module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", + "dev": true + }, + "morgan": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", + "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multiparty": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", + "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + }, + "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 + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + }, + "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 + } + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true + }, + "natives": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", + "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", + "dev": true + }, + "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 + }, + "ncp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", + "dev": true + }, + "negotiator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", + "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", + "dev": true + }, + "neo-async": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", + "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", + "dev": true + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "nightwatch": { + "version": "0.9.21", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.21.tgz", + "integrity": "sha1-nnlKdRS0/V9GYC02jlBRUjKrnpA=", + "dev": true, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "co": { + "version": "3.0.6", + "resolved": "https://npm.corp.appnexus.com/co/-/co-3.0.6.tgz", + "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "ejs": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://npm.corp.appnexus.com/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true + }, + "http-proxy-agent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", + "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", + "dev": true + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true + }, + "ip": { + "version": "1.0.1", + "resolved": "https://npm.corp.appnexus.com/ip/-/ip-1.0.1.tgz", + "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", + "dev": true + }, + "lru-cache": { + "version": "2.6.5", + "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.6.5.tgz", + "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", + "dev": true + }, + "minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "dev": true + }, + "pac-proxy-agent": { + "version": "1.1.0", + "resolved": "https://npm.corp.appnexus.com/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", + "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", + "dev": true + }, + "pac-resolver": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/pac-resolver/-/pac-resolver-2.0.0.tgz", + "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", + "dev": true + }, + "proxy-agent": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/proxy-agent/-/proxy-agent-2.0.0.tgz", + "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", + "dev": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true + }, + "semver": { + "version": "5.0.3", + "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + }, + "socks-proxy-agent": { + "version": "2.1.1", + "resolved": "https://npm.corp.appnexus.com/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", + "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", + "dev": true + } + } + }, + "nise": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.1.tgz", + "integrity": "sha512-9JX3YwoIt3kS237scmSSOpEv7vCukVzLfwK0I0XhocDSHUANid8ZHnLEULbbSkfeMn98B2y5kphIWzZUylESRQ==", + "dev": true + }, + "node-int64": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", + "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", + "dev": true + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "dependencies": { + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + } + } + }, + "nodemailer": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", + "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", + "dev": true, + "optional": true, + "dependencies": { + "socks": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", + "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", + "dev": true, + "optional": true + } + } + }, + "nodemailer-direct-transport": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", + "dev": true, + "optional": true + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", + "dev": true + }, + "nodemailer-shared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", + "dev": true + }, + "nodemailer-smtp-pool": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", + "dev": true, + "optional": true + }, + "nodemailer-smtp-transport": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", + "dev": true, + "optional": true + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "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=" + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true + }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "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": { + "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 + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + } + } + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "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 + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true + }, + "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 + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "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 + } + } + }, + "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 + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true + }, + "open": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", + "dev": true + }, + "openurl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optimize-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", + "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", + "dev": true, + "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 + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "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 + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "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 + }, + "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 + }, + "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 + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "dependencies": { + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true + } + } + }, + "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 + }, + "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-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true + }, + "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 + }, + "over": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", + "dev": true + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "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 + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dev": true + }, + "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 + }, + "pac-proxy-agent": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", + "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", + "dev": true, + "optional": true, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true, + "optional": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "optional": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://npm.corp.appnexus.com/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "optional": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "optional": true + } + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "dev": true, + "optional": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true + }, + "parse-domain": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.1.tgz", + "integrity": "sha512-xOQ/B+pnS8uzqFMHcS7VS9J7Cn+rFyPlGIoDMFL2e5g/tPhlpa8MSHQmFAlABHBKPCXgOOxFt5PFNdEmwtwvqQ==", + "dev": true, + "dependencies": { + "chai": { + "version": "4.1.2", + "resolved": "https://npm.corp.appnexus.com/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true + }, + "commander": { + "version": "2.11.0", + "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://npm.corp.appnexus.com/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true + }, + "diff": { + "version": "3.3.1", + "resolved": "https://npm.corp.appnexus.com/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://npm.corp.appnexus.com/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + } + } + }, + "parse-entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.2.tgz", + "integrity": "sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg==", + "dev": true + }, + "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 + }, + "parse-git-config": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", + "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", + "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, + "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 + } + } + }, + "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 + }, + "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 + }, + "parse-url": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", + "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "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 + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "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 + }, + "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 + }, + "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 + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-proxy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "dev": true, + "optional": true, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", + "dev": true, + "optional": true + } + } + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true + }, + "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 + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "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 + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pause": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", + "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", + "dev": true + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "dev": true + }, + "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 + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "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 + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "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 + }, + "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 + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "promisify-call": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", + "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", + "dev": true, + "optional": true + }, + "property-information": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", + "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE=", + "dev": true + }, + "protocols": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", + "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", + "dev": true + }, + "proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.0.tgz", + "integrity": "sha512-g6n6vnk8fRf705ShN+FEXFG/SDJaW++lSs0d9KaJh4uBWW/wi7en4Cpo5VYQW3SZzAE121lhB/KLQrbURoubZw==", + "dev": true, + "optional": true + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true, + "optional": true + }, + "proxyquire": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", + "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", + "dev": true, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "dev": true + }, + "pullstream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", + "integrity": "sha1-hQ15+MuDHZLhA7Rkg+TjXTRkAFA=", + "dev": true + }, + "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 + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "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": "0.0.3", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", + "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", + "dev": true + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "dev": true + }, + "randomatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "dev": true, + "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.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true + }, + "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 + }, + "range-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", + "dev": true + }, + "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": { + "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 + } + } + }, + "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 + }, + "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 + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==" + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true + }, + "readline2": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", + "dev": true, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true + }, + "mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", + "dev": true + }, + "strip-ansi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", + "dev": true + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true + }, + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "dev": true, + "optional": true + }, + "redis-commands": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", + "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==", + "dev": true, + "optional": true + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", + "dev": true, + "optional": true + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "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.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true + }, + "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 + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "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": "9.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", + "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", + "dev": true + }, + "remark-html": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", + "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", + "dev": true + }, + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true + }, + "remark-reference-links": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.1.tgz", + "integrity": "sha1-AhrtHFXBh9cSs8dtAFe/UQ0wC6c=", + "dev": true + }, + "remark-slug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", + "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", + "dev": true + }, + "remark-stringify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", + "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", + "dev": true + }, + "remark-toc": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", + "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", + "dev": true + }, + "remote-origin-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", + "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", + "dev": true + }, + "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 + }, + "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 + }, + "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=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "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 + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replacestream": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", + "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", + "dev": true + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true + }, + "requestretry": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", + "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", + "dev": true, + "optional": 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-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 + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true + }, + "requirejs": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", + "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", + "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.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "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 + }, + "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 + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "response-time": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", + "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", + "dev": true, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + } + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true + }, + "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 + }, + "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 + }, + "rewire": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", + "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", + "dev": true + }, + "rgb2hex": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.1.tgz", + "integrity": "sha512-icFtYF9bLbxRZ6zYlp28622lBM7Ae0ylPT+ob0SBZdd2p1FN5MoOClpwPcjT9TgXDLS8jyXlw3yVtHQZU3/vvg==", + "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 + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true + }, + "rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", + "dev": true + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true + }, + "rx": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", + "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", + "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 + }, + "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 + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "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": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true + } + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "send": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "statuses": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", + "dev": true + } + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "serve-favicon": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", + "dev": true, + "dependencies": { + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true + } + } + }, + "serve-index": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", + "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "serve-static": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", + "dev": true + }, + "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 + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "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 + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "sha.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 + }, + "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 + }, + "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 + }, + "shelljs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sinon": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", + "dev": true, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "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 + }, + "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 + } + } + }, + "slack-node": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", + "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", + "dev": true, + "optional": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "dependencies": { + "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 + } + } + }, + "slice-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", + "dev": true + }, + "smtp-connection": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", + "dev": true + }, + "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": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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 + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "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 + } + } + }, + "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": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "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 + }, + "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 + }, + "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 + } + } + }, + "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": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + } + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true + }, + "socket.io": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + } + } + }, + "socket.io-parser": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", + "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", + "dev": true, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "socks": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", + "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", + "dev": true + }, + "socks-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", + "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", + "dev": true + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "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==" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==" + }, + "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": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "space-separated-tokens": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", + "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", + "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.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "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 + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "dev": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "state-toggle": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", + "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=", + "dev": true, + "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 + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "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": { + "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=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "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 + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "dev": true + }, + "stream-counter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + }, + "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-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 + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "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==" + }, + "string-replace-webpack-plugin": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", + "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "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 + } + } + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true + }, + "stringify-entities": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", + "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", + "dev": true + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true + }, + "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-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + }, + "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 + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "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 + }, + "style-loader": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", + "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", + "dev": true, + "optional": true, + "dependencies": { + "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, + "optional": true + } + } + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "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 + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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 + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "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 + } + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "tar-stream": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", + "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "ternary-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "dev": true + }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "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 + }, + "textextensions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", + "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", + "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 + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=" + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", + "dev": true + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true + }, + "timers-ext": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", + "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==" + }, + "timespan": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "dev": true, + "optional": 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==", + "dev": true, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true + }, + "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 + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "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": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "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 + } + } + }, + "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 + }, + "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 + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-lines": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.1.tgz", + "integrity": "sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", + "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", + "dev": true + }, + "trough": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.2.tgz", + "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", + "dev": true + }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", + "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.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "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, + "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 + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "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 + }, + "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 + } + } + }, + "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 + }, + "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, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "uid-safe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", + "dev": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "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 + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "unherit": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", + "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "dev": true + }, + "unified": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "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 + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true + } + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true + }, + "unist-builder": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", + "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", + "dev": true + }, + "unist-util-generated": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.2.tgz", + "integrity": "sha512-1HcwiEO62dr0XWGT+abVK4f0aAm8Ik8N08c5nAYVmuSxfvpA9rCcNyX/le8xXj1pJK5nBrGlZefeWB6bN8Pstw==", + "dev": true + }, + "unist-util-is": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz", + "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", + "dev": true + }, + "unist-util-modify-children": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", + "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", + "dev": true + }, + "unist-util-position": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.1.tgz", + "integrity": "sha512-05QfJDPI7PE1BIUtAxeSV+cDx21xP7+tUZgSval5CA7tr0pHBwybF7OnEa1dOFqg6BfYH/qiMUnWwWj+Frhlww==", + "dev": true + }, + "unist-util-remove-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", + "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", + "dev": true + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", + "dev": true + }, + "unist-util-visit": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.1.tgz", + "integrity": "sha512-0fdB9EQJU0tho5tK0VzOJzAQpPv2LyLZ030b10GxuzAWEfvd54mpY7BMjQ1L69k2YNvL+SvxRzH0yUIehOO8aA==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "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": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true + } + } + }, + "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 + } + } + }, + "unzip": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", + "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.1.tgz", + "integrity": "sha512-x95Td74QcvICAA0+qERaVkRpTGKyBHHYdwL2LXZm5t/gBtCB9KQSO/0zQgSTYEV1p0WcvSg79TLNPSvd5IDJMQ==", + "dev": true, + "dependencies": { + "querystringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", + "dev": true + } + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "useragent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", + "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", + "dev": true, + "dependencies": { + "lru-cache": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "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 + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "uws": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", + "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true + }, + "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.0.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", + "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true + }, + "vfile-location": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.3.tgz", + "integrity": "sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==", + "dev": true + }, + "vfile-message": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz", + "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", + "dev": true + }, + "vfile-reporter": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", + "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", + "dev": true, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true + } + } + }, + "vfile-sort": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.1.tgz", + "integrity": "sha512-+fpTWKkVHwI6VF2xtkDTuCA6cH4UPLAxh+KxfU8g8pC0do5RSZCk1HXTTtMJguW0t5jC0PC19owjUZX9SGQ9tw==", + "dev": true + }, + "vfile-statistics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.1.tgz", + "integrity": "sha512-dxUM6IYvGChHuwMT3dseyU5BHprNRXzAV0OHx1A769lVGsTiT50kU7BbpRFV+IE6oWmU+PwHdsTKfXhnDIRIgQ==", + "dev": true + }, + "vhost": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", + "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "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 + }, + "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 + }, + "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": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "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 + }, + "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 + }, + "walk": { + "version": "2.3.13", + "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.13.tgz", + "integrity": "sha512-78SMe7To9U7kqVhSoGho3GfspA089ZDBIj2f8jElg2hi6lUCoagtDJ8sSMFNlpAh5Ib8Jt1gQ6Y7gh9mzHtFng==", + "dev": true + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true + }, + "webdriverio": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz", + "integrity": "sha1-2dTTwxNm8FPhCvZEsOqtXoc6t7U=", + "dev": true, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true + }, + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true + }, + "caseless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", + "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", + "dev": true + }, + "cli-width": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", + "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "dev": true + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true + }, + "hawk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "dev": true + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true + }, + "inquirer": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", + "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", + "dev": true + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true + }, + "oauth-sign": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", + "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", + "dev": true + }, + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + }, + "request": { + "version": "2.49.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", + "integrity": "sha1-DU9jSNwzSAWbVT5Ntg/SR43mYqc=", + "dev": true + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "dev": true + }, + "supports-color": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", + "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", + "dev": true + } + } + }, + "webpack": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", + "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", + "dev": true, + "dependencies": { + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://npm.corp.appnexus.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "async": { + "version": "2.6.1", + "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "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": "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 + }, + "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 + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true + }, + "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 + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "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 + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true + } + } + }, + "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, + "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 + } + } + }, + "webpack-dev-middleware": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "dev": true, + "dependencies": { + "time-stamp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", + "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "dev": true + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true + }, + "webpack-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", + "dev": true, + "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 + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true + }, + "browserify-aes": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", + "dev": true + }, + "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 + }, + "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 + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true + }, + "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 + }, + "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 + }, + "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, + "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 + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true + }, + "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 + }, + "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-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 + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + }, + "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 + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "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 + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true + }, + "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 + }, + "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 + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "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 + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true + }, + "tapable": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "dev": true + }, + "uglify-js": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true + }, + "watchpack": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", + "dev": true, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "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 + }, + "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 + }, + "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 + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "wgxpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", + "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", + "dev": true + }, + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true, + "optional": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true + }, + "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 + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "dev": true + }, + "with-callback": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", + "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "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=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", + "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", + "dev": true + }, + "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 + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "zip-stream": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", + "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lodash": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", + "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 + }, + "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 + } + } + } + } +} From eac09e7d070a55a37bbbd4be57f2a6825b5feeb9 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Tue, 10 Jul 2018 12:54:37 -0700 Subject: [PATCH 0540/1594] OpenX Adapter: Placement Id Support (#2774) * chore: update adapter version number * feat: Added support for placementId as a replacement to ad unit id. --- modules/openxBidAdapter.js | 31 ++- modules/openxBidAdapter.md | 8 + test/spec/modules/openxBidAdapter_spec.js | 233 +++++++++++++++++++--- 3 files changed, 232 insertions(+), 40 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 6a8783a662a..ba3bc98b766 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,9 +8,10 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.1'; +const BIDDER_VERSION = '2.1.2'; let shouldSendBoPixel = true; + export function resetBoPixel() { shouldSendBoPixel = true; } @@ -19,6 +20,10 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { + if (bidRequest.mediaTypes && bidRequest.mediaTypes.banner) { + return !!((bidRequest.params.unit || bidRequest.params.placementId) && bidRequest.params.delDomain); + } + return !!(bidRequest.params.unit && bidRequest.params.delDomain); }, buildRequests: function (bidRequests, bidderRequest) { @@ -48,14 +53,14 @@ export const spec = { return mediaType === VIDEO ? createVideoBidResponses(oxResponseObj, serverRequest.payload) : createBannerBidResponses(oxResponseObj, serverRequest.payload); }, - getUserSyncs: function(syncOptions, responses) { + getUserSyncs: function (syncOptions, responses) { if (syncOptions.iframeEnabled) { let url = utils.deepAccess(responses, '0.body.ads.pixels') || - utils.deepAccess(responses, '0.body.pixels') || - '//u.openx.net/w/1.0/pd'; + utils.deepAccess(responses, '0.body.pixels') || + '//u.openx.net/w/1.0/pd'; return [{ type: 'iframe', - url: url, + url: url }]; } } @@ -214,14 +219,22 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { } function buildOXBannerRequest(bids, bidderRequest) { + let customParamsForAllBids = []; + let hasCustomParam = false; let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); - - queryParams.auid = utils._map(bids, bid => bid.params.unit).join(','); + let auids = utils._map(bids, bid => bid.params.unit); + let pids = utils._map(bids, bid => bid.params.placementId); queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); queryParams.bc = bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`; + queryParams.divs = utils._map(bids, bid => bid.adUnitCode).join(','); + + if (auids.some(auid => auid)) { + queryParams.auid = auids.join(','); + } + if (pids.some(pid => pid)) { + queryParams.pids = pids.join(','); + } - let customParamsForAllBids = []; - let hasCustomParam = false; bids.forEach(function (bid) { if (bid.params.customParams) { let customParamsForBid = utils._map(Object.keys(bid.params.customParams), customKey => formatCustomParms(customKey, bid.params.customParams)); diff --git a/modules/openxBidAdapter.md b/modules/openxBidAdapter.md index 9e9d3ebfa7a..a7a39a8412e 100644 --- a/modules/openxBidAdapter.md +++ b/modules/openxBidAdapter.md @@ -21,6 +21,7 @@ Module that connects to OpenX's demand sources { bidder: 'openx', params: { + placementId: '/123/abcdefg' unit: '539439964', delDomain: 'se-demo-d.openx.net' } @@ -46,3 +47,10 @@ Module that connects to OpenX's demand sources } ]; ``` + + +# Links +[Banner Ads](https://docs.openx.com/Content/developers/containers/prebid-adapter.html) + +[Video Ads](https://docs.openx.com/Content/developers/containers/prebid-video-adapter.html) + diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 3585987e045..7f9cac405c3 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -129,34 +129,43 @@ describe('OpenxAdapter', () => { describe('isBidRequestValid', () => { describe('when request is for a banner ad', () => { - const bannerBid = { - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: {banner: {}}, - sizes: [[300, 250], [300, 600]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }; - - it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + let bannerBid; + beforeEach(() => { + bannerBid = { + bidder: 'openx', + params: {}, + adUnitCode: 'adunit-code', + mediaTypes: {banner: {}}, + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475' + }; }); it('should return false when there is no delivery domain', () => { - let bid = Object.assign({}, bannerBid); - bid.params = {'unit': '12345678'}; - expect(spec.isBidRequestValid(bid)).to.equal(false); + bannerBid.params = {'unit': '12345678'}; + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); - it('should return false when there is no ad unit id ', () => { - let bid = Object.assign({}, bannerBid); - bid.params = {delDomain: 'test-del-domain'}; - expect(spec.isBidRequestValid(bid)).to.equal(false); + describe('when there is a delivery domain', () => { + beforeEach(function () { + bannerBid.params = {delDomain: 'test-delivery-domain'} + }); + + it('should return false when there is no ad unit id and no placement id', () => { + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); + }); + + it('should return true if there is an adunit id ', () => { + bannerBid.params.unit = '12345678'; + expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + }); + + it('should return true if there is an placement id ', () => { + bannerBid.params.placementId = '/12345678/aaaa/bbbb'; + expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + }); }); }); @@ -186,7 +195,7 @@ describe('OpenxAdapter', () => { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', - 'mediaTypes': 'video', + 'mediaType': 'video', 'sizes': [640, 480], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -233,7 +242,7 @@ describe('OpenxAdapter', () => { const bidRequestsWithMediaTypes = [{ 'bidder': 'openx', 'params': { - 'unit': '12345678', + 'unit': '11', 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', @@ -242,9 +251,24 @@ describe('OpenxAdapter', () => { sizes: [[300, 250], [300, 600]] } }, - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475' + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' }]; it('should send bid request to openx url via GET, with mediaType specified as banner', () => { @@ -259,6 +283,153 @@ describe('OpenxAdapter', () => { expect(request[0].method).to.equal('GET'); }); + it('should send the adunit codes', () => { + const request = spec.buildRequests(bidRequestsWithMediaTypes); + expect(request[0].data.divs).to.equal(`${bidRequestsWithMediaTypes[0].adUnitCode},${bidRequestsWithMediaTypes[1].adUnitCode}`); + }); + + it('should send ad unit ids when any are defined', () => { + const bidRequestsWithPlacementIds = [{ + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithPlacementIds); + expect(request[0].data.auid).to.equal(`,${bidRequestsWithPlacementIds[1].params.unit}`); + }); + + it('should not send any ad unit ids when none are defined', () => { + const bidRequestsWithoutPlacementIds = [{ + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutPlacementIds); + expect(request[0].data).to.not.have.any.keys('auid'); + }); + + it('should send placement ids when any are defined', () => { + const bidRequestsWithPlacementIds = [{ + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain', + placementId: 'test-placement-id-2' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithPlacementIds); + expect(request[0].data.pids).to.equal(`,${bidRequestsWithPlacementIds[1].params.placementId}`); + }); + + it('should not send any placement ids when none are defined', () => { + const bidRequestsWithoutPlacementIds = [{ + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutPlacementIds); + expect(request[0].data).to.not.have.any.keys('pids'); + }); + describe('when there is a legacy request with no media type', function () { const deprecatedBidRequestsFormatWithNoMediaType = [{ 'bidder': 'openx', @@ -1077,10 +1248,10 @@ describe('OpenxAdapter', () => { it('should register the pixel iframe from banner ad response', () => { let syncs = spec.getUserSyncs( - { iframeEnabled: true }, - [{ body: { ads: { pixels: syncUrl } } }] + {iframeEnabled: true}, + [{body: {ads: {pixels: syncUrl}}}] ); - expect(syncs).to.deep.equal([{ type: 'iframe', url: syncUrl }]); + expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); }); it('should register the pixel iframe from video ad response', () => { From df3e34695b88e1dbe85a39be52171ccfcec6761c Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 10 Jul 2018 16:04:44 -0400 Subject: [PATCH 0541/1594] disable flash checks to allow travis build to complete (#2833) --- modules/tripleliftBidAdapter.js | 24 +++++++++---------- .../spec/modules/tripleliftBidAdapter_spec.js | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 5114444be3c..625b5e253f5 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -22,7 +22,7 @@ export const tripleliftAdapterSpec = { tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); - tlCall = utils.tryAppendQueryString(tlCall, 'fe', _isFlashEnabled().toString()); + // tlCall = utils.tryAppendQueryString(tlCall, 'fe', _isFlashEnabled().toString()); tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer); if (bidderRequest && bidderRequest.timeout) { @@ -125,16 +125,16 @@ function _buildResponseObject(bidderRequest, bid) { return bidResponse; } -function _isFlashEnabled() { - let flash; - try { - flash = Boolean(new ActiveXObject('ShockwaveFlash.ShockwaveFlash')); - } catch (e) { - flash = navigator.mimeTypes && - navigator.mimeTypes['application/x-shockwave-flash'] !== undefined && - navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin ? 1 : 0 - } - return flash ? 1 : 0; -} +// function _isFlashEnabled() { +// let flash; +// try { +// flash = Boolean(new ActiveXObject('ShockwaveFlash.ShockwaveFlash')); +// } catch (e) { +// flash = navigator.mimeTypes && +// navigator.mimeTypes['application/x-shockwave-flash'] !== undefined && +// navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin ? 1 : 0 +// } +// return flash ? 1 : 0; +// } registerBidder(tripleliftAdapterSpec); diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 3d5b7d2dcba..c7c023ed726 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -90,7 +90,7 @@ describe('triplelift adapter', () => { expect(url).to.match(/(?:tlx.3lift.com\/header\/auction)/) expect(url).to.match(/(?:lib=prebid)/) expect(url).to.match(/(?:prebid.version)/) - expect(url).to.match(/(?:fe=)/) + // expect(url).to.match(/(?:fe=)/) // expect(url).to.match(/(?:referrer)/) }) }); From 8010d07c90fb410286bc338b8cdaf1ffa67a6567 Mon Sep 17 00:00:00 2001 From: my6sense Date: Tue, 10 Jul 2018 23:10:04 +0300 Subject: [PATCH 0542/1594] My6sense new adapter (#2748) * My6sense new adapter * endpoint fix * Code fix * Added changes in adapter md file * Changed the end point * supportedMediaTypes values added * md file was updated with a valid widget key --- modules/my6senseBidAdapter.js | 197 +++++++++++++++++++ modules/my6senseBidAdapter.md | 36 ++++ test/spec/modules/my6senseBidAdapter_spec.js | 151 ++++++++++++++ 3 files changed, 384 insertions(+) create mode 100644 modules/my6senseBidAdapter.js create mode 100644 modules/my6senseBidAdapter.md create mode 100644 test/spec/modules/my6senseBidAdapter_spec.js diff --git a/modules/my6senseBidAdapter.js b/modules/my6senseBidAdapter.js new file mode 100644 index 00000000000..5796d1a0383 --- /dev/null +++ b/modules/my6senseBidAdapter.js @@ -0,0 +1,197 @@ +import { BANNER, NATIVE } from 'src/mediaTypes'; + +const {registerBidder} = require('../src/adapters/bidderFactory'); +const BIDDER_CODE = 'my6sense'; +const END_POINT = '//papi.mynativeplatform.com/pub2/web/v1.15.0/hbwidget.json'; +const END_POINT_METHOD = 'POST'; + +// called first +function isBidRequestValid(bid) { + return !(bid.bidder !== BIDDER_CODE || !bid.params || !bid.params.key); +} + +function getUrl(url) { + if (!url) { + url = window.location.href;// "clean" url of current web page + } + var canonicalLink = null; + // first look for meta data with property "og:url" + var metaElements = document.getElementsByTagName('meta'); + for (var i = 0; i < metaElements.length && !canonicalLink; i++) { + if (metaElements[i].getAttribute('property') == 'og:url') { + canonicalLink = metaElements[i].content; + } + } + if (!canonicalLink) { + var canonicalLinkContainer = document.querySelector("link[rel='canonical']");// html element containing the canonical link + if (canonicalLinkContainer) { + // get clean url from href of + canonicalLink = canonicalLinkContainer.href; + } + } + url = canonicalLink || url; + return encodeURIComponent(url).toString(); +} + +/** + * this function is used to fix param value before sending them to server, if user did not set it, + * default value for parameter will be returned + * example1: paidClicks: '[PAID_TRACKING_PIXEL]', will return {value: '', fromUser: false} + * example2: pageURL: 'www.my6sense.com', will return {value: 'www.my6sense.com', fromUser: true} + * @param key + * @param value + * @returns {{value: *, fromUser: boolean}} + */ +function fixRequestParamForServer(key, value) { + function isEmptyValue(key, value) { + return value === parametersMap[key].emptyValue; + } + + const parametersMap = { + 'pageUrl': { + emptyValue: '[PAGE_URL]', + defaultValue: getUrl() + }, + 'displayWithinIframe': { + emptyValue: '', + defaultValue: '' + }, + 'dataParams': { + emptyValue: '[KEY_VALUES]', + defaultValue: '' + }, + 'paidClicks': { + emptyValue: '[PAID_TRACKING_PIXEL]', + defaultValue: '' + }, + 'organicClicks': { + emptyValue: '[ORGANIC_TRACKING_PIXEL]', + defaultValue: '' + }, + 'dataView': { + emptyValue: '[VIEW_TRACKING_PIXEL]', + defaultValue: '' + }, + // ZONE is not part of this object, handled on server side + }; + + // if param is not in list we do not change it (return it as is) + if (!parametersMap.hasOwnProperty(key)) { + return { + value: value, + fromUser: true + }; + } + + // if no value given by user set it to default + if (!value || isEmptyValue(key, value)) { + return { + value: parametersMap[key].defaultValue, + fromUser: false + }; + } + + return { + value: value, + fromUser: true + }; +} + +// called second + +function buildGdprServerProperty(bidderRequest) { + var gdprObj = { + gdpr_consent: null, + gdpr: null + }; + + if (bidderRequest && 'gdprConsent' in bidderRequest) { + gdprObj.gdpr_consent = bidderRequest.gdprConsent.consentString || null; + + gdprObj.gdpr = gdprObj.gdpr === null && bidderRequest.gdprConsent.gdprApplies == true ? true : gdprObj.gdpr; + gdprObj.gdpr = gdprObj.gdpr === null && bidderRequest.gdprConsent.gdprApplies == false ? false : gdprObj.gdpr; + gdprObj.gdpr = gdprObj.gdpr === null && bidderRequest.gdprConsent.gdprApplies == 1 ? true : gdprObj.gdpr; + gdprObj.gdpr = gdprObj.gdpr === null && bidderRequest.gdprConsent.gdprApplies == 0 ? false : gdprObj.gdpr; + } + + return gdprObj; +} + +function buildRequests(validBidRequests, bidderRequest) { + let requests = []; + + if (validBidRequests && validBidRequests.length) { + validBidRequests.forEach(bidRequest => { + bidRequest.widget_num = 1; // mandatory property for server side + let isDataUrlSetByUser = false; + let debug = false; + + if (bidRequest.params) { + for (let key in bidRequest.params) { + // loop over params and remove empty/untouched values + if (bidRequest.params.hasOwnProperty(key)) { + // if debug we update url string to get core debug version + if (key === 'debug' && bidRequest.params[key] === true) { + debug = true; + delete bidRequest.params[key]; + continue; + } + + let fixedObj = fixRequestParamForServer(key, bidRequest.params[key]); + bidRequest.params[key] = fixedObj.value; + + // if pageUrl is set by user we should update variable for query string param + if (key === 'pageUrl' && fixedObj.fromUser === true) { + isDataUrlSetByUser = true; + } + + // remove empty params from request + if (!bidRequest.params[key]) { + delete bidRequest.params[key]; + } + } + } + } + + let url = `${END_POINT}?widget_key=${bidRequest.params.key}&is_data_url_set=${isDataUrlSetByUser}`; // mandatory query string for server side + if (debug) { + url = `${END_POINT}?env=debug&widget_key=${bidRequest.params.key}&is_data_url_set=${isDataUrlSetByUser}`; // this url is for debugging + } + + bidRequest.gdpr = buildGdprServerProperty(bidderRequest); + + requests.push({ + url: url, + method: END_POINT_METHOD, + data: JSON.stringify(bidRequest) + }); + }); + } + + return requests; +} + +// called third + +function interpretResponse(serverResponse) { + const bidResponses = []; + // currently server returns a single response which is the body property + if (serverResponse.body) { + serverResponse.body.bidderCode = BIDDER_CODE; + bidResponses.push(serverResponse.body); + } + + return bidResponses; +} + +const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, NATIVE], + isBidRequestValid, + buildRequests, + interpretResponse +}; + +registerBidder(spec); + +module.exports = spec; diff --git a/modules/my6senseBidAdapter.md b/modules/my6senseBidAdapter.md new file mode 100644 index 00000000000..7f422e6fabf --- /dev/null +++ b/modules/my6senseBidAdapter.md @@ -0,0 +1,36 @@ +# HeaderBiddingAdapter + +# Overview + +``` +Module Name: my6sense Bidder Adapter +Module Type: Bidder Adapter +``` + +# Description + +Module that connects to my6sense demand sources. +Banner formats are supported. + +# Test Parameters +``` + var adUnits = [ + + // { + // + // sizes: [[1000, 600]], + // bids: [{ + // bidder: 'my6sense', + // params: { + // key: 'OAJJBW2LRYi2CxfhzqogkA', + // pageUrl: '[PAGE_URL]', + // zone: '[ZONE]', + // dataView: '' + // organicClicks:'', + // paidClicks:'', + // } + // }] + // } + ]; + +``` diff --git a/test/spec/modules/my6senseBidAdapter_spec.js b/test/spec/modules/my6senseBidAdapter_spec.js new file mode 100644 index 00000000000..ec8389acbb3 --- /dev/null +++ b/test/spec/modules/my6senseBidAdapter_spec.js @@ -0,0 +1,151 @@ +import { expect } from 'chai'; +import spec from 'modules/my6senseBidAdapter'; + +describe('My6sense Bid adapter test', () => { + let bidRequests, serverResponses; + beforeEach(() => { + bidRequests = [ + { + // valid 1 + bidder: 'my6sense', + params: { + key: 'DTAeOJN67pCjY36dbhrM3G', + dataVersion: 3, + pageUrl: 'liran.com', + zone: '[ZONE]', + dataParams: '', + dataView: '', + organicClicks: '', + paidClicks: '' + } + }, + { + // invalid 2- no params + bidder: 'my6sense' + }, + { + // invalid 3 - no key in params + bidder: 'my6sense', + params: { + dataVersion: 3, + pageUrl: 'liran.com', + zone: '[ZONE]', + dataParams: '', + dataView: '', + organicClicks: '', + paidClicks: '' + } + }, + { + // invalid 3 - wrong bidder name + bidder: 'test', + params: { + key: 'ZxA0bNhlO9tf5EZ1Q9ZYdS', + dataVersion: 3, + pageUrl: 'liran.com', + zone: '[ZONE]', + dataParams: '', + dataView: '', + organicClicks: '', + paidClicks: '' + } + } + ]; + serverResponses = [ + { + headers: {}, + body: { + cpm: 1.5, + width: 300, + height: 250, + placement_id: 1, + adm: '' + } + }, + { + headers: {}, + body: { + cpm: 0, + width: 0, + height: 0, + placement_id: 1, + adm: '' + } + }, + { + headers: {}, + body: { + cpm: 0, + width: 0, + height: 0, + placement_id: 0, + adm: '' + } + }, + { + headers: {}, + body: { + cpm: 5, + creativeId: '5b29f5d1e4b086e3ee8de36b', + currency: 'USD', + height: 250, + netRevenue: false, + requestId: '2954a0957643bb', + ttl: 360, + width: 300, + adm: '' + } + } + ] + }); + + describe('test if requestIsValid function', () => { + it('with valid data 1', () => { + expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); + }); + it('with invalid data 2', () => { + expect(spec.isBidRequestValid(bidRequests[1])).to.equal(false); + }); + it('with invalid data 3', () => { + expect(spec.isBidRequestValid(bidRequests[2])).to.equal(false); + }); + it('with invalid data 3', () => { + expect(spec.isBidRequestValid(bidRequests[3])).to.equal(false); + }); + }); + + describe('test if buildRequests function', () => { + it('normal', () => { + var requests = spec.buildRequests([bidRequests[0]]); + expect(requests).to.be.lengthOf(1); + }); + }); + describe('test bid responses', () => { + it('success 1', () => { + var bids = spec.interpretResponse(serverResponses[0], {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(1.5); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(250); + expect(bids[0].adm).to.have.length.above(1); + }); + it('success 2', () => { + var bids = spec.interpretResponse(serverResponses[3]); + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(5); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(250); + expect(bids[0].netRevenue).to.equal(false); + expect(bids[0].ttl).to.equal(360); + expect(bids[0].currency).to.equal('USD'); + }); + it('fail 1 (cpm=0)', () => { + var bids = spec.interpretResponse(serverResponses[1]); + expect(bids).to.be.lengthOf(1); + }); + it('fail 2 (no response)', () => { + var bids = spec.interpretResponse([]); + expect(bids).to.be.lengthOf(0); + }); + }); +}); From c11aadf0ff63ff4d9bb1711ef85535a31e38ff38 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 10 Jul 2018 16:36:53 -0400 Subject: [PATCH 0543/1594] Prebid 1.16.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1223fc5f6ce..9d82152b5dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.16.0-pre", + "version": "1.16.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 72b7240cca057e87d2e05431b553a10bb770fe79 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 10 Jul 2018 16:46:15 -0400 Subject: [PATCH 0544/1594] increment prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9d82152b5dc..1adedf1174f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.16.0", + "version": "1.17.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4ad1a0006f5953f623cb3013be27b6375de88320 Mon Sep 17 00:00:00 2001 From: shannonAB Date: Wed, 11 Jul 2018 11:55:05 -0400 Subject: [PATCH 0545/1594] Add Sortable bid adapter (#2824) * Add Sortable bid adapter - [x] New bidder adapter This change adds the Sortable adapter to Prebid.js. * move global sortable config into its own object * update siteId * config can be undefined when module loads * support floor param --- modules/sortableBidAdapter.js | 149 ++++++++++++++ modules/sortableBidAdapter.md | 56 ++++++ test/spec/modules/sortableBidAdapter_spec.js | 194 +++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 modules/sortableBidAdapter.js create mode 100644 modules/sortableBidAdapter.md create mode 100644 test/spec/modules/sortableBidAdapter_spec.js diff --git a/modules/sortableBidAdapter.js b/modules/sortableBidAdapter.js new file mode 100644 index 00000000000..8e5e221a9d4 --- /dev/null +++ b/modules/sortableBidAdapter.js @@ -0,0 +1,149 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; +import { BANNER } from 'src/mediaTypes'; +import { REPO_AND_VERSION } from 'src/constants'; + +const BIDDER_CODE = 'sortable'; +const SERVER_URL = 'c.deployads.com'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: function(bid) { + const sortableConfig = config.getConfig('sortable'); + const haveSiteId = (sortableConfig && !!sortableConfig.siteId) || bid.params.siteId; + return !!(bid.params.tagId && haveSiteId && bid.sizes && + bid.sizes.every(sizeArr => sizeArr.length == 2 && sizeArr.every(Number.isInteger))); + }, + + buildRequests: function(validBidReqs, bidderRequest) { + const sortableConfig = config.getConfig('sortable') || {}; + const globalSiteId = sortableConfig.siteId; + let loc = utils.getTopWindowLocation(); + + const sortableImps = utils._map(validBidReqs, bid => { + let rv = { + id: bid.bidId, + tagid: bid.params.tagId, + banner: { + format: utils._map(bid.sizes, ([width, height]) => ({w: width, h: height})) + }, + ext: {} + }; + if (bid.params.floor) { + rv.bidfloor = bid.params.floor; + } + if (bid.params.keywords) { + let keywords = utils._map(bid.params.keywords, (foo, bar) => ({name: bar, value: foo})); + rv.ext.keywords = keywords; + } + if (bid.params.bidderParams) { + utils._each(bid.params.bidderParams, (params, partner) => { + rv.ext[partner] = params; + }); + } + return rv; + }); + const gdprConsent = bidderRequest && bidderRequest.gdprConsent; + const sortableBidReq = { + id: utils.getUniqueIdentifierStr(), + imp: sortableImps, + site: { + domain: loc.hostname, + page: loc.href, + ref: utils.getTopWindowReferrer(), + publisher: { + id: globalSiteId || validBidReqs[0].params.siteId, + }, + device: { + w: screen.width, + h: screen.height + }, + }, + }; + if (gdprConsent) { + sortableBidReq.user = { + ext: { + consent: gdprConsent.consentString + } + }; + sortableBidReq.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + }; + } + + return { + method: 'POST', + url: `//${SERVER_URL}/openrtb2/auction?src=${REPO_AND_VERSION}&host=${loc.host}`, + data: JSON.stringify(sortableBidReq), + options: {contentType: 'text/plain'} + }; + }, + + interpretResponse: function(serverResponse) { + const { body: {id, seatbid} } = serverResponse; + const sortableBids = []; + if (id && seatbid) { + utils._each(seatbid, seatbid => { + utils._each(seatbid.bid, bid => { + const bidObj = { + requestId: bid.impid, + cpm: parseFloat(bid.price), + width: parseInt(bid.w), + height: parseInt(bid.h), + creativeId: bid.id, + dealId: bid.dealid || null, + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ttl: 60 + }; + if (bid.adm && bid.nurl) { + bidObj.ad = bid.adm; + bidObj.ad += utils.createTrackPixelHtml(decodeURIComponent(bid.nurl)); + } else if (bid.adm) { + bidObj.ad = bid.adm; + } else if (bid.nurl) { + bidObj.adUrl = bid.nurl; + } + sortableBids.push(bidObj); + }); + }); + } + return sortableBids; + }, + + getUserSyncs: (syncOptions, responses, gdprConsent) => { + const sortableConfig = config.getConfig('sortable'); + if (syncOptions.iframeEnabled && sortableConfig && !!sortableConfig.siteId) { + let syncUrl = `//${SERVER_URL}/sync?f=html&s=${sortableConfig.siteId}&u=${encodeURIComponent(utils.getTopWindowLocation())}`; + + if (gdprConsent) { + syncurl += '&g=' + (gdprConsent.gdprApplies ? 1 : 0); + syncurl += '&cs=' + encodeURIComponent(gdprConsent.consentString || ''); + } + + return [{ + type: 'iframe', + url: syncUrl + }]; + } + }, + + onTimeout(details) { + fetch(`//${SERVER_URL}/prebid/timeout`, { + method: 'POST', + body: JSON.stringify(details), + mode: 'no-cors', + headers: new Headers({ + 'Content-Type': 'text/plain' + }) + }); + } +}; + +registerBidder(spec); diff --git a/modules/sortableBidAdapter.md b/modules/sortableBidAdapter.md new file mode 100644 index 00000000000..027d6390e87 --- /dev/null +++ b/modules/sortableBidAdapter.md @@ -0,0 +1,56 @@ +# Overview + +``` +Module Name: Sortable Bid Adapter +Module Type: Bidder Adapter +Maintainer: prebid@sortable.com +``` + +# Description + +Sortable's adapter integration to the Prebid library. Posts plain-text JSON to the /openrtb2/auction endpoint. + +# Test Parameters + +``` +var adUnits = [ + { + code: 'test-pb-leaderboard', + sizes: [[728, 90]], + bids: [{ + bidder: 'sortable', + params: { + tagId: 'test-pb-leaderboard', + siteId: 'prebid.example.com', + 'keywords': { + 'key1': 'val1', + 'key2': 'val2' + } + } + }] + }, { + code: 'test-pb-banner', + sizes: [[300, 250]], + bids: [{ + bidder: 'sortable', + params: { + tagId: 'test-pb-banner', + siteId: 'prebid.example.com' + } + }] + }, { + code: 'test-pb-sidebar', + size: [[160, 600]], + bids: [{ + bidder: 'sortable', + params: { + tagId: 'test-pb-sidebar', + siteId: 'prebid.example.com', + 'keywords': { + 'keyA': 'valA' + } + } + }] + } +] +``` diff --git a/test/spec/modules/sortableBidAdapter_spec.js b/test/spec/modules/sortableBidAdapter_spec.js new file mode 100644 index 00000000000..9f351e9764c --- /dev/null +++ b/test/spec/modules/sortableBidAdapter_spec.js @@ -0,0 +1,194 @@ +import { expect } from 'chai'; +import { spec } from 'modules/sortableBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { REPO_AND_VERSION } from 'src/constants'; +import * as utils from 'src/utils'; + +const ENDPOINT = `//c.deployads.com/openrtb2/auction?src=${REPO_AND_VERSION}&host=${utils.getTopWindowLocation().host}`; + +describe('sortableBidAdapter', function() { + const adapter = newBidder(spec); + + describe('isBidRequestValid', () => { + function makeBid() { + return { + 'bidder': 'sortable', + 'params': { + 'tagId': '403370', + 'siteId': 'example.com', + 'keywords': { + 'key1': 'val1', + 'key2': 'val2' + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + } + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(makeBid())).to.equal(true); + }); + + it('should return false when tagId not passed correctly', () => { + let bid = makeBid(); + delete bid.params.tagId; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when sizes not passed correctly', () => { + let bid = makeBid(); + delete bid.sizes; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when sizes are wrong length', () => { + let bid = makeBid(); + bid.sizes = [[300]]; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when require params are not passed', () => { + let bid = makeBid(); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const bidRequests = [{ + 'bidder': 'sortable', + 'params': { + 'tagId': '403370', + 'siteId': 'example.com', + 'floor': 0.21, + 'keywords': { + 'key1': 'val1', + 'key2': 'val2' + } + }, + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + const request = spec.buildRequests(bidRequests); + const requestBody = JSON.parse(request.data); + + it('sends bid request to our endpoint via POST', () => { + expect(request.method).to.equal('POST'); + }); + + it('attaches source and version to endpoint URL as query params', () => { + expect(request.url).to.equal(ENDPOINT); + }); + + it('sends screen dimensions', () => { + expect(requestBody.site.device.w).to.equal(screen.width); + expect(requestBody.site.device.h).to.equal(screen.height); + }); + + it('includes the ad size in the bid request', () => { + expect(requestBody.imp[0].banner.format[0].w).to.equal(300); + expect(requestBody.imp[0].banner.format[0].h).to.equal(250); + }); + + it('includes the params in the bid request', () => { + expect(requestBody.imp[0].ext.keywords).to.deep.equal([ + {'name': 'key1', 'value': 'val1'}, + {'name': 'key2', 'value': 'val2'} + ]); + expect(requestBody.site.publisher.id).to.equal('example.com'); + expect(requestBody.imp[0].tagid).to.equal('403370'); + expect(requestBody.imp[0].bidfloor).to.equal(0.21); + }); + }); + + describe('interpretResponse', () => { + function makeResponse() { + return { + body: { + 'id': '5e5c23a5ba71e78', + 'seatbid': [ + { + 'bid': [ + { + 'id': '6vmb3isptf', + 'impid': '322add653672f68', + 'price': 1.22, + 'adm': '', + 'attr': [5], + 'h': 90, + 'nurl': 'http://nurl', + 'w': 728 + } + ], + 'seat': 'MOCK' + } + ], + 'bidid': '5e5c23a5ba71e78' + } + }; + } + + const expectedBid = { + 'requestId': '322add653672f68', + 'cpm': 1.22, + 'width': 728, + 'height': 90, + 'creativeId': '6vmb3isptf', + 'dealId': null, + 'currency': 'USD', + 'netRevenue': true, + 'mediaType': 'banner', + 'ttl': 60, + 'ad': '
' + }; + + it('should get the correct bid response', () => { + let result = spec.interpretResponse(makeResponse()); + expect(result.length).to.equal(1); + expect(result[0]).to.deep.equal(expectedBid); + }); + + it('should handle a missing nurl', () => { + let noNurlResponse = makeResponse(); + delete noNurlResponse.body.seatbid[0].bid[0].nurl; + let noNurlResult = Object.assign({}, expectedBid); + noNurlResult.ad = ''; + let result = spec.interpretResponse(noNurlResponse); + expect(result.length).to.equal(1); + expect(result[0]).to.deep.equal(noNurlResult); + }); + + it('should handle a missing adm', () => { + let noAdmResponse = makeResponse(); + delete noAdmResponse.body.seatbid[0].bid[0].adm; + let noAdmResult = Object.assign({}, expectedBid); + delete noAdmResult.ad; + noAdmResult.adUrl = 'http://nurl'; + let result = spec.interpretResponse(noAdmResponse); + expect(result.length).to.equal(1); + expect(result[0]).to.deep.equal(noAdmResult); + }); + + it('handles empty bid response', () => { + let response = { + body: { + 'id': '5e5c23a5ba71e78', + 'seatbid': [] + } + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From a38a1fbdec2ed02f5f5f0d5e91a1cf3f0a843076 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 11 Jul 2018 14:38:41 -0400 Subject: [PATCH 0546/1594] fix sortable adapter unit test (#2837) --- modules/sortableBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/sortableBidAdapter.js b/modules/sortableBidAdapter.js index 8e5e221a9d4..eeac1cf2796 100644 --- a/modules/sortableBidAdapter.js +++ b/modules/sortableBidAdapter.js @@ -15,7 +15,7 @@ export const spec = { const sortableConfig = config.getConfig('sortable'); const haveSiteId = (sortableConfig && !!sortableConfig.siteId) || bid.params.siteId; return !!(bid.params.tagId && haveSiteId && bid.sizes && - bid.sizes.every(sizeArr => sizeArr.length == 2 && sizeArr.every(Number.isInteger))); + bid.sizes.every(sizeArr => sizeArr.length == 2 && sizeArr.every(num => utils.isNumber(num)))); }, buildRequests: function(validBidReqs, bidderRequest) { From ed28094054145e132d889d36ad79d51a00210c63 Mon Sep 17 00:00:00 2001 From: Steffen Anders Date: Thu, 12 Jul 2018 18:35:25 +0200 Subject: [PATCH 0547/1594] Add bid adapter for Ad Up Technology (#2809) --- modules/aduptechBidAdapter.js | 79 ++++++ modules/aduptechBidAdapter.md | 32 +++ test/spec/modules/aduptechBidAdapter_spec.js | 261 +++++++++++++++++++ 3 files changed, 372 insertions(+) create mode 100644 modules/aduptechBidAdapter.js create mode 100644 modules/aduptechBidAdapter.md create mode 100644 test/spec/modules/aduptechBidAdapter_spec.js diff --git a/modules/aduptechBidAdapter.js b/modules/aduptechBidAdapter.js new file mode 100644 index 00000000000..d2a53f0718c --- /dev/null +++ b/modules/aduptechBidAdapter.js @@ -0,0 +1,79 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes' + +export const BIDDER_CODE = 'aduptech'; +export const PUBLISHER_PLACEHOLDER = '{PUBLISHER}'; +export const ENDPOINT_URL = window.location.protocol + '//rtb.d.adup-tech.com/prebid/' + PUBLISHER_PLACEHOLDER + '_bid'; +export const ENDPOINT_METHOD = 'POST'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: (bid) => { + return !!(bid && + bid.sizes && + bid.sizes.length > 0 && + bid.params && + bid.params.publisher && + bid.params.placement); + }, + + buildRequests: (validBidRequests, bidderRequest) => { + const bidRequests = []; + + // collect GDPR information + let gdpr = null; + if (bidderRequest && bidderRequest.gdprConsent) { + gdpr = { + consentString: bidderRequest.gdprConsent.consentString, + consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true + }; + } + + validBidRequests.forEach((bidRequest) => { + bidRequests.push({ + url: ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, encodeURIComponent(bidRequest.params.publisher)), + method: ENDPOINT_METHOD, + data: { + pageUrl: utils.getTopWindowUrl(), + referrer: utils.getTopWindowReferrer(), + bidId: bidRequest.bidId, + auctionId: bidRequest.auctionId, + transactionId: bidRequest.transactionId, + adUnitCode: bidRequest.adUnitCode, + sizes: bidRequest.sizes, + params: bidRequest.params, + gdpr: gdpr + } + }); + }); + + return bidRequests; + }, + + interpretResponse: (response) => { + const bidResponses = []; + + if (!response.body || !response.body.bid || !response.body.creative) { + return bidResponses; + } + + bidResponses.push({ + requestId: response.body.bid.bidId, + cpm: response.body.bid.price, + netRevenue: response.body.bid.net, + currency: response.body.bid.currency, + ttl: response.body.bid.ttl, + creativeId: response.body.creative.id, + width: response.body.creative.width, + height: response.body.creative.height, + ad: response.body.creative.html + }); + + return bidResponses; + } +}; + +registerBidder(spec); diff --git a/modules/aduptechBidAdapter.md b/modules/aduptechBidAdapter.md new file mode 100644 index 00000000000..98602a61fe1 --- /dev/null +++ b/modules/aduptechBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +``` +Module Name: Ad Up Technology Bid Adapter +Module Type: Bidder Adapter +Maintainer: steffen.anders@adup-tech.com, berlin@adup-tech.com +``` + +# Description + +Connects to Ad Up Technology demand sources to fetch bids. +Please use ```aduptech``` as bidder code. Only banner formats are supported. + +The Ad Up Technology Bidding adapter requires setup and approval before beginning. +For more information visit [www.adup-tech.com](http://www.adup-tech.com/en). + +# Test Parameters +``` +var adUnits = [ + { + code: 'banner', + sizes: [[300, 250], [300, 600]], + bids: [{ + bidder: 'aduptech', + params: { + publisher: 'prebid', + placement: '12345' + } + }] + } +]; +``` diff --git a/test/spec/modules/aduptechBidAdapter_spec.js b/test/spec/modules/aduptechBidAdapter_spec.js new file mode 100644 index 00000000000..76689e9603f --- /dev/null +++ b/test/spec/modules/aduptechBidAdapter_spec.js @@ -0,0 +1,261 @@ +import { expect } from 'chai'; +import { BIDDER_CODE, PUBLISHER_PLACEHOLDER, ENDPOINT_URL, ENDPOINT_METHOD, spec } from 'modules/aduptechBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +describe('AduptechBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when necessary information is given', () => { + expect(spec.isBidRequestValid({ + sizes: [[100, 200]], + params: { + publisher: 'test', + placement: '1234' + } + })).to.be.true; + }); + + it('should return false on empty bid', () => { + expect(spec.isBidRequestValid({})).to.be.false; + }); + + it('should return false on missing sizes', () => { + expect(spec.isBidRequestValid({ + params: { + publisher: 'test', + placement: '1234' + } + })).to.be.false; + }); + + it('should return false on empty sizes', () => { + expect(spec.isBidRequestValid({ + sizes: [], + params: { + publisher: 'test', + placement: '1234' + } + })).to.be.false; + }); + + it('should return false on missing params', () => { + expect(spec.isBidRequestValid({ + sizes: [[100, 200]], + })).to.be.false; + }); + + it('should return false on invalid params', () => { + expect(spec.isBidRequestValid({ + sizes: [[100, 200]], + params: 'bar' + })).to.be.false; + }); + + it('should return false on empty params', () => { + expect(spec.isBidRequestValid({ + sizes: [[100, 200]], + params: {} + })).to.be.false; + }); + + it('should return false on missing publisher', () => { + expect(spec.isBidRequestValid({ + sizes: [[100, 200]], + params: { + placement: '1234' + } + })).to.be.false; + }); + + it('should return false on missing placement', () => { + expect(spec.isBidRequestValid({ + sizes: [[100, 200]], + params: { + publisher: 'test' + } + })).to.be.false; + }); + }); + + describe('buildRequests', () => { + it('should send one bid request per ad unit to the endpoint via POST', () => { + const bidRequests = [ + { + bidder: BIDDER_CODE, + bidId: 'bidId1', + adUnitCode: 'adUnitCode1', + transactionId: 'transactionId1', + auctionId: 'auctionId1', + sizes: [[100, 200], [300, 400]], + params: { + publisher: 'publisher1', + placement: 'placement1' + } + }, + { + bidder: BIDDER_CODE, + bidId: 'bidId2', + adUnitCode: 'adUnitCode2', + transactionId: 'transactionId2', + auctionId: 'auctionId2', + sizes: [[500, 600]], + params: { + publisher: 'publisher2', + placement: 'placement2' + } + } + ]; + + const result = spec.buildRequests(bidRequests); + expect(result.length).to.equal(2); + + expect(result[0].url).to.equal(ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, bidRequests[0].params.publisher)); + expect(result[0].method).to.equal(ENDPOINT_METHOD); + expect(result[0].data).to.deep.equal({ + pageUrl: utils.getTopWindowUrl(), + referrer: utils.getTopWindowReferrer(), + bidId: bidRequests[0].bidId, + auctionId: bidRequests[0].auctionId, + transactionId: bidRequests[0].transactionId, + adUnitCode: bidRequests[0].adUnitCode, + sizes: bidRequests[0].sizes, + params: bidRequests[0].params, + gdpr: null + }); + + expect(result[1].url).to.equal(ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, bidRequests[1].params.publisher)); + expect(result[1].method).to.equal(ENDPOINT_METHOD); + expect(result[1].data).to.deep.equal({ + pageUrl: utils.getTopWindowUrl(), + referrer: utils.getTopWindowReferrer(), + bidId: bidRequests[1].bidId, + auctionId: bidRequests[1].auctionId, + transactionId: bidRequests[1].transactionId, + adUnitCode: bidRequests[1].adUnitCode, + sizes: bidRequests[1].sizes, + params: bidRequests[1].params, + gdpr: null + }); + }); + + it('should pass gdpr informations', () => { + const bidderRequest = { + gdprConsent: { + consentString: 'consentString', + gdprApplies: true + } + }; + const bidRequests = [ + { + bidder: BIDDER_CODE, + bidId: 'bidId3', + adUnitCode: 'adUnitCode3', + transactionId: 'transactionId3', + auctionId: 'auctionId3', + sizes: [[100, 200], [300, 400]], + params: { + publisher: 'publisher3', + placement: 'placement3' + } + } + ]; + + const result = spec.buildRequests(bidRequests, bidderRequest); + expect(result.length).to.equal(1); + expect(result[0].data.gdpr).to.exist; + expect(result[0].data.gdpr.consentRequired).to.exist.and.to.equal(bidderRequest.gdprConsent.gdprApplies); + expect(result[0].data.gdpr.consentString).to.exist.and.to.equal(bidderRequest.gdprConsent.consentString); + }); + + it('should encode publisher param in endpoint url', () => { + const bidRequests = [ + { + bidder: BIDDER_CODE, + bidId: 'bidId1', + adUnitCode: 'adUnitCode1', + transactionId: 'transactionId1', + auctionId: 'auctionId1', + sizes: [[100, 200]], + params: { + publisher: 'crazy publisher key äÖÜ', + placement: 'placement1' + } + }, + ]; + + const result = spec.buildRequests(bidRequests); + + expect(result[0].url).to.equal(ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, encodeURIComponent(bidRequests[0].params.publisher))); + }); + + it('should handle empty bidRequests', () => { + expect(spec.buildRequests([])).to.deep.equal([]); + }); + }); + + describe('interpretResponse', () => { + it('should correctly interpret the server response', () => { + const serverResponse = { + body: { + bid: { + bidId: 'bidId1', + price: 0.12, + net: true, + currency: 'EUR', + ttl: 123 + }, + creative: { + id: 'creativeId1', + width: 100, + height: 200, + html: '
Hello World
' + } + } + }; + + const result = spec.interpretResponse(serverResponse); + + expect(result).to.deep.equal([ + { + requestId: serverResponse.body.bid.bidId, + cpm: serverResponse.body.bid.price, + netRevenue: serverResponse.body.bid.net, + currency: serverResponse.body.bid.currency, + ttl: serverResponse.body.bid.ttl, + creativeId: serverResponse.body.creative.id, + width: serverResponse.body.creative.width, + height: serverResponse.body.creative.height, + ad: serverResponse.body.creative.html + } + ]); + }); + + it('should handle empty serverResponse', () => { + expect(spec.interpretResponse({})).to.deep.equal([]); + }); + + it('should handle missing bid', () => { + expect(spec.interpretResponse({ + body: { + creative: {} + } + })).to.deep.equal([]); + }); + + it('should handle missing creative', () => { + expect(spec.interpretResponse({ + body: { + bid: {} + } + })).to.deep.equal([]); + }); + }); +}); From f32605ab23356653b31b6087850443a21b1a3326 Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Mon, 16 Jul 2018 15:14:14 +0300 Subject: [PATCH 0548/1594] vidazoo adapter - GDPR support (#2834) --- modules/vidazooBidAdapter.js | 7 ++++--- test/spec/modules/vidazooBidAdapter_spec.js | 11 ++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/modules/vidazooBidAdapter.js b/modules/vidazooBidAdapter.js index bcf8856e049..8523ad51f7f 100644 --- a/modules/vidazooBidAdapter.js +++ b/modules/vidazooBidAdapter.js @@ -19,7 +19,7 @@ function isBidRequestValid(bid) { return !!(params.cId && params.pId); } -function buildRequest(bid, topWindowUrl, size) { +function buildRequest(bid, topWindowUrl, size, bidderRequest) { const {params, bidId} = bid; const {bidFloor, cId, pId, ext} = params; // Prebid's util function returns AppNexus style sizes (i.e. 300x250) @@ -34,6 +34,7 @@ function buildRequest(bid, topWindowUrl, size) { bidFloor: bidFloor, bidId: bidId, publisherId: pId, + consent: bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString, width, height } @@ -46,13 +47,13 @@ function buildRequest(bid, topWindowUrl, size) { return dto; } -function buildRequests(validBidRequests) { +function buildRequests(validBidRequests, bidderRequest) { const topWindowUrl = utils.getTopWindowUrl(); const requests = []; validBidRequests.forEach(validBidRequest => { const sizes = utils.parseSizesInput(validBidRequest.sizes); sizes.forEach(size => { - const request = buildRequest(validBidRequest, topWindowUrl, size); + const request = buildRequest(validBidRequest, topWindowUrl, size, bidderRequest); requests.push(request); }); }); diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index d88e5a718ed..b857967a44e 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec as adapter, URL} from 'modules/vidazooBidAdapter'; import * as utils from 'src/utils'; + const BID = { 'bidId': '2d52001cabd527', 'params': { @@ -19,6 +20,12 @@ const BID = { 'requestId': 'b0777d85-d061-450e-9bc7-260dd54bbb7a' }; +const BIDDER_REQUEST = { + 'gdprConsent': { + 'consentString': 'consent_string' + } +}; + const SERVER_RESPONSE = { body: { 'ad': '', @@ -109,12 +116,13 @@ describe('VidazooBidAdapter', () => { }); it('should build request for each size', () => { - const requests = adapter.buildRequests([BID]); + const requests = adapter.buildRequests([BID], BIDDER_REQUEST); expect(requests).to.have.length(2); expect(requests[0]).to.deep.equal({ method: 'GET', url: `${URL}/prebid/59db6b3b4ffaa70004f45cdc`, data: { + consent: 'consent_string', width: '300', height: '250', url: 'http://www.greatsite.com', @@ -130,6 +138,7 @@ describe('VidazooBidAdapter', () => { method: 'GET', url: `${URL}/prebid/59db6b3b4ffaa70004f45cdc`, data: { + consent: 'consent_string', width: '300', height: '600', url: 'http://www.greatsite.com', From a658ae7a8328e1a110e742e9649843d33d5f7110 Mon Sep 17 00:00:00 2001 From: lotani-uolinc <41218295+lotani-uolinc@users.noreply.github.com> Date: Tue, 17 Jul 2018 14:52:11 -0300 Subject: [PATCH 0549/1594] UOL - BidAdapter release candidate (#2850) * UOL - BidAdapter release candidate * UOL - BidAdapter - applying requested changes/fixes for the release candidate * UOL - BidAdapter - disabled geolocation tests for unsupported browsers --- modules/uolBidAdapter.js | 192 +++++++++++++++ modules/uolBidAdapter.md | 51 ++++ test/spec/modules/uolBidAdapter_spec.js | 313 ++++++++++++++++++++++++ 3 files changed, 556 insertions(+) create mode 100644 modules/uolBidAdapter.js create mode 100644 modules/uolBidAdapter.md create mode 100644 test/spec/modules/uolBidAdapter_spec.js diff --git a/modules/uolBidAdapter.js b/modules/uolBidAdapter.js new file mode 100644 index 00000000000..0882dcdd12e --- /dev/null +++ b/modules/uolBidAdapter.js @@ -0,0 +1,192 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; +const BIDDER_CODE = 'uol'; +const ENDPOINT_URL = 'https://prebid.adilligo.com/v1/prebid.json'; +const UOL_LOG_HEADER = 'UOL Bidder Error: ' +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], // not required since it is default + aliases: ['uol'], // 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) { + var isValid = true; + if (bid.params) { + if (!bid.params.placementId) { + utils.logError(UOL_LOG_HEADER + 'Param placementId was not defined for bidID ' + bid.bidId); + isValid = false; + } + if (typeof bid.params.cpmFactor != 'undefined' && !bid.params.test) { + utils.logError(UOL_LOG_HEADER + 'Cannot manipulate cpmFactor outside test environment - bidID ' + bid.bidId); + isValid = false; + } + if (bid.params.cpmFactor && (isNaN(bid.params.cpmFactor) || parseInt(Number(bid.params.cpmFactor)) != bid.params.cpmFactor || isNaN(parseInt(bid.params.cpmFactor, 10)))) { + utils.logError(UOL_LOG_HEADER + 'Invalid param definition for cpmFactor on bidID ' + bid.bidId); + isValid = false; + } + } else { + isValid = false; + utils.logError(UOL_LOG_HEADER + 'No params defined for bidID ' + bid.bidId); + } + if (getSizes(bid).length == 0) { + utils.logError(UOL_LOG_HEADER + 'No sizing definition found for bidID ' + bid.bidId); + isValid = false; + } + return isValid; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @param {bidderRequests} - an object containing all bid params, including validBids. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + var data = JSON.stringify(getPayloadFor(validBidRequests, bidderRequest)); + return { + method: 'POST', + url: ENDPOINT_URL, + data, + bidRequest: validBidRequests, + }; + }, + /** + * 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 = []; + if (serverResponse.body) { + const ads = serverResponse.body.ads; + for (var index = 0; index < ads.length; index++) { + const bidResponse = { + requestId: ads[index].bidId, + cpm: ads[index].cpm, + width: ads[index].width, + height: ads[index].height, + creativeId: ads[index].creativeId, + dealId: ads[index].dealId, + currency: ads[index].currency, + netRevenue: ads[index].netRevenue, + ttl: ads[index].ttl, + ad: ads[index].ad, + mediaType: ads[index].mediaType + }; + 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) { + const syncs = []; + if (syncOptions.iframeEnabled) { + for (var index = 0; index < serverResponses.length; index++) { + if (serverResponses[index].body && serverResponses[index].body.trackingPixel) { + syncs.push({ + type: 'iframe', + url: serverResponses[index].body.trackingPixel + }); + } + } + } + return syncs; + } +} + +function getPayloadFor(bidRequests, bidderRequest) { + var payload = { + auctionId: bidderRequest.auctionId, + requestId: bidderRequest.bidderRequestId, + referrerURL: utils.getTopWindowUrl(), + trackingAllowed: !utils.getDNT() + }; + if (payload.trackingAllowed) { + try { + var location = getLastLocation(); + if (location != null) { + payload.geolocation = location; + } + } catch (error) { utils.logError(UOL_LOG_HEADER + 'Location acquisition error - ' + error.toString()); } + } + payload.requests = []; + for (var index = 0; index < bidRequests.length; index++) { + var request = { + bidId: bidRequests[index].bidId, + transactionId: bidRequests[index].transactionId, + adUnitCode: bidRequests[index].adUnitCode, + sizes: getSizes(bidRequests[index]), + customParams: extractCustomParams(bidRequests[index].params), + type: 'banner' + } + payload.requests.push(request); + } + return payload; +}; + +function getLastLocation() { + var location = localStorage.getItem('uolLocationTracker'); + if (navigator.permissions && navigator.permissions.query) { + getUserCoordinates().then(data => { + if (data != null) { + var coordinates = { + lat: data.latitude, + long: data.longitude, + timestamp: new Date().getTime() + }; + localStorage.setItem('uolLocationTracker', JSON.stringify(coordinates)); + } + }, {}) + } else { + location = null; + localStorage.removeItem('uolLocationTracker'); + } + return JSON.parse(location); +} + +function getUserCoordinates() { + return new Promise((resolve, reject) => + navigator.permissions.query({name: 'geolocation'}) + .then(permission => + permission.state === 'granted' + ? navigator.geolocation.getCurrentPosition(pos => resolve(pos.coords)) + : resolve(null) + )); +} + +function extractCustomParams(data) { + var params = { + placementId: data.placementId + } + if (data.test) { + params.test = data.test; + if (data.cpmFactor) { + params.cpmFactor = data.cpmFactor; + } + } + return params; +} + +function getSizes(bid) { + var adSizes = []; + if ((Array.isArray(bid.sizes)) && bid.sizes.length > 0) { + adSizes = bid.sizes; + } + return adSizes; +} + +registerBidder(spec); diff --git a/modules/uolBidAdapter.md b/modules/uolBidAdapter.md new file mode 100644 index 00000000000..1d465c9a9c5 --- /dev/null +++ b/modules/uolBidAdapter.md @@ -0,0 +1,51 @@ +# Overview + +``` +Module Name: UOL Project Bid Adapter +Module Type: Bidder Adapter +Maintainer: l-prebid@uolinc.com +``` + +# Description + +Connect to UOL Project's exchange for bids. + +For proper setup, please contact UOL Project's team at l-prebid@uolinc.com + +# Test Parameters +``` + var adUnits = [ + { + code: '/19968336/header-bid-tag-0', + mediaTypes: { + banner: { + sizes: [[300, 250],[300, 600]] + } + }, + bids: [{ + bidder: 'uol', + params: { + placementId: 1231244, + test: true, + cpmFactor: 2 + } + } + ] + }, + { + code: '/19968336/header-bid-tag-1', + mediaTypes: { + banner: { + sizes: [[970, 250],[728, 90]] + } + }, + bids: [{ + bidder: 'uol', + params: { + placementId: 1231242, + test: false + } + }] + } + ]; +``` diff --git a/test/spec/modules/uolBidAdapter_spec.js b/test/spec/modules/uolBidAdapter_spec.js new file mode 100644 index 00000000000..843f47682dc --- /dev/null +++ b/test/spec/modules/uolBidAdapter_spec.js @@ -0,0 +1,313 @@ +import { expect } from 'chai'; +import { spec } from 'modules/uolBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = 'https://prebid.adilligo.com/v1/prebid.json'; + +describe('UOL Bid Adapter', () => { + const adapter = newBidder(spec); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'uol', + 'params': { + 'placementId': '19571273' + }, + 'adUnitCode': '/uol/unit/code', + 'sizes': [[300, 250], [970, 250]], + 'bidId': '3ddb6ed2d73b45', + 'bidderRequestId': 'd2b12f9d2bad975b7', + 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', + }; + + it('should return true for valid params', () => { + let clonedBid = Object.assign({}, bid); + expect(spec.isBidRequestValid(clonedBid)).to.equal(true); + + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571277', + 'test': 'true' + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(true); + + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571278', + 'test': 'true', + 'cpmFactor': 2 + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(true); + }); + + it('should return false when required params are not passed', () => { + let clonedBid = Object.assign({}, bid); + delete clonedBid.params; + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + }); + + it('should return false when params are invalid', () => { + let clonedBid = Object.assign({}, bid); + delete clonedBid.params; + clonedBid.params = { + 'placementId': 0 + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571281', + 'cpmFactor': 2 + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571282', + 'cpmFactor': 'two' + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + }); + + it('should return false when cpmFactor is passed and test flag isn\'t active', () => { + let clonedBid = Object.assign({}, bid); + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571283', + 'test': false, + 'cpmFactor': 2 + }; + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + }); + + it('should not allow empty size', () => { + let clonedBid = Object.assign({}, bid); + delete clonedBid.sizes; + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let queryPermission; + let cleanup = function() { + navigator.permissions.query = queryPermission; + }; + let grantTriangulation = function() { + queryPermission = navigator.permissions.query; + navigator.permissions.query = function(data) { + return new Promise((resolve, reject) => { + resolve({state: 'granted'}); + }); + } + }; + let denyTriangulation = function() { + queryPermission = navigator.permissions.query; + navigator.permissions.query = function(data) { + return new Promise((resolve, reject) => { + resolve({state: 'prompt'}); + }); + } + }; + let removeQuerySupport = function() { + queryPermission = navigator.permissions.query; + navigator.permissions.query = undefined; + } + + let bidRequests = [ + { + 'bidder': 'uol', + 'params': { + 'placementId': '19571273' + }, + 'adUnitCode': '/uol/unit/code', + 'sizes': [[300, 250]], + 'bidId': '3ddb6ed2d73b45', + 'bidderRequestId': 'd2b12f9d2bad975b7', + 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', + }, { + 'bidder': 'uol', + 'params': { + 'placementId': '19571274' + }, + 'adUnitCode': '/uol/unit/code2', + 'sizes': [[300, 600], [970, 250]], + 'bidId': '3a3ea8e80a2dc5', + 'bidderRequestId': 'd2b12f9d2bad975b7', + 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', + } + ]; + + let bidderRequest = { + 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', + 'auctionStart': 1530133180799, + 'bidderCode': 'uol', + 'bidderRequestId': 'd2b12f9d2bad975b7', + 'bids': bidRequests, + 'doneCbCallCount': 1, + 'start': 1530133180801, + 'timeout': 3000 + }; + + describe('buildRequest basic params', () => { + const requestObject = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(requestObject.data); + + it('should send bid requests to expected endpoint via POST method', () => { + expect(requestObject.url).to.equal(ENDPOINT); + expect(requestObject.method).to.equal('POST'); + }); + + it('should contain referrer URL', () => { + expect(payload.referrerURL).to.exist.and.to.match(/^http(s)?:\/\/.+$/) + }); + + it('should contain an array of requests with length equivalent to bid count', () => { + expect(payload.requests).to.have.length(bidRequests.length); + }); + it('should return propper ad size if at least one entry is provided', () => { + expect(payload.requests[0].sizes).to.deep.equal(bidRequests[0].sizes); + }); + }); + + if (navigator.permissions && navigator.permissions.query && navigator.geolocation) { + describe('buildRequest geolocation param', () => { // shall only be tested if browser engine supports geolocation and permissions API. + let geolocation = { lat: 4, long: 3, timestamp: 123121451 }; + + it('should contain user coordinates if (i) DNT is off; (ii) browser supports implementation; (iii) localStorage contains geolocation history', () => { + localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); + grantTriangulation(); + const requestObject = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(requestObject.data); + expect(payload.geolocation).to.exist.and.not.be.empty; + cleanup(); + }) + + it('should not contain user coordinates if localStorage is empty', () => { + localStorage.removeItem('uolLocationTracker'); + denyTriangulation(); + const requestObject = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(requestObject.data); + expect(payload.geolocation).to.not.exist; + cleanup(); + }) + + it('should not contain user coordinates if browser doesnt support permission query', () => { + localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); + removeQuerySupport(); + const requestObject = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(requestObject.data); + expect(payload.geolocation).to.not.exist; + cleanup(); + }) + }) + } + describe('buildRequest test params', () => { + it('should return test and cpmFactor params if defined', () => { + let clonedBid = JSON.parse(JSON.stringify(bidRequests)); + delete clonedBid[0].params; + clonedBid.splice(1, 1); + clonedBid[0].params = { + 'placementId': '19571277', + 'test': true + } + let requestObject = spec.buildRequests(clonedBid, bidderRequest); + let payload = JSON.parse(requestObject.data); + expect(payload.requests[0].customParams.test).to.exist.and.equal(true); + expect(payload.requests[0].customParams.cpmFactor).to.be.an('undefined'); + + delete clonedBid[0].params; + clonedBid[0].params = { + 'placementId': '19571278', + 'test': true, + 'cpmFactor': 2 + } + requestObject = spec.buildRequests(clonedBid, bidderRequest); + payload = JSON.parse(requestObject.data); + expect(payload.requests[0].customParams.test).to.exist.and.equal(true); + expect(payload.requests[0].customParams.cpmFactor).to.exist.and.equal(2); + }); + }) + }); + + describe('interpretResponse', () => { + let serverResponse = { + 'body': { + 'bidderRequestId': '2a21a2fc993ef9', + 'ads': [{ + 'currency': 'BRL', + 'creativeId': '12334', + 'cpm': 1.9, + 'ttl': 300, + 'netRevenue': false, + 'ad': '', + 'width': 300, + 'height': 250, + 'bidId': '26df49c6447b82', + 'mediaType': 'banner' + }, { + 'currency': 'BRL', + 'creativeId': '12335', + 'cpm': 1.99, + 'ttl': 300, + 'netRevenue': false, + 'ad': '', + 'width': 300, + 'height': 600, + 'bidId': '26df49c6447b82', + 'mediaType': 'banner' + }] + }, + 'headers': {} + }; + let bidRequest = {}; + + it('should return the correct bid response structure', () => { + let expectedResponse = [ + { + 'requestId': '2a21a2fc993ef9', + 'cpm': 1.9, + 'width': 300, + 'height': 250, + 'creativeId': '12335', + 'currency': 'BRL', + 'dealId': null, + 'mediaType': 'banner', + 'netRevenue': false, + 'ttl': 300, + 'ad': '' + } + ]; + let result = spec.interpretResponse(serverResponse, {bidRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('should corretly return an empty array of bidResponses if no ads were received', () => { + let emptyResponse = Object.assign({}, serverResponse); + emptyResponse.body.ads = []; + let result = spec.interpretResponse(emptyResponse, {bidRequest}); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs', () => { + let syncOptions = { iframeEnabled: true }; + let serverResponses = [{ body: { trackingPixel: 'https://www.uol.com.br' } }, { body: { trackingPixel: 'http://www.dynad.net/' } }]; + + it('should return the two sync params for iframeEnabled bids with a trackingPixel response', () => { + expect(spec.getUserSyncs(syncOptions, serverResponses)).to.have.length(2); + }) + + it('should not return any sync params if iframe is disabled or no trackingPixel is received', () => { + let cloneOptions = Object.assign({}, syncOptions); + delete cloneOptions.iframeEnabled; + expect(spec.getUserSyncs(cloneOptions, serverResponses)).to.have.length(0); + + let cloneResponses = Object.assign({}, serverResponses); + delete cloneResponses[0].body.trackingPixel; + delete cloneResponses[1].body.trackingPixel; + expect(spec.getUserSyncs(syncOptions, cloneResponses)).to.have.length(0); + + expect(spec.getUserSyncs(cloneOptions, cloneResponses)).to.have.length(0); + }) + }); +}); From 0d19865883bc4e9a97df00a0909b2c3867ee03b9 Mon Sep 17 00:00:00 2001 From: adxcgcom <31470944+adxcgcom@users.noreply.github.com> Date: Wed, 18 Jul 2018 16:29:18 +0200 Subject: [PATCH 0550/1594] additional parameters sent on auction, impression and video level (#2819) * additional parameters sent on auction, impression and video level * Removed commented code here, line 64 and line 85 * removing trailing spaces * comments cleanup --- modules/adxcgBidAdapter.js | 280 +++++++++++++++------- test/spec/modules/adxcgBidAdapter_spec.js | 277 +++++++++++---------- 2 files changed, 346 insertions(+), 211 deletions(-) diff --git a/modules/adxcgBidAdapter.js b/modules/adxcgBidAdapter.js index c6f35445a46..6b95fb1d38a 100644 --- a/modules/adxcgBidAdapter.js +++ b/modules/adxcgBidAdapter.js @@ -1,17 +1,25 @@ -import * as utils from 'src/utils'; -import * as url from 'src/url'; -import {registerBidder} from 'src/adapters/bidderFactory'; -import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes'; +import { config } from 'src/config' +import * as utils from 'src/utils' +import * as url from 'src/url' +import { registerBidder } from 'src/adapters/bidderFactory' +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes' +import includes from 'core-js/library/fn/array/includes' /** * 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 */ -const BIDDER_CODE = 'adxcg'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; -const SOURCE = 'pbjs10'; +const BIDDER_CODE = 'adxcg' +const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE] +const SOURCE = 'pbjs10' +const VIDEO_TARGETING = ['id', 'mimes', '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 = 'r20180703PB10' + export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, @@ -23,7 +31,33 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - return !!(bid.params.adzoneid); + if (!bid || !bid.params) { + utils.logWarn(BIDDER_CODE + ': Missing bid parameters') + return false + } + + if (!utils.isStr(bid.params.adzoneid)) { + utils.logWarn(BIDDER_CODE + ': adzoneid must be specified as a string') + return false + } + + if (isVideoRequest(bid)) { + if (!bid.params.video.mimes) { + // Give a warning but let it pass + utils.logWarn(BIDDER_CODE + ': mimes should be specified for videos') + } else if (!utils.isArray(bid.params.video.mimes) || !bid.params.video.mimes.every(s => utils.isStr(s))) { + utils.logWarn(BIDDER_CODE + ': mimes must be an array of strings') + return false + } + + const context = utils.deepAccess(bid, 'mediaTypes.video.context') + if (context !== 'instream') { + utils.logWarn(BIDDER_CODE + ': video context must be valid - instream') + return false + } + } + + return true }, /** @@ -33,53 +67,110 @@ export const spec = { * Info describing the request to the server. */ buildRequests: function (validBidRequests, bidderRequest) { - utils.logMessage(`buildRequests: ${JSON.stringify(validBidRequests)}`); - - let adZoneIds = []; - let prebidBidIds = []; - let sizes = []; + utils.logMessage(`buildRequests: ${JSON.stringify(validBidRequests)}`) - validBidRequests.forEach(bid => { - adZoneIds.push(utils.getBidIdParameter('adzoneid', bid.params)); - prebidBidIds.push(bid.bidId); - sizes.push(utils.parseSizesInput(bid.sizes).join('|')); - }); + let location = utils.getTopWindowLocation() + let secure = location.protocol === 'https:' + 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 location = utils.getTopWindowLocation(); - let secure = location.protocol === 'https:'; + let bt = config.getConfig('bidderTimeout') + if (window.PREBID_TIMEOUT) { + bt = Math.min(window.PREBID_TIMEOUT, bt) + } - let requestUrl = url.parse(location.href); - requestUrl.search = null; - requestUrl.hash = null; + let requestUrl = url.parse(location.href) + requestUrl.search = null + requestUrl.hash = null + // add common parameters let beaconParams = { renderformat: 'javascript', - ver: 'r20180522PB10', - adzoneid: adZoneIds.join(','), - format: sizes.join(','), - prebidBidIds: prebidBidIds.join(','), - url: encodeURIComponent(url.format(requestUrl)), + ver: BIDADAPTERVERSION, + url: encodeURIComponent(utils.getTopWindowUrl()), secure: secure ? '1' : '0', source: SOURCE, - pbjs: '$prebid.version$' - }; + 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 + } + + if (utils.getTopWindowReferrer()) { + beaconParams.ref = encodeURIComponent(utils.getTopWindowReferrer()) + } if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { - beaconParams.gdpr = bidderRequest.gdprConsent.gdprApplies ? '1' : '0'; - beaconParams.gdpr_consent = bidderRequest.gdprConsent.consentString; + beaconParams.gdpr = bidderRequest.gdprConsent.gdprApplies ? '1' : '0' + beaconParams.gdpr_consent = bidderRequest.gdprConsent.consentString } + 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) + sizes.push(utils.parseSizesInput(bid.sizes).join('|')) + + let bidfloor = utils.getBidIdParameter('bidfloor', bid.params) || 0 + bidfloors.push(bidfloor) + // copy video params + 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 context params + beaconParams['video.context' + '.' + index] = utils.deepAccess(bid, 'mediaTypes.video.context') + } + + // 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])) + } + }) + + beaconParams.adzoneid = adZoneIds.join(',') + beaconParams.format = sizes.join(',') + beaconParams.prebidBidIds = prebidBidIds.join(',') + beaconParams.bidfloors = bidfloors.join(',') + let adxcgRequestUrl = url.format({ protocol: secure ? 'https' : 'http', hostname: secure ? 'hbps.adxcg.net' : 'hbp.adxcg.net', pathname: '/get/adi', search: beaconParams - }); + }) return { + contentType: 'text/plain', method: 'GET', url: adxcgRequestUrl, - }; + withCredentials: true + } }, /** * Unpack the response from the server into a list of bids. @@ -87,77 +178,84 @@ export const spec = { * @param {*} serverResponse A successful response from the server. * @return {bidRequests[]} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse, bidRequests) { - let bids = []; - - serverResponse = serverResponse.body; - if (serverResponse) { - serverResponse.forEach(serverResponseOneItem => { - let bid = {}; - - bid.requestId = serverResponseOneItem.bidId; - bid.cpm = serverResponseOneItem.cpm; - bid.creativeId = parseInt(serverResponseOneItem.creativeId); - bid.currency = serverResponseOneItem.currency ? serverResponseOneItem.currency : 'USD'; - bid.netRevenue = serverResponseOneItem.netRevenue ? serverResponseOneItem.netRevenue : true; - bid.ttl = serverResponseOneItem.ttl ? serverResponseOneItem.ttl : 300; - - if (serverResponseOneItem.deal_id != null && serverResponseOneItem.deal_id.trim().length > 0) { - bid.dealId = serverResponseOneItem.deal_id; - } + interpretResponse: - if (serverResponseOneItem.ad) { - bid.ad = serverResponseOneItem.ad; - } else if (serverResponseOneItem.vastUrl) { - bid.vastUrl = serverResponseOneItem.vastUrl; - bid.mediaType = 'video'; - } else if (serverResponseOneItem.nativeResponse) { - bid.mediaType = 'native'; + function (serverResponse, bidRequests) { + let bids = [] - let nativeResponse = serverResponseOneItem.nativeResponse; + serverResponse = serverResponse.body + if (serverResponse) { + serverResponse.forEach(serverResponseOneItem => { + let bid = {} - bid['native'] = { - clickUrl: encodeURIComponent(nativeResponse.link.url), - impressionTrackers: nativeResponse.imptrackers - }; + bid.requestId = serverResponseOneItem.bidId + bid.cpm = serverResponseOneItem.cpm + bid.creativeId = parseInt(serverResponseOneItem.creativeId) + bid.currency = serverResponseOneItem.currency ? serverResponseOneItem.currency : 'USD' + bid.netRevenue = serverResponseOneItem.netRevenue ? serverResponseOneItem.netRevenue : true + bid.ttl = serverResponseOneItem.ttl ? serverResponseOneItem.ttl : 300 - nativeResponse.assets.forEach(asset => { - if (asset.title && asset.title.text) { - bid['native'].title = asset.title.text; - } + if (serverResponseOneItem.deal_id != null && serverResponseOneItem.deal_id.trim().length > 0) { + bid.dealId = serverResponseOneItem.deal_id + } - if (asset.img && asset.img.url) { - bid['native'].image = asset.img.url; - } + if (serverResponseOneItem.ad) { + bid.ad = serverResponseOneItem.ad + } else if (serverResponseOneItem.vastUrl) { + bid.vastUrl = serverResponseOneItem.vastUrl + bid.mediaType = 'video' + } else if (serverResponseOneItem.nativeResponse) { + bid.mediaType = 'native' - if (asset.data && asset.data.label === 'DESC' && asset.data.value) { - bid['native'].body = asset.data.value; - } + let nativeResponse = serverResponseOneItem.nativeResponse - if (asset.data && asset.data.label === 'SPONSORED' && asset.data.value) { - bid['native'].sponsoredBy = asset.data.value; + bid['native'] = { + clickUrl: encodeURIComponent(nativeResponse.link.url), + impressionTrackers: nativeResponse.imptrackers } - }); - } - bid.width = serverResponseOneItem.width; - bid.height = serverResponseOneItem.height; - utils.logMessage(`submitting bid[${serverResponseOneItem.bidId}]: ${JSON.stringify(bid)}`); - bids.push(bid); - }); - } else { - utils.logMessage(`empty bid response`); - } - return bids; - }, + nativeResponse.assets.forEach(asset => { + if (asset.title && asset.title.text) { + bid['native'].title = asset.title.text + } + + if (asset.img && asset.img.url) { + bid['native'].image = asset.img.url + } + + if (asset.data && asset.data.label === 'DESC' && asset.data.value) { + bid['native'].body = asset.data.value + } + + if (asset.data && asset.data.label === 'SPONSORED' && asset.data.value) { + bid['native'].sponsoredBy = asset.data.value + } + }) + } + + bid.width = serverResponseOneItem.width + bid.height = serverResponseOneItem.height + utils.logMessage(`submitting bid[${serverResponseOneItem.bidId}]: ${JSON.stringify(bid)}`) + bids.push(bid) + }) + } else { + utils.logMessage(`empty bid response`) + } + return bids + }, + getUserSyncs: function (syncOptions) { if (syncOptions.iframeEnabled) { return [{ type: 'iframe', url: '//cdn.adxcg.net/pb-sync.html' - }]; + }] } } -}; +} + +function isVideoRequest (bid) { + return bid.mediaType === 'video' || !!utils.deepAccess(bid, 'mediaTypes.video') +} -registerBidder(spec); +registerBidder(spec) diff --git a/test/spec/modules/adxcgBidAdapter_spec.js b/test/spec/modules/adxcgBidAdapter_spec.js index 64b4805ca9f..60aadaec21f 100644 --- a/test/spec/modules/adxcgBidAdapter_spec.js +++ b/test/spec/modules/adxcgBidAdapter_spec.js @@ -1,10 +1,10 @@ -import {expect} from 'chai'; -import * as url from 'src/url'; -import {spec} from 'modules/adxcgBidAdapter'; +import { expect } from 'chai' +import * as url from 'src/url' +import { spec } from 'modules/adxcgBidAdapter' describe('AdxcgAdapter', () => { describe('isBidRequestValid', () => { - let bid = { + let bidBanner = { 'bidder': 'adxcg', 'params': { 'adzoneid': '1' @@ -14,19 +14,54 @@ describe('AdxcgAdapter', () => { 'bidId': '84ab500420319d', 'bidderRequestId': '7101db09af0db2', 'auctionId': '1d1a030790a475', - }; + } + + let bidVideo = { + 'bidder': 'adxcg', + 'params': { + 'adzoneid': '1', + 'api': [2], + 'protocols': [1, 2], + 'mimes': ['video/mp4', 'video/x-flv'], + 'maxduration': 30 + }, + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [640, 360], [1, 1]], + 'bidId': '84ab500420319d', + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '1d1a030790a475', + } it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); + expect(spec.isBidRequestValid(bidBanner)).to.equal(true) + }) + + it('should return true when required params not found', () => { + expect(spec.isBidRequestValid({})).to.be.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); - }); - }); + let bid = Object.assign({}, bidBanner) + delete bid.params + bid.params = {} + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + + it('should return true when required video params not found', () => { + const simpleVideo = JSON.parse(JSON.stringify(bidVideo)) + simpleVideo.params.adzoneid = 123 + expect(spec.isBidRequestValid(simpleVideo)).to.be.false + simpleVideo.params.mimes = [1, 2, 3] + expect(spec.isBidRequestValid(simpleVideo)).to.be.false + simpleVideo.params.mimes = 'bad type' + expect(spec.isBidRequestValid(simpleVideo)).to.be.false + }) + }) describe('request function http', () => { let bid = { @@ -39,30 +74,27 @@ describe('AdxcgAdapter', () => { 'bidId': '84ab500420319d', 'bidderRequestId': '7101db09af0db2', 'auctionId': '1d1a030790a475', - }; + } it('creates a valid adxcg request url', () => { - let request = spec.buildRequests([bid]); - expect(request).to.exist; - // console.log('IS:' + JSON.stringify(request)); - - expect(request.method).to.equal('GET'); - let parsedRequestUrl = url.parse(request.url); - - expect(parsedRequestUrl.hostname).to.equal('hbp.adxcg.net'); - expect(parsedRequestUrl.pathname).to.equal('/get/adi'); - - let query = parsedRequestUrl.search; - expect(query.renderformat).to.equal('javascript'); - expect(query.ver).to.equal('r20180522PB10'); - 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.empty; - expect(query.prebidBidIds).to.equal('84ab500420319d'); - }); - }); + let request = spec.buildRequests([bid]) + expect(request).to.exist + expect(request.method).to.equal('GET') + let parsedRequestUrl = url.parse(request.url) + expect(parsedRequestUrl.hostname).to.equal('hbp.adxcg.net') + expect(parsedRequestUrl.pathname).to.equal('/get/adi') + + let query = parsedRequestUrl.search + expect(query.renderformat).to.equal('javascript') + expect(query.ver).to.equal('r20180703PB10') + 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.empty + expect(query.prebidBidIds).to.equal('84ab500420319d') + }) + }) describe('gdpr compliance', () => { let bid = { @@ -75,26 +107,31 @@ describe('AdxcgAdapter', () => { 'bidId': '84ab500420319d', 'bidderRequestId': '7101db09af0db2', 'auctionId': '1d1a030790a475', - }; + } it('should send GDPR Consent data if gdprApplies', () => { - let request = spec.buildRequests([bid], {gdprConsent: {gdprApplies: true, consentString: 'consentDataString'}}); - let parsedRequestUrl = url.parse(request.url); - let query = parsedRequestUrl.search; + let request = spec.buildRequests([bid], {gdprConsent: {gdprApplies: true, consentString: 'consentDataString'}}) + let parsedRequestUrl = url.parse(request.url) + let query = parsedRequestUrl.search - expect(query.gdpr).to.equal('1'); - expect(query.gdpr_consent).to.equal('consentDataString'); - }); + expect(query.gdpr).to.equal('1') + expect(query.gdpr_consent).to.equal('consentDataString') + }) it('should not send GDPR Consent data if gdprApplies is false or undefined', () => { - let request = spec.buildRequests([bid], {gdprConsent: {gdprApplies: false, consentString: 'consentDataString'}}); - let parsedRequestUrl = url.parse(request.url); - let query = parsedRequestUrl.search; - - expect(query.gdpr).to.be.empty; - expect(query.gdpr_consent).to.be.empty; - }); - }); + let request = spec.buildRequests([bid], { + gdprConsent: { + gdprApplies: false, + consentString: 'consentDataString' + } + }) + let parsedRequestUrl = url.parse(request.url) + let query = parsedRequestUrl.search + + expect(query.gdpr).to.be.empty + expect(query.gdpr_consent).to.be.empty + }) + }) describe('response handler', () => { let BIDDER_REQUEST = { @@ -107,7 +144,7 @@ describe('AdxcgAdapter', () => { 'bidId': '84ab500420319d', 'bidderRequestId': '7101db09af0db2', 'auctionId': '1d1a030790a475', - }; + } let BANNER_RESPONSE = { @@ -209,89 +246,89 @@ describe('AdxcgAdapter', () => { } it('handles regular responses', () => { - 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.equal(0.45); - 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; - }); + 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.equal(0.45) + 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 + }) it('handles regular responses with dealid', () => { - let result = spec.interpretResponse(BANNER_RESPONSE_WITHDEALID, BIDDER_REQUEST); + let result = spec.interpretResponse(BANNER_RESPONSE_WITHDEALID, BIDDER_REQUEST) - expect(result).to.have.lengthOf(1); + expect(result).to.have.lengthOf(1) - 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].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].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].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('handles video responses', () => { - let result = spec.interpretResponse(VIDEO_RESPONSE, BIDDER_REQUEST); - 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); - }); + let result = spec.interpretResponse(VIDEO_RESPONSE, BIDDER_REQUEST) + 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) + }) it('handles native responses', () => { - let result = spec.interpretResponse(NATIVE_RESPONSE, BIDDER_REQUEST); - - expect(result[0].width).to.equal(0); - expect(result[0].height).to.equal(0); - expect(result[0].mediaType).to.equal('native'); - 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].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).to.equal('imageContent'); - expect(result[0].native.body).to.equal('descriptionContent'); - expect(result[0].native.sponsoredBy).to.equal('sponsoredByContent'); - }); + let result = spec.interpretResponse(NATIVE_RESPONSE, BIDDER_REQUEST) + + expect(result[0].width).to.equal(0) + expect(result[0].height).to.equal(0) + expect(result[0].mediaType).to.equal('native') + 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].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).to.equal('imageContent') + expect(result[0].native.body).to.equal('descriptionContent') + expect(result[0].native.sponsoredBy).to.equal('sponsoredByContent') + }) it('handles nobid responses', () => { - let response = []; - let bidderRequest = BIDDER_REQUEST; + let response = [] + let bidderRequest = BIDDER_REQUEST - let result = spec.interpretResponse(response, bidderRequest); - expect(result.length).to.equal(0); - }); - }); + let result = spec.interpretResponse(response, bidderRequest) + expect(result.length).to.equal(0) + }) + }) describe('getUserSyncs', () => { let syncoptionsIframe = { 'iframeEnabled': 'true' - }; + } it('should return iframe sync option', () => { - expect(spec.getUserSyncs(syncoptionsIframe)[0].type).to.equal('iframe'); - expect(spec.getUserSyncs(syncoptionsIframe)[0].url).to.equal('//cdn.adxcg.net/pb-sync.html'); - }); - }); -}); + expect(spec.getUserSyncs(syncoptionsIframe)[0].type).to.equal('iframe') + expect(spec.getUserSyncs(syncoptionsIframe)[0].url).to.equal('//cdn.adxcg.net/pb-sync.html') + }) + }) +}) From 54ba1d24e668ab5fabf3e3797893bf7037bbc4c1 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 19 Jul 2018 10:31:36 -0400 Subject: [PATCH 0551/1594] update several packages to address vulnerability warnings (#2863) * update coveralls and webdriver pacakges * remove gulp-webdriver and webdriverio packages * update additional packages to fix other vulnerabilities --- package-lock.json | 9122 +++++++++++++++++++++++++++++++-------------- package.json | 7 +- 2 files changed, 6360 insertions(+), 2769 deletions(-) diff --git a/package-lock.json b/package-lock.json index 08fc89fbd73..ae24e70fc80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,29 @@ { "name": "prebid.js", - "version": "1.16.0-pre", + "version": "1.17.0-pre", "lockfileVersion": 1, + "requires": true, "dependencies": { "@gulp-sourcemaps/identity-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", - "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.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=" + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + } }, "@sindresorhus/is": { "version": "0.7.0", @@ -28,9 +33,22 @@ }, "@sinonjs/formatio": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "dev": true + "dev": true, + "requires": { + "samsam": "1.3.0" + } + }, + "JSONStream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz", + "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } }, "abbrev": { "version": "1.0.9", @@ -39,21 +57,28 @@ "dev": true }, "accepts": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", - "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", - "dev": true + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } }, "acorn": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.2.tgz", - "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" }, "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": { + "acorn": "^4.0.3" + }, "dependencies": { "acorn": { "version": "4.0.13", @@ -68,6 +93,9 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, + "requires": { + "acorn": "^3.0.4" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -91,16 +119,24 @@ "dev": true }, "agent-base": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", - "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", - "dev": true + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } }, "ajv": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", - "dev": true + "dev": true, + "requires": { + "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", @@ -113,12 +149,20 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -133,6 +177,13 @@ "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", "dev": true, "optional": true, + "requires": { + "bitsyntax": "~0.0.4", + "bluebird": "^3.4.6", + "buffer-more-ints": "0.0.2", + "readable-stream": "1.x >=1.1.9", + "safe-buffer": "^5.0.1" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -146,7 +197,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, - "optional": true + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -161,7 +218,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } }, "ansi-escapes": { "version": "3.1.0", @@ -173,7 +233,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-html": { "version": "0.0.7", @@ -203,74 +266,28 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } }, "append-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } }, "append-transform": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", - "dev": true - }, - "archiver": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", - "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", "dev": true, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "glob": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", - "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lazystream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", - "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", - "dev": true - }, - "lodash": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", - "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", - "dev": true - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "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 - }, - "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 - } + "requires": { + "default-require-extensions": "^2.0.0" } }, "archy": { @@ -283,7 +300,10 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } }, "arr-diff": { "version": "4.0.0", @@ -337,7 +357,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } }, "array-uniq": { "version": "1.0.3", @@ -351,12 +374,6 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, - "array.from": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/array.from/-/array.from-0.2.0.tgz", - "integrity": "sha1-LGJ7G3bf8t7yNl+gUrZcPVheX2s=", - "dev": true - }, "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", @@ -379,32 +396,43 @@ "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "assert": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "dev": true, + "requires": { + "util": "0.10.3" + }, "dependencies": { "inherits": { "version": "2.0.1", - "resolved": "https://npm.corp.appnexus.com/inherits/-/inherits-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", "dev": true }, "util": { "version": "0.10.3", - "resolved": "https://npm.corp.appnexus.com/util/-/util-0.10.3.tgz", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true + "dev": true, + "requires": { + "inherits": "2.0.1" + } } } }, "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, "assertion-error": { @@ -455,9 +483,9 @@ "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" }, "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "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 }, "aws4": { @@ -472,20 +500,29 @@ "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", "dev": true, "optional": true, + "requires": { + "follow-redirects": "1.0.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, - "optional": true + "optional": true, + "requires": { + "ms": "2.0.0" + } }, "follow-redirects": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", "dev": true, - "optional": true + "optional": true, + "requires": { + "debug": "^2.2.0" + } } } }, @@ -493,19 +530,48 @@ "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 + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } }, "babel-core": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "babel-generator": "^6.22.0", + "babel-helpers": "^6.22.0", + "babel-messages": "^6.22.0", + "babel-register": "^6.22.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.22.0", + "babel-traverse": "^6.22.0", + "babel-types": "^6.22.0", + "babylon": "^6.11.0", + "convert-source-map": "^1.1.0", + "debug": "^2.1.1", + "json5": "^0.5.0", + "lodash": "^4.2.0", + "minimatch": "^3.0.2", + "path-is-absolute": "^1.0.0", + "private": "^0.1.6", + "slash": "^1.0.0", + "source-map": "^0.5.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "source-map": { "version": "0.5.7", @@ -520,6 +586,16 @@ "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": { "source-map": { "version": "0.5.7", @@ -533,109 +609,201 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-builder-react-jsx": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } }, "babel-helper-call-delegate": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-define-map": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-helper-explode-assignable-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-explode-class": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-get-function-arity": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-hoist-variables": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-regex": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-helper-remap-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helpers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-loader": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", - "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", - "dev": true + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz", + "integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==", + "dev": true, + "requires": { + "find-cache-dir": "^1.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.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 + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-check-es2015-constants": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", @@ -725,312 +893,600 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0" + } }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-generators": "^6.5.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-class-constructor-call": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "^6.18.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-class-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-decorators": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true + "dev": true, + "requires": { + "babel-helper-explode-class": "^6.24.1", + "babel-plugin-syntax-decorators": "^6.13.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-decorators-legacy": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-decorators": "^6.1.18", + "babel-runtime": "^6.2.0", + "babel-template": "^6.3.0" + } }, "babel-plugin-transform-do-expressions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-block-scoping": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-plugin-transform-es2015-classes": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-computed-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-destructuring": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-duplicate-keys": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-for-of": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-modules-amd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } }, "babel-plugin-transform-es2015-modules-systemjs": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-modules-umd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-parameters": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-shorthand-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-spread": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-sticky-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-template-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-typeof-symbol": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-unicode-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } }, "babel-plugin-transform-exponentiation-operator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-export-extensions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-flow-strip-types": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-function-bind": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "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=" + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx-source": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-regenerator": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true + "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + } }, "babel-plugin-transform-strict-mode": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } }, "babel-preset-flow": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "^6.22.0" + } }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.3.13", + "babel-plugin-transform-react-display-name": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "babel-plugin-transform-react-jsx-self": "^6.22.0", + "babel-plugin-transform-react-jsx-source": "^6.22.0", + "babel-preset-flow": "^6.23.0" + } }, "babel-preset-stage-0": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-do-expressions": "^6.22.0", + "babel-plugin-transform-function-bind": "^6.22.0", + "babel-preset-stage-1": "^6.24.1" + } }, "babel-preset-stage-1": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-class-constructor-call": "^6.24.1", + "babel-plugin-transform-export-extensions": "^6.22.0", + "babel-preset-stage-2": "^6.24.1" + } }, "babel-preset-stage-2": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-decorators": "^6.24.1", + "babel-preset-stage-3": "^6.24.1" + } }, "babel-preset-stage-3": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-plugin-transform-exponentiation-operator": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^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": { "babel-core": { "version": "6.26.3", - "resolved": "https://npm.corp.appnexus.com/babel-core/-/babel-core-6.26.3.tgz", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true + "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" + } }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "source-map": { "version": "0.5.7", @@ -1043,25 +1499,50 @@ "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=" + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } }, "babel-template": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true + "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 + "dev": true, + "requires": { + "ms": "2.0.0" + } } } }, @@ -1069,7 +1550,13 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } }, "babelify": { "version": "8.0.0", @@ -1106,30 +1593,53 @@ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "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" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -1145,42 +1655,27 @@ "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, - "base64-url": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", - "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", - "dev": true - }, "base64id": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", "dev": true }, - "basic-auth": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", - "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", - "dev": true - }, - "basic-auth-connect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", - "dev": true - }, "batch": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", - "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", "dev": true }, "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, - "optional": true + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } }, "beeper": { "version": "1.1.1", @@ -1192,7 +1687,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true + "dev": true, + "requires": { + "callsite": "1.0.0" + } }, "big.js": { "version": "3.2.0", @@ -1204,7 +1702,11 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } }, "binary-extensions": { "version": "1.11.0", @@ -1223,31 +1725,49 @@ "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", "dev": true, - "optional": true + "optional": true, + "requires": { + "buffer-more-ints": "0.0.2" + } }, "bl": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", - "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", "dev": true, + "optional": true, + "requires": { + "readable-stream": "~2.0.5" + }, "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "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, + "optional": 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 + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "optional": 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" + } }, "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 + "dev": true, + "optional": true } } }, @@ -1279,25 +1799,46 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true + "dev": true, + "requires": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } }, "body-parser": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", - "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", - "dev": true, + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "dev": true, + "requires": { + "bytes": "2.2.0", + "content-type": "~1.0.1", + "debug": "~2.2.0", + "depd": "~1.1.0", + "http-errors": "~1.3.1", + "iconv-lite": "0.4.13", + "on-finished": "~2.3.0", + "qs": "5.2.0", + "raw-body": "~2.1.5", + "type-is": "~1.6.10" + }, "dependencies": { "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", "dev": true }, "debug": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true + "dev": true, + "requires": { + "ms": "0.7.1" + } }, "ms": { "version": "0.7.1", @@ -1306,9 +1847,9 @@ "dev": true }, "qs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", "dev": true }, "raw-body": { @@ -1316,18 +1857,17 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + }, "dependencies": { "bytes": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", "dev": true - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true } } } @@ -1337,25 +1877,47 @@ "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true + "dev": true, + "requires": { + "hoek": "2.x.x" + } }, "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 + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "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 + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -1366,10 +1928,13 @@ "dev": true }, "browser-resolve": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, + "requires": { + "resolve": "1.1.7" + }, "dependencies": { "resolve": { "version": "1.1.7", @@ -1389,119 +1954,150 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "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 + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } }, "browserify-des": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", - "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", - "dev": true + "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.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "browserify-rsa": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } }, "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 + "dev": true, + "requires": { + "pako": "~1.0.5" + } }, "browserslist": { "version": "3.2.8", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } }, "browserstack": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", "dev": true, + "requires": { + "https-proxy-agent": "1.0.0" + }, "dependencies": { "agent-base": { "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true + "dev": true, + "requires": { + "extend": "~3.0.0", + "semver": "~5.0.1" + } }, "debug": { "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "https-proxy-agent": { "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true + "dev": true, + "requires": { + "agent-base": "2", + "debug": "2", + "extend": "3" + } }, "semver": { "version": "5.0.3", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", "dev": true } } }, "browserstacktunnel-wrapper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.2.tgz", - "integrity": "sha512-7w7HYA00qjBtuQH0c5rqW7RbWPHyRROqTZofwNp5G0sKc2fYChsTfbHz3ul8Yd+ffkQvR81m+iPjEB004P6kxQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.3.tgz", + "integrity": "sha512-I3u/EOOPGBt34RN0PBhPDwee4Dsik/Y2URK7iJn/vj5sR8JIoNh5I9gA6bFyxhU9sCo/1ISN4p7URNXK4zD4AA==", "dev": true, - "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true - }, - "semver": { - "version": "5.0.3", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - } + "requires": { + "https-proxy-agent": "^2.2.1", + "unzip": "~0.1.11" } }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true - }, - "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 + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } }, "buffer-equal": { "version": "1.0.0", @@ -1544,7 +2140,16 @@ "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", "dev": true, - "optional": true + "optional": true, + "requires": { + "addressparser": "1.0.1", + "libbase64": "0.1.0", + "libmime": "3.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.6.0", + "nodemailer-shared": "1.1.0", + "punycode": "1.4.1" + } }, "builtin-modules": { "version": "1.1.1", @@ -1568,17 +2173,37 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true + "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" + } }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", "dev": true, + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, "dependencies": { "lowercase-keys": { "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", "dev": true } @@ -1588,7 +2213,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true + "dev": true, + "requires": { + "callsites": "^0.2.0" + } }, "callsite": { "version": "1.0.0", @@ -1613,6 +2241,10 @@ "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" + }, "dependencies": { "camelcase": { "version": "2.1.1", @@ -1623,15 +2255,15 @@ } }, "caniuse-lite": { - "version": "1.0.30000851", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000851.tgz", - "integrity": "sha512-Y1ecA1cL9wg0vni8t33nBw/poX8ypm+2c3fbwAESj8cm4ufK9CBFQ1+nUK8Dp5dtFo5Fc3JzkI5DKmQbuIo6hQ==", + "version": "1.0.30000865", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", + "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==", "dev": true }, "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "ccount": { @@ -1644,19 +2276,32 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } }, "chai": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true + "dev": true, + "requires": { + "assertion-error": "^1.0.1", + "deep-eql": "^0.1.3", + "type-detect": "^1.0.0" + } }, "chai-nightwatch": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", "dev": true, + "requires": { + "assertion-error": "1.0.0", + "deep-eql": "0.1.3" + }, "dependencies": { "assertion-error": { "version": "1.0.0", @@ -1670,13 +2315,23 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "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" + } }, "character-entities": { "version": "1.2.2", @@ -1715,16 +2370,35 @@ "dev": true }, "chokidar": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", - "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", - "dev": true + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } }, "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 + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "circular-json": { "version": "0.3.3", @@ -1737,12 +2411,21 @@ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "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" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, @@ -1750,7 +2433,10 @@ "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 + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } }, "cli-width": { "version": "2.2.0", @@ -1762,7 +2448,12 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } }, "clone": { "version": "2.1.1", @@ -1780,7 +2471,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, "clone-stats": { "version": "1.0.0", @@ -1792,7 +2486,12 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } }, "co": { "version": "4.6.0", @@ -1816,13 +2515,20 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } }, "color-convert": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", - "dev": true + "dev": true, + "requires": { + "color-name": "1.1.1" + } }, "color-name": { "version": "1.1.1", @@ -1846,24 +2552,33 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.5.0" + } }, "combined-stream": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } }, "comma-separated-tokens": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "dev": true + "dev": true, + "requires": { + "trim": "0.0.1" + } }, "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.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", "dev": true }, "commondir": { @@ -1873,9 +2588,9 @@ "dev": true }, "compare-versions": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.2.1.tgz", - "integrity": "sha512-2y2nHcopMG/NAyk6vWXlLs86XeM9sik4jmx1tKIgzMi9/RQ2eo758RGpxQO3ErihHmg0RlQITPqgz73y6s7quA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.3.0.tgz", + "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==", "dev": true }, "component-bind": { @@ -1896,72 +2611,6 @@ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", "dev": true }, - "compress-commons": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", - "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "compressible": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz", - "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", - "dev": true, - "dependencies": { - "mime-db": { - "version": "1.34.0", - "resolved": "https://npm.corp.appnexus.com/mime-db/-/mime-db-1.34.0.tgz", - "integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o=", - "dev": true - } - } - }, - "compression": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/compression/-/compression-1.5.2.tgz", - "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", - "dev": true, - "dependencies": { - "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1972,43 +2621,43 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } }, "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 + "dev": true, + "requires": { + "source-map": "^0.6.1" + } }, "connect": { - "version": "2.30.2", - "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", - "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + }, "dependencies": { - "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", - "dev": true + "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" + } } } }, @@ -2018,31 +2667,14 @@ "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", "dev": true }, - "connect-timeout": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", - "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true + "dev": true, + "requires": { + "date-now": "^0.1.4" + } }, "constants-browserify": { "version": "1.0.0", @@ -2074,21 +2706,9 @@ "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" }, "cookie": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", - "dev": true - }, - "cookie-parser": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", - "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", "dev": true }, "copy-descriptor": { @@ -2108,10 +2728,18 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "coveralls": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", - "dev": true, + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.2.tgz", + "integrity": "sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw==", + "dev": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.11.0", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.85.0" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -2121,89 +2749,101 @@ } } }, - "crc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", - "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", - "dev": true - }, - "crc32-stream": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", - "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } }, "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 + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "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 + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "cryptiles": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true + "dev": true, + "optional": true, + "requires": { + "boom": "2.x.x" + } }, "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 - }, - "csrf": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", - "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", - "dev": true + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } }, "css": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", + "requires": { + "inherits": "^2.0.1", + "source-map": "^0.1.38", + "source-map-resolve": "^0.5.1", + "urix": "^0.1.0" + }, "dependencies": { "source-map": { "version": "0.1.43", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=" + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -2213,35 +2853,37 @@ "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", "dev": true, "optional": true, + "requires": { + "csso": "1.3.x", + "loader-utils": "~0.2.2", + "source-map": "~0.1.38" + }, "dependencies": { "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, - "optional": true + "optional": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } }, "source-map": { "version": "0.1.43", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, - "optional": true + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, - "css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true - }, - "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 - }, "csso": { "version": "1.3.12", "resolved": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", @@ -2249,23 +2891,14 @@ "dev": true, "optional": true }, - "csurf": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", - "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", - "dev": true - }, - "ctype": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", - "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", - "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 + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } }, "custom-event": { "version": "1.0.1", @@ -2276,24 +2909,18 @@ "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=" - }, - "dargs": { - "version": "github:christian-bromann/dargs#7d6d4164a7c4106dbd14ef39ed8d95b7b5e9b770", - "dev": true + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "^0.10.9" + } }, "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": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } + "requires": { + "assert-plus": "^1.0.0" } }, "data-uri-to-buffer": { @@ -2323,12 +2950,20 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==" + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } }, "debug-fabulous": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==" + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + } }, "decamelize": { "version": "1.2.0", @@ -2345,13 +2980,19 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, "deep-eql": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", "dev": true, + "requires": { + "type-detect": "0.1.1" + }, "dependencies": { "type-detect": { "version": "0.1.1", @@ -2367,23 +3008,23 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "deepmerge": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", - "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", - "dev": true - }, "default-require-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", - "dev": true + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + } }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, + "requires": { + "clone": "^1.0.2" + }, "dependencies": { "clone": { "version": "1.0.4", @@ -2397,31 +3038,50 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true + "dev": true, + "requires": { + "foreach": "^2.0.5", + "object-keys": "^1.0.8" + } }, "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, + "requires": { + "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -2436,6 +3096,11 @@ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", "dev": true, + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + }, "dependencies": { "esprima": { "version": "3.1.3", @@ -2450,6 +3115,15 @@ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, "dependencies": { "pify": { "version": "2.3.0", @@ -2466,9 +3140,9 @@ "dev": true }, "depd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "deprecated": { @@ -2481,7 +3155,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "destroy": { "version": "1.0.4", @@ -2493,7 +3171,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", - "dev": true + "dev": true, + "requires": { + "repeat-string": "^1.5.4" + } }, "detect-file": { "version": "1.0.0", @@ -2505,7 +3186,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "detect-newline": { "version": "2.1.0", @@ -2516,7 +3200,11 @@ "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } }, "di": { "version": "0.0.1", @@ -2534,31 +3222,99 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } }, "disparity": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", - "dev": true - }, + "dev": true, + "requires": { + "ansi-styles": "^2.0.1", + "diff": "^1.3.2" + } + }, "doctrine": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } }, "doctrine-temporary-fork": { "version": "2.0.0-alpha-allowarrayindex", "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } }, "documentation": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", "dev": true, + "requires": { + "ansi-html": "^0.0.7", + "babel-core": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-plugin-system-import-transformer": "3.1.0", + "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-preset-env": "^1.6.1", + "babel-preset-react": "^6.24.1", + "babel-preset-stage-0": "^6.24.1", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babelify": "^8.0.0", + "babylon": "^6.18.0", + "chalk": "^2.3.0", + "chokidar": "^2.0.0", + "concat-stream": "^1.6.0", + "disparity": "^2.0.0", + "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", + "get-port": "^3.2.0", + "git-url-parse": "^8.0.0", + "github-slugger": "1.2.0", + "glob": "^7.1.2", + "globals-docs": "^2.4.0", + "highlight.js": "^9.12.0", + "js-yaml": "^3.10.0", + "lodash": "^4.17.4", + "mdast-util-inject": "^1.1.0", + "micromatch": "^3.1.5", + "mime": "^1.4.1", + "module-deps-sortable": "4.0.6", + "parse-filepath": "^1.0.2", + "pify": "^3.0.0", + "read-pkg-up": "^3.0.0", + "remark": "^9.0.0", + "remark-html": "7.0.0", + "remark-reference-links": "^4.0.1", + "remark-toc": "^5.0.0", + "remote-origin-url": "0.4.0", + "shelljs": "^0.8.1", + "stream-array": "^1.1.2", + "strip-json-comments": "^2.0.1", + "tiny-lr": "^1.1.0", + "unist-builder": "^1.0.2", + "unist-util-visit": "^1.3.0", + "vfile": "^2.3.0", + "vfile-reporter": "^4.0.0", + "vfile-sort": "^2.1.0", + "vinyl": "^2.1.0", + "vinyl-fs": "^3.0.2", + "yargs": "^9.0.1" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -2570,31 +3326,57 @@ "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 + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "babel-core": { "version": "6.26.3", - "resolved": "https://npm.corp.appnexus.com/babel-core/-/babel-core-6.26.3.tgz", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true + "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" + } }, "chalk": { "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -2602,17 +3384,17 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "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.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", @@ -2626,13 +3408,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "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.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", @@ -2646,7 +3434,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } }, "source-map": { "version": "0.5.7", @@ -2658,31 +3451,60 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.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.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, "dependencies": { "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } } } } @@ -2692,7 +3514,13 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } }, "domain-browser": { "version": "1.2.0", @@ -2717,7 +3545,10 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } }, "duplexer3": { "version": "0.1.4", @@ -2729,14 +3560,23 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "dev": true, - "optional": true + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } }, "ee-first": { "version": "1.1.1", @@ -2751,16 +3591,25 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.48", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz", - "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=", + "version": "1.3.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", + "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=", "dev": true }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } }, "emoji-regex": { "version": "6.1.1", @@ -2784,51 +3633,69 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true + "dev": true, + "requires": { + "once": "^1.4.0" + } }, "engine.io": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", "dev": true, - "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "uws": "~9.14.0", + "ws": "~3.3.1" } }, "engine.io-client": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", - "dev": true + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } }, "engine.io-parser": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", - "dev": true + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary2": "~1.0.2" + } }, "enhanced-resolve": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.7" + } }, "ent": { "version": "2.2.0", @@ -2840,44 +3707,39 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true + "dev": true, + "requires": { + "prr": "~1.0.1" + } }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true + "dev": true, + "requires": { + "string-template": "~0.2.1", + "xtend": "~4.0.0" + } }, "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true - }, - "errorhandler": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", - "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", + "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": { - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } + "requires": { + "is-arrayish": "^0.2.1" } }, "es5-ext": { "version": "0.10.45", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", - "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==" + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } }, "es5-shim": { "version": "4.5.10", @@ -2888,13 +3750,26 @@ "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=" + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } }, "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 + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-promise": { "version": "4.2.4", @@ -2906,23 +3781,43 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=" + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "es6-weak-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=" + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } }, "escape-html": { "version": "1.0.3", @@ -2941,7 +3836,20 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + }, "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", @@ -2953,7 +3861,10 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, - "optional": true + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -2961,19 +3872,71 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "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", + "table": "4.0.2", + "text-table": "~0.2.0" + }, "dependencies": { "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true + "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" + } }, "ansi-regex": { "version": "3.0.0", @@ -2985,49 +3948,54 @@ "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 + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "chalk": { "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2" + } }, "globals": { - "version": "11.5.0", - "resolved": "https://npm.corp.appnexus.com/globals/-/globals-11.5.0.tgz", - "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -3042,12 +4010,19 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } } } }, @@ -3056,62 +4031,106 @@ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^1.0.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } }, "pkg-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true + "dev": true, + "requires": { + "find-up": "^1.0.0" + } } } }, "eslint-plugin-import": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz", - "integrity": "sha1-2tMXgSktZmSyUxf9BJ0uKy8CIF0=", - "dev": true, + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz", + "integrity": "sha512-t6hGKQDMIt9N8R7vLepsYXgDfeuhp6ZJSgtrLEDxonpSubyxUZHjhm6LsAaZX8q6GYVxkbT3kTsV9G5mBCFR6A==", + "dev": true, + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^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=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true + "dev": true, + "requires": { + "pify": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -3123,13 +4142,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } } } }, @@ -3138,6 +4166,12 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "5.3.0" + }, "dependencies": { "semver": { "version": "5.3.0", @@ -3160,10 +4194,14 @@ "dev": true }, "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true + "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, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint-visitor-keys": { "version": "1.0.0", @@ -3175,25 +4213,35 @@ "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } }, "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": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } }, "estraverse": { "version": "4.2.0", @@ -3222,13 +4270,26 @@ "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=" + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "event-stream": { "version": "3.3.4", "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true + "dev": true, + "requires": { + "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" + } }, "eventemitter3": { "version": "3.1.0", @@ -3246,19 +4307,37 @@ "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 + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.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" + } }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, "dependencies": { "array-slice": { "version": "0.2.3", @@ -3276,25 +4355,10 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true - }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true - }, - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } } } }, @@ -3303,55 +4367,65 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, "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=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + }, "dependencies": { - "fill-range": { - "version": "2.2.4", - "resolved": "https://npm.corp.appnexus.com/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true - }, "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", "dev": true }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", "dev": true } } @@ -3360,32 +4434,9 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true - }, - "express-session": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", - "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "uid-safe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", - "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", - "dev": true - } + "requires": { + "homedir-polyfill": "^1.0.1" } }, "extend": { @@ -3399,12 +4450,19 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, + "requires": { + "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 + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -3413,12 +4471,20 @@ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + }, "dependencies": { "iconv-lite": { "version": "0.4.23", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } } } }, @@ -3427,36 +4493,63 @@ "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.0", + "snapdragon": "^0.8.1", + "to-regex": "^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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -3476,7 +4569,12 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" + } }, "fast-deep-equal": { "version": "1.1.0", @@ -3500,19 +4598,29 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } }, "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 + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } }, "file-loader": { "version": "0.8.5", @@ -3520,13 +4628,22 @@ "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", "dev": true, "optional": true, + "requires": { + "loader-utils": "~0.2.5" + }, "dependencies": { "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, - "optional": true + "optional": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } } } }, @@ -3546,51 +4663,68 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } }, "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true + "dev": true, + "requires": { + "is-object": "~1.0.1", + "merge-descriptors": "~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.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 + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, "finalhandler": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", - "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", - "dev": true, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "escape-html": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", - "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true + "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" + } } } }, @@ -3598,7 +4732,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } }, "find-index": { "version": "0.1.1", @@ -3610,19 +4749,31 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, "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" + }, "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 + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } } } }, @@ -3630,7 +4781,14 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true + "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" + } }, "first-chunk-stream": { "version": "1.0.0", @@ -3648,19 +4806,32 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } }, "follow-redirects": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz", - "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz", + "integrity": "sha512-v9GI1hpaqq1ZZR6pBD1+kI7O24PhDvNGNodjS3MdcEqyrahCp8zbtpv+2B/krUnSmUH80lbAS7MrdeK5IylgKg==", + "dev": true, + "requires": { + "debug": "^3.1.0" + } }, "for-in": { "version": "1.0.2", @@ -3672,7 +4843,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true + "dev": true, + "requires": { + "for-in": "^1.0.1" + } }, "foreach": { "version": "2.0.5", @@ -3699,16 +4873,24 @@ "dev": true }, "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } }, "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 + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } }, "fresh": { "version": "0.3.0", @@ -3726,13 +4908,20 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } }, "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 + "dev": true, + "requires": { + "null-check": "^1.0.0" + } }, "fs-copy-file-sync": { "version": "1.1.1", @@ -3745,6 +4934,12 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, + "requires": { + "jsonfile": "~1.0.1", + "mkdirp": "0.3.x", + "ncp": "~0.4.2", + "rimraf": "~2.2.0" + }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -3764,13 +4959,22 @@ "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } }, "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, + "requires": { + "fs-extra": "~0.6.1", + "mkdirp": "~0.3.5", + "walk": "^2.3.9" + }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -3792,333 +4996,390 @@ "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", "dev": true, "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "dev": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "bundled": true, "dev": true }, "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 + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "chownr": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "dev": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ms": "2.0.0" + } }, "deep-extend": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", - "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", + "bundled": true, "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minipass": "^2.2.1" + } }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } }, "glob": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.21", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", - "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, "dev": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "bundled": true, "dev": true, "optional": 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 + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "bundled": true, "dev": true }, "minipass": { "version": "2.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", - "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", - "dev": true + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } }, "minizlib": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minipass": "^2.2.1" + } }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "bundled": true, "dev": true, "optional": true }, "needle": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", - "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } }, "node-pre-gyp": { "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", - "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } }, "npm-bundled": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", - "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "bundled": true, "dev": true, "optional": true }, "npm-packlist": { "version": "1.1.10", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", - "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "bundled": true, "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true, "optional": true }, "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=", + "bundled": true, "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "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=", + "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "bundled": true, "dev": true, "optional": true }, "rc": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", - "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "bundled": true, "dev": true, "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "dev": true, "optional": true } @@ -4126,116 +5387,134 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, "rimraf": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "glob": "^7.0.5" + } }, "safe-buffer": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "bundled": true, "dev": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, "dev": true, "optional": true }, "semver": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true, "optional": true }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.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=", + "bundled": true, "dev": true, "optional": true }, "tar": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", - "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "dev": true, "optional": true }, "wide-align": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "string-width": "^1.0.2" + } }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, "dev": true }, "yallist": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "bundled": true, "dev": true } } @@ -4245,12 +5524,21 @@ "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", "dev": true, + "requires": { + "graceful-fs": "~3.0.2", + "inherits": "~2.0.0", + "mkdirp": "0.5", + "rimraf": "2" + }, "dependencies": { "graceful-fs": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true + "dev": true, + "requires": { + "natives": "^1.1.0" + } } } }, @@ -4259,6 +5547,10 @@ "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", "dev": true, + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -4270,7 +5562,13 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -4296,24 +5594,32 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true + "dev": true, + "requires": { + "globule": "~0.1.0" + } }, "generate-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true + "dev": true, + "optional": true }, "generate-object-property": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true + "dev": true, + "optional": true, + "requires": { + "is-property": "^1.0.0" + } }, "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "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-func-name": { @@ -4345,12 +5651,23 @@ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", "dev": true, + "requires": { + "data-uri-to-buffer": "1", + "debug": "2", + "extend": "3", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "2" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } } } }, @@ -4365,50 +5682,71 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } + "requires": { + "assert-plus": "^1.0.0" } }, "git-up": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", - "dev": true + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "parse-url": "^1.3.0" + } }, "git-url-parse": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true + "dev": true, + "requires": { + "git-up": "^2.0.0", + "parse-domain": "^2.0.0" + } }, "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 - }, + "dev": true, + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + } + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true + "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-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, "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 + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } }, "is-extglob": { "version": "1.0.0", @@ -4420,7 +5758,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } } } }, @@ -4429,12 +5770,19 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } } } }, @@ -4442,31 +5790,61 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true + "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" + } }, "glob-watcher": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true + "dev": true, + "requires": { + "gaze": "^0.5.1" + } }, "glob2base": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true + "dev": true, + "requires": { + "find-index": "^0.1.1" + } }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } }, "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 + "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" + } }, "globals": { "version": "9.18.0", @@ -4485,6 +5863,14 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", @@ -4499,12 +5885,22 @@ "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, "dependencies": { "glob": { "version": "3.1.21", "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } }, "graceful-fs": { "version": "1.2.3", @@ -4534,7 +5930,11 @@ "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } } } }, @@ -4542,29 +5942,45 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "got": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/got/-/got-8.3.1.tgz", - "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", - "dev": true + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + } }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, "gulp": { @@ -4572,6 +5988,21 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, "dependencies": { "clone": { "version": "0.2.0", @@ -4589,19 +6020,36 @@ "version": "4.5.3", "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } }, "glob-stream": { "version": "3.1.18", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true + "dev": true, + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + } }, "graceful-fs": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true + "dev": true, + "requires": { + "natives": "^1.1.0" + } }, "isarray": { "version": "0.0.1", @@ -4613,7 +6061,10 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } }, "minimist": { "version": "1.2.0", @@ -4631,7 +6082,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "semver": { "version": "4.3.6", @@ -4649,13 +6106,21 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true + "dev": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } }, "unique-stream": { "version": "1.0.0", @@ -4667,13 +6132,27 @@ "version": "0.4.6", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } }, "vinyl-fs": { "version": "0.3.14", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true + "dev": true, + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + } } } }, @@ -4682,18 +6161,50 @@ "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", "dev": true, + "requires": { + "babel-core": "^6.23.1", + "object-assign": "^4.0.1", + "plugin-error": "^1.0.1", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + }, "dependencies": { "babel-core": { "version": "6.26.3", - "resolved": "https://npm.corp.appnexus.com/babel-core/-/babel-core-6.26.3.tgz", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true + "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" + } }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "replace-ext": { "version": "0.0.1", @@ -4714,6 +6225,11 @@ "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" + }, "dependencies": { "ansi-regex": { "version": "0.2.1", @@ -4731,7 +6247,14 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true + "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", @@ -4743,19 +6266,37 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.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 + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } } } }, @@ -4763,7 +6304,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^0.2.0" + } }, "isarray": { "version": "0.0.1", @@ -4781,25 +6325,48 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true + "dev": true, + "requires": { + "lodash._escapehtmlchar": "~2.4.1", + "lodash._reunescapedhtml": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "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 + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~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 + "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 + "dev": true, + "requires": { + "lodash._reinterpolate": "~2.4.1", + "lodash.escape": "~2.4.1" + } }, "minimist": { "version": "0.2.0", @@ -4817,7 +6384,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -4829,7 +6402,10 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^0.2.1" + } }, "supports-color": { "version": "0.2.0", @@ -4842,12 +6418,19 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~2.1.1" + }, "dependencies": { "xtend": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true + "dev": true, + "requires": { + "object-keys": "~0.4.0" + } } } }, @@ -4855,7 +6438,10 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true + "dev": true, + "requires": { + "clone-stats": "~0.0.1" + } }, "xtend": { "version": "3.0.0", @@ -4869,51 +6455,38 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + } }, "gulp-connect": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", - "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", - "dev": true, + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.5.0.tgz", + "integrity": "sha512-oRBLjw/4EVaZb8g8OcxOVdGD8ZXYrRiWKcNxlrGjxb/6Cp0GDdqw7ieX7D8xJrQS7sbXT+G94u63pMJF3MMjQA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "connect": "^3.6.5", + "connect-livereload": "^0.5.4", + "event-stream": "^3.3.2", + "fancy-log": "^1.3.2", + "send": "^0.13.2", + "serve-index": "^1.9.1", + "serve-static": "^1.13.1", + "tiny-lr": "^0.2.1" + }, "dependencies": { - "body-parser": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", - "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", - "dev": true, - "dependencies": { - "qs": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", - "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", - "dev": true - } - } - }, - "bytes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", - "dev": true - }, "debug": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true + "dev": true, + "requires": { + "ms": "0.7.1" + } }, "ms": { "version": "0.7.1", @@ -4927,25 +6500,19 @@ "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", "dev": true }, - "raw-body": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", - "dev": true, - "dependencies": { - "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true - } - } - }, "tiny-lr": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", - "dev": true + "dev": true, + "requires": { + "body-parser": "~1.14.0", + "debug": "~2.2.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.2.0", + "parseurl": "~1.3.0", + "qs": "~5.1.0" + } } } }, @@ -4953,37 +6520,65 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", - "dev": true + "dev": true, + "requires": { + "through2": "^2.0.3", + "vinyl": "^2.1.0" + } }, "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 + "dev": true, + "requires": { + "eslint": "^4.0.0", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.0" + } }, "gulp-footer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", - "dev": true + "dev": true, + "requires": { + "event-stream": "*", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.6.2" + } }, "gulp-header": { "version": "1.8.12", "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, + "requires": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + }, "dependencies": { "lodash.template": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } }, "lodash.templatesettings": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0" + } } } }, @@ -4991,13 +6586,21 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true + "dev": true, + "requires": { + "gulp-match": "^1.0.3", + "ternary-stream": "^2.0.1", + "through2": "^2.0.1" + } }, "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, + "requires": { + "through2": "^0.6.3" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -5009,7 +6612,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -5021,7 +6630,11 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } } } }, @@ -5029,18 +6642,27 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true + "dev": true, + "requires": { + "minimatch": "^3.0.3" + } }, "gulp-optimize-js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", - "dev": true + "dev": true, + "requires": { + "gulp-util": "^3.0.7", + "lodash": "^4.16.2", + "optimize-js": "^1.0.0", + "through2": "^2.0.1" + } }, "gulp-rename": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.3.tgz", - "integrity": "sha512-CmdPM0BjJ105QCX1fk+j7NGhiN/1rCl9HLGss+KllBS/tdYadpjTxqdKyh/5fNV+M3yjT1MFz5z93bXdrTyzAw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.3.0.tgz", + "integrity": "sha512-nEuZB7/9i0IZ8AXORTizl2QLP9tcC9uWc/s329zElBLJw1CfOhmMXBxwVlCRKjDyrWuhVP0uBKl61KeQ32TiCg==", "dev": true }, "gulp-replace": { @@ -5048,12 +6670,26 @@ "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", "dev": true, + "requires": { + "event-stream": "~3.0.18", + "istextorbinary": "~1.0.0", + "replacestream": "0.1.3" + }, "dependencies": { "event-stream": { "version": "3.0.20", "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", - "dev": true + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.0.3", + "pause-stream": "0.0.11", + "split": "0.2", + "stream-combiner": "~0.0.3", + "through": "~2.3.1" + } }, "map-stream": { "version": "0.0.7", @@ -5065,7 +6701,10 @@ "version": "0.2.10", "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "dev": true + "dev": true, + "requires": { + "through": "2" + } } } }, @@ -5073,24 +6712,62 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true + "dev": true, + "requires": { + "async": "^1.5.0", + "gulp-util": "^3.0.7", + "lodash": "^4.0.0", + "through2": "^2.0.0" + } }, "gulp-sourcemaps": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=" + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + } }, "gulp-uglify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", "dev": true, + "requires": { + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash": "^4.13.1", + "make-error-cause": "^1.1.1", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + }, "dependencies": { - "uglify-js": { - "version": "3.4.0", - "resolved": "https://npm.corp.appnexus.com/uglify-js/-/uglify-js-3.4.0.tgz", - "integrity": "sha512-Jcf5naPkX3rVPSQpRn9Vm6Rr572I1gTtR9LnqKgXjmOgfYQ/QS0V2WRStFR53Bdj520M66aCZqt9uzYXgtGrJQ==", + "commander": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", + "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", "dev": true + }, + "uglify-js": { + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.5.tgz", + "integrity": "sha512-Fm52gLqJqFBnT+Sn411NPDnsgaWiYeRLw42x7Va/mS8TKgaepwoGY7JLXHSEef3d3PmdFXSz1Zx7KMLL89E2QA==", + "dev": true, + "requires": { + "commander": "~2.16.0", + "source-map": "~0.6.1" + } } } }, @@ -5099,6 +6776,26 @@ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "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", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, "dependencies": { "clone": { "version": "1.0.4", @@ -5134,39 +6831,12 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true - } - } - }, - "gulp-webdriver": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-webdriver/-/gulp-webdriver-1.0.3.tgz", - "integrity": "sha1-mM6Bz5rganoZB7htEPaThvQ4Oi0=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } } } }, @@ -5174,45 +6844,90 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true + "dev": true, + "requires": { + "glogg": "^1.0.0" + } }, "handlebars": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, + "requires": { + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" + }, "dependencies": { "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true - }, - "has-ansi": { + "har-schema": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true }, - "has-binary2": { + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "^5.1.0", + "har-schema": "^2.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, + "requires": { + "isarray": "2.0.1" + }, "dependencies": { "isarray": { "version": "2.0.1", @@ -5238,7 +6953,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "has-symbol-support-x": { "version": "1.4.2", @@ -5256,25 +6974,40 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } }, "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, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5282,43 +7015,74 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } }, "hast-util-is-element": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz", - "integrity": "sha1-P3IWl4sq4U2YdJh4eCZ18zvjzgA=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.1.tgz", + "integrity": "sha512-s/ggaNehYVqmLgTXEv12Lbb72bsOD2r5DhAqPgtDdaI/YFNXVzz0zHFVJnhjIjn7Nak8GbL4nzT2q0RA5div+A==", "dev": true }, "hast-util-sanitize": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.1.2.tgz", - "integrity": "sha1-0QvWdXoh5ZwTq8iuNTDdO219Z54=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.2.0.tgz", + "integrity": "sha512-VwCTqjt6fbMGacxGB1FKV5sBJaVVkyCGVMDwb4nnqvCW2lkqscA2GEpOyBx4ZWRXty1eAZF58MHBrllEoQEoBg==", + "dev": true, + "requires": { + "xtend": "^4.0.1" + } }, "hast-util-to-html": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", - "dev": true + "dev": true, + "requires": { + "ccount": "^1.0.0", + "comma-separated-tokens": "^1.0.1", + "hast-util-is-element": "^1.0.0", + "hast-util-whitespace": "^1.0.0", + "html-void-elements": "^1.0.0", + "kebab-case": "^1.0.0", + "property-information": "^3.1.0", + "space-separated-tokens": "^1.0.0", + "stringify-entities": "^1.0.1", + "unist-util-is": "^2.0.0", + "xtend": "^4.0.1" + } }, "hast-util-whitespace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz", - "integrity": "sha1-vQlpGWJdKTbh/xe8Tff9cn8X7Ok=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.1.tgz", + "integrity": "sha512-Mfx2ZnmVMTAopZ8as42nKrNt650tCZYhy/MPeO1Imdg/cmCWK6GUSnFrrE3ezGjVifn7x5zMfu8jrjwIGyImSw==", "dev": true }, "hawk": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true + "dev": true, + "optional": true, + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } }, "he": { "version": "1.1.1", @@ -5337,13 +7101,22 @@ "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", "dev": true, - "optional": true + "optional": true, + "requires": { + "lodash": "^4.0.0", + "request": "^2.0.0" + } }, "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 + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } }, "hoek": { "version": "2.16.3", @@ -5355,18 +7128,25 @@ "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 + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } }, "homedir-polyfill": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } }, "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, "html-void-elements": { @@ -5385,7 +7165,11 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "dev": true + "dev": true, + "requires": { + "inherits": "~2.0.1", + "statuses": "1" + } }, "http-parser-js": { "version": "0.4.13", @@ -5397,25 +7181,43 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } }, "http-proxy-agent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + } }, "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } }, "httpntlm": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true + "dev": true, + "requires": { + "httpreq": ">=0.4.22", + "underscore": "~1.7.0" + } }, "httpreq": { "version": "0.4.24", @@ -5433,24 +7235,28 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "dev": true + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } }, "iconv-lite": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", - "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true }, "ieee754": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", - "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", "dev": true }, "ignore": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", - "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, "ignore-loader": { @@ -5469,7 +7275,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "indexof": { "version": "0.0.1", @@ -5488,7 +7297,11 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", @@ -5506,6 +7319,22 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "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", + "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" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -5517,13 +7346,21 @@ "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 + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "chalk": { "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -5535,19 +7372,29 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -5561,13 +7408,20 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true + "dev": true, + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } }, "invert-kv": { "version": "1.0.0", @@ -5585,19 +7439,29 @@ "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 + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.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.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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5617,7 +7481,11 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -5629,7 +7497,10 @@ "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 + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } }, "is-buffer": { "version": "1.1.6", @@ -5641,19 +7512,28 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5668,6 +7548,11 @@ "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", @@ -5687,7 +7572,10 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } }, "is-extendable": { "version": "0.1.1", @@ -5705,25 +7593,28 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true - }, - "is-generator": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", - "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } }, "is-hexadecimal": { "version": "1.0.2", @@ -5735,13 +7626,22 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true + "dev": true, + "optional": true }, "is-my-json-valid": { "version": "2.17.2", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", - "dev": true + "dev": true, + "optional": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } }, "is-negated-glob": { "version": "1.0.0", @@ -5754,12 +7654,18 @@ "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": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5769,20 +7675,6 @@ "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", "dev": true }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, - "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 - } - } - }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -5793,13 +7685,19 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } }, "is-plain-obj": { "version": "1.1.0", @@ -5811,7 +7709,10 @@ "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 + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "is-posix-bracket": { "version": "0.1.1", @@ -5834,13 +7735,17 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true + "dev": true, + "optional": true }, "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 + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } }, "is-resolvable": { "version": "1.1.0", @@ -5858,7 +7763,10 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", - "dev": true + "dev": true, + "requires": { + "protocols": "^1.1.0" + } }, "is-stream": { "version": "1.1.0", @@ -5876,7 +7784,10 @@ "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 + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } }, "is-utf8": { "version": "0.2.1", @@ -5942,12 +7853,41 @@ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, "dependencies": { + "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 + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-flag": { "version": "1.0.0", @@ -5965,7 +7905,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } } } }, @@ -5974,24 +7917,29 @@ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", "dev": true, + "requires": { + "async": "^2.1.4", + "compare-versions": "^3.1.0", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.0", + "istanbul-lib-hook": "^1.2.0", + "istanbul-lib-instrument": "^1.10.1", + "istanbul-lib-report": "^1.1.4", + "istanbul-lib-source-maps": "^1.2.4", + "istanbul-reports": "^1.3.0", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + }, "dependencies": { "async": { "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://npm.corp.appnexus.com/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.10" + } } } }, @@ -5999,7 +7947,13 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" + } }, "istanbul-lib-coverage": { "version": "1.2.0", @@ -6011,19 +7965,37 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz", "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==", - "dev": true + "dev": true, + "requires": { + "append-transform": "^1.0.0" + } }, "istanbul-lib-instrument": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", - "dev": true + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.0", + "semver": "^5.3.0" + } }, "istanbul-lib-report": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.0", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, "dependencies": { "has-flag": { "version": "1.0.0", @@ -6035,7 +8007,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } } } }, @@ -6044,6 +8019,13 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz", "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==", "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.0", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + }, "dependencies": { "source-map": { "version": "0.5.7", @@ -6057,25 +8039,40 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", - "dev": true + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } }, "istextorbinary": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", - "dev": true + "dev": true, + "requires": { + "binaryextensions": "~1.0.0", + "textextensions": "~1.0.0" + } }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } }, "jade": { "version": "0.26.3", "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, "dependencies": { "commander": { "version": "0.6.1", @@ -6098,10 +8095,14 @@ "dev": true }, "js-yaml": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", - "dev": true + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } }, "jsbn": { "version": "0.1.1", @@ -6150,7 +8151,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -6164,12 +8168,6 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", @@ -6198,26 +8196,19 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "JSONStream": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz", - "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==", - "dev": true + "dev": true, + "optional": true }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" } }, "just-clone": { @@ -6232,40 +8223,57 @@ "dev": true }, "karma": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.2.tgz", - "integrity": "sha1-TS25QChQpmVR+nhLAWT7CCTtjEs=", - "dev": true, + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.4.tgz", + "integrity": "sha512-32yhTwoi6BZgJZhR78GwhzyFABbYG/1WwQqYgY7Vh96Demvua2jM3+FyRltIMTUH/Kd5xaQvDw2L7jTvkYFeXg==", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.4", + "log4js": "^2.5.3", + "mime": "^1.3.4", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.0.4", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.2.1" + }, "dependencies": { - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, "body-parser": { "version": "1.18.3", - "resolved": "https://npm.corp.appnexus.com/body-parser/-/body-parser-1.18.3.tgz", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } }, "bytes": { "version": "3.0.0", @@ -6273,103 +8281,35 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true - }, - "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", - "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 - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "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 - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true - }, - "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "dev": true, - "dependencies": { - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - } + "requires": { + "ms": "2.0.0" } }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true - }, "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 + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } }, "iconv-lite": { "version": "0.4.23", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "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 - }, - "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 - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "range-parser": { "version": "1.2.0", @@ -6379,14 +8319,20 @@ }, "raw-body": { "version": "2.3.3", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true } } @@ -6395,20 +8341,20 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true + "dev": true, + "requires": { + "babel-core": "^6.0.0" + } }, "karma-browserstack-launcher": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", "dev": true, - "dependencies": { - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - } + "requires": { + "browserstack": "1.5.0", + "browserstacktunnel-wrapper": "~2.0.1", + "q": "~1.5.0" } }, "karma-chai": { @@ -6421,19 +8367,30 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true + "dev": true, + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } }, "karma-coverage-istanbul-reporter": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", - "dev": true + "dev": true, + "requires": { + "istanbul-api": "^1.3.1", + "minimatch": "^3.0.4" + } }, "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 + "dev": true, + "requires": { + "es5-shim": "^4.0.5" + } }, "karma-firefox-launcher": { "version": "1.1.0", @@ -6445,13 +8402,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.6.1" + } }, "karma-mocha": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", "dev": true, + "requires": { + "minimist": "1.2.0" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -6466,6 +8429,11 @@ "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", "dev": true, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "strip-ansi": "^4.0.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -6477,25 +8445,39 @@ "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 + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "chalk": { "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -6533,25 +8515,42 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + } }, "karma-spec-reporter": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true + "dev": true, + "requires": { + "colors": "^1.1.2" + } }, "karma-webpack": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", "dev": true, + "requires": { + "async": "^2.0.0", + "babel-runtime": "^6.0.0", + "loader-utils": "^1.0.0", + "lodash": "^4.0.0", + "source-map": "^0.5.6", + "webpack-dev-middleware": "^1.12.0" + }, "dependencies": { "async": { "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.10" + } }, "source-map": { "version": "0.5.7", @@ -6571,7 +8570,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } }, "kind-of": { "version": "6.0.2", @@ -6589,13 +8591,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } }, "lcov-parse": { "version": "0.0.10", @@ -6607,13 +8615,20 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } }, "libbase64": { "version": "0.1.0", @@ -6626,6 +8641,11 @@ "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, "dependencies": { "iconv-lite": { "version": "0.4.15", @@ -6645,7 +8665,17 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.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" + } }, "livereload-js": { "version": "2.3.0", @@ -6657,7 +8687,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } }, "loader-runner": { "version": "2.3.0", @@ -6669,19 +8705,34 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } }, "localtunnel": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.0.tgz", "integrity": "sha512-wCIiIHJ8kKIcWkTQE3m1VRABvsH2ZuOkiOpZUofUCf6Q42v3VIZ+Q0YfX1Z4sYDRj0muiKL1bLvz1FeoxsPO0w==", "dev": true, + "requires": { + "axios": "0.17.1", + "debug": "2.6.8", + "openurl": "1.1.1", + "yargs": "6.6.0" + }, "dependencies": { "axios": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", - "dev": true + "dev": true, + "requires": { + "follow-redirects": "^1.2.5", + "is-buffer": "^1.1.5" + } }, "camelcase": { "version": "3.0.0", @@ -6693,43 +8744,71 @@ "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.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=", - "dev": true + "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" + } }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true + "dev": true, + "requires": { + "lcid": "^1.0.0" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "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 + "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -6741,19 +8820,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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 + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } }, "which-module": { "version": "1.0.0", @@ -6765,13 +8856,31 @@ "version": "6.6.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "dev": true + "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": "^4.2.0" + } }, "yargs-parser": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } } } }, @@ -6779,7 +8888,11 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "lodash": { "version": "4.17.10", @@ -6803,13 +8916,25 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } }, "lodash._baseclone": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "dev": true + "dev": true, + "requires": { + "lodash._arraycopy": "^3.0.0", + "lodash._arrayeach": "^3.0.0", + "lodash._baseassign": "^3.0.0", + "lodash._basefor": "^3.0.0", + "lodash.isarray": "^3.0.0", + "lodash.keys": "^3.0.0" + } }, "lodash._basecopy": { "version": "3.0.1", @@ -6817,12 +8942,6 @@ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", "dev": true }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, "lodash._basefor": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", @@ -6851,7 +8970,10 @@ "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 + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1" + } }, "lodash._escapestringchar": { "version": "2.4.1", @@ -6912,12 +9034,21 @@ "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1", + "lodash.keys": "~2.4.1" + }, "dependencies": { "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 + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } } } }, @@ -6931,13 +9062,10 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true - }, - "lodash._stack": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", - "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } }, "lodash.assign": { "version": "4.2.0", @@ -6949,12 +9077,17 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true + "dev": true, + "requires": { + "lodash._baseclone": "^3.0.0", + "lodash._bindcallback": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "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 }, "lodash.defaults": { @@ -6962,35 +9095,39 @@ "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" + }, "dependencies": { "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 + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } } } }, "lodash.defaultsdeep": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", - "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", - "dev": true, - "dependencies": { - "lodash._baseclone": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", - "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", - "dev": true - } - } + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.0.tgz", + "integrity": "sha1-vsECT4WxvZbL6kBbI8FK1kQ6b4E=", + "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 - }, + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -7013,36 +9150,26 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true - }, - "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 + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.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 - }, - "lodash.keysin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", - "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } }, - "lodash.mergewith": { + "lodash.merge": { "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", - "dev": true - }, - "lodash.rest": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", - "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", "dev": true }, "lodash.restparam": { @@ -7061,32 +9188,55 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true + "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.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } }, "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, + "requires": { + "lodash.keys": "~2.4.1" + }, "dependencies": { "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 + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } } } }, "log-driver": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", "dev": true }, "log-symbols": { @@ -7094,37 +9244,66 @@ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, + "requires": { + "chalk": "^2.0.1" + }, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "chalk": { "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, "log4js": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.8.0.tgz", - "integrity": "sha512-PjsaE4ElS0e2jWOY14Ef2PrC1Y+fny4AWPPT3xD6+2k2Aa5golhqJ4DSzP+5kXRL5bSw/5j1ocU5A9ceaxZeGA==", - "dev": true, + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", + "integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==", + "dev": true, + "requires": { + "amqplib": "^0.5.2", + "axios": "^0.15.3", + "circular-json": "^0.5.4", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "hipchat-notifier": "^1.1.0", + "loggly": "^1.1.0", + "mailgun-js": "^0.18.0", + "nodemailer": "^2.5.0", + "redis": "^2.7.1", + "semver": "^5.5.0", + "slack-node": "~0.2.0", + "streamroller": "0.7.0" + }, "dependencies": { "circular-json": { - "version": "0.5.4", - "resolved": "https://npm.corp.appnexus.com/circular-json/-/circular-json-0.5.4.tgz", - "integrity": "sha512-vnJA8KS0BfOihugYEUkLRcnmq21FbuivbxgzDLXNs3zIk4KllV4Mx4UuTzBXht9F00C7QfD1YqMXg1zP6EXpig==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.5.tgz", + "integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==", "dev": true } } @@ -7135,11 +9314,30 @@ "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", "dev": true, "optional": true, + "requires": { + "json-stringify-safe": "5.0.x", + "request": "2.75.x", + "timespan": "2.3.x" + }, "dependencies": { - "bl": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true, + "optional": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true, "optional": true }, @@ -7148,7 +9346,37 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", "dev": true, - "optional": true + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "optional": true, + "requires": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } }, "node-uuid": { "version": "1.4.8", @@ -7157,13 +9385,6 @@ "dev": true, "optional": 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, - "optional": true - }, "qs": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", @@ -7171,33 +9392,49 @@ "dev": true, "optional": true }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "optional": true - }, "request": { "version": "2.75.0", "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", "dev": true, - "optional": true + "optional": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "bl": "~1.1.2", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.0.0", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "node-uuid": "~1.4.7", + "oauth-sign": "~0.8.1", + "qs": "~6.2.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1" + } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", "dev": true, "optional": true } } }, "lolex": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.0.tgz", - "integrity": "sha512-uJkH2e0BVfU5KOJUevbTOtpDduooSarH5PopO+LfM/vZf8Z9sJzODqKev804JYM2i++ktJfUmC1le4LwFQ1VMg==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.1.tgz", + "integrity": "sha512-Oo2Si3RMKV3+lV5MsSWplDQFoTClz/24S0MMHYcgGWWmFXr6TMlqcqk/l1GtH+d5wLBwNRiqGnwDRMirtFalJw==", "dev": true }, "longest": { @@ -7213,16 +9450,23 @@ "dev": true }, "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true + "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 + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } }, "lowercase-keys": { "version": "1.0.1", @@ -7234,46 +9478,67 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } }, "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=" + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "~0.10.2" + } }, "magic-string": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", - "dev": true + "dev": true, + "requires": { + "vlq": "^0.2.1" + } }, "mailcomposer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", "dev": true, - "optional": true + "optional": true, + "requires": { + "buildmail": "4.0.1", + "libmime": "3.0.0" + } }, "mailgun-js": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.0.tgz", - "integrity": "sha512-o0P6jjZlx5CQj12tvVgDTbgjTqVN0+5h6/6P1+3c6xmozVKBwniQ6Qt3MkCSF0+ueVTbobAfWyGpWRZMJu8t1g==", + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.1.tgz", + "integrity": "sha512-lvuMP14u24HS2uBsJEnzSyPMxzU2b99tQsIx1o6QNjqxjk8b3WvR+vq5oG1mjqz/IBYo+5gF+uSoDS0RkMVHmg==", "dev": true, "optional": true, + "requires": { + "async": "~2.6.0", + "debug": "~3.1.0", + "form-data": "~2.3.0", + "inflection": "~1.12.0", + "is-stream": "^1.1.0", + "path-proxy": "~1.0.0", + "promisify-call": "^2.0.2", + "proxy-agent": "~3.0.0", + "tsscmp": "~1.0.0" + }, "dependencies": { "async": { "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, - "optional": true - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://npm.corp.appnexus.com/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, - "optional": true + "optional": true, + "requires": { + "lodash": "^4.17.10" + } } } }, @@ -7281,7 +9546,10 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true + "dev": true, + "requires": { + "pify": "^3.0.0" + } }, "make-error": { "version": "1.3.4", @@ -7293,13 +9561,19 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true + "dev": true, + "requires": { + "make-error": "^1.2.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } }, "map-cache": { "version": "0.2.2", @@ -7323,7 +9597,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } }, "markdown-escapes": { "version": "1.0.2", @@ -7342,6 +9619,10 @@ "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", "dev": true, + "requires": { + "buffers": "~0.1.1", + "readable-stream": "~1.0.0" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -7353,7 +9634,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -7373,31 +9660,58 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } }, "mdast-util-compact": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", - "dev": true + "dev": true, + "requires": { + "unist-util-modify-children": "^1.0.0", + "unist-util-visit": "^1.1.0" + } }, "mdast-util-definitions": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.0" + } }, "mdast-util-to-hast": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.1.tgz", "integrity": "sha512-+eimV/12kdg0/T0EEfcK7IsDbSu2auVm92z5jdSEQ3DHF2HiU4OHmX9ir5wpQajr73nwabdxrUoxREvW2zVFFw==", - "dev": true + "dev": true, + "requires": { + "collapse-white-space": "^1.0.0", + "detab": "^2.0.0", + "mdast-util-definitions": "^1.2.0", + "mdurl": "^1.0.1", + "trim": "0.0.1", + "trim-lines": "^1.0.0", + "unist-builder": "^1.0.1", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.0", + "xtend": "^4.0.1" + } }, "mdast-util-to-string": { "version": "1.0.4", @@ -7409,7 +9723,12 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", - "dev": true + "dev": true, + "requires": { + "github-slugger": "^1.1.1", + "mdast-util-to-string": "^1.0.2", + "unist-util-visit": "^1.1.0" + } }, "mdurl": { "version": "1.0.1", @@ -7427,36 +9746,76 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "memoizee": { "version": "0.4.12", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz", - "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==" + "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==", + "requires": { + "d": "1", + "es5-ext": "^0.10.30", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.2" + } }, "memory-fs": { "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 + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } }, "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": { "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.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=", - "dev": true + "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" + } }, "minimist": { "version": "1.2.0", @@ -7468,19 +9827,30 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "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 + "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -7492,19 +9862,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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 + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } } } }, @@ -7518,45 +9900,41 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true - }, - "method-override": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", - "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", "dev": true, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - } + "requires": { + "readable-stream": "^2.0.1" } }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "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 + "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" + } }, "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 + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } }, "mime": { "version": "1.6.0", @@ -7565,16 +9943,19 @@ "dev": true }, "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", "dev": true }, "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "dev": true, + "requires": { + "mime-db": "~1.35.0" + } }, "mimic-fn": { "version": "1.2.0", @@ -7583,9 +9964,9 @@ "dev": true }, "mimic-response": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", - "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", "dev": true }, "minimalistic-assert": { @@ -7604,7 +9985,10 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "0.0.8", @@ -7617,12 +10001,19 @@ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, + "requires": { + "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 + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -7630,7 +10021,10 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true + "dev": true, + "requires": { + "minimist": "0.0.8" + } }, "mkpath": { "version": "1.0.0", @@ -7643,6 +10037,17 @@ "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.0.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.5.0", + "supports-color": "~1.2.0" + }, "dependencies": { "commander": { "version": "2.3.0", @@ -7654,7 +10059,10 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", - "dev": true + "dev": true, + "requires": { + "ms": "0.6.2" + } }, "escape-string-regexp": { "version": "1.0.2", @@ -7666,7 +10074,12 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "~2.0.0", + "inherits": "2", + "minimatch": "~0.2.11" + } }, "graceful-fs": { "version": "2.0.3", @@ -7676,7 +10089,7 @@ }, "growl": { "version": "1.8.1", - "resolved": "https://npm.corp.appnexus.com/growl/-/growl-1.8.1.tgz", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", "dev": true }, @@ -7690,13 +10103,20 @@ "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } }, "mkdirp": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", - "dev": true + "dev": true, + "requires": { + "minimist": "0.0.8" + } }, "ms": { "version": "0.6.2", @@ -7712,61 +10132,15 @@ } } }, - "mocha-nightwatch": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", - "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", - "dev": true, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "glob": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", - "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "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 - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true - } - } - }, "mock-fs": { "version": "3.12.1", "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", "dev": true, + "requires": { + "rewire": "2.5.2", + "semver": "5.3.0" + }, "dependencies": { "semver": { "version": "5.3.0", @@ -7781,18 +10155,47 @@ "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "concat-stream": "~1.5.0", + "defined": "^1.0.0", + "detective": "^4.0.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.3", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, "dependencies": { "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + }, "dependencies": { "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true + "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" + } } } }, @@ -7816,68 +10219,28 @@ "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", "dev": true }, - "morgan": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", - "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "multiparty": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", - "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true - }, - "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 - } - } - }, "multipipe": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, "dependencies": { "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } }, "isarray": { "version": "0.0.1", @@ -7889,7 +10252,13 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -7913,10 +10282,23 @@ "optional": true }, "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "dev": true + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "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" + } }, "natives": { "version": "1.1.4", @@ -7937,9 +10319,9 @@ "dev": true }, "negotiator": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", - "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, "neo-async": { @@ -7960,165 +10342,140 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nightwatch": { - "version": "0.9.21", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.21.tgz", - "integrity": "sha1-nnlKdRS0/V9GYC02jlBRUjKrnpA=", - "dev": true, - "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://npm.corp.appnexus.com/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "co": { - "version": "3.0.6", - "resolved": "https://npm.corp.appnexus.com/co/-/co-3.0.6.tgz", - "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.corp.appnexus.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "ejs": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://npm.corp.appnexus.com/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true - }, - "http-proxy-agent": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", - "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", - "dev": true - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://npm.corp.appnexus.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.6.tgz", + "integrity": "sha1-F7Ghm0VfEi+SPkftfth7bJimopY=", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "chai-nightwatch": "~0.1.x", + "ejs": "^2.5.9", + "lodash.clone": "^3.0.3", + "lodash.defaultsdeep": "^4.6.0", + "lodash.merge": "^4.6.1", + "minimatch": "3.0.3", + "mkpath": "1.0.0", + "mocha": "^5.1.1", + "optimist": "^0.6.1", + "proxy-agent": "^3.0.0" + }, + "dependencies": { + "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, + "optional": true }, - "ip": { - "version": "1.0.1", - "resolved": "https://npm.corp.appnexus.com/ip/-/ip-1.0.1.tgz", - "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", - "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==", + "dev": true, + "optional": true }, - "lru-cache": { - "version": "2.6.5", - "resolved": "https://npm.corp.appnexus.com/lru-cache/-/lru-cache-2.6.5.tgz", - "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", - "dev": true + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "optional": true }, "minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "dev": true - }, - "pac-proxy-agent": { - "version": "1.1.0", - "resolved": "https://npm.corp.appnexus.com/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", - "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", - "dev": true - }, - "pac-resolver": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/pac-resolver/-/pac-resolver-2.0.0.tgz", - "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", - "dev": true - }, - "proxy-agent": { - "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/proxy-agent/-/proxy-agent-2.0.0.tgz", - "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", - "dev": true - }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", - "dev": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } }, - "semver": { - "version": "5.0.3", - "resolved": "https://npm.corp.appnexus.com/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "optional": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } }, - "socks-proxy-agent": { - "version": "2.1.1", - "resolved": "https://npm.corp.appnexus.com/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", - "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", - "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, + "optional": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, "nise": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.1.tgz", - "integrity": "sha512-9JX3YwoIt3kS237scmSSOpEv7vCukVzLfwK0I0XhocDSHUANid8ZHnLEULbbSkfeMn98B2y5kphIWzZUylESRQ==", - "dev": true - }, - "node-int64": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", - "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", - "dev": true + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.2.tgz", + "integrity": "sha512-BxH/DxoQYYdhKgVAfqVy4pzXRZELHOIewzoesxpjYvpU+7YOalQhGNPf7wAx8pLrTNPrHRDlLOkAl8UI0ZpXjw==", + "dev": true, + "requires": { + "@sinonjs/formatio": "^2.0.0", + "just-extend": "^1.1.27", + "lolex": "^2.3.2", + "path-to-regexp": "^1.7.0", + "text-encoding": "^0.6.4" + } }, "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", "dev": true, - "dependencies": { - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - } + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" } }, "nodemailer": { @@ -8127,13 +10484,26 @@ "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", "dev": true, "optional": true, + "requires": { + "libmime": "3.0.0", + "mailcomposer": "4.0.1", + "nodemailer-direct-transport": "3.3.2", + "nodemailer-shared": "1.1.0", + "nodemailer-smtp-pool": "2.8.2", + "nodemailer-smtp-transport": "2.7.2", + "socks": "1.1.9" + }, "dependencies": { "socks": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", "dev": true, - "optional": true + "optional": true, + "requires": { + "ip": "^1.1.2", + "smart-buffer": "^1.0.4" + } } } }, @@ -8142,7 +10512,11 @@ "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", "dev": true, - "optional": true + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "smtp-connection": "2.12.0" + } }, "nodemailer-fetch": { "version": "1.6.0", @@ -8154,21 +10528,34 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true + "dev": true, + "requires": { + "nodemailer-fetch": "1.6.0" + } }, "nodemailer-smtp-pool": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", "dev": true, - "optional": true + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } }, "nodemailer-smtp-transport": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", "dev": true, - "optional": true + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } }, "nodemailer-wellknown": { "version": "0.1.10", @@ -8180,36 +10567,59 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true + "dev": true, + "requires": { + "abbrev": "1" + } }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=" + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } }, "normalize-url": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true + "dev": true, + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } }, "now-and-later": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.2" + } }, "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 + "dev": true, + "requires": { + "path-key": "^2.0.0" + } }, "null-check": { "version": "1.0.0", @@ -8245,62 +10655,99 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", "dev": true }, "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 + "dev": true, + "requires": { + "isobject": "^3.0.0" + } }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "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.4", + "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 + "dev": true, + "requires": { + "for-in": "^1.0.1" + } } } }, @@ -8308,31 +10755,37 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true - }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true + "dev": true, + "requires": { + "ee-first": "1.1.1" + } }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "open": { "version": "0.0.5", @@ -8351,6 +10804,10 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, "dependencies": { "wordwrap": { "version": "0.0.3", @@ -8365,6 +10822,13 @@ "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", "dev": true, + "requires": { + "acorn": "^3.3.0", + "concat-stream": "^1.5.1", + "estree-walker": "^0.3.0", + "magic-string": "^0.16.0", + "yargs": "^4.8.1" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -8382,37 +10846,62 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.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=", - "dev": true + "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" + } }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true + "dev": true, + "requires": { + "lcid": "^1.0.0" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "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 + "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -8424,19 +10913,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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 + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } }, "which-module": { "version": "1.0.0", @@ -8448,13 +10949,33 @@ "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true + "dev": true, + "requires": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.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.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } }, "yargs-parser": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } } } }, @@ -8462,25 +10983,44 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } }, "orchestrator": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + }, "dependencies": { "end-of-stream": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true + "dev": true, + "requires": { + "once": "~1.3.0" + } }, "once": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } } } }, @@ -8488,7 +11028,10 @@ "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 + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } }, "os-browserify": { "version": "0.3.0", @@ -8506,7 +11049,12 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } }, "os-tmpdir": { "version": "1.0.2", @@ -8542,19 +11090,28 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true + "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 + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } }, "p-try": { "version": "1.0.0", @@ -8567,42 +11124,71 @@ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", "dev": true, - "optional": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^3.0.0" + }, "dependencies": { "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true, - "optional": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://npm.corp.appnexus.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "optional": true + "dev": true }, "http-errors": { "version": "1.6.3", - "resolved": "https://npm.corp.appnexus.com/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, - "optional": true + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } }, "iconv-lite": { "version": "0.4.23", - "resolved": "https://npm.corp.appnexus.com/iconv-lite/-/iconv-lite-0.4.23.tgz", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, - "optional": true + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "raw-body": { "version": "2.3.3", - "resolved": "https://npm.corp.appnexus.com/raw-body/-/raw-body-2.3.3.tgz", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", "dev": true, - "optional": true + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", + "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "socks": "^1.1.10" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true } } }, @@ -8611,7 +11197,13 @@ "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", "dev": true, - "optional": true + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } }, "pako": { "version": "1.0.6", @@ -8623,65 +11215,108 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } }, "parse-asn1": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } }, "parse-domain": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.1.tgz", - "integrity": "sha512-xOQ/B+pnS8uzqFMHcS7VS9J7Cn+rFyPlGIoDMFL2e5g/tPhlpa8MSHQmFAlABHBKPCXgOOxFt5PFNdEmwtwvqQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.2.tgz", + "integrity": "sha512-I1HuHXYL8hZp9MYf0jHZE2nW0qhJnqBAxKOR9sGCbiBoD3znYrp4nh3SH9dkt2+f6gEenEj6sh537FTNe+QBqg==", "dev": true, + "requires": { + "chai": "^4.1.2", + "fs-copy-file-sync": "^1.1.1", + "got": "^8.0.1", + "mkdirp": "^0.5.1", + "mocha": "^4.0.1" + }, "dependencies": { "chai": { "version": "4.1.2", - "resolved": "https://npm.corp.appnexus.com/chai/-/chai-4.1.2.tgz", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", - "dev": true - }, - "commander": { - "version": "2.11.0", - "resolved": "https://npm.corp.appnexus.com/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true + "dev": true, + "requires": { + "assertion-error": "^1.0.1", + "check-error": "^1.0.1", + "deep-eql": "^3.0.0", + "get-func-name": "^2.0.0", + "pathval": "^1.0.0", + "type-detect": "^4.0.0" + } }, "deep-eql": { "version": "3.0.1", - "resolved": "https://npm.corp.appnexus.com/deep-eql/-/deep-eql-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } }, "diff": { "version": "3.3.1", - "resolved": "https://npm.corp.appnexus.com/diff/-/diff-3.3.1.tgz", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "dev": true }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, "has-flag": { "version": "2.0.0", - "resolved": "https://npm.corp.appnexus.com/has-flag/-/has-flag-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, "mocha": { "version": "4.1.0", - "resolved": "https://npm.corp.appnexus.com/mocha/-/mocha-4.1.0.tgz", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "dev": true + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + } }, "supports-color": { "version": "4.4.0", - "resolved": "https://npm.corp.appnexus.com/supports-color/-/supports-color-4.4.0.tgz", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } }, "type-detect": { "version": "4.0.8", - "resolved": "https://npm.corp.appnexus.com/type-detect/-/type-detect-4.0.8.tgz", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true } @@ -8691,25 +11326,47 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.2.tgz", "integrity": "sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg==", - "dev": true + "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" + } }, "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 + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } }, "parse-git-config": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", - "dev": true + "dev": true, + "requires": { + "ini": "^1.3.3" + } }, "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.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, "dependencies": { "is-extglob": { "version": "1.0.0", @@ -8721,7 +11378,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } } } }, @@ -8729,7 +11389,11 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } }, "parse-passwd": { "version": "1.0.0", @@ -8741,19 +11405,29 @@ "version": "1.3.11", "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", - "dev": true + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } }, "parseuri": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } }, "parseurl": { "version": "1.3.2", @@ -8821,6 +11495,9 @@ "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", "dev": true, "optional": true, + "requires": { + "inflection": "~1.3.0" + }, "dependencies": { "inflection": { "version": "1.3.8", @@ -8835,7 +11512,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } }, "path-root-regex": { "version": "0.1.2", @@ -8848,6 +11528,9 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, + "requires": { + "isarray": "0.0.1" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -8861,7 +11544,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true + "dev": true, + "requires": { + "pify": "^3.0.0" + } }, "pathval": { "version": "1.1.0", @@ -8869,23 +11555,27 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, - "pause": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", - "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", - "dev": true - }, "pause-stream": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true + "dev": true, + "requires": { + "through": "~2.3" + } }, "pbkdf2": { "version": "3.0.16", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "dev": true + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "pbkdf2-compat": { "version": "2.0.1", @@ -8893,6 +11583,12 @@ "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", "dev": true }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -8909,19 +11605,31 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true + "dev": true, + "requires": { + "find-up": "^2.1.0" + } }, "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 + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } }, "pluralize": { "version": "7.0.0", @@ -8987,7 +11695,10 @@ "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", "dev": true, - "optional": true + "optional": true, + "requires": { + "with-callback": "^1.0.2" + } }, "property-information": { "version": "3.2.0", @@ -9002,24 +11713,37 @@ "dev": true }, "proxy-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.0.tgz", - "integrity": "sha512-g6n6vnk8fRf705ShN+FEXFG/SDJaW++lSs0d9KaJh4uBWW/wi7en4Cpo5VYQW3SZzAE121lhB/KLQrbURoubZw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.1.tgz", + "integrity": "sha512-mAZexaz9ZxQhYPWfAjzlrloEjW+JHiBFryE4AJXFDTnaXfmH/FKqC1swTRKuEPbHWz02flQNXFOyDUF7zfEG6A==", "dev": true, - "optional": true + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "pac-proxy-agent": "^2.0.1", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + } }, "proxy-from-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true, - "optional": true + "dev": true }, "proxyquire": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", "dev": true, + "requires": { + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.0", + "resolve": "~1.1.7" + }, "dependencies": { "resolve": { "version": "1.1.7", @@ -9045,13 +11769,26 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1" + } }, "pullstream": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", "dev": true, + "requires": { + "over": ">= 0.0.5 < 1", + "readable-stream": "~1.0.31", + "setimmediate": ">= 1.0.2 < 2", + "slice-stream": ">= 1.0.0 < 2" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -9063,7 +11800,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -9077,13 +11820,22 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } }, "punycode": { "version": "1.4.1", @@ -9092,9 +11844,9 @@ "dev": true }, "q": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/q/-/q-1.3.0.tgz", - "integrity": "sha1-hQ15+MuDHZLhA7Rkg+TjXTRkAFA=", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, "qjobs": { @@ -9104,16 +11856,21 @@ "dev": true }, "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "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 }, "query-string": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } }, "querystring": { "version": "0.2.0", @@ -9133,17 +11890,16 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "dev": true }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", - "dev": true - }, "randomatic": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -9157,13 +11913,20 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } }, "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 + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } }, "range-parser": { "version": "1.0.3", @@ -9176,6 +11939,10 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, + "requires": { + "bytes": "1", + "string_decoder": "0.10" + }, "dependencies": { "string_decoder": { "version": "0.10.31", @@ -9189,69 +11956,79 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==" + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "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" + } }, "readdirp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true - }, - "readline2": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", - "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", "dev": true, - "dependencies": { - "ansi-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", - "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", - "dev": true - }, - "mute-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", - "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=", - "dev": true - }, - "strip-ansi": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", - "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", - "dev": true - } + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" } }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true + "dev": true, + "requires": { + "resolve": "^1.1.6" + } }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } }, "redis": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", "dev": true, - "optional": true + "optional": true, + "requires": { + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" + } }, "redis-commands": { "version": "1.3.5", @@ -9282,19 +12059,31 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.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 + "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 + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } }, "regexpp": { "version": "1.1.0", @@ -9306,7 +12095,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } }, "regjsgen": { "version": "0.2.0", @@ -9319,6 +12113,9 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -9332,61 +12129,129 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true + "dev": true, + "requires": { + "remark-parse": "^5.0.0", + "remark-stringify": "^5.0.0", + "unified": "^6.0.0" + } }, "remark-html": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true + "dev": true, + "requires": { + "hast-util-sanitize": "^1.0.0", + "hast-util-to-html": "^3.0.0", + "mdast-util-to-hast": "^3.0.0", + "xtend": "^4.0.1" + } }, "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } }, "remark-reference-links": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.1.tgz", "integrity": "sha1-AhrtHFXBh9cSs8dtAFe/UQ0wC6c=", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.0.0" + } }, "remark-slug": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", - "dev": true + "dev": true, + "requires": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^1.0.0" + } }, "remark-stringify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true + "dev": true, + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } }, "remark-toc": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", - "dev": true + "dev": true, + "requires": { + "mdast-util-toc": "^2.0.0", + "remark-slug": "^5.0.0" + } }, "remote-origin-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true + "dev": true, + "requires": { + "parse-git-config": "^0.2.0" + } }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } }, "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 + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } }, "remove-trailing-separator": { "version": "1.1.0", @@ -9409,7 +12274,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } }, "replace-ext": { "version": "1.0.0", @@ -9421,20 +12289,51 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", - "dev": true + "dev": true, + "requires": { + "through": "~2.3.4" + } }, "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.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.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" + } }, "requestretry": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", "dev": true, - "optional": true + "optional": true, + "requires": { + "extend": "^3.0.0", + "lodash": "^4.15.0", + "request": "^2.74.0", + "when": "^3.7.7" + } }, "require-directory": { "version": "2.1.1", @@ -9452,7 +12351,11 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } }, "requirejs": { "version": "2.3.5", @@ -9467,16 +12370,23 @@ "dev": true }, "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", - "dev": true + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } }, "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 + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } }, "resolve-from": { "version": "1.0.1", @@ -9488,38 +12398,34 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, - "response-time": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", - "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", - "dev": true, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - } - } - }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } }, "ret": { "version": "0.1.15", @@ -9533,47 +12439,42 @@ "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", "dev": true }, - "rgb2hex": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.1.tgz", - "integrity": "sha512-icFtYF9bLbxRZ6zYlp28622lBM7Ae0ylPT+ob0SBZdd2p1FN5MoOClpwPcjT9TgXDLS8jyXlw3yVtHQZU3/vvg==", - "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 + "dev": true, + "requires": { + "align-text": "^0.1.1" + } }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.5" + } }, "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true - }, - "rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", - "dev": true + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true - }, - "rx": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", - "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=", - "dev": true + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } }, "rx-lite": { "version": "4.0.8", @@ -9585,7 +12486,10 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true + "dev": true, + "requires": { + "rx-lite": "*" + } }, "safe-buffer": { "version": "5.1.2", @@ -9602,7 +12506,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true + "dev": true, + "requires": { + "ret": "~0.1.10" + } }, "safer-buffer": { "version": "2.1.2", @@ -9621,12 +12528,21 @@ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", "dev": true, + "requires": { + "ajv": "^5.0.0" + }, "dependencies": { "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true + "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" + } } } }, @@ -9641,18 +12557,29 @@ "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", "dev": true, + "requires": { + "debug": "~2.2.0", + "depd": "~1.1.0", + "destroy": "~1.0.4", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "fresh": "0.3.0", + "http-errors": "~1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "~2.3.0", + "range-parser": "~1.0.3", + "statuses": "~1.2.1" + }, "dependencies": { "debug": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "dev": true, + "requires": { + "ms": "0.7.1" + } }, "mime": { "version": "1.3.4", @@ -9680,46 +12607,136 @@ "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", "dev": true }, - "serve-favicon": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", - "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", - "dev": true, + "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": { + "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" + }, "dependencies": { - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "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" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true } } }, - "serve-index": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", - "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "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" + } + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "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" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "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", + "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" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "dev": true } } }, - "serve-static": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", - "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", - "dev": true - }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -9737,12 +12754,21 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "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 + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -9762,13 +12788,20 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "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 + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } }, "shebang-regex": { "version": "1.0.0", @@ -9780,7 +12813,12 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } }, "sigmund": { "version": "1.0.1", @@ -9799,6 +12837,15 @@ "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "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" + }, "dependencies": { "diff": { "version": "3.5.0", @@ -9810,7 +12857,10 @@ "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "type-detect": { "version": "4.0.8", @@ -9825,7 +12875,10 @@ "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", "dev": true, - "optional": true + "optional": true, + "requires": { + "requestretry": "^1.2.2" + } }, "slash": { "version": "1.0.0", @@ -9838,6 +12891,9 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + }, "dependencies": { "is-fullwidth-code-point": { "version": "2.0.0", @@ -9852,6 +12908,9 @@ "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", "dev": true, + "requires": { + "readable-stream": "~1.0.31" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -9863,7 +12922,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -9883,31 +12948,54 @@ "version": "2.12.0", "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true + "dev": true, + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } }, "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": { + "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "source-map": { "version": "0.5.7", @@ -9922,30 +13010,49 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -9954,12 +13061,18 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -9967,19 +13080,33 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true + "dev": true, + "optional": true, + "requires": { + "hoek": "2.x.x" + } }, "socket.io": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", "dev": true, + "requires": { + "debug": "~2.6.6", + "engine.io": "~3.1.0", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.0.4", + "socket.io-parser": "~3.1.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } } } }, @@ -9994,12 +13121,30 @@ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~2.6.4", + "engine.io-client": "~3.1.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.1.1", + "to-array": "0.1.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } } } }, @@ -10008,6 +13153,12 @@ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "has-binary2": "~1.0.2", + "isarray": "2.0.1" + }, "dependencies": { "isarray": { "version": "2.0.1", @@ -10021,19 +13172,48 @@ "version": "1.1.10", "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "dev": true + "dev": true, + "requires": { + "ip": "^1.1.4", + "smart-buffer": "^1.0.13" + } }, "socks-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", - "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", + "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", + "dev": true, + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + }, + "dependencies": { + "smart-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", + "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", + "dev": true + }, + "socks": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz", + "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.0.1" + } + } + } }, "sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } }, "source-list-map": { "version": "2.0.0", @@ -10049,13 +13229,23 @@ "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==" + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } }, "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" + }, "dependencies": { "source-map": { "version": "0.5.7", @@ -10074,7 +13264,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "dev": true + "dev": true, + "requires": { + "trim": "0.0.1" + } }, "sparkles": { "version": "1.0.1", @@ -10086,7 +13279,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-exceptions": { "version": "2.1.0", @@ -10098,7 +13295,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-license-ids": { "version": "3.0.0", @@ -10110,13 +13311,19 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true + "dev": true, + "requires": { + "through": "2" + } }, "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 + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } }, "sprintf-js": { "version": "1.0.3", @@ -10129,13 +13336,16 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "dev": true, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "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" } }, "state-toggle": { @@ -10149,19 +13359,26 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", "dev": true }, "stream-array": { @@ -10169,6 +13386,9 @@ "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", "dev": true, + "requires": { + "readable-stream": "~2.1.0" + }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -10180,7 +13400,16 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true + "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" + } }, "string_decoder": { "version": "0.10.31", @@ -10194,19 +13423,30 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } }, "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 + "dev": true, + "requires": { + "duplexer": "~0.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 + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } }, "stream-consume": { "version": "0.1.1", @@ -10214,38 +13454,19 @@ "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", "dev": true }, - "stream-counter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", - "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", + "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, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true - }, - "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 - } + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, - "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 - }, "stream-shift": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", @@ -10256,7 +13477,13 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", - "dev": true + "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + } }, "strict-uri-encode": { "version": "1.1.0", @@ -10264,16 +13491,18 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "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==" - }, "string-replace-webpack-plugin": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", "dev": true, + "requires": { + "async": "~0.2.10", + "css-loader": "^0.9.1", + "file-loader": "^0.8.1", + "loader-utils": "~0.2.3", + "style-loader": "^0.8.3" + }, "dependencies": { "async": { "version": "0.2.10", @@ -10285,7 +13514,13 @@ "version": "0.2.17", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } } } }, @@ -10299,25 +13534,48 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } }, "stringify-entities": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true + "dev": true, + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } }, "stringstream": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true + "dev": true, + "optional": true }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, "strip-bom": { "version": "3.0.0", @@ -10340,7 +13598,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } }, "strip-json-comments": { "version": "2.0.1", @@ -10354,13 +13615,22 @@ "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", "dev": true, "optional": true, + "requires": { + "loader-utils": "^0.2.5" + }, "dependencies": { "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, - "optional": true + "optional": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } } } }, @@ -10369,6 +13639,9 @@ "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, + "requires": { + "minimist": "^1.1.0" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -10389,12 +13662,26 @@ "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", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + }, "dependencies": { "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true + "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" + } }, "ansi-regex": { "version": "3.0.0", @@ -10406,13 +13693,21 @@ "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 + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "chalk": { "version": "2.4.1", - "resolved": "https://npm.corp.appnexus.com/chalk/-/chalk-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -10424,19 +13719,29 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -10446,37 +13751,17 @@ "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", "dev": true }, - "tar-stream": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", - "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, "ternary-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true + "dev": true, + "requires": { + "duplexify": "^3.5.0", + "fork-stream": "^0.0.4", + "merge-stream": "^1.0.0", + "through2": "^2.0.1" + } }, "text-encoding": { "version": "0.6.4", @@ -10505,13 +13790,21 @@ "through2": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=" + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } }, "through2-filter": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } }, "thunkify": { "version": "2.1.2", @@ -10523,7 +13816,10 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } }, "time-stamp": { "version": "1.1.0", @@ -10541,12 +13837,19 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } }, "timers-ext": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", - "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==" + "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==", + "requires": { + "es5-ext": "~0.10.14", + "next-tick": "1" + } }, "timespan": { "version": "2.3.0", @@ -10560,26 +13863,33 @@ "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", "dev": true, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://npm.corp.appnexus.com/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "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" } }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true + "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 + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } }, "to-array": { "version": "0.1.4", @@ -10604,12 +13914,18 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -10617,25 +13933,41 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } }, "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 + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } }, "to-through": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true + "dev": true, + "requires": { + "through2": "^2.0.3" + } }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true + "dev": true, + "requires": { + "punycode": "^1.4.1" + } }, "traverse": { "version": "0.3.9", @@ -10683,7 +14015,8 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", - "dev": true + "dev": true, + "optional": true }, "tty-browserify": { "version": "0.0.0", @@ -10692,10 +14025,13 @@ "dev": true }, "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } }, "tweetnacl": { "version": "0.14.5", @@ -10708,7 +14044,10 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } }, "type-detect": { "version": "1.0.0", @@ -10720,7 +14059,11 @@ "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } }, "typedarray": { "version": "0.0.6", @@ -10733,6 +14076,11 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, "dependencies": { "camelcase": { "version": "1.2.1", @@ -10744,7 +14092,12 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } }, "source-map": { "version": "0.5.7", @@ -10768,7 +14121,13 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } } } }, @@ -10783,6 +14142,11 @@ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + }, "dependencies": { "source-map": { "version": "0.5.7", @@ -10792,12 +14156,6 @@ } } }, - "uid-safe": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", - "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", - "dev": true - }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", @@ -10820,31 +14178,58 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + } }, "unified": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "set-value": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } } } }, @@ -10852,13 +14237,20 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } }, "unist-builder": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", - "dev": true + "dev": true, + "requires": { + "object-assign": "^4.1.0" + } }, "unist-util-generated": { "version": "1.1.2", @@ -10876,7 +14268,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", - "dev": true + "dev": true, + "requires": { + "array-iterate": "^1.0.0" + } }, "unist-util-position": { "version": "3.0.1", @@ -10888,7 +14283,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } }, "unist-util-stringify-position": { "version": "1.1.2", @@ -10900,7 +14298,10 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.1.tgz", "integrity": "sha512-0fdB9EQJU0tho5tK0VzOJzAQpPv2LyLZ030b10GxuzAWEfvd54mpY7BMjQ1L69k2YNvL+SvxRzH0yUIehOO8aA==", - "dev": true + "dev": true, + "requires": { + "unist-util-is": "^2.1.1" + } }, "unpipe": { "version": "1.0.0", @@ -10913,18 +14314,30 @@ "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=", "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.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 + "dev": true, + "requires": { + "isarray": "1.0.0" + } } } }, @@ -10941,6 +14354,14 @@ "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", "dev": true, + "requires": { + "binary": ">= 0.3.0 < 1", + "fstream": ">= 0.1.30 < 1", + "match-stream": ">= 0.0.2 < 1", + "pullstream": ">= 0.4.1 < 1", + "readable-stream": "~1.0.31", + "setimmediate": ">= 1.0.1 < 2" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -10952,7 +14373,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -10974,10 +14401,14 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, "dependencies": { "punycode": { "version": "1.3.2", @@ -10992,6 +14423,10 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.1.tgz", "integrity": "sha512-x95Td74QcvICAA0+qERaVkRpTGKyBHHYdwL2LXZm5t/gBtCB9KQSO/0zQgSTYEV1p0WcvSg79TLNPSvd5IDJMQ==", "dev": true, + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + }, "dependencies": { "querystringify": { "version": "2.0.0", @@ -11005,7 +14440,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } }, "url-to-options": { "version": "1.0.1", @@ -11014,9 +14452,9 @@ "dev": true }, "use": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", - "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "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 }, "user-home": { @@ -11030,6 +14468,10 @@ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "dev": true, + "requires": { + "lru-cache": "2.2.x", + "tmp": "0.0.x" + }, "dependencies": { "lru-cache": { "version": "2.2.4", @@ -11043,7 +14485,10 @@ "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true + "dev": true, + "requires": { + "inherits": "2.0.3" + } }, "util-deprecate": { "version": "1.0.2", @@ -11051,15 +14496,15 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true }, "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", "dev": true }, "uws": { @@ -11073,13 +14518,20 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true + "dev": true, + "requires": { + "user-home": "^1.1.1" + } }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "dev": true + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } }, "value-or-function": { "version": "3.0.0", @@ -11087,31 +14539,28 @@ "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, - "vary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", - "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", - "dev": true - }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" } }, "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } }, "vfile-location": { "version": "2.0.3", @@ -11123,13 +14572,23 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz", "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", - "dev": true + "dev": true, + "requires": { + "unist-util-stringify-position": "^1.1.1" + } }, "vfile-reporter": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, + "requires": { + "repeat-string": "^1.5.0", + "string-width": "^1.0.0", + "supports-color": "^4.1.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-statistics": "^1.1.0" + }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -11139,277 +14598,172 @@ }, "supports-color": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true - } - } - }, - "vfile-sort": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.1.tgz", - "integrity": "sha512-+fpTWKkVHwI6VF2xtkDTuCA6cH4UPLAxh+KxfU8g8pC0do5RSZCk1HXTTtMJguW0t5jC0PC19owjUZX9SGQ9tw==", - "dev": true - }, - "vfile-statistics": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.1.tgz", - "integrity": "sha512-dxUM6IYvGChHuwMT3dseyU5BHprNRXzAV0OHx1A769lVGsTiT50kU7BbpRFV+IE6oWmU+PwHdsTKfXhnDIRIgQ==", - "dev": true - }, - "vhost": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", - "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", - "dev": true - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "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 - }, - "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 - }, - "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": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true - }, - "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 - }, - "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 - }, - "walk": { - "version": "2.3.13", - "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.13.tgz", - "integrity": "sha512-78SMe7To9U7kqVhSoGho3GfspA089ZDBIj2f8jElg2hi6lUCoagtDJ8sSMFNlpAh5Ib8Jt1gQ6Y7gh9mzHtFng==", - "dev": true - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true - }, - "webdriverio": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-3.4.0.tgz", - "integrity": "sha1-2dTTwxNm8FPhCvZEsOqtXoc6t7U=", - "dev": true, - "dependencies": { - "ansi-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", - "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", - "dev": true - }, - "asn1": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", - "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", - "dev": true - }, - "assert-plus": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", - "dev": true - }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "aws-sign2": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", - "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", - "dev": true - }, - "boom": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", - "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", - "dev": true - }, - "caseless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", - "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=", - "dev": true - }, - "cli-width": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", - "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", - "dev": true - }, - "combined-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", - "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", - "dev": true - }, - "cryptiles": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", - "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", - "dev": true - }, - "delayed-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", - "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", - "dev": true - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true - }, - "forever-agent": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", - "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", - "dev": true - }, - "form-data": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", - "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true - }, - "hawk": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", - "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", - "dev": true - }, - "hoek": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", - "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", - "dev": true - }, - "http-signature": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", - "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", - "dev": true - }, - "inquirer": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", - "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", - "dev": true - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "mime": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", - "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", - "dev": true - }, - "mime-types": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", - "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", - "dev": true - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true - }, - "oauth-sign": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", - "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=", - "dev": true - }, - "qs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", - "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", - "dev": true - }, - "request": { - "version": "2.49.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.49.0.tgz", - "integrity": "sha1-DU9jSNwzSAWbVT5Ntg/SR43mYqc=", - "dev": true - }, - "sntp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", - "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", - "dev": true - }, - "supports-color": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", - "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, + "vfile-sort": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.1.tgz", + "integrity": "sha512-+fpTWKkVHwI6VF2xtkDTuCA6cH4UPLAxh+KxfU8g8pC0do5RSZCk1HXTTtMJguW0t5jC0PC19owjUZX9SGQ9tw==", + "dev": true + }, + "vfile-statistics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.1.tgz", + "integrity": "sha512-dxUM6IYvGChHuwMT3dseyU5BHprNRXzAV0OHx1A769lVGsTiT50kU7BbpRFV+IE6oWmU+PwHdsTKfXhnDIRIgQ==", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "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" + } + }, + "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" + } + }, + "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" + } + }, + "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" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "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": { + "indexof": "0.0.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 + }, + "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": { + "foreachasync": "^3.0.0" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, "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.0.0", + "acorn-dynamic-import": "^2.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "async": "^2.1.2", + "enhanced-resolve": "^3.4.0", + "escope": "^3.6.0", + "interpret": "^1.0.0", + "json-loader": "^0.5.4", + "json5": "^0.5.1", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "mkdirp": "~0.5.0", + "node-libs-browser": "^2.0.0", + "source-map": "^0.5.3", + "supports-color": "^4.2.1", + "tapable": "^0.2.7", + "uglifyjs-webpack-plugin": "^0.4.6", + "watchpack": "^1.4.0", + "webpack-sources": "^1.0.1", + "yargs": "^8.0.2" + }, "dependencies": { "ajv-keywords": { "version": "3.2.0", - "resolved": "https://npm.corp.appnexus.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", "dev": true }, @@ -11421,9 +14775,12 @@ }, "async": { "version": "2.6.1", - "resolved": "https://npm.corp.appnexus.com/async/-/async-2.6.1.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.10" + } }, "has-flag": { "version": "2.0.0", @@ -11441,19 +14798,31 @@ "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^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=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true + "dev": true, + "requires": { + "pify": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -11465,13 +14834,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } }, "source-map": { "version": "0.5.7", @@ -11483,25 +14861,50 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.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.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } } } }, @@ -11510,6 +14913,10 @@ "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, + "requires": { + "source-list-map": "~0.1.7", + "source-map": "~0.4.1" + }, "dependencies": { "source-list-map": { "version": "0.1.8", @@ -11521,7 +14928,10 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -11530,6 +14940,13 @@ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", "dev": true, + "requires": { + "memory-fs": "~0.4.1", + "mime": "^1.5.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "time-stamp": "^2.0.0" + }, "dependencies": { "time-stamp": { "version": "2.0.0", @@ -11543,13 +14960,26 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", - "dev": true + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } }, "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": { + "gulp-util": "^3.0.7", + "lodash.clone": "^4.3.2", + "lodash.some": "^4.2.2", + "memory-fs": "^0.3.0", + "through": "^2.3.8", + "vinyl": "^1.1.0", + "webpack": "^1.12.9" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -11561,13 +14991,20 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } }, "array-unique": { "version": "0.2.1", @@ -11579,19 +15016,30 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } }, "browserify-aes": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1" + } }, "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 + "dev": true, + "requires": { + "pako": "~0.2.0" + } }, "camelcase": { "version": "1.2.1", @@ -11603,13 +15051,29 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } }, "clone": { "version": "1.0.4", @@ -11627,13 +15091,24 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", - "dev": true + "dev": true, + "requires": { + "browserify-aes": "0.4.0", + "pbkdf2-compat": "2.0.1", + "ripemd160": "0.2.0", + "sha.js": "2.2.6" + } }, "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.1.2", + "memory-fs": "^0.2.0", + "tapable": "^0.1.8" + }, "dependencies": { "memory-fs": { "version": "0.2.0", @@ -11647,19 +15122,50 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "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.1.0" + } }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "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": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.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 + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } }, "has-flag": { "version": "1.0.0", @@ -11689,19 +15195,49 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "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" + } + }, + "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" + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } }, "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 + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } }, "lodash.clone": { "version": "4.5.0", @@ -11713,19 +15249,63 @@ "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 + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } }, "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 + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.1.4", + "buffer": "^4.9.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "0.0.1", + "os-browserify": "^0.2.0", + "path-browserify": "0.0.0", + "process": "^0.11.0", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.0.5", + "stream-browserify": "^2.0.1", + "stream-http": "^2.3.1", + "string_decoder": "^0.10.25", + "timers-browserify": "^2.0.2", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + } }, "os-browserify": { "version": "0.2.1", @@ -11773,7 +15353,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } }, "tapable": { "version": "0.1.10", @@ -11786,6 +15369,12 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, "dependencies": { "async": { "version": "0.2.10", @@ -11795,31 +15384,27 @@ } } }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, "vinyl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } }, "watchpack": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, + "requires": { + "async": "^0.9.0", + "chokidar": "^1.0.0", + "graceful-fs": "^4.1.2" + }, "dependencies": { "async": { "version": "0.9.2", @@ -11833,7 +15418,24 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "dev": true + "dev": true, + "requires": { + "acorn": "^3.0.0", + "async": "^1.3.0", + "clone": "^1.0.2", + "enhanced-resolve": "~0.9.0", + "interpret": "^0.6.4", + "loader-utils": "^0.2.11", + "memory-fs": "~0.3.0", + "mkdirp": "~0.5.0", + "node-libs-browser": "^0.7.0", + "optimist": "~0.6.0", + "supports-color": "^3.1.0", + "tapable": "~0.1.8", + "uglify-js": "~2.7.3", + "watchpack": "^0.2.1", + "webpack-core": "~0.6.9" + } }, "window-size": { "version": "0.1.0", @@ -11851,7 +15453,13 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } } } }, @@ -11859,7 +15467,11 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } }, "websocket-extensions": { "version": "0.1.3", @@ -11867,12 +15479,6 @@ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", "dev": true }, - "wgxpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", - "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", - "dev": true - }, "when": { "version": "3.7.8", "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", @@ -11884,7 +15490,10 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true + "dev": true, + "requires": { + "isexe": "^2.0.0" + } }, "which-module": { "version": "2.0.0", @@ -11915,7 +15524,11 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } }, "wrappy": { "version": "1.0.2", @@ -11927,13 +15540,21 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } }, "x-is-string": { "version": "0.1.0", @@ -11980,45 +15601,16 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", "dev": true - }, - "zip-stream": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", - "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lodash": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", - "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", - "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 - }, - "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 - } - } } } } diff --git a/package.json b/package.json index 1adedf1174f..08ba6e5e3b8 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "babel-preset-env": "^1.6.1", "block-loader": "^2.1.0", "chai": "^3.3.0", - "coveralls": "^2.11.11", + "coveralls": "^3.0.1", "del": "^2.2.0", "documentation": "^5.2.2", "ejs": "^2.5.1", @@ -46,7 +46,7 @@ "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", - "gulp-connect": "5.0.0", + "gulp-connect": "5.5.0", "gulp-documentation": "^3.2.1", "gulp-eslint": "^4.0.0", "gulp-footer": "^1.0.5", @@ -59,7 +59,6 @@ "gulp-shell": "^0.5.2", "gulp-uglify": "^3.0.0", "gulp-util": "^3.0.0", - "gulp-webdriver": "^1.0.1", "ignore-loader": "^0.1.2", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", @@ -88,7 +87,7 @@ "mkpath": "^1.0.0", "mocha": "2.2.5", "mock-fs": "^3.11.0", - "nightwatch": "^0.9.5", + "nightwatch": "^1.0.6", "open": "0.0.5", "proxyquire": "^1.7.10", "querystringify": "0.0.3", From c490107690c0b122249c4012ebc31e536b46eb12 Mon Sep 17 00:00:00 2001 From: John Ellis Date: Thu, 19 Jul 2018 16:53:15 -0400 Subject: [PATCH 0552/1594] Yieldbot adapter use utils.timestamp (#2848) --- modules/yieldbotBidAdapter.js | 16 +++---- test/spec/modules/yieldbotBidAdapter_spec.js | 47 ++++++++++++++++++++ 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/modules/yieldbotBidAdapter.js b/modules/yieldbotBidAdapter.js index 43d94220907..a18448a0b0b 100644 --- a/modules/yieldbotBidAdapter.js +++ b/modules/yieldbotBidAdapter.js @@ -10,7 +10,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; * @private */ export const YieldbotAdapter = { - _adapterLoaded: Date.now(), + _adapterLoaded: utils.timestamp(), _navigationStart: 0, _version: 'pbjs-yb-0.0.1', _bidRequestCount: 0, @@ -205,7 +205,7 @@ export const YieldbotAdapter = { const bidUrl = this.urlPrefix() + yieldbotSlotParams.psn + '/v1/init'; - searchParams['cts_ini'] = Date.now(); + searchParams['cts_ini'] = utils.timestamp(); requests.push({ method: 'GET', url: bidUrl, @@ -325,7 +325,7 @@ export const YieldbotAdapter = { buildAdUrl: function(urlPrefix, publisherNumber, commonSearchParams, bid) { const searchParams = Object.assign({}, commonSearchParams); - searchParams['cts_res'] = Date.now(); + searchParams['cts_res'] = utils.timestamp(); searchParams['slot'] = bid.slot + ':' + bid.size; searchParams['ioa'] = this.intersectionObserverAvailable(window); @@ -369,7 +369,7 @@ export const YieldbotAdapter = { const adUrl = this.buildAdUrl(urlPrefix, publisherNumber, commonSearchParams, bid); const impressionUrl = this.buildImpressionUrl(urlPrefix, publisherNumber, commonSearchParams); - const htmlMarkup = `
`; + const htmlMarkup = `
`; return { ad: htmlMarkup, creativeId: ybotAdRequestId }; }, @@ -410,7 +410,7 @@ export const YieldbotAdapter = { const userId = this.userId; const sessionId = this.sessionId; const pageviewId = this.newId(); - const currentBidTime = Date.now(); + const currentBidTime = utils.timestamp(); const lastBidTime = this.lastPageviewTime; const lastBidId = this.lastPageviewId; this.lastPageviewTime = currentBidTime; @@ -537,7 +537,7 @@ export const YieldbotAdapter = { setCookie: function(name, value, expireMillis, path, domain, secure) { const dataValue = encodeURIComponent(value); const cookieStr = name + '=' + dataValue + - (expireMillis ? ';expires=' + new Date(Date.now() + expireMillis).toGMTString() : '') + + (expireMillis ? ';expires=' + new Date(utils.timestamp() + expireMillis).toGMTString() : '') + (path ? ';path=' + path : '') + (domain ? ';domain=' + domain : '') + (secure ? ';secure' : ''); @@ -567,7 +567,7 @@ export const YieldbotAdapter = { * @private */ newId: function() { - return (+new Date()).toString(36) + 'xxxxxxxxxx' + return (utils.timestamp()).toString(36) + 'xxxxxxxxxx' .replace(/[x]/g, function() { return (0 | Math.random() * 36).toString(36); }); @@ -600,5 +600,5 @@ export const spec = { getUserSyncs: YieldbotAdapter.createDelegate(YieldbotAdapter, YieldbotAdapter.getUserSyncs) }; -YieldbotAdapter._navigationStart = Date.now(); +YieldbotAdapter._navigationStart = utils.timestamp(); registerBidder(spec); diff --git a/test/spec/modules/yieldbotBidAdapter_spec.js b/test/spec/modules/yieldbotBidAdapter_spec.js index 206645acd95..2977e4ef30d 100644 --- a/test/spec/modules/yieldbotBidAdapter_spec.js +++ b/test/spec/modules/yieldbotBidAdapter_spec.js @@ -1323,4 +1323,51 @@ describe('Yieldbot Adapter Unit Tests', function() { done(); }); }); + + describe('Adapter Request Timestamps', function() { + let sandbox; + beforeEach(function() { + sandbox = sinon.sandbox.create(); + sandbox.stub(Date, 'now').callsFake(() => { + return new Date(); + }); + }); + + afterEach(function() { + sandbox.restore(); + }); + + it('should have overridden Date.now() function', function() { + expect(Date.now().getTime()).to.match(/^[0-9]+/); + }); + + it('should be milliseconds past epoch query param values', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.data).to.not.equal(undefined); + + const timestampParams = [ + 'cts_ns', + 'cts_js', + 'cts_ini' + ]; + + timestampParams.forEach((item) => { + expect(!isNaN(request.data[item])).to.equal(true); + expect(request.data[item] > 0).to.equal(true); + expect(request.data[item]).to.match(/^[0-9]+/); + }); + }); + + it('should use (new Date()).getTime() for timestamps in ad markup', function() { + FIXTURE_SERVER_RESPONSE.body.url_prefix = 'http://close.edge.adserver.com/'; + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + + expect(responses[0].ad).to.match(/cts_rend_.*='\+\(new Date\(\)\)\.getTime\(\)/); + expect(responses[0].ad).to.match(/cts_ad='\+\(new Date\(\)\)\.getTime\(\)/); + expect(responses[0].ad).to.match(/cts_imp='\+\(new Date\(\)\)\.getTime\(\)/); + }); + }); }); From b0cda1c401a7645acedf37b6c35038943e611428 Mon Sep 17 00:00:00 2001 From: Casper Date: Fri, 20 Jul 2018 15:45:47 +0200 Subject: [PATCH 0553/1594] New function markWinningBidAsUsed for marking video bids (#2777) * Quick function to mark a video-bid as used * Added tests for the mark function * comments * Changed the function to accept a markBidRequest object to improve security * Changed the markWinningBidAsUsed to take and/or adUnitCode/adId --- src/prebid.js | 27 +++++++++++++ test/spec/unit/pbjs_api_spec.js | 70 ++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/prebid.js b/src/prebid.js index 767180f3286..75e1d117c2a 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -603,6 +603,33 @@ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { .map(removeRequestId); }; +/** + * Mark the winning bid as used, should only be used in conjunction with video + * @typedef {Object} MarkBidRequest + * @property {string} adUnitCode The ad unit code + * @property {string} adId The id representing the ad we want to mark + * + * @alias module:pbjs.markWinningBidAsUsed +*/ +$$PREBID_GLOBAL$$.markWinningBidAsUsed = function (markBidRequest) { + let bids = []; + + if (markBidRequest.adUnitCode && markBidRequest.adId) { + bids = auctionManager.getBidsReceived() + .filter(bid => bid.adId === markBidRequest.adId && bid.adUnitCode === markBidRequest.adUnitCode); + } else if (markBidRequest.adUnitCode) { + bids = targeting.getWinningBids(markBidRequest.adUnitCode); + } else if (markBidRequest.adId) { + bids = auctionManager.getBidsReceived().filter(bid => bid.adId === markBidRequest.adId); + } else { + utils.logWarn('Inproper usage of markWinningBidAsUsed. It\'ll need an adUnitCode and/or adId to function.'); + } + + if (bids.length > 0) { + bids[0].status = RENDERED; + } +}; + /** * Get Prebid config options * @param {Object} options diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 3d403a34ff2..d46a8d740a5 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -9,7 +9,7 @@ import { createBidReceived } from 'test/fixtures/fixtures'; import { auctionManager, newAuctionManager } from 'src/auctionManager'; -import { targeting, newTargeting } from 'src/targeting'; +import { targeting, newTargeting, RENDERED } from 'src/targeting'; import { config as configObj } from 'src/config'; import * as ajaxLib from 'src/ajax'; import * as auctionModule from 'src/auction'; @@ -1838,6 +1838,74 @@ describe('Unit: Prebid Module', function () { }); }); + describe('markWinningBidAsUsed', () => { + it('marks the bid object as used for the given adUnitCode/adId combination', () => { + // make sure the auction has "state" and does not reload the fixtures + const adUnitCode = '/19968336/header-bid-tag-0'; + const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); + auction.getBidsReceived = function() { return bidsReceived.bids }; + + // mark the bid and verify the state has changed to RENDERED + const winningBid = targeting.getWinningBids(adUnitCode)[0]; + $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode, adId: winningBid.adId }); + const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) + .bids + .find(bid => bid.adId === winningBid.adId); + + expect(markedBid.status).to.equal(RENDERED); + resetAuction(); + }); + + it('try and mark the bid object, but fail because we supplied the wrong adId', () => { + const adUnitCode = '/19968336/header-bid-tag-0'; + const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); + auction.getBidsReceived = function() { return bidsReceived.bids }; + + const winningBid = targeting.getWinningBids(adUnitCode)[0]; + $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode, adId: 'miss' }); + const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) + .bids + .find(bid => bid.adId === winningBid.adId); + + expect(markedBid.status).to.not.equal(RENDERED); + resetAuction(); + }); + + it('marks the winning bid object as used for the given adUnitCode', () => { + // make sure the auction has "state" and does not reload the fixtures + const adUnitCode = '/19968336/header-bid-tag-0'; + const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); + auction.getBidsReceived = function() { return bidsReceived.bids }; + + // mark the bid and verify the state has changed to RENDERED + const winningBid = targeting.getWinningBids(adUnitCode)[0]; + $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode }); + const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) + .bids + .find(bid => bid.adId === winningBid.adId); + + expect(markedBid.status).to.equal(RENDERED); + resetAuction(); + }); + + it('marks a bid object as used for the given adId', () => { + // make sure the auction has "state" and does not reload the fixtures + const adUnitCode = '/19968336/header-bid-tag-0'; + const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); + auction.getBidsReceived = function() { return bidsReceived.bids }; + + // mark the bid and verify the state has changed to RENDERED + const winningBid = targeting.getWinningBids(adUnitCode)[0]; + $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adId: winningBid.adId }); + const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) + .bids + .find(bid => bid.adId === winningBid.adId); + + expect(markedBid.status).to.equal(RENDERED); + resetAuction(); + }); + }); + describe('setTargetingForAst', () => { let targeting; let auctionManagerInstance; From a60bf5f489fa9723680050535f6c573fe8a73f5b Mon Sep 17 00:00:00 2001 From: Igor Soarez Date: Fri, 20 Jul 2018 17:40:54 +0100 Subject: [PATCH 0554/1594] quantcast: Update endpoint (#2828) --- modules/quantcastBidAdapter.js | 35 ++++------ test/spec/modules/quantcastBidAdapter_spec.js | 64 ++++++++----------- 2 files changed, 40 insertions(+), 59 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 3639a5a6bb7..e6f4d27bdbb 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -4,11 +4,19 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'quantcast'; const DEFAULT_BID_FLOOR = 0.0000000001; -export const QUANTCAST_CALLBACK_URL = 'global.qc.rtb.quantserve.com'; -export const QUANTCAST_CALLBACK_URL_TEST = 's2s-canary.quantserve.com'; +export const QUANTCAST_DOMAIN = 'qcx.quantserve.com'; +export const QUANTCAST_TEST_DOMAIN = 's2s-canary.quantserve.com'; export const QUANTCAST_NET_REVENUE = true; export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; export const QUANTCAST_TTL = 4; +export const QUANTCAST_PROTOCOL = + window.location.protocol === 'http:' + ? 'http' + : 'https'; +export const QUANTCAST_PORT = + QUANTCAST_PROTOCOL === 'http' + ? '8080' + : '8443'; /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, @@ -51,21 +59,6 @@ export const spec = { const loc = utils.getTopWindowLocation(); const domain = loc.hostname; - let publisherTagURL; - let publisherTagURLTest; - - // Switch the callback URL to Quantcast Canary Endpoint for testing purpose - // `//` is not used because we have different port setting at our end - switch (window.location.protocol) { - case 'https:': - publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`; - publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; - break; - default: - publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8080/qchb`; - publisherTagURLTest = `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`; - } - const bidRequestsList = bids.map(bid => { const bidSizes = []; @@ -104,10 +97,10 @@ export const spec = { const data = JSON.stringify(requestData); - const url = - bid.params.publisherId === QUANTCAST_TEST_PUBLISHER - ? publisherTagURLTest - : publisherTagURL; + const qcDomain = bid.params.publisherId === QUANTCAST_TEST_PUBLISHER + ? QUANTCAST_TEST_DOMAIN + : QUANTCAST_DOMAIN; + const url = `${QUANTCAST_PROTOCOL}://${qcDomain}:${QUANTCAST_PORT}/qchb`; return { data, diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index f6e2924515c..0b3a66efdfb 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,10 +1,13 @@ import * as utils from 'src/utils'; import { expect } from 'chai'; import { - QUANTCAST_CALLBACK_URL_TEST, - QUANTCAST_CALLBACK_URL, + QUANTCAST_DOMAIN, + QUANTCAST_TEST_DOMAIN, QUANTCAST_NET_REVENUE, QUANTCAST_TTL, + QUANTCAST_TEST_PUBLISHER, + QUANTCAST_PROTOCOL, + QUANTCAST_PORT, spec as qcSpec } from '../../../modules/quantcastBidAdapter'; import { newBidder } from '../../../src/adapters/bidderFactory'; @@ -21,7 +24,7 @@ describe('Quantcast adapter', () => { bidderRequestId: '1cc026909c24c8', placementCode: 'div-gpt-ad-1438287399331-0', params: { - publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast + publisherId: QUANTCAST_TEST_PUBLISHER, // REQUIRED - Publisher ID provided by Quantcast battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 }, sizes: [[300, 250]] @@ -53,50 +56,35 @@ describe('Quantcast adapter', () => { }); describe('`buildRequests`', () => { - it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', () => { - const requests = qcSpec.buildRequests([bidRequest]); - + it('selects protocol and port', () => { switch (window.location.protocol) { case 'https:': - expect(requests[0]['url']).to.equal( - `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb` - ); + expect(QUANTCAST_PROTOCOL).to.equal('https'); + expect(QUANTCAST_PORT).to.equal('8443'); break; default: - expect(requests[0]['url']).to.equal( - `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb` - ); + expect(QUANTCAST_PROTOCOL).to.equal('http'); + expect(QUANTCAST_PORT).to.equal('8080'); break; } }); - it('sends bid requests to Quantcast Global Endpoint for regular `publisherId`', () => { - const bidRequest = { - bidder: 'quantcast', - bidId: '2f7b179d443f14', - auctionId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', - bidderRequestId: '1cc026909c24c8', - placementCode: 'div-gpt-ad-1438287399331-0', - params: { - publisherId: 'regular-publisher', // REQUIRED - Publisher ID provided by Quantcast - battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 - }, - sizes: [[300, 250]] - }; + it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', () => { const requests = qcSpec.buildRequests([bidRequest]); + const url = new URL(requests[0]['url']); + expect(url.hostname).to.equal(QUANTCAST_TEST_DOMAIN); + }); - switch (window.location.protocol) { - case 'https:': - expect(requests[0]['url']).to.equal( - `https://${QUANTCAST_CALLBACK_URL}:8443/qchb` - ); - break; - default: - expect(requests[0]['url']).to.equal( - `http://${QUANTCAST_CALLBACK_URL}:8080/qchb` - ); - break; - } + it('sends bid requests to default endpoint for non standard publisher IDs', () => { + const modifiedBidRequest = Object.assign({}, bidRequest, { + params: Object.assign({}, bidRequest.params, { + publisherId: 'foo-bar', + }), + }); + const requests = qcSpec.buildRequests([modifiedBidRequest]); + expect(requests[0]['url']).to.equal( + `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb` + ); }); it('sends bid requests to Quantcast Header Bidding Endpoints via POST', () => { @@ -112,7 +100,7 @@ describe('Quantcast adapter', () => { const requests = qcSpec.buildRequests([bidRequest]); const expectedBidRequest = { - publisherId: 'test-publisher', + publisherId: QUANTCAST_TEST_PUBLISHER, requestId: '2f7b179d443f14', imp: [ { From ff816aa17407602a8619c1543ebbdf74810708ed Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 20 Jul 2018 11:10:37 -0600 Subject: [PATCH 0555/1594] make sure default storage check is in try catch (#2841) --- src/debugging.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/debugging.js b/src/debugging.js index fe5c269a18d..0d08bea4b03 100644 --- a/src/debugging.js +++ b/src/debugging.js @@ -77,9 +77,10 @@ export function getConfig(debugging) { } config.getConfig('debugging', ({debugging}) => getConfig(debugging)); -export function sessionLoader(storage = window.sessionStorage) { +export function sessionLoader(storage) { let overrides; try { + storage = storage || window.sessionStorage; overrides = JSON.parse(storage.getItem(OVERRIDE_KEY)); } catch (e) { } From 36cadef2f6d7dc97e2119ee96f42efc36a733c80 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Fri, 20 Jul 2018 13:21:51 -0400 Subject: [PATCH 0556/1594] Disable ajax timeout (#2864) * disable timeout * add config to disable timeout --- src/ajax.js | 16 ++++++++++++---- src/config.js | 9 +++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/ajax.js b/src/ajax.js index e17f782ac30..1916f4ea080 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -1,4 +1,5 @@ import {parse as parseURL, format as formatURL} from './url'; +import { config } from 'src/config'; var utils = require('./utils'); @@ -51,9 +52,13 @@ export function ajaxBuilder(timeout = 3000, {request, done} = {}) { } } }; - x.ontimeout = function () { - utils.logError(' xhr timeout after ', x.timeout, 'ms'); - }; + + // Disabled timeout temporarily to avoid xhr failed requests. https://github.com/prebid/Prebid.js/issues/2648 + if (!config.getConfig('disableAjaxTimeout')) { + x.ontimeout = function () { + utils.logError(' xhr timeout after ', x.timeout, 'ms'); + }; + } if (method === 'GET' && data) { let urlInfo = parseURL(url, options); @@ -63,7 +68,10 @@ export function ajaxBuilder(timeout = 3000, {request, done} = {}) { x.open(method, url); // IE needs timoeut to be set after open - see #1410 - x.timeout = timeout; + // Disabled timeout temporarily to avoid xhr failed requests. https://github.com/prebid/Prebid.js/issues/2648 + if (!config.getConfig('disableAjaxTimeout')) { + x.timeout = timeout; + } if (options.withCredentials) { x.withCredentials = true; diff --git a/src/config.js b/src/config.js index c4be2cd552b..f8d8195409b 100644 --- a/src/config.js +++ b/src/config.js @@ -18,6 +18,7 @@ const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_COOKIESYNC_DELAY = 100; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; +const DEFAULT_DISABLE_AJAX_TIMEOUT = false; const DEFAULT_TIMEOUTBUFFER = 200; @@ -163,6 +164,14 @@ export function newConfig() { this._timoutBuffer = val; }, + _disableAjaxTimeout: DEFAULT_DISABLE_AJAX_TIMEOUT, + get disableAjaxTimeout() { + return this._disableAjaxTimeout; + }, + set disableAjaxTimeout(val) { + this._disableAjaxTimeout = val; + }, + }; function hasGranularity(val) { From 1b41bcefc5fa34f5276e46b920d745a466270496 Mon Sep 17 00:00:00 2001 From: Brittany Zellman <33695402+brittanyzellman@users.noreply.github.com> Date: Fri, 20 Jul 2018 15:10:58 -0400 Subject: [PATCH 0557/1594] validated size array and added tests (#2870) --- modules/tripleliftBidAdapter.js | 20 ++++++------------- .../spec/modules/tripleliftBidAdapter_spec.js | 8 +++++++- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 625b5e253f5..795c75ef9bc 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -22,7 +22,6 @@ export const tripleliftAdapterSpec = { tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); - // tlCall = utils.tryAppendQueryString(tlCall, 'fe', _isFlashEnabled().toString()); tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer); if (bidderRequest && bidderRequest.timeout) { @@ -93,7 +92,8 @@ function _buildPostBody(bidRequests) { } function _sizes(sizeArray) { - return sizeArray.map(function(size) { + let sizes = sizeArray.filter(_isValidSize); + return sizes.map(function(size) { return { w: size[0], h: size[1] @@ -101,6 +101,10 @@ function _sizes(sizeArray) { }); } +function _isValidSize(size) { + return (size.length === 2 && typeof size[0] === 'number' && typeof size[1] === 'number'); +} + function _buildResponseObject(bidderRequest, bid) { let bidResponse = {}; let width = bid.width || 1; @@ -125,16 +129,4 @@ function _buildResponseObject(bidderRequest, bid) { return bidResponse; } -// function _isFlashEnabled() { -// let flash; -// try { -// flash = Boolean(new ActiveXObject('ShockwaveFlash.ShockwaveFlash')); -// } catch (e) { -// flash = navigator.mimeTypes && -// navigator.mimeTypes['application/x-shockwave-flash'] !== undefined && -// navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin ? 1 : 0 -// } -// return flash ? 1 : 0; -// } - registerBidder(tripleliftAdapterSpec); diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index c7c023ed726..ed343f1ebf9 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -61,7 +61,7 @@ describe('triplelift adapter', () => { floor: 1.0, }, adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 600]], + sizes: [[300, 250], [300, 600], [1, 1, 1], ['flex']], bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', @@ -73,6 +73,12 @@ describe('triplelift adapter', () => { expect(request).to.exist.and.to.be.a('object'); }); + it('should only parse sizes that are of the proper length and format', () => { + const request = tripleliftAdapterSpec.buildRequests(bidRequests); + expect(request.data.imp[0].banner.format).to.have.length(2); + expect(request.data.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + }); + it('should be a post request and populate the payload', () => { const request = tripleliftAdapterSpec.buildRequests(bidRequests); const payload = request.data; From 8f4fc0747867aba63513f766c1fe6b12d6bfe817 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 23 Jul 2018 10:29:19 -0400 Subject: [PATCH 0558/1594] fix failing unit test within quantcastBidAdapter (#2879) * fix failing unit test for quantcastBidAdapter * rename variable to be clearer * using alternate approach --- test/spec/modules/quantcastBidAdapter_spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 0b3a66efdfb..b6fc3f27f94 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -11,6 +11,7 @@ import { spec as qcSpec } from '../../../modules/quantcastBidAdapter'; import { newBidder } from '../../../src/adapters/bidderFactory'; +import { parse } from 'src/url'; describe('Quantcast adapter', () => { const quantcastAdapter = newBidder(qcSpec); @@ -71,7 +72,7 @@ describe('Quantcast adapter', () => { it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', () => { const requests = qcSpec.buildRequests([bidRequest]); - const url = new URL(requests[0]['url']); + const url = parse(requests[0]['url']); expect(url.hostname).to.equal(QUANTCAST_TEST_DOMAIN); }); From f5170d9d173b0c11a431fa172e26e565273a409a Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 23 Jul 2018 08:38:11 -0600 Subject: [PATCH 0559/1594] don't allow null or undefined bid properties (#2865) --- src/adapters/bidderFactory.js | 2 +- test/spec/unit/core/bidderFactory_spec.js | 30 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index d8b55f94f9c..8e359d98259 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -381,7 +381,7 @@ function validBidSize(adUnitCode, bid, bidRequests) { export function isValid(adUnitCode, bid, bidRequests) { function hasValidKeys() { let bidKeys = Object.keys(bid); - return COMMON_BID_RESPONSE_KEYS.every(key => includes(bidKeys, key)); + return COMMON_BID_RESPONSE_KEYS.every(key => includes(bidKeys, key) && !includes([undefined, null], bid[key])); } function errorMessage(msg) { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index ca2a9afc103..d1422cb1496 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -427,6 +427,36 @@ describe('bidders created by newBidder', () => { expect(logErrorSpy.calledOnce).to.equal(true); }); + + it('should logError when required bid response params are undefined', () => { + const bidder = newBidder(spec); + + const bid = { + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'requestId': '1', + 'creativeId': 'some-id', + 'currency': undefined, + '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); + + expect(logErrorSpy.calledOnce).to.equal(true); + }); }); describe('when the ajax call fails', () => { From 8eedfc3ce90b678c3c05869019567e371154da72 Mon Sep 17 00:00:00 2001 From: skazedo Date: Mon, 23 Jul 2018 17:02:19 -0400 Subject: [PATCH 0560/1594] New Adapter ZEDO (#2872) * initial commit * updated contact and tag details * changes ti support the renderers * changes to pass dimId * fixed names of internal mapping * added comment * added gdpr param to request and other fixes --- integrationExamples/gpt/pbjs_example_gpt.html | 7 + modules/zedoBidAdapter.js | 205 ++++++++++++++ modules/zedoBidAdapter.md | 30 ++ test/spec/modules/zedoBidAdapter_spec.js | 268 ++++++++++++++++++ 4 files changed, 510 insertions(+) create mode 100644 modules/zedoBidAdapter.js create mode 100644 modules/zedoBidAdapter.md create mode 100644 test/spec/modules/zedoBidAdapter_spec.js diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index e54a604e281..fbf21f1f856 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -288,6 +288,13 @@ pubId: 50357, //REQUIRED host: 'dsp-staging.adkernel.com' //OPTIONAL } + }, + { + bidder: 'zedo', + params: { + channelCode: 2264002816, //REQUIRED + dimId: 9 //REQUIRED + } } ] }, { diff --git a/modules/zedoBidAdapter.js b/modules/zedoBidAdapter.js new file mode 100644 index 00000000000..0420c479ae9 --- /dev/null +++ b/modules/zedoBidAdapter.js @@ -0,0 +1,205 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; + +const BIDDER_CODE = 'zedo'; +const URL = '//z2.zedo.com/asw/fmb.json'; +const SECURE_URL = '//z2.zedo.com/asw/fmb.json'; +const DIM_TYPE = { + '7': 'display', + '9': 'display', + '14': 'display', + '70': 'SBR', + '83': 'CurtainRaiser', + '85': 'Inarticle', + '86': 'pswipeup', + '88': 'Inview', + // '85': 'pre-mid-post-roll', +}; + +export const spec = { + code: BIDDER_CODE, + aliases: [], + 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) { + return !!(bid.params && bid.params.channelCode && bid.params.dimId); + }, + + /** + * 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) { + let data = { + placements: [] + }; + bidRequests.map(bidRequest => { + let channelCode = parseInt(bidRequest.params.channelCode); + let network = parseInt(channelCode / 1000000); + let channel = channelCode % 1000000; + let dim = getSizes(bidRequest.sizes); + let placement = { + id: bidRequest.bidId, + network: network, + channel: channel, + width: dim[0], + height: dim[1], + dimension: bidRequest.params.dimId, + version: '$prebid.version$', + keyword: '', + transactionId: bidRequest.transactionId + } + if (bidderRequest && bidderRequest.gdprConsent) { + if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { + data.gdpr = Number(bidderRequest.gdprConsent.gdprApplies); + } + data.gdpr_consent = bidderRequest.gdprConsent.consentString; + } + let dimType = DIM_TYPE[String(bidRequest.params.dimId)] + if (dimType) { + placement['renderers'] = [{ + 'name': dimType + }] + } else { // default to display + placement['renderers'] = [{ + 'name': 'display' + }] + } + data['placements'].push(placement); + }); + let reqUrl = utils.getTopWindowLocation().protocol === 'http:' ? URL : SECURE_URL; + return { + method: 'GET', + url: reqUrl, + data: 'g=' + JSON.stringify(data) + } + }, + + /** + * 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) { + serverResponse = serverResponse.body; + const bids = []; + if (!serverResponse || serverResponse.error) { + let errorMessage = `in response for ${request.bidderCode} adapter`; + if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } + utils.logError(errorMessage); + return bids; + } + + if (serverResponse.ad) { + serverResponse.ad.forEach(ad => { + const creativeBid = getCreative(ad); + if (creativeBid) { + if (parseInt(creativeBid.cpm) !== 0) { + const bid = newBid(ad, creativeBid, request); + bid.mediaType = parseMediaType(creativeBid); + bids.push(bid); + } + } + }); + } + return bids; + }, + + getUserSyncs: function (syncOptions, responses, gdprConsent) { + if (syncOptions.iframeEnabled) { + let url = utils.getTopWindowLocation().protocol === 'http:' ? 'http://d3.zedo.com/rs/us/fcs.html' : 'https://tt3.zedo.com/rs/us/fcs.html'; + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + // add 'gdpr' only if 'gdprApplies' is defined + if (typeof gdprConsent.gdprApplies === 'boolean') { + url += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + url += `?gdpr_consent=${gdprConsent.consentString}`; + } + } + return [{ + type: 'iframe', + url: url + }]; + } + } +}; + +function getCreative(ad) { + return ad && ad.creatives && ad.creatives.length && find(ad.creatives, creative => creative.adId); +} +/** + * Unpack the Server's Bid into a Prebid-compatible one. + * @param serverBid + * @param rtbBid + * @param bidderRequest + * @return Bid + */ +function newBid(serverBid, creativeBid, bidderRequest) { + const bid = { + requestId: serverBid.slotId, + creativeId: creativeBid.adId, + dealId: 99999999, + currency: 'USD', + netRevenue: true, + ttl: 300 + }; + + if (creativeBid.creativeDetails.type === 'VAST') { + Object.assign(bid, { + width: creativeBid.width, + height: creativeBid.height, + vastXml: creativeBid.creativeDetails.adContent, + cpm: (parseInt(creativeBid.cpm) * 0.65) / 1000000, + ttl: 3600 + }); + } else { + Object.assign(bid, { + width: creativeBid.width, + height: creativeBid.height, + cpm: (parseInt(creativeBid.cpm) * 0.6) / 1000000, + ad: creativeBid.creativeDetails.adContent + }); + } + + return bid; +} +/* Turn bid request sizes into compatible format */ +function getSizes(requestSizes) { + let width = 0; + let height = 0; + if (utils.isArray(requestSizes) && requestSizes.length === 2 && + !utils.isArray(requestSizes[0])) { + width = parseInt(requestSizes[0], 10); + height = parseInt(requestSizes[1], 10); + } else if (typeof requestSizes === 'object') { + for (let i = 0; i < requestSizes.length; i++) { + let size = requestSizes[i]; + width = parseInt(size[0], 10); + height = parseInt(size[1], 10); + break; + } + } + return [width, height]; +} + +function parseMediaType(creativeBid) { + const adType = creativeBid.creativeDetails.type; + if (adType === 'VAST') { + return VIDEO; + } else { + return BANNER; + } +} + +registerBidder(spec); diff --git a/modules/zedoBidAdapter.md b/modules/zedoBidAdapter.md new file mode 100644 index 00000000000..9ffcd61f164 --- /dev/null +++ b/modules/zedoBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +Module Name: ZEDO Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebidsupport@zedo.com + +# Description + +Module that connects to ZEDO's demand sources. + +For video integration, ZEDO 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 + +# Test Parameters +``` + var adUnits = [ + { + code: 'banner-ad-div', + sizes: [[300, 250], [728, 90]], + bids: [ + { + bidder: 'zedo', + params: { + code: 2264004118 + dimId: 9 + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js new file mode 100644 index 00000000000..6d0ab7c68f6 --- /dev/null +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -0,0 +1,268 @@ +import { expect } from 'chai'; +import { spec } from 'modules/zedoBidAdapter'; + +describe('The ZEDO bidding adapter', () => { + describe('isBidRequestValid', () => { + it('should return false when given an invalid bid', () => { + const bid = { + bidder: 'zedo', + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + + it('should return true when given a channelcode bid', () => { + const bid = { + bidder: 'zedo', + params: { + channelCode: 20000000, + dimId: 9 + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + }); + + describe('buildRequests', () => { + const bidderRequest = { + timeout: 3000, + }; + + it('should properly build a channelCode request for dim Id with type not defined', () => { + const bidRequests = [ + { + bidder: 'zedo', + adUnitCode: 'p12345', + transactionId: '12345667', + sizes: [[300, 200]], + params: { + channelCode: 20000000, + dimId: 10 + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmb.json/); + expect(request.method).to.equal('GET'); + const zedoRequest = request.data; + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}]}'); + }); + + it('should properly build a channelCode request for video with type defined', () => { + const bidRequests = [ + { + bidder: 'zedo', + adUnitCode: 'p12345', + transactionId: '12345667', + sizes: [640, 480], + mediaTypes: { + video: { + context: 'instream', + }, + }, + params: { + channelCode: 20000000, + dimId: 85 + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmb.json/); + expect(request.method).to.equal('GET'); + const zedoRequest = request.data; + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":640,"height":480,"dimension":85,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"Inarticle"}]}]}'); + }); + + describe('buildGDPRRequests', () => { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + const bidderRequest = { + timeout: 3000, + gdprConsent: { + 'consentString': consentString, + 'gdprApplies': true + } + }; + + it('should properly build request with gdpr consent', () => { + const bidRequests = [ + { + bidder: 'zedo', + adUnitCode: 'p12345', + transactionId: '12345667', + sizes: [[300, 200]], + params: { + channelCode: 20000000, + dimId: 10 + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.method).to.equal('GET'); + const zedoRequest = request.data; + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}],"gdpr":1,"gdpr_consent":"BOJ8RZsOJ8RZsABAB8AAAAAZ+A=="}'); + }); + }); + }); + describe('interpretResponse', () => { + it('should return an empty array when there is bid response', () => { + const response = {}; + const request = { bidRequests: [] }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(0); + }); + + it('should properly parse a bid response with no valid creative', () => { + const response = { + body: { + ad: [ + { + 'slotId': 'ad1d762', + 'network': '2000', + 'creatives': [ + { + 'adId': '12345', + 'height': '600', + 'width': '160', + 'isFoc': true, + 'creativeDetails': { + 'type': 'StdBanner', + 'adContent': { + 'focImage': { + 'url': 'https://c13.zedo.com/OzoDB/0/0/0/blank.gif', + 'target': '_blank', + } + } + }, + 'cpm': '0' + } + ] + } + ] + } + }; + const request = { + bidRequests: [{ + bidder: 'zedo', + adUnitCode: 'p12345', + bidId: 'test-bidId', + params: { + channelCode: 2000000, + dimId: 9 + } + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(0); + }); + + it('should properly parse a bid response with valid display creative', () => { + const response = { + body: { + ad: [ + { + 'slotId': 'ad1d762', + 'network': '2000', + 'creatives': [ + { + 'adId': '12345', + 'height': '600', + 'width': '160', + 'isFoc': true, + 'creativeDetails': { + 'type': 'StdBanner', + 'adContent': '' + }, + 'cpm': '1200000' + } + ] + } + ] + } + }; + const request = { + bidRequests: [{ + bidder: 'zedo', + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + channelCode: 2000000, + dimId: 9 + }, + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('ad1d762'); + expect(bids[0].cpm).to.equal(0.72); + expect(bids[0].width).to.equal('160'); + expect(bids[0].height).to.equal('600'); + }); + + it('should properly parse a bid response with valid video creative', () => { + const response = { + body: { + ad: [ + { + 'slotId': 'ad1d762', + 'network': '2000', + 'creatives': [ + { + 'adId': '12345', + 'height': '480', + 'width': '640', + 'isFoc': true, + 'creativeDetails': { + 'type': 'VAST', + 'adContent': '' + }, + 'cpm': '1200000' + } + ] + } + ] + } + }; + const request = { + bidRequests: [{ + bidder: 'zedo', + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + channelCode: 2000000, + dimId: 85 + }, + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('ad1d762'); + expect(bids[0].cpm).to.equal(0.78); + expect(bids[0].width).to.equal('640'); + expect(bids[0].height).to.equal('480'); + expect(bids[0].vastXml).to.not.equal(''); + expect(bids[0].ad).to.be.an('undefined'); + }); + }); + + describe('user sync', () => { + it('should register the iframe sync url', () => { + let syncs = spec.getUserSyncs({ + iframeEnabled: true + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('iframe'); + }); + + it('should pass gdpr params', () => { + let syncs = spec.getUserSyncs({ iframeEnabled: true }, {}, { + gdprApplies: false, consentString: 'test' + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.contains('gdpr=0'); + }); + }); +}); From 8d0213162c471e4fb59405db954a45967f2d24ac Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Mon, 23 Jul 2018 22:32:35 -0700 Subject: [PATCH 0561/1594] OpenX Adapter: Added support for Do Not Track & COPPA (#2838) Renamed divs query param to divIds Removed placementId Updated Documentation --- modules/openxBidAdapter.js | 18 +- modules/openxBidAdapter.md | 114 ++++++---- test/spec/modules/openxBidAdapter_spec.js | 252 +++++++++++++++------- 3 files changed, 258 insertions(+), 126 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index ba3bc98b766..cd5bcef36ad 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.2'; +const BIDDER_VERSION = '2.1.3'; let shouldSendBoPixel = true; @@ -20,8 +20,8 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { - if (bidRequest.mediaTypes && bidRequest.mediaTypes.banner) { - return !!((bidRequest.params.unit || bidRequest.params.placementId) && bidRequest.params.delDomain); + if (utils.deepAccess(bidRequest, 'mediaTypes.banner') && bidRequest.params.delDomain) { + return !!bidRequest.params.unit || utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes.length') > 0; } return !!(bidRequest.params.unit && bidRequest.params.delDomain); @@ -223,16 +223,20 @@ function buildOXBannerRequest(bids, bidderRequest) { let hasCustomParam = false; let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); let auids = utils._map(bids, bid => bid.params.unit); - let pids = utils._map(bids, bid => bid.params.placementId); queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); queryParams.bc = bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`; - queryParams.divs = utils._map(bids, bid => bid.adUnitCode).join(','); + queryParams.divIds = utils._map(bids, bid => encodeURIComponent(bid.adUnitCode)).join(','); if (auids.some(auid => auid)) { queryParams.auid = auids.join(','); } - if (pids.some(pid => pid)) { - queryParams.pids = pids.join(','); + + if (bids.some(bid => bid.params.doNotTrack)) { + queryParams.ns = 1; + } + + if (bids.some(bid => bid.params.coppa)) { + queryParams.tfcd = 1; } bids.forEach(function (bid) { diff --git a/modules/openxBidAdapter.md b/modules/openxBidAdapter.md index a7a39a8412e..243b2e53104 100644 --- a/modules/openxBidAdapter.md +++ b/modules/openxBidAdapter.md @@ -10,46 +10,88 @@ Maintainer: team-openx@openx.com Module that connects to OpenX's demand sources -# Test Parameters -``` - var adUnits = [ - { - code: 'test-div', - sizes: [[728, 90]], // a display size - mediaTypes: {'banner': {}}, - bids: [ - { - bidder: 'openx', - params: { - placementId: '/123/abcdefg' - unit: '539439964', - delDomain: 'se-demo-d.openx.net' - } - } - ] - }, - { - code: 'video1', - sizes: [[640,480]], - mediaTypes: {'video': {}}, - bids: [ - { - bidder: 'openx', - params: { - unit: '539131525', - delDomain: 'zdo.com', - video: { - url: 'abc.com' - } - } - } - ] +# Bid Parameters +## Banner + +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `delDomain` | required | String | OpenX delivery domain provided by your OpenX representative. | "PUBLISHER-d.openx.net" +| `unit` | required | String | OpenX ad unit ID provided by your OpenX representative. | "1611023122" +| `customParams` | optional | Object | User-defined targeting key-value pairs. customParams applies to a specific unit. | `{key1: "v1", key2: ["v2","v3"]}` +| `customFloor` | optional | Number | Minimum price in USD. customFloor applies to a specific unit. For example, use the following value to set a $1.50 floor: 1.50

**WARNING:**
Misuse of this parameter can impact revenue | 1.50 +| `doNotTrack` | optional | Boolean | Prevents advertiser from using data for this user.

**WARNING:**
Request-level setting. May impact revenue. | true +| `coppa` | optional | Boolean | Enables Child's Online Privacy Protection Act (COPPA) regulations. | true + +## Video + +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `unit` | required | String | OpenX ad unit ID provided by your OpenX representative. | "1611023122" +| `delDomain` | required | String | OpenX delivery domain provided by your OpenX representative. | "PUBLISHER-d.openx.net" +| `openrtb` | optional | OpenRTB Impression | An OpenRtb Impression with Video subtype properties | `{ imp: [{ video: {mimes: ['video/x-ms-wmv, video/mp4']} }] }` + + +# Example +```javascript +var adUnits = [ + { + code: 'test-div', + sizes: [[728, 90]], // a display size + mediaTypes: {'banner': {}}, + bids: [ + { + bidder: 'openx', + params: { + unit: '539439964', + delDomain: 'se-demo-d.openx.net', + customParams: { + key1: 'v1', + key2: ['v2', 'v3'] + }, + } + } + ] + }, + { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'openx', + params: { + unit: '1611023124', + delDomain: 'PUBLISHER-d.openx.net', + openrtb: { + imp: [{ + video: { + mimes: ['video/x-ms-wmv, video/mp4'] + } + }] } - ]; + } + }] + } +]; ``` +# Configuration +Add the following code to enable user syncing. By default, Prebid.js version 0.34.0+ turns off user syncing through iframes. +OpenX strongly recommends enabling user syncing through iframes. This functionality improves DSP user match rates and increases the +OpenX bid rate and bid price. Be sure to call `pbjs.setConfig()` only once. + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true + } +}); +``` -# Links +# Additional Details [Banner Ads](https://docs.openx.com/Content/developers/containers/prebid-adapter.html) [Video Ads](https://docs.openx.com/Content/developers/containers/prebid-video-adapter.html) diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 7f9cac405c3..c0588f2eff0 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -153,7 +153,7 @@ describe('OpenxAdapter', () => { bannerBid.params = {delDomain: 'test-delivery-domain'} }); - it('should return false when there is no ad unit id and no placement id', () => { + it('should return false when there is no ad unit id and size', () => { expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); @@ -162,10 +162,19 @@ describe('OpenxAdapter', () => { expect(spec.isBidRequestValid(bannerBid)).to.equal(true); }); - it('should return true if there is an placement id ', () => { - bannerBid.params.placementId = '/12345678/aaaa/bbbb'; + it('should return true if there is no adunit id and sizes are defined', () => { + bannerBid.mediaTypes.banner.sizes = [720, 90]; expect(spec.isBidRequestValid(bannerBid)).to.equal(true); }); + + it('should return false if no sizes are defined ', () => { + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); + }); + + it('should return false if sizes empty ', () => { + bannerBid.mediaTypes.banner.sizes = []; + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); + }); }); }); @@ -245,7 +254,7 @@ describe('OpenxAdapter', () => { 'unit': '11', 'delDomain': 'test-del-domain' }, - 'adUnitCode': 'adunit-code', + 'adUnitCode': '/adunit-code/test-path', mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] @@ -285,11 +294,11 @@ describe('OpenxAdapter', () => { it('should send the adunit codes', () => { const request = spec.buildRequests(bidRequestsWithMediaTypes); - expect(request[0].data.divs).to.equal(`${bidRequestsWithMediaTypes[0].adUnitCode},${bidRequestsWithMediaTypes[1].adUnitCode}`); + expect(request[0].data.divIds).to.equal(`${encodeURIComponent(bidRequestsWithMediaTypes[0].adUnitCode)},${encodeURIComponent(bidRequestsWithMediaTypes[1].adUnitCode)}`); }); it('should send ad unit ids when any are defined', () => { - const bidRequestsWithPlacementIds = [{ + const bidRequestsWithUnitIds = [{ 'bidder': 'openx', 'params': { 'delDomain': 'test-del-domain' @@ -319,12 +328,12 @@ describe('OpenxAdapter', () => { 'bidderRequestId': 'test-bid-request-2', 'auctionId': 'test-auction-2' }]; - const request = spec.buildRequests(bidRequestsWithPlacementIds); - expect(request[0].data.auid).to.equal(`,${bidRequestsWithPlacementIds[1].params.unit}`); + const request = spec.buildRequests(bidRequestsWithUnitIds); + expect(request[0].data.auid).to.equal(`,${bidRequestsWithUnitIds[1].params.unit}`); }); it('should not send any ad unit ids when none are defined', () => { - const bidRequestsWithoutPlacementIds = [{ + const bidRequestsWithoutUnitIds = [{ 'bidder': 'openx', 'params': { 'delDomain': 'test-del-domain' @@ -353,83 +362,10 @@ describe('OpenxAdapter', () => { 'bidderRequestId': 'test-bid-request-2', 'auctionId': 'test-auction-2' }]; - const request = spec.buildRequests(bidRequestsWithoutPlacementIds); + const request = spec.buildRequests(bidRequestsWithoutUnitIds); expect(request[0].data).to.not.have.any.keys('auid'); }); - it('should send placement ids when any are defined', () => { - const bidRequestsWithPlacementIds = [{ - 'bidder': 'openx', - 'params': { - 'unit': '11', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - 'bidId': 'test-bid-id-1', - 'bidderRequestId': 'test-bid-request-1', - 'auctionId': 'test-auction-1' - }, { - 'bidder': 'openx', - 'params': { - 'unit': '22', - 'delDomain': 'test-del-domain', - placementId: 'test-placement-id-2' - }, - 'adUnitCode': 'adunit-code', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - 'bidId': 'test-bid-id-2', - 'bidderRequestId': 'test-bid-request-2', - 'auctionId': 'test-auction-2' - }]; - const request = spec.buildRequests(bidRequestsWithPlacementIds); - expect(request[0].data.pids).to.equal(`,${bidRequestsWithPlacementIds[1].params.placementId}`); - }); - - it('should not send any placement ids when none are defined', () => { - const bidRequestsWithoutPlacementIds = [{ - 'bidder': 'openx', - 'params': { - 'unit': '11', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - 'bidId': 'test-bid-id-1', - 'bidderRequestId': 'test-bid-request-1', - 'auctionId': 'test-auction-1' - }, { - 'bidder': 'openx', - 'params': { - 'unit': '22', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - 'bidId': 'test-bid-id-2', - 'bidderRequestId': 'test-bid-request-2', - 'auctionId': 'test-auction-2' - }]; - const request = spec.buildRequests(bidRequestsWithoutPlacementIds); - expect(request[0].data).to.not.have.any.keys('pids'); - }); - describe('when there is a legacy request with no media type', function () { const deprecatedBidRequestsFormatWithNoMediaType = [{ 'bidder': 'openx', @@ -695,6 +631,156 @@ describe('OpenxAdapter', () => { }); }); }); + + it('should not send a coppa query param when there are no coppa param settings in the bid requests', () => { + const bidRequestsWithoutCoppa = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain', + coppa: false + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }, { + bidder: 'openx', + params: { + unit: '22', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bidId: 'test-bid-id-2', + bidderRequestId: 'test-bid-request-2', + auctionId: 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutCoppa); + expect(request[0].data).to.not.have.any.keys('tfcd'); + }); + + it('should send a coppa flag there is when there is coppa param settings in the bid requests', () => { + const bidRequestsWithCoppa = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain', + coppa: false + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }, { + bidder: 'openx', + params: { + unit: '22', + delDomain: 'test-del-domain', + coppa: true + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bidId: 'test-bid-id-2', + bidderRequestId: 'test-bid-request-2', + auctionId: 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithCoppa); + expect(request[0].data.tfcd).to.equal(1); + }); + + it('should not send a "no segmentation" flag there no DoNotTrack setting that is set to true', () => { + const bidRequestsWithoutDnt = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain', + doNotTrack: false + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }, { + bidder: 'openx', + params: { + unit: '22', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bidId: 'test-bid-id-2', + bidderRequestId: 'test-bid-request-2', + auctionId: 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutDnt); + expect(request[0].data).to.not.have.any.keys('ns'); + }); + + it('should send a "no segmentation" flag there is any DoNotTrack setting that is set to true', () => { + const bidRequestsWithDnt = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain', + doNotTrack: false + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }, { + bidder: 'openx', + params: { + unit: '22', + delDomain: 'test-del-domain', + doNotTrack: true + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bidId: 'test-bid-id-2', + bidderRequestId: 'test-bid-request-2', + auctionId: 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithDnt); + expect(request[0].data.ns).to.equal(1); + }); }); describe('buildRequests for video', () => { From 2fd552a9e0f0042db427148e6b29c8d30e9069c6 Mon Sep 17 00:00:00 2001 From: Denis Logachev Date: Tue, 24 Jul 2018 08:38:02 +0300 Subject: [PATCH 0562/1594] Meta keyword collection feature (#2866) --- modules/adkernelAdnBidAdapter.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index 16b2efce901..c66d2b68b40 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -55,15 +55,10 @@ function canonicalizeSizesArray(sizes) { } function buildRequestParams(tags, auctionId, transactionId, gdprConsent) { - let loc = utils.getTopWindowLocation(); let req = { id: auctionId, tid: transactionId, - site: { - page: loc.href, - ref: utils.getTopWindowReferrer(), - secure: ~~(loc.protocol === 'https:') - }, + site: buildSite(), imp: tags }; @@ -79,6 +74,20 @@ function buildRequestParams(tags, auctionId, transactionId, gdprConsent) { return req; } +function buildSite() { + let loc = utils.getTopWindowLocation(); + let result = { + page: loc.href, + ref: utils.getTopWindowReferrer(), + secure: ~~(loc.protocol === 'https:') + }; + let keywords = document.getElementsByTagName('meta').namedItem('keywords'); + if (keywords && keywords.content) { + result.keywords = keywords.content; + } + return result; +} + function buildBid(tag) { let bid = { requestId: tag.impid, From 875ffbab48037b75c706a58f74a4b60f79d5f112 Mon Sep 17 00:00:00 2001 From: CathyH Date: Mon, 23 Jul 2018 22:59:37 -0700 Subject: [PATCH 0563/1594] C1X Adapter GDPR Support (#2821) * C1X Adapter GDPR Support * remove the redundant userSync * fixed keyword spacing issue --- modules/c1xBidAdapter.js | 22 +++++++++++++++++----- test/spec/modules/c1xBidAdapter_spec.js | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/modules/c1xBidAdapter.js b/modules/c1xBidAdapter.js index af1de373985..ff1b011f787 100644 --- a/modules/c1xBidAdapter.js +++ b/modules/c1xBidAdapter.js @@ -14,7 +14,7 @@ const LOG_MSG = { /** * Adapter for requesting bids from C1X header tag server. - * v3.0 (c) C1X Inc., 2017 + * v3.1 (c) C1X Inc., 2018 */ export const c1xAdapter = { @@ -29,9 +29,10 @@ export const c1xAdapter = { return !!(bid.adUnitCode && siteId); }, - buildRequests: function(bidRequests) { + buildRequests: function(bidRequests, bidderRequest) { let payload = {}; let tagObj = {}; + let pixelUrl = ''; const adunits = bidRequests.length; const rnd = new Date().getTime(); const c1xTags = bidRequests.map(bidToTag); @@ -48,15 +49,26 @@ export const c1xAdapter = { response: 'json', compress: 'gzip' } - Object.assign(payload, tagObj); - let payloadString = stringifyPayload(payload); + // for GDPR support + if (bidderRequest && bidderRequest.gdprConsent) { + payload['consent_string'] = bidderRequest.gdprConsent.consentString; + payload['consent_required'] = (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies.toString() : 'true' + ; + } if (pixelId) { - const pixelUrl = (useSSL ? 'https:' : 'http:') + PIXEL_ENDPOINT + pixelId; + pixelUrl = (useSSL ? 'https:' : 'http:') + PIXEL_ENDPOINT + pixelId; + if (payload.consent_required) { + pixelUrl += '&gdpr=' + (bidderRequest.gdprConsent.gdprApplies ? 1 : 0); + pixelUrl += '&consent=' + encodeURIComponent(bidderRequest.gdprConsent.consentString || ''); + } userSync.registerSync('image', BIDDER_CODE, pixelUrl); } + Object.assign(payload, tagObj); + + let payloadString = stringifyPayload(payload); // ServerRequest object return { method: 'GET', diff --git a/test/spec/modules/c1xBidAdapter_spec.js b/test/spec/modules/c1xBidAdapter_spec.js index 0517668ea0d..bd7fa5df669 100644 --- a/test/spec/modules/c1xBidAdapter_spec.js +++ b/test/spec/modules/c1xBidAdapter_spec.js @@ -114,6 +114,24 @@ describe('C1XAdapter', () => { const payloadObj = JSON.parse(originalPayload); expect(payloadObj.pageurl).to.equal('http://c1exchange.com/'); }); + + it('should convert GDPR Consent to proper form and attach to request', () => { + let consentString = 'BOP2gFWOQIFovABABAENBGAAAAAAMw'; + let bidderRequest = { + 'bidderCode': 'c1x', + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true + } + } + bidderRequest.bids = bidRequests; + + const request = c1xAdapter.buildRequests(bidRequests, bidderRequest); + const originalPayload = parseRequest(request.data); + const payloadObj = JSON.parse(originalPayload); + expect(payloadObj['consent_string']).to.equal('BOP2gFWOQIFovABABAENBGAAAAAAMw'); + expect(payloadObj['consent_required']).to.equal('true'); + }); }); describe('interpretResponse', () => { From 283d13ad67d0a8de43920bfcf88ad9874de4223d Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 24 Jul 2018 10:51:22 -0400 Subject: [PATCH 0564/1594] fix Travis failures coming from adkernelAdnBidAdapter.js (#2888) --- modules/adkernelAdnBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index c66d2b68b40..e20f58d43f6 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -81,7 +81,7 @@ function buildSite() { ref: utils.getTopWindowReferrer(), secure: ~~(loc.protocol === 'https:') }; - let keywords = document.getElementsByTagName('meta').namedItem('keywords'); + let keywords = document.getElementsByTagName('meta')['keywords']; if (keywords && keywords.content) { result.keywords = keywords.content; } From fba092832d7b20d0b6a1780df476e4a1c15c6350 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 24 Jul 2018 11:05:58 -0400 Subject: [PATCH 0565/1594] hello_world page update (#2874) * updated placement * updated global timeout --- integrationExamples/gpt/hello_world.html | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index be181db21b2..e1cdaa0dc29 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -10,17 +10,20 @@ - ' - }]; + let response1 = [{ + 'cpm': 0.0625, + 'width': '3', + 'height': '3', + 'callback_uid': '2e27ec595bf1a', + 'type': 'public Bid', + 'tag': { + 'content': { + 'title': 'title', + 'content': 'content', + 'advertiser': 'advertiser', + 'button_text': 'button_text', + 'image': 'image', + 'icon': 'icon' + }, + 'cu': ['cu'], + 'iu': ['iu'], + 'p': '6878:11062:32586:8380573788dad9b9fc17edde444c4dcf:2795' + }, + 'creativeId': '8380573788dad9b9fc17edde444c4dcf-6878', + 'requestId': '2e27ec595bf1a', + 'currency': 'USD', + 'ttl': 60, + 'netRevenue': true, + 'zone': '6878' + }]; + + let expectedResponse = [{ + 'requestId': '220ed41385952a', + 'cpm': 0.5, + 'width': '300', + 'height': '250', + 'creativeId': '1f99ac5c3ef10a4097499a5686b30aff-6682', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 60, + 'ad': '', + 'mediaType': 'banner', + }]; + + let expectedResponse1 = [{ + 'requestId': '2e27ec595bf1a', + 'cpm': 0.0625, + 'width': '3', + 'height': '3', + 'creativeId': '8380573788dad9b9fc17edde444c4dcf-6878', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 60, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'image', + 'width': 1600, + 'height': 900 + }, + 'title': 'title', + 'sponsoredBy': 'advertiser', + 'body': 'content', + 'icon': { + 'url': 'icon', + 'width': 900, + 'height': 900 + }, + 'clickUrl': 'cu', + 'impressionTrackers': ['iu'] + } + }]; + it('should get the correct bid response by display ad', () => { let bidderRequest; let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); + it('should get the correct bid response by native ad', () => { + let bidderRequest; + let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse1[0])); + }); + it('handles empty bid response', () => { let response = { body: {} From 2eb77d0211219a5cd65d12cb3a372594aea54a39 Mon Sep 17 00:00:00 2001 From: etargetse <40423120+etargetse@users.noreply.github.com> Date: Mon, 30 Jul 2018 18:20:21 +0200 Subject: [PATCH 0583/1594] Etargetse patch 1 (#2811) * Add files via upload * Add files via upload * Delete etargetBidAdapter.js * Delete etargetBidAdapter.md * test for etargetBidAdapter * Update etargetBidAdapter.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter_spec.js * Update etargetBidAdapter.js * Update etargetBidAdapter_spec.js --- modules/etargetBidAdapter.js | 125 ++++++ modules/etargetBidAdapter.md | 29 ++ test/spec/modules/etargetBidAdapter_spec.js | 433 ++++++++++++++++++++ 3 files changed, 587 insertions(+) create mode 100644 modules/etargetBidAdapter.js create mode 100644 modules/etargetBidAdapter.md create mode 100644 test/spec/modules/etargetBidAdapter_spec.js diff --git a/modules/etargetBidAdapter.js b/modules/etargetBidAdapter.js new file mode 100644 index 00000000000..2ad524613c2 --- /dev/null +++ b/modules/etargetBidAdapter.js @@ -0,0 +1,125 @@ +'use strict'; + +import {registerBidder} from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; + +const BIDDER_CODE = 'etarget'; +const country_map = { + 1: 'sk', + 2: 'cz', + 3: 'hu', + 4: 'ro', + 5: 'rs', + 6: 'bg', + 7: 'pl', + 8: 'hr', + 9: 'at', + 10: 'co', + 11: 'de', + 255: 'en' +} +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, VIDEO ], + isBidRequestValid: function (bid) { + return !!(bid.params.refid && bid.params.country); + }, + buildRequests: function (validBidRequests, bidderRequest) { + var i, l, bid, reqParams, netRevenue, gdprObject; + var request = []; + var bids = JSON.parse(JSON.stringify(validBidRequests)); + var last_contry = 'sk'; + for (i = 0, l = bids.length; i < l; i++) { + bid = bids[i]; + if (country_map[bid.params.country]) { + last_contry = country_map[bid.params.country]; + } + reqParams = bid.params; + reqParams.transactionId = bid.transactionId; + request.push(formRequestUrl(reqParams)); + } + + request.unshift('//' + last_contry + '.search.etargetnet.com/hb/?hbget=1'); + netRevenue = 'net'; + + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { + gdprObject = { + gdpr: bidderRequest.gdprConsent.gdprApplies, + gdpr_consent: bidderRequest.gdprConsent.consentString + }; + request.push('gdpr=' + gdprObject.gdpr); + request.push('gdpr_consent=' + gdprObject.gdpr_consent); + } + + return { + method: 'POST', + url: request.join('&'), + data: bidderRequest, + bids: validBidRequests, + netRevenue: netRevenue, + bidder: 'etarget', + gdpr: gdprObject + }; + + function formRequestUrl(reqData) { + var key; + var url = []; + + for (key in reqData) { + if (reqData.hasOwnProperty(key) && reqData[key]) { url.push(key, '=', reqData[key], '&'); } + } + + return encodeURIComponent(btoa(url.join('').slice(0, -1))); + } + }, + interpretResponse: function (serverResponse, bidRequest) { + const VALID_RESPONSES = { + banner: 1, + video: 1 + }; + var bidObject, bid, type; + var bidRespones = []; + var bids = bidRequest.bids; + var responses = serverResponse.body; + var data = []; + for (var i = 0; i < responses.length; i++) { + data = responses[i]; + type = data.response === 'banner' ? BANNER : VIDEO; + bid = bids[i]; + if (VALID_RESPONSES[data.response] && (verifySize(data, bid.sizes) || type === VIDEO)) { + bidObject = { + requestId: bid.bidId, + cpm: data.win_bid ? data.win_bid : 0, + width: data.width, + height: data.height, + creativeId: data.creativeId, + currency: data.win_cur, + netRevenue: true, + ttl: 360, + ad: data.banner, + vastXml: data.vast_content, + vastUrl: data.vast_link, + mediaType: data.response, + transactionId: bid.transactionId + }; + if (bidRequest.gdpr) { + bidObject.gdpr = bidRequest.gdpr.gdpr; + bidObject.gdpr_consent = bidRequest.gdpr.gdpr_consent; + } + bidRespones.push(bidObject); + } + } + return bidRespones; + + function verifySize(adItem, validSizes) { + for (var j = 0, k = validSizes.length; j < k; j++) { + if (adItem.width == validSizes[j][0] && + adItem.height == validSizes[j][1]) { + return true; + } + } + return false; + } + } +}; +registerBidder(spec); diff --git a/modules/etargetBidAdapter.md b/modules/etargetBidAdapter.md new file mode 100644 index 00000000000..1032de2f9a1 --- /dev/null +++ b/modules/etargetBidAdapter.md @@ -0,0 +1,29 @@ +# Overview + +Module Name: ETARGET Bidder Adapter +Module Type: Bidder Adapter +Maintainer: info@etarget.sk + +# Description + +Module that connects to ETARGET demand sources to fetch bids. +Banner and video formats are supported. + +# Test Parameters +``` + var adUnits = [ + { + code: 'div-gpt-ad-1460505748561-0', // ID of elemnt where ad will be shown + sizes: [[300, 250], [300, 300], [300, 600], [160, 600]], // a display size + bids: [ + { + bidder: "etarget", + params: { + country: 1, //require // specific to your country {1:'sk',2:'cz',3:'hu',4:'ro',5:'rs',6:'bg',7:'pl',8:'hr',9:'at',11:'de',255:'en'} + refid: '12345' // require // you can create/find this ID in Our portal administration on https://sk.etarget-media.com/partner/ + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/etargetBidAdapter_spec.js b/test/spec/modules/etargetBidAdapter_spec.js new file mode 100644 index 00000000000..2af61505afa --- /dev/null +++ b/test/spec/modules/etargetBidAdapter_spec.js @@ -0,0 +1,433 @@ +import {assert, expect} from 'chai'; +import * as url from 'src/url'; +import {spec} from 'modules/etargetBidAdapter'; +import { BANNER, VIDEO } from 'src/mediaTypes'; + +describe('etarget adapter', () => { + let serverResponse, bidRequest, bidResponses; + let bids = []; + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'etarget', + 'params': { + 'refid': '55410', + 'country': '1' + } + }; + + it('should return true when required params found', () => { + assert(spec.isBidRequestValid(bid)); + }); + }); + + describe('buildRequests', () => { + it('should pass multiple bids via single request', () => { + let request = spec.buildRequests(bids); + let parsedUrl = parseUrl(request.url); + assert.lengthOf(parsedUrl.items, 7); + }); + + it('should handle global request parameters', () => { + let parsedUrl = parseUrl(spec.buildRequests([bids[0]]).url); + assert.equal(parsedUrl.path, '//sk.search.etargetnet.com/hb'); + }); + + it('should set correct request method', () => { + let request = spec.buildRequests([bids[0]]); + assert.equal(request.method, 'POST'); + }); + + it('should correctly form bid items', () => { + let bidList = bids; + let request = spec.buildRequests(bidList); + let parsedUrl = parseUrl(request.url); + assert.deepEqual(parsedUrl.items, [ + { + refid: '1', + country: '1', + transactionId: '5f33781f-9552-4ca1', + url: 'some// there' + }, + { + refid: '2', + country: '1', + someVar: 'someValue', + pt: 'gross', + transactionId: '5f33781f-9552-4iuy' + }, + { + refid: '3', + country: '1', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + }, + { + refid: '3', + country: '1', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + }, + { + refid: '3', + country: '1', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + }, + { + refid: '5', + country: '1', + pt: 'net', + transactionId: '5f33781f-9552-7ev3', + }, + { + refid: '6', + country: '1', + pt: 'gross', + transactionId: '5f33781f-9552-7ev3' + } + ]); + }); + + it('should not change original validBidRequests object', () => { + var resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]]); + assert.deepEqual(resultBids, bids[0]); + }); + + describe('gdpr', () => { + it('should send GDPR Consent data to etarget if gdprApplies', () => { + let resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); + let parsedUrl = parseUrl(request.url).query; + + assert.equal(parsedUrl.gdpr, 'true'); + assert.equal(parsedUrl.gdpr_consent, 'concentDataString'); + }); + + it('should not send GDPR Consent data to etarget if gdprApplies is false or undefined', () => { + let resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: false, consentString: 'concentDataString'}}); + let parsedUrl = parseUrl(request.url).query; + + assert.ok(!parsedUrl.gdpr); + assert.ok(!parsedUrl.gdpr_consent); + + request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: undefined, consentString: 'concentDataString'}}); + assert.ok(!parsedUrl.gdpr); + assert.ok(!parsedUrl.gdpr_consent); + }); + + it('should return GDPR Consent data with request data', () => { + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); + + assert.deepEqual(request.gdpr, { + gdpr: true, + gdpr_consent: 'concentDataString' + }); + + request = spec.buildRequests([bids[0]]); + assert.ok(!request.gdpr); + }); + }); + }); + + describe('interpretResponse', () => { + it('should respond with empty response when there is empty serverResponse', () => { + let result = spec.interpretResponse({ body: {} }, {}); + assert.deepEqual(result, []); + }); + it('should respond with empty response when response from server is not banner', () => { + serverResponse.body[0].response = 'not banner'; + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.deepEqual(result, []); + }); + it('should interpret server response correctly with one bid', () => { + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest)[0]; + + assert.equal(result.requestId, '2a0cf4e'); + assert.equal(result.cpm, 13.9); + assert.equal(result.width, 300); + assert.equal(result.height, 250); + assert.equal(result.currency, 'EUR'); + assert.equal(result.netRevenue, true); + assert.equal(result.ttl, 360); + assert.equal(result.ad, ''); + assert.equal(result.transactionId, '5f33781f-9552-4ca1'); + }); + + it('should set correct netRevenue', () => { + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[1]]; + bidRequest.netRevenue = 'net'; + let result = spec.interpretResponse(serverResponse, bidRequest)[0]; + + assert.equal(result.netRevenue, true); + }); + + it('should create bid response item for every requested item', () => { + let result = spec.interpretResponse(serverResponse, bidRequest); + assert.lengthOf(result, 5); + }); + + it('should create bid response with vast xml', () => { + const result = spec.interpretResponse(serverResponse, bidRequest)[3]; + assert.equal(result.vastXml, ''); + }); + + it('should create bid response with vast url', () => { + const result = spec.interpretResponse(serverResponse, bidRequest)[4]; + assert.equal(result.vastUrl, 'vast://url'); + }); + + it('should set mediaType on bid response', () => { + const expected = [ BANNER, BANNER, BANNER, VIDEO, VIDEO ]; + const result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].mediaType, expected[i]); + } + }); + + it('should set default netRevenue as gross', () => { + bidRequest.netRevenue = 'gross'; + const result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].netRevenue, true); + } + }); + + it('should set gdpr if it exist in bidRequest', () => { + bidRequest.gdpr = { + gdpr: true, + gdpr_consent: 'ERW342EIOWT34234KMGds' + }; + let result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].gdpr, true); + assert.equal(result[i].gdpr_consent, 'ERW342EIOWT34234KMGds'); + }; + + bidRequest.gdpr = undefined; + result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.ok(!result[i].gdpr); + assert.ok(!result[i].gdpr_consent); + }; + }); + + describe('verifySizes', () => { + it('should respond with empty response when sizes doesn\'t match', () => { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 100; + serverResponse.body[0].height = 150; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(serverResponse.body.length, 1); + assert.equal(serverResponse.body[0].response, 'banner'); + assert.deepEqual(result, []); + }); + it('should respond with empty response when sizes as a strings doesn\'t match', () => { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 100; + serverResponse.body[0].height = 150; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + + bidRequest.bids[0].sizes = [['101', '150']]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(serverResponse.body.length, 1); + assert.equal(serverResponse.body[0].response, 'banner'); + assert.deepEqual(result, []); + }); + it('should support size dimensions as a strings', () => { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 300; + serverResponse.body[0].height = 600; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + + bidRequest.bids[0].sizes = [['300', '250'], ['250', '300'], ['300', '600'], ['600', '300']] + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(result[0].width, 300); + assert.equal(result[0].height, 600); + }); + }) + }); + + beforeEach(() => { + let sizes = [[250, 300], [300, 250], [300, 600]]; + let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; + let params = [{refid: 1, country: 1, url: 'some// there'}, {refid: 2, country: 1, someVar: 'someValue', pt: 'gross'}, {refid: 3, country: 1, pdom: 'home'}, {refid: 5, country: 1, pt: 'net'}, {refid: 6, country: 1, pt: 'gross'}]; + bids = [ + { + adUnitCode: placementCode[0], + auctionId: '7aefb970-2045', + bidId: '2a0cf4e', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[0], + tid: 45, + placementCode: placementCode[0], + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-4ca1' + }, + { + adUnitCode: placementCode[1], + auctionId: '7aefb970-2045', + bidId: '2a0cf5b', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[1], + placementCode: placementCode[1], + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-4iuy' + }, + { + adUnitCode: placementCode[2], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[3], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[3], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[4], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + } + ]; + serverResponse = { + body: [ + { + banner: '', + deal_id: '123abc', + height: 250, + response: 'banner', + width: 300, + win_bid: 13.9, + win_cur: 'EUR' + }, + { + banner: '', + deal_id: '123abc', + height: 300, + response: 'banner', + width: 250, + win_bid: 13.9, + win_cur: 'EUR' + }, + { + banner: '', + deal_id: '123abc', + height: 300, + response: 'banner', + width: 600, + win_bid: 10, + win_cur: 'EUR' + }, + { + deal_id: '123abc', + height: 300, + response: 'video', + width: 600, + win_bid: 10, + win_cur: 'EUR', + vast_content: '' + }, + { + deal_id: '123abc', + height: 300, + response: 'video', + width: 600, + win_bid: 10, + win_cur: 'EUR', + vast_link: 'vast://url' + } + ], + headers: {} + }; + bidRequest = { + bidder: 'etarget', + bids: bids, + method: 'POST', + url: 'url', + netRevenue: 'net' + }; + }); +}); + +function parseUrl(url) { + const parts = url.split('/'); + const query = parts.pop().split('&'); + return { + path: parts.join('/'), + items: query + .filter((i) => !~i.indexOf('=')) + .map((i) => atob(decodeURIComponent(i)) + .split('&') + .reduce(toObject, {})), + query: query + .filter((i) => ~i.indexOf('=')) + .map((i) => i.replace('?', '')) + .reduce(toObject, {}) + }; +} + +function toObject(cache, string) { + const keyValue = string.split('='); + cache[keyValue[0]] = keyValue[1]; + return cache; +} From f21c6832bc19add02247d3d4dc42e33a5cef45c0 Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 30 Jul 2018 12:20:59 -0400 Subject: [PATCH 0584/1594] Adding new param to Sonobi bid request (#2900) * return null from buildRequests if there is no keymakers * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * return null from buildRequests if there is no keymakers * fixed issue where isEmpty was being called from old utils var. Changed test port expectations to the original 9876 port * add new us param for userSyncsPerBidder --- modules/sonobiBidAdapter.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 6b7841fbc6c..289d42d1719 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -2,6 +2,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { getTopWindowLocation, parseSizesInput, logError, generateUUID, deepAccess, isEmpty } from '../src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; +import { config } from '../src/config'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; @@ -51,9 +52,14 @@ export const spec = { 'pv': PAGEVIEW_ID, 'vp': _getPlatform(), 'lib_name': 'prebid', - 'lib_v': '$prebid.version$' + 'lib_v': '$prebid.version$', + 'us': 0, }; + if (config.getConfig('userSync') && config.getConfig('userSync').syncsPerBidder) { + payload.us = config.getConfig('userSync').syncsPerBidder; + } + if (validBidRequests[0].params.hfa) { payload.hfa = validBidRequests[0].params.hfa; } From 3e3ba8177d36fcd01014be5a44a11f1ee9689274 Mon Sep 17 00:00:00 2001 From: Bryan Gahagan Date: Mon, 30 Jul 2018 12:23:01 -0400 Subject: [PATCH 0585/1594] Sortable adapter: support different floors for each size (#2868) And some other minor fixes - Update the way keywords are send to the server - Use the correct creativeId --- modules/sortableBidAdapter.js | 22 ++++-- test/spec/modules/sortableBidAdapter_spec.js | 75 ++++++++++++++++++-- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/modules/sortableBidAdapter.js b/modules/sortableBidAdapter.js index eeac1cf2796..4eec7228c5b 100644 --- a/modules/sortableBidAdapter.js +++ b/modules/sortableBidAdapter.js @@ -14,7 +14,19 @@ export const spec = { isBidRequestValid: function(bid) { const sortableConfig = config.getConfig('sortable'); const haveSiteId = (sortableConfig && !!sortableConfig.siteId) || bid.params.siteId; - return !!(bid.params.tagId && haveSiteId && bid.sizes && + const validFloor = !bid.params.floor || utils.isNumber(bid.params.floor); + const validSize = /\d+x\d+/; + const validFloorSizeMap = !bid.params.floorSizeMap || + (utils.isPlainObject(bid.params.floorSizeMap) && + Object.keys(bid.params.floorSizeMap).every(size => + size.match(validSize) && utils.isNumber(bid.params.floorSizeMap[size]) + )) + const validKeywords = !bid.params.keywords || + (utils.isPlainObject(bid.params.keywords) && + Object.keys(bid.params.keywords).every(key => + utils.isStr(key) && utils.isStr(bid.params.keywords[key]) + )) + return !!(bid.params.tagId && haveSiteId && validFloor && validFloorSizeMap && validKeywords && bid.sizes && bid.sizes.every(sizeArr => sizeArr.length == 2 && sizeArr.every(num => utils.isNumber(num)))); }, @@ -36,14 +48,16 @@ export const spec = { rv.bidfloor = bid.params.floor; } if (bid.params.keywords) { - let keywords = utils._map(bid.params.keywords, (foo, bar) => ({name: bar, value: foo})); - rv.ext.keywords = keywords; + rv.ext.keywords = bid.params.keywords; } if (bid.params.bidderParams) { utils._each(bid.params.bidderParams, (params, partner) => { rv.ext[partner] = params; }); } + if (bid.params.floorSizeMap) { + rv.ext.floorSizeMap = bid.params.floorSizeMap; + } return rv; }); const gdprConsent = bidderRequest && bidderRequest.gdprConsent; @@ -95,7 +109,7 @@ export const spec = { cpm: parseFloat(bid.price), width: parseInt(bid.w), height: parseInt(bid.h), - creativeId: bid.id, + creativeId: bid.crid || bid.id, dealId: bid.dealid || null, currency: 'USD', netRevenue: true, diff --git a/test/spec/modules/sortableBidAdapter_spec.js b/test/spec/modules/sortableBidAdapter_spec.js index 9f351e9764c..6f1c9efba84 100644 --- a/test/spec/modules/sortableBidAdapter_spec.js +++ b/test/spec/modules/sortableBidAdapter_spec.js @@ -19,6 +19,10 @@ describe('sortableBidAdapter', function() { 'keywords': { 'key1': 'val1', 'key2': 'val2' + }, + 'floorSizeMap': { + '728x90': 0.15, + '300x250': 1.20 } }, 'adUnitCode': 'adunit-code', @@ -58,6 +62,45 @@ describe('sortableBidAdapter', function() { bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); + + it('should return false when the floorSizeMap is invalid', () => { + let bid = makeBid(); + bid.params.floorSizeMap = { + 'sixforty by foureighty': 1234 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + bid.params.floorSizeMap = { + '728x90': 'three' + } + expect(spec.isBidRequestValid(bid)).to.equal(false); + bid.params.floorSizeMap = 'a'; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true when the floorSizeMap is missing or empty', () => { + let bid = makeBid(); + bid.params.floorSizeMap = {}; + expect(spec.isBidRequestValid(bid)).to.equal(true); + delete bid.params.floorSizeMap; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should return false when the keywords are invalid', () => { + let bid = makeBid(); + bid.params.keywords = { + 'badval': 1234 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + bid.params.keywords = 'a'; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true when the keywords are missing or empty', () => { + let bid = makeBid(); + bid.params.keywords = {}; + expect(spec.isBidRequestValid(bid)).to.equal(true); + delete bid.params.keywords; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); }); describe('buildRequests', () => { @@ -70,6 +113,10 @@ describe('sortableBidAdapter', function() { 'keywords': { 'key1': 'val1', 'key2': 'val2' + }, + 'floorSizeMap': { + '728x90': 0.15, + '300x250': 1.20 } }, 'sizes': [ @@ -102,14 +149,21 @@ describe('sortableBidAdapter', function() { }); it('includes the params in the bid request', () => { - expect(requestBody.imp[0].ext.keywords).to.deep.equal([ - {'name': 'key1', 'value': 'val1'}, - {'name': 'key2', 'value': 'val2'} - ]); + expect(requestBody.imp[0].ext.keywords).to.deep.equal( + {'key1': 'val1', + 'key2': 'val2'} + ); expect(requestBody.site.publisher.id).to.equal('example.com'); expect(requestBody.imp[0].tagid).to.equal('403370'); expect(requestBody.imp[0].bidfloor).to.equal(0.21); }); + + it('should have the floor size map set', () => { + expect(requestBody.imp[0].ext.floorSizeMap).to.deep.equal({ + '728x90': 0.15, + '300x250': 1.20 + }); + }); }); describe('interpretResponse', () => { @@ -122,6 +176,7 @@ describe('sortableBidAdapter', function() { 'bid': [ { 'id': '6vmb3isptf', + 'crid': 'sortablescreative', 'impid': '322add653672f68', 'price': 1.22, 'adm': '', @@ -144,7 +199,7 @@ describe('sortableBidAdapter', function() { 'cpm': 1.22, 'width': 728, 'height': 90, - 'creativeId': '6vmb3isptf', + 'creativeId': 'sortablescreative', 'dealId': null, 'currency': 'USD', 'netRevenue': true, @@ -159,6 +214,16 @@ describe('sortableBidAdapter', function() { expect(result[0]).to.deep.equal(expectedBid); }); + it('should handle a missing crid', () => { + 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); + expect(result.length).to.equal(1); + expect(result[0]).to.deep.equal(noCridResult); + }); + it('should handle a missing nurl', () => { let noNurlResponse = makeResponse(); delete noNurlResponse.body.seatbid[0].bid[0].nurl; From 54f23fad873a4207b0e90bd13dbeea54d7677ced Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Mon, 30 Jul 2018 21:54:50 +0530 Subject: [PATCH 0586/1594] added display count global object to track number of times requestBids has been called per ad-unit (#2802) --- modules/medianetBidAdapter.js | 3 +- src/adaptermanager.js | 5 ++- src/prebid.js | 5 +++ test/spec/modules/medianetBidAdapter_spec.js | 36 +++++++++++++------- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 4ff7bfd000e..ed64df99231 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -122,7 +122,8 @@ function slotParams(bidRequest) { let params = { id: bidRequest.bidId, ext: { - dfp_id: bidRequest.adUnitCode + dfp_id: bidRequest.adUnitCode, + display_count: bidRequest.displayCount }, banner: transformSizes(bidRequest.sizes), all: bidRequest.params diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 2ee0d4625a8..00a371db009 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -8,11 +8,13 @@ import { ajaxBuilder } from 'src/ajax'; import { config, RANDOM } from 'src/config'; import includes from 'core-js/library/fn/array/includes'; import find from 'core-js/library/fn/array/find'; +import { getGlobal } from './prebidGlobal'; var utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); var events = require('./events'); let s2sTestingModule; // store s2sTesting module if it's loaded +const $$PREBID_GLOBAL$$ = getGlobal(); var _bidderRegistry = {}; exports.bidderRegistry = _bidderRegistry; @@ -95,7 +97,8 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { sizes: sizes, bidId: bid.bid_id || utils.getUniqueIdentifierStr(), bidderRequestId, - auctionId + auctionId, + displayCount: $$PREBID_GLOBAL$$.displayCount[adUnit.code] })); } return bids; diff --git a/src/prebid.js b/src/prebid.js index 75e1d117c2a..7234a3d2d3d 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -47,6 +47,9 @@ utils.logInfo('Prebid.js v$prebid.version$ loaded'); // create adUnit array $$PREBID_GLOBAL$$.adUnits = $$PREBID_GLOBAL$$.adUnits || []; +// store the number of times requestBids has been called per ad Unit +$$PREBID_GLOBAL$$.displayCount = $$PREBID_GLOBAL$$.displayCount || {}; + // Allow publishers who enable user sync override to trigger their sync $$PREBID_GLOBAL$$.triggerUserSyncs = triggerUserSyncs; @@ -367,6 +370,8 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa adUnit.bids = adUnit.bids.filter(bid => bid.bidder !== bidder); } }); + // increment the number of times requestBids has been called for this adUnit + $$PREBID_GLOBAL$$.displayCount[adUnit.code] = ($$PREBID_GLOBAL$$.displayCount[adUnit.code] + 1) || 1; }); if (!adUnits || adUnits.length === 0) { diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index d94cb64c145..f2ef372de61 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -17,7 +17,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 250]], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'displayCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -33,7 +34,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 251]], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'displayCount': 1 }], VALID_BID_REQUEST_INVALID_BIDFLOOR = [{ 'bidder': 'medianet', @@ -51,7 +53,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 250]], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'displayCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -67,7 +70,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 251]], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'displayCount': 1 }], VALID_AUCTIONDATA = { 'timeout': config.getConfig('bidderTimeout'), @@ -103,7 +107,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -133,7 +138,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -181,7 +187,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -210,7 +217,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -372,7 +380,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [300, 250], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'displayCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -388,7 +397,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [300, 251], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'displayCount': 1 }], VALID_BIDDER_REQUEST_WITH_GDPR = { 'gdprConsent': { @@ -429,7 +439,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -458,7 +469,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, From 838cceeb7eead03fb54de2d5d4a79fb8b3747df6 Mon Sep 17 00:00:00 2001 From: "N. Faure" Date: Mon, 30 Jul 2018 22:22:10 +0200 Subject: [PATCH 0587/1594] Add onBidWon method to bid adapter spec (#2786) --- src/adaptermanager.js | 28 ++++++++++++++++++---------- src/auction.js | 7 ++++++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 00a371db009..5f15112cc6b 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -495,6 +495,19 @@ exports.setS2STestingModule = function (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') { + utils.logInfo(`Invoking ${bidder}.${method}`); + spec[method](param); + } + } catch (e) { + utils.logWarn(`Error calling ${method} of ${bidder}`); + } +} + exports.callTimedOutBidders = function(adUnits, timedOutBidders, cbTimeout) { timedOutBidders = timedOutBidders.map((timedOutBidder) => { // Adding user configured params & timeout to timeout event data @@ -505,15 +518,10 @@ exports.callTimedOutBidders = function(adUnits, timedOutBidders, cbTimeout) { timedOutBidders = utils.groupBy(timedOutBidders, 'bidder'); Object.keys(timedOutBidders).forEach((bidder) => { - try { - const adapter = _bidderRegistry[bidder]; - const spec = adapter.getSpec(); - if (spec && spec.onTimeout && typeof spec.onTimeout === 'function') { - utils.logInfo(`Invoking ${bidder}.onTimeout`); - spec.onTimeout(timedOutBidders[bidder]); - } - } catch (e) { - utils.logWarn(`Error calling onTimeout of ${bidder}`); - } + tryCallBidderMethod(bidder, 'onTimeout', timedOutBidders[bidder]); }); } + +exports.callBidWonBidder = function(bidder, bid) { + tryCallBidderMethod(bidder, 'onBidWon', bid); +}; diff --git a/src/auction.js b/src/auction.js index fe57de38de1..49632fddcf0 100644 --- a/src/auction.js +++ b/src/auction.js @@ -279,12 +279,17 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } + function addWinningBid(winningBid) { + _winningBids = _winningBids.concat(winningBid); + adaptermanager.callBidWonBidder(winningBid.bidder, winningBid); + } + return { addBidReceived, executeCallback, callBids, bidsBackAll, - addWinningBid: (winningBid) => { _winningBids = _winningBids.concat(winningBid) }, + addWinningBid, getWinningBids: () => _winningBids, getTimeout: () => _timeout, getAuctionId: () => _auctionId, From 386fbac7e30a646ef83787b9a8120161c8af1d52 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 31 Jul 2018 10:34:56 -0400 Subject: [PATCH 0588/1594] Revert "Feature : Display counter at Adslot level " (#2912) * Revert "Add onBidWon method to bid adapter spec (#2786)" This reverts commit 838cceeb7eead03fb54de2d5d4a79fb8b3747df6. * Revert "added display count global object to track number of times requestBids has been called per ad-unit (#2802)" This reverts commit 54f23fad873a4207b0e90bd13dbeea54d7677ced. --- modules/medianetBidAdapter.js | 3 +- src/adaptermanager.js | 5 +-- src/prebid.js | 5 --- test/spec/modules/medianetBidAdapter_spec.js | 36 +++++++------------- 4 files changed, 14 insertions(+), 35 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index ed64df99231..4ff7bfd000e 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -122,8 +122,7 @@ function slotParams(bidRequest) { let params = { id: bidRequest.bidId, ext: { - dfp_id: bidRequest.adUnitCode, - display_count: bidRequest.displayCount + dfp_id: bidRequest.adUnitCode }, banner: transformSizes(bidRequest.sizes), all: bidRequest.params diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 5f15112cc6b..5f0ac5b5656 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -8,13 +8,11 @@ import { ajaxBuilder } from 'src/ajax'; import { config, RANDOM } from 'src/config'; import includes from 'core-js/library/fn/array/includes'; import find from 'core-js/library/fn/array/find'; -import { getGlobal } from './prebidGlobal'; var utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); var events = require('./events'); let s2sTestingModule; // store s2sTesting module if it's loaded -const $$PREBID_GLOBAL$$ = getGlobal(); var _bidderRegistry = {}; exports.bidderRegistry = _bidderRegistry; @@ -97,8 +95,7 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { sizes: sizes, bidId: bid.bid_id || utils.getUniqueIdentifierStr(), bidderRequestId, - auctionId, - displayCount: $$PREBID_GLOBAL$$.displayCount[adUnit.code] + auctionId })); } return bids; diff --git a/src/prebid.js b/src/prebid.js index 7234a3d2d3d..75e1d117c2a 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -47,9 +47,6 @@ utils.logInfo('Prebid.js v$prebid.version$ loaded'); // create adUnit array $$PREBID_GLOBAL$$.adUnits = $$PREBID_GLOBAL$$.adUnits || []; -// store the number of times requestBids has been called per ad Unit -$$PREBID_GLOBAL$$.displayCount = $$PREBID_GLOBAL$$.displayCount || {}; - // Allow publishers who enable user sync override to trigger their sync $$PREBID_GLOBAL$$.triggerUserSyncs = triggerUserSyncs; @@ -370,8 +367,6 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa adUnit.bids = adUnit.bids.filter(bid => bid.bidder !== bidder); } }); - // increment the number of times requestBids has been called for this adUnit - $$PREBID_GLOBAL$$.displayCount[adUnit.code] = ($$PREBID_GLOBAL$$.displayCount[adUnit.code] + 1) || 1; }); if (!adUnits || adUnits.length === 0) { diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index f2ef372de61..d94cb64c145 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -17,8 +17,7 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 250]], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'displayCount': 1 + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }, { 'bidder': 'medianet', 'params': { @@ -34,8 +33,7 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 251]], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'displayCount': 1 + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }], VALID_BID_REQUEST_INVALID_BIDFLOOR = [{ 'bidder': 'medianet', @@ -53,8 +51,7 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 250]], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'displayCount': 1 + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }, { 'bidder': 'medianet', 'params': { @@ -70,8 +67,7 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 251]], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'displayCount': 1 + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }], VALID_AUCTIONDATA = { 'timeout': config.getConfig('bidderTimeout'), @@ -107,8 +103,7 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - }, - 'display_count': 1 + } }, 'banner': [{ 'w': 300, @@ -138,8 +133,7 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - }, - 'display_count': 1 + } }, 'banner': [{ 'w': 300, @@ -187,8 +181,7 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - }, - 'display_count': 1 + } }, 'banner': [{ 'w': 300, @@ -217,8 +210,7 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - }, - 'display_count': 1 + } }, 'banner': [{ 'w': 300, @@ -380,8 +372,7 @@ let VALID_BID_REQUEST = [{ 'sizes': [300, 250], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'displayCount': 1 + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }, { 'bidder': 'medianet', 'params': { @@ -397,8 +388,7 @@ let VALID_BID_REQUEST = [{ 'sizes': [300, 251], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'displayCount': 1 + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }], VALID_BIDDER_REQUEST_WITH_GDPR = { 'gdprConsent': { @@ -439,8 +429,7 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - }, - 'display_count': 1 + } }, 'banner': [{ 'w': 300, @@ -469,8 +458,7 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - }, - 'display_count': 1 + } }, 'banner': [{ 'w': 300, From db38f7b3cba6275ba7635583c3b6a667c032b532 Mon Sep 17 00:00:00 2001 From: interactiveoffers-devteam <41801096+interactiveoffers-devteam@users.noreply.github.com> Date: Tue, 31 Jul 2018 10:48:43 -0400 Subject: [PATCH 0589/1594] InteractiveOffers Header Bidding Adapter V1 (#2908) * InteractiveOffers Header Bidding Adapter * Interactive Offers Header Bidding Adapter Test --- modules/interactiveOffersBidAdapter.js | 99 ++++++++++ modules/interactiveOffersBidAdapter.md | 34 ++++ .../interactiveOffersBidAdapter_spec.js | 177 ++++++++++++++++++ 3 files changed, 310 insertions(+) create mode 100644 modules/interactiveOffersBidAdapter.js create mode 100644 modules/interactiveOffersBidAdapter.md create mode 100644 test/spec/modules/interactiveOffersBidAdapter_spec.js diff --git a/modules/interactiveOffersBidAdapter.js b/modules/interactiveOffersBidAdapter.js new file mode 100644 index 00000000000..2437fa1d3c9 --- /dev/null +++ b/modules/interactiveOffersBidAdapter.js @@ -0,0 +1,99 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import {config} from 'src/config'; + +const BIDDER_CODE = 'interactiveOffers'; +const BIDDER_ENDPOINT = 'https://connect.interactiveoffers.com/api/endpoint.php'; +const TIMEOUT_DEFAULT = 5000; + +export const spec = { + code: BIDDER_CODE, + aliases: ['ino'], + isBidRequestValid: function(bid) { + if (!('params' in bid)) { + utils.logError(bid.bidder + ': No required params, please check your settings'); + return false; + } + if (!(bid.params.pubId)) { + utils.logError(bid.bidder + ': No required param pubId, please check your settings'); + return false; + } + return true; + }, + + buildRequests: function(validBidRequests, bidderRequest) { + let serverRequests = []; + for (let i = 0; i < validBidRequests.length; i++) { + let bidRequest = validBidRequests[i]; + let bidRequestParams = bidRequest.params; + let pubId = utils.getBidIdParameter('pubId', bidRequestParams); + + // Loc param is optional but always is sent to endpoint + let location = utils.getBidIdParameter('loc', bidRequestParams); + if (!location) { + location = utils.getTopWindowUrl(); + } + + // Tmax param is optional but always is sent to endpoint + let tmax = utils.getBidIdParameter('tmax', bidRequestParams); + if (!tmax) { + tmax = TIMEOUT_DEFAULT; + } + + serverRequests.push({ + method: 'POST', + url: BIDDER_ENDPOINT, + data: Object.assign({ + 'pubId': pubId, + 'bidId': utils.getUniqueIdentifierStr(), + 'loc': location, + 'tmax': tmax, + 'sizes': bidRequest.sizes + }), + options: {withCredentials: false}, + bidRequest: bidRequest + }); + } + return serverRequests; + }, + + interpretResponse: function(serverResponse, request) { + let bidResponses = []; + if (!serverResponse || serverResponse.error) { + utils.logError(BIDDER_CODE + ': server response error', serverResponse); + return bidResponses; + } + + const serverBody = serverResponse.body; + if (!serverBody || serverBody.success !== 'true') { + utils.logError(BIDDER_CODE + ': empty bid response'); + return bidResponses; + } + + const serverPayloadData = serverBody.payloadData; + if (!serverPayloadData || Array.isArray(serverPayloadData)) { + utils.logError(BIDDER_CODE + ': server response no data', serverResponse); + return bidResponses; + } + + const CPM = serverPayloadData.cpm; + if (CPM > 0) { + let bidResponse = { + requestId: request.bidRequest.bidId, + cpm: CPM, + width: serverPayloadData.width, + height: serverPayloadData.height, + creativeId: serverPayloadData.bidId, + ttl: config.getConfig('_bidderTimeout'), + referrer: utils.getTopWindowUrl(), + currency: 'USD', + netRevenue: true, + ad: serverPayloadData.ad + }; + bidResponses.push(bidResponse); + } + + return bidResponses; + }, +}; +registerBidder(spec); diff --git a/modules/interactiveOffersBidAdapter.md b/modules/interactiveOffersBidAdapter.md new file mode 100644 index 00000000000..7eb440c8216 --- /dev/null +++ b/modules/interactiveOffersBidAdapter.md @@ -0,0 +1,34 @@ +# Overview + +``` +Module Name: interactiveOffers Bidder Adapter +Module Type: Bidder Adapter +Maintainer: devteam@interactiveoffers.com +``` + +# Description + +Module that connects to interactiveOffers demand sources. Param pubId is required. + +# Test Parameters +``` + var adUnits = [ + { + code: 'interactiveOffers-slot', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: "interactiveOffers", + params: { + pubId: '10', + tmax: 5000 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/interactiveOffersBidAdapter_spec.js b/test/spec/modules/interactiveOffersBidAdapter_spec.js new file mode 100644 index 00000000000..6cf09cf6149 --- /dev/null +++ b/test/spec/modules/interactiveOffersBidAdapter_spec.js @@ -0,0 +1,177 @@ +import {expect} from 'chai'; +import {spec} from 'modules/interactiveOffersBidAdapter'; + +describe('interactiveOffers adapter', () => { + describe('implementation', () => { + describe('for requests', () => { + it('should accept valid bid', () => { + let validBid = { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + }, + isValid = spec.isBidRequestValid(validBid); + + expect(isValid).to.equal(true); + }); + + it('should reject invalid bid', () => { + let invalidBid = { + bidder: 'interactiveOffers' + }, + isValid = spec.isBidRequestValid(invalidBid); + + expect(isValid).to.equal(false); + }); + }); + describe('for requests', () => { + it('should accept valid bid with optional params', () => { + let validBid = { + bidder: 'interactiveOffers', + params: { + pubId: '42', + loc: 'http://test.com/prebid', + tmax: 1500 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + + let buildRequest = spec.buildRequests([validBid])[0]; + let requestUrlCustomParams = buildRequest.data; + expect(requestUrlCustomParams).have.property('loc', 'http://test.com/prebid'); + expect(requestUrlCustomParams).have.property('tmax', 1500); + }); + + it('should accept valid bid without optional params', () => { + let validBid = { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + + let buildRequest = spec.buildRequests([validBid])[0]; + let requestUrlCustomParams = buildRequest.data; + expect(requestUrlCustomParams).have.property('loc'); + expect(requestUrlCustomParams).have.property('tmax'); + }); + + it('should reject invalid bid without pubId', () => { + let invalidBid = { + bidder: 'interactiveOffers', + params: {} + }, + isValid = spec.isBidRequestValid(invalidBid); + + expect(isValid).to.equal(false); + }); + }); + describe('bid responses', () => { + it('should return complete bid response', () => { + let serverResponse = { + body: { + 'success': 'true', + 'message': 'Request Valid', + 'payloadData': { + bidId: '3842b02f7ec0fd', + cpm: 0.5, + width: 300, + height: 600, + ad: '
...
', + } + } + }; + + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(0.5); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(600); + expect(bids[0].currency).to.equal('USD'); + expect(bids[0].netRevenue).to.equal(true); + expect(bids[0].ad).to.have.length.above(1); + }); + + it('should return empty bid response', () => { + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let serverResponse = { + body: { + 'success': 'true', + 'message': 'Request Valid', + 'payloadData': { + bidId: '3842b02f7ec0fd', + cpm: 0 + } + } + }, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response with error', () => { + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let serverResponse = {body: {'success': 'false', 'message': 'Request Error'}}, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response without payload', () => { + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let serverResponse = {body: {'success': 'true', 'message': 'Empty Payload', 'payloadData': []}}, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response on empty body', () => { + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let serverResponse, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + }); + }); +}); From 7d008b41c6d1c2530214a3c3302e8d133d5737f4 Mon Sep 17 00:00:00 2001 From: adxcgcom <31470944+adxcgcom@users.noreply.github.com> Date: Tue, 31 Jul 2018 17:31:12 +0200 Subject: [PATCH 0590/1594] adxcgAnalyticsAdapter -cleaning up json data sent. (merged multiple local commits) (#2909) --- modules/adxcgAnalyticsAdapter.js | 165 +++++++++++----- modules/adxcgAnalyticsAdapter.md | 23 +++ .../modules/adxcgAnalyticsAdapter_spec.js | 184 +++++++++++++----- 3 files changed, 280 insertions(+), 92 deletions(-) create mode 100644 modules/adxcgAnalyticsAdapter.md diff --git a/modules/adxcgAnalyticsAdapter.js b/modules/adxcgAnalyticsAdapter.js index 8de0a346ed6..5dc934a861e 100644 --- a/modules/adxcgAnalyticsAdapter.js +++ b/modules/adxcgAnalyticsAdapter.js @@ -1,4 +1,4 @@ -import {ajax} from 'src/ajax'; +import { ajax } from 'src/ajax'; import adapter from 'src/AnalyticsAdapter'; import adaptermanager from 'src/adaptermanager'; import CONSTANTS from 'src/constants.json'; @@ -7,83 +7,154 @@ import * as utils from 'src/utils'; const emptyUrl = ''; const analyticsType = 'endpoint'; -const adxcgAnalyticsVersion = 'v1.05'; - -let initOptions; -let auctionTimestamp; -let events = { - bidRequests: [], - bidResponses: [] -}; +const adxcgAnalyticsVersion = 'v2.01'; var adxcgAnalyticsAdapter = Object.assign(adapter( { emptyUrl, analyticsType }), { - track({eventType, args}) { - if (typeof args !== 'undefined') { - if (eventType === CONSTANTS.EVENTS.BID_TIMEOUT) { - events.bidTimeout = args.map(item => item.bidder).filter(utils.uniques); - } else if (eventType === CONSTANTS.EVENTS.AUCTION_INIT) { - events.auctionInit = args; - auctionTimestamp = args.timestamp; - } else if (eventType === CONSTANTS.EVENTS.BID_REQUESTED) { - events.bidRequests.push(args); - } else if (eventType === CONSTANTS.EVENTS.BID_RESPONSE) { - events.bidResponses.push(mapBidResponse(args)); - } else if (eventType === CONSTANTS.EVENTS.BID_WON) { - send({ - bidWon: mapBidResponse(args) - }); - } - } - - if (eventType === CONSTANTS.EVENTS.AUCTION_END) { - send(events); + track ({eventType, args}) { + switch (eventType) { + case CONSTANTS.EVENTS.AUCTION_INIT: + adxcgAnalyticsAdapter.context.events.auctionInit = mapAuctionInit(args); + adxcgAnalyticsAdapter.context.auctionTimestamp = args.timestamp; + break; + case CONSTANTS.EVENTS.BID_REQUESTED: + adxcgAnalyticsAdapter.context.auctionId = args.auctionId; + adxcgAnalyticsAdapter.context.events.bidRequests.push(mapBidRequested(args)); + break; + case CONSTANTS.EVENTS.BID_ADJUSTMENT: + break; + case CONSTANTS.EVENTS.BID_TIMEOUT: + adxcgAnalyticsAdapter.context.events.bidTimeout = args.map(item => item.bidder).filter(utils.uniques); + break; + case CONSTANTS.EVENTS.BIDDER_DONE: + break; + case CONSTANTS.EVENTS.BID_RESPONSE: + adxcgAnalyticsAdapter.context.events.bidResponses.push(mapBidResponse(args, eventType)); + break; + case CONSTANTS.EVENTS.BID_WON: + let outData2 = {bidWons: mapBidWon(args)}; + send(outData2); + break; + case CONSTANTS.EVENTS.AUCTION_END: + send(adxcgAnalyticsAdapter.context.events); + break; } } + }); -function mapBidResponse(bidResponse) { +function mapAuctionInit (auctionInit) { + return { + timeout: auctionInit.timeout + }; +} + +function mapBidRequested (bidRequests) { + return { + bidderCode: bidRequests.bidderCode, + time: bidRequests.start, + bids: bidRequests.bids.map(function (bid) { + return { + transactionId: bid.transactionId, + adUnitCode: bid.adUnitCode, + bidId: bid.bidId, + start: bid.startTime, + sizes: utils.parseSizesInput(bid.sizes).toString(), + params: bid.params + }; + }), + }; +} + +function mapBidResponse (bidResponse, eventType) { return { + bidderCode: bidResponse.bidder, + transactionId: bidResponse.transactionId, adUnitCode: bidResponse.adUnitCode, statusMessage: bidResponse.statusMessage, - bidderCode: bidResponse.bidderCode, - adId: bidResponse.adId, mediaType: bidResponse.mediaType, - creative_id: bidResponse.creative_id, - width: bidResponse.width, - height: bidResponse.height, + renderedSize: bidResponse.size, cpm: bidResponse.cpm, - timeToRespond: bidResponse.timeToRespond + currency: bidResponse.currency, + netRevenue: bidResponse.netRevenue, + timeToRespond: bidResponse.timeToRespond, + bidId: eventType === CONSTANTS.EVENTS.BID_TIMEOUT ? bidResponse.bidId : bidResponse.requestId, + dealId: bidResponse.dealId, + status: bidResponse.status, + creativeId: bidResponse.creativeId.toString() }; } -function send(data) { - data.initOptions = initOptions; - data.auctionTimestamp = auctionTimestamp; +function mapBidWon (bidResponse) { + return [{ + bidderCode: bidResponse.bidder, + adUnitCode: bidResponse.adUnitCode, + statusMessage: bidResponse.statusMessage, + mediaType: bidResponse.mediaType, + renderedSize: bidResponse.size, + cpm: bidResponse.cpm, + currency: bidResponse.currency, + netRevenue: bidResponse.netRevenue, + timeToRespond: bidResponse.timeToRespond, + bidId: bidResponse.requestId, + dealId: bidResponse.dealId, + status: bidResponse.status, + creativeId: bidResponse.creativeId.toString() + }]; +} +function send (data) { let location = utils.getTopWindowLocation(); - let secure = location.protocol == 'https:'; + let secure = location.protocol === 'https:'; let adxcgAnalyticsRequestUrl = url.format({ protocol: secure ? 'https' : 'http', - hostname: secure ? 'hbarxs.adxcg.net' : 'hbarx.adxcg.net', - pathname: '/pbrx', + hostname: adxcgAnalyticsAdapter.context.host, + pathname: '/pbrx/v2', search: { - auctionTimestamp: auctionTimestamp, - adxcgAnalyticsVersion: adxcgAnalyticsVersion, - prebidVersion: $$PREBID_GLOBAL$$.version + pid: adxcgAnalyticsAdapter.context.initOptions.publisherId, + aid: adxcgAnalyticsAdapter.context.auctionId, + ats: adxcgAnalyticsAdapter.context.auctionTimestamp, + aav: adxcgAnalyticsVersion, + iob: intersectionObserverAvailable(window) ? '1' : '0', + pbv: $$PREBID_GLOBAL$$.version, + sz: window.screen.width + 'x' + window.screen.height } }); - ajax(adxcgAnalyticsRequestUrl, undefined, JSON.stringify(data), {method: 'POST'}); + ajax(adxcgAnalyticsRequestUrl, undefined, JSON.stringify(data), { + contentType: 'text/plain', + method: 'POST', + withCredentials: true + }); +} + +function intersectionObserverAvailable (win) { + return win && win.IntersectionObserver && win.IntersectionObserverEntry && + win.IntersectionObserverEntry.prototype && 'intersectionRatio' in win.IntersectionObserverEntry.prototype; } +adxcgAnalyticsAdapter.context = {}; adxcgAnalyticsAdapter.originEnableAnalytics = adxcgAnalyticsAdapter.enableAnalytics; adxcgAnalyticsAdapter.enableAnalytics = function (config) { - initOptions = config.options; + if (!config.options.publisherId) { + utils.logError('PublisherId option is not defined. Analytics won\'t work'); + return; + } + + let secure = location.protocol === 'https:'; + adxcgAnalyticsAdapter.context = { + events: { + bidRequests: [], + bidResponses: [] + }, + initOptions: config.options, + host: config.options.host || (secure ? 'hbarxs.adxcg.net' : 'hbarx.adxcg.net') + }; + adxcgAnalyticsAdapter.originEnableAnalytics(config); }; diff --git a/modules/adxcgAnalyticsAdapter.md b/modules/adxcgAnalyticsAdapter.md new file mode 100644 index 00000000000..e134ed23e3f --- /dev/null +++ b/modules/adxcgAnalyticsAdapter.md @@ -0,0 +1,23 @@ +# Overview +Module Name: adxcg Analytics Adapter + +Module Type: Analytics Adapter + +Maintainer: info@adxcg.com + +# Description + +Analytics adapter for Adxcg. We are an advanced programmatic solutions company. +https://www.adxcg.com/ + +# Test Parameters + +``` +{ + provider: 'adxcg', + options : { + publisherId: ["42"] + } +} + +``` diff --git a/test/spec/modules/adxcgAnalyticsAdapter_spec.js b/test/spec/modules/adxcgAnalyticsAdapter_spec.js index edd09fdf54e..9b6b057ee56 100644 --- a/test/spec/modules/adxcgAnalyticsAdapter_spec.js +++ b/test/spec/modules/adxcgAnalyticsAdapter_spec.js @@ -1,5 +1,6 @@ import adxcgAnalyticsAdapter from 'modules/adxcgAnalyticsAdapter'; import { expect } from 'chai'; + let adaptermanager = require('src/adaptermanager'); let events = require('src/events'); let constants = require('src/constants.json'); @@ -25,6 +26,139 @@ describe('adxcg analytics adapter', () => { publisherId: '42' }; + let auctionTimestamp = 1496510254313; + + // prepare general auction - request and response + let bidRequest = { + 'bidderCode': 'appnexus', + 'bids': [{ + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', + 'sizes': '300x250,300x600', + 'bidId': '2eddfdc0c791dc', + 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7' + } + ] + }; + + let bidResponse = { + 'height': 250, + 'statusMessage': 'Bid available', + 'adId': '2eddfdc0c791dc', + 'mediaType': 'banner', + 'source': 'client', + 'requestId': '2eddfdc0c791dc', + 'cpm': 0.5, + 'creativeId': 29681110, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7', + 'responseTimestamp': 1522265866110, + 'requestTimestamp': 1522265863600, + 'bidder': 'appnexus', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'timeToRespond': 2510, + 'size': '300x250' + }; + + // what we expect after general auction + let expectedAfterBid = { + 'bidRequests': [ + { + 'bidderCode': 'appnexus', + 'bids': [ + { + 'transactionId': '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'bidId': '2eddfdc0c791dc', + 'sizes': '300x250,300x600', + 'params': { + 'placementId': '10433394' + } + } + ] + } + ], + 'bidResponses': [ + { + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'bidderCode': 'appnexus', + 'statusMessage': 'Bid available', + 'mediaType': 'banner', + 'renderedSize': '300x250', + 'cpm': 0.5, + 'currency': 'USD', + 'netRevenue': true, + 'timeToRespond': 2510, + 'bidId': '2eddfdc0c791dc', + 'creativeId': '29681110' + } + ], + 'auctionInit': {}, + 'bidTimeout': [ + 'bidderOne', + 'bidderTwo' + ] + }; + + // lets simulate that some bidders timeout + let bidTimeoutArgsV1 = [ + { + bidId: '2baa51527bd015', + bidder: 'bidderOne', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + }, + { + bidId: '6fe3b4c2c23092', + bidder: 'bidderTwo', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + } + ]; + + // now simulate some WIN and RENDERING + let wonRequest = { + 'adId': '4587fec4900b81', + 'mediaType': 'banner', + 'requestId': '4587fec4900b81', + 'cpm': 1.962, + 'creativeId': 2126, + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 302, + 'auctionId': '914bedad-b145-4e46-ba58-51365faea6cb', + 'statusMessage': 'Bid available', + 'responseTimestamp': 1530628534437, + 'requestTimestamp': 1530628534219, + 'bidder': 'testbidder4', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'timeToRespond': 218, + 'size': '300x250', + 'status': 'rendered' + }; + + let wonExpect = { + 'bidWons': [{ + 'bidderCode': 'testbidder4', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'mediaType': 'banner', + 'renderedSize': '300x250', + 'cpm': 1.962, + 'currency': 'EUR', + 'netRevenue': true, + 'timeToRespond': 218, + 'bidId': '4587fec4900b81', + 'statusMessage': 'Bid available', + 'status': 'rendered', + 'creativeId': '2126' + }] + }; + adaptermanager.registerAnalyticsAdapter({ code: 'adxcg', adapter: adxcgAnalyticsAdapter @@ -42,30 +176,6 @@ describe('adxcg analytics adapter', () => { }); it('builds and sends auction data', () => { - let auctionTimestamp = 1496510254313; - let bidRequest = { - auctionId: 'requestIdData' - }; - let bidResponse = { - adId: 'adIdData', - ad: 'adContent' - }; - - let bidTimeoutArgsV1 = [ - { - bidId: '2baa51527bd015', - bidder: 'bidderOne', - adUnitCode: '/19968336/header-bid-tag-0', - auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' - }, - { - bidId: '6fe3b4c2c23092', - bidder: 'bidderTwo', - adUnitCode: '/19968336/header-bid-tag-0', - auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' - } - ]; - // Step 1: Send auction init event events.emit(constants.EVENTS.AUCTION_INIT, { timestamp: auctionTimestamp @@ -85,35 +195,19 @@ describe('adxcg analytics adapter', () => { expect(requests.length).to.equal(1); - let auctionEventData = JSON.parse(requests[0].requestBody); - - expect(auctionEventData.bidRequests.length).to.equal(1); - expect(auctionEventData.bidRequests[0]).to.deep.equal(bidRequest); - - expect(auctionEventData.bidResponses.length).to.equal(1); - expect(auctionEventData.bidResponses[0].adId).to.equal(bidResponse.adId); - expect(auctionEventData.bidResponses[0]).to.not.have.property('ad'); + let realAfterBid = JSON.parse(requests[0].requestBody); - expect(auctionEventData.initOptions).to.deep.equal(initOptions); + expect(realAfterBid).to.deep.equal(expectedAfterBid); - expect(auctionEventData.auctionTimestamp).to.equal(auctionTimestamp); - - expect(auctionEventData.bidTimeout).to.deep.equal(['bidderOne', 'bidderTwo']); + expect(realAfterBid.bidTimeout).to.deep.equal(['bidderOne', 'bidderTwo']); // Step 6: Send auction bid won event - events.emit(constants.EVENTS.BID_WON, { - adId: 'adIdData', - ad: 'adContent' - }); + events.emit(constants.EVENTS.BID_WON, wonRequest); expect(requests.length).to.equal(2); - let winEventData = JSON.parse(requests[1].requestBody); - expect(winEventData.bidWon.adId).to.equal(bidResponse.adId); - expect(winEventData.bidWon).to.not.have.property('ad'); - expect(winEventData.initOptions).to.deep.equal(initOptions); - expect(winEventData.auctionTimestamp).to.equal(auctionTimestamp); + expect(winEventData).to.deep.equal(wonExpect); }); }); }); From f90ec9d4ed154ccc5fe957f66942ae2ab8c1eb8c Mon Sep 17 00:00:00 2001 From: Arik Kfir Date: Tue, 31 Jul 2018 18:32:37 +0300 Subject: [PATCH 0591/1594] Add gamoshi outstream renderer (#2907) * Add renderer for video outstream units & bids * Update demo account IDs * Fix code formatting errors and add context check for outstream units * Fix few more formatting issues * Remove "onTimeout" no-op handler * Remove extra spaces * Fix outstream video context detection --- modules/gambidBidAdapter.js | 47 +++++++++++++++++++++++++++++++++---- modules/gambidBidAdapter.md | 26 ++++++++++---------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/modules/gambidBidAdapter.js b/modules/gambidBidAdapter.js index ca711f6e1eb..63b45ad0d0a 100644 --- a/modules/gambidBidAdapter.js +++ b/modules/gambidBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; +import { Renderer } from '../src/Renderer'; function getTopFrame() { try { @@ -128,7 +129,13 @@ export const spec = { if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { outBids.push(Object.assign({}, outBid, { mediaType: 'banner', ad: bid.adm })); } else if (bidRequest.bidRequest.mediaTypes.video) { - outBids.push(Object.assign({}, outBid, { mediaType: 'video', vastUrl: bid.ext.vast_url, vastXml: bid.adm })); + const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); + outBids.push(Object.assign({}, outBid, { + mediaType: 'video', + vastUrl: bid.ext.vast_url, + vastXml: bid.adm, + renderer: context === 'outstream' ? newRenderer(bidRequest, bid) : undefined + })); } }); return outBids; @@ -164,10 +171,40 @@ export const spec = { } }); return syncs; - }, - - onTimeout: function(data) { - utils.logWarn('Gambid request timed out.', data); } }; + +function newRenderer(adUnitCode, bid, rendererOptions = {}) { + const renderer = Renderer.install({ + url: '//s.gamoshi.io/video/latest/renderer.js', + config: rendererOptions, + loaded: false, + }); + try { + renderer.setRender(renderOutstream); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + return renderer; +} + +function renderOutstream(bid) { + bid.renderer.push(() => { + const unitId = bid.adUnitCode + '/' + bid.adId; + window['GamoshiPlayer'].renderAd({ + id: unitId, + debug: window.location.href.indexOf('pbjsDebug') >= 0, + placement: document.getElementById(bid.adUnitCode), + width: bid.width, + height: bid.height, + events: { + ALL_ADS_COMPLETED: () => window.setTimeout(() => { + window['GamoshiPlayer'].removeAd(unitId); + }, 300) + }, + vastXml: bid.vastXml + }); + }); +} + registerBidder(spec); diff --git a/modules/gambidBidAdapter.md b/modules/gambidBidAdapter.md index ddf1c8f7851..b34d05070a9 100644 --- a/modules/gambidBidAdapter.md +++ b/modules/gambidBidAdapter.md @@ -19,27 +19,27 @@ var adUnits = [ // Banner adUnit { code: 'banner-div', - sizes: [[300, 250], [300,600]], + sizes: [[300, 250]], bids: [{ bidder: 'gambid', params: { // ID of the supply partner you created in the Gambid dashboard - supplyPartnerId: '12345', + supplyPartnerId: '1253', // OPTIONAL: if you have a whitelabel account on Gamoshi, specify it here - rtbEndpoint: 'https://my.custom-whitelabel-domain.io', + //rtbEndpoint: 'https://my.custom-whitelabel-domain.io', // OPTIONAL: custom bid floor - bidfloor: 0.03, + bidfloor: 0.01, // OPTIONAL: if you know the ad position on the page, specify it here // (this corresponds to "Ad Position" in OpenRTB 2.3, section 5.4) - adpos: 1, + //adpos: 1, // OPTIONAL: whether this is an interstitial placement (0 or 1) // (see "instl" property in "Imp" object in the OpenRTB 2.3, section 3.2.2) - instl: 0 + //instl: 0 } }] }, @@ -47,11 +47,11 @@ var adUnits = [ // Video outstream adUnit { code: 'video-outstream', - sizes: [[640, 480]], + sizes: [[300, 250]], mediaTypes: { video: { context: 'outstream', - playerSize: [640, 480] + playerSize: [300, 250] } }, bids: [ { @@ -59,21 +59,21 @@ var adUnits = [ params: { // ID of the supply partner you created in the Gambid dashboard - supplyPartnerId: '12345', + supplyPartnerId: '1254', // OPTIONAL: if you have a whitelabel account on Gamoshi, specify it here - rtbEndpoint: 'https://my.custom-whitelabel-domain.io', + //rtbEndpoint: 'https://my.custom-whitelabel-domain.io', // OPTIONAL: custom bid floor - bidfloor: 0.03, + bidfloor: 0.01, // OPTIONAL: if you know the ad position on the page, specify it here // (this corresponds to "Ad Position" in OpenRTB 2.3, section 5.4) - adpos: 1, + //adpos: 1, // OPTIONAL: whether this is an interstitial placement (0 or 1) // (see "instl" property in "Imp" object in the OpenRTB 2.3, section 3.2.2) - instl: 0 + //instl: 0 } }] } From 801b05e7222680ece3bbd9db9d44bc79707e8ec4 Mon Sep 17 00:00:00 2001 From: "N. Faure" Date: Tue, 31 Jul 2018 17:36:38 +0200 Subject: [PATCH 0592/1594] Pass Prebid version and update IDs in Criteo bidding adapter (#2913) * Pass Prebid version to Criteo direct bidder * Update Criteo profile IDs --- modules/criteoBidAdapter.js | 10 ++++++---- test/spec/modules/criteoBidAdapter_spec.js | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 81da55ebf67..0595fc890f0 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -4,14 +4,15 @@ import { parse } from 'src/url'; import * as utils from 'src/utils'; import find from 'core-js/library/fn/array/find'; -const ADAPTER_VERSION = 8; +const ADAPTER_VERSION = 11; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; const INTEGRATION_MODES = { 'amp': 1, }; -const PROFILE_ID = 207; +const PROFILE_ID_INLINE = 207; +const PROFILE_ID_PUBLISHERTAG = 185; // Unminified source code can be found in: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js'; @@ -51,7 +52,7 @@ export const spec = { } if (publisherTagAvailable()) { - const adapter = new Criteo.PubTag.Adapters.Prebid(PROFILE_ID, ADAPTER_VERSION, bidRequests, bidderRequest); + const adapter = new Criteo.PubTag.Adapters.Prebid(PROFILE_ID_PUBLISHERTAG, ADAPTER_VERSION, bidRequests, bidderRequest, '$prebid.version$'); url = adapter.buildCdbUrl(); data = adapter.buildCdbRequest(); } else { @@ -156,8 +157,9 @@ function buildContext(bidRequests) { */ function buildCdbUrl(context) { let url = CDB_ENDPOINT; - url += '?profileId=' + PROFILE_ID; + url += '?profileId=' + PROFILE_ID_INLINE; url += '&av=' + String(ADAPTER_VERSION); + url += '&wv=' + encodeURIComponent('$prebid.version$'); url += '&cb=' + String(Math.floor(Math.random() * 99999999999)); if (context.integrationMode in INTEGRATION_MODES) { diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index e855c828b1f..6e2276d7e22 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -73,7 +73,7 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); @@ -113,7 +113,7 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); @@ -152,7 +152,7 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); From 58d24bf750c4d0796f45229938f62a869c3f03ec Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 31 Jul 2018 15:36:34 -0400 Subject: [PATCH 0593/1594] Prebid 1.18.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9b476ce1cb3..1fac6f44fc0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.18.0-pre", + "version": "1.18.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4cc2d1f7101342b508eb1a60e1a0bbdddec590c4 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 31 Jul 2018 15:46:26 -0400 Subject: [PATCH 0594/1594] increment prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1fac6f44fc0..10fe70d9e2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.18.0", + "version": "1.19.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 9d69f3d32321e29ae3c97e26bb5b930f383143f0 Mon Sep 17 00:00:00 2001 From: Arik Kfir Date: Wed, 1 Aug 2018 00:01:56 +0300 Subject: [PATCH 0595/1594] Add Gambid parameter "reqformat" to HTTP request (#2917) This parameter, while not yet required, is the preferred method of calling the Gambid server, and so as a best practice should be sent from the bid adapter as well. --- modules/gambidBidAdapter.js | 2 +- test/spec/modules/gambidBidAdapter_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/gambidBidAdapter.js b/modules/gambidBidAdapter.js index 63b45ad0d0a..6e1b6965cce 100644 --- a/modules/gambidBidAdapter.js +++ b/modules/gambidBidAdapter.js @@ -53,7 +53,7 @@ export const spec = { return validBidRequests.map(bidRequest => { const { adUnitCode, auctionId, mediaTypes, params, sizes, transactionId } = bidRequest; const baseEndpoint = params[ 'rtbEndpoint' ] || 'https://rtb.gambid.io'; - const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&bidder=prebid` + (params.query ? '&' + params.query : ''); + const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + (params.query ? '&' + params.query : ''); const rtbBidRequest = { 'id': auctionId, 'site': { diff --git a/test/spec/modules/gambidBidAdapter_spec.js b/test/spec/modules/gambidBidAdapter_spec.js index 0498de8790e..4c15d2113f1 100644 --- a/test/spec/modules/gambidBidAdapter_spec.js +++ b/test/spec/modules/gambidBidAdapter_spec.js @@ -72,13 +72,13 @@ describe('GambidAdapter', () => { response = spec.buildRequests([ bidRequest ])[ 0 ]; expect(response.method).to.equal('POST'); - expect(response.url).to.match(new RegExp(`^https://rtb\\.gambid\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&bidder=prebid$`, 'g')); + expect(response.url).to.match(new RegExp(`^https://rtb\\.gambid\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); expect(response.data.id).to.equal(bidRequest.auctionId); const bidRequestWithEndpoint = utils.deepClone(bidRequest); bidRequestWithEndpoint.params.rtbEndpoint = 'https://rtb2.gambid.io/a12'; response = spec.buildRequests([ bidRequestWithEndpoint ])[ 0 ]; - expect(response.url).to.match(new RegExp(`^https://rtb2\\.gambid\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&bidder=prebid$`, 'g')); + expect(response.url).to.match(new RegExp(`^https://rtb2\\.gambid\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); }); it('builds request correctly', () => { From a8580b58cf373e69f0fe733bd857f8b7d020a0a8 Mon Sep 17 00:00:00 2001 From: Shimogatsu Date: Wed, 1 Aug 2018 20:02:38 +0300 Subject: [PATCH 0596/1594] add between adapter (#2722) * add between adapter * add md dexcription about between adapter --- modules/betweenBidAdapter.js | 167 ++++++++++++++++++++ modules/betweenBidAdapter.md | 31 ++++ test/spec/modules/betweenBidAdapter_spec.js | 48 ++++++ 3 files changed, 246 insertions(+) create mode 100644 modules/betweenBidAdapter.js create mode 100644 modules/betweenBidAdapter.md create mode 100644 test/spec/modules/betweenBidAdapter_spec.js diff --git a/modules/betweenBidAdapter.js b/modules/betweenBidAdapter.js new file mode 100644 index 00000000000..005b7cdfe86 --- /dev/null +++ b/modules/betweenBidAdapter.js @@ -0,0 +1,167 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'between'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['btw'], + 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 !!(bid.params.w && bid.params.h && bid.params.s); + }, + /** + * 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) { + let requests = []; + validBidRequests.forEach(i => { + let params = { + jst: 'hb', + ord: Math.random() * 10000000000000000, + tz: get_tz(), + fl: get_fl(), + rr: get_rr(), + w: i.params.w, + h: i.params.h, + s: i.params.s, + bidid: i.bidId, + transactionid: i.transactionId, + auctionid: i.auctionId + }; + if (i.params.itu !== undefined) { + params.itu = i.params.itu; + } + if (i.params.cur !== undefined) { + params.cur = i.params.cur; + } + if (i.params.subid !== undefined) { + params.subid = i.params.subid; + } + if (i.params.click3rd !== undefined) { + params.click3rd = i.params.click3rd; + } + if (i.params.pubdata !== undefined) { + for (let key in i.params.pubdata) { + params['pubside_macro[' + key + ']'] = encodeURIComponent(i.params.pubdata[key]); + } + } + requests.push({method: 'GET', url: 'https://ads.betweendigital.com/adjson', data: params}) + }) + return requests; + }, + /** + * 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 = []; + for (var i = 0; i < serverResponse.body.length; i++) { + let bidResponse = { + requestId: serverResponse.body[i].bidid, + cpm: serverResponse.body[i].cpm || 123, + width: serverResponse.body[i].w || 200, + height: serverResponse.body[i].h || 400, + ttl: serverResponse.body[i].ttl || 120, + creativeId: serverResponse.body[i].creativeid || 123, + currency: serverResponse.body[i].currency || 'RUB', + netRevenue: serverResponse.body[i].netRevenue || false, + ad: serverResponse.body[i].ad + }; + 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) { + let syncs = [] + /* console.log(syncOptions,serverResponses) + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' + }); + } + if (syncOptions.pixelEnabled && serverResponses.length > 0) { + syncs.push({ + type: 'image', + url: serverResponses[0].body.userSync.url + }); + } */ + + syncs.push({ + type: 'iframe', + url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' + }) + return syncs; + } +} + +function get_rr() { + try { + var td = top.document; + var rr = td.referrer; + } catch (err) { return false } + + if (typeof rr != 'undefined' && rr.length > 0) { + return encodeURIComponent(rr); + } else if (typeof rr != 'undefined' && rr == '') { + return 'direct'; + } +} + +function get_fl() { + if (navigator.plugins !== undefined && navigator.plugins !== null) { + if (navigator.plugins['Shockwave Flash'] !== undefined && navigator.plugins['Shockwave Flash'] !== null && typeof navigator.plugins['Shockwave Flash'] === 'object') { + var description = navigator.plugins['Shockwave Flash'].description; + if (description && !(navigator.mimeTypes !== undefined && navigator.mimeTypes['application/x-shockwave-flash'] && !navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin)) { + description = description.replace(/^.*\s+(\S+\s+\S+$)/, '$1').replace(/^(.*)\..*$/, '$1'); + + return parseInt(description, 10); + } + } + } + + return 0; +} + +function get_tz() { + return new Date().getTimezoneOffset(); +} + +/* +function get_pubdata(adds) { + if (adds !== undefined && adds.pubdata !== undefined) { + let index = 0; + let url = ''; + for(var key in adds.pubdata) { + if (index == 0) { + url = url + encodeURIComponent('pubside_macro[' + key + ']') + '=' + encodeURIComponent(adds.pubdata[key]); + index++; + } else { + url = url + '&' + encodeURIComponent('pubside_macro[' + key + ']') + '=' + encodeURIComponent(adds.pubdata[key]); + } + } + return url; + } +} +*/ + +registerBidder(spec); diff --git a/modules/betweenBidAdapter.md b/modules/betweenBidAdapter.md new file mode 100644 index 00000000000..4ecd07e60bc --- /dev/null +++ b/modules/betweenBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +Module Name: Between Bidder Adapter +Module Type: Bidder Adapter +Maintainer: info@betweendigital.com + +# Description + +You can use this adapter to get a bid from betweendigital. + +About us : http://betweendigital.com + + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + bids: [ + { + bidder: "between", + params: { + w: 200, + h: 400, + s: 111 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/betweenBidAdapter_spec.js b/test/spec/modules/betweenBidAdapter_spec.js new file mode 100644 index 00000000000..a99417067f8 --- /dev/null +++ b/test/spec/modules/betweenBidAdapter_spec.js @@ -0,0 +1,48 @@ +import { expect } from 'chai'; +import { spec } from 'modules/betweenBidAdapter'; + +describe('betweenBidAdapterTests', () => { + it('validate_pub_params', () => { + expect(spec.isBidRequestValid({ + bidder: 'between', + params: { + placementId: 'example', + w: 240, + h: 400, + s: 1112 + } + })).to.equal(true); + }); + it('validate_generated_params', () => { + let bidRequestData = [{ + bidId: 'bid1234', + bidder: 'between', + params: {w: 240, h: 400, s: 1112, placementId: 'example'}, + sizes: [[240, 400]] + }] + let request = spec.buildRequests(bidRequestData); + let req_data = request[0].data; + expect(req_data.bidid).to.equal('bid1234'); + }); + it('validate_response_params', () => { + let serverResponse = { + body: [{ + bidid: 'bid1234', + cpm: 1.12, + w: 240, + h: 400, + currency: 'USD', + ad: 'Ad html' + }] + }; + let bids = spec.interpretResponse(serverResponse); + expect(bids).to.have.lengthOf(1); + let bid = bids[0]; + expect(bid.cpm).to.equal(1.12); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(240); + expect(bid.height).to.equal(400); + expect(bid.requestId).to.equal('bid1234'); + expect(bid.ad).to.equal('Ad html'); + }); +}); From 96c39dd317bd09770402414e24f6995c3fd0e56a Mon Sep 17 00:00:00 2001 From: guillaume-sticky Date: Wed, 1 Aug 2018 20:01:24 +0200 Subject: [PATCH 0597/1594] Solve custom download issues with freewheel-ssp bid adapter (#2910) * add stickyadsTV bidder adapter * init unit test file * ad some unit tests * fix unit test on ad format with parameters * add some unit tests * add unit tests on getBid method * add some test cases in unit tests * minor fix on component id tag. * remove adapters-sticky.json test file * use top most accessible window instead of window.top * Pass in the bid request in the createBid call. * use top most accessible window instead of window.top * add unit tests * update unit tests * fix unit test. * fix CI build * add alias freewheel-ssp * update unit tests on bidderCode value * fix component id values and add unit tests * allws to use any outstream format. * fix ASLoader on futur outstream format versions * minor: fix code format. * update unit tests * minor fix code format * minor: add missing new line at eof * replace StickyAdsTVAdapter by freewheel ssp bd adapter (for prebid 1.0) * remove old stickyadstv unittest spec. * fix server response parsing if sent as object with 'body' field * use the vastXml field for video mediatype * add user sync pixel in freewheel ssp adapter * remove all console log calls (replaced using util helper) * remove useless bidderCode (automatically added by the bidderFactory) * Return the SYNC pixel to be added in the page by Prebid.js * remove instance level properties to enable concurrent bids with the same adapter instance. * fix the request apss through and corresponding unit tests * fix 'freeheelssp' typo * add vast parameters feature and GDPR params in VAST request * fix lint issues * add gdpr parameter support on freewheelSSPBidAdapter * use bidderrequest to read gdpr parameters and update unit tests * fix lint errors * fix lint errors * fix typo and bidderRequest reference. * fix bidderRequest reference. * add missing declaration for 'key' variable * rename frewheel ssp bid adapter files to match the bidder code (fix custom download issues) * update unit tests using the new name freewheel-ssp --- ...dAdapter.js => freewheel-sspBidAdapter.js} | 0 ...dAdapter.md => freewheel-sspBidAdapter.md} | 0 ...pec.js => freewheel-sspBidAdapter_spec.js} | 394 +++++++++--------- 3 files changed, 197 insertions(+), 197 deletions(-) rename modules/{freewheelSSPBidAdapter.js => freewheel-sspBidAdapter.js} (100%) rename modules/{freewheelSSPBidAdapter.md => freewheel-sspBidAdapter.md} (100%) rename test/spec/modules/{freewheelSSPBidAdapter_spec.js => freewheel-sspBidAdapter_spec.js} (96%) diff --git a/modules/freewheelSSPBidAdapter.js b/modules/freewheel-sspBidAdapter.js similarity index 100% rename from modules/freewheelSSPBidAdapter.js rename to modules/freewheel-sspBidAdapter.js diff --git a/modules/freewheelSSPBidAdapter.md b/modules/freewheel-sspBidAdapter.md similarity index 100% rename from modules/freewheelSSPBidAdapter.md rename to modules/freewheel-sspBidAdapter.md diff --git a/test/spec/modules/freewheelSSPBidAdapter_spec.js b/test/spec/modules/freewheel-sspBidAdapter_spec.js similarity index 96% rename from test/spec/modules/freewheelSSPBidAdapter_spec.js rename to test/spec/modules/freewheel-sspBidAdapter_spec.js index ec4483fafed..00c725027a1 100644 --- a/test/spec/modules/freewheelSSPBidAdapter_spec.js +++ b/test/spec/modules/freewheel-sspBidAdapter_spec.js @@ -1,197 +1,197 @@ -import { expect } from 'chai'; -import { spec } from 'modules/freewheelSSPBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; - -const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; - -describe('freewheelSSP BidAdapter Test', () => { - const adapter = newBidder(spec); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - let bid = { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - - 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 zone id' - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', () => { - let bidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'gdprConsent': { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'gdprApplies': true - } - } - ]; - - it('should add parameters to the tag', () => { - const request = spec.buildRequests(bidRequests, bidRequests[0]); - const payload = request.data; - expect(payload.reqType).to.equal('AdsSetup'); - expect(payload.protocolVersion).to.equal('2.0'); - expect(payload.zoneId).to.equal('277225'); - expect(payload.componentId).to.equal('mustang'); - expect(payload.playerSize).to.equal('300x600'); - expect(payload._fw_gdpr).to.equal(true); - expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); - }); - - it('sends bid request to ENDPOINT via GET', () => { - const request = spec.buildRequests(bidRequests, bidRequests[0]); - expect(request.url).to.contain(ENDPOINT); - expect(request.method).to.equal('GET'); - }); - }) - - describe('interpretResponse', () => { - let bidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - let formattedBidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225', - 'format': 'floorad' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[600, 250], [300, 600]], - 'bidId': '30b3other1c1838de1e', - 'bidderRequestId': '22edbae273other3bf6', - 'auctionId': '1d1a03079test0a475', - }, - { - 'bidder': 'stickyadstv', - 'params': { - 'zoneId': '277225', - 'format': 'test' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 600]], - 'bidId': '2', - 'bidderRequestId': '3', - 'auctionId': '4', - } - ]; - - let response = '' + - '' + - ' ' + - ' Adswizz' + - ' ' + - ' ' + - ' ' + - ' 00:00:09' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' 0.2000' + - ' ' + - ' ' + - ' ' + - ''; - - let ad = '
'; - let formattedAd = '
'; - - it('should get correct bid response', () => { - var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - - let expectedResponse = [ - { - requestId: '30b31c1838de1e', - cpm: '0.2000', - width: 300, - height: 600, - creativeId: '28517153', - currency: 'EUR', - netRevenue: true, - ttl: 360, - ad: ad - } - ]; - - let result = spec.interpretResponse(response, request); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - - it('should get correct bid response with formated ad', () => { - var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - - let expectedResponse = [ - { - requestId: '30b31c1838de1e', - cpm: '0.2000', - width: 300, - height: 600, - creativeId: '28517153', - currency: 'EUR', - netRevenue: true, - ttl: 360, - ad: formattedAd - } - ]; - - let result = spec.interpretResponse(response, request); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - - it('handles nobid responses', () => { - var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - let response = ''; - - let result = spec.interpretResponse(response, reqest); - expect(result.length).to.equal(0); - }); - }); -}); +import { expect } from 'chai'; +import { spec } from 'modules/freewheel-sspBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; + +describe('freewheel-ssp BidAdapter Test', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 zone id' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'gdprConsent': { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'gdprApplies': true + } + } + ]; + + it('should add parameters to the tag', () => { + const request = spec.buildRequests(bidRequests, bidRequests[0]); + const payload = request.data; + expect(payload.reqType).to.equal('AdsSetup'); + expect(payload.protocolVersion).to.equal('2.0'); + expect(payload.zoneId).to.equal('277225'); + expect(payload.componentId).to.equal('mustang'); + expect(payload.playerSize).to.equal('300x600'); + expect(payload._fw_gdpr).to.equal(true); + expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + }); + + it('sends bid request to ENDPOINT via GET', () => { + const request = spec.buildRequests(bidRequests, bidRequests[0]); + expect(request.url).to.contain(ENDPOINT); + expect(request.method).to.equal('GET'); + }); + }) + + describe('interpretResponse', () => { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + let formattedBidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225', + 'format': 'floorad' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[600, 250], [300, 600]], + 'bidId': '30b3other1c1838de1e', + 'bidderRequestId': '22edbae273other3bf6', + 'auctionId': '1d1a03079test0a475', + }, + { + 'bidder': 'stickyadstv', + 'params': { + 'zoneId': '277225', + 'format': 'test' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 600]], + 'bidId': '2', + 'bidderRequestId': '3', + 'auctionId': '4', + } + ]; + + let response = '' + + '' + + ' ' + + ' Adswizz' + + ' ' + + ' ' + + ' ' + + ' 00:00:09' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 0.2000' + + ' ' + + ' ' + + ' ' + + ''; + + let ad = '
'; + let formattedAd = '
'; + + it('should get correct bid response', () => { + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: ad + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('should get correct bid response with formated ad', () => { + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: formattedAd + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', () => { + var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + let response = ''; + + let result = spec.interpretResponse(response, reqest); + expect(result.length).to.equal(0); + }); + }); +}); From a8b0b3e76c361c47898f1377658174ab965310d3 Mon Sep 17 00:00:00 2001 From: devBizzclick <41024425+devBizzclick@users.noreply.github.com> Date: Wed, 1 Aug 2018 21:07:21 +0300 Subject: [PATCH 0598/1594] BizzClick SSP header bidding adapter (#2877) * BizzClick Adapter Added * code style & example --- integrationExamples/gpt/pbjs_example_gpt.html | 15 +++ modules/bizzclickBidAdapter.js | 105 ++++++++++++++++ modules/bizzclickBidAdapter.md | 27 ++++ test/spec/modules/bizzclickBidAdapter_spec.js | 117 ++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 modules/bizzclickBidAdapter.js create mode 100644 modules/bizzclickBidAdapter.md create mode 100644 test/spec/modules/bizzclickBidAdapter_spec.js diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index fbf21f1f856..536bc5a655d 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -289,6 +289,13 @@ host: 'dsp-staging.adkernel.com' //OPTIONAL } }, + { + bidder: 'bizzclick', + params: { + placementId: 0, + type: "banner" + } + }, { bidder: 'zedo', params: { @@ -296,6 +303,7 @@ dimId: 9 //REQUIRED } } + ] }, { code: 'div-gpt-ad-12345678-1', @@ -427,6 +435,13 @@ params: { zone: '276' // REQUIRED Zone Id (276 is a test zone) } + }, + { + bidder: 'bizzclick', + params: { + placementId: 0, + type: "banner" + } } ] } diff --git a/modules/bizzclickBidAdapter.js b/modules/bizzclickBidAdapter.js new file mode 100644 index 00000000000..62ada43b970 --- /dev/null +++ b/modules/bizzclickBidAdapter.js @@ -0,0 +1,105 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'bizzclick'; +const URL = '//supply.bizzclick.com/?c=o&m=multi'; +const URL_SYNC = '//supply.bizzclick.com/?c=o&m=cookie'; + +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); + } + return false; +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + /** + * 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: (bid) => { + return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placementId) && bid.params.type); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: (validBidRequests) => { + let winTop = window; + try { + window.top.location.toString(); + winTop = window.top; + } catch (e) { + utils.logMessage(e); + }; + const location = utils.getTopWindowLocation(); + const placements = []; + const len = validBidRequests.length; + for (let i = 0; i < len; i++) { + const bid = validBidRequests[i]; + const placement = { + placementId: bid.params.placementId, + bidId: bid.bidId, + sizes: bid.sizes, + type: bid.params.type + }; + placements.push(placement); + } + return { + method: 'POST', + url: URL, + data: { + 'deviceWidth': winTop.screen.width, + 'deviceHeight': winTop.screen.height, + 'secure': (location.protocol === 'https:') ? 1 : 0, + 'host': location.host, + 'page': location.pathname, + 'placements': placements + } + }; + }, + + /** + * 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: (bidResponses) => { + const res = []; + bidResponses = bidResponses.body; + const len = bidResponses.length; + for (let i = 0; i < len; i++) { + const bid = bidResponses[i]; + if (isBidResponseValid(bid)) { + res.push(bid); + } + } + return res; + }, + + getUserSyncs: () => { + return [{ + type: 'image', + url: URL_SYNC + }]; + } +}; + +registerBidder(spec); diff --git a/modules/bizzclickBidAdapter.md b/modules/bizzclickBidAdapter.md new file mode 100644 index 00000000000..7dfa458b34c --- /dev/null +++ b/modules/bizzclickBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +``` +Module Name: BizzClick SSP Bidder Adapter +Module Type: Bidder Adapter +Maintainer: support@bizzclick.com +``` + +# Description + +Module that connects to BizzClick SSP demand sources + +# Test Parameters +``` + var adUnits = [{ + code: 'placementId', + sizes: [[300, 250]], + bids: [{ + bidder: 'bizzclick', + params: { + placementId: 0, + type: 'banner' + } + }] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/bizzclickBidAdapter_spec.js b/test/spec/modules/bizzclickBidAdapter_spec.js new file mode 100644 index 00000000000..39587791bba --- /dev/null +++ b/test/spec/modules/bizzclickBidAdapter_spec.js @@ -0,0 +1,117 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/bizzclickBidAdapter'; + +describe('BizzclickBidAdapter', () => { + let bid = { + bidId: '67d581a232281d', + bidder: 'bizzclickBidAdapter', + bidderRequestId: 'a7837c9145e136', + params: { + placementId: 0, + type: 'banner' + }, + placementCode: 'placementId', + auctionId: 'bfe951372e62-a92d-4cf1-869f-d24029', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-1b244bbfb5' + }; + + describe('isBidRequestValid', () => { + it('Should return true when placement_id can be cast to a number', () => { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when placement_id is not a number', () => { + bid.params.placementId = 'aaa'; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', () => { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', () => { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', () => { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', () => { + expect(serverRequest.url).to.equal('//supply.bizzclick.com/?c=o&m=multi'); + }); + it('Returns valid data if array of bids is valid', () => { + let data = serverRequest.data; + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'secure', 'host', 'page', 'placements'); + expect(data.deviceWidth).to.be.a('number'); + expect(data.deviceHeight).to.be.a('number'); + 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', 'bidId', 'type', 'sizes'); + expect(placement.placementId).to.be.a('number'); + expect(placement.bidId).to.be.a('string'); + expect(placement.type).to.be.a('string'); + expect(placement.sizes).to.be.an('array'); + } + }); + it('Returns empty data if no valid requests are passed', () => { + serverRequest = spec.buildRequests([]); + let data = serverRequest.data; + expect(data.placements).to.be.an('array').that.is.empty; + }); + }); + describe('interpretResponse', () => { + let resObject = { + body: [ { + requestId: '123', + mediaType: 'banner', + cpm: 0.3, + width: 320, + height: 50, + ad: '

Hello ad

', + ttl: 1000, + creativeId: '123asd', + netRevenue: true, + currency: 'USD' + }] + }; + let serverResponses = spec.interpretResponse(resObject); + it('Returns an array of valid server responses if response object is valid', () => { + 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'); + 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'); + } + it('Returns an empty array if invalid response is passed', () => { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); + + describe('getUserSyncs', () => { + let userSync = spec.getUserSyncs(); + it('Returns valid URL and type', () => { + 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('//supply.bizzclick.com/?c=o&m=cookie'); + }); + }); +}); From 9cb61aa88d17399f8fab9bb379b383efd9eb02c6 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Wed, 1 Aug 2018 15:37:57 -0400 Subject: [PATCH 0599/1594] switch to circleci instead of travis-ci (#2895) * circleci test * test push * update docker image * update docker image * sudo * add npm cache, update to use browserstack * update env vars * download local binary * download local binary * run in background * rename key * include circleci test * echo username * echo username * remove local identifier * remove .travis.yml --- .circleci/config.yml | 50 ++++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 29 ------------------------- README.md | 2 +- 3 files changed, 51 insertions(+), 30 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 .travis.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000000..62c23390666 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,50 @@ +# Javascript Node CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-javascript/ for more details +# +version: 2 +jobs: + build: + docker: + # specify the version you desire here + - image: circleci/node:7.10 + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/mongo:3.4.4 + + working_directory: ~/Prebid.js + + steps: + - checkout + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: sudo npm install -g gulp + # Download and run BrowserStack local + - run: + name : Download BrowserStack Local binary and start it. + command : | + # Download the browserstack binary file + wget "https://www.browserstack.com/browserstack-local/BrowserStackLocal-linux-x64.zip" + # Unzip it + unzip BrowserStackLocal-linux-x64.zip + # Run the file with user's access key + ./BrowserStackLocal ${BROWSERSTACK_ACCESS_KEY} & + # run tests! + - run: + name: BrowserStack testing + command: gulp test --browserstack diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bd4df66b5b0..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -sudo: required -dist: trusty -language: node_js -node_js: -- '7.0' -env: -- BROWSERSTACK_USERNAME=info184 -addons: - chrome: stable - browserstack: - username: info184 - access_key: - secure: Ru286R4pMcEIRKwb2AoaaJY6lEKIzeZraxY7CtbOP4ykNk7uqsnyitk4QwxpCCh0n35b71m30okW6ZmZnl0lJXhOMdYoSOYBAnUw2Vn7Y93oMSKIC5dc2/qmtF1t2b1qX65/Ont2iJUj+UY8VQw5Hk2vIT4/5wifYPBnV5ILK4AI7SVk/ma7OzK4rkp3WThlouddctAd7tx4O3YIyJKDi9lkfcMA0pnH4OZSOlDClRLIy50Q1NE+iyqHtWFZK1TwJ+IhQbSsCLbuyQJBRnyJJEftNmtrs5MCZt/9pwFDj7c8+o11F6HCsTBYFkehFRfbKnmhCc1G+bsNXY8OxIWwEHeuVmSGK7TDPYcPPQBc03mcQ1fY/IPNQOdsVJ/n8RsG2u0IU2CF2hhkuNFzeov7dOHljanc45NKOrLdjwzP1aZCAUvLquOTzvmdF23nJhMs8UO+Du4kTK5VfmKyz1MC91E40a0Q15+O4qmS39rNOlwhxPJSfuxxL1jKVPJ7PsFbTkGM8M/XPJ6dyGLufy225HjdLdJTAOa5BZ4st+nXH/AzqHzy6a2I5vTmAz1j4gHLgVU+iNxAkX8znb25s3Rs1ZuFVj+aBSBmNoQA1FA5f/uXWeruTdDig7ksp+XdjsjLm9Md8cWwYaEn04FYj1ztJrylrEMfnc0Kcs6zQ3fll1g= -before_install: -- npm install -g gulp -- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & -script: |- - if [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then - gulp test --browserstack - else - gulp run-tests - fi -notifications: - slack: - on_success: never - on_failure: always - on_pull_requests: false - rooms: - - secure: C4O77VtABLE5DiPDeKGqUcsBdTBMNjQRLc8iBfSp231e95K1rA/JXJJEQN/lVhhiFJyPhxueE0i6cR0zD8uAMC8HRShGGfPjEZ7f6glawPzap2wFwjAyVkknYV+BMKcX0jvn7CiSKBj+zTbHQfn/Uj3nMSbDZQIdbNDiFGh4NuDr3/Yd/efhsw/miExlSPSWqGVCKV3WPpTrU3BRpLNDq4sZMXP9ORZxGK7ER3tsMiD2z05YpvC+mibESJxaY0qsuQu1y1Gu65QLPe5ocw405btJwqYn+b4YFpUd2GbLNhjtLzsc+OKrD0DWuEI0bxePQUYDga5wR6g4cdZaXU3ixDjee7sJbDeVJAuykGlfZ4A1k+fQIgPs3s9XMHaeG9AfDhFiZ/UoNdonzos1iSa/Y1TzHIXp1wnbHKT5HUWWPFNb5PzJxHEtHbm3jwOH4iK8VAq94ec16M2aqUAj7muiqcrTlYa5rs6jRlXo/TRymFnbQRdBT7eLmLNDQD35yR1Y+4mxHqKi+3189yG9RE+uwIlB+9HZFgNbioOApB+jarKC6M0qEgn0bHxkpJBP8JmNCA84U0ZUzyPvuMGsRbisAmKoUsU8C6cq59QDfBTcCTvKXK6r+6f23iRGieoGSbTxYQj46QkykpbWU0WstQDQsZL3L316uZecOVZmWKBRxPs= diff --git a/README.md b/README.md index 946d6755774..fa3a11fbb88 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/prebid/Prebid.js.svg?branch=master)](https://travis-ci.org/prebid/Prebid.js) +[![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) From 16a621bc190cd6334d83a5ffddc90dc1f2a4bc6a Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 1 Aug 2018 13:50:46 -0600 Subject: [PATCH 0600/1594] don't allow null or undefined bid properties (#2923) --- src/adapters/bidderFactory.js | 2 +- test/spec/unit/core/bidderFactory_spec.js | 30 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index d8b55f94f9c..8e359d98259 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -381,7 +381,7 @@ function validBidSize(adUnitCode, bid, bidRequests) { export function isValid(adUnitCode, bid, bidRequests) { function hasValidKeys() { let bidKeys = Object.keys(bid); - return COMMON_BID_RESPONSE_KEYS.every(key => includes(bidKeys, key)); + return COMMON_BID_RESPONSE_KEYS.every(key => includes(bidKeys, key) && !includes([undefined, null], bid[key])); } function errorMessage(msg) { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index ca2a9afc103..d1422cb1496 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -427,6 +427,36 @@ describe('bidders created by newBidder', () => { expect(logErrorSpy.calledOnce).to.equal(true); }); + + it('should logError when required bid response params are undefined', () => { + const bidder = newBidder(spec); + + const bid = { + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'requestId': '1', + 'creativeId': 'some-id', + 'currency': undefined, + '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); + + expect(logErrorSpy.calledOnce).to.equal(true); + }); }); describe('when the ajax call fails', () => { From 47d3c3eb937a9912e4c4a8c1cdbff7315afc64b9 Mon Sep 17 00:00:00 2001 From: Steve Alliance Date: Wed, 1 Aug 2018 19:18:22 -0400 Subject: [PATCH 0601/1594] update dmx adapter file name part 2 (#2911) * adding DMX test @97%, two files added one updated * Update districtm_spec.js * Update districtmDMX.js * adding all districtm needed file * remove legacy file * remove typo || 0 in the test method * force default to return a valid width and height * update unit test code for failing test * changed class for an object * remove package-lock.json * change file name for dmx adapter * renamed files * restaure package-lock.json * update to last package-lock state --- modules/{districtmDmxAdapter.js => districtmDmxBidAdapter.js} | 0 modules/{districtmDmxAdapter.md => districtmDmxBidAdapter.md} | 0 ...strictmDmxAdapter_spec.js => districtmDmxBidAdapter_spec.js} | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename modules/{districtmDmxAdapter.js => districtmDmxBidAdapter.js} (100%) rename modules/{districtmDmxAdapter.md => districtmDmxBidAdapter.md} (100%) rename test/spec/modules/{districtmDmxAdapter_spec.js => districtmDmxBidAdapter_spec.js} (99%) diff --git a/modules/districtmDmxAdapter.js b/modules/districtmDmxBidAdapter.js similarity index 100% rename from modules/districtmDmxAdapter.js rename to modules/districtmDmxBidAdapter.js diff --git a/modules/districtmDmxAdapter.md b/modules/districtmDmxBidAdapter.md similarity index 100% rename from modules/districtmDmxAdapter.md rename to modules/districtmDmxBidAdapter.md diff --git a/test/spec/modules/districtmDmxAdapter_spec.js b/test/spec/modules/districtmDmxBidAdapter_spec.js similarity index 99% rename from test/spec/modules/districtmDmxAdapter_spec.js rename to test/spec/modules/districtmDmxBidAdapter_spec.js index d3ab685e20c..cfdab445f71 100644 --- a/test/spec/modules/districtmDmxAdapter_spec.js +++ b/test/spec/modules/districtmDmxBidAdapter_spec.js @@ -1,6 +1,6 @@ import {expect} from 'chai'; import * as _ from 'lodash'; -import {spec, matchRequest, checkDeepArray, defaultSize} from '../../../modules/districtmDmxAdapter'; +import {spec, matchRequest, checkDeepArray, defaultSize} from '../../../modules/districtmDmxBidAdapter'; const bidRequest = [{ 'bidder': 'districtmDMX', From c1a04f17cc19127c966db9b9500e6c1d88f96500 Mon Sep 17 00:00:00 2001 From: Arik Kfir Date: Thu, 2 Aug 2018 18:45:18 +0300 Subject: [PATCH 0602/1594] Pass the "vastUrl" property from the bid to the outstream renderer (#2918) * Pass the "vastUrl" property from the bid to the outstream renderer * Fix name of "bidRequest" parameter in "newRenderer" method * Support using server-provided URL of outstream video renderer * Support using publisher-provided URL of outstream video renderer * Fix lint & mixed operators warning --- modules/gambidBidAdapter.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/gambidBidAdapter.js b/modules/gambidBidAdapter.js index 6e1b6965cce..f7026f9c76f 100644 --- a/modules/gambidBidAdapter.js +++ b/modules/gambidBidAdapter.js @@ -134,7 +134,7 @@ export const spec = { mediaType: 'video', vastUrl: bid.ext.vast_url, vastXml: bid.adm, - renderer: context === 'outstream' ? newRenderer(bidRequest, bid) : undefined + renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined })); } }); @@ -174,9 +174,9 @@ export const spec = { } }; -function newRenderer(adUnitCode, bid, rendererOptions = {}) { +function newRenderer(bidRequest, bid, rendererOptions = {}) { const renderer = Renderer.install({ - url: '//s.gamoshi.io/video/latest/renderer.js', + url: (bidRequest.params && bidRequest.params.rendererUrl) || (bid.ext && bid.ext.renderer_url) || '//s.gamoshi.io/video/latest/renderer.js', config: rendererOptions, loaded: false, }); @@ -202,6 +202,7 @@ function renderOutstream(bid) { window['GamoshiPlayer'].removeAd(unitId); }, 300) }, + vastUrl: bid.vastUrl, vastXml: bid.vastXml }); }); From a568fdf3c377dce4552d6923fd2c459536cb13b6 Mon Sep 17 00:00:00 2001 From: Rade Popovic <32302052+nanointeractive@users.noreply.github.com> Date: Thu, 2 Aug 2018 17:51:28 +0200 Subject: [PATCH 0603/1594] Sending window location to server if possible (#2914) * nanointeractive bid adapter * nanointeractive bid adapter * - using utils.getParameterByName instead of utils.getTopWindowLocation().href - bidderCode is removed - Default ALG changed to 'ihr' - added protocol to 'cors' param * markdown file * enabling localhost for bid requests * Bugfix interpretResponse - added body; Removed unnecessary parameters; Adjusted tests; * New feature - subId * Fixed lint errors * Nano Interactive Bid Adapter New Bid params: - categoryName - name Getting referrer information * Fixed documentation * Removed unnecessary parameter from documentation * Cleaning up documentation * - Sending window location to server if possible * - Lint errors fix * Using utils.js method for sending location to server * Removing unnecessary parameter passing --- modules/nanointeractiveBidAdapter.js | 6 + .../modules/nanointeractiveBidAdapter_spec.js | 728 ++++++------------ 2 files changed, 243 insertions(+), 491 deletions(-) diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index afcfef1f5b6..a1eab2cbbb2 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -12,6 +12,7 @@ export const CATEGORY = 'category'; export const CATEGORY_NAME = 'categoryName'; export const SUB_ID = 'subId'; export const REF = 'ref'; +export const LOCATION = 'loc'; export const spec = { @@ -52,6 +53,7 @@ function createSingleBidRequest (bid) { sizes: bid.sizes.map(value => value[0] + 'x' + value[1]), bidId: bid.bidId, cors: utils.getOrigin(), + [LOCATION]: createLocationParam(), }; } @@ -85,6 +87,10 @@ function createRefParam (bid) { return bid.params[REF] ? null : utils.getTopWindowReferrer() || null; } +function createLocationParam () { + return utils.getTopWindowLocation().href; +} + function isEngineResponseValid (response) { return !!response.cpm && !!response.ad; } diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index f93cc546859..1aecb8ab06b 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -20,7 +20,8 @@ describe('nanointeractive adapter tests', function () { const BID_ID_PARAM = 'bidId'; const BID_ID_VALUE = '24a1c9ec270973'; const CORS_PARAM = 'cors'; - const DATA_PARTNER_PIXEL_ID_VALUE = 'pid1'; + const LOC_PARAM = 'loc'; + const DATA_PARTNER_PIXEL_ID_VALUE = 'testPID'; const NQ_VALUE = 'rumpelstiltskin'; const NQ_NAME_QUERY_PARAM = 'nqName'; const CATEGORY_VALUE = 'some category'; @@ -36,7 +37,7 @@ describe('nanointeractive adapter tests', function () { const AD = ' '; const CPM = 1; - function getBidResponse (pid, nq, category, subId, cors, ref) { + function getBidResponse (pid, nq, category, subId, cors, ref, loc) { return { [DATA_PARTNER_PIXEL_ID]: pid, [NQ]: nq, @@ -46,8 +47,10 @@ describe('nanointeractive adapter tests', function () { [SIZES_PARAM]: [WIDTH1 + 'x' + HEIGHT1, WIDTH2 + 'x' + HEIGHT2], [BID_ID_PARAM]: BID_ID_VALUE, [CORS_PARAM]: cors, + [LOC_PARAM]: loc, }; } + function getBidRequest (params) { return { bidder: BIDDER_CODE, @@ -187,12 +190,33 @@ describe('nanointeractive adapter tests', function () { [SUB_ID]: SUB_ID_VALUE, }))).to.equal(false); }); - it('Test buildRequest() - pid', function () { + + let sandbox; + + function getMocks () { + let mockWindowLocationAddress = 'http://some-location.test'; let mockOriginAddress = 'http://localhost'; let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + return { + 'windowLocationAddress': mockWindowLocationAddress, + 'originAddress': mockOriginAddress, + 'refAddress': mockRefAddress, + }; + } + + function setUpMocks (mockRefAddress = null) { + sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => getMocks()['originAddress']); + sandbox.stub(utils, 'getTopWindowLocation').callsFake(() => { + return { + 'href': getMocks()['windowLocationAddress'] + }; + }); + if (mockRefAddress == null) { + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => getMocks()['refAddress']); + } else { + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + } sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { switch (arg) { case CATEGORY_NAME_QUERY_PARAM: @@ -201,520 +225,242 @@ describe('nanointeractive adapter tests', function () { return NQ_VALUE; } }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [null], - expectedCategory: [null], - expectedSubId: null, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); + } + + function assert ( + request, + expectedPid, + expectedNq, + expectedCategory, + expectedSubId, + expectedRef = getMocks()['refAddress'], + expectedOrigin = getMocks()['originAddress'], + expectedLocation = getMocks()['windowLocationAddress'] + ) { expect(request.method).to.equal('POST'); expect(request.url).to.equal(ENGINE_BASE_URL); expect(request.data).to.equal(JSON.stringify([ getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef + expectedPid, + expectedNq, + expectedCategory, + expectedSubId, + expectedOrigin, + expectedRef, + expectedLocation, ), ])); + } + + function tearDownMocks () { sandbox.restore(); + } + + it('Test buildRequest() - pid', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [null]; + let expectedCategory = [null]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, nq', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [NQ_VALUE], - expectedCategory: [null], - expectedSubId: null, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [null]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, nq, category', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY]: CATEGORY_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [NQ_VALUE], - expectedCategory: [CATEGORY_VALUE], - expectedSubId: null, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, nq, categoryName', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [NQ_VALUE], - expectedCategory: [CATEGORY_VALUE], - expectedSubId: null, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, nq, subId', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [SUB_ID]: SUB_ID_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [NQ_VALUE], - expectedCategory: [null], - expectedSubId: SUB_ID_VALUE, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [null]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, category', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [CATEGORY]: CATEGORY_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [null], - expectedCategory: [CATEGORY_VALUE], - expectedSubId: null, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [null]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, category, subId', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [CATEGORY]: CATEGORY_VALUE, - [SUB_ID]: SUB_ID_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [null], - expectedCategory: [CATEGORY_VALUE], - expectedSubId: SUB_ID_VALUE, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [null]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, subId', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [SUB_ID]: SUB_ID_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [null], - expectedCategory: [null], - expectedSubId: SUB_ID_VALUE, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [null]; + let expectedCategory = [null]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, nq, category, subId', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY]: CATEGORY_VALUE, - [SUB_ID]: SUB_ID_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [NQ_VALUE], - expectedCategory: [CATEGORY_VALUE], - expectedSubId: SUB_ID_VALUE, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, nqName, categoryName, subId', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ_NAME]: NQ_NAME_QUERY_PARAM, - [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, - [SUB_ID]: SUB_ID_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [NQ_VALUE], - expectedCategory: [CATEGORY_VALUE], - expectedSubId: SUB_ID_VALUE, - expectedCors: mockOriginAddress, - expectedRef: mockRefAddress, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); }); it('Test buildRequest() - pid, nq, category, subId, ref (value none)', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY]: CATEGORY_VALUE, - [SUB_ID]: SUB_ID_VALUE, - [REF]: REF_NO_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [NQ_VALUE], - expectedCategory: [CATEGORY_VALUE], - expectedSubId: SUB_ID_VALUE, - expectedCors: mockOriginAddress, - expectedRef: null, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(null); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_NO_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId, null); + tearDownMocks(); }); it('Test buildRequest() - pid, nq, category, subId, ref (value other)', function () { - let mockOriginAddress = 'http://localhost'; - let mockRefAddress = 'http://some-ref.test'; - let sandbox = sinon.sandbox.create(); - sandbox.stub(utils, 'getOrigin').callsFake(() => mockOriginAddress); - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { - switch (arg) { - case CATEGORY_NAME_QUERY_PARAM: - return CATEGORY_VALUE; - case NQ_NAME_QUERY_PARAM: - return NQ_VALUE; - } - }); - let testInput = - { - requestParams: { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY]: CATEGORY_VALUE, - [SUB_ID]: SUB_ID_VALUE, - [REF]: REF_OTHER_VALUE, - }, - expectedPid: DATA_PARTNER_PIXEL_ID_VALUE, - expectedNq: [NQ_VALUE], - expectedCategory: [CATEGORY_VALUE], - expectedSubId: SUB_ID_VALUE, - expectedCors: mockOriginAddress, - expectedRef: null, - }; - let request = nanoBidAdapter.buildRequests([ - getBidRequest(testInput.requestParams)]); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - testInput.expectedPid, - testInput.expectedNq, - testInput.expectedCategory, - testInput.expectedSubId, - testInput.expectedCors, - testInput.expectedRef - ), - ])); - sandbox.restore(); + setUpMocks(null); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_OTHER_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId, null); + tearDownMocks(); }); it('Test interpretResponse() length', function () { let bids = nanoBidAdapter.interpretResponse({ From 198013edf0506126e1f7a99378a5da00e2256d7c Mon Sep 17 00:00:00 2001 From: John Rosendahl Date: Fri, 3 Aug 2018 06:11:44 -0600 Subject: [PATCH 0604/1594] 1206 eslint repair camel case (#2925) * Camel Case issues addresed * after merge cleanup * updated between adapter --- .eslintrc.js | 1 - modules/adkernelAdnBidAdapter.js | 2 +- modules/adkernelBidAdapter.js | 2 +- modules/andbeyondBidAdapter.js | 2 +- modules/audienceNetworkBidAdapter.js | 12 ++++---- modules/betweenBidAdapter.js | 12 ++++---- modules/bridgewellBidAdapter.js | 40 +++++++++++++------------- modules/etargetBidAdapter.js | 10 +++---- modules/nasmediaAdmixerBidAdapter.js | 4 +-- modules/polluxBidAdapter.js | 24 ++++++++-------- modules/realvuAnalyticsAdapter.js | 42 ++++++++++++++-------------- modules/rtbdemandadkBidAdapter.js | 2 +- modules/rtbhouseBidAdapter.js | 4 +-- modules/rubiconBidAdapter.js | 10 +++---- modules/sekindoUMBidAdapter.js | 2 +- modules/sonobiBidAdapter.js | 10 +++---- modules/trionBidAdapter.js | 20 ++++++------- modules/underdogmediaBidAdapter.js | 6 ++-- modules/widespaceBidAdapter.js | 2 +- package-lock.json | 5 +++- src/auction.js | 22 +++++++-------- src/utils.js | 24 ++++++++-------- 22 files changed, 130 insertions(+), 128 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index e6975951f06..02ff81614c7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -26,7 +26,6 @@ module.exports = { // Violations of these styles should be fixed, and the exceptions removed over time. // // See Issue #1111. - "camelcase": "off", "eqeqeq": "off", "no-return-assign": "off", "no-throw-literal": "off", diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index e20f58d43f6..60c33170b3c 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -165,7 +165,7 @@ export const spec = { return serverResponses.filter(rps => rps.body && rps.body.syncpages) .map(rsp => rsp.body.syncpages) .reduce((a, b) => a.concat(b), []) - .map(sync_url => ({type: 'iframe', url: sync_url})); + .map(syncUrl => ({type: 'iframe', url: syncUrl})); } }; diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index e9f88e9a3ef..dffcaacec3d 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -87,7 +87,7 @@ export const spec = { return serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.adk_usersync) .map(rsp => rsp.body.ext.adk_usersync) .reduce((a, b) => a.concat(b), []) - .map(sync_url => ({type: 'iframe', url: sync_url})); + .map(syncUrl => ({type: 'iframe', url: syncUrl})); } }; diff --git a/modules/andbeyondBidAdapter.js b/modules/andbeyondBidAdapter.js index 1a3535f4704..710d75aec6d 100644 --- a/modules/andbeyondBidAdapter.js +++ b/modules/andbeyondBidAdapter.js @@ -86,7 +86,7 @@ export const spec = { return serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.adk_usersync) .map(rsp => rsp.body.ext.adk_usersync) .reduce((a, b) => a.concat(b), []) - .map(sync_url => ({type: 'iframe', url: sync_url})); + .map(syncUrl => ({type: 'iframe', url: syncUrl})); } }; diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 7256ce99e73..5e9053dfc40 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -14,7 +14,7 @@ const method = 'GET'; const url = 'https://an.facebook.com/v2/placementbid.json'; const supportedMediaTypes = ['banner', 'video']; const netRevenue = true; -const hb_bidder = 'fan'; +const hbBidder = 'fan'; const platver = '$prebid.version$'; const platform = '241394079772386'; const adapterver = '1.0.0'; @@ -205,14 +205,14 @@ const interpretResponse = ({ body }, { adformats, requestIds, sizes }) => { // transform to bidResponse .map((bid, i) => { const { - bid_id: fb_bidid, + bid_id: fbBidid, placement_id: creativeId, bid_price_cents: cpm } = bid; const format = adformats[i]; const [width, height] = expandSize(flattenSize(sizes[i])); - const ad = createAdHtml(creativeId, format, fb_bidid); + const ad = createAdHtml(creativeId, format, fbBidid); const requestId = requestIds[i]; const bidResponse = { @@ -227,8 +227,8 @@ const interpretResponse = ({ body }, { adformats, requestIds, sizes }) => { netRevenue, currency, // Audience Network attributes - hb_bidder, - fb_bidid, + hb_bidder: hbBidder, + fb_bidid: fbBidid, fb_format: format, fb_placementid: creativeId }; @@ -236,7 +236,7 @@ const interpretResponse = ({ body }, { adformats, requestIds, sizes }) => { if (isVideo(format)) { const pageurl = getTopWindowUrlEncoded(); bidResponse.mediaType = 'video'; - bidResponse.vastUrl = `https://an.facebook.com/v1/instream/vast.xml?placementid=${creativeId}&pageurl=${pageurl}&playerwidth=${width}&playerheight=${height}&bidid=${fb_bidid}`; + bidResponse.vastUrl = `https://an.facebook.com/v1/instream/vast.xml?placementid=${creativeId}&pageurl=${pageurl}&playerwidth=${width}&playerheight=${height}&bidid=${fbBidid}`; } return bidResponse; }); diff --git a/modules/betweenBidAdapter.js b/modules/betweenBidAdapter.js index 005b7cdfe86..98140fe68e6 100644 --- a/modules/betweenBidAdapter.js +++ b/modules/betweenBidAdapter.js @@ -27,9 +27,9 @@ export const spec = { let params = { jst: 'hb', ord: Math.random() * 10000000000000000, - tz: get_tz(), - fl: get_fl(), - rr: get_rr(), + tz: getTz(), + fl: getFl(), + rr: getRr(), w: i.params.w, h: i.params.h, s: i.params.s, @@ -114,7 +114,7 @@ export const spec = { } } -function get_rr() { +function getRr() { try { var td = top.document; var rr = td.referrer; @@ -127,7 +127,7 @@ function get_rr() { } } -function get_fl() { +function getFl() { if (navigator.plugins !== undefined && navigator.plugins !== null) { if (navigator.plugins['Shockwave Flash'] !== undefined && navigator.plugins['Shockwave Flash'] !== null && typeof navigator.plugins['Shockwave Flash'] === 'object') { var description = navigator.plugins['Shockwave Flash'].description; @@ -142,7 +142,7 @@ function get_fl() { return 0; } -function get_tz() { +function getTz() { return new Date().getTimezoneOffset(); } diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index 222f904f276..65fa49a25f8 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -164,35 +164,35 @@ export const spec = { return; } - let req_nativeLayout = req.mediaTypes.native; - let res_native = matchedResponse.native; + let reqNativeLayout = req.mediaTypes.native; + let resNative = matchedResponse.native; // check title - let title = req_nativeLayout.title; + let title = reqNativeLayout.title; if (title && title.required) { - if (typeof res_native.title !== 'string') { + if (typeof resNative.title !== 'string') { return; - } else if (title.len && title.len < res_native.title.length) { + } else if (title.len && title.len < resNative.title.length) { return; } } // check body - let body = req_nativeLayout.body; + let body = reqNativeLayout.body; if (body && body.required) { - if (typeof res_native.body !== 'string') { + if (typeof resNative.body !== 'string') { return; } } // check image - let image = req_nativeLayout.image; + let image = reqNativeLayout.image; if (image && image.required) { - if (res_native.image) { - if (typeof res_native.image.url !== 'string') { // check image url + if (resNative.image) { + if (typeof resNative.image.url !== 'string') { // check image url return; } else { - if (res_native.image.width !== image.sizes[0] || res_native.image.height !== image.sizes[1]) { // check image sizes + if (resNative.image.width !== image.sizes[0] || resNative.image.height !== image.sizes[1]) { // check image sizes return; } } @@ -202,21 +202,21 @@ export const spec = { } // check sponsoredBy - let sponsoredBy = req_nativeLayout.sponsoredBy; + let sponsoredBy = reqNativeLayout.sponsoredBy; if (sponsoredBy && sponsoredBy.required) { - if (typeof res_native.sponsoredBy !== 'string') { + if (typeof resNative.sponsoredBy !== 'string') { return; } } // check icon - let icon = req_nativeLayout.icon; + let icon = reqNativeLayout.icon; if (icon && icon.required) { - if (res_native.icon) { - if (typeof res_native.icon.url !== 'string') { // check icon url + if (resNative.icon) { + if (typeof resNative.icon.url !== 'string') { // check icon url return; } else { - if (res_native.icon.width !== icon.sizes[0] || res_native.icon.height !== icon.sizes[0]) { // check image sizes + if (resNative.icon.width !== icon.sizes[0] || resNative.icon.height !== icon.sizes[0]) { // check image sizes return; } } @@ -226,12 +226,12 @@ export const spec = { } // check clickUrl - if (typeof res_native.clickUrl !== 'string') { + if (typeof resNative.clickUrl !== 'string') { return; } // check clickTracker - let clickTrackers = res_native.clickTrackers; + let clickTrackers = resNative.clickTrackers; if (clickTrackers) { if (clickTrackers.length === 0) { return; @@ -241,7 +241,7 @@ export const spec = { } // check impressionTrackers - let impressionTrackers = res_native.impressionTrackers; + let impressionTrackers = resNative.impressionTrackers; if (impressionTrackers) { if (impressionTrackers.length === 0) { return; diff --git a/modules/etargetBidAdapter.js b/modules/etargetBidAdapter.js index 2ad524613c2..0804fa25e87 100644 --- a/modules/etargetBidAdapter.js +++ b/modules/etargetBidAdapter.js @@ -4,7 +4,7 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import { BANNER, VIDEO } from 'src/mediaTypes'; const BIDDER_CODE = 'etarget'; -const country_map = { +const countryMap = { 1: 'sk', 2: 'cz', 3: 'hu', @@ -28,18 +28,18 @@ export const spec = { var i, l, bid, reqParams, netRevenue, gdprObject; var request = []; var bids = JSON.parse(JSON.stringify(validBidRequests)); - var last_contry = 'sk'; + var lastContry = 'sk'; for (i = 0, l = bids.length; i < l; i++) { bid = bids[i]; - if (country_map[bid.params.country]) { - last_contry = country_map[bid.params.country]; + if (countryMap[bid.params.country]) { + lastContry = countryMap[bid.params.country]; } reqParams = bid.params; reqParams.transactionId = bid.transactionId; request.push(formRequestUrl(reqParams)); } - request.unshift('//' + last_contry + '.search.etargetnet.com/hb/?hbget=1'); + request.unshift('//' + lastContry + '.search.etargetnet.com/hb/?hbget=1'); netRevenue = 'net'; if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { diff --git a/modules/nasmediaAdmixerBidAdapter.js b/modules/nasmediaAdmixerBidAdapter.js index 7de5c638c9e..5b403b21b08 100644 --- a/modules/nasmediaAdmixerBidAdapter.js +++ b/modules/nasmediaAdmixerBidAdapter.js @@ -61,10 +61,10 @@ export const spec = { function getOsType() { let ua = navigator.userAgent.toLowerCase(); let os = ['android', 'ios', 'mac', 'linux', 'window']; - let regexp_os = [/android/i, /iphone|ipad/i, /mac/i, /linux/i, /window/i]; + let regexpOs = [/android/i, /iphone|ipad/i, /mac/i, /linux/i, /window/i]; return find(os, (tos, idx) => { - if (ua.match(regexp_os[idx])) { + if (ua.match(regexpOs[idx])) { return os[idx]; } }) || 'etc'; diff --git a/modules/polluxBidAdapter.js b/modules/polluxBidAdapter.js index 463de07341c..577ff57670e 100644 --- a/modules/polluxBidAdapter.js +++ b/modules/polluxBidAdapter.js @@ -34,7 +34,7 @@ export const spec = { return []; } const payload = []; - let custom_url = null; + let customUrl = null; for (let i = 0; i < validBidRequests.length; i++) { const bid = validBidRequests[i]; const request = { @@ -42,8 +42,8 @@ export const spec = { zones: bid.params.zone, sizes: bid.sizes }; - if (bid.bidderUrl && !custom_url) { - custom_url = bid.bidderUrl; + if (bid.bidderUrl && !customUrl) { + customUrl = bid.bidderUrl; } payload.push(request); } @@ -51,24 +51,24 @@ export const spec = { // build url parameters const domain = utils.getParameterByName('domain'); const tracker2 = utils.getParameterByName('tracker2'); - const url_params = {}; + const urlParams = {}; if (domain) { - url_params.domain = domain; + urlParams.domain = domain; } else { - url_params.domain = utils.getTopWindowUrl(); + urlParams.domain = utils.getTopWindowUrl(); } if (tracker2) { - url_params.tracker2 = tracker2; + urlParams.tracker2 = tracker2; } // build url - let bidder_url = custom_url || PLX_ENDPOINT_URL; - if (url_params) { - bidder_url = bidder_url + '?' + utils.parseQueryStringParameters(url_params); + let bidderUrl = customUrl || PLX_ENDPOINT_URL; + if (urlParams) { + bidderUrl = bidderUrl + '?' + utils.parseQueryStringParameters(urlParams); } - utils.logMessage('== ' + BIDDER_CODE + ' == request built: ' + bidder_url); + utils.logMessage('== ' + BIDDER_CODE + ' == request built: ' + bidderUrl); return { method: 'POST', - url: bidder_url, + url: bidderUrl, data: payloadString }; }, diff --git a/modules/realvuAnalyticsAdapter.js b/modules/realvuAnalyticsAdapter.js index 7dbb309ea18..1ce854b539e 100644 --- a/modules/realvuAnalyticsAdapter.js +++ b/modules/realvuAnalyticsAdapter.js @@ -356,15 +356,15 @@ window.top1.realvu_aa = window.top1.realvu_aa || { } if (a.riff === '') { a.riff = a.r; - let vr_score = z.score(a, 'v:r'); - if (vr_score != null) { - if (a.r == 'no' && vr_score > 75) { + let vrScore = z.score(a, 'v:r'); + if (vrScore != null) { + if (a.r == 'no' && vrScore > 75) { a.riff = 'yes'; } } - let vv0_score = z.score(a, 'v:v0'); - if (vv0_score != null) { - if (a.r == 'yes' && vv0_score < (30 + 25 * Math.random())) { + let vv0Score = z.score(a, 'v:v0'); + if (vv0Score != null) { + if (a.r == 'yes' && vv0Score < (30 + 25 * Math.random())) { a.riff = 'no'; } } @@ -439,20 +439,20 @@ window.top1.realvu_aa = window.top1.realvu_aa || { return par.offsetParent; } } - let not_friendly = false; + let notFriendly = false; let ain = null; let tn = a.tagName; if (tn == 'HEAD' || tn == 'SCRIPT') return null; if (tn == 'IFRAME') { ain = this.doc(a); if (ain == null) { - not_friendly = true; + notFriendly = true; } else { a = ain; tn = a.tagName; } } - if (not_friendly || tn == 'OBJECT' || tn == 'IMG' || tn == 'EMBED' || tn == 'SVG' || tn == 'CANVAS' || + if (notFriendly || tn == 'OBJECT' || tn == 'IMG' || tn == 'EMBED' || tn == 'SVG' || tn == 'CANVAS' || (tn == 'DIV' && a.style.backgroundImage)) { let w1 = a.offsetWidth; let h1 = a.offsetHeight; @@ -658,12 +658,12 @@ window.top1.realvu_aa = window.top1.realvu_aa || { return null; }, // API functions - addUnitById: function (partner_id, unit_id, callback, delay) { - let p1 = partner_id; + addUnitById: function (partnerId, unitId, callback, delay) { + let p1 = partnerId; if (typeof (p1) == 'string') { p1 = { - partner_id: partner_id, - unit_id: unit_id, + partner_id: partnerId, + unit_id: unitId, callback: callback, delay: delay }; @@ -676,25 +676,25 @@ window.top1.realvu_aa = window.top1.realvu_aa || { // b==true - add/update, b==false - update only if (args.cpm == 0) return; // collect only bids submitted const boost = window.top1.realvu_aa; - let push_bid = false; + let pushBid = false; let adi = null; if (!b) { // update only if already checked in by xyzBidAdapter for (let i = 0; i < boost.ads.length; i++) { adi = boost.ads[i]; if (adi.unit_id == args.adUnitCode) { - push_bid = true; + pushBid = true; break; } } } else { - push_bid = true; + pushBid = true; adi = window.top1.realvu_aa.check({ unit_id: args.adUnitCode, size: args.size, partner_id: partnerId }); } - if (push_bid) { + if (pushBid) { let pb = { bidder: args.bidder, cpm: args.cpm, @@ -715,10 +715,10 @@ window.top1.realvu_aa = window.top1.realvu_aa || { checkBidWon: function(partnerId, args, b) { // b==true - add/update, b==false - update only const z = this; - const unit_id = args.adUnitCode; + const unitId = args.adUnitCode; for (let i = 0; i < z.ads.length; i++) { let adi = z.ads[i]; - if (adi.unit_id == unit_id) { + if (adi.unit_id == unitId) { for (let j = 0; j < adi.bids.length; j++) { let bj = adi.bids[j]; if (bj.adId == args.adId) { @@ -754,10 +754,10 @@ window.top1.realvu_aa = window.top1.realvu_aa || { return rpt; }, - getStatusById: function (unit_id) { // return status object + getStatusById: function (unitId) { // return status object for (let i = 0; i < this.ads.length; i++) { let adi = this.ads[i]; - if (adi.unit_id == unit_id) return this.fmt(adi); + if (adi.unit_id == unitId) return this.fmt(adi); } return null; }, diff --git a/modules/rtbdemandadkBidAdapter.js b/modules/rtbdemandadkBidAdapter.js index a7ec8463c17..f199f20be56 100644 --- a/modules/rtbdemandadkBidAdapter.js +++ b/modules/rtbdemandadkBidAdapter.js @@ -96,7 +96,7 @@ export const spec = { return serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.adk_usersync) .map(rsp => rsp.body.ext.adk_usersync) .reduce((a, b) => a.concat(b), []) - .map(sync_url => ({type: 'iframe', url: sync_url})); + .map(syncUrl => ({type: 'iframe', url: syncUrl})); } }; diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js index 678e156c5e6..bb527528e43 100644 --- a/modules/rtbhouseBidAdapter.js +++ b/modules/rtbhouseBidAdapter.js @@ -41,9 +41,9 @@ function mapBanner(slot) { /** * Produce openRTB banner.format object */ -function mapSizes(slot_sizes) { +function mapSizes(slotSizes) { const format = []; - slot_sizes.forEach(elem => { + slotSizes.forEach(elem => { format.push({ w: elem[0], h: elem[1] diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index e5e3c390740..e77b247a349 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -506,13 +506,13 @@ function _getDigiTrustQueryParams() { * @returns {string} */ function _getPageUrl(bidRequest) { - let page_url = config.getConfig('pageUrl'); + let pageUrl = config.getConfig('pageUrl'); if (bidRequest.params.referrer) { - page_url = bidRequest.params.referrer; - } else if (!page_url) { - page_url = utils.getTopWindowUrl(); + pageUrl = bidRequest.params.referrer; + } else if (!pageUrl) { + pageUrl = utils.getTopWindowUrl(); } - return bidRequest.params.secure ? page_url.replace(/^http:/i, 'https:') : page_url; + return bidRequest.params.secure ? pageUrl.replace(/^http:/i, 'https:') : pageUrl; } function _renderCreative(script, impId) { diff --git a/modules/sekindoUMBidAdapter.js b/modules/sekindoUMBidAdapter.js index ffaaa2c1c62..66002ba7e1b 100644 --- a/modules/sekindoUMBidAdapter.js +++ b/modules/sekindoUMBidAdapter.js @@ -62,7 +62,7 @@ export const spec = { if (bidRequest.mediaType === 'video' || (typeof bidRequest.mediaTypes == 'object' && typeof bidRequest.mediaTypes.video == 'object')) { queryString = utils.tryAppendQueryString(queryString, 'x', bidRequest.params.playerWidth); queryString = utils.tryAppendQueryString(queryString, 'y', bidRequest.params.playerHeight); - if (typeof vid_vastType != 'undefined') { + if (typeof vid_vastType != 'undefined') { // eslint-disable-line camelcase queryString = utils.tryAppendQueryString(queryString, 'vid_vastType', bidRequest.params.vid_vastType); } if (typeof bidRequest.mediaTypes == 'object' && typeof bidRequest.mediaTypes.video == 'object' && typeof bidRequest.mediaTypes.video.context == 'string') { diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 289d42d1719..3d9ad2ce976 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -185,16 +185,16 @@ function _validateFloor (bid) { return ''; } -const _creative = (mediaType) => (sbi_dc, sbi_aid) => { +const _creative = (mediaType) => (sbiDc, sbiAid) => { if (mediaType === 'video') { - return _videoCreative(sbi_dc, sbi_aid) + return _videoCreative(sbiDc, sbiAid) } - const src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null' + '&ref=' + getTopWindowLocation().href; + const src = 'https://' + sbiDc + 'apex.go.sonobi.com/sbi.js?aid=' + sbiAid + '&as=null' + '&ref=' + getTopWindowLocation().href; return ''; }; -function _videoCreative(sbi_dc, sbi_aid) { - return `https://${sbi_dc}apex.go.sonobi.com/vast.xml?vid=${sbi_aid}&ref=${getTopWindowLocation().href}` +function _videoCreative(sbiDc, sbiAid) { + return `https://${sbiDc}apex.go.sonobi.com/vast.xml?vid=${sbiAid}&ref=${getTopWindowLocation().href}` } function _getBidIdFromTrinityKey (key) { diff --git a/modules/trionBidAdapter.js b/modules/trionBidAdapter.js index c2488bd351a..e5acba1bf5e 100644 --- a/modules/trionBidAdapter.js +++ b/modules/trionBidAdapter.js @@ -85,12 +85,12 @@ function buildTrionUrlParams(bid) { var url = utils.getTopWindowUrl(); var sizes = utils.parseSizesInput(bid.sizes).join(','); - var int_t = window.TR_INT_T && window.TR_INT_T != -1 ? window.TR_INT_T : null; - if (!int_t) { - int_t = getStorageData(BASE_KEY + 'int_t'); + var intT = window.TR_INT_T && window.TR_INT_T != -1 ? window.TR_INT_T : null; + if (!intT) { + intT = getStorageData(BASE_KEY + 'int_t'); } - if (int_t) { - setStorageData(BASE_KEY + 'int_t', int_t) + if (intT) { + setStorageData(BASE_KEY + 'int_t', intT) } setStorageData(BASE_KEY + 'lps', pubId + ':' + sectionId); var trionUrl = ''; @@ -105,8 +105,8 @@ function buildTrionUrlParams(bid) { if (sizes) { trionUrl += 'sizes=' + sizes + '&'; } - if (int_t) { - trionUrl = utils.tryAppendQueryString(trionUrl, 'int_t', encodeURIComponent(int_t)); + if (intT) { + trionUrl = utils.tryAppendQueryString(trionUrl, 'int_t', encodeURIComponent(intT)); } // remove the trailing "&" @@ -150,8 +150,8 @@ export function acceptPostMessage(e) { if (message.indexOf(BASE_KEY + 'userId') !== 0) { return; } - var int_t = message.split(BASE_KEY + 'userId=')[1]; - if (int_t) { - setStorageData(BASE_KEY + 'int_t', int_t); + var intT = message.split(BASE_KEY + 'userId=')[1]; + if (intT) { + setStorageData(BASE_KEY + 'int_t', intT); } } diff --git a/modules/underdogmediaBidAdapter.js b/modules/underdogmediaBidAdapter.js index a4531968d31..184ecb6e930 100644 --- a/modules/underdogmediaBidAdapter.js +++ b/modules/underdogmediaBidAdapter.js @@ -66,14 +66,14 @@ export const spec = { mid.useCount = 0; } - var size_not_found = true; + var sizeNotFound = true; utils.parseSizesInput(bidParam.sizes).forEach(size => { if (size === mid.width + 'x' + mid.height) { - size_not_found = false; + sizeNotFound = false; } }); - if (size_not_found) { + if (sizeNotFound) { return; } diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js index 2fb6c87c8df..f40a541aeb0 100644 --- a/modules/widespaceBidAdapter.js +++ b/modules/widespaceBidAdapter.js @@ -38,7 +38,7 @@ export const spec = { let serverRequests = []; const REQUEST_SERVER_URL = getEngineUrl(); const DEMO_DATA_PARAMS = ['gender', 'country', 'region', 'postal', 'city', 'yob']; - const PERF_DATA = getData(LS_KEYS.PERF_DATA).map(perf_data => JSON.parse(perf_data)); + const PERF_DATA = getData(LS_KEYS.PERF_DATA).map(perfData => JSON.parse(perfData)); const CUST_DATA = getData(LS_KEYS.CUST_DATA, false)[0]; const LC_UID = getLcuid(); diff --git a/package-lock.json b/package-lock.json index ae24e70fc80..4366f57423a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9339,7 +9339,10 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true, - "optional": true + "optional": true, + "requires": { + "readable-stream": "2.0.6" + } }, "form-data": { "version": "2.0.0", diff --git a/src/auction.js b/src/auction.js index 49632fddcf0..e2db713dd93 100644 --- a/src/auction.js +++ b/src/auction.js @@ -425,12 +425,12 @@ export function getStandardBidderSettings(mediaType) { const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${mediaType}`); const granularity = (typeof mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); - let bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; - if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { - bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; + let bidderSettings = $$PREBID_GLOBAL$$.bidderSettings; + if (!bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; } - if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [ + 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] = [ { key: 'hb_bidder', val: function (bidResponse) { @@ -483,7 +483,7 @@ export function getStandardBidderSettings(mediaType) { }, ] } - return bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; + return bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; } export function getKeyValueTargetingPairs(bidderCode, custBidObj) { @@ -492,18 +492,18 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj) { } var keyValues = {}; - var bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; + var bidderSettings = $$PREBID_GLOBAL$$.bidderSettings; // 1) set the keys from "standard" setting or from prebid defaults - if (bidder_settings) { + if (bidderSettings) { // initialize default if not set const standardSettings = getStandardBidderSettings(custBidObj.mediaType); setKeys(keyValues, standardSettings, custBidObj); // 2) set keys from specific bidder setting override if they exist - if (bidderCode && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - setKeys(keyValues, bidder_settings[bidderCode], custBidObj); - custBidObj.sendStandardTargeting = bidder_settings[bidderCode].sendStandardTargeting; + if (bidderCode && bidderSettings[bidderCode] && bidderSettings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + setKeys(keyValues, bidderSettings[bidderCode], custBidObj); + custBidObj.sendStandardTargeting = bidderSettings[bidderCode].sendStandardTargeting; } } diff --git a/src/utils.js b/src/utils.js index be1b3fbf5e2..7845e1e9bb0 100644 --- a/src/utils.js +++ b/src/utils.js @@ -7,12 +7,12 @@ const CONSTANTS = require('./constants'); var _loggingChecked = false; -var t_Arr = 'Array'; -var t_Str = 'String'; -var t_Fn = 'Function'; -var t_Numb = 'Number'; -var t_Object = 'Object'; -var t_Boolean = 'Boolean'; +var tArr = 'Array'; +var tStr = 'String'; +var tFn = 'Function'; +var tNumb = 'Number'; +var tObject = 'Object'; +var tBoolean = 'Boolean'; var toString = Object.prototype.toString; let infoLogger = null; let warnLogger = null; @@ -405,27 +405,27 @@ exports.isA = function (object, _t) { }; exports.isFn = function (object) { - return exports.isA(object, t_Fn); + return exports.isA(object, tFn); }; exports.isStr = function (object) { - return exports.isA(object, t_Str); + return exports.isA(object, tStr); }; exports.isArray = function (object) { - return exports.isA(object, t_Arr); + return exports.isA(object, tArr); }; exports.isNumber = function(object) { - return exports.isA(object, t_Numb); + return exports.isA(object, tNumb); }; exports.isPlainObject = function(object) { - return exports.isA(object, t_Object); + return exports.isA(object, tObject); } exports.isBoolean = function(object) { - return exports.isA(object, t_Boolean); + return exports.isA(object, tBoolean); } /** From aca5fb77268d7fdb6ef3549eeef7a98cba40272b Mon Sep 17 00:00:00 2001 From: Omer Koren Date: Fri, 3 Aug 2018 23:34:43 +0300 Subject: [PATCH 0605/1594] fix domain extraction in undertone adapter (#2921) * fix domain extraction in undertone adapter There was a bug when trying to extract domain from hostnames with two letter suffixes such as .co / .io / etc This fix solves this issue * fix lint issues --- modules/undertoneBidAdapter.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index 1f32fe0347a..d7e063b85f5 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -21,11 +21,15 @@ export const spec = { 'x-ut-hb-params': [] }; const location = utils.getTopWindowLocation(); - let domain = /[-\w]+\.(?:[-\w]+\.xn--[-\w]+|[-\w]{3,}|[-\w]+\.[-\w]{2})$/i.exec(location.host); - if (domain == null || domain.length == 0) { - domain = null; - } else { - domain = domain[0]; + let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(location.host); + let domain = null; + 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]; + } + } } const pubid = validBidRequests[0].params.publisherId; From d303d1db27528ad742a25864072577dcc618ad62 Mon Sep 17 00:00:00 2001 From: telariaEng <36203956+telariaEng@users.noreply.github.com> Date: Mon, 6 Aug 2018 06:54:36 -0700 Subject: [PATCH 0606/1594] Telaria Bid Adapter (#2924) * Added telaria bid adapter * more documentation * Added more test cases. And improved some code in the adapter * Removed the check for optional params, they are handled in the server. Also updated certain param names used in the test spec. * added some spaces to fix CircleCI tests * added some spaces to fix CircleCI tests * fixed code indentation in /spec/AnalyticsAdapter_spec.js which causing the CircleCI tests to fail. * Reverted the changes * merged with prebid master. * creative Id is required when we build a response but our server doesn't always have the crid, so using a sentinel value when we don't have the crid. * - removed an un used method - Removed the package-lock file. --- modules/telariaBidAdapter.js | 190 ++++++++++++++++++++ modules/telariaBidAdapter.md | 35 ++++ test/spec/modules/telariaBidAdapter_spec.js | 190 ++++++++++++++++++++ 3 files changed, 415 insertions(+) create mode 100644 modules/telariaBidAdapter.js create mode 100644 modules/telariaBidAdapter.md create mode 100644 test/spec/modules/telariaBidAdapter_spec.js diff --git a/modules/telariaBidAdapter.js b/modules/telariaBidAdapter.js new file mode 100644 index 00000000000..e59ed6cd0f6 --- /dev/null +++ b/modules/telariaBidAdapter.js @@ -0,0 +1,190 @@ +import * as utils from 'src/utils'; +import * as bidfactory from 'src/bidfactory'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import {config} from 'src/config'; +import {VIDEO} from '../src/mediaTypes'; +import {STATUS} from 'src/constants'; + +const BIDDER_CODE = 'telaria'; +const ENDPOINT = '.ads.tremorhub.com/ad/tag'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['tremor', 'tremorvideo'], + supportedMediaTypes: [VIDEO], + /** + * Determines if the request is valid + * @param bid + * @returns {*|string} + */ + isBidRequestValid: function (bid) { + return !!(bid && bid.params && bid.params.adCode && bid.params.supplyCode); + }, + + /** + * Make a server request from the list of BidRequests. + * @param validBidRequests list of valid bid requests that have passed isBidRequestValid check + * @returns {Array} of url objects + */ + buildRequests: function (validBidRequests) { + let requests = []; + + validBidRequests.forEach(bid => { + let url = generateUrl(bid); + if (url) { + requests.push({ + method: 'GET', + url: generateUrl(bid), + bidId: bid.bidId, + vastUrl: url.split('&fmt=json')[0] + }); + } + }); + + return requests; + }, + + /** + * convert the server response into a list of BidObjects that prebid accepts + * http://prebid.org/dev-docs/bidder-adaptor.html#interpreting-the-response + * @param serverResponse + * @param bidderRequest + * @returns {Array} + */ + interpretResponse: function (serverResponse, bidderRequest) { + let bidResult; + let width, height; + + let bids = []; + + try { + bidResult = serverResponse.body; + + bidderRequest.url.split('&').forEach(param => { + let lower = param.toLowerCase(); + if (lower.indexOf('player') > -1) { + if (lower.indexOf('width') > -1) { + width = param.split('=')[1]; + } else if (lower.indexOf('height') > -1) { + height = param.split('=')[1]; + } + } + }); + } catch (error) { + utils.logError(error); + width = 0; + height = 0; + } + + if (!bidResult || bidResult.error) { + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; + if (bidResult && bidResult.error) { + errorMessage += `: ${bidResult.error}`; + } + utils.logError(errorMessage); + } else if (bidResult.seatbid && bidResult.seatbid.length > 0) { + bidResult.seatbid[0].bid.forEach(tag => { + bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, bidResult.seatbid[0].seat)); + }); + } + + return bids; + }, + /** + * We support pixel syncing only at the moment. Telaria ad server returns 'ext' + * as an optional parameter if the tag has 'incIdSync' parameter set to true + * @param syncOptions + * @param serverResponses + * @returns {Array} + */ + getUserSyncs: function (syncOptions, serverResponses) { + const syncs = []; + if (syncOptions.pixelEnabled && serverResponses.length) { + try { + serverResponses[0].body.ext.telaria.userSync.forEach(url => syncs.push({type: 'image', url: url})); + } catch (e) {} + } + return syncs; + } +}; + +/** + * Generates the url based on the parameters given. Sizes, supplyCode & adCode are required. + * The format is: [L,W] or [[L1,W1],...] + * @param bid + * @returns {string} + */ +function generateUrl(bid) { + let width, height; + if (!bid.sizes) { + return ''; + } + + if (utils.isArray(bid.sizes) && (bid.sizes.length === 2) && (!isNaN(bid.sizes[0]) && !isNaN(bid.sizes[1]))) { + width = bid.sizes[0]; + height = bid.sizes[1]; + } else if (typeof bid.sizes === 'object') { + // take the primary (first) size from the array + width = bid.sizes[0][0]; + height = bid.sizes[0][1]; + } + if (width && height && bid.params.supplyCode && bid.params.adCode) { + let scheme = ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; + let url = scheme + bid.params.supplyCode + ENDPOINT + '?adCode=' + bid.params.adCode; + + url += ('&playerWidth=' + width); + url += ('&playerHeight=' + height); + + for (let key in bid.params) { + if (bid.params.hasOwnProperty(key) && bid.params[key]) { + url += ('&' + key + '=' + bid.params[key]); + } + } + + if (!bid.params['srcPageUrl']) { + url += ('&srcPageUrl=' + encodeURIComponent(document.location.href)); + } + + url += ('&transactionId=' + bid.transactionId); + url += ('&referrer=' + config.getConfig('pageUrl') || utils.getTopWindowUrl()); + + return (url + '&fmt=json'); + } +} + +/** + * 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(status, reqBid, response, width, height, bidderCode) { + let bid = bidfactory.createBid(status, reqBid); + + // TTL 5 mins by default, future support for extended imp wait time + 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, + adId: response.id, + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: response.adm + }); + } + + return bid; +} + +registerBidder(spec); diff --git a/modules/telariaBidAdapter.md b/modules/telariaBidAdapter.md new file mode 100644 index 00000000000..6a34a14a6b2 --- /dev/null +++ b/modules/telariaBidAdapter.md @@ -0,0 +1,35 @@ +# Overview + +``` +Module Name: Telaria Bid Adapter +Module Type: Bidder Adapter +Maintainer: github@telaria.com +``` + +# Description + +Connects to Telaria's exchange. + +Telaria bid adapter supports insteream Video. + +# Test Parameters +``` +{ + code: 'video1', + mediaTypes: { + 'video': { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'tremor', + params: { + supplyCode: 'ssp-demo-rm6rh', + adCode: 'ssp-!demo!-lufip', + videoId: 'MyCoolVideo' + } + }] +} +``` + diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js new file mode 100644 index 00000000000..2483ec70e76 --- /dev/null +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -0,0 +1,190 @@ +import {expect} from 'chai'; +import {newBidder} from 'src/adapters/bidderFactory'; +import {spec} from 'modules/telariaBidAdapter'; + +const ENDPOINT = '.ads.tremorhub.com/ad/tag'; +const AD_CODE = 'ssp-!demo!-lufip'; +const SUPPLY_CODE = 'ssp-demo-rm6rh'; +const SIZES = [640, 480]; +const REQUEST = { + 'code': 'video1', + 'sizes': [640, 480], + 'mediaType': 'video', + 'bids': [{ + 'bidder': 'tremor', + 'params': { + 'videoId': 'MyCoolVideo', + 'inclSync': true + } + }] +}; + +const RESPONSE = { + 'cur': 'USD', + 'id': '3dba13e35f3d42f998bc7e65fd871889', + 'seatbid': [{ + 'seat': 'TremorVideo', + 'bid': [{ + 'adomain': [], + 'price': 0.50000, + 'id': '3dba13e35f3d42f998bc7e65fd871889', + 'adm': '\n Tremor Video Test MP4 Creative \n\n \n\n\n\n\n\n \n\n \n\n', + 'impid': '1' + }] + }] +}; + +describe('TelariaAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = REQUEST.bids[0]; + + it('should return true when required params found', () => { + let tempBid = bid; + tempBid.params.adCode = 'ssp-!demo!-lufip'; + tempBid.params.supplyCode = 'ssp-demo-rm6rh'; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', () => { + let tempBid = bid; + delete tempBid.params; + tempBid.params = { + supplyCode: 'ssp-demo-rm6rh', + adCode: 'ssp-!demo!-lufip', + }; + + expect(spec.isBidRequestValid(tempBid)).to.equal(true); + }); + + it('should return false when required params are not passed', () => { + let tempBid = bid; + tempBid.params = {}; + expect(spec.isBidRequestValid(tempBid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const stub = [{ + bidder: 'tremor', + sizes: [[300, 250], [300, 600]], + params: { + supplyCode: 'ssp-demo-rm6rh', + adCode: 'ssp-!demo!-lufip', + videoId: 'MyCoolVideo' + } + }]; + + it('exists and is a function', () => { + expect(spec.buildRequests).to.exist.and.to.be.a('function'); + }); + + it('requires supply code, ad code and sizes to make a request', () => { + const tempRequest = spec.buildRequests(stub); + expect(tempRequest.length).to.equal(1); + }); + + it('generates an array of requests with 4 params, method, url, bidId and vastUrl', () => { + const tempRequest = spec.buildRequests(stub); + + expect(tempRequest.length).to.equal(1); + expect(tempRequest[0].method).to.equal('GET'); + expect(tempRequest[0].url).to.exist; + expect(tempRequest[0].bidId).to.equal(undefined); + expect(tempRequest[0].vastUrl).to.exist; + }); + + it('requires sizes to make a request', () => { + let tempBid = stub; + tempBid[0].sizes = null; + const tempRequest = spec.buildRequests(tempBid); + + expect(tempRequest.length).to.equal(0); + }); + + it('generates a valid request with sizes as an array of two elements', () => { + let tempBid = stub; + tempBid[0].sizes = [640, 480]; + expect(spec.buildRequests(tempBid).length).to.equal(1); + }); + + it('requires ad code and supply code to make a request', () => { + let tempBid = stub; + tempBid[0].params.adCode = null; + tempBid[0].params.supplyCode = null; + + const tempRequest = spec.buildRequests(tempBid); + + expect(tempRequest.length).to.equal(0); + }); + }); + + describe('interpretResponse', () => { + const responseStub = RESPONSE; + const stub = [{ + bidder: 'tremor', + sizes: [[300, 250], [300, 600]], + params: { + supplyCode: 'ssp-demo-rm6rh', + adCode: 'ssp-!demo!-lufip', + videoId: 'MyCoolVideo' + } + }]; + + it('should get correct bid response', () => { + let expectedResponseKeys = ['bidderCode', 'width', 'height', 'statusMessage', 'adId', 'mediaType', 'source', + 'getStatusCode', 'getSize', 'requestId', 'cpm', 'creativeId', 'vastXml', + 'vastUrl', 'currency', 'netRevenue', 'ttl', 'ad']; + + let bidRequest = spec.buildRequests(stub)[0]; + bidRequest.bidId = '1234'; + let result = spec.interpretResponse({body: responseStub}, bidRequest); + expect(Object.keys(result[0])).to.have.members(expectedResponseKeys); + }); + + it('handles nobid responses', () => { + let tempResponse = responseStub; + tempResponse.seatbid = []; + + let bidRequest = spec.buildRequests(stub)[0]; + bidRequest.bidId = '1234'; + + let result = spec.interpretResponse({body: tempResponse}, bidRequest); + expect(result.length).to.equal(0); + }); + + it('handles invalid responses', () => { + let result = spec.interpretResponse(null, {bbidderCode: 'telaria'}); + expect(result.length).to.equal(0); + }); + + it('handles error responses', () => { + let result = spec.interpretResponse({body: {error: 'Invalid request'}}, {bbidderCode: 'telaria'}); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs', () => { + const responses = [{body: RESPONSE}]; + responses[0].body.ext = { + telaria: { + userSync: [ + 'https://url.com', + 'https://url2.com' + ] + } + }; + + it('should get the correct number of sync urls', () => { + let urls = spec.getUserSyncs({pixelEnabled: true}, responses); + expect(urls.length).to.equal(2); + }); + }); +}); From 752e234f54f8f4de09f541e6c0d4acd63bd12d61 Mon Sep 17 00:00:00 2001 From: PROPS IPAX <41884470+PROPSIPAX@users.noreply.github.com> Date: Tue, 7 Aug 2018 22:38:56 +0700 Subject: [PATCH 0607/1594] PROPS IPAX - GIANTS Adapter (#2933) * add giants bidder * add giants bidder spec * newline end file newline end file * add GDPR Module --- modules/giantsBidAdapter.js | 343 +++++++++++++++++++++ modules/giantsBidAdapter.md | 30 ++ test/spec/modules/giantsBidAdapter_spec.js | 301 ++++++++++++++++++ 3 files changed, 674 insertions(+) create mode 100644 modules/giantsBidAdapter.js create mode 100644 modules/giantsBidAdapter.md create mode 100644 test/spec/modules/giantsBidAdapter_spec.js diff --git a/modules/giantsBidAdapter.js b/modules/giantsBidAdapter.js new file mode 100644 index 00000000000..6844cb684bc --- /dev/null +++ b/modules/giantsBidAdapter.js @@ -0,0 +1,343 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import includes from 'core-js/library/fn/array/includes'; + +const BIDDER_CODE = 'giants'; +const URL = '//d.admp.io/hb'; +const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', + 'startdelay', 'skippable', 'playback_method', 'frameworks']; +const NATIVE_MAPPING = { + body: 'description', + cta: 'ctatext', + image: { + serverName: 'main_image', + requiredParams: { required: true }, + minimumParams: { sizes: [{}] }, + }, + icon: { + serverName: 'icon', + requiredParams: { required: true }, + minimumParams: { sizes: [{}] }, + }, + sponsoredBy: 'sponsored_by', +}; +const SOURCE = 'pbjs'; + +export const spec = { + code: BIDDER_CODE, + aliases: [], + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + + /** + * 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 !!(bid.params.zoneId); + }, + + /** + * 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) { + const tags = bidRequests.map(bidToTag); + // const zoneIds = bidRequests.map(bidToZoneId); + // var firstBid = bidRequests[0]; + var ref = utils.getTopWindowUrl(); + const url = URL + '/multi?url=' + ref; + // + '&callback=window.$$PREBID_GLOBAL$$.giantsResponse&callback_uid=' + bid.bidId; + + const payload = { + tags: [...tags], + // user: userObj, + sdk: { + source: SOURCE, + version: '$prebid.version$' + } + }; + // if (member > 0) { + // payload.member_id = member; + // } + + 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 + }; + } + + const payloadString = JSON.stringify(payload); + + return { + method: 'POST', + // url: URL, + url: url, + data: payloadString, + 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, {bidderRequest}) { + serverResponse = serverResponse.body; + const bids = []; + if (!serverResponse || serverResponse.error) { + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; + if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } + utils.logError(errorMessage); + return bids; + } + if (serverResponse.tags) { + serverResponse.tags.forEach(serverBid => { + if (serverBid.cpm && serverBid.cpm !== 0) { + const bid = newBid(serverBid, bidderRequest); + bid.mediaType = BANNER; + bids.push(bid); + } + }); + } + return bids; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//d.admp.io/ping' + }]; + } + } +} + +/* Turn keywords parameter into ut-compatible format */ +function getKeywords(keywords) { + let arrs = []; + + utils._each(keywords, (v, k) => { + if (utils.isArray(v)) { + let values = []; + utils._each(v, (val) => { + val = utils.getValueString('keywords.' + k, val); + if (val) { values.push(val); } + }); + v = values; + } else { + v = utils.getValueString('keywords.' + k, v); + if (utils.isStr(v)) { + v = [v]; + } else { + return; + } // unsuported types - don't send a key + } + arrs.push({key: k, value: v}); + }); + + return arrs; +} + +/** + * Unpack the Server's Bid into a Prebid-compatible one. + * @param serverBid + * @param rtbBid + * @param bidderRequest + * @return Bid + */ +function newBid(serverBid, bidderRequest) { + const bid = { + requestId: serverBid.uuid, + cpm: serverBid.cpm, + creativeId: serverBid.creative_id, + // dealId: rtbBid.deal_id, + currency: 'USD', + netRevenue: true, + ttl: 300 + }; + + Object.assign(bid, { + width: serverBid.width, + height: serverBid.height, + // ad: serverBid.ad + ad: _renderCreative(serverBid.adUrl, serverBid.width, serverBid.height) + }); + // try { + // const url = rtbBid.rtb.trackers[0].impression_urls[0]; + // const tracker = utils.createTrackPixelHtml(url); + // bid.ad += tracker; + // } catch (error) { + // utils.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.zoneId) { + tag.id = bid.params.zoneId; + } 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; + if (bid.params.reserve) { + tag.reserve = bid.params.reserve; + } + 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.externalImpId) { + tag.external_imp_id = bid.params.externalImpId; + } + if (!utils.isEmpty(bid.params.keywords)) { + tag.keywords = getKeywords(bid.params.keywords); + } + + if (bid.mediaType === NATIVE || utils.deepAccess(bid, `mediaTypes.${NATIVE}`)) { + tag.ad_types.push(NATIVE); + + if (bid.nativeParams) { + const nativeRequest = buildNativeRequest(bid.nativeParams); + tag[NATIVE] = {layouts: [nativeRequest]}; + } + } + + const videoMediaType = utils.deepAccess(bid, `mediaTypes.${VIDEO}`); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + + 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 => tag.video[param] = bid.params.video[param]); + } + + if ( + (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) || + (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER])) + ) { + tag.ad_types.push(BANNER); + } + + return tag; +} + +// function bidToZoneId(bid) { +// return bid.params.zoneId; +// } + +/* Turn bid request sizes into ut-compatible format */ +function transformSizes(requestSizes) { + let sizes = []; + let sizeObj = {}; + + 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); + } 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 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]); + + // minimum params are passed if no non-required params given on adunit + const minimumParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].minimumParams; + + if (requiredParams && minimumParams) { + // subtract required keys from adunit keys + const adunitKeys = Object.keys(params[key]); + const requiredKeys = Object.keys(requiredParams); + const remaining = adunitKeys.filter(key => !includes(requiredKeys, key)); + + // if none are left over, the minimum params needs to be sent + if (remaining.length === 0) { + request[requestKey] = Object.assign({}, request[requestKey], minimumParams); + } + } + }); + + return request; +} + +function _renderCreative(adUrl, width, height) { + return ` + + + + ' + - '\');'; +const REQUEST = { + 'bidderCode': 'consumable', + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d', + 'bidderRequestId': '109f2a181342a9', + 'bidRequest': [{ + 'bidder': 'consumable', + 'params': { + 'networkId': 9969, + 'siteId': 730181, + 'unitId': 123456, + 'unitName': 'cnsmbl-unit' + }, + 'placementCode': 'div-gpt-ad-1487778092495-0', + 'sizes': [ + [728, 90], + [970, 90] + ], + 'bidId': '2b0f82502298c9', + 'bidderRequestId': '109f2a181342a9', + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' + }, + { + 'bidder': 'consumable', + 'params': { + 'networkId': 9969, + 'siteId': 730181, + 'unitId': 123456, + 'unitName': 'cnsmbl-unit' + }, + 'placementCode': 'div-gpt-ad-1487778092495-0', + 'sizes': [ + [728, 90], + [970, 90] + ], + 'bidId': '123', + 'bidderRequestId': '109f2a181342a9', + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' + }], + 'start': 1487883186070, + 'auctionStart': 1487883186069, + 'timeout': 3000 }; -describe('ConsumableAdapter', () => { - const CONSUMABLE_URL = '//adserver-us.adtech.advertising.com/pubapi/3.0/'; - const CONSUMABLE_TTL = 60; - - function createCustomBidRequest({bids, params} = {}) { - var bidderRequest = getDefaultBidRequest(); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - if (params) { - bidderRequest.bids.forEach(bid => bid.params = params); +const RESPONSE = { + 'headers': null, + 'body': { + 'user': { 'key': 'ue1-2d33e91b71e74929b4aeecc23f4376f1' }, + '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} + }, + '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} + } } - return bidderRequest; } +}; - describe('interpretResponse()', () => { - let bidderSettingsBackup; - let bidResponse; - let bidRequest; - let logWarnSpy; - - beforeEach(() => { - bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; - bidRequest = { - bidderCode: 'test-bidder-code', - bidId: 'bid-id', - unitName: 'unitname', - unitId: '987654', - zoneId: '9599.1', - network: '9599.1' - }; - bidResponse = { - body: getDefaultBidResponse() +describe('Consumable BidAdapter', () => { + let bidRequests; + let adapter = spec; + + beforeEach(() => { + bidRequests = [ + { + bidder: 'consumable', + params: { + networkId: '9969', + siteId: '730181', + unitId: '123456', + unitName: 'cnsmbl-unit' + }, + placementCode: 'header-bid-tag-1', + sizes: [[300, 250], [300, 600]], + bidId: '23acc48ad47af5', + auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ]; + }); + + describe('bid request validation', () => { + it('should accept valid bid requests', () => { + let bid = { + bidder: 'consumable', + params: { + networkId: '9969', + siteId: '123', + unitId: '123456', + unitName: 'cnsmbl-unit' + } }; - logWarnSpy = sinon.spy(utils, 'logWarn'); + expect(spec.isBidRequestValid(bid)).to.equal(true); }); - afterEach(() => { - $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; - logWarnSpy.restore(); + it('should accept valid bid requests with extra fields', () => { + let bid = { + bidder: 'consumable', + params: { + networkId: '9969', + siteId: '123', + unitId: '123456', + unitName: 'cnsmbl-unit', + zoneId: '123' + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return formatted bid response with required properties', () => { - let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - expect(formattedBidResponse).to.deep.equal({ - bidderCode: bidRequest.bidderCode, - requestId: 'bid-id', - ad: DEFAULT_AD_CONTENT, - cpm: 0.09, - width: 728, - height: 90, - creativeId: 'creative-id', - pubapiId: '245730051428950632', - currency: 'USD', - dealId: 'deal-id', - netRevenue: true, - ttl: 60 - }); + it('should reject bid requests without siteId', () => { + let bid = { + bidder: 'consumable', + params: { + networkId: '9969', + unitId: '123456', + unitName: 'cnsmbl-unit' + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should add formatted pixels to ad content when pixels are present in the response', () => { - bidResponse.body.ext = { - pixels: 'pixels-content' + it('should reject bid requests without networkId', () => { + let bid = { + bidder: 'consumable', + params: { + siteId: '9969', + unitId: '123456', + unitName: 'cnsmbl-unit' + } }; - - let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - - expect(formattedBidResponse.ad).to.equal(DEFAULT_AD_CONTENT + ''); - return true; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests()', () => { - it('method exists and is a function', () => { - expect(spec.buildRequests).to.exist.and.to.be.a('function'); + describe('buildRequests validation', () => { + it('creates request data', () => { + let request = spec.buildRequests(bidRequests); + + expect(request).to.exist.and.to.be.a('object'); }); - describe('Consumable', () => { - it('should not return request when no bids are present', () => { - let [request] = spec.buildRequests([]); - expect(request).to.be.empty; - }); + it('request to consumable should contain a url', () => { + let request = spec.buildRequests(bidRequests); - it('should return request for endpoint', () => { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(CONSUMABLE_URL); - }); + expect(request.url).to.have.string('serverbid.com'); + }); - it('should return url with pubapi bid option', () => { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('cmd=bid;'); - }); + it('requires valid bids to make request', () => { + let request = spec.buildRequests([]); + expect(request.bidRequest).to.be.empty; + }); - it('should return url with version 2 of pubapi', () => { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('v=2;'); - }); + it('sends bid request to ENDPOINT via POST', () => { + let request = spec.buildRequests(bidRequests); - it('should return url with cache busting option', () => { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.match(/misc=\d+/); - }); + expect(request.method).to.have.string('POST'); }); }); + describe('interpretResponse validation', () => { + it('response should have valid bidderCode', () => { + let bidRequest = spec.buildRequests(REQUEST.bidRequest); + let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); + + expect(bid.bidderCode).to.equal('consumable'); + }); - describe('getUserSyncs()', () => { - let bidResponse; - let bidRequest; + it('response should include objects for all bids', () => { + let bids = spec.interpretResponse(RESPONSE, REQUEST); + expect(bids.length).to.equal(2); + }); - beforeEach(() => { - $$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped = false; - config.setConfig({ - consumable: { - userSyncOn: 'bidResponse' - }, + it('registers bids', () => { + let bids = spec.interpretResponse(RESPONSE, REQUEST); + bids.forEach(b => { + expect(b).to.have.property('cpm'); + expect(b.cpm).to.be.above(0); + expect(b).to.have.property('requestId'); + expect(b).to.have.property('unitId'); + expect(b).to.have.property('unitName'); + expect(b).to.have.property('cpm'); + expect(b).to.have.property('width'); + expect(b).to.have.property('height'); + expect(b).to.have.property('ad'); + expect(b).to.have.property('currency', 'USD'); + expect(b).to.have.property('creativeId'); + expect(b).to.have.property('ttl', 360); + expect(b).to.have.property('netRevenue', true); + expect(b).to.have.property('referrer'); }); - bidResponse = getDefaultBidResponse(); - bidResponse.ext = { - pixels: getPixels() - }; }); - it('should return user syncs only if userSyncOn equals to "bidResponse"', () => { - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + it('handles nobid responses', () => { + let EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {'decisions': null}}) + let bids = spec.interpretResponse(EMPTY_RESP, REQUEST); - expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.true; - expect(userSyncs).to.deep.equal([ - {type: 'image', url: 'img.org'}, - {type: 'iframe', url: 'pixels1.org'} - ]); + expect(bids).to.be.empty; }); - it('should not return user syncs if it has already been returned', () => { - $$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped = true; + it('handles no server response', () => { + let bids = spec.interpretResponse(null, REQUEST); - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - - expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.true; - expect(userSyncs).to.deep.equal([]); + expect(bids).to.be.empty; }); + }); + describe('getUserSyncs', () => { + let syncOptions = {'iframeEnabled': true}; - it('should not return user syncs if pixels are not present', () => { - bidResponse.ext.pixels = null; + it('handles empty sync options', () => { + let opts = spec.getUserSyncs({}); + + expect(opts).to.be.empty; + }); - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + it('should return a sync url if iframe syncs are enabled', () => { + let opts = spec.getUserSyncs(syncOptions); - expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.false; - expect(userSyncs).to.deep.equal([]); + expect(opts.length).to.equal(1); }); }); }); From 10b318a3526f43ef5d4c4fdc1bef8911f3b13c1e Mon Sep 17 00:00:00 2001 From: nwlosinski Date: Mon, 13 Aug 2018 17:08:47 +0200 Subject: [PATCH 0618/1594] returning tracking pixels (#2876) * returning tracking pixels * removed event on global object --- modules/justpremiumBidAdapter.js | 57 ++++++++++++++++++- .../modules/justpremiumBidAdapter_spec.js | 32 ++++++++++- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 406fc166483..0f38f586a4d 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -3,8 +3,11 @@ import { getTopWindowLocation } from 'src/utils' const BIDDER_CODE = 'justpremium' const ENDPOINT_URL = getTopWindowLocation().protocol + '//pre.ads.justpremium.com/v/2.0/t/xhr' -const JP_ADAPTER_VERSION = '1.1' +const JP_ADAPTER_VERSION = '1.2' const pixels = [] +const TRACK_START_TIME = Date.now() +let LAST_PAYLOAD = {} +let AD_UNIT_IDS = [] export const spec = { code: BIDDER_CODE, @@ -17,6 +20,11 @@ export const spec = { buildRequests: (validBidRequests, bidderRequest) => { const c = preparePubCond(validBidRequests) const dim = getWebsiteDim() + AD_UNIT_IDS = validBidRequests.map(b => { + return b.adUnitCode + }).filter((value, index, self) => { + return self.indexOf(value) === index + }) const payload = { zone: validBidRequests.map(b => { return parseInt(b.params.zone) @@ -44,7 +52,7 @@ export const spec = { payload.gdpr_consent = { consent_string: bidderRequest.gdprConsent.consentString, consent_required: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true - }; + } } payload.version = { @@ -54,6 +62,8 @@ export const spec = { const payloadString = JSON.stringify(payload) + LAST_PAYLOAD = payload + return { method: 'POST', url: ENDPOINT_URL + '?i=' + (+new Date()), @@ -97,10 +107,51 @@ export const spec = { pixels.push({ type: 'iframe', url: url - }); + }) } return pixels + }, + + onTimeout: (timeoutData) => { + timeoutData.forEach((data) => { + if (AD_UNIT_IDS.indexOf(data.adUnitCode) != -1) { + track(data, LAST_PAYLOAD, 'btm') + } + }) + }, + +} + +function track (data, payload, type) { + let pubUrl = '' + + let jp = { + auc: data.adUnitCode, + to: data.timeout } + + if (window.top == window) { + pubUrl = window.location.href + } else { + try { + pubUrl = window.top.location.href + } catch (e) { + pubUrl = document.referrer + } + } + + let duration = Date.now() - TRACK_START_TIME + + const pixelUrl = `${getTopWindowLocation().protocol}//emea-v3.tracking.justpremium.com/tracking.gif?rid=&sid=&uid=&vr=& +ru=${encodeURIComponent(pubUrl)}&tt=&siw=&sh=${payload.sh}&sw=${payload.sw}&wh=${payload.wh}&ww=${payload.ww}&an=&vn=& +sd=&_c=&et=&aid=&said=&ei=&fc=&sp=&at=bidder&cid=&ist=&mg=&dl=&dlt=&ev=&vt=&zid=${payload.id}&dr=${duration}&di=&pr=& +cw=&ch=&nt=&st=&jp=${encodeURIComponent(JSON.stringify(jp))}&ty=${type}` + + let img = document.createElement('img') + img.src = pixelUrl + img.id = 'jp-pixel-track' + img.style.cssText = 'display:none !important;' + document.body.appendChild(img) } function findBid (params, bids) { diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index 3b74b730044..eb6d17d7a32 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -4,6 +4,7 @@ import { spec } from 'modules/justpremiumBidAdapter' describe('justpremium adapter', () => { let adUnits = [ { + adUnitCode: 'div-gpt-ad-1471513102552-1', bidder: 'justpremium', params: { zone: 28313, @@ -11,6 +12,7 @@ describe('justpremium adapter', () => { } }, { + adUnitCode: 'div-gpt-ad-1471513102552-2', bidder: 'justpremium', params: { zone: 32831, @@ -51,7 +53,7 @@ describe('justpremium adapter', () => { expect(jpxRequest.id).to.equal(adUnits[0].params.zone) expect(jpxRequest.sizes).to.not.equal('undefined') expect(jpxRequest.version.prebid).to.equal('$prebid.version$') - expect(jpxRequest.version.jp_adapter).to.equal('1.1') + expect(jpxRequest.version.jp_adapter).to.equal('1.2') }) }) @@ -128,4 +130,32 @@ describe('justpremium adapter', () => { expect(options[0].url).to.match(/\/\/pre.ads.justpremium.com\/v\/1.0\/t\/sync/) }) }) + + describe('onTimeout', () => { + it('onTimeout', (done) => { + spec.onTimeout([{ + 'bidId': '25cd3ec3fd6ed7', + 'bidder': 'justpremium', + 'adUnitCode': 'div-gpt-ad-1471513102552-1', + 'auctionId': '6fbd0562-f613-4151-a6df-6cb446fc717b', + 'params': [{ + 'adType': 'iab', + 'zone': 21521 + }], + 'timeout': 1 + }, { + 'bidId': '3b51df1f254e32', + 'bidder': 'justpremium', + 'adUnitCode': 'div-gpt-ad-1471513102552-3', + 'auctionId': '6fbd0562-f613-4151-a6df-6cb446fc717b', + 'params': [{ + 'adType': 'iab', + 'zone': 21521 + }], + 'timeout': 1 + }]) + + done() + }) + }) }) From bd607504cf208563b42d41742c9f3686fde3d182 Mon Sep 17 00:00:00 2001 From: onaydenov Date: Mon, 13 Aug 2018 17:12:27 +0200 Subject: [PATCH 0619/1594] Fidelity Media fmxSSP. Adding GDPR Support (#2935) * Add GDPR support * Add GDPR Support * Add GDPR support. Amended .js --- modules/fidelityBidAdapter.js | 42 +++++++++++++++----- test/spec/modules/fidelityBidAdapter_spec.js | 28 +++++++++++-- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/modules/fidelityBidAdapter.js b/modules/fidelityBidAdapter.js index ca7dc9d6fd6..fbe5e4b01cd 100644 --- a/modules/fidelityBidAdapter.js +++ b/modules/fidelityBidAdapter.js @@ -3,6 +3,7 @@ import {registerBidder} from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'fidelity'; const BIDDER_SERVER = 'x.fidelity-media.com'; +const FIDELITY_VENDOR_ID = 408; export const spec = { code: BIDDER_CODE, isBidRequestValid: function(bid) { @@ -20,16 +21,14 @@ export const spec = { zoneid: bidRequest.params.zoneid, floor: parseFloat(bidRequest.params.floor) > 0 ? bidRequest.params.floor : 0, charset: document.charSet || document.characterSet, - defloc: utils.getTopWindowUrl(), - altloc: window.location.href, subid: 'hb', flashver: getFlashVersion(), tmax: bidderRequest.timeout, + defloc: utils.getTopWindowUrl(), + referrer: utils.getTopWindowReferrer(), }; - if (document.referrer) { - payload.referrer = document.referrer; - } - + setConsentParams(bidderRequest.gdprConsent, payload); + return { method: 'GET', url: '//' + server + '/delivery/hb.php', @@ -59,12 +58,18 @@ export const spec = { } return bidResponses; }, - getUserSyncs: function getUserSyncs(syncOptions) { - if (syncOptions.iframeEnabled) { + getUserSyncs: function getUserSyncs(syncOptions, serverResponses, gdprConsent) { + if (syncOptions.iframeEnabled) { + var url = '//' + BIDDER_SERVER + '/delivery/matches.php'; + var payload = { + type: 'iframe' + }; + setConsentParams(gdprConsent, payload); + return [{ type: 'iframe', - url: '//' + BIDDER_SERVER + '/delivery/matches.php?type=iframe', - }]; + url: url + '?' + utils.parseQueryStringParameters(payload).replace(/\&$/, '') + }]; } } } @@ -84,4 +89,21 @@ function getFlashVersion() { return result || ''; } +function setConsentParams(gdprConsent, payload) { + if (gdprConsent) { + payload.gdpr = 0; + payload.consent_str = ''; + payload.consent_given = 0; + if (typeof gdprConsent.gdprApplies !== 'undefined') { + payload.gdpr = gdprConsent.gdprApplies ? 1 : 0; + } + if (typeof gdprConsent.consentString !== 'undefined') { + payload.consent_str = gdprConsent.consentString; + } + if (gdprConsent.vendorData && gdprConsent.vendorData.vendorConsents && typeof gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] !== 'undefined') { + payload.consent_given = gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] ? 1 : 0; + } + } +} + registerBidder(spec); diff --git a/test/spec/modules/fidelityBidAdapter_spec.js b/test/spec/modules/fidelityBidAdapter_spec.js index 28ea18aacac..007f4e6b480 100644 --- a/test/spec/modules/fidelityBidAdapter_spec.js +++ b/test/spec/modules/fidelityBidAdapter_spec.js @@ -52,7 +52,7 @@ describe('FidelityAdapter', () => { describe('buildRequests', () => { let bidderRequest = { bidderCode: 'fidelity', - auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', bidderRequestId: '178e34bad3658f', bids: [ { @@ -66,7 +66,7 @@ describe('FidelityAdapter', () => { sizes: [[300, 250], [320, 50]], bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', - auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } ], @@ -85,11 +85,31 @@ describe('FidelityAdapter', () => { expect(payload.zoneid).to.exist; expect(payload.floor).to.exist; expect(payload.charset).to.exist; - expect(payload.defloc).to.exist; - expect(payload.altloc).to.exist; expect(payload.subid).to.exist; expect(payload.flashver).to.exist; expect(payload.tmax).to.exist; + expect(payload.defloc).to.exist; + }); + + it('should add gdpr consent information to the request', () => { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + bidderRequest.gdprConsent = { + gdprApplies: true, + consentString: consentString, + vendorData: { + vendorConsents: { + '408': 1 + }, + }, + }; + const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + const payload = request.data; + expect(payload.gdpr).to.exist.and.to.be.a('number'); + expect(payload.gdpr).to.equal(1); + expect(payload.consent_str).to.exist.and.to.be.a('string'); + expect(payload.consent_str).to.equal(consentString); + expect(payload.consent_given).to.exist.and.to.be.a('number'); + expect(payload.consent_given).to.equal(1); }); it('sends bid request to ENDPOINT via GET', () => { From 700d5f24cc92d9f1e3a4ede79f54cb1ce20cac48 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 13 Aug 2018 11:45:11 -0400 Subject: [PATCH 0620/1594] lint fix (#2972) --- modules/fidelityBidAdapter.js | 106 +++++++++++++++++----------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/modules/fidelityBidAdapter.js b/modules/fidelityBidAdapter.js index fbe5e4b01cd..08a032bcba9 100644 --- a/modules/fidelityBidAdapter.js +++ b/modules/fidelityBidAdapter.js @@ -1,14 +1,14 @@ -import * as utils from 'src/utils'; -import {registerBidder} from 'src/adapters/bidderFactory'; - -const BIDDER_CODE = 'fidelity'; -const BIDDER_SERVER = 'x.fidelity-media.com'; -const FIDELITY_VENDOR_ID = 408; -export const spec = { - code: BIDDER_CODE, - isBidRequestValid: function(bid) { - return !!(bid && bid.params && bid.params.zoneid); - }, +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'fidelity'; +const BIDDER_SERVER = 'x.fidelity-media.com'; +const FIDELITY_VENDOR_ID = 408; +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: function(bid) { + return !!(bid && bid.params && bid.params.zoneid); + }, buildRequests: function(validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { var server = bidRequest.params.server || BIDDER_SERVER; @@ -25,10 +25,10 @@ export const spec = { flashver: getFlashVersion(), tmax: bidderRequest.timeout, defloc: utils.getTopWindowUrl(), - referrer: utils.getTopWindowReferrer(), + referrer: utils.getTopWindowReferrer(), }; - setConsentParams(bidderRequest.gdprConsent, payload); - + setConsentParams(bidderRequest.gdprConsent, payload); + return { method: 'GET', url: '//' + server + '/delivery/hb.php', @@ -36,13 +36,13 @@ export const spec = { }; }); }, - interpretResponse: function(serverResponse) { - serverResponse = serverResponse.body; + interpretResponse: function(serverResponse) { + serverResponse = serverResponse.body; const bidResponses = []; if (serverResponse && serverResponse.seatbid) { serverResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { const bidResponse = { - requestId: bid.impid, + requestId: bid.impid, creativeId: bid.impid, cpm: bid.price, width: bid.width, @@ -50,30 +50,30 @@ export const spec = { ad: bid.adm, netRevenue: bid.netRevenue, currency: bid.cur, - ttl: bid.ttl, + ttl: bid.ttl, }; bidResponses.push(bidResponse); })); } - return bidResponses; + return bidResponses; }, getUserSyncs: function getUserSyncs(syncOptions, serverResponses, gdprConsent) { - if (syncOptions.iframeEnabled) { - var url = '//' + BIDDER_SERVER + '/delivery/matches.php'; - var payload = { - type: 'iframe' - }; - setConsentParams(gdprConsent, payload); - - return [{ - type: 'iframe', - url: url + '?' + utils.parseQueryStringParameters(payload).replace(/\&$/, '') - }]; + if (syncOptions.iframeEnabled) { + var url = '//' + BIDDER_SERVER + '/delivery/matches.php'; + var payload = { + type: 'iframe' + }; + setConsentParams(gdprConsent, payload); + + return [{ + type: 'iframe', + url: url + '?' + utils.parseQueryStringParameters(payload).replace(/\&$/, '') + }]; } - } -} - + } +} + function getFlashVersion() { var plugins, plugin, result; @@ -87,23 +87,23 @@ function getFlashVersion() { } } return result || ''; -} - -function setConsentParams(gdprConsent, payload) { - if (gdprConsent) { - payload.gdpr = 0; - payload.consent_str = ''; - payload.consent_given = 0; - if (typeof gdprConsent.gdprApplies !== 'undefined') { - payload.gdpr = gdprConsent.gdprApplies ? 1 : 0; - } - if (typeof gdprConsent.consentString !== 'undefined') { - payload.consent_str = gdprConsent.consentString; - } - if (gdprConsent.vendorData && gdprConsent.vendorData.vendorConsents && typeof gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] !== 'undefined') { - payload.consent_given = gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] ? 1 : 0; - } - } -} - -registerBidder(spec); +} + +function setConsentParams(gdprConsent, payload) { + if (gdprConsent) { + payload.gdpr = 0; + payload.consent_str = ''; + payload.consent_given = 0; + if (typeof gdprConsent.gdprApplies !== 'undefined') { + payload.gdpr = gdprConsent.gdprApplies ? 1 : 0; + } + if (typeof gdprConsent.consentString !== 'undefined') { + payload.consent_str = gdprConsent.consentString; + } + if (gdprConsent.vendorData && gdprConsent.vendorData.vendorConsents && typeof gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] !== 'undefined') { + payload.consent_given = gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] ? 1 : 0; + } + } +} + +registerBidder(spec); From 5b4e3828111dd3b9a6c5965fdcd67800c0bd838e Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Mon, 13 Aug 2018 12:03:42 -0400 Subject: [PATCH 0621/1594] Fix safeFrame resize issue (#2947) * the dfp container div was not being resized, which results in content overlap * little cleanup --- src/secureCreatives.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 424d1402831..2204a6e7643 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -69,10 +69,14 @@ function sendAdToCreative(adObject, remoteDomain, source) { } function resizeRemoteCreative({ adUnitCode, width, height }) { - const iframe = document.getElementById( - find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot) - .getSlotElementId()).querySelector('iframe'); - - iframe.width = '' + width; - iframe.height = '' + height; + // resize both container div + iframe + ['div', 'iframe'].forEach(elmType => { + let elementStyle = getElementByAdUnit(elmType).style; + elementStyle.width = width; + elementStyle.height = height; + }); + function getElementByAdUnit(elmType) { + return document.getElementById(find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot) + .getSlotElementId()).querySelector(elmType); + } } From aa2860095b210f982013c720cd245424c0662dcb Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Mon, 13 Aug 2018 13:54:18 -0400 Subject: [PATCH 0622/1594] kargo analytics adapter (#2939) --- modules/kargoAnalyticsAdapter.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 modules/kargoAnalyticsAdapter.js diff --git a/modules/kargoAnalyticsAdapter.js b/modules/kargoAnalyticsAdapter.js new file mode 100644 index 00000000000..6bb77d926b5 --- /dev/null +++ b/modules/kargoAnalyticsAdapter.js @@ -0,0 +1,14 @@ +import adapter from 'src/AnalyticsAdapter'; +import adaptermanager from 'src/adaptermanager'; + +var kargoAdapter = adapter({ + analyticsType: 'endpoint', + url: 'https://krk.kargo.com/api/v1/event/prebid' +}); + +adaptermanager.registerAnalyticsAdapter({ + adapter: kargoAdapter, + code: 'kargo' +}); + +export default kargoAdapter; From 6f43b6bb1afd1e2799541f24f54d04803105f329 Mon Sep 17 00:00:00 2001 From: PWyrembak Date: Tue, 14 Aug 2018 02:46:50 +0300 Subject: [PATCH 0623/1594] Add wtimeout parameter in ad request for TrustX Bid Adapter (#2968) * Add wtimeout to ad request params for TrustX Bid Adapter * TrustX Bid Adapter: remove last ampersand in the ad request --- modules/trustxBidAdapter.js | 21 ++++++----- test/spec/modules/trustxBidAdapter_spec.js | 42 +++++++++++++--------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index 3688aa3b976..20e000e3379 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -60,19 +60,24 @@ export const spec = { r: reqId }; - if (bidderRequest && bidderRequest.gdprConsent) { - if (bidderRequest.gdprConsent.consentString) { - payload.gdpr_consent = bidderRequest.gdprConsent.consentString; + if (bidderRequest) { + 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; } - payload.gdpr_applies = - (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') - ? Number(bidderRequest.gdprConsent.gdprApplies) : 1; } return { method: 'GET', url: ENDPOINT_URL, - data: payload, + data: utils.parseQueryStringParameters(payload).replace(/\&$/, ''), bidsMap: bidsMap, }; }, @@ -84,7 +89,7 @@ export const spec = { * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: function(serverResponse, bidRequest) { - serverResponse = serverResponse && serverResponse.body + serverResponse = serverResponse && serverResponse.body; const bidResponses = []; const bidsMap = bidRequest.bidsMap; const priceType = bidRequest.data.pt; diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index 75405850d7a..2e099772593 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -39,6 +39,14 @@ describe('TrustXAdapter', function () { }); describe('buildRequests', () => { + function parseRequest(url) { + const res = {}; + url.split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } let bidRequests = [ { 'bidder': 'trustx', @@ -77,8 +85,8 @@ describe('TrustXAdapter', function () { it('should attach valid params to the tag', () => { const request = spec.buildRequests([bidRequests[0]]); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43'); @@ -87,8 +95,8 @@ describe('TrustXAdapter', function () { it('auids must not be duplicated', () => { const request = spec.buildRequests(bidRequests); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43,45'); @@ -98,8 +106,8 @@ describe('TrustXAdapter', function () { it('pt parameter must be "gross" if params.priceType === "gross"', () => { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'gross'); expect(payload).to.have.property('auids', '43,45'); @@ -110,8 +118,8 @@ describe('TrustXAdapter', function () { it('pt parameter must be "net" or "gross"', () => { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43,45'); @@ -121,26 +129,26 @@ describe('TrustXAdapter', function () { it('if gdprConsent is present payload must have gdpr params', () => { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); - const payload = request.data; - expect(payload).to.be.an('object'); + 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); + expect(payload).to.have.property('gdpr_applies', '1'); }); it('if gdprApplies is false gdpr_applies must be 0', () => { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); - const payload = request.data; - expect(payload).to.be.an('object'); + 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); + expect(payload).to.have.property('gdpr_applies', '0'); }); it('if gdprApplies is undefined gdpr_applies must be 1', () => { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); - const payload = request.data; - expect(payload).to.be.an('object'); + 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); + expect(payload).to.have.property('gdpr_applies', '1'); }); }); From 8134b0315a7de57c70122c7ebf8e9820c18a9cf5 Mon Sep 17 00:00:00 2001 From: Bas van Schaik Date: Tue, 14 Aug 2018 15:48:40 +0100 Subject: [PATCH 0624/1594] Add LGTM.com alert count badge (#2956) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fa3a11fbb88..e43833fd4d2 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![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) +[![Total Alerts](https://img.shields.io/lgtm/alerts/g/prebid/Prebid.js.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/prebid/Prebid.js/alerts/) # Prebid.js From e643997d45f0fbefc3e75e08e8513a080bd34ef9 Mon Sep 17 00:00:00 2001 From: Andy Blackwell Date: Tue, 14 Aug 2018 11:12:00 -0500 Subject: [PATCH 0625/1594] modified console logging to include a Prebid label, and normalized the calls to all work with N args like the native methods (#2966) --- src/utils.js | 70 ++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/src/utils.js b/src/utils.js index ac7f035d652..db50745ebcc 100644 --- a/src/utils.js +++ b/src/utils.js @@ -14,13 +14,11 @@ var tNumb = 'Number'; var tObject = 'Object'; var tBoolean = 'Boolean'; var toString = Object.prototype.toString; -let infoLogger = null; -let warnLogger = null; -try { - infoLogger = console.info.bind(window.console); - warnLogger = console.warn.bind(window.console); -} catch (e) { -} +let consoleExists = Boolean(window.console); +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); /* * Substitutes into a string from a given map using the token @@ -260,42 +258,43 @@ exports.getTopWindowReferrer = function() { } }; -exports.logWarn = function (msg, args) { - if (debugTurnedOn() && console.warn) { - if (warnLogger) { - if (!args || args.length === 0) { - args = ''; - } - - warnLogger('WARNING: ' + msg + ((args === '') ? '' : ' : params : '), args); - } +/** + * Wrappers to console.(log | info | warn | error). Takes N arguments, the same as the native methods + */ +exports.logMessage = function () { + if (debugTurnedOn() && consoleLogExists) { + console.log.apply(console, decorateLog(arguments, 'MESSAGE:')); } }; -exports.logInfo = function (msg, args) { - if (debugTurnedOn() && hasConsoleLogger()) { - if (infoLogger) { - if (!args || args.length === 0) { - args = ''; - } +exports.logInfo = function () { + if (debugTurnedOn() && consoleInfoExists) { + console.info.apply(console, decorateLog(arguments, 'INFO:')); + } +}; - infoLogger('INFO: ' + msg + ((args === '') ? '' : ' : params : '), args); - } +exports.logWarn = function () { + if (debugTurnedOn() && consoleWarnExists) { + console.warn.apply(console, decorateLog(arguments, 'WARNING:')); } }; -exports.logMessage = function (msg) { - if (debugTurnedOn() && hasConsoleLogger()) { - console.log('MESSAGE: ' + msg); +exports.logError = function () { + if (debugTurnedOn() && consoleErrorExists) { + console.error.apply(console, decorateLog(arguments, 'ERROR:')); } }; -function hasConsoleLogger() { - return (window.console && window.console.log); +function decorateLog(args, prefix) { + args = [].slice.call(args); + prefix && args.unshift(prefix); + args.unshift('display: inline-block; color: #fff; background: #3b88c3; padding: 1px 4px; border-radius: 3px;'); + args.unshift('%cPrebid'); + return args; } -function hasConsoleError() { - return (window.console && window.console.error); +function hasConsoleLogger() { + return consoleLogExists; } exports.hasConsoleLogger = hasConsoleLogger; @@ -312,15 +311,6 @@ var debugTurnedOn = function () { exports.debugTurnedOn = debugTurnedOn; -/** - * Wrapper to console.error. Takes N arguments to log the same as console.error. - */ -exports.logError = function () { - if (debugTurnedOn() && hasConsoleError()) { - console.error.apply(console, arguments); - } -}; - exports.createInvisibleIframe = function _createInvisibleIframe() { var f = document.createElement('iframe'); f.id = _getUniqueIdentifierStr(); From 6cc84aa03d7f2a830a8d0aba7e599bdada153d8f Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Tue, 14 Aug 2018 21:44:55 +0530 Subject: [PATCH 0626/1594] Feature : Display counter at Adslot level (#2940) * adunit refresh counter added * refresh counter added for media.net adapter * jsdoc added * renamed displayCount to bidRequestsCount --- modules/medianetBidAdapter.js | 3 +- src/adUnits.js | 34 ++++++++++++++++++ src/adaptermanager.js | 4 ++- src/prebid.js | 2 ++ test/spec/modules/medianetBidAdapter_spec.js | 36 +++++++++++++------- test/spec/unit/adUnits_spec.js | 23 +++++++++++++ 6 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 src/adUnits.js create mode 100644 test/spec/unit/adUnits_spec.js diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 4ff7bfd000e..07c721371bd 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -122,7 +122,8 @@ function slotParams(bidRequest) { let params = { id: bidRequest.bidId, ext: { - dfp_id: bidRequest.adUnitCode + dfp_id: bidRequest.adUnitCode, + display_count: bidRequest.bidRequestsCount }, banner: transformSizes(bidRequest.sizes), all: bidRequest.params diff --git a/src/adUnits.js b/src/adUnits.js new file mode 100644 index 00000000000..bbdc82b6073 --- /dev/null +++ b/src/adUnits.js @@ -0,0 +1,34 @@ +import { deepAccess } from './utils'; + +let adUnits = {}; + +/** + * Increments and returns current Adunit counter + * @param {string} adunit id + * @returns {number} current adunit count + */ +function incrementCounter(adunit) { + adUnits[adunit] = adUnits[adunit] || {}; + adUnits[adunit].counter = (deepAccess(adUnits, `${adunit}.counter`) + 1) || 1; + return adUnits[adunit].counter; +} + +/** + * Returns current Adunit counter + * @param {string} adunit id + * @returns {number} current adunit count + */ +function getCounter(adunit) { + return deepAccess(adUnits, `${adunit}.counter`) || 0; +} + +/** + * A module which counts how many times an adunit was called + * @module adunitCounter + */ +let adunitCounter = { + incrementCounter, + getCounter +} + +export { adunitCounter }; diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 5f0ac5b5656..009ba18347b 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -8,6 +8,7 @@ import { ajaxBuilder } from 'src/ajax'; import { config, RANDOM } from 'src/config'; import includes from 'core-js/library/fn/array/includes'; import find from 'core-js/library/fn/array/find'; +import { adunitCounter } from './adUnits'; var utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); @@ -95,7 +96,8 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { sizes: sizes, bidId: bid.bid_id || utils.getUniqueIdentifierStr(), bidderRequestId, - auctionId + auctionId, + bidRequestsCount: adunitCounter.getCounter(adUnit.code) })); } return bids; diff --git a/src/prebid.js b/src/prebid.js index 75e1d117c2a..ac7731d92fd 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -11,6 +11,7 @@ import { targeting, getHighestCpmBidsFromBidPool, RENDERED, BID_TARGETING_SET } import { createHook } from 'src/hook'; import { sessionLoader } from 'src/debugging'; import includes from 'core-js/library/fn/array/includes'; +import { adunitCounter } from './adUnits'; const $$PREBID_GLOBAL$$ = getGlobal(); const CONSTANTS = require('./constants.json'); @@ -367,6 +368,7 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa adUnit.bids = adUnit.bids.filter(bid => bid.bidder !== bidder); } }); + adunitCounter.incrementCounter(adUnit.code); }); if (!adUnits || adUnits.length === 0) { diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index d94cb64c145..027b23f54bb 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -17,7 +17,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 250]], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -33,7 +34,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 251]], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }], VALID_BID_REQUEST_INVALID_BIDFLOOR = [{ 'bidder': 'medianet', @@ -51,7 +53,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 250]], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -67,7 +70,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 251]], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }], VALID_AUCTIONDATA = { 'timeout': config.getConfig('bidderTimeout'), @@ -103,7 +107,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -133,7 +138,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -181,7 +187,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -210,7 +217,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -372,7 +380,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [300, 250], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -388,7 +397,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [300, 251], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }], VALID_BIDDER_REQUEST_WITH_GDPR = { 'gdprConsent': { @@ -429,7 +439,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -458,7 +469,8 @@ let VALID_BID_REQUEST = [{ x: 100, y: 100 } - } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, diff --git a/test/spec/unit/adUnits_spec.js b/test/spec/unit/adUnits_spec.js new file mode 100644 index 00000000000..ff77315ba4a --- /dev/null +++ b/test/spec/unit/adUnits_spec.js @@ -0,0 +1,23 @@ +import { expect } from 'chai'; +import { adunitCounter } from 'src/adUnits'; + +describe('Adunit Counter', function () { + const ADUNIT_ID_1 = 'test1'; + const ADUNIT_ID_2 = 'test2'; + + it('increments and checks counter of adunit 1', function () { + adunitCounter.incrementCounter(ADUNIT_ID_1); + expect(adunitCounter.getCounter(ADUNIT_ID_1)).to.be.equal(1); + }); + it('checks counter of adunit 2', function () { + expect(adunitCounter.getCounter(ADUNIT_ID_2)).to.be.equal(0); + }); + it('increments and checks counter of adunit 1', function () { + adunitCounter.incrementCounter(ADUNIT_ID_1); + expect(adunitCounter.getCounter(ADUNIT_ID_1)).to.be.equal(2); + }); + it('increments and checks counter of adunit 2', function () { + adunitCounter.incrementCounter(ADUNIT_ID_2); + expect(adunitCounter.getCounter(ADUNIT_ID_2)).to.be.equal(1); + }); +}); From 4ba1d4542e144c931b8b372e5b860f1c96a6d588 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Tue, 14 Aug 2018 14:10:07 -0400 Subject: [PATCH 0627/1594] Kargo adapter BidID support (#2958) * better support for bidIDs (multiple ad slots of same type) * currency config fix --- modules/kargoBidAdapter.js | 21 +++++---- test/spec/modules/kargoBidAdapter_spec.js | 57 +++++++++++++++++------ 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index dfcc3057ab7..1ba0f392d08 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -12,7 +12,10 @@ export const spec = { return !!bid.params.placementId; }, buildRequests: function(validBidRequests, bidderRequest) { - const currency = config.getConfig('currency'); + const currencyObj = config.getConfig('currency'); + const currency = (currencyObj && currencyObj.adServerCurrency) || 'USD'; + const bidIds = {}; + utils._each(validBidRequests, bid => bidIds[bid.bidId] = bid.params.placementId); const transformedParams = Object.assign({}, { timeout: bidderRequest.timeout, currency: currency, @@ -22,31 +25,29 @@ export const spec = { floor: 0, ceil: 20 }, - adSlotIDs: utils._map(validBidRequests, bid => bid.params.placementId) + bidIDs: bidIds }, spec._getAllMetadata()); const encodedParams = encodeURIComponent(JSON.stringify(transformedParams)); return Object.assign({}, bidderRequest, { method: 'GET', - url: `${HOST}/api/v1/bid`, + url: `${HOST}/api/v2/bid`, data: `json=${encodedParams}`, currency: currency }); }, interpretResponse: function(response, bidRequest) { - let adUnits = response.body; - let bids = {}; - utils._each(bidRequest.bids, bid => bids[bid.params.placementId] = bid); + let bids = response.body; const bidResponses = []; - for (let adUnitId in adUnits) { - let adUnit = adUnits[adUnitId]; + for (let bidId in bids) { + let adUnit = bids[bidId]; bidResponses.push({ - requestId: bids[adUnitId].bidId, + requestId: bidId, cpm: Number(adUnit.cpm), width: adUnit.width, height: adUnit.height, ad: adUnit.adm, ttl: 300, - creativeId: adUnitId, + creativeId: adUnit.id, netRevenue: true, currency: bidRequest.currency }); diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index bb0feeba069..432ae086511 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -50,13 +50,19 @@ describe('kargo adapter tests', function () { params: { placementId: 'foo' }, - placementCode: 1 + bidId: 1 }, { params: { placementId: 'bar' }, - placementCode: 2 + bidId: 2 + }, + { + params: { + placementId: 'bar' + }, + bidId: 3 } ]; }); @@ -173,10 +179,11 @@ describe('kargo adapter tests', function () { floor: 0, ceil: 20 }, - adSlotIDs: [ - 'foo', - 'bar' - ], + bidIDs: { + 1: 'foo', + 2: 'bar', + 3: 'bar' + }, userIDs: { kargoID: '5f108831-302d-11e7-bf6b-4595acd3bf6c', clientID: '2410d8f2-c111-4811-88a5-7b5e190e475f', @@ -235,7 +242,7 @@ describe('kargo adapter tests', function () { var request = spec.buildRequests(bids, {timeout: 200, foo: 'bar'}); var krakenParams = JSON.parse(decodeURIComponent(request.data.slice(5))); expect(request.data.slice(0, 5)).to.equal('json='); - expect(request.url).to.equal('https://krk.kargo.com/api/v1/bid'); + expect(request.url).to.equal('https://krk.kargo.com/api/v2/bid'); expect(request.method).to.equal('GET'); expect(request.currency).to.equal('USD'); expect(request.timeout).to.equal(200); @@ -306,13 +313,22 @@ describe('kargo adapter tests', function () { describe('response handler', function() { it('handles bid responses', function() { var resp = spec.interpretResponse({body: { - foo: { + 1: { + id: 'foo', cpm: 3, adm: '
', width: 320, height: 50 }, - bar: { + 2: { + id: 'bar', + cpm: 2.5, + adm: '
', + width: 300, + height: 250 + }, + 3: { + id: 'bar', cpm: 2.5, adm: '
', width: 300, @@ -321,19 +337,24 @@ describe('kargo adapter tests', function () { }}, { currency: 'USD', bids: [{ - bidId: 'fake bid id 1', + bidId: 1, params: { placementId: 'foo' } }, { - bidId: 'fake bid id 2', + bidId: 2, + params: { + placementId: 'bar' + } + }, { + bidId: 3, params: { placementId: 'bar' } }] }); var expectation = [{ - requestId: 'fake bid id 1', + requestId: '1', cpm: 3, width: 320, height: 50, @@ -343,7 +364,17 @@ describe('kargo adapter tests', function () { netRevenue: true, currency: 'USD' }, { - requestId: 'fake bid id 2', + requestId: '2', + cpm: 2.5, + width: 300, + height: 250, + ad: '
', + ttl: 300, + creativeId: 'bar', + netRevenue: true, + currency: 'USD' + }, { + requestId: '3', cpm: 2.5, width: 300, height: 250, From ba1671c0b112a01617ab7ab9cb5b7a827440c27c Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 14 Aug 2018 14:26:43 -0400 Subject: [PATCH 0628/1594] 1.20.0 release. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64138f4a3aa..b23544f9268 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.20.0-pre", + "version": "1.20.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From caa9c0fdc4b642aa823542fd13b4f133ef269ecd Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 14 Aug 2018 14:50:05 -0400 Subject: [PATCH 0629/1594] 1.21.0-pre --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b23544f9268..efb57eb9c59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.20.0", + "version": "1.21.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 5e430e382922ee16e5e0cefa88198b9a01e60ba2 Mon Sep 17 00:00:00 2001 From: Jerome Eteve Date: Wed, 15 Aug 2018 19:16:47 +0100 Subject: [PATCH 0630/1594] Added render param in Sonobi adapter (#2970) --- modules/sonobiBidAdapter.js | 3 +++ test/spec/modules/sonobiBidAdapter_spec.js | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 3d9ad2ce976..779736520cc 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -66,6 +66,9 @@ export const spec = { if (validBidRequests[0].params.referrer) { payload.ref = validBidRequests[0].params.referrer; } + if (validBidRequests[0].params.render) { + payload.render = validBidRequests[0].params.render; + } // Apply GDPR parameters to request. if (bidderRequest && bidderRequest.gdprConsent) { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 1b0986cb8c1..63fb52b2dbd 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -207,6 +207,11 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.s).not.to.be.empty expect(bidRequests.data.hfa).to.equal('hfakey') }) + it('should return a properly formatted request with render', () => { + bidRequest[0].params.render = 'safeframe' + const bidRequests = spec.buildRequests(bidRequest) + expect(bidRequests.data.render).to.equal('safeframe') + }) it('should return null if there is nothing to bid on', () => { const bidRequests = spec.buildRequests([{params: {}}]) From 2fb1d951ac23393cbabe0403491ec6261911367f Mon Sep 17 00:00:00 2001 From: yoshito oe Date: Thu, 16 Aug 2018 03:42:54 +0900 Subject: [PATCH 0631/1594] AJA adapter (#2934) * AJA Bid Adapter * fix markdown * delete log * multiple tracking support * semicolon * fix test parameters * v1 -> v2 * add parameters * JPY -> USD --- modules/ajaBidAdapter.js | 142 +++++++++++++++++++++++ modules/ajaBidAdapter.md | 52 +++++++++ test/spec/modules/ajaBidAdapter_spec.js | 144 ++++++++++++++++++++++++ 3 files changed, 338 insertions(+) create mode 100644 modules/ajaBidAdapter.js create mode 100644 modules/ajaBidAdapter.md create mode 100644 test/spec/modules/ajaBidAdapter_spec.js diff --git a/modules/ajaBidAdapter.js b/modules/ajaBidAdapter.js new file mode 100644 index 00000000000..bbdbeb53886 --- /dev/null +++ b/modules/ajaBidAdapter.js @@ -0,0 +1,142 @@ +import { Renderer } from 'src/Renderer'; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { VIDEO, BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'aja'; +const URL = '//ad.as.amanad.adtdp.com/v2/prebid'; +const SDK_TYPE = 5; +const AD_TYPE = { + BANNER: 1, + NATIVE: 2, + VIDEO: 3, +}; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [VIDEO, BANNER], + + isBidRequestValid: function(bid) { + return !!(bid.params.asi); + }, + + buildRequests: function(validBidRequests, bidderRequest) { + var bidRequests = []; + for (var i = 0, len = validBidRequests.length; i < len; i++) { + var bid = validBidRequests[i]; + var queryString = ''; + 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$'); + + bidRequests.push({ + method: 'GET', + url: URL, + data: queryString + }); + } + + return bidRequests; + }, + + interpretResponse: function(bidderResponse, request) { + const bidderResponseBody = bidderResponse.body; + + if (!bidderResponseBody.is_ad_return) { + return []; + } + + const ad = bidderResponseBody.ad; + + const bid = { + requestId: ad.prebid_id, + cpm: ad.price, + creativeId: ad.creative_id, + dealId: ad.deal_id, + currency: ad.currency || 'USD', + netRevenue: true, + ttl: 300, // 5 minutes + } + + if (AD_TYPE.VIDEO === ad.ad_type) { + const videoAd = bidderResponseBody.ad.video; + Object.assign(bid, { + vastXml: videoAd.vtag, + width: videoAd.w, + height: videoAd.h, + renderer: newRenderer(bidderResponseBody), + adResponse: bidderResponseBody, + mediaType: VIDEO + }); + } else if (AD_TYPE.BANNER === ad.ad_type) { + const bannerAd = bidderResponseBody.ad.banner; + Object.assign(bid, { + width: bannerAd.w, + height: bannerAd.h, + ad: bannerAd.tag, + mediaType: BANNER + }); + try { + bannerAd.imps.forEach(impTracker => { + const tracker = utils.createTrackPixelHtml(impTracker); + bid.ad += tracker; + }); + } catch (error) { + utils.logError('Error appending tracking pixel', error); + } + } + + return [bid]; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = []; + if (syncOptions.pixelEnabled) { + const bidderResponseBody = serverResponses[0].body; + if (bidderResponseBody.syncs) { + bidderResponseBody.syncs.forEach(sync => { + syncs.push({ + type: 'image', + url: sync + }); + }); + } + } + + return syncs; + }, +} + +function newRenderer(bidderResponse) { + const renderer = Renderer.install({ + id: bidderResponse.ad.prebid_id, + url: bidderResponse.ad.video.purl, + loaded: false, + }); + + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on newRenderer', err); + } + + return renderer; +} + +function outstreamRender(bid) { + bid.renderer.push(() => { + window.aja_vast_player.init({ + vast_tag: bid.adResponse.ad.video.vtag, + ad_unit_code: bid.adUnitCode, // target div id to render video + width: bid.width, + height: bid.height, + progress: bid.adResponse.ad.video.progress, + loop: bid.adResponse.ad.video.loop, + inread: bid.adResponse.ad.video.inread + }); + }); +} + +registerBidder(spec); diff --git a/modules/ajaBidAdapter.md b/modules/ajaBidAdapter.md new file mode 100644 index 00000000000..ea2b8e97a43 --- /dev/null +++ b/modules/ajaBidAdapter.md @@ -0,0 +1,52 @@ +# Overview + +``` +Module Name: Aja Bid adapter +Module Type: Bidder adapter +Maintainer: ssp_support@aja-kk.co.jp +``` + +# Description +Connects to Aja exchange for bids. +Aja bid adapter supports Banner and Outstream Video. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250] + ], + } + }, + bids: [{ + bidder: 'aja', + params: { + asi: 'szs4htFiR' + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [300, 250] + } + }, + bids: [ + { + bidder: 'aja', + params: { + asi: 'Kp2O2tFig' + } + } + ] + } +]; +``` diff --git a/test/spec/modules/ajaBidAdapter_spec.js b/test/spec/modules/ajaBidAdapter_spec.js new file mode 100644 index 00000000000..c6a531c9f1f --- /dev/null +++ b/test/spec/modules/ajaBidAdapter_spec.js @@ -0,0 +1,144 @@ +import { spec } from 'modules/ajaBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//ad.as.amanad.adtdp.com/v2/prebid'; + +describe('AjaAdapter', () => { + const adapter = newBidder(spec); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'aja', + 'params': { + 'asi': '123456' + }, + 'adUnitCode': 'adunit', + 'sizes': [[300, 250]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'asi': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': 'aja', + 'params': { + 'asi': '123456' + }, + 'adUnitCode': 'adunit', + 'sizes': [[300, 250]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('sends bid request to ENDPOINT via GET', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].url).to.equal(ENDPOINT); + expect(requests[0].method).to.equal('GET'); + }); + }); + describe('interpretResponse', () => { + let response = { + 'is_ad_return': true, + 'ad': { + 'ad_type': 1, + 'prebid_id': '51ef8751f9aead', + 'price': 12.34, + 'currency': 'USD', + 'creative_id': '123abc', + 'banner': { + 'w': 300, + 'h': 250, + 'tag': '
', + 'imps': [ + '//as.amanad.adtdp.com/v1/imp' + ] + } + }, + 'syncs': [ + 'https://example.com' + ] + }; + + it('should get correct banner bid response', () => { + let expectedResponse = [ + { + 'requestId': '51ef8751f9aead', + 'cpm': 12.34, + 'creativeId': '123abc', + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true + } + ]; + + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles video responses', () => { + let response = { + 'is_ad_return': true, + 'ad': { + 'ad_type': 3, + 'prebid_id': '51ef8751f9aead', + 'price': 12.34, + 'currency': 'JPY', + 'creative_id': '123abc', + 'video': { + 'w': 300, + 'h': 250, + 'vtag': '', + 'purl': 'http://cdn/player', + 'progress': true, + 'loop': false, + 'inread': false + } + }, + 'syncs': [ + 'https://example.com' + ] + }; + + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result[0]).to.have.property('vastXml'); + expect(result[0]).to.have.property('renderer'); + expect(result[0]).to.have.property('mediaType', 'video'); + }); + + it('handles nobid responses', () => { + let response = { + 'is_ad_return': false, + 'ad': {} + }; + + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result.length).to.equal(0); + }); + }); +}); From ee02e13bb0838877eb666705cb740f53849d432b Mon Sep 17 00:00:00 2001 From: AdmixerTech <35560933+AdmixerTech@users.noreply.github.com> Date: Wed, 15 Aug 2018 21:46:03 +0300 Subject: [PATCH 0632/1594] Add DivReach adapter (#2946) --- modules/divreachBidAdapter.js | 74 ++++++++++++ modules/divreachBidAdapter.md | 52 +++++++++ test/spec/modules/divreachBidAdapter_spec.js | 117 +++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 modules/divreachBidAdapter.js create mode 100644 modules/divreachBidAdapter.md create mode 100644 test/spec/modules/divreachBidAdapter_spec.js diff --git a/modules/divreachBidAdapter.js b/modules/divreachBidAdapter.js new file mode 100644 index 00000000000..e597e32f4be --- /dev/null +++ b/modules/divreachBidAdapter.js @@ -0,0 +1,74 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'divreach'; +const ENDPOINT_URL = '//ads.divreach.com/prebid.1.0.aspx'; +export const spec = { + code: BIDDER_CODE, + aliases: [], + 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) { + return !!bid.params.zone; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {bidderRequest} - bidderRequest.bids[] is an array of AdUnits and bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (bidderRequest) { + const payload = { + imps: [], + referrer: encodeURIComponent(utils.getTopWindowUrl()), + }; + bidderRequest.forEach((bid) => { + if (bid.bidder === BIDDER_CODE) { + payload.imps.push(bid); + } + }); + const payloadString = JSON.stringify(payload); + return { + method: 'GET', + url: ENDPOINT_URL, + data: `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, bidRequest) { + const bidResponses = []; + // loop through serverResponses { + try { + serverResponse = serverResponse.body; + serverResponse.forEach((bidResponse) => { + const bidResp = { + requestId: bidResponse.bidId, + cpm: bidResponse.cpm, + width: bidResponse.width, + height: bidResponse.height, + ad: bidResponse.ad, + ttl: bidResponse.ttl, + creativeId: bidResponse.creativeId, + netRevenue: bidResponse.netRevenue, + currency: bidResponse.currency, + vastUrl: bidResponse.vastUrl, + }; + bidResponses.push(bidResp); + }); + } catch (e) { + utils.logError(e); + } + return bidResponses; + } +}; +registerBidder(spec); diff --git a/modules/divreachBidAdapter.md b/modules/divreachBidAdapter.md new file mode 100644 index 00000000000..da2ebee97cf --- /dev/null +++ b/modules/divreachBidAdapter.md @@ -0,0 +1,52 @@ +# Overview + +Module Name: DivReach Bidder Adapter +Module Type: Bidder Adapter +Maintainer: Zeke@divreach.com + +# Description + +Connects to DivReach demand source to fetch bids. +Banner and Video formats are supported. +Please use ```divreach``` as the bidder code. + +# Test Parameters +``` + var adUnits = [ + { + code: 'desktop-banner-ad-div', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "divreach", + params: { + zone: '261eae83-0508-4e1a-8c9b-19561fa9279e' + } + } + ] + },{ + code: 'mobile-banner-ad-div', + sizes: [[300, 50]], // a mobile size + bids: [ + { + bidder: "divreach", + params: { + zone: '561e26ea-1999-4fb6-ad0b-9d72929e545e' + } + } + ] + },{ + code: 'video-ad', + sizes: [[300, 50]], + mediaType: 'video', + bids: [ + { + bidder: "divreach", + params: { + zone: 'e784ecbe-720f-46f7-8388-aff8c2c4ed86' + } + } + ] + }, + ]; +``` diff --git a/test/spec/modules/divreachBidAdapter_spec.js b/test/spec/modules/divreachBidAdapter_spec.js new file mode 100644 index 00000000000..8beb0830385 --- /dev/null +++ b/test/spec/modules/divreachBidAdapter_spec.js @@ -0,0 +1,117 @@ +import {expect} from 'chai'; +import {spec} from 'modules/divreachBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'divreach'; +const ENDPOINT_URL = '//ads.divreach.com/prebid.1.0.aspx'; +const ZONE_ID = '2eb6bd58-865c-47ce-af7f-a918108c3fd2'; + +describe('DivReachAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.be.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': BIDDER_CODE, + 'params': { + 'zone': ZONE_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + 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 = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'zone': ZONE_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should add referrer and imp to be equal bidRequest', () => { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data.substr(5)); + expect(payload.referrer).to.not.be.undefined; + expect(payload.imps[0]).to.deep.equal(bidRequests[0]); + }); + + it('sends bid request to ENDPOINT via GET', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT_URL); + expect(request.method).to.equal('GET'); + }); + }); + + describe('interpretResponse', () => { + let response = { + body: [{ + 'currency': 'USD', + 'cpm': 6.210000, + 'ad': '
ad
', + 'width': 300, + 'height': 600, + 'creativeId': 'ccca3e5e-0c54-4761-9667-771322fbdffc', + 'ttl': 360, + 'netRevenue': false, + 'bidId': '5e4e763b6bc60b' + }] + }; + + it('should get correct bid response', () => { + const body = response.body; + let expectedResponse = [ + { + 'requestId': body[0].bidId, + 'cpm': body[0].cpm, + 'creativeId': body[0].creativeId, + 'width': body[0].width, + 'height': body[0].height, + 'ad': body[0].ad, + 'vastUrl': undefined, + 'currency': body[0].currency, + 'netRevenue': body[0].netRevenue, + 'ttl': body[0].ttl, + } + ]; + + let result = spec.interpretResponse(response); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + it('handles nobid responses', () => { + let response = []; + + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From ab2d7fcf6d937cdbca75cfef180ae0ac1b3a62fe Mon Sep 17 00:00:00 2001 From: Margaret Liu Date: Thu, 16 Aug 2018 09:38:06 -0500 Subject: [PATCH 0633/1594] Add adUnitCode to LockerDome bid requests (#2979) --- modules/lockerdomeBidAdapter.js | 1 + test/spec/modules/lockerdomeBidAdapter_spec.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/modules/lockerdomeBidAdapter.js b/modules/lockerdomeBidAdapter.js index 43c8a15c37b..d4b4e048b8b 100644 --- a/modules/lockerdomeBidAdapter.js +++ b/modules/lockerdomeBidAdapter.js @@ -12,6 +12,7 @@ export const spec = { const adUnitBidRequests = bidRequests.map(function (bid) { return { requestId: bid.bidId, + adUnitCode: bid.adUnitCode, adUnitId: utils.getBidIdParameter('adUnitId', bid.params), sizes: bid.sizes } diff --git a/test/spec/modules/lockerdomeBidAdapter_spec.js b/test/spec/modules/lockerdomeBidAdapter_spec.js index 84f0dd43e72..19884065597 100644 --- a/test/spec/modules/lockerdomeBidAdapter_spec.js +++ b/test/spec/modules/lockerdomeBidAdapter_spec.js @@ -65,12 +65,14 @@ describe('LockerDomeAdapter', () => { expect(bids).to.have.lengthOf(2); expect(bids[0].requestId).to.equal('2652ca954bce9'); + expect(bids[0].adUnitCode).to.equal('ad-1'); expect(bids[0].adUnitId).to.equal(10809467961050726); expect(bids[0].sizes).to.have.lengthOf(1); expect(bids[0].sizes[0][0]).to.equal(300); expect(bids[0].sizes[0][1]).to.equal(250); expect(bids[1].requestId).to.equal('4510f2834773ce'); + expect(bids[1].adUnitCode).to.equal('ad-2'); expect(bids[1].adUnitId).to.equal(9434769725128806); expect(bids[1].sizes).to.have.lengthOf(1); expect(bids[1].sizes[0][0]).to.equal(300); From 17f11da091b456a19da6f07ee53370902aedd9a9 Mon Sep 17 00:00:00 2001 From: Daniel Grek Date: Thu, 16 Aug 2018 17:43:10 +0200 Subject: [PATCH 0634/1594] AdForm Adapter - setting alias code in received bids (#2976) --- modules/adformBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index 889c8ba4813..cc64b49d8f7 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -15,6 +15,7 @@ export const spec = { var request = []; var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ] ]; var bids = JSON.parse(JSON.stringify(validBidRequests)); + var bidder = (bids[0] && bids[0].bidder) || BIDDER_CODE for (i = 0, l = bids.length; i < l; i++) { bid = bids[i]; if ((bid.params.priceType === 'net') || (bid.params.pt === 'net')) { @@ -60,7 +61,7 @@ export const spec = { url: request.join('&'), bids: validBidRequests, netRevenue: netRevenue, - bidder: 'adform', + bidder, gdpr: gdprObject }; From 014fffe4d1e17555b41415c5c11444b3c1ef1915 Mon Sep 17 00:00:00 2001 From: bretg Date: Mon, 20 Aug 2018 12:50:23 -0400 Subject: [PATCH 0635/1594] changing rubicon endpoint to openrtb2 endpoint (#2996) * changing rubicon endpoint to openrtb2 endpoint * updated test for rubicon prebid server endpoint --- modules/prebidServerBidAdapter/config.js | 2 +- test/spec/modules/prebidServerBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/prebidServerBidAdapter/config.js b/modules/prebidServerBidAdapter/config.js index a2b0b6bec77..74eb4a95744 100644 --- a/modules/prebidServerBidAdapter/config.js +++ b/modules/prebidServerBidAdapter/config.js @@ -12,7 +12,7 @@ export const S2S_VENDORS = { adapter: 'prebidServer', cookieSet: false, enabled: true, - endpoint: '//prebid-server.rubiconproject.com/auction', + endpoint: '//prebid-server.rubiconproject.com/openrtb2/auction', syncEndpoint: '//prebid-server.rubiconproject.com/cookie_sync', timeout: 500 } diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index f3cc150ab6e..556755316eb 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1092,7 +1092,7 @@ describe('S2S Adapter', () => { expect(vendorConfig.cookieSet).to.be.false; expect(vendorConfig.cookieSetUrl).to.be.undefined; expect(vendorConfig.enabled).to.be.true; - expect(vendorConfig).to.have.property('endpoint', '//prebid-server.rubiconproject.com/auction'); + expect(vendorConfig).to.have.property('endpoint', '//prebid-server.rubiconproject.com/openrtb2/auction'); expect(vendorConfig).to.have.property('syncEndpoint', '//prebid-server.rubiconproject.com/cookie_sync'); expect(vendorConfig).to.have.property('timeout', 750); }); From db2fdfad1537583d2f4d56e6ffd2deed88e9de9d Mon Sep 17 00:00:00 2001 From: Bryan DeLong Date: Mon, 20 Aug 2018 14:56:57 -0400 Subject: [PATCH 0636/1594] SomoAudience Adapter Enhancements (#2986) * Support additional targeting options, support video, support GDPR, and implement usersync pixels More work cleaning up tests and making sure this stuff actually worked Documentation Updates * Trying to fix Mac-only errors * Squashing more bugs that cropped up * Added additional parameter for userip * Delete package-lock.json * Fix accidently deleting a file --- modules/somoaudienceBidAdapter.js | 195 ++++++- modules/somoaudienceBidAdapter.md | 2 + .../modules/somoaudienceBidAdapter_spec.js | 548 +++++++++++++++--- 3 files changed, 636 insertions(+), 109 deletions(-) diff --git a/modules/somoaudienceBidAdapter.js b/modules/somoaudienceBidAdapter.js index 7655eb9e2e0..836d87417cc 100644 --- a/modules/somoaudienceBidAdapter.js +++ b/modules/somoaudienceBidAdapter.js @@ -1,19 +1,30 @@ -import {getTopWindowReferrer, getTopWindowLocation} from 'src/utils'; +import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; +import includes from 'core-js/library/fn/array/includes'; +import {BANNER, VIDEO} from 'src/mediaTypes'; + +const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', + 'startdelay', 'linearity', 'skip', 'delivery', + 'pos', 'api', 'ext', 'battr']; +const BANNER_TARGETING = ['battr', 'btype', 'pos', 'mimes', 'ext']; + +const SITE_TARGETING = ['name', 'domain', 'cat', 'keywords', 'content'] +const APP_TARGETING = ['name', 'bundle', 'domain', 'storeUrl', 'cat', 'ver', 'keywords', 'content'] export const spec = { code: 'somoaudience', + supportedMediaTypes: [BANNER, VIDEO], aliases: ['somo'], isBidRequestValid: bid => ( !!(bid && bid.params && bid.params.placementId) ), - buildRequests: function(bidRequests) { + buildRequests: function(bidRequests, bidderRequest) { return bidRequests.map(bidRequest => { - let da = openRtbRequest(bidRequest); + let da = openRtbRequest(bidRequest, bidderRequest); if (window.top1 && window.top1.realvu_aa) { let a = window.top1.realvu_aa.check({ unit_id: bidRequest.adUnitCode, @@ -48,51 +59,135 @@ export const spec = { interpretResponse(response, request) { return bidResponseAvailable(request, response); + }, + + getUserSyncs: (syncOptions, serverResponses, gdprConsent) => { + const syncs = []; + var url = '//publisher-east.mobileadtrading.com/usersync'; + + if (syncOptions.pixelEnabled) { + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + // add 'gdpr' only if 'gdprApplies' is defined + if (typeof gdprConsent.gdprApplies === 'boolean') { + url += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } + } + syncs.push({ + type: 'image', + url: url + }); + } + return syncs; } }; function bidResponseAvailable(bidRequest, bidResponse) { let bidResponses = []; - let bidId = 1; - if (typeof bidRequest != 'undefined' && typeof bidRequest.bidRequest != 'undefined' && typeof bidRequest.bidRequest.bidId != 'undefined') { - bidId = bidRequest.bidRequest.bidId; - } if (bidResponse.body) { let bidData = bidResponse.body.seatbid[0].bid[0]; const bid = { - requestId: bidId, + requestId: bidData.impid, cpm: bidData.price, width: bidData.w, height: bidData.h, ad: bidData.adm, ttl: 360, creativeId: bidData.crid, - adId: bidId, + adId: bidData.impid, netRevenue: false, currency: 'USD', }; + if (isVideo(bidRequest.bidRequest)) { + bid.vastXml = bidData.adm; + bid.mediaType = 'video'; + } else { + bid.ad = bidData.adm; + bid.mediaType = 'banner'; + } bidResponses.push(bid); } return bidResponses; } -function openRtbRequest(bidRequest) { - return { +function openRtbRequest(bidRequest, bidderRequest) { + var openRtbRequest = { id: bidRequest.bidderRequestId, imp: [openRtbImpression(bidRequest)], at: 1, tmax: 400, site: openRtbSite(bidRequest), app: openRtbApp(bidRequest), - device: openRtbDevice() + device: openRtbDevice(), + bcat: openRtbBCat(bidRequest), + badv: openRtbBAdv(bidRequest), + ext: { + prebid: '$prebid.version$', + }, }; + if (bidderRequest != undefined) { + openRtbRequest = populateOpenRtbGdpr(bidderRequest.gdprConsent, openRtbRequest); + } + + return openRtbRequest; +} + +function populateOpenRtbGdpr(gdpr, bidRequest) { + if (gdpr && bidRequest && 'gdprApplies' in gdpr) { + if (!('reqs' in bidRequest)) { + bidRequest.reqs = {}; + } + if (!('ext' in bidRequest.reqs)) { + bidRequest.reqs.ext = {}; + } + bidRequest.reqs.ext.gdpr = gdpr.gdprApplies; + + if ('consentString' in gdpr) { + if (!('user' in bidRequest)) { + bidRequest.user = {}; + } + if (!('ext' in bidRequest.user)) { + bidRequest.user.ext = {}; + } + bidRequest.user.ext.consent = gdpr.consentString; + } + } + + return bidRequest; } function openRtbImpression(bidRequest) { - return { - id: bidRequest.bidId, - banner: {} + const imp = { + 'id': bidRequest.bidId, + bidfloor: bidRequest.params.bidfloor || 0, }; + if (isVideo(bidRequest)) { + imp.video = {}; + if (bidRequest.sizes) { + const sizes = getSizes(bidRequest.sizes); + imp.video.w = sizes[0]; + imp.video.h = sizes[1]; + } + if (bidRequest.params.video) { + Object.keys(bidRequest.params.video) + .filter(param => includes(VIDEO_TARGETING, param)) + .forEach(param => imp.video[param] = bidRequest.params.video[param]); + } + } else { + imp.banner = { + topframe: 0 + }; + if (bidRequest.sizes) { + const sizes = getSizes(bidRequest.sizes); + imp.banner.w = sizes[0]; + imp.banner.h = sizes[1]; + } + if (bidRequest.params.banner) { + Object.keys(bidRequest.params.banner) + .filter(param => includes(BANNER_TARGETING, param)) + .forEach(param => imp.banner[param] = bidRequest.params.banner[param]); + } + } + return imp; } function isApp(bidRequest) { @@ -105,13 +200,20 @@ function isApp(bidRequest) { function openRtbSite(bidRequest) { if (!isApp(bidRequest)) { - const pageUrl = getTopWindowLocation().href; - const domain = getTopWindowLocation().hostname; - return { - ref: getTopWindowReferrer(), - page: pageUrl, - domain: domain + const site = { + ref: utils.getTopWindowReferrer(), + page: utils.getTopWindowLocation().href + }; + if (bidRequest.params.site) { + Object.keys(bidRequest.params.site) + .filter(param => includes(SITE_TARGETING, param)) + .forEach(param => site[param] = bidRequest.params.site[param]); + } + if (site.domain == undefined) { + site.domain = utils.getTopWindowLocation().hostname; } + + return site; } else { return null; } @@ -119,13 +221,14 @@ function openRtbSite(bidRequest) { function openRtbApp(bidRequest) { if (isApp(bidRequest)) { - const appParams = bidRequest.params.app; - return { - bundle: appParams.bundle ? appParams.bundle : null, - storeurl: appParams.storeUrl ? appParams.storeUrl : null, - domain: appParams.domain ? appParams.domain : null, - name: appParams.name ? appParams.name : null, + const app = { + } + Object.keys(bidRequest.params.app) + .filter(param => includes(APP_TARGETING, param)) + .forEach(param => app[param] = bidRequest.params.app[param]); + + return app; } else { return null; } @@ -133,9 +236,47 @@ function openRtbApp(bidRequest) { function openRtbDevice() { return { + ip: 'check', ua: navigator.userAgent, language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), }; } +function openRtbBCat(bidRequest) { + if (utils.isArray(bidRequest.params.bcat)) { + return bidRequest.params.bcat; + } + return []; +} + +function openRtbBAdv(bidRequest) { + if (utils.isArray(bidRequest.params.badv)) { + return bidRequest.params.badv; + } + return []; +} + +function isVideo (format) { + return utils.deepAccess(format, 'mediaTypes.video') || format.mediaType == 'video'; +} + +/* Turn bid request sizes into compatible format */ +function getSizes(requestSizes) { + let width = 0; + let height = 0; + if (utils.isArray(requestSizes) && requestSizes.length === 2 && + !utils.isArray(requestSizes[0])) { + width = parseInt(requestSizes[0], 10); + height = parseInt(requestSizes[1], 10); + } else if (typeof requestSizes === 'object') { + for (let i = 0; i < requestSizes.length; i++) { + let size = requestSizes[i]; + width = parseInt(size[0], 10); + height = parseInt(size[1], 10); + break; + } + } + return [width, height]; +} + registerBidder(spec); diff --git a/modules/somoaudienceBidAdapter.md b/modules/somoaudienceBidAdapter.md index a622d73d84b..10af6023cb5 100644 --- a/modules/somoaudienceBidAdapter.md +++ b/modules/somoaudienceBidAdapter.md @@ -6,6 +6,8 @@ # Description Connects to Somo Audience demand source. Please use ```somoaudience``` as the bidder code. + +For video integration, somoAudience 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 # Test Site Parameters ``` var adUnits = [{ diff --git a/test/spec/modules/somoaudienceBidAdapter_spec.js b/test/spec/modules/somoaudienceBidAdapter_spec.js index 2189cacb0ec..79ece7ffcf6 100644 --- a/test/spec/modules/somoaudienceBidAdapter_spec.js +++ b/test/spec/modules/somoaudienceBidAdapter_spec.js @@ -1,97 +1,481 @@ import {expect} from 'chai'; import {spec} from 'modules/somoaudienceBidAdapter'; -import {getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; describe('Somo Audience Adapter Tests', () => { - const bidderSet = [ - { - bidder: 'somoaudience', - params: { - placementId: 'test' - } - }, - ]; - - const bidderAppSet = [ - { - bidder: 'somoaudience', - params: { - placementId: 'test', - app: { - bundle: 'com.somoaudience.apps', - storeUrl: 'http://somoaudience.com/apps', - domain: 'somoaudience.com', + describe('isBidRequestValid', () => { + it('should return false when given an invalid bid', () => { + const bid = { + bidder: 'somoaudience', + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + it('should return true when given a placementId bid', () => { + const bid = { + bidder: 'somoaudience', + params: { + placementId: 'test' } - } - }, - ]; - - const bidderBadSet = [ - { - bidder: 'somoaudience', - params: { - placement_id: 'test' - } - }, - ]; - - it('Verifies bidder code', () => { - expect(spec.code).to.equal('somoaudience'); + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); }); - it('Verifies bidder aliases', () => { - expect(spec.aliases).to.have.lengthOf(1); - expect(spec.aliases[0]).to.equal('somo'); - }); + describe('buildRequests', () => { + describe('buildBannerRequests', () => { + it('should properly build a banner request with type not defined and sizes not defined', () => { + const bidRequests = [{ + bidder: 'somoaudience', + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests); + expect(request[0].url).to.equal('//publisher-east.mobileadtrading.com/rtb/bid?s=test'); + expect(request[0].method).to.equal('POST'); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal(utils.getTopWindowReferrer()); + expect(ortbRequest.site.page).to.equal(utils.getTopWindowLocation().href); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.device).to.not.equal(null); + expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + expect(ortbRequest.imp[0].bidfloor).to.not.be.null; + expect(ortbRequest.imp[0].banner).to.not.equal(null); + }); - it('Verifies if bid request valid', () => { - expect(spec.isBidRequestValid(bidderSet[0])).to.equal(true); - expect(spec.isBidRequestValid(bidderAppSet[0])).to.equal(true); - expect(spec.isBidRequestValid({})).to.equal(false); - expect(spec.isBidRequestValid(bidderBadSet[0])).to.equal(false); - expect(spec.isBidRequestValid({ params: {} })).to.equal(false); - expect(spec.isBidRequestValid({ params: { placementId: '12345' } })).to.equal(true); - }); + it('should properly build a banner request with sizes defined in 2d array', () => { + const bidRequests = [{ + bidder: 'somoaudience', + sizes: [[300, 250]], + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests); + expect(request[0].url).to.equal('//publisher-east.mobileadtrading.com/rtb/bid?s=test'); + expect(request[0].method).to.equal('POST'); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal(utils.getTopWindowReferrer()); + expect(ortbRequest.site.page).to.equal(utils.getTopWindowLocation().href); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].bidfloor).to.not.be.null; + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + }); + it('should properly build a banner request with sizes defined in 1d array', () => { + const bidRequests = [{ + bidder: 'somoaudience', + sizes: [300, 250], + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests); + expect(request[0].url).to.equal('//publisher-east.mobileadtrading.com/rtb/bid?s=test'); + expect(request[0].method).to.equal('POST'); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal(utils.getTopWindowReferrer()); + expect(ortbRequest.site.page).to.equal(utils.getTopWindowLocation().href); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].bidfloor).to.not.be.null; + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + expect(ortbRequest.imp[0].banner.mimes).to.equal(undefined); + expect(ortbRequest.imp[0].banner.btype).to.equal(undefined); + expect(ortbRequest.imp[0].banner.pos).to.equal(undefined); + expect(ortbRequest.imp[0].banner.battr).to.equal(undefined); + }); + + it('should populate optional banner parameters', () => { + const bidRequests = [ + { + bidder: 'somoaudience', + sizes: [[300, 200]], + mediaType: 'banner', + params: { + placementId: 'test', + banner: { + mimes: 'video/mp4', + btype: '4', + pos: '1', + battr: 'ibv', + } + } + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(200); + expect(ortbRequest.imp[0].banner.mimes).to.equal('video/mp4'); + expect(ortbRequest.imp[0].banner.btype).to.equal('4'); + expect(ortbRequest.imp[0].banner.pos).to.equal('1'); + expect(ortbRequest.imp[0].banner.battr).to.equal('ibv'); + }); + }); + + describe('buildVideoRequests', () => { + it('should properly build a video request with sizes defined', () => { + const bidRequests = [{ + bidder: 'somoaudience', + mediaTypes: { + video: {} + }, + sizes: [200, 300], + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal(utils.getTopWindowReferrer()); + expect(ortbRequest.site.page).to.equal(utils.getTopWindowLocation().href); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].video).to.not.equal(null); + expect(ortbRequest.imp[0].video.w).to.equal(200); + expect(ortbRequest.imp[0].video.h).to.equal(300); + }); + + it('should properly build a video request with sizes defined in 2d array', () => { + const bidRequests = [{ + bidder: 'somoaudience', + mediaTypes: { + video: {} + }, + sizes: [[200, 300]], + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal(utils.getTopWindowReferrer()); + expect(ortbRequest.site.page).to.equal(utils.getTopWindowLocation().href); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].video).to.not.equal(null); + expect(ortbRequest.imp[0].video.w).to.equal(200); + expect(ortbRequest.imp[0].video.h).to.equal(300); + }); + it('should properly build a video request with sizes not defined', () => { + const bidRequests = [{ + bidder: 'somoaudience', + mediaType: 'video', + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].video).to.not.equal(null); + expect(ortbRequest.imp[0].video.mimes).to.equal(undefined); + expect(ortbRequest.imp[0].video.minduration).to.equal(undefined); + expect(ortbRequest.imp[0].video.maxduration).to.equal(undefined); + expect(ortbRequest.imp[0].video.protocols).to.equal(undefined); + expect(ortbRequest.imp[0].video.startdelay).to.equal(undefined); + expect(ortbRequest.imp[0].video.linearity).to.equal(undefined); + expect(ortbRequest.imp[0].video.skip).to.equal(undefined); + expect(ortbRequest.imp[0].video.delivery).to.equal(undefined); + expect(ortbRequest.imp[0].video.pos).to.equal(undefined); + expect(ortbRequest.imp[0].video.api).to.equal(undefined); + expect(ortbRequest.imp[0].video.battr).to.equal(undefined); + }); + + it('should populate optional video parameters', () => { + const bidRequests = [ + { + bidder: 'somoaudience', + sizes: [[200, 300]], + mediaType: 'video', + params: { + placementId: 'test', + video: { + mimes: 'video/mp4', + minduration: '15', + maxduration: '30', + protocols: 'mp4', + startdelay: '0', + linearity: 'linear', + skip: '1', + delivery: 'web', + pos: '1', + api: 'VPAID 1.0', + battr: 'ibv', + } + } + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.imp[0].video).to.not.equal(null); + expect(ortbRequest.imp[0].video.w).to.equal(200); + expect(ortbRequest.imp[0].video.h).to.equal(300); + expect(ortbRequest.imp[0].video.mimes).to.equal('video/mp4'); + expect(ortbRequest.imp[0].video.minduration).to.equal('15'); + expect(ortbRequest.imp[0].video.maxduration).to.equal('30'); + expect(ortbRequest.imp[0].video.protocols).to.equal('mp4'); + expect(ortbRequest.imp[0].video.startdelay).to.equal('0'); + expect(ortbRequest.imp[0].video.linearity).to.equal('linear'); + expect(ortbRequest.imp[0].video.skip).to.equal('1'); + expect(ortbRequest.imp[0].video.delivery).to.equal('web'); + expect(ortbRequest.imp[0].video.pos).to.equal('1'); + expect(ortbRequest.imp[0].video.api).to.equal('VPAID 1.0'); + expect(ortbRequest.imp[0].video.battr).to.equal('ibv'); + }); + }); + + describe('buildSiteRequests', () => { + it('should fill in basic site parameters', () => { + const bidRequests = [{ + bidder: 'somoaudience', + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.app).to.equal(null); + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal(utils.getTopWindowReferrer()); + expect(ortbRequest.site.page).to.equal(utils.getTopWindowLocation().href); + expect(ortbRequest.site.domain).to.not.be.undefined; + }); + + it('should fill in optional site parameters', () => { + const bidRequests = [{ + bidder: 'somoaudience', + params: { + placementId: 'test', + site: { + domain: 'somoaudience.com', + name: 'Somo Audience', + cat: 'IAB-25', + keywords: 'unit testing', + content: 'Unit Testing' + } + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.app).to.equal(null); + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.name).to.equal('Somo Audience'); + expect(ortbRequest.site.domain).to.equal('somoaudience.com'); + expect(ortbRequest.site.cat).to.equal('IAB-25'); + expect(ortbRequest.site.keywords).to.equal('unit testing'); + expect(ortbRequest.site.content).to.equal('Unit Testing'); + }) + }); + + describe('buildAppRequests', () => { + it('should fill in app parameters', () => { + const bidRequests = [{ + bidder: 'somoaudience', + params: { + placementId: 'test', + app: { + bundle: 'com.somoaudience.apps', + storeUrl: 'http://somoaudience.com/apps', + domain: 'somoaudience.com', + name: 'Generic SomoAudience App 5', + cat: 'IAB-25', + keywords: 'unit testing', + content: 'Unit Testing', + ver: '5.423-s', + } + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.bundle).to.equal('com.somoaudience.apps'); + expect(ortbRequest.app.storeUrl).to.equal('http://somoaudience.com/apps'); + expect(ortbRequest.app.domain).to.equal('somoaudience.com'); + expect(ortbRequest.app.name).to.equal('Generic SomoAudience App 5'); + expect(ortbRequest.app.ver).to.equal('5.423-s'); + expect(ortbRequest.app.cat).to.equal('IAB-25'); + expect(ortbRequest.app.keywords).to.equal('unit testing'); + expect(ortbRequest.app.content).to.equal('Unit Testing'); + }); + }); - it('Verifies buildRequests', () => { - const request = spec.buildRequests(bidderSet); - let br = request[0]; - expect(br.url).to.equal('//publisher-east.mobileadtrading.com/rtb/bid?s=test'); - expect(br.method).to.equal('POST'); - const ortbRequest = br.data; - expect(ortbRequest.site).to.not.equal(null); - expect(ortbRequest.site.ref).to.equal(getTopWindowReferrer()); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); - expect(ortbRequest.imp).to.have.lengthOf(1); - expect(ortbRequest.device).to.not.equal(null); - expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + describe('buildGDPRRequests', () => { + const bidderRequest = { + gdprConsent: { + gdprApplies: true, + consentString: 'test' + }, + }; + + it('should properly build request with gdpr consent', () => { + const bidRequests = [{ + bidder: 'somoaudience', + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request[0].data; + expect(ortbRequest.reqs).to.not.equal(undefined); + expect(ortbRequest.reqs.ext).to.not.equal(undefined); + expect(ortbRequest.reqs.ext.gdpr).to.equal(true); + expect(ortbRequest.user).to.not.equal(undefined); + expect(ortbRequest.user.ext).to.not.equal(undefined); + expect(ortbRequest.user.ext.consent).to.equal('test'); + }); + it('should properly build request with gdpr not applies', () => { + bidderRequest.gdprConsent.gdprApplies = false; + const bidRequests = [{ + bidder: 'somoaudience', + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request[0].data; + expect(ortbRequest.reqs).to.not.equal(undefined); + expect(ortbRequest.reqs.ext).to.not.equal(undefined); + expect(ortbRequest.reqs.ext.gdpr).to.equal(false); + expect(ortbRequest.user).to.not.equal(undefined); + expect(ortbRequest.user.ext).to.not.equal(undefined); + expect(ortbRequest.user.ext.consent).to.equal('test'); + }); + }); + + describe('buildExtraArgsRequests', () => { + it('should populate optional parameters', () => { + const bidRequests = [ + { + bidder: 'somoaudience', + params: { + placementId: 'test', + bcat: ['IAB-2', 'IAB-7'], + badv: ['somoaudience.com', 'mobileadtrading.com'], + bidfloor: '0.05', + }, + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.imp[0].bidfloor).to.not.be.null; + expect(ortbRequest.imp[0].bidfloor).to.be.equal('0.05'); + expect(ortbRequest.bcat).to.not.be.null; + expect(ortbRequest.bcat).to.have.lengthOf(2); + expect(ortbRequest.bcat).to.contain('IAB-2'); + expect(ortbRequest.badv).to.not.be.null; + expect(ortbRequest.badv).to.have.lengthOf(2); + expect(ortbRequest.badv).to.contain('somoaudience.com'); + }); + }); }); - it('Verify parse response', () => { - const request = spec.buildRequests(bidderSet); - const ortbRequest = request[0].data; - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: 'Somo Test Ad' + describe('interpretResponse', () => { + it('Verify banner parse response', () => { + const bidRequests = [ + { + bidder: 'somoaudience', + params: { + placementId: 'test', + }, + bidId: '234234234', + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'Somo Test Ad' + }], + bidId: '234234234' }] - }] - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.ad).to.equal('Somo Test Ad'); + }; + const bids = spec.interpretResponse({ body: ortbResponse }, {bidRequest: bidRequests[0]}); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.ad).to.equal('Somo Test Ad'); + }); + + it('Verify video parse response', () => { + const bidRequests = [ + { + bidder: 'somoaudience', + mediaTypes: { + video: { + } + }, + params: { + placementId: 'test', + }, + bidId: '234234234', + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'Somo Test Ad' + }], + bidId: '234234234' + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, {bidRequest: bidRequests[0]}); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.vastXml).to.equal('Somo Test Ad'); + }); }); - it('Verify app requests', () => { - const request = spec.buildRequests(bidderAppSet); - const ortbRequest = request[0].data; - expect(ortbRequest.site).to.equal(null); - expect(ortbRequest.app).to.not.be.null; - expect(ortbRequest.app.bundle).to.equal('com.somoaudience.apps'); - expect(ortbRequest.app.storeurl).to.equal('http://somoaudience.com/apps'); - expect(ortbRequest.app.domain).to.equal('somoaudience.com'); + + describe('user sync', () => { + it('should register the pixel sync url', () => { + let syncs = spec.getUserSyncs({ + pixelEnabled: true + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('image'); + }); + + it('should pass gdpr params', () => { + let syncs = spec.getUserSyncs({ pixelEnabled: true }, {}, { + gdprApplies: false, consentString: 'test' + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('image'); + expect(syncs[0].url).to.contains('gdpr=0'); + }); + + it('should pass gdpr applies params', () => { + let syncs = spec.getUserSyncs({ pixelEnabled: true }, {}, { + gdprApplies: true, consentString: 'test' + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('image'); + expect(syncs[0].url).to.contains('gdpr=1'); + expect(syncs[0].url).to.contains('gdpr_consent=test'); + }); }); }); From e36f10e6d52463d4f3e993ad9524ce3d2fec00b4 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Mon, 20 Aug 2018 21:14:44 +0100 Subject: [PATCH 0637/1594] Audience Network: correct TTL, allow platform override (#2974) --- modules/audienceNetworkBidAdapter.js | 19 +++++++++++++++---- .../modules/audienceNetworkBidAdapter_spec.js | 19 ++++++++++++++++--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 12810a960c1..544670863b8 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -2,7 +2,6 @@ * @file AudienceNetwork adapter. */ import { registerBidder } from 'src/adapters/bidderFactory'; -import { config } from 'src/config'; import { formatQS } from 'src/url'; import { generateUUID, getTopWindowUrl, isSafariBrowser, convertTypes } from 'src/utils'; import findIndex from 'core-js/library/fn/array/find-index'; @@ -15,9 +14,11 @@ const url = 'https://an.facebook.com/v2/placementbid.json'; const supportedMediaTypes = ['banner', 'video']; const netRevenue = true; const hbBidder = 'fan'; +const ttl = 600; +const videoTtl = 3600; const platver = '$prebid.version$'; const platform = '241394079772386'; -const adapterver = '1.0.0'; +const adapterver = '1.0.1'; /** * Does this bid request contain valid parameters? @@ -93,6 +94,13 @@ const isFullWidth = format => format === 'fullwidth'; */ const sdkVersion = format => isVideo(format) ? '' : '5.5.web'; +/** + * Which platform identifier should be used? + * @param {Array} platforms Possible platform identifiers + * @returns {String} First valid platform found, or default if none found + */ +const findPlatform = platforms => [...platforms.filter(Boolean), platform][0]; + /** * Does the search part of the URL contain "anhb_testmode" * and therefore indicate testmode should be used? @@ -133,6 +141,7 @@ const getTopWindowUrlEncoded = () => encodeURIComponent(getTopWindowUrl()); * @param {String} bids[].placementCode - Prebid placement identifier * @param {Object} bids[].params * @param {String} bids[].params.placementId - Audience Network placement identifier + * @param {String} bids[].params.platform - Audience Network platform identifier (optional) * @param {String} bids[].params.format - Optional format, one of 'video', 'native' or 'fullwidth' if set * @param {Array} bids[].sizes - list of desired advert sizes * @param {Array} bids[].sizes[] - Size arrays [h,w]: should include one of [300, 250], [320, 50]: first matched size is used @@ -144,6 +153,7 @@ const buildRequests = bids => { const adformats = []; const sizes = []; const sdk = []; + const platforms = []; const requestIds = []; bids.forEach(bid => bid.sizes @@ -155,6 +165,7 @@ const buildRequests = bids => { adformats.push(bid.params.format || size); sizes.push(size); sdk.push(sdkVersion(bid.params.format)); + platforms.push(bid.params.platform); requestIds.push(bid.bidId); }) ); @@ -162,6 +173,7 @@ const buildRequests = bids => { // Build URL const testmode = isTestmode(); const pageurl = getTopWindowUrlEncoded(); + const platform = findPlatform(platforms); const search = { placementids, adformats, @@ -194,8 +206,6 @@ const buildRequests = bids => { * @returns {Array} A list of bid response objects */ const interpretResponse = ({ body }, { adformats, requestIds, sizes }) => { - const ttl = Number(config.getConfig().bidderTimeout); - const { bids = {} } = body; return Object.keys(bids) // extract Array of bid responses @@ -237,6 +247,7 @@ const interpretResponse = ({ body }, { adformats, requestIds, sizes }) => { const pageurl = getTopWindowUrlEncoded(); bidResponse.mediaType = 'video'; bidResponse.vastUrl = `https://an.facebook.com/v1/instream/vast.xml?placementid=${creativeId}&pageurl=${pageurl}&playerwidth=${width}&playerheight=${height}&bidid=${fbBidid}`; + bidResponse.ttl = videoTtl; } return bidResponse; }); diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index c61cd04c422..3e6a890e4dc 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -19,7 +19,7 @@ const placementId = 'test-placement-id'; const playerwidth = 320; const playerheight = 180; const requestId = 'test-request-id'; -const debug = 'adapterver=1.0.0&platform=241394079772386&platver=$prebid.version$'; +const debug = 'adapterver=1.0.1&platform=241394079772386&platver=$prebid.version$'; const pageUrl = encodeURIComponent(utils.getTopWindowUrl()); describe('AudienceNetwork adapter', () => { @@ -182,13 +182,17 @@ describe('AudienceNetwork adapter', () => { }]); }); - it('can build URL for fullwidth 300x250 unit', () => { + it('can build URL for fullwidth 300x250 unit, overriding platform', () => { + const platform = 'test-platform'; + const debugPlatform = debug.replace('241394079772386', platform); + expect(buildRequests([{ bidder, bidId: requestId, sizes: [[300, 250]], params: { placementId, + platform, format: 'fullwidth' } }])).to.deep.equal([{ @@ -197,7 +201,7 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debug}` + data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debugPlatform}` }]); }); @@ -249,6 +253,7 @@ describe('AudienceNetwork adapter', () => { .to.contain(`placementid:'${placementId}',format:'native',bidid:'test-bid-id'`, 'ad missing parameters') .and.to.contain('getElementsByTagName("style")', 'ad missing native styles') .and.to.contain('
', 'ad missing native container'); + expect(bidResponse.ttl).to.equal(600); expect(bidResponse.creativeId).to.equal(placementId); expect(bidResponse.netRevenue).to.equal(true); expect(bidResponse.currency).to.equal('USD'); @@ -287,6 +292,7 @@ describe('AudienceNetwork adapter', () => { .to.contain(`placementid:'${placementId}',format:'300x250',bidid:'test-bid-id'`, 'ad missing parameters') .and.not.to.contain('getElementsByTagName("style")', 'ad should not contain native styles') .and.not.to.contain('
', 'ad should not contain native container'); + expect(bidResponse.ttl).to.equal(600); expect(bidResponse.creativeId).to.equal(placementId); expect(bidResponse.netRevenue).to.equal(true); expect(bidResponse.currency).to.equal('USD'); @@ -320,6 +326,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.requestId).to.equal(requestId); expect(bidResponse.width).to.equal(300); expect(bidResponse.height).to.equal(250); + expect(bidResponse.ttl).to.equal(600); expect(bidResponse.creativeId).to.equal(placementId); expect(bidResponse.netRevenue).to.equal(true); expect(bidResponse.currency).to.equal('USD'); @@ -364,6 +371,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseNative.width).to.equal(300); expect(bidResponseNative.height).to.equal(250); expect(bidResponseNative.ad).to.contain(`placementid:'${placementIdNative}',format:'native',bidid:'test-bid-id-native'`, 'ad missing parameters'); + expect(bidResponseNative.ttl).to.equal(600); expect(bidResponseNative.creativeId).to.equal(placementIdNative); expect(bidResponseNative.netRevenue).to.equal(true); expect(bidResponseNative.currency).to.equal('USD'); @@ -377,6 +385,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseIab.width).to.equal(300); expect(bidResponseIab.height).to.equal(250); expect(bidResponseIab.ad).to.contain(`placementid:'${placementIdIab}',format:'300x250',bidid:'test-bid-id-iab'`, 'ad missing parameters'); + expect(bidResponseIab.ttl).to.equal(600); expect(bidResponseIab.creativeId).to.equal(placementIdIab); expect(bidResponseIab.netRevenue).to.equal(true); expect(bidResponseIab.currency).to.equal('USD'); @@ -410,6 +419,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.cpm).to.equal(1.23); expect(bidResponse.requestId).to.equal(requestId); + expect(bidResponse.ttl).to.equal(3600); expect(bidResponse.mediaType).to.equal('video'); expect(bidResponse.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${placementId}&pageurl=${pageUrl}&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${bidId}`); expect(bidResponse.width).to.equal(playerwidth); @@ -450,6 +460,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseVideo.cpm).to.equal(1.23); expect(bidResponseVideo.requestId).to.equal(requestId); + expect(bidResponseVideo.ttl).to.equal(3600); expect(bidResponseVideo.mediaType).to.equal('video'); expect(bidResponseVideo.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${videoPlacementId}&pageurl=${pageUrl}&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${videoBidId}`); expect(bidResponseVideo.width).to.equal(playerwidth); @@ -457,6 +468,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseNative.cpm).to.equal(4.56); expect(bidResponseNative.requestId).to.equal(requestId); + expect(bidResponseNative.ttl).to.equal(600); expect(bidResponseNative.width).to.equal(300); expect(bidResponseNative.height).to.equal(250); expect(bidResponseNative.ad).to.contain(`placementid:'${nativePlacementId}',format:'native',bidid:'${nativeBidId}'`); @@ -490,6 +502,7 @@ describe('AudienceNetwork adapter', () => { .to.contain(`placementid:'${placementId}',format:'native',bidid:'test-bid-id'`, 'ad missing parameters') .and.to.contain('getElementsByTagName("style")', 'ad missing native styles') .and.to.contain('
', 'ad missing native container'); + expect(bidResponse.ttl).to.equal(600); expect(bidResponse.creativeId).to.equal(placementId); expect(bidResponse.netRevenue).to.equal(true); expect(bidResponse.currency).to.equal('USD'); From c09d9db7a49dde12aafa99e139a3cce1f308f11d Mon Sep 17 00:00:00 2001 From: Daniel Russell Date: Mon, 20 Aug 2018 13:17:06 -0700 Subject: [PATCH 0638/1594] fix tests running in headless chrome inside a docker environment (#2965) * fix tests running in headless chrome if inside a docker environment * -mdelete unnecessary conditional * add is-docker to devDependencies instead of regular dependencies --- karma.conf.maker.js | 14 +++++++++++++- package.json | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 0a4e10d9792..7faf91f0847 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -92,7 +92,19 @@ function setBrowsers(karmaConf, browserstack) { karmaConf.customLaunchers = require('./browsers.json') karmaConf.browsers = Object.keys(karmaConf.customLaunchers); } else { - karmaConf.browsers = ['ChromeHeadless']; + var isDocker = require('is-docker')(); + if (isDocker) { + karmaConf.customLaunchers = karmaConf.customLaunchers || {}; + karmaConf.customLaunchers.ChromeCustom = { + base: 'ChromeHeadless', + // We must disable the Chrome sandbox when running Chrome inside Docker (Chrome's sandbox needs + // more permissions than Docker allows by default) + flags: ['--no-sandbox'] + } + karmaConf.browsers = ['ChromeCustom']; + } else { + karmaConf.browsers = ['ChromeHeadless']; + } } } diff --git a/package.json b/package.json index efb57eb9c59..0e70313b737 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "gulp-uglify": "^3.0.0", "gulp-util": "^3.0.0", "ignore-loader": "^0.1.2", + "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", "json-loader": "^0.5.1", From 18bf1a1ab6595f81aa29784d78b990cbaed4dd27 Mon Sep 17 00:00:00 2001 From: Aparna Rao-Hegde Date: Mon, 20 Aug 2018 16:31:22 -0400 Subject: [PATCH 0639/1594] 33Across: GDPR compliancy (#2985) * check gdpr in buildRequest * User sync based on whether gdpr applies or not * check if consent data exists during user sync * split user sync into further branches: 1) when gdpr does not apply 2) when consent data is unavailable --- modules/33acrossBidAdapter.js | 40 +- test/spec/modules/33acrossBidAdapter_spec.js | 414 +++++++++++++------ 2 files changed, 313 insertions(+), 141 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 7b26f66331f..109d9387ce6 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -23,8 +23,9 @@ function _createBidResponse(response) { } } -// infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request -function _createServerRequest(bidRequest) { +// Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request +// NOTE: At this point, TTX only accepts request for a single impression +function _createServerRequest(bidRequest, gdprConsent) { const ttxRequest = {}; const params = bidRequest.params; @@ -48,11 +49,24 @@ function _createServerRequest(bidRequest) { // therefore in ad targetting process ttxRequest.id = bidRequest.bidId; + // Set GDPR related fields + ttxRequest.user = { + ext: { + consent: gdprConsent.consentString + } + } + ttxRequest.regs = { + ext: { + gdpr: (gdprConsent.gdprApplies === true) ? 1 : 0 + } + } + // Finally, set the openRTB 'test' param if this is to be a test bid if (params.test === 1) { ttxRequest.test = 1; } + /* * Now construct the full server request */ @@ -104,11 +118,18 @@ function isBidRequestValid(bid) { return true; } -// NOTE: At this point, TTX only accepts request for a single impression -function buildRequests(bidRequests) { +// NOTE: With regards to gdrp consent data, +// - the server independently infers gdpr applicability therefore, setting the default value to false +// - the server, at this point, also doesn't need the consent string to handle gdpr compliance. So passing +// value whether set or not, for the sake of future dev. +function buildRequests(bidRequests, bidderRequest) { + const gdprConsent = Object.assign({ consentString: undefined, gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent) + adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(uniques); - return bidRequests.map(_createServerRequest); + return bidRequests.map((req) => { + return _createServerRequest(req, gdprConsent); + }); } // NOTE: At this point, the response from 33exchange will only ever contain one bid i.e. the highest bid @@ -124,8 +145,13 @@ function interpretResponse(serverResponse, bidRequest) { } // Register one sync per unique guid -function getUserSyncs(syncOptions) { - return (syncOptions.iframeEnabled) ? adapterState.uniqueSiteIds.map(_createSync) : ([]); +// NOTE: If gdpr applies do not sync +function getUserSyncs(syncOptions, responses, gdprConsent) { + if (gdprConsent && gdprConsent.gdprApplies === true) { + return [] + } else { + return (syncOptions.iframeEnabled) ? adapterState.uniqueSiteIds.map(_createSync) : ([]); + } } const spec = { diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 8ca2f3da902..3dbd7401d76 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -40,6 +40,7 @@ describe('33acrossBidAdapter:', function () { afterEach(function() { this.sandbox.restore(); + delete this.bidRequests; }); describe('isBidRequestValid:', function () { @@ -112,150 +113,255 @@ describe('33acrossBidAdapter:', function () { }); describe('buildRequests:', function() { - it('returns corresponding server requests for each valid bidRequest', function() { - const ttxRequest = { - imp: [ { - banner: { - format: [ - { - w: 300, - h: 250, - ext: {} - }, - { - w: 728, - h: 90, - ext: {} + + context('when gdpr consent data exists', function() { + beforeEach(function() { + this.bidderRequest= { + gdprConsent: { + consentString: "foobarMyPreference", + gdprApplies: true + } + } + }); + + it('returns corresponding server requests with gdpr consent data', function() { + const ttxRequest = { + imp: [ { + banner: { + format: [ + { + w: 300, + h: 250, + ext: {} + }, + { + w: 728, + h: 90, + ext: {} + } + ] + }, + ext: { + ttx: { + prod: PRODUCT_ID } - ] + } + } ], + site: { + id: SITE_ID }, - ext: { - ttx: { - prod: PRODUCT_ID + id: 'b1', + user: { + ext: { + consent: "foobarMyPreference" + } + }, + regs: { + ext: { + gdpr: 1 } } - } ], - site: { - id: SITE_ID - }, - id: 'b1' - }; - const serverRequest = { - 'method': 'POST', - 'url': END_POINT, - 'data': JSON.stringify(ttxRequest), - 'options': { - 'contentType': 'text/plain', - 'withCredentials': true - } - } - const builtServerRequests = buildRequests(this.bidRequests); - expect(builtServerRequests).to.deep.equal([ serverRequest ]); - expect(builtServerRequests.length).to.equal(1); - }); + }; - it('returns corresponding test server requests for each valid bidRequest', function() { - this.sandbox.stub(config, 'getConfig').callsFake(() => { - return { - 'url': 'https://foo.com/hb/' + const serverRequest = { + 'method': 'POST', + 'url': END_POINT, + 'data': JSON.stringify(ttxRequest), + 'options': { + 'contentType': 'text/plain', + 'withCredentials': true + } } + const builtServerRequests = buildRequests(this.bidRequests, this.bidderRequest); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); + expect(builtServerRequests.length).to.equal(1); }); - const ttxRequest = { - imp: [ { - banner: { - format: [ - { - w: 300, - h: 250, - ext: { } - }, - { - w: 728, - h: 90, - ext: { } + it('returns corresponding test server requests with gdpr consent data', function() { + this.sandbox.stub(config, 'getConfig').callsFake(() => { + return { + 'url': 'https://foo.com/hb/' + } + }); + + const ttxRequest = { + imp: [ { + banner: { + format: [ + { + w: 300, + h: 250, + ext: { } + }, + { + w: 728, + h: 90, + ext: { } + } + ] + }, + ext: { + ttx: { + prod: PRODUCT_ID } - ] + } + } ], + site: { + id: SITE_ID }, - ext: { - ttx: { - prod: PRODUCT_ID + id: 'b1', + user: { + ext: { + consent: "foobarMyPreference" + } + }, + regs: { + ext: { + gdpr: 1 } } - } ], - site: { - id: SITE_ID - }, - id: 'b1' - }; - const serverRequest = { - method: 'POST', - url: 'https://foo.com/hb/', - data: JSON.stringify(ttxRequest), - options: { - contentType: 'text/plain', - withCredentials: true - } - }; + }; + const serverRequest = { + method: 'POST', + url: 'https://foo.com/hb/', + data: JSON.stringify(ttxRequest), + options: { + contentType: 'text/plain', + withCredentials: true + } + }; + + const builtServerRequests = buildRequests(this.bidRequests, this.bidderRequest); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); + expect(builtServerRequests.length).to.equal(1); + }); - const builtServerRequests = buildRequests(this.bidRequests); - expect(builtServerRequests).to.deep.equal([ serverRequest ]); - expect(builtServerRequests.length).to.equal(1); + afterEach(function() { + delete this.bidderRequest; + }) }); - it('returns corresponding test server requests for each valid bidRequest', function() { - this.sandbox.stub(config, 'getConfig').callsFake(() => { - return { - 'url': 'https://foo.com/hb/' - } + context('when gdpr consent data does not exist', function() { + beforeEach(function() { + this.bidderRequest= { } }); - this.bidRequests[0].params.test = 1; - const ttxRequest = { - imp: [ { - banner: { - format: [ - { - w: 300, - h: 250, - ext: { } - }, - { - w: 728, - h: 90, - ext: { } + + it('returns corresponding server requests with default gdpr consent data', function() { + const ttxRequest = { + imp: [ { + banner: { + format: [ + { + w: 300, + h: 250, + ext: {} + }, + { + w: 728, + h: 90, + ext: {} + } + ] + }, + ext: { + ttx: { + prod: PRODUCT_ID } - ] + } + } ], + site: { + id: SITE_ID }, - ext: { - ttx: { - prod: PRODUCT_ID + id: 'b1', + user: { + ext: { + consent: undefined + } + }, + regs: { + ext: { + gdpr: 0 } } - } ], - site: { - id: SITE_ID - }, - id: 'b1', - test: 1 - }; - const serverRequest = { - method: 'POST', - url: 'https://foo.com/hb/', - data: JSON.stringify(ttxRequest), - options: { - contentType: 'text/plain', - withCredentials: true + }; + + const serverRequest = { + 'method': 'POST', + 'url': END_POINT, + 'data': JSON.stringify(ttxRequest), + 'options': { + 'contentType': 'text/plain', + 'withCredentials': true + } } - }; + const builtServerRequests = buildRequests(this.bidRequests, this.bidderRequest); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); + expect(builtServerRequests.length).to.equal(1); + }); - const builtServerRequests = buildRequests(this.bidRequests); - expect(builtServerRequests).to.deep.equal([ serverRequest ]); - expect(builtServerRequests.length).to.equal(1); - }); + it('returns corresponding test server requests with default gdpr consent data', function() { + this.sandbox.stub(config, 'getConfig').callsFake(() => { + return { + 'url': 'https://foo.com/hb/' + } + }); + + const ttxRequest = { + imp: [ { + banner: { + format: [ + { + w: 300, + h: 250, + ext: { } + }, + { + w: 728, + h: 90, + ext: { } + } + ] + }, + ext: { + ttx: { + prod: PRODUCT_ID + } + } + } ], + site: { + id: SITE_ID + }, + id: 'b1', + user: { + ext: { + consent: undefined + } + }, + regs: { + ext: { + gdpr: 0 + } + } + }; + const serverRequest = { + method: 'POST', + url: 'https://foo.com/hb/', + data: JSON.stringify(ttxRequest), + options: { + contentType: 'text/plain', + withCredentials: true + } + }; - afterEach(function() { - delete this.bidRequests; - }) + const builtServerRequests = buildRequests(this.bidRequests, this.bidderRequest); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); + expect(builtServerRequests.length).to.equal(1); + }); + + afterEach(function() { + delete this.bidderRequest; + }) + }); }); describe('interpretResponse', function() { @@ -452,23 +558,63 @@ describe('33acrossBidAdapter:', function () { ]; }); - context('when iframe is not enabled', function() { - it('returns empty sync array', function() { - const syncOptions = {}; - buildRequests(this.bidRequests); - expect(getUserSyncs(syncOptions)).to.deep.equal([]); + context('when gdpr does not apply', function() { + beforeEach(function() { + this.gdprConsent = { + gdprApplies: false + } + }); + + context('when iframe is not enabled', function() { + it('returns empty sync array', function() { + const syncOptions = {}; + buildRequests(this.bidRequests); + expect(getUserSyncs(syncOptions, {}, this.gdprConsent)).to.deep.equal([]); + }); + }); + + context('when iframe is enabled', function() { + it('returns sync array equal to number of unique siteIDs', function() { + const syncOptions = { + iframeEnabled: true + }; + buildRequests(this.bidRequests); + const syncs = getUserSyncs(syncOptions, {}, this.gdprConsent); + expect(syncs).to.deep.equal(this.syncs); + }); }); }); - context('when iframe is enabled', function() { - it('returns sync array equal to number of unique siteIDs', function() { - const syncOptions = { - iframeEnabled: true - }; - buildRequests(this.bidRequests); - const syncs = getUserSyncs(syncOptions); - expect(syncs).to.deep.equal(this.syncs); + context('when consent data is not defined', function() { + context('when iframe is not enabled', function() { + it('returns empty sync array', function() { + const syncOptions = {}; + buildRequests(this.bidRequests); + expect(getUserSyncs(syncOptions)).to.deep.equal([]); + }); + }); + + context('when iframe is enabled', function() { + it('returns sync array equal to number of unique siteIDs', function() { + const syncOptions = { + iframeEnabled: true + }; + buildRequests(this.bidRequests); + const syncs = getUserSyncs(syncOptions); + expect(syncs).to.deep.equal(this.syncs); + }); }); }); + + context('when gdpr applies', function() { + it('returns empty sync array', function() { + const syncOptions = {}; + const gdprConsent = { + gdprApplies: true + } + buildRequests(this.bidRequests); + expect(getUserSyncs(syncOptions, {}, gdprConsent)).to.deep.equal([]); + }); + }) }); }); From 65df3bbbd3d3feb0e684aff0f223179ee6113651 Mon Sep 17 00:00:00 2001 From: Andrew Bowman Date: Tue, 21 Aug 2018 10:17:04 -0400 Subject: [PATCH 0640/1594] Appnexus adaptor - Added App parameters for hybrid apps. (#2973) * Added hybrid app parameters and debug url parameters * Fix test for app parameters. removed debugging * added defensive code per review from @jaiminpanchal27 * simplified if/then statements * fix JS lint issue --- modules/appnexusBidAdapter.js | 38 +++++++++++++++++ modules/appnexusBidAdapter.md | 41 ++++++++++++++++-- test/spec/modules/appnexusBidAdapter_spec.js | 44 ++++++++++++++++++++ 3 files changed, 120 insertions(+), 3 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index d5cb3ac2800..7dac4b8b182 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -10,6 +10,7 @@ const URL = '//ib.adnxs.com/ut/v3/prebid'; const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', 'startdelay', 'skippable', 'playback_method', 'frameworks']; const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'language']; +const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately const NATIVE_MAPPING = { body: 'description', cta: 'ctatext', @@ -59,6 +60,23 @@ export const spec = { .forEach(param => userObj[param] = 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 + }; + } + const memberIdBid = find(bidRequests, hasMemberId); const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; @@ -74,6 +92,13 @@ export const spec = { payload.member_id = member; } + if (appDeviceObjBid) { + payload.device = appDeviceObj + } + if (appIdObjBid) { + payload.app = appIdObj; + } + if (bidderRequest && bidderRequest.gdprConsent) { // note - objects for impbus use underscore instead of camelCase payload.gdpr_consent = { @@ -381,6 +406,19 @@ 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 getRtbBid(tag) { return tag && tag.ads && tag.ads.length && find(tag.ads, ad => ad.rtb); } diff --git a/modules/appnexusBidAdapter.md b/modules/appnexusBidAdapter.md index 58f260cdfc8..822bd62997f 100644 --- a/modules/appnexusBidAdapter.md +++ b/modules/appnexusBidAdapter.md @@ -17,9 +17,13 @@ Appnexus bid adapter supports Banner, Video (instream and outstream) and Native. var adUnits = [ // Banner adUnit { - code: 'banner-div', - sizes: [[300, 250], [300,600]], - bids: [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + } + bids: [{ bidder: 'appnexus', params: { placementId: '10433394' @@ -98,6 +102,37 @@ var adUnits = [ } } ] + }, + // 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: 'appnexus', + 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 + } + } + } + }] } ]; ``` diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index abfd50d1746..b65988e3ec1 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -326,6 +326,50 @@ describe('AppNexusAdapter', () => { expect(payload.gdpr_consent.consent_string).to.exist.and.to.equal(consentString); expect(payload.gdpr_consent.consent_required).to.exist.and.to.be.true; }); + + it('supports sending hybrid mobile app parameters', () => { + 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 + }); + }); }) describe('interpretResponse', () => { From dc8c822d5c6f70e5e3dc696a0ac3b41418c1fd77 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 21 Aug 2018 10:23:27 -0400 Subject: [PATCH 0641/1594] fix lint errors in 33across files (#3002) --- modules/33acrossBidAdapter.js | 1 - test/spec/modules/33acrossBidAdapter_spec.js | 19 +++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 109d9387ce6..6b41c652152 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -66,7 +66,6 @@ function _createServerRequest(bidRequest, gdprConsent) { ttxRequest.test = 1; } - /* * Now construct the full server request */ diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 3dbd7401d76..2779209c1cf 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -113,12 +113,11 @@ describe('33acrossBidAdapter:', function () { }); describe('buildRequests:', function() { - context('when gdpr consent data exists', function() { beforeEach(function() { - this.bidderRequest= { + this.bidderRequest = { gdprConsent: { - consentString: "foobarMyPreference", + consentString: 'foobarMyPreference', gdprApplies: true } } @@ -151,9 +150,9 @@ describe('33acrossBidAdapter:', function () { id: SITE_ID }, id: 'b1', - user: { + user: { ext: { - consent: "foobarMyPreference" + consent: 'foobarMyPreference' } }, regs: { @@ -210,9 +209,9 @@ describe('33acrossBidAdapter:', function () { id: SITE_ID }, id: 'b1', - user: { + user: { ext: { - consent: "foobarMyPreference" + consent: 'foobarMyPreference' } }, regs: { @@ -243,7 +242,7 @@ describe('33acrossBidAdapter:', function () { context('when gdpr consent data does not exist', function() { beforeEach(function() { - this.bidderRequest= { } + this.bidderRequest = { } }); it('returns corresponding server requests with default gdpr consent data', function() { @@ -273,7 +272,7 @@ describe('33acrossBidAdapter:', function () { id: SITE_ID }, id: 'b1', - user: { + user: { ext: { consent: undefined } @@ -332,7 +331,7 @@ describe('33acrossBidAdapter:', function () { id: SITE_ID }, id: 'b1', - user: { + user: { ext: { consent: undefined } From 031943c94811dc0b61b2c77802f7982f4a4c68a1 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 21 Aug 2018 11:15:59 -0400 Subject: [PATCH 0642/1594] fix getHighestCpmBids function (#2990) --- src/prebid.js | 7 +++---- test/spec/unit/pbjs_api_spec.js | 27 ++++++++++++++++++++------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index ac7731d92fd..ea7e3fadd8e 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -1,13 +1,13 @@ /** @module pbjs */ import { getGlobal } from './prebidGlobal'; -import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId, getLatestHighestCpmBid } from './utils'; +import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId } from './utils'; import { listenMessagesFromCreative } from './secureCreatives'; import { userSync } from 'src/userSync.js'; import { loadScript } from './adloader'; import { config } from './config'; import { auctionManager } from './auctionManager'; -import { targeting, getHighestCpmBidsFromBidPool, RENDERED, BID_TARGETING_SET } from './targeting'; +import { targeting, RENDERED, BID_TARGETING_SET } from './targeting'; import { createHook } from 'src/hook'; import { sessionLoader } from 'src/debugging'; import includes from 'core-js/library/fn/array/includes'; @@ -600,8 +600,7 @@ $$PREBID_GLOBAL$$.getAllPrebidWinningBids = function () { * @return {Array} array containing highest cpm bid object(s) */ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { - let bidsReceived = getHighestCpmBidsFromBidPool(auctionManager.getBidsReceived(), getLatestHighestCpmBid); - return targeting.getWinningBids(adUnitCode, bidsReceived) + return targeting.getWinningBids(adUnitCode) .map(removeRequestId); }; diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index d46a8d740a5..385adc321d0 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1809,12 +1809,9 @@ describe('Unit: Prebid Module', function () { }); describe('getHighestCpm', () => { - // it('returns an array of winning bid objects for each adUnit', () => { - // const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids(); - // expect(highestCpmBids.length).to.equal(2); - // expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); - // expect(highestCpmBids[1]).to.deep.equal(auctionManager.getBidsReceived()[2]); - // }); + after(() => { + resetAuction(); + }); it('returns an array containing the highest bid object for the given adUnitCode', () => { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); @@ -1834,7 +1831,23 @@ describe('Unit: Prebid Module', function () { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); expect(highestCpmBids.length).to.equal(0); - resetAuction(); + }); + + it('should not return rendered bid', function() { + let _bidsReceived = getBidResponses().slice(0, 3); + _bidsReceived[0].cpm = 12; + _bidsReceived[0].status = 'rendered'; + _bidsReceived[1].cpm = 9; + _bidsReceived[2].cpm = 11; + + _bidsReceived.forEach((bid) => { + bid.adUnitCode = '/19968336/header-bid-tag-0'; + }); + + auction.getBidsReceived = function() { return _bidsReceived }; + + const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); + expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[2]); }); }); From 754625780d9eff551cf0a3dab3b0d236c6ce36c7 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 21 Aug 2018 09:42:38 -0600 Subject: [PATCH 0643/1594] Update from travis to circle CI in release documentation --- RELEASE_SCHEDULE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index 0c424e76ed4..637ed354c74 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -17,7 +17,7 @@ Announcements regarding releases will be made to the #headerbidding-dev channel ## Release Process -1. Make Sure all browserstack tests are passing. On PR merge to master travis will run unit tests on browserstack. Checking the last travis build [here](https://travis-ci.org/prebid/Prebid.js/branches) for master branch will show you detailed results. +1. Make Sure all browserstack tests are passing. On PR merge to master CircleCI will run unit tests on browserstack. Checking the last CircleCI build [here](https://circleci.com/gh/prebid) for master branch will show you detailed results. In case of failure do following, - Try to fix the failing tests. From 744261399710797136457d38b6e3a72901eb3653 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 21 Aug 2018 10:05:00 -0600 Subject: [PATCH 0644/1594] moved assignment of `bid.getCpmInNewCurrency` function for currency (#2997) --- modules/currency.js | 14 +++++++++----- test/spec/modules/currency_spec.js | 12 ++++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/modules/currency.js b/modules/currency.js index 25eddc5b993..f66c33bbed8 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -154,6 +154,14 @@ export function addBidResponseHook(adUnitCode, bid, fn) { bid.currency = 'USD'; } + let fromCurrency = bid.currency; + let cpm = bid.cpm; + + // used for analytics + bid.getCpmInNewCurrency = function(toCurrency) { + return (parseFloat(cpm) * getCurrencyConversion(fromCurrency, toCurrency)).toFixed(3); + }; + // execute immediately if the bid is already in the desired currency if (bid.currency === adServerCurrency) { return fn.apply(this, arguments); @@ -178,16 +186,12 @@ function wrapFunction(fn, context, params) { let fromCurrency = bid.currency; try { let conversion = getCurrencyConversion(fromCurrency); - let cpm = bid.originalCpm = bid.cpm; + bid.originalCpm = bid.cpm; bid.originalCurrency = bid.currency; if (conversion !== 1) { bid.cpm = (parseFloat(bid.cpm) * conversion).toFixed(4); bid.currency = adServerCurrency; } - // used for analytics - bid.getCpmInNewCurrency = function(toCurrency) { - return (parseFloat(cpm) * getCurrencyConversion(fromCurrency, toCurrency)).toFixed(3); - }; } catch (e) { utils.logWarn('Returning NO_BID, getCurrencyConversion threw error: ', e); params[1] = bidfactory.createBid(STATUS.NO_BID, { diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index a4ef643fece..74e2b8a3c38 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -62,7 +62,9 @@ describe('currency', function () { innerBid = bid; }); - expect(innerBid.currency).to.equal('GBP') + expect(innerBid.currency).to.equal('GBP'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('GBP')).to.equal('1.000'); }); it('uses adapter currency over currency override if specified', () => { @@ -82,7 +84,9 @@ describe('currency', function () { innerBid = bid; }); - expect(innerBid.currency).to.equal('JPY') + expect(innerBid.currency).to.equal('JPY'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('1.000'); }); it('uses rates specified in json when provided', () => { @@ -103,6 +107,8 @@ describe('currency', function () { }); expect(innerBid.cpm).to.equal('1.0000'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000'); }); it('uses default rates when currency file fails to load', () => { @@ -128,6 +134,8 @@ describe('currency', function () { }); expect(innerBid.cpm).to.equal('1.0000'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000'); }); }); From 40c368f5fe0307b4f0ad4ad4079d0555719d96ec Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 21 Aug 2018 10:11:41 -0600 Subject: [PATCH 0645/1594] Prebid 1.21.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e70313b737..c66782e3a88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.21.0-pre", + "version": "1.21.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 11ec22a75636ba79bf635224cb7affcae41c0778 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 21 Aug 2018 10:27:09 -0600 Subject: [PATCH 0646/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c66782e3a88..377f49b3810 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.21.0", + "version": "1.22.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From e1e03db7f3d7a8122a547a97f035d1dac71e8cc0 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 22 Aug 2018 08:10:31 -0400 Subject: [PATCH 0647/1594] update gulp test to include lint (#3003) * update gulp test to include lint * adding lint erro in appnexus adapter to test circleci * fixing lint error previous test commit added --- gulpfile.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index d2955f7d777..92dd2a7c1f1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -39,7 +39,7 @@ var port = 9999; // Tasks gulp.task('default', ['webpack']); -gulp.task('serve', ['lint', 'build-bundle-dev', 'watch', 'test']); +gulp.task('serve', ['build-bundle-dev', 'watch', 'test']); gulp.task('serve-nw', ['lint', 'watch', 'e2etest']); @@ -49,8 +49,8 @@ gulp.task('build', ['build-bundle-prod']); gulp.task('clean', function () { return gulp.src(['build'], { - read: false - }) + read: false + }) .pipe(clean()); }); @@ -78,13 +78,13 @@ var explicitModules = [ function bundle(dev, moduleArr) { var modules = moduleArr || helpers.getArgModules(), - allModules = helpers.getModuleNames(modules); + allModules = helpers.getModuleNames(modules); - if(modules.length === 0) { + if (modules.length === 0) { modules = allModules.filter(module => !explicitModules.includes(module)); } else { var diff = _.difference(modules, allModules); - if(diff.length !== 0) { + if (diff.length !== 0) { throw new gutil.PluginError({ plugin: 'bundle', message: 'invalid modules: ' + diff.join(', ') @@ -106,13 +106,13 @@ function bundle(dev, moduleArr) { gutil.log('Generating bundle:', outputFileName); return gulp.src( - entries - ) + entries + ) .pipe(gulpif(dev, sourcemaps.init({loadMaps: true}))) .pipe(concat(outputFileName)) .pipe(gulpif(!argv.manualEnable, footer('\n<%= global %>.processQueue();', { - global: prebid.globalVarName - } + global: prebid.globalVarName + } ))) .pipe(gulpif(dev, sourcemaps.write('.'))); } @@ -186,7 +186,7 @@ gulp.task('webpack', ['clean'], function () { // If --file "" is given, the task will only run tests in the specified file. // If --browserstack is given, it will run the full suite of currently supported browsers. // If --browsers is given, browsers can be chosen explicitly. e.g. --browsers=chrome,firefox,ie9 -gulp.task('test', ['clean'], function (done) { +gulp.task('test', ['clean', 'lint'], function (done) { var karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch, argv.file); var browserOverride = helpers.parseBrowserArgs(argv).map(helpers.toCapitalCase); @@ -229,7 +229,7 @@ gulp.task('watch', function () { 'modules/**/*.js', 'test/spec/**/*.js', '!test/spec/loaders/**/*.js' - ], ['lint', 'build-bundle-dev', 'test']); + ], ['build-bundle-dev', 'test']); gulp.watch([ 'loaders/**/*.js', 'test/spec/loaders/**/*.js' @@ -264,7 +264,7 @@ gulp.task('docs', ['clean-docs'], function () { gulp.task('e2etest', ['devpack', 'webpack'], function() { var cmdQueue = []; - if(argv.browserstack) { + if (argv.browserstack) { var browsers = require('./browsers.json'); delete browsers['bs_ie_9_windows_7']; @@ -276,11 +276,11 @@ gulp.task('e2etest', ['devpack', 'webpack'], function() { var startWith = 'bs'; - Object.keys(browsers).filter(function(v){ + Object.keys(browsers).filter(function(v) { return v.substring(0, startWith.length) === startWith && browsers[v].browser !== 'iphone'; - }).map(function(v,i,arr) { - var newArr = (i%2 === 0) ? arr.slice(i,i+2) : null; - if(newArr) { + }).map(function(v, i, arr) { + var newArr = (i % 2 === 0) ? arr.slice(i, i + 2) : null; + if (newArr) { var cmd = 'nightwatch --env ' + newArr.join(',') + cmdStr; cmdQueue.push(cmd); } From 322a7b870f12b3bf0a1750d3c1b634b40e098b8c Mon Sep 17 00:00:00 2001 From: Jacek Drobiecki Date: Wed, 22 Aug 2018 21:26:41 +0200 Subject: [PATCH 0648/1594] AdOcean adapter: GDPR support (#2988) * GDPR support * do not send empty gdpr_consent * AdOcean adapter: tests for gdpr_support * remove old comment --- modules/adoceanBidAdapter.js | 16 ++++++++++------ test/spec/modules/adoceanBidAdapter_spec.js | 19 ++++++++++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index 1949e0414a7..21e13e77a0a 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -15,11 +15,15 @@ function buildEndpointUrl(emiter, payload) { return 'https://' + emiter + '/ad.json?' + payloadString; } -function buildRequest(masterBidRequests, masterId) { +function buildRequest(masterBidRequests, masterId, gdprConsent) { const firstBid = masterBidRequests[0]; const payload = { id: masterId, }; + if (gdprConsent) { + payload.gdpr_consent = gdprConsent.consentString || undefined; + payload.gdpr = gdprConsent.gdprApplies ? 1 : 0; + } const bidIdMap = {}; @@ -72,15 +76,15 @@ export const spec = { return !!(bid.params.slaveId && bid.params.masterId && bid.params.emiter); }, - buildRequests: function(validBidRequests) { + buildRequests: function(validBidRequests, bidderRequest) { const bidRequestsByMaster = {}; let requests = []; - utils._each(validBidRequests, function(v) { - assignToMaster(v, bidRequestsByMaster); + utils._each(validBidRequests, function(bidRequest) { + assignToMaster(bidRequest, bidRequestsByMaster); }); - requests = utils._map(bidRequestsByMaster, function(v, k) { - return buildRequest(v, k); + requests = utils._map(bidRequestsByMaster, function(requests, masterId) { + return buildRequest(requests, masterId, bidderRequest.gdprConsent); }); return requests; diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index 149b9eb4d53..39eb514752a 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -57,23 +57,36 @@ describe('AdoceanAdapter', () => { } ]; + const bidderRequest = { + gdprConsent: { + consentString: 'BOQHk-4OSlWKFBoABBPLBd-AAAAgWAHAACAAsAPQBSACmgFTAOkA', + gdprApplies: true + } + }; + it('should add bidIdMap with slaveId => bidId mapping', () => { - const request = spec.buildRequests(bidRequests)[0]; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.bidIdMap).to.exists; const bidIdMap = request.bidIdMap; expect(bidIdMap[bidRequests[0].params.slaveId]).to.equal(bidRequests[0].bidId); }); it('sends bid request to url via GET', () => { - const request = spec.buildRequests(bidRequests)[0]; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.method).to.equal('GET'); expect(request.url).to.match(new RegExp(`^https://${bidRequests[0].params.emiter}/ad.json`)); }); it('should attach id to url', () => { - const request = spec.buildRequests(bidRequests)[0]; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.url).to.include('id=' + bidRequests[0].params.masterId); }); + + it('should attach consent information to url', () => { + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.url).to.include('gdpr=1'); + expect(request.url).to.include('gdpr_consent=' + bidderRequest.gdprConsent.consentString); + }); }) describe('interpretResponse', () => { From 3838a8f1d99c708b0903f722015f45e4f7a686ab Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 23 Aug 2018 10:31:51 -0400 Subject: [PATCH 0649/1594] update appnexus md file with working examples (#3014) --- modules/appnexusBidAdapter.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/modules/appnexusBidAdapter.md b/modules/appnexusBidAdapter.md index 822bd62997f..a1d12243888 100644 --- a/modules/appnexusBidAdapter.md +++ b/modules/appnexusBidAdapter.md @@ -22,58 +22,59 @@ var adUnits = [ banner: { sizes: [[300, 250], [300,600]] } - } + }, bids: [{ bidder: 'appnexus', params: { - placementId: '10433394' + placementId: 13144370 } }] }, // Native adUnit { code: 'native-div', - sizes: [[300, 250], [300,600]], + sizes: [[1, 1]], mediaTypes: { native: { title: { - required: true, - len: 80 - }, - body: { required: true }, - brand: { + body: { required: true }, image: { required: true }, - clickUrl: { + sponsoredBy: { required: true }, + icon: { + required: false + } } }, bids: [{ bidder: 'appnexus', params: { - placementId: '9880618' + placementId: 13232354, + allowSmallerSizes: true } }] }, // Video instream adUnit { code: 'video-instream', - sizes: [640, 480], + sizes: [[640, 480]], mediaTypes: { video: { + playerSize: [[640, 480]], context: 'instream' }, }, bids: [{ bidder: 'appnexus', params: { - placementId: '9333431', + placementId: 13232361, video: { skippable: true, playback_methods: ['auto_play_sound_off'] @@ -84,9 +85,10 @@ var adUnits = [ // Video outstream adUnit { code: 'video-outstream', - sizes: [[640, 480]], + sizes: [[300, 250]], mediaTypes: { video: { + playerSize: [[300, 250]], context: 'outstream' } }, @@ -94,7 +96,7 @@ var adUnits = [ { bidder: 'appnexus', params: { - placementId: '5768085', + placementId: 13232385, video: { skippable: true, playback_method: ['auto_play_sound_off'] @@ -116,7 +118,7 @@ var adUnits = [ bids: [{ bidder: 'appnexus', params: { - placementId: '10433394', + placementId: 13144370, app: { id: "B1O2W3M4AN.com.prebid.webview", geo: { From ab2c0500a53e772ed1e7ce76287bf3f967c9cc5b Mon Sep 17 00:00:00 2001 From: ankur-modi <38654685+ankur-modi@users.noreply.github.com> Date: Thu, 23 Aug 2018 21:12:36 +0530 Subject: [PATCH 0650/1594] support gdpr for one video adapter (#2981) * support gdpr for one video adapter * gdpr support 1video --- modules/oneVideoBidAdapter.js | 30 ++++++++++++++++-- test/spec/modules/oneVideoBidAdapter_spec.js | 32 ++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 38367837faf..5b1fd999ee6 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -36,14 +36,17 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {validBidRequests[]} - an array of bids + * @param bidderRequest * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(bids) { + buildRequests: function(bids, bidRequest) { + let consentData = bidRequest ? bidRequest.gdprConsent : null; + return bids.map(bid => { return { method: 'POST', url: location.protocol + spec.ENDPOINT + bid.params.pubId, - data: getRequestData(bid), + data: getRequestData(bid, consentData), options: {contentType: 'application/json'}, bidRequest: bid } @@ -127,7 +130,11 @@ function getSize(sizes) { }; } -function getRequestData(bid) { +function isConsentRequired(consentData) { + return !!(consentData && consentData.gdprApplies); +} + +function getRequestData(bid, consentData) { let loc = utils.getTopWindowLocation(); let global = (window.top) ? window.top : window; let page = (bid.params.site && bid.params.site.page) ? (bid.params.site.page) : (loc.href); @@ -179,6 +186,23 @@ function getRequestData(bid) { if (bid.params.site && bid.params.site.id) { bidData.site.id = bid.params.site.id } + + if (isConsentRequired(consentData)) { + bidData.regs = { + ext: { + gdpr: 1 + } + }; + + if (consentData.consentString) { + bidData.user = { + ext: { + consent: consentData.consentString + } + }; + } + } + return bidData; } diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 3d7bba417f9..278b39fd079 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -1,9 +1,12 @@ import { expect } from 'chai'; import { spec } from 'modules/oneVideoBidAdapter'; import * as utils from 'src/utils'; +import {config} from 'src/config'; describe('OneVideoBidAdapter', () => { let bidRequest; + let bidderRequest; + let mockConfig; beforeEach(() => { bidRequest = { @@ -132,4 +135,33 @@ describe('OneVideoBidAdapter', () => { expect(bidResponse).to.deep.equal(o); }); }); + + describe('when GDPR applies', function () { + beforeEach(function () { + bidderRequest = { + gdprConsent: { + consentString: 'test-gdpr-consent-string', + gdprApplies: true + } + }; + + mockConfig = { + consentManagement: { + cmpApi: 'iab', + timeout: 1111, + allowAuctionWithoutConsent: 'cancel' + } + }; + }); + + it('should send a signal to specify that GDPR applies to this request', function () { + const request = spec.buildRequests([ bidRequest ], bidderRequest); + expect(request[0].data.regs.ext.gdpr).to.equal(1); + }); + + it('should send the consent string', function () { + const request = spec.buildRequests([ bidRequest ], bidderRequest); + expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); + }); + }); }); From bf3beefc73b4445a19f24267e04a7ce9e814e414 Mon Sep 17 00:00:00 2001 From: bretg Date: Fri, 24 Aug 2018 11:51:25 -0400 Subject: [PATCH 0651/1594] Rubicon adapter: adding size 320x180 (#3018) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 83c3c69cf15..0f66aa36fb0 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -71,6 +71,7 @@ var sizeMap = { 199: '640x200', 213: '1030x590', 214: '980x360', + 229: '320x180', 232: '580x400', 257: '400x600' }; From ce1ea590856805fe603b4933f3542871672982a4 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 24 Aug 2018 12:51:01 -0600 Subject: [PATCH 0652/1594] few tweaks and clarifications to release documentation (#3020) * few tweaks and clarifications to release documentation * added release template to release instructions * fix formatting * fix formatting --- RELEASE_SCHEDULE.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index 637ed354c74..a1fa77b7db0 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -17,6 +17,8 @@ Announcements regarding releases will be made to the #headerbidding-dev channel ## 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 all browserstack tests are passing. On PR merge to master CircleCI will run unit tests on browserstack. Checking the last CircleCI build [here](https://circleci.com/gh/prebid) for master branch will show you detailed results. In case of failure do following, @@ -24,6 +26,8 @@ Announcements regarding releases will be made to the #headerbidding-dev channel - If you are not able to fix tests in time. Skip the test, create issue and tag contributor. #### How to run tests in browserstack + + _Note: the following browserstack information is only relevant for debugging purposes, if you will not be debugging then it can be skipped._ Set the environment variables. You may want to add these to your `~/.bashrc` for convenience. @@ -59,11 +63,12 @@ Announcements regarding releases will be made to the #headerbidding-dev channel Pull these changes locally by running command ``` git pull + git fetch --tags ``` and verify the tag. -5. Update coveralls +5. Update coveralls _(skip for legacy)_ We use https://coveralls.io/ to show parts of code covered by unit tests. @@ -75,7 +80,9 @@ Announcements regarding releases will be made to the #headerbidding-dev channel Run `gulp coveralls` to update code coverage history. -6. Distribute the code +6. Distribute the code + + _Note: do not go to step 7 until step 6 has been verified completed._ Reach out to any of the Appnexus folks to trigger the jenkins job. @@ -83,7 +90,7 @@ Announcements regarding releases will be made to the #headerbidding-dev channel 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. -7. Post Release Steps +7. Post Release Version Update the version Manually edit Prebid's package.json to become "1.x.x-pre" (using the values for the next release). Then commit your changes. @@ -91,6 +98,17 @@ Announcements regarding releases will be made to the #headerbidding-dev channel git commit -m "Increment pre version" git push ``` + +8. Create new release draft + + Go to [github releases](https://github.com/prebid/Prebid.js/releases) and add a new draft for the next version of Prebid.js with the following template: +``` +## 🚀New Features + +## 🛠Maintenance + +## 🐛Bug Fixes +``` ## Beta Releases From d7f3f90ed42b4e47d64e5484b0a2638d42a47694 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Mon, 27 Aug 2018 10:30:27 -0700 Subject: [PATCH 0653/1594] OpenX Adapter: Fixed a bug where video requests do not have a bidder configuration code. (#3021) --- modules/openxBidAdapter.js | 4 ++-- test/spec/modules/openxBidAdapter_spec.js | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 6a79681484e..952e706ef7d 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.3'; +const BIDDER_VERSION = '2.1.4'; let shouldSendBoPixel = true; @@ -201,6 +201,7 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { tz: new Date().getTimezoneOffset(), tws: getViewportDimensions(isInIframe), be: 1, + bc: bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, dddid: utils._map(bids, bid => bid.transactionId).join(','), nocache: new Date().getTime() }; @@ -230,7 +231,6 @@ function buildOXBannerRequest(bids, bidderRequest) { let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); let auids = utils._map(bids, bid => bid.params.unit); queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); - queryParams.bc = bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`; queryParams.divIds = utils._map(bids, bid => encodeURIComponent(bid.adUnitCode)).join(','); if (auids.some(auid => auid)) { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index c0588f2eff0..324f9d80ae4 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -839,6 +839,13 @@ describe('OpenxAdapter', () => { expect(dataParams.vwd).to.equal(640); }); + it('should send a bc parameter', () => { + const request = spec.buildRequests(bidRequestsWithMediaTypes); + const dataParams = request[0].data; + + expect(dataParams.bc).to.have.string('hb_pb'); + }); + describe('when using the video param', function () { let videoBidRequest; From 0bfe01331a8b08957f065d8373b179f5bc55cc65 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 28 Aug 2018 08:52:56 -0400 Subject: [PATCH 0654/1594] Revert "Added render param in Sonobi adapter (#2970)" (#3027) This reverts commit 5e430e382922ee16e5e0cefa88198b9a01e60ba2. --- modules/sonobiBidAdapter.js | 3 --- test/spec/modules/sonobiBidAdapter_spec.js | 5 ----- 2 files changed, 8 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 779736520cc..3d9ad2ce976 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -66,9 +66,6 @@ export const spec = { if (validBidRequests[0].params.referrer) { payload.ref = validBidRequests[0].params.referrer; } - if (validBidRequests[0].params.render) { - payload.render = validBidRequests[0].params.render; - } // Apply GDPR parameters to request. if (bidderRequest && bidderRequest.gdprConsent) { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 63fb52b2dbd..1b0986cb8c1 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -207,11 +207,6 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.s).not.to.be.empty expect(bidRequests.data.hfa).to.equal('hfakey') }) - it('should return a properly formatted request with render', () => { - bidRequest[0].params.render = 'safeframe' - const bidRequests = spec.buildRequests(bidRequest) - expect(bidRequests.data.render).to.equal('safeframe') - }) it('should return null if there is nothing to bid on', () => { const bidRequests = spec.buildRequests([{params: {}}]) From e83f3e843c557a67d2038da13fe4cb1f985fdd4a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 28 Aug 2018 10:05:46 -0400 Subject: [PATCH 0655/1594] check for null in data (#3026) --- src/secureCreatives.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 2204a6e7643..cd289cf657f 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -25,7 +25,7 @@ function receiveMessage(ev) { return; } - if (data.adId) { + if (data && data.adId) { const adObject = find(auctionManager.getBidsReceived(), function (bid) { return bid.adId === data.adId; }); From 69a275a416227ba218029142468f5c4876b65536 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 28 Aug 2018 10:33:44 -0400 Subject: [PATCH 0656/1594] Prebid 1.22.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 377f49b3810..892b7bcec43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.22.0-pre", + "version": "1.22.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From fa786348f53b3ab6f01c39e713b3c4f75578f2fd Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 28 Aug 2018 10:43:51 -0400 Subject: [PATCH 0657/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 892b7bcec43..a71e6309103 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.22.0", + "version": "1.23.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 8dc9a03e9c041d5fe65dc69bd60acd816edeadb3 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 30 Aug 2018 08:03:51 -0600 Subject: [PATCH 0658/1594] Remove unused pbjs.cbTimeout (#3028) --- src/prebid.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index ea7e3fadd8e..f30b063f70e 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -35,9 +35,6 @@ sessionLoader(); /* Public vars */ $$PREBID_GLOBAL$$.bidderSettings = $$PREBID_GLOBAL$$.bidderSettings || {}; -// current timeout set in `requestBids` or to default `bidderTimeout` -$$PREBID_GLOBAL$$.cbTimeout = $$PREBID_GLOBAL$$.cbTimeout || 200; - // let the world know we are loaded $$PREBID_GLOBAL$$.libLoaded = true; From 38c9fe7724385c268cb27c4cb2c134017806e3e1 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Thu, 30 Aug 2018 19:45:53 +0200 Subject: [PATCH 0659/1594] Improve Digital adapter: always drop user syncs when available (#3009) * Always drop user syncs when available --- modules/improvedigitalBidAdapter.js | 36 +++-- .../modules/improvedigitalBidAdapter_spec.js | 135 ++++++++++-------- 2 files changed, 100 insertions(+), 71 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index c99e496f17c..2cc1d8b39b0 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -1,12 +1,11 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; -import { userSync } from 'src/userSync'; const BIDDER_CODE = 'improvedigital'; export const spec = { - version: '4.2.0', + version: '4.3.0', code: BIDDER_CODE, aliases: ['id'], @@ -91,15 +90,34 @@ export const spec = { bid.width = bidObject.w; bids.push(bid); - - // Register user sync URLs - if (utils.isArray(bidObject.sync)) { - utils._each(bidObject.sync, function (syncElement) { - userSync.registerSync('image', spec.code, syncElement); - }); - } }); return bids; + }, + + /** + * 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) { + if (syncOptions.pixelEnabled) { + const syncs = []; + serverResponses.forEach(response => { + response.body.bid.forEach(bidObject => { + if (utils.isArray(bidObject.sync)) { + bidObject.sync.forEach(syncElement => { + if (syncs.indexOf(syncElement) === -1) { + syncs.push(syncElement); + } + }); + } + }); + }); + return syncs.map(sync => ({ type: 'image', url: sync })); + } + return []; } }; diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index d7595934194..b3e99b3274e 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -164,61 +164,61 @@ describe('Improve Digital Adapter Tests', function () { }); }); - describe('interpretResponse', () => { - const serverResponse = { - 'body': { - 'id': '687a06c541d8d1', - 'site_id': 191642, - 'bid': [ - { - 'isNet': false, - 'id': '33e9500b21129f', - 'advid': '5279', - 'price': 1.45888594164456, - 'nurl': 'http://ad.360yield.com/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', - 'h': 290, - 'pid': 1053688, - 'sync': [ - 'http://link1', - 'http://link2' - ], - 'crid': '422031', - 'w': 600, - 'cid': '99006', - 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' - } - ], - 'debug': '' - } - }; - - const serverResponseTwoBids = { - 'body': { - 'id': '687a06c541d8d1', - 'site_id': 191642, - 'bid': [ - serverResponse.body.bid[0], - { - 'isNet': true, - 'id': '1234', - 'advid': '5280', - 'price': 1.23, - 'nurl': 'http://link/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', - 'h': 400, - 'pid': 1053688, - 'sync': [ - 'http://link3' - ], - 'crid': '422033', - 'w': 700, - 'cid': '99006', - 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' - } - ], - 'debug': '' - } - }; + const serverResponse = { + 'body': { + 'id': '687a06c541d8d1', + 'site_id': 191642, + 'bid': [ + { + 'isNet': false, + 'id': '33e9500b21129f', + 'advid': '5279', + 'price': 1.45888594164456, + 'nurl': 'http://ad.360yield.com/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', + 'h': 290, + 'pid': 1053688, + 'sync': [ + 'http://link1', + 'http://link2' + ], + 'crid': '422031', + 'w': 600, + 'cid': '99006', + 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' + } + ], + 'debug': '' + } + }; + + const serverResponseTwoBids = { + 'body': { + 'id': '687a06c541d8d1', + 'site_id': 191642, + 'bid': [ + serverResponse.body.bid[0], + { + 'isNet': true, + 'id': '1234', + 'advid': '5280', + 'price': 1.23, + 'nurl': 'http://link/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', + 'h': 400, + 'pid': 1053688, + 'sync': [ + 'http://link3' + ], + 'crid': '422033', + 'w': 700, + 'cid': '99006', + 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' + } + ], + 'debug': '' + } + }; + describe('interpretResponse', () => { let expectedBid = [ { 'ad': '', @@ -260,14 +260,6 @@ describe('Improve Digital Adapter Tests', function () { expect(bids).to.deep.equal(expectedTwoBids); }); - it('should register user syncs', () => { - const registerSyncSpy = sinon.spy(userSync, 'registerSync'); - const bids = spec.interpretResponse(serverResponse); - expect(registerSyncSpy.withArgs('image', 'improvedigital', 'http://link1').calledOnce).to.equal(true); - expect(registerSyncSpy.withArgs('image', 'improvedigital', 'http://link2').calledOnce).to.equal(true); - registerSyncSpy.restore(); - }); - it('should set dealId correctly', () => { let response = JSON.parse(JSON.stringify(serverResponse)); let bids; @@ -338,4 +330,23 @@ describe('Improve Digital Adapter Tests', function () { expect(bids[0].netRevenue).to.equal(true); }); }); + + describe('getUserSyncs', () => { + const serverResponses = [ serverResponseTwoBids ]; + + it('should return no syncs when pixel syncing is disabled', () => { + const syncs = spec.getUserSyncs({ pixelEnabled: false }, serverResponses); + expect(syncs).to.deep.equal([]); + }); + + it('should return user syncs', () => { + const syncs = spec.getUserSyncs({ pixelEnabled: true }, serverResponses); + const expected = [ + { type: 'image', url: 'http://link1' }, + { type: 'image', url: 'http://link2' }, + { type: 'image', url: 'http://link3' } + ]; + expect(syncs).to.deep.equal(expected); + }); + }); }); From c6927c5846f41b043704e0ee25d48ce00502e69a Mon Sep 17 00:00:00 2001 From: skazedo Date: Thu, 30 Aug 2018 16:38:20 -0400 Subject: [PATCH 0660/1594] Modified API url (#3030) * initial commit * updated contact and tag details * changes ti support the renderers * changes to pass dimId * fixed names of internal mapping * added comment * added gdpr param to request and other fixes * modified api url --- modules/zedoBidAdapter.js | 8 ++++++-- modules/zedoBidAdapter.md | 2 +- test/spec/modules/zedoBidAdapter_spec.js | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/zedoBidAdapter.js b/modules/zedoBidAdapter.js index 0420c479ae9..d6f75da4ece 100644 --- a/modules/zedoBidAdapter.js +++ b/modules/zedoBidAdapter.js @@ -4,8 +4,8 @@ import { BANNER, VIDEO } from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'zedo'; -const URL = '//z2.zedo.com/asw/fmb.json'; -const SECURE_URL = '//z2.zedo.com/asw/fmb.json'; +const URL = '//z2.zedo.com/asw/fmh.json'; +const SECURE_URL = '//z2.zedo.com/asw/fmh.json'; const DIM_TYPE = { '7': 'display', '9': 'display', @@ -15,6 +15,10 @@ const DIM_TYPE = { '85': 'Inarticle', '86': 'pswipeup', '88': 'Inview', + '100': 'display', + '101': 'display', + '102': 'display', + '103': 'display' // '85': 'pre-mid-post-roll', }; diff --git a/modules/zedoBidAdapter.md b/modules/zedoBidAdapter.md index 9ffcd61f164..6555a1e6506 100644 --- a/modules/zedoBidAdapter.md +++ b/modules/zedoBidAdapter.md @@ -20,7 +20,7 @@ For video integration, ZEDO returns content as vastXML and requires the publishe { bidder: 'zedo', params: { - code: 2264004118 + channelCode: 2264004118 dimId: 9 } } diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js index 6d0ab7c68f6..d199156cfe4 100644 --- a/test/spec/modules/zedoBidAdapter_spec.js +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -43,7 +43,7 @@ describe('The ZEDO bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmb.json/); + expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmh.json/); expect(request.method).to.equal('GET'); const zedoRequest = request.data; expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}]}'); @@ -68,7 +68,7 @@ describe('The ZEDO bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmb.json/); + expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmh.json/); expect(request.method).to.equal('GET'); const zedoRequest = request.data; expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":640,"height":480,"dimension":85,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"Inarticle"}]}]}'); From 25e62a0c5be8abd4cacafd6f7e2190574804ac8c Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Fri, 31 Aug 2018 17:47:49 +0300 Subject: [PATCH 0661/1594] Replacing all arrow functions in Mocha function calls (#3036) * replace arrow function in describe calls * replace arrow function in it calls * replace arrow function in before, beforeEach, after and afterEach calls * Merge remote-tracking branch 'upstream/master' # Conflicts: # test/spec/modules/improvedigitalBidAdapter_spec.js --- test/mocks/videoCacheStub.js | 4 +- test/spec/AnalyticsAdapter_spec.js | 36 +- test/spec/adloader_spec.js | 10 +- test/spec/auctionmanager_spec.js | 56 +- test/spec/config_spec.js | 46 +- test/spec/cpmBucketManager_spec.js | 18 +- test/spec/debugging_spec.js | 30 +- test/spec/hook_spec.js | 18 +- test/spec/modules/a4gBidAdapter_spec.js | 26 +- test/spec/modules/aardvarkBidAdapter_spec.js | 38 +- test/spec/modules/adbutlerBidAdapter_spec.js | 32 +- test/spec/modules/adformBidAdapter_spec.js | 62 +- .../modules/adgenerationBidAdapter_spec.js | 30 +- .../adkernelAdnAnalyticsAdapter_spec.js | 54 +- .../modules/adkernelAdnBidAdapter_spec.js | 62 +- test/spec/modules/adkernelBidAdapter_spec.js | 66 +- test/spec/modules/admixerBidAdapter_spec.js | 24 +- test/spec/modules/adoceanBidAdapter_spec.js | 28 +- .../modules/adomikAnalyticsAdapter_spec.js | 6 +- test/spec/modules/adspiritBidAdapter_spec.js | 32 +- .../modules/adtelligentBidAdapter_spec.js | 36 +- test/spec/modules/aduptechBidAdapter_spec.js | 46 +- .../modules/adxcgAnalyticsAdapter_spec.js | 14 +- test/spec/modules/adxcgBidAdapter_spec.js | 38 +- test/spec/modules/adyoulikeBidAdapter_spec.js | 40 +- test/spec/modules/ajaBidAdapter_spec.js | 20 +- test/spec/modules/andbeyondBidAdapter_spec.js | 46 +- test/spec/modules/aolBidAdapter_spec.js | 130 ++-- test/spec/modules/appnexusBidAdapter_spec.js | 56 +- test/spec/modules/arteebeeBidAdapter_spec.js | 24 +- test/spec/modules/atomxBidAdapter_spec.js | 20 +- .../modules/audienceNetworkBidAdapter_spec.js | 66 +- .../spec/modules/beachfrontBidAdapter_spec.js | 116 +-- test/spec/modules/betweenBidAdapter_spec.js | 8 +- test/spec/modules/bizzclickBidAdapter_spec.js | 30 +- test/spec/modules/brainyBidAdapter_spec.js | 28 +- .../spec/modules/bridgewellBidAdapter_spec.js | 76 +- test/spec/modules/c1xBidAdapter_spec.js | 32 +- test/spec/modules/ccxBidAdapter_spec.js | 14 +- .../spec/modules/clickforceBidAdapter_spec.js | 30 +- .../modules/colossussspBidAdapter_spec.js | 30 +- test/spec/modules/consentManagement_spec.js | 64 +- .../spec/modules/consumableBidAdapter_spec.js | 42 +- .../modules/contentigniteBidAdapter_spec.js | 28 +- test/spec/modules/coxBidAdapter_spec.js | 44 +- test/spec/modules/criteoBidAdapter_spec.js | 32 +- test/spec/modules/currency_spec.js | 44 +- test/spec/modules/danmarketBidAdapter_spec.js | 34 +- test/spec/modules/dfpAdServerVideo_spec.js | 30 +- test/spec/modules/dgadsBidAdapter_spec.js | 30 +- .../modules/districtmDmxBidAdapter_spec.js | 58 +- test/spec/modules/divreachBidAdapter_spec.js | 24 +- test/spec/modules/ebdrBidAdapter_spec.js | 58 +- .../modules/eplanningAnalyticsAdapter_spec.js | 10 +- test/spec/modules/eplanningBidAdapter_spec.js | 62 +- test/spec/modules/etargetBidAdapter_spec.js | 58 +- test/spec/modules/fairtradeBidAdapter_spec.js | 28 +- test/spec/modules/fidelityBidAdapter_spec.js | 32 +- .../modules/freewheel-sspBidAdapter_spec.js | 394 +++++----- test/spec/modules/fyberBidAdapter_spec.js | 36 +- test/spec/modules/gambidBidAdapter_spec.js | 36 +- test/spec/modules/gammaBidAdapter_spec.js | 20 +- test/spec/modules/getintentBidAdapter_spec.js | 18 +- test/spec/modules/giantsBidAdapter_spec.js | 602 ++++++++-------- test/spec/modules/gjirafaBidAdapter_spec.js | 28 +- test/spec/modules/gumgumBidAdapter_spec.js | 32 +- test/spec/modules/gxoneBidAdapter_spec.js | 28 +- .../modules/huddledmassesBidAdapter_spec.js | 32 +- test/spec/modules/iasBidAdapter_spec.js | 72 +- .../modules/improvedigitalBidAdapter_spec.js | 50 +- test/spec/modules/innityBidAdapter_spec.js | 18 +- test/spec/modules/inskinBidAdapter_spec.js | 46 +- .../interactiveOffersBidAdapter_spec.js | 30 +- test/spec/modules/invibesBidAdapter_spec.js | 50 +- test/spec/modules/iqmBidAdapter_spec.js | 34 +- test/spec/modules/ixBidAdapter_spec.js | 94 +-- test/spec/modules/jcmBidAdapter_spec.js | 30 +- .../modules/justpremiumBidAdapter_spec.js | 24 +- test/spec/modules/kargoBidAdapter_spec.js | 8 +- test/spec/modules/komoonaBidAdapter_spec.js | 12 +- test/spec/modules/kummaBidAdapter_spec.js | 26 +- .../spec/modules/lifestreetBidAdapter_spec.js | 48 +- test/spec/modules/lkqdBidAdapter_spec.js | 30 +- .../spec/modules/lockerdomeBidAdapter_spec.js | 20 +- .../spec/modules/madvertiseBidAdapter_spec.js | 28 +- test/spec/modules/mantisBidAdapter_spec.js | 32 +- test/spec/modules/medianetBidAdapter_spec.js | 60 +- test/spec/modules/mobfoxBidAdapter_spec.js | 20 +- test/spec/modules/my6senseBidAdapter_spec.js | 28 +- .../modules/nanointeractiveBidAdapter_spec.js | 4 +- .../modules/nasmediaAdmixerBidAdapter_spec.js | 22 +- test/spec/modules/oneVideoBidAdapter_spec.js | 34 +- .../modules/oneplanetonlyBidAdapter_spec.js | 26 +- test/spec/modules/onetagBidAdapter_spec.js | 32 +- test/spec/modules/openxBidAdapter_spec.js | 106 +-- test/spec/modules/optimaticBidAdapter_spec.js | 44 +- test/spec/modules/optimeraBidAdapter_spec.js | 18 +- test/spec/modules/orbitsoftBidAdapter_spec.js | 32 +- test/spec/modules/papyrusBidAdapter_spec.js | 24 +- test/spec/modules/peak226BidAdapter_spec.js | 22 +- .../spec/modules/platformioBidAdapter_spec.js | 670 +++++++++--------- .../modules/playgroundxyzBidAdapter_spec.js | 32 +- test/spec/modules/polluxBidAdapter_spec.js | 20 +- test/spec/modules/polymorphBidAdapter_spec.js | 28 +- .../modules/prebidServerBidAdapter_spec.js | 102 +-- test/spec/modules/pubCommonId_spec.js | 6 +- test/spec/modules/pubmaticBidAdapter_spec.js | 44 +- .../modules/pubwiseAnalyticsAdapter_spec.js | 8 +- .../spec/modules/pulsepointBidAdapter_spec.js | 30 +- test/spec/modules/quantcastBidAdapter_spec.js | 42 +- test/spec/modules/quantumBidAdapter_spec.js | 32 +- test/spec/modules/readpeakBidAdapter_spec.js | 28 +- .../modules/realvuAnalyticsAdapter_spec.js | 30 +- test/spec/modules/rhythmoneBidAdapter_spec.js | 2 +- test/spec/modules/rockyouBidAdapter_spec.js | 42 +- .../modules/roxotAnalyticsAdapter_spec.js | 24 +- test/spec/modules/rtbdemandBidAdapter_spec.js | 30 +- .../modules/rtbdemandadkBidAdapter_spec.js | 58 +- test/spec/modules/rtbhouseBidAdapter_spec.js | 30 +- .../modules/rubiconAnalyticsAdapter_spec.js | 44 +- test/spec/modules/rubiconBidAdapter_spec.js | 174 ++--- test/spec/modules/rxrtbBidAdapter_spec.js | 20 +- test/spec/modules/s2sTesting_spec.js | 58 +- test/spec/modules/saraBidAdapter_spec.js | 28 +- test/spec/modules/sekindoUMBidAdapter_spec.js | 30 +- test/spec/modules/serverbidBidAdapter_spec.js | 42 +- .../modules/serverbidServerBidAdapter_spec.js | 32 +- .../modules/sharethroughBidAdapter_spec.js | 50 +- .../modules/sigmoidAnalyticsAdapter_spec.js | 14 +- .../modules/smartadserverBidAdapter_spec.js | 22 +- test/spec/modules/smartyadsBidAdapter_spec.js | 40 +- .../modules/somoaudienceBidAdapter_spec.js | 64 +- test/spec/modules/sonobiBidAdapter_spec.js | 64 +- test/spec/modules/sortableBidAdapter_spec.js | 46 +- test/spec/modules/sovrnBidAdapter_spec.js | 32 +- test/spec/modules/telariaBidAdapter_spec.js | 42 +- test/spec/modules/trionBidAdapter_spec.js | 54 +- .../spec/modules/tripleliftBidAdapter_spec.js | 30 +- test/spec/modules/trustxBidAdapter_spec.js | 34 +- test/spec/modules/ucfunnelBidAdapter_spec.js | 38 +- .../modules/underdogmediaBidAdapter_spec.js | 40 +- test/spec/modules/undertoneBidAdapter_spec.js | 24 +- test/spec/modules/unrulyBidAdapter_spec.js | 46 +- test/spec/modules/uolBidAdapter_spec.js | 50 +- .../spec/modules/vertamediaBidAdapter_spec.js | 34 +- test/spec/modules/vertozBidAdapter_spec.js | 22 +- test/spec/modules/viBidAdapter_spec.js | 24 +- test/spec/modules/vidazooBidAdapter_spec.js | 42 +- test/spec/modules/visxBidAdapter_spec.js | 40 +- .../modules/vubleAnalyticsAdapter_spec.js | 8 +- test/spec/modules/vubleBidAdapter_spec.js | 50 +- test/spec/modules/weboramaBidAdapter_spec.js | 30 +- test/spec/modules/widespaceBidAdapter_spec.js | 36 +- test/spec/modules/xendizBidAdapter_spec.js | 30 +- test/spec/modules/xhbBidAdapter_spec.js | 54 +- test/spec/modules/yieldlabBidAdapter_spec.js | 30 +- test/spec/modules/yieldmoBidAdapter_spec.js | 30 +- test/spec/modules/yieldoneBidAdapter_spec.js | 20 +- .../yuktamediaAnalyticsAdaptor_spec.js | 14 +- test/spec/modules/zedoBidAdapter_spec.js | 34 +- test/spec/native_spec.js | 20 +- test/spec/renderer_spec.js | 22 +- test/spec/sizeMapping_spec.js | 26 +- test/spec/unit/adServerManager_spec.js | 8 +- test/spec/unit/core/adapterManager_spec.js | 120 ++-- test/spec/unit/core/bidderFactory_spec.js | 90 +-- test/spec/unit/core/targeting_spec.js | 40 +- test/spec/unit/pbjs_api_spec.js | 220 +++--- test/spec/url_spec.js | 38 +- test/spec/userSync_spec.js | 48 +- test/spec/utils_spec.js | 44 +- test/spec/videoCache_spec.js | 38 +- test/spec/video_spec.js | 12 +- 173 files changed, 4110 insertions(+), 4096 deletions(-) diff --git a/test/mocks/videoCacheStub.js b/test/mocks/videoCacheStub.js index 4a1d8bca343..39f5d67b6a9 100644 --- a/test/mocks/videoCacheStub.js +++ b/test/mocks/videoCacheStub.js @@ -12,7 +12,7 @@ import * as videoCache from 'src/videoCache'; export default function useVideoCacheStub(responses) { let storeStub; - beforeEach(() => { + beforeEach(function () { storeStub = sinon.stub(videoCache, 'store'); if (responses.store instanceof Error) { @@ -22,7 +22,7 @@ export default function useVideoCacheStub(responses) { } }); - afterEach(() => { + afterEach(function () { videoCache.store.restore(); }); diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index c6c50f76ecd..39096c0c4a3 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -22,19 +22,19 @@ FEATURE: Analytics Adapters API let requests; let adapter; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = (request) => requests.push(request); adapter = new AnalyticsAdapter(config); }); - afterEach(() => { + afterEach(function () { xhr.restore(); adapter.disableAnalytics(); }); - it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, () => { + it(`SHOULD call the endpoint WHEN an event occurs that is to be tracked`, function () { const eventType = BID_REQUESTED; const args = { some: 'data' }; @@ -44,7 +44,7 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {some: 'data'}, eventType: 'bidRequested'}); }); - it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, () => { + it(`SHOULD queue the event first and then track it WHEN an event occurs before tracking library is available`, function () { const eventType = BID_RESPONSE; const args = { wat: 'wot' }; @@ -55,16 +55,16 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {wat: 'wot'}, eventType: 'bidResponse'}); }); - describe(`WHEN an event occurs after enable analytics\n`, () => { - beforeEach(() => { + describe(`WHEN an event occurs after enable analytics\n`, function () { + beforeEach(function () { sinon.stub(events, 'getEvents').returns([]); // these tests shouldn't be affected by previous tests }); - afterEach(() => { + afterEach(function () { events.getEvents.restore(); }); - it('SHOULD call global when a bidWon event occurs', () => { + it('SHOULD call global when a bidWon event occurs', function () { const eventType = BID_WON; const args = { more: 'info' }; @@ -75,7 +75,7 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it('SHOULD call global when a adRenderFailed event occurs', () => { + it('SHOULD call global when a adRenderFailed event occurs', function () { const eventType = AD_RENDER_FAILED; const args = { call: 'adRenderFailed' }; @@ -86,7 +86,7 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); - it('SHOULD call global when a bidRequest event occurs', () => { + it('SHOULD call global when a bidRequest event occurs', function () { const eventType = BID_REQUESTED; const args = { call: 'request' }; @@ -97,7 +97,7 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'bidRequested'}); }); - it('SHOULD call global when a bidResponse event occurs', () => { + it('SHOULD call global when a bidResponse event occurs', function () { const eventType = BID_RESPONSE; const args = { call: 'response' }; @@ -108,7 +108,7 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {call: 'response'}, eventType: 'bidResponse'}); }); - it('SHOULD call global when a bidTimeout event occurs', () => { + it('SHOULD call global when a bidTimeout event occurs', function () { const eventType = BID_TIMEOUT; const args = { call: 'timeout' }; @@ -119,7 +119,7 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {call: 'timeout'}, eventType: 'bidTimeout'}); }); - it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', () => { + it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', function () { const eventType = BID_TIMEOUT; const args = { call: 'timeout' }; @@ -130,19 +130,19 @@ FEATURE: Analytics Adapters API expect(requests.length).to.equal(1); }); - describe(`AND sampling is enabled\n`, () => { + describe(`AND sampling is enabled\n`, function () { const eventType = BID_WON; const args = { more: 'info' }; - beforeEach(() => { + beforeEach(function () { sinon.stub(Math, 'random').returns(0.5); }); - afterEach(() => { + afterEach(function () { Math.random.restore(); }); - it(`THEN should enable analytics when random number is in sample range`, () => { + it(`THEN should enable analytics when random number is in sample range`, function () { adapter.enableAnalytics({ options: { sampling: 0.75 @@ -155,7 +155,7 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {more: 'info'}, eventType: 'bidWon'}); }); - it(`THEN should disable analytics when random number is outside sample range`, () => { + it(`THEN should disable analytics when random number is outside sample range`, function () { adapter.enableAnalytics({ options: { sampling: 0.25 diff --git a/test/spec/adloader_spec.js b/test/spec/adloader_spec.js index 55224cb0aab..5c4eff31028 100644 --- a/test/spec/adloader_spec.js +++ b/test/spec/adloader_spec.js @@ -5,24 +5,24 @@ describe('adLoader', function () { let utilsinsertElementStub; let utilsLogErrorStub; - beforeEach(() => { + beforeEach(function () { utilsinsertElementStub = sinon.stub(utils, 'insertElement'); utilsLogErrorStub = sinon.stub(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { utilsinsertElementStub.restore(); utilsLogErrorStub.restore(); }); - describe('loadExternalScript', () => { - it('requires moduleCode to be included on the request', () => { + describe('loadExternalScript', function () { + it('requires moduleCode to be included on the request', function () { adLoader.loadExternalScript('someURL'); expect(utilsLogErrorStub.called).to.be.true; expect(utilsinsertElementStub.called).to.be.false; }); - it('only allows whitelisted vendors to load scripts', () => { + it('only allows whitelisted vendors to load scripts', function () { adLoader.loadExternalScript('someURL', 'criteo'); expect(utilsLogErrorStub.called).to.be.false; expect(utilsinsertElementStub.called).to.be.true; diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 6fbc48b3cdc..0562479ca24 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -109,11 +109,11 @@ function mockAjaxBuilder() { describe('auctionmanager.js', function () { let xhr; - before(() => { + before(function () { xhr = sinon.useFakeXMLHttpRequest(); }); - after(() => { + after(function () { xhr.restore(); }); @@ -483,8 +483,8 @@ describe('auctionmanager.js', function () { }); }); - describe('adjustBids', () => { - it('should adjust bids if greater than zero and pass copy of bid object', () => { + describe('adjustBids', function () { + it('should adjust bids if greater than zero and pass copy of bid object', function () { const bid = Object.assign({}, bidfactory.createBid(2), fixtures.getBidResponses()[5] @@ -532,7 +532,7 @@ describe('auctionmanager.js', function () { }); }); - describe('addBidResponse', () => { + describe('addBidResponse', function () { let createAuctionStub; let adUnits; let adUnitCodes; @@ -542,23 +542,23 @@ describe('auctionmanager.js', function () { let bids = TEST_BIDS; let makeRequestsStub; - before(() => { + before(function () { makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder); }); - after(() => { + after(function () { ajaxStub.restore(); adaptermanager.makeBidRequests.restore(); }); - describe('when auction timeout is 3000', () => { + describe('when auction timeout is 3000', function () { let loadScriptStub; - before(() => { + before(function () { makeRequestsStub.returns(TEST_BID_REQS); }); - beforeEach(() => { + beforeEach(function () { adUnits = [{ code: ADUNIT_CODE, bids: [ @@ -578,7 +578,7 @@ describe('auctionmanager.js', function () { registerBidder(spec); }); - afterEach(() => { + afterEach(function () { auctionModule.newAuction.restore(); loadScriptStub.restore(); }); @@ -605,7 +605,7 @@ describe('auctionmanager.js', function () { it('should return proper price bucket increments for dense mode when cpm is 20+', checkPbDg('73.07', '20.00', '20+ caps at 20.00')); - it('should place dealIds in adserver targeting', () => { + it('should place dealIds in adserver targeting', function () { bids[0].dealId = 'test deal'; auction.callBids(); @@ -613,7 +613,7 @@ describe('auctionmanager.js', function () { assert.equal(registeredBid.adserverTargeting[`hb_deal`], 'test deal', 'dealId placed in adserverTargeting'); }); - it('should pass through default adserverTargeting sent from adapter', () => { + it('should pass through default adserverTargeting sent from adapter', function () { bids[0].adserverTargeting = {}; bids[0].adserverTargeting.extra = 'stuff'; auction.callBids(); @@ -623,7 +623,7 @@ describe('auctionmanager.js', function () { assert.equal(registeredBid.adserverTargeting.extra, 'stuff'); }); - it('installs publisher-defined renderers on bids', () => { + it('installs publisher-defined renderers on bids', function () { let renderer = { url: 'renderer.js', render: (bid) => bid @@ -675,19 +675,19 @@ describe('auctionmanager.js', function () { }); }); - describe('when auction timeout is 20', () => { + describe('when auction timeout is 20', function () { let loadScriptStub; let eventsEmitSpy; let getBidderRequestStub; - before(() => { + before(function () { bids = [mockBid(), mockBid({ bidderCode: BIDDER_CODE1 })]; let bidRequests = bids.map(bid => mockBidRequest(bid)); makeRequestsStub.returns(bidRequests); }); - beforeEach(() => { + beforeEach(function () { adUnits = [{ code: ADUNIT_CODE, bids: [ @@ -723,20 +723,20 @@ describe('auctionmanager.js', function () { return req; }); }); - afterEach(() => { + afterEach(function () { auctionModule.newAuction.restore(); loadScriptStub.restore(); events.emit.restore(); getBidderRequestStub.restore(); }); - it('should emit BID_TIMEOUT for timed out bids', () => { + it('should emit BID_TIMEOUT for timed out bids', function () { auction.callBids(); assert.ok(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BID_TIMEOUT), 'emitted events BID_TIMEOUT'); }); }); }); - describe('addBidResponse', () => { + describe('addBidResponse', function () { let createAuctionStub; let adUnits; let adUnitCodes; @@ -748,7 +748,7 @@ describe('auctionmanager.js', function () { let bids = TEST_BIDS; let bids1 = [mockBid({ bidderCode: BIDDER_CODE1 })]; - before(() => { + before(function () { let bidRequests = [ mockBidRequest(bids[0]), mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 }) @@ -759,12 +759,12 @@ describe('auctionmanager.js', function () { ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder); }); - after(() => { + after(function () { ajaxStub.restore(); adaptermanager.makeBidRequests.restore(); }); - beforeEach(() => { + beforeEach(function () { adUnits = [{ code: ADUNIT_CODE, bids: [ @@ -788,11 +788,11 @@ describe('auctionmanager.js', function () { registerBidder(spec1); }); - afterEach(() => { + afterEach(function () { auctionModule.newAuction.restore(); }); - it('should not alter bid adID', () => { + it('should not alter bid adID', function () { auction.callBids(); const addedBid2 = auction.getBidsReceived().pop(); @@ -801,7 +801,7 @@ describe('auctionmanager.js', function () { assert.equal(addedBid1.adId, bids[0].requestId); }); - it('should not add banner bids that have no width or height', () => { + it('should not add banner bids that have no width or height', function () { bids1[0].width = undefined; bids1[0].height = undefined; @@ -813,7 +813,7 @@ describe('auctionmanager.js', function () { assert.equal(length, 1); }); - it('should run auction after video bids have been cached', () => { + it('should run auction after video bids have been cached', function () { sinon.stub(store, 'store').callsArgWith(1, null, [{ uuid: 123 }]); sinon.stub(config, 'getConfig').withArgs('cache.url').returns('cache-url'); @@ -832,7 +832,7 @@ describe('auctionmanager.js', function () { store.store.restore(); }); - it('runs auction after video responses with multiple bid objects have been cached', () => { + it('runs auction after video responses with multiple bid objects have been cached', function () { sinon.stub(store, 'store').callsArgWith(1, null, [{ uuid: 123 }]); sinon.stub(config, 'getConfig').withArgs('cache.url').returns('cache-url'); diff --git a/test/spec/config_spec.js b/test/spec/config_spec.js index 6b26d7da76a..196e167420a 100644 --- a/test/spec/config_spec.js +++ b/test/spec/config_spec.js @@ -8,10 +8,10 @@ let getConfig; let setConfig; let setDefaults; -describe('config API', () => { +describe('config API', function () { let logErrorSpy; let logWarnSpy; - beforeEach(() => { + beforeEach(function () { const config = newConfig(); getConfig = config.getConfig; setConfig = config.setConfig; @@ -20,30 +20,30 @@ describe('config API', () => { logWarnSpy = sinon.spy(utils, 'logWarn'); }); - afterEach(() => { + afterEach(function () { utils.logError.restore(); utils.logWarn.restore(); }); - it('setConfig is a function', () => { + it('setConfig is a function', function () { expect(setConfig).to.be.a('function'); }); - it('getConfig returns an object', () => { + it('getConfig returns an object', function () { expect(getConfig()).to.be.a('object'); }); - it('sets and gets arbitrary configuarion properties', () => { + it('sets and gets arbitrary configuarion properties', function () { setConfig({ baz: 'qux' }); expect(getConfig('baz')).to.equal('qux'); }); - it('only accepts objects', () => { + it('only accepts objects', function () { setConfig('invalid'); expect(getConfig('0')).to.not.equal('i'); }); - it('sets multiple config properties', () => { + it('sets multiple config properties', function () { setConfig({ foo: 'bar' }); setConfig({ biz: 'buz' }); var config = getConfig(); @@ -51,28 +51,28 @@ describe('config API', () => { expect(config.biz).to.equal('buz'); }); - it('overwrites existing config properties', () => { + it('overwrites existing config properties', function () { setConfig({ foo: {biz: 'buz'} }); setConfig({ foo: {baz: 'qux'} }); expect(getConfig('foo')).to.eql({baz: 'qux'}); }); - it('sets debugging', () => { + it('sets debugging', function () { setConfig({ debug: true }); expect(getConfig('debug')).to.be.true; }); - it('sets bidderTimeout', () => { + it('sets bidderTimeout', function () { setConfig({ bidderTimeout: 1000 }); expect(getConfig('bidderTimeout')).to.be.equal(1000); }); - it('gets user-defined publisherDomain', () => { + it('gets user-defined publisherDomain', function () { setConfig({ publisherDomain: 'fc.kahuna' }); expect(getConfig('publisherDomain')).to.equal('fc.kahuna'); }); - it('gets default userSync config', () => { + it('gets default userSync config', function () { const DEFAULT_USERSYNC = { syncEnabled: true, pixelEnabled: true, @@ -83,7 +83,7 @@ describe('config API', () => { expect(getConfig('userSync')).to.eql(DEFAULT_USERSYNC); }); - it('has subscribe functionality for adding listeners to config updates', () => { + it('has subscribe functionality for adding listeners to config updates', function () { const listener = sinon.spy(); getConfig(listener); @@ -94,7 +94,7 @@ describe('config API', () => { sinon.assert.calledWith(listener, { foo: 'bar' }); }); - it('subscribers can unsubscribe', () => { + it('subscribers can unsubscribe', function () { const listener = sinon.spy(); const unsubscribe = getConfig(listener); @@ -106,7 +106,7 @@ describe('config API', () => { sinon.assert.notCalled(listener); }); - it('subscribers can subscribe to topics', () => { + it('subscribers can subscribe to topics', function () { const listener = sinon.spy(); getConfig('logging', listener); @@ -117,7 +117,7 @@ describe('config API', () => { sinon.assert.calledWithExactly(listener, { logging: true }); }); - it('topic subscribers are only called when that topic is changed', () => { + it('topic subscribers are only called when that topic is changed', function () { const listener = sinon.spy(); const wildcard = sinon.spy(); @@ -130,12 +130,12 @@ describe('config API', () => { sinon.assert.calledOnce(wildcard); }); - it('sets priceGranularity', () => { + it('sets priceGranularity', function () { setConfig({ priceGranularity: 'low' }); expect(getConfig('priceGranularity')).to.be.equal('low'); }); - it('set mediaTypePriceGranularity', () => { + it('set mediaTypePriceGranularity', function () { const customPriceGranularity = { 'buckets': [{ 'min': 0, @@ -158,7 +158,7 @@ describe('config API', () => { expect(configResult.native).to.be.equal('medium'); }); - it('sets priceGranularity and customPriceBucket', () => { + it('sets priceGranularity and customPriceBucket', function () { const goodConfig = { 'buckets': [{ 'min': 0, @@ -172,18 +172,18 @@ describe('config API', () => { expect(getConfig('customPriceBucket')).to.equal(goodConfig); }); - it('should log error for invalid priceGranularity', () => { + it('should log error for invalid priceGranularity', function () { setConfig({ priceGranularity: '' }); const error = 'Prebid Error: no value passed to `setPriceGranularity()`'; assert.ok(logErrorSpy.calledWith(error), 'expected error was logged'); }); - it('should log a warning on invalid values', () => { + it('should log a warning on invalid values', function () { setConfig({ bidderSequence: 'unrecognized sequence' }); expect(logWarnSpy.calledOnce).to.equal(true); }); - it('should not log warnings when given recognized values', () => { + it('should not log warnings when given recognized values', function () { setConfig({ bidderSequence: 'fixed' }); setConfig({ bidderSequence: 'random' }); expect(logWarnSpy.called).to.equal(false); diff --git a/test/spec/cpmBucketManager_spec.js b/test/spec/cpmBucketManager_spec.js index 55fae3bb869..88e04be9ad6 100644 --- a/test/spec/cpmBucketManager_spec.js +++ b/test/spec/cpmBucketManager_spec.js @@ -2,8 +2,8 @@ import { expect } from 'chai'; import {getPriceBucketString, isValidPriceConfig} from 'src/cpmBucketManager'; let cpmFixtures = require('test/fixtures/cpmInputsOutputs.json'); -describe('cpmBucketManager', () => { - it('getPriceBucketString function generates the correct price strings', () => { +describe('cpmBucketManager', function () { + it('getPriceBucketString function generates the correct price strings', function () { let input = cpmFixtures.cpmInputs; for (let i = 0; i < input.length; i++) { let output = getPriceBucketString(input[i]); @@ -12,7 +12,7 @@ describe('cpmBucketManager', () => { } }); - it('gets the correct custom bucket strings', () => { + it('gets the correct custom bucket strings', function () { let cpm = 16.50908; let customConfig = { 'buckets': [{ @@ -35,7 +35,7 @@ describe('cpmBucketManager', () => { expect(JSON.stringify(output)).to.deep.equal(expected); }); - it('gets the correct custom bucket strings with irregular increment', () => { + it('gets the correct custom bucket strings with irregular increment', function () { let cpm = 14.50908; let customConfig = { 'buckets': [{ @@ -58,7 +58,7 @@ describe('cpmBucketManager', () => { expect(JSON.stringify(output)).to.deep.equal(expected); }); - it('gets the correct custom bucket strings in non-USD currency', () => { + it('gets the correct custom bucket strings in non-USD currency', function () { let cpm = 16.50908 * 110.49; let customConfig = { 'buckets': [{ @@ -81,7 +81,7 @@ describe('cpmBucketManager', () => { expect(JSON.stringify(output)).to.deep.equal(expected); }); - it('gets the correct custom bucket strings with specific cpms that round oddly with certain increments', () => { + it('gets the correct custom bucket strings with specific cpms that round oddly with certain increments', function () { let customConfig = { 'buckets': [{ 'precision': 4, @@ -155,7 +155,7 @@ describe('cpmBucketManager', () => { expect(JSON.stringify(output)).to.deep.equal(expected); }); - it('gets custom bucket strings and it should honor 0', () => { + it('gets custom bucket strings and it should honor 0', function () { let cpm = 16.50908; let customConfig = { 'buckets': [ @@ -172,7 +172,7 @@ describe('cpmBucketManager', () => { expect(JSON.stringify(output)).to.deep.equal(expected); }); - it('gets the custom bucket strings without passing precision and it should honor the default precision', () => { + it('gets the custom bucket strings without passing precision and it should honor the default precision', function () { let cpm = 16.50908; let customConfig = { 'buckets': [ @@ -188,7 +188,7 @@ describe('cpmBucketManager', () => { expect(JSON.stringify(output)).to.deep.equal(expected); }); - it('checks whether custom config is valid', () => { + it('checks whether custom config is valid', function () { let badConfig = { 'buckets': [{ 'min': 0, diff --git a/test/spec/debugging_spec.js b/test/spec/debugging_spec.js index 286df26f7ba..b048382171b 100644 --- a/test/spec/debugging_spec.js +++ b/test/spec/debugging_spec.js @@ -4,28 +4,28 @@ import { sessionLoader, addBidResponseHook, getConfig, disableOverrides, boundHo import { addBidResponse } from 'src/auction'; import { config } from 'src/config'; -describe('bid overrides', () => { +describe('bid overrides', function () { let sandbox; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); }); - afterEach(() => { + afterEach(function () { window.sessionStorage.clear(); sandbox.restore(); }); - describe('initialization', () => { - beforeEach(() => { + describe('initialization', function () { + beforeEach(function () { sandbox.stub(config, 'setConfig'); }); - afterEach(() => { + afterEach(function () { disableOverrides(); }); - it('should happen when enabled with setConfig', () => { + it('should happen when enabled with setConfig', function () { getConfig({ enabled: true }); @@ -33,14 +33,14 @@ describe('bid overrides', () => { expect(addBidResponse.hasHook(boundHook)).to.equal(true); }); - it('should happen when configuration found in sessionStorage', () => { + it('should happen when configuration found in sessionStorage', function () { sessionLoader({ getItem: () => ('{"enabled": true}') }); expect(addBidResponse.hasHook(boundHook)).to.equal(true); }); - it('should not throw if sessionStorage is inaccessible', () => { + it('should not throw if sessionStorage is inaccessible', function () { expect(() => { sessionLoader({ getItem() { @@ -51,11 +51,11 @@ describe('bid overrides', () => { }); }); - describe('hook', () => { + describe('hook', function () { let mockBids; let bids; - beforeEach(() => { + beforeEach(function () { let baseBid = { 'bidderCode': 'rubicon', 'width': 970, @@ -86,7 +86,7 @@ describe('bid overrides', () => { }); } - it('should allow us to exclude bidders', () => { + it('should allow us to exclude bidders', function () { run({ enabled: true, bidders: ['appnexus'] @@ -96,7 +96,7 @@ describe('bid overrides', () => { expect(bids[0].bidderCode).to.equal('appnexus'); }); - it('should allow us to override all bids', () => { + it('should allow us to override all bids', function () { run({ enabled: true, bids: [{ @@ -109,7 +109,7 @@ describe('bid overrides', () => { expect(bids[1].cpm).to.equal(2); }); - it('should allow us to override bids by bidder', () => { + it('should allow us to override bids by bidder', function () { run({ enabled: true, bids: [{ @@ -123,7 +123,7 @@ describe('bid overrides', () => { expect(bids[1].cpm).to.equal(0.5); }); - it('should allow us to override bids by adUnitCode', () => { + it('should allow us to override bids by adUnitCode', function () { mockBids[1].adUnitCode = 'test'; run({ diff --git a/test/spec/hook_spec.js b/test/spec/hook_spec.js index 1fab4ecd1b7..7536f8316d5 100644 --- a/test/spec/hook_spec.js +++ b/test/spec/hook_spec.js @@ -2,18 +2,18 @@ import { expect } from 'chai'; import { createHook, hooks } from 'src/hook'; -describe('the hook module', () => { +describe('the hook module', function () { let sandbox; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); }); - afterEach(() => { + afterEach(function () { sandbox.restore(); }); - it('should call all sync hooks attached to a function', () => { + it('should call all sync hooks attached to a function', function () { let called = []; let calledWith; @@ -63,7 +63,7 @@ describe('the hook module', () => { ]); }); - it('should allow context to be passed to hooks, but keep bound contexts', () => { + it('should allow context to be passed to hooks, but keep bound contexts', function () { let context; let fn = function() { context = this; @@ -85,8 +85,8 @@ describe('the hook module', () => { expect(calledBoundContext).to.equal(boundContext); }); - describe('asyncSeries', () => { - it('should call function as normal if no hooks attached', () => { + describe('asyncSeries', function () { + it('should call function as normal if no hooks attached', function () { let fn = sandbox.spy(); let hookFn = createHook('asyncSeries', fn); @@ -96,7 +96,7 @@ describe('the hook module', () => { expect(fn.firstCall.args[0]).to.equal(1); }); - it('should call hooks correctly applied in asyncSeries', () => { + it('should call hooks correctly applied in asyncSeries', function () { let called = []; let testFn = (called) => { @@ -124,7 +124,7 @@ describe('the hook module', () => { ]); }); - it('should allow context to be passed to hooks, but keep bound contexts', () => { + it('should allow context to be passed to hooks, but keep bound contexts', function () { let context; let fn = function() { context = this; diff --git a/test/spec/modules/a4gBidAdapter_spec.js b/test/spec/modules/a4gBidAdapter_spec.js index 84346a1149f..4c7520d3b0c 100644 --- a/test/spec/modules/a4gBidAdapter_spec.js +++ b/test/spec/modules/a4gBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/a4gBidAdapter'; -describe('a4gAdapterTests', () => { - describe('bidRequestValidity', () => { - it('bidRequest with zoneId and deliveryUrl params', () => { +describe('a4gAdapterTests', function () { + describe('bidRequestValidity', function () { + it('bidRequest with zoneId and deliveryUrl params', function () { expect(spec.isBidRequestValid({ bidder: 'a4g', params: { @@ -13,7 +13,7 @@ describe('a4gAdapterTests', () => { })).to.equal(true); }); - it('bidRequest with only zoneId', () => { + it('bidRequest with only zoneId', function () { expect(spec.isBidRequestValid({ bidder: 'a4g', params: { @@ -22,7 +22,7 @@ describe('a4gAdapterTests', () => { })).to.equal(true); }); - it('bidRequest with only deliveryUrl', () => { + it('bidRequest with only deliveryUrl', function () { expect(spec.isBidRequestValid({ bidder: 'a4g', params: { @@ -32,7 +32,7 @@ describe('a4gAdapterTests', () => { }); }); - describe('bidRequest', () => { + describe('bidRequest', function () { const bidRequests = [{ 'bidder': 'a4g', 'bidId': '51ef8751f9aead', @@ -58,27 +58,27 @@ describe('a4gAdapterTests', () => { 'auctionId': '18fd8b8b0bd757' }]; - it('bidRequest method', () => { + it('bidRequest method', function () { const request = spec.buildRequests(bidRequests); expect(request.method).to.equal('GET'); }); - it('bidRequest url', () => { + it('bidRequest url', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.match(new RegExp(`${bidRequests[1].params.deliveryUrl}`)); }); - it('bidRequest data', () => { + it('bidRequest data', function () { const request = spec.buildRequests(bidRequests); expect(request.data).to.exists; }); - it('bidRequest zoneIds', () => { + it('bidRequest zoneIds', function () { const request = spec.buildRequests(bidRequests); expect(request.data.zoneId).to.equal('59304;59354'); }); - it('bidRequest gdpr consent', () => { + it('bidRequest gdpr consent', function () { const consentString = 'consentString'; const bidderRequest = { bidderCode: 'a4g', @@ -99,7 +99,7 @@ describe('a4gAdapterTests', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequest = [{ 'bidder': 'a4g', 'bidId': '51ef8751f9aead', @@ -124,7 +124,7 @@ describe('a4gAdapterTests', () => { headers: {} }; - it('required keys', () => { + it('required keys', function () { const result = spec.interpretResponse(bidResponse, bidRequest); let requiredKeys = [ diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js index 6d4649ea107..628f19f8fd2 100644 --- a/test/spec/modules/aardvarkBidAdapter_spec.js +++ b/test/spec/modules/aardvarkBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/aardvarkBidAdapter'; -describe('aardvarkAdapterTest', () => { - describe('forming valid bidRequests', () => { - it('should accept valid bidRequests', () => { +describe('aardvarkAdapterTest', function () { + describe('forming valid bidRequests', function () { + it('should accept valid bidRequests', function () { expect(spec.isBidRequestValid({ bidder: 'aardvark', params: { @@ -14,7 +14,7 @@ describe('aardvarkAdapterTest', () => { })).to.equal(true); }); - it('should reject invalid bidRequests', () => { + it('should reject invalid bidRequests', function () { expect(spec.isBidRequestValid({ bidder: 'aardvark', params: { @@ -25,7 +25,7 @@ describe('aardvarkAdapterTest', () => { }); }); - describe('executing network requests', () => { + describe('executing network requests', function () { const bidRequests = [{ bidder: 'aardvark', params: { @@ -54,20 +54,20 @@ describe('aardvarkAdapterTest', () => { auctionId: 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' }]; - it('should use HTTP GET method', () => { + it('should use HTTP GET method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); - it('should call the correct bidRequest url', () => { + it('should call the correct bidRequest url', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(1); expect(requests[0].url).to.match(new RegExp('^\/\/adzone.pub.com/xiby/TdAx_RAZd/aardvark\?')); }); - it('should have correct data', () => { + it('should have correct data', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(1); expect(requests[0].data.version).to.equal(1); @@ -78,7 +78,7 @@ describe('aardvarkAdapterTest', () => { }); }); - describe('splitting multi-auction ad units into own requests', () => { + describe('splitting multi-auction ad units into own requests', function () { const bidRequests = [{ bidder: 'aardvark', params: { @@ -108,21 +108,21 @@ describe('aardvarkAdapterTest', () => { auctionId: 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' }]; - it('should use HTTP GET method', () => { + it('should use HTTP GET method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); - it('should call the correct bidRequest urls for each auction', () => { + it('should call the correct bidRequest urls for each auction', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].url).to.match(new RegExp('^\/\/bidder.rtk.io/Toby/TdAx/aardvark\?')); expect(requests[0].data.categories.length).to.equal(2); expect(requests[1].url).to.match(new RegExp('^\/\/adzone.pub.com/xiby/RAZd/aardvark\?')); }); - it('should have correct data', () => { + it('should have correct data', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(2); expect(requests[0].data.version).to.equal(1); @@ -138,7 +138,7 @@ describe('aardvarkAdapterTest', () => { }); }); - describe('GDPR conformity', () => { + describe('GDPR conformity', function () { const bidRequests = [{ bidder: 'aardvark', params: { @@ -160,7 +160,7 @@ describe('aardvarkAdapterTest', () => { } }; - it('should transmit correct data', () => { + it('should transmit correct data', function () { const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests.length).to.equal(1); expect(requests[0].data.gdpr).to.equal(true); @@ -168,7 +168,7 @@ describe('aardvarkAdapterTest', () => { }); }); - describe('GDPR absence conformity', () => { + describe('GDPR absence conformity', function () { const bidRequests = [{ bidder: 'aardvark', params: { @@ -187,7 +187,7 @@ describe('aardvarkAdapterTest', () => { gdprConsent: undefined }; - it('should transmit correct data', () => { + it('should transmit correct data', function () { const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests.length).to.equal(1); expect(requests[0].data.gdpr).to.be.undefined; @@ -195,8 +195,8 @@ describe('aardvarkAdapterTest', () => { }); }); - describe('interpretResponse', () => { - it('should handle bid responses', () => { + describe('interpretResponse', function () { + it('should handle bid responses', function () { const serverResponse = { body: [ { @@ -245,7 +245,7 @@ describe('aardvarkAdapterTest', () => { expect(result[1].ad).to.not.be.undefined; }); - it('should handle nobid responses', () => { + it('should handle nobid responses', function () { var emptyResponse = [{ nurl: '', cid: '9e5a09319e18f1', diff --git a/test/spec/modules/adbutlerBidAdapter_spec.js b/test/spec/modules/adbutlerBidAdapter_spec.js index a46039402e6..cf6b52f70e5 100644 --- a/test/spec/modules/adbutlerBidAdapter_spec.js +++ b/test/spec/modules/adbutlerBidAdapter_spec.js @@ -1,10 +1,10 @@ import {expect} from 'chai'; import {spec} from 'modules/adbutlerBidAdapter'; -describe('AdButler adapter', () => { +describe('AdButler adapter', function () { let bidRequests; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'adbutler', @@ -25,9 +25,9 @@ describe('AdButler adapter', () => { ]; }); - describe('implementation', () => { - describe('for requests', () => { - it('should accept valid bid', () => { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { let validBid = { bidder: 'adbutler', params: { @@ -40,7 +40,7 @@ describe('AdButler adapter', () => { expect(isValid).to.equal(true); }); - it('should reject invalid bid', () => { + it('should reject invalid bid', function () { let invalidBid = { bidder: 'adbutler', params: { @@ -52,7 +52,7 @@ describe('AdButler adapter', () => { expect(isValid).to.equal(false); }); - it('should use custom domain string', () => { + it('should use custom domain string', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -73,7 +73,7 @@ describe('AdButler adapter', () => { expect(requestURL).to.have.string('.dan.test'); }); - it('should set default domain', () => { + it('should set default domain', function () { let requests = spec.buildRequests(bidRequests), request = requests[0]; @@ -82,14 +82,14 @@ describe('AdButler adapter', () => { expect(domain).to.equal('http://servedbyadbutler.com'); }); - it('should set the keyword parameter', () => { + it('should set the keyword parameter', function () { let requests = spec.buildRequests(bidRequests), requestURL = requests[0].url; expect(requestURL).to.have.string(';kw=red;'); }); - it('should increment the count for the same zone', () => { + it('should increment the count for the same zone', function () { let bidRequests = [ { sizes: [[300, 250]], @@ -118,8 +118,8 @@ describe('AdButler adapter', () => { }); }); - describe('bid responses', () => { - it('should return complete bid response', () => { + describe('bid responses', function () { + it('should return complete bid response', function () { let serverResponse = { body: { status: 'SUCCESS', @@ -149,7 +149,7 @@ describe('AdButler adapter', () => { expect(bids[0].ad).to.have.string('http://tracking.pixel.com/params=info'); }); - it('should return empty bid response', () => { + it('should return empty bid response', function () { let serverResponse = { status: 'NO_ELIGIBLE_ADS', zone_id: 210083, @@ -162,7 +162,7 @@ describe('AdButler adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on incorrect size', () => { + it('should return empty bid response on incorrect size', function () { let serverResponse = { status: 'SUCCESS', account_id: 167283, @@ -177,7 +177,7 @@ describe('AdButler adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with CPM too low', () => { + it('should return empty bid response with CPM too low', function () { let serverResponse = { status: 'SUCCESS', account_id: 167283, @@ -192,7 +192,7 @@ describe('AdButler adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with CPM too high', () => { + it('should return empty bid response with CPM too high', function () { let serverResponse = { status: 'SUCCESS', account_id: 167283, diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index d888b4b7a5b..d3054794485 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -3,10 +3,10 @@ import * as url from 'src/url'; import {spec} from 'modules/adformBidAdapter'; import { BANNER, VIDEO } from 'src/mediaTypes'; -describe('Adform adapter', () => { +describe('Adform adapter', function () { let serverResponse, bidRequest, bidResponses; let bids = []; - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'adform', 'params': { @@ -14,11 +14,11 @@ describe('Adform adapter', () => { } }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { assert(spec.isBidRequestValid(bid)); }); - it('should return false when required params are missing', () => { + it('should return false when required params are missing', function () { bid.params = { adxDomain: 'adx.adform.net' }; @@ -26,14 +26,14 @@ describe('Adform adapter', () => { }); }); - describe('buildRequests', () => { - it('should pass multiple bids via single request', () => { + describe('buildRequests', function () { + it('should pass multiple bids via single request', function () { let request = spec.buildRequests(bids); let parsedUrl = parseUrl(request.url); assert.lengthOf(parsedUrl.items, 7); }); - it('should handle global request parameters', () => { + it('should handle global request parameters', function () { let parsedUrl = parseUrl(spec.buildRequests([bids[0]]).url); let query = parsedUrl.query; @@ -45,12 +45,12 @@ describe('Adform adapter', () => { assert.equal(query.url, encodeURIComponent('some// there')); }); - it('should set correct request method', () => { + it('should set correct request method', function () { let request = spec.buildRequests([bids[0]]); assert.equal(request.method, 'GET'); }); - it('should correctly form bid items', () => { + it('should correctly form bid items', function () { let bidList = bids; let request = spec.buildRequests(bidList); let parsedUrl = parseUrl(request.url); @@ -93,13 +93,13 @@ describe('Adform adapter', () => { ]); }); - it('should not change original validBidRequests object', () => { + it('should not change original validBidRequests object', function () { var resultBids = JSON.parse(JSON.stringify(bids[0])); let request = spec.buildRequests([bids[0]]); assert.deepEqual(resultBids, bids[0]); }); - it('should set gross to the request, if there is any gross priceType', () => { + it('should set gross to the request, if there is any gross priceType', function () { let request = spec.buildRequests([bids[5], bids[5]]); let parsedUrl = parseUrl(request.url); @@ -111,8 +111,8 @@ describe('Adform adapter', () => { assert.equal(parsedUrl.query.pt, 'gross'); }); - describe('gdpr', () => { - it('should send GDPR Consent data to adform if gdprApplies', () => { + describe('gdpr', function () { + it('should send GDPR Consent data to adform if gdprApplies', function () { let resultBids = JSON.parse(JSON.stringify(bids[0])); let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); let parsedUrl = parseUrl(request.url).query; @@ -121,7 +121,7 @@ describe('Adform adapter', () => { assert.equal(parsedUrl.gdpr_consent, 'concentDataString'); }); - it('should not send GDPR Consent data to adform if gdprApplies is false or undefined', () => { + it('should not send GDPR Consent data to adform if gdprApplies is false or undefined', function () { let resultBids = JSON.parse(JSON.stringify(bids[0])); let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: false, consentString: 'concentDataString'}}); let parsedUrl = parseUrl(request.url).query; @@ -134,7 +134,7 @@ describe('Adform adapter', () => { assert.ok(!parsedUrl.gdpr_consent); }); - it('should return GDPR Consent data with request data', () => { + it('should return GDPR Consent data with request data', function () { let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); assert.deepEqual(request.gdpr, { @@ -148,12 +148,12 @@ describe('Adform adapter', () => { }); }); - describe('interpretResponse', () => { - it('should respond with empty response when there is empty serverResponse', () => { + describe('interpretResponse', function () { + it('should respond with empty response when there is empty serverResponse', function () { let result = spec.interpretResponse({ body: {} }, {}); assert.deepEqual(result, []); }); - it('should respond with empty response when response from server is not banner', () => { + it('should respond with empty response when response from server is not banner', function () { serverResponse.body[0].response = 'not banner'; serverResponse.body = [serverResponse.body[0]]; bidRequest.bids = [bidRequest.bids[0]]; @@ -161,7 +161,7 @@ describe('Adform adapter', () => { assert.deepEqual(result, []); }); - it('should interpret server response correctly with one bid', () => { + it('should interpret server response correctly with one bid', function () { serverResponse.body = [serverResponse.body[0]]; bidRequest.bids = [bidRequest.bids[0]]; let result = spec.interpretResponse(serverResponse, bidRequest)[0]; @@ -180,7 +180,7 @@ describe('Adform adapter', () => { assert.equal(result.transactionId, '5f33781f-9552-4ca1'); }); - it('should set correct netRevenue', () => { + it('should set correct netRevenue', function () { serverResponse.body = [serverResponse.body[0]]; bidRequest.bids = [bidRequest.bids[1]]; bidRequest.netRevenue = 'gross'; @@ -189,22 +189,22 @@ describe('Adform adapter', () => { assert.equal(result.netRevenue, false); }); - it('should create bid response item for every requested item', () => { + it('should create bid response item for every requested item', function () { let result = spec.interpretResponse(serverResponse, bidRequest); assert.lengthOf(result, 5); }); - it('should create bid response with vast xml', () => { + it('should create bid response with vast xml', function () { const result = spec.interpretResponse(serverResponse, bidRequest)[3]; assert.equal(result.vastXml, ''); }); - it('should create bid response with vast url', () => { + it('should create bid response with vast url', function () { const result = spec.interpretResponse(serverResponse, bidRequest)[4]; assert.equal(result.vastUrl, 'vast://url'); }); - it('should set mediaType on bid response', () => { + it('should set mediaType on bid response', function () { const expected = [ BANNER, BANNER, BANNER, VIDEO, VIDEO ]; const result = spec.interpretResponse(serverResponse, bidRequest); for (let i = 0; i < result.length; i++) { @@ -212,7 +212,7 @@ describe('Adform adapter', () => { } }); - it('should set default netRevenue as gross', () => { + it('should set default netRevenue as gross', function () { bidRequest.netRevenue = 'gross'; const result = spec.interpretResponse(serverResponse, bidRequest); for (let i = 0; i < result.length; i++) { @@ -220,7 +220,7 @@ describe('Adform adapter', () => { } }); - it('should set gdpr if it exist in bidRequest', () => { + it('should set gdpr if it exist in bidRequest', function () { bidRequest.gdpr = { gdpr: true, gdpr_consent: 'ERW342EIOWT34234KMGds' @@ -239,8 +239,8 @@ describe('Adform adapter', () => { }; }); - describe('verifySizes', () => { - it('should respond with empty response when sizes doesn\'t match', () => { + describe('verifySizes', function () { + it('should respond with empty response when sizes doesn\'t match', function () { serverResponse.body[0].response = 'banner'; serverResponse.body[0].width = 100; serverResponse.body[0].height = 150; @@ -253,7 +253,7 @@ describe('Adform adapter', () => { assert.equal(serverResponse.body[0].response, 'banner'); assert.deepEqual(result, []); }); - it('should respond with empty response when sizes as a strings doesn\'t match', () => { + it('should respond with empty response when sizes as a strings doesn\'t match', function () { serverResponse.body[0].response = 'banner'; serverResponse.body[0].width = 100; serverResponse.body[0].height = 150; @@ -268,7 +268,7 @@ describe('Adform adapter', () => { assert.equal(serverResponse.body[0].response, 'banner'); assert.deepEqual(result, []); }); - it('should support size dimensions as a strings', () => { + it('should support size dimensions as a strings', function () { serverResponse.body[0].response = 'banner'; serverResponse.body[0].width = 300; serverResponse.body[0].height = 600; @@ -285,7 +285,7 @@ describe('Adform adapter', () => { }) }); - beforeEach(() => { + beforeEach(function () { let sizes = [[250, 300], [300, 250], [300, 600]]; let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; let params = [{ mid: 1, url: 'some// there' }, {adxDomain: null, mid: 2, someVar: 'someValue', pt: 'gross'}, { adxDomain: null, mid: 3, pdom: 'home' }, {mid: 5, pt: 'net'}, {mid: 6, pt: 'gross'}]; diff --git a/test/spec/modules/adgenerationBidAdapter_spec.js b/test/spec/modules/adgenerationBidAdapter_spec.js index 4239712ccaf..558303ccecb 100644 --- a/test/spec/modules/adgenerationBidAdapter_spec.js +++ b/test/spec/modules/adgenerationBidAdapter_spec.js @@ -4,28 +4,28 @@ import {spec} from 'modules/adgenerationBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import {NATIVE} from 'src/mediaTypes'; -describe('AdgenerationAdapter', () => { +describe('AdgenerationAdapter', function () { const adapter = newBidder(spec); const ENDPOINT = ['http://api-test.scaleout.jp/adsv/v1', 'https://d.socdm.com/adsv/v1']; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'adg', 'params': { id: '58278', // banner } }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = {}; @@ -33,7 +33,7 @@ describe('AdgenerationAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [ { // banner bidder: 'adg', @@ -91,31 +91,31 @@ describe('AdgenerationAdapter', () => { banner: 'posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&imark=1', native: 'posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3' }; - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(ENDPOINT[1]); expect(request.method).to.equal('GET'); }); - it('sends bid request to debug ENDPOINT via GET', () => { + it('sends bid request to debug ENDPOINT via GET', function () { bidRequests[0].params.debug = true; const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(ENDPOINT[0]); expect(request.method).to.equal('GET'); }); - it('should attache params to the banner request', () => { + it('should attache params to the banner request', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.data).to.equal(data.banner); }); - it('should attache params to the native request', () => { + it('should attache params to the native request', function () { const request = spec.buildRequests(bidRequests)[1]; expect(request.data).to.equal(data.native); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequests = { banner: { bidRequest: { @@ -336,12 +336,12 @@ describe('AdgenerationAdapter', () => { } }; - it('no bid responses', () => { + it('no bid responses', function () { const result = spec.interpretResponse({body: serverResponse.noAd}, bidRequests.banner); expect(result.length).to.equal(0); }); - it('handles banner responses', () => { + it('handles banner responses', function () { const result = spec.interpretResponse({body: serverResponse.banner}, bidRequests.banner)[0]; expect(result.requestId).to.equal(bidResponses.banner.requestId); expect(result.width).to.equal(bidResponses.banner.width); @@ -355,7 +355,7 @@ describe('AdgenerationAdapter', () => { expect(result.ad).to.equal(bidResponses.banner.ad); }); - it('handles native responses', () => { + it('handles native responses', function () { const result = spec.interpretResponse({body: serverResponse.native}, bidRequests.native)[0]; expect(result.requestId).to.equal(bidResponses.native.requestId); expect(result.width).to.equal(bidResponses.native.width); diff --git a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js index f5d1a5d02f1..1291a375fc0 100644 --- a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js +++ b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js @@ -33,81 +33,81 @@ const CAMPAIGN = { c5: '5' }; -describe('', () => { +describe('', function () { let sandbox; - before(() => { + before(function () { sandbox = sinon.sandbox.create(); }); - after(() => { + after(function () { sandbox.restore(); analyticsAdapter.disableAnalytics(); }); - describe('UTM source parser', () => { + describe('UTM source parser', function () { let stubSetItem; let stubGetItem; - before(() => { + before(function () { stubSetItem = sandbox.stub(storage, 'setItem'); stubGetItem = sandbox.stub(storage, 'getItem'); }); - afterEach(() => { + afterEach(function () { sandbox.reset(); }); - it('should parse first direct visit as (direct)', () => { + it('should parse first direct visit as (direct)', function () { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com'); expect(source).to.be.eql(DIRECT); }); - it('should respect past campaign visits before direct', () => { + it('should respect past campaign visits before direct', function () { stubGetItem.withArgs('adk_dpt_analytics').returns(JSON.stringify(CAMPAIGN)); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com'); expect(source).to.be.eql(CAMPAIGN); }); - it('should parse visit from google as organic', () => { + it('should parse visit from google as organic', function () { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com', 'https://www.google.com/search?q=pikachu'); expect(source).to.be.eql(GOOGLE_ORGANIC); }); - it('should respect previous campaign visit before organic', () => { + it('should respect previous campaign visit before organic', function () { stubGetItem.withArgs('adk_dpt_analytics').returns(JSON.stringify(CAMPAIGN)); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com', 'https://www.google.com/search?q=pikachu'); expect(source).to.be.eql(CAMPAIGN); }); - it('should parse referral visit', () => { + it('should parse referral visit', function () { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com', 'http://lander.com/lander.html'); expect(source).to.be.eql(REFERRER); }); - it('should respect previous campaign visit before referral', () => { + it('should respect previous campaign visit before referral', function () { stubGetItem.withArgs('adk_dpt_analytics').returns(JSON.stringify(CAMPAIGN)); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com', 'https://www.google.com/search?q=pikachu'); expect(source).to.be.eql(CAMPAIGN); }); - it('should parse referral visit from same domain as direct', () => { + it('should parse referral visit from same domain as direct', function () { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://lander.com/news.html', 'http://lander.com/lander.html'); expect(source).to.be.eql(DIRECT); }); - it('should parse campaign visit', () => { + it('should parse campaign visit', function () { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://lander.com/index.html?utm_campaign=new_campaign&utm_source=adkernel&utm_medium=email&utm_c1=1&utm_c2=2&utm_c3=3&utm_c4=4&utm_c5=5'); @@ -115,12 +115,12 @@ describe('', () => { }); }); - describe('ExpiringQueue', () => { + describe('ExpiringQueue', function () { let timer; - before(() => { + before(function () { timer = sandbox.useFakeTimers(0); }); - after(() => { + after(function () { timer.restore(); }); @@ -184,26 +184,26 @@ describe('', () => { size: '300x250' }; - describe('Analytics adapter', () => { + describe('Analytics adapter', function () { let ajaxStub; let timer; - before(() => { + before(function () { ajaxStub = sandbox.stub(ajax, 'ajax'); timer = sandbox.useFakeTimers(0); }); - beforeEach(() => { + beforeEach(function () { sandbox.stub(events, 'getEvents').callsFake(() => { return [] }); }); - afterEach(() => { + afterEach(function () { events.getEvents.restore(); }); - it('should be configurable', () => { + it('should be configurable', function () { adaptermanager.registerAnalyticsAdapter({ code: 'adkernelAdn', adapter: analyticsAdapter @@ -221,21 +221,21 @@ describe('', () => { expect(analyticsAdapter.context).to.have.property('pubId', 777); }); - it('should handle auction init event', () => { + it('should handle auction init event', function () { events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {config: {}, timeout: 3000}); const ev = analyticsAdapter.context.queue.peekAll(); expect(ev).to.have.length(1); expect(ev[0]).to.be.eql({event: 'auctionInit'}); }); - it('should handle bid request event', () => { + it('should handle bid request event', function () { events.emit(CONSTANTS.EVENTS.BID_REQUESTED, REQUEST); const ev = analyticsAdapter.context.queue.peekAll(); expect(ev).to.have.length(2); expect(ev[1]).to.be.eql({event: 'bidRequested', adapter: 'adapter', tagid: 'container-1'}); }); - it('should handle bid response event', () => { + it('should handle bid response event', function () { events.emit(CONSTANTS.EVENTS.BID_RESPONSE, RESPONSE); const ev = analyticsAdapter.context.queue.peekAll(); expect(ev).to.have.length(3); @@ -248,7 +248,7 @@ describe('', () => { }); }); - it('should handle auction end event', () => { + it('should handle auction end event', function () { timer.tick(447); events.emit(CONSTANTS.EVENTS.AUCTION_END, RESPONSE); let ev = analyticsAdapter.context.queue.peekAll(); @@ -258,7 +258,7 @@ describe('', () => { expect(ev[3]).to.be.eql({event: 'auctionEnd', time: 0.447}); }); - it('should handle winning bid', () => { + it('should handle winning bid', function () { events.emit(CONSTANTS.EVENTS.BID_WON, RESPONSE); timer.tick(4500); expect(ajaxStub.calledTwice).to.be.equal(true); diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index af9ccfd78ed..fe71d968571 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/adkernelAdnBidAdapter'; import * as utils from 'src/utils'; -describe('AdkernelAdn adapter', () => { +describe('AdkernelAdn adapter', function () { const bid1_pub1 = { bidder: 'adkernelAdn', transactionId: 'transact0', @@ -110,12 +110,12 @@ describe('AdkernelAdn adapter', () => { syncpages: ['https://dsp.adkernel.com/sync'] }; - describe('input parameters validation', () => { - it('empty request shouldn\'t generate exception', () => { + describe('input parameters validation', function () { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid({bidderCode: 'adkernelAdn' })).to.be.equal(false); }); - it('request without pubid should be ignored', () => { + it('request without pubid should be ignored', function () { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', params: {}, @@ -123,7 +123,7 @@ describe('AdkernelAdn adapter', () => { sizes: [[300, 250]] })).to.be.equal(false); }); - it('request with invalid pubid should be ignored', () => { + it('request with invalid pubid should be ignored', function () { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', params: { @@ -157,41 +157,41 @@ describe('AdkernelAdn adapter', () => { return [pbRequests, tagRequests]; } - describe('banner request building', () => { + describe('banner request building', function () { let [_, tagRequests] = buildRequest([bid1_pub1]); let tagRequest = tagRequests[0]; - it('should have request id', () => { + it('should have request id', function () { expect(tagRequest).to.have.property('id'); }); - it('should have transaction id', () => { + it('should have transaction id', function () { expect(tagRequest).to.have.property('tid'); }); - it('should have sizes', () => { + it('should have sizes', function () { expect(tagRequest.imp[0].banner).to.have.property('format'); expect(tagRequest.imp[0].banner.format).to.be.eql(['300x250', '300x200']); }); - it('should have impression id', () => { + it('should have impression id', function () { expect(tagRequest.imp[0]).to.have.property('id', 'bidid_1'); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(tagRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); - it('should create proper site block', () => { + it('should create proper site block', function () { expect(tagRequest.site).to.have.property('page', 'https://example.com/index.html'); expect(tagRequest.site).to.have.property('secure', 1); }); - it('should not have user object', () => { + it('should not have user object', function () { expect(tagRequest).to.not.have.property('user'); }); - it('shouldn\'t contain gdpr-related information for default request', () => { + it('shouldn\'t contain gdpr-related information for default request', function () { let [_, tagRequests] = buildRequest([bid1_pub1]); expect(tagRequests[0]).to.not.have.property('user'); }); - it('should contain gdpr-related information if consent is configured', () => { + it('should contain gdpr-related information if consent is configured', function () { let [_, bidRequests] = buildRequest([bid1_pub1], {gdprConsent: {gdprApplies: true, consentString: 'test-consent-string'}}); expect(bidRequests[0]).to.have.property('user'); @@ -199,7 +199,7 @@ describe('AdkernelAdn adapter', () => { expect(bidRequests[0].user).to.have.property('consent', 'test-consent-string'); }); - it('should\'t contain consent string if gdpr isn\'t applied', () => { + it('should\'t contain consent string if gdpr isn\'t applied', function () { let [_, bidRequests] = buildRequest([bid1_pub1], {gdprConsent: {gdprApplies: false}}); expect(bidRequests[0]).to.have.property('user'); expect(bidRequests[0].user).to.have.property('gdpr', 0); @@ -207,19 +207,19 @@ describe('AdkernelAdn adapter', () => { }); }); - describe('video request building', () => { + describe('video request building', function () { let [_, tagRequests] = buildRequest([bid_video1, bid_video2]); let tagRequest = tagRequests[0]; - it('should have video object', () => { + it('should have video object', function () { expect(tagRequest.imp[0]).to.have.property('video'); expect(tagRequest.imp[1]).to.have.property('video'); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(tagRequest.imp[0]).to.have.property('tagid', 'video_wrapper'); expect(tagRequest.imp[1]).to.have.property('tagid', 'video_wrapper2'); }); - it('should have size', () => { + it('should have size', function () { expect(tagRequest.imp[0].video).to.have.property('w', 640); expect(tagRequest.imp[0].video).to.have.property('h', 300); expect(tagRequest.imp[1].video).to.have.property('w', 1920); @@ -227,8 +227,8 @@ describe('AdkernelAdn adapter', () => { }); }); - describe('requests routing', () => { - it('should issue a request for each publisher', () => { + describe('requests routing', function () { + it('should issue a request for each publisher', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1, bid_video1]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string(`account=${bid1_pub1.params.pubId}`); @@ -236,7 +236,7 @@ describe('AdkernelAdn adapter', () => { expect(tagRequests[0].imp).to.have.length(1); expect(tagRequests[1].imp).to.have.length(1); }); - it('should issue a request for each host', () => { + it('should issue a request for each host', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1, bid1_pub2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string('//tag.adkernel.com/tag'); @@ -246,15 +246,15 @@ describe('AdkernelAdn adapter', () => { }); }); - describe('responses processing', () => { + describe('responses processing', function () { let responses; - before(() => { + before(function () { responses = spec.interpretResponse({body: response}); }); - it('should parse all responses', () => { + it('should parse all responses', function () { expect(responses).to.have.length(3); }); - it('should return fully-initialized bid-response', () => { + it('should return fully-initialized bid-response', function () { let resp = responses[0]; expect(resp).to.have.property('bidderCode', 'adkernelAdn'); expect(resp).to.have.property('requestId', '2c5e951baeeadd'); @@ -268,7 +268,7 @@ describe('AdkernelAdn adapter', () => { expect(resp).to.have.property('ad'); expect(resp.ad).to.have.string(''); }); - it('should return fully-initialized video bid-response', () => { + it('should return fully-initialized video bid-response', function () { let resp = responses[2]; expect(resp).to.have.property('bidderCode', 'adkernelAdn'); expect(resp).to.have.property('requestId', '57d602ad1c9545'); @@ -280,7 +280,7 @@ describe('AdkernelAdn adapter', () => { expect(resp).to.have.property('vastUrl', 'http://vast.com/vast.xml'); expect(resp).to.not.have.property('ad'); }); - it('should perform usersync', () => { + it('should perform usersync', function () { let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: response}]); expect(syncs).to.have.length(0); syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: response}]); @@ -288,12 +288,12 @@ describe('AdkernelAdn adapter', () => { expect(syncs[0]).to.have.property('type', 'iframe'); expect(syncs[0]).to.have.property('url', 'https://dsp.adkernel.com/sync'); }); - it('should handle user-sync only response', () => { + it('should handle user-sync only response', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1]); let resp = spec.interpretResponse({body: usersyncOnlyResponse}, pbRequests[0]); expect(resp).to.have.length(0); }); - it('shouldn\' fail on empty response', () => { + it('shouldn\' fail on empty response', function () { let syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: ''}]); expect(syncs).to.have.length(0); }); diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index 0f5596b8b23..590e0ebb96e 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -3,7 +3,7 @@ import {spec} from 'modules/adkernelBidAdapter'; import * as utils from 'src/utils'; import {parse as parseUrl} from 'src/url'; -describe('Adkernel adapter', () => { +describe('Adkernel adapter', function () { const bid1_zone1 = { bidder: 'adkernel', bidId: 'Bid_01', @@ -127,73 +127,73 @@ describe('Adkernel adapter', () => { return [pbRequests, rtbRequests]; } - describe('input parameters validation', () => { - it('empty request shouldn\'t generate exception', () => { + describe('input parameters validation', function () { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid({ bidderCode: 'adkernel' })).to.be.equal(false); }); - it('request without zone shouldn\'t issue a request', () => { + it('request without zone shouldn\'t issue a request', function () { expect(spec.isBidRequestValid(bid_without_zone)).to.be.equal(false); }); - it('request without host shouldn\'t issue a request', () => { + it('request without host shouldn\'t issue a request', function () { expect(spec.isBidRequestValid(bid_without_host)).to.be.equal(false); }); - it('empty request shouldn\'t generate exception', () => { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid(bid_with_wrong_zoneId)).to.be.equal(false); }); }); - describe('banner request building', () => { + describe('banner request building', function () { let bidRequest, bidRequests, _; - before(() => { + before(function () { [_, bidRequests] = buildRequest([bid1_zone1]); bidRequest = bidRequests[0]; }); - it('should be a first-price auction', () => { + it('should be a first-price auction', function () { expect(bidRequest).to.have.property('at', 1); }); - it('should have banner object', () => { + it('should have banner object', function () { expect(bidRequest.imp[0]).to.have.property('banner'); }); - it('should have w/h', () => { + it('should have w/h', function () { expect(bidRequest.imp[0].banner).to.have.property('format'); expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); }); - it('should respect secure connection', () => { + it('should respect secure connection', function () { expect(bidRequest.imp[0]).to.have.property('secure', 1); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); - it('should create proper site block', () => { + it('should create proper site block', function () { expect(bidRequest.site).to.have.property('domain', 'example.com'); expect(bidRequest.site).to.have.property('page', 'https://example.com/index.html'); }); - it('should fill device with caller macro', () => { + it('should fill device with caller macro', function () { expect(bidRequest).to.have.property('device'); expect(bidRequest.device).to.have.property('ip', 'caller'); expect(bidRequest.device).to.have.property('ua', 'caller'); expect(bidRequest.device).to.have.property('dnt', 1); }); - it('shouldn\'t contain gdpr-related information for default request', () => { + it('shouldn\'t contain gdpr-related information for default request', function () { let [_, bidRequests] = buildRequest([bid1_zone1]); expect(bidRequests[0]).to.not.have.property('regs'); expect(bidRequests[0]).to.not.have.property('user'); }); - it('should contain gdpr-related information if consent is configured', () => { + it('should contain gdpr-related information if consent is configured', function () { let [_, bidRequests] = buildRequest([bid1_zone1], {gdprConsent: {gdprApplies: true, consentString: 'test-consent-string', vendorData: {}}}); let bidRequest = bidRequests[0]; @@ -203,7 +203,7 @@ describe('Adkernel adapter', () => { expect(bidRequest.user.ext).to.be.eql({'consent': 'test-consent-string'}); }); - it('should\'t contain consent string if gdpr isn\'t applied', () => { + it('should\'t contain consent string if gdpr isn\'t applied', function () { let [_, bidRequests] = buildRequest([bid1_zone1], {gdprConsent: {gdprApplies: false}}); let bidRequest = bidRequests[0]; expect(bidRequest).to.have.property('regs'); @@ -211,41 +211,41 @@ describe('Adkernel adapter', () => { expect(bidRequest).to.not.have.property('user'); }); - it('should\'t pass dnt if state is unknown', () => { + it('should\'t pass dnt if state is unknown', function () { let [_, bidRequests] = buildRequest([bid1_zone1], {}, 'https://example.com/index.html', false); expect(bidRequests[0].device).to.not.have.property('dnt'); }); }); - describe('video request building', () => { + describe('video request building', function () { let _, bidRequests; - before(() => { + before(function () { [_, bidRequests] = buildRequest([bid_video]); }); - it('should have video object', () => { + it('should have video object', function () { expect(bidRequests[0].imp[0]).to.have.property('video'); }); - it('should have h/w', () => { + it('should have h/w', function () { expect(bidRequests[0].imp[0].video).to.have.property('w', 640); expect(bidRequests[0].imp[0].video).to.have.property('h', 480); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(bidRequests[0].imp[0]).to.have.property('tagid', 'ad-unit-1'); }); }); - describe('requests routing', () => { - it('should issue a request for each host', () => { + describe('requests routing', function () { + it('should issue a request for each host', function () { let [pbRequests, _] = buildRequest([bid1_zone1, bid3_host2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string(`//${bid1_zone1.params.host}/`); expect(pbRequests[1].url).to.have.string(`//${bid3_host2.params.host}/`); }); - it('should issue a request for each zone', () => { + it('should issue a request for each zone', function () { let [pbRequests, _] = buildRequest([bid1_zone1, bid2_zone2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].data.zone).to.be.equal(bid1_zone1.params.zoneId); @@ -253,8 +253,8 @@ describe('Adkernel adapter', () => { }); }); - describe('responses processing', () => { - it('should return fully-initialized banner bid-response', () => { + describe('responses processing', function () { + it('should return fully-initialized banner bid-response', function () { let [pbRequests, _] = buildRequest([bid1_zone1]); let resp = spec.interpretResponse({body: bidResponse1}, pbRequests[0])[0]; expect(resp).to.have.property('requestId', 'Bid_01'); @@ -269,7 +269,7 @@ describe('Adkernel adapter', () => { expect(resp.ad).to.have.string(''); }); - it('should return fully-initialized video bid-response', () => { + it('should return fully-initialized video bid-response', function () { let [pbRequests, _] = buildRequest([bid_video]); let resp = spec.interpretResponse({body: videoBidResponse}, pbRequests[0])[0]; expect(resp).to.have.property('requestId', 'Bid_Video'); @@ -280,20 +280,20 @@ describe('Adkernel adapter', () => { expect(resp.height).to.equal(480); }); - it('should add nurl as pixel for banner response', () => { + it('should add nurl as pixel for banner response', function () { let [pbRequests, _] = buildRequest([bid1_zone1]); let resp = spec.interpretResponse({body: bidResponse1}, pbRequests[0])[0]; let expectedNurl = bidResponse1.seatbid[0].bid[0].nurl + '&px=1'; expect(resp.ad).to.have.string(expectedNurl); }); - it('should handle bidresponse with user-sync only', () => { + it('should handle bidresponse with user-sync only', function () { let [pbRequests, _] = buildRequest([bid1_zone1]); let resp = spec.interpretResponse({body: usersyncOnlyResponse}, pbRequests[0]); expect(resp).to.have.length(0); }); - it('should perform usersync', () => { + it('should perform usersync', function () { let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: bidResponse1}]); expect(syncs).to.have.length(0); syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: bidResponse1}]); diff --git a/test/spec/modules/admixerBidAdapter_spec.js b/test/spec/modules/admixerBidAdapter_spec.js index 13312e3d24e..54d0dbee6e4 100644 --- a/test/spec/modules/admixerBidAdapter_spec.js +++ b/test/spec/modules/admixerBidAdapter_spec.js @@ -6,16 +6,16 @@ const BIDDER_CODE = 'admixer'; const ENDPOINT_URL = '//inv-nets.admixer.net/prebid.1.0.aspx'; const ZONE_ID = '2eb6bd58-865c-47ce-af7f-a918108c3fd2'; -describe('AdmixerAdapter', () => { +describe('AdmixerAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.be.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': BIDDER_CODE, 'params': { @@ -28,11 +28,11 @@ describe('AdmixerAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -42,7 +42,7 @@ describe('AdmixerAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': BIDDER_CODE, @@ -57,21 +57,21 @@ describe('AdmixerAdapter', () => { } ]; - it('should add referrer and imp to be equal bidRequest', () => { + it('should add referrer and imp to be equal bidRequest', function () { const request = spec.buildRequests(bidRequests); const payload = JSON.parse(request.data.substr(5)); expect(payload.referrer).to.not.be.undefined; expect(payload.imps[0]).to.deep.equal(bidRequests[0]); }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT_URL); expect(request.method).to.equal('GET'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { body: [{ 'currency': 'USD', @@ -86,7 +86,7 @@ describe('AdmixerAdapter', () => { }] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const body = response.body; let expectedResponse = [ { @@ -107,7 +107,7 @@ describe('AdmixerAdapter', () => { expect(result[0]).to.deep.equal(expectedResponse[0]); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = []; let result = spec.interpretResponse(response); diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index 39eb514752a..c9f33b940b5 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/adoceanBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('AdoceanAdapter', () => { +describe('AdoceanAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { const bid = { 'bidder': 'adocean', 'params': { @@ -26,11 +26,11 @@ describe('AdoceanAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { const bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,7 +40,7 @@ describe('AdoceanAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [ { 'bidder': 'adocean', @@ -64,32 +64,32 @@ describe('AdoceanAdapter', () => { } }; - it('should add bidIdMap with slaveId => bidId mapping', () => { + it('should add bidIdMap with slaveId => bidId mapping', function () { const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.bidIdMap).to.exists; const bidIdMap = request.bidIdMap; expect(bidIdMap[bidRequests[0].params.slaveId]).to.equal(bidRequests[0].bidId); }); - it('sends bid request to url via GET', () => { + it('sends bid request to url via GET', function () { const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.method).to.equal('GET'); expect(request.url).to.match(new RegExp(`^https://${bidRequests[0].params.emiter}/ad.json`)); }); - it('should attach id to url', () => { + it('should attach id to url', function () { const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.url).to.include('id=' + bidRequests[0].params.masterId); }); - it('should attach consent information to url', () => { + it('should attach consent information to url', function () { const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.url).to.include('gdpr=1'); expect(request.url).to.include('gdpr_consent=' + bidderRequest.gdprConsent.consentString); }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { const response = { 'body': [ { @@ -128,7 +128,7 @@ describe('AdoceanAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const expectedResponse = [ { 'requestId': '30b31c1838de1e', @@ -156,7 +156,7 @@ describe('AdoceanAdapter', () => { }); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { response.body = [ { 'id': 'adoceanmyaolafpjwftbz', diff --git a/test/spec/modules/adomikAnalyticsAdapter_spec.js b/test/spec/modules/adomikAnalyticsAdapter_spec.js index 59e6dadec96..cb3c30705f4 100644 --- a/test/spec/modules/adomikAnalyticsAdapter_spec.js +++ b/test/spec/modules/adomikAnalyticsAdapter_spec.js @@ -9,21 +9,21 @@ describe('Adomik Prebid Analytic', function () { let sendWonEventStub; describe('enableAnalytics', function () { - beforeEach(() => { + beforeEach(function () { sinon.spy(adomikAnalytics, 'track'); sendEventStub = sinon.stub(adomikAnalytics, 'sendTypedEvent'); sendWonEventStub = sinon.stub(adomikAnalytics, 'sendWonEvent'); sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { adomikAnalytics.track.restore(); sendEventStub.restore(); sendWonEventStub.restore(); events.getEvents.restore(); }); - after(() => { + after(function () { adomikAnalytics.disableAnalytics(); }); diff --git a/test/spec/modules/adspiritBidAdapter_spec.js b/test/spec/modules/adspiritBidAdapter_spec.js index 5c8400a8cbc..7f907612384 100644 --- a/test/spec/modules/adspiritBidAdapter_spec.js +++ b/test/spec/modules/adspiritBidAdapter_spec.js @@ -1,10 +1,10 @@ import {expect} from 'chai'; import {spec} from 'modules/adspiritBidAdapter'; -describe('Adspirit adapter tests', () => { +describe('Adspirit adapter tests', function () { let bidRequests, serverResponses; - beforeEach(() => { + beforeEach(function () { bidRequests = [ // valid for adspirit { @@ -89,36 +89,36 @@ describe('Adspirit adapter tests', () => { ] }); - describe('test bid request', () => { - it('with valid data 1', () => { + describe('test bid request', function () { + it('with valid data 1', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); }); - it('with valid data 2', () => { + it('with valid data 2', function () { expect(spec.isBidRequestValid(bidRequests[1])).to.equal(true); }); - it('with valid data 3', () => { + it('with valid data 3', function () { expect(spec.isBidRequestValid(bidRequests[2])).to.equal(true); }); - it('with invalid data 1 (no host)', () => { + it('with invalid data 1 (no host)', function () { expect(spec.isBidRequestValid(bidRequests[3])).to.equal(false); }); - it('with invalid data 2 (no placementId)', () => { + it('with invalid data 2 (no placementId)', function () { expect(spec.isBidRequestValid(bidRequests[4])).to.equal(false); }); - it('with invalid data 3 (no bidder code)', () => { + it('with invalid data 3 (no bidder code)', function () { expect(spec.isBidRequestValid(bidRequests[5])).to.equal(false); }); }); - describe('test request build', () => { - it('normal', () => { + describe('test request build', function () { + it('normal', function () { var requests = spec.buildRequests([bidRequests[0]]); expect(requests).to.be.lengthOf(1); }); }); - describe('test bid responses', () => { - it('success 1', () => { + describe('test bid responses', function () { + it('success 1', function () { var bids = spec.interpretResponse(serverResponses[0], {'bidRequest': bidRequests[0]}); expect(bids).to.be.lengthOf(1); expect(bids[0].cpm).to.equal(1.5); @@ -126,15 +126,15 @@ describe('Adspirit adapter tests', () => { expect(bids[0].height).to.equal(250); expect(bids[0].ad).to.have.length.above(1); }); - it('fail 1 (cpm=0)', () => { + it('fail 1 (cpm=0)', function () { var bids = spec.interpretResponse(serverResponses[1], {'bidRequest': bidRequests[0]}); expect(bids).to.be.lengthOf(0); }); - it('fail 2 (no response)', () => { + it('fail 2 (no response)', function () { var bids = spec.interpretResponse([], {'bidRequest': bidRequests[0]}); expect(bids).to.be.lengthOf(0); }); - it('fail 3 (status fail)', () => { + it('fail 3 (status fail)', function () { var bids = spec.interpretResponse(serverResponses[2], {'bidRequest': bidRequests[0]}); expect(bids).to.be.lengthOf(0); }); diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js index fa3e0479372..6190f53fdc4 100644 --- a/test/spec/modules/adtelligentBidAdapter_spec.js +++ b/test/spec/modules/adtelligentBidAdapter_spec.js @@ -96,28 +96,28 @@ const displayEqResponse = [{ cpm: 0.9 }]; -describe('adtelligentBidAdapter', () => { +describe('adtelligentBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(VIDEO_REQUEST)).to.equal(12345); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, VIDEO_REQUEST); delete bid.params; expect(spec.isBidRequestValid(bid)).to.equal(undefined); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let videoBidRequests = [VIDEO_REQUEST]; let displayBidRequests = [DISPLAY_REQUEST]; let videoAndDisplayBidRequests = [DISPLAY_REQUEST, VIDEO_REQUEST]; @@ -126,19 +126,19 @@ describe('adtelligentBidAdapter', () => { const videoRequest = spec.buildRequests(videoBidRequests, {}); const videoAndDisplayRequests = spec.buildRequests(videoAndDisplayBidRequests, {}); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(videoRequest.method).to.equal('GET'); expect(displayRequest.method).to.equal('GET'); expect(videoAndDisplayRequests.method).to.equal('GET'); }); - it('sends bid request to correct ENDPOINT', () => { + it('sends bid request to correct ENDPOINT', function () { expect(videoRequest.url).to.equal(ENDPOINT); expect(displayRequest.url).to.equal(ENDPOINT); expect(videoAndDisplayRequests.url).to.equal(ENDPOINT); }); - it('sends correct video bid parameters', () => { + it('sends correct video bid parameters', function () { const bid = Object.assign({}, videoRequest.data); delete bid.domain; @@ -152,7 +152,7 @@ describe('adtelligentBidAdapter', () => { expect(bid).to.deep.equal(eq); }); - it('sends correct display bid parameters', () => { + it('sends correct display bid parameters', function () { const bid = Object.assign({}, displayRequest.data); delete bid.domain; @@ -166,7 +166,7 @@ describe('adtelligentBidAdapter', () => { expect(bid).to.deep.equal(eq); }); - it('sends correct video and display bid parameters', () => { + it('sends correct video and display bid parameters', function () { const bid = Object.assign({}, videoAndDisplayRequests.data); delete bid.domain; @@ -185,18 +185,18 @@ describe('adtelligentBidAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse; let bidderRequest; let eqResponse; - afterEach(() => { + afterEach(function () { serverResponse = null; bidderRequest = null; eqResponse = null; }); - it('should get correct video bid response', () => { + it('should get correct video bid response', function () { serverResponse = SERVER_VIDEO_RESPONSE; bidderRequest = videoBidderRequest; eqResponse = videoEqResponse; @@ -204,7 +204,7 @@ describe('adtelligentBidAdapter', () => { bidServerResponseCheck(); }); - it('should get correct display bid response', () => { + it('should get correct display bid response', function () { serverResponse = SERVER_DISPLAY_RESPONSE; bidderRequest = displayBidderRequest; eqResponse = displayEqResponse; @@ -225,13 +225,13 @@ describe('adtelligentBidAdapter', () => { expect(noBidResult.length).to.equal(0); } - it('handles video nobid responses', () => { + it('handles video nobid responses', function () { bidderRequest = videoBidderRequest; nobidServerResponseCheck(); }); - it('handles display nobid responses', () => { + it('handles display nobid responses', function () { bidderRequest = displayBidderRequest; nobidServerResponseCheck(); diff --git a/test/spec/modules/aduptechBidAdapter_spec.js b/test/spec/modules/aduptechBidAdapter_spec.js index 76689e9603f..da0b603ebfc 100644 --- a/test/spec/modules/aduptechBidAdapter_spec.js +++ b/test/spec/modules/aduptechBidAdapter_spec.js @@ -3,17 +3,17 @@ import { BIDDER_CODE, PUBLISHER_PLACEHOLDER, ENDPOINT_URL, ENDPOINT_METHOD, spec import { newBidder } from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; -describe('AduptechBidAdapter', () => { +describe('AduptechBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when necessary information is given', () => { + describe('isBidRequestValid', function () { + it('should return true when necessary information is given', function () { expect(spec.isBidRequestValid({ sizes: [[100, 200]], params: { @@ -23,11 +23,11 @@ describe('AduptechBidAdapter', () => { })).to.be.true; }); - it('should return false on empty bid', () => { + it('should return false on empty bid', function () { expect(spec.isBidRequestValid({})).to.be.false; }); - it('should return false on missing sizes', () => { + it('should return false on missing sizes', function () { expect(spec.isBidRequestValid({ params: { publisher: 'test', @@ -36,7 +36,7 @@ describe('AduptechBidAdapter', () => { })).to.be.false; }); - it('should return false on empty sizes', () => { + it('should return false on empty sizes', function () { expect(spec.isBidRequestValid({ sizes: [], params: { @@ -46,27 +46,27 @@ describe('AduptechBidAdapter', () => { })).to.be.false; }); - it('should return false on missing params', () => { + it('should return false on missing params', function () { expect(spec.isBidRequestValid({ sizes: [[100, 200]], })).to.be.false; }); - it('should return false on invalid params', () => { + it('should return false on invalid params', function () { expect(spec.isBidRequestValid({ sizes: [[100, 200]], params: 'bar' })).to.be.false; }); - it('should return false on empty params', () => { + it('should return false on empty params', function () { expect(spec.isBidRequestValid({ sizes: [[100, 200]], params: {} })).to.be.false; }); - it('should return false on missing publisher', () => { + it('should return false on missing publisher', function () { expect(spec.isBidRequestValid({ sizes: [[100, 200]], params: { @@ -75,7 +75,7 @@ describe('AduptechBidAdapter', () => { })).to.be.false; }); - it('should return false on missing placement', () => { + it('should return false on missing placement', function () { expect(spec.isBidRequestValid({ sizes: [[100, 200]], params: { @@ -85,8 +85,8 @@ describe('AduptechBidAdapter', () => { }); }); - describe('buildRequests', () => { - it('should send one bid request per ad unit to the endpoint via POST', () => { + describe('buildRequests', function () { + it('should send one bid request per ad unit to the endpoint via POST', function () { const bidRequests = [ { bidder: BIDDER_CODE, @@ -146,7 +146,7 @@ describe('AduptechBidAdapter', () => { }); }); - it('should pass gdpr informations', () => { + it('should pass gdpr informations', function () { const bidderRequest = { gdprConsent: { consentString: 'consentString', @@ -175,7 +175,7 @@ describe('AduptechBidAdapter', () => { expect(result[0].data.gdpr.consentString).to.exist.and.to.equal(bidderRequest.gdprConsent.consentString); }); - it('should encode publisher param in endpoint url', () => { + it('should encode publisher param in endpoint url', function () { const bidRequests = [ { bidder: BIDDER_CODE, @@ -196,13 +196,13 @@ describe('AduptechBidAdapter', () => { expect(result[0].url).to.equal(ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, encodeURIComponent(bidRequests[0].params.publisher))); }); - it('should handle empty bidRequests', () => { + it('should handle empty bidRequests', function () { expect(spec.buildRequests([])).to.deep.equal([]); }); }); - describe('interpretResponse', () => { - it('should correctly interpret the server response', () => { + describe('interpretResponse', function () { + it('should correctly interpret the server response', function () { const serverResponse = { body: { bid: { @@ -238,11 +238,11 @@ describe('AduptechBidAdapter', () => { ]); }); - it('should handle empty serverResponse', () => { + it('should handle empty serverResponse', function () { expect(spec.interpretResponse({})).to.deep.equal([]); }); - it('should handle missing bid', () => { + it('should handle missing bid', function () { expect(spec.interpretResponse({ body: { creative: {} @@ -250,7 +250,7 @@ describe('AduptechBidAdapter', () => { })).to.deep.equal([]); }); - it('should handle missing creative', () => { + it('should handle missing creative', function () { expect(spec.interpretResponse({ body: { bid: {} diff --git a/test/spec/modules/adxcgAnalyticsAdapter_spec.js b/test/spec/modules/adxcgAnalyticsAdapter_spec.js index 9b6b057ee56..dfccbf6e87e 100644 --- a/test/spec/modules/adxcgAnalyticsAdapter_spec.js +++ b/test/spec/modules/adxcgAnalyticsAdapter_spec.js @@ -5,23 +5,23 @@ let adaptermanager = require('src/adaptermanager'); let events = require('src/events'); let constants = require('src/constants.json'); -describe('adxcg analytics adapter', () => { +describe('adxcg analytics adapter', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { xhr.restore(); events.getEvents.restore(); }); - describe('track', () => { + describe('track', function () { let initOptions = { publisherId: '42' }; @@ -164,18 +164,18 @@ describe('adxcg analytics adapter', () => { adapter: adxcgAnalyticsAdapter }); - beforeEach(() => { + beforeEach(function () { adaptermanager.enableAnalytics({ provider: 'adxcg', options: initOptions }); }); - afterEach(() => { + afterEach(function () { adxcgAnalyticsAdapter.disableAnalytics(); }); - it('builds and sends auction data', () => { + it('builds and sends auction data', function () { // Step 1: Send auction init event events.emit(constants.EVENTS.AUCTION_INIT, { timestamp: auctionTimestamp diff --git a/test/spec/modules/adxcgBidAdapter_spec.js b/test/spec/modules/adxcgBidAdapter_spec.js index 60aadaec21f..faa8db8050a 100644 --- a/test/spec/modules/adxcgBidAdapter_spec.js +++ b/test/spec/modules/adxcgBidAdapter_spec.js @@ -2,8 +2,8 @@ import { expect } from 'chai' import * as url from 'src/url' import { spec } from 'modules/adxcgBidAdapter' -describe('AdxcgAdapter', () => { - describe('isBidRequestValid', () => { +describe('AdxcgAdapter', function () { + describe('isBidRequestValid', function () { let bidBanner = { 'bidder': 'adxcg', 'params': { @@ -37,22 +37,22 @@ describe('AdxcgAdapter', () => { 'auctionId': '1d1a030790a475', } - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bidBanner)).to.equal(true) }) - it('should return true when required params not found', () => { + it('should return true when required params not found', function () { expect(spec.isBidRequestValid({})).to.be.false }) - it('should return false when required params are not passed', () => { + 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 return true when required video params not found', () => { + 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 @@ -63,7 +63,7 @@ describe('AdxcgAdapter', () => { }) }) - describe('request function http', () => { + describe('request function http', function () { let bid = { 'bidder': 'adxcg', 'params': { @@ -76,7 +76,7 @@ describe('AdxcgAdapter', () => { 'auctionId': '1d1a030790a475', } - it('creates a valid adxcg request url', () => { + it('creates a valid adxcg request url', function () { let request = spec.buildRequests([bid]) expect(request).to.exist expect(request.method).to.equal('GET') @@ -96,7 +96,7 @@ describe('AdxcgAdapter', () => { }) }) - describe('gdpr compliance', () => { + describe('gdpr compliance', function () { let bid = { 'bidder': 'adxcg', 'params': { @@ -109,7 +109,7 @@ describe('AdxcgAdapter', () => { 'auctionId': '1d1a030790a475', } - it('should send GDPR Consent data if gdprApplies', () => { + it('should send GDPR Consent data if gdprApplies', function () { let request = spec.buildRequests([bid], {gdprConsent: {gdprApplies: true, consentString: 'consentDataString'}}) let parsedRequestUrl = url.parse(request.url) let query = parsedRequestUrl.search @@ -118,7 +118,7 @@ describe('AdxcgAdapter', () => { expect(query.gdpr_consent).to.equal('consentDataString') }) - it('should not send GDPR Consent data if gdprApplies is false or undefined', () => { + it('should not send GDPR Consent data if gdprApplies is false or undefined', function () { let request = spec.buildRequests([bid], { gdprConsent: { gdprApplies: false, @@ -133,7 +133,7 @@ describe('AdxcgAdapter', () => { }) }) - describe('response handler', () => { + describe('response handler', function () { let BIDDER_REQUEST = { 'bidder': 'adxcg', 'params': { @@ -245,7 +245,7 @@ describe('AdxcgAdapter', () => { header: {'someheader': 'fakedata'} } - it('handles regular responses', () => { + it('handles regular responses', function () { let result = spec.interpretResponse(BANNER_RESPONSE, BIDDER_REQUEST) expect(result).to.have.lengthOf(1) @@ -262,7 +262,7 @@ describe('AdxcgAdapter', () => { expect(result[0].dealId).to.not.exist }) - it('handles regular responses with dealid', () => { + it('handles regular responses with dealid', function () { let result = spec.interpretResponse(BANNER_RESPONSE_WITHDEALID, BIDDER_REQUEST) expect(result).to.have.lengthOf(1) @@ -277,7 +277,7 @@ describe('AdxcgAdapter', () => { expect(result[0].ttl).to.equal(300) }) - it('handles video responses', () => { + it('handles video responses', function () { let result = spec.interpretResponse(VIDEO_RESPONSE, BIDDER_REQUEST) expect(result).to.have.lengthOf(1) @@ -292,7 +292,7 @@ describe('AdxcgAdapter', () => { expect(result[0].ttl).to.equal(300) }) - it('handles native responses', () => { + it('handles native responses', function () { let result = spec.interpretResponse(NATIVE_RESPONSE, BIDDER_REQUEST) expect(result[0].width).to.equal(0) @@ -312,7 +312,7 @@ describe('AdxcgAdapter', () => { expect(result[0].native.sponsoredBy).to.equal('sponsoredByContent') }) - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = [] let bidderRequest = BIDDER_REQUEST @@ -321,12 +321,12 @@ describe('AdxcgAdapter', () => { }) }) - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let syncoptionsIframe = { 'iframeEnabled': 'true' } - it('should return iframe sync option', () => { + it('should return iframe sync option', function () { expect(spec.getUserSyncs(syncoptionsIframe)[0].type).to.equal('iframe') expect(spec.getUserSyncs(syncoptionsIframe)[0].url).to.equal('//cdn.adxcg.net/pb-sync.html') }) diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js index d7a5b1a87b7..26898d3f57e 100644 --- a/test/spec/modules/adyoulikeBidAdapter_spec.js +++ b/test/spec/modules/adyoulikeBidAdapter_spec.js @@ -4,7 +4,7 @@ import { parse } from '../../../src/url'; import { spec } from 'modules/adyoulikeBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('Adyoulike Adapter', () => { +describe('Adyoulike Adapter', function () { const canonicalUrl = 'http://canonical.url/?t=%26'; const defaultDC = 'hb-api'; const bidderCode = 'adyoulike'; @@ -136,13 +136,13 @@ describe('Adyoulike Adapter', () => { let getEndpoint = (dc = defaultDC) => `http://${dc}.omnitagjs.com/hb-api/prebid`; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidId': 'bid_id_1', 'bidder': 'adyoulike', @@ -154,18 +154,18 @@ describe('Adyoulike Adapter', () => { 'transactionId': 'bid_id_1_transaction_id' }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.size; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -175,10 +175,10 @@ describe('Adyoulike Adapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let canonicalQuery; - beforeEach(() => { + beforeEach(function () { let canonical = document.createElement('link'); canonical.rel = 'canonical'; canonical.href = canonicalUrl; @@ -186,11 +186,11 @@ describe('Adyoulike Adapter', () => { canonicalQuery.withArgs('link[rel="canonical"][href]').returns(canonical); }); - afterEach(() => { + afterEach(function () { canonicalQuery.restore(); }); - it('should add gdpr consent information to the request', () => { + it('should add gdpr consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { 'bidderCode': 'adyoulike', @@ -212,7 +212,7 @@ describe('Adyoulike Adapter', () => { expect(payload.gdprConsent.consentRequired).to.exist.and.to.be.true; }); - it('sends bid request to endpoint with single placement', () => { + it('sends bid request to endpoint with single placement', function () { const request = spec.buildRequests(bidRequestWithSinglePlacement); const payload = JSON.parse(request.data); @@ -226,7 +226,7 @@ describe('Adyoulike Adapter', () => { expect(payload.Bids['bid_id_0'].TransactionID).to.be.equal('bid_id_0_transaction_id'); }); - it('sends bid request to endpoint with single placement without canonical', () => { + it('sends bid request to endpoint with single placement without canonical', function () { canonicalQuery.restore(); const request = spec.buildRequests(bidRequestWithSinglePlacement); const payload = JSON.parse(request.data); @@ -241,7 +241,7 @@ describe('Adyoulike Adapter', () => { expect(payload.Bids['bid_id_0'].TransactionID).to.be.equal('bid_id_0_transaction_id'); }); - it('sends bid request to endpoint with multiple placements', () => { + it('sends bid request to endpoint with multiple placements', function () { const request = spec.buildRequests(bidRequestMultiPlacements); const payload = JSON.parse(request.data); expect(request.url).to.contain(getEndpoint()); @@ -261,7 +261,7 @@ describe('Adyoulike Adapter', () => { expect(payload.PageRefreshed).to.equal(false); }); - it('sends bid request to endpoint setted by parameters', () => { + it('sends bid request to endpoint setted by parameters', function () { const request = spec.buildRequests(bidRequestWithDCPlacement); const payload = JSON.parse(request.data); @@ -269,16 +269,16 @@ describe('Adyoulike Adapter', () => { }); }); // - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse; - beforeEach(() => { + beforeEach(function () { serverResponse = { body: {} } }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = [{ BidID: '123dfsdf', Attempt: '32344fdse1', @@ -289,7 +289,7 @@ describe('Adyoulike Adapter', () => { expect(result).deep.equal([]); }); - it('receive reponse with single placement', () => { + it('receive reponse with single placement', function () { serverResponse.body = responseWithSinglePlacement; let result = spec.interpretResponse(serverResponse, bidRequestWithSinglePlacement); @@ -300,7 +300,7 @@ describe('Adyoulike Adapter', () => { expect(result[0].height).to.equal(300); }); - it('receive reponse with multiple placement', () => { + it('receive reponse with multiple placement', function () { serverResponse.body = responseWithMultiplePlacements; let result = spec.interpretResponse(serverResponse, bidRequestMultiPlacements); diff --git a/test/spec/modules/ajaBidAdapter_spec.js b/test/spec/modules/ajaBidAdapter_spec.js index c6a531c9f1f..5d5e5924cd5 100644 --- a/test/spec/modules/ajaBidAdapter_spec.js +++ b/test/spec/modules/ajaBidAdapter_spec.js @@ -3,10 +3,10 @@ import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = '//ad.as.amanad.adtdp.com/v2/prebid'; -describe('AjaAdapter', () => { +describe('AjaAdapter', function () { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'aja', 'params': { @@ -19,11 +19,11 @@ describe('AjaAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -33,7 +33,7 @@ describe('AjaAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'aja', @@ -48,13 +48,13 @@ describe('AjaAdapter', () => { } ]; - it('sends bid request to ENDPOINT via GET', () => { + 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', () => { + describe('interpretResponse', function () { let response = { 'is_ad_return': true, 'ad': { @@ -77,7 +77,7 @@ describe('AjaAdapter', () => { ] }; - it('should get correct banner bid response', () => { + it('should get correct banner bid response', function () { let expectedResponse = [ { 'requestId': '51ef8751f9aead', @@ -99,7 +99,7 @@ describe('AjaAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles video responses', () => { + it('handles video responses', function () { let response = { 'is_ad_return': true, 'ad': { @@ -130,7 +130,7 @@ describe('AjaAdapter', () => { expect(result[0]).to.have.property('mediaType', 'video'); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'is_ad_return': false, 'ad': {} diff --git a/test/spec/modules/andbeyondBidAdapter_spec.js b/test/spec/modules/andbeyondBidAdapter_spec.js index 5e58101ef66..f9b0758749b 100644 --- a/test/spec/modules/andbeyondBidAdapter_spec.js +++ b/test/spec/modules/andbeyondBidAdapter_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/andbeyondBidAdapter'; import * as utils from 'src/utils'; -describe('andbeyond adapter', () => { +describe('andbeyond adapter', function () { const bid1_zone1 = { bidder: 'andbeyond', bidId: 'Bid_01', @@ -80,29 +80,29 @@ describe('andbeyond adapter', () => { cur: 'USD' }; - describe('input parameters validation', () => { - it('empty request shouldn\'t generate exception', () => { + describe('input parameters validation', function () { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid({ bidderCode: 'andbeyond' })).to.be.equal(false); }); - it('request without zone shouldn\'t issue a request', () => { + it('request without zone shouldn\'t issue a request', function () { expect(spec.isBidRequestValid(bid_without_zone)).to.be.equal(false); }); - it('request without host shouldn\'t issue a request', () => { + it('request without host shouldn\'t issue a request', function () { expect(spec.isBidRequestValid(bid_without_host)).to.be.equal(false); }); - it('empty request shouldn\'t generate exception', () => { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid(bid_with_wrong_zoneId)).to.be.equal(false); }); }); - describe('banner request building', () => { + describe('banner request building', function () { let bidRequest; - before(() => { + before(function () { let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => ({ protocol: 'https:', hostname: 'example.com', @@ -117,33 +117,33 @@ describe('andbeyond adapter', () => { dntmock.restore(); }); - it('should be a first-price auction', () => { + it('should be a first-price auction', function () { expect(bidRequest).to.have.property('at', 1); }); - it('should have banner object', () => { + it('should have banner object', function () { expect(bidRequest.imp[0]).to.have.property('banner'); }); - it('should have w/h', () => { + it('should have w/h', function () { expect(bidRequest.imp[0].banner).to.have.property('format'); expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); }); - it('should respect secure connection', () => { + it('should respect secure connection', function () { expect(bidRequest.imp[0]).to.have.property('secure', 1); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); - it('should create proper site block', () => { + it('should create proper site block', function () { expect(bidRequest.site).to.have.property('domain', 'example.com'); expect(bidRequest.site).to.have.property('page', 'https://example.com/index.html'); }); - it('should fill device with caller macro', () => { + it('should fill device with caller macro', function () { expect(bidRequest).to.have.property('device'); expect(bidRequest.device).to.have.property('ip', 'caller'); expect(bidRequest.device).to.have.property('ua', 'caller'); @@ -151,15 +151,15 @@ describe('andbeyond adapter', () => { }); }); - describe('requests routing', () => { - it('should issue a request for each host', () => { + describe('requests routing', function () { + it('should issue a request for each host', function () { let pbRequests = spec.buildRequests([bid1_zone1, bid3_host2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string(`//${bid1_zone1.params.host}/`); expect(pbRequests[1].url).to.have.string(`//${bid3_host2.params.host}/`); }); - it('should issue a request for each zone', () => { + it('should issue a request for each zone', function () { let pbRequests = spec.buildRequests([bid1_zone1, bid2_zone2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].data.zone).to.be.equal(bid1_zone1.params.zoneId); @@ -167,8 +167,8 @@ describe('andbeyond adapter', () => { }); }); - describe('responses processing', () => { - it('should return fully-initialized banner bid-response', () => { + describe('responses processing', function () { + it('should return fully-initialized banner bid-response', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; expect(resp).to.have.property('requestId', 'Bid_01'); @@ -183,20 +183,20 @@ describe('andbeyond adapter', () => { expect(resp.ad).to.have.string(''); }); - it('should add nurl as pixel for banner response', () => { + it('should add nurl as pixel for banner response', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; let expectedNurl = bidResponse1.seatbid[0].bid[0].nurl + '&px=1'; expect(resp.ad).to.have.string(expectedNurl); }); - it('should handle bidresponse with user-sync only', () => { + it('should handle bidresponse with user-sync only', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: usersyncOnlyResponse}, request); expect(resp).to.have.length(0); }); - it('should perform usersync', () => { + it('should perform usersync', function () { let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: bidResponse1}]); expect(syncs).to.have.length(0); syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: bidResponse1}]); diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index bc42f69ce63..396ebf36c7d 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -75,7 +75,7 @@ let getPixels = () => { '\');'; }; -describe('AolAdapter', () => { +describe('AolAdapter', function () { const MARKETPLACE_URL = '//adserver-us.adtech.advertising.com/pubapi/3.0/'; const NEXAGE_URL = '//hb.nexage.com/bidRequest?'; const ONE_DISPLAY_TTL = 60; @@ -92,7 +92,7 @@ describe('AolAdapter', () => { return bidderRequest; } - describe('interpretResponse()', () => { + describe('interpretResponse()', function () { let bidderSettingsBackup; let bidResponse; let bidRequest; @@ -100,7 +100,7 @@ describe('AolAdapter', () => { let formatPixelsStub; let isOneMobileBidderStub; - beforeEach(() => { + beforeEach(function () { bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; bidRequest = { bidderCode: 'test-bidder-code', @@ -115,14 +115,14 @@ describe('AolAdapter', () => { isOneMobileBidderStub = sinon.stub(spec, 'isOneMobileBidder'); }); - afterEach(() => { + afterEach(function () { $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; logWarnSpy.restore(); formatPixelsStub.restore(); isOneMobileBidderStub.restore(); }); - it('should return formatted bid response with required properties', () => { + it('should return formatted bid response with required properties', function () { let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); expect(formattedBidResponse).to.deep.equal({ bidderCode: bidRequest.bidderCode, @@ -140,7 +140,7 @@ describe('AolAdapter', () => { }); }); - it('should add pixels to ad content when pixels are present in the response', () => { + it('should add pixels to ad content when pixels are present in the response', function () { bidResponse.body.ext = { pixels: 'pixels-content' }; @@ -162,24 +162,24 @@ describe('AolAdapter', () => { }); }); - describe('buildRequests()', () => { - it('method exists and is a function', () => { + describe('buildRequests()', function () { + it('method exists and is a function', function () { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); - describe('Marketplace', () => { - it('should not return request when no bids are present', () => { + describe('Marketplace', function () { + it('should not return request when no bids are present', function () { let [request] = spec.buildRequests([]); expect(request).to.be.empty; }); - it('should return request for Marketplace endpoint', () => { + it('should return request for Marketplace endpoint', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).to.contain(MARKETPLACE_URL); }); - it('should return request for Marketplace via onedisplay bidder code', () => { + it('should return request for Marketplace via onedisplay bidder code', function () { let bidRequest = createCustomBidRequest({ bids: [{ bidder: 'onedisplay' @@ -233,7 +233,7 @@ describe('AolAdapter', () => { expect(request).to.be.empty; }); - it('should return Marketplace URL for eu region', () => { + it('should return Marketplace URL for eu region', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -245,7 +245,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); }); - it('should return Marketplace URL for eu region when server option is present', () => { + it('should return Marketplace URL for eu region when server option is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -257,7 +257,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); }); - it('should return default Marketplace URL in case of unknown region config option', () => { + it('should return default Marketplace URL in case of unknown region config option', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -269,25 +269,25 @@ describe('AolAdapter', () => { expect(request.url).to.contain(MARKETPLACE_URL); }); - it('should return url with pubapi bid option', () => { + it('should return url with pubapi bid option', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).to.contain('cmd=bid;'); }); - it('should return url with version 2 of pubapi', () => { + it('should return url with version 2 of pubapi', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).to.contain('v=2;'); }); - it('should return url with cache busting option', () => { + it('should return url with cache busting option', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).to.match(/misc=\d+/); }); - it('should return url with default pageId and sizeId', () => { + it('should return url with default pageId and sizeId', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -298,7 +298,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('/pubapi/3.0/9599.1/1234567/0/0/ADTECH;'); }); - it('should return url with custom pageId and sizeId when options are present', () => { + it('should return url with custom pageId and sizeId when options are present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -311,13 +311,13 @@ describe('AolAdapter', () => { expect(request.url).to.contain('/pubapi/3.0/9599.1/1234567/1111/2222/ADTECH;'); }); - it('should return url with default alias if alias param is missing', () => { + it('should return url with default alias if alias param is missing', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).to.match(/alias=\w+?;/); }); - it('should return url with custom alias if it is present', () => { + it('should return url with custom alias if it is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -329,13 +329,13 @@ describe('AolAdapter', () => { expect(request.url).to.contain('alias=desktop_articlepage_something_box_300_250'); }); - it('should return url without bidfloor option if is is missing', () => { + it('should return url without bidfloor option if is is missing', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).not.to.contain('bidfloor='); }); - it('should return url with bidFloor option if it is present', () => { + it('should return url with bidFloor option if it is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -347,7 +347,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('bidfloor=0.8'); }); - it('should return url with key values if keyValues param is present', () => { + it('should return url with key values if keyValues param is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -363,7 +363,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('kvage=25;kvheight=3.42;kvtest=key'); }); - it('should return request object for One Display when configuration is present', () => { + it('should return request object for One Display when configuration is present', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); expect(request.method).to.equal('GET'); @@ -371,8 +371,8 @@ describe('AolAdapter', () => { }); }); - describe('One Mobile', () => { - it('should return One Mobile url when One Mobile get params are present', () => { + describe('One Mobile', function () { + it('should return One Mobile url when One Mobile get params are present', function () { let bidRequest = createCustomBidRequest({ params: getNexageGetBidParams() }); @@ -380,7 +380,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain(NEXAGE_URL); }); - it('should return One Mobile url with different host when host option is present', () => { + it('should return One Mobile url with different host when host option is present', function () { let bidParams = Object.assign({ host: 'qa-hb.nexage.com' }, getNexageGetBidParams()); @@ -391,7 +391,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('qa-hb.nexage.com/bidRequest?'); }); - it('should return One Mobile url when One Mobile and Marketplace params are present', () => { + it('should return One Mobile url when One Mobile and Marketplace params are present', function () { let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); let bidRequest = createCustomBidRequest({ params: bidParams @@ -425,7 +425,7 @@ describe('AolAdapter', () => { expect(request).to.be.empty; }); - it('should return One Mobile url with required params - dcn & pos', () => { + it('should return One Mobile url with required params - dcn & pos', function () { let bidRequest = createCustomBidRequest({ params: getNexageGetBidParams() }); @@ -433,7 +433,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain(NEXAGE_URL + 'dcn=2c9d2b50015c5ce9db6aeeed8b9500d6&pos=header'); }); - it('should return One Mobile url with cmd=bid option', () => { + it('should return One Mobile url with cmd=bid option', function () { let bidRequest = createCustomBidRequest({ params: getNexageGetBidParams() }); @@ -441,7 +441,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('cmd=bid'); }); - it('should return One Mobile url with generic params if ext option is present', () => { + it('should return One Mobile url with generic params if ext option is present', function () { let bidRequest = createCustomBidRequest({ params: { dcn: '54321123', @@ -459,7 +459,7 @@ describe('AolAdapter', () => { '¶m1=val1¶m2=val2¶m3=val3¶m4=val4'); }); - it('should return request object for One Mobile POST endpoint when POST configuration is present', () => { + it('should return request object for One Mobile POST endpoint when POST configuration is present', function () { let bidConfig = getNexagePostBidParams(); let bidRequest = createCustomBidRequest({ params: bidConfig @@ -491,11 +491,11 @@ describe('AolAdapter', () => { }); }); - describe('getUserSyncs()', () => { + describe('getUserSyncs()', function () { let bidResponse; let bidRequest; - beforeEach(() => { + beforeEach(function () { $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = false; config.setConfig({ aol: { @@ -508,7 +508,7 @@ describe('AolAdapter', () => { }; }); - it('should return user syncs only if userSyncOn equals to "bidResponse"', () => { + it('should return user syncs only if userSyncOn equals to "bidResponse"', function () { let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.true; @@ -518,7 +518,7 @@ describe('AolAdapter', () => { ]); }); - it('should not return user syncs if it has already been returned', () => { + it('should not return user syncs if it has already been returned', function () { $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); @@ -527,7 +527,7 @@ describe('AolAdapter', () => { expect(userSyncs).to.deep.equal([]); }); - it('should not return user syncs if pixels are not present', () => { + it('should not return user syncs if pixels are not present', function () { bidResponse.ext.pixels = null; let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); @@ -537,8 +537,8 @@ describe('AolAdapter', () => { }); }); - describe('formatPixels()', () => { - it('should return pixels wrapped for dropping them once and within nested frames ', () => { + describe('formatPixels()', function () { + it('should return pixels wrapped for dropping them once and within nested frames ', function () { let pixels = ''; let formattedPixels = spec.formatPixels(pixels); @@ -553,30 +553,30 @@ describe('AolAdapter', () => { }); }); - describe('isOneMobileBidder()', () => { - it('should return false when when bidderCode is not present', () => { + describe('isOneMobileBidder()', function () { + it('should return false when when bidderCode is not present', function () { expect(spec.isOneMobileBidder(null)).to.be.false; }); - it('should return false for unknown bidder code', () => { + it('should return false for unknown bidder code', function () { expect(spec.isOneMobileBidder('unknownBidder')).to.be.false; }); - it('should return true for aol bidder code', () => { + it('should return true for aol bidder code', function () { expect(spec.isOneMobileBidder('aol')).to.be.true; }); - it('should return true for one mobile bidder code', () => { + it('should return true for one mobile bidder code', function () { expect(spec.isOneMobileBidder('onemobile')).to.be.true; }); }); - describe('isConsentRequired()', () => { - it('should return false when consentData object is not present', () => { + describe('isConsentRequired()', function () { + it('should return false when consentData object is not present', function () { expect(spec.isConsentRequired(null)).to.be.false; }); - it('should return true when gdprApplies equals true and consentString is not present', () => { + it('should return true when gdprApplies equals true and consentString is not present', function () { let consentData = { consentString: null, gdprApplies: true @@ -585,7 +585,7 @@ describe('AolAdapter', () => { expect(spec.isConsentRequired(consentData)).to.be.true; }); - it('should return false when consentString is present and gdprApplies equals false', () => { + it('should return false when consentString is present and gdprApplies equals false', function () { let consentData = { consentString: 'consent-string', gdprApplies: false @@ -594,7 +594,7 @@ describe('AolAdapter', () => { expect(spec.isConsentRequired(consentData)).to.be.false; }); - it('should return true when consentString is present and gdprApplies equals true', () => { + it('should return true when consentString is present and gdprApplies equals true', function () { let consentData = { consentString: 'consent-string', gdprApplies: true @@ -604,25 +604,25 @@ describe('AolAdapter', () => { }); }); - describe('formatMarketplaceDynamicParams()', () => { + describe('formatMarketplaceDynamicParams()', function () { let formatConsentDataStub; let formatKeyValuesStub; - beforeEach(() => { + beforeEach(function () { formatConsentDataStub = sinon.stub(spec, 'formatConsentData'); formatKeyValuesStub = sinon.stub(spec, 'formatKeyValues'); }); - afterEach(() => { + afterEach(function () { formatConsentDataStub.restore(); formatKeyValuesStub.restore(); }); - it('should return empty string when params are not present', () => { + it('should return empty string when params are not present', function () { expect(spec.formatMarketplaceDynamicParams()).to.be.equal(''); }); - it('should return formatted params when formatConsentData returns data', () => { + it('should return formatted params when formatConsentData returns data', function () { formatConsentDataStub.returns({ euconsent: 'test-consent', gdpr: 1 @@ -630,7 +630,7 @@ describe('AolAdapter', () => { expect(spec.formatMarketplaceDynamicParams()).to.be.equal('euconsent=test-consent;gdpr=1;'); }); - it('should return formatted params when formatKeyValues returns data', () => { + it('should return formatted params when formatKeyValues returns data', function () { formatKeyValuesStub.returns({ param1: 'val1', param2: 'val2', @@ -639,7 +639,7 @@ describe('AolAdapter', () => { expect(spec.formatMarketplaceDynamicParams()).to.be.equal('param1=val1;param2=val2;param3=val3;'); }); - it('should return formatted bid floor param when it is present', () => { + it('should return formatted bid floor param when it is present', function () { let params = { bidFloor: 0.45 }; @@ -647,25 +647,25 @@ describe('AolAdapter', () => { }); }); - describe('formatOneMobileDynamicParams()', () => { + describe('formatOneMobileDynamicParams()', function () { let consentRequiredStub; let secureProtocolStub; - beforeEach(() => { + beforeEach(function () { consentRequiredStub = sinon.stub(spec, 'isConsentRequired'); secureProtocolStub = sinon.stub(spec, 'isSecureProtocol'); }); - afterEach(() => { + afterEach(function () { consentRequiredStub.restore(); secureProtocolStub.restore(); }); - it('should return empty string when params are not present', () => { + it('should return empty string when params are not present', function () { expect(spec.formatOneMobileDynamicParams()).to.be.equal(''); }); - it('should return formatted params when params are present', () => { + it('should return formatted params when params are present', function () { let params = { param1: 'val1', param2: 'val2', @@ -674,7 +674,7 @@ describe('AolAdapter', () => { expect(spec.formatOneMobileDynamicParams(params)).to.contain('¶m1=val1¶m2=val2¶m3=val3'); }); - it('should return formatted gdpr params when isConsentRequired returns true', () => { + it('should return formatted gdpr params when isConsentRequired returns true', function () { let consentData = { consentString: 'test-consent' }; @@ -682,7 +682,7 @@ describe('AolAdapter', () => { expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&gdpr=1&euconsent=test-consent'); }); - it('should return formatted secure param when isSecureProtocol returns true', () => { + it('should return formatted secure param when isSecureProtocol returns true', function () { secureProtocolStub.returns(true); expect(spec.formatOneMobileDynamicParams()).to.be.equal('&secure=1'); }); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index b65988e3ec1..d9e21a95f78 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -5,16 +5,16 @@ import { deepClone } from 'src/utils'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; -describe('AppNexusAdapter', () => { +describe('AppNexusAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'appnexus', 'params': { @@ -27,11 +27,11 @@ describe('AppNexusAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -42,7 +42,7 @@ describe('AppNexusAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -52,7 +52,7 @@ describe('AppNexusAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'appnexus', @@ -67,7 +67,7 @@ describe('AppNexusAdapter', () => { } ]; - it('should parse out private sizes', () => { + it('should parse out private sizes', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -85,7 +85,7 @@ describe('AppNexusAdapter', () => { expect(payload.tags[0].private_sizes).to.deep.equal([{width: 300, height: 250}]); }); - it('should add source and verison to the tag', () => { + 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; @@ -95,7 +95,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should populate the ad_types array on all requests', () => { + it('should populate the ad_types array on all requests', function () { ['banner', 'video', 'native'].forEach(type => { const bidRequest = Object.assign({}, bidRequests[0]); bidRequest.mediaTypes = {}; @@ -108,7 +108,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should populate the ad_types array on outstream requests', () => { + it('should populate the ad_types array on outstream requests', function () { const bidRequest = Object.assign({}, bidRequests[0]); bidRequest.mediaTypes = {}; bidRequest.mediaTypes.video = {context: 'outstream'}; @@ -119,13 +119,13 @@ describe('AppNexusAdapter', () => { expect(payload.tags[0].ad_types).to.deep.equal(['video']); }); - it('sends bid request to ENDPOINT via POST', () => { + 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', () => { + it('should attach valid video params to the tag', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -148,7 +148,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should attach valid user params to the tag', () => { + it('should attach valid user params to the tag', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -171,7 +171,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should attach native params to the request', () => { + it('should attach native params to the request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -198,7 +198,7 @@ describe('AppNexusAdapter', () => { }); }); - it('sets minimum native asset params when not provided on adunit', () => { + it('sets minimum native asset params when not provided on adunit', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -217,7 +217,7 @@ describe('AppNexusAdapter', () => { }); }); - it('does not overwrite native ad unit params with mimimum params', () => { + it('does not overwrite native ad unit params with mimimum params', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -249,7 +249,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should convert keyword params to proper form and attaches to request', () => { + it('should convert keyword params to proper form and attaches to request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -288,7 +288,7 @@ describe('AppNexusAdapter', () => { }]); }); - it('should add payment rules to the request', () => { + it('should add payment rules to the request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -305,7 +305,7 @@ describe('AppNexusAdapter', () => { expect(payload.tags[0].use_pmt_rule).to.equal(true); }); - it('should add gdpr consent information to the request', () => { + it('should add gdpr consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { 'bidderCode': 'appnexus', @@ -327,7 +327,7 @@ describe('AppNexusAdapter', () => { expect(payload.gdpr_consent.consent_required).to.exist.and.to.be.true; }); - it('supports sending hybrid mobile app parameters', () => { + it('supports sending hybrid mobile app parameters', function () { let appRequest = Object.assign({}, bidRequests[0], { @@ -372,7 +372,7 @@ describe('AppNexusAdapter', () => { }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'version': '3.0.0', 'tags': [ @@ -417,7 +417,7 @@ describe('AppNexusAdapter', () => { ] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { 'requestId': '3db3773286ee59', @@ -441,7 +441,7 @@ describe('AppNexusAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'version': '0.0.1', 'tags': [{ @@ -457,7 +457,7 @@ describe('AppNexusAdapter', () => { expect(result.length).to.equal(0); }); - it('handles non-banner media responses', () => { + it('handles non-banner media responses', function () { let response = { 'tags': [{ 'uuid': '84ab500420319d', @@ -481,7 +481,7 @@ describe('AppNexusAdapter', () => { expect(result[0]).to.have.property('mediaType', 'video'); }); - it('handles native responses', () => { + it('handles native responses', function () { let response1 = deepClone(response); response1.tags[0].ads[0].ad_type = 'native'; response1.tags[0].ads[0].rtb.native = { @@ -515,7 +515,7 @@ describe('AppNexusAdapter', () => { expect(result[0].native.image.url).to.equal('http://cdn.adnxs.com/img.png'); }); - it('supports configuring outstream renderers', () => { + 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'; diff --git a/test/spec/modules/arteebeeBidAdapter_spec.js b/test/spec/modules/arteebeeBidAdapter_spec.js index 041b48b0bc9..013e1bd6c0c 100644 --- a/test/spec/modules/arteebeeBidAdapter_spec.js +++ b/test/spec/modules/arteebeeBidAdapter_spec.js @@ -1,9 +1,9 @@ import {expect} from 'chai'; import {spec} from 'modules/arteebeeBidAdapter'; -describe('Arteebee adapater', () => { - describe('Test validate req', () => { - it('should accept minimum valid bid', () => { +describe('Arteebee adapater', function () { + describe('Test validate req', function () { + it('should accept minimum valid bid', function () { let bid = { bidder: 'arteebee', params: { @@ -16,7 +16,7 @@ describe('Arteebee adapater', () => { expect(isValid).to.equal(true); }); - it('should reject missing pub', () => { + it('should reject missing pub', function () { let bid = { bidder: 'arteebee', params: { @@ -28,7 +28,7 @@ describe('Arteebee adapater', () => { expect(isValid).to.equal(false); }); - it('should reject missing source', () => { + it('should reject missing source', function () { let bid = { bidder: 'arteebee', params: { @@ -41,8 +41,8 @@ describe('Arteebee adapater', () => { }); }); - describe('Test build request', () => { - it('minimum request', () => { + describe('Test build request', function () { + it('minimum request', function () { let bid = { bidder: 'arteebee', params: { @@ -59,7 +59,7 @@ describe('Arteebee adapater', () => { expect(req.imp[0]).to.not.have.property('secure'); }); - it('make test request', () => { + it('make test request', function () { let bid = { bidder: 'arteebee', params: { @@ -77,7 +77,7 @@ describe('Arteebee adapater', () => { expect(req.imp[0]).to.not.have.property('secure'); }); - it('test coppa', () => { + it('test coppa', function () { let bid = { bidder: 'arteebee', params: { @@ -95,7 +95,7 @@ describe('Arteebee adapater', () => { expect(req.imp[0]).to.not.have.property('secure'); }); - it('test gdpr', () => { + it('test gdpr', function () { let bid = { bidder: 'arteebee', params: { @@ -124,8 +124,8 @@ describe('Arteebee adapater', () => { }); }); - describe('Test interpret response', () => { - it('General banner response', () => { + describe('Test interpret response', function () { + it('General banner response', function () { let resp = spec.interpretResponse({ body: { id: 'abcd', diff --git a/test/spec/modules/atomxBidAdapter_spec.js b/test/spec/modules/atomxBidAdapter_spec.js index fdbb01a1838..fdcdb55ec7f 100644 --- a/test/spec/modules/atomxBidAdapter_spec.js +++ b/test/spec/modules/atomxBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/atomxBidAdapter'; -describe('atomxAdapterTest', () => { - describe('bidRequestValidity', () => { - it('bidRequest with id param', () => { +describe('atomxAdapterTest', function () { + describe('bidRequestValidity', function () { + it('bidRequest with id param', function () { expect(spec.isBidRequestValid({ bidder: 'atomx', params: { @@ -12,7 +12,7 @@ describe('atomxAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with no id param', () => { + it('bidRequest with no id param', function () { expect(spec.isBidRequestValid({ bidder: 'atomx', params: { @@ -21,7 +21,7 @@ describe('atomxAdapterTest', () => { }); }); - describe('bidRequest', () => { + describe('bidRequest', function () { const bidRequests = [{ 'bidder': 'atomx', 'params': { @@ -47,21 +47,21 @@ describe('atomxAdapterTest', () => { 'auctionId': 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' }]; - it('bidRequest HTTP method', () => { + it('bidRequest HTTP method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); - it('bidRequest url', () => { + it('bidRequest url', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.url).to.match(new RegExp('p\\.ato\\.mx/placement')); }); }); - it('bidRequest data', () => { + it('bidRequest data', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].data.id).to.equal('123'); expect(requests[0].data.size).to.equal('300x250'); @@ -72,7 +72,7 @@ describe('atomxAdapterTest', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequest = { 'method': 'GET', 'url': 'https://p.ato.mx/placement', @@ -103,7 +103,7 @@ describe('atomxAdapterTest', () => { headers: {} }; - it('result is correct', () => { + it('result is correct', function () { const result = spec.interpretResponse(bidResponse, bidRequest); expect(result[0].requestId).to.equal('22aidtbx5eabd9'); diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index 3e6a890e4dc..9e3f37b7395 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -22,34 +22,34 @@ const requestId = 'test-request-id'; const debug = 'adapterver=1.0.1&platform=241394079772386&platver=$prebid.version$'; const pageUrl = encodeURIComponent(utils.getTopWindowUrl()); -describe('AudienceNetwork adapter', () => { - describe('Public API', () => { - it('code', () => { +describe('AudienceNetwork adapter', function () { + describe('Public API', function () { + it('code', function () { expect(code).to.equal(bidder); }); - it('supportedMediaTypes', () => { + it('supportedMediaTypes', function () { expect(supportedMediaTypes).to.deep.equal(['banner', 'video']); }); - it('isBidRequestValid', () => { + it('isBidRequestValid', function () { expect(isBidRequestValid).to.be.a('function'); }); - it('buildRequests', () => { + it('buildRequests', function () { expect(buildRequests).to.be.a('function'); }); - it('interpretResponse', () => { + it('interpretResponse', function () { expect(interpretResponse).to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('missing placementId parameter', () => { + describe('isBidRequestValid', function () { + it('missing placementId parameter', function () { expect(isBidRequestValid({ bidder, sizes: [[300, 250]] })).to.equal(false); }); - it('invalid sizes parameter', () => { + it('invalid sizes parameter', function () { expect(isBidRequestValid({ bidder, sizes: ['', undefined, null, '300x100', [300, 100], [300], {}], @@ -57,7 +57,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(false); }); - it('valid when at least one valid size', () => { + it('valid when at least one valid size', function () { expect(isBidRequestValid({ bidder, sizes: [[1, 1], [300, 250]], @@ -65,7 +65,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('valid parameters', () => { + it('valid parameters', function () { expect(isBidRequestValid({ bidder, sizes: [[300, 250], [320, 50]], @@ -73,7 +73,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('fullwidth', () => { + it('fullwidth', function () { expect(isBidRequestValid({ bidder, sizes: [[300, 250], [336, 280]], @@ -84,7 +84,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('native', () => { + it('native', function () { expect(isBidRequestValid({ bidder, sizes: [[300, 250]], @@ -95,7 +95,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('native with non-IAB size', () => { + it('native with non-IAB size', function () { expect(isBidRequestValid({ bidder, sizes: [[728, 90]], @@ -106,7 +106,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('video', () => { + it('video', function () { expect(isBidRequestValid({ bidder, sizes: [[playerwidth, playerheight]], @@ -118,17 +118,17 @@ describe('AudienceNetwork adapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let isSafariBrowserStub; - before(() => { + before(function () { isSafariBrowserStub = sinon.stub(utils, 'isSafariBrowser'); }); - after(() => { + after(function () { isSafariBrowserStub.restore(); }); - it('can build URL for IAB unit', () => { + it('can build URL for IAB unit', function () { expect(buildRequests([{ bidder, bidId: requestId, @@ -144,7 +144,7 @@ describe('AudienceNetwork adapter', () => { }]); }); - it('can build URL for video unit', () => { + it('can build URL for video unit', function () { expect(buildRequests([{ bidder, bidId: requestId, @@ -163,7 +163,7 @@ describe('AudienceNetwork adapter', () => { }]); }); - it('can build URL for native unit in non-IAB size', () => { + it('can build URL for native unit in non-IAB size', function () { expect(buildRequests([{ bidder, bidId: requestId, @@ -182,7 +182,7 @@ describe('AudienceNetwork adapter', () => { }]); }); - it('can build URL for fullwidth 300x250 unit, overriding platform', () => { + it('can build URL for fullwidth 300x250 unit, overriding platform', function () { const platform = 'test-platform'; const debugPlatform = debug.replace('241394079772386', platform); @@ -205,7 +205,7 @@ describe('AudienceNetwork adapter', () => { }]); }); - it('can build URL on Safari that includes a cachebuster param', () => { + it('can build URL on Safari that includes a cachebuster param', function () { isSafariBrowserStub.returns(true); expect(buildRequests([{ bidder, @@ -216,8 +216,8 @@ describe('AudienceNetwork adapter', () => { }); }); - describe('interpretResponse', () => { - it('error in response', () => { + describe('interpretResponse', function () { + it('error in response', function () { expect(interpretResponse({ body: { errors: ['test-error-message'] @@ -225,7 +225,7 @@ describe('AudienceNetwork adapter', () => { }, {})).to.deep.equal([]); }); - it('valid native bid in response', () => { + it('valid native bid in response', function () { const [bidResponse] = interpretResponse({ body: { errors: [], @@ -264,7 +264,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.fb_placementid).to.equal(placementId); }); - it('valid IAB bid in response', () => { + it('valid IAB bid in response', function () { const [bidResponse] = interpretResponse({ body: { errors: [], @@ -302,7 +302,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.fb_placementid).to.equal(placementId); }); - it('filters invalid slot sizes', () => { + it('filters invalid slot sizes', function () { const [bidResponse] = interpretResponse({ body: { errors: [], @@ -336,7 +336,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.fb_placementid).to.equal(placementId); }); - it('valid multiple bids in response', () => { + it('valid multiple bids in response', function () { const placementIdNative = 'test-placement-id-native'; const placementIdIab = 'test-placement-id-iab'; @@ -395,7 +395,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseIab.fb_placementid).to.equal(placementIdIab); }); - it('valid video bid in response', () => { + it('valid video bid in response', function () { const bidId = 'test-bid-id-video'; const [bidResponse] = interpretResponse({ @@ -426,7 +426,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.height).to.equal(playerheight); }); - it('mixed video and native bids', () => { + it('mixed video and native bids', function () { const videoPlacementId = 'test-video-placement-id'; const videoBidId = 'test-video-bid-id'; const nativePlacementId = 'test-native-placement-id'; @@ -474,7 +474,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseNative.ad).to.contain(`placementid:'${nativePlacementId}',format:'native',bidid:'${nativeBidId}'`); }); - it('mixture of valid native bid and error in response', () => { + it('mixture of valid native bid and error in response', function () { const [bidResponse] = interpretResponse({ body: { errors: ['test-error-message'], diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index fb149d59aee..a70fdfb77b6 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -2,10 +2,10 @@ import { expect } from 'chai'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import * as utils from 'src/utils'; -describe('BeachfrontAdapter', () => { +describe('BeachfrontAdapter', function () { let bidRequests; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'beachfront', @@ -31,13 +31,13 @@ describe('BeachfrontAdapter', () => { ]; }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { const bidRequest = bidRequests[0]; expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the "bidfloor" param is missing', () => { + it('should return false when the "bidfloor" param is missing', function () { const bidRequest = bidRequests[0]; bidRequest.params = { appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' @@ -45,7 +45,7 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when the "appId" param is missing', () => { + it('should return false when the "appId" param is missing', function () { const bidRequest = bidRequests[0]; bidRequest.params = { bidfloor: 5.00 @@ -53,19 +53,19 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { const bidRequest = bidRequests[0]; bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when a bid request is not passed', () => { + 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('for multi-format bids', () => { - it('should return true when the required params are passed for video', () => { + describe('for multi-format bids', function () { + it('should return true when the required params are passed for video', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} @@ -79,7 +79,7 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the required params are missing for video', () => { + it('should return false when the required params are missing for video', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} @@ -93,7 +93,7 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return true when the required params are passed for banner', () => { + it('should return true when the required params are passed for banner', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} @@ -107,7 +107,7 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the required params are missing for banner', () => { + it('should return false when the required params are missing for banner', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} @@ -123,9 +123,9 @@ describe('BeachfrontAdapter', () => { }); }); - describe('spec.buildRequests', () => { - describe('for video bids', () => { - it('should attach the bid request object', () => { + describe('spec.buildRequests', function () { + describe('for video bids', function () { + it('should attach the bid request object', function () { bidRequests[0].mediaTypes = { video: {} }; bidRequests[1].mediaTypes = { video: {} }; const requests = spec.buildRequests(bidRequests); @@ -133,7 +133,7 @@ describe('BeachfrontAdapter', () => { expect(requests[1].bidRequest).to.equal(bidRequests[1]); }); - it('should create a POST request for each bid', () => { + it('should create a POST request for each bid', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const requests = spec.buildRequests([ bidRequest ]); @@ -141,7 +141,7 @@ describe('BeachfrontAdapter', () => { expect(requests[0].url).to.equal(VIDEO_ENDPOINT + bidRequest.params.appId); }); - it('should attach request data', () => { + it('should attach request data', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -164,7 +164,7 @@ describe('BeachfrontAdapter', () => { expect(data.cur).to.deep.equal(['USD']); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -178,7 +178,7 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); }); - it('must parse bid size from a string', () => { + it('must parse bid size from a string', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -192,7 +192,7 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); }); - it('must handle an empty bid size', () => { + it('must handle an empty bid size', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: { @@ -204,7 +204,7 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ w: undefined, h: undefined }); }); - it('must fall back to the size on the bid object', () => { + it('must fall back to the size on the bid object', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -215,7 +215,7 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); }); - it('must override video targeting params', () => { + it('must override video targeting params', function () { const bidRequest = bidRequests[0]; const mimes = ['video/webm']; bidRequest.mediaTypes = { video: {} }; @@ -225,7 +225,7 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ mimes }); }); - it('must add GDPR consent data to the request', () => { + it('must add GDPR consent data to the request', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; @@ -242,15 +242,15 @@ describe('BeachfrontAdapter', () => { }); }); - describe('for banner bids', () => { - it('should attach the bid requests array', () => { + describe('for banner bids', function () { + it('should attach the bid requests array', function () { bidRequests[0].mediaTypes = { banner: {} }; bidRequests[1].mediaTypes = { banner: {} }; const requests = spec.buildRequests(bidRequests); expect(requests[0].bidRequest).to.deep.equal(bidRequests); }); - it('should create a single POST request for all bids', () => { + it('should create a single POST request for all bids', function () { bidRequests[0].mediaTypes = { banner: {} }; bidRequests[1].mediaTypes = { banner: {} }; const requests = spec.buildRequests(bidRequests); @@ -259,7 +259,7 @@ describe('BeachfrontAdapter', () => { expect(requests[0].url).to.equal(BANNER_ENDPOINT); }); - it('should attach request data', () => { + it('should attach request data', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -285,7 +285,7 @@ describe('BeachfrontAdapter', () => { expect(data.ua).to.equal(navigator.userAgent); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -301,7 +301,7 @@ describe('BeachfrontAdapter', () => { ]); }); - it('must parse bid size from a string', () => { + it('must parse bid size from a string', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -317,7 +317,7 @@ describe('BeachfrontAdapter', () => { ]); }); - it('must handle an empty bid size', () => { + it('must handle an empty bid size', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: { @@ -329,7 +329,7 @@ describe('BeachfrontAdapter', () => { expect(data.slots[0].sizes).to.deep.equal([]); }); - it('must fall back to the size on the bid object', () => { + it('must fall back to the size on the bid object', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -340,7 +340,7 @@ describe('BeachfrontAdapter', () => { expect(data.slots[0].sizes).to.deep.contain({ w: width, h: height }); }); - it('must add GDPR consent data to the request', () => { + it('must add GDPR consent data to the request', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; @@ -357,8 +357,8 @@ describe('BeachfrontAdapter', () => { }); }); - describe('for multi-format bids', () => { - it('should create a POST request for each bid format', () => { + describe('for multi-format bids', function () { + it('should create a POST request for each bid format', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -386,7 +386,7 @@ describe('BeachfrontAdapter', () => { expect(requests[1].url).to.contain(BANNER_ENDPOINT); }); - it('must parse bid sizes for each bid format', () => { + it('must parse bid sizes for each bid format', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: { @@ -413,16 +413,16 @@ describe('BeachfrontAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - describe('for video bids', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + describe('for video bids', function () { + it('should return no bids if the response is not valid', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "url" is missing', () => { + it('should return no bids if the response "url" is missing', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const serverResponse = { @@ -432,7 +432,7 @@ describe('BeachfrontAdapter', () => { expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "bidPrice" is missing', () => { + it('should return no bids if the response "bidPrice" is missing', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const serverResponse = { @@ -442,7 +442,7 @@ describe('BeachfrontAdapter', () => { expect(bidResponse.length).to.equal(0); }); - it('should return a valid video bid response', () => { + it('should return a valid video bid response', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -473,7 +473,7 @@ describe('BeachfrontAdapter', () => { }); }); - it('should return a renderer for outstream video bids', () => { + it('should return a renderer for outstream video bids', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: { @@ -493,22 +493,22 @@ describe('BeachfrontAdapter', () => { }); }); - describe('for banner bids', () => { - it('should return no bids if the response is not valid', () => { + 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 }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response is empty', () => { + it('should return no bids if the response is empty', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; const bidResponse = spec.interpretResponse({ body: [] }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return valid banner bid responses', () => { + it('should return valid banner bid responses', function () { bidRequests[0].mediaTypes = { banner: { sizes: [[ 300, 250 ], [ 728, 90 ]] @@ -555,11 +555,11 @@ describe('BeachfrontAdapter', () => { }); }); - describe('spec.getUserSyncs', () => { - describe('for video bids', () => { + describe('spec.getUserSyncs', function () { + describe('for video bids', function () { let bidResponse; - beforeEach(() => { + beforeEach(function () { bidResponse = { bidPrice: 5.00, url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', @@ -567,7 +567,7 @@ describe('BeachfrontAdapter', () => { }; }); - it('should return an iframe user sync if iframes are enabled', () => { + it('should return an iframe user sync if iframes are enabled', function () { const syncOptions = { iframeEnabled: true, pixelEnabled: true @@ -580,7 +580,7 @@ describe('BeachfrontAdapter', () => { expect(userSyncs[0].type).to.equal('iframe'); }); - it('should return an image user sync if iframes are disabled', () => { + it('should return an image user sync if iframes are disabled', function () { const syncOptions = { iframeEnabled: false, pixelEnabled: true @@ -593,7 +593,7 @@ describe('BeachfrontAdapter', () => { expect(userSyncs[0].type).to.equal('image'); }); - it('should not return user syncs if none are enabled', () => { + it('should not return user syncs if none are enabled', function () { const syncOptions = { iframeEnabled: false, pixelEnabled: false @@ -606,10 +606,10 @@ describe('BeachfrontAdapter', () => { }); }); - describe('for banner bids', () => { + describe('for banner bids', function () { let bidResponse; - beforeEach(() => { + beforeEach(function () { bidResponse = { slot: bidRequests[0].adUnitCode, adm: '
', @@ -620,7 +620,7 @@ describe('BeachfrontAdapter', () => { }; }); - it('should return user syncs defined the bid response', () => { + it('should return user syncs defined the bid response', function () { const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; const syncOptions = { iframeEnabled: true, @@ -638,7 +638,7 @@ describe('BeachfrontAdapter', () => { ]); }); - it('should not return user syncs if iframes are disabled', () => { + it('should not return user syncs if iframes are disabled', function () { const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; const syncOptions = { iframeEnabled: false, @@ -654,7 +654,7 @@ describe('BeachfrontAdapter', () => { expect(userSyncs).to.deep.equal([]); }); - it('should not return user syncs if there are none in the bid response', () => { + it('should not return user syncs if there are none in the bid response', function () { const syncOptions = { iframeEnabled: true, pixelEnabled: true diff --git a/test/spec/modules/betweenBidAdapter_spec.js b/test/spec/modules/betweenBidAdapter_spec.js index a99417067f8..b1eea08a147 100644 --- a/test/spec/modules/betweenBidAdapter_spec.js +++ b/test/spec/modules/betweenBidAdapter_spec.js @@ -1,8 +1,8 @@ import { expect } from 'chai'; import { spec } from 'modules/betweenBidAdapter'; -describe('betweenBidAdapterTests', () => { - it('validate_pub_params', () => { +describe('betweenBidAdapterTests', function () { + it('validate_pub_params', function () { expect(spec.isBidRequestValid({ bidder: 'between', params: { @@ -13,7 +13,7 @@ describe('betweenBidAdapterTests', () => { } })).to.equal(true); }); - it('validate_generated_params', () => { + it('validate_generated_params', function () { let bidRequestData = [{ bidId: 'bid1234', bidder: 'between', @@ -24,7 +24,7 @@ describe('betweenBidAdapterTests', () => { let req_data = request[0].data; expect(req_data.bidid).to.equal('bid1234'); }); - it('validate_response_params', () => { + it('validate_response_params', function () { let serverResponse = { body: [{ bidid: 'bid1234', diff --git a/test/spec/modules/bizzclickBidAdapter_spec.js b/test/spec/modules/bizzclickBidAdapter_spec.js index 39587791bba..6f518f32ccf 100644 --- a/test/spec/modules/bizzclickBidAdapter_spec.js +++ b/test/spec/modules/bizzclickBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/bizzclickBidAdapter'; -describe('BizzclickBidAdapter', () => { +describe('BizzclickBidAdapter', function () { let bid = { bidId: '67d581a232281d', bidder: 'bizzclickBidAdapter', @@ -16,31 +16,31 @@ describe('BizzclickBidAdapter', () => { transactionId: '3bb2f6da-87a6-4029-aeb0-1b244bbfb5' }; - describe('isBidRequestValid', () => { - it('Should return true when placement_id can be cast to a number', () => { + describe('isBidRequestValid', function () { + it('Should return true when placement_id can be cast to a number', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false when placement_id is not a number', () => { + it('Should return false when placement_id is not a number', function () { bid.params.placementId = 'aaa'; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + 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', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//supply.bizzclick.com/?c=o&m=multi'); }); - it('Returns valid data if array of bids is valid', () => { + 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', 'secure', 'host', 'page', 'placements'); @@ -59,13 +59,13 @@ describe('BizzclickBidAdapter', () => { expect(placement.sizes).to.be.an('array'); } }); - it('Returns empty data if no valid requests are passed', () => { + 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', () => { + describe('interpretResponse', function () { let resObject = { body: [ { requestId: '123', @@ -81,7 +81,7 @@ describe('BizzclickBidAdapter', () => { }] }; let serverResponses = spec.interpretResponse(resObject); - it('Returns an array of valid server responses if response object is valid', () => { + it('Returns an array of valid server responses if response object is valid', function () { expect(serverResponses).to.be.an('array').that.is.not.empty; for (let i = 0; i < serverResponses.length; i++) { let dataItem = serverResponses[i]; @@ -97,16 +97,16 @@ describe('BizzclickBidAdapter', () => { expect(dataItem.currency).to.be.a('string'); expect(dataItem.mediaType).to.be.a('string'); } - it('Returns an empty array if invalid response is passed', () => { + it('Returns an empty array if invalid response is passed', function () { serverResponses = spec.interpretResponse('invalid_response'); expect(serverResponses).to.be.an('array').that.is.empty; }); }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let userSync = spec.getUserSyncs(); - it('Returns valid URL and type', () => { + 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; diff --git a/test/spec/modules/brainyBidAdapter_spec.js b/test/spec/modules/brainyBidAdapter_spec.js index 157356e82db..a3ce90d927a 100644 --- a/test/spec/modules/brainyBidAdapter_spec.js +++ b/test/spec/modules/brainyBidAdapter_spec.js @@ -64,17 +64,17 @@ const invalidSyncBidResponse = [{ } }]; -describe('brainy Adapter', () => { - describe('request', () => { - it('should validate bid request', () => { +describe('brainy Adapter', function () { + describe('request', function () { + it('should validate bid request', function () { expect(spec.isBidRequestValid(validBidReq)).to.equal(true); }); - it('should not validate incorrect bid request', () => { + it('should not validate incorrect bid request', function () { expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); }); }); - describe('build request', () => { - it('Verify bid request', () => { + describe('build request', function () { + it('Verify bid request', function () { const request = spec.buildRequests(bidReq); expect(request[0].method).to.equal('GET'); expect(request[0].url).to.equal(URL); @@ -83,14 +83,14 @@ describe('brainy Adapter', () => { }); }); - describe('interpretResponse', () => { - it('should build bid array', () => { + describe('interpretResponse', function () { + it('should build bid array', function () { const request = spec.buildRequests(bidReq); const result = spec.interpretResponse({body: bidResponse}, request[0]); expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const request = spec.buildRequests(bidReq); const result = spec.interpretResponse({body: bidResponse}, request[0]); const bid = result[0]; @@ -101,25 +101,25 @@ describe('brainy Adapter', () => { }); }); - describe('spec.getUserSyncs', () => { + describe('spec.getUserSyncs', function () { let syncOptions - beforeEach(() => { + beforeEach(function () { syncOptions = { enabledBidders: ['brainy'], pixelEnabled: true } }); - it('sucess with usersync url', () => { + it('sucess with usersync url', function () { const result = []; result.push({type: 'image', url: '//testparm.com/ssp-sync/p/sync?uid=2110180601155125000059&buyer=2&slot=34'}); expect(spec.getUserSyncs(syncOptions, bidSyncResponse)).to.deep.equal(result); }); - it('sucess without usersync url', () => { + it('sucess without usersync url', function () { const result = []; expect(spec.getUserSyncs(syncOptions, invalidSyncBidResponse)).to.deep.equal(result); }); - it('empty response', () => { + it('empty response', function () { const serverResponse = [{body: {}}]; const result = []; expect(spec.getUserSyncs(syncOptions, serverResponse)).to.deep.equal(result); diff --git a/test/spec/modules/bridgewellBidAdapter_spec.js b/test/spec/modules/bridgewellBidAdapter_spec.js index 5dae3c474ac..6ca9675a1bb 100644 --- a/test/spec/modules/bridgewellBidAdapter_spec.js +++ b/test/spec/modules/bridgewellBidAdapter_spec.js @@ -169,13 +169,13 @@ describe('bridgewellBidAdapter', function () { ]; const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bidWithoutCpmWeight = { 'bidder': 'bridgewell', 'params': { @@ -227,18 +227,18 @@ describe('bridgewellBidAdapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bidWithoutCpmWeight)).to.equal(true); expect(spec.isBidRequestValid(bidWithCorrectCpmWeight)).to.equal(true); expect(spec.isBidRequestValid(bidWithUncorrectCpmWeight)).to.equal(false); expect(spec.isBidRequestValid(bidWithZeroCpmWeight)).to.equal(false); }); - it('should return false when required params not found', () => { + it('should return false when required params not found', function () { expect(spec.isBidRequestValid({})).to.equal(false); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bidWithoutCpmWeight = Object.assign({}, bidWithoutCpmWeight); let bidWithCorrectCpmWeight = Object.assign({}, bidWithCorrectCpmWeight); let bidWithUncorrectCpmWeight = Object.assign({}, bidWithUncorrectCpmWeight); @@ -272,8 +272,8 @@ describe('bridgewellBidAdapter', function () { }); }); - describe('buildRequests', () => { - it('should attach valid params to the tag', () => { + describe('buildRequests', function () { + it('should attach valid params to the tag', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; const adUnits = payload.adUnits; @@ -286,14 +286,14 @@ describe('bridgewellBidAdapter', function () { } }); - it('should attach validBidRequests to the tag', () => { + it('should attach validBidRequests to the tag', function () { const request = spec.buildRequests(bidRequests); const validBidRequests = request.validBidRequests; expect(validBidRequests).to.deep.equal(bidRequests); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const request = spec.buildRequests(bidRequests); const serverResponses = [ { @@ -440,7 +440,7 @@ describe('bridgewellBidAdapter', function () { } ]; - it('should return all required parameters', () => { + it('should return all required parameters', function () { const result = spec.interpretResponse({'body': serverResponses}, request); result.every(res => expect(res.cpm).to.be.a('number')); result.every(res => expect(res.width).to.be.a('number')); @@ -457,12 +457,12 @@ describe('bridgewellBidAdapter', function () { }); }); - it('should give up bid if server response is undefiend', () => { + it('should give up bid if server response is undefiend', function () { const result = spec.interpretResponse({'body': undefined}, request); expect(result).to.deep.equal([]); }); - it('should give up bid if request sizes is missing', () => { + it('should give up bid if request sizes is missing', function () { let target = Object.assign({}, serverResponses[0]); target.consumed = false; const result = spec.interpretResponse({'body': [target]}, spec.buildRequests([{ @@ -478,7 +478,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if response sizes is invalid', () => { + it('should give up bid if response sizes is invalid', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -495,7 +495,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if cpm is missing', () => { + it('should give up bid if cpm is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -511,7 +511,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if width or height is missing', () => { + it('should give up bid if width or height is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -526,7 +526,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if ad is missing', () => { + it('should give up bid if ad is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -543,7 +543,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if revenue mode is missing', () => { + it('should give up bid if revenue mode is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -559,7 +559,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if currency is missing', () => { + it('should give up bid if currency is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -575,7 +575,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if mediaType is missing', () => { + it('should give up bid if mediaType is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -592,7 +592,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if property native of mediaType native is missing', () => { + it('should give up bid if property native of mediaType native is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -609,7 +609,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native title is missing', () => { + it('should give up bid if native title is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -643,7 +643,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native title is too long', () => { + it('should give up bid if native title is too long', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -678,7 +678,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native body is missing', () => { + it('should give up bid if native body is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -711,7 +711,7 @@ describe('bridgewellBidAdapter', function () { const result = spec.interpretResponse({'body': [target]}, request); expect(result).to.deep.equal([]); - it('should give up bid if native image url is missing', () => { + it('should give up bid if native image url is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -746,7 +746,7 @@ describe('bridgewellBidAdapter', function () { }); }); - it('should give up bid if native image is missing', () => { + it('should give up bid if native image is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -776,7 +776,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native image url is missing', () => { + it('should give up bid if native image url is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -808,7 +808,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native image sizes is unmatch', () => { + it('should give up bid if native image sizes is unmatch', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -841,7 +841,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native sponsoredBy is missing', () => { + it('should give up bid if native sponsoredBy is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -875,7 +875,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native icon is missing', () => { + it('should give up bid if native icon is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -905,7 +905,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native icon url is missing', () => { + it('should give up bid if native icon url is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -939,7 +939,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native icon sizes is unmatch', () => { + it('should give up bid if native icon sizes is unmatch', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -972,7 +972,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native clickUrl is missing', () => { + it('should give up bid if native clickUrl is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1006,7 +1006,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native clickTrackers is missing', () => { + it('should give up bid if native clickTrackers is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1040,7 +1040,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native clickTrackers is empty', () => { + it('should give up bid if native clickTrackers is empty', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1075,7 +1075,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native impressionTrackers is missing', () => { + it('should give up bid if native impressionTrackers is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1109,7 +1109,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native impressionTrackers is empty', () => { + it('should give up bid if native impressionTrackers is empty', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1144,7 +1144,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if mediaType is not support', () => { + it('should give up bid if mediaType is not support', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', diff --git a/test/spec/modules/c1xBidAdapter_spec.js b/test/spec/modules/c1xBidAdapter_spec.js index bd7fa5df669..268ad46d0ce 100644 --- a/test/spec/modules/c1xBidAdapter_spec.js +++ b/test/spec/modules/c1xBidAdapter_spec.js @@ -5,16 +5,16 @@ import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = 'https://ht.c1exchange.com/ht'; const BIDDER_CODE = 'c1x'; -describe('C1XAdapter', () => { +describe('C1XAdapter', function () { const adapter = newBidder(c1xAdapter); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': BIDDER_CODE, 'adUnitCode': 'adunit-code', @@ -24,11 +24,11 @@ describe('C1XAdapter', () => { } }; - it('should return true when required params are passed', () => { + it('should return true when required params are passed', function () { expect(c1xAdapter.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not found', () => { + it('should return false when required params are not found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('C1XAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': BIDDER_CODE, @@ -61,19 +61,19 @@ describe('C1XAdapter', () => { return parsedData; }; - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const request = c1xAdapter.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET'); }); - it('should generate correct bid Id tag', () => { + it('should generate correct bid Id tag', function () { const request = c1xAdapter.buildRequests(bidRequests); expect(request.bids[0].adUnitCode).to.equal('adunit-code'); expect(request.bids[0].bidId).to.equal('30b31c1838de1e'); }); - it('should convert params to proper form and attach to request', () => { + it('should convert params to proper form and attach to request', function () { const request = c1xAdapter.buildRequests(bidRequests); const originalPayload = parseRequest(request.data); const payloadObj = JSON.parse(originalPayload); @@ -83,7 +83,7 @@ describe('C1XAdapter', () => { expect(payloadObj.site).to.equal('9999'); }); - it('should convert floor price to proper form and attach to request', () => { + it('should convert floor price to proper form and attach to request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -100,7 +100,7 @@ describe('C1XAdapter', () => { expect(payloadObj.a1p).to.equal('4.35'); }); - it('should convert pageurl to proper form and attach to request', () => { + it('should convert pageurl to proper form and attach to request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -115,7 +115,7 @@ describe('C1XAdapter', () => { expect(payloadObj.pageurl).to.equal('http://c1exchange.com/'); }); - it('should convert GDPR Consent to proper form and attach to request', () => { + it('should convert GDPR Consent to proper form and attach to request', function () { let consentString = 'BOP2gFWOQIFovABABAENBGAAAAAAMw'; let bidderRequest = { 'bidderCode': 'c1x', @@ -134,7 +134,7 @@ describe('C1XAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'bid': true, 'cpm': 1.5, @@ -146,7 +146,7 @@ describe('C1XAdapter', () => { 'bidType': 'GROSS_BID' }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { width: 300, @@ -169,7 +169,7 @@ describe('C1XAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { bid: false, adId: 'c1x-test' diff --git a/test/spec/modules/ccxBidAdapter_spec.js b/test/spec/modules/ccxBidAdapter_spec.js index 535b3906a27..292503c9e04 100644 --- a/test/spec/modules/ccxBidAdapter_spec.js +++ b/test/spec/modules/ccxBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { spec } from 'modules/ccxBidAdapter'; import * as utils from 'src/utils'; -describe('ccxAdapter', () => { +describe('ccxAdapter', function () { let bids = [ { adUnitCode: 'banner', @@ -39,17 +39,17 @@ describe('ccxAdapter', () => { transactionId: 'aefddd38-cfa0-48ab-8bdd-325de4bab5f9' } ]; - describe('isBidRequestValid', () => { - it('Valid bid requests', () => { + describe('isBidRequestValid', function () { + it('Valid bid requests', function () { expect(spec.isBidRequestValid(bids[0])).to.be.true; expect(spec.isBidRequestValid(bids[1])).to.be.true; }); - it('Invalid bid reqeusts - no placementId', () => { + it('Invalid bid reqeusts - no placementId', function () { let bidsClone = utils.deepClone(bids); bidsClone[0].params = undefined; expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; }); - it('Invalid bid reqeusts - invalid banner sizes', () => { + it('Invalid bid reqeusts - invalid banner sizes', function () { let bidsClone = utils.deepClone(bids); bidsClone[0].mediaTypes.banner.sizes = [300, 250]; expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; @@ -58,14 +58,14 @@ describe('ccxAdapter', () => { bidsClone[0].mediaTypes.banner.sizes = []; expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; }); - it('Invalid bid reqeusts - invalid video sizes', () => { + it('Invalid bid reqeusts - invalid video sizes', function () { let bidsClone = utils.deepClone(bids); bidsClone[1].mediaTypes.video.playerSize = []; expect(spec.isBidRequestValid(bidsClone[1])).to.be.false; bidsClone[1].mediaTypes.video.sizes = [640, 480]; expect(spec.isBidRequestValid(bidsClone[1])).to.be.false; }); - it('Valid bid reqeust - old style sizes', () => { + it('Valid bid reqeust - old style sizes', function () { let bidsClone = utils.deepClone(bids); delete (bidsClone[0].mediaTypes); delete (bidsClone[1].mediaTypes); diff --git a/test/spec/modules/clickforceBidAdapter_spec.js b/test/spec/modules/clickforceBidAdapter_spec.js index c09b69a6320..3d4fc70c057 100644 --- a/test/spec/modules/clickforceBidAdapter_spec.js +++ b/test/spec/modules/clickforceBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/clickforceBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('ClickforceAdapter', () => { +describe('ClickforceAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'clickforce', 'params': { @@ -26,11 +26,11 @@ describe('ClickforceAdapter', () => { 'auctionId': '1d1a030790a475' }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,7 +40,7 @@ describe('ClickforceAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [{ 'bidder': 'clickforce', 'params': { @@ -57,12 +57,12 @@ describe('ClickforceAdapter', () => { const request = spec.buildRequests(bidRequests); - it('sends bid request to our endpoint via POST', () => { + it('sends bid request to our endpoint via POST', function () { expect(request.method).to.equal('POST'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = [{ 'cpm': 0.5, 'width': '300', @@ -147,19 +147,19 @@ describe('ClickforceAdapter', () => { } }]; - it('should get the correct bid response by display ad', () => { + it('should get the correct bid response by display ad', function () { let bidderRequest; let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('should get the correct bid response by native ad', () => { + it('should get the correct bid response by native ad', function () { let bidderRequest; let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse1[0])); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: {} }; @@ -168,8 +168,8 @@ describe('ClickforceAdapter', () => { }); }); - describe('getUserSyncs function', () => { - it('should register type is iframe', () => { + describe('getUserSyncs function', function () { + it('should register type is iframe', function () { const syncOptions = { 'iframeEnabled': 'true' } @@ -178,7 +178,7 @@ describe('ClickforceAdapter', () => { expect(userSync[0].url).to.equal('https://cdn.doublemax.net/js/capmapping.htm'); }); - it('should register type is image', () => { + it('should register type is image', function () { const syncOptions = { 'pixelEnabled': 'true' } diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js index 54952fbf4b5..62b4158676e 100644 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ b/test/spec/modules/colossussspBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/colossussspBidAdapter'; -describe('ColossussspAdapter', () => { +describe('ColossussspAdapter', function () { let bid = { bidId: '2dd581a2b6281d', bidder: 'colossusssp', @@ -15,31 +15,31 @@ describe('ColossussspAdapter', () => { transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' }; - describe('isBidRequestValid', () => { - it('Should return true when placement_id can be cast to a number', () => { + describe('isBidRequestValid', function () { + it('Should return true when placement_id can be cast to a number', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false when placement_id is not a number', () => { + it('Should return false when placement_id is not a number', function () { bid.params.placement_id = 'aaa'; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + 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', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//colossusssp.com/?c=o&m=multi'); }); - it('Returns valid data if array of bids is valid', () => { + 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'); @@ -59,13 +59,13 @@ describe('ColossussspAdapter', () => { expect(placement.sizes).to.be.an('array'); } }); - it('Returns empty data if no valid requests are passed', () => { + 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', () => { + describe('interpretResponse', function () { let resObject = { body: [ { requestId: '123', @@ -81,7 +81,7 @@ describe('ColossussspAdapter', () => { } ] }; let serverResponses = spec.interpretResponse(resObject); - it('Returns an array of valid server responses if response object is valid', () => { + it('Returns an array of valid server responses if response object is valid', function () { expect(serverResponses).to.be.an('array').that.is.not.empty; for (let i = 0; i < serverResponses.length; i++) { let dataItem = serverResponses[i]; @@ -98,16 +98,16 @@ describe('ColossussspAdapter', () => { expect(dataItem.currency).to.be.a('string'); expect(dataItem.mediaType).to.be.a('string'); } - it('Returns an empty array if invalid response is passed', () => { + it('Returns an empty array if invalid response is passed', function () { serverResponses = spec.interpretResponse('invalid_response'); expect(serverResponses).to.be.an('array').that.is.empty; }); }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let userSync = spec.getUserSyncs(); - it('Returns valid URL and type', () => { + 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; diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index fe6bfc1ebfd..baa9a43f6aa 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -7,18 +7,18 @@ let assert = require('chai').assert; let expect = require('chai').expect; describe('consentManagement', function () { - describe('setConfig tests:', () => { - describe('empty setConfig value', () => { - beforeEach(() => { + describe('setConfig tests:', function () { + describe('empty setConfig value', function () { + beforeEach(function () { sinon.stub(utils, 'logInfo'); }); - afterEach(() => { + afterEach(function () { utils.logInfo.restore(); config.resetConfig(); }); - it('should use system default values', () => { + it('should use system default values', function () { setConfig({}); expect(userCMP).to.be.equal('iab'); expect(consentTimeout).to.be.equal(10000); @@ -27,12 +27,12 @@ describe('consentManagement', function () { }); }); - describe('valid setConfig value', () => { - afterEach(() => { + describe('valid setConfig value', function () { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); }); - it('results in all user settings overriding system defaults', () => { + it('results in all user settings overriding system defaults', function () { let allConfig = { cmpApi: 'iab', timeout: 7500, @@ -47,7 +47,7 @@ describe('consentManagement', function () { }); }); - describe('requestBidsHook tests:', () => { + describe('requestBidsHook tests:', function () { let goodConfigWithCancelAuction = { cmpApi: 'iab', timeout: 7500, @@ -62,19 +62,19 @@ describe('consentManagement', function () { let didHookReturn; - afterEach(() => { + afterEach(function () { gdprDataHandler.consentData = null; resetConsentData(); }); - describe('error checks:', () => { - beforeEach(() => { + describe('error checks:', function () { + beforeEach(function () { didHookReturn = false; sinon.stub(utils, 'logWarn'); sinon.stub(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { utils.logWarn.restore(); utils.logError.restore(); config.resetConfig(); @@ -82,7 +82,7 @@ describe('consentManagement', function () { resetConsentData(); }); - it('should throw a warning and return to hooked function when an unknown CMP framework ID is used', () => { + it('should throw a warning and return to hooked function when an unknown CMP framework ID is used', function () { let badCMPConfig = { cmpApi: 'bad' }; @@ -98,7 +98,7 @@ describe('consentManagement', function () { expect(consent).to.be.null; }); - it('should throw proper errors when CMP is not found', () => { + it('should throw proper errors when CMP is not found', function () { setConfig(goodConfigWithCancelAuction); requestBidsHook({}, () => { @@ -112,15 +112,15 @@ describe('consentManagement', function () { }); }); - describe('already known consentData:', () => { + describe('already known consentData:', function () { let cmpStub = sinon.stub(); - beforeEach(() => { + beforeEach(function () { didHookReturn = false; window.__cmp = function() {}; }); - afterEach(() => { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); cmpStub.restore(); @@ -128,7 +128,7 @@ describe('consentManagement', function () { resetConsentData(); }); - it('should bypass CMP and simply use previously stored consentData', () => { + it('should bypass CMP and simply use previously stored consentData', function () { let testConsentData = { gdprApplies: true, consentData: 'xyz' @@ -158,10 +158,10 @@ describe('consentManagement', function () { }); }); - describe('CMP workflow for safeframe page', () => { + describe('CMP workflow for safeframe page', function () { let registerStub = sinon.stub(); - beforeEach(() => { + beforeEach(function () { didHookReturn = false; window.$sf = { ext: { @@ -173,7 +173,7 @@ describe('consentManagement', function () { sinon.stub(utils, 'logWarn'); }); - afterEach(() => { + afterEach(function () { delete window.$sf; config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); @@ -183,7 +183,7 @@ describe('consentManagement', function () { resetConsentData(); }); - it('should return the consent data from a safeframe callback', () => { + it('should return the consent data from a safeframe callback', function () { var testConsentData = { data: { msgName: 'cmpReturn', @@ -215,18 +215,18 @@ describe('consentManagement', function () { }); }); - describe('CMP workflow for iframed page', () => { + describe('CMP workflow for iframed page', function () { let ifr = null; let stringifyResponse = false; - beforeEach(() => { + beforeEach(function () { sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); ifr = createIFrameMarker(); window.addEventListener('message', cmpMessageHandler, false); }); - afterEach(() => { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); delete window.__cmp; @@ -288,17 +288,17 @@ describe('consentManagement', function () { } }); - describe('CMP workflow for normal pages:', () => { + describe('CMP workflow for normal pages:', function () { let cmpStub = sinon.stub(); - beforeEach(() => { + beforeEach(function () { didHookReturn = false; sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); window.__cmp = function() {}; }); - afterEach(() => { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); cmpStub.restore(); @@ -308,7 +308,7 @@ describe('consentManagement', function () { resetConsentData(); }); - it('performs lookup check and stores consentData for a valid existing user', () => { + it('performs lookup check and stores consentData for a valid existing user', function () { let testConsentData = { gdprApplies: true, consentData: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' @@ -331,7 +331,7 @@ describe('consentManagement', function () { expect(consent.gdprApplies).to.be.true; }); - it('throws an error when processCmpData check failed while config had allowAuction set to false', () => { + it('throws an error when processCmpData check failed while config had allowAuction set to false', function () { let testConsentData = {}; let bidsBackHandlerReturn = false; @@ -352,7 +352,7 @@ describe('consentManagement', function () { expect(consent).to.be.null; }); - it('throws a warning + stores consentData + calls callback when processCmpData check failed while config had allowAuction set to true', () => { + it('throws a warning + stores consentData + calls callback when processCmpData check failed while config had allowAuction set to true', function () { let testConsentData = {}; cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index 45c56885c03..d13c3c56398 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -104,11 +104,11 @@ const RESPONSE = { } }; -describe('Consumable BidAdapter', () => { +describe('Consumable BidAdapter', function () { let bidRequests; let adapter = spec; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'consumable', @@ -128,8 +128,8 @@ describe('Consumable BidAdapter', () => { ]; }); - describe('bid request validation', () => { - it('should accept valid bid requests', () => { + describe('bid request validation', function () { + it('should accept valid bid requests', function () { let bid = { bidder: 'consumable', params: { @@ -142,7 +142,7 @@ describe('Consumable BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should accept valid bid requests with extra fields', () => { + it('should accept valid bid requests with extra fields', function () { let bid = { bidder: 'consumable', params: { @@ -156,7 +156,7 @@ describe('Consumable BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should reject bid requests without siteId', () => { + it('should reject bid requests without siteId', function () { let bid = { bidder: 'consumable', params: { @@ -168,7 +168,7 @@ describe('Consumable BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should reject bid requests without networkId', () => { + it('should reject bid requests without networkId', function () { let bid = { bidder: 'consumable', params: { @@ -181,44 +181,44 @@ describe('Consumable BidAdapter', () => { }); }); - describe('buildRequests validation', () => { - it('creates request data', () => { + describe('buildRequests validation', function () { + it('creates request data', function () { let request = spec.buildRequests(bidRequests); expect(request).to.exist.and.to.be.a('object'); }); - it('request to consumable should contain a url', () => { + it('request to consumable should contain a url', function () { let request = spec.buildRequests(bidRequests); expect(request.url).to.have.string('serverbid.com'); }); - it('requires valid bids to make request', () => { + it('requires valid bids to make request', function () { let request = spec.buildRequests([]); expect(request.bidRequest).to.be.empty; }); - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { let request = spec.buildRequests(bidRequests); expect(request.method).to.have.string('POST'); }); }); - describe('interpretResponse validation', () => { - it('response should have valid bidderCode', () => { + describe('interpretResponse validation', function () { + it('response should have valid bidderCode', function () { let bidRequest = spec.buildRequests(REQUEST.bidRequest); let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('consumable'); }); - it('response should include objects for all bids', () => { + it('response should include objects for all bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); expect(bids.length).to.equal(2); }); - it('registers bids', () => { + it('registers bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); bids.forEach(b => { expect(b).to.have.property('cpm'); @@ -238,29 +238,29 @@ describe('Consumable BidAdapter', () => { }); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {'decisions': null}}) let bids = spec.interpretResponse(EMPTY_RESP, REQUEST); expect(bids).to.be.empty; }); - it('handles no server response', () => { + it('handles no server response', function () { let bids = spec.interpretResponse(null, REQUEST); expect(bids).to.be.empty; }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let syncOptions = {'iframeEnabled': true}; - it('handles empty sync options', () => { + it('handles empty sync options', function () { let opts = spec.getUserSyncs({}); expect(opts).to.be.empty; }); - it('should return a sync url if iframe syncs are enabled', () => { + it('should return a sync url if iframe syncs are enabled', function () { let opts = spec.getUserSyncs(syncOptions); expect(opts.length).to.equal(1); diff --git a/test/spec/modules/contentigniteBidAdapter_spec.js b/test/spec/modules/contentigniteBidAdapter_spec.js index cdf70e15615..1867791a234 100644 --- a/test/spec/modules/contentigniteBidAdapter_spec.js +++ b/test/spec/modules/contentigniteBidAdapter_spec.js @@ -1,10 +1,10 @@ import { expect } from 'chai'; import { spec } from '../../../modules/contentigniteBidAdapter'; -describe('Content Ignite adapter', () => { +describe('Content Ignite adapter', function () { let bidRequests; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'contentignite', @@ -25,9 +25,9 @@ describe('Content Ignite adapter', () => { ]; }); - describe('implementation', () => { - describe('for requests', () => { - it('should accept valid bid', () => { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { const validBid = { bidder: 'contentignite', params: { @@ -40,7 +40,7 @@ describe('Content Ignite adapter', () => { expect(isValid).to.equal(true); }); - it('should reject invalid bid', () => { + it('should reject invalid bid', function () { const invalidBid = { bidder: 'contentignite', params: { @@ -52,14 +52,14 @@ describe('Content Ignite adapter', () => { expect(isValid).to.equal(false); }); - it('should set the keyword parameter', () => { + it('should set the keyword parameter', function () { const requests = spec.buildRequests(bidRequests), requestURL = requests[0].url; expect(requestURL).to.have.string(';kw=business;'); }); - it('should increment the count for the same zone', () => { + it('should increment the count for the same zone', function () { const bidRequests = [ { sizes: [[728, 90]], @@ -87,8 +87,8 @@ describe('Content Ignite adapter', () => { }); }); - describe('bid responses', () => { - it('should return complete bid response', () => { + describe('bid responses', function () { + it('should return complete bid response', function () { const serverResponse = { body: { status: 'SUCCESS', @@ -116,7 +116,7 @@ describe('Content Ignite adapter', () => { expect(bids[0].ad).to.have.length.above(1); }); - it('should return empty bid response', () => { + it('should return empty bid response', function () { const serverResponse = { status: 'NO_ELIGIBLE_ADS', zone_id: 299680, @@ -131,7 +131,7 @@ describe('Content Ignite adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on incorrect size', () => { + it('should return empty bid response on incorrect size', function () { const serverResponse = { status: 'SUCCESS', account_id: 168237, @@ -148,7 +148,7 @@ describe('Content Ignite adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with CPM too low', () => { + it('should return empty bid response with CPM too low', function () { const serverResponse = { status: 'SUCCESS', account_id: 168237, @@ -165,7 +165,7 @@ describe('Content Ignite adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with CPM too high', () => { + it('should return empty bid response with CPM too high', function () { const serverResponse = { status: 'SUCCESS', account_id: 168237, diff --git a/test/spec/modules/coxBidAdapter_spec.js b/test/spec/modules/coxBidAdapter_spec.js index 9dd5a5a92b4..8d8b29ed4d7 100644 --- a/test/spec/modules/coxBidAdapter_spec.js +++ b/test/spec/modules/coxBidAdapter_spec.js @@ -3,10 +3,10 @@ import { spec } from 'modules/coxBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; -describe('CoxBidAdapter', () => { +describe('CoxBidAdapter', function () { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { const CONFIG = { 'bidder': 'cox', 'params': { @@ -16,18 +16,18 @@ describe('CoxBidAdapter', () => { } }; - it('should return true when required params present', () => { + it('should return true when required params present', function () { expect(spec.isBidRequestValid(CONFIG)).to.equal(true); }); - it('should return false when id param is missing', () => { + it('should return false when id param is missing', function () { let config = deepClone(CONFIG); config.params.id = null; expect(spec.isBidRequestValid(config)).to.equal(false); }); - it('should return false when size param is missing', () => { + it('should return false when size param is missing', function () { let config = deepClone(CONFIG); config.params.size = null; @@ -35,7 +35,7 @@ describe('CoxBidAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const PROD_DOMAIN = 'ad.afy11.net'; const PPE_DOMAIN = 'ppe-ad.afy11.net'; const STG_DOMAIN = 'staging-ad.afy11.net'; @@ -52,13 +52,13 @@ describe('CoxBidAdapter', () => { 'bidId': 'bId-bar' }]; - it('should send bid request to PROD_DOMAIN via GET', () => { + it('should send bid request to PROD_DOMAIN via GET', function () { let request = spec.buildRequests(BID_INFO); expect(request.url).to.have.string(PROD_DOMAIN); expect(request.method).to.equal('GET'); }); - it('should send bid request to PPE_DOMAIN when configured', () => { + it('should send bid request to PPE_DOMAIN when configured', function () { let clone = deepClone(BID_INFO); clone[0].params.env = 'PPE'; @@ -66,7 +66,7 @@ describe('CoxBidAdapter', () => { expect(request.url).to.have.string(PPE_DOMAIN); }); - it('should send bid request to STG_DOMAIN when configured', () => { + it('should send bid request to STG_DOMAIN when configured', function () { let clone = deepClone(BID_INFO); clone[0].params.env = 'STG'; @@ -74,7 +74,7 @@ describe('CoxBidAdapter', () => { expect(request.url).to.have.string(STG_DOMAIN); }); - it('should return empty when id is invalid', () => { + it('should return empty when id is invalid', function () { let clone = deepClone(BID_INFO); clone[0].params.id = null; @@ -82,7 +82,7 @@ describe('CoxBidAdapter', () => { expect(request).to.be.an('object').that.is.empty; }); - it('should return empty when size is invalid', () => { + it('should return empty when size is invalid', function () { let clone = deepClone(BID_INFO); clone[0].params.size = 'FOO'; @@ -91,7 +91,7 @@ describe('CoxBidAdapter', () => { }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { const BID_INFO_1 = [{ 'bidder': 'cox', 'params': { @@ -157,12 +157,12 @@ describe('CoxBidAdapter', () => { 'ad': '

2000005658887
300x250

' }; - it('should return correct pbjs bid', () => { + it('should return correct pbjs bid', function () { let result = spec.interpretResponse(RESPONSE_2, spec.buildRequests(BID_INFO_2)); expect(result[0]).to.eql(PBJS_BID_2); }); - it('should handle multiple bid instances', () => { + it('should handle multiple bid instances', function () { let request1 = spec.buildRequests(BID_INFO_1); let request2 = spec.buildRequests(BID_INFO_2); @@ -173,7 +173,7 @@ describe('CoxBidAdapter', () => { expect(result1[0]).to.eql(PBJS_BID_1); }); - it('should return empty when price is zero', () => { + it('should return empty when price is zero', function () { let clone = deepClone(RESPONSE_1); clone.body.zones.as2000005657007.price = 0; @@ -181,7 +181,7 @@ describe('CoxBidAdapter', () => { expect(result).to.be.an('array').that.is.empty; }); - it('should return empty when there is no ad', () => { + it('should return empty when there is no ad', function () { let clone = deepClone(RESPONSE_1); clone.body.zones.as2000005657007.ad = null; @@ -189,7 +189,7 @@ describe('CoxBidAdapter', () => { expect(result).to.be.an('array').that.is.empty; }); - it('should return empty when there is no ad unit info', () => { + it('should return empty when there is no ad unit info', function () { let clone = deepClone(RESPONSE_1); delete (clone.body.zones.as2000005657007); @@ -198,26 +198,26 @@ describe('CoxBidAdapter', () => { }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const RESPONSE = [{ body: { 'zones': {}, 'tpCookieSync': ['http://pixel.foo.com/', 'http://pixel.bar.com/'] }}]; - it('should return correct pbjs syncs when pixels are enabled', () => { + it('should return correct pbjs syncs when pixels are enabled', function () { let syncs = spec.getUserSyncs({ pixelEnabled: true }, RESPONSE); expect(syncs.map(x => x.type)).to.eql(['image', 'image']); expect(syncs.map(x => x.url)).to.have.members(['http://pixel.bar.com/', 'http://pixel.foo.com/']); }); - it('should return empty when pixels are not enabled', () => { + it('should return empty when pixels are not enabled', function () { let syncs = spec.getUserSyncs({ pixelEnabled: false }, RESPONSE); expect(syncs).to.be.an('array').that.is.empty; }); - it('should return empty when response has no sync data', () => { + it('should return empty when response has no sync data', function () { let clone = deepClone(RESPONSE); delete (clone[0].body.tpCookieSync); @@ -225,7 +225,7 @@ describe('CoxBidAdapter', () => { expect(syncs).to.be.an('array').that.is.empty; }); - it('should return empty when response is empty', () => { + it('should return empty when response is empty', function () { let syncs = spec.getUserSyncs({ pixelEnabled: true }, [{}]); expect(syncs).to.be.an('array').that.is.empty; }); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 6e2276d7e22..e232bf0e3d9 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -2,9 +2,9 @@ import { expect } from 'chai'; import { spec } from 'modules/criteoBidAdapter'; import * as utils from 'src/utils'; -describe('The Criteo bidding adapter', () => { - describe('isBidRequestValid', () => { - it('should return false when given an invalid bid', () => { +describe('The Criteo bidding adapter', function () { + describe('isBidRequestValid', function () { + it('should return false when given an invalid bid', function () { const bid = { bidder: 'criteo', }; @@ -12,7 +12,7 @@ describe('The Criteo bidding adapter', () => { expect(isValid).to.equal(false); }); - it('should return true when given a zoneId bid', () => { + it('should return true when given a zoneId bid', function () { const bid = { bidder: 'criteo', params: { @@ -23,7 +23,7 @@ describe('The Criteo bidding adapter', () => { expect(isValid).to.equal(true); }); - it('should return true when given a networkId bid', () => { + it('should return true when given a networkId bid', function () { const bid = { bidder: 'criteo', params: { @@ -34,7 +34,7 @@ describe('The Criteo bidding adapter', () => { expect(isValid).to.equal(true); }); - it('should return true when given a mixed bid with both a zoneId and a networkId', () => { + it('should return true when given a mixed bid with both a zoneId and a networkId', function () { const bid = { bidder: 'criteo', params: { @@ -47,7 +47,7 @@ describe('The Criteo bidding adapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidderRequest = { timeout: 3000, gdprConsent: { gdprApplies: 1, @@ -60,7 +60,7 @@ describe('The Criteo bidding adapter', () => { }, }; - it('should properly build a zoneId request', () => { + it('should properly build a zoneId request', function () { const bidRequests = [ { bidder: 'criteo', @@ -88,7 +88,7 @@ describe('The Criteo bidding adapter', () => { expect(ortbRequest.gdprConsent.consentGiven).to.equal(true); }); - it('should properly build a networkId request', () => { + it('should properly build a networkId request', function () { const bidderRequest = { timeout: 3000, gdprConsent: { @@ -129,7 +129,7 @@ describe('The Criteo bidding adapter', () => { expect(ortbRequest.gdprConsent.consentGiven).to.equal(undefined); }); - it('should properly build a mixed request', () => { + it('should properly build a mixed request', function () { const bidderRequest = { timeout: 3000 }; const bidRequests = [ { @@ -170,7 +170,7 @@ describe('The Criteo bidding adapter', () => { expect(ortbRequest.gdprConsent).to.equal(undefined); }); - it('should properly build request with undefined gdpr consent fields when they are not provided', () => { + it('should properly build request with undefined gdpr consent fields when they are not provided', function () { const bidRequests = [ { bidder: 'criteo', @@ -194,15 +194,15 @@ describe('The Criteo bidding adapter', () => { }); }); - describe('interpretResponse', () => { - it('should return an empty array when parsing a no bid response', () => { + describe('interpretResponse', function () { + it('should return an empty array when parsing a no bid response', function () { const response = {}; const request = { bidRequests: [] }; const bids = spec.interpretResponse(response, request); expect(bids).to.have.lengthOf(0); }); - it('should properly parse a bid response with a networkId', () => { + it('should properly parse a bid response with a networkId', function () { const response = { body: { slots: [{ @@ -232,7 +232,7 @@ describe('The Criteo bidding adapter', () => { expect(bids[0].height).to.equal(90); }); - it('should properly parse a bid responsewith with a zoneId', () => { + it('should properly parse a bid responsewith with a zoneId', function () { const response = { body: { slots: [{ @@ -263,7 +263,7 @@ describe('The Criteo bidding adapter', () => { expect(bids[0].height).to.equal(90); }); - it('should properly parse a bid responsewith with a zoneId passed as a string', () => { + it('should properly parse a bid responsewith with a zoneId passed as a string', function () { const response = { body: { slots: [{ diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index 74e2b8a3c38..e96b15d11e9 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -21,21 +21,21 @@ describe('currency', function () { let fn = sinon.spy(); let hookFn = createHook('asyncSeries', fn, 'addBidResponse'); - beforeEach(() => { + beforeEach(function () { fakeCurrencyFileServer = sinon.fakeServer.create(); }); - afterEach(() => { + afterEach(function () { fakeCurrencyFileServer.restore(); }); - describe('setConfig', () => { - it('results in currencySupportEnabled = false when currency not configured', () => { + describe('setConfig', function () { + it('results in currencySupportEnabled = false when currency not configured', function () { setConfig({}); expect(currencySupportEnabled).to.equal(false); }); - it('results in currencySupportEnabled = true and currencyRates being loaded when configured', () => { + it('results in currencySupportEnabled = true and currencyRates being loaded when configured', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); @@ -44,8 +44,8 @@ describe('currency', function () { }); }); - describe('bidder override', () => { - it('allows setConfig to set bidder currency', () => { + describe('bidder override', function () { + it('allows setConfig to set bidder currency', function () { setConfig({}); var bid = { cpm: 1, bidder: 'rubicon' }; @@ -67,7 +67,7 @@ describe('currency', function () { expect(innerBid.getCpmInNewCurrency('GBP')).to.equal('1.000'); }); - it('uses adapter currency over currency override if specified', () => { + it('uses adapter currency over currency override if specified', function () { setConfig({}); var bid = { cpm: 1, currency: 'JPY', bidder: 'rubicon' }; @@ -89,7 +89,7 @@ describe('currency', function () { expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('1.000'); }); - it('uses rates specified in json when provided', () => { + it('uses rates specified in json when provided', function () { setConfig({ adServerCurrency: 'USD', rates: { @@ -111,7 +111,7 @@ describe('currency', function () { expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000'); }); - it('uses default rates when currency file fails to load', () => { + it('uses default rates when currency file fails to load', function () { setConfig({}); setConfig({ @@ -139,8 +139,8 @@ describe('currency', function () { }); }); - describe('currency.addBidResponseDecorator bidResponseQueue', () => { - it('not run until currency rates file is loaded', () => { + describe('currency.addBidResponseDecorator bidResponseQueue', function () { + it('not run until currency rates file is loaded', function () { setConfig({}); fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); @@ -161,8 +161,8 @@ describe('currency', function () { }); }); - describe('currency.addBidResponseDecorator', () => { - it('should leave bid at 1 when currency support is not enabled and fromCurrency is USD', () => { + describe('currency.addBidResponseDecorator', function () { + it('should leave bid at 1 when currency support is not enabled and fromCurrency is USD', function () { setConfig({}); var bid = { 'cpm': 1, 'currency': 'USD' }; var innerBid; @@ -172,7 +172,7 @@ describe('currency', function () { expect(innerBid.cpm).to.equal(1); }); - it('should result in NO_BID when currency support is not enabled and fromCurrency is not USD', () => { + it('should result in NO_BID when currency support is not enabled and fromCurrency is not USD', function () { setConfig({}); var bid = { 'cpm': 1, 'currency': 'GBP' }; var innerBid; @@ -182,7 +182,7 @@ describe('currency', function () { expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); - it('should not buffer bid when currency is already in desired currency', () => { + it('should not buffer bid when currency is already in desired currency', function () { setConfig({ 'adServerCurrency': 'USD' }); @@ -194,7 +194,7 @@ describe('currency', function () { expect(bid).to.equal(innerBid); }); - it('should result in NO_BID when fromCurrency is not supported in file', () => { + it('should result in NO_BID when fromCurrency is not supported in file', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); @@ -206,7 +206,7 @@ describe('currency', function () { expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); - it('should result in NO_BID when adServerCurrency is not supported in file', () => { + it('should result in NO_BID when adServerCurrency is not supported in file', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'ABC' }); fakeCurrencyFileServer.respond(); @@ -218,7 +218,7 @@ describe('currency', function () { expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); - it('should return 1 when currency support is enabled and same currency code is requested as is set to adServerCurrency', () => { + it('should return 1 when currency support is enabled and same currency code is requested as is set to adServerCurrency', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); @@ -231,7 +231,7 @@ describe('currency', function () { expect(innerBid.currency).to.equal('JPY'); }); - it('should return direct conversion rate when fromCurrency is one of the configured bases', () => { + it('should return direct conversion rate when fromCurrency is one of the configured bases', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'GBP' }); fakeCurrencyFileServer.respond(); @@ -244,7 +244,7 @@ describe('currency', function () { expect(innerBid.currency).to.equal('GBP'); }); - it('should return reciprocal conversion rate when adServerCurrency is one of the configured bases, but fromCurrency is not', () => { + it('should return reciprocal conversion rate when adServerCurrency is one of the configured bases, but fromCurrency is not', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'GBP' }); fakeCurrencyFileServer.respond(); @@ -257,7 +257,7 @@ describe('currency', function () { expect(innerBid.currency).to.equal('GBP'); }); - it('should return intermediate conversion rate when neither fromCurrency nor adServerCurrency is one of the configured bases', () => { + it('should return intermediate conversion rate when neither fromCurrency nor adServerCurrency is one of the configured bases', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'CNY' }); fakeCurrencyFileServer.respond(); diff --git a/test/spec/modules/danmarketBidAdapter_spec.js b/test/spec/modules/danmarketBidAdapter_spec.js index 243e2fdfb66..973cd2afb1c 100644 --- a/test/spec/modules/danmarketBidAdapter_spec.js +++ b/test/spec/modules/danmarketBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('DAN_Marketplace Adapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'danmarket', 'params': { @@ -24,11 +24,11 @@ describe('DAN_Marketplace Adapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('DAN_Marketplace Adapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'danmarket', @@ -75,7 +75,7 @@ describe('DAN_Marketplace Adapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); const payload = request.data; expect(payload).to.be.an('object'); @@ -84,7 +84,7 @@ describe('DAN_Marketplace Adapter', function () { expect(payload).to.have.property('auids', '5'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); @@ -93,7 +93,7 @@ describe('DAN_Marketplace Adapter', function () { expect(payload).to.have.property('auids', '5,6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -104,7 +104,7 @@ describe('DAN_Marketplace Adapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -115,7 +115,7 @@ describe('DAN_Marketplace Adapter', function () { delete bidRequests[1].params.priceType; }); - it('if gdprConsent is present payload must have gdpr params', () => { + it('if gdprConsent is present payload must have gdpr params', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -123,7 +123,7 @@ describe('DAN_Marketplace Adapter', function () { expect(payload).to.have.property('gdpr_applies', 1); }); - it('if gdprApplies is false gdpr_applies must be 0', () => { + it('if gdprApplies is false gdpr_applies must be 0', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -131,7 +131,7 @@ describe('DAN_Marketplace Adapter', function () { expect(payload).to.have.property('gdpr_applies', 0); }); - it('if gdprApplies is undefined gdpr_applies must be 1', () => { + it('if gdprApplies is undefined gdpr_applies must be 1', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -140,7 +140,7 @@ describe('DAN_Marketplace Adapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -151,7 +151,7 @@ describe('DAN_Marketplace Adapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'danmarket', @@ -185,7 +185,7 @@ describe('DAN_Marketplace Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'danmarket', @@ -265,7 +265,7 @@ describe('DAN_Marketplace Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'danmarket', diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 8f779412c80..8afc597d3b4 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -13,8 +13,8 @@ const bid = { adserverTargeting: { }, }; -describe('The DFP video support module', () => { - it('should make a legal request URL when given the required params', () => { +describe('The DFP video support module', function () { + it('should make a legal request URL when given the required params', function () { const url = parse(buildDfpVideoUrl({ adUnit: adUnit, bid: bid, @@ -39,7 +39,7 @@ describe('The DFP video support module', () => { expect(queryParams).to.have.property('url'); }); - it('can take an adserver url as a parameter', () => { + it('can take an adserver url as a parameter', function () { const bidCopy = Object.assign({ }, bid); bidCopy.vastUrl = 'vastUrl.example'; @@ -55,7 +55,7 @@ describe('The DFP video support module', () => { expect(queryObject.description_url).to.equal('vastUrl.example'); }); - it('requires a params object or url', () => { + it('requires a params object or url', function () { const url = buildDfpVideoUrl({ adUnit: adUnit, bid: bid, @@ -64,7 +64,7 @@ describe('The DFP video support module', () => { expect(url).to.be.undefined; }); - it('overwrites url params when both url and params object are given', () => { + it('overwrites url params when both url and params object are given', function () { const url = parse(buildDfpVideoUrl({ adUnit: adUnit, bid: bid, @@ -76,7 +76,7 @@ describe('The DFP video support module', () => { expect(queryObject.iu).to.equal('my/adUnit'); }); - it('should override param defaults with user-provided ones', () => { + it('should override param defaults with user-provided ones', function () { const url = parse(buildDfpVideoUrl({ adUnit: adUnit, bid: bid, @@ -89,7 +89,7 @@ describe('The DFP video support module', () => { expect(parseQS(url.query)).to.have.property('output', 'vast'); }); - it('should include the cache key and adserver targeting in cust_params', () => { + it('should include the cache key and adserver targeting in cust_params', function () { const bidCopy = Object.assign({ }, bid); bidCopy.adserverTargeting = { hb_adid: 'ad_id', @@ -110,7 +110,7 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('hb_cache_id', bid.videoCacheKey); }); - describe('special targeting unit test', () => { + describe('special targeting unit test', function () { const allTargetingData = { 'hb_format': 'video', 'hb_source': 'client', @@ -133,7 +133,7 @@ describe('The DFP video support module', () => { }; let targetingStub; - before(() => { + before(function () { targetingStub = sinon.stub(targeting, 'getAllTargeting'); targetingStub.returns({'video1': allTargetingData}); @@ -142,12 +142,12 @@ describe('The DFP video support module', () => { }); }); - after(() => { + after(function () { config.resetConfig(); targetingStub.restore(); }); - it('should include all adserver targeting in cust_params if pbjs.enableSendAllBids is true', () => { + it('should include all adserver targeting in cust_params if pbjs.enableSendAllBids is true', function () { const adUnitsCopy = utils.deepClone(adUnit); adUnitsCopy.bids.push({ 'bidder': 'testBidder2', @@ -183,7 +183,7 @@ describe('The DFP video support module', () => { }); }); - it('should merge the user-provided cust_params with the default ones', () => { + it('should merge the user-provided cust_params with the default ones', function () { const bidCopy = Object.assign({ }, bid); bidCopy.adserverTargeting = { hb_adid: 'ad_id', @@ -206,7 +206,7 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('my_targeting', 'foo'); }); - it('should merge the user-provided cust-params with the default ones when using url object', () => { + it('should merge the user-provided cust-params with the default ones when using url object', function () { const bidCopy = Object.assign({ }, bid); bidCopy.adserverTargeting = { hb_adid: 'ad_id', @@ -228,7 +228,7 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('hb_cache_id', 'abc'); }); - it('should not overwrite an existing description_url for object input and cache disabled', () => { + it('should not overwrite an existing description_url for object input and cache disabled', function () { const bidCopy = Object.assign({}, bid); bidCopy.vastUrl = 'vastUrl.example'; @@ -245,7 +245,7 @@ describe('The DFP video support module', () => { expect(queryObject.description_url).to.equal('descriptionurl.example'); }); - it('should work with nobid responses', () => { + it('should work with nobid responses', function () { const url = buildDfpVideoUrl({ adUnit: adUnit, params: { 'iu': 'my/adUnit' } diff --git a/test/spec/modules/dgadsBidAdapter_spec.js b/test/spec/modules/dgadsBidAdapter_spec.js index 89affd94880..25f484678a0 100644 --- a/test/spec/modules/dgadsBidAdapter_spec.js +++ b/test/spec/modules/dgadsBidAdapter_spec.js @@ -4,17 +4,17 @@ import {spec} from 'modules/dgadsBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import { BANNER, NATIVE } from 'src/mediaTypes'; -describe('dgadsBidAdapter', () => { +describe('dgadsBidAdapter', function () { const adapter = newBidder(spec); const VALID_ENDPOINT = 'https://ads-tr.bigmining.com/ad/p/bid'; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'dgads', params: { @@ -22,11 +22,11 @@ describe('dgadsBidAdapter', () => { location_id: '1' } }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params(location_id) are not passed', () => { + it('should return false when required params(location_id) are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -35,7 +35,7 @@ describe('dgadsBidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when required params(site_id) are not passed', () => { + it('should return false when required params(site_id) are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -45,7 +45,7 @@ describe('dgadsBidAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [ { // banner bidder: 'dgads', @@ -97,7 +97,7 @@ describe('dgadsBidAdapter', () => { transactionId: 'c1f1eff6-23c6-4844-a321-575212939e37' } ]; - it('no bidRequests', () => { + it('no bidRequests', function () { const noBidRequests = []; expect(Object.keys(spec.buildRequests(noBidRequests)).length).to.equal(0); }); @@ -107,12 +107,12 @@ describe('dgadsBidAdapter', () => { transaction_id: 'c1f1eff6-23c6-4844-a321-575212939e37', bid_id: '2db3101abaec66' }; - it('sends bid request to VALID_ENDPOINT via POST', () => { + it('sends bid request to VALID_ENDPOINT via POST', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(VALID_ENDPOINT); expect(request.method).to.equal('POST'); }); - it('should attache params to the request', () => { + it('should attache params to the request', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.data['location_id']).to.equal(data['location_id']); expect(request.data['site_id']).to.equal(data['site_id']); @@ -121,7 +121,7 @@ describe('dgadsBidAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequests = { banner: { bidRequest: { @@ -252,11 +252,11 @@ describe('dgadsBidAdapter', () => { } }; - it('no bid responses', () => { + it('no bid responses', function () { const result = spec.interpretResponse({body: serverResponse.noAd}, bidRequests.banner); expect(result.length).to.equal(0); }); - it('handles banner responses', () => { + it('handles banner responses', function () { const result = spec.interpretResponse({body: serverResponse.banner}, bidRequests.banner)[0]; expect(result.requestId).to.equal(bidResponses.banner.requestId); expect(result.width).to.equal(bidResponses.banner.width); @@ -269,7 +269,7 @@ describe('dgadsBidAdapter', () => { expect(result.ad).to.equal(bidResponses.banner.ad); }); - it('handles native responses', () => { + it('handles native responses', function () { const result = spec.interpretResponse({body: serverResponse.native}, bidRequests.native)[0]; expect(result.requestId).to.equal(bidResponses.native.requestId); expect(result.creativeId).to.equal(bidResponses.native.creativeId); diff --git a/test/spec/modules/districtmDmxBidAdapter_spec.js b/test/spec/modules/districtmDmxBidAdapter_spec.js index cfdab445f71..a0bd76f9591 100644 --- a/test/spec/modules/districtmDmxBidAdapter_spec.js +++ b/test/spec/modules/districtmDmxBidAdapter_spec.js @@ -420,58 +420,58 @@ const responsesNegative = { const emptyResponse = { body: {} }; const emptyResponseSeatBid = { body: { seatbid: [] } }; -describe('DistrictM Adaptor', () => { +describe('DistrictM Adaptor', function () { const districtm = spec; - describe('All needed functions are available', () => { - it(`isBidRequestValid is present and type function`, () => { + describe('All needed functions are available', function () { + it(`isBidRequestValid is present and type function`, function () { expect(districtm.isBidRequestValid).to.exist.and.to.be.a('function') }); - it(`BuildRequests is present and type function`, () => { + it(`BuildRequests is present and type function`, function () { expect(districtm.buildRequests).to.exist.and.to.be.a('function') }); - it(`interpretResponse is present and type function`, () => { + it(`interpretResponse is present and type function`, function () { expect(districtm.interpretResponse).to.exist.and.to.be.a('function') }); - it(`getUserSyncs is present and type function`, () => { + it(`getUserSyncs is present and type function`, function () { expect(districtm.getUserSyncs).to.exist.and.to.be.a('function') }); }); - describe(`these properties are available or not`, () => { - it(`code should have a value of districtmDMX`, () => { + describe(`these properties are available or not`, function () { + it(`code should have a value of districtmDMX`, function () { expect(districtm.code).to.be.equal('districtmDMX'); }); - it(`timeout should not be defined`, () => { + it(`timeout should not be defined`, function () { expect(districtm.onTimeout).to.be.an('undefined'); }); }); - describe(`isBidRequestValid test response`, () => { + describe(`isBidRequestValid test response`, function () { let params = { dmxid: 10001, memberid: 10003, }; - it(`function should return true`, () => { + it(`function should return true`, function () { expect(districtm.isBidRequestValid({params})).to.be.equal(true); }); - it(`function should return false`, () => { + it(`function should return false`, function () { expect(districtm.isBidRequestValid({ params: { memberid: 12345 } })).to.be.equal(false); }); - it(`expect to have two property available dmxid and memberid`, () => { + it(`expect to have two property available dmxid and memberid`, function () { expect(params).to.have.property('dmxid'); expect(params).to.have.property('memberid'); }); }); - describe(`getUserSyncs test usage`, () => { - it(`return value should be an array`, () => { + describe(`getUserSyncs test usage`, function () { + it(`return value should be an array`, function () { expect(districtm.getUserSyncs({ iframeEnabled: true })).to.be.an('array'); }); - it(`array should have only one object and it should have a property type = 'iframe'`, () => { + it(`array should have only one object and it should have a property type = 'iframe'`, function () { expect(districtm.getUserSyncs({ iframeEnabled: true }).length).to.be.equal(1); let [userSync] = districtm.getUserSyncs({ iframeEnabled: true }); expect(userSync).to.have.property('type'); @@ -479,53 +479,53 @@ describe('DistrictM Adaptor', () => { }); }); - describe(`buildRequests test usage`, () => { + describe(`buildRequests test usage`, function () { const buildRequestResults = districtm.buildRequests(bidRequest, bidderRequest); - it(`the function should return an array`, () => { + it(`the function should return an array`, function () { expect(buildRequestResults).to.be.an('object'); }); - it(`the function should return array length of 1`, () => { + it(`the function should return array length of 1`, function () { expect(buildRequestResults.data).to.be.a('string'); }); }); - describe(`interpretResponse test usage`, () => { + describe(`interpretResponse test usage`, function () { const responseResults = districtm.interpretResponse(responses, {bidderRequest}); const emptyResponseResults = districtm.interpretResponse(emptyResponse, {bidderRequest}); const emptyResponseResultsNegation = districtm.interpretResponse(responsesNegative, {bidderRequest}); const emptyResponseResultsEmptySeat = districtm.interpretResponse(emptyResponseSeatBid, {bidderRequest}); - it(`the function should return an array`, () => { + it(`the function should return an array`, function () { expect(responseResults).to.be.an('array'); }); - it(`the function should return array length of 1`, () => { + it(`the function should return array length of 1`, function () { expect(responseResults.length).to.be.equal(1); }); - it(`the response return nothing`, () => { + it(`the response return nothing`, function () { expect(emptyResponseResults.length).to.be.equal(0); }); - it(`the response seatbid return nothing`, () => { + it(`the response seatbid return nothing`, function () { expect(emptyResponseResultsEmptySeat.length).to.be.equal(0); }); - it(`on invalid CPM`, () => { + it(`on invalid CPM`, function () { expect(emptyResponseResultsNegation.length).to.be.equal(0); }); }); - describe(`Helper function testing`, () => { + describe(`Helper function testing`, function () { const bid = matchRequest('29a28a1bbc8a8d', {bidderRequest}); const {width, height} = defaultSize(bid); - it(`test matchRequest`, () => { + it(`test matchRequest`, function () { expect(matchRequest('29a28a1bbc8a8d', {bidderRequest})).to.be.an('object'); }); - it(`test checkDeepArray`, () => { + it(`test checkDeepArray`, function () { expect(_.isEqual(checkDeepArray([728, 90]), [728, 90])).to.be.equal(true); expect(_.isEqual(checkDeepArray([[728, 90]]), [728, 90])).to.be.equal(true); expect(_.isEqual(checkDeepArray([[728, 90], [300, 250]]), [728, 90])).to.be.equal(true); expect(_.isEqual(checkDeepArray([[300, 250], [300, 250]]), [728, 90])).to.be.equal(false); expect(_.isEqual(checkDeepArray([300, 250]), [300, 250])).to.be.equal(true); }); - it(`test defaultSize`, () => { + it(`test defaultSize`, function () { expect(width).to.be.equal(300); expect(height).to.be.equal(250); }); diff --git a/test/spec/modules/divreachBidAdapter_spec.js b/test/spec/modules/divreachBidAdapter_spec.js index 8beb0830385..f874a206a87 100644 --- a/test/spec/modules/divreachBidAdapter_spec.js +++ b/test/spec/modules/divreachBidAdapter_spec.js @@ -6,16 +6,16 @@ const BIDDER_CODE = 'divreach'; const ENDPOINT_URL = '//ads.divreach.com/prebid.1.0.aspx'; const ZONE_ID = '2eb6bd58-865c-47ce-af7f-a918108c3fd2'; -describe('DivReachAdapter', () => { +describe('DivReachAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.be.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': BIDDER_CODE, 'params': { @@ -28,11 +28,11 @@ describe('DivReachAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -42,7 +42,7 @@ describe('DivReachAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': BIDDER_CODE, @@ -57,21 +57,21 @@ describe('DivReachAdapter', () => { } ]; - it('should add referrer and imp to be equal bidRequest', () => { + it('should add referrer and imp to be equal bidRequest', function () { const request = spec.buildRequests(bidRequests); const payload = JSON.parse(request.data.substr(5)); expect(payload.referrer).to.not.be.undefined; expect(payload.imps[0]).to.deep.equal(bidRequests[0]); }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT_URL); expect(request.method).to.equal('GET'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { body: [{ 'currency': 'USD', @@ -86,7 +86,7 @@ describe('DivReachAdapter', () => { }] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const body = response.body; let expectedResponse = [ { @@ -107,7 +107,7 @@ describe('DivReachAdapter', () => { expect(result[0]).to.deep.equal(expectedResponse[0]); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = []; let result = spec.interpretResponse(response); diff --git a/test/spec/modules/ebdrBidAdapter_spec.js b/test/spec/modules/ebdrBidAdapter_spec.js index 3ec5a4f0a81..d742e28f2e6 100644 --- a/test/spec/modules/ebdrBidAdapter_spec.js +++ b/test/spec/modules/ebdrBidAdapter_spec.js @@ -3,10 +3,10 @@ import { spec } from 'modules/ebdrBidAdapter'; import { VIDEO, BANNER } from 'src/mediaTypes'; import * as utils from 'src/utils'; -describe('ebdrBidAdapter', () => { +describe('ebdrBidAdapter', function () { let bidRequests; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { code: 'div-gpt-ad-1460505748561-0', @@ -51,13 +51,13 @@ describe('ebdrBidAdapter', () => { ]; }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { const bidRequest = bidRequests[0]; expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return true when the only required param is missing', () => { + it('should return true when the only required param is missing', function () { const bidRequest = bidRequests[0]; bidRequest.params = { zoneid: '99998', @@ -66,7 +66,7 @@ describe('ebdrBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return true when the "bidfloor" param is missing', () => { + it('should return true when the "bidfloor" param is missing', function () { const bidRequest = bidRequests[0]; bidRequest.params = { zoneid: '99998', @@ -74,34 +74,34 @@ describe('ebdrBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { const bidRequest = bidRequests[0]; bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when a bid request is not passed', () => { + 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', () => { - describe('for banner bids', () => { - it('must handle an empty bid size', () => { + describe('spec.buildRequests', function () { + describe('for banner bids', function () { + it('must handle an empty bid size', function () { bidRequests[0].mediaTypes = { banner: {} }; const requests = spec.buildRequests(bidRequests); const bidRequest = {}; bidRequest['2c5e8a1a84522d'] = { mediaTypes: BANNER, w: null, h: null }; expect(requests.bids['2c5e8a1a84522d']).to.deep.equals(bidRequest['2c5e8a1a84522d']); }); - it('should create a single GET', () => { + it('should create a single GET', function () { bidRequests[0].mediaTypes = { banner: {} }; bidRequests[1].mediaTypes = { banner: {} }; const requests = spec.buildRequests(bidRequests); expect(requests.method).to.equal('GET'); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -112,8 +112,8 @@ describe('ebdrBidAdapter', () => { expect(requests.bids['2c5e8a1a84522d']).to.deep.equal(data['2c5e8a1a84522d']); }); }); - describe('for video bids', () => { - it('must handle an empty bid size', () => { + describe('for video bids', function () { + it('must handle an empty bid size', function () { bidRequests[1].mediaTypes = { video: {} }; const requests = spec.buildRequests(bidRequests); const bidRequest = {}; @@ -121,7 +121,7 @@ describe('ebdrBidAdapter', () => { expect(requests.bids['23a01e95856577']).to.deep.equals(bidRequest['23a01e95856577']); }); - it('should create a GET request for each bid', () => { + it('should create a GET request for each bid', function () { const bidRequest = bidRequests[1]; const requests = spec.buildRequests([ bidRequest ]); expect(requests.method).to.equal('GET'); @@ -129,16 +129,16 @@ describe('ebdrBidAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - describe('for video bids', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + describe('for video bids', function () { + it('should return no bids if the response is not valid', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return a valid video bid response', () => { + it('should return a valid video bid response', function () { const ebdrReq = {bids: {}}; bidRequests.forEach(bid => { let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); @@ -165,22 +165,22 @@ describe('ebdrBidAdapter', () => { }); }); - describe('for banner bids', () => { - it('should return no bids if the response is not valid', () => { + 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 }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response is empty', () => { + it('should return no bids if the response is empty', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; const bidResponse = spec.interpretResponse({ body: [] }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return valid banner bid responses', () => { + it('should return valid banner bid responses', function () { const ebdrReq = {bids: {}}; bidRequests.forEach(bid => { let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); @@ -206,27 +206,27 @@ describe('ebdrBidAdapter', () => { }); }); }); - describe('spec.getUserSyncs', () => { + describe('spec.getUserSyncs', function () { let syncOptions - beforeEach(() => { + beforeEach(function () { syncOptions = { enabledBidders: ['ebdr'], // only these bidders are allowed to sync pixelEnabled: true } }); - it('sucess with usersync url', () => { + it('sucess with usersync url', function () { const serverResponse = {id: '1d0c4017f02458', seatbid: [{bid: [{id: '2c5e8a1a84522d', impid: '2c5e8a1a84522d', price: 0.81, adid: 'abcde-12345', nurl: '', adm: '
', adomain: ['advertiserdomain.com'], iurl: '//match.bnmla.com/usersync?sspid=59&redir=', cid: 'campaign1', crid: 'abcde-12345', w: 300, h: 250}], seat: '19513bcfca8006'}], bidid: '19513bcfca8006', cur: 'USD', w: 300, h: 250}; const result = []; result.push({type: 'image', url: '//match.bnmla.com/usersync?sspid=59&redir='}); expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); }); - it('sucess without usersync url', () => { + it('sucess without usersync url', function () { const serverResponse = {id: '1d0c4017f02458', seatbid: [{bid: [{id: '2c5e8a1a84522d', impid: '2c5e8a1a84522d', price: 0.81, adid: 'abcde-12345', nurl: '', adm: '
', adomain: ['advertiserdomain.com'], iurl: '', cid: 'campaign1', crid: 'abcde-12345', w: 300, h: 250}], seat: '19513bcfca8006'}], bidid: '19513bcfca8006', cur: 'USD', w: 300, h: 250}; const result = []; expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); }); - it('empty response', () => { + it('empty response', function () { const serverResponse = {}; const result = []; expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); diff --git a/test/spec/modules/eplanningAnalyticsAdapter_spec.js b/test/spec/modules/eplanningAnalyticsAdapter_spec.js index cd538815954..2b10f10adf2 100644 --- a/test/spec/modules/eplanningAnalyticsAdapter_spec.js +++ b/test/spec/modules/eplanningAnalyticsAdapter_spec.js @@ -6,25 +6,25 @@ let adaptermanager = require('src/adaptermanager'); let events = require('src/events'); let constants = require('src/constants.json'); -describe('eplanning analytics adapter', () => { +describe('eplanning analytics adapter', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => { requests.push(request) }; sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { xhr.restore(); events.getEvents.restore(); eplAnalyticsAdapter.disableAnalytics(); }); - describe('track', () => { - it('builds and sends auction data', () => { + describe('track', function () { + it('builds and sends auction data', function () { sinon.spy(eplAnalyticsAdapter, 'track'); let auctionTimestamp = 1496510254313; diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js index a56bff42285..80129a03bd2 100644 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ b/test/spec/modules/eplanningBidAdapter_spec.js @@ -3,7 +3,7 @@ import { spec } from 'modules/eplanningBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; -describe('E-Planning Adapter', () => { +describe('E-Planning Adapter', function () { const adapter = newBidder('spec'); const CI = '12345'; const ADUNIT_CODE = 'adunit-code'; @@ -167,55 +167,55 @@ describe('E-Planning Adapter', () => { } }; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when bid has ci parameter', () => { + describe('isBidRequestValid', function () { + it('should return true when bid has ci parameter', function () { expect(spec.isBidRequestValid(validBid)).to.equal(true); }); - it('should return false when bid does not have ci parameter and is not a test bid', () => { + it('should return false when bid does not have ci parameter and is not a test bid', function () { expect(spec.isBidRequestValid(invalidBid)).to.equal(false); }); - it('should return true when bid does not have ci parameter but is a test bid', () => { + it('should return true when bid does not have ci parameter but is a test bid', function () { expect(spec.isBidRequestValid(testBid)).to.equal(true); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [validBid]; - it('should create the url correctly', () => { + it('should create the url correctly', function () { const url = spec.buildRequests(bidRequests).url; expect(url).to.equal('//ads.us.e-planning.net/hb/1/' + CI + '/1/localhost/ROS'); }); - it('should return GET method', () => { + it('should return GET method', function () { const method = spec.buildRequests(bidRequests).method; expect(method).to.equal('GET'); }); - it('should return r parameter with value pbjs', () => { + it('should return r parameter with value pbjs', function () { const r = spec.buildRequests(bidRequests).data.r; expect(r).to.equal('pbjs'); }); - it('should return pbv parameter with value prebid version', () => { + it('should return pbv parameter with value prebid version', function () { const pbv = spec.buildRequests(bidRequests).data.pbv; expect(pbv).to.equal('$prebid.version$'); }); - it('should return e parameter with value according to the adunit sizes', () => { + it('should return e parameter with value according to the adunit sizes', function () { const e = spec.buildRequests(bidRequests).data.e; expect(e).to.equal(CLEAN_ADUNIT_CODE + ':300x250,300x600'); }); - it('should return correct e parameter with more than one adunit', () => { + it('should return correct e parameter with more than one adunit', function () { const NEW_CODE = ADUNIT_CODE + '2'; const CLEAN_NEW_CODE = CLEAN_ADUNIT_CODE + '2'; const anotherBid = { @@ -232,7 +232,7 @@ describe('E-Planning Adapter', () => { expect(e).to.equal(CLEAN_ADUNIT_CODE + ':300x250,300x600+' + CLEAN_NEW_CODE + ':100x100'); }); - it('should return correct e parameter when the adunit has no size', () => { + it('should return correct e parameter when the adunit has no size', function () { const noSizeBid = { 'bidder': 'eplanning', 'params': { @@ -245,12 +245,12 @@ describe('E-Planning Adapter', () => { expect(e).to.equal(CLEAN_ADUNIT_CODE + ':1x1'); }); - it('should return ur parameter with current window url', () => { + it('should return ur parameter with current window url', function () { const ur = spec.buildRequests(bidRequests).data.ur; expect(ur).to.equal(utils.getTopWindowUrl()); }); - it('should return fr parameter when there is a referrer', () => { + it('should return fr parameter when there is a referrer', function () { const referrer = 'thisisafakereferrer'; const stubGetReferrer = sinon.stub(utils, 'getTopWindowReferrer'); stubGetReferrer.returns(referrer); @@ -259,7 +259,7 @@ describe('E-Planning Adapter', () => { stubGetReferrer.restore() }); - it('should return crs parameter with document charset', () => { + it('should return crs parameter with document charset', function () { let expected; try { expected = window.top.document.characterSet; @@ -272,30 +272,30 @@ describe('E-Planning Adapter', () => { expect(chset).to.equal(expected); }); - it('should return the testing url when the request has the t parameter', () => { + it('should return the testing url when the request has the t parameter', function () { const url = spec.buildRequests([testBid]).url; const expectedUrl = '//' + TEST_ISV + '/layers/t_pbjs_2.json'; expect(url).to.equal(expectedUrl); }); - it('should return the parameter ncb with value 1', () => { + it('should return the parameter ncb with value 1', function () { const ncb = spec.buildRequests(bidRequests).data.ncb; expect(ncb).to.equal('1'); }); }); - describe('interpretResponse', () => { - it('should return an empty array when there is no ads in the response', () => { + describe('interpretResponse', function () { + it('should return an empty array when there is no ads in the response', function () { const bidResponses = spec.interpretResponse(responseWithNoAd); expect(bidResponses).to.be.empty; }); - it('should return an empty array when there is no spaces in the response', () => { + it('should return an empty array when there is no spaces in the response', function () { const bidResponses = spec.interpretResponse(responseWithNoSpace); expect(bidResponses).to.be.empty; }); - it('should correctly map the parameters in the response', () => { + it('should correctly map the parameters in the response', function () { const bidResponse = spec.interpretResponse(response, { adUnitToBidId: { [CLEAN_ADUNIT_CODE]: BID_ID } })[0]; const expectedResponse = { requestId: BID_ID, @@ -312,7 +312,7 @@ describe('E-Planning Adapter', () => { }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const sOptionsAllEnabled = { pixelEnabled: true, iframeEnabled: true @@ -330,30 +330,30 @@ describe('E-Planning Adapter', () => { iframeEnabled: true }; - it('should return an empty array if the response has no syncs', () => { + it('should return an empty array if the response has no syncs', function () { const noSyncsResponse = { cs: [] }; const syncs = spec.getUserSyncs(sOptionsAllEnabled, [noSyncsResponse]); expect(syncs).to.be.empty; }); - it('should return an empty array if there is no sync options enabled', () => { + it('should return an empty array if there is no sync options enabled', function () { const syncs = spec.getUserSyncs(sOptionsAllDisabled, [response]); expect(syncs).to.be.empty; }); - it('should only return pixels if iframe is not enabled', () => { + it('should only return pixels if iframe is not enabled', function () { const syncs = spec.getUserSyncs(sOptionsOnlyPixel, [response]); syncs.forEach(sync => expect(sync.type).to.equal('image')); }); - it('should only return iframes if pixel is not enabled', () => { + it('should only return iframes if pixel is not enabled', function () { const syncs = spec.getUserSyncs(sOptionsOnlyIframe, [response]); syncs.forEach(sync => expect(sync.type).to.equal('iframe')); }); }); - describe('adUnits mapping to bidId', () => { - it('should correctly map the bidId to the adunit', () => { + describe('adUnits mapping to bidId', function () { + it('should correctly map the bidId to the adunit', function () { const requests = spec.buildRequests([validBid, validBid2]); const responses = spec.interpretResponse(responseWithTwoAdunits, requests); expect(responses[0].requestId).to.equal(BID_ID); diff --git a/test/spec/modules/etargetBidAdapter_spec.js b/test/spec/modules/etargetBidAdapter_spec.js index 2af61505afa..e4cccbf5cf3 100644 --- a/test/spec/modules/etargetBidAdapter_spec.js +++ b/test/spec/modules/etargetBidAdapter_spec.js @@ -3,10 +3,10 @@ import * as url from 'src/url'; import {spec} from 'modules/etargetBidAdapter'; import { BANNER, VIDEO } from 'src/mediaTypes'; -describe('etarget adapter', () => { +describe('etarget adapter', function () { let serverResponse, bidRequest, bidResponses; let bids = []; - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'etarget', 'params': { @@ -15,29 +15,29 @@ describe('etarget adapter', () => { } }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { assert(spec.isBidRequestValid(bid)); }); }); - describe('buildRequests', () => { - it('should pass multiple bids via single request', () => { + describe('buildRequests', function () { + it('should pass multiple bids via single request', function () { let request = spec.buildRequests(bids); let parsedUrl = parseUrl(request.url); assert.lengthOf(parsedUrl.items, 7); }); - it('should handle global request parameters', () => { + it('should handle global request parameters', function () { let parsedUrl = parseUrl(spec.buildRequests([bids[0]]).url); assert.equal(parsedUrl.path, '//sk.search.etargetnet.com/hb'); }); - it('should set correct request method', () => { + it('should set correct request method', function () { let request = spec.buildRequests([bids[0]]); assert.equal(request.method, 'POST'); }); - it('should correctly form bid items', () => { + it('should correctly form bid items', function () { let bidList = bids; let request = spec.buildRequests(bidList); let parsedUrl = parseUrl(request.url); @@ -88,14 +88,14 @@ describe('etarget adapter', () => { ]); }); - it('should not change original validBidRequests object', () => { + it('should not change original validBidRequests object', function () { var resultBids = JSON.parse(JSON.stringify(bids[0])); let request = spec.buildRequests([bids[0]]); assert.deepEqual(resultBids, bids[0]); }); - describe('gdpr', () => { - it('should send GDPR Consent data to etarget if gdprApplies', () => { + describe('gdpr', function () { + it('should send GDPR Consent data to etarget if gdprApplies', function () { let resultBids = JSON.parse(JSON.stringify(bids[0])); let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); let parsedUrl = parseUrl(request.url).query; @@ -104,7 +104,7 @@ describe('etarget adapter', () => { assert.equal(parsedUrl.gdpr_consent, 'concentDataString'); }); - it('should not send GDPR Consent data to etarget if gdprApplies is false or undefined', () => { + it('should not send GDPR Consent data to etarget if gdprApplies is false or undefined', function () { let resultBids = JSON.parse(JSON.stringify(bids[0])); let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: false, consentString: 'concentDataString'}}); let parsedUrl = parseUrl(request.url).query; @@ -117,7 +117,7 @@ describe('etarget adapter', () => { assert.ok(!parsedUrl.gdpr_consent); }); - it('should return GDPR Consent data with request data', () => { + it('should return GDPR Consent data with request data', function () { let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); assert.deepEqual(request.gdpr, { @@ -131,12 +131,12 @@ describe('etarget adapter', () => { }); }); - describe('interpretResponse', () => { - it('should respond with empty response when there is empty serverResponse', () => { + describe('interpretResponse', function () { + it('should respond with empty response when there is empty serverResponse', function () { let result = spec.interpretResponse({ body: {} }, {}); assert.deepEqual(result, []); }); - it('should respond with empty response when response from server is not banner', () => { + it('should respond with empty response when response from server is not banner', function () { serverResponse.body[0].response = 'not banner'; serverResponse.body = [serverResponse.body[0]]; bidRequest.bids = [bidRequest.bids[0]]; @@ -144,7 +144,7 @@ describe('etarget adapter', () => { assert.deepEqual(result, []); }); - it('should interpret server response correctly with one bid', () => { + it('should interpret server response correctly with one bid', function () { serverResponse.body = [serverResponse.body[0]]; bidRequest.bids = [bidRequest.bids[0]]; let result = spec.interpretResponse(serverResponse, bidRequest)[0]; @@ -160,7 +160,7 @@ describe('etarget adapter', () => { assert.equal(result.transactionId, '5f33781f-9552-4ca1'); }); - it('should set correct netRevenue', () => { + it('should set correct netRevenue', function () { serverResponse.body = [serverResponse.body[0]]; bidRequest.bids = [bidRequest.bids[1]]; bidRequest.netRevenue = 'net'; @@ -169,22 +169,22 @@ describe('etarget adapter', () => { assert.equal(result.netRevenue, true); }); - it('should create bid response item for every requested item', () => { + it('should create bid response item for every requested item', function () { let result = spec.interpretResponse(serverResponse, bidRequest); assert.lengthOf(result, 5); }); - it('should create bid response with vast xml', () => { + it('should create bid response with vast xml', function () { const result = spec.interpretResponse(serverResponse, bidRequest)[3]; assert.equal(result.vastXml, ''); }); - it('should create bid response with vast url', () => { + it('should create bid response with vast url', function () { const result = spec.interpretResponse(serverResponse, bidRequest)[4]; assert.equal(result.vastUrl, 'vast://url'); }); - it('should set mediaType on bid response', () => { + it('should set mediaType on bid response', function () { const expected = [ BANNER, BANNER, BANNER, VIDEO, VIDEO ]; const result = spec.interpretResponse(serverResponse, bidRequest); for (let i = 0; i < result.length; i++) { @@ -192,7 +192,7 @@ describe('etarget adapter', () => { } }); - it('should set default netRevenue as gross', () => { + it('should set default netRevenue as gross', function () { bidRequest.netRevenue = 'gross'; const result = spec.interpretResponse(serverResponse, bidRequest); for (let i = 0; i < result.length; i++) { @@ -200,7 +200,7 @@ describe('etarget adapter', () => { } }); - it('should set gdpr if it exist in bidRequest', () => { + it('should set gdpr if it exist in bidRequest', function () { bidRequest.gdpr = { gdpr: true, gdpr_consent: 'ERW342EIOWT34234KMGds' @@ -219,8 +219,8 @@ describe('etarget adapter', () => { }; }); - describe('verifySizes', () => { - it('should respond with empty response when sizes doesn\'t match', () => { + describe('verifySizes', function () { + it('should respond with empty response when sizes doesn\'t match', function () { serverResponse.body[0].response = 'banner'; serverResponse.body[0].width = 100; serverResponse.body[0].height = 150; @@ -233,7 +233,7 @@ describe('etarget adapter', () => { assert.equal(serverResponse.body[0].response, 'banner'); assert.deepEqual(result, []); }); - it('should respond with empty response when sizes as a strings doesn\'t match', () => { + it('should respond with empty response when sizes as a strings doesn\'t match', function () { serverResponse.body[0].response = 'banner'; serverResponse.body[0].width = 100; serverResponse.body[0].height = 150; @@ -248,7 +248,7 @@ describe('etarget adapter', () => { assert.equal(serverResponse.body[0].response, 'banner'); assert.deepEqual(result, []); }); - it('should support size dimensions as a strings', () => { + it('should support size dimensions as a strings', function () { serverResponse.body[0].response = 'banner'; serverResponse.body[0].width = 300; serverResponse.body[0].height = 600; @@ -265,7 +265,7 @@ describe('etarget adapter', () => { }) }); - beforeEach(() => { + beforeEach(function () { let sizes = [[250, 300], [300, 250], [300, 600]]; let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; let params = [{refid: 1, country: 1, url: 'some// there'}, {refid: 2, country: 1, someVar: 'someValue', pt: 'gross'}, {refid: 3, country: 1, pdom: 'home'}, {refid: 5, country: 1, pt: 'net'}, {refid: 6, country: 1, pt: 'gross'}]; diff --git a/test/spec/modules/fairtradeBidAdapter_spec.js b/test/spec/modules/fairtradeBidAdapter_spec.js index 07c26e8f0c1..ecd5db3c051 100644 --- a/test/spec/modules/fairtradeBidAdapter_spec.js +++ b/test/spec/modules/fairtradeBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('FairTradeAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'fairtrade', 'params': { @@ -24,11 +24,11 @@ describe('FairTradeAdapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('FairTradeAdapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'fairtrade', @@ -75,7 +75,7 @@ describe('FairTradeAdapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); const payload = request.data; expect(payload).to.be.an('object'); @@ -85,7 +85,7 @@ describe('FairTradeAdapter', function () { expect(payload).to.have.property('r', '22edbae2733bf6'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); @@ -95,7 +95,7 @@ describe('FairTradeAdapter', function () { expect(payload).to.have.property('r', '22edbae2733bf6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -107,7 +107,7 @@ describe('FairTradeAdapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -120,7 +120,7 @@ describe('FairTradeAdapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 165, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 166, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -131,7 +131,7 @@ describe('FairTradeAdapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'fairtrade', @@ -165,7 +165,7 @@ describe('FairTradeAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'fairtrade', @@ -245,7 +245,7 @@ describe('FairTradeAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'fairtrade', diff --git a/test/spec/modules/fidelityBidAdapter_spec.js b/test/spec/modules/fidelityBidAdapter_spec.js index 007f4e6b480..e8e008103e6 100644 --- a/test/spec/modules/fidelityBidAdapter_spec.js +++ b/test/spec/modules/fidelityBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/fidelityBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('FidelityAdapter', () => { +describe('FidelityAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'fidelity', 'params': { @@ -26,11 +26,11 @@ describe('FidelityAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -39,7 +39,7 @@ describe('FidelityAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -49,7 +49,7 @@ describe('FidelityAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidderRequest = { bidderCode: 'fidelity', requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', @@ -75,7 +75,7 @@ describe('FidelityAdapter', () => { timeout: 5000 }; - it('should add source and verison to the tag', () => { + it('should add source and verison to the tag', function () { const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); const payload = request.data; expect(payload.from).to.exist; @@ -91,7 +91,7 @@ describe('FidelityAdapter', () => { expect(payload.defloc).to.exist; }); - it('should add gdpr consent information to the request', () => { + it('should add gdpr consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; bidderRequest.gdprConsent = { gdprApplies: true, @@ -112,14 +112,14 @@ describe('FidelityAdapter', () => { expect(payload.consent_given).to.equal(1); }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(request.url).to.equal('//t.fidelity-media.com/delivery/hb.php'); expect(request.method).to.equal('GET'); }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'id': '543210', 'seatbid': [ { @@ -134,7 +134,7 @@ describe('FidelityAdapter', () => { } ] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { requestId: 'bidId-123456-1', @@ -153,7 +153,7 @@ describe('FidelityAdapter', () => { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'id': '543210', 'seatbid': [ ] @@ -164,10 +164,10 @@ describe('FidelityAdapter', () => { }); }); - describe('user sync', () => { + describe('user sync', function () { const syncUrl = '//x.fidelity-media.com/delivery/matches.php?type=iframe'; - it('should register the sync iframe', () => { + it('should register the sync iframe', function () { expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({iframeEnabled: false})).to.be.undefined; const options = spec.getUserSyncs({iframeEnabled: true}); diff --git a/test/spec/modules/freewheel-sspBidAdapter_spec.js b/test/spec/modules/freewheel-sspBidAdapter_spec.js index 00c725027a1..adc6e1bcde4 100644 --- a/test/spec/modules/freewheel-sspBidAdapter_spec.js +++ b/test/spec/modules/freewheel-sspBidAdapter_spec.js @@ -1,197 +1,197 @@ -import { expect } from 'chai'; -import { spec } from 'modules/freewheel-sspBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; - -const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; - -describe('freewheel-ssp BidAdapter Test', () => { - const adapter = newBidder(spec); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - let bid = { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - - 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 zone id' - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', () => { - let bidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'gdprConsent': { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'gdprApplies': true - } - } - ]; - - it('should add parameters to the tag', () => { - const request = spec.buildRequests(bidRequests, bidRequests[0]); - const payload = request.data; - expect(payload.reqType).to.equal('AdsSetup'); - expect(payload.protocolVersion).to.equal('2.0'); - expect(payload.zoneId).to.equal('277225'); - expect(payload.componentId).to.equal('mustang'); - expect(payload.playerSize).to.equal('300x600'); - expect(payload._fw_gdpr).to.equal(true); - expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); - }); - - it('sends bid request to ENDPOINT via GET', () => { - const request = spec.buildRequests(bidRequests, bidRequests[0]); - expect(request.url).to.contain(ENDPOINT); - expect(request.method).to.equal('GET'); - }); - }) - - describe('interpretResponse', () => { - let bidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - let formattedBidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225', - 'format': 'floorad' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[600, 250], [300, 600]], - 'bidId': '30b3other1c1838de1e', - 'bidderRequestId': '22edbae273other3bf6', - 'auctionId': '1d1a03079test0a475', - }, - { - 'bidder': 'stickyadstv', - 'params': { - 'zoneId': '277225', - 'format': 'test' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 600]], - 'bidId': '2', - 'bidderRequestId': '3', - 'auctionId': '4', - } - ]; - - let response = '' + - '' + - ' ' + - ' Adswizz' + - ' ' + - ' ' + - ' ' + - ' 00:00:09' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' 0.2000' + - ' ' + - ' ' + - ' ' + - ''; - - let ad = '
'; - let formattedAd = '
'; - - it('should get correct bid response', () => { - var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - - let expectedResponse = [ - { - requestId: '30b31c1838de1e', - cpm: '0.2000', - width: 300, - height: 600, - creativeId: '28517153', - currency: 'EUR', - netRevenue: true, - ttl: 360, - ad: ad - } - ]; - - let result = spec.interpretResponse(response, request); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - - it('should get correct bid response with formated ad', () => { - var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - - let expectedResponse = [ - { - requestId: '30b31c1838de1e', - cpm: '0.2000', - width: 300, - height: 600, - creativeId: '28517153', - currency: 'EUR', - netRevenue: true, - ttl: 360, - ad: formattedAd - } - ]; - - let result = spec.interpretResponse(response, request); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - - it('handles nobid responses', () => { - var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - let response = ''; - - let result = spec.interpretResponse(response, reqest); - expect(result.length).to.equal(0); - }); - }); -}); +import { expect } from 'chai'; +import { spec } from 'modules/freewheel-sspBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; + +describe('freewheel-ssp BidAdapter Test', 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': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + wrong: 'missing zone id' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'gdprConsent': { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'gdprApplies': true + } + } + ]; + + it('should add parameters to the tag', function () { + const request = spec.buildRequests(bidRequests, bidRequests[0]); + const payload = request.data; + expect(payload.reqType).to.equal('AdsSetup'); + expect(payload.protocolVersion).to.equal('2.0'); + expect(payload.zoneId).to.equal('277225'); + expect(payload.componentId).to.equal('mustang'); + expect(payload.playerSize).to.equal('300x600'); + expect(payload._fw_gdpr).to.equal(true); + expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + }); + + it('sends bid request to ENDPOINT via GET', function () { + const request = spec.buildRequests(bidRequests, bidRequests[0]); + expect(request.url).to.contain(ENDPOINT); + expect(request.method).to.equal('GET'); + }); + }) + + describe('interpretResponse', function () { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + let formattedBidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225', + 'format': 'floorad' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[600, 250], [300, 600]], + 'bidId': '30b3other1c1838de1e', + 'bidderRequestId': '22edbae273other3bf6', + 'auctionId': '1d1a03079test0a475', + }, + { + 'bidder': 'stickyadstv', + 'params': { + 'zoneId': '277225', + 'format': 'test' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 600]], + 'bidId': '2', + 'bidderRequestId': '3', + 'auctionId': '4', + } + ]; + + let response = '' + + '' + + ' ' + + ' Adswizz' + + ' ' + + ' ' + + ' ' + + ' 00:00:09' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 0.2000' + + ' ' + + ' ' + + ' ' + + ''; + + let ad = '
'; + let formattedAd = '
'; + + it('should get correct bid response', function () { + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: ad + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('should get correct bid response with formated ad', function () { + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: formattedAd + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', function () { + var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + let response = ''; + + let result = spec.interpretResponse(response, reqest); + expect(result.length).to.equal(0); + }); + }); +}); diff --git a/test/spec/modules/fyberBidAdapter_spec.js b/test/spec/modules/fyberBidAdapter_spec.js index c6b49916519..a16c069d2a0 100644 --- a/test/spec/modules/fyberBidAdapter_spec.js +++ b/test/spec/modules/fyberBidAdapter_spec.js @@ -72,82 +72,82 @@ const mock = { } }; -describe('FyberAdapter', () => { +describe('FyberAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('callBids exists and is a function', () => { + describe('inherited functions', function () { + it('callBids exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('Verifies bidder code', () => { - it('Verifies bidder code', () => { + describe('Verifies bidder code', function () { + it('Verifies bidder code', function () { expect(spec.code).to.equal('fyber'); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { const bid = Object.assign({}, mock.bid); expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params{spotType} not found', () => { + it('should return false when required params{spotType} not found', function () { const bid = Object.assign({}, mock.bid); delete bid.params.spotType; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when required{appId} params not found', () => { + it('should return false when required{appId} params not found', function () { const bid = Object.assign({}, mock.bid); delete bid.params.appId; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidsRequest = Object.assign([], mock.bidsRequest); const requests = spec.buildRequests(bidsRequest); - it('Verify only one build request', () => { + it('Verify only one build request', function () { expect(requests.length).to.equal(1); }); const request = requests[0]; - it('Verify build request http method', () => { + it('Verify build request http method', function () { expect(request.method).to.equal('GET'); }); - it('Verify build request bidId', () => { + it('Verify build request bidId', function () { expect(request.bidId).to.equal(bidId); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const request = Object.assign([], mock.bidsRequest)[0]; const validResponse = Object.assign({}, mock.validResponse); const validResult = spec.interpretResponse(validResponse, request); - it('Verify only one bid response', () => { + it('Verify only one bid response', function () { expect(validResult.length).to.equal(1); }); const bidResponse = validResult[0]; - it('Verify CPM', () => { + it('Verify CPM', function () { expect(bidResponse.cpm).to.equal(10000); }); - it('Verify requestId', () => { + it('Verify requestId', function () { expect(bidResponse.requestId).to.equal(bidId); }); const invalidResponse = Object.assign({}, mock.invalidResponse); const invalidResult = spec.interpretResponse(invalidResponse, request); - it('Verify empty bid response', () => { + it('Verify empty bid response', function () { expect(invalidResult.length).to.equal(0); }); }); diff --git a/test/spec/modules/gambidBidAdapter_spec.js b/test/spec/modules/gambidBidAdapter_spec.js index 4c15d2113f1..06118f7f7d8 100644 --- a/test/spec/modules/gambidBidAdapter_spec.js +++ b/test/spec/modules/gambidBidAdapter_spec.js @@ -4,29 +4,29 @@ import * as utils from 'src/utils'; const supplyPartnerId = '123'; -describe('GambidAdapter', () => { - describe('isBidRequestValid', () => { - it('should validate supply-partner ID', () => { +describe('GambidAdapter', function () { + describe('isBidRequestValid', function () { + it('should validate supply-partner ID', function () { expect(spec.isBidRequestValid({ params: {} })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: 123 } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); }); - it('should validate RTB endpoint', () => { + it('should validate RTB endpoint', function () { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // RTB endpoint has a default expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', rtbEndpoint: 123 } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', rtbEndpoint: 'https://some.url.com' } })).to.equal(true); }); - it('should validate bid floor', () => { + it('should validate bid floor', function () { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // bidfloor has a default expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', bidfloor: '123' } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', bidfloor: 0.1 } })).to.equal(true); }); - it('should validate adpos', () => { + it('should validate adpos', function () { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // adpos has a default expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', adpos: '123' } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', adpos: 0.1 } })).to.equal(true); }); - it('should validate instl', () => { + it('should validate instl', function () { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // adpos has a default expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: '123' } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: -1 } })).to.equal(false); @@ -35,7 +35,7 @@ describe('GambidAdapter', () => { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: 2 } })).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequest = { 'adUnitCode': 'adunit-code', 'auctionId': '1d1a030790a475', @@ -49,7 +49,7 @@ describe('GambidAdapter', () => { 'transactionId': 'a123456789' }; - it('returns an array', () => { + it('returns an array', function () { let response; response = spec.buildRequests([]); @@ -67,7 +67,7 @@ describe('GambidAdapter', () => { expect(response.length).to.equal(2); }); - it('targets correct endpoint', () => { + it('targets correct endpoint', function () { let response; response = spec.buildRequests([ bidRequest ])[ 0 ]; @@ -81,7 +81,7 @@ describe('GambidAdapter', () => { expect(response.url).to.match(new RegExp(`^https://rtb2\\.gambid\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); }); - it('builds request correctly', () => { + it('builds request correctly', function () { let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); let response; @@ -114,7 +114,7 @@ describe('GambidAdapter', () => { stub.restore(); }); - it('builds request banner object correctly', () => { + it('builds request banner object correctly', function () { let response; const bidRequestWithBanner = utils.deepClone(bidRequest); @@ -136,7 +136,7 @@ describe('GambidAdapter', () => { expect(response.data.imp[ 0 ].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); - it('builds request video object correctly', () => { + it('builds request video object correctly', function () { let response; const bidRequestWithVideo = utils.deepClone(bidRequest); @@ -158,7 +158,7 @@ describe('GambidAdapter', () => { expect(response.data.imp[ 0 ].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bannerBidRequest = { 'adUnitCode': 'adunit-code', 'auctionId': '1d1a030790a475', @@ -249,7 +249,7 @@ describe('GambidAdapter', () => { } ] }; - it('returns an empty array on missing response', () => { + it('returns an empty array on missing response', function () { let response; response = spec.interpretResponse(undefined, { bidRequest: bannerBidRequest }); @@ -260,7 +260,7 @@ describe('GambidAdapter', () => { expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); }); - it('aggregates banner bids from all seat bids', () => { + it('aggregates banner bids from all seat bids', function () { const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: bannerBidRequest }); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); @@ -291,7 +291,7 @@ describe('GambidAdapter', () => { // expect(ad1.ad).to.be.an('undefined'); // expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); }); - it('aggregates video bids from all seat bids', () => { + it('aggregates video bids from all seat bids', function () { const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: videoBidRequest }); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); @@ -321,7 +321,7 @@ describe('GambidAdapter', () => { expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.vast_url); }); - it('aggregates user-sync pixels', () => { + it('aggregates user-sync pixels', function () { const response = spec.getUserSyncs({}, [ { body: rtbResponse } ]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(4); diff --git a/test/spec/modules/gammaBidAdapter_spec.js b/test/spec/modules/gammaBidAdapter_spec.js index 5ff959cfb21..99593e6e06f 100644 --- a/test/spec/modules/gammaBidAdapter_spec.js +++ b/test/spec/modules/gammaBidAdapter_spec.js @@ -22,26 +22,26 @@ describe('gammaBidAdapter', function() { }; let bidArray = [bid]; - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when require params are not passed', () => { + it('should return false when require params are not passed', function () { let bid = Object.assign({}, bid); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when params not passed correctly', () => { + it('should return false when params not passed correctly', function () { bid.params.siteId = ''; bid.params.zoneId = ''; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { - it('should attempt to send bid requests to the endpoint via GET', () => { + describe('buildRequests', function () { + it('should attempt to send bid requests to the endpoint via GET', function () { const requests = spec.buildRequests(bidArray); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); @@ -50,10 +50,10 @@ describe('gammaBidAdapter', function() { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse; - beforeEach(() => { + beforeEach(function () { serverResponse = { body: { 'id': '23beaa6af6cdde', @@ -77,7 +77,7 @@ describe('gammaBidAdapter', function() { }; }) - it('should get the correct bid response', () => { + it('should get the correct bid response', function () { let expectedResponse = [{ 'requestId': '23beaa6af6cdde', 'cpm': 0.45, @@ -94,7 +94,7 @@ describe('gammaBidAdapter', function() { expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: {} }; diff --git a/test/spec/modules/getintentBidAdapter_spec.js b/test/spec/modules/getintentBidAdapter_spec.js index 17f9a95fec4..ebbda7e108e 100644 --- a/test/spec/modules/getintentBidAdapter_spec.js +++ b/test/spec/modules/getintentBidAdapter_spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai' import { spec } from 'modules/getintentBidAdapter' -describe('GetIntent Adapter Tests:', () => { +describe('GetIntent Adapter Tests:', function () { const bidRequests = [{ bidId: 'bid12345', params: { @@ -34,7 +34,7 @@ describe('GetIntent Adapter Tests:', () => { mediaType: 'video' }; - it('Verify build request', () => { + it('Verify build request', function () { const serverRequests = spec.buildRequests(bidRequests); let serverRequest = serverRequests[0]; expect(serverRequest.url).to.equal('//px.adhigh.net/rtb/direct_banner'); @@ -48,7 +48,7 @@ describe('GetIntent Adapter Tests:', () => { expect(serverRequest.data.size).to.equal('50x50,100x100'); }); - it('Verify build video request', () => { + it('Verify build video request', function () { const serverRequests = spec.buildRequests([videoBidRequest]); let serverRequest = serverRequests[0]; expect(serverRequest.url).to.equal('//px.adhigh.net/rtb/direct_vast'); @@ -64,7 +64,7 @@ describe('GetIntent Adapter Tests:', () => { expect(serverRequest.data.skippable).to.equal(true); }); - it('Verify parse response', () => { + it('Verify parse response', function () { const serverResponse = { body: { bid_id: 'bid12345', @@ -90,7 +90,7 @@ describe('GetIntent Adapter Tests:', () => { expect(bid.ad).to.equal('Ad markup'); }); - it('Verify parse video response', () => { + it('Verify parse video response', function () { const serverResponse = { body: { bid_id: 'bid789', @@ -116,22 +116,22 @@ describe('GetIntent Adapter Tests:', () => { expect(bid.vastUrl).to.equal('//vast.xml/url'); }); - it('Verify bidder code', () => { + it('Verify bidder code', function () { expect(spec.code).to.equal('getintent'); }); - it('Verify bidder aliases', () => { + it('Verify bidder aliases', function () { expect(spec.aliases).to.have.lengthOf(1); expect(spec.aliases[0]).to.equal('getintentAdapter'); }); - it('Verify supported media types', () => { + it('Verify supported media types', function () { expect(spec.supportedMediaTypes).to.have.lengthOf(2); expect(spec.supportedMediaTypes[0]).to.equal('video'); expect(spec.supportedMediaTypes[1]).to.equal('banner'); }); - it('Verify if bid request valid', () => { + it('Verify if bid request valid', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); expect(spec.isBidRequestValid(bidRequests[1])).to.equal(true); expect(spec.isBidRequestValid({})).to.equal(false); diff --git a/test/spec/modules/giantsBidAdapter_spec.js b/test/spec/modules/giantsBidAdapter_spec.js index 69535cba13f..bab2415745d 100644 --- a/test/spec/modules/giantsBidAdapter_spec.js +++ b/test/spec/modules/giantsBidAdapter_spec.js @@ -1,301 +1,301 @@ -import { expect } from 'chai'; -import { spec } from 'modules/giantsBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; -import { deepClone } from 'src/utils'; -import * as utils from 'src/utils'; - -const ENDPOINT = '//d.admp.io/hb/multi?url='; - -describe('GiantsAdapter', () => { - const adapter = newBidder(spec); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - let bid = { - 'bidder': 'giants', - 'params': { - 'zoneId': '584072408' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - - 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 = { - 'zoneId': 0 - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', () => { - let bidRequests = [ - { - 'bidder': 'giants', - 'params': { - 'zoneId': '584072408' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - it('should parse out private sizes', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - zoneId: '584072408', - 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 source and verison to the tag', () => { - 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', () => { - ['banner', 'video', 'native'].forEach(type => { - 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]); - }); - }); - - it('should populate the ad_types array on outstream requests', () => { - 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']); - }); - - it('sends bid request to ENDPOINT via POST', () => { - const request = spec.buildRequests(bidRequests); - expect(request.url).to.equal(ENDPOINT + utils.getTopWindowUrl()); - expect(request.method).to.equal('POST'); - }); - - it('should attach valid video params to the tag', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - zoneId: '584072408', - 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 - }); - }); - - it('sets minimum native asset params when not provided on adunit', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: {required: true}, - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: {required: true, sizes: [{}]}, - }); - }); - - it('does not overwrite native ad unit params with mimimum params', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: { - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: { - required: true, - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - }, - }); - }); - - it('should convert keyword params to proper form and attaches to request', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - zoneId: '584072408', - keywords: { - single: 'val', - singleArr: ['val'], - singleArrNum: [5], - multiValMixed: ['value1', 2, 'value3'], - singleValNum: 123, - 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'] - }]); - }); - - it('should add payment rules to the request', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - zoneId: '584072408', - usePaymentRule: true - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].use_pmt_rule).to.equal(true); - }); - }) - - describe('interpretResponse', () => { - let response = { - 'version': '3.0.0', - 'tags': [ - { - 'uuid': '3db3773286ee59', - 'creative_id': '584944065', - 'height': 600, - 'width': 300, - 'zoneId': '584072408', - 'adUrl': '//d.admp.io/pbc/v1/cache-banner/f7aca005-8171-4299-90bf-0750a864a61c', - 'cpm': 0.5 - } - ] - }; - - it('should get correct bid response', () => { - let expectedResponse = [ - { - 'requestId': '3db3773286ee59', - 'cpm': 0.5, - 'creativeId': 29681110, - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 300, - 'width': 300, - 'height': 250, - 'ad': '', - 'mediaType': 'banner' - } - ]; - let bidderRequest; - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); - }); - - it('handles nobid responses', () => { - 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); - }); - }); -}); +import { expect } from 'chai'; +import { spec } from 'modules/giantsBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; +import * as utils from 'src/utils'; + +const ENDPOINT = '//d.admp.io/hb/multi?url='; + +describe('GiantsAdapter', 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': 'giants', + 'params': { + 'zoneId': '584072408' + }, + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'zoneId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'giants', + 'params': { + 'zoneId': '584072408' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should parse out private sizes', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + zoneId: '584072408', + 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 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 () { + ['banner', 'video', 'native'].forEach(type => { + 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]); + }); + }); + + 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']); + }); + + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT + utils.getTopWindowUrl()); + expect(request.method).to.equal('POST'); + }); + + it('should attach valid video params to the tag', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + zoneId: '584072408', + 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 + }); + }); + + it('sets minimum native asset params when not provided on adunit', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: {required: true}, + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: {required: true, sizes: [{}]}, + }); + }); + + it('does not overwrite native ad unit params with mimimum params', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: { + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: { + required: true, + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + }, + }); + }); + + it('should convert keyword params to proper form and attaches to request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + zoneId: '584072408', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + 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'] + }]); + }); + + it('should add payment rules to the request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + zoneId: '584072408', + usePaymentRule: true + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].use_pmt_rule).to.equal(true); + }); + }) + + describe('interpretResponse', function () { + let response = { + 'version': '3.0.0', + 'tags': [ + { + 'uuid': '3db3773286ee59', + 'creative_id': '584944065', + 'height': 600, + 'width': 300, + 'zoneId': '584072408', + 'adUrl': '//d.admp.io/pbc/v1/cache-banner/f7aca005-8171-4299-90bf-0750a864a61c', + 'cpm': 0.5 + } + ] + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + 'requestId': '3db3773286ee59', + 'cpm': 0.5, + 'creativeId': 29681110, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner' + } + ]; + let bidderRequest; + 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 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); + }); + }); +}); diff --git a/test/spec/modules/gjirafaBidAdapter_spec.js b/test/spec/modules/gjirafaBidAdapter_spec.js index 542e8185db5..d3aaf9765b2 100644 --- a/test/spec/modules/gjirafaBidAdapter_spec.js +++ b/test/spec/modules/gjirafaBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/gjirafaBidAdapter'; -describe('gjirafaAdapterTest', () => { - describe('bidRequestValidity', () => { - it('bidRequest with placementId, minCPM and minCPC params', () => { +describe('gjirafaAdapterTest', function () { + describe('bidRequestValidity', function () { + it('bidRequest with placementId, minCPM and minCPC params', function () { expect(spec.isBidRequestValid({ bidder: 'gjirafa', params: { @@ -14,7 +14,7 @@ describe('gjirafaAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with only placementId param', () => { + it('bidRequest with only placementId param', function () { expect(spec.isBidRequestValid({ bidder: 'gjirafa', params: { @@ -23,7 +23,7 @@ describe('gjirafaAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with minCPM and minCPC params', () => { + it('bidRequest with minCPM and minCPC params', function () { expect(spec.isBidRequestValid({ bidder: 'gjirafa', params: { @@ -33,7 +33,7 @@ describe('gjirafaAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with no placementId, minCPM or minCPC params', () => { + it('bidRequest with no placementId, minCPM or minCPC params', function () { expect(spec.isBidRequestValid({ bidder: 'gjirafa', params: { @@ -42,7 +42,7 @@ describe('gjirafaAdapterTest', () => { }); }); - describe('bidRequest', () => { + describe('bidRequest', function () { const bidRequests = [{ 'bidder': 'gjirafa', 'params': { @@ -74,14 +74,14 @@ describe('gjirafaAdapterTest', () => { 'consent_required': 'true' }]; - it('bidRequest HTTP method', () => { + it('bidRequest HTTP method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); - it('bidRequest url', () => { + it('bidRequest url', function () { const endpointUrl = 'https://gjc.gjirafa.com/Home/GetBid'; const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { @@ -89,20 +89,20 @@ describe('gjirafaAdapterTest', () => { }); }); - it('bidRequest data', () => { + it('bidRequest data', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.data).to.exists; }); }); - it('bidRequest sizes', () => { + it('bidRequest sizes', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].data.sizes).to.equal('728x90;980x200;980x150;970x90;970x250'); expect(requests[1].data.sizes).to.equal('300x250'); }); - it('should add GDPR data', () => { + it('should add GDPR data', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].data.consent_string).to.exists; expect(requests[0].data.consent_required).to.exists; @@ -111,7 +111,7 @@ describe('gjirafaAdapterTest', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequest = { 'method': 'GET', 'url': 'https://gjc.gjirafa.com/Home/GetBid', @@ -143,7 +143,7 @@ describe('gjirafaAdapterTest', () => { headers: {} }; - it('all keys present', () => { + it('all keys present', function () { const result = spec.interpretResponse(bidResponse, bidRequest); let keys = [ diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 23ad392ff1b..0c1431b71a5 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -4,16 +4,16 @@ import { spec } from 'modules/gumgumBidAdapter'; const ENDPOINT = 'https://g2.gumgum.com/hbid/imp'; -describe('gumgumAdapter', () => { +describe('gumgumAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'gumgum', 'params': { @@ -26,11 +26,11 @@ describe('gumgumAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,7 +40,7 @@ describe('gumgumAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -50,7 +50,7 @@ describe('gumgumAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'gumgum', @@ -63,20 +63,20 @@ describe('gumgumAdapter', () => { } ]; - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET'); expect(request.id).to.equal('30b31c1838de1e'); }); - it('should add consent parameters if gdprConsent is present', () => { + it('should add consent parameters if gdprConsent is present', function () { const gdprConsent = { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', gdprApplies: true }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; expect(bidRequest.data.gdprApplies).to.eq(true); expect(bidRequest.data.gdprConsent).to.eq('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); - it('should handle gdprConsent is present but values are undefined case', () => { + it('should handle gdprConsent is present but values are undefined case', function () { const gdprConsent = { consent_string: undefined, gdprApplies: undefined }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; @@ -84,7 +84,7 @@ describe('gumgumAdapter', () => { }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse = { 'ad': { 'id': 29593, @@ -115,7 +115,7 @@ describe('gumgumAdapter', () => { pi: 3 } - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = { 'ad': '

I am an ad

', 'cpm': 0, @@ -132,7 +132,7 @@ describe('gumgumAdapter', () => { expect(spec.interpretResponse({ body: serverResponse }, bidRequest)).to.deep.equal([expectedResponse]); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'ad': {}, 'pag': { @@ -147,7 +147,7 @@ describe('gumgumAdapter', () => { expect(result.length).to.equal(0); }); - it('returns 1x1 when eligible product and size available', () => { + it('returns 1x1 when eligible product and size available', function () { let inscreenBidRequest = { id: 12346, sizes: [[300, 250], [1, 1]], @@ -184,7 +184,7 @@ describe('gumgumAdapter', () => { expect(result[0].height).to.equal('1'); }) }) - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const syncOptions = { 'iframeEnabled': 'true' } diff --git a/test/spec/modules/gxoneBidAdapter_spec.js b/test/spec/modules/gxoneBidAdapter_spec.js index f34f4358490..afeb2c781f5 100644 --- a/test/spec/modules/gxoneBidAdapter_spec.js +++ b/test/spec/modules/gxoneBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('GXOne Adapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'gxone', 'params': { @@ -24,11 +24,11 @@ describe('GXOne Adapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('GXOne Adapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { function parseRequest(url) { const res = {}; url.split('&').forEach((it) => { @@ -83,7 +83,7 @@ describe('GXOne Adapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -92,7 +92,7 @@ describe('GXOne Adapter', function () { expect(payload).to.have.property('auids', '5'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -101,7 +101,7 @@ describe('GXOne Adapter', function () { expect(payload).to.have.property('auids', '5,6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -112,7 +112,7 @@ describe('GXOne Adapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -124,7 +124,7 @@ describe('GXOne Adapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -135,7 +135,7 @@ describe('GXOne Adapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'gxone', @@ -169,7 +169,7 @@ describe('GXOne Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'gxone', @@ -249,7 +249,7 @@ describe('GXOne Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'gxone', diff --git a/test/spec/modules/huddledmassesBidAdapter_spec.js b/test/spec/modules/huddledmassesBidAdapter_spec.js index f98bc06d0da..7823ae53c12 100644 --- a/test/spec/modules/huddledmassesBidAdapter_spec.js +++ b/test/spec/modules/huddledmassesBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/huddledmassesBidAdapter'; -describe('HuddledmassesAdapter', () => { +describe('HuddledmassesAdapter', function () { let bid = { bidId: '2dd581a2b6281d', bidder: 'huddledmasses', @@ -15,35 +15,35 @@ describe('HuddledmassesAdapter', () => { transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' }; - describe('isBidRequestValid', () => { - it('Should return true when placement_id can be cast to a number, and when at least one of the sizes passed is allowed', () => { + describe('isBidRequestValid', function () { + it('Should return true when placement_id can be cast to a number, and when at least one of the sizes passed is allowed', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false when placement_id is not a number', () => { + it('Should return false when placement_id is not a number', function () { bid.params.placement_id = 'aaa'; expect(spec.isBidRequestValid(bid)).to.be.false; }); - it('Should return false when the sizes are not allowed', () => { + it('Should return false when the sizes are not allowed', function () { bid.sizes = [[1, 1]]; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + 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', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//huddledmassessupply.com/?c=o&m=multi'); }); - it('Returns valid data if array of bids is valid', () => { + 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'); @@ -62,13 +62,13 @@ describe('HuddledmassesAdapter', () => { expect(placement.sizes).to.be.an('array'); } }); - it('Returns empty data if no valid requests are passed', () => { + 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', () => { + describe('interpretResponse', function () { let resObject = { body: [ { requestId: '123', @@ -83,7 +83,7 @@ describe('HuddledmassesAdapter', () => { } ] }; let serverResponses = spec.interpretResponse(resObject); - it('Returns an array of valid server responses if response object is valid', () => { + it('Returns an array of valid server responses if response object is valid', function () { expect(serverResponses).to.be.an('array').that.is.not.empty; for (let i = 0; i < serverResponses.length; i++) { let dataItem = serverResponses[i]; @@ -99,16 +99,16 @@ describe('HuddledmassesAdapter', () => { expect(dataItem.netRevenue).to.be.a('boolean'); expect(dataItem.currency).to.be.a('string'); } - it('Returns an empty array if invalid response is passed', () => { + it('Returns an empty array if invalid response is passed', function () { serverResponses = spec.interpretResponse('invalid_response'); expect(serverResponses).to.be.an('array').that.is.empty; }); }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let userSync = spec.getUserSyncs(); - it('Returns valid URL and type', () => { + 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; diff --git a/test/spec/modules/iasBidAdapter_spec.js b/test/spec/modules/iasBidAdapter_spec.js index 1ee38999f7f..21ef9f8e15a 100644 --- a/test/spec/modules/iasBidAdapter_spec.js +++ b/test/spec/modules/iasBidAdapter_spec.js @@ -1,15 +1,15 @@ import { expect } from 'chai'; import { spec } from 'modules/iasBidAdapter'; -describe('iasBidAdapter is an adapter that', () => { - it('has the correct bidder code', () => { +describe('iasBidAdapter is an adapter that', function () { + it('has the correct bidder code', function () { expect(spec.code).to.equal('ias'); }); - describe('has a method `isBidRequestValid` that', () => { - it('exists', () => { + describe('has a method `isBidRequestValid` that', function () { + it('exists', function () { expect(spec.isBidRequestValid).to.be.a('function'); }); - it('returns false if bid params misses `pubId`', () => { + it('returns false if bid params misses `pubId`', function () { expect(spec.isBidRequestValid( { params: { @@ -17,7 +17,7 @@ describe('iasBidAdapter is an adapter that', () => { } })).to.equal(false); }); - it('returns false if bid params misses `adUnitPath`', () => { + it('returns false if bid params misses `adUnitPath`', function () { expect(spec.isBidRequestValid( { params: { @@ -25,7 +25,7 @@ describe('iasBidAdapter is an adapter that', () => { } })).to.equal(false); }); - it('returns true otherwise', () => { + it('returns true otherwise', function () { expect(spec.isBidRequestValid( { params: { @@ -37,13 +37,13 @@ describe('iasBidAdapter is an adapter that', () => { }); }); - describe('has a method `buildRequests` that', () => { - it('exists', () => { + describe('has a method `buildRequests` that', function () { + it('exists', function () { expect(spec.buildRequests).to.be.a('function'); }); - describe('given bid requests, returns a `ServerRequest` instance that', () => { + describe('given bid requests, returns a `ServerRequest` instance that', function () { let bidRequests, IAS_HOST; - beforeEach(() => { + beforeEach(function () { IAS_HOST = '//pixel.adsafeprotected.com/services/pub'; bidRequests = [ { @@ -79,20 +79,20 @@ describe('iasBidAdapter is an adapter that', () => { } ]; }); - it('has property `method` of `GET`', () => { + it('has property `method` of `GET`', function () { expect(spec.buildRequests(bidRequests)).to.deep.include({ method: 'GET' }); }); - it('has property `url` to be the correct IAS endpoint', () => { + it('has property `url` to be the correct IAS endpoint', function () { expect(spec.buildRequests(bidRequests)).to.deep.include({ url: IAS_HOST }); }); - it('only includes the first `bidRequest` as the bidRequest variable on a multiple slot request', () => { + it('only includes the first `bidRequest` as the bidRequest variable on a multiple slot request', function () { expect(spec.buildRequests(bidRequests).bidRequest.adUnitCode).to.equal(bidRequests[0].adUnitCode); }); - describe('has property `data` that is an encode query string containing information such as', () => { + describe('has property `data` that is an encode query string containing information such as', function () { let val; const ANID_PARAM = 'anId'; const SLOT_PARAM = 'slot'; @@ -100,35 +100,37 @@ describe('iasBidAdapter is an adapter that', () => { const SLOT_SIZE_PARAM = 'ss'; const SLOT_AD_UNIT_PATH_PARAM = 'p'; - beforeEach(() => val = decodeURI(spec.buildRequests(bidRequests).data)); - it('publisher id', () => { + beforeEach(function () { + val = decodeURI(spec.buildRequests(bidRequests).data); + }); + it('publisher id', function () { expect(val).to.have.string(`${ANID_PARAM}=1234`); }); - it('ad slot`s id, size and ad unit path', () => { + it('ad slot`s id, size and ad unit path', function () { expect(val).to.have.string(`${SLOT_PARAM}={${SLOT_ID_PARAM}:one-div-id,${SLOT_SIZE_PARAM}:[10.20,300.400],${SLOT_AD_UNIT_PATH_PARAM}:/a/b/c}`); expect(val).to.have.string(`${SLOT_PARAM}={${SLOT_ID_PARAM}:two-div-id,${SLOT_SIZE_PARAM}:[50.60],${SLOT_AD_UNIT_PATH_PARAM}:/d/e/f}`); }); - it('window size', () => { + it('window size', function () { expect(val).to.match(/.*wr=[0-9]*\.[0-9]*/); }); - it('screen size', () => { + it('screen size', function () { expect(val).to.match(/.*sr=[0-9]*\.[0-9]*/); }); }); - it('has property `bidRequest` that is the first passed in bid request', () => { + it('has property `bidRequest` that is the first passed in bid request', function () { expect(spec.buildRequests(bidRequests)).to.deep.include({ bidRequest: bidRequests[0] }); }); }); }); - describe('has a method `interpretResponse` that', () => { - it('exists', () => { + describe('has a method `interpretResponse` that', function () { + it('exists', function () { expect(spec.interpretResponse).to.be.a('function'); }); - describe('returns a list of bid response that', () => { + describe('returns a list of bid response that', function () { let bidRequests, bidResponse, slots, serverResponse; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { adUnitCode: 'one-div-id', @@ -194,34 +196,34 @@ describe('iasBidAdapter is an adapter that', () => { }; bidResponse = spec.interpretResponse(serverResponse, request); }); - it('has IAS keyword `adt` as property', () => { + it('has IAS keyword `adt` as property', function () { expect(bidResponse[0]).to.deep.include({ adt: 'adtVal' }); }); - it('has IAS keyword `alc` as property', () => { + it('has IAS keyword `alc` as property', function () { expect(bidResponse[0]).to.deep.include({ alc: 'alcVal' }); }); - it('has IAS keyword `dlm` as property', () => { + it('has IAS keyword `dlm` as property', function () { expect(bidResponse[0]).to.deep.include({ dlm: 'dlmVal' }); }); - it('has IAS keyword `drg` as property', () => { + it('has IAS keyword `drg` as property', function () { expect(bidResponse[0]).to.deep.include({ drg: 'drgVal' }); }); - it('has IAS keyword `hat` as property', () => { + it('has IAS keyword `hat` as property', function () { expect(bidResponse[0]).to.deep.include({ hat: 'hatVal' }); }); - it('has IAS keyword `off` as property', () => { + it('has IAS keyword `off` as property', function () { expect(bidResponse[0]).to.deep.include({ off: 'offVal' }); }); - it('has IAS keyword `vio` as property', () => { + it('has IAS keyword `vio` as property', function () { expect(bidResponse[0]).to.deep.include({ vio: 'vioVal' }); }); - it('has IAS keyword `fr` as property', () => { + it('has IAS keyword `fr` as property', function () { expect(bidResponse[0]).to.deep.include({ fr: 'false' }); }); - it('has property `slots`', () => { + it('has property `slots`', function () { expect(bidResponse[0]).to.deep.include({ slots: slots }); }); - it('response is the same for multiple slots', () => { + it('response is the same for multiple slots', function () { var adapter = spec; var requests = adapter.buildRequests(bidRequests); expect(adapter.interpretResponse(serverResponse, requests)).to.length(2); diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index b3e99b3274e..bab469b936e 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -40,22 +40,22 @@ describe('Improve Digital Adapter Tests', function () { }, }; - describe('isBidRequestValid', () => { - it('should return false when no bid', () => { + describe('isBidRequestValid', function () { + it('should return false when no bid', function () { expect(spec.isBidRequestValid()).to.equal(false); }); - it('should return false when no bid.params', () => { + it('should return false when no bid.params', function () { let bid = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when both placementId and placementKey + publisherId are missing', () => { + it('should return false when both placementId and placementKey + publisherId are missing', function () { let bid = { 'params': {} }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when only one of placementKey and publisherId is present', () => { + it('should return false when only one of placementKey and publisherId is present', function () { let bid = { params: { publisherId: 1234 @@ -70,19 +70,19 @@ describe('Improve Digital Adapter Tests', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true when placementId is passed', () => { + it('should return true when placementId is passed', function () { let bid = { 'params': {} }; expect(spec.isBidRequestValid(simpleBidRequest)).to.equal(true); }); - it('should return true when both placementKey and publisherId are passed', () => { + it('should return true when both placementKey and publisherId are passed', function () { let bid = { 'params': {} }; expect(spec.isBidRequestValid(simpleSmartTagBidRequest)).to.equal(true); }); }); - describe('buildRequests', () => { - it('should make a well-formed request objects', () => { + describe('buildRequests', function () { + it('should make a well-formed request objects', function () { const requests = spec.buildRequests([simpleBidRequest]); expect(requests).to.be.an('array'); expect(requests.length).to.equal(1); @@ -106,14 +106,14 @@ describe('Improve Digital Adapter Tests', function () { ]); }); - it('should set placementKey and publisherId for smart tags', () => { + it('should set placementKey and publisherId for smart tags', function () { const requests = spec.buildRequests([simpleSmartTagBidRequest]); const params = JSON.parse(requests[0].data.substring(PARAM_PREFIX.length)); expect(params.bid_request.imp[0].pubid).to.equal(1032); expect(params.bid_request.imp[0].pkey).to.equal('data_team_test_hb_smoke_test'); }); - it('should add keyValues', () => { + it('should add keyValues', function () { let bidRequest = Object.assign({}, simpleBidRequest); const keyValues = { testKey: [ @@ -126,7 +126,7 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.imp[0].kvw).to.deep.equal(keyValues); }); - it('should add size', () => { + it('should add size', function () { let bidRequest = Object.assign({}, simpleBidRequest); const size = { w: 800, @@ -138,7 +138,7 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.imp[0].banner).to.deep.equal(size); }); - it('should add currency', () => { + it('should add currency', function () { const bidRequest = Object.assign({}, simpleBidRequest); const getConfigStub = sinon.stub(config, 'getConfig').returns('JPY'); const request = spec.buildRequests([bidRequest])[0]; @@ -147,14 +147,14 @@ describe('Improve Digital Adapter Tests', function () { getConfigStub.restore(); }); - it('should add GDPR consent string', () => { + it('should add GDPR consent string', function () { const bidRequest = Object.assign({}, simpleBidRequest); const request = spec.buildRequests([bidRequest], bidderRequest)[0]; const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); expect(params.bid_request.gdpr).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); - it('should return 2 requests', () => { + it('should return 2 requests', function () { const requests = spec.buildRequests([ simpleBidRequest, simpleSmartTagBidRequest @@ -218,7 +218,7 @@ describe('Improve Digital Adapter Tests', function () { } }; - describe('interpretResponse', () => { + describe('interpretResponse', function () { let expectedBid = [ { 'ad': '', @@ -250,17 +250,17 @@ describe('Improve Digital Adapter Tests', function () { } ]; - it('should return a well-formed bid', () => { + it('should return a well-formed bid', function () { const bids = spec.interpretResponse(serverResponse); expect(bids).to.deep.equal(expectedBid); }); - it('should return two bids', () => { + it('should return two bids', function () { const bids = spec.interpretResponse(serverResponseTwoBids); expect(bids).to.deep.equal(expectedTwoBids); }); - it('should set dealId correctly', () => { + it('should set dealId correctly', function () { let response = JSON.parse(JSON.stringify(serverResponse)); let bids; @@ -279,14 +279,14 @@ describe('Improve Digital Adapter Tests', function () { expect(bids[0].dealId).to.equal(268515); }); - it('should set currency', () => { + it('should set currency', function () { let response = JSON.parse(JSON.stringify(serverResponse)); response.body.bid[0].currency = 'eur'; const bids = spec.interpretResponse(response); expect(bids[0].currency).to.equal('EUR'); }); - it('should return empty array for bad response or no price', () => { + it('should return empty array for bad response or no price', function () { let response = JSON.parse(JSON.stringify(serverResponse)); let bids; @@ -323,7 +323,7 @@ describe('Improve Digital Adapter Tests', function () { expect(bids).to.deep.equal([]); }); - it('should set netRevenue', () => { + it('should set netRevenue', function () { let response = JSON.parse(JSON.stringify(serverResponse)); response.body.bid[0].isNet = true; const bids = spec.interpretResponse(response); @@ -331,15 +331,15 @@ describe('Improve Digital Adapter Tests', function () { }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const serverResponses = [ serverResponseTwoBids ]; - it('should return no syncs when pixel syncing is disabled', () => { + it('should return no syncs when pixel syncing is disabled', function () { const syncs = spec.getUserSyncs({ pixelEnabled: false }, serverResponses); expect(syncs).to.deep.equal([]); }); - it('should return user syncs', () => { + it('should return user syncs', function () { const syncs = spec.getUserSyncs({ pixelEnabled: true }, serverResponses); const expected = [ { type: 'image', url: 'http://link1' }, diff --git a/test/spec/modules/innityBidAdapter_spec.js b/test/spec/modules/innityBidAdapter_spec.js index 87042ca6a6d..0132f093ca1 100644 --- a/test/spec/modules/innityBidAdapter_spec.js +++ b/test/spec/modules/innityBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/innityBidAdapter'; -describe('innityAdapterTest', () => { - describe('bidRequestValidity', () => { - it('bidRequest with pub ID and zone ID param', () => { +describe('innityAdapterTest', function () { + describe('bidRequestValidity', function () { + it('bidRequest with pub ID and zone ID param', function () { expect(spec.isBidRequestValid({ bidder: 'innity', params: { @@ -13,7 +13,7 @@ describe('innityAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with no required params', () => { + it('bidRequest with no required params', function () { expect(spec.isBidRequestValid({ bidder: 'innity', params: { @@ -22,7 +22,7 @@ describe('innityAdapterTest', () => { }); }); - describe('bidRequest', () => { + describe('bidRequest', function () { const bidRequests = [{ 'bidder': 'innity', 'params': { @@ -37,14 +37,14 @@ describe('innityAdapterTest', () => { 'auctionId': '18fd8b8b0bd757' }]; - it('bidRequest HTTP method', () => { + it('bidRequest HTTP method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); - it('bidRequest data', () => { + it('bidRequest data', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].data.pub).to.equal(267); expect(requests[0].data.zone).to.equal(62546); @@ -54,7 +54,7 @@ describe('innityAdapterTest', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequest = { 'method': 'GET', 'url': 'https://as.innity.com/synd/?', @@ -85,7 +85,7 @@ describe('innityAdapterTest', () => { headers: {} }; - it('result is correct', () => { + it('result is correct', function () { const result = spec.interpretResponse(bidResponse, bidRequest); expect(result[0].requestId).to.equal('51ef8751f9aead'); expect(result[0].cpm).to.equal(1); diff --git a/test/spec/modules/inskinBidAdapter_spec.js b/test/spec/modules/inskinBidAdapter_spec.js index 40a84525ffa..24ae9321954 100644 --- a/test/spec/modules/inskinBidAdapter_spec.js +++ b/test/spec/modules/inskinBidAdapter_spec.js @@ -99,11 +99,11 @@ const RESPONSE = { } }; -describe('InSkin BidAdapter', () => { +describe('InSkin BidAdapter', function () { let bidRequests; let adapter = spec; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'inskin', @@ -121,8 +121,8 @@ describe('InSkin BidAdapter', () => { ]; }); - describe('bid request validation', () => { - it('should accept valid bid requests', () => { + describe('bid request validation', function () { + it('should accept valid bid requests', function () { let bid = { bidder: 'inskin', params: { @@ -133,7 +133,7 @@ describe('InSkin BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should accept valid bid requests with extra fields', () => { + it('should accept valid bid requests with extra fields', function () { let bid = { bidder: 'inskin', params: { @@ -145,7 +145,7 @@ describe('InSkin BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should reject bid requests without siteId', () => { + it('should reject bid requests without siteId', function () { let bid = { bidder: 'inskin', params: { @@ -155,7 +155,7 @@ describe('InSkin BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should reject bid requests without networkId', () => { + it('should reject bid requests without networkId', function () { let bid = { bidder: 'inskin', params: { @@ -166,31 +166,31 @@ describe('InSkin BidAdapter', () => { }); }); - describe('buildRequests validation', () => { - it('creates request data', () => { + describe('buildRequests validation', function () { + it('creates request data', function () { let request = spec.buildRequests(bidRequests); expect(request).to.exist.and.to.be.a('object'); }); - it('request to inskin should contain a url', () => { + it('request to inskin should contain a url', function () { let request = spec.buildRequests(bidRequests); expect(request.url).to.have.string('inskinad.com'); }); - it('requires valid bids to make request', () => { + it('requires valid bids to make request', function () { let request = spec.buildRequests([]); expect(request.bidRequest).to.be.empty; }); - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { let request = spec.buildRequests(bidRequests); expect(request.method).to.have.string('POST'); }); - it('should add gdpr consent information to the request', () => { + it('should add gdpr consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { 'bidderCode': 'inskin', @@ -210,21 +210,21 @@ describe('InSkin BidAdapter', () => { expect(payload.consent.gdprConsentRequired).to.exist.and.to.be.true; }); }); - describe('interpretResponse validation', () => { - it('response should have valid bidderCode', () => { + describe('interpretResponse validation', function () { + it('response should have valid bidderCode', function () { let bidRequest = spec.buildRequests(REQUEST.bidRequest); let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('inskin'); }); - it('response should include objects for all bids', () => { + it('response should include objects for all bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); expect(bids.length).to.equal(2); }); - it('registers bids', () => { + it('registers bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); bids.forEach(b => { expect(b).to.have.property('cpm'); @@ -242,34 +242,34 @@ describe('InSkin BidAdapter', () => { }); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {'decisions': null}}) let bids = spec.interpretResponse(EMPTY_RESP, REQUEST); expect(bids).to.be.empty; }); - it('handles no server response', () => { + it('handles no server response', function () { let bids = spec.interpretResponse(null, REQUEST); expect(bids).to.be.empty; }); }); - describe('getUserSyncs', () => { - it('handles empty sync options', () => { + describe('getUserSyncs', function () { + it('handles empty sync options', function () { let opts = spec.getUserSyncs({}); expect(opts).to.be.empty; }); - it('should return two sync urls if pixel syncs are enabled', () => { + it('should return two sync urls if pixel syncs are enabled', function () { let syncOptions = {'pixelEnabled': true}; let opts = spec.getUserSyncs(syncOptions); expect(opts.length).to.equal(2); }); - it('should return three sync urls if pixel and iframe syncs are enabled', () => { + it('should return three sync urls if pixel and iframe syncs are enabled', function () { let syncOptions = {'iframeEnabled': true, 'pixelEnabled': true}; let opts = spec.getUserSyncs(syncOptions); diff --git a/test/spec/modules/interactiveOffersBidAdapter_spec.js b/test/spec/modules/interactiveOffersBidAdapter_spec.js index 6cf09cf6149..8921a302738 100644 --- a/test/spec/modules/interactiveOffersBidAdapter_spec.js +++ b/test/spec/modules/interactiveOffersBidAdapter_spec.js @@ -1,10 +1,10 @@ import {expect} from 'chai'; import {spec} from 'modules/interactiveOffersBidAdapter'; -describe('interactiveOffers adapter', () => { - describe('implementation', () => { - describe('for requests', () => { - it('should accept valid bid', () => { +describe('interactiveOffers adapter', function () { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { let validBid = { bidder: 'interactiveOffers', params: { @@ -16,7 +16,7 @@ describe('interactiveOffers adapter', () => { expect(isValid).to.equal(true); }); - it('should reject invalid bid', () => { + it('should reject invalid bid', function () { let invalidBid = { bidder: 'interactiveOffers' }, @@ -25,8 +25,8 @@ describe('interactiveOffers adapter', () => { expect(isValid).to.equal(false); }); }); - describe('for requests', () => { - it('should accept valid bid with optional params', () => { + describe('for requests', function () { + it('should accept valid bid with optional params', function () { let validBid = { bidder: 'interactiveOffers', params: { @@ -44,7 +44,7 @@ describe('interactiveOffers adapter', () => { expect(requestUrlCustomParams).have.property('tmax', 1500); }); - it('should accept valid bid without optional params', () => { + it('should accept valid bid without optional params', function () { let validBid = { bidder: 'interactiveOffers', params: { @@ -60,7 +60,7 @@ describe('interactiveOffers adapter', () => { expect(requestUrlCustomParams).have.property('tmax'); }); - it('should reject invalid bid without pubId', () => { + it('should reject invalid bid without pubId', function () { let invalidBid = { bidder: 'interactiveOffers', params: {} @@ -70,8 +70,8 @@ describe('interactiveOffers adapter', () => { expect(isValid).to.equal(false); }); }); - describe('bid responses', () => { - it('should return complete bid response', () => { + describe('bid responses', function () { + it('should return complete bid response', function () { let serverResponse = { body: { 'success': 'true', @@ -104,7 +104,7 @@ describe('interactiveOffers adapter', () => { expect(bids[0].ad).to.have.length.above(1); }); - it('should return empty bid response', () => { + it('should return empty bid response', function () { let bidRequests = [ { bidder: 'interactiveOffers', @@ -128,7 +128,7 @@ describe('interactiveOffers adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with error', () => { + it('should return empty bid response with error', function () { let bidRequests = [ { bidder: 'interactiveOffers', @@ -143,7 +143,7 @@ describe('interactiveOffers adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response without payload', () => { + it('should return empty bid response without payload', function () { let bidRequests = [ { bidder: 'interactiveOffers', @@ -158,7 +158,7 @@ describe('interactiveOffers adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on empty body', () => { + it('should return empty bid response on empty body', function () { let bidRequests = [ { bidder: 'interactiveOffers', diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js index f6f601e0efc..d0fa627929e 100644 --- a/test/spec/modules/invibesBidAdapter_spec.js +++ b/test/spec/modules/invibesBidAdapter_spec.js @@ -86,19 +86,19 @@ describe('invibesBidAdapter:', function () { }); }); - describe('buildRequests', () => { - it('sends bid request to ENDPOINT via GET', () => { + describe('buildRequests', function () { + it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET'); }); - it('sends cookies with the bid request', () => { + it('sends cookies with the bid request', function () { const request = spec.buildRequests(bidRequests); expect(request.options.withCredentials).to.equal(true); }); - it('has location, html id, placement and width/height', () => { + it('has location, html id, placement and width/height', function () { const request = spec.buildRequests(bidRequests, { auctionStart: Date.now() }); const parsedData = request.data; expect(parsedData.location).to.exist; @@ -108,53 +108,53 @@ describe('invibesBidAdapter:', function () { expect(parsedData.height).to.exist; }); - it('sends all Placement Ids', () => { + it('sends all Placement Ids', function () { const request = spec.buildRequests(bidRequests); expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[0].params.placementId); expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[1].params.placementId); }); - it('uses cookies', () => { + it('uses cookies', function () { global.document.cookie = 'ivNoCookie=1'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.be.undefined; }); - it('doesnt send the domain id if not graduated', () => { + it('doesnt send the domain id if not graduated', function () { global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1522929537626,"hc":1}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.not.exist; }); - it('graduate and send the domain id', () => { + it('graduate and send the domain id', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":7}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.exist; }); - it('send the domain id if already graduated', () => { + it('send the domain id if already graduated', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"f8zoh044p9oi"}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.exist; }); - it('send the domain id after replacing it with new format', () => { + it('send the domain id after replacing it with new format', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"f8zoh044p9oi.8537626"}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.exist; }); - it('try to graduate but not enough count - doesnt send the domain id', () => { + it('try to graduate but not enough count - doesnt send the domain id', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":5}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.not.exist; }); - it('try to graduate but not old enough - doesnt send the domain id', () => { + it('try to graduate but not old enough - doesnt send the domain id', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":' + Date.now() + ',"hc":5}'; let request = spec.buildRequests(bidRequests); @@ -194,55 +194,55 @@ describe('invibesBidAdapter:', function () { }]; context('when the response is not valid', function () { - it('handles response with no bids requested', () => { + it('handles response with no bids requested', function () { let emptyResult = spec.interpretResponse({ body: response }); expect(emptyResult).to.be.empty; }); - it('handles empty response', () => { + it('handles empty response', function () { let emptyResult = spec.interpretResponse(null, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response with bidding is not configured', () => { + it('handles response with bidding is not configured', function () { let emptyResult = spec.interpretResponse({ body: { Ads: [{ BidPrice: 1 }] } }, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response with no ads are received', () => { + it('handles response with no ads are received', function () { let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '12345' }, AdReason: 'No ads' } }, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response with no ads are received - no ad reason', () => { + it('handles response with no ads are received - no ad reason', function () { let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '12345' } } }, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response when no placement Id matches', () => { + it('handles response when no placement Id matches', function () { let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '123456' }, Ads: [{ BidPrice: 1 }] } }, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response when placement Id is not present', () => { + it('handles response when placement Id is not present', function () { let emptyResult = spec.interpretResponse({ BidModel: { }, Ads: [{ BidPrice: 1 }] }, { bidRequests }); expect(emptyResult).to.be.empty; }); }); context('when the response is valid', function () { - it('responds with a valid bid', () => { + it('responds with a valid bid', function () { let result = spec.interpretResponse({ body: response }, { bidRequests }); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('responds with a valid bid and uses logger', () => { + it('responds with a valid bid and uses logger', function () { localStorage.InvibesDEBUG = true; let result = spec.interpretResponse({ body: response }, { bidRequests }); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('does not make multiple bids', () => { + it('does not make multiple bids', function () { localStorage.InvibesDEBUG = false; let result = spec.interpretResponse({ body: response }, { bidRequests }); let secondResult = spec.interpretResponse({ body: response }, { bidRequests }); @@ -252,13 +252,13 @@ describe('invibesBidAdapter:', function () { }); describe('getUserSyncs', function () { - it('returns an iframe if enabled', () => { + it('returns an iframe if enabled', function () { let response = spec.getUserSyncs({iframeEnabled: true}); expect(response.type).to.equal('iframe'); expect(response.url).to.include(SYNC_ENDPOINT); }); - it('returns an iframe with params if enabled', () => { + it('returns an iframe with params if enabled', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivvbks=17639.0,1,2'; let response = spec.getUserSyncs({ iframeEnabled: true }); @@ -269,7 +269,7 @@ describe('invibesBidAdapter:', function () { expect(response.url).to.include('ivbsdid'); }); - it('returns undefined if iframe not enabled ', () => { + it('returns undefined if iframe not enabled ', function () { let response = spec.getUserSyncs({ iframeEnabled: false }); expect(response).to.equal(undefined); }); diff --git a/test/spec/modules/iqmBidAdapter_spec.js b/test/spec/modules/iqmBidAdapter_spec.js index 8958a4dfc45..5535c52af9b 100644 --- a/test/spec/modules/iqmBidAdapter_spec.js +++ b/test/spec/modules/iqmBidAdapter_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/iqmBidAdapter' import * as utils from 'src/utils'; -describe('iqmBidAdapter', () => { +describe('iqmBidAdapter', function () { const ENDPOINT_URL = 'https://pbd.bids.iqm.com'; const bidRequests = [{ bidder: 'iqm', @@ -80,15 +80,15 @@ describe('iqmBidAdapter', () => { headers: {} }; - describe('Request verification', () => { - it('basic property verification', () => { + describe('Request verification', function () { + it('basic property verification', function () { expect(spec.code).to.equal('iqm'); expect(spec.aliases).to.be.an('array'); // expect(spec.aliases).to.be.ofSize(1); expect(spec.aliases).to.have.lengthOf(1); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'iqm', 'params': { @@ -103,17 +103,17 @@ describe('iqmBidAdapter', () => { 'auctionId': '1d1a030790a475' }; - it('should return false for empty object', () => { + it('should return false for empty object', function () { expect(spec.isBidRequestValid({})).to.equal(false); }); - it('should return false for request without param', () => { + it('should return false for request without param', function () { let bid = Object.assign({}, bid); delete bid.params; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false for invalid params', () => { + it('should return false for invalid params', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -122,13 +122,13 @@ describe('iqmBidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true for proper request', () => { + it('should return true for proper request', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); }); - describe('buildRequests', () => { - it('sends every bid request to ENDPOINT_URL via POST method', () => { + describe('buildRequests', function () { + it('sends every bid request to ENDPOINT_URL via POST method', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].method).to.equal('POST'); expect(requests[0].url).to.equal(ENDPOINT_URL); @@ -136,7 +136,7 @@ describe('iqmBidAdapter', () => { // expect(requests[1].url).to.equal(ENDPOINT_URL); }); - it('should send request data with every request', () => { + it('should send request data with every request', function () { const requests = spec.buildRequests(bidRequests); const data = requests[0].data; expect(data.id).to.equal(bidRequests[0].requestId); @@ -175,31 +175,31 @@ describe('iqmBidAdapter', () => { }); }); - describe('interpretResponse', () => { - it('should handle no bid response', () => { + describe('interpretResponse', function () { + it('should handle no bid response', function () { const response = spec.interpretResponse({ body: null }, { bidRequests }); expect(response.length).to.equal(0); }); - it('should have at least one Seat Object', () => { + it('should have at least one Seat Object', function () { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponseEmptySeat, request); expect(response.length).to.equal(0); }); - it('should have at least one Bid Object', () => { + it('should have at least one Bid Object', function () { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponseEmptyBid, request); expect(response.length).to.equal(0); }); - it('should have impId in Bid Object', () => { + it('should have impId in Bid Object', function () { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponseNoImpId, request); expect(response.length).to.equal(0); }); - it('should handle valid response', () => { + it('should handle valid response', function () { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponses, request); expect(response).to.be.an('array').to.have.lengthOf(1); diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 3bf0fb27280..8e0df9959ef 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { newBidder } from 'src/adapters/bidderFactory'; import { spec } from 'modules/ixBidAdapter'; -describe('IndexexchangeAdapter', () => { +describe('IndexexchangeAdapter', function () { const IX_ENDPOINT = 'http://as.casalemedia.com/cygnus'; const BIDDER_VERSION = 7.2; @@ -58,44 +58,44 @@ describe('IndexexchangeAdapter', () => { ] }; - describe('inherited functions', () => { - it('should exists and is a function', () => { + describe('inherited functions', function () { + it('should exists and is a function', function () { const adapter = newBidder(spec); expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found for a banner ad', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found for a banner ad', function () { expect(spec.isBidRequestValid(DEFAULT_BANNER_VALID_BID[0])).to.equal(true); }); - it('should return true when optional params found for a banner ad', () => { + it('should return true when optional params found for a banner ad', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when siteID is number', () => { + it('should return true when siteID is number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.siteId = 123; expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when siteID is missing', () => { + it('should return false when siteID is missing', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.params.siteId; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when size is missing', () => { + it('should return false when size is missing', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.params.size; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when size array is wrong length', () => { + it('should return false when size array is wrong length', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.size = [ 300, @@ -105,13 +105,13 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when size array is array of strings', () => { + it('should return false when size array is array of strings', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.size = ['300', '250']; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes is not banner', () => { + it('should return false when mediaTypes is not banner', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.mediaTypes = { video: { @@ -121,7 +121,7 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes.banner does not have sizes', () => { + it('should return false when mediaTypes.banner does not have sizes', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.mediaTypes = { banner: { @@ -131,7 +131,7 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaType is not banner', () => { + it('should return false when mediaType is not banner', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.params.mediaTypes; bid.mediaType = 'banne'; @@ -139,7 +139,7 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaType is video', () => { + it('should return false when mediaType is video', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.params.mediaTypes; bid.mediaType = 'video'; @@ -147,7 +147,7 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaType is native', () => { + it('should return false when mediaType is native', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.params.mediaTypes; bid.mediaType = 'native'; @@ -155,14 +155,14 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true when mediaType is missing and has sizes', () => { + it('should return true when mediaType is missing and has sizes', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.mediaTypes; bid.sizes = [[300, 250]]; expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when mediaType is banner', () => { + it('should return true when mediaType is banner', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.mediaTypes; bid.mediaType = 'banner'; @@ -170,26 +170,26 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when there is only bidFloor', () => { + it('should return false when there is only bidFloor', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when there is only bidFloorCur', () => { + it('should return false when there is only bidFloorCur', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloorCur = 'USD'; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when bidFloor is string', () => { + it('should return false when bidFloor is string', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = '50'; bid.params.bidFloorCur = 'USD'; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when bidFloorCur is number', () => { + it('should return false when bidFloorCur is number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 70; @@ -197,7 +197,7 @@ describe('IndexexchangeAdapter', () => { }); }); - describe('buildRequestsBanner', () => { + describe('buildRequestsBanner', function () { const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID); const requestUrl = request.url; const requestMethod = request.method; @@ -209,12 +209,12 @@ describe('IndexexchangeAdapter', () => { const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType); const queryWithoutMediaType = requestWithoutMediaType.data; - it('request should be made to IX endpoint with GET method', () => { + it('request should be made to IX endpoint with GET method', function () { expect(requestMethod).to.equal('GET'); expect(requestUrl).to.equal(IX_ENDPOINT); }); - it('query object (version, siteID and request) should be correct', () => { + it('query object (version, siteID and request) should be correct', function () { expect(query.v).to.equal(BIDDER_VERSION); expect(query.s).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId); expect(query.r).to.exist; @@ -222,7 +222,7 @@ describe('IndexexchangeAdapter', () => { expect(query.sd).to.equal(1); }); - it('payload should have correct format and value', () => { + it('payload should have correct format and value', function () { const payload = JSON.parse(query.r); expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); @@ -238,7 +238,7 @@ describe('IndexexchangeAdapter', () => { expect(payload.imp).to.have.lengthOf(1); }); - it('impression should have correct format and value', () => { + it('impression should have correct format and value', function () { const impression = JSON.parse(query.r).imp[0]; const sidValue = `${DEFAULT_BANNER_VALID_BID[0].params.size[0].toString()}x${DEFAULT_BANNER_VALID_BID[0].params.size[1].toString()}`; @@ -253,7 +253,7 @@ describe('IndexexchangeAdapter', () => { expect(impression.ext.sid).to.equal(sidValue); }); - it('impression should have bidFloor and bidFloorCur if configured', () => { + it('impression should have bidFloor and bidFloorCur if configured', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; @@ -264,7 +264,7 @@ describe('IndexexchangeAdapter', () => { expect(impression.bidfloorcur).to.equal(bid.params.bidFloorCur); }); - it('payload without mediaType should have correct format and value', () => { + it('payload without mediaType should have correct format and value', function () { const payload = JSON.parse(queryWithoutMediaType.r); expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); @@ -280,7 +280,7 @@ describe('IndexexchangeAdapter', () => { expect(payload.imp).to.have.lengthOf(1); }); - it('impression without mediaType should have correct format and value', () => { + it('impression without mediaType should have correct format and value', function () { const impression = JSON.parse(queryWithoutMediaType.r).imp[0]; const sidValue = `${DEFAULT_BANNER_VALID_BID[0].params.size[0].toString()}x${DEFAULT_BANNER_VALID_BID[0].params.size[1].toString()}`; @@ -295,7 +295,7 @@ describe('IndexexchangeAdapter', () => { expect(impression.ext.sid).to.equal(sidValue); }); - it('impression should have sid if id is configured as number', () => { + it('impression should have sid if id is configured as number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 50; const requestBidFloor = spec.buildRequests([bid]); @@ -312,7 +312,7 @@ describe('IndexexchangeAdapter', () => { expect(impression.ext.sid).to.equal('50'); }); - it('impression should have sid if id is configured as string', () => { + it('impression should have sid if id is configured as string', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 'abc'; const requestBidFloor = spec.buildRequests([bid]); @@ -328,7 +328,7 @@ describe('IndexexchangeAdapter', () => { expect(impression.ext.sid).to.equal('abc'); }); - it('should add first party data to page url in bid request if it exists in config', () => { + it('should add first party data to page url in bid request if it exists in config', function () { config.setConfig({ ix: { firstPartyData: { @@ -347,7 +347,7 @@ describe('IndexexchangeAdapter', () => { expect(pageUrl).to.equal(expectedPageUrl); }); - it('should not set first party data if it is not an object', () => { + it('should not set first party data if it is not an object', function () { config.setConfig({ ix: { firstPartyData: 500 @@ -360,7 +360,7 @@ describe('IndexexchangeAdapter', () => { expect(pageUrl).to.equal(utils.getTopWindowUrl()); }); - it('should not set first party or timeout if it is not present', () => { + it('should not set first party or timeout if it is not present', function () { config.setConfig({ ix: {} }); @@ -372,7 +372,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithoutConfig.data.t).to.be.undefined; }); - it('should not set first party or timeout if it is setConfig is not called', () => { + it('should not set first party or timeout if it is setConfig is not called', function () { const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID); const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; @@ -380,7 +380,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithoutConfig.data.t).to.be.undefined; }); - it('should set timeout if publisher set it through setConfig', () => { + it('should set timeout if publisher set it through setConfig', function () { config.setConfig({ ix: { timeout: 500 @@ -391,7 +391,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithTimeout.data.t).to.equal(500); }); - it('should set timeout if timeout is a string', () => { + it('should set timeout if timeout is a string', function () { config.setConfig({ ix: { timeout: '500' @@ -403,8 +403,8 @@ describe('IndexexchangeAdapter', () => { }); }); - describe('interpretResponseBanner', () => { - it('should get correct bid response', () => { + describe('interpretResponseBanner', function () { + it('should get correct bid response', function () { const expectedParse = [ { requestId: '1a2b3c4d', @@ -423,7 +423,7 @@ describe('IndexexchangeAdapter', () => { expect(result[0]).to.deep.equal(expectedParse[0]); }); - it('should set creativeId to default value if not provided', () => { + it('should set creativeId to default value if not provided', function () { const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); delete bidResponse.seatbid[0].bid[0].crid; const expectedParse = [ @@ -444,7 +444,7 @@ describe('IndexexchangeAdapter', () => { expect(result[0]).to.deep.equal(expectedParse[0]); }); - it('should set Japanese price correctly', () => { + it('should set Japanese price correctly', function () { const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); bidResponse.cur = 'JPY'; const expectedParse = [ @@ -465,7 +465,7 @@ describe('IndexexchangeAdapter', () => { expect(result[0]).to.deep.equal(expectedParse[0]); }); - it('should set dealId correctly', () => { + it('should set dealId correctly', function () { const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); bidResponse.seatbid[0].bid[0].ext.dealid = 'deal'; const expectedParse = [ @@ -486,7 +486,7 @@ describe('IndexexchangeAdapter', () => { expect(result[0]).to.deep.equal(expectedParse[0]); }); - it('bidrequest should have consent info if gdprApplies and consentString exist', () => { + it('bidrequest should have consent info if gdprApplies and consentString exist', function () { const options = { gdprConsent: { gdprApplies: true, @@ -501,7 +501,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); }); - it('bidrequest should not have consent field if consentString is undefined', () => { + it('bidrequest should not have consent field if consentString is undefined', function () { const options = { gdprConsent: { gdprApplies: true, @@ -515,7 +515,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithConsent.user).to.be.undefined; }); - it('bidrequest should not have gdpr field if gdprApplies is undefined', () => { + it('bidrequest should not have gdpr field if gdprApplies is undefined', function () { const options = { gdprConsent: { consentString: '3huaa11=qu3198ae', @@ -529,7 +529,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); }); - it('bidrequest should not have consent info if options.gdprConsent is undefined', () => { + it('bidrequest should not have consent info if options.gdprConsent is undefined', function () { const options = {}; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); const requestWithConsent = JSON.parse(validBidWithConsent.data.r); diff --git a/test/spec/modules/jcmBidAdapter_spec.js b/test/spec/modules/jcmBidAdapter_spec.js index 27784def4f9..0b467e1ecfb 100644 --- a/test/spec/modules/jcmBidAdapter_spec.js +++ b/test/spec/modules/jcmBidAdapter_spec.js @@ -4,16 +4,16 @@ import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = '//media.adfrontiers.com/'; -describe('jcmAdapter', () => { +describe('jcmAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'jcm', 'params': { @@ -26,18 +26,18 @@ describe('jcmAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'jcm', @@ -55,11 +55,11 @@ describe('jcmAdapter', () => { const request = spec.buildRequests(bidRequests); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(request.method).to.equal('GET'); }); - it('sends correct bid parameters', () => { + it('sends correct bid parameters', function () { const payloadArr = request.data.split('&'); expect(request.method).to.equal('GET'); expect(payloadArr.length).to.equal(4); @@ -75,8 +75,8 @@ describe('jcmAdapter', () => { }); }); - describe('interpretResponse', () => { - it('should get correct bid response', () => { + describe('interpretResponse', function () { + it('should get correct bid response', function () { let serverResponse = {'bids': [{'width': 300, 'height': 250, 'creativeId': '29681110', 'ad': '', 'cpm': 0.5, 'callbackId': '30b31c1838de1e'}]}; let expectedResponse = [ @@ -109,15 +109,15 @@ describe('jcmAdapter', () => { expect(Object.keys(result[0]).ad).to.equal(Object.keys(expectedResponse[0]).ad); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let serverResponse = {'bids': []}; let result = spec.interpretResponse({ body: serverResponse }); expect(result.length).to.equal(0); }); }); - describe('getUserSyncs', () => { - it('Verifies sync iframe option', () => { + describe('getUserSyncs', function () { + it('Verifies sync iframe option', function () { expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; const options = spec.getUserSyncs({ iframeEnabled: true }); @@ -127,7 +127,7 @@ describe('jcmAdapter', () => { expect(options[0].url).to.equal('//media.adfrontiers.com/hb/jcm_usersync.html'); }); - it('Verifies sync image option', () => { + it('Verifies sync image option', function () { expect(spec.getUserSyncs({ image: false })).to.be.undefined; const options = spec.getUserSyncs({ image: true }); expect(options).to.not.be.undefined; diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index eb6d17d7a32..da0e147bd29 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai' import { spec } from 'modules/justpremiumBidAdapter' -describe('justpremium adapter', () => { +describe('justpremium adapter', function () { let adUnits = [ { adUnitCode: 'div-gpt-ad-1471513102552-1', @@ -21,12 +21,12 @@ describe('justpremium adapter', () => { }, ] - describe('isBidRequestValid', () => { - it('Verifies bidder code', () => { + describe('isBidRequestValid', function () { + it('Verifies bidder code', function () { expect(spec.code).to.equal('justpremium') }) - it('Verify build request', () => { + it('Verify build request', function () { expect(spec.isBidRequestValid({bidder: 'justpremium', params: {}})).to.equal(false) expect(spec.isBidRequestValid({})).to.equal(false) expect(spec.isBidRequestValid(adUnits[0])).to.equal(true) @@ -34,8 +34,8 @@ describe('justpremium adapter', () => { }) }) - describe('buildRequests', () => { - it('Verify build request and parameters', () => { + describe('buildRequests', function () { + it('Verify build request and parameters', function () { const request = spec.buildRequests(adUnits) expect(request.method).to.equal('POST') expect(request.url).to.match(/pre.ads.justpremium.com\/v\/2.0\/t\/xhr/) @@ -57,9 +57,9 @@ describe('justpremium adapter', () => { }) }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { const request = spec.buildRequests(adUnits) - it('Verify server response', () => { + it('Verify server response', function () { let response = { 'bid': { '28313': [{ @@ -107,7 +107,7 @@ describe('justpremium adapter', () => { expect(result[0].format).to.equal('lb') }) - it('Verify wrong server response', () => { + it('Verify wrong server response', function () { let response = { 'bid': { '28313': [] @@ -122,8 +122,8 @@ describe('justpremium adapter', () => { }) }) - describe('getUserSyncs', () => { - it('Verifies sync options', () => { + describe('getUserSyncs', function () { + it('Verifies sync options', function () { const options = spec.getUserSyncs({iframeEnabled: true}) expect(options).to.not.be.undefined expect(options[0].type).to.equal('iframe') @@ -131,7 +131,7 @@ describe('justpremium adapter', () => { }) }) - describe('onTimeout', () => { + describe('onTimeout', function () { it('onTimeout', (done) => { spec.onTimeout([{ 'bidId': '25cd3ec3fd6ed7', diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 432ae086511..eafb5a9c0f3 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -6,12 +6,12 @@ import {config} from 'src/config'; describe('kargo adapter tests', function () { var sandbox, clock, frozenNow = new Date(); - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); clock = sinon.useFakeTimers(frozenNow.getTime()); }); - afterEach(() => { + afterEach(function () { sandbox.restore(); clock.restore(); }); @@ -37,7 +37,7 @@ describe('kargo adapter tests', function () { describe('build request', function() { var bids, cookies = [], localStorageItems = []; - beforeEach(() => { + beforeEach(function () { sandbox.stub(config, 'getConfig').callsFake(function(key) { if (key === 'currency') { return 'USD'; @@ -67,7 +67,7 @@ describe('kargo adapter tests', function () { ]; }); - afterEach(() => { + afterEach(function () { for (let key in cookies) { let cookie = cookies[key]; removeCookie(cookie); diff --git a/test/spec/modules/komoonaBidAdapter_spec.js b/test/spec/modules/komoonaBidAdapter_spec.js index f7038505db3..b6d17c7b20c 100644 --- a/test/spec/modules/komoonaBidAdapter_spec.js +++ b/test/spec/modules/komoonaBidAdapter_spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import { spec } from 'modules/komoonaBidAdapter'; -describe('Komoona.com Adapter Tests', () => { +describe('Komoona.com Adapter Tests', function () { const bidsRequest = [ { bidder: 'komoona', @@ -54,11 +54,11 @@ describe('Komoona.com Adapter Tests', () => { } }; - it('Verifies komoonaAdapter bidder code', () => { + it('Verifies komoonaAdapter bidder code', function () { expect(spec.code).to.equal('komoona'); }); - it('Verifies komoonaAdapter bid request validation', () => { + it('Verifies komoonaAdapter bid request validation', function () { expect(spec.isBidRequestValid(bidsRequest[0])).to.equal(true); expect(spec.isBidRequestValid(bidsRequest[1])).to.equal(true); expect(spec.isBidRequestValid({})).to.equal(false); @@ -69,7 +69,7 @@ describe('Komoona.com Adapter Tests', () => { expect(spec.isBidRequestValid({ params: { hbid: 12345, placementId: 67890, floorPrice: 0.8 } })).to.equal(true); }); - it('Verify komoonaAdapter build request', () => { + it('Verify komoonaAdapter build request', function () { var startTime = new Date().getTime(); const request = spec.buildRequests(bidsRequest); @@ -127,7 +127,7 @@ describe('Komoona.com Adapter Tests', () => { expect(kbConf.hb_placements[1]).to.equal(bids[1].placementid); }); - it('Verify komoonaAdapter build response', () => { + it('Verify komoonaAdapter build response', function () { const request = spec.buildRequests(bidsRequest); const bids = spec.interpretResponse(bidsResponse, request); @@ -150,7 +150,7 @@ describe('Komoona.com Adapter Tests', () => { expect(bid.creativeId).to.equal(responseBids[0].creativeId); }); - it('Verifies komoonaAdapter sync options', () => { + it('Verifies komoonaAdapter sync options', function () { // user sync disabled expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; diff --git a/test/spec/modules/kummaBidAdapter_spec.js b/test/spec/modules/kummaBidAdapter_spec.js index 84efa032cec..82076717dcc 100644 --- a/test/spec/modules/kummaBidAdapter_spec.js +++ b/test/spec/modules/kummaBidAdapter_spec.js @@ -3,7 +3,7 @@ import {spec} from 'modules/kummaBidAdapter'; import {getTopWindowLocation} from 'src/utils'; import {newBidder} from 'src/adapters/bidderFactory'; -describe('Kumma Adapter Tests', () => { +describe('Kumma Adapter Tests', function () { const slotConfigs = [{ placementCode: '/DfpAccount1/slot1', sizes: [[300, 250]], @@ -77,7 +77,7 @@ describe('Kumma Adapter Tests', () => { } }]; - it('Verify build request', () => { + it('Verify build request', function () { const request = spec.buildRequests(slotConfigs); expect(request.url).to.equal('//hb.kumma.com/'); expect(request.method).to.equal('POST'); @@ -109,7 +109,7 @@ describe('Kumma Adapter Tests', () => { expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); }); - it('Verify parse response', () => { + it('Verify parse response', function () { const request = spec.buildRequests(slotConfigs); const ortbRequest = JSON.parse(request.data); const ortbResponse = { @@ -137,13 +137,13 @@ describe('Kumma Adapter Tests', () => { expect(bid.ttl).to.equal(360); }); - it('Verify full passback', () => { + it('Verify full passback', function () { const request = spec.buildRequests(slotConfigs); const bids = spec.interpretResponse({ body: null }, request) expect(bids).to.have.lengthOf(0); }); - it('Verify Native request', () => { + it('Verify Native request', function () { const request = spec.buildRequests(nativeSlotConfig); expect(request.url).to.equal('//hb.kumma.com/'); expect(request.method).to.equal('POST'); @@ -181,7 +181,7 @@ describe('Kumma Adapter Tests', () => { expect(nativeRequest.assets[4].img.type).to.equal(3); }); - it('Verify Native response', () => { + it('Verify Native response', function () { const request = spec.buildRequests(nativeSlotConfig); expect(request.url).to.equal('//hb.kumma.com/'); expect(request.method).to.equal('POST'); @@ -231,7 +231,7 @@ describe('Kumma Adapter Tests', () => { expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); }); - it('Verify Video request', () => { + it('Verify Video request', function () { const request = spec.buildRequests(videoSlotConfig); expect(request.url).to.equal('//hb.kumma.com/'); expect(request.method).to.equal('POST'); @@ -253,7 +253,7 @@ describe('Kumma Adapter Tests', () => { expect(videoRequest.imp[0].native).to.equal(null); }); - it('Verify parse video response', () => { + it('Verify parse video response', function () { const request = spec.buildRequests(videoSlotConfig); const videoRequest = JSON.parse(request.data); const videoResponse = { @@ -282,25 +282,25 @@ describe('Kumma Adapter Tests', () => { expect(bid.ttl).to.equal(360); }); - it('Verifies bidder code', () => { + it('Verifies bidder code', function () { expect(spec.code).to.equal('kumma'); }); - it('Verifies supported media types', () => { + it('Verifies supported media types', function () { expect(spec.supportedMediaTypes).to.have.lengthOf(3); expect(spec.supportedMediaTypes[0]).to.equal('banner'); expect(spec.supportedMediaTypes[1]).to.equal('native'); expect(spec.supportedMediaTypes[2]).to.equal('video'); }); - it('Verifies if bid request valid', () => { + it('Verifies if bid request valid', function () { expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); }); - it('Verify app requests', () => { + it('Verify app requests', function () { const request = spec.buildRequests(appSlotConfig); const ortbRequest = JSON.parse(request.data); expect(ortbRequest.site).to.equal(null); @@ -314,7 +314,7 @@ describe('Kumma Adapter Tests', () => { expect(ortbRequest.app.domain).to.equal('kumma.com'); }); - it('Verify GDPR', () => { + it('Verify GDPR', function () { const bidderRequest = { gdprConsent: { gdprApplies: true, diff --git a/test/spec/modules/lifestreetBidAdapter_spec.js b/test/spec/modules/lifestreetBidAdapter_spec.js index 2c48a0f1892..6c9c6eeba31 100644 --- a/test/spec/modules/lifestreetBidAdapter_spec.js +++ b/test/spec/modules/lifestreetBidAdapter_spec.js @@ -56,45 +56,45 @@ let getDefaultBidResponse = (isBanner, noBid = 0) => { }; }; -describe('LifestreetAdapter', () => { +describe('LifestreetAdapter', function () { const LIFESTREET_URL = '//ads.lfstmedia.com/gate/'; const ADAPTER_VERSION = 'prebidJS-2.0'; - describe('buildRequests()', () => { - it('method exists and is a function', () => { + describe('buildRequests()', function () { + it('method exists and is a function', function () { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); - it('should not return request when no bids are present', () => { + it('should not return request when no bids are present', function () { let [request] = spec.buildRequests([]); expect(request).to.be.empty; }); let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); - it('should return request for Lifestreet endpoint', () => { + it('should return request for Lifestreet endpoint', function () { expect(request.url).to.contain(LIFESTREET_URL); }); - it('should use json adapter', () => { + it('should use json adapter', function () { expect(request.url).to.contain('/prebid/'); }); - it('should contain slot', () => { + it('should contain slot', function () { expect(request.url).to.contain('slot166704'); }); - it('should contain adkey', () => { + it('should contain adkey', function () { expect(request.url).to.contain('adkey=78c'); }); - it('should contain ad_size', () => { + it('should contain ad_size', function () { expect(request.url).to.contain('ad_size=160x600'); }); - it('should contain location and rferrer paramters', () => { + it('should contain location and rferrer paramters', function () { expect(request.url).to.contain('__location='); expect(request.url).to.contain('__referrer='); }); - it('should contain info parameters', () => { + it('should contain info parameters', function () { expect(request.url).to.contain('__wn='); expect(request.url).to.contain('__sf='); expect(request.url).to.contain('__fif='); @@ -103,24 +103,24 @@ describe('LifestreetAdapter', () => { expect(request.url).to.contain('__pp='); }); - it('should contain HB enabled', () => { + it('should contain HB enabled', function () { expect(request.url).to.contain('__hb=1'); }); - it('should include gzip', () => { + it('should include gzip', function () { expect(request.url).to.contain('__gz=1'); }); - it('should not contain __gdpr parameter', () => { + it('should not contain __gdpr parameter', function () { expect(request.url).to.not.contain('__gdpr'); }); - it('should not contain __concent parameter', () => { + it('should not contain __concent parameter', function () { expect(request.url).to.not.contain('__consent'); }); - it('should contain the right version of adapter', () => { + it('should contain the right version of adapter', function () { expect(request.url).to.contain('__hbver=' + ADAPTER_VERSION); }); - it('should contain __gdpr and __consent parameters', () => { + it('should contain __gdpr and __consent parameters', function () { const options = { gdprConsent: { gdprApplies: true, @@ -132,7 +132,7 @@ describe('LifestreetAdapter', () => { expect(request.url).to.contain('__gdpr=1'); expect(request.url).to.contain('__consent=test'); }); - it('should contain __gdpr parameters', () => { + it('should contain __gdpr parameters', function () { const options = { gdprConsent: { gdprApplies: true, @@ -143,7 +143,7 @@ describe('LifestreetAdapter', () => { expect(request.url).to.contain('__gdpr=1'); expect(request.url).to.not.contain('__consent'); }); - it('should contain __consent parameters', () => { + it('should contain __consent parameters', function () { const options = { gdprConsent: { consentString: 'test', @@ -155,8 +155,8 @@ describe('LifestreetAdapter', () => { expect(request.url).to.contain('__consent=test'); }); }); - describe('interpretResponse()', () => { - it('should return formatted bid response with required properties', () => { + describe('interpretResponse()', function () { + it('should return formatted bid response with required properties', function () { let bidRequest = getDefaultBidRequest().bids[0]; let bidResponse = { body: getDefaultBidResponse(true) }; let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); @@ -174,7 +174,7 @@ describe('LifestreetAdapter', () => { mediaType: 'banner' }]); }); - it('should return formatted VAST bid response with required properties', () => { + it('should return formatted VAST bid response with required properties', function () { let bidRequest = getDefaultBidRequest().bids[0]; let bidResponse = { body: getDefaultBidResponse(false) }; let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); @@ -192,7 +192,7 @@ describe('LifestreetAdapter', () => { mediaType: 'video' }]); }); - it('should return formatted VAST bid response with vastUrl', () => { + it('should return formatted VAST bid response with vastUrl', function () { let bidRequest = getDefaultBidRequest().bids[0]; let bidResponse = { body: getDefaultBidResponse(false) }; bidResponse.body.vastUrl = 'http://lifestreet.com'; // set vastUrl @@ -212,7 +212,7 @@ describe('LifestreetAdapter', () => { }]); }); - it('should return no-bid', () => { + it('should return no-bid', function () { let bidRequest = getDefaultBidRequest().bids[0]; let bidResponse = { body: getDefaultBidResponse(true, true) }; let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); diff --git a/test/spec/modules/lkqdBidAdapter_spec.js b/test/spec/modules/lkqdBidAdapter_spec.js index a5e75086229..0cebb2651a9 100644 --- a/test/spec/modules/lkqdBidAdapter_spec.js +++ b/test/spec/modules/lkqdBidAdapter_spec.js @@ -2,16 +2,16 @@ import { spec } from 'modules/lkqdBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; const { expect } = require('chai'); -describe('LKQD Bid Adapter Test', () => { +describe('LKQD Bid Adapter Test', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'lkqd', 'params': { @@ -26,11 +26,11 @@ describe('LKQD Bid Adapter Test', () => { 'transactionId': 'd6f6b392-54a9-454c-85fb-a2fd882c4a2d', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,7 +40,7 @@ describe('LKQD Bid Adapter Test', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const ENDPOINT = 'https://v.lkqd.net/ad'; let bidRequests = [ { @@ -73,7 +73,7 @@ describe('LKQD Bid Adapter Test', () => { } ]; - it('should populate available parameters', () => { + it('should populate available parameters', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(2); const r1 = requests[0].data; @@ -96,7 +96,7 @@ describe('LKQD Bid Adapter Test', () => { expect(r2.height).to.equal(480); }); - it('should not populate unspecified parameters', () => { + it('should not populate unspecified parameters', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(2); const r1 = requests[0].data; @@ -115,7 +115,7 @@ describe('LKQD Bid Adapter Test', () => { expect(r2).to.not.have.property('contenturl'); }); - it('should handle single size request', () => { + it('should handle single size request', function () { const requests = spec.buildRequests(bidRequest); expect(requests.length).to.equal(1); const r1 = requests[0].data; @@ -129,7 +129,7 @@ describe('LKQD Bid Adapter Test', () => { expect(r1.height).to.equal(480); }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(2); const r1 = requests[0]; @@ -141,7 +141,7 @@ describe('LKQD Bid Adapter Test', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let bidRequest = { 'url': 'https://ssp.lkqd.net/ad?pid=263&sid=662921&output=vast&execution=any&placement=&playinit=auto&volume=100&timeout=&width=300%E2%80%8C&height=250&pbt=[PREBID_TOKEN]%E2%80%8C&dnt=[DO_NOT_TRACK]%E2%80%8C&pageurl=[PAGEURL]%E2%80%8C&contentid=[CONTENT_ID]%E2%80%8C&contenttitle=[CONTENT_TITLE]%E2%80%8C&contentlength=[CONTENT_LENGTH]%E2%80%8C&contenturl=[CONTENT_URL]&prebid=true%E2%80%8C&rnd=874313435?bidId=253dcb69fb2577&bidWidth=300&bidHeight=250&', 'data': { @@ -322,7 +322,7 @@ https://creative.lkqd.net/internal/lkqd_300x250.mp4 `; - it('should correctly parse valid bid response', () => { + it('should correctly parse valid bid response', function () { const BIDDER_CODE = 'lkqd'; let bidResponses = spec.interpretResponse(serverResponse, bidRequest); expect(bidResponses.length).to.equal(1); @@ -340,7 +340,7 @@ https://creative.lkqd.net/internal/lkqd_300x250.mp4 expect(bidResponse.mediaType).to.equal('video'); }); - it('safely handles XML parsing failure from invalid bid response', () => { + it('safely handles XML parsing failure from invalid bid response', function () { let invalidServerResponse = {}; invalidServerResponse.body = ''; @@ -348,7 +348,7 @@ https://creative.lkqd.net/internal/lkqd_300x250.mp4 expect(result.length).to.equal(0); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let nobidResponse = {}; nobidResponse.body = ''; diff --git a/test/spec/modules/lockerdomeBidAdapter_spec.js b/test/spec/modules/lockerdomeBidAdapter_spec.js index 19884065597..1cd6778b01f 100644 --- a/test/spec/modules/lockerdomeBidAdapter_spec.js +++ b/test/spec/modules/lockerdomeBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { spec } from '../../../modules/lockerdomeBidAdapter'; import * as utils from 'src/utils'; -describe('LockerDomeAdapter', () => { +describe('LockerDomeAdapter', function () { const bidRequests = [{ bidder: 'lockerdome', params: { @@ -37,20 +37,20 @@ describe('LockerDomeAdapter', () => { auctionId: 'd4c83108-615d-4c2c-9384-dac9ffd4fd72' }]; - describe('isBidRequestValid', () => { - it('should return true if the adUnitId parameter is present', () => { + describe('isBidRequestValid', function () { + it('should return true if the adUnitId parameter is present', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.be.true; expect(spec.isBidRequestValid(bidRequests[1])).to.be.true; }); - it('should return false if the adUnitId parameter is not present', () => { + it('should return false if the adUnitId parameter is not present', function () { let bidRequest = utils.deepClone(bidRequests[0]); delete bidRequest.params.adUnitId; expect(spec.isBidRequestValid(bidRequest)).to.be.false; }); }); - describe('buildRequests', () => { - it('should generate a valid single POST request for multiple bid requests', () => { + describe('buildRequests', function () { + it('should generate a valid single POST request for multiple bid requests', function () { const request = spec.buildRequests(bidRequests); expect(request.method).to.equal('POST'); expect(request.url).to.equal('https://lockerdome.com/ladbid/prebid'); @@ -79,7 +79,7 @@ describe('LockerDomeAdapter', () => { expect(bids[1].sizes[0][1]).to.equal(600); }); - it('should add GDPR data to request if available', () => { + it('should add GDPR data to request if available', function () { const bidderRequest = { gdprConsent: { consentString: 'AAABBB', @@ -95,13 +95,13 @@ describe('LockerDomeAdapter', () => { }); }); - describe('interpretResponse', () => { - it('should return an empty array if an invalid response is passed', () => { + describe('interpretResponse', function () { + it('should return an empty array if an invalid response is passed', function () { const interpretedResponse = spec.interpretResponse({ body: {} }); expect(interpretedResponse).to.be.an('array').that.is.empty; }); - it('should return valid response when passed valid server response', () => { + it('should return valid response when passed valid server response', function () { const serverResponse = { body: { bids: [{ diff --git a/test/spec/modules/madvertiseBidAdapter_spec.js b/test/spec/modules/madvertiseBidAdapter_spec.js index c391ca1d39f..b2a08410532 100644 --- a/test/spec/modules/madvertiseBidAdapter_spec.js +++ b/test/spec/modules/madvertiseBidAdapter_spec.js @@ -3,9 +3,9 @@ import {config} from 'src/config'; import * as utils from 'src/utils'; import {spec} from 'modules/madvertiseBidAdapter'; -describe('madvertise adapater', () => { - describe('Test validate req', () => { - it('should accept minimum valid bid', () => { +describe('madvertise adapater', function () { + describe('Test validate req', function () { + it('should accept minimum valid bid', function () { let bid = { bidder: 'madvertise', sizes: [[728, 90]], @@ -17,7 +17,7 @@ describe('madvertise adapater', () => { expect(isValid).to.equal(true); }); - it('should reject no sizes', () => { + it('should reject no sizes', function () { let bid = { bidder: 'madvertise', params: { @@ -28,7 +28,7 @@ describe('madvertise adapater', () => { expect(isValid).to.equal(false); }); - it('should reject empty sizes', () => { + it('should reject empty sizes', function () { let bid = { bidder: 'madvertise', sizes: [], @@ -40,7 +40,7 @@ describe('madvertise adapater', () => { expect(isValid).to.equal(false); }); - it('should reject wrong format sizes', () => { + it('should reject wrong format sizes', function () { let bid = { bidder: 'madvertise', sizes: [['728x90']], @@ -51,7 +51,7 @@ describe('madvertise adapater', () => { const isValid = spec.isBidRequestValid(bid); expect(isValid).to.equal(false); }); - it('should reject no params', () => { + it('should reject no params', function () { let bid = { bidder: 'madvertise', sizes: [[728, 90]] @@ -60,7 +60,7 @@ describe('madvertise adapater', () => { expect(isValid).to.equal(false); }); - it('should reject missing s', () => { + it('should reject missing s', function () { let bid = { bidder: 'madvertise', params: {} @@ -71,7 +71,7 @@ describe('madvertise adapater', () => { }); }); - describe('Test build request', () => { + describe('Test build request', function () { beforeEach(function () { let mockConfig = { consentManagement: { @@ -100,7 +100,7 @@ describe('madvertise adapater', () => { s: 'test', } }]; - it('minimum request with gdpr consent', () => { + it('minimum request with gdpr consent', function () { let bidderRequest = { gdprConsent: { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', @@ -122,7 +122,7 @@ describe('madvertise adapater', () => { expect(req[0].url).to.contain(`&consent[0][value]=BOJ/P2HOJ/P2HABABMAAAAAZ+A==`) }); - it('minimum request without gdpr consent', () => { + it('minimum request without gdpr consent', function () { let bidderRequest = {}; const req = spec.buildRequests(bid, bidderRequest); @@ -139,8 +139,8 @@ describe('madvertise adapater', () => { }); }); - describe('Test interpret response', () => { - it('General banner response', () => { + describe('Test interpret response', function () { + it('General banner response', function () { let bid = { bidder: 'madvertise', sizes: [[728, 90]], @@ -180,7 +180,7 @@ describe('madvertise adapater', () => { expect(resp[0]).to.have.property('currency', 'EUR'); expect(resp[0]).to.have.property('dealId', 'DEAL_ID'); }); - it('No response', () => { + it('No response', function () { let bid = { bidder: 'madvertise', sizes: [[728, 90]], diff --git a/test/spec/modules/mantisBidAdapter_spec.js b/test/spec/modules/mantisBidAdapter_spec.js index 46cb413597e..464cea2aab3 100644 --- a/test/spec/modules/mantisBidAdapter_spec.js +++ b/test/spec/modules/mantisBidAdapter_spec.js @@ -2,10 +2,10 @@ import {expect} from 'chai'; import {spec} from 'modules/mantisBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -describe('MantisAdapter', () => { +describe('MantisAdapter', function () { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'mantis', 'params': { @@ -19,11 +19,11 @@ describe('MantisAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = {}; @@ -31,7 +31,7 @@ describe('MantisAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'mantis', @@ -47,7 +47,7 @@ describe('MantisAdapter', () => { } ]; - it('domain override', () => { + it('domain override', function () { window.mantis_domain = 'http://foo'; const request = spec.buildRequests(bidRequests); @@ -56,7 +56,7 @@ describe('MantisAdapter', () => { delete window.mantis_domain; }); - it('standard request', () => { + it('standard request', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.include('property=10433394'); @@ -68,7 +68,7 @@ describe('MantisAdapter', () => { expect(request.url).to.include('bids[0][sizes][1][height]=600'); }); - it('use window uuid', () => { + it('use window uuid', function () { window.mantis_uuid = 'foo'; const request = spec.buildRequests(bidRequests); @@ -78,7 +78,7 @@ describe('MantisAdapter', () => { delete window.mantis_uuid; }); - it('use storage uuid', () => { + it('use storage uuid', function () { window.localStorage.setItem('mantis:uuid', 'bar'); const request = spec.buildRequests(bidRequests); @@ -88,7 +88,7 @@ describe('MantisAdapter', () => { window.localStorage.removeItem('mantis:uuid'); }); - it('detect amp', () => { + it('detect amp', function () { var oldContext = window.context; window.context = {}; @@ -107,8 +107,8 @@ describe('MantisAdapter', () => { }); }); - describe('getUserSyncs', () => { - it('iframe', () => { + describe('getUserSyncs', function () { + it('iframe', function () { let result = spec.getUserSyncs({ iframeEnabled: true }); @@ -117,7 +117,7 @@ describe('MantisAdapter', () => { expect(result[0].url).to.include('https://mantodea.mantisadnetwork.com/prebid/iframe'); }); - it('pixel', () => { + it('pixel', function () { let result = spec.getUserSyncs({ pixelEnabled: true }); @@ -127,8 +127,8 @@ describe('MantisAdapter', () => { }); }); - describe('interpretResponse', () => { - it('display ads returned', () => { + describe('interpretResponse', function () { + it('display ads returned', function () { let response = { body: { uuid: 'uuid', @@ -166,7 +166,7 @@ describe('MantisAdapter', () => { expect(window.localStorage.getItem('mantis:uuid')).to.equal(response.body.uuid); }); - it('no ads returned', () => { + it('no ads returned', function () { let response = { body: { ads: [] diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 027b23f54bb..bb55ed99e02 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -488,40 +488,40 @@ let VALID_BID_REQUEST = [{ 'tmax': 3000, }; -describe('Media.net bid adapter', () => { +describe('Media.net bid adapter', function () { let sandbox; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); }); - afterEach(() => { + afterEach(function () { sandbox.restore(); }); - describe('isBidRequestValid', () => { - it('should accept valid bid params', () => { + describe('isBidRequestValid', function () { + it('should accept valid bid params', function () { let isValid = spec.isBidRequestValid(VALID_PARAMS); expect(isValid).to.equal(true); }); - it('should reject bid if cid is not present', () => { + it('should reject bid if cid is not present', function () { let isValid = spec.isBidRequestValid(PARAMS_WITHOUT_CID); expect(isValid).to.equal(false); }); - it('should reject bid if cid is not a string', () => { + it('should reject bid if cid is not a string', function () { let isValid = spec.isBidRequestValid(PARAMS_WITH_INTEGER_CID); expect(isValid).to.equal(false); }); - it('should reject bid if cid is a empty string', () => { + it('should reject bid if cid is a empty string', function () { let isValid = spec.isBidRequestValid(PARAMS_WITH_EMPTY_CID); expect(isValid).to.equal(false); }); }); - describe('buildRequests', () => { - beforeEach(() => { + describe('buildRequests', function () { + beforeEach(function () { let documentStub = sandbox.stub(document, 'getElementById'); let boundingRect = { top: 50, @@ -542,28 +542,28 @@ describe('Media.net bid adapter', () => { }); }); - it('should build valid payload on bid', () => { + it('should build valid payload on bid', function () { let requestObj = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); expect(JSON.parse(requestObj.data)).to.deep.equal(VALID_PAYLOAD); }); - it('should accept size as a one dimensional array', () => { + it('should accept size as a one dimensional array', function () { let bidReq = spec.buildRequests(BID_REQUEST_SIZE_AS_1DARRAY, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD); }); - it('should ignore bidfloor if not a valid number', () => { + it('should ignore bidfloor if not a valid number', function () { let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_INVALID_BIDFLOOR); }); - it('should add gdpr to response ext', () => { + it('should add gdpr to response ext', function () { let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_BIDDER_REQUEST_WITH_GDPR); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_FOR_GDPR); }); - describe('build requests: when page meta-data is available', () => { - it('should pass canonical, twitter and fb paramters if available', () => { + describe('build requests: when page meta-data is available', function () { + it('should pass canonical, twitter and fb paramters if available', function () { let documentStub = sandbox.stub(window.top.document, 'querySelector'); documentStub.withArgs('link[rel="canonical"]').returns({ href: 'http://localhost:9999/canonical-test' @@ -580,9 +580,9 @@ describe('Media.net bid adapter', () => { }); }); - describe('slot visibility', () => { + describe('slot visibility', function () { let documentStub; - beforeEach(() => { + beforeEach(function () { let windowSizeStub = sandbox.stub(spec, 'getWindowSize'); windowSizeStub.returns({ w: 1000, @@ -590,7 +590,7 @@ describe('Media.net bid adapter', () => { }); documentStub = sandbox.stub(document, 'getElementById'); }); - it('slot visibility should be 2 and ratio 0 when ad unit is BTF', () => { + it('slot visibility should be 2 and ratio 0 when ad unit is BTF', function () { let boundingRect = { top: 1010, left: 1010, @@ -609,7 +609,7 @@ describe('Media.net bid adapter', () => { expect(data.imp[0].ext.visibility).to.equal(2); expect(data.imp[0].ext.viewability).to.equal(0); }); - it('slot visibility should be 2 and ratio < 0.5 when ad unit is partially inside viewport', () => { + it('slot visibility should be 2 and ratio < 0.5 when ad unit is partially inside viewport', function () { let boundingRect = { top: 990, left: 990, @@ -627,7 +627,7 @@ describe('Media.net bid adapter', () => { expect(data.imp[0].ext.visibility).to.equal(2); expect(data.imp[0].ext.viewability).to.equal(100 / 75000); }); - it('slot visibility should be 1 and ratio > 0.5 when ad unit mostly in viewport', () => { + it('slot visibility should be 1 and ratio > 0.5 when ad unit mostly in viewport', function () { let boundingRect = { top: 800, left: 800, @@ -645,7 +645,7 @@ describe('Media.net bid adapter', () => { expect(data.imp[0].ext.visibility).to.equal(1); expect(data.imp[0].ext.viewability).to.equal(40000 / 75000); }); - it('co-ordinates should not be sent and slot visibility should be 0 when ad unit is not present', () => { + it('co-ordinates should not be sent and slot visibility should be 0 when ad unit is not present', function () { let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); let data = JSON.parse(bidReq.data); expect(data.imp[1].ext).to.not.have.ownPropertyDescriptor('viewability'); @@ -653,37 +653,37 @@ describe('Media.net bid adapter', () => { }); }); - describe('getUserSyncs', () => { - it('should exclude iframe syncs if iframe is disabled', () => { + describe('getUserSyncs', function () { + it('should exclude iframe syncs if iframe is disabled', function () { let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_PIXEL_ENABLED, SERVER_CSYNC_RESPONSE); expect(userSyncs).to.deep.equal(ENABLED_SYNC_PIXEL); }); - it('should exclude pixel syncs if pixel is disabled', () => { + it('should exclude pixel syncs if pixel is disabled', function () { let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_IFRAME_ENABLED, SERVER_CSYNC_RESPONSE); expect(userSyncs).to.deep.equal(ENABLED_SYNC_IFRAME); }); - it('should choose iframe sync urls if both sync options are enabled', () => { + it('should choose iframe sync urls if both sync options are enabled', function () { let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_BOTH_ENABLED, SERVER_CSYNC_RESPONSE); expect(userSyncs).to.deep.equal(ENABLED_SYNC_IFRAME); }); }); - describe('interpretResponse', () => { - it('should not push bid response if cpm missing', () => { + describe('interpretResponse', function () { + it('should not push bid response if cpm missing', function () { let validBids = []; let bids = spec.interpretResponse(SERVER_RESPONSE_CPM_MISSING, []); expect(bids).to.deep.equal(validBids); }); - it('should not push bid response if cpm 0', () => { + it('should not push bid response if cpm 0', function () { let validBids = []; let bids = spec.interpretResponse(SERVER_RESPONSE_CPM_ZERO, []); expect(bids).to.deep.equal(validBids); }); - it('should not push response if no-bid', () => { + it('should not push response if no-bid', function () { let validBids = []; let bids = spec.interpretResponse(SERVER_RESPONSE_NOBID, []); expect(bids).to.deep.equal(validBids); diff --git a/test/spec/modules/mobfoxBidAdapter_spec.js b/test/spec/modules/mobfoxBidAdapter_spec.js index 54a057991e3..90125f3e0d0 100644 --- a/test/spec/modules/mobfoxBidAdapter_spec.js +++ b/test/spec/modules/mobfoxBidAdapter_spec.js @@ -1,4 +1,4 @@ -describe('mobfox adapter tests', () => { +describe('mobfox adapter tests', function () { const expect = require('chai').expect; const utils = require('src/utils'); const adapter = require('modules/mobfoxBidAdapter'); @@ -18,7 +18,7 @@ describe('mobfox adapter tests', () => { transactionId: '31f42cba-5920-4e47-adad-69c79d0d4fb4' }]; - describe('validRequests', () => { + describe('validRequests', function () { let bidRequestInvalid1 = [{ code: 'div-gpt-ad-1460505748561-0', sizes: [[320, 480], [300, 250], [300, 600]], @@ -33,19 +33,19 @@ describe('mobfox adapter tests', () => { transactionId: '31f42cba-5920-4e47-adad-69c79d0d4fb4' }]; - it('test valid MF request success', () => { + it('test valid MF request success', function () { let isValid = adapter.spec.isBidRequestValid(bidRequest[0]); expect(isValid).to.equal(true); }); - it('test valid MF request failed1', () => { + it('test valid MF request failed1', function () { let isValid = adapter.spec.isBidRequestValid(bidRequestInvalid1[0]); expect(isValid).to.equal(false); }); }) - describe('buildRequests', () => { - it('test build MF request', () => { + describe('buildRequests', function () { + it('test build MF request', function () { let request = adapter.spec.buildRequests(bidRequest); let payload = request.data.split('&'); expect(payload[0]).to.equal('rt=api-fetchip'); @@ -57,7 +57,7 @@ describe('mobfox adapter tests', () => { expect(payload[7]).to.equal('imp_instl=1'); }); - it('test build MF request', () => { + it('test build MF request', function () { let request = adapter.spec.buildRequests(bidRequest); let payload = request.data.split('&'); expect(payload[0]).to.equal('rt=api-fetchip'); @@ -70,7 +70,7 @@ describe('mobfox adapter tests', () => { }); }) - describe('interceptResponse', () => { + describe('interceptResponse', function () { let mockServerResponse = { body: { request: { @@ -93,7 +93,7 @@ describe('mobfox adapter tests', () => { } } }; - it('test intercept response', () => { + it('test intercept response', function () { let request = adapter.spec.buildRequests(bidRequest); let bidResponses = adapter.spec.interpretResponse(mockServerResponse, request); expect(bidResponses.length).to.equal(1); @@ -109,7 +109,7 @@ describe('mobfox adapter tests', () => { expect(bidResponses[0].width).to.equal('320'); }); - it('test intercept response with empty server response', () => { + it('test intercept response with empty server response', function () { let request = adapter.spec.buildRequests(bidRequest); let serverResponse = { request: { diff --git a/test/spec/modules/my6senseBidAdapter_spec.js b/test/spec/modules/my6senseBidAdapter_spec.js index ec8389acbb3..80671305aca 100644 --- a/test/spec/modules/my6senseBidAdapter_spec.js +++ b/test/spec/modules/my6senseBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import spec from 'modules/my6senseBidAdapter'; -describe('My6sense Bid adapter test', () => { +describe('My6sense Bid adapter test', function () { let bidRequests, serverResponses; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { // valid 1 @@ -99,29 +99,29 @@ describe('My6sense Bid adapter test', () => { ] }); - describe('test if requestIsValid function', () => { - it('with valid data 1', () => { + describe('test if requestIsValid function', function () { + it('with valid data 1', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); }); - it('with invalid data 2', () => { + it('with invalid data 2', function () { expect(spec.isBidRequestValid(bidRequests[1])).to.equal(false); }); - it('with invalid data 3', () => { + it('with invalid data 3', function () { expect(spec.isBidRequestValid(bidRequests[2])).to.equal(false); }); - it('with invalid data 3', () => { + it('with invalid data 3', function () { expect(spec.isBidRequestValid(bidRequests[3])).to.equal(false); }); }); - describe('test if buildRequests function', () => { - it('normal', () => { + describe('test if buildRequests function', function () { + it('normal', function () { var requests = spec.buildRequests([bidRequests[0]]); expect(requests).to.be.lengthOf(1); }); }); - describe('test bid responses', () => { - it('success 1', () => { + describe('test bid responses', function () { + it('success 1', function () { var bids = spec.interpretResponse(serverResponses[0], {'bidRequest': bidRequests[0]}); expect(bids).to.be.lengthOf(1); expect(bids[0].cpm).to.equal(1.5); @@ -129,7 +129,7 @@ describe('My6sense Bid adapter test', () => { expect(bids[0].height).to.equal(250); expect(bids[0].adm).to.have.length.above(1); }); - it('success 2', () => { + it('success 2', function () { var bids = spec.interpretResponse(serverResponses[3]); expect(bids).to.be.lengthOf(1); expect(bids[0].cpm).to.equal(5); @@ -139,11 +139,11 @@ describe('My6sense Bid adapter test', () => { expect(bids[0].ttl).to.equal(360); expect(bids[0].currency).to.equal('USD'); }); - it('fail 1 (cpm=0)', () => { + it('fail 1 (cpm=0)', function () { var bids = spec.interpretResponse(serverResponses[1]); expect(bids).to.be.lengthOf(1); }); - it('fail 2 (no response)', () => { + it('fail 2 (no response)', function () { var bids = spec.interpretResponse([]); expect(bids).to.be.lengthOf(0); }); diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index 1aecb8ab06b..3731535b88a 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -64,10 +64,10 @@ describe('nanointeractive adapter tests', function () { }; } - describe('NanoAdapter', () => { + describe('NanoAdapter', function () { let nanoBidAdapter = spec; - describe('Methods', () => { + describe('Methods', function () { it('Test isBidRequestValid() with valid param(s): pid', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, diff --git a/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js b/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js index 7ed65718657..dd6ed4686d1 100644 --- a/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js +++ b/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js @@ -2,16 +2,16 @@ import {expect} from 'chai'; import {spec} from 'modules/nasmediaAdmixerBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -describe('nasmediaAdmixerBidAdapter', () => { +describe('nasmediaAdmixerBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { const bid = { 'bidder': 'nasmediaAdmixer', 'params': { @@ -24,11 +24,11 @@ describe('nasmediaAdmixerBidAdapter', () => { 'auctionId': '124cb070528662', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { const bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('nasmediaAdmixerBidAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [ { 'bidder': 'nasmediaAdmixer', @@ -53,14 +53,14 @@ describe('nasmediaAdmixerBidAdapter', () => { } ]; - it('sends bid request to url via GET', () => { + it('sends bid request to url via GET', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.method).to.equal('GET'); expect(request.url).to.match(new RegExp(`https://adn.admixer.co.kr`)); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const response = { 'body': { 'bidder': 'nasmedia_admixer', @@ -94,7 +94,7 @@ describe('nasmediaAdmixerBidAdapter', () => { 'auctionId': '169827a33f03cc', }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const expectedResponse = [ { 'requestId': '861a8e7952c82c', @@ -122,7 +122,7 @@ describe('nasmediaAdmixerBidAdapter', () => { }); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { response.body = { 'bidder': 'nasmedia_admixer', 'req_id': '861a8e7952c82c', diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 278b39fd079..f67105751df 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -3,12 +3,12 @@ import { spec } from 'modules/oneVideoBidAdapter'; import * as utils from 'src/utils'; import {config} from 'src/config'; -describe('OneVideoBidAdapter', () => { +describe('OneVideoBidAdapter', function () { let bidRequest; let bidderRequest; let mockConfig; - beforeEach(() => { + beforeEach(function () { bidRequest = { bidder: 'oneVideo', sizes: [640, 480], @@ -33,19 +33,19 @@ describe('OneVideoBidAdapter', () => { }; }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the "video" param is missing', () => { + it('should return false when the "video" param is missing', function () { bidRequest.params = { pubId: 'brxd' }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when the "pubId" param is missing', () => { + it('should return false when the "pubId" param is missing', function () { bidRequest.params = { video: { playerWidth: 480, @@ -60,25 +60,25 @@ describe('OneVideoBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); }); - describe('spec.buildRequests', () => { - it('should create a POST request for every bid', () => { + describe('spec.buildRequests', function () { + it('should create a POST request for every bid', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].method).to.equal('POST'); expect(requests[0].url).to.equal(location.protocol + spec.ENDPOINT + bidRequest.params.pubId); }); - it('should attach the bid request object', () => { + it('should attach the bid request object', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].bidRequest).to.equal(bidRequest); }); - it('should attach request data', () => { + it('should attach request data', function () { const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; const [ width, height ] = bidRequest.sizes; @@ -87,7 +87,7 @@ describe('OneVideoBidAdapter', () => { expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; bidRequest.sizes = [[ width, height ]]; @@ -98,25 +98,25 @@ describe('OneVideoBidAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + it('should return no bids if the response is not valid', function () { const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "nurl" and "adm" are missing', () => { + it('should return no bids if the response "nurl" and "adm" are missing', function () { const serverResponse = {seatbid: [{bid: [{price: 6.01}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "price" is missing', () => { + it('should return no bids if the response "price" is missing', function () { const serverResponse = {seatbid: [{bid: [{adm: ''}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return a valid bid response with just "adm"', () => { + it('should return a valid bid response with just "adm"', function () { const serverResponse = {seatbid: [{bid: [{id: 1, price: 6.01, adm: ''}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { diff --git a/test/spec/modules/oneplanetonlyBidAdapter_spec.js b/test/spec/modules/oneplanetonlyBidAdapter_spec.js index 4a42b471b6f..fbcec66ef51 100644 --- a/test/spec/modules/oneplanetonlyBidAdapter_spec.js +++ b/test/spec/modules/oneplanetonlyBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/oneplanetonlyBidAdapter'; -describe('OnePlanetOnlyAdapter', () => { +describe('OnePlanetOnlyAdapter', function () { let bid = { bidId: '51ef8751f9aead', bidder: 'oneplanetonly', @@ -16,31 +16,31 @@ describe('OnePlanetOnlyAdapter', () => { auctionId: '18fd8b8b0bd757' }; - describe('isBidRequestValid', () => { - it('Should return true if there are params.siteId and params.adUnitId parameters present', () => { + describe('isBidRequestValid', function () { + it('Should return true if there are params.siteId and params.adUnitId parameters present', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false if at least one of parameters is not present', () => { + it('Should return false if at least one of parameters is not present', function () { delete bid.params.adUnitId; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + 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', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//show.oneplanetonly.com/prebid?siteId=5'); }); - it('Returns valid data if array of bids is valid', () => { + 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('id', 'ver', 'prebidVer', 'transactionId', 'currency', 'timeout', 'siteId', @@ -52,14 +52,14 @@ describe('OnePlanetOnlyAdapter', () => { expect(adUnit.bidId).to.equal('51ef8751f9aead'); expect(adUnit.sizes).to.have.members(['300x250', '300x600']); }); - it('Returns empty data if no valid requests are passed', () => { + it('Returns empty data if no valid requests are passed', function () { serverRequest = spec.buildRequests([]); let data = serverRequest.data; expect(data.adUnits).to.be.an('array').that.is.empty; }); }); - describe('interpretResponse', () => { - it('Should interpret banner response', () => { + describe('interpretResponse', function () { + it('Should interpret banner response', function () { const serverResponse = { body: { bids: [{ @@ -89,7 +89,7 @@ describe('OnePlanetOnlyAdapter', () => { expect(bidObject.netRevenue).to.be.true; expect(bidObject.currency).to.equal('USD'); }); - it('Should return an empty array if invalid response is passed', () => { + it('Should return an empty array if invalid response is passed', function () { const invalid = { body: {} }; diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js index 85597a0c6c6..d56ad9e6dc5 100644 --- a/test/spec/modules/onetagBidAdapter_spec.js +++ b/test/spec/modules/onetagBidAdapter_spec.js @@ -1,7 +1,7 @@ import { spec } from 'modules/onetagBidAdapter'; import { expect } from 'chai'; -describe('onetag', () => { +describe('onetag', function () { let bid = { 'bidder': 'onetag', 'params': { @@ -15,43 +15,43 @@ describe('onetag', () => { 'transactionId': 'qwerty123' }; - describe('isBidRequestValid', () => { - it('Should return true when required params are found', () => { + describe('isBidRequestValid', function () { + it('Should return true when required params are found', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false when pubId is not a string', () => { + it('Should return false when pubId is not a string', function () { bid.params.pubId = 30; expect(spec.isBidRequestValid(bid)).to.be.false; }); - it('Should return false when pubId is undefined', () => { + it('Should return false when pubId is undefined', function () { bid.params.pubId = undefined; expect(spec.isBidRequestValid(bid)).to.be.false; }); - it('Should return false when the sizes array is empty', () => { + it('Should return false when the sizes array is empty', function () { bid.sizes = []; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + 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', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('https://onetag-sys.com/prebid-request'); }); const d = serverRequest.data; try { const data = JSON.parse(d); - it('Should contains all keys', () => { + it('Should contains all keys', function () { expect(data).to.be.an('object'); expect(data).to.have.all.keys('location', 'masked', 'referrer', 'sHeight', 'sWidth', 'timeOffset', 'date', 'wHeight', 'wWidth', 'bids'); expect(data.location).to.be.a('string'); @@ -76,7 +76,7 @@ describe('onetag', () => { } catch (e) { console.log('Error while parsing'); } - it('Returns empty data if no valid requests are passed', () => { + it('Returns empty data if no valid requests are passed', function () { serverRequest = spec.buildRequests([]); let dataString = serverRequest.data; try { @@ -86,7 +86,7 @@ describe('onetag', () => { console.log('Error while parsing'); } }); - it('should send GDPR consent data', () => { + it('should send GDPR consent data', function () { let consentString = 'consentString'; let bidderRequest = { 'bidderCode': 'onetag', @@ -107,7 +107,7 @@ describe('onetag', () => { expect(payload.gdprConsent.consentRequired).to.exist.and.to.be.true; }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const resObject = { body: { nobid: false, @@ -123,7 +123,7 @@ describe('onetag', () => { }] } }; - it('Returns an array of valid server responses if response object is valid', () => { + it('Returns an array of valid server responses if response object is valid', function () { const serverResponses = spec.interpretResponse(resObject); expect(serverResponses).to.be.an('array').that.is.not.empty; @@ -140,7 +140,7 @@ describe('onetag', () => { expect(dataItem.netRevenue).to.be.a('boolean'); expect(dataItem.currency).to.be.a('string'); } - it('Returns an empty array if invalid response is passed', () => { + it('Returns an empty array if invalid response is passed', function () { const serverResponses = spec.interpretResponse('invalid_response'); expect(serverResponses).to.be.an('array').that.is.empty; }); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 324f9d80ae4..bce6b2e4acf 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -8,7 +8,7 @@ import * as utils from 'src/utils'; const URLBASE = '/w/1.0/arj'; const URLBASEVIDEO = '/v/1.0/avjp'; -describe('OpenxAdapter', () => { +describe('OpenxAdapter', function () { const adapter = newBidder(spec); /** @@ -121,16 +121,16 @@ describe('OpenxAdapter', () => { } }; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - describe('when request is for a banner ad', () => { + describe('isBidRequestValid', function () { + describe('when request is for a banner ad', function () { let bannerBid; - beforeEach(() => { + beforeEach(function () { bannerBid = { bidder: 'openx', params: {}, @@ -143,35 +143,35 @@ describe('OpenxAdapter', () => { }; }); - it('should return false when there is no delivery domain', () => { + it('should return false when there is no delivery domain', function () { bannerBid.params = {'unit': '12345678'}; expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); - describe('when there is a delivery domain', () => { + describe('when there is a delivery domain', function () { beforeEach(function () { bannerBid.params = {delDomain: 'test-delivery-domain'} }); - it('should return false when there is no ad unit id and size', () => { + it('should return false when there is no ad unit id and size', function () { expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); - it('should return true if there is an adunit id ', () => { + it('should return true if there is an adunit id ', function () { bannerBid.params.unit = '12345678'; expect(spec.isBidRequestValid(bannerBid)).to.equal(true); }); - it('should return true if there is no adunit id and sizes are defined', () => { + it('should return true if there is no adunit id and sizes are defined', function () { bannerBid.mediaTypes.banner.sizes = [720, 90]; expect(spec.isBidRequestValid(bannerBid)).to.equal(true); }); - it('should return false if no sizes are defined ', () => { + it('should return false if no sizes are defined ', function () { expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); - it('should return false if sizes empty ', () => { + it('should return false if sizes empty ', function () { bannerBid.mediaTypes.banner.sizes = []; expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); @@ -211,21 +211,21 @@ describe('OpenxAdapter', () => { 'auctionId': '1d1a030790a475', 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let videoBidWithMediaTypes = Object.assign({}, videoBidWithMediaTypes); videoBidWithMediaTypes.params = {}; expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let videoBidWithMediaType = Object.assign({}, videoBidWithMediaType); delete videoBidWithMediaType.params; videoBidWithMediaType.params = {}; @@ -234,7 +234,7 @@ describe('OpenxAdapter', () => { }); }); - describe('buildRequests for banner ads', () => { + describe('buildRequests for banner ads', function () { const bidRequestsWithMediaType = [{ 'bidder': 'openx', 'params': { @@ -280,24 +280,24 @@ describe('OpenxAdapter', () => { 'auctionId': 'test-auction-2' }]; - it('should send bid request to openx url via GET, with mediaType specified as banner', () => { + it('should send bid request to openx url via GET, with mediaType specified as banner', function () { const request = spec.buildRequests(bidRequestsWithMediaType); expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); }); - it('should send bid request to openx url via GET, with mediaTypes specified with banner type', () => { + it('should send bid request to openx url via GET, with mediaTypes specified with banner type', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); }); - it('should send the adunit codes', () => { + it('should send the adunit codes', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); expect(request[0].data.divIds).to.equal(`${encodeURIComponent(bidRequestsWithMediaTypes[0].adUnitCode)},${encodeURIComponent(bidRequestsWithMediaTypes[1].adUnitCode)}`); }); - it('should send ad unit ids when any are defined', () => { + it('should send ad unit ids when any are defined', function () { const bidRequestsWithUnitIds = [{ 'bidder': 'openx', 'params': { @@ -332,7 +332,7 @@ describe('OpenxAdapter', () => { expect(request[0].data.auid).to.equal(`,${bidRequestsWithUnitIds[1].params.unit}`); }); - it('should not send any ad unit ids when none are defined', () => { + it('should not send any ad unit ids when none are defined', function () { const bidRequestsWithoutUnitIds = [{ 'bidder': 'openx', 'params': { @@ -386,7 +386,7 @@ describe('OpenxAdapter', () => { requestData = spec.buildRequests(deprecatedBidRequestsFormatWithNoMediaType)[0].data; }); - it('should have an ad unit id', () => { + it('should have an ad unit id', function () { expect(requestData.auid).to.equal('12345678'); }); @@ -395,7 +395,7 @@ describe('OpenxAdapter', () => { }); }); - it('should send out custom params on bids that have customParams specified', () => { + it('should send out custom params on bids that have customParams specified', function () { const bidRequest = Object.assign({}, bidRequestsWithMediaTypes[0], { @@ -414,7 +414,7 @@ describe('OpenxAdapter', () => { expect(dataParams.tps).to.equal(btoa('test1=testval1.&test2=testval2_,testval3')); }); - it('should send out custom floors on bids that have customFloors specified', () => { + it('should send out custom floors on bids that have customFloors specified', function () { const bidRequest = Object.assign({}, bidRequestsWithMediaTypes[0], { @@ -433,7 +433,7 @@ describe('OpenxAdapter', () => { expect(dataParams.aumfs).to.equal('1500'); }); - it('should send out custom bc parameter, if override is present', () => { + it('should send out custom bc parameter, if override is present', function () { const bidRequest = Object.assign({}, bidRequestsWithMediaTypes[0], { @@ -459,13 +459,13 @@ describe('OpenxAdapter', () => { expect(request[0].data.x_gdpr_f).to.equal(undefined); }); - describe('when there is a consent management framework', () => { + describe('when there is a consent management framework', function () { let bidRequests; let mockConfig; let bidderRequest; const IAB_CONSENT_FRAMEWORK_CODE = 1; - beforeEach(() => { + beforeEach(function () { bidRequests = [{ bidder: 'openx', params: { @@ -632,7 +632,7 @@ describe('OpenxAdapter', () => { }); }); - it('should not send a coppa query param when there are no coppa param settings in the bid requests', () => { + it('should not send a coppa query param when there are no coppa param settings in the bid requests', function () { const bidRequestsWithoutCoppa = [{ bidder: 'openx', params: { @@ -669,7 +669,7 @@ describe('OpenxAdapter', () => { expect(request[0].data).to.not.have.any.keys('tfcd'); }); - it('should send a coppa flag there is when there is coppa param settings in the bid requests', () => { + it('should send a coppa flag there is when there is coppa param settings in the bid requests', function () { const bidRequestsWithCoppa = [{ bidder: 'openx', params: { @@ -707,7 +707,7 @@ describe('OpenxAdapter', () => { expect(request[0].data.tfcd).to.equal(1); }); - it('should not send a "no segmentation" flag there no DoNotTrack setting that is set to true', () => { + it('should not send a "no segmentation" flag there no DoNotTrack setting that is set to true', function () { const bidRequestsWithoutDnt = [{ bidder: 'openx', params: { @@ -744,7 +744,7 @@ describe('OpenxAdapter', () => { expect(request[0].data).to.not.have.any.keys('ns'); }); - it('should send a "no segmentation" flag there is any DoNotTrack setting that is set to true', () => { + it('should send a "no segmentation" flag there is any DoNotTrack setting that is set to true', function () { const bidRequestsWithDnt = [{ bidder: 'openx', params: { @@ -783,7 +783,7 @@ describe('OpenxAdapter', () => { }); }); - describe('buildRequests for video', () => { + describe('buildRequests for video', function () { const bidRequestsWithMediaTypes = [{ 'bidder': 'openx', 'mediaTypes': { @@ -818,19 +818,19 @@ describe('OpenxAdapter', () => { 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' }]; - it('should send bid request to openx url via GET, with mediaType as video', () => { + it('should send bid request to openx url via GET, with mediaType as video', function () { const request = spec.buildRequests(bidRequestsWithMediaType); expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); - it('should send bid request to openx url via GET, with mediaTypes having video parameter', () => { + it('should send bid request to openx url via GET, with mediaTypes having video parameter', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); - it('should have the correct parameters', () => { + it('should have the correct parameters', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); const dataParams = request[0].data; @@ -839,7 +839,7 @@ describe('OpenxAdapter', () => { expect(dataParams.vwd).to.equal(640); }); - it('should send a bc parameter', () => { + it('should send a bc parameter', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); const dataParams = request[0].data; @@ -933,8 +933,8 @@ describe('OpenxAdapter', () => { }); }); - describe('interpretResponse for banner ads', () => { - beforeEach(() => { + describe('interpretResponse for banner ads', function () { + beforeEach(function () { sinon.spy(userSync, 'registerSync'); }); @@ -1030,7 +1030,7 @@ describe('OpenxAdapter', () => { expect(bid.ts).to.equal(adUnitOverride.ts); }); - it('should register a beacon', () => { + it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequest); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(new RegExp(`\/\/openx-d\.openx\.net.*\/bo\?.*ts=${adUnitOverride.ts}`))); @@ -1107,7 +1107,7 @@ describe('OpenxAdapter', () => { }; }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { const bidResponse = { 'ads': { @@ -1215,8 +1215,8 @@ describe('OpenxAdapter', () => { }); }); - describe('interpretResponse for video ads', () => { - beforeEach(() => { + describe('interpretResponse for video ads', function () { + beforeEach(function () { sinon.spy(userSync, 'registerSync'); }); @@ -1273,7 +1273,7 @@ describe('OpenxAdapter', () => { 'pixels': 'http://testpixels.net' }; - it('should return correct bid response with MediaTypes', () => { + it('should return correct bid response with MediaTypes', function () { const expectedResponse = [ { 'requestId': '30b31c1838de1e', @@ -1294,7 +1294,7 @@ describe('OpenxAdapter', () => { expect(JSON.stringify(Object.keys(result[0]).sort())).to.eql(JSON.stringify(Object.keys(expectedResponse[0]).sort())); }); - it('should return correct bid response with MediaType', () => { + it('should return correct bid response with MediaType', function () { const expectedResponse = [ { 'requestId': '30b31c1838de1e', @@ -1315,19 +1315,19 @@ describe('OpenxAdapter', () => { expect(JSON.stringify(Object.keys(result[0]).sort())).to.eql(JSON.stringify(Object.keys(expectedResponse[0]).sort())); }); - it('should handle nobid responses for bidRequests with MediaTypes', () => { + it('should handle nobid responses for bidRequests with MediaTypes', function () { const bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); expect(result.length).to.equal(0); }); - it('should handle nobid responses for bidRequests with MediaType', () => { + it('should handle nobid responses for bidRequests with MediaType', function () { const bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaType); expect(result.length).to.equal(0); }); - it('should register a beacon', () => { + it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/^\/\/test-colo\.com/)) @@ -1336,10 +1336,10 @@ describe('OpenxAdapter', () => { }); }); - describe('user sync', () => { + describe('user sync', function () { const syncUrl = 'http://testpixels.net'; - it('should register the pixel iframe from banner ad response', () => { + it('should register the pixel iframe from banner ad response', function () { let syncs = spec.getUserSyncs( {iframeEnabled: true}, [{body: {ads: {pixels: syncUrl}}}] @@ -1347,7 +1347,7 @@ describe('OpenxAdapter', () => { expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); }); - it('should register the pixel iframe from video ad response', () => { + it('should register the pixel iframe from video ad response', function () { let syncs = spec.getUserSyncs( {iframeEnabled: true}, [{body: {pixels: syncUrl}}] @@ -1355,7 +1355,7 @@ describe('OpenxAdapter', () => { expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); }); - it('should register the default iframe if no pixels available', () => { + it('should register the default iframe if no pixels available', function () { let syncs = spec.getUserSyncs( {iframeEnabled: true}, [] diff --git a/test/spec/modules/optimaticBidAdapter_spec.js b/test/spec/modules/optimaticBidAdapter_spec.js index d701d981f37..3dd7ca79cc7 100644 --- a/test/spec/modules/optimaticBidAdapter_spec.js +++ b/test/spec/modules/optimaticBidAdapter_spec.js @@ -2,10 +2,10 @@ import { expect } from 'chai'; import { spec, ENDPOINT } from 'modules/optimaticBidAdapter'; import * as utils from 'src/utils'; -describe('OptimaticBidAdapter', () => { +describe('OptimaticBidAdapter', function () { let bidRequest; - beforeEach(() => { + beforeEach(function () { bidRequest = { bidder: 'optimatic', params: { @@ -20,49 +20,49 @@ describe('OptimaticBidAdapter', () => { }; }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the "bidfloor" param is missing', () => { + it('should return false when the "bidfloor" param is missing', function () { bidRequest.params = { placement: '2chy7Gc2eSQL' }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when the "placement" param is missing', () => { + it('should return false when the "placement" param is missing', function () { bidRequest.params = { bidfloor: 5.00 }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when a bid request is not passed', () => { + 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', () => { - it('should create a POST request for every bid', () => { + describe('spec.buildRequests', function () { + it('should create a POST request for every bid', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].method).to.equal('POST'); expect(requests[0].url).to.equal(ENDPOINT + bidRequest.params.placement); }); - it('should attach the bid request object', () => { + it('should attach the bid request object', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].bidRequest).to.equal(bidRequest); }); - it('should attach request data', () => { + it('should attach request data', function () { const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; const [ width, height ] = bidRequest.sizes; @@ -71,7 +71,7 @@ describe('OptimaticBidAdapter', () => { expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; bidRequest.sizes = [[ width, height ]]; @@ -81,7 +81,7 @@ describe('OptimaticBidAdapter', () => { expect(data.imp[0].video.h).to.equal(height); }); - it('must parse bid size from a string', () => { + it('must parse bid size from a string', function () { const width = 640; const height = 480; bidRequest.sizes = `${width}x${height}`; @@ -91,7 +91,7 @@ describe('OptimaticBidAdapter', () => { expect(data.imp[0].video.h).to.equal(height); }); - it('must handle an empty bid size', () => { + it('must handle an empty bid size', function () { bidRequest.sizes = []; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; @@ -100,25 +100,25 @@ describe('OptimaticBidAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + it('should return no bids if the response is not valid', function () { const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "nurl" and "adm" are missing', () => { + it('should return no bids if the response "nurl" and "adm" are missing', function () { const serverResponse = {seatbid: [{bid: [{price: 5.01}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "price" is missing', () => { + it('should return no bids if the response "price" is missing', function () { const serverResponse = {seatbid: [{bid: [{adm: ''}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return a valid bid response with just "adm"', () => { + it('should return a valid bid response with just "adm"', function () { const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, adm: ''}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { @@ -137,7 +137,7 @@ describe('OptimaticBidAdapter', () => { expect(bidResponse).to.deep.equal(o); }); - it('should return a valid bid response with just "nurl"', () => { + it('should return a valid bid response with just "nurl"', function () { const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, nurl: 'https://mg-bid-win.optimatic.com/win/134eb262-948a-463e-ad93-bc8b622d399c?wp=${AUCTION_PRICE}'}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { @@ -156,7 +156,7 @@ describe('OptimaticBidAdapter', () => { expect(bidResponse).to.deep.equal(o); }); - it('should return a valid bid response with "nurl" when both nurl and adm exist', () => { + it('should return a valid bid response with "nurl" when both nurl and adm exist', function () { const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, adm: '', nurl: 'https://mg-bid-win.optimatic.com/win/134eb262-948a-463e-ad93-bc8b622d399c?wp=${AUCTION_PRICE}'}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { diff --git a/test/spec/modules/optimeraBidAdapter_spec.js b/test/spec/modules/optimeraBidAdapter_spec.js index 413a52d2d7f..ff5793b5040 100644 --- a/test/spec/modules/optimeraBidAdapter_spec.js +++ b/test/spec/modules/optimeraBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/optimeraBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('OptimeraAdapter', () => { +describe('OptimeraAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }) - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'optimera', 'params': { @@ -24,12 +24,12 @@ describe('OptimeraAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); }) - describe('buildRequests', () => { + describe('buildRequests', function () { let bid = [ { 'adUnitCode': 'div-0', @@ -42,7 +42,7 @@ describe('OptimeraAdapter', () => { } } ]; - it('buildRequests fires', () => { + it('buildRequests fires', function () { let request = spec.buildRequests(bid); expect(request).to.exist; expect(request.method).to.equal('GET'); @@ -51,7 +51,7 @@ describe('OptimeraAdapter', () => { }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse = {}; serverResponse.body = JSON.parse('{"div-0":["RB_K","728x90K"], "timestamp":["RB_K","1507565666"]}'); var bidRequest = { @@ -67,7 +67,7 @@ describe('OptimeraAdapter', () => { } ] } - it('interpresResponse fires', () => { + it('interpresResponse fires', function () { let bidResponses = spec.interpretResponse(serverResponse, bidRequest); expect(bidResponses[0].dealId[0]).to.equal('RB_K'); expect(bidResponses[0].dealId[1]).to.equal('728x90K'); diff --git a/test/spec/modules/orbitsoftBidAdapter_spec.js b/test/spec/modules/orbitsoftBidAdapter_spec.js index 50145a1e72e..18ba9a6e8f3 100644 --- a/test/spec/modules/orbitsoftBidAdapter_spec.js +++ b/test/spec/modules/orbitsoftBidAdapter_spec.js @@ -2,10 +2,10 @@ import {expect} from 'chai'; import {spec} from 'modules/orbitsoftBidAdapter'; const ENDPOINT_URL = 'https://orbitsoft.com/php/ads/hb.phps'; -describe('Orbitsoft adapter', () => { - describe('implementation', () => { - describe('for requests', () => { - it('should accept valid bid', () => { +describe('Orbitsoft adapter', function () { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { let validBid = { bidder: 'orbitsoft', params: { @@ -18,7 +18,7 @@ describe('Orbitsoft adapter', () => { expect(isValid).to.equal(true); }); - it('should reject invalid bid', () => { + it('should reject invalid bid', function () { let invalidBid = { bidder: 'orbitsoft' }, @@ -27,8 +27,8 @@ describe('Orbitsoft adapter', () => { expect(isValid).to.equal(false); }); }); - describe('for requests', () => { - it('should accept valid bid with styles', () => { + describe('for requests', function () { + it('should accept valid bid with styles', function () { let validBid = { bidder: 'orbitsoft', params: { @@ -91,7 +91,7 @@ describe('Orbitsoft adapter', () => { expect(requestUrlParams).have.property('c6', '5B99FE'); }); - it('should accept valid bid with custom params', () => { + it('should accept valid bid with custom params', function () { let validBid = { bidder: 'orbitsoft', params: { @@ -112,7 +112,7 @@ describe('Orbitsoft adapter', () => { expect(requestUrlCustomParams).have.property('c.clickUrl', 'http://testclickurl.com'); }); - it('should reject invalid bid without requestUrl', () => { + it('should reject invalid bid without requestUrl', function () { let invalidBid = { bidder: 'orbitsoft', params: { @@ -124,7 +124,7 @@ describe('Orbitsoft adapter', () => { expect(isValid).to.equal(false); }); - it('should reject invalid bid without placementId', () => { + it('should reject invalid bid without placementId', function () { let invalidBid = { bidder: 'orbitsoft', params: { @@ -136,8 +136,8 @@ describe('Orbitsoft adapter', () => { expect(isValid).to.equal(false); }); }); - describe('bid responses', () => { - it('should return complete bid response', () => { + describe('bid responses', function () { + it('should return complete bid response', function () { let serverResponse = { body: { callback_uid: '265b29b70cc106', @@ -168,7 +168,7 @@ describe('Orbitsoft adapter', () => { expect(bids[0].adUrl).to.have.string('https://orbitsoft.com/php/ads/hb.html'); }); - it('should return empty bid response', () => { + it('should return empty bid response', function () { let bidRequests = [ { bidder: 'orbitsoft', @@ -189,7 +189,7 @@ describe('Orbitsoft adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on incorrect size', () => { + it('should return empty bid response on incorrect size', function () { let bidRequests = [ { bidder: 'orbitsoft', @@ -212,7 +212,7 @@ describe('Orbitsoft adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with error', () => { + it('should return empty bid response with error', function () { let bidRequests = [ { bidder: 'orbitsoft', @@ -228,7 +228,7 @@ describe('Orbitsoft adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on empty body', () => { + it('should return empty bid response on empty body', function () { let bidRequests = [ { bidder: 'orbitsoft', diff --git a/test/spec/modules/papyrusBidAdapter_spec.js b/test/spec/modules/papyrusBidAdapter_spec.js index a61a1c55269..289da56379a 100644 --- a/test/spec/modules/papyrusBidAdapter_spec.js +++ b/test/spec/modules/papyrusBidAdapter_spec.js @@ -4,8 +4,8 @@ import { spec } from 'modules/papyrusBidAdapter'; const ENDPOINT = '//prebid.papyrus.global'; const BIDDER_CODE = 'papyrus'; -describe('papyrus Adapter', () => { - describe('isBidRequestValid', () => { +describe('papyrus Adapter', function () { + describe('isBidRequestValid', function () { let validBidReq = { bidder: BIDDER_CODE, params: { @@ -14,7 +14,7 @@ describe('papyrus Adapter', () => { } }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(validBidReq)).to.equal(true); }); @@ -25,12 +25,12 @@ describe('papyrus Adapter', () => { } }; - it('should not validate incorrect bid request', () => { + it('should not validate incorrect bid request', function () { expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { bidder: BIDDER_CODE, @@ -46,29 +46,29 @@ describe('papyrus Adapter', () => { } ]; - it('sends bid request to ENDPOINT via POST', () => { + 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('sends valid bids count', () => { + it('sends valid bids count', function () { const request = spec.buildRequests(bidRequests); expect(request.data.length).to.equal(1); }); - it('sends all bid parameters', () => { + it('sends all bid parameters', function () { const request = spec.buildRequests(bidRequests); expect(request.data[0]).to.have.all.keys(['address', 'placementId', 'sizes', 'bidId', 'transactionId']); }); - it('sedns valid sizes parameter', () => { + it('sedns valid sizes parameter', function () { const request = spec.buildRequests(bidRequests); expect(request.data[0].sizes[0]).to.equal('300x250'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let bidRequests = [ { bidder: BIDDER_CODE, @@ -96,13 +96,13 @@ describe('papyrus Adapter', () => { ] }; - it('should build bid array', () => { + it('should build bid array', function () { const request = spec.buildRequests(bidRequests); const result = spec.interpretResponse({body: bidResponse}, request[0]); expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const request = spec.buildRequests(bidRequests); const result = spec.interpretResponse({body: bidResponse}, request[0]); const bid = result[0]; diff --git a/test/spec/modules/peak226BidAdapter_spec.js b/test/spec/modules/peak226BidAdapter_spec.js index f85e46c4289..8b8157225bb 100644 --- a/test/spec/modules/peak226BidAdapter_spec.js +++ b/test/spec/modules/peak226BidAdapter_spec.js @@ -4,11 +4,11 @@ import { newBidder } from 'src/adapters/bidderFactory'; const URL = 'a.ad216.com/header_bid'; -describe('PeakAdapter', () => { +describe('PeakAdapter', function () { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { const bid = { params: { uid: 123 @@ -18,7 +18,7 @@ describe('PeakAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { const bid = { params: {} }; @@ -27,7 +27,7 @@ describe('PeakAdapter', () => { }); }); - // xdescribe('buildRequests', () => { + // xdescribe('buildRequests', function () { // const bidRequests = [ // { // params: { @@ -36,7 +36,7 @@ describe('PeakAdapter', () => { // } // ]; - // it('sends bid request to URL via GET', () => { + // it('sends bid request to URL via GET', function () { // const request = spec.buildRequests(bidRequests); // expect(request.url).to.equal(`${URL}?uids=1234`); @@ -44,8 +44,8 @@ describe('PeakAdapter', () => { // }); // }); - describe('interpretResponse', () => { - it('should handle empty response', () => { + describe('interpretResponse', function () { + it('should handle empty response', function () { let bids = spec.interpretResponse( {}, { @@ -56,7 +56,7 @@ describe('PeakAdapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle no seatbid returned', () => { + it('should handle no seatbid returned', function () { let response = {}; let bids = spec.interpretResponse( @@ -69,7 +69,7 @@ describe('PeakAdapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle empty seatbid returned', () => { + it('should handle empty seatbid returned', function () { let response = { seatbid: [] }; let bids = spec.interpretResponse( @@ -82,7 +82,7 @@ describe('PeakAdapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle seatbid returned bids', () => { + it('should handle seatbid returned bids', function () { const bidsMap = { 1: [{ bidId: 11 }] }; const bid = { price: 0.2, diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index 39ada3cc01c..f3754654cf1 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -1,335 +1,335 @@ -import {expect} from 'chai'; -import {spec} from 'modules/platformioBidAdapter'; -import {getTopWindowLocation} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; - -describe('Platform.io Adapter Tests', () => { - const slotConfigs = [{ - placementCode: '/DfpAccount1/slot1', - bidId: 'bid12345', - mediaType: 'banner', - params: { - pubId: '29521', - siteId: '26047', - placementId: '123', - size: '300x250', - bidFloor: '0.001', - ifa: 'IFA', - latitude: '40.712775', - longitude: '-74.005973' - } - }, { - placementCode: '/DfpAccount2/slot2', - bidId: 'bid23456', - mediaType: 'banner', - params: { - pubId: '29521', - siteId: '26047', - placementId: '1234', - size: '728x90', - bidFloor: '0.000001', - } - }]; - const nativeSlotConfig = [{ - placementCode: '/DfpAccount1/slot3', - bidId: 'bid12345', - mediaType: 'native', - nativeParams: { - title: { required: true, len: 200 }, - body: {}, - image: { wmin: 100 }, - sponsoredBy: { }, - icon: { } - }, - params: { - pubId: '29521', - placementId: '123', - siteId: '26047' - } - }]; - const videoSlotConfig = [{ - placementCode: '/DfpAccount1/slot4', - bidId: 'bid12345678', - mediaType: 'video', - video: { - skippable: true - }, - params: { - pubId: '29521', - placementId: '1234567', - siteId: '26047', - size: '640x480' - } - }]; - const appSlotConfig = [{ - placementCode: '/DfpAccount1/slot5', - bidId: 'bid12345', - params: { - pubId: '29521', - placementId: '1234', - app: { - id: '1111', - name: 'app name', - bundle: 'io.platform.apps', - storeUrl: 'http://platform.io/apps', - domain: 'platform.io' - } - } - }]; - - it('Verify build request', () => { - const request = spec.buildRequests(slotConfigs); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // site object - expect(ortbRequest.site).to.not.equal(null); - expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('29521'); - expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); - expect(ortbRequest.imp).to.have.lengthOf(2); - // device object - expect(ortbRequest.device).to.not.equal(null); - expect(ortbRequest.device.ua).to.equal(navigator.userAgent); - expect(ortbRequest.device.ifa).to.equal('IFA'); - expect(ortbRequest.device.geo.lat).to.equal('40.712775'); - expect(ortbRequest.device.geo.lon).to.equal('-74.005973'); - // slot 1 - expect(ortbRequest.imp[0].tagid).to.equal('123'); - expect(ortbRequest.imp[0].banner).to.not.equal(null); - expect(ortbRequest.imp[0].banner.w).to.equal(300); - expect(ortbRequest.imp[0].banner.h).to.equal(250); - expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); - // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('1234'); - expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(728); - expect(ortbRequest.imp[1].banner.h).to.equal(90); - expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); - }); - - it('Verify parse response', () => { - const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: 'This is an Ad' - }] - }], - cur: 'USD' - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.ad).to.equal('This is an Ad'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.adId).to.equal('bid12345'); - expect(bid.creativeId).to.equal('bid12345'); - expect(bid.netRevenue).to.equal(true); - expect(bid.currency).to.equal('USD'); - expect(bid.ttl).to.equal(360); - }); - - it('Verify full passback', () => { - const request = spec.buildRequests(slotConfigs); - const bids = spec.interpretResponse({ body: null }, request) - expect(bids).to.have.lengthOf(0); - }); - - it('Verify Native request', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // native impression - expect(ortbRequest.imp[0].tagid).to.equal('123'); - const nativePart = ortbRequest.imp[0]['native']; - expect(nativePart).to.not.equal(null); - expect(nativePart.ver).to.equal('1.1'); - expect(nativePart.request).to.not.equal(null); - // native request assets - const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); - expect(nativeRequest).to.not.equal(null); - expect(nativeRequest.assets).to.have.lengthOf(5); - expect(nativeRequest.assets[0].id).to.equal(1); - expect(nativeRequest.assets[1].id).to.equal(2); - expect(nativeRequest.assets[2].id).to.equal(3); - expect(nativeRequest.assets[3].id).to.equal(4); - expect(nativeRequest.assets[4].id).to.equal(5); - expect(nativeRequest.assets[0].required).to.equal(1); - expect(nativeRequest.assets[0].title).to.not.equal(null); - expect(nativeRequest.assets[0].title.len).to.equal(200); - expect(nativeRequest.assets[1].title).to.be.undefined; - expect(nativeRequest.assets[1].data).to.not.equal(null); - expect(nativeRequest.assets[1].data.type).to.equal(2); - expect(nativeRequest.assets[1].data.len).to.equal(200); - expect(nativeRequest.assets[2].required).to.equal(0); - expect(nativeRequest.assets[3].img).to.not.equal(null); - expect(nativeRequest.assets[3].img.wmin).to.equal(50); - expect(nativeRequest.assets[3].img.hmin).to.equal(50); - expect(nativeRequest.assets[3].img.type).to.equal(1); - expect(nativeRequest.assets[4].img).to.not.equal(null); - expect(nativeRequest.assets[4].img.wmin).to.equal(100); - expect(nativeRequest.assets[4].img.hmin).to.equal(150); - expect(nativeRequest.assets[4].img.type).to.equal(3); - }); - - it('Verify Native response', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - const nativeResponse = { - 'native': { - assets: [ - { id: 1, title: { text: 'Ad Title' } }, - { id: 2, data: { value: 'Test description' } }, - { id: 3, data: { value: 'Brand' } }, - { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, - { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } - ], - link: { url: 'http://brand.com/' } - } - }; - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - nurl: 'http://rtb.adx1.com/log', - adm: JSON.stringify(nativeResponse) - }] - }], - cur: 'USD', - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - // verify bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.adId).to.equal('bid12345'); - expect(bid.ad).to.be.undefined; - expect(bid.mediaType).to.equal('native'); - const nativeBid = bid['native']; - expect(nativeBid).to.not.equal(null); - expect(nativeBid.title).to.equal('Ad Title'); - expect(nativeBid.sponsoredBy).to.equal('Brand'); - expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); - expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); - expect(nativeBid.image.width).to.equal(300); - expect(nativeBid.image.height).to.equal(300); - expect(nativeBid.icon.width).to.equal(100); - expect(nativeBid.icon.height).to.equal(100); - expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); - expect(nativeBid.impressionTrackers).to.have.lengthOf(1); - expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); - }); - - it('Verify Video request', () => { - const request = spec.buildRequests(videoSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const videoRequest = JSON.parse(request.data); - // site object - expect(videoRequest.site).to.not.equal(null); - expect(videoRequest.site.publisher.id).to.equal('29521'); - expect(videoRequest.site.ref).to.equal(window.top.document.referrer); - expect(videoRequest.site.page).to.equal(getTopWindowLocation().href); - // device object - expect(videoRequest.device).to.not.equal(null); - expect(videoRequest.device.ua).to.equal(navigator.userAgent); - // slot 1 - expect(videoRequest.imp[0].tagid).to.equal('1234567'); - expect(videoRequest.imp[0].video).to.not.equal(null); - expect(videoRequest.imp[0].video.w).to.equal(640); - expect(videoRequest.imp[0].video.h).to.equal(480); - expect(videoRequest.imp[0].banner).to.equal(null); - expect(videoRequest.imp[0].native).to.equal(null); - }); - - it('Verify parse video response', () => { - const request = spec.buildRequests(videoSlotConfig); - const videoRequest = JSON.parse(request.data); - const videoResponse = { - seatbid: [{ - bid: [{ - impid: videoRequest.imp[0].id, - price: 1.90, - adm: 'http://vid.example.com/9876', - crid: '510511_754567308' - }] - }], - cur: 'USD' - }; - const bids = spec.interpretResponse({ body: videoResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.90); - expect(bid.vastUrl).to.equal('http://vid.example.com/9876'); - expect(bid.crid).to.equal('510511_754567308'); - expect(bid.width).to.equal(640); - expect(bid.height).to.equal(480); - expect(bid.adId).to.equal('bid12345678'); - expect(bid.netRevenue).to.equal(true); - expect(bid.currency).to.equal('USD'); - expect(bid.ttl).to.equal(360); - }); - - it('Verifies bidder code', () => { - expect(spec.code).to.equal('platformio'); - }); - - it('Verifies supported media types', () => { - expect(spec.supportedMediaTypes).to.have.lengthOf(3); - expect(spec.supportedMediaTypes[0]).to.equal('banner'); - expect(spec.supportedMediaTypes[1]).to.equal('native'); - expect(spec.supportedMediaTypes[2]).to.equal('video'); - }); - - it('Verifies if bid request valid', () => { - expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); - expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); - expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); - }); - - it('Verify app requests', () => { - const request = spec.buildRequests(appSlotConfig); - const ortbRequest = JSON.parse(request.data); - expect(ortbRequest.site).to.equal(null); - expect(ortbRequest.app).to.not.be.null; - expect(ortbRequest.app.publisher).to.not.equal(null); - expect(ortbRequest.app.publisher.id).to.equal('29521'); - expect(ortbRequest.app.id).to.equal('1111'); - expect(ortbRequest.app.name).to.equal('app name'); - expect(ortbRequest.app.bundle).to.equal('io.platform.apps'); - expect(ortbRequest.app.storeurl).to.equal('http://platform.io/apps'); - expect(ortbRequest.app.domain).to.equal('platform.io'); - }); - - it('Verify GDPR', () => { - const bidderRequest = { - gdprConsent: { - gdprApplies: true, - consentString: 'serialized_gpdr_data' - } - }; - const request = spec.buildRequests(slotConfigs, bidderRequest); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - expect(ortbRequest.user).to.not.equal(null); - expect(ortbRequest.user.ext).to.not.equal(null); - expect(ortbRequest.user.ext.consent).to.equal('serialized_gpdr_data'); - expect(ortbRequest.regs).to.not.equal(null); - expect(ortbRequest.regs.ext).to.not.equal(null); - expect(ortbRequest.regs.ext.gdpr).to.equal(1); - }); -}); +import {expect} from 'chai'; +import {spec} from 'modules/platformioBidAdapter'; +import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; + +describe('Platform.io Adapter Tests', function () { + const slotConfigs = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + mediaType: 'banner', + params: { + pubId: '29521', + siteId: '26047', + placementId: '123', + size: '300x250', + bidFloor: '0.001', + ifa: 'IFA', + latitude: '40.712775', + longitude: '-74.005973' + } + }, { + placementCode: '/DfpAccount2/slot2', + bidId: 'bid23456', + mediaType: 'banner', + params: { + pubId: '29521', + siteId: '26047', + placementId: '1234', + size: '728x90', + bidFloor: '0.000001', + } + }]; + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + mediaType: 'native', + nativeParams: { + title: { required: true, len: 200 }, + body: {}, + image: { wmin: 100 }, + sponsoredBy: { }, + icon: { } + }, + params: { + pubId: '29521', + placementId: '123', + siteId: '26047' + } + }]; + const videoSlotConfig = [{ + placementCode: '/DfpAccount1/slot4', + bidId: 'bid12345678', + mediaType: 'video', + video: { + skippable: true + }, + params: { + pubId: '29521', + placementId: '1234567', + siteId: '26047', + size: '640x480' + } + }]; + const appSlotConfig = [{ + placementCode: '/DfpAccount1/slot5', + bidId: 'bid12345', + params: { + pubId: '29521', + placementId: '1234', + app: { + id: '1111', + name: 'app name', + bundle: 'io.platform.apps', + storeUrl: 'http://platform.io/apps', + domain: 'platform.io' + } + } + }]; + + it('Verify build request', function () { + const request = spec.buildRequests(slotConfigs); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // site object + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.publisher).to.not.equal(null); + expect(ortbRequest.site.publisher.id).to.equal('29521'); + expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); + expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); + expect(ortbRequest.imp).to.have.lengthOf(2); + // device object + expect(ortbRequest.device).to.not.equal(null); + expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + expect(ortbRequest.device.ifa).to.equal('IFA'); + expect(ortbRequest.device.geo.lat).to.equal('40.712775'); + expect(ortbRequest.device.geo.lon).to.equal('-74.005973'); + // slot 1 + expect(ortbRequest.imp[0].tagid).to.equal('123'); + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); + // slot 2 + expect(ortbRequest.imp[1].tagid).to.equal('1234'); + expect(ortbRequest.imp[1].banner).to.not.equal(null); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); + expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); + }); + + it('Verify parse response', function () { + const request = spec.buildRequests(slotConfigs); + const ortbRequest = JSON.parse(request.data); + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'This is an Ad' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.ad).to.equal('This is an Ad'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.adId).to.equal('bid12345'); + expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + + it('Verify full passback', function () { + const request = spec.buildRequests(slotConfigs); + const bids = spec.interpretResponse({ body: null }, request) + expect(bids).to.have.lengthOf(0); + }); + + it('Verify Native request', function () { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // native impression + expect(ortbRequest.imp[0].tagid).to.equal('123'); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(5); + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[3].id).to.equal(4); + expect(nativeRequest.assets[4].id).to.equal(5); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(2); + expect(nativeRequest.assets[1].data.len).to.equal(200); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[3].img).to.not.equal(null); + expect(nativeRequest.assets[3].img.wmin).to.equal(50); + expect(nativeRequest.assets[3].img.hmin).to.equal(50); + expect(nativeRequest.assets[3].img.type).to.equal(1); + expect(nativeRequest.assets[4].img).to.not.equal(null); + expect(nativeRequest.assets[4].img.wmin).to.equal(100); + expect(nativeRequest.assets[4].img.hmin).to.equal(150); + expect(nativeRequest.assets[4].img.type).to.equal(3); + }); + + it('Verify Native response', function () { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { id: 1, title: { text: 'Ad Title' } }, + { id: 2, data: { value: 'Test description' } }, + { id: 3, data: { value: 'Brand' } }, + { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + ], + link: { url: 'http://brand.com/' } + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + nurl: 'http://rtb.adx1.com/log', + adm: JSON.stringify(nativeResponse) + }] + }], + cur: 'USD', + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Brand'); + expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.image.width).to.equal(300); + expect(nativeBid.image.height).to.equal(300); + expect(nativeBid.icon.width).to.equal(100); + expect(nativeBid.icon.height).to.equal(100); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(1); + expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); + }); + + it('Verify Video request', function () { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const videoRequest = JSON.parse(request.data); + // site object + expect(videoRequest.site).to.not.equal(null); + expect(videoRequest.site.publisher.id).to.equal('29521'); + expect(videoRequest.site.ref).to.equal(window.top.document.referrer); + expect(videoRequest.site.page).to.equal(getTopWindowLocation().href); + // device object + expect(videoRequest.device).to.not.equal(null); + expect(videoRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(videoRequest.imp[0].tagid).to.equal('1234567'); + expect(videoRequest.imp[0].video).to.not.equal(null); + expect(videoRequest.imp[0].video.w).to.equal(640); + expect(videoRequest.imp[0].video.h).to.equal(480); + expect(videoRequest.imp[0].banner).to.equal(null); + expect(videoRequest.imp[0].native).to.equal(null); + }); + + it('Verify parse video response', function () { + const request = spec.buildRequests(videoSlotConfig); + const videoRequest = JSON.parse(request.data); + const videoResponse = { + seatbid: [{ + bid: [{ + impid: videoRequest.imp[0].id, + price: 1.90, + adm: 'http://vid.example.com/9876', + crid: '510511_754567308' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: videoResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.90); + expect(bid.vastUrl).to.equal('http://vid.example.com/9876'); + expect(bid.crid).to.equal('510511_754567308'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.adId).to.equal('bid12345678'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + + it('Verifies bidder code', function () { + expect(spec.code).to.equal('platformio'); + }); + + it('Verifies supported media types', function () { + expect(spec.supportedMediaTypes).to.have.lengthOf(3); + expect(spec.supportedMediaTypes[0]).to.equal('banner'); + expect(spec.supportedMediaTypes[1]).to.equal('native'); + expect(spec.supportedMediaTypes[2]).to.equal('video'); + }); + + it('Verifies if bid request valid', function () { + expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); + expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); + }); + + it('Verify app requests', function () { + const request = spec.buildRequests(appSlotConfig); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.publisher).to.not.equal(null); + expect(ortbRequest.app.publisher.id).to.equal('29521'); + expect(ortbRequest.app.id).to.equal('1111'); + expect(ortbRequest.app.name).to.equal('app name'); + expect(ortbRequest.app.bundle).to.equal('io.platform.apps'); + expect(ortbRequest.app.storeurl).to.equal('http://platform.io/apps'); + expect(ortbRequest.app.domain).to.equal('platform.io'); + }); + + it('Verify GDPR', function () { + const bidderRequest = { + gdprConsent: { + gdprApplies: true, + consentString: 'serialized_gpdr_data' + } + }; + const request = spec.buildRequests(slotConfigs, bidderRequest); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.user).to.not.equal(null); + expect(ortbRequest.user.ext).to.not.equal(null); + expect(ortbRequest.user.ext.consent).to.equal('serialized_gpdr_data'); + expect(ortbRequest.regs).to.not.equal(null); + expect(ortbRequest.regs.ext).to.not.equal(null); + expect(ortbRequest.regs.ext.gdpr).to.equal(1); + }); +}); diff --git a/test/spec/modules/playgroundxyzBidAdapter_spec.js b/test/spec/modules/playgroundxyzBidAdapter_spec.js index becd8612a9c..ac0922ef82e 100644 --- a/test/spec/modules/playgroundxyzBidAdapter_spec.js +++ b/test/spec/modules/playgroundxyzBidAdapter_spec.js @@ -6,16 +6,16 @@ import { deepClone } from 'src/utils'; const URL = 'https://ads.playground.xyz/host-config/prebid'; const GDPR_CONSENT = 'XYZ-CONSENT'; -describe('playgroundxyzBidAdapter', () => { +describe('playgroundxyzBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'playgroundxyz', 'params': { @@ -28,11 +28,11 @@ describe('playgroundxyzBidAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -42,7 +42,7 @@ describe('playgroundxyzBidAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'playgroundxyz', @@ -57,7 +57,7 @@ describe('playgroundxyzBidAdapter', () => { } ]; - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { let bidRequest = Object.assign([], bidRequests); const request = spec.buildRequests(bidRequest); @@ -72,7 +72,7 @@ describe('playgroundxyzBidAdapter', () => { }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'id': 'bidd_id', 'seatbid': [ { @@ -109,7 +109,7 @@ describe('playgroundxyzBidAdapter', () => { 'bidderCode': 'playgroundxyz' }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { 'requestId': '221f2bdc1fbc31', @@ -128,14 +128,14 @@ describe('playgroundxyzBidAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = ''; let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(result.length).to.equal(0); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'playgroundxyz', @@ -150,7 +150,7 @@ describe('playgroundxyzBidAdapter', () => { } ]; - it('should not populate GDPR', () => { + it('should not populate GDPR', function () { let bidRequest = Object.assign([], bidRequests); const request = spec.buildRequests(bidRequest); let data = JSON.parse(request.data); @@ -158,7 +158,7 @@ describe('playgroundxyzBidAdapter', () => { expect(data).to.not.have.property('regs'); }); - it('should populate GDPR and consent string when consetString is presented but not gdpApplies', () => { + it('should populate GDPR and consent string when consetString is presented but not gdpApplies', function () { let bidRequest = Object.assign([], bidRequests); const request = spec.buildRequests(bidRequest, {gdprConsent: {consentString: GDPR_CONSENT}}); let data = JSON.parse(request.data); @@ -166,7 +166,7 @@ describe('playgroundxyzBidAdapter', () => { expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); }); - it('should populate GDPR and consent string when gdpr is set to true', () => { + it('should populate GDPR and consent string when gdpr is set to true', function () { let bidRequest = Object.assign([], bidRequests); const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true, consentString: GDPR_CONSENT}}); let data = JSON.parse(request.data); @@ -174,7 +174,7 @@ describe('playgroundxyzBidAdapter', () => { expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); }); - it('should populate GDPR and consent string when gdpr is set to false', () => { + it('should populate GDPR and consent string when gdpr is set to false', function () { let bidRequest = Object.assign([], bidRequests); const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: false, consentString: GDPR_CONSENT}}); let data = JSON.parse(request.data); diff --git a/test/spec/modules/polluxBidAdapter_spec.js b/test/spec/modules/polluxBidAdapter_spec.js index ea550fecd71..ad30771e15b 100644 --- a/test/spec/modules/polluxBidAdapter_spec.js +++ b/test/spec/modules/polluxBidAdapter_spec.js @@ -24,7 +24,7 @@ describe('POLLUX Bid Adapter tests', function () { params: {zone: '276'} }]; - it('TEST: verify buildRequests no valid bid requests', () => { + it('TEST: verify buildRequests no valid bid requests', function () { let request = spec.buildRequests(false); expect(request).to.not.equal(null); expect(request).to.not.have.property('method'); @@ -47,7 +47,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(request).to.not.have.property('data'); }); - it('TEST: verify buildRequests single bid', () => { + it('TEST: verify buildRequests single bid', function () { const request = spec.buildRequests(setup_single_bid); expect(request.method).to.equal('POST'); const requested_bids = JSON.parse(request.data); @@ -70,7 +70,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(requested_bids[0].zones).to.equal('1806,276'); }); - it('TEST: verify buildRequests multi bid', () => { + it('TEST: verify buildRequests multi bid', function () { const request = spec.buildRequests(setup_multi_bid); expect(request.method).to.equal('POST'); const requested_bids = JSON.parse(request.data); @@ -102,7 +102,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(requested_bids[1].zones).to.equal('276'); }); - it('TEST: verify interpretResponse empty', () => { + it('TEST: verify interpretResponse empty', function () { let bids = spec.interpretResponse(false, {}); expect(bids).to.not.equal(null); expect(bids).to.have.lengthOf(0); @@ -117,7 +117,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(bids).to.have.lengthOf(0); }); - it('TEST: verify interpretResponse ad_type url', () => { + it('TEST: verify interpretResponse ad_type url', function () { const serverResponse = { body: [ { @@ -147,7 +147,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(bids[0]).to.not.have.property('ad'); }); - it('TEST: verify interpretResponse ad_type html', () => { + it('TEST: verify interpretResponse ad_type html', function () { const serverResponse = { body: [ { @@ -176,7 +176,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(bids[0].ad).to.equal('

I am an ad

'); }); - it('TEST: verify url and query params', () => { + it('TEST: verify url and query params', function () { const URL = require('url-parse'); const querystringify = require('querystringify'); const request = spec.buildRequests(setup_single_bid); @@ -188,7 +188,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(parsedQuery).to.have.property('domain').and.to.have.length.above(1); }); - it('TEST: verify isBidRequestValid', () => { + it('TEST: verify isBidRequestValid', function () { expect(spec.isBidRequestValid({})).to.equal(false); expect(spec.isBidRequestValid({params: {}})).to.equal(false); expect(spec.isBidRequestValid(setup_single_bid[0])).to.equal(true); @@ -196,11 +196,11 @@ describe('POLLUX Bid Adapter tests', function () { expect(spec.isBidRequestValid(setup_multi_bid[1])).to.equal(true); }); - it('TEST: verify bidder code', () => { + it('TEST: verify bidder code', function () { expect(spec.code).to.equal('pollux'); }); - it('TEST: verify bidder aliases', () => { + it('TEST: verify bidder aliases', function () { expect(spec.aliases).to.have.lengthOf(1); expect(spec.aliases[0]).to.equal('plx'); }); diff --git a/test/spec/modules/polymorphBidAdapter_spec.js b/test/spec/modules/polymorphBidAdapter_spec.js index cf20cdfaf22..e2df44e8cfc 100644 --- a/test/spec/modules/polymorphBidAdapter_spec.js +++ b/test/spec/modules/polymorphBidAdapter_spec.js @@ -33,19 +33,19 @@ const bidRequests = [{ 'auctionId': '1d1a030790a476', }]; -describe('Polymorph adapter test', () => { - describe('.code', () => { - it('should return a bidder code of polymorph', () => { +describe('Polymorph adapter test', function () { + describe('.code', function () { + it('should return a bidder code of polymorph', function () { expect(spec.code).to.eql(BIDDER_CODE); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); }); - it('should return false if req has no placementId', () => { + it('should return false if req has no placementId', function () { const invalidBidRequest = { bidder: BIDDER_CODE, params: { @@ -55,7 +55,7 @@ describe('Polymorph adapter test', () => { expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); }); - it('should return false if req has wrong bidder code', () => { + it('should return false if req has wrong bidder code', function () { const invalidBidRequest = { bidder: 'something', params: { @@ -66,8 +66,8 @@ describe('Polymorph adapter test', () => { }); }); - describe('buildRequests', () => { - it('payload test', () => { + describe('buildRequests', function () { + it('payload test', function () { const requests = spec.buildRequests(bidRequests); var payload1 = {}; requests[0].data.replace(/([^=&]+)=([^&]*)/g, function(m, key, value) { @@ -92,14 +92,14 @@ describe('Polymorph adapter test', () => { expect(payload2.sizes).to.equal('700,250,300,600'); }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].url).to.equal(ENDPOINT_URL); expect(requests[0].method).to.equal('GET'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const response = { body: { 'status': 'OK', @@ -133,7 +133,7 @@ describe('Polymorph adapter test', () => { } }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const body = response.body; const expectedResponse = [{ requestId: bidRequests[0].bidId, @@ -152,7 +152,7 @@ describe('Polymorph adapter test', () => { expect(result).to.deep.equal(expectedResponse); }); - it('widget use case', () => { + it('widget use case', function () { const body = response2.body; const expectedResponse = [ { @@ -173,7 +173,7 @@ describe('Polymorph adapter test', () => { expect(result).to.deep.equal(expectedResponse); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = []; let result = spec.interpretResponse(response, { 'bidderRequest': bidRequests[0] }); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 556755316eb..a22006e5a81 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -329,12 +329,12 @@ const RESPONSE_UNSUPPORTED_BIDDER = { }] }; -describe('S2S Adapter', () => { +describe('S2S Adapter', function () { let adapter, addBidResponse = sinon.spy(), done = sinon.spy(); - beforeEach(() => { + beforeEach(function () { adapter = new Adapter(); BID_REQUESTS = [ { @@ -370,16 +370,16 @@ describe('S2S Adapter', () => { ]; }); - afterEach(() => { + afterEach(function () { addBidResponse.resetHistory(); done.resetHistory(); }); - describe('request function', () => { + describe('request function', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); @@ -387,13 +387,15 @@ describe('S2S Adapter', () => { resetSyncedStatus(); }); - afterEach(() => xhr.restore()); + afterEach(function () { + xhr.restore(); + }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); - it('exists converts types', () => { + it('exists converts types', function () { config.setConfig({s2sConfig: CONFIG}); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); @@ -402,13 +404,13 @@ describe('S2S Adapter', () => { expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); }); - describe('gdpr tests', () => { - afterEach(() => { + describe('gdpr tests', function () { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); }); - it('adds gdpr consent information to ortb2 request depending on presence of module', () => { + it('adds gdpr consent information to ortb2 request depending on presence of module', function () { let ortb2Config = utils.deepClone(CONFIG); ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' @@ -437,7 +439,7 @@ describe('S2S Adapter', () => { expect(requestBid.user).to.not.exist; }); - it('check gdpr info gets added into cookie_sync request: have consent data', () => { + it('check gdpr info gets added into cookie_sync request: have consent data', function () { let cookieSyncConfig = utils.deepClone(CONFIG); cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; @@ -458,7 +460,7 @@ describe('S2S Adapter', () => { expect(requestBid.gdpr_consent).is.equal('abc123def'); }); - it('check gdpr info gets added into cookie_sync request: have consent data but gdprApplies is false', () => { + it('check gdpr info gets added into cookie_sync request: have consent data but gdprApplies is false', function () { let cookieSyncConfig = utils.deepClone(CONFIG); cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; @@ -478,7 +480,7 @@ describe('S2S Adapter', () => { expect(requestBid.gdpr_consent).is.undefined; }); - it('checks gdpr info gets added to cookie_sync request: consent data unknown', () => { + it('checks gdpr info gets added to cookie_sync request: consent data unknown', function () { let cookieSyncConfig = utils.deepClone(CONFIG); cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; @@ -499,7 +501,7 @@ describe('S2S Adapter', () => { }); }); - it('sets invalid cacheMarkup value to 0', () => { + it('sets invalid cacheMarkup value to 0', function () { const s2sConfig = Object.assign({}, CONFIG, { cacheMarkup: 999 }); @@ -509,7 +511,7 @@ describe('S2S Adapter', () => { expect(requestBid).to.have.property('cache_markup', 0); }); - it('adds digitrust id is present and user is not optout', () => { + it('adds digitrust id is present and user is not optout', function () { let digiTrustObj = { success: true, identity: { @@ -544,7 +546,7 @@ describe('S2S Adapter', () => { delete window.DigiTrust; }); - it('adds device and app objects to request', () => { + it('adds device and app objects to request', function () { const _config = { s2sConfig: CONFIG, device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, app: { bundle: 'com.test.app' }, @@ -562,7 +564,7 @@ describe('S2S Adapter', () => { }); }); - it('adds device and app objects to request for ORTB', () => { + it('adds device and app objects to request for ORTB', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -585,7 +587,7 @@ describe('S2S Adapter', () => { }); }); - it('adds site if app is not present', () => { + it('adds site if app is not present', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -602,7 +604,7 @@ describe('S2S Adapter', () => { expect(requestBid.site.page).to.exist.and.to.be.a('string'); }); - it('adds appnexus aliases to request', () => { + it('adds appnexus aliases to request', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -629,7 +631,7 @@ describe('S2S Adapter', () => { }); }); - it('adds dynamic aliases to request', () => { + it('adds dynamic aliases to request', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -659,7 +661,7 @@ describe('S2S Adapter', () => { }); }); - it('converts appnexus params to expected format for PBS', () => { + it('converts appnexus params to expected format for PBS', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -710,11 +712,11 @@ describe('S2S Adapter', () => { }); }); - describe('response handler', () => { + describe('response handler', function () { let server; let logWarnSpy; - beforeEach(() => { + beforeEach(function () { server = sinon.fakeServer.create(); sinon.stub(utils, 'triggerPixel'); sinon.stub(utils, 'insertUserSyncIframe'); @@ -724,7 +726,7 @@ describe('S2S Adapter', () => { logWarnSpy = sinon.spy(utils, 'logWarn'); }); - afterEach(() => { + afterEach(function () { server.restore(); utils.triggerPixel.restore(); utils.insertUserSyncIframe.restore(); @@ -735,7 +737,7 @@ describe('S2S Adapter', () => { }); // TODO: test dependent on pbjs_api_spec. Needs to be isolated - it('registers bids and calls BIDDER_DONE', () => { + it('registers bids and calls BIDDER_DONE', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -758,7 +760,7 @@ describe('S2S Adapter', () => { expect(response).to.not.have.property('vastUrl'); }); - it('registers video bids', () => { + it('registers video bids', function () { server.respondWith(JSON.stringify(VIDEO_RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -776,7 +778,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('vastUrl', 'video_cache_url'); }); - it('does not call addBidResponse and calls done when ad unit not set', () => { + it('does not call addBidResponse and calls done when ad unit not set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); config.setConfig({s2sConfig: CONFIG}); @@ -787,7 +789,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(done); }); - it('does not call addBidResponse and calls done when server requests cookie sync', () => { + it('does not call addBidResponse and calls done when server requests cookie sync', function () { server.respondWith(JSON.stringify(RESPONSE_NO_COOKIE)); config.setConfig({s2sConfig: CONFIG}); @@ -798,7 +800,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(done); }); - it('does not call addBidResponse and calls done when ad unit is set', () => { + it('does not call addBidResponse and calls done when ad unit is set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_UNIT_SET)); config.setConfig({s2sConfig: CONFIG}); @@ -809,7 +811,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(done); }); - it('registers successful bids and calls done when there are less bids than requests', () => { + it('registers successful bids and calls done when there are less bids than requests', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -827,7 +829,7 @@ describe('S2S Adapter', () => { .to.have.property('statusMessage', 'Bid available'); }); - it('should have dealId in bidObject', () => { + it('should have dealId in bidObject', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -837,7 +839,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('dealId', 'test-dealid'); }); - it('should pass through default adserverTargeting if present in bidObject', () => { + it('should pass through default adserverTargeting if present in bidObject', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -847,7 +849,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('adserverTargeting').that.deep.equals({'foo': 'bar'}); }); - it('registers client user syncs when client bid adapter is present', () => { + it('registers client user syncs when client bid adapter is present', function () { let rubiconAdapter = { registerSyncs: sinon.spy() }; @@ -864,7 +866,7 @@ describe('S2S Adapter', () => { adapterManager.getBidAdapter.restore(); }); - it('registers client user syncs when using OpenRTB endpoint', () => { + it('registers client user syncs when using OpenRTB endpoint', function () { let rubiconAdapter = { registerSyncs: sinon.spy() }; @@ -884,7 +886,7 @@ describe('S2S Adapter', () => { adapterManager.getBidAdapter.restore(); }); - it('registers bid responses when server requests cookie sync', () => { + it('registers bid responses when server requests cookie sync', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); config.setConfig({s2sConfig: CONFIG}); @@ -903,7 +905,7 @@ describe('S2S Adapter', () => { expect(bid_request_passed).to.have.property('adId', '123'); }); - it('does not call cookieSet cookie sync when no_cookie response && not opted in', () => { + it('does not call cookieSet cookie sync when no_cookie response && not opted in', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); let myConfig = Object.assign({}, CONFIG); @@ -914,7 +916,7 @@ describe('S2S Adapter', () => { sinon.assert.notCalled(cookie.cookieSet); }); - it('calls cookieSet cookie sync when no_cookie response && opted in', () => { + it('calls cookieSet cookie sync when no_cookie response && opted in', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); let myConfig = Object.assign({ cookieSet: true, @@ -927,7 +929,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(cookie.cookieSet); }); - it('handles OpenRTB responses and call BIDDER_DONE', () => { + it('handles OpenRTB responses and call BIDDER_DONE', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -950,7 +952,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('cpm', 0.5); }); - it('handles OpenRTB video responses', () => { + it('handles OpenRTB video responses', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); @@ -970,7 +972,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('cpm', 10); }); - it('should log warning for unsupported bidder', () => { + it('should log warning for unsupported bidder', function () { server.respondWith(JSON.stringify(RESPONSE_UNSUPPORTED_BIDDER)); const s2sConfig = Object.assign({}, CONFIG, { @@ -990,18 +992,18 @@ describe('S2S Adapter', () => { }); }); - describe('s2sConfig', () => { + describe('s2sConfig', function () { let logErrorSpy; - beforeEach(() => { + beforeEach(function () { logErrorSpy = sinon.spy(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { utils.logError.restore(); }); - it('should log an error when accountId is missing', () => { + it('should log an error when accountId is missing', function () { const options = { enabled: true, bidders: ['appnexus'], @@ -1014,7 +1016,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should log an error when bidders is missing', () => { + it('should log an error when bidders is missing', function () { const options = { accountId: '1', enabled: true, @@ -1027,7 +1029,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should log an error when endpoint is missing', () => { + it('should log an error when endpoint is missing', function () { const options = { accountId: '1', bidders: ['appnexus'], @@ -1040,7 +1042,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should log an error when using an unknown vendor', () => { + it('should log an error when using an unknown vendor', function () { const options = { accountId: '1', bidders: ['appnexus'], @@ -1051,7 +1053,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should configure the s2sConfig object with appnexus vendor defaults unless specified by user', () => { + it('should configure the s2sConfig object with appnexus vendor defaults unless specified by user', function () { const options = { accountId: '123', bidders: ['appnexus'], @@ -1074,7 +1076,7 @@ describe('S2S Adapter', () => { expect(vendorConfig).to.have.property('timeout', 750); }); - it('should configure the s2sConfig object with rubicon vendor defaults unless specified by user', () => { + it('should configure the s2sConfig object with rubicon vendor defaults unless specified by user', function () { const options = { accountId: 'abc', bidders: ['rubicon'], diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js index bdb9d4f0545..aaf296cfb43 100644 --- a/test/spec/modules/pubCommonId_spec.js +++ b/test/spec/modules/pubCommonId_spec.js @@ -18,7 +18,7 @@ const COOKIE_NAME = '_pubcid'; const TIMEOUT = 2000; describe('Publisher Common ID', function () { - afterEach(() => { + afterEach(function () { $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidHook); }); describe('Decorate adUnits', function () { @@ -159,7 +159,7 @@ describe('Publisher Common ID', function () { getUserSyncs: () => {} }; - beforeEach(() => { + beforeEach(function () { adUnits = [{ code: 'adUnit-code', mediaTypes: { @@ -179,7 +179,7 @@ describe('Publisher Common ID', function () { registerBidder(sampleSpec); }); - afterEach(() => { + afterEach(function () { auctionModule.newAuction.restore(); }); diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 5c1d668f435..e67ec1f11a2 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -3,13 +3,13 @@ import {spec} from 'modules/pubmaticBidAdapter'; import * as utils from 'src/utils'; const constants = require('src/constants.json'); -describe('PubMatic adapter', () => { +describe('PubMatic adapter', function () { let bidRequests; let videoBidRequests; let multipleMediaRequests; let bidResponses; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'pubmatic', @@ -155,9 +155,9 @@ describe('PubMatic adapter', () => { }; }); - describe('implementation', () => { - describe('Bid validations', () => { - it('valid bid case', () => { + describe('implementation', function () { + describe('Bid validations', function () { + it('valid bid case', function () { let validBid = { bidder: 'pubmatic', params: { @@ -169,7 +169,7 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(true); }); - it('invalid bid case: publisherId not passed', () => { + it('invalid bid case: publisherId not passed', function () { let validBid = { bidder: 'pubmatic', params: { @@ -180,7 +180,7 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(false); }); - it('invalid bid case: publisherId is not string', () => { + it('invalid bid case: publisherId is not string', function () { let validBid = { bidder: 'pubmatic', params: { @@ -192,7 +192,7 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(false); }); - it('invalid bid case: adSlot not passed', () => { + it('invalid bid case: adSlot not passed', function () { let validBid = { bidder: 'pubmatic', params: { @@ -203,7 +203,7 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(false); }); - it('invalid bid case: adSlot is not string', () => { + it('invalid bid case: adSlot is not string', function () { let validBid = { bidder: 'pubmatic', params: { @@ -216,14 +216,14 @@ describe('PubMatic adapter', () => { }); }); - describe('Request formation', () => { - it('Endpoint checking', () => { + describe('Request formation', function () { + it('Endpoint checking', function () { let request = spec.buildRequests(bidRequests); expect(request.url).to.equal('//hbopenbid.pubmatic.com/translator?source=prebid-client'); expect(request.method).to.equal('POST'); }); - it('Request params check', () => { + it('Request params check', function () { let request = spec.buildRequests(bidRequests); let data = JSON.parse(request.data); expect(data.at).to.equal(1); // auction type @@ -254,7 +254,7 @@ describe('PubMatic adapter', () => { expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); }); - it('Request params multi size format object check', () => { + it('Request params multi size format object check', function () { let bidRequests = [ { bidder: 'pubmatic', @@ -309,7 +309,7 @@ describe('PubMatic adapter', () => { expect(data.imp[0].banner.format[0].h).to.equal(600); // height }); - it('Request params currency check', () => { + it('Request params currency check', function () { let multipleBidRequests = [ { bidder: 'pubmatic', @@ -406,7 +406,7 @@ describe('PubMatic adapter', () => { expect(data.imp[1].bidfloorcur).to.equal('USD'); }); - it('Request params check with GDPR Consent', () => { + it('Request params check with GDPR Consent', function () { let bidRequest = { gdprConsent: { consentString: 'kjfdniwjnifwenrif3', @@ -442,7 +442,7 @@ describe('PubMatic adapter', () => { expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid }); - it('Request params check for video ad', () => { + it('Request params check for video ad', function () { let request = spec.buildRequests(videoBidRequests); let data = JSON.parse(request.data); expect(data.imp[0].video).to.exist; @@ -480,7 +480,7 @@ describe('PubMatic adapter', () => { expect(data.imp[0]['video']['h']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[1]); }); - it('Request params check for 1 banner and 1 video ad', () => { + it('Request params check for 1 banner and 1 video ad', function () { let request = spec.buildRequests(multipleMediaRequests); let data = JSON.parse(request.data); @@ -549,7 +549,7 @@ describe('PubMatic adapter', () => { }); }); - it('Request params dctr check', () => { + it('Request params dctr check', function () { let multipleBidRequests = [ { bidder: 'pubmatic', @@ -632,8 +632,8 @@ describe('PubMatic adapter', () => { expect(data.site.ext).to.not.exist; }); - describe('Response checking', () => { - it('should check for valid response values', () => { + describe('Response checking', function () { + it('should check for valid response values', function () { let request = spec.buildRequests(bidRequests); let response = spec.interpretResponse(bidResponses, request); expect(response).to.be.an('array').with.length.above(0); @@ -670,7 +670,7 @@ describe('PubMatic adapter', () => { expect(response[1].ad).to.equal(bidResponses.body.seatbid[1].bid[0].adm); }); - it('should check for dealChannel value selection', () => { + it('should check for dealChannel value selection', function () { let request = spec.buildRequests(bidRequests); let response = spec.interpretResponse(bidResponses, request); expect(response).to.be.an('array').with.length.above(0); @@ -678,7 +678,7 @@ describe('PubMatic adapter', () => { expect(response[1].dealChannel).to.equal('PREF'); }); - it('should check for unexpected dealChannel value selection', () => { + it('should check for unexpected dealChannel value selection', function () { let request = spec.buildRequests(bidRequests); let updateBiResponse = bidResponses; updateBiResponse.body.seatbid[0].bid[0].ext.deal_channel = 11; diff --git a/test/spec/modules/pubwiseAnalyticsAdapter_spec.js b/test/spec/modules/pubwiseAnalyticsAdapter_spec.js index ffb8d3c0570..e7e31fccc43 100644 --- a/test/spec/modules/pubwiseAnalyticsAdapter_spec.js +++ b/test/spec/modules/pubwiseAnalyticsAdapter_spec.js @@ -6,21 +6,21 @@ let constants = require('src/constants.json'); describe('PubWise Prebid Analytics', function () { let xhr; - before(() => { + before(function () { xhr = sinon.useFakeXMLHttpRequest(); }); - after(() => { + after(function () { xhr.restore(); pubwiseAnalytics.disableAnalytics(); }); describe('enableAnalytics', function () { - beforeEach(() => { + beforeEach(function () { sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { events.getEvents.restore(); }); diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 709dbeb76a2..ebeedde7783 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -4,7 +4,7 @@ import {spec} from 'modules/pulsepointBidAdapter'; import {getTopWindowLocation} from 'src/utils'; import {newBidder} from 'src/adapters/bidderFactory'; -describe('PulsePoint Adapter Tests', () => { +describe('PulsePoint Adapter Tests', function () { const slotConfigs = [{ placementCode: '/DfpAccount1/slot1', bidId: 'bid12345', @@ -49,7 +49,7 @@ describe('PulsePoint Adapter Tests', () => { } }]; - it('Verify build request', () => { + it('Verify build request', function () { const request = spec.buildRequests(slotConfigs); expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); expect(request.method).to.equal('POST'); @@ -76,7 +76,7 @@ describe('PulsePoint Adapter Tests', () => { expect(ortbRequest.imp[1].banner.h).to.equal(90); }); - it('Verify parse response', () => { + it('Verify parse response', function () { const request = spec.buildRequests(slotConfigs); const ortbRequest = JSON.parse(request.data); const ortbResponse = { @@ -104,7 +104,7 @@ describe('PulsePoint Adapter Tests', () => { expect(bid.ttl).to.equal(20); }); - it('Verify use ttl in ext', () => { + it('Verify use ttl in ext', function () { const request = spec.buildRequests(slotConfigs); const ortbRequest = JSON.parse(request.data); const ortbResponse = { @@ -130,13 +130,13 @@ describe('PulsePoint Adapter Tests', () => { expect(bid.currency).to.equal('INR'); }); - it('Verify full passback', () => { + it('Verify full passback', function () { const request = spec.buildRequests(slotConfigs); const bids = spec.interpretResponse({ body: null }, request) expect(bids).to.have.lengthOf(0); }); - it('Verify Native request', () => { + it('Verify Native request', function () { const request = spec.buildRequests(nativeSlotConfig); expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); expect(request.method).to.equal('POST'); @@ -174,7 +174,7 @@ describe('PulsePoint Adapter Tests', () => { expect(nativeRequest.assets[2].img.type).to.equal(3); }); - it('Verify Native response', () => { + it('Verify Native response', function () { const request = spec.buildRequests(nativeSlotConfig); expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); expect(request.method).to.equal('POST'); @@ -217,22 +217,22 @@ describe('PulsePoint Adapter Tests', () => { expect(nativeBid.impressionTrackers[1]).to.equal('http://imp1.contextweb.com/'); }); - it('Verifies bidder code', () => { + it('Verifies bidder code', function () { expect(spec.code).to.equal('pulsepoint'); }); - it('Verifies bidder aliases', () => { + it('Verifies bidder aliases', function () { expect(spec.aliases).to.have.lengthOf(2); expect(spec.aliases[0]).to.equal('pulseLite'); expect(spec.aliases[1]).to.equal('pulsepointLite'); }); - it('Verifies supported media types', () => { + it('Verifies supported media types', function () { expect(spec.supportedMediaTypes).to.have.lengthOf(2); expect(spec.supportedMediaTypes[1]).to.equal('native'); }); - it('Verifies if bid request valid', () => { + it('Verifies if bid request valid', function () { expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); @@ -243,7 +243,7 @@ describe('PulsePoint Adapter Tests', () => { expect(spec.isBidRequestValid({ params: { ct: 123, cp: 234 } })).to.equal(true); }); - it('Verifies sync options', () => { + it('Verifies sync options', function () { expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; const options = spec.getUserSyncs({ iframeEnabled: true }); @@ -253,7 +253,7 @@ describe('PulsePoint Adapter Tests', () => { expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch'); }); - it('Verifies image pixel sync', () => { + it('Verifies image pixel sync', function () { const options = spec.getUserSyncs({ pixelEnabled: true }); expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); @@ -261,7 +261,7 @@ describe('PulsePoint Adapter Tests', () => { expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch/prebid'); }); - it('Verify app requests', () => { + it('Verify app requests', function () { const request = spec.buildRequests(appSlotConfig); const ortbRequest = JSON.parse(request.data); // site object @@ -274,7 +274,7 @@ describe('PulsePoint Adapter Tests', () => { expect(ortbRequest.app.domain).to.equal('pulsepoint.com'); }); - it('Verify GDPR', () => { + it('Verify GDPR', function () { const bidderRequest = { gdprConsent: { gdprApplies: true, diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index b6fc3f27f94..f5a7602c7ab 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -13,11 +13,11 @@ import { import { newBidder } from '../../../src/adapters/bidderFactory'; import { parse } from 'src/url'; -describe('Quantcast adapter', () => { +describe('Quantcast adapter', function () { const quantcastAdapter = newBidder(qcSpec); let bidRequest; - beforeEach(() => { + beforeEach(function () { bidRequest = { bidder: 'quantcast', bidId: '2f7b179d443f14', @@ -32,32 +32,32 @@ describe('Quantcast adapter', () => { }; }); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(quantcastAdapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('`isBidRequestValid`', () => { - it('should return `false` when bid is not passed', () => { + describe('`isBidRequestValid`', function () { + it('should return `false` when bid is not passed', function () { expect(qcSpec.isBidRequestValid()).to.equal(false); }); - it('should return `false` when bid `mediaType` is `video`', () => { + it('should return `false` when bid `mediaType` is `video`', function () { const bidRequest = { mediaType: 'video' }; expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return `true` when bid contains required params', () => { + it('should return `true` when bid contains required params', function () { const bidRequest = { mediaType: 'banner' }; expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); }); }); - describe('`buildRequests`', () => { - it('selects protocol and port', () => { + describe('`buildRequests`', function () { + it('selects protocol and port', function () { switch (window.location.protocol) { case 'https:': expect(QUANTCAST_PROTOCOL).to.equal('https'); @@ -70,13 +70,13 @@ describe('Quantcast adapter', () => { } }); - it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', () => { + it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', function () { const requests = qcSpec.buildRequests([bidRequest]); const url = parse(requests[0]['url']); expect(url.hostname).to.equal(QUANTCAST_TEST_DOMAIN); }); - it('sends bid requests to default endpoint for non standard publisher IDs', () => { + it('sends bid requests to default endpoint for non standard publisher IDs', function () { const modifiedBidRequest = Object.assign({}, bidRequest, { params: Object.assign({}, bidRequest.params, { publisherId: 'foo-bar', @@ -88,13 +88,13 @@ describe('Quantcast adapter', () => { ); }); - it('sends bid requests to Quantcast Header Bidding Endpoints via POST', () => { + it('sends bid requests to Quantcast Header Bidding Endpoints via POST', function () { const requests = qcSpec.buildRequests([bidRequest]); expect(requests[0].method).to.equal('POST'); }); - it('sends bid requests contains all the required parameters', () => { + it('sends bid requests contains all the required parameters', function () { const referrer = utils.getTopWindowUrl(); const loc = utils.getTopWindowLocation(); const domain = loc.hostname; @@ -126,7 +126,7 @@ describe('Quantcast adapter', () => { }); }); - it('propagates GDPR consent string and signal', () => { + it('propagates GDPR consent string and signal', function () { const gdprConsent = { gdprApplies: true, consentString: 'consentString' } const requests = qcSpec.buildRequests([bidRequest], { gdprConsent }); const parsed = JSON.parse(requests[0].data) @@ -134,7 +134,7 @@ describe('Quantcast adapter', () => { expect(parsed.gdprConsent).to.equal(gdprConsent.consentString); }); - describe('`interpretResponse`', () => { + describe('`interpretResponse`', function () { // The sample response is from https://wiki.corp.qc/display/adinf/QCX const body = { bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name @@ -159,25 +159,25 @@ describe('Quantcast adapter', () => { headers: {} }; - it('should return an empty array if `serverResponse` is `undefined`', () => { + it('should return an empty array if `serverResponse` is `undefined`', function () { const interpretedResponse = qcSpec.interpretResponse(); expect(interpretedResponse.length).to.equal(0); }); - it('should return an empty array if the parsed response does NOT include `bids`', () => { + it('should return an empty array if the parsed response does NOT include `bids`', function () { const interpretedResponse = qcSpec.interpretResponse({}); expect(interpretedResponse.length).to.equal(0); }); - it('should return an empty array if the parsed response has an empty `bids`', () => { + it('should return an empty array if the parsed response has an empty `bids`', function () { const interpretedResponse = qcSpec.interpretResponse({ bids: [] }); expect(interpretedResponse.length).to.equal(0); }); - it('should get correct bid response', () => { + it('should get correct bid response', function () { const expectedResponse = { requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', cpm: 4.5, @@ -195,7 +195,7 @@ describe('Quantcast adapter', () => { expect(interpretedResponse[0]).to.deep.equal(expectedResponse); }); - it('handles no bid response', () => { + it('handles no bid response', function () { const body = { bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames diff --git a/test/spec/modules/quantumBidAdapter_spec.js b/test/spec/modules/quantumBidAdapter_spec.js index f45b9ed37e7..d14d24ebfe1 100644 --- a/test/spec/modules/quantumBidAdapter_spec.js +++ b/test/spec/modules/quantumBidAdapter_spec.js @@ -203,38 +203,38 @@ const nativeServerResponse = { ] } -describe('quantumBidAdapter', () => { +describe('quantumBidAdapter', function () { const adapter = newBidder(spec) - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function') }) }) - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, REQUEST) delete bid.params expect(spec.isBidRequestValid(bid)).to.equal(false) }) }) - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [REQUEST] const request = spec.buildRequests(bidRequests, {}) - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(request[0].method).to.equal('GET') }) }) - describe('GDPR conformity', () => { + describe('GDPR conformity', function () { const bidRequests = [{ 'bidder': 'quantum', 'mediaType': 'native', @@ -256,7 +256,7 @@ describe('quantumBidAdapter', () => { } }; - it('should transmit correct data', () => { + it('should transmit correct data', function () { const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests.length).to.equal(1); expect(requests[0].data.quantx_gdpr).to.equal(1); @@ -264,7 +264,7 @@ describe('quantumBidAdapter', () => { }); }); - describe('GDPR absence conformity', () => { + describe('GDPR absence conformity', function () { const bidRequests = [{ 'bidder': 'quantum', 'mediaType': 'native', @@ -283,7 +283,7 @@ describe('quantumBidAdapter', () => { gdprConsent: undefined }; - it('should transmit correct data', () => { + it('should transmit correct data', function () { const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests.length).to.equal(1); expect(requests[0].data.quantx_gdpr).to.be.undefined; @@ -291,13 +291,13 @@ describe('quantumBidAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let bidderRequest = { bidderCode: 'bidderCode', bids: [] } - it('handles native request : should get correct bid response', () => { + it('handles native request : should get correct bid response', function () { const result = spec.interpretResponse({body: nativeServerResponse}, NATIVE_REQUEST) expect(result[0]).to.have.property('cpm').equal(0.3) expect(result[0]).to.have.property('width').to.be.below(2) @@ -306,7 +306,7 @@ describe('quantumBidAdapter', () => { expect(result[0]).to.have.property('native') }) - it('should get correct bid response', () => { + it('should get correct bid response', function () { const result = spec.interpretResponse({body: serverResponse}, REQUEST) expect(result[0]).to.have.property('cpm').equal(0.3) expect(result[0]).to.have.property('width').equal(300) @@ -315,7 +315,7 @@ describe('quantumBidAdapter', () => { expect(result[0]).to.have.property('ad') }) - it('handles nobid responses', () => { + it('handles nobid responses', function () { const nobidServerResponse = {bids: []} const nobidResult = spec.interpretResponse({body: nobidServerResponse}, bidderRequest) // console.log(nobidResult) diff --git a/test/spec/modules/readpeakBidAdapter_spec.js b/test/spec/modules/readpeakBidAdapter_spec.js index 776261c8db2..572c2b73f8c 100644 --- a/test/spec/modules/readpeakBidAdapter_spec.js +++ b/test/spec/modules/readpeakBidAdapter_spec.js @@ -2,12 +2,12 @@ import { expect } from 'chai'; import { spec, ENDPOINT } from 'modules/readpeakBidAdapter'; import * as utils from 'src/utils'; -describe('ReadPeakAdapter', () => { +describe('ReadPeakAdapter', function () { let bidRequest let serverResponse let serverRequest - beforeEach(() => { + beforeEach(function () { bidRequest = { bidder: 'readpeak', nativeParams: { @@ -113,42 +113,42 @@ describe('ReadPeakAdapter', () => { } }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the native params are missing', () => { + it('should return false when the native params are missing', function () { bidRequest.nativeParams = undefined; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when the "publisherId" param is missing', () => { + it('should return false when the "publisherId" param is missing', function () { bidRequest.params = { bidfloor: 5.00 }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when a bid request is not passed', () => { + 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', () => { - it('should create a POST request for every bid', () => { + describe('spec.buildRequests', function () { + it('should create a POST request for every bid', function () { const request = spec.buildRequests([ bidRequest ]); expect(request.method).to.equal('POST'); expect(request.url).to.equal(ENDPOINT); }); - it('should attach request data', () => { + it('should attach request data', function () { const request = spec.buildRequests([ bidRequest ]); const data = JSON.parse(request.data); @@ -171,13 +171,13 @@ describe('ReadPeakAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - it('should return no bids if the response is not valid', () => { + 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); }); - it('should return a valid bid response', () => { + it('should return a valid bid response', function () { const bidResponse = spec.interpretResponse({ body: serverResponse }, serverRequest)[0]; expect(bidResponse).to.contain({ requestId: bidRequest.bidId, diff --git a/test/spec/modules/realvuAnalyticsAdapter_spec.js b/test/spec/modules/realvuAnalyticsAdapter_spec.js index 7bb43002939..1d0fcf9be1a 100644 --- a/test/spec/modules/realvuAnalyticsAdapter_spec.js +++ b/test/spec/modules/realvuAnalyticsAdapter_spec.js @@ -22,19 +22,19 @@ function addDiv(id) { return dv; } -describe('RealVu Analytics Adapter.', () => { - before(() => { +describe('RealVu Analytics Adapter.', function () { + before(function () { addDiv('ad1'); addDiv('ad2'); }); - after(() => { + after(function () { let a1 = document.getElementById('ad1'); document.body.removeChild(a1); let a2 = document.getElementById('ad2'); document.body.removeChild(a2); }); - it('enableAnalytics', () => { + it('enableAnalytics', function () { const config = { options: { partnerId: '1Y', @@ -46,7 +46,7 @@ describe('RealVu Analytics Adapter.', () => { expect(p).to.equal('1Y'); }); - it('checkIn', () => { + it('checkIn', function () { const bid = { adUnitCode: 'ad1', sizes: [ @@ -71,13 +71,13 @@ describe('RealVu Analytics Adapter.', () => { expect(inview).to.equal('yes'); }); - it('isInView return "NA"', () => { + it('isInView return "NA"', function () { const adUnitCode = '1234'; let result = realvuAnalyticsAdapter.isInView(adUnitCode); expect(result).to.equal('NA'); }); - it('bid response event', () => { + it('bid response event', function () { const config = { options: { partnerId: '1Y', @@ -112,12 +112,12 @@ describe('RealVu Analytics Adapter.', () => { }); }); -describe('RealVu Boost.', () => { - before(() => { +describe('RealVu Boost.', function () { + before(function () { addDiv('ad1'); addDiv('ad2'); }); - after(() => { + after(function () { let a1 = document.getElementById('ad1'); document.body.removeChild(a1); let a2 = document.getElementById('ad2'); @@ -126,25 +126,25 @@ describe('RealVu Boost.', () => { const boost = window.top1.realvu_aa; - it('brd', () => { + it('brd', function () { let a1 = document.getElementById('ad1'); let p = boost.brd(a1, 'Left'); expect(typeof p).to.not.equal('undefined'); }); - it('addUnitById', () => { + it('addUnitById', function () { let a1 = document.getElementById('ad1'); let p = boost.addUnitById('1Y', 'ad1'); expect(typeof p).to.not.equal('undefined'); }); - it('questA', () => { + it('questA', function () { const dv = document.getElementById('ad1'); let q = boost.questA(dv); expect(q).to.not.equal(null); }); - it('render', () => { + it('render', function () { let dv = document.getElementById('ad1'); // dv.style.width = '728px'; // dv.style.height = '90px'; @@ -155,7 +155,7 @@ describe('RealVu Boost.', () => { expect(q).to.not.equal(null); }); - it('readPos', () => { + it('readPos', function () { const a = boost.ads[boost.len - 1]; let r = boost.readPos(a); expect(r).to.equal(true); diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index dd7ce4c379d..2f06e7f8288 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -61,7 +61,7 @@ describe('rhythmone adapter tests', function () { assert.equal(mangoRequest.length, 1); }); - it('should send GDPR Consent data to RhythmOne tag', () => { + it('should send GDPR Consent data to RhythmOne tag', function () { let _consentString = 'testConsentString'; var request = z.buildRequests( [ diff --git a/test/spec/modules/rockyouBidAdapter_spec.js b/test/spec/modules/rockyouBidAdapter_spec.js index f929b50d581..65d87566c26 100644 --- a/test/spec/modules/rockyouBidAdapter_spec.js +++ b/test/spec/modules/rockyouBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec, internals } from 'modules/rockyouBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('RockYouAdapter', () => { +describe('RockYouAdapter', function () { const adapter = newBidder(spec); - describe('bid validator', () => { - it('rejects a bid that is missing the placementId', () => { + describe('bid validator', function () { + it('rejects a bid that is missing the placementId', function () { let testBid = {}; expect(spec.isBidRequestValid(testBid)).to.be.false; }); - it('accepts a bid with all the expected parameters', () => { + it('accepts a bid with all the expected parameters', function () { let testBid = { params: { placementId: 'f39ba81609' @@ -22,7 +22,7 @@ describe('RockYouAdapter', () => { }); }); - describe('request builder', () => { + describe('request builder', function () { // Taken from the docs, so used as much as is valid const sampleBidRequest = { 'bidder': 'tests', @@ -43,7 +43,7 @@ describe('RockYouAdapter', () => { } }; - it('successfully generates a URL', () => { + it('successfully generates a URL', function () { const placementId = 'ZZZPLACEMENTZZZ'; let bidRequests = [ @@ -65,7 +65,7 @@ describe('RockYouAdapter', () => { expect(result.url).to.include('/servlet/rotator/' + placementId + '/0/vo?z=') }); - it('uses the bidId id as the openRtb request ID', () => { + it('uses the bidId id as the openRtb request ID', function () { const bidId = '51ef8751f9aead'; let bidRequests = [ @@ -84,7 +84,7 @@ describe('RockYouAdapter', () => { expect(payload.id).to.equal(bidId); }); - it('generates the device payload as expected', () => { + it('generates the device payload as expected', function () { let bidRequests = [ sampleBidRequest ]; @@ -103,7 +103,7 @@ describe('RockYouAdapter', () => { expect(userData).to.not.be.null; }); - it('generates multiple requests with single imp bodies', () => { + it('generates multiple requests with single imp bodies', function () { const SECOND_PLACEMENT_ID = 'YYYPLACEMENTIDYYY'; let firstBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); let secondBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); @@ -146,7 +146,7 @@ describe('RockYouAdapter', () => { expect(secondRequest.url.indexOf(SECOND_PLACEMENT_ID)).to.be.gt(0); }); - it('generates a banner request as expected', () => { + it('generates a banner request as expected', function () { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); @@ -172,7 +172,7 @@ describe('RockYouAdapter', () => { expect(bannerData.h).to.equal(50); }); - it('generates a banner request using a singular adSize instead of an array', () => { + it('generates a banner request using a singular adSize instead of an array', function () { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.sizes = [320, 50]; @@ -200,7 +200,7 @@ describe('RockYouAdapter', () => { expect(bannerData.h).to.equal(50); }); - it('fails gracefully on an invalid size', () => { + it('fails gracefully on an invalid size', function () { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.sizes = ['x', 'w']; @@ -229,7 +229,7 @@ describe('RockYouAdapter', () => { expect(bannerData.h).to.equal(null); }); - it('generates a video request as expected', () => { + it('generates a video request as expected', function () { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); @@ -259,7 +259,7 @@ describe('RockYouAdapter', () => { expect(videoData.h).to.equal(56); }); - it('propagates the mediaTypes object in the built request', () => { + it('propagates the mediaTypes object in the built request', function () { let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.mediaTypes = { video: {} }; @@ -278,8 +278,8 @@ describe('RockYouAdapter', () => { }); }); - describe('response interpreter', () => { - it('returns an empty array when no bids present', () => { + describe('response interpreter', function () { + it('returns an empty array when no bids present', function () { // an empty JSON body indicates no ad was found let result = spec.interpretResponse({ body: '' }, {}) @@ -287,13 +287,13 @@ describe('RockYouAdapter', () => { expect(result).to.eql([]); }); - it('gracefully fails when a non-JSON body is present', () => { + it('gracefully fails when a non-JSON body is present', function () { let result = spec.interpretResponse({ body: 'THIS IS NOT ' }, {}) expect(result).to.eql([]); }); - it('returns a valid bid response on sucessful banner request', () => { + it('returns a valid bid response on sucessful banner request', function () { let incomingRequestId = 'XXtestingXX'; let responsePrice = 3.14 @@ -365,7 +365,7 @@ describe('RockYouAdapter', () => { expect(processedBid.currency).to.equal(responseCurrency); }); - it('returns an valid bid response on sucessful video request', () => { + it('returns an valid bid response on sucessful video request', function () { let incomingRequestId = 'XXtesting-275XX'; let responsePrice = 6 @@ -438,7 +438,7 @@ describe('RockYouAdapter', () => { expect(processedBid.vastXml).to.equal(responseCreative); }); - it('generates event callbacks as expected', () => { + it('generates event callbacks as expected', function () { let tally = {}; let renderer = { handleVideoEvent: (eventObject) => { @@ -466,7 +466,7 @@ describe('RockYouAdapter', () => { expect(tally['ended']).to.equal(2); }); - it('generates a renderer that will hide on complete', () => { + it('generates a renderer that will hide on complete', function () { let elementName = 'test_element_id'; let selector = `#${elementName}`; diff --git a/test/spec/modules/roxotAnalyticsAdapter_spec.js b/test/spec/modules/roxotAnalyticsAdapter_spec.js index 9a80d2d0597..cd48cb7f37d 100644 --- a/test/spec/modules/roxotAnalyticsAdapter_spec.js +++ b/test/spec/modules/roxotAnalyticsAdapter_spec.js @@ -161,20 +161,20 @@ describe('Roxot Prebid Analytic', function () { let bidderDone = bidRequested; let bidWon = bidAdjustmentWithBid; - before(() => { + before(function () { xhr = sinon.useFakeXMLHttpRequest(); xhr.onCreate = request => requests.push(request); }); - after(() => { + after(function () { xhr.restore(); }); describe('correct build and send events', function () { - beforeEach(() => { + beforeEach(function () { requests = []; sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { roxotAnalytic.disableAnalytics(); events.getEvents.restore(); }); @@ -249,11 +249,11 @@ describe('Roxot Prebid Analytic', function () { }); describe('support ad unit filter', function () { - beforeEach(() => { + beforeEach(function () { requests = []; sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { roxotAnalytic.disableAnalytics(); events.getEvents.restore(); }); @@ -297,12 +297,12 @@ describe('Roxot Prebid Analytic', function () { }); describe('should correct parse config', function () { - beforeEach(() => { + beforeEach(function () { requests = []; sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { roxotAnalytic.disableAnalytics(); events.getEvents.restore(); }); @@ -427,8 +427,8 @@ describe('Roxot Prebid Analytic', function () { }); }); - describe('build utm tag data', () => { - beforeEach(() => { + describe('build utm tag data', function () { + beforeEach(function () { localStorage.setItem('roxot_analytics_utm_source', 'utm_source'); localStorage.setItem('roxot_analytics_utm_medium', 'utm_medium'); localStorage.setItem('roxot_analytics_utm_campaign', ''); @@ -436,7 +436,7 @@ describe('Roxot Prebid Analytic', function () { localStorage.setItem('roxot_analytics_utm_content', ''); localStorage.setItem('roxot_analytics_utm_ttl', Date.now()); }); - afterEach(() => { + afterEach(function () { localStorage.removeItem('roxot_analytics_utm_source'); localStorage.removeItem('roxot_analytics_utm_medium'); localStorage.removeItem('roxot_analytics_utm_campaign'); @@ -444,7 +444,7 @@ describe('Roxot Prebid Analytic', function () { localStorage.removeItem('roxot_analytics_utm_content'); localStorage.removeItem('roxot_analytics_utm_ttl'); }); - it('should build utm data from local storage', () => { + it('should build utm data from local storage', function () { let utmTagData = roxotAnalytic.buildUtmTagData(); expect(utmTagData.utm_source).to.equal('utm_source'); expect(utmTagData.utm_medium).to.equal('utm_medium'); diff --git a/test/spec/modules/rtbdemandBidAdapter_spec.js b/test/spec/modules/rtbdemandBidAdapter_spec.js index 20d3e410aee..25178c21d88 100644 --- a/test/spec/modules/rtbdemandBidAdapter_spec.js +++ b/test/spec/modules/rtbdemandBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/rtbdemandBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('rtbdemandAdapter', () => { +describe('rtbdemandAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'rtbdemand', 'params': { @@ -26,11 +26,11 @@ describe('rtbdemandAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -39,7 +39,7 @@ describe('rtbdemandAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -49,7 +49,7 @@ describe('rtbdemandAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidderRequest = { bidderCode: 'rtbdemand', auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', @@ -89,7 +89,7 @@ describe('rtbdemandAdapter', () => { timeout: 5000 }; - it('should add source and verison to the tag', () => { + it('should add source and verison to the tag', function () { const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); const payload = request.data; expect(payload.from).to.exist; @@ -106,14 +106,14 @@ describe('rtbdemandAdapter', () => { expect(payload.tmax).to.exist; }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(request.url).to.equal('//bidding.rtbdemand.com/hb'); expect(request.method).to.equal('GET'); }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'id': '543210', 'seatbid': [ { @@ -128,7 +128,7 @@ describe('rtbdemandAdapter', () => { } ] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { requestId: 'bidId-123456-1', @@ -147,7 +147,7 @@ describe('rtbdemandAdapter', () => { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'id': '543210', 'seatbid': [ ] @@ -158,10 +158,10 @@ describe('rtbdemandAdapter', () => { }); }); - describe('user sync', () => { + describe('user sync', function () { const syncUrl = '//bidding.rtbdemand.com/delivery/matches.php?type=iframe'; - it('should register the sync iframe', () => { + it('should register the sync iframe', function () { expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({iframeEnabled: false})).to.be.undefined; const options = spec.getUserSyncs({iframeEnabled: true}); diff --git a/test/spec/modules/rtbdemandadkBidAdapter_spec.js b/test/spec/modules/rtbdemandadkBidAdapter_spec.js index 8e49c2b85da..c1fbd35d6c9 100644 --- a/test/spec/modules/rtbdemandadkBidAdapter_spec.js +++ b/test/spec/modules/rtbdemandadkBidAdapter_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/rtbdemandadkBidAdapter'; import * as utils from 'src/utils'; -describe('rtbdemandadk adapter', () => { +describe('rtbdemandadk adapter', function () { const bid1_zone1 = { bidder: 'rtbdemandadk', bidId: 'Bid_01', @@ -107,29 +107,29 @@ describe('rtbdemandadk adapter', () => { } }; - describe('input parameters validation', () => { - it('empty request shouldn\'t generate exception', () => { + describe('input parameters validation', function () { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid({ bidderCode: 'rtbdemandadk' })).to.be.equal(false); }); - it('request without zone shouldn\'t issue a request', () => { + it('request without zone shouldn\'t issue a request', function () { expect(spec.isBidRequestValid(bid_without_zone)).to.be.equal(false); }); - it('request without host shouldn\'t issue a request', () => { + it('request without host shouldn\'t issue a request', function () { expect(spec.isBidRequestValid(bid_without_host)).to.be.equal(false); }); - it('empty request shouldn\'t generate exception', () => { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid(bid_with_wrong_zoneId)).to.be.equal(false); }); }); - describe('banner request building', () => { + describe('banner request building', function () { let bidRequest; - before(() => { + before(function () { let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => ({ protocol: 'https:', hostname: 'example.com', @@ -144,33 +144,33 @@ describe('rtbdemandadk adapter', () => { dntmock.restore(); }); - it('should be a first-price auction', () => { + it('should be a first-price auction', function () { expect(bidRequest).to.have.property('at', 1); }); - it('should have banner object', () => { + it('should have banner object', function () { expect(bidRequest.imp[0]).to.have.property('banner'); }); - it('should have w/h', () => { + it('should have w/h', function () { expect(bidRequest.imp[0].banner).to.have.property('format'); expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); }); - it('should respect secure connection', () => { + it('should respect secure connection', function () { expect(bidRequest.imp[0]).to.have.property('secure', 1); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); - it('should create proper site block', () => { + it('should create proper site block', function () { expect(bidRequest.site).to.have.property('domain', 'example.com'); expect(bidRequest.site).to.have.property('page', 'https://example.com/index.html'); }); - it('should fill device with caller macro', () => { + it('should fill device with caller macro', function () { expect(bidRequest).to.have.property('device'); expect(bidRequest.device).to.have.property('ip', 'caller'); expect(bidRequest.device).to.have.property('ua', 'caller'); @@ -178,37 +178,37 @@ describe('rtbdemandadk adapter', () => { }); }); - describe('video request building', () => { + describe('video request building', function () { let bidRequest; - before(() => { + before(function () { let request = spec.buildRequests([bid_video])[0]; bidRequest = JSON.parse(request.data.r); }); - it('should have video object', () => { + it('should have video object', function () { expect(bidRequest.imp[0]).to.have.property('video'); }); - it('should have h/w', () => { + it('should have h/w', function () { expect(bidRequest.imp[0].video).to.have.property('w', 640); expect(bidRequest.imp[0].video).to.have.property('h', 480); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); }); - describe('requests routing', () => { - it('should issue a request for each host', () => { + describe('requests routing', function () { + it('should issue a request for each host', function () { let pbRequests = spec.buildRequests([bid1_zone1, bid3_host2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string(`//${bid1_zone1.params.host}/`); expect(pbRequests[1].url).to.have.string(`//${bid3_host2.params.host}/`); }); - it('should issue a request for each zone', () => { + it('should issue a request for each zone', function () { let pbRequests = spec.buildRequests([bid1_zone1, bid2_zone2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].data.zone).to.be.equal(bid1_zone1.params.zoneId); @@ -216,8 +216,8 @@ describe('rtbdemandadk adapter', () => { }); }); - describe('responses processing', () => { - it('should return fully-initialized banner bid-response', () => { + describe('responses processing', function () { + it('should return fully-initialized banner bid-response', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; expect(resp).to.have.property('requestId', 'Bid_01'); @@ -232,7 +232,7 @@ describe('rtbdemandadk adapter', () => { expect(resp.ad).to.have.string(''); }); - it('should return fully-initialized video bid-response', () => { + it('should return fully-initialized video bid-response', function () { let request = spec.buildRequests([bid_video])[0]; let resp = spec.interpretResponse({body: videoBidResponse}, request)[0]; expect(resp).to.have.property('requestId', 'Bid_Video'); @@ -243,20 +243,20 @@ describe('rtbdemandadk adapter', () => { expect(resp.height).to.equal(480); }); - it('should add nurl as pixel for banner response', () => { + it('should add nurl as pixel for banner response', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; let expectedNurl = bidResponse1.seatbid[0].bid[0].nurl + '&px=1'; expect(resp.ad).to.have.string(expectedNurl); }); - it('should handle bidresponse with user-sync only', () => { + it('should handle bidresponse with user-sync only', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: usersyncOnlyResponse}, request); expect(resp).to.have.length(0); }); - it('should perform usersync', () => { + it('should perform usersync', function () { let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: bidResponse1}]); expect(syncs).to.have.length(0); syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: bidResponse1}]); diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index 70f21d2c868..b1d20ebc203 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -17,16 +17,16 @@ function buildEndpointUrl(region) { * endof Helpers */ -describe('RTBHouseAdapter', () => { +describe('RTBHouseAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'rtbhouse', 'params': { @@ -40,11 +40,11 @@ describe('RTBHouseAdapter', () => { 'auctionId': '1d1a030790a475' }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -54,7 +54,7 @@ describe('RTBHouseAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'rtbhouse', @@ -71,12 +71,12 @@ describe('RTBHouseAdapter', () => { } ]; - it('should build test param into the request', () => { + it('should build test param into the request', function () { let builtTestRequest = spec.buildRequests(bidRequests).data; expect(JSON.parse(builtTestRequest).test).to.equal(1); }); - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest); @@ -84,7 +84,7 @@ describe('RTBHouseAdapter', () => { expect(request.method).to.equal('POST'); }); - it('should not populate GDPR if for non-EEA users', () => { + it('should not populate GDPR if for non-EEA users', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest); @@ -93,7 +93,7 @@ describe('RTBHouseAdapter', () => { expect(data).to.not.have.property('user'); }); - it('should populate GDPR and consent string if available for EEA users', () => { + it('should populate GDPR and consent string if available for EEA users', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true, consentString: consentStr}}); @@ -102,7 +102,7 @@ describe('RTBHouseAdapter', () => { expect(data.user.ext.consent).to.equal('BOJ8RZsOJ8RZsABAB8AAAAAZ-A'); }); - it('should populate GDPR and empty consent string if available for EEA users without consent string but with consent', () => { + it('should populate GDPR and empty consent string if available for EEA users without consent string but with consent', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true}}); @@ -112,7 +112,7 @@ describe('RTBHouseAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = [{ 'id': 'bidder_imp_identifier', 'impid': '552b8922e28f27', @@ -125,7 +125,7 @@ describe('RTBHouseAdapter', () => { 'h': 250 }]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { 'requestId': '552b8922e28f27', @@ -145,7 +145,7 @@ describe('RTBHouseAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = ''; let bidderRequest; let result = spec.interpretResponse({ body: response }, {bidderRequest}); diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 3af82a1fb62..fa64513730a 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -409,14 +409,14 @@ function performStandardAuction() { events.emit(BID_WON, MOCK.BID_WON[1]); } -describe('rubicon analytics adapter', () => { +describe('rubicon analytics adapter', function () { let sandbox; let xhr; let requests; let oldScreen; let clock; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); xhr = sandbox.useFakeXMLHttpRequest(); @@ -437,12 +437,12 @@ describe('rubicon analytics adapter', () => { }) }); - afterEach(() => { + afterEach(function () { sandbox.restore(); config.resetConfig(); }); - it('should require accountId', () => { + it('should require accountId', function () { sandbox.stub(utils, 'logError'); rubiconAnalyticsAdapter.enableAnalytics({ @@ -454,7 +454,7 @@ describe('rubicon analytics adapter', () => { expect(utils.logError.called).to.equal(true); }); - it('should require endpoint', () => { + it('should require endpoint', function () { sandbox.stub(utils, 'logError'); rubiconAnalyticsAdapter.enableAnalytics({ @@ -466,18 +466,18 @@ describe('rubicon analytics adapter', () => { expect(utils.logError.called).to.equal(true); }); - describe('sampling', () => { - beforeEach(() => { + describe('sampling', function () { + beforeEach(function () { sandbox.stub(Math, 'random').returns(0.08); sandbox.stub(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { rubiconAnalyticsAdapter.disableAnalytics(); }); - describe('with options.samplingFactor', () => { - it('should sample', () => { + describe('with options.samplingFactor', function () { + it('should sample', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -491,7 +491,7 @@ describe('rubicon analytics adapter', () => { expect(requests.length).to.equal(1); }); - it('should unsample', () => { + it('should unsample', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -505,7 +505,7 @@ describe('rubicon analytics adapter', () => { expect(requests.length).to.equal(0); }); - it('should throw errors for invalid samplingFactor', () => { + it('should throw errors for invalid samplingFactor', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -520,8 +520,8 @@ describe('rubicon analytics adapter', () => { expect(utils.logError.called).to.equal(true); }); }); - describe('with options.sampling', () => { - it('should sample', () => { + describe('with options.sampling', function () { + it('should sample', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -535,7 +535,7 @@ describe('rubicon analytics adapter', () => { expect(requests.length).to.equal(1); }); - it('should unsample', () => { + it('should unsample', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -549,7 +549,7 @@ describe('rubicon analytics adapter', () => { expect(requests.length).to.equal(0); }); - it('should throw errors for invalid samplingFactor', () => { + it('should throw errors for invalid samplingFactor', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -566,8 +566,8 @@ describe('rubicon analytics adapter', () => { }); }); - describe('when handling events', () => { - beforeEach(() => { + describe('when handling events', function () { + beforeEach(function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -576,11 +576,11 @@ describe('rubicon analytics adapter', () => { }); }); - afterEach(() => { + afterEach(function () { rubiconAnalyticsAdapter.disableAnalytics(); }); - it('should build a batched message from prebid events', () => { + it('should build a batched message from prebid events', function () { performStandardAuction(); expect(requests.length).to.equal(1); @@ -594,7 +594,7 @@ describe('rubicon analytics adapter', () => { expect(message).to.deep.equal(ANALYTICS_MESSAGE); }); - it('should send batched message without BID_WON if necessary and further BID_WON events individually', () => { + it('should send batched message without BID_WON if necessary and further BID_WON events individually', function () { events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); @@ -623,7 +623,7 @@ describe('rubicon analytics adapter', () => { expect(message.bidsWon[0]).to.deep.equal(ANALYTICS_MESSAGE.bidsWon[1]); }); - it('should properly mark bids as timed out', () => { + it('should properly mark bids as timed out', function () { events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); events.emit(BID_TIMEOUT, MOCK.BID_TIMEOUT); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index c02a4c9f86c..3afb424c824 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -12,7 +12,7 @@ var CONSTANTS = require('src/constants.json'); const INTEGRATION = `pbjs_lite_v$prebid.version$`; // $prebid.version$ will be substituted in by gulp in built prebid -describe('the rubicon adapter', () => { +describe('the rubicon adapter', function () { let sandbox, bidderRequest, sizeMap; @@ -257,7 +257,7 @@ describe('the rubicon adapter', () => { }; } - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); bidderRequest = { @@ -327,17 +327,17 @@ describe('the rubicon adapter', () => { }); }); - afterEach(() => { + afterEach(function () { sandbox.restore(); }); - describe('MAS mapping / ordering', () => { - it('should sort values without any MAS priority sizes in regular ascending order', () => { + describe('MAS mapping / ordering', function () { + it('should sort values without any MAS priority sizes in regular ascending order', function () { let ordering = masSizeOrdering([126, 43, 65, 16]); expect(ordering).to.deep.equal([16, 43, 65, 126]); }); - it('should sort MAS priority sizes in the proper order w/ rest ascending', () => { + it('should sort MAS priority sizes in the proper order w/ rest ascending', function () { let ordering = masSizeOrdering([43, 9, 65, 15, 16, 126]); expect(ordering).to.deep.equal([15, 9, 16, 43, 65, 126]); @@ -349,10 +349,10 @@ describe('the rubicon adapter', () => { }); }); - describe('buildRequests implementation', () => { - describe('for requests', () => { - describe('to fastlane', () => { - it('should make a well-formed request objects', () => { + describe('buildRequests implementation', function () { + describe('for requests', function () { + describe('to fastlane', function () { + it('should make a well-formed request objects', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -394,7 +394,7 @@ describe('the rubicon adapter', () => { }); }); - it('ad engine query params should be ordered correctly', () => { + it('ad engine query params should be ordered correctly', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); @@ -405,7 +405,7 @@ describe('the rubicon adapter', () => { }); }); - it('should make a well-formed request object without latLong', () => { + it('should make a well-formed request object without latLong', function () { let expectedQuery = { 'account_id': '14062', 'site_id': '70608', @@ -466,7 +466,7 @@ describe('the rubicon adapter', () => { }); }); - it('page_url should use params.referrer, config.getConfig("pageUrl"), utils.getTopWindowUrl() in that order', () => { + it('page_url should use params.referrer, config.getConfig("pageUrl"), utils.getTopWindowUrl() in that order', function () { sandbox.stub(utils, 'getTopWindowUrl').callsFake(() => 'http://www.prebid.org'); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); @@ -491,7 +491,7 @@ describe('the rubicon adapter', () => { expect(parseQuery(request.data).rf).to.equal('https://www.rubiconproject.com'); }); - it('should use rubicon sizes if present (including non-mappable sizes)', () => { + it('should use rubicon sizes if present (including non-mappable sizes)', function () { var sizesBidderRequest = clone(bidderRequest); sizesBidderRequest.bids[0].params.sizes = [55, 57, 59, 801]; @@ -502,7 +502,7 @@ describe('the rubicon adapter', () => { expect(data['alt_size_ids']).to.equal('57,59,801'); }); - it('should not validate bid request if no valid sizes', () => { + it('should not validate bid request if no valid sizes', function () { var sizesBidderRequest = clone(bidderRequest); sizesBidderRequest.bids[0].sizes = [[621, 250], [300, 251]]; @@ -511,7 +511,7 @@ describe('the rubicon adapter', () => { expect(result).to.equal(false); }); - it('should not validate bid request if no account id is present', () => { + it('should not validate bid request if no account id is present', function () { var noAccountBidderRequest = clone(bidderRequest); delete noAccountBidderRequest.bids[0].params.accountId; @@ -520,7 +520,7 @@ describe('the rubicon adapter', () => { expect(result).to.equal(false); }); - it('should allow a floor override', () => { + it('should allow a floor override', function () { var floorBidderRequest = clone(bidderRequest); floorBidderRequest.bids[0].params.floor = 2; @@ -530,7 +530,7 @@ describe('the rubicon adapter', () => { expect(data['rp_floor']).to.equal('2'); }); - it('should send digitrust params', () => { + it('should send digitrust params', function () { window.DigiTrust = { getUser: function () { } @@ -564,7 +564,7 @@ describe('the rubicon adapter', () => { delete window.DigiTrust; }); - it('should not send digitrust params when DigiTrust not loaded', () => { + it('should not send digitrust params when DigiTrust not loaded', function () { let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -576,7 +576,7 @@ describe('the rubicon adapter', () => { }); }); - it('should not send digitrust params due to optout', () => { + it('should not send digitrust params due to optout', function () { window.DigiTrust = { getUser: function () { } @@ -605,7 +605,7 @@ describe('the rubicon adapter', () => { delete window.DigiTrust; }); - it('should not send digitrust params due to failure', () => { + it('should not send digitrust params due to failure', function () { window.DigiTrust = { getUser: function () { } @@ -634,19 +634,19 @@ describe('the rubicon adapter', () => { delete window.DigiTrust; }); - describe('digiTrustId config', () => { + describe('digiTrustId config', function () { var origGetConfig; - beforeEach(() => { + beforeEach(function () { window.DigiTrust = { getUser: sandbox.spy() }; }); - afterEach(() => { + afterEach(function () { delete window.DigiTrust; }); - it('should send digiTrustId config params', () => { + it('should send digiTrustId config params', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { @@ -679,7 +679,7 @@ describe('the rubicon adapter', () => { expect(window.DigiTrust.getUser.notCalled).to.equal(true); }); - it('should not send digiTrustId config params due to optout', () => { + it('should not send digiTrustId config params due to optout', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { @@ -708,7 +708,7 @@ describe('the rubicon adapter', () => { expect(window.DigiTrust.getUser.notCalled).to.equal(true); }); - it('should not send digiTrustId config params due to failure', () => { + it('should not send digiTrustId config params due to failure', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { @@ -737,7 +737,7 @@ describe('the rubicon adapter', () => { expect(window.DigiTrust.getUser.notCalled).to.equal(true); }); - it('should not send digiTrustId config params if they do not exist', () => { + it('should not send digiTrustId config params if they do not exist', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { var config = {}; return config[key]; @@ -758,8 +758,8 @@ describe('the rubicon adapter', () => { }); }); - describe('GDPR consent config', () => { - it('should send "gdpr" and "gdpr_consent", when gdprConsent defines consentString and gdprApplies', () => { + describe('GDPR consent config', function () { + it('should send "gdpr" and "gdpr_consent", when gdprConsent defines consentString and gdprApplies', function () { createGdprBidderRequest(true); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -768,7 +768,7 @@ describe('the rubicon adapter', () => { expect(data['gdpr_consent']).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); - it('should send only "gdpr_consent", when gdprConsent defines only consentString', () => { + it('should send only "gdpr_consent", when gdprConsent defines only consentString', function () { createGdprBidderRequest(); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -777,7 +777,7 @@ describe('the rubicon adapter', () => { expect(data['gdpr']).to.equal(undefined); }); - it('should not send GDPR params if gdprConsent is not defined', () => { + it('should not send GDPR params if gdprConsent is not defined', function () { let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -785,7 +785,7 @@ describe('the rubicon adapter', () => { expect(data['gdpr_consent']).to.equal(undefined); }); - it('should set "gdpr" value as 1 or 0, using "gdprApplies" value of either true/false', () => { + it('should set "gdpr" value as 1 or 0, using "gdprApplies" value of either true/false', function () { createGdprBidderRequest(true); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -798,8 +798,8 @@ describe('the rubicon adapter', () => { }); }); - describe('singleRequest config', () => { - it('should group all bid requests with the same site id', () => { + describe('singleRequest config', function () { + it('should group all bid requests with the same site id', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); sandbox.stub(config, 'getConfig').callsFake((key) => { @@ -914,7 +914,7 @@ describe('the rubicon adapter', () => { }); }); - it('should not send more than 10 bids in a request', () => { + it('should not send more than 10 bids in a request', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { const config = { 'rubicon.singleRequest': true @@ -945,7 +945,7 @@ describe('the rubicon adapter', () => { expect(data.zone_id.split(';')).to.have.lengthOf(10); }); - it('should not group bid requests if singleRequest does not equal true', () => { + it('should not group bid requests if singleRequest does not equal true', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { const config = { 'rubicon.singleRequest': false @@ -968,7 +968,7 @@ describe('the rubicon adapter', () => { expect(serverRequests).that.is.an('array').of.length(4); }); - it('should not group video bid requests', () => { + it('should not group video bid requests', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { const config = { 'rubicon.singleRequest': true @@ -1009,8 +1009,8 @@ describe('the rubicon adapter', () => { }); }); - describe('for video requests', () => { - it('should make a well-formed video request with legacy mediaType config', () => { + describe('for video requests', function () { + it('should make a well-formed video request with legacy mediaType config', function () { createLegacyVideoBidderRequest(); sandbox.stub(Date, 'now').callsFake(() => @@ -1074,7 +1074,7 @@ describe('the rubicon adapter', () => { expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); }); - it('should make a well-formed video request', () => { + it('should make a well-formed video request', function () { createVideoBidderRequest(); sandbox.stub(Date, 'now').callsFake(() => @@ -1138,7 +1138,7 @@ describe('the rubicon adapter', () => { expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); }); - it('should send request with proper ad position', () => { + it('should send request with proper ad position', function () { createVideoBidderRequest(); var positionBidderRequest = clone(bidderRequest); positionBidderRequest.bids[0].params.position = 'atf'; @@ -1182,7 +1182,7 @@ describe('the rubicon adapter', () => { expect(slot.position).to.equal('unknown'); }); - it('should allow a floor price override', () => { + it('should allow a floor price override', function () { createVideoBidderRequest(); sandbox.stub(Date, 'now').callsFake(() => @@ -1202,7 +1202,7 @@ describe('the rubicon adapter', () => { expect(floor).to.equal(3.25); }); - it('should validate bid request with invalid video if a mediaTypes banner property is defined', () => { + it('should validate bid request with invalid video if a mediaTypes banner property is defined', function () { const bidRequest = { mediaTypes: { video: { @@ -1226,7 +1226,7 @@ describe('the rubicon adapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should not validate bid request when a invalid video object and no banner object is passed in', () => { + it('should not validate bid request when a invalid video object and no banner object is passed in', function () { createVideoBidderRequestNoVideo(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -1251,7 +1251,7 @@ describe('the rubicon adapter', () => { expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); }); - it('should not validate bid request when an invalid video object is passed in with legacy config mediaType', () => { + it('should not validate bid request when an invalid video object is passed in with legacy config mediaType', function () { createLegacyVideoBidderRequestNoVideo(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -1273,7 +1273,7 @@ describe('the rubicon adapter', () => { expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); }); - it('bid request is valid when video context is outstream', () => { + it('bid request is valid when video context is outstream', function () { createVideoBidderRequestOutstream(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -1286,7 +1286,7 @@ describe('the rubicon adapter', () => { expect(request.data.slots[0].size_id).to.equal(203); }); - it('should get size from bid.sizes too', () => { + it('should get size from bid.sizes too', function () { createVideoBidderRequestNoPlayer(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -1300,7 +1300,7 @@ describe('the rubicon adapter', () => { expect(request.data.slots[0].height).to.equal(250); }); - it('should get size from bid.sizes too with legacy config mediaType', () => { + it('should get size from bid.sizes too with legacy config mediaType', function () { createLegacyVideoBidderRequestNoPlayer(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -1315,8 +1315,8 @@ describe('the rubicon adapter', () => { }); }); - describe('combineSlotUrlParams', () => { - it('should combine an array of slot url params', () => { + describe('combineSlotUrlParams', function () { + it('should combine an array of slot url params', function () { expect(spec.combineSlotUrlParams([])).to.deep.equal({}); expect(spec.combineSlotUrlParams([{p1: 'foo', p2: 'test', p3: ''}])).to.deep.equal({p1: 'foo', p2: 'test', p3: ''}); @@ -1341,8 +1341,8 @@ describe('the rubicon adapter', () => { }); }); - describe('createSlotParams', () => { - it('should return a valid slot params object', () => { + describe('createSlotParams', function () { + it('should return a valid slot params object', function () { let expectedQuery = { 'account_id': '14062', 'site_id': '70608', @@ -1380,14 +1380,14 @@ describe('the rubicon adapter', () => { }); }); - describe('hasVideoMediaType', () => { - it('should return true if mediaType is video and size_id is set', () => { + describe('hasVideoMediaType', function () { + it('should return true if mediaType is video and size_id is set', function () { createVideoBidderRequest(); const legacyVideoTypeBidRequest = hasVideoMediaType(bidderRequest.bids[0]); expect(legacyVideoTypeBidRequest).is.equal(true); }); - it('should return false if mediaType is video and size_id is not defined', () => { + it('should return false if mediaType is video and size_id is not defined', function () { expect(spec.isBidRequestValid({ bid: 99, mediaType: 'video', @@ -1397,17 +1397,17 @@ describe('the rubicon adapter', () => { })).is.equal(false); }); - it('should return false if bidRequest.mediaType is not equal to video', () => { + it('should return false if bidRequest.mediaType is not equal to video', function () { expect(hasVideoMediaType({ mediaType: 'banner' })).is.equal(false); }); - it('should return false if bidRequest.mediaType is not defined', () => { + it('should return false if bidRequest.mediaType is not defined', function () { expect(hasVideoMediaType({})).is.equal(false); }); - it('should return true if bidRequest.mediaTypes.video.context is instream and size_id is defined', () => { + it('should return true if bidRequest.mediaTypes.video.context is instream and size_id is defined', function () { expect(hasVideoMediaType({ mediaTypes: { video: { @@ -1422,7 +1422,7 @@ describe('the rubicon adapter', () => { })).is.equal(true); }); - it('should return false if bidRequest.mediaTypes.video.context is instream but size_id is not defined', () => { + it('should return false if bidRequest.mediaTypes.video.context is instream but size_id is not defined', function () { expect(spec.isBidRequestValid({ mediaTypes: { video: { @@ -1437,9 +1437,9 @@ describe('the rubicon adapter', () => { }); }); - describe('interpretResponse', () => { - describe('for fastlane', () => { - it('should handle a success response and sort by cpm', () => { + describe('interpretResponse', function () { + describe('for fastlane', function () { + it('should handle a success response and sort by cpm', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1534,7 +1534,7 @@ describe('the rubicon adapter', () => { expect(bids[1].rubiconTargeting.rpfl_14062).to.equal('15_tier_all_test'); }); - it('should be fine with a CPM of 0', () => { + it('should be fine with a CPM of 0', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1561,7 +1561,7 @@ describe('the rubicon adapter', () => { expect(bids[0].cpm).to.be.equal(0); }); - it('should handle an error with no ads returned', () => { + it('should handle an error with no ads returned', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1583,7 +1583,7 @@ describe('the rubicon adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle an error', () => { + it('should handle an error', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1607,7 +1607,7 @@ describe('the rubicon adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle an error because of malformed json response', () => { + it('should handle an error because of malformed json response', function () { let response = '{test{'; let bids = spec.interpretResponse({body: response}, { @@ -1617,7 +1617,7 @@ describe('the rubicon adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle a bidRequest argument of type Array', () => { + it('should handle a bidRequest argument of type Array', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1644,8 +1644,8 @@ describe('the rubicon adapter', () => { expect(bids[0].cpm).to.be.equal(0); }); - describe('singleRequest enabled', () => { - it('handles bidRequest of type Array and returns associated adUnits', () => { + describe('singleRequest enabled', function () { + it('handles bidRequest of type Array and returns associated adUnits', function () { const overrideMap = []; overrideMap[0] = { impression_id: '1' }; @@ -1700,7 +1700,7 @@ describe('the rubicon adapter', () => { }); }); - it('handles incorrect adUnits length by returning all bids with matching ads', () => { + it('handles incorrect adUnits length by returning all bids with matching ads', function () { const overrideMap = []; overrideMap[0] = { impression_id: '1' }; @@ -1730,7 +1730,7 @@ describe('the rubicon adapter', () => { expect(bids).to.be.a('array').with.lengthOf(6); }); - it('skips adUnits with error status and returns all bids with ok status', () => { + it('skips adUnits with error status and returns all bids with ok status', function () { const stubAds = []; // Create overrides to break associations between bids and ads // Each override should cause one less bid to be returned by interpretResponse @@ -1795,12 +1795,12 @@ describe('the rubicon adapter', () => { }); }); - describe('for video', () => { - beforeEach(() => { + describe('for video', function () { + beforeEach(function () { createVideoBidderRequest(); }); - it('should register a successful bid', () => { + it('should register a successful bid', function () { let response = { 'status': 'ok', 'ads': { @@ -1849,14 +1849,14 @@ describe('the rubicon adapter', () => { }); }); - describe('user sync', () => { + describe('user sync', function () { const emilyUrl = 'https://eus.rubiconproject.com/usync.html'; - beforeEach(() => { + beforeEach(function () { resetUserSync(); }); - it('should register the Emily iframe', () => { + it('should register the Emily iframe', function () { let syncs = spec.getUserSyncs({ iframeEnabled: true }); @@ -1864,7 +1864,7 @@ describe('the rubicon adapter', () => { expect(syncs).to.deep.equal({type: 'iframe', url: emilyUrl}); }); - it('should not register the Emily iframe more than once', () => { + it('should not register the Emily iframe more than once', function () { let syncs = spec.getUserSyncs({ iframeEnabled: true }); @@ -1875,7 +1875,7 @@ describe('the rubicon adapter', () => { expect(syncs).to.equal(undefined); }); - it('should pass gdpr params if consent is true', () => { + it('should pass gdpr params if consent is true', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { gdprApplies: true, consentString: 'foo' })).to.deep.equal({ @@ -1883,7 +1883,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass gdpr params if consent is false', () => { + it('should pass gdpr params if consent is false', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { gdprApplies: false, consentString: 'foo' })).to.deep.equal({ @@ -1891,7 +1891,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass gdpr param gdpr_consent only when gdprApplies is undefined', () => { + it('should pass gdpr param gdpr_consent only when gdprApplies is undefined', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { consentString: 'foo' })).to.deep.equal({ @@ -1899,13 +1899,13 @@ describe('the rubicon adapter', () => { }); }); - it('should pass no params if gdpr consentString is not defined', () => { + it('should pass no params if gdpr consentString is not defined', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, {})).to.deep.equal({ type: 'iframe', url: `${emilyUrl}` }); }); - it('should pass no params if gdpr consentString is a number', () => { + it('should pass no params if gdpr consentString is a number', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { consentString: 0 })).to.deep.equal({ @@ -1913,7 +1913,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass no params if gdpr consentString is null', () => { + it('should pass no params if gdpr consentString is null', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { consentString: null })).to.deep.equal({ @@ -1921,7 +1921,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass no params if gdpr consentString is a object', () => { + it('should pass no params if gdpr consentString is a object', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { consentString: {} })).to.deep.equal({ @@ -1929,7 +1929,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass no params if gdpr is not defined', () => { + it('should pass no params if gdpr is not defined', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, undefined)).to.deep.equal({ type: 'iframe', url: `${emilyUrl}` }); diff --git a/test/spec/modules/rxrtbBidAdapter_spec.js b/test/spec/modules/rxrtbBidAdapter_spec.js index 0785c6f144b..b56ef0544b2 100644 --- a/test/spec/modules/rxrtbBidAdapter_spec.js +++ b/test/spec/modules/rxrtbBidAdapter_spec.js @@ -1,9 +1,9 @@ import {expect} from 'chai'; import {spec} from 'modules/rxrtbBidAdapter'; -describe('rxrtb adapater', () => { - describe('Test validate req', () => { - it('should accept minimum valid bid', () => { +describe('rxrtb adapater', function () { + describe('Test validate req', function () { + it('should accept minimum valid bid', function () { let bid = { bidder: 'rxrtb', params: { @@ -17,7 +17,7 @@ describe('rxrtb adapater', () => { expect(isValid).to.equal(true); }); - it('should reject missing id', () => { + it('should reject missing id', function () { let bid = { bidder: 'rxrtb', params: { @@ -30,7 +30,7 @@ describe('rxrtb adapater', () => { expect(isValid).to.equal(false); }); - it('should reject id not Integer', () => { + it('should reject id not Integer', function () { let bid = { bidder: 'rxrtb', params: { @@ -44,7 +44,7 @@ describe('rxrtb adapater', () => { expect(isValid).to.equal(false); }); - it('should reject missing source', () => { + it('should reject missing source', function () { let bid = { bidder: 'rxrtb', params: { @@ -58,8 +58,8 @@ describe('rxrtb adapater', () => { }); }); - describe('Test build request', () => { - it('minimum request', () => { + describe('Test build request', function () { + it('minimum request', function () { let bid = { bidder: 'rxrtb', sizes: [[728, 90]], @@ -88,8 +88,8 @@ describe('rxrtb adapater', () => { }); }); - describe('Test interpret response', () => { - it('General banner response', () => { + describe('Test interpret response', function () { + it('General banner response', function () { let resp = spec.interpretResponse({ body: { id: 'abcd', diff --git a/test/spec/modules/s2sTesting_spec.js b/test/spec/modules/s2sTesting_spec.js index 33552011aa1..b2b35a585c7 100644 --- a/test/spec/modules/s2sTesting_spec.js +++ b/test/spec/modules/s2sTesting_spec.js @@ -12,15 +12,15 @@ describe('s2sTesting', function () { let mathRandomStub; let randomNumber = 0; - beforeEach(() => { + beforeEach(function () { mathRandomStub = sinon.stub(Math, 'random').callsFake(() => { return randomNumber; }); }); - afterEach(() => { + afterEach(function () { mathRandomStub.restore(); }); - describe('getSource', () => { + describe('getSource', function () { // helper function to set random number and get the source function getExpectedSource(randNumber, sourceWeights, sources) { // set random number for testing @@ -28,18 +28,18 @@ describe('s2sTesting', function () { return getSource(sourceWeights, sources); } - it('returns undefined if no sources', () => { + it('returns undefined if no sources', function () { expect(getExpectedSource(0, {})).to.be.undefined; expect(getExpectedSource(0.5, {})).to.be.undefined; expect(getExpectedSource(0.9999, {})).to.be.undefined; }); - it('returns undefined if no weights', () => { + it('returns undefined if no weights', function () { expect(getExpectedSource(0, {server: 0, client: 0})).to.be.undefined; expect(getExpectedSource(0.5, {client: 0})).to.be.undefined; }); - it('gets the expected source from 3 sources', () => { + it('gets the expected source from 3 sources', function () { var sources = ['server', 'client', 'both']; expect(getExpectedSource(0, {server: 1, client: 1, both: 2}, sources)).to.equal('server'); expect(getExpectedSource(0.2499999, {server: 1, client: 1, both: 2}, sources)).to.equal('server'); @@ -49,7 +49,7 @@ describe('s2sTesting', function () { expect(getExpectedSource(0.99999, {server: 1, client: 1, both: 2}, sources)).to.equal('both'); }); - it('gets the expected source from 2 sources', () => { + it('gets the expected source from 2 sources', function () { expect(getExpectedSource(0, {server: 2, client: 3})).to.equal('server'); expect(getExpectedSource(0.39999, {server: 2, client: 3})).to.equal('server'); expect(getExpectedSource(0.4, {server: 2, client: 3})).to.equal('client'); @@ -61,19 +61,19 @@ describe('s2sTesting', function () { expect(getExpectedSource(0.9, {server: 2, client: 3}, sources)).to.equal('client'); }); - it('gets the expected source from 1 source', () => { + it('gets the expected source from 1 source', function () { expect(getExpectedSource(0, {client: 2})).to.equal('client'); expect(getExpectedSource(0.5, {client: 2})).to.equal('client'); expect(getExpectedSource(0.99999, {client: 2})).to.equal('client'); }); - it('ignores an invalid source', () => { + it('ignores an invalid source', function () { expect(getExpectedSource(0, {client: 2, cache: 2})).to.equal('client'); expect(getExpectedSource(0.3333, {server: 1, cache: 1, client: 2})).to.equal('server'); expect(getExpectedSource(0.34, {server: 1, cache: 1, client: 2})).to.equal('client'); }); - it('ignores order of sources', () => { + it('ignores order of sources', function () { var sources = ['server', 'client', 'both']; expect(getExpectedSource(0, {client: 1, server: 1, both: 2}, sources)).to.equal('server'); expect(getExpectedSource(0.2499999, {both: 2, client: 1, server: 1}, sources)).to.equal('server'); @@ -82,21 +82,21 @@ describe('s2sTesting', function () { expect(getExpectedSource(0.5, {both: 2, server: 1, client: 1}, sources)).to.equal('both'); }); - it('accepts an array of sources', () => { + it('accepts an array of sources', function () { expect(getExpectedSource(0.3333, {second: 2, first: 1}, ['first', 'second'])).to.equal('first'); expect(getExpectedSource(0.34, {second: 2, first: 1}, ['first', 'second'])).to.equal('second'); expect(getExpectedSource(0.9999, {second: 2, first: 1}, ['first', 'second'])).to.equal('second'); }); }); - describe('getSourceBidderMap', () => { - describe('setting source through s2sConfig', () => { - beforeEach(() => { + describe('getSourceBidderMap', function () { + describe('setting source through s2sConfig', function () { + beforeEach(function () { // set random number for testing randomNumber = 0.7; }); - it('does not work if testing is "false"', () => { + it('does not work if testing is "false"', function () { config.setConfig({s2sConfig: { bidders: ['rubicon'], testing: false, @@ -108,7 +108,7 @@ describe('s2sTesting', function () { }); }); - it('sets one client bidder', () => { + it('sets one client bidder', function () { config.setConfig({s2sConfig: { bidders: ['rubicon'], testing: true, @@ -120,7 +120,7 @@ describe('s2sTesting', function () { }); }); - it('sets one server bidder', () => { + it('sets one server bidder', function () { config.setConfig({s2sConfig: { bidders: ['rubicon'], testing: true, @@ -132,7 +132,7 @@ describe('s2sTesting', function () { }); }); - it('defaults to server', () => { + it('defaults to server', function () { config.setConfig({s2sConfig: { bidders: ['rubicon'], testing: true @@ -143,7 +143,7 @@ describe('s2sTesting', function () { }); }); - it('sets two bidders', () => { + it('sets two bidders', function () { config.setConfig({s2sConfig: { bidders: ['rubicon', 'appnexus'], testing: true, @@ -157,15 +157,15 @@ describe('s2sTesting', function () { }); }); - describe('setting source through adUnits', () => { - beforeEach(() => { + describe('setting source through adUnits', function () { + beforeEach(function () { // reset s2sconfig bid sources config.setConfig({s2sConfig: {testing: true}}); // set random number for testing randomNumber = 0.7; }); - it('sets one bidder source from one adUnit', () => { + it('sets one bidder source from one adUnit', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', bidSource: {server: 4, client: 1}} @@ -193,7 +193,7 @@ describe('s2sTesting', function () { expect(adUnits[0].bids[0].finalSource).to.equal('client'); }); - it('defaults to client if no bidSource', () => { + it('defaults to client if no bidSource', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', bidSource: {}} @@ -208,7 +208,7 @@ describe('s2sTesting', function () { expect(adUnits[0].bids[0].finalSource).to.equal('client'); }); - it('sets multiple bidders sources from one adUnit', () => { + it('sets multiple bidders sources from one adUnit', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', bidSource: {server: 2, client: 1}}, @@ -225,7 +225,7 @@ describe('s2sTesting', function () { expect(adUnits[0].bids[1].finalSource).to.equal('server'); }); - it('sets multiple bidders sources from multiple adUnits', () => { + it('sets multiple bidders sources from multiple adUnits', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', bidSource: {server: 2, client: 1}}, @@ -251,7 +251,7 @@ describe('s2sTesting', function () { expect(adUnits[1].bids[1].finalSource).to.equal('client'); }); - it('should reuse calculated sources', () => { + it('should reuse calculated sources', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', calcSource: 'client', bidSource: {server: 4, client: 1}}, @@ -275,15 +275,15 @@ describe('s2sTesting', function () { }); }); - describe('setting source through s2sconfig and adUnits', () => { - beforeEach(() => { + describe('setting source through s2sconfig and adUnits', function () { + beforeEach(function () { // reset s2sconfig bid sources config.setConfig({s2sConfig: {testing: true}}); // set random number for testing randomNumber = 0.7; }); - it('should get sources from both', () => { + it('should get sources from both', function () { // set rubicon: server and appnexus: client var adUnits = [ {bids: [ diff --git a/test/spec/modules/saraBidAdapter_spec.js b/test/spec/modules/saraBidAdapter_spec.js index 1b5d75170ae..6614ec65265 100644 --- a/test/spec/modules/saraBidAdapter_spec.js +++ b/test/spec/modules/saraBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('Sara Adapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'sara', 'params': { @@ -24,11 +24,11 @@ describe('Sara Adapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('Sara Adapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { function parseRequest(url) { const res = {}; url.split('&').forEach((it) => { @@ -83,7 +83,7 @@ describe('Sara Adapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -92,7 +92,7 @@ describe('Sara Adapter', function () { expect(payload).to.have.property('auids', '5'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -101,7 +101,7 @@ describe('Sara Adapter', function () { expect(payload).to.have.property('auids', '5,6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -112,7 +112,7 @@ describe('Sara Adapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -124,7 +124,7 @@ describe('Sara Adapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -135,7 +135,7 @@ describe('Sara Adapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'sara', @@ -169,7 +169,7 @@ describe('Sara Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'sara', @@ -249,7 +249,7 @@ describe('Sara Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'sara', diff --git a/test/spec/modules/sekindoUMBidAdapter_spec.js b/test/spec/modules/sekindoUMBidAdapter_spec.js index 8f275d7fc05..b699015bb3e 100644 --- a/test/spec/modules/sekindoUMBidAdapter_spec.js +++ b/test/spec/modules/sekindoUMBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { spec } from 'modules/sekindoUMBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('sekindoUMAdapter', () => { +describe('sekindoUMAdapter', function () { const adapter = newBidder(spec); const bannerParams = { @@ -29,34 +29,34 @@ describe('sekindoUMAdapter', () => { 'mediaType': 'banner' }; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { bidRequests.mediaType = 'banner'; bidRequests.params = bannerParams; expect(spec.isBidRequestValid(bidRequests)).to.equal(true); }); - it('should return false when required video params are missing', () => { + it('should return false when required video params are missing', function () { bidRequests.mediaType = 'video'; bidRequests.params = bannerParams; expect(spec.isBidRequestValid(bidRequests)).to.equal(false); }); - it('should return true when required Video params found', () => { + it('should return true when required Video params found', function () { bidRequests.mediaType = 'video'; bidRequests.params = videoParams; expect(spec.isBidRequestValid(bidRequests)).to.equal(true); }); }); - describe('buildRequests', () => { - it('banner data should be a query string and method = GET', () => { + describe('buildRequests', function () { + it('banner data should be a query string and method = GET', function () { bidRequests.mediaType = 'banner'; bidRequests.params = bannerParams; const request = spec.buildRequests([bidRequests]); @@ -64,7 +64,7 @@ describe('sekindoUMAdapter', () => { expect(request[0].method).to.equal('GET'); }); - it('with gdprConsent, banner data should be a query string and method = GET', () => { + it('with gdprConsent, banner data should be a query string and method = GET', function () { bidRequests.mediaType = 'banner'; bidRequests.params = bannerParams; const request = spec.buildRequests([bidRequests], {'gdprConsent': {'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', 'vendorData': {}, 'gdprApplies': true}}); @@ -72,7 +72,7 @@ describe('sekindoUMAdapter', () => { expect(request[0].method).to.equal('GET'); }); - it('video data should be a query string and method = GET', () => { + it('video data should be a query string and method = GET', function () { bidRequests.mediaType = 'video'; bidRequests.params = videoParams; const request = spec.buildRequests([bidRequests]); @@ -81,8 +81,8 @@ describe('sekindoUMAdapter', () => { }); }); - describe('interpretResponse', () => { - it('banner should get correct bid response', () => { + describe('interpretResponse', function () { + it('banner should get correct bid response', function () { let response = { 'headers': function(header) { return 'dummy header'; @@ -110,7 +110,7 @@ describe('sekindoUMAdapter', () => { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('vastXml video should get correct bid response', () => { + it('vastXml video should get correct bid response', function () { let response = { 'headers': function(header) { return 'dummy header'; @@ -138,7 +138,7 @@ describe('sekindoUMAdapter', () => { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('vastUrl video should get correct bid response', () => { + it('vastUrl video should get correct bid response', function () { let response = { 'headers': function(header) { return 'dummy header'; diff --git a/test/spec/modules/serverbidBidAdapter_spec.js b/test/spec/modules/serverbidBidAdapter_spec.js index d3dc64ae6df..aa40ee31ce5 100644 --- a/test/spec/modules/serverbidBidAdapter_spec.js +++ b/test/spec/modules/serverbidBidAdapter_spec.js @@ -100,11 +100,11 @@ const RESPONSE = { } }; -describe('Serverbid BidAdapter', () => { +describe('Serverbid BidAdapter', function () { let bidRequests; let adapter = spec; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'serverbid', @@ -122,8 +122,8 @@ describe('Serverbid BidAdapter', () => { ]; }); - describe('bid request validation', () => { - it('should accept valid bid requests', () => { + describe('bid request validation', function () { + it('should accept valid bid requests', function () { let bid = { bidder: 'serverbid', params: { @@ -134,7 +134,7 @@ describe('Serverbid BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should accept valid bid requests with extra fields', () => { + it('should accept valid bid requests with extra fields', function () { let bid = { bidder: 'serverbid', params: { @@ -146,7 +146,7 @@ describe('Serverbid BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should reject bid requests without siteId', () => { + it('should reject bid requests without siteId', function () { let bid = { bidder: 'serverbid', params: { @@ -156,7 +156,7 @@ describe('Serverbid BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should reject bid requests without networkId', () => { + it('should reject bid requests without networkId', function () { let bid = { bidder: 'serverbid', params: { @@ -167,45 +167,45 @@ describe('Serverbid BidAdapter', () => { }); }); - describe('buildRequests validation', () => { - it('creates request data', () => { + describe('buildRequests validation', function () { + it('creates request data', function () { let request = spec.buildRequests(bidRequests); expect(request).to.exist.and.to.be.a('object'); }); - it('request to serverbid should contain a url', () => { + it('request to serverbid should contain a url', function () { let request = spec.buildRequests(bidRequests); expect(request.url).to.have.string('serverbid.com'); }); - it('requires valid bids to make request', () => { + it('requires valid bids to make request', function () { let request = spec.buildRequests([]); expect(request.bidRequest).to.be.empty; }); - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { let request = spec.buildRequests(bidRequests); expect(request.method).to.have.string('POST'); }); }); - describe('interpretResponse validation', () => { - it('response should have valid bidderCode', () => { + describe('interpretResponse validation', function () { + it('response should have valid bidderCode', function () { let bidRequest = spec.buildRequests(REQUEST.bidRequest); let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('serverbid'); }); - it('response should include objects for all bids', () => { + it('response should include objects for all bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); expect(bids.length).to.equal(2); }); - it('registers bids', () => { + it('registers bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); bids.forEach(b => { expect(b).to.have.property('cpm'); @@ -223,29 +223,29 @@ describe('Serverbid BidAdapter', () => { }); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {'decisions': null}}) let bids = spec.interpretResponse(EMPTY_RESP, REQUEST); expect(bids).to.be.empty; }); - it('handles no server response', () => { + it('handles no server response', function () { let bids = spec.interpretResponse(null, REQUEST); expect(bids).to.be.empty; }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let syncOptions = {'iframeEnabled': true}; - it('handles empty sync options', () => { + it('handles empty sync options', function () { let opts = spec.getUserSyncs({}); expect(opts).to.be.empty; }); - it('should return a sync url if iframe syncs are enabled', () => { + it('should return a sync url if iframe syncs are enabled', function () { let opts = spec.getUserSyncs(syncOptions); expect(opts.length).to.equal(1); diff --git a/test/spec/modules/serverbidServerBidAdapter_spec.js b/test/spec/modules/serverbidServerBidAdapter_spec.js index 29d35b921d6..7c428647f62 100644 --- a/test/spec/modules/serverbidServerBidAdapter_spec.js +++ b/test/spec/modules/serverbidServerBidAdapter_spec.js @@ -184,51 +184,55 @@ const REQUEST_TWO_UNITS = { ] }; -describe('ServerBid S2S Adapter', () => { +describe('ServerBid S2S Adapter', function () { let adapter, addBidResponse = sinon.spy(), done = sinon.spy(); - beforeEach(() => adapter = new Adapter()); + beforeEach(function () { + adapter = new Adapter() + }); - afterEach(() => { + afterEach(function () { addBidResponse.resetHistory(); done.resetHistory(); }); - describe('request function', () => { + describe('request function', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); }); - afterEach(() => xhr.restore()); + afterEach(function () { + xhr.restore(); + }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('response handler', () => { + describe('response handler', function () { let server; - beforeEach(() => { + beforeEach(function () { server = sinon.fakeServer.create(); sinon.stub(utils, 'getBidRequest').returns({ bidId: '123' }); }); - afterEach(() => { + afterEach(function () { server.restore(); utils.getBidRequest.restore(); }); - it('registers bids', () => { + it('registers bids', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig(CONFIG_ARG); @@ -242,7 +246,7 @@ describe('ServerBid S2S Adapter', () => { expect(response).to.have.property('adId', '123'); }); - it('registers no-bid response when ad unit not set', () => { + it('registers no-bid response when ad unit not set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); config.setConfig(CONFIG_ARG); @@ -260,7 +264,7 @@ describe('ServerBid S2S Adapter', () => { expect(bid_request_passed).to.have.property('adId', '123'); }); - it('registers no-bid response when ad unit is set', () => { + it('registers no-bid response when ad unit is set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); config.setConfig(CONFIG_ARG); @@ -275,7 +279,7 @@ describe('ServerBid S2S Adapter', () => { expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); }); - it('registers no-bid response when there are less bids than requests', () => { + it('registers no-bid response when there are less bids than requests', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig(CONFIG_ARG); diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index 85fc6daf758..6a4ab016fdc 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -104,15 +104,15 @@ const b64EncodeUnicode = (str) => { })); } -describe('sharethrough adapter spec', () => { - describe('.code', () => { - it('should return a bidder code of sharethrough', () => { +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', () => { - it('should return false if req has no pkey', () => { + describe('.isBidRequestValid', function () { + it('should return false if req has no pkey', function () { const invalidBidRequest = { bidder: 'sharethrough', params: { @@ -122,7 +122,7 @@ describe('sharethrough adapter spec', () => { expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); }); - it('should return false if req has wrong bidder code', () => { + it('should return false if req has wrong bidder code', function () { const invalidBidRequest = { bidder: 'notSharethrough', params: { @@ -132,14 +132,14 @@ describe('sharethrough adapter spec', () => { expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); }); - it('should return true if req is correct', () => { + it('should return true if req is correct', function () { expect(spec.isBidRequestValid(bidderRequest[0])).to.eq(true); expect(spec.isBidRequestValid(bidderRequest[1])).to.eq(true); }) }); - describe('.buildRequests', () => { - it('should return an array of requests', () => { + describe('.buildRequests', function () { + it('should return an array of requests', function () { const bidRequests = spec.buildRequests(bidderRequest); expect(bidRequests[0].url).to.eq( @@ -149,7 +149,7 @@ describe('sharethrough adapter spec', () => { expect(bidRequests[0].method).to.eq('GET'); }); - it('should add consent parameters if gdprConsent is present', () => { + it('should add consent parameters if gdprConsent is present', function () { const gdprConsent = { consentString: 'consent_string123', gdprApplies: true }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; @@ -157,7 +157,7 @@ describe('sharethrough adapter spec', () => { expect(bidRequest.data.consent_string).to.eq('consent_string123'); }); - it('should handle gdprConsent is present but values are undefined case', () => { + it('should handle gdprConsent is present but values are undefined case', function () { const gdprConsent = { consent_string: undefined, gdprApplies: undefined }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; @@ -165,8 +165,8 @@ describe('sharethrough adapter spec', () => { }); }); - describe('.interpretResponse', () => { - it('returns a correctly parsed out response', () => { + describe('.interpretResponse', function () { + it('returns a correctly parsed out response', function () { expect(spec.interpretResponse(bidderResponse, prebidRequests[0])[0]).to.include( { width: 0, @@ -180,7 +180,7 @@ describe('sharethrough adapter spec', () => { }); }); - it('returns a correctly parsed out response with largest size when strData.stayInIframe is true', () => { + it('returns a correctly parsed out response with largest size when strData.stayInIframe is true', function () { expect(spec.interpretResponse(bidderResponse, prebidRequests[1])[0]).to.include( { width: 300, @@ -194,7 +194,7 @@ describe('sharethrough adapter spec', () => { }); }); - it('returns a correctly parsed out response with explicitly defined size when strData.stayInIframe is true and strData.iframeSize is provided', () => { + it('returns a correctly parsed out response with explicitly defined size when strData.stayInIframe is true and strData.iframeSize is provided', function () { expect(spec.interpretResponse(bidderResponse, prebidRequests[2])[0]).to.include( { width: 500, @@ -208,22 +208,22 @@ describe('sharethrough adapter spec', () => { }); }); - it('returns a blank array if there are no creatives', () => { + 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; }); - it('returns a blank array if body object is empty', () => { + 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; }); - it('returns a blank array if body is null', () => { + 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('correctly generates ad markup', () => { + it('correctly generates ad markup', function () { const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[0])[0].ad; let resp = null; @@ -240,7 +240,7 @@ describe('sharethrough adapter spec', () => { /window.top.document.getElementsByTagName\('body'\)\[0\].appendChild\(sfp_js\);/) }); - it('correctly generates ad markup for staying in iframe', () => { + it('correctly generates ad markup for staying in iframe', function () { const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[1])[0].ad; let resp = null; @@ -254,11 +254,11 @@ describe('sharethrough adapter spec', () => { }); }); - describe('.getUserSyncs', () => { + describe('.getUserSyncs', function () { const cookieSyncs = ['cookieUrl1', 'cookieUrl2', 'cookieUrl3']; const serverResponses = [{ body: { cookieSyncUrls: cookieSyncs } }]; - it('returns an array of correctly formatted user syncs', () => { + it('returns an array of correctly formatted user syncs', function () { const syncArray = spec.getUserSyncs({ pixelEnabled: true }, serverResponses); expect(syncArray).to.deep.equal([ { type: 'image', url: 'cookieUrl1' }, @@ -267,17 +267,17 @@ describe('sharethrough adapter spec', () => { ); }); - it('returns an empty array if the body is null', () => { + it('returns an empty array if the body is null', function () { const syncArray = spec.getUserSyncs({ pixelEnabled: true }, [{ body: null }]); expect(syncArray).to.be.an('array').that.is.empty; }); - it('returns an empty array if the body.cookieSyncUrls is missing', () => { + it('returns an empty array if the body.cookieSyncUrls is missing', function () { const syncArray = spec.getUserSyncs({ pixelEnabled: true }, [{ body: { creatives: ['creative'] } }]); expect(syncArray).to.be.an('array').that.is.empty; }); - it('returns an empty array if pixels are not enabled', () => { + it('returns an empty array if pixels are not enabled', function () { const syncArray = spec.getUserSyncs({ pixelEnabled: false }, serverResponses); expect(syncArray).to.be.an('array').that.is.empty; }); diff --git a/test/spec/modules/sigmoidAnalyticsAdapter_spec.js b/test/spec/modules/sigmoidAnalyticsAdapter_spec.js index 115c296d489..0552e02383a 100644 --- a/test/spec/modules/sigmoidAnalyticsAdapter_spec.js +++ b/test/spec/modules/sigmoidAnalyticsAdapter_spec.js @@ -6,21 +6,21 @@ let constants = require('src/constants.json'); describe('sigmoid Prebid Analytic', function () { let xhr; - before(() => { + before(function () { xhr = sinon.useFakeXMLHttpRequest(); }) - after(() => { + after(function () { sigmoidAnalytic.disableAnalytics(); xhr.restore(); }); describe('enableAnalytics', function () { - beforeEach(() => { + beforeEach(function () { sinon.spy(sigmoidAnalytic, 'track'); sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { sigmoidAnalytic.track.restore(); events.getEvents.restore(); }); @@ -46,8 +46,8 @@ describe('sigmoid Prebid Analytic', function () { sinon.assert.callCount(sigmoidAnalytic.track, 5); }); }); - describe('build utm tag data', () => { - beforeEach(() => { + describe('build utm tag data', function () { + beforeEach(function () { localStorage.setItem('sigmoid_analytics_utm_source', 'utm_source'); localStorage.setItem('sigmoid_analytics_utm_medium', 'utm_medium'); localStorage.setItem('sigmoid_analytics_utm_campaign', ''); @@ -55,7 +55,7 @@ describe('sigmoid Prebid Analytic', function () { localStorage.setItem('sigmoid_analytics_utm_content', ''); localStorage.setItem('sigmoid_analytics_utm_timeout', Date.now()); }); - it('should build utm data from local storage', () => { + it('should build utm data from local storage', function () { let utmTagData = sigmoidAnalytic.buildUtmTagData(); expect(utmTagData.utm_source).to.equal('utm_source'); expect(utmTagData.utm_medium).to.equal('utm_medium'); diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index e6364de94a9..91fb4e3e6a7 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -14,7 +14,7 @@ import * as utils from 'src/utils'; import { requestBidsHook } from 'modules/consentManagement'; // Default params with optional ones -describe('Smart bid adapter tests', () => { +describe('Smart bid adapter tests', function () { var DEFAULT_PARAMS = [{ adUnitCode: 'sas_42', bidId: 'abcd1234', @@ -71,7 +71,7 @@ describe('Smart bid adapter tests', () => { } }; - it('Verify build request', () => { + it('Verify build request', function () { config.setConfig({ 'currency': { 'adServerCurrency': 'EUR' @@ -100,13 +100,13 @@ describe('Smart bid adapter tests', () => { expect(requestContent).to.have.property('ckid').and.to.equal(42); }); - describe('gdpr tests', () => { - afterEach(() => { + describe('gdpr tests', function () { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); }); - it('Verify build request with GDPR', () => { + it('Verify build request with GDPR', function () { config.setConfig({ 'currency': { 'adServerCurrency': 'EUR' @@ -129,7 +129,7 @@ describe('Smart bid adapter tests', () => { expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOKAVy4OKAVy4ABAB8AAAAAZ+A=='); }); - it('Verify build request with GDPR without gdprApplies', () => { + it('Verify build request with GDPR without gdprApplies', function () { config.setConfig({ 'currency': { 'adServerCurrency': 'EUR' @@ -152,7 +152,7 @@ describe('Smart bid adapter tests', () => { }); }); - it('Verify parse response', () => { + it('Verify parse response', function () { const request = spec.buildRequests(DEFAULT_PARAMS); const bids = spec.interpretResponse(BID_RESPONSE, request[0]); expect(bids).to.have.lengthOf(1); @@ -176,16 +176,16 @@ describe('Smart bid adapter tests', () => { }).to.not.throw(); }); - it('Verifies bidder code', () => { + it('Verifies bidder code', function () { expect(spec.code).to.equal('smartadserver'); }); - it('Verifies bidder aliases', () => { + it('Verifies bidder aliases', function () { expect(spec.aliases).to.have.lengthOf(1); expect(spec.aliases[0]).to.equal('smart'); }); - it('Verifies if bid request valid', () => { + it('Verifies if bid request valid', function () { expect(spec.isBidRequestValid(DEFAULT_PARAMS[0])).to.equal(true); expect(spec.isBidRequestValid(DEFAULT_PARAMS_WO_OPTIONAL[0])).to.equal(true); expect(spec.isBidRequestValid({})).to.equal(false); @@ -243,7 +243,7 @@ describe('Smart bid adapter tests', () => { })).to.equal(false); }); - it('Verifies user sync', () => { + it('Verifies user sync', function () { var syncs = spec.getUserSyncs({ iframeEnabled: true }, [BID_RESPONSE]); diff --git a/test/spec/modules/smartyadsBidAdapter_spec.js b/test/spec/modules/smartyadsBidAdapter_spec.js index 858e8bf37a0..e301e9733a6 100644 --- a/test/spec/modules/smartyadsBidAdapter_spec.js +++ b/test/spec/modules/smartyadsBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/smartyadsBidAdapter'; -describe('SmartyadsAdapter', () => { +describe('SmartyadsAdapter', function () { let bid = { bidId: '23fhj33i987f', bidder: 'smartyads', @@ -11,31 +11,31 @@ describe('SmartyadsAdapter', () => { } }; - describe('isBidRequestValid', () => { - it('Should return true if there are bidId, params and placementId parameters present', () => { + describe('isBidRequestValid', 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', () => { + 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', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + 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', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//ssp-nj.webtradehub.com/?c=o&m=multi'); }); - it('Returns valid data if array of bids is valid', () => { + 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'); @@ -51,14 +51,14 @@ describe('SmartyadsAdapter', () => { expect(placement.bidId).to.equal('23fhj33i987f'); expect(placement.traffic).to.equal('banner'); }); - it('Returns empty data if no valid requests are passed', () => { + 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', () => { - it('Should interpret banner response', () => { + describe('interpretResponse', function () { + it('Should interpret banner response', function () { const banner = { body: [{ mediaType: 'banner', @@ -89,7 +89,7 @@ describe('SmartyadsAdapter', () => { expect(dataItem.netRevenue).to.be.true; expect(dataItem.currency).to.equal('USD'); }); - it('Should interpret video response', () => { + it('Should interpret video response', function () { const video = { body: [{ vastUrl: 'test.com', @@ -118,7 +118,7 @@ describe('SmartyadsAdapter', () => { expect(dataItem.netRevenue).to.be.true; expect(dataItem.currency).to.equal('USD'); }); - it('Should interpret native response', () => { + it('Should interpret native response', function () { const native = { body: [{ mediaType: 'native', @@ -152,7 +152,7 @@ describe('SmartyadsAdapter', () => { expect(dataItem.netRevenue).to.be.true; expect(dataItem.currency).to.equal('USD'); }); - it('Should return an empty array if invalid banner response is passed', () => { + it('Should return an empty array if invalid banner response is passed', function () { const invBanner = { body: [{ width: 300, @@ -170,7 +170,7 @@ describe('SmartyadsAdapter', () => { 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', () => { + it('Should return an empty array if invalid video response is passed', function () { const invVideo = { body: [{ mediaType: 'video', @@ -186,7 +186,7 @@ describe('SmartyadsAdapter', () => { 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', () => { + it('Should return an empty array if invalid native response is passed', function () { const invNative = { body: [{ mediaType: 'native', @@ -203,7 +203,7 @@ describe('SmartyadsAdapter', () => { 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', () => { + it('Should return an empty array if invalid response is passed', function () { const invalid = { body: [{ ttl: 120, @@ -217,9 +217,9 @@ describe('SmartyadsAdapter', () => { expect(serverResponses).to.be.an('array').that.is.empty; }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let userSync = spec.getUserSyncs(); - it('Returns valid URL and type', () => { + 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; diff --git a/test/spec/modules/somoaudienceBidAdapter_spec.js b/test/spec/modules/somoaudienceBidAdapter_spec.js index 79ece7ffcf6..bdd2dade96f 100644 --- a/test/spec/modules/somoaudienceBidAdapter_spec.js +++ b/test/spec/modules/somoaudienceBidAdapter_spec.js @@ -2,16 +2,16 @@ import {expect} from 'chai'; import {spec} from 'modules/somoaudienceBidAdapter'; import * as utils from 'src/utils'; -describe('Somo Audience Adapter Tests', () => { - describe('isBidRequestValid', () => { - it('should return false when given an invalid bid', () => { +describe('Somo Audience Adapter Tests', function () { + describe('isBidRequestValid', function () { + it('should return false when given an invalid bid', function () { const bid = { bidder: 'somoaudience', }; const isValid = spec.isBidRequestValid(bid); expect(isValid).to.equal(false); }); - it('should return true when given a placementId bid', () => { + it('should return true when given a placementId bid', function () { const bid = { bidder: 'somoaudience', params: { @@ -23,9 +23,9 @@ describe('Somo Audience Adapter Tests', () => { }); }); - describe('buildRequests', () => { - describe('buildBannerRequests', () => { - it('should properly build a banner request with type not defined and sizes not defined', () => { + describe('buildRequests', function () { + describe('buildBannerRequests', function () { + it('should properly build a banner request with type not defined and sizes not defined', function () { const bidRequests = [{ bidder: 'somoaudience', params: { @@ -47,7 +47,7 @@ describe('Somo Audience Adapter Tests', () => { expect(ortbRequest.imp[0].banner).to.not.equal(null); }); - it('should properly build a banner request with sizes defined in 2d array', () => { + it('should properly build a banner request with sizes defined in 2d array', function () { const bidRequests = [{ bidder: 'somoaudience', sizes: [[300, 250]], @@ -69,7 +69,7 @@ describe('Somo Audience Adapter Tests', () => { expect(ortbRequest.imp[0].banner.w).to.equal(300); expect(ortbRequest.imp[0].banner.h).to.equal(250); }); - it('should properly build a banner request with sizes defined in 1d array', () => { + it('should properly build a banner request with sizes defined in 1d array', function () { const bidRequests = [{ bidder: 'somoaudience', sizes: [300, 250], @@ -96,7 +96,7 @@ describe('Somo Audience Adapter Tests', () => { expect(ortbRequest.imp[0].banner.battr).to.equal(undefined); }); - it('should populate optional banner parameters', () => { + it('should populate optional banner parameters', function () { const bidRequests = [ { bidder: 'somoaudience', @@ -125,8 +125,8 @@ describe('Somo Audience Adapter Tests', () => { }); }); - describe('buildVideoRequests', () => { - it('should properly build a video request with sizes defined', () => { + describe('buildVideoRequests', function () { + it('should properly build a video request with sizes defined', function () { const bidRequests = [{ bidder: 'somoaudience', mediaTypes: { @@ -149,7 +149,7 @@ describe('Somo Audience Adapter Tests', () => { expect(ortbRequest.imp[0].video.h).to.equal(300); }); - it('should properly build a video request with sizes defined in 2d array', () => { + it('should properly build a video request with sizes defined in 2d array', function () { const bidRequests = [{ bidder: 'somoaudience', mediaTypes: { @@ -171,7 +171,7 @@ describe('Somo Audience Adapter Tests', () => { expect(ortbRequest.imp[0].video.w).to.equal(200); expect(ortbRequest.imp[0].video.h).to.equal(300); }); - it('should properly build a video request with sizes not defined', () => { + it('should properly build a video request with sizes not defined', function () { const bidRequests = [{ bidder: 'somoaudience', mediaType: 'video', @@ -196,7 +196,7 @@ describe('Somo Audience Adapter Tests', () => { expect(ortbRequest.imp[0].video.battr).to.equal(undefined); }); - it('should populate optional video parameters', () => { + it('should populate optional video parameters', function () { const bidRequests = [ { bidder: 'somoaudience', @@ -239,8 +239,8 @@ describe('Somo Audience Adapter Tests', () => { }); }); - describe('buildSiteRequests', () => { - it('should fill in basic site parameters', () => { + describe('buildSiteRequests', function () { + it('should fill in basic site parameters', function () { const bidRequests = [{ bidder: 'somoaudience', params: { @@ -256,7 +256,7 @@ describe('Somo Audience Adapter Tests', () => { expect(ortbRequest.site.domain).to.not.be.undefined; }); - it('should fill in optional site parameters', () => { + it('should fill in optional site parameters', function () { const bidRequests = [{ bidder: 'somoaudience', params: { @@ -282,8 +282,8 @@ describe('Somo Audience Adapter Tests', () => { }) }); - describe('buildAppRequests', () => { - it('should fill in app parameters', () => { + describe('buildAppRequests', function () { + it('should fill in app parameters', function () { const bidRequests = [{ bidder: 'somoaudience', params: { @@ -315,7 +315,7 @@ describe('Somo Audience Adapter Tests', () => { }); }); - describe('buildGDPRRequests', () => { + describe('buildGDPRRequests', function () { const bidderRequest = { gdprConsent: { gdprApplies: true, @@ -323,7 +323,7 @@ describe('Somo Audience Adapter Tests', () => { }, }; - it('should properly build request with gdpr consent', () => { + it('should properly build request with gdpr consent', function () { const bidRequests = [{ bidder: 'somoaudience', params: { @@ -339,7 +339,7 @@ describe('Somo Audience Adapter Tests', () => { expect(ortbRequest.user.ext).to.not.equal(undefined); expect(ortbRequest.user.ext.consent).to.equal('test'); }); - it('should properly build request with gdpr not applies', () => { + it('should properly build request with gdpr not applies', function () { bidderRequest.gdprConsent.gdprApplies = false; const bidRequests = [{ bidder: 'somoaudience', @@ -358,8 +358,8 @@ describe('Somo Audience Adapter Tests', () => { }); }); - describe('buildExtraArgsRequests', () => { - it('should populate optional parameters', () => { + describe('buildExtraArgsRequests', function () { + it('should populate optional parameters', function () { const bidRequests = [ { bidder: 'somoaudience', @@ -385,8 +385,8 @@ describe('Somo Audience Adapter Tests', () => { }); }); - describe('interpretResponse', () => { - it('Verify banner parse response', () => { + describe('interpretResponse', function () { + it('Verify banner parse response', function () { const bidRequests = [ { bidder: 'somoaudience', @@ -414,7 +414,7 @@ describe('Somo Audience Adapter Tests', () => { expect(bid.ad).to.equal('Somo Test Ad'); }); - it('Verify video parse response', () => { + it('Verify video parse response', function () { const bidRequests = [ { bidder: 'somoaudience', @@ -447,8 +447,8 @@ describe('Somo Audience Adapter Tests', () => { }); }); - describe('user sync', () => { - it('should register the pixel sync url', () => { + describe('user sync', function () { + it('should register the pixel sync url', function () { let syncs = spec.getUserSyncs({ pixelEnabled: true }); @@ -457,7 +457,7 @@ describe('Somo Audience Adapter Tests', () => { expect(syncs[0].type).to.equal('image'); }); - it('should pass gdpr params', () => { + it('should pass gdpr params', function () { let syncs = spec.getUserSyncs({ pixelEnabled: true }, {}, { gdprApplies: false, consentString: 'test' }); @@ -467,7 +467,7 @@ describe('Somo Audience Adapter Tests', () => { expect(syncs[0].url).to.contains('gdpr=0'); }); - it('should pass gdpr applies params', () => { + it('should pass gdpr applies params', function () { let syncs = spec.getUserSyncs({ pixelEnabled: true }, {}, { gdprApplies: true, consentString: 'test' }); diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 1b0986cb8c1..349a2e80263 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -2,22 +2,22 @@ import { expect } from 'chai' import { spec, _getPlatform } from 'modules/sonobiBidAdapter' import { newBidder } from 'src/adapters/bidderFactory' -describe('SonobiBidAdapter', () => { +describe('SonobiBidAdapter', function () { const adapter = newBidder(spec) - describe('.code', () => { - it('should return a bidder code of sonobi', () => { + describe('.code', function () { + it('should return a bidder code of sonobi', function () { expect(spec.code).to.equal('sonobi') }) }) - describe('inherited functions', () => { - it('should exist and be a function', () => { + describe('inherited functions', function () { + it('should exist and be a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function') }) }) - describe('.isBidRequestValid', () => { + describe('.isBidRequestValid', function () { let bid = { 'bidder': 'sonobi', 'params': { @@ -32,11 +32,11 @@ describe('SonobiBidAdapter', () => { 'auctionId': '1d1a030790a475', } - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true) }) - it('should return true when bid.params.placement_id and bid.params.sizes are found', () => { + it('should return true when bid.params.placement_id and bid.params.sizes are found', function () { let bid = Object.assign({}, bid) delete bid.params delete bid.sizes @@ -48,7 +48,7 @@ describe('SonobiBidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true) }) - it('should return true when bid.params.placement_id and bid.sizes are found', () => { + it('should return true when bid.params.placement_id and bid.sizes are found', function () { let bid = Object.assign({}, bid) delete bid.params bid.sizes = [[300, 250], [300, 600]] @@ -59,7 +59,7 @@ describe('SonobiBidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true) }) - it('should return true when bid.params.ad_unit and bid.params.sizes are found', () => { + it('should return true when bid.params.ad_unit and bid.params.sizes are found', function () { let bid = Object.assign({}, bid) delete bid.params delete bid.sizes @@ -71,7 +71,7 @@ describe('SonobiBidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true) }) - it('should return true when bid.params.ad_unit and bid.sizes are found', () => { + it('should return true when bid.params.ad_unit and bid.sizes are found', function () { let bid = Object.assign({}, bid) delete bid.params bid.sizes = [[300, 250], [300, 600]] @@ -82,13 +82,13 @@ describe('SonobiBidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true) }) - it('should return false when no params are found', () => { + it('should return false when no params are found', function () { let bid = Object.assign({}, bid) delete bid.params expect(spec.isBidRequestValid(bid)).to.equal(false) }) - it('should return false when bid.params.placement_id and bid.params.ad_unit are not found', () => { + it('should return false when bid.params.placement_id and bid.params.ad_unit are not found', function () { let bid = Object.assign({}, bid) delete bid.params bid.params = { @@ -100,7 +100,7 @@ describe('SonobiBidAdapter', () => { }) }) - describe('.buildRequests', () => { + describe('.buildRequests', function () { let bidRequest = [{ 'bidder': 'sonobi', 'params': { @@ -138,7 +138,7 @@ describe('SonobiBidAdapter', () => { }, }; - it('should return a properly formatted request', () => { + it('should return a properly formatted request', function () { const bidRequests = spec.buildRequests(bidRequest) const bidRequestsPageViewID = spec.buildRequests(bidRequest) expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') @@ -153,7 +153,7 @@ describe('SonobiBidAdapter', () => { expect(['mobile', 'tablet', 'desktop']).to.contain(bidRequests.data.vp); }) - it('should return a properly formatted request with GDPR applies set to true', () => { + 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://apex.go.sonobi.com/trinity.json') expect(bidRequests.method).to.equal('GET') @@ -161,7 +161,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.consent_string).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==') }) - it('should return a properly formatted request with GDPR applies set to false', () => { + 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://apex.go.sonobi.com/trinity.json') @@ -169,7 +169,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.gdpr).to.equal('false') expect(bidRequests.data.consent_string).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==') }) - it('should return a properly formatted request with GDPR applies set to false with no consent_string param', () => { + it('should return a properly formatted request with GDPR applies set to false with no consent_string param', function () { let bidderRequests = { 'gdprConsent': { 'consentString': undefined, @@ -183,7 +183,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.gdpr).to.equal('false') expect(bidRequests.data).to.not.include.keys('consent_string') }) - it('should return a properly formatted request with GDPR applies set to true with no consent_string param', () => { + it('should return a properly formatted request with GDPR applies set to true with no consent_string param', function () { let bidderRequests = { 'gdprConsent': { 'consentString': undefined, @@ -197,7 +197,7 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.gdpr).to.equal('true') expect(bidRequests.data).to.not.include.keys('consent_string') }) - it('should return a properly formatted request with hfa', () => { + it('should return a properly formatted request with hfa', function () { bidRequest[0].params.hfa = 'hfakey' bidRequest[1].params.hfa = 'hfakey' const bidRequests = spec.buildRequests(bidRequest) @@ -208,13 +208,13 @@ describe('SonobiBidAdapter', () => { expect(bidRequests.data.hfa).to.equal('hfakey') }) - it('should return null if there is nothing to bid on', () => { + it('should return null if there is nothing to bid on', function () { const bidRequests = spec.buildRequests([{params: {}}]) expect(bidRequests).to.equal(null); }) }) - describe('.interpretResponse', () => { + describe('.interpretResponse', function () { const bidRequests = { 'method': 'GET', 'url': 'https://apex.go.sonobi.com/trinity.json', @@ -316,7 +316,7 @@ describe('SonobiBidAdapter', () => { } ]; - it('should map bidResponse to prebidResponse', () => { + it('should map bidResponse to prebidResponse', function () { const response = spec.interpretResponse(bidResponse, bidRequests); response.forEach(resp => { let regx = /http:\/\/localhost:9876\/.*?(?="|$)/ @@ -326,7 +326,7 @@ describe('SonobiBidAdapter', () => { }) }) - describe('.getUserSyncs', () => { + describe('.getUserSyncs', function () { let bidResponse = [{ 'body': { 'sbi_px': [{ @@ -338,35 +338,35 @@ describe('SonobiBidAdapter', () => { } }]; - it('should return one sync pixel', () => { + it('should return one sync pixel', function () { expect(spec.getUserSyncs({ pixelEnabled: true }, bidResponse)).to.deep.equal([{ type: 'image', url: 'https://pixel-test' }]); }) - it('should return an empty array when sync is enabled but there are no bidResponses', () => { + it('should return an empty array when sync is enabled but there are no bidResponses', function () { expect(spec.getUserSyncs({ pixelEnabled: true }, [])).to.have.length(0); }) - it('should return an empty array when sync is enabled but no sync pixel returned', () => { + it('should return an empty array when sync is enabled but no sync pixel returned', function () { const pixel = Object.assign({}, bidResponse); delete pixel[0].body.sbi_px; expect(spec.getUserSyncs({ pixelEnabled: true }, bidResponse)).to.have.length(0); }) - it('should return an empty array', () => { + it('should return an empty array', function () { expect(spec.getUserSyncs({ pixelEnabled: false }, bidResponse)).to.have.length(0); expect(spec.getUserSyncs({ pixelEnabled: true }, [])).to.have.length(0); }); }) - describe('_getPlatform', () => { - it('should return mobile', () => { + describe('_getPlatform', function () { + it('should return mobile', function () { expect(_getPlatform({innerWidth: 767})).to.equal('mobile') }) - it('should return tablet', () => { + it('should return tablet', function () { expect(_getPlatform({innerWidth: 800})).to.equal('tablet') }) - it('should return desktop', () => { + it('should return desktop', function () { expect(_getPlatform({innerWidth: 1000})).to.equal('desktop') }) }) diff --git a/test/spec/modules/sortableBidAdapter_spec.js b/test/spec/modules/sortableBidAdapter_spec.js index 6f1c9efba84..09f5b4f7514 100644 --- a/test/spec/modules/sortableBidAdapter_spec.js +++ b/test/spec/modules/sortableBidAdapter_spec.js @@ -9,7 +9,7 @@ const ENDPOINT = `//c.deployads.com/openrtb2/auction?src=${REPO_AND_VERSION}&hos describe('sortableBidAdapter', function() { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { function makeBid() { return { 'bidder': 'sortable', @@ -35,35 +35,35 @@ describe('sortableBidAdapter', function() { }; } - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(makeBid())).to.equal(true); }); - it('should return false when tagId not passed correctly', () => { + it('should return false when tagId not passed correctly', function () { let bid = makeBid(); delete bid.params.tagId; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when sizes not passed correctly', () => { + it('should return false when sizes not passed correctly', function () { let bid = makeBid(); delete bid.sizes; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when sizes are wrong length', () => { + it('should return false when sizes are wrong length', function () { let bid = makeBid(); bid.sizes = [[300]]; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when require params are not passed', () => { + it('should return false when require params are not passed', function () { let bid = makeBid(); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when the floorSizeMap is invalid', () => { + it('should return false when the floorSizeMap is invalid', function () { let bid = makeBid(); bid.params.floorSizeMap = { 'sixforty by foureighty': 1234 @@ -77,14 +77,14 @@ describe('sortableBidAdapter', function() { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true when the floorSizeMap is missing or empty', () => { + it('should return true when the floorSizeMap is missing or empty', function () { let bid = makeBid(); bid.params.floorSizeMap = {}; expect(spec.isBidRequestValid(bid)).to.equal(true); delete bid.params.floorSizeMap; expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when the keywords are invalid', () => { + it('should return false when the keywords are invalid', function () { let bid = makeBid(); bid.params.keywords = { 'badval': 1234 @@ -94,7 +94,7 @@ describe('sortableBidAdapter', function() { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true when the keywords are missing or empty', () => { + it('should return true when the keywords are missing or empty', function () { let bid = makeBid(); bid.params.keywords = {}; expect(spec.isBidRequestValid(bid)).to.equal(true); @@ -103,7 +103,7 @@ describe('sortableBidAdapter', function() { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [{ 'bidder': 'sortable', 'params': { @@ -130,25 +130,25 @@ describe('sortableBidAdapter', function() { const request = spec.buildRequests(bidRequests); const requestBody = JSON.parse(request.data); - it('sends bid request to our endpoint via POST', () => { + it('sends bid request to our endpoint via POST', function () { expect(request.method).to.equal('POST'); }); - it('attaches source and version to endpoint URL as query params', () => { + it('attaches source and version to endpoint URL as query params', function () { expect(request.url).to.equal(ENDPOINT); }); - it('sends screen dimensions', () => { + it('sends screen dimensions', function () { expect(requestBody.site.device.w).to.equal(screen.width); expect(requestBody.site.device.h).to.equal(screen.height); }); - it('includes the ad size in the bid request', () => { + it('includes the ad size in the bid request', function () { expect(requestBody.imp[0].banner.format[0].w).to.equal(300); expect(requestBody.imp[0].banner.format[0].h).to.equal(250); }); - it('includes the params in the bid request', () => { + it('includes the params in the bid request', function () { expect(requestBody.imp[0].ext.keywords).to.deep.equal( {'key1': 'val1', 'key2': 'val2'} @@ -158,7 +158,7 @@ describe('sortableBidAdapter', function() { expect(requestBody.imp[0].bidfloor).to.equal(0.21); }); - it('should have the floor size map set', () => { + it('should have the floor size map set', function () { expect(requestBody.imp[0].ext.floorSizeMap).to.deep.equal({ '728x90': 0.15, '300x250': 1.20 @@ -166,7 +166,7 @@ describe('sortableBidAdapter', function() { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { function makeResponse() { return { body: { @@ -208,13 +208,13 @@ describe('sortableBidAdapter', function() { 'ad': '
' }; - it('should get the correct bid response', () => { + it('should get the correct bid response', function () { let result = spec.interpretResponse(makeResponse()); expect(result.length).to.equal(1); expect(result[0]).to.deep.equal(expectedBid); }); - it('should handle a missing crid', () => { + 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; @@ -224,7 +224,7 @@ describe('sortableBidAdapter', function() { expect(result[0]).to.deep.equal(noCridResult); }); - it('should handle a missing nurl', () => { + it('should handle a missing nurl', function () { let noNurlResponse = makeResponse(); delete noNurlResponse.body.seatbid[0].bid[0].nurl; let noNurlResult = Object.assign({}, expectedBid); @@ -234,7 +234,7 @@ describe('sortableBidAdapter', function() { expect(result[0]).to.deep.equal(noNurlResult); }); - it('should handle a missing adm', () => { + it('should handle a missing adm', function () { let noAdmResponse = makeResponse(); delete noAdmResponse.body.seatbid[0].bid[0].adm; let noAdmResult = Object.assign({}, expectedBid); @@ -245,7 +245,7 @@ describe('sortableBidAdapter', function() { expect(result[0]).to.deep.equal(noAdmResult); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: { 'id': '5e5c23a5ba71e78', diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index dd3a43a3f0c..0f1c0d43396 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -8,7 +8,7 @@ const ENDPOINT = `//ap.lijit.com/rtb/bid?src=${REPO_AND_VERSION}`; describe('sovrnBidAdapter', function() { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'sovrn', 'params': { @@ -23,23 +23,23 @@ describe('sovrnBidAdapter', function() { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when tagid not passed correctly', () => { + it('should return false when tagid not passed correctly', function () { bid.params.tagid = 'ABCD'; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when require params are not passed', () => { + it('should return false when require params are not passed', function () { let bid = Object.assign({}, bid); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [{ 'bidder': 'sovrn', 'params': { @@ -56,15 +56,15 @@ describe('sovrnBidAdapter', function() { const request = spec.buildRequests(bidRequests); - it('sends bid request to our endpoint via POST', () => { + it('sends bid request to our endpoint via POST', function () { expect(request.method).to.equal('POST'); }); - it('attaches source and version to endpoint URL as query params', () => { + it('attaches source and version to endpoint URL as query params', function () { expect(request.url).to.equal(ENDPOINT) }); - it('sends \'iv\' as query param if present', () => { + it('sends \'iv\' as query param if present', function () { const ivBidRequests = [{ 'bidder': 'sovrn', 'params': { @@ -84,7 +84,7 @@ describe('sovrnBidAdapter', function() { expect(request.url).to.contain('iv=vet') }); - it('sends gdpr info if exists', () => { + it('sends gdpr info if exists', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { 'bidderCode': 'sovrn', @@ -107,7 +107,7 @@ describe('sovrnBidAdapter', function() { expect(payload.user.ext.consent).to.equal(consentString); }); - it('converts tagid to string', () => { + it('converts tagid to string', function () { const ivBidRequests = [{ 'bidder': 'sovrn', 'params': { @@ -128,9 +128,9 @@ describe('sovrnBidAdapter', function() { }) }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response; - beforeEach(() => { + beforeEach(function () { response = { body: { 'id': '37386aade21a71', @@ -150,7 +150,7 @@ describe('sovrnBidAdapter', function() { }; }); - it('should get the correct bid response', () => { + it('should get the correct bid response', function () { let expectedResponse = [{ 'requestId': '263c448586f5a1', 'cpm': 0.45882675, @@ -169,7 +169,7 @@ describe('sovrnBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('crid should default to the bid id if not on the response', () => { + it('crid should default to the bid id if not on the response', function () { delete response.body.seatbid[0].bid[0].crid; let expectedResponse = [{ 'requestId': '263c448586f5a1', @@ -189,7 +189,7 @@ describe('sovrnBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('should get correct bid response when dealId is passed', () => { + it('should get correct bid response when dealId is passed', function () { response.body.dealid = 'baking'; let expectedResponse = [{ @@ -210,7 +210,7 @@ describe('sovrnBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: { 'id': '37386aade21a71', diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js index 2483ec70e76..6b5278c20ae 100644 --- a/test/spec/modules/telariaBidAdapter_spec.js +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -34,26 +34,26 @@ const RESPONSE = { }] }; -describe('TelariaAdapter', () => { +describe('TelariaAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = REQUEST.bids[0]; - it('should return true when required params found', () => { + it('should return true when required params found', function () { let tempBid = bid; tempBid.params.adCode = 'ssp-!demo!-lufip'; tempBid.params.supplyCode = 'ssp-demo-rm6rh'; expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let tempBid = bid; delete tempBid.params; tempBid.params = { @@ -64,14 +64,14 @@ describe('TelariaAdapter', () => { expect(spec.isBidRequestValid(tempBid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let tempBid = bid; tempBid.params = {}; expect(spec.isBidRequestValid(tempBid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const stub = [{ bidder: 'tremor', sizes: [[300, 250], [300, 600]], @@ -82,16 +82,16 @@ describe('TelariaAdapter', () => { } }]; - it('exists and is a function', () => { + it('exists and is a function', function () { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); - it('requires supply code, ad code and sizes to make a request', () => { + it('requires supply code, ad code and sizes to make a request', function () { const tempRequest = spec.buildRequests(stub); expect(tempRequest.length).to.equal(1); }); - it('generates an array of requests with 4 params, method, url, bidId and vastUrl', () => { + it('generates an array of requests with 4 params, method, url, bidId and vastUrl', function () { const tempRequest = spec.buildRequests(stub); expect(tempRequest.length).to.equal(1); @@ -101,7 +101,7 @@ describe('TelariaAdapter', () => { expect(tempRequest[0].vastUrl).to.exist; }); - it('requires sizes to make a request', () => { + it('requires sizes to make a request', function () { let tempBid = stub; tempBid[0].sizes = null; const tempRequest = spec.buildRequests(tempBid); @@ -109,13 +109,13 @@ describe('TelariaAdapter', () => { expect(tempRequest.length).to.equal(0); }); - it('generates a valid request with sizes as an array of two elements', () => { + it('generates a valid request with sizes as an array of two elements', function () { let tempBid = stub; tempBid[0].sizes = [640, 480]; expect(spec.buildRequests(tempBid).length).to.equal(1); }); - it('requires ad code and supply code to make a request', () => { + it('requires ad code and supply code to make a request', function () { let tempBid = stub; tempBid[0].params.adCode = null; tempBid[0].params.supplyCode = null; @@ -126,7 +126,7 @@ describe('TelariaAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responseStub = RESPONSE; const stub = [{ bidder: 'tremor', @@ -138,7 +138,7 @@ describe('TelariaAdapter', () => { } }]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponseKeys = ['bidderCode', 'width', 'height', 'statusMessage', 'adId', 'mediaType', 'source', 'getStatusCode', 'getSize', 'requestId', 'cpm', 'creativeId', 'vastXml', 'vastUrl', 'currency', 'netRevenue', 'ttl', 'ad']; @@ -149,7 +149,7 @@ describe('TelariaAdapter', () => { expect(Object.keys(result[0])).to.have.members(expectedResponseKeys); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let tempResponse = responseStub; tempResponse.seatbid = []; @@ -160,18 +160,18 @@ describe('TelariaAdapter', () => { expect(result.length).to.equal(0); }); - it('handles invalid responses', () => { + it('handles invalid responses', function () { let result = spec.interpretResponse(null, {bbidderCode: 'telaria'}); expect(result.length).to.equal(0); }); - it('handles error responses', () => { + it('handles error responses', function () { let result = spec.interpretResponse({body: {error: 'Invalid request'}}, {bbidderCode: 'telaria'}); expect(result.length).to.equal(0); }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const responses = [{body: RESPONSE}]; responses[0].body.ext = { telaria: { @@ -182,7 +182,7 @@ describe('TelariaAdapter', () => { } }; - it('should get the correct number of sync urls', () => { + it('should get the correct number of sync urls', function () { let urls = spec.getUserSyncs({pixelEnabled: true}, responses); expect(urls.length).to.equal(2); }); diff --git a/test/spec/modules/trionBidAdapter_spec.js b/test/spec/modules/trionBidAdapter_spec.js index 559122a2772..805ae70a339 100644 --- a/test/spec/modules/trionBidAdapter_spec.js +++ b/test/spec/modules/trionBidAdapter_spec.js @@ -35,22 +35,24 @@ const TRION_BID_RESPONSE = { }; -describe('Trion adapter tests', () => { +describe('Trion adapter tests', function () { let adapter; - beforeEach(() => { + beforeEach(function () { // adapter = trionAdapter.createNew(); sinon.stub(document.body, 'appendChild'); }); - afterEach(() => document.body.appendChild.restore()); + afterEach(function () { + document.body.appendChild.restore(); + }); - describe('isBidRequestValid', () => { - it('should return true with correct params', () => { + describe('isBidRequestValid', function () { + it('should return true with correct params', function () { expect(spec.isBidRequestValid(TRION_BID)).to.equal(true); }); - it('should return false when params are missing', () => { + it('should return false when params are missing', function () { TRION_BID.params = {}; expect(spec.isBidRequestValid(TRION_BID)).to.equal(false); @@ -60,7 +62,7 @@ describe('Trion adapter tests', () => { }; }); - it('should return false when pubId is missing', () => { + it('should return false when pubId is missing', function () { TRION_BID.params = { sectionId: '2' }; @@ -72,7 +74,7 @@ describe('Trion adapter tests', () => { }; }); - it('should return false when sectionId is missing', () => { + it('should return false when sectionId is missing', function () { TRION_BID.params = { pubId: '1' }; @@ -85,20 +87,20 @@ describe('Trion adapter tests', () => { }); }); - describe('buildRequests', () => { - it('should return bids requests with empty params', () => { + describe('buildRequests', function () { + it('should return bids requests with empty params', function () { let bidRequests = spec.buildRequests([]); expect(bidRequests.length).to.equal(0); }); - it('should include the base bidrequest url', () => { + it('should include the base bidrequest url', function () { let bidRequests = spec.buildRequests(TRION_BID_REQUEST); let bidUrl = bidRequests[0].url; expect(bidUrl).to.include(BID_REQUEST_BASE_URL); }); - it('should call buildRequests with the correct required params', () => { + it('should call buildRequests with the correct required params', function () { let bidRequests = spec.buildRequests(TRION_BID_REQUEST); let bidUrlParams = bidRequests[0].data; @@ -107,7 +109,7 @@ describe('Trion adapter tests', () => { expect(bidUrlParams).to.include('sizes=300x250,300x600'); }); - it('should call buildRequests with the correct optional params', () => { + it('should call buildRequests with the correct optional params', function () { let params = TRION_BID_REQUEST[0].params; params.re = 1; let bidRequests = spec.buildRequests(TRION_BID_REQUEST); @@ -119,13 +121,13 @@ describe('Trion adapter tests', () => { }); }); - describe('interpretResponse', () => { - it('when there is no response do not bid', () => { + describe('interpretResponse', function () { + it('when there is no response do not bid', function () { let response = spec.interpretResponse(null, {bidRequest: TRION_BID}); expect(response).to.deep.equal([]); }); - it('when place bid is returned as false', () => { + it('when place bid is returned as false', function () { TRION_BID_RESPONSE.result.placeBid = false; let response = spec.interpretResponse({body: TRION_BID_RESPONSE}, {bidRequest: TRION_BID}); @@ -134,21 +136,21 @@ describe('Trion adapter tests', () => { TRION_BID_RESPONSE.result.placeBid = true; }); - it('when no cpm is in the response', () => { + it('when no cpm is in the response', function () { TRION_BID_RESPONSE.result.cpm = 0; let response = spec.interpretResponse({body: TRION_BID_RESPONSE}, {bidRequest: TRION_BID}); expect(response).to.deep.equal([]); TRION_BID_RESPONSE.result.cpm = 1; }); - it('when no ad is in the response', () => { + it('when no ad is in the response', function () { TRION_BID_RESPONSE.result.ad = null; let response = spec.interpretResponse({body: TRION_BID_RESPONSE}, {bidRequest: TRION_BID}); expect(response).to.deep.equal([]); TRION_BID_RESPONSE.result.ad = 'test'; }); - it('height and width are appropriately set', () => { + it('height and width are appropriately set', function () { let bidWidth = '1'; let bidHeight = '2'; TRION_BID_RESPONSE.result.width = bidWidth; @@ -160,7 +162,7 @@ describe('Trion adapter tests', () => { TRION_BID_RESPONSE.result.height = '250'; }); - it('cpm is properly set and transformed to cents', () => { + it('cpm is properly set and transformed to cents', function () { let bidCpm = 2; TRION_BID_RESPONSE.result.cpm = bidCpm * 100; let response = spec.interpretResponse({body: TRION_BID_RESPONSE}, {bidRequest: TRION_BID}); @@ -169,15 +171,15 @@ describe('Trion adapter tests', () => { }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const USER_SYNC_URL = 'https://in-appadvertising.com/api/userSync.html'; const BASE_KEY = '_trion_'; - beforeEach(() => { + beforeEach(function () { delete window.TR_INT_T; }); - it('trion int is included in bid url', () => { + it('trion int is included in bid url', function () { window.TR_INT_T = 'test_user_sync'; let userTag = encodeURIComponent(window.TR_INT_T); let bidRequests = spec.buildRequests(TRION_BID_REQUEST); @@ -186,7 +188,7 @@ describe('Trion adapter tests', () => { expect(bidUrlParams).to.include(userTag); }); - it('should register trion user script', () => { + it('should register trion user script', function () { let syncs = spec.getUserSyncs({iframeEnabled: true}); let url = utils.getTopWindowUrl(); let pubId = 1; @@ -195,7 +197,7 @@ describe('Trion adapter tests', () => { expect(syncs[0]).to.deep.equal({type: 'iframe', url: USER_SYNC_URL + syncString}); }); - it('should except posted messages from user sync script', () => { + it('should except posted messages from user sync script', function () { let testId = 'testId'; let message = BASE_KEY + 'userId=' + testId; setStorageData(BASE_KEY + 'int_t', null); @@ -204,7 +206,7 @@ describe('Trion adapter tests', () => { expect(newKey).to.equal(testId); }); - it('should not try to post messages not from trion', () => { + it('should not try to post messages not from trion', function () { let testId = 'testId'; let badId = 'badId'; let message = 'Not Trion: userId=' + testId; diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index ed343f1ebf9..d3013d9be22 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -5,16 +5,16 @@ import { deepClone } from 'src/utils'; const ENDPOINT = document.location.protocol + '//tlx.3lift.com/header/auction?'; -describe('triplelift adapter', () => { +describe('triplelift adapter', function () { const adapter = newBidder(tripleliftAdapterSpec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { bidder: 'triplelift', params: { @@ -28,11 +28,11 @@ describe('triplelift adapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true for valid bid request', () => { + it('should return true for valid bid request', function () { expect(tripleliftAdapterSpec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -42,7 +42,7 @@ describe('triplelift adapter', () => { expect(tripleliftAdapterSpec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -52,7 +52,7 @@ describe('triplelift adapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { bidder: 'triplelift', @@ -68,18 +68,18 @@ describe('triplelift adapter', () => { } ]; - it('exists and is an object', () => { + it('exists and is an object', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests); expect(request).to.exist.and.to.be.a('object'); }); - it('should only parse sizes that are of the proper length and format', () => { + it('should only parse sizes that are of the proper length and format', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests); expect(request.data.imp[0].banner.format).to.have.length(2); expect(request.data.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); }); - it('should be a post request and populate the payload', () => { + it('should be a post request and populate the payload', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.exist; @@ -88,7 +88,7 @@ describe('triplelift adapter', () => { expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); }); - it('should return a query string for TL call', () => { + it('should return a query string for TL call', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests); const url = request.url; expect(url).to.exist; @@ -101,7 +101,7 @@ describe('triplelift adapter', () => { }) }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { body: { bids: [ @@ -136,7 +136,7 @@ describe('triplelift adapter', () => { } }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { requestId: '3db3773286ee59', @@ -156,7 +156,7 @@ describe('triplelift adapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('should return multile responses to support SRA', () => { + it('should return multile responses to support SRA', function () { let response = { body: { bids: [ diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index 2e099772593..9f2fdca6a99 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('TrustXAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'trustx', 'params': { @@ -24,11 +24,11 @@ describe('TrustXAdapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('TrustXAdapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { function parseRequest(url) { const res = {}; url.split('&').forEach((it) => { @@ -83,7 +83,7 @@ describe('TrustXAdapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -93,7 +93,7 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('r', '22edbae2733bf6'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -103,7 +103,7 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('r', '22edbae2733bf6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -115,7 +115,7 @@ describe('TrustXAdapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -127,7 +127,7 @@ describe('TrustXAdapter', function () { delete bidRequests[1].params.priceType; }); - it('if gdprConsent is present payload must have gdpr params', () => { + it('if gdprConsent is present payload must have gdpr params', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -135,7 +135,7 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('gdpr_applies', '1'); }); - it('if gdprApplies is false gdpr_applies must be 0', () => { + it('if gdprApplies is false gdpr_applies must be 0', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -143,7 +143,7 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('gdpr_applies', '0'); }); - it('if gdprApplies is undefined gdpr_applies must be 1', () => { + it('if gdprApplies is undefined gdpr_applies must be 1', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -152,7 +152,7 @@ describe('TrustXAdapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'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': 90, 'w': 728}], 'seat': '1'}, @@ -163,7 +163,7 @@ describe('TrustXAdapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'trustx', @@ -198,7 +198,7 @@ describe('TrustXAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'trustx', @@ -281,7 +281,7 @@ describe('TrustXAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'trustx', diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js index e8a4624bf16..32daf5ecb96 100644 --- a/test/spec/modules/ucfunnelBidAdapter_spec.js +++ b/test/spec/modules/ucfunnelBidAdapter_spec.js @@ -89,34 +89,34 @@ const validNativeBidRes = { width: 1 }; -describe('ucfunnel Adapter', () => { - describe('request', () => { - it('should validate bid request', () => { +describe('ucfunnel Adapter', function () { + describe('request', function () { + it('should validate bid request', function () { expect(spec.isBidRequestValid(validBannerBidReq)).to.equal(true); }); - it('should not validate incorrect bid request', () => { + it('should not validate incorrect bid request', function () { expect(spec.isBidRequestValid(invalidBannerBidReq)).to.equal(false); }); }); - describe('build request', () => { + describe('build request', function () { const request = spec.buildRequests([validBannerBidReq]); - it('should create a POST request for every bid', () => { + it('should create a POST request for every bid', function () { expect(request[0].method).to.equal('GET'); expect(request[0].url).to.equal(location.protocol + spec.ENDPOINT); }); - it('should attach the bid request object', () => { + it('should attach the bid request object', function () { expect(request[0].bidRequest).to.equal(validBannerBidReq); }); - it('should attach request data', () => { + it('should attach request data', function () { const data = request[0].data; const [ width, height ] = validBannerBidReq.sizes[0]; expect(data.w).to.equal(width); expect(data.h).to.equal(height); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; validBannerBidReq.sizes = [[ width, height ]]; @@ -127,15 +127,15 @@ describe('ucfunnel Adapter', () => { }); }); - describe('interpretResponse', () => { - describe('should support banner', () => { + describe('interpretResponse', function () { + describe('should support banner', function () { const request = spec.buildRequests([ validBannerBidReq ]); const result = spec.interpretResponse({body: validBannerBidRes}, request[0]); - it('should build bid array for banner', () => { + it('should build bid array for banner', function () { expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const bid = result[0]; expect(bid.mediaType).to.equal(BANNER); @@ -147,14 +147,14 @@ describe('ucfunnel Adapter', () => { }); }); - describe('should support video', () => { + describe('should support video', function () { const request = spec.buildRequests([ validVideoBidReq ]); const result = spec.interpretResponse({body: validVideoBidRes}, request[0]); - it('should build bid array', () => { + it('should build bid array', function () { expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const bid = result[0]; expect(bid.mediaType).to.equal(VIDEO); @@ -167,14 +167,14 @@ describe('ucfunnel Adapter', () => { }); }); - describe('should support native', () => { + describe('should support native', function () { const request = spec.buildRequests([ validNativeBidReq ]); const result = spec.interpretResponse({body: validNativeBidRes}, request[0]); - it('should build bid array', () => { + it('should build bid array', function () { expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const bid = result[0]; expect(bid.mediaType).to.equal(NATIVE); diff --git a/test/spec/modules/underdogmediaBidAdapter_spec.js b/test/spec/modules/underdogmediaBidAdapter_spec.js index 8ccac8d4f08..6f4df57d316 100644 --- a/test/spec/modules/underdogmediaBidAdapter_spec.js +++ b/test/spec/modules/underdogmediaBidAdapter_spec.js @@ -1,11 +1,11 @@ import { expect } from 'chai'; import { spec } from 'modules/underdogmediaBidAdapter'; -describe('UnderdogMedia adapter', () => { +describe('UnderdogMedia adapter', function () { let bidRequests; let bidderRequest; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'underdogmedia', @@ -35,9 +35,9 @@ describe('UnderdogMedia adapter', () => { } }); - describe('implementation', () => { - describe('for requests', () => { - it('should accept valid bid', () => { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { let validBid = { bidder: 'underdogmedia', params: { @@ -50,7 +50,7 @@ describe('UnderdogMedia adapter', () => { expect(isValid).to.equal(true); }); - it('should reject invalid bid missing sizes', () => { + it('should reject invalid bid missing sizes', function () { let invalidBid = { bidder: 'underdogmedia', params: { @@ -62,7 +62,7 @@ describe('UnderdogMedia adapter', () => { expect(isValid).to.equal(false); }); - it('should reject invalid bid missing siteId', () => { + it('should reject invalid bid missing siteId', function () { let invalidBid = { bidder: 'underdogmedia', params: {}, @@ -73,7 +73,7 @@ describe('UnderdogMedia adapter', () => { expect(isValid).to.equal(false); }); - it('request data should contain sid', () => { + it('request data should contain sid', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -91,7 +91,7 @@ describe('UnderdogMedia adapter', () => { expect(request.data.sid).to.equal('12143'); }); - it('request data should contain sizes', () => { + it('request data should contain sizes', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -109,7 +109,7 @@ describe('UnderdogMedia adapter', () => { expect(request.data.sizes).to.equal('300x250,728x90'); }); - it('request data should contain gdpr info', () => { + it('request data should contain gdpr info', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -129,7 +129,7 @@ describe('UnderdogMedia adapter', () => { expect(request.data.consentData).to.equal('consentDataString'); }); - it('should not build a request if no vendorConsent', () => { + it('should not build a request if no vendorConsent', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -160,7 +160,7 @@ describe('UnderdogMedia adapter', () => { expect(request).to.equal(undefined); }); - it('should properly build a request if no vendorConsent but no gdprApplies', () => { + it('should properly build a request if no vendorConsent but no gdprApplies', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -195,7 +195,7 @@ describe('UnderdogMedia adapter', () => { expect(request.data.consentData).to.equal('consentDataString'); }); - it('should properly build a request if gdprConsent empty', () => { + it('should properly build a request if gdprConsent empty', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -220,8 +220,8 @@ describe('UnderdogMedia adapter', () => { }); }); - describe('bid responses', () => { - it('should return complete bid response', () => { + describe('bid responses', function () { + it('should return complete bid response', function () { let serverResponse = { body: { mids: [ @@ -260,7 +260,7 @@ describe('UnderdogMedia adapter', () => { expect(bids[0].currency).to.equal('USD'); }); - it('should return empty bid response if mids empty', () => { + it('should return empty bid response if mids empty', function () { let serverResponse = { body: { mids: [] @@ -272,7 +272,7 @@ describe('UnderdogMedia adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on incorrect size', () => { + it('should return empty bid response on incorrect size', function () { let serverResponse = { body: { mids: [ @@ -294,7 +294,7 @@ describe('UnderdogMedia adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on 0 cpm', () => { + it('should return empty bid response on 0 cpm', function () { let serverResponse = { body: { mids: [ @@ -316,7 +316,7 @@ describe('UnderdogMedia adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response if no ad in response', () => { + it('should return empty bid response if no ad in response', function () { let serverResponse = { body: { mids: [ @@ -338,7 +338,7 @@ describe('UnderdogMedia adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('ad html string should contain the notification urls', () => { + it('ad html string should contain the notification urls', function () { let serverResponse = { body: { mids: [ diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index 4a621fb4465..4b816d851d9 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -87,24 +87,24 @@ const bidResArray = [ } ]; -describe('Undertone Adapter', () => { - describe('request', () => { - it('should validate bid request', () => { +describe('Undertone Adapter', function () { + describe('request', function () { + it('should validate bid request', function () { expect(spec.isBidRequestValid(validBidReq)).to.equal(true); }); - it('should not validate incorrect bid request', () => { + it('should not validate incorrect bid request', function () { expect(spec.isBidRequestValid(invalidBidReq)).to.equal(undefined); }); }); - describe('build request', () => { - it('should send request to correct url via POST', () => { + describe('build request', function () { + it('should send request to correct url via POST', function () { const request = spec.buildRequests(bidReq); const domain = null; const REQ_URL = `${URL}?pid=${bidReq[0].params.publisherId}&domain=${domain}`; expect(request.url).to.equal(REQ_URL); expect(request.method).to.equal('POST'); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const request = spec.buildRequests(bidReq); const bid1 = JSON.parse(request.data)['x-ut-hb-params'][0]; expect(bid1.bidRequestId).to.equal('263be71e91dd9d'); @@ -121,13 +121,13 @@ describe('Undertone Adapter', () => { }); }); - describe('interpretResponse', () => { - it('should build bid array', () => { + describe('interpretResponse', function () { + it('should build bid array', function () { let result = spec.interpretResponse({body: bidResponse}); expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const result = spec.interpretResponse({body: bidResponse}); const bid = result[0]; @@ -141,12 +141,12 @@ describe('Undertone Adapter', () => { expect(bid.ttl).to.equal(360); }); - it('should return empty array when response is incorrect', () => { + it('should return empty array when response is incorrect', function () { expect(spec.interpretResponse({body: {}}).length).to.equal(0); expect(spec.interpretResponse({body: []}).length).to.equal(0); }); - it('should only use valid bid responses', () => { + it('should only use valid bid responses', function () { expect(spec.interpretResponse({ body: bidResArray }).length).to.equal(1); }); }); diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js index 3e39842bd0a..2c8fd9071d6 100644 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -6,7 +6,7 @@ import { VIDEO } from 'src/mediaTypes' import { Renderer } from 'src/Renderer' import { adapter } from 'modules/unrulyBidAdapter' -describe('UnrulyAdapter', () => { +describe('UnrulyAdapter', function () { function createOutStreamExchangeBid({ adUnitCode = 'placement2', statusCode = 1, @@ -39,7 +39,7 @@ describe('UnrulyAdapter', () => { let sandbox; let fakeRenderer; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); sandbox.stub(utils, 'logError'); sandbox.stub(Renderer, 'install'); @@ -50,12 +50,12 @@ describe('UnrulyAdapter', () => { Renderer.install.returns(fakeRenderer) }); - afterEach(() => { + afterEach(function () { sandbox.restore(); delete parent.window.unruly }); - it('should expose Unruly Bidder code', () => { + it('should expose Unruly Bidder code', function () { expect(adapter.code).to.equal('unruly') }); @@ -63,22 +63,22 @@ describe('UnrulyAdapter', () => { expect(adapter.supportedMediaTypes).to.deep.equal([ VIDEO ]) }); - describe('isBidRequestValid', () => { - it('should be a function', () => { + describe('isBidRequestValid', function () { + it('should be a function', function () { expect(typeof adapter.isBidRequestValid).to.equal('function') }); - it('should return false if bid is falsey', () => { + it('should return false if bid is falsey', function () { expect(adapter.isBidRequestValid()).to.be.false; }); - it('should return true if bid.mediaType is "video"', () => { + it('should return true if bid.mediaType is "video"', function () { const mockBid = { mediaType: 'video' }; expect(adapter.isBidRequestValid(mockBid)).to.be.true; }); - it('should return true if bid.mediaTypes.video.context is "outstream"', () => { + it('should return true if bid.mediaTypes.video.context is "outstream"', function () { const mockBid = { mediaTypes: { video: { @@ -91,19 +91,19 @@ describe('UnrulyAdapter', () => { }); }); - describe('buildRequests', () => { - it('should be a function', () => { + describe('buildRequests', function () { + it('should be a function', function () { expect(typeof adapter.buildRequests).to.equal('function'); }); - it('should return an object', () => { + it('should return an object', function () { const mockBidRequests = ['mockBid']; expect(typeof adapter.buildRequests(mockBidRequests)).to.equal('object') }); - it('should return a server request with a valid exchange url', () => { + it('should return a server request with a valid exchange url', function () { const mockBidRequests = ['mockBid']; expect(adapter.buildRequests(mockBidRequests).url).to.equal('https://targeting.unrulymedia.com/prebid') }); - it('should return a server request with method === POST', () => { + it('should return a server request with method === POST', function () { const mockBidRequests = ['mockBid']; expect(adapter.buildRequests(mockBidRequests).method).to.equal('POST'); }); @@ -113,7 +113,7 @@ describe('UnrulyAdapter', () => { contentType: 'application/json' }); }); - it('should return a server request with valid payload', () => { + it('should return a server request with valid payload', function () { const mockBidRequests = ['mockBid']; const mockBidderRequest = {bidderCode: 'mockBidder'}; expect(adapter.buildRequests(mockBidRequests, mockBidderRequest).data) @@ -121,18 +121,18 @@ describe('UnrulyAdapter', () => { }) }); - describe('interpretResponse', () => { - it('should be a function', () => { + describe('interpretResponse', function () { + it('should be a function', function () { expect(typeof adapter.interpretResponse).to.equal('function'); }); - it('should return empty array when serverResponse is undefined', () => { + it('should return empty array when serverResponse is undefined', function () { expect(adapter.interpretResponse()).to.deep.equal([]); }); - it('should return empty array when serverResponse has no bids', () => { + it('should return empty array when serverResponse has no bids', function () { const mockServerResponse = { body: { bids: [] } }; expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]) }); - it('should return array of bids when receive a successful response from server', () => { + it('should return array of bids when receive a successful response from server', function () { const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); const mockServerResponse = createExchangeResponse(mockExchangeBid); expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([ @@ -151,7 +151,7 @@ describe('UnrulyAdapter', () => { ]) }); - it('should initialize and set the renderer', () => { + it('should initialize and set the renderer', function () { expect(Renderer.install).not.to.have.been.called; expect(fakeRenderer.setRender).not.to.have.been.called; @@ -172,7 +172,7 @@ describe('UnrulyAdapter', () => { sinon.assert.calledWithExactly(fakeRenderer.setRender, sinon.match.func) }); - it('bid is placed on the bid queue when render is called', () => { + it('bid is placed on the bid queue when render is called', function () { const exchangeBid = createOutStreamExchangeBid({ adUnitCode: 'video', vastUrl: 'value: vastUrl' }); const exchangeResponse = createExchangeResponse(exchangeBid); @@ -192,7 +192,7 @@ describe('UnrulyAdapter', () => { expect(sentRendererConfig.adUnitCode).to.equal('video') }) - it('should ensure that renderer is placed in Prebid supply mode', () => { + it('should ensure that renderer is placed in Prebid supply mode', function () { const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); const mockServerResponse = createExchangeResponse(mockExchangeBid); diff --git a/test/spec/modules/uolBidAdapter_spec.js b/test/spec/modules/uolBidAdapter_spec.js index 843f47682dc..1733afc91f9 100644 --- a/test/spec/modules/uolBidAdapter_spec.js +++ b/test/spec/modules/uolBidAdapter_spec.js @@ -4,10 +4,10 @@ import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = 'https://prebid.adilligo.com/v1/prebid.json'; -describe('UOL Bid Adapter', () => { +describe('UOL Bid Adapter', function () { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'uol', 'params': { @@ -20,7 +20,7 @@ describe('UOL Bid Adapter', () => { 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', }; - it('should return true for valid params', () => { + it('should return true for valid params', function () { let clonedBid = Object.assign({}, bid); expect(spec.isBidRequestValid(clonedBid)).to.equal(true); @@ -40,13 +40,13 @@ describe('UOL Bid Adapter', () => { expect(spec.isBidRequestValid(clonedBid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let clonedBid = Object.assign({}, bid); delete clonedBid.params; expect(spec.isBidRequestValid(clonedBid)).to.equal(false); }); - it('should return false when params are invalid', () => { + it('should return false when params are invalid', function () { let clonedBid = Object.assign({}, bid); delete clonedBid.params; clonedBid.params = { @@ -69,7 +69,7 @@ describe('UOL Bid Adapter', () => { expect(spec.isBidRequestValid(clonedBid)).to.equal(false); }); - it('should return false when cpmFactor is passed and test flag isn\'t active', () => { + it('should return false when cpmFactor is passed and test flag isn\'t active', function () { let clonedBid = Object.assign({}, bid); delete clonedBid.params; clonedBid.params = { @@ -80,14 +80,14 @@ describe('UOL Bid Adapter', () => { expect(spec.isBidRequestValid(clonedBid)).to.equal(false); }); - it('should not allow empty size', () => { + it('should not allow empty size', function () { let clonedBid = Object.assign({}, bid); delete clonedBid.sizes; expect(spec.isBidRequestValid(clonedBid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let queryPermission; let cleanup = function() { navigator.permissions.query = queryPermission; @@ -148,32 +148,32 @@ describe('UOL Bid Adapter', () => { 'timeout': 3000 }; - describe('buildRequest basic params', () => { + describe('buildRequest basic params', function () { const requestObject = spec.buildRequests(bidRequests, bidderRequest); const payload = JSON.parse(requestObject.data); - it('should send bid requests to expected endpoint via POST method', () => { + it('should send bid requests to expected endpoint via POST method', function () { expect(requestObject.url).to.equal(ENDPOINT); expect(requestObject.method).to.equal('POST'); }); - it('should contain referrer URL', () => { + it('should contain referrer URL', function () { expect(payload.referrerURL).to.exist.and.to.match(/^http(s)?:\/\/.+$/) }); - it('should contain an array of requests with length equivalent to bid count', () => { + it('should contain an array of requests with length equivalent to bid count', function () { expect(payload.requests).to.have.length(bidRequests.length); }); - it('should return propper ad size if at least one entry is provided', () => { + it('should return propper ad size if at least one entry is provided', function () { expect(payload.requests[0].sizes).to.deep.equal(bidRequests[0].sizes); }); }); if (navigator.permissions && navigator.permissions.query && navigator.geolocation) { - describe('buildRequest geolocation param', () => { // shall only be tested if browser engine supports geolocation and permissions API. + describe('buildRequest geolocation param', function () { // shall only be tested if browser engine supports geolocation and permissions API. let geolocation = { lat: 4, long: 3, timestamp: 123121451 }; - it('should contain user coordinates if (i) DNT is off; (ii) browser supports implementation; (iii) localStorage contains geolocation history', () => { + it('should contain user coordinates if (i) DNT is off; (ii) browser supports implementation; (iii) localStorage contains geolocation history', function () { localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); grantTriangulation(); const requestObject = spec.buildRequests(bidRequests, bidderRequest); @@ -182,7 +182,7 @@ describe('UOL Bid Adapter', () => { cleanup(); }) - it('should not contain user coordinates if localStorage is empty', () => { + it('should not contain user coordinates if localStorage is empty', function () { localStorage.removeItem('uolLocationTracker'); denyTriangulation(); const requestObject = spec.buildRequests(bidRequests, bidderRequest); @@ -191,7 +191,7 @@ describe('UOL Bid Adapter', () => { cleanup(); }) - it('should not contain user coordinates if browser doesnt support permission query', () => { + it('should not contain user coordinates if browser doesnt support permission query', function () { localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); removeQuerySupport(); const requestObject = spec.buildRequests(bidRequests, bidderRequest); @@ -201,8 +201,8 @@ describe('UOL Bid Adapter', () => { }) }) } - describe('buildRequest test params', () => { - it('should return test and cpmFactor params if defined', () => { + describe('buildRequest test params', function () { + it('should return test and cpmFactor params if defined', function () { let clonedBid = JSON.parse(JSON.stringify(bidRequests)); delete clonedBid[0].params; clonedBid.splice(1, 1); @@ -229,7 +229,7 @@ describe('UOL Bid Adapter', () => { }) }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse = { 'body': { 'bidderRequestId': '2a21a2fc993ef9', @@ -261,7 +261,7 @@ describe('UOL Bid Adapter', () => { }; let bidRequest = {}; - it('should return the correct bid response structure', () => { + it('should return the correct bid response structure', function () { let expectedResponse = [ { 'requestId': '2a21a2fc993ef9', @@ -281,7 +281,7 @@ describe('UOL Bid Adapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('should corretly return an empty array of bidResponses if no ads were received', () => { + it('should corretly return an empty array of bidResponses if no ads were received', function () { let emptyResponse = Object.assign({}, serverResponse); emptyResponse.body.ads = []; let result = spec.interpretResponse(emptyResponse, {bidRequest}); @@ -289,15 +289,15 @@ describe('UOL Bid Adapter', () => { }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let syncOptions = { iframeEnabled: true }; let serverResponses = [{ body: { trackingPixel: 'https://www.uol.com.br' } }, { body: { trackingPixel: 'http://www.dynad.net/' } }]; - it('should return the two sync params for iframeEnabled bids with a trackingPixel response', () => { + it('should return the two sync params for iframeEnabled bids with a trackingPixel response', function () { expect(spec.getUserSyncs(syncOptions, serverResponses)).to.have.length(2); }) - it('should not return any sync params if iframe is disabled or no trackingPixel is received', () => { + it('should not return any sync params if iframe is disabled or no trackingPixel is received', function () { let cloneOptions = Object.assign({}, syncOptions); delete cloneOptions.iframeEnabled; expect(spec.getUserSyncs(cloneOptions, serverResponses)).to.have.length(0); diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 271f1f2d04a..fefa8e446ed 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -96,45 +96,45 @@ const displayEqResponse = [{ cpm: 0.9 }]; -describe('vertamediaBidAdapter', () => { +describe('vertamediaBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(VIDEO_REQUEST)).to.equal(12345); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, VIDEO_REQUEST); delete bid.params; expect(spec.isBidRequestValid(bid)).to.equal(undefined); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let videoBidRequests = [VIDEO_REQUEST]; let dispalyBidRequests = [DISPLAY_REQUEST]; const displayRequest = spec.buildRequests(dispalyBidRequests, {}); const videoRequest = spec.buildRequests(videoBidRequests, {}); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(videoRequest.method).to.equal('GET'); expect(displayRequest.method).to.equal('GET'); }); - it('sends bid request to correct ENDPOINT', () => { + it('sends bid request to correct ENDPOINT', function () { expect(videoRequest.url).to.equal(ENDPOINT); expect(displayRequest.url).to.equal(ENDPOINT); }); - it('sends correct video bid parameters', () => { + it('sends correct video bid parameters', function () { const bid = Object.assign({}, videoRequest.data); delete bid.domain; @@ -148,7 +148,7 @@ describe('vertamediaBidAdapter', () => { expect(bid).to.deep.equal(eq); }); - it('sends correct display bid parameters', () => { + it('sends correct display bid parameters', function () { const bid = Object.assign({}, displayRequest.data); delete bid.domain; @@ -163,18 +163,18 @@ describe('vertamediaBidAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse; let bidderRequest; let eqResponse; - afterEach(() => { + afterEach(function () { serverResponse = null; bidderRequest = null; eqResponse = null; }); - it('should get correct video bid response', () => { + it('should get correct video bid response', function () { serverResponse = SERVER_VIDEO_RESPONSE; bidderRequest = videoBidderRequest; eqResponse = videoEqResponse; @@ -182,7 +182,7 @@ describe('vertamediaBidAdapter', () => { bidServerResponseCheck(); }); - it('should get correct display bid response', () => { + it('should get correct display bid response', function () { serverResponse = SERVER_DISPLAY_RESPONSE; bidderRequest = displayBidderRequest; eqResponse = displayEqResponse; @@ -203,13 +203,13 @@ describe('vertamediaBidAdapter', () => { expect(noBidResult.length).to.equal(0); } - it('handles video nobid responses', () => { + it('handles video nobid responses', function () { bidderRequest = videoBidderRequest; nobidServerResponseCheck(); }); - it('handles display nobid responses', () => { + it('handles display nobid responses', function () { bidderRequest = displayBidderRequest; nobidServerResponseCheck(); diff --git a/test/spec/modules/vertozBidAdapter_spec.js b/test/spec/modules/vertozBidAdapter_spec.js index a84fc4847f5..1eb85b6b566 100644 --- a/test/spec/modules/vertozBidAdapter_spec.js +++ b/test/spec/modules/vertozBidAdapter_spec.js @@ -4,16 +4,16 @@ import { newBidder } from 'src/adapters/bidderFactory'; const BASE_URI = '//hb.vrtzads.com/vzhbidder/bid?'; -describe('VertozAdapter', () => { +describe('VertozAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'vertoz', 'params': { @@ -26,11 +26,11 @@ describe('VertozAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,7 +40,7 @@ describe('VertozAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'vertoz', @@ -55,14 +55,14 @@ describe('VertozAdapter', () => { } ]; - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(BASE_URI); expect(request.method).to.equal('POST'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'vzhPlacementId': 'VZ-HB-B784382V6C6G3C', 'bid': '76021e56-adaf-4114-b68d-ccacd1b3e551_1', @@ -75,7 +75,7 @@ describe('VertozAdapter', () => { 'statusText': 'Vertoz:Success' }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { 'requestId': '44b3fcfd24aa93', @@ -97,7 +97,7 @@ describe('VertozAdapter', () => { expect(result[0].cpm).to.not.equal(null); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'vzhPlacementId': 'VZ-HB-I617046VBGE3EH', 'slotBidId': 'f00412ac86b79', diff --git a/test/spec/modules/viBidAdapter_spec.js b/test/spec/modules/viBidAdapter_spec.js index e8b0fbcc4b2..2468da0cfaf 100644 --- a/test/spec/modules/viBidAdapter_spec.js +++ b/test/spec/modules/viBidAdapter_spec.js @@ -7,7 +7,7 @@ const ENDPOINT = `//pb.vi-serve.com/prebid/bid`; describe('viBidAdapter', function() { newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'vi', 'params': { @@ -27,17 +27,17 @@ describe('viBidAdapter', function() { 'transactionId': '474da635-9cf0-4188-a3d9-58961be8f905' }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when pubId not passed', () => { + it('should return false when pubId not passed', function () { bid.params.pubId = undefined; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [{ 'bidder': 'vi', 'params': { @@ -59,16 +59,16 @@ describe('viBidAdapter', function() { const request = spec.buildRequests(bidRequests); - it('POST bid request to vi', () => { + it('POST bid request to vi', function () { expect(request.method).to.equal('POST'); }); - it('check endpoint URL', () => { + it('check endpoint URL', function () { expect(request.url).to.equal(ENDPOINT) }); }); - describe('buildRequests can handle size in 1-dim array', () => { + describe('buildRequests can handle size in 1-dim array', function () { let bidRequests = [{ 'bidder': 'vi', 'params': { @@ -88,16 +88,16 @@ describe('viBidAdapter', function() { const request = spec.buildRequests(bidRequests); - it('POST bid request to vi', () => { + it('POST bid request to vi', function () { expect(request.method).to.equal('POST'); }); - it('check endpoint URL', () => { + it('check endpoint URL', function () { expect(request.url).to.equal(ENDPOINT) }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { body: [{ 'id': '29b891ad542377', @@ -109,7 +109,7 @@ describe('viBidAdapter', function() { }] }; - it('should get the correct bid response', () => { + it('should get the correct bid response', function () { let expectedResponse = [{ 'requestId': '29b891ad542377', 'cpm': 0.1, @@ -128,7 +128,7 @@ describe('viBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: [] }; diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index b857967a44e..d9c08ad924c 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -54,31 +54,31 @@ const SYNC_OPTIONS = { 'pixelEnabled': true }; -describe('VidazooBidAdapter', () => { - describe('validtae spec', () => { - it('exists and is a function', () => { +describe('VidazooBidAdapter', function () { + describe('validtae spec', function () { + it('exists and is a function', function () { expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function'); }); - it('exists and is 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', () => { + it('exists and is a function', function () { expect(adapter.interpretResponse).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.getUserSyncs).to.exist.and.to.be.a('function'); }); - it('exists and is a string', () => { + it('exists and is a string', function () { expect(adapter.code).to.exist.and.to.be.a('string'); }); }); - describe('validate bid requests', () => { - it('should require cId', () => { + describe('validate bid requests', function () { + it('should require cId', function () { const isValid = adapter.isBidRequestValid({ params: { pId: 'pid' @@ -87,7 +87,7 @@ describe('VidazooBidAdapter', () => { expect(isValid).to.be.false; }); - it('should require pId', () => { + it('should require pId', function () { const isValid = adapter.isBidRequestValid({ params: { cId: 'cid' @@ -96,7 +96,7 @@ describe('VidazooBidAdapter', () => { expect(isValid).to.be.false; }); - it('should validate correctly', () => { + it('should validate correctly', function () { const isValid = adapter.isBidRequestValid({ params: { cId: 'cid', @@ -107,15 +107,15 @@ describe('VidazooBidAdapter', () => { }); }); - describe('build requests', () => { + describe('build requests', function () { let sandbox; - before(() => { + before(function () { sandbox = sinon.sandbox.create(); sandbox.stub(utils, 'getTopWindowUrl').returns('http://www.greatsite.com'); sandbox.stub(Date, 'now').returns(1000); }); - it('should build request for each size', () => { + it('should build request for each size', function () { const requests = adapter.buildRequests([BID], BIDDER_REQUEST); expect(requests).to.have.length(2); expect(requests[0]).to.deep.equal({ @@ -152,28 +152,28 @@ describe('VidazooBidAdapter', () => { }); }); - after(() => { + after(function () { sandbox.restore(); }); }); - describe('interpret response', () => { - it('should return empty array when there is no response', () => { + describe('interpret response', function () { + it('should return empty array when there is no response', function () { const responses = adapter.interpretResponse(null); expect(responses).to.be.empty; }); - it('should return empty array when there is no ad', () => { + it('should return empty array when there is no ad', function () { const responses = adapter.interpretResponse({price: 1, ad: ''}); expect(responses).to.be.empty; }); - it('should return empty array when there is no price', () => { + it('should return empty array when there is no price', function () { const responses = adapter.interpretResponse({price: null, ad: 'great ad'}); expect(responses).to.be.empty; }); - it('should return an array of interpreted responses', () => { + it('should return an array of interpreted responses', function () { const responses = adapter.interpretResponse(SERVER_RESPONSE, REQUEST); expect(responses).to.have.length(1); expect(responses[0]).to.deep.equal({ @@ -189,7 +189,7 @@ describe('VidazooBidAdapter', () => { }); }); - it('should take default TTL', () => { + it('should take default TTL', function () { const serverResponse = utils.deepClone(SERVER_RESPONSE); delete serverResponse.body.exp; const responses = adapter.interpretResponse(serverResponse, REQUEST); diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 67b747b5130..bf8d4cc7d13 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -6,13 +6,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('VisxAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'visx', 'params': { @@ -25,11 +25,11 @@ describe('VisxAdapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -39,7 +39,7 @@ describe('VisxAdapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'visx', @@ -76,7 +76,7 @@ describe('VisxAdapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); const payload = request.data; expect(payload).to.be.an('object'); @@ -87,7 +87,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'EUR'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); @@ -98,7 +98,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'EUR'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -111,7 +111,7 @@ describe('VisxAdapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -123,7 +123,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'EUR'); delete bidRequests[1].params.priceType; }); - it('should add currency from currency.bidderCurrencyDefault', () => { + it('should add currency from currency.bidderCurrencyDefault', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'JPY' : 'USD'); const request = spec.buildRequests(bidRequests); @@ -136,7 +136,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'JPY'); getConfigStub.restore(); }); - it('should add currency from currency.adServerCurrency', () => { + it('should add currency from currency.adServerCurrency', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? '' : 'USD'); const request = spec.buildRequests(bidRequests); @@ -149,7 +149,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'USD'); getConfigStub.restore(); }); - it('if gdprConsent is present payload must have gdpr params', () => { + it('if gdprConsent is present payload must have gdpr params', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -157,7 +157,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('gdpr_applies', 1); }); - it('if gdprApplies is false gdpr_applies must be 0', () => { + it('if gdprApplies is false gdpr_applies must be 0', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -165,7 +165,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('gdpr_applies', 0); }); - it('if gdprApplies is undefined gdpr_applies must be 1', () => { + it('if gdprApplies is undefined gdpr_applies must be 1', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -174,7 +174,7 @@ describe('VisxAdapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -185,7 +185,7 @@ describe('VisxAdapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'visx', @@ -219,7 +219,7 @@ describe('VisxAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'visx', @@ -299,7 +299,7 @@ describe('VisxAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should return right currency', () => { + it('should return right currency', function () { const bidRequests = [ { 'bidder': 'visx', @@ -335,7 +335,7 @@ describe('VisxAdapter', function () { getConfigStub.restore(); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'visx', diff --git a/test/spec/modules/vubleAnalyticsAdapter_spec.js b/test/spec/modules/vubleAnalyticsAdapter_spec.js index 896f6e4ee87..fe84c0a6b04 100644 --- a/test/spec/modules/vubleAnalyticsAdapter_spec.js +++ b/test/spec/modules/vubleAnalyticsAdapter_spec.js @@ -6,21 +6,21 @@ let constants = require('src/constants.json'); describe('Vuble Prebid Analytic', function () { let xhr; - before(() => { + before(function () { xhr = sinon.useFakeXMLHttpRequest(); }); - after(() => { + after(function () { vubleAnalytics.disableAnalytics(); xhr.restore(); }); describe('enableAnalytics', function () { - beforeEach(() => { + beforeEach(function () { sinon.spy(vubleAnalytics, 'track'); sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { vubleAnalytics.track.restore(); events.getEvents.restore(); }); diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 6d266ca465e..8996c1b4957 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -4,23 +4,23 @@ import {expect} from 'chai'; import {spec as adapter} from 'modules/vubleBidAdapter'; import * as utils from 'src/utils'; -describe('VubleAdapter', () => { - describe('Check methods existance', () => { - it('exists and is a function', () => { +describe('VubleAdapter', 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', () => { + it('exists and is a function', function () { expect(adapter.buildRequests).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.interpretResponse).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.getUserSyncs).to.exist.and.to.be.a('function'); }); }); - describe('Check method isBidRequestValid return', () => { + describe('Check method isBidRequestValid return', function () { let bid = { bidder: 'vuble', params: { @@ -37,11 +37,11 @@ describe('VubleAdapter', () => { }, }; - it('should be true', () => { + it('should be true', function () { expect(adapter.isBidRequestValid(bid)).to.be.true; }); - it('should be false because the sizes are missing or in the wrong format', () => { + it('should be false because the sizes are missing or in the wrong format', function () { let wrongBid = utils.deepClone(bid); wrongBid.sizes = '640360'; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; @@ -51,7 +51,7 @@ describe('VubleAdapter', () => { expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); - it('should be false because the mediaType is missing or wrong', () => { + it('should be false because the mediaType is missing or wrong', function () { let wrongBid = utils.deepClone(bid); wrongBid.mediaTypes = {}; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; @@ -61,7 +61,7 @@ describe('VubleAdapter', () => { expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); - it('should be false because the env is missing or wrong', () => { + it('should be false because the env is missing or wrong', function () { let wrongBid = utils.deepClone(bid); wrongBid.params.env = 'us'; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; @@ -71,22 +71,22 @@ describe('VubleAdapter', () => { expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); - it('should be false because params.pubId is missing', () => { + it('should be false because params.pubId is missing', function () { let wrongBid = utils.deepClone(bid); delete wrongBid.params.pubId; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); - it('should be false because params.zoneId is missing', () => { + it('should be false because params.zoneId is missing', function () { let wrongBid = utils.deepClone(bid); delete wrongBid.params.zoneId; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); }); - describe('Check buildRequests method', () => { + describe('Check buildRequests method', function () { let sandbox; - before(() => { + before(function () { sandbox = sinon.sandbox.create(); sandbox.stub(utils, 'getTopWindowUrl').returns('http://www.vuble.tv/'); }); @@ -161,17 +161,17 @@ describe('VubleAdapter', () => { } }; - it('must return the right formatted requests', () => { + it('must return the right formatted requests', function () { let rs = adapter.buildRequests([bid1, bid2]); expect(adapter.buildRequests([bid1, bid2])).to.deep.equal([request1, request2]); }); - after(() => { + after(function () { sandbox.restore(); }); }); - describe('Check interpretResponse method return', () => { + describe('Check interpretResponse method return', function () { // Server's response let response = { body: { @@ -213,11 +213,11 @@ describe('VubleAdapter', () => { mediaType: 'video' }; - it('should equal to the expected formatted result', () => { + it('should equal to the expected formatted result', function () { expect(adapter.interpretResponse(response, bid)).to.deep.equal([result]); }); - it('should be empty because the status is missing or wrong', () => { + it('should be empty because the status is missing or wrong', function () { let wrongResponse = utils.deepClone(response); wrongResponse.body.status = 'ko'; expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; @@ -227,7 +227,7 @@ describe('VubleAdapter', () => { expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; }); - it('should be empty because the body is missing or wrong', () => { + it('should be empty because the body is missing or wrong', function () { let wrongResponse = utils.deepClone(response); wrongResponse.body = [1, 2, 3]; expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; @@ -237,7 +237,7 @@ describe('VubleAdapter', () => { expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; }); - it('should equal to the expected formatted result', () => { + it('should equal to the expected formatted result', function () { response.body.renderer_url = 'vuble_renderer.js'; result.adUnitCode = 'code'; let formattedResponses = adapter.interpretResponse(response, bid); @@ -245,7 +245,7 @@ describe('VubleAdapter', () => { }); }); - describe('Check getUserSyncs method return', () => { + describe('Check getUserSyncs method return', function () { // Sync options let syncOptions = { iframeEnabled: false @@ -265,7 +265,7 @@ describe('VubleAdapter', () => { url: 'http://player.mediabong.net/csifr?1234' }; - it('should return an empty array', () => { + it('should return an empty array', function () { expect(adapter.getUserSyncs({}, [])).to.be.empty; expect(adapter.getUserSyncs({}, [])).to.be.empty; expect(adapter.getUserSyncs(syncOptions, [response])).to.be.empty; @@ -275,7 +275,7 @@ describe('VubleAdapter', () => { expect(adapter.getUserSyncs(syncOptions, [response])).to.be.empty; }); - it('should be equal to the expected result', () => { + it('should be equal to the expected result', function () { response.body.iframeSync = 'http://player.mediabong.net/csifr?1234'; expect(adapter.getUserSyncs(syncOptions, [response])).to.deep.equal([result]); }) diff --git a/test/spec/modules/weboramaBidAdapter_spec.js b/test/spec/modules/weboramaBidAdapter_spec.js index ef8414eb487..d0b119825a6 100644 --- a/test/spec/modules/weboramaBidAdapter_spec.js +++ b/test/spec/modules/weboramaBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/weboramaBidAdapter'; -describe('WeboramaAdapter', () => { +describe('WeboramaAdapter', function () { let bid = { bidId: '2dd581a2b6281d', bidder: 'weborama', @@ -16,31 +16,31 @@ describe('WeboramaAdapter', () => { transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' }; - describe('isBidRequestValid', () => { - it('Should return true when placementId can be cast to a number', () => { + describe('isBidRequestValid', function () { + it('Should return true when placementId can be cast to a number', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false when placementId is not a number', () => { + it('Should return false when placementId is not a number', function () { bid.params.placementId = 'aaa'; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + 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', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//supply.nl.weborama.fr/?c=o&m=multi'); }); - it('Returns valid data if array of bids is valid', () => { + 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', 'secure', 'host', 'page', 'placements'); @@ -59,13 +59,13 @@ describe('WeboramaAdapter', () => { expect(placement.sizes).to.be.an('array'); } }); - it('Returns empty data if no valid requests are passed', () => { + 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', () => { + describe('interpretResponse', function () { let resObject = { body: [ { requestId: '123', @@ -81,7 +81,7 @@ describe('WeboramaAdapter', () => { } ] }; let serverResponses = spec.interpretResponse(resObject); - it('Returns an array of valid server responses if response object is valid', () => { + it('Returns an array of valid server responses if response object is valid', function () { expect(serverResponses).to.be.an('array').that.is.not.empty; for (let i = 0; i < serverResponses.length; i++) { let dataItem = serverResponses[i]; @@ -98,16 +98,16 @@ describe('WeboramaAdapter', () => { expect(dataItem.currency).to.be.a('string'); expect(dataItem.mediaType).to.be.a('string'); } - it('Returns an empty array if invalid response is passed', () => { + it('Returns an empty array if invalid response is passed', function () { serverResponses = spec.interpretResponse('invalid_response'); expect(serverResponses).to.be.an('array').that.is.empty; }); }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let userSync = spec.getUserSyncs(); - it('Returns valid URL and `', () => { + it('Returns valid URL and `', function () { expect(userSync).to.be.an('array').with.lengthOf(1); expect(userSync[0].type).to.exist; expect(userSync[0].url).to.exist; diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js index 81d2528465e..dc0d547d47a 100644 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ b/test/spec/modules/widespaceBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { spec } from 'modules/widespaceBidAdapter'; import includes from 'core-js/library/fn/array/includes'; -describe('+widespaceAdatperTest', () => { +describe('+widespaceAdatperTest', function () { // Dummy bid request const bidRequest = [{ 'adUnitCode': 'div-gpt-ad-1460505748561-0', @@ -110,8 +110,8 @@ describe('+widespaceAdatperTest', () => { navigator.connection.type = 'wifi'; } - describe('+bidRequestValidity', () => { - it('bidRequest with sid and currency params', () => { + describe('+bidRequestValidity', function () { + it('bidRequest with sid and currency params', function () { expect(spec.isBidRequestValid({ bidder: 'widespace', params: { @@ -121,7 +121,7 @@ describe('+widespaceAdatperTest', () => { })).to.equal(true); }); - it('-bidRequest with missing sid', () => { + it('-bidRequest with missing sid', function () { expect(spec.isBidRequestValid({ bidder: 'widespace', params: { @@ -130,7 +130,7 @@ describe('+widespaceAdatperTest', () => { })).to.equal(false); }); - it('-bidRequest with missing currency', () => { + it('-bidRequest with missing currency', function () { expect(spec.isBidRequestValid({ bidder: 'widespace', params: { @@ -140,37 +140,37 @@ describe('+widespaceAdatperTest', () => { }); }); - describe('+bidRequest', () => { + describe('+bidRequest', function () { const request = spec.buildRequests(bidRequest, bidderRequest); const UrlRegExp = /^((ftp|http|https):)?\/\/[^ "]+$/; - it('-bidRequest method is POST', () => { + it('-bidRequest method is POST', function () { expect(request[0].method).to.equal('POST'); }); - it('-bidRequest url is valid', () => { + it('-bidRequest url is valid', function () { expect(UrlRegExp.test(request[0].url)).to.equal(true); }); - it('-bidRequest data exist', () => { + it('-bidRequest data exist', function () { expect(request[0].data).to.exists; }); - it('-bidRequest data is form data', () => { + it('-bidRequest data is form data', function () { expect(typeof request[0].data).to.equal('string'); }); - it('-bidRequest options have header type', () => { + it('-bidRequest options have header type', function () { expect(request[0].options.contentType).to.exists; }); - it('-cookie test for wsCustomData ', () => { + it('-cookie test for wsCustomData ', function () { expect(request[0].data.indexOf('hb.cd') > -1).to.equal(true); }); }); - describe('+interpretResponse', () => { - it('-required params available in response', () => { + describe('+interpretResponse', function () { + it('-required params available in response', function () { const result = spec.interpretResponse(bidResponse, bidRequest); let requiredKeys = [ 'requestId', @@ -201,19 +201,19 @@ describe('+widespaceAdatperTest', () => { }); }); - it('-empty result if noad responded', () => { + it('-empty result if noad responded', function () { const noAdResult = spec.interpretResponse(bidResponseNoAd, bidRequest); expect(noAdResult.length).to.equal(0); }); - it('-empty response should not breake anything in adapter', () => { + it('-empty response should not breake anything in adapter', function () { const noResponse = spec.interpretResponse({}, bidRequest); expect(noResponse.length).to.equal(0); }); }); - describe('+getUserSyncs', () => { - it('-always return an array', () => { + describe('+getUserSyncs', function () { + it('-always return an array', function () { const userSync_test1 = spec.getUserSyncs({}, [bidResponse]); expect(Array.isArray(userSync_test1)).to.equal(true); diff --git a/test/spec/modules/xendizBidAdapter_spec.js b/test/spec/modules/xendizBidAdapter_spec.js index 66b9dc62b88..4d1aa3c935f 100644 --- a/test/spec/modules/xendizBidAdapter_spec.js +++ b/test/spec/modules/xendizBidAdapter_spec.js @@ -34,39 +34,39 @@ const bidResponse = { const noBidResponse = { body: { id: '1d1a030790a475', bids: [] } }; -describe('xendizBidAdapter', () => { +describe('xendizBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return false', () => { + describe('isBidRequestValid', function () { + it('should return false', function () { let bid = Object.assign({}, bidRequest); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true', () => { + it('should return true', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); }); - describe('buildRequests', () => { - it('should format valid url', () => { + describe('buildRequests', function () { + it('should format valid url', function () { const request = spec.buildRequests([bidRequest]); expect(request.url).to.equal(VALID_ENDPOINT); }); - it('should format valid url', () => { + it('should format valid url', function () { const request = spec.buildRequests([bidRequest]); expect(request.url).to.equal(VALID_ENDPOINT); }); - it('should format valid request body', () => { + it('should format valid request body', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); expect(payload.id).to.exist; @@ -74,7 +74,7 @@ describe('xendizBidAdapter', () => { expect(payload.device).to.exist; }); - it('should attach valid device info', () => { + it('should attach valid device info', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); expect(payload.device).to.deep.equal([ @@ -84,7 +84,7 @@ describe('xendizBidAdapter', () => { ]); }); - it('should transform sizes', () => { + it('should transform sizes', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); const item = payload.items[0]; @@ -92,8 +92,8 @@ describe('xendizBidAdapter', () => { }); }); - describe('interpretResponse', () => { - it('should get correct bid response', () => { + describe('interpretResponse', function () { + it('should get correct bid response', function () { const result = spec.interpretResponse(bidResponse); const validResponse = [{ requestId: '30b31c1838de1e', @@ -111,7 +111,7 @@ describe('xendizBidAdapter', () => { expect(result).to.deep.equal(validResponse); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let result = spec.interpretResponse(noBidResponse); expect(result.length).to.equal(0); }); diff --git a/test/spec/modules/xhbBidAdapter_spec.js b/test/spec/modules/xhbBidAdapter_spec.js index 98bc744224c..e48d3011ed2 100644 --- a/test/spec/modules/xhbBidAdapter_spec.js +++ b/test/spec/modules/xhbBidAdapter_spec.js @@ -5,16 +5,16 @@ import { deepClone } from 'src/utils'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; -describe('xhbAdapter', () => { +describe('xhbAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'xhb', 'params': { @@ -27,11 +27,11 @@ describe('xhbAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -42,7 +42,7 @@ describe('xhbAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -52,7 +52,7 @@ describe('xhbAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'xhb', @@ -67,7 +67,7 @@ describe('xhbAdapter', () => { } ]; - it('should parse out private sizes', () => { + it('should parse out private sizes', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -85,7 +85,7 @@ describe('xhbAdapter', () => { expect(payload.tags[0].private_sizes).to.deep.equal([{width: 300, height: 250}]); }); - it('should add source and verison to the tag', () => { + 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; @@ -95,7 +95,7 @@ describe('xhbAdapter', () => { }); }); - it('should populate the ad_types array on all requests', () => { + it('should populate the ad_types array on all requests', function () { ['banner', 'video', 'native'].forEach(type => { const bidRequest = Object.assign({}, bidRequests[0]); bidRequest.mediaTypes = {}; @@ -108,7 +108,7 @@ describe('xhbAdapter', () => { }); }); - it('should populate the ad_types array on outstream requests', () => { + it('should populate the ad_types array on outstream requests', function () { const bidRequest = Object.assign({}, bidRequests[0]); bidRequest.mediaTypes = {}; bidRequest.mediaTypes.video = {context: 'outstream'}; @@ -119,13 +119,13 @@ describe('xhbAdapter', () => { expect(payload.tags[0].ad_types).to.deep.equal(['video']); }); - it('sends bid request to ENDPOINT via POST', () => { + 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', () => { + it('should attach valid video params to the tag', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -148,7 +148,7 @@ describe('xhbAdapter', () => { }); }); - it('should attach valid user params to the tag', () => { + it('should attach valid user params to the tag', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -171,7 +171,7 @@ describe('xhbAdapter', () => { }); }); - it('should attach native params to the request', () => { + it('should attach native params to the request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -198,7 +198,7 @@ describe('xhbAdapter', () => { }); }); - it('sets minimum native asset params when not provided on adunit', () => { + it('sets minimum native asset params when not provided on adunit', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -217,7 +217,7 @@ describe('xhbAdapter', () => { }); }); - it('does not overwrite native ad unit params with mimimum params', () => { + it('does not overwrite native ad unit params with mimimum params', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -249,7 +249,7 @@ describe('xhbAdapter', () => { }); }); - it('should convert keyword params to proper form and attaches to request', () => { + it('should convert keyword params to proper form and attaches to request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -288,7 +288,7 @@ describe('xhbAdapter', () => { }]); }); - it('should add payment rules to the request', () => { + it('should add payment rules to the request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -305,7 +305,7 @@ describe('xhbAdapter', () => { expect(payload.tags[0].use_pmt_rule).to.equal(true); }); - it('should add gdpr consent information to the request', () => { + it('should add gdpr consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { 'bidderCode': 'xhb', @@ -328,7 +328,7 @@ describe('xhbAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'version': '3.0.0', 'tags': [ @@ -373,7 +373,7 @@ describe('xhbAdapter', () => { ] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { 'requestId': '3db3773286ee59', @@ -397,7 +397,7 @@ describe('xhbAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'version': '0.0.1', 'tags': [{ @@ -413,7 +413,7 @@ describe('xhbAdapter', () => { expect(result.length).to.equal(0); }); - it('handles non-banner media responses', () => { + it('handles non-banner media responses', function () { let response = { 'tags': [{ 'uuid': '84ab500420319d', @@ -437,7 +437,7 @@ describe('xhbAdapter', () => { expect(result[0]).to.have.property('mediaType', 'video'); }); - it('handles native responses', () => { + it('handles native responses', function () { let response1 = deepClone(response); response1.tags[0].ads[0].ad_type = 'native'; response1.tags[0].ads[0].rtb.native = { @@ -471,7 +471,7 @@ describe('xhbAdapter', () => { expect(result[0].native.image.url).to.equal('http://cdn.adnxs.com/img.png'); }); - it('supports configuring outstream renderers', () => { + 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'; diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index a58a10ae153..0e97910bbb7 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -29,17 +29,17 @@ const RESPONSE = { pid: 2222 } -describe('yieldlabBidAdapter', () => { +describe('yieldlabBidAdapter', function () { const adapter = newBidder(spec) - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function') }) }) - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { const request = { 'params': { 'adslotId': '1111', @@ -50,24 +50,24 @@ describe('yieldlabBidAdapter', () => { expect(spec.isBidRequestValid(request)).to.equal(true) }) - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { expect(spec.isBidRequestValid({})).to.equal(false) }) }) - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [REQUEST] const request = spec.buildRequests(bidRequests) - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(request.method).to.equal('GET') }) - it('returns a list of valid requests', () => { + it('returns a list of valid requests', function () { expect(request.validBidRequests).to.eql([REQUEST]) }) - it('passes targeting to bid request', () => { + it('passes targeting to bid request', function () { expect(request.url).to.include('t=key1%3Dvalue1%26key2%3Dvalue2') }) @@ -78,23 +78,23 @@ describe('yieldlabBidAdapter', () => { } }) - it('passes gdpr flag and consent if present', () => { + it('passes gdpr flag and consent if present', function () { expect(gdprRequest.url).to.include('consent=BN5lERiOMYEdiAKAWXEND1AAAAE6DABACMA') expect(gdprRequest.url).to.include('gdpr=true') }) }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { const validRequests = { validBidRequests: [REQUEST] } - it('handles nobid responses', () => { + it('handles nobid responses', function () { expect(spec.interpretResponse({body: {}}, {validBidRequests: []}).length).to.equal(0) expect(spec.interpretResponse({body: []}, {validBidRequests: []}).length).to.equal(0) }) - it('should get correct bid response', () => { + it('should get correct bid response', function () { const result = spec.interpretResponse({body: [RESPONSE]}, validRequests) expect(result[0].requestId).to.equal('2d925f27f5079f') @@ -110,7 +110,7 @@ describe('yieldlabBidAdapter', () => { expect(result[0].ad).to.include('" }); @@ -1034,7 +1034,7 @@ describe('Unit: Prebid Module', function () { assert.ok(spyLogError.calledWith(error), 'expected error was logged'); }); - it('should not render videos', () => { + it('should not render videos', function () { pushBidResponseToAuction({ mediatype: 'video' }); @@ -1070,7 +1070,7 @@ describe('Unit: Prebid Module', function () { assert.deepEqual($$PREBID_GLOBAL$$.getAllWinningBids()[0], adResponse); }); - it('fires billing url if present on s2s bid', () => { + it('fires billing url if present on s2s bid', function () { const burl = 'http://www.example.com/burl'; pushBidResponseToAuction({ ad: '
ad
', @@ -1085,7 +1085,7 @@ describe('Unit: Prebid Module', function () { }); }); - describe('requestBids', () => { + describe('requestBids', function () { let logMessageSpy; let makeRequestsStub; let xhr; @@ -1128,7 +1128,7 @@ describe('Unit: Prebid Module', function () { 'start': 1000 }]; - beforeEach(() => { + beforeEach(function () { logMessageSpy = sinon.spy(utils, 'logMessage'); makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); makeRequestsStub.returns(bidRequests); @@ -1151,7 +1151,7 @@ describe('Unit: Prebid Module', function () { createAuctionStub.returns(auction); }); - afterEach(() => { + afterEach(function () { clock.restore(); adaptermanager.makeBidRequests.restore(); auctionModule.newAuction.restore(); @@ -1159,7 +1159,7 @@ describe('Unit: Prebid Module', function () { xhr.restore(); }); - it('should execute callback after timeout', () => { + it('should execute callback after timeout', function () { let spec = { code: BIDDER_CODE, isBidRequestValid: sinon.stub(), @@ -1193,17 +1193,19 @@ describe('Unit: Prebid Module', function () { }); }) - describe('requestBids', () => { + describe('requestBids', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); }); - afterEach(() => xhr.restore()); + afterEach(function () { + xhr.restore(); + }); var adUnitsBackup; var auctionManagerStub; let logMessageSpy @@ -1217,10 +1219,10 @@ describe('Unit: Prebid Module', function () { }; registerBidder(spec); - describe('part 1', () => { + describe('part 1', function () { let auctionArgs; - beforeEach(() => { + beforeEach(function () { adUnitsBackup = auction.getAdUnits auctionManagerStub = sinon.stub(auctionManager, 'createAuction').callsFake(function() { auctionArgs = arguments[0]; @@ -1229,14 +1231,14 @@ describe('Unit: Prebid Module', function () { logMessageSpy = sinon.spy(utils, 'logMessage'); }); - afterEach(() => { + afterEach(function () { auction.getAdUnits = adUnitsBackup; auctionManager.createAuction.restore(); utils.logMessage.restore(); resetAuction(); }); - it('should log message when adUnits not configured', () => { + it('should log message when adUnits not configured', function () { $$PREBID_GLOBAL$$.adUnits = []; try { $$PREBID_GLOBAL$$.requestBids({}); @@ -1246,7 +1248,7 @@ describe('Unit: Prebid Module', function () { assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); }); - it('should attach transactionIds to ads (or pass through transactionId if it already exists)', () => { + it('should attach transactionIds to ads (or pass through transactionId if it already exists)', function () { $$PREBID_GLOBAL$$.requestBids({ adUnits: [ { @@ -1266,7 +1268,7 @@ describe('Unit: Prebid Module', function () { .and.to.match(/[a-f0-9\-]{36}/i); }); - it('should execute callback immediately if adUnits is empty', () => { + it('should execute callback immediately if adUnits is empty', function () { var bidsBackHandler = function bidsBackHandlerCallback() {}; var spyExecuteCallback = sinon.spy(bidsBackHandler); @@ -1279,7 +1281,7 @@ describe('Unit: Prebid Module', function () { ' empty'); }); - it('should not propagate exceptions from bidsBackHandler', () => { + it('should not propagate exceptions from bidsBackHandler', function () { $$PREBID_GLOBAL$$.adUnits = []; var requestObj = { @@ -1295,12 +1297,12 @@ describe('Unit: Prebid Module', function () { }); }); - describe('multiformat requests', () => { + describe('multiformat requests', function () { let spyCallBids; let createAuctionStub; let adUnits; - beforeEach(() => { + beforeEach(function () { adUnits = [{ code: 'adUnit-code', mediaTypes: { @@ -1321,12 +1323,12 @@ describe('Unit: Prebid Module', function () { createAuctionStub.returns(auction); }) - afterEach(() => { + afterEach(function () { auctionModule.newAuction.restore(); adaptermanager.callBids.restore(); }); - it('bidders that support one of the declared formats are allowed to participate', () => { + it('bidders that support one of the declared formats are allowed to participate', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); sinon.assert.calledOnce(adaptermanager.callBids); @@ -1337,7 +1339,7 @@ describe('Unit: Prebid Module', function () { expect(biddersCalled.length).to.equal(2); }); - it('bidders that do not support one of the declared formats are dropped', () => { + it('bidders that do not support one of the declared formats are dropped', function () { delete adUnits[0].mediaTypes.banner; $$PREBID_GLOBAL$$.requestBids({adUnits}); @@ -1351,12 +1353,12 @@ describe('Unit: Prebid Module', function () { }); }); - describe('part 2', () => { + describe('part 2', function () { let spyCallBids; let createAuctionStub; let adUnits; - before(() => { + before(function () { adUnits = [{ code: 'adUnit-code', sizes: [[300, 250], [300, 600]], @@ -1387,24 +1389,24 @@ describe('Unit: Prebid Module', function () { createAuctionStub.returns(auction); }); - after(() => { + after(function () { auctionModule.newAuction.restore(); }); - beforeEach(() => { + beforeEach(function () { spyCallBids = sinon.spy(adaptermanager, 'callBids'); }) - afterEach(() => { + afterEach(function () { adaptermanager.callBids.restore(); }) - it('should callBids if a native adUnit has all native bidders', () => { + it('should callBids if a native adUnit has all native bidders', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); sinon.assert.calledOnce(adaptermanager.callBids); }); - it('should call callBids function on adaptermanager', () => { + it('should call callBids function on adaptermanager', function () { let adUnits = [{ code: 'adUnit-code', sizes: [[300, 250], [300, 600]], @@ -1416,7 +1418,7 @@ describe('Unit: Prebid Module', function () { assert.ok(spyCallBids.called, 'called adaptermanager.callBids'); }); - it('splits native type to individual native assets', () => { + it('splits native type to individual native assets', function () { let adUnits = [{ code: 'adUnit-code', nativeParams: {type: 'image'}, @@ -1440,7 +1442,7 @@ describe('Unit: Prebid Module', function () { }); }); - describe('part-3', () => { + describe('part-3', function () { let auctionManagerInstance = newAuctionManager(); let auctionManagerStub; let adUnits1 = getAdUnits().filter((adUnit) => { @@ -1500,7 +1502,7 @@ describe('Unit: Prebid Module', function () { adaptermanager.callBids.restore(); }); - it('should not queue bid requests when a previous bid request is in process', () => { + it('should not queue bid requests when a previous bid request is in process', function () { var requestObj1 = { bidsBackHandler: function bidsBackHandlerCallback() {}, timeout: 2000, @@ -1543,8 +1545,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('onEvent', () => { - it('should log an error when handler is not a function', () => { + describe('onEvent', function () { + it('should log an error when handler is not a function', function () { var spyLogError = sinon.spy(utils, 'logError'); var event = 'testEvent'; $$PREBID_GLOBAL$$.onEvent(event); @@ -1553,7 +1555,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); }); - it('should log an error when id provided is not valid for event', () => { + it('should log an error when id provided is not valid for event', function () { var spyLogError = sinon.spy(utils, 'logError'); var event = 'bidWon'; $$PREBID_GLOBAL$$.onEvent(event, Function, 'testId'); @@ -1562,7 +1564,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); }); - it('should call events.on with valid parameters', () => { + it('should call events.on with valid parameters', function () { var spyEventsOn = sinon.spy(events, 'on'); $$PREBID_GLOBAL$$.onEvent('bidWon', Function); assert.ok(spyEventsOn.calledWith('bidWon', Function)); @@ -1570,15 +1572,15 @@ describe('Unit: Prebid Module', function () { }); }); - describe('offEvent', () => { - it('should return when id provided is not valid for event', () => { + describe('offEvent', function () { + it('should return when id provided is not valid for event', function () { var spyEventsOff = sinon.spy(events, 'off'); $$PREBID_GLOBAL$$.offEvent('bidWon', Function, 'testId'); assert.ok(spyEventsOff.notCalled); events.off.restore(); }); - it('should call events.off with valid parameters', () => { + it('should call events.off with valid parameters', function () { var spyEventsOff = sinon.spy(events, 'off'); $$PREBID_GLOBAL$$.offEvent('bidWon', Function); assert.ok(spyEventsOff.calledWith('bidWon', Function)); @@ -1586,8 +1588,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('emit', () => { - it('should be able to emit event without arguments', () => { + describe('emit', function () { + it('should be able to emit event without arguments', function () { var spyEventsEmit = sinon.spy(events, 'emit'); events.emit(CONSTANTS.EVENTS.AUCTION_END); assert.ok(spyEventsEmit.calledWith('auctionEnd')); @@ -1595,15 +1597,15 @@ describe('Unit: Prebid Module', function () { }); }); - describe('registerBidAdapter', () => { - it('should register bidAdaptor with adaptermanager', () => { + describe('registerBidAdapter', function () { + it('should register bidAdaptor with adaptermanager', function () { var registerBidAdapterSpy = sinon.spy(adaptermanager, 'registerBidAdapter'); $$PREBID_GLOBAL$$.registerBidAdapter(Function, 'biddercode'); assert.ok(registerBidAdapterSpy.called, 'called adaptermanager.registerBidAdapter'); adaptermanager.registerBidAdapter.restore(); }); - it('should catch thrown errors', () => { + it('should catch thrown errors', function () { var spyLogError = sinon.spy(utils, 'logError'); var errorObject = { message: 'bidderAdaptor error' }; var bidderAdaptor = sinon.stub().throws(errorObject); @@ -1616,8 +1618,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('createBid', () => { - it('should return a bid object', () => { + describe('createBid', function () { + it('should return a bid object', function () { const statusCode = 1; const bid = $$PREBID_GLOBAL$$.createBid(statusCode); assert.isObject(bid, 'bid is an object'); @@ -1629,8 +1631,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('loadScript', () => { - it('should call adloader.loadScript', () => { + describe('loadScript', function () { + it('should call adloader.loadScript', function () { const loadScriptSpy = sinon.spy(adloader, 'loadScript'); const tagSrc = ''; const callback = Function; @@ -1642,8 +1644,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('aliasBidder', () => { - it('should call adaptermanager.aliasBidder', () => { + describe('aliasBidder', function () { + it('should call adaptermanager.aliasBidder', function () { const aliasBidAdapterSpy = sinon.spy(adaptermanager, 'aliasBidAdapter'); const bidderCode = 'testcode'; const alias = 'testalias'; @@ -1653,7 +1655,7 @@ describe('Unit: Prebid Module', function () { adaptermanager.aliasBidAdapter.restore(); }); - it('should log error when not passed correct arguments', () => { + it('should log error when not passed correct arguments', function () { const logErrorSpy = sinon.spy(utils, 'logError'); const error = 'bidderCode and alias must be passed as arguments'; @@ -1663,8 +1665,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('setPriceGranularity', () => { - it('should log error when not passed granularity', () => { + describe('setPriceGranularity', function () { + it('should log error when not passed granularity', function () { const logErrorSpy = sinon.spy(utils, 'logError'); const error = 'Prebid Error: no value passed to `setPriceGranularity()`'; @@ -1673,7 +1675,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); }); - it('should log error when not passed a valid config object', () => { + it('should log error when not passed a valid config object', function () { const logErrorSpy = sinon.spy(utils, 'logError'); const error = 'Invalid custom price value passed to `setPriceGranularity()`'; const badConfig = { @@ -1696,7 +1698,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); }); - it('should set customPriceBucket with custom config buckets', () => { + it('should set customPriceBucket with custom config buckets', function () { let customPriceBucket = configObj.getConfig('customPriceBucket'); const goodConfig = { 'buckets': [{ @@ -1715,21 +1717,21 @@ describe('Unit: Prebid Module', function () { }); }); - describe('emit event', () => { + describe('emit event', function () { let auctionManagerStub; - beforeEach(() => { + beforeEach(function () { auctionManagerStub = sinon.stub(auctionManager, 'createAuction').callsFake(function() { return auction; }); }); - afterEach(() => { + afterEach(function () { auctionManager.createAuction.restore(); }); }); - describe('removeAdUnit', () => { - it('should remove given adUnit in adUnits array', () => { + describe('removeAdUnit', function () { + it('should remove given adUnit in adUnits array', function () { const adUnit1 = { code: 'adUnit1', bids: [{ @@ -1757,16 +1759,16 @@ describe('Unit: Prebid Module', function () { }); }); - describe('getDealTargeting', () => { - beforeEach(() => { + describe('getDealTargeting', function () { + beforeEach(function () { resetAuction(); }); - afterEach(() => { + afterEach(function () { resetAuction(); }); - it('should truncate deal keys', () => { + it('should truncate deal keys', function () { $$PREBID_GLOBAL$$._bidsReceived = [ { 'bidderCode': 'appnexusDummyName', @@ -1808,23 +1810,23 @@ describe('Unit: Prebid Module', function () { }); }); - describe('getHighestCpm', () => { - after(() => { + describe('getHighestCpm', function () { + after(function () { resetAuction(); }); - it('returns an array containing the highest bid object for the given adUnitCode', () => { + it('returns an array containing the highest bid object for the given adUnitCode', function () { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); expect(highestCpmBids.length).to.equal(1); expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); }); - it('returns an empty array when the given adUnit is not found', () => { + it('returns an empty array when the given adUnit is not found', function () { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/stallone'); expect(highestCpmBids.length).to.equal(0); }); - it('returns an empty array when the given adUnit has no bids', () => { + it('returns an empty array when the given adUnit has no bids', function () { let _bidsReceived = getBidResponses()[0]; _bidsReceived.cpm = 0; auction.getBidsReceived = function() { return _bidsReceived }; @@ -1851,8 +1853,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('markWinningBidAsUsed', () => { - it('marks the bid object as used for the given adUnitCode/adId combination', () => { + describe('markWinningBidAsUsed', function () { + it('marks the bid object as used for the given adUnitCode/adId combination', function () { // make sure the auction has "state" and does not reload the fixtures const adUnitCode = '/19968336/header-bid-tag-0'; const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); @@ -1869,7 +1871,7 @@ describe('Unit: Prebid Module', function () { resetAuction(); }); - it('try and mark the bid object, but fail because we supplied the wrong adId', () => { + it('try and mark the bid object, but fail because we supplied the wrong adId', function () { const adUnitCode = '/19968336/header-bid-tag-0'; const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); auction.getBidsReceived = function() { return bidsReceived.bids }; @@ -1884,7 +1886,7 @@ describe('Unit: Prebid Module', function () { resetAuction(); }); - it('marks the winning bid object as used for the given adUnitCode', () => { + it('marks the winning bid object as used for the given adUnitCode', function () { // make sure the auction has "state" and does not reload the fixtures const adUnitCode = '/19968336/header-bid-tag-0'; const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); @@ -1901,7 +1903,7 @@ describe('Unit: Prebid Module', function () { resetAuction(); }); - it('marks a bid object as used for the given adId', () => { + it('marks a bid object as used for the given adId', function () { // make sure the auction has "state" and does not reload the fixtures const adUnitCode = '/19968336/header-bid-tag-0'; const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); @@ -1919,11 +1921,11 @@ describe('Unit: Prebid Module', function () { }); }); - describe('setTargetingForAst', () => { + describe('setTargetingForAst', function () { let targeting; let auctionManagerInstance; - beforeEach(() => { + beforeEach(function () { resetAuction(); auctionManagerInstance = newAuctionManager(); sinon.stub(auctionManagerInstance, 'getBidsReceived').callsFake(function() { @@ -1938,13 +1940,13 @@ describe('Unit: Prebid Module', function () { targeting = newTargeting(auctionManagerInstance); }); - afterEach(() => { + afterEach(function () { auctionManagerInstance.getBidsReceived.restore(); auctionManagerInstance.getAdUnitCodes.restore(); resetAuction(); }); - it('should set targeting for appnexus apntag object', () => { + it('should set targeting for appnexus apntag object', function () { const bids = auctionManagerInstance.getBidsReceived(); const adUnitCode = '/19968336/header-bid-tag-0'; @@ -1963,7 +1965,7 @@ describe('Unit: Prebid Module', function () { expect(newAdserverTargeting).to.deep.equal(window.apntag.tags[adUnitCode].keywords); }); - it('should not find hb_adid key in lowercase for all bidders', () => { + it('should not find hb_adid key in lowercase for all bidders', function () { const adUnitCode = '/19968336/header-bid-tag-0'; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); targeting.setTargetingForAst(); @@ -2006,17 +2008,17 @@ describe('Unit: Prebid Module', function () { }); }); - describe('getAllPrebidWinningBids', () => { + describe('getAllPrebidWinningBids', function () { let auctionManagerStub; - beforeEach(() => { + beforeEach(function () { auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); }); - afterEach(() => { + afterEach(function () { auctionManagerStub.restore(); }); - it('should return prebid auction winning bids', () => { + it('should return prebid auction winning bids', function () { let bidsReceived = [ createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'targetingSet'}), createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), diff --git a/test/spec/url_spec.js b/test/spec/url_spec.js index cfa1b0c80b4..90047273043 100644 --- a/test/spec/url_spec.js +++ b/test/spec/url_spec.js @@ -1,31 +1,31 @@ import {format, parse} from '../../src/url'; import { expect } from 'chai'; -describe('helpers.url', () => { - describe('parse()', () => { +describe('helpers.url', function () { + describe('parse()', function () { let parsed; - beforeEach(() => { + beforeEach(function () { parsed = parse('http://example.com:3000/pathname/?search=test&foo=bar&bar=foo%26foo%3Dxxx#hash'); }); - it('extracts the protocol', () => { + it('extracts the protocol', function () { expect(parsed).to.have.property('protocol', 'http'); }); - it('extracts the hostname', () => { + it('extracts the hostname', function () { expect(parsed).to.have.property('hostname', 'example.com'); }); - it('extracts the port', () => { + it('extracts the port', function () { expect(parsed).to.have.property('port', 3000); }); - it('extracts the pathname', () => { + it('extracts the pathname', function () { expect(parsed).to.have.property('pathname', '/pathname/'); }); - it('extracts the search query', () => { + it('extracts the search query', function () { expect(parsed).to.have.property('search'); expect(parsed.search).to.eql({ foo: 'xxx', @@ -34,23 +34,23 @@ describe('helpers.url', () => { }); }); - it('extracts the hash', () => { + it('extracts the hash', function () { expect(parsed).to.have.property('hash', 'hash'); }); - it('extracts the host', () => { + it('extracts the host', function () { expect(parsed).to.have.property('host', 'example.com:3000'); }); }); - describe('parse(url, {noDecodeWholeURL: true})', () => { + describe('parse(url, {noDecodeWholeURL: true})', function () { let parsed; - beforeEach(() => { + beforeEach(function () { parsed = parse('http://example.com:3000/pathname/?search=test&foo=bar&bar=foo%26foo%3Dxxx#hash', {noDecodeWholeURL: true}); }); - it('extracts the search query', () => { + it('extracts the search query', function () { expect(parsed).to.have.property('search'); expect(parsed.search).to.eql({ foo: 'bar', @@ -60,8 +60,8 @@ describe('helpers.url', () => { }); }); - describe('format()', () => { - it('formats an object in to a URL', () => { + describe('format()', function () { + it('formats an object in to a URL', function () { expect(format({ protocol: 'http', hostname: 'example.com', @@ -72,21 +72,21 @@ describe('helpers.url', () => { })).to.equal('http://example.com:3000/pathname/?foo=bar&search=test&bar=foo%26foo%3Dxxx#hash'); }); - it('will use defaults for missing properties', () => { + it('will use defaults for missing properties', function () { expect(format({ hostname: 'example.com' })).to.equal('http://example.com'); }); }); - describe('parse(url, {decodeSearchAsString: true})', () => { + describe('parse(url, {decodeSearchAsString: true})', function () { let parsed; - beforeEach(() => { + beforeEach(function () { parsed = parse('http://example.com:3000/pathname/?search=test&foo=bar&bar=foo%26foo%3Dxxx#hash', {decodeSearchAsString: true}); }); - it('extracts the search query', () => { + it('extracts the search query', function () { expect(parsed).to.have.property('search'); expect(parsed.search).to.equal('?search=test&foo=bar&bar=foo&foo=xxx'); }); diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index 60e07441e0c..7040256ccd6 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -4,7 +4,7 @@ import { config } from 'src/config'; const utils = require('../../src/utils'); let { newUserSync } = require('../../src/userSync'); -describe('user sync', () => { +describe('user sync', function () { let triggerPixelStub; let logWarnStub; let timeoutStub; @@ -25,15 +25,15 @@ describe('user sync', () => { }) } let clock; - before(() => { + before(function () { clock = sinon.useFakeTimers(); }); - after(() => { + after(function () { clock.restore(); }); - beforeEach(() => { + beforeEach(function () { triggerPixelStub = sinon.stub(utils, 'triggerPixel'); logWarnStub = sinon.stub(utils, 'logWarn'); shuffleStub = sinon.stub(utils, 'shuffle').callsFake((array) => array.reverse()); @@ -41,7 +41,7 @@ describe('user sync', () => { insertUserSyncIframeStub = sinon.stub(utils, 'insertUserSyncIframe'); }); - afterEach(() => { + afterEach(function () { triggerPixelStub.restore(); logWarnStub.restore(); shuffleStub.restore(); @@ -49,7 +49,7 @@ describe('user sync', () => { insertUserSyncIframeStub.restore(); }); - it('should register and fire a pixel URL', () => { + it('should register and fire a pixel URL', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'testBidder', 'http://example.com'); userSync.syncUsers(); @@ -57,13 +57,13 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com'); }); - it('should clear queue after sync', () => { + it('should clear queue after sync', function () { const userSync = newTestUserSync(); userSync.syncUsers(); expect(triggerPixelStub.callCount).to.equal(0); }); - it('should delay firing a pixel by the expected amount', () => { + it('should delay firing a pixel by the expected amount', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'testBidder', 'http://example.com'); // This implicitly tests cookie and browser support @@ -72,7 +72,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0)).to.not.be.null; }); - it('should register and fires multiple pixel URLs', () => { + it('should register and fires multiple pixel URLs', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.registerSync('image', 'testBidder', 'http://example.com/2'); @@ -84,21 +84,21 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(2)).to.be.null; }); - it('should not register pixel URL since it is not supported', () => { + it('should not register pixel URL since it is not supported', function () { const userSync = newTestUserSync({pixelEnabled: false}); userSync.registerSync('image', 'testBidder', 'http://example.com'); userSync.syncUsers(); expect(triggerPixelStub.getCall(0)).to.be.null; }); - it('should register and load an iframe', () => { + it('should register and load an iframe', function () { const userSync = newTestUserSync({iframeEnabled: true}); userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); userSync.syncUsers(); expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); }); - it('should only trigger syncs once per page', () => { + it('should only trigger syncs once per page', function () { const userSync = newTestUserSync({pixelEnabled: true}); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.syncUsers(); @@ -109,20 +109,20 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(1)).to.be.null; }); - it('should not fire syncs if cookies are not supported', () => { + it('should not fire syncs if cookies are not supported', function () { const userSync = newTestUserSync({pixelEnabled: true}, true); userSync.registerSync('image', 'testBidder', 'http://example.com'); userSync.syncUsers(); expect(triggerPixelStub.getCall(0)).to.be.null; }); - it('should prevent registering invalid type', () => { + it('should prevent registering invalid type', function () { const userSync = newTestUserSync(); userSync.registerSync('invalid', 'testBidder', 'http://example.com'); expect(logWarnStub.getCall(0).args[0]).to.exist; }); - it('should expose the syncUsers method for the publisher to manually trigger syncs', () => { + it('should expose the syncUsers method for the publisher to manually trigger syncs', function () { // triggerUserSyncs should do nothing by default let userSync = newTestUserSync(); let syncUsersSpy = sinon.spy(userSync, 'syncUsers'); @@ -135,7 +135,7 @@ describe('user sync', () => { expect(syncUsersSpy.called).to.be.true; }); - it('should limit the sync per bidder', () => { + it('should limit the sync per bidder', function () { const userSync = newTestUserSync({syncsPerBidder: 2}); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.registerSync('image', 'testBidder', 'http://example.com/2'); @@ -148,7 +148,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(2)).to.be.null; }); - it('should balance out bidder requests', () => { + it('should balance out bidder requests', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); userSync.registerSync('image', 'atestBidder', 'http://example.com/3'); @@ -164,7 +164,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(3)).to.be.null; }); - it('should disable user sync', () => { + it('should disable user sync', function () { const userSync = newTestUserSync({syncEnabled: false}); userSync.registerSync('pixel', 'testBidder', 'http://example.com'); expect(logWarnStub.getCall(0).args[0]).to.exist; @@ -172,7 +172,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0)).to.be.null; }); - it('should only sync enabled bidders', () => { + it('should only sync enabled bidders', function () { const userSync = newTestUserSync({enabledBidders: ['testBidderA']}); userSync.registerSync('image', 'testBidderA', 'http://example.com/1'); userSync.registerSync('image', 'testBidderB', 'http://example.com/2'); @@ -182,7 +182,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(1)).to.be.null; }); - it('should register config set after instantiation', () => { + it('should register config set after instantiation', function () { // start with userSync off const userSync = newTestUserSync({syncEnabled: false}); // turn it on with setConfig() @@ -193,7 +193,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com'); }); - it('should register both image and iframe pixels with filterSettings.all config', () => { + it('should register both image and iframe pixels with filterSettings.all config', function () { const userSync = newTestUserSync({ filterSettings: { all: { @@ -211,7 +211,7 @@ describe('user sync', () => { expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); }); - it('should register iframe and not register image pixels based on filterSettings config', () => { + it('should register iframe and not register image pixels based on filterSettings config', function () { const userSync = newTestUserSync({ filterSettings: { image: { @@ -231,7 +231,7 @@ describe('user sync', () => { expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); }); - it('should throw a warning and default to basic resgistration rules when filterSettings config is invalid', () => { + it('should throw a warning and default to basic resgistration rules when filterSettings config is invalid', function () { // invalid config - passed invalid filter option const userSync1 = newTestUserSync({ filterSettings: { @@ -317,7 +317,7 @@ describe('user sync', () => { expect(insertUserSyncIframeStub.getCall(0)).to.be.null; }); - it('should overwrite logic of deprecated fields when filterSettings is defined', () => { + it('should overwrite logic of deprecated fields when filterSettings is defined', function () { const userSync = newTestUserSync({ pixelsEnabled: false, iframeEnabled: true, diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 454d6ed4136..7891eff5f33 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -639,8 +639,8 @@ describe('Utils', function () { }); }); - describe('getDefinedParams', () => { - it('builds an object consisting of defined params', () => { + describe('getDefinedParams', function () { + it('builds an object consisting of defined params', function () { const adUnit = { mediaType: 'video', comeWithMe: 'ifuwant2live', @@ -658,8 +658,8 @@ describe('Utils', function () { }); }); - describe('deepClone', () => { - it('deep copies objects', () => { + describe('deepClone', function () { + it('deep copies objects', function () { const adUnit = [{ code: 'swan', mediaTypes: {video: {context: 'outstream'}}, @@ -679,7 +679,7 @@ describe('Utils', function () { }); }); - describe('getUserConfiguredParams', () => { + describe('getUserConfiguredParams', function () { const adUnits = [{ code: 'adUnit1', bids: [{ @@ -692,7 +692,7 @@ describe('Utils', function () { }] }]; - it('should return params configured', () => { + it('should return params configured', function () { const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder1'); const expected = [{ key1: 'value1' @@ -700,37 +700,37 @@ describe('Utils', function () { assert.deepEqual(output, expected); }); - it('should return array containting empty object, if bidder present and no params are configured', () => { + it('should return array containting empty object, if bidder present and no params are configured', function () { const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder2'); const expected = [{}]; assert.deepEqual(output, expected); }); - it('should return empty array, if bidder is not present', () => { + it('should return empty array, if bidder is not present', function () { const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder3'); const expected = []; assert.deepEqual(output, expected); }); - it('should return empty array, if adUnit is not present', () => { + it('should return empty array, if adUnit is not present', function () { const output = utils.getUserConfiguredParams(adUnits, 'adUnit2', 'bidder3'); const expected = []; assert.deepEqual(output, expected); }); }); - describe('getTopWindowLocation', () => { + describe('getTopWindowLocation', function () { let sandbox; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); }); - afterEach(() => { + afterEach(function () { sandbox.restore(); }); - it('returns window.location if not in iFrame', () => { + it('returns window.location if not in iFrame', function () { sandbox.stub(utils, 'getWindowLocation').returns({ href: 'https://www.google.com/', ancestorOrigins: {}, @@ -762,7 +762,7 @@ describe('Utils', function () { expect(topWindowLocation.host).to.equal('www.google.com'); }); - it('returns parsed dom string from ancestorOrigins if in iFrame & ancestorOrigins is populated', () => { + it('returns parsed dom string from ancestorOrigins if in iFrame & ancestorOrigins is populated', function () { sandbox.stub(utils, 'getWindowSelf').returns( { self: 'is not same as top' } ); @@ -783,7 +783,7 @@ describe('Utils', function () { expect(topWindowLocation.host).to.be.oneOf(['www.google.com', 'www.google.com:443']); }); - it('returns parsed referrer string if in iFrame but no ancestorOrigins', () => { + it('returns parsed referrer string if in iFrame but no ancestorOrigins', function () { sandbox.stub(utils, 'getWindowSelf').returns( { self: 'is not same as top' } ); @@ -806,8 +806,8 @@ describe('Utils', function () { }); }); - describe('convertCamelToUnderscore', () => { - it('returns converted string value using underscore syntax instead of camelCase', () => { + describe('convertCamelToUnderscore', function () { + it('returns converted string value using underscore syntax instead of camelCase', function () { let var1 = 'placementIdTest'; let test1 = utils.convertCamelToUnderscore(var1); expect(test1).to.equal('placement_id_test'); @@ -818,18 +818,18 @@ describe('Utils', function () { }); }); - describe('getAdUnitSizes', () => { - it('returns an empty response when adUnits is undefined', () => { + describe('getAdUnitSizes', function () { + it('returns an empty response when adUnits is undefined', function () { let sizes = utils.getAdUnitSizes(); expect(sizes).to.be.undefined; }); - it('returns an empty array when invalid data is present in adUnit object', () => { + it('returns an empty array when invalid data is present in adUnit object', function () { let sizes = utils.getAdUnitSizes({ sizes: 300 }); expect(sizes).to.deep.equal([]); }); - it('retuns an array of arrays when reading from adUnit.sizes', () => { + it('retuns an array of arrays when reading from adUnit.sizes', function () { let sizes = utils.getAdUnitSizes({ sizes: [300, 250] }); expect(sizes).to.deep.equal([[300, 250]]); @@ -837,7 +837,7 @@ describe('Utils', function () { expect(sizes).to.deep.equal([[300, 250], [300, 600]]); }); - it('returns an array of arrays when reading from adUnit.mediaTypes.banner.sizes', () => { + it('returns an array of arrays when reading from adUnit.mediaTypes.banner.sizes', function () { let sizes = utils.getAdUnitSizes({ mediaTypes: { banner: { sizes: [300, 250] } } }); expect(sizes).to.deep.equal([[300, 250]]); diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index b853da708fc..c9052fbbf9d 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -5,7 +5,7 @@ import { config } from 'src/config'; const should = chai.should(); -describe('The video cache', () => { +describe('The video cache', function () { function assertError(callbackSpy) { callbackSpy.calledOnce.should.equal(true); callbackSpy.firstCall.args[0].should.be.an('error'); @@ -16,19 +16,21 @@ describe('The video cache', () => { should.not.exist(callbackSpy.firstCall.args[0]); } - describe('when the cache server is unreachable', () => { + describe('when the cache server is unreachable', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = (request) => requests.push(request); }); - afterEach(() => xhr.restore()); + afterEach(function () { + xhr.restore(); + }); - it('should execute the callback with an error when store() is called', () => { + it('should execute the callback with an error when store() is called', function () { const callback = sinon.spy(); store([ { vastUrl: 'my-mock-url.com' } ], callback); @@ -41,11 +43,11 @@ describe('The video cache', () => { }); }); - describe('when the cache server is available', () => { + describe('when the cache server is available', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = (request) => requests.push(request); @@ -56,12 +58,12 @@ describe('The video cache', () => { }) }); - afterEach(() => { + afterEach(function () { xhr.restore(); config.resetConfig(); }); - it('should execute the callback with a successful result when store() is called', () => { + it('should execute the callback with a successful result when store() is called', function () { const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; const callback = fakeServerCall( { vastUrl: 'my-mock-url.com' }, @@ -71,7 +73,7 @@ describe('The video cache', () => { callback.firstCall.args[1].should.deep.equal([{ uuid: uuid }]); }); - it('should execute the callback with an error if the cache server response has no responses property', () => { + it('should execute the callback with an error if the cache server response has no responses property', function () { const callback = fakeServerCall( { vastUrl: 'my-mock-url.com' }, '{"broken":[{"uuid":"c488b101-af3e-4a99-b538-00423e5a3371"}]}'); @@ -79,7 +81,7 @@ describe('The video cache', () => { callback.firstCall.args[1].should.deep.equal([]); }); - it('should execute the callback with an error if the cache server responds with malformed JSON', () => { + it('should execute the callback with an error if the cache server responds with malformed JSON', function () { const callback = fakeServerCall( { vastUrl: 'my-mock-url.com' }, 'Not JSON here'); @@ -87,7 +89,7 @@ describe('The video cache', () => { callback.firstCall.args[1].should.deep.equal([]); }); - it('should make the expected request when store() is called on an ad with a vastUrl', () => { + it('should make the expected request when store() is called on an ad with a vastUrl', function () { const expectedValue = ` @@ -101,7 +103,7 @@ describe('The video cache', () => { assertRequestMade({ vastUrl: 'my-mock-url.com' }, expectedValue) }); - it('should make the expected request when store() is called on an ad with a vastUrl and a vastImpUrl', () => { + it('should make the expected request when store() is called on an ad with a vastUrl and a vastImpUrl', function () { const expectedValue = ` @@ -115,7 +117,7 @@ describe('The video cache', () => { assertRequestMade({ vastUrl: 'my-mock-url.com', vastImpUrl: 'imptracker.com' }, expectedValue) }); - it('should make the expected request when store() is called on an ad with vastXml', () => { + it('should make the expected request when store() is called on an ad with vastXml', function () { const vastXml = ''; assertRequestMade({ vastXml: vastXml }, vastXml); }); @@ -150,8 +152,8 @@ describe('The video cache', () => { }); }); -describe('The getCache function', () => { - beforeEach(() => { +describe('The getCache function', function () { + beforeEach(function () { config.setConfig({ cache: { url: 'https://prebid.adnxs.com/pbc/v1/cache' @@ -159,11 +161,11 @@ describe('The getCache function', () => { }) }); - afterEach(() => { + afterEach(function () { config.resetConfig(); }); - it('should return the expected URL', () => { + it('should return the expected URL', function () { const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; const url = getCacheUrl(uuid); url.should.equal(`https://prebid.adnxs.com/pbc/v1/cache?uuid=${uuid}`); diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js index 06cd653f444..3d6ed04ffae 100644 --- a/test/spec/video_spec.js +++ b/test/spec/video_spec.js @@ -1,7 +1,7 @@ import { isValidVideoBid } from 'src/video'; -describe('video.js', () => { - it('validates valid instream bids', () => { +describe('video.js', function () { + it('validates valid instream bids', function () { const bid = { adId: '123abc', vastUrl: 'http://www.example.com/vastUrl' @@ -19,7 +19,7 @@ describe('video.js', () => { expect(valid).to.equal(true); }); - it('catches invalid instream bids', () => { + it('catches invalid instream bids', function () { const bid = { adId: '123abc' }; @@ -36,7 +36,7 @@ describe('video.js', () => { expect(valid).to.equal(false); }); - it('catches invalid bids when prebid-cache is disabled', () => { + it('catches invalid bids when prebid-cache is disabled', function () { const bidRequests = [{ bids: [{ bidder: 'vastOnlyVideoBidder', @@ -49,7 +49,7 @@ describe('video.js', () => { expect(valid).to.equal(false); }); - it('validates valid outstream bids', () => { + it('validates valid outstream bids', function () { const bid = { adId: '123abc', renderer: { @@ -70,7 +70,7 @@ describe('video.js', () => { expect(valid).to.equal(true); }); - it('catches invalid outstream bids', () => { + it('catches invalid outstream bids', function () { const bid = { adId: '123abc' }; From 890315bfa9a463ab52867e580d2fabc5261ff625 Mon Sep 17 00:00:00 2001 From: rachelrj Date: Fri, 31 Aug 2018 10:32:54 -0600 Subject: [PATCH 0662/1594] Sovrn add user sync (#3029) --- modules/sovrnBidAdapter.js | 22 +++++++- test/spec/modules/sovrnBidAdapter_spec.js | 62 +++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 337f2ec2d00..4f1eb298794 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -55,7 +55,7 @@ export const spec = { } let url = `//ap.lijit.com/rtb/bid?` + - `src=${REPO_AND_VERSION}`; + `src=${REPO_AND_VERSION}`; if (iv) url += `&iv=${iv}`; return { @@ -95,7 +95,25 @@ export const spec = { }); } return sovrnBidResponses; - } + }, + + getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + if (serverResponses && serverResponses.length !== 0 && syncOptions.iframeEnabled) { + let iidArr = serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.iid) + .map(rsp => { return rsp.body.ext.iid }); + let consentString = ''; + if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { + consentString = gdprConsent.consentString + } + if (iidArr[0]) { + return [{ + type: 'iframe', + url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, + }]; + } + } + return []; + }, }; registerBidder(spec); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 0f1c0d43396..22c93505ecf 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -221,4 +221,66 @@ describe('sovrnBidAdapter', function() { expect(result.length).to.equal(0); }); }); + + describe('getUserSyncs ', () => { + let syncOptions = {iframeEnabled: true, pixelEnabled: true}; + let iframeDisabledSyncOptions = {iframeEnabled: false, pixelEnabled: true}; + let serverResponse = [ + { + 'body': { + 'id': '546956d68c757f', + 'seatbid': [ + { + '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_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 + } + }, + 'headers': {} + } + ]; + it('should return if iid present on server response & iframe syncs enabled', () => { + let expectedReturnStatement = [ + { + 'type': 'iframe', + 'url': '//ap.lijit.com/beacon?informer=13487408&gdpr_consent=', + } + ]; + let returnStatement = spec.getUserSyncs(syncOptions, serverResponse); + expect(returnStatement[0]).to.deep.equal(expectedReturnStatement[0]); + }); + + it('should not return if iid missing on server response', () => { + let returnStatement = spec.getUserSyncs(syncOptions, []); + expect(returnStatement).to.be.empty; + }); + + it('should not return if iframe syncs disabled', () => { + let returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse); + expect(returnStatement).to.be.empty; + }); + }); }); From edc9d436542116c11dbab04fd4334d02a1a7aef1 Mon Sep 17 00:00:00 2001 From: Eric <41298164+ericyld@users.noreply.github.com> Date: Tue, 4 Sep 2018 21:19:04 +0300 Subject: [PATCH 0663/1594] YieldNexus Bid Adapter v1 (#2855) * YieldNexus Bid Adapter v1 * Apply code-review changes requested by @jsneker Removed redundant decration of 'onTik which does nothing. Import banner & video constants instead of hard-coding them. Remove usage of "config.getConfig('pageurl')". Also updated the "spid" to 1249. * Remove unused 'config' import * Update demo account IDs for both banner & video * Add video renderer support * Fix unit test checking url * Fix code linting errors * Add missing import statement --- modules/yieldNexusBidAdapter.js | 193 +++++++++++ modules/yieldNexusBidAdapter.md | 53 +++ .../spec/modules/yieldNexusBidAdapter_spec.js | 310 ++++++++++++++++++ 3 files changed, 556 insertions(+) create mode 100644 modules/yieldNexusBidAdapter.js create mode 100644 modules/yieldNexusBidAdapter.md create mode 100644 test/spec/modules/yieldNexusBidAdapter_spec.js diff --git a/modules/yieldNexusBidAdapter.js b/modules/yieldNexusBidAdapter.js new file mode 100644 index 00000000000..975f335b9a7 --- /dev/null +++ b/modules/yieldNexusBidAdapter.js @@ -0,0 +1,193 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; +import { Renderer } from 'src/Renderer'; + +const pixKey = 'utrk'; + +function startsWith(str, search) { + return str.substr(0, search.length) === search; +} + +export const spec = { + code: 'yieldnexus', + aliases: [], + supportedMediaTypes: [BANNER, VIDEO], + + isBidRequestValid: function(bid) { + if (!bid.params.spid) { + return false; + } else if (typeof bid.params.spid !== 'string') { + return false; + } + return (typeof bid.params.instl === 'undefined' || bid.params.instl === 0 || bid.params.instl === 1) && + (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && + (typeof bid.params['protocols'] === 'undefined' || Array.isArray(bid.params['protocols'])) && + (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number'); + }, + + buildRequests: function(validBidRequests, bidderRequest) { + return validBidRequests.map(bidRequest => { + let referrer = ''; + try { + referrer = window.top.document.referrer; + } catch (e) { + try { + referrer = window.document.referrer; + } catch (e) { + } + } + const url = utils.getTopWindowUrl(); + const domainStart = url.indexOf('://') + 3; + const req = { + id: bidRequest.auctionId, + site: { + domain: url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)), + page: url, + ref: referrer + }, + device: { + ua: navigator.userAgent + }, + imp: [], + ext: {} + }; + if (bidderRequest && bidderRequest.gdprConsent) { + req.ext.gdpr_consent = { + consent_string: bidderRequest.gdprConsent.consentString, + consent_required: bidderRequest.gdprConsent.gdprApplies + }; + } + let topFrame; + try { + topFrame = window.top === window ? 1 : 0; + } catch (e) { + topFrame = 0; + } + const imp = { + id: bidRequest.transactionId, + instl: bidRequest.params.instl === 1 ? 1 : 0, + tagid: bidRequest.adUnitCode, + bidfloor: bidRequest.params.bidfloor || 0, + bidfloorcur: 'USD', + secure: startsWith(utils.getTopWindowUrl().toLowerCase(), 'http://') ? 0 : 1 + }; + if (!bidRequest.mediaTypes || bidRequest.mediaTypes.banner) { + imp.banner = { + w: bidRequest.sizes.length ? bidRequest.sizes[0][0] : 300, + h: bidRequest.sizes.length ? bidRequest.sizes[0][1] : 250, + pos: bidRequest.params.pos || 0, + topframe: topFrame + }; + } else if (bidRequest.mediaTypes.video) { + imp.video = { + w: bidRequest.sizes.length ? bidRequest.sizes[0][0] : 300, + h: bidRequest.sizes.length ? bidRequest.sizes[0][1] : 250, + protocols: bidRequest.params.protocols || [1, 2, 3, 4, 5, 6], + pos: bidRequest.params.pos || 0, + topframe: topFrame + }; + } else { + return; + } + req.imp.push(imp); + return { + method: 'POST', + url: `https://ssp.ynxs.io/r/${bidRequest.params.spid}/bidr?bidder=prebid&rformat=open_rtb&reqformat=rtb_json` + (bidRequest.params.query ? '&' + bidRequest.params.query : ''), + data: req, + bidRequest + }; + }); + }, + + interpretResponse: function(serverResponse, bidRequest) { + const outBids = []; + if (serverResponse && serverResponse.body) { + const bids = serverResponse.body.seatbid.reduce((acc, seatBid) => acc.concat(seatBid.bid), []); + bids.forEach(bid => { + const outBid = { + requestId: bidRequest.bidRequest.bidId, + cpm: bid.price, + width: bid.w, + height: bid.h, + ttl: 15 * 60, + creativeId: bid.crid, + netRevenue: true, + currency: bid.cur || serverResponse.body.cur + }; + if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { + outBids.push(Object.assign({}, outBid, { mediaType: 'banner', ad: bid.adm })); + } else if (bidRequest.bidRequest.mediaTypes.video) { + const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); + outBids.push(Object.assign({}, outBid, { + mediaType: 'video', + vastUrl: bid.ext.vast_url, + vastXml: bid.adm, + renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined + })); + } + }); + } + return outBids; + }, + + getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + const syncs = []; + const gdprApplies = gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : false; + const suffix = gdprApplies ? 'gc=' + encodeURIComponent(gdprConsent.consentString) : 'gc=missing'; + serverResponses.forEach(resp => { + if (resp.body) { + const bidResponse = resp.body; + if (bidResponse.ext && Array.isArray(bidResponse.ext[pixKey])) { + bidResponse.ext[pixKey].forEach(pixel => syncs.push({ type: pixel.type, url: pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix) })); + } + if (Array.isArray(bidResponse.seatbid)) { + bidResponse.seatbid.forEach(seatBid => { + if (Array.isArray(seatBid.bid)) { + seatBid.bid.forEach(bid => { + if (bid.ext && Array.isArray(bid.ext[pixKey])) { + bid.ext[pixKey].forEach(pixel => syncs.push({ type: pixel.type, url: pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix) })); + } + }); + } + }); + } + } + }); + return syncs; + } +}; + +function newRenderer(bidRequest, bid, rendererOptions = {}) { + let rendererUrl = '//s.gambid.io/video/latest/renderer.js'; + if (bid.ext && bid.ext.renderer_url) { + rendererUrl = bid.ext.renderer_url; + } + if (bidRequest.params && bidRequest.params.rendererUrl) { + rendererUrl = bidRequest.params.rendererUrl; + } + const renderer = Renderer.install({ url: rendererUrl, config: rendererOptions, loaded: false }); + renderer.setRender(renderOutstream); + return renderer; +} + +function renderOutstream(bid) { + bid.renderer.push(() => { + window[ 'GambidPlayer' ].renderAd({ + id: bid.adUnitCode + '/' + bid.adId, + debug: window.location.href.indexOf('pbjsDebug') >= 0, + placement: document.getElementById(bid.adUnitCode), + width: bid.width, + height: bid.height, + events: { + ALL_ADS_COMPLETED: () => window.setTimeout(() => { + window[ 'GambidPlayer' ].removeAd(bid.adUnitCode + '/' + bid.adId); + }, 300) + }, + vastUrl: bid.vastUrl, + vastXml: bid.vastXml + }); + }); +} + +registerBidder(spec); diff --git a/modules/yieldNexusBidAdapter.md b/modules/yieldNexusBidAdapter.md new file mode 100644 index 00000000000..675e8948a3e --- /dev/null +++ b/modules/yieldNexusBidAdapter.md @@ -0,0 +1,53 @@ +# Overview + +``` +Module Name: YieldNexus Bid Adapter +Module Type: Bidder Adapter +Maintainer: rtbops@yieldnexus.com +``` + +# Description + +Adds support to query the YieldNexus platform for bids. The YieldNexus platform supports banners & video. + +Only one parameter is required: `spid`, which provides your YieldNexus account number. + +# Test Parameters +``` +var adUnits = [ + // Banner: + { + code: 'banner-ad-unit', + sizes: [[300, 250]], + bids: [{ + bidder: 'yieldnexus', + params: { + spid: '1253', // your supply ID in your YieldNexus dashboard + bidfloor: 0.03, // an optional custom bid floor + adpos: 1, // ad position on the page (optional) + instl: 0 // interstitial placement? (0 or 1, optional) + } + }] + }, + // Outstream video: + { + code: 'video-ad-unit', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [ { + bidder: 'yieldnexus', + params: { + spid: '1254', // your supply ID in your YieldNexus dashboard + bidfloor: 0.03, // an optional custom bid floor + adpos: 1, // ad position on the page (optional) + instl: 0 // interstitial placement? (0 or 1, optional) + } + }] + } +]; +``` diff --git a/test/spec/modules/yieldNexusBidAdapter_spec.js b/test/spec/modules/yieldNexusBidAdapter_spec.js new file mode 100644 index 00000000000..b966d890e7a --- /dev/null +++ b/test/spec/modules/yieldNexusBidAdapter_spec.js @@ -0,0 +1,310 @@ +import { expect } from 'chai'; +import { spec } from 'modules/yieldNexusBidAdapter'; +import * as utils from 'src/utils'; + +const spid = '123'; + +describe('YieldNexusAdapter', () => { + describe('isBidRequestValid', () => { + it('should validate supply', () => { + expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: 123 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); + }); + it('should validate bid floor', () => { + expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // bidfloor has a default + expect(spec.isBidRequestValid({ params: { spid: '123', bidfloor: '123' } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123', bidfloor: 0.1 } })).to.equal(true); + }); + it('should validate adpos', () => { + expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // adpos has a default + expect(spec.isBidRequestValid({ params: { spid: '123', adpos: '123' } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123', adpos: 0.1 } })).to.equal(true); + }); + it('should validate instl', () => { + expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // adpos has a default + expect(spec.isBidRequestValid({ params: { spid: '123', instl: '123' } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123', instl: -1 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123', instl: 0 } })).to.equal(true); + expect(spec.isBidRequestValid({ params: { spid: '123', instl: 1 } })).to.equal(true); + expect(spec.isBidRequestValid({ params: { spid: '123', instl: 2 } })).to.equal(false); + }); + }); + describe('buildRequests', () => { + const bidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': 'fdkhjg3s7ahjja', + 'mediaTypes': { + banner: {} + }, + 'params': { spid }, + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ] + }; + + it('returns an array', () => { + let response; + + response = spec.buildRequests([]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + + response = spec.buildRequests([ bidRequest ]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(1); + + const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'a' }); + const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'b' }); + response = spec.buildRequests([adUnit1, adUnit2]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + }); + + it('uses yieldnexus dns', () => { + const response = spec.buildRequests([ bidRequest ])[ 0 ]; + expect(response.method).to.equal('POST'); + expect(response.url).to.match(new RegExp(`^https://ssp\\.ynxs\\.io/r/${spid}/bidr\\?bidder=prebid&rformat=open_rtb&reqformat=rtb_json$`, 'g')); + expect(response.data.id).to.equal(bidRequest.auctionId); + }); + + it('builds request correctly', () => { + let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); + + let response; + response = spec.buildRequests([ bidRequest ])[ 0 ]; + expect(response.data.site.domain).to.equal('www.test.com'); + expect(response.data.site.page).to.equal('http://www.test.com/page.html'); + expect(response.data.site.ref).to.equal(''); + expect(response.data.imp.length).to.equal(1); + expect(response.data.imp[ 0 ].id).to.equal(bidRequest.transactionId); + expect(response.data.imp[ 0 ].instl).to.equal(0); + expect(response.data.imp[ 0 ].tagid).to.equal(bidRequest.adUnitCode); + expect(response.data.imp[ 0 ].bidfloor).to.equal(0); + expect(response.data.imp[ 0 ].bidfloorcur).to.equal('USD'); + + const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); + bidRequestWithInstlEquals1.params.instl = 1; + response = spec.buildRequests([ bidRequestWithInstlEquals1 ])[ 0 ]; + expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals1.params.instl); + + const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); + bidRequestWithInstlEquals0.params.instl = 1; + response = spec.buildRequests([ bidRequestWithInstlEquals0 ])[ 0 ]; + expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals0.params.instl); + + const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); + bidRequestWithBidfloorEquals1.params.bidfloor = 1; + response = spec.buildRequests([ bidRequestWithBidfloorEquals1 ])[ 0 ]; + expect(response.data.imp[ 0 ].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); + + stub.restore(); + }); + + it('builds request banner object correctly', () => { + let response; + + const bidRequestWithBanner = utils.deepClone(bidRequest); + bidRequestWithBanner.mediaTypes = { + banner: { + sizes: [ [ 300, 250 ], [ 120, 600 ] ] + } + }; + + response = spec.buildRequests([ bidRequestWithBanner ])[ 0 ]; + expect(response.data.imp[ 0 ].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[ 0 ][ 0 ]); + expect(response.data.imp[ 0 ].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[ 0 ][ 1 ]); + expect(response.data.imp[ 0 ].banner.pos).to.equal(0); + expect(response.data.imp[ 0 ].banner.topframe).to.equal(0); + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); + bidRequestWithPosEquals1.params.pos = 1; + response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; + expect(response.data.imp[ 0 ].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); + }); + + it('builds request video object correctly', () => { + let response; + + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes = { + video: { + sizes: [ [ 300, 250 ], [ 120, 600 ] ] + } + }; + + response = spec.buildRequests([ bidRequestWithVideo ])[ 0 ]; + expect(response.data.imp[ 0 ].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[ 0 ][ 0 ]); + expect(response.data.imp[ 0 ].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[ 0 ][ 1 ]); + expect(response.data.imp[ 0 ].video.pos).to.equal(0); + expect(response.data.imp[ 0 ].video.topframe).to.equal(0); + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.params.pos = 1; + response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; + expect(response.data.imp[ 0 ].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); + }); + }); + describe('interpretResponse', () => { + const bannerBidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': 'fdkhjg3s7ahjja', + 'mediaTypes': { + banner: {} + }, + 'params': { + 'spid': spid + }, + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], + 'bidId': '111' + }; + const videoBidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': 'fdkhjg3s7ahjja', + 'mediaTypes': { + video: {} + }, + 'params': { + 'spid': spid + }, + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], + 'bidId': '111' + }; + const rtbResponse = { + 'id': 'imp_5b05b9fde4b09084267a556f', + 'bidid': 'imp_5b05b9fde4b09084267a556f', + 'cur': 'USD', + 'ext': { + 'utrk': [ + { 'type': 'iframe', 'url': '//ssp.ynxs.io/user/sync/1' }, + { 'type': 'image', 'url': '//ssp.ynxs.io/user/sync/2' } + ] + }, + 'seatbid': [ + { + 'seat': 'testSeatBidA', + 'bid': [ + { + 'id': '0', + 'impid': '1', + 'price': 2.016, + 'adm': '', + 'adomain': [ 'nike.com' ], + 'h': 600, + 'w': 120, + 'ext': { + 'vast_url': 'http://vast.tag.com', + 'utrk': [ + { 'type': 'iframe', 'url': '//pix.usersync.io/user-sync' } + ] + } + } + ] + }, + { + 'seat': 'testSeatBidB', + 'bid': [ + { + 'id': '1', + 'impid': '1', + 'price': 3, + 'adid': '542jlhdfd2112jnjf3x', + 'adm': '', + 'adomain': [ 'adidas.com' ], + 'h': 250, + 'w': 300, + 'ext': { + 'utrk': [ + { 'type': 'image', 'url': '//pix.usersync.io/user-sync' } + ] + } + } + ] + } + ] + }; + it('fails gracefully on empty response body', () => { + let response; + + response = spec.interpretResponse(undefined, { bidRequest: bannerBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + + response = spec.interpretResponse({}, { bidRequest: bannerBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + }); + it('collects banner bids', () => { + const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: bannerBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + + const ad0 = response[ 0 ], ad1 = response[ 1 ]; + expect(ad0.requestId).to.equal(bannerBidRequest.bidId); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].h); + expect(ad0.ttl).to.equal(15 * 60); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].crid); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); + expect(ad0.vastXml).to.be.an('undefined'); + + expect(ad1.requestId).to.equal(bannerBidRequest.bidId); + expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); + expect(ad1.width).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].w); + expect(ad1.height).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].h); + expect(ad1.ttl).to.equal(15 * 60); + expect(ad1.creativeId).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].crid); + expect(ad1.netRevenue).to.equal(true); + expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad1.ad).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + expect(ad1.vastXml).to.be.an('undefined'); + + // expect(ad1.ad).to.be.an('undefined'); + // expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + }); + it('collects video bids', () => { + const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: videoBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + + const ad0 = response[ 0 ], ad1 = response[ 1 ]; + expect(ad0.requestId).to.equal(videoBidRequest.bidId); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].h); + expect(ad0.ttl).to.equal(15 * 60); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].crid); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.be.an('undefined'); + expect(ad0.vastXml).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); + expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.vast_url); + + expect(ad1.requestId).to.equal(videoBidRequest.bidId); + expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); + expect(ad1.width).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].w); + expect(ad1.height).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].h); + expect(ad1.ttl).to.equal(15 * 60); + expect(ad1.creativeId).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].crid); + expect(ad1.netRevenue).to.equal(true); + expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad1.ad).to.be.an('undefined'); + expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.vast_url); + }); + it('applies user-syncs', () => { + const response = spec.getUserSyncs({}, [ { body: rtbResponse } ]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(4); + expect(response[ 0 ].type).to.equal(rtbResponse.ext.utrk[ 0 ].type); + expect(response[ 0 ].url).to.equal(rtbResponse.ext.utrk[ 0 ].url + '?gc=missing'); + expect(response[ 1 ].type).to.equal(rtbResponse.ext.utrk[ 1 ].type); + expect(response[ 1 ].url).to.equal(rtbResponse.ext.utrk[ 1 ].url + '?gc=missing'); + expect(response[ 2 ].type).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.utrk[ 0 ].type); + expect(response[ 2 ].url).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.utrk[ 0 ].url + '?gc=missing'); + expect(response[ 3 ].type).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.utrk[ 0 ].type); + expect(response[ 3 ].url).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.utrk[ 0 ].url + '?gc=missing'); + }); + }); +}); From ce3fe7dbc1dda8392eebacb861f230dad6798d15 Mon Sep 17 00:00:00 2001 From: Nick Le Mouton Date: Wed, 5 Sep 2018 07:17:59 +1200 Subject: [PATCH 0664/1594] Fix utils problem with convertTypes (#3033) --- modules/pulsepointBidAdapter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 7a05253e339..1a1abfb2fdd 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -1,5 +1,5 @@ /* eslint dot-notation:0, quote-props:0 */ -import {logError, getTopWindowLocation} from 'src/utils'; +import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; const NATIVE_DEFAULTS = { @@ -237,7 +237,7 @@ function site(bidderRequest) { id: pubId.toString(), }, ref: referrer(), - page: getTopWindowLocation().href, + page: utils.getTopWindowLocation().href, } } return null; @@ -293,7 +293,7 @@ function parse(rawResponse) { return JSON.parse(rawResponse); } } catch (ex) { - logError('pulsepointLite.safeParse', 'ERROR', ex); + utils.logError('pulsepointLite.safeParse', 'ERROR', ex); } return null; } From ba5ea0a7dc23492bf1f203e4bc71335989ea1ffc Mon Sep 17 00:00:00 2001 From: dkharton Date: Tue, 4 Sep 2018 12:24:57 -0700 Subject: [PATCH 0665/1594] Explicitly set ajax() XHR to asynchronous. (#3038) --- src/ajax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ajax.js b/src/ajax.js index 1916f4ea080..d8b0712594d 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -66,7 +66,7 @@ export function ajaxBuilder(timeout = 3000, {request, done} = {}) { url = formatURL(urlInfo); } - x.open(method, url); + x.open(method, url, true); // IE needs timoeut to be set after open - see #1410 // Disabled timeout temporarily to avoid xhr failed requests. https://github.com/prebid/Prebid.js/issues/2648 if (!config.getConfig('disableAjaxTimeout')) { From 0bdeb45abfa20e5daaeaa5a51061344d750ba786 Mon Sep 17 00:00:00 2001 From: Steve Alliance Date: Tue, 4 Sep 2018 15:33:48 -0400 Subject: [PATCH 0666/1594] update user consent object that was send to DMX (#3023) * adding DMX test @97%, two files added one updated * Update districtm_spec.js * Update districtmDMX.js * adding all districtm needed file * remove legacy file * remove typo || 0 in the test method * force default to return a valid width and height * update unit test code for failing test * changed class for an object * remove package-lock.json * change file name for dmx adapter * renamed files * restaure package-lock.json * update to last package-lock state * update gdpr user consent * fix sizes issue * Documentation updates Adding the readme.md info * update file name and update unit testing import file location --- ...idAdapter.js => districtmDMXBidAdapter.js} | 8 +- modules/districtmDmxBidAdapter.md | 102 ++++++++++++++++-- .../modules/districtmDmxBidAdapter_spec.js | 2 +- 3 files changed, 99 insertions(+), 13 deletions(-) rename modules/{districtmDmxBidAdapter.js => districtmDMXBidAdapter.js} (94%) diff --git a/modules/districtmDmxBidAdapter.js b/modules/districtmDMXBidAdapter.js similarity index 94% rename from modules/districtmDmxBidAdapter.js rename to modules/districtmDMXBidAdapter.js index 3ec0b72649e..51ceedfc470 100644 --- a/modules/districtmDmxBidAdapter.js +++ b/modules/districtmDMXBidAdapter.js @@ -76,9 +76,9 @@ export const spec = { dmxRequest.regs = {}; dmxRequest.regs.ext = {}; dmxRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; - if (dmxRequest.regs.ext.gdpr) { - dmxRequest.regs.ext.consent = bidderRequest.gdprConsent.consentString; - } + dmxRequest.user = {}; + dmxRequest.user.ext = {}; + dmxRequest.user.ext.consent = bidderRequest.gdprConsent.consentString; } let tosendtags = bidRequest.map(dmx => { var obj = {}; @@ -91,7 +91,7 @@ export const spec = { h: dmx.sizes[0][1] || 0, format: dmx.sizes.map(s => { return {w: s[0], h: s[1]}; - }) + }).filter(obj => typeof obj.w === 'number' && typeof obj.h === 'number') }; return obj; }); diff --git a/modules/districtmDmxBidAdapter.md b/modules/districtmDmxBidAdapter.md index a096029963c..2859bcfa19d 100644 --- a/modules/districtmDmxBidAdapter.md +++ b/modules/districtmDmxBidAdapter.md @@ -1,23 +1,105 @@ +``` +Module Name: district m Bid Adapter +Module Type: Bidder Adapter +Maintainer: Steve Alliance (steve@districtm.net) +``` + # Overview +The `districtmDmxAdapter` module allows publishers to include DMX Exchange demand using Prebid 1.0+. + +## Attributes + +* Single Request +* Multi-Size Support +* GDPR Compliant +* Bids returned in **NET** + + ## Media Types + +* Banner + +## Bidder Parameters + +| Key | Scope | Type | Description +| --- | --- | --- | --- +| dmxid | Mandatory | Integer | Unique identifier of the placement, dmxid can be obtained in the district m Boost platform. +| memberid | Mandatory | Integer | Unique identifier for your account, memberid can be obtained in the district m Boost platform. + +# Ad Unit Configuration Example + +```javascript + var adUnits = [{ + code: 'div-gpt-ad-1460505748561-0', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + }, + bids: [{ + bidder: 'districtmDMX', + params: { + dmxid: 100001, + memberid: 100003 + } + }] + }]; +``` + + +# Quick Start Guide + +###### 1. Including the `districtmDmxAdapter` in your build process. + +Add the adapter as an argument to gulp build. + +``` +gulp build --modules=districtmDmxAdapter,ixBidAdapter,appnexusBidAdapter +``` + +*Adding `"districtmDmxAdapter"` as an entry in a JSON file with your bidders is also acceptable.* + +``` +[ + "districtmDmxAdapter", + "ixBidAdapter", + "appnexusBidAdapter" +] +``` + +*Proceed to build with the JSON file.* + ``` -Module Name: DistrictM Bid Adapter -Module Type: Bidder Adapter -Maintainer: steve@districtm.net +gulp build --modules=bidderModules.json ``` -# Description +###### 2. Configure the ad unit object -Adapter that connects to DistrictM's demand sources. -This version only support banner +Once Prebid is ready you may use the below example to create the adUnits object and begin building the configuration. -# Test Parameters +```javascript +var adUnits = [{ + code: 'div-gpt-ad-1460505748561-0', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600], [728, 90]], + } + }, + bids: [] + } +]; ``` + +###### 3. Add the bidder + +Our demand and adapter supports multiple sizes per placement, as such a single dmxid may be used for all sizes of a single domain. + +```javascript var adUnits = [{ code: 'div-gpt-ad-1460505748561-0', mediaTypes: { banner: { - sizes: [[300, 250], [300,600]], + sizes: [[300, 250], [300, 600], [728, 90]], } }, bids: [{ @@ -29,3 +111,7 @@ This version only support banner }] }]; ``` + +###### 4. Implementation Checking + +Once the bidder is live in your Prebid configuration you may confirm it is making requests to our end point by looking for requests to `https://dmx.districtm.io/b/v1`. diff --git a/test/spec/modules/districtmDmxBidAdapter_spec.js b/test/spec/modules/districtmDmxBidAdapter_spec.js index a0bd76f9591..64f76eb026d 100644 --- a/test/spec/modules/districtmDmxBidAdapter_spec.js +++ b/test/spec/modules/districtmDmxBidAdapter_spec.js @@ -1,6 +1,6 @@ import {expect} from 'chai'; import * as _ from 'lodash'; -import {spec, matchRequest, checkDeepArray, defaultSize} from '../../../modules/districtmDmxBidAdapter'; +import {spec, matchRequest, checkDeepArray, defaultSize} from '../../../modules/districtmDMXBidAdapter'; const bidRequest = [{ 'bidder': 'districtmDMX', From 25d214a0e6ee1ea2141f8a6dc93c443b72f84e3d Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 4 Sep 2018 15:41:01 -0400 Subject: [PATCH 0667/1594] Prebid 1.23.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a71e6309103..2449b005f53 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.23.0-pre", + "version": "1.23.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 794509892e30a53b50aee32e474554caa7740ad4 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 4 Sep 2018 15:48:24 -0400 Subject: [PATCH 0668/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2449b005f53..77181edc6a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.23.0", + "version": "1.24.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From ac207c582416a3517c6cfe1abaa589bf986fc3a8 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 5 Sep 2018 12:10:49 -0400 Subject: [PATCH 0669/1594] upgrade to gulp 4 (#2930) * upgrade to gulp 4 * update circleci config * removed some tasks and added notest flag * update lint dependency for test task --- .circleci/config.yml | 2 +- README.md | 2 + gulpfile.js | 318 +++++----- package-lock.json | 1405 ++++++++++++++++++++++++------------------ package.json | 4 +- 5 files changed, 1001 insertions(+), 730 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 62c23390666..fbf7e77e10f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,7 +33,7 @@ jobs: - node_modules key: v1-dependencies-{{ checksum "package.json" }} - - run: sudo npm install -g gulp + - run: sudo npm install -g gulp-cli # Download and run BrowserStack local - run: name : Download BrowserStack Local binary and start it. diff --git a/README.md b/README.md index e43833fd4d2..137374ebaa7 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ Working examples can be found in [the developer docs](http://prebid.org/dev-docs $ npm install *Note:* You need to have `NodeJS` 4.x or greater installed. +*Note:* Because we have transitioned to using gulp 4.0 - you need to have `gulp-cli` installed globally prior to running the general `npm install`. Run the following command to perform the install: `npm install gulp-cli -g` +If you have a previous version of `gulp` installed globally, you'll need to remove it before installing `gulp-cli`. This removal can be done with the command: `npm rm gulp -g`
diff --git a/gulpfile.js b/gulpfile.js index 92dd2a7c1f1..b373e6299c6 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,18 +5,15 @@ var argv = require('yargs').argv; var gulp = require('gulp'); var gutil = require('gulp-util'); var connect = require('gulp-connect'); -var path = require('path'); var webpack = require('webpack'); var webpackStream = require('webpack-stream'); var uglify = require('gulp-uglify'); -var clean = require('gulp-clean'); +var gulpClean = require('gulp-clean'); var KarmaServer = require('karma').Server; var karmaConfMaker = require('./karma.conf.maker'); var opens = require('open'); var webpackConfig = require('./webpack.conf'); var helpers = require('./gulpHelpers'); -var del = require('del'); -var gulpDocumentation = require('gulp-documentation'); var concat = require('gulp-concat'); var header = require('gulp-header'); var footer = require('gulp-footer'); @@ -36,23 +33,131 @@ var banner = '/* <%= prebid.name %> v<%= prebid.version %>\n' + dateString + ' * var analyticsDirectory = '../analytics'; var port = 9999; -// Tasks -gulp.task('default', ['webpack']); +// these modules must be explicitly listed in --modules to be included in the build, won't be part of "all" modules +var explicitModules = [ + 'pre1api' +]; -gulp.task('serve', ['build-bundle-dev', 'watch', 'test']); +// all the following functions are task functions +function bundleToStdout() { + nodeBundle().then(file => console.log(file)); +} +bundleToStdout.displayName = 'bundle-to-stdout'; -gulp.task('serve-nw', ['lint', 'watch', 'e2etest']); +function clean() { + return gulp.src(['build'], { + read: false, + allowEmpty: true + }) + .pipe(gulpClean()); +} -gulp.task('run-tests', ['lint', 'test-coverage']); +function e2etestReport() { + var reportPort = 9010; + var targetDestinationDir = './e2etest-report'; + helpers.createEnd2EndTestReport(targetDestinationDir); + connect.server({ + port: reportPort, + root: './', + livereload: true + }); -gulp.task('build', ['build-bundle-prod']); + setTimeout(function() { + opens('http://localhost:' + reportPort + '/' + targetDestinationDir.slice(2) + '/results.html'); + }, 5000); +}; +e2etestReport.displayName = 'e2etest-report'; -gulp.task('clean', function () { - return gulp.src(['build'], { - read: false - }) - .pipe(clean()); -}); +// Dependant task for building postbid. It escapes postbid-config file. +function escapePostbidConfig() { + gulp.src('./integrationExamples/postbid/oas/postbid-config.js') + .pipe(jsEscape()) + .pipe(gulp.dest('build/postbid/')); +}; +escapePostbidConfig.displayName = 'escape-postbid-config'; + +function lint() { + return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js']) + .pipe(eslint()) + .pipe(eslint.format('stylish')) + .pipe(eslint.failAfterError()); +}; + +// View the code coverage report in the browser. +function viewCoverage(done) { + var coveragePort = 1999; + + connect.server({ + port: coveragePort, + root: 'build/coverage/karma_html', + livereload: false + }); + opens('http://localhost:' + coveragePort); + done(); +}; +viewCoverage.displayName = 'view-coverage'; + +// 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, + root: './', + livereload: true + }); + + mainWatcher.on('all', gulp.series(clean, gulp.parallel(lint, 'build-bundle-dev', test))); + loaderWatcher.on('all', gulp.series(lint)); + done(); +}; + +function makeDevpackPkg() { + var cloned = _.cloneDeep(webpackConfig); + cloned.devtool = 'source-map'; + var externalModules = helpers.getArgModules(); + + const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); + const moduleSources = helpers.getModulePaths(externalModules); + + return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) + .pipe(helpers.nameModules(externalModules)) + .pipe(webpackStream(cloned, webpack)) + .pipe(replace('$prebid.version$', prebid.version)) + .pipe(gulp.dest('build/dev')) + .pipe(connect.reload()); +} + +function makeWebpackPkg() { + var cloned = _.cloneDeep(webpackConfig); + + delete cloned.devtool; + + var externalModules = helpers.getArgModules(); + + const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); + const moduleSources = helpers.getModulePaths(externalModules); + + return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) + .pipe(helpers.nameModules(externalModules)) + .pipe(webpackStream(cloned, webpack)) + .pipe(replace('$prebid.version$', prebid.version)) + .pipe(uglify()) + .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid }))) + .pipe(optimizejs()) + .pipe(gulp.dest('build/dist')) + .pipe(connect.reload()); +} function gulpBundle(dev) { return bundle(dev).pipe(gulp.dest('build/' + (dev ? 'dev' : 'dist'))); @@ -71,14 +176,9 @@ function nodeBundle(modules) { }); } -// these modules must be explicitly listed in --modules to be included in the build, won't be part of "all" modules -var explicitModules = [ - 'pre1api' -]; - function bundle(dev, moduleArr) { - var modules = moduleArr || helpers.getArgModules(), - allModules = helpers.getModuleNames(modules); + var modules = moduleArr || helpers.getArgModules(); + var allModules = helpers.getModuleNames(modules); if (modules.length === 0) { modules = allModules.filter(module => !explicitModules.includes(module)); @@ -125,7 +225,8 @@ function newKarmaCallback(done) { done(new Error('Karma tests failed with exit code ' + exitCode)); } else { if (argv.browserstack) { - process.exit(0); + // process.exit(0); + done(); // test this with travis (or circleci) } else { done(); } @@ -133,51 +234,6 @@ function newKarmaCallback(done) { } } -gulp.task('build-bundle-dev', ['devpack'], gulpBundle.bind(null, true)); -gulp.task('build-bundle-prod', ['webpack'], gulpBundle.bind(null, false)); -gulp.task('bundle', gulpBundle.bind(null, false)); // used for just concatenating pre-built files with no build step - -gulp.task('bundle-to-stdout', function() { - nodeBundle().then(file => console.log(file)); -}); - -gulp.task('devpack', ['clean'], function () { - var cloned = _.cloneDeep(webpackConfig); - cloned.devtool = 'source-map'; - var externalModules = helpers.getArgModules(); - - const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); - const moduleSources = helpers.getModulePaths(externalModules); - - return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) - .pipe(helpers.nameModules(externalModules)) - .pipe(webpackStream(cloned, webpack)) - .pipe(replace('$prebid.version$', prebid.version)) - .pipe(gulp.dest('build/dev')) - .pipe(connect.reload()); -}); - -gulp.task('webpack', ['clean'], function () { - var cloned = _.cloneDeep(webpackConfig); - - delete cloned.devtool; - - var externalModules = helpers.getArgModules(); - - const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); - const moduleSources = helpers.getModulePaths(externalModules); - - return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) - .pipe(helpers.nameModules(externalModules)) - .pipe(webpackStream(cloned, webpack)) - .pipe(replace('$prebid.version$', prebid.version)) - .pipe(uglify()) - .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid }))) - .pipe(optimizejs()) - .pipe(gulp.dest('build/dist')) - .pipe(connect.reload()); -}); - // Run the unit tests. // // By default, this runs in headless chrome. @@ -186,41 +242,33 @@ gulp.task('webpack', ['clean'], function () { // If --file "" is given, the task will only run tests in the specified file. // If --browserstack is given, it will run the full suite of currently supported browsers. // If --browsers is given, browsers can be chosen explicitly. e.g. --browsers=chrome,firefox,ie9 -gulp.task('test', ['clean', 'lint'], function (done) { - var karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch, argv.file); +// If --notest is given, it will immediately skip the test task (useful for developing changes with `gulp serve --notest`) +function test(done) { + if (argv.notest) { + done(); + } else { + var karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch, argv.file); - var browserOverride = helpers.parseBrowserArgs(argv).map(helpers.toCapitalCase); - if (browserOverride.length > 0) { - karmaConf.browsers = browserOverride; - } + var browserOverride = helpers.parseBrowserArgs(argv).map(helpers.toCapitalCase); + if (browserOverride.length > 0) { + karmaConf.browsers = browserOverride; + } - new KarmaServer(karmaConf, newKarmaCallback(done)).start(); -}); + new KarmaServer(karmaConf, newKarmaCallback(done)).start(); + } +} // If --file "" is given, the task will only run tests in the specified file. -gulp.task('test-coverage', ['clean'], function(done) { +function testCoverage(done) { new KarmaServer(karmaConfMaker(true, false, false, argv.file), newKarmaCallback(done)).start(); -}); - -// View the code coverage report in the browser. -gulp.task('view-coverage', function (done) { - var coveragePort = 1999; - - connect.server({ - port: coveragePort, - root: 'build/coverage/karma_html', - livereload: false - }); - opens('http://localhost:' + coveragePort); - done(); -}); +} -gulp.task('coveralls', ['test-coverage'], function() { // 2nd arg is a dependency: 'test' must be finished +function coveralls() { // 2nd arg is a dependency: 'test' must be finished // first send results of istanbul's test coverage to coveralls.io. return gulp.src('gulpfile.js', { read: false }) // You have to give it a file, but you don't // have to read it. .pipe(shell('cat build/coverage/lcov.info | node_modules/coveralls/bin/coveralls.js')); -}); +} // Watch Task with Live Reload gulp.task('watch', function () { @@ -242,27 +290,7 @@ gulp.task('watch', function () { }); }); -gulp.task('lint', () => { - return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js']) - .pipe(eslint()) - .pipe(eslint.format('stylish')) - .pipe(eslint.failAfterError()); -}); - -gulp.task('clean-docs', function () { - del(['docs']); -}); - -gulp.task('docs', ['clean-docs'], function () { - return gulp.src('src/prebid.js') - .pipe(gulpDocumentation('md')) - .on('error', function (err) { - gutil.log('`gulp-documentation` failed:', err.message); - }) - .pipe(gulp.dest('docs')); -}); - -gulp.task('e2etest', ['devpack', 'webpack'], function() { +function e2eTest() { var cmdQueue = []; if (argv.browserstack) { var browsers = require('./browsers.json'); @@ -289,38 +317,50 @@ gulp.task('e2etest', ['devpack', 'webpack'], function() { return gulp.src('') .pipe(shell(cmdQueue.join(';'))); -}); - -gulp.task('e2etest-report', function() { - var reportPort = 9010; - var targetDestinationDir = './e2etest-report'; - helpers.createEnd2EndTestReport(targetDestinationDir); - connect.server({ - port: reportPort, - root: './', - livereload: true - }); - - setTimeout(function() { - opens('http://localhost:' + reportPort + '/' + targetDestinationDir.slice(2) + '/results.html'); - }, 5000); -}); +} // This task creates postbid.js. Postbid setup is different from prebid.js // More info can be found here http://prebid.org/overview/what-is-post-bid.html -gulp.task('build-postbid', ['escape-postbid-config'], function() { + +function buildPostbid() { var fileContent = fs.readFileSync('./build/postbid/postbid-config.js', 'utf8'); return gulp.src('./integrationExamples/postbid/oas/postbid.js') .pipe(replace('\[%%postbid%%\]', fileContent)) .pipe(gulp.dest('build/postbid/')); -}); +} -// Dependant task for building postbid. It escapes postbid-config file. -gulp.task('escape-postbid-config', function() { - gulp.src('./integrationExamples/postbid/oas/postbid-config.js') - .pipe(jsEscape()) - .pipe(gulp.dest('build/postbid/')); -}); +// support tasks +gulp.task(lint); +gulp.task(watch); + +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, gulpBundle.bind(null, false))); + +// public tasks (dependencies are needed for each task since they can be ran on their own) +gulp.task('test', gulp.series(clean, lint, test)); + +gulp.task('test-coverage', gulp.series(clean, testCoverage)); +gulp.task(viewCoverage); + +gulp.task('coveralls', gulp.series('test-coverage', coveralls)); + +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('default', gulp.series(clean, makeWebpackPkg)); + +gulp.task(e2etestReport); +gulp.task('e2etest', gulp.series(clean, gulp.parallel(makeDevpackPkg, makeWebpackPkg), e2eTest)); + +// other tasks +gulp.task(bundleToStdout); +gulp.task('bundle', gulpBundle.bind(null, false)); // used for just concatenating pre-built files with no build step +gulp.task('serve-nw', gulp.parallel(lint, watch, 'e2etest')); module.exports = nodeBundle; diff --git a/package-lock.json b/package-lock.json index 4366f57423a..58d408a6be4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.17.0-pre", + "version": "1.19.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -41,9 +41,9 @@ } }, "JSONStream": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz", - "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.4.tgz", + "integrity": "sha512-Y7vfi3I5oMOYIr+WxV8NZxDSwcbNgzdKYsTNInmycOq9bUYwGg9ryu57Wg5NLmCjqdFPNUmpMBo3kSJN9tCbXg==", "dev": true, "requires": { "jsonparse": "^1.2.0", @@ -311,12 +311,30 @@ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, + "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, + "requires": { + "make-iterator": "^1.0.0" + } + }, "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 }, + "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, + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", @@ -341,18 +359,72 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "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 + } + } + }, "array-iterate": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", "dev": true }, + "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, + "requires": { + "is-number": "^4.0.0" + }, + "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 + } + } + }, "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 }, + "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, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "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-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -387,10 +459,13 @@ "dev": true }, "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true + "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.0" + } }, "asn1.js": { "version": "4.10.1", @@ -459,6 +534,26 @@ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, + "async-done": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", + "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^1.0.7", + "stream-exhaust": "^1.0.1" + }, + "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 + } + } + }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", @@ -471,6 +566,15 @@ "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", "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" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -489,9 +593,9 @@ "dev": true }, "aws4": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, "axios": { @@ -1570,6 +1674,23 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "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" + } + }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -2099,16 +2220,38 @@ "isarray": "^1.0.0" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, "buffer-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", "dev": true }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, "buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "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-more-ints": { @@ -2255,9 +2398,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000865", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", - "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==", + "version": "1.0.30000876", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000876.tgz", + "integrity": "sha512-v+Q2afhJJ1oydQnEB4iHhxDz5x9lWPbRnQBQlM3FgtZxqLO8KDSdu4txUrFwC1Ws9I2kQi/QImkvj17NbVpNAg==", "dev": true }, "caseless": { @@ -2456,9 +2599,9 @@ } }, "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, "clone-buffer": { @@ -2511,6 +2654,17 @@ "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", "dev": true }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2543,9 +2697,9 @@ "dev": true }, "colors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", - "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.1.tgz", + "integrity": "sha512-jg/vxRmv430jixZrC+La5kMbUWqIg32/JsYNZb94+JEmzceYbWKTsv1OuTp+7EaqiaWRR2tPcykibwCRgclIsw==", "dev": true }, "combine-lists": { @@ -2717,6 +2871,16 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, "core-js": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", @@ -2942,10 +3106,14 @@ "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 + "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" + } }, "debug": { "version": "3.1.0", @@ -3008,6 +3176,23 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "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, + "requires": { + "kind-of": "^5.0.2" + }, + "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-require-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", @@ -3017,22 +3202,11 @@ "strip-bom": "^3.0.0" } }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "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 - } - } + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true }, "define-properties": { "version": "1.1.2", @@ -3145,12 +3319,6 @@ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -3568,14 +3736,25 @@ "stream-shift": "^1.0.0" } }, + "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, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "optional": true, "requires": { - "jsbn": "~0.1.0" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, "ee-first": { @@ -3591,15 +3770,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.52", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", - "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=", + "version": "1.3.57", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.57.tgz", + "integrity": "sha512-YYpZlr6mzR8cK5VRmTZydEt5Mp+WMg1/syrO40PoQzl76vJ+oQchL2d3FmEcWzw3FYqJVYJP/kYYSzTa7FLXwg==", "dev": true }, "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -3732,9 +3911,9 @@ } }, "es5-ext": { - "version": "0.10.45", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", - "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", @@ -4076,9 +4255,9 @@ } }, "eslint-plugin-import": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz", - "integrity": "sha512-t6hGKQDMIt9N8R7vLepsYXgDfeuhp6ZJSgtrLEDxonpSubyxUZHjhm6LsAaZX8q6GYVxkbT3kTsV9G5mBCFR6A==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", + "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", "dev": true, "requires": { "contains-path": "^0.1.0", @@ -4440,9 +4619,9 @@ } }, "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "extend-shallow": { @@ -4739,12 +4918,6 @@ "pkg-dir": "^2.0.0" } }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -4790,12 +4963,6 @@ "parse-filepath": "^1.0.1" } }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, "flagged-respawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", @@ -4825,9 +4992,9 @@ } }, "follow-redirects": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz", - "integrity": "sha512-v9GI1hpaqq1ZZR6pBD1+kI7O24PhDvNGNodjS3MdcEqyrahCp8zbtpv+2B/krUnSmUH80lbAS7MrdeK5IylgKg==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.5.tgz", + "integrity": "sha512-GHjtHDlY/ehslqv0Gr5N0PUJppgg/q0rOBvX0na1s7y1A3LWxPqCYU76s3Z1bM4+UZB4QF0usaXLT5wFpof5PA==", "dev": true, "requires": { "debug": "^3.1.0" @@ -4946,12 +5113,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true - }, - "rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true } } }, @@ -5590,15 +5751,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "~0.1.0" - } - }, "generate-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", @@ -5805,21 +5957,15 @@ } }, "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "^0.5.1" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.1.tgz", + "integrity": "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g==", "dev": true, "requires": { - "find-index": "^0.1.1" + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" } }, "global-modules": { @@ -5880,64 +6026,6 @@ } } }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - } - } - }, "glogg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", @@ -5984,174 +6072,180 @@ "dev": true }, "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", + "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", "dev": true, "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" + "glob-watcher": "^5.0.0", + "gulp-cli": "^2.0.0", + "undertaker": "^1.0.0", + "vinyl-fs": "^3.0.0" }, "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "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=", + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "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": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "gulp-cli": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", + "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", + "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.1.0", + "isobject": "^3.0.1", + "liftoff": "^2.5.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.0.1", + "yargs": "^7.1.0" } }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "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": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" } }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "natives": "^1.1.0" + "lcid": "^1.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 - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "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": { - "brace-expansion": "^1.0.0" + "error-ex": "^1.2.0" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true + "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" + } }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "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": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "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" + } }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "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": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "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": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "is-utf8": "^0.2.0" } }, - "unique-stream": { + "which-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" } }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", "dev": true, "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" + "camelcase": "^3.0.0" } } } @@ -6262,16 +6356,6 @@ "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" - } - }, "gulp-util": { "version": "2.2.20", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", @@ -6315,59 +6399,6 @@ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, - "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.escape": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" - } - }, - "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, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~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" - } - }, "minimist": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", @@ -6516,16 +6547,6 @@ } } }, - "gulp-documentation": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/gulp-documentation/-/gulp-documentation-3.2.1.tgz", - "integrity": "sha1-r1JKv9cuI+cVXwCyoYoHo2QqjdU=", - "dev": true, - "requires": { - "through2": "^2.0.3", - "vinyl": "^2.1.0" - } - }, "gulp-eslint": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", @@ -6548,6 +6569,61 @@ "lodash._reevaluate": "^3.0.0", "lodash._reinterpolate": "^3.0.0", "lodash.template": "^3.6.2" + }, + "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.0" + } + }, + "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.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "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.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.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.0.0" + } + } } }, "gulp-header": { @@ -6561,6 +6637,12 @@ "through2": "^2.0.0" }, "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.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", @@ -6660,9 +6742,9 @@ } }, "gulp-rename": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.3.0.tgz", - "integrity": "sha512-nEuZB7/9i0IZ8AXORTizl2QLP9tcC9uWc/s329zElBLJw1CfOhmMXBxwVlCRKjDyrWuhVP0uBKl61KeQ32TiCg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", + "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", "dev": true }, "gulp-replace": { @@ -6739,15 +6821,16 @@ } }, "gulp-uglify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", - "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.1.tgz", + "integrity": "sha512-KVffbGY9d4Wv90bW/B1KZJyunLMyfHTBbilpDvmcrj5Go0/a1G3uVpt+1gRBWSw/11dqR3coJ1oWNTt1AiXuWQ==", "dev": true, "requires": { "gulplog": "^1.0.0", "has-gulplog": "^0.1.0", "lodash": "^4.13.1", "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", "through2": "^2.0.0", "uglify-js": "^3.0.5", "vinyl-sourcemaps-apply": "^0.2.0" @@ -6760,9 +6843,9 @@ "dev": true }, "uglify-js": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.5.tgz", - "integrity": "sha512-Fm52gLqJqFBnT+Sn411NPDnsgaWiYeRLw42x7Va/mS8TKgaepwoGY7JLXHSEef3d3PmdFXSz1Zx7KMLL89E2QA==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.7.tgz", + "integrity": "sha512-J0M2i1mQA+ze3EdN9SBi751DNdAXmeFLfJrd/MDIkRc3G3Gbb9OPVSx7GIQvVwfWxQARcYV2DTxIkMyDAk3o9Q==", "dev": true, "requires": { "commander": "~2.16.0", @@ -6809,6 +6892,65 @@ "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.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.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "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.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.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.0.0" + } + }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -6879,12 +7021,12 @@ "dev": true }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", "dev": true, "requires": { - "ajv": "^5.1.0", + "ajv": "^5.3.0", "har-schema": "^2.0.0" }, "dependencies": { @@ -7630,9 +7772,9 @@ "optional": true }, "is-my-json-valid": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", - "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", + "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", "dev": true, "optional": true, "requires": { @@ -7825,10 +7967,13 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } }, "isexe": { "version": "2.0.0", @@ -8027,6 +8172,15 @@ "source-map": "^0.5.3" }, "dependencies": { + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -8216,6 +8370,12 @@ "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-1.0.2.tgz", "integrity": "sha1-v7P672WqEqMWBYcSlFwyb9jwFDQ=" }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, "just-extend": { "version": "1.1.27", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", @@ -8223,9 +8383,9 @@ "dev": true }, "karma": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.4.tgz", - "integrity": "sha512-32yhTwoi6BZgJZhR78GwhzyFABbYG/1WwQqYgY7Vh96Demvua2jM3+FyRltIMTUH/Kd5xaQvDw2L7jTvkYFeXg==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", + "integrity": "sha512-rECezBeY7mjzGUWhFlB7CvPHgkHJLXyUmWg+6vHCEsdWNUTnmiS6jRrIMcJEWgU2DUGZzGWG0bTRVky8fsDTOA==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -8329,6 +8489,15 @@ "unpipe": "1.0.0" } }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -8581,6 +8750,16 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "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" + } + }, "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -8920,6 +9099,19 @@ "requires": { "lodash._basecopy": "^3.0.0", "lodash.keys": "^3.0.0" + }, + "dependencies": { + "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.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + } } }, "lodash._baseclone": { @@ -8934,6 +9126,19 @@ "lodash._basefor": "^3.0.0", "lodash.isarray": "^3.0.0", "lodash.keys": "^3.0.0" + }, + "dependencies": { + "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.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + } } }, "lodash._basecopy": { @@ -9024,9 +9229,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": { @@ -9037,19 +9242,6 @@ "requires": { "lodash._htmlescapes": "~2.4.1", "lodash.keys": "~2.4.1" - }, - "dependencies": { - "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, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } - } } }, "lodash._root": { @@ -9098,19 +9290,6 @@ "requires": { "lodash._objecttypes": "~2.4.1", "lodash.keys": "~2.4.1" - }, - "dependencies": { - "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, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } - } } }, "lodash.defaultsdeep": { @@ -9120,12 +9299,14 @@ "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=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", "dev": true, "requires": { - "lodash._root": "^3.0.0" + "lodash._escapehtmlchar": "~2.4.1", + "lodash._reunescapedhtml": "~2.4.1", + "lodash.keys": "~2.4.1" } }, "lodash.get": { @@ -9156,14 +9337,14 @@ } }, "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" } }, "lodash.merge": { @@ -9185,30 +9366,28 @@ "dev": true }, "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "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._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._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": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "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.escape": "^3.0.0" + "lodash._reinterpolate": "~2.4.1", + "lodash.escape": "~2.4.1" } }, "lodash.values": { @@ -9218,19 +9397,6 @@ "dev": true, "requires": { "lodash.keys": "~2.4.1" - }, - "dependencies": { - "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, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } - } } }, "log-driver": { @@ -9388,6 +9554,13 @@ "dev": true, "optional": true }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true, + "optional": true + }, "qs": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", @@ -9425,6 +9598,16 @@ "tunnel-agent": "~0.4.1" } }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "optional": true, + "requires": { + "punycode": "^1.4.1" + } + }, "tunnel-agent": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", @@ -9653,6 +9836,18 @@ } } }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + } + }, "math-random": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", @@ -9698,9 +9893,9 @@ } }, "mdast-util-to-hast": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.1.tgz", - "integrity": "sha512-+eimV/12kdg0/T0EEfcK7IsDbSu2auVm92z5jdSEQ3DHF2HiU4OHmX9ir5wpQajr73nwabdxrUoxREvW2zVFFw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.2.tgz", + "integrity": "sha512-YI8Ea3TFWEZrS31+6Q/d8ZYTOSDKM06IPc3l2+OMFX1o3JTG2mrztlmzDsUMwIXLWofEdTVl/WXBgRG6ddlU/A==", "dev": true, "requires": { "collapse-white-space": "^1.0.0", @@ -9755,18 +9950,18 @@ } }, "memoizee": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz", - "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", "requires": { "d": "1", - "es5-ext": "^0.10.30", + "es5-ext": "^0.10.45", "es6-weak-map": "^2.0.2", "event-emitter": "^0.3.5", "is-promise": "^2.1", "lru-queue": "0.1", "next-tick": "1", - "timers-ext": "^0.1.2" + "timers-ext": "^0.1.5" } }, "memory-fs": { @@ -10271,6 +10466,12 @@ } } }, + "mute-stdout": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.0.tgz", + "integrity": "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0=", + "dev": true + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -10328,9 +10529,9 @@ "dev": true }, "neo-async": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", - "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz", + "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==", "dev": true }, "netmask": { @@ -10345,9 +10546,9 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nightwatch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.6.tgz", - "integrity": "sha1-F7Ghm0VfEi+SPkftfth7bJimopY=", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.8.tgz", + "integrity": "sha512-2G6mc2DALGs73BfmJjknmm2pClOz+qaYe7UY7RPtX1O0sZ7GLyV/CJXvBUBj42payEGdJpSX51s2s50IBfeQ9Q==", "dev": true, "requires": { "assertion-error": "^1.1.0", @@ -10637,9 +10838,9 @@ "dev": true }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, "object-assign": { @@ -10763,6 +10964,16 @@ "isobject": "^3.0.1" } }, + "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, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -10996,37 +11207,6 @@ "wordwrap": "~1.0.0" } }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" - }, - "dependencies": { - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "~1.3.0" - } - }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1" - } - } - } - }, "ordered-read-streams": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", @@ -11481,9 +11661,9 @@ "dev": true }, "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-platform": { @@ -11768,6 +11948,12 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "dev": true + }, "public-encrypt": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", @@ -11894,9 +12080,9 @@ "dev": true }, "randomatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", - "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", "dev": true, "requires": { "is-number": "^4.0.0", @@ -12175,18 +12361,18 @@ } }, "remark-reference-links": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.1.tgz", - "integrity": "sha1-AhrtHFXBh9cSs8dtAFe/UQ0wC6c=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.2.tgz", + "integrity": "sha512-871gKTysBtdQUjoqXA0URWmVhI2jFrpLkWrM3/bydAbsngilDYRjjl2LDAgmNooW8bYbHa57YQ13ld+mYr3TLg==", "dev": true, "requires": { "unist-util-visit": "^1.0.0" } }, "remark-slug": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.0.0.tgz", - "integrity": "sha512-bRFK90ia6iooqC5KH6e9nEIL3OwRbTPU6ed2fm/fa66uofKdmRcsmRVMwND3pXLbvH2F022cETYlE7YlVs7LNQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.0.tgz", + "integrity": "sha512-FW/V7b3ekfDL1eyPDyzfq0qz5HFPKPNWVC2eqFDie45r774FLGoymOS1oU7LVQfdFNEvNLZ6oBJT/oIxAyBISg==", "dev": true, "requires": { "github-slugger": "^1.0.0", @@ -12288,6 +12474,17 @@ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", "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": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, "replacestream": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", @@ -12298,31 +12495,31 @@ } }, "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "requires": { "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" + "uuid": "^3.3.2" } }, "requestretry": { @@ -12452,13 +12649,10 @@ } }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true }, "ripemd160": { "version": "2.0.2", @@ -12555,6 +12749,15 @@ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "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=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, "send": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", @@ -12604,12 +12807,6 @@ } } }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -13351,6 +13548,12 @@ "tweetnacl": "~0.14.0" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, "state-toggle": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", @@ -13451,10 +13654,10 @@ "readable-stream": "^2.0.2" } }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "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": { @@ -13660,6 +13863,16 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "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=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", @@ -13815,15 +14028,6 @@ "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", "dev": true }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, "time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", @@ -13964,11 +14168,12 @@ } }, "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { + "psl": "^1.1.24", "punycode": "^1.4.1" } }, @@ -14009,15 +14214,15 @@ "dev": true }, "trough": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.2.tgz", - "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", + "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", "dev": true }, "tsscmp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", "dev": true, "optional": true }, @@ -14177,6 +14382,29 @@ "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", "dev": true }, + "undertaker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", + "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", + "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", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.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 + }, "unherit": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", @@ -14298,12 +14526,21 @@ "dev": true }, "unist-util-visit": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.1.tgz", - "integrity": "sha512-0fdB9EQJU0tho5tK0VzOJzAQpPv2LyLZ030b10GxuzAWEfvd54mpY7BMjQ1L69k2YNvL+SvxRzH0yUIehOO8aA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", + "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", + "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", "dev": true, "requires": { - "unist-util-is": "^2.1.1" + "unist-util-is": "^2.1.2" } }, "unpipe": { @@ -14422,9 +14659,9 @@ } }, "url-parse": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.1.tgz", - "integrity": "sha512-x95Td74QcvICAA0+qERaVkRpTGKyBHHYdwL2LXZm5t/gBtCB9KQSO/0zQgSTYEV1p0WcvSg79TLNPSvd5IDJMQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", + "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", "dev": true, "requires": { "querystringify": "^2.0.0", @@ -14460,12 +14697,6 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, "useragent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", @@ -14518,18 +14749,18 @@ "optional": true }, "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", + "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", "dev": true, "requires": { - "user-home": "^1.1.1" + "homedir-polyfill": "^1.0.1" } }, "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -14952,9 +15183,9 @@ }, "dependencies": { "time-stamp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", - "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.1.tgz", + "integrity": "sha512-KUnkvOWC3C+pEbwE/0u3CcmNpGCDqkYGYZOphe1QFxApYQkJ5g195TDBjgZch/zG6chU1NcabLwnM7BCpWAzTQ==", "dev": true } } diff --git a/package.json b/package.json index 77181edc6a5..9d2de7d4e37 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "block-loader": "^2.1.0", "chai": "^3.3.0", "coveralls": "^3.0.1", - "del": "^2.2.0", "documentation": "^5.2.2", "ejs": "^2.5.1", "es5-shim": "^4.5.2", @@ -42,12 +41,11 @@ "eslint-plugin-standard": "^3.0.1", "faker": "^3.1.0", "fs.extra": "^1.3.2", - "gulp": "^3.9.1", + "gulp": "^4.0.0", "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", "gulp-connect": "5.5.0", - "gulp-documentation": "^3.2.1", "gulp-eslint": "^4.0.0", "gulp-footer": "^1.0.5", "gulp-header": "^1.7.1", From f04ff6fd06a9c15240a6b7e98a0c6d738a1ece00 Mon Sep 17 00:00:00 2001 From: susyt Date: Wed, 5 Sep 2018 09:31:55 -0700 Subject: [PATCH 0670/1594] Update gumgumBidAdapter.md (#3031) New zone and slot Ids were created for Prebid testing --- modules/gumgumBidAdapter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/gumgumBidAdapter.md b/modules/gumgumBidAdapter.md index 500c2a49e3b..14f2fe40abb 100644 --- a/modules/gumgumBidAdapter.md +++ b/modules/gumgumBidAdapter.md @@ -20,7 +20,7 @@ var adUnits = [ { bidder: 'gumgum', params: { - inSlot: '9' // GumGum Slot ID given to the client + inSlot: '15901' // GumGum Slot ID given to the client } } ] @@ -31,7 +31,7 @@ var adUnits = [ { bidder: 'gumgum', params: { - inScreen: 'ggumtest' // GumGum Zone ID given to the client + inScreen: 'dc9d6be1' // GumGum Zone ID given to the client } } ] From 3c50ff684722b454ab80a480516f40248ecfc212 Mon Sep 17 00:00:00 2001 From: Jonathan Mullins Date: Thu, 6 Sep 2018 03:39:25 +1000 Subject: [PATCH 0671/1594] corrected user sync type (#3034) --- modules/playgroundxyzBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/playgroundxyzBidAdapter.js b/modules/playgroundxyzBidAdapter.js index e521f7f98d6..e54f93ab8ca 100644 --- a/modules/playgroundxyzBidAdapter.js +++ b/modules/playgroundxyzBidAdapter.js @@ -102,7 +102,7 @@ export const spec = { } if (syncOptions.pixelEnabled) { return [{ - type: 'pixel', + type: 'image', url: '//ib.adnxs.com/getuidnb?https://ads.playground.xyz/usersync?partner=appnexus&uid=$UID' }]; } From 803e609547cbc965266055d07cba2eec9237828b Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 5 Sep 2018 14:11:24 -0400 Subject: [PATCH 0672/1594] Revert breaking change (#3052) --- src/prebid.js | 7 ++++--- test/spec/unit/pbjs_api_spec.js | 29 ++++++++--------------------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index f30b063f70e..bfc9e31a06c 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -1,13 +1,13 @@ /** @module pbjs */ import { getGlobal } from './prebidGlobal'; -import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId } from './utils'; +import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId, getLatestHighestCpmBid } from './utils'; import { listenMessagesFromCreative } from './secureCreatives'; import { userSync } from 'src/userSync.js'; import { loadScript } from './adloader'; import { config } from './config'; import { auctionManager } from './auctionManager'; -import { targeting, RENDERED, BID_TARGETING_SET } from './targeting'; +import { targeting, getHighestCpmBidsFromBidPool, RENDERED, BID_TARGETING_SET } from './targeting'; import { createHook } from 'src/hook'; import { sessionLoader } from 'src/debugging'; import includes from 'core-js/library/fn/array/includes'; @@ -597,7 +597,8 @@ $$PREBID_GLOBAL$$.getAllPrebidWinningBids = function () { * @return {Array} array containing highest cpm bid object(s) */ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { - return targeting.getWinningBids(adUnitCode) + let bidsReceived = getHighestCpmBidsFromBidPool(auctionManager.getBidsReceived(), getLatestHighestCpmBid); + return targeting.getWinningBids(adUnitCode, bidsReceived) .map(removeRequestId); }; diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 63656cb39f6..41e40100011 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1810,10 +1810,13 @@ describe('Unit: Prebid Module', function () { }); }); - describe('getHighestCpm', function () { - after(function () { - resetAuction(); - }); + describe('getHighestCpm', () => { + // it('returns an array of winning bid objects for each adUnit', () => { + // const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids(); + // expect(highestCpmBids.length).to.equal(2); + // expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); + // expect(highestCpmBids[1]).to.deep.equal(auctionManager.getBidsReceived()[2]); + // }); it('returns an array containing the highest bid object for the given adUnitCode', function () { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); @@ -1833,23 +1836,7 @@ describe('Unit: Prebid Module', function () { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); expect(highestCpmBids.length).to.equal(0); - }); - - it('should not return rendered bid', function() { - let _bidsReceived = getBidResponses().slice(0, 3); - _bidsReceived[0].cpm = 12; - _bidsReceived[0].status = 'rendered'; - _bidsReceived[1].cpm = 9; - _bidsReceived[2].cpm = 11; - - _bidsReceived.forEach((bid) => { - bid.adUnitCode = '/19968336/header-bid-tag-0'; - }); - - auction.getBidsReceived = function() { return _bidsReceived }; - - const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); - expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[2]); + resetAuction(); }); }); From bf4e2d67d1df34c5077a27c4f031dea2032b7101 Mon Sep 17 00:00:00 2001 From: beth92 Date: Wed, 5 Sep 2018 14:40:46 -0400 Subject: [PATCH 0673/1594] Fix creativeId field in Yieldmo bid response (#3053) * Fix creativeId field in bid response We had an issue whereby prebid wasn't passing us yieldmo bids even though we could see them in the network requests. Turned out that the `creativeId` field was being set to `undefined` because the response body from the yieldmo server uses snake case, not camel case. Tested the proposed fix and saw prebid log the bid as expected. * Fix test --- modules/yieldmoBidAdapter.js | 2 +- test/spec/modules/yieldmoBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index ad2aff7dec8..b747e40becd 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -111,7 +111,7 @@ function createNewBid(response) { cpm: response.cpm, width: response.width, height: response.height, - creativeId: response.creativeId, + creativeId: response.creative_id, currency: CURRENCY, netRevenue: NET_REVENUE, ttl: TIME_TO_LIVE, diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 462b2715d24..45baecf9617 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -104,7 +104,7 @@ describe('YieldmoAdapter', function () { width: 300, height: 250, ad: '
', - creativeId: '9874652394875' + creative_id: '9874652394875' }], header: 'header?' }; From 0f401eefed245db91249758a3a7a8d9d41844607 Mon Sep 17 00:00:00 2001 From: kusapan Date: Fri, 7 Sep 2018 04:41:02 +0900 Subject: [PATCH 0674/1594] YIELDONE adapter - added UserSync (#3045) * added UserSync * added UserSync Unit Test --- modules/yieldoneBidAdapter.js | 9 +++++++++ modules/yieldoneBidAdapter.md | 12 ++++++++++++ test/spec/modules/yieldoneBidAdapter_spec.js | 16 ++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index 9f94b5b815e..cdcab0c705a 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -4,6 +4,7 @@ import {registerBidder} from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'yieldone'; const ENDPOINT_URL = '//y.one.impact-ad.jp/h_bid'; +const USER_SYNC_URL = '//y.one.impact-ad.jp/push_sync'; export const spec = { code: BIDDER_CODE, @@ -66,6 +67,14 @@ export const spec = { bidResponses.push(bidResponse); } return bidResponses; + }, + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: USER_SYNC_URL + }]; + } } } registerBidder(spec); diff --git a/modules/yieldoneBidAdapter.md b/modules/yieldoneBidAdapter.md index b5d96f822b5..b154a2ee781 100644 --- a/modules/yieldoneBidAdapter.md +++ b/modules/yieldoneBidAdapter.md @@ -25,3 +25,15 @@ THE YIELDONE adapter requires setup and approval from the YIELDONE team. Please }] }]; ``` + +### Configuration + +YIELDONE recommends the UserSync configuration below. Without it, the YIELDONE adapter will not able to perform user syncs, which lowers match rate and reduces monetization. + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + enabledBidders: ['yieldone'] + }}); +``` diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js index ca4f1fb8dec..b717ef52709 100644 --- a/test/spec/modules/yieldoneBidAdapter_spec.js +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -144,4 +144,20 @@ describe('yieldoneBidAdapter', function() { expect(result.length).to.equal(0); }); }); + + describe('getUserSyncs', function () { + const userSyncUrl = '//y.one.impact-ad.jp/push_sync'; + + it('handles empty sync options', function () { + expect(spec.getUserSyncs({})).to.be.empty; + }); + + it('should return a sync url if iframe syncs are enabled', function () { + expect(spec.getUserSyncs({ + 'iframeEnabled': true + })).to.deep.equal([{ + type: 'iframe', url: userSyncUrl + }]); + }); + }); }); From 55669ac493ccced1196644defa3352ad8af80375 Mon Sep 17 00:00:00 2001 From: phtechno Date: Thu, 6 Sep 2018 21:52:29 +0200 Subject: [PATCH 0675/1594] Changes on AdSize + gdpr (#3035) * Changes on AdSize + gdpr - Primary adsize is now the prebid slot adsize - On bidder.params you can now overwrite the prebid slot size (Not primary size anymore) - gdpr string will be only attached if "gdprApplies=true" * Update yieldlabBidAdapter.js --- modules/yieldlabBidAdapter.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index b62e6b827e5..32ed723a15a 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -13,7 +13,7 @@ export const spec = { supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { - if (bid && bid.params && bid.params.adslotId && bid.params.adSize) { + if (bid && bid.params && bid.params.adslotId && bid.params.supplyId) { return true } return false @@ -40,8 +40,10 @@ export const spec = { }) if (bidderRequest && bidderRequest.gdprConsent) { - query.consent = bidderRequest.gdprConsent.consentString query.gdpr = (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true + if (query.gdpr) { + query.consent = bidderRequest.gdprConsent.consentString + } } const adslots = adslotIds.join(',') @@ -73,23 +75,24 @@ export const spec = { }) if (matchedBid) { - const sizes = parseSize(bidRequest.params.adSize) + const primarysize = bidRequest.sizes.length === 2 && !utils.isArray(bidRequest.sizes[0]) ? bidRequest.sizes : bidRequest.sizes[0] + const customsize = bidRequest.params.adSize !== undefined ? parseSize(bidRequest.params.adSize) : primarysize const bidResponse = { requestId: bidRequest.bidId, cpm: matchedBid.price / 100, - width: sizes[0], - height: sizes[1], + width: primarysize[0], + height: primarysize[1], creativeId: '' + matchedBid.id, dealId: matchedBid.pid, currency: CURRENCY_CODE, netRevenue: false, ttl: BID_RESPONSE_TTL_SEC, referrer: '', - ad: `` + ad: `` } if (isVideo(bidRequest)) { bidResponse.mediaType = VIDEO - bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/${sizes[0]}x${sizes[1]}?ts=${timestamp}` + bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/${customsize[0]}x${customsize[1]}?ts=${timestamp}` } bidResponses.push(bidResponse) From d8743670c6e2b3cc6307d17a02be795359beea49 Mon Sep 17 00:00:00 2001 From: Ignat Khaylov Date: Thu, 6 Sep 2018 22:56:05 +0300 Subject: [PATCH 0676/1594] Fixed default values in bidResponse and added changes to the description (#3051) * Fixed default values in bidResponse and added changes to the description * Added unit test for default cpm and netRevenue, removed placementId from tests and description --- modules/betweenBidAdapter.js | 20 +++--- modules/betweenBidAdapter.md | 67 ++++++++++++++++++++- test/spec/modules/betweenBidAdapter_spec.js | 25 +++++++- 3 files changed, 101 insertions(+), 11 deletions(-) diff --git a/modules/betweenBidAdapter.js b/modules/betweenBidAdapter.js index 98140fe68e6..b0e487d0eef 100644 --- a/modules/betweenBidAdapter.js +++ b/modules/betweenBidAdapter.js @@ -69,13 +69,13 @@ export const spec = { for (var i = 0; i < serverResponse.body.length; i++) { let bidResponse = { requestId: serverResponse.body[i].bidid, - cpm: serverResponse.body[i].cpm || 123, - width: serverResponse.body[i].w || 200, - height: serverResponse.body[i].h || 400, - ttl: serverResponse.body[i].ttl || 120, - creativeId: serverResponse.body[i].creativeid || 123, + cpm: serverResponse.body[i].cpm || 0, + width: serverResponse.body[i].w, + height: serverResponse.body[i].h, + ttl: serverResponse.body[i].ttl, + creativeId: serverResponse.body[i].creativeid, currency: serverResponse.body[i].currency || 'RUB', - netRevenue: serverResponse.body[i].netRevenue || false, + netRevenue: serverResponse.body[i].netRevenue || true, ad: serverResponse.body[i].ad }; bidResponses.push(bidResponse); @@ -106,10 +106,14 @@ export const spec = { }); } */ + // syncs.push({ + // type: 'iframe', + // url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' + // }); syncs.push({ type: 'iframe', - url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' - }) + url: 'http://ads.betweendigital.com/sspmatch-iframe' + }); return syncs; } } diff --git a/modules/betweenBidAdapter.md b/modules/betweenBidAdapter.md index 4ecd07e60bc..426d0aa2ed7 100644 --- a/modules/betweenBidAdapter.md +++ b/modules/betweenBidAdapter.md @@ -12,7 +12,7 @@ About us : http://betweendigital.com # Test Parameters -``` +```javascript var adUnits = [ { code: 'test-div', @@ -28,4 +28,69 @@ About us : http://betweendigital.com ] } ]; +``` + +Where: + +* s - the section id +* code - the id of the iframe tag to which the ads will be rendered + +# Example page + +```html + + + + + + + + + + +

Prebid.js BetweenBidAdapter Test

+ + + ``` \ No newline at end of file diff --git a/test/spec/modules/betweenBidAdapter_spec.js b/test/spec/modules/betweenBidAdapter_spec.js index b1eea08a147..f2d770805c5 100644 --- a/test/spec/modules/betweenBidAdapter_spec.js +++ b/test/spec/modules/betweenBidAdapter_spec.js @@ -6,7 +6,6 @@ describe('betweenBidAdapterTests', function () { expect(spec.isBidRequestValid({ bidder: 'between', params: { - placementId: 'example', w: 240, h: 400, s: 1112 @@ -17,7 +16,7 @@ describe('betweenBidAdapterTests', function () { let bidRequestData = [{ bidId: 'bid1234', bidder: 'between', - params: {w: 240, h: 400, s: 1112, placementId: 'example'}, + params: {w: 240, h: 400, s: 1112}, sizes: [[240, 400]] }] let request = spec.buildRequests(bidRequestData); @@ -42,6 +41,28 @@ describe('betweenBidAdapterTests', function () { expect(bid.currency).to.equal('USD'); expect(bid.width).to.equal(240); expect(bid.height).to.equal(400); + expect(bid.netRevenue).to.equal(true); + expect(bid.requestId).to.equal('bid1234'); + expect(bid.ad).to.equal('Ad html'); + }); + it('validate_response_params', function () { + let serverResponse = { + body: [{ + bidid: 'bid1234', + w: 240, + h: 400, + currency: 'USD', + ad: 'Ad html' + }] + }; + let bids = spec.interpretResponse(serverResponse); + expect(bids).to.have.lengthOf(1); + let bid = bids[0]; + expect(bid.cpm).to.equal(0); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(240); + expect(bid.height).to.equal(400); + expect(bid.netRevenue).to.equal(true); expect(bid.requestId).to.equal('bid1234'); expect(bid.ad).to.equal('Ad html'); }); From b1e784385a71b2efb974f6c8e80ae896a502c737 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Fri, 7 Sep 2018 13:03:37 -0400 Subject: [PATCH 0677/1594] PR review and ticket coordinater updates per PMC discussion (#3050) * updates per previous discussion * updates per review --- PR_REVIEW.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/PR_REVIEW.md b/PR_REVIEW.md index 012a2d8b501..d5799472377 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -18,6 +18,7 @@ For modules and core platform updates, the initial reviewer should request an ad - Once there is 2 `LGTM` on the PR, merge to master - Ask the submitter to add a PR for documentation if applicable. - Add a line into the [draft release](https://github.com/prebid/Prebid.js/releases) notes for this submission. If no draft release is available, create one using [this template]( https://gist.github.com/mkendall07/c3af6f4691bed8a46738b3675cb5a479) +- Add the PR to the appropriate project board (I.E. 1.23.0 Release) for the week, [see](https://github.com/prebid/Prebid.js/projects) ### New Adapter or updates to adapter process - Follow steps above for general review process. In addition, please verify the following: @@ -39,9 +40,9 @@ For modules and core platform updates, the initial reviewer should request an ad ## Ticket Coordinator Each week, Prebid Org assigns one person to keep an eye on incoming issues and PRs. That person should: -- Review issues and PRs at least once per weekday for new items. +- Review issues and PRs at least once per weekday for new items. Encourage a 48 "SLA" on PRs/issues assigned. Aim for touchpoint once every 48/hours. - For PRs: assign PRs to individuals on the PR review list. Try to be equitable -- not all PRs are created equally. Use the "Assigned" field and add the "Needs Review" label. -- For Issues: try to address questions and troubleshooting requests on your own, assigning them to others as needed. +- For Issues: try to address questions and troubleshooting requests on your own, assigning them to others as needed. Please add labels as appropriate (I.E. bug, question, backlog etc). - Issues that are questions or troubleshooting requests may be closed if the originator doesn't respond within a week to requests for confirmation or details. - Issues that are bug reports should be left open and assigned to someone in PR rotation to confirm or deny the bug status. - It's polite to check with others before assigning them large tasks. From 6a3d62899f0aa4aa8032f492d9203e32c7cf5213 Mon Sep 17 00:00:00 2001 From: Tomas Roos Date: Mon, 10 Sep 2018 14:55:48 +0200 Subject: [PATCH 0678/1594] Ability to statically pass consentData (#2636) * Added static consentData to consentManagement config * Added test for static cmpApi * logError instead of logInfo --- modules/consentManagement.js | 24 +- test/spec/modules/consentManagement_spec.js | 411 +++++++++++++++++++- 2 files changed, 433 insertions(+), 2 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index 0618a3f752c..1c8095b4dbd 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -17,14 +17,26 @@ const DEFAULT_ALLOW_AUCTION_WO_CONSENT = true; export let userCMP; export let consentTimeout; export let allowAuction; +export let staticConsentData; let consentData; // add new CMPs here, with their dedicated lookup function const cmpCallMap = { - 'iab': lookupIabConsent + 'iab': lookupIabConsent, + 'static': lookupStaticConsentData }; +/** + * 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(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 @@ -348,7 +360,17 @@ export function setConfig(config) { allowAuction = DEFAULT_ALLOW_AUCTION_WO_CONSENT; utils.logInfo(`consentManagement config did not specify allowAuctionWithoutConsent. Using system default setting (${DEFAULT_ALLOW_AUCTION_WO_CONSENT}).`); } + utils.logInfo('consentManagement module has been activated...'); + + if (userCMP === 'static') { + if (utils.isPlainObject(config.consentData)) { + staticConsentData = config.consentData; + consentTimeout = 0; + } else { + utils.logError(`consentManagement config with cmpApi: 'static' did not specify consentData. No consents will be available to adapters.`); + } + } $$PREBID_GLOBAL$$.requestBids.addHook(requestBidsHook, 50); } config.getConfig('consentManagement', config => setConfig(config.consentManagement)); diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index baa9a43f6aa..6af8c8a4478 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -1,4 +1,4 @@ -import {setConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, allowAuction} from 'modules/consentManagement'; +import {setConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, allowAuction, staticConsentData} from 'modules/consentManagement'; import {gdprDataHandler} from 'src/adaptermanager'; import * as utils from 'src/utils'; import { config } from 'src/config'; @@ -45,6 +45,415 @@ describe('consentManagement', function () { expect(allowAuction).to.be.false; }); }); + + describe('static consent string setConfig value', () => { + afterEach(() => { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + }); + it('results in user settings overriding system defaults', () => { + let staticConfig = { + cmpApi: 'static', + timeout: 7500, + allowAuctionWithoutConsent: false, + consentData: { + getConsentData: { + 'gdprApplies': true, + 'hasGlobalScope': false, + 'consentData': 'BOOgjO9OOgjO9APABAENAi-AAAAWd7_______9____7_9uz_Gv_r_ff_3nW0739P1A_r_Oz_rm_-zzV44_lpQQRCEA' + }, + getVendorConsents: { + 'metadata': 'BOOgjO9OOgjO9APABAENAi-AAAAWd7_______9____7_9uz_Gv_r_ff_3nW0739P1A_r_Oz_rm_-zzV44_lpQQRCEA', + 'gdprApplies': true, + 'hasGlobalScope': false, + 'isEU': true, + 'cookieVersion': 1, + 'created': '2018-05-29T07:45:48.522Z', + 'lastUpdated': '2018-05-29T07:45:48.522Z', + 'cmpId': 15, + 'cmpVersion': 1, + 'consentLanguage': 'EN', + 'vendorListVersion': 34, + 'maxVendorId': 359, + 'purposeConsents': { + '1': true, + '2': true, + '3': true, + '4': true, + '5': true + }, + 'vendorConsents': { + '1': true, + '2': true, + '3': true, + '4': true, + '5': false, + '6': true, + '7': true, + '8': true, + '9': true, + '10': true, + '11': true, + '12': true, + '13': true, + '14': true, + '15': true, + '16': true, + '17': true, + '18': true, + '19': true, + '20': true, + '21': true, + '22': true, + '23': true, + '24': true, + '25': true, + '26': true, + '27': true, + '28': true, + '29': true, + '30': true, + '31': true, + '32': true, + '33': true, + '34': true, + '35': true, + '36': true, + '37': true, + '38': true, + '39': true, + '40': true, + '41': true, + '42': true, + '43': true, + '44': true, + '45': true, + '46': true, + '47': true, + '48': true, + '49': true, + '50': true, + '51': true, + '52': true, + '53': true, + '54': false, + '55': true, + '56': true, + '57': true, + '58': true, + '59': true, + '60': true, + '61': true, + '62': true, + '63': true, + '64': true, + '65': true, + '66': true, + '67': true, + '68': true, + '69': true, + '70': true, + '71': true, + '72': true, + '73': true, + '74': true, + '75': true, + '76': true, + '77': true, + '78': true, + '79': true, + '80': true, + '81': true, + '82': true, + '83': false, + '84': true, + '85': true, + '86': true, + '87': true, + '88': true, + '89': true, + '90': true, + '91': true, + '92': true, + '93': true, + '94': true, + '95': true, + '96': false, + '97': true, + '98': true, + '99': false, + '100': true, + '101': true, + '102': true, + '103': false, + '104': true, + '105': true, + '106': false, + '107': false, + '108': true, + '109': true, + '110': true, + '111': true, + '112': true, + '113': true, + '114': true, + '115': true, + '116': false, + '117': false, + '118': false, + '119': true, + '120': true, + '121': false, + '122': true, + '123': false, + '124': true, + '125': true, + '126': true, + '127': true, + '128': true, + '129': true, + '130': true, + '131': true, + '132': true, + '133': true, + '134': true, + '135': false, + '136': true, + '137': false, + '138': true, + '139': true, + '140': true, + '141': true, + '142': true, + '143': true, + '144': true, + '145': true, + '146': false, + '147': true, + '148': true, + '149': true, + '150': true, + '151': true, + '152': false, + '153': true, + '154': true, + '155': true, + '156': true, + '157': true, + '158': true, + '159': true, + '160': true, + '161': true, + '162': true, + '163': true, + '164': true, + '165': true, + '166': false, + '167': true, + '168': true, + '169': true, + '170': true, + '171': false, + '172': false, + '173': true, + '174': true, + '175': true, + '176': false, + '177': true, + '178': false, + '179': true, + '180': true, + '181': false, + '182': true, + '183': true, + '184': false, + '185': true, + '186': false, + '187': false, + '188': true, + '189': true, + '190': true, + '191': false, + '192': true, + '193': true, + '194': true, + '195': true, + '196': false, + '197': true, + '198': true, + '199': true, + '200': true, + '201': true, + '202': true, + '203': true, + '204': false, + '205': true, + '206': false, + '207': false, + '208': true, + '209': true, + '210': true, + '211': true, + '212': true, + '213': true, + '214': false, + '215': true, + '216': false, + '217': true, + '218': false, + '219': false, + '220': false, + '221': false, + '222': false, + '223': false, + '224': true, + '225': true, + '226': true, + '227': true, + '228': true, + '229': true, + '230': true, + '231': false, + '232': true, + '233': false, + '234': true, + '235': true, + '236': true, + '237': true, + '238': true, + '239': true, + '240': true, + '241': true, + '242': false, + '243': false, + '244': true, + '245': true, + '246': true, + '247': false, + '248': true, + '249': true, + '250': false, + '251': false, + '252': true, + '253': true, + '254': true, + '255': true, + '256': true, + '257': true, + '258': true, + '259': true, + '260': true, + '261': false, + '262': true, + '263': false, + '264': true, + '265': true, + '266': true, + '267': false, + '268': false, + '269': true, + '270': true, + '271': false, + '272': true, + '273': true, + '274': true, + '275': true, + '276': true, + '277': true, + '278': true, + '279': true, + '280': true, + '281': true, + '282': true, + '283': false, + '284': true, + '285': true, + '286': false, + '287': false, + '288': true, + '289': true, + '290': true, + '291': true, + '292': false, + '293': false, + '294': true, + '295': true, + '296': false, + '297': true, + '298': false, + '299': true, + '300': false, + '301': true, + '302': true, + '303': true, + '304': true, + '305': false, + '306': false, + '307': false, + '308': true, + '309': true, + '310': true, + '311': false, + '312': false, + '313': false, + '314': true, + '315': true, + '316': true, + '317': true, + '318': true, + '319': true, + '320': true, + '321': false, + '322': false, + '323': true, + '324': false, + '325': true, + '326': true, + '327': false, + '328': true, + '329': false, + '330': false, + '331': true, + '332': false, + '333': true, + '334': false, + '335': false, + '336': false, + '337': false, + '338': false, + '339': true, + '340': false, + '341': false, + '342': false, + '343': false, + '344': false, + '345': true, + '346': false, + '347': false, + '348': false, + '349': true, + '350': false, + '351': false, + '352': false, + '353': false, + '354': true, + '355': false, + '356': false, + '357': false, + '358': false, + '359': true + } + } + } + }; + + setConfig(staticConfig); + expect(userCMP).to.be.equal('static'); + expect(consentTimeout).to.be.equal(0); // should always return without a timeout when config is used + expect(allowAuction).to.be.false; + expect(staticConsentData).to.be.equal(staticConfig.consentData); + }); + }); }); describe('requestBidsHook tests:', function () { From e368e0701c6a0352bea2f9c99804132068d6342f Mon Sep 17 00:00:00 2001 From: r-sato Date: Mon, 10 Sep 2018 22:36:57 +0900 Subject: [PATCH 0679/1594] Update dgadsBidAdapter (#3048) * Add dgads adapter * Add dgads adapter * Add spec file for dgads * Add spec file for dgads * Add dgads bid adapter * Add dgads bid adapter * fix * fix * fix email * remove semi-colon * Add mediaType native * Add import medaTypes * Change method to 'GET' and Change parameter name and Add get cookie. * fix camelcase * fix space * revert to normal function --- modules/dgadsBidAdapter.js | 21 ++++++++++++++++++--- test/spec/modules/dgadsBidAdapter_spec.js | 20 ++++++++++++++------ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/modules/dgadsBidAdapter.js b/modules/dgadsBidAdapter.js index 7d47cc7acf6..0d6f00fe9a9 100644 --- a/modules/dgadsBidAdapter.js +++ b/modules/dgadsBidAdapter.js @@ -3,6 +3,7 @@ import * as utils from 'src/utils'; import { BANNER, NATIVE } from 'src/mediaTypes'; const BIDDER_CODE = 'dgads'; +const UID_NAME = 'dgads_uid'; const ENDPOINT = 'https://ads-tr.bigmining.com/ad/p/bid'; export const spec = { @@ -27,13 +28,15 @@ export const spec = { const params = bidRequest.params; const data = {}; - data['location_id'] = params.location_id; - data['site_id'] = params.site_id; + data['_loc'] = params.location_id; + data['_medium'] = params.site_id; data['transaction_id'] = bidRequest.transactionId; data['bid_id'] = bidRequest.bidId; + data['referer'] = utils.getTopWindowUrl(); + data['_uid'] = getCookieUid(UID_NAME); return { - method: 'POST', + method: 'GET', url: ENDPOINT, data, }; @@ -84,5 +87,17 @@ function setNativeResponse(ad) { nativeResponce.impressionTrackers = ad.impressionTrackers || []; return nativeResponce; } +export function getCookieUid(uidName) { + if (utils.cookiesAreEnabled()) { + let cookies = document.cookie.split(';'); + for (let i = 0; i < cookies.length; i++) { + let value = cookies[i].split('='); + if (value[0].indexOf(uidName) > -1) { + return value[1]; + } + } + } + return ''; +} registerBidder(spec); diff --git a/test/spec/modules/dgadsBidAdapter_spec.js b/test/spec/modules/dgadsBidAdapter_spec.js index 25f484678a0..2454885217d 100644 --- a/test/spec/modules/dgadsBidAdapter_spec.js +++ b/test/spec/modules/dgadsBidAdapter_spec.js @@ -1,11 +1,12 @@ import {expect} from 'chai'; import * as utils from 'src/utils'; -import {spec} from 'modules/dgadsBidAdapter'; +import {spec, getCookieUid} from 'modules/dgadsBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import { BANNER, NATIVE } from 'src/mediaTypes'; describe('dgadsBidAdapter', function () { const adapter = newBidder(spec); + const UID_NAME = 'dgads_uid'; const VALID_ENDPOINT = 'https://ads-tr.bigmining.com/ad/p/bid'; describe('inherited functions', function () { @@ -101,23 +102,30 @@ describe('dgadsBidAdapter', function () { const noBidRequests = []; expect(Object.keys(spec.buildRequests(noBidRequests)).length).to.equal(0); }); + it('getCookieUid return empty if cookie not found', function () { + expect(getCookieUid(UID_NAME)).to.equal(''); + }); const data = { location_id: '1', site_id: '1', transaction_id: 'c1f1eff6-23c6-4844-a321-575212939e37', - bid_id: '2db3101abaec66' + bid_id: '2db3101abaec66', + referer: utils.getTopWindowUrl(), + _uid: '' }; - it('sends bid request to VALID_ENDPOINT via POST', function () { + it('sends bid request to VALID_ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(VALID_ENDPOINT); - expect(request.method).to.equal('POST'); + expect(request.method).to.equal('GET'); }); it('should attache params to the request', function () { const request = spec.buildRequests(bidRequests)[0]; - expect(request.data['location_id']).to.equal(data['location_id']); - expect(request.data['site_id']).to.equal(data['site_id']); + expect(request.data['_loc']).to.equal(data['location_id']); + expect(request.data['_medium']).to.equal(data['site_id']); expect(request.data['transaction_id']).to.equal(data['transaction_id']); expect(request.data['bid_id']).to.equal(data['bid_id']); + expect(request.data['referer']).to.equal(data['referer']); + expect(request.data['_uid']).to.equal(data['_uid']); }); }); From ebfbc54030bf05156102c54bbfdfc4dd392dee26 Mon Sep 17 00:00:00 2001 From: Zachary Lester Date: Tue, 11 Sep 2018 07:59:15 -0700 Subject: [PATCH 0680/1594] Fix #3059 by returning both hb_deal and hb_deal_${bidder_code} (#3062) * Fix #3059 by returning both hb_deal and hb_deal_${bidder_code} * Add unit test per @mkendall07 --- src/targeting.js | 13 ++++++++++--- test/spec/unit/core/targeting_spec.js | 15 ++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index d645a8ed20d..4bd3adbd9fc 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -259,9 +259,16 @@ export function newTargeting(auctionManager) { typeof winner.sendStandardTargeting === 'undefined' || winner.sendStandardTargeting || standardKeys.indexOf(key) === -1) - .map(key => ({ - [(key === 'hb_deal') ? `${key}_${winner.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH) : key.substring(0, MAX_DFP_KEYLENGTH)]: [winner.adserverTargeting[key]] - })) + .reduce((acc, key) => { + const targetingValue = [winner.adserverTargeting[key]]; + const targeting = { [key.substring(0, MAX_DFP_KEYLENGTH)]: targetingValue }; + if (key === 'hb_deal') { + const bidderCodeTargetingKey = `${key}_${winner.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH); + const bidderCodeTargeting = { [bidderCodeTargetingKey]: targetingValue }; + return [...acc, targeting, bidderCodeTargeting]; + } + return [...acc, targeting]; + }, []) }; }); diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 2fdca462a35..a72992e099d 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -30,6 +30,7 @@ const bid1 = { 'hb_bidder': 'rubicon', 'hb_adid': '148018fe5e', 'hb_pb': '0.53', + 'hb_deal': '1234', 'foobar': '300x250' }, 'netRevenue': true, @@ -120,6 +121,18 @@ describe('targeting tests', function () { targetingModule.isBidNotExpired.restore(); }); + describe('when hb_deal is present in bid.adserverTargeting', function () { + it('returns targeting with both hb_deal and hb_deal_{bidder_code}', function () { + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // We should add both keys rather than one or the other + expect(targeting['/123456/header-bid-tag-0']).to.contain.keys('hb_deal', `hb_deal_${bid1.bidderCode}`); + + // We should assign both keys the same value + expect(targeting['/123456/header-bid-tag-0']['hb_deal']).to.deep.equal(targeting['/123456/header-bid-tag-0'][`hb_deal_${bid1.bidderCode}`]); + }); + }); + it('selects the top bid when _sendAllBids true', function () { config.setConfig({ enableSendAllBids: true }); let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); @@ -127,7 +140,7 @@ describe('targeting tests', function () { // we should only get the targeting data for the one requested adunit expect(Object.keys(targeting).length).to.equal(1); - let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf('hb_pb_') != -1) + let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf('hb_pb_') != -1); // we shouldn't get more than 1 key for hb_pb_${bidder} expect(sendAllBidCpm.length).to.equal(1); From f46fcc8d29f5c169f6489f64cb892c6c221b112a Mon Sep 17 00:00:00 2001 From: christopher-allene-piximedia Date: Tue, 11 Sep 2018 17:08:19 +0200 Subject: [PATCH 0681/1594] Add Piximedia adapter (#3063) * Add Piximedia adapter * Fix piximediaBidAdapter_spec.js style --- modules/piximediaBidAdapter.js | 46 ++++++++ modules/piximediaBidAdapter.md | 25 +++++ test/spec/modules/piximediaBidAdapter_spec.js | 102 ++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 modules/piximediaBidAdapter.js create mode 100644 modules/piximediaBidAdapter.md create mode 100644 test/spec/modules/piximediaBidAdapter_spec.js diff --git a/modules/piximediaBidAdapter.js b/modules/piximediaBidAdapter.js new file mode 100644 index 00000000000..bf894116d7b --- /dev/null +++ b/modules/piximediaBidAdapter.js @@ -0,0 +1,46 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'piximedia'; +const ENDPOINT = '//ad.piximedia.com/prebid'; + +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: function(bid) { + return !!(bid.params && bid.params.siteId && bid.params.placementId); + }, + buildRequests: function(validBidRequests) { + return validBidRequests.map(bidRequest => { + let parseSized = utils.parseSizesInput(bidRequest.sizes); + let arrSize = parseSized[0].split('x'); + return { + method: 'GET', + url: ENDPOINT, + data: { + timestamp: utils.timestamp(), + pver: '1.0', + pbparams: JSON.stringify(bidRequest.params), + pbwidth: arrSize[0], + pbheight: arrSize[1], + pbbidid: bidRequest.bidId, + }, + }; + }); + }, + interpretResponse: function(serverResponse, request) { + const res = serverResponse.body; + const bidResponse = { + requestId: res.bidId, + cpm: parseFloat(res.cpm), + width: res.width, + height: res.height, + creativeId: res.creative_id, + currency: res.currency, + netRevenue: true, + ttl: 300, + ad: res.adm + }; + return [bidResponse]; + } +} +registerBidder(spec); diff --git a/modules/piximediaBidAdapter.md b/modules/piximediaBidAdapter.md new file mode 100644 index 00000000000..fae014cbdff --- /dev/null +++ b/modules/piximediaBidAdapter.md @@ -0,0 +1,25 @@ +# Overview + +**Module Name**: Piximedia Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: contact@piximedia.fr + +# Description + +Piximedia Bidder Adapter for Prebid.js. + +# Test Parameters +``` + var adUnits = [{ + code: 'mpu', + sizes: [[300, 250]], + bids: [{ + bidder: 'piximedia', + params: { + siteId: 'PIXIMEDIA', + placementId: 'PREBID' + } + }] + }]; + +``` diff --git a/test/spec/modules/piximediaBidAdapter_spec.js b/test/spec/modules/piximediaBidAdapter_spec.js new file mode 100644 index 00000000000..02cf80c614f --- /dev/null +++ b/test/spec/modules/piximediaBidAdapter_spec.js @@ -0,0 +1,102 @@ +import { expect } from 'chai'; +import { spec } from 'modules/piximediaBidAdapter'; + +describe('piximediaAdapterTest', function() { + describe('bidRequestValidity', function() { + it('bidRequest with site ID and placement ID param', function() { + expect(spec.isBidRequestValid({ + bidder: 'piximedia', + params: { + 'siteId': 'PIXIMEDIA_PREBID10', + 'placementId': 'RG' + }, + })).to.equal(true); + }); + + it('bidRequest with no required params', function() { + expect(spec.isBidRequestValid({ + bidder: 'piximedia', + params: { + }, + })).to.equal(false); + }); + }); + + describe('bidRequest', function() { + const bidRequests = [{ + 'bidder': 'piximedia', + 'params': { + 'siteId': 'PIXIMEDIA_PREBID10', + 'placementId': 'RG' + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [300, 250], + 'bidId': '51ef8751f9aead', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }]; + + it('bidRequest HTTP method', function() { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + }); + }); + + it('bidRequest data', function() { + const requests = spec.buildRequests(bidRequests); + expect(typeof requests[0].data.timestamp).to.equal('number'); + expect(requests[0].data.pver).to.equal('1.0'); + expect(requests[0].data.pbparams).to.equal(JSON.stringify(bidRequests[0].params)); + expect(requests[0].data.pbwidth).to.equal('300'); + expect(requests[0].data.pbheight).to.equal('250'); + expect(requests[0].data.pbbidid).to.equal('51ef8751f9aead'); + }); + }); + + describe('interpretResponse', function() { + const bidRequest = { + 'method': 'GET', + 'url': 'https://ad.piximedia.com/', + 'data': { + 'ver': 2, + 'hb': 1, + 'output': 'js', + 'pub': 267, + 'zone': 62546, + 'width': '300', + 'height': '250', + 'callback': 'json', + 'callback_uid': '51ef8751f9aead', + 'url': 'https://example.com', + 'cb': '', + } + }; + + const bidResponse = { + body: { + 'bidId': '51ef8751f9aead', + 'cpm': 4.2, + 'width': '300', + 'height': '250', + 'creative_id': '1234', + 'currency': 'EUR', + 'adm': '
', + }, + headers: {} + }; + + it('result is correct', function() { + const result = spec.interpretResponse(bidResponse, bidRequest); + expect(result[0].requestId).to.equal('51ef8751f9aead'); + expect(result[0].cpm).to.equal(4.2); + expect(result[0].width).to.equal('300'); + expect(result[0].height).to.equal('250'); + expect(result[0].creativeId).to.equal('1234'); + expect(result[0].currency).to.equal('EUR'); + expect(result[0].ttl).to.equal(300); + expect(result[0].ad).to.equal('
'); + }); + }); +}); From 640fa2ba89cc880b916e7fd38bd52f75b0f9d7b6 Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Wed, 12 Sep 2018 01:52:38 +0530 Subject: [PATCH 0682/1594] Media.net Adapter Improvements (#2954) * Media.net bid adapter: firing logs on 'bidWon' and 'onTimeout' events * Media.net Bid Adapter: removed use of prebid global to save page meta data --- modules/medianetBidAdapter.js | 77 +++++++++++++++++++- src/adaptermanager.js | 4 +- src/auction.js | 2 +- test/spec/modules/medianetBidAdapter_spec.js | 7 +- 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 07c721371bd..aee26f0ae3e 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -1,6 +1,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; import { config } from 'src/config'; +import * as url from 'src/url'; const BIDDER_CODE = 'medianet'; const BID_URL = '//prebid.media.net/rtb/prebid'; @@ -9,6 +10,13 @@ const SLOT_VISIBILITY = { ABOVE_THE_FOLD: 1, BELOW_THE_FOLD: 2 }; +const EVENTS = { + TIMEOUT_EVENT_NAME: 'client_timeout', + BID_WON_EVENT_NAME: 'client_bid_won' +}; +const EVENT_PIXEL_URL = 'qsearch-a.akamaihd.net/log'; + +let mnData = {}; $$PREBID_GLOBAL$$.medianetGlobals = {}; @@ -24,15 +32,20 @@ function siteDetails(site) { } function getPageMeta() { + if (mnData.pageMeta) { + return mnData.pageMeta; + } let canonicalUrl = getUrlFromSelector('link[rel="canonical"]', 'href'); let ogUrl = getUrlFromSelector('meta[property="og:url"]', 'content'); let twitterUrl = getUrlFromSelector('meta[name="twitter:url"]', 'content'); - return Object.assign({}, + mnData.pageMeta = Object.assign({}, canonicalUrl && { 'canonical_url': canonicalUrl }, ogUrl && { 'og_url': ogUrl }, twitterUrl && { 'twitter_url': twitterUrl } ); + + return mnData.pageMeta; } function getUrlFromSelector(selector, attribute) { @@ -218,6 +231,39 @@ function fetchCookieSyncUrls(response) { return []; } +function getLoggingData(event, data) { + data = (utils.isArray(data) && data) || []; + + let params = {}; + params.logid = 'kfk'; + params.evtid = 'projectevents'; + params.project = 'prebid'; + params.acid = utils.deepAccess(data, '0.auctionId') || ''; + params.cid = $$PREBID_GLOBAL$$.medianetGlobals.cid || ''; + params.crid = data.map((adunit) => utils.deepAccess(adunit, 'params.0.crid') || adunit.adUnitCode).join('|'); + params.adunit_count = data.length || 0; + params.dn = utils.getTopWindowLocation().host || ''; + params.requrl = utils.getTopWindowUrl() || ''; + params.event = event.name || ''; + params.value = event.value || ''; + params.rd = event.related_data || ''; + + return params; +} + +function logEvent (event, data) { + let getParams = { + protocol: 'https', + hostname: EVENT_PIXEL_URL, + search: getLoggingData(event, data) + }; + utils.triggerPixel(url.format(getParams)); +} + +function clearMnData() { + mnData = {}; +} + export const spec = { code: BIDDER_CODE, @@ -296,6 +342,35 @@ export const spec = { } }, + /** + * @param {TimedOutBid} timeoutData + */ + onTimeout: (timeoutData) => { + try { + let eventData = { + name: EVENTS.TIMEOUT_EVENT_NAME, + value: timeoutData.length, + related_data: timeoutData[0].timeout || config.getConfig('bidderTimeout') + }; + logEvent(eventData, timeoutData); + } catch (e) {} + }, + + /** + * @param {TimedOutBid} timeoutData + */ + onBidWon: (bid) => { + try { + let eventData = { + name: EVENTS.BID_WON_EVENT_NAME, + value: bid.cpm + }; + logEvent(eventData, [bid]); + } catch (e) {} + }, + + clearMnData, + getWindowSize, }; registerBidder(spec); diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 009ba18347b..8dd750b916a 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -521,6 +521,8 @@ exports.callTimedOutBidders = function(adUnits, timedOutBidders, cbTimeout) { }); } -exports.callBidWonBidder = function(bidder, bid) { +exports.callBidWonBidder = function(bidder, bid, adUnits) { + // Adding user configured params to bidWon event data + bid.params = utils.getUserConfiguredParams(adUnits, bid.adUnitCode, bid.bidder); tryCallBidderMethod(bidder, 'onBidWon', bid); }; diff --git a/src/auction.js b/src/auction.js index e2db713dd93..fd46c5fec16 100644 --- a/src/auction.js +++ b/src/auction.js @@ -281,7 +281,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) function addWinningBid(winningBid) { _winningBids = _winningBids.concat(winningBid); - adaptermanager.callBidWonBidder(winningBid.bidder, winningBid); + adaptermanager.callBidWonBidder(winningBid.bidder, winningBid, adUnits); } return { diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index bb55ed99e02..331b36b3217 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -562,8 +562,11 @@ describe('Media.net bid adapter', function () { expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_FOR_GDPR); }); - describe('build requests: when page meta-data is available', function () { - it('should pass canonical, twitter and fb paramters if available', function () { + describe('build requests: when page meta-data is available', () => { + beforeEach(() => { + spec.clearMnData(); + }); + it('should pass canonical, twitter and fb paramters if available', () => { let documentStub = sandbox.stub(window.top.document, 'querySelector'); documentStub.withArgs('link[rel="canonical"]').returns({ href: 'http://localhost:9999/canonical-test' From db694a074a4a2699566310aba4489b3cf6ede334 Mon Sep 17 00:00:00 2001 From: florevallatmrf <32760132+florevallatmrf@users.noreply.github.com> Date: Tue, 11 Sep 2018 23:13:58 +0200 Subject: [PATCH 0683/1594] Fix the secure creative resizing (#3066) * Fix the secure creative resize * do not use template litterals --- src/secureCreatives.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index cd289cf657f..1038afdf46a 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -72,8 +72,8 @@ function resizeRemoteCreative({ adUnitCode, width, height }) { // resize both container div + iframe ['div', 'iframe'].forEach(elmType => { let elementStyle = getElementByAdUnit(elmType).style; - elementStyle.width = width; - elementStyle.height = height; + elementStyle.width = width + 'px'; + elementStyle.height = height + 'px'; }); function getElementByAdUnit(elmType) { return document.getElementById(find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot) From 73e9ef15d298ce687f7e5593bfd03a53f61f7288 Mon Sep 17 00:00:00 2001 From: Jeremy Blencowe Date: Tue, 11 Sep 2018 14:14:51 -0700 Subject: [PATCH 0684/1594] AOL adapter - add defaults for currency and creative ID until fix issued server-side (#3068) * Add AOL defaults for currency and creative ID until fix issued server-side * Satisfy linter single quotes --- modules/aolBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 28e8cb0b46e..3d89007bbc2 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -387,9 +387,9 @@ export const spec = { cpm: cpm, width: bidData.w, height: bidData.h, - creativeId: bidData.crid, + creativeId: bidData.crid || 0, pubapiId: response.id, - currency: response.cur, + currency: response.cur || 'USD', dealId: bidData.dealid, netRevenue: true, ttl: bidRequest.ttl From f272031f1fc5f44c08ac7e0ebee5e47bf973dbe9 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 11 Sep 2018 17:33:48 -0400 Subject: [PATCH 0685/1594] Fix for early auction close with video + done cb cleanup (#3024) * done cb cleanup * rename some vars * added unit tests, updates after changes requested * add deprecated notice to function --- modules/prebidServerBidAdapter/index.js | 8 +- src/adaptermanager.js | 6 +- src/adapters/bidderFactory.js | 16 +--- src/auction.js | 114 +++++++++++++++--------- src/utils.js | 9 ++ src/video.js | 2 +- test/spec/auctionmanager_spec.js | 90 ++++++++++++++++--- 7 files changed, 161 insertions(+), 84 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 47c1bfa80db..f94cfeecec9 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -630,13 +630,7 @@ export function PrebidServer() { utils.logError('error parsing response: ', result.status); } - const videoBid = bids.some(bidResponse => bidResponse.bid.mediaType === 'video'); - const cacheEnabled = config.getConfig('cache.url'); - - // video bids with cache enabled need to be cached first before they are considered done - if (!(videoBid && cacheEnabled)) { - done(); - } + done(); doClientSideSyncs(requestedBidders); } diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 8dd750b916a..5b05578d303 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -335,8 +335,7 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbac if (s2sBidRequest.ad_units.length) { let doneCbs = serverBidRequests.map(bidRequest => { bidRequest.start = timestamp(); - bidRequest.doneCbCallCount = 0; - return doneCb(bidRequest.bidderRequestId) + return doneCb; }); // only log adapters that actually have adUnit bids @@ -372,12 +371,11 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbac utils.logMessage(`CALLING BIDDER ======= ${bidRequest.bidderCode}`); events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); bidRequest.doneCbCallCount = 0; - let done = doneCb(bidRequest.bidderRequestId); let ajax = ajaxBuilder(requestBidsTimeout, requestCallbacks ? { request: requestCallbacks.request.bind(null, bidRequest.bidderCode), done: requestCallbacks.done } : undefined); - adapter.callBids(bidRequest, addBidResponse, done, ajax); + adapter.callBids(bidRequest, addBidResponse, doneCb, ajax); }); } diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index b7574f24c08..d5ccf57e394 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -177,22 +177,8 @@ export function newBidder(spec) { // register any required usersync pixels. const responses = []; function afterAllResponses(bids) { - const bidsArray = bids ? (bids[0] ? bids : [bids]) : []; - - const videoBid = bidsArray.some(bid => bid.mediaType === 'video'); - const cacheEnabled = config.getConfig('cache.url'); - - // video bids with cache enabled need to be cached first before they are considered done - if (!(videoBid && cacheEnabled)) { - done(); - } - - // TODO: the code above needs to be refactored. We should always call done when we're done. if the auction - // needs to do cleanup before _it_ can be done it should handle that itself in the auction. It should _not_ - // require us, the bidders, to conditionally call done. That makes the whole done API very flaky. - // As soon as that is refactored, we can move this emit event where it should be, within the done function. + done(); events.emit(CONSTANTS.EVENTS.BIDDER_DONE, bidderRequest); - registerSyncs(responses, bidderRequest.gdprConsent); } diff --git a/src/auction.js b/src/auction.js index fd46c5fec16..280f3209b3a 100644 --- a/src/auction.js +++ b/src/auction.js @@ -48,7 +48,7 @@ * @property {function(): void} callBids - sends requests to all adapters for bids */ -import { uniques, flatten, timestamp, adUnitsFilter, delayExecution, getBidderRequest } from './utils'; +import { uniques, flatten, timestamp, adUnitsFilter, getBidderRequest, deepAccess } from './utils'; import { getPriceBucketString } from './cpmBucketManager'; import { getNativeTargeting } from './native'; import { getCacheUrl, store } from './videoCache'; @@ -58,6 +58,7 @@ import { userSync } from 'src/userSync'; import { createHook } from 'src/hook'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; +import { OUTSTREAM } from './video'; const { syncUsers } = userSync; const utils = require('./utils'); @@ -155,29 +156,21 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } - function done(bidRequestId) { - const innerBidRequestId = bidRequestId; - return delayExecution(function() { - const request = find(_bidderRequests, (bidRequest) => { - return innerBidRequestId === bidRequest.bidderRequestId; - }); - - // this is done for cache-enabled video bids in tryAddVideoBid, after the cache is stored - request.doneCbCallCount += 1; - bidsBackAll(); - }, 1); + function auctionDone(bidderCount) { + let doneCalled = 0; + return function() { + doneCalled++; + if (doneCalled === bidderCount) { + closeAuction(); + } + } } - /** - * Execute bidBackHandler if all bidders have called done. - */ - function bidsBackAll() { - if (_bidderRequests.every((bidRequest) => bidRequest.doneCbCallCount >= 1)) { - // when all bidders have called done callback atleast once it means auction is complete - utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); - _auctionStatus = AUCTION_COMPLETED; - executeCallback(false, true); - } + function closeAuction() { + // when all bidders have called done callback atleast once it means auction is complete + utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); + _auctionStatus = AUCTION_COMPLETED; + executeCallback(false, true); } function callBids() { @@ -206,7 +199,11 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) }; events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); - adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(this), done.bind(this), { + let callbacks = auctionCallbacks(auctionDone(bidRequests.length), this); + let boundObj = { + auctionAddBidResponse: callbacks.addBidResponse + } + adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(boundObj), callbacks.adapterDone, { request(source, origin) { increment(outstandingRequests, origin); increment(requests, source); @@ -288,7 +285,6 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) addBidReceived, executeCallback, callBids, - bidsBackAll, addWinningBid, getWinningBids: () => _winningBids, getTimeout: () => _timeout, @@ -301,6 +297,50 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } +export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid) { + this.auctionAddBidResponse(adUnitCode, bid); +}, 'addBidResponse'); + +export function auctionCallbacks(auctionDone, auctionInstance) { + let outstandingBidsAdded = 0; + let doneCalled = false; + + function afterBidAdded() { + outstandingBidsAdded--; + if (doneCalled && outstandingBidsAdded === 0) { + auctionDone() + } + } + + function addBidResponse(adUnitCode, bid) { + outstandingBidsAdded++; + let bidRequests = auctionInstance.getBidRequests(); + let auctionId = auctionInstance.getAuctionId(); + + let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); + let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}); + + if (bidResponse.mediaType === 'video') { + tryAddVideoBid(auctionInstance, bidResponse, afterBidAdded); + } else { + addBidToAuction(auctionInstance, bidResponse); + afterBidAdded(); + } + } + + function adapterDone() { + doneCalled = true; + if ((outstandingBidsAdded === 0)) { + auctionDone(); + } + } + + return { + addBidResponse, + adapterDone + } +} + function doCallbacksIfTimedout(auctionInstance, bidResponse) { if (bidResponse.timeToRespond > auctionInstance.getTimeout() + config.getConfig('timeoutBuffer')) { auctionInstance.executeCallback(true); @@ -316,9 +356,11 @@ function addBidToAuction(auctionInstance, bidResponse) { } // Video bids may fail if the cache is down, or there's trouble on the network. -function tryAddVideoBid(auctionInstance, bidResponse, bidRequest) { +function tryAddVideoBid(auctionInstance, bidResponse, afterBidAdded) { let addBid = true; - if (config.getConfig('cache.url')) { + const context = deepAccess(bidResponse, 'context'); + + if (config.getConfig('cache.url') && context !== OUTSTREAM) { if (!bidResponse.videoCacheKey) { addBid = false; store([bidResponse], function (error, cacheIds) { @@ -331,10 +373,8 @@ function tryAddVideoBid(auctionInstance, bidResponse, bidRequest) { if (!bidResponse.vastUrl) { bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); } - // only set this prop after the bid has been cached to avoid early ending auction early in bidsBackAll - bidRequest.doneCbCallCount += 1; addBidToAuction(auctionInstance, bidResponse); - auctionInstance.bidsBackAll(); + afterBidAdded(); } }); } else if (!bidResponse.vastUrl) { @@ -344,24 +384,10 @@ function tryAddVideoBid(auctionInstance, bidResponse, bidRequest) { } if (addBid) { addBidToAuction(auctionInstance, bidResponse); + afterBidAdded(); } } -export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid) { - let auctionInstance = this; - let bidRequests = auctionInstance.getBidRequests(); - let auctionId = auctionInstance.getAuctionId(); - - let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); - let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}); - - if (bidResponse.mediaType === 'video') { - tryAddVideoBid(auctionInstance, bidResponse, bidRequest); - } else { - addBidToAuction(auctionInstance, bidResponse); - } -}, 'addBidResponse'); - // 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, bidRequest, auctionId}) { diff --git a/src/utils.js b/src/utils.js index db50745ebcc..77dfe10c918 100644 --- a/src/utils.js +++ b/src/utils.js @@ -189,6 +189,9 @@ export function parseGPTSingleSizeArray(singleSize) { } }; +/** + * @deprecated This function will be removed soon + */ exports.getTopWindowLocation = function() { if (exports.inIframe()) { let loc; @@ -202,6 +205,9 @@ exports.getTopWindowLocation = function() { return exports.getWindowLocation(); } +/** + * @deprecated This function will be removed soon + */ exports.getTopFrameReferrer = function () { try { // force an exception in x-domain environments. #1509 @@ -221,6 +227,9 @@ exports.getTopFrameReferrer = function () { } }; +/** + * @deprecated This function will be removed soon + */ exports.getAncestorOrigins = function () { if (window.document.location && window.document.location.ancestorOrigins && window.document.location.ancestorOrigins.length >= 1) { diff --git a/src/video.js b/src/video.js index 8e0775a6d62..b0d03ab6377 100644 --- a/src/video.js +++ b/src/video.js @@ -4,7 +4,7 @@ import { config } from '../src/config'; import includes from 'core-js/library/fn/array/includes'; const VIDEO_MEDIA_TYPE = 'video'; -const OUTSTREAM = 'outstream'; +export const OUTSTREAM = 'outstream'; /** * Helper functions for working with video-enabled adUnits diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 0562479ca24..fae85310a38 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -1,5 +1,5 @@ import { auctionManager, newAuctionManager } from 'src/auctionManager'; -import { getKeyValueTargetingPairs } from 'src/auction'; +import { getKeyValueTargetingPairs, auctionCallbacks } from 'src/auction'; import CONSTANTS from 'src/constants.json'; import { adjustBids } from 'src/auction'; import * as auctionModule from 'src/auction'; @@ -44,7 +44,8 @@ function mockBid(opts) { 'creativeId': 'id', 'currency': 'USD', 'netRevenue': true, - 'ttl': 360 + 'ttl': 360, + getSize: () => '300x250' }; } @@ -54,6 +55,12 @@ function mockBidRequest(bid, opts) { } let bidderCode = opts && opts.bidderCode; let adUnitCode = opts && opts.adUnitCode; + let defaultMediaType = { + banner: { + sizes: [[300, 250], [300, 600]] + } + } + let mediaType = (opts && opts.mediaType) ? opts.mediaType : defaultMediaType; let requestId = utils.getUniqueIdentifierStr(); @@ -71,7 +78,8 @@ function mockBidRequest(bid, opts) { 'sizes': [[300, 250], [300, 600]], 'bidId': bid.requestId, 'bidderRequestId': requestId, - 'auctionId': '20882439e3238c' + 'auctionId': '20882439e3238c', + 'mediaTypes': mediaType } ], 'auctionStart': 1505250713622, @@ -107,16 +115,6 @@ function mockAjaxBuilder() { } describe('auctionmanager.js', function () { - let xhr; - - before(function () { - xhr = sinon.useFakeXMLHttpRequest(); - }); - - after(function () { - xhr.restore(); - }); - describe('getKeyValueTargetingPairs', function () { const DEFAULT_BID = { cpm: 5.578, @@ -857,4 +855,70 @@ describe('auctionmanager.js', function () { store.store.restore(); }); }); + + describe('auctionCallbacks', function() { + let bids = TEST_BIDS; + let bidRequests; + let xhr; + let requests; + let doneSpy; + let auction = { + getBidRequests: () => bidRequests, + getAuctionId: () => '1', + addBidReceived: () => true, + getTimeout: () => 1000 + } + + beforeEach(() => { + doneSpy = sinon.spy(); + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = (request) => requests.push(request); + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }) + }); + + afterEach(() => { + doneSpy.reset(); + xhr.restore(); + config.resetConfig(); + }); + + it('should call auction done after bid is added to auction for mediaType banner', function () { + bidRequests = [ + mockBidRequest(bids[0]), + ]; + let cbs = auctionCallbacks(doneSpy, auction); + cbs.addBidResponse(ADUNIT_CODE, bids[0]); + cbs.adapterDone(); + assert.equal(doneSpy.callCount, 1); + }); + + it('should call auction done after prebid cache is complete for mediaType video', function() { + bids[0].mediaType = 'video'; + let opts = { + mediaType: { + video: { + context: 'instream', + playerSize: [640, 480], + }, + } + } + bidRequests = [ + mockBidRequest(bids[0], opts) + ] + + let cbs = auctionCallbacks(doneSpy, auction); + cbs.addBidResponse(ADUNIT_CODE, bids[0]); + assert.equal(doneSpy.callCount, 0); + const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; + const responseBody = `{"responses":[{"uuid":"${uuid}"}]}`; + requests[0].respond(200, { 'Content-Type': 'application/json' }, responseBody); + cbs.adapterDone(); + assert.equal(doneSpy.callCount, 1); + }) + }); }); From 079e27fa412e622a12b9b670471a3b30f90542df Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 12 Sep 2018 10:00:04 -0400 Subject: [PATCH 0686/1594] Add referer detection module (#3067) * add referere detection module * dont log all errors on console * Update message * Add jsdoc --- modules/appnexusBidAdapter.js | 10 ++ src/adaptermanager.js | 10 +- src/refererDetection.js | 152 +++++++++++++++++++ test/spec/modules/appnexusBidAdapter_spec.js | 26 ++++ test/spec/refererDetection_spec.js | 80 ++++++++++ 5 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 src/refererDetection.js create mode 100644 test/spec/refererDetection_spec.js diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 7dac4b8b182..1bffb80975f 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -107,6 +107,16 @@ export const spec = { }; } + if (bidderRequest && bidderRequest.refererInfo) { + let refererinfo = { + rd_ref: bidderRequest.refererInfo.referer, + rd_top: bidderRequest.refererInfo.reachedTop, + rd_ifs: bidderRequest.refererInfo.numIframes, + rd_stk: bidderRequest.refererInfo.stack.join(',') + } + payload.referrer_detection = refererinfo; + } + const payloadString = JSON.stringify(payload); return { method: 'POST', diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 5b05578d303..e851a9accc9 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -9,6 +9,7 @@ import { config, RANDOM } from 'src/config'; import includes from 'core-js/library/fn/array/includes'; import find from 'core-js/library/fn/array/find'; import { adunitCounter } from './adUnits'; +import { getRefererInfo } from './refererDetection'; var utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); @@ -97,7 +98,7 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { bidId: bid.bid_id || utils.getUniqueIdentifierStr(), bidderRequestId, auctionId, - bidRequestsCount: adunitCounter.getCounter(adUnit.code) + bidRequestsCount: adunitCounter.getCounter(adUnit.code), })); } return bids; @@ -165,6 +166,7 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, if (config.getConfig('bidderSequence') === RANDOM) { bidderCodes = shuffle(bidderCodes); } + const refererInfo = getRefererInfo(); let clientBidderCodes = bidderCodes; let clientTestAdapters = []; @@ -195,7 +197,8 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsS2SCopy, labels}), auctionStart: auctionStart, timeout: _s2sConfig.timeout, - src: CONSTANTS.S2S.SRC + src: CONSTANTS.S2S.SRC, + refererInfo }; if (bidderRequest.bids.length !== 0) { bidRequests.push(bidderRequest); @@ -228,7 +231,8 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, bidderRequestId, bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsClientCopy, labels}), auctionStart: auctionStart, - timeout: cbTimeout + timeout: cbTimeout, + refererInfo }; const adapter = _bidderRegistry[bidderCode]; if (!adapter) { diff --git a/src/refererDetection.js b/src/refererDetection.js new file mode 100644 index 00000000000..6292b65f92a --- /dev/null +++ b/src/refererDetection.js @@ -0,0 +1,152 @@ +import { logWarn } from './utils'; + +export function detectReferer(win) { + function getLevels() { + let levels = walkUpWindows(); + let ancestors = getAncestorOrigins(); + + if (ancestors) { + for (let i = 0, l = ancestors.length; i < l; i++) { + levels[i].ancestor = ancestors[i]; + } + } + return levels; + } + + function getAncestorOrigins() { + try { + if (!win.location.ancestorOrigins) { + return; + } + return win.location.ancestorOrigins; + } catch (e) { + // Ignore error + } + } + + function getPubUrlStack(levels) { + let stack = []; + let defUrl = null; + let encodedUrl = null; + let frameLocation = null; + let prevFrame = null; + let prevRef = null; + let ancestor = null; + let detectedRefererUrl = null; + + let i; + for (i = levels.length - 1; i >= 0; i--) { + try { + frameLocation = levels[i].location; + } catch (e) { + // Ignore error + } + + if (frameLocation) { + encodedUrl = encodeURIComponent(frameLocation); + stack.push(encodedUrl); + if (!detectedRefererUrl) { + detectedRefererUrl = encodedUrl; + } + } else if (i !== 0) { + prevFrame = levels[i - 1]; + try { + prevRef = prevFrame.referrer; + ancestor = prevFrame.ancestor; + } catch (e) { + // Ignore error + } + + if (prevRef) { + encodedUrl = encodeURIComponent(prevRef); + stack.push(encodedUrl); + if (!detectedRefererUrl) { + detectedRefererUrl = encodedUrl; + } + } else if (ancestor) { + encodedUrl = encodeURIComponent(ancestor); + stack.push(encodedUrl); + if (!detectedRefererUrl) { + detectedRefererUrl = encodedUrl; + } + } else { + stack.push(defUrl); + } + } else { + stack.push(defUrl); + } + } + return { + stack, + detectedRefererUrl + }; + } + + function walkUpWindows() { + let acc = []; + let currentWindow; + do { + try { + currentWindow = currentWindow ? currentWindow.parent : win; + try { + acc.push({ + referrer: currentWindow.document.referrer || null, + location: currentWindow.location.href || null, + isTop: (currentWindow == win.top) + }); + } catch (e) { + acc.push({ + referrer: null, + location: null, + isTop: (currentWindow == win.top) + }); + logWarn('Trying to access cross domain iframe. Continuing without referrer and location'); + } + } catch (e) { + acc.push({ + referrer: null, + location: null, + isTop: false + }); + return acc; + } + } while (currentWindow != win.top); + return acc; + } + + /** + * Referer info + * @typedef {Object} refererInfo + * @property {string} referer detected top url + * @property {boolean} reachedTop whether prebid was able to walk upto top window or not + * @property {number} numIframes number of iframes + * @property {string} stack comma separated urls of all origins + */ + + /** + * Get referer info + * @returns {refererInfo} + */ + function refererInfo() { + try { + let levels = getLevels(); + let numIframes = levels.length - 1; + let reachedTop = (levels[numIframes].location !== null || + (numIframes > 0 && levels[numIframes - 1].referrer !== null)); + let stackInfo = getPubUrlStack(levels); + + return { + referer: stackInfo.detectedRefererUrl, + reachedTop, + numIframes, + stack: stackInfo.stack, + }; + } catch (e) { + // Ignore error + } + } + + return refererInfo; +} + +export const getRefererInfo = detectReferer(window); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index d9e21a95f78..66568781a84 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -370,6 +370,32 @@ describe('AppNexusAdapter', function () { lng: -75.3009142 }); }); + + it('should add referer info to payload', function () { + const bidRequest = Object.assign({}, bidRequests[0]) + const bidderRequest = { + refererInfo: { + referer: 'http%3A%2F%2Fexample.com%2Fpage.html', + reachedTop: true, + numIframes: 2, + stack: [ + 'http%3A%2F%2Fexample.com%2Fpage.html', + 'http%3A%2F%2Fexample.com%2Fiframe1.html', + 'http%3A%2F%2Fexample.com%2Fiframe2.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: 'http%3A%2F%2Fexample.com%2Fpage.html', + rd_top: true, + rd_ifs: 2, + rd_stk: bidderRequest.refererInfo.stack.join(',') + }); + }); }) describe('interpretResponse', function () { diff --git a/test/spec/refererDetection_spec.js b/test/spec/refererDetection_spec.js new file mode 100644 index 00000000000..95a2d096389 --- /dev/null +++ b/test/spec/refererDetection_spec.js @@ -0,0 +1,80 @@ +import { detectReferer } from 'src/refererDetection'; +import { expect } from 'chai'; + +var mocks = { + createFakeWindow: function (referrer, href) { + return { + document: { + referrer: referrer + }, + location: { + href: href, + // TODO: add ancestorOrigins to increase test coverage + }, + parent: null, + top: null + }; + } +} + +describe('referer detection', () => { + it('should return referer details in nested friendly iframes', function() { + // Fake window object to test friendly iframes + // - Main page http://example.com/page.html + // - - Iframe1 http://example.com/iframe1.html + // - - - Iframe2 http://example.com/iframe2.html + let mockIframe2WinObject = mocks.createFakeWindow('http://example.com/iframe1.html', 'http://example.com/iframe2.html'); + let mockIframe1WinObject = mocks.createFakeWindow('http://example.com/page.html', 'http://example.com/iframe1.html'); + let mainWinObject = mocks.createFakeWindow('http://example.com/page.html', 'http://example.com/page.html'); + mockIframe2WinObject.parent = mockIframe1WinObject; + mockIframe2WinObject.top = mainWinObject; + mockIframe1WinObject.parent = mainWinObject; + mockIframe1WinObject.top = mainWinObject; + mainWinObject.top = mainWinObject; + + const getRefererInfo = detectReferer(mockIframe2WinObject); + let result = getRefererInfo(); + let expectedResult = { + referer: 'http%3A%2F%2Fexample.com%2Fpage.html', + reachedTop: true, + numIframes: 2, + stack: [ + 'http%3A%2F%2Fexample.com%2Fpage.html', + 'http%3A%2F%2Fexample.com%2Fiframe1.html', + 'http%3A%2F%2Fexample.com%2Fiframe2.html' + ] + }; + expect(result).to.deep.equal(expectedResult); + }); + + it('should return referer details in nested cross domain iframes', function() { + // Fake window object to test cross domain iframes. + // - Main page http://example.com/page.html + // - - Iframe1 http://aaa.com/iframe1.html + // - - - Iframe2 http://bbb.com/iframe2.html + let mockIframe2WinObject = mocks.createFakeWindow('http://aaa.com/iframe1.html', 'http://bbb.com/iframe2.html'); + // Sinon cannot throw exception when accessing a propery so passing null to create cross domain + // environment for refererDetection module + let mockIframe1WinObject = mocks.createFakeWindow(null, null); + let mainWinObject = mocks.createFakeWindow(null, null); + mockIframe2WinObject.parent = mockIframe1WinObject; + mockIframe2WinObject.top = mainWinObject; + mockIframe1WinObject.parent = mainWinObject; + mockIframe1WinObject.top = mainWinObject; + mainWinObject.top = mainWinObject; + + const getRefererInfo = detectReferer(mockIframe2WinObject); + let result = getRefererInfo(); + let expectedResult = { + referer: 'http%3A%2F%2Faaa.com%2Fiframe1.html', + reachedTop: false, + numIframes: 2, + stack: [ + null, + 'http%3A%2F%2Faaa.com%2Fiframe1.html', + 'http%3A%2F%2Fbbb.com%2Fiframe2.html' + ] + }; + expect(result).to.deep.equal(expectedResult); + }); +}); From 004256f65376181e52ad6e6df5fde4ea0c825e9d Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 12 Sep 2018 13:22:09 -0600 Subject: [PATCH 0687/1594] Allow multiple media type rubcion bid w/ invalid video to go through as banner (#3037) --- modules/rubiconBidAdapter.js | 84 ++++++++++++++------- test/spec/modules/rubiconBidAdapter_spec.js | 23 +++++- 2 files changed, 78 insertions(+), 29 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 0f66aa36fb0..5b57172ac2e 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -10,9 +10,9 @@ function isSecure() { } // use protocol relative urls for http or https -const FASTLANE_ENDPOINT = '//fastlane.rubiconproject.com/a/api/fastlane.json'; -const VIDEO_ENDPOINT = '//fastlane-adv.rubiconproject.com/v1/auction/video'; -const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html'; +export const FASTLANE_ENDPOINT = '//fastlane.rubiconproject.com/a/api/fastlane.json'; +export const VIDEO_ENDPOINT = '//fastlane-adv.rubiconproject.com/v1/auction/video'; +export const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html'; const TIMEOUT_BUFFER = 500; @@ -94,26 +94,7 @@ export const spec = { return false; } - if (hasVideoMediaType(bid)) { - // Log warning if mediaTypes contains both 'banner' and 'video' - if (utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'instream' || bid.mediaType === VIDEO) { - if (typeof utils.deepAccess(bid, 'params.video.size_id') === 'undefined') { - utils.logError('Rubicon bid adapter Error: size id is missing for instream video request.'); - return false; - } - } else if (utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream') { - if (utils.deepAccess(bid, 'params.video.size_id') !== 203) { - utils.logWarn('Rubicon bid adapter Warning: outstream video is sending invalid size id, converting size id to 203.'); - } - } else { - utils.logError('Rubicon bid adapter Error: no instream or outstream context defined in mediaTypes.'); - return false; - } - if (typeof utils.deepAccess(bid, `mediaTypes.${BANNER}`) !== 'undefined') { - utils.logWarn('Rubicon bid adapter Warning: video and banner requested for same ad unit, continuing with video request, multi-format request is not supported by rubicon yet.'); - } - } - return parseSizes(bid).length > 0; + return !!bidType(bid, true); }, /** * @param {BidRequest[]} bidRequests @@ -123,7 +104,7 @@ export const spec = { buildRequests: function (bidRequests, bidderRequest) { // separate video bids because the requests are structured differently let requests = []; - const videoRequests = bidRequests.filter(hasVideoMediaType).map(bidRequest => { + const videoRequests = bidRequests.filter(bidRequest => bidType(bidRequest) === 'video').map(bidRequest => { bidRequest.startTime = new Date().getTime(); let params = bidRequest.params; @@ -190,7 +171,7 @@ export const spec = { if (config.getConfig('rubicon.singleRequest') !== true) { // bids are not grouped if single request mode is not enabled - requests = videoRequests.concat(bidRequests.filter(bidRequest => !hasVideoMediaType(bidRequest)).map(bidRequest => { + requests = videoRequests.concat(bidRequests.filter(bidRequest => bidType(bidRequest) === 'banner').map(bidRequest => { const bidParams = spec.createSlotParams(bidRequest, bidderRequest); return { method: 'GET', @@ -205,7 +186,7 @@ export const spec = { } else { // single request requires bids to be grouped by site id into a single request // note: utils.groupBy wasn't used because deep property access was needed - const nonVideoRequests = bidRequests.filter(bidRequest => !hasVideoMediaType(bidRequest)); + const nonVideoRequests = bidRequests.filter(bidRequest => bidType(bidRequest) === 'banner'); const groupedBidRequests = nonVideoRequests.reduce((groupedBids, bid) => { (groupedBids[bid.params['siteId']] = groupedBids[bid.params['siteId']] || []).push(bid); return groupedBids; @@ -394,7 +375,7 @@ export const spec = { let ads = responseObj.ads; // video ads array is wrapped in an object - if (typeof bidRequest === 'object' && !Array.isArray(bidRequest) && hasVideoMediaType(bidRequest) && typeof ads === 'object') { + if (typeof bidRequest === 'object' && !Array.isArray(bidRequest) && bidType(bidRequest) === 'video' && typeof ads === 'object') { ads = ads[bidRequest.adUnitCode]; } @@ -595,6 +576,55 @@ export function hasVideoMediaType(bidRequest) { return bidRequest.mediaType === VIDEO || typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'; } +/** + * Determine bidRequest mediaType + * @param bid the bid to test + * @param log whether we should log errors/warnings for invalid bids + * @returns {string|undefined} Returns 'video' or 'banner' if resolves to a type, or undefined otherwise (invalid). + */ +function bidType(bid, log = false) { + let validVideo; + if (hasVideoMediaType(bid)) { + validVideo = true; + + if (utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'instream' || bid.mediaType === VIDEO) { + if (typeof utils.deepAccess(bid, 'params.video.size_id') === 'undefined') { + if (log) { + utils.logError('Rubicon bid adapter Error: size id is missing for instream video request.'); + } + validVideo = false; + } + } else if (utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream') { + if (utils.deepAccess(bid, 'params.video.size_id') !== 203) { + if (log) { + utils.logWarn('Rubicon bid adapter Warning: outstream video is sending invalid size id, converting size id to 203.'); + } + } + } else { + if (log) { + utils.logError('Rubicon bid adapter Error: no instream or outstream context defined in mediaTypes.'); + } + validVideo = false; + } + if (validVideo) { + if (typeof utils.deepAccess(bid, `mediaTypes.${BANNER}`) !== 'undefined') { + if (log) { + utils.logWarn('Rubicon bid adapter Warning: video and banner requested for same adUnit, continuing with video request, multi-format request is not supported by rubicon yet.'); + } + } + return 'video'; + } else if (typeof utils.deepAccess(bid, `mediaTypes.${BANNER}`) === 'undefined') { + return undefined; + } + } + if (parseSizes(bid).length > 0) { + if (log && validVideo === false) { + utils.logWarn('Rubicon bid adapter Warning: invalid video requested for adUnit, continuing with banner request.'); + } + return 'banner'; + } +} + export function masSizeOrdering(sizes) { const MAS_SIZE_PRIORITY = [15, 2, 9]; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 3afb424c824..d685f4330d9 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1,6 +1,6 @@ import {expect} from 'chai'; import adapterManager from 'src/adaptermanager'; -import {spec, masSizeOrdering, resetUserSync, hasVideoMediaType} from 'modules/rubiconBidAdapter'; +import {spec, masSizeOrdering, resetUserSync, hasVideoMediaType, FASTLANE_ENDPOINT} from 'modules/rubiconBidAdapter'; import {parse as parseQuery} from 'querystring'; import {newBidder} from 'src/adapters/bidderFactory'; import {userSync} from 'src/userSync'; @@ -1286,7 +1286,26 @@ describe('the rubicon adapter', function () { expect(request.data.slots[0].size_id).to.equal(203); }); - it('should get size from bid.sizes too', function () { + it('should send request as banner when invalid video bid in multiple mediaType bidRequest', function () { + createVideoBidderRequestNoVideo(); + + let bid = bidderRequest.bids[0]; + bid.mediaTypes.banner = { + sizes: [[300, 250]] + }; + + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + + const bidRequestCopy = clone(bidderRequest); + + let requests = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal(FASTLANE_ENDPOINT); + }); + + it('should get size from bid.sizes too', () => { createVideoBidderRequestNoPlayer(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 From b3f878874b3bae1f05207c002e646debb0ab88d4 Mon Sep 17 00:00:00 2001 From: harpere Date: Wed, 12 Sep 2018 15:35:07 -0400 Subject: [PATCH 0688/1594] rubicon adapter - make sure creativeId is not empty (#3082) --- modules/rubiconBidAdapter.js | 2 +- test/spec/modules/rubiconBidAdapter_spec.js | 123 ++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 5b57172ac2e..2f4f3e01ce4 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -396,7 +396,7 @@ export const spec = { let bid = { requestId: associatedBidRequest.bidId, currency: 'USD', - creativeId: ad.creative_id, + creativeId: ad.creative_id || `${ad.network || ''}-${ad.advertiser || ''}`, cpm: ad.cpm || 0, dealId: ad.deal, ttl: 300, // 5 minutes diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index d685f4330d9..76859729455 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1553,6 +1553,129 @@ describe('the rubicon adapter', function () { expect(bids[1].rubiconTargeting.rpfl_14062).to.equal('15_tier_all_test'); }); + it('should use "network-advertiser" if no creative_id', function () { + let response = { + 'status': 'ok', + 'account_id': 14062, + 'site_id': 70608, + 'zone_id': 530022, + 'size_id': 15, + 'alt_size_ids': [ + 43, 10, 2 + ], + 'tracking': '', + 'inventory': {} + }; + + response.ads = [ + { + 'status': 'ok', + 'impression_id': '153dc240-8229-4604-b8f5-256933b9374c', + 'size_id': '15', + 'ad_id': '6', + 'advertiser': 7, + 'network': 8, + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': 10, + 'cpm': 0.811, + 'targeting': [ + { + 'key': 'rpfl_14062', + 'values': [ + '15_tier_all_test' + ] + } + ] + } + ]; + + let bids = spec.interpretResponse({body: response}, { + bidRequest: bidderRequest.bids[0] + }); + expect(bids[0].creativeId).to.equal('8-7'); + + response.ads = [ + { + 'status': 'ok', + 'impression_id': '153dc240-8229-4604-b8f5-256933b9374d', + 'size_id': '43', + 'ad_id': '7', + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': 10, + 'cpm': 0.911, + 'targeting': [ + { + 'key': 'rpfl_14062', + 'values': [ + '43_tier_all_test' + ] + } + ] + } + ]; + + bids = spec.interpretResponse({body: response}, { + bidRequest: bidderRequest.bids[0] + }); + expect(bids[0].creativeId).to.equal('-'); + + response.ads = [ + { + 'status': 'ok', + 'impression_id': '153dc240-8229-4604-b8f5-256933b9374d', + 'size_id': '10', + 'ad_id': '7', + 'network': 8, + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': 10, + 'cpm': 0.911, + 'targeting': [ + { + 'key': 'rpfl_14062', + 'values': [ + '10_tier_all_test' + ] + } + ] + } + ]; + + bids = spec.interpretResponse({body: response}, { + bidRequest: bidderRequest.bids[0] + }); + expect(bids[0].creativeId).to.equal('8-'); + + response.ads = [ + { + 'status': 'ok', + 'impression_id': '153dc240-8229-4604-b8f5-256933b9374d', + 'size_id': '2', + 'ad_id': '7', + 'advertiser': 7, + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': 10, + 'cpm': 0.911, + 'targeting': [ + { + 'key': 'rpfl_14062', + 'values': [ + '2_tier_all_test' + ] + } + ] + } + ]; + + bids = spec.interpretResponse({body: response}, { + bidRequest: bidderRequest.bids[0] + }); + expect(bids[0].creativeId).to.equal('-7'); + }); + it('should be fine with a CPM of 0', function () { let response = { 'status': 'ok', From 8e50d5d13c21dcfe6a9dd91d89a1f6231f946ed1 Mon Sep 17 00:00:00 2001 From: Zachary Lester Date: Wed, 12 Sep 2018 13:22:22 -0700 Subject: [PATCH 0689/1594] Fix #3055 and maintain compatibility with Node v4.0.0 by removing .includes from build process (#3073) --- gulpfile.js | 2 +- webpack.conf.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index b373e6299c6..ced29b266a7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -181,7 +181,7 @@ function bundle(dev, moduleArr) { var allModules = helpers.getModuleNames(modules); if (modules.length === 0) { - modules = allModules.filter(module => !explicitModules.includes(module)); + modules = allModules.filter(module => explicitModules.indexOf(module) === -1); } else { var diff = _.difference(modules, allModules); if (diff.length !== 0) { diff --git a/webpack.conf.js b/webpack.conf.js index 4b53aabef22..1048cb94386 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -19,7 +19,7 @@ module.exports = { ], }, output: { - jsonpFunction: prebid.globalVarName+"Chunk" + jsonpFunction: prebid.globalVarName + "Chunk" }, module: { rules: [ @@ -88,7 +88,7 @@ module.exports = { name: 'prebid', filename: 'prebid-core.js', minChunks: function(module, count) { - return !(count < 2 || neverBundle.includes(path.basename(module.resource))) + return !(count < 2 || neverBundle.indexOf(path.basename(module.resource)) !== -1) } }) ] From 1ce1280239d29eb1e2c4fd230ffcd1ddda2425e7 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 12 Sep 2018 16:24:15 -0400 Subject: [PATCH 0690/1594] Prebid 1.24.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9d2de7d4e37..4a6dd51cd5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.24.0-pre", + "version": "1.24.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 94a9692969ad25037c0f520d1bda4415262d73ed Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 12 Sep 2018 16:52:48 -0400 Subject: [PATCH 0691/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4a6dd51cd5a..f4c7756b7d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.24.0", + "version": "1.25.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 6c0f21da2f7ab98fd0243147e2e4f893142e1b6a Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Thu, 13 Sep 2018 15:45:08 +0300 Subject: [PATCH 0692/1594] Update README.md (#3083) * Update README.md fix broken link to PR review page * Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 137374ebaa7..a89f68b8abc 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ Many SSPs, bidders, and publishers have contributed to this project. [60+ Bidder For guidelines, see [Contributing](./CONTRIBUTING.md). -Our PR review process can be found [here](https://github.com/prebid/Prebid.js/tree/master/pr_review.md). +Our PR review process can be found [here](https://github.com/prebid/Prebid.js/tree/master/PR_REVIEW.md). ### Add a Bidder Adapter From 95bcf54efab6f312d11d6a99beea7be0622f951e Mon Sep 17 00:00:00 2001 From: "Tom Riley (Coull)" Date: Thu, 13 Sep 2018 20:58:27 +0100 Subject: [PATCH 0693/1594] Wrap window.top reference with try/catch in aardvark adapter (#3080) --- modules/aardvarkBidAdapter.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index 6a4c8b99572..3569999b998 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -28,9 +28,12 @@ export const spec = { var referer = utils.getTopWindowUrl(); var pageCategories = []; - if (window.top.rtkcategories && Array.isArray(window.top.rtkcategories)) { - pageCategories = window.top.rtkcategories; - } + // This reference to window.top can cause issues when loaded in an iframe if not protected with a try/catch. + try { + if (window.top.rtkcategories && Array.isArray(window.top.rtkcategories)) { + pageCategories = window.top.rtkcategories; + } + } catch (e) {} utils._each(validBidRequests, function(b) { var rMap = requestsMap[b.params.ai]; From d0161e93cbb8803c66d3c09d154b1b225cfe21c8 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Sat, 15 Sep 2018 00:59:23 +0100 Subject: [PATCH 0694/1594] Audience Network: deprecate fullwidth format, prefer 300x250 (#3085) --- modules/audienceNetworkBidAdapter.js | 39 +++++++++++++------ modules/audienceNetworkBidAdapter.md | 2 +- .../modules/audienceNetworkBidAdapter_spec.js | 27 +++++-------- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 544670863b8..6733b6ec007 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -3,7 +3,7 @@ */ import { registerBidder } from 'src/adapters/bidderFactory'; import { formatQS } from 'src/url'; -import { generateUUID, getTopWindowUrl, isSafariBrowser, convertTypes } from 'src/utils'; +import { generateUUID, getTopWindowUrl, convertTypes } from 'src/utils'; import findIndex from 'core-js/library/fn/array/find-index'; import includes from 'core-js/library/fn/array/includes'; @@ -18,7 +18,7 @@ const ttl = 600; const videoTtl = 3600; const platver = '$prebid.version$'; const platform = '241394079772386'; -const adapterver = '1.0.1'; +const adapterver = '1.1.0'; /** * Does this bid request contain valid parameters? @@ -73,6 +73,22 @@ const isValidSizeAndFormat = (size, format) => isValidNonSizedFormat(format) || isValidSize(flattenSize(size)); +/** + * Find a preferred entry, if any, from an array of valid sizes. + * @param {Array} acc + * @param {String} cur + */ +const sortByPreferredSize = (acc, cur) => + (cur === '300x250') ? [cur, ...acc] : [...acc, cur]; + +/** + * Map any deprecated size/formats to new values. + * @param {String} size + * @param {String} format + */ +const mapDeprecatedSizeAndFormat = (size, format) => + isFullWidth(format) ? ['300x250', null] : [size, format]; + /** * Is this a video format? * @param {String} format @@ -142,9 +158,9 @@ const getTopWindowUrlEncoded = () => encodeURIComponent(getTopWindowUrl()); * @param {Object} bids[].params * @param {String} bids[].params.placementId - Audience Network placement identifier * @param {String} bids[].params.platform - Audience Network platform identifier (optional) - * @param {String} bids[].params.format - Optional format, one of 'video', 'native' or 'fullwidth' if set + * @param {String} bids[].params.format - Optional format, one of 'video' or 'native' if set * @param {Array} bids[].sizes - list of desired advert sizes - * @param {Array} bids[].sizes[] - Size arrays [h,w]: should include one of [300, 250], [320, 50]: first matched size is used + * @param {Array} bids[].sizes[] - Size arrays [h,w]: should include one of [300, 250], [320, 50] * @returns {Array} List of URLs to fetch, plus formats and sizes for later use with interpretResponse */ const buildRequests = bids => { @@ -159,12 +175,14 @@ const buildRequests = bids => { bids.forEach(bid => bid.sizes .map(flattenSize) .filter(size => isValidSizeAndFormat(size, bid.params.format)) + .reduce(sortByPreferredSize, []) .slice(0, 1) - .forEach(size => { + .forEach(preferredSize => { + const [size, format] = mapDeprecatedSizeAndFormat(preferredSize, bid.params.format); placementids.push(bid.params.placementId); - adformats.push(bid.params.format || size); + adformats.push(format || size); sizes.push(size); - sdk.push(sdkVersion(bid.params.format)); + sdk.push(sdkVersion(format)); platforms.push(bid.params.platform); requestIds.push(bid.bidId); }) @@ -174,6 +192,7 @@ const buildRequests = bids => { const testmode = isTestmode(); const pageurl = getTopWindowUrlEncoded(); const platform = findPlatform(platforms); + const cb = generateUUID(); const search = { placementids, adformats, @@ -182,15 +201,13 @@ const buildRequests = bids => { sdk, adapterver, platform, - platver + platver, + cb }; const video = findIndex(adformats, isVideo); if (video !== -1) { [search.playerwidth, search.playerheight] = expandSize(sizes[video]); } - if (isSafariBrowser()) { - search.cb = generateUUID(); - } const data = formatQS(search); return [{ adformats, data, method, requestIds, sizes, url }]; diff --git a/modules/audienceNetworkBidAdapter.md b/modules/audienceNetworkBidAdapter.md index 72013c8610b..6147191f4b7 100644 --- a/modules/audienceNetworkBidAdapter.md +++ b/modules/audienceNetworkBidAdapter.md @@ -11,7 +11,7 @@ Maintainer: Lovell Fuller | Name | Scope | Description | Example | | :------------ | :------- | :---------------------------------------------- | :--------------------------------- | | `placementId` | required | The Placement ID from Audience Network | "555555555555555\_555555555555555" | -| `format` | optional | Format, one of "native", "fullwidth" or "video" | "native" | +| `format` | optional | Format, one of "native" or "video" | "native" | # Example ad units diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index 9e3f37b7395..2f7e5776354 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -19,7 +19,7 @@ const placementId = 'test-placement-id'; const playerwidth = 320; const playerheight = 180; const requestId = 'test-request-id'; -const debug = 'adapterver=1.0.1&platform=241394079772386&platver=$prebid.version$'; +const debug = 'adapterver=1.1.0&platform=241394079772386&platver=$prebid.version$&cb=test-uuid'; const pageUrl = encodeURIComponent(utils.getTopWindowUrl()); describe('AudienceNetwork adapter', function () { @@ -119,20 +119,21 @@ describe('AudienceNetwork adapter', function () { }); describe('buildRequests', function () { - let isSafariBrowserStub; before(function () { - isSafariBrowserStub = sinon.stub(utils, 'isSafariBrowser'); + sinon + .stub(utils, 'generateUUID') + .returns('test-uuid'); }); after(function () { - isSafariBrowserStub.restore(); + utils.generateUUID.restore(); }); it('can build URL for IAB unit', function () { expect(buildRequests([{ bidder, bidId: requestId, - sizes: [[300, 250], [320, 50]], + sizes: [[300, 50], [300, 250], [320, 50]], params: { placementId } }])).to.deep.equal([{ adformats: ['300x250'], @@ -182,7 +183,7 @@ describe('AudienceNetwork adapter', function () { }]); }); - it('can build URL for fullwidth 300x250 unit, overriding platform', function () { + it('can build URL for deprecated fullwidth unit, overriding platform', function () { const platform = 'test-platform'; const debugPlatform = debug.replace('241394079772386', platform); @@ -196,24 +197,14 @@ describe('AudienceNetwork adapter', function () { format: 'fullwidth' } }])).to.deep.equal([{ - adformats: ['fullwidth'], + adformats: ['300x250'], method: 'GET', requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debugPlatform}` + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debugPlatform}` }]); }); - - it('can build URL on Safari that includes a cachebuster param', function () { - isSafariBrowserStub.returns(true); - expect(buildRequests([{ - bidder, - bidId: requestId, - sizes: [[300, 250]], - params: { placementId } - }])[0].data).to.contain('&cb='); - }); }); describe('interpretResponse', function () { From aade9d5a845cd22630c2e4e1482610305725657a Mon Sep 17 00:00:00 2001 From: nwlosinski Date: Sat, 15 Sep 2018 02:05:16 +0200 Subject: [PATCH 0695/1594] JustPremium: fix for endpoint url (#3078) --- modules/justpremiumBidAdapter.js | 6 +++--- test/spec/modules/justpremiumBidAdapter_spec.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 0f38f586a4d..48b6805c0e1 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -2,8 +2,8 @@ import { registerBidder } from 'src/adapters/bidderFactory' import { getTopWindowLocation } from 'src/utils' const BIDDER_CODE = 'justpremium' -const ENDPOINT_URL = getTopWindowLocation().protocol + '//pre.ads.justpremium.com/v/2.0/t/xhr' -const JP_ADAPTER_VERSION = '1.2' +const ENDPOINT_URL = '//pre.ads.justpremium.com/v/2.0/t/xhr' +const JP_ADAPTER_VERSION = '1.3' const pixels = [] const TRACK_START_TIME = Date.now() let LAST_PAYLOAD = {} @@ -142,7 +142,7 @@ function track (data, payload, type) { let duration = Date.now() - TRACK_START_TIME - const pixelUrl = `${getTopWindowLocation().protocol}//emea-v3.tracking.justpremium.com/tracking.gif?rid=&sid=&uid=&vr=& + const pixelUrl = `//emea-v3.tracking.justpremium.com/tracking.gif?rid=&sid=&uid=&vr=& ru=${encodeURIComponent(pubUrl)}&tt=&siw=&sh=${payload.sh}&sw=${payload.sw}&wh=${payload.wh}&ww=${payload.ww}&an=&vn=& sd=&_c=&et=&aid=&said=&ei=&fc=&sp=&at=bidder&cid=&ist=&mg=&dl=&dlt=&ev=&vt=&zid=${payload.id}&dr=${duration}&di=&pr=& cw=&ch=&nt=&st=&jp=${encodeURIComponent(JSON.stringify(jp))}&ty=${type}` diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index da0e147bd29..3c1048143d2 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -53,7 +53,7 @@ describe('justpremium adapter', function () { expect(jpxRequest.id).to.equal(adUnits[0].params.zone) expect(jpxRequest.sizes).to.not.equal('undefined') expect(jpxRequest.version.prebid).to.equal('$prebid.version$') - expect(jpxRequest.version.jp_adapter).to.equal('1.2') + expect(jpxRequest.version.jp_adapter).to.equal('1.3') }) }) From 18bf25b744fe833c50a90080d64efa05bfc54ce3 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 17 Sep 2018 09:46:38 -0400 Subject: [PATCH 0696/1594] Fixes #3091 Auction closing prematurely (#3096) * auction closing early fix * minor updates after code review --- src/auction.js | 36 +++++++------- test/fixtures/fixtures.js | 56 +++++++++++----------- test/spec/auctionmanager_spec.js | 20 +++++++- test/spec/unit/core/adapterManager_spec.js | 10 ++-- 4 files changed, 68 insertions(+), 54 deletions(-) diff --git a/src/auction.js b/src/auction.js index 280f3209b3a..a77708486f2 100644 --- a/src/auction.js +++ b/src/auction.js @@ -48,7 +48,7 @@ * @property {function(): void} callBids - sends requests to all adapters for bids */ -import { uniques, flatten, timestamp, adUnitsFilter, getBidderRequest, deepAccess } from './utils'; +import { uniques, flatten, timestamp, adUnitsFilter, getBidderRequest, deepAccess, delayExecution, getBidRequest } from './utils'; import { getPriceBucketString } from './cpmBucketManager'; import { getNativeTargeting } from './native'; import { getCacheUrl, store } from './videoCache'; @@ -157,16 +157,6 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } function auctionDone(bidderCount) { - let doneCalled = 0; - return function() { - doneCalled++; - if (doneCalled === bidderCount) { - closeAuction(); - } - } - } - - function closeAuction() { // when all bidders have called done callback atleast once it means auction is complete utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); _auctionStatus = AUCTION_COMPLETED; @@ -199,7 +189,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) }; events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); - let callbacks = auctionCallbacks(auctionDone(bidRequests.length), this); + let callbacks = auctionCallbacks(auctionDone, this); let boundObj = { auctionAddBidResponse: callbacks.addBidResponse } @@ -303,11 +293,15 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid export function auctionCallbacks(auctionDone, auctionInstance) { let outstandingBidsAdded = 0; - let doneCalled = false; + let allAdapterCalledDone = false; + + let onAllAdapterDone = delayExecution(() => { + allAdapterCalledDone = true; + }, auctionInstance.getBidRequests().length); function afterBidAdded() { outstandingBidsAdded--; - if (doneCalled && outstandingBidsAdded === 0) { + if (allAdapterCalledDone && outstandingBidsAdded === 0) { auctionDone() } } @@ -321,7 +315,7 @@ export function auctionCallbacks(auctionDone, auctionInstance) { let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}); if (bidResponse.mediaType === 'video') { - tryAddVideoBid(auctionInstance, bidResponse, afterBidAdded); + tryAddVideoBid(auctionInstance, bidResponse, bidRequest, afterBidAdded); } else { addBidToAuction(auctionInstance, bidResponse); afterBidAdded(); @@ -329,8 +323,8 @@ export function auctionCallbacks(auctionDone, auctionInstance) { } function adapterDone() { - doneCalled = true; - if ((outstandingBidsAdded === 0)) { + onAllAdapterDone(); + if (allAdapterCalledDone && outstandingBidsAdded === 0) { auctionDone(); } } @@ -356,9 +350,13 @@ 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) { +function tryAddVideoBid(auctionInstance, bidResponse, bidRequests, afterBidAdded) { let addBid = true; - const context = deepAccess(bidResponse, 'context'); + + const bidRequest = getBidRequest(bidResponse.adId, [bidRequests]); + const videoMediaType = + bidRequest && deepAccess(bidRequest, 'mediaTypes.video'); + const context = videoMediaType && deepAccess(videoMediaType, 'context'); if (config.getConfig('cache.url') && context !== OUTSTREAM) { if (!bidResponse.videoCacheKey) { diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index fc59d7eeab3..75d998d4a09 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -13,7 +13,7 @@ export function getBidRequests() { 'placementId': '4799418', 'test': 'me' }, - 'placementCode': '/19968336/header-bid-tag1', + 'adUnitCode': '/19968336/header-bid-tag1', 'sizes': [ [ 728, @@ -36,7 +36,7 @@ export function getBidRequests() { 'params': { 'placementId': '4799418' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -68,7 +68,7 @@ export function getBidRequests() { 'publisherId': 39741, 'adSlot': '39620189@300x250' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -117,7 +117,7 @@ export function getBidRequests() { 10 ], }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -146,7 +146,7 @@ export function getBidRequests() { 'params': { 'inventoryCode': 'sortable_all_right_sports' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -176,7 +176,7 @@ export function getBidRequests() { 'params': { 'tagId': 16577 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -206,7 +206,7 @@ export function getBidRequests() { 'params': { 'placementId': '4799418' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -237,7 +237,7 @@ export function getBidRequests() { 'params': { 'placementId': '4799418' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -268,7 +268,7 @@ export function getBidRequests() { 'params': { 'aId': 3080 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -596,7 +596,7 @@ export function getAdUnits() { 'publisher_id': '1234567', 'bidfloor': 0.01 }, - 'placementCode': '/19968336/header-bid-tag1', + 'adUnitCode': '/19968336/header-bid-tag1', 'sizes': [ [ 728, @@ -617,7 +617,7 @@ export function getAdUnits() { 'placementId': '543221', 'test': 'me' }, - 'placementCode': '/19968336/header-bid-tag1', + 'adUnitCode': '/19968336/header-bid-tag1', 'sizes': [ [ 728, @@ -654,7 +654,7 @@ export function getAdUnits() { 'params': { 'placementId': '5324321' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -676,7 +676,7 @@ export function getAdUnits() { 'publisher_id': '12353433', 'bidfloor': 0.01 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -696,7 +696,7 @@ export function getAdUnits() { 'params': { 'inventoryCode': 'inv_code_here' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -719,7 +719,7 @@ export function getAdUnits() { 'supplyPartnerId': 1, 'test': true }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -759,7 +759,7 @@ export function getAdUnits() { 10 ] }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -780,7 +780,7 @@ export function getAdUnits() { 'jstag_url': 'http://servedbyopenx.com/w/1.0/jstag?nc=account_key', 'unit': 2345677 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -801,7 +801,7 @@ export function getAdUnits() { 'publisherId': 1234567, 'adSlot': '1234567@300x250' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -821,7 +821,7 @@ export function getAdUnits() { 'params': { 'placementId': '1234567' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -842,7 +842,7 @@ export function getAdUnits() { 'params': { 'placementId': '1234567' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -865,7 +865,7 @@ export function getAdUnits() { 'siteID': 123456, 'timeout': 10000 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -887,7 +887,7 @@ export function getAdUnits() { 'mid': 123456, 'test': 1 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -907,7 +907,7 @@ export function getAdUnits() { 'params': { 'aId': 3080 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -928,7 +928,7 @@ export function getAdUnits() { 'network': '112345.45', 'placement': 12345 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -948,7 +948,7 @@ export function getAdUnits() { 'params': { 'tagid': '123556' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -970,7 +970,7 @@ export function getAdUnits() { 'cp': 1233456, 'ct': 12357 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -990,7 +990,7 @@ export function getAdUnits() { 'params': { 'tagId': 75423 }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -1367,7 +1367,7 @@ export function getBidRequestedPayload() { 'publisher_id': '5000563', 'bidfloor': 0.01 }, - 'placementCode': '/19968336/header-bid-tag-1', + 'adUnitCode': '/19968336/header-bid-tag-1', 'sizes': [ [ 300, diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index fae85310a38..fa21050e78e 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -888,17 +888,30 @@ describe('auctionmanager.js', function () { }); it('should call auction done after bid is added to auction for mediaType banner', function () { + let ADUNIT_CODE2 = 'adUnitCode2'; + let BIDDER_CODE2 = 'sampleBidder2'; + + let bids1 = [mockBid({ bidderCode: BIDDER_CODE1 })]; + let bids2 = [mockBid({ bidderCode: BIDDER_CODE2 })]; bidRequests = [ mockBidRequest(bids[0]), + mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 }), + mockBidRequest(bids2[0], { adUnitCode: ADUNIT_CODE2 }) ]; let cbs = auctionCallbacks(doneSpy, auction); cbs.addBidResponse(ADUNIT_CODE, bids[0]); cbs.adapterDone(); + cbs.addBidResponse(ADUNIT_CODE1, bids1[0]); + cbs.adapterDone(); + cbs.addBidResponse(ADUNIT_CODE2, bids2[0]); + cbs.adapterDone(); assert.equal(doneSpy.callCount, 1); }); it('should call auction done after prebid cache is complete for mediaType video', function() { bids[0].mediaType = 'video'; + let bids1 = [mockBid({ bidderCode: BIDDER_CODE1 })]; + let opts = { mediaType: { video: { @@ -908,16 +921,19 @@ describe('auctionmanager.js', function () { } } bidRequests = [ - mockBidRequest(bids[0], opts) + mockBidRequest(bids[0], opts), + mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 }), ] let cbs = auctionCallbacks(doneSpy, auction); cbs.addBidResponse(ADUNIT_CODE, bids[0]); + cbs.adapterDone(); + cbs.addBidResponse(ADUNIT_CODE1, bids1[0]); + cbs.adapterDone(); assert.equal(doneSpy.callCount, 0); const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; const responseBody = `{"responses":[{"uuid":"${uuid}"}]}`; requests[0].respond(200, { 'Content-Type': 'application/json' }, responseBody); - cbs.adapterDone(); assert.equal(doneSpy.callCount, 1); }) }); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index fc4ef023743..644f10de794 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -175,7 +175,7 @@ describe('adapterManager tests', function () { 'placementId': '543221', 'test': 'me' }, - 'placementCode': '/19968336/header-bid-tag1', + 'adUnitCode': '/19968336/header-bid-tag1', 'sizes': [ [ 728, @@ -213,7 +213,7 @@ describe('adapterManager tests', function () { 'params': { 'placementId': '5324321' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -339,7 +339,7 @@ describe('adapterManager tests', function () { 'placementId': '543221', 'test': 'me' }, - 'placementCode': '/19968336/header-bid-tag1', + 'adUnitCode': '/19968336/header-bid-tag1', 'sizes': [ [ 728, @@ -377,7 +377,7 @@ describe('adapterManager tests', function () { 'params': { 'placementId': '5324321' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -911,7 +911,7 @@ describe('adapterManager tests', function () { expect(bidRequests[0].adUnitsS2SCopy.length).to.equal(1); expect(bidRequests[0].adUnitsS2SCopy[0].bids.length).to.equal(1); expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].bidder).to.equal('rubicon'); - expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].placementCode).to.equal(adUnits[1].code); + expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].adUnitCode).to.equal(adUnits[1].code); expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].bid_id).to.equal(bidRequests[0].bids[0].bid_id); expect(bidRequests[0].adUnitsS2SCopy[0].labelAny).to.deep.equal(['visitor-uk', 'desktop']); }); From 0b2ceb6b5d40a223e1275b29a0e69040bab26de7 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 17 Sep 2018 10:10:15 -0400 Subject: [PATCH 0697/1594] Prebid 1.24.1 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4c7756b7d2..4614d1f535d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.25.0-pre", + "version": "1.24.1", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 6101399a4b334a9e4bdcf7d33a373aa5290c09d0 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 17 Sep 2018 10:17:37 -0400 Subject: [PATCH 0698/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4614d1f535d..f4c7756b7d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.24.1", + "version": "1.25.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 6d51add4defcde83f3c29fa75b9b0afe1ee7477a Mon Sep 17 00:00:00 2001 From: ColombiaOnline Date: Tue, 18 Sep 2018 19:01:38 +0530 Subject: [PATCH 0699/1594] Add Colombia adapter (#2975) * Add colombia adapter * Add https in the url * update files * add test cases and update md file * remove native from package.json and update colombia test cases --- modules/colombiaBidAdapter.js | 72 +++++++++ modules/colombiaBidAdapter.md | 27 ++++ test/spec/modules/colombiaBidAdapter_spec.js | 152 +++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 modules/colombiaBidAdapter.js create mode 100644 modules/colombiaBidAdapter.md create mode 100644 test/spec/modules/colombiaBidAdapter_spec.js diff --git a/modules/colombiaBidAdapter.js b/modules/colombiaBidAdapter.js new file mode 100644 index 00000000000..f5a45deb619 --- /dev/null +++ b/modules/colombiaBidAdapter.js @@ -0,0 +1,72 @@ +import * as utils from 'src/utils'; +import {config} from 'src/config'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'colombia'; +const ENDPOINT_URL = 'https://ade.clmbtech.com/cde/prebid.htm'; +const HOST_NAME = document.location.protocol + '//' + window.location.host; + +export const spec = { + code: BIDDER_CODE, + aliases: ['clmb'], + isBidRequestValid: function(bid) { + return !!(bid.params.placementId); + }, + buildRequests: function(validBidRequests) { + return validBidRequests.map(bidRequest => { + const params = bidRequest.params; + const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; + const width = sizes.split('x')[0]; + const height = sizes.split('x')[1]; + const placementId = params.placementId; + const cb = Math.floor(Math.random() * 99999999999); + const referrer = encodeURIComponent(utils.getTopWindowUrl()); + const bidId = bidRequest.bidId; + const payload = { + v: 'hb1', + p: placementId, + w: width, + h: height, + cb: cb, + r: referrer, + uid: bidId, + t: 'i', + d: HOST_NAME, + }; + return { + method: 'POST', + url: ENDPOINT_URL, + data: payload, + } + }); + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + const response = serverResponse.body; + const crid = response.creativeId || 0; + const width = response.width || 0; + const height = response.height || 0; + const cpm = response.cpm || 0; + if (width !== 0 && height !== 0 && cpm !== 0 && crid !== 0) { + const dealId = response.dealid || ''; + const currency = response.currency || 'USD'; + const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; + const referrer = utils.getTopWindowUrl(); + const bidResponse = { + requestId: bidRequest.data.uid, + cpm: cpm, + width: response.width, + height: response.height, + creativeId: crid, + dealId: dealId, + currency: currency, + netRevenue: netRevenue, + ttl: config.getConfig('_bidderTimeout'), + referrer: referrer, + ad: response.ad + }; + bidResponses.push(bidResponse); + } + return bidResponses; + } +} +registerBidder(spec); diff --git a/modules/colombiaBidAdapter.md b/modules/colombiaBidAdapter.md new file mode 100644 index 00000000000..2131fcb4c5a --- /dev/null +++ b/modules/colombiaBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +``` +Module Name: COLOMBIA Bidder Adapter +Module Type: Bidder Adapter +Maintainer: colombiaonline@timesinteret.in +``` + +# Description + +Connect to COLOMBIA for bids. + +THE COLOMBIA adapter requires setup and approval from the COLOMBIA team. Please reach out to your account team or colombiaonline@timesinteret.in for more information. + +# Test Parameters +``` + var adUnits = [{ + code: 'test-ad-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'colombia', + params: { + placementId: '307466' + } + }] + }]; +``` diff --git a/test/spec/modules/colombiaBidAdapter_spec.js b/test/spec/modules/colombiaBidAdapter_spec.js new file mode 100644 index 00000000000..5a8678e866c --- /dev/null +++ b/test/spec/modules/colombiaBidAdapter_spec.js @@ -0,0 +1,152 @@ +import { expect } from 'chai'; +import { spec } from 'modules/colombiaBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const HOST_NAME = document.location.protocol + '//' + window.location.host; +const ENDPOINT = 'https://ade.clmbtech.com/cde/prebid.htm'; + +describe('colombiaBidAdapter', function() { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'colombia', + 'params': { + placementId: '307466' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when placementId not passed correctly', function () { + bid.params.placementId = ''; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when require params are not passed', function () { + let bid = Object.assign({}, bid); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'colombia', + 'params': { + placementId: '307466' + }, + 'adUnitCode': 'adunit-code1', + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }, + { + 'bidder': 'colombia', + 'params': { + placementId: '307466' + }, + 'adUnitCode': 'adunit-code2', + 'sizes': [ + [300, 250] + ], + 'bidId': '382091349b149f"', + 'bidderRequestId': '"1f9c98192de251"', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + } + ]; + + const request = spec.buildRequests(bidRequests); + + it('sends bid request to our endpoint via POST', function () { + expect(request[0].method).to.equal('POST'); + expect(request[1].method).to.equal('POST'); + }); + + 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('interpretResponse', function () { + let bidRequest = [ + { + 'method': 'POST', + 'url': ENDPOINT, + 'data': { + 'v': 'hb1', + 'p': '307466', + 'w': '300', + 'h': '250', + 'cb': 12892917383, + 'r': 'http%3A%2F%2Flocalhost%3A9876%2F%3Fid%3D74552836', + 'uid': '23beaa6af6cdde', + 't': 'i', + 'd': HOST_NAME + } + } + ]; + + let serverResponse = { + body: { + 'ad': '
This is test case
', + 'cpm': 3.14, + 'creativeId': '6b958110-612c-4b03-b6a9-7436c9f746dc-1sk24', + 'currency': 'USD', + 'statusMessage': 'Bid available', + 'uid': '23beaa6af6cdde', + 'width': 300, + 'height': 250, + 'netRevenue': true, + 'ttl': 600 + } + }; + + it('should get the correct bid response', function () { + let expectedResponse = [{ + 'requestId': '23beaa6af6cdde', + 'cpm': 3.14, + 'width': 300, + 'height': 250, + 'creativeId': '6b958110-612c-4b03-b6a9-7436c9f746dc-1sk24', + 'dealId': '', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 3000, + 'referrer': '', + 'ad': '
This is test case
' + }]; + let result = spec.interpretResponse(serverResponse, bidRequest[0]); + expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); + }); + + it('handles empty bid response', function () { + let response = { + body: { + 'uid': '2c0b634db95a01', + 'height': 0, + 'crid': '', + 'statusMessage': 'Bid returned empty or error response', + 'width': 0, + 'cpm': 0 + } + }; + let result = spec.interpretResponse(response, bidRequest[0]); + expect(result.length).to.equal(0); + }); + }); +}); From 0f929ec36d87ae3ea52a7510c8f56ae169a59608 Mon Sep 17 00:00:00 2001 From: iijimalo1023 <39043884+iijimalo1023@users.noreply.github.com> Date: Thu, 20 Sep 2018 04:02:28 +0900 Subject: [PATCH 0700/1594] Add new Adapter rdnBidAdapter (#3074) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add: Documentation of RDN BidAdapter * fix: inside documentation of Placement ID item area * add: RDN bid adapter * fix: modify ENDPOINT constant name * add: rdnBidAdapter_spec(work in progress) * add: interpretResponse unit test * fix: adUnits format * fix: adSpotId key * fix: interpretResponse process * fix: nobid response spec * fix: cpm value * change param key * Added UID sync correspondence. Expand the response SyncURL as a beacon. Delete language acquisition deplecated method. * Bid end point changed to destination. * test code url fixed * Corrected items pointed out · Extra definition deletion · Remove unnecessary processing * Added test code of getUserSyncs. * test parameter fixed. --- modules/rdnBidAdapter.js | 77 ++++++++++++++ modules/rdnBidAdapter.md | 33 ++++++ test/spec/modules/rdnBidAdapter_spec.js | 128 ++++++++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 modules/rdnBidAdapter.js create mode 100644 modules/rdnBidAdapter.md create mode 100644 test/spec/modules/rdnBidAdapter_spec.js diff --git a/modules/rdnBidAdapter.js b/modules/rdnBidAdapter.js new file mode 100644 index 00000000000..6a1d1fa93d0 --- /dev/null +++ b/modules/rdnBidAdapter.js @@ -0,0 +1,77 @@ +import { registerBidder } from 'src/adapters/bidderFactory' +import * as utils from 'src/utils' +import { BANNER } from 'src/mediaTypes' + +const BIDDER_CODE = 'rdn' +const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h' + +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: bid => !!bid.params.adSpotId, + buildRequests: validBidRequests => { + const bidRequests = [] + validBidRequests.forEach(bid => { + const params = bid.params + bidRequests.push({ + method: 'GET', + url: ENDPOINT, + data: { + bi: bid.bidId, + t: params.adSpotId, + s: document.location.protocol, + ua: navigator.userAgent, + l: + navigator.browserLanguage || + navigator.language, + d: document.domain, + tp: encodeURIComponent(utils.getTopWindowUrl()), + pp: encodeURIComponent(utils.getTopWindowReferrer()) + } + }) + }) + return bidRequests + }, + interpretResponse: (response, request) => { + const sb = response.body + const bidResponses = [] + bidResponses.push({ + requestId: sb.bid_id, + cpm: sb.cpm || 0, + width: sb.width || 0, + height: sb.height || 0, + creativeId: sb.creative_id || 0, + dealId: sb.deal_id || '', + currency: sb.currency || 'JPY', + netRevenue: (sb.net_revenue === undefined) ? true : sb.net_revenue, + mediaType: BANNER, + ttl: sb.ttl, + referrer: utils.getTopWindowUrl(), + ad: sb.ad + }) + + return bidResponses + }, + + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = []; + if (syncOptions.pixelEnabled && serverResponses[0].body !== undefined) { + const bidResponseObj = serverResponses[0].body; + if (!bidResponseObj) { + return []; + } + if (bidResponseObj.sync_urls && bidResponseObj.sync_urls.length > 0) { + bidResponseObj.sync_urls.forEach(syncUrl => { + if (syncUrl && syncUrl != 'null' && syncUrl.length > 0) { + syncs.push({ + type: 'image', + url: syncUrl + }); + } + }); + } + } + return syncs; + } +} + +registerBidder(spec) diff --git a/modules/rdnBidAdapter.md b/modules/rdnBidAdapter.md new file mode 100644 index 00000000000..9082c95c520 --- /dev/null +++ b/modules/rdnBidAdapter.md @@ -0,0 +1,33 @@ +# Overview + +``` +Module Name: RDN Bidder Adapter +Module Type: Bidder Adapter +Maintainer: engineer@lob-inc.com +``` + +# Description + +Connect to RDN for bids. + +RDN bid adapter supports Banner currently. + +# Test Parameters + +``` + var adUnits = [ + { + code: 'test-ad-div', + sizes: [[300, 250]], + mediaTypes: {banner: {}}, + bids: [ + { + bidder: 'rdn', + params: { + adSpotId: '10000' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/rdnBidAdapter_spec.js b/test/spec/modules/rdnBidAdapter_spec.js new file mode 100644 index 00000000000..1c5958c8065 --- /dev/null +++ b/test/spec/modules/rdnBidAdapter_spec.js @@ -0,0 +1,128 @@ +import { expect } from 'chai' +import * as utils from 'src/utils' +import { spec } from 'modules/rdnBidAdapter' +import { newBidder } from 'src/adapters/bidderFactory' + +describe('rdnBidAdapter', function() { + const adapter = newBidder(spec); + const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h'; + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function') + }) + }); + + describe('isBidRequestValid', () => { + let bid = { + bidder: 'rdn', + params: { + adSpotId: '56789' + } + }; + + 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', () => { + bid.params.adSpotId = ''; + 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', () => { + const bidRequests = [ + { + // banner + params: { + adSpotId: '58278' + } + } + ]; + + it('sends bid request to ENDPOINT via GET', () => { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('GET') + }) + }); + + describe('interpretResponse', () => { + const bidRequests = { + banner: { + method: 'GET', + url: '', + data: { + t: '56789', + s: 'https', + ua: + 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Mobile Safari/537.36', + l: 'ja', + d: 'examples.com', + tp: 'https://examples.com/foo/fuga', + pp: 'https://examples.com/hoge/muga' + } + } + }; + + const serverResponse = { + noAd: [], + banner: { + requestId: 'biequa9oaph4we', + cpm: 37.66, + width: 300, + height: 250, + creativeId: 140281, + dealId: 'phoh3pad-ai4ah-xoh7x-ahk7cheasae3oh', + currency: 'JPY', + netRevenue: 300, + ttl: 3000, + referrer: utils.getTopWindowUrl(), + ad: '' + } + }; + + it('handles nobid responses', () => { + const result = spec.interpretResponse( + { body: serverResponse.noAd }, + + bidRequests.banner + ); + expect(result.length).to.equal(1) + }) + }); + describe('spec.getUserSyncs', function () { + const syncResponse = [{ + body: { + request_id: 'biequa9oaph4we', + sync_urls: ['https://rdn1.test/sync?uid=9876543210', 'https://rdn2.test/sync?uid=9876543210'] + } + }]; + const nosyncResponse = [{ + body: { + request_id: 'biequa9oaph4we', + sync_urls: [] + } + }]; + let syncOptions + beforeEach(function () { + syncOptions = { + pixelEnabled: true + } + }); + it('sucess usersync url', function () { + const result = []; + result.push({type: 'image', url: 'https://rdn1.test/sync?uid=9876543210'}); + result.push({type: 'image', url: 'https://rdn2.test/sync?uid=9876543210'}); + expect(spec.getUserSyncs(syncOptions, syncResponse)).to.deep.equal(result); + }); + }); +}); From 46d53861a302a973c0f9287d67010b50435e00d6 Mon Sep 17 00:00:00 2001 From: Gleb Glushtsov Date: Wed, 19 Sep 2018 15:27:14 -0400 Subject: [PATCH 0701/1594] 33Across: add viewability (#3084) * check gdpr in buildRequest * User sync based on whether gdpr applies or not * check if consent data exists during user sync * split user sync into further branches: 1) when gdpr does not apply 2) when consent data is unavailable * contribute viewability to ttxRequest * update tests * remove window mock from tests * use local variables * introduce ServerRequestBuilder * add withOptions() method to ServerRequestBuilder * add semicolons * sync up package-lock.json with upstream/master * stub window.top in tests * introduce getTopWindowSize() for test purpose * reformat code * add withSite() method to TtxRequestBuilder add withSite() method to TtxRequestBuilder * add isIframe() and _isViewabilityMeasurable() * handle NON_MEASURABLE viewability in nested iframes * consider page visibility, stub utils functions getWindowTop() and getWindowSelf() * contribute viewability as 0 for inactive tab --- modules/33acrossBidAdapter.js | 165 ++++- test/spec/modules/33acrossBidAdapter_spec.js | 669 ++++++++++--------- 2 files changed, 514 insertions(+), 320 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 6b41c652152..497cf9f7110 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -1,12 +1,16 @@ -import { uniques } from 'src/utils'; +import * as utils from 'src/utils'; + const { registerBidder } = require('../src/adapters/bidderFactory'); const { config } = require('../src/config'); + const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch&rt=html'; const adapterState = {}; +const NON_MEASURABLE = 'nm'; + // All this assumes that only one bid is ever returned by ttx function _createBidResponse(response) { return { @@ -23,11 +27,30 @@ function _createBidResponse(response) { } } +function _isViewabilityMeasurable() { + return !_isIframe(); +} + +function _getViewability(element, topWin, { w, h } = {}) { + return utils.getWindowTop().document.visibilityState === 'visible' + ? _getPercentInView(element, topWin, { w, h }) + : 0; +} + // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request // NOTE: At this point, TTX only accepts request for a single impression function _createServerRequest(bidRequest, gdprConsent) { const ttxRequest = {}; const params = bidRequest.params; + const element = document.getElementById(bidRequest.adUnitCode); + const sizes = _transformSizes(bidRequest.sizes); + const minSize = _getMinSize(sizes); + + const viewabilityAmount = _isViewabilityMeasurable() + ? _getViewability(element, utils.getWindowTop(), minSize) + : NON_MEASURABLE; + + const contributeViewability = ViewabilityContributor(viewabilityAmount); /* * Infer data for the request payload @@ -35,14 +58,14 @@ function _createServerRequest(bidRequest, gdprConsent) { ttxRequest.imp = []; ttxRequest.imp[0] = { banner: { - format: bidRequest.sizes.map(_getFormatSize) + format: sizes.map(size => Object.assign(size, {ext: {}})) }, ext: { ttx: { prod: params.productId } } - } + }; ttxRequest.site = { id: params.siteId }; // Go ahead send the bidId in request to 33exchange so it's kept track of in the bid response and @@ -54,12 +77,12 @@ function _createServerRequest(bidRequest, gdprConsent) { ext: { consent: gdprConsent.consentString } - } + }; ttxRequest.regs = { ext: { gdpr: (gdprConsent.gdprApplies === true) ? 1 : 0 } - } + }; // Finally, set the openRTB 'test' param if this is to be a test bid if (params.test === 1) { @@ -81,7 +104,7 @@ function _createServerRequest(bidRequest, gdprConsent) { return { 'method': 'POST', 'url': url, - 'data': JSON.stringify(ttxRequest), + 'data': JSON.stringify(contributeViewability(ttxRequest)), 'options': options } } @@ -97,11 +120,118 @@ function _createSync(siteId) { } } -function _getFormatSize(sizeArr) { +function _getSize(size) { return { - w: sizeArr[0], - h: sizeArr[1], - ext: {} + w: parseInt(size[0], 10), + h: parseInt(size[1], 10) + } +} + +function _getMinSize(sizes) { + return sizes.reduce((min, size) => size.h * size.w < min.h * min.w ? size : min); +} + +function _getBoundingBox(element, { w, h } = {}) { + let { width, height, left, top, right, bottom } = element.getBoundingClientRect(); + + if ((width === 0 || height === 0) && w && h) { + width = w; + height = h; + right = left + w; + bottom = top + h; + } + + return { width, height, left, top, right, bottom }; +} + +function _transformSizes(sizes) { + if (utils.isArray(sizes) && sizes.length === 2 && !utils.isArray(sizes[0])) { + return [_getSize(sizes)]; + } + + return sizes.map(_getSize); +} + +function _getIntersectionOfRects(rects) { + const bbox = { + left: rects[0].left, + right: rects[0].right, + top: rects[0].top, + bottom: rects[0].bottom + }; + + for (let i = 1; i < rects.length; ++i) { + bbox.left = Math.max(bbox.left, rects[i].left); + bbox.right = Math.min(bbox.right, rects[i].right); + + if (bbox.left >= bbox.right) { + return null; + } + + bbox.top = Math.max(bbox.top, rects[i].top); + bbox.bottom = Math.min(bbox.bottom, rects[i].bottom); + + if (bbox.top >= bbox.bottom) { + return null; + } + } + + bbox.width = bbox.right - bbox.left; + bbox.height = bbox.bottom - bbox.top; + + return bbox; +} + +function _getPercentInView(element, topWin, { w, h } = {}) { + const elementBoundingBox = _getBoundingBox(element, { w, h }); + + // Obtain the intersection of the element and the viewport + const elementInViewBoundingBox = _getIntersectionOfRects([ { + left: 0, + top: 0, + right: topWin.innerWidth, + bottom: topWin.innerHeight + }, elementBoundingBox ]); + + let elementInViewArea, elementTotalArea; + + if (elementInViewBoundingBox !== null) { + // Some or all of the element is in view + elementInViewArea = elementInViewBoundingBox.width * elementInViewBoundingBox.height; + elementTotalArea = elementBoundingBox.width * elementBoundingBox.height; + + return ((elementInViewArea / elementTotalArea) * 100); + } + + // No overlap between element and the viewport; therefore, the element + // lies completely out of view + return 0; +} + +/** + * Viewability contribution to request.. + */ +function ViewabilityContributor(viewabilityAmount) { + function contributeViewability(ttxRequest) { + const req = Object.assign({}, ttxRequest); + const imp = req.imp = req.imp.map(impItem => Object.assign({}, impItem)); + const banner = imp[0].banner = Object.assign({}, imp[0].banner); + const ext = banner.ext = Object.assign({}, banner.ext); + const ttx = ext.ttx = Object.assign({}, ext.ttx); + + ttx.viewability = { amount: isNaN(viewabilityAmount) ? viewabilityAmount : Math.round(viewabilityAmount) }; + + return req; + } + + return contributeViewability; +} + +function _isIframe() { + try { + return utils.getWindowSelf() !== utils.getWindowTop(); + } catch (e) { + return true; } } @@ -122,9 +252,9 @@ function isBidRequestValid(bid) { // - the server, at this point, also doesn't need the consent string to handle gdpr compliance. So passing // value whether set or not, for the sake of future dev. function buildRequests(bidRequests, bidderRequest) { - const gdprConsent = Object.assign({ consentString: undefined, gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent) + const gdprConsent = Object.assign({ consentString: undefined, gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent); - adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(uniques); + adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(utils.uniques); return bidRequests.map((req) => { return _createServerRequest(req, gdprConsent); @@ -153,14 +283,15 @@ function getUserSyncs(syncOptions, responses, gdprConsent) { } } -const spec = { +export const spec = { + NON_MEASURABLE, + code: BIDDER_CODE, + isBidRequestValid, buildRequests, interpretResponse, - getUserSyncs -} + getUserSyncs, +}; registerBidder(spec); - -module.exports = spec; diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 2779209c1cf..c8f0421e1e6 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -1,23 +1,161 @@ -const { userSync } = require('../../../src/userSync'); -const { config } = require('../../../src/config'); +import { expect } from 'chai'; -const { expect } = require('chai'); -const { - isBidRequestValid, - buildRequests, - interpretResponse, - getUserSyncs -} = require('../../../modules/33acrossBidAdapter'); +import * as utils from 'src/utils'; +import { config } from 'src/config'; + +import { spec } from 'modules/33acrossBidAdapter'; describe('33acrossBidAdapter:', function () { const BIDDER_CODE = '33across'; const SITE_ID = 'pub1234'; const PRODUCT_ID = 'product1'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; - const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch&rt=html'; + + let element, win; + let bidRequests; + let sandbox; + + function TtxRequestBuilder() { + const ttxRequest = { + imp: [{ + banner: { + format: [ + { + w: 300, + h: 250, + ext: {} + }, + { + w: 728, + h: 90, + ext: {} + } + ], + ext: { + ttx: { + viewability: { + amount: 100 + } + } + } + }, + ext: { + ttx: { + prod: PRODUCT_ID + } + } + }], + site: { + id: SITE_ID + }, + id: 'b1', + user: { + ext: { + consent: undefined + } + }, + regs: { + ext: { + gdpr: 0 + } + } + }; + + this.withSizes = sizes => { + Object.assign(ttxRequest.imp[0].banner, { format: sizes }); + return this; + }; + + this.withViewabiliuty = viewability => { + Object.assign(ttxRequest.imp[0].banner, { + ext: { + ttx: { viewability } + } + }); + return this; + }; + + this.withGdprConsent = (consent, gdpr) => { + Object.assign(ttxRequest, { + user: { + ext: { consent } + } + }); + Object.assign(ttxRequest, { + regs: { + ext: { gdpr } + } + }); + return this; + }; + + this.withSite = site => { + Object.assign(ttxRequest, { site }); + return this; + }; + + this.build = () => ttxRequest; + } + + function ServerRequestBuilder() { + const serverRequest = { + 'method': 'POST', + 'url': END_POINT, + 'data': null, + 'options': { + 'contentType': 'text/plain', + 'withCredentials': true + } + }; + + this.withData = data => { + serverRequest['data'] = JSON.stringify(data); + return this; + }; + + this.withUrl = url => { + serverRequest['url'] = url; + return this; + }; + + this.withOptions = options => { + serverRequest['options'] = options; + return this; + }; + + this.build = () => serverRequest; + } beforeEach(function() { - this.bidRequests = [ + element = { + x: 0, + y: 0, + + width: 0, + height: 0, + + getBoundingClientRect: () => { + return { + width: element.width, + height: element.height, + + left: element.x, + top: element.y, + right: element.x + element.width, + bottom: element.y + element.height + }; + } + }; + win = { + document: { + visibilityState: 'visible' + }, + + innerWidth: 800, + innerHeight: 600 + }; + + bidRequests = [ { bidId: 'b1', bidder: '33across', @@ -29,21 +167,24 @@ describe('33acrossBidAdapter:', function () { adUnitCode: 'div-id', auctionId: 'r1', sizes: [ - [ 300, 250 ], - [ 728, 90 ] + [300, 250], + [728, 90] ], transactionId: 't1' } ]; - this.sandbox = sinon.sandbox.create(); + + sandbox = sinon.sandbox.create(); + sandbox.stub(document, 'getElementById').withArgs('div-id').returns(element); + sandbox.stub(utils, 'getWindowTop').returns(win); + sandbox.stub(utils, 'getWindowSelf').returns(win); }); afterEach(function() { - this.sandbox.restore(); - delete this.bidRequests; + sandbox.restore(); }); - describe('isBidRequestValid:', function () { + describe('isBidRequestValid:', function() { it('returns true when valid bid request is sent', function() { const validBid = { bidder: BIDDER_CODE, @@ -51,9 +192,9 @@ describe('33acrossBidAdapter:', function () { siteId: SITE_ID, productId: PRODUCT_ID } - } + }; - expect(isBidRequestValid(validBid)).to.be.true; + expect(spec.isBidRequestValid(validBid)).to.be.true; }); it('returns true when valid test bid request is sent', function() { @@ -64,29 +205,29 @@ describe('33acrossBidAdapter:', function () { productId: PRODUCT_ID, test: 1 } - } + }; - expect(isBidRequestValid(validBid)).to.be.true; + expect(spec.isBidRequestValid(validBid)).to.be.true; }); - it('returns false when bidder not set to "33across"', function () { + it('returns false when bidder not set to "33across"', function() { const invalidBid = { bidder: 'foo', params: { siteId: SITE_ID, productId: PRODUCT_ID } - } + }; - expect(isBidRequestValid(invalidBid)).to.be.false; + expect(spec.isBidRequestValid(invalidBid)).to.be.false; }); it('returns false when params not set', function() { const invalidBid = { bidder: 'foo' - } + }; - expect(isBidRequestValid(invalidBid)).to.be.false; + expect(spec.isBidRequestValid(invalidBid)).to.be.false; }); it('returns false when site ID is not set in params', function() { @@ -95,9 +236,9 @@ describe('33acrossBidAdapter:', function () { params: { productId: PRODUCT_ID } - } + }; - expect(isBidRequestValid(invalidBid)).to.be.false; + expect(spec.isBidRequestValid(invalidBid)).to.be.false; }); it('returns false when product ID not set in params', function() { @@ -106,16 +247,119 @@ describe('33acrossBidAdapter:', function () { params: { siteId: SITE_ID } - } + }; - expect(isBidRequestValid(invalidBid)).to.be.false; + expect(spec.isBidRequestValid(invalidBid)).to.be.false; }); }); describe('buildRequests:', function() { + context('when element is fully in view', function() { + it('returns 100', function() { + const ttxRequest = new TtxRequestBuilder() + .withViewabiliuty({amount: 100}) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + + Object.assign(element, { width: 600, height: 400 }); + + expect(spec.buildRequests(bidRequests)).to.deep.equal([ serverRequest ]); + }); + }); + + context('when element is out of view', function() { + it('returns 0', function() { + const ttxRequest = new TtxRequestBuilder() + .withViewabiliuty({amount: 0}) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + + Object.assign(element, { x: -300, y: 0, width: 207, height: 320 }); + + expect(spec.buildRequests(bidRequests)).to.deep.equal([ serverRequest ]); + }); + }); + + context('when element is partially in view', function() { + it('returns percentage', function() { + const ttxRequest = new TtxRequestBuilder() + .withViewabiliuty({amount: 75}) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + + Object.assign(element, { width: 800, height: 800 }); + + expect(spec.buildRequests(bidRequests)).to.deep.equal([ serverRequest ]); + }); + }); + + context('when width or height of the element is zero', function() { + it('try to use alternative values', function() { + const ttxRequest = new TtxRequestBuilder() + .withSizes([{ w: 800, h: 2400, ext: {} }]) + .withViewabiliuty({amount: 25}) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + + Object.assign(element, { width: 0, height: 0 }); + bidRequests[0].sizes = [[800, 2400]]; + + expect(spec.buildRequests(bidRequests)).to.deep.equal([ serverRequest ]); + }); + }); + + context('when nested iframes', function() { + it('returns \'nm\'', function() { + const ttxRequest = new TtxRequestBuilder() + .withViewabiliuty({amount: spec.NON_MEASURABLE}) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + + Object.assign(element, { width: 600, height: 400 }); + + utils.getWindowTop.restore(); + utils.getWindowSelf.restore(); + sandbox.stub(utils, 'getWindowTop').returns(win); + sandbox.stub(utils, 'getWindowSelf').returns({}); + + expect(spec.buildRequests(bidRequests)).to.deep.equal([ serverRequest ]); + }); + }); + + context('when tab is inactive', function() { + it('returns 0', function() { + const ttxRequest = new TtxRequestBuilder() + .withViewabiliuty({amount: 0}) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + + Object.assign(element, { width: 600, height: 400 }); + + utils.getWindowTop.restore(); + win.document.visibilityState = 'hidden'; + sandbox.stub(utils, 'getWindowTop').returns(win); + + expect(spec.buildRequests(bidRequests)).to.deep.equal([ serverRequest ]); + }); + }); + context('when gdpr consent data exists', function() { + let bidderRequest; + beforeEach(function() { - this.bidderRequest = { + bidderRequest = { gdprConsent: { consentString: 'foobarMyPreference', gdprApplies: true @@ -124,284 +368,93 @@ describe('33acrossBidAdapter:', function () { }); it('returns corresponding server requests with gdpr consent data', function() { - const ttxRequest = { - imp: [ { - banner: { - format: [ - { - w: 300, - h: 250, - ext: {} - }, - { - w: 728, - h: 90, - ext: {} - } - ] - }, - ext: { - ttx: { - prod: PRODUCT_ID - } - } - } ], - site: { - id: SITE_ID - }, - id: 'b1', - user: { - ext: { - consent: 'foobarMyPreference' - } - }, - regs: { - ext: { - gdpr: 1 - } - } - }; - - const serverRequest = { - 'method': 'POST', - 'url': END_POINT, - 'data': JSON.stringify(ttxRequest), - 'options': { - 'contentType': 'text/plain', - 'withCredentials': true - } - } - const builtServerRequests = buildRequests(this.bidRequests, this.bidderRequest); - expect(builtServerRequests).to.deep.equal([ serverRequest ]); - expect(builtServerRequests.length).to.equal(1); + const ttxRequest = new TtxRequestBuilder() + .withGdprConsent('foobarMyPreference', 1) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, bidderRequest); + + expect(builtServerRequests).to.deep.equal([serverRequest]); }); it('returns corresponding test server requests with gdpr consent data', function() { - this.sandbox.stub(config, 'getConfig').callsFake(() => { + sandbox.stub(config, 'getConfig').callsFake(() => { return { 'url': 'https://foo.com/hb/' } }); - const ttxRequest = { - imp: [ { - banner: { - format: [ - { - w: 300, - h: 250, - ext: { } - }, - { - w: 728, - h: 90, - ext: { } - } - ] - }, - ext: { - ttx: { - prod: PRODUCT_ID - } - } - } ], - site: { - id: SITE_ID - }, - id: 'b1', - user: { - ext: { - consent: 'foobarMyPreference' - } - }, - regs: { - ext: { - gdpr: 1 - } - } - }; - const serverRequest = { - method: 'POST', - url: 'https://foo.com/hb/', - data: JSON.stringify(ttxRequest), - options: { - contentType: 'text/plain', - withCredentials: true - } - }; + const ttxRequest = new TtxRequestBuilder() + .withGdprConsent('foobarMyPreference', 1) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .withUrl('https://foo.com/hb/') + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, bidderRequest); - const builtServerRequests = buildRequests(this.bidRequests, this.bidderRequest); - expect(builtServerRequests).to.deep.equal([ serverRequest ]); - expect(builtServerRequests.length).to.equal(1); + expect(builtServerRequests).to.deep.equal([serverRequest]); }); - - afterEach(function() { - delete this.bidderRequest; - }) }); context('when gdpr consent data does not exist', function() { + let bidderRequest; + beforeEach(function() { - this.bidderRequest = { } + bidderRequest = {}; }); it('returns corresponding server requests with default gdpr consent data', function() { - const ttxRequest = { - imp: [ { - banner: { - format: [ - { - w: 300, - h: 250, - ext: {} - }, - { - w: 728, - h: 90, - ext: {} - } - ] - }, - ext: { - ttx: { - prod: PRODUCT_ID - } - } - } ], - site: { - id: SITE_ID - }, - id: 'b1', - user: { - ext: { - consent: undefined - } - }, - regs: { - ext: { - gdpr: 0 - } - } - }; - - const serverRequest = { - 'method': 'POST', - 'url': END_POINT, - 'data': JSON.stringify(ttxRequest), - 'options': { - 'contentType': 'text/plain', - 'withCredentials': true - } - } - const builtServerRequests = buildRequests(this.bidRequests, this.bidderRequest); - expect(builtServerRequests).to.deep.equal([ serverRequest ]); - expect(builtServerRequests.length).to.equal(1); + const ttxRequest = new TtxRequestBuilder() + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, bidderRequest); + + expect(builtServerRequests).to.deep.equal([serverRequest]); }); it('returns corresponding test server requests with default gdpr consent data', function() { - this.sandbox.stub(config, 'getConfig').callsFake(() => { + sandbox.stub(config, 'getConfig').callsFake(() => { return { 'url': 'https://foo.com/hb/' } }); - const ttxRequest = { - imp: [ { - banner: { - format: [ - { - w: 300, - h: 250, - ext: { } - }, - { - w: 728, - h: 90, - ext: { } - } - ] - }, - ext: { - ttx: { - prod: PRODUCT_ID - } - } - } ], - site: { - id: SITE_ID - }, - id: 'b1', - user: { - ext: { - consent: undefined - } - }, - regs: { - ext: { - gdpr: 0 - } - } - }; - const serverRequest = { - method: 'POST', - url: 'https://foo.com/hb/', - data: JSON.stringify(ttxRequest), - options: { - contentType: 'text/plain', - withCredentials: true - } - }; + const ttxRequest = new TtxRequestBuilder() + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .withUrl('https://foo.com/hb/') + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, bidderRequest); - const builtServerRequests = buildRequests(this.bidRequests, this.bidderRequest); - expect(builtServerRequests).to.deep.equal([ serverRequest ]); - expect(builtServerRequests.length).to.equal(1); + expect(builtServerRequests).to.deep.equal([serverRequest]); }); - - afterEach(function() { - delete this.bidderRequest; - }) }); }); describe('interpretResponse', function() { + let ttxRequest, serverRequest; + beforeEach(function() { - this.ttxRequest = { - imp: [ { - banner: { - format: [ - { - w: 300, - h: 250, - ext: {} - }, - { - w: 728, - h: 90, - ext: {} - } - ] - }, - ext: { - ttx: { - prod: PRODUCT_ID - } - } - } ], - site: { + ttxRequest = new TtxRequestBuilder() + .withSite({ id: SITE_ID, page: 'http://test-url.com' - }, - id: 'b1' - }; - this.serverRequest = { - method: 'POST', - url: '//staging-ssc.33across.com/api/v1/hb', - data: JSON.stringify(this.ttxRequest), - options: { + }) + .build(); + serverRequest = new ServerRequestBuilder() + .withUrl('//staging-ssc.33across.com/api/v1/hb') + .withData(ttxRequest) + .withOptions({ contentType: 'text/plain', withCredentials: false - } - }; + }) + .build(); }); context('when exactly one bid is returned', function() { @@ -412,18 +465,17 @@ describe('33acrossBidAdapter:', function () { id: 'b1', seatbid: [ { - bid: [ { + bid: [{ id: '1', adm: '

I am an ad

', crid: 1, h: 250, w: 300, price: 0.0938 - } ] + }] } ] }; - const bidResponse = { requestId: 'b1', bidderCode: BIDDER_CODE, @@ -435,9 +487,9 @@ describe('33acrossBidAdapter:', function () { creativeId: 1, currency: 'USD', netRevenue: true - } + }; - expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([ bidResponse ]); + expect(spec.interpretResponse({ body: serverResponse }, serverRequest)).to.deep.equal([bidResponse]); }); }); @@ -450,7 +502,7 @@ describe('33acrossBidAdapter:', function () { seatbid: [] }; - expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([]); + expect(spec.interpretResponse({ body: serverResponse }, serverRequest)).to.deep.equal([]); }); }); @@ -462,7 +514,7 @@ describe('33acrossBidAdapter:', function () { id: 'b1', seatbid: [ { - bid: [ { + bid: [{ id: '1', adm: '

I am an ad

', crid: 1, @@ -481,18 +533,17 @@ describe('33acrossBidAdapter:', function () { ] }, { - bid: [ { + bid: [{ id: '3', adm: '

I am an ad

', crid: 3, h: 250, w: 300, price: 0.0938 - } ] + }] } ] }; - const bidResponse = { requestId: 'b1', bidderCode: BIDDER_CODE, @@ -506,14 +557,16 @@ describe('33acrossBidAdapter:', function () { netRevenue: true }; - expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([ bidResponse ]); + expect(spec.interpretResponse({ body: serverResponse }, serverRequest)).to.deep.equal([bidResponse]); }); }); }); describe('getUserSyncs', function() { + let syncs; + beforeEach(function() { - this.syncs = [ + syncs = [ { type: 'iframe', url: 'https://de.tynt.com/deb/v2?m=xch&rt=html&id=id1' @@ -523,7 +576,7 @@ describe('33acrossBidAdapter:', function () { url: 'https://de.tynt.com/deb/v2?m=xch&rt=html&id=id2' }, ]; - this.bidRequests = [ + bidRequests = [ { bidId: 'b1', bidder: '33across', @@ -535,7 +588,7 @@ describe('33acrossBidAdapter:', function () { adUnitCode: 'div-id', auctionId: 'r1', sizes: [ - [ 300, 250 ] + [300, 250] ], transactionId: 't1' }, @@ -550,7 +603,7 @@ describe('33acrossBidAdapter:', function () { adUnitCode: 'div-id', auctionId: 'r1', sizes: [ - [ 300, 250 ] + [300, 250] ], transactionId: 't2' } @@ -558,17 +611,21 @@ describe('33acrossBidAdapter:', function () { }); context('when gdpr does not apply', function() { + let gdprConsent; + beforeEach(function() { - this.gdprConsent = { + gdprConsent = { gdprApplies: false - } + }; }); context('when iframe is not enabled', function() { it('returns empty sync array', function() { const syncOptions = {}; - buildRequests(this.bidRequests); - expect(getUserSyncs(syncOptions, {}, this.gdprConsent)).to.deep.equal([]); + + spec.buildRequests(bidRequests); + + expect(spec.getUserSyncs(syncOptions, {}, gdprConsent)).to.deep.equal([]); }); }); @@ -577,9 +634,10 @@ describe('33acrossBidAdapter:', function () { const syncOptions = { iframeEnabled: true }; - buildRequests(this.bidRequests); - const syncs = getUserSyncs(syncOptions, {}, this.gdprConsent); - expect(syncs).to.deep.equal(this.syncs); + + spec.buildRequests(bidRequests); + + expect(spec.getUserSyncs(syncOptions, {}, gdprConsent)).to.deep.equal(syncs); }); }); }); @@ -588,8 +646,10 @@ describe('33acrossBidAdapter:', function () { context('when iframe is not enabled', function() { it('returns empty sync array', function() { const syncOptions = {}; - buildRequests(this.bidRequests); - expect(getUserSyncs(syncOptions)).to.deep.equal([]); + + spec.buildRequests(bidRequests); + + expect(spec.getUserSyncs(syncOptions)).to.deep.equal([]); }); }); @@ -598,9 +658,10 @@ describe('33acrossBidAdapter:', function () { const syncOptions = { iframeEnabled: true }; - buildRequests(this.bidRequests); - const syncs = getUserSyncs(syncOptions); - expect(syncs).to.deep.equal(this.syncs); + + spec.buildRequests(bidRequests); + + expect(spec.getUserSyncs(syncOptions)).to.deep.equal(syncs); }); }); }); @@ -610,9 +671,11 @@ describe('33acrossBidAdapter:', function () { const syncOptions = {}; const gdprConsent = { gdprApplies: true - } - buildRequests(this.bidRequests); - expect(getUserSyncs(syncOptions, {}, gdprConsent)).to.deep.equal([]); + }; + + spec.buildRequests(bidRequests); + + expect(spec.getUserSyncs(syncOptions, {}, gdprConsent)).to.deep.equal([]); }); }) }); From 1b97d55928f44e79e1ff68dda458f721c1cc4311 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Wed, 19 Sep 2018 14:08:27 -0700 Subject: [PATCH 0702/1594] add support for pubcid user opt-out (#3071) --- modules/pubCommonId.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/pubCommonId.js b/modules/pubCommonId.js index 58b91ae956c..2150a1f4444 100644 --- a/modules/pubCommonId.js +++ b/modules/pubCommonId.js @@ -93,7 +93,9 @@ export function initPubcid() { config.getConfig('pubcid', config => setConfig(config.pubcid)); if (utils.cookiesAreEnabled()) { - $$PREBID_GLOBAL$$.requestBids.addHook(requestBidHook); + if (!getCookie('_pubcid_optout')) { + $$PREBID_GLOBAL$$.requestBids.addHook(requestBidHook); + } } } From 84e1cbff48e27055bf60343c8d881ac9f94f6326 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Thu, 20 Sep 2018 14:46:19 -0400 Subject: [PATCH 0703/1594] add user syncing for kargo (#3099) --- modules/kargoBidAdapter.js | 37 +++++++++ test/spec/modules/kargoBidAdapter_spec.js | 93 +++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 1ba0f392d08..4f594c2856f 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -3,6 +3,8 @@ import {config} from 'src/config'; import {registerBidder} from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'kargo'; const HOST = 'https://krk.kargo.com'; +const SYNC = 'https://crb.kargo.com/api/v1/initsyncrnd/{UUID}?seed={SEED}&idx={INDEX}'; +const SYNC_COUNT = 5; export const spec = { code: BIDDER_CODE, isBidRequestValid: function(bid) { @@ -54,6 +56,20 @@ export const spec = { } return bidResponses; }, + getUserSyncs: function(syncOptions) { + const syncs = []; + const seed = spec._generateRandomUuid(); + const clientId = spec._getClientId(); + if (syncOptions.iframeEnabled && seed && clientId) { + for (let i = 0; i < SYNC_COUNT; i++) { + syncs.push({ + type: 'iframe', + url: SYNC.replace('{UUID}', clientId).replace('{SEED}', seed).replace('{INDEX}', i) + }); + } + } + return syncs; + }, // PRIVATE _readCookie(name) { @@ -150,6 +166,11 @@ export const spec = { }; }, + _getClientId() { + const uid = spec._getUid(); + return uid.clientId; + }, + _getAllMetadata() { return { userIDs: spec._getUserIds(), @@ -157,6 +178,22 @@ export const spec = { pageURL: window.location.href, rawCRB: spec._readCookie('krg_crb') }; + }, + + _generateRandomUuid() { + try { + // crypto.getRandomValues is supported everywhere but Opera Mini for years + 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, 8) + '-' + hex.slice(8, 12) + '-' + hex.slice(12, 16) + '-' + hex.slice(16, 20) + '-' + hex.slice(20); + } catch (e) { + return ''; + } } }; registerBidder(spec); diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index eafb5a9c0f3..c60d74e040a 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -387,4 +387,97 @@ describe('kargo adapter tests', function () { expect(resp).to.deep.equal(expectation); }); }); + + describe('user sync handler', function() { + const clientId = '74c81cbb-7d07-46d9-be9b-68ccb291c949'; + var shouldSimulateOutdatedBrowser, uid, isActuallyOutdatedBrowser; + + beforeEach(() => { + uid = {}; + shouldSimulateOutdatedBrowser = false; + isActuallyOutdatedBrowser = false; + + // IE11 fails these tests in the Prebid test suite. Since this + // browser won't support any of this stuff we expect all user + // syncing to fail gracefully. Kargo is mobile only, so this + // doesn't really matter. + if (!window.crypto) { + isActuallyOutdatedBrowser = true; + } else { + sandbox.stub(crypto, 'getRandomValues').callsFake(function(buf) { + if (shouldSimulateOutdatedBrowser) { + throw new Error('Could not generate random values'); + } + var bytes = [50, 5, 232, 133, 141, 55, 49, 57, 244, 126, 248, 44, 255, 38, 128, 0]; + for (var i = 0; i < bytes.length; i++) { + buf[i] = bytes[i]; + } + return buf; + }); + } + + sandbox.stub(spec, '_getUid').callsFake(function() { + return uid; + }); + }); + + function getUserSyncsWhenAllowed() { + return spec.getUserSyncs({iframeEnabled: true}); + } + + function getUserSyncsWhenForbidden() { + return spec.getUserSyncs({}); + } + + function turnOnClientId() { + uid.clientId = clientId; + } + + function simulateOutdatedBrowser() { + shouldSimulateOutdatedBrowser = true; + } + + function getSyncUrl(index) { + return { + type: 'iframe', + url: `https://crb.kargo.com/api/v1/initsyncrnd/${clientId}?seed=3205e885-8d37-4139-b47e-f82cff268000&idx=${index}` + }; + } + + function getSyncUrls() { + var syncs = []; + for (var i = 0; i < 5; i++) { + syncs[i] = getSyncUrl(i); + } + return syncs; + } + + function safelyRun(runExpectation) { + if (isActuallyOutdatedBrowser) { + expect(getUserSyncsWhenAllowed()).to.be.an('array').that.is.empty; + } else { + runExpectation(); + } + } + + it('handles user syncs when there is a client id', function() { + turnOnClientId(); + safelyRun(() => expect(getUserSyncsWhenAllowed()).to.deep.equal(getSyncUrls())); + }); + + it('no user syncs when there is no client id', function() { + safelyRun(() => expect(getUserSyncsWhenAllowed()).to.be.an('array').that.is.empty); + }); + + it('no user syncs when there is outdated browser', function() { + turnOnClientId(); + simulateOutdatedBrowser(); + safelyRun(() => expect(getUserSyncsWhenAllowed()).to.be.an('array').that.is.empty); + }); + + it('no user syncs when no iframe syncing allowed', function() { + turnOnClientId(); + safelyRun(() => expect(getUserSyncsWhenForbidden()).to.be.an('array').that.is.empty); + }); + }); }); From b7946e6465536e06d8872fb58e2b6f19c574f01e Mon Sep 17 00:00:00 2001 From: guillaume-sticky Date: Thu, 20 Sep 2018 21:03:47 +0200 Subject: [PATCH 0704/1594] Freewheel-ssp BidAdapter improvements (#3097) * add stickyadsTV bidder adapter * init unit test file * ad some unit tests * fix unit test on ad format with parameters * add some unit tests * add unit tests on getBid method * add some test cases in unit tests * minor fix on component id tag. * remove adapters-sticky.json test file * use top most accessible window instead of window.top * Pass in the bid request in the createBid call. * use top most accessible window instead of window.top * add unit tests * update unit tests * fix unit test. * fix CI build * add alias freewheel-ssp * update unit tests on bidderCode value * fix component id values and add unit tests * allws to use any outstream format. * fix ASLoader on futur outstream format versions * minor: fix code format. * update unit tests * minor fix code format * minor: add missing new line at eof * replace StickyAdsTVAdapter by freewheel ssp bd adapter (for prebid 1.0) * remove old stickyadstv unittest spec. * fix server response parsing if sent as object with 'body' field * use the vastXml field for video mediatype * add user sync pixel in freewheel ssp adapter * remove all console log calls (replaced using util helper) * remove useless bidderCode (automatically added by the bidderFactory) * Return the SYNC pixel to be added in the page by Prebid.js * remove instance level properties to enable concurrent bids with the same adapter instance. * fix the request apss through and corresponding unit tests * fix 'freeheelssp' typo * add vast parameters feature and GDPR params in VAST request * fix lint issues * add gdpr parameter support on freewheelSSPBidAdapter * use bidderrequest to read gdpr parameters and update unit tests * fix lint errors * fix lint errors * fix typo and bidderRequest reference. * fix bidderRequest reference. * add missing declaration for 'key' variable * rename frewheel ssp bid adapter files to match the bidder code (fix custom download issues) * update unit tests using the new name freewheel-ssp * update documented test zone to a more recent one * target created div insitead of original placement (avoid some misplaced ad) * fix target div size * add key and timestamp parameters for a better request identification. * Remove the arrow function call so the style is consistent throughout the file --- modules/freewheel-sspBidAdapter.js | 31 +- modules/freewheel-sspBidAdapter.md | 2 +- .../modules/freewheel-sspBidAdapter_spec.js | 394 +++++++++--------- 3 files changed, 222 insertions(+), 205 deletions(-) diff --git a/modules/freewheel-sspBidAdapter.js b/modules/freewheel-sspBidAdapter.js index 87c1979ac5d..321d5ee95e8 100644 --- a/modules/freewheel-sspBidAdapter.js +++ b/modules/freewheel-sspBidAdapter.js @@ -68,6 +68,18 @@ function getPricing(xmlNode) { return princingData; } +function hashcode(inputString) { + var hash = 0; + var char; + if (inputString.length == 0) return hash; + for (var i = 0; i < inputString.length; i++) { + char = inputString.charCodeAt(i); + hash = ((hash << 5) - hash) + char; + hash = hash & hash; // Convert to 32bit integer + } + return hash; +} + function getCreativeId(xmlNode) { var creaId = ''; var adNodes = xmlNode.querySelectorAll('Ad'); @@ -116,7 +128,7 @@ function getAPIName(componentId) { function formatAdHTML(bid, size) { var integrationType = bid.params.format; - var divHtml = '
'; + var divHtml = '
'; var script = ''; var libUrl = ''; @@ -161,13 +173,11 @@ var getInBannerScript = function(bid, size) { }; var getOutstreamScript = function(bid) { - var placementCode = bid.adUnitCode; - var config = bid.params; // default placement if no placement is set if (!config.hasOwnProperty('domId') && !config.hasOwnProperty('auto') && !config.hasOwnProperty('p') && !config.hasOwnProperty('article')) { - config.domId = placementCode; + config.domId = 'freewheelssp_prebid_target'; } var script = 'var config = {' + @@ -216,11 +226,17 @@ export const spec = { utils.logMessage('Prebid.JS - freewheel bid adapter: only one ad unit is required.'); } + var zone = currentBidRequest.params.zoneId; + var timeInMillis = new Date().getTime(); + var keyCode = hashcode(zone + '' + timeInMillis); + var requestParams = { reqType: 'AdsSetup', protocolVersion: '2.0', - zoneId: currentBidRequest.params.zoneId, - componentId: getComponentId(currentBidRequest.params.format) + zoneId: zone, + componentId: getComponentId(currentBidRequest.params.format), + timestamp: timeInMillis, + pKey: keyCode }; // Add GDPR flag and consent string @@ -330,6 +346,7 @@ export const spec = { url: USER_SYNC_URL }]; } - } + }, + } registerBidder(spec); diff --git a/modules/freewheel-sspBidAdapter.md b/modules/freewheel-sspBidAdapter.md index ba7915c87e1..70ab2415279 100644 --- a/modules/freewheel-sspBidAdapter.md +++ b/modules/freewheel-sspBidAdapter.md @@ -18,7 +18,7 @@ Module that connects to Freewheel ssp's demand sources { bidder: "freewheel-ssp", params: { - zoneId : '277225' + zoneId : '41852' } } ] diff --git a/test/spec/modules/freewheel-sspBidAdapter_spec.js b/test/spec/modules/freewheel-sspBidAdapter_spec.js index adc6e1bcde4..a1123cee151 100644 --- a/test/spec/modules/freewheel-sspBidAdapter_spec.js +++ b/test/spec/modules/freewheel-sspBidAdapter_spec.js @@ -1,197 +1,197 @@ -import { expect } from 'chai'; -import { spec } from 'modules/freewheel-sspBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; - -const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; - -describe('freewheel-ssp BidAdapter Test', 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': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - '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 false when required params are not passed', function () { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - wrong: 'missing zone id' - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - let bidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'gdprConsent': { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'gdprApplies': true - } - } - ]; - - it('should add parameters to the tag', function () { - const request = spec.buildRequests(bidRequests, bidRequests[0]); - const payload = request.data; - expect(payload.reqType).to.equal('AdsSetup'); - expect(payload.protocolVersion).to.equal('2.0'); - expect(payload.zoneId).to.equal('277225'); - expect(payload.componentId).to.equal('mustang'); - expect(payload.playerSize).to.equal('300x600'); - expect(payload._fw_gdpr).to.equal(true); - expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); - }); - - it('sends bid request to ENDPOINT via GET', function () { - const request = spec.buildRequests(bidRequests, bidRequests[0]); - expect(request.url).to.contain(ENDPOINT); - expect(request.method).to.equal('GET'); - }); - }) - - describe('interpretResponse', function () { - let bidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - let formattedBidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225', - 'format': 'floorad' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[600, 250], [300, 600]], - 'bidId': '30b3other1c1838de1e', - 'bidderRequestId': '22edbae273other3bf6', - 'auctionId': '1d1a03079test0a475', - }, - { - 'bidder': 'stickyadstv', - 'params': { - 'zoneId': '277225', - 'format': 'test' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 600]], - 'bidId': '2', - 'bidderRequestId': '3', - 'auctionId': '4', - } - ]; - - let response = '' + - '' + - ' ' + - ' Adswizz' + - ' ' + - ' ' + - ' ' + - ' 00:00:09' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' 0.2000' + - ' ' + - ' ' + - ' ' + - ''; - - let ad = '
'; - let formattedAd = '
'; - - it('should get correct bid response', function () { - var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - - let expectedResponse = [ - { - requestId: '30b31c1838de1e', - cpm: '0.2000', - width: 300, - height: 600, - creativeId: '28517153', - currency: 'EUR', - netRevenue: true, - ttl: 360, - ad: ad - } - ]; - - let result = spec.interpretResponse(response, request); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - - it('should get correct bid response with formated ad', function () { - var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - - let expectedResponse = [ - { - requestId: '30b31c1838de1e', - cpm: '0.2000', - width: 300, - height: 600, - creativeId: '28517153', - currency: 'EUR', - netRevenue: true, - ttl: 360, - ad: formattedAd - } - ]; - - let result = spec.interpretResponse(response, request); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - - it('handles nobid responses', function () { - var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); - let response = ''; - - let result = spec.interpretResponse(response, reqest); - expect(result.length).to.equal(0); - }); - }); -}); +import { expect } from 'chai'; +import { spec } from 'modules/freewheel-sspBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; + +describe('freewheel-ssp BidAdapter Test', 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': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + wrong: 'missing zone id' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'gdprConsent': { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'gdprApplies': true + } + } + ]; + + it('should add parameters to the tag', function () { + const request = spec.buildRequests(bidRequests, bidRequests[0]); + const payload = request.data; + expect(payload.reqType).to.equal('AdsSetup'); + expect(payload.protocolVersion).to.equal('2.0'); + expect(payload.zoneId).to.equal('277225'); + expect(payload.componentId).to.equal('mustang'); + expect(payload.playerSize).to.equal('300x600'); + expect(payload._fw_gdpr).to.equal(true); + expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + }); + + it('sends bid request to ENDPOINT via GET', function () { + const request = spec.buildRequests(bidRequests, bidRequests[0]); + expect(request.url).to.contain(ENDPOINT); + expect(request.method).to.equal('GET'); + }); + }) + + describe('interpretResponse', function () { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + let formattedBidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225', + 'format': 'floorad' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[600, 250], [300, 600]], + 'bidId': '30b3other1c1838de1e', + 'bidderRequestId': '22edbae273other3bf6', + 'auctionId': '1d1a03079test0a475', + }, + { + 'bidder': 'stickyadstv', + 'params': { + 'zoneId': '277225', + 'format': 'test' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 600]], + 'bidId': '2', + 'bidderRequestId': '3', + 'auctionId': '4', + } + ]; + + let response = '' + + '' + + ' ' + + ' Adswizz' + + ' ' + + ' ' + + ' ' + + ' 00:00:09' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 0.2000' + + ' ' + + ' ' + + ' ' + + ''; + + let ad = '
'; + let formattedAd = '
'; + + it('should get correct bid response', function () { + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: ad + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('should get correct bid response with formated ad', function () { + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: formattedAd + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', function () { + var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + let response = ''; + + let result = spec.interpretResponse(response, reqest); + expect(result.length).to.equal(0); + }); + }); +}); From 4baf2e46f433439dca5c166da891d943bebbec6e Mon Sep 17 00:00:00 2001 From: Valentin Zhukovsky Date: Thu, 20 Sep 2018 22:40:26 +0300 Subject: [PATCH 0705/1594] AOL adapter - switched to native Prebid user syncs support. (#3032) * Switched to native Prebid user syncs support. * Removed bid CPM adjustment warning to prevent using globals. --- modules/aolBidAdapter.js | 107 +++++++----------------- test/spec/modules/aolBidAdapter_spec.js | 72 ++-------------- 2 files changed, 39 insertions(+), 140 deletions(-) diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 3d89007bbc2..b97252bf9b3 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -1,7 +1,5 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; -import { config } from 'src/config'; -import { EVENTS } from 'src/constants.json'; import { BANNER } from 'src/mediaTypes'; const AOL_BIDDERS_CODES = { @@ -43,31 +41,11 @@ const NEXAGE_SERVER = 'hb.nexage.com'; const ONE_DISPLAY_TTL = 60; const ONE_MOBILE_TTL = 3600; -$$PREBID_GLOBAL$$.aolGlobals = { - pixelsDropped: false -}; - const NUMERIC_VALUES = { TRUE: 1, FALSE: 0 }; -let showCpmAdjustmentWarning = (function() { - let showCpmWarning = true; - - return function() { - let bidderSettings = $$PREBID_GLOBAL$$.bidderSettings; - if (showCpmWarning && bidderSettings && bidderSettings.aol && - typeof bidderSettings.aol.bidCpmAdjustment === 'function') { - utils.logWarn( - 'bidCpmAdjustment is active for the AOL adapter. ' + - 'As of Prebid 0.14, AOL can bid in net – please contact your accounts team to enable.' - ); - showCpmWarning = false; // warning is shown at most once - } - }; -})(); - function template(strings, ...keys) { return function(...values) { let dict = values[values.length - 1] || {}; @@ -80,32 +58,6 @@ function template(strings, ...keys) { }; } -function parsePixelItems(pixels) { - let itemsRegExp = /(img|iframe)[\s\S]*?src\s*=\s*("|')(.*?)\2/gi; - let tagNameRegExp = /\w*(?=\s)/; - let srcRegExp = /src=("|')(.*?)\1/; - let pixelsItems = []; - - if (pixels) { - let matchedItems = pixels.match(itemsRegExp); - if (matchedItems) { - matchedItems.forEach(item => { - let tagName = item.match(tagNameRegExp)[0]; - let url = item.match(srcRegExp)[2]; - - if (tagName && tagName) { - pixelsItems.push({ - type: tagName === SYNC_TYPES.IMAGE.TAG ? SYNC_TYPES.IMAGE.TYPE : SYNC_TYPES.IFRAME.TYPE, - url: url - }); - } - }); - } - } - - return pixelsItems; -} - function _isMarketplaceBidder(bidder) { return bidder === AOL_BIDDERS_CODES.AOL || bidder === AOL_BIDDERS_CODES.ONEDISPLAY; } @@ -164,8 +116,6 @@ export const spec = { }); }, interpretResponse({body}, bidRequest) { - showCpmAdjustmentWarning(); - if (!body) { utils.logError('Empty bid response', bidRequest.bidderCode, body); } else { @@ -176,15 +126,11 @@ export const spec = { } } }, - getUserSyncs(options, bidResponses) { - let bidResponse = bidResponses[0]; + getUserSyncs(options, serverResponses) { + const bidResponse = !utils.isEmpty(serverResponses) && serverResponses[0].body; - if (config.getConfig('aol.userSyncOn') === EVENTS.BID_RESPONSE) { - if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse && bidResponse.ext && bidResponse.ext.pixels) { - $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; - - return parsePixelItems(bidResponse.ext.pixels); - } + if (bidResponse && bidResponse.ext && bidResponse.ext.pixels) { + return this.parsePixelItems(bidResponse.ext.pixels); } return []; @@ -357,6 +303,31 @@ export const spec = { return params; }, + parsePixelItems(pixels) { + let itemsRegExp = /(img|iframe)[\s\S]*?src\s*=\s*("|')(.*?)\2/gi; + let tagNameRegExp = /\w*(?=\s)/; + let srcRegExp = /src=("|')(.*?)\1/; + let pixelsItems = []; + + if (pixels) { + let matchedItems = pixels.match(itemsRegExp); + if (matchedItems) { + matchedItems.forEach(item => { + let tagName = item.match(tagNameRegExp)[0]; + let url = item.match(srcRegExp)[2]; + + if (tagName && tagName) { + pixelsItems.push({ + type: tagName === SYNC_TYPES.IMAGE.TAG ? SYNC_TYPES.IMAGE.TYPE : SYNC_TYPES.IFRAME.TYPE, + url: url + }); + } + }); + } + } + + return pixelsItems; + }, _parseBidResponse(response, bidRequest) { let bidData; @@ -380,7 +351,7 @@ export const spec = { } } - let bidResponse = { + return { bidderCode: bidRequest.bidderCode, requestId: bidRequest.bidId, ad: bidData.adm, @@ -394,24 +365,6 @@ export const spec = { netRevenue: true, ttl: bidRequest.ttl }; - - if (response.ext && response.ext.pixels) { - if (config.getConfig('aol.userSyncOn') !== EVENTS.BID_RESPONSE) { - bidResponse.ad += this.formatPixels(response.ext.pixels); - } - } - - return bidResponse; - }, - formatPixels(pixels) { - let formattedPixels = pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, ''); - - return ''; }, isOneMobileBidder: _isOneMobileBidder, isSecureProtocol() { diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index 396ebf36c7d..53113d0a67c 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -97,7 +97,6 @@ describe('AolAdapter', function () { let bidResponse; let bidRequest; let logWarnSpy; - let formatPixelsStub; let isOneMobileBidderStub; beforeEach(function () { @@ -111,14 +110,12 @@ describe('AolAdapter', function () { body: getDefaultBidResponse() }; logWarnSpy = sinon.spy(utils, 'logWarn'); - formatPixelsStub = sinon.stub(spec, 'formatPixels'); isOneMobileBidderStub = sinon.stub(spec, 'isOneMobileBidder'); }); afterEach(function () { $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; logWarnSpy.restore(); - formatPixelsStub.restore(); isOneMobileBidderStub.restore(); }); @@ -139,27 +136,6 @@ describe('AolAdapter', function () { ttl: bidRequest.ttl }); }); - - it('should add pixels to ad content when pixels are present in the response', function () { - bidResponse.body.ext = { - pixels: 'pixels-content' - }; - - formatPixelsStub.returns('pixels-content'); - let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - - expect(formattedBidResponse.ad).to.equal(DEFAULT_AD_CONTENT + 'pixels-content'); - }); - - it('should show warning in the console', function() { - $$PREBID_GLOBAL$$.bidderSettings = { - aol: { - bidCpmAdjustment: function() {} - } - }; - spec.interpretResponse(bidResponse, bidRequest); - expect(utils.logWarn.calledOnce).to.be.true; - }); }); describe('buildRequests()', function () { @@ -492,69 +468,39 @@ describe('AolAdapter', function () { }); describe('getUserSyncs()', function () { + let serverResponses; let bidResponse; - let bidRequest; beforeEach(function () { - $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = false; - config.setConfig({ - aol: { - userSyncOn: 'bidResponse' - }, - }); bidResponse = getDefaultBidResponse(); bidResponse.ext = { pixels: getPixels() }; + + serverResponses = [ + {body: bidResponse} + ]; }); - it('should return user syncs only if userSyncOn equals to "bidResponse"', function () { - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + it('should return user syncs if pixels are present in the response', function () { + let userSyncs = spec.getUserSyncs({}, serverResponses); - expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.true; expect(userSyncs).to.deep.equal([ {type: 'image', url: 'img.org'}, {type: 'iframe', url: 'pixels1.org'} ]); }); - it('should not return user syncs if it has already been returned', function () { - $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; - - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - - expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.true; - expect(userSyncs).to.deep.equal([]); - }); - it('should not return user syncs if pixels are not present', function () { bidResponse.ext.pixels = null; + let userSyncs = spec.getUserSyncs({}, serverResponses); - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - - expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.false; expect(userSyncs).to.deep.equal([]); }); }); - describe('formatPixels()', function () { - it('should return pixels wrapped for dropping them once and within nested frames ', function () { - let pixels = ''; - let formattedPixels = spec.formatPixels(pixels); - - expect(formattedPixels).to.equal( - ''); - }); - }); - describe('isOneMobileBidder()', function () { - it('should return false when when bidderCode is not present', function () { + it('should return false when when bidderCode is not present', () => { expect(spec.isOneMobileBidder(null)).to.be.false; }); From 80b5c3a47baa4acbf482266dbd5eac86ddce566d Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Fri, 21 Sep 2018 12:56:48 -0400 Subject: [PATCH 0706/1594] send url as it is (#3116) --- modules/appnexusBidAdapter.js | 4 ++-- src/refererDetection.js | 16 ++++++---------- test/spec/modules/appnexusBidAdapter_spec.js | 10 +++++----- test/spec/refererDetection_spec.js | 14 +++++++------- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 1bffb80975f..aaec207dc1e 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -109,10 +109,10 @@ export const spec = { if (bidderRequest && bidderRequest.refererInfo) { let refererinfo = { - rd_ref: bidderRequest.refererInfo.referer, + rd_ref: encodeURIComponent(bidderRequest.refererInfo.referer), rd_top: bidderRequest.refererInfo.reachedTop, rd_ifs: bidderRequest.refererInfo.numIframes, - rd_stk: bidderRequest.refererInfo.stack.join(',') + rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') } payload.referrer_detection = refererinfo; } diff --git a/src/refererDetection.js b/src/refererDetection.js index 6292b65f92a..bf2ef5209f6 100644 --- a/src/refererDetection.js +++ b/src/refererDetection.js @@ -27,7 +27,6 @@ export function detectReferer(win) { function getPubUrlStack(levels) { let stack = []; let defUrl = null; - let encodedUrl = null; let frameLocation = null; let prevFrame = null; let prevRef = null; @@ -43,10 +42,9 @@ export function detectReferer(win) { } if (frameLocation) { - encodedUrl = encodeURIComponent(frameLocation); - stack.push(encodedUrl); + stack.push(frameLocation); if (!detectedRefererUrl) { - detectedRefererUrl = encodedUrl; + detectedRefererUrl = frameLocation; } } else if (i !== 0) { prevFrame = levels[i - 1]; @@ -58,16 +56,14 @@ export function detectReferer(win) { } if (prevRef) { - encodedUrl = encodeURIComponent(prevRef); - stack.push(encodedUrl); + stack.push(prevRef); if (!detectedRefererUrl) { - detectedRefererUrl = encodedUrl; + detectedRefererUrl = prevRef; } } else if (ancestor) { - encodedUrl = encodeURIComponent(ancestor); - stack.push(encodedUrl); + stack.push(ancestor); if (!detectedRefererUrl) { - detectedRefererUrl = encodedUrl; + detectedRefererUrl = ancestor; } } else { stack.push(defUrl); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 66568781a84..9be87ac8628 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -375,13 +375,13 @@ describe('AppNexusAdapter', function () { const bidRequest = Object.assign({}, bidRequests[0]) const bidderRequest = { refererInfo: { - referer: 'http%3A%2F%2Fexample.com%2Fpage.html', + referer: 'http://example.com/page.html', reachedTop: true, numIframes: 2, stack: [ - 'http%3A%2F%2Fexample.com%2Fpage.html', - 'http%3A%2F%2Fexample.com%2Fiframe1.html', - 'http%3A%2F%2Fexample.com%2Fiframe2.html' + 'http://example.com/page.html', + 'http://example.com/iframe1.html', + 'http://example.com/iframe2.html' ] } } @@ -393,7 +393,7 @@ describe('AppNexusAdapter', function () { rd_ref: 'http%3A%2F%2Fexample.com%2Fpage.html', rd_top: true, rd_ifs: 2, - rd_stk: bidderRequest.refererInfo.stack.join(',') + rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') }); }); }) diff --git a/test/spec/refererDetection_spec.js b/test/spec/refererDetection_spec.js index 95a2d096389..956ba794546 100644 --- a/test/spec/refererDetection_spec.js +++ b/test/spec/refererDetection_spec.js @@ -35,13 +35,13 @@ describe('referer detection', () => { const getRefererInfo = detectReferer(mockIframe2WinObject); let result = getRefererInfo(); let expectedResult = { - referer: 'http%3A%2F%2Fexample.com%2Fpage.html', + referer: 'http://example.com/page.html', reachedTop: true, numIframes: 2, stack: [ - 'http%3A%2F%2Fexample.com%2Fpage.html', - 'http%3A%2F%2Fexample.com%2Fiframe1.html', - 'http%3A%2F%2Fexample.com%2Fiframe2.html' + 'http://example.com/page.html', + 'http://example.com/iframe1.html', + 'http://example.com/iframe2.html' ] }; expect(result).to.deep.equal(expectedResult); @@ -66,13 +66,13 @@ describe('referer detection', () => { const getRefererInfo = detectReferer(mockIframe2WinObject); let result = getRefererInfo(); let expectedResult = { - referer: 'http%3A%2F%2Faaa.com%2Fiframe1.html', + referer: 'http://aaa.com/iframe1.html', reachedTop: false, numIframes: 2, stack: [ null, - 'http%3A%2F%2Faaa.com%2Fiframe1.html', - 'http%3A%2F%2Fbbb.com%2Fiframe2.html' + 'http://aaa.com/iframe1.html', + 'http://bbb.com/iframe2.html' ] }; expect(result).to.deep.equal(expectedResult); From e97c5f0f01c3a892efd2b57dbcf43708690e003e Mon Sep 17 00:00:00 2001 From: Pascal S Date: Mon, 24 Sep 2018 16:07:56 +0200 Subject: [PATCH 0707/1594] Update package.json - make `npm run test` work (#3114) (#3117) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4c7756b7d2..a45283e1d24 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { - "test": "gulp run-tests", + "test": "gulp test", "lint": "gulp lint" }, "repository": { From 0e180e3e59645e95c679988fa55a5d571331b596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Buzun?= <38724309+michalbuzun@users.noreply.github.com> Date: Mon, 24 Sep 2018 18:57:45 +0200 Subject: [PATCH 0708/1594] added sizes for rubicon (#3094) --- modules/rubiconBidAdapter.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 2f4f3e01ce4..4e5ef22c2ce 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -34,6 +34,9 @@ var sizeMap = { 35: '980x150', 37: '468x400', 38: '930x180', + 39: '750x100', + 40: '750x200', + 41: '750x300', 43: '320x50', 44: '300x50', 48: '300x300', From 146d33bd9eec28e0ef7b56076bace926ad9fe432 Mon Sep 17 00:00:00 2001 From: susyt Date: Mon, 24 Sep 2018 10:09:53 -0700 Subject: [PATCH 0709/1594] Adds an id parameter (#3107) * adds jcsi param * adds try catch --- modules/gumgumBidAdapter.js | 73 ++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index d8881f56f0d..55a22c23ef8 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -13,6 +13,76 @@ const TIME_TO_LIVE = 60 let browserParams = {}; let pageViewId = null +function hasTopAccess () { + var hasTopAccess = false + try { hasTopAccess = !!top.document } catch (e) {} + return hasTopAccess +} + +function isInSafeFrame (windowRef) { + const w = windowRef || window + if (w.$sf) return w.$sf + else if (hasTopAccess() && w !== top) return isInSafeFrame(w.parent) + return null +} + +function getGoogleTag (windowRef) { + try { + const w = windowRef || window + var GOOGLETAG = null + if ('googletag' in w) { + GOOGLETAG = w.googletag + } else if (w !== top) { + GOOGLETAG = getGoogleTag(w.parent) + } + return GOOGLETAG + } catch (error) { + utils.logError('Error getting googletag ', error) + return null + } +} + +function getAMPContext (windowRef) { + const w = windowRef || window + var context = null + var nameJSON = null + if (utils.isPlainObject(w.context)) { + context = w.context + } else { + try { + nameJSON = JSON.parse(w.name || null) + } catch (error) { + utils.logError('Error getting w.name', error) + } + if (utils.isPlainObject(nameJSON)) { + context = nameJSON._context || (nameJSON.attributes ? nameJSON.attributes._context : null) + } + if (utils.isPlainObject(w.AMP_CONTEXT_DATA)) { + context = w.AMP_CONTEXT_DATA + } + } + return context +} + +function getJCSI () { + const entrypointOffset = 7 + const inFrame = (window.top && window.top !== window) + const frameType = (!inFrame ? 1 : (isInSafeFrame() ? 2 : (hasTopAccess() ? 3 : 4))) + const context = [] + if (getAMPContext()) { + context.push(1) + } + if (getGoogleTag()) { + context.push(2) + } + const jcsi = { + ep: entrypointOffset, + fc: frameType, + ctx: context + } + return JSON.stringify(jcsi) +} + // TODO: potential 0 values for browserParams sent to ad server function _getBrowserParams() { let topWindow @@ -40,7 +110,8 @@ function _getBrowserParams() { sh: topScreen.height, pu: topUrl, ce: utils.cookiesAreEnabled(), - dpr: topWindow.devicePixelRatio || 1 + dpr: topWindow.devicePixelRatio || 1, + jcsi: getJCSI() } ggad = (topUrl.match(/#ggad=(\w+)$/) || [0, 0])[1] if (ggad) { From 398eb7b3688fbe1f264464d72c11ba24585f229a Mon Sep 17 00:00:00 2001 From: Justin Grimes Date: Mon, 24 Sep 2018 10:11:06 -0700 Subject: [PATCH 0710/1594] Serverbid Bid Adapter: Add pubnx alias (#3064) --- modules/serverbidBidAdapter.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index 50afa4bc469..44bbb406585 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -30,6 +30,9 @@ const CONFIG = { }, 'answermedia': { 'BASE_URI': 'https://e.serverbid.com/api/v2' + }, + 'pubnx': { + 'BASE_URI': 'https://e.serverbid.com/api/v2' } }; @@ -38,7 +41,7 @@ let bidder = 'serverbid'; export const spec = { code: BIDDER_CODE, - aliases: ['connectad', 'onefiftytwo', 'insticator', 'adsparc', 'automatad', 'archon', 'buysellads', 'answermedia'], + aliases: ['connectad', 'onefiftytwo', 'insticator', 'adsparc', 'automatad', 'archon', 'buysellads', 'answermedia', 'pubnx'], /** * Determines whether or not the given bid request is valid. From 2f9c5cf51261647e84fde5a963e6e415aa9cf5d8 Mon Sep 17 00:00:00 2001 From: Jacek Drobiecki Date: Mon, 24 Sep 2018 19:28:38 +0200 Subject: [PATCH 0711/1594] AdOcean adapter improvment (#3011) * Initial revision of adocean bid adapter (ADOCEAN-13634, ADOCEAN-13635) * Minor fixes * new demo placement * formating after lint * move request parameters to params * adocean adpater tests * minor fixes * added ttl, netRevenue nad creativeId. merged with upstream * GDPR support * do not send empty gdpr_consent * GDPR support * do not send empty gdpr_consent * AdOcean adapter: tests for gdpr_support * remove old comment * Added possibility to use multiple times same ad placement * Tests for placement duplication and gdpr support. * formating --- modules/adoceanBidAdapter.js | 30 ++++++++++++++------ test/spec/modules/adoceanBidAdapter_spec.js | 31 +++++++++++++++++---- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index 21e13e77a0a..e84fd04a35e 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -16,7 +16,7 @@ function buildEndpointUrl(emiter, payload) { } function buildRequest(masterBidRequests, masterId, gdprConsent) { - const firstBid = masterBidRequests[0]; + let emiter; const payload = { id: masterId, }; @@ -27,13 +27,16 @@ function buildRequest(masterBidRequests, masterId, gdprConsent) { const bidIdMap = {}; - utils._each(masterBidRequests, function(v) { - bidIdMap[v.params.slaveId] = v.bidId; + utils._each(masterBidRequests, function(bid, slaveId) { + if (!emiter) { + emiter = bid.params.emiter; + } + bidIdMap[slaveId] = bid.bidId; }); return { method: 'GET', - url: buildEndpointUrl(firstBid.params.emiter, payload), + url: buildEndpointUrl(emiter, payload), data: {}, bidIdMap: bidIdMap }; @@ -41,8 +44,16 @@ function buildRequest(masterBidRequests, masterId, gdprConsent) { function assignToMaster(bidRequest, bidRequestsByMaster) { const masterId = bidRequest.params.masterId; - bidRequestsByMaster[masterId] = bidRequestsByMaster[masterId] || []; - bidRequestsByMaster[masterId].push(bidRequest); + const slaveId = bidRequest.params.slaveId; + const masterBidRequests = bidRequestsByMaster[masterId] = bidRequestsByMaster[masterId] || [{}]; + let i = 0; + while (masterBidRequests[i] && masterBidRequests[i][slaveId]) { + i++; + } + if (!masterBidRequests[i]) { + masterBidRequests[i] = {}; + } + masterBidRequests[i][slaveId] = bidRequest; } function interpretResponse(placementResponse, bidRequest, bids) { @@ -83,8 +94,11 @@ export const spec = { utils._each(validBidRequests, function(bidRequest) { assignToMaster(bidRequest, bidRequestsByMaster); }); - requests = utils._map(bidRequestsByMaster, function(requests, masterId) { - return buildRequest(requests, masterId, bidderRequest.gdprConsent); + + utils._each(bidRequestsByMaster, function(masterRequests, masterId) { + utils._each(masterRequests, function(instanceRequests) { + requests.push(buildRequest(instanceRequests, masterId, bidderRequest.gdprConsent)); + }); }); return requests; diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index c9f33b940b5..3e6d321e4f9 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -36,6 +36,7 @@ describe('AdoceanAdapter', function () { bid.params = { 'masterId': 0 }; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); @@ -54,6 +55,19 @@ describe('AdoceanAdapter', function () { 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'adocean', + 'params': { + 'masterId': 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', + 'slaveId': 'adoceanmyaozpniqismex', + 'emiter': 'myao.adocean.pl' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '30b31c1838de1f', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', } ]; @@ -64,11 +78,18 @@ describe('AdoceanAdapter', function () { } }; - it('should add bidIdMap with slaveId => bidId mapping', function () { - const request = spec.buildRequests(bidRequests, bidderRequest)[0]; - expect(request.bidIdMap).to.exists; - const bidIdMap = request.bidIdMap; - expect(bidIdMap[bidRequests[0].params.slaveId]).to.equal(bidRequests[0].bidId); + it('should send two requests if slave is duplicated', () => { + const nrOfRequests = spec.buildRequests(bidRequests, bidderRequest).length; + expect(nrOfRequests).to.equal(2); + }); + + it('should add bidIdMap with correct slaveId => bidId mapping', () => { + const requests = spec.buildRequests(bidRequests, bidderRequest); + for (let i = 0; i < bidRequests.length; i++) { + expect(requests[i]).to.exists; + expect(requests[i].bidIdMap).to.exists; + expect(requests[i].bidIdMap[bidRequests[i].params.slaveId]).to.equal(bidRequests[i].bidId); + } }); it('sends bid request to url via GET', function () { From d7f7ab6719bc3effbfe4ddf58148bbbb4c2ac58d Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Mon, 24 Sep 2018 13:57:40 -0400 Subject: [PATCH 0712/1594] improving kargo unit tests for currency handling (#3106) --- test/spec/modules/kargoBidAdapter_spec.js | 40 +++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index c60d74e040a..680b402392a 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -35,12 +35,20 @@ describe('kargo adapter tests', function () { }); describe('build request', function() { - var bids, cookies = [], localStorageItems = []; + var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = []; beforeEach(function () { + undefinedCurrency = false; + noAdServerCurrency = false; sandbox.stub(config, 'getConfig').callsFake(function(key) { if (key === 'currency') { - return 'USD'; + if (undefinedCurrency) { + return undefined; + } + if (noAdServerCurrency) { + return {}; + } + return {adServerCurrency: 'USD'}; } throw new Error(`Config stub incomplete! Missing key "${key}"`) }); @@ -109,6 +117,16 @@ describe('kargo adapter tests', function () { return sandbox.stub(localStorage, 'getItem').throws(); } + function simulateNoCurrencyObject() { + undefinedCurrency = true; + noAdServerCurrency = false; + } + + function simulateNoAdServerCurrency() { + undefinedCurrency = false; + noAdServerCurrency = true; + } + function initializeKruxUser() { setLocalStorageItem('kxkar_user', 'rsgr9pnij'); } @@ -308,6 +326,24 @@ describe('kargo adapter tests', function () { initializeInvalidKrgCrbType3(); testBuildRequests(getExpectedKrakenParams({crb: true}, undefined, getInvalidKrgCrbType3())); }); + + it('handles a non-existant currency object on the config', function() { + simulateNoCurrencyObject(); + initializeKruxUser(); + initializeKruxSegments(); + initializeKrgUid(); + initializeKrgCrb(); + testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb())); + }); + + it('handles no ad server currency being set on the currency object in the config', function() { + simulateNoAdServerCurrency(); + initializeKruxUser(); + initializeKruxSegments(); + initializeKrgUid(); + initializeKrgCrb(); + testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb())); + }); }); describe('response handler', function() { From 005df8b4915c61df954ad535958c44479e93a295 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Mon, 24 Sep 2018 15:28:04 -0400 Subject: [PATCH 0713/1594] add versioning and deprecation policy doc (#3103) --- PREBID_VERSIONING_DEPRECATION.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 PREBID_VERSIONING_DEPRECATION.md diff --git a/PREBID_VERSIONING_DEPRECATION.md b/PREBID_VERSIONING_DEPRECATION.md new file mode 100644 index 00000000000..f006922259b --- /dev/null +++ b/PREBID_VERSIONING_DEPRECATION.md @@ -0,0 +1,25 @@ +# Prebid versioning and deprecation policy + +## Goals +Provide clear definitions and policy around versioning and breaking changes to APIs that are both publisher and demand partner facing. + + - Limit the number of breaking changes. + - Ensure significant time for updates for breaking changes so that publisher or demand partners do not break. + - Provide a path to deprecation and reduce technical debt and increase security. + - Major versions should not be changed more than once per 30 days. + +## Versioning + +Follow semantic versioning so that all breaking changes occur within a major release. A breaking change includes both demand partner internal APIs* and publisher facing APIs (global APIs). + +*Demand partner APIs may be excluded from breaking change policy at the core teams discretion if the changes are made so to be transparent to the bidders (such as internal refactoring). + +## Deprecation process + + - Open an issue with an "intent to implement" and "API impact" labels. + - Allow 2 weeks for discussion. + - Announce breaking change to the mailing list (TBD needs to be created). + - At least 2 core members needs to provide explicit approval for the deprecation. + - Open a PR against current master for console warning for possible breakage. + - Support the previous major version for a minimum of 30 days. + - Coordinate with the core team to ensure clean merging into feature branch if applicable (future major version branch). From 726d0a46be2c3671c0b6cf0c0474da61b5c798a4 Mon Sep 17 00:00:00 2001 From: Cary White Date: Tue, 25 Sep 2018 10:47:43 -0700 Subject: [PATCH 0714/1594] Trafficroots Bid Adapter Submission (#2993) * Trafficroots bid adapter submission. Thank you! * unit test * typo fix --- modules/trafficrootsBidAdapter.js | 129 +++++++++++++++ modules/trafficrootsBidAdapter.md | 37 +++++ .../modules/trafficrootsBidAdapter_spec.js | 149 ++++++++++++++++++ 3 files changed, 315 insertions(+) create mode 100644 modules/trafficrootsBidAdapter.js create mode 100644 modules/trafficrootsBidAdapter.md create mode 100644 test/spec/modules/trafficrootsBidAdapter_spec.js diff --git a/modules/trafficrootsBidAdapter.js b/modules/trafficrootsBidAdapter.js new file mode 100644 index 00000000000..4e1c0390d65 --- /dev/null +++ b/modules/trafficrootsBidAdapter.js @@ -0,0 +1,129 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +const TR_BIDDER_CODE = 'trafficroots'; +const TR_CURRENCY = 'USD'; +const TR_DEFAULT_BID_URL = '//service.trafficroots.com/prebid'; +const TR_TTL = 60; + +const LOCATION_PARAM_NAME = 'siteurl'; +const ID_PARAM_NAME = 'id'; +const IFRAME_PARAM_NAME = 'if'; +const ZONE_ID_PARAM_NAME = 'zoneId'; +const SIZE_PARAM_NAME = 'size'; +const KEYWORDS_PARAM_NAME = 'keywords'; +const MOBILE_PARAM_NAME = 'mobile'; +const TRID_PARAM_NAME = 'trid'; + +const ARRAY_PARAM_SEPARATOR = ';'; +const ARRAY_SIZE_SEPARATOR = ','; +const SIZE_SEPARATOR = 'x'; +const IS_MOBILE = window.navigator.userAgent.toLowerCase().includes('mobi'); + +let keywords = () => { + let clean = input => { + return input.replace(/\W/g, ' ').replace(/[ ]{2,}/g, ' ').trim(); + }; + let meta = name => { + let tag = document.querySelector("meta[name='" + name + "']"); + return (tag !== null) ? tag.getAttribute('content') : ''; + }; + return encodeURIComponent( + clean( + meta('keywords') + ' ' + meta('description') + ' ' + document.title + ) + ).substring(0, 400); +}; + +export const spec = { + code: TR_BIDDER_CODE, + isBidRequestValid: function(bid) { + return bid.params && !!bid.params.zoneId; + }, + + buildRequests: function(validBidRequests, bidderRequest) { + let deliveryUrl = ''; + const idParams = []; + const sizeParams = []; + const zoneIds = []; + let trid = ''; + if (window.localStorage) { + try { + var myid = window.localStorage.getItem('trafficroots:trid'); + if (myid) { + trid = myid; + } + } catch (ex) { + } + } + utils._each(validBidRequests, function(bid) { + if (!deliveryUrl && typeof bid.params.deliveryUrl === 'string') { + deliveryUrl = bid.params.deliveryUrl; + } + idParams.push(bid.bidId); + sizeParams.push(bid.sizes.map(size => size.join(SIZE_SEPARATOR)).join(ARRAY_SIZE_SEPARATOR)); + zoneIds.push(bid.params.zoneId); + }); + + if (!deliveryUrl) { + deliveryUrl = TR_DEFAULT_BID_URL; + } + + let data = { + [IFRAME_PARAM_NAME]: 0, + [LOCATION_PARAM_NAME]: utils.getTopWindowUrl(), + [SIZE_PARAM_NAME]: sizeParams.join(ARRAY_PARAM_SEPARATOR), + [ID_PARAM_NAME]: idParams.join(ARRAY_PARAM_SEPARATOR), + [ZONE_ID_PARAM_NAME]: zoneIds.join(ARRAY_PARAM_SEPARATOR), + [MOBILE_PARAM_NAME]: IS_MOBILE, + [KEYWORDS_PARAM_NAME]: decodeURIComponent(keywords()), + [TRID_PARAM_NAME]: trid + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + data.gdpr = { + applies: bidderRequest.gdprConsent.gdprApplies, + consent: bidderRequest.gdprConsent.consentString + }; + } + + return { + method: 'GET', + url: deliveryUrl, + data: data + }; + }, + + interpretResponse: function(serverResponses, request) { + const bidResponses = []; + var tridSet = false; + utils._each(serverResponses.body, function(response) { + if (!tridSet) { + try { + if (window.localStorage) { + window.localStorage.setItem('trafficroots:trid', response.trid); + tridSet = true; + } + } catch (ex) {} + } + if (response.cpm > 0) { + const bidResponse = { + requestId: response.id, + creativeId: response.id, + adId: response.id, + cpm: response.cpm, + width: response.width, + height: response.height, + currency: TR_CURRENCY, + netRevenue: true, + ttl: TR_TTL, + ad: response.ad + }; + bidResponses.push(bidResponse); + } + }); + return bidResponses; + } +}; + +registerBidder(spec); diff --git a/modules/trafficrootsBidAdapter.md b/modules/trafficrootsBidAdapter.md new file mode 100644 index 00000000000..2aceb0c866b --- /dev/null +++ b/modules/trafficrootsBidAdapter.md @@ -0,0 +1,37 @@ +# Overview + +Module Name: Trafficroots Bid Adapter + +Module Type: Bidder Adapter + +Maintainer: cary@trafficroots.com + +# Description + +Module that connects to Trafficroots demand sources + +# Test Parameters +```javascript + + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250],[300,600]], // a display size + bids: [ + { + bidder: 'trafficroots', + params: { + zoneId: 'aa0444af31', + deliveryUrl: location.protocol + '//service.trafficroots.com/prebid' + } + },{ + bidder: 'trafficroots', + params: { + zoneId: '8f527a4835', + deliveryUrl: location.protocol + '//service.trafficroots.com/prebid' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/trafficrootsBidAdapter_spec.js b/test/spec/modules/trafficrootsBidAdapter_spec.js new file mode 100644 index 00000000000..40d549e4a5a --- /dev/null +++ b/test/spec/modules/trafficrootsBidAdapter_spec.js @@ -0,0 +1,149 @@ +import { expect } from 'chai'; +import { spec } from 'modules/trafficrootsBidAdapter'; + +describe('trafficrootsAdapterTests', () => { + describe('bidRequestValidity', () => { + it('bidRequest with zoneId and deliveryUrl params', () => { + expect(spec.isBidRequestValid({ + bidder: 'trafficroots', + params: { + zoneId: 'aa0444af31', + deliveryUrl: 'https://service.trafficroosts.com/prebid' + } + })).to.equal(true); + }); + + it('bidRequest with only zoneId', () => { + expect(spec.isBidRequestValid({ + bidder: 'trafficroots', + params: { + zoneId: '8f527a4835' + } + })).to.equal(true); + }); + + it('bidRequest with only deliveryUrl', () => { + expect(spec.isBidRequestValid({ + bidder: 'trafficroots', + params: { + deliveryUrl: 'https://service.trafficroosts.com/prebid' + } + })).to.equal(false); + }); + }); + + describe('bidRequest', () => { + const bidRequests = [{ + 'bidder': 'trafficroots', + 'bidId': '29fa5c08928bde', + 'params': { + 'zoneId': 'aa0444af31', + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [[300, 250], [300, 600]], + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }, { + 'bidder': 'trafficroots', + 'bidId': '29fa5c08928bde', + 'params': { + 'zoneId': '8f527a4835', + 'deliveryUrl': 'https://service.trafficroosts.com/prebid' + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [[300, 250], [300, 600]], + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }]; + + it('bidRequest method', () => { + const request = spec.buildRequests(bidRequests); + expect(request.method).to.equal('GET'); + }); + + it('bidRequest url', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.match(new RegExp(`${bidRequests[1].params.deliveryUrl}`)); + }); + + it('bidRequest data', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data).to.exists; + }); + + it('bidRequest zoneIds', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data.zoneId).to.equal('aa0444af31;8f527a4835'); + }); + + it('bidRequest gdpr consent', () => { + const consentString = 'consentString'; + const bidderRequest = { + bidderCode: 'trafficroots', + auctionId: '18fd8b8b0bd757', + bidderRequestId: '418b37f85e772c', + timeout: 3000, + gdprConsent: { + consentString: consentString, + gdprApplies: true + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.gdpr).to.exist; + expect(request.data.gdpr.applies).to.exist.and.to.be.true; + expect(request.data.gdpr.consent).to.exist.and.to.equal(consentString); + }); + }); + + describe('interpretResponse', () => { + const bidRequest = [{ + 'bidder': 'trafficroots', + 'bidId': '29fa5c08928bde', + 'params': { + 'zoneId': 'aa0444af31', + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [[300, 250], [300, 600]], + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }]; + + const bidResponse = { + body: [{ + 'id': 'div-gpt-ad-1460505748561-0', + 'ad': 'test ad', + 'width': 320, + 'height': 250, + 'cpm': 5.2 + }], + headers: {} + }; + + it('required keys', () => { + const result = spec.interpretResponse(bidResponse, bidRequest); + + let requiredKeys = [ + 'requestId', + 'creativeId', + 'adId', + 'cpm', + 'width', + 'height', + 'currency', + 'netRevenue', + 'ttl', + 'ad' + ]; + + let resultKeys = Object.keys(result[0]); + resultKeys.forEach(function(key) { + expect(requiredKeys.indexOf(key) !== -1).to.equal(true); + }); + }) + }); +}); From 57e1b5e018ca0cb96972366587915583481c410c Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 25 Sep 2018 11:15:24 -0700 Subject: [PATCH 0715/1594] Revert "Trafficroots Bid Adapter Submission (#2993)" (#3124) This reverts commit 726d0a46be2c3671c0b6cf0c0474da61b5c798a4. --- modules/trafficrootsBidAdapter.js | 129 --------------- modules/trafficrootsBidAdapter.md | 37 ----- .../modules/trafficrootsBidAdapter_spec.js | 149 ------------------ 3 files changed, 315 deletions(-) delete mode 100644 modules/trafficrootsBidAdapter.js delete mode 100644 modules/trafficrootsBidAdapter.md delete mode 100644 test/spec/modules/trafficrootsBidAdapter_spec.js diff --git a/modules/trafficrootsBidAdapter.js b/modules/trafficrootsBidAdapter.js deleted file mode 100644 index 4e1c0390d65..00000000000 --- a/modules/trafficrootsBidAdapter.js +++ /dev/null @@ -1,129 +0,0 @@ -import {registerBidder} from 'src/adapters/bidderFactory'; -import * as utils from 'src/utils'; - -const TR_BIDDER_CODE = 'trafficroots'; -const TR_CURRENCY = 'USD'; -const TR_DEFAULT_BID_URL = '//service.trafficroots.com/prebid'; -const TR_TTL = 60; - -const LOCATION_PARAM_NAME = 'siteurl'; -const ID_PARAM_NAME = 'id'; -const IFRAME_PARAM_NAME = 'if'; -const ZONE_ID_PARAM_NAME = 'zoneId'; -const SIZE_PARAM_NAME = 'size'; -const KEYWORDS_PARAM_NAME = 'keywords'; -const MOBILE_PARAM_NAME = 'mobile'; -const TRID_PARAM_NAME = 'trid'; - -const ARRAY_PARAM_SEPARATOR = ';'; -const ARRAY_SIZE_SEPARATOR = ','; -const SIZE_SEPARATOR = 'x'; -const IS_MOBILE = window.navigator.userAgent.toLowerCase().includes('mobi'); - -let keywords = () => { - let clean = input => { - return input.replace(/\W/g, ' ').replace(/[ ]{2,}/g, ' ').trim(); - }; - let meta = name => { - let tag = document.querySelector("meta[name='" + name + "']"); - return (tag !== null) ? tag.getAttribute('content') : ''; - }; - return encodeURIComponent( - clean( - meta('keywords') + ' ' + meta('description') + ' ' + document.title - ) - ).substring(0, 400); -}; - -export const spec = { - code: TR_BIDDER_CODE, - isBidRequestValid: function(bid) { - return bid.params && !!bid.params.zoneId; - }, - - buildRequests: function(validBidRequests, bidderRequest) { - let deliveryUrl = ''; - const idParams = []; - const sizeParams = []; - const zoneIds = []; - let trid = ''; - if (window.localStorage) { - try { - var myid = window.localStorage.getItem('trafficroots:trid'); - if (myid) { - trid = myid; - } - } catch (ex) { - } - } - utils._each(validBidRequests, function(bid) { - if (!deliveryUrl && typeof bid.params.deliveryUrl === 'string') { - deliveryUrl = bid.params.deliveryUrl; - } - idParams.push(bid.bidId); - sizeParams.push(bid.sizes.map(size => size.join(SIZE_SEPARATOR)).join(ARRAY_SIZE_SEPARATOR)); - zoneIds.push(bid.params.zoneId); - }); - - if (!deliveryUrl) { - deliveryUrl = TR_DEFAULT_BID_URL; - } - - let data = { - [IFRAME_PARAM_NAME]: 0, - [LOCATION_PARAM_NAME]: utils.getTopWindowUrl(), - [SIZE_PARAM_NAME]: sizeParams.join(ARRAY_PARAM_SEPARATOR), - [ID_PARAM_NAME]: idParams.join(ARRAY_PARAM_SEPARATOR), - [ZONE_ID_PARAM_NAME]: zoneIds.join(ARRAY_PARAM_SEPARATOR), - [MOBILE_PARAM_NAME]: IS_MOBILE, - [KEYWORDS_PARAM_NAME]: decodeURIComponent(keywords()), - [TRID_PARAM_NAME]: trid - }; - - if (bidderRequest && bidderRequest.gdprConsent) { - data.gdpr = { - applies: bidderRequest.gdprConsent.gdprApplies, - consent: bidderRequest.gdprConsent.consentString - }; - } - - return { - method: 'GET', - url: deliveryUrl, - data: data - }; - }, - - interpretResponse: function(serverResponses, request) { - const bidResponses = []; - var tridSet = false; - utils._each(serverResponses.body, function(response) { - if (!tridSet) { - try { - if (window.localStorage) { - window.localStorage.setItem('trafficroots:trid', response.trid); - tridSet = true; - } - } catch (ex) {} - } - if (response.cpm > 0) { - const bidResponse = { - requestId: response.id, - creativeId: response.id, - adId: response.id, - cpm: response.cpm, - width: response.width, - height: response.height, - currency: TR_CURRENCY, - netRevenue: true, - ttl: TR_TTL, - ad: response.ad - }; - bidResponses.push(bidResponse); - } - }); - return bidResponses; - } -}; - -registerBidder(spec); diff --git a/modules/trafficrootsBidAdapter.md b/modules/trafficrootsBidAdapter.md deleted file mode 100644 index 2aceb0c866b..00000000000 --- a/modules/trafficrootsBidAdapter.md +++ /dev/null @@ -1,37 +0,0 @@ -# Overview - -Module Name: Trafficroots Bid Adapter - -Module Type: Bidder Adapter - -Maintainer: cary@trafficroots.com - -# Description - -Module that connects to Trafficroots demand sources - -# Test Parameters -```javascript - - var adUnits = [ - { - code: 'test-div', - sizes: [[300, 250],[300,600]], // a display size - bids: [ - { - bidder: 'trafficroots', - params: { - zoneId: 'aa0444af31', - deliveryUrl: location.protocol + '//service.trafficroots.com/prebid' - } - },{ - bidder: 'trafficroots', - params: { - zoneId: '8f527a4835', - deliveryUrl: location.protocol + '//service.trafficroots.com/prebid' - } - } - ] - } - ]; -``` diff --git a/test/spec/modules/trafficrootsBidAdapter_spec.js b/test/spec/modules/trafficrootsBidAdapter_spec.js deleted file mode 100644 index 40d549e4a5a..00000000000 --- a/test/spec/modules/trafficrootsBidAdapter_spec.js +++ /dev/null @@ -1,149 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/trafficrootsBidAdapter'; - -describe('trafficrootsAdapterTests', () => { - describe('bidRequestValidity', () => { - it('bidRequest with zoneId and deliveryUrl params', () => { - expect(spec.isBidRequestValid({ - bidder: 'trafficroots', - params: { - zoneId: 'aa0444af31', - deliveryUrl: 'https://service.trafficroosts.com/prebid' - } - })).to.equal(true); - }); - - it('bidRequest with only zoneId', () => { - expect(spec.isBidRequestValid({ - bidder: 'trafficroots', - params: { - zoneId: '8f527a4835' - } - })).to.equal(true); - }); - - it('bidRequest with only deliveryUrl', () => { - expect(spec.isBidRequestValid({ - bidder: 'trafficroots', - params: { - deliveryUrl: 'https://service.trafficroosts.com/prebid' - } - })).to.equal(false); - }); - }); - - describe('bidRequest', () => { - const bidRequests = [{ - 'bidder': 'trafficroots', - 'bidId': '29fa5c08928bde', - 'params': { - 'zoneId': 'aa0444af31', - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - 'sizes': [[300, 250], [300, 600]], - 'bidderRequestId': '418b37f85e772c', - 'auctionId': '18fd8b8b0bd757' - }, { - 'bidder': 'trafficroots', - 'bidId': '29fa5c08928bde', - 'params': { - 'zoneId': '8f527a4835', - 'deliveryUrl': 'https://service.trafficroosts.com/prebid' - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - 'sizes': [[300, 250], [300, 600]], - 'bidderRequestId': '418b37f85e772c', - 'auctionId': '18fd8b8b0bd757' - }]; - - it('bidRequest method', () => { - const request = spec.buildRequests(bidRequests); - expect(request.method).to.equal('GET'); - }); - - it('bidRequest url', () => { - const request = spec.buildRequests(bidRequests); - expect(request.url).to.match(new RegExp(`${bidRequests[1].params.deliveryUrl}`)); - }); - - it('bidRequest data', () => { - const request = spec.buildRequests(bidRequests); - expect(request.data).to.exists; - }); - - it('bidRequest zoneIds', () => { - const request = spec.buildRequests(bidRequests); - expect(request.data.zoneId).to.equal('aa0444af31;8f527a4835'); - }); - - it('bidRequest gdpr consent', () => { - const consentString = 'consentString'; - const bidderRequest = { - bidderCode: 'trafficroots', - auctionId: '18fd8b8b0bd757', - bidderRequestId: '418b37f85e772c', - timeout: 3000, - gdprConsent: { - consentString: consentString, - gdprApplies: true - } - }; - - const request = spec.buildRequests(bidRequests, bidderRequest); - - expect(request.data.gdpr).to.exist; - expect(request.data.gdpr.applies).to.exist.and.to.be.true; - expect(request.data.gdpr.consent).to.exist.and.to.equal(consentString); - }); - }); - - describe('interpretResponse', () => { - const bidRequest = [{ - 'bidder': 'trafficroots', - 'bidId': '29fa5c08928bde', - 'params': { - 'zoneId': 'aa0444af31', - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - 'sizes': [[300, 250], [300, 600]], - 'bidderRequestId': '418b37f85e772c', - 'auctionId': '18fd8b8b0bd757' - }]; - - const bidResponse = { - body: [{ - 'id': 'div-gpt-ad-1460505748561-0', - 'ad': 'test ad', - 'width': 320, - 'height': 250, - 'cpm': 5.2 - }], - headers: {} - }; - - it('required keys', () => { - const result = spec.interpretResponse(bidResponse, bidRequest); - - let requiredKeys = [ - 'requestId', - 'creativeId', - 'adId', - 'cpm', - 'width', - 'height', - 'currency', - 'netRevenue', - 'ttl', - 'ad' - ]; - - let resultKeys = Object.keys(result[0]); - resultKeys.forEach(function(key) { - expect(requiredKeys.indexOf(key) !== -1).to.equal(true); - }); - }) - }); -}); From 6ddd14fa3474a72661e0c2b6aa7e37e918522b0a Mon Sep 17 00:00:00 2001 From: harpere Date: Tue, 25 Sep 2018 14:15:49 -0400 Subject: [PATCH 0716/1594] adding account to s2s bidder-sync request (#3123) * adding account_id to s2s bidder-sync request * changed param name from account_id to account --- modules/prebidServerBidAdapter/index.js | 3 ++- test/spec/modules/prebidServerBidAdapter_spec.js | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index f94cfeecec9..5d23a0366ea 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -98,7 +98,8 @@ function queueSync(bidderCodes, gdprConsent) { const payload = { uuid: utils.generateUUID(), - bidders: bidderCodes + bidders: bidderCodes, + account: _s2sConfig.accountId }; if (gdprConsent) { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index a22006e5a81..7c3a356c9e8 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -458,6 +458,8 @@ describe('S2S Adapter', function () { expect(requestBid.gdpr).is.equal(1); expect(requestBid.gdpr_consent).is.equal('abc123def'); + expect(requestBid.bidders).to.contain('appnexus').and.to.have.lengthOf(1); + expect(requestBid.account).is.equal('1'); }); it('check gdpr info gets added into cookie_sync request: have consent data but gdprApplies is false', function () { From fec06e8d9596372574abe8e080811518cb5d6826 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 25 Sep 2018 14:42:21 -0400 Subject: [PATCH 0717/1594] Prebid 1.25.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a45283e1d24..5d6ee2dc7bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.25.0-pre", + "version": "1.25.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From abf9f54d6fe370377fe4cc59d3eb151a466fb68c Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 25 Sep 2018 14:55:10 -0400 Subject: [PATCH 0718/1594] increment prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5d6ee2dc7bb..f5c134bf07e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.25.0", + "version": "1.26.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 100e3e1b533cf03943c8cb4c096bf859961faa51 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Wed, 26 Sep 2018 08:00:28 -0700 Subject: [PATCH 0719/1594] Bugfix: Issue 3111 (#3122) * bug fix for Prebid issue 3111 * adding try-catch around the fix * added a warning on exception handling * updated the message * using util.deepClone * changed variable name from original_bid to originalBid * unit test case for checking original object modification --- modules/pubmaticBidAdapter.js | 4 +++- test/spec/modules/pubmaticBidAdapter_spec.js | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 8b5a766e48b..452f6149091 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -319,7 +319,9 @@ export const spec = { var dctr = ''; var dctrLen; var dctrArr = []; - validBidRequests.forEach(bid => { + var bid; + validBidRequests.forEach(originalBid => { + bid = utils.deepClone(originalBid); _parseAdSlot(bid); if (bid.params.hasOwnProperty('video')) { if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex)) { diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index e67ec1f11a2..be3b59c1a80 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -217,7 +217,13 @@ describe('PubMatic adapter', function () { }); describe('Request formation', function () { - it('Endpoint checking', function () { + it('buildRequests function should not modify original bidRequests object', function () { + let originalBidRequests = utils.deepClone(bidRequests); + let request = spec.buildRequests(bidRequests); + expect(bidRequests).to.deep.equal(originalBidRequests); + }); + + it('Endpoint checking', function () { let request = spec.buildRequests(bidRequests); expect(request.url).to.equal('//hbopenbid.pubmatic.com/translator?source=prebid-client'); expect(request.method).to.equal('POST'); From df8cb0079a91f658dfaae5caa9b841d09f3c496b Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 27 Sep 2018 10:26:34 -0400 Subject: [PATCH 0720/1594] update circleci link to just Prebid.js builds (#3132) --- RELEASE_SCHEDULE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index a1fa77b7db0..611a98473ff 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -19,7 +19,7 @@ Announcements regarding releases will be made to the #headerbidding-dev channel _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 all browserstack tests are passing. On PR merge to master CircleCI will run unit tests on browserstack. Checking the last CircleCI build [here](https://circleci.com/gh/prebid) for master branch will show you detailed results. +1. Make Sure all browserstack tests are passing. On PR merge to master CircleCI will run unit tests on browserstack. Checking the last CircleCI build [here](https://circleci.com/gh/prebid/Prebid.js) for master branch will show you detailed results. In case of failure do following, - Try to fix the failing tests. From 84c04664fae1c855197775e68d1772c03a26f29e Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Thu, 27 Sep 2018 15:59:18 -0400 Subject: [PATCH 0721/1594] Sonobi - Fix ref encoding (#3125) * encoding ref param in sbi.js * fixed unit tests * template stringed creative * fixed unit test checking ref param * add some missing colons --- modules/sonobiBidAdapter.js | 4 ++-- test/spec/modules/sonobiBidAdapter_spec.js | 23 ++++++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 3d9ad2ce976..15bcca50a13 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -189,12 +189,12 @@ const _creative = (mediaType) => (sbiDc, sbiAid) => { if (mediaType === 'video') { return _videoCreative(sbiDc, sbiAid) } - const src = 'https://' + sbiDc + 'apex.go.sonobi.com/sbi.js?aid=' + sbiAid + '&as=null' + '&ref=' + getTopWindowLocation().href; + const src = `https://${sbiDc}apex.go.sonobi.com/sbi.js?aid=${sbiAid}&as=null&ref=${encodeURIComponent(getTopWindowLocation().href)}`; return ''; }; function _videoCreative(sbiDc, sbiAid) { - return `https://${sbiDc}apex.go.sonobi.com/vast.xml?vid=${sbiAid}&ref=${getTopWindowLocation().href}` + return `https://${sbiDc}apex.go.sonobi.com/vast.xml?vid=${sbiAid}&ref=${encodeURIComponent(getTopWindowLocation().href)}` } function _getBidIdFromTrinityKey (key) { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 349a2e80263..69138c063c9 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -294,7 +294,7 @@ describe('SonobiBidAdapter', function () { 'cpm': 1.07, 'width': 300, 'height': 600, - 'ad': '', + 'ad': ``, 'ttl': 500, 'creativeId': '1234abcd', 'netRevenue': true, @@ -306,7 +306,7 @@ describe('SonobiBidAdapter', function () { 'cpm': 1.25, 'width': 300, 'height': 250, - 'ad': 'https://mco-1-apex.go.sonobi.com/vast.xml?vid=30292e432662bd5f86d90774b944b038&ref=http://localhost/', + 'ad': 'https://mco-1-apex.go.sonobi.com/vast.xml?vid=30292e432662bd5f86d90774b944b038&ref=http%3A%2F%2Flocalhost%2F', 'ttl': 500, 'creativeId': '30292e432662bd5f86d90774b944b038', 'netRevenue': true, @@ -318,13 +318,20 @@ describe('SonobiBidAdapter', function () { it('should map bidResponse to prebidResponse', function () { const response = spec.interpretResponse(bidResponse, bidRequests); - response.forEach(resp => { - let regx = /http:\/\/localhost:9876\/.*?(?="|$)/ - resp.ad = resp.ad.replace(regx, 'http://localhost/'); + response.forEach((resp, i) => { + expect(resp.requestId).to.equal(prebidResponse[i].requestId); + expect(resp.cpm).to.equal(prebidResponse[i].cpm); + expect(resp.width).to.equal(prebidResponse[i].width); + expect(resp.height).to.equal(prebidResponse[i].height); + expect(resp.ttl).to.equal(prebidResponse[i].ttl); + expect(resp.creativeId).to.equal(prebidResponse[i].creativeId); + expect(resp.netRevenue).to.equal(prebidResponse[i].netRevenue); + expect(resp.currency).to.equal(prebidResponse[i].currency); + expect(resp.aid).to.equal(prebidResponse[i].aid); + expect(resp.ad.indexOf('localhost')).to.be.greaterThan(0); }); - expect(response).to.deep.equal(prebidResponse); - }) - }) + }); + }); describe('.getUserSyncs', function () { let bidResponse = [{ From cea3f1e5f7eaf8b17d9f945ad2bb1b7a4379db52 Mon Sep 17 00:00:00 2001 From: John Salis Date: Thu, 27 Sep 2018 16:30:24 -0400 Subject: [PATCH 0722/1594] Add video params to Beachfront adapter (#3121) * add playback method to video targeting * bump adapter version * add maxduration to video targeting --- modules/beachfrontBidAdapter.js | 4 ++-- test/spec/modules/beachfrontBidAdapter_spec.js | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 7ce1476627c..ccb45d0a041 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -5,7 +5,7 @@ import { VIDEO, BANNER } from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.2'; +const ADAPTER_VERSION = '1.3'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; @@ -13,7 +13,7 @@ export const VIDEO_ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; export const BANNER_ENDPOINT = '//display.bfmio.com/prebid_display'; export const OUTSTREAM_SRC = '//player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; -export const VIDEO_TARGETING = ['mimes']; +export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration']; export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; let appId = ''; diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index a70fdfb77b6..21e175a5b82 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -218,11 +218,13 @@ describe('BeachfrontAdapter', function () { it('must override video targeting params', function () { const bidRequest = bidRequests[0]; const mimes = ['video/webm']; + const playbackmethod = 2; + const maxduration = 30; bidRequest.mediaTypes = { video: {} }; - bidRequest.params.video = { mimes }; + bidRequest.params.video = { mimes, playbackmethod, maxduration }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video).to.deep.contain({ mimes }); + expect(data.imp[0].video).to.deep.contain({ mimes, playbackmethod, maxduration }); }); it('must add GDPR consent data to the request', function () { From ab706adef22f051d3ee28027faeb778d9bcd0b09 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Fri, 28 Sep 2018 12:54:11 -0700 Subject: [PATCH 0723/1594] Fix for Issue 3130: passing new copy of adUnits object to every adapter (#3131) * passing new copy of adUnits object to every adapter * add test to verify bidders can't mutate eachothers bid requests --- src/adaptermanager.js | 4 ++-- test/spec/unit/core/adapterManager_spec.js | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index e851a9accc9..9b2abe79f01 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -194,7 +194,7 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, auctionId, bidderRequestId, tid, - bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsS2SCopy, labels}), + bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': utils.deepClone(adUnitsS2SCopy), labels}), auctionStart: auctionStart, timeout: _s2sConfig.timeout, src: CONSTANTS.S2S.SRC, @@ -229,7 +229,7 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, bidderCode, auctionId, bidderRequestId, - bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsClientCopy, labels}), + bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': utils.deepClone(adUnitsClientCopy), labels}), auctionStart: auctionStart, timeout: cbTimeout, refererInfo diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 644f10de794..47f4af7ad24 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -762,6 +762,26 @@ describe('adapterManager tests', function () { }) }); + it('should make separate bidder request objects for each bidder', () => { + adUnits = [utils.deepClone(getAdUnits()[0])]; + + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + let sizes1 = bidRequests[1].bids[0].sizes; + let sizes2 = bidRequests[0].bids[0].sizes; + + // mutate array + sizes1.splice(0, 1); + + expect(sizes1).not.to.deep.equal(sizes2); + }); + describe('setBidderSequence', function () { beforeEach(function () { sinon.spy(utils, 'shuffle'); From 9b19930d1ebda0c5783f8cce114f48ed244f72e6 Mon Sep 17 00:00:00 2001 From: skazedo Date: Fri, 28 Sep 2018 16:02:18 -0400 Subject: [PATCH 0724/1594] Support Video Renderer (#3104) * initial commit * updated contact and tag details * changes ti support the renderers * changes to pass dimId * fixed names of internal mapping * added comment * added gdpr param to request and other fixes * modified api url * fix * fixed the secure api call * rolled back video event callback till we support it --- modules/zedoBidAdapter.js | 49 +++++++++++++++++++++++- test/spec/modules/zedoBidAdapter_spec.js | 8 +++- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/modules/zedoBidAdapter.js b/modules/zedoBidAdapter.js index d6f75da4ece..970f28e47d5 100644 --- a/modules/zedoBidAdapter.js +++ b/modules/zedoBidAdapter.js @@ -2,10 +2,11 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { BANNER, VIDEO } from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; +import { Renderer } from 'src/Renderer'; const BIDDER_CODE = 'zedo'; const URL = '//z2.zedo.com/asw/fmh.json'; -const SECURE_URL = '//z2.zedo.com/asw/fmh.json'; +const SECURE_URL = '//saxp.zedo.com/asw/fmh.json'; const DIM_TYPE = { '7': 'display', '9': 'display', @@ -153,6 +154,8 @@ function newBid(serverBid, creativeBid, bidderRequest) { const bid = { requestId: serverBid.slotId, creativeId: creativeBid.adId, + network: serverBid.network, + adType: creativeBid.creativeDetails.type, dealId: 99999999, currency: 'USD', netRevenue: true, @@ -167,12 +170,21 @@ function newBid(serverBid, creativeBid, bidderRequest) { cpm: (parseInt(creativeBid.cpm) * 0.65) / 1000000, ttl: 3600 }); + const rendererOptions = utils.deepAccess( + bidderRequest, + 'renderer.options' + ); + let rendererUrl = utils.getTopWindowLocation().protocol === 'http:' ? 'http://c14.zedo.com/gecko/beta/fmpbgt.min.js' : 'https://ss3.zedo.com/gecko/beta/fmpbgt.min.js'; + Object.assign(bid, { + adResponse: serverBid, + renderer: getRenderer(bid.adUnitCode, serverBid.slotId, rendererUrl, rendererOptions) + }); } else { Object.assign(bid, { width: creativeBid.width, height: creativeBid.height, cpm: (parseInt(creativeBid.cpm) * 0.6) / 1000000, - ad: creativeBid.creativeDetails.adContent + ad: creativeBid.creativeDetails.adContent, }); } @@ -197,6 +209,39 @@ function getSizes(requestSizes) { return [width, height]; } +function getRenderer(adUnitCode, rendererId, rendererUrl, rendererOptions = {}) { + const renderer = Renderer.install({ + id: rendererId, + url: rendererUrl, + config: rendererOptions, + loaded: false, + }); + + try { + renderer.setRender(videoRenderer); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + + renderer.setEventHandlers({ + impression: () => utils.logMessage('ZEDO video impression'), + loaded: () => utils.logMessage('ZEDO video loaded'), + ended: () => { + utils.logMessage('ZEDO renderer video ended'); + document.querySelector(`#${adUnitCode}`).style.display = 'none'; + } + }); + return renderer; +} + +function videoRenderer(bid) { + // push to render queue + bid.renderer.push(() => { + var rndr = new ZdPBTag(bid.adUnitCode, bid.network, bid.width, bid.height, bid.adType, bid.vastXml); + rndr.renderAd(); + }); +} + function parseMediaType(creativeBid) { const adType = creativeBid.creativeDetails.type; if (adType === 'VAST') { diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js index 85209edd4c3..abb0a5c97fb 100644 --- a/test/spec/modules/zedoBidAdapter_spec.js +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -43,7 +43,7 @@ describe('The ZEDO bidding adapter', function () { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmh.json/); + expect(request.url).to.match(/^\/\/saxp.zedo.com\/asw\/fmh.json/); expect(request.method).to.equal('GET'); const zedoRequest = request.data; expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}]}'); @@ -68,7 +68,7 @@ describe('The ZEDO bidding adapter', function () { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmh.json/); + expect(request.url).to.match(/^\/\/saxp.zedo.com\/asw\/fmh.json/); expect(request.method).to.equal('GET'); const zedoRequest = request.data; expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":640,"height":480,"dimension":85,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"Inarticle"}]}]}'); @@ -234,14 +234,18 @@ describe('The ZEDO bidding adapter', function () { }, }] }; + const bids = spec.interpretResponse(response, request); expect(bids).to.have.lengthOf(1); expect(bids[0].requestId).to.equal('ad1d762'); expect(bids[0].cpm).to.equal(0.78); expect(bids[0].width).to.equal('640'); expect(bids[0].height).to.equal('480'); + expect(bids[0].adType).to.equal('VAST'); expect(bids[0].vastXml).to.not.equal(''); expect(bids[0].ad).to.be.an('undefined'); + expect(bids[0].renderer).not.to.be.an('undefined'); + bids[0].renderer.render(bids[0]); }); }); From 0bd1d1ab485e222c0b013cd8ec4f7c489d063f9c Mon Sep 17 00:00:00 2001 From: derdeka Date: Fri, 28 Sep 2018 22:16:11 +0200 Subject: [PATCH 0725/1594] fixes #3128 YieldlabBidAdapter is not using bidRequest.params.adSize (#3129) * fixes #3128 YieldlabBidAdapter is not using bidRequest.params.adSize as customsize in bidResponse * fixes #3128 YieldlabBidAdapter is not using bidRequest.params.adSize as customsize in bidResponse - add test --- modules/yieldlabBidAdapter.js | 4 +-- test/spec/modules/yieldlabBidAdapter_spec.js | 34 ++++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 32ed723a15a..94aae092997 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -80,8 +80,8 @@ export const spec = { const bidResponse = { requestId: bidRequest.bidId, cpm: matchedBid.price / 100, - width: primarysize[0], - height: primarysize[1], + width: customsize[0], + height: customsize[1], creativeId: '' + matchedBid.id, dealId: matchedBid.pid, currency: CURRENCY_CODE, diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index 0e97910bbb7..497e9c7b894 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -85,17 +85,36 @@ describe('yieldlabBidAdapter', function () { }) describe('interpretResponse', function () { - const validRequests = { - validBidRequests: [REQUEST] - } - it('handles nobid responses', function () { expect(spec.interpretResponse({body: {}}, {validBidRequests: []}).length).to.equal(0) expect(spec.interpretResponse({body: []}, {validBidRequests: []}).length).to.equal(0) }) it('should get correct bid response', function () { - const result = spec.interpretResponse({body: [RESPONSE]}, validRequests) + const result = spec.interpretResponse({body: [RESPONSE]}, {validBidRequests: [REQUEST]}) + + expect(result[0].requestId).to.equal('2d925f27f5079f') + expect(result[0].cpm).to.equal(0.01) + expect(result[0].width).to.equal(728) + expect(result[0].height).to.equal(90) + expect(result[0].creativeId).to.equal('1111') + expect(result[0].dealId).to.equal(2222) + expect(result[0].currency).to.equal('EUR') + expect(result[0].netRevenue).to.equal(false) + expect(result[0].ttl).to.equal(300) + expect(result[0].referrer).to.equal('') + expect(result[0].ad).to.include(''; - let formattedAd = '
'; + let intextAd = '
'; + let expandAd = '
'; - it('should get correct bid response', function () { - var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + it('should get correct intext bid response', function () { + var request = spec.buildRequests(bannerBidRequests, bannerBidRequests[0]); let expectedResponse = [ { @@ -165,8 +184,29 @@ describe('freewheel-ssp BidAdapter Test', function () { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); + it('should get correct expand bid response', function () { + var request = spec.buildRequests(expandBidRequests, expandBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: expandAd + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + it('should get correct bid response with formated ad', function () { - var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + var request = spec.buildRequests(intextBidRequests, intextBidRequests[0]); let expectedResponse = [ { @@ -178,7 +218,7 @@ describe('freewheel-ssp BidAdapter Test', function () { currency: 'EUR', netRevenue: true, ttl: 360, - ad: formattedAd + ad: intextAd } ]; @@ -187,7 +227,7 @@ describe('freewheel-ssp BidAdapter Test', function () { }); it('handles nobid responses', function () { - var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + var reqest = spec.buildRequests(intextBidRequests, intextBidRequests[0]); let response = ''; let result = spec.interpretResponse(response, reqest); From ee1cd7e0b6b3c8be9e6cfac71aac6c76809876c7 Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Sat, 29 Sep 2018 06:24:37 +0800 Subject: [PATCH 0727/1594] Rubicon adapter: get referrer from bidderRequest.refererInfo.referer; (#3087) * DecodeUrl if url is encoded Appnexus new module is passing the encoded url and sometimes Publisher are passing encoded url in the referrer parameter. This fix is a protection in case a module is update and start passing encode url. Our AE is not decoding and from some test I did, monetisation could be highly impacted. * Update rubiconBidAdapter.js * Update rubiconBidAdapter_spec.js * Update rubiconBidAdapter_spec.js * Update rubiconBidAdapter_spec.js * Update rubiconBidAdapter_spec.js * Update rubiconBidAdapter_spec.js * Update rubiconBidAdapter_spec.js * Update rubiconBidAdapter.js * Update rubiconBidAdapter.js * Update rubiconBidAdapter_spec.js * Update rubiconBidAdapter.js * Update rubiconBidAdapter_spec.js * Update rubiconBidAdapter_spec.js --- modules/rubiconBidAdapter.js | 8 +++---- test/spec/modules/rubiconBidAdapter_spec.js | 24 +++++++++++++++++++-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 4e5ef22c2ce..7f219886057 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -114,7 +114,7 @@ export const spec = { let size = parseSizes(bidRequest); let data = { - page_url: _getPageUrl(bidRequest), + page_url: _getPageUrl(bidRequest, bidderRequest), resolution: _getScreenResolution(), account_id: params.accountId, integration: INTEGRATION, @@ -327,7 +327,7 @@ export const spec = { 'p_geo.latitude': isNaN(parseFloat(latitude)) ? undefined : parseFloat(latitude).toFixed(4), 'p_geo.longitude': isNaN(parseFloat(longitude)) ? undefined : parseFloat(longitude).toFixed(4), 'tg_fl.eid': bidRequest.code, - 'rf': _getPageUrl(bidRequest) + 'rf': _getPageUrl(bidRequest, bidderRequest) }; if (bidderRequest.gdprConsent) { @@ -503,12 +503,12 @@ function _getDigiTrustQueryParams() { * @param {BidRequest} bidRequest * @returns {string} */ -function _getPageUrl(bidRequest) { +function _getPageUrl(bidRequest, bidderRequest) { let pageUrl = config.getConfig('pageUrl'); if (bidRequest.params.referrer) { pageUrl = bidRequest.params.referrer; } else if (!pageUrl) { - pageUrl = utils.getTopWindowUrl(); + pageUrl = bidderRequest.refererInfo.referer; } return bidRequest.params.secure ? pageUrl.replace(/^http:/i, 'https:') : pageUrl; } diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 76859729455..70790eaa46f 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -466,13 +466,33 @@ describe('the rubicon adapter', function () { }); }); - it('page_url should use params.referrer, config.getConfig("pageUrl"), utils.getTopWindowUrl() in that order', function () { - sandbox.stub(utils, 'getTopWindowUrl').callsFake(() => 'http://www.prebid.org'); + it('should add referer info to request data', function () { + let refererInfo = { + referer: 'http://www.prebid.org', + reachedTop: true, + numIframes: 1, + stack: [ + 'http://www.prebid.org/page.html', + 'http://www.prebid.org/iframe1.html', + ] + }; + + bidderRequest = Object.assign({refererInfo}, bidderRequest); + delete bidderRequest.bids[0].params.referrer; + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); + + expect(parseQuery(request.data).rf).to.exist; + expect(parseQuery(request.data).rf).to.equal('http://www.prebid.org'); + }); + it('page_url should use params.referrer, config.getConfig("pageUrl"), bidderRequest.refererInfo in that order', function () { let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(parseQuery(request.data).rf).to.equal('localhost'); delete bidderRequest.bids[0].params.referrer; + let refererInfo = { referer: 'http://www.prebid.org' }; + bidderRequest = Object.assign({refererInfo}, bidderRequest); [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(parseQuery(request.data).rf).to.equal('http://www.prebid.org'); From f217d118b44598f429f2e05938a32bbc31e7b124 Mon Sep 17 00:00:00 2001 From: REXRTB Date: Mon, 1 Oct 2018 07:30:36 +0300 Subject: [PATCH 0728/1594] [Update] Change name BidAdapter and some fix (#3118) * Add: rxrtb prebidAdapter * Update: params for test * Update: code format * Update: code format * Update: code format * Fix param check * Update rxrtbBidAdapter.js * Remove required source param * Update and rename rxrtbBidAdapter.js to rexrtbBidAdapter.js * Update and rename rxrtbBidAdapter.md to rexrtbBidAdapter.md * Update and rename rxrtbBidAdapter_spec.js to rexrtbBidAdapter_spec.js * Revert "Update rxrtbBidAdapter.js" This reverts commit 09bca026d7e28e98ed5ff7a138df78618cd363a2. * Revert "Update and rename rxrtbBidAdapter_spec.js to rexrtbBidAdapter_spec.js" This reverts commit 2481c58bb10a4634327773198edaaeea3b5a89f5. * Revert "Update and rename rxrtbBidAdapter.md to rexrtbBidAdapter.md" This reverts commit af9a49134752043e83c6fd922ba16e7ffd6f8f42. * Revert "Update and rename rxrtbBidAdapter.js to rexrtbBidAdapter.js" This reverts commit 81a17ad8076cdafc637ca9a69f57fe1180a8c7a1. * Revert "Remove required source param" This reverts commit 38b273d76aa2d93ab167b96db80ca146d5267e2e. * Revert "Update rxrtbBidAdapter.js" * Update and rename rexrtbPrebid --- ...rxrtbBidAdapter.js => rexrtbBidAdapter.js} | 12 ++++----- ...rxrtbBidAdapter.md => rexrtbBidAdapter.md} | 8 +++--- ...apter_spec.js => rexrtbBidAdapter_spec.js} | 25 +++++-------------- 3 files changed, 15 insertions(+), 30 deletions(-) rename modules/{rxrtbBidAdapter.js => rexrtbBidAdapter.js} (90%) rename modules/{rxrtbBidAdapter.md => rexrtbBidAdapter.md} (75%) rename test/spec/modules/{rxrtbBidAdapter_spec.js => rexrtbBidAdapter_spec.js} (85%) diff --git a/modules/rxrtbBidAdapter.js b/modules/rexrtbBidAdapter.js similarity index 90% rename from modules/rxrtbBidAdapter.js rename to modules/rexrtbBidAdapter.js index 37aa20b68cd..4048bf40afe 100644 --- a/modules/rxrtbBidAdapter.js +++ b/modules/rexrtbBidAdapter.js @@ -3,7 +3,7 @@ import {BANNER} from 'src/mediaTypes'; import {registerBidder} from 'src/adapters/bidderFactory'; import {config} from 'src/config'; -const BIDDER_CODE = 'rxrtb'; +const BIDDER_CODE = 'rexrtb'; const DEFAULT_HOST = 'bid.rxrtb.bid'; const AUCTION_TYPE = 2; const RESPONSE_TTL = 900; @@ -12,7 +12,7 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], isBidRequestValid: function (bidRequest) { - return 'params' in bidRequest && bidRequest.params.source !== undefined && bidRequest.params.id !== undefined && utils.isInteger(bidRequest.params.id) && bidRequest.params.token !== undefined; + return 'params' in bidRequest && bidRequest.params.id !== undefined && utils.isInteger(bidRequest.params.id) && bidRequest.params.token !== undefined; }, buildRequests: function (validBidRequests) { var requests = []; @@ -62,7 +62,6 @@ registerBidder(spec); function getDomain(url) { var a = document.createElement('a'); a.href = url; - return a.host; } @@ -99,11 +98,9 @@ function makeImp(req) { 'tagid': req.adUnitCode, 'banner': makeBanner(req) }; - if (req.params.bidfloor && isFinite(req.params.bidfloor)) { imp.bidfloor = req.params.bidfloor } - return imp; } @@ -124,9 +121,10 @@ function makeBanner(req) { } function makeSite(req) { + let domain = getDomain(config.getConfig('publisherDomain')); return { - 'id': req.params.source, - 'domain': getDomain(config.getConfig('publisherDomain')), + 'id': req.params.source || domain, + 'domain': domain, 'page': utils.getTopWindowUrl(), 'ref': utils.getTopWindowReferrer() }; diff --git a/modules/rxrtbBidAdapter.md b/modules/rexrtbBidAdapter.md similarity index 75% rename from modules/rxrtbBidAdapter.md rename to modules/rexrtbBidAdapter.md index e9628bed0dc..1cb937b0a3d 100644 --- a/modules/rxrtbBidAdapter.md +++ b/modules/rexrtbBidAdapter.md @@ -1,15 +1,15 @@ # Overview -Module Name: rxrtb Bidder Adapter +Module Name: REXRTB Bidder Adapter Module Type: Bidder Adapter -Maintainer: contact@picellaltd.com +Maintainer: tech@rexrtb.com # Description -Module that connects to rxrtb's demand source +Module that connects to REXRTB's demand source # Test Parameters ```javascript @@ -19,7 +19,7 @@ Module that connects to rxrtb's demand source sizes: [[728, 98]], bids: [ { - bidder: 'rxrtb', + bidder: 'rexrtb', params: { id: 89, token: '658f11a5efbbce2f9be3f1f146fcbc22', diff --git a/test/spec/modules/rxrtbBidAdapter_spec.js b/test/spec/modules/rexrtbBidAdapter_spec.js similarity index 85% rename from test/spec/modules/rxrtbBidAdapter_spec.js rename to test/spec/modules/rexrtbBidAdapter_spec.js index b56ef0544b2..b35e05bbf46 100644 --- a/test/spec/modules/rxrtbBidAdapter_spec.js +++ b/test/spec/modules/rexrtbBidAdapter_spec.js @@ -1,11 +1,11 @@ import {expect} from 'chai'; -import {spec} from 'modules/rxrtbBidAdapter'; +import {spec} from 'modules/rexrtbBidAdapter'; -describe('rxrtb adapater', function () { +describe('rexrtb adapater', function () { describe('Test validate req', function () { it('should accept minimum valid bid', function () { let bid = { - bidder: 'rxrtb', + bidder: 'rexrtb', params: { id: 89, token: '658f11a5efbbce2f9be3f1f146fcbc22', @@ -19,7 +19,7 @@ describe('rxrtb adapater', function () { it('should reject missing id', function () { let bid = { - bidder: 'rxrtb', + bidder: 'rexrtb', params: { token: '658f11a5efbbce2f9be3f1f146fcbc22', source: 'prebidtest' @@ -32,7 +32,7 @@ describe('rxrtb adapater', function () { it('should reject id not Integer', function () { let bid = { - bidder: 'rxrtb', + bidder: 'rexrtb', params: { id: '123', token: '658f11a5efbbce2f9be3f1f146fcbc22', @@ -43,25 +43,12 @@ describe('rxrtb adapater', function () { expect(isValid).to.equal(false); }); - - it('should reject missing source', function () { - let bid = { - bidder: 'rxrtb', - params: { - id: 89, - token: '658f11a5efbbce2f9be3f1f146fcbc22' - } - }; - const isValid = spec.isBidRequestValid(bid); - - expect(isValid).to.equal(false); - }); }); describe('Test build request', function () { it('minimum request', function () { let bid = { - bidder: 'rxrtb', + bidder: 'rexrtb', sizes: [[728, 90]], bidId: '4d0a6829338a07', adUnitCode: 'div-gpt-ad-1460505748561-0', From 29e9b13d15628f1e0a9da6d6f051ff06034e614f Mon Sep 17 00:00:00 2001 From: Daniel Tiplinsky Date: Mon, 1 Oct 2018 17:09:41 +0300 Subject: [PATCH 0729/1594] Add ADSpend bidder adapter (#3005) * Add ADSpend bidder adapter * Remove superfluous argument and fix bug with sizes * Change bidder aliases * Replace fetch with ajax from src/ajax.js * Store win event URL in memory, not in cookie * Use getConfig(...) instead of nested access * Add sending multiple impressions to bidder --- modules/adspendBidAdapter.js | 165 +++++++++++++++++++++++++++++++++++ modules/adspendBidAdapter.md | 60 +++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 modules/adspendBidAdapter.js create mode 100644 modules/adspendBidAdapter.md diff --git a/modules/adspendBidAdapter.js b/modules/adspendBidAdapter.js new file mode 100644 index 00000000000..70b98a05112 --- /dev/null +++ b/modules/adspendBidAdapter.js @@ -0,0 +1,165 @@ +import * as utils from 'src/utils'; +import { ajax } from 'src/ajax' +import { config } from 'src/config'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'adspend'; +const BID_URL = '//rtb.com.ru/headerbidding-bid'; +const SYNC_URL = '//rtb.com.ru/headerbidding-sync?uid={UUID}'; +const COOKIE_NAME = 'hb-adspend-id'; +const UUID_LEN = 36; +const TTL = 10000; +const RUB = 'RUB'; +const FIRST_PRICE = 1; +const NET_REVENUE = true; + +const winEventURLs = {}; +const placementToBidMap = {}; + +export const spec = { + code: BIDDER_CODE, + aliases: ['as'], + supportedMediaTypes: [BANNER], + + onBidWon: function(winObj) { + const requestId = winObj.requestId; + const cpm = winObj.cpm; + const event = winEventURLs[requestId].replace( + /\$\{AUCTION_PRICE\}/, + cpm + ); + + ajax(event, null); + }, + + isBidRequestValid: function(bid) { + const adServerCur = config.getConfig('currency.adServerCurrency') === RUB; + + return !!(adServerCur && + bid.params && + bid.params.bidfloor && + bid.crumbs.pubcid && + utils.checkCookieSupport() && + utils.cookiesAreEnabled() + ); + }, + + buildRequests: function(bidRequests, bidderRequest) { + const req = bidRequests[Math.floor(Math.random() * bidRequests.length)]; + const bidId = req.bidId; + const at = FIRST_PRICE; + const site = { id: req.crumbs.pubcid, domain: document.domain }; + const device = { ua: navigator.userAgent, ip: '' }; + const user = { id: getUserID() } + const cur = [ RUB ]; + const tmax = bidderRequest.timeout; + + const imp = bidRequests.map(req => { + const params = req.params; + + const tagId = params.tagId; + const id = params.placement; + const banner = { 'format': getFormats(req.sizes) }; + const bidfloor = params.bidfloor !== undefined + ? Number(params.bidfloor) : 1; + const bidfloorcur = RUB; + + placementToBidMap[id] = bidId; + + return { + id, + tagId, + banner, + bidfloor, + bidfloorcur, + secure: 0, + }; + }); + + const payload = { + bidId, + at, + site, + device, + user, + imp, + cur, + tmax, + }; + + return { + method: 'POST', + url: BID_URL, + data: JSON.stringify(payload), + }; + }, + + interpretResponse: function(resp, {bidderRequest}) { + if (resp.body === '') return []; + + const bids = resp.body.seatbid[0].bid.map(bid => { + const cpm = bid.price; + const impid = bid.impid; + const requestId = placementToBidMap[impid]; + const width = bid.w; + const height = bid.h; + const creativeId = bid.adid; + const dealId = bid.dealid; + const currency = resp.body.cur; + const netRevenue = NET_REVENUE; + const ttl = TTL; + const ad = bid.adm; + + return { + cpm, + requestId, + width, + height, + creativeId, + dealId, + currency, + netRevenue, + ttl, + ad, + }; + }); + + return bids; + }, + + getUserSyncs: function(syncOptions, resps) { + let syncs = []; + + resps.forEach(resp => { + if (syncOptions.pixelEnabled && resp.body === '') { + const uuid = getUserID(); + syncs.push({ + type: 'image', + url: SYNC_URL.replace('{UUID}', uuid), + }); + } + }); + + return syncs + } +} + +const getUserID = () => { + const i = document.cookie.indexOf(COOKIE_NAME); + + if (i === -1) { + const uuid = utils.generateUUID(); + document.cookie = `${COOKIE_NAME}=${uuid}; path=/`; + return uuid; + } + + const j = i + COOKIE_NAME.length + 1; + return document.cookie.substring(j, j + UUID_LEN); +}; + +const getFormats = arr => arr.map((s) => { + return { w: s[0], h: s[1] }; +}); + +registerBidder(spec); diff --git a/modules/adspendBidAdapter.md b/modules/adspendBidAdapter.md new file mode 100644 index 00000000000..dc3409b0057 --- /dev/null +++ b/modules/adspendBidAdapter.md @@ -0,0 +1,60 @@ +# Overview + +``` +Module Name: AdSpend Bidder Adapter +Module Type: Bidder Adapter +Maintainer: gaffoonster@gmail.com +``` + +# Description + +Connects to AdSpend bidder. +AdSpend adapter supports only Banner at the moment. Video and Native will be add soon. + +# Test Parameters +``` +var adUnits = [ + // Banner + { + code: 'div-gpt-ad-1460505748561-0', + mediaTypes: { + banner: { + // You can choose one of them + sizes: [ + [300, 250], + [300, 600], + [240, 400], + [728, 90], + ] + } + }, + bids: [ + { + bidder: "adspend", + params: { + bidfloor: 1, + placement: 'test', + tagId: 'test-ad', + } + } + ] + } +]; + +pbjs.que.push(() => { + pbjs.setConfig({ + userSync: { + syncEnabled: true, + enabledBidders: ['adspend'], + pixelEnabled: true, + syncsPerBidder: 200, + syncDelay: 100, + }, + currency: { + adServerCurrency: 'RUB' // We work only with rubles for now + } + }); +}); +``` + +**It's a test banner, so you'll see some errors in console cause it will be trying to call our system's events.** From d81dfd2be314e115e2323bffcf8a79bdfe165d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Fouch=C3=A9?= Date: Mon, 1 Oct 2018 23:58:02 +0200 Subject: [PATCH 0730/1594] Add Adagio bidder and analytics adapters (#3069) * Add Adagio bidder and analytics adapters * Adagio - removed the superfluous argument passed to `_getDevice()` * Adagio - IE11 fix - replaced Array.prototype.find by its core-js equivalent * Adagio - linting. * Adagio - Renamed the property 'gdpr_consent' to 'gdpr' in our adRequest. * Adagio - Send one HTTP request per siteId - add the suffix `Id` to most params - add `dealId` and `timeout` to the payload of the analytics adapter - move `siteId` at the top-level of the ad request - remov the param `Publisher` * Removed the analytics adapters, they are not ready from prime time. * Removed the analytics adapter, it's not ready from prime time. * Added adagioAnalyticsAdapter as a 'bundle'. --- modules/adagioAnalyticsAdapter.js | 23 ++ modules/adagioAnalyticsAdapter.md | 17 ++ modules/adagioBidAdapter.js | 178 ++++++++++++++ modules/adagioBidAdapter.md | 60 +++++ test/spec/modules/adagioBidAdapter_spec.js | 273 +++++++++++++++++++++ 5 files changed, 551 insertions(+) create mode 100644 modules/adagioAnalyticsAdapter.js create mode 100644 modules/adagioAnalyticsAdapter.md create mode 100644 modules/adagioBidAdapter.js create mode 100644 modules/adagioBidAdapter.md create mode 100644 test/spec/modules/adagioBidAdapter_spec.js diff --git a/modules/adagioAnalyticsAdapter.js b/modules/adagioAnalyticsAdapter.js new file mode 100644 index 00000000000..4198e4d1561 --- /dev/null +++ b/modules/adagioAnalyticsAdapter.js @@ -0,0 +1,23 @@ +/** + * Analytics Adapter for Adagio + */ + +import adapter from 'src/AnalyticsAdapter'; +import adaptermanager from 'src/adaptermanager'; + +// This config makes Prebid.js call this function on each event: +// `window['AdagioPrebidAnalytics']('on', eventType, args)` +// If it is missing, then Prebid.js will immediately log an error, +// instead of queueing the events until the function appears. +var adagioAdapter = adapter({ + global: 'AdagioPrebidAnalytics', + handler: 'on', + analyticsType: 'bundle' +}); + +adaptermanager.registerAnalyticsAdapter({ + adapter: adagioAdapter, + code: 'adagio' +}); + +export default adagioAdapter; diff --git a/modules/adagioAnalyticsAdapter.md b/modules/adagioAnalyticsAdapter.md new file mode 100644 index 00000000000..5734bc85b2a --- /dev/null +++ b/modules/adagioAnalyticsAdapter.md @@ -0,0 +1,17 @@ +# Overview + +Module Name: Adagio Analytics Adapter +Module Type: Adagio Adapter +Maintainer: dev@adagio.io + +# Description + +Analytics adapter for Adagio + +# Test Parameters + +``` +{ + provider: 'adagio' +} +``` diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js new file mode 100644 index 00000000000..3a26593799d --- /dev/null +++ b/modules/adagioBidAdapter.js @@ -0,0 +1,178 @@ +import find from 'core-js/library/fn/array/find'; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'adagio'; +const VERSION = '1.0.0'; +const ENDPOINT = 'https://mp.4dex.io/prebid'; +const SUPPORTED_MEDIA_TYPES = ['banner']; + +/** + * Based on https://github.com/ua-parser/uap-cpp/blob/master/UaParser.cpp#L331, with the following updates: + * - replaced `mobile` by `mobi` in the table regexp, so Opera Mobile on phones is not detected as a tablet. + */ +function _getDeviceType() { + let ua = navigator.userAgent; + + // Tablets must be checked before phones. + if ((/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i).test(ua)) { + return 5; // "tablet" + } + if ((/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/).test(ua)) { + return 4; // "phone" + } + // Consider that all other devices are personal computers + return 2; +}; + +function _getDevice() { + const language = navigator.language ? 'language' : 'userLanguage'; + return { + userAgent: navigator.userAgent, + language: navigator[language], + deviceType: _getDeviceType(), + dnt: utils.getDNT() ? 1 : 0, + geo: {}, + js: 1 + }; +}; + +function _getSite() { + const topLocation = utils.getTopWindowLocation(); + return { + domain: topLocation.hostname, + page: topLocation.href, + referrer: utils.getTopWindowReferrer() + }; +}; + +function _getPageviewId() { + return (!window.top.ADAGIO || !window.top.ADAGIO.pageviewId) ? '_' : window.top.ADAGIO.pageviewId; +}; + +function _getFeatures(bidRequest) { + if (!window.top._ADAGIO || !window.top._ADAGIO.features) { + return {}; + } + + const rawFeatures = window.top._ADAGIO.features.getFeatures( + document.getElementById(bidRequest.adUnitCode), + function(features) { + return { + site_id: bidRequest.params.siteId, + placement: bidRequest.params.placementId, + pagetype: bidRequest.params.pagetypeId, + categories: bidRequest.params.categories + }; + } + ); + return rawFeatures; +} + +function _getGdprConsent(bidderRequest) { + const consent = {}; + if (utils.deepAccess(bidderRequest, 'gdprConsent')) { + if (bidderRequest.gdprConsent.consentString !== undefined) { + consent.consentString = bidderRequest.gdprConsent.consentString; + } + if (bidderRequest.gdprConsent.gdprApplies !== undefined) { + consent.consentRequired = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; + } + if (bidderRequest.gdprConsent.allowAuctionWithoutConsent !== undefined) { + consent.allowAuctionWithoutConsent = bidderRequest.gdprConsent.allowAuctionWithoutConsent ? 1 : 0; + } + } + return consent; +} + +export const spec = { + code: BIDDER_CODE, + + supportedMediaType: SUPPORTED_MEDIA_TYPES, + + isBidRequestValid: function(bid) { + return !!(bid.params.siteId && bid.params.placementId); + }, + + buildRequests: function(validBidRequests, bidderRequest) { + const secure = (location.protocol === 'https:') ? 1 : 0; + const device = _getDevice(); + const site = _getSite(); + const pageviewId = _getPageviewId(); + const gdprConsent = _getGdprConsent(bidderRequest); + const adUnits = utils._map(validBidRequests, (bidRequest) => { + bidRequest.params.features = _getFeatures(bidRequest); + const categories = bidRequest.params.categories; + if (typeof categories !== 'undefined' && !Array.isArray(categories)) { + bidRequest.params.categories = [categories]; + } + return bidRequest; + }); + + // Regroug ad units by siteId + const groupedAdUnits = adUnits.reduce((groupedAdUnits, adUnit) => { + (groupedAdUnits[adUnit.params.siteId] = groupedAdUnits[adUnit.params.siteId] || []).push(adUnit); + return groupedAdUnits; + }, {}); + + // Build one request per siteId + const requests = utils._map(Object.keys(groupedAdUnits), (siteId) => { + return { + method: 'POST', + url: ENDPOINT, + data: { + id: utils.generateUUID(), + secure: secure, + device: device, + site: site, + siteId: siteId, + pageviewId: pageviewId, + adUnits: groupedAdUnits[siteId], + gdpr: gdprConsent, + adapterVersion: VERSION + }, + options: { + contentType: 'application/json' + } + } + }); + + return requests; + }, + + interpretResponse: function(serverResponse, bidRequest) { + let bidResponses = []; + try { + const response = serverResponse.body; + if (response) { + response.bids.forEach(bidObj => { + const bidReq = (find(bidRequest.data.adUnits, bid => bid.bidId === bidObj.requestId)); + if (bidReq) { + bidObj.placementId = bidReq.params.placementId; + bidObj.pagetypeId = bidReq.params.pagetypeId; + bidObj.categories = (bidReq.params.features && bidReq.params.features.categories) ? bidReq.params.features.categories : []; + } + bidResponses.push(bidObj); + }); + } + } catch (err) { + utils.logError(err); + } + return bidResponses; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + if (!serverResponses.length || serverResponses[0].body === '' || !serverResponses[0].body.userSyncs) { + return false; + } + const syncs = serverResponses[0].body.userSyncs.map((sync) => { + return { + type: sync.t === 'p' ? 'image' : 'iframe', + url: sync.u + } + }) + return syncs; + } +} + +registerBidder(spec); diff --git a/modules/adagioBidAdapter.md b/modules/adagioBidAdapter.md new file mode 100644 index 00000000000..ff33b035e5f --- /dev/null +++ b/modules/adagioBidAdapter.md @@ -0,0 +1,60 @@ +# Overview + +Module Name: Adagio Bid Adapter +Module Type: Adagio Adapter +Maintainer: dev@adagio.io + +## Description + +Connects to Adagio demand source to fetch bids. + +## Test Parameters + +```javascript + var adUnits = [ + { + code: 'ad-unit_code', + sizes: [[300, 250], [300, 600]], + bids: [ + { + bidder: 'adagio', // Required + params: { + siteId: '0', // Required - Site ID from Adagio. + placementId: '4', // Required - Placement ID from Adagio. Refers to the placement of an ad unit in a page. + pagetypeId: '343', // Required - Page type ID from Adagio. + categories: ['IAB12', 'IAB12-2'], // IAB categories of the page. + } + } + ] + } + ]; + + pbjs.addAdUnits(adUnits); + + pbjs.bidderSettings = { + adagio: { + alwaysUseBid: true, + adserverTargeting: [ + { + key: "placement", + val: function (bidResponse) { + return bidResponse.placementId; + } + }, + { + key: "pagetype", + val: function (bidResponse) { + return bidResponse.pagetypeId; + } + }, + { + key: "categories", + val: function (bidResponse) { + return bidResponse.categories.join(","); + } + } + ] + } + } + +``` diff --git a/test/spec/modules/adagioBidAdapter_spec.js b/test/spec/modules/adagioBidAdapter_spec.js new file mode 100644 index 00000000000..7437b45b6c1 --- /dev/null +++ b/test/spec/modules/adagioBidAdapter_spec.js @@ -0,0 +1,273 @@ +import { expect } from 'chai'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { spec } from 'modules/adagioBidAdapter'; + +describe('adagioAdapter', () => { + const adapter = newBidder(spec); + const ENDPOINT = 'https://mp.4dex.io/prebid'; + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'adagio', + 'params': { + siteId: '123', + placementId: 4, + categories: ['IAB12', 'IAB12-2'] + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'c180kg4267tyqz', + 'bidderRequestId': '8vfscuixrovn8i', + 'auctionId': 'lel4fhp239i9km', + }; + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when site params is not passed', () => { + let bidTest = Object.assign({}, bid); + delete bidTest.params.siteId; + expect(spec.isBidRequestValid(bidTest)).to.equal(false); + }); + + it('should return false when placement params is not passed', () => { + let bidTest = Object.assign({}, bid); + delete bidTest.params.placementId; + expect(spec.isBidRequestValid(bidTest)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ + // siteId 123 + { + 'bidder': 'adagio', + 'params': { + siteId: '123', + placementId: 4, + pagetypeId: '232', + categories: ['IAB12'] + }, + 'adUnitCode': 'adunit-code1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'c180kg4267tyqz', + 'bidderRequestId': '8vfscuixrovn8i', + 'auctionId': 'lel4fhp239i9km', + }, + { + 'bidder': 'adagio', + 'params': { + siteId: '123', + placementId: 3, + pagetypeId: '232', + categories: ['IAB12'] + }, + 'adUnitCode': 'adunit-code2', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'c180kg4267tyqz', + 'bidderRequestId': '8vfscuixrovn8i', + 'auctionId': 'lel4fhp239i9km', + }, + // siteId 456 + { + 'bidder': 'adagio', + 'params': { + siteId: '456', + placementId: 4, + pagetypeId: '232', + categories: ['IAB12'] + }, + 'adUnitCode': 'adunit-code3', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'c180kg4267tyqz', + 'bidderRequestId': '8vfscuixrovn8i', + 'auctionId': 'lel4fhp239i9km', + } + ]; + + let consentString = 'theConsentString'; + let bidderRequest = { + 'bidderCode': 'adagio', + 'auctionId': '12jejebn', + 'bidderRequestId': 'hehehehbeheh', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true, + allowAuctionWithoutConsent: true + } + }; + + it('groups requests by siteId', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests).to.have.lengthOf(2); + + expect(requests[0].data.siteId).to.equal('123'); + expect(requests[0].data.adUnits).to.have.lengthOf(2); + + expect(requests[1].data.siteId).to.equal('456'); + expect(requests[1].data.adUnits).to.have.lengthOf(1); + }); + + it('sends bid request to ENDPOINT_PB via POST', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests).to.have.lengthOf(2); + const request = requests[0]; + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENDPOINT); + }); + + it('features params must be an empty object if featurejs is not loaded', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests).to.have.lengthOf(2); + const request = requests[0]; + const expected = {}; + expect(request.data.adUnits[0].params.features).to.deep.equal(expected); + }); + + it('GDPR consent is applied', () => { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests).to.have.lengthOf(2); + const request = requests[0]; + expect(request.data.gdpr).to.exist; + expect(request.data.gdpr.consentString).to.exist.and.to.equal(consentString); + expect(request.data.gdpr.consentRequired).to.exist.and.to.equal(1); + }); + + it('GDPR consent is not applied', () => { + bidderRequest.gdprConsent.gdprApplies = false; + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests).to.have.lengthOf(2); + const request = requests[0]; + expect(request.data.gdpr).to.exist; + expect(request.data.gdpr.consentString).to.exist.and.to.equal(consentString); + expect(request.data.gdpr.consentRequired).to.exist.and.to.equal(0); + }); + + it('GDPR consent is undefined', () => { + delete bidderRequest.gdprConsent.consentString; + delete bidderRequest.gdprConsent.gdprApplies; + delete bidderRequest.gdprConsent.allowAuctionWithoutConsent; + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests).to.have.lengthOf(2); + const request = requests[0]; + expect(request.data.gdpr).to.exist; + expect(request.data.gdpr).to.not.have.property('consentString'); + expect(request.data.gdpr).to.not.have.property('gdprApplies'); + expect(request.data.gdpr).to.not.have.property('allowAuctionWithoutConsent'); + }); + + it('GDPR consent bidderRequest does not have gdprConsent', () => { + delete bidderRequest.gdprConsent; + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests).to.have.lengthOf(2); + const request = requests[0]; + expect(request.data.gdpr).to.exist; + expect(request.data.gdpr).to.be.empty; + }); + }); + + describe('interpretResponse', () => { + let serverResponse = { + body: { + bids: [ + { + ad: '
', + cpm: 1, + creativeId: 'creativeId', + currency: 'EUR', + height: 250, + netRevenue: true, + requestId: 'c180kg4267tyqz', + ttl: 360, + width: 300 + } + ] + } + }; + + let bidRequest = { + 'data': { + 'adUnits': [ + { + 'bidder': 'adagio', + 'params': { + siteId: '666', + placementId: 4, + pagetypeId: '232', + categories: ['IAB12'] + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'c180kg4267tyqz', + 'bidderRequestId': '8vfscuixrovn8i', + 'auctionId': 'lel4fhp239i9km', + } + ] + } + }; + + it('should get correct bid response', () => { + let expectedResponse = [{ + ad: '
', + cpm: 1, + creativeId: 'creativeId', + currency: 'EUR', + height: 250, + netRevenue: true, + requestId: 'c180kg4267tyqz', + ttl: 360, + width: 300, + categories: [], + pagetypeId: '232', + placementId: 4, + }]; + expect(spec.interpretResponse(serverResponse, bidRequest)).to.be.an('array'); + expect(spec.interpretResponse(serverResponse, bidRequest)).to.deep.equal(expectedResponse); + }); + }); + + describe('getUserSyncs', () => { + const syncOptions = { + 'iframeEnabled': 'true' + } + const serverResponses = [ + { + body: { + userSyncs: [ + { + t: 'i', + u: 'https://test.url.com/setuid' + }, + { + t: 'p', + u: 'https://test.url.com/setuid' + } + ] + } + } + ]; + + const emptyServerResponses = [ + { + body: '' + } + ]; + + it('should handle correctly user syncs', () => { + let result = spec.getUserSyncs(syncOptions, serverResponses); + let emptyResult = spec.getUserSyncs(syncOptions, emptyServerResponses); + expect(result[0].type).to.equal('iframe'); + expect(result[0].url).contain('setuid'); + expect(result[1].type).to.equal('image'); + expect(emptyResult).to.equal(false); + }); + }); +}); From 298e41a2c08ba48d3d8bb9ce6c10b3f7bc19782a Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 2 Oct 2018 11:41:23 -0600 Subject: [PATCH 0731/1594] Make size mapping mediaType aware (#3134) * make sizeMapping mediaTypes aware * no sizeMapping if the only mediaType is not banner * better logging for size mapping and no auction when no bids * fix size mapping tests to ignore filter results (which are only for logging) --- src/adaptermanager.js | 55 ++++++++------ src/auction.js | 94 ++++++++++++----------- src/sizeMapping.js | 71 ++++++++++++----- test/spec/sizeMapping_spec.js | 138 ++++++++++++++++++++-------------- 4 files changed, 217 insertions(+), 141 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 9b2abe79f01..32cbc55cd8f 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -49,13 +49,22 @@ function getLabels(bidOrAdUnit, activeLabels) { function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { return adUnits.reduce((result, adUnit) => { - let bannerSizes = utils.deepAccess(adUnit, 'mediaTypes.banner.sizes'); - - let {active, sizes: filteredAdUnitSizes} = resolveStatus( + let { + active, + mediaTypes: filteredMediaTypes, + filterResults + } = resolveStatus( getLabels(adUnit, labels), - bannerSizes || adUnit.sizes + 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) => { @@ -72,29 +81,33 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { 'renderer' ])); - let {active, sizes} = resolveStatus(getLabels(bid, labels), filteredAdUnitSizes); - - if (adUnit.mediaTypes) { - if (utils.isValidMediaTypes(adUnit.mediaTypes)) { - if (bannerSizes) { - adUnit.mediaTypes.banner.sizes = sizes; - } - - bid = Object.assign({}, bid, { - mediaTypes: adUnit.mediaTypes - }); - } else { - utils.logError( - `mediaTypes is not correctly configured for adunit ${adUnit.code}` - ); - } + 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: sizes, + sizes: utils.deepAccess(mediaTypes, 'banner.sizes') || [], bidId: bid.bid_id || utils.getUniqueIdentifierStr(), bidderRequestId, auctionId, diff --git a/src/auction.js b/src/auction.js index a77708486f2..83768ef8724 100644 --- a/src/auction.js +++ b/src/auction.js @@ -175,54 +175,58 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) let requests = {}; - let call = { - bidRequests, - run: () => { - startAuctionTimer(); - - _auctionStatus = AUCTION_IN_PROGRESS; - - const auctionInit = { - timestamp: _auctionStart, - auctionId: _auctionId, - timeout: _timeout - }; - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); - - let callbacks = auctionCallbacks(auctionDone, this); - let boundObj = { - auctionAddBidResponse: callbacks.addBidResponse - } - adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(boundObj), callbacks.adapterDone, { - request(source, origin) { - increment(outstandingRequests, origin); - increment(requests, source); - - if (!sourceInfo[source]) { - sourceInfo[source] = { - SRA: true, - origin - }; - } - if (requests[source] > 1) { - sourceInfo[source].SRA = false; - } - }, - done(origin) { - outstandingRequests[origin]--; - if (queuedCalls[0]) { - if (runIfOriginHasCapacity(queuedCalls[0])) { - queuedCalls.shift(); + if (bidRequests.length < 1) { + utils.logWarn('No valid bid requests returned for auction'); + } else { + let call = { + bidRequests, + run: () => { + startAuctionTimer(); + + _auctionStatus = AUCTION_IN_PROGRESS; + + const auctionInit = { + timestamp: _auctionStart, + auctionId: _auctionId, + timeout: _timeout + }; + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); + + let callbacks = auctionCallbacks(auctionDone, this); + let boundObj = { + auctionAddBidResponse: callbacks.addBidResponse + }; + adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(boundObj), callbacks.adapterDone, { + request(source, origin) { + increment(outstandingRequests, origin); + increment(requests, source); + + if (!sourceInfo[source]) { + sourceInfo[source] = { + SRA: true, + origin + }; + } + if (requests[source] > 1) { + sourceInfo[source].SRA = false; + } + }, + done(origin) { + outstandingRequests[origin]--; + if (queuedCalls[0]) { + if (runIfOriginHasCapacity(queuedCalls[0])) { + queuedCalls.shift(); + } } } - } - }, _timeout); - } - }; + }, _timeout); + } + }; - if (!runIfOriginHasCapacity(call)) { - utils.logWarn('queueing auction due to limited endpoint capacity'); - queuedCalls.push(call); + if (!runIfOriginHasCapacity(call)) { + utils.logWarn('queueing auction due to limited endpoint capacity'); + queuedCalls.push(call); + } } function runIfOriginHasCapacity(call) { diff --git a/src/sizeMapping.js b/src/sizeMapping.js index 5533c6b4efe..a8fec661bd1 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -1,5 +1,5 @@ import { config } from 'src/config'; -import { logWarn } from 'src/utils'; +import {logWarn, isPlainObject, deepAccess, deepClone} from 'src/utils'; import includes from 'core-js/library/fn/array/includes'; let sizeConfig = []; @@ -29,36 +29,67 @@ config.getConfig('sizeConfig', config => setSizeConfig(config.sizeConfig)); * @param {Array} labels Labels specified on adUnit or bidder * @param {boolean} labelAll if true, all labels must match to be enabled * @param {Array} activeLabels Labels passed in through requestBids - * @param {Array>} sizes Sizes specified on adUnit + * @param {object} mediaTypes A mediaTypes object describing the various media types (banner, video, native) + * @param {Array>} sizes Sizes specified on adUnit (deprecated) * @param {Array} configs * @returns {{labels: Array, sizes: Array>}} */ -export function resolveStatus({labels = [], labelAll = false, activeLabels = []} = {}, sizes = [], configs = sizeConfig) { +export function resolveStatus({labels = [], labelAll = false, activeLabels = []} = {}, mediaTypes, sizes, configs = sizeConfig) { let maps = evaluateSizeConfig(configs); - let filteredSizes; - if (maps.shouldFilter) { - filteredSizes = sizes.filter(size => maps.sizesSupported[size]); + if (!isPlainObject(mediaTypes)) { + mediaTypes = {}; } else { - filteredSizes = sizes; + mediaTypes = deepClone(mediaTypes); } - return { - active: filteredSizes.length > 0 && ( - labels.length === 0 || ( - (!labelAll && ( - labels.some(label => maps.labels[label]) || - labels.some(label => includes(activeLabels, label)) - )) || - (labelAll && ( - labels.reduce((result, label) => !result ? result : ( - maps.labels[label] || includes(activeLabels, label) - ), true) - )) + // add support for deprecated adUnit.sizes by creating correct banner mediaTypes if they don't already exist + if (sizes) { + if (!mediaTypes.banner) { + mediaTypes.banner = { + sizes + } + } else if (!mediaTypes.banner.sizes) { + mediaTypes.banner.sizes = sizes; + } + } + + let oldSizes = deepAccess(mediaTypes, 'banner.sizes'); + if (maps.shouldFilter && oldSizes) { + mediaTypes.banner.sizes = oldSizes.filter(size => maps.sizesSupported[size]); + } + + let allMediaTypes = Object.keys(mediaTypes); + + let results = { + active: ( + allMediaTypes.length > 1 || (allMediaTypes.length === 1 && allMediaTypes[0] !== 'banner') + ) || ( + allMediaTypes[0] === 'banner' && deepAccess(mediaTypes, 'banner.sizes.length') > 0 && ( + labels.length === 0 || ( + (!labelAll && ( + labels.some(label => maps.labels[label]) || + labels.some(label => includes(activeLabels, label)) + )) || + (labelAll && ( + labels.reduce((result, label) => !result ? result : ( + maps.labels[label] || includes(activeLabels, label) + ), true) + )) + ) ) ), - sizes: filteredSizes + mediaTypes }; + + if (oldSizes && oldSizes.length !== mediaTypes.banner.sizes.length) { + results.filterResults = { + before: oldSizes, + after: mediaTypes.banner.sizes + } + } + + return results; } function evaluateSizeConfig(configs) { diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index 15213958296..ac51d405e36 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -6,7 +6,11 @@ let utils = require('src/utils'); let deepClone = utils.deepClone; describe('sizeMapping', function () { - var testSizes = [[970, 90], [728, 90], [300, 250], [300, 100], [80, 80]]; + var testSizes = { + banner: { + sizes: [[970, 90], [728, 90], [300, 250], [300, 100], [80, 80]] + } + }; var sizeConfig = [{ 'mediaQuery': '(min-width: 1200px)', @@ -78,19 +82,34 @@ describe('sizeMapping', function () { sandbox.stub(utils, 'logWarn'); - resolveStatus(undefined, testSizes, errorConfig); + resolveStatus(undefined, testSizes, undefined, errorConfig); expect(utils.logWarn.firstCall.args[0]).to.match(/missing.+?mediaQuery/); }); + it('should allow deprecated adUnit.sizes', function() { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, undefined, testSizes.banner.sizes, sizeConfig); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[970, 90], [728, 90], [300, 250]] + } + }); + }); + it('when one mediaQuery block matches, it should filter the adUnit.sizes passed in', function () { matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - let status = resolveStatus(undefined, testSizes, sizeConfig); + let status = resolveStatus(undefined, testSizes, undefined, sizeConfig); - expect(status).to.deep.equal({ - active: true, - sizes: [[970, 90], [728, 90], [300, 250]] - }) + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[970, 90], [728, 90], [300, 250]] + } + }); }); it('when multiple mediaQuery block matches, it should filter a union of the matched sizesSupported', function () { @@ -99,41 +118,60 @@ describe('sizeMapping', function () { '(min-width: 768px) and (max-width: 1199px)' ], str) ? {matches: true} : {matches: false}; - let status = resolveStatus(undefined, testSizes, sizeConfig); - expect(status).to.deep.equal({ - active: true, - sizes: [[970, 90], [728, 90], [300, 250], [300, 100]] - }) + let status = resolveStatus(undefined, testSizes, undefined, sizeConfig); + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[970, 90], [728, 90], [300, 250], [300, 100]] + } + }); }); it('if no mediaQueries match, it should allow all sizes specified', function () { matchMediaOverride = () => ({matches: false}); - let status = resolveStatus(undefined, testSizes, sizeConfig); - expect(status).to.deep.equal({ - active: true, - sizes: testSizes - }) + let status = resolveStatus(undefined, testSizes, undefined, sizeConfig); + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal(testSizes); }); it('if a mediaQuery matches and has sizesSupported: [], it should filter all sizes', function () { matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; - let status = resolveStatus(undefined, testSizes, sizeConfig); - expect(status).to.deep.equal({ - active: false, - sizes: [] - }) + let status = resolveStatus(undefined, testSizes, undefined, sizeConfig); + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [] + } + }); }); - it('if a mediaQuery matches and no sizesSupported specified, it should not effect adUnit.sizes', function () { + it('should filter all banner sizes but not disable adUnit if multiple mediaTypes are present', function () { + matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, Object.assign({}, testSizes, { + native: { + type: 'image' + } + }), undefined, sizeConfig); + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [] + }, + native: { + type: 'image' + } + }); + }); + + it('if a mediaQuery matches and no sizesSupported specified, it should not affect adUnit.sizes', function () { matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - let status = resolveStatus(undefined, testSizes, sizeConfigWithLabels); - expect(status).to.deep.equal({ - active: true, - sizes: testSizes - }) + let status = resolveStatus(undefined, testSizes, undefined, sizeConfigWithLabels); + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal(testSizes); }); }); @@ -143,21 +181,19 @@ describe('sizeMapping', function () { let status = resolveStatus({ labels: ['desktop'] - }, testSizes, sizeConfigWithLabels); + }, testSizes, undefined, sizeConfigWithLabels); expect(status).to.deep.equal({ active: true, - sizes: testSizes + mediaTypes: testSizes }); status = resolveStatus({ labels: ['tablet'] - }, testSizes, sizeConfigWithLabels); + }, testSizes, undefined, sizeConfigWithLabels); - expect(status).to.deep.equal({ - active: false, - sizes: testSizes - }); + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal(testSizes); }); it('should active/deactivate adUnits/bidders based on requestBids labels', function () { @@ -166,44 +202,36 @@ describe('sizeMapping', function () { let status = resolveStatus({ labels: ['uk-visitor'], activeLabels - }, testSizes, sizeConfigWithLabels); + }, testSizes, undefined, sizeConfigWithLabels); - expect(status).to.deep.equal({ - active: false, - sizes: testSizes - }); + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal(testSizes); status = resolveStatus({ labels: ['us-visitor'], activeLabels - }, testSizes, sizeConfigWithLabels); + }, testSizes, undefined, sizeConfigWithLabels); - expect(status).to.deep.equal({ - active: true, - sizes: testSizes - }); + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal(testSizes); status = resolveStatus({ labels: ['us-visitor', 'tablet'], labelAll: true, activeLabels - }, testSizes, sizeConfigWithLabels); + }, testSizes, undefined, sizeConfigWithLabels); - expect(status).to.deep.equal({ - active: false, - sizes: testSizes - }); + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal(testSizes); status = resolveStatus({ labels: ['us-visitor', 'desktop'], labelAll: true, activeLabels - }, testSizes, sizeConfigWithLabels); + }, testSizes, undefined, sizeConfigWithLabels); - expect(status).to.deep.equal({ - active: true, - sizes: testSizes - }); + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal(testSizes); }); }); }); From 4e8955e5e7425859a1b00ddaf61cfd948677e572 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 2 Oct 2018 13:16:10 -0700 Subject: [PATCH 0732/1594] Making targeting keys configurable (#3140) * moved NATIVE_KEYS to constants * Changed TARGETING_KEYS from array to an array - Now you can change key names - Made changes in code at auction.js and targeting.js to handle the TARGETING_KEYS object than array * fixed aauctionmanager test cases for dynamic targeting key names * fixed native test cases for dynamic targeting key names * fixed test cases of targeting for dynamic targeting key names * in-dev changes * replace old keys with new keys * fixed a typo * fixed a unit case in utils * updated convertTargetingsFromOldToNew in fixtures this will now replace partner specific keys as well as per config * removed a log * keep test case as it was * improved convertTargetingsFromOldToNew in fixtures * Capitalized key names in TARGETING_KEYS object; not values in object * using computed properties * using computed properties * fixed eslint suggestion * fixed eslint suggestions * keeping unit tests more compliant with Mocha --- src/auction.js | 16 +-- src/constants.json | 27 ++-- src/native.js | 18 +-- src/targeting.js | 10 +- test/fixtures/fixtures.js | 175 +++++++++++++++----------- test/spec/auctionmanager_spec.js | 87 +++++++------ test/spec/native_spec.js | 7 +- test/spec/unit/core/targeting_spec.js | 30 ++--- test/spec/unit/pbjs_api_spec.js | 127 ++++++++++--------- test/spec/utils_spec.js | 3 +- 10 files changed, 267 insertions(+), 233 deletions(-) diff --git a/src/auction.js b/src/auction.js index 83768ef8724..b9f3574ed31 100644 --- a/src/auction.js +++ b/src/auction.js @@ -460,17 +460,17 @@ export function getStandardBidderSettings(mediaType) { 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] = [ { - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function (bidResponse) { return bidResponse.bidderCode; } }, { - key: 'hb_adid', + key: CONSTANTS.TARGETING_KEYS.AD_ID, val: function (bidResponse) { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function (bidResponse) { if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { return bidResponse.pbAg; @@ -487,24 +487,24 @@ export function getStandardBidderSettings(mediaType) { } } }, { - key: 'hb_size', + key: CONSTANTS.TARGETING_KEYS.SIZE, val: function (bidResponse) { return bidResponse.size; } }, { - key: 'hb_deal', + key: CONSTANTS.TARGETING_KEYS.DEAL, val: function (bidResponse) { return bidResponse.dealId; } }, { - key: 'hb_source', + key: CONSTANTS.TARGETING_KEYS.SOURCE, val: function (bidResponse) { return bidResponse.source; } }, { - key: 'hb_format', + key: CONSTANTS.TARGETING_KEYS.FORMAT, val: function (bidResponse) { return bidResponse.mediaType; } @@ -565,7 +565,7 @@ function setKeys(keyValues, bidderSettings, custBidObj) { if ( ((typeof bidderSettings.suppressEmptyKeys !== 'undefined' && bidderSettings.suppressEmptyKeys === true) || - key === 'hb_deal') && // hb_deal is suppressed automatically if not set + key === CONSTANTS.TARGETING_KEYS.DEAL) && // hb_deal is suppressed automatically if not set ( utils.isEmptyStr(value) || value === null || diff --git a/src/constants.json b/src/constants.json index 3bbad70585a..9ec51e4047b 100644 --- a/src/constants.json +++ b/src/constants.json @@ -55,15 +55,24 @@ "DENSE": "dense", "CUSTOM": "custom" }, - "TARGETING_KEYS": [ - "hb_bidder", - "hb_adid", - "hb_pb", - "hb_size", - "hb_deal", - "hb_source", - "hb_format" - ], + "TARGETING_KEYS": { + "BIDDER": "hb_bidder", + "AD_ID": "hb_adid", + "PRICE_BUCKET": "hb_pb", + "SIZE": "hb_size", + "DEAL": "hb_deal", + "SOURCE": "hb_source", + "FORMAT": "hb_format" + }, + "NATIVE_KEYS": { + "title": "hb_native_title", + "body": "hb_native_body", + "sponsoredBy": "hb_native_brand", + "image": "hb_native_image", + "icon": "hb_native_icon", + "clickUrl": "hb_native_linkurl", + "cta": "hb_native_cta" + }, "S2S" : { "SRC" : "s2s", "DEFAULT_ENDPOINT" : "https://prebid.adnxs.com/pbs/v1/openrtb2/auction", diff --git a/src/native.js b/src/native.js index 3d2ec2fe688..b4d2d959b70 100644 --- a/src/native.js +++ b/src/native.js @@ -1,20 +1,12 @@ import { deepAccess, getBidRequest, logError, triggerPixel, insertHtmlIntoIframe } from './utils'; import includes from 'core-js/library/fn/array/includes'; -export const nativeAdapters = []; +const CONSTANTS = require('./constants.json'); -export const NATIVE_KEYS = { - title: 'hb_native_title', - body: 'hb_native_body', - sponsoredBy: 'hb_native_brand', - image: 'hb_native_image', - icon: 'hb_native_icon', - clickUrl: 'hb_native_linkurl', - cta: 'hb_native_cta', -}; +export const nativeAdapters = []; -export const NATIVE_TARGETING_KEYS = Object.keys(NATIVE_KEYS).map( - key => NATIVE_KEYS[key] +export const NATIVE_TARGETING_KEYS = Object.keys(CONSTANTS.NATIVE_KEYS).map( + key => CONSTANTS.NATIVE_KEYS[key] ); const IMAGE = { @@ -163,7 +155,7 @@ export function getNativeTargeting(bid) { let keyValues = {}; Object.keys(bid['native']).forEach(asset => { - const key = NATIVE_KEYS[asset]; + const key = CONSTANTS.NATIVE_KEYS[asset]; let value = bid['native'][asset]; // native image-type assets can be a string or an object with a url prop diff --git a/src/targeting.js b/src/targeting.js index 4bd3adbd9fc..8cb567001d5 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -15,6 +15,10 @@ export const RENDERED = 'rendered'; const MAX_DFP_KEYLENGTH = 20; const TTL_BUFFER = 1000; +export const TARGETING_KEYS = Object.keys(CONSTANTS.TARGETING_KEYS).map( + key => CONSTANTS.TARGETING_KEYS[key] +); + // return unexpired bids export const isBidNotExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 + TTL_BUFFER) > timestamp(); @@ -262,7 +266,7 @@ export function newTargeting(auctionManager) { .reduce((acc, key) => { const targetingValue = [winner.adserverTargeting[key]]; const targeting = { [key.substring(0, MAX_DFP_KEYLENGTH)]: targetingValue }; - if (key === 'hb_deal') { + if (key === CONSTANTS.TARGETING_KEYS.DEAL) { const bidderCodeTargetingKey = `${key}_${winner.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH); const bidderCodeTargeting = { [bidderCodeTargetingKey]: targetingValue }; return [...acc, targeting, bidderCodeTargeting]; @@ -278,7 +282,7 @@ export function newTargeting(auctionManager) { function getStandardKeys() { return auctionManager.getStandardBidderAdServerTargeting() // in case using a custom standard key set .map(targeting => targeting.key) - .concat(CONSTANTS.TARGETING_KEYS).filter(uniques); // standard keys defined in the library. + .concat(TARGETING_KEYS).filter(uniques); // standard keys defined in the library. } /** @@ -360,7 +364,7 @@ export function newTargeting(auctionManager) { * @return {targetingArray} all non-winning bids targeting */ function getBidLandscapeTargeting(adUnitCodes, bidsReceived) { - const standardKeys = CONSTANTS.TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); + const standardKeys = TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); const bids = getHighestCpmBidsFromBidPool(bidsReceived, getHighestCpm); diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index 75d998d4a09..816363f5eea 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -1,4 +1,33 @@ // jscs:disable +import CONSTANTS from 'src/constants.json'; +const utils = require('src/utils.js'); + +function convertTargetingsFromOldToNew(targetings) { + var mapOfOldToNew = { + 'hb_bidder': CONSTANTS.TARGETING_KEYS.BIDDER, + 'hb_adid': CONSTANTS.TARGETING_KEYS.AD_ID, + 'hb_pb': CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, + 'hb_size': CONSTANTS.TARGETING_KEYS.SIZE, + 'hb_deal': CONSTANTS.TARGETING_KEYS.DEAL, + 'hb_source': CONSTANTS.TARGETING_KEYS.SOURCE, + 'hb_format': CONSTANTS.TARGETING_KEYS.FORMAT + }; + var newTargetings = {}; + utils._each(targetings, function(value, currentKey) { + var replaced = false; + utils._each(mapOfOldToNew, function(newKey, oldKey) { + if (currentKey.indexOf(oldKey) === 0 && oldKey !== newKey) { + var updatedKey = currentKey.replace(oldKey, newKey); + newTargetings[updatedKey] = targetings[currentKey]; + replaced = true; + } + }); + if (!replaced) { + newTargetings[currentKey] = targetings[currentKey]; + } + }) + return newTargetings; +} export function getBidRequests() { return [ @@ -311,13 +340,13 @@ export function getBidResponses() { 'pbAg': '0.10', 'size': '0x0', 'auctionId': 123456, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'triplelift', 'hb_adid': '222bb26f9e8bd', 'hb_pb': '10.00', 'hb_size': '0x0', 'foobar': '0x0' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -343,13 +372,13 @@ export function getBidResponses() { 'size': '300x250', 'alwaysUseBid': true, 'auctionId': 123456, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'appnexus', 'hb_adid': '233bcbee889d46d', 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -375,13 +404,13 @@ export function getBidResponses() { 'size': '728x90', 'alwaysUseBid': true, 'auctionId': 123456, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'appnexus', 'hb_adid': '24bd938435ec3fc', 'hb_pb': '10.00', 'hb_size': '728x90', 'foobar': '728x90' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -406,13 +435,13 @@ export function getBidResponses() { 'pbAg': '0.50', 'size': '300x250', 'auctionId': 123456, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'pagescience', 'hb_adid': '25bedd4813632d7', 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -436,13 +465,13 @@ export function getBidResponses() { 'pbAg': '0.15', 'size': '300x250', 'auctionId': 654321, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'brightcom', 'hb_adid': '26e0795ab963896', 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -467,13 +496,13 @@ export function getBidResponses() { 'pbAg': '0.50', 'size': '300x250', 'auctionId': 654321, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'brealtime', 'hb_adid': '275bd666f5a5a5d', 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -499,13 +528,13 @@ export function getBidResponses() { 'pbAg': '5.90', 'size': '300x250', 'auctionId': 654321, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'pubmatic', 'hb_adid': '28f4039c636b6a7', 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -529,13 +558,13 @@ export function getBidResponses() { 'pbAg': '2.70', 'size': '300x600', 'auctionId': 654321, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'rubicon', 'hb_adid': '29019e2ab586a5a', 'hb_pb': '10.00', 'hb_size': '300x600', 'foobar': '300x600' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -546,26 +575,26 @@ export function getBidResponses() { export function getSlotTargeting() { return { '/19968336/header-bid-tag-0': [ - { + convertTargetingsFromOldToNew({ 'hb_bidder': [ 'appnexus' ] - }, - { + }), + convertTargetingsFromOldToNew({ 'hb_adid': [ '233bcbee889d46d' ] - }, - { + }), + convertTargetingsFromOldToNew({ 'hb_pb': [ '10.00' ] - }, - { + }), + convertTargetingsFromOldToNew({ 'hb_size': [ '300x250' ] - }, + }), { 'foobar': [ '300x250' @@ -1033,13 +1062,13 @@ export function getBidResponsesFromAPI() { 'pbAg': '0.15', 'size': '300x250', 'auctionId': 654321, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'brightcom', 'hb_adid': '26e0795ab963896', 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -1064,13 +1093,13 @@ export function getBidResponsesFromAPI() { 'pbAg': '0.50', 'size': '300x250', 'auctionId': 654321, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'brealtime', 'hb_adid': '275bd666f5a5a5d', 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -1096,13 +1125,13 @@ export function getBidResponsesFromAPI() { 'pbAg': '5.90', 'size': '300x250', 'auctionId': 654321, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'pubmatic', 'hb_adid': '28f4039c636b6a7', 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -1126,13 +1155,13 @@ export function getBidResponsesFromAPI() { 'pbAg': '2.70', 'size': '300x600', 'auctionId': 654321, - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'rubicon', 'hb_adid': '29019e2ab586a5a', 'hb_pb': '10.00', 'hb_size': '300x600', 'foobar': '300x600' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -1145,7 +1174,7 @@ export function getBidResponsesFromAPI() { // Ad server targeting when `setConfig({ enableSendAllBids: true })` is set. export function getAdServerTargeting() { return { - '/19968336/header-bid-tag-0': { + '/19968336/header-bid-tag-0': convertTargetingsFromOldToNew({ 'foobar': '0x0,300x250,300x600', 'hb_size': '300x250', 'hb_pb': '10.00', @@ -1179,8 +1208,8 @@ export function getAdServerTargeting() { 'hb_pb_rubicon': '10.00', 'hb_adid_rubicon': '29019e2ab586a5a', 'hb_bidder_rubicon': 'rubicon' - }, - '/19968336/header-bid-tag1': { + }), + '/19968336/header-bid-tag1': convertTargetingsFromOldToNew({ 'foobar': '728x90', 'hb_size': '728x90', 'hb_pb': '10.00', @@ -1190,7 +1219,7 @@ export function getAdServerTargeting() { 'hb_pb_appnexus': '10.00', 'hb_adid_appnexus': '24bd938435ec3fc', 'hb_bidder_appnexus': 'appnexus' - } + }) }; } @@ -1198,19 +1227,19 @@ export function getAdServerTargeting() { export function getTargetingKeys() { return [ [ - 'hb_bidder', + CONSTANTS.TARGETING_KEYS.BIDDER, 'appnexus' ], [ - 'hb_adid', + CONSTANTS.TARGETING_KEYS.AD_ID, '233bcbee889d46d' ], [ - 'hb_pb', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, '10.00' ], [ - 'hb_size', + CONSTANTS.TARGETING_KEYS.SIZE, '300x250' ], [ @@ -1225,19 +1254,19 @@ export function getTargetingKeys() { export function getTargetingKeysBidLandscape() { return [ [ - 'hb_bidder', + CONSTANTS.TARGETING_KEYS.BIDDER, 'appnexus' ], [ - 'hb_adid_appnexus', + CONSTANTS.TARGETING_KEYS.AD_ID + '_appnexus', '233bcbee889d46d' ], [ - 'hb_pb', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, '10.00' ], [ - 'hb_size', + CONSTANTS.TARGETING_KEYS.SIZE, '300x250' ], [ @@ -1245,111 +1274,111 @@ export function getTargetingKeysBidLandscape() { ['0x0', '300x250', '300x600'] ], [ - 'hb_bidder_triplelift', + CONSTANTS.TARGETING_KEYS.BIDDER + '_triplelift', 'triplelift' ], [ - 'hb_adid_triplelift', + CONSTANTS.TARGETING_KEYS.AD_ID + '_triplelift', '222bb26f9e8bd' ], [ - 'hb_pb_triplelift', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_triplelift', '10.00' ], [ - 'hb_size_triplelift', + CONSTANTS.TARGETING_KEYS.SIZE + '_triplelift', '0x0' ], [ - 'hb_bidder_appnexus', + CONSTANTS.TARGETING_KEYS.BIDDER + '_appnexus', 'appnexus' ], [ - 'hb_pb_appnexus', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_appnexus', '10.00' ], [ - 'hb_size_appnexus', + CONSTANTS.TARGETING_KEYS.SIZE + '_appnexus', '300x250' ], [ - 'hb_bidder_pagescienc', + CONSTANTS.TARGETING_KEYS.BIDDER + '_pagescienc', 'pagescience' ], [ - 'hb_adid_pagescience', + CONSTANTS.TARGETING_KEYS.AD_ID + '_pagescience', '25bedd4813632d7' ], [ - 'hb_pb_pagescience', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_pagescience', '10.00' ], [ - 'hb_size_pagescience', + CONSTANTS.TARGETING_KEYS.SIZE + '_pagescience', '300x250' ], [ - 'hb_bidder_brightcom', + CONSTANTS.TARGETING_KEYS.BIDDER + '_brightcom', 'brightcom' ], [ - 'hb_adid_brightcom', + CONSTANTS.TARGETING_KEYS.AD_ID + '_brightcom', '26e0795ab963896' ], [ - 'hb_pb_brightcom', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_brightcom', '10.00' ], [ - 'hb_size_brightcom', + CONSTANTS.TARGETING_KEYS.SIZE + '_brightcom', '300x250' ], [ - 'hb_bidder_brealtime', + CONSTANTS.TARGETING_KEYS.BIDDER + '_brealtime', 'brealtime' ], [ - 'hb_adid_brealtime', + CONSTANTS.TARGETING_KEYS.AD_ID + '_brealtime', '275bd666f5a5a5d' ], [ - 'hb_pb_brealtime', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_brealtime', '10.00' ], [ - 'hb_size_brealtime', + CONSTANTS.TARGETING_KEYS.SIZE + '_brealtime', '300x250' ], [ - 'hb_bidder_pubmatic', + CONSTANTS.TARGETING_KEYS.BIDDER + '_pubmatic', 'pubmatic' ], [ - 'hb_adid_pubmatic', + CONSTANTS.TARGETING_KEYS.AD_ID + '_pubmatic', '28f4039c636b6a7' ], [ - 'hb_pb_pubmatic', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_pubmatic', '10.00' ], [ - 'hb_size_pubmatic', + CONSTANTS.TARGETING_KEYS.SIZE + '_pubmatic', '300x250' ], [ - 'hb_bidder_rubicon', + CONSTANTS.TARGETING_KEYS.BIDDER + '_rubicon', 'rubicon' ], [ - 'hb_adid_rubicon', + CONSTANTS.TARGETING_KEYS.AD_ID + '_rubicon', '29019e2ab586a5a' ], [ - 'hb_pb_rubicon', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_rubicon', '10.00' ], [ - 'hb_size_rubicon', + CONSTANTS.TARGETING_KEYS.SIZE + '_rubicon', '300x600' ] ]; @@ -1426,12 +1455,12 @@ export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, ad 'adUnitCode': adUnitCode, 'bidder': bidder, 'size': '300x250', - 'adserverTargeting': { + 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': bidder, 'hb_adid': adId, 'hb_pb': cpm, 'foobar': '300x250' - }, + }), 'netRevenue': true, 'currency': 'USD', 'ttl': (!ttl) ? 300 : ttl diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index fa21050e78e..f4c6fc22cb7 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -138,14 +138,13 @@ describe('auctionmanager.js', function () { /* return the expected response for a given bid, filter by keys if given */ function getDefaultExpected(bid, keys) { - var expected = { - 'hb_bidder': bid.bidderCode, - 'hb_adid': bid.adId, - 'hb_pb': bid.pbMg, - 'hb_size': bid.getSize(), - 'hb_source': bid.source, - 'hb_format': bid.mediaType, - }; + var expected = {}; + expected[ CONSTANTS.TARGETING_KEYS.BIDDER ] = bid.bidderCode; + expected[ CONSTANTS.TARGETING_KEYS.AD_ID ] = bid.adId; + expected[ CONSTANTS.TARGETING_KEYS.PRICE_BUCKET ] = bid.pbMg; + expected[ CONSTANTS.TARGETING_KEYS.SIZE ] = bid.getSize(); + expected[ CONSTANTS.TARGETING_KEYS.SOURCE ] = bid.source; + expected[ CONSTANTS.TARGETING_KEYS.FORMAT ] = bid.mediaType; if (!keys) { return expected; @@ -175,35 +174,35 @@ describe('auctionmanager.js', function () { standard: { adserverTargeting: [ { - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function (bidResponse) { return bidResponse.bidderCode; } }, { - key: 'hb_adid', + key: CONSTANTS.TARGETING_KEYS.AD_ID, val: function (bidResponse) { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function (bidResponse) { // change default here return bidResponse.pbHg; } }, { - key: 'hb_size', + key: CONSTANTS.TARGETING_KEYS.SIZE, val: function (bidResponse) { return bidResponse.size; } }, { - key: 'hb_source', + key: CONSTANTS.TARGETING_KEYS.SOURCE, val: function (bidResponse) { return bidResponse.source; } }, { - key: 'hb_format', + key: CONSTANTS.TARGETING_KEYS.FORMAT, val: function (bidResponse) { return bidResponse.mediaType; } @@ -214,7 +213,7 @@ describe('auctionmanager.js', function () { }; var expected = getDefaultExpected(bid); - expected.hb_pb = bid.pbHg; + expected[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] = bid.pbHg; var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); @@ -226,23 +225,23 @@ describe('auctionmanager.js', function () { appnexus: { adserverTargeting: [ { - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function (bidResponse) { return bidResponse.bidderCode; } }, { - key: 'hb_adid', + key: CONSTANTS.TARGETING_KEYS.AD_ID, val: function (bidResponse) { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function (bidResponse) { // change default here return bidResponse.pbHg; } }, { - key: 'hb_size', + key: CONSTANTS.TARGETING_KEYS.SIZE, val: function (bidResponse) { return bidResponse.size; } @@ -253,7 +252,7 @@ describe('auctionmanager.js', function () { }; var expected = getDefaultExpected(bid); - expected.hb_pb = bid.pbHg; + expected[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] = bid.pbHg; var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); @@ -265,23 +264,23 @@ describe('auctionmanager.js', function () { nonExistentBidder: { adserverTargeting: [ { - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function (bidResponse) { return bidResponse.bidderCode; } }, { - key: 'hb_adid', + key: CONSTANTS.TARGETING_KEYS.AD_ID, val: function (bidResponse) { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function (bidResponse) { // change default here return bidResponse.pbHg; } }, { - key: 'hb_size', + key: CONSTANTS.TARGETING_KEYS.SIZE, val: function (bidResponse) { return bidResponse.size; } @@ -310,17 +309,17 @@ describe('auctionmanager.js', function () { }, adserverTargeting: [ { - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function (bidResponse) { return bidResponse.bidderCode; } }, { - key: 'hb_adid', + key: CONSTANTS.TARGETING_KEYS.AD_ID, val: function (bidResponse) { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function (bidResponse) { // change default here return 10.00; @@ -330,8 +329,8 @@ describe('auctionmanager.js', function () { } }; - var expected = getDefaultExpected(bid, ['hb_bidder', 'hb_adid']); - expected.hb_pb = 10.0; + var expected = getDefaultExpected(bid, [CONSTANTS.TARGETING_KEYS.BIDDER, CONSTANTS.TARGETING_KEYS.AD_ID]); + expected[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] = 10.0; var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); @@ -367,17 +366,17 @@ describe('auctionmanager.js', function () { }, adserverTargeting: [ { - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function (bidResponse) { return bidResponse.bidderCode; } }, { - key: 'hb_adid', + key: CONSTANTS.TARGETING_KEYS.AD_ID, val: function (bidResponse) { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function (bidResponse) { // change default here return 15.00; @@ -388,24 +387,24 @@ describe('auctionmanager.js', function () { standard: { adserverTargeting: [ { - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function (bidResponse) { return bidResponse.bidderCode; } }, { - key: 'hb_adid', + key: CONSTANTS.TARGETING_KEYS.AD_ID, val: function (bidResponse) { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function (bidResponse) { // change default here return 10.00; }, }, { - key: 'hb_size', + key: CONSTANTS.TARGETING_KEYS.SIZE, val: function (bidResponse) { return bidResponse.size; } @@ -414,8 +413,8 @@ describe('auctionmanager.js', function () { } }; - var expected = getDefaultExpected(bid, ['hb_bidder', 'hb_adid', 'hb_size']); - expected.hb_pb = 15.0; + var expected = getDefaultExpected(bid, [CONSTANTS.TARGETING_KEYS.BIDDER, CONSTANTS.TARGETING_KEYS.AD_ID, CONSTANTS.TARGETING_KEYS.SIZE]); + expected[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] = 15.0; var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); @@ -428,17 +427,17 @@ describe('auctionmanager.js', function () { sendStandardTargeting: false, adserverTargeting: [ { - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function (bidResponse) { return bidResponse.bidderCode; } }, { - key: 'hb_adid', + key: CONSTANTS.TARGETING_KEYS.AD_ID, val: function (bidResponse) { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function (bidResponse) { return bidResponse.pbHg; } @@ -447,7 +446,7 @@ describe('auctionmanager.js', function () { } }; var expected = getDefaultExpected(bid); - expected.hb_pb = 5.57; + expected[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] = 5.57; var response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); @@ -608,7 +607,7 @@ describe('auctionmanager.js', function () { auction.callBids(); let registeredBid = auction.getBidsReceived().pop(); - assert.equal(registeredBid.adserverTargeting[`hb_deal`], 'test deal', 'dealId placed in adserverTargeting'); + assert.equal(registeredBid.adserverTargeting[CONSTANTS.TARGETING_KEYS.DEAL], 'test deal', 'dealId placed in adserverTargeting'); }); it('should pass through default adserverTargeting sent from adapter', function () { @@ -617,7 +616,7 @@ describe('auctionmanager.js', function () { auction.callBids(); let registeredBid = auction.getBidsReceived().pop(); - assert.equal(registeredBid.adserverTargeting.hb_bidder, BIDDER_CODE); + assert.equal(registeredBid.adserverTargeting[CONSTANTS.TARGETING_KEYS.BIDDER], BIDDER_CODE); assert.equal(registeredBid.adserverTargeting.extra, 'stuff'); }); diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index dc70592877e..91b96cac281 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -1,5 +1,6 @@ import { expect } from 'chai'; import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid } from 'src/native'; +import CONSTANTS from 'src/constants.json'; const utils = require('src/utils'); const bid = { @@ -31,9 +32,9 @@ describe('native.js', function () { it('gets native targeting keys', function () { const targeting = getNativeTargeting(bid); - expect(targeting.hb_native_title).to.equal(bid.native.title); - expect(targeting.hb_native_body).to.equal(bid.native.body); - expect(targeting.hb_native_linkurl).to.equal(bid.native.clickUrl); + expect(targeting[CONSTANTS.NATIVE_KEYS.title]).to.equal(bid.native.title); + expect(targeting[CONSTANTS.NATIVE_KEYS.body]).to.equal(bid.native.body); + expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal(bid.native.clickUrl); }); it('fires impression trackers', function () { diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index a72992e099d..9910645be09 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -27,11 +27,11 @@ const bid1 = { 'bidder': 'rubicon', 'size': '300x250', 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '148018fe5e', - 'hb_pb': '0.53', - 'hb_deal': '1234', - 'foobar': '300x250' + 'foobar': '300x250', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'rubicon', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '148018fe5e', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '0.53', + [CONSTANTS.TARGETING_KEYS.DEAL]: '1234' }, 'netRevenue': true, 'currency': 'USD', @@ -58,10 +58,10 @@ const bid2 = { 'bidder': 'rubicon', 'size': '300x250', 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '5454545', - 'hb_pb': '0.25', - 'foobar': '300x250' + 'foobar': '300x250', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'rubicon', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '5454545', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '0.25' }, 'netRevenue': true, 'currency': 'USD', @@ -88,10 +88,10 @@ const bid3 = { 'bidder': 'rubicon', 'size': '300x600', 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '48747745', - 'hb_pb': '0.75', - 'foobar': '300x600' + 'foobar': '300x600', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'rubicon', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '48747745', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '0.75' }, 'netRevenue': true, 'currency': 'USD', @@ -140,12 +140,12 @@ describe('targeting tests', function () { // we should only get the targeting data for the one requested adunit expect(Object.keys(targeting).length).to.equal(1); - let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf('hb_pb_') != -1); + let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf(CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_') != -1) // we shouldn't get more than 1 key for hb_pb_${bidder} expect(sendAllBidCpm.length).to.equal(1); // expect the winning CPM to be equal to the sendAllBidCPM - expect(targeting['/123456/header-bid-tag-0']['hb_pb_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0']['hb_pb']); + expect(targeting['/123456/header-bid-tag-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]); }); }); // end getAllTargeting tests diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 41e40100011..96f02e7f8f2 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -166,7 +166,7 @@ describe('Unit: Prebid Module', function () { it('should return targeting info as a string', function () { const adUnitCode = config.adUnitCodes[0]; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - var expected = 'foobar=0x0%2C300x250%2C300x600&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; + var expected = 'foobar=0x0%2C300x250%2C300x600&' + CONSTANTS.TARGETING_KEYS.SIZE + '=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '=233bcbee889d46d&' + CONSTANTS.TARGETING_KEYS.BIDDER + '=appnexus&' + CONSTANTS.TARGETING_KEYS.SIZE + '_triplelift=0x0&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_triplelift=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_triplelift=222bb26f9e8bd&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_triplelift=triplelift&' + CONSTANTS.TARGETING_KEYS.SIZE + '_appnexus=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_appnexus=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_appnexus=233bcbee889d46d&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_appnexus=appnexus&' + CONSTANTS.TARGETING_KEYS.SIZE + '_pagescience=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_pagescience=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_pagescience=25bedd4813632d7&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_pagescienc=pagescience&' + CONSTANTS.TARGETING_KEYS.SIZE + '_brightcom=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_brightcom=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_brightcom=26e0795ab963896&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_brightcom=brightcom&' + CONSTANTS.TARGETING_KEYS.SIZE + '_brealtime=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_brealtime=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_brealtime=275bd666f5a5a5d&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_brealtime=brealtime&' + CONSTANTS.TARGETING_KEYS.SIZE + '_pubmatic=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_pubmatic=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_pubmatic=28f4039c636b6a7&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_pubmatic=pubmatic&' + CONSTANTS.TARGETING_KEYS.SIZE + '_rubicon=300x600&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_rubicon=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_rubicon=29019e2ab586a5a&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_rubicon=rubicon'; var result = $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCodeStr(adUnitCode); assert.equal(expected, result, 'returns expected string of ad targeting info'); }); @@ -212,17 +212,17 @@ describe('Unit: Prebid Module', function () { var expected = { '/19968336/header-bid-tag-0': { foobar: '0x0,300x250,300x600', - hb_size: '300x250', - hb_pb: '10.00', - hb_adid: '233bcbee889d46d', - hb_bidder: 'appnexus' + [CONSTANTS.TARGETING_KEYS.SIZE]: '300x250', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '233bcbee889d46d', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus' }, '/19968336/header-bid-tag1': { foobar: '728x90', - hb_size: '728x90', - hb_pb: '10.00', - hb_adid: '24bd938435ec3fc', - hb_bidder: 'appnexus' + [CONSTANTS.TARGETING_KEYS.SIZE]: '728x90', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '24bd938435ec3fc', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus' } }; assert.deepEqual(targeting, expected); @@ -259,18 +259,18 @@ describe('Unit: Prebid Module', function () { var expected = { '/19968336/header-bid-tag-0': { foobar: '300x250,300x600', - hb_size: '300x250', - hb_pb: '10.00', - hb_adid: '233bcbee889d46d', - hb_bidder: 'appnexus', - always_use_me: 'abc' + always_use_me: 'abc', + [CONSTANTS.TARGETING_KEYS.SIZE]: '300x250', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '233bcbee889d46d', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus' }, '/19968336/header-bid-tag1': { foobar: '728x90', - hb_size: '728x90', - hb_pb: '10.00', - hb_adid: '24bd938435ec3fc', - hb_bidder: 'appnexus' + [CONSTANTS.TARGETING_KEYS.SIZE]: '728x90', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '24bd938435ec3fc', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus' } }; assert.deepEqual(targeting, expected); @@ -289,7 +289,7 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.bidderSettings = { 'standard': { adserverTargeting: [{ - key: 'hb_bidder', + key: CONSTANTS.TARGETING_KEYS.BIDDER, val: function(bidResponse) { return bidResponse.bidderCode; } @@ -299,7 +299,7 @@ describe('Unit: Prebid Module', function () { return bidResponse.adId; } }, { - key: 'hb_pb', + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, val: function(bidResponse) { return bidResponse.pbMg; } @@ -317,22 +317,21 @@ describe('Unit: Prebid Module', function () { var expected = { '/19968336/header-bid-tag-0': { foobar: '300x250', - hb_size: '300x250', - hb_pb: '10.00', - hb_adid: '233bcbee889d46d', - hb_bidder: 'appnexus', - custom_ad_id: '233bcbee889d46d' + custom_ad_id: '233bcbee889d46d', + [CONSTANTS.TARGETING_KEYS.SIZE]: '300x250', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '233bcbee889d46d', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus' }, '/19968336/header-bid-tag1': { foobar: '728x90', - hb_size: '728x90', - hb_pb: '10.00', - hb_adid: '24bd938435ec3fc', - hb_bidder: 'appnexus', + [CONSTANTS.TARGETING_KEYS.SIZE]: '728x90', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '24bd938435ec3fc', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus', custom_ad_id: '24bd938435ec3fc' } }; - assert.deepEqual(targeting, expected); $$PREBID_GLOBAL$$.bidderSettings = {}; }); @@ -480,32 +479,32 @@ describe('Unit: Prebid Module', function () { ajaxStub.restore(); }); - it('should get correct hb_pb when using bid.cpm is between 0 to 5', function () { + it('should get correct ' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + ' when using bid.cpm is between 0 to 5', function() { RESPONSE.tags[0].ads[0].cpm = 2.1234; auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); - expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('2.12'); + expect(bidTargeting['div-gpt-ad-1460505748561-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]).to.equal('2.12'); }); - it('should get correct hb_pb when using bid.cpm is between 5 to 8', function () { + it('should get correct ' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + ' when using bid.cpm is between 5 to 8', function() { RESPONSE.tags[0].ads[0].cpm = 6.78; auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); - expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('6.75'); + expect(bidTargeting['div-gpt-ad-1460505748561-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]).to.equal('6.75'); }); - it('should get correct hb_pb when using bid.cpm is between 8 to 20', function () { + it('should get correct ' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + ' when using bid.cpm is between 8 to 20', function() { RESPONSE.tags[0].ads[0].cpm = 19.5234; auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); - expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('19.50'); + expect(bidTargeting['div-gpt-ad-1460505748561-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]).to.equal('19.50'); }); - it('should get correct hb_pb when using bid.cpm is between 20 to 25', function () { + it('should get correct ' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + ' when using bid.cpm is between 20 to 25', function() { RESPONSE.tags[0].ads[0].cpm = 21.5234; auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); - expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('21.00'); + expect(bidTargeting['div-gpt-ad-1460505748561-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]).to.equal('21.00'); }); }); @@ -720,7 +719,7 @@ describe('Unit: Prebid Module', function () { ajaxStub.restore(); }); - it('should get correct hb_pb with cpm between 0 - 5', function () { + it('should get correct ' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + ' with cpm between 0 - 5', function() { initTestConfig({ adUnits: [createAdUnit('div-gpt-ad-1460505748561-0')], adUnitCodes: ['div-gpt-ad-1460505748561-0'] @@ -731,10 +730,10 @@ describe('Unit: Prebid Module', function () { auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); - expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('3.25'); + expect(bidTargeting['div-gpt-ad-1460505748561-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]).to.equal('3.25'); }); - it('should get correct hb_pb with cpm between 21 - 100', function () { + it('should get correct ' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + ' with cpm between 21 - 100', function() { initTestConfig({ adUnits: [createAdUnit('div-gpt-ad-1460505748561-0')], adUnitCodes: ['div-gpt-ad-1460505748561-0'] @@ -745,7 +744,7 @@ describe('Unit: Prebid Module', function () { auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); - expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('43.00'); + expect(bidTargeting['div-gpt-ad-1460505748561-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]).to.equal('43.00'); }); it('should only apply price granularity if bid media type matches', function () { @@ -759,7 +758,7 @@ describe('Unit: Prebid Module', function () { auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); - expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('3.00'); + expect(bidTargeting['div-gpt-ad-1460505748561-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]).to.equal('3.00'); }); }); @@ -821,7 +820,7 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); $$PREBID_GLOBAL$$.setTargetingForGPTAsync('/19968336/header-bid-tag-0'); - expect(slots[0].spySetTargeting.args).to.deep.contain.members([['hb_bidder', 'appnexus'], ['hb_adid_appnexus', '233bcbee889d46d'], ['hb_pb_appnexus', '10.00']]); + expect(slots[0].spySetTargeting.args).to.deep.contain.members([[CONSTANTS.TARGETING_KEYS.BIDDER, 'appnexus'], [CONSTANTS.TARGETING_KEYS.AD_ID + '_appnexus', '233bcbee889d46d'], [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_appnexus', '10.00']]); }); it('should set targeting when passed an array of ad unit codes with enableSendAllBids', function () { @@ -830,7 +829,7 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); $$PREBID_GLOBAL$$.setTargetingForGPTAsync(['/19968336/header-bid-tag-0']); - expect(slots[0].spySetTargeting.args).to.deep.contain.members([['hb_bidder', 'appnexus'], ['hb_adid_appnexus', '233bcbee889d46d'], ['hb_pb_appnexus', '10.00']]); + expect(slots[0].spySetTargeting.args).to.deep.contain.members([[CONSTANTS.TARGETING_KEYS.BIDDER, 'appnexus'], [CONSTANTS.TARGETING_KEYS.AD_ID + '_appnexus', '233bcbee889d46d'], [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_appnexus', '10.00']]); }); it('should set targeting from googletag data', function () { @@ -877,19 +876,19 @@ describe('Unit: Prebid Module', function () { var expected = [ [ - 'hb_bidder', + CONSTANTS.TARGETING_KEYS.BIDDER, 'appnexus' ], [ - 'hb_adid', + CONSTANTS.TARGETING_KEYS.AD_ID, '233bcbee889d46d' ], [ - 'hb_pb', + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, '10.00' ], [ - 'hb_size', + CONSTANTS.TARGETING_KEYS.SIZE, '300x250' ], [ @@ -1527,16 +1526,16 @@ describe('Unit: Prebid Module', function () { let expected = { '/19968336/header-bid-tag-0': { 'foobar': '0x0,300x250,300x600', - 'hb_size': '300x250', - 'hb_pb': '10.00', - 'hb_adid': '233bcbee889d46d', - 'hb_bidder': 'appnexus' + [CONSTANTS.TARGETING_KEYS.SIZE]: '300x250', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '233bcbee889d46d', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus' }, '/19968336/header-bid-tag1': { - 'hb_bidder': 'appnexus', - 'hb_adid': '24bd938435ec3fc', - 'hb_pb': '10.00', - 'hb_size': '728x90', + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '24bd938435ec3fc', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.SIZE]: '728x90', 'foobar': '728x90' } } @@ -1793,12 +1792,12 @@ describe('Unit: Prebid Module', function () { 'alwaysUseBid': true, 'auctionId': 123456, 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '233bcbee889d46d', - 'hb_pb': '10.00', - 'hb_size': '300x250', 'foobar': '300x250', - 'hb_deal_appnexusDummyName': '1234' + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '233bcbee889d46d', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.SIZE]: '300x250', + [CONSTANTS.TARGETING_KEYS.DEAL + '_appnexusDummyName']: '1234' } } ]; @@ -1952,11 +1951,11 @@ describe('Unit: Prebid Module', function () { expect(newAdserverTargeting).to.deep.equal(window.apntag.tags[adUnitCode].keywords); }); - it('should not find hb_adid key in lowercase for all bidders', function () { + it('should not find ' + CONSTANTS.TARGETING_KEYS.AD_ID + ' key in lowercase for all bidders', function() { const adUnitCode = '/19968336/header-bid-tag-0'; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); targeting.setTargetingForAst(); - const keywords = Object.keys(window.apntag.tags[adUnitCode].keywords).filter(keyword => (keyword.substring(0, 'hb_adid'.length) === 'hb_adid')); + const keywords = Object.keys(window.apntag.tags[adUnitCode].keywords).filter(keyword => (keyword.substring(0, CONSTANTS.TARGETING_KEYS.AD_ID.length) === CONSTANTS.TARGETING_KEYS.AD_ID)); expect(keywords.length).to.equal(0); }); }); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 7891eff5f33..952c6791056 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -1,5 +1,6 @@ import { getAdServerTargeting } from 'test/fixtures/fixtures'; import { expect } from 'chai'; +import CONSTANTS from 'src/constants.json'; var assert = require('assert'); var utils = require('src/utils'); @@ -101,7 +102,7 @@ describe('Utils', function () { var obj = getAdServerTargeting(); var output = utils.transformAdServerTargetingObj(obj[Object.keys(obj)[0]]); - var expected = 'foobar=0x0%2C300x250%2C300x600&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; + var expected = 'foobar=0x0%2C300x250%2C300x600&' + CONSTANTS.TARGETING_KEYS.SIZE + '=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '=233bcbee889d46d&' + CONSTANTS.TARGETING_KEYS.BIDDER + '=appnexus&' + CONSTANTS.TARGETING_KEYS.SIZE + '_triplelift=0x0&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_triplelift=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_triplelift=222bb26f9e8bd&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_triplelift=triplelift&' + CONSTANTS.TARGETING_KEYS.SIZE + '_appnexus=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_appnexus=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_appnexus=233bcbee889d46d&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_appnexus=appnexus&' + CONSTANTS.TARGETING_KEYS.SIZE + '_pagescience=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_pagescience=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_pagescience=25bedd4813632d7&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_pagescienc=pagescience&' + CONSTANTS.TARGETING_KEYS.SIZE + '_brightcom=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_brightcom=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_brightcom=26e0795ab963896&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_brightcom=brightcom&' + CONSTANTS.TARGETING_KEYS.SIZE + '_brealtime=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_brealtime=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_brealtime=275bd666f5a5a5d&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_brealtime=brealtime&' + CONSTANTS.TARGETING_KEYS.SIZE + '_pubmatic=300x250&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_pubmatic=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_pubmatic=28f4039c636b6a7&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_pubmatic=pubmatic&' + CONSTANTS.TARGETING_KEYS.SIZE + '_rubicon=300x600&' + CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_rubicon=10.00&' + CONSTANTS.TARGETING_KEYS.AD_ID + '_rubicon=29019e2ab586a5a&' + CONSTANTS.TARGETING_KEYS.BIDDER + '_rubicon=rubicon'; assert.equal(output, expected); }); From e7ad006f2f1c14978e0175fbdb935e5ca1dca547 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 3 Oct 2018 06:56:43 +1000 Subject: [PATCH 0733/1594] 4235 prebid endpoint return empty array instead of 204 when no bids returned (#3136) * corrected user sync type * add alias pxyz add version to endpoint add validation for 204 bid response * add validation with serverResponse is undefined fix test for 204 (no bid response) * remove package lock * restore package-lock --- modules/playgroundxyzBidAdapter.js | 20 +++++++++++++++---- .../modules/playgroundxyzBidAdapter_spec.js | 8 ++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/modules/playgroundxyzBidAdapter.js b/modules/playgroundxyzBidAdapter.js index e54f93ab8ca..f6a85b6522e 100644 --- a/modules/playgroundxyzBidAdapter.js +++ b/modules/playgroundxyzBidAdapter.js @@ -3,11 +3,11 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { BANNER } from 'src/mediaTypes'; const BIDDER_CODE = 'playgroundxyz'; -const URL = 'https://ads.playground.xyz/host-config/prebid'; +const URL = 'https://ads.playground.xyz/host-config/prebid?v=2'; export const spec = { code: BIDDER_CODE, - aliases: ['playgroundxyz'], + aliases: ['playgroundxyz', 'pxyz'], supportedMediaTypes: [BANNER], /** @@ -69,8 +69,10 @@ export const spec = { if (!serverResponse || serverResponse.error) { let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; - if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } - utils.logError(errorMessage); + if (serverResponse && serverResponse.error) { + errorMessage += `: ${serverResponse.error}`; + utils.logError(errorMessage); + } return bids; } @@ -80,6 +82,10 @@ export const spec = { return bids; } + if (!serverResponse.seatbid) { + return bids; + } + serverResponse.seatbid.forEach(sBid => { if (sBid.hasOwnProperty('bid')) { sBid.bid.forEach(iBid => { @@ -131,6 +137,12 @@ function mapImpression(bid) { ext: { appnexus: { placement_id: parseInt(bid.params.placementId, 10) + }, + pxyz: { + adapter: { + vendor: 'prebid', + prebid: '$prebid.version$' + } } } }; diff --git a/test/spec/modules/playgroundxyzBidAdapter_spec.js b/test/spec/modules/playgroundxyzBidAdapter_spec.js index ac0922ef82e..92f88092e5d 100644 --- a/test/spec/modules/playgroundxyzBidAdapter_spec.js +++ b/test/spec/modules/playgroundxyzBidAdapter_spec.js @@ -3,7 +3,7 @@ import { spec } from 'modules/playgroundxyzBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; -const URL = 'https://ads.playground.xyz/host-config/prebid'; +const URL = 'https://ads.playground.xyz/host-config/prebid?v=2'; const GDPR_CONSENT = 'XYZ-CONSENT'; describe('playgroundxyzBidAdapter', function () { @@ -64,7 +64,7 @@ describe('playgroundxyzBidAdapter', function () { const data = JSON.parse(request.data); const banner = data.imp[0].banner; - expect(Object.keys(data.imp[0].ext)).to.have.members(['appnexus']); + expect(Object.keys(data.imp[0].ext)).to.have.members(['appnexus', 'pxyz']); expect([banner.w, banner.h]).to.deep.equal([300, 250]); expect(banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); expect(request.url).to.equal(URL); @@ -128,8 +128,8 @@ describe('playgroundxyzBidAdapter', function () { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', function () { - let response = ''; + it('handles nobid response', function () { + const response = undefined; let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(result.length).to.equal(0); }); From 9faccab43f4229df37962fff21900136ec29f2fb Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 3 Oct 2018 13:15:02 -0400 Subject: [PATCH 0734/1594] update gulp 4 notes on README (#3154) --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a89f68b8abc..b81d19a574c 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,15 @@ Working examples can be found in [the developer docs](http://prebid.org/dev-docs $ npm install *Note:* You need to have `NodeJS` 4.x or greater installed. -*Note:* Because we have transitioned to using gulp 4.0 - you need to have `gulp-cli` installed globally prior to running the general `npm install`. Run the following command to perform the install: `npm install gulp-cli -g` -If you have a previous version of `gulp` installed globally, you'll need to remove it before installing `gulp-cli`. This removal can be done with the command: `npm rm gulp -g` + +*Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To compily with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in it's setup. + +If you have a previous version of `gulp` installed globally, you'll need to remove it before installing `gulp-cli`. You can check if this is installed by running `gulp -v` and seeing the version that's listed in the `CLI` field of the output. If you have the `gulp` package installd globally, it's likely the same version that you'll see in the `Local` field. If you already have `gulp-cli` installed, it should be a lower major version (it's at version `2.0.1` at the time of the transition). + +To remove the old package, you can use the command: `npm rm gulp -g` + +Once setup, run the following command to globally install the `gulp-cli` package: `npm install gulp-cli -g` + From c2847abc0dfb69667dd4365388a7bf127f1c73fa Mon Sep 17 00:00:00 2001 From: Valentin Date: Wed, 3 Oct 2018 19:39:38 +0200 Subject: [PATCH 0735/1594] Add teads bidder adapter (#3135) * Add teads bidder adapter * Remove bidder code & tests arrow functions --- modules/teadsBidAdapter.js | 134 ++++++++++++ modules/teadsBidAdapter.md | 48 +++++ test/spec/modules/teadsBidAdapter_spec.js | 247 ++++++++++++++++++++++ 3 files changed, 429 insertions(+) create mode 100644 modules/teadsBidAdapter.js create mode 100644 modules/teadsBidAdapter.md create mode 100644 test/spec/modules/teadsBidAdapter_spec.js diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js new file mode 100644 index 00000000000..e8dbe4e1c6b --- /dev/null +++ b/modules/teadsBidAdapter.js @@ -0,0 +1,134 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +const utils = require('src/utils'); +const BIDDER_CODE = 'teads'; +const ENDPOINT_URL = '//a.teads.tv/hb/bid-request'; +const gdprStatus = { + GDPR_APPLIES_PUBLISHER: 12, + GDPR_APPLIES_GLOBAL: 11, + GDPR_DOESNT_APPLY: 0, + CMP_NOT_FOUND_OR_ERROR: 22 +} + +export const spec = { + code: BIDDER_CODE, + 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') { + let isValidPlacementId = _validateId(utils.getValue(bid.params, 'placementId')); + let isValidPageId = _validateId(utils.getValue(bid.params, 'pageId')); + isValid = isValidPlacementId && isValidPageId; + } + + if (!isValid) { + utils.logError('Teads placementId and pageId parameters are required. Bid aborted.'); + } + 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: utils.getTopWindowUrl(), + data: bids, + deviceWidth: screen.width + }; + + let gdpr = bidderRequest.gdprConsent; + if (bidderRequest && gdpr) { + let isCmp = (typeof gdpr.gdprApplies === 'boolean') + let isConsentString = (typeof gdpr.consentString === 'string') + let status = isCmp ? findGdprStatus(gdpr.gdprApplies, gdpr.vendorData) : gdprStatus.CMP_NOT_FOUND_OR_ERROR + payload.gdpr_iab = { + consent: isConsentString ? gdpr.consentString : '', + status: status + }; + } + + 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, bidderRequest) { + 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: true, + ttl: bid.ttl, + ad: bid.ad, + requestId: bid.bidId, + creativeId: bid.creativeId + }; + bidResponses.push(bidResponse); + }); + } + return bidResponses; + }, + + getUserSyncs: function(syncOptions, responses, gdprApplies) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//sync.teads.tv/iframe' + }]; + } + } +}; + +function findGdprStatus(gdprApplies, gdprData) { + let status = gdprStatus.GDPR_APPLIES_PUBLISHER; + + if (gdprApplies) { + if (gdprData.hasGlobalScope || gdprData.hasGlobalConsent) status = gdprStatus.GDPR_APPLIES_GLOBAL + } else status = gdprStatus.GDPR_DOESNT_APPLY + return status; +} + +function buildRequestObject(bid) { + const reqObj = {}; + let placementId = utils.getValue(bid.params, 'placementId'); + let pageId = utils.getValue(bid.params, 'pageId'); + + reqObj.sizes = utils.parseSizesInput(bid.sizes); + reqObj.bidId = utils.getBidIdParameter('bidId', bid); + reqObj.bidderRequestId = utils.getBidIdParameter('bidderRequestId', bid); + reqObj.placementId = parseInt(placementId, 10); + reqObj.pageId = parseInt(pageId, 10); + reqObj.adUnitCode = utils.getBidIdParameter('adUnitCode', bid); + reqObj.auctionId = utils.getBidIdParameter('auctionId', bid); + reqObj.transactionId = utils.getBidIdParameter('transactionId', bid); + return reqObj; +} + +function _validateId(id) { + return (parseInt(id) > 0); +} + +registerBidder(spec); diff --git a/modules/teadsBidAdapter.md b/modules/teadsBidAdapter.md new file mode 100644 index 00000000000..ded9323540b --- /dev/null +++ b/modules/teadsBidAdapter.md @@ -0,0 +1,48 @@ +# Overview + +**Module Name**: Teads Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: innov-ssp@teads.tv + +# Description + +Use `teads` as bidder. + +`placementId` & `pageId` are required and must be integers. + +## AdUnits configuration example +``` + var adUnits = [{ + code: 'your-slot_1-div', //use exactly the same code as your slot div id. + sizes: [[300, 250]], + bids: [{ + bidder: 'teads', + params: { + placementId: 12345, + pageId: 1234 + } + }] + },{ + code: 'your-slot_2-div', //use exactly the same code as your slot div id. + sizes: [[600, 800]], + bids: [{ + bidder: 'teads', + params: { + placementId: 12345, + pageId: 1234 + } + }] + }]; +``` + +## UserSync example + +``` +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + syncEnabled: true, + syncDelay: 1 + } +}); +``` diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js new file mode 100644 index 00000000000..ab34c600a53 --- /dev/null +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -0,0 +1,247 @@ +import {expect} from 'chai'; +import {spec} from 'modules/teadsBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//a.teads.tv/hb/bid-request'; +const AD_SCRIPT = '"'; + +describe('teadsBidAdapter', 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': 'teads', + 'params': { + 'placementId': 10433394, + 'pageId': 1234 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'creativeId': 'er2ee' + }; + + it('should return true when required params found', function() { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when pageId is not valid (letters)', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 1234, + 'pageId': 'ABCD' + }; + + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when placementId is not valid (letters)', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 'FCP', + 'pageId': 1234 + }; + + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when placementId < 0 or pageId < 0', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': -1, + 'pageId': -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 = { + 'placementId': 0 + }; + + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function() { + let bidRequests = [ + { + 'bidder': 'teads', + 'params': { + 'placementId': 10433394, + 'pageId': 1234 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'creativeId': 'er2ee', + 'deviceWidth': 1680 + } + ]; + + it('sends bid request to ENDPOINT via POST', function() { + let bidderRequest = { + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000 + }; + const request = spec.buildRequests(bidRequests, bidderRequest); + + 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': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + '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); + expect(payload.gdpr_iab.status).to.equal(12); + }) + + it('should send GDPR to endpoint with 11 status', function() { + let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; + let bidderRequest = { + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true, + 'vendorData': { + 'hasGlobalScope': true + } + } + }; + + 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); + expect(payload.gdpr_iab.status).to.equal(11); + }) + + it('should send GDPR to endpoint with 22 status', function() { + let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; + let bidderRequest = { + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + 'consentString': undefined, + 'gdprApplies': undefined, + 'vendorData': undefined + } + }; + + 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(''); + expect(payload.gdpr_iab.status).to.equal(22); + }) + + it('should send GDPR to endpoint with 0 status', function() { + let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; + let bidderRequest = { + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': false, + 'vendorData': { + 'hasGlobalScope': 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); + expect(payload.gdpr_iab.status).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' + }] + } + }; + + 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' + }]; + + 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); + }); + }); +}); From 400486449cb45a2d975df8ca8c58b4bd37c81626 Mon Sep 17 00:00:00 2001 From: Benjamin Hanzelmann Date: Wed, 3 Oct 2018 20:25:23 +0200 Subject: [PATCH 0736/1594] Added the option to pass a deal id instead of a partnership id (#3148) --- modules/yieldlabBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 94aae092997..ada73bc08a0 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -83,7 +83,7 @@ export const spec = { width: customsize[0], height: customsize[1], creativeId: '' + matchedBid.id, - dealId: matchedBid.pid, + dealId: (matchedBid['c.dealid']) ? matchedBid['c.dealid'] : matchedBid.pid, currency: CURRENCY_CODE, netRevenue: false, ttl: BID_RESPONSE_TTL_SEC, From e7333c3c424d7a2050c07cb167e1606bb3720e70 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 3 Oct 2018 15:29:54 -0400 Subject: [PATCH 0737/1594] increment Prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5c134bf07e..1f8f145d81e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.26.0-pre", + "version": "1.26.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 015b803da7298a0c3507c7a2ef4e83df45d9a438 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 3 Oct 2018 15:45:57 -0400 Subject: [PATCH 0738/1594] Prebid 1.26.0 release From c3f9107d6764bfb319cbccaa6e0008e23d705203 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 3 Oct 2018 15:54:04 -0400 Subject: [PATCH 0739/1594] increment prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f8f145d81e..1b28a54f72a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.26.0", + "version": "1.27.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3ba867ae7157c00c6414379a3629e95b00b102e9 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 4 Oct 2018 08:08:11 -0400 Subject: [PATCH 0740/1594] implement find polyfill in unit test (#3156) --- test/spec/unit/pbjs_api_spec.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 96f02e7f8f2..f113b8f0f45 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -15,6 +15,7 @@ import * as ajaxLib from 'src/ajax'; import * as auctionModule from 'src/auction'; import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; import * as targetingModule from 'src/targeting'; +import find from 'core-js/library/fn/array/find'; var assert = require('chai').assert; var expect = require('chai').expect; @@ -1849,9 +1850,8 @@ describe('Unit: Prebid Module', function () { // mark the bid and verify the state has changed to RENDERED const winningBid = targeting.getWinningBids(adUnitCode)[0]; $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode, adId: winningBid.adId }); - const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) - .bids - .find(bid => bid.adId === winningBid.adId); + const markedBid = find($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode).bids, + bid => bid.adId === winningBid.adId); expect(markedBid.status).to.equal(RENDERED); resetAuction(); @@ -1864,9 +1864,8 @@ describe('Unit: Prebid Module', function () { const winningBid = targeting.getWinningBids(adUnitCode)[0]; $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode, adId: 'miss' }); - const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) - .bids - .find(bid => bid.adId === winningBid.adId); + const markedBid = find($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode).bids, + bid => bid.adId === winningBid.adId); expect(markedBid.status).to.not.equal(RENDERED); resetAuction(); @@ -1881,9 +1880,8 @@ describe('Unit: Prebid Module', function () { // mark the bid and verify the state has changed to RENDERED const winningBid = targeting.getWinningBids(adUnitCode)[0]; $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode }); - const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) - .bids - .find(bid => bid.adId === winningBid.adId); + const markedBid = find($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode).bids, + bid => bid.adId === winningBid.adId); expect(markedBid.status).to.equal(RENDERED); resetAuction(); @@ -1898,9 +1896,8 @@ describe('Unit: Prebid Module', function () { // mark the bid and verify the state has changed to RENDERED const winningBid = targeting.getWinningBids(adUnitCode)[0]; $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adId: winningBid.adId }); - const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) - .bids - .find(bid => bid.adId === winningBid.adId); + const markedBid = find($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode).bids, + bid => bid.adId === winningBid.adId); expect(markedBid.status).to.equal(RENDERED); resetAuction(); From 3fec73f7684bb8df9d265214c03d656bb436b631 Mon Sep 17 00:00:00 2001 From: rcheptanariu <35690143+rcheptanariu@users.noreply.github.com> Date: Mon, 8 Oct 2018 20:16:49 +0300 Subject: [PATCH 0741/1594] InvibesBidAdapter - gdpr support (#3151) --- modules/invibesBidAdapter.js | 60 ++++++++++------ test/spec/modules/invibesBidAdapter_spec.js | 77 ++++++++++++++++----- 2 files changed, 97 insertions(+), 40 deletions(-) diff --git a/modules/invibesBidAdapter.js b/modules/invibesBidAdapter.js index eefe63034bd..d6edff75ec9 100644 --- a/modules/invibesBidAdapter.js +++ b/modules/invibesBidAdapter.js @@ -8,7 +8,8 @@ const CONSTANTS = { TIME_TO_LIVE: 300, DEFAULT_CURRENCY: 'EUR', PREBID_VERSION: 1, - METHOD: 'GET' + METHOD: 'GET', + INVIBES_VENDOR_ID: 436 }; export const spec = { @@ -23,9 +24,7 @@ export const spec = { * @param bidderRequest * @return ServerRequest[] */ - buildRequests: function (bidRequests, bidderRequest) { - return buildRequest(bidRequests, bidderRequest != null ? bidderRequest.auctionStart : null); - }, + buildRequests: buildRequest, /** * @param {*} responseObj * @param {requestParams} bidRequests @@ -55,6 +54,11 @@ let invibes = topWin.invibes = topWin.invibes || {}; let _customUserSync; function isBidRequestValid(bid) { + if (invibes && typeof invibes.bidResponse === 'object') { + utils.logInfo('Invibes Adapter - Bid response already received. Invibes only responds to one bid request per user visit'); + return false; + } + if (typeof bid.params !== 'object') { return false; } @@ -67,11 +71,11 @@ function isBidRequestValid(bid) { return true; } -function buildRequest(bidRequests, auctionStart) { - // invibes only responds to 1 bid request for each user visit +function buildRequest(bidRequests, bidderRequest) { + bidderRequest = bidderRequest || {}; const _placementIds = []; let _loginId, _customEndpoint; - let _ivAuctionStart = auctionStart || Date.now(); + let _ivAuctionStart = bidderRequest.auctionStart || Date.now(); bidRequests.forEach(function (bidRequest) { bidRequest.startTime = new Date().getTime(); @@ -85,9 +89,9 @@ function buildRequest(bidRequests, auctionStart) { cookieDomain = detectTopmostCookieDomain(); invibes.noCookies = invibes.noCookies || invibes.getCookie('ivNoCookie'); - invibes.optIn = invibes.optIn || invibes.getCookie('ivOptIn'); + invibes.optIn = invibes.optIn || invibes.getCookie('ivOptIn') || readGdprConsent(bidderRequest.gdprConsent); - initDomainId(); + initDomainId(invibes.domainOptions); const currentQueryStringParams = parseQueryStringParams(); @@ -96,7 +100,6 @@ function buildRequest(bidRequests, auctionStart) { videoAdHtmlId: generateRandomId(), showFallback: currentQueryStringParams['advs'] === '0', ivbsCampIdsLocal: invibes.getCookie('IvbsCampIdsLocal'), - lId: invibes.dom.id, bidParamsJson: JSON.stringify({ placementIds: _placementIds, @@ -110,11 +113,12 @@ function buildRequest(bidRequests, auctionStart) { width: topWin.innerWidth, height: topWin.innerHeight, - noc: !cookieDomain + noc: !cookieDomain, + oi: invibes.optIn }; - if (invibes.optIn) { - data.oi = 1; + if (invibes.dom.id) { + data.lId = invibes.dom.id; } const parametersToPassForward = 'videoaddebug,advs,bvci,bvid,istop,trybvid,trybvci'.split(','); @@ -323,10 +327,7 @@ function initLogger() { function buildSyncUrl() { let syncUrl = _customUserSync || CONSTANTS.SYNC_ENDPOINT; syncUrl += '?visitId=' + invibes.visitId; - - if (invibes.optIn) { - syncUrl += '&optIn=1'; - } + syncUrl += '&optIn=' + invibes.optIn; const did = invibes.getCookie('ivbsdid'); if (did) { @@ -358,6 +359,14 @@ function acceptPostMessage(e) { } } +function readGdprConsent(gdprConsent) { + if (gdprConsent && gdprConsent.vendorData && gdprConsent.vendorData.vendorConsents) { + return !!gdprConsent.vendorData.vendorConsents[CONSTANTS.INVIBES_VENDOR_ID.toString(10)] === true ? 2 : -2; + } + + return 0; +} + const ivLogger = initLogger(); /// Local domain cookie management ===================== @@ -400,9 +409,9 @@ invibes.setCookie = function (name, value, exdays, domain) { let detectTopmostCookieDomain = function () { let testCookie = invibes.Uid.generate(); - let hostParts = location.host.split('.'); + let hostParts = location.hostname.split('.'); if (hostParts.length === 1) { - return location.host; + return location.hostname; } for (let i = hostParts.length - 1; i >= 0; i--) { let domain = '.' + hostParts.slice(i).join('.'); @@ -463,8 +472,8 @@ let initDomainId = function (options) { let setId = function () { invibes.dom = { - id: !state.cr && invibes.optIn ? state.id : undefined, - tempId: invibes.optIn ? state.id : undefined, + id: (!state.cr && invibes.optIn > 0) ? state.id : undefined, + tempId: (invibes.optIn > 0) ? state.id : undefined, graduate: graduate }; }; @@ -481,7 +490,7 @@ let initDomainId = function (options) { if (state.hc < minHC) { state.hc++; } - if (state.hc >= minHC && validGradTime(state)) { + if ((state.hc >= minHC && validGradTime(state)) || options.skipGraduation) { graduate(); } } @@ -496,4 +505,11 @@ export function resetInvibes() { invibes.noCookies = undefined; invibes.dom = undefined; invibes.bidResponse = undefined; + invibes.domainOptions = undefined; +} + +export function stubDomainOptions(persistence) { + invibes.domainOptions = { + persistence: persistence + }; } diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js index d0fa627929e..6391f168599 100644 --- a/test/spec/modules/invibesBidAdapter_spec.js +++ b/test/spec/modules/invibesBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec, resetInvibes } from 'modules/invibesBidAdapter'; +import { spec, resetInvibes, stubDomainOptions } from 'modules/invibesBidAdapter'; describe('invibesBidAdapter:', function () { const BIDDER_CODE = 'invibes'; @@ -40,6 +40,21 @@ describe('invibesBidAdapter:', function () { } ]; + let StubbedPersistence = function(initialValue) { + var value = initialValue; + return { + load: function () { + let str = value || ''; + try { + return JSON.parse(str); + } catch (e) { } + }, + save: function (obj) { + value = JSON.stringify(obj); + } + } + }; + beforeEach(function () { resetInvibes(); document.cookie = ''; @@ -83,6 +98,18 @@ describe('invibesBidAdapter:', function () { expect(spec.isBidRequestValid(invalidBid)).to.be.false; }); + + it('returns false when bid response was previously received', function() { + const validBid = { + bidder: BIDDER_CODE, + params: { + placementId: PLACEMENT_ID + } + } + + top.window.invibes.bidResponse = { prop: 'prop' }; + expect(spec.isBidRequestValid(validBid)).to.be.false; + }); }); }); @@ -126,38 +153,52 @@ describe('invibesBidAdapter:', function () { expect(request.data.lId).to.not.exist; }); + it('try to graduate but not enough count - doesnt send the domain id', function () { + global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":5}'; + let bidderRequest = { gdprConsent: { vendorData: { vendorConsents: { 436: true } } } }; + let request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.lId).to.not.exist; + }); + + it('try to graduate but not old enough - doesnt send the domain id', function () { + let bidderRequest = { gdprConsent: { vendorData: { vendorConsents: { 436: true } } } }; + global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":' + Date.now() + ',"hc":5}'; + let request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.lId).to.not.exist; + }); + it('graduate and send the domain id', function () { - top.window.invibes.optIn = 1; - global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":7}'; - let request = spec.buildRequests(bidRequests); + let bidderRequest = { gdprConsent: { vendorData: { vendorConsents: { 436: true } } } }; + stubDomainOptions(new StubbedPersistence('{"id":"dvdjkams6nkq","cr":1521818537626,"hc":7}')); + let request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.lId).to.exist; }); it('send the domain id if already graduated', function () { - top.window.invibes.optIn = 1; - global.document.cookie = 'ivbsdid={"id":"f8zoh044p9oi"}'; - let request = spec.buildRequests(bidRequests); + let bidderRequest = { gdprConsent: { vendorData: { vendorConsents: { 436: true } } } }; + stubDomainOptions(new StubbedPersistence('{"id":"f8zoh044p9oi"}')); + let request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.lId).to.exist; }); it('send the domain id after replacing it with new format', function () { - top.window.invibes.optIn = 1; - global.document.cookie = 'ivbsdid={"id":"f8zoh044p9oi.8537626"}'; - let request = spec.buildRequests(bidRequests); + let bidderRequest = { gdprConsent: { vendorData: { vendorConsents: { 436: true } } } }; + stubDomainOptions(new StubbedPersistence('{"id":"f8zoh044p9oi.8537626"}')); + let request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.lId).to.exist; }); - it('try to graduate but not enough count - doesnt send the domain id', function () { - top.window.invibes.optIn = 1; - global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":5}'; - let request = spec.buildRequests(bidRequests); + it('dont send the domain id if consent declined', function () { + let bidderRequest = { gdprConsent: { vendorData: { vendorConsents: { 436: false } } } }; + stubDomainOptions(new StubbedPersistence('{"id":"f8zoh044p9oi.8537626"}')); + let request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.lId).to.not.exist; }); - it('try to graduate but not old enough - doesnt send the domain id', function () { - top.window.invibes.optIn = 1; - global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":' + Date.now() + ',"hc":5}'; - let request = spec.buildRequests(bidRequests); + it('dont send the domain id if no consent', function () { + let bidderRequest = { }; + stubDomainOptions(new StubbedPersistence('{"id":"f8zoh044p9oi.8537626"}')); + let request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.lId).to.not.exist; }); }); From c3432e55e9660feeb7610e3506f8b1899f3f611e Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Tue, 9 Oct 2018 17:46:19 +0300 Subject: [PATCH 0742/1594] removed `cookieSyncDelay` from `config` since we have more configuration options now with the `userSync` object (#3142) --- src/config.js | 10 ---------- src/prebid.js | 1 - 2 files changed, 11 deletions(-) diff --git a/src/config.js b/src/config.js index f8d8195409b..ecb5f78a43f 100644 --- a/src/config.js +++ b/src/config.js @@ -16,7 +16,6 @@ const utils = require('./utils'); const DEFAULT_DEBUG = false; const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; -const DEFAULT_COOKIESYNC_DELAY = 100; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; const DEFAULT_DISABLE_AJAX_TIMEOUT = false; @@ -84,15 +83,6 @@ export function newConfig() { this._publisherDomain = val; }, - // delay to request cookie sync to stay out of critical path - _cookieSyncDelay: DEFAULT_COOKIESYNC_DELAY, - get cookieSyncDelay() { - return $$PREBID_GLOBAL$$.cookieSyncDelay || this._cookieSyncDelay; - }, - set cookieSyncDelay(val) { - this._cookieSyncDelay = val; - }, - // calls existing function which may be moved after deprecation _priceGranularity: GRANULARITY_OPTIONS.MEDIUM, set priceGranularity(val) { diff --git a/src/prebid.js b/src/prebid.js index bfc9e31a06c..5993073e474 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -667,7 +667,6 @@ $$PREBID_GLOBAL$$.getConfig = config.getConfig; * @param {boolean} options.enableSendAllBids Turn "send all bids" mode on/off. Example: `pbjs.setConfig({ enableSendAllBids: true })`. * @param {number} options.bidderTimeout Set a global bidder timeout, in milliseconds. Example: `pbjs.setConfig({ bidderTimeout: 3000 })`. Note that it's still possible for a bid to get into the auction that responds after this timeout. This is due to how [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) works in JS: it queues the callback in the event loop in an approximate location that should execute after this time but it is not guaranteed. For more information about the asynchronous event loop and `setTimeout`, see [How JavaScript Timers Work](https://johnresig.com/blog/how-javascript-timers-work/). * @param {string} options.publisherDomain The publisher's domain where Prebid is running, for cross-domain iFrame communication. Example: `pbjs.setConfig({ publisherDomain: "https://www.theverge.com" })`. - * @param {number} options.cookieSyncDelay A delay (in milliseconds) for requesting cookie sync to stay out of the critical path of page load. Example: `pbjs.setConfig({ cookieSyncDelay: 100 })`. * @param {Object} options.s2sConfig The configuration object for [server-to-server header bidding](http://prebid.org/dev-docs/get-started-with-prebid-server.html). Example: * @alias module:pbjs.setConfig * ``` From 95ab4a05e1b24afbc7440cc34db0719fde08b726 Mon Sep 17 00:00:00 2001 From: bjorn-lw <32431346+bjorn-lw@users.noreply.github.com> Date: Tue, 9 Oct 2018 16:50:54 +0200 Subject: [PATCH 0743/1594] Livewrapped bid and analytics adapter (#3157) * Livewrapped bid and analytics adapter * Fixed some tests for browser compatibility * Fixed some tests for browser compatibility * Changed analytics adapter code name * Fix double quote in debug message --- modules/livewrappedAnalyticsAdapter.js | 222 +++++++ modules/livewrappedBidAdapter.js | 187 ++++++ modules/livewrappedBidAdapter.md | 28 + .../livewrappedAnalyticsAdapter_spec.js | 265 ++++++++ .../modules/livewrappedBidAdapter_spec.js | 609 ++++++++++++++++++ 5 files changed, 1311 insertions(+) create mode 100644 modules/livewrappedAnalyticsAdapter.js create mode 100644 modules/livewrappedBidAdapter.js create mode 100644 modules/livewrappedBidAdapter.md create mode 100644 test/spec/modules/livewrappedAnalyticsAdapter_spec.js create mode 100644 test/spec/modules/livewrappedBidAdapter_spec.js diff --git a/modules/livewrappedAnalyticsAdapter.js b/modules/livewrappedAnalyticsAdapter.js new file mode 100644 index 00000000000..21c0bc73ec4 --- /dev/null +++ b/modules/livewrappedAnalyticsAdapter.js @@ -0,0 +1,222 @@ +import * as utils from 'src/utils'; +import {ajax} from 'src/ajax'; +import adapter from 'src/AnalyticsAdapter'; +import CONSTANTS from 'src/constants.json'; +import adaptermanager from 'src/adaptermanager'; + +const ANALYTICSTYPE = 'endpoint'; +const URL = '//lwadm.com/analytics/10'; +const EMPTYURL = ''; +const REQUESTSENT = 1; +const RESPONSESENT = 2; +const WINSENT = 4; +const TIMEOUTSENT = 8; + +let initOptions; +export const BID_WON_TIMEOUT = 500; + +const cache = { + auctions: {}, +}; + +let livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTYPE}), { + track({eventType, args}) { + utils.logInfo('LIVEWRAPPED_EVENT:', [eventType, args]); + + switch (eventType) { + case CONSTANTS.EVENTS.AUCTION_INIT: + utils.logInfo('LIVEWRAPPED_AUCTION_INIT:', args); + cache.auctions[args.auctionId] = {bids: {}}; + break; + case CONSTANTS.EVENTS.BID_REQUESTED: + utils.logInfo('LIVEWRAPPED_BID_REQUESTED:', args); + + args.bids.forEach(function(bidRequest) { + cache.auctions[args.auctionId].timeStamp = args.start; + cache.auctions[args.auctionId].bids[bidRequest.bidId] = { + bidder: bidRequest.bidder, + adUnit: bidRequest.adUnitCode, + isBid: false, + won: false, + timeout: false, + sendStatus: 0 + } + + utils.logInfo(bidRequest); + }) + utils.logInfo(livewrappedAnalyticsAdapter.requestEvents); + break; + case CONSTANTS.EVENTS.BID_RESPONSE: + utils.logInfo('LIVEWRAPPED_BID_RESPONSE:', args); + + let bidResponse = cache.auctions[args.auctionId].bids[args.adId]; + bidResponse.isBid = args.getStatusCode() === CONSTANTS.STATUS.GOOD; + bidResponse.width = args.width; + bidResponse.height = args.height; + bidResponse.cpm = args.cpm; + bidResponse.ttr = args.timeToRespond; + break; + case CONSTANTS.EVENTS.BIDDER_DONE: + utils.logInfo('LIVEWRAPPED_BIDDER_DONE:', args); + args.bids.forEach(doneBid => { + let bid = cache.auctions[doneBid.auctionId].bids[doneBid.bidId]; + if (!bid.ttr) { + bid.ttr = Date.now() - args.auctionStart; + } + }); + break; + case CONSTANTS.EVENTS.BID_WON: + utils.logInfo('LIVEWRAPPED_BID_WON:', args); + let wonBid = cache.auctions[args.auctionId].bids[args.adId]; + wonBid.won = true; + if (wonBid.sendStatus != 0) { + livewrappedAnalyticsAdapter.sendEvents(); + } + break; + case CONSTANTS.EVENTS.BID_TIMEOUT: + utils.logInfo('LIVEWRAPPED_BID_TIMEOUT:', args); + args.forEach(timeout => { + cache.auctions[timeout.auctionId].bids[timeout.bidId].timeout = true; + }); + break; + case CONSTANTS.EVENTS.AUCTION_END: + utils.logInfo('LIVEWRAPPED_AUCTION_END:', args); + setTimeout(() => { + livewrappedAnalyticsAdapter.sendEvents(); + }, BID_WON_TIMEOUT); + break; + } + } +}); + +// save the base class function +livewrappedAnalyticsAdapter.originEnableAnalytics = livewrappedAnalyticsAdapter.enableAnalytics; +livewrappedAnalyticsAdapter.allRequestEvents = []; + +// override enableAnalytics so we can get access to the config passed in from the page +livewrappedAnalyticsAdapter.enableAnalytics = function (config) { + initOptions = config.options; + livewrappedAnalyticsAdapter.originEnableAnalytics(config); +}; + +livewrappedAnalyticsAdapter.sendEvents = function() { + var events = { + publisherId: initOptions.publisherId, + requests: getSentRequests(), + responses: getResponses(), + wins: getWins(), + timeouts: getTimeouts() + }; + + if (events.requests.length == 0 && + events.responses.length == 0 && + events.wins.length == 0 && + events.timeouts.length == 0) { + return; + } + + ajax(URL, undefined, JSON.stringify(events), {method: 'POST'}); +} + +function getSentRequests() { + var sentRequests = []; + + Object.keys(cache.auctions).forEach(auctionId => { + Object.keys(cache.auctions[auctionId].bids).forEach(bidId => { + let auction = cache.auctions[auctionId]; + let bid = auction.bids[bidId]; + if (!(bid.sendStatus & REQUESTSENT)) { + bid.sendStatus |= REQUESTSENT; + + sentRequests.push({ + timeStamp: auction.timeStamp, + adUnit: bid.adUnit, + bidder: bid.bidder + }); + } + }); + }); + + return sentRequests; +} + +function getResponses() { + var responses = []; + + Object.keys(cache.auctions).forEach(auctionId => { + Object.keys(cache.auctions[auctionId].bids).forEach(bidId => { + let auction = cache.auctions[auctionId]; + let bid = auction.bids[bidId]; + if (!(bid.sendStatus & RESPONSESENT) && !bid.timeout) { + bid.sendStatus |= RESPONSESENT; + + responses.push({ + timeStamp: auction.timeStamp, + adUnit: bid.adUnit, + bidder: bid.bidder, + width: bid.width, + height: bid.height, + cpm: bid.cpm, + ttr: bid.ttr, + IsBid: bid.isBid + }); + } + }); + }); + + return responses; +} + +function getWins() { + var wins = []; + + Object.keys(cache.auctions).forEach(auctionId => { + Object.keys(cache.auctions[auctionId].bids).forEach(bidId => { + let auction = cache.auctions[auctionId]; + let bid = auction.bids[bidId]; + if (!(bid.sendStatus & WINSENT) && bid.won) { + bid.sendStatus |= WINSENT; + + wins.push({ + timeStamp: auction.timeStamp, + adUnit: bid.adUnit, + bidder: bid.bidder, + width: bid.width, + height: bid.height, + cpm: bid.cpm, + }); + } + }); + }); + + return wins; +} + +function getTimeouts() { + var timeouts = []; + + Object.keys(cache.auctions).forEach(auctionId => { + Object.keys(cache.auctions[auctionId].bids).forEach(bidId => { + let auction = cache.auctions[auctionId]; + let bid = auction.bids[bidId]; + if (!(bid.sendStatus & TIMEOUTSENT) && bid.timeout) { + bid.sendStatus |= TIMEOUTSENT; + + timeouts.push({ + bidder: bid.bidder, + adUnit: bid.adUnit, + timeStamp: auction.timeStamp + }); + } + }); + }); + + return timeouts; +} + +adaptermanager.registerAnalyticsAdapter({ + adapter: livewrappedAnalyticsAdapter, + code: 'livewrapped' +}); + +export default livewrappedAnalyticsAdapter; diff --git a/modules/livewrappedBidAdapter.js b/modules/livewrappedBidAdapter.js new file mode 100644 index 00000000000..ebfe4aad2d4 --- /dev/null +++ b/modules/livewrappedBidAdapter.js @@ -0,0 +1,187 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; +import find from 'core-js/library/fn/array/find'; + +const BIDDER_CODE = 'livewrapped'; +export const URL = 'https://lwadm.com/ad'; +const VERSION = '1.1'; + +export const spec = { + code: BIDDER_CODE, + + /** + * Determines whether or not the given bid request is valid. + * + * Parameters should be + * + * adUnitId: LiveWrapped's id of the ad unit. Optional. A guid identifying the ad unit. + * adUnitName: LiveWrapped's name of the ad unit Optional. (Prebid's ad unit code will be used otherwise.) + * publisherId: Publisher id. Required if adUnitName is used or both adUnitName and adUnitId is omitted, otherwise optional. + * userId: A persistent user id if available. Optional. + * url: Page url Optional. Use if page url cannot be determined due to use of iframes. + * bidUrl: Bidding endpoint Optional. + * seats: List of bidders and seats Optional. {"bidder name": ["seat 1", "seat 2"], ...} + * deviceId: Device id if available Optional. + * ifa: Advertising ID Optional. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function(bid) { + return (bid.params.adUnitId || ((bid.params.adUnitName || bid.adUnitCode || bid.placementCode) && bid.params.publisherId)) !== undefined; + }, + + /** + * 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) { + const userId = find(bidRequests, hasUserId); + const publisherId = find(bidRequests, hasPublisherId); + const auctionId = find(bidRequests, hasAuctionId); + let bidUrl = find(bidRequests, hasBidUrl); + let url = find(bidRequests, hasUrl); + let test = find(bidRequests, hasTestParam); + let seats = find(bidRequests, hasSeatsParam); + let deviceId = find(bidRequests, hasDeviceIdParam); + let ifa = find(bidRequests, hasIfaParam); + let tid = find(bidRequests, hasTidParam); + bidUrl = bidUrl ? bidUrl.params.bidUrl : URL; + url = url ? url.params.url : (config.getConfig('pageUrl') || utils.getTopWindowUrl()); + test = test ? test.params.test : undefined; + var adRequests = bidRequests.map(bidToAdRequest); + + const payload = { + auctionId: auctionId ? auctionId.auctionId : undefined, + publisherId: publisherId ? publisherId.params.publisherId : undefined, + userId: userId ? userId.params.userId : undefined, + url: url, + test: test, + seats: seats ? seats.params.seats : undefined, + deviceId: deviceId ? deviceId.params.deviceId : undefined, + ifa: ifa ? ifa.params.ifa : undefined, + tid: tid ? tid.params.tid : undefined, + version: VERSION, + gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : false, + gdprConsent: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined, + cookieSupport: !utils.isSafariBrowser() && utils.cookiesAreEnabled(), + adRequests: [...adRequests] + }; + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: bidUrl, + 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) { + const bidResponses = []; + + serverResponse.body.ads.forEach(function(ad) { + let bidResponse = { + requestId: ad.bidId, + bidderCode: BIDDER_CODE, + cpm: ad.cpmBid, + width: ad.width, + height: ad.height, + ad: ad.tag, + ttl: ad.ttl, + creativeId: ad.creativeId, + netRevenue: true, + currency: serverResponse.body.currency + }; + + bidResponses.push(bidResponse); + }); + + return bidResponses; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + if (serverResponses.length == 0) return []; + + let syncList = []; + let userSync = serverResponses[0].body.pixels || []; + + userSync.forEach(function(sync) { + if (syncOptions.pixelEnabled && sync.type == 'Redirect') { + syncList.push({type: 'image', url: sync.url}); + } + + if (syncOptions.iframeEnabled && sync.type == 'Iframe') { + syncList.push({type: 'iframe', url: sync.url}); + } + }); + + return syncList; + } +} + +function hasUserId(bid) { + return !!bid.params.userId; +} + +function hasPublisherId(bid) { + return !!bid.params.publisherId; +} + +function hasUrl(bid) { + return !!bid.params.url; +} + +function hasBidUrl(bid) { + return !!bid.params.bidUrl; +} + +function hasAuctionId(bid) { + return !!bid.auctionId; +} + +function hasTestParam(bid) { + return !!bid.params.test; +} + +function hasSeatsParam(bid) { + return !!bid.params.seats; +} + +function hasDeviceIdParam(bid) { + return !!bid.params.deviceId; +} + +function hasIfaParam(bid) { + return !!bid.params.ifa; +} + +function hasTidParam(bid) { + return !!bid.params.tid; +} + +function bidToAdRequest(bid) { + return { + adUnitId: bid.params.adUnitId, + callerAdUnitId: bid.params.adUnitName || bid.adUnitCode || bid.placementCode, + bidId: bid.bidId, + transactionId: bid.transactionId, + formats: bid.sizes.map(sizeToFormat) + }; +} + +function sizeToFormat(size) { + return { + width: size[0], + height: size[1] + } +} + +registerBidder(spec); diff --git a/modules/livewrappedBidAdapter.md b/modules/livewrappedBidAdapter.md new file mode 100644 index 00000000000..15e3e8d533a --- /dev/null +++ b/modules/livewrappedBidAdapter.md @@ -0,0 +1,28 @@ +# Overview + +**Module Name**: Livewrapped Bid Adapter +**Module Type**: Bidder Adapter +**Maintainer**: info@livewrapped.com + +# Description + +Connects to Livewrapped Header Bidding wrapper for bids. + +Livewrapped supports banner. + +# Test Parameters + +``` +var adUnits = [ + { + code: 'banner-div', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'livewrapped', + params: { + adUnitId: '6A32352E-BC17-4B94-B2A7-5BF1724417D7' + } + }] + } +]; +``` diff --git a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..f7de9cd8101 --- /dev/null +++ b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js @@ -0,0 +1,265 @@ +import livewrappedAnalyticsAdapter, { BID_WON_TIMEOUT } from 'modules/livewrappedAnalyticsAdapter'; +import CONSTANTS from 'src/constants.json'; +import { config } from 'src/config'; + +let events = require('src/events'); +let adaptermanager = require('src/adaptermanager'); + +const { + EVENTS: { + AUCTION_INIT, + AUCTION_END, + BID_REQUESTED, + BID_RESPONSE, + BIDDER_DONE, + BID_WON, + BID_TIMEOUT, + SET_TARGETING + }, + STATUS: { + GOOD + } +} = CONSTANTS; + +const BID1 = { + width: 980, + height: 240, + cpm: 1.1, + timeToRespond: 200, + bidId: '2ecff0db240757', + adId: '2ecff0db240757', + auctionId: '25c6d7f5-699a-4bfc-87c9-996f915341fa', + getStatusCode() { + return CONSTANTS.STATUS.GOOD; + } +}; + +const BID2 = Object.assign({}, BID1, { + width: 300, + height: 250, + cpm: 2.2, + timeToRespond: 300, + bidId: '3ecff0db240757', + adId: '3ecff0db240757', +}); + +const MOCK = { + AUCTION_INIT: { + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', + }, + BID_REQUESTED: { + 'bidder': 'livewrapped', + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', + 'bidderRequestId': '1be65d7958826a', + 'bids': [ + { + 'bidder': 'livewrapped', + 'adUnitCode': 'panorama_d_1', + 'bidId': '2ecff0db240757', + }, + { + 'bidder': 'livewrapped', + 'adUnitCode': 'box_d_1', + 'bidId': '3ecff0db240757', + } + ], + 'start': 1519149562216 + }, + BID_RESPONSE: [ + BID1, + BID2 + ], + AUCTION_END: { + }, + BID_WON: [ + Object.assign({}, BID1, { + 'status': 'rendered' + }), + Object.assign({}, BID2, { + 'status': 'rendered' + }) + ], + BIDDER_DONE: { + 'bidderCode': 'livewrapped', + 'bids': [ + BID1, + BID2 + ] + }, + BID_TIMEOUT: [ + { + 'bidId': '2ecff0db240757', + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' + } + ] +}; + +const ANALYTICS_MESSAGE = { + publisherId: 'CC411485-42BC-4F92-8389-42C503EE38D7', + requests: [ + { + adUnit: 'panorama_d_1', + bidder: 'livewrapped', + timeStamp: 1519149562216 + }, + { + adUnit: 'box_d_1', + bidder: 'livewrapped', + timeStamp: 1519149562216 + } + ], + responses: [ + { + timeStamp: 1519149562216, + adUnit: 'panorama_d_1', + bidder: 'livewrapped', + width: 980, + height: 240, + cpm: 1.1, + ttr: 200, + IsBid: true + }, + { + timeStamp: 1519149562216, + adUnit: 'box_d_1', + bidder: 'livewrapped', + width: 300, + height: 250, + cpm: 2.2, + ttr: 300, + IsBid: true + } + ], + timeouts: [], + wins: [ + { + timeStamp: 1519149562216, + adUnit: 'panorama_d_1', + bidder: 'livewrapped', + width: 980, + height: 240, + cpm: 1.1 + }, + { + timeStamp: 1519149562216, + adUnit: 'box_d_1', + bidder: 'livewrapped', + width: 300, + height: 250, + cpm: 2.2 + } + ] +}; + +function performStandardAuction() { + 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); + events.emit(SET_TARGETING, MOCK.SET_TARGETING); + events.emit(BID_WON, MOCK.BID_WON[0]); + events.emit(BID_WON, MOCK.BID_WON[1]); +} + +describe('Livewrapped analytics adapter', function () { + let sandbox; + let xhr; + let requests; + let clock; + + beforeEach(function () { + sandbox = sinon.sandbox.create(); + + xhr = sandbox.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + + sandbox.stub(events, 'getEvents').returns([]); + + clock = sandbox.useFakeTimers(1519767013781); + }); + + afterEach(function () { + sandbox.restore(); + config.resetConfig(); + }); + + describe('when handling events', function () { + adaptermanager.registerAnalyticsAdapter({ + code: 'livewrapped', + adapter: livewrappedAnalyticsAdapter + }); + + beforeEach(function () { + adaptermanager.enableAnalytics({ + provider: 'livewrapped', + options: { + publisherId: 'CC411485-42BC-4F92-8389-42C503EE38D7' + } + }); + }); + + afterEach(function () { + livewrappedAnalyticsAdapter.disableAnalytics(); + }); + + it('should build a batched message from prebid events', function () { + performStandardAuction(); + + clock.tick(BID_WON_TIMEOUT + 1000); + + expect(requests.length).to.equal(1); + let request = requests[0]; + + expect(request.url).to.equal('//lwadm.com/analytics/10'); + + let message = JSON.parse(request.requestBody); + + expect(message).to.deep.equal(ANALYTICS_MESSAGE); + }); + + it('should send batched message without BID_WON if necessary and further BID_WON events individually', 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); + events.emit(SET_TARGETING, MOCK.SET_TARGETING); + events.emit(BID_WON, MOCK.BID_WON[0]); + + clock.tick(BID_WON_TIMEOUT + 1000); + + events.emit(BID_WON, MOCK.BID_WON[1]); + + expect(requests.length).to.equal(2); + + let message = JSON.parse(requests[0].requestBody); + expect(message.wins.length).to.equal(1); + expect(message.requests).to.deep.equal(ANALYTICS_MESSAGE.requests); + expect(message.wins[0]).to.deep.equal(ANALYTICS_MESSAGE.wins[0]); + + message = JSON.parse(requests[1].requestBody); + expect(message.wins.length).to.equal(1); + expect(message.wins[0]).to.deep.equal(ANALYTICS_MESSAGE.wins[1]); + }); + + it('should properly mark bids as timed out', function () { + events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); + events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); + events.emit(BID_TIMEOUT, MOCK.BID_TIMEOUT); + events.emit(AUCTION_END, MOCK.AUCTION_END); + + clock.tick(BID_WON_TIMEOUT + 1000); + + expect(requests.length).to.equal(1); + + let message = JSON.parse(requests[0].requestBody); + expect(message.timeouts.length).to.equal(1); + expect(message.timeouts[0].bidder).to.equal('livewrapped'); + expect(message.timeouts[0].adUnit).to.equal('panorama_d_1'); + }); + }); +}); diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js new file mode 100644 index 00000000000..64a70b946ef --- /dev/null +++ b/test/spec/modules/livewrappedBidAdapter_spec.js @@ -0,0 +1,609 @@ +import {expect} from 'chai'; +import {spec} from 'modules/livewrappedBidAdapter'; +import {config} from 'src/config'; +import * as utils from 'src/utils'; + +describe('Livewrapped adapter tests', function () { + let sandbox, + bidderRequest; + + beforeEach(function () { + sandbox = sinon.sandbox.create(); + + bidderRequest = { + bidderCode: 'livewrapped', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + bidderRequestId: '178e34bad3658f', + bids: [ + { + bidder: 'livewrapped', + params: { + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']} + }, + adUnitCode: 'panorama_d_1', + sizes: [[980, 240], [980, 120]], + bidId: '2ffb201a808da7', + bidderRequestId: '178e34bad3658f', + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D' + } + ], + start: 1472239426002, + auctionStart: 1472239426000, + timeout: 5000 + }; + }); + + afterEach(function () { + sandbox.restore(); + }); + + describe('isBidRequestValid', function() { + it('should accept a request with id only as valid', function() { + let bid = {params: {adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37'}}; + + let result = spec.isBidRequestValid(bid); + + expect(result).to.be.true; + }); + + it('should accept a request with adUnitName and PublisherId as valid', function() { + let bid = {params: {adUnitName: 'panorama_d_1', publisherId: '26947112-2289-405D-88C1-A7340C57E63E'}}; + + let result = spec.isBidRequestValid(bid); + + expect(result).to.be.true; + }); + + it('should accept a request with adUnitCode and PublisherId as valid', function() { + let bid = {adUnitCode: 'panorama_d_1', params: {publisherId: '26947112-2289-405D-88C1-A7340C57E63E'}}; + + let result = spec.isBidRequestValid(bid); + + expect(result).to.be.true; + }); + + it('should accept a request with placementCode and PublisherId as valid', function() { + let bid = {placementCode: 'panorama_d_1', params: {publisherId: '26947112-2289-405D-88C1-A7340C57E63E'}}; + + let result = spec.isBidRequestValid(bid); + + expect(result).to.be.true; + }); + + it('should not accept a request with adUnitName, adUnitCode, placementCode but no PublisherId as valid', function() { + let bid = {placementCode: 'panorama_d_1', adUnitCode: 'panorama_d_1', params: {adUnitName: 'panorama_d_1'}}; + + let result = spec.isBidRequestValid(bid); + + expect(result).to.be.false; + }); + }); + + describe('buildRequests', function() { + it('should make a well-formed single request object', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let result = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('https://lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + cookieSupport: true, + gdprApplies: false, + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should make a well-formed multiple request object', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let multiplebidRequest = clone(bidderRequest); + multiplebidRequest.bids.push(clone(bidderRequest.bids[0])); + multiplebidRequest.bids[1].adUnitCode = 'box_d_1'; + multiplebidRequest.bids[1].sizes = [[300, 250]]; + multiplebidRequest.bids[1].bidId = '3ffb201a808da7'; + delete multiplebidRequest.bids[1].params.adUnitId; + + let result = spec.buildRequests(multiplebidRequest.bids, multiplebidRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('https://lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + cookieSupport: true, + gdprApplies: false, + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }, { + callerAdUnitId: 'box_d_1', + bidId: '3ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 300, height: 250}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should make a well-formed single request object with AdUnitName', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + testbidRequest.bids[0].params.adUnitName = 'caller id 1'; + delete testbidRequest.bids[0].params.adUnitId; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('https://lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + cookieSupport: true, + gdprApplies: false, + adRequests: [{ + callerAdUnitId: 'caller id 1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should make a well-formed single request object with less parameters', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + delete testbidRequest.bids[0].params.seats; + delete testbidRequest.bids[0].params.adUnitId; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('https://lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + url: 'http://www.domain.com', + version: '1.1', + cookieSupport: true, + gdprApplies: false, + adRequests: [{ + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should make a well-formed single request object with less parameters, no publisherId', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + delete testbidRequest.bids[0].params.seats; + delete testbidRequest.bids[0].params.publisherId; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('https://lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + url: 'http://www.domain.com', + version: '1.1', + cookieSupport: true, + gdprApplies: false, + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should make a well-formed single request object with app parameters', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + delete testbidRequest.bids[0].params.seats; + delete testbidRequest.bids[0].params.adUnitId; + testbidRequest.bids[0].params.deviceId = 'deviceid'; + testbidRequest.bids[0].params.ifa = 'ifa'; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + url: 'http://www.domain.com', + version: '1.1', + deviceId: 'deviceid', + ifa: 'ifa', + cookieSupport: true, + gdprApplies: false, + adRequests: [{ + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should make a well-formed single request object with debug parameters', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + delete testbidRequest.bids[0].params.seats; + delete testbidRequest.bids[0].params.adUnitId; + testbidRequest.bids[0].params.tid = 'tracking id'; + testbidRequest.bids[0].params.test = true; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + url: 'http://www.domain.com', + version: '1.1', + tid: 'tracking id', + test: true, + cookieSupport: true, + gdprApplies: false, + adRequests: [{ + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should pass gdpr parameters', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testRequest = clone(bidderRequest); + testRequest.gdprConsent = { + gdprApplies: true, + consentString: 'test' + }; + let result = spec.buildRequests(testRequest.bids, testRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('https://lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + cookieSupport: true, + gdprApplies: true, + gdprConsent: 'test', + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should pass no cookie support', function() { + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => false); + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + let result = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('https://lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + gdprApplies: false, + cookieSupport: false, + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should pass no cookie support Safari', function() { + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => true); + let result = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('https://lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + gdprApplies: false, + cookieSupport: false, + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should use params.url, then config pageUrl, then getTopWindowUrl', function() { + let testRequest = clone(bidderRequest); + sandbox.stub(utils, 'getTopWindowUrl').callsFake(() => 'http://www.topurl.com'); + + let result = spec.buildRequests(testRequest.bids, testRequest); + let data = JSON.parse(result.data); + + expect(data.url).to.equal('http://www.domain.com'); + + delete testRequest.bids[0].params.url; + + result = spec.buildRequests(testRequest.bids, testRequest); + data = JSON.parse(result.data); + + expect(data.url).to.equal('http://www.topurl.com'); + + let origGetConfig = config.getConfig; + sandbox.stub(config, 'getConfig').callsFake(function (key) { + if (key === 'pageUrl') { + return 'http://www.configurl.com'; + } + return origGetConfig.apply(config, arguments); + }); + + result = spec.buildRequests(testRequest.bids, testRequest); + data = JSON.parse(result.data); + + expect(data.url).to.equal('http://www.configurl.com'); + }); + }); + + describe('interpretResponse', function () { + it('should handle single success response', function() { + let lwResponse = { + ads: [ + { + id: '28e5ddf4-3c01-11e8-86a7-0a44794250d4', + callerId: 'site_outsider_0', + tag: 'ad', + width: 300, + height: 250, + cpmBid: 2.565917, + bidId: '32e50fad901ae89', + auctionId: '13e674db-d4d8-4e19-9d28-ff38177db8bf', + creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', + ttl: 120 + } + ], + currency: 'USD' + }; + + let expectedResponse = [{ + requestId: '32e50fad901ae89', + bidderCode: 'livewrapped', + cpm: 2.565917, + width: 300, + height: 250, + ad: 'ad', + ttl: 120, + creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', + netRevenue: true, + currency: 'USD' + }]; + + let bids = spec.interpretResponse({body: lwResponse}); + + expect(bids).to.deep.equal(expectedResponse); + }) + + it('should handle multiple success response', function() { + let lwResponse = { + ads: [ + { + id: '28e5ddf4-3c01-11e8-86a7-0a44794250d4', + callerId: 'site_outsider_0', + tag: 'ad1', + width: 300, + height: 250, + cpmBid: 2.565917, + bidId: '32e50fad901ae89', + auctionId: '13e674db-d4d8-4e19-9d28-ff38177db8bf', + creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', + ttl: 120 + }, + { + id: '38e5ddf4-3c01-11e8-86a7-0a44794250d4', + callerId: 'site_outsider_1', + tag: 'ad2', + width: 980, + height: 240, + cpmBid: 3.565917, + bidId: '42e50fad901ae89', + auctionId: '13e674db-d4d8-4e19-9d28-ff38177db8bf', + creativeId: '62cbd598-2715-4c43-a06f-229fc170f945:427077', + ttl: 120 + } + ], + currency: 'USD' + }; + + let expectedResponse = [{ + requestId: '32e50fad901ae89', + bidderCode: 'livewrapped', + cpm: 2.565917, + width: 300, + height: 250, + ad: 'ad1', + ttl: 120, + creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', + netRevenue: true, + currency: 'USD' + }, { + requestId: '42e50fad901ae89', + bidderCode: 'livewrapped', + cpm: 3.565917, + width: 980, + height: 240, + ad: 'ad2', + ttl: 120, + creativeId: '62cbd598-2715-4c43-a06f-229fc170f945:427077', + netRevenue: true, + currency: 'USD' + }]; + + let bids = spec.interpretResponse({body: lwResponse}); + + expect(bids).to.deep.equal(expectedResponse); + }) + }); + + describe('user sync', function () { + let serverResponses; + + beforeEach(function () { + serverResponses = [{ + body: { + pixels: [ + {type: 'Redirect', url: 'http://pixelsync'}, + {type: 'Iframe', url: 'http://iframesync'} + ] + } + }]; + }); + + it('should return empty if no server responses', function() { + let syncs = spec.getUserSyncs({ + pixelEnabled: true, + iframeEnabled: true + }, []); + + let expectedResponse = []; + + expect(syncs).to.deep.equal(expectedResponse) + }); + + it('should return empty if no user sync', function() { + let syncs = spec.getUserSyncs({ + pixelEnabled: true, + iframeEnabled: true + }, [{body: {}}]); + + let expectedResponse = []; + + expect(syncs).to.deep.equal(expectedResponse) + }); + + it('should returns pixel and iframe user sync', function() { + let syncs = spec.getUserSyncs({ + pixelEnabled: true, + iframeEnabled: true + }, serverResponses); + + let expectedResponse = [{type: 'image', url: 'http://pixelsync'}, {type: 'iframe', url: 'http://iframesync'}]; + + expect(syncs).to.deep.equal(expectedResponse) + }); + + it('should returns pixel only if iframe not supported user sync', function() { + let syncs = spec.getUserSyncs({ + pixelEnabled: true, + iframeEnabled: false + }, serverResponses); + + let expectedResponse = [{type: 'image', url: 'http://pixelsync'}]; + + expect(syncs).to.deep.equal(expectedResponse) + }); + + it('should returns iframe only if pixel not supported user sync', function() { + let syncs = spec.getUserSyncs({ + pixelEnabled: false, + iframeEnabled: true + }, serverResponses); + + let expectedResponse = [{type: 'iframe', url: 'http://iframesync'}]; + + expect(syncs).to.deep.equal(expectedResponse) + }); + }); +}); + +function clone(obj) { + return JSON.parse(JSON.stringify(obj)); +} From 4797ea2953612e915d9119ffa00393f7d417b5a3 Mon Sep 17 00:00:00 2001 From: Andrew Bowman Date: Tue, 9 Oct 2018 11:31:47 -0400 Subject: [PATCH 0744/1594] Adding appnexus debug via cookie/params (#3152) * adding appnexus debug via cookie/params * removing nested object * added documentation link and removed useless conditional * fix lint error on documentation message --- modules/appnexusBidAdapter.js | 57 ++++++++++++++++++++ test/spec/modules/appnexusBidAdapter_spec.js | 28 +++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index aaec207dc1e..f65a3409684 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -11,6 +11,7 @@ const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', 'startdelay', 'skippable', 'playback_method', 'frameworks']; const USER_PARAMS = ['age', 'external_uid', '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 NATIVE_MAPPING = { body: 'description', cta: 'ctatext', @@ -77,6 +78,32 @@ export const spec = { }; } + let debugObj = {}; + let debugObjParams = {}; + const debugCookieName = 'apn_prebid_debug'; + const debugCookie = getCookie(debugCookieName) || null; + + if (debugCookie) { + try { + debugObj = JSON.parse(debugCookie); + } catch (e) { + utils.logError('AppNexus Debug Auction Cookie Error:\n\n' + e); + } + } else { + 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; @@ -99,6 +126,11 @@ export const spec = { payload.app = appIdObj; } + if (debugObjParams.enabled) { + payload.debug = debugObjParams; + utils.logInfo('AppNexus 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 = { @@ -154,6 +186,22 @@ export const spec = { } }); } + + 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 + utils.logMessage('AppNexus Debug Auction Glossary: https://wiki.appnexus.com/x/qwmHAg'); + utils.logMessage(debugText); + } + return bids; }, @@ -429,6 +477,15 @@ function hasAppId(bid) { return !!bid.params.app } +function hasDebug(bid) { + return !!bid.debug +} + +function getCookie(name) { + let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); + return m ? decodeURIComponent(m[2]) : null; +} + function getRtbBid(tag) { return tag && tag.ads && tag.ads.length && find(tag.ads, ad => ad.rtb); } diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 9be87ac8628..0d7c670ee8a 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -396,7 +396,33 @@ describe('AppNexusAdapter', function () { rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') }); }); - }) + + it('adds debug auction settings to payload', () => { + let debugRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394' + }, + debug: { + enabled: true, + dongle: 'QWERTY', + member_id: 958, + debug_timeout: 1000 + } + } + ); + const request = spec.buildRequests([debugRequest]); + const payload = JSON.parse(request.data); + expect(payload.debug).to.exist; + expect(payload.debug).to.deep.equal({ + enabled: true, + dongle: 'QWERTY', + member_id: 958, + debug_timeout: 1000 + }); + }); + }); describe('interpretResponse', function () { let response = { From e72e2dc1754c090b07922dafe61dd61cd6478be4 Mon Sep 17 00:00:00 2001 From: Js Date: Tue, 9 Oct 2018 21:31:50 +0200 Subject: [PATCH 0745/1594] Add RSA validation to Criteo FastBid (#3110) * Pass Prebid version to Criteo direct bidder * Update Criteo profile IDs * Add RSA verification to Criteo FastBid * Update package-lock with jsencrypt and crypto-js * Replacing all arrow functions in Mocha function calls * Update Adapter Version to 14 --- modules/criteoBidAdapter.js | 49 ++++++++++++++++++++-- package-lock.json | 10 +++++ package.json | 2 + test/spec/modules/criteoBidAdapter_spec.js | 19 ++++++++- 4 files changed, 75 insertions(+), 5 deletions(-) mode change 100644 => 100755 package.json diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 0595fc890f0..284c3f57406 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -3,8 +3,10 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { parse } from 'src/url'; import * as utils from 'src/utils'; import find from 'core-js/library/fn/array/find'; +import JSEncrypt from 'jsencrypt/bin/jsencrypt'; +import sha256 from 'crypto-js/sha256'; -const ADAPTER_VERSION = 11; +const ADAPTER_VERSION = 14; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -17,6 +19,13 @@ const PROFILE_ID_PUBLISHERTAG = 185; // Unminified source code can be found in: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js'; +export const FAST_BID_PUBKEY = `-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO1BjAITkFTtP0IMzmF7qsqhpu +y1dGaTPHnjMU9mRZsrnfR3C0sEN5pYEzEcFRPnkJjJuhH8Rnh5+CE+LcKg0Z8ZZ7 +OmOSj0/qnYTAYCu0cR5LiyWG79KlIgUyMbp92ulGg24gAyGrVn4+v/4c53WlOEUp +4YWvb82G0CD5NcDNpQIDAQAB +-----END PUBLIC KEY-----`; + /** @type {BidderSpec} */ export const spec = { code: BIDDER_CODE, @@ -251,6 +260,34 @@ function createNativeAd(id, payload, callback) { `; } +export function cryptoVerify(key, hash, code) { + var jse = new JSEncrypt(); + jse.setPublicKey(key); + return jse.verify(code, hash, sha256); +} + +function validateFastBid(fastBid) { + // The value stored must contain the file's encrypted hash as first line + const firstLineEnd = fastBid.indexOf('\n'); + const firstLine = fastBid.substr(0, firstLineEnd).trim(); + if (firstLine.substr(0, 9) !== '// Hash: ') { + utils.logWarn('No hash found in FastBid'); + return false; + } + + // Remove the hash part from the locally stored value + const fileEncryptedHash = firstLine.substr(9); + const publisherTag = fastBid.substr(firstLineEnd + 1); + + // Verify the hash using cryptography + try { + return cryptoVerify(FAST_BID_PUBKEY, fileEncryptedHash, publisherTag); + } catch (e) { + utils.logWarn('Failed to verify Criteo FastBid'); + return undefined; + } +} + /** * @return {boolean} */ @@ -258,13 +295,17 @@ function tryGetCriteoFastBid() { try { const fastBid = localStorage.getItem('criteo_fast_bid'); if (fastBid !== null) { - eval(fastBid); // eslint-disable-line no-eval - return true; + if (validateFastBid(fastBid) === false) { + utils.logWarn('Invalid Criteo FastBid found'); + localStorage.removeItem('criteo_fast_bid'); + } else { + utils.logInfo('Using Criteo FastBid'); + eval(fastBid); // eslint-disable-line no-eval + } } } catch (e) { // Unable to get fast bid } - return false; } registerBidder(spec); diff --git a/package-lock.json b/package-lock.json index 58d408a6be4..f28ecb283eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2990,6 +2990,11 @@ "randomfill": "^1.0.3" } }, + "crypto-js": { + "version": "3.1.9-1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", + "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" + }, "css": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", @@ -8265,6 +8270,11 @@ "dev": true, "optional": true }, + "jsencrypt": { + "version": "3.0.0-rc.1", + "resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.0.0-rc.1.tgz", + "integrity": "sha512-gcvGaqerlUJy1Kq6tNgPYteVEoWNemu+9hBe2CdsCIz4rVcwjoTQ72iD1W76/PRMlnkzG0yVh7nwOOMOOUfKmg==" + }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", diff --git a/package.json b/package.json old mode 100644 new mode 100755 index 1b28a54f72a..c27e0dd48b9 --- a/package.json +++ b/package.json @@ -103,7 +103,9 @@ "dependencies": { "babel-plugin-transform-object-assign": "^6.22.0", "core-js": "^2.4.1", + "crypto-js": "^3.1.9-1", "gulp-sourcemaps": "^2.6.0", + "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2" } } diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index e232bf0e3d9..d124ebf3709 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec } from 'modules/criteoBidAdapter'; +import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter'; import * as utils from 'src/utils'; describe('The Criteo bidding adapter', function () { @@ -294,4 +294,21 @@ describe('The Criteo bidding adapter', function () { expect(bids[0].height).to.equal(90); }); }); + + describe('cryptoVerify', function () { + const TEST_HASH = 'vBeD8Q7GU6lypFbzB07W8hLGj7NL+p7dI9ro2tCxkrmyv0F6stNuoNd75Us33iNKfEoW+cFWypelr6OJPXxki2MXWatRhJuUJZMcK4VBFnxi3Ro+3a0xEfxE4jJm4eGe98iC898M+/YFHfp+fEPEnS6pEyw124ONIFZFrcejpHU='; + + it('should verify right signature', function () { + expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test')).to.equal(true); + }); + + it('should verify wrong signature', function () { + expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test wrong')).to.equal(false); + }); + + it('should return undefined with incompatible browsers', function () { + // Here use a null hash to make the call to crypto library fail and simulate a browser failure + expect(cryptoVerify(FAST_BID_PUBKEY, null, 'test')).to.equal.undefined; + }); + }); }); From 8fdf61da6acd70792bf81a7a3f94d6fa4f0a2c20 Mon Sep 17 00:00:00 2001 From: Kuldeep Kapade Date: Tue, 9 Oct 2018 12:33:07 -0700 Subject: [PATCH 0746/1594] Added support for user syncing pixel (#3092) * Added Polymorph adapter * Cleaned up code * Updated var to let * Updated with mediaType * Updated tests * Fixed tests * Updated polymorph adapter to support cookie syncing and network key integration * Fixed parens for lint * Fixed a bug related to network_key approach * Fixed double negation warning * Updated tests for network_key * Added bidId as cache buster and updated tests * Fixed tests --- modules/polymorphBidAdapter.js | 31 ++++++++++++++-- test/spec/modules/polymorphBidAdapter_spec.js | 36 +++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/modules/polymorphBidAdapter.js b/modules/polymorphBidAdapter.js index 8d07a66d0da..da5f7f711ec 100644 --- a/modules/polymorphBidAdapter.js +++ b/modules/polymorphBidAdapter.js @@ -2,8 +2,18 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { BANNER } from 'src/mediaTypes'; +const PROTOCOL = getProtocol(); const BIDDER_CODE = 'polymorph'; const URL = '//api.adsnative.com/v1/ad-template.json'; +const USER_SYNC_URL = PROTOCOL + '//rudy.adsnative.com/cm.gif'; + +function getProtocol() { + if (location.protocol && location.protocol.indexOf('https') === 0) { + return 'https:'; + } else { + return 'http:'; + } +} export const polymorphAdapterSpec = { code: BIDDER_CODE, @@ -17,7 +27,7 @@ export const polymorphAdapterSpec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function(bid) { - return !!(bid.params.placementId); + return !!(bid.params.placementId) || (!!(bid.params.network_key) && !!(bid.params.widget_id) && !!(bid.params.cat)); }, /** @@ -31,11 +41,18 @@ export const polymorphAdapterSpec = { var payload = { url: utils.getTopWindowUrl(), ref: utils.getTopFrameReferrer(), - zid: bid.params.placementId, sizes: bid.sizes, hb: 1, - hb_source: 'prebid' + hb_source: 'prebid', + bid_id: bid.bidId, }; + if (bid.params.placementId) { + payload.zid = bid.params.placementId; + } else if (bid.params.network_key && bid.params.widget_id && bid.params.cat) { + payload.network_key = bid.params.network_key; + payload.widget_id = bid.params.widget_id; + payload.cat = bid.params.cat; + } Object.keys(bid.params).forEach(function(key) { if (key != 'defaultWidth' && key != 'defaultHeight') { payload[key] = bid.params[key]; @@ -100,6 +117,14 @@ export const polymorphAdapterSpec = { utils.logError(e); } return bidResponses; + }, + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: USER_SYNC_URL + }]; + } } } diff --git a/test/spec/modules/polymorphBidAdapter_spec.js b/test/spec/modules/polymorphBidAdapter_spec.js index e2df44e8cfc..6fd4bd90288 100644 --- a/test/spec/modules/polymorphBidAdapter_spec.js +++ b/test/spec/modules/polymorphBidAdapter_spec.js @@ -5,6 +5,9 @@ import { newBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'polymorph'; const ENDPOINT_URL = '//api.adsnative.com/v1/ad-template.json'; const PLACEMENT_ID = 'ping'; +const NETWORK_KEY = 'abcd1234'; +const WIDGET_ID = 'xyz'; +const CATEGORIES = 'IAB1,IAB2'; const spec = newBidder(polymorphAdapterSpec).getSpec(); @@ -31,6 +34,19 @@ const bidRequests = [{ 'bidId': '30b31c1838de1d', 'bidderRequestId': '22edbae2733bf7', 'auctionId': '1d1a030790a476', +}, +{ + 'bidder': BIDDER_CODE, + 'params': { + 'network_key': NETWORK_KEY, + 'widget_id': WIDGET_ID, + 'cat': CATEGORIES + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[700, 250], [300, 600]], + 'bidId': '30b31c1838de1f', + 'bidderRequestId': '22edbae2733bf7', + 'auctionId': '1d1a030790a476', }]; describe('Polymorph adapter test', function () { @@ -45,6 +61,10 @@ describe('Polymorph adapter test', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); }); + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bidRequests[2])).to.equal(true); + }); + it('should return false if req has no placementId', function () { const invalidBidRequest = { bidder: BIDDER_CODE, @@ -79,6 +99,7 @@ describe('Polymorph adapter test', function () { expect(payload1.hb_source).to.equal('prebid'); expect(payload1.zid).to.equal(PLACEMENT_ID); expect(payload1.sizes).to.equal('300,250,300,600'); + expect(payload1.bid_id).to.equal('30b31c1838de1e'); var payload2 = {}; requests[1].data.replace(/([^=&]+)=([^&]*)/g, function(m, key, value) { @@ -90,6 +111,21 @@ describe('Polymorph adapter test', function () { expect(payload2.hb_source).to.equal('prebid'); expect(payload2.zid).to.equal(PLACEMENT_ID); expect(payload2.sizes).to.equal('700,250,300,600'); + expect(payload2.bid_id).to.equal('30b31c1838de1d'); + + var payload3 = {}; + requests[2].data.replace(/([^=&]+)=([^&]*)/g, function(m, key, value) { + payload3[decodeURIComponent(key)] = decodeURIComponent(value); + }); + expect(payload3.ref).to.not.be.undefined; + expect(payload3.url).to.not.be.undefined; + expect(payload3.hb).to.equal('1'); + expect(payload3.hb_source).to.equal('prebid'); + expect(payload3.network_key).to.equal(NETWORK_KEY); + expect(payload3.widget_id).to.equal(WIDGET_ID); + expect(payload3.cat).to.equal(CATEGORIES); + expect(payload3.sizes).to.equal('700,250,300,600'); + expect(payload3.bid_id).to.equal('30b31c1838de1f'); }); it('sends bid request to ENDPOINT via GET', function () { From a1f07e95e8637ef2b02222db3b852e4f59d2e5c6 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 9 Oct 2018 13:34:38 -0600 Subject: [PATCH 0747/1594] Small bugfix and cleanup for Prebid Server OpenRTB code (#3113) * change bid map to bid_id map and clean up openrtb in pbs * add src to bids in bid request when known --- modules/prebidServerBidAdapter/index.js | 26 +++++++++++++------------ src/adaptermanager.js | 7 ++++--- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 5d23a0366ea..7a1ff94644d 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -355,10 +355,8 @@ const LEGACY_PROTOCOL = { * Protocol spec for OpenRTB endpoint * e.g., https:///v1/openrtb2/auction */ +let bidIdMap = {}; const OPEN_RTB_PROTOCOL = { - - bidMap: {}, - buildRequest(s2sBidRequest, bidRequests, adUnits) { let imps = []; let aliases = {}; @@ -368,8 +366,7 @@ const OPEN_RTB_PROTOCOL = { adUnit.bids.forEach(bid => { // OpenRTB response contains the adunit code and bidder name. These are // combined to create a unique key for each bid since an id isn't returned - const key = `${adUnit.code}${bid.bidder}`; - this.bidMap[key] = bid; + bidIdMap[`${adUnit.code}${bid.bidder}`] = bid.bid_id; // check for and store valid aliases to add to the request if (adaptermanager.aliasRegistry[bid.bidder]) { @@ -481,17 +478,22 @@ const OPEN_RTB_PROTOCOL = { // a seatbid object contains a `bid` array and a `seat` string response.seatbid.forEach(seatbid => { (seatbid.bid || []).forEach(bid => { - const bidRequest = utils.getBidRequest( - this.bidMap[`${bid.impid}${seatbid.seat}`].bid_id, - bidderRequests - ); + 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 ? STATUS.GOOD : STATUS.NO_BID; - let bidObject = bidfactory.createBid(status, bidRequest); + let bidObject = bidfactory.createBid(status, bidRequest || { + bidder: seatbid.seat, + src: TYPE + }); - bidObject.source = TYPE; - bidObject.bidderCode = seatbid.seat; bidObject.cpm = cpm; let serverResponseTimeMs = utils.deepAccess(response, ['ext', 'responsetimemillis', seatbid.seat].join('.')); diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 32cbc55cd8f..8d07e0ccacc 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -47,7 +47,7 @@ function getLabels(bidOrAdUnit, activeLabels) { return {labelAll: false, labels: bidOrAdUnit.labelAny, activeLabels}; } -function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { +function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels, src}) { return adUnits.reduce((result, adUnit) => { let { active, @@ -111,6 +111,7 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { bidId: bid.bid_id || utils.getUniqueIdentifierStr(), bidderRequestId, auctionId, + src, bidRequestsCount: adunitCounter.getCounter(adUnit.code), })); } @@ -207,7 +208,7 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, auctionId, bidderRequestId, tid, - bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': utils.deepClone(adUnitsS2SCopy), labels}), + bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': utils.deepClone(adUnitsS2SCopy), labels, src: CONSTANTS.S2S.SRC}), auctionStart: auctionStart, timeout: _s2sConfig.timeout, src: CONSTANTS.S2S.SRC, @@ -242,7 +243,7 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, bidderCode, auctionId, bidderRequestId, - bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': utils.deepClone(adUnitsClientCopy), labels}), + bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': utils.deepClone(adUnitsClientCopy), labels, src: 'client'}), auctionStart: auctionStart, timeout: cbTimeout, refererInfo From f466b8cfe44a8d5efbd595d1d5023a4842364f13 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 9 Oct 2018 16:01:02 -0400 Subject: [PATCH 0748/1594] Revert "Adding appnexus debug via cookie/params" (#3164) * Revert "Small bugfix and cleanup for Prebid Server OpenRTB code (#3113)" This reverts commit a1f07e95e8637ef2b02222db3b852e4f59d2e5c6. * Revert "Added support for user syncing pixel (#3092)" This reverts commit 8fdf61da6acd70792bf81a7a3f94d6fa4f0a2c20. * Revert "Add RSA validation to Criteo FastBid (#3110)" This reverts commit e72e2dc1754c090b07922dafe61dd61cd6478be4. * Revert "Adding appnexus debug via cookie/params (#3152)" This reverts commit 4797ea2953612e915d9119ffa00393f7d417b5a3. --- modules/appnexusBidAdapter.js | 57 -------------------- test/spec/modules/appnexusBidAdapter_spec.js | 28 +--------- 2 files changed, 1 insertion(+), 84 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index f65a3409684..aaec207dc1e 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -11,7 +11,6 @@ const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', 'startdelay', 'skippable', 'playback_method', 'frameworks']; const USER_PARAMS = ['age', 'external_uid', '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 NATIVE_MAPPING = { body: 'description', cta: 'ctatext', @@ -78,32 +77,6 @@ export const spec = { }; } - let debugObj = {}; - let debugObjParams = {}; - const debugCookieName = 'apn_prebid_debug'; - const debugCookie = getCookie(debugCookieName) || null; - - if (debugCookie) { - try { - debugObj = JSON.parse(debugCookie); - } catch (e) { - utils.logError('AppNexus Debug Auction Cookie Error:\n\n' + e); - } - } else { - 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; @@ -126,11 +99,6 @@ export const spec = { payload.app = appIdObj; } - if (debugObjParams.enabled) { - payload.debug = debugObjParams; - utils.logInfo('AppNexus 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 = { @@ -186,22 +154,6 @@ export const spec = { } }); } - - 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 - utils.logMessage('AppNexus Debug Auction Glossary: https://wiki.appnexus.com/x/qwmHAg'); - utils.logMessage(debugText); - } - return bids; }, @@ -477,15 +429,6 @@ function hasAppId(bid) { return !!bid.params.app } -function hasDebug(bid) { - return !!bid.debug -} - -function getCookie(name) { - let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); - return m ? decodeURIComponent(m[2]) : null; -} - function getRtbBid(tag) { return tag && tag.ads && tag.ads.length && find(tag.ads, ad => ad.rtb); } diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 0d7c670ee8a..9be87ac8628 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -396,33 +396,7 @@ describe('AppNexusAdapter', function () { rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') }); }); - - it('adds debug auction settings to payload', () => { - let debugRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394' - }, - debug: { - enabled: true, - dongle: 'QWERTY', - member_id: 958, - debug_timeout: 1000 - } - } - ); - const request = spec.buildRequests([debugRequest]); - const payload = JSON.parse(request.data); - expect(payload.debug).to.exist; - expect(payload.debug).to.deep.equal({ - enabled: true, - dongle: 'QWERTY', - member_id: 958, - debug_timeout: 1000 - }); - }); - }); + }) describe('interpretResponse', function () { let response = { From 5736e8376b0abab67fc6c2aa9fe4be6f6a4edf83 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Tue, 9 Oct 2018 16:15:46 -0400 Subject: [PATCH 0749/1594] add bid ttl to cache call (#3163) --- src/videoCache.js | 3 ++- test/spec/videoCache_spec.js | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/videoCache.js b/src/videoCache.js index cec2a3ec864..bc70397fc94 100644 --- a/src/videoCache.js +++ b/src/videoCache.js @@ -62,7 +62,8 @@ function toStorageRequest(bid) { const vastValue = bid.vastXml ? bid.vastXml : wrapURI(bid.vastUrl, bid.vastImpUrl); return { type: 'xml', - value: vastValue + value: vastValue, + ttlseconds: Number(bid.ttl) }; } diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index c9052fbbf9d..b9c2d445646 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -100,7 +100,7 @@ describe('The video cache', function () { `; - assertRequestMade({ vastUrl: 'my-mock-url.com' }, expectedValue) + assertRequestMade({ vastUrl: 'my-mock-url.com', ttl: 25 }, expectedValue) }); it('should make the expected request when store() is called on an ad with a vastUrl and a vastImpUrl', function () { @@ -114,12 +114,12 @@ describe('The video cache', function () { `; - assertRequestMade({ vastUrl: 'my-mock-url.com', vastImpUrl: 'imptracker.com' }, expectedValue) + assertRequestMade({ vastUrl: 'my-mock-url.com', vastImpUrl: 'imptracker.com', ttl: 25 }, expectedValue) }); it('should make the expected request when store() is called on an ad with vastXml', function () { const vastXml = ''; - assertRequestMade({ vastXml: vastXml }, vastXml); + assertRequestMade({ vastXml: vastXml, ttl: 25 }, vastXml); }); function assertRequestMade(bid, expectedValue) { @@ -134,6 +134,7 @@ describe('The video cache', function () { puts: [{ type: 'xml', value: expectedValue, + ttlseconds: 25 }], }); } From 24dd19aef0867972544e9f40fa18f2fa2f4578e4 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 9 Oct 2018 16:36:38 -0400 Subject: [PATCH 0750/1594] Render outstream safeframe (#3159) * render outstream safeframe * move code to Renderer module * some more logic to move --- src/Renderer.js | 18 ++++++++++++++++++ src/prebid.js | 5 +++-- src/secureCreatives.js | 9 ++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Renderer.js b/src/Renderer.js index 3ef0be5ae4d..3a156b2b86e 100644 --- a/src/Renderer.js +++ b/src/Renderer.js @@ -76,3 +76,21 @@ Renderer.prototype.process = function() { } } }; + +/** + * Checks whether creative rendering should be done by Renderer or not. + * @param {Object} renderer Renderer object installed by adapter + * @returns {Boolean} + */ +export function isRendererRequired(renderer) { + return !!(renderer && renderer.url); +} + +/** + * Render the bid returned by the adapter + * @param {Object} renderer Renderer object installed by adapter + * @param {Object} bid Bid response + */ +export function executeRenderer(renderer, bid) { + renderer.render(bid); +} diff --git a/src/prebid.js b/src/prebid.js index 5993073e474..48d08719cb1 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -12,6 +12,7 @@ import { createHook } from 'src/hook'; import { sessionLoader } from 'src/debugging'; import includes from 'core-js/library/fn/array/includes'; import { adunitCounter } from './adUnits'; +import { isRendererRequired, executeRenderer } from './Renderer'; const $$PREBID_GLOBAL$$ = getGlobal(); const CONSTANTS = require('./constants.json'); @@ -248,8 +249,8 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { const creativeComment = document.createComment(`Creative ${bid.creativeId} served by ${bid.bidder} Prebid.js Header Bidding`); utils.insertElement(creativeComment, doc, 'body'); - if (renderer && renderer.url) { - renderer.render(bid); + if (isRendererRequired(renderer)) { + executeRenderer(renderer, bid); } 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(PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid); diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 1038afdf46a..415fbc17c63 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -9,6 +9,7 @@ import { EVENTS } from './constants'; import { isSlotMatchingAdUnitCode } from './utils'; import { auctionManager } from './auctionManager'; import find from 'core-js/library/fn/array/find'; +import { isRendererRequired, executeRenderer } from './Renderer'; const BID_WON = EVENTS.BID_WON; @@ -53,9 +54,11 @@ function receiveMessage(ev) { } function sendAdToCreative(adObject, remoteDomain, source) { - const { adId, ad, adUrl, width, height } = adObject; - - if (adId) { + const { adId, ad, adUrl, width, height, renderer } = adObject; + // rendering for outstream safeframe + if (isRendererRequired(renderer)) { + executeRenderer(renderer, adObject); + } else if (adId) { resizeRemoteCreative(adObject); source.postMessage(JSON.stringify({ message: 'Prebid Response', From b66e2410df6a197777ecabefb9264a2b5d59f9fe Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 9 Oct 2018 16:43:40 -0400 Subject: [PATCH 0751/1594] Prebid 1.27.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c27e0dd48b9..b0d4380f44f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.27.0-pre", + "version": "1.27.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From a4d91fd74cfc2baac33974caa0fd31fb53d9407a Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 9 Oct 2018 16:51:27 -0400 Subject: [PATCH 0752/1594] increment Prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b0d4380f44f..50e6105099b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.27.0", + "version": "1.28.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 7f949288a40b48654c191aa2608ea014c442f479 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 9 Oct 2018 14:36:17 -0700 Subject: [PATCH 0753/1594] rubiconBidAdapter - Checking FPD values are defined before toString() (#3165) * rubiconBidAdapter - Checking FPD values are defined before toString() - Added two tests for this behavior * Removing unused variable * changed to compare against null added some null params to the tests to verify --- modules/rubiconBidAdapter.js | 8 ++- test/spec/modules/rubiconBidAdapter_spec.js | 66 +++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 7f219886057..e54b4999144 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -341,14 +341,18 @@ export const spec = { // visitor properties if (params.visitor !== null && typeof params.visitor === 'object') { Object.keys(params.visitor).forEach((key) => { - data[`tg_v.${key}`] = params.visitor[key].toString(); + if (params.visitor[key] != null) { + data[`tg_v.${key}`] = params.visitor[key].toString(); // initialize array; + } }); } // inventory properties if (params.inventory !== null && typeof params.inventory === 'object') { Object.keys(params.inventory).forEach((key) => { - data[`tg_i.${key}`] = params.inventory[key].toString(); + if (params.inventory[key] != null) { + data[`tg_i.${key}`] = params.inventory[key].toString(); + } }); } diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 70790eaa46f..9988d983bf9 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -818,6 +818,72 @@ describe('the rubicon adapter', function () { }); }); + describe('first party data', function () { + it('should not have any tg_v or tg_i params if all are undefined', function () { + let params = { + inventory: { + rating: null, + prodtype: undefined + }, + visitor: { + ucat: undefined, + lastsearch: null, + likes: undefined + }, + }; + + // Overwrite the bidder request params with the above ones + Object.assign(bidderRequest.bids[0].params, params); + + // get the built request + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); + + // make sure that no tg_v or tg_i keys are present in the request + let matchingExp = RegExp('^tg_(i|v)\..*$') + Object.keys(data).forEach(key => { + expect(key).to.not.match(matchingExp); + }); + }); + + it('should contain valid params when some are undefined', function () { + let params = { + inventory: { + rating: undefined, + prodtype: ['tech', 'mobile'] + }, + visitor: { + ucat: null, + lastsearch: 'iphone', + likes: undefined + }, + }; + let undefinedKeys = ['tg_i.rating', 'tg_v.ucat', 'tg_v.likes'] + let expectedQuery = { + 'tg_v.lastsearch': 'iphone', + 'tg_i.prodtype': 'tech,mobile', + } + + // Overwrite the bidder request params with the above ones + Object.assign(bidderRequest.bids[0].params, params); + + // get the built request + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); + + // make sure none of the undefined keys are in query + undefinedKeys.forEach(key => { + expect(typeof data[key]).to.equal('undefined'); + }); + + // make sure the expected and defined ones do show up still + Object.keys(expectedQuery).forEach(key => { + let value = expectedQuery[key]; + expect(data[key]).to.equal(value); + }); + }); + }); + describe('singleRequest config', function () { it('should group all bid requests with the same site id', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); From 18107d8f1807b3dd0b84a9ea54a7f21b9a2d8d30 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Wed, 10 Oct 2018 10:19:23 -0700 Subject: [PATCH 0754/1594] Adding mediaType param to parseSizes in order to ALWAYS get the correct parse Size method correct. (#3166) --- modules/rubiconBidAdapter.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index e54b4999144..122164f6a09 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -111,7 +111,7 @@ export const spec = { bidRequest.startTime = new Date().getTime(); let params = bidRequest.params; - let size = parseSizes(bidRequest); + let size = parseSizes(bidRequest, 'video'); let data = { page_url: _getPageUrl(bidRequest, bidderRequest), @@ -306,7 +306,7 @@ export const spec = { const params = bidRequest.params; // use rubicon sizes if provided, otherwise adUnit.sizes - const parsedSizes = parseSizes(bidRequest); + const parsedSizes = parseSizes(bidRequest, 'banner'); const [latitude, longitude] = params.latLong || []; @@ -529,9 +529,9 @@ function _renderCreative(script, impId) { `; } -function parseSizes(bid) { +function parseSizes(bid, mediaType) { let params = bid.params; - if (hasVideoMediaType(bid)) { + if (mediaType === 'video') { let size = []; if (params.video && params.video.playerWidth && params.video.playerHeight) { size = [ @@ -624,7 +624,7 @@ function bidType(bid, log = false) { return undefined; } } - if (parseSizes(bid).length > 0) { + if (parseSizes(bid, 'banner').length > 0) { if (log && validVideo === false) { utils.logWarn('Rubicon bid adapter Warning: invalid video requested for adUnit, continuing with banner request.'); } From 2903eb08fb04e4fda605d41fe5a96ac742814c46 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Thu, 11 Oct 2018 06:12:35 -0700 Subject: [PATCH 0755/1594] PubMatic to support DigiTrust Id passing (#3160) * in-dev changes * included config * Unit test cases for DigitrustId passing in PubMatic bid adapter * eslint fixes * removed a comment * replaced "() => {" with "() => {" --- modules/pubmaticBidAdapter.js | 43 +++++ test/spec/modules/pubmaticBidAdapter_spec.js | 192 +++++++++++++++++++ 2 files changed, 235 insertions(+) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 452f6149091..354addc6def 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; import { BANNER, VIDEO } from 'src/mediaTypes'; +import {config} from 'src/config'; const constants = require('src/constants.json'); const BIDDER_CODE = 'pubmatic'; @@ -8,6 +9,7 @@ const ENDPOINT = '//hbopenbid.pubmatic.com/translator?source=prebid-client'; const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const DEFAULT_CURRENCY = 'USD'; const AUCTION_TYPE = 1; +const PUBMATIC_DIGITRUST_KEY = 'nFIn8aLzbd'; const UNDEFINED = undefined; const CUSTOM_PARAMS = { 'kadpageurl': '', // Custom page url @@ -275,6 +277,45 @@ function _createImpressionObject(bid, conf) { return impObj; } +function _getDigiTrustObject(key) { + function getDigiTrustId() { + let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: key})); + return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; + } + let digiTrustId = getDigiTrustId(); + // Verify there is an ID and this user has not opted out + if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { + return null; + } + return digiTrustId; +} + +function _handleDigitrustId(eids) { + let digiTrustId = _getDigiTrustObject(PUBMATIC_DIGITRUST_KEY); + if (digiTrustId !== null) { + eids.push({ + 'source': 'digitru.st', + 'uids': [ + { + 'id': digiTrustId.id || '', + 'atype': 1, + 'ext': { + 'keyv': parseInt(digiTrustId.keyv) || 0 + } + } + ] + }); + } +} + +function _handleEids(payload) { + let eids = []; + _handleDigitrustId(eids); + if (eids.length > 0) { + payload.user.eids = eids; + } +} + export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER, VIDEO], @@ -414,6 +455,8 @@ export const spec = { utils.logWarn(BIDDER_CODE + ': dctr value not found in 1st adunit, ignoring values from subsequent adunits'); } + _handleEids(payload); + return { method: 'POST', url: ENDPOINT, diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index be3b59c1a80..4fca6656e46 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec} from 'modules/pubmaticBidAdapter'; import * as utils from 'src/utils'; +import {config} from 'src/config'; const constants = require('src/constants.json'); describe('PubMatic adapter', function () { @@ -448,6 +449,197 @@ describe('PubMatic adapter', function () { expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid }); + it('Request should have digitrust params', function() { + window.DigiTrust = { + getUser: function () { + } + }; + var bidRequest = {}; + let sandbox = sinon.sandbox.create(); + sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => + ({ + success: true, + identity: { + privacy: {optout: false}, + id: 'testId', + keyv: 4 + } + }) + ); + + let request = spec.buildRequests(bidRequests, bidRequest); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'digitru.st', + 'uids': [{ + 'id': 'testId', + 'atype': 1, + 'ext': { + 'keyv': 4 + } + }] + }]); + sandbox.restore(); + delete window.DigiTrust; + }); + + it('Request should not have digitrust params when DigiTrust not loaded', function() { + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + }); + + it('Request should not have digitrust params due to optout', function() { + window.DigiTrust = { + getUser: function () { + } + }; + let sandbox = sinon.sandbox.create(); + sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => + ({ + success: true, + identity: { + privacy: {optout: true}, + id: 'testId', + keyv: 4 + } + }) + ); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + sandbox.restore(); + delete window.DigiTrust; + }); + + it('Request should not have digitrust params due to failure', function() { + window.DigiTrust = { + getUser: function () { + } + }; + let sandbox = sinon.sandbox.create(); + sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => + ({ + success: false, + identity: { + privacy: {optout: false}, + id: 'testId', + keyv: 4 + } + }) + ); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + sandbox.restore(); + delete window.DigiTrust; + }); + + describe('DigiTrustId from config', function() { + var origGetConfig; + let sandbox; + beforeEach(() => { + sandbox = sinon.sandbox.create(); + window.DigiTrust = { + getUser: sandbox.spy() + }; + }); + + afterEach(() => { + sandbox.restore(); + delete window.DigiTrust; + }); + + it('Request should have digiTrustId config params', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + digiTrustId: { + success: true, + identity: { + privacy: {optout: false}, + id: 'testId', + keyv: 4 + } + } + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'digitru.st', + 'uids': [{ + 'id': 'testId', + 'atype': 1, + 'ext': { + 'keyv': 4 + } + }] + }]); + // should not have called DigiTrust.getUser() + expect(window.DigiTrust.getUser.notCalled).to.equal(true); + }); + + it('Request should not have digiTrustId config params due to optout', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + digiTrustId: { + success: true, + identity: { + privacy: {optout: true}, + id: 'testId', + keyv: 4 + } + } + } + return config[key]; + }); + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + // should not have called DigiTrust.getUser() + expect(window.DigiTrust.getUser.notCalled).to.equal(true); + }); + + it('Request should not have digiTrustId config params due to failure', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + digiTrustId: { + success: false, + identity: { + privacy: {optout: false}, + id: 'testId', + keyv: 4 + } + } + } + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + // should not have called DigiTrust.getUser() + expect(window.DigiTrust.getUser.notCalled).to.equal(true); + }); + + it('Request should not have digiTrustId config params if they do not exist', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = {}; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + // should have called DigiTrust.getUser() once + expect(window.DigiTrust.getUser.calledOnce).to.equal(true); + }); + }); + it('Request params check for video ad', function () { let request = spec.buildRequests(videoBidRequests); let data = JSON.parse(request.data); From 1e77957e8702d8b6839d6a82fd08b52912013612 Mon Sep 17 00:00:00 2001 From: lu-ruo Date: Thu, 11 Oct 2018 10:46:02 -0700 Subject: [PATCH 0756/1594] OpenX Adapter: Added support for pubcid (#3158) --- modules/openxBidAdapter.js | 6 ++++- test/spec/modules/openxBidAdapter_spec.js | 31 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 952e706ef7d..ee1fa58a4e9 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.4'; +const BIDDER_VERSION = '2.1.5'; let shouldSendBoPixel = true; @@ -222,6 +222,10 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { } } + if (bids[0].crumbs && bids[0].crumbs.pubcid) { + defaultParams.pubcid = bids[0].crumbs.pubcid; + } + return defaultParams; } diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index bce6b2e4acf..eff78b4d9a3 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -781,6 +781,37 @@ describe('OpenxAdapter', function () { const request = spec.buildRequests(bidRequestsWithDnt); expect(request[0].data.ns).to.equal(1); }); + + describe('publisher common id query param', function() { + it('should not send a pubcid query param when there is no crumbs.pubcid defined in the bid requests', function () { + const request = spec.buildRequests(bidRequestsWithMediaType); + expect(request[0].data).to.not.have.any.keys('pubcid'); + }); + + it('should send a pubcid query param when crumbs.pubcid is defined in the bid requests', function () { + const bidRequestsWithPubcid = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain' + }, + crumbs: { + pubcid: 'c4a4c843-2368-4b5e-b3b1-6ee4702b9ad6' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }]; + const request = spec.buildRequests(bidRequestsWithPubcid); + expect(request[0].data.pubcid).to.equal('c4a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); + }); + }) }); describe('buildRequests for video', function () { From 4585a93bf6bf882d3f4ed3b72b192c50cf60d772 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 11 Oct 2018 11:48:18 -0600 Subject: [PATCH 0757/1594] use version replace rather than package.json in widespace (#3143) --- modules/widespaceBidAdapter.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js index f40a541aeb0..91c0901b6e8 100644 --- a/modules/widespaceBidAdapter.js +++ b/modules/widespaceBidAdapter.js @@ -1,4 +1,3 @@ -import { version } from '../package.json'; import { config } from 'src/config'; import { registerBidder } from 'src/adapters/bidderFactory'; import { @@ -66,7 +65,7 @@ export const spec = { 'hb.floor': bid.bidfloor || '', 'hb.spb': i === 0 ? pixelSyncPossibility() : -1, 'hb.ver': WS_ADAPTER_VERSION, - 'hb.name': `prebidjs-${version}`, + 'hb.name': 'prebidjs-$prebid.version$', 'hb.bidId': bid.bidId, 'hb.sizes': parseSizesInput(bid.sizes).join(','), 'hb.currency': bid.params.cur || bid.params.currency || '' From 0c53a473964fcf618b14a77d5e09bef763c2b4a6 Mon Sep 17 00:00:00 2001 From: Cary White Date: Mon, 15 Oct 2018 09:17:12 -0700 Subject: [PATCH 0758/1594] Trafficroots Resubmit (#3141) circleci is still failing, but I cannot find a workaround for this PR at the moment --- modules/trafficrootsBidAdapter.js | 129 +++++++++++++++ modules/trafficrootsBidAdapter.md | 37 +++++ .../modules/trafficrootsBidAdapter_spec.js | 149 ++++++++++++++++++ 3 files changed, 315 insertions(+) create mode 100644 modules/trafficrootsBidAdapter.js create mode 100644 modules/trafficrootsBidAdapter.md create mode 100644 test/spec/modules/trafficrootsBidAdapter_spec.js diff --git a/modules/trafficrootsBidAdapter.js b/modules/trafficrootsBidAdapter.js new file mode 100644 index 00000000000..c931ef3b4a4 --- /dev/null +++ b/modules/trafficrootsBidAdapter.js @@ -0,0 +1,129 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; + +const TR_BIDDER_CODE = 'trafficroots'; +const TR_CURRENCY = 'USD'; +const TR_DEFAULT_BID_URL = '//service.trafficroots.com/prebid'; +const TR_TTL = 60; + +const LOCATION_PARAM_NAME = 'siteurl'; +const ID_PARAM_NAME = 'id'; +const IFRAME_PARAM_NAME = 'if'; +const ZONE_ID_PARAM_NAME = 'zoneId'; +const SIZE_PARAM_NAME = 'size'; +const KEYWORDS_PARAM_NAME = 'keywords'; +const MOBILE_PARAM_NAME = 'mobile'; +const TRID_PARAM_NAME = 'trid'; + +const ARRAY_PARAM_SEPARATOR = ';'; +const ARRAY_SIZE_SEPARATOR = ','; +const SIZE_SEPARATOR = 'x'; +const IS_MOBILE = window.navigator.userAgent.toLowerCase().indexOf('mobi'); + +let keywords = () => { + let clean = input => { + return input.replace(/\W/g, ' ').replace(/[ ]{2,}/g, ' ').trim(); + }; + let meta = name => { + let tag = document.querySelector("meta[name='" + name + "']"); + return (tag !== null) ? tag.getAttribute('content') : ''; + }; + return encodeURIComponent( + clean( + meta('keywords') + ' ' + meta('description') + ' ' + document.title + ) + ).substring(0, 400); +}; + +export const spec = { + code: TR_BIDDER_CODE, + isBidRequestValid: function(bid) { + return bid.params && !!bid.params.zoneId; + }, + + buildRequests: function(validBidRequests, bidderRequest) { + let deliveryUrl = ''; + const idParams = []; + const sizeParams = []; + const zoneIds = []; + let trid = ''; + if (window.localStorage) { + try { + var myid = window.localStorage.getItem('trafficroots:trid'); + if (myid) { + trid = myid; + } + } catch (ex) { + } + } + utils._each(validBidRequests, function(bid) { + if (!deliveryUrl && typeof bid.params.deliveryUrl === 'string') { + deliveryUrl = bid.params.deliveryUrl; + } + idParams.push(bid.bidId); + sizeParams.push(bid.sizes.map(size => size.join(SIZE_SEPARATOR)).join(ARRAY_SIZE_SEPARATOR)); + zoneIds.push(bid.params.zoneId); + }); + + if (!deliveryUrl) { + deliveryUrl = TR_DEFAULT_BID_URL; + } + + let data = { + [IFRAME_PARAM_NAME]: 0, + [LOCATION_PARAM_NAME]: utils.getTopWindowUrl(), + [SIZE_PARAM_NAME]: sizeParams.join(ARRAY_PARAM_SEPARATOR), + [ID_PARAM_NAME]: idParams.join(ARRAY_PARAM_SEPARATOR), + [ZONE_ID_PARAM_NAME]: zoneIds.join(ARRAY_PARAM_SEPARATOR), + [MOBILE_PARAM_NAME]: IS_MOBILE, + [KEYWORDS_PARAM_NAME]: decodeURIComponent(keywords()), + [TRID_PARAM_NAME]: trid + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + data.gdpr = { + applies: bidderRequest.gdprConsent.gdprApplies, + consent: bidderRequest.gdprConsent.consentString + }; + } + + return { + method: 'GET', + url: deliveryUrl, + data: data + }; + }, + + interpretResponse: function(serverResponses, request) { + const bidResponses = []; + var tridSet = false; + utils._each(serverResponses.body, function(response) { + if (!tridSet) { + try { + if (window.localStorage) { + window.localStorage.setItem('trafficroots:trid', response.trid); + tridSet = true; + } + } catch (ex) {} + } + if (response.cpm > 0) { + const bidResponse = { + requestId: response.id, + creativeId: response.id, + adId: response.id, + cpm: response.cpm, + width: response.width, + height: response.height, + currency: TR_CURRENCY, + netRevenue: true, + ttl: TR_TTL, + ad: response.ad + }; + bidResponses.push(bidResponse); + } + }); + return bidResponses; + } +}; + +registerBidder(spec); diff --git a/modules/trafficrootsBidAdapter.md b/modules/trafficrootsBidAdapter.md new file mode 100644 index 00000000000..2aceb0c866b --- /dev/null +++ b/modules/trafficrootsBidAdapter.md @@ -0,0 +1,37 @@ +# Overview + +Module Name: Trafficroots Bid Adapter + +Module Type: Bidder Adapter + +Maintainer: cary@trafficroots.com + +# Description + +Module that connects to Trafficroots demand sources + +# Test Parameters +```javascript + + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250],[300,600]], // a display size + bids: [ + { + bidder: 'trafficroots', + params: { + zoneId: 'aa0444af31', + deliveryUrl: location.protocol + '//service.trafficroots.com/prebid' + } + },{ + bidder: 'trafficroots', + params: { + zoneId: '8f527a4835', + deliveryUrl: location.protocol + '//service.trafficroots.com/prebid' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/trafficrootsBidAdapter_spec.js b/test/spec/modules/trafficrootsBidAdapter_spec.js new file mode 100644 index 00000000000..40d549e4a5a --- /dev/null +++ b/test/spec/modules/trafficrootsBidAdapter_spec.js @@ -0,0 +1,149 @@ +import { expect } from 'chai'; +import { spec } from 'modules/trafficrootsBidAdapter'; + +describe('trafficrootsAdapterTests', () => { + describe('bidRequestValidity', () => { + it('bidRequest with zoneId and deliveryUrl params', () => { + expect(spec.isBidRequestValid({ + bidder: 'trafficroots', + params: { + zoneId: 'aa0444af31', + deliveryUrl: 'https://service.trafficroosts.com/prebid' + } + })).to.equal(true); + }); + + it('bidRequest with only zoneId', () => { + expect(spec.isBidRequestValid({ + bidder: 'trafficroots', + params: { + zoneId: '8f527a4835' + } + })).to.equal(true); + }); + + it('bidRequest with only deliveryUrl', () => { + expect(spec.isBidRequestValid({ + bidder: 'trafficroots', + params: { + deliveryUrl: 'https://service.trafficroosts.com/prebid' + } + })).to.equal(false); + }); + }); + + describe('bidRequest', () => { + const bidRequests = [{ + 'bidder': 'trafficroots', + 'bidId': '29fa5c08928bde', + 'params': { + 'zoneId': 'aa0444af31', + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [[300, 250], [300, 600]], + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }, { + 'bidder': 'trafficroots', + 'bidId': '29fa5c08928bde', + 'params': { + 'zoneId': '8f527a4835', + 'deliveryUrl': 'https://service.trafficroosts.com/prebid' + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [[300, 250], [300, 600]], + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }]; + + it('bidRequest method', () => { + const request = spec.buildRequests(bidRequests); + expect(request.method).to.equal('GET'); + }); + + it('bidRequest url', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.match(new RegExp(`${bidRequests[1].params.deliveryUrl}`)); + }); + + it('bidRequest data', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data).to.exists; + }); + + it('bidRequest zoneIds', () => { + const request = spec.buildRequests(bidRequests); + expect(request.data.zoneId).to.equal('aa0444af31;8f527a4835'); + }); + + it('bidRequest gdpr consent', () => { + const consentString = 'consentString'; + const bidderRequest = { + bidderCode: 'trafficroots', + auctionId: '18fd8b8b0bd757', + bidderRequestId: '418b37f85e772c', + timeout: 3000, + gdprConsent: { + consentString: consentString, + gdprApplies: true + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.gdpr).to.exist; + expect(request.data.gdpr.applies).to.exist.and.to.be.true; + expect(request.data.gdpr.consent).to.exist.and.to.equal(consentString); + }); + }); + + describe('interpretResponse', () => { + const bidRequest = [{ + 'bidder': 'trafficroots', + 'bidId': '29fa5c08928bde', + 'params': { + 'zoneId': 'aa0444af31', + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [[300, 250], [300, 600]], + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }]; + + const bidResponse = { + body: [{ + 'id': 'div-gpt-ad-1460505748561-0', + 'ad': 'test ad', + 'width': 320, + 'height': 250, + 'cpm': 5.2 + }], + headers: {} + }; + + it('required keys', () => { + const result = spec.interpretResponse(bidResponse, bidRequest); + + let requiredKeys = [ + 'requestId', + 'creativeId', + 'adId', + 'cpm', + 'width', + 'height', + 'currency', + 'netRevenue', + 'ttl', + 'ad' + ]; + + let resultKeys = Object.keys(result[0]); + resultKeys.forEach(function(key) { + expect(requiredKeys.indexOf(key) !== -1).to.equal(true); + }); + }) + }); +}); From e530cbbc95977081b2864a5257df18fd6115e35c Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Tue, 16 Oct 2018 05:05:34 +0800 Subject: [PATCH 0759/1594] Rubicon skip video request in mutlti format when video is not setup (#3167) * Update rubiconBidAdapter.js --- modules/rubiconBidAdapter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 122164f6a09..90210ec4ac8 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -580,7 +580,11 @@ function mapSizes(sizes) { * @returns {boolean} */ export function hasVideoMediaType(bidRequest) { - return bidRequest.mediaType === VIDEO || typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'; + if (typeof utils.deepAccess(bidRequest, 'params.video') === 'undefined' && Array.isArray(utils.deepAccess(bidRequest, 'params.sizes'))) { + utils.logWarn('Rubicon bid adapter Warning: no video params found, convert to banner with the bidder size id'); + return false; + } + return (bidRequest.mediaType === VIDEO || typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'); } /** From cb668609b5678a829bc77af50f1810b0700efbc2 Mon Sep 17 00:00:00 2001 From: HolzAndrew Date: Mon, 15 Oct 2018 17:08:25 -0400 Subject: [PATCH 0760/1594] OpenXOutstream Bid Adapter (#3153) * adds openxoutstreamadapter files * cleans up url, adds bidder config and version, removes unused code * updates template ad response * remove final unused custom param code * add openrtb to list of params again. * add payload back so we can read bidId * extra checks for cpm (pub_rev) * adds unit tests * adds unit tests * update md page * undo openx adapter space changes from autosave * undo openx adapter space changes from autosave * test cleanup * test cleanup * update md file * update example page params * remove sneaky console.log * return false * adds yieldmo to the md. remove useless docEl assignment * remove useless docEl assignments * move crid and adid to constants * fix test * remove another useless variable assignment caught by LGTM * changes CR_ID. moves tdoc to within if scope * updates crid on test * use more constants and use crid for lfid * remove superfluous trailing argument * adds viewport meta tag to header. removes unnecessary string interpolation. * move ad_id to a string * undo changes for pacakge-lock * fixes lfid to lfId, pID to pId * fixes lfid to lfId, pID to pId * remove rti:1 * adds openx maintainer email --- integrationExamples/gpt/pbjs_example_gpt.html | 10 + modules/openxoutstreamBidAdapter.js | 214 ++++++++++++++++ modules/openxoutstreamBidAdapter.md | 41 +++ .../modules/openxoutstreamBidAdapter_spec.js | 238 ++++++++++++++++++ 4 files changed, 503 insertions(+) create mode 100644 modules/openxoutstreamBidAdapter.js create mode 100644 modules/openxoutstreamBidAdapter.md create mode 100644 test/spec/modules/openxoutstreamBidAdapter_spec.js diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index 536bc5a655d..88d4839d984 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -302,6 +302,16 @@ channelCode: 2264002816, //REQUIRED dimId: 9 //REQUIRED } + }, + { + bidder: 'openxoutstream', + params: { + unit: '53943996499', + delDomain: 'se-demo-d.openx.net', + publisher_page_url: 'yieldmo.com', + width: '300', + height: '250', + } } ] diff --git a/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js new file mode 100644 index 00000000000..6da234284c6 --- /dev/null +++ b/modules/openxoutstreamBidAdapter.js @@ -0,0 +1,214 @@ +import { config } from 'src/config'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; +import { BANNER } from 'src/mediaTypes'; + +const SUPPORTED_AD_TYPES = [BANNER]; +const BIDDER_CODE = 'openxoutstream'; +const BIDDER_CONFIG = 'hb_pb_ym'; +const BIDDER_VERSION = '1.0.0'; +const CURRENCY = 'USD'; +const NET_REVENUE = true; +const TIME_TO_LIVE = 300; +const YM_SCRIPT = `!function(e,t){if(void 0===t._ym){var a=Math.round(5*Math.random()/3)+'';t._ym='';var m=e.createElement('script');m.type='text/javascript',m.async=!0,m.src='//static.yieldmo.com/ym.'+a+'.js',(e.getElementsByTagName('head')[0]||e.getElementsByTagName('body')[0]).appendChild(m)}else t._ym instanceof String||void 0===t._ym.chkPls||t._ym.chkPls()}(document,window);`; +const PLACEMENT_ID = '1986307928000988495'; +const PUBLISHER_ID = '1986307525700126029'; +const CR_ID = '2052941939925262540'; +const AD_ID = '1991358644725162800'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: SUPPORTED_AD_TYPES, + isBidRequestValid: function(bidRequest) { + if (bidRequest.params.delDomain) { + return !!bidRequest.params.unit || utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes.length') > 0; + } + return false; + }, + buildRequests: function(bidRequests, bidderRequest) { + if (bidRequests.length === 0) { + return []; + } + let requests = []; + requests.push(buildOXBannerRequest(bidRequests, bidderRequest)); + return requests; + }, + interpretResponse: function(serverResponse, serverRequest) { + return handleVastResponse(serverResponse, serverRequest.payload) + }, + + transformBidParams: function(params, isOpenRtb) { + return utils.convertTypes({ + 'unit': 'string', + }, params); + } +}; + +function getViewportDimensions(isIfr) { + let width; + let height; + let tWin = window; + let body; + + if (isIfr) { + let tDoc; + try { + tWin = window.top; + tDoc = window.top.document; + } catch (e) { + return; + } + body = tDoc.body; + + width = tWin.innerWidth || docEl.clientWidth || body.clientWidth; + height = tWin.innerHeight || docEl.clientHeight || body.clientHeight; + } else { + width = tWin.innerWidth || docEl.clientWidth; + height = tWin.innerHeight || docEl.clientHeight; + } + + return `${width}x${height}`; +} + +function buildCommonQueryParamsFromBids(bids, bidderRequest) { + const isInIframe = utils.inIframe(); + let defaultParams; + defaultParams = { + ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), + jr: utils.getTopWindowReferrer(), + ch: document.charSet || document.characterSet, + res: `${screen.width}x${screen.height}x${screen.colorDepth}`, + ifr: isInIframe, + tz: new Date().getTimezoneOffset(), + tws: getViewportDimensions(isInIframe), + be: 1, + bc: bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, + auid: '540141567', + dddid: utils._map(bids, bid => bid.transactionId).join(','), + openrtb: '%7B%22mimes%22%3A%5B%22video%2Fmp4%22%5D%7D', + nocache: new Date().getTime() + }; + + if (utils.deepAccess(bidderRequest, 'gdprConsent')) { + let gdprConsentConfig = bidderRequest.gdprConsent; + + if (gdprConsentConfig.consentString !== undefined) { + defaultParams.gdpr_consent = gdprConsentConfig.consentString; + } + + if (gdprConsentConfig.gdprApplies !== undefined) { + defaultParams.gdpr = gdprConsentConfig.gdprApplies ? 1 : 0; + } + + if (config.getConfig('consentManagement.cmpApi') === 'iab') { + defaultParams.x_gdpr_f = 1; + } + } + + return defaultParams; +} + +function buildOXBannerRequest(bids, bidderRequest) { + let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); + queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); + + if (bids.some(bid => bid.params.doNotTrack)) { + queryParams.ns = 1; + } + + if (bids.some(bid => bid.params.coppa)) { + queryParams.tfcd = 1; + } + + let url = `https://${bids[0].params.delDomain}/v/1.0/avjp` + return { + method: 'GET', + url: url, + data: queryParams, + payload: {'bids': bids} + }; +} + +function handleVastResponse(response, serverResponse) { + const body = response.body + let bidResponses = []; + if (response !== undefined && body.vastUrl !== '' && body.pub_rev && body.pub_rev > 0) { + const openHtmlTag = ''; + const closeHtmlTag = ''; + const sdkScript = createSdkScript().outerHTML; + const placementDiv = createPlacementDiv(); + placementDiv.dataset.pId = PUBLISHER_ID; + const placementDivString = placementDiv.outerHTML; + const adResponse = getTemplateAdResponse(body.vastUrl); + const adResponseString = JSON.stringify(adResponse); + const ymAdsScript = ''; + + let bidResponse = {}; + bidResponse.requestId = serverResponse.bids[0].bidId; + bidResponse.bidderCode = BIDDER_CODE; + bidResponse.netRevenue = NET_REVENUE; + bidResponse.currency = CURRENCY; + bidResponse.cpm = Number(body.pub_rev) / 1000; + bidResponse.creativeId = body.adid; + bidResponse.height = body.height; + bidResponse.width = body.width; + bidResponse.vastUrl = body.vastUrl; + bidResponse.ttl = TIME_TO_LIVE; + bidResponse.mediaType = BANNER; + bidResponse.ad = openHtmlTag + placementDivString + ymAdsScript + sdkScript + closeHtmlTag; + + bidResponses.push(bidResponse); + } + return bidResponses; +} +registerBidder(spec); + +// HELPER FUNCTIONS +function createSdkScript() { + const script = document.createElement('script'); + script.innerHTML = YM_SCRIPT; + return script; +} +function createPlacementDiv() { + const div = document.createElement('div'); + div.id = `ym_${PLACEMENT_ID}`; + div.classList.add('ym'); + div.dataset.lfId = CR_ID; + return div +} + +/** + * Create a nativeplay template with the placement id and vastURL. + * @param vastUrl + */ +const getTemplateAdResponse = (vastUrl) => { + return { + availability_zone: 'us-east-1a', + data: [ + { + ads: [ + { + actions: {}, + adv_id: AD_ID, + configurables: { + cta_button_copy: 'Learn More', + vast_click_tracking: 'true', + vast_url: vastUrl, + }, + cr_id: CR_ID, + } + ], + column_count: 1, + configs: { + allowable_height: '248', + header_copy: 'You May Like', + ping: 'true', + }, + creative_format_id: 40, + css: '', + placement_id: PLACEMENT_ID, + } + ], + nc: 0, + }; +}; diff --git a/modules/openxoutstreamBidAdapter.md b/modules/openxoutstreamBidAdapter.md new file mode 100644 index 00000000000..a77b4560f97 --- /dev/null +++ b/modules/openxoutstreamBidAdapter.md @@ -0,0 +1,41 @@ +# Overview + +``` +Module Name: OpenX Outstream Bidder Adapter +Module Type: Bidder Adapter +Maintainer: opensource@yieldmo.com, jimmy.tu@openx.com +Note: Ads will only render in mobile +``` + +# Description + +Module that connects to OpenX's demand sources for outstream to Yieldmo. + +This bid adapter supports Banner. + +# Example +```javascript +var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], // a display size + mediaTypes: {'banner': {}}, + bids: [ + { + bidder: 'openxoutstream', + params: { + unit: '53943996499', + delDomain: 'se-demo-d.openx.net', + publisher_page_url: 'yieldmo.com', + width: '300', + height: '250', + } + } + ] + } +]; +``` + +# Additional Details +[Banner Ads](https://docs.openx.com/Content/developers/containers/prebid-adapter.html) + diff --git a/test/spec/modules/openxoutstreamBidAdapter_spec.js b/test/spec/modules/openxoutstreamBidAdapter_spec.js new file mode 100644 index 00000000000..a1d4f4aa2d4 --- /dev/null +++ b/test/spec/modules/openxoutstreamBidAdapter_spec.js @@ -0,0 +1,238 @@ +import {expect} from 'chai'; +import {spec} from 'modules/openxoutstreamBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +describe('OpenXOutstreamAdapter', function () { + const adapter = newBidder(spec); + const URLBASE = '/v/1.0/avjp'; + const BIDDER = 'openxoutstream'; + const div = document.createElement('div'); + const PLACEMENT_ID = '1986307928000988495'; + const YM_SCRIPT = `!function(e,t){if(void 0===t._ym){var a=Math.round(5*Math.random()/3)+'';t._ym='';var m=e.createElement('script');m.type='text/javascript',m.async=!0,m.src='//static.yieldmo.com/ym.'+a+'.js',(e.getElementsByTagName('head')[0]||e.getElementsByTagName('body')[0]).appendChild(m)}else t._ym instanceof String||void 0===t._ym.chkPls||t._ym.chkPls()}(document,window);`; + const PUBLISHER_ID = '1986307525700126029'; + const CR_ID = '2052941939925262540'; + const AD_ID = '1991358644725162800'; + + 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('when request is for a banner ad', function () { + let bannerBid; + beforeEach(function () { + bannerBid = { + bidder: BIDDER, + params: {}, + adUnitCode: 'adunit-code', + mediaTypes: {banner: {}}, + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475' + }; + }); + it('should return false when there is no delivery domain', function () { + bannerBid.params = {'unit': '12345678'}; + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); + }); + + describe('when there is a delivery domain', function () { + beforeEach(function () { + bannerBid.params = {delDomain: 'test-delivery-domain'} + }); + + it('should return false when there is no ad unit id and size', function () { + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); + }); + + it('should return true if there is an adunit id ', function () { + bannerBid.params.unit = '12345678'; + expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + }); + + it('should return true if there is no adunit id and sizes are defined', function () { + bannerBid.mediaTypes.banner.sizes = [720, 90]; + expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + }); + + it('should return false if no sizes are defined ', function () { + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); + }); + + it('should return false if sizes empty ', function () { + bannerBid.mediaTypes.banner.sizes = []; + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); + }); + }); + }); + }); + + describe('buildRequests for banner ads', function () { + const bidRequestsWithMediaType = [{ + 'bidder': BIDDER, + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + 'mediaType': 'banner', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + it('should send bid request to openx url via GET, with mediaType specified as banner', function () { + const request = spec.buildRequests(bidRequestsWithMediaType); + const params = bidRequestsWithMediaType[0].params; + expect(request[0].url).to.equal(`https://` + params.delDomain + URLBASE); + expect(request[0].method).to.equal('GET'); + }); + + it('should send ad unit ids when any are defined', function () { + const bidRequestsWithUnitIds = [{ + 'bidder': BIDDER, + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': BIDDER, + 'params': { + 'unit': '540141567', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithUnitIds); + expect(request[0].data.auid).to.equal(`${bidRequestsWithUnitIds[1].params.unit}`); + }); + + describe('interpretResponse', function () { + let serverResponse; + let serverRequest; + + beforeEach(function () { + serverResponse = { + body: { + width: 300, + height: 250, + pub_rev: 3000, + bidderCode: 'openxoutstream', + vastUrl: 'test.vast.url', + mediaType: 'banner', + adid: '9874652394875' + }, + header: 'header?', + }; + serverRequest = { + payload: { + bids: [{ + bidId: '2d36ac90d654af', + }], + } + }; + }); + + it('should correctly reorder the server response', function () { + const newResponse = spec.interpretResponse(serverResponse, serverRequest); + const openHtmlTag = ''; + const closeHtmlTag = ''; + const sdkScript = createSdkScript().outerHTML; + const placementDiv = createPlacementDiv(); + placementDiv.dataset.pId = PUBLISHER_ID; + const placementDivString = placementDiv.outerHTML; + const adResponse = getTemplateAdResponse(serverResponse.body.vastUrl, PLACEMENT_ID); + const adResponseString = JSON.stringify(adResponse); + const ymAdsScript = ''; + expect(newResponse.length).to.be.equal(1); + expect(newResponse[0]).to.deep.equal({ + requestId: '2d36ac90d654af', + bidderCode: 'openxoutstream', + vastUrl: 'test.vast.url', + mediaType: 'banner', + cpm: 3, + width: 300, + height: 250, + creativeId: '9874652394875', + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: openHtmlTag + placementDivString + ymAdsScript + sdkScript + closeHtmlTag + }); + }); + + it('should not add responses if the cpm is 0 or null', function () { + serverResponse.body.pub_rev = 0; + let response = spec.interpretResponse(serverResponse, serverRequest); + expect(response).to.deep.equal([]); + + serverResponse.body.pub_rev = null; + response = spec.interpretResponse(serverResponse, serverRequest); + expect(response).to.deep.equal([]) + }); + }); + }) + + function createSdkScript() { + const script = document.createElement('script'); + script.innerHTML = YM_SCRIPT; + return script; + } + function createPlacementDiv() { + div.id = `ym_${PLACEMENT_ID}`; + div.classList.add('ym'); + div.dataset.lfId = CR_ID; + return div + } + const getTemplateAdResponse = (vastUrl) => { + return { + availability_zone: 'us-east-1a', + data: [ + { + ads: [ + { + actions: {}, + adv_id: AD_ID, + configurables: { + cta_button_copy: 'Learn More', + vast_click_tracking: 'true', + vast_url: vastUrl, + }, + cr_id: CR_ID, + } + ], + column_count: 1, + configs: { + allowable_height: '248', + header_copy: 'You May Like', + ping: 'true', + }, + creative_format_id: 40, + css: '', + placement_id: PLACEMENT_ID, + } + ], + nc: 0, + }; + }; +}); From de597ae6630031e08953c0a993bbb1539399ba47 Mon Sep 17 00:00:00 2001 From: Marco Masotti Date: Tue, 16 Oct 2018 19:27:54 +0200 Subject: [PATCH 0761/1594] improves additional data passed to the handler in AuctionInit and AuctionEnd events (#3168) --- src/auction.js | 30 ++++++++++++++++++++++-------- test/spec/unit/pbjs_api_spec.js | 4 ++-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/auction.js b/src/auction.js index b9f3574ed31..50b681d61a8 100644 --- a/src/auction.js +++ b/src/auction.js @@ -96,6 +96,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) let _bidderRequests = []; let _bidsReceived = []; let _auctionStart; + let _auctionEnd; let _auctionId = utils.generateUUID(); let _auctionStatus; let _callback = callback; @@ -106,6 +107,22 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) function addBidRequests(bidderRequests) { _bidderRequests = _bidderRequests.concat(bidderRequests) }; function addBidReceived(bidsReceived) { _bidsReceived = _bidsReceived.concat(bidsReceived); } + function getProperties() { + return { + auctionId: _auctionId, + auctionStart: _auctionStart, + auctionEnd: _auctionEnd, + auctionStatus: _auctionStatus, + adUnits: _adUnits, + adUnitCodes: _adUnitCodes, + labels: _labels, + bidderRequests: _bidderRequests, + bidsReceived: _bidsReceived, + winningBids: _winningBids, + timeout: _timeout + }; + } + function startAuctionTimer() { const timedOut = true; const timeoutCallback = executeCallback.bind(null, timedOut); @@ -129,10 +146,12 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } - events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: _auctionId}); - try { _auctionStatus = AUCTION_COMPLETED; + _auctionEnd = Date.now(); + + events.emit(CONSTANTS.EVENTS.AUCTION_END, getProperties()); + const adUnitCodes = _adUnitCodes; const bids = _bidsReceived .filter(adUnitsFilter.bind(this, adUnitCodes)) @@ -185,12 +204,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) _auctionStatus = AUCTION_IN_PROGRESS; - const auctionInit = { - timestamp: _auctionStart, - auctionId: _auctionId, - timeout: _timeout - }; - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, getProperties()); let callbacks = auctionCallbacks(auctionDone, this); let boundObj = { diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index f113b8f0f45..1a791f8dd51 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1591,8 +1591,8 @@ describe('Unit: Prebid Module', function () { describe('emit', function () { it('should be able to emit event without arguments', function () { var spyEventsEmit = sinon.spy(events, 'emit'); - events.emit(CONSTANTS.EVENTS.AUCTION_END); - assert.ok(spyEventsEmit.calledWith('auctionEnd')); + events.emit(CONSTANTS.EVENTS.REQUEST_BIDS); + assert.ok(spyEventsEmit.calledWith('requestBids')); events.emit.restore(); }); }); From 1cdf4184e1d8c4a68046d5cd63bbb0b2720d37e3 Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 16 Oct 2018 13:30:01 -0400 Subject: [PATCH 0762/1594] removing cookieSet (#3175) * removing cookieSet * removing blank line * not including src/cookie anymore --- modules/prebidServerBidAdapter/config.js | 2 -- modules/prebidServerBidAdapter/index.js | 7 ----- src/cookie.js | 11 ------- .../modules/prebidServerBidAdapter_spec.js | 31 ------------------- 4 files changed, 51 deletions(-) delete mode 100644 src/cookie.js diff --git a/modules/prebidServerBidAdapter/config.js b/modules/prebidServerBidAdapter/config.js index 74eb4a95744..835d09e2010 100644 --- a/modules/prebidServerBidAdapter/config.js +++ b/modules/prebidServerBidAdapter/config.js @@ -2,7 +2,6 @@ export const S2S_VENDORS = { 'appnexus': { adapter: 'prebidServer', - cookieSet: false, enabled: true, endpoint: '//prebid.adnxs.com/pbs/v1/openrtb2/auction', syncEndpoint: '//prebid.adnxs.com/pbs/v1/cookie_sync', @@ -10,7 +9,6 @@ export const S2S_VENDORS = { }, 'rubicon': { adapter: 'prebidServer', - cookieSet: false, enabled: true, endpoint: '//prebid-server.rubiconproject.com/openrtb2/auction', syncEndpoint: '//prebid-server.rubiconproject.com/cookie_sync', diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 7a1ff94644d..80724630da9 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -3,7 +3,6 @@ import bidfactory from 'src/bidfactory'; import * as utils from 'src/utils'; import { ajax } from 'src/ajax'; import { STATUS, S2S, EVENTS } from 'src/constants'; -import { cookieSet } from 'src/cookie.js'; import adaptermanager from 'src/adaptermanager'; import { config } from 'src/config'; import { VIDEO } from 'src/mediaTypes'; @@ -44,7 +43,6 @@ config.setDefaults({ * @property {boolean} [cacheMarkup] whether to cache the adm result * @property {string} [adapter] adapter code to use for S2S * @property {string} [syncEndpoint] endpoint URL for syncing cookies - * @property {string} [cookieSetUrl] url for cookie set library, if passed then cookieSet is enabled */ function setS2sConfig(options) { if (options.defaultVendor) { @@ -620,11 +618,6 @@ export function PrebidServer() { }); bidderRequests.forEach(bidderRequest => events.emit(EVENTS.BIDDER_DONE, bidderRequest)); - - if (result.status === 'no_cookie' && _s2sConfig.cookieSet && typeof _s2sConfig.cookieSetUrl === 'string') { - // cookie sync - cookieSet(_s2sConfig.cookieSetUrl); - } } catch (error) { utils.logError(error); } diff --git a/src/cookie.js b/src/cookie.js deleted file mode 100644 index 893e22e6f27..00000000000 --- a/src/cookie.js +++ /dev/null @@ -1,11 +0,0 @@ -import * as utils from './utils'; -import adLoader from './adloader'; - -const cookie = exports; - -cookie.cookieSet = function(cookieSetUrl) { - if (!utils.isSafariBrowser()) { - return; - } - adLoader.loadScript(cookieSetUrl, null, true); -}; diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 7c3a356c9e8..15aa94ad335 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -2,7 +2,6 @@ import { expect } from 'chai'; import { PrebidServer as Adapter, resetSyncedStatus } from 'modules/prebidServerBidAdapter/index.js'; import adapterManager from 'src/adaptermanager'; import * as utils from 'src/utils'; -import cookie from 'src/cookie'; import { userSync } from 'src/userSync'; import { ajax } from 'src/ajax'; import { config } from 'src/config'; @@ -723,7 +722,6 @@ describe('S2S Adapter', function () { sinon.stub(utils, 'triggerPixel'); sinon.stub(utils, 'insertUserSyncIframe'); sinon.stub(utils, 'logError'); - sinon.stub(cookie, 'cookieSet'); sinon.stub(events, 'emit'); logWarnSpy = sinon.spy(utils, 'logWarn'); }); @@ -734,7 +732,6 @@ describe('S2S Adapter', function () { utils.insertUserSyncIframe.restore(); utils.logError.restore(); events.emit.restore(); - cookie.cookieSet.restore(); logWarnSpy.restore(); }); @@ -907,30 +904,6 @@ describe('S2S Adapter', function () { expect(bid_request_passed).to.have.property('adId', '123'); }); - it('does not call cookieSet cookie sync when no_cookie response && not opted in', function () { - server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - - let myConfig = Object.assign({}, CONFIG); - - config.setConfig({s2sConfig: myConfig}); - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - server.respond(); - sinon.assert.notCalled(cookie.cookieSet); - }); - - it('calls cookieSet cookie sync when no_cookie response && opted in', function () { - server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - let myConfig = Object.assign({ - cookieSet: true, - cookieSetUrl: 'https://acdn.adnxs.com/cookieset/cs.js' - }, CONFIG); - - config.setConfig({s2sConfig: myConfig}); - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - server.respond(); - sinon.assert.calledOnce(cookie.cookieSet); - }); - it('handles OpenRTB responses and call BIDDER_DONE', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' @@ -1070,8 +1043,6 @@ describe('S2S Adapter', function () { expect(vendorConfig).to.have.property('accountId', '123'); expect(vendorConfig).to.have.property('adapter', 'prebidServer'); expect(vendorConfig.bidders).to.deep.equal(['appnexus']); - expect(vendorConfig.cookieSet).to.be.false; - expect(vendorConfig.cookieSetUrl).to.be.undefined; expect(vendorConfig.enabled).to.be.true; expect(vendorConfig).to.have.property('endpoint', '//prebid.adnxs.com/pbs/v1/openrtb2/auction'); expect(vendorConfig).to.have.property('syncEndpoint', '//prebid.adnxs.com/pbs/v1/cookie_sync'); @@ -1093,8 +1064,6 @@ describe('S2S Adapter', function () { expect(vendorConfig).to.have.property('accountId', 'abc'); expect(vendorConfig).to.have.property('adapter', 'prebidServer'); expect(vendorConfig.bidders).to.deep.equal(['rubicon']); - expect(vendorConfig.cookieSet).to.be.false; - expect(vendorConfig.cookieSetUrl).to.be.undefined; expect(vendorConfig.enabled).to.be.true; expect(vendorConfig).to.have.property('endpoint', '//prebid-server.rubiconproject.com/openrtb2/auction'); expect(vendorConfig).to.have.property('syncEndpoint', '//prebid-server.rubiconproject.com/cookie_sync'); From 8529386395cb9f92fd1f0817c3209644c2b1dd5b Mon Sep 17 00:00:00 2001 From: Evgenij Tovba Date: Tue, 16 Oct 2018 19:36:33 +0200 Subject: [PATCH 0763/1594] Removed deprecated priceType option (+tests) (#3170) --- modules/visxBidAdapter.js | 14 ++++---------- test/spec/modules/visxBidAdapter_spec.js | 24 ++++++++++++++++++++---- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 39bfe7eca4e..8e4f9202c7d 100755 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -30,13 +30,9 @@ export const spec = { config.getConfig(`currency.bidderCurrencyDefault.${BIDDER_CODE}`) || config.getConfig('currency.adServerCurrency') || DEFAULT_CUR; - let priceType = 'net'; let reqId; bids.forEach(bid => { - if (bid.params.priceType === 'gross') { - priceType = 'gross'; - } if (!bidsMap[bid.params.uid]) { bidsMap[bid.params.uid] = [bid]; auids.push(bid.params.uid); @@ -48,9 +44,8 @@ export const spec = { const payload = { u: utils.getTopWindowUrl(), - pt: priceType, + pt: 'net', auids: auids.join(','), - test: 1, r: reqId, cur: currency, }; @@ -75,7 +70,6 @@ export const spec = { serverResponse = serverResponse && serverResponse.body; const bidResponses = []; const bidsMap = bidRequest.bidsMap; - const priceType = bidRequest.data.pt; const currency = bidRequest.data.cur; let errorMessage; @@ -87,7 +81,7 @@ export const spec = { if (!errorMessage && serverResponse.seatbid) { serverResponse.seatbid.forEach(respItem => { - _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, currency, bidResponses); + _addBidResponse(_getBidFromResponse(respItem), bidsMap, currency, bidResponses); }); } if (errorMessage) utils.logError(errorMessage); @@ -123,7 +117,7 @@ function _getBidFromResponse(respItem) { return respItem && respItem.bid && respItem.bid[0]; } -function _addBidResponse(serverBid, bidsMap, priceType, currency, bidResponses) { +function _addBidResponse(serverBid, bidsMap, currency, bidResponses) { if (!serverBid) return; let errorMessage; if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); @@ -139,7 +133,7 @@ function _addBidResponse(serverBid, bidsMap, priceType, currency, bidResponses) height: serverBid.h, creativeId: serverBid.auid, currency: currency || DEFAULT_CUR, - netRevenue: priceType !== 'gross', + netRevenue: true, ttl: TIME_TO_LIVE, ad: serverBid.adm, dealId: serverBid.dealid diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index bf8d4cc7d13..93dbe5626c2 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -98,21 +98,21 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'EUR'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', function () { + it('pt parameter must be "net" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); expect(payload).to.have.property('u').that.is.a('string'); - expect(payload).to.have.property('pt', 'gross'); + expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903536'); 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" or "gross"', function () { - bidRequests[1].params.priceType = 'some'; + it('pt parameter must be "net" if params.priceType === "net"', function () { + bidRequests[1].params.priceType = 'net'; const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); @@ -123,6 +123,20 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'EUR'); delete bidRequests[1].params.priceType; }); + + it('pt parameter must be "net" if params.priceType === "undefined"', function () { + bidRequests[1].params.priceType = 'undefined'; + const request = spec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '903535,903536'); + 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' ? 'JPY' : 'USD'); @@ -136,6 +150,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'JPY'); getConfigStub.restore(); }); + it('should add currency from currency.adServerCurrency', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? '' : 'USD'); @@ -149,6 +164,7 @@ describe('VisxAdapter', function () { 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, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); const payload = request.data; From b771e4f087e6c180f044c84cb7cb44b4ba27e5c8 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Tue, 16 Oct 2018 20:39:50 +0200 Subject: [PATCH 0764/1594] Improve Digital adapter: set dealID based on buying type (#3182) * Adding GDPR support * Always drop user syncs when available * Set dealID based on buying type --- modules/improvedigitalBidAdapter.js | 21 ++++++++++--- .../modules/improvedigitalBidAdapter_spec.js | 31 ++++++++++++++++--- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 2cc1d8b39b0..54eb3bb6574 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -5,7 +5,7 @@ import { config } from 'src/config'; const BIDDER_CODE = 'improvedigital'; export const spec = { - version: '4.3.0', + version: '4.4.0', code: BIDDER_CODE, aliases: ['id'], @@ -78,11 +78,24 @@ export const spec = { bid.cpm = parseFloat(bidObject.price); bid.creativeId = bidObject.crid; bid.currency = bidObject.currency ? bidObject.currency.toUpperCase() : 'USD'; - if (utils.isNumber(bidObject.lid)) { + + // 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 === 'deal_id') { bid.dealId = bidObject.lid; - } else if (typeof bidObject.lid === 'object' && bidObject.lid['1']) { - bid.dealId = bidObject.lid['1']; + } 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 === 'deal_id') { + isDeal = true; + bid.dealId = bidObject.lid[i]; + } + }); } + bid.height = bidObject.h; bid.netRevenue = bidObject.isNet ? bidObject.isNet : false; bid.requestId = bidObject.id; diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index bab469b936e..3d7f5a86016 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -264,19 +264,40 @@ describe('Improve Digital Adapter Tests', function () { let response = JSON.parse(JSON.stringify(serverResponse)); let bids; - response.body.bid[0].lid = 'xyz'; + delete response.body.bid[0].lid; + response.body.bid[0].buying_type = 'deal_id'; bids = spec.interpretResponse(response); expect(bids[0].dealId).to.not.exist; response.body.bid[0].lid = 268515; + delete response.body.bid[0].buying_type; bids = spec.interpretResponse(response); - expect(bids[0].dealId).to.equal(268515); + expect(bids[0].dealId).to.not.exist; - response.body.bid[0].lid = { - 1: 268515 - }; + response.body.bid[0].lid = 268515; + response.body.bid[0].buying_type = 'classic'; + bids = spec.interpretResponse(response); + expect(bids[0].dealId).to.not.exist; + + response.body.bid[0].lid = 268515; + response.body.bid[0].buying_type = 'deal_id'; bids = spec.interpretResponse(response); expect(bids[0].dealId).to.equal(268515); + + response.body.bid[0].lid = [ 268515, 12456, 34567 ]; + response.body.bid[0].buying_type = 'deal_id'; + bids = spec.interpretResponse(response); + expect(bids[0].dealId).to.not.exist; + + response.body.bid[0].lid = [ 268515, 12456, 34567 ]; + response.body.bid[0].buying_type = [ 'deal_id', 'classic' ]; + bids = spec.interpretResponse(response); + expect(bids[0].dealId).to.not.exist; + + response.body.bid[0].lid = [ 268515, 12456, 34567 ]; + response.body.bid[0].buying_type = [ 'classic', 'deal_id', 'deal_id' ]; + bids = spec.interpretResponse(response); + expect(bids[0].dealId).to.equal(12456); }); it('should set currency', function () { From bf3137c34181c743ff4c5a88cc75613cc9861fd4 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 16 Oct 2018 16:41:30 -0400 Subject: [PATCH 0765/1594] disabling tests that are failing in safari (#3186) --- test/spec/modules/consentManagement_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index 6af8c8a4478..1303d9cd718 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -678,8 +678,8 @@ describe('consentManagement', function () { // Run tests with JSON response and String response // from CMP window postMessage listener. - testIFramedPage('with/JSON response', false); - testIFramedPage('with/String response', true); + // testIFramedPage('with/JSON response', false); + // testIFramedPage('with/String response', true); function testIFramedPage(testName, messageFormatString) { it(`should return the consent string from a postmessage + addEventListener response - ${testName}`, (done) => { From 613d167b365b76b232b989e2f609a2bc6e750434 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 16 Oct 2018 16:42:21 -0400 Subject: [PATCH 0766/1594] Prebid 1.28.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50e6105099b..40436a6af36 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.28.0-pre", + "version": "1.28.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 79af988600d1c73b52ab759a584be974f838cf0e Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 16 Oct 2018 16:52:19 -0400 Subject: [PATCH 0767/1594] Increment pre version --- package-lock.json | 7997 +++++++++------------------------------------ package.json | 2 +- 2 files changed, 1589 insertions(+), 6410 deletions(-) diff --git a/package-lock.json b/package-lock.json index f28ecb283eb..28a701a2de3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,17 @@ { "name": "prebid.js", - "version": "1.19.0-pre", + "version": "1.28.0", "lockfileVersion": 1, - "requires": true, "dependencies": { "@gulp-sourcemaps/identity-map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", - "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", - "requires": { - "acorn": "^5.0.3", - "css": "^2.2.1", - "normalize-path": "^2.1.1", - "source-map": "^0.6.0", - "through2": "^2.0.3" - } + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==" }, "@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=", - "requires": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - } + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=" }, "@sindresorhus/is": { "version": "0.7.0", @@ -33,22 +21,15 @@ }, "@sinonjs/formatio": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "dev": true, - "requires": { - "samsam": "1.3.0" - } + "dev": true }, - "JSONStream": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.4.tgz", - "integrity": "sha512-Y7vfi3I5oMOYIr+WxV8NZxDSwcbNgzdKYsTNInmycOq9bUYwGg9ryu57Wg5NLmCjqdFPNUmpMBo3kSJN9tCbXg==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } + "@sinonjs/samsam": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.0.tgz", + "integrity": "sha512-5x2kFgJYupaF1ns/RmharQ90lQkd2ELS8A9X0ymkAAdemYHGtI2KiUHG8nX2WU0T1qgnOU5YMqnBM2V7NUanNw==", + "dev": true }, "abbrev": { "version": "1.0.9", @@ -60,25 +41,18 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } + "dev": true }, "acorn": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", - "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" }, "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": { - "acorn": "^4.0.3" - }, "dependencies": { "acorn": { "version": "4.0.13", @@ -90,16 +64,13 @@ }, "acorn-jsx": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, - "requires": { - "acorn": "^3.0.4" - }, "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true } @@ -122,21 +93,13 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } + "dev": true }, "ajv": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", + "resolved": "http://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", - "dev": true, - "requires": { - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } + "dev": true }, "ajv-keywords": { "version": "2.1.1", @@ -149,27 +112,20 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, "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" - } + "dev": true } } }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true }, "amqplib": { "version": "0.5.2", @@ -177,13 +133,6 @@ "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", "dev": true, "optional": true, - "requires": { - "bitsyntax": "~0.0.4", - "bluebird": "^3.4.6", - "buffer-more-ints": "0.0.2", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "^5.0.1" - }, "dependencies": { "isarray": { "version": "0.0.1", @@ -194,16 +143,10 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "optional": true }, "string_decoder": { "version": "0.10.31", @@ -216,12 +159,9 @@ }, "ansi-colors": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } + "dev": true }, "ansi-escapes": { "version": "3.1.0", @@ -233,10 +173,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } + "dev": true }, "ansi-html": { "version": "0.0.7", @@ -266,29 +203,19 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } + "dev": true }, "append-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } + "dev": true }, "append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", - "dev": true, - "requires": { - "default-require-extensions": "^2.0.0" - } + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true }, "archy": { "version": "1.0.0", @@ -300,10 +227,7 @@ "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.2" - } + "dev": true }, "arr-diff": { "version": "4.0.0", @@ -315,10 +239,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } + "dev": true }, "arr-flatten": { "version": "1.1.0", @@ -330,10 +251,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } + "dev": true }, "arr-union": { "version": "3.1.0", @@ -359,15 +277,17 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, "dependencies": { "is-number": { "version": "4.0.0", @@ -377,20 +297,11 @@ } } }, - "array-iterate": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", - "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==", - "dev": true - }, "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, - "requires": { - "is-number": "^4.0.0" - }, "dependencies": { "is-number": { "version": "4.0.0", @@ -411,11 +322,6 @@ "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -429,10 +335,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } + "dev": true }, "array-uniq": { "version": "1.0.3", @@ -462,30 +365,19 @@ "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.0" - } + "dev": true }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } + "dev": true }, "assert": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "dev": true, - "requires": { - "util": "0.10.3" - }, "dependencies": { "inherits": { "version": "2.0.1", @@ -497,10 +389,7 @@ "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" - } + "dev": true } } }, @@ -523,14 +412,14 @@ "dev": true }, "ast-types": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", - "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.6.tgz", + "integrity": "sha512-nHiuV14upVGl7MWwFUYbzJ6YlfwWS084CU9EA8HajfYQjMSli5TQi3UTRygGF58LFWVkXxS1rbgRhROEqlQkXg==", "dev": true }, "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, @@ -539,12 +428,6 @@ "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^1.0.7", - "stream-exhaust": "^1.0.1" - }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -570,10 +453,7 @@ "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" - } + "dev": true }, "asynckit": { "version": "0.4.0", @@ -582,9 +462,9 @@ "dev": true }, "atob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "aws-sign2": { "version": "0.7.0", @@ -600,33 +480,31 @@ }, "axios": { "version": "0.15.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "resolved": "http://registry.npmjs.org/axios/-/axios-0.15.3.tgz", "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", "dev": true, "optional": true, - "requires": { - "follow-redirects": "1.0.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, - "optional": true, - "requires": { - "ms": "2.0.0" - } + "optional": true }, "follow-redirects": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", "dev": true, - "optional": true, - "requires": { - "debug": "^2.2.0" - } + "optional": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true } } }, @@ -634,48 +512,25 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } + "dev": true }, "babel-core": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "babel-generator": "^6.22.0", - "babel-helpers": "^6.22.0", - "babel-messages": "^6.22.0", - "babel-register": "^6.22.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.22.0", - "babel-traverse": "^6.22.0", - "babel-types": "^6.22.0", - "babylon": "^6.11.0", - "convert-source-map": "^1.1.0", - "debug": "^2.1.1", - "json5": "^0.5.0", - "lodash": "^4.2.0", - "minimatch": "^3.0.2", - "path-is-absolute": "^1.0.0", - "private": "^0.1.6", - "slash": "^1.0.0", - "source-map": "^0.5.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" - } + "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": { "version": "0.5.7", @@ -690,16 +545,6 @@ "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": { "source-map": { "version": "0.5.7", @@ -713,277 +558,185 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-builder-react-jsx": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" - } + "dev": true }, "babel-helper-call-delegate": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-define-map": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-helper-explode-assignable-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-explode-class": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-get-function-arity": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-hoist-variables": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-regex": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-helper-remap-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "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" - } + "dev": true }, "babel-loader": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz", "integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==", - "dev": true, - "requires": { - "find-cache-dir": "^1.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1" - } + "dev": true }, "babel-messages": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-check-es2015-constants": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", "dev": true }, "babel-plugin-syntax-async-generators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", "dev": true }, "babel-plugin-syntax-class-constructor-call": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", "dev": true }, "babel-plugin-syntax-class-properties": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", "dev": true }, "babel-plugin-syntax-decorators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", "dev": true }, "babel-plugin-syntax-do-expressions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", "dev": true }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", "dev": true }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", "dev": true }, "babel-plugin-syntax-export-extensions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", "dev": true }, "babel-plugin-syntax-flow": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", "dev": true }, "babel-plugin-syntax-function-bind": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", "dev": true }, "babel-plugin-syntax-jsx": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", "dev": true }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", "dev": true }, @@ -997,600 +750,318 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0" - } + "dev": true }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-generators": "^6.5.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-class-constructor-call": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, - "requires": { - "babel-plugin-syntax-class-constructor-call": "^6.18.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-class-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-decorators": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "^6.24.1", - "babel-plugin-syntax-decorators": "^6.13.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-decorators-legacy": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", - "dev": true, - "requires": { - "babel-plugin-syntax-decorators": "^6.1.18", - "babel-runtime": "^6.2.0", - "babel-template": "^6.3.0" - } + "dev": true }, "babel-plugin-transform-do-expressions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true, - "requires": { - "babel-plugin-syntax-do-expressions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-block-scoping": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-plugin-transform-es2015-classes": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-computed-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-destructuring": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-duplicate-keys": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-for-of": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-modules-amd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } + "dev": true }, "babel-plugin-transform-es2015-modules-systemjs": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-modules-umd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-parameters": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-shorthand-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-spread": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-sticky-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-template-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-typeof-symbol": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-unicode-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } + "dev": true }, "babel-plugin-transform-exponentiation-operator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-export-extensions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, - "requires": { - "babel-plugin-syntax-export-extensions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-flow-strip-types": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-function-bind": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true, - "requires": { - "babel-plugin-syntax-function-bind": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "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=", - "requires": { - "babel-runtime": "^6.22.0" - } + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=" }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" - } + "dev": true }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx-source": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-regenerator": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - } + "dev": true }, "babel-plugin-transform-strict-mode": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - } + "dev": true }, "babel-preset-flow": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } + "dev": true }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" - } + "dev": true }, "babel-preset-stage-0": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true, - "requires": { - "babel-plugin-transform-do-expressions": "^6.22.0", - "babel-plugin-transform-function-bind": "^6.22.0", - "babel-preset-stage-1": "^6.24.1" - } + "dev": true }, "babel-preset-stage-1": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, - "requires": { - "babel-plugin-transform-class-constructor-call": "^6.24.1", - "babel-plugin-transform-export-extensions": "^6.22.0", - "babel-preset-stage-2": "^6.24.1" - } + "dev": true }, "babel-preset-stage-2": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-decorators": "^6.24.1", - "babel-preset-stage-3": "^6.24.1" - } + "dev": true }, "babel-preset-stage-3": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-async-to-generator": "^6.24.1", - "babel-plugin-transform-exponentiation-operator": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.22.0" - } + "dev": true }, "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": { "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" - } + "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" - } + "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": { "version": "0.5.7", @@ -1603,50 +1074,31 @@ "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=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=" }, "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" - } + "dev": true }, "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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -1654,13 +1106,7 @@ "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" - } + "dev": true }, "babelify": { "version": "8.0.0", @@ -1678,18 +1124,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", "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" - } + "dev": true }, "backo2": { "version": "1.0.2", @@ -1714,53 +1149,30 @@ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "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" - }, "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.0" - } + "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.0" - } + "dev": true }, "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.0" - } + "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.2" - } + "dev": true } } }, @@ -1792,11 +1204,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } + "dev": true }, "beeper": { "version": "1.1.1", @@ -1808,10 +1216,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } + "dev": true + }, + "big-integer": { + "version": "1.6.36", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz", + "integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==", + "dev": true }, "big.js": { "version": "3.2.0", @@ -1823,16 +1234,12 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } + "dev": true }, "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", "dev": true }, "binaryextensions": { @@ -1846,20 +1253,14 @@ "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", "dev": true, - "optional": true, - "requires": { - "buffer-more-ints": "0.0.2" - } + "optional": true }, "bl": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "resolved": "http://registry.npmjs.org/bl/-/bl-1.1.2.tgz", "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", "dev": true, "optional": true, - "requires": { - "readable-stream": "~2.0.5" - }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -1870,18 +1271,10 @@ }, "readable-stream": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, - "optional": 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" - } + "optional": true }, "string_decoder": { "version": "0.10.31", @@ -1905,9 +1298,9 @@ "dev": true }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", + "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", "dev": true }, "bn.js": { @@ -1920,31 +1313,13 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "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" - } + "dev": true }, "body-parser": { "version": "1.14.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", "dev": true, - "requires": { - "bytes": "2.2.0", - "content-type": "~1.0.1", - "debug": "~2.2.0", - "depd": "~1.1.0", - "http-errors": "~1.3.1", - "iconv-lite": "0.4.13", - "on-finished": "~2.3.0", - "qs": "5.2.0", - "raw-body": "~2.1.5", - "type-is": "~1.6.10" - }, "dependencies": { "bytes": { "version": "2.2.0", @@ -1954,16 +1329,13 @@ }, "debug": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } + "dev": true }, "ms": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, @@ -1978,11 +1350,6 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", "dev": true, - "requires": { - "bytes": "2.4.0", - "iconv-lite": "0.4.13", - "unpipe": "1.0.0" - }, "dependencies": { "bytes": { "version": "2.4.0", @@ -1998,47 +1365,25 @@ "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } + "dev": true }, "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, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "dev": true }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, "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" - } + "dev": true } } }, @@ -2053,9 +1398,6 @@ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, - "requires": { - "resolve": "1.1.7" - }, "dependencies": { "resolve": { "version": "1.1.7", @@ -2073,162 +1415,101 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://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.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "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.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } + "dev": true }, "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.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "dev": true }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } + "dev": true }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } + "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.5" - } + "dev": true }, "browserslist": { "version": "3.2.8", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } + "dev": true }, "browserstack": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", "dev": true, - "requires": { - "https-proxy-agent": "1.0.0" - }, "dependencies": { "agent-base": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, - "requires": { - "extend": "~3.0.0", - "semver": "~5.0.1" - } + "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" - } + "dev": true }, "https-proxy-agent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true, - "requires": { - "agent-base": "2", - "debug": "2", - "extend": "3" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "semver": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.0.3.tgz", "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", "dev": true } } }, "browserstacktunnel-wrapper": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.3.tgz", - "integrity": "sha512-I3u/EOOPGBt34RN0PBhPDwee4Dsik/Y2URK7iJn/vj5sR8JIoNh5I9gA6bFyxhU9sCo/1ISN4p7URNXK4zD4AA==", - "dev": true, - "requires": { - "https-proxy-agent": "^2.2.1", - "unzip": "~0.1.11" - } + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.4.tgz", + "integrity": "sha512-GCV599FUUxNOCFl3WgPnfc5dcqq9XTmMXoxWpqkvmk0R9TOIoqmjENNU6LY6DtgIL6WfBVbg/jmWtnM5K6UYSg==", + "dev": true }, "buffer": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } + "dev": true }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } + "dev": true }, "buffer-alloc-unsafe": { "version": "1.1.0", @@ -2254,6 +1535,12 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "buffer-indexof-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz", + "integrity": "sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8=", + "dev": true + }, "buffer-more-ints": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", @@ -2283,16 +1570,7 @@ "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", "dev": true, - "optional": true, - "requires": { - "addressparser": "1.0.1", - "libbase64": "0.1.0", - "libmime": "3.0.0", - "libqp": "1.1.0", - "nodemailer-fetch": "1.6.0", - "nodemailer-shared": "1.1.0", - "punycode": "1.4.1" - } + "optional": true }, "builtin-modules": { "version": "1.1.1", @@ -2316,33 +1594,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "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" - } + "dev": true }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", "dev": true, - "requires": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - }, "dependencies": { "lowercase-keys": { "version": "1.0.0", @@ -2356,10 +1614,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } + "dev": true }, "callsite": { "version": "1.0.0", @@ -2381,13 +1636,9 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "http://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" - }, "dependencies": { "camelcase": { "version": "2.1.1", @@ -2398,9 +1649,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000876", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000876.tgz", - "integrity": "sha512-v+Q2afhJJ1oydQnEB4iHhxDz5x9lWPbRnQBQlM3FgtZxqLO8KDSdu4txUrFwC1Ws9I2kQi/QImkvj17NbVpNAg==", + "version": "1.0.30000892", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000892.tgz", + "integrity": "sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w==", "dev": true }, "caseless": { @@ -2419,32 +1670,19 @@ "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.3", - "lazy-cache": "^1.0.3" - } + "dev": true }, "chai": { "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "resolved": "http://registry.npmjs.org/chai/-/chai-3.5.0.tgz", "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "^1.0.1", - "deep-eql": "^0.1.3", - "type-detect": "^1.0.0" - } + "dev": true }, "chai-nightwatch": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", - "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.2.1.tgz", + "integrity": "sha512-2lprSMi72sHq2ZGyPTYUDQNsd2O4z81SicascbI4bkU54Xzk5Ofunn2CbrExADGC7jBH2D8r66X/aSEl+/agXQ==", "dev": true, - "requires": { - "assertion-error": "1.0.0", - "deep-eql": "0.1.3" - }, "dependencies": { "assertion-error": { "version": "1.0.0", @@ -2458,23 +1696,13 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } + "dev": true }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://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" - } + "dev": true }, "character-entities": { "version": "1.2.2", @@ -2516,32 +1744,13 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } + "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.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "circular-json": { "version": "0.3.3", @@ -2554,21 +1763,12 @@ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "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" - }, "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" - } + "dev": true } } }, @@ -2576,10 +1776,7 @@ "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, - "requires": { - "restore-cursor": "^2.0.0" - } + "dev": true }, "cli-width": { "version": "2.2.0", @@ -2591,12 +1788,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } + "dev": true }, "clone": { "version": "2.1.2", @@ -2614,10 +1806,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } + "dev": true }, "clone-stats": { "version": "1.0.0", @@ -2629,12 +1818,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } + "dev": true }, "co": { "version": "4.6.0", @@ -2658,36 +1842,24 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "dev": true }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } + "dev": true }, "color-convert": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", - "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", - "dev": true, - "requires": { - "color-name": "1.1.1" - } + "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 }, "color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "color-support": { @@ -2697,37 +1869,28 @@ "dev": true }, "colors": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.1.tgz", - "integrity": "sha512-jg/vxRmv430jixZrC+La5kMbUWqIg32/JsYNZb94+JEmzceYbWKTsv1OuTp+7EaqiaWRR2tPcykibwCRgclIsw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", "dev": true }, "combine-lists": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } + "dev": true }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true }, "comma-separated-tokens": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "dev": true, - "requires": { - "trim": "0.0.1" - } + "dev": true }, "commander": { "version": "2.11.0", @@ -2741,12 +1904,6 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, - "compare-versions": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.3.0.tgz", - "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==", - "dev": true - }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -2775,43 +1932,31 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "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" - } + "dev": true }, "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, - "requires": { - "source-map": "^0.6.1" - } + "dev": true }, "connect": { "version": "3.6.6", "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", - "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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -2825,10 +1970,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } + "dev": true }, "constants-browserify": { "version": "1.0.0", @@ -2855,9 +1997,9 @@ "dev": true }, "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==" }, "cookie": { "version": "0.3.1", @@ -2875,11 +2017,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true, - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" - } + "dev": true }, "core-js": { "version": "2.5.7", @@ -2896,18 +2034,10 @@ "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.2.tgz", "integrity": "sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw==", "dev": true, - "requires": { - "growl": "~> 1.10.0", - "js-yaml": "^3.11.0", - "lcov-parse": "^0.0.10", - "log-driver": "^1.2.7", - "minimist": "^1.2.0", - "request": "^2.85.0" - }, "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -2917,78 +2047,38 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } + "dev": true }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } + "dev": true }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://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.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } + "dev": true }, "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.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "dev": true }, "cryptiles": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, - "optional": true, - "requires": { - "boom": "2.x.x" - } + "optional": true }, "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": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } + "dev": true }, "crypto-js": { "version": "3.1.9-1", @@ -2996,60 +2086,30 @@ "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" }, "css": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", - "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", - "requires": { - "inherits": "^2.0.1", - "source-map": "^0.1.38", - "source-map-resolve": "^0.5.1", - "urix": "^0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "requires": { - "amdefine": ">=0.0.4" - } - } - } + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==" }, "css-loader": { "version": "0.9.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", + "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-0.9.1.tgz", "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", "dev": true, "optional": true, - "requires": { - "csso": "1.3.x", - "loader-utils": "~0.2.2", - "source-map": "~0.1.38" - }, "dependencies": { "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, - "optional": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } + "optional": true }, "source-map": { "version": "0.1.43", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } + "optional": true } } }, @@ -3064,10 +2124,7 @@ "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" - } + "dev": true }, "custom-event": { "version": "1.0.1", @@ -3078,19 +2135,13 @@ "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "^0.10.9" - } + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=" }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } + "dev": true }, "data-uri-to-buffer": { "version": "1.2.0", @@ -3114,29 +2165,17 @@ "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" - } + "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==" }, "debug-fabulous": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", - "requires": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - } + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==" }, "decamelize": { "version": "1.2.0", @@ -3153,19 +2192,13 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } + "dev": true }, "deep-eql": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "resolved": "http://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", "dev": true, - "requires": { - "type-detect": "0.1.1" - }, "dependencies": { "type-detect": { "version": "0.1.1", @@ -3186,9 +2219,6 @@ "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -3199,12 +2229,17 @@ } }, "default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, - "requires": { - "strip-bom": "^3.0.0" + "dependencies": { + "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 + } } }, "default-resolution": { @@ -3214,53 +2249,34 @@ "dev": true }, "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "^2.0.5", - "object-keys": "^1.0.8" - } + "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 }, "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, - "requires": { - "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.0" - } + "dev": true }, "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.0" - } + "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.2" - } + "dev": true } } }, @@ -3275,11 +2291,6 @@ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", "dev": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - }, "dependencies": { "esprima": { "version": "3.1.3", @@ -3294,15 +2305,6 @@ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, - "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - }, "dependencies": { "pify": { "version": "2.3.0", @@ -3328,11 +2330,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } + "dev": true }, "destroy": { "version": "1.0.4", @@ -3344,10 +2342,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", - "dev": true, - "requires": { - "repeat-string": "^1.5.4" - } + "dev": true }, "detect-file": { "version": "1.0.0", @@ -3359,10 +2354,7 @@ "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" - } + "dev": true }, "detect-newline": { "version": "2.1.0", @@ -3373,11 +2365,7 @@ "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true, - "requires": { - "acorn": "^5.2.1", - "defined": "^1.0.0" - } + "dev": true }, "di": { "version": "0.0.1", @@ -3393,101 +2381,33 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } + "dev": true }, "disparity": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", - "dev": true, - "requires": { - "ansi-styles": "^2.0.1", - "diff": "^1.3.2" - } + "dev": true }, "doctrine": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } + "dev": true }, "doctrine-temporary-fork": { "version": "2.0.0-alpha-allowarrayindex", "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } + "dev": true }, "documentation": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", + "resolved": "http://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", "dev": true, - "requires": { - "ansi-html": "^0.0.7", - "babel-core": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-plugin-system-import-transformer": "3.1.0", - "babel-plugin-transform-decorators-legacy": "^1.3.4", - "babel-preset-env": "^1.6.1", - "babel-preset-react": "^6.24.1", - "babel-preset-stage-0": "^6.24.1", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babelify": "^8.0.0", - "babylon": "^6.18.0", - "chalk": "^2.3.0", - "chokidar": "^2.0.0", - "concat-stream": "^1.6.0", - "disparity": "^2.0.0", - "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", - "get-port": "^3.2.0", - "git-url-parse": "^8.0.0", - "github-slugger": "1.2.0", - "glob": "^7.1.2", - "globals-docs": "^2.4.0", - "highlight.js": "^9.12.0", - "js-yaml": "^3.10.0", - "lodash": "^4.17.4", - "mdast-util-inject": "^1.1.0", - "micromatch": "^3.1.5", - "mime": "^1.4.1", - "module-deps-sortable": "4.0.6", - "parse-filepath": "^1.0.2", - "pify": "^3.0.0", - "read-pkg-up": "^3.0.0", - "remark": "^9.0.0", - "remark-html": "7.0.0", - "remark-reference-links": "^4.0.1", - "remark-toc": "^5.0.0", - "remote-origin-url": "0.4.0", - "shelljs": "^0.8.1", - "stream-array": "^1.1.2", - "strip-json-comments": "^2.0.1", - "tiny-lr": "^1.1.0", - "unist-builder": "^1.0.2", - "unist-util-visit": "^1.3.0", - "vfile": "^2.3.0", - "vfile-reporter": "^4.0.0", - "vfile-sort": "^2.1.0", - "vinyl": "^2.1.0", - "vinyl-fs": "^3.0.2", - "yargs": "^9.0.1" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -3499,57 +2419,25 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } + "dev": true }, "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" - } + "dev": true }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "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" - } + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -3559,15 +2447,9 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "http://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.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, "dependencies": { "pify": { "version": "2.3.0", @@ -3577,23 +2459,23 @@ } } }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "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" - } + "dev": true }, "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.0.0" - }, "dependencies": { "pify": { "version": "2.3.0", @@ -3607,12 +2489,7 @@ "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.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "source-map": { "version": "0.5.7", @@ -3624,60 +2501,31 @@ "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" - } + "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": { - "ansi-regex": "^3.0.0" - } + "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" - } + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, - "requires": { - "camelcase": "^4.1.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.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.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" - }, "dependencies": { "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.0.0", - "read-pkg": "^2.0.0" - } + "dev": true } } } @@ -3687,13 +2535,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } + "dev": true }, "domain-browser": { "version": "1.2.0", @@ -3710,7 +2552,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, @@ -3718,10 +2560,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } + "dev": true }, "duplexer3": { "version": "0.1.4", @@ -3730,37 +2569,22 @@ "dev": true }, "duplexify": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "dev": true }, "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, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } + "dev": true }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } + "dev": true }, "ee-first": { "version": "1.1.1", @@ -3775,25 +2599,16 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.57", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.57.tgz", - "integrity": "sha512-YYpZlr6mzR8cK5VRmTZydEt5Mp+WMg1/syrO40PoQzl76vJ+oQchL2d3FmEcWzw3FYqJVYJP/kYYSzTa7FLXwg==", + "version": "1.3.79", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.79.tgz", + "integrity": "sha512-LQdY3j4PxuUl6xfxiFruTSlCniTrTrzAd8/HfsLEMi0PUpaQ0Iy+Pr4N4VllDYjs0Hyu2lkTbvzqlG+PX9NsNw==", "dev": true }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } + "dev": true }, "emoji-regex": { "version": "6.1.1", @@ -3817,24 +2632,26 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } + "dev": true }, "engine.io": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "uws": "~9.14.0", - "ws": "~3.3.1" + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "engine.io-client": { @@ -3842,44 +2659,32 @@ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "engine.io-parser": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary2": "~1.0.2" - } + "dev": true }, "enhanced-resolve": { "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.1.2", - "memory-fs": "^0.4.0", - "object-assign": "^4.0.1", - "tapable": "^0.2.7" - } + "dev": true }, "ent": { "version": "2.2.0", @@ -3891,117 +2696,69 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } + "dev": true }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true, - "requires": { - "string-template": "~0.2.1", - "xtend": "~4.0.0" - } + "dev": true }, "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, - "requires": { - "is-arrayish": "^0.2.1" - } + "dev": true }, "es5-ext": { "version": "0.10.46", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==" }, "es5-shim": { - "version": "4.5.10", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", - "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==", + "version": "4.5.12", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.12.tgz", + "integrity": "sha512-MjoCAHE6P2Dirme70Cxd9i2Ng8rhXiaVSsxDWdSwimfLERJL/ypR2ed2rTYkeeYrMk8gq281dzKLiGcdrmc8qg==", "dev": true }, "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=" }, "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", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } + "dev": true }, "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", "dev": true }, "es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } + "dev": true }, "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", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } + "dev": true }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=" }, "es6-weak-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "requires": { - "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=" }, "escape-html": { "version": "1.0.3", @@ -4020,13 +2777,6 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, "dependencies": { "esprima": { "version": "2.7.3", @@ -4045,10 +2795,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } + "optional": true } } }, @@ -4056,71 +2803,19 @@ "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.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "dev": true }, "eslint": { "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "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", - "table": "4.0.2", - "text-table": "~0.2.0" - }, "dependencies": { "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" - } + "dev": true }, "ansi-regex": { "version": "3.0.0", @@ -4132,54 +2827,37 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } + "dev": true }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "dev": true }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } + "dev": true }, "globals": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", - "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", "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": { - "ansi-regex": "^3.0.0" - } + "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" - } + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true } } }, @@ -4194,19 +2872,18 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -4215,47 +2892,36 @@ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, - "requires": { - "debug": "^2.6.8", - "pkg-dir": "^1.0.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" - } + "dev": true }, "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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "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" - } + "dev": true }, "pkg-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } + "dev": true } } }, @@ -4264,57 +2930,36 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", "dev": true, - "requires": { - "contains-path": "^0.1.0", - "debug": "^2.6.8", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0", - "resolve": "^1.6.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" - } + "dev": true }, "load-json-file": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "http://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.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } + "dev": true }, - "parse-json": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "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" - } + "dev": true }, "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.0.0" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -4326,22 +2971,13 @@ "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.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "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.0.0", - "read-pkg": "^2.0.0" - } + "dev": true } } }, @@ -4350,16 +2986,10 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, - "requires": { - "ignore": "^3.3.6", - "minimatch": "^3.0.4", - "resolve": "^1.3.3", - "semver": "5.3.0" - }, "dependencies": { "semver": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } @@ -4381,11 +3011,7 @@ "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, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "dev": true }, "eslint-visitor-keys": { "version": "1.0.0", @@ -4397,11 +3023,7 @@ "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } + "dev": true }, "esprima": { "version": "4.0.1", @@ -4413,19 +3035,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } + "dev": true }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } + "dev": true }, "estraverse": { "version": "4.2.0", @@ -4454,26 +3070,13 @@ "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=" }, "event-stream": { - "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "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" - } + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.6.tgz", + "integrity": "sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==", + "dev": true }, "eventemitter3": { "version": "3.1.0", @@ -4483,7 +3086,7 @@ }, "events": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", "dev": true }, @@ -4491,37 +3094,19 @@ "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.4", - "safe-buffer": "^5.1.1" - } + "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.0.1", - "get-stream": "^3.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" - } + "dev": true }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, "dependencies": { "array-slice": { "version": "0.2.3", @@ -4539,10 +3124,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } + "dev": true } } }, @@ -4551,42 +3133,30 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "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" - }, "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" - } + "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.0" - } + "dev": true }, "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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -4595,10 +3165,6 @@ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - }, "dependencies": { "is-number": { "version": "0.1.1", @@ -4618,10 +3184,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "dev": true }, "extend": { "version": "3.0.2", @@ -4634,41 +3197,26 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, - "requires": { - "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" - } + "dev": true } } }, "external-editor": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - }, "dependencies": { "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true } } }, @@ -4677,63 +3225,36 @@ "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.0", - "snapdragon": "^0.8.1", - "to-regex": "^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.0" - } + "dev": true }, "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" - } + "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.0" - } + "dev": true }, "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.0" - } + "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.2" - } + "dev": true } } }, @@ -4745,7 +3266,7 @@ }, "faker": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-3.1.0.tgz", + "resolved": "http://registry.npmjs.org/faker/-/faker-3.1.0.tgz", "integrity": "sha1-D5CPr05uwCUk5UpX5DLFwBPgjJ8=", "dev": true }, @@ -4753,12 +3274,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "time-stamp": "^1.0.0" - } + "dev": true }, "fast-deep-equal": { "version": "1.1.0", @@ -4782,52 +3298,33 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } + "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" - } + "dev": true }, "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, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } + "dev": true }, "file-loader": { "version": "0.8.5", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", + "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-0.8.5.tgz", "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", "dev": true, "optional": true, - "requires": { - "loader-utils": "~0.2.5" - }, "dependencies": { "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, - "optional": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } + "optional": true } } }, @@ -4847,42 +3344,25 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, - "requires": { - "glob": "^7.0.3", - "minimatch": "^3.0.3" - } + "dev": true }, "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - } + "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.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" - } + "dev": true } } }, @@ -4891,24 +3371,18 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -4916,42 +3390,25 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" - } + "dev": true }, "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" - } + "dev": true }, "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" - }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } + "dev": true } } }, @@ -4959,14 +3416,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "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" - } + "dev": true }, "flagged-respawn": { "version": "1.0.0", @@ -4978,31 +3428,38 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" - } + "dev": true + }, + "flatmap-stream": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.1.tgz", + "integrity": "sha512-lAq4tLbm3sidmdCN8G3ExaxH7cUCtP5mgDvrYowsx84dcYkJJ4I28N7gkxA6+YlSXzaGLJYIDEi9WGfXzMiXdw==", + "dev": true }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - } + "dev": true }, "follow-redirects": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.5.tgz", - "integrity": "sha512-GHjtHDlY/ehslqv0Gr5N0PUJppgg/q0rOBvX0na1s7y1A3LWxPqCYU76s3Z1bM4+UZB4QF0usaXLT5wFpof5PA==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz", + "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==", "dev": true, - "requires": { - "debug": "^3.1.0" + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "for-in": { @@ -5015,15 +3472,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, "foreachasync": { @@ -5049,20 +3497,20 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true + } } }, "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, - "requires": { - "map-cache": "^0.2.2" - } + "dev": true }, "fresh": { "version": "0.3.0", @@ -5080,20 +3528,13 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } + "dev": true }, "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, - "requires": { - "null-check": "^1.0.0" - } + "dev": true }, "fs-copy-file-sync": { "version": "1.1.1", @@ -5106,16 +3547,10 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, - "requires": { - "jsonfile": "~1.0.1", - "mkdirp": "0.3.x", - "ncp": "~0.4.2", - "rimraf": "~2.2.0" - }, "dependencies": { "mkdirp": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true } @@ -5125,26 +3560,17 @@ "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, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } + "dev": true }, "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, - "requires": { - "fs-extra": "~0.6.1", - "mkdirp": "~0.3.5", - "walk": "^2.3.9" - }, "dependencies": { "mkdirp": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true } @@ -5162,10 +3588,6 @@ "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", "dev": true, "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, "dependencies": { "abbrev": { "version": "1.1.1", @@ -5188,11 +3610,7 @@ "version": "1.1.4", "bundled": true, "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } + "optional": true }, "balanced-match": { "version": "1.0.0", @@ -5202,11 +3620,7 @@ "brace-expansion": { "version": "1.1.11", "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "dev": true }, "chownr": { "version": "1.0.1", @@ -5239,10 +3653,7 @@ "version": "2.6.9", "bundled": true, "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } + "optional": true }, "deep-extend": { "version": "0.5.1", @@ -5266,10 +3677,7 @@ "version": "1.2.5", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } + "optional": true }, "fs.realpath": { "version": "1.0.0", @@ -5281,31 +3689,13 @@ "version": "2.7.4", "bundled": true, "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } + "optional": true }, "glob": { "version": "7.1.2", "bundled": true, "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "optional": true }, "has-unicode": { "version": "2.0.1", @@ -5317,29 +3707,19 @@ "version": "0.4.21", "bundled": true, "dev": true, - "optional": true, - "requires": { - "safer-buffer": "^2.1.0" - } + "optional": true }, "ignore-walk": { "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } + "optional": true }, "inflight": { "version": "1.0.6", "bundled": true, "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } + "optional": true }, "inherits": { "version": "2.0.3", @@ -5355,10 +3735,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "isarray": { "version": "1.0.0", @@ -5369,10 +3746,7 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } + "dev": true }, "minimist": { "version": "0.0.8", @@ -5382,28 +3756,18 @@ "minipass": { "version": "2.2.4", "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } + "dev": true }, "minizlib": { "version": "1.1.0", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } + "optional": true }, "mkdirp": { "version": "0.5.1", "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5415,40 +3779,19 @@ "version": "2.2.0", "bundled": true, "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } + "optional": true }, "node-pre-gyp": { "version": "0.10.0", "bundled": true, "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } + "optional": true }, "nopt": { "version": "4.0.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } + "optional": true }, "npm-bundled": { "version": "1.0.3", @@ -5460,23 +3803,13 @@ "version": "1.1.10", "bundled": true, "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } + "optional": true }, "npmlog": { "version": "4.1.2", "bundled": true, "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } + "optional": true }, "number-is-nan": { "version": "1.0.1", @@ -5492,10 +3825,7 @@ "once": { "version": "1.4.0", "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } + "dev": true }, "os-homedir": { "version": "1.0.2", @@ -5513,11 +3843,7 @@ "version": "0.1.5", "bundled": true, "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } + "optional": true }, "path-is-absolute": { "version": "1.0.1", @@ -5536,12 +3862,6 @@ "bundled": true, "dev": true, "optional": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, "dependencies": { "minimist": { "version": "1.2.0", @@ -5555,25 +3875,13 @@ "version": "2.3.6", "bundled": true, "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "optional": true }, "rimraf": { "version": "2.6.2", "bundled": true, "dev": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } + "optional": true }, "safe-buffer": { "version": "5.1.1", @@ -5610,32 +3918,21 @@ "dev": true, "optional": true }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "string_decoder": { "version": "1.1.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true }, "strip-ansi": { "version": "3.0.1", "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -5647,16 +3944,7 @@ "version": "4.4.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - } + "optional": true }, "util-deprecate": { "version": "1.0.2", @@ -5668,10 +3956,7 @@ "version": "1.1.2", "bundled": true, "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } + "optional": true }, "wrappy": { "version": "1.0.2", @@ -5686,37 +3971,16 @@ } }, "fstream": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", - "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", - "dev": true, - "requires": { - "graceful-fs": "~3.0.2", - "inherits": "~2.0.0", - "mkdirp": "0.5", - "rimraf": "2" - }, - "dependencies": { - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "^1.1.0" - } - } - } + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true }, "ftp": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", "dev": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, "dependencies": { "isarray": { "version": "0.0.1", @@ -5726,15 +3990,9 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -5757,9 +4015,9 @@ "dev": true }, "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", "dev": true, "optional": true }, @@ -5768,10 +4026,7 @@ "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, - "optional": true, - "requires": { - "is-property": "^1.0.0" - } + "optional": true }, "get-caller-file": { "version": "1.0.3", @@ -5799,7 +4054,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, @@ -5808,23 +4063,18 @@ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", "dev": true, - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - }, "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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -5838,72 +4088,43 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } + "dev": true }, "git-up": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "parse-url": "^1.3.0" - } + "dev": true }, "git-url-parse": { "version": "8.3.1", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", + "resolved": "http://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true, - "requires": { - "git-up": "^2.0.0", - "parse-domain": "^2.0.0" - } + "dev": true }, "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, - "requires": { - "emoji-regex": ">=6.0.0 <=6.1.1" - } + "dev": true }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true }, "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": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, "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.0" - } + "dev": true }, "is-extglob": { "version": "1.0.0", @@ -5915,10 +4136,7 @@ "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" - } + "dev": true } } }, @@ -5927,19 +4145,12 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } + "dev": true } } }, @@ -5947,55 +4158,25 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "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" - } + "dev": true }, "glob-watcher": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.1.tgz", "integrity": "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g==", - "dev": true, - "requires": { - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "just-debounce": "^1.0.0", - "object.defaults": "^1.1.0" - } + "dev": true }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } + "dev": true }, "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, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } + "dev": true }, "globals": { "version": "9.18.0", @@ -6014,14 +4195,6 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, "dependencies": { "pify": { "version": "2.3.0", @@ -6035,35 +4208,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } + "dev": true }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" - } + "dev": true }, "graceful-fs": { "version": "4.1.11", @@ -6081,12 +4232,6 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", "dev": true, - "requires": { - "glob-watcher": "^5.0.0", - "gulp-cli": "^2.0.0", - "undertaker": "^1.0.0", - "vinyl-fs": "^3.0.0" - }, "dependencies": { "camelcase": { "version": "3.0.0", @@ -6098,88 +4243,43 @@ "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" - } + "dev": true }, "gulp-cli": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", - "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.1.0", - "isobject": "^3.0.1", - "liftoff": "^2.5.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.0.1", - "yargs": "^7.1.0" - } + "dev": true }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://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" - } + "dev": true }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } + "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -6191,31 +4291,19 @@ "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" - } + "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=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "dev": true }, "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" - } + "dev": true }, "which-module": { "version": "1.0.0", @@ -6227,31 +4315,13 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "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.0" - } + "dev": true }, "yargs-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - } + "dev": true } } }, @@ -6260,50 +4330,24 @@ "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", "dev": true, - "requires": { - "babel-core": "^6.23.1", - "object-assign": "^4.0.1", - "plugin-error": "^1.0.1", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" - }, "dependencies": { "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" - } + "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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "replace-ext": { "version": "0.0.1", @@ -6324,15 +4368,10 @@ "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" - }, "dependencies": { "ansi-regex": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "resolved": "http://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", "dev": true }, @@ -6344,16 +4383,9 @@ }, "chalk": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "resolved": "http://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" - } + "dev": true }, "clone-stats": { "version": "0.0.1", @@ -6366,26 +4398,12 @@ "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" - } + "dev": true } } }, @@ -6393,10 +4411,7 @@ "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" - } + "dev": true }, "isarray": { "version": "0.0.1", @@ -6406,7 +4421,7 @@ }, "minimist": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", "dev": true }, @@ -6418,15 +4433,9 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://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" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -6436,12 +4445,9 @@ }, "strip-ansi": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "^0.2.1" - } + "dev": true }, "supports-color": { "version": "0.2.0", @@ -6454,19 +4460,12 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, - "requires": { - "readable-stream": "~1.0.17", - "xtend": "~2.1.1" - }, "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" - } + "dev": true } } }, @@ -6474,10 +4473,7 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "~0.0.1" - } + "dev": true }, "xtend": { "version": "3.0.0", @@ -6491,42 +4487,23 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - } + "dev": true }, "gulp-connect": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.5.0.tgz", + "resolved": "http://registry.npmjs.org/gulp-connect/-/gulp-connect-5.5.0.tgz", "integrity": "sha512-oRBLjw/4EVaZb8g8OcxOVdGD8ZXYrRiWKcNxlrGjxb/6Cp0GDdqw7ieX7D8xJrQS7sbXT+G94u63pMJF3MMjQA==", "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "connect": "^3.6.5", - "connect-livereload": "^0.5.4", - "event-stream": "^3.3.2", - "fancy-log": "^1.3.2", - "send": "^0.13.2", - "serve-index": "^1.9.1", - "serve-static": "^1.13.1", - "tiny-lr": "^0.2.1" - }, "dependencies": { "debug": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } + "dev": true }, "ms": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, @@ -6540,15 +4517,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", - "dev": true, - "requires": { - "body-parser": "~1.14.0", - "debug": "~2.2.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.2.0", - "parseurl": "~1.3.0", - "qs": "~5.1.0" - } + "dev": true } } }, @@ -6556,25 +4525,13 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", - "dev": true, - "requires": { - "eslint": "^4.0.0", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.0" - } + "dev": true }, "gulp-footer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", "dev": true, - "requires": { - "event-stream": "*", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.6.2" - }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -6586,48 +4543,25 @@ "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" - } + "dev": true }, "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.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } + "dev": true }, "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.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" - } + "dev": true }, "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.0.0" - } + "dev": true } } }, @@ -6636,11 +4570,6 @@ "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, - "requires": { - "concat-with-sourcemaps": "*", - "lodash.template": "^4.4.0", - "through2": "^2.0.0" - }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -6652,20 +4581,13 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0", - "lodash.templatesettings": "^4.0.0" - } + "dev": true }, "lodash.templatesettings": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0" - } + "dev": true } } }, @@ -6673,21 +4595,13 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true, - "requires": { - "gulp-match": "^1.0.3", - "ternary-stream": "^2.0.1", - "through2": "^2.0.1" - } + "dev": true }, "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, - "requires": { - "through2": "^0.6.3" - }, "dependencies": { "isarray": { "version": "0.0.1", @@ -6697,15 +4611,9 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://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" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -6717,11 +4625,7 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } + "dev": true } } }, @@ -6729,22 +4633,13 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true, - "requires": { - "minimatch": "^3.0.3" - } + "dev": true }, "gulp-optimize-js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", - "dev": true, - "requires": { - "gulp-util": "^3.0.7", - "lodash": "^4.16.2", - "optimize-js": "^1.0.0", - "through2": "^2.0.1" - } + "dev": true }, "gulp-rename": { "version": "1.4.0", @@ -6757,41 +4652,24 @@ "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", "dev": true, - "requires": { - "event-stream": "~3.0.18", - "istextorbinary": "~1.0.0", - "replacestream": "0.1.3" - }, "dependencies": { "event-stream": { "version": "3.0.20", "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.0.3", - "pause-stream": "0.0.11", - "split": "0.2", - "stream-combiner": "~0.0.3", - "through": "~2.3.1" - } - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, "split": { "version": "0.2.10", - "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.2.10.tgz", "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "dev": true, - "requires": { - "through": "2" - } + "dev": true + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true } } }, @@ -6799,63 +4677,30 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true, - "requires": { - "async": "^1.5.0", - "gulp-util": "^3.0.7", - "lodash": "^4.0.0", - "through2": "^2.0.0" - } + "dev": true }, "gulp-sourcemaps": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", - "requires": { - "@gulp-sourcemaps/identity-map": "1.X", - "@gulp-sourcemaps/map-sources": "1.X", - "acorn": "5.X", - "convert-source-map": "1.X", - "css": "2.X", - "debug-fabulous": "1.X", - "detect-newline": "2.X", - "graceful-fs": "4.X", - "source-map": "~0.6.0", - "strip-bom-string": "1.X", - "through2": "2.X" - } + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=" }, "gulp-uglify": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.1.tgz", "integrity": "sha512-KVffbGY9d4Wv90bW/B1KZJyunLMyfHTBbilpDvmcrj5Go0/a1G3uVpt+1gRBWSw/11dqR3coJ1oWNTt1AiXuWQ==", "dev": true, - "requires": { - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash": "^4.13.1", - "make-error-cause": "^1.1.1", - "safe-buffer": "^5.1.2", - "through2": "^2.0.0", - "uglify-js": "^3.0.5", - "vinyl-sourcemaps-apply": "^0.2.0" - }, "dependencies": { "commander": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", - "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", "dev": true }, "uglify-js": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.7.tgz", - "integrity": "sha512-J0M2i1mQA+ze3EdN9SBi751DNdAXmeFLfJrd/MDIkRc3G3Gbb9OPVSx7GIQvVwfWxQARcYV2DTxIkMyDAk3o9Q==", - "dev": true, - "requires": { - "commander": "~2.16.0", - "source-map": "~0.6.1" - } + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "dev": true } } }, @@ -6864,26 +4709,6 @@ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "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", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, "dependencies": { "clone": { "version": "1.0.4", @@ -6913,52 +4738,29 @@ "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" - } + "dev": true }, "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.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } + "dev": true }, "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.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" - } + "dev": true }, "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.0.0" - } + "dev": true }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -6978,12 +4780,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } + "dev": true } } }, @@ -6991,31 +4788,33 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } + "dev": true }, "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", + "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", "dev": true, - "requires": { - "async": "^1.4.0", - "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" - }, "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } + "optional": true + }, + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "dev": true, + "optional": true } } }, @@ -7030,22 +4829,12 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", "dev": true, - "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" - }, "dependencies": { "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" - } + "dev": true } } }, @@ -7053,28 +4842,19 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } + "dev": true }, "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, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, - "requires": { - "isarray": "2.0.1" - }, "dependencies": { "isarray": { "version": "2.0.1", @@ -7100,10 +4880,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } + "dev": true }, "has-symbol-support-x": { "version": "1.4.2", @@ -7121,40 +4898,25 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "requires": { - "has-symbol-support-x": "^1.4.1" - } + "dev": true }, "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" - } + "dev": true }, "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, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -7162,21 +4924,13 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "hash.js": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } + "dev": true }, "hast-util-is-element": { "version": "1.0.1", @@ -7188,29 +4942,13 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.2.0.tgz", "integrity": "sha512-VwCTqjt6fbMGacxGB1FKV5sBJaVVkyCGVMDwb4nnqvCW2lkqscA2GEpOyBx4ZWRXty1eAZF58MHBrllEoQEoBg==", - "dev": true, - "requires": { - "xtend": "^4.0.1" - } + "dev": true }, "hast-util-to-html": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "comma-separated-tokens": "^1.0.1", - "hast-util-is-element": "^1.0.0", - "hast-util-whitespace": "^1.0.0", - "html-void-elements": "^1.0.0", - "kebab-case": "^1.0.0", - "property-information": "^3.1.0", - "space-separated-tokens": "^1.0.0", - "stringify-entities": "^1.0.1", - "unist-util-is": "^2.0.0", - "xtend": "^4.0.1" - } + "dev": true }, "hast-util-whitespace": { "version": "1.0.1", @@ -7223,13 +4961,7 @@ "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, - "optional": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } + "optional": true }, "he": { "version": "1.1.1", @@ -7238,9 +4970,9 @@ "dev": true }, "highlight.js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", - "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.0.tgz", + "integrity": "sha512-2B90kcNnErqRTmzdZw6IPLEC9CdsiIMhj+r8L3LJKRCgtEJ+LY5yzWuQCVnADTI0wwocQinFzaaL/JjTQNqI/g==", "dev": true }, "hipchat-notifier": { @@ -7248,22 +4980,13 @@ "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", "dev": true, - "optional": true, - "requires": { - "lodash": "^4.0.0", - "request": "^2.0.0" - } + "optional": true }, "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": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } + "dev": true }, "hoek": { "version": "2.16.3", @@ -7275,20 +4998,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } + "dev": true }, "homedir-polyfill": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } + "dev": true }, "hosted-git-info": { "version": "2.7.1", @@ -7310,13 +5026,9 @@ }, "http-errors": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "statuses": "1" - } + "dev": true }, "http-parser-js": { "version": "0.4.13", @@ -7328,43 +5040,39 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } + "dev": true }, "http-proxy-agent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } + "dev": true }, "httpntlm": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true, - "requires": { - "httpreq": ">=0.4.22", - "underscore": "~1.7.0" - } + "dev": true }, "httpreq": { "version": "0.4.24", @@ -7382,15 +5090,11 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - } + "dev": true }, "iconv-lite": { "version": "0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true }, @@ -7422,10 +5126,7 @@ "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" - } + "dev": true }, "indexof": { "version": "0.0.1", @@ -7444,11 +5145,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } + "dev": true }, "inherits": { "version": "2.0.3", @@ -7466,22 +5163,6 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "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", - "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" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -7493,21 +5174,13 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } + "dev": true }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -7519,29 +5192,19 @@ "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" - } + "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": { - "ansi-regex": "^3.0.0" - } + "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" - } + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true } } }, @@ -7553,22 +5216,15 @@ }, "into-stream": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "resolved": "http://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, - "requires": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" - } + "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" - } + "dev": true }, "invert-kv": { "version": "1.0.0", @@ -7586,29 +5242,19 @@ "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, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } + "dev": true }, "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" - } + "dev": true } } }, @@ -7628,11 +5274,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true, - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } + "dev": true }, "is-arrayish": { "version": "0.2.1", @@ -7644,10 +5286,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } + "dev": true }, "is-buffer": { "version": "1.1.6", @@ -7657,30 +5296,21 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } + "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" - } + "dev": true } } }, @@ -7695,11 +5325,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", @@ -7709,6 +5334,12 @@ } } }, + "is-docker": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-1.1.0.tgz", + "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", + "dev": true + }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", @@ -7719,10 +5350,7 @@ "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-primitive": "^2.0.0" - } + "dev": true }, "is-extendable": { "version": "0.1.1", @@ -7740,28 +5368,19 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "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.0" - } + "dev": true }, "is-glob": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } + "dev": true }, "is-hexadecimal": { "version": "1.0.2", @@ -7781,14 +5400,7 @@ "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", "dev": true, - "optional": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" - } + "optional": true }, "is-negated-glob": { "version": "1.0.0", @@ -7801,18 +5413,12 @@ "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": { "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" - } + "dev": true } } }, @@ -7832,19 +5438,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } + "dev": true }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } + "dev": true }, "is-plain-obj": { "version": "1.1.0", @@ -7856,10 +5456,7 @@ "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" - } + "dev": true }, "is-posix-bracket": { "version": "0.1.1", @@ -7882,17 +5479,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true, - "optional": true + "dev": true }, "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, - "requires": { - "is-unc-path": "^1.0.0" - } + "dev": true }, "is-resolvable": { "version": "1.1.0", @@ -7910,10 +5503,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", - "dev": true, - "requires": { - "protocols": "^1.1.0" - } + "dev": true }, "is-stream": { "version": "1.1.0", @@ -7931,10 +5521,7 @@ "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, - "requires": { - "unc-path-regex": "^0.1.2" - } + "dev": true }, "is-utf8": { "version": "0.2.1", @@ -7975,10 +5562,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } + "dev": true }, "isexe": { "version": "2.0.0", @@ -8003,22 +5587,6 @@ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, "dependencies": { "esprima": { "version": "2.7.3", @@ -8030,14 +5598,7 @@ "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" - } + "dev": true }, "has-flag": { "version": "1.0.0", @@ -8055,41 +5616,21 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } + "dev": true } } }, "istanbul-api": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", - "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", - "dev": true, - "requires": { - "async": "^2.1.4", - "compare-versions": "^3.1.0", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.0", - "istanbul-lib-hook": "^1.2.0", - "istanbul-lib-instrument": "^1.10.1", - "istanbul-lib-report": "^1.1.4", - "istanbul-lib-source-maps": "^1.2.4", - "istanbul-reports": "^1.3.0", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" - }, + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", + "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", + "dev": true, "dependencies": { "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } + "dev": true } } }, @@ -8097,55 +5638,31 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true, - "requires": { - "convert-source-map": "^1.5.0", - "istanbul-lib-instrument": "^1.7.3", - "loader-utils": "^1.1.0", - "schema-utils": "^0.3.0" - } + "dev": true }, "istanbul-lib-coverage": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", - "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", "dev": true }, "istanbul-lib-hook": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz", - "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==", - "dev": true, - "requires": { - "append-transform": "^1.0.0" - } + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", + "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "dev": true }, "istanbul-lib-instrument": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", - "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.0", - "semver": "^5.3.0" - } + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true }, "istanbul-lib-report": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", - "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", + "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", "dev": true, - "requires": { - "istanbul-lib-coverage": "^1.2.0", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" - }, "dependencies": { "has-flag": { "version": "1.0.0", @@ -8157,34 +5674,21 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } + "dev": true } } }, "istanbul-lib-source-maps": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz", - "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.0", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" - }, + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, "dependencies": { "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } + "dev": true }, "source-map": { "version": "0.5.7", @@ -8195,53 +5699,38 @@ } }, "istanbul-reports": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", - "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", - "dev": true, - "requires": { - "handlebars": "^4.0.3" - } + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", + "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "dev": true }, "istextorbinary": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", - "dev": true, - "requires": { - "binaryextensions": "~1.0.0", - "textextensions": "~1.0.0" - } + "dev": true }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - } + "dev": true }, "jade": { "version": "0.26.3", "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", "dev": true, - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" - }, "dependencies": { "commander": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-0.6.1.tgz", "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", "dev": true }, "mkdirp": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", "dev": true } @@ -8257,18 +5746,13 @@ "version": "3.12.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } + "dev": true }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true + "dev": true }, "jsencrypt": { "version": "3.0.0-rc.1", @@ -8315,10 +5799,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -8334,13 +5815,13 @@ }, "json5": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, "jsonfile": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-1.0.1.tgz", "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", "dev": true }, @@ -8363,17 +5844,17 @@ "dev": true, "optional": 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 + }, "jsprim": { "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.2.3", - "verror": "1.10.0" - } + "dev": true }, "just-clone": { "version": "1.0.2", @@ -8387,9 +5868,9 @@ "dev": true }, "just-extend": { - "version": "1.1.27", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", - "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-3.0.0.tgz", + "integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==", "dev": true }, "karma": { @@ -8397,53 +5878,12 @@ "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", "integrity": "sha512-rECezBeY7mjzGUWhFlB7CvPHgkHJLXyUmWg+6vHCEsdWNUTnmiS6jRrIMcJEWgU2DUGZzGWG0bTRVky8fsDTOA==", "dev": true, - "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^2.0.3", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.4", - "log4js": "^2.5.3", - "mime": "^1.3.4", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.0.4", - "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.2.1" - }, "dependencies": { "body-parser": { "version": "1.18.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } + "dev": true }, "bytes": { "version": "3.0.0", @@ -8455,31 +5895,25 @@ "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" - } + "dev": true }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://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" - } + "dev": true }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "range-parser": { "version": "1.2.0", @@ -8491,22 +5925,13 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } + "dev": true }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } + "dev": true }, "statuses": { "version": "1.5.0", @@ -8520,21 +5945,13 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true, - "requires": { - "babel-core": "^6.0.0" - } + "dev": true }, "karma-browserstack-launcher": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", - "dev": true, - "requires": { - "browserstack": "1.5.0", - "browserstacktunnel-wrapper": "~2.0.1", - "q": "~1.5.0" - } + "dev": true }, "karma-chai": { "version": "0.1.0", @@ -8546,30 +5963,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true, - "requires": { - "fs-access": "^1.0.0", - "which": "^1.2.1" - } + "dev": true }, "karma-coverage-istanbul-reporter": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", - "dev": true, - "requires": { - "istanbul-api": "^1.3.1", - "minimatch": "^3.0.4" - } + "dev": true }, "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, - "requires": { - "es5-shim": "^4.0.5" - } + "dev": true }, "karma-firefox-launcher": { "version": "1.1.0", @@ -8581,23 +5987,17 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true, - "requires": { - "lodash": "^4.6.1" - } + "dev": true }, "karma-mocha": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", "dev": true, - "requires": { - "minimist": "1.2.0" - }, "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -8608,11 +6008,6 @@ "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", "dev": true, - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "strip-ansi": "^4.0.0" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -8624,39 +6019,25 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } + "dev": true }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "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": { - "ansi-regex": "^3.0.0" - } + "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" - } + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true } } }, @@ -8694,42 +6075,25 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - } + "dev": true }, "karma-spec-reporter": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true, - "requires": { - "colors": "^1.1.2" - } + "dev": true }, "karma-webpack": { "version": "2.0.13", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", + "resolved": "http://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", "dev": true, - "requires": { - "async": "^2.0.0", - "babel-runtime": "^6.0.0", - "loader-utils": "^1.0.0", - "lodash": "^4.0.0", - "source-map": "^0.5.6", - "webpack-dev-middleware": "^1.12.0" - }, "dependencies": { "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } + "dev": true }, "source-map": { "version": "0.5.7", @@ -8749,10 +6113,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } + "dev": true }, "kind-of": { "version": "6.0.2", @@ -8764,11 +6125,7 @@ "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" - } + "dev": true }, "lazy-cache": { "version": "1.0.4", @@ -8780,19 +6137,13 @@ "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" - } + "dev": true }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "dev": true }, "lcov-parse": { "version": "0.0.10", @@ -8804,20 +6155,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } + "dev": true }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } + "dev": true }, "libbase64": { "version": "0.1.0", @@ -8830,15 +6174,10 @@ "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, - "requires": { - "iconv-lite": "0.4.15", - "libbase64": "0.1.0", - "libqp": "1.1.0" - }, "dependencies": { "iconv-lite": { "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", "dev": true } @@ -8854,17 +6193,13 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.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" - } + "dev": true + }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", + "dev": true }, "livereload-js": { "version": "2.3.0", @@ -8876,52 +6211,31 @@ "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.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } + "dev": true }, "loader-runner": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", + "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", "dev": true }, "loader-utils": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } + "dev": true }, "localtunnel": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.0.tgz", - "integrity": "sha512-wCIiIHJ8kKIcWkTQE3m1VRABvsH2ZuOkiOpZUofUCf6Q42v3VIZ+Q0YfX1Z4sYDRj0muiKL1bLvz1FeoxsPO0w==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.1.tgz", + "integrity": "sha512-HWrhOslklDvxgOGFLxi6fQVnvpl6XdX4sPscfqMZkzi3gtt9V7LKBWYvNUcpHSVvjwCQ6xzXacVvICNbNcyPnQ==", "dev": true, - "requires": { - "axios": "0.17.1", - "debug": "2.6.8", - "openurl": "1.1.1", - "yargs": "6.6.0" - }, "dependencies": { "axios": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", - "dev": true, - "requires": { - "follow-redirects": "^1.2.5", - "is-buffer": "^1.1.5" - } + "dev": true }, "camelcase": { "version": "3.0.0", @@ -8930,74 +6244,52 @@ "dev": true }, "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true }, "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" - } + "dev": true }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } + "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -9009,31 +6301,19 @@ "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" - } + "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=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "dev": true }, "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" - } + "dev": true }, "which-module": { "version": "1.0.0", @@ -9043,33 +6323,15 @@ }, "yargs": { "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "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": "^4.2.0" - } + "dev": true }, "yargs-parser": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - } + "dev": true } } }, @@ -9077,16 +6339,12 @@ "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" - } + "dev": true }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash._arraycopy": { @@ -9106,21 +6364,12 @@ "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - }, "dependencies": { "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.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } + "dev": true } } }, @@ -9129,25 +6378,12 @@ "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", "dev": true, - "requires": { - "lodash._arraycopy": "^3.0.0", - "lodash._arrayeach": "^3.0.0", - "lodash._baseassign": "^3.0.0", - "lodash._basefor": "^3.0.0", - "lodash.isarray": "^3.0.0", - "lodash.keys": "^3.0.0" - }, "dependencies": { "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.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } + "dev": true } } }, @@ -9185,10 +6421,7 @@ "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, - "requires": { - "lodash._htmlescapes": "~2.4.1" - } + "dev": true }, "lodash._escapestringchar": { "version": "2.4.1", @@ -9248,11 +6481,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "requires": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" - } + "dev": true }, "lodash._root": { "version": "3.0.1", @@ -9264,10 +6493,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1" - } + "dev": true }, "lodash.assign": { "version": "4.2.0", @@ -9279,12 +6505,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true, - "requires": { - "lodash._baseclone": "^3.0.0", - "lodash._bindcallback": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } + "dev": true }, "lodash.debounce": { "version": "4.0.8", @@ -9296,11 +6517,7 @@ "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" - } + "dev": true }, "lodash.defaultsdeep": { "version": "4.6.0", @@ -9312,12 +6529,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" - } + "dev": true }, "lodash.get": { "version": "4.4.2", @@ -9341,21 +6553,13 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1" - } + "dev": true }, "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, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } + "dev": true }, "lodash.merge": { "version": "4.6.1", @@ -9379,35 +6583,19 @@ "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" - } + "dev": true }, "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" - } + "dev": true }, "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, - "requires": { - "lodash.keys": "~2.4.1" - } + "dev": true }, "log-driver": { "version": "1.2.7", @@ -9420,38 +6608,24 @@ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, - "requires": { - "chalk": "^2.0.1" - }, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } + "dev": true }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "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" - } + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true } } }, @@ -9460,26 +6634,11 @@ "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", "integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==", "dev": true, - "requires": { - "amqplib": "^0.5.2", - "axios": "^0.15.3", - "circular-json": "^0.5.4", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "hipchat-notifier": "^1.1.0", - "loggly": "^1.1.0", - "mailgun-js": "^0.18.0", - "nodemailer": "^2.5.0", - "redis": "^2.7.1", - "semver": "^5.5.0", - "slack-node": "~0.2.0", - "streamroller": "0.7.0" - }, "dependencies": { "circular-json": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.5.tgz", - "integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.7.tgz", + "integrity": "sha512-/pXoV1JA847qRKPrHbBK6YIBGFF8GOP4wzSgUOA7q0ew0vAv0iJswP+2/nZQ9uzA3Azi7eTrg9L2yzXc/7ZMIA==", "dev": true } } @@ -9490,11 +6649,6 @@ "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", "dev": true, "optional": true, - "requires": { - "json-stringify-safe": "5.0.x", - "request": "2.75.x", - "timespan": "2.3.x" - }, "dependencies": { "assert-plus": { "version": "0.2.0", @@ -9515,47 +6669,28 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true, - "optional": true, - "requires": { - "readable-stream": "2.0.6" - } + "optional": true }, "form-data": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", "dev": true, - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.11" - } + "optional": true }, "har-validator": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", "dev": true, - "optional": true, - "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" - } + "optional": true }, "http-signature": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, - "optional": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } + "optional": true }, "node-uuid": { "version": "1.4.8", @@ -9580,43 +6715,17 @@ }, "request": { "version": "2.75.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "resolved": "http://registry.npmjs.org/request/-/request-2.75.0.tgz", "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", "dev": true, - "optional": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "bl": "~1.1.2", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.0.0", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "node-uuid": "~1.4.7", - "oauth-sign": "~0.8.1", - "qs": "~6.2.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1" - } + "optional": true }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, - "optional": true, - "requires": { - "punycode": "^1.4.1" - } + "optional": true }, "tunnel-agent": { "version": "0.4.3", @@ -9628,9 +6737,9 @@ } }, "lolex": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.1.tgz", - "integrity": "sha512-Oo2Si3RMKV3+lV5MsSWplDQFoTClz/24S0MMHYcgGWWmFXr6TMlqcqk/l1GtH+d5wLBwNRiqGnwDRMirtFalJw==", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", "dev": true }, "longest": { @@ -9649,20 +6758,13 @@ "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" - } + "dev": true }, "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" - } + "dev": true }, "lowercase-keys": { "version": "1.0.1", @@ -9674,39 +6776,25 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + "dev": true }, "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "requires": { - "es5-ext": "~0.10.2" - } + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=" }, "magic-string": { "version": "0.16.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", + "resolved": "http://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", - "dev": true, - "requires": { - "vlq": "^0.2.1" - } + "dev": true }, "mailcomposer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", "dev": true, - "optional": true, - "requires": { - "buildmail": "4.0.1", - "libmime": "3.0.0" - } + "optional": true }, "mailgun-js": { "version": "0.18.1", @@ -9714,27 +6802,27 @@ "integrity": "sha512-lvuMP14u24HS2uBsJEnzSyPMxzU2b99tQsIx1o6QNjqxjk8b3WvR+vq5oG1mjqz/IBYo+5gF+uSoDS0RkMVHmg==", "dev": true, "optional": true, - "requires": { - "async": "~2.6.0", - "debug": "~3.1.0", - "form-data": "~2.3.0", - "inflection": "~1.12.0", - "is-stream": "^1.1.0", - "path-proxy": "~1.0.0", - "promisify-call": "^2.0.2", - "proxy-agent": "~3.0.0", - "tsscmp": "~1.0.0" - }, "dependencies": { "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, - "optional": true, - "requires": { - "lodash": "^4.17.10" - } + "optional": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "optional": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true } } }, @@ -9742,34 +6830,25 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } + "dev": true }, "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, "make-error-cause": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "^1.2.0" - } + "dev": true }, "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, - "requires": { - "kind-of": "^6.0.2" - } + "dev": true }, "map-cache": { "version": "0.2.2", @@ -9784,19 +6863,16 @@ "dev": true }, "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, "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, - "requires": { - "object-visit": "^1.0.0" - } + "dev": true }, "markdown-escapes": { "version": "1.0.2", @@ -9810,53 +6886,11 @@ "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", "dev": true }, - "match-stream": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", - "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "readable-stream": "~1.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.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" - } - }, - "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 - } - } - }, "matchdep": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - } + "dev": true }, "math-random": { "version": "1.0.1", @@ -9865,78 +6899,46 @@ "dev": true }, "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } + "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 }, "mdast-util-compact": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", - "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", - "dev": true, - "requires": { - "unist-util-modify-children": "^1.0.0", - "unist-util-visit": "^1.1.0" - } + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz", + "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==", + "dev": true }, "mdast-util-definitions": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.2.tgz", - "integrity": "sha512-9NloPSwaB9f1PKcGqaScfqRf6zKOEjTIXVIbPOmgWI/JKxznlgVXC5C+8qgl3AjYg2vJBRgLYfLICaNiac89iA==", - "dev": true, - "requires": { - "unist-util-visit": "^1.0.0" - } + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.3.tgz", + "integrity": "sha512-P6wpRO8YVQ1iv30maMc93NLh7COvufglBE8/ldcOyYmk5EbfF0YeqlLgtqP/FOBU501Kqar1x5wYWwB3Nga74g==", + "dev": true }, "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, - "requires": { - "mdast-util-to-string": "^1.0.0" - } + "dev": true }, "mdast-util-to-hast": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.2.tgz", "integrity": "sha512-YI8Ea3TFWEZrS31+6Q/d8ZYTOSDKM06IPc3l2+OMFX1o3JTG2mrztlmzDsUMwIXLWofEdTVl/WXBgRG6ddlU/A==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.0", - "detab": "^2.0.0", - "mdast-util-definitions": "^1.2.0", - "mdurl": "^1.0.1", - "trim": "0.0.1", - "trim-lines": "^1.0.0", - "unist-builder": "^1.0.1", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.0", - "xtend": "^4.0.1" - } + "dev": true }, "mdast-util-to-string": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.4.tgz", - "integrity": "sha1-XEVch4yTVfDB5/PotxnPWDaRrPs=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz", + "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==", "dev": true }, "mdast-util-toc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.0.1.tgz", - "integrity": "sha1-sdLLI7+wH4Evp7Vb/+iwqL7fbyE=", - "dev": true, - "requires": { - "github-slugger": "^1.1.1", - "mdast-util-to-string": "^1.0.2", - "unist-util-visit": "^1.1.0" - } + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.1.0.tgz", + "integrity": "sha512-ove/QQWSrYOrf9G3xn2MTAjy7PKCtCmm261wpQwecoPAsUtkihkMVczxFqil7VihxgSz4ID9c8bBTsyXR30gQg==", + "dev": true }, "mdurl": { "version": "1.0.1", @@ -9954,80 +6956,40 @@ "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.0.0" - } + "dev": true }, "memoizee": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "requires": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==" }, "memory-fs": { "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" - } + "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": { "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" - } + "dev": true }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://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" - } + "dev": true }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10035,30 +6997,19 @@ "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -10070,31 +7021,19 @@ "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" - } + "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=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "dev": true }, "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" - } + "dev": true } } }, @@ -10108,41 +7047,19 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } + "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.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" - } + "dev": true }, "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.0.0", - "brorand": "^1.0.1" - } + "dev": true }, "mime": { "version": "1.6.0", @@ -10151,19 +7068,16 @@ "dev": true }, "mime-db": { - "version": "1.35.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", - "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", "dev": true }, "mime-types": { - "version": "2.1.19", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", - "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", - "dev": true, - "requires": { - "mime-db": "~1.35.0" - } + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "dev": true }, "mimic-fn": { "version": "1.2.0", @@ -10193,14 +7107,11 @@ "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" - } + "dev": true }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, @@ -10209,30 +7120,20 @@ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, - "requires": { - "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" - } + "dev": true } } }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } + "dev": true }, "mkpath": { "version": "1.0.0", @@ -10242,35 +7143,21 @@ }, "mocha": { "version": "2.2.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", + "resolved": "http://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", "dev": true, - "requires": { - "commander": "2.3.0", - "debug": "2.0.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.3", - "growl": "1.8.1", - "jade": "0.26.3", - "mkdirp": "0.5.0", - "supports-color": "~1.2.0" - }, "dependencies": { "commander": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.3.0.tgz", "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", "dev": true }, "debug": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", - "dev": true, - "requires": { - "ms": "0.6.2" - } + "dev": true }, "escape-string-regexp": { "version": "1.0.2", @@ -10282,12 +7169,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", - "dev": true, - "requires": { - "graceful-fs": "~2.0.0", - "inherits": "2", - "minimatch": "~0.2.11" - } + "dev": true }, "graceful-fs": { "version": "2.0.3", @@ -10311,24 +7193,17 @@ "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } + "dev": true }, "mkdirp": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } + "dev": true }, "ms": { "version": "0.6.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "resolved": "http://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", "dev": true }, @@ -10342,17 +7217,13 @@ }, "mock-fs": { "version": "3.12.1", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", + "resolved": "http://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", "dev": true, - "requires": { - "rewire": "2.5.2", - "semver": "5.3.0" - }, "dependencies": { "semver": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } @@ -10360,50 +7231,21 @@ }, "module-deps-sortable": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", + "resolved": "http://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "browser-resolve": "^1.7.0", - "concat-stream": "~1.5.0", - "defined": "^1.0.0", - "detective": "^4.0.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.3", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, "dependencies": { "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~2.0.0", - "typedarray": "~0.0.5" - }, "dependencies": { "readable-stream": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "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" - } + "dev": true } } }, @@ -10428,27 +7270,21 @@ "dev": true }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "multipipe": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, - "requires": { - "duplexer2": "0.0.2" - }, "dependencies": { "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - } + "dev": true }, "isarray": { "version": "0.0.1", @@ -10458,15 +7294,9 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -10477,9 +7307,9 @@ } }, "mute-stdout": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.0.tgz", - "integrity": "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0=", + "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 }, "mute-stream": { @@ -10489,9 +7319,9 @@ "dev": true }, "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", "dev": true, "optional": true }, @@ -10499,25 +7329,6 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "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" - } - }, - "natives": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", - "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", "dev": true }, "natural-compare": { @@ -10528,7 +7339,7 @@ }, "ncp": { "version": "0.4.2", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "resolved": "http://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", "dev": true }, @@ -10539,9 +7350,9 @@ "dev": true }, "neo-async": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz", - "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", "dev": true }, "netmask": { @@ -10556,23 +7367,10 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nightwatch": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.8.tgz", - "integrity": "sha512-2G6mc2DALGs73BfmJjknmm2pClOz+qaYe7UY7RPtX1O0sZ7GLyV/CJXvBUBj42payEGdJpSX51s2s50IBfeQ9Q==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "chai-nightwatch": "~0.1.x", - "ejs": "^2.5.9", - "lodash.clone": "^3.0.3", - "lodash.defaultsdeep": "^4.6.0", - "lodash.merge": "^4.6.1", - "minimatch": "3.0.3", - "mkpath": "1.0.0", - "mocha": "^5.1.1", - "optimist": "^0.6.1", - "proxy-agent": "^3.0.0" - }, + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.11.tgz", + "integrity": "sha512-vEAit4rVgufCAyaqQ6Cxs29A9cBNEKeXxWcPFXrG/AOp+19Vz2K6shoNTwpbdNpDDbp7Pjy1YnvjlG9aQrCsmQ==", + "dev": true, "dependencies": { "browser-stdout": { "version": "1.3.1", @@ -10583,11 +7381,18 @@ }, "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true, "optional": true }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "optional": true + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -10595,14 +7400,27 @@ "dev": true, "optional": true }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "optional": true, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "optional": true + } + } + }, "minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "dev": true, - "requires": { - "brace-expansion": "^1.0.0" - } + "dev": true }, "mocha": { "version": "5.2.0", @@ -10610,87 +7428,51 @@ "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, "optional": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, "dependencies": { "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } + "optional": true } } }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": 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, - "optional": true, - "requires": { - "has-flag": "^3.0.0" - } + "optional": true } } }, "nise": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.2.tgz", - "integrity": "sha512-BxH/DxoQYYdhKgVAfqVy4pzXRZELHOIewzoesxpjYvpU+7YOalQhGNPf7wAx8pLrTNPrHRDlLOkAl8UI0ZpXjw==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.6.tgz", + "integrity": "sha512-1GedetLKzmqmgwabuMSqPsT7oumdR77SBpDfNNJhADRIeA3LN/2RVqR4fFqwvzhAqcTef6PPCzQwITE/YQ8S8A==", "dev": true, - "requires": { - "@sinonjs/formatio": "^2.0.0", - "just-extend": "^1.1.27", - "lolex": "^2.3.2", - "path-to-regexp": "^1.7.0", - "text-encoding": "^0.6.4" + "dependencies": { + "@sinonjs/formatio": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.0.0.tgz", + "integrity": "sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w==", + "dev": true + } } }, "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - } + "dev": true }, "nodemailer": { "version": "2.7.2", @@ -10698,26 +7480,20 @@ "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", "dev": true, "optional": true, - "requires": { - "libmime": "3.0.0", - "mailcomposer": "4.0.1", - "nodemailer-direct-transport": "3.3.2", - "nodemailer-shared": "1.1.0", - "nodemailer-smtp-pool": "2.8.2", - "nodemailer-smtp-transport": "2.7.2", - "socks": "1.1.9" - }, "dependencies": { + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", + "dev": true, + "optional": true + }, "socks": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", "dev": true, - "optional": true, - "requires": { - "ip": "^1.1.2", - "smart-buffer": "^1.0.4" - } + "optional": true } } }, @@ -10726,11 +7502,7 @@ "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "smtp-connection": "2.12.0" - } + "optional": true }, "nodemailer-fetch": { "version": "1.6.0", @@ -10742,34 +7514,21 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true, - "requires": { - "nodemailer-fetch": "1.6.0" - } + "dev": true }, "nodemailer-smtp-pool": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } + "optional": true }, "nodemailer-smtp-transport": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } + "optional": true }, "nodemailer-wellknown": { "version": "0.1.10", @@ -10781,59 +7540,36 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } + "dev": true }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } + "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=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=" }, "normalize-url": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, - "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" - } + "dev": true }, "now-and-later": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", - "dev": true, - "requires": { - "once": "^1.3.2" - } + "dev": true }, "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, - "requires": { - "path-key": "^2.0.0" - } + "dev": true }, "null-check": { "version": "1.0.0", @@ -10869,29 +7605,18 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, "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" - } + "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" - } + "dev": true } } }, @@ -10905,63 +7630,37 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } + "dev": true }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } + "dev": true }, "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, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } + "dev": true }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "dev": true }, "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.4", - "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.1" - } + "dev": true } } }, @@ -10969,47 +7668,31 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "dev": true }, "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, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "dev": true }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } + "dev": true }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } + "dev": true }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } + "dev": true }, "open": { "version": "0.0.5", @@ -11028,10 +7711,6 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, "dependencies": { "wordwrap": { "version": "0.0.3", @@ -11046,17 +7725,10 @@ "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", "dev": true, - "requires": { - "acorn": "^3.3.0", - "concat-stream": "^1.5.1", - "estree-walker": "^0.3.0", - "magic-string": "^0.16.0", - "yargs": "^4.8.1" - }, "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, @@ -11070,62 +7742,37 @@ "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" - } + "dev": true }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://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" - } + "dev": true }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } + "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -11137,31 +7784,19 @@ "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" - } + "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=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "dev": true }, "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" - } + "dev": true }, "which-module": { "version": "1.0.0", @@ -11171,35 +7806,15 @@ }, "yargs": { "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, - "requires": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "lodash.assign": "^4.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.1", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.1" - } + "dev": true }, "yargs-parser": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "lodash.assign": "^4.0.6" - } + "dev": true } } }, @@ -11207,24 +7822,13 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } + "dev": true }, "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, - "requires": { - "readable-stream": "^2.0.1" - } + "dev": true }, "os-browserify": { "version": "0.3.0", @@ -11242,12 +7846,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } + "dev": true }, "os-tmpdir": { "version": "1.0.2", @@ -11255,15 +7854,9 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "over": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", - "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", - "dev": true - }, "p-cancelable": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "resolved": "http://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", "dev": true }, @@ -11275,7 +7868,7 @@ }, "p-is-promise": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", "dev": true }, @@ -11283,28 +7876,19 @@ "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" - } + "dev": true }, "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.1.0" - } + "dev": true }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -11313,20 +7897,10 @@ "dev": true }, "pac-proxy-agent": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", - "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^3.0.0" - }, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", + "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", + "dev": true, "dependencies": { "bytes": { "version": "3.0.0", @@ -11336,46 +7910,21 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://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" - } + "dev": true }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } + "dev": true }, "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", - "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", - "dev": true, - "requires": { - "agent-base": "^4.1.0", - "socks": "^1.1.10" - } + "dev": true }, "statuses": { "version": "1.5.0", @@ -11389,14 +7938,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } + "dev": true }, "pako": { "version": "1.0.6", @@ -11408,59 +7950,37 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true, - "requires": { - "path-platform": "~0.11.15" - } + "dev": true }, "parse-asn1": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true, - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" - } + "dev": true }, "parse-domain": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.2.tgz", "integrity": "sha512-I1HuHXYL8hZp9MYf0jHZE2nW0qhJnqBAxKOR9sGCbiBoD3znYrp4nh3SH9dkt2+f6gEenEj6sh537FTNe+QBqg==", "dev": true, - "requires": { - "chai": "^4.1.2", - "fs-copy-file-sync": "^1.1.1", - "got": "^8.0.1", - "mkdirp": "^0.5.1", - "mocha": "^4.0.1" - }, "dependencies": { "chai": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", - "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", - "dev": true, - "requires": { - "assertion-error": "^1.0.1", - "check-error": "^1.0.1", - "deep-eql": "^3.0.0", - "get-func-name": "^2.0.0", - "pathval": "^1.0.0", - "type-detect": "^4.0.0" - } + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "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, - "requires": { - "type-detect": "^4.0.0" - } + "dev": true }, "diff": { "version": "3.3.1", @@ -11468,6 +7988,12 @@ "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "dev": true }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, "growl": { "version": "1.10.3", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", @@ -11484,28 +8010,19 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } + "dev": true }, "type-detect": { "version": "4.0.8", @@ -11516,50 +8033,28 @@ } }, "parse-entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.2.tgz", - "integrity": "sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg==", - "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" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.0.tgz", + "integrity": "sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==", + "dev": true }, "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, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } + "dev": true }, "parse-git-config": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", - "dev": true, - "requires": { - "ini": "^1.3.3" - } + "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.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, "dependencies": { "is-extglob": { "version": "1.0.0", @@ -11571,10 +8066,7 @@ "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" - } + "dev": true } } }, @@ -11582,11 +8074,7 @@ "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.1", - "json-parse-better-errors": "^1.0.1" - } + "dev": true }, "parse-passwd": { "version": "1.0.0", @@ -11598,29 +8086,19 @@ "version": "1.3.11", "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "protocols": "^1.4.0" - } + "dev": true }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "dev": true }, "parseuri": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "dev": true }, "parseurl": { "version": "1.3.2", @@ -11688,9 +8166,6 @@ "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", "dev": true, "optional": true, - "requires": { - "inflection": "~1.3.0" - }, "dependencies": { "inflection": { "version": "1.3.8", @@ -11705,10 +8180,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } + "dev": true }, "path-root-regex": { "version": "0.1.2", @@ -11721,9 +8193,6 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, - "requires": { - "isarray": "0.0.1" - }, "dependencies": { "isarray": { "version": "0.0.1", @@ -11737,10 +8206,7 @@ "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" - } + "dev": true }, "pathval": { "version": "1.1.0", @@ -11750,29 +8216,19 @@ }, "pause-stream": { "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "~2.3" - } + "dev": true }, "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true }, "pbkdf2-compat": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "resolved": "http://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", "dev": true }, @@ -11798,31 +8254,19 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } + "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" - } + "dev": true }, "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, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - } + "dev": true }, "pluralize": { "version": "7.0.0", @@ -11856,7 +8300,7 @@ }, "pretty-hrtime": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "resolved": "http://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "dev": true }, @@ -11888,10 +8332,7 @@ "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", "dev": true, - "optional": true, - "requires": { - "with-callback": "^1.0.2" - } + "optional": true }, "property-information": { "version": "3.2.0", @@ -11906,20 +8347,10 @@ "dev": true }, "proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.1.tgz", - "integrity": "sha512-mAZexaz9ZxQhYPWfAjzlrloEjW+JHiBFryE4AJXFDTnaXfmH/FKqC1swTRKuEPbHWz02flQNXFOyDUF7zfEG6A==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^2.0.1", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - } + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", + "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", + "dev": true }, "proxy-from-env": { "version": "1.0.0", @@ -11932,11 +8363,6 @@ "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", "dev": true, - "requires": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.0", - "resolve": "~1.1.7" - }, "dependencies": { "resolve": { "version": "1.1.7", @@ -11965,76 +8391,22 @@ "dev": true }, "public-encrypt": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "pullstream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", - "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", - "dev": true, - "requires": { - "over": ">= 0.0.5 < 1", - "readable-stream": "~1.0.31", - "setimmediate": ">= 1.0.2 < 2", - "slice-stream": ">= 1.0.0 < 2" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.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" - } - }, - "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": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true }, "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" - } + "dev": true }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } + "dev": true }, "punycode": { "version": "1.4.1", @@ -12062,14 +8434,9 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } + "dev": true }, "querystring": { "version": "0.2.0", @@ -12085,7 +8452,7 @@ }, "querystringify": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", + "resolved": "http://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "dev": true }, @@ -12094,11 +8461,6 @@ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, "dependencies": { "is-number": { "version": "4.0.0", @@ -12112,20 +8474,13 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } + "dev": true }, "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.0.5", - "safe-buffer": "^5.1.0" - } + "dev": true }, "range-parser": { "version": "1.0.3", @@ -12138,10 +8493,6 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, - "requires": { - "bytes": "1", - "string_decoder": "0.10" - }, "dependencies": { "string_decoder": { "version": "0.10.31", @@ -12155,84 +8506,48 @@ "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.3.2", - "path-type": "^3.0.0" - } + "dev": true }, "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": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - } + "dev": true }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "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" - } + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==" }, "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" - } + "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 }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } + "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" - } + "dev": true }, "redis": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", "dev": true, - "optional": true, - "requires": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.2.0", - "redis-parser": "^2.6.0" - } + "optional": true }, "redis-commands": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", - "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", + "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==", "dev": true, "optional": true }, @@ -12258,35 +8573,23 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "regexpp": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", "dev": true }, @@ -12294,12 +8597,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } + "dev": true }, "regjsgen": { "version": "0.2.0", @@ -12312,9 +8610,6 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -12328,129 +8623,61 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true, - "requires": { - "remark-parse": "^5.0.0", - "remark-stringify": "^5.0.0", - "unified": "^6.0.0" - } + "dev": true }, "remark-html": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true, - "requires": { - "hast-util-sanitize": "^1.0.0", - "hast-util-to-html": "^3.0.0", - "mdast-util-to-hast": "^3.0.0", - "xtend": "^4.0.1" - } + "dev": true }, "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } + "dev": true }, "remark-reference-links": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.2.tgz", "integrity": "sha512-871gKTysBtdQUjoqXA0URWmVhI2jFrpLkWrM3/bydAbsngilDYRjjl2LDAgmNooW8bYbHa57YQ13ld+mYr3TLg==", - "dev": true, - "requires": { - "unist-util-visit": "^1.0.0" - } + "dev": true }, "remark-slug": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.0.tgz", "integrity": "sha512-FW/V7b3ekfDL1eyPDyzfq0qz5HFPKPNWVC2eqFDie45r774FLGoymOS1oU7LVQfdFNEvNLZ6oBJT/oIxAyBISg==", - "dev": true, - "requires": { - "github-slugger": "^1.0.0", - "mdast-util-to-string": "^1.0.0", - "unist-util-visit": "^1.0.0" - } + "dev": true }, "remark-stringify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "is-alphanumeric": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "longest-streak": "^2.0.1", - "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4", - "xtend": "^4.0.1" - } + "dev": true }, "remark-toc": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", - "dev": true, - "requires": { - "mdast-util-toc": "^2.0.0", - "remark-slug": "^5.0.0" - } + "dev": true }, "remote-origin-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true, - "requires": { - "parse-git-config": "^0.2.0" - } + "dev": true }, "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, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } + "dev": true }, "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": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } + "dev": true }, "remove-trailing-separator": { "version": "1.1.0", @@ -12458,9 +8685,9 @@ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", "dev": true }, "repeat-string": { @@ -12473,10 +8700,7 @@ "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" - } + "dev": true }, "replace-ext": { "version": "1.0.0", @@ -12488,62 +8712,26 @@ "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": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } + "dev": true }, "replacestream": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", - "dev": true, - "requires": { - "through": "~2.3.4" - } + "dev": true }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } + "dev": true }, "requestretry": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", "dev": true, - "optional": true, - "requires": { - "extend": "^3.0.0", - "lodash": "^4.15.0", - "request": "^2.74.0", - "when": "^3.7.7" - } + "optional": true }, "require-directory": { "version": "2.1.1", @@ -12561,16 +8749,12 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } + "dev": true }, "requirejs": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", - "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", "dev": true }, "requires-port": { @@ -12583,20 +8767,13 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } + "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": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } + "dev": true }, "resolve-from": { "version": "1.0.1", @@ -12608,10 +8785,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } + "dev": true }, "resolve-url": { "version": "0.2.1", @@ -12622,20 +8796,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } + "dev": true }, "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, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } + "dev": true }, "ret": { "version": "0.1.15", @@ -12653,14 +8820,11 @@ "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": { - "align-text": "^0.1.1" - } + "dev": true }, "rimraf": { "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", "dev": true }, @@ -12668,20 +8832,13 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } + "dev": true }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } + "dev": true }, "rx-lite": { "version": "4.0.8", @@ -12693,10 +8850,7 @@ "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": { - "rx-lite": "*" - } + "dev": true }, "safe-buffer": { "version": "5.1.2", @@ -12713,10 +8867,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -12735,67 +8886,38 @@ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", "dev": true, - "requires": { - "ajv": "^5.0.0" - }, "dependencies": { "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" - } + "dev": true } } }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "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=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } + "dev": true }, "send": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", "dev": true, - "requires": { - "debug": "~2.2.0", - "depd": "~1.1.0", - "destroy": "~1.0.4", - "escape-html": "~1.0.3", - "etag": "~1.7.0", - "fresh": "0.3.0", - "http-errors": "~1.3.1", - "mime": "1.3.4", - "ms": "0.7.1", - "on-finished": "~2.3.0", - "range-parser": "~1.0.3", - "statuses": "~1.2.1" - }, "dependencies": { "debug": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } + "dev": true }, "mime": { "version": "1.3.4", @@ -12805,7 +8927,7 @@ }, "ms": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, @@ -12822,36 +8944,24 @@ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "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" - }, "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" - } + "dev": true }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "statuses": { "version": "1.5.0", @@ -12866,21 +8976,12 @@ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.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" - } + "dev": true }, "etag": { "version": "1.8.1", @@ -12896,15 +8997,9 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://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" - } + "dev": true }, "mime": { "version": "1.4.1", @@ -12912,6 +9007,12 @@ "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 + }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -12922,22 +9023,7 @@ "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "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", - "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" - } + "dev": true }, "statuses": { "version": "1.4.0", @@ -12953,32 +9039,17 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "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" - } + "dev": true } } }, @@ -12996,22 +9067,15 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "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" - } + "dev": true }, "shebang-regex": { "version": "1.0.0", @@ -13023,12 +9087,7 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } + "dev": true }, "sigmund": { "version": "1.0.1", @@ -13044,18 +9103,9 @@ }, "sinon": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "resolved": "http://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "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" - }, "dependencies": { "diff": { "version": "3.5.0", @@ -13064,13 +9114,10 @@ "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" - } + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true }, "type-detect": { "version": "4.0.8", @@ -13085,10 +9132,7 @@ "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", "dev": true, - "optional": true, - "requires": { - "requestretry": "^1.2.2" - } + "optional": true }, "slash": { "version": "1.0.0", @@ -13101,9 +9145,6 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - }, "dependencies": { "is-fullwidth-code-point": { "version": "2.0.0", @@ -13113,99 +9154,47 @@ } } }, - "slice-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", - "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", - "dev": true, - "requires": { - "readable-stream": "~1.0.31" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.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" - } - }, - "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 - } - } - }, "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", + "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", "dev": true }, "smtp-connection": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true, - "requires": { - "httpntlm": "1.6.1", - "nodemailer-shared": "1.1.0" - } + "dev": true }, "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": { - "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" - }, "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" - } + "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.0" - } + "dev": true }, "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" - } + "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": { "version": "0.5.7", @@ -13220,49 +9209,30 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "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.0" - } + "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.0" - } + "dev": true }, "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.0" - } + "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.2" - } + "dev": true } } }, @@ -13271,18 +9241,12 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, "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" - } + "dev": true } } }, @@ -13291,32 +9255,25 @@ "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, - "optional": true, - "requires": { - "hoek": "2.x.x" - } + "optional": true }, "socket.io": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", "dev": true, - "requires": { - "debug": "~2.6.6", - "engine.io": "~3.1.0", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.0.4", - "socket.io-parser": "~3.1.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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -13331,30 +9288,18 @@ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~2.6.4", - "engine.io-client": "~3.1.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.1.1", - "to-array": "0.1.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" - } + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -13363,72 +9308,49 @@ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "has-binary2": "~1.0.2", - "isarray": "2.0.1" - }, "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true + }, "isarray": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "socks": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "dev": true, - "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" - } + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz", + "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", + "dev": true }, "socks-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", - "dev": true, - "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" - }, - "dependencies": { - "smart-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", - "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", - "dev": true - }, - "socks": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz", - "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", - "dev": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" - } - } - } + "dev": true }, "sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } + "dev": true }, "source-list-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "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": { @@ -13439,23 +9361,13 @@ "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==" }, "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" - }, "dependencies": { "source-map": { "version": "0.5.7", @@ -13474,10 +9386,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "dev": true, - "requires": { - "trim": "0.0.1" - } + "dev": true }, "sparkles": { "version": "1.0.1", @@ -13486,54 +9395,40 @@ "dev": true }, "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "dev": true }, "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } + "dev": true }, "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", "dev": true }, "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" - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "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": { - "extend-shallow": "^3.0.0" - } + "dev": true }, "sprintf-js": { "version": "1.0.3", @@ -13542,21 +9437,10 @@ "dev": true }, "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", - "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" - } + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", + "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "dev": true }, "stack-trace": { "version": "0.0.10", @@ -13575,19 +9459,12 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.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" - } + "dev": true } } }, @@ -13602,9 +9479,6 @@ "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", "dev": true, - "requires": { - "readable-stream": "~2.1.0" - }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -13614,18 +9488,9 @@ }, "readable-stream": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "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" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -13639,30 +9504,19 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } + "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.1" - } + "version": "0.2.2", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true }, "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" - } + "dev": true }, "stream-exhaust": { "version": "1.0.2", @@ -13674,14 +9528,7 @@ "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": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } + "dev": true }, "stream-shift": { "version": "1.0.0", @@ -13693,13 +9540,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", - "dev": true, - "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" - } + "dev": true }, "strict-uri-encode": { "version": "1.1.0", @@ -13707,22 +9548,20 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "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==" + }, "string-replace-webpack-plugin": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", "dev": true, - "requires": { - "async": "~0.2.10", - "css-loader": "^0.9.1", - "file-loader": "^0.8.1", - "loader-utils": "~0.2.3", - "style-loader": "^0.8.3" - }, "dependencies": { "async": { "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true }, @@ -13730,13 +9569,7 @@ "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.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } + "dev": true } } }, @@ -13750,32 +9583,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "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==", - "requires": { - "safe-buffer": "~5.1.0" - } + "dev": true }, "stringify-entities": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, - "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } + "dev": true }, "stringstream": { "version": "0.0.6", @@ -13786,12 +9600,9 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "strip-bom": { "version": "3.0.0", @@ -13814,10 +9625,7 @@ "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" - } + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -13827,26 +9635,17 @@ }, "style-loader": { "version": "0.8.3", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", + "resolved": "http://registry.npmjs.org/style-loader/-/style-loader-0.8.3.tgz", "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", "dev": true, "optional": true, - "requires": { - "loader-utils": "^0.2.5" - }, "dependencies": { "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, - "optional": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } + "optional": true } } }, @@ -13855,13 +9654,10 @@ "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, - "requires": { - "minimist": "^1.1.0" - }, "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -13877,37 +9673,19 @@ "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.1", - "es6-symbol": "^3.1.1" - } + "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", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - }, "dependencies": { "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" - } + "dev": true }, "ansi-regex": { "version": "3.0.0", @@ -13919,21 +9697,13 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } + "dev": true }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -13945,29 +9715,19 @@ "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" - } + "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": { - "ansi-regex": "^3.0.0" - } + "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" - } + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true } } }, @@ -13981,17 +9741,11 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true, - "requires": { - "duplexify": "^3.5.0", - "fork-stream": "^0.0.4", - "merge-stream": "^1.0.0", - "through2": "^2.0.1" - } + "dev": true }, "text-encoding": { "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", "dev": true }, @@ -14009,28 +9763,20 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "through2": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - } + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=" }, "through2-filter": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } + "dev": true }, "thunkify": { "version": "2.1.2", @@ -14054,19 +9800,12 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } + "dev": true }, "timers-ext": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", - "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==", - "requires": { - "es5-ext": "~0.10.14", - "next-tick": "1" - } + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==" }, "timespan": { "version": "2.3.0", @@ -14079,34 +9818,19 @@ "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": { - "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "to-array": { "version": "0.1.4", @@ -14131,18 +9855,12 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "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" - } + "dev": true } } }, @@ -14150,42 +9868,25 @@ "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" - } + "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" - } + "dev": true }, "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": { - "through2": "^2.0.3" - } + "dev": true }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } + "dev": true }, "traverse": { "version": "0.3.9", @@ -14246,26 +9947,19 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } + "dev": true }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true + "dev": true }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } + "dev": true }, "type-detect": { "version": "1.0.0", @@ -14277,11 +9971,7 @@ "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } + "dev": true }, "typedarray": { "version": "0.0.6", @@ -14294,11 +9984,6 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, "dependencies": { "camelcase": { "version": "1.2.1", @@ -14310,12 +9995,7 @@ "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.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } + "dev": true }, "source-map": { "version": "0.5.7", @@ -14337,15 +10017,9 @@ }, "yargs": { "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } + "dev": true } } }, @@ -14360,11 +10034,6 @@ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, - "requires": { - "source-map": "^0.5.6", - "uglify-js": "^2.8.29", - "webpack-sources": "^1.0.1" - }, "dependencies": { "source-map": { "version": "0.5.7", @@ -14396,18 +10065,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", - "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", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } + "dev": true }, "undertaker-registry": { "version": "1.0.1", @@ -14419,58 +10077,31 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" - } + "dev": true }, "unified": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^2.0.0", - "x-is-string": "^0.1.0" - } + "dev": true }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "dev": true }, "set-value": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } + "dev": true } } }, @@ -14478,20 +10109,13 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "^1.0.0", - "through2-filter": "^2.0.0" - } + "dev": true }, "unist-builder": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.2.tgz", - "integrity": "sha1-jDuZA+9kvPsRfdfPal2Y/Bs7J7Y=", - "dev": true, - "requires": { - "object-assign": "^4.1.0" - } + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.3.tgz", + "integrity": "sha512-/KB8GEaoeHRyIqClL+Kam+Y5NWJ6yEiPsAfv1M+O1p+aKGgjR89WwoEHKTyOj17L6kAlqtKpAgv2nWvdbQDEig==", + "dev": true }, "unist-util-generated": { "version": "1.1.2", @@ -14505,15 +10129,6 @@ "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", "dev": true }, - "unist-util-modify-children": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", - "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", - "dev": true, - "requires": { - "array-iterate": "^1.0.0" - } - }, "unist-util-position": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.1.tgz", @@ -14524,10 +10139,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } + "dev": true }, "unist-util-stringify-position": { "version": "1.1.2", @@ -14539,19 +10151,13 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } + "dev": true }, "unist-util-visit-parents": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", - "dev": true, - "requires": { - "unist-util-is": "^2.1.2" - } + "dev": true }, "unpipe": { "version": "1.0.0", @@ -14564,30 +10170,18 @@ "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=", "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.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" - } + "dev": true } } }, @@ -14599,42 +10193,16 @@ } } }, - "unzip": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", - "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", + "unzipper": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.4.tgz", + "integrity": "sha512-kGrkTaphmXE+0/A5Q7rwcm/xHlDkXDOGEh6wuiN3SUQsyVWd7V51rwqttlNTT91JrLkfn34MoBNf38unF0vhRw==", "dev": true, - "requires": { - "binary": ">= 0.3.0 < 1", - "fstream": ">= 0.1.30 < 1", - "match-stream": ">= 0.0.2 < 1", - "pullstream": ">= 0.4.1 < 1", - "readable-stream": "~1.0.31", - "setimmediate": ">= 1.0.1 < 2" - }, "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "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" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "bluebird": { + "version": "3.4.7", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true } } @@ -14655,10 +10223,6 @@ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, "dependencies": { "punycode": { "version": "1.3.2", @@ -14673,15 +10237,11 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", "dev": true, - "requires": { - "querystringify": "^2.0.0", - "requires-port": "^1.0.0" - }, "dependencies": { "querystringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", + "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", "dev": true } } @@ -14690,10 +10250,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "requires": { - "prepend-http": "^2.0.0" - } + "dev": true }, "url-to-options": { "version": "1.0.1", @@ -14712,10 +10269,6 @@ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "dev": true, - "requires": { - "lru-cache": "2.2.x", - "tmp": "0.0.x" - }, "dependencies": { "lru-cache": { "version": "2.2.4", @@ -14729,10 +10282,7 @@ "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" - } + "dev": true }, "util-deprecate": { "version": "1.0.2", @@ -14762,20 +10312,13 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "dev": true }, "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": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } + "dev": true }, "value-or-function": { "version": "3.0.0", @@ -14787,24 +10330,13 @@ "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.2.0" - } + "dev": true }, "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true, - "requires": { - "is-buffer": "^1.1.4", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } + "dev": true }, "vfile-location": { "version": "2.0.3", @@ -14816,23 +10348,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz", "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } + "dev": true }, "vfile-reporter": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, - "requires": { - "repeat-string": "^1.5.0", - "string-width": "^1.0.0", - "supports-color": "^4.1.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-statistics": "^1.1.0" - }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -14844,10 +10366,7 @@ "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" - } + "dev": true } } }, @@ -14867,64 +10386,25 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "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" - } + "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - }, "dependencies": { "source-map": { "version": "0.5.7", @@ -14944,10 +10424,7 @@ "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } + "dev": true }, "void-elements": { "version": "2.0.1", @@ -14959,51 +10436,19 @@ "version": "2.3.14", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", - "dev": true, - "requires": { - "foreachasync": "^3.0.0" - } + "dev": true }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - } + "dev": true }, "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.0.0", - "acorn-dynamic-import": "^2.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "async": "^2.1.2", - "enhanced-resolve": "^3.4.0", - "escope": "^3.6.0", - "interpret": "^1.0.0", - "json-loader": "^0.5.4", - "json5": "^0.5.1", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "mkdirp": "~0.5.0", - "node-libs-browser": "^2.0.0", - "source-map": "^0.5.3", - "supports-color": "^4.2.1", - "tapable": "^0.2.7", - "uglifyjs-webpack-plugin": "^0.4.6", - "watchpack": "^1.4.0", - "webpack-sources": "^1.0.1", - "yargs": "^8.0.2" - }, "dependencies": { "ajv-keywords": { "version": "3.2.0", @@ -15021,10 +10466,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } + "dev": true }, "has-flag": { "version": "2.0.0", @@ -15040,33 +10482,21 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "http://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.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } + "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" - } + "dev": true }, "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.0.0" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -15078,22 +10508,13 @@ "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.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "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.0.0", - "read-pkg": "^2.0.0" - } + "dev": true }, "source-map": { "version": "0.5.7", @@ -15105,50 +10526,25 @@ "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" - } + "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": { - "ansi-regex": "^3.0.0" - } + "dev": true }, "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" - } + "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.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.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.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" - } + "dev": true } } }, @@ -15157,10 +10553,6 @@ "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, - "requires": { - "source-list-map": "~0.1.7", - "source-map": "~0.4.1" - }, "dependencies": { "source-list-map": { "version": "0.1.8", @@ -15172,10 +10564,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } + "dev": true } } }, @@ -15184,50 +10573,30 @@ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", "dev": true, - "requires": { - "memory-fs": "~0.4.1", - "mime": "^1.5.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "time-stamp": "^2.0.0" - }, "dependencies": { "time-stamp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.1.tgz", - "integrity": "sha512-KUnkvOWC3C+pEbwE/0u3CcmNpGCDqkYGYZOphe1QFxApYQkJ5g195TDBjgZch/zG6chU1NcabLwnM7BCpWAzTQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.1.0.tgz", + "integrity": "sha512-lJbq6KsFhZJtN3fPUVje1tq/hHsJOKUUcUj/MGCiQR6qWBDcyi5kxL9J7/RnaEChCn0+L/DUN2WvemDrkk4i3Q==", "dev": true } } }, "webpack-sources": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "dev": true }, "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": { - "gulp-util": "^3.0.7", - "lodash.clone": "^4.3.2", - "lodash.some": "^4.2.2", - "memory-fs": "^0.3.0", - "through": "^2.3.8", - "vinyl": "^1.1.0", - "webpack": "^1.12.9" - }, "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, @@ -15235,20 +10604,13 @@ "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.1.5", - "normalize-path": "^2.0.0" - } + "dev": true }, "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.0.1" - } + "dev": true }, "array-unique": { "version": "0.2.1", @@ -15260,30 +10622,19 @@ "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.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } + "dev": true }, "browserify-aes": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true, - "requires": { - "inherits": "^2.0.1" - } + "dev": true }, "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.0" - } + "dev": true }, "camelcase": { "version": "1.2.1", @@ -15295,29 +10646,13 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } + "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.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } + "dev": true }, "clone": { "version": "1.0.4", @@ -15333,26 +10668,15 @@ }, "crypto-browserify": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", + "resolved": "http://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" - } + "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.1.2", - "memory-fs": "^0.2.0", - "tapable": "^0.1.8" - }, "dependencies": { "memory-fs": { "version": "0.2.0", @@ -15366,50 +10690,31 @@ "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.0" - } + "dev": true }, "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.1.0" - } + "dev": true }, "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" - } + "dev": true }, "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": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } + "dev": true }, "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.0" - } + "dev": true }, "has-flag": { "version": "1.0.0", @@ -15439,49 +10744,31 @@ "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "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" - } + "dev": true }, "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.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } + "dev": true }, "lodash.clone": { "version": "4.5.0", @@ -15493,63 +10780,19 @@ "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.3", - "readable-stream": "^2.0.1" - } + "dev": true }, "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.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } + "dev": true }, "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.1.1", - "browserify-zlib": "^0.1.4", - "buffer": "^4.9.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "3.3.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "0.0.1", - "os-browserify": "^0.2.0", - "path-browserify": "0.0.0", - "process": "^0.11.0", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.0.5", - "stream-browserify": "^2.0.1", - "stream-http": "^2.3.1", - "string_decoder": "^0.10.25", - "timers-browserify": "^2.0.2", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - } + "dev": true }, "os-browserify": { "version": "0.2.1", @@ -15571,13 +10814,13 @@ }, "ripemd160": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "resolved": "http://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", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", "dev": true }, @@ -15597,32 +10840,23 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } + "dev": true }, "tapable": { "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "resolved": "http://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", "dev": true }, "uglify-js": { "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, - "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, "dependencies": { "async": { "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true } @@ -15632,27 +10866,17 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } + "dev": true }, "watchpack": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, - "requires": { - "async": "^0.9.0", - "chokidar": "^1.0.0", - "graceful-fs": "^4.1.2" - }, "dependencies": { "async": { "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true } @@ -15662,24 +10886,7 @@ "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.0.0", - "async": "^1.3.0", - "clone": "^1.0.2", - "enhanced-resolve": "~0.9.0", - "interpret": "^0.6.4", - "loader-utils": "^0.2.11", - "memory-fs": "~0.3.0", - "mkdirp": "~0.5.0", - "node-libs-browser": "^0.7.0", - "optimist": "~0.6.0", - "supports-color": "^3.1.0", - "tapable": "~0.1.8", - "uglify-js": "~2.7.3", - "watchpack": "^0.2.1", - "webpack-core": "~0.6.9" - } + "dev": true }, "window-size": { "version": "0.1.0", @@ -15695,15 +10902,9 @@ }, "yargs": { "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } + "dev": true } } }, @@ -15711,11 +10912,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true, - "requires": { - "http-parser-js": ">=0.4.0", - "websocket-extensions": ">=0.1.1" - } + "dev": true }, "websocket-extensions": { "version": "0.1.3", @@ -15734,10 +10931,7 @@ "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" - } + "dev": true }, "which-module": { "version": "2.0.0", @@ -15766,13 +10960,9 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } + "dev": true }, "wrappy": { "version": "1.0.2", @@ -15784,21 +10974,13 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } + "dev": true }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } + "dev": true }, "x-is-string": { "version": "0.1.0", @@ -15837,7 +11019,7 @@ }, "yargs": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", "dev": true }, @@ -15845,10 +11027,7 @@ "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" - } + "dev": true }, "yeast": { "version": "0.1.2", diff --git a/package.json b/package.json index 40436a6af36..0bfe17c256e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.28.0", + "version": "1.29.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 175a7ca63112c0e6d14a5d671ac1c56f5131d9a1 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 17 Oct 2018 09:10:09 -0600 Subject: [PATCH 0768/1594] add a check against the size config when setting targeting (#3183) --- src/adaptermanager.js | 15 +-------------- src/sizeMapping.js | 27 +++++++++++++++++++++++++++ src/targeting.js | 2 ++ test/spec/sizeMapping_spec.js | 9 ++++++++- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 8d07e0ccacc..c324bb72e6c 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -1,7 +1,7 @@ /** @module adaptermanger */ import { flatten, getBidderCodes, getDefinedParams, shuffle, timestamp } from './utils'; -import { resolveStatus } from './sizeMapping'; +import { getLabels, resolveStatus } from './sizeMapping'; import { processNativeAdUnitParams, nativeAdapters } from './native'; import { newBidder } from './adapters/bidderFactory'; import { ajaxBuilder } from 'src/ajax'; @@ -34,19 +34,6 @@ var _analyticsRegistry = {}; * @property {Array} activeLabels the labels specified as being active by requestBids */ -/** - * Returns object describing the status of labels on the adUnit or bidder along with labels passed into requestBids - * @param bidOrAdUnit the bidder or adUnit to get label info on - * @param activeLabels the labels passed to requestBids - * @returns {LabelDescriptor} - */ -function getLabels(bidOrAdUnit, activeLabels) { - if (bidOrAdUnit.labelAll) { - return {labelAll: true, labels: bidOrAdUnit.labelAll, activeLabels}; - } - return {labelAll: false, labels: bidOrAdUnit.labelAny, activeLabels}; -} - function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels, src}) { return adUnits.reduce((result, adUnit) => { let { diff --git a/src/sizeMapping.js b/src/sizeMapping.js index a8fec661bd1..2cf1b1a0fa9 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -24,6 +24,33 @@ export function setSizeConfig(config) { } config.getConfig('sizeConfig', config => setSizeConfig(config.sizeConfig)); +/** + * Returns object describing the status of labels on the adUnit or bidder along with labels passed into requestBids + * @param bidOrAdUnit the bidder or adUnit to get label info on + * @param activeLabels the labels passed to requestBids + * @returns {LabelDescriptor} + */ +export function getLabels(bidOrAdUnit, activeLabels) { + if (bidOrAdUnit.labelAll) { + return {labelAll: true, labels: bidOrAdUnit.labelAll, activeLabels}; + } + return {labelAll: false, labels: bidOrAdUnit.labelAny, activeLabels}; +} + +/** + * Determines whether a single size is valid given configured sizes + * @param {Array} size [width, height] + * @param {Array} configs + * @returns {boolean} + */ +export function sizeSupported(size, configs = sizeConfig) { + let maps = evaluateSizeConfig(configs); + if (!maps.shouldFilter) { + return true; + } + return !!maps.sizesSupported[size]; +} + /** * Resolves the unique set of the union of all sizes and labels that are active from a SizeConfig.mediaQuery match * @param {Array} labels Labels specified on adUnit or bidder diff --git a/src/targeting.js b/src/targeting.js index 8cb567001d5..dcd59f362c6 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -2,6 +2,7 @@ import { uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, gro import { config } from './config'; import { NATIVE_TARGETING_KEYS } from './native'; import { auctionManager } from './auctionManager'; +import { sizeSupported } from './sizeMapping'; import includes from 'core-js/library/fn/array/includes'; const utils = require('./utils.js'); @@ -198,6 +199,7 @@ export function newTargeting(auctionManager) { function getBidsReceived() { const bidsReceived = auctionManager.getBidsReceived() + .filter(bid => bid.mediaType !== 'banner' || sizeSupported([bid.width, bid.height])) .filter(isUnusedBid) .filter(exports.isBidNotExpired) ; diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index ac51d405e36..aca4ccf8f54 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { resolveStatus, setSizeConfig } from 'src/sizeMapping'; +import { resolveStatus, setSizeConfig, sizeSupported } from 'src/sizeMapping'; import includes from 'core-js/library/fn/array/includes'; let utils = require('src/utils'); @@ -75,6 +75,13 @@ describe('sizeMapping', function () { }); describe('when handling sizes', function () { + it('should allow us to validate a single size', function() { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + expect(sizeSupported([300, 250])).to.equal(true); + expect(sizeSupported([80, 80])).to.equal(false); + }); + it('should log a warning when mediaQuery property missing from sizeConfig', function () { let errorConfig = deepClone(sizeConfig); From c238e682d595dcb3b1f3861f39ee648497c51a10 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 17 Oct 2018 14:35:26 -0400 Subject: [PATCH 0769/1594] add stub for adloader.loadScript in various adapter test files (#3193) * add stub for adloader in various adapter test files * remove unneeded commented line of code --- test/spec/modules/appnexusBidAdapter_spec.js | 12 ++++++++++++ test/spec/modules/beachfrontBidAdapter_spec.js | 12 ++++++++++++ test/spec/modules/consentManagement_spec.js | 4 ++-- test/spec/modules/rockyouBidAdapter_spec.js | 12 ++++++++++++ test/spec/modules/vubleBidAdapter_spec.js | 13 +++++++++++++ test/spec/modules/xhbBidAdapter_spec.js | 12 ++++++++++++ test/spec/modules/zedoBidAdapter_spec.js | 14 +++++++++++++- test/spec/unit/core/bidderFactory_spec.js | 12 ++++++++++++ 8 files changed, 88 insertions(+), 3 deletions(-) diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 9be87ac8628..37126475af8 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -4,9 +4,21 @@ import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; +const adloader = require('src/adloader'); describe('AppNexusAdapter', function () { const adapter = newBidder(spec); + let loadScriptStub; + + before(function() { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); + + after(function() { + loadScriptStub.restore(); + }); describe('inherited functions', function () { it('exists and is a function', function () { diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 21e175a5b82..edaff2c88ce 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,9 +1,21 @@ import { expect } from 'chai'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import * as utils from 'src/utils'; +const adloader = require('src/adloader'); describe('BeachfrontAdapter', function () { let bidRequests; + let loadScriptStub; + + before(function() { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); + + after(function() { + loadScriptStub.restore(); + }); beforeEach(function () { bidRequests = [ diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index 1303d9cd718..6af8c8a4478 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -678,8 +678,8 @@ describe('consentManagement', function () { // Run tests with JSON response and String response // from CMP window postMessage listener. - // testIFramedPage('with/JSON response', false); - // testIFramedPage('with/String response', true); + testIFramedPage('with/JSON response', false); + testIFramedPage('with/String response', true); function testIFramedPage(testName, messageFormatString) { it(`should return the consent string from a postmessage + addEventListener response - ${testName}`, (done) => { diff --git a/test/spec/modules/rockyouBidAdapter_spec.js b/test/spec/modules/rockyouBidAdapter_spec.js index 65d87566c26..81404189802 100644 --- a/test/spec/modules/rockyouBidAdapter_spec.js +++ b/test/spec/modules/rockyouBidAdapter_spec.js @@ -1,9 +1,21 @@ import { expect } from 'chai'; import { spec, internals } from 'modules/rockyouBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; +const adloader = require('src/adloader'); describe('RockYouAdapter', function () { const adapter = newBidder(spec); + let loadScriptStub; + + before(function() { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); + + after(function() { + loadScriptStub.restore(); + }); describe('bid validator', function () { it('rejects a bid that is missing the placementId', function () { diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 8996c1b4957..0a23965b22b 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -3,8 +3,21 @@ import {expect} from 'chai'; import {spec as adapter} from 'modules/vubleBidAdapter'; import * as utils from 'src/utils'; +const adloader = require('../../../src/adloader'); describe('VubleAdapter', function () { + let loadScriptStub; + + before(function() { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); + + after(function() { + loadScriptStub.restore(); + }); + describe('Check methods existance', function () { it('exists and is a function', function () { expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function'); diff --git a/test/spec/modules/xhbBidAdapter_spec.js b/test/spec/modules/xhbBidAdapter_spec.js index e48d3011ed2..9ef90492acc 100644 --- a/test/spec/modules/xhbBidAdapter_spec.js +++ b/test/spec/modules/xhbBidAdapter_spec.js @@ -4,9 +4,21 @@ import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; +const adloader = require('../../../src/adloader'); describe('xhbAdapter', function () { const adapter = newBidder(spec); + let loadScriptStub; + + before(function() { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); + + after(function() { + loadScriptStub.restore(); + }); describe('inherited functions', function () { it('exists and is a function', function () { diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js index abb0a5c97fb..1bae0997749 100644 --- a/test/spec/modules/zedoBidAdapter_spec.js +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -1,7 +1,20 @@ import { expect } from 'chai'; import { spec } from 'modules/zedoBidAdapter'; +const adloader = require('src/adloader'); describe('The ZEDO bidding adapter', function () { + let loadScriptStub; + + before(function() { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); + + after(function() { + loadScriptStub.restore(); + }); + describe('isBidRequestValid', function () { it('should return false when given an invalid bid', function () { const bid = { @@ -245,7 +258,6 @@ describe('The ZEDO bidding adapter', function () { expect(bids[0].vastXml).to.not.equal(''); expect(bids[0].ad).to.be.an('undefined'); expect(bids[0].renderer).not.to.be.an('undefined'); - bids[0].renderer.render(bids[0]); }); }); diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 6cc4a0b172c..bc815a8afd2 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -7,6 +7,7 @@ import { userSync } from 'src/userSync' import * as utils from 'src/utils'; import { config } from 'src/config'; +const adloader = require('src/adloader'); const CODE = 'sampleBidder'; const MOCK_BIDS_REQUEST = { bids: [ @@ -34,6 +35,13 @@ describe('bidders created by newBidder', function () { let bidder; let addBidResponseStub; let doneStub; + let loadScriptStub; + + before(function() { + loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + }); beforeEach(function () { spec = { @@ -48,6 +56,10 @@ describe('bidders created by newBidder', function () { doneStub = sinon.stub(); }); + after(function() { + loadScriptStub.restore(); + }); + describe('when the ajax response is irrelevant', function () { let ajaxStub; From ea96547641e771df639e0d5e55ff029a2cbfae1f Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 17 Oct 2018 14:40:14 -0600 Subject: [PATCH 0770/1594] fix simon spy.reset deprecation warning --- test/spec/auctionmanager_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index f4c6fc22cb7..e4b2458c18b 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -881,7 +881,7 @@ describe('auctionmanager.js', function () { }); afterEach(() => { - doneSpy.reset(); + doneSpy.resetHistory(); xhr.restore(); config.resetConfig(); }); From 73e7014275e31e16a1a878a214de37b0d10eeb94 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 17 Oct 2018 15:41:27 -0600 Subject: [PATCH 0771/1594] Stub adloader across the board to prevent requests going out (#3196) * stub adloader across the board to prevent requests going out * add the adloader stub --- test/mocks/adloaderStub.js | 22 +++++++++++++++++++ test/spec/adloader_spec.js | 2 +- test/spec/auctionmanager_spec.js | 13 ----------- test/spec/modules/appnexusBidAdapter_spec.js | 12 ---------- .../spec/modules/beachfrontBidAdapter_spec.js | 12 ---------- test/spec/modules/rockyouBidAdapter_spec.js | 12 ---------- test/spec/modules/vubleBidAdapter_spec.js | 13 ----------- test/spec/modules/xhbBidAdapter_spec.js | 12 ---------- test/spec/modules/zedoBidAdapter_spec.js | 13 ----------- test/spec/renderer_spec.js | 11 ---------- test/spec/unit/core/adapterManager_spec.js | 6 ----- test/spec/unit/core/bidderFactory_spec.js | 12 ---------- test/spec/unit/pbjs_api_spec.js | 6 ++--- test/test_index.js | 1 + 14 files changed, 26 insertions(+), 121 deletions(-) create mode 100644 test/mocks/adloaderStub.js diff --git a/test/mocks/adloaderStub.js b/test/mocks/adloaderStub.js new file mode 100644 index 00000000000..45a7824e71d --- /dev/null +++ b/test/mocks/adloaderStub.js @@ -0,0 +1,22 @@ +const adloader = require('src/adloader'); + +let sandbox; + +export let loadScript; +export let loadExternalScript; +export let loadScriptStub; +export let loadExternalScriptStub; + +beforeEach(function() { + sandbox = sinon.sandbox.create(); + loadScript = adloader.loadScript; + loadExternalScript = adloader.loadExternalScript; + loadScriptStub = sandbox.stub(adloader, 'loadScript').callsFake((...args) => { + args[1](); + }); + loadExternalScriptStub = sandbox.stub(adloader, 'loadExternalScript'); +}); + +afterEach(function() { + sandbox.restore(); +}); diff --git a/test/spec/adloader_spec.js b/test/spec/adloader_spec.js index 5c4eff31028..27f574c9c42 100644 --- a/test/spec/adloader_spec.js +++ b/test/spec/adloader_spec.js @@ -1,5 +1,5 @@ import * as utils from 'src/utils'; -import * as adLoader from 'src/adloader'; +import * as adLoader from 'test/mocks/adloaderStub'; describe('adLoader', function () { let utilsinsertElementStub; diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index e4b2458c18b..cd0c8586d04 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -9,7 +9,6 @@ import * as store from 'src/videoCache'; import * as ajaxLib from 'src/ajax'; import find from 'core-js/library/fn/array/find'; -const adloader = require('../../src/adloader'); var assert = require('assert'); /* use this method to test individual files instead of the whole prebid.js project */ @@ -551,7 +550,6 @@ describe('auctionmanager.js', function () { }); describe('when auction timeout is 3000', function () { - let loadScriptStub; before(function () { makeRequestsStub.returns(TEST_BID_REQS); }); @@ -567,17 +565,12 @@ describe('auctionmanager.js', function () { createAuctionStub = sinon.stub(auctionModule, 'newAuction'); createAuctionStub.returns(auction); - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - spec = mockBidder(BIDDER_CODE, bids); registerBidder(spec); }); afterEach(function () { auctionModule.newAuction.restore(); - loadScriptStub.restore(); }); function checkPbDg(cpm, expected, msg) { @@ -673,7 +666,6 @@ describe('auctionmanager.js', function () { }); describe('when auction timeout is 20', function () { - let loadScriptStub; let eventsEmitSpy; let getBidderRequestStub; @@ -697,10 +689,6 @@ describe('auctionmanager.js', function () { createAuctionStub = sinon.stub(auctionModule, 'newAuction'); createAuctionStub.returns(auction); - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - spec = mockBidder(BIDDER_CODE, [bids[0]]); registerBidder(spec); @@ -722,7 +710,6 @@ describe('auctionmanager.js', function () { }); afterEach(function () { auctionModule.newAuction.restore(); - loadScriptStub.restore(); events.emit.restore(); getBidderRequestStub.restore(); }); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 37126475af8..9be87ac8628 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -4,21 +4,9 @@ import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; -const adloader = require('src/adloader'); describe('AppNexusAdapter', function () { const adapter = newBidder(spec); - let loadScriptStub; - - before(function() { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); - - after(function() { - loadScriptStub.restore(); - }); describe('inherited functions', function () { it('exists and is a function', function () { diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index edaff2c88ce..21e175a5b82 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,21 +1,9 @@ import { expect } from 'chai'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import * as utils from 'src/utils'; -const adloader = require('src/adloader'); describe('BeachfrontAdapter', function () { let bidRequests; - let loadScriptStub; - - before(function() { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); - - after(function() { - loadScriptStub.restore(); - }); beforeEach(function () { bidRequests = [ diff --git a/test/spec/modules/rockyouBidAdapter_spec.js b/test/spec/modules/rockyouBidAdapter_spec.js index 81404189802..65d87566c26 100644 --- a/test/spec/modules/rockyouBidAdapter_spec.js +++ b/test/spec/modules/rockyouBidAdapter_spec.js @@ -1,21 +1,9 @@ import { expect } from 'chai'; import { spec, internals } from 'modules/rockyouBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -const adloader = require('src/adloader'); describe('RockYouAdapter', function () { const adapter = newBidder(spec); - let loadScriptStub; - - before(function() { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); - - after(function() { - loadScriptStub.restore(); - }); describe('bid validator', function () { it('rejects a bid that is missing the placementId', function () { diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 0a23965b22b..8996c1b4957 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -3,21 +3,8 @@ import {expect} from 'chai'; import {spec as adapter} from 'modules/vubleBidAdapter'; import * as utils from 'src/utils'; -const adloader = require('../../../src/adloader'); describe('VubleAdapter', function () { - let loadScriptStub; - - before(function() { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); - - after(function() { - loadScriptStub.restore(); - }); - describe('Check methods existance', function () { it('exists and is a function', function () { expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function'); diff --git a/test/spec/modules/xhbBidAdapter_spec.js b/test/spec/modules/xhbBidAdapter_spec.js index 9ef90492acc..e48d3011ed2 100644 --- a/test/spec/modules/xhbBidAdapter_spec.js +++ b/test/spec/modules/xhbBidAdapter_spec.js @@ -4,21 +4,9 @@ import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; -const adloader = require('../../../src/adloader'); describe('xhbAdapter', function () { const adapter = newBidder(spec); - let loadScriptStub; - - before(function() { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); - - after(function() { - loadScriptStub.restore(); - }); describe('inherited functions', function () { it('exists and is a function', function () { diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js index 1bae0997749..93e65602984 100644 --- a/test/spec/modules/zedoBidAdapter_spec.js +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -1,20 +1,7 @@ import { expect } from 'chai'; import { spec } from 'modules/zedoBidAdapter'; -const adloader = require('src/adloader'); describe('The ZEDO bidding adapter', function () { - let loadScriptStub; - - before(function() { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); - - after(function() { - loadScriptStub.restore(); - }); - describe('isBidRequestValid', function () { it('should return false when given an invalid bid', function () { const bid = { diff --git a/test/spec/renderer_spec.js b/test/spec/renderer_spec.js index 7f95af1a257..d4e90245ea5 100644 --- a/test/spec/renderer_spec.js +++ b/test/spec/renderer_spec.js @@ -1,6 +1,5 @@ import { expect } from 'chai'; import { Renderer } from 'src/Renderer'; -const adloader = require('../../src/adloader'); describe('Renderer: A renderer installed on a bid response', function () { let testRenderer1; @@ -8,13 +7,7 @@ describe('Renderer: A renderer installed on a bid response', function () { let spyRenderFn; let spyEventHandler; - let loadScriptStub; - beforeEach(function () { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - testRenderer1 = Renderer.install({ url: 'https://httpbin.org/post', config: { test: 'config1' }, @@ -30,10 +23,6 @@ describe('Renderer: A renderer installed on a bid response', function () { spyEventHandler = sinon.spy(); }); - afterEach(function () { - loadScriptStub.restore(); - }); - it('is an instance of Renderer', function () { expect(testRenderer1 instanceof Renderer).to.equal(true); }); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 47f4af7ad24..bde5f234ffb 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -11,7 +11,6 @@ import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; var s2sTesting = require('../../../../modules/s2sTesting'); var events = require('../../../../src/events'); -const adloader = require('../../../../src/adloader'); const CONFIG = { enabled: true, @@ -39,7 +38,6 @@ var rubiconAdapterMock = { bidder: 'rubicon', callBids: sinon.stub() }; -let loadScriptStub; describe('adapterManager tests', function () { let orgAppnexusAdapter; @@ -51,9 +49,6 @@ describe('adapterManager tests', function () { orgAdequantAdapter = AdapterManager.bidderRegistry['adequant']; orgPrebidServerAdapter = AdapterManager.bidderRegistry['prebidServer']; orgRubiconAdapter = AdapterManager.bidderRegistry['rubicon']; - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); }); after(function () { @@ -61,7 +56,6 @@ describe('adapterManager tests', function () { AdapterManager.bidderRegistry['adequant'] = orgAdequantAdapter; AdapterManager.bidderRegistry['prebidServer'] = orgPrebidServerAdapter; AdapterManager.bidderRegistry['rubicon'] = orgRubiconAdapter; - loadScriptStub.restore(); config.setConfig({s2sConfig: { enabled: false }}); }); diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index bc815a8afd2..6cc4a0b172c 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -7,7 +7,6 @@ import { userSync } from 'src/userSync' import * as utils from 'src/utils'; import { config } from 'src/config'; -const adloader = require('src/adloader'); const CODE = 'sampleBidder'; const MOCK_BIDS_REQUEST = { bids: [ @@ -35,13 +34,6 @@ describe('bidders created by newBidder', function () { let bidder; let addBidResponseStub; let doneStub; - let loadScriptStub; - - before(function() { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); beforeEach(function () { spec = { @@ -56,10 +48,6 @@ describe('bidders created by newBidder', function () { doneStub = sinon.stub(); }); - after(function() { - loadScriptStub.restore(); - }); - describe('when the ajax response is irrelevant', function () { let ajaxStub; diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 1a791f8dd51..61e26891bac 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -26,7 +26,7 @@ var prebid = require('src/prebid'); var utils = require('src/utils'); // var bidmanager = require('src/bidmanager'); var bidfactory = require('src/bidfactory'); -var adloader = require('src/adloader'); +var adloader = require('test/mocks/adloaderStub'); var adaptermanager = require('src/adaptermanager'); var events = require('src/events'); var adserver = require('src/adserver'); @@ -1633,14 +1633,12 @@ describe('Unit: Prebid Module', function () { describe('loadScript', function () { it('should call adloader.loadScript', function () { - const loadScriptSpy = sinon.spy(adloader, 'loadScript'); const tagSrc = ''; const callback = Function; const useCache = false; $$PREBID_GLOBAL$$.loadScript(tagSrc, callback, useCache); - assert.ok(loadScriptSpy.calledWith(tagSrc, callback, useCache), 'called adloader.loadScript'); - adloader.loadScript.restore(); + assert.ok(adloader.loadScriptStub.calledWith(tagSrc, callback, useCache), 'called adloader.loadScript'); }); }); diff --git a/test/test_index.js b/test/test_index.js index 51323d87437..f6a48a7542b 100644 --- a/test/test_index.js +++ b/test/test_index.js @@ -1,4 +1,5 @@ require('test/helpers/prebidGlobal.js'); +require('test/mocks/adloaderStub.js'); var testsContext = require.context('.', true, /_spec$/); testsContext.keys().forEach(testsContext); From a62e088af2aea124f866b08de4909765c3bbd318 Mon Sep 17 00:00:00 2001 From: avj83 Date: Fri, 19 Oct 2018 16:42:44 +0400 Subject: [PATCH 0772/1594] Add buyer bid adapter (#3200) * add adapter and doc * add test * fix adapter * fix adapter * fix adapter * correct code after tests * fix tests * fix adapter and test * fix buildQueryString and tests * fix cpm devisor * fix cpm devisor test * fix doc * fix tests * add adapter and doc * add test * fix adapter * fix adapter * fix adapter * correct code after tests * fix tests * fix adapter and test * fix buildQueryString and tests * fix cpm devisor * fix cpm devisor test * fix doc * fix tests * change referer source and remove userSync --- modules/buyerBidAdapter.js | 96 ++++++++++++++++ modules/buyerBidAdapter.md | 73 ++++++++++++ test/spec/modules/buyerBidAdapter_spec.js | 130 ++++++++++++++++++++++ 3 files changed, 299 insertions(+) create mode 100755 modules/buyerBidAdapter.js create mode 100755 modules/buyerBidAdapter.md create mode 100755 test/spec/modules/buyerBidAdapter_spec.js diff --git a/modules/buyerBidAdapter.js b/modules/buyerBidAdapter.js new file mode 100755 index 00000000000..61500edf38b --- /dev/null +++ b/modules/buyerBidAdapter.js @@ -0,0 +1,96 @@ +import * as utils from 'src/utils'; +import {config} from 'src/config'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'buyer'; +const ENDPOINT_URL = 'https://buyer.dspx.tv/request/'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['buyer'], + isBidRequestValid: function(bid) { + return !!(bid.params.placement); + }, + buildRequests: function(validBidRequests, bidderRequest) { + return validBidRequests.map(bidRequest => { + const params = bidRequest.params; + const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; + const width = sizes.split('x')[0]; + const height = sizes.split('x')[1]; + const placementId = params.placement; + + const rnd = Math.floor(Math.random() * 99999999999); + const referrer = encodeURIComponent(bidderRequest.refererInfo.referer); + const bidId = bidRequest.bidId; + const payload = { + _f: 'html', + alternative: 'prebid_js', + inventory_item_id: placementId, + srw: width, + srh: height, + idt: 100, + rnd: rnd, + ref: referrer, + bid_id: bidId, + }; + if (params.pfilter !== undefined) { + payload.pfilter = params.pfilter; + } + if (params.bcat !== undefined) { + payload.bcat = params.bcat; + } + if (params.dvt !== undefined) { + payload.dvt = params.dvt; + } + return { + method: 'GET', + url: ENDPOINT_URL, + data: objectToQueryString(payload), + } + }); + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + const response = serverResponse.body; + const crid = response.crid || 0; + const cpm = response.cpm / 1000000 || 0; + if (cpm !== 0 && crid !== 0) { + const dealId = response.dealid || ''; + const currency = response.currency || 'EUR'; + const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; + const referrer = utils.getTopWindowUrl(); + const bidResponse = { + requestId: response.bid_id, + cpm: cpm, + width: response.width, + height: response.height, + creativeId: crid, + dealId: dealId, + currency: currency, + netRevenue: netRevenue, + ttl: config.getConfig('_bidderTimeout'), + referrer: referrer, + ad: response.adTag + }; + bidResponses.push(bidResponse); + } + return bidResponses; + } +} + +function objectToQueryString(obj, prefix) { + let str = []; + let p; + for (p in obj) { + if (obj.hasOwnProperty(p)) { + let k = prefix ? prefix + '[' + p + ']' : p; + let v = obj[p]; + str.push((v !== null && typeof v === 'object') + ? objectToQueryString(v, k) + : encodeURIComponent(k) + '=' + encodeURIComponent(v)); + } + } + return str.join('&'); +} + +registerBidder(spec); diff --git a/modules/buyerBidAdapter.md b/modules/buyerBidAdapter.md new file mode 100755 index 00000000000..607cbf190e0 --- /dev/null +++ b/modules/buyerBidAdapter.md @@ -0,0 +1,73 @@ +# Overview + +``` +Module Name: Buyer Bidder Adapter +Module Type: Bidder Adapter +Maintainer: avj83@list.ru +``` + +# Description + +Buyer adapter for Prebid.js 1.0 + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600], + ], // a display size + } + }, + bids: [ + { + bidder: "buyer", + params: { + placement: '12345', + pfilter: { + floorprice: 1000000, // EUR * 1,000,000 + private_auction: 1, // Is private auction? 0 - no, 1 - yes + deals: [ + "666-9315-d58a7f9a-bdb9-4450-a3a2-046ba8ab2489;3;25000000;dspx-tv",// DEAL_ID;at;bidfloor;wseat1,wseat2;wadomain1,wadomain2" + "666-9315-d58a7f9a-bdb9-4450-a6a2-046ba8ab2489;3;25000000;dspx-tv",// DEAL_ID;at;bidfloor;wseat1,wseat2;wadomain1,wadomain2" + ], + geo: { // set client geo info manually (empty for auto detect) + lat: 52.52437, // Latitude from -90.0 to +90.0, where negative is south. + lon: 13.41053, // Longitude from -180.0 to +180.0, where negative is west + type: 1, // Source of location data: 1 - GPS/Location Services, 2 - IP Address, 3 - User provided (e.g. registration form) + country: 'DE', // Region of a country using FIPS 10-4 notation + region: 'DE-BE', // Region code using ISO-3166-2; 2-letter state code if USA. + regionfips104: 'GM', // Region of a country using FIPS 10-4 notation + city: 'BER', // City using United Nations Code for Trade and Transport Locations + zip: '10115' // Zip or postal code. + } + }, + bcat: "IAB2,IAB4", // List of Blocked Categories (IAB) - comma separated + dvt: "desktop|smartphone|tv|tablet" // DeVice Type (autodetect if not exists) + } + } + ] + },{ + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[320, 50]], // a mobile size + } + }, + bids: [ + { + bidder: "buyer", + params: { + placement: 67890 + } + } + ] + } + ]; +``` + +Required param field is only `placement`. \ No newline at end of file diff --git a/test/spec/modules/buyerBidAdapter_spec.js b/test/spec/modules/buyerBidAdapter_spec.js new file mode 100755 index 00000000000..602a1104fdb --- /dev/null +++ b/test/spec/modules/buyerBidAdapter_spec.js @@ -0,0 +1,130 @@ +import { expect } from 'chai'; +import { spec } from 'modules/buyerBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT_URL = 'https://buyer.dspx.tv/request/'; + +describe('buyerAdapter', function () { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'buyer', + 'params': { + 'placement': '6682', + 'pfilter': { + 'floorprice': 1000000 + }, + 'bcat': 'IAB2,IAB4', + 'dvt': 'desktop' + }, + 'sizes': [ + [300, 250] + ], + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'someIncorrectParam': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [{ + 'bidder': 'buyer', + 'params': { + 'placement': '6682', + 'pfilter': { + 'floorprice': 1000000, + 'private_auction': 0, + 'geo': { + 'country': 'DE' + } + }, + 'bcat': 'IAB2,IAB4', + 'dvt': 'desktop' + }, + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + let bidderRequest = { + refererInfo: { + referer: 'some_referrer.net' + } + } + + const request = spec.buildRequests(bidRequests, bidderRequest); + it('sends bid request to our endpoint via GET', function () { + expect(request[0].method).to.equal('GET'); + let data = request[0].data.replace(/rnd=\d+\&/g, '').replace(/ref=.*\&bid/g, 'bid'); + expect(data).to.equal('_f=html&alternative=prebid_js&inventory_item_id=6682&srw=300&srh=250&idt=100&bid_id=30b31c1838de1e&pfilter%5Bfloorprice%5D=1000000&pfilter%5Bprivate_auction%5D=0&pfilter%5Bgeo%5D%5Bcountry%5D=DE&bcat=IAB2%2CIAB4&dvt=desktop'); + }); + }); + + describe('interpretResponse', function () { + let serverResponse = { + 'body': { + 'cpm': 5000000, + 'crid': 100500, + 'width': '300', + 'height': '250', + 'tag': '', + 'requestId': '220ed41385952a', + 'currency': 'EUR', + 'ttl': 60, + 'netRevenue': true, + 'zone': '6682' + } + }; + + let expectedResponse = [{ + requestId: '23beaa6af6cdde', + cpm: 0.5, + width: 0, + height: 0, + creativeId: 100500, + dealId: '', + currency: 'EUR', + netRevenue: true, + ttl: 300, + referrer: '', + ad: '' + }]; + + it('should get the correct bid response by display ad', function () { + let bidRequest = [{ + 'method': 'GET', + 'url': ENDPOINT_URL, + 'data': { + 'bid_id': '30b31c1838de1e' + } + }]; + let result = spec.interpretResponse(serverResponse, bidRequest[0]); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles empty bid response', function () { + let response = { + body: {} + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From 6879fead422ec77da5fc7443bd4e7a209f6fc343 Mon Sep 17 00:00:00 2001 From: Mikhail Ivanchenko Date: Fri, 19 Oct 2018 16:07:58 +0300 Subject: [PATCH 0773/1594] Adlive bid adapter (#3109) * send request to endpoint * tests * improve tests * Add description. Small fix * add maintainer email * restore origin package.json * add getUserSyncs function * remove userSyncs * change endpoint_url params * change test params * change netRevenue to false --- modules/adliveBidAdapter.js | 68 +++++++++++++++++++ modules/adliveBidAdapter.md | 28 ++++++++ test/spec/modules/adliveBidAdapter_spec.js | 78 ++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 modules/adliveBidAdapter.js create mode 100644 modules/adliveBidAdapter.md create mode 100644 test/spec/modules/adliveBidAdapter_spec.js diff --git a/modules/adliveBidAdapter.js b/modules/adliveBidAdapter.js new file mode 100644 index 00000000000..54a11270133 --- /dev/null +++ b/modules/adliveBidAdapter.js @@ -0,0 +1,68 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'adlive'; +const ENDPOINT_URL = 'https://api.publishers.adlive.io/get?pbjs=1'; +const CURRENCY = 'USD'; +const TIME_TO_LIVE = 360; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: function(bid) { + return !!(bid.params.hashes && utils.isArray(bid.params.hashes)); + }, + + buildRequests: function(validBidRequests) { + let requests = []; + + utils._each(validBidRequests, function(bid) { + requests.push({ + method: 'POST', + url: ENDPOINT_URL, + options: { + contentType: 'application/json', + withCredentials: true + }, + data: JSON.stringify({ + transaction_id: bid.bidId, + hashes: utils.getBidIdParameter('hashes', bid.params) + }), + bidId: bid.bidId + }); + }); + + return requests; + }, + + interpretResponse: function(serverResponse, bidRequest) { + try { + const response = serverResponse.body; + const bidResponses = []; + + utils._each(response, function(bidResponse) { + if (!bidResponse.is_passback) { + bidResponses.push({ + requestId: bidRequest.bidId, + cpm: bidResponse.price, + width: bidResponse.size[0], + height: bidResponse.size[1], + creativeId: bidResponse.hash, + currency: CURRENCY, + netRevenue: false, + ttl: TIME_TO_LIVE, + ad: bidResponse.content + }); + } + }); + + return bidResponses; + } catch (err) { + utils.logError(err); + return []; + } + } +}; +registerBidder(spec); diff --git a/modules/adliveBidAdapter.md b/modules/adliveBidAdapter.md new file mode 100644 index 00000000000..4fc6a112e82 --- /dev/null +++ b/modules/adliveBidAdapter.md @@ -0,0 +1,28 @@ +# Overview +``` +Module Name: Adlive Bid Adapter +Module Type: Bidder Adapter +Maintainer: traffic@adlive.io +``` + +# Description +Module that connects to Adlive's server for bids. +Currently module supports only banner mediaType. + +# Test Parameters +``` + var adUnits = [{ + code: '/test/div', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'adlive', + params: { + hashes: ['1e100887dd614b0909bf6c49ba7f69fdd1360437'] + } + }] + }]; +``` \ No newline at end of file diff --git a/test/spec/modules/adliveBidAdapter_spec.js b/test/spec/modules/adliveBidAdapter_spec.js new file mode 100644 index 00000000000..a048ce6932b --- /dev/null +++ b/test/spec/modules/adliveBidAdapter_spec.js @@ -0,0 +1,78 @@ +import { expect } from 'chai'; +import { spec } from 'modules/adliveBidAdapter'; + +describe('adliveBidAdapterTests', function() { + let bidRequestData = { + bids: [ + { + bidId: 'transaction_1234', + bidder: 'adlive', + params: { + hashes: ['1e100887dd614b0909bf6c49ba7f69fdd1360437'] + }, + sizes: [[300, 250]] + } + ] + }; + let request = []; + + it('validate_pub_params', function() { + expect( + spec.isBidRequestValid({ + bidder: 'adlive', + params: { + hashes: ['1e100887dd614b0909bf6c49ba7f69fdd1360437'] + } + }) + ).to.equal(true); + }); + + it('validate_generated_params', function() { + request = spec.buildRequests(bidRequestData.bids); + let req_data = JSON.parse(request[0].data); + + expect(req_data.transaction_id).to.equal('transaction_1234'); + }); + + it('validate_response_params', function() { + let serverResponse = { + body: [ + { + hash: '1e100887dd614b0909bf6c49ba7f69fdd1360437', + content: 'Ad html', + price: 1.12, + size: [300, 250], + is_passback: 0 + } + ] + }; + + let bids = spec.interpretResponse(serverResponse, bidRequestData.bids[0]); + expect(bids).to.have.lengthOf(1); + + let bid = bids[0]; + + expect(bid.creativeId).to.equal('1e100887dd614b0909bf6c49ba7f69fdd1360437'); + expect(bid.ad).to.equal('Ad html'); + expect(bid.cpm).to.equal(1.12); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.currency).to.equal('USD'); + }); + + it('validate_response_params_with passback', function() { + let serverResponse = { + body: [ + { + hash: '1e100887dd614b0909bf6c49ba7f69fdd1360437', + content: 'Ad html passback', + size: [300, 250], + is_passback: 1 + } + ] + }; + let bids = spec.interpretResponse(serverResponse); + + expect(bids).to.have.lengthOf(0); + }); +}); From b8eb55c6e86324403472ad69c01cdec7f2f3b726 Mon Sep 17 00:00:00 2001 From: Kamoris Date: Fri, 19 Oct 2018 19:28:30 +0200 Subject: [PATCH 0774/1594] Add native support to RTBHouseAdapter (#3189) * Refactor rtbhouseBidAdapter and spec * Add native support to RTB House adapter --- modules/rtbhouseBidAdapter.js | 351 ++++++++++++++----- modules/rtbhouseBidAdapter.md | 27 ++ test/spec/modules/rtbhouseBidAdapter_spec.js | 334 +++++++++++++++--- 3 files changed, 592 insertions(+), 120 deletions(-) diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js index bb527528e43..e4a30782dbe 100644 --- a/modules/rtbhouseBidAdapter.js +++ b/modules/rtbhouseBidAdapter.js @@ -1,5 +1,5 @@ import * as utils from 'src/utils'; -import { BANNER } from 'src/mediaTypes'; +import { BANNER, NATIVE } from 'src/mediaTypes'; import { registerBidder } from 'src/adapters/bidderFactory'; import includes from 'core-js/library/fn/array/includes'; @@ -7,68 +7,34 @@ const BIDDER_CODE = 'rtbhouse'; const REGIONS = ['prebid-eu', 'prebid-us', 'prebid-asia']; 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 TTL = 55; -/** - * Helpers - */ - -function buildEndpointUrl(region) { - return 'https://' + region + '.' + ENDPOINT_URL; -} - -/** - * Produces an OpenRTBImpression from a slot config. - */ -function mapImpression(slot) { - return { - id: slot.bidId, - banner: mapBanner(slot), - tagid: slot.adUnitCode.toString(), - }; -} - -/** - * Produces an OpenRTB Banner object for the slot given. - */ -function mapBanner(slot) { - return { - w: slot.sizes[0][0], - h: slot.sizes[0][1], - format: mapSizes(slot.sizes) - }; -} - -/** - * Produce openRTB banner.format object - */ -function mapSizes(slotSizes) { - const format = []; - slotSizes.forEach(elem => { - format.push({ - w: elem[0], - h: elem[1] - }); - }); - return format; -} - -/** - * Produces an OpenRTB site object. - */ -function mapSite(validRequest) { - const pubId = validRequest && validRequest.length > 0 ? validRequest[0].params.publisherId : 'unknown'; - return { - publisher: { - id: pubId.toString(), +// Codes defined by OpenRTB Native Ads 1.1 specification +export const OPENRTB = { + NATIVE: { + IMAGE_TYPE: { + ICON: 1, + MAIN: 3, + }, + ASSET_ID: { + TITLE: 1, + IMAGE: 2, + ICON: 3, + BODY: 4, + SPONSORED: 5, + CTA: 6 + }, + DATA_ASSET_TYPE: { + SPONSORED: 1, + DESC: 2, + CTA_TEXT: 12, }, - page: utils.getTopWindowUrl(), - name: utils.getOrigin() } -} +}; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [BANNER], + supportedMediaTypes: [BANNER, NATIVE], isBidRequestValid: function (bid) { return !!(includes(REGIONS, bid.params.region) && bid.params.publisherId); @@ -87,39 +53,262 @@ export const spec = { const gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; request.regs = {ext: {gdpr: gdpr}}; request.user = {ext: {consent: consentStr}}; - }; + } return { method: 'POST', - url: buildEndpointUrl(validBidRequests[0].params.region), + url: 'https://' + validBidRequests[0].params.region + '.' + ENDPOINT_URL, data: JSON.stringify(request) }; }, interpretResponse: function (serverResponse, originalRequest) { - serverResponse = serverResponse.body; - const bids = []; - - if (utils.isArray(serverResponse)) { - serverResponse.forEach(serverBid => { - if (serverBid.price !== 0) { - const bid = { - requestId: serverBid.impid, - mediaType: BANNER, - cpm: serverBid.price, - creativeId: serverBid.adid, - ad: serverBid.adm, - width: serverBid.w, - height: serverBid.h, - ttl: 55, - netRevenue: true, - currency: 'USD' - }; - bids.push(bid); - } - }); + const responseBody = serverResponse.body; + if (!utils.isArray(responseBody)) { + return []; } + + const bids = []; + responseBody.forEach(serverBid => { + if (serverBid.price === 0) { + return; + } + // try...catch would be risky cause JSON.parse throws SyntaxError + if (serverBid.adm.indexOf('{') === 0) { + bids.push(interpretNativeBid(serverBid)); + } else { + bids.push(interpretBannerBid(serverBid)); + } + }); return bids; } }; - registerBidder(spec); + +/** + * @param {object} slot Ad Unit Params by Prebid + * @returns {object} Imp by OpenRTB 2.5 §3.2.4 + */ +function mapImpression(slot) { + return { + id: slot.bidId, + banner: mapBanner(slot), + native: mapNative(slot), + tagid: slot.adUnitCode.toString() + }; +} + +/** + * @param {object} slot Ad Unit Params by Prebid + * @returns {object} Banner by OpenRTB 2.5 §3.2.6 + */ +function mapBanner(slot) { + if (slot.mediaType === 'banner' || + utils.deepAccess(slot, 'mediaTypes.banner') || + (!slot.mediaType && !slot.mediaTypes)) { + return { + w: slot.sizes[0][0], + h: slot.sizes[0][1], + format: slot.sizes.map(size => ({ + w: size[0], + h: size[1] + })) + }; + } +} + +/** + * @param {object} slot Ad Unit Params by Prebid + * @returns {object} Site by OpenRTB 2.5 §3.2.13 + */ +function mapSite(slot) { + const pubId = slot && slot.length > 0 + ? slot[0].params.publisherId + : 'unknown'; + return { + publisher: { + id: pubId.toString(), + }, + page: utils.getTopWindowUrl(), + name: utils.getOrigin() + } +} + +/** + * @param {object} slot Ad Unit Params by Prebid + * @returns {object} Request by OpenRTB Native Ads 1.1 §4 + */ +function mapNative(slot) { + if (slot.mediaType === 'native' || utils.deepAccess(slot, 'mediaTypes.native')) { + return { + request: { + assets: mapNativeAssets(slot) + }, + ver: '1.1' + } + } +} + +/** + * @param {object} slot Slot config by Prebid + * @returns {array} Request Assets by OpenRTB Native Ads 1.1 §4.2 + */ +function mapNativeAssets(slot) { + const params = slot.nativeParams || utils.deepAccess(slot, 'mediaTypes.native'); + const assets = []; + if (params.title) { + assets.push({ + id: OPENRTB.NATIVE.ASSET_ID.TITLE, + required: params.title.required ? 1 : 0, + title: { + len: params.title.len || 25 + } + }) + } + if (params.image) { + assets.push({ + id: OPENRTB.NATIVE.ASSET_ID.IMAGE, + required: params.image.required ? 1 : 0, + img: mapNativeImage(params.image, OPENRTB.NATIVE.IMAGE_TYPE.MAIN) + }) + } + if (params.icon) { + assets.push({ + id: OPENRTB.NATIVE.ASSET_ID.ICON, + required: params.icon.required ? 1 : 0, + img: mapNativeImage(params.icon, OPENRTB.NATIVE.IMAGE_TYPE.ICON) + }) + } + if (params.sponsoredBy) { + assets.push({ + id: OPENRTB.NATIVE.ASSET_ID.SPONSORED, + required: params.sponsoredBy.required ? 1 : 0, + data: { + type: OPENRTB.NATIVE.DATA_ASSET_TYPE.SPONSORED, + len: params.sponsoredBy.len + } + }) + } + if (params.body) { + assets.push({ + id: OPENRTB.NATIVE.ASSET_ID.BODY, + required: params.body.request ? 1 : 0, + data: { + type: OPENRTB.NATIVE.DATA_ASSET_TYPE.DESC, + len: params.body.len + } + }) + } + if (params.cta) { + assets.push({ + id: OPENRTB.NATIVE.ASSET_ID.CTA, + required: params.cta.required ? 1 : 0, + data: { + type: OPENRTB.NATIVE.DATA_ASSET_TYPE.CTA_TEXT, + len: params.cta.len + } + }) + } + return assets; +} + +/** + * @param {object} image Prebid native.image/icon + * @param {int} type Image or icon code + * @returns {object} Request Image by OpenRTB Native Ads 1.1 §4.4 + */ +function mapNativeImage(image, type) { + const img = {type: type}; + if (image.aspect_ratios) { + const ratio = image.aspect_ratios[0]; + const minWidth = ratio.min_width || 100; + img.wmin = minWidth; + img.hmin = (minWidth / ratio.ratio_width * ratio.ratio_height); + } + if (image.sizes) { + const size = Array.isArray(image.sizes[0]) ? image.sizes[0] : image.sizes; + img.w = size[0]; + img.h = size[1]; + } + return img +} + +/** + * @param {object} serverBid Bid by OpenRTB 2.5 §4.2.3 + * @returns {object} Prebid banner bidObject + */ +function interpretBannerBid(serverBid) { + return { + requestId: serverBid.impid, + mediaType: BANNER, + cpm: serverBid.price, + creativeId: serverBid.adid, + ad: serverBid.adm, + width: serverBid.w, + height: serverBid.h, + ttl: TTL, + netRevenue: true, + currency: 'USD' + } +} + +/** + * @param {object} serverBid Bid by OpenRTB 2.5 §4.2.3 + * @returns {object} Prebid native bidObject + */ +function interpretNativeBid(serverBid) { + return { + requestId: serverBid.impid, + mediaType: NATIVE, + cpm: serverBid.price, + creativeId: serverBid.adid, + width: 1, + height: 1, + ttl: TTL, + netRevenue: true, + currency: 'USD', + native: interpretNativeAd(serverBid.adm), + } +} + +/** + * @param {string} adm JSON-encoded Request by OpenRTB Native Ads 1.1 §4.1 + * @returns {object} Prebid bidObject.native + */ +function interpretNativeAd(adm) { + const native = JSON.parse(adm).native; + const result = { + clickUrl: encodeURIComponent(native.link.url), + impressionTrackers: native.imptrackers + }; + native.assets.forEach(asset => { + switch (asset.id) { + case OPENRTB.NATIVE.ASSET_ID.TITLE: + result.title = asset.title.text; + break; + case OPENRTB.NATIVE.ASSET_ID.IMAGE: + result.image = { + url: encodeURIComponent(asset.img.url), + width: asset.img.w, + height: asset.img.h + }; + break; + case OPENRTB.NATIVE.ASSET_ID.ICON: + result.icon = { + url: encodeURIComponent(asset.img.url), + width: asset.img.w, + height: asset.img.h + }; + break; + case OPENRTB.NATIVE.ASSET_ID.BODY: + result.body = asset.data.value; + break; + case OPENRTB.NATIVE.ASSET_ID.SPONSORED: + result.sponsoredBy = asset.data.value; + break; + case OPENRTB.NATIVE.ASSET_ID.CTA: + result.cta = asset.data.value; + break; + } + }); + return result; +} diff --git a/modules/rtbhouseBidAdapter.md b/modules/rtbhouseBidAdapter.md index 47deed1a277..a2d7e2aedda 100644 --- a/modules/rtbhouseBidAdapter.md +++ b/modules/rtbhouseBidAdapter.md @@ -14,6 +14,7 @@ Please reach out to pmp@rtbhouse.com to receive your own # Test Parameters ``` var adUnits = [ + // banner { code: 'test-div', sizes: [[300, 250]], @@ -26,6 +27,32 @@ Please reach out to pmp@rtbhouse.com to receive your own } } ] + }, + // native + { + code: 'test-div', + mediaTypes: { + native: { + title: { + required: true + }, + image: { + required: true + }, + body: { + required: true + } + } + }, + bids: [ + { + bidder: "rtbhouse", + params: { + region: 'prebid-eu', + publisherId: 'PREBID_TEST_ID' + } + } + ] } ]; ``` diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index b1d20ebc203..3c1d81a86c9 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -1,23 +1,8 @@ import { expect } from 'chai'; -import { spec } from 'modules/rtbhouseBidAdapter'; +import { OPENRTB, spec } from 'modules/rtbhouseBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -const REGIONS = ['prebid-eu', 'prebid-us', 'prebid-asia']; -const ENDPOINT_URL = 'creativecdn.com/bidder/prebid/bids'; -const consentStr = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; -/** - * Helpers - */ - -function buildEndpointUrl(region) { - return 'https://' + region + '.' + ENDPOINT_URL; -} - -/** - * endof Helpers - */ - -describe('RTBHouseAdapter', function () { +describe('RTBHouseAdapter', () => { const adapter = newBidder(spec); describe('inherited functions', function () { @@ -57,12 +42,12 @@ describe('RTBHouseAdapter', function () { describe('buildRequests', function () { let bidRequests = [ { - 'bidder': 'rtbhouse', - 'params': { - 'publisherId': 'PREBID_TEST', - 'region': 'prebid-eu', - 'test': 1 - }, + 'bidder': 'rtbhouse', + 'params': { + 'publisherId': 'PREBID_TEST', + 'region': 'prebid-eu', + 'test': 1 + }, 'adUnitCode': 'adunit-code', 'sizes': [[300, 250], [300, 600]], 'bidId': '30b31c1838de1e', @@ -71,16 +56,32 @@ describe('RTBHouseAdapter', function () { } ]; - it('should build test param into the request', function () { - let builtTestRequest = spec.buildRequests(bidRequests).data; - expect(JSON.parse(builtTestRequest).test).to.equal(1); + it('should build test param into the request', () => { + let builtTestRequest = spec.buildRequests(bidRequests).data; + expect(JSON.parse(builtTestRequest).test).to.equal(1); + }); + + it('should build valid OpenRTB banner object', () => { + const request = JSON.parse(spec.buildRequests((bidRequests)).data); + const imp = request.imp[0]; + expect(imp.banner).to.deep.equal({ + w: 300, + h: 250, + format: [{ + w: 300, + h: 250 + }, { + w: 300, + h: 600 + }] + }) }); it('sends bid request to ENDPOINT via POST', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest); - expect(request.url).to.equal(buildEndpointUrl(bidRequest[0].params.region)); + expect(request.url).to.equal('https://prebid-eu.creativecdn.com/bidder/prebid/bids'); expect(request.method).to.equal('POST'); }); @@ -96,7 +97,12 @@ describe('RTBHouseAdapter', function () { it('should populate GDPR and consent string if available for EEA users', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; - const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true, consentString: consentStr}}); + const request = spec.buildRequests(bidRequest, { + gdprConsent: { + gdprApplies: true, + consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==' + } + }); let data = JSON.parse(request.data); expect(data.regs.ext.gdpr).to.equal(1); expect(data.user.ext.consent).to.equal('BOJ8RZsOJ8RZsABAB8AAAAAZ-A'); @@ -110,19 +116,208 @@ describe('RTBHouseAdapter', function () { expect(data.regs.ext.gdpr).to.equal(1); expect(data.user.ext.consent).to.equal(''); }); + + it('should include banner imp in request', () => { + const bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest); + const data = JSON.parse(request.data); + expect(data.imp[0].banner).to.not.be.empty; + }); + + describe('native imp', () => { + function basicRequest(extension) { + return Object.assign({ + bidder: 'bidder', + adUnitCode: 'adunit-code', + bidId: '1', + params: { + publisherId: 'PREBID_TEST', + region: 'prebid-eu', + test: 1 + } + }, extension); + } + + function buildImp(request) { + return JSON.parse(spec.buildRequests([request]).data).imp[0]; + } + + it('should extract native params when single mediaType', () => { + const imp = buildImp(basicRequest({ + mediaType: 'native', + nativeParams: { + title: { + required: true, + len: 100 + } + } + })); + expect(imp.native.request.assets[0]).to.deep.equal({ + id: OPENRTB.NATIVE.ASSET_ID.TITLE, + required: 1, + title: { + len: 100 + } + }) + }); + + it('should extract native params when many mediaTypes', () => { + const imp = buildImp(basicRequest({ + mediaTypes: { + native: { + title: { + len: 100 + } + } + } + })); + expect(imp.native.request.assets[0]).to.deep.equal({ + id: OPENRTB.NATIVE.ASSET_ID.TITLE, + required: 0, + title: { + len: 100 + } + }) + }); + + it('should not contain banner in imp', () => { + const imp = buildImp(basicRequest({ + mediaTypes: { + native: { + title: { + required: true + } + } + } + })); + expect(imp.banner).to.be.empty; + }); + + describe('image sizes', () => { + it('should parse single image size', () => { + const imp = buildImp(basicRequest({ + mediaTypes: { + native: { + image: { + sizes: [300, 250] + } + } + } + })); + expect(imp.native.request.assets[0]).to.deep.equal({ + id: OPENRTB.NATIVE.ASSET_ID.IMAGE, + required: 0, + img: { + w: 300, + h: 250, + type: OPENRTB.NATIVE.IMAGE_TYPE.MAIN, + } + }) + }); + + it('should parse multiple image sizes', () => { + const imp = buildImp(basicRequest({ + mediaTypes: { + native: { + image: { + sizes: [[300, 250], [100, 100]] + } + } + } + })); + expect(imp.native.request.assets[0]).to.deep.equal({ + id: OPENRTB.NATIVE.ASSET_ID.IMAGE, + required: 0, + img: { + w: 300, + h: 250, + type: OPENRTB.NATIVE.IMAGE_TYPE.MAIN, + } + }) + }) + }); + + it('should parse aspect ratios with min_width', () => { + const imp = buildImp(basicRequest({ + mediaTypes: { + native: { + icon: { + aspect_ratios: [{ + min_width: 300, + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + })); + expect(imp.native.request.assets[0]).to.deep.equal({ + id: OPENRTB.NATIVE.ASSET_ID.ICON, + required: 0, + img: { + type: OPENRTB.NATIVE.IMAGE_TYPE.ICON, + wmin: 300, + hmin: 450, + } + }) + }); + + it('should parse aspect ratios without min_width', () => { + const imp = buildImp(basicRequest({ + mediaTypes: { + native: { + icon: { + aspect_ratios: [{ + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + })); + expect(imp.native.request.assets[0]).to.deep.equal({ + id: OPENRTB.NATIVE.ASSET_ID.ICON, + required: 0, + img: { + type: OPENRTB.NATIVE.IMAGE_TYPE.ICON, + wmin: 100, + hmin: 150, + } + }) + }); + + it('should handle all native assets', () => { + const imp = buildImp(basicRequest({ + mediaTypes: { + native: { + title: {}, + image: {}, + icon: {}, + sponsoredBy: {}, + body: {}, + cta: {}, + } + } + })); + expect(imp.native.request.assets.length).to.equal(6); + imp.native.request.assets.forEach(asset => { + expect(asset.id).to.be.at.least(1) + }) + }); + }); }); describe('interpretResponse', function () { let response = [{ - 'id': 'bidder_imp_identifier', - 'impid': '552b8922e28f27', - 'price': 0.5, - 'adid': 'Ad_Identifier', - 'adm': '', - 'adomain': ['rtbhouse.com'], - 'cid': 'Ad_Identifier', - 'w': 300, - 'h': 250 + 'id': 'bidder_imp_identifier', + 'impid': '552b8922e28f27', + 'price': 0.5, + 'adid': 'Ad_Identifier', + 'adm': '', + 'adomain': ['rtbhouse.com'], + 'cid': 'Ad_Identifier', + 'w': 300, + 'h': 250 }]; it('should get correct bid response', function () { @@ -141,15 +336,76 @@ describe('RTBHouseAdapter', function () { } ]; let bidderRequest; - let result = spec.interpretResponse({ body: response }, {bidderRequest}); + 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 response = ''; let bidderRequest; - let result = spec.interpretResponse({ body: response }, {bidderRequest}); + let result = spec.interpretResponse({body: response}, {bidderRequest}); expect(result.length).to.equal(0); }); + + describe('native', () => { + const adm = { + native: { + ver: 1.1, + link: { + url: 'http://example.com' + }, + imptrackers: [ + 'http://example.com/imptracker' + ], + assets: [{ + id: OPENRTB.NATIVE.ASSET_ID.TITLE, + required: 1, + title: { + text: 'Title text' + } + }, { + id: OPENRTB.NATIVE.ASSET_ID.IMAGE, + required: 1, + img: { + url: 'http://example.com/image.jpg', + w: 150, + h: 50 + } + }, { + id: OPENRTB.NATIVE.ASSET_ID.BODY, + required: 0, + data: { + value: 'Body text' + } + }], + } + }; + const response = [{ + 'id': 'id', + 'impid': 'impid', + 'price': 1, + 'adid': 'adid', + 'adm': JSON.stringify(adm), + 'adomain': ['rtbhouse.com'], + 'cid': 'cid', + 'w': 1, + 'h': 1 + }]; + + it('should contain native assets in valid format', () => { + const bids = spec.interpretResponse({body: response}, {}); + expect(bids[0].native).to.deep.equal({ + title: 'Title text', + clickUrl: encodeURIComponent('http://example.com'), + impressionTrackers: ['http://example.com/imptracker'], + image: { + url: encodeURIComponent('http://example.com/image.jpg'), + width: 150, + height: 50 + }, + body: 'Body text' + }); + }); + }); }); }); From 86357a8614e1c5bf8c6fceae0f45586cb5c6e4e7 Mon Sep 17 00:00:00 2001 From: Denis Logachev Date: Fri, 19 Oct 2018 21:14:38 +0300 Subject: [PATCH 0775/1594] Ref and meta keyword collection feature (#3184) --- modules/adkernelBidAdapter.js | 40 +++++++++++++------- test/spec/modules/adkernelBidAdapter_spec.js | 20 +++++----- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index dffcaacec3d..9bdab13de7b 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -3,6 +3,7 @@ import { BANNER, VIDEO } from 'src/mediaTypes'; import {registerBidder} from 'src/adapters/bidderFactory'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; +import {parse as parseUrl} from 'src/url' const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', @@ -22,13 +23,13 @@ export const spec = { 'zoneId' in bidRequest.params && !isNaN(Number(bidRequest.params.zoneId)); }, buildRequests: function(bidRequests, bidderRequest) { - let impDispatch = dispatchImps(bidRequests); + let impDispatch = dispatchImps(bidRequests, bidderRequest.refererInfo); const gdprConsent = bidderRequest.gdprConsent; const auctionId = bidderRequest.auctionId; const requests = []; Object.keys(impDispatch).forEach(host => { Object.keys(impDispatch[host]).forEach(zoneId => { - const request = buildRtbRequest(impDispatch[host][zoneId], auctionId, gdprConsent); + const request = buildRtbRequest(impDispatch[host][zoneId], auctionId, gdprConsent, bidderRequest.refererInfo); requests.push({ method: 'GET', url: `${window.location.protocol}//${host}/rtbg`, @@ -96,8 +97,9 @@ registerBidder(spec); /** * Dispatch impressions by ad network host and zone */ -function dispatchImps(bidRequests) { - return bidRequests.map(buildImp) +function dispatchImps(bidRequests, refererInfo) { + let secure = (refererInfo && refererInfo.referer.indexOf('https:') === 0); + return bidRequests.map(bidRequest => buildImp(bidRequest, secure)) .reduce((acc, curr, index) => { let bidRequest = bidRequests[index]; let zoneId = bidRequest.params.zoneId; @@ -112,7 +114,7 @@ function dispatchImps(bidRequests) { /** * Builds parameters object for single impression */ -function buildImp(bidRequest) { +function buildImp(bidRequest, secure) { const imp = { 'id': bidRequest.bidId, 'tagid': bidRequest.adUnitCode @@ -137,7 +139,7 @@ function buildImp(bidRequest) { .forEach(param => imp.video[param] = bidRequest.params.video[param]); } } - if (utils.getTopWindowLocation().protocol === 'https:') { + if (secure) { imp.secure = 1; } return imp; @@ -149,7 +151,7 @@ function buildImp(bidRequest) { * @return Array[Array[Number]] */ function canonicalizeSizesArray(sizes) { - if (sizes.length == 2 && !utils.isArray(sizes[0])) { + if (sizes.length === 2 && !utils.isArray(sizes[0])) { return [sizes]; } return sizes; @@ -160,12 +162,14 @@ function canonicalizeSizesArray(sizes) { * @param imps collection of impressions * @param auctionId * @param gdprConsent + * @param refInfo + * @return Object complete rtb request */ -function buildRtbRequest(imps, auctionId, gdprConsent) { +function buildRtbRequest(imps, auctionId, gdprConsent, refInfo) { let req = { 'id': auctionId, 'imp': imps, - 'site': createSite(), + 'site': createSite(refInfo), 'at': 1, 'device': { 'ip': 'caller', @@ -197,12 +201,20 @@ function getLanguage() { /** * Creates site description object */ -function createSite() { - var location = utils.getTopWindowLocation(); - return { - 'domain': location.hostname, - 'page': location.href.split('?')[0] +function createSite(refInfo) { + let url = parseUrl(refInfo.referer); + let result = { + 'domain': url.hostname, + 'page': url.protocol + '://' + url.hostname + url.pathname }; + if (self === top && document.referrer) { + result.ref = document.referrer; + } + let keywords = document.getElementsByTagName('meta')['keywords']; + if (keywords && keywords.content) { + result.keywords = keywords.content; + } + return result; } /** diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index 590e0ebb96e..3243b980b9f 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -1,7 +1,6 @@ import {expect} from 'chai'; import {spec} from 'modules/adkernelBidAdapter'; import * as utils from 'src/utils'; -import {parse as parseUrl} from 'src/url'; describe('Adkernel adapter', function () { const bid1_zone1 = { @@ -113,15 +112,13 @@ describe('Adkernel adapter', function () { } }; - function buildRequest(bidRequests, bidderRequest = {}, url = 'https://example.com/index.html', dnt = true) { - let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => { - let loc = parseUrl(url); - loc.protocol += ':'; - return loc; - }); + function buildBidderRequest(url = 'https://example.com/index.html', params = {}) { + return Object.assign({}, params, {refererInfo: {referer: url, reachedTop: true}}) + } + const DEFAULT_BIDDER_REQUEST = buildBidderRequest(); + function buildRequest(bidRequests, bidderRequest = DEFAULT_BIDDER_REQUEST, dnt = true) { let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => dnt); let pbRequests = spec.buildRequests(bidRequests, bidderRequest); - wmock.restore(); dntmock.restore(); let rtbRequests = pbRequests.map(r => JSON.parse(r.data.r)); return [pbRequests, rtbRequests]; @@ -195,7 +192,8 @@ describe('Adkernel adapter', function () { it('should contain gdpr-related information if consent is configured', function () { let [_, bidRequests] = buildRequest([bid1_zone1], - {gdprConsent: {gdprApplies: true, consentString: 'test-consent-string', vendorData: {}}}); + buildBidderRequest('http://example.com/index.html', + {gdprConsent: {gdprApplies: true, consentString: 'test-consent-string', vendorData: {}}})); let bidRequest = bidRequests[0]; expect(bidRequest).to.have.property('regs'); expect(bidRequest.regs.ext).to.be.eql({'gdpr': 1}); @@ -204,7 +202,7 @@ describe('Adkernel adapter', function () { }); it('should\'t contain consent string if gdpr isn\'t applied', function () { - let [_, bidRequests] = buildRequest([bid1_zone1], {gdprConsent: {gdprApplies: false}}); + let [_, bidRequests] = buildRequest([bid1_zone1], buildBidderRequest('https://example.com/index.html', {gdprConsent: {gdprApplies: false}})); let bidRequest = bidRequests[0]; expect(bidRequest).to.have.property('regs'); expect(bidRequest.regs.ext).to.be.eql({'gdpr': 0}); @@ -212,7 +210,7 @@ describe('Adkernel adapter', function () { }); it('should\'t pass dnt if state is unknown', function () { - let [_, bidRequests] = buildRequest([bid1_zone1], {}, 'https://example.com/index.html', false); + let [_, bidRequests] = buildRequest([bid1_zone1], DEFAULT_BIDDER_REQUEST, false); expect(bidRequests[0].device).to.not.have.property('dnt'); }); }); From 3178468333a6913fc641057e53221ecbf7dab7c7 Mon Sep 17 00:00:00 2001 From: John Salis Date: Mon, 22 Oct 2018 11:06:37 -0400 Subject: [PATCH 0776/1594] use referrer detection module (#3188) --- modules/beachfrontBidAdapter.js | 27 ++++++++++++++----- .../spec/modules/beachfrontBidAdapter_spec.js | 19 ++++++++++--- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index ccb45d0a041..064b647f64d 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -1,11 +1,13 @@ import * as utils from 'src/utils'; +import { parse as parseUrl } from 'src/url'; +import { config } from 'src/config'; import { registerBidder } from 'src/adapters/bidderFactory'; import { Renderer } from 'src/Renderer'; import { VIDEO, BANNER } from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.3'; +const ADAPTER_VERSION = '1.4'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; @@ -237,6 +239,19 @@ function isBannerBidValid(bid) { return isBannerBid(bid) && getBannerBidParam(bid, 'appId') && getBannerBidParam(bid, 'bidfloor'); } +function getTopWindowLocation(bidderRequest) { + let url = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; + return parseUrl(config.getConfig('pageUrl') || url, { decodeSearchAsString: true }); +} + +function getTopWindowReferrer() { + try { + return window.top.document.referrer; + } catch (e) { + return ''; + } +} + function getVideoTargetingParams(bid) { return Object.keys(Object(bid.params.video)) .filter(param => includes(VIDEO_TARGETING, param)) @@ -252,7 +267,7 @@ function createVideoRequestData(bid, bidderRequest) { let video = getVideoTargetingParams(bid); let appId = getVideoBidParam(bid, 'appId'); let bidfloor = getVideoBidParam(bid, 'bidfloor'); - let topLocation = utils.getTopWindowLocation(); + let topLocation = getTopWindowLocation(bidderRequest); let payload = { isPrebid: true, appId: appId, @@ -294,8 +309,8 @@ function createVideoRequestData(bid, bidderRequest) { } function createBannerRequestData(bids, bidderRequest) { - let topLocation = utils.getTopWindowLocation(); - let referrer = utils.getTopWindowReferrer(); + let topLocation = getTopWindowLocation(bidderRequest); + let topReferrer = getTopWindowReferrer(); let slots = bids.map(bid => { return { slot: bid.adUnitCode, @@ -309,8 +324,8 @@ function createBannerRequestData(bids, bidderRequest) { page: topLocation.href, domain: topLocation.hostname, search: topLocation.search, - secure: topLocation.protocol === 'https:' ? 1 : 0, - referrer: referrer, + secure: topLocation.protocol.indexOf('https') === 0 ? 1 : 0, + referrer: topReferrer, ua: navigator.userAgent, deviceOs: getOsVersion(), isMobile: isMobile() ? 1 : 0, diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 21e175a5b82..b369ed1f941 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,6 +1,7 @@ import { expect } from 'chai'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import * as utils from 'src/utils'; +import { parse as parseUrl } from 'src/url'; describe('BeachfrontAdapter', function () { let bidRequests; @@ -150,9 +151,14 @@ describe('BeachfrontAdapter', function () { playerSize: [ width, height ] } }; - const requests = spec.buildRequests([ bidRequest ]); + const topLocation = parseUrl('http://www.example.com?foo=bar', { decodeSearchAsString: true }); + const bidderRequest = { + refererInfo: { + referer: topLocation.href + } + }; + const requests = spec.buildRequests([ bidRequest ], bidderRequest); const data = requests[0].data; - const topLocation = utils.getTopWindowLocation(); expect(data.isPrebid).to.equal(true); expect(data.appId).to.equal(bidRequest.params.appId); expect(data.domain).to.equal(document.location.hostname); @@ -270,9 +276,14 @@ describe('BeachfrontAdapter', function () { sizes: [ width, height ] } }; - const requests = spec.buildRequests([ bidRequest ]); + const topLocation = parseUrl('http://www.example.com?foo=bar', { decodeSearchAsString: true }); + const bidderRequest = { + refererInfo: { + referer: topLocation.href + } + }; + const requests = spec.buildRequests([ bidRequest ], bidderRequest); const data = requests[0].data; - const topLocation = utils.getTopWindowLocation(); expect(data.slots).to.deep.equal([ { slot: bidRequest.adUnitCode, From db677442e00d0e2d1bc4563c98c1a1a4547d880e Mon Sep 17 00:00:00 2001 From: skazedo Date: Mon, 22 Oct 2018 14:09:12 -0400 Subject: [PATCH 0777/1594] ZEDO - Updated Documentation (#3192) * initial commit * updated contact and tag details * changes ti support the renderers * changes to pass dimId * fixed names of internal mapping * added comment * added gdpr param to request and other fixes * modified api url * fix * fixed the secure api call * rolled back video event callback till we support it * updated doc with video details --- modules/zedoBidAdapter.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/modules/zedoBidAdapter.md b/modules/zedoBidAdapter.md index 6555a1e6506..1ea35585a64 100644 --- a/modules/zedoBidAdapter.md +++ b/modules/zedoBidAdapter.md @@ -8,10 +8,16 @@ Maintainer: prebidsupport@zedo.com Module that connects to ZEDO's demand sources. +ZEDO supports both display and video. For video integration, ZEDO 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 +ZEDO has its own renderer and will render the video unit if not defined in the config. + + # Test Parameters +# display ``` + var adUnits = [ { code: 'banner-ad-div', @@ -28,3 +34,29 @@ For video integration, ZEDO returns content as vastXML and requires the publishe } ]; ``` +# video +``` + + var adUnit1 = [ + { + code: 'videoAdUnit', + mediaTypes: + { + video: + { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [ + { + bidder: 'zedo', + params: + { + channelCode: 2264004593, + dimId: 85 + } + } + ] + }]; +``` \ No newline at end of file From 52b8a773d75831dc2e88b79865b44d1858f1d277 Mon Sep 17 00:00:00 2001 From: Dave Naffis Date: Mon, 22 Oct 2018 14:27:32 -0400 Subject: [PATCH 0778/1594] change domain of sync URL (#3207) --- modules/consumableBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/consumableBidAdapter.js b/modules/consumableBidAdapter.js index 7d8cc1b2deb..8ed0f6dfc91 100644 --- a/modules/consumableBidAdapter.js +++ b/modules/consumableBidAdapter.js @@ -127,7 +127,7 @@ export const spec = { if (syncOptions.iframeEnabled) { return [{ type: 'iframe', - url: '//s.zkcdn.net/ss/' + siteId + '.html' + url: '//sync.serverbid.com/ss/' + siteId + '.html' }]; } else { utils.logWarn(bidder + ': Please enable iframe based user syncing.'); From bf3b3ae988fb620cf9116dff979e0889f0506a27 Mon Sep 17 00:00:00 2001 From: avj83 Date: Tue, 23 Oct 2018 00:55:02 +0400 Subject: [PATCH 0779/1594] rename buyer to dspx (#3210) --- modules/{buyerBidAdapter.js => dspxBidAdapter.js} | 4 ++-- modules/{buyerBidAdapter.md => dspxBidAdapter.md} | 14 +++++++------- ...erBidAdapter_spec.js => dspxBidAdapter_spec.js} | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) rename modules/{buyerBidAdapter.js => dspxBidAdapter.js} (98%) mode change 100755 => 100644 rename modules/{buyerBidAdapter.md => dspxBidAdapter.md} (91%) mode change 100755 => 100644 rename test/spec/modules/{buyerBidAdapter_spec.js => dspxBidAdapter_spec.js} (96%) mode change 100755 => 100644 diff --git a/modules/buyerBidAdapter.js b/modules/dspxBidAdapter.js old mode 100755 new mode 100644 similarity index 98% rename from modules/buyerBidAdapter.js rename to modules/dspxBidAdapter.js index 61500edf38b..6cf0b32a7d7 --- a/modules/buyerBidAdapter.js +++ b/modules/dspxBidAdapter.js @@ -2,12 +2,12 @@ import * as utils from 'src/utils'; import {config} from 'src/config'; import {registerBidder} from 'src/adapters/bidderFactory'; -const BIDDER_CODE = 'buyer'; +const BIDDER_CODE = 'dspx'; const ENDPOINT_URL = 'https://buyer.dspx.tv/request/'; export const spec = { code: BIDDER_CODE, - aliases: ['buyer'], + aliases: ['dspx'], isBidRequestValid: function(bid) { return !!(bid.params.placement); }, diff --git a/modules/buyerBidAdapter.md b/modules/dspxBidAdapter.md old mode 100755 new mode 100644 similarity index 91% rename from modules/buyerBidAdapter.md rename to modules/dspxBidAdapter.md index 607cbf190e0..362f4fbcb69 --- a/modules/buyerBidAdapter.md +++ b/modules/dspxBidAdapter.md @@ -1,14 +1,14 @@ # Overview ``` -Module Name: Buyer Bidder Adapter +Module Name: Dspx Bidder Adapter Module Type: Bidder Adapter -Maintainer: avj83@list.ru +Maintainer: prebid@dspx.tv ``` # Description -Buyer adapter for Prebid.js 1.0 +Dspx adapter for Prebid.js 1.0 # Test Parameters ``` @@ -25,9 +25,9 @@ Buyer adapter for Prebid.js 1.0 }, bids: [ { - bidder: "buyer", + bidder: "dspx", params: { - placement: '12345', + placement: '101', pfilter: { floorprice: 1000000, // EUR * 1,000,000 private_auction: 1, // Is private auction? 0 - no, 1 - yes @@ -60,9 +60,9 @@ Buyer adapter for Prebid.js 1.0 }, bids: [ { - bidder: "buyer", + bidder: "dspx", params: { - placement: 67890 + placement: 101 } } ] diff --git a/test/spec/modules/buyerBidAdapter_spec.js b/test/spec/modules/dspxBidAdapter_spec.js old mode 100755 new mode 100644 similarity index 96% rename from test/spec/modules/buyerBidAdapter_spec.js rename to test/spec/modules/dspxBidAdapter_spec.js index 602a1104fdb..7eeac43680a --- a/test/spec/modules/buyerBidAdapter_spec.js +++ b/test/spec/modules/dspxBidAdapter_spec.js @@ -1,15 +1,15 @@ import { expect } from 'chai'; -import { spec } from 'modules/buyerBidAdapter'; +import { spec } from 'modules/dspxBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT_URL = 'https://buyer.dspx.tv/request/'; -describe('buyerAdapter', function () { +describe('dspxAdapter', function () { const adapter = newBidder(spec); describe('isBidRequestValid', function () { let bid = { - 'bidder': 'buyer', + 'bidder': 'dspx', 'params': { 'placement': '6682', 'pfilter': { @@ -42,7 +42,7 @@ describe('buyerAdapter', function () { describe('buildRequests', function () { let bidRequests = [{ - 'bidder': 'buyer', + 'bidder': 'dspx', 'params': { 'placement': '6682', 'pfilter': { From 14d3031d5f754faf556d13b01e2f368bed4ba906 Mon Sep 17 00:00:00 2001 From: Dmitry Fedotov <4129726+drdmitry@users.noreply.github.com> Date: Tue, 23 Oct 2018 15:59:37 +0200 Subject: [PATCH 0780/1594] Fixes #3197 - call auctionDone() when 'No valid bid requests returned for auction' (#3198) * Fixes #3197 - call auctionDone() when 'No valid bid requests returned for auction' * #3197 Added unit test to check if callback is called when bidRequests is empty --- src/auction.js | 1 + test/spec/unit/pbjs_api_spec.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/auction.js b/src/auction.js index 50b681d61a8..61c403e7ff5 100644 --- a/src/auction.js +++ b/src/auction.js @@ -196,6 +196,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) if (bidRequests.length < 1) { utils.logWarn('No valid bid requests returned for auction'); + auctionDone(); } else { let call = { bidRequests, diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 61e26891bac..a03339c76b3 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1193,6 +1193,39 @@ describe('Unit: Prebid Module', function () { }); }) + describe('requestBids', function () { + let sandbox; + beforeEach(function () { + sandbox = sinon.sandbox.create(); + }); + afterEach(function () { + sandbox.restore(); + }); + describe('bidRequests is empty', function () { + it('should log warning message and execute callback if bidRequests is empty', function () { + let bidsBackHandler = function bidsBackHandlerCallback() {}; + let spyExecuteCallback = sinon.spy(bidsBackHandler); + let logWarnSpy = sandbox.spy(utils, 'logWarn'); + + $$PREBID_GLOBAL$$.requestBids({ + adUnits: [ + { + code: 'test1', + bids: [], + }, { + code: 'test2', + bids: [], + } + ], + bidsBackHandler: spyExecuteCallback + }); + + assert.ok(logWarnSpy.calledWith('No valid bid requests returned for auction'), 'expected warning message was logged'); + assert.ok(spyExecuteCallback.calledOnce, 'callback executed when bidRequests is empty'); + }); + }); + }); + describe('requestBids', function () { let xhr; let requests; From ebca05ab446237df09895e338b96729b4224f1dc Mon Sep 17 00:00:00 2001 From: REXRTB Date: Tue, 23 Oct 2018 17:24:24 +0300 Subject: [PATCH 0781/1594] [Update rexrtbBidAdapter] Update default host (#3217) * Add: rxrtb prebidAdapter * Update: params for test * Update: code format * Update: code format * Update: code format * Fix param check * Update rxrtbBidAdapter.js * Remove required source param * Update and rename rxrtbBidAdapter.js to rexrtbBidAdapter.js * Update and rename rxrtbBidAdapter.md to rexrtbBidAdapter.md * Update and rename rxrtbBidAdapter_spec.js to rexrtbBidAdapter_spec.js * Revert "Update rxrtbBidAdapter.js" This reverts commit 09bca026d7e28e98ed5ff7a138df78618cd363a2. * Revert "Update and rename rxrtbBidAdapter_spec.js to rexrtbBidAdapter_spec.js" This reverts commit 2481c58bb10a4634327773198edaaeea3b5a89f5. * Revert "Update and rename rxrtbBidAdapter.md to rexrtbBidAdapter.md" This reverts commit af9a49134752043e83c6fd922ba16e7ffd6f8f42. * Revert "Update and rename rxrtbBidAdapter.js to rexrtbBidAdapter.js" This reverts commit 81a17ad8076cdafc637ca9a69f57fe1180a8c7a1. * Revert "Remove required source param" This reverts commit 38b273d76aa2d93ab167b96db80ca146d5267e2e. * Revert "Update rxrtbBidAdapter.js" * Update and rename rexrtbPrebid * Update default host * Revert update * Update default host --- modules/rexrtbBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rexrtbBidAdapter.js b/modules/rexrtbBidAdapter.js index 4048bf40afe..f8388e1e74f 100644 --- a/modules/rexrtbBidAdapter.js +++ b/modules/rexrtbBidAdapter.js @@ -4,7 +4,7 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import {config} from 'src/config'; const BIDDER_CODE = 'rexrtb'; -const DEFAULT_HOST = 'bid.rxrtb.bid'; +const DEFAULT_HOST = 'bid.rxrtb.com'; const AUCTION_TYPE = 2; const RESPONSE_TTL = 900; From 47d726a3abe0a4b2dc7c0d8ba426412ba01f9e22 Mon Sep 17 00:00:00 2001 From: HolzAndrew Date: Tue, 23 Oct 2018 10:27:20 -0400 Subject: [PATCH 0782/1594] adds height and width params to request (#3215) --- modules/openxoutstreamBidAdapter.js | 4 +++- test/spec/modules/openxoutstreamBidAdapter_spec.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js index 6da234284c6..dde101f25d5 100644 --- a/modules/openxoutstreamBidAdapter.js +++ b/modules/openxoutstreamBidAdapter.js @@ -86,7 +86,9 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { auid: '540141567', dddid: utils._map(bids, bid => bid.transactionId).join(','), openrtb: '%7B%22mimes%22%3A%5B%22video%2Fmp4%22%5D%7D', - nocache: new Date().getTime() + nocache: new Date().getTime(), + vht: bids[0].params.height || bids[0].sizes[0][1], + vwd: bids[0].params.width || bids[0].sizes[0][0] }; if (utils.deepAccess(bidderRequest, 'gdprConsent')) { diff --git a/test/spec/modules/openxoutstreamBidAdapter_spec.js b/test/spec/modules/openxoutstreamBidAdapter_spec.js index a1d4f4aa2d4..59d56bee74b 100644 --- a/test/spec/modules/openxoutstreamBidAdapter_spec.js +++ b/test/spec/modules/openxoutstreamBidAdapter_spec.js @@ -99,6 +99,7 @@ describe('OpenXOutstreamAdapter', function () { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', + 'sizes': [300, 250], mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] From b4705e3b3c5b3b51d79a7fc0dfcdd55a28b732ae Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 23 Oct 2018 10:32:20 -0400 Subject: [PATCH 0783/1594] Rubicon adapter: Removed extraneous warning (#3218) * Rubicon adapter: Removed extraneous warning * removing spaces to kick off the build again circleci failed on some other adapter --- modules/rubiconBidAdapter.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 90210ec4ac8..20175ceb550 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -92,11 +92,9 @@ export const spec = { if (typeof bid.params !== 'object') { return false; } - if (!/^\d+$/.test(bid.params.accountId)) { return false; } - return !!bidType(bid, true); }, /** @@ -581,7 +579,6 @@ function mapSizes(sizes) { */ export function hasVideoMediaType(bidRequest) { if (typeof utils.deepAccess(bidRequest, 'params.video') === 'undefined' && Array.isArray(utils.deepAccess(bidRequest, 'params.sizes'))) { - utils.logWarn('Rubicon bid adapter Warning: no video params found, convert to banner with the bidder size id'); return false; } return (bidRequest.mediaType === VIDEO || typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'); From 62137081f2f15c20517251e904b05148f093dc41 Mon Sep 17 00:00:00 2001 From: susyt Date: Tue, 23 Oct 2018 11:12:05 -0700 Subject: [PATCH 0784/1594] updates jcsi (#3220) --- modules/gumgumBidAdapter.js | 75 ++----------------------------------- 1 file changed, 4 insertions(+), 71 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 55a22c23ef8..33baaf83548 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -13,76 +13,6 @@ const TIME_TO_LIVE = 60 let browserParams = {}; let pageViewId = null -function hasTopAccess () { - var hasTopAccess = false - try { hasTopAccess = !!top.document } catch (e) {} - return hasTopAccess -} - -function isInSafeFrame (windowRef) { - const w = windowRef || window - if (w.$sf) return w.$sf - else if (hasTopAccess() && w !== top) return isInSafeFrame(w.parent) - return null -} - -function getGoogleTag (windowRef) { - try { - const w = windowRef || window - var GOOGLETAG = null - if ('googletag' in w) { - GOOGLETAG = w.googletag - } else if (w !== top) { - GOOGLETAG = getGoogleTag(w.parent) - } - return GOOGLETAG - } catch (error) { - utils.logError('Error getting googletag ', error) - return null - } -} - -function getAMPContext (windowRef) { - const w = windowRef || window - var context = null - var nameJSON = null - if (utils.isPlainObject(w.context)) { - context = w.context - } else { - try { - nameJSON = JSON.parse(w.name || null) - } catch (error) { - utils.logError('Error getting w.name', error) - } - if (utils.isPlainObject(nameJSON)) { - context = nameJSON._context || (nameJSON.attributes ? nameJSON.attributes._context : null) - } - if (utils.isPlainObject(w.AMP_CONTEXT_DATA)) { - context = w.AMP_CONTEXT_DATA - } - } - return context -} - -function getJCSI () { - const entrypointOffset = 7 - const inFrame = (window.top && window.top !== window) - const frameType = (!inFrame ? 1 : (isInSafeFrame() ? 2 : (hasTopAccess() ? 3 : 4))) - const context = [] - if (getAMPContext()) { - context.push(1) - } - if (getGoogleTag()) { - context.push(2) - } - const jcsi = { - ep: entrypointOffset, - fc: frameType, - ctx: context - } - return JSON.stringify(jcsi) -} - // TODO: potential 0 values for browserParams sent to ad server function _getBrowserParams() { let topWindow @@ -111,7 +41,10 @@ function _getBrowserParams() { pu: topUrl, ce: utils.cookiesAreEnabled(), dpr: topWindow.devicePixelRatio || 1, - jcsi: getJCSI() + jcsi: { + t: 0, + rq: 7 + } } ggad = (topUrl.match(/#ggad=(\w+)$/) || [0, 0])[1] if (ggad) { From a7b143dd662dff3f0a9763272dc3dc04b7ad9643 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 23 Oct 2018 14:32:07 -0400 Subject: [PATCH 0785/1594] Prebid 1.29.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0bfe17c256e..56eeee85469 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.29.0-pre", + "version": "1.29.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 8159d4085a84525a54f9dd320595c6d27b2dc45b Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 23 Oct 2018 15:24:17 -0400 Subject: [PATCH 0786/1594] Increment pre version --- package.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 56eeee85469..a53085fa062 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.29.0", + "version": "1.30.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { @@ -46,6 +46,7 @@ "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", "gulp-connect": "5.5.0", + "gulp-coveralls": "^0.1.4", "gulp-eslint": "^4.0.0", "gulp-footer": "^1.0.5", "gulp-header": "^1.7.1", @@ -101,11 +102,19 @@ "yargs": "^1.3.1" }, "dependencies": { + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.1", "babel-plugin-transform-object-assign": "^6.22.0", "core-js": "^2.4.1", "crypto-js": "^3.1.9-1", + "eslint-scope": "^4.0.0", + "grunt-coveralls": "^2.0.0", "gulp-sourcemaps": "^2.6.0", + "has-ansi": "^3.0.0", "jsencrypt": "^3.0.0-rc.1", - "just-clone": "^1.0.2" + "just-clone": "^1.0.2", + "supports-color": "^5.5.0", + "util-deprecate": "^1.0.2", + "vlq": "^1.0.0" } } From bd3cb66d101292477f5ff7e7411bc5117410d179 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 23 Oct 2018 13:48:06 -0600 Subject: [PATCH 0787/1594] add proper cleanup to realvu analytics (#3195) --- modules/realvuAnalyticsAdapter.js | 29 ++- .../modules/realvuAnalyticsAdapter_spec.js | 233 +++++++++--------- 2 files changed, 138 insertions(+), 124 deletions(-) diff --git a/modules/realvuAnalyticsAdapter.js b/modules/realvuAnalyticsAdapter.js index 1ce854b539e..217ccb2b596 100644 --- a/modules/realvuAnalyticsAdapter.js +++ b/modules/realvuAnalyticsAdapter.js @@ -20,8 +20,8 @@ try { } catch (e) { /* continue regardless of error */ } -window.top1.realvu_aa_fifo = window.top1.realvu_aa_fifo || []; -window.top1.realvu_aa = window.top1.realvu_aa || { + +export let lib = { ads: [], x1: 0, y1: 0, @@ -35,6 +35,7 @@ window.top1.realvu_aa = window.top1.realvu_aa || { c: '', // owner id sr: '', // beacons: [], // array of beacons to collect while 'conf' is not responded + defer: [], init: function () { let z = this; let u = navigator.userAgent; @@ -75,13 +76,10 @@ window.top1.realvu_aa = window.top1.realvu_aa || { }, add_evt: function (elem, evtType, func) { - if (elem.addEventListener) { - elem.addEventListener(evtType, func, true); - } else if (elem.attachEvent) { - elem.attachEvent('on' + evtType, func); - } else { - elem['on' + evtType] = func; - } + elem.addEventListener(evtType, func, true); + this.defer.push(function() { + elem.removeEventListener(evtType, func, true); + }); }, update: function () { @@ -849,6 +847,9 @@ window.top1.realvu_aa = window.top1.realvu_aa || { } }; +window.top1.realvu_aa_fifo = window.top1.realvu_aa_fifo || []; +window.top1.realvu_aa = window.top1.realvu_aa || lib; + if (typeof (window.top1.boost_poll) == 'undefined') { window.top1.realvu_aa.init(); window.top1.boost_poll = setInterval(function () { @@ -937,9 +938,17 @@ realvuAnalyticsAdapter.isInView = function (adUnitCode) { return r; }; +let disableAnalyticsSuper = realvuAnalyticsAdapter.disableAnalytics; +realvuAnalyticsAdapter.disableAnalytics = function () { + while (lib.defer.length) { + lib.defer.pop()(); + } + disableAnalyticsSuper.apply(this, arguments); +}; + adaptermanager.registerAnalyticsAdapter({ adapter: realvuAnalyticsAdapter, code: 'realvuAnalytics' }); -module.exports = realvuAnalyticsAdapter; +export default realvuAnalyticsAdapter; diff --git a/test/spec/modules/realvuAnalyticsAdapter_spec.js b/test/spec/modules/realvuAnalyticsAdapter_spec.js index 1d0fcf9be1a..1aa1c4be8a5 100644 --- a/test/spec/modules/realvuAnalyticsAdapter_spec.js +++ b/test/spec/modules/realvuAnalyticsAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import realvuAnalyticsAdapter from 'modules/realvuAnalyticsAdapter'; +import realvuAnalyticsAdapter, { lib } from 'modules/realvuAnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; function addDiv(id) { @@ -22,142 +22,147 @@ function addDiv(id) { return dv; } -describe('RealVu Analytics Adapter.', function () { - before(function () { +describe('RealVu', function() { + let sandbox; + beforeEach(function () { + sandbox = sinon.sandbox.create(); addDiv('ad1'); addDiv('ad2'); + sandbox.stub(lib, 'scr'); }); - after(function () { + + afterEach(function () { let a1 = document.getElementById('ad1'); document.body.removeChild(a1); let a2 = document.getElementById('ad2'); document.body.removeChild(a2); + sandbox.restore(); + realvuAnalyticsAdapter.disableAnalytics(); }); - it('enableAnalytics', function () { - const config = { - options: { - partnerId: '1Y', - regAllUnits: true - // unitIds: ['ad1', 'ad2'] - } - }; - let p = realvuAnalyticsAdapter.enableAnalytics(config); - expect(p).to.equal('1Y'); - }); - - it('checkIn', function () { - const bid = { - adUnitCode: 'ad1', - sizes: [ - [728, 90], - [970, 250], - [970, 90] - ] - }; - let result = realvuAnalyticsAdapter.checkIn(bid, '1Y'); - const b = window.top1.realvu_aa; - let a = b.ads[0]; - // console.log('a: ' + a.x + ', ' + a.y + ', ' + a.w + ', ' + a.h); - // console.log('b: ' + b.x1 + ', ' + b.y1 + ', ' + b.x2 + ', ' + b.y2); - expect(result).to.equal('yes'); - - result = realvuAnalyticsAdapter.checkIn(bid); // test invalid partnerId 'undefined' - result = realvuAnalyticsAdapter.checkIn(bid, ''); // test invalid partnerId '' + after(function () { + delete window.top1; + delete window.realvu_aa_fifo; + delete window.realvu_aa; + clearInterval(window.boost_poll); + delete window.boost_poll; }); - it.skip('isInView returns "yes"', () => { - let inview = realvuAnalyticsAdapter.isInView('ad1'); - expect(inview).to.equal('yes'); - }); + describe('Analytics Adapter.', function () { + it('enableAnalytics', function () { + const config = { + options: { + partnerId: '1Y', + regAllUnits: true + // unitIds: ['ad1', 'ad2'] + } + }; + let p = realvuAnalyticsAdapter.enableAnalytics(config); + expect(p).to.equal('1Y'); + }); - it('isInView return "NA"', function () { - const adUnitCode = '1234'; - let result = realvuAnalyticsAdapter.isInView(adUnitCode); - expect(result).to.equal('NA'); - }); + it('checkIn', function () { + const bid = { + adUnitCode: 'ad1', + sizes: [ + [728, 90], + [970, 250], + [970, 90] + ] + }; + let result = realvuAnalyticsAdapter.checkIn(bid, '1Y'); + const b = window.top1.realvu_aa; + let a = b.ads[0]; + // console.log('a: ' + a.x + ', ' + a.y + ', ' + a.w + ', ' + a.h); + // console.log('b: ' + b.x1 + ', ' + b.y1 + ', ' + b.x2 + ', ' + b.y2); + expect(result).to.equal('yes'); + + result = realvuAnalyticsAdapter.checkIn(bid); // test invalid partnerId 'undefined' + result = realvuAnalyticsAdapter.checkIn(bid, ''); // test invalid partnerId '' + }); - it('bid response event', function () { - const config = { - options: { - partnerId: '1Y', - regAllUnits: true - // unitIds: ['ad1', 'ad2'] - } - }; - realvuAnalyticsAdapter.enableAnalytics(config); - const args = { - 'biddercode': 'realvu', - 'adUnitCode': 'ad1', - 'width': 300, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '7ba299eba818c1', - 'mediaType': 'banner', - 'creative_id': 85792851, - 'cpm': 0.4308 - }; - realvuAnalyticsAdapter.track({ - eventType: CONSTANTS.EVENTS.BID_RESPONSE, - args: args + it.skip('isInView returns "yes"', () => { + let inview = realvuAnalyticsAdapter.isInView('ad1'); + expect(inview).to.equal('yes'); }); - const boost = window.top1.realvu_aa; - expect(boost.ads[boost.len - 1].bids.length).to.equal(1); - realvuAnalyticsAdapter.track({ - eventType: CONSTANTS.EVENTS.BID_WON, - args: args + it('isInView return "NA"', function () { + const adUnitCode = '1234'; + let result = realvuAnalyticsAdapter.isInView(adUnitCode); + expect(result).to.equal('NA'); }); - expect(boost.ads[boost.len - 1].bids[0].winner).to.equal(1); - }); -}); -describe('RealVu Boost.', function () { - before(function () { - addDiv('ad1'); - addDiv('ad2'); - }); - after(function () { - let a1 = document.getElementById('ad1'); - document.body.removeChild(a1); - let a2 = document.getElementById('ad2'); - document.body.removeChild(a2); + it('bid response event', function () { + const config = { + options: { + partnerId: '1Y', + regAllUnits: true + // unitIds: ['ad1', 'ad2'] + } + }; + realvuAnalyticsAdapter.enableAnalytics(config); + const args = { + 'biddercode': 'realvu', + 'adUnitCode': 'ad1', + 'width': 300, + 'height': 250, + 'statusMessage': 'Bid available', + 'adId': '7ba299eba818c1', + 'mediaType': 'banner', + 'creative_id': 85792851, + 'cpm': 0.4308 + }; + realvuAnalyticsAdapter.track({ + eventType: CONSTANTS.EVENTS.BID_RESPONSE, + args: args + }); + const boost = window.top1.realvu_aa; + expect(boost.ads[boost.len - 1].bids.length).to.equal(1); + + realvuAnalyticsAdapter.track({ + eventType: CONSTANTS.EVENTS.BID_WON, + args: args + }); + expect(boost.ads[boost.len - 1].bids[0].winner).to.equal(1); + }); }); - const boost = window.top1.realvu_aa; + describe('Boost.', function () { + const boost = window.top1.realvu_aa; - it('brd', function () { - let a1 = document.getElementById('ad1'); - let p = boost.brd(a1, 'Left'); - expect(typeof p).to.not.equal('undefined'); - }); + it('brd', function () { + let a1 = document.getElementById('ad1'); + let p = boost.brd(a1, 'Left'); + expect(typeof p).to.not.equal('undefined'); + }); - it('addUnitById', function () { - let a1 = document.getElementById('ad1'); - let p = boost.addUnitById('1Y', 'ad1'); - expect(typeof p).to.not.equal('undefined'); - }); + it('addUnitById', function () { + let a1 = document.getElementById('ad1'); + let p = boost.addUnitById('1Y', 'ad1'); + expect(typeof p).to.not.equal('undefined'); + }); - it('questA', function () { - const dv = document.getElementById('ad1'); - let q = boost.questA(dv); - expect(q).to.not.equal(null); - }); + it('questA', function () { + const dv = document.getElementById('ad1'); + let q = boost.questA(dv); + expect(q).to.not.equal(null); + }); - it('render', function () { - let dv = document.getElementById('ad1'); - // dv.style.width = '728px'; - // dv.style.height = '90px'; - // dv.style.display = 'block'; - dv.getBoundingClientRect = false; - // document.body.appendChild(dv); - let q = boost.findPosG(dv); - expect(q).to.not.equal(null); - }); + it('render', function () { + let dv = document.getElementById('ad1'); + // dv.style.width = '728px'; + // dv.style.height = '90px'; + // dv.style.display = 'block'; + dv.getBoundingClientRect = false; + // document.body.appendChild(dv); + let q = boost.findPosG(dv); + expect(q).to.not.equal(null); + }); - it('readPos', function () { - const a = boost.ads[boost.len - 1]; - let r = boost.readPos(a); - expect(r).to.equal(true); + it('readPos', function () { + const a = boost.ads[boost.len - 1]; + let r = boost.readPos(a); + expect(r).to.equal(true); + }); }); }); From 5e27370b550451cb07cd75304a9e7af157312c5f Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Wed, 24 Oct 2018 10:46:39 -0400 Subject: [PATCH 0788/1594] Submitting EMX Digital Adapter (#3173) * Submitting EMX Digital Prebid Adapter Submitting EMX Digital Prebid Adapter code * fixing lint errors. updating our md * updating to const/let variables. adding test spec. * fixed linting on test spec js --- modules/emx_digitalBidAdapter.js | 108 ++++++ modules/emx_digitalBidAdapter.md | 38 ++ .../modules/emx_digitalBidAdapter_spec.js | 338 ++++++++++++++++++ 3 files changed, 484 insertions(+) create mode 100644 modules/emx_digitalBidAdapter.js create mode 100644 modules/emx_digitalBidAdapter.md create mode 100644 test/spec/modules/emx_digitalBidAdapter_spec.js diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js new file mode 100644 index 00000000000..c25c20f2eda --- /dev/null +++ b/modules/emx_digitalBidAdapter.js @@ -0,0 +1,108 @@ +import * as utils from 'src/utils'; +import { + registerBidder +} from 'src/adapters/bidderFactory'; +import { + BANNER +} from 'src/mediaTypes'; +import { + config +} from 'src/config'; + +const BIDDER_CODE = 'emx_digital'; +const ENDPOINT = 'hb.emxdgt.com'; +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + isBidRequestValid: function (bid) { + return !!(bid.params.tagid); + }, + buildRequests: function (validBidRequests, bidRequests) { + const {host, href, protocol} = utils.getTopWindowLocation(); + let emxData = {}; + let emxImps = []; + const auctionId = bidRequests.auctionId; + const timeout = config.getConfig('bidderTimeout'); + const timestamp = Date.now(); + const url = location.protocol + '//' + ENDPOINT + ('?t=' + timeout + '&ts=' + timestamp); + + utils._each(validBidRequests, function (bid) { + let tagId = String(utils.getBidIdParameter('tagid', bid.params)); + let bidFloor = utils.getBidIdParameter('bidfloor', bid.params) || 0; + let emxBid = { + id: bid.bidId, + tid: bid.transactionId, + tagid: tagId, + secure: protocol === 'https:' ? 1 : 0, + banner: { + format: bid.sizes.map(function (size) { + return { + w: size[0], + h: size[1] + }; + }), + w: bid.sizes[0][0], + h: bid.sizes[0][1] + } + } + if (bidFloor > 0) { + emxBid.bidfloor = bidFloor + } + emxImps.push(emxBid); + }); + emxData = { + id: auctionId, + imp: emxImps, + site: { + domain: host, + page: href + } + }; + if (bidRequests.gdprConsent) { + emxData.regs = { + ext: { + gdpr: bidRequests.gdprConsent.gdprApplies === true ? 1 : 0 + } + }; + } + if (bidRequests.gdprConsent && bidRequests.gdprConsent.gdprApplies) { + emxData.user = { + ext: { + consent: bidRequests.gdprConsent.consentString + } + }; + } + return { + method: 'POST', + url: url, + data: JSON.stringify(emxData), + options: { + withCredentials: true + } + }; + }, + interpretResponse: function (serverResponse) { + let emxBidResponses = []; + let response = serverResponse.body || {}; + if (response.seatbid && response.seatbid.length > 0 && response.seatbid[0].bid) { + response.seatbid.forEach(function (emxBid) { + emxBid = emxBid.bid[0]; + emxBidResponses.push({ + requestId: emxBid.id, + cpm: emxBid.price, + width: emxBid.w, + height: emxBid.h, + creativeId: emxBid.crid || emxBid.id, + dealId: emxBid.dealid || null, + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: decodeURIComponent(emxBid.adm), + ttl: emxBid.ttl + }); + }); + } + return emxBidResponses; + } +}; +registerBidder(spec); diff --git a/modules/emx_digitalBidAdapter.md b/modules/emx_digitalBidAdapter.md new file mode 100644 index 00000000000..c9435e2f1d1 --- /dev/null +++ b/modules/emx_digitalBidAdapter.md @@ -0,0 +1,38 @@ +# Overview + +``` +Module Name: EMX Digital Adapter +Module Type: Bidder Adapter +Maintainer: git@emxdigital.com +``` + +# Description + +The EMX Digital adapter provides publishers with access to the EMX Marketplace. The adapter is GDPR compliant. Please note that the adapter supports Banner media type only. + +Note: The EMX Digital adapter requires approval and implementation guidelines from the EMX team, including existing publishers that work with EMX Digital. Please reach out to your account manager or prebid@emxdigital.com for more information. + +The bidder code should be ```emx_digital``` +The params used by the bidder are : +```tagid``` - string (mandatory) +```bidfloor``` - string (optional) + +# Test Parameters +``` +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], [300, 600] + } + }, + bids: [ + { + bidder: 'emx_digital', + params: { + tagid: '25251', + } + }] +}]; +``` diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js new file mode 100644 index 00000000000..dd34582e22d --- /dev/null +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -0,0 +1,338 @@ +import { expect } from 'chai'; +import { spec } from 'modules/emx_digitalBidAdapter'; +import * as utils from 'src/utils'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('emx_digital Adapter', function () { + const adapter = newBidder(spec); + + describe('required function', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'emx_digital', + 'params': { + 'tagid': '25251' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c2501de1e', + 'bidderRequestId': '22edbae3120bf6', + 'auctionId': '1d1a01234a475' + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should contain tagid param', function () { + expect(spec.isBidRequestValid({ + params: {} + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + tagid: '' + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + tagid: '123' + } + })).to.equal(true); + }); + }); + + describe('buildRequests', function () { + const bidRequests = [{ + 'bidder': 'emx_digital', + 'params': { + 'tagid': '25251' + }, + 'adUnitCode': 'adunit-code', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [300, 250], + [300, 600] + ] + } + }, + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c2501de1e', + 'bidderRequestId': '22edbae3120bf6', + 'auctionId': 'e19f1eff-8b27-42a6-888d-9674e5a6130c', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec' + }, { + 'bidder': 'emx_digital', + 'params': { + 'tagid': '25251' + }, + 'adUnitCode': 'adunit-code', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [300, 250], + [300, 600] + ] + } + }, + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c2501de1e', + 'bidderRequestId': '22edbae3120bf6', + 'auctionId': 'e19f1eff-8b27-42a6-888d-9674e5a6130c', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec' + }]; + let bidderRequest = { + 'bidderCode': 'emx_digital', + 'auctionId': 'e19f1eff-8b27-42a6-888d-9674e5a6130c', + 'bidderRequestId': '22edbae3120bf6', + 'timeout': 1500, + }; + bidderRequest.bids = bidRequests + + let request = spec.buildRequests(bidRequests, bidderRequest); + + it('sends bid request to ENDPOINT via POST', function () { + expect(request.method).to.equal('POST'); + }); + + it('contains the correct options', function () { + expect(request.options.withCredentials).to.equal(true); + }); + + it('sends contains a properly formatted endpoint url', function () { + const url = request.url.split('?'); + const queryParams = url[1].split('&'); + expect(queryParams[0]).to.match(new RegExp('^t=\d*', 'g')); + expect(queryParams[1]).to.match(new RegExp('^ts=\d*', 'g')); + }); + + it('builds request properly', function () { + const data = JSON.parse(request.data); + + expect(Array.isArray(data.imp)).to.equal(true); + expect(data.id).to.equal(bidderRequest.auctionId); + expect(data.imp.length).to.equal(2); + expect(data.imp[0].id).to.equal('30b31c2501de1e'); + expect(data.imp[0].tid).to.equal('d7b773de-ceaa-484d-89ca-d9f51b8d61ec'); + expect(data.imp[0].tagid).to.equal('25251'); + expect(data.imp[0].secure).to.equal(0); + }); + + it('builds with bid floor', function() { + const bidRequestWithBidFloor = utils.deepClone(bidRequests); + bidRequestWithBidFloor[0].params.bidfloor = 1; + const requestWithFloor = spec.buildRequests(bidRequestWithBidFloor, bidderRequest); + const data = JSON.parse(requestWithFloor.data); + expect(data.imp[0].bidfloor).to.equal(bidRequestWithBidFloor[0].params.bidfloor); + }) + + it('properly sends site information and protocol', function () { + let mock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => { + return { + protocol: 'https:', + host: 'example.com', + href: 'https://example.com/index.html' + }; + }); + + let request; + + request = spec.buildRequests(bidRequests, bidderRequest); + request = JSON.parse(request.data); + expect(request.site.domain).to.equal('example.com'); + expect(request.site.page).to.equal('https://example.com/index.html'); + expect(request.imp[0].secure).to.equal(1); + + mock.restore(); + }) + + it('builds correctly formatted request banner object', function () { + let request; + + let bidRequestWithBanner = utils.deepClone(bidRequests); + + request = spec.buildRequests(bidRequestWithBanner, bidderRequest); + const data = JSON.parse(request.data); + expect(data.imp[0].banner.w).to.equal(bidRequestWithBanner[0].mediaTypes.banner.sizes[0][0]); + expect(data.imp[0].banner.h).to.equal(bidRequestWithBanner[0].mediaTypes.banner.sizes[0][1]); + expect(data.imp[0].banner.format[0].w).to.equal(bidRequestWithBanner[0].mediaTypes.banner.sizes[0][0]); + expect(data.imp[0].banner.format[0].h).to.equal(bidRequestWithBanner[0].mediaTypes.banner.sizes[0][1]); + expect(data.imp[0].banner.format[1].w).to.equal(bidRequestWithBanner[0].mediaTypes.banner.sizes[1][0]); + expect(data.imp[0].banner.format[1].h).to.equal(bidRequestWithBanner[0].mediaTypes.banner.sizes[1][1]); + }) + + it('shouldn\'t contain a user obj without GDPR information', function () { + let request = spec.buildRequests(bidRequests, bidderRequest) + request = JSON.parse(request.data) + expect(request).to.not.have.property('user'); + }); + + it('should have the right gdpr info when enabled', function () { + let consentString = 'OIJSZsOAFsABAB8EMXZZZZZ+A=='; + let bidderRequest = { + 'bidderCode': 'emx_digital', + 'auctionId': 'e19f1eff-8b27-42a6-888d-9674e5a6130c', + 'bidderRequestId': '22edbae3120bf6', + 'timeout': 1500, + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true + } + }; + bidderRequest.bids = bidRequests + let request = spec.buildRequests(bidRequests, bidderRequest); + + request = JSON.parse(request.data) + expect(request.regs.ext).to.have.property('gdpr', 1); + expect(request.user.ext).to.have.property('consent', 'OIJSZsOAFsABAB8EMXZZZZZ+A=='); + }); + + it('should\'t contain consent string if gdpr isn\'t applied', function () { + let bidderRequest = { + 'bidderCode': 'emx_digital', + 'auctionId': 'e19f1eff-8b27-42a6-888d-9674e5a6130c', + 'bidderRequestId': '22edbae3120bf6', + 'timeout': 1500, + 'gdprConsent': { + 'gdprApplies': false + } + }; + bidderRequest.bids = bidRequests + let request = spec.buildRequests(bidRequests, bidderRequest); + + request = JSON.parse(request.data) + expect(request.regs.ext).to.have.property('gdpr', 0); + expect(request).to.not.have.property('user'); + }); + }); + + describe('interpretResponse', function () { + const serverResponse = { + 'id': '12819a18-56e1-4256-b836-b69a10202668', + 'seatbid': [{ + 'bid': [{ + 'adid': '123456abcde', + 'adm': '', + 'crid': '3434abab34', + 'h': 250, + 'id': '987654321cba', + 'price': 0.5, + 'ttl': 300, + 'w': 300 + }], + 'seat': '1356' + }, { + 'bid': [{ + 'adid': '123456abcdf', + 'adm': '', + 'crid': '3434abab35', + 'h': 600, + 'id': '987654321cba', + 'price': 0.5, + 'ttl': 300, + 'w': 300 + }] + }] + }; + + const expectedResponse = [{ + 'requestId': '12819a18-56e1-4256-b836-b69a10202668', + 'cpm': 0.5, + 'width': 300, + 'height': 250, + 'creativeId': '3434abab34', + 'dealId': null, + 'currency': 'USD', + 'netRevneue': true, + 'mediaType': 'banner', + 'ad': '', + 'ttl': 300 + }, { + 'requestId': '12819a18-56e1-4256-b836-b69a10202668', + 'cpm': 0.7, + 'width': 300, + 'height': 600, + 'creativeId': '3434abab35', + 'dealId': null, + 'currency': 'USD', + 'netRevneue': true, + 'mediaType': 'banner', + 'ad': '', + 'ttl': 300 + }]; + + it('should properly format bid response', function () { + let result = spec.interpretResponse({ + body: serverResponse + }); + expect(Object.keys(result[0]).length).to.equal(Object.keys(expectedResponse[0]).length); + expect(Object.keys(result[0]).requestId).to.equal(Object.keys(expectedResponse[0]).requestId); + expect(Object.keys(result[0]).bidderCode).to.equal(Object.keys(expectedResponse[0]).bidderCode); + expect(Object.keys(result[0]).cpm).to.equal(Object.keys(expectedResponse[0]).cpm); + expect(Object.keys(result[0]).creativeId).to.equal(Object.keys(expectedResponse[0]).creativeId); + expect(Object.keys(result[0]).width).to.equal(Object.keys(expectedResponse[0]).width); + expect(Object.keys(result[0]).height).to.equal(Object.keys(expectedResponse[0]).height); + expect(Object.keys(result[0]).ttl).to.equal(Object.keys(expectedResponse[0]).ttl); + expect(Object.keys(result[0]).adId).to.equal(Object.keys(expectedResponse[0]).adId); + expect(Object.keys(result[0]).currency).to.equal(Object.keys(expectedResponse[0]).currency); + expect(Object.keys(result[0]).netRevenue).to.equal(Object.keys(expectedResponse[0]).netRevenue); + expect(Object.keys(result[0]).ad).to.equal(Object.keys(expectedResponse[0]).ad); + }); + + it('should return multiple bids', function () { + let result = spec.interpretResponse({ + body: serverResponse + }); + expect(Array.isArray(result.seatbid)) + + const ad0 = result[0]; + const ad1 = result[1]; + expect(ad0.ad).to.equal(serverResponse.seatbid[0].bid[0].adm); + expect(ad0.cpm).to.equal(serverResponse.seatbid[0].bid[0].price); + expect(ad0.creativeId).to.equal(serverResponse.seatbid[0].bid[0].crid); + expect(ad0.currency).to.equal('USD'); + expect(ad0.height).to.equal(serverResponse.seatbid[0].bid[0].h); + expect(ad0.mediaType).to.equal('banner'); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.requestId).to.equal(serverResponse.seatbid[0].bid[0].id); + expect(ad0.ttl).to.equal(300); + expect(ad0.width).to.equal(serverResponse.seatbid[0].bid[0].w); + + expect(ad1.ad).to.equal(serverResponse.seatbid[1].bid[0].adm); + expect(ad1.cpm).to.equal(serverResponse.seatbid[1].bid[0].price); + expect(ad1.creativeId).to.equal(serverResponse.seatbid[1].bid[0].crid); + expect(ad1.currency).to.equal('USD'); + expect(ad1.height).to.equal(serverResponse.seatbid[1].bid[0].h); + expect(ad1.mediaType).to.equal('banner'); + expect(ad1.netRevenue).to.equal(true); + expect(ad1.requestId).to.equal(serverResponse.seatbid[1].bid[0].id); + expect(ad1.ttl).to.equal(300); + expect(ad1.width).to.equal(serverResponse.seatbid[1].bid[0].w); + }); + + it('handles nobid responses', function () { + let serverResponse = { + 'bids': [] + }; + + let result = spec.interpretResponse({ + body: serverResponse + }); + expect(result.length).to.equal(0); + }); + }); +}); From 2863df1090a79d570fdddd12974a7da62fa98b3b Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Thu, 25 Oct 2018 23:03:19 +0300 Subject: [PATCH 0789/1594] TheMediaGrid Bid Adapter (#3204) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter --- modules/gridBidAdapter.js | 151 ++++++++++++ modules/gridBidAdapter.md | 40 +++ test/spec/modules/gridBidAdapter_spec.js | 299 +++++++++++++++++++++++ 3 files changed, 490 insertions(+) create mode 100644 modules/gridBidAdapter.js create mode 100755 modules/gridBidAdapter.md create mode 100644 test/spec/modules/gridBidAdapter_spec.js diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js new file mode 100644 index 00000000000..660b5c66a78 --- /dev/null +++ b/modules/gridBidAdapter.js @@ -0,0 +1,151 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'grid'; +const ENDPOINT_URL = '//grid.bidswitch.net/hb'; +const TIME_TO_LIVE = 360; +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', + noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', + emptyUids: 'Uids should be not empty', + emptySeatbid: 'Seatbid array from response has empty item', + emptyResponse: 'Response is empty', + hasEmptySeatbidArray: 'Response has empty seatbid array', + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' +}; +export const spec = { + code: BIDDER_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 !!bid.params.uid; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests - an array of bids + * @param {bidderRequest} bidderRequest bidder request object + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + const auids = []; + const bidsMap = {}; + const bids = validBidRequests || []; + let reqId; + + bids.forEach(bid => { + reqId = bid.bidderRequestId; + if (!bidsMap[bid.params.uid]) { + bidsMap[bid.params.uid] = [bid]; + auids.push(bid.params.uid); + } else { + bidsMap[bid.params.uid].push(bid); + } + }); + + const payload = { + u: utils.getTopWindowUrl(), + auids: auids.join(','), + r: reqId + }; + + if (bidderRequest) { + 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; + } + } + + return { + method: 'GET', + url: ENDPOINT_URL, + data: utils.parseQueryStringParameters(payload).replace(/\&$/, ''), + bidsMap: bidsMap, + }; + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param {*} bidRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidRequest) { + serverResponse = serverResponse && serverResponse.body; + const bidResponses = []; + const bidsMap = bidRequest.bidsMap; + + let errorMessage; + + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } + + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidsMap, bidResponses); + }); + } + if (errorMessage) utils.logError(errorMessage); + return bidResponses; + } +} + +function _getBidFromResponse(respItem) { + if (!respItem) { + utils.logError(LOG_ERROR_MESS.emptySeatbid); + } else if (!respItem.bid) { + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + } else if (!respItem.bid[0]) { + utils.logError(LOG_ERROR_MESS.noBid); + } + return respItem && respItem.bid && respItem.bid[0]; +} + +function _addBidResponse(serverBid, bidsMap, bidResponses) { + if (!serverBid) return; + let errorMessage; + if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + awaitingBids.forEach(bid => { + const bidResponse = { + requestId: bid.bidId, // bid.bidderRequestId, + bidderCode: spec.code, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, // bid.bidId, + currency: 'USD', + netRevenue: false, + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid + }; + bidResponses.push(bidResponse); + }); + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } + if (errorMessage) { + utils.logError(errorMessage); + } +} + +registerBidder(spec); diff --git a/modules/gridBidAdapter.md b/modules/gridBidAdapter.md new file mode 100755 index 00000000000..9b7b0e0515e --- /dev/null +++ b/modules/gridBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +Module Name: The Grid Media Bidder Adapter +Module Type: Bidder Adapter +Maintainer: grid-tech@themediagrid.com + +# Description + +Module that connects to Grid demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "grid", + params: { + uid: '1', + priceType: 'gross' // by default is 'net' + } + } + ] + },{ + code: 'test-div', + sizes: [[728, 90]], + bids: [ + { + bidder: "grid", + params: { + uid: 2, + priceType: 'gross' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js new file mode 100644 index 00000000000..f4401dfe677 --- /dev/null +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -0,0 +1,299 @@ +import { expect } from 'chai'; +import { spec } from 'modules/gridBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('TheMediaGrid Adapter', 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': 'grid', + 'params': { + 'uid': '1' + }, + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'uid': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + function parseRequest(url) { + const res = {}; + url.split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } + let bidRequests = [ + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '2' + }, + '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]]); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('auids', '1'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + }); + + it('auids must not be duplicated', function () { + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('auids', '1,2'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + }); + + it('if gdprConsent is present payload must have gdpr params', function () { + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); + 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 request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); + 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 request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); + 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'); + }); + }); + + describe('interpretResponse', function () { + const responses = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 2, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 3, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + undefined, + {'bid': [], 'seat': '1'}, + {'seat': '1'}, + ]; + + it('should get correct bid response', function () { + const bidRequests = [ + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 1, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'netRevenue': false, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should get correct multi bid response', function () { + const bidRequests = [ + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71a5b', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '2' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dff80cc4ee346', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '5703af74d0472a', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '300bfeb0d71a5b', + 'cpm': 1.15, + 'creativeId': 1, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'netRevenue': false, + 'ttl': 360, + }, + { + 'requestId': '5703af74d0472a', + 'cpm': 1.15, + 'creativeId': 1, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'netRevenue': false, + 'ttl': 360, + }, + { + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 2, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 2
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'netRevenue': false, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('handles wrong and nobid responses', function () { + const bidRequests = [ + { + 'bidder': 'grid', + 'params': { + 'uid': '3' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d7190gf', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '4' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71321', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '5' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '300bfeb0d7183bb', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + } + ]; + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + expect(result.length).to.equal(0); + }); + }); +}); From 50a7cffcdcfdecd45d7c9ec02395df9313e189aa Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Thu, 25 Oct 2018 16:24:32 -0400 Subject: [PATCH 0790/1594] Adding user sync method for IFRAME and Pixel (#3232) * Submitting EMX Digital Prebid Adapter Submitting EMX Digital Prebid Adapter code * fixing lint errors. updating our md * updating to const/let variables. adding test spec. * fixed linting on test spec js * adding emx usersync methods --- modules/emx_digitalBidAdapter.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index c25c20f2eda..042251ea035 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -103,6 +103,22 @@ export const spec = { }); } return emxBidResponses; + }, + getUserSyncs: function (syncOptions) { + const syncs = []; + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: '//biddr.brealtime.com/check.html' + }); + } + if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: '//edba.brealtime.com/' + }); + } + return syncs; } }; registerBidder(spec); From 5743e2bf2e086fec09f87f6337319d507e81efc5 Mon Sep 17 00:00:00 2001 From: Stephen Johnston Date: Fri, 26 Oct 2018 09:04:44 -0400 Subject: [PATCH 0791/1594] updates (#3162) --- src/utils.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index 77dfe10c918..93b19485dfe 100644 --- a/src/utils.js +++ b/src/utils.js @@ -66,10 +66,22 @@ exports.getUniqueIdentifierStr = _getUniqueIdentifierStr; */ exports.generateUUID = function generateUUID(placeholder) { return placeholder - ? (placeholder ^ Math.random() * 16 >> placeholder / 4).toString(16) + ? (placeholder ^ _getRandomData() >> placeholder / 4).toString(16) : ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, generateUUID); }; +/** + * Returns random data using the Crypto API if available and Math.random if not + * Method is from https://gist.github.com/jed/982883 like generateUUID, direct link https://gist.github.com/jed/982883#gistcomment-45104 + */ +function _getRandomData() { + if (window && window.crypto && window.crypto.getRandomValues) { + return crypto.getRandomValues(new Uint8Array(1))[0] % 16; + } else { + return Math.random() * 16; + } +} + exports.getBidIdParameter = function (key, paramsObj) { if (paramsObj && paramsObj[key]) { return paramsObj[key]; From 6363197be50c1cad6a5c4a17ba71d85582d45e0d Mon Sep 17 00:00:00 2001 From: Kenan Shifflett Date: Fri, 26 Oct 2018 11:15:06 -0400 Subject: [PATCH 0792/1594] Only set native targeting if value exists. (#3225) --- src/native.js | 4 ++-- test/spec/native_spec.js | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/native.js b/src/native.js index b4d2d959b70..c9d274ddccd 100644 --- a/src/native.js +++ b/src/native.js @@ -147,7 +147,7 @@ export function fireNativeTrackers(message, adObject) { } /** - * Gets native targeting key-value paris + * Gets native targeting key-value pairs * @param {Object} bid * @return {Object} targeting */ @@ -163,7 +163,7 @@ export function getNativeTargeting(bid) { value = value.url; } - if (key) { + if (key && value) { keyValues[key] = value; } }); diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 91b96cac281..68653808c06 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -16,6 +16,19 @@ const bid = { } }; +const bidWithUndefinedFields = { + native: { + title: 'Native Creative', + body: undefined, + cta: undefined, + sponsoredBy: 'AppNexus', + clickUrl: 'https://www.link.example', + clickTrackers: ['https://tracker.example'], + impressionTrackers: ['https://impression.example'], + javascriptTrackers: '' + } +}; + describe('native.js', function () { let triggerPixelStub; let insertHtmlIntoIframeStub; @@ -37,6 +50,16 @@ describe('native.js', function () { expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal(bid.native.clickUrl); }); + it('should only include native targeting keys with values', function () { + const targeting = getNativeTargeting(bidWithUndefinedFields); + + expect(Object.keys(targeting)).to.deep.equal([ + CONSTANTS.NATIVE_KEYS.title, + CONSTANTS.NATIVE_KEYS.sponsoredBy, + CONSTANTS.NATIVE_KEYS.clickUrl + ]); + }); + it('fires impression trackers', function () { fireNativeTrackers({}, bid); sinon.assert.calledOnce(triggerPixelStub); From e1f55ceb2f9385a080c80fb7d751d286b99356a6 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 26 Oct 2018 11:36:37 -0600 Subject: [PATCH 0793/1594] add nolint command line option, similar to notest (#3234) --- gulpfile.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index ced29b266a7..03a0a4a7559 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -76,7 +76,10 @@ function escapePostbidConfig() { }; escapePostbidConfig.displayName = 'escape-postbid-config'; -function lint() { +function lint(done) { + if (argv.nolint) { + return done(); + } return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js']) .pipe(eslint()) .pipe(eslint.format('stylish')) From fda63ec22a96907333651f37be5ee08b370b8023 Mon Sep 17 00:00:00 2001 From: Micha Niskin Date: Fri, 26 Oct 2018 15:50:56 -0400 Subject: [PATCH 0794/1594] add inskin iab vendor id: enables consent via string (#3235) --- modules/inskinBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js index 0e7e28b9b6b..27d01e677ef 100644 --- a/modules/inskinBidAdapter.js +++ b/modules/inskinBidAdapter.js @@ -59,6 +59,7 @@ export const spec = { if (bidderRequest && bidderRequest.gdprConsent) { data.consent = { + gdprVendorId: 150, gdprConsentString: 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 gdprConsentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true From 67b24c9edff4a5845cafd7a03342deb397493c82 Mon Sep 17 00:00:00 2001 From: Omer Koren Date: Mon, 29 Oct 2018 20:15:23 +0200 Subject: [PATCH 0795/1594] Added user sync support for undertone bid adapter (#3172) * Added user sync support for undertone bid adapter (new pull request) * Added user sync support for undertone bid adapter * fix indentation * Changed utils.getWindowTop() with the newer prebid utilities --- modules/undertoneBidAdapter.js | 77 +++++++++++++++---- test/spec/modules/undertoneBidAdapter_spec.js | 37 ++++++++- 2 files changed, 97 insertions(+), 17 deletions(-) diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index dd99df1fc7e..6d4ced88ba1 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -2,11 +2,44 @@ * Adapter to send bids to Undertone */ -import * as utils from 'src/utils'; +import * as urlUtils from 'src/url'; import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'undertone'; const URL = '//hb.undertone.com/hb'; +const FRAME_USER_SYNC = '//cdn.undertone.com/js/usersync.html'; +const PIXEL_USER_SYNC_1 = '//usr.undertone.com/userPixel/syncOne?id=1&of=2'; +const PIXEL_USER_SYNC_2 = '//usr.undertone.com/userPixel/syncOne?id=2&of=2'; + +function getCanonicalUrl() { + try { + let doc = window.top.document; + let element = doc.querySelector("link[rel='canonical']"); + if (element !== null) { + return element.href; + } + } catch (e) { + } + return null; +} + +function extractDomainFromHost(pageHost) { + 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; +} export const spec = { code: BIDDER_CODE, @@ -16,21 +49,14 @@ export const spec = { return true; } }, - buildRequests: function(validBidRequests) { + buildRequests: function(validBidRequests, bidderRequest) { const payload = { 'x-ut-hb-params': [] }; - const location = utils.getTopWindowLocation(); - let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(location.host); - let domain = null; - 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]; - } - } - } + const referer = bidderRequest.refererInfo.referer; + const hostname = urlUtils.parse(referer).hostname; + let domain = extractDomainFromHost(hostname); + const pageUrl = getCanonicalUrl() || referer; const pubid = validBidRequests[0].params.publisherId; const REQ_URL = `${URL}?pid=${pubid}&domain=${domain}`; @@ -39,7 +65,7 @@ export const spec = { const bid = { bidRequestId: bidReq.bidId, hbadaptor: 'prebid', - url: location.href, + url: pageUrl, domain: domain, placementId: bidReq.params.placementId != undefined ? bidReq.params.placementId : null, publisherId: bidReq.params.publisherId, @@ -78,6 +104,29 @@ export const spec = { }); } return bids; + }, + getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + const syncs = []; + if (gdprConsent && gdprConsent.gdprApplies === true) { + return syncs; + } + + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: FRAME_USER_SYNC + }); + } else if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: PIXEL_USER_SYNC_1 + }, + { + type: 'image', + url: PIXEL_USER_SYNC_2 + }); + } + return syncs; } }; registerBidder(spec); diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index 4b816d851d9..400e86567ea 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -44,6 +44,12 @@ const bidReq = [{ auctionId: '6c22f5a5-59df-4dc6-b92c-f433bcf0a874' }]; +const bidderReq = { + refererInfo: { + referer: 'http://prebid.org/dev-docs/bidder-adaptor.html' + } +}; + const validBidRes = { ad: '
Hello
', publisherId: 12345, @@ -98,14 +104,16 @@ describe('Undertone Adapter', function () { }); describe('build request', function () { it('should send request to correct url via POST', function () { - const request = spec.buildRequests(bidReq); - const domain = null; + const request = spec.buildRequests(bidReq, bidderReq); + const domainStart = bidderReq.refererInfo.referer.indexOf('//'); + const domainEnd = bidderReq.refererInfo.referer.indexOf('/', domainStart + 2); + const domain = bidderReq.refererInfo.referer.substring(domainStart + 2, domainEnd); const REQ_URL = `${URL}?pid=${bidReq[0].params.publisherId}&domain=${domain}`; expect(request.url).to.equal(REQ_URL); expect(request.method).to.equal('POST'); }); it('should have all relevant fields', function () { - const request = spec.buildRequests(bidReq); + const request = spec.buildRequests(bidReq, bidderReq); const bid1 = JSON.parse(request.data)['x-ut-hb-params'][0]; expect(bid1.bidRequestId).to.equal('263be71e91dd9d'); expect(bid1.sizes.length).to.equal(2); @@ -150,4 +158,27 @@ describe('Undertone Adapter', function () { expect(spec.interpretResponse({ body: bidResArray }).length).to.equal(1); }); }); + + describe('getUserSyncs', () => { + it('verifies gdpr consent checked', () => { + const options = ({ iframeEnabled: true, pixelEnabled: true }); + expect(spec.getUserSyncs(options, {}, { gdprApplies: true }).length).to.equal(0); + }); + + it('Verifies sync iframe option', function () { + const result = spec.getUserSyncs({ iframeEnabled: true, pixelEnabled: true }); + expect(result).to.have.lengthOf(1); + expect(result[0].type).to.equal('iframe'); + expect(result[0].url).to.equal('//cdn.undertone.com/js/usersync.html'); + }); + + it('Verifies sync image option', function () { + const result = spec.getUserSyncs({ pixelEnabled: true }); + expect(result).to.have.lengthOf(2); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('//usr.undertone.com/userPixel/syncOne?id=1&of=2'); + expect(result[1].type).to.equal('image'); + expect(result[1].url).to.equal('//usr.undertone.com/userPixel/syncOne?id=2&of=2'); + }); + }); }); From 4c085b8d0f430c6b476a58a19fc29976f638c56a Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 30 Oct 2018 06:52:03 -0700 Subject: [PATCH 0796/1594] Updating Auction Init Pick for timestamp + Test update (#3223) * Updating Auction Init Pick for timestamp + Test update * Updating Auction Init to include once again + Rubicon Analytics update accordingly * Removing from auction init events in favor of old --- src/auction.js | 2 +- .../modules/rubiconAnalyticsAdapter_spec.js | 54 ++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/auction.js b/src/auction.js index 61c403e7ff5..221cd519815 100644 --- a/src/auction.js +++ b/src/auction.js @@ -110,7 +110,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) function getProperties() { return { auctionId: _auctionId, - auctionStart: _auctionStart, + timestamp: _auctionStart, auctionEnd: _auctionEnd, auctionStatus: _auctionStatus, adUnits: _adUnits, diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index fa64513730a..97737675325 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -106,9 +106,59 @@ const MOCK = { [BID2.adUnitCode]: BID2.adserverTargeting }, AUCTION_INIT: { - 'timestamp': 1519767010567, 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'timeout': 3000 + 'timestamp': 1519767010567, + 'auctionStatus': 'inProgress', + 'adUnits': [ { + 'code': '/19968336/header-bid-tag1', + 'sizes': [[640, 480]], + 'bids': [ { + 'bidder': 'rubicon', + 'params': { + 'accountId': 1001, 'siteId': 113932, 'zoneId': 535512 + } + } ], + 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014' + } + ], + 'adUnitCodes': ['/19968336/header-bid-tag1'], + 'bidderRequests': [ { + 'bidderCode': 'rubicon', + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', + 'bidderRequestId': '1be65d7958826a', + 'bids': [ { + 'bidder': 'rubicon', + 'params': { + 'accountId': 1001, 'siteId': 113932, 'zoneId': 535512 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[640, 480]] + } + }, + 'adUnitCode': '/19968336/header-bid-tag1', + 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014', + 'sizes': [[640, 480]], + 'bidId': '2ecff0db240757', + 'bidderRequestId': '1be65d7958826a', + 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', + 'src': 'client', + 'bidRequestsCount': 1 + } + ], + 'auctionStart': 1519767010567, + 'timeout': 3000, + 'refererInfo': { + 'referer': 'http://www.test.com/page.html', 'reachedTop': true, 'numIframes': 0, 'stack': ['http://www.test.com/page.html'] + } + } + ], + 'bidsReceived': [], + 'winningBids': [], + 'timeout': 3000, + 'config': { + 'accountId': 1001, 'endpoint': '//localhost:9999/event' + } }, BID_REQUESTED: { 'bidder': 'rubicon', From 50d509764e6b1d81903c9f00a8ac0524131a397b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E9=9B=A8=E8=BB=92=20=D0=9F=D0=B5=D1=82=D1=80?= Date: Tue, 30 Oct 2018 15:47:21 +0100 Subject: [PATCH 0797/1594] Add code, test, and doc for Adikteev adapter (#3229) * Add code, test, and doc for Adikteev adapter * Reflect comments on other PR http://prebid.org/dev-docs/bidder-adaptor.html#referrers https://github.com/prebid/Prebid.js/pull/3230#discussion_r228319752 * 'currency' isn't a bidder-specific param Update PR following this remark on another one: https://github.com/prebid/Prebid.js/pull/3228#discussion_r228317072 * Add integration example, fix bid requestId --- .../gpt/hello_world_adikteev.html | 93 +++++++ integrationExamples/gpt/pbjs_example_gpt.html | 11 +- modules/adikteevBidAdapter.js | 94 +++++++ modules/adikteevBidAdapter.md | 35 +++ test/spec/modules/adikteevBidAdapter_spec.js | 235 ++++++++++++++++++ 5 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 integrationExamples/gpt/hello_world_adikteev.html create mode 100644 modules/adikteevBidAdapter.js create mode 100644 modules/adikteevBidAdapter.md create mode 100644 test/spec/modules/adikteevBidAdapter_spec.js diff --git a/integrationExamples/gpt/hello_world_adikteev.html b/integrationExamples/gpt/hello_world_adikteev.html new file mode 100644 index 00000000000..7372ff12d7f --- /dev/null +++ b/integrationExamples/gpt/hello_world_adikteev.html @@ -0,0 +1,93 @@ + + + + + + + + + + + +

Basic Prebid.js Example

+
Div-1
+
+ +
+ + + diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index 88d4839d984..6852b9f680a 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -312,8 +312,15 @@ width: '300', height: '250', } - } - + }, + { + bidder: 'adikteev', + params: { + placementId: 12345, + currency: 'EUR', + bidFloorPrice: 0.1, + } + }, ] }, { code: 'div-gpt-ad-12345678-1', diff --git a/modules/adikteevBidAdapter.js b/modules/adikteevBidAdapter.js new file mode 100644 index 00000000000..12d502de94a --- /dev/null +++ b/modules/adikteevBidAdapter.js @@ -0,0 +1,94 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +import {BANNER} from 'src/mediaTypes'; +import * as utils from '../src/utils'; +import {config} from 'src/config'; + +export const BIDDER_CODE = 'adikteev'; +export const ENDPOINT_URL = 'https://serve-adserver.adikteev.com/api/prebid/bid'; +export const ENDPOINT_URL_STAGING = 'https://serve-adserver-staging.adikteev.com/api/prebid/bid'; +export const USER_SYNC_IFRAME_URL = 'https://serve-adserver.adikteev.com/api/prebid/sync-iframe'; +export const USER_SYNC_IFRAME_URL_STAGING = 'https://serve-adserver-staging.adikteev.com/api/prebid/sync-iframe'; +export const USER_SYNC_IMAGE_URL = 'https://serve-adserver.adikteev.com/api/prebid/sync-image'; +export const USER_SYNC_IMAGE_URL_STAGING = 'https://serve-adserver-staging.adikteev.com/api/prebid/sync-image'; + +export let stagingEnvironmentSwitch = false; // Don't use it. Allow us to make tests on staging + +export function setstagingEnvironmentSwitch(value) { + stagingEnvironmentSwitch = value; +} + +function validateSizes(sizes) { + if (!utils.isArray(sizes) || typeof sizes[0] === 'undefined') { + return false; + } + return sizes.every(size => utils.isArray(size) && size.length === 2); +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: (bid) => { + setstagingEnvironmentSwitch(stagingEnvironmentSwitch || !!bid.params.stagingEnvironment); + return !!( + bid && + bid.params && + bid.params.bidFloorPrice && + bid.params.placementId && + bid.bidder === BIDDER_CODE && + validateSizes(bid.mediaTypes.banner.sizes) + ); + }, + + buildRequests: (validBidRequests, bidderRequest) => { + const payload = { + validBidRequests, + bidderRequest, + refererInfo: bidderRequest.refererInfo, + currency: config.getConfig('currency'), + userAgent: navigator.userAgent, + screen: { + width: window.screen.width, + height: window.screen.height + }, + language: navigator.language, + cookies: document.cookie.split(';'), + prebidUpdateVersion: '1.29.0', + }; + return { + method: 'POST', + url: stagingEnvironmentSwitch ? ENDPOINT_URL_STAGING : ENDPOINT_URL, + data: JSON.stringify(payload), + }; + }, + + interpretResponse: (serverResponse, bidRequests) => { + const returnedBids = []; + const validBidRequests = JSON.parse(bidRequests.data).validBidRequests; + serverResponse.body.forEach((value, index) => { + const overrides = { + requestId: validBidRequests[index].bidId, + }; + returnedBids.push(Object.assign({}, value, overrides)); + }); + return returnedBids; + }, + + getUserSyncs: (syncOptions, serverResponses) => { + const syncs = []; + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: stagingEnvironmentSwitch ? USER_SYNC_IFRAME_URL_STAGING : USER_SYNC_IFRAME_URL, + }); + } + if (syncOptions.pixelEnabled && serverResponses.length > 0) { + syncs.push({ + type: 'image', + url: stagingEnvironmentSwitch ? USER_SYNC_IMAGE_URL_STAGING : USER_SYNC_IMAGE_URL, + }); + } + return syncs; + }, +}; +registerBidder(spec); diff --git a/modules/adikteevBidAdapter.md b/modules/adikteevBidAdapter.md new file mode 100644 index 00000000000..d5008f61b03 --- /dev/null +++ b/modules/adikteevBidAdapter.md @@ -0,0 +1,35 @@ +# Overview + +``` +Module Name: Adikteev Bidder Adapter +Module Type: Bidder Adapter +Maintainer: adnetwork@adikteev.com +``` + +# Description + +Module that connects to Adikteev's demand sources + +# Test Parameters + +``` javascript + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[750, 200]], // a display size + } + }, + bids: [ + { + bidder: 'adikteev', + params: { + placementId: 12345, + bidFloorPrice: 0.1, + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/adikteevBidAdapter_spec.js b/test/spec/modules/adikteevBidAdapter_spec.js new file mode 100644 index 00000000000..243cbe2a9c5 --- /dev/null +++ b/test/spec/modules/adikteevBidAdapter_spec.js @@ -0,0 +1,235 @@ +import {expect} from 'chai'; +import { + ENDPOINT_URL, + ENDPOINT_URL_STAGING, + setstagingEnvironmentSwitch, + spec, + stagingEnvironmentSwitch, + USER_SYNC_IFRAME_URL, + USER_SYNC_IFRAME_URL_STAGING, + USER_SYNC_IMAGE_URL, + USER_SYNC_IMAGE_URL_STAGING, +} from 'modules/adikteevBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +import * as utils from '../../../src/utils'; + +describe('adikteevBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + it('exists and is a function', () => { + expect(setstagingEnvironmentSwitch).to.exist.and.to.be.a('function'); + }); + it('exists and is correctly set', () => { + expect(stagingEnvironmentSwitch).to.exist.and.to.equal(false); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + const validBid = { + bidder: 'adikteev', + params: { + placementId: 12345, + bidFloorPrice: 0.1, + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + }; + expect(spec.isBidRequestValid(validBid)).to.equal(true); + }); + + it('should mutate stagingEnvironmentSwitch when required params found', () => { + const withstagingEnvironmentSwitch = { + params: { + stagingEnvironment: true, + }, + }; + spec.isBidRequestValid(withstagingEnvironmentSwitch); + expect(stagingEnvironmentSwitch).to.equal(true); + setstagingEnvironmentSwitch(false); + }); + + it('should return false when required params are invalid', () => { + expect(spec.isBidRequestValid({ + bidder: '', // invalid bidder + params: { + placementId: 12345, + bidFloorPrice: 0.1, + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + })).to.equal(false); + expect(spec.isBidRequestValid({ + bidder: 'adikteev', + params: { + placementId: '', // invalid placementId + bidFloorPrice: 0.1, + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + })).to.equal(false); + expect(spec.isBidRequestValid({ + bidder: 'adikteev', + params: { + placementId: 12345, + bidFloorPrice: 0.1, + }, + mediaTypes: { + banner: { + sizes: [[750]] // invalid size + } + }, + })).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const validBidRequests = []; + const bidderRequest = {}; + const serverRequest = spec.buildRequests(validBidRequests, bidderRequest); + it('creates a request object with correct method, url and data', () => { + expect(serverRequest).to.exist.and.have.all.keys( + 'method', + 'url', + 'data', + ); + expect(serverRequest.method).to.equal('POST'); + expect(serverRequest.url).to.equal(ENDPOINT_URL); + + let requestData = JSON.parse(serverRequest.data); + expect(requestData).to.exist.and.have.all.keys( + 'validBidRequests', + 'bidderRequest', + 'userAgent', + 'screen', + 'language', + 'cookies', + // 'refererInfo', + // 'currency', + 'prebidUpdateVersion', + ); + expect(requestData.validBidRequests).to.deep.equal(validBidRequests); + expect(requestData.bidderRequest).to.deep.equal(bidderRequest); + expect(requestData.userAgent).to.deep.equal(navigator.userAgent); + expect(requestData.screen.width).to.deep.equal(window.screen.width); + expect(requestData.screen.height).to.deep.equal(window.screen.height); + expect(requestData.language).to.deep.equal(navigator.language); + expect(requestData.prebidUpdateVersion).to.deep.equal('1.29.0'); + }); + + describe('staging environment', () => { + setstagingEnvironmentSwitch(true); + const serverRequest = spec.buildRequests(validBidRequests, bidderRequest); + expect(serverRequest.url).to.equal(ENDPOINT_URL_STAGING); + setstagingEnvironmentSwitch(false); + }); + }); + + describe('interpretResponse', () => { + it('bid objects from response', () => { + const serverResponse = + { + body: [ + { + cpm: 1, + width: 300, + height: 250, + ad: '
', + ttl: 360, + creativeId: 123, + netRevenue: false, + currency: 'EUR', + } + ] + }; + const payload = { + validBidRequests: [{ + bidId: '2ef7bb021ac847' + }], + }; + const bidRequests = { + method: 'POST', + url: stagingEnvironmentSwitch ? ENDPOINT_URL_STAGING : ENDPOINT_URL, + data: JSON.stringify(payload), + }; + const bidResponses = spec.interpretResponse(serverResponse, bidRequests); + expect(bidResponses).to.be.an('array').that.is.not.empty; // yes, syntax is correct + expect(bidResponses[0]).to.have.all.keys( + 'requestId', + 'cpm', + 'width', + 'height', + 'ad', + 'ttl', + 'creativeId', + 'netRevenue', + 'currency', + ); + + expect(bidResponses[0].requestId).to.equal(payload.validBidRequests[0].bidId); + expect(bidResponses[0].cpm).to.equal(serverResponse.body[0].cpm); + expect(bidResponses[0].width).to.equal(serverResponse.body[0].width); + expect(bidResponses[0].height).to.equal(serverResponse.body[0].height); + expect(bidResponses[0].ad).to.equal(serverResponse.body[0].ad); + expect(bidResponses[0].ttl).to.equal(serverResponse.body[0].ttl); + expect(bidResponses[0].creativeId).to.equal(serverResponse.body[0].creativeId); + expect(bidResponses[0].netRevenue).to.equal(serverResponse.body[0].netRevenue); + expect(bidResponses[0].currency).to.equal(serverResponse.body[0].currency); + }); + }); + + describe('getUserSyncs', () => { + expect(spec.getUserSyncs({ + iframeEnabled: true + }, [{}])).to.deep.equal([{ + type: 'iframe', + url: USER_SYNC_IFRAME_URL + }]); + + expect(spec.getUserSyncs({ + pixelEnabled: true + }, [{}])).to.deep.equal([{ + type: 'image', + url: USER_SYNC_IMAGE_URL + }]); + + expect(spec.getUserSyncs({ + iframeEnabled: true, + pixelEnabled: true + }, [{}])).to.deep.equal([{ + type: 'iframe', + url: USER_SYNC_IFRAME_URL + }, { + type: 'image', + url: USER_SYNC_IMAGE_URL + }]); + + describe('staging environment', () => { + setstagingEnvironmentSwitch(true); + expect(spec.getUserSyncs({ + iframeEnabled: true, + pixelEnabled: true + }, [{}])).to.deep.equal([{ + type: 'iframe', + url: USER_SYNC_IFRAME_URL_STAGING + }, { + type: 'image', + url: USER_SYNC_IMAGE_URL_STAGING + }]); + setstagingEnvironmentSwitch(false); + }); + }); +}); From 9ddb20b689f65c4305de7129163a7d2308bfc868 Mon Sep 17 00:00:00 2001 From: jacekburys-quantcast <44467819+jacekburys-quantcast@users.noreply.github.com> Date: Tue, 30 Oct 2018 14:49:27 +0000 Subject: [PATCH 0798/1594] Quantcast adapter onTimeout (#3239) * onTimeout WIP * test for onTimeout * some renaming * cleanup * cleanup * trying to fix the test * using ajax instead of fetch --- modules/quantcastBidAdapter.js | 7 ++++++- test/spec/modules/quantcastBidAdapter_spec.js | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index e6f4d27bdbb..79128a834a4 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,4 +1,5 @@ import * as utils from 'src/utils'; +import { ajax } from 'src/ajax'; import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'quantcast'; @@ -69,7 +70,7 @@ export const spec = { }); }); - const gdprConsent = bidderRequest ? bidderRequest.gdprConsent : {}; + const gdprConsent = (bidderRequest && bidderRequest.gdprConsent) ? bidderRequest.gdprConsent : {}; // Request Data Format can be found at https://wiki.corp.qc/display/adinf/QCX const requestData = { @@ -157,6 +158,10 @@ export const spec = { }); return bidResponsesList; + }, + onTimeout(timeoutData) { + const url = `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb_notify?type=timeout`; + ajax(url, null, null); } }; diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index f5a7602c7ab..e64294e87e2 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,5 +1,6 @@ import * as utils from 'src/utils'; import { expect } from 'chai'; +import { stub, sandbox } from 'sinon'; import { QUANTCAST_DOMAIN, QUANTCAST_TEST_DOMAIN, @@ -12,6 +13,7 @@ import { } from '../../../modules/quantcastBidAdapter'; import { newBidder } from '../../../src/adapters/bidderFactory'; import { parse } from 'src/url'; +import * as ajax from 'src/ajax'; describe('Quantcast adapter', function () { const quantcastAdapter = newBidder(qcSpec); @@ -211,4 +213,19 @@ describe('Quantcast adapter', function () { expect(interpretedResponse.length).to.equal(0); }); }); + + describe('`onTimeout`', function() { + it('makes a request to the notify endpoint', function() { + const sinonSandbox = sandbox.create(); + const ajaxStub = sinonSandbox.stub(ajax, 'ajax').callsFake(function() {}); + const timeoutData = { + bidder: 'quantcast' + }; + qcSpec.onTimeout(timeoutData); + const expectedUrl = `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb_notify?type=timeout`; + ajaxStub.withArgs(expectedUrl, null, null).calledOnce.should.be.true; + ajaxStub.restore(); + sinonSandbox.restore(); + }); + }); }); From 903743a20fb721428851413491e75ff271261e3a Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 30 Oct 2018 09:30:48 -0600 Subject: [PATCH 0799/1594] Test cleanup (#3238) * stub pixel call in justpremium tests * properly stub geolocation services to prevent prompts * stub img creation as well to prevent call in justpremium --- modules/justpremiumBidAdapter.js | 16 ++-- .../modules/justpremiumBidAdapter_spec.js | 20 ++++- test/spec/modules/uolBidAdapter_spec.js | 75 +++++++++---------- 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 48b6805c0e1..c31f485020e 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -122,6 +122,16 @@ export const spec = { } +export let pixel = { + fire(url) { + let img = document.createElement('img') + img.src = url + img.id = 'jp-pixel-track' + img.style.cssText = 'display:none !important;' + document.body.appendChild(img) + } +}; + function track (data, payload, type) { let pubUrl = '' @@ -147,11 +157,7 @@ ru=${encodeURIComponent(pubUrl)}&tt=&siw=&sh=${payload.sh}&sw=${payload.sw}&wh=$ sd=&_c=&et=&aid=&said=&ei=&fc=&sp=&at=bidder&cid=&ist=&mg=&dl=&dlt=&ev=&vt=&zid=${payload.id}&dr=${duration}&di=&pr=& cw=&ch=&nt=&st=&jp=${encodeURIComponent(JSON.stringify(jp))}&ty=${type}` - let img = document.createElement('img') - img.src = pixelUrl - img.id = 'jp-pixel-track' - img.style.cssText = 'display:none !important;' - document.body.appendChild(img) + pixel.fire(pixelUrl); } function findBid (params, bids) { diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index 3c1048143d2..8167c29e5c2 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -1,7 +1,19 @@ import { expect } from 'chai' -import { spec } from 'modules/justpremiumBidAdapter' +import { spec, pixel } from 'modules/justpremiumBidAdapter' describe('justpremium adapter', function () { + let sandbox; + let pixelStub; + + beforeEach(function() { + sandbox = sinon.sandbox.create(); + pixelStub = sandbox.stub(pixel, 'fire'); + }); + + afterEach(function() { + sandbox.restore(); + }); + let adUnits = [ { adUnitCode: 'div-gpt-ad-1471513102552-1', @@ -132,7 +144,7 @@ describe('justpremium adapter', function () { }) describe('onTimeout', function () { - it('onTimeout', (done) => { + it('onTimeout', function(done) { spec.onTimeout([{ 'bidId': '25cd3ec3fd6ed7', 'bidder': 'justpremium', @@ -153,7 +165,9 @@ describe('justpremium adapter', function () { 'zone': 21521 }], 'timeout': 1 - }]) + }]); + + expect(pixelStub.calledOnce).to.equal(true); done() }) diff --git a/test/spec/modules/uolBidAdapter_spec.js b/test/spec/modules/uolBidAdapter_spec.js index 1733afc91f9..e9341772e7d 100644 --- a/test/spec/modules/uolBidAdapter_spec.js +++ b/test/spec/modules/uolBidAdapter_spec.js @@ -1,11 +1,20 @@ import { expect } from 'chai'; import { spec } from 'modules/uolBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = 'https://prebid.adilligo.com/v1/prebid.json'; describe('UOL Bid Adapter', function () { - const adapter = newBidder(spec); + let sandbox; + let queryStub; + let getCurrentPositionStub; + + beforeEach(function() { + sandbox = sinon.sandbox.create(); + }); + + afterEach(function() { + sandbox.restore(); + }); describe('isBidRequestValid', function () { let bid = { @@ -88,31 +97,6 @@ describe('UOL Bid Adapter', function () { }); describe('buildRequests', function () { - let queryPermission; - let cleanup = function() { - navigator.permissions.query = queryPermission; - }; - let grantTriangulation = function() { - queryPermission = navigator.permissions.query; - navigator.permissions.query = function(data) { - return new Promise((resolve, reject) => { - resolve({state: 'granted'}); - }); - } - }; - let denyTriangulation = function() { - queryPermission = navigator.permissions.query; - navigator.permissions.query = function(data) { - return new Promise((resolve, reject) => { - resolve({state: 'prompt'}); - }); - } - }; - let removeQuerySupport = function() { - queryPermission = navigator.permissions.query; - navigator.permissions.query = undefined; - } - let bidRequests = [ { 'bidder': 'uol', @@ -173,31 +157,42 @@ describe('UOL Bid Adapter', function () { describe('buildRequest geolocation param', function () { // shall only be tested if browser engine supports geolocation and permissions API. let geolocation = { lat: 4, long: 3, timestamp: 123121451 }; - it('should contain user coordinates if (i) DNT is off; (ii) browser supports implementation; (iii) localStorage contains geolocation history', function () { + beforeEach(function() { + getCurrentPositionStub = sandbox.stub(navigator.geolocation, 'getCurrentPosition'); + queryStub = sandbox.stub(navigator.permissions, 'query'); + }); + + it('should not contain user coordinates if browser doesnt support permission query', function () { localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); - grantTriangulation(); + navigator.permissions.query = undefined; const requestObject = spec.buildRequests(bidRequests, bidderRequest); const payload = JSON.parse(requestObject.data); - expect(payload.geolocation).to.exist.and.not.be.empty; - cleanup(); + expect(payload.geolocation).to.not.exist; }) - it('should not contain user coordinates if localStorage is empty', function () { - localStorage.removeItem('uolLocationTracker'); - denyTriangulation(); + it('should contain user coordinates if (i) DNT is off; (ii) browser supports implementation; (iii) localStorage contains geolocation history', function (done) { + localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); + queryStub.callsFake(function() { + return new Promise((resolve, reject) => { + resolve({state: 'granted'}); + }); + }); + getCurrentPositionStub.callsFake(() => done()); const requestObject = spec.buildRequests(bidRequests, bidderRequest); const payload = JSON.parse(requestObject.data); - expect(payload.geolocation).to.not.exist; - cleanup(); + expect(payload.geolocation).to.exist.and.not.be.empty; }) - it('should not contain user coordinates if browser doesnt support permission query', function () { - localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); - removeQuerySupport(); + it('should not contain user coordinates if localStorage is empty', function () { + localStorage.removeItem('uolLocationTracker'); + queryStub.callsFake(function() { + return new Promise((resolve, reject) => { + resolve({state: 'prompt'}); + }); + }); const requestObject = spec.buildRequests(bidRequests, bidderRequest); const payload = JSON.parse(requestObject.data); expect(payload.geolocation).to.not.exist; - cleanup(); }) }) } From 0de2478f8f94ebfa5fcc802673b65b4d33989ba5 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 30 Oct 2018 11:32:27 -0400 Subject: [PATCH 0800/1594] Appnexus adapter: Added dealPriority and dealCode to bidResponse (#3201) * Added dealPriority and dealCode to appnexus adapter * update failed test * added namespace and did deep merge * keep all properties together --- modules/appnexusBidAdapter.js | 4 +++- test/spec/modules/appnexusBidAdapter_spec.js | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index aaec207dc1e..19aa5e7cf73 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -233,7 +233,9 @@ function newBid(serverBid, rtbBid, bidderRequest) { netRevenue: true, ttl: 300, appnexus: { - buyerMemberId: rtbBid.buyer_member_id + buyerMemberId: rtbBid.buyer_member_id, + dealPriority: rtbBid.deal_priority, + dealCode: rtbBid.deal_code } }; diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 9be87ac8628..5e41c1c9544 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -561,5 +561,15 @@ describe('AppNexusAdapter', function () { bidderRequest.bids[0].renderer.options ); }); + + it('should add deal_priority and deal_code', function() { + let responseWithDeal = deepClone(response); + responseWithDeal.tags[0].ads[0].deal_priority = 'high'; + responseWithDeal.tags[0].ads[0].deal_code = '123'; + + let bidderRequest; + let result = spec.interpretResponse({ body: responseWithDeal }, {bidderRequest}); + expect(Object.keys(result[0].appnexus)).to.include.members(['buyerMemberId', 'dealPriority', 'dealCode']); + }); }); }); From 5481af902483506628302dbf0659bf1ccd7f1f21 Mon Sep 17 00:00:00 2001 From: HolzAndrew Date: Tue, 30 Oct 2018 13:32:25 -0400 Subject: [PATCH 0801/1594] use unit id being sent instead of hard coded auid (#3236) * use unit id being sent instead of hard coded auid * make multiple requests * removes commented out code. adds aus param back --- modules/openxoutstreamBidAdapter.js | 47 +++++++--------- modules/openxoutstreamBidAdapter.md | 3 +- .../modules/openxoutstreamBidAdapter_spec.js | 54 +++++++++---------- 3 files changed, 48 insertions(+), 56 deletions(-) diff --git a/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js index dde101f25d5..aee260e0a11 100644 --- a/modules/openxoutstreamBidAdapter.js +++ b/modules/openxoutstreamBidAdapter.js @@ -20,28 +20,21 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function(bidRequest) { - if (bidRequest.params.delDomain) { - return !!bidRequest.params.unit || utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes.length') > 0; - } - return false; + return !!(bidRequest.params.delDomain && bidRequest.params.unit) }, buildRequests: function(bidRequests, bidderRequest) { if (bidRequests.length === 0) { return []; } let requests = []; - requests.push(buildOXBannerRequest(bidRequests, bidderRequest)); + bidRequests.forEach(bid => { + requests.push(buildOXBannerRequest(bid, bidderRequest)); + }) return requests; }, - interpretResponse: function(serverResponse, serverRequest) { - return handleVastResponse(serverResponse, serverRequest.payload) + interpretResponse: function(bid, serverResponse) { + return handleVastResponse(bid, serverResponse.payload) }, - - transformBidParams: function(params, isOpenRtb) { - return utils.convertTypes({ - 'unit': 'string', - }, params); - } }; function getViewportDimensions(isIfr) { @@ -70,7 +63,7 @@ function getViewportDimensions(isIfr) { return `${width}x${height}`; } -function buildCommonQueryParamsFromBids(bids, bidderRequest) { +function buildCommonQueryParamsFromBids(bid, bidderRequest) { const isInIframe = utils.inIframe(); let defaultParams; defaultParams = { @@ -82,13 +75,13 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { tz: new Date().getTimezoneOffset(), tws: getViewportDimensions(isInIframe), be: 1, - bc: bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, - auid: '540141567', - dddid: utils._map(bids, bid => bid.transactionId).join(','), + bc: bid.params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, + auid: bid.params.unit, + dddid: bid.transactionId, openrtb: '%7B%22mimes%22%3A%5B%22video%2Fmp4%22%5D%7D', nocache: new Date().getTime(), - vht: bids[0].params.height || bids[0].sizes[0][1], - vwd: bids[0].params.width || bids[0].sizes[0][0] + vht: bid.params.height || bid.sizes[0][1], + vwd: bid.params.width || bid.sizes[0][0] }; if (utils.deepAccess(bidderRequest, 'gdprConsent')) { @@ -110,24 +103,24 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { return defaultParams; } -function buildOXBannerRequest(bids, bidderRequest) { - let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); - queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); +function buildOXBannerRequest(bid, bidderRequest) { + let queryParams = buildCommonQueryParamsFromBids(bid, bidderRequest); + queryParams.aus = utils.parseSizesInput(bid.sizes).join(','); - if (bids.some(bid => bid.params.doNotTrack)) { + if (bid.params.doNotTrack) { queryParams.ns = 1; } - if (bids.some(bid => bid.params.coppa)) { + if (bid.params.coppa) { queryParams.tfcd = 1; } - let url = `https://${bids[0].params.delDomain}/v/1.0/avjp` + let url = `https://${bid.params.delDomain}/v/1.0/avjp` return { method: 'GET', url: url, data: queryParams, - payload: {'bids': bids} + payload: {'bid': bid} }; } @@ -146,7 +139,7 @@ function handleVastResponse(response, serverResponse) { const ymAdsScript = ''; let bidResponse = {}; - bidResponse.requestId = serverResponse.bids[0].bidId; + bidResponse.requestId = serverResponse.bid.bidId; bidResponse.bidderCode = BIDDER_CODE; bidResponse.netRevenue = NET_REVENUE; bidResponse.currency = CURRENCY; diff --git a/modules/openxoutstreamBidAdapter.md b/modules/openxoutstreamBidAdapter.md index a77b4560f97..16d66b92409 100644 --- a/modules/openxoutstreamBidAdapter.md +++ b/modules/openxoutstreamBidAdapter.md @@ -24,9 +24,8 @@ var adUnits = [ { bidder: 'openxoutstream', params: { - unit: '53943996499', + unit: '540141567', delDomain: 'se-demo-d.openx.net', - publisher_page_url: 'yieldmo.com', width: '300', height: '250', } diff --git a/test/spec/modules/openxoutstreamBidAdapter_spec.js b/test/spec/modules/openxoutstreamBidAdapter_spec.js index 59d56bee74b..9b189856e1a 100644 --- a/test/spec/modules/openxoutstreamBidAdapter_spec.js +++ b/test/spec/modules/openxoutstreamBidAdapter_spec.js @@ -44,28 +44,23 @@ describe('OpenXOutstreamAdapter', function () { bannerBid.params = {delDomain: 'test-delivery-domain'} }); - it('should return false when there is no ad unit id and size', function () { + it('should return false if there is no adunit id and sizes are defined', function () { + bannerBid.mediaTypes.banner.sizes = [720, 90]; expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); - it('should return true if there is an adunit id ', function () { + it('should return true if there is delivery domain and unit', function () { bannerBid.params.unit = '12345678'; expect(spec.isBidRequestValid(bannerBid)).to.equal(true); }); - - it('should return true if there is no adunit id and sizes are defined', function () { - bannerBid.mediaTypes.banner.sizes = [720, 90]; - expect(spec.isBidRequestValid(bannerBid)).to.equal(true); - }); - - it('should return false if no sizes are defined ', function () { + it('should return false if there is unit but no delivery domain', function () { + bannerBid.params = {unit: '12345678'}; expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); - - it('should return false if sizes empty ', function () { - bannerBid.mediaTypes.banner.sizes = []; + it('shoud return false if there is no delivery domain and no unit', function () { + bannerBid.params = {}; expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); + }) }); }); }); @@ -92,40 +87,45 @@ describe('OpenXOutstreamAdapter', function () { expect(request[0].method).to.equal('GET'); }); - it('should send ad unit ids when any are defined', function () { + it('should send ad unit ids, height, and width when any are defined', function () { const bidRequestsWithUnitIds = [{ 'bidder': BIDDER, 'params': { + 'unit': '540141567', + 'height': '300', + 'width': '250', 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', - 'sizes': [300, 250], + sizes: [300, 250], mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] + sizes: [[728, 90]] } }, - 'bidId': 'test-bid-id-1', - 'bidderRequestId': 'test-bid-request-1', - 'auctionId': 'test-auction-1' + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' }, { 'bidder': BIDDER, 'params': { - 'unit': '540141567', 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', + 'sizes': [300, 250], mediaTypes: { banner: { - sizes: [[728, 90]] + sizes: [[300, 250], [300, 600]] } }, - 'bidId': 'test-bid-id-2', - 'bidderRequestId': 'test-bid-request-2', - 'auctionId': 'test-auction-2' + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' }]; const request = spec.buildRequests(bidRequestsWithUnitIds); - expect(request[0].data.auid).to.equal(`${bidRequestsWithUnitIds[1].params.unit}`); + expect(request[0].data.auid).to.equal(`${bidRequestsWithUnitIds[0].params.unit}`); + expect(request[0].data.vht).to.equal(`${bidRequestsWithUnitIds[0].params.height}`); + expect(request[0].data.vwd).to.equal(`${bidRequestsWithUnitIds[0].params.width}`); }); describe('interpretResponse', function () { @@ -147,9 +147,9 @@ describe('OpenXOutstreamAdapter', function () { }; serverRequest = { payload: { - bids: [{ + bid: { bidId: '2d36ac90d654af', - }], + }, } }; }); From 6649ef96ec224cb861e23a2fe8891a9073fd49e8 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 30 Oct 2018 14:34:12 -0400 Subject: [PATCH 0802/1594] Prebid 1.30.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a53085fa062..542c14f3525 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.30.0-pre", + "version": "1.30.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From ab703accc628d2dcf888125c818bf925ffa77ab2 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 30 Oct 2018 14:50:06 -0400 Subject: [PATCH 0803/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 542c14f3525..288d970f842 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.30.0", + "version": "1.31.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 2c5685cb271c364478113546cef471c11499ec06 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 31 Oct 2018 07:52:28 -0600 Subject: [PATCH 0804/1594] fix deal targeting for cpm 0 (#3233) --- src/targeting.js | 13 +---- test/spec/unit/core/targeting_spec.js | 78 ++++++++++++++++----------- 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index dcd59f362c6..30407994b8e 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -35,20 +35,11 @@ export function getHighestCpmBidsFromBidPool(bidsReceived, highestCpmCallback) { // filter top bid for each bucket by bidder Object.keys(buckets).forEach(bucketKey => { let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); - Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(highestCpmCallback, getEmptyBid()))); + Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(highestCpmCallback))); }); return bids; } -function getEmptyBid(adUnitCode) { - return { - adUnitCode: adUnitCode, - cpm: 0, - adserverTargeting: {}, - timeToRespond: 0 - }; -} - /** * @typedef {Object.} targeting * @property {string} targeting_key @@ -222,7 +213,7 @@ export function newTargeting(auctionManager) { .filter(uniques) .map(adUnitCode => bidsReceived .filter(bid => bid.adUnitCode === adUnitCode ? bid : null) - .reduce(getHighestCpm, getEmptyBid(adUnitCode))); + .reduce(getHighestCpm)); }; /** diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 9910645be09..427ceeca74c 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -99,42 +99,68 @@ const bid3 = { }; describe('targeting tests', function () { + let sandbox; + let enableSendAllBids = false; + + beforeEach(function() { + sandbox = sinon.sandbox.create(); + + let origGetConfig = config.getConfig; + sandbox.stub(config, 'getConfig').callsFake(function (key) { + if (key === 'enableSendAllBids') { + return enableSendAllBids; + } + return origGetConfig.apply(config, arguments); + }); + }); + + afterEach(function () { + sandbox.restore(); + }); + describe('getAllTargeting', function () { let amBidsReceivedStub; let amGetAdUnitsStub; let bidExpiryStub; + let bidsReceived; beforeEach(function () { - $$PREBID_GLOBAL$$._sendAllBids = false; - amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived').callsFake(function() { - return [bid1, bid2, bid3]; + bidsReceived = [bid1, bid2, bid3]; + + amBidsReceivedStub = sandbox.stub(auctionManager, 'getBidsReceived').callsFake(function() { + return bidsReceived; }); - amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { + amGetAdUnitsStub = sandbox.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; }); - bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); - }); - - afterEach(function () { - auctionManager.getBidsReceived.restore(); - auctionManager.getAdUnitCodes.restore(); - targetingModule.isBidNotExpired.restore(); + bidExpiryStub = sandbox.stub(targetingModule, 'isBidNotExpired').returns(true); }); describe('when hb_deal is present in bid.adserverTargeting', function () { + let bid4; + + beforeEach(function() { + bid4 = utils.deepClone(bid1); + bid4.adserverTargeting['hb_bidder'] = bid4.bidder = bid4.bidderCode = 'appnexus'; + bid4.cpm = 0; + enableSendAllBids = true; + + bidsReceived.push(bid4); + }); + it('returns targeting with both hb_deal and hb_deal_{bidder_code}', function () { const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); // We should add both keys rather than one or the other - expect(targeting['/123456/header-bid-tag-0']).to.contain.keys('hb_deal', `hb_deal_${bid1.bidderCode}`); + expect(targeting['/123456/header-bid-tag-0']).to.contain.keys('hb_deal', `hb_deal_${bid1.bidderCode}`, `hb_deal_${bid4.bidderCode}`); // We should assign both keys the same value expect(targeting['/123456/header-bid-tag-0']['hb_deal']).to.deep.equal(targeting['/123456/header-bid-tag-0'][`hb_deal_${bid1.bidderCode}`]); }); }); - it('selects the top bid when _sendAllBids true', function () { - config.setConfig({ enableSendAllBids: true }); + it('selects the top bid when enableSendAllBids true', function () { + enableSendAllBids = true; let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); // we should only get the targeting data for the one requested adunit @@ -155,14 +181,13 @@ describe('targeting tests', function () { let bidExpiryStub; beforeEach(function () { - $$PREBID_GLOBAL$$._sendAllBids = false; - amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived').callsFake(function() { + amBidsReceivedStub = sandbox.stub(auctionManager, 'getBidsReceived').callsFake(function() { return []; }); - amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { + amGetAdUnitsStub = sandbox.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; }); - bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); + bidExpiryStub = sandbox.stub(targetingModule, 'isBidNotExpired').returns(true); }); afterEach(function () { @@ -184,13 +209,8 @@ describe('targeting tests', function () { let bidExpiryStub; let auctionManagerStub; beforeEach(function () { - bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); - auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); - }); - - afterEach(function () { - bidExpiryStub.restore(); - auctionManagerStub.restore(); + bidExpiryStub = sandbox.stub(targetingModule, 'isBidNotExpired').returns(true); + auctionManagerStub = sandbox.stub(auctionManager, 'getBidsReceived'); }); it('should use bids from pool to get Winning Bid', function () { @@ -248,14 +268,10 @@ describe('targeting tests', function () { let auctionManagerStub; let timestampStub; beforeEach(function () { - auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); - timestampStub = sinon.stub(utils, 'timestamp'); + auctionManagerStub = sandbox.stub(auctionManager, 'getBidsReceived'); + timestampStub = sandbox.stub(utils, 'timestamp'); }); - afterEach(function () { - auctionManagerStub.restore(); - timestampStub.restore(); - }); it('should not include expired bids in the auction', function () { timestampStub.returns(200000); // Pool is having 4 bids from 2 auctions. All the bids are expired and only bid #3 is passing the bidExpiry check. From d25f57187b8eeae25a7aa5f3a26ffa76ea4e865b Mon Sep 17 00:00:00 2001 From: kusapan Date: Thu, 1 Nov 2018 23:23:40 +0900 Subject: [PATCH 0805/1594] YIELDONE adapter - support Video (#3227) * added UserSync * added UserSync Unit Test * support for multi sizes * register the adapter as supporting video * supporting video * change requestId acquisition method * fix the parameter name of dealID * update test parameters * support instream video * add test for bidRequest * add test for interpretResponse * add test params * add note to documentaion * clarifying the multi-format support message --- modules/yieldoneBidAdapter.js | 36 ++++-- modules/yieldoneBidAdapter.md | 50 ++++++-- test/spec/modules/yieldoneBidAdapter_spec.js | 117 ++++++++++++++----- 3 files changed, 154 insertions(+), 49 deletions(-) diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index cdcab0c705a..5843ce9d339 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from 'src/utils'; import {config} from 'src/config'; import {registerBidder} from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; const BIDDER_CODE = 'yieldone'; const ENDPOINT_URL = '//y.one.impact-ad.jp/h_bid'; @@ -9,15 +10,13 @@ const USER_SYNC_URL = '//y.one.impact-ad.jp/push_sync'; export const spec = { code: BIDDER_CODE, aliases: ['y1'], + supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bid) { return !!(bid.params.placementId); }, buildRequests: function(validBidRequests) { return validBidRequests.map(bidRequest => { const params = bidRequest.params; - const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; - const width = sizes.split('x')[0]; - const height = sizes.split('x')[1]; const placementId = params.placementId; const cb = Math.floor(Math.random() * 99999999999); const referrer = encodeURIComponent(utils.getTopWindowUrl()); @@ -25,13 +24,24 @@ export const spec = { const payload = { v: 'hb1', p: placementId, - w: width, - h: height, cb: cb, r: referrer, uid: bidId, t: 'i' }; + + const videoMediaType = utils.deepAccess(bidRequest, 'mediaTypes.video'); + 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]; + } else 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(','); + } + return { method: 'GET', url: ENDPOINT_URL, @@ -47,12 +57,12 @@ export const spec = { const height = response.height || 0; const cpm = response.cpm * 1000 || 0; if (width !== 0 && height !== 0 && cpm !== 0 && crid !== 0) { - const dealId = response.dealid || ''; + const dealId = response.dealId || ''; const currency = response.currency || 'JPY'; const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; const referrer = utils.getTopWindowUrl(); const bidResponse = { - requestId: bidRequest.data.uid, + requestId: response.uid, cpm: cpm, width: response.width, height: response.height, @@ -61,9 +71,17 @@ export const spec = { currency: currency, netRevenue: netRevenue, ttl: config.getConfig('_bidderTimeout'), - referrer: referrer, - ad: response.adTag + referrer: referrer }; + + if (response.adTag) { + bidResponse.mediaType = BANNER; + bidResponse.ad = response.adTag; + } else if (response.adm) { + bidResponse.mediaType = VIDEO; + bidResponse.vastXml = response.adm; + } + bidResponses.push(bidResponse); } return bidResponses; diff --git a/modules/yieldoneBidAdapter.md b/modules/yieldoneBidAdapter.md index b154a2ee781..1414d4e464f 100644 --- a/modules/yieldoneBidAdapter.md +++ b/modules/yieldoneBidAdapter.md @@ -10,20 +10,46 @@ Maintainer: y1dev@platform-one.co.jp Connect to YIELDONE for bids. -THE YIELDONE adapter requires setup and approval from the YIELDONE team. Please reach out to your account team or y1s@platform-one.co.jp for more information. +THE YIELDONE adapter requires setup and approval from the YIELDONE team. +Please reach out to your account team or y1s@platform-one.co.jp for more information. + +Note: THE YIELDONE adapter do not support "multi-format" scenario... if both +banner and video are specified as mediatypes, YIELDONE will treat it as a video unit. # Test Parameters -``` - var adUnits = [{ - code: 'banner-ad-div', - sizes: [[300, 250]], - bids: [{ - bidder: 'yieldone', - params: { - placementId: '44082' - } - }] - }]; +```javascript +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [336, 280]] + } + }, + bids: [{ + bidder: 'yieldone', + params: { + placementId: '36891' + } + }] + }, + // Video adUnit + { + code: 'video-div', + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'outstream' + }, + }, + bids: [{ + bidder: 'yieldone', + params: { + placementId: '41993' + } + }] + } ``` ### Configuration diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js index b717ef52709..19756b86bc1 100644 --- a/test/spec/modules/yieldoneBidAdapter_spec.js +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -3,6 +3,7 @@ import { spec } from 'modules/yieldoneBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = '//y.one.impact-ad.jp/h_bid'; +const USER_SYNC_URL = '//y.one.impact-ad.jp/push_sync'; describe('yieldoneBidAdapter', function() { const adapter = newBidder(spec); @@ -11,12 +12,10 @@ describe('yieldoneBidAdapter', function() { let bid = { 'bidder': 'yieldone', 'params': { - placementId: '44082' + placementId: '36891' }, 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250] - ], + 'sizes': [[300, 250], [336, 280]], 'bidId': '23beaa6af6cdde', 'bidderRequestId': '19c0c1efdf37e7', 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', @@ -43,12 +42,10 @@ describe('yieldoneBidAdapter', function() { { 'bidder': 'yieldone', 'params': { - placementId: '44082' + placementId: '36891' }, 'adUnitCode': 'adunit-code1', - 'sizes': [ - [300, 250] - ], + 'sizes': [[300, 250], [336, 280]], 'bidId': '23beaa6af6cdde', 'bidderRequestId': '19c0c1efdf37e7', 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', @@ -56,12 +53,10 @@ describe('yieldoneBidAdapter', function() { { 'bidder': 'yieldone', 'params': { - placementId: '44337' + placementId: '47919' }, 'adUnitCode': 'adunit-code2', - 'sizes': [ - [300, 250] - ], + 'sizes': [[300, 250]], 'bidId': '382091349b149f"', 'bidderRequestId': '"1f9c98192de251"', 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', @@ -79,18 +74,31 @@ describe('yieldoneBidAdapter', function() { expect(request[0].url).to.equal(ENDPOINT); expect(request[1].url).to.equal(ENDPOINT); }); + + 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'); + }); + + 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]); + expect(request[0].data.w).to.equal('300'); + expect(request[0].data.h).to.equal('250'); + }); }); describe('interpretResponse', function () { - let bidRequest = [ + let bidRequestBanner = [ { 'method': 'GET', 'url': '//y.one.impact-ad.jp/h_bid', 'data': { 'v': 'hb1', - 'p': '44082', - 'w': '300', - 'h': '250', + 'p': '36891', + 'sz': '300x250,336x280', 'cb': 12892917383, 'r': 'http%3A%2F%2Flocalhost%3A9876%2F%3Fid%3D74552836', 'uid': '23beaa6af6cdde', @@ -99,34 +107,89 @@ describe('yieldoneBidAdapter', function() { } ]; - let serverResponse = { + let serverResponseBanner = { body: { 'adTag': '', + 'uid': '23beaa6af6cdde', + 'height': 250, + 'width': 300, 'cpm': 0.0536616, 'crid': '2494768', + 'currency': 'JPY', 'statusMessage': 'Bid available', - 'uid': '23beaa6af6cdde', - 'width': 300, - 'height': 250 + 'dealId': 'P1-FIX-7800-DSP-MON' } }; - it('should get the correct bid response', function () { + it('should get the correct bid response for banner', function () { let expectedResponse = [{ 'requestId': '23beaa6af6cdde', 'cpm': 53.6616, 'width': 300, 'height': 250, 'creativeId': '2494768', - 'dealId': '', + 'dealId': 'P1-FIX-7800-DSP-MON', 'currency': 'JPY', 'netRevenue': true, 'ttl': 3000, 'referrer': '', + 'mediaType': 'banner', 'ad': '' }]; - let result = spec.interpretResponse(serverResponse, bidRequest[0]); - expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); + let result = spec.interpretResponse(serverResponseBanner, bidRequestBanner[0]); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + expect(result[0].mediaType).to.equal(expectedResponse[0].mediaType); + }); + + let serverResponseVideo = { + body: { + 'uid': '23beaa6af6cdde', + 'height': 360, + 'width': 640, + 'cpm': 0.0536616, + 'dealId': 'P1-FIX-766-DSP-MON', + 'crid': '2494768', + 'currency': 'JPY', + 'statusMessage': 'Bid available', + 'adm': '' + } + }; + + let bidRequestVideo = [ + { + 'method': 'GET', + 'url': '//y.one.impact-ad.jp/h_bid', + 'data': { + 'v': 'hb1', + 'p': '41993', + 'w': '640', + 'h': '360', + 'cb': 12892917383, + 'r': 'http%3A%2F%2Flocalhost%3A9876%2F%3Fid%3D74552836', + 'uid': '23beaa6af6cdde', + 't': 'i' + } + } + ]; + + it('should get the correct bid response for video', function () { + let expectedResponse = [{ + 'requestId': '23beaa6af6cdde', + 'cpm': 53.6616, + 'width': 640, + 'height': 360, + 'creativeId': '2494768', + 'dealId': 'P1-FIX-7800-DSP-MON', + 'currency': 'JPY', + 'netRevenue': true, + 'ttl': 3000, + 'referrer': '', + 'mediaType': 'video', + 'vastXml': '' + }]; + let result = spec.interpretResponse(serverResponseVideo, bidRequestVideo[0]); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + expect(result[0].mediaType).to.equal(expectedResponse[0].mediaType); }); it('handles empty bid response', function () { @@ -140,14 +203,12 @@ describe('yieldoneBidAdapter', function() { 'cpm': 0 } }; - let result = spec.interpretResponse(response, bidRequest[0]); + let result = spec.interpretResponse(response, bidRequestBanner[0]); expect(result.length).to.equal(0); }); }); describe('getUserSyncs', function () { - const userSyncUrl = '//y.one.impact-ad.jp/push_sync'; - it('handles empty sync options', function () { expect(spec.getUserSyncs({})).to.be.empty; }); @@ -156,7 +217,7 @@ describe('yieldoneBidAdapter', function() { expect(spec.getUserSyncs({ 'iframeEnabled': true })).to.deep.equal([{ - type: 'iframe', url: userSyncUrl + type: 'iframe', url: USER_SYNC_URL }]); }); }); From d854db39c0d6b70f4369a634089129b6baecdf17 Mon Sep 17 00:00:00 2001 From: Kamoris Date: Thu, 1 Nov 2018 15:29:51 +0100 Subject: [PATCH 0806/1594] rtbhouseBidAdapter changes (#3241) * Add transactionId support * Change site getting method * Add bidfloor param --- modules/rtbhouseBidAdapter.js | 21 +++++-- modules/rtbhouseBidAdapter.md | 6 +- test/spec/modules/rtbhouseBidAdapter_spec.js | 63 +++++++++++++++----- 3 files changed, 69 insertions(+), 21 deletions(-) diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js index e4a30782dbe..0be3887637d 100644 --- a/modules/rtbhouseBidAdapter.js +++ b/modules/rtbhouseBidAdapter.js @@ -43,9 +43,12 @@ export const spec = { const request = { id: validBidRequests[0].auctionId, imp: validBidRequests.map(slot => mapImpression(slot)), - site: mapSite(validBidRequests), + site: mapSite(validBidRequests, bidderRequest), cur: DEFAULT_CURRENCY_ARR, - test: validBidRequests[0].params.test || 0 + test: validBidRequests[0].params.test || 0, + source: { + tid: validBidRequests[0].transactionId + } }; if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { const consentStr = (bidderRequest.gdprConsent.consentString) @@ -89,12 +92,19 @@ registerBidder(spec); * @returns {object} Imp by OpenRTB 2.5 §3.2.4 */ function mapImpression(slot) { - return { + const imp = { id: slot.bidId, banner: mapBanner(slot), native: mapNative(slot), tagid: slot.adUnitCode.toString() }; + + const bidfloor = parseFloat(slot.params.bidfloor); + if (bidfloor) { + imp.bidfloor = bidfloor + } + + return imp; } /** @@ -118,9 +128,10 @@ function mapBanner(slot) { /** * @param {object} slot Ad Unit Params by Prebid + * @param {object} bidderRequest by Prebid * @returns {object} Site by OpenRTB 2.5 §3.2.13 */ -function mapSite(slot) { +function mapSite(slot, bidderRequest) { const pubId = slot && slot.length > 0 ? slot[0].params.publisherId : 'unknown'; @@ -128,7 +139,7 @@ function mapSite(slot) { publisher: { id: pubId.toString(), }, - page: utils.getTopWindowUrl(), + page: bidderRequest.refererInfo.referer, name: utils.getOrigin() } } diff --git a/modules/rtbhouseBidAdapter.md b/modules/rtbhouseBidAdapter.md index a2d7e2aedda..c847e688941 100644 --- a/modules/rtbhouseBidAdapter.md +++ b/modules/rtbhouseBidAdapter.md @@ -7,7 +7,7 @@ Maintainer: prebid@rtbhouse.com # Description Connects to RTB House unique demand. -Banner formats are supported. +Banner and native formats are supported. Unique publisherId is required. Please reach out to pmp@rtbhouse.com to receive your own @@ -23,7 +23,8 @@ Please reach out to pmp@rtbhouse.com to receive your own bidder: "rtbhouse", params: { region: 'prebid-eu', - publisherId: 'PREBID_TEST_ID' + publisherId: 'PREBID_TEST_ID', + bidfloor: 0.01 // optional } } ] @@ -50,6 +51,7 @@ Please reach out to pmp@rtbhouse.com to receive your own params: { region: 'prebid-eu', publisherId: 'PREBID_TEST_ID' + bidfloor: 0.01 // optional } } ] diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index 3c1d81a86c9..bd341465ab9 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -52,17 +52,26 @@ describe('RTBHouseAdapter', () => { 'sizes': [[300, 250], [300, 600]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475' + 'auctionId': '1d1a030790a475', + 'transactionId': 'example-transaction-id', } ]; + const bidderRequest = { + 'refererInfo': { + 'numIframes': 0, + 'reachedTop': true, + 'referer': 'http://example.com', + 'stack': ['http://example.com'] + } + }; it('should build test param into the request', () => { - let builtTestRequest = spec.buildRequests(bidRequests).data; + let builtTestRequest = spec.buildRequests(bidRequests, bidderRequest).data; expect(JSON.parse(builtTestRequest).test).to.equal(1); }); it('should build valid OpenRTB banner object', () => { - const request = JSON.parse(spec.buildRequests((bidRequests)).data); + const request = JSON.parse(spec.buildRequests(bidRequests, bidderRequest).data); const imp = request.imp[0]; expect(imp.banner).to.deep.equal({ w: 300, @@ -80,7 +89,7 @@ describe('RTBHouseAdapter', () => { it('sends bid request to ENDPOINT via POST', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; - const request = spec.buildRequests(bidRequest); + const request = spec.buildRequests(bidRequest, bidderRequest); expect(request.url).to.equal('https://prebid-eu.creativecdn.com/bidder/prebid/bids'); expect(request.method).to.equal('POST'); }); @@ -88,7 +97,7 @@ describe('RTBHouseAdapter', () => { it('should not populate GDPR if for non-EEA users', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; - const request = spec.buildRequests(bidRequest); + const request = spec.buildRequests(bidRequest, bidderRequest); let data = JSON.parse(request.data); expect(data).to.not.have.property('regs'); expect(data).to.not.have.property('user'); @@ -97,12 +106,15 @@ describe('RTBHouseAdapter', () => { it('should populate GDPR and consent string if available for EEA users', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; - const request = spec.buildRequests(bidRequest, { - gdprConsent: { - gdprApplies: true, - consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==' - } - }); + const request = spec.buildRequests( + bidRequest, + Object.assign({}, bidderRequest, { + gdprConsent: { + gdprApplies: true, + consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==' + } + }) + ); let data = JSON.parse(request.data); expect(data.regs.ext.gdpr).to.equal(1); expect(data.user.ext.consent).to.equal('BOJ8RZsOJ8RZsABAB8AAAAAZ-A'); @@ -111,7 +123,14 @@ describe('RTBHouseAdapter', () => { it('should populate GDPR and empty consent string if available for EEA users without consent string but with consent', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; - const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true}}); + const request = spec.buildRequests( + bidRequest, + Object.assign({}, bidderRequest, { + gdprConsent: { + gdprApplies: true + } + }) + ); let data = JSON.parse(request.data); expect(data.regs.ext.gdpr).to.equal(1); expect(data.user.ext.consent).to.equal(''); @@ -119,11 +138,26 @@ describe('RTBHouseAdapter', () => { it('should include banner imp in request', () => { const bidRequest = Object.assign([], bidRequests); - const request = spec.buildRequests(bidRequest); + const request = spec.buildRequests(bidRequest, bidderRequest); const data = JSON.parse(request.data); expect(data.imp[0].banner).to.not.be.empty; }); + it('should include source.tid in request', () => { + const bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest, bidderRequest); + const data = JSON.parse(request.data); + expect(data.source.tid).to.equal('example-transaction-id'); + }); + + it('should include bidfloor in request if available', () => { + const bidRequest = Object.assign([], bidRequests); + bidRequest[0].params.bidfloor = 0.01; + const request = spec.buildRequests(bidRequest, bidderRequest); + const data = JSON.parse(request.data); + expect(data.imp[0].bidfloor).to.equal(0.01) + }); + describe('native imp', () => { function basicRequest(extension) { return Object.assign({ @@ -139,7 +173,8 @@ describe('RTBHouseAdapter', () => { } function buildImp(request) { - return JSON.parse(spec.buildRequests([request]).data).imp[0]; + const resultRequest = spec.buildRequests([request], bidderRequest); + return JSON.parse(resultRequest.data).imp[0]; } it('should extract native params when single mediaType', () => { From ec023bae07fef725c8a69f8dc111f227138d0c88 Mon Sep 17 00:00:00 2001 From: ankur-modi <38654685+ankur-modi@users.noreply.github.com> Date: Thu, 1 Nov 2018 22:56:02 +0530 Subject: [PATCH 0807/1594] correct user agent value population (#3248) --- modules/oneVideoBidAdapter.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 5b1fd999ee6..bd341dfd79f 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -136,7 +136,6 @@ function isConsentRequired(consentData) { function getRequestData(bid, consentData) { let loc = utils.getTopWindowLocation(); - let global = (window.top) ? window.top : window; let page = (bid.params.site && bid.params.site.page) ? (bid.params.site.page) : (loc.href); let ref = (bid.params.site && bid.params.site.referrer) ? bid.params.site.referrer : utils.getTopWindowReferrer(); let bidData = { @@ -160,7 +159,7 @@ function getRequestData(bid, consentData) { ref: ref }, device: { - ua: global.navigator.userAgent + ua: navigator.userAgent }, tmax: 200 }; From 728465c6574213cc127e82216f1e2aa1edb67c57 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Fri, 2 Nov 2018 14:35:01 -0400 Subject: [PATCH 0808/1594] Increase timeoutBuffer default to 400 ms (#3258) * Increase default to 400 ms * fixed typo --- src/config.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/config.js b/src/config.js index ecb5f78a43f..e2302357591 100644 --- a/src/config.js +++ b/src/config.js @@ -19,7 +19,7 @@ const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; const DEFAULT_DISABLE_AJAX_TIMEOUT = false; -const DEFAULT_TIMEOUTBUFFER = 200; +const DEFAULT_TIMEOUTBUFFER = 400; export const RANDOM = 'random'; const FIXED = 'fixed'; @@ -146,12 +146,12 @@ export function newConfig() { }, // timeout buffer to adjust for bidder CDN latency - _timoutBuffer: DEFAULT_TIMEOUTBUFFER, + _timeoutBuffer: DEFAULT_TIMEOUTBUFFER, get timeoutBuffer() { - return this._timoutBuffer; + return this._timeoutBuffer; }, set timeoutBuffer(val) { - this._timoutBuffer = val; + this._timeoutBuffer = val; }, _disableAjaxTimeout: DEFAULT_DISABLE_AJAX_TIMEOUT, From 033b151e4f60493f61db4fa4d2c3bcc41cb40cc6 Mon Sep 17 00:00:00 2001 From: naegelin Date: Fri, 2 Nov 2018 23:31:28 +0100 Subject: [PATCH 0809/1594] Ensure transaction ID is always unique (#3190) * Ensure transaction ID is always unique Transaction ID implicitly suggests that this is a unique identifier per transaction. However in the case of a refresh / re-use of an ad unit the transaction ID remains the same causing undesirable bidding with certain SSPs. --- src/prebid.js | 4 +--- test/spec/unit/pbjs_api_spec.js | 5 +++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 48d08719cb1..61c5421c0d3 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -348,9 +348,7 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa return !includes(s2sBidders, bidder); }) : allBidders; - if (!adUnit.transactionId) { - adUnit.transactionId = utils.generateUUID(); - } + adUnit.transactionId = utils.generateUUID(); bidders.forEach(bidder => { const adapter = bidderRegistry[bidder]; diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index a03339c76b3..215bf2cd757 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1281,7 +1281,7 @@ describe('Unit: Prebid Module', function () { assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); }); - it('should attach transactionIds to ads (or pass through transactionId if it already exists)', function () { + it('should always attach new transactionIds to adUnits passed to requestBids', function () { $$PREBID_GLOBAL$$.requestBids({ adUnits: [ { @@ -1296,7 +1296,8 @@ describe('Unit: Prebid Module', function () { }); expect(auctionArgs.adUnits[0]).to.have.property('transactionId') - .and.to.equal('d0676a3c-ff32-45a5-af65-8175a8e7ddca'); + .and.to.match(/[a-f0-9\-]{36}/i) + .and.not.to.equal('d0676a3c-ff32-45a5-af65-8175a8e7ddca'); expect(auctionArgs.adUnits[1]).to.have.property('transactionId') .and.to.match(/[a-f0-9\-]{36}/i); }); From 1110e25f2e052be78b749f68b9cee2c32287b0f2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 5 Nov 2018 08:29:19 -0500 Subject: [PATCH 0810/1594] Add canonical url to referer info (#3254) --- src/refererDetection.js | 29 ++++++++++++++++++++++++++--- src/utils.js | 12 +++++++++--- test/spec/refererDetection_spec.js | 11 +++++++++-- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/refererDetection.js b/src/refererDetection.js index bf2ef5209f6..fb0b1dbeebb 100644 --- a/src/refererDetection.js +++ b/src/refererDetection.js @@ -78,6 +78,17 @@ export function detectReferer(win) { }; } + function getCanonicalUrl(doc) { + try { + let element = doc.querySelector("link[rel='canonical']"); + if (element !== null) { + return element.href; + } + } catch (e) { + } + return null; + } + function walkUpWindows() { let acc = []; let currentWindow; @@ -85,11 +96,18 @@ export function detectReferer(win) { try { currentWindow = currentWindow ? currentWindow.parent : win; try { - acc.push({ + let isTop = (currentWindow == win.top); + let refData = { referrer: currentWindow.document.referrer || null, location: currentWindow.location.href || null, - isTop: (currentWindow == win.top) - }); + isTop + } + if (isTop) { + refData = Object.assign(refData, { + canonicalUrl: getCanonicalUrl(currentWindow.document) + }) + } + acc.push(refData); } catch (e) { acc.push({ referrer: null, @@ -130,12 +148,17 @@ export function detectReferer(win) { let reachedTop = (levels[numIframes].location !== null || (numIframes > 0 && levels[numIframes - 1].referrer !== null)); let stackInfo = getPubUrlStack(levels); + let canonicalUrl; + if (levels[levels.length - 1].canonicalUrl) { + canonicalUrl = levels[levels.length - 1].canonicalUrl; + } return { referer: stackInfo.detectedRefererUrl, reachedTop, numIframes, stack: stackInfo.stack, + canonicalUrl }; } catch (e) { // Ignore error diff --git a/src/utils.js b/src/utils.js index 93b19485dfe..8203b3d4242 100644 --- a/src/utils.js +++ b/src/utils.js @@ -202,7 +202,7 @@ export function parseGPTSingleSizeArray(singleSize) { }; /** - * @deprecated This function will be removed soon + * @deprecated This function will be removed soon. Use http://prebid.org/dev-docs/bidder-adaptor.html#referrers */ exports.getTopWindowLocation = function() { if (exports.inIframe()) { @@ -218,7 +218,7 @@ exports.getTopWindowLocation = function() { } /** - * @deprecated This function will be removed soon + * @deprecated This function will be removed soon. Use http://prebid.org/dev-docs/bidder-adaptor.html#referrers */ exports.getTopFrameReferrer = function () { try { @@ -240,7 +240,7 @@ exports.getTopFrameReferrer = function () { }; /** - * @deprecated This function will be removed soon + * @deprecated This function will be removed soon. Use http://prebid.org/dev-docs/bidder-adaptor.html#referrers */ exports.getAncestorOrigins = function () { if (window.document.location && window.document.location.ancestorOrigins && @@ -261,6 +261,9 @@ exports.getWindowLocation = function () { return window.location; }; +/** + * @deprecated This function will be removed soon. Use http://prebid.org/dev-docs/bidder-adaptor.html#referrers + */ exports.getTopWindowUrl = function () { let href; try { @@ -271,6 +274,9 @@ exports.getTopWindowUrl = function () { return href; }; +/** + * @deprecated This function will be removed soon. Use http://prebid.org/dev-docs/bidder-adaptor.html#referrers + */ exports.getTopWindowReferrer = function() { try { return window.top.document.referrer; diff --git a/test/spec/refererDetection_spec.js b/test/spec/refererDetection_spec.js index 956ba794546..b2ef4e2058f 100644 --- a/test/spec/refererDetection_spec.js +++ b/test/spec/refererDetection_spec.js @@ -26,6 +26,11 @@ describe('referer detection', () => { let mockIframe2WinObject = mocks.createFakeWindow('http://example.com/iframe1.html', 'http://example.com/iframe2.html'); let mockIframe1WinObject = mocks.createFakeWindow('http://example.com/page.html', 'http://example.com/iframe1.html'); let mainWinObject = mocks.createFakeWindow('http://example.com/page.html', 'http://example.com/page.html'); + mainWinObject.document.querySelector = function() { + return { + href: 'http://prebid.org' + } + } mockIframe2WinObject.parent = mockIframe1WinObject; mockIframe2WinObject.top = mainWinObject; mockIframe1WinObject.parent = mainWinObject; @@ -42,7 +47,8 @@ describe('referer detection', () => { 'http://example.com/page.html', 'http://example.com/iframe1.html', 'http://example.com/iframe2.html' - ] + ], + canonicalUrl: 'http://prebid.org' }; expect(result).to.deep.equal(expectedResult); }); @@ -73,7 +79,8 @@ describe('referer detection', () => { null, 'http://aaa.com/iframe1.html', 'http://bbb.com/iframe2.html' - ] + ], + canonicalUrl: undefined }; expect(result).to.deep.equal(expectedResult); }); From 5e1c996ab8c04ee43420053f9bb1d82009239f80 Mon Sep 17 00:00:00 2001 From: Francesco Date: Mon, 5 Nov 2018 08:32:31 -0600 Subject: [PATCH 0811/1594] Bidfluence adapter 1.x (#3244) * Bidfluence Adapter 1.x * Test for Bidfluence Adapter 1.x * Update to Bidfluence Adapter 1.x * Update due to test not passing * Fixed undefined gdpr object and unsupported gdpr vendor * Removed gdpr vendor line test * Updated as requested Related to https://github.com/prebid/prebid.github.io/pull/1020#issuecomment-434789720 --- modules/bidfluenceBidAdapter.js | 116 ++++++++++++++++++ modules/bidfluenceBidAdapter.md | 31 +++++ .../spec/modules/bidfluenceBidAdapter_spec.js | 111 +++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 modules/bidfluenceBidAdapter.js create mode 100644 modules/bidfluenceBidAdapter.md create mode 100644 test/spec/modules/bidfluenceBidAdapter_spec.js diff --git a/modules/bidfluenceBidAdapter.js b/modules/bidfluenceBidAdapter.js new file mode 100644 index 00000000000..655e52e2d6d --- /dev/null +++ b/modules/bidfluenceBidAdapter.js @@ -0,0 +1,116 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'bidfluence'; + +function stdTimezoneOffset(t) { + const jan = new Date(t.getFullYear(), 0, 1); + const jul = new Date(t.getFullYear(), 6, 1); + return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()); +} +function dst(t) { + return t.getTimezoneOffset() < stdTimezoneOffset(t); +} +function getBdfTz(d) { + let tz = d.getTimezoneOffset(); + if (dst(d)) { + tz += 60; + } + return tz.toString(); +} +function getUTCDate() { + var m = new Date(); + var dateString = m.getUTCFullYear() + '/' + + ('0' + (m.getUTCMonth() + 1)).slice(-2) + '/' + + ('0' + m.getUTCDate()).slice(-2) + ' ' + + ('0' + m.getUTCHours()).slice(-2) + ':' + + ('0' + m.getUTCMinutes()).slice(-2) + ':' + + ('0' + m.getUTCSeconds()).slice(-2); + + return dateString; +} + +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: function (bid) { + return !!bid.params.placementId || !!bid.params.publisherId; + }, + + buildRequests: function (validBidRequests, bidderRequest) { + return validBidRequests.map(bidRequest => { + const params = bidRequest.params; + const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; + const width = sizes.split('x')[0]; + const height = sizes.split('x')[1]; + const refInfo = bidderRequest.refererInfo; + const gdpr = bidderRequest.gdprConsent; + const body = document.getElementsByTagName('body')[0]; + const vpW = Math.max(window.innerWidth || body.clientWidth || 0) + 2; + const vpH = Math.max(window.innerHeight || body.clientHeight || 0) + 2; + const sr = screen.height > screen.width ? screen.height + 'x' + screen.width + 'x' + screen.colorDepth : screen.width + 'x' + screen.height + 'x' + screen.colorDepth; + + const payload = { + bid: bidRequest.bidId, + v: '1.0', + azr: true, + ck: utils.cookiesAreEnabled(), + tid: params.placementId, + pid: params.publisherId, + rp: params.reservePrice || 0, + re: refInfo ? refInfo.referer : '', + st: refInfo ? refInfo.stack : [], + tz: getBdfTz(new Date()), + sr: sr, + tm: bidderRequest.timeout, + vp: vpW + 'x' + vpH, + sdt: getUTCDate(), + w: width, + h: height, + gdpr: gdpr ? gdpr.gdprApplies : false, + gdprc: gdpr ? gdpr.consentString : '' + }; + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: `//${payload.pid}.bidfluence.com/Hb`, + data: payloadString, + options: { contentType: 'text/plain' } + }; + }); + }, + + interpretResponse: function (serverResponse, bidRequest) { + const bidResponses = []; + const response = serverResponse.body; + const cpm = response.Cpm || 0; + + if (cpm > 0) { + const bidResponse = { + requestId: response.BidId, + cpm: cpm, + width: response.Width, + height: response.Height, + creativeId: response.CreativeId, + ad: response.Ad, + currency: 'USD', + netRevenue: true, + ttl: 360 + }; + bidResponses.push(bidResponse); + } + + return bidResponses; + }, + + getUserSyncs: function (serverResponses) { + if (serverResponses.userSyncs) { + const syncs = serverResponses.UserSyncs.map((sync) => { + return { + type: sync.Type === 'ifr' ? 'iframe' : 'image', + url: sync.Url + }; + }); + return syncs; + } + } +}; +registerBidder(spec); diff --git a/modules/bidfluenceBidAdapter.md b/modules/bidfluenceBidAdapter.md new file mode 100644 index 00000000000..34dbb3d3a1c --- /dev/null +++ b/modules/bidfluenceBidAdapter.md @@ -0,0 +1,31 @@ +# Overview + +``` +Module Name: Bidfluence Adapter +Module Type: Bidder Adapter +Maintainer: integrations@bidfluence.com +prebid_1_0_supported : true +gdpr_supported: true +``` + +# Description + +Bidfluence adapter for prebid. + +# Test Parameters + +``` +var adUnits = [ + { + code: 'test-prebid', + sizes: [[300, 250]], + bids: [{ + bidder: 'bidfluence', + params: { + placementId: '1000', + publisherId: '1000' + } + }] + } +] +``` diff --git a/test/spec/modules/bidfluenceBidAdapter_spec.js b/test/spec/modules/bidfluenceBidAdapter_spec.js new file mode 100644 index 00000000000..71471c6650b --- /dev/null +++ b/test/spec/modules/bidfluenceBidAdapter_spec.js @@ -0,0 +1,111 @@ +import { expect } from 'chai'; +import { spec } from 'modules/bidfluenceBidAdapter'; + +const BIDDER_CODE = 'bidfluence'; +const PLACEMENT_ID = '1000'; +const PUB_ID = '1000'; +const CONSENT_STRING = 'DUXDSDFSFWRRR8345F=='; + +const validBidRequests = [{ + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': PLACEMENT_ID, + 'publisherId': PUB_ID, + 'reservePrice': 0 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '2b1f23307fb8ef', + 'bidderRequestId': '10edf38ec1a719', + 'auctionId': '1025ba77-5463-4877-b0eb-14b205cb9304' +}]; + +const bidderRequest = { + 'bidderCode': 'bidfluence', + 'auctionId': '1025ba77-5463-4877-b0eb-14b205cb9304', + 'bidderRequestId': '10edf38ec1a719', + 'refererInfo': { + 'numIframes': 0, + 'reachedTop': true, + 'referer': 'test', + 'stack': ['test'] + }, + 'timeout': 1000, + 'gdprConsent': { + 'gdprApplies': true, + 'consentString': CONSENT_STRING, + 'vendorData': '' + } +}; + +bidderRequest.bids = validBidRequests; + +describe('Bidfluence Adapter test', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(validBidRequests[0])).to.equal(true); + }); + it('should return the right bidder code', function () { + expect(spec.code).to.eql(BIDDER_CODE); + }); + }); + + describe('buildRequests', function () { + const request = spec.buildRequests(validBidRequests, bidderRequest); + + it('sends bid request to our endpoint via POST', function () { + expect(request[0].method).to.equal('POST'); + }); + + const payload = JSON.parse(request[0].data); + + expect(payload.bid).to.equal(validBidRequests[0].bidId); + expect(payload.azr).to.equal(true); + expect(payload.ck).to.not.be.undefined; + expect(payload.tid).to.equal(PLACEMENT_ID); + expect(payload.pid).to.equal(PUB_ID); + expect(payload.rp).to.be.a('number'); + expect(payload.re).to.not.be.undefined; + expect(payload.st).to.not.be.undefined; + expect(payload.tz).to.not.be.undefined; + expect(payload.sr).to.not.be.undefined; + expect(payload.vp).to.not.be.undefined; + expect(payload.sdt).to.not.be.undefined; + expect(payload.w).to.equal('300'); + expect(payload.h).to.equal('250'); + + it('sends gdpr info if exists', function () { + expect(payload.gdpr).to.equal(true); + expect(payload.gdprc).to.equal(CONSENT_STRING); + }); + }); + + describe('interpretResponse', function () { + const response = { + body: { + 'CreativeId': '1000', + 'Cpm': 0.50, + 'Ad': '
', + 'Height': 250, + 'Width': 300 + } + }; + + it('should get correct bid response', function () { + const expectedResponse = [{ + requestId: response.body.BidId, + cpm: response.body.Cpm, + width: response.body.Width, + height: response.body.Height, + creativeId: response.body.CreativeId, + ad: response.body.Ad, + currency: 'USD', + netRevenue: true, + ttl: 360 + }]; + + let result = spec.interpretResponse(response, { 'bidderRequest': validBidRequests[0] }); + expect(result).to.deep.equal(expectedResponse); + }); + }); +}); From 432c656fb59765702be79eec473052a0b09c3d75 Mon Sep 17 00:00:00 2001 From: AlessandroDG Date: Mon, 5 Nov 2018 16:23:40 +0100 Subject: [PATCH 0812/1594] Rivr Analytics Adapter (#3202) * RVR-1124 Setup initial skeleton analytics adapter that can send something. Approved-by: Alessandro Di Giovanni * Formatted auction/events data to fit needed schema. * RVR-1135 fetched device data. * Applied feedback. * Applied feedback. * Fetched core. * Added click handler for reporting banners click events. * Applied analyzer for reporting displayed impressions. * Applied feedback. * Merged in RVR-1214-invoke-handlers-on-rendering (pull request #7) RVR-1214 Invoke handlers on rendering * RVR-1214 Invoked handlers right after ad is displayed. * Applied feedback. Approved-by: Alessandro Di Giovanni * Merged in RVR-1192-configuration-global-parameters (pull request #8) RVR-1192 Configuration/Global parameters Approved-by: Alessandro Di Giovanni * Merged in RVR-1181-Prebid-js-unit-tests-setup (pull request #6) RVR-1181 Prebid.js Unit tests setup Approved-by: Alessandro Di Giovanni * Merged in RVR-1247-additional-data-to-impression-records (pull request #9) RVR-1247 Additional data to impression records Approved-by: Alessandro Di Giovanni * Merged in RVR-1249-add-requestedbids-to-auction (pull request #10) RVR-1249 Add requested bids to auction object request. Approved-by: Alessandro Di Giovanni * Merged in RVR-1261-fix-tests (pull request #11) RVR-1261 fix tests * RVR-1261 Secured adapter from no containers configuration. And changed fetching URL. * RVR-1261 Added event check for request and changed some names. * Applied feedback. Approved-by: Alessandro Di Giovanni * RVR-1352 analytics adapter bugs Approved-by: Alessandro Di Giovanni * Fixed bug with geolocation notification. * fixed missing bracket. * one more fix. * RVR-1357 Different optimisation responses & tracking into auction event * RVR-1852 - Add content type and hardcoded auth headers (cherry picked from commit 4def881) * RVR-1852 - Change tracker host * RVR-1852 - Override content type instead of adding header * RVR-1914 Consistent data types in events Also removes undefined and null properties in audience events * Merged in RVR-1883-Add-Basic-Access-Authentication (pull request #17) RVR-1883 Add Basic Access Authentication * RVR-1914 - Rename functions * RVR-1914 - Set default total_duration to null in bid response * RVR-1883 - Use RIVR_CLIENT_AUTH_TOKEN global variable for Auth token * RVR-1883 - Restore stub after every test not just at the end * RVR-1883 - Remove commented code * Increase code coverage * Fix for IE 11.0.0 and Safari 8.0.8 - includes() Use core-js includes function for array * Restore pbjs_api_spec.js * Fix API calls for rivr analytics impressions and clicks * Rvr 2005 rvr analytics adapter (#4) * Submitting EMX Digital Adapter (#3173) * Submitting EMX Digital Prebid Adapter Submitting EMX Digital Prebid Adapter code * fixing lint errors. updating our md * updating to const/let variables. adding test spec. * fixed linting on test spec js * TheMediaGrid Bid Adapter (#3204) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Adding user sync method for IFRAME and Pixel (#3232) * Submitting EMX Digital Prebid Adapter Submitting EMX Digital Prebid Adapter code * fixing lint errors. updating our md * updating to const/let variables. adding test spec. * fixed linting on test spec js * adding emx usersync methods * updates (#3162) * Only set native targeting if value exists. (#3225) * add nolint command line option, similar to notest (#3234) * add inskin iab vendor id: enables consent via string (#3235) * Added user sync support for undertone bid adapter (#3172) * Added user sync support for undertone bid adapter (new pull request) * Added user sync support for undertone bid adapter * fix indentation * Changed utils.getWindowTop() with the newer prebid utilities * Updating Auction Init Pick for timestamp + Test update (#3223) * Updating Auction Init Pick for timestamp + Test update * Updating Auction Init to include once again + Rubicon Analytics update accordingly * Removing from auction init events in favor of old * Add code, test, and doc for Adikteev adapter (#3229) * Add code, test, and doc for Adikteev adapter * Reflect comments on other PR http://prebid.org/dev-docs/bidder-adaptor.html#referrers https://github.com/prebid/Prebid.js/pull/3230#discussion_r228319752 * 'currency' isn't a bidder-specific param Update PR following this remark on another one: https://github.com/prebid/Prebid.js/pull/3228#discussion_r228317072 * Add integration example, fix bid requestId * Quantcast adapter onTimeout (#3239) * onTimeout WIP * test for onTimeout * some renaming * cleanup * cleanup * trying to fix the test * using ajax instead of fetch * Test cleanup (#3238) * stub pixel call in justpremium tests * properly stub geolocation services to prevent prompts * stub img creation as well to prevent call in justpremium * Appnexus adapter: Added dealPriority and dealCode to bidResponse (#3201) * Added dealPriority and dealCode to appnexus adapter * update failed test * added namespace and did deep merge * keep all properties together * use unit id being sent instead of hard coded auid (#3236) * use unit id being sent instead of hard coded auid * make multiple requests * removes commented out code. adds aus param back * Prebid 1.30.0 Release * increment pre version * fix deal targeting for cpm 0 (#3233) * YIELDONE adapter - support Video (#3227) * added UserSync * added UserSync Unit Test * support for multi sizes * register the adapter as supporting video * supporting video * change requestId acquisition method * fix the parameter name of dealID * update test parameters * support instream video * add test for bidRequest * add test for interpretResponse * add test params * add note to documentaion * clarifying the multi-format support message * rtbhouseBidAdapter changes (#3241) * Add transactionId support * Change site getting method * Add bidfloor param * correct user agent value population (#3248) * RVR-1124 Setup initial skeleton analytics adapter that can send something. Approved-by: Alessandro Di Giovanni * Formatted auction/events data to fit needed schema. * RVR-1135 fetched device data. * Applied feedback. * Applied feedback. * Fetched core. * Added click handler for reporting banners click events. * Applied analyzer for reporting displayed impressions. * Applied feedback. * Merged in RVR-1214-invoke-handlers-on-rendering (pull request #7) RVR-1214 Invoke handlers on rendering * RVR-1214 Invoked handlers right after ad is displayed. * Applied feedback. Approved-by: Alessandro Di Giovanni * Merged in RVR-1192-configuration-global-parameters (pull request #8) RVR-1192 Configuration/Global parameters Approved-by: Alessandro Di Giovanni * Merged in RVR-1181-Prebid-js-unit-tests-setup (pull request #6) RVR-1181 Prebid.js Unit tests setup Approved-by: Alessandro Di Giovanni * Merged in RVR-1247-additional-data-to-impression-records (pull request #9) RVR-1247 Additional data to impression records Approved-by: Alessandro Di Giovanni * Merged in RVR-1249-add-requestedbids-to-auction (pull request #10) RVR-1249 Add requested bids to auction object request. Approved-by: Alessandro Di Giovanni * Merged in RVR-1261-fix-tests (pull request #11) RVR-1261 fix tests * RVR-1261 Secured adapter from no containers configuration. And changed fetching URL. * RVR-1261 Added event check for request and changed some names. * Applied feedback. Approved-by: Alessandro Di Giovanni * RVR-1352 analytics adapter bugs Approved-by: Alessandro Di Giovanni * Fixed bug with geolocation notification. * fixed missing bracket. * one more fix. * RVR-1357 Different optimisation responses & tracking into auction event * RVR-1852 - Add content type and hardcoded auth headers (cherry picked from commit 4def881) * RVR-1852 - Change tracker host * RVR-1852 - Override content type instead of adding header * RVR-1914 Consistent data types in events Also removes undefined and null properties in audience events * Merged in RVR-1883-Add-Basic-Access-Authentication (pull request #17) RVR-1883 Add Basic Access Authentication * RVR-1914 - Rename functions * RVR-1914 - Set default total_duration to null in bid response * RVR-1883 - Use RIVR_CLIENT_AUTH_TOKEN global variable for Auth token * RVR-1883 - Restore stub after every test not just at the end * RVR-1883 - Remove commented code * Increase code coverage * Fix for IE 11.0.0 and Safari 8.0.8 - includes() Use core-js includes function for array * Restore pbjs_api_spec.js * Fix API calls for rivr analytics impressions and clicks * RVR-2005 - Change auction object model * RVR-2005 - Set rvr_usr_id cookie * RVR-2005 - Remove BID_REQUESTED and BID_RESPONSE handlers We have the same infos all collected in AUCTION_END * RVR-2005 - build Bidders Array From Auction End * RVR-2005 - build impressions Array From Auction End * RVR-2005 - set status of winning bid * RVR-2005 - cleanup * RVR-2005 - adapt enableAnalytics() test * RVR-2005 - adapt all tests * RVR-2005 - Add Rivr Analytics adapter md file * RVR-2005 - rewrite connectAllUnits * RVR-2005 - correct typo * RVR-2005 - use IE compatible find() --- modules/rivrAnalyticsAdapter.js | 472 +++++++ modules/rivrAnalyticsAdapter.md | 13 + .../spec/modules/rivrAnalyticsAdapter_spec.js | 1132 +++++++++++++++++ 3 files changed, 1617 insertions(+) create mode 100644 modules/rivrAnalyticsAdapter.js create mode 100644 modules/rivrAnalyticsAdapter.md create mode 100644 test/spec/modules/rivrAnalyticsAdapter_spec.js diff --git a/modules/rivrAnalyticsAdapter.js b/modules/rivrAnalyticsAdapter.js new file mode 100644 index 00000000000..14143f5f21d --- /dev/null +++ b/modules/rivrAnalyticsAdapter.js @@ -0,0 +1,472 @@ +import {ajax} from 'src/ajax'; +import adapter from 'src/AnalyticsAdapter'; +import find from 'core-js/library/fn/array/find'; +import CONSTANTS from 'src/constants.json'; +import adaptermanager from 'src/adaptermanager'; +import { logInfo, generateUUID, timestamp } from 'src/utils'; + +const analyticsType = 'endpoint'; +const rivrUsrIdCookieKey = 'rvr_usr_id'; +const DEFAULT_HOST = 'tracker.rivr.simplaex.com'; +const DEFAULT_QUEUE_TIMEOUT = 4000; + +let rivrAnalytics = Object.assign(adapter({analyticsType}), { + track({ eventType, args }) { + if (!rivrAnalytics.context) { + return; + } + logInfo(`ARGUMENTS FOR TYPE: ============= ${eventType}`, args); + let handler = null; + switch (eventType) { + case CONSTANTS.EVENTS.AUCTION_INIT: + logInfo(`CONSTANTS.EVENTS.AUCTION_INIT rivrAnalytics.context.auctionObject`, rivrAnalytics.context.auctionObject); + if (rivrAnalytics.context.queue) { + rivrAnalytics.context.queue.init(); + } + if (rivrAnalytics.context.auctionObject) { + rivrAnalytics.context.auctionObject = createNewAuctionObject(); + saveUnoptimisedAdUnits(); + fetchLocalization(); + } + handler = trackAuctionInit; + break; + case CONSTANTS.EVENTS.BID_WON: + handler = trackBidWon; + break; + case CONSTANTS.EVENTS.BID_TIMEOUT: + handler = trackBidTimeout; + break; + case CONSTANTS.EVENTS.AUCTION_END: + handler = trackAuctionEnd; + break; + } + if (handler) { + handler(args) + } + } +}); + +export function sendAuction() { + if (rivrAnalytics.context.authToken) { + removeEmptyProperties(rivrAnalytics.context.auctionObject); + let auctionObject = rivrAnalytics.context.auctionObject; + let req = Object.assign({}, {Auction: auctionObject}); + rivrAnalytics.context.auctionObject = createNewAuctionObject(); + logInfo('sending request to analytics => ', req); + ajax( + `http://${rivrAnalytics.context.host}/${rivrAnalytics.context.clientID}/auctions`, + () => {}, + JSON.stringify(req), + { + contentType: 'application/json', + customHeaders: { + 'Authorization': 'Basic ' + rivrAnalytics.context.authToken + } + } + ); + } +}; + +export function sendImpressions() { + if (rivrAnalytics.context.authToken) { + let impressions = rivrAnalytics.context.queue.popAll(); + if (impressions.length !== 0) { + let impressionsReq = Object.assign({}, {impressions}); + logInfo('sending impressions request to analytics => ', impressionsReq); + ajax( + `http://${rivrAnalytics.context.host}/${rivrAnalytics.context.clientID}/impressions`, + () => {}, + JSON.stringify(impressionsReq), + { + contentType: 'application/json', + customHeaders: { + 'Authorization': 'Basic ' + rivrAnalytics.context.authToken + } + } + ); + } + } +}; + +function trackAuctionInit(args) { + rivrAnalytics.context.auctionTimeStart = Date.now(); + rivrAnalytics.context.auctionObject.id = args.auctionId; +}; + +function trackBidWon(args) { + setWinningBidStatus(args); +}; + +function setWinningBidStatus(args) { + let auctionObject = rivrAnalytics.context.auctionObject; + const bidderObjectForThisWonBid = find(auctionObject.bidders, (bidder) => { + return bidder.id === args.bidderCode; + }); + if (bidderObjectForThisWonBid) { + const bidObjectForThisWonBid = find(bidderObjectForThisWonBid.bids, (bid) => { + return bid.impId === args.adUnitCode; + }); + if (bidObjectForThisWonBid) { + bidObjectForThisWonBid.status = 1; + } + } +}; + +export function trackAuctionEnd(args) { + rivrAnalytics.context.auctionTimeEnd = Date.now(); + rivrAnalytics.context.auctionObject.bidders = buildBiddersArrayFromAuctionEnd(args); + rivrAnalytics.context.auctionObject.impressions = buildImpressionsArrayFromAuctionEnd(args); +}; + +function buildImpressionsArrayFromAuctionEnd(auctionEndEvent) { + return auctionEndEvent.adUnits.map((adUnit) => { + const impression = {}; + impression.id = adUnit.code; + impression.adType = 'unknown'; + impression.acceptedSizes = []; + const bidReceivedForThisAdUnit = find(auctionEndEvent.bidsReceived, (bidReceived) => { + return adUnit.code === bidReceived.adUnitCode; + }); + if (adUnit.mediaTypes) { + if (adUnit.mediaTypes.banner) { + buildAdTypeDependentFieldsForImpression(impression, 'banner', adUnit, bidReceivedForThisAdUnit); + } else if (adUnit.mediaTypes.video) { + buildAdTypeDependentFieldsForImpression(impression, 'video', adUnit, bidReceivedForThisAdUnit); + } + } + return impression; + }); +} + +function buildAdTypeDependentFieldsForImpression(impression, adType, adUnit, bidReceivedForThisAdUnit) { + impression.adType = adType; + impression.acceptedSizes = adUnit.mediaTypes[adType].sizes.map((acceptedSize) => { + return { + w: acceptedSize[0], + h: acceptedSize[1] + }; + }); + if (bidReceivedForThisAdUnit) { + impression[adType] = { + w: bidReceivedForThisAdUnit.width, + h: bidReceivedForThisAdUnit.height + }; + } +} + +function buildBiddersArrayFromAuctionEnd(auctionEndEvent) { + return auctionEndEvent.bidderRequests.map((bidderRequest) => { + const bidder = {}; + bidder.id = bidderRequest.bidderCode; + bidder.bids = bidderRequest.bids.map((bid) => { + const bidReceivedForThisRequest = find(auctionEndEvent.bidsReceived, (bidReceived) => { + return bidderRequest.bidderCode === bidReceived.bidderCode && + bid.bidId === bidReceived.adId && + bid.adUnitCode === bidReceived.adUnitCode; + }); + return { + adomain: [''], + clearPrice: 0.0, + impId: bid.adUnitCode, + price: bidReceivedForThisRequest ? bidReceivedForThisRequest.cpm : 0.0, + status: 0 + }; + }); + return bidder; + }); +} + +function trackBidTimeout(args) { + return [args]; +}; + +export function fetchLocalization() { + if (navigator.permissions) { + navigator.permissions.query({ name: 'geolocation' }).then((permission) => { + if (permission.status === 'granted') { + navigator.geolocation.getCurrentPosition((position) => { + setAuctionAbjectPosition(position); + }); + } + }); + } +} + +export function setAuctionAbjectPosition(position) { + rivrAnalytics.context.auctionObject.device.geo.lat = position.coords.latitude; + rivrAnalytics.context.auctionObject.device.geo.long = position.coords.longitude; +} + +function getPlatformType() { + if (navigator.userAgent.match(/mobile/i) || navigator.userAgent.match(/iPad|Android|Touch/i)) { + return 1; + } else { + return 2; + } +}; + +export function reportClickEvent(event) { + let link = event.currentTarget.getElementsByTagName('a')[0]; + let clickUrl; + if (link) { + clickUrl = link.getAttribute('href'); + } + let timestamp = new Date().toISOString(); + let requestId = generateUUID(); + let req = { + timestamp, + 'request_id': requestId, + 'click_url': clickUrl + }; + logInfo('Sending click events with parameters: ', req); + ajax( + `http://${rivrAnalytics.context.host}/${rivrAnalytics.context.clientID}/clicks`, + () => {}, + JSON.stringify(req), + { + contentType: 'application/json', + customHeaders: { + 'Authorization': 'Basic ' + rivrAnalytics.context.authToken + } + } + ); +}; + +function addClickHandler(bannerId) { + pinHandlerToHTMLElement(bannerId, dataLoaderForHandler, addClickListener); +}; + +function addDisplayedImpHandler(bannerId) { + pinHandlerToHTMLElement(bannerId, dataLoaderForHandler, impHandler); +}; + +export function pinHandlerToHTMLElement(elementId, dataLoaderForHandler, specializedHandler) { + function waitForElement() { + let element = document.getElementById(elementId); + if (!element) { + window.requestAnimationFrame(waitForElement); + } else { + dataLoaderForHandler(element, specializedHandler); + } + } + waitForElement(); +} + +export function dataLoaderForHandler(element, specializedHandler) { + function waitForElement() { + let iframe = element.getElementsByTagName('iframe')[0]; + if (!iframe) { + window.requestAnimationFrame(waitForElement); + } else { + let displayedImpression = iframe.contentDocument.getElementsByTagName('img').length > 0; + if (!displayedImpression) { + window.requestAnimationFrame(waitForElement); + } else { + specializedHandler(iframe); + } + } + } + waitForElement(); +}; + +function addClickListener(iframe) { + iframe.contentDocument.addEventListener('click', reportClickEvent); +} + +function impHandler(iframe) { + let timestamp = new Date().toISOString(); + let requestId = generateUUID(); + let adContainerId = iframe.parentElement.parentElement.id; + let impression = { + timestamp, + 'request_id': requestId, + 'tag_id': adContainerId + }; + if (rivrAnalytics.context.queue) { + rivrAnalytics.context.queue.push(impression); + } +} + +function addHandlers(bannersIds) { + bannersIds.forEach((bannerId) => { + addClickHandler(bannerId); + addDisplayedImpHandler(bannerId); + }) +}; + +export function createNewAuctionObject() { + const auction = { + id: '', + publisher: rivrAnalytics.context.clientID, + blockedCategories: [''], + timestamp: timestamp(), + user: { + id: rivrAnalytics.context.userId + }, + site: { + domain: window.location.host, + page: window.location.pathname, + categories: rivrAnalytics.context.siteCategories + }, + impressions: [], + bidders: [], + device: { + userAgent: navigator.userAgent, + browser: '', + deviceType: getPlatformType() + }, + 'ext.rivr.originalvalues': [], + 'ext.rivr.optimiser': localStorage.getItem('rivr_should_optimise') || 'unoptimised', + modelVersion: localStorage.getItem('rivr_model_version') || null, + } + + return auction; +}; + +export function saveUnoptimisedAdUnits() { + let units = rivrAnalytics.context.adUnits; + if (units) { + if (units.length > 0) { + let allUnits = concatAllUnits(units); + allUnits.forEach((adUnit) => { + adUnit.bids.forEach((bid) => { + let configForBidder = fetchConfigForBidder(bid.bidder); + if (configForBidder) { + let unOptimisedParamsField = createUnOptimisedParamsField(bid, configForBidder); + rivrAnalytics.context.auctionObject['ext.rivr.originalvalues'].push(unOptimisedParamsField); + } + }) + }); + } + } +}; + +export function concatAllUnits(units) { + return Array.prototype.concat.apply([], units); +} + +export function createUnOptimisedParamsField(bid, config) { + let floorPriceLabel = config['floorPriceLabel']; + let currencyLabel = config['currencyLabel']; + let pmpLabel = config['pmpLabel']; + return { + 'ext.rivr.demand_source_original': bid.bidder, + 'ext.rivr.bidfloor_original': bid.params[floorPriceLabel], + 'ext.rivr.currency_original': bid.params[currencyLabel], + 'ext.rivr.pmp_original': bid.params[pmpLabel], + } +} + +function fetchConfigForBidder(bidderName) { + let config = localStorage.getItem('rivr_config_string'); + if (config) { + let parsed = JSON.parse(config); + return parsed.demand.map((bidderConfig) => { + if (bidderName === bidderConfig.partner) { + return bidderConfig + }; + })[0]; + } +} +/** + * Expiring queue implementation. Fires callback on elapsed timeout since last last update or creation. + * @param callback + * @param ttl + * @constructor + */ +export function ExpiringQueue(sendImpressions, sendAuction, ttl, log) { + let queue = []; + let timeoutId; + + this.push = (event) => { + if (event instanceof Array) { + queue.push.apply(queue, event); + } else { + queue.push(event); + } + reset(); + }; + + this.popAll = () => { + let result = queue; + queue = []; + reset(); + return result; + }; + /** + * For test/debug purposes only + * @return {Array} + */ + this.peekAll = () => { + return queue; + }; + + this.init = reset; + + function reset() { + if (timeoutId) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(() => { + sendAuction(); + if (queue.length) { + sendImpressions(); + } + }, ttl); + } +}; + +function removeEmptyProperties(obj) { + Object.keys(obj).forEach(function(key) { + if (obj[key] && typeof obj[key] === 'object') removeEmptyProperties(obj[key]) + else if (obj[key] == null) delete obj[key] + }); +}; + +function getCookie(name) { + var value = '; ' + document.cookie; + var parts = value.split('; ' + name + '='); + if (parts.length == 2) return parts.pop().split(';').shift(); +} + +function storeAndReturnRivrUsrIdCookie() { + return document.cookie = 'rvr_usr_id=' + generateUUID(); +} + +// save the base class function +rivrAnalytics.originEnableAnalytics = rivrAnalytics.enableAnalytics; + +// override enableAnalytics so we can get access to the config passed in from the page +rivrAnalytics.enableAnalytics = (config) => { + let copiedUnits; + if (config.options.adUnits) { + let stringifiedAdUnits = JSON.stringify(config.options.adUnits); + copiedUnits = JSON.parse(stringifiedAdUnits); + } + rivrAnalytics.context = { + userId: getCookie(rivrUsrIdCookieKey) || storeAndReturnRivrUsrIdCookie(), + host: config.options.host || DEFAULT_HOST, + auctionObject: {}, + adUnits: copiedUnits, + siteCategories: config.options.siteCategories || [], + clientID: config.options.clientID, + authToken: config.options.authToken, + queue: new ExpiringQueue(sendImpressions, sendAuction, config.options.queueTimeout || DEFAULT_QUEUE_TIMEOUT) + }; + + let bannersIds = config.options.bannersIds; + if (bannersIds) { + if (bannersIds.length > 0) { + addHandlers(config.options.bannersIds); + } + } + logInfo('Rivr Analytics enabled with config', rivrAnalytics.context); + rivrAnalytics.originEnableAnalytics(config); +}; + +adaptermanager.registerAnalyticsAdapter({ + adapter: rivrAnalytics, + code: 'rivr' +}); + +export default rivrAnalytics diff --git a/modules/rivrAnalyticsAdapter.md b/modules/rivrAnalyticsAdapter.md new file mode 100644 index 00000000000..787034e362e --- /dev/null +++ b/modules/rivrAnalyticsAdapter.md @@ -0,0 +1,13 @@ +# Overview + +Module Name: Rivr Analytics Adapter + +Module Type: Analytics Adapter + +Maintainer: rnd@simplaex.com + +# Description + +Analytics adapter for www.rivr.ai. + +Contact support@simplaex.com for information and support. diff --git a/test/spec/modules/rivrAnalyticsAdapter_spec.js b/test/spec/modules/rivrAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..0fc20171e0a --- /dev/null +++ b/test/spec/modules/rivrAnalyticsAdapter_spec.js @@ -0,0 +1,1132 @@ +import * as utils from 'src/utils'; +import analyticsAdapter from 'modules/rivrAnalyticsAdapter'; +import { + ExpiringQueue, + sendAuction, + sendImpressions, + reportClickEvent, + createUnOptimisedParamsField, + dataLoaderForHandler, + pinHandlerToHTMLElement, + setAuctionAbjectPosition, + createNewAuctionObject, + concatAllUnits, + trackAuctionEnd, +} from 'modules/rivrAnalyticsAdapter'; +import {expect} from 'chai'; +import adaptermanager from 'src/adaptermanager'; +import * as ajax from 'src/ajax'; +import CONSTANTS from 'src/constants.json'; + +const events = require('../../../src/events'); + +describe('RIVR Analytics adapter', () => { + const EXPIRING_QUEUE_TIMEOUT = 4000; + const EXPIRING_QUEUE_TIMEOUT_MOCK = 100; + const RVR_CLIENT_ID_MOCK = 'aCliendId'; + const SITE_CATEGORIES_MOCK = ['cat1', 'cat2']; + const EMITTED_AUCTION_ID = 1; + const TRACKER_BASE_URL_MOCK = 'tracker.rivr.simplaex.com'; + const UUID_REG_EXP = new RegExp('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', 'i'); + let sandbox; + let ajaxStub; + let timer; + + before(() => { + sandbox = sinon.sandbox.create(); + }); + + beforeEach(() => { + timer = sandbox.useFakeTimers(0); + ajaxStub = sandbox.stub(ajax, 'ajax'); + sinon.stub(events, 'getEvents').returns([]); + + adaptermanager.registerAnalyticsAdapter({ + code: 'rivr', + adapter: analyticsAdapter + }); + adaptermanager.enableAnalytics({ + provider: 'rivr', + options: { + clientID: RVR_CLIENT_ID_MOCK, + adUnits: [utils.deepClone(BANNER_AD_UNITS_MOCK)], + siteCategories: SITE_CATEGORIES_MOCK, + } + }); + }); + + afterEach(() => { + analyticsAdapter.disableAnalytics(); + events.getEvents.restore(); + ajaxStub.restore(); + timer.restore(); + }); + + after(() => { + sandbox.restore(); + }); + + it('ExpiringQueue should call sendImpression callback after expiring queue timeout is elapsed', (done) => { + const sendImpressionMock = () => { + let elements = queue.popAll(); + expect(elements).to.be.eql([1, 2, 3, 4]); + elements = queue.popAll(); + expect(elements).to.have.lengthOf(0); + expect(Date.now()).to.be.equal(200); + done(); + }; + const sendAuctionMock = () => {}; + + let queue = new ExpiringQueue( + sendImpressionMock, + sendAuctionMock, + EXPIRING_QUEUE_TIMEOUT_MOCK); + + queue.push(1); + + setTimeout(() => { + queue.push([2, 3]); + timer.tick(50); + }, 50); + setTimeout(() => { + queue.push([4]); + timer.tick(100); + }, 100); + timer.tick(50); + }); + + it('enableAnalytics - should configure host and clientID in adapter context', () => { + // adaptermanager.enableAnalytics() is called in beforeEach. If only called here it doesn't seem to work. + + expect(analyticsAdapter.context).to.have.property('host', TRACKER_BASE_URL_MOCK); + expect(analyticsAdapter.context).to.have.property('clientID', RVR_CLIENT_ID_MOCK); + }); + + it('enableAnalytics - should set a cookie containing a user id', () => { + expect(UUID_REG_EXP.test(analyticsAdapter.context.userId)).to.equal(true); + }); + + it('Firing AUCTION_INIT should set auction id of context when AUCTION_INIT event is fired', () => { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: EMITTED_AUCTION_ID, config: {}, timeout: 3000}); + const auctionId = analyticsAdapter.context.auctionObject.id; + expect(auctionId).to.be.eql(EMITTED_AUCTION_ID); + }); + + it('Firing AUCTION_INIT when rivr_should_optimise and rivr_model_version are in local storage, sets ext.rivr.optimiser and modelVersion of in auction context', () => { + const RIVR_SHOULD_OPTIMISE_VALUE_MOCK = 'optimise'; + const RIVR_MODEL_VERSION_VALUE_MOCK = 'some model version'; + + localStorage.setItem('rivr_should_optimise', RIVR_SHOULD_OPTIMISE_VALUE_MOCK); + localStorage.setItem('rivr_model_version', RIVR_MODEL_VERSION_VALUE_MOCK); + + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 2, config: {}, timeout: 3000}); + + let auctionObject2 = analyticsAdapter.context.auctionObject; + + expect(auctionObject2['ext.rivr.optimiser']).to.be.eql(RIVR_SHOULD_OPTIMISE_VALUE_MOCK); + expect(auctionObject2['modelVersion']).to.be.eql(RIVR_MODEL_VERSION_VALUE_MOCK); + + localStorage.removeItem('rivr_should_optimise'); + localStorage.removeItem('rivr_model_version'); + }); + + it('Firing AUCTION_INIT , when auction object is already there and rivr_config_string is not in local storage, it does not save unoptimized params in rivr original values', () => { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 3, config: {}, timeout: 3000}); + + expect(analyticsAdapter.context.auctionObject['ext.rivr.originalvalues']).to.be.eql([]); + }); + + it('Firing AUCTION_INIT when rivr_should_optimise and rivr_model_version are NOT in local storage, does not set ext.rivr.optimiser and modelVersion of in auction context', () => { + localStorage.removeItem('rivr_should_optimise'); + localStorage.removeItem('rivr_model_version'); + + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 3, config: {}, timeout: 3000}); + + let auctionObject3 = analyticsAdapter.context.auctionObject; + + expect(auctionObject3['ext.rivr.optimiser']).to.be.eql('unoptimised'); + expect(auctionObject3['modelVersion']).to.be.eql(null); + }); + + it('Firing AUCTION_END it sets auction time end to current time', () => { + analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + + const MILLIS_FROM_EPOCH_TO_NOW_MOCK = 477; + timer.tick(MILLIS_FROM_EPOCH_TO_NOW_MOCK); + + events.emit(CONSTANTS.EVENTS.AUCTION_END, BID_RESPONSE_MOCK); + + const endTime = analyticsAdapter.context.auctionTimeEnd; + expect(endTime).to.be.eql(MILLIS_FROM_EPOCH_TO_NOW_MOCK); + }); + + it('Firing AUCTION_END populates impressions array in auction object', () => { + analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + + events.emit(CONSTANTS.EVENTS.AUCTION_END, AUCTION_END_EVENT_WITH_AD_UNITS_AND_BID_RESPONSES_MOCK); + + const impressions = analyticsAdapter.context.auctionObject.impressions; + expect(impressions.length).to.be.eql(3); + }); + + it('Firing BID_WON should set to 1 the status of the corresponding bid', () => { + analyticsAdapter.context.auctionObject = utils.deepClone(AUCTION_OBJECT_AFTER_AUCTION_END_MOCK); + + events.emit(CONSTANTS.EVENTS.BID_WON, BID_WON_MOCK); + + expect(analyticsAdapter.context.auctionObject.bidders.length).to.be.equal(3); + + expect(analyticsAdapter.context.auctionObject.bidders[0].bids[0].status).to.be.equal(0); + + expect(analyticsAdapter.context.auctionObject.bidders[1].bids[0].status).to.be.equal(0); + + expect(analyticsAdapter.context.auctionObject.bidders[2].bids[0].status).to.be.equal(1); + expect(analyticsAdapter.context.auctionObject.bidders[2].bids[1].status).to.be.equal(0); + }); + + it('when auction is initialized and authToken is defined and ExpiringQueue ttl expires, it sends the auction', () => { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: EMITTED_AUCTION_ID, config: {}, timeout: 3000}); + analyticsAdapter.context.authToken = 'anAuthToken'; + + expect(ajaxStub.notCalled).to.be.equal(true); + + timer.tick(EXPIRING_QUEUE_TIMEOUT + 500); + + expect(ajaxStub.calledOnce).to.be.equal(true); + }); + + it('when auction is initialized and authToken is defined and ExpiringQueue ttl expires, it resets auctionObject', () => { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: EMITTED_AUCTION_ID, config: {}, timeout: 3000}); + + analyticsAdapter.context.authToken = 'anAuthToken'; + events.emit(CONSTANTS.EVENTS.AUCTION_END, AUCTION_END_EVENT_WITH_AD_UNITS_AND_BID_RESPONSES_MOCK); + + let impressions = analyticsAdapter.context.auctionObject.impressions; + + expect(impressions.length).to.be.eql(3); + + timer.tick(EXPIRING_QUEUE_TIMEOUT + 500); + + let impressionsAfterSend = analyticsAdapter.context.auctionObject.impressions; + let biddersAfterSend = analyticsAdapter.context.auctionObject.bidders; + + expect(impressionsAfterSend.length).to.be.eql(0); + expect(biddersAfterSend.length).to.be.eql(0); + }); + + it('sendAuction(), when authToken is defined, it fires call clearing empty payload properties', () => { + analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + analyticsAdapter.context.authToken = 'anAuthToken'; + analyticsAdapter.context.auctionObject.nullProperty = null; + analyticsAdapter.context.auctionObject.notNullProperty = 'aValue'; + + sendAuction(); + + expect(ajaxStub.getCall(0).args[0]).to.match(/http:\/\/tracker.rivr.simplaex.com\/(\w+)\/auctions/); + + const payload = JSON.parse(ajaxStub.getCall(0).args[2]); + + expect(payload.Auction.notNullProperty).to.be.equal('aValue'); + expect(payload.nullProperty).to.be.equal(undefined); + + analyticsAdapter.context.authToken = undefined; + }); + + it('sendAuction(), when authToken is not defined, it does not fire call', () => { + analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + analyticsAdapter.context.authToken = undefined; + analyticsAdapter.context.auctionObject.nullProperty = null; + analyticsAdapter.context.auctionObject.notNullProperty = 'aValue'; + + expect(ajaxStub.callCount).to.be.equal(0); + + sendAuction(); + + expect(ajaxStub.callCount).to.be.equal(0); + }); + + it('sendImpressions(), when authToken is not defined, it does not fire call', () => { + analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + analyticsAdapter.context.authToken = undefined; + analyticsAdapter.context.auctionObject.nullProperty = null; + analyticsAdapter.context.auctionObject.notNullProperty = 'aValue'; + + expect(ajaxStub.callCount).to.be.equal(0); + + sendImpressions(); + + expect(ajaxStub.callCount).to.be.equal(0); + }); + + it('sendImpressions(), when authToken is defined and there are impressions, it sends impressions to the tracker', () => { + const aMockString = 'anImpressionPropertyValue'; + const IMPRESSION_MOCK = { anImpressionProperty: aMockString }; + const CLIENT_ID_MOCK = 'aClientID'; + analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + analyticsAdapter.context.authToken = 'anAuthToken'; + analyticsAdapter.context.clientID = CLIENT_ID_MOCK; + analyticsAdapter.context.queue = new ExpiringQueue( + () => {}, + () => {}, + EXPIRING_QUEUE_TIMEOUT_MOCK + ); + + analyticsAdapter.context.queue.push(IMPRESSION_MOCK); + + expect(ajaxStub.callCount).to.be.equal(0); + + sendImpressions(); + + const payload = JSON.parse(ajaxStub.getCall(0).args[2]); + + expect(ajaxStub.callCount).to.be.equal(1); + expect(payload.impressions.length).to.be.equal(1); + expect(ajaxStub.getCall(0).args[0]).to.match(/http:\/\/tracker.rivr.simplaex.com\/aClientID\/impressions/); + expect(payload.impressions[0].anImpressionProperty).to.be.equal(aMockString); + }); + + it('reportClickEvent() calls endpoint', () => { + const CLIENT_ID_MOCK = 'aClientId'; + const AUTH_TOKEN_MOCK = 'aToken'; + const CLICK_URL_MOCK = 'clickURLMock'; + const EVENT_MOCK = { + currentTarget: { + getElementsByTagName: () => { + return [ + { + getAttribute: (attributeName) => { + return CLICK_URL_MOCK; + } + } + ] + } + } + }; + analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + analyticsAdapter.context.authToken = AUTH_TOKEN_MOCK; + analyticsAdapter.context.clientID = CLIENT_ID_MOCK; + analyticsAdapter.context.auctionObject.nullProperty = null; + analyticsAdapter.context.auctionObject.notNullProperty = 'aValue'; + + expect(ajaxStub.callCount).to.be.equal(0); + + reportClickEvent(EVENT_MOCK); + + const payload = JSON.parse(ajaxStub.getCall(0).args[2]); + const options = ajaxStub.getCall(0).args[3]; + + expect(ajaxStub.callCount).to.be.equal(1); + expect(ajaxStub.getCall(0).args[0]).to.match(/http:\/\/tracker.rivr.simplaex.com\/aClientId\/clicks/); + expect(options.customHeaders.Authorization).to.equal('Basic aToken'); + expect(payload.timestamp).to.be.equal('1970-01-01T00:00:00.000Z'); + expect(payload.request_id).to.be.a('string'); + expect(payload.click_url).to.be.equal(CLICK_URL_MOCK); + }); + + it('createUnOptimisedParamsField(), creates object with unoptimized properties', () => { + const CONFIG_FOR_BIDDER_MOCK = { + floorPriceLabel: 'floorPriceLabelForTestBidder', + currencyLabel: 'currencyLabelForTestBidder', + pmpLabel: 'pmpLabelForTestBidder', + }; + const BID_MOCK = { + bidder: 'aBidder', + params: { + floorPriceLabelForTestBidder: 'theOriginalBidFloor', + currencyLabelForTestBidder: 'theOriginalCurrency', + pmpLabelForTestBidder: 'theOriginalPmp', + }, + }; + + const result = createUnOptimisedParamsField(BID_MOCK, CONFIG_FOR_BIDDER_MOCK); + + expect(result['ext.rivr.demand_source_original']).to.be.equal('aBidder'); + expect(result['ext.rivr.bidfloor_original']).to.be.equal('theOriginalBidFloor'); + expect(result['ext.rivr.currency_original']).to.be.equal('theOriginalCurrency'); + expect(result['ext.rivr.pmp_original']).to.be.equal('theOriginalPmp'); + }); + + it('dataLoaderForHandler(), when iframe and the ad image contained in it are there, it calls the specialized handler', () => { + const MOCK_ELEMENT = { + getElementsByTagName: () => { + return [ + { + contentDocument: { + getElementsByTagName: () => { + return ['displayedImpressionMock'] + } + }, + aDummyProperty: 'aDummyPropertyValue' + } + ] + } + }; + + var specializedHandlerSpy = sinon.spy(); + + expect(specializedHandlerSpy.callCount).to.be.equal(0); + + dataLoaderForHandler(MOCK_ELEMENT, specializedHandlerSpy); + + expect(specializedHandlerSpy.callCount).to.be.equal(1); + expect(specializedHandlerSpy.firstCall.args[0].aDummyProperty).to.be.equal('aDummyPropertyValue'); + expect(specializedHandlerSpy.firstCall.args[0].contentDocument.getElementsByTagName()[0]).to.be.equal('displayedImpressionMock'); + }); + + it('dataLoaderForHandler(), when iframe is not there, it requests animation frame', () => { + const MOCK_ELEMENT = { + getElementsByTagName: () => { + return [ + { + contentDocument: { + getElementsByTagName: () => { + return [] + } + }, + } + ] + } + }; + + const specializedHandlerSpy = sinon.spy(); + const requestAnimationFrameStub = sinon.stub(window, 'requestAnimationFrame'); + expect(requestAnimationFrameStub.callCount).to.be.equal(0); + + dataLoaderForHandler(MOCK_ELEMENT, specializedHandlerSpy); + + expect(requestAnimationFrameStub.callCount).to.be.equal(1); + + requestAnimationFrameStub.restore(); + }); + + it('pinHandlerToHTMLElement(), when element is there, it calls dataLoaderForHandler', () => { + const ELEMENT_MOCK = { + anElementProperty: 'aValue' + } + const dataLoaderForHandlerSpy = sinon.spy(); + sinon.stub(window, 'requestAnimationFrame'); + + sinon.stub(document, 'getElementById').returns(ELEMENT_MOCK); + + expect(dataLoaderForHandlerSpy.callCount).to.be.equal(0); + + pinHandlerToHTMLElement('', dataLoaderForHandlerSpy, () => {}); + + expect(dataLoaderForHandlerSpy.callCount).to.be.equal(1); + expect(dataLoaderForHandlerSpy.firstCall.args[0].anElementProperty).to.be.equal('aValue'); + + window.requestAnimationFrame.restore(); + document.getElementById.restore(); + }); + + it('pinHandlerToHTMLElement(), when element is not there, it requests animation frame', () => { + const dataLoaderForHandlerSpy = sinon.spy(); + const requestAnimationFrameStub = sinon.stub(window, 'requestAnimationFrame'); + + sinon.stub(document, 'getElementById').returns(undefined); + + expect(requestAnimationFrameStub.callCount).to.be.equal(0); + + pinHandlerToHTMLElement('', dataLoaderForHandlerSpy, () => {}); + + expect(dataLoaderForHandlerSpy.callCount).to.be.equal(0); + expect(requestAnimationFrameStub.callCount).to.be.equal(1); + + requestAnimationFrameStub.restore(); + document.getElementById.restore(); + }); + + it('setAuctionAbjectPosition(), it sets latitude and longitude in auction object', () => { + const POSITION_MOCK = { + coords: { + latitude: 'aLatitude', + longitude: 'aLongitude', + } + } + analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + + setAuctionAbjectPosition(POSITION_MOCK); + + expect(analyticsAdapter.context.auctionObject.device.geo.lat).to.be.equal('aLatitude'); + }); + + it('createNewAuctionObject(), it creates a new auction object', () => { + const MILLIS_FROM_EPOCH_TO_NOW_MOCK = 123456; + timer.tick(MILLIS_FROM_EPOCH_TO_NOW_MOCK); + + const result = createNewAuctionObject(); + + expect(result.device.deviceType).to.be.equal(2); + expect(result.publisher).to.be.equal(RVR_CLIENT_ID_MOCK); + expect(result.device.userAgent).to.be.equal(navigator.userAgent); + expect(result.timestamp).to.be.equal(MILLIS_FROM_EPOCH_TO_NOW_MOCK); + expect(result.site.domain.substring(0, 9)).to.be.equal('localhost'); + expect(result.site.page).to.be.equal('/context.html'); + expect(result.site.categories).to.be.equal(SITE_CATEGORIES_MOCK); + }); + + it('concatAllUnits(), returns a flattened array with all banner and video adunits', () => { + const allAdUnits = [BANNER_AD_UNITS_MOCK, VIDEO_AD_UNITS_MOCK]; + + const result = concatAllUnits(allAdUnits); + + expect(result.length).to.be.eql(2); + expect(result[0].code).to.be.eql('banner-container1'); + expect(result[1].code).to.be.eql('video'); + }); + + it('trackAuctionEnd(), populates the bidders array from bidderRequests and bidsReceived', () => { + trackAuctionEnd(AUCTION_END_EVENT_WITH_BID_REQUESTS_AND_BID_RESPONSES_MOCK); + + const result = analyticsAdapter.context.auctionObject.bidders; + + expect(result.length).to.be.eql(3); + + expect(result[0].id).to.be.eql('vuble'); + expect(result[0].bids[0].price).to.be.eql(0); + + expect(result[1].id).to.be.eql('vertamedia'); + expect(result[1].bids[0].price).to.be.eql(0); + + expect(result[2].id).to.be.eql('appnexus'); + expect(result[2].bids[0].price).to.be.eql(0.5); + expect(result[2].bids[0].impId).to.be.eql('/19968336/header-bid-tag-0'); + expect(result[2].bids[1].price).to.be.eql(0.7); + expect(result[2].bids[1].impId).to.be.eql('/19968336/header-bid-tag-1'); + }); + + it('trackAuctionEnd(), populates the impressions array from adUnits', () => { + trackAuctionEnd(AUCTION_END_EVENT_WITH_AD_UNITS_AND_BID_RESPONSES_MOCK); + + const result = analyticsAdapter.context.auctionObject.impressions; + + expect(result.length).to.be.eql(3); + + expect(result[0].id).to.be.eql('/19968336/header-bid-tag-0'); + expect(result[0].adType).to.be.eql('banner'); + + expect(result[1].id).to.be.eql('/19968336/header-bid-tag-1'); + expect(result[1].adType).to.be.eql('banner'); + expect(result[1].acceptedSizes).to.be.eql([{w: 728, h: 90}, {w: 970, h: 250}]); + expect(result[1].banner).to.be.eql({w: 300, h: 250}); + + expect(result[2].id).to.be.eql('video'); + expect(result[2].adType).to.be.eql('video'); + expect(result[2].acceptedSizes).to.be.eql([{w: 640, h: 360}, {w: 640, h: 480}]); + }); + + const BANNER_AD_UNITS_MOCK = [ + { + code: 'banner-container1', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 200], [300, 600]] + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: '10433394', + reserve: 0.5 + } + }, + { + bidder: 'huddledmasses', + params: { + placement_id: 0 + } + }, + ] + } + ]; + + const VIDEO_AD_UNITS_MOCK = [ + { + code: 'video', + mediaTypes: { + video: { + context: 'outstream', + sizes: [[640, 360], [640, 480]] + } + }, + bids: [ + { + bidder: 'vuble', + params: { + env: 'net', + pubId: '18', + zoneId: '12345', + referrer: 'http://www.vuble.tv/', // optional + floorPrice: 5.00 // optional + } + }, + { + bidder: 'vertamedia', + params: { + aid: 331133 + } + } + ] + }]; + + const REQUEST = { + bidderCode: 'adapter', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + bidderRequestId: '1a6fc81528d0f6', + bids: [{ + bidder: 'adapter', + params: {}, + adUnitCode: 'container-1', + transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', + sizes: [[300, 250]], + bidId: '208750227436c1', + bidderRequestId: '1a6fc81528d0f6', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' + }], + auctionStart: 1509369418387, + timeout: 3000, + start: 1509369418389 + }; + + const REQUEST2 = { + bidderCode: 'adapter', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + bidderRequestId: '1a6fc81528d0f6', + bids: [{ + bidder: 'adapter', + params: {}, + adUnitCode: 'container-1', + transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', + sizes: [[300, 250]], + bidId: 'request2id', + bidderRequestId: '1a6fc81528d0f6', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' + }], + auctionStart: 1509369418387, + timeout: 3000, + start: 1509369418389 + }; + + const REQUEST3 = { + bidderCode: 'adapter', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + bidderRequestId: '1a6fc81528d0f6', + bids: [{ + bidder: 'adapter', + params: {}, + adUnitCode: 'container-1', + transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', + sizes: [[300, 250]], + bidId: 'request3id', + bidderRequestId: '1a6fc81528d0f6', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' + }], + auctionStart: 1509369418387, + timeout: 3000, + start: 1509369418389 + }; + + const BID_RESPONSE_MOCK = { + bidderCode: 'adapter', + width: 300, + height: 250, + statusMessage: 'Bid available', + getStatusCode: () => 1, + adId: '208750227436c1', + mediaType: 'banner', + cpm: 0.015, + creativeId: 999, + ad: '', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + responseTimestamp: 1509369418832, + requestTimestamp: 1509369418389, + bidder: 'adapter', + adUnitCode: 'container-1', + timeToRespond: 443, + currency: 'EU', + size: '300x250' + }; + + const BID_WON_MOCK = { + bidderCode: 'appnexus', + width: 300, + height: 600, + statusMessage: 'Bid available', + adId: '63301dc59deb3b', + mediaType: 'banner', + source: 'client', + requestId: '63301dc59deb3b', + cpm: 0.5, + creativeId: 98493581, + currency: 'USD', + netRevenue: true, + ttl: 300, + appnexus: { + buyerMemberId: 9325 + }, + ad: '...HTML CONTAINING THE AD...', + auctionId: '1825871c-b4c2-401a-b219-64549d412495', + responseTimestamp: 1540560447955, + requestTimestamp: 1540560447622, + bidder: 'appnexus', + adUnitCode: '/19968336/header-bid-tag-0', + timeToRespond: 333, + pbLg: '0.50', + pbMg: '0.50', + pbHg: '0.50', + pbAg: '0.50', + pbDg: '0.50', + pbCg: '', + size: '300x600', + adserverTargeting: { + hb_bidder: 'appnexus', + hb_adid: '63301dc59deb3b', + hb_pb: '0.50', + hb_size: '300x600', + hb_source: 'client', + hb_format: 'banner' + }, + status: 'rendered', + params: [ + { + placementId: 13144370 + } + ] + }; + + const CONTEXT_AFTER_AUCTION_INIT = { + host: TRACKER_BASE_URL_MOCK, + clientID: RVR_CLIENT_ID_MOCK, + queue: { + mockProp: 'mockValue' + }, + auctionObject: { + id: null, + timestamp: null, + at: null, + bcat: [], + imp: [], + app: { + id: null, + name: null, + domain: window.location.href, + bundle: null, + cat: [], + publisher: { + id: null, + name: null + } + }, + site: { + id: null, + name: null, + domain: window.location.href, + cat: [], + publisher: { + id: null, + name: null + } + }, + device: { + geo: {} + }, + user: { + id: null, + yob: null, + gender: null, + }, + bidResponses: [], + bidRequests: [], + 'ext.rivr.optimiser': 'unoptimised', + modelVersion: null, + 'ext.rivr.originalvalues': [] + } + }; + + const AUCTION_END_EVENT_WITH_AD_UNITS_AND_BID_RESPONSES_MOCK = { + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + auctionStart: 1540560217395, + auctionEnd: 1540560217703, + auctionStatus: 'completed', + adUnits: [ + { + code: '/19968336/header-bid-tag-0', + mediaTypes: { + banner: { + sizes: [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ] + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 13144370 + }, + crumbs: { + pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' + } + } + ], + transactionId: 'aee9bf8d-6d8f-425b-a42a-52c875371ebc', + sizes: [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ] + }, + { + code: '/19968336/header-bid-tag-1', + mediaTypes: { + banner: { + sizes: [ + [ + 728, + 90 + ], + [ + 970, + 250 + ] + ] + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 13144370 + }, + crumbs: { + pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' + } + } + ], + transactionId: '3d5f0f89-e9cd-4714-b314-3f0fb7fcf8e3', + sizes: [ + [ + 728, + 90 + ], + [ + 970, + 250 + ] + ] + }, + { + code: 'video', + mediaTypes: { + video: { + context: 'outstream', + sizes: [ + [ + 640, + 360 + ], + [ + 640, + 480 + ] + ] + } + }, + bids: [ + { + bidder: 'vuble', + params: { + env: 'net', + pubId: '18', + zoneId: '12345', + referrer: 'http: //www.vuble.tv/', + floorPrice: 5 + }, + crumbs: { + pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' + } + }, + { + bidder: 'vertamedia', + params: { + aid: 331133 + }, + crumbs: { + pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' + } + } + ], + transactionId: 'df11a105-4eef-4ceb-bbc3-a49224f7c49d' + } + ], + adUnitCodes: [ + '/19968336/header-bid-tag-0', + '/19968336/header-bid-tag-1', + 'video' + ], + bidderRequests: [], + bidsReceived: [ + { + bidderCode: 'appnexus', + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '6de82e80757293', + mediaType: 'banner', + source: 'client', + requestId: '6de82e80757293', + cpm: 0.5, + creativeId: 96846035, + currency: 'USD', + netRevenue: true, + ttl: 300, + appnexus: { + buyerMemberId: 9325 + }, + ad: '...HTML CONTAINING THE AD...', + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + responseTimestamp: 1540560217636, + requestTimestamp: 1540560217403, + bidder: 'appnexus', + adUnitCode: '/19968336/header-bid-tag-1', + timeToRespond: 233, + pbLg: '0.50', + pbMg: '0.50', + pbHg: '0.50', + pbAg: '0.50', + pbDg: '0.50', + pbCg: '', + size: '728x90', + adserverTargeting: { + hb_bidder: 'appnexus', + hb_adid: '7e1a45d85bd57c', + hb_pb: '0.50', + hb_size: '728x90', + hb_source: 'client', + hb_format: 'banner' + } + } + ], + winningBids: [], + timeout: 3000 + }; + + const AUCTION_OBJECT_AFTER_AUCTION_END_MOCK = { + bidders: [ + { + id: 'vuble', + bids: [ + { + adomain: [ + '' + ], + clearPrice: 0, + impId: 'video', + price: 0, + status: 0 + } + ] + }, + { + id: 'vertamedia', + bids: [ + { + adomain: [ + '' + ], + clearPrice: 0, + impId: 'video', + price: 0, + status: 0 + } + ] + }, + { + id: 'appnexus', + bids: [ + { + adomain: [ + '' + ], + clearPrice: 0, + impId: '/19968336/header-bid-tag-0', + price: 0.5, + status: 0 + }, + { + adomain: [ + '' + ], + clearPrice: 0, + impId: '/19968336/header-bid-tag-1', + price: 0.7, + status: 0 + } + ] + } + ], + impressions: [] + }; + + const AUCTION_END_EVENT_WITH_BID_REQUESTS_AND_BID_RESPONSES_MOCK = { + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + auctionStart: 1540560217395, + auctionEnd: 1540560217703, + auctionStatus: 'completed', + adUnits: [], + adUnitCodes: [ + '/19968336/header-bid-tag-0', + '/19968336/header-bid-tag-1', + 'video' + ], + bidderRequests: [ + { + bidderCode: 'vuble', + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + bidderRequestId: '1bb11e055665bc', + bids: [ + { + bidder: 'vuble', + crumbs: { + pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' + }, + adUnitCode: 'video', + transactionId: 'df11a105-4eef-4ceb-bbc3-a49224f7c49d', + bidId: '2859b890da7418', + bidderRequestId: '1bb11e055665bc', + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + src: 'client', + bidRequestsCount: 1 + } + ], + auctionStart: 1540560217395, + timeout: 3000, + refererInfo: { + referer: 'http: //localhost: 8080/', + reachedTop: true, + numIframes: 0, + stack: [ + 'http://localhost:8080/' + ] + }, + start: 1540560217401, + doneCbCallCount: 0 + }, + { + bidderCode: 'vertamedia', + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + bidderRequestId: '3c2cbf7f1466cb', + bids: [ + { + bidder: 'vertamedia', + params: { + aid: 331133 + }, + crumbs: { + pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' + }, + adUnitCode: 'video', + transactionId: 'df11a105-4eef-4ceb-bbc3-a49224f7c49d', + bidId: '45b3ad5c2dc794', + bidderRequestId: '3c2cbf7f1466cb', + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + bidRequestsCount: 1 + } + ], + auctionStart: 1540560217395, + timeout: 3000, + start: 1540560217401 + }, + { + bidderCode: 'appnexus', + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + bidderRequestId: '5312eef4418cd7', + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 13144370 + }, + crumbs: { + pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' + }, + adUnitCode: '/19968336/header-bid-tag-0', + transactionId: 'aee9bf8d-6d8f-425b-a42a-52c875371ebc', + bidId: '6de82e80757293', + bidderRequestId: '5312eef4418cd7', + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + src: 'client', + bidRequestsCount: 1 + }, + { + bidder: 'appnexus', + params: { + placementId: 13144370 + }, + crumbs: { + pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' + }, + adUnitCode: '/19968336/header-bid-tag-1', + transactionId: '3d5f0f89-e9cd-4714-b314-3f0fb7fcf8e3', + bidId: '7e1a45d85bd57c', + bidderRequestId: '5312eef4418cd7', + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + src: 'client', + bidRequestsCount: 1 + } + ], + auctionStart: 1540560217395, + timeout: 3000, + start: 1540560217403, + doneCbCallCount: 0 + } + ], + bidsReceived: [ + { + bidderCode: 'appnexus', + adId: '6de82e80757293', + mediaType: 'banner', + source: 'client', + requestId: '6de82e80757293', + cpm: 0.5, + creativeId: 96846035, + appnexus: { + buyerMemberId: 9325 + }, + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + bidder: 'appnexus', + adUnitCode: '/19968336/header-bid-tag-0', + }, + { + bidderCode: 'appnexus', + adId: '7e1a45d85bd57c', + mediaType: 'banner', + source: 'client', + requestId: '7e1a45d85bd57c', + cpm: 0.7, + creativeId: 96846035, + appnexus: { + buyerMemberId: 9325 + }, + auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', + bidder: 'appnexus', + adUnitCode: '/19968336/header-bid-tag-1', + } + ], + winningBids: [], + timeout: 3000 + }; +}); From db24dea98f8fcbb4c92ca5e3f02b2f03de8f8425 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 6 Nov 2018 00:41:35 +0530 Subject: [PATCH 0813/1594] MarsMedia analytic adpater to use PREBID_GLOBAL than hard-coded pbjs (#3261) --- modules/marsmediaAnalyticsAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/marsmediaAnalyticsAdapter.js b/modules/marsmediaAnalyticsAdapter.js index 98c079ebff0..497078158e0 100644 --- a/modules/marsmediaAnalyticsAdapter.js +++ b/modules/marsmediaAnalyticsAdapter.js @@ -33,7 +33,7 @@ var marsmediaAnalyticsAdapter = Object.assign(adapter( success: function() {}, error: function() {} }, - JSON.stringify({act: 'prebid_analytics', params: events, 'pbjs': pbjs.getBidResponses(), ver: MARS_VERSION}), + JSON.stringify({act: 'prebid_analytics', params: events, 'pbjs': $$PREBID_GLOBAL$$.getBidResponses(), ver: MARS_VERSION}), { method: 'POST' } From 7fe95d89464cbc95adf3446cd8e39bb499f2c321 Mon Sep 17 00:00:00 2001 From: Js Date: Tue, 6 Nov 2018 15:38:16 +0100 Subject: [PATCH 0814/1594] On set targeting (#3203) * Add onSetTargeting method to bid adapter spec * Reset context before each criteo adapter test * Add a unit test to check spec.onTimeout() is called * Add a unit test to check spec.onBidWon() is called * Add a unit test to check spec.onSetTargeting() is called * Remove unused adUnits argument from callSetTargetingBidder * Add integration test on onSetTargeting * Move Bid status constants from targeting.js to constants.json * Make sure onSetTargeting won't be called when the bid is not in status BID_TARGETING_SET --- src/adaptermanager.js | 4 + src/auction.js | 5 + src/auctionManager.js | 5 + src/constants.json | 4 + src/prebid.js | 10 +- src/targeting.js | 6 +- test/spec/modules/criteoBidAdapter_spec.js | 4 + test/spec/unit/core/adapterManager_spec.js | 102 +++++++++++++++++++++ test/spec/unit/pbjs_api_spec.js | 61 ++++++++++-- 9 files changed, 185 insertions(+), 16 deletions(-) diff --git a/src/adaptermanager.js b/src/adaptermanager.js index c324bb72e6c..55aab710741 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -529,3 +529,7 @@ exports.callBidWonBidder = function(bidder, bid, adUnits) { bid.params = utils.getUserConfiguredParams(adUnits, bid.adUnitCode, bid.bidder); tryCallBidderMethod(bidder, 'onBidWon', bid); }; + +exports.callSetTargetingBidder = function(bidder, bid) { + tryCallBidderMethod(bidder, 'onSetTargeting', bid); +}; diff --git a/src/auction.js b/src/auction.js index 221cd519815..37b2c6896f2 100644 --- a/src/auction.js +++ b/src/auction.js @@ -290,11 +290,16 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) adaptermanager.callBidWonBidder(winningBid.bidder, winningBid, adUnits); } + function setBidTargeting(bid) { + adaptermanager.callSetTargetingBidder(bid.bidder, bid); + } + return { addBidReceived, executeCallback, callBids, addWinningBid, + setBidTargeting, getWinningBids: () => _winningBids, getTimeout: () => _timeout, getAuctionId: () => _auctionId, diff --git a/src/auctionManager.js b/src/auctionManager.js index e19a80e5e02..389cac31fe3 100644 --- a/src/auctionManager.js +++ b/src/auctionManager.js @@ -91,6 +91,11 @@ export function newAuctionManager() { auctionManager.setStatusForBids = function(adId, status) { let bid = auctionManager.findBidByAdId(adId); if (bid) bid.status = status; + + if (bid && status === CONSTANTS.BID_STATUS.BID_TARGETING_SET) { + const auction = find(_auctions, auction => auction.getAuctionId() === bid.auctionId); + if (auction) auction.setBidTargeting(bid); + } } function _addAuction(auction) { diff --git a/src/constants.json b/src/constants.json index 9ec51e4047b..7c06db48469 100644 --- a/src/constants.json +++ b/src/constants.json @@ -77,5 +77,9 @@ "SRC" : "s2s", "DEFAULT_ENDPOINT" : "https://prebid.adnxs.com/pbs/v1/openrtb2/auction", "SYNCED_BIDDERS_KEY": "pbjsSyncs" + }, + "BID_STATUS" : { + "BID_TARGETING_SET": "targetingSet", + "RENDERED": "rendered" } } diff --git a/src/prebid.js b/src/prebid.js index 61c5421c0d3..0460b99bbb0 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -7,7 +7,7 @@ import { userSync } from 'src/userSync.js'; import { loadScript } from './adloader'; import { config } from './config'; import { auctionManager } from './auctionManager'; -import { targeting, getHighestCpmBidsFromBidPool, RENDERED, BID_TARGETING_SET } from './targeting'; +import { targeting, getHighestCpmBidsFromBidPool } from './targeting'; import { createHook } from 'src/hook'; import { sessionLoader } from 'src/debugging'; import includes from 'core-js/library/fn/array/includes'; @@ -180,7 +180,7 @@ $$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit, customSlotMatching Object.keys(targetingSet).forEach((adUnitCode) => { Object.keys(targetingSet[adUnitCode]).forEach((targetingKey) => { if (targetingKey === 'hb_adid') { - auctionManager.setStatusForBids(targetingSet[adUnitCode][targetingKey], BID_TARGETING_SET); + auctionManager.setStatusForBids(targetingSet[adUnitCode][targetingKey], CONSTANTS.BID_STATUS.BID_TARGETING_SET); } }); }); @@ -234,7 +234,7 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { // lookup ad by ad Id const bid = auctionManager.findBidByAdId(id); if (bid) { - bid.status = RENDERED; + bid.status = CONSTANTS.BID_STATUS.RENDERED; // replace macros according to openRTB with price paid = bid.cpm bid.ad = utils.replaceAuctionPrice(bid.ad, bid.cpm); bid.adUrl = utils.replaceAuctionPrice(bid.adUrl, bid.cpm); @@ -584,7 +584,7 @@ $$PREBID_GLOBAL$$.getAllWinningBids = function () { */ $$PREBID_GLOBAL$$.getAllPrebidWinningBids = function () { return auctionManager.getBidsReceived() - .filter(bid => bid.status === BID_TARGETING_SET) + .filter(bid => bid.status === CONSTANTS.BID_STATUS.BID_TARGETING_SET) .map(removeRequestId); }; @@ -624,7 +624,7 @@ $$PREBID_GLOBAL$$.markWinningBidAsUsed = function (markBidRequest) { } if (bids.length > 0) { - bids[0].status = RENDERED; + bids[0].status = CONSTANTS.BID_STATUS.RENDERED; } }; diff --git a/src/targeting.js b/src/targeting.js index 30407994b8e..0fb482c3377 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -10,9 +10,6 @@ var CONSTANTS = require('./constants.json'); var pbTargetingKeys = []; -export const BID_TARGETING_SET = 'targetingSet'; -export const RENDERED = 'rendered'; - const MAX_DFP_KEYLENGTH = 20; const TTL_BUFFER = 1000; @@ -24,7 +21,7 @@ export const TARGETING_KEYS = Object.keys(CONSTANTS.TARGETING_KEYS).map( export const isBidNotExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 + TTL_BUFFER) > timestamp(); // return bids whose status is not set. Winning bid can have status `targetingSet` or `rendered`. -const isUnusedBid = (bid) => bid && ((bid.status && !includes([BID_TARGETING_SET, RENDERED], bid.status)) || !bid.status); +const isUnusedBid = (bid) => bid && ((bid.status && !includes([CONSTANTS.BID_STATUS.BID_TARGETING_SET, CONSTANTS.BID_STATUS.RENDERED], bid.status)) || !bid.status); // If two bids are found for same adUnitCode, we will use the highest one to take part in auction // This can happen in case of concurrent auctions @@ -205,7 +202,6 @@ export function newTargeting(auctionManager) { */ targeting.getWinningBids = function(adUnitCode, bidsReceived = getBidsReceived()) { const adUnitCodes = getAdUnitCodes(adUnitCode); - return bidsReceived .filter(bid => includes(adUnitCodes, bid.adUnitCode)) .filter(bid => bid.cpm > 0) diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index d124ebf3709..6dbf51932a0 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -3,6 +3,10 @@ import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter'; import * as utils from 'src/utils'; describe('The Criteo bidding adapter', function () { + beforeEach(function () { + // Remove FastBid to avoid side effects. + localStorage.removeItem('criteo_fast_bid'); + }); describe('isBidRequestValid', function () { it('should return false when given an invalid bid', function () { const bid = { diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index bde5f234ffb..a7b25d2524d 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -134,6 +134,108 @@ describe('adapterManager tests', function () { }); }); + describe('callTimedOutBidders', function () { + var criteoSpec = { onTimeout: sinon.stub() } + var criteoAdapter = { + bidder: 'criteo', + getSpec: function() { return criteoSpec; } + } + before(function () { + config.setConfig({s2sConfig: { enabled: false }}); + }); + + beforeEach(function () { + AdapterManager.bidderRegistry['criteo'] = criteoAdapter; + }); + + afterEach(function () { + delete AdapterManager.bidderRegistry['criteo']; + }); + + it('should call spec\'s onTimeout callback when callTimedOutBidders is called', function () { + const adUnits = [{ + code: 'adUnit-code', + sizes: [[728, 90]], + bids: [ + {bidder: 'criteo', params: {placementId: 'id'}}, + ] + }]; + const timedOutBidders = [{ + bidId: 'bidId', + bidder: 'criteo', + adUnitCode: adUnits[0].code, + auctionId: 'auctionId', + }]; + AdapterManager.callTimedOutBidders(adUnits, timedOutBidders, CONFIG.timeout); + sinon.assert.called(criteoSpec.onTimeout); + }); + }); // end callTimedOutBidders + + describe('onBidWon', function () { + var criteoSpec = { onBidWon: sinon.stub() } + var criteoAdapter = { + bidder: 'criteo', + getSpec: function() { return criteoSpec; } + } + before(function () { + config.setConfig({s2sConfig: { enabled: false }}); + }); + + beforeEach(function () { + AdapterManager.bidderRegistry['criteo'] = criteoAdapter; + }); + + afterEach(function () { + delete AdapterManager.bidderRegistry['criteo']; + }); + + it('should call spec\'s onBidWon callback when a bid is won', function () { + const bids = [ + {bidder: 'criteo', params: {placementId: 'id'}}, + ]; + const adUnits = [{ + code: 'adUnit-code', + sizes: [[728, 90]], + bids + }]; + + AdapterManager.callBidWonBidder(bids[0].bidder, bids[0], adUnits); + sinon.assert.called(criteoSpec.onBidWon); + }); + }); // end onBidWon + + describe('onSetTargeting', function () { + var criteoSpec = { onSetTargeting: sinon.stub() } + var criteoAdapter = { + bidder: 'criteo', + getSpec: function() { return criteoSpec; } + } + before(function () { + config.setConfig({s2sConfig: { enabled: false }}); + }); + + beforeEach(function () { + AdapterManager.bidderRegistry['criteo'] = criteoAdapter; + }); + + afterEach(function () { + delete AdapterManager.bidderRegistry['criteo']; + }); + + it('should call spec\'s onSetTargeting callback when setTargeting is called', function () { + const bids = [ + {bidder: 'criteo', params: {placementId: 'id'}}, + ]; + const adUnits = [{ + code: 'adUnit-code', + sizes: [[728, 90]], + bids + }]; + AdapterManager.callSetTargetingBidder(bids[0].bidder, bids[0], adUnits); + sinon.assert.called(criteoSpec.onSetTargeting); + }); + }); // end onSetTargeting + describe('S2S tests', function () { beforeEach(function () { config.setConfig({s2sConfig: CONFIG}); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 215bf2cd757..e19f40c4644 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -9,7 +9,7 @@ import { createBidReceived } from 'test/fixtures/fixtures'; import { auctionManager, newAuctionManager } from 'src/auctionManager'; -import { targeting, newTargeting, RENDERED } from 'src/targeting'; +import { targeting, newTargeting } from 'src/targeting'; import { config as configObj } from 'src/config'; import * as ajaxLib from 'src/ajax'; import * as auctionModule from 'src/auction'; @@ -1165,7 +1165,8 @@ describe('Unit: Prebid Module', function () { isBidRequestValid: sinon.stub(), buildRequests: sinon.stub(), interpretResponse: sinon.stub(), - getUserSyncs: sinon.stub() + getUserSyncs: sinon.stub(), + onTimeout: sinon.stub() }; registerBidder(spec); @@ -1190,6 +1191,54 @@ describe('Unit: Prebid Module', function () { expect(bidsBackHandlerStub.getCall(0).args[1]).to.equal(true, 'bidsBackHandler should be called with timedOut=true'); + + sinon.assert.called(spec.onTimeout); + }); + + it('should execute callback after setTargeting', function () { + let spec = { + code: BIDDER_CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + onSetTargeting: sinon.stub() + }; + + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + + const bidId = 1; + const auctionId = 1; + let adResponse = Object.assign({ + auctionId: auctionId, + adId: String(bidId), + width: 300, + height: 250, + adUnitCode: bidRequests[0].bids[0].adUnitCode, + adserverTargeting: { + 'hb_bidder': BIDDER_CODE, + 'hb_adid': bidId, + 'hb_pb': bids[0].cpm, + 'hb_size': '300x250', + }, + bidder: bids[0].bidderCode, + }, bids[0]); + auction.getBidsReceived = function() { return [adResponse]; } + auction.getAuctionId = () => auctionId; + + clock = sinon.useFakeTimers(); + let requestObj = { + bidsBackHandler: null, // does not need to be defined because of newAuction mock in beforeEach + timeout: 2000, + adUnits: adUnits + }; + + $$PREBID_GLOBAL$$.requestBids(requestObj); + $$PREBID_GLOBAL$$.setTargetingForGPTAsync(); + + sinon.assert.called(spec.onSetTargeting); }); }) @@ -1885,7 +1934,7 @@ describe('Unit: Prebid Module', function () { const markedBid = find($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode).bids, bid => bid.adId === winningBid.adId); - expect(markedBid.status).to.equal(RENDERED); + expect(markedBid.status).to.equal(CONSTANTS.BID_STATUS.RENDERED); resetAuction(); }); @@ -1899,7 +1948,7 @@ describe('Unit: Prebid Module', function () { const markedBid = find($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode).bids, bid => bid.adId === winningBid.adId); - expect(markedBid.status).to.not.equal(RENDERED); + expect(markedBid.status).to.not.equal(CONSTANTS.BID_STATUS.RENDERED); resetAuction(); }); @@ -1915,7 +1964,7 @@ describe('Unit: Prebid Module', function () { const markedBid = find($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode).bids, bid => bid.adId === winningBid.adId); - expect(markedBid.status).to.equal(RENDERED); + expect(markedBid.status).to.equal(CONSTANTS.BID_STATUS.RENDERED); resetAuction(); }); @@ -1931,7 +1980,7 @@ describe('Unit: Prebid Module', function () { const markedBid = find($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode).bids, bid => bid.adId === winningBid.adId); - expect(markedBid.status).to.equal(RENDERED); + expect(markedBid.status).to.equal(CONSTANTS.BID_STATUS.RENDERED); resetAuction(); }); }); From 01e6718bc6394c828e6fef92fed416dab92ba31f Mon Sep 17 00:00:00 2001 From: skazedo Date: Tue, 6 Nov 2018 09:51:14 -0500 Subject: [PATCH 0815/1594] Added trackers in ZEDO adapter (#3240) * initial commit * updated contact and tag details * changes ti support the renderers * changes to pass dimId * fixed names of internal mapping * added comment * added gdpr param to request and other fixes * modified api url * fix * fixed the secure api call * rolled back video event callback till we support it * updated doc with video details * added bid won and timeout pixel * added testcase for bid events * modified testcase * fixed the url logged --- modules/zedoBidAdapter.js | 56 +++++++++++++++- test/spec/modules/zedoBidAdapter_spec.js | 82 ++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/modules/zedoBidAdapter.js b/modules/zedoBidAdapter.js index 970f28e47d5..c21b55b88a2 100644 --- a/modules/zedoBidAdapter.js +++ b/modules/zedoBidAdapter.js @@ -3,6 +3,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { BANNER, VIDEO } from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import { Renderer } from 'src/Renderer'; +import * as url from 'src/url'; const BIDDER_CODE = 'zedo'; const URL = '//z2.zedo.com/asw/fmh.json'; @@ -22,6 +23,8 @@ const DIM_TYPE = { '103': 'display' // '85': 'pre-mid-post-roll', }; +const EVENT_PIXEL_URL = 'm1.zedo.com/log/p.gif'; +const SECURE_EVENT_PIXEL_URL = 'tt1.zedo.com/log/p.gif'; export const spec = { code: BIDDER_CODE, @@ -137,7 +140,23 @@ export const spec = { url: url }]; } - } + }, + + onTimeout: function (timeoutData) { + try { + logEvent('117', timeoutData); + } catch (e) { + utils.logError(e); + } + }, + + onBidWon: function (bid) { + try { + logEvent('116', [bid]); + } catch (e) { + utils.logError(e); + } + }, }; function getCreative(ad) { @@ -251,4 +270,39 @@ function parseMediaType(creativeBid) { } } +function logEvent(eid, data) { + let getParams = { + protocol: utils.getTopWindowLocation().protocol === 'http:' ? 'http' : 'https', + hostname: utils.getTopWindowLocation().protocol === 'http:' ? EVENT_PIXEL_URL : SECURE_EVENT_PIXEL_URL, + search: getLoggingData(eid, data) + }; + utils.triggerPixel(url.format(getParams).replace(/&/g, ';')); +} + +function getLoggingData(eid, data) { + data = (utils.isArray(data) && data) || []; + + let params = {}; + let channel, network, dim, adunitCode, timeToRespond, cpm; + data.map((adunit) => { + adunitCode = adunit.adUnitCode; + channel = utils.deepAccess(adunit, 'params.0.channelCode') || 0; + network = channel > 0 ? parseInt(channel / 1000000) : 0; + dim = utils.deepAccess(adunit, 'params.0.dimId') * 256 || 0; + timeToRespond = adunit.timeout ? adunit.timeout : adunit.timeToRespond; + cpm = adunit.cpm; + }); + params.n = network; + params.c = channel; + params.s = '0'; + params.x = dim; + params.ai = encodeURI('Prebid^zedo^' + adunitCode + '^' + cpm + '^' + timeToRespond); + params.pu = encodeURI(utils.getTopWindowUrl()) || ''; + params.eid = eid; + params.e = 'e'; + params.z = Math.random(); + + return params; +} + registerBidder(spec); diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js index 93e65602984..8e6578d9b2c 100644 --- a/test/spec/modules/zedoBidAdapter_spec.js +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -268,4 +268,86 @@ describe('The ZEDO bidding adapter', function () { expect(syncs[0].url).to.contains('gdpr=0'); }); }); + + describe('bid events', function () { + it('should trigger a win pixel', function () { + const bid = { + 'bidderCode': 'zedo', + 'width': '300', + 'height': '250', + 'statusMessage': 'Bid available', + 'adId': '148018fe5e', + 'cpm': 0.5, + 'ad': 'dummy data', + 'ad_id': '12345', + 'sizeId': '15', + 'adResponse': + { + 'creatives': [ + { + 'adId': '12345', + 'height': '480', + 'width': '640', + 'isFoc': true, + 'creativeDetails': { + 'type': 'VAST', + 'adContent': '' + }, + 'seeder': { + 'network': 1234, + 'servedChan': 1234567, + }, + 'cpm': '1200000', + 'servedChan': 1234, + }] + }, + 'params': [{ + 'channelCode': '123456', + 'dimId': '85' + }], + 'requestTimestamp': 1540401686, + 'responseTimestamp': 1540401687, + 'timeToRespond': 6253, + 'pbLg': '0.50', + 'pbMg': '0.50', + 'pbHg': '0.53', + 'adUnitCode': '/123456/header-bid-tag-0', + 'bidder': 'zedo', + 'size': '300x250', + 'adserverTargeting': { + 'hb_bidder': 'zedo', + 'hb_adid': '148018fe5e', + 'hb_pb': '10.00', + } + }; + spec.onBidWon(bid); + spec.onTimeout(bid); + }); + it('should trigger a timeout pixel', function () { + const bid = { + 'bidderCode': 'zedo', + 'width': '300', + 'height': '250', + 'statusMessage': 'Bid available', + 'adId': '148018fe5e', + 'cpm': 0.5, + 'ad': 'dummy data', + 'ad_id': '12345', + 'sizeId': '15', + 'params': [{ + 'channelCode': '123456', + 'dimId': '85' + }], + 'timeout': 1, + 'requestTimestamp': 1540401686, + 'responseTimestamp': 1540401687, + 'timeToRespond': 6253, + 'adUnitCode': '/123456/header-bid-tag-0', + 'bidder': 'zedo', + 'size': '300x250', + }; + spec.onBidWon(bid); + spec.onTimeout(bid); + }); + }); }); From 0d5ea4b5ec4522957ac71dd9afa9d1885437b46e Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 6 Nov 2018 10:36:45 -0800 Subject: [PATCH 0816/1594] Rubicon analytics site zone (#3242) * Adding site and zone ids to adunit and bidwon levels to improve reporting * Updating tests to account for new addition of site and zone * Indexof !== -1 rather than >= 0 * Removing Unnecessary check + schema update * Adding toUpperCase when comparing currency - Found an adapter which uses lowercase --- modules/rubiconAnalyticsAdapter.js | 37 ++++++++++++++++++- .../modules/rubiconAnalyticsAdapter_spec.js | 14 ++++--- test/spec/modules/rubiconAnalyticsSchema.json | 22 ++++++++++- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index 613cc703eb9..e952eec36a8 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -131,6 +131,8 @@ function sendMessage(auctionId, bidWonId) { adserverTargeting: stringProperties(cache.targeting[bid.adUnit.adUnitCode] || {}), bidwonStatus: 'success', // hard-coded for now accountId, + siteId: bid.siteId, + zoneId: bid.zoneId, samplingFactor }); } @@ -157,6 +159,15 @@ function sendMessage(auctionId, bidWonId) { adUnit.bids = []; } + // 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 (utils.deepAccess(bid, 'params.accountId') == accountId) { + adUnit.accountId = parseInt(accountId); + adUnit.siteId = parseInt(utils.deepAccess(bid, 'params.siteId')); + adUnit.zoneId = parseInt(utils.deepAccess(bid, 'params.zoneId')); + } + } + if (bid.videoAdFormat && !adUnit.videoAdFormat) { adUnit.videoAdFormat = bid.videoAdFormat; } @@ -172,6 +183,13 @@ function sendMessage(auctionId, bidWonId) { return adUnits; }, {}); + // We need to mark each cached bid response with its appropriate rubicon site-zone id + // 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'])); + }); + let auction = { clientTimeoutMillis: auctionCache.timeout, samplingFactor, @@ -217,7 +235,7 @@ function sendMessage(auctionId, bidWonId) { function parseBidResponse(bid) { return _pick(bid, [ 'getCpmInNewCurrency as bidPriceUSD', (fn) => { - if (bid.currency === 'USD') { + if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === 'USD') { return Number(bid.cpm); } // use currency conversion function if present @@ -238,6 +256,21 @@ function parseBidResponse(bid) { let samplingFactor = 1; let accountId; +// List of known rubicon aliases +// This gets updated on auction init to account for any custom aliases present +let rubiconAliases = ['rubicon']; + +/* + Checks the alias registry for any entries of the rubicon bid adapter. + adds to the rubiconAliases list if found +*/ +function setRubiconAliases(aliasRegistry) { + Object.keys(aliasRegistry).forEach(function (alias) { + if (aliasRegistry[alias] === 'rubicon') { + rubiconAliases.push(alias); + } + }); +} let baseAdapter = adapter({analyticsType: 'endpoint'}); let rubiconAdapter = Object.assign({}, baseAdapter, { @@ -288,6 +321,8 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { track({eventType, args}) { switch (eventType) { case AUCTION_INIT: + // set the rubicon aliases + setRubiconAliases(adaptermanager.aliasRegistry); let cacheEntry = _pick(args, [ 'timestamp', 'timeout' diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 97737675325..c67c73bd280 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -146,7 +146,6 @@ const MOCK = { 'bidRequestsCount': 1 } ], - 'auctionStart': 1519767010567, 'timeout': 3000, 'refererInfo': { 'referer': 'http://www.test.com/page.html', 'reachedTop': true, 'numIframes': 0, 'stack': ['http://www.test.com/page.html'] @@ -168,7 +167,7 @@ const MOCK = { { 'bidder': 'rubicon', 'params': { - 'accountId': '14062', + 'accountId': '1001', 'siteId': '70608', 'zoneId': '335918', 'userId': '12346', @@ -286,6 +285,9 @@ const ANALYTICS_MESSAGE = { } ], 'status': 'success', + 'accountId': 1001, + 'siteId': 70608, + 'zoneId': 335918, 'adserverTargeting': { 'hb_bidder': 'rubicon', 'hb_adid': '2ecff0db240757', @@ -301,7 +303,7 @@ const ANALYTICS_MESSAGE = { 'source': 'client', 'clientLatencyMillis': 3214, 'params': { - 'accountId': '14062', + 'accountId': '1001', 'siteId': '70608', 'zoneId': '335918' }, @@ -382,8 +384,10 @@ const ANALYTICS_MESSAGE = { 'clientLatencyMillis': 3214, 'samplingFactor': 1, 'accountId': 1001, + 'siteId': 70608, + 'zoneId': 335918, 'params': { - 'accountId': '14062', + 'accountId': '1001', 'siteId': '70608', 'zoneId': '335918' }, @@ -621,7 +625,7 @@ describe('rubicon analytics adapter', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', - accountId: '1001' + accountId: 1001 } }); }); diff --git a/test/spec/modules/rubiconAnalyticsSchema.json b/test/spec/modules/rubiconAnalyticsSchema.json index cc4ad20db19..b16b6a01ed8 100644 --- a/test/spec/modules/rubiconAnalyticsSchema.json +++ b/test/spec/modules/rubiconAnalyticsSchema.json @@ -113,6 +113,18 @@ "items": { "$ref": "#/definitions/bid" } + }, + "accountId": { + "type": "number", + "description": "The Rubicon AccountId associated with this adUnit - Removed if null" + }, + "siteId": { + "type": "number", + "description": "The Rubicon siteId associated with this adUnit - Removed if null" + }, + "zoneId": { + "type": "number", + "description": "The Rubicon zoneId associated with this adUnit - Removed if null" } } } @@ -166,6 +178,14 @@ "success", "error" ] + }, + "siteId": { + "type": "number", + "description": "The Rubicon siteId associated with this adUnit - Removed if null" + }, + "zoneId": { + "type": "number", + "description": "The Rubicon zoneId associated with this adUnit - Removed if null" } } } @@ -354,4 +374,4 @@ } } } -} +} \ No newline at end of file From 3b541a3df2c7ee2ecd26e4328522e0fe875db87e Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 7 Nov 2018 05:46:18 +1100 Subject: [PATCH 0817/1594] Multi currency (#3250) * corrected user sync type * add support to multiple currencies * push package-lock * remove package lock * restore packagelock.json --- modules/playgroundxyzBidAdapter.js | 8 +++++--- test/spec/modules/playgroundxyzBidAdapter_spec.js | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/playgroundxyzBidAdapter.js b/modules/playgroundxyzBidAdapter.js index f6a85b6522e..a031b8850e5 100644 --- a/modules/playgroundxyzBidAdapter.js +++ b/modules/playgroundxyzBidAdapter.js @@ -4,6 +4,7 @@ import { BANNER } from 'src/mediaTypes'; const BIDDER_CODE = 'playgroundxyz'; const URL = 'https://ads.playground.xyz/host-config/prebid?v=2'; +const DEFAULT_CURRENCY = 'USD'; export const spec = { code: BIDDER_CODE, @@ -86,11 +87,12 @@ export const spec = { return bids; } + const currency = serverResponse.cur || DEFAULT_CURRENCY; serverResponse.seatbid.forEach(sBid => { if (sBid.hasOwnProperty('bid')) { sBid.bid.forEach(iBid => { if (iBid.price !== 0) { - const bid = newBid(iBid); + const bid = newBid(iBid, currency); bids.push(bid); } }); @@ -115,7 +117,7 @@ export const spec = { } } -function newBid(bid) { +function newBid(bid, currency) { return { requestId: bid.impid, mediaType: BANNER, @@ -126,7 +128,7 @@ function newBid(bid) { height: bid.h, ttl: 300, netRevenue: true, - currency: 'USD', + currency: currency, }; } diff --git a/test/spec/modules/playgroundxyzBidAdapter_spec.js b/test/spec/modules/playgroundxyzBidAdapter_spec.js index 92f88092e5d..fc430bfb31b 100644 --- a/test/spec/modules/playgroundxyzBidAdapter_spec.js +++ b/test/spec/modules/playgroundxyzBidAdapter_spec.js @@ -102,7 +102,7 @@ describe('playgroundxyzBidAdapter', function () { 'seat': '4321' }], 'bidid': '6894227111893743356', - 'cur': 'USD' + 'cur': 'AUD' }; let bidderRequest = { @@ -119,7 +119,7 @@ describe('playgroundxyzBidAdapter', function () { 'height': 50, 'ad': '', 'mediaType': 'banner', - 'currency': 'USD', + 'currency': 'AUD', 'ttl': 300, 'netRevenue': true } From 41537889949bcf2449a446b03079f417d6769874 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 6 Nov 2018 10:58:21 -0800 Subject: [PATCH 0818/1594] Altering logic to determine if is video bid or not + update tests (#3263) * Altering logic to determine if is video bid or not + update tests * Browser compatible int check * Spelling error fix (deprecated) * fixing suggestion by isaac --- modules/rubiconBidAdapter.js | 78 +++++++++++++-------- test/spec/modules/rubiconBidAdapter_spec.js | 67 ++++++++++++++---- 2 files changed, 103 insertions(+), 42 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 20175ceb550..415027ef500 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -132,7 +132,7 @@ export const spec = { name: bidRequest.adUnitCode, width: size[0], height: size[1], - size_id: utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}.context`) === 'outstream' ? 203 : params.video.size_id + size_id: determineRubiconVideoSizeId(bidRequest) }; if (params.video) { @@ -573,12 +573,12 @@ function mapSizes(sizes) { /** * Test if bid has mediaType or mediaTypes set for video. - * note: 'mediaType' has been deprecated, however support will remain for a transitional period + * Also makes sure the video object is present in the rubicon bidder params * @param {BidRequest} bidRequest * @returns {boolean} */ export function hasVideoMediaType(bidRequest) { - if (typeof utils.deepAccess(bidRequest, 'params.video') === 'undefined' && Array.isArray(utils.deepAccess(bidRequest, 'params.sizes'))) { + if (typeof utils.deepAccess(bidRequest, 'params.video') !== 'object') { return false; } return (bidRequest.mediaType === VIDEO || typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'); @@ -591,43 +591,54 @@ export function hasVideoMediaType(bidRequest) { * @returns {string|undefined} Returns 'video' or 'banner' if resolves to a type, or undefined otherwise (invalid). */ function bidType(bid, log = false) { - let validVideo; + // Is it considered video ad unit by rubicon if (hasVideoMediaType(bid)) { - validVideo = true; - - if (utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'instream' || bid.mediaType === VIDEO) { - if (typeof utils.deepAccess(bid, 'params.video.size_id') === 'undefined') { + // legacy mediaType or the new mediaTypes + // this is the preffered "new" way to define mediaTypes + if (typeof utils.deepAccess(bid, `mediaTypes.${VIDEO}`) !== 'undefined') { + // We require either context as instream or outstream + if (['outstream', 'instream'].indexOf(utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`)) === -1) { if (log) { - utils.logError('Rubicon bid adapter Error: size id is missing for instream video request.'); + utils.logError('Rubicon bid adapter requires mediaTypes.video.context to be one of outstream or instream'); } - validVideo = false; + return; + } + } else { // Otherwise its the legacy way where mediaType == 'video' + if (log) { + utils.logWarn('Rubicon video bid requested using legacy `adUnit.mediaType = `video``\nThis is deprecated\nPlease move towards the PBJS standard using mediaTypes object!'); } - } else if (utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream') { - if (utils.deepAccess(bid, 'params.video.size_id') !== 203) { + if (isNaN(parseInt(utils.deepAccess(bid, 'params.video.size_id')))) { if (log) { - utils.logWarn('Rubicon bid adapter Warning: outstream video is sending invalid size id, converting size id to 203.'); + utils.logError('Rubicon bid adapter needs params.video.size_id to be declared and an integer in order to process a legacy video request using mediaType == video'); } + return; } - } else { + } + // 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) { - utils.logError('Rubicon bid adapter Error: no instream or outstream context defined in mediaTypes.'); + utils.logError('Rubicon bid adapter could not determine the playerSize of the video\nplayerWidth and playerHeight are inferred from one of params.playerWidth/playerHeight or mediaTypes.video.playerSize or adUnit.sizes, in that order'); } - validVideo = false; + return; } - if (validVideo) { - if (typeof utils.deepAccess(bid, `mediaTypes.${BANNER}`) !== 'undefined') { - if (log) { - utils.logWarn('Rubicon bid adapter Warning: video and banner requested for same adUnit, continuing with video request, multi-format request is not supported by rubicon yet.'); - } + + if (log) { + utils.logMessage('Rubicon bid adapter making video request for adUnit', bid.adUnitCode); + } + return 'video'; + } else { + // we require banner sizes to come from one of params.sizes or mediaTypes.banner.sizes or adUnit.sizes, in that order + // if we cannot determine them, we reject it! + if (parseSizes(bid, 'banner').length === 0) { + if (log) { + utils.logError('Rubicon bid adapter could not determine the sizes for a banner request\nThey are inferred from one of params.sizes or mediaTypes.banner.sizes or adUnit.sizes, in that order'); } - return 'video'; - } else if (typeof utils.deepAccess(bid, `mediaTypes.${BANNER}`) === 'undefined') { - return undefined; + return; } - } - if (parseSizes(bid, 'banner').length > 0) { - if (log && validVideo === false) { - utils.logWarn('Rubicon bid adapter Warning: invalid video requested for adUnit, continuing with banner request.'); + + // everything looks good for banner so lets do it + if (log) { + utils.logMessage('Rubicon bid adapter making banner request for adUnit', bid.adUnitCode); } return 'banner'; } @@ -656,6 +667,17 @@ export function masSizeOrdering(sizes) { }); } +export function determineRubiconVideoSizeId(bid) { + // If we have size_id in the bid then use it + 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 utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream' ? 203 : 201; +} + var hasSynced = false; export function resetUserSync() { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 9988d983bf9..282a8a2c369 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1312,8 +1312,13 @@ describe('the rubicon adapter', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should not validate bid request when a invalid video object and no banner object is passed in', function () { - createVideoBidderRequestNoVideo(); + it('should not validate bid request when a params.video object is present but no context instream or outstream is passed in', function () { + let bid = bidderRequest.bids[0]; + bid.mediaTypes = { + video: {} + } + bid.params.video = {}; + sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 ); @@ -1321,20 +1326,23 @@ describe('the rubicon adapter', function () { const bidRequestCopy = clone(bidderRequest.bids[0]); expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - bidRequestCopy.params.video = {}; + bidRequestCopy.params.video = {sizeId: 201}; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - bidRequestCopy.params.video = undefined; + bidRequestCopy.mediaTypes.video = {context: undefined}; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - bidRequestCopy.params.video = 123; + bidRequestCopy.mediaTypes.video = {context: ''}; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - bidRequestCopy.params.video = {size_id: undefined}; + bidRequestCopy.mediaTypes.video = {context: 'random'}; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - delete bidRequestCopy.params.video; - expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); + bidRequestCopy.mediaTypes.video = {context: 'instream'}; + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(true); + + bidRequestCopy.mediaTypes.video = {context: 'outstream'}; + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(true); }); it('should not validate bid request when an invalid video object is passed in with legacy config mediaType', function () { @@ -1344,19 +1352,20 @@ describe('the rubicon adapter', function () { ); const bidderRequestCopy = clone(bidderRequest); - expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); - bidderRequestCopy.bids[0].params.video = {}; expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); - bidderRequestCopy.bids[0].params.video = undefined; + bidderRequestCopy.bids[0].params.video = {size_id: undefined}; expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); - bidderRequestCopy.bids[0].params.video = NaN; + bidderRequestCopy.bids[0].params.video = {size_id: 'size'}; expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); - delete bidderRequestCopy.bids[0].params.video; - expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + bidderRequestCopy.bids[0].params.video = {size_id: '201'}; + expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(true); + + bidderRequestCopy.bids[0].params.video = {size_id: 201}; + expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(true); }); it('bid request is valid when video context is outstream', function () { @@ -1372,6 +1381,36 @@ describe('the rubicon adapter', function () { expect(request.data.slots[0].size_id).to.equal(203); }); + it('should send banner request when outstream or instream video included but no rubicon video obect is present', function () { + let bid = bidderRequest.bids[0]; + // add banner and video mediaTypes + bidderRequest.mediaTypes = { + banner: { + sizes: [[300, 250]] + }, + video: { + context: 'outstream' + } + }; + // no video object in rubicon params, so we should see one call made for banner + + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + + let requests = spec.buildRequests(bidderRequest.bids, bidderRequest); + + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal(FASTLANE_ENDPOINT); + + bidderRequest.mediaTypes.video.context = 'instream'; + + requests = spec.buildRequests(bidderRequest.bids, bidderRequest); + + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal(FASTLANE_ENDPOINT); + }); + it('should send request as banner when invalid video bid in multiple mediaType bidRequest', function () { createVideoBidderRequestNoVideo(); From 6456231ec7d8d1e5c85fc514bf4a405edfbcbb3a Mon Sep 17 00:00:00 2001 From: Sergey A Rudakov Date: Tue, 6 Nov 2018 11:01:25 -0800 Subject: [PATCH 0819/1594] COX COMET Bid adapter removed (#3260) removed bid adapter for COX COMET (coxmt.com) --- modules/coxBidAdapter.js | 165 ----------------- modules/coxBidAdapter.md | 41 ----- test/spec/modules/coxBidAdapter_spec.js | 233 ------------------------ 3 files changed, 439 deletions(-) delete mode 100644 modules/coxBidAdapter.js delete mode 100644 modules/coxBidAdapter.md delete mode 100644 test/spec/modules/coxBidAdapter_spec.js diff --git a/modules/coxBidAdapter.js b/modules/coxBidAdapter.js deleted file mode 100644 index eac1b2081d2..00000000000 --- a/modules/coxBidAdapter.js +++ /dev/null @@ -1,165 +0,0 @@ -'use strict'; - -import * as utils from 'src/utils'; -import { BANNER } from 'src/mediaTypes'; -import { config } from 'src/config'; -import { registerBidder } from 'src/adapters/bidderFactory'; - -const helper = (() => { - let srTestCapabilities = () => { // Legacy - let plugins = navigator.plugins; - let flashVer = -1; - let sf = 'Shockwave Flash'; - - if (plugins && plugins.length > 0) { - if (plugins[sf + ' 2.0'] || plugins[sf]) { - var swVer2 = plugins[sf + ' 2.0'] ? ' 2.0' : ''; - var flashDescription = plugins[sf + swVer2].description; - flashVer = flashDescription.split(' ')[2].split('.')[0]; - } - } - if (flashVer > 4) return 15; else return 7; - }; - - let getRand = () => { - return Math.round(Math.random() * 100000000); - }; - - return { - ingest: function(rawBids = []) { - const adZoneAttributeKeys = ['id', 'size', 'thirdPartyClickUrl', 'dealId']; - const otherKeys = ['siteId', 'wrapper', 'referrerUrl']; - let state = this.createState(); - - rawBids.forEach(oneBid => { - let params = oneBid.params || {}; - - state.tag.auctionId = oneBid.auctionId; - state.tag.responseJSON = true; - - if (params.id && (/^\d+x\d+$/).test(params.size)) { - let adZoneKey = 'as' + params.id; - let zone = {}; - - zone.transactionId = oneBid.transactionId; - zone.bidId = oneBid.bidId; - state.tag.zones = state.tag.zones || {}; - state.tag.zones[adZoneKey] = zone; - - adZoneAttributeKeys.forEach(key => { if (params[key]) zone[key] = params[key]; }); - otherKeys.forEach(key => { if (params[key]) state.tag[key] = params[key]; }); - - // Check for an environment setting - if (params.env) state.env = params.env; - - // Update the placement map - let [x, y] = (params.size).split('x'); - state.placementMap[adZoneKey] = { - 'b': oneBid.bidId, - 'w': x, - 'h': y - }; - } - }); - return state; - }, - - transform: function(coxRawBids = {}, state) { - const pbjsBids = []; - - for (let adZoneKey in state.placementMap) { - let responded = coxRawBids[adZoneKey] - let ingested = state.placementMap[adZoneKey]; - - utils.logInfo('coxBidAdapter.transform', adZoneKey, responded, ingested); - - if (ingested && responded && responded['ad'] && responded['price'] > 0) { - pbjsBids.push({ - requestId: ingested['b'], - cpm: responded['price'], - width: ingested['w'], - height: ingested['h'], - creativeId: responded['adid'], - dealId: responded['dealid'], - currency: 'USD', - netRevenue: true, - ttl: 300, - ad: responded['ad'] - }); - } - } - return pbjsBids; - }, - - getUrl: state => { - // Bounce if the tag is invalid - if (!state.tag.zones) return null; - - let src = (document.location.protocol === 'https:' ? 'https://' : 'http://') + - (!state.env || state.env === 'PRD' ? '' : state.env === 'PPE' ? 'ppe-' : state.env === 'STG' ? 'staging-' : '') + - 'ad.afy11.net/ad?mode=11&nif=0&sf=0&sfd=0&ynw=0&hb=1' + - '&ct=' + srTestCapabilities() + - '&rand=' + getRand() + - '&rk1=' + getRand() + - '&rk2=' + new Date().valueOf() / 1000; - - state.tag.pageUrl = config.getConfig('pageUrl') || utils.getTopWindowUrl(); - state.tag.puTop = true; - - // Attach the serialized tag to our string - src += '&ab=' + encodeURIComponent(JSON.stringify(state.tag)); - - return src; - }, - - createState: () => ({ - env: '', - tag: {}, - placementMap: {} - }) - }; -})(); - -export const spec = { - code: 'cox', - supportedMediaTypes: [BANNER], - - isBidRequestValid: function(bid) { - return !!(bid.params && bid.params.id && bid.params.size); - }, - - buildRequests: function(validBidReqs) { - let state = helper.ingest(validBidReqs); - let url = helper.getUrl(state); - - return !url ? {} : { - method: 'GET', - url: url, - state - }; - }, - - interpretResponse: function({ body: { zones: coxRawBids } }, { state }) { - let bids = helper.transform(coxRawBids, state); - - utils.logInfo('coxBidAdapter.interpretResponse', bids); - return bids; - }, - - getUserSyncs: function(syncOptions, thing) { - try { - var [{ body: { tpCookieSync: urls = [] } }] = thing; - } catch (ignore) { - return []; - } - - let syncs = []; - if (syncOptions.pixelEnabled && urls.length > 0) { - syncs = urls.map((url) => ({ type: 'image', url: url })) - } - utils.logInfo('coxBidAdapter.getuserSyncs', syncs); - return syncs; - } -}; - -registerBidder(spec); diff --git a/modules/coxBidAdapter.md b/modules/coxBidAdapter.md deleted file mode 100644 index f4460b969ed..00000000000 --- a/modules/coxBidAdapter.md +++ /dev/null @@ -1,41 +0,0 @@ -# Overview - -``` -Module Name: Cox/COMET Bid Adapter -Module Type: Bidder Adapter -Maintainer: reynold@coxds.com -``` - -# Description - -Cox/COMET's adapter integration to the Prebid library. - -# Test Parameters - -``` -var adUnits = [ - { - code: 'test-leaderboard', - sizes: [[728, 90]], - bids: [{ - bidder: 'cox', - params: { - size: '728x90', - id: 2000005991607, - siteId: 2000100948180, - } - }] - }, { - code: 'test-banner', - sizes: [[300, 250]], - bids: [{ - bidder: 'cox', - params: { - size: '300x250', - id: 2000005991707, - siteId: 2000100948180, - } - }] - } -] -``` \ No newline at end of file diff --git a/test/spec/modules/coxBidAdapter_spec.js b/test/spec/modules/coxBidAdapter_spec.js deleted file mode 100644 index 8d8b29ed4d7..00000000000 --- a/test/spec/modules/coxBidAdapter_spec.js +++ /dev/null @@ -1,233 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/coxBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; -import { deepClone } from 'src/utils'; - -describe('CoxBidAdapter', function () { - const adapter = newBidder(spec); - - describe('isBidRequestValid', function () { - const CONFIG = { - 'bidder': 'cox', - 'params': { - 'id': '8888', - 'siteId': '1000', - 'size': '300x250' - } - }; - - it('should return true when required params present', function () { - expect(spec.isBidRequestValid(CONFIG)).to.equal(true); - }); - - it('should return false when id param is missing', function () { - let config = deepClone(CONFIG); - config.params.id = null; - - expect(spec.isBidRequestValid(config)).to.equal(false); - }); - - it('should return false when size param is missing', function () { - let config = deepClone(CONFIG); - config.params.size = null; - - expect(spec.isBidRequestValid(config)).to.equal(false); - }); - }); - - describe('buildRequests', function () { - const PROD_DOMAIN = 'ad.afy11.net'; - const PPE_DOMAIN = 'ppe-ad.afy11.net'; - const STG_DOMAIN = 'staging-ad.afy11.net'; - - const BID_INFO = [{ - 'bidder': 'cox', - 'params': { - 'id': '8888', - 'siteId': '1000', - 'size': '300x250' - }, - 'sizes': [[300, 250]], - 'transactionId': 'tId-foo', - 'bidId': 'bId-bar' - }]; - - it('should send bid request to PROD_DOMAIN via GET', function () { - let request = spec.buildRequests(BID_INFO); - expect(request.url).to.have.string(PROD_DOMAIN); - expect(request.method).to.equal('GET'); - }); - - it('should send bid request to PPE_DOMAIN when configured', function () { - let clone = deepClone(BID_INFO); - clone[0].params.env = 'PPE'; - - let request = spec.buildRequests(clone); - expect(request.url).to.have.string(PPE_DOMAIN); - }); - - it('should send bid request to STG_DOMAIN when configured', function () { - let clone = deepClone(BID_INFO); - clone[0].params.env = 'STG'; - - let request = spec.buildRequests(clone); - expect(request.url).to.have.string(STG_DOMAIN); - }); - - it('should return empty when id is invalid', function () { - let clone = deepClone(BID_INFO); - clone[0].params.id = null; - - let request = spec.buildRequests(clone); - expect(request).to.be.an('object').that.is.empty; - }); - - it('should return empty when size is invalid', function () { - let clone = deepClone(BID_INFO); - clone[0].params.size = 'FOO'; - - let request = spec.buildRequests(clone); - expect(request).to.be.an('object').that.is.empty; - }); - }) - - describe('interpretResponse', function () { - const BID_INFO_1 = [{ - 'bidder': 'cox', - 'params': { - 'id': '2000005657007', - 'siteId': '2000101880180', - 'size': '728x90' - }, - 'transactionId': 'foo_1', - 'bidId': 'bar_1' - }]; - - const BID_INFO_2 = [{ - 'bidder': 'cox', - 'params': { - 'id': '2000005658887', - 'siteId': '2000101880180', - 'size': '300x250' - }, - 'transactionId': 'foo_2', - 'bidId': 'bar_2' - }]; - - const RESPONSE_1 = { body: { - 'zones': { - 'as2000005657007': { - 'price': 1.88, - 'dealid': 'AA128460', - 'ad': '

2000005657007
728x90

', - 'adid': '7007-728-90' - }}}}; - - const RESPONSE_2 = { body: { - 'zones': { - 'as2000005658887': { - 'price': 2.88, - 'ad': '

2000005658887
300x250

', - 'adid': '888-88' - }}}}; - - const PBJS_BID_1 = { - 'requestId': 'bar_1', - 'cpm': 1.88, - 'width': '728', - 'height': '90', - 'creativeId': '7007-728-90', - 'dealId': 'AA128460', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 300, - 'ad': '

2000005657007
728x90

' - }; - - const PBJS_BID_2 = { - 'requestId': 'bar_2', - 'cpm': 2.88, - 'width': '300', - 'height': '250', - 'creativeId': '888-88', - 'dealId': undefined, - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 300, - 'ad': '

2000005658887
300x250

' - }; - - it('should return correct pbjs bid', function () { - let result = spec.interpretResponse(RESPONSE_2, spec.buildRequests(BID_INFO_2)); - expect(result[0]).to.eql(PBJS_BID_2); - }); - - it('should handle multiple bid instances', function () { - let request1 = spec.buildRequests(BID_INFO_1); - let request2 = spec.buildRequests(BID_INFO_2); - - let result2 = spec.interpretResponse(RESPONSE_2, request2); - expect(result2[0]).to.eql(PBJS_BID_2); - - let result1 = spec.interpretResponse(RESPONSE_1, request1); - expect(result1[0]).to.eql(PBJS_BID_1); - }); - - it('should return empty when price is zero', function () { - let clone = deepClone(RESPONSE_1); - clone.body.zones.as2000005657007.price = 0; - - let result = spec.interpretResponse(clone, spec.buildRequests(BID_INFO_1)); - expect(result).to.be.an('array').that.is.empty; - }); - - it('should return empty when there is no ad', function () { - let clone = deepClone(RESPONSE_1); - clone.body.zones.as2000005657007.ad = null; - - let result = spec.interpretResponse(clone, spec.buildRequests(BID_INFO_1)); - expect(result).to.be.an('array').that.is.empty; - }); - - it('should return empty when there is no ad unit info', function () { - let clone = deepClone(RESPONSE_1); - delete (clone.body.zones.as2000005657007); - - let result = spec.interpretResponse(clone, spec.buildRequests(BID_INFO_1)); - expect(result).to.be.an('array').that.is.empty; - }); - }); - - describe('getUserSyncs', function () { - const RESPONSE = [{ body: { - 'zones': {}, - 'tpCookieSync': ['http://pixel.foo.com/', 'http://pixel.bar.com/'] - }}]; - - it('should return correct pbjs syncs when pixels are enabled', function () { - let syncs = spec.getUserSyncs({ pixelEnabled: true }, RESPONSE); - - expect(syncs.map(x => x.type)).to.eql(['image', 'image']); - expect(syncs.map(x => x.url)).to.have.members(['http://pixel.bar.com/', 'http://pixel.foo.com/']); - }); - - it('should return empty when pixels are not enabled', function () { - let syncs = spec.getUserSyncs({ pixelEnabled: false }, RESPONSE); - - expect(syncs).to.be.an('array').that.is.empty; - }); - - it('should return empty when response has no sync data', function () { - let clone = deepClone(RESPONSE); - delete (clone[0].body.tpCookieSync); - - let syncs = spec.getUserSyncs({ pixelEnabled: true }, clone); - expect(syncs).to.be.an('array').that.is.empty; - }); - - it('should return empty when response is empty', function () { - let syncs = spec.getUserSyncs({ pixelEnabled: true }, [{}]); - expect(syncs).to.be.an('array').that.is.empty; - }); - }); -}); From ec47ed0739104d4c0877b35ace7b040409ea233c Mon Sep 17 00:00:00 2001 From: bjorn-lw <32431346+bjorn-lw@users.noreply.github.com> Date: Tue, 6 Nov 2018 20:05:05 +0100 Subject: [PATCH 0820/1594] Modified how gdpr info is being sent from adapter (#3253) * Livewrapped bid and analytics adapter * Fixed some tests for browser compatibility * Fixed some tests for browser compatibility * Changed analytics adapter code name * Fix double quote in debug message * modified how gdpr is being passed --- modules/livewrappedBidAdapter.js | 4 +- .../modules/livewrappedBidAdapter_spec.js | 60 +++++++++++++------ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/modules/livewrappedBidAdapter.js b/modules/livewrappedBidAdapter.js index ebfe4aad2d4..110a9567364 100644 --- a/modules/livewrappedBidAdapter.js +++ b/modules/livewrappedBidAdapter.js @@ -4,7 +4,7 @@ import { config } from 'src/config'; import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'livewrapped'; -export const URL = 'https://lwadm.com/ad'; +export const URL = '//lwadm.com/ad'; const VERSION = '1.1'; export const spec = { @@ -65,7 +65,7 @@ export const spec = { ifa: ifa ? ifa.params.ifa : undefined, tid: tid ? tid.params.tid : undefined, version: VERSION, - gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : false, + gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, gdprConsent: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined, cookieSupport: !utils.isSafariBrowser() && utils.cookiesAreEnabled(), adRequests: [...adRequests] diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js index 64a70b946ef..072d374ac72 100644 --- a/test/spec/modules/livewrappedBidAdapter_spec.js +++ b/test/spec/modules/livewrappedBidAdapter_spec.js @@ -91,7 +91,7 @@ describe('Livewrapped adapter tests', function () { let result = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = JSON.parse(result.data); - expect(result.url).to.equal('https://lwadm.com/ad'); + expect(result.url).to.equal('//lwadm.com/ad'); let expectedQuery = { auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', @@ -101,7 +101,6 @@ describe('Livewrapped adapter tests', function () { seats: {'dsp': ['seat 1']}, version: '1.1', cookieSupport: true, - gdprApplies: false, adRequests: [{ adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', callerAdUnitId: 'panorama_d_1', @@ -127,7 +126,7 @@ describe('Livewrapped adapter tests', function () { let result = spec.buildRequests(multiplebidRequest.bids, multiplebidRequest); let data = JSON.parse(result.data); - expect(result.url).to.equal('https://lwadm.com/ad'); + expect(result.url).to.equal('//lwadm.com/ad'); let expectedQuery = { auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', @@ -137,7 +136,6 @@ describe('Livewrapped adapter tests', function () { seats: {'dsp': ['seat 1']}, version: '1.1', cookieSupport: true, - gdprApplies: false, adRequests: [{ adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', callerAdUnitId: 'panorama_d_1', @@ -164,7 +162,7 @@ describe('Livewrapped adapter tests', function () { let result = spec.buildRequests(testbidRequest.bids, testbidRequest); let data = JSON.parse(result.data); - expect(result.url).to.equal('https://lwadm.com/ad'); + expect(result.url).to.equal('//lwadm.com/ad'); let expectedQuery = { auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', @@ -174,7 +172,6 @@ describe('Livewrapped adapter tests', function () { seats: {'dsp': ['seat 1']}, version: '1.1', cookieSupport: true, - gdprApplies: false, adRequests: [{ callerAdUnitId: 'caller id 1', bidId: '2ffb201a808da7', @@ -196,7 +193,7 @@ describe('Livewrapped adapter tests', function () { let result = spec.buildRequests(testbidRequest.bids, testbidRequest); let data = JSON.parse(result.data); - expect(result.url).to.equal('https://lwadm.com/ad'); + expect(result.url).to.equal('//lwadm.com/ad'); let expectedQuery = { auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', @@ -204,7 +201,6 @@ describe('Livewrapped adapter tests', function () { url: 'http://www.domain.com', version: '1.1', cookieSupport: true, - gdprApplies: false, adRequests: [{ callerAdUnitId: 'panorama_d_1', bidId: '2ffb201a808da7', @@ -226,14 +222,13 @@ describe('Livewrapped adapter tests', function () { let result = spec.buildRequests(testbidRequest.bids, testbidRequest); let data = JSON.parse(result.data); - expect(result.url).to.equal('https://lwadm.com/ad'); + expect(result.url).to.equal('//lwadm.com/ad'); let expectedQuery = { auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', url: 'http://www.domain.com', version: '1.1', cookieSupport: true, - gdprApplies: false, adRequests: [{ adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', callerAdUnitId: 'panorama_d_1', @@ -266,7 +261,6 @@ describe('Livewrapped adapter tests', function () { deviceId: 'deviceid', ifa: 'ifa', cookieSupport: true, - gdprApplies: false, adRequests: [{ callerAdUnitId: 'panorama_d_1', bidId: '2ffb201a808da7', @@ -298,7 +292,6 @@ describe('Livewrapped adapter tests', function () { tid: 'tracking id', test: true, cookieSupport: true, - gdprApplies: false, adRequests: [{ callerAdUnitId: 'panorama_d_1', bidId: '2ffb201a808da7', @@ -310,7 +303,7 @@ describe('Livewrapped adapter tests', function () { expect(data).to.deep.equal(expectedQuery); }); - it('should pass gdpr parameters', function() { + it('should pass gdpr true parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); let testRequest = clone(bidderRequest); @@ -321,7 +314,7 @@ describe('Livewrapped adapter tests', function () { let result = spec.buildRequests(testRequest.bids, testRequest); let data = JSON.parse(result.data); - expect(result.url).to.equal('https://lwadm.com/ad'); + expect(result.url).to.equal('//lwadm.com/ad'); let expectedQuery = { auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', @@ -345,13 +338,46 @@ describe('Livewrapped adapter tests', function () { expect(data).to.deep.equal(expectedQuery); }); + it('should pass gdpr false parameters', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testRequest = clone(bidderRequest); + testRequest.gdprConsent = { + gdprApplies: false + }; + let result = spec.buildRequests(testRequest.bids, testRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('//lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + cookieSupport: true, + gdprApplies: false, + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + it('should pass no cookie support', function() { sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => false); sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); let result = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = JSON.parse(result.data); - expect(result.url).to.equal('https://lwadm.com/ad'); + expect(result.url).to.equal('//lwadm.com/ad'); let expectedQuery = { auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', @@ -360,7 +386,6 @@ describe('Livewrapped adapter tests', function () { url: 'http://www.domain.com', seats: {'dsp': ['seat 1']}, version: '1.1', - gdprApplies: false, cookieSupport: false, adRequests: [{ adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', @@ -380,7 +405,7 @@ describe('Livewrapped adapter tests', function () { let result = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = JSON.parse(result.data); - expect(result.url).to.equal('https://lwadm.com/ad'); + expect(result.url).to.equal('//lwadm.com/ad'); let expectedQuery = { auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', @@ -389,7 +414,6 @@ describe('Livewrapped adapter tests', function () { url: 'http://www.domain.com', seats: {'dsp': ['seat 1']}, version: '1.1', - gdprApplies: false, cookieSupport: false, adRequests: [{ adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', From 7a5ca11974000797f323a0eaeeb6ff35b03df43e Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 6 Nov 2018 14:06:02 -0500 Subject: [PATCH 0821/1594] appnexus adapter support empty keyvalues in bidder params (#3257) * appnexus adapter support empty keyvalues in bidder params * create function to check if array is populated * refactor forEach functions --- modules/appnexusBidAdapter.js | 21 +++++- src/utils.js | 2 +- test/spec/modules/appnexusBidAdapter_spec.js | 6 ++ test/spec/utils_spec.js | 69 ++++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 19aa5e7cf73..cc0cac579da 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -178,6 +178,10 @@ export const spec = { 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 = utils.convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { @@ -191,6 +195,16 @@ export const spec = { } } +function isPopulatedArray(arr) { + return !!(utils.isArray(arr) && arr.length > 0); +} + +function deleteValues(keyPairObj) { + if (isPopulatedArray(keyPairObj.value) && keyPairObj.value[0] === '') { + delete keyPairObj.value; + } +} + function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { const renderer = Renderer.install({ id: rtbBid.renderer_id, @@ -345,7 +359,12 @@ function bidToTag(bid) { tag.external_imp_id = bid.params.externalImpId; } if (!utils.isEmpty(bid.params.keywords)) { - tag.keywords = utils.transformBidderParamKeywords(bid.params.keywords); + let keywords = utils.transformBidderParamKeywords(bid.params.keywords); + + if (keywords.length > 0) { + keywords.forEach(deleteValues); + } + tag.keywords = keywords; } if (bid.mediaType === NATIVE || utils.deepAccess(bid, `mediaTypes.${NATIVE}`)) { diff --git a/src/utils.js b/src/utils.js index 8203b3d4242..843c0c11c76 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1092,7 +1092,7 @@ export function transformBidderParamKeywords(keywords, paramName = 'keywords') { let values = []; exports._each(v, (val) => { val = exports.getValueString(paramName + '.' + k, val); - if (val) { values.push(val); } + if (val || val === '') { values.push(val); } }); v = values; } else { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 5e41c1c9544..e6afc8561b6 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -261,6 +261,8 @@ describe('AppNexusAdapter', function () { singleArrNum: [5], multiValMixed: ['value1', 2, 'value3'], singleValNum: 123, + emptyStr: '', + emptyArr: [''], badValue: {'foo': 'bar'} // should be dropped } } @@ -285,6 +287,10 @@ describe('AppNexusAdapter', function () { }, { 'key': 'singleValNum', 'value': ['123'] + }, { + 'key': 'emptyStr' + }, { + 'key': 'emptyArr' }]); }); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 952c6791056..df5d46223c0 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -846,4 +846,73 @@ describe('Utils', function () { expect(sizes).to.deep.equal([[300, 250], [300, 600]]); }); }); + + describe('transformBidderParamKeywords', function () { + it('returns an array of objects when keyvalue is an array', function () { + let keywords = { + genre: ['rock', 'pop'] + }; + let result = utils.transformBidderParamKeywords(keywords); + expect(result).to.deep.equal([{ + key: 'genre', + value: ['rock', 'pop'] + }]); + }); + + it('returns an array of objects when keyvalue is a string', function () { + let keywords = { + genre: 'opera' + }; + let result = utils.transformBidderParamKeywords(keywords); + expect(result).to.deep.equal([{ + key: 'genre', + value: ['opera'] + }]); + }); + + it('returns an array of objects when keyvalue is a number', function () { + let keywords = { + age: 15 + }; + let result = utils.transformBidderParamKeywords(keywords); + expect(result).to.deep.equal([{ + key: 'age', + value: ['15'] + }]); + }); + + it('returns an array of objects when using multiple keys with values of differing types', function () { + let keywords = { + genre: 'classical', + mix: ['1', 2, '3', 4], + age: 10 + }; + let result = utils.transformBidderParamKeywords(keywords); + expect(result).to.deep.equal([{ + key: 'genre', + value: ['classical'] + }, { + key: 'mix', + value: ['1', '2', '3', '4'] + }, { + key: 'age', + value: ['10'] + }]); + }); + + it('returns an array of objects when the keyvalue uses an empty string', function() { + let keywords = { + test: [''], + test2: '' + }; + let result = utils.transformBidderParamKeywords(keywords); + expect(result).to.deep.equal([{ + key: 'test', + value: [''] + }, { + key: 'test2', + value: [''] + }]); + }); + }); }); From 05ba9e06c696aa1cae8c4064fa6f683f94f39262 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 6 Nov 2018 13:10:20 -0800 Subject: [PATCH 0822/1594] "Prebid 1.31.0 Release" "Prebid 1.31.0 Release" --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 288d970f842..ec35a43c6d2 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.31.0-pre", + "version": "1.31.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 1f9e624e4e8219bc4cbe7c5c6ddad932538d5aad Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 6 Nov 2018 14:11:31 -0800 Subject: [PATCH 0823/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec35a43c6d2..18ccc07800b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.31.0", + "version": "1.32.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3d9f5c555f9d42076139a1840acedd0008d0266c Mon Sep 17 00:00:00 2001 From: Omer Koren Date: Wed, 7 Nov 2018 19:19:07 +0200 Subject: [PATCH 0824/1594] fix undertone adapter user sync url (#3271) * fix undertone adapter user sync url * fix sync user url unit test --- modules/undertoneBidAdapter.js | 4 ++-- test/spec/modules/undertoneBidAdapter_spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index 6d4ced88ba1..05b1b90c08d 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -8,8 +8,8 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'undertone'; const URL = '//hb.undertone.com/hb'; const FRAME_USER_SYNC = '//cdn.undertone.com/js/usersync.html'; -const PIXEL_USER_SYNC_1 = '//usr.undertone.com/userPixel/syncOne?id=1&of=2'; -const PIXEL_USER_SYNC_2 = '//usr.undertone.com/userPixel/syncOne?id=2&of=2'; +const PIXEL_USER_SYNC_1 = '//usr.undertone.com/userpixel/syncOne?id=1&of=2'; +const PIXEL_USER_SYNC_2 = '//usr.undertone.com/userpixel/syncOne?id=2&of=2'; function getCanonicalUrl() { try { diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index 400e86567ea..517710e7995 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -176,9 +176,9 @@ describe('Undertone Adapter', function () { const result = spec.getUserSyncs({ pixelEnabled: true }); expect(result).to.have.lengthOf(2); expect(result[0].type).to.equal('image'); - expect(result[0].url).to.equal('//usr.undertone.com/userPixel/syncOne?id=1&of=2'); + expect(result[0].url).to.equal('//usr.undertone.com/userpixel/syncOne?id=1&of=2'); expect(result[1].type).to.equal('image'); - expect(result[1].url).to.equal('//usr.undertone.com/userPixel/syncOne?id=2&of=2'); + expect(result[1].url).to.equal('//usr.undertone.com/userpixel/syncOne?id=2&of=2'); }); }); }); From 459a2e27b6d4c8fe28242fa017b8c94d708cee82 Mon Sep 17 00:00:00 2001 From: Omer Koren Date: Wed, 7 Nov 2018 19:38:33 +0200 Subject: [PATCH 0825/1594] Revert "fix undertone adapter user sync url (#3271)" (#3273) This reverts commit 3d9f5c555f9d42076139a1840acedd0008d0266c. --- modules/undertoneBidAdapter.js | 4 ++-- test/spec/modules/undertoneBidAdapter_spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index 05b1b90c08d..6d4ced88ba1 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -8,8 +8,8 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'undertone'; const URL = '//hb.undertone.com/hb'; const FRAME_USER_SYNC = '//cdn.undertone.com/js/usersync.html'; -const PIXEL_USER_SYNC_1 = '//usr.undertone.com/userpixel/syncOne?id=1&of=2'; -const PIXEL_USER_SYNC_2 = '//usr.undertone.com/userpixel/syncOne?id=2&of=2'; +const PIXEL_USER_SYNC_1 = '//usr.undertone.com/userPixel/syncOne?id=1&of=2'; +const PIXEL_USER_SYNC_2 = '//usr.undertone.com/userPixel/syncOne?id=2&of=2'; function getCanonicalUrl() { try { diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index 517710e7995..400e86567ea 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -176,9 +176,9 @@ describe('Undertone Adapter', function () { const result = spec.getUserSyncs({ pixelEnabled: true }); expect(result).to.have.lengthOf(2); expect(result[0].type).to.equal('image'); - expect(result[0].url).to.equal('//usr.undertone.com/userpixel/syncOne?id=1&of=2'); + expect(result[0].url).to.equal('//usr.undertone.com/userPixel/syncOne?id=1&of=2'); expect(result[1].type).to.equal('image'); - expect(result[1].url).to.equal('//usr.undertone.com/userpixel/syncOne?id=2&of=2'); + expect(result[1].url).to.equal('//usr.undertone.com/userPixel/syncOne?id=2&of=2'); }); }); }); From d644363b37636da7751bc409c1bc7c6497f9de9d Mon Sep 17 00:00:00 2001 From: Brittany Zellman <33695402+brittanyzellman@users.noreply.github.com> Date: Wed, 7 Nov 2018 14:06:51 -0500 Subject: [PATCH 0826/1594] TripleliftBidAdapter - remove dependency on getTopWindowLocation util (#3139) * removed dependancy on getTopWindowUrl for referer * protect against undefined obj and remove test on old dependency * added unit test for referer and gdpr in query string * removed gdpr test * removed gdpr from bidderRequest obj * decontructed bidder request obj in chai test * just need to run karma tests again * added gdpr consent to all bidderRequest obj in chai tests --- modules/tripleliftBidAdapter.js | 7 ++- .../spec/modules/tripleliftBidAdapter_spec.js | 44 +++++++++++++++---- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 795c75ef9bc..5989d0c2fca 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -17,12 +17,15 @@ export const tripleliftAdapterSpec = { buildRequests: function(bidRequests, bidderRequest) { let tlCall = STR_ENDPOINT; - let referrer = utils.getTopWindowUrl(); let data = _buildPostBody(bidRequests); tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); - tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer); + + if (bidderRequest && bidderRequest.refererInfo) { + let referrer = bidderRequest.refererInfo.referer; + tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer); + } if (bidderRequest && bidderRequest.timeout) { tlCall = utils.tryAppendQueryString(tlCall, 'tmax', bidderRequest.timeout); diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index d3013d9be22..f614bdbd31a 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -68,19 +68,42 @@ describe('triplelift adapter', function () { } ]; + let bidderRequest = { + bidderCode: 'triplelift', + auctionId: 'a7ebcd1d-66ff-4b5c-a82c-6a21a6ee5a18', + bidderRequestId: '5c55612f99bc11', + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 250, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ], + refererInfo: { + referer: 'http://examplereferer.com' + }, + gdprConsent: { + consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', + gdprApplies: true + } + }; + it('exists and is an object', function () { - const request = tripleliftAdapterSpec.buildRequests(bidRequests); + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); expect(request).to.exist.and.to.be.a('object'); }); it('should only parse sizes that are of the proper length and format', function () { - const request = tripleliftAdapterSpec.buildRequests(bidRequests); + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); expect(request.data.imp[0].banner.format).to.have.length(2); expect(request.data.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); }); it('should be a post request and populate the payload', function () { - const request = tripleliftAdapterSpec.buildRequests(bidRequests); + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.exist; expect(payload.imp[0].tagid).to.equal('12345'); @@ -89,16 +112,15 @@ describe('triplelift adapter', function () { }); it('should return a query string for TL call', function () { - const request = tripleliftAdapterSpec.buildRequests(bidRequests); + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const url = request.url; expect(url).to.exist; expect(url).to.be.a('string'); expect(url).to.match(/(?:tlx.3lift.com\/header\/auction)/) expect(url).to.match(/(?:lib=prebid)/) expect(url).to.match(/(?:prebid.version)/) - // expect(url).to.match(/(?:fe=)/) // - expect(url).to.match(/(?:referrer)/) - }) + expect(url).to.match(/(?:referrer)/); + }); }); describe('interpretResponse', function () { @@ -130,8 +152,11 @@ describe('triplelift adapter', function () { iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' } ], + refererInfo: { + referer: 'http://examplereferer.com' + }, gdprConsent: { - consentString: 'BOONm0NOONma-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVOQ6gEaY', + consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', gdprApplies: true } }; @@ -201,6 +226,9 @@ describe('triplelift adapter', function () { iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' } ], + refererInfo: { + referer: 'http://examplereferer.com' + }, gdprConsent: { consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', gdprApplies: true From b17a11e05a7227925740e6a92d1601d5b2450e64 Mon Sep 17 00:00:00 2001 From: "Takaaki.Kojima" Date: Thu, 8 Nov 2018 04:22:10 +0900 Subject: [PATCH 0827/1594] update AdGeneration adapter (#3228) * update AdGeneration adapter * fix test spec * update AdGeneration adapter * update AdGeneration adapter - Adding UnitTest for setCurrency --- modules/adgenerationBidAdapter.js | 44 +++++++++++++-- .../modules/adgenerationBidAdapter_spec.js | 55 +++++++++++++------ 2 files changed, 75 insertions(+), 24 deletions(-) diff --git a/modules/adgenerationBidAdapter.js b/modules/adgenerationBidAdapter.js index 1753446fc67..340017c26cf 100644 --- a/modules/adgenerationBidAdapter.js +++ b/modules/adgenerationBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from 'src/utils'; -// import {config} from 'src/config'; import {registerBidder} from 'src/adapters/bidderFactory'; import {BANNER, NATIVE} from 'src/mediaTypes'; +import { config } from 'src/config'; const ADG_BIDDER_CODE = 'adgeneration'; export const spec = { @@ -23,7 +23,8 @@ export const spec = { * @param {validBidRequests[]} - an array of bids * @return ServerRequest Info describing the request to the server. */ - buildRequests: function (validBidRequests) { + buildRequests: function (validBidRequests, bidderRequest) { + const ADGENE_PREBID_VERSION = '1.0.1'; let serverRequests = []; for (let i = 0, len = validBidRequests.length; i < len; i++) { const validReq = validBidRequests[i]; @@ -38,12 +39,16 @@ export const spec = { 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 = 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); @@ -82,10 +87,9 @@ export const spec = { height: body.h ? body.h : 1, creativeId: body.creativeid || '', dealId: body.dealid || '', - currency: 'JPY', + currency: getCurrencyType(), netRevenue: true, ttl: body.ttl || 10, - referrer: utils.getTopWindowUrl(), }; if (bidRequest.mediaTypes && bidRequest.mediaTypes.native) { bidResponse.native = createNativeAd(body); @@ -198,4 +202,32 @@ function removeWrapper(ad) { return ad.substr(bodyIndex, lastBodyIndex).replace('', '').replace('', ''); } +/** + * request + * @param validReq request + * @returns {?string} 300x250,320x50... + */ +function getSizes(validReq) { + const sizes = validReq.sizes; + if (!sizes || sizes.length < 1) return null; + let sizesStr = ''; + for (const i in sizes) { + const size = sizes[i]; + if (size.length !== 2) return null; + sizesStr += `${size[0]}x${size[1]},`; + } + if (sizesStr || sizesStr.lastIndexOf(',') === sizesStr.length - 1) { + sizesStr = sizesStr.substring(0, sizesStr.length - 1); + } + return sizesStr; +} + +/** + * @return {?string} USD or JPY + */ +function getCurrencyType() { + if (config.getConfig('currency.adServerCurrency') && config.getConfig('currency.adServerCurrency').toUpperCase() === 'USD') return 'USD'; + return 'JPY'; +} + registerBidder(spec); diff --git a/test/spec/modules/adgenerationBidAdapter_spec.js b/test/spec/modules/adgenerationBidAdapter_spec.js index 558303ccecb..2cd810d7fb4 100644 --- a/test/spec/modules/adgenerationBidAdapter_spec.js +++ b/test/spec/modules/adgenerationBidAdapter_spec.js @@ -1,8 +1,8 @@ import {expect} from 'chai'; -import * as utils from 'src/utils'; import {spec} from 'modules/adgenerationBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import {NATIVE} from 'src/mediaTypes'; +import {config} from 'src/config'; describe('AdgenerationAdapter', function () { const adapter = newBidder(spec); @@ -15,7 +15,7 @@ describe('AdgenerationAdapter', function () { }); describe('isBidRequestValid', function () { - let bid = { + const bid = { 'bidder': 'adg', 'params': { id: '58278', // banner @@ -39,11 +39,10 @@ describe('AdgenerationAdapter', function () { bidder: 'adg', params: { id: '58278', - width: '300', - height: '250' + currency: 'JPY', }, adUnitCode: 'adunit-code', - sizes: [[300, 250]], + sizes: [[300, 250], [320, 100]], bidId: '2f6ac468a9c15e', bidderRequestId: '14a9f773e30243', auctionId: '4aae9f05-18c6-4fcd-80cf-282708cd584a', @@ -53,8 +52,7 @@ describe('AdgenerationAdapter', function () { bidder: 'adg', params: { id: '58278', - width: '300', - height: '250' + currency: 'JPY', }, mediaTypes: { native: { @@ -87,34 +85,59 @@ describe('AdgenerationAdapter', function () { transactionTd: 'f76f6dfd-d64f-4645-a29f-682bac7f431a' } ]; + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; const data = { - banner: 'posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&imark=1', - native: 'posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3' + banner: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100¤cy=JPY&pbver=%24prebid.version%24&sdkname=prebidjs&adapterver=1.0.1&imark=1&tp=http%3A%2F%2Fexample.com`, + bannerUSD: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100¤cy=USD&pbver=%24prebid.version%24&sdkname=prebidjs&adapterver=1.0.1&imark=1&tp=http%3A%2F%2Fexample.com`, + native: 'posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=1x1¤cy=JPY&pbver=%24prebid.version%24&sdkname=prebidjs&adapterver=1.0.1&tp=http%3A%2F%2Fexample.com' }; it('sends bid request to ENDPOINT via GET', function () { - const request = spec.buildRequests(bidRequests)[0]; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.url).to.equal(ENDPOINT[1]); expect(request.method).to.equal('GET'); }); it('sends bid request to debug ENDPOINT via GET', function () { bidRequests[0].params.debug = true; - const request = spec.buildRequests(bidRequests)[0]; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.url).to.equal(ENDPOINT[0]); expect(request.method).to.equal('GET'); }); it('should attache params to the banner request', function () { - const request = spec.buildRequests(bidRequests)[0]; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data).to.equal(data.banner); }); it('should attache params to the native request', function () { - const request = spec.buildRequests(bidRequests)[1]; + const request = spec.buildRequests(bidRequests, bidderRequest)[1]; expect(request.data).to.equal(data.native); }); + it('allows setConfig to set bidder currency for JPY', function () { + config.setConfig({ + currency: { + adServerCurrency: 'JPY' + } + }); + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.data).to.equal(data.banner); + config.resetConfig(); + }); + it('allows setConfig to set bidder currency for USD', function () { + config.setConfig({ + currency: { + adServerCurrency: 'USD' + } + }); + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.data).to.equal(data.bannerUSD); + config.resetConfig(); + }); }); - describe('interpretResponse', function () { const bidRequests = { banner: { @@ -298,7 +321,6 @@ describe('AdgenerationAdapter', function () { currency: 'JPY', netRevenue: true, ttl: 1000, - referrer: utils.getTopWindowUrl(), ad: '
', }, native: { @@ -311,7 +333,6 @@ describe('AdgenerationAdapter', function () { currency: 'JPY', netRevenue: true, ttl: 1000, - referrer: utils.getTopWindowUrl(), ad: '↵
', native: { title: 'Title', @@ -351,7 +372,6 @@ describe('AdgenerationAdapter', function () { expect(result.currency).to.equal(bidResponses.banner.currency); expect(result.netRevenue).to.equal(bidResponses.banner.netRevenue); expect(result.ttl).to.equal(bidResponses.banner.ttl); - expect(result.referrer).to.equal(bidResponses.banner.referrer); expect(result.ad).to.equal(bidResponses.banner.ad); }); @@ -365,7 +385,6 @@ describe('AdgenerationAdapter', function () { expect(result.currency).to.equal(bidResponses.native.currency); expect(result.netRevenue).to.equal(bidResponses.native.netRevenue); expect(result.ttl).to.equal(bidResponses.native.ttl); - expect(result.referrer).to.equal(bidResponses.native.referrer); expect(result.native.title).to.equal(bidResponses.native.native.title); expect(result.native.image.url).to.equal(bidResponses.native.native.image.url); expect(result.native.image.height).to.equal(bidResponses.native.native.image.height); From 8c78cde83d3565e7a61db9845ec091c2700741c6 Mon Sep 17 00:00:00 2001 From: jacekburys-quantcast <44467819+jacekburys-quantcast@users.noreply.github.com> Date: Wed, 7 Nov 2018 19:36:43 +0000 Subject: [PATCH 0828/1594] adding Prebid.js version to request in quantcastBidAdapter (#3230) * adding Prebid.js version to request in quantcastBidAdapter * using .version$ instead of pbjs.version --- modules/quantcastBidAdapter.js | 3 ++- test/spec/modules/quantcastBidAdapter_spec.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 79128a834a4..7d4393fe12c 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -93,7 +93,8 @@ export const spec = { }, bidId: bid.bidId, gdprSignal: gdprConsent.gdprApplies ? 1 : 0, - gdprConsent: gdprConsent.consentString + gdprConsent: gdprConsent.consentString, + prebidJsVersion: '$prebid.version$' }; const data = JSON.stringify(requestData); diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index e64294e87e2..cda42b6ddb6 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -121,7 +121,8 @@ describe('Quantcast adapter', function () { domain }, bidId: '2f7b179d443f14', - gdprSignal: 0 + gdprSignal: 0, + prebidJsVersion: '$prebid.version$' }; expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); From 2206ba48aeaf23035739946cb55eef765262f14f Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 8 Nov 2018 08:16:38 -0500 Subject: [PATCH 0829/1594] add logic to resize AST divs and iframes (#3206) * add logic to resize AST divs and iframes * fix import package * replace AST lookup with new API function --- src/secureCreatives.js | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 415fbc17c63..67579bae76c 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -6,7 +6,7 @@ import events from './events'; import { fireNativeTrackers } from './native'; import { EVENTS } from './constants'; -import { isSlotMatchingAdUnitCode } from './utils'; +import { isSlotMatchingAdUnitCode, logWarn } from './utils'; import { auctionManager } from './auctionManager'; import find from 'core-js/library/fn/array/find'; import { isRendererRequired, executeRenderer } from './Renderer'; @@ -74,12 +74,38 @@ function sendAdToCreative(adObject, remoteDomain, source) { function resizeRemoteCreative({ adUnitCode, width, height }) { // resize both container div + iframe ['div', 'iframe'].forEach(elmType => { - let elementStyle = getElementByAdUnit(elmType).style; - elementStyle.width = width + 'px'; - elementStyle.height = height + 'px'; + let element = getElementByAdUnit(elmType); + if (element) { + let elementStyle = element.style; + elementStyle.width = width + 'px'; + elementStyle.height = height + 'px'; + } else { + logWarn(`Unable to locate matching page element for adUnitCode ${adUnitCode}. Can't resize it to ad's dimensions. Please review setup.`); + } }); + function getElementByAdUnit(elmType) { - return document.getElementById(find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot) - .getSlotElementId()).querySelector(elmType); + let id = getElementIdBasedOnAdServer(adUnitCode); + let parentDivEle = document.getElementById(id); + return parentDivEle && parentDivEle.querySelector(elmType); + } + + function getElementIdBasedOnAdServer(adUnitCode) { + if (window.googletag) { + return getDfpElementId(adUnitCode) + } else if (window.apntag) { + return getAstElementId(adUnitCode) + } else { + return adUnitCode; + } + } + + function getDfpElementId(adUnitCode) { + return find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot).getSlotElementId() + } + + function getAstElementId(adUnitCode) { + let astTag = window.apntag.getTag(adUnitCode); + return astTag && astTag.targetId; } } From 143d1b0b22150e5f04821839dfbdb71f98061196 Mon Sep 17 00:00:00 2001 From: Gleb Glushtsov Date: Thu, 8 Nov 2018 13:46:22 -0500 Subject: [PATCH 0830/1594] Add Prebid.js version to the request (#3280) * check gdpr in buildRequest * User sync based on whether gdpr applies or not * check if consent data exists during user sync * split user sync into further branches: 1) when gdpr does not apply 2) when consent data is unavailable * contribute viewability to ttxRequest * update tests * remove window mock from tests * use local variables * introduce ServerRequestBuilder * add withOptions() method to ServerRequestBuilder * add semicolons * sync up package-lock.json with upstream/master * stub window.top in tests * introduce getTopWindowSize() for test purpose * reformat code * add withSite() method to TtxRequestBuilder add withSite() method to TtxRequestBuilder * add isIframe() and _isViewabilityMeasurable() * handle NON_MEASURABLE viewability in nested iframes * consider page visibility, stub utils functions getWindowTop() and getWindowSelf() * contribute viewability as 0 for inactive tab * add prebidjs version to ttx request * send caller as an array --- modules/33acrossBidAdapter.js | 8 ++++++++ test/spec/modules/33acrossBidAdapter_spec.js | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 497cf9f7110..2ecab4013f9 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -83,6 +83,14 @@ function _createServerRequest(bidRequest, gdprConsent) { gdpr: (gdprConsent.gdprApplies === true) ? 1 : 0 } }; + ttxRequest.ext = { + ttx: { + caller: [{ + 'name': 'prebidjs', + 'version': '$prebid.version$' + }] + } + } // Finally, set the openRTB 'test' param if this is to be a test bid if (params.test === 1) { diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index c8f0421e1e6..1fc77a7e14d 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -58,6 +58,14 @@ describe('33acrossBidAdapter:', function () { ext: { gdpr: 0 } + }, + ext: { + ttx: { + caller: [{ + 'name': 'prebidjs', + 'version': '$prebid.version$' + }] + } } }; From bf2dc9ca73ad1bd0f315bb64cda5c3098f3c5c09 Mon Sep 17 00:00:00 2001 From: skazedo Date: Thu, 8 Nov 2018 13:49:47 -0500 Subject: [PATCH 0831/1594] Tag level params passed to renderer in ZEDO Adapter (#3279) * initial commit * updated contact and tag details * changes ti support the renderers * changes to pass dimId * fixed names of internal mapping * added comment * added gdpr param to request and other fixes * modified api url * fix * fixed the secure api call * rolled back video event callback till we support it * updated doc with video details * added bid won and timeout pixel * added testcase for bid events * modified testcase * fixed the url logged * tag param values passed ot renderer * added a conditioal check --- modules/zedoBidAdapter.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/zedoBidAdapter.js b/modules/zedoBidAdapter.js index c21b55b88a2..f44493a7489 100644 --- a/modules/zedoBidAdapter.js +++ b/modules/zedoBidAdapter.js @@ -256,7 +256,12 @@ function getRenderer(adUnitCode, rendererId, rendererUrl, rendererOptions = {}) function videoRenderer(bid) { // push to render queue bid.renderer.push(() => { - var rndr = new ZdPBTag(bid.adUnitCode, bid.network, bid.width, bid.height, bid.adType, bid.vastXml); + let channelCode = utils.deepAccess(bid, 'params.0.channelCode') || 0; + let dimId = utils.deepAccess(bid, 'params.0.dimId') || 0; + let options = utils.deepAccess(bid, 'params.0.options') || {}; + let channel = (channelCode > 0) ? (channelCode - (bid.network * 1000000)) : 0; + var rndr = new ZdPBTag(bid.adUnitCode, bid.network, bid.width, bid.height, bid.adType, bid.vastXml, channel, dimId, + (encodeURI(utils.getTopWindowUrl()) || ''), options); rndr.renderAd(); }); } From a4e8c4939e93f2c07a5761a7e1069981ce18b27a Mon Sep 17 00:00:00 2001 From: Justas Pupelis Date: Thu, 8 Nov 2018 20:55:26 +0200 Subject: [PATCH 0832/1594] Adform openrtb adapter (#3245) * adformOpenRtb native adapter * Updated info --- modules/adformOpenRTBAdapter.js | 173 +++++++ modules/adformOpenRTBAdapter.md | 59 +++ .../spec/modules/adformOpenRTBAdapter_spec.js | 473 ++++++++++++++++++ 3 files changed, 705 insertions(+) create mode 100644 modules/adformOpenRTBAdapter.js create mode 100644 modules/adformOpenRTBAdapter.md create mode 100644 test/spec/modules/adformOpenRTBAdapter_spec.js diff --git a/modules/adformOpenRTBAdapter.js b/modules/adformOpenRTBAdapter.js new file mode 100644 index 00000000000..41bb9db9fcd --- /dev/null +++ b/modules/adformOpenRTBAdapter.js @@ -0,0 +1,173 @@ +// jshint esversion: 6, es3: false, node: true +'use strict'; + +import { + registerBidder +} from 'src/adapters/bidderFactory'; +import { + NATIVE +} from 'src/mediaTypes'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'adformOpenRTB'; +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' + } +}; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [ NATIVE ], + isBidRequestValid: bid => !!bid.params.mid, + buildRequests: (validBidRequests, bidderRequest) => { + const page = bidderRequest.refererInfo.referer; + const adxDomain = setOnAny(validBidRequests, 'params.adxDomain') || 'adx.adform.net'; + const ua = navigator.userAgent; + const pt = setOnAny(validBidRequests, 'params.pt') || setOnAny(validBidRequests, 'params.priceType') || 'net'; + const tid = validBidRequests[0].transactionId; // ??? check with ssp + const test = setOnAny(validBidRequests, 'params.test'); + const publisher = setOnAny(validBidRequests, 'params.publisher'); + const siteId = setOnAny(validBidRequests, 'params.siteId'); + + const imp = validBidRequests.map((bid, id) => { + bid.netRevenue = pt; + const assets = utils._map(bid.nativeParams, (bidParams, key) => { + const props = NATIVE_PARAMS[key]; + const asset = { + required: bidParams.required & 1, + }; + if (props) { + asset.id = props.id; + asset[props.name] = { + len: bidParams.len, + wmin: bidParams.sizes && bidParams.sizes[0], + hmin: bidParams.sizes && bidParams.sizes[1], + type: props.type + }; + + return asset; + } + }).filter(Boolean); + + return { + id: id + 1, + tagid: bid.params.mid, + native: { + request: { + assets + } + } + }; + }); + + const request = { + id: bidderRequest.auctionId, + site: { id: siteId, page, publisher }, + device: { ua }, + source: { tid, fd: 1 }, + ext: { pt }, + imp + }; + + if (test) { + request.is_debug = !!test; + request.test = 1; + } + if (utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { + request.user = { ext: { consent: bidderRequest.gdprConsent.consentString } }; + request.regs = { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies & 1 } }; + } + + return { + method: 'POST', + url: '//' + adxDomain + '/adx/openrtb', + data: JSON.stringify(request), + options: { + contentType: 'application/json' + }, + bids: validBidRequests + }; + }, + interpretResponse: function(serverResponse, { bids }) { + if (!serverResponse.body) { + return; + } + const { seatbid, cur } = serverResponse.body; + + return bids.map((bid, id) => { + const _cbid = seatbid && seatbid[id] && seatbid[id].bid; + const bidResponse = _cbid && _cbid[0]; + if (bidResponse) { + return { + requestId: bid.bidId, + cpm: bidResponse.price, + creativeId: bidResponse.crid, + ttl: 360, + netRevenue: bid.netRevenue === 'net', + currency: cur, + mediaType: NATIVE, + bidderCode: BIDDER_CODE, + native: parseNative(bidResponse) + }; + } + }).filter(Boolean); + } +}; + +registerBidder(spec); + +function parseNative(bid) { + const { assets, link, imptrackers, jstracker } = bid.native; + 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 setOnAny(collection, key) { + for (let i = 0, result; i < collection.length; i++) { + result = utils.deepAccess(collection[i], key); + if (result) { + return result; + } + } +} diff --git a/modules/adformOpenRTBAdapter.md b/modules/adformOpenRTBAdapter.md new file mode 100644 index 00000000000..f59f039f3ec --- /dev/null +++ b/modules/adformOpenRTBAdapter.md @@ -0,0 +1,59 @@ +# Overview + +Module Name: Adform OpenRTB Adapter +Module Type: Bidder Adapter +Maintainer: Scope.FL.Scripts@adform.com + +# Description + +Module that connects to Adform demand sources to fetch bids. +Only native format is supported. Using OpenRTB standard. + +# Test Parameters +``` + var adUnits = [ + code: '/19968336/prebid_native_example_1', + sizes: [ + [360, 360] + ], + 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: 'adformOpenRTB', + params: { + mid: 606169, // required + adxDomain: 'axd.adform.net', // optional + siteId: '23455', // optional + priceType: 'gross' // optional, default is 'net' + publisher: { // optional block + id: "2706", + name: "Publishers Name", + domain: "publisher.com" + } + } + }] + ]; +``` diff --git a/test/spec/modules/adformOpenRTBAdapter_spec.js b/test/spec/modules/adformOpenRTBAdapter_spec.js new file mode 100644 index 00000000000..8e101c3d41b --- /dev/null +++ b/test/spec/modules/adformOpenRTBAdapter_spec.js @@ -0,0 +1,473 @@ +// jshint esversion: 6, es3: false, node: true +import {assert, expect} from 'chai'; +import * as url from 'src/url'; +import {spec} from 'modules/adformOpenRTBAdapter'; +import { NATIVE } from 'src/mediaTypes'; + +describe('AdformOpenRTB adapter', function () { + let serverResponse, bidRequest, bidResponses; + let bids = []; + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'adformOpenRTB', + 'params': { + 'mid': '19910113' + } + }; + + it('should return true when required params found', function () { + assert(spec.isBidRequestValid(bid)); + }); + + it('should return false when required params are missing', function () { + bid.params = { adxDomain: 'adx.adform.net' }; + assert.isFalse(spec.isBidRequestValid(bid)); + }); + }); + + describe('buildRequests', function () { + it('should send request with correct structure', function () { + let validBidRequests = [{ + bidId: 'bidId', + params: { + siteId: 'siteId', + adxDomain: '10.8.57.207' + } + }]; + let request = spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }); + + assert.equal(request.method, 'POST'); + assert.equal(request.url, '//10.8.57.207/adx/openrtb'); + assert.deepEqual(request.options, {contentType: 'application/json'}); + assert.ok(request.data); + }); + + describe('gdpr', function () { + it('should send GDPR Consent data to adform if gdprApplies', function () { + let validBidRequests = [{ bidId: 'bidId', params: { siteId: 'siteId', 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: { siteId: 'siteId', 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'); + }); + + it('should not send GDPR Consent data to adform if gdprApplies is false or 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, undefined); + assert.equal(request.regs, undefined); + }); + it('should send default GDPR Consent data to adform', 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 add test and is_debug to request, if test is set in parameters', function () { + let validBidRequests = [{ + bidId: 'bidId', + params: { siteId: 'siteId', 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 have default request structure', function () { + let keys = 'site,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); + }); + + 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('should send info about device', function () { + let validBidRequests = [{ + bidId: 'bidId', + params: { siteId: 'siteId' } + }]; + let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data); + + assert.equal(request.device.ua, navigator.userAgent); + }); + it('should send info about the site', function () { + let validBidRequests = [{ + bidId: 'bidId', + params: { siteId: 'siteId', publisher: {id: '123123', domain: 'publisher.domain.com', name: 'publisher\'s name'} } + }]; + let refererInfo = { referer: 'page' }; + let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo }).data); + + assert.deepEqual(request.site, { + page: refererInfo.referer, + publisher: validBidRequests[0].params.publisher, + id: validBidRequests[0].params.siteId + }); + }); + + describe('priceType', function () { + it('should send default priceType', function () { + let validBidRequests = [{ + bidId: 'bidId', + params: { siteId: 'siteId' } + }]; + let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data); + + assert.equal(request.ext.pt, 'net'); + }); + it('should send correct priceType value', function () { + let validBidRequests = [{ + bidId: 'bidId', + params: { siteId: 'siteId', priceType: 'net' } + }]; + let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data); + + assert.equal(request.ext.pt, 'net'); + }); + }); + + 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: { siteId: 'siteId' } + }, { + bidId: 'bidId2', + params: { siteId: 'siteId' } + }, { + bidId: 'bidId3', + params: { siteId: 'siteId' } + }]; + 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); + } + }); + + it('should add mid', function () { + let validBidRequests = [{ bidId: 'bidId', params: { siteId: 'siteId', mid: 1000 } }, + { bidId: 'bidId2', params: { siteId: 'siteId', mid: 1001 } }, + { bidId: 'bidId3', params: { siteId: 'siteId', mid: 1002 } }]; + 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.mid); + } + }); + + describe('native', function () { + describe('assets', function () { + it('should set correct asset id', function () { + let validBidRequests = [{ + bidId: 'bidId', + params: { siteId: 'siteId', mid: 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 assets = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp[0].native.request.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: { siteId: 'siteId', mid: 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 assets = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp[0].native.request.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: { siteId: 'siteId', mid: 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 assets = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp[0].native.request.assets; + assert.ok(assets[0].title); + assert.equal(assets[0].title.len, 140); + assert.deepEqual(assets[1].img, { type: 3, wmin: 150, hmin: 50 }); + assert.deepEqual(assets[2].img, { type: 1, wmin: 50, hmin: 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('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: 'impid1', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}}] + }, { + bid: [{impid: 'impid2', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, data: {value: 'Asset title text'}}]}}] + }] + } + }; + let bidRequest = { + data: {}, + bids: [ + { + bidId: 'bidId1', + params: { siteId: 'siteId', mid: 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: { siteId: 'siteId', mid: 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 } + } + } + ] + }; + + bids = spec.interpretResponse(serverResponse, bidRequest); + assert.equal(spec.interpretResponse(serverResponse, bidRequest).length, 2); + }); + it('should set correct values to bid', function () { + let serverResponse = { + body: { + id: null, + bidid: null, + seatbid: [{ + bid: [ + { + impid: 'impid1', + price: 93.1231, + crid: '12312312', + native: { + assets: [], + link: { url: 'link' }, + imptrackers: ['imptrackers url1', 'imptrackers url2'] + } + } + ] + }], + cur: 'NOK' + } + }; + let bidRequest = { + data: {}, + bids: [ + { + bidId: 'bidId1', + params: { siteId: 'siteId', mid: 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 } + } + } + ] + }; + + 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, 360); + assert.deepEqual(bids[0].netRevenue, false); + assert.deepEqual(bids[0].currency, serverResponse.body.cur); + assert.deepEqual(bids[0].mediaType, 'native'); + assert.deepEqual(bids[0].bidderCode, 'adformOpenRTB'); + }); + it('should set correct native params', function () { + const bid = [ + { + impid: 'impid1', + price: 93.1231, + crid: '12312312', + native: { + assets: [ + { + data: null, + id: 0, + img: null, + required: 0, + title: {text: 'title', len: null}, + video: null + }, { + data: null, + id: 2, + img: {type: null, url: 'test.url.com/Files/58345/308185.jpg?bv=1', w: 30, h: 10}, + required: 0, + title: null, + video: null + }, { + data: null, + id: 3, + img: {type: null, url: 'test.url.com/Files/58345/308200.jpg?bv=1', w: 100, h: 100}, + required: 0, + title: null, + video: null + }, { + data: {type: null, len: null, value: 'body'}, + id: 4, + img: null, + required: 0, + title: null, + video: null + }, { + data: {type: null, len: null, value: 'cta'}, + id: 1, + img: null, + required: 0, + title: null, + video: null + }, { + data: {type: null, len: null, value: 'sponsoredBy'}, + id: 5, + img: null, + required: 0, + title: null, + video: null + } + ], + link: { url: 'clickUrl', clicktrackers: ['clickTracker1', 'clickTracker2'] }, + imptrackers: ['imptrackers url1', 'imptrackers url2'], + jstracker: 'jstracker' + } + } + ]; + const serverResponse = { + body: { + id: null, + bidid: null, + seatbid: [{ bid }], + cur: 'NOK' + } + }; + let bidRequest = { + data: {}, + bids: [{ bidId: 'bidId1' }] + }; + + const result = spec.interpretResponse(serverResponse, bidRequest)[0].native; + const native = bid[0].native; + const assets = native.assets; + assert.deepEqual({ + clickUrl: native.link.url, + clickTrackers: native.link.clicktrackers, + impressionTrackers: native.imptrackers, + javascriptTrackers: [ native.jstracker ], + title: assets[0].title.text, + icon: {url: assets[1].img.url, width: assets[1].img.w, height: assets[1].img.h}, + image: {url: assets[2].img.url, width: assets[2].img.w, height: assets[2].img.h}, + body: assets[3].data.value, + cta: assets[4].data.value, + sponsoredBy: assets[5].data.value + }, result); + }); + it('should return empty when there is no bids in response', function () { + const serverResponse = { + body: { + id: null, + bidid: null, + seatbid: [{ bid: [] }], + cur: 'NOK' + } + }; + let bidRequest = { + data: {}, + bids: [{ bidId: 'bidId1' }] + }; + const result = spec.interpretResponse(serverResponse, bidRequest)[0]; + assert.ok(!result); + }); + }); +}); From a186c83096fc52293604cca44ec149b7b2843ce4 Mon Sep 17 00:00:00 2001 From: Js Date: Thu, 8 Nov 2018 20:09:28 +0100 Subject: [PATCH 0833/1594] Criteo adapter handles onSetTargeting and onBidWon (#3276) * Add onBidWon method to bid adapter spec * Add onSetTargeting method to bid adapter spec * Update the Criteo adapter to use the new event handlers * Update Criteo adapter version to 15 * Pass bid to handleSetTargeting --- modules/criteoBidAdapter.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 284c3f57406..8bf92c07f00 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -6,7 +6,7 @@ import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -const ADAPTER_VERSION = 14; +const ADAPTER_VERSION = 15; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -127,6 +127,26 @@ export const spec = { adapter.handleBidTimeout(); } }, + + /** + * @param {Bid} bid + */ + onBidWon: (bid) => { + if (publisherTagAvailable()) { + const adapter = Criteo.PubTag.Adapters.Prebid.GetAdapter(bid.auctionId); + adapter.handleBidWon(bid); + } + }, + + /** + * @param {Bid} bid + */ + onSetTargeting: (bid) => { + if (publisherTagAvailable()) { + const adapter = Criteo.PubTag.Adapters.Prebid.GetAdapter(bid.auctionId); + adapter.handleSetTargeting(bid); + } + }, }; /** From 771db1c03be476c8d1ea7597f0bbefb7a00b4d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Marek=20Sielski?= Date: Thu, 8 Nov 2018 19:11:47 +0000 Subject: [PATCH 0834/1594] fix: secure kargoBidAdapter against wrong Array extensions (#3275) --- modules/kargoBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 4f594c2856f..4d2190a29f1 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -76,8 +76,8 @@ export const spec = { let nameEquals = `${name}=`; let cookies = document.cookie.split(';'); - for (let key in cookies) { - let cookie = cookies[key]; + for (let i = 0; i < cookies.length; i++) { + let cookie = cookies[i]; while (cookie.charAt(0) === ' ') { cookie = cookie.substring(1, cookie.length); } From 1b5b83e366223cf0cab5c24ca707fb4906c7c093 Mon Sep 17 00:00:00 2001 From: Mikhail Ivanchenko Date: Mon, 12 Nov 2018 18:21:50 +0300 Subject: [PATCH 0835/1594] Add nextMilleniumBidAdapter (#3249) * Add nextMilleniumBidAdapter * fix bugs --- modules/nextMilleniumBidAdapter.js | 85 +++++++++++++++++ modules/nextMilleniumBidAdapter.md | 28 ++++++ .../modules/nextMilleniumBidAdapter_spec.js | 91 +++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 modules/nextMilleniumBidAdapter.js create mode 100644 modules/nextMilleniumBidAdapter.md create mode 100644 test/spec/modules/nextMilleniumBidAdapter_spec.js diff --git a/modules/nextMilleniumBidAdapter.js b/modules/nextMilleniumBidAdapter.js new file mode 100644 index 00000000000..0d91d58cd49 --- /dev/null +++ b/modules/nextMilleniumBidAdapter.js @@ -0,0 +1,85 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'nextMillenium'; +const HOST = 'https://brainlyads.com'; +const CURRENCY = 'USD'; +const TIME_TO_LIVE = 360; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: function(bid) { + return !!( + bid.params.placement_id && utils.isNumber(bid.params.placement_id) + ); + }, + + buildRequests: function(validBidRequests) { + let requests = []; + + utils._each(validBidRequests, function(bid) { + requests.push({ + method: 'POST', + url: HOST + '/hb/s2s', + options: { + contentType: 'application/json', + withCredentials: true + }, + data: JSON.stringify({ + placement_id: utils.getBidIdParameter('placement_id', bid.params) + }), + bidId: bid.bidId + }); + }); + + return requests; + }, + + interpretResponse: function(serverResponse, bidRequest) { + try { + const bidResponse = serverResponse.body; + const bidResponses = []; + + if (Number(bidResponse.cpm) > 0) { + bidResponses.push({ + requestId: bidRequest.bidId, + cpm: bidResponse.cpm, + width: bidResponse.width, + height: bidResponse.height, + creativeId: bidResponse.creativeId, + currency: CURRENCY, + netRevenue: false, + ttl: TIME_TO_LIVE, + ad: bidResponse.ad + }); + } + + return bidResponses; + } catch (err) { + utils.logError(err); + return []; + } + }, + + getUserSyncs: function(syncOptions) { + const syncs = [] + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: HOST + '/hb/s2s/matching' + }); + } + + if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: HOST + '/hb/s2s/matching' + }); + } + return syncs; + } +}; +registerBidder(spec); diff --git a/modules/nextMilleniumBidAdapter.md b/modules/nextMilleniumBidAdapter.md new file mode 100644 index 00000000000..a89e7e30822 --- /dev/null +++ b/modules/nextMilleniumBidAdapter.md @@ -0,0 +1,28 @@ +# Overview +``` +Module Name: NextMillenium Bid Adapter +Module Type: Bidder Adapter +Maintainer: mikhail.ivanchenko@iageengineering.net +``` + +# Description +Module that connects to NextMillenium's server for bids. +Currently module supports only banner mediaType. + +# Test Parameters +``` + var adUnits = [{ + code: '/test/div', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'nextMillenium', + params: { + placement_id: -1 + } + }] + }]; +``` \ No newline at end of file diff --git a/test/spec/modules/nextMilleniumBidAdapter_spec.js b/test/spec/modules/nextMilleniumBidAdapter_spec.js new file mode 100644 index 00000000000..74c8ff5dfd9 --- /dev/null +++ b/test/spec/modules/nextMilleniumBidAdapter_spec.js @@ -0,0 +1,91 @@ +import { expect } from 'chai'; +import { spec } from 'modules/nextMilleniumBidAdapter'; + +describe('nextMilleniumBidAdapterTests', function() { + let bidRequestData = { + bids: [ + { + bidId: 'transaction_1234', + bidder: 'nextMillenium', + params: { + placement_id: 12345 + }, + sizes: [[300, 250]] + } + ] + }; + let request = []; + + it('validate_pub_params', function() { + expect( + spec.isBidRequestValid({ + bidder: 'nextMillenium', + params: { + placement_id: 12345 + } + }) + ).to.equal(true); + }); + + it('validate_generated_params', function() { + let bidRequestData = [ + { + bidId: 'bid1234', + bidder: 'nextMillenium', + params: { placement_id: -1 }, + sizes: [[300, 250]] + } + ]; + let request = spec.buildRequests(bidRequestData); + expect(request[0].bidId).to.equal('bid1234'); + }); + + it('validate_getUserSyncs_function', function() { + expect(spec.getUserSyncs({ iframeEnabled: true })).to.have.lengthOf(1); + expect(spec.getUserSyncs({ iframeEnabled: false })).to.have.lengthOf(0); + + let pixel = spec.getUserSyncs({ iframeEnabled: true }); + expect(pixel[0].type).to.equal('iframe'); + expect(pixel[0].url).to.equal('https://brainlyads.com/hb/s2s/matching'); + }); + + it('validate_response_params', function() { + let serverResponse = { + body: { + cpm: 1.7, + width: 300, + height: 250, + creativeId: 'p35t0enob6twbt9mofjc8e', + ad: 'Hello! It\'s a test ad!' + } + }; + + let bids = spec.interpretResponse(serverResponse, bidRequestData.bids[0]); + expect(bids).to.have.lengthOf(1); + + let bid = bids[0]; + + expect(bid.creativeId).to.equal('p35t0enob6twbt9mofjc8e'); + expect(bid.ad).to.equal('Hello! It\'s a test ad!'); + expect(bid.cpm).to.equal(1.7); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.currency).to.equal('USD'); + }); + + it('validate_response_params_with passback', function() { + let serverResponse = { + body: [ + { + hash: '1e100887dd614b0909bf6c49ba7f69fdd1360437', + content: 'Ad html passback', + size: [300, 250], + is_passback: 1 + } + ] + }; + let bids = spec.interpretResponse(serverResponse); + + expect(bids).to.have.lengthOf(0); + }); +}); From 7904190ffc9931acad10a7122e205cf641009822 Mon Sep 17 00:00:00 2001 From: Denis Logachev Date: Mon, 12 Nov 2018 18:35:06 +0300 Subject: [PATCH 0836/1594] Alias for adkernelAdn adapter (#3289) --- modules/adkernelAdnBidAdapter.js | 1 + test/spec/modules/adkernelAdnBidAdapter_spec.js | 7 +++++++ test/spec/modules/adkernelBidAdapter_spec.js | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index 60c33170b3c..55690a79281 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -113,6 +113,7 @@ function buildBid(tag) { export const spec = { code: 'adkernelAdn', supportedMediaTypes: [BANNER, VIDEO], + aliases: ['engagesimply'], isBidRequestValid: function(bidRequest) { return 'params' in bidRequest && (typeof bidRequest.params.host === 'undefined' || typeof bidRequest.params.host === 'string') && diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index fe71d968571..43e2dec7ce9 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -298,4 +298,11 @@ describe('AdkernelAdn adapter', function () { expect(syncs).to.have.length(0); }); }); + + describe('adapter configuration', () => { + it('should have aliases', () => { + expect(spec.aliases).to.have.lengthOf(1); + expect(spec.aliases[0]).to.be.equal('engagesimply'); + }); + }); }); diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index 3243b980b9f..0668e84869a 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -300,4 +300,11 @@ describe('Adkernel adapter', function () { expect(syncs[0]).to.have.property('url', 'http://adk.sync.com/sync'); }); }); + + describe('adapter configuration', () => { + it('should have aliases', () => { + expect(spec.aliases).to.have.lengthOf(1); + expect(spec.aliases[0]).to.be.equal('headbidding'); + }); + }); }); From 40c8284cfcd4adedee25861dab3b0b845eada084 Mon Sep 17 00:00:00 2001 From: rjvelicaria Date: Tue, 13 Nov 2018 06:24:50 -0800 Subject: [PATCH 0837/1594] add support for platform ids (#3282) --- modules/openxBidAdapter.js | 14 +++- modules/openxBidAdapter.md | 14 +++- test/spec/modules/openxBidAdapter_spec.js | 80 +++++++++++++++++++++++ 3 files changed, 103 insertions(+), 5 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index ee1fa58a4e9..7119d669cb4 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -20,11 +20,12 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { - if (utils.deepAccess(bidRequest, 'mediaTypes.banner') && bidRequest.params.delDomain) { + const hasDelDomainOrPlatform = bidRequest.params.delDomain || bidRequest.params.platform; + if (utils.deepAccess(bidRequest, 'mediaTypes.banner') && hasDelDomainOrPlatform) { return !!bidRequest.params.unit || utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes.length') > 0; } - return !!(bidRequest.params.unit && bidRequest.params.delDomain); + return !!(bidRequest.params.unit && hasDelDomainOrPlatform); }, buildRequests: function (bidRequests, bidderRequest) { if (bidRequests.length === 0) { @@ -206,6 +207,10 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { nocache: new Date().getTime() }; + if (bids[0].params.platform) { + defaultParams.ph = bids[0].params.platform; + } + if (utils.deepAccess(bidderRequest, 'gdprConsent')) { let gdprConsentConfig = bidderRequest.gdprConsent; @@ -277,7 +282,10 @@ function buildOXBannerRequest(bids, bidderRequest) { queryParams.aumfs = customFloorsForAllBids.join(','); } - let url = `//${bids[0].params.delDomain}/w/1.0/arj`; + let url = queryParams.ph + ? `//u.openx.net/w/1.0/arj` + : `//${bids[0].params.delDomain}/w/1.0/arj`; + return { method: 'GET', url: url, diff --git a/modules/openxBidAdapter.md b/modules/openxBidAdapter.md index 243b2e53104..042399cf023 100644 --- a/modules/openxBidAdapter.md +++ b/modules/openxBidAdapter.md @@ -15,7 +15,7 @@ Module that connects to OpenX's demand sources | Name | Scope | Type | Description | Example | ---- | ----- | ---- | ----------- | ------- -| `delDomain` | required | String | OpenX delivery domain provided by your OpenX representative. | "PUBLISHER-d.openx.net" +| `delDomain` or `platform` | required | String | OpenX delivery domain or platform id provided by your OpenX representative. | "PUBLISHER-d.openx.net" or "555not5a-real-plat-form-id0123456789" | `unit` | required | String | OpenX ad unit ID provided by your OpenX representative. | "1611023122" | `customParams` | optional | Object | User-defined targeting key-value pairs. customParams applies to a specific unit. | `{key1: "v1", key2: ["v2","v3"]}` | `customFloor` | optional | Number | Minimum price in USD. customFloor applies to a specific unit. For example, use the following value to set a $1.50 floor: 1.50

**WARNING:**
Misuse of this parameter can impact revenue | 1.50 @@ -49,7 +49,17 @@ var adUnits = [ key2: ['v2', 'v3'] }, } - } + }, { + bidder: 'openx', + params: { + unit: '539439964', + platform: 'a3aece0c-9e80-4316-8deb-faf804779bd1', + customParams: { + key1: 'v1', + key2: ['v2', 'v3'] + }, + } + } ] }, { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index eff78b4d9a3..8a602dc479b 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -279,16 +279,96 @@ describe('OpenxAdapter', function () { 'bidderRequestId': 'test-bid-request-2', 'auctionId': 'test-auction-2' }]; + const bidRequestsWithPlatform = [{ + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + }, + 'adUnitCode': '/adunit-code/test-path', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + }, + 'adUnitCode': '/adunit-code/test-path', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }]; + const bidRequestsWithPlatformAndDelDomain = [{ + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + }, + 'adUnitCode': '/adunit-code/test-path', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + }, + 'adUnitCode': '/adunit-code/test-path', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }]; it('should send bid request to openx url via GET, with mediaType specified as banner', function () { const request = spec.buildRequests(bidRequestsWithMediaType); expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASE); + expect(request[0].data.ph).to.be.undefined; expect(request[0].method).to.equal('GET'); }); it('should send bid request to openx url via GET, with mediaTypes specified with banner type', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASE); + expect(request[0].data.ph).to.be.undefined; + expect(request[0].method).to.equal('GET'); + }); + + it('should send bid request to openx platform url via GET, if platform is present', function () { + const request = spec.buildRequests(bidRequestsWithPlatform); + expect(request[0].url).to.equal(`//u.openx.net${URLBASE}`); + expect(request[0].data.ph).to.equal(bidRequestsWithPlatform[0].params.platform); + expect(request[0].method).to.equal('GET'); + }); + + it('should send bid request to openx platform url via GET, if both params present', function () { + const request = spec.buildRequests(bidRequestsWithPlatformAndDelDomain); + expect(request[0].url).to.equal(`//u.openx.net${URLBASE}`); + expect(request[0].data.ph).to.equal(bidRequestsWithPlatform[0].params.platform); expect(request[0].method).to.equal('GET'); }); From e8347355b4a733e840ada8bf305108b440f78c8c Mon Sep 17 00:00:00 2001 From: pokutuna Date: Tue, 13 Nov 2018 23:51:28 +0900 Subject: [PATCH 0838/1594] handles empty responses in getUserSyncs & add tests - ajaBidAdapter (#3283) --- modules/ajaBidAdapter.js | 2 +- test/spec/modules/ajaBidAdapter_spec.js | 42 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/modules/ajaBidAdapter.js b/modules/ajaBidAdapter.js index bbdbeb53886..ff44aaa1208 100644 --- a/modules/ajaBidAdapter.js +++ b/modules/ajaBidAdapter.js @@ -93,7 +93,7 @@ export const spec = { getUserSyncs: function(syncOptions, serverResponses) { const syncs = []; - if (syncOptions.pixelEnabled) { + if (syncOptions.pixelEnabled && serverResponses.length) { const bidderResponseBody = serverResponses[0].body; if (bidderResponseBody.syncs) { bidderResponseBody.syncs.forEach(sync => { diff --git a/test/spec/modules/ajaBidAdapter_spec.js b/test/spec/modules/ajaBidAdapter_spec.js index 5d5e5924cd5..8561f8c0baf 100644 --- a/test/spec/modules/ajaBidAdapter_spec.js +++ b/test/spec/modules/ajaBidAdapter_spec.js @@ -141,4 +141,46 @@ describe('AjaAdapter', function () { expect(result.length).to.equal(0); }); }); + + describe('getUserSyncs', function () { + const bidResponse1 = { + body: { + 'is_ad_return': true, + 'ad': { /* ad body */ }, + 'syncs': [ + 'https://example.test/1' + ] + } + }; + + const bidResponse2 = { + body: { + 'is_ad_return': true, + 'ad': { /* ad body */ }, + 'syncs': [ + 'https://example.test/2' + ] + } + }; + + it('should use a sync url from first response', function () { + const syncs = spec.getUserSyncs({ pixelEnabled: true }, [bidResponse1, bidResponse2]); + expect(syncs).to.deep.equal([ + { + type: 'image', + url: 'https://example.test/1' + } + ]); + }); + + 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 }, [bidResponse1]); + expect(syncs).to.deep.equal([]); + }); + }); }); From c7482b59a9df614a067c169076b96a80835411d7 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 13 Nov 2018 15:41:13 -0500 Subject: [PATCH 0839/1594] Prebid 1.32.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 18ccc07800b..f448cf22178 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.32.0-pre", + "version": "1.32.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From aa61b7661c0d0bf2f1cc4c7b77274ce979991753 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 13 Nov 2018 15:48:47 -0500 Subject: [PATCH 0840/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f448cf22178..9f99f1dcc1d 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.32.0", + "version": "1.33.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 433efea4177e2ed9947ed5b1235b849969d13ef8 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Wed, 14 Nov 2018 12:49:57 -0500 Subject: [PATCH 0841/1594] kargo adapter deal support (#3292) --- modules/kargoBidAdapter.js | 1 + test/spec/modules/kargoBidAdapter_spec.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 4d2190a29f1..e4d3d09a8e0 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -50,6 +50,7 @@ export const spec = { ad: adUnit.adm, ttl: 300, creativeId: adUnit.id, + dealId: adUnit.targetingCustom, netRevenue: true, currency: bidRequest.currency }); diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 680b402392a..3e8bc6c7f92 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -361,7 +361,8 @@ describe('kargo adapter tests', function () { cpm: 2.5, adm: '
', width: 300, - height: 250 + height: 250, + targetingCustom: 'dmpmptest1234' }, 3: { id: 'bar', @@ -397,6 +398,7 @@ describe('kargo adapter tests', function () { ad: '
', ttl: 300, creativeId: 'foo', + dealId: undefined, netRevenue: true, currency: 'USD' }, { @@ -407,6 +409,7 @@ describe('kargo adapter tests', function () { ad: '
', ttl: 300, creativeId: 'bar', + dealId: 'dmpmptest1234', netRevenue: true, currency: 'USD' }, { @@ -417,6 +420,7 @@ describe('kargo adapter tests', function () { ad: '
', ttl: 300, creativeId: 'bar', + dealId: undefined, netRevenue: true, currency: 'USD' }]; From 3320a83ed31e5b243a9e0e534937f86ef939b7d7 Mon Sep 17 00:00:00 2001 From: Gena Date: Wed, 14 Nov 2018 20:10:16 +0100 Subject: [PATCH 0842/1594] Add new alias for Adtelligent adapter (#3295) * Add new alias for Adtelligent adapter * Fix alias --- modules/adtelligentBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/adtelligentBidAdapter.js b/modules/adtelligentBidAdapter.js index ed7da360e0b..65181c70ed9 100644 --- a/modules/adtelligentBidAdapter.js +++ b/modules/adtelligentBidAdapter.js @@ -12,6 +12,7 @@ const DISPLAY = 'display'; export const spec = { code: BIDDER_CODE, + aliases: ['onefiftytwomedia'], supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { return bid && bid.params && bid.params.aid; From 259af196dd5c4a9aea65c6fb7a41b1bbd550fc0c Mon Sep 17 00:00:00 2001 From: John Rosendahl Date: Wed, 14 Nov 2018 17:54:28 -0700 Subject: [PATCH 0843/1594] Updated Sovrn Bid Adaptor for MultiSized and added Error Call Home. (#3237) * Updated Bid Adaptor for MultiSized and added Error Call Home * Updated to conform with prebid requirements * added missing this * Added tests for more coverage * simplified error object for edge 15 --- modules/sovrnBidAdapter.js | 216 ++++++++++++++-------- test/spec/modules/sovrnBidAdapter_spec.js | 140 ++++++++++++-- 2 files changed, 266 insertions(+), 90 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 4f1eb298794..7ebe5dd0ecc 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -1,7 +1,9 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; -import { REPO_AND_VERSION } from 'src/constants'; +import * as utils from 'src/utils' +import { registerBidder } from 'src/adapters/bidderFactory' +import { BANNER } from 'src/mediaTypes' +import { REPO_AND_VERSION } from 'src/constants' +const errorUrl = 'https://pcb.aws.lijit.com/c' +let errorpxls = [] export const spec = { code: 'sovrn', @@ -22,48 +24,59 @@ export const spec = { * @return object of parameters for Prebid AJAX request */ buildRequests: function(bidReqs, bidderRequest) { - const loc = utils.getTopWindowLocation(); - let sovrnImps = []; - let iv; - utils._each(bidReqs, function (bid) { - iv = iv || utils.getBidIdParameter('iv', bid.params); - sovrnImps.push({ - id: bid.bidId, - banner: { w: 1, h: 1 }, - tagid: String(utils.getBidIdParameter('tagid', bid.params)), - bidfloor: utils.getBidIdParameter('bidfloor', bid.params) + try { + const loc = utils.getTopWindowLocation(); + let sovrnImps = []; + let iv; + utils._each(bidReqs, function (bid) { + iv = iv || utils.getBidIdParameter('iv', bid.params); + bid.sizes = ((utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]) + bid.sizes = bid.sizes.filter(size => utils.isArray(size)) + const processedSizes = bid.sizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) + sovrnImps.push({ + id: bid.bidId, + banner: { + format: processedSizes, + w: 1, + h: 1, + }, + tagid: String(utils.getBidIdParameter('tagid', bid.params)), + bidfloor: utils.getBidIdParameter('bidfloor', bid.params) + }); }); - }); - const sovrnBidReq = { - id: utils.getUniqueIdentifierStr(), - imp: sovrnImps, - site: { - domain: loc.host, - page: loc.host + loc.pathname + loc.search + loc.hash - } - }; + const sovrnBidReq = { + id: utils.getUniqueIdentifierStr(), + imp: sovrnImps, + site: { + domain: loc.host, + page: loc.host + loc.pathname + loc.search + loc.hash + } + }; - if (bidderRequest && bidderRequest.gdprConsent) { - sovrnBidReq.regs = { - ext: { - gdpr: +bidderRequest.gdprConsent.gdprApplies - }}; - sovrnBidReq.user = { - ext: { - consent: bidderRequest.gdprConsent.consentString - }}; - } + if (bidderRequest && bidderRequest.gdprConsent) { + sovrnBidReq.regs = { + ext: { + gdpr: +bidderRequest.gdprConsent.gdprApplies + }}; + sovrnBidReq.user = { + ext: { + consent: bidderRequest.gdprConsent.consentString + }}; + } - let url = `//ap.lijit.com/rtb/bid?` + - `src=${REPO_AND_VERSION}`; - if (iv) url += `&iv=${iv}`; + let url = `//ap.lijit.com/rtb/bid?` + + `src=${REPO_AND_VERSION}`; + if (iv) url += `&iv=${iv}`; - return { - method: 'POST', - url: url, - data: JSON.stringify(sovrnBidReq), - options: {contentType: 'text/plain'} - }; + return { + method: 'POST', + url: url, + data: JSON.stringify(sovrnBidReq), + options: {contentType: 'text/plain'} + } + } catch (e) { + new LogError(e, {bidReqs, bidderRequest}).append() + } }, /** @@ -72,48 +85,99 @@ export const spec = { * @return {Bid[]} An array of formatted bids. */ interpretResponse: function({ body: {id, seatbid} }) { - 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), - height: parseInt(sovrnBid.h), - creativeId: sovrnBid.crid || sovrnBid.id, - dealId: sovrnBid.dealid || null, - currency: 'USD', - netRevenue: true, - mediaType: BANNER, - ad: decodeURIComponent(`${sovrnBid.adm}`), - ttl: 60 + try { + 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), + height: parseInt(sovrnBid.h), + creativeId: sovrnBid.crid || sovrnBid.id, + dealId: sovrnBid.dealid || null, + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: decodeURIComponent(`${sovrnBid.adm}`), + ttl: 60 + }); }); - }); + } + return sovrnBidResponses + } catch (e) { + new LogError(e, {id, seatbid}).append() } - return sovrnBidResponses; }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { - if (serverResponses && serverResponses.length !== 0 && syncOptions.iframeEnabled) { - let iidArr = serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.iid) - .map(rsp => { return rsp.body.ext.iid }); - let consentString = ''; - if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { - consentString = gdprConsent.consentString + try { + let tracks = [] + if (serverResponses && serverResponses.length !== 0 && syncOptions.iframeEnabled) { + let iidArr = serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.iid) + .map(rsp => { return rsp.body.ext.iid }); + let consentString = ''; + if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { + consentString = gdprConsent.consentString + } + if (iidArr[0]) { + tracks.push({ + type: 'iframe', + url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, + }); + } + } + if (errorpxls.length && syncOptions.pixelEnabled) { + tracks = tracks.concat(errorpxls) } - if (iidArr[0]) { - return [{ - type: 'iframe', - url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, - }]; + return tracks + } catch (e) { + if (syncOptions.pixelEnabled) { + return errorpxls } + return [] } - return []; }, -}; +} + +export class LogError { + constructor(e, data) { + utils.logError(e) + this.error = {} + this.error.t = utils.timestamp() + this.error.m = e.message + this.error.s = e.stack + this.error.d = data + this.error.v = REPO_AND_VERSION + this.error.u = utils.getTopWindowLocation().href + this.error.ua = navigator.userAgent + } + buildErrorString(obj) { + return errorUrl + '?b=' + btoa(JSON.stringify(obj)) + } + append() { + let errstr = this.buildErrorString(this.error) + if (errstr.length > 2083) { + delete this.error.d + errstr = this.buildErrorString(this.error) + if (errstr.length > 2083) { + delete this.error.s + errstr = this.buildErrorString(this.error) + if (errstr.length > 2083) { + errstr = this.buildErrorString({m: 'unknown error message', t: this.error.t, u: this.error.u}) + } + } + } + let obj = {type: 'image', url: errstr} + errorpxls.push(obj) + } + static getErrPxls() { + return errorpxls + } +} registerBidder(spec); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 22c93505ecf..a774aa64062 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -1,7 +1,8 @@ import { expect } from 'chai'; -import { spec } from 'modules/sovrnBidAdapter'; +import { spec, LogError } from 'modules/sovrnBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import { REPO_AND_VERSION } from 'src/constants'; +import { SSL_OP_SINGLE_ECDH_USE } from 'constants'; const ENDPOINT = `//ap.lijit.com/rtb/bid?src=${REPO_AND_VERSION}`; @@ -16,7 +17,8 @@ describe('sovrnBidAdapter', function() { }, 'adUnitCode': 'adunit-code', 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -47,7 +49,8 @@ describe('sovrnBidAdapter', function() { }, 'adUnitCode': 'adunit-code', 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -64,6 +67,33 @@ describe('sovrnBidAdapter', function() { expect(request.url).to.equal(ENDPOINT) }); + it('sets the proper banner object', function() { + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]) + expect(payload.imp[0].banner.w).to.equal(1) + expect(payload.imp[0].banner.h).to.equal(1) + }) + + it('accepts a single array as a size', function() { + const singleSize = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': '403370', + 'iv': 'vet' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [300, 250], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + const request = spec.buildRequests(singleSize) + const payload = JSON.parse(request.data) + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]) + expect(payload.imp[0].banner.w).to.equal(1) + expect(payload.imp[0].banner.h).to.equal(1) + }) + it('sends \'iv\' as query param if present', function () { const ivBidRequests = [{ 'bidder': 'sovrn', @@ -73,7 +103,8 @@ describe('sovrnBidAdapter', function() { }, 'adUnitCode': 'adunit-code', 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -116,7 +147,8 @@ describe('sovrnBidAdapter', function() { }, 'adUnitCode': 'adunit-code', 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -268,19 +300,99 @@ describe('sovrnBidAdapter', function() { 'type': 'iframe', 'url': '//ap.lijit.com/beacon?informer=13487408&gdpr_consent=', } - ]; + ] let returnStatement = spec.getUserSyncs(syncOptions, serverResponse); expect(returnStatement[0]).to.deep.equal(expectedReturnStatement[0]); - }); + }) it('should not return if iid missing on server response', () => { - let returnStatement = spec.getUserSyncs(syncOptions, []); + let returnStatement = spec.getUserSyncs(syncOptions, []) expect(returnStatement).to.be.empty; - }); + }) it('should not return if iframe syncs disabled', () => { - let returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse); - expect(returnStatement).to.be.empty; - }); - }); -}); + let returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse) + expect(returnStatement).to.be.empty + }) + }) + describe('LogError', () => { + it('should build and append an error object', () => { + const thrown = { + message: 'message', + stack: 'stack' + } + const data = {name: 'Oscar Hathenswiotch'} + const err = new LogError(thrown, data) + err.append() + const errList = LogError.getErrPxls() + expect(errList.length).to.equal(1) + const errdata = JSON.parse(atob(errList[0].url.split('=')[1])) + expect(errdata.d.name).to.equal('Oscar Hathenswiotch') + }) + it('should drop data when there is too much', () => { + const thrown = { + message: 'message', + stack: 'stack' + } + const tooLong = () => { + let str = '' + for (let i = 0; i < 10000; i++) { + str = str + String.fromCharCode(i % 100) + } + return str + } + const data = {name: 'Oscar Hathenswiotch', tooLong: tooLong()} + const err = new LogError(thrown, data) + err.append() + const errList = LogError.getErrPxls() + expect(errList.length).to.equal(2) + const errdata = JSON.parse(atob(errList[1].url.split('=')[1])) + expect(errdata.d).to.be.an('undefined') + }) + it('should drop data and stack when there is too much', () => { + const thrown = { + message: 'message', + stack: 'stack' + } + const tooLong = () => { + let str = '' + for (let i = 0; i < 10000; i++) { + str = str + String.fromCharCode(i % 100) + } + return str + } + const data = {name: 'Oscar Hathenswiotch'} + thrown.stack = tooLong() + const err = new LogError(thrown, data) + err.append() + const errList = LogError.getErrPxls() + expect(errList.length).to.equal(3) + const errdata = JSON.parse(atob(errList[2].url.split('=')[1])) + expect(errdata.d).to.be.an('undefined') + expect(errdata.s).to.be.an('undefined') + }) + it('should drop send a reduced message when other reduction methods fail', () => { + const thrown = { + message: 'message', + stack: 'stack' + } + const tooLong = () => { + let str = '' + for (let i = 0; i < 10000; i++) { + str = str + String.fromCharCode(i % 100) + } + return str + } + const data = {name: 'Oscar Hathenswiotch'} + thrown.message = tooLong() + const err = new LogError(thrown, data) + err.append() + const errList = LogError.getErrPxls() + expect(errList.length).to.equal(4) + const errdata = JSON.parse(atob(errList[3].url.split('=')[1])) + expect(errdata.d).to.be.an('undefined') + expect(errdata.s).to.be.an('undefined') + expect(errdata.m).to.equal('unknown error message') + }) + }) +}) From 8f53dca05a6377c6f4f1713030ef403edf421ab1 Mon Sep 17 00:00:00 2001 From: Dave Naffis Date: Thu, 15 Nov 2018 11:08:25 -0500 Subject: [PATCH 0844/1594] update the TTL for winning bids to 30s (#3296) * update the TTL for winning bids to 30s * update test for TTL update --- modules/consumableBidAdapter.js | 2 +- test/spec/modules/consumableBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/consumableBidAdapter.js b/modules/consumableBidAdapter.js index 8ed0f6dfc91..a2e505bc744 100644 --- a/modules/consumableBidAdapter.js +++ b/modules/consumableBidAdapter.js @@ -111,7 +111,7 @@ export const spec = { bid.ad = retrieveAd(decision, bid.unitId, bid.unitName); bid.currency = 'USD'; bid.creativeId = decision.adId; - bid.ttl = 360; + bid.ttl = 30; bid.netRevenue = true; bid.referrer = utils.getTopWindowUrl(); diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index d13c3c56398..2628ed6e5c4 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -232,7 +232,7 @@ describe('Consumable BidAdapter', function () { expect(b).to.have.property('ad'); expect(b).to.have.property('currency', 'USD'); expect(b).to.have.property('creativeId'); - expect(b).to.have.property('ttl', 360); + expect(b).to.have.property('ttl', 30); expect(b).to.have.property('netRevenue', true); expect(b).to.have.property('referrer'); }); From 186ee66de03b80746844aaa1c0dfec3ad3bd682e Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Thu, 15 Nov 2018 10:03:21 -0700 Subject: [PATCH 0845/1594] only set mediaTypes.banner.sizes from sizes if mediaTypes doesn't exist. (#3274) fixed #3269 --- src/sizeMapping.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/sizeMapping.js b/src/sizeMapping.js index 2cf1b1a0fa9..1a9746205b6 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -65,22 +65,20 @@ export function resolveStatus({labels = [], labelAll = false, activeLabels = []} let maps = evaluateSizeConfig(configs); if (!isPlainObject(mediaTypes)) { - mediaTypes = {}; + // add support for deprecated adUnit.sizes by creating correct banner mediaTypes if they don't already exist + if (sizes) { + mediaTypes = { + banner: { + sizes + } + }; + } else { + mediaTypes = {}; + } } else { mediaTypes = deepClone(mediaTypes); } - // add support for deprecated adUnit.sizes by creating correct banner mediaTypes if they don't already exist - if (sizes) { - if (!mediaTypes.banner) { - mediaTypes.banner = { - sizes - } - } else if (!mediaTypes.banner.sizes) { - mediaTypes.banner.sizes = sizes; - } - } - let oldSizes = deepAccess(mediaTypes, 'banner.sizes'); if (maps.shouldFilter && oldSizes) { mediaTypes.banner.sizes = oldSizes.filter(size => maps.sizesSupported[size]); From 6c4243c9be8e21ac9e59901f6f8e9acca1ec364c Mon Sep 17 00:00:00 2001 From: haohany Date: Thu, 15 Nov 2018 22:05:21 -0800 Subject: [PATCH 0846/1594] OpenX analytics adapter (#3285) --- modules/openxAnalyticsAdapter.js | 253 ++++++++++ .../modules/openxAnalyticsAdapter_spec.js | 445 ++++++++++++++++++ 2 files changed, 698 insertions(+) create mode 100644 modules/openxAnalyticsAdapter.js create mode 100644 test/spec/modules/openxAnalyticsAdapter_spec.js diff --git a/modules/openxAnalyticsAdapter.js b/modules/openxAnalyticsAdapter.js new file mode 100644 index 00000000000..c4808dd13c0 --- /dev/null +++ b/modules/openxAnalyticsAdapter.js @@ -0,0 +1,253 @@ +import adapter from 'src/AnalyticsAdapter'; +import CONSTANTS from 'src/constants.json'; +import adaptermanager from 'src/adaptermanager'; +import { config } from 'src/config'; +import { ajax } from 'src/ajax'; +import * as utils from 'src/utils'; + +const { + EVENTS: { AUCTION_INIT, BID_REQUESTED, BID_RESPONSE, BID_TIMEOUT, BID_WON } +} = CONSTANTS; + +const SLOT_LOADED = 'slotOnload'; + +const ENDPOINT = '//ads.openx.net/w/1.0/pban'; + +let initOptions; + +let auctionMap = {}; + +function onAuctionInit({ auctionId }) { + auctionMap[auctionId] = { + adUnitMap: {} + }; +} + +function onBidRequested({ auctionId, auctionStart, bids, start }) { + const adUnitMap = auctionMap[auctionId]['adUnitMap']; + + bids.forEach(bid => { + const { adUnitCode, bidId, bidder, params, transactionId } = bid; + + adUnitMap[adUnitCode] = adUnitMap[adUnitCode] || { + auctionId, + auctionStart, + transactionId, + bidMap: {} + }; + + adUnitMap[adUnitCode]['bidMap'][bidId] = { + bidder, + params, + requestTimestamp: start + }; + }); +} + +function onBidResponse({ + auctionId, + adUnitCode, + adId: bidId, + cpm, + creativeId, + responseTimestamp, + ts +}) { + const adUnit = auctionMap[auctionId]['adUnitMap'][adUnitCode]; + const bid = adUnit['bidMap'][bidId]; + bid.cpm = cpm; + bid.creativeId = creativeId; + bid.responseTimestamp = responseTimestamp; + bid.ts = ts; +} + +function onBidTimeout(args) { + utils + ._map(args, value => value) + .forEach(({ auctionId, adUnitCode, bidId }) => { + const bid = + auctionMap[auctionId]['adUnitMap'][adUnitCode]['bidMap'][bidId]; + bid.timedOut = true; + }); +} + +function onBidWon({ auctionId, adUnitCode, adId: bidId }) { + const adUnit = auctionMap[auctionId]['adUnitMap'][adUnitCode]; + const bid = adUnit['bidMap'][bidId]; + bid.won = true; +} + +function onSlotLoaded({ slot }) { + const targeting = slot.getTargetingKeys().reduce((targeting, key) => { + targeting[key] = slot.getTargeting(key); + return targeting; + }, {}); + utils.logMessage( + 'GPT slot is loaded. Current targeting set on slot:', + targeting + ); + + const bidId = slot.getTargeting('hb_adid')[0]; + const adUnit = getAdUnitByBidId(bidId); + + if (!adUnit) { + return; + } + + const adUnitData = getAdUnitData(adUnit); + const performanceData = getPerformanceData(adUnit.auctionStart); + const commonFields = { + 'hb.asiid': slot.getAdUnitPath(), + 'hb.cur': config.getConfig('currency.adServerCurrency'), + 'hb.pubid': initOptions.publisherId + }; + + const data = Object.assign({}, adUnitData, performanceData, commonFields); + sendEvent(data); +} + +function getAdUnitByBidId(bidId) { + let result; + + utils._map(auctionMap, value => value).forEach(auction => { + utils._map(auction.adUnitMap, value => value).forEach(adUnit => { + if (bidId in adUnit.bidMap) { + result = adUnit; + } + }); + }); + + return result; +} + +function getAdUnitData(adUnit) { + const bids = utils._map(adUnit.bidMap, value => value); + const bidders = bids.map(bid => bid.bidder); + const requestTimes = bids.map( + bid => bid.requestTimestamp && bid.requestTimestamp - adUnit.auctionStart + ); + const responseTimes = bids.map( + bid => bid.responseTimestamp && bid.responseTimestamp - adUnit.auctionStart + ); + const bidValues = bids.map(bid => bid.cpm || 0); + const timeouts = bids.map(bid => !!bid.timedOut); + const creativeIds = bids.map(bid => bid.creativeId); + const winningBid = bids.filter(bid => bid.won)[0]; + const winningExchangeIndex = bids.indexOf(winningBid); + const openxBid = bids.filter(bid => bid.bidder === 'openx')[0]; + + return { + 'hb.ct': adUnit.auctionStart, + 'hb.rid': adUnit.auctionId, + 'hb.exn': bidders.join(','), + 'hb.sts': requestTimes.join(','), + 'hb.ets': responseTimes.join(','), + 'hb.bv': bidValues.join(','), + 'hb.to': timeouts.join(','), + 'hb.crid': creativeIds.join(','), + 'hb.we': winningExchangeIndex, + 'hb.g1': winningExchangeIndex === -1, + dddid: adUnit.transactionId, + ts: openxBid && openxBid.ts, + auid: openxBid && openxBid.params && openxBid.params.unit + }; +} + +function getPerformanceData(auctionStart) { + let timing; + try { + timing = window.top.performance.timing; + } catch (e) {} + + if (!timing) { + return; + } + + const { fetchStart, domContentLoadedEventEnd, loadEventEnd } = timing; + const domContentLoadTime = domContentLoadedEventEnd - fetchStart; + const pageLoadTime = loadEventEnd - fetchStart; + const timeToAuction = auctionStart - fetchStart; + const timeToRender = Date.now() - fetchStart; + + return { + 'hb.dcl': domContentLoadTime, + 'hb.dl': pageLoadTime, + 'hb.tta': timeToAuction, + 'hb.ttr': timeToRender + }; +} + +function sendEvent(data) { + utils._map(data, (value, key) => [key, value]).forEach(([key, value]) => { + if ( + value === undefined || + value === null || + (typeof value === 'number' && isNaN(value)) + ) { + delete data[key]; + } + }); + ajax(ENDPOINT, null, data, { method: 'GET' }); +} + +let googletag = window.googletag || {}; +googletag.cmd = googletag.cmd || []; +googletag.cmd.push(function() { + googletag.pubads().addEventListener(SLOT_LOADED, args => { + openxAdapter.track({ eventType: SLOT_LOADED, args }); + }); +}); + +const openxAdapter = Object.assign( + adapter({ url: ENDPOINT, analyticsType: 'endpoint' }), + { + track({ eventType, args }) { + utils.logMessage(eventType, Object.assign({}, args)); + switch (eventType) { + case AUCTION_INIT: + onAuctionInit(args); + break; + case BID_REQUESTED: + onBidRequested(args); + break; + case BID_RESPONSE: + onBidResponse(args); + break; + case BID_TIMEOUT: + onBidTimeout(args); + break; + case BID_WON: + onBidWon(args); + break; + case SLOT_LOADED: + onSlotLoaded(args); + break; + } + } + } +); + +// save the base class function +openxAdapter.originEnableAnalytics = openxAdapter.enableAnalytics; + +// override enableAnalytics so we can get access to the config passed in from the page +openxAdapter.enableAnalytics = function(config) { + if (!config || !config.options || !config.options.publisherId) { + utils.logError('OpenX analytics adapter: publisherId is required.'); + return; + } + initOptions = config.options; + openxAdapter.originEnableAnalytics(config); // call the base class function +}; + +// reset the cache for unit tests +openxAdapter.reset = function() { + auctionMap = {}; +}; + +adaptermanager.registerAnalyticsAdapter({ + adapter: openxAdapter, + code: 'openx' +}); + +export default openxAdapter; diff --git a/test/spec/modules/openxAnalyticsAdapter_spec.js b/test/spec/modules/openxAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..7b73b11887f --- /dev/null +++ b/test/spec/modules/openxAnalyticsAdapter_spec.js @@ -0,0 +1,445 @@ +import { expect } from 'chai'; +import openxAdapter from 'modules/openxAnalyticsAdapter'; +import { config } from 'src/config'; +import events from 'src/events'; +import CONSTANTS from 'src/constants.json'; +import * as utils from 'src/utils'; + +const { + EVENTS: { AUCTION_INIT, BID_REQUESTED, BID_RESPONSE, BID_TIMEOUT, BID_WON } +} = CONSTANTS; + +const SLOT_LOADED = 'slotOnload'; + +describe('openx analytics adapter', function() { + it('should require publisher id', function() { + sinon.spy(utils, 'logError'); + + openxAdapter.enableAnalytics(); + expect( + utils.logError.calledWith( + 'OpenX analytics adapter: publisherId is required.' + ) + ).to.be.true; + + utils.logError.restore(); + }); + + describe('sending analytics event', function() { + const auctionInit = { auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79' }; + + const bidRequestedOpenX = { + auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79', + auctionStart: 1540944528017, + bids: [ + { + adUnitCode: 'div-1', + bidId: '2f0c647b904e25', + bidder: 'openx', + params: { unit: '540249866' }, + transactionId: 'ac66c3e6-3118-4213-a3ae-8cdbe4f72873' + } + ], + start: 1540944528021 + }; + + const bidRequestedCloseX = { + auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79', + auctionStart: 1540944528017, + bids: [ + { + adUnitCode: 'div-1', + bidId: '43d454020e9409', + bidder: 'closex', + params: { unit: '513144370' }, + transactionId: 'ac66c3e6-3118-4213-a3ae-8cdbe4f72873' + } + ], + start: 1540944528026 + }; + + const bidResponseOpenX = { + adId: '2f0c647b904e25', + adUnitCode: 'div-1', + auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79', + cpm: 0.5, + creativeId: 'openx-crid', + responseTimestamp: 1540944528184, + ts: '2DAABBgABAAECAAIBAAsAAgAAAJccGApKSGt6NUZxRXYyHBbinsLj' + }; + + const bidResponseCloseX = { + adId: '43d454020e9409', + adUnitCode: 'div-1', + auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79', + cpm: 0.3, + creativeId: 'closex-crid', + responseTimestamp: 1540944528196, + ts: 'hu1QWo6iD3MHs6NG_AQAcFtyNqsj9y4S0YRbX7Kb06IrGns0BABb' + }; + + const bidTimeoutOpenX = { + 0: { + adUnitCode: 'div-1', + auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79', + bidId: '2f0c647b904e25' + } + }; + + const bidTimeoutCloseX = { + 0: { + adUnitCode: 'div-1', + auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79', + bidId: '43d454020e9409' + } + }; + + const bidWonOpenX = { + adId: '2f0c647b904e25', + adUnitCode: 'div-1', + auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79' + }; + + const bidWonCloseX = { + adId: '43d454020e9409', + adUnitCode: 'div-1', + auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79' + }; + + function simulateAuction(events) { + let highestBid; + + events.forEach(event => { + const [eventType, args] = event; + openxAdapter.track({ eventType, args }); + if (eventType === BID_RESPONSE) { + highestBid = highestBid || args; + if (highestBid.cpm < args.cpm) { + highestBid = args; + } + } + }); + + openxAdapter.track({ + eventType: SLOT_LOADED, + args: { + slot: { + getAdUnitPath: () => { + return '/90577858/test_ad_unit'; + }, + getTargetingKeys: () => { + return []; + }, + getTargeting: sinon + .stub() + .withArgs('hb_adid') + .returns(highestBid ? [highestBid.adId] : []) + } + } + }); + } + + function getQueryData(url) { + const queryArgs = url.split('?')[1].split('&'); + return queryArgs.reduce((data, arg) => { + const [key, val] = arg.split('='); + data[key] = val; + return data; + }, {}); + } + + let xhr; + let requests; + + before(function() { + xhr = sinon.useFakeXMLHttpRequest(); + xhr.onCreate = request => requests.push(request); + sinon.stub(events, 'getEvents').returns([]); + openxAdapter.enableAnalytics({ + options: { + publisherId: 'test123' + } + }); + }); + + after(function() { + xhr.restore(); + events.getEvents.restore(); + openxAdapter.disableAnalytics(); + }); + + beforeEach(function() { + requests = []; + openxAdapter.reset(); + }); + + afterEach(function() {}); + + it('should not send request if no bid response', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX] + ]); + + expect(requests.length).to.equal(0); + }); + + it('should send 1 request to the right endpoint', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_RESPONSE, bidResponseOpenX] + ]); + + expect(requests.length).to.equal(1); + + const endpoint = requests[0].url.split('?')[0]; + expect(endpoint).to.equal('http://ads.openx.net/w/1.0/pban'); + }); + + describe('hb.ct, hb.rid, dddid, hb.asiid, hb.pubid', function() { + it('should always be in the query string', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_RESPONSE, bidResponseOpenX] + ]); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.include({ + 'hb.ct': String(bidRequestedOpenX.auctionStart), + 'hb.rid': auctionInit.auctionId, + dddid: bidRequestedOpenX.bids[0].transactionId, + 'hb.asiid': '/90577858/test_ad_unit', + 'hb.pubid': 'test123' + }); + }); + }); + + describe('hb.cur', function() { + it('should be in the query string if currency is set', function() { + sinon + .stub(config, 'getConfig') + .withArgs('currency.adServerCurrency') + .returns('bitcoin'); + + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_RESPONSE, bidResponseOpenX] + ]); + + config.getConfig.restore(); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.include({ + 'hb.cur': 'bitcoin' + }); + }); + + it('should not be in the query string if currency is not set', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_RESPONSE, bidResponseOpenX] + ]); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.not.have.key('hb.cur'); + }); + }); + + describe('hb.dcl, hb.dl, hb.tta, hb.ttr', function() { + it('should be in the query string if browser supports performance API', function() { + const timing = { + fetchStart: 1540944528000, + domContentLoadedEventEnd: 1540944528010, + loadEventEnd: 1540944528110 + }; + const originalPerf = window.top.performance; + window.top.performance = { timing }; + + const renderTime = 1540944528100; + sinon.stub(Date, 'now').returns(renderTime); + + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_RESPONSE, bidResponseOpenX] + ]); + + window.top.performance = originalPerf; + Date.now.restore(); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.include({ + 'hb.dcl': String(timing.domContentLoadedEventEnd - timing.fetchStart), + 'hb.dl': String(timing.loadEventEnd - timing.fetchStart), + 'hb.tta': String(bidRequestedOpenX.auctionStart - timing.fetchStart), + 'hb.ttr': String(renderTime - timing.fetchStart) + }); + }); + + it('should not be in the query string if browser does not support performance API', function() { + const originalPerf = window.top.performance; + window.top.performance = undefined; + + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_RESPONSE, bidResponseOpenX] + ]); + + window.top.performance = originalPerf; + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.not.have.keys( + 'hb.dcl', + 'hb.dl', + 'hb.tta', + 'hb.ttr' + ); + }); + }); + + describe('ts, auid', function() { + it('OpenX is in auction and has a bid response', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_REQUESTED, bidRequestedCloseX], + [BID_RESPONSE, bidResponseOpenX], + [BID_RESPONSE, bidResponseCloseX] + ]); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.include({ + ts: bidResponseOpenX.ts, + auid: bidRequestedOpenX.bids[0].params.unit + }); + }); + + it('OpenX is in auction but no bid response', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_REQUESTED, bidRequestedCloseX], + [BID_RESPONSE, bidResponseCloseX] + ]); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.include({ + auid: bidRequestedOpenX.bids[0].params.unit + }); + expect(queryData).to.not.have.key('ts'); + }); + + it('OpenX is not in auction', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedCloseX], + [BID_RESPONSE, bidResponseCloseX] + ]); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.not.have.keys('auid', 'ts'); + }); + }); + + describe('hb.exn, hb.sts, hb.ets, hb.bv, hb.crid, hb.to', function() { + it('2 bidders in auction', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_REQUESTED, bidRequestedCloseX], + [BID_RESPONSE, bidResponseOpenX], + [BID_RESPONSE, bidResponseCloseX] + ]); + + const queryData = getQueryData(requests[0].url); + const auctionStart = bidRequestedOpenX.auctionStart; + expect(queryData).to.include({ + 'hb.exn': [ + bidRequestedOpenX.bids[0].bidder, + bidRequestedCloseX.bids[0].bidder + ].join(','), + 'hb.sts': [ + bidRequestedOpenX.start - auctionStart, + bidRequestedCloseX.start - auctionStart + ].join(','), + 'hb.ets': [ + bidResponseOpenX.responseTimestamp - auctionStart, + bidResponseCloseX.responseTimestamp - auctionStart + ].join(','), + 'hb.bv': [bidResponseOpenX.cpm, bidResponseCloseX.cpm].join(','), + 'hb.crid': [ + bidResponseOpenX.creativeId, + bidResponseCloseX.creativeId + ].join(','), + 'hb.to': [false, false].join(',') + }); + }); + + it('OpenX timed out', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_REQUESTED, bidRequestedCloseX], + [BID_RESPONSE, bidResponseCloseX], + [BID_TIMEOUT, bidTimeoutOpenX] + ]); + + const queryData = getQueryData(requests[0].url); + const auctionStart = bidRequestedOpenX.auctionStart; + expect(queryData).to.include({ + 'hb.exn': [ + bidRequestedOpenX.bids[0].bidder, + bidRequestedCloseX.bids[0].bidder + ].join(','), + 'hb.sts': [ + bidRequestedOpenX.start - auctionStart, + bidRequestedCloseX.start - auctionStart + ].join(','), + 'hb.ets': [ + undefined, + bidResponseCloseX.responseTimestamp - auctionStart + ].join(','), + 'hb.bv': [0, bidResponseCloseX.cpm].join(','), + 'hb.crid': [undefined, bidResponseCloseX.creativeId].join(','), + 'hb.to': [true, false].join(',') + }); + }); + }); + + describe('hb.we, hb.g1', function() { + it('OpenX won', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_RESPONSE, bidResponseOpenX], + [BID_WON, bidWonOpenX] + ]); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.include({ + 'hb.we': '0', + 'hb.g1': 'false' + }); + }); + + it('DFP won', function() { + simulateAuction([ + [AUCTION_INIT, auctionInit], + [BID_REQUESTED, bidRequestedOpenX], + [BID_RESPONSE, bidResponseOpenX] + ]); + + const queryData = getQueryData(requests[0].url); + expect(queryData).to.include({ + 'hb.we': '-1', + 'hb.g1': 'true' + }); + }); + }); + }); +}); From e1fb3a818fc166734f29758dc1b445a785319f3a Mon Sep 17 00:00:00 2001 From: Brittany Zellman <33695402+brittanyzellman@users.noreply.github.com> Date: Fri, 16 Nov 2018 08:38:46 -0500 Subject: [PATCH 0847/1594] Triplelift - update creativeId (#3305) * removed dependancy on getTopWindowUrl for referer * protect against undefined obj and remove test on old dependency * added unit test for referer and gdpr in query string * removed gdpr test * removed gdpr from bidderRequest obj * decontructed bidder request obj in chai test * just need to run karma tests again * added gdpr consent to all bidderRequest obj in chai tests * changed creativeId to be a Triplelift specific id rather than represent SRA impression * error-proofed creative id --- modules/tripleliftBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 5989d0c2fca..fac6224d1dc 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -113,11 +113,11 @@ function _buildResponseObject(bidderRequest, bid) { let width = bid.width || 1; let height = bid.height || 1; let dealId = bid.deal_id || ''; - let creativeId = bid.imp_id; + let creativeId = bid.crid || ''; if (bid.cpm != 0 && bid.ad) { bidResponse = { - requestId: bidderRequest.bids[creativeId].bidId, + requestId: bidderRequest.bids[bid.imp_id].bidId, cpm: bid.cpm, width: width, height: height, From 155dd8a0252ab98ac5f8c7422edfdbf2d14eb99d Mon Sep 17 00:00:00 2001 From: Fedor Belov Date: Fri, 16 Nov 2018 17:11:57 +0300 Subject: [PATCH 0848/1594] otm (#3302) --- modules/otmBidAdapter.js | 50 +++++++++++++++++++++ modules/otmBidAdapter.md | 38 ++++++++++++++++ test/spec/modules/otmBidAdapter_spec.js | 60 +++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 modules/otmBidAdapter.js create mode 100644 modules/otmBidAdapter.md create mode 100644 test/spec/modules/otmBidAdapter_spec.js diff --git a/modules/otmBidAdapter.js b/modules/otmBidAdapter.js new file mode 100644 index 00000000000..000985e2889 --- /dev/null +++ b/modules/otmBidAdapter.js @@ -0,0 +1,50 @@ +import {BANNER} from 'src/mediaTypes'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +export const spec = { + code: 'otm', + supportedMediaTypes: [BANNER], + isBidRequestValid: function (bid) { + return !!bid.params.pid && !!bid.params.tid; + }, + buildRequests: function (bidRequests) { + const requests = bidRequests.map(function (bid) { + const params = { + pid: bid.params.pid, + tid: bid.params.tid, + bidfloor: bid.params.bidfloor, + url: encodeURIComponent(window.location.href), + size: bid.sizes[0][0] + 'x' + bid.sizes[0][1], + resp_type: 'json', + rnd: Math.random(), + bidId: bid.bidId, + }; + + return {method: 'GET', url: 'https://ads2.otm-r.com/banner/hb', data: params} + }); + + return requests; + }, + interpretResponse: function (serverResponse, bidRequest) { + if (!serverResponse || !serverResponse.body || !serverResponse.body.ad) { + return []; + } + + const bid = serverResponse.body; + const sizes = bid.size.split('x'); + + return [{ + requestId: bidRequest.data.bidId, + cpm: bid.price, + width: sizes[0], + height: sizes[1], + creativeId: bidRequest.data.bidId, + currency: bid.currency || 'RUB', + netRevenue: true, + ad: bid.ad, + ttl: 360 + }]; + }, +}; + +registerBidder(spec); diff --git a/modules/otmBidAdapter.md b/modules/otmBidAdapter.md new file mode 100644 index 00000000000..e51d73443dd --- /dev/null +++ b/modules/otmBidAdapter.md @@ -0,0 +1,38 @@ +# Overview + +Module Name: OTM Bidder Adapter +Module Type: Bidder Adapter +Maintainer: ? + +# Description + +You can use this adapter to get a bid from otm-r.com. + +About us : http://otm-r.com + + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'div-otm-example', + sizes: [[320, 480]], + bids: [ + { + bidder: "otm", + params: { + pid: 1, + tid: "demo", + bidfloor: 20 + } + } + ] + } + ]; +``` + +Where: + +* pid - Publisher id +* tid - A tag id (should have low cardinality) +* bidfloor - Floor price diff --git a/test/spec/modules/otmBidAdapter_spec.js b/test/spec/modules/otmBidAdapter_spec.js new file mode 100644 index 00000000000..fa047f38109 --- /dev/null +++ b/test/spec/modules/otmBidAdapter_spec.js @@ -0,0 +1,60 @@ +import { expect } from 'chai'; +import { spec } from 'modules/otmBidAdapter'; + +describe('otmBidAdapterTests', function () { + it('validate_pub_params', function () { + expect(spec.isBidRequestValid({ + bidder: 'otm', + params: { + pid: 1, + tid: 'demo', + bidfloor: 20 + } + })).to.equal(true); + }); + + it('validate_generated_params', function () { + let bidRequestData = [{ + bidId: 'bid1234', + bidder: 'otm', + params: { + pid: 1, + tid: 'demo', + bidfloor: 20 + }, + sizes: [[240, 400]] + }]; + + let request = spec.buildRequests(bidRequestData); + let req_data = request[0].data; + + expect(req_data.bidId).to.equal('bid1234'); + }); + + it('validate_response_params', function () { + let bidRequestData = { + data: { + bidId: 'bid1234' + } + }; + + let serverResponse = { + body: { + price: 1.12, + ad: 'Ad html', + size: '250x600' + } + }; + + let bids = spec.interpretResponse(serverResponse, bidRequestData); + expect(bids).to.have.lengthOf(1); + let bid = bids[0]; + expect(bid.cpm).to.equal(1.12); + expect(bid.currency).to.equal('RUB'); + expect(bid.width).to.equal('250'); + expect(bid.height).to.equal('600'); + expect(bid.netRevenue).to.equal(true); + expect(bid.requestId).to.equal('bid1234'); + expect(bid.ad).to.equal('Ad html'); + }); +}); From f5890e8dcab2b6d4f0e27cffe532f5d2ee72e064 Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Fri, 16 Nov 2018 10:16:23 -0500 Subject: [PATCH 0849/1594] Updating bidrequestvalid and protocol checks. (#3297) * Submitting EMX Digital Prebid Adapter Submitting EMX Digital Prebid Adapter code * fixing lint errors. updating our md * updating to const/let variables. adding test spec. * fixed linting on test spec js * adding emx usersync methods * updating valid bid request checks and protocol check. * remove includes replaced with indexOf --- modules/emx_digitalBidAdapter.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 042251ea035..5638fa24e31 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -15,7 +15,8 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], isBidRequestValid: function (bid) { - return !!(bid.params.tagid); + return !!bid.params.tagid && typeof bid.params.tagid === 'string' && + (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'string'); }, buildRequests: function (validBidRequests, bidRequests) { const {host, href, protocol} = utils.getTopWindowLocation(); @@ -25,15 +26,16 @@ export const spec = { const timeout = config.getConfig('bidderTimeout'); const timestamp = Date.now(); const url = location.protocol + '//' + ENDPOINT + ('?t=' + timeout + '&ts=' + timestamp); + const networkProtocol = protocol.indexOf('https') > -1 ? 1 : 0; utils._each(validBidRequests, function (bid) { let tagId = String(utils.getBidIdParameter('tagid', bid.params)); - let bidFloor = utils.getBidIdParameter('bidfloor', bid.params) || 0; + let bidFloor = parseFloat(utils.getBidIdParameter('bidfloor', bid.params)) || 0; let emxBid = { id: bid.bidId, tid: bid.transactionId, tagid: tagId, - secure: protocol === 'https:' ? 1 : 0, + secure: networkProtocol, banner: { format: bid.sizes.map(function (size) { return { From 836acf78a6794760c74475f3fbe850aa7a4842ee Mon Sep 17 00:00:00 2001 From: jacekburys-quantcast <44467819+jacekburys-quantcast@users.noreply.github.com> Date: Tue, 20 Nov 2018 20:59:07 +0000 Subject: [PATCH 0850/1594] Quantcast supporting instream video (#3303) * changed isBidRequestValid to allow video except outstream video, some refactoring * supporting video WIP * updated quantcastBidAdapter.md * cleanup * supporting instream video, needs testing * test * adding vastUrl * cleanup * more cleanup * adding prebidJsVersion to expected request in test * updating page, referrer and domain * trying to make CI pass * trying to make CI pass 2 --- modules/quantcastBidAdapter.js | 102 ++++++++---- modules/quantcastBidAdapter.md | 37 +++++ test/spec/modules/quantcastBidAdapter_spec.js | 150 ++++++++++++++++-- 3 files changed, 249 insertions(+), 40 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 7d4393fe12c..97043be76a6 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,5 +1,6 @@ import * as utils from 'src/utils'; import { ajax } from 'src/ajax'; +import { config } from 'src/config'; import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'quantcast'; @@ -19,12 +20,60 @@ export const QUANTCAST_PORT = ? '8080' : '8443'; +function extractBidSizes(bid) { + const bidSizes = []; + + bid.sizes.forEach(size => { + bidSizes.push({ + width: size[0], + height: size[1] + }); + }); + + return bidSizes; +} + +function makeVideoImp(bid) { + const video = bid.params.video; + if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { + video['w'] = bid.mediaTypes.video.playerSize[0][0]; + video['h'] = bid.mediaTypes.video.playerSize[0][1]; + } else { + video['w'] = bid.mediaTypes.video.playerSize[0]; + video['h'] = bid.mediaTypes.video.playerSize[1]; + } + return { + video: video, + placementCode: bid.placementCode, + bidFloor: bid.params.bidFloor || DEFAULT_BID_FLOOR + }; +} + +function makeBannerImp(bid) { + return { + banner: { + battr: bid.params.battr, + sizes: extractBidSizes(bid), + }, + placementCode: bid.placementCode, + bidFloor: bid.params.bidFloor || DEFAULT_BID_FLOOR + }; +} + +function getDomain(url) { + if (!url) { + return url; + } + return url.replace('http://', '').replace('https://', '').replace('www.', '').split(/[/?#]/)[0]; +} + /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, * http://prebid.org/dev-docs/bidder-adapter-1.html */ export const spec = { code: BIDDER_CODE, + supportedMediaTypes: ['banner', 'video'], /** * Verify the `AdUnits.bids` response with `true` for valid request and `false` @@ -38,7 +87,9 @@ export const spec = { return false; } - if (bid.mediaType === 'video') { + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + if (videoMediaType && context == 'outstream') { return false; } @@ -55,39 +106,28 @@ export const spec = { */ buildRequests(bidRequests, bidderRequest) { const bids = bidRequests || []; + const gdprConsent = (bidderRequest && bidderRequest.gdprConsent) ? bidderRequest.gdprConsent : {}; - const referrer = utils.getTopWindowUrl(); - const loc = utils.getTopWindowLocation(); - const domain = loc.hostname; + 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); const bidRequestsList = bids.map(bid => { - const bidSizes = []; - - bid.sizes.forEach(size => { - bidSizes.push({ - width: size[0], - height: size[1] - }); - }); - - const gdprConsent = (bidderRequest && bidderRequest.gdprConsent) ? bidderRequest.gdprConsent : {}; + let imp; + const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); + if (videoContext === 'instream') { + imp = makeVideoImp(bid); + } else { + imp = makeBannerImp(bid); + } // Request Data Format can be found at https://wiki.corp.qc/display/adinf/QCX const requestData = { publisherId: bid.params.publisherId, requestId: bid.bidId, - imp: [ - { - banner: { - battr: bid.params.battr, - sizes: bidSizes - }, - placementCode: bid.placementCode, - bidFloor: bid.params.bidFloor || DEFAULT_BID_FLOOR - } - ], + imp: [imp], site: { - page: loc.href, + page, referrer, domain }, @@ -98,7 +138,6 @@ export const spec = { }; const data = JSON.stringify(requestData); - const qcDomain = bid.params.publisherId === QUANTCAST_TEST_PUBLISHER ? QUANTCAST_TEST_DOMAIN : QUANTCAST_DOMAIN; @@ -143,9 +182,9 @@ export const spec = { } const bidResponsesList = response.bids.map(bid => { - const { ad, cpm, width, height, creativeId, currency } = bid; + const { ad, cpm, width, height, creativeId, currency, videoUrl } = bid; - return { + const result = { requestId: response.requestId, cpm, width, @@ -156,6 +195,13 @@ export const spec = { netRevenue: QUANTCAST_NET_REVENUE, currency }; + + if (videoUrl !== undefined && videoUrl) { + result['vastUrl'] = videoUrl; + result['mediaType'] = 'video'; + } + + return result; }); return bidResponsesList; diff --git a/modules/quantcastBidAdapter.md b/modules/quantcastBidAdapter.md index efc21466c75..5d0c2e10fc0 100644 --- a/modules/quantcastBidAdapter.md +++ b/modules/quantcastBidAdapter.md @@ -12,6 +12,7 @@ Module that connects to Quantcast demand sources to fetch bids. # Test Parameters +## Sample Banner Ad Unit ```js const adUnits = [{ code: 'banner', @@ -29,3 +30,39 @@ const adUnits = [{ ] }]; ``` + +## Sample Video Ad Unit +```js +var adUnits = [{ + code: 'video', + mediaTypes: { + video: { + context: 'instream', // required + playerSize: [600, 300] // required + } + }, + bids: [ + { + bidder: 'quantcast', + params: { + publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast + // Video object as specified in OpenRTB 2.5 + video: { + mimes: ['video/mp4'], // required + minduration: 3, // optional + maxduration: 5, // optional + protocols: [3], // optional + startdelay: 1, // optional + linearity: 1, // optinal + battr: [1, 2], // optional + maxbitrate: 10, // optional + playbackmethod: [1], // optional + delivery: [1], // optional + placement: 1, // optional + api: [2, 3] // optional + } + } + } + ] +}]; +``` diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index cda42b6ddb6..4392d9603e3 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -34,6 +34,33 @@ describe('Quantcast adapter', function () { }; }); + function setupVideoBidRequest() { + bidRequest.params = { + publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast + // Video object as specified in OpenRTB 2.5 + video: { + mimes: ['video/mp4'], // required + minduration: 3, // optional + maxduration: 5, // optional + protocols: [3], // optional + startdelay: 1, // optional + linearity: 1, // optinal + battr: [1, 2], // optional + maxbitrate: 10, // optional + playbackmethod: [1], // optional + delivery: [1], // optional + placement: 1, // optional + api: [2, 3] // optional + } + }; + bidRequest['mediaTypes'] = { + video: { + context: 'instream', + playerSize: [600, 300] + } + } + }; + describe('inherited functions', function () { it('exists and is a function', function () { expect(quantcastAdapter.callBids).to.exist.and.to.be.a('function'); @@ -45,8 +72,15 @@ describe('Quantcast adapter', function () { expect(qcSpec.isBidRequestValid()).to.equal(false); }); - it('should return `false` when bid `mediaType` is `video`', function () { - const bidRequest = { mediaType: 'video' }; + it('should return `false` when bid is for outstream video', function () { + const bidRequest = { + mediaType: 'video', + mediaTypes: { + video: { + context: 'outstream' + } + } + }; expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); }); @@ -96,13 +130,16 @@ describe('Quantcast adapter', function () { expect(requests[0].method).to.equal('POST'); }); - it('sends bid requests contains all the required parameters', function () { - const referrer = utils.getTopWindowUrl(); - const loc = utils.getTopWindowLocation(); - const domain = loc.hostname; + it('sends banner bid requests contains all the required parameters', function () { + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/hello.html', + canonicalUrl: 'http://example.com/hello.html' + } + }; - const requests = qcSpec.buildRequests([bidRequest]); - const expectedBidRequest = { + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + const expectedBannerBidRequest = { publisherId: QUANTCAST_TEST_PUBLISHER, requestId: '2f7b179d443f14', imp: [ @@ -116,16 +153,65 @@ describe('Quantcast adapter', function () { } ], site: { - page: loc.href, - referrer, - domain + page: 'http://example.com/hello.html', + referrer: 'http://example.com/hello.html', + domain: 'example.com' + }, + bidId: '2f7b179d443f14', + gdprSignal: 0, + prebidJsVersion: '$prebid.version$' + }; + + expect(requests[0].data).to.equal(JSON.stringify(expectedBannerBidRequest)); + }); + + it('sends video bid requests containing all the required parameters', function () { + setupVideoBidRequest(); + + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/hello.html', + canonicalUrl: 'http://example.com/hello.html' + } + }; + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + const expectedVideoBidRequest = { + publisherId: QUANTCAST_TEST_PUBLISHER, + requestId: '2f7b179d443f14', + imp: [ + { + video: { + mimes: ['video/mp4'], + minduration: 3, + maxduration: 5, + protocols: [3], + startdelay: 1, + linearity: 1, + battr: [1, 2], + maxbitrate: 10, + playbackmethod: [1], + delivery: [1], + placement: 1, + api: [2, 3], + w: 600, + h: 300 + }, + placementCode: 'div-gpt-ad-1438287399331-0', + bidFloor: 1e-10 + } + ], + site: { + page: 'http://example.com/hello.html', + referrer: 'http://example.com/hello.html', + domain: 'example.com' }, bidId: '2f7b179d443f14', gdprSignal: 0, prebidJsVersion: '$prebid.version$' }; - expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); + expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); }); }); @@ -162,6 +248,27 @@ describe('Quantcast adapter', function () { headers: {} }; + const videoBody = { + bidderCode: 'qcx', + requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', + bids: [ + { + statusCode: 1, + placementCode: 'video1', + cpm: 4.5, + currency: 'USD', + videoUrl: 'https://vast.quantserve.com/vast?p=&r=&gdpr=&gdpr_consent=&rand=1337&d=H4sIAAAAAAAAAONi4mIQcrzFqGLi5OzibOzmpGtm4eyia-LoaqDraGRupOtobGJhYuni6GRiYLmLiYWrp5f_BBPDDybGScxcPs7-aRYmpmVVoVJgCSXBkozMYl0gKslI1S1Izk9JBQALkFy_YAAAAA&h=uRnsTjyXbOrXJtBQiaMn239i9GI', + width: 600, + height: 300 + } + ] + }; + + const videoResponse = { + body: videoBody, + headers: {} + }; + it('should return an empty array if `serverResponse` is `undefined`', function () { const interpretedResponse = qcSpec.interpretResponse(); @@ -198,6 +305,25 @@ describe('Quantcast adapter', function () { expect(interpretedResponse[0]).to.deep.equal(expectedResponse); }); + it('should get correct bid response for instream video', function() { + const expectedResponse = { + requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', + cpm: 4.5, + width: 600, + height: 300, + vastUrl: 'https://vast.quantserve.com/vast?p=&r=&gdpr=&gdpr_consent=&rand=1337&d=H4sIAAAAAAAAAONi4mIQcrzFqGLi5OzibOzmpGtm4eyia-LoaqDraGRupOtobGJhYuni6GRiYLmLiYWrp5f_BBPDDybGScxcPs7-aRYmpmVVoVJgCSXBkozMYl0gKslI1S1Izk9JBQALkFy_YAAAAA&h=uRnsTjyXbOrXJtBQiaMn239i9GI', + mediaType: 'video', + ttl: QUANTCAST_TTL, + creativeId: undefined, + ad: undefined, + netRevenue: QUANTCAST_NET_REVENUE, + currency: 'USD' + }; + const interpretedResponse = qcSpec.interpretResponse(videoResponse); + + expect(interpretedResponse[0]).to.deep.equal(expectedResponse); + }); + it('handles no bid response', function () { const body = { bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name From 706f5690ff1b5facce0fde657756a0d92832d667 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 20 Nov 2018 17:24:23 -0500 Subject: [PATCH 0851/1594] Do not load external js if renderer defined on adUnit (#3284) * do not load external js if renderer defined on adUnit * Added unit test --- modules/appnexusBidAdapter.js | 3 + src/Renderer.js | 23 ++- test/spec/modules/appnexusBidAdapter_spec.js | 30 +++- test/spec/renderer_spec.js | 175 +++++++++++-------- 4 files changed, 152 insertions(+), 79 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index cc0cac579da..1e77dfce564 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -211,6 +211,7 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { url: rtbBid.renderer_url, config: rendererOptions, loaded: false, + adUnitCode }); try { @@ -238,6 +239,7 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { * @return Bid */ function newBid(serverBid, rtbBid, bidderRequest) { + const bidRequest = utils.getBidRequest(serverBid.uuid, [bidderRequest]); const bid = { requestId: serverBid.uuid, cpm: rtbBid.cpm, @@ -246,6 +248,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { currency: 'USD', netRevenue: true, ttl: 300, + adUnitCode: bidRequest.adUnitCode, appnexus: { buyerMemberId: rtbBid.buyer_member_id, dealPriority: rtbBid.deal_priority, diff --git a/src/Renderer.js b/src/Renderer.js index 3a156b2b86e..87f60e65668 100644 --- a/src/Renderer.js +++ b/src/Renderer.js @@ -1,5 +1,6 @@ import { loadScript } from './adloader'; import * as utils from './utils'; +import find from 'core-js/library/fn/array/find'; /** * @typedef {object} Renderer @@ -10,7 +11,7 @@ import * as utils from './utils'; */ export function Renderer(options) { - const { url, config, id, callback, loaded } = options; + const { url, config, id, callback, loaded, adUnitCode } = options; this.url = url; this.config = config; this.handlers = {}; @@ -35,12 +36,16 @@ export function Renderer(options) { this.process(); }); - // we expect to load a renderer url once only so cache the request to load script - loadScript(url, this.callback, true); + if (!isRendererDefinedOnAdUnit(adUnitCode)) { + // we expect to load a renderer url once only so cache the request to load script + loadScript(url, this.callback, true); + } else { + utils.logWarn(`External Js not loaded by Renderer since renderer url and callback is already defined on adUnit ${adUnitCode}`); + } } -Renderer.install = function({ url, config, id, callback, loaded }) { - return new Renderer({ url, config, id, callback, loaded }); +Renderer.install = function({ url, config, id, callback, loaded, adUnitCode }) { + return new Renderer({ url, config, id, callback, loaded, adUnitCode }); }; Renderer.prototype.getConfig = function() { @@ -94,3 +99,11 @@ export function isRendererRequired(renderer) { export function executeRenderer(renderer, bid) { renderer.render(bid); } + +function isRendererDefinedOnAdUnit(adUnitCode) { + const adUnits = $$PREBID_GLOBAL$$.adUnits; + const adUnit = find(adUnits, adUnit => { + return adUnit.code === adUnitCode; + }); + return !!(adUnit && adUnit.renderer && adUnit.renderer.url && adUnit.renderer.render); +} diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index e6afc8561b6..08e5f35cb8d 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -463,12 +463,18 @@ describe('AppNexusAdapter', function () { 'currency': 'USD', 'ttl': 300, 'netRevenue': true, + 'adUnitCode': 'code', 'appnexus': { 'buyerMemberId': 958 } } ]; - let bidderRequest; + 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])); }); @@ -505,7 +511,12 @@ describe('AppNexusAdapter', function () { }] }] }; - let bidderRequest; + let bidderRequest = { + bids: [{ + bidId: '84ab500420319d', + adUnitCode: 'code' + }] + } let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(result[0]).to.have.property('vastUrl'); @@ -538,7 +549,12 @@ describe('AppNexusAdapter', function () { }, 'impression_trackers': ['http://example.com'], }; - let bidderRequest; + let bidderRequest = { + bids: [{ + bidId: '3db3773286ee59', + adUnitCode: 'code' + }] + } let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); expect(result[0].native.title).to.equal('Native Creative'); @@ -554,6 +570,7 @@ describe('AppNexusAdapter', function () { const bidderRequest = { bids: [{ + bidId: '3db3773286ee59', renderer: { options: { adText: 'configured' @@ -573,7 +590,12 @@ describe('AppNexusAdapter', function () { responseWithDeal.tags[0].ads[0].deal_priority = 'high'; responseWithDeal.tags[0].ads[0].deal_code = '123'; - let bidderRequest; + let bidderRequest = { + bids: [{ + bidId: '3db3773286ee59', + adUnitCode: 'code' + }] + } let result = spec.interpretResponse({ body: responseWithDeal }, {bidderRequest}); expect(Object.keys(result[0].appnexus)).to.include.members(['buyerMemberId', 'dealPriority', 'dealCode']); }); diff --git a/test/spec/renderer_spec.js b/test/spec/renderer_spec.js index d4e90245ea5..7a7354add31 100644 --- a/test/spec/renderer_spec.js +++ b/test/spec/renderer_spec.js @@ -1,96 +1,131 @@ import { expect } from 'chai'; import { Renderer } from 'src/Renderer'; - -describe('Renderer: A renderer installed on a bid response', function () { - let testRenderer1; - let testRenderer2; - let spyRenderFn; - let spyEventHandler; - - beforeEach(function () { - testRenderer1 = Renderer.install({ - url: 'https://httpbin.org/post', - config: { test: 'config1' }, - id: 1 +import * as utils from 'src/utils'; + +describe('Renderer', function () { + describe('Renderer: A renderer installed on a bid response', function () { + let testRenderer1; + let testRenderer2; + let spyRenderFn; + let spyEventHandler; + + beforeEach(function () { + testRenderer1 = Renderer.install({ + url: 'https://httpbin.org/post', + config: { test: 'config1' }, + id: 1 + }); + testRenderer2 = Renderer.install({ + url: 'https://httpbin.org/post', + config: { test: 'config2' }, + id: 2 + }); + + spyRenderFn = sinon.spy(); + spyEventHandler = sinon.spy(); }); - testRenderer2 = Renderer.install({ - url: 'https://httpbin.org/post', - config: { test: 'config2' }, - id: 2 + + it('is an instance of Renderer', function () { + expect(testRenderer1 instanceof Renderer).to.equal(true); }); - spyRenderFn = sinon.spy(); - spyEventHandler = sinon.spy(); - }); + it('has expected properties ', function () { + expect(testRenderer1.url).to.equal('https://httpbin.org/post'); + expect(testRenderer1.config).to.deep.equal({ test: 'config1' }); + expect(testRenderer1.id).to.equal(1); + }); - it('is an instance of Renderer', function () { - expect(testRenderer1 instanceof Renderer).to.equal(true); - }); + it('returns config from getConfig method', function () { + expect(testRenderer1.getConfig()).to.deep.equal({ test: 'config1' }); + expect(testRenderer2.getConfig()).to.deep.equal({ test: 'config2' }); + }); - it('has expected properties ', function () { - expect(testRenderer1.url).to.equal('https://httpbin.org/post'); - expect(testRenderer1.config).to.deep.equal({ test: 'config1' }); - expect(testRenderer1.id).to.equal(1); - }); + it('sets a render function with setRender method', function () { + testRenderer1.setRender(spyRenderFn); + expect(typeof testRenderer1.render).to.equal('function'); + testRenderer1.render(); + expect(spyRenderFn.called).to.equal(true); + }); - it('returns config from getConfig method', function () { - expect(testRenderer1.getConfig()).to.deep.equal({ test: 'config1' }); - expect(testRenderer2.getConfig()).to.deep.equal({ test: 'config2' }); - }); + it('sets event handlers with setEventHandlers method and handles events with installed handlers', function () { + testRenderer1.setEventHandlers({ + testEvent: spyEventHandler + }); - it('sets a render function with setRender method', function () { - testRenderer1.setRender(spyRenderFn); - expect(typeof testRenderer1.render).to.equal('function'); - testRenderer1.render(); - expect(spyRenderFn.called).to.equal(true); - }); + expect(testRenderer1.handlers).to.deep.equal({ + testEvent: spyEventHandler + }); - it('sets event handlers with setEventHandlers method and handles events with installed handlers', function () { - testRenderer1.setEventHandlers({ - testEvent: spyEventHandler + testRenderer1.handleVideoEvent({ id: 1, eventName: 'testEvent' }); + expect(spyEventHandler.called).to.equal(true); }); - expect(testRenderer1.handlers).to.deep.equal({ - testEvent: spyEventHandler + it('pushes commands to queue if renderer is not loaded', function () { + testRenderer1.loaded = false; + testRenderer1.push(spyRenderFn); + expect(testRenderer1.cmd.length).to.equal(1); + + // clear queue for next tests + testRenderer1.cmd = []; }); - testRenderer1.handleVideoEvent({ id: 1, eventName: 'testEvent' }); - expect(spyEventHandler.called).to.equal(true); - }); + it('fires commands immediately if the renderer is loaded', function () { + const func = sinon.spy(); - it('pushes commands to queue if renderer is not loaded', function () { - testRenderer1.loaded = false; - testRenderer1.push(spyRenderFn); - expect(testRenderer1.cmd.length).to.equal(1); + testRenderer1.loaded = true; + testRenderer1.push(func); - // clear queue for next tests - testRenderer1.cmd = []; - }); + expect(testRenderer1.cmd.length).to.equal(0); - it('fires commands immediately if the renderer is loaded', function () { - const func = sinon.spy(); + sinon.assert.calledOnce(func); + }); - testRenderer1.loaded = true; - testRenderer1.push(func); + it('processes queue by calling each function in queue', function () { + testRenderer1.loaded = false; + const func1 = sinon.spy(); + const func2 = sinon.spy(); - expect(testRenderer1.cmd.length).to.equal(0); + testRenderer1.push(func1); + testRenderer1.push(func2); + expect(testRenderer1.cmd.length).to.equal(2); - sinon.assert.calledOnce(func); - }); + testRenderer1.process(); - it('processes queue by calling each function in queue', function () { - testRenderer1.loaded = false; - const func1 = sinon.spy(); - const func2 = sinon.spy(); + sinon.assert.calledOnce(func1); + sinon.assert.calledOnce(func2); + expect(testRenderer1.cmd.length).to.equal(0); + }); + }); - testRenderer1.push(func1); - testRenderer1.push(func2); - expect(testRenderer1.cmd.length).to.equal(2); + describe('3rd party renderer', function () { + let adUnitsOld; + let utilsSpy; + before(function () { + adUnitsOld = $$PREBID_GLOBAL$$.adUnits; + utilsSpy = sinon.spy(utils, 'logWarn'); + }); - testRenderer1.process(); + after(function() { + $$PREBID_GLOBAL$$.adUnits = adUnitsOld; + utilsSpy.restore(); + }); - sinon.assert.calledOnce(func1); - sinon.assert.calledOnce(func2); - expect(testRenderer1.cmd.length).to.equal(0); + it('should not load renderer and log warn message', function() { + $$PREBID_GLOBAL$$.adUnits = [{ + code: 'video1', + renderer: { + url: 'http://cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + render: sinon.spy() + } + }] + + let testRenderer = Renderer.install({ + url: 'https://httpbin.org/post', + config: { test: 'config1' }, + id: 1, + adUnitCode: 'video1' + }); + expect(utilsSpy.callCount).to.equal(1); + }); }); }); From e562c62f9cef13f80352d99806c1259dd848840f Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 20 Nov 2018 17:27:41 -0500 Subject: [PATCH 0852/1594] Prebid 1.33.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9f99f1dcc1d..bdc24f934ee 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.33.0-pre", + "version": "1.33.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4c3120085ab43e5d444dbbaac995898b2cfbc137 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 20 Nov 2018 17:33:01 -0500 Subject: [PATCH 0853/1594] Increment Pre Version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bdc24f934ee..81f46b620b0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.33.0", + "version": "1.34.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From aed272fd6005c10db0fb5f2ced8822df4961ac0e Mon Sep 17 00:00:00 2001 From: John Ellis Date: Wed, 21 Nov 2018 10:52:26 -0500 Subject: [PATCH 0854/1594] YieldbotBidAdapter to use implicit document open via write (#3313) --- modules/yieldbotBidAdapter.js | 2 +- test/spec/modules/yieldbotBidAdapter_spec.js | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/yieldbotBidAdapter.js b/modules/yieldbotBidAdapter.js index a18448a0b0b..15b5cf34f96 100644 --- a/modules/yieldbotBidAdapter.js +++ b/modules/yieldbotBidAdapter.js @@ -369,7 +369,7 @@ export const YieldbotAdapter = { const adUrl = this.buildAdUrl(urlPrefix, publisherNumber, commonSearchParams, bid); const impressionUrl = this.buildImpressionUrl(urlPrefix, publisherNumber, commonSearchParams); - const htmlMarkup = `
`; + const htmlMarkup = `
`; return { ad: htmlMarkup, creativeId: ybotAdRequestId }; }, diff --git a/test/spec/modules/yieldbotBidAdapter_spec.js b/test/spec/modules/yieldbotBidAdapter_spec.js index 2977e4ef30d..3f78d4aa688 100644 --- a/test/spec/modules/yieldbotBidAdapter_spec.js +++ b/test/spec/modules/yieldbotBidAdapter_spec.js @@ -1059,6 +1059,16 @@ describe('Yieldbot Adapter Unit Tests', function() { expect(edgeServerUrlPrefix).to.match(beginsRegex); expect(responses[0].ad).to.match(containsRegex); }); + + it('should not use document.open() in ad markup', function() { + FIXTURE_SERVER_RESPONSE.body.url_prefix = 'http://close.edge.adserver.com/'; + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + expect(responses[0].ad).to.not.match(/var innerFrameDoc=innerFrame\.contentWindow\.document;innerFrameDoc\.open\(\);innerFrameDoc\.write\(iframeHtml\);innerFrameDoc\.close\(\);/); + expect(responses[0].ad).to.match(/var innerFrameDoc=innerFrame\.contentWindow\.document;innerFrameDoc\.write\(iframeHtml\);innerFrameDoc\.close\(\);/); + }); }); describe('getUserSyncs', function() { From 4b148443079343fd8000b4dcae5e644cc366a096 Mon Sep 17 00:00:00 2001 From: Mohit Patil <13765991+mohit546@users.noreply.github.com> Date: Wed, 21 Nov 2018 21:27:47 +0530 Subject: [PATCH 0855/1594] - vertoz adaptor response params updated (#3316) --- modules/vertozBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/vertozBidAdapter.js b/modules/vertozBidAdapter.js index f3727714454..57a87613286 100644 --- a/modules/vertozBidAdapter.js +++ b/modules/vertozBidAdapter.js @@ -74,7 +74,7 @@ export const spec = { mediaType: 'banner', currency: 'USD', dealId: null, - creativeId: null, + creativeId: bidRespObj.bid, ttl: 300, ad: bidRespObj.ad + utils.createTrackPixelHtml(decodeURIComponent(bidRespObj.nurl)) }; From f8b14ec95f70686777f253568d749de938f244b1 Mon Sep 17 00:00:00 2001 From: Justas Pupelis Date: Wed, 21 Nov 2018 18:05:30 +0200 Subject: [PATCH 0856/1594] Rename adformOpenRTBBidAdapter (#3318) --- modules/{adformOpenRTBAdapter.js => adformOpenRTBBidAdapter.js} | 0 modules/{adformOpenRTBAdapter.md => adformOpenRTBBidAdapter.md} | 0 ...rmOpenRTBAdapter_spec.js => adformOpenRTBBidAdapter_spec.js} | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename modules/{adformOpenRTBAdapter.js => adformOpenRTBBidAdapter.js} (100%) rename modules/{adformOpenRTBAdapter.md => adformOpenRTBBidAdapter.md} (100%) rename test/spec/modules/{adformOpenRTBAdapter_spec.js => adformOpenRTBBidAdapter_spec.js} (99%) diff --git a/modules/adformOpenRTBAdapter.js b/modules/adformOpenRTBBidAdapter.js similarity index 100% rename from modules/adformOpenRTBAdapter.js rename to modules/adformOpenRTBBidAdapter.js diff --git a/modules/adformOpenRTBAdapter.md b/modules/adformOpenRTBBidAdapter.md similarity index 100% rename from modules/adformOpenRTBAdapter.md rename to modules/adformOpenRTBBidAdapter.md diff --git a/test/spec/modules/adformOpenRTBAdapter_spec.js b/test/spec/modules/adformOpenRTBBidAdapter_spec.js similarity index 99% rename from test/spec/modules/adformOpenRTBAdapter_spec.js rename to test/spec/modules/adformOpenRTBBidAdapter_spec.js index 8e101c3d41b..5c0009ab1c7 100644 --- a/test/spec/modules/adformOpenRTBAdapter_spec.js +++ b/test/spec/modules/adformOpenRTBBidAdapter_spec.js @@ -1,7 +1,7 @@ // jshint esversion: 6, es3: false, node: true import {assert, expect} from 'chai'; import * as url from 'src/url'; -import {spec} from 'modules/adformOpenRTBAdapter'; +import {spec} from 'modules/adformOpenRTBBidAdapter'; import { NATIVE } from 'src/mediaTypes'; describe('AdformOpenRTB adapter', function () { From e90b5d5597cf779d6dc8deda7d160556dac92d42 Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Mon, 26 Nov 2018 16:42:00 +0000 Subject: [PATCH 0857/1594] Added 930x600 to Rubicon Adapter (#3323) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 415027ef500..1eef3b4813d 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -50,6 +50,7 @@ var sizeMap = { 61: '1000x1000', 64: '580x500', 65: '640x480', + 66: '930x600', 67: '320x480', 68: '1800x1000', 72: '320x320', From 7990f9278bb721db2baaaf7f7bd696c9972420a7 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 27 Nov 2018 11:46:31 +0530 Subject: [PATCH 0858/1594] PubMatic adapter to support TTD (#3311) * first commit * added unit test cases for TTD id --- modules/pubmaticBidAdapter.js | 19 ++ test/spec/modules/pubmaticBidAdapter_spec.js | 233 +++++++++++++++++++ 2 files changed, 252 insertions(+) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 354addc6def..7203cee2391 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -308,9 +308,28 @@ function _handleDigitrustId(eids) { } } +function _handleTTDId(eids) { + let adsrvrOrgId = config.getConfig('adsrvrOrgId'); + if (adsrvrOrgId && utils.isStr(adsrvrOrgId.TDID)) { + eids.push({ + 'source': 'adserver.org', + 'uids': [ + { + 'id': adsrvrOrgId.TDID, + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' + } + } + ] + }); + } +} + function _handleEids(payload) { let eids = []; _handleDigitrustId(eids); + _handleTTDId(eids); if (eids.length > 0) { payload.user.eids = eids; } diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 4fca6656e46..05aaa191207 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -640,6 +640,239 @@ describe('PubMatic adapter', function () { }); }); + describe('AdsrvrOrgId from config', function() { + let sandbox; + beforeEach(() => { + sandbox = sinon.sandbox.create(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('Request should have adsrvrOrgId config params', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: { + 'TDID': '5e740345-c25e-436d-b466-5f2f9fa95c17', + 'TDID_LOOKUP': 'TRUE', + 'TDID_CREATED_AT': '2018-10-01T07:05:40' + } + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'adserver.org', + 'uids': [{ + 'id': '5e740345-c25e-436d-b466-5f2f9fa95c17', + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' + } + }] + }]); + }); + + it('Request should NOT have adsrvrOrgId config params if id in adsrvrOrgId is NOT string', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: { + 'TDID': 1, + 'TDID_LOOKUP': 'TRUE', + 'TDID_CREATED_AT': '2018-10-01T07:05:40' + } + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + }); + + it('Request should NOT have adsrvrOrgId config params if adsrvrOrgId is NOT object', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: null + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + }); + + it('Request should NOT have adsrvrOrgId config params if id in adsrvrOrgId is NOT set', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: { + 'TDID_LOOKUP': 'TRUE', + 'TDID_CREATED_AT': '2018-10-01T07:05:40' + } + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + }); + }); + + describe('AdsrvrOrgId and Digitrust', function() { + // here we are considering cases only of accepting DigiTrustId from config + let sandbox; + beforeEach(() => { + sandbox = sinon.sandbox.create(); + window.DigiTrust = { + getUser: sandbox.spy() + }; + }); + + afterEach(() => { + sandbox.restore(); + delete window.DigiTrust; + }); + + it('Request should have id of both AdsrvrOrgId and Digitrust if both have returned valid ids', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: { + 'TDID': '5e740345-c25e-436d-b466-5f2f9fa95c17', + 'TDID_LOOKUP': 'TRUE', + 'TDID_CREATED_AT': '2018-10-01T07:05:40' + }, + digiTrustId: { + success: true, + identity: { + privacy: {optout: false}, + id: 'testId', + keyv: 4 + } + } + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'digitru.st', + 'uids': [{ + 'id': 'testId', + 'atype': 1, + 'ext': { + 'keyv': 4 + } + }] + }, { + 'source': 'adserver.org', + 'uids': [{ + 'id': '5e740345-c25e-436d-b466-5f2f9fa95c17', + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' + } + }] + }]); + }); + + it('Request should have id of only AdsrvrOrgId and NOT Digitrust if only AdsrvrOrgId have returned valid id', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: { + 'TDID': '5e740345-c25e-436d-b466-5f2f9fa95c17', + 'TDID_LOOKUP': 'TRUE', + 'TDID_CREATED_AT': '2018-10-01T07:05:40' + }, + digiTrustId: { + success: true, + identity: { + privacy: {optout: true}, + id: 'testId', + keyv: 4 + } + } + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'adserver.org', + 'uids': [{ + 'id': '5e740345-c25e-436d-b466-5f2f9fa95c17', + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' + } + }] + }]); + }); + + it('Request should have id of only Digitrust and NOT AdsrvrOrgId if only Digitrust have returned valid id', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: { + 'TDID_LOOKUP': 'TRUE', + 'TDID_CREATED_AT': '2018-10-01T07:05:40' + }, + digiTrustId: { + success: true, + identity: { + privacy: {optout: false}, + id: 'testId', + keyv: 4 + } + } + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'digitru.st', + 'uids': [{ + 'id': 'testId', + 'atype': 1, + 'ext': { + 'keyv': 4 + } + }] + }]); + }); + + it('Request should NOT have id of Digitrust and NOT AdsrvrOrgId if only both have NOT returned valid ids', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: { + 'TDID_LOOKUP': 'TRUE', + 'TDID_CREATED_AT': '2018-10-01T07:05:40' + }, + digiTrustId: { + success: true, + identity: { + privacy: {optout: true}, + id: 'testId', + keyv: 4 + } + } + }; + return config[key]; + }); + + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + }); + }); + it('Request params check for video ad', function () { let request = spec.buildRequests(videoBidRequests); let data = JSON.parse(request.data); From c7b060b643bc038fddfe1002e2da6a653e5262c9 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Tue, 27 Nov 2018 15:16:37 -0500 Subject: [PATCH 0859/1594] Sonobi - support video and display same adunit (#3325) * changed adapter to support video and display for ad unit * added case for sbi_ct outstream * outstream is display media type --- modules/sonobiBidAdapter.js | 12 +++---- test/spec/modules/sonobiBidAdapter_spec.js | 39 ++++++++++++++++++---- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 15bcca50a13..0400aa46ecf 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -1,7 +1,6 @@ import { registerBidder } from 'src/adapters/bidderFactory'; -import { getTopWindowLocation, parseSizesInput, logError, generateUUID, deepAccess, isEmpty } from '../src/utils'; +import { getTopWindowLocation, parseSizesInput, logError, generateUUID, isEmpty } from '../src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; -import find from 'core-js/library/fn/array/find'; import { config } from '../src/config'; const BIDDER_CODE = 'sonobi'; @@ -104,12 +103,10 @@ export const spec = { } Object.keys(bidResponse.slots).forEach(slot => { + const bid = bidResponse.slots[slot]; const bidId = _getBidIdFromTrinityKey(slot); - const bidRequest = find(bidderRequests, bidReqest => bidReqest.bidId === bidId); - const videoMediaType = deepAccess(bidRequest, 'mediaTypes.video'); - const mediaType = bidRequest.mediaType || (videoMediaType ? 'video' : null); + const mediaType = (bid.sbi_ct === 'video') ? 'video' : null; const createCreative = _creative(mediaType); - const bid = bidResponse.slots[slot]; if (bid.sbi_aid && bid.sbi_mouse && bid.sbi_size) { const [ width = 1, @@ -132,8 +129,7 @@ export const spec = { bids.dealId = bid.sbi_dozer; } - const creativeType = bid.sbi_ct; - if (creativeType && (creativeType === 'video' || creativeType === 'outstream')) { + if (mediaType === 'video') { bids.mediaType = 'video'; bids.vastUrl = createCreative(bidResponse.sbi_dc, bid.sbi_aid); delete bids.ad; diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 69138c063c9..43b35c7d961 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -242,8 +242,7 @@ describe('SonobiBidAdapter', function () { }, 'adUnitCode': 'adunit-code-2', 'sizes': [[120, 600], [300, 600], [160, 600]], - 'bidId': '30b31c1838de1e', - 'mediaType': 'video' + 'bidId': '30b31c1838de1e' }, { 'bidder': 'sonobi', @@ -274,6 +273,14 @@ describe('SonobiBidAdapter', function () { 'sbi_aid': '30292e432662bd5f86d90774b944b038', 'sbi_mouse': 1.25, 'sbi_dozer': 'dozerkey', + 'sbi_ct': 'video' + }, + '/7780971/sparks_prebid_LB_OUTSTREAM|30b31c1838de1g': { + 'sbi_size': '300x600', + 'sbi_apoc': 'remnant', + 'sbi_crid': '1234abcd', + 'sbi_aid': '30292e432662bd5f86d90774b944b038', + 'sbi_mouse': 1.07, }, '/7780971/sparks_prebid_LB|30b31c1838de1g': {}, }, @@ -313,7 +320,19 @@ describe('SonobiBidAdapter', function () { 'currency': 'USD', 'dealId': 'dozerkey', 'aid': '30292e432662bd5f86d90774b944b038' - } + }, + { + 'requestId': '30b31c1838de1g', + 'cpm': 1.07, + 'width': 300, + 'height': 600, + 'ad': ``, + 'ttl': 500, + 'creativeId': '1234abcd', + 'netRevenue': true, + 'currency': 'USD', + 'aid': '30292e432662bd5f86d90774b944b038' + }, ]; it('should map bidResponse to prebidResponse', function () { @@ -321,14 +340,22 @@ describe('SonobiBidAdapter', function () { response.forEach((resp, i) => { expect(resp.requestId).to.equal(prebidResponse[i].requestId); expect(resp.cpm).to.equal(prebidResponse[i].cpm); - expect(resp.width).to.equal(prebidResponse[i].width); - expect(resp.height).to.equal(prebidResponse[i].height); + expect(resp.ttl).to.equal(prebidResponse[i].ttl); expect(resp.creativeId).to.equal(prebidResponse[i].creativeId); expect(resp.netRevenue).to.equal(prebidResponse[i].netRevenue); expect(resp.currency).to.equal(prebidResponse[i].currency); expect(resp.aid).to.equal(prebidResponse[i].aid); - expect(resp.ad.indexOf('localhost')).to.be.greaterThan(0); + if (resp.mediaType === 'video') { + expect(resp.vastUrl.indexOf('vast.xml')).to.be.greaterThan(0); + expect(resp.ad).to.be.undefined; + expect(resp.width).to.be.undefined; + expect(resp.height).to.be.undefined; + } else { + expect(resp.ad.indexOf('localhost')).to.be.greaterThan(0); + expect(resp.width).to.equal(prebidResponse[i].width); + expect(resp.height).to.equal(prebidResponse[i].height); + } }); }); }); From 0654c064fe5c62994331e6548862da095f91cde7 Mon Sep 17 00:00:00 2001 From: Kelvin Chappell Date: Tue, 27 Nov 2018 21:55:01 +0000 Subject: [PATCH 0860/1594] Fix user-sync iframes insertion bug (#3300) According to documentation, iframes should be inserted at bottom of head, rather than at top. --- src/utils.js | 6 ++++-- test/spec/utils_spec.js | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/utils.js b/src/utils.js index 843c0c11c76..05fc627f795 100644 --- a/src/utils.js +++ b/src/utils.js @@ -552,16 +552,18 @@ var hasOwn = function (objectToCheck, propertyToCheckFor) { exports.insertElement = function(elm, doc, target) { doc = doc || document; let elToAppend; + const head = doc.getElementsByTagName('head'); if (target) { elToAppend = doc.getElementsByTagName(target); } else { - elToAppend = doc.getElementsByTagName('head'); + elToAppend = head; } try { elToAppend = elToAppend.length ? elToAppend : doc.getElementsByTagName('body'); if (elToAppend.length) { elToAppend = elToAppend[0]; - elToAppend.insertBefore(elm, elToAppend.firstChild); + const refChild = head && head[0] === elToAppend ? null : elToAppend.firstChild; + return elToAppend.insertBefore(elm, refChild); } } catch (e) {} }; diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index df5d46223c0..ea1ea55cd43 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -914,5 +914,14 @@ describe('Utils', function () { value: [''] }]); }); + + describe('insertElement', function () { + it('returns a node at bottom of head if no target is given', function () { + const toInsert = document.createElement('div'); + const head = document.getElementsByTagName('head')[0]; + const inserted = utils.insertElement(toInsert); + expect(inserted).to.equal(head.lastChild); + }); + }); }); }); From 2660078bc6ba70a55fea48d58ab7688ef001166d Mon Sep 17 00:00:00 2001 From: Gleb Glushtsov Date: Tue, 27 Nov 2018 16:58:18 -0500 Subject: [PATCH 0861/1594] Prevent 33Across adapter from throwing an error when unable to getElementById(), fix JSDocs in utils.js (#3333) * check gdpr in buildRequest * User sync based on whether gdpr applies or not * check if consent data exists during user sync * split user sync into further branches: 1) when gdpr does not apply 2) when consent data is unavailable * contribute viewability to ttxRequest * update tests * remove window mock from tests * use local variables * introduce ServerRequestBuilder * add withOptions() method to ServerRequestBuilder * add semicolons * sync up package-lock.json with upstream/master * stub window.top in tests * introduce getTopWindowSize() for test purpose * reformat code * add withSite() method to TtxRequestBuilder add withSite() method to TtxRequestBuilder * add isIframe() and _isViewabilityMeasurable() * handle NON_MEASURABLE viewability in nested iframes * consider page visibility, stub utils functions getWindowTop() and getWindowSelf() * contribute viewability as 0 for inactive tab * add prebidjs version to ttx request * send caller as an array * fix JSDoc in utils.js * send viewability as non measurable when unable to locate target HTMLElement, add warning message --- modules/33acrossBidAdapter.js | 12 ++++++--- src/utils.js | 46 +++++++++++++++++------------------ 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 2ecab4013f9..8bb084a7aeb 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -27,8 +27,8 @@ function _createBidResponse(response) { } } -function _isViewabilityMeasurable() { - return !_isIframe(); +function _isViewabilityMeasurable(element) { + return !_isIframe() && element !== null; } function _getViewability(element, topWin, { w, h } = {}) { @@ -46,12 +46,16 @@ function _createServerRequest(bidRequest, gdprConsent) { const sizes = _transformSizes(bidRequest.sizes); const minSize = _getMinSize(sizes); - const viewabilityAmount = _isViewabilityMeasurable() + const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, utils.getWindowTop(), minSize) : NON_MEASURABLE; const contributeViewability = ViewabilityContributor(viewabilityAmount); + if (element === null) { + utils.logWarn(`Unable to locate element with id: '${bidRequest.adUnitCode}'`); + } + /* * Infer data for the request payload */ @@ -90,7 +94,7 @@ function _createServerRequest(bidRequest, gdprConsent) { 'version': '$prebid.version$' }] } - } + }; // Finally, set the openRTB 'test' param if this is to be a test bid if (params.test === 1) { diff --git a/src/utils.js b/src/utils.js index 05fc627f795..7d9424f8489 100644 --- a/src/utils.js +++ b/src/utils.js @@ -124,7 +124,7 @@ exports.transformAdServerTargetingObj = function (targeting) { * Read an adUnit object and return the sizes used in an [[728, 90]] format (even if they had [728, 90] defined) * Preference is given to the `adUnit.mediaTypes.banner.sizes` object over the `adUnit.sizes` * @param {object} adUnit one adUnit object from the normal list of adUnits - * @returns {array[array[number]]} array of arrays containing numeric sizes + * @returns {Array.} array of arrays containing numeric sizes */ export function getAdUnitSizes(adUnit) { if (!adUnit) { @@ -151,8 +151,8 @@ export function getAdUnitSizes(adUnit) { /** * Parse a GPT-Style general size Array like `[[300, 250]]` or `"300x250,970x90"` into an array of sizes `["300x250"]` or '['300x250', '970x90']' - * @param {array[array|number]} sizeObj Input array or double array [300,250] or [[300,250], [728,90]] - * @return {array[string]} Array of strings like `["300x250"]` or `["300x250", "728x90"]` + * @param {(Array.|Array.)} sizeObj Input array or double array [300,250] or [[300,250], [728,90]] + * @return {Array.} Array of strings like `["300x250"]` or `["300x250", "728x90"]` */ export function parseSizesInput(sizeObj) { var parsedSizes = []; @@ -190,7 +190,7 @@ export function parseSizesInput(sizeObj) { } return parsedSizes; -}; +} // parse a GPT style sigle size array, (i.e [300,250]) // into an AppNexus style string, (i.e. 300x250) @@ -199,7 +199,7 @@ export function parseGPTSingleSizeArray(singleSize) { if (exports.isArray(singleSize) && singleSize.length === 2 && (!isNaN(singleSize[0]) && !isNaN(singleSize[1]))) { return singleSize[0] + 'x' + singleSize[1]; } -}; +} /** * @deprecated This function will be removed soon. Use http://prebid.org/dev-docs/bidder-adaptor.html#referrers @@ -215,7 +215,7 @@ exports.getTopWindowLocation = function() { if (loc) return parse(loc, {'decodeSearchAsString': true}); } return exports.getWindowLocation(); -} +}; /** * @deprecated This function will be removed soon. Use http://prebid.org/dev-docs/bidder-adaptor.html#referrers @@ -375,9 +375,9 @@ exports.getParameterByName = getParameterByName; /** * This function validates paramaters. - * @param {object[string]} paramObj [description] + * @param {Object} paramObj [description] * @param {string[]} requiredParamsArr [description] - * @return {bool} Bool if paramaters are valid + * @return {boolean} Bool if paramaters are valid */ exports.hasValidBidRequest = function (paramObj, requiredParamsArr, adapter) { var found = false; @@ -439,11 +439,11 @@ exports.isNumber = function(object) { exports.isPlainObject = function(object) { return exports.isA(object, tObject); -} +}; exports.isBoolean = function(object) { return exports.isA(object, tBoolean); -} +}; /** * Return if the object is "empty"; @@ -671,8 +671,8 @@ exports.createTrackPixelIframeHtml = function (url, encodeUri = true, sandbox = /** * Returns iframe document in a browser agnostic way - * @param {object} iframe reference - * @return {object} iframe `document` reference + * @param {Object} iframe reference + * @return {Object} iframe `document` reference */ exports.getIframeDocument = function (iframe) { if (!iframe) { @@ -876,7 +876,7 @@ export function delayExecution(func, numRequiredCalls) { * @export * @param {array} xs * @param {string} key - * @returns {${key_value}: ${groupByArray}, key_value: {groupByArray}} + * @returns {Object} {${key_value}: ${groupByArray}, key_value: {groupByArray}} */ export function groupBy(xs, key) { return xs.reduce(function(rv, x) { @@ -887,7 +887,7 @@ export function groupBy(xs, key) { /** * deepAccess utility function useful for doing safe access (will not throw exceptions) of deep object paths. - * @param {object} obj The object containing the values you would like to access. + * @param {Object} obj The object containing the values you would like to access. * @param {string|number} path Object path to the value you would like to access. Non-strings are coerced to strings. * @returns {*} The value found at the specified object path, or undefined if path is not found. */ @@ -907,7 +907,7 @@ export function deepAccess(obj, path) { /** * Returns content for a friendly iframe to execute a URL in script tag - * @param {url} URL to be executed in a script tag in a friendly iframe + * @param {string} url URL to be executed in a script tag in a friendly iframe * and are macros left to be replaced if required */ export function createContentToExecuteExtScriptInFriendlyFrame(url) { @@ -921,9 +921,9 @@ export function createContentToExecuteExtScriptInFriendlyFrame(url) { /** * Build an object consisting of only defined parameters to avoid creating an * object with defined keys and undefined values. - * @param {object} object The object to pick defined params out of + * @param {Object} object The object to pick defined params out of * @param {string[]} params An array of strings representing properties to look for in the object - * @returns {object} An object containing all the specified values that are defined + * @returns {Object} An object containing all the specified values that are defined */ export function getDefinedParams(object, params) { return params @@ -968,8 +968,8 @@ export function getBidderRequest(bidRequests, bidder, adUnitCode) { } /** * Returns user configured bidder params from adunit - * @param {object} adunits - * @param {string} adunit code + * @param {Object} adUnits + * @param {string} adUnitCode code * @param {string} bidder code * @return {Array} user configured param for the given bidder adunit configuration */ @@ -1004,7 +1004,7 @@ const compareCodeAndSlot = (slot, adUnitCode) => slot.getAdUnitPath() === adUnit /** * Returns filter function to match adUnitCode in slot - * @param {object} slot GoogleTag slot + * @param {Object} slot GoogleTag slot * @return {function} filter function */ export function isAdUnitCodeMatchingSlot(slot) { @@ -1043,9 +1043,9 @@ export function unsupportedBidderMessage(adUnit, bidder) { * @return {Object} object */ export function deletePropertyFromObject(object, prop) { - let result = Object.assign({}, object) + let result = Object.assign({}, object); delete result[prop]; - return result + return result; } /** @@ -1083,7 +1083,7 @@ export function convertCamelToUnderscore(value) { * normally read from bidder params * eg { foo: ['bar', 'baz'], fizz: ['buzz'] } * becomes [{ key: 'foo', value: ['bar', 'baz']}, {key: 'fizz', value: ['buzz']}] - * @param {Object{Arrays}} keywords object of arrays representing keyvalue pairs + * @param {Object} keywords object of arrays representing keyvalue pairs * @param {string} paramName name of parent object (eg 'keywords') containing keyword data, used in error handling */ export function transformBidderParamKeywords(keywords, paramName = 'keywords') { From a4863aee9c06179bc543e7b4232221265573ed46 Mon Sep 17 00:00:00 2001 From: Brittany Zellman <33695402+brittanyzellman@users.noreply.github.com> Date: Tue, 27 Nov 2018 17:10:28 -0500 Subject: [PATCH 0862/1594] TripleliftBidAdapter-update creative_id (#3324) * removed dependancy on getTopWindowUrl for referer * protect against undefined obj and remove test on old dependency * added unit test for referer and gdpr in query string * removed gdpr test * removed gdpr from bidderRequest obj * decontructed bidder request obj in chai test * just need to run karma tests again * added gdpr consent to all bidderRequest obj in chai tests * changed creativeId to be a Triplelift specific id rather than represent SRA impression * error-proofed creative id From 45a41ade8960c4e28fd8fe850aac2071251c6e3e Mon Sep 17 00:00:00 2001 From: Michael Callari Date: Wed, 28 Nov 2018 10:08:37 -0500 Subject: [PATCH 0863/1594] Updating Optimera scores file base path. (#3312) --- modules/optimeraBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/optimeraBidAdapter.js b/modules/optimeraBidAdapter.js index fc3c4c96f1b..4f77a9da1ac 100644 --- a/modules/optimeraBidAdapter.js +++ b/modules/optimeraBidAdapter.js @@ -1,6 +1,6 @@ import {registerBidder} from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'optimera'; -const SCORES_BASE_URL = 'https://s3.amazonaws.com/elasticbeanstalk-us-east-1-397719490216/json/client/'; +const SCORES_BASE_URL = 'https://s3.amazonaws.com/optimera-client/'; export const spec = { code: BIDDER_CODE, From 27107e27911861af2235c2efcc4f029fb5e2c1ab Mon Sep 17 00:00:00 2001 From: lu-ruo Date: Wed, 28 Nov 2018 09:04:39 -0800 Subject: [PATCH 0864/1594] support image pixel type for user sync (#3326) --- modules/openxBidAdapter.js | 7 ++- test/spec/modules/openxBidAdapter_spec.js | 68 +++++++++++++++++------ 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 7119d669cb4..446c790fded 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.5'; +const BIDDER_VERSION = '2.1.6'; let shouldSendBoPixel = true; @@ -55,12 +55,13 @@ export const spec = { : createBannerBidResponses(oxResponseObj, serverRequest.payload); }, getUserSyncs: function (syncOptions, responses) { - if (syncOptions.iframeEnabled) { + if (syncOptions.iframeEnabled || syncOptions.pixelEnabled) { + let pixelType = syncOptions.iframeEnabled ? 'iframe' : 'image'; let url = utils.deepAccess(responses, '0.body.ads.pixels') || utils.deepAccess(responses, '0.body.pixels') || '//u.openx.net/w/1.0/pd'; return [{ - type: 'iframe', + type: pixelType, url: url }]; } diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 8a602dc479b..4d9266169a0 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1450,28 +1450,64 @@ describe('OpenxAdapter', function () { describe('user sync', function () { const syncUrl = 'http://testpixels.net'; - it('should register the pixel iframe from banner ad response', function () { - let syncs = spec.getUserSyncs( - {iframeEnabled: true}, - [{body: {ads: {pixels: syncUrl}}}] - ); - expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); + describe('iframe sync', function () { + it('should register the pixel iframe from banner ad response', function () { + let syncs = spec.getUserSyncs( + {iframeEnabled: true}, + [{body: {ads: {pixels: syncUrl}}}] + ); + expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); + }); + + it('should register the pixel iframe from video ad response', function () { + let syncs = spec.getUserSyncs( + {iframeEnabled: true}, + [{body: {pixels: syncUrl}}] + ); + expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); + }); + + it('should register the default iframe if no pixels available', function () { + let syncs = spec.getUserSyncs( + {iframeEnabled: true}, + [] + ); + expect(syncs).to.deep.equal([{type: 'iframe', url: '//u.openx.net/w/1.0/pd'}]); + }); }); - it('should register the pixel iframe from video ad response', function () { - let syncs = spec.getUserSyncs( - {iframeEnabled: true}, - [{body: {pixels: syncUrl}}] - ); - expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); + describe('pixel sync', function () { + it('should register the image pixel from banner ad response', function () { + let syncs = spec.getUserSyncs( + {pixelEnabled: true}, + [{body: {ads: {pixels: syncUrl}}}] + ); + expect(syncs).to.deep.equal([{type: 'image', url: syncUrl}]); + }); + + it('should register the image pixel from video ad response', function () { + let syncs = spec.getUserSyncs( + {pixelEnabled: true}, + [{body: {pixels: syncUrl}}] + ); + expect(syncs).to.deep.equal([{type: 'image', url: syncUrl}]); + }); + + it('should register the default image pixel if no pixels available', function () { + let syncs = spec.getUserSyncs( + {pixelEnabled: true}, + [] + ); + expect(syncs).to.deep.equal([{type: 'image', url: '//u.openx.net/w/1.0/pd'}]); + }); }); - it('should register the default iframe if no pixels available', function () { + it('should prioritize iframe over image for user sync', function () { let syncs = spec.getUserSyncs( - {iframeEnabled: true}, - [] + {iframeEnabled: true, pixelEnabled: true}, + [{body: {ads: {pixels: syncUrl}}}] ); - expect(syncs).to.deep.equal([{type: 'iframe', url: '//u.openx.net/w/1.0/pd'}]); + expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); }); }); From 45f1f67c5583f4c3bc4191ef1f0b471bd9d52c2a Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 28 Nov 2018 15:42:39 -0500 Subject: [PATCH 0865/1594] Prebid 1.34.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 81f46b620b0..29738c99bf4 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.34.0-pre", + "version": "1.34.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 56b154caa525fa0cf5150146051cbc2b9cbb7a20 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 28 Nov 2018 16:01:59 -0500 Subject: [PATCH 0866/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 29738c99bf4..08c7d3a6587 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.34.0", + "version": "1.35.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 96fef93b4d51714e493460a112c65b87bcf765b8 Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Thu, 29 Nov 2018 14:34:44 +0000 Subject: [PATCH 0867/1594] Added 980x150 size (#3334) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 1eef3b4813d..76122452222 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -70,6 +70,7 @@ var sizeMap = { 125: '800x250', 126: '200x600', 144: '980x600', + 145: '980x150', 159: '320x250', 195: '600x300', 199: '640x200', From e9bd097d3b11ca74739be47383df657770b34394 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 30 Nov 2018 10:08:40 -0500 Subject: [PATCH 0868/1594] replaced deprecated getWindowTopLocation with refererInfo.referer (#3332) * replaced deprecated getWindowTopLocation with refererInfo.referer * Removed unused import and unnecessary reassign * Rename variable bidderRequests to bidderRequest Renamed the bidderRequests variable to the singular bidderRequest to better portray the value as a single request instead of multiple. --- modules/sonobiBidAdapter.js | 21 +++++++------- test/spec/modules/sonobiBidAdapter_spec.js | 32 +++++++++++++++++++--- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 0400aa46ecf..a65657ec13a 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -1,5 +1,5 @@ import { registerBidder } from 'src/adapters/bidderFactory'; -import { getTopWindowLocation, parseSizesInput, logError, generateUUID, isEmpty } from '../src/utils'; +import { parseSizesInput, logError, generateUUID, isEmpty } from '../src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; import { config } from '../src/config'; @@ -46,7 +46,7 @@ export const spec = { const payload = { 'key_maker': JSON.stringify(data), - 'ref': getTopWindowLocation().href, + 'ref': bidderRequest.refererInfo.referer, 's': generateUUID(), 'pv': PAGEVIEW_ID, 'vp': _getPlatform(), @@ -91,12 +91,13 @@ export const spec = { * Unpack the response from the server into a list of bids. * * @param {*} serverResponse A successful response from the server. - * @param {*} bidderRequests - Info describing the request to the server. + * @param {*} bidderRequest - Info describing the request to the server. * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse: (serverResponse, { bidderRequests }) => { + interpretResponse: (serverResponse, bidderRequest) => { const bidResponse = serverResponse.body; const bidsReturned = []; + const referrer = bidderRequest.data.ref; if (Object.keys(bidResponse.slots).length === 0) { return bidsReturned; @@ -106,7 +107,7 @@ export const spec = { const bid = bidResponse.slots[slot]; const bidId = _getBidIdFromTrinityKey(slot); const mediaType = (bid.sbi_ct === 'video') ? 'video' : null; - const createCreative = _creative(mediaType); + const createCreative = _creative(mediaType, referrer); if (bid.sbi_aid && bid.sbi_mouse && bid.sbi_size) { const [ width = 1, @@ -181,16 +182,16 @@ function _validateFloor (bid) { return ''; } -const _creative = (mediaType) => (sbiDc, sbiAid) => { +const _creative = (mediaType, referer) => (sbiDc, sbiAid) => { if (mediaType === 'video') { - return _videoCreative(sbiDc, sbiAid) + return _videoCreative(sbiDc, sbiAid, referer) } - const src = `https://${sbiDc}apex.go.sonobi.com/sbi.js?aid=${sbiAid}&as=null&ref=${encodeURIComponent(getTopWindowLocation().href)}`; + const src = `https://${sbiDc}apex.go.sonobi.com/sbi.js?aid=${sbiAid}&as=null&ref=${encodeURIComponent(referer)}`; return ''; }; -function _videoCreative(sbiDc, sbiAid) { - return `https://${sbiDc}apex.go.sonobi.com/vast.xml?vid=${sbiAid}&ref=${encodeURIComponent(getTopWindowLocation().href)}` +function _videoCreative(sbiDc, sbiAid, referer) { + return `https://${sbiDc}apex.go.sonobi.com/vast.xml?vid=${sbiAid}&ref=${encodeURIComponent(referer)}` } function _getBidIdFromTrinityKey (key) { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 43b35c7d961..593b885176e 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -136,11 +136,17 @@ describe('SonobiBidAdapter', function () { 'vendorData': {}, 'gdprApplies': true }, + 'refererInfo': { + 'numIframes': 0, + 'reachedTop': true, + 'referer': 'http://example.com', + 'stack': ['http://example.com'] + } }; it('should return a properly formatted request', function () { - const bidRequests = spec.buildRequests(bidRequest) - const bidRequestsPageViewID = spec.buildRequests(bidRequest) + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + const bidRequestsPageViewID = spec.buildRequests(bidRequest, bidderRequests) expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') expect(bidRequests.method).to.equal('GET') expect(bidRequests.data.key_maker).to.deep.equal(JSON.stringify(keyMakerData)) @@ -161,6 +167,12 @@ describe('SonobiBidAdapter', function () { expect(bidRequests.data.consent_string).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A==') }) + it('should return a properly formatted request with referer', function () { + bidRequest[0].params.referrer = '' + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.data.ref).to.equal('http://example.com') + }) + it('should return a properly formatted request with GDPR applies set to false', function () { bidderRequests.gdprConsent.gdprApplies = false; const bidRequests = spec.buildRequests(bidRequest, bidderRequests) @@ -176,6 +188,12 @@ describe('SonobiBidAdapter', function () { 'vendorData': {}, 'gdprApplies': false }, + 'refererInfo': { + 'numIframes': 0, + 'reachedTop': true, + 'referer': 'http://example.com', + 'stack': ['http://example.com'] + } }; const bidRequests = spec.buildRequests(bidRequest, bidderRequests) expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') @@ -190,6 +208,12 @@ describe('SonobiBidAdapter', function () { 'vendorData': {}, 'gdprApplies': true }, + 'refererInfo': { + 'numIframes': 0, + 'reachedTop': true, + 'referer': 'http://example.com', + 'stack': ['http://example.com'] + } }; const bidRequests = spec.buildRequests(bidRequest, bidderRequests) expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') @@ -200,7 +224,7 @@ describe('SonobiBidAdapter', function () { it('should return a properly formatted request with hfa', function () { bidRequest[0].params.hfa = 'hfakey' bidRequest[1].params.hfa = 'hfakey' - const bidRequests = spec.buildRequests(bidRequest) + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') expect(bidRequests.method).to.equal('GET') expect(bidRequests.data.ref).not.to.be.empty @@ -209,7 +233,7 @@ describe('SonobiBidAdapter', function () { }) it('should return null if there is nothing to bid on', function () { - const bidRequests = spec.buildRequests([{params: {}}]) + const bidRequests = spec.buildRequests([{params: {}}], bidderRequests) expect(bidRequests).to.equal(null); }) }) From 7aef26e03b40cae5b4a9691f45447ac7dca932b6 Mon Sep 17 00:00:00 2001 From: Keiran Date: Mon, 3 Dec 2018 07:52:36 -0800 Subject: [PATCH 0869/1594] new TapHype bidder adapter (#3319) * new TapHype bidder adapter * Added 930x600 to Rubicon Adapter (#3323) * PubMatic adapter to support TTD (#3311) * first commit * added unit test cases for TTD id * Sonobi - support video and display same adunit (#3325) * changed adapter to support video and display for ad unit * added case for sbi_ct outstream * outstream is display media type * Fix user-sync iframes insertion bug (#3300) According to documentation, iframes should be inserted at bottom of head, rather than at top. * Prevent 33Across adapter from throwing an error when unable to getElementById(), fix JSDocs in utils.js (#3333) * check gdpr in buildRequest * User sync based on whether gdpr applies or not * check if consent data exists during user sync * split user sync into further branches: 1) when gdpr does not apply 2) when consent data is unavailable * contribute viewability to ttxRequest * update tests * remove window mock from tests * use local variables * introduce ServerRequestBuilder * add withOptions() method to ServerRequestBuilder * add semicolons * sync up package-lock.json with upstream/master * stub window.top in tests * introduce getTopWindowSize() for test purpose * reformat code * add withSite() method to TtxRequestBuilder add withSite() method to TtxRequestBuilder * add isIframe() and _isViewabilityMeasurable() * handle NON_MEASURABLE viewability in nested iframes * consider page visibility, stub utils functions getWindowTop() and getWindowSelf() * contribute viewability as 0 for inactive tab * add prebidjs version to ttx request * send caller as an array * fix JSDoc in utils.js * send viewability as non measurable when unable to locate target HTMLElement, add warning message * TripleliftBidAdapter-update creative_id (#3324) * removed dependancy on getTopWindowUrl for referer * protect against undefined obj and remove test on old dependency * added unit test for referer and gdpr in query string * removed gdpr test * removed gdpr from bidderRequest obj * decontructed bidder request obj in chai test * just need to run karma tests again * added gdpr consent to all bidderRequest obj in chai tests * changed creativeId to be a Triplelift specific id rather than represent SRA impression * error-proofed creative id * Update taphypeBidAdapter.js removed `supportedMediaTypes` and logging * Update taphypeBidAdapter.js remove mediaTypes import * new TapHype bidder adapter * Update taphypeBidAdapter.js removed `supportedMediaTypes` and logging * Update taphypeBidAdapter.js remove mediaTypes import --- modules/taphypeBidAdapter.js | 45 +++++++++++++++++ modules/taphypeBidAdapter.md | 32 ++++++++++++ test/spec/modules/taphypeBidAdapter_spec.js | 56 +++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 modules/taphypeBidAdapter.js create mode 100644 modules/taphypeBidAdapter.md create mode 100644 test/spec/modules/taphypeBidAdapter_spec.js diff --git a/modules/taphypeBidAdapter.js b/modules/taphypeBidAdapter.js new file mode 100644 index 00000000000..ae9eb7296e0 --- /dev/null +++ b/modules/taphypeBidAdapter.js @@ -0,0 +1,45 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; + +export const spec = { + code: 'taphype', + isBidRequestValid: function (bid) { + return !!bid.params.placementId; + }, + buildRequests: function (bidRequests) { + const requests = bidRequests.map(function (bid) { + const params = { + placementId: bid.params.placementId, + url: encodeURIComponent(window.location.href), + size: bid.sizes[0][0] + 'x' + bid.sizes[0][1], + rnd: Math.random(), + bidId: bid.bidId, + }; + + return {method: 'GET', url: 'https://us-central1-taphype-internal.cloudfunctions.net/th-prebid', data: params, options: {withCredentials: false}} + }); + + return requests; + }, + interpretResponse: function (serverResponse, bidRequest) { + if (!serverResponse || !serverResponse.body || !serverResponse.body.ad) { + return []; + } + + const bid = serverResponse.body; + const sizes = bid.size.split(','); + + return [{ + requestId: bidRequest.data.bidId, + cpm: bid.price, + width: sizes[0], + height: sizes[1], + creativeId: bidRequest.data.bidId, + currency: bid.currency || 'USD', + netRevenue: true, + ad: bid.ad, + ttl: 360 + }]; + }, +}; + +registerBidder(spec); diff --git a/modules/taphypeBidAdapter.md b/modules/taphypeBidAdapter.md new file mode 100644 index 00000000000..c6ff40a42ba --- /dev/null +++ b/modules/taphypeBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +Module Name: TapHype Bidder Adapter +Module Type: Bidder Adapter +Maintainer: admin@taphype.com + +# Description + +You can use this adapter to get a bid from taphype.com. + + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'div-taphype-example', + sizes: [[300, 250]], + bids: [ + { + bidder: "taphype", + params: { + placementId: 12345 + } + } + ] + } + ]; +``` + +Where: + +* placementId - TapHype Placement ID diff --git a/test/spec/modules/taphypeBidAdapter_spec.js b/test/spec/modules/taphypeBidAdapter_spec.js new file mode 100644 index 00000000000..2fcdd964520 --- /dev/null +++ b/test/spec/modules/taphypeBidAdapter_spec.js @@ -0,0 +1,56 @@ +import { expect } from 'chai'; +import { spec } from 'modules/taphypeBidAdapter'; + +describe('taphypeBidAdapterTests', function () { + it('validate_pub_params', function () { + expect(spec.isBidRequestValid({ + bidder: 'taphype', + params: { + placementId: 12345 + } + })).to.equal(true); + }); + + it('validate_generated_params', function () { + let bidRequestData = [{ + bidId: 'bid12345', + bidder: 'taphype', + params: { + placementId: 12345 + }, + sizes: [[300, 250]] + }]; + + let request = spec.buildRequests(bidRequestData); + let req_data = request[0].data; + + expect(req_data.bidId).to.equal('bid12345'); + }); + + it('validate_response_params', function () { + let bidRequestData = { + data: { + bidId: 'bid12345' + } + }; + + let serverResponse = { + body: { + price: 1.23, + ad: '', + size: '300,250' + } + }; + + let bids = spec.interpretResponse(serverResponse, bidRequestData); + expect(bids).to.have.lengthOf(1); + let bid = bids[0]; + expect(bid.cpm).to.equal(1.23); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal('300'); + expect(bid.height).to.equal('250'); + expect(bid.netRevenue).to.equal(true); + expect(bid.requestId).to.equal('bid12345'); + expect(bid.ad).to.equal(''); + }); +}); From 6f1d23b8f8ceeaa62b50c96782e4f491a7457195 Mon Sep 17 00:00:00 2001 From: Jeremy Hernandez Date: Mon, 3 Dec 2018 19:01:07 +0100 Subject: [PATCH 0870/1594] fix(adyoulike): use bidderRequest referer info (#3339) --- modules/adyoulikeBidAdapter.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index b9f57115e21..d0ca4e07d08 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -31,7 +31,6 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (bidRequests, bidderRequest) { - let dcHostname = getHostname(bidRequests); const payload = { Version: VERSION, Bids: bidRequests.reduce((accumulator, bid) => { @@ -60,7 +59,7 @@ export const spec = { return { method: 'POST', - url: createEndpoint(dcHostname), + url: createEndpoint(bidRequests, bidderRequest), data, options }; @@ -94,14 +93,10 @@ function getHostname(bidderRequest) { } /* Get current page referrer url */ -function getReferrerUrl() { +function getReferrerUrl(bidderRequest) { let referer = ''; - if (window.self !== window.top) { - try { - referer = window.top.document.referrer; - } catch (e) { } - } else { - referer = document.referrer; + if (bidderRequest && bidderRequest.refererInfo) { + referer = encodeURIComponent(bidderRequest.refererInfo.referer); } return referer; } @@ -134,20 +129,21 @@ function getPageRefreshed() { } /* Create endpoint url */ -function createEndpoint(host) { +function createEndpoint(bidRequests, bidderRequest) { + let host = getHostname(bidRequests); return format({ protocol: (document.location.protocol === 'https:') ? 'https' : 'http', host: `${DEFAULT_DC}${host}.omnitagjs.com`, pathname: '/hb-api/prebid/v1', - search: createEndpointQS() + search: createEndpointQS(bidderRequest) }); } /* Create endpoint query string */ -function createEndpointQS() { +function createEndpointQS(bidderRequest) { const qs = {}; - const ref = getReferrerUrl(); + const ref = getReferrerUrl(bidderRequest); if (ref) { qs.RefererUrl = encodeURIComponent(ref); } From b215559cc0cf364be549fb69314cc15dd5aca268 Mon Sep 17 00:00:00 2001 From: Benjamin Clot Date: Tue, 4 Dec 2018 18:03:54 +0100 Subject: [PATCH 0871/1594] Fix for Quantum Adapter empty size detection (#3329) --- modules/quantumBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quantumBidAdapter.js b/modules/quantumBidAdapter.js index d17423bc49d..f14ce3226f7 100644 --- a/modules/quantumBidAdapter.js +++ b/modules/quantumBidAdapter.js @@ -106,7 +106,7 @@ export const spec = { if (serverBody.cobj) { bid.cobj = serverBody.cobj; } - if (bidRequest.sizes) { + if (!utils.isEmpty(bidRequest.sizes)) { bid.width = bidRequest.sizes[0][0]; bid.height = bidRequest.sizes[0][1]; } From 5e3f144b21e799cb5baa50e41d035a217c29f85b Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 4 Dec 2018 13:14:33 -0500 Subject: [PATCH 0872/1594] update gulp packages to address vulnerability (#3343) * update gulp packages to address vulnerability * some minor cleanup in the gulpfile tasks * replace the fork used for gulp-footer --- gulpfile.js | 76 +- package-lock.json | 8456 ++++++++++++++++++++++++++++++++++++--------- package.json | 6 +- 3 files changed, 6834 insertions(+), 1704 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 03a0a4a7559..c8ca36324cb 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,7 +4,7 @@ var _ = require('lodash'); var argv = require('yargs').argv; var gulp = require('gulp'); var gutil = require('gulp-util'); -var connect = require('gulp-connect'); +var webserver = require('gulp-webserver'); var webpack = require('webpack'); var webpackStream = require('webpack-stream'); var uglify = require('gulp-uglify'); @@ -56,11 +56,12 @@ function e2etestReport() { var reportPort = 9010; var targetDestinationDir = './e2etest-report'; helpers.createEnd2EndTestReport(targetDestinationDir); - connect.server({ - port: reportPort, - root: './', - livereload: true - }); + gulp.src('./') + .pipe(webserver({ + port: reportPort, + directoryListing: true, + livereload: true + })); setTimeout(function() { opens('http://localhost:' + reportPort + '/' + targetDestinationDir.slice(2) + '/results.html'); @@ -90,13 +91,14 @@ function lint(done) { function viewCoverage(done) { var coveragePort = 1999; - connect.server({ - port: coveragePort, - root: 'build/coverage/karma_html', - livereload: false - }); - opens('http://localhost:' + coveragePort); - done(); + var stream = gulp.src('./') + .pipe(webserver({ + port: coveragePort, + directoryListing: true, + livereload: false, + open: 'build/coverage/karma_html/index.html' + })); + stream.on('finish', done); }; viewCoverage.displayName = 'view-coverage'; @@ -113,16 +115,17 @@ function watch(done) { 'test/spec/loaders/**/*.js' ]); - connect.server({ - https: argv.https, - port: port, - root: './', - livereload: true - }); + var stream = gulp.src('./') + .pipe(webserver({ + https: argv.https, + port: port, + directoryListing: true, + livereload: true + })); mainWatcher.on('all', gulp.series(clean, gulp.parallel(lint, 'build-bundle-dev', test))); loaderWatcher.on('all', gulp.series(lint)); - done(); + stream.on('finish', done); }; function makeDevpackPkg() { @@ -137,8 +140,7 @@ function makeDevpackPkg() { .pipe(helpers.nameModules(externalModules)) .pipe(webpackStream(cloned, webpack)) .pipe(replace('$prebid.version$', prebid.version)) - .pipe(gulp.dest('build/dev')) - .pipe(connect.reload()); + .pipe(gulp.dest('build/dev')); } function makeWebpackPkg() { @@ -158,8 +160,7 @@ function makeWebpackPkg() { .pipe(uglify()) .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid }))) .pipe(optimizejs()) - .pipe(gulp.dest('build/dist')) - .pipe(connect.reload()); + .pipe(gulp.dest('build/dist')); } function gulpBundle(dev) { @@ -227,12 +228,7 @@ function newKarmaCallback(done) { if (exitCode) { done(new Error('Karma tests failed with exit code ' + exitCode)); } else { - if (argv.browserstack) { - // process.exit(0); - done(); // test this with travis (or circleci) - } else { - done(); - } + done(); } } } @@ -273,26 +269,6 @@ function coveralls() { // 2nd arg is a dependency: 'test' must be finished .pipe(shell('cat build/coverage/lcov.info | node_modules/coveralls/bin/coveralls.js')); } -// Watch Task with Live Reload -gulp.task('watch', function () { - gulp.watch([ - 'src/**/*.js', - 'modules/**/*.js', - 'test/spec/**/*.js', - '!test/spec/loaders/**/*.js' - ], ['build-bundle-dev', 'test']); - gulp.watch([ - 'loaders/**/*.js', - 'test/spec/loaders/**/*.js' - ], ['lint']); - connect.server({ - https: argv.https, - port: port, - root: './', - livereload: true - }); -}); - function e2eTest() { var cmdQueue = []; if (argv.browserstack) { diff --git a/package-lock.json b/package-lock.json index 28a701a2de3..794b2d88c60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,29 @@ { "name": "prebid.js", - "version": "1.28.0", + "version": "1.35.0-pre", "lockfileVersion": 1, + "requires": true, "dependencies": { "@gulp-sourcemaps/identity-map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", - "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==" + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.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=" + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + } }, "@sindresorhus/is": { "version": "0.7.0", @@ -23,13 +35,29 @@ "version": "2.0.0", "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "dev": true + "dev": true, + "requires": { + "samsam": "1.3.0" + } }, "@sinonjs/samsam": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.0.tgz", "integrity": "sha512-5x2kFgJYupaF1ns/RmharQ90lQkd2ELS8A9X0ymkAAdemYHGtI2KiUHG8nX2WU0T1qgnOU5YMqnBM2V7NUanNw==", - "dev": true + "dev": true, + "requires": { + "array-from": "^2.1.1" + } + }, + "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" + } }, "abbrev": { "version": "1.0.9", @@ -41,7 +69,11 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } }, "acorn": { "version": "5.7.3", @@ -53,6 +85,9 @@ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", "dev": true, + "requires": { + "acorn": "^4.0.3" + }, "dependencies": { "acorn": { "version": "4.0.13", @@ -67,6 +102,9 @@ "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, + "requires": { + "acorn": "^3.0.4" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -93,13 +131,35 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } }, "ajv": { "version": "6.2.0", "resolved": "http://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", - "dev": true + "dev": true, + "requires": { + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + }, + "dependencies": { + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "http://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": "2.1.1", @@ -112,12 +172,20 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -128,11 +196,19 @@ "dev": true }, "amqplib": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.3.tgz", + "integrity": "sha512-ZOdUhMxcF+u62rPI+hMtU1NBXSDFQ3eCJJrenamtdQ7YYwh7RZJHOIM1gonVbZ5PyVdYH4xqBPje9OYqk7fnqw==", "dev": true, "optional": true, + "requires": { + "bitsyntax": "~0.1.0", + "bluebird": "^3.5.2", + "buffer-more-ints": "~1.0.0", + "readable-stream": "1.x >=1.1.9", + "safe-buffer": "~5.1.2", + "url-parse": "~1.4.3" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -146,11 +222,17 @@ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, - "optional": true + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true, "optional": true @@ -161,11 +243,14 @@ "version": "1.1.0", "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } }, "ansi-escapes": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, @@ -173,7 +258,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-html": { "version": "0.0.7", @@ -182,16 +270,17 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==" }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } }, "ansi-wrap": { "version": "0.1.0", @@ -203,19 +292,29 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } }, "append-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } }, "append-transform": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } }, "archy": { "version": "1.0.0", @@ -227,7 +326,9 @@ "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.2" + } }, "arr-diff": { "version": "4.0.0", @@ -239,7 +340,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } }, "arr-flatten": { "version": "1.1.0", @@ -251,7 +355,10 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } }, "arr-union": { "version": "3.1.0", @@ -288,6 +395,10 @@ "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -302,6 +413,9 @@ "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", "dev": true, + "requires": { + "is-number": "^4.0.0" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -322,6 +436,11 @@ "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -331,12 +450,6 @@ } } }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true - }, "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", @@ -355,29 +468,33 @@ "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, "asn1": { "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.0" + } }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "assert": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "dev": true, + "requires": { + "util": "0.10.3" + }, "dependencies": { "inherits": { "version": "2.0.1", @@ -387,17 +504,19 @@ }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true + "dev": true, + "requires": { + "inherits": "2.0.1" + } } } }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "assertion-error": { "version": "1.1.0", @@ -412,9 +531,9 @@ "dev": true }, "ast-types": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.6.tgz", - "integrity": "sha512-nHiuV14upVGl7MWwFUYbzJ6YlfwWS084CU9EA8HajfYQjMSli5TQi3UTRygGF58LFWVkXxS1rbgRhROEqlQkXg==", + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.7.tgz", + "integrity": "sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw==", "dev": true }, "async": { @@ -428,6 +547,12 @@ "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^1.0.7", + "stream-exhaust": "^1.0.1" + }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -453,13 +578,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true + "dev": true, + "requires": { + "async-done": "^1.2.2" + } }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "atob": { "version": "2.1.2", @@ -469,14 +596,12 @@ "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 + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "axios": { "version": "0.15.3", @@ -484,20 +609,29 @@ "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", "dev": true, "optional": true, + "requires": { + "follow-redirects": "1.0.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, - "optional": true + "optional": true, + "requires": { + "ms": "2.0.0" + } }, "follow-redirects": { "version": "1.0.0", "resolved": "http://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", "dev": true, - "optional": true + "optional": true, + "requires": { + "debug": "^2.2.0" + } }, "ms": { "version": "2.0.0", @@ -512,19 +646,48 @@ "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 + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } }, "babel-core": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "babel-generator": "^6.22.0", + "babel-helpers": "^6.22.0", + "babel-messages": "^6.22.0", + "babel-register": "^6.22.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.22.0", + "babel-traverse": "^6.22.0", + "babel-types": "^6.22.0", + "babylon": "^6.11.0", + "convert-source-map": "^1.1.0", + "debug": "^2.1.1", + "json5": "^0.5.0", + "lodash": "^4.2.0", + "minimatch": "^3.0.2", + "path-is-absolute": "^1.0.0", + "private": "^0.1.6", + "slash": "^1.0.0", + "source-map": "^0.5.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -545,6 +708,16 @@ "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": { "source-map": { "version": "0.5.7", @@ -558,109 +731,201 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-builder-react-jsx": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } }, "babel-helper-call-delegate": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-define-map": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-helper-explode-assignable-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-explode-class": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-get-function-arity": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-hoist-variables": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-regex": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-helper-remap-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helpers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-loader": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz", "integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==", - "dev": true + "dev": true, + "requires": { + "find-cache-dir": "^1.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.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 + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-check-es2015-constants": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", @@ -750,312 +1015,600 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0" + } }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-generators": "^6.5.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-class-constructor-call": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "^6.18.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-class-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-decorators": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true + "dev": true, + "requires": { + "babel-helper-explode-class": "^6.24.1", + "babel-plugin-syntax-decorators": "^6.13.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-decorators-legacy": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-decorators": "^6.1.18", + "babel-runtime": "^6.2.0", + "babel-template": "^6.3.0" + } }, "babel-plugin-transform-do-expressions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-block-scoping": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-plugin-transform-es2015-classes": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-computed-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-destructuring": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-duplicate-keys": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-for-of": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-modules-amd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } }, "babel-plugin-transform-es2015-modules-systemjs": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-modules-umd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-parameters": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-shorthand-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-spread": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-sticky-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-template-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-typeof-symbol": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-unicode-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } }, "babel-plugin-transform-exponentiation-operator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-export-extensions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-flow-strip-types": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-function-bind": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true - }, + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, "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=" + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx-source": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-regenerator": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true + "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + } }, "babel-plugin-transform-strict-mode": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } }, "babel-preset-flow": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "^6.22.0" + } }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.3.13", + "babel-plugin-transform-react-display-name": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "babel-plugin-transform-react-jsx-self": "^6.22.0", + "babel-plugin-transform-react-jsx-source": "^6.22.0", + "babel-preset-flow": "^6.23.0" + } }, "babel-preset-stage-0": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-do-expressions": "^6.22.0", + "babel-plugin-transform-function-bind": "^6.22.0", + "babel-preset-stage-1": "^6.24.1" + } }, "babel-preset-stage-1": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-class-constructor-call": "^6.24.1", + "babel-plugin-transform-export-extensions": "^6.22.0", + "babel-preset-stage-2": "^6.24.1" + } }, "babel-preset-stage-2": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-decorators": "^6.24.1", + "babel-preset-stage-3": "^6.24.1" + } }, "babel-preset-stage-3": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-plugin-transform-exponentiation-operator": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^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": { "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 + "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" + } }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -1074,25 +1627,50 @@ "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=" + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } }, "babel-template": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true + "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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -1106,7 +1684,13 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } }, "babelify": { "version": "8.0.0", @@ -1124,7 +1708,18 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true + "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" + } }, "backo2": { "version": "1.0.2", @@ -1149,30 +1744,53 @@ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "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" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -1204,7 +1822,9 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true + "requires": { + "tweetnacl": "^0.14.3" + } }, "beeper": { "version": "1.1.1", @@ -1216,12 +1836,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true + "dev": true, + "requires": { + "callsite": "1.0.0" + } }, "big-integer": { - "version": "1.6.36", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz", - "integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==", + "version": "1.6.38", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.38.tgz", + "integrity": "sha512-csPPkI8MBCIoFAs2D7RoX9Bn5jrHwvQ/6CMfdRzwkB5cmpw74zb6Lbc/VbT9xCWrkgdwJDxw/uLIvXGch74Lhg==", "dev": true }, "big.js": { @@ -1234,7 +1857,11 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } }, "binary-extensions": { "version": "1.12.0", @@ -1243,17 +1870,41 @@ "dev": true }, "binaryextensions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", - "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.2.tgz", + "integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==", "dev": true }, "bitsyntax": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", - "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", + "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", "dev": true, - "optional": true + "optional": true, + "requires": { + "buffer-more-ints": "~1.0.0", + "debug": "~2.6.9", + "safe-buffer": "~5.1.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, + "optional": 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, + "optional": true + } + } }, "bl": { "version": "1.1.2", @@ -1261,6 +1912,9 @@ "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", "dev": true, "optional": true, + "requires": { + "readable-stream": "~2.0.5" + }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -1274,11 +1928,19 @@ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, - "optional": true + "optional": 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" + } }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true, "optional": true @@ -1286,9 +1948,9 @@ } }, "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", "dev": true }, "block-loader": { @@ -1298,9 +1960,9 @@ "dev": true }, "bluebird": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", - "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", "dev": true }, "bn.js": { @@ -1313,77 +1975,120 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true + "dev": true, + "requires": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } }, "body-parser": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", - "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "version": "1.8.4", + "resolved": "http://registry.npmjs.org/body-parser/-/body-parser-1.8.4.tgz", + "integrity": "sha1-1JfgS8E7P5qL2McLsM3Bby4CiJg=", "dev": true, + "requires": { + "bytes": "1.0.0", + "depd": "0.4.5", + "iconv-lite": "0.4.4", + "media-typer": "0.3.0", + "on-finished": "2.1.0", + "qs": "2.2.4", + "raw-body": "1.3.0", + "type-is": "~1.5.1" + }, "dependencies": { - "bytes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", + "depd": { + "version": "0.4.5", + "resolved": "http://registry.npmjs.org/depd/-/depd-0.4.5.tgz", + "integrity": "sha1-GmZLUziLSmVz6K5ntfdnxpPKl/E=", "dev": true }, - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "ee-first": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", + "integrity": "sha1-jJshKJjYzZ8alDZlDOe+ICyen/A=", "dev": true }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "iconv-lite": { + "version": "0.4.4", + "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz", + "integrity": "sha1-6V8uQdsHNfwhZS94J6XuMuY8g6g=", "dev": true }, + "on-finished": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", + "integrity": "sha1-DFOfCSkej/rd4MiiWFD7LO3HAi0=", + "dev": true, + "requires": { + "ee-first": "1.0.5" + } + }, "qs": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", - "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "version": "2.2.4", + "resolved": "http://registry.npmjs.org/qs/-/qs-2.2.4.tgz", + "integrity": "sha1-Lp+800tUDjQhySTs0B6QqpdTGcg=", "dev": true }, "raw-body": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.0.tgz", + "integrity": "sha1-l4IwoValVI9C7vFN4i0PT2EAg9E=", "dev": true, - "dependencies": { - "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true - } + "requires": { + "bytes": "1", + "iconv-lite": "0.4.4" } } } }, "boom": { "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "resolved": "http://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true + "dev": true, + "requires": { + "hoek": "2.x.x" + } }, "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 + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "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 + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -1398,6 +2103,9 @@ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, + "requires": { + "resolve": "1.1.7" + }, "dependencies": { "resolve": { "version": "1.1.7", @@ -1408,76 +2116,130 @@ } }, "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "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 }, "browserify-aes": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "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 + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "browserify-rsa": { "version": "4.0.1", "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } }, "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 + "dev": true, + "requires": { + "pako": "~1.0.5" + } }, "browserslist": { "version": "3.2.8", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } }, "browserstack": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", "dev": true, + "requires": { + "https-proxy-agent": "1.0.0" + }, "dependencies": { "agent-base": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true + "dev": true, + "requires": { + "extend": "~3.0.0", + "semver": "~5.0.1" + } }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "https-proxy-agent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true + "dev": true, + "requires": { + "agent-base": "2", + "debug": "2", + "extend": "3" + } }, "ms": { "version": "2.0.0", @@ -1497,19 +2259,32 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.4.tgz", "integrity": "sha512-GCV599FUUxNOCFl3WgPnfc5dcqq9XTmMXoxWpqkvmk0R9TOIoqmjENNU6LY6DtgIL6WfBVbg/jmWtnM5K6UYSg==", - "dev": true + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1", + "unzipper": "^0.9.3" + } }, "buffer": { "version": "4.9.1", "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } }, "buffer-alloc-unsafe": { "version": "1.1.0", @@ -1542,9 +2317,9 @@ "dev": true }, "buffer-more-ints": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", - "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", + "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==", "dev": true }, "buffer-shims": { @@ -1570,7 +2345,25 @@ "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", "dev": true, - "optional": true + "optional": true, + "requires": { + "addressparser": "1.0.1", + "libbase64": "0.1.0", + "libmime": "3.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.6.0", + "nodemailer-shared": "1.1.0", + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + } + } }, "builtin-modules": { "version": "1.1.1", @@ -1594,19 +2387,76 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true + "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" + } }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", "dev": true, + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, "dependencies": { "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", "dev": true + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "query-string": { + "version": "5.1.1", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } } } }, @@ -1614,7 +2464,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true + "dev": true, + "requires": { + "callsites": "^0.2.0" + } }, "callsite": { "version": "1.0.0", @@ -1624,7 +2477,7 @@ }, "callsites": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, @@ -1639,6 +2492,10 @@ "resolved": "http://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" + }, "dependencies": { "camelcase": { "version": "2.1.1", @@ -1649,16 +2506,15 @@ } }, "caniuse-lite": { - "version": "1.0.30000892", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000892.tgz", - "integrity": "sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w==", + "version": "1.0.30000913", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000913.tgz", + "integrity": "sha512-PP7Ypc35XY1mNduHqweGNOp0qfNUCmaQauGOYDByvirlFjrzRyY72pBRx7jnBidOB8zclg00DAzsy2H475BouQ==", "dev": true }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "ccount": { "version": "1.0.3", @@ -1670,19 +2526,32 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } }, "chai": { "version": "3.5.0", "resolved": "http://registry.npmjs.org/chai/-/chai-3.5.0.tgz", "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true + "dev": true, + "requires": { + "assertion-error": "^1.0.1", + "deep-eql": "^0.1.3", + "type-detect": "^1.0.0" + } }, "chai-nightwatch": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.2.1.tgz", "integrity": "sha512-2lprSMi72sHq2ZGyPTYUDQNsd2O4z81SicascbI4bkU54Xzk5Ofunn2CbrExADGC7jBH2D8r66X/aSEl+/agXQ==", "dev": true, + "requires": { + "assertion-error": "1.0.0", + "deep-eql": "0.1.3" + }, "dependencies": { "assertion-error": { "version": "1.0.0", @@ -1696,13 +2565,52 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } }, "chalk": { "version": "1.1.3", "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "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" + }, + "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 + }, + "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, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "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 + } + } }, "character-entities": { "version": "1.2.2", @@ -1744,13 +2652,32 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } }, "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 + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "circular-json": { "version": "0.3.3", @@ -1763,12 +2690,21 @@ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "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" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, @@ -1776,7 +2712,10 @@ "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 + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } }, "cli-width": { "version": "2.2.0", @@ -1788,7 +2727,12 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } }, "clone": { "version": "2.1.2", @@ -1806,7 +2750,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, "clone-stats": { "version": "1.0.0", @@ -1818,7 +2765,12 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } }, "co": { "version": "4.6.0", @@ -1842,25 +2794,35 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } }, "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 + "requires": { + "color-name": "1.1.3" + } }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-support": { "version": "1.1.3", @@ -1878,24 +2840,32 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.5.0" + } }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "dev": true + "requires": { + "delayed-stream": "~1.0.0" + } }, "comma-separated-tokens": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "dev": true + "dev": true, + "requires": { + "trim": "0.0.1" + } }, "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "version": "2.15.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, "commondir": { @@ -1932,25 +2902,43 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } }, "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 + "dev": true, + "requires": { + "source-map": "^0.6.1" + } }, "connect": { "version": "3.6.6", "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -1961,16 +2949,19 @@ } }, "connect-livereload": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", - "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.4.1.tgz", + "integrity": "sha1-D4oagWvJuv+uRjfM6pF0Yv41kXo=", "dev": true }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true + "dev": true, + "requires": { + "date-now": "^0.1.4" + } }, "constants-browserify": { "version": "1.0.0", @@ -1999,7 +2990,10 @@ "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==" + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "requires": { + "safe-buffer": "~5.1.1" + } }, "cookie": { "version": "0.3.1", @@ -2017,7 +3011,11 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } }, "core-js": { "version": "2.5.7", @@ -2033,52 +3031,90 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.2.tgz", "integrity": "sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw==", - "dev": true, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.11.0", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.85.0" } }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } }, "create-hash": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } }, "create-hmac": { "version": "1.1.7", "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "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 + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "cryptiles": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "resolved": "http://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, - "optional": true + "requires": { + "boom": "2.x.x" + } }, "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 + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } }, "crypto-js": { "version": "3.1.9-1", @@ -2088,7 +3124,13 @@ "css": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==" + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } }, "css-loader": { "version": "0.9.1", @@ -2096,20 +3138,34 @@ "integrity": "sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw=", "dev": true, "optional": true, + "requires": { + "csso": "1.3.x", + "loader-utils": "~0.2.2", + "source-map": "~0.1.38" + }, "dependencies": { "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, - "optional": true + "optional": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } }, "source-map": { "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, - "optional": true + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -2124,7 +3180,10 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } }, "custom-event": { "version": "1.0.1", @@ -2134,14 +3193,19 @@ }, "d": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=" + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "^0.10.9" + } }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true + "requires": { + "assert-plus": "^1.0.0" + } }, "data-uri-to-buffer": { "version": "1.2.0", @@ -2165,17 +3229,29 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==" + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } }, "debug-fabulous": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==" + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + } }, "decamelize": { "version": "1.2.0", @@ -2192,13 +3268,19 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, "deep-eql": { "version": "0.1.3", "resolved": "http://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", "dev": true, + "requires": { + "type-detect": "0.1.1" + }, "dependencies": { "type-detect": { "version": "0.1.1", @@ -2219,6 +3301,9 @@ "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -2233,12 +3318,18 @@ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, + "requires": { + "strip-bom": "^2.0.0" + }, "dependencies": { "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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } } } }, @@ -2252,31 +3343,49 @@ "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 + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } }, "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, + "requires": { + "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -2291,6 +3400,11 @@ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", "dev": true, + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + }, "dependencies": { "esprima": { "version": "3.1.3", @@ -2300,25 +3414,10 @@ } } }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "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 + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "depd": { "version": "1.1.2", @@ -2330,7 +3429,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "destroy": { "version": "1.0.4", @@ -2342,7 +3445,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", - "dev": true + "dev": true, + "requires": { + "repeat-string": "^1.5.4" + } }, "detect-file": { "version": "1.0.0", @@ -2354,7 +3460,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "detect-newline": { "version": "2.1.0", @@ -2365,7 +3474,11 @@ "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } }, "di": { "version": "0.0.1", @@ -2383,31 +3496,107 @@ "version": "5.0.3", "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } }, "disparity": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^2.0.1", + "diff": "^1.3.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + } + } }, "doctrine": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } }, "doctrine-temporary-fork": { "version": "2.0.0-alpha-allowarrayindex", "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } }, "documentation": { "version": "5.5.0", "resolved": "http://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", "dev": true, + "requires": { + "ansi-html": "^0.0.7", + "babel-core": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-plugin-system-import-transformer": "3.1.0", + "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-preset-env": "^1.6.1", + "babel-preset-react": "^6.24.1", + "babel-preset-stage-0": "^6.24.1", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babelify": "^8.0.0", + "babylon": "^6.18.0", + "chalk": "^2.3.0", + "chokidar": "^2.0.0", + "concat-stream": "^1.6.0", + "disparity": "^2.0.0", + "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", + "get-port": "^3.2.0", + "git-url-parse": "^8.0.0", + "github-slugger": "1.2.0", + "glob": "^7.1.2", + "globals-docs": "^2.4.0", + "highlight.js": "^9.12.0", + "js-yaml": "^3.10.0", + "lodash": "^4.17.4", + "mdast-util-inject": "^1.1.0", + "micromatch": "^3.1.5", + "mime": "^1.4.1", + "module-deps-sortable": "4.0.6", + "parse-filepath": "^1.0.2", + "pify": "^3.0.0", + "read-pkg-up": "^3.0.0", + "remark": "^9.0.0", + "remark-html": "7.0.0", + "remark-reference-links": "^4.0.1", + "remark-toc": "^5.0.0", + "remote-origin-url": "0.4.0", + "shelljs": "^0.8.1", + "stream-array": "^1.1.2", + "strip-json-comments": "^2.0.1", + "tiny-lr": "^1.1.0", + "unist-builder": "^1.0.2", + "unist-util-visit": "^1.3.0", + "vfile": "^2.3.0", + "vfile-reporter": "^4.0.0", + "vfile-sort": "^2.1.0", + "vinyl": "^2.1.0", + "vinyl-fs": "^3.0.2", + "yargs": "^9.0.1" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -2415,29 +3604,52 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, "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 + "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" + } }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -2450,10 +3662,16 @@ "resolved": "http://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.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -2469,17 +3687,23 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "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.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -2489,7 +3713,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } }, "source-map": { "version": "0.5.7", @@ -2501,31 +3730,51 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "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 - }, - "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.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.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, "dependencies": { "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } } } } @@ -2535,7 +3784,13 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } }, "domain-browser": { "version": "1.2.0", @@ -2560,7 +3815,10 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } }, "duplexer3": { "version": "0.1.4", @@ -2572,18 +3830,37 @@ "version": "3.6.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", "dev": true }, "ee-first": { @@ -2599,16 +3876,25 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.79", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.79.tgz", - "integrity": "sha512-LQdY3j4PxuUl6xfxiFruTSlCniTrTrzAd8/HfsLEMi0PUpaQ0Iy+Pr4N4VllDYjs0Hyu2lkTbvzqlG+PX9NsNw==", + "version": "1.3.87", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.87.tgz", + "integrity": "sha512-EV5FZ68Hu+n9fHVhOc9AcG3Lvf+E1YqR36ulJUpwaQTkf4LwdvBqmGIazaIrt4kt6J8Gw3Kv7r9F+PQjAkjWeA==", "dev": true }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } }, "emoji-regex": { "version": "6.1.1", @@ -2632,19 +3918,34 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true + "dev": true, + "requires": { + "once": "^1.4.0" + } }, "engine.io": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", + "resolved": "http://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "uws": "~9.14.0", + "ws": "~3.3.1" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -2656,15 +3957,31 @@ }, "engine.io-client": { "version": "3.1.6", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -2675,16 +3992,29 @@ } }, "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } }, "enhanced-resolve": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.7" + } }, "ent": { "version": "2.2.0", @@ -2696,24 +4026,39 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true + "dev": true, + "requires": { + "prr": "~1.0.1" + } }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true + "dev": true, + "requires": { + "string-template": "~0.2.1", + "xtend": "~4.0.0" + } }, "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 + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } }, "es5-ext": { "version": "0.10.46", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==" + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } }, "es5-shim": { "version": "4.5.12", @@ -2724,13 +4069,26 @@ "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=" + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } }, "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 + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-promise": { "version": "4.2.5", @@ -2740,25 +4098,45 @@ }, "es6-promisify": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=" + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "es6-weak-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=" + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } }, "escape-html": { "version": "1.0.3", @@ -2777,6 +4155,13 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + }, "dependencies": { "esprima": { "version": "2.7.3", @@ -2792,10 +4177,13 @@ }, "source-map": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, - "optional": true + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -2803,19 +4191,71 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint": { "version": "4.19.1", "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "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", + "table": "4.0.2", + "text-table": "~0.2.0" + }, "dependencies": { "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true + "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" + } }, "ansi-regex": { "version": "3.0.0", @@ -2823,41 +4263,62 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "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, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "globals": { - "version": "11.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", - "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", + "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", + "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 }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -2872,12 +4333,19 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -2892,18 +4360,29 @@ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^1.0.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "ms": { "version": "2.0.0", @@ -2915,13 +4394,19 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } }, "pkg-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true + "dev": true, + "requires": { + "find-up": "^1.0.0" + } } } }, @@ -2930,18 +4415,39 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", "dev": true, + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "load-json-file": { "version": "2.0.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } }, "ms": { "version": "2.0.0", @@ -2953,17 +4459,23 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true + "dev": true, + "requires": { + "pify": "^2.0.0" + } }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -2971,13 +4483,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } } } }, @@ -2986,6 +4507,12 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "5.3.0" + }, "dependencies": { "semver": { "version": "5.3.0", @@ -3008,10 +4535,13 @@ "dev": true }, "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 + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint-visitor-keys": { "version": "1.0.0", @@ -3021,33 +4551,40 @@ }, "espree": { "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "resolved": "http://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } }, "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 + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true + "requires": { + "estraverse": "^4.1.0" + } }, "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "estree-walker": { "version": "0.3.1", @@ -3062,21 +4599,34 @@ "dev": true }, "etag": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=" + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "event-stream": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.6.tgz", - "integrity": "sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==", - "dev": true + "version": "3.3.4", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "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" + } }, "eventemitter3": { "version": "3.1.0", @@ -3094,19 +4644,37 @@ "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 + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.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" + } }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, "dependencies": { "array-slice": { "version": "0.2.3", @@ -3124,7 +4692,10 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } } } }, @@ -3133,24 +4704,42 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "ms": { "version": "2.0.0", @@ -3162,9 +4751,13 @@ }, "expand-range": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + }, "dependencies": { "is-number": { "version": "0.1.1", @@ -3184,25 +4777,34 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, + "requires": { + "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 + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -3211,13 +4813,10 @@ "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true - } + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" } }, "extglob": { @@ -3225,44 +4824,70 @@ "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.0", + "snapdragon": "^0.8.1", + "to-regex": "^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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "faker": { "version": "3.1.0", @@ -3271,22 +4896,26 @@ "dev": true }, "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true + "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, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } }, "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 + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", @@ -3298,19 +4927,29 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } }, "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 + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } }, "file-loader": { "version": "0.8.5", @@ -3318,13 +4957,22 @@ "integrity": "sha1-knXQMf54DyfUf19K8CvUNxPMFRs=", "dev": true, "optional": true, + "requires": { + "loader-utils": "~0.2.5" + }, "dependencies": { "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, - "optional": true + "optional": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } } } }, @@ -3344,25 +4992,42 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } }, "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true + "dev": true, + "requires": { + "is-object": "~1.0.1", + "merge-descriptors": "~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.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 + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -3371,12 +5036,24 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -3390,25 +5067,42 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.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 + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, "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" + }, "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 + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } } } }, @@ -3416,7 +5110,14 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true + "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" + } }, "flagged-respawn": { "version": "1.0.0", @@ -3425,34 +5126,55 @@ "dev": true }, "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true - }, - "flatmap-stream": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.1.tgz", - "integrity": "sha512-lAq4tLbm3sidmdCN8G3ExaxH7cUCtP5mgDvrYowsx84dcYkJJ4I28N7gkxA6+YlSXzaGLJYIDEi9WGfXzMiXdw==", - "dev": true + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "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" + }, + "dependencies": { + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + } + } }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } }, "follow-redirects": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz", - "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==", + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", "dev": true, + "requires": { + "debug": "=3.1.0" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -3472,7 +5194,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true + "dev": true, + "requires": { + "for-in": "^1.0.1" + } }, "foreachasync": { "version": "3.0.0", @@ -3483,8 +5208,7 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "fork-stream": { "version": "0.0.4", @@ -3493,29 +5217,28 @@ "dev": true }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, - "dependencies": { - "combined-stream": { - "version": "1.0.6", - "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true - } + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" } }, "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 + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } }, "fresh": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, "from": { @@ -3528,25 +5251,32 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } }, "fs-access": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true - }, - "fs-copy-file-sync": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz", - "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==", - "dev": true + "dev": true, + "requires": { + "null-check": "^1.0.0" + } }, "fs-extra": { "version": "0.6.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", + "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, + "requires": { + "jsonfile": "~1.0.1", + "mkdirp": "0.3.x", + "ncp": "~0.4.2", + "rimraf": "~2.2.0" + }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -3560,13 +5290,22 @@ "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } }, "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, + "requires": { + "fs-extra": "~0.6.1", + "mkdirp": "~0.3.5", + "walk": "^2.3.9" + }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -3588,6 +5327,10 @@ "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", "dev": true, "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, "dependencies": { "abbrev": { "version": "1.1.1", @@ -3610,7 +5353,11 @@ "version": "1.1.4", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } }, "balanced-match": { "version": "1.0.0", @@ -3620,7 +5367,11 @@ "brace-expansion": { "version": "1.1.11", "bundled": true, - "dev": true + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "chownr": { "version": "1.0.1", @@ -3653,7 +5404,10 @@ "version": "2.6.9", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ms": "2.0.0" + } }, "deep-extend": { "version": "0.5.1", @@ -3677,7 +5431,10 @@ "version": "1.2.5", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minipass": "^2.2.1" + } }, "fs.realpath": { "version": "1.0.0", @@ -3689,13 +5446,31 @@ "version": "2.7.4", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } }, "glob": { "version": "7.1.2", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-unicode": { "version": "2.0.1", @@ -3707,19 +5482,29 @@ "version": "0.4.21", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } }, "ignore-walk": { "version": "3.0.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } }, "inflight": { "version": "1.0.6", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", @@ -3735,7 +5520,10 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "isarray": { "version": "1.0.0", @@ -3746,7 +5534,10 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "0.0.8", @@ -3756,18 +5547,28 @@ "minipass": { "version": "2.2.4", "bundled": true, - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } }, "minizlib": { "version": "1.1.0", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minipass": "^2.2.1" + } }, "mkdirp": { "version": "0.5.1", "bundled": true, - "dev": true + "dev": true, + "requires": { + "minimist": "0.0.8" + } }, "ms": { "version": "2.0.0", @@ -3779,19 +5580,40 @@ "version": "2.2.0", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } }, "node-pre-gyp": { "version": "0.10.0", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } }, "nopt": { "version": "4.0.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } }, "npm-bundled": { "version": "1.0.3", @@ -3803,13 +5625,23 @@ "version": "1.1.10", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } }, "npmlog": { "version": "4.1.2", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } }, "number-is-nan": { "version": "1.0.1", @@ -3825,7 +5657,10 @@ "once": { "version": "1.4.0", "bundled": true, - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } }, "os-homedir": { "version": "1.0.2", @@ -3843,7 +5678,11 @@ "version": "0.1.5", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "path-is-absolute": { "version": "1.0.1", @@ -3862,6 +5701,12 @@ "bundled": true, "dev": true, "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -3875,13 +5720,25 @@ "version": "2.3.6", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, "rimraf": { "version": "2.6.2", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "glob": "^7.0.5" + } }, "safe-buffer": { "version": "5.1.1", @@ -3918,21 +5775,32 @@ "dev": true, "optional": true }, - "string_decoder": { - "version": "1.1.1", + "string-width": { + "version": "1.0.2", "bundled": true, "dev": true, - "optional": true + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, - "string-width": { - "version": "1.0.2", + "string_decoder": { + "version": "1.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, "strip-ansi": { "version": "3.0.1", "bundled": true, - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, "strip-json-comments": { "version": "2.0.1", @@ -3944,7 +5812,16 @@ "version": "4.4.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } }, "util-deprecate": { "version": "1.0.2", @@ -3956,7 +5833,10 @@ "version": "1.1.2", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "string-width": "^1.0.2" + } }, "wrappy": { "version": "1.0.2", @@ -3974,13 +5854,23 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } }, "ftp": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", "dev": true, + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -3992,11 +5882,17 @@ "version": "1.1.14", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -4019,14 +5915,18 @@ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", "dev": true, - "optional": true + "requires": { + "is-property": "^1.0.2" + } }, "generate-object-property": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, - "optional": true + "requires": { + "is-property": "^1.0.0" + } }, "get-caller-file": { "version": "1.0.3", @@ -4063,12 +5963,23 @@ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", "dev": true, + "requires": { + "data-uri-to-buffer": "1", + "debug": "2", + "extend": "3", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "2" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -4088,43 +5999,71 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true + "requires": { + "assert-plus": "^1.0.0" + } }, "git-up": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", - "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.1.0.tgz", + "integrity": "sha512-MJgwfcSd9qxgDyEYpRU/CDxNpUadrK80JHuEQDG4Urn0m7tpSOgCBrtiSIa9S9KH8Tbuo/TN8SSQmJBvsw1HkA==", + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "parse-url": "^3.0.2" + } }, "git-url-parse": { "version": "8.3.1", "resolved": "http://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true + "dev": true, + "requires": { + "git-up": "^2.0.0", + "parse-domain": "^2.0.0" + } }, "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 + "dev": true, + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + } }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true + "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-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, "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 + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } }, "is-extglob": { "version": "1.0.0", @@ -4136,7 +6075,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } } } }, @@ -4145,12 +6087,19 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } } } }, @@ -4158,25 +6107,57 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true + "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" + } }, "glob-watcher": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.1.tgz", - "integrity": "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g==", - "dev": true + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "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", + "object.defaults": "^1.1.0" + } }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } }, "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 + "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" + } }, "globals": { "version": "9.18.0", @@ -4190,48 +6171,69 @@ "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", "dev": true }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "glogg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", - "dev": true + "dev": true, + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" + }, + "grunt-coveralls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-coveralls/-/grunt-coveralls-2.0.0.tgz", + "integrity": "sha1-2WkGQB8xIrW30ojr2XP2r6OFuiQ=", + "requires": { + "coveralls": "^3.0.0" + } }, "gulp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", "dev": true, + "requires": { + "glob-watcher": "^5.0.0", + "gulp-cli": "^2.0.0", + "undertaker": "^1.0.0", + "vinyl-fs": "^3.0.0" + }, "dependencies": { "camelcase": { "version": "3.0.0", @@ -4243,47 +6245,92 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "gulp-cli": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", - "dev": true + "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.1.0", + "isobject": "^3.0.1", + "liftoff": "^2.5.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.0.1", + "yargs": "^7.1.0" + } }, "load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true + "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" + } }, "os-locale": { "version": "1.4.0", "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true + "dev": true, + "requires": { + "lcid": "^1.0.0" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "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 + "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 + "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", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -4291,19 +6338,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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 + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } }, "which-module": { "version": "1.0.0", @@ -4315,13 +6374,31 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true + "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.0" + } }, "yargs-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } } } }, @@ -4330,18 +6407,50 @@ "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", "dev": true, + "requires": { + "babel-core": "^6.23.1", + "object-assign": "^4.0.1", + "plugin-error": "^1.0.1", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + }, "dependencies": { "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 + "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" + } }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -4368,6 +6477,11 @@ "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" + }, "dependencies": { "ansi-regex": { "version": "0.2.1", @@ -4385,7 +6499,14 @@ "version": "0.5.1", "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true + "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", @@ -4398,12 +6519,26 @@ "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", + "resolved": "http://registry.npmjs.org/through2/-/through2-0.5.1.tgz", "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } } } }, @@ -4411,7 +6546,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^0.2.0" + } }, "isarray": { "version": "0.0.1", @@ -4435,11 +6573,17 @@ "version": "1.0.34", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, @@ -4447,7 +6591,10 @@ "version": "0.3.0", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^0.2.1" + } }, "supports-color": { "version": "0.2.0", @@ -4457,15 +6604,22 @@ }, "through2": { "version": "0.4.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "resolved": "http://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~2.1.1" + }, "dependencies": { "xtend": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true + "dev": true, + "requires": { + "object-keys": "~0.4.0" + } } } }, @@ -4473,7 +6627,10 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true + "dev": true, + "requires": { + "clone-stats": "~0.0.1" + } }, "xtend": { "version": "3.0.0", @@ -4487,89 +6644,296 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + } }, - "gulp-connect": { - "version": "5.5.0", - "resolved": "http://registry.npmjs.org/gulp-connect/-/gulp-connect-5.5.0.tgz", - "integrity": "sha512-oRBLjw/4EVaZb8g8OcxOVdGD8ZXYrRiWKcNxlrGjxb/6Cp0GDdqw7ieX7D8xJrQS7sbXT+G94u63pMJF3MMjQA==", + "gulp-coveralls": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/gulp-coveralls/-/gulp-coveralls-0.1.4.tgz", + "integrity": "sha1-L2IKyN9i0LhrS73mTaNnzEGhkMk=", "dev": true, + "requires": { + "coveralls": "^2.11.2", + "gulp-util": "^3.0.4", + "through2": "^1.1.1" + }, "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", "dev": true }, - "qs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", - "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true }, - "tiny-lr": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", - "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "coveralls": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", + "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "dev": true, + "requires": { + "js-yaml": "3.6.1", + "lcov-parse": "0.0.10", + "log-driver": "1.2.5", + "minimist": "1.2.0", + "request": "2.79.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true - } - } - }, - "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 - }, - "gulp-footer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gulp-footer/-/gulp-footer-1.1.2.tgz", - "integrity": "sha512-G6Z8DNNeIhq1KU++7kZnbuwbvCubkUMOVADOt+0qTHSIqjy2OPo1W4bu4n1aE9JGZncuRTvVQrYecGx2uazlpg==", - "dev": true, - "dependencies": { - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "http://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "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=", + "js-yaml": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^2.6.0" + } + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", "dev": true }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "request": { + "version": "2.79.0", + "resolved": "http://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "qs": "~6.3.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1", + "uuid": "^3.0.0" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "requires": { + "readable-stream": ">=1.1.13-1 <1.2.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "http://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "^1.4.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", "dev": true } } }, + "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, + "requires": { + "eslint": "^4.0.0", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.0" + } + }, + "gulp-footer": { + "version": "github:prebid/gulp-footer#ff2b46e6376c7f04900357ff9f7b30f219fe5f8a", + "from": "github:prebid/gulp-footer#master", + "dev": true, + "requires": { + "event-stream": "3.3.4", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.6.2" + }, + "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.0" + } + }, + "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.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "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.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.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.0.0" + } + } + } + }, "gulp-header": { "version": "1.8.12", "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, + "requires": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -4581,13 +6945,20 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } }, "lodash.templatesettings": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0" + } } } }, @@ -4595,13 +6966,21 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true + "dev": true, + "requires": { + "gulp-match": "^1.0.3", + "ternary-stream": "^2.0.1", + "through2": "^2.0.1" + } }, "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, + "requires": { + "through2": "^0.6.3" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -4613,19 +6992,29 @@ "version": "1.0.34", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "through2": { "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "resolved": "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } } } }, @@ -4633,13 +7022,22 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true + "dev": true, + "requires": { + "minimatch": "^3.0.3" + } }, "gulp-optimize-js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", - "dev": true + "dev": true, + "requires": { + "gulp-util": "^3.0.7", + "lodash": "^4.16.2", + "optimize-js": "^1.0.0", + "through2": "^2.0.1" + } }, "gulp-rename": { "version": "1.4.0", @@ -4648,47 +7046,61 @@ "dev": true }, "gulp-replace": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.4.0.tgz", - "integrity": "sha1-4ivJwD6dBRsyiBzFib0+jE5UFoo=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", + "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", "dev": true, - "dependencies": { - "event-stream": { - "version": "3.0.20", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", - "integrity": "sha1-A4u7LqnqkDhbJvvBhU0LU58qvqM=", - "dev": true - }, - "split": { - "version": "0.2.10", - "resolved": "http://registry.npmjs.org/split/-/split-0.2.10.tgz", - "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "dev": true - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true - } + "requires": { + "istextorbinary": "2.2.1", + "readable-stream": "^2.0.1", + "replacestream": "^4.0.0" } }, "gulp-shell": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true + "dev": true, + "requires": { + "async": "^1.5.0", + "gulp-util": "^3.0.7", + "lodash": "^4.0.0", + "through2": "^2.0.0" + } }, "gulp-sourcemaps": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=" + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + } }, "gulp-uglify": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.1.tgz", "integrity": "sha512-KVffbGY9d4Wv90bW/B1KZJyunLMyfHTBbilpDvmcrj5Go0/a1G3uVpt+1gRBWSw/11dqR3coJ1oWNTt1AiXuWQ==", "dev": true, + "requires": { + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash": "^4.13.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + }, "dependencies": { "commander": { "version": "2.17.1", @@ -4700,7 +7112,11 @@ "version": "3.4.9", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", - "dev": true + "dev": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + } } } }, @@ -4709,6 +7125,26 @@ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "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", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, "dependencies": { "clone": { "version": "1.0.4", @@ -4738,31 +7174,48 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true + "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.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } }, "object-assign": { "version": "3.0.0", @@ -4780,6 +7233,193 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-webserver": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/gulp-webserver/-/gulp-webserver-0.9.1.tgz", + "integrity": "sha1-4JmSFl2XxYZWFtZCoWAVKbA2cGQ=", + "dev": true, + "requires": { + "connect": "^3.0.1", + "connect-livereload": "^0.4.0", + "gulp-util": "^2.2.19", + "isarray": "0.0.1", + "node.extend": "^1.0.10", + "open": "^0.0.5", + "proxy-middleware": "^0.5.0", + "serve-index": "^1.1.4", + "serve-static": "^1.3.0", + "through2": "^0.5.1", + "tiny-lr": "0.1.4", + "watch": "^0.11.0" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "http://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 + }, + "chalk": { + "version": "0.5.1", + "resolved": "http://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 + }, + "debug": { + "version": "0.8.1", + "resolved": "http://registry.npmjs.org/debug/-/debug-0.8.1.tgz", + "integrity": "sha1-IP9NJvXkIstoobrLu2EDmtjBwTA=", + "dev": true + }, + "faye-websocket": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.7.3.tgz", + "integrity": "sha1-zEB0x/Sk39A69U3WXDVLE1EyzhE=", + "dev": true, + "requires": { + "websocket-driver": ">=0.3.6" + } + }, + "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" + } + }, + "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" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimist": { + "version": "0.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "dev": true + }, + "qs": { + "version": "2.2.5", + "resolved": "http://registry.npmjs.org/qs/-/qs-2.2.5.tgz", + "integrity": "sha1-EIirr53MCuWuRbcJ5sa1iIsjkjw=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "http://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" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "^0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + }, + "tiny-lr": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.1.4.tgz", + "integrity": "sha1-bkHX5n39CHjl4LN+N6BtZ+MJ/00=", + "dev": true, + "requires": { + "body-parser": "~1.8.0", + "debug": "~0.8.1", + "faye-websocket": "~0.7.2", + "parseurl": "~1.3.0", + "qs": "~2.2.3" + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true, + "requires": { + "clone-stats": "~0.0.1" + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", "dev": true } } @@ -4788,19 +7428,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true + "dev": true, + "requires": { + "glogg": "^1.0.0" + } }, "handlebars": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", "dev": true, + "requires": { + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, "dependencies": { "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.10" + } }, "commander": { "version": "2.17.1", @@ -4814,27 +7466,38 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "dev": true, - "optional": true + "optional": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + } } } }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", - "dev": true, + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, "dependencies": { "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", + "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } } } }, @@ -4842,19 +7505,34 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } }, "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-3.0.0.tgz", + "integrity": "sha1-Ngd+8dFfMzSEqn+neihgbxxlWzc=", + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + } + } }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, + "requires": { + "isarray": "2.0.1" + }, "dependencies": { "isarray": { "version": "2.0.1", @@ -4873,14 +7551,16 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-gulplog": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "has-symbol-support-x": { "version": "1.4.2", @@ -4898,25 +7578,40 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } }, "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, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -4924,44 +7619,73 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "hash.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", - "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "dev": true + "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.0.1", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.1.tgz", - "integrity": "sha512-s/ggaNehYVqmLgTXEv12Lbb72bsOD2r5DhAqPgtDdaI/YFNXVzz0zHFVJnhjIjn7Nak8GbL4nzT2q0RA5div+A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.2.tgz", + "integrity": "sha512-4MEtyofNi3ZunPFrp9NpTQdNPN24xvLX3M+Lr/RGgPX6TLi+wR4/DqeoyQ7lwWcfUp4aevdt4RR0r7ZQPFbHxw==", "dev": true }, "hast-util-sanitize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.2.0.tgz", - "integrity": "sha512-VwCTqjt6fbMGacxGB1FKV5sBJaVVkyCGVMDwb4nnqvCW2lkqscA2GEpOyBx4ZWRXty1eAZF58MHBrllEoQEoBg==", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.2.1.tgz", + "integrity": "sha512-bRyZ316tTETfxkpM0De0Fk5slEtR5hvkzDGbHpEAjZRmfQyT3xMTzMk0/gGWlkqsfafFCaPNbrtPdZBPMK8X8A==", + "dev": true, + "requires": { + "xtend": "^4.0.1" + } }, "hast-util-to-html": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", - "dev": true + "dev": true, + "requires": { + "ccount": "^1.0.0", + "comma-separated-tokens": "^1.0.1", + "hast-util-is-element": "^1.0.0", + "hast-util-whitespace": "^1.0.0", + "html-void-elements": "^1.0.0", + "kebab-case": "^1.0.0", + "property-information": "^3.1.0", + "space-separated-tokens": "^1.0.0", + "stringify-entities": "^1.0.1", + "unist-util-is": "^2.0.0", + "xtend": "^4.0.1" + } }, "hast-util-whitespace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.1.tgz", - "integrity": "sha512-Mfx2ZnmVMTAopZ8as42nKrNt650tCZYhy/MPeO1Imdg/cmCWK6GUSnFrrE3ezGjVifn7x5zMfu8jrjwIGyImSw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.2.tgz", + "integrity": "sha512-4JT8B0HKPHBMFZdDQzexjxwhKx9TrpV/+uelvmqlPu8RqqDrnNIEHDtDZCmgE+4YmcFAtKVPLmnY3dQGRaN53A==", "dev": true }, "hawk": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "resolved": "http://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, - "optional": true + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } }, "he": { "version": "1.1.1", @@ -4970,9 +7694,9 @@ "dev": true }, "highlight.js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.0.tgz", - "integrity": "sha512-2B90kcNnErqRTmzdZw6IPLEC9CdsiIMhj+r8L3LJKRCgtEJ+LY5yzWuQCVnADTI0wwocQinFzaaL/JjTQNqI/g==", + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz", + "integrity": "sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==", "dev": true }, "hipchat-notifier": { @@ -4980,17 +7704,26 @@ "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", "dev": true, - "optional": true + "optional": true, + "requires": { + "lodash": "^4.0.0", + "request": "^2.0.0" + } }, "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 + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } }, "hoek": { "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "resolved": "http://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, @@ -4998,13 +7731,20 @@ "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 + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } }, "homedir-polyfill": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } }, "hosted-git-info": { "version": "2.7.1", @@ -5025,34 +7765,60 @@ "dev": true }, "http-errors": { - "version": "1.3.1", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "dev": true + "version": "1.6.3", + "resolved": "http://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" + }, + "dependencies": { + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + } + } }, "http-parser-js": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", - "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", + "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", "dev": true }, "http-proxy": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } }, "http-proxy-agent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -5066,13 +7832,21 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } }, "httpntlm": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true + "dev": true, + "requires": { + "httpreq": ">=0.4.22", + "underscore": "~1.7.0" + } }, "httpreq": { "version": "0.4.24", @@ -5090,13 +7864,20 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "dev": true + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } }, "iconv-lite": { - "version": "0.4.13", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ieee754": { "version": "1.1.12", @@ -5126,7 +7907,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "indexof": { "version": "0.0.1", @@ -5145,7 +7929,11 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", @@ -5163,6 +7951,22 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "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", + "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" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -5170,17 +7974,16 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -5192,19 +7995,20 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "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 - }, - "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -5218,13 +8022,20 @@ "version": "3.1.0", "resolved": "http://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true + "dev": true, + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } }, "invert-kv": { "version": "1.0.0", @@ -5238,23 +8049,39 @@ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, + "is": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", + "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", + "dev": true + }, "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 + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.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.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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5274,7 +8101,11 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -5286,7 +8117,10 @@ "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 + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } }, "is-buffer": { "version": "1.1.6", @@ -5298,19 +8132,28 @@ "version": "1.0.0", "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5325,6 +8168,11 @@ "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", @@ -5350,7 +8198,10 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } }, "is-extendable": { "version": "0.1.1", @@ -5368,19 +8219,28 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } }, "is-hexadecimal": { "version": "1.0.2", @@ -5392,15 +8252,20 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true, - "optional": true + "dev": true }, "is-my-json-valid": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", "dev": true, - "optional": true + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } }, "is-negated-glob": { "version": "1.0.0", @@ -5413,12 +8278,18 @@ "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": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5428,24 +8299,6 @@ "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", "dev": true }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -5456,7 +8309,10 @@ "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 + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "is-posix-bracket": { "version": "0.1.1", @@ -5485,7 +8341,10 @@ "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 + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } }, "is-resolvable": { "version": "1.1.0", @@ -5503,7 +8362,10 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", - "dev": true + "dev": true, + "requires": { + "protocols": "^1.1.0" + } }, "is-stream": { "version": "1.1.0", @@ -5514,14 +8376,16 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "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 + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } }, "is-utf8": { "version": "0.2.1", @@ -5562,7 +8426,10 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } }, "isexe": { "version": "2.0.0", @@ -5579,14 +8446,29 @@ "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 + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, "dependencies": { "esprima": { "version": "2.7.3", @@ -5598,7 +8480,14 @@ "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-flag": { "version": "1.0.0", @@ -5616,7 +8505,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } } } }, @@ -5625,12 +8517,28 @@ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", "dev": true, + "requires": { + "async": "^2.1.4", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + }, "dependencies": { "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.10" + } } } }, @@ -5638,7 +8546,13 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" + } }, "istanbul-lib-coverage": { "version": "1.2.1", @@ -5650,19 +8564,37 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", - "dev": true + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } }, "istanbul-lib-instrument": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } }, "istanbul-lib-report": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, "dependencies": { "has-flag": { "version": "1.0.0", @@ -5674,7 +8606,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } } } }, @@ -5683,12 +8618,22 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + }, "dependencies": { "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.5" + } }, "source-map": { "version": "0.5.7", @@ -5702,25 +8647,41 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", - "dev": true + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } }, "istextorbinary": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", - "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", - "dev": true + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "dev": true, + "requires": { + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" + } }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } }, "jade": { "version": "0.26.3", "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, "dependencies": { "commander": { "version": "0.6.1", @@ -5746,13 +8707,15 @@ "version": "3.12.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsencrypt": { "version": "3.0.0-rc.1", @@ -5761,7 +8724,7 @@ }, "jsesc": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, @@ -5786,20 +8749,21 @@ "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "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 + "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==" }, "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -5810,8 +8774,7 @@ "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 + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { "version": "0.5.1", @@ -5841,20 +8804,18 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true, - "optional": 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 }, "jsprim": { "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.2.3", + "verror": "1.10.0" + } }, "just-clone": { "version": "1.0.2", @@ -5878,12 +8839,53 @@ "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", "integrity": "sha512-rECezBeY7mjzGUWhFlB7CvPHgkHJLXyUmWg+6vHCEsdWNUTnmiS6jRrIMcJEWgU2DUGZzGWG0bTRVky8fsDTOA==", "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.4", + "log4js": "^2.5.3", + "mime": "^1.3.4", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.0.4", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.2.1" + }, "dependencies": { "body-parser": { "version": "1.18.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } }, "bytes": { "version": "3.0.0", @@ -5895,19 +8897,19 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ms": { "version": "2.0.0", @@ -5915,29 +8917,36 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.5" + } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } } } }, @@ -5945,13 +8954,21 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true + "dev": true, + "requires": { + "babel-core": "^6.0.0" + } }, "karma-browserstack-launcher": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", - "dev": true + "dev": true, + "requires": { + "browserstack": "1.5.0", + "browserstacktunnel-wrapper": "~2.0.1", + "q": "~1.5.0" + } }, "karma-chai": { "version": "0.1.0", @@ -5963,19 +8980,30 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true + "dev": true, + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } }, "karma-coverage-istanbul-reporter": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", - "dev": true + "dev": true, + "requires": { + "istanbul-api": "^1.3.1", + "minimatch": "^3.0.4" + } }, "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 + "dev": true, + "requires": { + "es5-shim": "^4.0.5" + } }, "karma-firefox-launcher": { "version": "1.1.0", @@ -5987,20 +9015,18 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.6.1" + } }, "karma-mocha": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", "dev": true, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } + "requires": { + "minimist": "1.2.0" } }, "karma-mocha-reporter": { @@ -6008,6 +9034,11 @@ "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", "dev": true, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "strip-ansi": "^4.0.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -6015,29 +9046,25 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.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 - }, - "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -6075,25 +9102,42 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + } }, "karma-spec-reporter": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true + "dev": true, + "requires": { + "colors": "^1.1.2" + } }, "karma-webpack": { "version": "2.0.13", "resolved": "http://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", "dev": true, + "requires": { + "async": "^2.0.0", + "babel-runtime": "^6.0.0", + "loader-utils": "^1.0.0", + "lodash": "^4.0.0", + "source-map": "^0.5.6", + "webpack-dev-middleware": "^1.12.0" + }, "dependencies": { "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.10" + } }, "source-map": { "version": "0.5.7", @@ -6113,7 +9157,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } }, "kind-of": { "version": "6.0.2", @@ -6125,7 +9172,11 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } }, "lazy-cache": { "version": "1.0.4", @@ -6137,31 +9188,43 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } }, "lcov-parse": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=" }, "lead": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } }, "libbase64": { "version": "0.1.0", @@ -6174,6 +9237,11 @@ "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, "dependencies": { "iconv-lite": { "version": "0.4.15", @@ -6193,7 +9261,17 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.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" + } }, "listenercount": { "version": "1.0.1", @@ -6202,16 +9280,22 @@ "dev": true }, "livereload-js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", - "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", + "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 }, "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } }, "loader-runner": { "version": "2.3.1", @@ -6223,19 +9307,34 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } }, "localtunnel": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.1.tgz", "integrity": "sha512-HWrhOslklDvxgOGFLxi6fQVnvpl6XdX4sPscfqMZkzi3gtt9V7LKBWYvNUcpHSVvjwCQ6xzXacVvICNbNcyPnQ==", "dev": true, + "requires": { + "axios": "0.17.1", + "debug": "2.6.9", + "openurl": "1.1.1", + "yargs": "6.6.0" + }, "dependencies": { "axios": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", - "dev": true + "dev": true, + "requires": { + "follow-redirects": "^1.2.5", + "is-buffer": "^1.1.5" + } }, "camelcase": { "version": "3.0.0", @@ -6247,19 +9346,33 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true + "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" + } }, "ms": { "version": "2.0.0", @@ -6271,29 +9384,43 @@ "version": "1.4.0", "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true + "dev": true, + "requires": { + "lcid": "^1.0.0" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "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 + "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 + "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", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -6301,19 +9428,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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 + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } }, "which-module": { "version": "1.0.0", @@ -6325,13 +9464,31 @@ "version": "6.6.0", "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "dev": true + "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": "^4.2.0" + } }, "yargs-parser": { "version": "4.2.1", "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } } } }, @@ -6339,7 +9496,11 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "lodash": { "version": "4.17.11", @@ -6364,12 +9525,21 @@ "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + }, "dependencies": { "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } } } }, @@ -6378,12 +9548,25 @@ "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", "dev": true, + "requires": { + "lodash._arraycopy": "^3.0.0", + "lodash._arrayeach": "^3.0.0", + "lodash._baseassign": "^3.0.0", + "lodash._basefor": "^3.0.0", + "lodash.isarray": "^3.0.0", + "lodash.keys": "^3.0.0" + }, "dependencies": { "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } } } }, @@ -6421,7 +9604,10 @@ "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 + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1" + } }, "lodash._escapestringchar": { "version": "2.4.1", @@ -6481,7 +9667,11 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash._root": { "version": "3.0.1", @@ -6493,7 +9683,10 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } }, "lodash.assign": { "version": "4.2.0", @@ -6505,7 +9698,12 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true + "dev": true, + "requires": { + "lodash._baseclone": "^3.0.0", + "lodash._bindcallback": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } }, "lodash.debounce": { "version": "4.0.8", @@ -6517,7 +9715,11 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash.defaultsdeep": { "version": "4.6.0", @@ -6529,7 +9731,12 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true + "dev": true, + "requires": { + "lodash._escapehtmlchar": "~2.4.1", + "lodash._reunescapedhtml": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash.get": { "version": "4.4.2", @@ -6553,13 +9760,21 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } }, "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 + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } }, "lodash.merge": { "version": "4.6.1", @@ -6583,49 +9798,60 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true + "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 + "dev": true, + "requires": { + "lodash._reinterpolate": "~2.4.1", + "lodash.escape": "~2.4.1" + } }, "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 + "dev": true, + "requires": { + "lodash.keys": "~2.4.1" + } }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, + "requires": { + "chalk": "^2.0.1" + }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "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 + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } } } }, @@ -6634,11 +9860,26 @@ "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", "integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==", "dev": true, + "requires": { + "amqplib": "^0.5.2", + "axios": "^0.15.3", + "circular-json": "^0.5.4", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "hipchat-notifier": "^1.1.0", + "loggly": "^1.1.0", + "mailgun-js": "^0.18.0", + "nodemailer": "^2.5.0", + "redis": "^2.7.1", + "semver": "^5.5.0", + "slack-node": "~0.2.0", + "streamroller": "0.7.0" + }, "dependencies": { "circular-json": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.7.tgz", - "integrity": "sha512-/pXoV1JA847qRKPrHbBK6YIBGFF8GOP4wzSgUOA7q0ew0vAv0iJswP+2/nZQ9uzA3Azi7eTrg9L2yzXc/7ZMIA==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true } } @@ -6649,6 +9890,11 @@ "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", "dev": true, "optional": true, + "requires": { + "json-stringify-safe": "5.0.x", + "request": "2.75.x", + "timespan": "2.3.x" + }, "dependencies": { "assert-plus": { "version": "0.2.0", @@ -6673,24 +9919,40 @@ }, "form-data": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", "dev": true, - "optional": true + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + } }, "har-validator": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", "dev": true, - "optional": true + "optional": true, + "requires": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + } }, "http-signature": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, - "optional": true + "optional": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } }, "node-uuid": { "version": "1.4.8", @@ -6706,6 +9968,13 @@ "dev": true, "optional": true }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, "qs": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", @@ -6718,14 +9987,40 @@ "resolved": "http://registry.npmjs.org/request/-/request-2.75.0.tgz", "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", "dev": true, - "optional": true + "optional": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "bl": "~1.1.2", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.0.0", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "node-uuid": "~1.4.7", + "oauth-sign": "~0.8.1", + "qs": "~6.2.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1" + } }, "tough-cookie": { "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "resolved": "http://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, - "optional": true + "optional": true, + "requires": { + "punycode": "^1.4.1" + } }, "tunnel-agent": { "version": "0.4.3", @@ -6758,13 +10053,20 @@ "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 + "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 + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } }, "lowercase-keys": { "version": "1.0.1", @@ -6773,28 +10075,50 @@ "dev": true }, "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true + "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" + } }, "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=" + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "~0.10.2" + } }, "magic-string": { "version": "0.16.0", "resolved": "http://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", - "dev": true + "dev": true, + "requires": { + "vlq": "^0.2.1" + }, + "dependencies": { + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + } + } }, "mailcomposer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", "dev": true, - "optional": true + "optional": true, + "requires": { + "buildmail": "4.0.1", + "libmime": "3.0.0" + } }, "mailgun-js": { "version": "0.18.1", @@ -6802,20 +10126,37 @@ "integrity": "sha512-lvuMP14u24HS2uBsJEnzSyPMxzU2b99tQsIx1o6QNjqxjk8b3WvR+vq5oG1mjqz/IBYo+5gF+uSoDS0RkMVHmg==", "dev": true, "optional": true, + "requires": { + "async": "~2.6.0", + "debug": "~3.1.0", + "form-data": "~2.3.0", + "inflection": "~1.12.0", + "is-stream": "^1.1.0", + "path-proxy": "~1.0.0", + "promisify-call": "^2.0.2", + "proxy-agent": "~3.0.0", + "tsscmp": "~1.0.0" + }, "dependencies": { "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, - "optional": true + "optional": true, + "requires": { + "lodash": "^4.17.10" + } }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, - "optional": true + "optional": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -6830,7 +10171,10 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true + "dev": true, + "requires": { + "pify": "^3.0.0" + } }, "make-error": { "version": "1.3.5", @@ -6842,13 +10186,19 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true + "dev": true, + "requires": { + "make-error": "^1.2.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } }, "map-cache": { "version": "0.2.2", @@ -6863,16 +10213,19 @@ "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": "http://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", "dev": true }, "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 + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } }, "markdown-escapes": { "version": "1.0.2", @@ -6890,7 +10243,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + } }, "math-random": { "version": "1.0.1", @@ -6902,31 +10261,58 @@ "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 + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "mdast-util-compact": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz", "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } }, "mdast-util-definitions": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.3.tgz", "integrity": "sha512-P6wpRO8YVQ1iv30maMc93NLh7COvufglBE8/ldcOyYmk5EbfF0YeqlLgtqP/FOBU501Kqar1x5wYWwB3Nga74g==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.0" + } }, "mdast-util-to-hast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.2.tgz", - "integrity": "sha512-YI8Ea3TFWEZrS31+6Q/d8ZYTOSDKM06IPc3l2+OMFX1o3JTG2mrztlmzDsUMwIXLWofEdTVl/WXBgRG6ddlU/A==", - "dev": true + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.4.tgz", + "integrity": "sha512-/eIbly2YmyVgpJNo+bFLLMCI1XgolO/Ffowhf+pHDq3X4/V6FntC9sGQCDLM147eTS+uSXv5dRzJyFn+o0tazA==", + "dev": true, + "requires": { + "collapse-white-space": "^1.0.0", + "detab": "^2.0.0", + "mdast-util-definitions": "^1.2.0", + "mdurl": "^1.0.1", + "trim": "0.0.1", + "trim-lines": "^1.0.0", + "unist-builder": "^1.0.1", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.0", + "xtend": "^4.0.1" + } }, "mdast-util-to-string": { "version": "1.0.5", @@ -6935,10 +10321,15 @@ "dev": true }, "mdast-util-toc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-2.1.0.tgz", - "integrity": "sha512-ove/QQWSrYOrf9G3xn2MTAjy7PKCtCmm261wpQwecoPAsUtkihkMVczxFqil7VihxgSz4ID9c8bBTsyXR30gQg==", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-3.0.1.tgz", + "integrity": "sha512-Z8lKq6sQr/vDNIcUkIWzPwKo5JQIzlDLouZuzIMVajOdUAyjnkA+s98RhjVpFt7SiuJzase9oh6Iw7n4zhVNDQ==", + "dev": true, + "requires": { + "github-slugger": "^1.1.1", + "mdast-util-to-string": "^1.0.2", + "unist-util-visit": "^1.1.0" + } }, "mdurl": { "version": "1.0.1", @@ -6948,7 +10339,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, @@ -6956,64 +10347,109 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "memoizee": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==" + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } }, "memory-fs": { "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 + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } }, "meow": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "http://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": { "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "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" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "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 + "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 + "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", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -7021,19 +10457,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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 + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } } } }, @@ -7047,19 +10495,41 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true + "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" + } }, "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 + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } }, "mime": { "version": "1.6.0", @@ -7068,16 +10538,17 @@ "dev": true }, "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", - "dev": true + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" }, "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", - "dev": true + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } }, "mimic-fn": { "version": "1.2.0", @@ -7107,25 +10578,34 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, + "requires": { + "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 + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -7133,7 +10613,18 @@ "version": "0.5.1", "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } }, "mkpath": { "version": "1.0.0", @@ -7146,6 +10637,17 @@ "resolved": "http://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.0.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.5.0", + "supports-color": "~1.2.0" + }, "dependencies": { "commander": { "version": "2.3.0", @@ -7157,7 +10659,10 @@ "version": "2.0.0", "resolved": "http://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", - "dev": true + "dev": true, + "requires": { + "ms": "0.6.2" + } }, "escape-string-regexp": { "version": "1.0.2", @@ -7169,11 +10674,16 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "~2.0.0", + "inherits": "2", + "minimatch": "~0.2.11" + } }, "graceful-fs": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "resolved": "http://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", "dev": true }, @@ -7185,7 +10695,7 @@ }, "lru-cache": { "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", "dev": true }, @@ -7193,13 +10703,26 @@ "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mkdirp": { "version": "0.5.0", "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", - "dev": true + "dev": true, + "requires": { + "minimist": "0.0.8" + } }, "ms": { "version": "0.6.2", @@ -7220,6 +10743,10 @@ "resolved": "http://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", "dev": true, + "requires": { + "rewire": "2.5.2", + "semver": "5.3.0" + }, "dependencies": { "semver": { "version": "5.3.0", @@ -7234,18 +10761,47 @@ "resolved": "http://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "concat-stream": "~1.5.0", + "defined": "^1.0.0", + "detective": "^4.0.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.3", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, "dependencies": { "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + }, "dependencies": { "readable-stream": { "version": "2.0.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true + "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" + } } } }, @@ -7257,7 +10813,7 @@ }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -7279,12 +10835,18 @@ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, "dependencies": { "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } }, "isarray": { "version": "0.0.1", @@ -7296,11 +10858,17 @@ "version": "1.1.14", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -7329,7 +10897,20 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true + "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" + } }, "natural-compare": { "version": "1.4.0", @@ -7363,35 +10944,37 @@ }, "next-tick": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nightwatch": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.11.tgz", - "integrity": "sha512-vEAit4rVgufCAyaqQ6Cxs29A9cBNEKeXxWcPFXrG/AOp+19Vz2K6shoNTwpbdNpDDbp7Pjy1YnvjlG9aQrCsmQ==", - "dev": true, + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.14.tgz", + "integrity": "sha512-SXJk0BtXAWslcdByueESJ8a265rshGfllCPy9yPdAEGhIjSKsaMw1ASPn+q+msFhpOYRKEjoQ+Qu9e4SlSz2xQ==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "chai-nightwatch": "0.2.1", + "ejs": "^2.5.9", + "lodash.clone": "^3.0.3", + "lodash.defaultsdeep": "^4.6.0", + "lodash.merge": "^4.6.1", + "minimatch": "3.0.3", + "mkpath": "1.0.0", + "mocha": "^5.1.1", + "optimist": "^0.6.1", + "proxy-agent": "^3.0.0" + }, "dependencies": { - "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, - "optional": true - }, - "commander": { - "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true, - "optional": true - }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, - "optional": true + "optional": true, + "requires": { + "ms": "2.0.0" + } }, "diff": { "version": "3.5.0", @@ -7406,13 +10989,24 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "dependencies": { "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "optional": true + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } } } }, @@ -7420,7 +11014,10 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } }, "mocha": { "version": "5.2.0", @@ -7428,13 +11025,29 @@ "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, "optional": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, "dependencies": { "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "optional": true + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } } } }, @@ -7450,7 +11063,10 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, - "optional": true + "optional": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -7459,12 +11075,22 @@ "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.6.tgz", "integrity": "sha512-1GedetLKzmqmgwabuMSqPsT7oumdR77SBpDfNNJhADRIeA3LN/2RVqR4fFqwvzhAqcTef6PPCzQwITE/YQ8S8A==", "dev": true, + "requires": { + "@sinonjs/formatio": "3.0.0", + "just-extend": "^3.0.0", + "lolex": "^2.3.2", + "path-to-regexp": "^1.7.0", + "text-encoding": "^0.6.4" + }, "dependencies": { "@sinonjs/formatio": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.0.0.tgz", "integrity": "sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w==", - "dev": true + "dev": true, + "requires": { + "@sinonjs/samsam": "2.1.0" + } } } }, @@ -7472,7 +11098,50 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node.extend": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz", + "integrity": "sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA==", + "dev": true, + "requires": { + "has": "^1.0.3", + "is": "^3.2.1" + } }, "nodemailer": { "version": "2.7.2", @@ -7480,6 +11149,15 @@ "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", "dev": true, "optional": true, + "requires": { + "libmime": "3.0.0", + "mailcomposer": "4.0.1", + "nodemailer-direct-transport": "3.3.2", + "nodemailer-shared": "1.1.0", + "nodemailer-smtp-pool": "2.8.2", + "nodemailer-smtp-transport": "2.7.2", + "socks": "1.1.9" + }, "dependencies": { "smart-buffer": { "version": "1.1.15", @@ -7490,10 +11168,14 @@ }, "socks": { "version": "1.1.9", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", + "resolved": "http://registry.npmjs.org/socks/-/socks-1.1.9.tgz", "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", "dev": true, - "optional": true + "optional": true, + "requires": { + "ip": "^1.1.2", + "smart-buffer": "^1.0.4" + } } } }, @@ -7502,7 +11184,11 @@ "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", "dev": true, - "optional": true + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "smtp-connection": "2.12.0" + } }, "nodemailer-fetch": { "version": "1.6.0", @@ -7514,21 +11200,34 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true + "dev": true, + "requires": { + "nodemailer-fetch": "1.6.0" + } }, "nodemailer-smtp-pool": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", "dev": true, - "optional": true + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } }, "nodemailer-smtp-transport": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", "dev": true, - "optional": true + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } }, "nodemailer-wellknown": { "version": "0.1.10", @@ -7540,36 +11239,60 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true + "dev": true, + "requires": { + "abbrev": "1" + } }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=" + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } }, "normalize-url": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } }, "now-and-later": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.2" + } }, "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 + "dev": true, + "requires": { + "path-key": "^2.0.0" + } }, "null-check": { "version": "1.0.0", @@ -7586,8 +11309,7 @@ "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 + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", @@ -7605,18 +11327,29 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -7630,37 +11363,63 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.0" + } }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "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.4", + "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 + "dev": true, + "requires": { + "for-in": "^1.0.1" + } } } }, @@ -7668,31 +11427,47 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "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 + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true + "dev": true, + "requires": { + "ee-first": "1.1.1" + } }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "open": { "version": "0.0.5", @@ -7711,7 +11486,17 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "http://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", @@ -7725,6 +11510,13 @@ "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", "dev": true, + "requires": { + "acorn": "^3.3.0", + "concat-stream": "^1.5.1", + "estree-walker": "^0.3.0", + "magic-string": "^0.16.0", + "yargs": "^4.8.1" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -7742,41 +11534,66 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true + "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" + } }, "os-locale": { "version": "1.4.0", "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true + "dev": true, + "requires": { + "lcid": "^1.0.0" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "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 + "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 + "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", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -7784,19 +11601,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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 + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } }, "which-module": { "version": "1.0.0", @@ -7808,13 +11637,33 @@ "version": "4.8.1", "resolved": "http://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true + "dev": true, + "requires": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.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.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } }, "yargs-parser": { "version": "2.4.1", "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } } } }, @@ -7822,13 +11671,24 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } }, "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 + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } }, "os-browserify": { "version": "0.3.0", @@ -7838,7 +11698,7 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, @@ -7846,11 +11706,16 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, @@ -7876,19 +11741,28 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true + "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 + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } }, "p-try": { "version": "1.0.0", @@ -7901,6 +11775,16 @@ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", "dev": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + }, "dependencies": { "bytes": { "version": "3.0.0", @@ -7908,29 +11792,26 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, - "http-errors": { - "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true - }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } } } }, @@ -7938,79 +11819,125 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true + "dev": true, + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } }, "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", + "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", "dev": true }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } }, "parse-asn1": { "version": "5.1.1", "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } }, "parse-domain": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.2.tgz", - "integrity": "sha512-I1HuHXYL8hZp9MYf0jHZE2nW0qhJnqBAxKOR9sGCbiBoD3znYrp4nh3SH9dkt2+f6gEenEj6sh537FTNe+QBqg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.7.tgz", + "integrity": "sha512-yb0VWRwDCe96ML49b3xg+4wScbocpIrFSAdkml8eKq/deH3FiFPBpsC6RTC9ZUtnDhInmXPfNIHsN/v62+TAMA==", "dev": true, + "requires": { + "chai": "^4.2.0", + "got": "^8.3.2", + "mkdirp": "^0.5.1", + "mocha": "^5.2.0" + }, "dependencies": { "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "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 + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } }, "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", - "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 + "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" + } }, "mocha": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "dev": true + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + } }, "ms": { "version": "2.0.0", @@ -8019,10 +11946,13 @@ "dev": true }, "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true + "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" + } }, "type-detect": { "version": "4.0.8", @@ -8036,25 +11966,47 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.0.tgz", "integrity": "sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==", - "dev": true + "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" + } }, "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 + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } }, "parse-git-config": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", - "dev": true + "dev": true, + "requires": { + "ini": "^1.3.3" + } }, "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.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, "dependencies": { "is-extglob": { "version": "1.0.0", @@ -8066,7 +12018,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } } } }, @@ -8074,6 +12029,16 @@ "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.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-node-version": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", + "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==", "dev": true }, "parse-passwd": { @@ -8082,23 +12047,45 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse-path": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-3.0.4.tgz", + "integrity": "sha512-wP70vtwv2DyrM2YoA7ZHVv4zIXa4P7dGgHlj+VwyXNDduLLVJ7NMY1zsFxjUUJ3DAwJLupGb1H5gMDDiNlJaxw==", + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } + }, "parse-url": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", - "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", - "dev": true + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-3.0.2.tgz", + "integrity": "sha1-YCeHpwY6eV1yuGcxl1BecvYGEL4=", + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "normalize-url": "^1.9.1", + "parse-path": "^3.0.1", + "protocols": "^1.4.0" + } }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } }, "parseuri": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } }, "parseurl": { "version": "1.3.2", @@ -8132,7 +12119,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -8166,6 +12153,9 @@ "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", "dev": true, "optional": true, + "requires": { + "inflection": "~1.3.0" + }, "dependencies": { "inflection": { "version": "1.3.8", @@ -8180,7 +12170,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } }, "path-root-regex": { "version": "0.1.2", @@ -8193,6 +12186,9 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, + "requires": { + "isarray": "0.0.1" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -8206,7 +12202,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true + "dev": true, + "requires": { + "pify": "^3.0.0" + } }, "pathval": { "version": "1.1.0", @@ -8218,13 +12217,23 @@ "version": "0.0.11", "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true + "dev": true, + "requires": { + "through": "~2.3" + } }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "pbkdf2-compat": { "version": "2.0.1", @@ -8235,8 +12244,7 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pify": { "version": "3.0.0", @@ -8254,19 +12262,31 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true + "dev": true, + "requires": { + "find-up": "^2.1.0" + } }, "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 + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } }, "pluralize": { "version": "7.0.0", @@ -8287,9 +12307,9 @@ "dev": true }, "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, "preserve": { @@ -8322,9 +12342,9 @@ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.2.tgz", + "integrity": "sha512-/OLz5F9beZUWwSHZDreXgap1XShX6W+DCHQCqwCF7uZ88s6uTlD2cR3JBE77SegCmNtb1Idst+NfmwcdU6KVhw==", "dev": true }, "promisify-call": { @@ -8332,7 +12352,10 @@ "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", "dev": true, - "optional": true + "optional": true, + "requires": { + "with-callback": "^1.0.2" + } }, "property-information": { "version": "3.2.0", @@ -8350,7 +12373,17 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", - "dev": true + "dev": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "pac-proxy-agent": "^3.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + } }, "proxy-from-env": { "version": "1.0.0", @@ -8358,11 +12391,22 @@ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", "dev": true }, + "proxy-middleware": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.5.1.tgz", + "integrity": "sha1-2iTV1Ywd3xPa0jfH7KUDhJ6uqQM=", + "dev": true + }, "proxyquire": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", "dev": true, + "requires": { + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.0", + "resolve": "~1.1.7" + }, "dependencies": { "resolve": { "version": "1.1.7", @@ -8387,32 +12431,47 @@ "psl": { "version": "1.1.29", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", - "dev": true + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" }, "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "q": { "version": "1.5.1", @@ -8429,14 +12488,17 @@ "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 + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "query-string": { - "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } }, "querystring": { "version": "0.2.0", @@ -8457,10 +12519,15 @@ "dev": true }, "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "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.0", + "math-random": "^1.0.1" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -8474,18 +12541,25 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } }, "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 + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } }, "range-parser": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", - "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", "dev": true }, "raw-body": { @@ -8493,10 +12567,14 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, + "requires": { + "bytes": "1", + "string_decoder": "0.10" + }, "dependencies": { "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -8506,43 +12584,78 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } }, "readable-stream": { "version": "2.3.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==" + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "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" + } }, "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true + "dev": true, + "requires": { + "resolve": "^1.1.6" + } }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } }, "redis": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", "dev": true, - "optional": true + "optional": true, + "requires": { + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" + } }, "redis-commands": { "version": "1.4.0", @@ -8573,19 +12686,31 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.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 + "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 + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } }, "regexpp": { "version": "1.1.0", @@ -8597,23 +12722,31 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } }, "regjsgen": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, "regjsparser": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "resolved": "http://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -8623,61 +12756,129 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true + "dev": true, + "requires": { + "remark-parse": "^5.0.0", + "remark-stringify": "^5.0.0", + "unified": "^6.0.0" + } }, "remark-html": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true + "dev": true, + "requires": { + "hast-util-sanitize": "^1.0.0", + "hast-util-to-html": "^3.0.0", + "mdast-util-to-hast": "^3.0.0", + "xtend": "^4.0.1" + } }, "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } }, "remark-reference-links": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.2.tgz", - "integrity": "sha512-871gKTysBtdQUjoqXA0URWmVhI2jFrpLkWrM3/bydAbsngilDYRjjl2LDAgmNooW8bYbHa57YQ13ld+mYr3TLg==", - "dev": true + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.3.tgz", + "integrity": "sha512-Q9d7JaK5r0JDBo3TInfrodBuI3xulI8htCr8jlX+0oXosF3GaebJbo5y228VYFoV6xJ+syDukkUGMKNlwSJWjQ==", + "dev": true, + "requires": { + "unist-util-visit": "^1.0.0" + } }, "remark-slug": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.0.tgz", - "integrity": "sha512-FW/V7b3ekfDL1eyPDyzfq0qz5HFPKPNWVC2eqFDie45r774FLGoymOS1oU7LVQfdFNEvNLZ6oBJT/oIxAyBISg==", - "dev": true + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.1.tgz", + "integrity": "sha512-r591rdoDPJkSSAVvEaTVUkqbMp7c7AyZfif14V0Dp66GQkOHzaPAS6wyhawSbqpS0ZdTnfJS+TltFoxzi6bdIA==", + "dev": true, + "requires": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^1.0.0" + } }, "remark-stringify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true + "dev": true, + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } }, "remark-toc": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.0.0.tgz", - "integrity": "sha512-j2A/fpio1nzNRJtY6nVaFUCtXNfFPxaj6I5UHFsFgo4xKmc0VokRRIzGqz4Vfs7u+dPrHjnoHkImu1Dia0jDSQ==", - "dev": true + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.1.1.tgz", + "integrity": "sha512-vCPW4YOsm2CfyuScdktM9KDnJXVHJsd/ZeRtst+dnBU3B3KKvt8bc+bs5syJjyptAHfqo7H+5Uhz+2blWBfwow==", + "dev": true, + "requires": { + "mdast-util-toc": "^3.0.0", + "remark-slug": "^5.0.0" + } }, "remote-origin-url": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", + "resolved": "http://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true + "dev": true, + "requires": { + "parse-git-config": "^0.2.0" + } }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } }, "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 + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } }, "remove-trailing-separator": { "version": "1.1.0", @@ -8700,7 +12901,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } }, "replace-ext": { "version": "1.0.0", @@ -8712,26 +12916,63 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } }, "replacestream": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-0.1.3.tgz", - "integrity": "sha1-4BjTo3ckYAzNDABZkNiiG3tU/zQ=", - "dev": true + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + } }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } }, "requestretry": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", "dev": true, - "optional": true + "optional": true, + "requires": { + "extend": "^3.0.0", + "lodash": "^4.15.0", + "request": "^2.74.0", + "when": "^3.7.7" + } }, "require-directory": { "version": "2.1.1", @@ -8747,9 +12988,13 @@ }, "require-uncached": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } }, "requirejs": { "version": "2.3.6", @@ -8767,13 +13012,20 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } }, "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 + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } }, "resolve-from": { "version": "1.0.1", @@ -8785,7 +13037,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } }, "resolve-url": { "version": "0.2.1", @@ -8796,13 +13051,20 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } }, "ret": { "version": "0.1.15", @@ -8820,7 +13082,10 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true + "dev": true, + "requires": { + "align-text": "^0.1.1" + } }, "rimraf": { "version": "2.2.8", @@ -8832,13 +13097,20 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } }, "rx-lite": { "version": "4.0.8", @@ -8850,7 +13122,10 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true + "dev": true, + "requires": { + "rx-lite": "*" + } }, "safe-buffer": { "version": "5.1.2", @@ -8865,15 +13140,17 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true + "dev": true, + "requires": { + "ret": "~0.1.10" + } }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "samsam": { "version": "1.3.0", @@ -8886,11 +13163,32 @@ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", "dev": true, + "requires": { + "ajv": "^5.0.0" + }, "dependencies": { "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" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "http://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 } } @@ -8905,101 +13203,40 @@ "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 - }, - "send": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", - "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", - "dev": true, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true - }, - "mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "statuses": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", - "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", - "dev": true - } - } - }, - "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": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - } + "requires": { + "sver-compat": "^1.5.0" } }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "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", + "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "mime": { "version": "1.4.1", @@ -9008,21 +13245,9 @@ "dev": true }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "statuses": { @@ -9033,6 +13258,50 @@ } } }, + "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": { + "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" + }, + "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 + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -9044,12 +13313,21 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "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 + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -9069,13 +13347,20 @@ "version": "2.4.11", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "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 + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } }, "shebang-regex": { "version": "1.0.0", @@ -9084,10 +13369,15 @@ "dev": true }, "shelljs": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", - "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", - "dev": true + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } }, "sigmund": { "version": "1.0.1", @@ -9106,6 +13396,15 @@ "resolved": "http://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "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" + }, "dependencies": { "diff": { "version": "3.5.0", @@ -9113,12 +13412,6 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "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 - }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -9132,7 +13425,10 @@ "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", "dev": true, - "optional": true + "optional": true, + "requires": { + "requestretry": "^1.2.2" + } }, "slash": { "version": "1.0.0", @@ -9145,6 +13441,9 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + }, "dependencies": { "is-fullwidth-code-point": { "version": "2.0.0", @@ -9164,31 +13463,54 @@ "version": "2.12.0", "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true + "dev": true, + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } }, "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": { + "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "ms": { "version": "2.0.0", @@ -9209,30 +13531,49 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -9241,33 +13582,51 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, "sntp": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "resolved": "http://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, - "optional": true + "requires": { + "hoek": "2.x.x" + } }, "socket.io": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", "dev": true, + "requires": { + "debug": "~2.6.6", + "engine.io": "~3.1.0", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.0.4", + "socket.io-parser": "~3.1.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -9288,12 +13647,30 @@ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~2.6.4", + "engine.io-client": "~3.1.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.1.1", + "to-array": "0.1.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -9305,15 +13682,24 @@ }, "socket.io-parser": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "has-binary2": "~1.0.2", + "isarray": "2.0.1" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "isarray": { "version": "2.0.1", @@ -9330,22 +13716,33 @@ } }, "socks": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz", - "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", - "dev": true + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.2.tgz", + "integrity": "sha512-g6wjBnnMOZpE0ym6e0uHSddz9p3a+WsBaaYQaBaSCJYvrC4IXykQR9MNGjLQf38e9iIIhp3b1/Zk8YZI3KGJ0Q==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.0.1" + } }, "socks-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", - "dev": true + "dev": true, + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + } }, "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } }, "source-list-map": { "version": "2.0.1", @@ -9361,13 +13758,23 @@ "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==" + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } }, "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" + }, "dependencies": { "source-map": { "version": "0.5.7", @@ -9386,7 +13793,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "dev": true + "dev": true, + "requires": { + "trim": "0.0.1" + } }, "sparkles": { "version": "1.0.1", @@ -9398,7 +13808,11 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", - "dev": true + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-exceptions": { "version": "2.2.0", @@ -9410,37 +13824,56 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-license-ids": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", - "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", "dev": true }, "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true + "version": "0.3.3", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2" + } }, "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 + "dev": true, + "requires": { + "extend-shallow": "^3.0.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 + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", - "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", - "dev": true + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", + "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "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" + } }, "stack-trace": { "version": "0.0.10", @@ -9459,12 +13892,19 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, @@ -9479,6 +13919,9 @@ "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", "dev": true, + "requires": { + "readable-stream": "~2.1.0" + }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -9490,11 +13933,20 @@ "version": "2.1.5", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true + "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" + } }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -9502,21 +13954,32 @@ }, "stream-browserify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } }, "stream-combiner": { - "version": "0.2.2", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dev": true + "version": "0.0.4", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.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 + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } }, "stream-exhaust": { "version": "1.0.2", @@ -9528,7 +13991,14 @@ "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 + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } }, "stream-shift": { "version": "1.0.0", @@ -9540,7 +14010,13 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", - "dev": true + "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + } }, "strict-uri-encode": { "version": "1.1.0", @@ -9548,16 +14024,18 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "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==" - }, "string-replace-webpack-plugin": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz", "integrity": "sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw=", "dev": true, + "requires": { + "async": "~0.2.10", + "css-loader": "^0.9.1", + "file-loader": "^0.8.1", + "loader-utils": "~0.2.3", + "style-loader": "^0.8.3" + }, "dependencies": { "async": { "version": "0.2.10", @@ -9569,7 +14047,13 @@ "version": "0.2.17", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } } } }, @@ -9583,26 +14067,55 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } }, "stringify-entities": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true + "dev": true, + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } }, "stringstream": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true, - "optional": true + "dev": true }, "strip-ansi": { "version": "3.0.1", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^2.0.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 + } + } }, "strip-bom": { "version": "3.0.0", @@ -9617,7 +14130,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -9625,7 +14138,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } }, "strip-json-comments": { "version": "2.0.1", @@ -9639,13 +14155,22 @@ "integrity": "sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c=", "dev": true, "optional": true, + "requires": { + "loader-utils": "^0.2.5" + }, "dependencies": { "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, - "optional": true + "optional": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } } } }, @@ -9654,38 +14179,53 @@ "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } + "requires": { + "minimist": "^1.1.0" } }, "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 + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } }, "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 + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } }, "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", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + }, "dependencies": { "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true + "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" + } }, "ansi-regex": { "version": "3.0.0", @@ -9693,16 +14233,21 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "is-fullwidth-code-point": { @@ -9711,37 +14256,50 @@ "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 + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "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 - }, - "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, "tapable": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", - "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz", + "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", "dev": true }, "ternary-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true + "dev": true, + "requires": { + "duplexify": "^3.5.0", + "fork-stream": "^0.0.4", + "merge-stream": "^1.0.0", + "through2": "^2.0.1" + } }, "text-encoding": { "version": "0.6.4", @@ -9756,9 +14314,9 @@ "dev": true }, "textextensions": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", - "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz", + "integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==", "dev": true }, "through": { @@ -9768,15 +14326,23 @@ "dev": true }, "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } }, "through2-filter": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } }, "thunkify": { "version": "2.1.2", @@ -9800,12 +14366,19 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } }, "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==" + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } }, "timespan": { "version": "2.3.0", @@ -9818,19 +14391,34 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", - "dev": true + "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" + } }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true + "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 + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } }, "to-array": { "version": "0.1.4", @@ -9855,12 +14443,18 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -9868,25 +14462,48 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } }, "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 + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } }, "to-through": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true + "dev": true, + "requires": { + "through2": "^2.0.3" + } }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } }, "traverse": { "version": "0.3.9", @@ -9947,19 +14564,23 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true + "requires": { + "safe-buffer": "^5.0.1" + } }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } }, "type-detect": { "version": "1.0.0", @@ -9968,10 +14589,31 @@ "dev": true }, "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", + "integrity": "sha1-uTaKWTzG730GReeLL0xky+zQXpA=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.0.9" + }, + "dependencies": { + "mime-db": { + "version": "1.12.0", + "resolved": "http://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", + "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=", + "dev": true + }, + "mime-types": { + "version": "2.0.14", + "resolved": "http://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "dev": true, + "requires": { + "mime-db": "~1.12.0" + } + } + } }, "typedarray": { "version": "0.0.6", @@ -9984,6 +14626,11 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, "dependencies": { "camelcase": { "version": "1.2.1", @@ -9995,7 +14642,12 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } }, "source-map": { "version": "0.5.7", @@ -10019,7 +14671,13 @@ "version": "3.10.0", "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } } } }, @@ -10034,6 +14692,11 @@ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + }, "dependencies": { "source-map": { "version": "0.5.7", @@ -10065,7 +14728,18 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", - "dev": true + "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", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } }, "undertaker-registry": { "version": "1.0.1", @@ -10077,31 +14751,58 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + } }, "unified": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "set-value": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } } } }, @@ -10109,18 +14810,25 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } }, "unist-builder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.3.tgz", "integrity": "sha512-/KB8GEaoeHRyIqClL+Kam+Y5NWJ6yEiPsAfv1M+O1p+aKGgjR89WwoEHKTyOj17L6kAlqtKpAgv2nWvdbQDEig==", - "dev": true + "dev": true, + "requires": { + "object-assign": "^4.1.0" + } }, "unist-util-generated": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.2.tgz", - "integrity": "sha512-1HcwiEO62dr0XWGT+abVK4f0aAm8Ik8N08c5nAYVmuSxfvpA9rCcNyX/le8xXj1pJK5nBrGlZefeWB6bN8Pstw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.3.tgz", + "integrity": "sha512-qlPeDqnQnd84KIqwphzOR+l02cxjDzvEYEBl84EjmKRrX4eUmjyAo8xJv1SCDhJqNjyHRnBMZWNKAiBtXE6hBg==", "dev": true }, "unist-util-is": { @@ -10130,16 +14838,19 @@ "dev": true }, "unist-util-position": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.1.tgz", - "integrity": "sha512-05QfJDPI7PE1BIUtAxeSV+cDx21xP7+tUZgSval5CA7tr0pHBwybF7OnEa1dOFqg6BfYH/qiMUnWwWj+Frhlww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.2.tgz", + "integrity": "sha512-npmFu92l/+b1Ao6uGP4I1WFz9hsKv7qleZ4aliw6x0RVu6A9A3tAf57NMpFfzQ02jxRtJZuRn+C8xWT7GWnH0g==", "dev": true }, "unist-util-remove-position": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } }, "unist-util-stringify-position": { "version": "1.1.2", @@ -10151,13 +14862,19 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } }, "unist-util-visit-parents": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", - "dev": true + "dev": true, + "requires": { + "unist-util-is": "^2.1.2" + } }, "unpipe": { "version": "1.0.0", @@ -10170,18 +14887,30 @@ "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=", "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.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 + "dev": true, + "requires": { + "isarray": "1.0.0" + } } } }, @@ -10198,6 +14927,17 @@ "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.4.tgz", "integrity": "sha512-kGrkTaphmXE+0/A5Q7rwcm/xHlDkXDOGEh6wuiN3SUQsyVWd7V51rwqttlNTT91JrLkfn34MoBNf38unF0vhRw==", "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.10", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + }, "dependencies": { "bluebird": { "version": "3.4.7", @@ -10213,6 +14953,14 @@ "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", "dev": true }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -10223,6 +14971,10 @@ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, "dependencies": { "punycode": { "version": "1.3.2", @@ -10233,10 +14985,14 @@ } }, "url-parse": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", - "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", + "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", "dev": true, + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + }, "dependencies": { "querystringify": { "version": "2.1.0", @@ -10250,7 +15006,18 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + }, + "dependencies": { + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + } + } }, "url-to-options": { "version": "1.0.1", @@ -10269,10 +15036,14 @@ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "dev": true, + "requires": { + "lru-cache": "2.2.x", + "tmp": "0.0.x" + }, "dependencies": { "lru-cache": { "version": "2.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", "dev": true } @@ -10282,7 +15053,10 @@ "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true + "dev": true, + "requires": { + "inherits": "2.0.3" + } }, "util-deprecate": { "version": "1.0.2", @@ -10298,8 +15072,7 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "uws": { "version": "9.14.0", @@ -10312,13 +15085,20 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", - "dev": true + "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==", - "dev": true + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } }, "value-or-function": { "version": "3.0.0", @@ -10330,31 +15110,51 @@ "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.2.0" + } }, "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } }, "vfile-location": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.3.tgz", - "integrity": "sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.4.tgz", + "integrity": "sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w==", "dev": true }, "vfile-message": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz", - "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.2.tgz", + "integrity": "sha512-dNdEXHfPCvzyOlEaaQ+DcXpcxEz+pFvdrebKLiAMjobjaBC2bMeWoHOKPwJ+I8A4jQOEUDH7uoVcLWDLF1qhVQ==", + "dev": true, + "requires": { + "unist-util-stringify-position": "^1.1.1" + } }, "vfile-reporter": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, + "requires": { + "repeat-string": "^1.5.0", + "string-width": "^1.0.0", + "supports-color": "^4.1.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-statistics": "^1.1.0" + }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -10366,45 +15166,87 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } } } }, "vfile-sort": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.1.1.tgz", - "integrity": "sha512-+fpTWKkVHwI6VF2xtkDTuCA6cH4UPLAxh+KxfU8g8pC0do5RSZCk1HXTTtMJguW0t5jC0PC19owjUZX9SGQ9tw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.0.tgz", + "integrity": "sha512-RgxLXVWrJBWb2GuP8FsSkqK7HmbjXjnI8qx3nD6NTWhsWaelaKvJuxfh1F1d1lkCPD7imo4zzi8cf6IOMgaTnQ==", "dev": true }, "vfile-statistics": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.1.tgz", - "integrity": "sha512-dxUM6IYvGChHuwMT3dseyU5BHprNRXzAV0OHx1A769lVGsTiT50kU7BbpRFV+IE6oWmU+PwHdsTKfXhnDIRIgQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.2.tgz", + "integrity": "sha512-16wAC9eEGXdsD35LX9m/iXCRIZyX5LIrDgDtAF92rbATSqsBRbC4n05e0Rj5vt3XRpcKu0UJeWnTxWsSyvNZ+w==", "dev": true }, "vinyl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true + "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" + } }, "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 + "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" + } }, "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 + "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" + } }, "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" + }, "dependencies": { "source-map": { "version": "0.5.7", @@ -10415,16 +15257,18 @@ } }, "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.0.tgz", + "integrity": "sha512-o3WmXySo+oI5thgqr7Qy8uBkT/v9Zr+sRyrh1lr8aWPUkgDWdWt4Nae2WKBrLsocgE8BuWWD0jLc+VW8LeU+2g==" }, "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 + "dev": true, + "requires": { + "indexof": "0.0.1" + } }, "void-elements": { "version": "2.0.1", @@ -10436,19 +15280,57 @@ "version": "2.3.14", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", + "dev": true, + "requires": { + "foreachasync": "^3.0.0" + } + }, + "watch": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.11.0.tgz", + "integrity": "sha1-6NugkbdFZ5mjr1eXi5hud+EyBAY=", "dev": true }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.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.0.0", + "acorn-dynamic-import": "^2.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "async": "^2.1.2", + "enhanced-resolve": "^3.4.0", + "escope": "^3.6.0", + "interpret": "^1.0.0", + "json-loader": "^0.5.4", + "json5": "^0.5.1", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "mkdirp": "~0.5.0", + "node-libs-browser": "^2.0.0", + "source-map": "^0.5.3", + "supports-color": "^4.2.1", + "tapable": "^0.2.7", + "uglifyjs-webpack-plugin": "^0.4.6", + "watchpack": "^1.4.0", + "webpack-sources": "^1.0.1", + "yargs": "^8.0.2" + }, "dependencies": { "ajv-keywords": { "version": "3.2.0", @@ -10466,7 +15348,10 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.10" + } }, "has-flag": { "version": "2.0.0", @@ -10484,23 +15369,35 @@ "version": "2.0.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^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=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true + "dev": true, + "requires": { + "pify": "^2.0.0" + } }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -10508,13 +15405,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } }, "source-map": { "version": "0.5.7", @@ -10526,25 +15432,50 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.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.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } } } }, @@ -10553,6 +15484,10 @@ "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, + "requires": { + "source-list-map": "~0.1.7", + "source-map": "~0.4.1" + }, "dependencies": { "source-list-map": { "version": "0.1.8", @@ -10562,9 +15497,12 @@ }, "source-map": { "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -10573,11 +15511,18 @@ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", "dev": true, + "requires": { + "memory-fs": "~0.4.1", + "mime": "^1.5.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "time-stamp": "^2.0.0" + }, "dependencies": { "time-stamp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.1.0.tgz", - "integrity": "sha512-lJbq6KsFhZJtN3fPUVje1tq/hHsJOKUUcUj/MGCiQR6qWBDcyi5kxL9J7/RnaEChCn0+L/DUN2WvemDrkk4i3Q==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.2.0.tgz", + "integrity": "sha512-zxke8goJQpBeEgD82CXABeMh0LSJcj7CXEd0OHOg45HgcofF7pxNwZm9+RknpxpDhwN4gFpySkApKfFYfRQnUA==", "dev": true } } @@ -10586,13 +15531,26 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", - "dev": true + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } }, "webpack-stream": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", "dev": true, + "requires": { + "gulp-util": "^3.0.7", + "lodash.clone": "^4.3.2", + "lodash.some": "^4.2.2", + "memory-fs": "^0.3.0", + "through": "^2.3.8", + "vinyl": "^1.1.0", + "webpack": "^1.12.9" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -10604,13 +15562,20 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } }, "array-unique": { "version": "0.2.1", @@ -10622,19 +15587,30 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } }, "browserify-aes": { "version": "0.4.0", "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1" + } }, "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 + "dev": true, + "requires": { + "pako": "~0.2.0" + } }, "camelcase": { "version": "1.2.1", @@ -10646,13 +15622,29 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } }, "clone": { "version": "1.0.4", @@ -10670,13 +15662,24 @@ "version": "3.3.0", "resolved": "http://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", - "dev": true + "dev": true, + "requires": { + "browserify-aes": "0.4.0", + "pbkdf2-compat": "2.0.1", + "ripemd160": "0.2.0", + "sha.js": "2.2.6" + } }, "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.1.2", + "memory-fs": "^0.2.0", + "tapable": "^0.1.8" + }, "dependencies": { "memory-fs": { "version": "0.2.0", @@ -10690,31 +15693,50 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } }, "expand-range": { "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true + "dev": true, + "requires": { + "fill-range": "^2.1.0" + } }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.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 + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } }, "has-flag": { "version": "1.0.0", @@ -10744,31 +15766,49 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } }, "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true + "dev": true, + "requires": { + "isarray": "1.0.0" + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } }, "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 + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } }, "lodash.clone": { "version": "4.5.0", @@ -10780,19 +15820,63 @@ "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 + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } }, "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 + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.1.4", + "buffer": "^4.9.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "0.0.1", + "os-browserify": "^0.2.0", + "path-browserify": "0.0.0", + "process": "^0.11.0", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.0.5", + "stream-browserify": "^2.0.1", + "stream-http": "^2.3.1", + "string_decoder": "^0.10.25", + "timers-browserify": "^2.0.2", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + } }, "os-browserify": { "version": "0.2.1", @@ -10802,10 +15886,16 @@ }, "pako": { "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "resolved": "http://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", @@ -10832,7 +15922,7 @@ }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, @@ -10840,7 +15930,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } }, "tapable": { "version": "0.1.10", @@ -10853,6 +15946,12 @@ "resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, "dependencies": { "async": { "version": "0.2.10", @@ -10866,13 +15965,23 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } }, "watchpack": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, + "requires": { + "async": "^0.9.0", + "chokidar": "^1.0.0", + "graceful-fs": "^4.1.2" + }, "dependencies": { "async": { "version": "0.9.2", @@ -10886,7 +15995,24 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "dev": true + "dev": true, + "requires": { + "acorn": "^3.0.0", + "async": "^1.3.0", + "clone": "^1.0.2", + "enhanced-resolve": "~0.9.0", + "interpret": "^0.6.4", + "loader-utils": "^0.2.11", + "memory-fs": "~0.3.0", + "mkdirp": "~0.5.0", + "node-libs-browser": "^0.7.0", + "optimist": "~0.6.0", + "supports-color": "^3.1.0", + "tapable": "~0.1.8", + "uglify-js": "~2.7.3", + "watchpack": "^0.2.1", + "webpack-core": "~0.6.9" + } }, "window-size": { "version": "0.1.0", @@ -10904,7 +16030,13 @@ "version": "3.10.0", "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } } } }, @@ -10912,7 +16044,11 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } }, "websocket-extensions": { "version": "0.1.3", @@ -10931,7 +16067,10 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true + "dev": true, + "requires": { + "isexe": "^2.0.0" + } }, "which-module": { "version": "2.0.0", @@ -10962,7 +16101,11 @@ "version": "2.1.0", "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } }, "wrappy": { "version": "1.0.2", @@ -10974,13 +16117,21 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } }, "x-is-string": { "version": "0.1.0", @@ -11027,7 +16178,10 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } }, "yeast": { "version": "0.1.2", diff --git a/package.json b/package.json index 08c7d3a6587..b2b883f69da 100755 --- a/package.json +++ b/package.json @@ -45,16 +45,16 @@ "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", - "gulp-connect": "5.5.0", + "gulp-webserver": "^0.9.1", "gulp-coveralls": "^0.1.4", "gulp-eslint": "^4.0.0", - "gulp-footer": "^1.0.5", + "gulp-footer": "github:prebid/gulp-footer#master", "gulp-header": "^1.7.1", "gulp-if": "^2.0.2", "gulp-js-escape": "^1.0.1", "gulp-optimize-js": "^1.1.0", "gulp-rename": "^1.2.0", - "gulp-replace": "^0.4.0", + "gulp-replace": "^1.0.0", "gulp-shell": "^0.5.2", "gulp-uglify": "^3.0.0", "gulp-util": "^3.0.0", From 96df52f506177d2740f41a295e9d3d61fca0a012 Mon Sep 17 00:00:00 2001 From: afsheenb Date: Tue, 4 Dec 2018 14:12:36 -0500 Subject: [PATCH 0873/1594] initial version of ozone adapter for review (#3307) * initial version of ozone adapter for review * updates made per prebid.org feedback * Added a new line as failed prebid.org automated test * Unit Tests for Ozone Adaptor * updated URIs to include https protocol which failed tests --- modules/ozoneBidAdapter.js | 233 +++++++++++ modules/ozoneBidAdapter.md | 45 +++ test/spec/modules/ozoneBidAdapter_spec.js | 454 ++++++++++++++++++++++ 3 files changed, 732 insertions(+) create mode 100644 modules/ozoneBidAdapter.js create mode 100644 modules/ozoneBidAdapter.md create mode 100644 test/spec/modules/ozoneBidAdapter_spec.js diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js new file mode 100644 index 00000000000..1907b74ee02 --- /dev/null +++ b/modules/ozoneBidAdapter.js @@ -0,0 +1,233 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'ozone'; + +const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; +const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; + +export const spec = { + code: BIDDER_CODE, + + /** + * Basic check to see whether required parameters are in the request. + * @param bid + * @returns {boolean} + */ + isBidRequestValid(bid) { + if (!(bid.params.hasOwnProperty('placementId'))) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : missing placementId : siteId, placementId and publisherId are REQUIRED'); + return false; + } + if (!(bid.params.placementId).toString().match(/^[0-9]{10}$/)) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : placementId must be exactly 10 numeric characters'); + return false; + } + if (!(bid.params.hasOwnProperty('publisherId'))) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : missing publisherId : siteId, placementId and publisherId are REQUIRED'); + return false; + } + if (!(bid.params.publisherId).toString().match(/^[a-zA-Z0-9\-]{12}$/)) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : publisherId must be exactly 12 alphanumieric characters including hyphens'); + return false; + } + if (!(bid.params.hasOwnProperty('siteId'))) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : missing siteId : siteId, placementId and publisherId are REQUIRED'); + return false; + } + if (!(bid.params.siteId).toString().match(/^[0-9]{10}$/)) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : siteId must be exactly 10 numeric characters'); + return false; + } + if (bid.params.hasOwnProperty('customData')) { + if (typeof bid.params.customData !== 'object') { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : customData is not an object'); + return false; + } + } + if (bid.params.hasOwnProperty('customParams')) { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : customParams should be renamed to customData'); + return false; + } + if (bid.params.hasOwnProperty('ozoneData')) { + if (typeof bid.params.ozoneData !== 'object') { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : ozoneData is not an object'); + return false; + } + } + if (bid.params.hasOwnProperty('lotameData')) { + if (typeof bid.params.lotameData !== 'object') { + utils.logInfo('OZONE BID ADAPTER VALIDATION FAILED : lotameData is not an object'); + return false; + } + } + return true; + }, + /** + * @param serverResponse + * @param request + * @returns {*} + */ + interpretResponse(serverResponse, request) { + serverResponse = serverResponse.body || {}; + if (serverResponse.seatbid) { + if (utils.isArray(serverResponse.seatbid)) { + const {seatbid: arrSeatbid} = serverResponse; + let winnerAds = arrSeatbid.reduce((bid, ads) => { + var _seat = ads.seat; + let ad = ads.bid.reduce(function(currentWinningBid, considerBid) { + if (currentWinningBid.price < considerBid.price) { + const bid = matchRequest(considerBid.impid, request); + const {width, height} = defaultSize(bid); + considerBid.cpm = considerBid.price; + considerBid.bidId = considerBid.impid; + considerBid.requestId = considerBid.impid; + considerBid.width = considerBid.w || width; + considerBid.height = considerBid.h || height; + considerBid.ad = considerBid.adm; + considerBid.netRevenue = true; + considerBid.creativeId = considerBid.crid; + considerBid.currency = 'USD'; + considerBid.ttl = 60; + considerBid.seat = _seat; + + return considerBid; + } else { + currentWinningBid.cpm = currentWinningBid.price; + return currentWinningBid; + } + }, {price: 0}); + if (ad.adm) { + bid.push(ad) + } + return bid; + }, []) + let winnersClean = winnerAds.filter(w => { + if (w.bidId) { + return true; + } + return false; + }); + utils.logInfo(['going to return winnersClean:', winnersClean]); + return winnersClean; + } else { + return []; + } + } else { + return []; + } + }, + buildRequests(validBidRequests, bidderRequest) { + let ozoneRequest = validBidRequests[0].params; + ozoneRequest['id'] = utils.generateUUID(); + ozoneRequest['auctionId'] = bidderRequest['auctionId']; + + if (bidderRequest.hasOwnProperty('placementId')) { + bidderRequest.placementId = (bidderRequest.placementId).toString(); + } + if (bidderRequest.hasOwnProperty('siteId')) { + bidderRequest.siteId = (bidderRequest.siteId).toString(); + } + if (bidderRequest.hasOwnProperty('publisherId')) { + bidderRequest.publisherId = (bidderRequest.publisherId).toString(); + } + + if (!ozoneRequest.test) { + delete ozoneRequest.test; + } + if (bidderRequest.gdprConsent) { + ozoneRequest.regs = {}; + ozoneRequest.regs.ext = {}; + ozoneRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; + if (ozoneRequest.regs.ext.gdpr) { + ozoneRequest.regs.ext.consent = bidderRequest.gdprConsent.consentString; + } + } + let tosendtags = validBidRequests.map(ozone => { + var obj = {}; + obj.id = ozone.bidId; + obj.tagid = String(ozone.params.ozoneid); + obj.secure = window.location.protocol === 'https:' ? 1 : 0; + obj.banner = { + topframe: 1, + w: ozone.sizes[0][0] || 0, + h: ozone.sizes[0][1] || 0, + format: ozone.sizes.map(s => { + return {w: s[0], h: s[1]}; + }) + }; + if (ozone.params.hasOwnProperty('customData')) { + obj.customData = ozone.params.customData; + } + if (ozone.params.hasOwnProperty('ozoneData')) { + obj.ozoneData = ozone.params.ozoneData; + } + if (ozone.params.hasOwnProperty('lotameData')) { + obj.lotameData = ozone.params.lotameData; + } + if (ozone.params.hasOwnProperty('publisherId')) { + obj.publisherId = (ozone.params.publisherId).toString(); + } + if (ozone.params.hasOwnProperty('siteId')) { + obj.siteId = (ozone.params.siteId).toString(); + } + obj.ext = {'prebid': {'storedrequest': {'id': (ozone.params.placementId).toString()}}}; + return obj; + }); + ozoneRequest.imp = tosendtags; + var ret = { + method: 'POST', + url: OZONEURI, + data: JSON.stringify(ozoneRequest), + bidderRequest: bidderRequest + }; + utils.logInfo(['buildRequests going to return', ret]); + return ret; + }, + getUserSyncs(optionsType, serverResponse) { + if (!serverResponse || serverResponse.length === 0) { + return []; + } + if (optionsType.iframeEnabled) { + return [{ + type: 'iframe', + url: OZONECOOKIESYNC + }]; + } + } +} + +/** + * Function matchRequest(id: string, BidRequest: object) + * @param id + * @type string + * @param bidRequest + * @type Object + * @returns Object + * + */ +export function matchRequest(id, bidRequest) { + const {bids} = bidRequest.bidderRequest; + const [returnValue] = bids.filter(bid => bid.bidId === id); + return returnValue; +} + +export function checkDeepArray(Arr) { + if (Array.isArray(Arr)) { + if (Array.isArray(Arr[0])) { + return Arr[0]; + } else { + return Arr; + } + } else { + return Arr; + } +} +export function defaultSize(thebidObj) { + const {sizes} = thebidObj; + const returnObject = {}; + returnObject.width = checkDeepArray(sizes)[0]; + returnObject.height = checkDeepArray(sizes)[1]; + return returnObject; +} +registerBidder(spec); diff --git a/modules/ozoneBidAdapter.md b/modules/ozoneBidAdapter.md new file mode 100644 index 00000000000..c013a4d558c --- /dev/null +++ b/modules/ozoneBidAdapter.md @@ -0,0 +1,45 @@ + +# Overview + +``` +Module Name: Ozone Project Bidder Adapter +Module Type: Bidder Adapter +Maintainer: engineering@ozoneproject.com + +``` + +# Description + +Module that connects to the Ozone Project's demand source(s). + +The Ozone Project bid adapter supports Banner mediaTypes ONLY. + +# Test Parameters + + +A test ad unit that will consistently return test creatives: + +``` + +//Banner adUnit + +adUnits = [{ + code: 'id-of-your-banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'ozone', + params: { + publisherId: 'OZONENUK0001', /* an ID to identify the publisher account - required */ + siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ + placementId: '0420420421', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */ + customData: {"key1": "value1", "key2": "value2}, /* optional JSON placeholder for passing publisher key-values for targeting. */ + ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ + lotameData: {"key1": "value1", "key2": "value2} /* optional JSON placeholder for passing Lotame DMP data */ + } + }] + }]; +``` diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js new file mode 100644 index 00000000000..0dcad2b0858 --- /dev/null +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -0,0 +1,454 @@ +import { expect } from 'chai'; +import { spec } from 'modules/ozoneBidAdapter'; + +const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; +const BIDDER_CODE = 'ozone'; +/* + +NOTE - use firefox console to deep copy the objects to use here + + */ +var validBidRequests = [ + { + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + bidId: '2899ec066a91ff8', + bidRequestsCount: 1, + bidder: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + sizes: [[300, 250], [300, 600]], + transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' + } +]; + +var validBidderRequest = { + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + auctionStart: 1536838908986, + bidderCode: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + bids: [{ + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + bidId: '2899ec066a91ff8', + bidRequestsCount: 1, + bidder: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + sizes: [[300, 250], [300, 600]], + transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' + }], + doneCbCallCount: 1, + start: 1536838908987, + timeout: 3000 +}; +// make sure the impid matches the request bidId +var validResponse = { + 'body': { + 'id': 'd6198807-7a53-4141-b2db-d2cb754d68ba', + 'seatbid': [ + { + 'bid': [ + { + 'id': '677903815252395017', + 'impid': '2899ec066a91ff8', + 'price': 0.5, + 'adm': '', + 'adid': '98493581', + 'adomain': [ + 'http://prebid.org' + ], + 'iurl': 'https://fra1-ib.adnxs.com/cr?id=98493581', + 'cid': '9325', + 'crid': '98493581', + 'cat': [ + 'IAB3-1' + ], + 'w': 300, + 'h': 600, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 555545, + 'auction_id': 6500448734132353000, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + } + ], + 'seat': 'appnexus' + } + ], + 'ext': { + 'responsetimemillis': { + 'appnexus': 47, + 'openx': 30 + } + }, + 'timing': { + 'start': 1536848078.089177, + 'end': 1536848078.142203, + 'TimeTaken': 0.05302619934082031 + } + }, + 'headers': {} +} + +describe('ozone Adapter', function () { + describe('isBidRequestValid', function () { + // A test ad unit that will consistently return test creatives + let validBidReq = { + bidder: BIDDER_CODE, + params: { + placementId: '1310000099', + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(validBidReq)).to.equal(true); + }); + + var validBidReq2 = { + + bidder: BIDDER_CODE, + params: { + placementId: '1310000099', + publisherId: '9876abcd12-3', + siteId: '1234567890' + }, + customData: {'gender': 'bart', 'age': 'low'}, + ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, + lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, + siteId: 1234567890 + } + + it('should return true when required params found and all optional params are valid', function () { + expect(spec.isBidRequestValid(validBidReq2)).to.equal(true); + }); + + var xEmptyPlacement = { + bidder: BIDDER_CODE, + params: { + placementId: '', + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate empty placementId', function () { + expect(spec.isBidRequestValid(xEmptyPlacement)).to.equal(false); + }); + + var xMissingPlacement = { + bidder: BIDDER_CODE, + params: { + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate missing placementId', function () { + expect(spec.isBidRequestValid(xMissingPlacement)).to.equal(false); + }); + + var xBadPlacement = { + bidder: BIDDER_CODE, + params: { + placementId: '123X45', + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate placementId with a non-numeric value', function () { + expect(spec.isBidRequestValid(xBadPlacement)).to.equal(false); + }); + + var xBadPlacementTooShort = { + bidder: BIDDER_CODE, + params: { + placementId: 123456789, /* should be exactly 10 chars */ + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate placementId with a numeric value of wrong length', function () { + expect(spec.isBidRequestValid(xBadPlacementTooShort)).to.equal(false); + }); + + var xBadPlacementTooLong = { + bidder: BIDDER_CODE, + params: { + placementId: 12345678901, /* should be exactly 10 chars */ + publisherId: '9876abcd12-3', + siteId: '1234567890' + } + }; + + it('should not validate placementId with a numeric value of wrong length', function () { + expect(spec.isBidRequestValid(xBadPlacementTooLong)).to.equal(false); + }); + + var xMissingPublisher = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + siteId: '1234567890' + } + }; + + it('should not validate missing publisherId', function () { + expect(spec.isBidRequestValid(xMissingPublisher)).to.equal(false); + }); + + var xBadPublisherTooShort = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12a', + siteId: '1234567890' + } + }; + + it('should not validate publisherId being too short', function () { + expect(spec.isBidRequestValid(xBadPublisherTooShort)).to.equal(false); + }); + + var xBadPublisherTooLong = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12abc', + siteId: '1234567890' + } + }; + + it('should not validate publisherId being too long', function () { + expect(spec.isBidRequestValid(xBadPublisherTooLong)).to.equal(false); + }); + + var publisherNumericOk = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: 123456789012, + siteId: '1234567890' + } + }; + + it('should validate publisherId being 12 digits', function () { + expect(spec.isBidRequestValid(publisherNumericOk)).to.equal(true); + }); + + var xEmptyPublisher = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '', + siteId: '1234567890' + } + }; + + it('should not validate empty publisherId', function () { + expect(spec.isBidRequestValid(xEmptyPublisher)).to.equal(false); + }); + + var xBadSite = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12-3', + siteId: '12345Z' + } + }; + + it('should not validate bad siteId', function () { + expect(spec.isBidRequestValid(xBadSite)).to.equal(false); + }); + + var xBadSiteTooLong = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12-3', + siteId: '12345678901' + } + }; + + it('should not validate siteId too long', function () { + expect(spec.isBidRequestValid(xBadSite)).to.equal(false); + }); + + var xBadSiteTooShort = { + bidder: BIDDER_CODE, + params: { + placementId: '1234567890', + publisherId: '9876abcd12-3', + siteId: '123456789' + } + }; + + it('should not validate siteId too short', function () { + expect(spec.isBidRequestValid(xBadSite)).to.equal(false); + }); + + var allNonStrings = { + bidder: BIDDER_CODE, + params: { + placementId: 1234567890, + publisherId: '9876abcd12-3', + siteId: 1234567890 + } + }; + + it('should validate all numeric values being sent as non-string numbers', function () { + expect(spec.isBidRequestValid(allNonStrings)).to.equal(true); + }); + + var emptySiteId = { + bidder: BIDDER_CODE, + params: { + placementId: 1234567890, + publisherId: '9876abcd12-3', + siteId: '' + } + }; + + it('should not validate siteId being empty string (it is required now)', function () { + expect(spec.isBidRequestValid(emptySiteId)).to.equal(false); + }); + + var xBadCustomData = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'siteId': '1234567890', + 'customData': 'this aint gonna work' + } + }; + + it('should not validate customData not being an object', function () { + expect(spec.isBidRequestValid(xBadCustomData)).to.equal(false); + }); + + var xCustomParams = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'customParams': {'info': 'this is not allowed'}, + siteId: '1234567890' + } + }; + + it('should not validate customParams being sent', function () { + expect(spec.isBidRequestValid(xCustomParams)).to.equal(false); + }); + + var xBadOzoneData = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'ozoneData': 'this should be an object', + siteId: '1234567890' + } + }; + + it('should not validate ozoneData being sent', function () { + expect(spec.isBidRequestValid(xBadOzoneData)).to.equal(false); + }); + + var xBadCustomData = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'customData': 'this should be an object', + siteId: '1234567890' + } + }; + + it('should not validate ozoneData being sent', function () { + expect(spec.isBidRequestValid(xBadCustomData)).to.equal(false); + }); + var xBadLotame = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'lotameData': 'this should be an object', + siteId: '1234567890' + } + }; + + it('should not validate lotameData being sent', function () { + expect(spec.isBidRequestValid(xBadLotame)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + it('sends bid request to OZONEURI via POST', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request.url).to.equal(OZONEURI); + expect(request.method).to.equal('POST'); + }); + + it('sends data as a string', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request.data).to.be.a('string'); + }); + + it('sends all bid parameters', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); + }); + + it('has correct bidder', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request.bidderRequest.bids[0].bidder).to.equal(BIDDER_CODE); + }); + }); + + describe('interpretResponse', function () { + it('should build bid array', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + console.log(['interpretResponse request = ', request]); + const result = spec.interpretResponse(validResponse, request); + console.log(['interpretResponse result = ', result]); + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + console.log(['Request: ', request]); + const result = spec.interpretResponse(validResponse, request); + console.log(['result[0]: ', result[0]]); + const bid = result[0]; + expect(bid.cpm).to.equal(validResponse.body.seatbid[0].bid[0].cpm); + expect(bid.width).to.equal(validResponse.body.seatbid[0].bid[0].width); + expect(bid.height).to.equal(validResponse.body.seatbid[0].bid[0].height); + }); + + it('should build bid array with gdpr', function () { + var validBidderRequestWithGdpr = validBidderRequest; + validBidderRequestWithGdpr.gdprConsent = {'gdprApplies': 1, 'consentString': 'This is the gdpr consent string'}; + const request = spec.buildRequests(validBidRequests, validBidderRequestWithGdpr); + console.log(['interpretResponse request = ', request]); + const result = spec.interpretResponse(validResponse, request); + console.log(['interpretResponse result = ', result]); + expect(result.length).to.equal(1); + }); + }); +}); From f7473c7f85fa1d1a7fa4dcb4e581ac4fa7c8f541 Mon Sep 17 00:00:00 2001 From: "Takaaki.Kojima" Date: Wed, 5 Dec 2018 04:15:21 +0900 Subject: [PATCH 0874/1594] update AdGenetation adapter (+1 squashed commit) (#3327) Squashed commits: [1b55ca0] update AdGenetation adapter --- modules/adgenerationBidAdapter.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/adgenerationBidAdapter.js b/modules/adgenerationBidAdapter.js index 340017c26cf..1ec1da3005d 100644 --- a/modules/adgenerationBidAdapter.js +++ b/modules/adgenerationBidAdapter.js @@ -75,11 +75,6 @@ export const spec = { return []; } const bidRequest = bidRequests.bidRequest; - if (!bidRequest.mediaTypes || bidRequest.mediaTypes.banner) { - if (!body.w || !body.h) { - return []; - } - } const bidResponse = { requestId: bidRequest.bidId, cpm: body.cpm || 0, @@ -91,7 +86,7 @@ export const spec = { netRevenue: true, ttl: body.ttl || 10, }; - if (bidRequest.mediaTypes && bidRequest.mediaTypes.native) { + if (isNative(body)) { bidResponse.native = createNativeAd(body); bidResponse.mediaType = NATIVE; } else { @@ -124,6 +119,11 @@ function createAd(body, bidRequest) { return ad; } +function isNative(body) { + if (!body) return false; + return body.native_ad && body.native_ad.assets.length > 0; +} + function createNativeAd(body) { let native = {}; if (body.native_ad && body.native_ad.assets.length > 0) { From d933a96974d8857d4ad566bfe53b0cc4fea4548e Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Tue, 4 Dec 2018 14:16:58 -0500 Subject: [PATCH 0875/1594] adding additional bid request validity checks. updating how we grab sizes array (#3317) * Submitting EMX Digital Prebid Adapter Submitting EMX Digital Prebid Adapter code * fixing lint errors. updating our md * updating to const/let variables. adding test spec. * fixed linting on test spec js * adding emx usersync methods * updating valid bid request checks and protocol check. * remove includes replaced with indexOf * adding more bid valid checks. updating how we grab sizes array * linting fix * code typo fixed * updated our spec --- modules/emx_digitalBidAdapter.js | 29 +++++++-- .../modules/emx_digitalBidAdapter_spec.js | 63 ++++++++++++++++++- 2 files changed, 85 insertions(+), 7 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 5638fa24e31..925c062a8cb 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -11,12 +11,25 @@ import { const BIDDER_CODE = 'emx_digital'; const ENDPOINT = 'hb.emxdgt.com'; + +let emxAdapter = {}; + +emxAdapter.validateSizes = function(sizes) { + if (!utils.isArray(sizes) || typeof sizes[0] === 'undefined') { + return false; + } + return sizes.every(size => utils.isArray(size) && size.length === 2); +} + export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], isBidRequestValid: function (bid) { - return !!bid.params.tagid && typeof bid.params.tagid === 'string' && - (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'string'); + return !!bid.params.tagid && + typeof bid.params.tagid === 'string' && + (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'string') && + bid.bidder === BIDDER_CODE && + (emxAdapter.validateSizes(bid.mediaTypes.banner.sizes) || emxAdapter.validateSizes(bid.sizes)); }, buildRequests: function (validBidRequests, bidRequests) { const {host, href, protocol} = utils.getTopWindowLocation(); @@ -29,22 +42,26 @@ export const spec = { const networkProtocol = protocol.indexOf('https') > -1 ? 1 : 0; utils._each(validBidRequests, function (bid) { - let tagId = String(utils.getBidIdParameter('tagid', bid.params)); + let tagId = utils.getBidIdParameter('tagid', bid.params); let bidFloor = parseFloat(utils.getBidIdParameter('bidfloor', bid.params)) || 0; + let sizes = bid.mediaTypes.banner.sizes; + if (!emxAdapter.validateSizes(sizes)) { + sizes = bid.sizes + } let emxBid = { id: bid.bidId, tid: bid.transactionId, tagid: tagId, secure: networkProtocol, banner: { - format: bid.sizes.map(function (size) { + format: sizes.map(function (size) { return { w: size[0], h: size[1] }; }), - w: bid.sizes[0][0], - h: bid.sizes[0][1] + w: sizes[0][0], + h: sizes[0][1] } } if (bidFloor > 0) { diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js index dd34582e22d..85256c20bd9 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -18,6 +18,14 @@ describe('emx_digital Adapter', function () { 'params': { 'tagid': '25251' }, + 'mediaTypes': { + 'banner': { + 'sizes': [ + [300, 250], + [300, 600] + ] + } + }, 'adUnitCode': 'adunit-code', 'sizes': [ [300, 250], @@ -34,16 +42,69 @@ describe('emx_digital Adapter', function () { it('should contain tagid param', function () { expect(spec.isBidRequestValid({ - params: {} + bidder: 'emx_digital', + params: {}, + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + } })).to.equal(false); expect(spec.isBidRequestValid({ + bidder: 'emx_digital', params: { tagid: '' + }, + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + bidder: 'emx_digital', + params: { + tagid: '123' + }, + mediaTypes: { + banner: { + sizes: [ + ] + } + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + bidder: 'emxdigital', + params: { + tagid: '123' + }, + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } } })).to.equal(false); expect(spec.isBidRequestValid({ + bidder: 'emx_digital', params: { tagid: '123' + }, + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } } })).to.equal(true); }); From 9e752d83515b85256b3a8c29daba14e9dfec3cfd Mon Sep 17 00:00:00 2001 From: ucfunnel <39581136+ucfunnel@users.noreply.github.com> Date: Wed, 5 Dec 2018 03:18:33 +0800 Subject: [PATCH 0876/1594] Update TTL to 30 mins (#3345) * Add a new ucfunnel Adapter and test page * Add a new ucfunnel Adapter and test page * 1. Use prebid lib in the repo to keep updated 2. Replace var with let 3. Put JSON.parse(JSON.stringify()) into try catch block * utils.getTopWindowLocation is a function * Change to modules from adapters * Migrate to module design * [Dev Fix] Remove width and height which can be got from ad unit id * Update ucfunnelBidAdapter to fit into new spec * Correct the endpoint. Fix the error of query string * Add test case for ucfunnelBidAdapter * Fix lint error * Update version number * Combine all checks on bid request * Add GDPR support for ucfunnel adapter * Add in-stream video and native support for ucfunnel adapter * Remove demo page. Add more test cases. * Change request method from POST to GET * Remove unnecessary comment * Support vastXml and vastUrl for video request * update TTL to 30 mins * Avoid using arrow function which is not discuraged in mocha --- modules/ucfunnelBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index d0ed7044242..e751dd3451c 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -68,7 +68,7 @@ export const spec = { dealId: ad.deal || null, currency: 'USD', netRevenue: true, - ttl: 1000 + ttl: 1800 }; if (ad.creative_type) { From 9271d36349e24c29c24f429ac431ab8a01a53b39 Mon Sep 17 00:00:00 2001 From: dbemiller <27972385+dbemiller@users.noreply.github.com> Date: Tue, 4 Dec 2018 14:35:08 -0500 Subject: [PATCH 0877/1594] Set the OpenRTB device dimensions (#3336) * Set the device dimensions if the config didnt do it. * add unit tests * Added a regresstion test to catch the bug. The code should still populate w and h even if the config doesnt have that object. --- modules/prebidServerBidAdapter/index.js | 9 +++++++ .../modules/prebidServerBidAdapter_spec.js | 27 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 80724630da9..165e0a6f80e 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -196,6 +196,15 @@ function _appendSiteAppDevice(request) { if (typeof config.getConfig('device') === 'object') { request.device = config.getConfig('device'); } + if (!request.device) { + request.device = {}; + } + if (!request.device.w) { + request.device.w = window.innerWidth; + } + if (!request.device.h) { + request.device.h = window.innerHeight; + } } function transformHeightWidth(adUnit) { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 15aa94ad335..77e7f3ad868 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -558,6 +558,8 @@ describe('S2S Adapter', function () { const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid.device).to.deep.equal({ ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC', + w: window.innerWidth, + h: window.innerHeight }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', @@ -581,6 +583,31 @@ describe('S2S Adapter', function () { const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid.device).to.deep.equal({ ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC', + w: window.innerWidth, + h: window.innerHeight + }); + expect(requestBid.app).to.deep.equal({ + bundle: 'com.test.app', + publisher: {'id': '1'} + }); + }); + + it('adds device.w and device.h even if the config lacks a device object', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + + const _config = { + s2sConfig: s2sConfig, + app: { bundle: 'com.test.app' }, + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.device).to.deep.equal({ + w: window.innerWidth, + h: window.innerHeight }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', From 00c955a36631642aa8035746e452d42e8b5eaec7 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 4 Dec 2018 15:04:02 -0500 Subject: [PATCH 0878/1594] removing out console.log statements in ozoneBidAdapter test file (#3349) removing out console.log statements in ozoneBidAdapter test file --- test/spec/modules/ozoneBidAdapter_spec.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index 0dcad2b0858..6b4f6c88bdd 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -424,17 +424,13 @@ describe('ozone Adapter', function () { describe('interpretResponse', function () { it('should build bid array', function () { const request = spec.buildRequests(validBidRequests, validBidderRequest); - console.log(['interpretResponse request = ', request]); const result = spec.interpretResponse(validResponse, request); - console.log(['interpretResponse result = ', result]); expect(result.length).to.equal(1); }); it('should have all relevant fields', function () { const request = spec.buildRequests(validBidRequests, validBidderRequest); - console.log(['Request: ', request]); const result = spec.interpretResponse(validResponse, request); - console.log(['result[0]: ', result[0]]); const bid = result[0]; expect(bid.cpm).to.equal(validResponse.body.seatbid[0].bid[0].cpm); expect(bid.width).to.equal(validResponse.body.seatbid[0].bid[0].width); @@ -445,9 +441,7 @@ describe('ozone Adapter', function () { var validBidderRequestWithGdpr = validBidderRequest; validBidderRequestWithGdpr.gdprConsent = {'gdprApplies': 1, 'consentString': 'This is the gdpr consent string'}; const request = spec.buildRequests(validBidRequests, validBidderRequestWithGdpr); - console.log(['interpretResponse request = ', request]); const result = spec.interpretResponse(validResponse, request); - console.log(['interpretResponse result = ', result]); expect(result.length).to.equal(1); }); }); From e8d9b1ab79865d4cae679c9c0bbc2789e3dc0228 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 4 Dec 2018 15:11:33 -0500 Subject: [PATCH 0879/1594] Prebid 1.35.0 Release --- package-lock.json | 20 ++++++++++---------- package.json | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 794b2d88c60..567516277e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.35.0-pre", + "version": "1.35.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1842,9 +1842,9 @@ } }, "big-integer": { - "version": "1.6.38", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.38.tgz", - "integrity": "sha512-csPPkI8MBCIoFAs2D7RoX9Bn5jrHwvQ/6CMfdRzwkB5cmpw74zb6Lbc/VbT9xCWrkgdwJDxw/uLIvXGch74Lhg==", + "version": "1.6.39", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.39.tgz", + "integrity": "sha512-JgwrfTfdSxDQGRPx3j9hHrag/Ih2oCQwE/kMHW5tujSyjLFLk3hbum5ZJhaginvQ2LBw2YxGgP73AquAWNW/ZA==", "dev": true }, "big.js": { @@ -2506,9 +2506,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000913", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000913.tgz", - "integrity": "sha512-PP7Ypc35XY1mNduHqweGNOp0qfNUCmaQauGOYDByvirlFjrzRyY72pBRx7jnBidOB8zclg00DAzsy2H475BouQ==", + "version": "1.0.30000914", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000914.tgz", + "integrity": "sha512-qqj0CL1xANgg6iDOybiPTIxtsmAnfIky9mBC35qgWrnK4WwmhqfpmkDYMYgwXJ8LRZ3/2jXlCntulO8mBaAgSg==", "dev": true }, "caseless": { @@ -3876,9 +3876,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.87", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.87.tgz", - "integrity": "sha512-EV5FZ68Hu+n9fHVhOc9AcG3Lvf+E1YqR36ulJUpwaQTkf4LwdvBqmGIazaIrt4kt6J8Gw3Kv7r9F+PQjAkjWeA==", + "version": "1.3.88", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.88.tgz", + "integrity": "sha512-UPV4NuQMKeUh1S0OWRvwg0PI8ASHN9kBC8yDTk1ROXLC85W5GnhTRu/MZu3Teqx3JjlQYuckuHYXSUSgtb3J+A==", "dev": true }, "elliptic": { diff --git a/package.json b/package.json index b2b883f69da..4470c824ad7 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.35.0-pre", + "version": "1.35.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 650aa3a7205b3890d9990c9282abada047bdfbaa Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 4 Dec 2018 17:14:47 -0500 Subject: [PATCH 0880/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4470c824ad7..499a0ce57bc 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.35.0", + "version": "1.33.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From f80f2d59d2e62b8ada4d3ed8518089d65276acfc Mon Sep 17 00:00:00 2001 From: Francesco Cristallo Date: Fri, 7 Dec 2018 09:41:49 -0600 Subject: [PATCH 0881/1594] Bidfluence Adapter update - Single call (#3347) * Bidfluence Adapter update Support single call to server for all bids * Bidfluence Adapter update Support single call to server for all bids - relative to adapter update --- modules/bidfluenceBidAdapter.js | 106 ++++++++++-------- .../spec/modules/bidfluenceBidAdapter_spec.js | 41 +++---- 2 files changed, 81 insertions(+), 66 deletions(-) diff --git a/modules/bidfluenceBidAdapter.js b/modules/bidfluenceBidAdapter.js index 655e52e2d6d..31c581276f1 100644 --- a/modules/bidfluenceBidAdapter.js +++ b/modules/bidfluenceBidAdapter.js @@ -36,67 +36,79 @@ export const spec = { }, buildRequests: function (validBidRequests, bidderRequest) { - return validBidRequests.map(bidRequest => { - const params = bidRequest.params; - const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; - const width = sizes.split('x')[0]; - const height = sizes.split('x')[1]; - const refInfo = bidderRequest.refererInfo; - const gdpr = bidderRequest.gdprConsent; - const body = document.getElementsByTagName('body')[0]; - const vpW = Math.max(window.innerWidth || body.clientWidth || 0) + 2; - const vpH = Math.max(window.innerHeight || body.clientHeight || 0) + 2; - const sr = screen.height > screen.width ? screen.height + 'x' + screen.width + 'x' + screen.colorDepth : screen.width + 'x' + screen.height + 'x' + screen.colorDepth; + const body = document.getElementsByTagName('body')[0]; + const refInfo = bidderRequest.refererInfo; + const gdpr = bidderRequest.gdprConsent; + const vpW = Math.max(window.innerWidth || body.clientWidth || 0) + 2; + const vpH = Math.max(window.innerHeight || body.clientHeight || 0) + 2; + const sr = screen.height > screen.width ? screen.height + 'x' + screen.width + 'x' + screen.colorDepth : screen.width + 'x' + screen.height + 'x' + screen.colorDepth; - const payload = { + var payload = { + v: '2.0', + azr: true, + ck: utils.cookiesAreEnabled(), + re: refInfo ? refInfo.referer : '', + st: refInfo ? refInfo.stack : [], + tz: getBdfTz(new Date()), + sr: sr, + tm: bidderRequest.timeout, + vp: vpW + 'x' + vpH, + sdt: getUTCDate(), + top: refInfo ? refInfo.reachedTop : false, + gdpr: gdpr ? gdpr.gdprApplies : false, + gdprc: gdpr ? gdpr.consentString : '', + bids: [] + }; + + utils._each(validBidRequests, function (bidRequest) { + var params = bidRequest.params; + var sizes = utils.parseSizesInput(bidRequest.sizes)[0]; + var width = sizes.split('x')[0]; + var height = sizes.split('x')[1]; + + var currentBidPayload = { bid: bidRequest.bidId, - v: '1.0', - azr: true, - ck: utils.cookiesAreEnabled(), tid: params.placementId, pid: params.publisherId, rp: params.reservePrice || 0, - re: refInfo ? refInfo.referer : '', - st: refInfo ? refInfo.stack : [], - tz: getBdfTz(new Date()), - sr: sr, - tm: bidderRequest.timeout, - vp: vpW + 'x' + vpH, - sdt: getUTCDate(), w: width, - h: height, - gdpr: gdpr ? gdpr.gdprApplies : false, - gdprc: gdpr ? gdpr.consentString : '' - }; - const payloadString = JSON.stringify(payload); - return { - method: 'POST', - url: `//${payload.pid}.bidfluence.com/Hb`, - data: payloadString, - options: { contentType: 'text/plain' } + h: height }; + + payload.bids.push(currentBidPayload); }); + + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: `//bdf${payload.bids[0].pid}.bidfluence.com/Prebid`, + data: payloadString, + options: { contentType: 'text/plain' } + }; }, interpretResponse: function (serverResponse, bidRequest) { const bidResponses = []; const response = serverResponse.body; - const cpm = response.Cpm || 0; - if (cpm > 0) { - const bidResponse = { - requestId: response.BidId, - cpm: cpm, - width: response.Width, - height: response.Height, - creativeId: response.CreativeId, - ad: response.Ad, - currency: 'USD', - netRevenue: true, - ttl: 360 - }; - bidResponses.push(bidResponse); - } + utils._each(response.Bids, function (currentResponse) { + var cpm = currentResponse.Cpm || 0; + + if (cpm > 0) { + const bidResponse = { + requestId: currentResponse.BidId, + cpm: cpm, + width: currentResponse.Width, + height: currentResponse.Height, + creativeId: currentResponse.CreativeId, + ad: currentResponse.Ad, + currency: 'USD', + netRevenue: true, + ttl: 360 + }; + bidResponses.push(bidResponse); + } + }); return bidResponses; }, diff --git a/test/spec/modules/bidfluenceBidAdapter_spec.js b/test/spec/modules/bidfluenceBidAdapter_spec.js index 71471c6650b..9ce6e808c6b 100644 --- a/test/spec/modules/bidfluenceBidAdapter_spec.js +++ b/test/spec/modules/bidfluenceBidAdapter_spec.js @@ -54,25 +54,25 @@ describe('Bidfluence Adapter test', () => { const request = spec.buildRequests(validBidRequests, bidderRequest); it('sends bid request to our endpoint via POST', function () { - expect(request[0].method).to.equal('POST'); + expect(request.method).to.equal('POST'); }); - const payload = JSON.parse(request[0].data); + const payload = JSON.parse(request.data); - expect(payload.bid).to.equal(validBidRequests[0].bidId); + expect(payload.bids[0].bid).to.equal(validBidRequests[0].bidId); expect(payload.azr).to.equal(true); expect(payload.ck).to.not.be.undefined; - expect(payload.tid).to.equal(PLACEMENT_ID); - expect(payload.pid).to.equal(PUB_ID); - expect(payload.rp).to.be.a('number'); + expect(payload.bids[0].tid).to.equal(PLACEMENT_ID); + expect(payload.bids[0].pid).to.equal(PUB_ID); + expect(payload.bids[0].rp).to.be.a('number'); expect(payload.re).to.not.be.undefined; expect(payload.st).to.not.be.undefined; expect(payload.tz).to.not.be.undefined; expect(payload.sr).to.not.be.undefined; expect(payload.vp).to.not.be.undefined; expect(payload.sdt).to.not.be.undefined; - expect(payload.w).to.equal('300'); - expect(payload.h).to.equal('250'); + expect(payload.bids[0].w).to.equal('300'); + expect(payload.bids[0].h).to.equal('250'); it('sends gdpr info if exists', function () { expect(payload.gdpr).to.equal(true); @@ -83,22 +83,25 @@ describe('Bidfluence Adapter test', () => { describe('interpretResponse', function () { const response = { body: { - 'CreativeId': '1000', - 'Cpm': 0.50, - 'Ad': '
', - 'Height': 250, - 'Width': 300 + Bids: + [{ + 'CreativeId': '1000', + 'Cpm': 0.50, + 'Ad': '
', + 'Height': 250, + 'Width': 300 + }] } }; it('should get correct bid response', function () { const expectedResponse = [{ - requestId: response.body.BidId, - cpm: response.body.Cpm, - width: response.body.Width, - height: response.body.Height, - creativeId: response.body.CreativeId, - ad: response.body.Ad, + requestId: response.body.Bids[0].BidId, + cpm: response.body.Bids[0].Cpm, + width: response.body.Bids[0].Width, + height: response.body.Bids[0].Height, + creativeId: response.body.Bids[0].CreativeId, + ad: response.body.Bids[0].Ad, currency: 'USD', netRevenue: true, ttl: 360 From 3b7f4621977e6142deb90612cf94a9c6bb177541 Mon Sep 17 00:00:00 2001 From: susyt Date: Fri, 7 Dec 2018 08:33:20 -0800 Subject: [PATCH 0882/1594] conditionally adds another param to browserParams (#3355) * conditionally adds another param to browserParams * fixes lint error --- modules/gumgumBidAdapter.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 33baaf83548..9702eb14f0c 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -19,6 +19,12 @@ function _getBrowserParams() { 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 // 1 megabit -> 1024 kilobits + } if (browserParams.vw) { // we've already initialized browserParams, just return it. return browserParams @@ -41,11 +47,14 @@ function _getBrowserParams() { pu: topUrl, ce: utils.cookiesAreEnabled(), dpr: topWindow.devicePixelRatio || 1, - jcsi: { - t: 0, - rq: 7 - } + jcsi: JSON.stringify({ t: 0, rq: 7 }) } + + ns = getNetworkSpeed() + if (ns) { + browserParams.ns = ns + } + ggad = (topUrl.match(/#ggad=(\w+)$/) || [0, 0])[1] if (ggad) { browserParams[isNaN(ggad) ? 'eAdBuyId' : 'adBuyId'] = ggad From ca6991268f42dae81ad5c015d3dbbca1de6e40de Mon Sep 17 00:00:00 2001 From: afsheenb Date: Fri, 7 Dec 2018 13:00:32 -0500 Subject: [PATCH 0883/1594] enable ozone to support multiple bid responses (#3354) --- modules/ozoneBidAdapter.js | 97 ++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 36 deletions(-) diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index 1907b74ee02..5ef5d7058b6 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -64,49 +64,30 @@ export const spec = { return true; }, /** + * Interpret the response if the array contains BIDDER elements, in the format: [ [bidder1 bid 1, bidder1 bid 2], [bidder2 bid 1, bidder2 bid 2] ] * @param serverResponse * @param request * @returns {*} */ interpretResponse(serverResponse, request) { + utils.logInfo('ozone interpretResponse version 2018-12-05 16:46'); serverResponse = serverResponse.body || {}; if (serverResponse.seatbid) { if (utils.isArray(serverResponse.seatbid)) { - const {seatbid: arrSeatbid} = serverResponse; - let winnerAds = arrSeatbid.reduce((bid, ads) => { - var _seat = ads.seat; - let ad = ads.bid.reduce(function(currentWinningBid, considerBid) { - if (currentWinningBid.price < considerBid.price) { - const bid = matchRequest(considerBid.impid, request); - const {width, height} = defaultSize(bid); - considerBid.cpm = considerBid.price; - considerBid.bidId = considerBid.impid; - considerBid.requestId = considerBid.impid; - considerBid.width = considerBid.w || width; - considerBid.height = considerBid.h || height; - considerBid.ad = considerBid.adm; - considerBid.netRevenue = true; - considerBid.creativeId = considerBid.crid; - considerBid.currency = 'USD'; - considerBid.ttl = 60; - considerBid.seat = _seat; - - return considerBid; - } else { - currentWinningBid.cpm = currentWinningBid.price; - return currentWinningBid; - } - }, {price: 0}); - if (ad.adm) { - bid.push(ad) - } - return bid; - }, []) - let winnersClean = winnerAds.filter(w => { - if (w.bidId) { - return true; + // serverResponse seems good, let's get the list of bids from the request object: + let arrRequestBids = request.bidderRequest.bids; + // build up a list of winners, one for each bidId in arrBidIds + let arrWinners = []; + for (let i = 0; i < arrRequestBids.length; i++) { + let winner = ozoneGetWinnerForRequestBid(arrRequestBids[i], serverResponse.seatbid); + if (winner !== null) { + const {defaultWidth, defaultHeight} = defaultSize(arrRequestBids[i]); + winner = ozoneAddStandardProperties(winner, defaultWidth, defaultHeight); + arrWinners.push(winner); } - return false; + } + let winnersClean = arrWinners.filter(w => { + return (w.bidId); // will be cast to boolean }); utils.logInfo(['going to return winnersClean:', winnersClean]); return winnersClean; @@ -184,6 +165,7 @@ export const spec = { utils.logInfo(['buildRequests going to return', ret]); return ret; }, + getUserSyncs(optionsType, serverResponse) { if (!serverResponse || serverResponse.length === 0) { return []; @@ -226,8 +208,51 @@ export function checkDeepArray(Arr) { export function defaultSize(thebidObj) { const {sizes} = thebidObj; const returnObject = {}; - returnObject.width = checkDeepArray(sizes)[0]; - returnObject.height = checkDeepArray(sizes)[1]; + returnObject.defaultWidth = checkDeepArray(sizes)[0]; + returnObject.defaultHeight = checkDeepArray(sizes)[1]; return returnObject; } + +/** + * Do the messy searching for the best bid response in the serverResponse.seatbid array matching the requestBid.bidId + * @param requestBid + * @param serverResponseSeatBid + * @returns {*} bid object + */ +export function ozoneGetWinnerForRequestBid(requestBid, serverResponseSeatBid) { + let thisBidWinner = null; + for (let j = 0; j < serverResponseSeatBid.length; j++) { + let theseBids = serverResponseSeatBid[j].bid; + let thisSeat = serverResponseSeatBid[j].seat; + for (let k = 0; k < theseBids.length; k++) { + if (theseBids[k].impid === requestBid.bidId) { // we've found a matching server response bid for this request bid + if ((thisBidWinner == null) || (thisBidWinner.price < theseBids[k].price)) { + thisBidWinner = theseBids[k]; + thisBidWinner.seat = thisSeat; // we need to add this here - it's the name of the winning bidder, not guaranteed to be available in the bid object. + } + } + } + } + return thisBidWinner; +} + +/** + * We expect to be able to find a standard set of properties on winning bid objects; add them here. + * @param seatBid + * @returns {*} + */ +export function ozoneAddStandardProperties(seatBid, defaultWidth, defaultHeight) { + seatBid.cpm = seatBid.price; + seatBid.bidId = seatBid.impid; + seatBid.requestId = seatBid.impid; + seatBid.width = seatBid.w || defaultWidth; + seatBid.height = seatBid.h || defaultHeight; + seatBid.ad = seatBid.adm; + seatBid.netRevenue = true; + seatBid.creativeId = seatBid.crid; + seatBid.currency = 'USD'; + seatBid.ttl = 60; + return seatBid; +} + registerBidder(spec); From efc28ad0215f7ddda1563811cb5de91f7dfad005 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Fri, 7 Dec 2018 14:22:27 -0500 Subject: [PATCH 0884/1594] increment to correct pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 499a0ce57bc..2445032536c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.33.0-pre", + "version": "1.36.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 8fa2a8402d632a04d10208be0a609f83dd14d3bf Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Fri, 7 Dec 2018 16:21:10 -0500 Subject: [PATCH 0885/1594] update unit test example to mocha recommendations (#3361) * update unit test example to mocha recommendations * fix formatting --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7f4127cf3ba..b82b249fa36 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,8 +64,8 @@ A test module might have the following general structure: import { expect } from 'chai'; // may prefer 'assert' in place of 'expect' import adapter from 'src/adapters/'; -describe('', () => { - it('', () => { +describe('', function () { + it('', function () { // Arrange - set up preconditions and inputs // Act - call or act on the code under test // Assert - use chai to check that expected results have occurred From 522a0ce8b119e574dabe4870700db9dd701e8dc3 Mon Sep 17 00:00:00 2001 From: Vishalrkanse <43662192+Vishalrkanse@users.noreply.github.com> Date: Sat, 8 Dec 2018 02:40:48 +0300 Subject: [PATCH 0886/1594] Supply2 Bid Adapter (#3335) * Added Supply2 Bid Adapter with spec file * Supply2BidAdapter: fix typo --- modules/supply2BidAdapter.js | 166 ++++++++++ modules/supply2BidAdapter.md | 40 +++ test/spec/modules/supply2BidAdapter_spec.js | 332 ++++++++++++++++++++ 3 files changed, 538 insertions(+) create mode 100644 modules/supply2BidAdapter.js create mode 100755 modules/supply2BidAdapter.md create mode 100644 test/spec/modules/supply2BidAdapter_spec.js diff --git a/modules/supply2BidAdapter.js b/modules/supply2BidAdapter.js new file mode 100644 index 00000000000..b8951d96759 --- /dev/null +++ b/modules/supply2BidAdapter.js @@ -0,0 +1,166 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'supply2'; +const ENDPOINT_URL = '//pool.supply2.com/hb'; +const TIME_TO_LIVE = 360; +const ADAPTER_SYNC_URL = '//pool.supply2.com/push_sync'; +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', + noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', + emptyUids: 'Uids should be not empty', + emptySeatbid: 'Seatbid array from response has empty item', + emptyResponse: 'Response is empty', + hasEmptySeatbidArray: 'Response has empty seatbid array', + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' +}; +export const spec = { + code: BIDDER_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 !!bid.params.uid; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests - an array of bids + * @param {bidderRequest} bidderRequest - bidder request object + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + const auids = []; + const bidsMap = {}; + const bids = validBidRequests || []; + let priceType = 'net'; + let reqId; + + bids.forEach(bid => { + if (bid.params.priceType === 'gross') { + priceType = 'gross'; + } + reqId = bid.bidderRequestId; + if (!bidsMap[bid.params.uid]) { + bidsMap[bid.params.uid] = [bid]; + auids.push(bid.params.uid); + } else { + bidsMap[bid.params.uid].push(bid); + } + }); + + const payload = { + u: utils.getTopWindowUrl(), + pt: priceType, + auids: auids.join(','), + r: reqId + }; + + if (bidderRequest) { + 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; + } + } + + return { + method: 'GET', + url: ENDPOINT_URL, + data: utils.parseQueryStringParameters(payload).replace(/\&$/, ''), + bidsMap: bidsMap, + }; + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param {*} bidRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidRequest) { + serverResponse = serverResponse && serverResponse.body; + const bidResponses = []; + const bidsMap = bidRequest.bidsMap; + const priceType = bidRequest.data.pt; + + let errorMessage; + + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } + + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses); + }); + } + if (errorMessage) utils.logError(errorMessage); + return bidResponses; + }, + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: ADAPTER_SYNC_URL + }]; + } + } +} + +function _getBidFromResponse(respItem) { + if (!respItem) { + utils.logError(LOG_ERROR_MESS.emptySeatbid); + } else if (!respItem.bid) { + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + } else if (!respItem.bid[0]) { + utils.logError(LOG_ERROR_MESS.noBid); + } + return respItem && respItem.bid && respItem.bid[0]; +} + +function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { + if (!serverBid) return; + let errorMessage; + if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + awaitingBids.forEach(bid => { + const bidResponse = { + requestId: bid.bidId, // bid.bidderRequestId, + bidderCode: spec.code, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, // bid.bidId, + currency: 'USD', + netRevenue: priceType !== 'gross', + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid + }; + bidResponses.push(bidResponse); + }); + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } + if (errorMessage) { + utils.logError(errorMessage); + } +} + +registerBidder(spec); diff --git a/modules/supply2BidAdapter.md b/modules/supply2BidAdapter.md new file mode 100755 index 00000000000..3d86f065abf --- /dev/null +++ b/modules/supply2BidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +Module Name: Supply2 Bidder Adapter +Module Type: Bidder Adapter +Maintainer: vishal@mediadonuts.com + +# Description + +Module that connects to Media Donuts demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "supply2", + params: { + uid: '23', + priceType: 'gross' // by default is 'net' + } + } + ] + },{ + code: 'test-div', + sizes: [[728, 90]], + bids: [ + { + bidder: "supply2", + params: { + uid: 24, + priceType: 'gross' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/supply2BidAdapter_spec.js b/test/spec/modules/supply2BidAdapter_spec.js new file mode 100644 index 00000000000..8abbecd801c --- /dev/null +++ b/test/spec/modules/supply2BidAdapter_spec.js @@ -0,0 +1,332 @@ +import { expect } from 'chai'; +import { spec } from 'modules/supply2BidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('Supply2Adapter', 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': 'supply2', + 'params': { + 'uid': '16' + }, + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'uid': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + function parseRequest(url) { + const res = {}; + url.split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } + let bidRequests = [ + { + 'bidder': 'supply2', + 'params': { + 'uid': '16' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'supply2', + 'params': { + 'uid': '16' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'supply2', + 'params': { + 'uid': '17' + }, + '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]]); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '16'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + }); + + it('auids must not be duplicated', function () { + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '16,17'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + }); + + it('if timeout is present, payload must have wtimeout parameter', function () { + const request = spec.buildRequests(bidRequests, {timeout: 2000}); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('wtimeout', '2000'); + }); + + it('pt parameter must be "gross" if params.priceType === "gross"', function () { + bidRequests[1].params.priceType = 'gross'; + const request = spec.buildRequests(bidRequests); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'gross'); + expect(payload).to.have.property('auids', '16,17'); + 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); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); + expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('pt', 'net'); + expect(payload).to.have.property('auids', '16,17'); + expect(payload).to.have.property('r', '22edbae2733bf6'); + delete bidRequests[1].params.priceType; + }); + + it('if gdprConsent is present payload must have gdpr params', function () { + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); + 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 request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); + 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 request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); + 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'); + }); + }); + + describe('interpretResponse', function () { + const responses = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 23, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 24, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 25, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + undefined, + {'bid': [], 'seat': '1'}, + {'seat': '1'}, + ]; + + it('should get correct bid response', function () { + const bidRequests = [ + { + 'bidder': 'supply2', + 'params': { + 'uid': '23' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 23, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'supply2', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should get correct multi bid response', function () { + const bidRequests = [ + { + 'bidder': 'supply2', + 'params': { + 'uid': '23' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71a5b', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'supply2', + 'params': { + 'uid': '24' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dff80cc4ee346', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'supply2', + 'params': { + 'uid': '23' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '5703af74d0472a', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '300bfeb0d71a5b', + 'cpm': 1.15, + 'creativeId': 23, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'supply2', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '5703af74d0472a', + 'cpm': 1.15, + 'creativeId': 23, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'supply2', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 24, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 2
', + 'bidderCode': 'supply2', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('handles wrong and nobid responses', function () { + const bidRequests = [ + { + 'bidder': 'supply2', + 'params': { + 'uid': '25' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d7190gf', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'supply2', + 'params': { + 'uid': '26' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71321', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'supply2', + 'params': { + 'uid': '27' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '300bfeb0d7183bb', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + } + ]; + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + expect(result.length).to.equal(0); + }); + }); +}); From 13182f7a22f800090b8fa17a12d47f676343c7fa Mon Sep 17 00:00:00 2001 From: Manasi Date: Sat, 8 Dec 2018 05:23:10 +0530 Subject: [PATCH 0887/1594] Dctr fixes (#3337) * changes to not show dctr message when none of the adunits have dctr set * added usage description for dctr and currency params --- modules/pubmaticBidAdapter.js | 40 ++++++++++++++++++----------------- modules/pubmaticBidAdapter.md | 4 ++-- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 7203cee2391..eb8a082f61f 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -449,29 +449,31 @@ export const spec = { payload.site.domain = _getDomainFromURL(payload.site.page); // set dctr value in site.ext, if present in validBidRequests[0], else ignore - if (validBidRequests[0].params.hasOwnProperty('dctr')) { - dctr = validBidRequests[0].params.dctr; - if (utils.isStr(dctr) && dctr.length > 0) { - var arr = dctr.split('|'); - dctr = ''; - arr.forEach(val => { - dctr += (val.length > 0) ? (val.trim() + '|') : ''; - }); - dctrLen = dctr.length; - if (dctr.substring(dctrLen, dctrLen - 1) === '|') { - dctr = dctr.substring(0, dctrLen - 1); + if (dctrArr.length > 0) { + if (validBidRequests[0].params.hasOwnProperty('dctr')) { + dctr = validBidRequests[0].params.dctr; + if (utils.isStr(dctr) && dctr.length > 0) { + var arr = dctr.split('|'); + dctr = ''; + arr.forEach(val => { + dctr += (val.length > 0) ? (val.trim() + '|') : ''; + }); + dctrLen = dctr.length; + if (dctr.substring(dctrLen, dctrLen - 1) === '|') { + dctr = dctr.substring(0, dctrLen - 1); + } + payload.site.ext = { + key_val: dctr.trim() + } + } else { + utils.logWarn(BIDDER_CODE + ': Ignoring param : dctr with value : ' + dctr + ', expects string-value, found empty or non-string value'); } - payload.site.ext = { - key_val: dctr.trim() + if (dctrArr.length > 1) { + utils.logWarn(BIDDER_CODE + ': dctr value found in more than 1 adunits. Value from 1st adunit will be picked. Ignoring values from subsequent adunits'); } } else { - utils.logWarn(BIDDER_CODE + ': Ignoring param : dctr with value : ' + dctr + ', expects string-value, found empty or non-string value'); - } - if (dctrArr.length > 1) { - utils.logWarn(BIDDER_CODE + ': dctr value found in more than 1 adunits. Value from 1st adunit will be picked. Ignoring values from subsequent adunits'); + utils.logWarn(BIDDER_CODE + ': dctr value not found in 1st adunit, ignoring values from subsequent adunits'); } - } else { - utils.logWarn(BIDDER_CODE + ': dctr value not found in 1st adunit, ignoring values from subsequent adunits'); } _handleEids(payload); diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 86d59d333f0..3f28d4586e7 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -33,8 +33,8 @@ var adUnits = [ kadpageurl: 'www.test.com', // optional gender: 'M', // optional kadfloor: '0.50', // optional - currency: 'AUD' // optional - dctr: 'key1=123|key2=345' // optional + currency: 'AUD' // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) + dctr: 'key1=123|key2=345' // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) } }] }]; From 5a2282eb7445841dcdf36678c4bf50a9240c27ca Mon Sep 17 00:00:00 2001 From: edahood-sonobi Date: Mon, 10 Dec 2018 10:26:17 -0500 Subject: [PATCH 0888/1594] Added publisher common ID support to sonobi adapter. (#3363) --- modules/sonobiBidAdapter.js | 7 +++--- test/spec/modules/sonobiBidAdapter_spec.js | 26 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index a65657ec13a..ce925eacc51 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -1,5 +1,5 @@ import { registerBidder } from 'src/adapters/bidderFactory'; -import { parseSizesInput, logError, generateUUID, isEmpty } from '../src/utils'; +import { parseSizesInput, logError, generateUUID, isEmpty, deepAccess } from '../src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; import { config } from '../src/config'; @@ -59,9 +59,10 @@ export const spec = { payload.us = config.getConfig('userSync').syncsPerBidder; } - if (validBidRequests[0].params.hfa) { - payload.hfa = validBidRequests[0].params.hfa; + if (deepAccess(validBidRequests[0], 'crumbs.pubcid') || deepAccess(validBidRequests[0], 'params.hfa')) { + payload.hfa = deepAccess(validBidRequests[0], 'params.hfa') ? deepAccess(validBidRequests[0], 'params.hfa') : `PRE-${deepAccess(validBidRequests[0], 'crumbs.pubcid')}`; } + if (validBidRequests[0].params.referrer) { payload.ref = validBidRequests[0].params.referrer; } diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 593b885176e..463067ffa8a 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -236,6 +236,32 @@ describe('SonobiBidAdapter', function () { const bidRequests = spec.buildRequests([{params: {}}], bidderRequests) expect(bidRequests).to.equal(null); }) + + it('should return a properly formatted request with commonid as hfa', function () { + delete bidRequest[0].params.hfa; + delete bidRequest[1].params.hfa; + bidRequest[0].crumbs = {'pubcid': 'abcd-efg-0101'}; + bidRequest[1].crumbs = {'pubcid': 'abcd-efg-0101'}; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.ref).not.to.be.empty + expect(bidRequests.data.s).not.to.be.empty + expect(bidRequests.data.hfa).to.equal('PRE-abcd-efg-0101'); + }) + + it('should return a properly formatted request with hfa preferred over commonid', function () { + bidRequest[0].params.hfa = 'hfakey'; + bidRequest[1].params.hfa = 'hfakey'; + bidRequest[0].crumbs = {'pubcid': 'abcd-efg-0101'}; + bidRequest[1].crumbs = {'pubcid': 'abcd-efg-0101'}; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.ref).not.to.be.empty + expect(bidRequests.data.s).not.to.be.empty + expect(bidRequests.data.hfa).to.equal('hfakey') + }) }) describe('.interpretResponse', function () { From 239f180a79d06190b4ba5813dcef3acbd1e17b02 Mon Sep 17 00:00:00 2001 From: Andrew Bowman Date: Mon, 10 Dec 2018 11:53:40 -0500 Subject: [PATCH 0889/1594] adding native parameters: body2, rating, privacyLink (#3348) --- modules/appnexusBidAdapter.js | 5 +++++ src/constants.json | 5 ++++- test/spec/modules/appnexusBidAdapter_spec.js | 10 ++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 1e77dfce564..fa6a888601b 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -13,6 +13,7 @@ const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'langua const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately const NATIVE_MAPPING = { body: 'description', + body2: 'desc2', cta: 'ctatext', image: { serverName: 'main_image', @@ -25,6 +26,7 @@ const NATIVE_MAPPING = { minimumParams: { sizes: [{}] }, }, sponsoredBy: 'sponsored_by', + privacyLink: 'privacy_link' }; const SOURCE = 'pbjs'; @@ -283,8 +285,11 @@ function newBid(serverBid, rtbBid, bidderRequest) { bid[NATIVE] = { title: nativeAd.title, body: nativeAd.desc, + body2: nativeAd.desc2, cta: nativeAd.ctatext, + rating: nativeAd.rating, sponsoredBy: nativeAd.sponsored, + privacyLink: nativeAd.privacy_link, clickUrl: nativeAd.link.url, clickTrackers: nativeAd.link.click_trackers, impressionTrackers: nativeAd.impression_trackers, diff --git a/src/constants.json b/src/constants.json index 7c06db48469..768e073b625 100644 --- a/src/constants.json +++ b/src/constants.json @@ -67,11 +67,14 @@ "NATIVE_KEYS": { "title": "hb_native_title", "body": "hb_native_body", + "body2": "hb_native_body2", + "privacyLink": "hb_native_privacy", "sponsoredBy": "hb_native_brand", "image": "hb_native_image", "icon": "hb_native_icon", "clickUrl": "hb_native_linkurl", - "cta": "hb_native_cta" + "cta": "hb_native_cta", + "rating": "hb_native_rating" }, "S2S" : { "SRC" : "s2s", diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 08e5f35cb8d..677b45b95a9 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -179,9 +179,12 @@ describe('AppNexusAdapter', function () { nativeParams: { title: {required: true}, body: {required: true}, + body2: {required: true}, image: {required: true, sizes: [{ width: 100, height: 100 }]}, cta: {required: false}, - sponsoredBy: {required: true} + rating: {required: true}, + sponsoredBy: {required: true}, + privacyLink: {required: true} } } ); @@ -192,9 +195,12 @@ describe('AppNexusAdapter', function () { 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 }]}, ctatext: {required: false}, - sponsored_by: {required: true} + rating: {required: true}, + sponsored_by: {required: true}, + privacy_link: {required: true} }); }); From f424cd2c74b28159cc31134536f037cecdd267b8 Mon Sep 17 00:00:00 2001 From: Gena Date: Mon, 10 Dec 2018 18:52:39 +0100 Subject: [PATCH 0890/1594] Add user sync pixel logic in Adtelligent adapter (#3359) * Add user sync pixel logic in Adtelligent adapter * Add gdpr support * Add gdpr support * Update tests --- modules/adtelligentBidAdapter.js | 37 ++++++++++++++++++- .../modules/adtelligentBidAdapter_spec.js | 37 ++++++++++++++++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/modules/adtelligentBidAdapter.js b/modules/adtelligentBidAdapter.js index 65181c70ed9..95087b56f21 100644 --- a/modules/adtelligentBidAdapter.js +++ b/modules/adtelligentBidAdapter.js @@ -17,7 +17,35 @@ export const spec = { isBidRequestValid: function (bid) { return bid && bid.params && bid.params.aid; }, + getUserSyncs: function (syncOptions, serverResponses) { + var syncs = []; + + function addSyncs(_s) { + if (_s && _s.length) { + _s.forEach(s => { + syncs.push({ + type: 'image', + url: s + }) + }) + } + } + if (syncOptions.pixelEnabled) { + serverResponses && serverResponses.length && serverResponses.forEach((response) => { + if (response.body) { + if (utils.isArray(response.body)) { + response.body.forEach(b => { + addSyncs(b.cookieURLs); + }) + } else { + addSyncs(response.body.cookieURLs) + } + } + }) + } + return syncs; + }, /** * Make a server request from the list of BidRequests * @param bidRequests @@ -25,7 +53,7 @@ export const spec = { */ buildRequests: function (bidRequests, bidderRequest) { return { - data: bidToTag(bidRequests), + data: bidToTag(bidRequests, bidderRequest), bidderRequest, method: 'GET', url: URL @@ -83,11 +111,16 @@ function parseRTBResponse(serverResponse, bidderRequest) { return bids; } -function bidToTag(bidRequests) { +function bidToTag(bidRequests, bidderRequest) { let tag = { domain: utils.getTopWindowLocation().hostname }; + if (bidderRequest && bidderRequest.gdprConsent) { + tag.gdpr = 1; + tag.gdpr_consent = bidderRequest.gdprConsent.consentString; + } + for (let i = 0, length = bidRequests.length; i < length; i++) { Object.assign(tag, prepareRTBRequestParams(i, bidRequests[i])); } diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js index 6190f53fdc4..0ee2bb2726f 100644 --- a/test/spec/modules/adtelligentBidAdapter_spec.js +++ b/test/spec/modules/adtelligentBidAdapter_spec.js @@ -46,6 +46,7 @@ const SERVER_VIDEO_RESPONSE = { } ] }; + const SERVER_DISPLAY_RESPONSE = { 'source': {'aid': 12345, 'pubId': 54321}, 'bids': [{ @@ -57,7 +58,8 @@ const SERVER_DISPLAY_RESPONSE = { 'cur': 'USD', 'width': 300, 'cpm': 0.9 - }] + }], + 'cookieURLs': ['link1', 'link2'] }; const videoBidderRequest = { @@ -70,6 +72,14 @@ const displayBidderRequest = { bids: [{bidId: '2e41f65424c87c'}] }; +const displayBidderRequestWithGdpr = { + bidderCode: 'bidderCode', + bids: [{bidId: '2e41f65424c87c'}], + gdprConsent: { + consentString: 'test' + } +}; + const videoEqResponse = [{ vastUrl: 'http://rtb.adtelligent.com/vast/?adid=44F2AEB9BFC881B3', requestId: '2e41f65424c87c', @@ -96,9 +106,25 @@ const displayEqResponse = [{ cpm: 0.9 }]; -describe('adtelligentBidAdapter', function () { +describe('adtelligentBidAdapter', function () { // todo remove only const adapter = newBidder(spec); + describe('user syncs', function () { + it('should be returned if pixel enabled', function () { + const syncs = spec.getUserSyncs({pixelEnabled: true}, [{body: SERVER_DISPLAY_RESPONSE}]); + + expect(syncs.map(s => s.url)).to.deep.equal(SERVER_DISPLAY_RESPONSE.cookieURLs); + }) + }) + + describe('user syncs', function () { + it('should not be returned if pixel not set', function () { + const syncs = spec.getUserSyncs({}, [{body: SERVER_DISPLAY_RESPONSE}]); + + expect(syncs).to.be.empty; + }) + }) + describe('inherited functions', function () { it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); @@ -212,6 +238,13 @@ describe('adtelligentBidAdapter', function () { bidServerResponseCheck(); }); + it('should set gdpr data correctly', function () { + const builtRequestData = spec.buildRequests([DISPLAY_REQUEST], displayBidderRequestWithGdpr); + + expect(builtRequestData.data.gdpr).to.be.equal(1); + expect(builtRequestData.data.gdpr_consent).to.be.equal(displayBidderRequestWithGdpr.gdprConsent.consentString); + }); + function bidServerResponseCheck() { const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); From 88156e7026306f703c30ec032f6b422174b221d5 Mon Sep 17 00:00:00 2001 From: Andrew Bowman Date: Mon, 10 Dec 2018 17:53:41 -0500 Subject: [PATCH 0891/1594] AppNexus debug auction via cookie (#3314) * updating appnexus debug auction to be cookie-only * adding getCookie to utils * remove LGTM alert on getCookie * fix failed tests --- modules/appnexusBidAdapter.js | 52 +++++++++++++++++++++++++++++++++++ src/utils.js | 5 ++++ 2 files changed, 57 insertions(+) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index fa6a888601b..77a27376bbb 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -11,6 +11,7 @@ const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', 'startdelay', 'skippable', 'playback_method', 'frameworks']; const USER_PARAMS = ['age', 'external_uid', '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 NATIVE_MAPPING = { body: 'description', body2: 'desc2', @@ -79,6 +80,32 @@ export const spec = { }; } + let debugObj = {}; + let debugObjParams = {}; + const debugCookieName = 'apn_prebid_debug'; + const debugCookie = utils.getCookie(debugCookieName) || null; + + if (debugCookie) { + try { + debugObj = JSON.parse(debugCookie); + } catch (e) { + utils.logError('AppNexus Debug Auction Cookie Error:\n\n' + e); + } + } else { + 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; @@ -101,6 +128,11 @@ export const spec = { payload.app = appIdObj; } + if (debugObjParams.enabled) { + payload.debug = debugObjParams; + utils.logInfo('AppNexus 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 = { @@ -156,6 +188,22 @@ export const spec = { } }); } + + 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 + utils.logMessage('https://console.appnexus.com/docs/understanding-the-debug-auction'); + utils.logMessage(debugText); + } + return bids; }, @@ -458,6 +506,10 @@ function hasAppId(bid) { return !!bid.params.app } +function hasDebug(bid) { + return !!bid.debug +} + function getRtbBid(tag) { return tag && tag.ads && tag.ads.length && find(tag.ads, ad => ad.rtb); } diff --git a/src/utils.js b/src/utils.js index 7d9424f8489..a769f588691 100644 --- a/src/utils.js +++ b/src/utils.js @@ -846,6 +846,11 @@ export function cookiesAreEnabled() { return window.document.cookie.indexOf('prebid.cookieTest') != -1; } +export function getCookie(name) { + let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); + return m ? decodeURIComponent(m[2]) : null; +} + /** * Given a function, return a function which only executes the original after * it's been called numRequiredCalls times. From 4c1f69057901a62b8a5064d71d757581be7d7994 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 13 Dec 2018 10:07:08 -0500 Subject: [PATCH 0892/1594] fix bug when syncsPerBidder was set to 0 (#3360) --- src/userSync.js | 2 +- test/spec/userSync_spec.js | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/userSync.js b/src/userSync.js index 20563d447a2..e2743c7f81f 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -152,7 +152,7 @@ export function newUserSync(userSyncDependencies) { if (!bidder) { return utils.logWarn(`Bidder is required for registering sync`); } - if (Number(numAdapterBids[bidder]) >= usConfig.syncsPerBidder) { + if (usConfig.syncsPerBidder !== 0 && Number(numAdapterBids[bidder]) >= usConfig.syncsPerBidder) { return utils.logWarn(`Number of user syncs exceeded for "${bidder}"`); } diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index 7040256ccd6..dfe6372288f 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -135,7 +135,7 @@ describe('user sync', function () { expect(syncUsersSpy.called).to.be.true; }); - it('should limit the sync per bidder', function () { + it('should limit the number of syncs per bidder', function () { const userSync = newTestUserSync({syncsPerBidder: 2}); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.registerSync('image', 'testBidder', 'http://example.com/2'); @@ -148,6 +148,20 @@ describe('user sync', function () { expect(triggerPixelStub.getCall(2)).to.be.null; }); + it('should not limit the number of syncs per bidder when set to 0', function() { + const userSync = newTestUserSync({syncsPerBidder: 0}); + userSync.registerSync('image', 'testBidder', 'http://example.com/1'); + userSync.registerSync('image', 'testBidder', 'http://example.com/2'); + userSync.registerSync('image', 'testBidder', 'http://example.com/3'); + userSync.syncUsers(); + expect(triggerPixelStub.getCall(0)).to.not.be.null; + expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.match(/^http:\/\/example\.com\/[1|2|3]/); + expect(triggerPixelStub.getCall(1)).to.not.be.null; + expect(triggerPixelStub.getCall(1).args[0]).to.exist.and.to.match(/^http:\/\/example\.com\/[1|2|3]/); + expect(triggerPixelStub.getCall(2)).to.not.be.null; + expect(triggerPixelStub.getCall(2).args[0]).to.exist.and.to.match(/^http:\/\/example\.com\/[1|2|3]/); + }); + it('should balance out bidder requests', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); From ba49c0d56f1767ab2220ff3d14824ed39adbbe34 Mon Sep 17 00:00:00 2001 From: Suzanne Ohlhausen Date: Thu, 13 Dec 2018 13:23:21 -0500 Subject: [PATCH 0893/1594] update conversant bid adapter to use video playerSize instead of sizes to determine the video player size (#3372) --- modules/conversantBidAdapter.js | 6 +++++- modules/conversantBidAdapter.md | 5 +++-- test/spec/modules/conversantBidAdapter_spec.js | 11 ++++++----- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index aae892f4eed..b3d944a99e4 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -62,7 +62,7 @@ export const spec = { siteId = utils.getBidIdParameter('site_id', bid.params); requestId = bid.auctionId; - const format = convertSizes(bid.sizes); + let format = convertSizes(bid.sizes); const imp = { id: bid.bidId, @@ -75,6 +75,10 @@ export const spec = { copyOptProperty(bid.params, 'tag_id', imp, 'tagid'); if (isVideoRequest(bid)) { + if (bid.mediaTypes.video.playerSize) { + format = convertSizes(bid.mediaTypes.video.playerSize); + } + const video = { w: format[0].w, h: format[0].h diff --git a/modules/conversantBidAdapter.md b/modules/conversantBidAdapter.md index 1afdad6d544..2b1e3ce8d55 100644 --- a/modules/conversantBidAdapter.md +++ b/modules/conversantBidAdapter.md @@ -25,7 +25,8 @@ var adUnits = [ sizes: [640, 480], mediaTypes: { video: { - context: 'instream' + context: 'instream', + playerSize: [640, 480] } }, bids: [{ @@ -38,4 +39,4 @@ var adUnits = [ } }] }]; -``` \ No newline at end of file +``` diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 91b3ed6892b..be173279f2d 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -60,7 +60,8 @@ describe('Conversant adapter tests', function() { }, mediaTypes: { video: { - context: 'instream' + context: 'instream', + playerSize: [632, 499], } }, placementCode: 'pcode003', @@ -193,8 +194,8 @@ describe('Conversant adapter tests', function() { expect(payload.imp[3]).to.not.have.property('tagid'); expect(payload.imp[3]).to.have.property('video'); expect(payload.imp[3].video).to.not.have.property('pos'); - expect(payload.imp[3].video).to.have.property('w', 640); - expect(payload.imp[3].video).to.have.property('h', 480); + expect(payload.imp[3].video).to.have.property('w', 632); + expect(payload.imp[3].video).to.have.property('h', 499); expect(payload.imp[3].video).to.have.property('mimes'); expect(payload.imp[3].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); expect(payload.imp[3].video).to.have.property('protocols'); @@ -254,8 +255,8 @@ describe('Conversant adapter tests', function() { expect(bid).to.have.property('currency', 'USD'); expect(bid).to.have.property('cpm', 3.99); expect(bid).to.have.property('creativeId', '1003'); - expect(bid).to.have.property('width', 640); - expect(bid).to.have.property('height', 480); + expect(bid).to.have.property('width', 632); + expect(bid).to.have.property('height', 499); expect(bid).to.have.property('vastUrl', 'markup003'); expect(bid).to.have.property('mediaType', 'video'); expect(bid).to.have.property('ttl', 300); From 5253d29e425aed70562be3a5c8e6968a2f6d0a48 Mon Sep 17 00:00:00 2001 From: ankur-modi <38654685+ankur-modi@users.noreply.github.com> Date: Fri, 14 Dec 2018 01:53:34 +0530 Subject: [PATCH 0894/1594] Remove application json from bid request header (#3346) --- modules/oneVideoBidAdapter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index bd341dfd79f..f2687c17619 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -47,7 +47,6 @@ export const spec = { method: 'POST', url: location.protocol + spec.ENDPOINT + bid.params.pubId, data: getRequestData(bid, consentData), - options: {contentType: 'application/json'}, bidRequest: bid } }) From bbc6316b744bba53dba4492b2ac11311ee1eb928 Mon Sep 17 00:00:00 2001 From: rjvelicaria Date: Fri, 14 Dec 2018 08:42:44 -0800 Subject: [PATCH 0895/1594] feat(video-platform-ids): BID-3468: video support for platform IDs (#3374) --- modules/openxBidAdapter.js | 4 +- test/spec/modules/openxBidAdapter_spec.js | 141 +++++++++++++++------- 2 files changed, 98 insertions(+), 47 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 446c790fded..046d494bb39 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -296,8 +296,10 @@ function buildOXBannerRequest(bids, bidderRequest) { } function buildOXVideoRequest(bid, bidderRequest) { - let url = `//${bid.params.delDomain}/v/1.0/avjp`; let oxVideoParams = generateVideoParameters(bid, bidderRequest); + let url = oxVideoParams.ph + ? `//u.openx.net/v/1.0/avjp` + : `//${bid.params.delDomain}/v/1.0/avjp`; return { method: 'GET', url: url, diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 4d9266169a0..7a115ae1096 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -179,57 +179,106 @@ describe('OpenxAdapter', function () { }); describe('when request is for a video ad', function () { - const videoBidWithMediaTypes = { - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - video: { - playerSize: [640, 480] - } - }, - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' - }; - - const videoBidWithMediaType = { - 'bidder': 'openx', - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'mediaType': 'video', - 'sizes': [640, 480], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' - }; - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(true); - }); + describe('and request config uses mediaTypes', () => { + const videoBidWithMediaTypes = { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + video: { + playerSize: [640, 480] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(true); + }); - it('should return false when required params are not passed', function () { - let videoBidWithMediaTypes = Object.assign({}, videoBidWithMediaTypes); - videoBidWithMediaTypes.params = {}; - expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); + it('should return false when required params are not passed', function () { + let videoBidWithMediaTypes = Object.assign({}, videoBidWithMediaTypes); + videoBidWithMediaTypes.params = {}; + expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); + }); + it('should send bid request to openx url via GET, with mediaType specified as video', function () { + const request = spec.buildRequests([videoBidWithMediaTypes]); + expect(request[0].url).to.equal(`//${videoBidWithMediaTypes.params.delDomain}${URLBASEVIDEO}`); + expect(request[0].data.ph).to.be.undefined; + expect(request[0].method).to.equal('GET'); + }); }); + describe('and request config uses both delDomain and platform', () => { + const videoBidWithDelDomainAndPlatform = { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain', + platform: '1cabba9e-cafe-3665-beef-f00f00f00f00', + }, + adUnitCode: 'adunit-code', + mediaTypes: { + video: { + playerSize: [640, 480] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(videoBidWithDelDomainAndPlatform)).to.equal(true); + }); - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(true); + it('should return false when required params are not passed', function () { + let videoBidWithMediaTypes = Object.assign({}, videoBidWithDelDomainAndPlatform); + videoBidWithMediaTypes.params = {}; + expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); + }); + it('should send bid request to openx url via GET, with mediaType specified as video', function () { + const request = spec.buildRequests([videoBidWithDelDomainAndPlatform]); + expect(request[0].url).to.equal(`//u.openx.net${URLBASEVIDEO}`); + expect(request[0].data.ph).to.equal(videoBidWithDelDomainAndPlatform.params.platform); + expect(request[0].method).to.equal('GET'); + }); }); + describe('and request config uses mediaType', () => { + const videoBidWithMediaType = { + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + 'mediaType': 'video', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(true); + }); - it('should return false when required params are not passed', function () { - let videoBidWithMediaType = Object.assign({}, videoBidWithMediaType); - delete videoBidWithMediaType.params; - videoBidWithMediaType.params = {}; - expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(false); + it('should return false when required params are not passed', function () { + let videoBidWithMediaType = Object.assign({}, videoBidWithMediaType); + delete videoBidWithMediaType.params; + videoBidWithMediaType.params = {}; + expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(false); + }); + it('should send bid request to openx url via GET, with mediaType specified as video', function () { + const request = spec.buildRequests([videoBidWithMediaType]); + expect(request[0].url).to.equal(`//${videoBidWithMediaType.params.delDomain}${URLBASEVIDEO}`); + expect(request[0].data.ph).to.be.undefined; + expect(request[0].method).to.equal('GET'); + }); }); }); }); From 32a611d6d88c9953246c7d420ecf9bcfb1aceaf0 Mon Sep 17 00:00:00 2001 From: PCMan-Appier <45620368+PCMan-Appier@users.noreply.github.com> Date: Sat, 15 Dec 2018 02:46:15 +0800 Subject: [PATCH 0896/1594] Add a new adapter for Appier bidder. (#3370) --- modules/appierBidAdapter.js | 89 +++++++++++ modules/appierBidAdapter.md | 57 +++++++ test/spec/modules/appierBidAdapter_spec.js | 174 +++++++++++++++++++++ 3 files changed, 320 insertions(+) create mode 100644 modules/appierBidAdapter.js create mode 100644 modules/appierBidAdapter.md create mode 100644 test/spec/modules/appierBidAdapter_spec.js diff --git a/modules/appierBidAdapter.js b/modules/appierBidAdapter.js new file mode 100644 index 00000000000..f000bbdc89f --- /dev/null +++ b/modules/appierBidAdapter.js @@ -0,0 +1,89 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; +import { config } from 'src/config'; + +export const ADAPTER_VERSION = '1.0.0'; +const SUPPORTED_AD_TYPES = [BANNER]; + +// we have different servers for different regions / farms +export const API_SERVERS_MAP = { + 'default': 'ad2.apx.appier.net', + 'tw': 'ad2.apx.appier.net', + 'jp': 'ad-jp.apx.appier.net' +}; + +const BIDDER_API_ENDPOINT = '/v1/prebid/bid'; + +export const spec = { + code: 'appier', + supportedMediaTypes: SUPPORTED_AD_TYPES, + + /** + * 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.params.hzid === 'string'; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {bidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (bidRequests, bidderRequest) { + if (bidRequests.length === 0) { + return []; + } + const server = this.getApiServer(); + const bidderApiUrl = `//${server}${BIDDER_API_ENDPOINT}` + const payload = { + 'bids': bidRequests, + 'refererInfo': bidderRequest.refererInfo, + 'version': ADAPTER_VERSION + }; + return [{ + method: 'POST', + url: bidderApiUrl, + data: payload, + // keep the bidder request object for later use + bidderRequest: 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, serverRequest) { + if (!Array.isArray(serverResponse.body)) { + return []; + } + // server response body is an array of bid results + const bidResults = serverResponse.body; + // our server directly returns the format needed by prebid.js so no more + // transformation is needed here. + return bidResults; + }, + + /** + * Get the hostname of the server we want to use. + */ + getApiServer() { + // we may use different servers for different farms (geographical regions) + // if a server is specified explicitly, use it. otherwise, use farm specific server. + let server = config.getConfig('appier.server'); + if (!server) { + const farm = config.getConfig('appier.farm'); + server = API_SERVERS_MAP[farm] || API_SERVERS_MAP['default']; + } + return server; + } +}; + +registerBidder(spec); diff --git a/modules/appierBidAdapter.md b/modules/appierBidAdapter.md new file mode 100644 index 00000000000..92fdaab1e40 --- /dev/null +++ b/modules/appierBidAdapter.md @@ -0,0 +1,57 @@ +# Overview + +``` +Module Name: Appier Bid Adapter +Module Type: Bidder Adapter +Maintainer: apn-dev@appier.com +``` + +# Description + +Connects to Appier exchange for bids. + +NOTE: +- Appier bid adapter only supports Banner at the moment. +- Multi-currency is not supported. Please make sure you have correct DFP currency settings according to your deal with Appier. + +# Sample Ad Unit Config +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'appier', + params: { + hzid: 'WhM5WIOp' + } + }] + } +]; +``` + +# Additional Config (Optional) +Set the "farm" to use region-specific server +``` + // use the bid server in Taiwan (country code: tw) + pbjs.setConfig({ + appier: { + 'farm': 'tw' + } + }); +``` + +Explicitly override the bid server used for bidding +``` + // use the bid server specified and override the default + pbjs.setConfig({ + appier: { + 'server': '${HOST_NAME_OF_THE_SERVER}' + } + }); +``` diff --git a/test/spec/modules/appierBidAdapter_spec.js b/test/spec/modules/appierBidAdapter_spec.js new file mode 100644 index 00000000000..c7fc5744d1c --- /dev/null +++ b/test/spec/modules/appierBidAdapter_spec.js @@ -0,0 +1,174 @@ +import { expect } from 'chai'; +import { spec, API_SERVERS_MAP, ADAPTER_VERSION } from 'modules/appierBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; + +describe('AppierAdapter', 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': 'appier', + 'params': { + 'hzid': 'abcd' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params zoneId found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required param zoneId is missing', function () { + let bid = Object.assign({}, bid); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when required param zoneId has wrong type', function () { + let bid = Object.assign({}, bid); + bid.params = { + 'hzid': null + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function() { + it('should return an empty list when there are no bid requests', function() { + const fakeBidRequests = []; + const fakeBidderRequest = {}; + expect(spec.buildRequests(fakeBidRequests, fakeBidderRequest)).to.be.an('array').that.is.empty; + }); + + it('should generate a POST bid request with method, url, and data fields', function() { + const bid = { + 'bidder': 'appier', + 'params': { + 'hzid': 'abcd' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + const fakeBidRequests = [bid]; + const fakeBidderRequest = {refererInfo: { + 'referer': 'fakeReferer', + 'reachedTop': true, + 'numIframes': 1, + 'stack': [] + }}; + + const builtRequests = spec.buildRequests(fakeBidRequests, fakeBidderRequest); + expect(builtRequests.length).to.equal(1); + expect(builtRequests[0].method).to.equal('POST'); + expect(builtRequests[0].url).match(/v1\/prebid\/bid/); + expect(builtRequests[0].data).deep.equal({ + 'bids': fakeBidRequests, + 'refererInfo': fakeBidderRequest.refererInfo, + 'version': ADAPTER_VERSION + }); + }); + }); + + describe('interpretResponse', function() { + const bid = { + 'bidder': 'appier', + 'params': { + 'hzid': 'abcd' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + const fakeBidRequests = [bid]; + + it('should return an empty aray to indicate no valid bids', function() { + const fakeServerResponse = {}; + + const bidResponses = spec.interpretResponse(fakeServerResponse, fakeBidRequests); + + expect(bidResponses).is.an('array').that.is.empty; + }); + + it('should generate correct response array for bidder', function() { + const fakeBidResult = { + 'requestId': '30b31c1838de1e', + 'cpm': 0.0029346001, + 'creativeId': 'Idl0P0d5S3Ca5kVWcia-wQ', + 'width': 300, + 'height': 250, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'ad': '
fake html
', + 'appierParams': { + 'hzid': 'test_hzid' + } + }; + const fakeServerResponse = { + headers: [], + body: [fakeBidResult] + }; + + const bidResponses = spec.interpretResponse(fakeServerResponse, fakeBidRequests); + expect(bidResponses).deep.equal([fakeBidResult]); + }); + }); + + describe('getApiServer', function() { + it('should use the server specified by setConfig(appier.server)', function() { + config.setConfig({ + 'appier': {'server': 'fake_server'} + }); + + const server = spec.getApiServer(); + + expect(server).equals('fake_server'); + }); + + it('should retrieve a farm specific hostname if server is not specpfied', function() { + config.setConfig({ + 'appier': {'farm': 'tw'} + }); + + const server = spec.getApiServer(); + + expect(server).equals(API_SERVERS_MAP['tw']); + }); + + it('if farm is not recognized, use the default farm', function() { + config.setConfig({ + 'appier': {'farm': 'no_this_farm'} + }); + + const server = spec.getApiServer(); + + expect(server).equals(API_SERVERS_MAP['default']); + }); + + it('if farm is not specified, use the default farm', function() { + config.setConfig({ + 'appier': {} + }); + + const server = spec.getApiServer(); + + expect(server).equals(API_SERVERS_MAP['default']); + }); + }); +}); From 65afce66fd25b3724173e960c8901e92e7d2cf36 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 17 Dec 2018 07:25:52 -0700 Subject: [PATCH 0897/1594] new no bid event and no bids available from auction (#3286) --- src/AnalyticsAdapter.js | 2 ++ src/adaptermanager.js | 14 +++++--- src/adapters/bidderFactory.js | 2 +- src/auction.js | 57 +++++++++++++++++++++----------- src/auctionManager.js | 9 +++-- src/constants.json | 1 + src/prebid.js | 33 +++++++++++++----- test/spec/api_spec.js | 4 +++ test/spec/auctionmanager_spec.js | 44 ++++++++++-------------- 9 files changed, 104 insertions(+), 62 deletions(-) diff --git a/src/AnalyticsAdapter.js b/src/AnalyticsAdapter.js index 3cb64f1b911..5565ba2ed18 100644 --- a/src/AnalyticsAdapter.js +++ b/src/AnalyticsAdapter.js @@ -11,6 +11,7 @@ const { BID_REQUESTED, BID_TIMEOUT, BID_RESPONSE, + NO_BID, BID_WON, BID_ADJUSTMENT, BIDDER_DONE, @@ -100,6 +101,7 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } _handlers = { [BID_REQUESTED]: args => this.enqueue({ eventType: BID_REQUESTED, args }), [BID_RESPONSE]: args => this.enqueue({ eventType: BID_RESPONSE, args }), + [NO_BID]: args => this.enqueue({ eventType: NO_BID, args }), [BID_TIMEOUT]: args => this.enqueue({ eventType: BID_TIMEOUT, args }), [BID_WON]: args => this.enqueue({ eventType: BID_WON, args }), [BID_ADJUSTMENT]: args => this.enqueue({ eventType: BID_ADJUSTMENT, args }), diff --git a/src/adaptermanager.js b/src/adaptermanager.js index 55aab710741..3242115f024 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -1,6 +1,6 @@ /** @module adaptermanger */ -import { flatten, getBidderCodes, getDefinedParams, shuffle, timestamp } from './utils'; +import { flatten, getBidderCodes, getDefinedParams, shuffle, timestamp, getBidderRequest } from './utils'; import { getLabels, resolveStatus } from './sizeMapping'; import { processNativeAdUnitParams, nativeAdapters } from './native'; import { newBidder } from './adapters/bidderFactory'; @@ -340,7 +340,7 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbac if (s2sBidRequest.ad_units.length) { let doneCbs = serverBidRequests.map(bidRequest => { bidRequest.start = timestamp(); - return doneCb; + return doneCb.bind(bidRequest); }); // only log adapters that actually have adUnit bids @@ -360,7 +360,12 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbac s2sAdapter.callBids( s2sBidRequest, serverBidRequests, - addBidResponse, + function(adUnitCode, bid) { + let bidderRequest = getBidderRequest(serverBidRequests, bid.bidderCode, adUnitCode); + if (bidderRequest) { + addBidResponse.call(bidderRequest, adUnitCode, bid) + } + }, () => doneCbs.forEach(done => done()), s2sAjax ); @@ -375,12 +380,11 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbac const adapter = _bidderRegistry[bidRequest.bidderCode]; utils.logMessage(`CALLING BIDDER ======= ${bidRequest.bidderCode}`); events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); - bidRequest.doneCbCallCount = 0; let ajax = ajaxBuilder(requestBidsTimeout, requestCallbacks ? { request: requestCallbacks.request.bind(null, bidRequest.bidderCode), done: requestCallbacks.done } : undefined); - adapter.callBids(bidRequest, addBidResponse, doneCb, ajax); + adapter.callBids(bidRequest, addBidResponse.bind(bidRequest), doneCb.bind(bidRequest), ajax); }); } diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index d5ccf57e394..e25c041527e 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -176,7 +176,7 @@ export function newBidder(spec) { // After all the responses have come back, call done() and // register any required usersync pixels. const responses = []; - function afterAllResponses(bids) { + function afterAllResponses() { done(); events.emit(CONSTANTS.EVENTS.BIDDER_DONE, bidderRequest); registerSyncs(responses, bidderRequest.gdprConsent); diff --git a/src/auction.js b/src/auction.js index 37b2c6896f2..a8affd40ca6 100644 --- a/src/auction.js +++ b/src/auction.js @@ -48,7 +48,7 @@ * @property {function(): void} callBids - sends requests to all adapters for bids */ -import { uniques, flatten, timestamp, adUnitsFilter, getBidderRequest, deepAccess, delayExecution, getBidRequest } from './utils'; +import { uniques, flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest } from './utils'; import { getPriceBucketString } from './cpmBucketManager'; import { getNativeTargeting } from './native'; import { getCacheUrl, store } from './videoCache'; @@ -95,6 +95,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) let _adUnitCodes = adUnitCodes; let _bidderRequests = []; let _bidsReceived = []; + let _noBids = []; let _auctionStart; let _auctionEnd; let _auctionId = utils.generateUUID(); @@ -106,6 +107,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) function addBidRequests(bidderRequests) { _bidderRequests = _bidderRequests.concat(bidderRequests) }; function addBidReceived(bidsReceived) { _bidsReceived = _bidsReceived.concat(bidsReceived); } + function addNoBid(noBid) { _noBids = _noBids.concat(noBid); } function getProperties() { return { @@ -117,6 +119,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) adUnitCodes: _adUnitCodes, labels: _labels, bidderRequests: _bidderRequests, + noBids: _noBids, bidsReceived: _bidsReceived, winningBids: _winningBids, timeout: _timeout @@ -175,7 +178,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } - function auctionDone(bidderCount) { + function auctionDone() { // when all bidders have called done callback atleast once it means auction is complete utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); _auctionStatus = AUCTION_COMPLETED; @@ -208,10 +211,12 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) events.emit(CONSTANTS.EVENTS.AUCTION_INIT, getProperties()); let callbacks = auctionCallbacks(auctionDone, this); - let boundObj = { - auctionAddBidResponse: callbacks.addBidResponse - }; - adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(boundObj), 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); @@ -296,6 +301,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) return { addBidReceived, + addNoBid, executeCallback, callBids, addWinningBid, @@ -308,20 +314,19 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) getAdUnitCodes: () => _adUnitCodes, getBidRequests: () => _bidderRequests, getBidsReceived: () => _bidsReceived, + getNoBids: () => _noBids } } export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid) { - this.auctionAddBidResponse(adUnitCode, bid); + this.dispatch.call(this.bidderRequest, adUnitCode, bid); }, 'addBidResponse'); export function auctionCallbacks(auctionDone, auctionInstance) { let outstandingBidsAdded = 0; let allAdapterCalledDone = false; - - let onAllAdapterDone = delayExecution(() => { - allAdapterCalledDone = true; - }, auctionInstance.getBidRequests().length); + let bidderRequestsDone = new Set(); + let bidResponseMap = {}; function afterBidAdded() { outstandingBidsAdded--; @@ -331,15 +336,17 @@ export function auctionCallbacks(auctionDone, auctionInstance) { } function addBidResponse(adUnitCode, bid) { + let bidderRequest = this; + + bidResponseMap[bid.requestId] = true; + outstandingBidsAdded++; - let bidRequests = auctionInstance.getBidRequests(); let auctionId = auctionInstance.getAuctionId(); - let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); - let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}); + let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}); if (bidResponse.mediaType === 'video') { - tryAddVideoBid(auctionInstance, bidResponse, bidRequest, afterBidAdded); + tryAddVideoBid(auctionInstance, bidResponse, bidderRequest, afterBidAdded); } else { addBidToAuction(auctionInstance, bidResponse); afterBidAdded(); @@ -347,7 +354,19 @@ export function auctionCallbacks(auctionDone, auctionInstance) { } function adapterDone() { - onAllAdapterDone(); + let bidderRequest = this; + + bidderRequestsDone.add(bidderRequest); + allAdapterCalledDone = auctionInstance.getBidRequests() + .every(bidderRequest => bidderRequestsDone.has(bidderRequest)); + + bidderRequest.bids.forEach(bid => { + if (!bidResponseMap[bid.bidId]) { + auctionInstance.addNoBid(bid); + events.emit(CONSTANTS.EVENTS.NO_BID, bid); + } + }); + if (allAdapterCalledDone && outstandingBidsAdded === 0) { auctionDone(); } @@ -412,8 +431,8 @@ function tryAddVideoBid(auctionInstance, bidResponse, bidRequests, afterBidAdded // 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, bidRequest, auctionId}) { - const start = bidRequest.start; +function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) { + const start = bidderRequest.start; let bidObject = Object.assign({}, bid, { auctionId, @@ -433,7 +452,7 @@ function getPreparedBidForAuction({adUnitCode, bid, bidRequest, auctionId}) { events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bidObject); // a publisher-defined renderer can be used to render bids - const bidReq = bidRequest.bids && find(bidRequest.bids, bid => bid.adUnitCode == adUnitCode); + const bidReq = bidderRequest.bids && find(bidderRequest.bids, bid => bid.adUnitCode == adUnitCode); const adUnitRenderer = bidReq && bidReq.renderer; if (adUnitRenderer && adUnitRenderer.url) { diff --git a/src/auctionManager.js b/src/auctionManager.js index 389cac31fe3..3f28062ecfd 100644 --- a/src/auctionManager.js +++ b/src/auctionManager.js @@ -39,18 +39,23 @@ export function newAuctionManager() { } else { utils.logWarn(`Auction not found when adding winning bid`); } - } + }; auctionManager.getAllWinningBids = function() { return _auctions.map(auction => auction.getWinningBids()) .reduce(flatten, []); - } + }; auctionManager.getBidsRequested = function() { return _auctions.map(auction => auction.getBidRequests()) .reduce(flatten, []); }; + auctionManager.getNoBids = function() { + return _auctions.map(auction => auction.getNoBids()) + .reduce(flatten, []); + }; + auctionManager.getBidsReceived = function() { // As of now, an old bid which is not used in auction 1 can be used in auction n. // To prevent this, bid.ttl (time to live) will be added to this logic and bid pool will also be added diff --git a/src/constants.json b/src/constants.json index 768e073b625..4edf120b15f 100644 --- a/src/constants.json +++ b/src/constants.json @@ -30,6 +30,7 @@ "BID_TIMEOUT": "bidTimeout", "BID_REQUESTED": "bidRequested", "BID_RESPONSE": "bidResponse", + "NO_BID": "noBid", "BID_WON": "bidWon", "BIDDER_DONE": "bidderDone", "SET_TARGETING": "setTargeting", diff --git a/src/prebid.js b/src/prebid.js index 0460b99bbb0..ed4398feb6f 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -114,15 +114,8 @@ $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { return targeting.getAllTargeting(adUnitCode); }; -/** - * This function returns the bid responses at the given moment. - * @alias module:pbjs.getBidResponses - * @return {Object} map | object that contains the bidResponses - */ - -$$PREBID_GLOBAL$$.getBidResponses = function () { - utils.logInfo('Invoking $$PREBID_GLOBAL$$.getBidResponses', arguments); - const responses = auctionManager.getBidsReceived() +function getBids(type) { + const responses = auctionManager[type]() .filter(adUnitsFilter.bind(this, auctionManager.getAdUnitCodes())); // find the last auction id to get responses for most recent auction only @@ -139,6 +132,28 @@ $$PREBID_GLOBAL$$.getBidResponses = function () { }; }) .reduce((a, b) => Object.assign(a, b), {}); +} + +/** + * This function returns the bids requests involved in an auction but not bid on + * @alias module:pbjs.getNoBids + * @return {Object} map | object that contains the bidRequests + */ + +$$PREBID_GLOBAL$$.getNoBids = function () { + utils.logInfo('Invoking $$PREBID_GLOBAL$$.getNoBids', arguments); + return getBids('getNoBids'); +}; + +/** + * This function returns the bid responses at the given moment. + * @alias module:pbjs.getBidResponses + * @return {Object} map | object that contains the bidResponses + */ + +$$PREBID_GLOBAL$$.getBidResponses = function () { + utils.logInfo('Invoking $$PREBID_GLOBAL$$.getBidResponses', arguments); + return getBids('getBidsReceived'); }; /** diff --git a/test/spec/api_spec.js b/test/spec/api_spec.js index 41fafb080ad..a8987d3ed07 100755 --- a/test/spec/api_spec.js +++ b/test/spec/api_spec.js @@ -39,6 +39,10 @@ describe('Publisher API', function () { assert.isFunction($$PREBID_GLOBAL$$.getBidResponses); }); + it('should have function $$PREBID_GLOBAL$$.getBidResponses', function () { + assert.isFunction($$PREBID_GLOBAL$$.getNoBids); + }); + it('should have function $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode', function () { assert.isFunction($$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode); }); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index cd0c8586d04..85e37ca512d 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -1,9 +1,8 @@ -import { auctionManager, newAuctionManager } from 'src/auctionManager'; import { getKeyValueTargetingPairs, auctionCallbacks } from 'src/auction'; import CONSTANTS from 'src/constants.json'; import { adjustBids } from 'src/auction'; import * as auctionModule from 'src/auction'; -import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; +import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; import * as store from 'src/videoCache'; import * as ajaxLib from 'src/ajax'; @@ -20,10 +19,6 @@ var fixtures = require('../fixtures/fixtures'); var adaptermanager = require('src/adaptermanager'); var events = require('src/events'); -function timestamp() { - return new Date().getTime(); -} - const BIDDER_CODE = 'sampleBidder'; const BIDDER_CODE1 = 'sampleBidder1'; @@ -667,7 +662,6 @@ describe('auctionmanager.js', function () { describe('when auction timeout is 20', function () { let eventsEmitSpy; - let getBidderRequestStub; before(function () { bids = [mockBid(), mockBid({ bidderCode: BIDDER_CODE1 })]; @@ -700,18 +694,16 @@ describe('auctionmanager.js', function () { eventsEmitSpy = sinon.spy(events, 'emit'); - let origGBR = utils.getBidderRequest; - getBidderRequestStub = sinon.stub(utils, 'getBidderRequest'); - getBidderRequestStub.callsFake((bidRequests, bidder, adUnitCode) => { - let req = origGBR(bidRequests, bidder, adUnitCode); - req.start = 1000; - return req; + // make all timestamp calls 5 minutes apart + let callCount = 0; + sinon.stub(utils, 'timestamp').callsFake(function() { + return new Date().getTime() + (callCount++ * 1000 * 60 * 5); }); }); afterEach(function () { auctionModule.newAuction.restore(); events.emit.restore(); - getBidderRequestStub.restore(); + utils.timestamp.restore(); }); it('should emit BID_TIMEOUT for timed out bids', function () { auction.callBids(); @@ -885,12 +877,12 @@ describe('auctionmanager.js', function () { mockBidRequest(bids2[0], { adUnitCode: ADUNIT_CODE2 }) ]; let cbs = auctionCallbacks(doneSpy, auction); - cbs.addBidResponse(ADUNIT_CODE, bids[0]); - cbs.adapterDone(); - cbs.addBidResponse(ADUNIT_CODE1, bids1[0]); - cbs.adapterDone(); - cbs.addBidResponse(ADUNIT_CODE2, bids2[0]); - cbs.adapterDone(); + cbs.addBidResponse.call(bidRequests[0], ADUNIT_CODE, bids[0]); + cbs.adapterDone.call(bidRequests[0]); + cbs.addBidResponse.call(bidRequests[1], ADUNIT_CODE1, bids1[0]); + cbs.adapterDone.call(bidRequests[1]); + cbs.addBidResponse.call(bidRequests[2], ADUNIT_CODE2, bids2[0]); + cbs.adapterDone.call(bidRequests[2]); assert.equal(doneSpy.callCount, 1); }); @@ -905,17 +897,17 @@ describe('auctionmanager.js', function () { playerSize: [640, 480], }, } - } + }; bidRequests = [ mockBidRequest(bids[0], opts), mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 }), - ] + ]; let cbs = auctionCallbacks(doneSpy, auction); - cbs.addBidResponse(ADUNIT_CODE, bids[0]); - cbs.adapterDone(); - cbs.addBidResponse(ADUNIT_CODE1, bids1[0]); - cbs.adapterDone(); + cbs.addBidResponse.call(bidRequests[0], ADUNIT_CODE, bids[0]); + cbs.adapterDone.call(bidRequests[0]); + cbs.addBidResponse.call(bidRequests[1], ADUNIT_CODE1, bids1[0]); + cbs.adapterDone.call(bidRequests[1]); assert.equal(doneSpy.callCount, 0); const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; const responseBody = `{"responses":[{"uuid":"${uuid}"}]}`; From 14bf872264e6ab06c64653285cf06cbc16c76f71 Mon Sep 17 00:00:00 2001 From: devcollectcent <45760266+devcollectcent@users.noreply.github.com> Date: Tue, 18 Dec 2018 04:29:31 +0200 Subject: [PATCH 0898/1594] New bidder adapter for collectcent (#3365) * Create collectcentBidAdapter.js New bider adapter for collectcent * Create collectcentBidAdapter.md Description and integration example * Create collectcentBidAdapter_spec.js Collectcent bidder adapter tests added * Update collectcentBidAdapter_spec.js edit * Update collectcentBidAdapter.js Used bidderRequest.refererInfo.referer instead of window.location * Update collectcentBidAdapter.js * Update collectcentBidAdapter.js Rename URL to URL_MULTI --- modules/collectcentBidAdapter.js | 93 ++++++++++++++ modules/collectcentBidAdapter.md | 27 ++++ .../modules/collectcentBidAdapter_spec.js | 118 ++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 modules/collectcentBidAdapter.js create mode 100644 modules/collectcentBidAdapter.md create mode 100644 test/spec/modules/collectcentBidAdapter_spec.js diff --git a/modules/collectcentBidAdapter.js b/modules/collectcentBidAdapter.js new file mode 100644 index 00000000000..df64da1f7f0 --- /dev/null +++ b/modules/collectcentBidAdapter.js @@ -0,0 +1,93 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'collectcent'; +const URL_MULTI = '//publishers.motionspots.com/?c=o&m=multi'; +const URL_SYNC = '//publishers.motionspots.com/?c=o&m=cookie'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + + /** + * 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: (bid) => { + return Boolean(bid.bidId && + bid.params && + !isNaN(bid.params.placementId) && + spec.supportedMediaTypes.indexOf(bid.params.traffic) !== -1 + ); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: (validBidRequests, bidderRequest) => { + let winTop; + try { + winTop = window.top; + } catch (e) { + utils.logMessage(e); + winTop = window; + }; + + const placements = []; + const location = bidderRequest ? new URL(bidderRequest.refererInfo.referer) : winTop.location; + const request = { + 'secure': (location.protocol === 'https:') ? 1 : 0, + 'deviceWidth': winTop.screen.width, + 'deviceHeight': winTop.screen.height, + 'host': location.host, + 'page': location.pathname, + 'placements': placements + }; + + for (let i = 0; i < validBidRequests.length; i++) { + const bid = validBidRequests[i]; + const params = bid.params; + placements.push({ + placementId: params.placementId, + bidId: bid.bidId, + sizes: bid.sizes, + traffic: params.traffic + }); + } + return { + method: 'POST', + url: URL_MULTI, + data: request + }; + }, + + /** + * 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: (serverResponse) => { + try { + serverResponse = serverResponse.body; + } catch (e) { + utils.logMessage(e); + }; + return serverResponse; + }, + + getUserSyncs: () => { + return [{ + type: 'image', + url: URL_SYNC + }]; + } +}; + +registerBidder(spec); diff --git a/modules/collectcentBidAdapter.md b/modules/collectcentBidAdapter.md new file mode 100644 index 00000000000..938bdc420cd --- /dev/null +++ b/modules/collectcentBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +``` +Module Name: Collectcent SSP Bidder Adapter +Module Type: Bidder Adapter +Maintainer: dev.collectcent@gmail.com +``` + +# Description + +Module that connects to Collectcent SSP demand sources + +# Test Parameters +``` + var adUnits = [{ + code: 'placementCode', + sizes: [[300, 250]], + bids: [{ + bidder: 'collectcent', + params: { + placementId: 0, + traffic: 'banner' + } + }] + } + ]; +``` diff --git a/test/spec/modules/collectcentBidAdapter_spec.js b/test/spec/modules/collectcentBidAdapter_spec.js new file mode 100644 index 00000000000..04c819992cd --- /dev/null +++ b/test/spec/modules/collectcentBidAdapter_spec.js @@ -0,0 +1,118 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/collectcentBidAdapter'; + +describe('Collectcent', function () { + let bid = { + bidId: '2dd581a2b6281d', + bidder: 'collectcent', + bidderRequestId: '145e1d6a7837c9', + params: { + placementId: 123, + traffic: 'banner' + }, + placementCode: 'placement_0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' + }; + + describe('isBidRequestValid', function () { + it('Should return true when placementId can be cast to a number', function () { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when placementId is not a number', function () { + bid.params.placementId = 'aaa'; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', function () { + let serverRequest = spec.buildRequests([bid]); + 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('//publishers.motionspots.com/?c=o&m=multi'); + }); + 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', 'secure', 'host', 'page', 'placements'); + expect(data.deviceWidth).to.be.a('number'); + expect(data.deviceHeight).to.be.a('number'); + 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', 'bidId', 'traffic', 'sizes'); + 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'); + } + }); + 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 () { + let resObject = { + body: [ { + requestId: '123', + mediaType: 'banner', + cpm: 0.3, + width: 320, + height: 50, + ad: '

Hello ad

', + ttl: 1000, + creativeId: '123asd', + netRevenue: true, + currency: 'USD' + } ] + }; + let serverResponses = spec.interpretResponse(resObject); + it('Returns an array of valid server responses if response object is valid', function () { + 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'); + 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'); + } + it('Returns an empty array if invalid response is passed', function () { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); + + describe('getUserSyncs', function () { + let userSync = spec.getUserSyncs(); + it('Returns valid URL and `', 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('//publishers.motionspots.com/?c=o&m=cookie'); + }); + }); +}); From 514fc5f1cd83b7c90753164a5100b642903543ef Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Tue, 18 Dec 2018 15:03:09 +0000 Subject: [PATCH 0899/1594] Added 640x360 size (#3388) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 76122452222..c13833502fb 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -73,6 +73,7 @@ var sizeMap = { 145: '980x150', 159: '320x250', 195: '600x300', + 198: '640x360', 199: '640x200', 213: '1030x590', 214: '980x360', From 05df581c753efdd189775d9ba183a608c98c57ed Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Tue, 18 Dec 2018 16:09:27 +0000 Subject: [PATCH 0900/1594] Added 250x800 size (#3390) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index c13833502fb..22db444f8d6 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -64,6 +64,7 @@ var sizeMap = { 101: '480x320', 102: '768x1024', 103: '480x280', + 105: '250x800', 108: '320x240', 113: '1000x300', 117: '320x100', From 927736553ed43b1dc61a1a89779a9401f28b16a2 Mon Sep 17 00:00:00 2001 From: naoto yamaguchi Date: Wed, 19 Dec 2018 05:12:56 +0900 Subject: [PATCH 0901/1594] update AJA adapter: support user sync by iframe (#3382) * fix indent * add handling iframe user sync --- modules/ajaBidAdapter.js | 30 +++++++---- modules/ajaBidAdapter.md | 68 ++++++++++++------------- test/spec/modules/ajaBidAdapter_spec.js | 43 +++++++++++++--- 3 files changed, 89 insertions(+), 52 deletions(-) diff --git a/modules/ajaBidAdapter.js b/modules/ajaBidAdapter.js index ff44aaa1208..3a4a14592e7 100644 --- a/modules/ajaBidAdapter.js +++ b/modules/ajaBidAdapter.js @@ -93,16 +93,28 @@ export const spec = { getUserSyncs: function(syncOptions, serverResponses) { const syncs = []; - if (syncOptions.pixelEnabled && serverResponses.length) { - const bidderResponseBody = serverResponses[0].body; - if (bidderResponseBody.syncs) { - bidderResponseBody.syncs.forEach(sync => { - syncs.push({ - type: 'image', - url: sync - }); + if (!serverResponses.length) { + return syncs; + } + + const bidderResponseBody = serverResponses[0].body; + + if (syncOptions.pixelEnabled && bidderResponseBody.syncs) { + bidderResponseBody.syncs.forEach(sync => { + syncs.push({ + type: 'image', + url: sync }); - } + }); + } + + if (syncOptions.iframeEnabled && bidderResponseBody.sync_htmls) { + bidderResponseBody.sync_htmls.forEach(sync => { + syncs.push({ + type: 'iframe', + url: sync + }); + }); } return syncs; diff --git a/modules/ajaBidAdapter.md b/modules/ajaBidAdapter.md index ea2b8e97a43..6e513b94ff0 100644 --- a/modules/ajaBidAdapter.md +++ b/modules/ajaBidAdapter.md @@ -13,40 +13,38 @@ Aja bid adapter supports Banner and Outstream Video. # Test Parameters ``` var adUnits = [ - // Banner adUnit - { - code: 'banner-div', - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ], - } - }, - bids: [{ - bidder: 'aja', - params: { - asi: 'szs4htFiR' - } - }] - }, - // Video outstream adUnit - { - code: 'video-outstream', - mediaTypes: { - video: { - context: 'outstream', - playerSize: [300, 250] - } - }, - bids: [ - { - bidder: 'aja', - params: { - asi: 'Kp2O2tFig' - } - } - ] - } + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250] + ], + } + }, + bids: [{ + bidder: 'aja', + params: { + asi: 'szs4htFiR' + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [300, 250] + } + }, + bids: [{ + bidder: 'aja', + params: { + asi: 'Kp2O2tFig' + } + }] + } ]; ``` diff --git a/test/spec/modules/ajaBidAdapter_spec.js b/test/spec/modules/ajaBidAdapter_spec.js index 8561f8c0baf..00dafcb7b11 100644 --- a/test/spec/modules/ajaBidAdapter_spec.js +++ b/test/spec/modules/ajaBidAdapter_spec.js @@ -148,7 +148,10 @@ describe('AjaAdapter', function () { 'is_ad_return': true, 'ad': { /* ad body */ }, 'syncs': [ - 'https://example.test/1' + 'https://example.test/pixel/1' + ], + 'sync_htmls': [ + 'https://example.test/iframe/1' ] } }; @@ -158,29 +161,53 @@ describe('AjaAdapter', function () { 'is_ad_return': true, 'ad': { /* ad body */ }, 'syncs': [ - 'https://example.test/2' + 'https://example.test/pixel/2' ] } }; - it('should use a sync url from first response', function () { - const syncs = spec.getUserSyncs({ pixelEnabled: true }, [bidResponse1, bidResponse2]); + 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://example.test/1' + url: 'https://example.test/pixel/1' + }, + { + type: 'iframe', + url: 'https://example.test/iframe/1' } ]); }); it('handle empty response (e.g. timeout)', function () { - const syncs = spec.getUserSyncs({ pixelEnabled: true }, []); + const syncs = spec.getUserSyncs({ pixelEnabled: true, iframeEnabled: true }, []); expect(syncs).to.deep.equal([]); }); - it('returns empty syncs when not enabled', function () { - const syncs = spec.getUserSyncs({ pixelEnabled: false }, [bidResponse1]); + 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() { + const syncs = spec.getUserSyncs({ pixelEnabled: true, iframeEnabled: false }, [bidResponse1]); + expect(syncs).to.deep.equal([ + { + type: 'image', + url: 'https://example.test/pixel/1' + } + ]); + }); + + it('returns iframe syncs when not pixel enabled and iframe enabled', function() { + const syncs = spec.getUserSyncs({ pixelEnabled: false, iframeEnabled: true }, [bidResponse1]); + expect(syncs).to.deep.equal([ + { + type: 'iframe', + url: 'https://example.test/iframe/1' + } + ]); + }); }); }); From 7224e78b02d11e9b675b97e343702d786edadb13 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 18 Dec 2018 13:09:48 -0800 Subject: [PATCH 0902/1594] Prebid 1.36.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2445032536c..446136eef3e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.36.0-pre", + "version": "1.36.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 691dcf6656a96537caa241f4496349d39af239b7 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 18 Dec 2018 13:24:38 -0800 Subject: [PATCH 0903/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 446136eef3e..a03509bf3c3 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.36.0", + "version": "1.37.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From f2e5f1751898b32f9d49cdc6074c113ac84d1ed5 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 18 Dec 2018 18:55:26 -0500 Subject: [PATCH 0904/1594] add support for userSyncLimit field in s2sConfig (#3375) --- modules/prebidServerBidAdapter/index.js | 5 +++ .../modules/prebidServerBidAdapter_spec.js | 42 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 165e0a6f80e..4519a657345 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -100,6 +100,11 @@ function queueSync(bidderCodes, gdprConsent) { account: _s2sConfig.accountId }; + let userSyncLimit = _s2sConfig.userSyncLimit; + if (utils.isNumber(userSyncLimit) && userSyncLimit > 0) { + payload['limit'] = userSyncLimit; + } + if (gdprConsent) { // only populate gdpr field if we know CMP returned consent information (ie didn't timeout or have an error) if (typeof gdprConsent.consentString !== 'undefined') { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 77e7f3ad868..af568788bd8 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -738,6 +738,48 @@ describe('S2S Adapter', function () { value: ['buzz'] }]); }); + + it('adds limit to the cookie_sync request if userSyncLimit is greater than 0', function () { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + cookieSyncConfig.userSyncLimit = 1; + + config.setConfig({ s2sConfig: cookieSyncConfig }); + + let bidRequest = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, bidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.bidders).to.contain('appnexus').and.to.have.lengthOf(1); + expect(requestBid.account).is.equal('1'); + expect(requestBid.limit).is.equal(1); + }); + + it('does not add limit to cooke_sync request if userSyncLimit is missing or 0', function () { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + config.setConfig({ s2sConfig: cookieSyncConfig }); + + let bidRequest = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, bidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.bidders).to.contain('appnexus').and.to.have.lengthOf(1); + expect(requestBid.account).is.equal('1'); + expect(requestBid.limit).is.undefined; + + cookieSyncConfig.userSyncLimit = 0; + config.resetConfig(); + config.setConfig({ s2sConfig: cookieSyncConfig }); + + bidRequest = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, bidRequest, addBidResponse, done, ajax); + requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.bidders).to.contain('appnexus').and.to.have.lengthOf(1); + expect(requestBid.account).is.equal('1'); + expect(requestBid.limit).is.undefined; + }); }); describe('response handler', function () { From 49ea705266c4714b7b6cb48bade4b24eef6ae296 Mon Sep 17 00:00:00 2001 From: AlessandroDG Date: Wed, 19 Dec 2018 15:32:08 +0100 Subject: [PATCH 0905/1594] Rivr thin adapter (#3351) * Rivr thin adapter (#5) * RVR-2049 - change impression event * RVR-2049 - fix user id value returned on creation of the cookie * RVR-2049 - remove blockedCategories and browser properties from Auction object * RVR-2060 - rewrite rendering detection for impression and click events * RVR-2060 - rewrite tests for rendering detection for impression and click events * RVR-2049 - send ad unit code in click event * RVR-2049 - adapt tests for click event * RVR-2072 - split impression detection depending on the ad server - DFP/none * RVR-2056 - set creativeId in Auction -> received bids * RVR-2056 - set bid.clearPrice to cmp * RVR-2087 - extract trackAuctionInit implementation to rivraddon * RVR-2087 - extract implementation to rivraddon WIP * RVR-2087 - extract implementation to rivraddon * RVR-2087 - extract implementation to rivraddon * RVR-2087 - Update package-lock * RVR-2087 - Add addons check * Rivr Thin Adapter - part 2 (#6) * RVR-2087 - Remove sendAuction call from ExpiringQueue * RVR-2147 - Fix test failing on IE 11.0.0 * RVR-2087 - Remove ExpiringQueue --- modules/rivrAnalyticsAdapter.js | 445 +------ .../spec/modules/rivrAnalyticsAdapter_spec.js | 1067 +---------------- 2 files changed, 70 insertions(+), 1442 deletions(-) diff --git a/modules/rivrAnalyticsAdapter.js b/modules/rivrAnalyticsAdapter.js index 14143f5f21d..867cc3d68bc 100644 --- a/modules/rivrAnalyticsAdapter.js +++ b/modules/rivrAnalyticsAdapter.js @@ -1,43 +1,27 @@ import {ajax} from 'src/ajax'; import adapter from 'src/AnalyticsAdapter'; -import find from 'core-js/library/fn/array/find'; import CONSTANTS from 'src/constants.json'; import adaptermanager from 'src/adaptermanager'; -import { logInfo, generateUUID, timestamp } from 'src/utils'; +import * as utils from 'src/utils'; const analyticsType = 'endpoint'; -const rivrUsrIdCookieKey = 'rvr_usr_id'; -const DEFAULT_HOST = 'tracker.rivr.simplaex.com'; -const DEFAULT_QUEUE_TIMEOUT = 4000; let rivrAnalytics = Object.assign(adapter({analyticsType}), { track({ eventType, args }) { - if (!rivrAnalytics.context) { + if (!window.rivraddon || !window.rivraddon.analytics || !window.rivraddon.analytics.getContext()) { return; } - logInfo(`ARGUMENTS FOR TYPE: ============= ${eventType}`, args); + utils.logInfo(`ARGUMENTS FOR TYPE: ============= ${eventType}`, args); let handler = null; switch (eventType) { case CONSTANTS.EVENTS.AUCTION_INIT: - logInfo(`CONSTANTS.EVENTS.AUCTION_INIT rivrAnalytics.context.auctionObject`, rivrAnalytics.context.auctionObject); - if (rivrAnalytics.context.queue) { - rivrAnalytics.context.queue.init(); - } - if (rivrAnalytics.context.auctionObject) { - rivrAnalytics.context.auctionObject = createNewAuctionObject(); - saveUnoptimisedAdUnits(); - fetchLocalization(); - } - handler = trackAuctionInit; - break; - case CONSTANTS.EVENTS.BID_WON: - handler = trackBidWon; - break; - case CONSTANTS.EVENTS.BID_TIMEOUT: - handler = trackBidTimeout; + handler = window.rivraddon.analytics.trackAuctionInit; break; case CONSTANTS.EVENTS.AUCTION_END: - handler = trackAuctionEnd; + handler = window.rivraddon.analytics.trackAuctionEnd; + break; + case CONSTANTS.EVENTS.BID_WON: + handler = window.rivraddon.analytics.trackBidWon; break; } if (handler) { @@ -46,422 +30,15 @@ let rivrAnalytics = Object.assign(adapter({analyticsType}), { } }); -export function sendAuction() { - if (rivrAnalytics.context.authToken) { - removeEmptyProperties(rivrAnalytics.context.auctionObject); - let auctionObject = rivrAnalytics.context.auctionObject; - let req = Object.assign({}, {Auction: auctionObject}); - rivrAnalytics.context.auctionObject = createNewAuctionObject(); - logInfo('sending request to analytics => ', req); - ajax( - `http://${rivrAnalytics.context.host}/${rivrAnalytics.context.clientID}/auctions`, - () => {}, - JSON.stringify(req), - { - contentType: 'application/json', - customHeaders: { - 'Authorization': 'Basic ' + rivrAnalytics.context.authToken - } - } - ); - } -}; - -export function sendImpressions() { - if (rivrAnalytics.context.authToken) { - let impressions = rivrAnalytics.context.queue.popAll(); - if (impressions.length !== 0) { - let impressionsReq = Object.assign({}, {impressions}); - logInfo('sending impressions request to analytics => ', impressionsReq); - ajax( - `http://${rivrAnalytics.context.host}/${rivrAnalytics.context.clientID}/impressions`, - () => {}, - JSON.stringify(impressionsReq), - { - contentType: 'application/json', - customHeaders: { - 'Authorization': 'Basic ' + rivrAnalytics.context.authToken - } - } - ); - } - } -}; - -function trackAuctionInit(args) { - rivrAnalytics.context.auctionTimeStart = Date.now(); - rivrAnalytics.context.auctionObject.id = args.auctionId; -}; - -function trackBidWon(args) { - setWinningBidStatus(args); -}; - -function setWinningBidStatus(args) { - let auctionObject = rivrAnalytics.context.auctionObject; - const bidderObjectForThisWonBid = find(auctionObject.bidders, (bidder) => { - return bidder.id === args.bidderCode; - }); - if (bidderObjectForThisWonBid) { - const bidObjectForThisWonBid = find(bidderObjectForThisWonBid.bids, (bid) => { - return bid.impId === args.adUnitCode; - }); - if (bidObjectForThisWonBid) { - bidObjectForThisWonBid.status = 1; - } - } -}; - -export function trackAuctionEnd(args) { - rivrAnalytics.context.auctionTimeEnd = Date.now(); - rivrAnalytics.context.auctionObject.bidders = buildBiddersArrayFromAuctionEnd(args); - rivrAnalytics.context.auctionObject.impressions = buildImpressionsArrayFromAuctionEnd(args); -}; - -function buildImpressionsArrayFromAuctionEnd(auctionEndEvent) { - return auctionEndEvent.adUnits.map((adUnit) => { - const impression = {}; - impression.id = adUnit.code; - impression.adType = 'unknown'; - impression.acceptedSizes = []; - const bidReceivedForThisAdUnit = find(auctionEndEvent.bidsReceived, (bidReceived) => { - return adUnit.code === bidReceived.adUnitCode; - }); - if (adUnit.mediaTypes) { - if (adUnit.mediaTypes.banner) { - buildAdTypeDependentFieldsForImpression(impression, 'banner', adUnit, bidReceivedForThisAdUnit); - } else if (adUnit.mediaTypes.video) { - buildAdTypeDependentFieldsForImpression(impression, 'video', adUnit, bidReceivedForThisAdUnit); - } - } - return impression; - }); -} - -function buildAdTypeDependentFieldsForImpression(impression, adType, adUnit, bidReceivedForThisAdUnit) { - impression.adType = adType; - impression.acceptedSizes = adUnit.mediaTypes[adType].sizes.map((acceptedSize) => { - return { - w: acceptedSize[0], - h: acceptedSize[1] - }; - }); - if (bidReceivedForThisAdUnit) { - impression[adType] = { - w: bidReceivedForThisAdUnit.width, - h: bidReceivedForThisAdUnit.height - }; - } -} - -function buildBiddersArrayFromAuctionEnd(auctionEndEvent) { - return auctionEndEvent.bidderRequests.map((bidderRequest) => { - const bidder = {}; - bidder.id = bidderRequest.bidderCode; - bidder.bids = bidderRequest.bids.map((bid) => { - const bidReceivedForThisRequest = find(auctionEndEvent.bidsReceived, (bidReceived) => { - return bidderRequest.bidderCode === bidReceived.bidderCode && - bid.bidId === bidReceived.adId && - bid.adUnitCode === bidReceived.adUnitCode; - }); - return { - adomain: [''], - clearPrice: 0.0, - impId: bid.adUnitCode, - price: bidReceivedForThisRequest ? bidReceivedForThisRequest.cpm : 0.0, - status: 0 - }; - }); - return bidder; - }); -} - -function trackBidTimeout(args) { - return [args]; -}; - -export function fetchLocalization() { - if (navigator.permissions) { - navigator.permissions.query({ name: 'geolocation' }).then((permission) => { - if (permission.status === 'granted') { - navigator.geolocation.getCurrentPosition((position) => { - setAuctionAbjectPosition(position); - }); - } - }); - } -} - -export function setAuctionAbjectPosition(position) { - rivrAnalytics.context.auctionObject.device.geo.lat = position.coords.latitude; - rivrAnalytics.context.auctionObject.device.geo.long = position.coords.longitude; -} - -function getPlatformType() { - if (navigator.userAgent.match(/mobile/i) || navigator.userAgent.match(/iPad|Android|Touch/i)) { - return 1; - } else { - return 2; - } -}; - -export function reportClickEvent(event) { - let link = event.currentTarget.getElementsByTagName('a')[0]; - let clickUrl; - if (link) { - clickUrl = link.getAttribute('href'); - } - let timestamp = new Date().toISOString(); - let requestId = generateUUID(); - let req = { - timestamp, - 'request_id': requestId, - 'click_url': clickUrl - }; - logInfo('Sending click events with parameters: ', req); - ajax( - `http://${rivrAnalytics.context.host}/${rivrAnalytics.context.clientID}/clicks`, - () => {}, - JSON.stringify(req), - { - contentType: 'application/json', - customHeaders: { - 'Authorization': 'Basic ' + rivrAnalytics.context.authToken - } - } - ); -}; - -function addClickHandler(bannerId) { - pinHandlerToHTMLElement(bannerId, dataLoaderForHandler, addClickListener); -}; - -function addDisplayedImpHandler(bannerId) { - pinHandlerToHTMLElement(bannerId, dataLoaderForHandler, impHandler); -}; - -export function pinHandlerToHTMLElement(elementId, dataLoaderForHandler, specializedHandler) { - function waitForElement() { - let element = document.getElementById(elementId); - if (!element) { - window.requestAnimationFrame(waitForElement); - } else { - dataLoaderForHandler(element, specializedHandler); - } - } - waitForElement(); -} - -export function dataLoaderForHandler(element, specializedHandler) { - function waitForElement() { - let iframe = element.getElementsByTagName('iframe')[0]; - if (!iframe) { - window.requestAnimationFrame(waitForElement); - } else { - let displayedImpression = iframe.contentDocument.getElementsByTagName('img').length > 0; - if (!displayedImpression) { - window.requestAnimationFrame(waitForElement); - } else { - specializedHandler(iframe); - } - } - } - waitForElement(); -}; - -function addClickListener(iframe) { - iframe.contentDocument.addEventListener('click', reportClickEvent); -} - -function impHandler(iframe) { - let timestamp = new Date().toISOString(); - let requestId = generateUUID(); - let adContainerId = iframe.parentElement.parentElement.id; - let impression = { - timestamp, - 'request_id': requestId, - 'tag_id': adContainerId - }; - if (rivrAnalytics.context.queue) { - rivrAnalytics.context.queue.push(impression); - } -} - -function addHandlers(bannersIds) { - bannersIds.forEach((bannerId) => { - addClickHandler(bannerId); - addDisplayedImpHandler(bannerId); - }) -}; - -export function createNewAuctionObject() { - const auction = { - id: '', - publisher: rivrAnalytics.context.clientID, - blockedCategories: [''], - timestamp: timestamp(), - user: { - id: rivrAnalytics.context.userId - }, - site: { - domain: window.location.host, - page: window.location.pathname, - categories: rivrAnalytics.context.siteCategories - }, - impressions: [], - bidders: [], - device: { - userAgent: navigator.userAgent, - browser: '', - deviceType: getPlatformType() - }, - 'ext.rivr.originalvalues': [], - 'ext.rivr.optimiser': localStorage.getItem('rivr_should_optimise') || 'unoptimised', - modelVersion: localStorage.getItem('rivr_model_version') || null, - } - - return auction; -}; - -export function saveUnoptimisedAdUnits() { - let units = rivrAnalytics.context.adUnits; - if (units) { - if (units.length > 0) { - let allUnits = concatAllUnits(units); - allUnits.forEach((adUnit) => { - adUnit.bids.forEach((bid) => { - let configForBidder = fetchConfigForBidder(bid.bidder); - if (configForBidder) { - let unOptimisedParamsField = createUnOptimisedParamsField(bid, configForBidder); - rivrAnalytics.context.auctionObject['ext.rivr.originalvalues'].push(unOptimisedParamsField); - } - }) - }); - } - } -}; - -export function concatAllUnits(units) { - return Array.prototype.concat.apply([], units); -} - -export function createUnOptimisedParamsField(bid, config) { - let floorPriceLabel = config['floorPriceLabel']; - let currencyLabel = config['currencyLabel']; - let pmpLabel = config['pmpLabel']; - return { - 'ext.rivr.demand_source_original': bid.bidder, - 'ext.rivr.bidfloor_original': bid.params[floorPriceLabel], - 'ext.rivr.currency_original': bid.params[currencyLabel], - 'ext.rivr.pmp_original': bid.params[pmpLabel], - } -} - -function fetchConfigForBidder(bidderName) { - let config = localStorage.getItem('rivr_config_string'); - if (config) { - let parsed = JSON.parse(config); - return parsed.demand.map((bidderConfig) => { - if (bidderName === bidderConfig.partner) { - return bidderConfig - }; - })[0]; - } -} -/** - * Expiring queue implementation. Fires callback on elapsed timeout since last last update or creation. - * @param callback - * @param ttl - * @constructor - */ -export function ExpiringQueue(sendImpressions, sendAuction, ttl, log) { - let queue = []; - let timeoutId; - - this.push = (event) => { - if (event instanceof Array) { - queue.push.apply(queue, event); - } else { - queue.push(event); - } - reset(); - }; - - this.popAll = () => { - let result = queue; - queue = []; - reset(); - return result; - }; - /** - * For test/debug purposes only - * @return {Array} - */ - this.peekAll = () => { - return queue; - }; - - this.init = reset; - - function reset() { - if (timeoutId) { - clearTimeout(timeoutId); - } - timeoutId = setTimeout(() => { - sendAuction(); - if (queue.length) { - sendImpressions(); - } - }, ttl); - } -}; - -function removeEmptyProperties(obj) { - Object.keys(obj).forEach(function(key) { - if (obj[key] && typeof obj[key] === 'object') removeEmptyProperties(obj[key]) - else if (obj[key] == null) delete obj[key] - }); -}; - -function getCookie(name) { - var value = '; ' + document.cookie; - var parts = value.split('; ' + name + '='); - if (parts.length == 2) return parts.pop().split(';').shift(); -} - -function storeAndReturnRivrUsrIdCookie() { - return document.cookie = 'rvr_usr_id=' + generateUUID(); -} - // save the base class function rivrAnalytics.originEnableAnalytics = rivrAnalytics.enableAnalytics; // override enableAnalytics so we can get access to the config passed in from the page rivrAnalytics.enableAnalytics = (config) => { - let copiedUnits; - if (config.options.adUnits) { - let stringifiedAdUnits = JSON.stringify(config.options.adUnits); - copiedUnits = JSON.parse(stringifiedAdUnits); - } - rivrAnalytics.context = { - userId: getCookie(rivrUsrIdCookieKey) || storeAndReturnRivrUsrIdCookie(), - host: config.options.host || DEFAULT_HOST, - auctionObject: {}, - adUnits: copiedUnits, - siteCategories: config.options.siteCategories || [], - clientID: config.options.clientID, - authToken: config.options.authToken, - queue: new ExpiringQueue(sendImpressions, sendAuction, config.options.queueTimeout || DEFAULT_QUEUE_TIMEOUT) - }; - - let bannersIds = config.options.bannersIds; - if (bannersIds) { - if (bannersIds.length > 0) { - addHandlers(config.options.bannersIds); - } + if (window.rivraddon && window.rivraddon.analytics) { + window.rivraddon.analytics.enableAnalytics(config, {utils, ajax}); + rivrAnalytics.originEnableAnalytics(config); } - logInfo('Rivr Analytics enabled with config', rivrAnalytics.context); - rivrAnalytics.originEnableAnalytics(config); }; adaptermanager.registerAnalyticsAdapter({ diff --git a/test/spec/modules/rivrAnalyticsAdapter_spec.js b/test/spec/modules/rivrAnalyticsAdapter_spec.js index 0fc20171e0a..5bd526579ac 100644 --- a/test/spec/modules/rivrAnalyticsAdapter_spec.js +++ b/test/spec/modules/rivrAnalyticsAdapter_spec.js @@ -1,10 +1,8 @@ import * as utils from 'src/utils'; import analyticsAdapter from 'modules/rivrAnalyticsAdapter'; import { - ExpiringQueue, - sendAuction, sendImpressions, - reportClickEvent, + handleClickEventWithClosureScope, createUnOptimisedParamsField, dataLoaderForHandler, pinHandlerToHTMLElement, @@ -12,6 +10,11 @@ import { createNewAuctionObject, concatAllUnits, trackAuctionEnd, + handleImpression, + getCookie, + storeAndReturnRivrUsrIdCookie, + arrayDifference, + activelyWaitForBannersToRender, } from 'modules/rivrAnalyticsAdapter'; import {expect} from 'chai'; import adaptermanager from 'src/adaptermanager'; @@ -28,12 +31,27 @@ describe('RIVR Analytics adapter', () => { const EMITTED_AUCTION_ID = 1; const TRACKER_BASE_URL_MOCK = 'tracker.rivr.simplaex.com'; const UUID_REG_EXP = new RegExp('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', 'i'); + const MOCK_RIVRADDON_CONTEXT = {}; let sandbox; let ajaxStub; + let rivraddonsEnableAnalyticsStub; + let rivraddonsTrackAuctionInitStub; + let rivraddonsTrackAuctionEndStub; + let rivraddonsTrackBidWonStub; let timer; before(() => { sandbox = sinon.sandbox.create(); + window.rivraddon = { + analytics: { + enableAnalytics: () => {}, + getContext: () => { return MOCK_RIVRADDON_CONTEXT; }, + trackAuctionInit: () => {}, + trackAuctionEnd: () => {}, + trackBidWon: () => {}, + } + }; + rivraddonsEnableAnalyticsStub = sandbox.stub(window.rivraddon.analytics, 'enableAnalytics'); }); beforeEach(() => { @@ -64,455 +82,77 @@ describe('RIVR Analytics adapter', () => { after(() => { sandbox.restore(); + delete window.rivraddon; }); - it('ExpiringQueue should call sendImpression callback after expiring queue timeout is elapsed', (done) => { - const sendImpressionMock = () => { - let elements = queue.popAll(); - expect(elements).to.be.eql([1, 2, 3, 4]); - elements = queue.popAll(); - expect(elements).to.have.lengthOf(0); - expect(Date.now()).to.be.equal(200); - done(); - }; - const sendAuctionMock = () => {}; - - let queue = new ExpiringQueue( - sendImpressionMock, - sendAuctionMock, - EXPIRING_QUEUE_TIMEOUT_MOCK); + it('enableAnalytics - should call rivraddon enableAnalytics with the correct arguments', () => { + // adaptermanager.enableAnalytics() is called in beforeEach. If just called here it doesn't seem to work. + const firstArgument = rivraddonsEnableAnalyticsStub.getCall(0).args[0]; + const secondArgument = rivraddonsEnableAnalyticsStub.getCall(0).args[1]; - queue.push(1); + expect(firstArgument.provider).to.be.equal('rivr'); - setTimeout(() => { - queue.push([2, 3]); - timer.tick(50); - }, 50); - setTimeout(() => { - queue.push([4]); - timer.tick(100); - }, 100); - timer.tick(50); + expect(secondArgument).to.have.property('utils'); + expect(secondArgument).to.have.property('ajax'); }); - it('enableAnalytics - should configure host and clientID in adapter context', () => { - // adaptermanager.enableAnalytics() is called in beforeEach. If only called here it doesn't seem to work. + it('Firing an event when rivraddon context is not defined it should do nothing', () => { + let rivraddonsGetContextStub = sandbox.stub(window.rivraddon.analytics, 'getContext'); + rivraddonsTrackAuctionInitStub = sandbox.stub(window.rivraddon.analytics, 'trackAuctionInit'); - expect(analyticsAdapter.context).to.have.property('host', TRACKER_BASE_URL_MOCK); - expect(analyticsAdapter.context).to.have.property('clientID', RVR_CLIENT_ID_MOCK); - }); - - it('enableAnalytics - should set a cookie containing a user id', () => { - expect(UUID_REG_EXP.test(analyticsAdapter.context.userId)).to.equal(true); - }); + expect(rivraddonsTrackAuctionInitStub.callCount).to.be.equal(0); - it('Firing AUCTION_INIT should set auction id of context when AUCTION_INIT event is fired', () => { events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: EMITTED_AUCTION_ID, config: {}, timeout: 3000}); - const auctionId = analyticsAdapter.context.auctionObject.id; - expect(auctionId).to.be.eql(EMITTED_AUCTION_ID); - }); - - it('Firing AUCTION_INIT when rivr_should_optimise and rivr_model_version are in local storage, sets ext.rivr.optimiser and modelVersion of in auction context', () => { - const RIVR_SHOULD_OPTIMISE_VALUE_MOCK = 'optimise'; - const RIVR_MODEL_VERSION_VALUE_MOCK = 'some model version'; - - localStorage.setItem('rivr_should_optimise', RIVR_SHOULD_OPTIMISE_VALUE_MOCK); - localStorage.setItem('rivr_model_version', RIVR_MODEL_VERSION_VALUE_MOCK); - - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 2, config: {}, timeout: 3000}); - - let auctionObject2 = analyticsAdapter.context.auctionObject; - - expect(auctionObject2['ext.rivr.optimiser']).to.be.eql(RIVR_SHOULD_OPTIMISE_VALUE_MOCK); - expect(auctionObject2['modelVersion']).to.be.eql(RIVR_MODEL_VERSION_VALUE_MOCK); - - localStorage.removeItem('rivr_should_optimise'); - localStorage.removeItem('rivr_model_version'); - }); - - it('Firing AUCTION_INIT , when auction object is already there and rivr_config_string is not in local storage, it does not save unoptimized params in rivr original values', () => { - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 3, config: {}, timeout: 3000}); - - expect(analyticsAdapter.context.auctionObject['ext.rivr.originalvalues']).to.be.eql([]); - }); - - it('Firing AUCTION_INIT when rivr_should_optimise and rivr_model_version are NOT in local storage, does not set ext.rivr.optimiser and modelVersion of in auction context', () => { - localStorage.removeItem('rivr_should_optimise'); - localStorage.removeItem('rivr_model_version'); - - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 3, config: {}, timeout: 3000}); - - let auctionObject3 = analyticsAdapter.context.auctionObject; - - expect(auctionObject3['ext.rivr.optimiser']).to.be.eql('unoptimised'); - expect(auctionObject3['modelVersion']).to.be.eql(null); - }); - - it('Firing AUCTION_END it sets auction time end to current time', () => { - analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); - - const MILLIS_FROM_EPOCH_TO_NOW_MOCK = 477; - timer.tick(MILLIS_FROM_EPOCH_TO_NOW_MOCK); - events.emit(CONSTANTS.EVENTS.AUCTION_END, BID_RESPONSE_MOCK); + expect(rivraddonsTrackAuctionInitStub.callCount).to.be.equal(0); - const endTime = analyticsAdapter.context.auctionTimeEnd; - expect(endTime).to.be.eql(MILLIS_FROM_EPOCH_TO_NOW_MOCK); + window.rivraddon.analytics.getContext.restore(); + window.rivraddon.analytics.trackAuctionInit.restore(); }); - it('Firing AUCTION_END populates impressions array in auction object', () => { - analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); + it('Firing AUCTION_INIT should call rivraddon trackAuctionInit passing the parameters', () => { + rivraddonsTrackAuctionInitStub = sandbox.stub(window.rivraddon.analytics, 'trackAuctionInit'); - events.emit(CONSTANTS.EVENTS.AUCTION_END, AUCTION_END_EVENT_WITH_AD_UNITS_AND_BID_RESPONSES_MOCK); + expect(rivraddonsTrackAuctionInitStub.callCount).to.be.equal(0); - const impressions = analyticsAdapter.context.auctionObject.impressions; - expect(impressions.length).to.be.eql(3); - }); - - it('Firing BID_WON should set to 1 the status of the corresponding bid', () => { - analyticsAdapter.context.auctionObject = utils.deepClone(AUCTION_OBJECT_AFTER_AUCTION_END_MOCK); - - events.emit(CONSTANTS.EVENTS.BID_WON, BID_WON_MOCK); - - expect(analyticsAdapter.context.auctionObject.bidders.length).to.be.equal(3); - - expect(analyticsAdapter.context.auctionObject.bidders[0].bids[0].status).to.be.equal(0); - - expect(analyticsAdapter.context.auctionObject.bidders[1].bids[0].status).to.be.equal(0); - - expect(analyticsAdapter.context.auctionObject.bidders[2].bids[0].status).to.be.equal(1); - expect(analyticsAdapter.context.auctionObject.bidders[2].bids[1].status).to.be.equal(0); - }); - - it('when auction is initialized and authToken is defined and ExpiringQueue ttl expires, it sends the auction', () => { - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: EMITTED_AUCTION_ID, config: {}, timeout: 3000}); - analyticsAdapter.context.authToken = 'anAuthToken'; - - expect(ajaxStub.notCalled).to.be.equal(true); - - timer.tick(EXPIRING_QUEUE_TIMEOUT + 500); - - expect(ajaxStub.calledOnce).to.be.equal(true); - }); - - it('when auction is initialized and authToken is defined and ExpiringQueue ttl expires, it resets auctionObject', () => { events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: EMITTED_AUCTION_ID, config: {}, timeout: 3000}); - analyticsAdapter.context.authToken = 'anAuthToken'; - events.emit(CONSTANTS.EVENTS.AUCTION_END, AUCTION_END_EVENT_WITH_AD_UNITS_AND_BID_RESPONSES_MOCK); - - let impressions = analyticsAdapter.context.auctionObject.impressions; - - expect(impressions.length).to.be.eql(3); - - timer.tick(EXPIRING_QUEUE_TIMEOUT + 500); - - let impressionsAfterSend = analyticsAdapter.context.auctionObject.impressions; - let biddersAfterSend = analyticsAdapter.context.auctionObject.bidders; - - expect(impressionsAfterSend.length).to.be.eql(0); - expect(biddersAfterSend.length).to.be.eql(0); - }); - - it('sendAuction(), when authToken is defined, it fires call clearing empty payload properties', () => { - analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); - analyticsAdapter.context.authToken = 'anAuthToken'; - analyticsAdapter.context.auctionObject.nullProperty = null; - analyticsAdapter.context.auctionObject.notNullProperty = 'aValue'; - - sendAuction(); - - expect(ajaxStub.getCall(0).args[0]).to.match(/http:\/\/tracker.rivr.simplaex.com\/(\w+)\/auctions/); - - const payload = JSON.parse(ajaxStub.getCall(0).args[2]); - - expect(payload.Auction.notNullProperty).to.be.equal('aValue'); - expect(payload.nullProperty).to.be.equal(undefined); - - analyticsAdapter.context.authToken = undefined; - }); - - it('sendAuction(), when authToken is not defined, it does not fire call', () => { - analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); - analyticsAdapter.context.authToken = undefined; - analyticsAdapter.context.auctionObject.nullProperty = null; - analyticsAdapter.context.auctionObject.notNullProperty = 'aValue'; - - expect(ajaxStub.callCount).to.be.equal(0); - - sendAuction(); - - expect(ajaxStub.callCount).to.be.equal(0); - }); - - it('sendImpressions(), when authToken is not defined, it does not fire call', () => { - analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); - analyticsAdapter.context.authToken = undefined; - analyticsAdapter.context.auctionObject.nullProperty = null; - analyticsAdapter.context.auctionObject.notNullProperty = 'aValue'; - - expect(ajaxStub.callCount).to.be.equal(0); - - sendImpressions(); - - expect(ajaxStub.callCount).to.be.equal(0); - }); - - it('sendImpressions(), when authToken is defined and there are impressions, it sends impressions to the tracker', () => { - const aMockString = 'anImpressionPropertyValue'; - const IMPRESSION_MOCK = { anImpressionProperty: aMockString }; - const CLIENT_ID_MOCK = 'aClientID'; - analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); - analyticsAdapter.context.authToken = 'anAuthToken'; - analyticsAdapter.context.clientID = CLIENT_ID_MOCK; - analyticsAdapter.context.queue = new ExpiringQueue( - () => {}, - () => {}, - EXPIRING_QUEUE_TIMEOUT_MOCK - ); - - analyticsAdapter.context.queue.push(IMPRESSION_MOCK); - - expect(ajaxStub.callCount).to.be.equal(0); - - sendImpressions(); - - const payload = JSON.parse(ajaxStub.getCall(0).args[2]); - - expect(ajaxStub.callCount).to.be.equal(1); - expect(payload.impressions.length).to.be.equal(1); - expect(ajaxStub.getCall(0).args[0]).to.match(/http:\/\/tracker.rivr.simplaex.com\/aClientID\/impressions/); - expect(payload.impressions[0].anImpressionProperty).to.be.equal(aMockString); - }); - - it('reportClickEvent() calls endpoint', () => { - const CLIENT_ID_MOCK = 'aClientId'; - const AUTH_TOKEN_MOCK = 'aToken'; - const CLICK_URL_MOCK = 'clickURLMock'; - const EVENT_MOCK = { - currentTarget: { - getElementsByTagName: () => { - return [ - { - getAttribute: (attributeName) => { - return CLICK_URL_MOCK; - } - } - ] - } - } - }; - analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); - analyticsAdapter.context.authToken = AUTH_TOKEN_MOCK; - analyticsAdapter.context.clientID = CLIENT_ID_MOCK; - analyticsAdapter.context.auctionObject.nullProperty = null; - analyticsAdapter.context.auctionObject.notNullProperty = 'aValue'; - - expect(ajaxStub.callCount).to.be.equal(0); - - reportClickEvent(EVENT_MOCK); - - const payload = JSON.parse(ajaxStub.getCall(0).args[2]); - const options = ajaxStub.getCall(0).args[3]; - - expect(ajaxStub.callCount).to.be.equal(1); - expect(ajaxStub.getCall(0).args[0]).to.match(/http:\/\/tracker.rivr.simplaex.com\/aClientId\/clicks/); - expect(options.customHeaders.Authorization).to.equal('Basic aToken'); - expect(payload.timestamp).to.be.equal('1970-01-01T00:00:00.000Z'); - expect(payload.request_id).to.be.a('string'); - expect(payload.click_url).to.be.equal(CLICK_URL_MOCK); - }); - - it('createUnOptimisedParamsField(), creates object with unoptimized properties', () => { - const CONFIG_FOR_BIDDER_MOCK = { - floorPriceLabel: 'floorPriceLabelForTestBidder', - currencyLabel: 'currencyLabelForTestBidder', - pmpLabel: 'pmpLabelForTestBidder', - }; - const BID_MOCK = { - bidder: 'aBidder', - params: { - floorPriceLabelForTestBidder: 'theOriginalBidFloor', - currencyLabelForTestBidder: 'theOriginalCurrency', - pmpLabelForTestBidder: 'theOriginalPmp', - }, - }; - - const result = createUnOptimisedParamsField(BID_MOCK, CONFIG_FOR_BIDDER_MOCK); - - expect(result['ext.rivr.demand_source_original']).to.be.equal('aBidder'); - expect(result['ext.rivr.bidfloor_original']).to.be.equal('theOriginalBidFloor'); - expect(result['ext.rivr.currency_original']).to.be.equal('theOriginalCurrency'); - expect(result['ext.rivr.pmp_original']).to.be.equal('theOriginalPmp'); - }); - - it('dataLoaderForHandler(), when iframe and the ad image contained in it are there, it calls the specialized handler', () => { - const MOCK_ELEMENT = { - getElementsByTagName: () => { - return [ - { - contentDocument: { - getElementsByTagName: () => { - return ['displayedImpressionMock'] - } - }, - aDummyProperty: 'aDummyPropertyValue' - } - ] - } - }; - - var specializedHandlerSpy = sinon.spy(); - - expect(specializedHandlerSpy.callCount).to.be.equal(0); - - dataLoaderForHandler(MOCK_ELEMENT, specializedHandlerSpy); - - expect(specializedHandlerSpy.callCount).to.be.equal(1); - expect(specializedHandlerSpy.firstCall.args[0].aDummyProperty).to.be.equal('aDummyPropertyValue'); - expect(specializedHandlerSpy.firstCall.args[0].contentDocument.getElementsByTagName()[0]).to.be.equal('displayedImpressionMock'); - }); - - it('dataLoaderForHandler(), when iframe is not there, it requests animation frame', () => { - const MOCK_ELEMENT = { - getElementsByTagName: () => { - return [ - { - contentDocument: { - getElementsByTagName: () => { - return [] - } - }, - } - ] - } - }; - - const specializedHandlerSpy = sinon.spy(); - const requestAnimationFrameStub = sinon.stub(window, 'requestAnimationFrame'); - expect(requestAnimationFrameStub.callCount).to.be.equal(0); - - dataLoaderForHandler(MOCK_ELEMENT, specializedHandlerSpy); + expect(rivraddonsTrackAuctionInitStub.callCount).to.be.equal(1); - expect(requestAnimationFrameStub.callCount).to.be.equal(1); + const firstArgument = rivraddonsTrackAuctionInitStub.getCall(0).args[0]; + expect(firstArgument.auctionId).to.be.equal(EMITTED_AUCTION_ID); - requestAnimationFrameStub.restore(); + window.rivraddon.analytics.trackAuctionInit.restore(); }); - it('pinHandlerToHTMLElement(), when element is there, it calls dataLoaderForHandler', () => { - const ELEMENT_MOCK = { - anElementProperty: 'aValue' - } - const dataLoaderForHandlerSpy = sinon.spy(); - sinon.stub(window, 'requestAnimationFrame'); + it('Firing AUCTION_END should call rivraddon trackAuctionEnd passing the parameters', () => { + rivraddonsTrackAuctionEndStub = sandbox.stub(window.rivraddon.analytics, 'trackAuctionEnd'); - sinon.stub(document, 'getElementById').returns(ELEMENT_MOCK); + expect(rivraddonsTrackAuctionEndStub.callCount).to.be.equal(0); - expect(dataLoaderForHandlerSpy.callCount).to.be.equal(0); + events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: EMITTED_AUCTION_ID}); - pinHandlerToHTMLElement('', dataLoaderForHandlerSpy, () => {}); + expect(rivraddonsTrackAuctionEndStub.callCount).to.be.equal(1); - expect(dataLoaderForHandlerSpy.callCount).to.be.equal(1); - expect(dataLoaderForHandlerSpy.firstCall.args[0].anElementProperty).to.be.equal('aValue'); + const firstArgument = rivraddonsTrackAuctionEndStub.getCall(0).args[0]; + expect(firstArgument.auctionId).to.be.equal(EMITTED_AUCTION_ID); - window.requestAnimationFrame.restore(); - document.getElementById.restore(); + window.rivraddon.analytics.trackAuctionEnd.restore(); }); - it('pinHandlerToHTMLElement(), when element is not there, it requests animation frame', () => { - const dataLoaderForHandlerSpy = sinon.spy(); - const requestAnimationFrameStub = sinon.stub(window, 'requestAnimationFrame'); + it('Firing BID_WON should call rivraddon trackBidWon passing the parameters', () => { + rivraddonsTrackBidWonStub = sandbox.stub(window.rivraddon.analytics, 'trackBidWon'); - sinon.stub(document, 'getElementById').returns(undefined); + expect(rivraddonsTrackBidWonStub.callCount).to.be.equal(0); - expect(requestAnimationFrameStub.callCount).to.be.equal(0); + events.emit(CONSTANTS.EVENTS.BID_WON, {auctionId: EMITTED_AUCTION_ID}); - pinHandlerToHTMLElement('', dataLoaderForHandlerSpy, () => {}); + expect(rivraddonsTrackBidWonStub.callCount).to.be.equal(1); - expect(dataLoaderForHandlerSpy.callCount).to.be.equal(0); - expect(requestAnimationFrameStub.callCount).to.be.equal(1); + const firstArgument = rivraddonsTrackBidWonStub.getCall(0).args[0]; + expect(firstArgument.auctionId).to.be.equal(EMITTED_AUCTION_ID); - requestAnimationFrameStub.restore(); - document.getElementById.restore(); - }); - - it('setAuctionAbjectPosition(), it sets latitude and longitude in auction object', () => { - const POSITION_MOCK = { - coords: { - latitude: 'aLatitude', - longitude: 'aLongitude', - } - } - analyticsAdapter.context = utils.deepClone(CONTEXT_AFTER_AUCTION_INIT); - - setAuctionAbjectPosition(POSITION_MOCK); - - expect(analyticsAdapter.context.auctionObject.device.geo.lat).to.be.equal('aLatitude'); - }); - - it('createNewAuctionObject(), it creates a new auction object', () => { - const MILLIS_FROM_EPOCH_TO_NOW_MOCK = 123456; - timer.tick(MILLIS_FROM_EPOCH_TO_NOW_MOCK); - - const result = createNewAuctionObject(); - - expect(result.device.deviceType).to.be.equal(2); - expect(result.publisher).to.be.equal(RVR_CLIENT_ID_MOCK); - expect(result.device.userAgent).to.be.equal(navigator.userAgent); - expect(result.timestamp).to.be.equal(MILLIS_FROM_EPOCH_TO_NOW_MOCK); - expect(result.site.domain.substring(0, 9)).to.be.equal('localhost'); - expect(result.site.page).to.be.equal('/context.html'); - expect(result.site.categories).to.be.equal(SITE_CATEGORIES_MOCK); - }); - - it('concatAllUnits(), returns a flattened array with all banner and video adunits', () => { - const allAdUnits = [BANNER_AD_UNITS_MOCK, VIDEO_AD_UNITS_MOCK]; - - const result = concatAllUnits(allAdUnits); - - expect(result.length).to.be.eql(2); - expect(result[0].code).to.be.eql('banner-container1'); - expect(result[1].code).to.be.eql('video'); - }); - - it('trackAuctionEnd(), populates the bidders array from bidderRequests and bidsReceived', () => { - trackAuctionEnd(AUCTION_END_EVENT_WITH_BID_REQUESTS_AND_BID_RESPONSES_MOCK); - - const result = analyticsAdapter.context.auctionObject.bidders; - - expect(result.length).to.be.eql(3); - - expect(result[0].id).to.be.eql('vuble'); - expect(result[0].bids[0].price).to.be.eql(0); - - expect(result[1].id).to.be.eql('vertamedia'); - expect(result[1].bids[0].price).to.be.eql(0); - - expect(result[2].id).to.be.eql('appnexus'); - expect(result[2].bids[0].price).to.be.eql(0.5); - expect(result[2].bids[0].impId).to.be.eql('/19968336/header-bid-tag-0'); - expect(result[2].bids[1].price).to.be.eql(0.7); - expect(result[2].bids[1].impId).to.be.eql('/19968336/header-bid-tag-1'); - }); - - it('trackAuctionEnd(), populates the impressions array from adUnits', () => { - trackAuctionEnd(AUCTION_END_EVENT_WITH_AD_UNITS_AND_BID_RESPONSES_MOCK); - - const result = analyticsAdapter.context.auctionObject.impressions; - - expect(result.length).to.be.eql(3); - - expect(result[0].id).to.be.eql('/19968336/header-bid-tag-0'); - expect(result[0].adType).to.be.eql('banner'); - - expect(result[1].id).to.be.eql('/19968336/header-bid-tag-1'); - expect(result[1].adType).to.be.eql('banner'); - expect(result[1].acceptedSizes).to.be.eql([{w: 728, h: 90}, {w: 970, h: 250}]); - expect(result[1].banner).to.be.eql({w: 300, h: 250}); - - expect(result[2].id).to.be.eql('video'); - expect(result[2].adType).to.be.eql('video'); - expect(result[2].acceptedSizes).to.be.eql([{w: 640, h: 360}, {w: 640, h: 480}]); + window.rivraddon.analytics.trackBidWon.restore(); }); const BANNER_AD_UNITS_MOCK = [ @@ -540,593 +180,4 @@ describe('RIVR Analytics adapter', () => { ] } ]; - - const VIDEO_AD_UNITS_MOCK = [ - { - code: 'video', - mediaTypes: { - video: { - context: 'outstream', - sizes: [[640, 360], [640, 480]] - } - }, - bids: [ - { - bidder: 'vuble', - params: { - env: 'net', - pubId: '18', - zoneId: '12345', - referrer: 'http://www.vuble.tv/', // optional - floorPrice: 5.00 // optional - } - }, - { - bidder: 'vertamedia', - params: { - aid: 331133 - } - } - ] - }]; - - const REQUEST = { - bidderCode: 'adapter', - auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', - bidderRequestId: '1a6fc81528d0f6', - bids: [{ - bidder: 'adapter', - params: {}, - adUnitCode: 'container-1', - transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', - sizes: [[300, 250]], - bidId: '208750227436c1', - bidderRequestId: '1a6fc81528d0f6', - auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' - }], - auctionStart: 1509369418387, - timeout: 3000, - start: 1509369418389 - }; - - const REQUEST2 = { - bidderCode: 'adapter', - auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', - bidderRequestId: '1a6fc81528d0f6', - bids: [{ - bidder: 'adapter', - params: {}, - adUnitCode: 'container-1', - transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', - sizes: [[300, 250]], - bidId: 'request2id', - bidderRequestId: '1a6fc81528d0f6', - auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' - }], - auctionStart: 1509369418387, - timeout: 3000, - start: 1509369418389 - }; - - const REQUEST3 = { - bidderCode: 'adapter', - auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', - bidderRequestId: '1a6fc81528d0f6', - bids: [{ - bidder: 'adapter', - params: {}, - adUnitCode: 'container-1', - transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', - sizes: [[300, 250]], - bidId: 'request3id', - bidderRequestId: '1a6fc81528d0f6', - auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' - }], - auctionStart: 1509369418387, - timeout: 3000, - start: 1509369418389 - }; - - const BID_RESPONSE_MOCK = { - bidderCode: 'adapter', - width: 300, - height: 250, - statusMessage: 'Bid available', - getStatusCode: () => 1, - adId: '208750227436c1', - mediaType: 'banner', - cpm: 0.015, - creativeId: 999, - ad: '', - auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', - responseTimestamp: 1509369418832, - requestTimestamp: 1509369418389, - bidder: 'adapter', - adUnitCode: 'container-1', - timeToRespond: 443, - currency: 'EU', - size: '300x250' - }; - - const BID_WON_MOCK = { - bidderCode: 'appnexus', - width: 300, - height: 600, - statusMessage: 'Bid available', - adId: '63301dc59deb3b', - mediaType: 'banner', - source: 'client', - requestId: '63301dc59deb3b', - cpm: 0.5, - creativeId: 98493581, - currency: 'USD', - netRevenue: true, - ttl: 300, - appnexus: { - buyerMemberId: 9325 - }, - ad: '...HTML CONTAINING THE AD...', - auctionId: '1825871c-b4c2-401a-b219-64549d412495', - responseTimestamp: 1540560447955, - requestTimestamp: 1540560447622, - bidder: 'appnexus', - adUnitCode: '/19968336/header-bid-tag-0', - timeToRespond: 333, - pbLg: '0.50', - pbMg: '0.50', - pbHg: '0.50', - pbAg: '0.50', - pbDg: '0.50', - pbCg: '', - size: '300x600', - adserverTargeting: { - hb_bidder: 'appnexus', - hb_adid: '63301dc59deb3b', - hb_pb: '0.50', - hb_size: '300x600', - hb_source: 'client', - hb_format: 'banner' - }, - status: 'rendered', - params: [ - { - placementId: 13144370 - } - ] - }; - - const CONTEXT_AFTER_AUCTION_INIT = { - host: TRACKER_BASE_URL_MOCK, - clientID: RVR_CLIENT_ID_MOCK, - queue: { - mockProp: 'mockValue' - }, - auctionObject: { - id: null, - timestamp: null, - at: null, - bcat: [], - imp: [], - app: { - id: null, - name: null, - domain: window.location.href, - bundle: null, - cat: [], - publisher: { - id: null, - name: null - } - }, - site: { - id: null, - name: null, - domain: window.location.href, - cat: [], - publisher: { - id: null, - name: null - } - }, - device: { - geo: {} - }, - user: { - id: null, - yob: null, - gender: null, - }, - bidResponses: [], - bidRequests: [], - 'ext.rivr.optimiser': 'unoptimised', - modelVersion: null, - 'ext.rivr.originalvalues': [] - } - }; - - const AUCTION_END_EVENT_WITH_AD_UNITS_AND_BID_RESPONSES_MOCK = { - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - auctionStart: 1540560217395, - auctionEnd: 1540560217703, - auctionStatus: 'completed', - adUnits: [ - { - code: '/19968336/header-bid-tag-0', - mediaTypes: { - banner: { - sizes: [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ] - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 13144370 - }, - crumbs: { - pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' - } - } - ], - transactionId: 'aee9bf8d-6d8f-425b-a42a-52c875371ebc', - sizes: [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ] - }, - { - code: '/19968336/header-bid-tag-1', - mediaTypes: { - banner: { - sizes: [ - [ - 728, - 90 - ], - [ - 970, - 250 - ] - ] - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 13144370 - }, - crumbs: { - pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' - } - } - ], - transactionId: '3d5f0f89-e9cd-4714-b314-3f0fb7fcf8e3', - sizes: [ - [ - 728, - 90 - ], - [ - 970, - 250 - ] - ] - }, - { - code: 'video', - mediaTypes: { - video: { - context: 'outstream', - sizes: [ - [ - 640, - 360 - ], - [ - 640, - 480 - ] - ] - } - }, - bids: [ - { - bidder: 'vuble', - params: { - env: 'net', - pubId: '18', - zoneId: '12345', - referrer: 'http: //www.vuble.tv/', - floorPrice: 5 - }, - crumbs: { - pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' - } - }, - { - bidder: 'vertamedia', - params: { - aid: 331133 - }, - crumbs: { - pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' - } - } - ], - transactionId: 'df11a105-4eef-4ceb-bbc3-a49224f7c49d' - } - ], - adUnitCodes: [ - '/19968336/header-bid-tag-0', - '/19968336/header-bid-tag-1', - 'video' - ], - bidderRequests: [], - bidsReceived: [ - { - bidderCode: 'appnexus', - width: 300, - height: 250, - statusMessage: 'Bid available', - adId: '6de82e80757293', - mediaType: 'banner', - source: 'client', - requestId: '6de82e80757293', - cpm: 0.5, - creativeId: 96846035, - currency: 'USD', - netRevenue: true, - ttl: 300, - appnexus: { - buyerMemberId: 9325 - }, - ad: '...HTML CONTAINING THE AD...', - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - responseTimestamp: 1540560217636, - requestTimestamp: 1540560217403, - bidder: 'appnexus', - adUnitCode: '/19968336/header-bid-tag-1', - timeToRespond: 233, - pbLg: '0.50', - pbMg: '0.50', - pbHg: '0.50', - pbAg: '0.50', - pbDg: '0.50', - pbCg: '', - size: '728x90', - adserverTargeting: { - hb_bidder: 'appnexus', - hb_adid: '7e1a45d85bd57c', - hb_pb: '0.50', - hb_size: '728x90', - hb_source: 'client', - hb_format: 'banner' - } - } - ], - winningBids: [], - timeout: 3000 - }; - - const AUCTION_OBJECT_AFTER_AUCTION_END_MOCK = { - bidders: [ - { - id: 'vuble', - bids: [ - { - adomain: [ - '' - ], - clearPrice: 0, - impId: 'video', - price: 0, - status: 0 - } - ] - }, - { - id: 'vertamedia', - bids: [ - { - adomain: [ - '' - ], - clearPrice: 0, - impId: 'video', - price: 0, - status: 0 - } - ] - }, - { - id: 'appnexus', - bids: [ - { - adomain: [ - '' - ], - clearPrice: 0, - impId: '/19968336/header-bid-tag-0', - price: 0.5, - status: 0 - }, - { - adomain: [ - '' - ], - clearPrice: 0, - impId: '/19968336/header-bid-tag-1', - price: 0.7, - status: 0 - } - ] - } - ], - impressions: [] - }; - - const AUCTION_END_EVENT_WITH_BID_REQUESTS_AND_BID_RESPONSES_MOCK = { - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - auctionStart: 1540560217395, - auctionEnd: 1540560217703, - auctionStatus: 'completed', - adUnits: [], - adUnitCodes: [ - '/19968336/header-bid-tag-0', - '/19968336/header-bid-tag-1', - 'video' - ], - bidderRequests: [ - { - bidderCode: 'vuble', - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - bidderRequestId: '1bb11e055665bc', - bids: [ - { - bidder: 'vuble', - crumbs: { - pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' - }, - adUnitCode: 'video', - transactionId: 'df11a105-4eef-4ceb-bbc3-a49224f7c49d', - bidId: '2859b890da7418', - bidderRequestId: '1bb11e055665bc', - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - src: 'client', - bidRequestsCount: 1 - } - ], - auctionStart: 1540560217395, - timeout: 3000, - refererInfo: { - referer: 'http: //localhost: 8080/', - reachedTop: true, - numIframes: 0, - stack: [ - 'http://localhost:8080/' - ] - }, - start: 1540560217401, - doneCbCallCount: 0 - }, - { - bidderCode: 'vertamedia', - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - bidderRequestId: '3c2cbf7f1466cb', - bids: [ - { - bidder: 'vertamedia', - params: { - aid: 331133 - }, - crumbs: { - pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' - }, - adUnitCode: 'video', - transactionId: 'df11a105-4eef-4ceb-bbc3-a49224f7c49d', - bidId: '45b3ad5c2dc794', - bidderRequestId: '3c2cbf7f1466cb', - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - bidRequestsCount: 1 - } - ], - auctionStart: 1540560217395, - timeout: 3000, - start: 1540560217401 - }, - { - bidderCode: 'appnexus', - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - bidderRequestId: '5312eef4418cd7', - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 13144370 - }, - crumbs: { - pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' - }, - adUnitCode: '/19968336/header-bid-tag-0', - transactionId: 'aee9bf8d-6d8f-425b-a42a-52c875371ebc', - bidId: '6de82e80757293', - bidderRequestId: '5312eef4418cd7', - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - src: 'client', - bidRequestsCount: 1 - }, - { - bidder: 'appnexus', - params: { - placementId: 13144370 - }, - crumbs: { - pubcid: '87eb6b0e-e1a8-42a9-b58d-e93a382e2d9b' - }, - adUnitCode: '/19968336/header-bid-tag-1', - transactionId: '3d5f0f89-e9cd-4714-b314-3f0fb7fcf8e3', - bidId: '7e1a45d85bd57c', - bidderRequestId: '5312eef4418cd7', - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - src: 'client', - bidRequestsCount: 1 - } - ], - auctionStart: 1540560217395, - timeout: 3000, - start: 1540560217403, - doneCbCallCount: 0 - } - ], - bidsReceived: [ - { - bidderCode: 'appnexus', - adId: '6de82e80757293', - mediaType: 'banner', - source: 'client', - requestId: '6de82e80757293', - cpm: 0.5, - creativeId: 96846035, - appnexus: { - buyerMemberId: 9325 - }, - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - bidder: 'appnexus', - adUnitCode: '/19968336/header-bid-tag-0', - }, - { - bidderCode: 'appnexus', - adId: '7e1a45d85bd57c', - mediaType: 'banner', - source: 'client', - requestId: '7e1a45d85bd57c', - cpm: 0.7, - creativeId: 96846035, - appnexus: { - buyerMemberId: 9325 - }, - auctionId: 'f6c1d093-14a3-4ade-bc7d-1de37e7cbdb2', - bidder: 'appnexus', - adUnitCode: '/19968336/header-bid-tag-1', - } - ], - winningBids: [], - timeout: 3000 - }; }); From e5f425531ed300350f88b32749bef13baaee56bc Mon Sep 17 00:00:00 2001 From: "N. Faure" Date: Wed, 19 Dec 2018 16:24:54 +0100 Subject: [PATCH 0906/1594] Fix multi-bid adId in Criteo bid adapter (#3340) * Fix multi-bid adId in Criteo bid adapter A single bid request can generate multiple bids if it has multiple sizes. However, by default 'adId' will be filled with the bid request's 'bidId' field, so if we create two bids from the same bid request, they will share the same 'adId'. Because of this, Prebid will not know which bid to use once DFP makes either of those bids win, always taking the first one (see 'auctionManager.findBidByAdId' used in 'pbjs.renderAd'). * Increment Criteo adapter version * Add test for Criteo multi-bid fix --- modules/criteoBidAdapter.js | 3 +- test/spec/modules/criteoBidAdapter_spec.js | 38 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 8bf92c07f00..7ed6c42ac23 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -6,7 +6,7 @@ import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -const ADAPTER_VERSION = 15; +const ADAPTER_VERSION = 16; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -98,6 +98,7 @@ export const spec = { const bidId = bidRequest.bidId; const bid = { requestId: bidId, + adId: slot.bidId || utils.getUniqueIdentifierStr(), cpm: slot.cpm, currency: slot.currency, netRevenue: true, diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 6dbf51932a0..34fa111260b 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -1,5 +1,7 @@ import { expect } from 'chai'; import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter'; +import * as bidfactory from 'src/bidfactory'; +import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; describe('The Criteo bidding adapter', function () { @@ -241,6 +243,7 @@ describe('The Criteo bidding adapter', function () { body: { slots: [{ impid: 'test-requestId', + bidId: 'abc123', cpm: 1.23, creative: 'test-ad', width: 728, @@ -261,6 +264,7 @@ describe('The Criteo bidding adapter', function () { const bids = spec.interpretResponse(response, request); expect(bids).to.have.lengthOf(1); expect(bids[0].requestId).to.equal('test-bidId'); + expect(bids[0].adId).to.equal('abc123'); expect(bids[0].cpm).to.equal(1.23); expect(bids[0].ad).to.equal('test-ad'); expect(bids[0].width).to.equal(728); @@ -297,6 +301,40 @@ describe('The Criteo bidding adapter', function () { expect(bids[0].width).to.equal(728); expect(bids[0].height).to.equal(90); }); + + it('should generate unique adIds if none are returned by the endpoint', function () { + const response = { + body: { + slots: [{ + impid: 'test-requestId', + cpm: 1.23, + creative: 'test-ad', + width: 300, + height: 250, + }, { + impid: 'test-requestId', + cpm: 4.56, + creative: 'test-ad', + width: 728, + height: 90, + }], + }, + }; + const request = { + bidRequests: [{ + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + sizes: [[300, 250], [728, 90]], + params: { + networkId: 456, + } + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(2); + const prebidBids = bids.map(bid => Object.assign(bidfactory.createBid(CONSTANTS.STATUS.GOOD, request.bidRequests[0]), bid)); + expect(prebidBids[0].adId).to.not.equal(prebidBids[1].adId); + }); }); describe('cryptoVerify', function () { From e47602142febf3469672fdcfa6f1f1574ec29a46 Mon Sep 17 00:00:00 2001 From: telariaEng <36203956+telariaEng@users.noreply.github.com> Date: Thu, 20 Dec 2018 12:04:41 -0800 Subject: [PATCH 0907/1594] Modified the Telaria Bid Adapter to use bid.mediaTypes.video.playerSize instead of bid.sizes (#3377) * Added telaria bid adapter * more documentation * Added more test cases. And improved some code in the adapter * Removed the check for optional params, they are handled in the server. Also updated certain param names used in the test spec. * added some spaces to fix CircleCI tests * added some spaces to fix CircleCI tests * fixed code indentation in /spec/AnalyticsAdapter_spec.js which causing the CircleCI tests to fail. * Reverted the changes * merged with prebid master. * creative Id is required when we build a response but our server doesn't always have the crid, so using a sentinel value when we don't have the crid. * - removed an un used method - Removed the package-lock file. * merging to master * updated telaria bid adapter to use player size provided by the bid.mediaTypes.video.playerSize instead of bid.sizes. https://github.com/prebid/Prebid.js/issues/3331 * - removed the requirement for having player size - updated the test spec to reflect the above change - removed changes to the package-lock.json file. * added a param to the ad call url to let us know that the request is coming via hb. * to lower casing the bidder code. --- modules/telariaBidAdapter.js | 50 ++++++----- test/spec/modules/telariaBidAdapter_spec.js | 92 +++++++++++++-------- 2 files changed, 87 insertions(+), 55 deletions(-) diff --git a/modules/telariaBidAdapter.js b/modules/telariaBidAdapter.js index e59ed6cd0f6..7bbd7573307 100644 --- a/modules/telariaBidAdapter.js +++ b/modules/telariaBidAdapter.js @@ -1,7 +1,6 @@ import * as utils from 'src/utils'; import * as bidfactory from 'src/bidfactory'; import {registerBidder} from 'src/adapters/bidderFactory'; -import {config} from 'src/config'; import {VIDEO} from '../src/mediaTypes'; import {STATUS} from 'src/constants'; @@ -24,17 +23,18 @@ export const spec = { /** * Make a server request from the list of BidRequests. * @param validBidRequests list of valid bid requests that have passed isBidRequestValid check + * @param bidderRequest * @returns {Array} of url objects */ - buildRequests: function (validBidRequests) { + buildRequests: function (validBidRequests, bidderRequest) { let requests = []; validBidRequests.forEach(bid => { - let url = generateUrl(bid); + let url = generateUrl(bid, bidderRequest); if (url) { requests.push({ method: 'GET', - url: generateUrl(bid), + url: generateUrl(bid, bidderRequest), bidId: bid.bidId, vastUrl: url.split('&fmt=json')[0] }); @@ -84,7 +84,7 @@ export const spec = { utils.logError(errorMessage); } else if (bidResult.seatbid && bidResult.seatbid.length > 0) { bidResult.seatbid[0].bid.forEach(tag => { - bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, bidResult.seatbid[0].seat)); + bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, bidResult.seatbid[0].seat.toLowerCase())); }); } @@ -112,28 +112,36 @@ export const spec = { * Generates the url based on the parameters given. Sizes, supplyCode & adCode are required. * The format is: [L,W] or [[L1,W1],...] * @param bid + * @param bidderRequest * @returns {string} */ -function generateUrl(bid) { - let width, height; - if (!bid.sizes) { - return ''; +function generateUrl(bid, bidderRequest) { + let playerSize = (bid.mediaTypes && bid.mediaTypes.video && bid.mediaTypes.video.playerSize); + if (!playerSize) { + utils.logWarn('Although player size isn\'t required it is highly recommended'); } - if (utils.isArray(bid.sizes) && (bid.sizes.length === 2) && (!isNaN(bid.sizes[0]) && !isNaN(bid.sizes[1]))) { - width = bid.sizes[0]; - height = bid.sizes[1]; - } else if (typeof bid.sizes === 'object') { - // take the primary (first) size from the array - width = bid.sizes[0][0]; - height = bid.sizes[0][1]; + let width, height; + if (playerSize) { + if (utils.isArray(playerSize) && (playerSize.length === 2) && (!isNaN(playerSize[0]) && !isNaN(playerSize[1]))) { + width = playerSize[0]; + height = playerSize[1]; + } else if (typeof playerSize === 'object') { + width = playerSize[0][0]; + height = playerSize[0][1]; + } } - if (width && height && bid.params.supplyCode && bid.params.adCode) { + + if (bid.params.supplyCode && bid.params.adCode) { let scheme = ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; let url = scheme + bid.params.supplyCode + ENDPOINT + '?adCode=' + bid.params.adCode; - url += ('&playerWidth=' + width); - url += ('&playerHeight=' + height); + if (width) { + url += ('&playerWidth=' + width); + } + if (height) { + url += ('&playerHeight=' + height); + } for (let key in bid.params) { if (bid.params.hasOwnProperty(key) && bid.params[key]) { @@ -145,8 +153,8 @@ function generateUrl(bid) { url += ('&srcPageUrl=' + encodeURIComponent(document.location.href)); } - url += ('&transactionId=' + bid.transactionId); - url += ('&referrer=' + config.getConfig('pageUrl') || utils.getTopWindowUrl()); + url += ('&transactionId=' + bid.transactionId + '&hb=1'); + url += ('&referrer=' + encodeURIComponent(bidderRequest.refererInfo.referer)); return (url + '&fmt=json'); } diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js index 6b5278c20ae..88b61844ea4 100644 --- a/test/spec/modules/telariaBidAdapter_spec.js +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -8,7 +8,12 @@ const SUPPLY_CODE = 'ssp-demo-rm6rh'; const SIZES = [640, 480]; const REQUEST = { 'code': 'video1', - 'sizes': [640, 480], + 'mediaTypes': { + 'video': { + 'playerSize': [[640, 480]], + 'context': 'instream' + } + }, 'mediaType': 'video', 'bids': [{ 'bidder': 'tremor', @@ -19,6 +24,12 @@ const REQUEST = { }] }; +const BIDDER_REQUEST = { + 'refererInfo': { + 'referer': 'www.test.com' + } +}; + const RESPONSE = { 'cur': 'USD', 'id': '3dba13e35f3d42f998bc7e65fd871889', @@ -34,26 +45,26 @@ const RESPONSE = { }] }; -describe('TelariaAdapter', function () { +describe('TelariaAdapter', () => { const adapter = newBidder(spec); - describe('inherited functions', function () { - it('exists and is a function', function () { + describe('inherited functions', () => { + it('exists and is a function', () => { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', function () { + describe('isBidRequestValid', () => { let bid = REQUEST.bids[0]; - it('should return true when required params found', function () { + it('should return true when required params found', () => { let tempBid = bid; tempBid.params.adCode = 'ssp-!demo!-lufip'; tempBid.params.supplyCode = 'ssp-demo-rm6rh'; expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', function () { + it('should return true when required params found', () => { let tempBid = bid; delete tempBid.params; tempBid.params = { @@ -64,17 +75,22 @@ describe('TelariaAdapter', function () { expect(spec.isBidRequestValid(tempBid)).to.equal(true); }); - it('should return false when required params are not passed', function () { + it('should return false when required params are not passed', () => { let tempBid = bid; tempBid.params = {}; expect(spec.isBidRequestValid(tempBid)).to.equal(false); }); }); - describe('buildRequests', function () { + describe('buildRequests', () => { const stub = [{ + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'instream' + } + }, bidder: 'tremor', - sizes: [[300, 250], [300, 600]], params: { supplyCode: 'ssp-demo-rm6rh', adCode: 'ssp-!demo!-lufip', @@ -82,17 +98,17 @@ describe('TelariaAdapter', function () { } }]; - it('exists and is a function', function () { + it('exists and is a function', () => { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); - it('requires supply code, ad code and sizes to make a request', function () { - const tempRequest = spec.buildRequests(stub); + it('requires supply code & ad code to make a request', () => { + const tempRequest = spec.buildRequests(stub, BIDDER_REQUEST); expect(tempRequest.length).to.equal(1); }); - it('generates an array of requests with 4 params, method, url, bidId and vastUrl', function () { - const tempRequest = spec.buildRequests(stub); + it('generates an array of requests with 4 params, method, url, bidId and vastUrl', () => { + const tempRequest = spec.buildRequests(stub, BIDDER_REQUEST); expect(tempRequest.length).to.equal(1); expect(tempRequest[0].method).to.equal('GET'); @@ -101,36 +117,44 @@ describe('TelariaAdapter', function () { expect(tempRequest[0].vastUrl).to.exist; }); - it('requires sizes to make a request', function () { + it('doesn\'t require player size but is highly recommended', () => { let tempBid = stub; - tempBid[0].sizes = null; - const tempRequest = spec.buildRequests(tempBid); + tempBid[0].mediaTypes.video.playerSize = null; + const tempRequest = spec.buildRequests(tempBid, BIDDER_REQUEST); - expect(tempRequest.length).to.equal(0); + expect(tempRequest.length).to.equal(1); }); - it('generates a valid request with sizes as an array of two elements', function () { + it('generates a valid request with sizes as an array of two elements', () => { let tempBid = stub; - tempBid[0].sizes = [640, 480]; - expect(spec.buildRequests(tempBid).length).to.equal(1); + tempBid[0].mediaTypes.video.playerSize = [640, 480]; + tempBid[0].params.adCode = 'ssp-!demo!-lufip'; + tempBid[0].params.supplyCode = 'ssp-demo-rm6rh'; + let builtRequests = spec.buildRequests(tempBid, BIDDER_REQUEST); + expect(builtRequests.length).to.equal(1); }); - it('requires ad code and supply code to make a request', function () { + it('requires ad code and supply code to make a request', () => { let tempBid = stub; tempBid[0].params.adCode = null; tempBid[0].params.supplyCode = null; - const tempRequest = spec.buildRequests(tempBid); + const tempRequest = spec.buildRequests(tempBid, BIDDER_REQUEST); expect(tempRequest.length).to.equal(0); }); }); - describe('interpretResponse', function () { + describe('interpretResponse', () => { const responseStub = RESPONSE; const stub = [{ + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'instream' + } + }, bidder: 'tremor', - sizes: [[300, 250], [300, 600]], params: { supplyCode: 'ssp-demo-rm6rh', adCode: 'ssp-!demo!-lufip', @@ -138,40 +162,40 @@ describe('TelariaAdapter', function () { } }]; - it('should get correct bid response', function () { + it('should get correct bid response', () => { let expectedResponseKeys = ['bidderCode', 'width', 'height', 'statusMessage', 'adId', 'mediaType', 'source', 'getStatusCode', 'getSize', 'requestId', 'cpm', 'creativeId', 'vastXml', 'vastUrl', 'currency', 'netRevenue', 'ttl', 'ad']; - let bidRequest = spec.buildRequests(stub)[0]; + let bidRequest = spec.buildRequests(stub, BIDDER_REQUEST)[0]; bidRequest.bidId = '1234'; let result = spec.interpretResponse({body: responseStub}, bidRequest); expect(Object.keys(result[0])).to.have.members(expectedResponseKeys); }); - it('handles nobid responses', function () { + it('handles nobid responses', () => { let tempResponse = responseStub; tempResponse.seatbid = []; - let bidRequest = spec.buildRequests(stub)[0]; + let bidRequest = spec.buildRequests(stub, BIDDER_REQUEST)[0]; bidRequest.bidId = '1234'; let result = spec.interpretResponse({body: tempResponse}, bidRequest); expect(result.length).to.equal(0); }); - it('handles invalid responses', function () { + it('handles invalid responses', () => { let result = spec.interpretResponse(null, {bbidderCode: 'telaria'}); expect(result.length).to.equal(0); }); - it('handles error responses', function () { + it('handles error responses', () => { let result = spec.interpretResponse({body: {error: 'Invalid request'}}, {bbidderCode: 'telaria'}); expect(result.length).to.equal(0); }); }); - describe('getUserSyncs', function () { + describe('getUserSyncs', () => { const responses = [{body: RESPONSE}]; responses[0].body.ext = { telaria: { @@ -182,7 +206,7 @@ describe('TelariaAdapter', function () { } }; - it('should get the correct number of sync urls', function () { + it('should get the correct number of sync urls', () => { let urls = spec.getUserSyncs({pixelEnabled: true}, responses); expect(urls.length).to.equal(2); }); From e3c67d00d1349373e6e1317baacaab5e1ac9e7a3 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 2 Jan 2019 17:17:34 +0200 Subject: [PATCH 0908/1594] New adapter Coinzilla (#3385) * New adapter "Coinzilla" added * Solved required modifications related to bidderRequest.referrerInfo.referer --- modules/coinzillaBidAdapter.js | 89 +++++++++++++ modules/coinzillaBidAdapter.md | 24 ++++ test/spec/modules/coinzillaBidAdapter_spec.js | 120 ++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 modules/coinzillaBidAdapter.js create mode 100644 modules/coinzillaBidAdapter.md create mode 100644 test/spec/modules/coinzillaBidAdapter_spec.js diff --git a/modules/coinzillaBidAdapter.js b/modules/coinzillaBidAdapter.js new file mode 100644 index 00000000000..635c9e492ae --- /dev/null +++ b/modules/coinzillaBidAdapter.js @@ -0,0 +1,89 @@ +import * as utils from 'src/utils'; +import {config} from 'src/config'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'coinzilla'; +const ENDPOINT_URL = 'https://request.czilladx.com/serve/request.php'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['czlla'], // 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 !!(bid.params.placementId); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @return Array Info describing the request to the server. + * @param validBidRequests + * @param bidderRequest + */ + buildRequests: function (validBidRequests, bidderRequest) { + if (validBidRequests.length === 0) { + return []; + } + return validBidRequests.map(bidRequest => { + const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; + const width = sizes.split('x')[0]; + const height = sizes.split('x')[1]; + const payload = { + placementId: bidRequest.params.placementId, + width: width, + height: height, + bidId: bidRequest.bidId, + referer: bidderRequest.refererInfo.referer, + }; + 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. + * @param bidRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function (serverResponse, bidRequest) { + const bidResponses = []; + const response = serverResponse.body; + const creativeId = response.creativeId || 0; + const width = response.width || 0; + const height = response.height || 0; + const cpm = response.cpm || 0; + if (width !== 0 && height !== 0 && cpm !== 0 && creativeId !== 0) { + const dealId = response.dealid || ''; + const currency = response.currency || 'EUR'; + const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; + const referrer = bidRequest.data.referer; + const bidResponse = { + requestId: response.requestId, + cpm: cpm, + width: response.width, + height: response.height, + creativeId: creativeId, + dealId: dealId, + currency: currency, + netRevenue: netRevenue, + ttl: config.getConfig('_bidderTimeout'), + referrer: referrer, + ad: response.ad + }; + bidResponses.push(bidResponse); + } + return bidResponses; + }, +}; +registerBidder(spec); diff --git a/modules/coinzillaBidAdapter.md b/modules/coinzillaBidAdapter.md new file mode 100644 index 00000000000..c7da4efb1a4 --- /dev/null +++ b/modules/coinzillaBidAdapter.md @@ -0,0 +1,24 @@ +# Overview + +``` +Module Name: Coinzilla Bidder Adapter +Module Type: Coinzilla Adapter +Maintainer: technical@sevio.com +``` + +# Description + +Our module helps you have an easier time implementing Coinzilla on your website. All you have to do is replace the ``placementId`` with your zoneID, depending on the required size in your account dashboard. If you need additional information please contact us at ``publishers@coinzilla.com``. +# Test Parameters +``` + var adUnits = [{ + code: 'test-ad-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'coinzilla', + params: { + placementId: 'testPlacementId' + } + }] + }]; +``` \ No newline at end of file diff --git a/test/spec/modules/coinzillaBidAdapter_spec.js b/test/spec/modules/coinzillaBidAdapter_spec.js new file mode 100644 index 00000000000..7a0c745d57d --- /dev/null +++ b/test/spec/modules/coinzillaBidAdapter_spec.js @@ -0,0 +1,120 @@ +import {assert, expect} from 'chai'; +import {spec} from 'modules/coinzillaBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT_URL = 'https://request.czilladx.com/serve/request.php'; + +describe('coinzillaBidAdapter', function () { + const adapter = newBidder(spec); + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'coinzilla', + 'params': { + placementId: 'testPlacementId' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '1234asdf1234', + 'bidderRequestId': '1234asdf1234asdf', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf120' + }; + it('should return true where required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'coinzilla', + 'params': { + placementId: 'testPlacementId' + }, + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }, + { + 'bidder': 'coinzilla', + 'params': { + placementId: 'testPlacementId' + }, + 'adUnitCode': 'adunit-code2', + 'sizes': [ + [300, 250] + ], + 'bidId': '382091349b149f"', + 'bidderRequestId': '1f9c98192de251', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + } + ]; + + let bidderRequests = { + 'refererInfo': { + 'numIframes': 0, + 'reachedTop': true, + 'referer': 'http://example.com', + 'stack': ['http://example.com'] + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequests); + it('sends bid request to our endpoint via POST', function () { + expect(request[0].method).to.equal('POST'); + expect(request[1].method).to.equal('POST'); + }); + it('attaches source and version to endpoint URL as query params', function () { + expect(request[0].url).to.equal(ENDPOINT_URL); + expect(request[1].url).to.equal(ENDPOINT_URL); + }); + }); + + describe('interpretResponse', function () { + let bidRequest = [ + { + 'method': 'POST', + 'url': ENDPOINT_URL, + 'data': { + 'placementId': 'testPlacementId', + 'width': '300', + 'height': '200', + 'bidId': 'bidId123', + 'referer': 'www.example.com' + } + + } + ]; + let serverResponse = { + body: { + 'ad': '

I am an ad

', + 'cpm': 4.2, + 'creativeId': '12345asdfg', + 'currency': 'EUR', + 'statusMessage': 'Bid available', + 'requestId': 'bidId123', + 'width': 300, + 'height': 250, + 'netRevenue': true + } + }; + it('should get the correct bid response', function () { + let expectedResponse = [{ + 'requestId': 'bidId123', + 'cpm': 4.2, + 'width': 300, + 'height': 250, + 'creativeId': '12345asdfg', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 3000, + 'ad': '

I am an ad

' + }]; + let result = spec.interpretResponse(serverResponse, bidRequest[0]); + expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); + }); + }); +}); From b1eeaa90b74601bf4feb2a4f4d9df8558cf685f7 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Wed, 2 Jan 2019 09:40:04 -0800 Subject: [PATCH 0909/1594] Rubicon analytics fix bid response mapping (#3411) * Changing to requestId in order to align with prebid cores mapping of bidId to responseId * Need to update in other events as well * Catching and logging no bid found * Lint error fix --- modules/rubiconAnalyticsAdapter.js | 14 +++++++++----- test/spec/modules/rubiconAnalyticsAdapter_spec.js | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index e952eec36a8..6da987594eb 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -406,7 +406,11 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { }, {})); break; case BID_RESPONSE: - let bid = cache.auctions[args.auctionId].bids[args.adId]; + let bid = cache.auctions[args.auctionId].bids[args.requestId]; + if (!bid) { + 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); switch (args.getStatusCode()) { case GOOD: @@ -428,7 +432,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { break; case BIDDER_DONE: args.bids.forEach(bid => { - let cachedBid = cache.auctions[bid.auctionId].bids[bid.bidId || bid.adId]; + let cachedBid = cache.auctions[bid.auctionId].bids[bid.bidId || bid.requestId]; if (typeof bid.serverResponseTimeMs !== 'undefined') { cachedBid.serverLatencyMillis = bid.serverResponseTimeMs; } @@ -445,11 +449,11 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { break; case BID_WON: let auctionCache = cache.auctions[args.auctionId]; - auctionCache.bidsWon[args.adUnitCode] = args.adId; + auctionCache.bidsWon[args.adUnitCode] = args.requestId; // check if this BID_WON missed the boat, if so send by itself if (auctionCache.sent === true) { - sendMessage.call(this, args.auctionId, args.adId); + sendMessage.call(this, args.auctionId, args.requestId); } else if (Object.keys(auctionCache.bidsWon).reduce((memo, adUnitCode) => { // only send if we've received bidWon events for all adUnits in auction memo = memo && auctionCache.bidsWon[adUnitCode]; @@ -470,7 +474,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { case BID_TIMEOUT: args.forEach(badBid => { let auctionCache = cache.auctions[badBid.auctionId]; - let bid = auctionCache.bids[badBid.bidId || badBid.adId]; + let bid = auctionCache.bids[badBid.bidId || badBid.requestId]; bid.status = 'error'; bid.error = { code: 'timeout-error' diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index c67c73bd280..efb7a1725e7 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -40,7 +40,7 @@ const BID = { 'mediaType': 'video', 'statusMessage': 'Bid available', 'bidId': '2ecff0db240757', - 'adId': '2ecff0db240757', + 'adId': 'fake_ad_id', 'source': 'client', 'requestId': '2ecff0db240757', 'currency': 'USD', @@ -80,7 +80,7 @@ const BID = { const BID2 = Object.assign({}, BID, { adUnitCode: '/19968336/header-bid-tag1', bidId: '3bd4ebb1c900e2', - adId: '3bd4ebb1c900e2', + adId: 'fake_ad_id', requestId: '3bd4ebb1c900e2', width: 728, height: 90, From 320f9ed5d88d69b8b12016e6ced763485d1abe04 Mon Sep 17 00:00:00 2001 From: olafbuitelaar Date: Wed, 2 Jan 2019 21:23:54 +0100 Subject: [PATCH 0910/1594] Consent module doublecall (#3399) * * check if consent hook is already set * * removed debug code * * formatting --- modules/consentManagement.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index 1c8095b4dbd..6471f6d0a67 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -20,6 +20,7 @@ export let allowAuction; export let staticConsentData; let consentData; +let addedConsentHook = false; // add new CMPs here, with their dedicated lookup function const cmpCallMap = { @@ -56,11 +57,11 @@ function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { } return { - consentDataCallback: function(consentResponse) { + consentDataCallback: function (consentResponse) { cmpResponse.getConsentData = consentResponse; afterEach(); }, - vendorConsentsCallback: function(consentResponse) { + vendorConsentsCallback: function (consentResponse) { cmpResponse.getVendorConsents = consentResponse; afterEach(); } @@ -82,7 +83,7 @@ function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { // if the CMP is not found, the iframe function will call the cmpError exit callback to abort the rest of the CMP workflow try { cmpFunction = window.__cmp || utils.getWindowTop().__cmp; - } catch (e) {} + } catch (e) { } if (utils.isFn(cmpFunction)) { cmpFunction('getConsentData', null, callbackHandler.consentDataCallback); @@ -97,7 +98,7 @@ function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { while (!cmpFrame) { try { if (f.frames['__cmpLocator']) cmpFrame = f; - } catch (e) {} + } catch (e) { } if (f === window.top) break; f = f.parent; } @@ -139,13 +140,15 @@ function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { function callCmpWhileInIframe(commandName, cmpFrame, moduleCallback) { /* Setup up a __cmp function to do the postMessage and stash the callback. This function behaves (from the caller's perspective identicially to the in-frame __cmp call */ - window.__cmp = function(cmd, arg, callback) { + window.__cmp = function (cmd, arg, callback) { let callId = Math.random() + ''; - let msg = {__cmpCall: { - command: cmd, - parameter: arg, - callId: callId - }}; + let msg = { + __cmpCall: { + command: cmd, + parameter: arg, + callId: callId + } + }; cmpCallbacks[callId] = callback; cmpFrame.postMessage(msg, '*'); } @@ -371,6 +374,9 @@ export function setConfig(config) { utils.logError(`consentManagement config with cmpApi: 'static' did not specify consentData. No consents will be available to adapters.`); } } - $$PREBID_GLOBAL$$.requestBids.addHook(requestBidsHook, 50); + if (!addedConsentHook) { + $$PREBID_GLOBAL$$.requestBids.addHook(requestBidsHook, 50); + } + addedConsentHook = true; } config.getConfig('consentManagement', config => setConfig(config.consentManagement)); From 9b47b1aaac6a15ba166349b020274d8f6f2122e2 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Wed, 2 Jan 2019 12:33:57 -0800 Subject: [PATCH 0911/1594] pbs adapter support bidder specifc options (#3394) * inprogress * add support for s2sConfig bidderOptions * merged missing updates from origin * changed arrow function in spec mocha tests to standard functions * fixed missing closing bracket and paren * updated incorrect spec expected values for s2sConfig tests * removed rubicon specific s2s configuration default value for sra * deleted unnecessary test and revised a test description since the rubicon specific defaults were removed * removed jsdoc for deprecated cookieSetUrl --- modules/prebidServerBidAdapter/index.js | 33 +++++++- .../modules/prebidServerBidAdapter_spec.js | 75 +++++++++++++++++++ 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 4519a657345..7ecf61088d4 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -21,11 +21,39 @@ const DEFAULT_S2S_NETREVENUE = true; let _s2sConfig; +/** + * @typedef {Object} AdapterOptions + * @summary s2sConfig parameter that adds arguments to resulting OpenRTB payload that goes to Prebid Server + * @example + * // example of multiple bidder configuration + * pbjs.setConfig({ + * s2sConfig: { + * adapterOptions: { + * rubicon: {singleRequest: false} + * appnexus: {key: "value"} + * } + * } + * }); + */ + +/** + * @typedef {Object} S2SDefaultConfig + * @property {boolean} enabled + * @property {number} timeout + * @property {number} maxBids + * @property {string} adapter + * @property {AdapterOptions} adapterOptions + */ + +/** + * @type {S2SDefaultConfig} + */ const s2sDefaultConfig = { enabled: false, timeout: 1000, maxBids: 1, - adapter: 'prebidServer' + adapter: 'prebidServer', + adapterOptions: {} }; config.setDefaults({ @@ -43,6 +71,7 @@ config.setDefaults({ * @property {boolean} [cacheMarkup] whether to cache the adm result * @property {string} [adapter] adapter code to use for S2S * @property {string} [syncEndpoint] endpoint URL for syncing cookies + * @property {AdapterOptions} [adapterOptions] adds arguments to resulting OpenRTB payload to Prebid Server */ function setS2sConfig(options) { if (options.defaultVendor) { @@ -420,7 +449,7 @@ const OPEN_RTB_PROTOCOL = { if (adapter && adapter.getSpec().transformBidParams) { bid.params = adapter.getSpec().transformBidParams(bid.params, isOpenRtb()); } - acc[bid.bidder] = bid.params; + acc[bid.bidder] = (_s2sConfig.adapterOptions && _s2sConfig.adapterOptions[bid.bidder]) ? Object.assign({}, bid.params, _s2sConfig.adapterOptions[bid.bidder]) : bid.params; return acc; }, {}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index af568788bd8..cf0e9fafef1 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -780,6 +780,28 @@ describe('S2S Adapter', function () { expect(requestBid.account).is.equal('1'); expect(requestBid.limit).is.undefined; }); + + it('adds s2sConfig adapterOptions to request for ORTB', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', + adapterOptions: { + appnexus: { + key: 'value' + } + } + }); + const _config = { + s2sConfig: s2sConfig, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.imp[0].ext.appnexus).to.haveOwnProperty('key'); + expect(requestBid.imp[0].ext.appnexus.key).to.be.equal('value') + }); }); describe('response handler', function () { @@ -1138,5 +1160,58 @@ describe('S2S Adapter', function () { expect(vendorConfig).to.have.property('syncEndpoint', '//prebid-server.rubiconproject.com/cookie_sync'); expect(vendorConfig).to.have.property('timeout', 750); }); + + it('should return proper defaults', function () { + expect(config.getConfig('s2sConfig')).to.deep.equal({ + 'accountId': 'abc', + 'adapter': 'prebidServer', + 'bidders': ['rubicon'], + 'defaultVendor': 'rubicon', + 'enabled': true, + 'endpoint': '//prebid-server.rubiconproject.com/openrtb2/auction', + 'syncEndpoint': '//prebid-server.rubiconproject.com/cookie_sync', + 'timeout': 750 + }) + }); + + it('should return default adapterOptions if not set', function () { + config.setConfig({ + s2sConfig: { + accountId: 'abc', + bidders: ['rubicon'], + defaultVendor: 'rubicon', + timeout: 750 + } + }); + expect(config.getConfig('s2sConfig')).to.deep.equal({ + enabled: true, + timeout: 750, + adapter: 'prebidServer', + accountId: 'abc', + bidders: ['rubicon'], + defaultVendor: 'rubicon', + endpoint: '//prebid-server.rubiconproject.com/openrtb2/auction', + syncEndpoint: '//prebid-server.rubiconproject.com/cookie_sync' + }) + }); + + it('should set adapterOptions', function () { + config.setConfig({ + s2sConfig: { + adapterOptions: { + rubicon: { + singleRequest: true, + foo: 'bar' + } + } + } + }); + expect(config.getConfig('s2sConfig').adapterOptions).to.deep.equal({ + rubicon: { + singleRequest: true, + foo: 'bar' + } + }) + }); }); }); From be77fa503404a5dfee15ebe707897afbcace7695 Mon Sep 17 00:00:00 2001 From: Dan Harton Date: Wed, 2 Jan 2019 13:53:27 -0800 Subject: [PATCH 0912/1594] Change DivReach adapter to be alias of AdButler. (#3386) --- modules/adbutlerBidAdapter.js | 3 +- modules/divreachBidAdapter.js | 74 ------------ modules/divreachBidAdapter.md | 30 +---- test/spec/modules/divreachBidAdapter_spec.js | 117 ------------------- 4 files changed, 6 insertions(+), 218 deletions(-) delete mode 100644 modules/divreachBidAdapter.js delete mode 100644 test/spec/modules/divreachBidAdapter_spec.js diff --git a/modules/adbutlerBidAdapter.js b/modules/adbutlerBidAdapter.js index 44a2ef49f51..6f8ce2783b2 100644 --- a/modules/adbutlerBidAdapter.js +++ b/modules/adbutlerBidAdapter.js @@ -9,6 +9,7 @@ const BIDDER_CODE = 'adbutler'; export const spec = { code: BIDDER_CODE, pageID: Math.floor(Math.random() * 10e6), + aliases: ['divreach'], isBidRequestValid: function (bid) { return !!(bid.params.accountID && bid.params.zoneID); @@ -98,7 +99,7 @@ export const spec = { }); if (isCorrectCPM && isCorrectSize) { bidResponse.requestId = bidObj.bidId; - bidResponse.bidderCode = spec.code; + bidResponse.bidderCode = bidObj.bidder; bidResponse.creativeId = serverResponse.placement_id; bidResponse.cpm = CPM; bidResponse.width = width; diff --git a/modules/divreachBidAdapter.js b/modules/divreachBidAdapter.js deleted file mode 100644 index e597e32f4be..00000000000 --- a/modules/divreachBidAdapter.js +++ /dev/null @@ -1,74 +0,0 @@ -import * as utils from 'src/utils'; -import {registerBidder} from 'src/adapters/bidderFactory'; - -const BIDDER_CODE = 'divreach'; -const ENDPOINT_URL = '//ads.divreach.com/prebid.1.0.aspx'; -export const spec = { - code: BIDDER_CODE, - aliases: [], - 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) { - return !!bid.params.zone; - }, - /** - * Make a server request from the list of BidRequests. - * - * @param {bidderRequest} - bidderRequest.bids[] is an array of AdUnits and bids - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function (bidderRequest) { - const payload = { - imps: [], - referrer: encodeURIComponent(utils.getTopWindowUrl()), - }; - bidderRequest.forEach((bid) => { - if (bid.bidder === BIDDER_CODE) { - payload.imps.push(bid); - } - }); - const payloadString = JSON.stringify(payload); - return { - method: 'GET', - url: ENDPOINT_URL, - data: `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, bidRequest) { - const bidResponses = []; - // loop through serverResponses { - try { - serverResponse = serverResponse.body; - serverResponse.forEach((bidResponse) => { - const bidResp = { - requestId: bidResponse.bidId, - cpm: bidResponse.cpm, - width: bidResponse.width, - height: bidResponse.height, - ad: bidResponse.ad, - ttl: bidResponse.ttl, - creativeId: bidResponse.creativeId, - netRevenue: bidResponse.netRevenue, - currency: bidResponse.currency, - vastUrl: bidResponse.vastUrl, - }; - bidResponses.push(bidResp); - }); - } catch (e) { - utils.logError(e); - } - return bidResponses; - } -}; -registerBidder(spec); diff --git a/modules/divreachBidAdapter.md b/modules/divreachBidAdapter.md index da2ebee97cf..643845782b8 100644 --- a/modules/divreachBidAdapter.md +++ b/modules/divreachBidAdapter.md @@ -7,7 +7,6 @@ Maintainer: Zeke@divreach.com # Description Connects to DivReach demand source to fetch bids. -Banner and Video formats are supported. Please use ```divreach``` as the bidder code. # Test Parameters @@ -15,35 +14,14 @@ Please use ```divreach``` as the bidder code. var adUnits = [ { code: 'desktop-banner-ad-div', - sizes: [[300, 250]], // a display size + sizes: [[300, 250]], bids: [ { bidder: "divreach", params: { - zone: '261eae83-0508-4e1a-8c9b-19561fa9279e' - } - } - ] - },{ - code: 'mobile-banner-ad-div', - sizes: [[300, 50]], // a mobile size - bids: [ - { - bidder: "divreach", - params: { - zone: '561e26ea-1999-4fb6-ad0b-9d72929e545e' - } - } - ] - },{ - code: 'video-ad', - sizes: [[300, 50]], - mediaType: 'video', - bids: [ - { - bidder: "divreach", - params: { - zone: 'e784ecbe-720f-46f7-8388-aff8c2c4ed86' + accountID: '167283', + zoneID: '335105', + domain: 'ad.divreach.com', } } ] diff --git a/test/spec/modules/divreachBidAdapter_spec.js b/test/spec/modules/divreachBidAdapter_spec.js deleted file mode 100644 index f874a206a87..00000000000 --- a/test/spec/modules/divreachBidAdapter_spec.js +++ /dev/null @@ -1,117 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/divreachBidAdapter'; -import {newBidder} from 'src/adapters/bidderFactory'; - -const BIDDER_CODE = 'divreach'; -const ENDPOINT_URL = '//ads.divreach.com/prebid.1.0.aspx'; -const ZONE_ID = '2eb6bd58-865c-47ce-af7f-a918108c3fd2'; - -describe('DivReachAdapter', 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 () { - let bid = { - 'bidder': BIDDER_CODE, - 'params': { - 'zone': ZONE_ID - }, - '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 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 bidRequests = [ - { - 'bidder': BIDDER_CODE, - 'params': { - 'zone': ZONE_ID - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - it('should add referrer and imp to be equal bidRequest', function () { - const request = spec.buildRequests(bidRequests); - const payload = JSON.parse(request.data.substr(5)); - expect(payload.referrer).to.not.be.undefined; - expect(payload.imps[0]).to.deep.equal(bidRequests[0]); - }); - - it('sends bid request to ENDPOINT via GET', function () { - const request = spec.buildRequests(bidRequests); - expect(request.url).to.equal(ENDPOINT_URL); - expect(request.method).to.equal('GET'); - }); - }); - - describe('interpretResponse', function () { - let response = { - body: [{ - 'currency': 'USD', - 'cpm': 6.210000, - 'ad': '
ad
', - 'width': 300, - 'height': 600, - 'creativeId': 'ccca3e5e-0c54-4761-9667-771322fbdffc', - 'ttl': 360, - 'netRevenue': false, - 'bidId': '5e4e763b6bc60b' - }] - }; - - it('should get correct bid response', function () { - const body = response.body; - let expectedResponse = [ - { - 'requestId': body[0].bidId, - 'cpm': body[0].cpm, - 'creativeId': body[0].creativeId, - 'width': body[0].width, - 'height': body[0].height, - 'ad': body[0].ad, - 'vastUrl': undefined, - 'currency': body[0].currency, - 'netRevenue': body[0].netRevenue, - 'ttl': body[0].ttl, - } - ]; - - let result = spec.interpretResponse(response); - expect(result[0]).to.deep.equal(expectedResponse[0]); - }); - - it('handles nobid responses', function () { - let response = []; - - let result = spec.interpretResponse(response); - expect(result.length).to.equal(0); - }); - }); -}); From 10a9111ab2b769f71872bef6b7af3529a1a472d7 Mon Sep 17 00:00:00 2001 From: ix-prebid-support <38486470+ix-prebid-support@users.noreply.github.com> Date: Wed, 2 Jan 2019 18:17:10 -0500 Subject: [PATCH 0913/1594] Replace deprecated getWindowTopLocation with referrer detection module (#3380) * Backward compatible update & reduced TTL * replaced deprecated getWindowTopLocation with referer detection module --- modules/ixBidAdapter.js | 60 +++++++++-------- test/spec/modules/ixBidAdapter_spec.js | 90 ++++++++++++++++++-------- 2 files changed, 95 insertions(+), 55 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index c09a35e4d67..ce85b57a98c 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -13,17 +13,6 @@ const ENDPOINT_VERSION = 7.2; const CENT_TO_DOLLAR_FACTOR = 100; const TIME_TO_LIVE = 35; const NET_REVENUE = true; - -// Always start by assuming the protocol is HTTPS. This way, it will work -// whether the page protocol is HTTP or HTTPS. Then check if the page is -// actually HTTP.If we can guarantee it is, then, and only then, set protocol to -// HTTP. -let isSecureWeb = true; -if (utils.getTopWindowLocation().protocol.indexOf('https') !== 0) { - isSecureWeb = false; -} -const baseUrl = isSecureWeb ? BANNER_SECURE_BID_URL : BANNER_INSECURE_BID_URL; - const PRICE_TO_DOLLAR_FACTOR = { JPY: 1 }; @@ -193,6 +182,11 @@ export const spec = { const bannerImps = []; let validBidRequest = null; let bannerImp = null; + // Always start by assuming the protocol is HTTPS. This way, it will work + // whether the page protocol is HTTP or HTTPS. Then check if the page is + // actually HTTP.If we can guarantee it is, then, and only then, set protocol to + // HTTP. + let baseUrl = BANNER_SECURE_BID_URL; for (let i = 0; i < validBidRequests.length; i++) { validBidRequest = validBidRequests[i]; @@ -209,29 +203,41 @@ export const spec = { r.imp = bannerImps; r.site = {}; - r.site.page = utils.getTopWindowUrl(); - r.site.ref = utils.getTopWindowReferrer(); r.ext = {}; r.ext.source = 'prebid'; + if (document.referrer && document.referrer !== '') { + r.site.ref = document.referrer; + } + // Apply GDPR information to the request if GDPR is enabled. - if (options && options.gdprConsent) { - const gdprConsent = options.gdprConsent; + if (options) { + if (options.gdprConsent) { + const gdprConsent = options.gdprConsent; + + if (gdprConsent.hasOwnProperty('gdprApplies')) { + r.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + }; + } - if (gdprConsent.hasOwnProperty('gdprApplies')) { - r.regs = { - ext: { - gdpr: gdprConsent.gdprApplies ? 1 : 0 - } - }; + if (gdprConsent.hasOwnProperty('consentString')) { + r.user = { + ext: { + consent: gdprConsent.consentString || '' + } + }; + } } - if (gdprConsent.hasOwnProperty('consentString')) { - r.user = { - ext: { - consent: gdprConsent.consentString || '' - } - }; + if (options.refererInfo) { + r.site.page = options.refererInfo.referer; + + if (options.refererInfo.referer && options.refererInfo.referer.indexOf('https') !== 0) { + baseUrl = BANNER_INSECURE_BID_URL; + } } } diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 8e0df9959ef..6bf7a0331a8 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -5,7 +5,8 @@ import { newBidder } from 'src/adapters/bidderFactory'; import { spec } from 'modules/ixBidAdapter'; describe('IndexexchangeAdapter', function () { - const IX_ENDPOINT = 'http://as.casalemedia.com/cygnus'; + const IX_INSECURE_ENDPOINT = 'http://as.casalemedia.com/cygnus'; + const IX_SECURE_ENDPOINT = 'https://as-sec.casalemedia.com/cygnus'; const BIDDER_VERSION = 7.2; const DEFAULT_BANNER_VALID_BID = [ @@ -28,6 +29,17 @@ describe('IndexexchangeAdapter', function () { auctionId: '1aa2bb3cc4dd' } ]; + const DEFAULT_BANNER_OPTION = { + gdprConsent: { + gdprApplies: true, + consentString: '3huaa11=qu3198ae', + vendorData: {} + }, + refererInfo: { + referer: 'http://www.prebid.org', + canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' + } + }; const DEFAULT_BANNER_BID_RESPONSE = { cur: 'USD', id: '11a22b33c44d', @@ -198,7 +210,7 @@ describe('IndexexchangeAdapter', function () { }); describe('buildRequestsBanner', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const requestUrl = request.url; const requestMethod = request.method; const query = request.data; @@ -206,12 +218,12 @@ describe('IndexexchangeAdapter', function () { const bidWithoutMediaType = utils.deepClone(DEFAULT_BANNER_VALID_BID); delete bidWithoutMediaType[0].mediaTypes; bidWithoutMediaType[0].sizes = [[300, 250], [300, 600]]; - const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType); + const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_BANNER_OPTION); const queryWithoutMediaType = requestWithoutMediaType.data; it('request should be made to IX endpoint with GET method', function () { expect(requestMethod).to.equal('GET'); - expect(requestUrl).to.equal(IX_ENDPOINT); + expect(requestUrl).to.equal(IX_INSECURE_ENDPOINT); }); it('query object (version, siteID and request) should be correct', function () { @@ -227,10 +239,8 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.exist; - expect(payload.site.page).to.contain('http'); - expect(payload.site.ref).to.exist; - expect(payload.site.ref).to.be.a('string'); + expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); expect(payload.imp).to.exist; @@ -269,10 +279,8 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.exist; - expect(payload.site.page).to.contain('http'); - expect(payload.site.ref).to.exist; - expect(payload.site.ref).to.be.a('string'); + expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); expect(payload.imp).to.exist; @@ -340,9 +348,9 @@ describe('IndexexchangeAdapter', function () { } }); - const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; - const expectedPageUrl = `${utils.getTopWindowUrl()}?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd`; + const expectedPageUrl = DEFAULT_BANNER_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; expect(pageUrl).to.equal(expectedPageUrl); }); @@ -354,10 +362,10 @@ describe('IndexexchangeAdapter', function () { } }); - const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestFirstPartyDataNumber.data.r).site.page; - expect(pageUrl).to.equal(utils.getTopWindowUrl()); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); }); it('should not set first party or timeout if it is not present', function () { @@ -365,18 +373,18 @@ describe('IndexexchangeAdapter', function () { ix: {} }); - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(utils.getTopWindowUrl()); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); it('should not set first party or timeout if it is setConfig is not called', function () { - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(utils.getTopWindowUrl()); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); @@ -487,14 +495,7 @@ describe('IndexexchangeAdapter', function () { }); it('bidrequest should have consent info if gdprApplies and consentString exist', function () { - const options = { - gdprConsent: { - gdprApplies: true, - consentString: '3huaa11=qu3198ae', - vendorData: {} - } - }; - const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); @@ -537,5 +538,38 @@ describe('IndexexchangeAdapter', function () { expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user).to.be.undefined; }); + + it('bidrequest should not have page if options is undefined', function () { + const options = {}; + const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + + expect(requestWithoutreferInfo.site.page).to.be.undefined; + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + }); + + it('bidrequest should not have page if options.refererInfo is an empty object', function () { + const options = { + refererInfo: {} + }; + const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + + expect(requestWithoutreferInfo.site.page).to.be.undefined; + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + }); + + it('bidrequest should sent to secure endpoint if page url is secure', function () { + const options = { + refererInfo: { + referer: 'https://www.prebid.org' + } + }; + const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + + expect(requestWithoutreferInfo.site.page).to.equal(options.refererInfo.referer); + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + }); }); }); From 3c9592f3bfbfa0c0a72ee32a7f44ec3611191f3f Mon Sep 17 00:00:00 2001 From: deekshithraop Date: Thu, 3 Jan 2019 12:10:33 -0500 Subject: [PATCH 0914/1594] Upgrade packages (#3405) * RAD-2356 Upgrade Mocha karma-webpack karma * RAD-2356 update readme to support node v6 or more * Remove webpack output logs while testing * move from gulp-webserver to gulp-connect * remove karma-require and redundant watch task --- README.md | 2 +- gulpfile.js | 49 +- karma.conf.maker.js | 2 +- package-lock.json | 2312 ++++++++++------------------------ package.json | 13 +- test/spec/videoCache_spec.js | 2 +- 6 files changed, 702 insertions(+), 1678 deletions(-) diff --git a/README.md b/README.md index b81d19a574c..11d0f2d50e3 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Working examples can be found in [the developer docs](http://prebid.org/dev-docs $ cd Prebid.js $ npm install -*Note:* You need to have `NodeJS` 4.x or greater installed. +*Note:* You need to have `NodeJS` 6.x or greater installed. *Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To compily with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in it's setup. diff --git a/gulpfile.js b/gulpfile.js index c8ca36324cb..abea226d387 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,14 +4,14 @@ var _ = require('lodash'); var argv = require('yargs').argv; var gulp = require('gulp'); var gutil = require('gulp-util'); -var webserver = require('gulp-webserver'); +var connect = require('gulp-connect'); var webpack = require('webpack'); var webpackStream = require('webpack-stream'); var uglify = require('gulp-uglify'); var gulpClean = require('gulp-clean'); var KarmaServer = require('karma').Server; var karmaConfMaker = require('./karma.conf.maker'); -var opens = require('open'); +var opens = require('opn'); var webpackConfig = require('./webpack.conf'); var helpers = require('./gulpHelpers'); var concat = require('gulp-concat'); @@ -56,12 +56,11 @@ function e2etestReport() { var reportPort = 9010; var targetDestinationDir = './e2etest-report'; helpers.createEnd2EndTestReport(targetDestinationDir); - gulp.src('./') - .pipe(webserver({ - port: reportPort, - directoryListing: true, - livereload: true - })); + connect.server({ + port: reportPort, + root: './', + livereload: true + }); setTimeout(function() { opens('http://localhost:' + reportPort + '/' + targetDestinationDir.slice(2) + '/results.html'); @@ -91,15 +90,15 @@ function lint(done) { function viewCoverage(done) { var coveragePort = 1999; - var stream = gulp.src('./') - .pipe(webserver({ - port: coveragePort, - directoryListing: true, - livereload: false, - open: 'build/coverage/karma_html/index.html' - })); - stream.on('finish', done); + connect.server({ + port: coveragePort, + root: 'build/coverage/karma_html', + livereload: false + }); + opens('http://localhost:' + coveragePort); + done(); }; + viewCoverage.displayName = 'view-coverage'; // Watch Task with Live Reload @@ -115,17 +114,16 @@ function watch(done) { 'test/spec/loaders/**/*.js' ]); - var stream = gulp.src('./') - .pipe(webserver({ - https: argv.https, - port: port, - directoryListing: true, - livereload: true - })); + connect.server({ + https: argv.https, + port: port, + root: './', + livereload: true + }); mainWatcher.on('all', gulp.series(clean, gulp.parallel(lint, 'build-bundle-dev', test))); loaderWatcher.on('all', gulp.series(lint)); - stream.on('finish', done); + done(); }; function makeDevpackPkg() { @@ -140,7 +138,8 @@ function makeDevpackPkg() { .pipe(helpers.nameModules(externalModules)) .pipe(webpackStream(cloned, webpack)) .pipe(replace('$prebid.version$', prebid.version)) - .pipe(gulp.dest('build/dev')); + .pipe(gulp.dest('build/dev')) + .pipe(connect.reload()); } function makeWebpackPkg() { diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 7faf91f0847..6073ee2585a 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -34,7 +34,6 @@ function newPluginsArray(browserstack) { 'karma-es5-shim', 'karma-mocha', 'karma-chai', - 'karma-requirejs', 'karma-sinon', 'karma-sourcemap-loader', 'karma-spec-reporter', @@ -125,6 +124,7 @@ module.exports = function(codeCoverage, browserstack, watchMode, file) { webpack: webpackConfig, webpackMiddleware: { + stats: 'errors-only', noInfo: true }, // frameworks to use diff --git a/package-lock.json b/package-lock.json index 567516277e2..420bd8abe0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { "name": "prebid.js", - "version": "1.35.0", + "version": "1.36.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { "@gulp-sourcemaps/identity-map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", - "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "integrity": "sha1-Hm/l2AJ7HyhdwNMXYvVmvM1z1ak=", "requires": { "acorn": "^5.0.3", "css": "^2.2.1", @@ -28,7 +28,7 @@ "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "integrity": "sha1-mgb08TfuhNffBGDB/bETX/psUP0=", "dev": true }, "@sinonjs/formatio": { @@ -52,7 +52,7 @@ "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "integrity": "sha1-MgjB8I06TZkmGrZPkjArwV4RHKA=", "dev": true, "requires": { "jsonparse": "^1.2.0", @@ -78,7 +78,7 @@ "acorn": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + "integrity": "sha1-Z6ojG/iBKXS4UjWpZ3Hra9B+onk=" }, "acorn-dynamic-import": { "version": "2.0.2", @@ -114,13 +114,6 @@ } } }, - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", - "dev": true, - "optional": true - }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -195,50 +188,6 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, - "amqplib": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.3.tgz", - "integrity": "sha512-ZOdUhMxcF+u62rPI+hMtU1NBXSDFQ3eCJJrenamtdQ7YYwh7RZJHOIM1gonVbZ5PyVdYH4xqBPje9OYqk7fnqw==", - "dev": true, - "optional": true, - "requires": { - "bitsyntax": "~0.1.0", - "bluebird": "^3.5.2", - "buffer-more-ints": "~1.0.0", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "~5.1.2", - "url-parse": "~1.4.3" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, "ansi-colors": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -272,12 +221,12 @@ "ansi-regex": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", - "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==" + "integrity": "sha1-cN55Ht8CFATD/WFaqJEYrgQy5ak=" }, "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==", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", "requires": { "color-convert": "^1.9.0" } @@ -291,7 +240,7 @@ "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", "dev": true, "requires": { "micromatch": "^3.1.4", @@ -325,7 +274,7 @@ "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", "requires": { "sprintf-js": "~1.0.2" } @@ -348,7 +297,7 @@ "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==", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, "arr-map": { @@ -403,7 +352,7 @@ "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==", + "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", "dev": true } } @@ -411,7 +360,7 @@ "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==", + "integrity": "sha1-eqdwc/7FZd2rJJP1+IGF9ASp0zY=", "dev": true, "requires": { "is-number": "^4.0.0" @@ -420,7 +369,7 @@ "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==", + "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", "dev": true } } @@ -428,13 +377,13 @@ "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", "dev": true }, "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==", + "integrity": "sha1-5MBTVkU/VvU1EqfR1hI/LFTAqIo=", "dev": true, "requires": { "default-compare": "^1.0.0", @@ -445,7 +394,7 @@ "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==", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } @@ -465,13 +414,13 @@ "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", "dev": true }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", "requires": { "safer-buffer": "~2.1.0" } @@ -479,7 +428,7 @@ "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", "dev": true, "requires": { "bn.js": "^4.0.0", @@ -521,7 +470,7 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", "dev": true }, "assign-symbols": { @@ -533,7 +482,7 @@ "ast-types": { "version": "0.11.7", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.7.tgz", - "integrity": "sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw==", + "integrity": "sha1-8xi/ROM522oyC+AAne1k7BRx9Gw=", "dev": true }, "async": { @@ -545,7 +494,7 @@ "async-done": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", - "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", + "integrity": "sha1-FLe3Nme4ZMjwK1slP8nG7dt3fz4=", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -571,7 +520,7 @@ "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=", "dev": true }, "async-settle": { @@ -591,7 +540,7 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=" }, "aws-sign2": { "version": "0.7.0", @@ -601,46 +550,7 @@ "aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "axios": { - "version": "0.15.3", - "resolved": "http://registry.npmjs.org/axios/-/axios-0.15.3.tgz", - "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", - "dev": true, - "optional": true, - "requires": { - "follow-redirects": "1.0.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, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "follow-redirects": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", - "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", - "dev": true, - "optional": true, - "requires": { - "debug": "^2.2.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - } - } + "integrity": "sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8=" }, "babel-code-frame": { "version": "6.26.0", @@ -683,7 +593,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -706,7 +616,7 @@ "babel-generator": { "version": "6.26.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "integrity": "sha1-GERAjTuPDTWkBOp6wYDwh6YBvZA=", "dev": true, "requires": { "babel-messages": "^6.23.0", @@ -901,7 +811,7 @@ "babel-loader": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz", - "integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==", + "integrity": "sha1-4+4M1zlKpVfgE7AtPkkr/QeqbWg=", "dev": true, "requires": { "find-cache-dir": "^1.0.0", @@ -1081,7 +991,7 @@ "babel-plugin-transform-decorators-legacy": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", - "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", + "integrity": "sha1-Dkkt/6Dt1wUpByiH+KqG1N2LQKE=", "dev": true, "requires": { "babel-plugin-syntax-decorators": "^6.1.18", @@ -1219,7 +1129,7 @@ "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "integrity": "sha1-WKeThjqefKhwvcWogRF/+sJ9tvM=", "dev": true, "requires": { "babel-plugin-transform-strict-mode": "^6.24.1", @@ -1454,7 +1364,7 @@ "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "integrity": "sha1-3qefpOvriDzTXasH4mDBycBN93o=", "dev": true, "requires": { "babel-plugin-check-es2015-constants": "^6.22.0", @@ -1577,7 +1487,7 @@ "babel-core": { "version": "6.26.3", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "integrity": "sha1-suLwnjQtDwyI4vAuBneUEl51wgc=", "dev": true, "requires": { "babel-code-frame": "^6.26.0", @@ -1604,7 +1514,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -1666,7 +1576,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -1695,13 +1605,13 @@ "babelify": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz", - "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw==", + "integrity": "sha1-b2D18GK/52lXVO8kA7hCAUpYDtM=", "dev": true }, "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", "dev": true }, "bach": { @@ -1730,7 +1640,7 @@ "bail": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", + "integrity": "sha1-Y8+53brIKbAqMSjNUyJL545sIaM=", "dev": true }, "balanced-match": { @@ -1742,7 +1652,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -1766,7 +1676,7 @@ "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==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -1775,7 +1685,7 @@ "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==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -1784,7 +1694,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -1803,7 +1713,7 @@ "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=", "dev": true }, "base64id": { @@ -1850,7 +1760,7 @@ "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==", + "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=", "dev": true }, "binary": { @@ -1866,91 +1776,19 @@ "binary-extensions": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "integrity": "sha1-wteA9T1Fu6gxeokC1M7q86Y4WxQ=", "dev": true }, "binaryextensions": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.2.tgz", - "integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==", + "integrity": "sha1-yDw9dCM7p2dOTzE8sqK3D1TpS3w=", "dev": true }, - "bitsyntax": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", - "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", - "dev": true, - "optional": true, - "requires": { - "buffer-more-ints": "~1.0.0", - "debug": "~2.6.9", - "safe-buffer": "~5.1.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, - "optional": 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, - "optional": true - } - } - }, - "bl": { - "version": "1.1.2", - "resolved": "http://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "~2.0.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, - "optional": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "optional": 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" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "integrity": "sha1-1oDu7yX4zZGtUz9bAe7UjmTK9oM=", "dev": true }, "block-loader": { @@ -1962,13 +1800,13 @@ "bluebird": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "integrity": "sha1-fQHG+WFsmlGrD4xUmnnf5uwz76c=", "dev": true }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", "dev": true }, "body": { @@ -1983,67 +1821,6 @@ "safe-json-parse": "~1.0.1" } }, - "body-parser": { - "version": "1.8.4", - "resolved": "http://registry.npmjs.org/body-parser/-/body-parser-1.8.4.tgz", - "integrity": "sha1-1JfgS8E7P5qL2McLsM3Bby4CiJg=", - "dev": true, - "requires": { - "bytes": "1.0.0", - "depd": "0.4.5", - "iconv-lite": "0.4.4", - "media-typer": "0.3.0", - "on-finished": "2.1.0", - "qs": "2.2.4", - "raw-body": "1.3.0", - "type-is": "~1.5.1" - }, - "dependencies": { - "depd": { - "version": "0.4.5", - "resolved": "http://registry.npmjs.org/depd/-/depd-0.4.5.tgz", - "integrity": "sha1-GmZLUziLSmVz6K5ntfdnxpPKl/E=", - "dev": true - }, - "ee-first": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", - "integrity": "sha1-jJshKJjYzZ8alDZlDOe+ICyen/A=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.4", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz", - "integrity": "sha1-6V8uQdsHNfwhZS94J6XuMuY8g6g=", - "dev": true - }, - "on-finished": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", - "integrity": "sha1-DFOfCSkej/rd4MiiWFD7LO3HAi0=", - "dev": true, - "requires": { - "ee-first": "1.0.5" - } - }, - "qs": { - "version": "2.2.4", - "resolved": "http://registry.npmjs.org/qs/-/qs-2.2.4.tgz", - "integrity": "sha1-Lp+800tUDjQhySTs0B6QqpdTGcg=", - "dev": true - }, - "raw-body": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.0.tgz", - "integrity": "sha1-l4IwoValVI9C7vFN4i0PT2EAg9E=", - "dev": true, - "requires": { - "bytes": "1", - "iconv-lite": "0.4.4" - } - } - } - }, "boom": { "version": "2.10.1", "resolved": "http://registry.npmjs.org/boom/-/boom-2.10.1.tgz", @@ -2056,7 +1833,7 @@ "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -2066,7 +1843,7 @@ "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", "dev": true, "requires": { "arr-flatten": "^1.1.0", @@ -2101,7 +1878,7 @@ "browser-resolve": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "integrity": "sha1-m3y7PQ9RDky4a9vXlhJNKLWJCvY=", "dev": true, "requires": { "resolve": "1.1.7" @@ -2118,7 +1895,7 @@ "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==", + "integrity": "sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA=", "dev": true }, "browserify-aes": { @@ -2138,7 +1915,7 @@ "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==", + "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", "dev": true, "requires": { "browserify-aes": "^1.0.4", @@ -2149,7 +1926,7 @@ "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==", + "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", "dev": true, "requires": { "cipher-base": "^1.0.1", @@ -2186,7 +1963,7 @@ "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==", + "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", "dev": true, "requires": { "pako": "~1.0.5" @@ -2195,7 +1972,7 @@ "browserslist": { "version": "3.2.8", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "integrity": "sha1-sABTYdZHHw9ZUnl6dvyYXx+Xj8Y=", "dev": true, "requires": { "caniuse-lite": "^1.0.30000844", @@ -2258,7 +2035,7 @@ "browserstacktunnel-wrapper": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.4.tgz", - "integrity": "sha512-GCV599FUUxNOCFl3WgPnfc5dcqq9XTmMXoxWpqkvmk0R9TOIoqmjENNU6LY6DtgIL6WfBVbg/jmWtnM5K6UYSg==", + "integrity": "sha1-Dr/9PWMRuFJsMNi0MP3GUaU17rs=", "dev": true, "requires": { "https-proxy-agent": "^2.2.1", @@ -2279,7 +2056,7 @@ "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", "dev": true, "requires": { "buffer-alloc-unsafe": "^1.1.0", @@ -2289,7 +2066,7 @@ "buffer-alloc-unsafe": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=", "dev": true }, "buffer-equal": { @@ -2307,7 +2084,7 @@ "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=", "dev": true }, "buffer-indexof-polyfill": { @@ -2316,12 +2093,6 @@ "integrity": "sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8=", "dev": true }, - "buffer-more-ints": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", - "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==", - "dev": true - }, "buffer-shims": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", @@ -2340,31 +2111,6 @@ "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", "dev": true }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", - "dev": true, - "optional": true, - "requires": { - "addressparser": "1.0.1", - "libbase64": "0.1.0", - "libmime": "3.0.0", - "libqp": "1.1.0", - "nodemailer-fetch": "1.6.0", - "nodemailer-shared": "1.1.0", - "punycode": "1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true, - "optional": true - } - } - }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -2386,7 +2132,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -2424,7 +2170,7 @@ "normalize-url": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "integrity": "sha1-g1qdoVUfom9w6SMpBpojqmV01+Y=", "dev": true, "requires": { "prepend-http": "^2.0.0", @@ -2519,7 +2265,7 @@ "ccount": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", + "integrity": "sha1-8c7EPzMuLqWlaf1G+fW95OYQKv8=", "dev": true }, "center-align": { @@ -2546,7 +2292,7 @@ "chai-nightwatch": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.2.1.tgz", - "integrity": "sha512-2lprSMi72sHq2ZGyPTYUDQNsd2O4z81SicascbI4bkU54Xzk5Ofunn2CbrExADGC7jBH2D8r66X/aSEl+/agXQ==", + "integrity": "sha1-XMiysAXfwFBXIrbPvqJX9z3pvXA=", "dev": true, "requires": { "assertion-error": "1.0.0", @@ -2615,25 +2361,25 @@ "character-entities": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", + "integrity": "sha1-WMjzccB3TvC6myrKXwDY8QDm42M=", "dev": true }, "character-entities-html4": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", + "integrity": "sha1-xE/d485mtS6NMh1sG/RhAfAVBhA=", "dev": true }, "character-entities-legacy": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", + "integrity": "sha1-fG3vuBZISYIiyYVTCZU9BfTWOpw=", "dev": true }, "character-reference-invalid": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", + "integrity": "sha1-IeQhrT2EBVlS2rSkOgTnPNQl0+0=", "dev": true }, "chardet": { @@ -2651,7 +2397,7 @@ "chokidar": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "integrity": "sha1-NW/04rDo5D4yLRijckYLvPOszSY=", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -2672,7 +2418,7 @@ "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==", + "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", "dev": true, "requires": { "inherits": "^2.0.1", @@ -2682,13 +2428,13 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", "dev": true }, "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==", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -2764,7 +2510,7 @@ "cloneable-readable": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "integrity": "sha1-1ZHe5Kj4vBXaQ86X3O66E9Q+KmU=", "dev": true, "requires": { "inherits": "^2.0.1", @@ -2787,7 +2533,7 @@ "collapse-white-space": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", + "integrity": "sha1-zgXPSeVMMneuVzA2omhRukMKAJE=", "dev": true }, "collection-map": { @@ -2814,7 +2560,7 @@ "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==", + "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", "requires": { "color-name": "1.1.3" } @@ -2827,7 +2573,7 @@ "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==", + "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", "dev": true }, "colors": { @@ -2848,7 +2594,7 @@ "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "integrity": "sha1-LR0kMXr7ir6V1tLAsHtXgTU52Cg=", "requires": { "delayed-stream": "~1.0.0" } @@ -2856,7 +2602,7 @@ "comma-separated-tokens": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", - "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", + "integrity": "sha1-sTeTEx2eotJDHPW1B93sJY8M4Ns=", "dev": true, "requires": { "trim": "0.0.1" @@ -2901,7 +2647,7 @@ "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -2913,7 +2659,7 @@ "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==", + "integrity": "sha1-1OqT8FriV5CVG5nns7CeOQikCC4=", "dev": true, "requires": { "source-map": "^0.6.1" @@ -2934,7 +2680,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -2948,12 +2694,6 @@ } } }, - "connect-livereload": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.4.1.tgz", - "integrity": "sha1-D4oagWvJuv+uRjfM6pF0Yv41kXo=", - "dev": true - }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -2978,7 +2718,7 @@ "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==", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", "dev": true }, "continuable-cache": { @@ -2990,7 +2730,7 @@ "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "integrity": "sha1-UbU3qMQ+DwTewZk7/83VBOdYrCA=", "requires": { "safe-buffer": "~5.1.1" } @@ -3010,7 +2750,7 @@ "copy-props": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "integrity": "sha1-k7scrfr9MdpbuKnUtB9HHsOnLf4=", "dev": true, "requires": { "each-props": "^1.3.0", @@ -3030,7 +2770,7 @@ "coveralls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.2.tgz", - "integrity": "sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw==", + "integrity": "sha1-9aC82Qyk5k4Ii3EPqN2mQK6kiE8=", "requires": { "growl": "~> 1.10.0", "js-yaml": "^3.11.0", @@ -3043,7 +2783,7 @@ "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", "dev": true, "requires": { "bn.js": "^4.1.0", @@ -3100,7 +2840,7 @@ "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==", + "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", "dev": true, "requires": { "browserify-cipher": "^1.0.0", @@ -3124,7 +2864,7 @@ "css": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "integrity": "sha1-xkZ1XHOXHyu6amAeLPL9cbEpiSk=", "requires": { "inherits": "^2.0.3", "source-map": "^0.6.1", @@ -3210,7 +2950,7 @@ "data-uri-to-buffer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", + "integrity": "sha1-dxY+qcINhkG0cH6PGKvfmnjzSDU=", "dev": true }, "date-format": { @@ -3238,7 +2978,7 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", "requires": { "ms": "^2.1.1" } @@ -3246,7 +2986,7 @@ "debug-fabulous": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "integrity": "sha1-r4oIYyRlIk70F0qfBjCMPCoevI4=", "requires": { "debug": "3.X", "memoizee": "0.4.X", @@ -3299,7 +3039,7 @@ "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==", + "integrity": "sha1-y2ETGESthNhHiPto/QFoHKd4Gi8=", "dev": true, "requires": { "kind-of": "^5.0.2" @@ -3308,7 +3048,7 @@ "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==", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } @@ -3342,7 +3082,7 @@ "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==", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", "dev": true, "requires": { "object-keys": "^1.0.12" @@ -3351,7 +3091,7 @@ "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { "is-descriptor": "^1.0.2", @@ -3361,7 +3101,7 @@ "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==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3370,7 +3110,7 @@ "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==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3379,7 +3119,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -3444,7 +3184,7 @@ "detab": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", - "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", + "integrity": "sha1-Ux9eMmYg4v1PAyZKkF+zvMivTfQ=", "dev": true, "requires": { "repeat-string": "^1.5.4" @@ -3473,7 +3213,7 @@ "detective": { "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "integrity": "sha1-DspzFDOEQv67bWXaVMELscgrJG4=", "dev": true, "requires": { "acorn": "^5.2.1", @@ -3795,16 +3535,9 @@ "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==", + "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", "dev": true }, - "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", - "dev": true, - "optional": true - }, "duplexer": { "version": "0.1.1", "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -3829,7 +3562,7 @@ "duplexify": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "integrity": "sha1-saeinEq/1jlYXvrszoDWZrHjQSU=", "dev": true, "requires": { "end-of-stream": "^1.0.0", @@ -3841,7 +3574,7 @@ "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==", + "integrity": "sha1-6kWkFNFt1c+kGbGoFyDVygaJIzM=", "dev": true, "requires": { "is-plain-object": "^2.0.1", @@ -3860,7 +3593,7 @@ "editions": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", - "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", + "integrity": "sha1-NmLLWSNHwxaOuOSYoP9zJx1n9Qs=", "dev": true }, "ee-first": { @@ -3872,7 +3605,7 @@ "ejs": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", - "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "integrity": "sha1-SY7A1JVlWrxvI81hho2SZGQHGqA=", "dev": true }, "electron-to-chromium": { @@ -3884,7 +3617,7 @@ "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "integrity": "sha1-wtC3d2kRuGcixjLDwGxg8vgZk5o=", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -3917,16 +3650,16 @@ "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", "dev": true, "requires": { "once": "^1.4.0" } }, "engine.io": { - "version": "3.1.5", - "resolved": "http://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", - "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -3934,14 +3667,13 @@ "cookie": "0.3.1", "debug": "~3.1.0", "engine.io-parser": "~2.1.0", - "uws": "~9.14.0", "ws": "~3.3.1" }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -3956,9 +3688,9 @@ } }, "engine.io-client": { - "version": "3.1.6", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", - "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", + "version": "3.2.1", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { "component-emitter": "1.2.1", @@ -3977,7 +3709,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -3994,7 +3726,7 @@ "engine.io-parser": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "integrity": "sha1-dXq5cPvy37Mse3SwMyFtVznveaY=", "dev": true, "requires": { "after": "0.8.2", @@ -4025,7 +3757,7 @@ "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", "dev": true, "requires": { "prr": "~1.0.1" @@ -4044,7 +3776,7 @@ "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==", + "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", "dev": true, "requires": { "is-arrayish": "^0.2.1" @@ -4053,7 +3785,7 @@ "es5-ext": { "version": "0.10.46", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "integrity": "sha1-79mfZ8Wn7Hibqj2qf3mHA4j39XI=", "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", @@ -4063,7 +3795,7 @@ "es5-shim": { "version": "4.5.12", "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.12.tgz", - "integrity": "sha512-MjoCAHE6P2Dirme70Cxd9i2Ng8rhXiaVSsxDWdSwimfLERJL/ypR2ed2rTYkeeYrMk8gq281dzKLiGcdrmc8qg==", + "integrity": "sha1-UIwT3aHIfdPfG1DmnnuWuCFJtkk=", "dev": true }, "es6-iterator": { @@ -4093,7 +3825,7 @@ "es6-promise": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "integrity": "sha1-2m0NVpLvtGHggsFIF/4kJ9j10FQ=", "dev": true }, "es6-promisify": { @@ -4331,7 +4063,7 @@ "eslint-import-resolver-node": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "integrity": "sha1-WPFfuDm40FdsqYBBNHaqskcttmo=", "dev": true, "requires": { "debug": "^2.6.9", @@ -4341,7 +4073,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -4368,7 +4100,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -4413,7 +4145,7 @@ "eslint-plugin-import": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "integrity": "sha1-axdibS4+atUs/OiAeoRdFeIhEag=", "dev": true, "requires": { "contains-path": "^0.1.0", @@ -4431,7 +4163,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -4505,7 +4237,7 @@ "eslint-plugin-node": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", - "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "integrity": "sha1-gN8yU8TXkBBF7If6ZgooTjK9yik=", "dev": true, "requires": { "ignore": "^3.3.6", @@ -4525,19 +4257,19 @@ "eslint-plugin-promise": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", - "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", + "integrity": "sha1-ZevyeoRePB6db2pWIt3TgBaUtiE=", "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==", + "integrity": "sha1-Kp4hJZukxHwC1TstDJE11LECLUc=", "dev": true }, "eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "integrity": "sha1-UL8wcekzi83EMzF5Sgy1M/ATYXI=", "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" @@ -4546,7 +4278,7 @@ "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", "dev": true }, "espree": { @@ -4562,12 +4294,12 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=" }, "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", "dev": true, "requires": { "estraverse": "^4.0.0" @@ -4576,7 +4308,7 @@ "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", "requires": { "estraverse": "^4.1.0" } @@ -4631,7 +4363,7 @@ "eventemitter3": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "integrity": "sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=", "dev": true }, "events": { @@ -4643,7 +4375,7 @@ "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==", + "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", "dev": true, "requires": { "md5.js": "^1.3.4", @@ -4717,7 +4449,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -4785,7 +4517,7 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=" }, "extend-shallow": { "version": "3.0.2", @@ -4800,7 +4532,7 @@ "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==", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -4822,7 +4554,7 @@ "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { "array-unique": "^0.3.2", @@ -4856,7 +4588,7 @@ "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==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -4865,7 +4597,7 @@ "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==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -4874,7 +4606,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -4898,7 +4630,7 @@ "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==", + "integrity": "sha1-28GRVPVYaQFQojlToK29A1vkX8c=", "dev": true, "requires": { "ansi-gray": "^0.1.1", @@ -4979,7 +4711,7 @@ "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==", + "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", "dev": true }, "filename-regex": { @@ -5049,7 +4781,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -5128,7 +4860,7 @@ "flat-cache": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "integrity": "sha1-LC73dSXMKSkAff/6HdMUqpyd7m8=", "dev": true, "requires": { "circular-json": "^0.3.1", @@ -5140,7 +4872,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { "glob": "^7.0.5" @@ -5148,10 +4880,16 @@ } } }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "dev": true + }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "integrity": "sha1-xdWG7zivYJdlC0m8QbVfq7GfNb0=", "dev": true, "requires": { "inherits": "^2.0.1", @@ -5161,7 +4899,7 @@ "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "integrity": "sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=", "dev": true, "requires": { "debug": "=3.1.0" @@ -5170,7 +4908,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -5219,7 +4957,7 @@ "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==", + "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -5324,7 +5062,7 @@ "fsevents": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "integrity": "sha1-9B3LGvJYKvNpLaNvxVy9jhBBxCY=", "dev": true, "optional": true, "requires": { @@ -5901,7 +5639,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", "dev": true }, "functional-red-black-tree": { @@ -5913,7 +5651,7 @@ "generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "integrity": "sha1-8GlhdpDBDIaOc7hGV0Z2T5fDR58=", "dev": true, "requires": { "is-property": "^1.0.2" @@ -5931,7 +5669,7 @@ "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==", + "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", "dev": true }, "get-func-name": { @@ -5961,7 +5699,7 @@ "get-uri": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", + "integrity": "sha1-XHlecTJvbKEoby/IJXXNK6sq9Xg=", "dev": true, "requires": { "data-uri-to-buffer": "1", @@ -5975,7 +5713,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -6006,7 +5744,7 @@ "git-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.1.0.tgz", - "integrity": "sha512-MJgwfcSd9qxgDyEYpRU/CDxNpUadrK80JHuEQDG4Urn0m7tpSOgCBrtiSIa9S9KH8Tbuo/TN8SSQmJBvsw1HkA==", + "integrity": "sha1-LxTP54Mn58SiuS/Kx7/GdP361Aw=", "dev": true, "requires": { "is-ssh": "^1.3.0", @@ -6026,7 +5764,7 @@ "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==", + "integrity": "sha1-itoyhv0EbYlRw8lSqNeFTP2Q/Zo=", "dev": true, "requires": { "emoji-regex": ">=6.0.0 <=6.1.1" @@ -6035,7 +5773,7 @@ "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -6124,7 +5862,7 @@ "glob-watcher": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", - "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "integrity": "sha1-iKir8cTRMeuTkomUvEpZPC5d1iY=", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -6138,7 +5876,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -6162,13 +5900,13 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", "dev": true }, "globals-docs": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", - "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", + "integrity": "sha1-8sZHVE62Fhx8OEUoCOFuaTwtr7s=", "dev": true }, "glogg": { @@ -6183,7 +5921,7 @@ "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", - "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "integrity": "sha1-HSP2Q5Dpf3dsrFLluTbl9RTS6Tc=", "dev": true, "requires": { "@sindresorhus/is": "^0.7.0", @@ -6208,12 +5946,12 @@ "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + "integrity": "sha1-/7cD4QZuig7qpMi4C6klPu77+wA=" }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" + "integrity": "sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4=" }, "grunt-coveralls": { "version": "2.0.0", @@ -6254,7 +5992,7 @@ "gulp-cli": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", - "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", + "integrity": "sha1-eEfiIMs2YvK+im1XK/FOF75amUs=", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -6405,7 +6143,7 @@ "gulp-babel": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", - "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", + "integrity": "sha1-Wq2Kyw22t/Lwvhnu7pUo8gZN9jE=", "dev": true, "requires": { "babel-core": "^6.23.1", @@ -6419,7 +6157,7 @@ "babel-core": { "version": "6.26.3", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "integrity": "sha1-suLwnjQtDwyI4vAuBneUEl51wgc=", "dev": true, "requires": { "babel-code-frame": "^6.26.0", @@ -6446,7 +6184,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -6651,6 +6389,43 @@ "vinyl": "^2.0.0" } }, + "gulp-connect": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", + "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "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" + }, + "dependencies": { + "ansi-colors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", + "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "dev": true + }, + "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 + }, + "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-coveralls": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/gulp-coveralls/-/gulp-coveralls-0.1.4.tgz", @@ -6683,7 +6458,7 @@ "coveralls": { "version": "2.13.3", "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "integrity": "sha1-mtfCrlJ0F/Nh6LYmSD9I7pLdK8c=", "dev": true, "requires": { "js-yaml": "3.6.1", @@ -6849,7 +6624,7 @@ "gulp-eslint": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", - "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", + "integrity": "sha1-GKKmdo5EBMvz4gMjnLV0dBaPpgY=", "dev": true, "requires": { "eslint": "^4.0.0", @@ -6927,7 +6702,7 @@ "gulp-header": { "version": "1.8.12", "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", - "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "integrity": "sha1-rTBr4AZlmRJygcT4eGZg5wUICoQ=", "dev": true, "requires": { "concat-with-sourcemaps": "*", @@ -7042,13 +6817,13 @@ "gulp-rename": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", - "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", + "integrity": "sha1-3hxxjnxAla6GH3KW708ySGSCQL0=", "dev": true }, "gulp-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", - "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", + "integrity": "sha1-syvWFlTZe414Qwpns+jOBnt8kUM=", "dev": true, "requires": { "istextorbinary": "2.2.1", @@ -7089,7 +6864,7 @@ "gulp-uglify": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.1.tgz", - "integrity": "sha512-KVffbGY9d4Wv90bW/B1KZJyunLMyfHTBbilpDvmcrj5Go0/a1G3uVpt+1gRBWSw/11dqR3coJ1oWNTt1AiXuWQ==", + "integrity": "sha1-jT7uRmUhvqaxD9dd/3Kt+LfqLZc=", "dev": true, "requires": { "gulplog": "^1.0.0", @@ -7105,13 +6880,13 @@ "commander": { "version": "2.17.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=", "dev": true }, "uglify-js": { "version": "3.4.9", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "integrity": "sha1-rwLxgMEgfXZDLkc+0koo9KeCuuM=", "dev": true, "requires": { "commander": "~2.17.1", @@ -7242,213 +7017,31 @@ } } }, - "gulp-webserver": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/gulp-webserver/-/gulp-webserver-0.9.1.tgz", - "integrity": "sha1-4JmSFl2XxYZWFtZCoWAVKbA2cGQ=", + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "handlebars": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", + "integrity": "sha1-LBXIqW1G2l4mZwBRi6jLjZGdW8U=", "dev": true, "requires": { - "connect": "^3.0.1", - "connect-livereload": "^0.4.0", - "gulp-util": "^2.2.19", - "isarray": "0.0.1", - "node.extend": "^1.0.10", - "open": "^0.0.5", - "proxy-middleware": "^0.5.0", - "serve-index": "^1.1.4", - "serve-static": "^1.3.0", - "through2": "^0.5.1", - "tiny-lr": "0.1.4", - "watch": "^0.11.0" + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" }, "dependencies": { - "ansi-regex": { - "version": "0.2.1", - "resolved": "http://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 - }, - "chalk": { - "version": "0.5.1", - "resolved": "http://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 - }, - "debug": { - "version": "0.8.1", - "resolved": "http://registry.npmjs.org/debug/-/debug-0.8.1.tgz", - "integrity": "sha1-IP9NJvXkIstoobrLu2EDmtjBwTA=", - "dev": true - }, - "faye-websocket": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.7.3.tgz", - "integrity": "sha1-zEB0x/Sk39A69U3WXDVLE1EyzhE=", - "dev": true, - "requires": { - "websocket-driver": ">=0.3.6" - } - }, - "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" - } - }, - "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" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "minimist": { - "version": "0.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", - "dev": true - }, - "qs": { - "version": "2.2.5", - "resolved": "http://registry.npmjs.org/qs/-/qs-2.2.5.tgz", - "integrity": "sha1-EIirr53MCuWuRbcJ5sa1iIsjkjw=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://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" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "^0.2.1" - } - }, - "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", - "dev": true - }, - "through2": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" - } - }, - "tiny-lr": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.1.4.tgz", - "integrity": "sha1-bkHX5n39CHjl4LN+N6BtZ+MJ/00=", - "dev": true, - "requires": { - "body-parser": "~1.8.0", - "debug": "~0.8.1", - "faye-websocket": "~0.7.2", - "parseurl": "~1.3.0", - "qs": "~2.2.3" - } - }, - "vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "~0.0.1" - } - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "handlebars": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", - "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", - "dev": true, - "requires": { - "async": "^2.5.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha1-skWiPKcZMAROxT+kaqAKPofGphA=", "dev": true, "requires": { "lodash": "^4.17.10" @@ -7457,14 +7050,14 @@ "commander": { "version": "2.17.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=", "dev": true, "optional": true }, "uglify-js": { "version": "3.4.9", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "integrity": "sha1-rwLxgMEgfXZDLkc+0koo9KeCuuM=", "dev": true, "optional": true, "requires": { @@ -7482,7 +7075,7 @@ "har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", "requires": { "ajv": "^6.5.5", "har-schema": "^2.0.0" @@ -7504,7 +7097,7 @@ "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -7528,7 +7121,7 @@ "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "integrity": "sha1-d3asYn8+p3JQz8My2rfd9eT10R0=", "dev": true, "requires": { "isarray": "2.0.1" @@ -7565,7 +7158,7 @@ "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "integrity": "sha1-FAn5i8ACR9pF2mfO4KNvKC/yZFU=", "dev": true }, "has-symbols": { @@ -7577,7 +7170,7 @@ "has-to-string-tag-x": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "integrity": "sha1-oEWrOD17SyASoAFIqwql8pAETU0=", "dev": true, "requires": { "has-symbol-support-x": "^1.4.1" @@ -7628,7 +7221,7 @@ "hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=", "dev": true, "requires": { "inherits": "^2.0.3", @@ -7638,13 +7231,13 @@ "hast-util-is-element": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.2.tgz", - "integrity": "sha512-4MEtyofNi3ZunPFrp9NpTQdNPN24xvLX3M+Lr/RGgPX6TLi+wR4/DqeoyQ7lwWcfUp4aevdt4RR0r7ZQPFbHxw==", + "integrity": "sha1-wjyUKLalpOMjv54W+HQXR2MUmBs=", "dev": true }, "hast-util-sanitize": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.2.1.tgz", - "integrity": "sha512-bRyZ316tTETfxkpM0De0Fk5slEtR5hvkzDGbHpEAjZRmfQyT3xMTzMk0/gGWlkqsfafFCaPNbrtPdZBPMK8X8A==", + "integrity": "sha1-zfYPc0o95qZGKQK/OR8tydOMeCA=", "dev": true, "requires": { "xtend": "^4.0.1" @@ -7672,7 +7265,7 @@ "hast-util-whitespace": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.2.tgz", - "integrity": "sha512-4JT8B0HKPHBMFZdDQzexjxwhKx9TrpV/+uelvmqlPu8RqqDrnNIEHDtDZCmgE+4YmcFAtKVPLmnY3dQGRaN53A==", + "integrity": "sha1-yXFTo/vJCRoU/YI4MKR3JOeh2pk=", "dev": true }, "hawk": { @@ -7696,20 +7289,9 @@ "highlight.js": { "version": "9.13.1", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz", - "integrity": "sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==", + "integrity": "sha1-BUWG1TpoYzERaEiKD1jWxQXOZB4=", "dev": true }, - "hipchat-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", - "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", - "dev": true, - "optional": true, - "requires": { - "lodash": "^4.0.0", - "request": "^2.0.0" - } - }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -7749,19 +7331,19 @@ "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc=", "dev": true }, "html-void-elements": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.3.tgz", - "integrity": "sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==", + "integrity": "sha1-lWcH2+zRDPZYySxdJ/7nY6pqqYI=", "dev": true }, "http-cache-semantics": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "integrity": "sha1-ObDhat2bYFvwqe89nar0hDtMrNI=", "dev": true }, "http-errors": { @@ -7787,13 +7369,13 @@ "http-parser-js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", - "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", + "integrity": "sha1-1l7b7ehDSdDcMDIIFaFdOcw8u9g=", "dev": true }, "http-proxy": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=", "dev": true, "requires": { "eventemitter3": "^3.0.0", @@ -7804,7 +7386,7 @@ "http-proxy-agent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "integrity": "sha1-5IIb7vWyFCogJr1zkm/lN2McVAU=", "dev": true, "requires": { "agent-base": "4", @@ -7814,7 +7396,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -7838,22 +7420,6 @@ "sshpk": "^1.7.0" } }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true, - "requires": { - "httpreq": ">=0.4.22", - "underscore": "~1.7.0" - } - }, - "httpreq": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", - "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true - }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -7873,7 +7439,7 @@ "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -7882,13 +7448,13 @@ "ieee754": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "integrity": "sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs=", "dev": true }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=", "dev": true }, "ignore-loader": { @@ -7918,13 +7484,6 @@ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "dev": true, - "optional": true - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7943,13 +7502,13 @@ "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", "dev": true }, "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", "dev": true, "requires": { "ansi-escapes": "^3.0.0", @@ -7977,7 +7536,7 @@ "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -7994,7 +7553,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -8031,7 +7590,7 @@ "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", "dev": true, "requires": { "loose-envify": "^1.0.0" @@ -8049,16 +7608,10 @@ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, - "is": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", - "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", - "dev": true - }, "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==", + "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", "dev": true, "requires": { "is-relative": "^1.0.0", @@ -8088,7 +7641,7 @@ "is-alphabetical": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", - "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", + "integrity": "sha1-H6bkkhPLeIW3XRWGL7Pz2WyIT0E=", "dev": true }, "is-alphanumeric": { @@ -8100,7 +7653,7 @@ "is-alphanumerical": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", - "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "integrity": "sha1-ETjprlBAFY3G/3a4IKzWt6GB/UA=", "dev": true, "requires": { "is-alphabetical": "^1.0.0", @@ -8125,7 +7678,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", "dev": true }, "is-builtin-module": { @@ -8160,13 +7713,13 @@ "is-decimal": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", + "integrity": "sha1-iUZi1qhwnTB/OidspDOcj6Xf8P8=", "dev": true }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", @@ -8177,7 +7730,7 @@ "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==", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } @@ -8245,19 +7798,19 @@ "is-hexadecimal": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", + "integrity": "sha1-tucQ19B7tmuYy4zs5cm0kh3uuDU=", "dev": true }, "is-my-ip-valid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "integrity": "sha1-ezUbjo7dTTmV1NBmaA5mTZRpaCQ=", "dev": true }, "is-my-json-valid": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", - "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", + "integrity": "sha1-j9bkA2PNBrlj+od9REv7Xt3GIXU=", "dev": true, "requires": { "generate-function": "^2.0.0", @@ -8308,7 +7861,7 @@ "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==", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { "isobject": "^3.0.1" @@ -8340,7 +7893,7 @@ "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==", + "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", "dev": true, "requires": { "is-unc-path": "^1.0.0" @@ -8349,7 +7902,7 @@ "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", "dev": true }, "is-retry-allowed": { @@ -8381,7 +7934,7 @@ "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==", + "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", "dev": true, "requires": { "unc-path-regex": "^0.1.2" @@ -8402,19 +7955,25 @@ "is-whitespace-character": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", - "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", + "integrity": "sha1-7eU7TG9vs4dFM3UeySgNAZKNA+0=", "dev": true }, "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==", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", "dev": true }, "is-word-character": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", - "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", + "integrity": "sha1-RqXaw/KhhAiYuR5XbNQNST865VM=", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true }, "isarray": { @@ -8425,7 +7984,7 @@ "isbinaryfile": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "integrity": "sha1-XW3vPt6/boyoyunDAYOoBLX4voA=", "dev": true, "requires": { "buffer-alloc": "^1.2.0" @@ -8515,7 +8074,7 @@ "istanbul-api": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", - "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", + "integrity": "sha1-qGx3DSsD4R4/d4zXrt2C0nIgkqo=", "dev": true, "requires": { "async": "^2.1.4", @@ -8534,7 +8093,7 @@ "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "integrity": "sha1-skWiPKcZMAROxT+kaqAKPofGphA=", "dev": true, "requires": { "lodash": "^4.17.10" @@ -8545,7 +8104,7 @@ "istanbul-instrumenter-loader": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", - "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", + "integrity": "sha1-mVe9WSUrNz+uXFK3tRiOb94qCUk=", "dev": true, "requires": { "convert-source-map": "^1.5.0", @@ -8557,13 +8116,13 @@ "istanbul-lib-coverage": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "integrity": "sha1-zPftzQoLubj3Kf7rCTBHD5r2ZPA=", "dev": true }, "istanbul-lib-hook": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", - "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "integrity": "sha1-vGvwfxKmQfvxyFOR0Nqo8K6mv4Y=", "dev": true, "requires": { "append-transform": "^0.4.0" @@ -8572,7 +8131,7 @@ "istanbul-lib-instrument": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "integrity": "sha1-H1XtEKw8R/K93dUweTUSZ1TQqco=", "dev": true, "requires": { "babel-generator": "^6.18.0", @@ -8587,7 +8146,7 @@ "istanbul-lib-report": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", - "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "integrity": "sha1-8qZX/GKC+WFwqvKB6zCkWPf0Fww=", "dev": true, "requires": { "istanbul-lib-coverage": "^1.2.1", @@ -8616,7 +8175,7 @@ "istanbul-lib-source-maps": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", - "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "integrity": "sha1-N7n/ZhWA+PyhEjJ1LuQuCMZnXY8=", "dev": true, "requires": { "debug": "^3.1.0", @@ -8629,7 +8188,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { "glob": "^7.0.5" @@ -8646,7 +8205,7 @@ "istanbul-reports": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", - "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "integrity": "sha1-l+Tb87UV6MSEyuoV1lJO69P/Tho=", "dev": true, "requires": { "handlebars": "^4.0.3" @@ -8655,7 +8214,7 @@ "istextorbinary": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", - "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "integrity": "sha1-pSMaCO9t0ismjQiVCEz41Ytb7FM=", "dev": true, "requires": { "binaryextensions": "2", @@ -8666,37 +8225,13 @@ "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "integrity": "sha1-sn9PSfPNqj6kSgpbfzRi5u3DnWc=", "dev": true, "requires": { "has-to-string-tag-x": "^1.2.0", "is-object": "^1.0.1" } }, - "jade": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", - "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", - "dev": true, - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" - }, - "dependencies": { - "commander": { - "version": "0.6.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-0.6.1.tgz", - "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", - "dev": true - }, - "mkdirp": { - "version": "0.3.0", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", - "dev": true - } - } - }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -8706,7 +8241,7 @@ "js-yaml": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "integrity": "sha1-6u1lbsg0TxD1J8a/obbiJE3hZ9E=", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -8720,7 +8255,7 @@ "jsencrypt": { "version": "3.0.0-rc.1", "resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.0.0-rc.1.tgz", - "integrity": "sha512-gcvGaqerlUJy1Kq6tNgPYteVEoWNemu+9hBe2CdsCIz4rVcwjoTQ72iD1W76/PRMlnkzG0yVh7nwOOMOOUfKmg==" + "integrity": "sha1-DgpHRLpDzFV/tc9i/oZGvOtWGxw=" }, "jsesc": { "version": "1.3.0", @@ -8737,13 +8272,13 @@ "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==", + "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=", "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", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", "dev": true }, "json-schema": { @@ -8835,9 +8370,9 @@ "dev": true }, "karma": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", - "integrity": "sha512-rECezBeY7mjzGUWhFlB7CvPHgkHJLXyUmWg+6vHCEsdWNUTnmiS6jRrIMcJEWgU2DUGZzGWG0bTRVky8fsDTOA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", + "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -8850,23 +8385,24 @@ "di": "^0.0.1", "dom-serialize": "^2.2.0", "expand-braces": "^0.1.1", + "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.4", - "log4js": "^2.5.3", - "mime": "^1.3.4", + "lodash": "^4.17.5", + "log4js": "^3.0.0", + "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", "qjobs": "^1.1.4", "range-parser": "^1.2.0", "rimraf": "^2.6.0", "safe-buffer": "^5.0.1", - "socket.io": "2.0.4", + "socket.io": "2.1.1", "source-map": "^0.6.1", "tmp": "0.0.33", - "useragent": "2.2.1" + "useragent": "2.3.0" }, "dependencies": { "body-parser": { @@ -8896,7 +8432,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -8905,12 +8441,18 @@ "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "integrity": "sha1-KXhx9jvlB63Pv8pxXQzQ7thOmmM=", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha1-4FH9iBNYWF8yed8zP+aU2gvP/dY=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -8920,7 +8462,7 @@ "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "integrity": "sha1-GzJOzmtXBuFThVvBFIxlu39uoMM=", "dev": true, "requires": { "bytes": "3.0.0", @@ -8932,7 +8474,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { "glob": "^7.0.5" @@ -8941,7 +8483,7 @@ "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", "dev": true, "requires": { "media-typer": "0.3.0", @@ -8962,7 +8504,7 @@ "karma-browserstack-launcher": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", - "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", + "integrity": "sha1-Yf49NrHPEGgeQPnYdL83Jx+xxnQ=", "dev": true, "requires": { "browserstack": "1.5.0", @@ -8979,7 +8521,7 @@ "karma-chrome-launcher": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "integrity": "sha1-zxudBxNswY/iOTJ9JGVMPbw2is8=", "dev": true, "requires": { "fs-access": "^1.0.0", @@ -9008,7 +8550,7 @@ "karma-firefox-launcher": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", + "integrity": "sha1-LEcDBFLwRTHrfRPU/HZpYwu5Mzk=", "dev": true }, "karma-ie-launcher": { @@ -9049,7 +8591,7 @@ "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -9117,9 +8659,9 @@ } }, "karma-webpack": { - "version": "2.0.13", - "resolved": "http://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", - "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.5.tgz", + "integrity": "sha1-H/HjppD7c66V7pX5q1jzQc/HtA8=", "dev": true, "requires": { "async": "^2.0.0", @@ -9127,13 +8669,13 @@ "loader-utils": "^1.0.0", "lodash": "^4.0.0", "source-map": "^0.5.6", - "webpack-dev-middleware": "^1.12.0" + "webpack-dev-middleware": "^2.0.6" }, "dependencies": { "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "integrity": "sha1-skWiPKcZMAROxT+kaqAKPofGphA=", "dev": true, "requires": { "lodash": "^4.17.10" @@ -9156,7 +8698,7 @@ "keyv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", - "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "integrity": "sha1-RJI7o55osSp87H32wyaMAx8u83M=", "dev": true, "requires": { "json-buffer": "3.0.0" @@ -9165,7 +8707,7 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", "dev": true }, "last-run": { @@ -9226,37 +8768,6 @@ "type-check": "~0.3.2" } }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", - "dev": true, - "requires": { - "iconv-lite": "0.4.15", - "libbase64": "0.1.0", - "libqp": "1.1.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.15", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true - } - } - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true - }, "liftoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", @@ -9282,7 +8793,7 @@ "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==", + "integrity": "sha1-RHwxzx6pq1L8INthXF3fZ494AJw=", "dev": true }, "load-json-file": { @@ -9300,7 +8811,7 @@ "loader-runner": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", - "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", + "integrity": "sha1-Am8S/nwxFZkolqwCugIrqSlxuXk=", "dev": true }, "loader-utils": { @@ -9317,7 +8828,7 @@ "localtunnel": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.1.tgz", - "integrity": "sha512-HWrhOslklDvxgOGFLxi6fQVnvpl6XdX4sPscfqMZkzi3gtt9V7LKBWYvNUcpHSVvjwCQ6xzXacVvICNbNcyPnQ==", + "integrity": "sha1-HRc36rZYrdWkAmbY5D84m2Ru47E=", "dev": true, "requires": { "axios": "0.17.1", @@ -9345,7 +8856,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -9505,7 +9016,7 @@ "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "integrity": "sha1-s56mIp72B+zYniyN8SU2iRysm40=", "dev": true }, "lodash._arraycopy": { @@ -9779,7 +9290,7 @@ "lodash.merge": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", - "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", + "integrity": "sha1-rcJdnLmbk5HFliTzefu6YNcRHVQ=", "dev": true }, "lodash.restparam": { @@ -9831,12 +9342,12 @@ "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" + "integrity": "sha1-Y7lQIfBwL+36LJuwok53l9cYcdg=" }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", "dev": true, "requires": { "chalk": "^2.0.1" @@ -9845,7 +9356,7 @@ "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -9856,185 +9367,40 @@ } }, "log4js": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", - "integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", "dev": true, "requires": { - "amqplib": "^0.5.2", - "axios": "^0.15.3", - "circular-json": "^0.5.4", + "circular-json": "^0.5.5", "date-format": "^1.2.0", "debug": "^3.1.0", - "hipchat-notifier": "^1.1.0", - "loggly": "^1.1.0", - "mailgun-js": "^0.18.0", - "nodemailer": "^2.5.0", - "redis": "^2.7.1", - "semver": "^5.5.0", - "slack-node": "~0.2.0", + "rfdc": "^1.1.2", "streamroller": "0.7.0" }, "dependencies": { "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", "dev": true } } }, - "loggly": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", - "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha1-NvxPWZbWZA9Tn/IDuoGWQWgNdaI=", "dev": true, - "optional": true, "requires": { - "json-stringify-safe": "5.0.x", - "request": "2.75.x", - "timespan": "2.3.x" - }, - "dependencies": { - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true, - "optional": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.0.0", - "resolved": "http://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", - "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.11" - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "http://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "optional": true, - "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true, - "optional": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true, - "optional": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true, - "optional": true - }, - "qs": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true, - "optional": true - }, - "request": { - "version": "2.75.0", - "resolved": "http://registry.npmjs.org/request/-/request-2.75.0.tgz", - "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "bl": "~1.1.2", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.0.0", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "node-uuid": "~1.4.7", - "oauth-sign": "~0.8.1", - "qs": "~6.2.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "http://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "optional": true, - "requires": { - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true, - "optional": true - } + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" } }, "lolex": { "version": "2.7.5", "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "integrity": "sha1-ETAB1Wv8fgLVbjYpHMXEE9GqBzM=", "dev": true }, "longest": { @@ -10046,13 +9412,13 @@ "longest-streak": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "integrity": "sha1-JCG2upOaRDu5/+v1llhaULTDji4=", "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==", + "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -10071,13 +9437,13 @@ "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=", "dev": true }, "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==", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -10109,68 +9475,10 @@ } } }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", - "dev": true, - "optional": true, - "requires": { - "buildmail": "4.0.1", - "libmime": "3.0.0" - } - }, - "mailgun-js": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.1.tgz", - "integrity": "sha512-lvuMP14u24HS2uBsJEnzSyPMxzU2b99tQsIx1o6QNjqxjk8b3WvR+vq5oG1mjqz/IBYo+5gF+uSoDS0RkMVHmg==", - "dev": true, - "optional": true, - "requires": { - "async": "~2.6.0", - "debug": "~3.1.0", - "form-data": "~2.3.0", - "inflection": "~1.12.0", - "is-stream": "^1.1.0", - "path-proxy": "~1.0.0", - "promisify-call": "^2.0.2", - "proxy-agent": "~3.0.0", - "tsscmp": "~1.0.0" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "optional": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "optional": 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, - "optional": true - } - } - }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", "dev": true, "requires": { "pify": "^3.0.0" @@ -10179,7 +9487,7 @@ "make-error": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "integrity": "sha1-7+ToH22yjK3WBccPKcgxtY73dsg=", "dev": true }, "make-error-cause": { @@ -10194,7 +9502,7 @@ "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=", "dev": true, "requires": { "kind-of": "^6.0.2" @@ -10230,13 +9538,13 @@ "markdown-escapes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", + "integrity": "sha1-5jnL3nuZyEHAusyKB5goc7RtISI=", "dev": true }, "markdown-table": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", - "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", + "integrity": "sha1-x425SPqHmQOkG85SLjuW+AHGN4Y=", "dev": true }, "matchdep": { @@ -10260,7 +9568,7 @@ "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==", + "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=", "dev": true, "requires": { "hash-base": "^3.0.0", @@ -10271,7 +9579,7 @@ "mdast-util-compact": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz", - "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==", + "integrity": "sha1-wS6+Fv/8hFc9Phl2dybeIm6V9kk=", "dev": true, "requires": { "unist-util-visit": "^1.1.0" @@ -10280,7 +9588,7 @@ "mdast-util-definitions": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.3.tgz", - "integrity": "sha512-P6wpRO8YVQ1iv30maMc93NLh7COvufglBE8/ldcOyYmk5EbfF0YeqlLgtqP/FOBU501Kqar1x5wYWwB3Nga74g==", + "integrity": "sha1-Sfk2sJIHxFtDjbGVUWUpNDEvBPA=", "dev": true, "requires": { "unist-util-visit": "^1.0.0" @@ -10298,7 +9606,7 @@ "mdast-util-to-hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.4.tgz", - "integrity": "sha512-/eIbly2YmyVgpJNo+bFLLMCI1XgolO/Ffowhf+pHDq3X4/V6FntC9sGQCDLM147eTS+uSXv5dRzJyFn+o0tazA==", + "integrity": "sha1-EyABsmYDEZI0jTNmprAR8o5U3EA=", "dev": true, "requires": { "collapse-white-space": "^1.0.0", @@ -10317,13 +9625,13 @@ "mdast-util-to-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz", - "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==", + "integrity": "sha1-NVKwVCivIs7aNPFWr+YuyObXMco=", "dev": true }, "mdast-util-toc": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-3.0.1.tgz", - "integrity": "sha512-Z8lKq6sQr/vDNIcUkIWzPwKo5JQIzlDLouZuzIMVajOdUAyjnkA+s98RhjVpFt7SiuJzase9oh6Iw7n4zhVNDQ==", + "integrity": "sha1-eLMmW5/ZElwNzHprtKaRJ6zX6Ts=", "dev": true, "requires": { "github-slugger": "^1.1.1", @@ -10355,7 +9663,7 @@ "memoizee": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "integrity": "sha1-B6APIEaZ+alcLZ53IYJxx81hDVc=", "requires": { "d": "1", "es5-ext": "^0.10.45", @@ -10503,7 +9811,7 @@ "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -10524,7 +9832,7 @@ "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", "dev": true, "requires": { "bn.js": "^4.0.0", @@ -10534,18 +9842,18 @@ "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", "dev": true }, "mime-db": { "version": "1.37.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + "integrity": "sha1-C2oM5v2+lXbiXx8tL96IMNwK0Ng=" }, "mime-types": { "version": "2.1.21", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "integrity": "sha1-KJlaoey3cHQv5q5+WPkYHHRLP5Y=", "requires": { "mime-db": "~1.37.0" } @@ -10553,19 +9861,19 @@ "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==", + "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", "dev": true }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "integrity": "sha1-SSNTiHju9CBjy4o+OweYeBSHqxs=", "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==", + "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=", "dev": true }, "minimalistic-crypto-utils": { @@ -10577,7 +9885,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -10591,7 +9899,7 @@ "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", "dev": true, "requires": { "for-in": "^1.0.2", @@ -10601,7 +9909,7 @@ "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==", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -10633,108 +9941,67 @@ "dev": true }, "mocha": { - "version": "2.2.5", - "resolved": "http://registry.npmjs.org/mocha/-/mocha-2.2.5.tgz", - "integrity": "sha1-07cqT+SeyUOTU/GsiT28Qw2ZMUA=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha1-bYrlCPWRZ/lA8rWzxKYSrlDJCuY=", "dev": true, "requires": { - "commander": "2.3.0", - "debug": "2.0.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.3", - "growl": "1.8.1", - "jade": "0.26.3", - "mkdirp": "0.5.0", - "supports-color": "~1.2.0" + "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" }, - "dependencies": { - "commander": { - "version": "2.3.0", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.3.0.tgz", - "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", - "dev": true - }, + "dependencies": { "debug": { - "version": "2.0.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.0.0.tgz", - "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { - "ms": "0.6.2" + "ms": "2.0.0" } }, - "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=", "dev": true }, "glob": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", - "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { - "graceful-fs": "~2.0.0", + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", "inherits": "2", - "minimatch": "~0.2.11" - } - }, - "graceful-fs": { - "version": "2.0.3", - "resolved": "http://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", - "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", - "dev": true - }, - "growl": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", - "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "mkdirp": { - "version": "0.5.0", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", - "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha1-HGszdALCE3YF7+GfEP7DkPb6q1Q=", "dev": true, "requires": { - "minimist": "0.0.8" + "has-flag": "^3.0.0" } - }, - "ms": { - "version": "0.6.2", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.6.2.tgz", - "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", - "dev": true - }, - "supports-color": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz", - "integrity": "sha1-Eu4hUHCGzZjBBY2ewPSsR2t687I=", - "dev": true } } }, @@ -10828,7 +10095,7 @@ "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==" + "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=" }, "multipipe": { "version": "0.1.2", @@ -10877,7 +10144,7 @@ "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==", + "integrity": "sha1-rLAwDrTeI6fd7sAU4+lgRLNHIzE=", "dev": true }, "mute-stream": { @@ -10896,7 +10163,7 @@ "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -10933,7 +10200,7 @@ "neo-async": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "integrity": "sha1-udFeTXHGdikIZUtRg+04t1M0CDU=", "dev": true }, "netmask": { @@ -11097,7 +10364,7 @@ "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=", "dev": true, "requires": { "assert": "^1.1.1", @@ -11133,108 +10400,6 @@ } } }, - "node.extend": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz", - "integrity": "sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA==", - "dev": true, - "requires": { - "has": "^1.0.3", - "is": "^3.2.1" - } - }, - "nodemailer": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", - "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", - "dev": true, - "optional": true, - "requires": { - "libmime": "3.0.0", - "mailcomposer": "4.0.1", - "nodemailer-direct-transport": "3.3.2", - "nodemailer-shared": "1.1.0", - "nodemailer-smtp-pool": "2.8.2", - "nodemailer-smtp-transport": "2.7.2", - "socks": "1.1.9" - }, - "dependencies": { - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true, - "optional": true - }, - "socks": { - "version": "1.1.9", - "resolved": "http://registry.npmjs.org/socks/-/socks-1.1.9.tgz", - "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", - "dev": true, - "optional": true, - "requires": { - "ip": "^1.1.2", - "smart-buffer": "^1.0.4" - } - } - } - }, - "nodemailer-direct-transport": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", - "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true, - "requires": { - "nodemailer-fetch": "1.6.0" - } - }, - "nodemailer-smtp-pool": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", - "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", - "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-wellknown": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -11247,7 +10412,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { "hosted-git-info": "^2.1.4", @@ -11309,7 +10474,7 @@ "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=" }, "object-assign": { "version": "4.1.1", @@ -11356,7 +10521,7 @@ "object-keys": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "integrity": "sha1-CcU4VTd1dTEMymL1W7M0q/97PtI=", "dev": true }, "object-visit": { @@ -11371,7 +10536,7 @@ "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", "dev": true, "requires": { "define-properties": "^1.1.2", @@ -11469,18 +10634,21 @@ "mimic-fn": "^1.0.0" } }, - "open": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", - "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", - "dev": true - }, "openurl": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", "dev": true }, + "opn": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", + "integrity": "sha1-y1Reeqt4VivrEao7+rxwQuF2EDU=", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -11705,7 +10873,7 @@ "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", "dev": true, "requires": { "execa": "^0.7.0", @@ -11740,7 +10908,7 @@ "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", "dev": true, "requires": { "p-try": "^1.0.0" @@ -11758,7 +10926,7 @@ "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", - "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "integrity": "sha1-2N0ZeVldLcATnh/ka4tkbLPN8Dg=", "dev": true, "requires": { "p-finally": "^1.0.0" @@ -11773,7 +10941,7 @@ "pac-proxy-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", - "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", + "integrity": "sha1-EdV4tyoWStdL+dW6yf9GKjgoJDI=", "dev": true, "requires": { "agent-base": "^4.2.0", @@ -11795,7 +10963,7 @@ "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "integrity": "sha1-KXhx9jvlB63Pv8pxXQzQ7thOmmM=", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -11804,7 +10972,7 @@ "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "integrity": "sha1-GzJOzmtXBuFThVvBFIxlu39uoMM=", "dev": true, "requires": { "bytes": "3.0.0", @@ -11818,7 +10986,7 @@ "pac-resolver": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "integrity": "sha1-auoweH2wqJFwTet4AKcip2FabyY=", "dev": true, "requires": { "co": "^4.6.0", @@ -11831,7 +10999,7 @@ "pako": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", - "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", + "integrity": "sha1-JHNDkCG1fxUWyC9YvnJ1rY7xuyc=", "dev": true }, "parents": { @@ -11859,7 +11027,7 @@ "parse-domain": { "version": "2.1.7", "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.7.tgz", - "integrity": "sha512-yb0VWRwDCe96ML49b3xg+4wScbocpIrFSAdkml8eKq/deH3FiFPBpsC6RTC9ZUtnDhInmXPfNIHsN/v62+TAMA==", + "integrity": "sha1-202M4wAwkX4g84fy/yHa1W4R1Yw=", "dev": true, "requires": { "chai": "^4.2.0", @@ -11871,7 +11039,7 @@ "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "integrity": "sha1-dgqnLPION5XoSxKHfODoNzeqKeU=", "dev": true, "requires": { "assertion-error": "^1.1.0", @@ -11894,7 +11062,7 @@ "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==", + "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -11957,7 +11125,7 @@ "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==", + "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=", "dev": true } } @@ -11965,7 +11133,7 @@ "parse-entities": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.0.tgz", - "integrity": "sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==", + "integrity": "sha1-nerAh2YbLjaBQVPLeNflSkxf1vQ=", "dev": true, "requires": { "character-entities": "^1.0.0", @@ -12038,7 +11206,7 @@ "parse-node-version": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", - "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==", + "integrity": "sha1-M9mqiSDcw8DTNljsGM4jcAmlbVM=", "dev": true }, "parse-passwd": { @@ -12050,7 +11218,7 @@ "parse-path": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-3.0.4.tgz", - "integrity": "sha512-wP70vtwv2DyrM2YoA7ZHVv4zIXa4P7dGgHlj+VwyXNDduLLVJ7NMY1zsFxjUUJ3DAwJLupGb1H5gMDDiNlJaxw==", + "integrity": "sha1-pIt7Up2kHzTZ0UKGAqObKfxxgOQ=", "dev": true, "requires": { "is-ssh": "^1.3.0", @@ -12138,7 +11306,7 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", "dev": true }, "path-platform": { @@ -12147,25 +11315,6 @@ "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", "dev": true }, - "path-proxy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "dev": true, - "optional": true, - "requires": { - "inflection": "~1.3.0" - }, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", - "dev": true, - "optional": true - } - } - }, "path-root": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", @@ -12201,7 +11350,7 @@ "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", "dev": true, "requires": { "pify": "^3.0.0" @@ -12225,7 +11374,7 @@ "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=", "dev": true, "requires": { "create-hash": "^1.1.2", @@ -12279,7 +11428,7 @@ "plugin-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "integrity": "sha1-dwFr2JGdCsN3/c3QMiMolTyleBw=", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -12291,7 +11440,7 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", "dev": true }, "posix-character-classes": { @@ -12327,7 +11476,7 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", "dev": true }, "process": { @@ -12339,7 +11488,7 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" }, "progress": { "version": "2.0.2", @@ -12347,16 +11496,6 @@ "integrity": "sha512-/OLz5F9beZUWwSHZDreXgap1XShX6W+DCHQCqwCF7uZ88s6uTlD2cR3JBE77SegCmNtb1Idst+NfmwcdU6KVhw==", "dev": true }, - "promisify-call": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", - "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", - "dev": true, - "optional": true, - "requires": { - "with-callback": "^1.0.2" - } - }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12372,7 +11511,7 @@ "proxy-agent": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", - "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", + "integrity": "sha1-HBoz22DvXy6eNbh2/WPCvGgcYR0=", "dev": true, "requires": { "agent-base": "^4.2.0", @@ -12391,12 +11530,6 @@ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", "dev": true }, - "proxy-middleware": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.5.1.tgz", - "integrity": "sha1-2iTV1Ywd3xPa0jfH7KUDhJ6uqQM=", - "dev": true - }, "proxyquire": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", @@ -12436,7 +11569,7 @@ "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=", "dev": true, "requires": { "bn.js": "^4.1.0", @@ -12450,7 +11583,7 @@ "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -12460,7 +11593,7 @@ "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", "dev": true, "requires": { "duplexify": "^3.6.0", @@ -12482,13 +11615,13 @@ "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==", + "integrity": "sha1-xF6cYYAL0IfviNfiVkI73Unl0HE=", "dev": true }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=" }, "query-string": { "version": "4.3.4", @@ -12521,7 +11654,7 @@ "randomatic": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "integrity": "sha1-t3bvxZN1mE42xTey9RofCv8Noe0=", "dev": true, "requires": { "is-number": "^4.0.0", @@ -12532,7 +11665,7 @@ "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==", + "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", "dev": true } } @@ -12540,7 +11673,7 @@ "randombytes": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "integrity": "sha1-0wLFIpSFiISKjTAMkytEwkIx2oA=", "dev": true, "requires": { "safe-buffer": "^5.1.0" @@ -12549,7 +11682,7 @@ "randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", "dev": true, "requires": { "randombytes": "^2.0.5", @@ -12618,7 +11751,7 @@ "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -12645,47 +11778,21 @@ "strip-indent": "^1.0.1" } }, - "redis": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", - "dev": true, - "optional": true, - "requires": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.2.0", - "redis-parser": "^2.6.0" - } - }, - "redis-commands": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", - "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==", - "dev": true, - "optional": true - }, - "redis-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", - "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", - "dev": true, - "optional": true - }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=", "dev": true }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" }, "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", "dev": true, "requires": { "babel-runtime": "^6.18.0", @@ -12696,7 +11803,7 @@ "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", "dev": true, "requires": { "is-equal-shallow": "^0.1.3" @@ -12705,7 +11812,7 @@ "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { "extend-shallow": "^3.0.2", @@ -12755,7 +11862,7 @@ "remark": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", - "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", + "integrity": "sha1-xc+o7FNcc6Z8Sw8Sv9vTpn2LL2A=", "dev": true, "requires": { "remark-parse": "^5.0.0", @@ -12766,7 +11873,7 @@ "remark-html": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", - "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", + "integrity": "sha1-0T3BupNS4lf86IAMQsdpDZ42kMg=", "dev": true, "requires": { "hast-util-sanitize": "^1.0.0", @@ -12778,7 +11885,7 @@ "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "integrity": "sha1-TAd/nkmQRNHVwT+A16mM97koXZU=", "dev": true, "requires": { "collapse-white-space": "^1.0.2", @@ -12801,7 +11908,7 @@ "remark-reference-links": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.3.tgz", - "integrity": "sha512-Q9d7JaK5r0JDBo3TInfrodBuI3xulI8htCr8jlX+0oXosF3GaebJbo5y228VYFoV6xJ+syDukkUGMKNlwSJWjQ==", + "integrity": "sha1-61GtT92wCRmfmKxAPQVY1zLi34k=", "dev": true, "requires": { "unist-util-visit": "^1.0.0" @@ -12810,7 +11917,7 @@ "remark-slug": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.1.tgz", - "integrity": "sha512-r591rdoDPJkSSAVvEaTVUkqbMp7c7AyZfif14V0Dp66GQkOHzaPAS6wyhawSbqpS0ZdTnfJS+TltFoxzi6bdIA==", + "integrity": "sha1-6126DPd5SH733fZcc1uk1MoBdUI=", "dev": true, "requires": { "github-slugger": "^1.0.0", @@ -12821,7 +11928,7 @@ "remark-stringify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", - "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", + "integrity": "sha1-M206TUpqM5DZM+66YujeS9KAr7o=", "dev": true, "requires": { "ccount": "^1.0.0", @@ -12843,7 +11950,7 @@ "remark-toc": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.1.1.tgz", - "integrity": "sha512-vCPW4YOsm2CfyuScdktM9KDnJXVHJsd/ZeRtst+dnBU3B3KKvt8bc+bs5syJjyptAHfqo7H+5Uhz+2blWBfwow==", + "integrity": "sha1-jCKdb4NM20P95mheLUMkjT/ILXg=", "dev": true, "requires": { "mdast-util-toc": "^3.0.0", @@ -12862,7 +11969,7 @@ "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==", + "integrity": "sha1-wr8eN3Ug0yT2I4kuM8EMrCwlK1M=", "dev": true, "requires": { "is-buffer": "^1.1.5", @@ -12888,7 +11995,7 @@ "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", "dev": true }, "repeat-string": { @@ -12926,7 +12033,7 @@ "replacestream": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", - "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "integrity": "sha1-PuV5gJK+Nksc2xSEMISSyz3/LzY=", "dev": true, "requires": { "escape-string-regexp": "^1.0.3", @@ -12937,7 +12044,7 @@ "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "integrity": "sha1-nC/KT301tZLv5Xx/ClXoEFIST+8=", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -12961,19 +12068,6 @@ "uuid": "^3.3.2" } }, - "requestretry": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", - "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", - "dev": true, - "optional": true, - "requires": { - "extend": "^3.0.0", - "lodash": "^4.15.0", - "request": "^2.74.0", - "when": "^3.7.7" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -12999,7 +12093,7 @@ "requirejs": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", - "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", + "integrity": "sha1-5Qk9lgHCgpJRJYwLlEXU0Z+p58k=", "dev": true }, "requires-port": { @@ -13069,7 +12163,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", "dev": true }, "rewire": { @@ -13078,6 +12172,12 @@ "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", "dev": true }, + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -13096,7 +12196,7 @@ "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", "dev": true, "requires": { "hash-base": "^3.0.0", @@ -13130,7 +12230,7 @@ "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==" + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" }, "safe-json-parse": { "version": "1.0.1", @@ -13150,12 +12250,12 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=" }, "samsam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "integrity": "sha1-jR2TUOJWItow3j5EumkrUiGrfFA=", "dev": true }, "schema-utils": { @@ -13196,7 +12296,7 @@ "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "integrity": "sha1-fnQlb7qknHWqfHogXMInmcrIAAQ=", "dev": true }, "semver-greatest-satisfied-range": { @@ -13211,7 +12311,7 @@ "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "integrity": "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=", "dev": true, "requires": { "debug": "2.6.9", @@ -13232,7 +12332,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -13241,7 +12341,7 @@ "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=", "dev": true }, "ms": { @@ -13253,7 +12353,7 @@ "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=", "dev": true } } @@ -13276,7 +12376,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -13293,7 +12393,7 @@ "serve-static": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=", "dev": true, "requires": { "encodeurl": "~1.0.2", @@ -13311,7 +12411,7 @@ "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -13340,7 +12440,7 @@ "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", "dev": true }, "sha.js": { @@ -13371,7 +12471,7 @@ "shelljs": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "integrity": "sha1-p/MxlSDr8J7oEnWyNorbKGZZsJc=", "dev": true, "requires": { "glob": "^7.0.0", @@ -13379,12 +12479,6 @@ "rechoir": "^0.6.2" } }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -13420,16 +12514,6 @@ } } }, - "slack-node": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", - "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", - "dev": true, - "optional": true, - "requires": { - "requestretry": "^1.2.2" - } - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -13439,7 +12523,7 @@ "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==", + "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0" @@ -13456,23 +12540,13 @@ "smart-buffer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", - "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", + "integrity": "sha1-B+ocqNTbJOtMrIZTfX0YmVIhrOM=", "dev": true }, - "smtp-connection": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", - "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true, - "requires": { - "httpntlm": "1.6.1", - "nodemailer-shared": "1.1.0" - } - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "requires": { "base": "^0.11.1", @@ -13488,7 +12562,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -13529,7 +12603,7 @@ "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==", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { "define-property": "^1.0.0", @@ -13549,7 +12623,7 @@ "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==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -13558,7 +12632,7 @@ "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==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -13567,7 +12641,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -13580,7 +12654,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -13607,22 +12681,23 @@ } }, "socket.io": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", - "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { - "debug": "~2.6.6", - "engine.io": "~3.1.0", + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.0.4", - "socket.io-parser": "~3.1.1" + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13643,30 +12718,31 @@ "dev": true }, "socket.io-client": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", - "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "~2.6.4", - "engine.io-client": "~3.1.0", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "~3.1.1", + "socket.io-parser": "~3.2.0", "to-array": "0.1.4" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13681,21 +12757,20 @@ } }, "socket.io-parser": { - "version": "3.1.3", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", - "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", + "version": "3.2.0", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { "component-emitter": "1.2.1", "debug": "~3.1.0", - "has-binary2": "~1.0.2", "isarray": "2.0.1" }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13718,7 +12793,7 @@ "socks": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.2.tgz", - "integrity": "sha512-g6wjBnnMOZpE0ym6e0uHSddz9p3a+WsBaaYQaBaSCJYvrC4IXykQR9MNGjLQf38e9iIIhp3b1/Zk8YZI3KGJ0Q==", + "integrity": "sha1-8GEhn8LU0zKvtK+T6GXITT+ibis=", "dev": true, "requires": { "ip": "^1.1.5", @@ -13728,7 +12803,7 @@ "socks-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", - "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", + "integrity": "sha1-WTa/i3B6mTB5xvN9sgkYIb/6ZHM=", "dev": true, "requires": { "agent-base": "~4.2.0", @@ -13747,18 +12822,18 @@ "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==", + "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=", "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==" + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" }, "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=", "requires": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", @@ -13770,7 +12845,7 @@ "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==", + "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", "dev": true, "requires": { "source-map": "^0.5.6" @@ -13792,7 +12867,7 @@ "space-separated-tokens": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", - "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", + "integrity": "sha1-6Vq50ZroQeIAgIzZa8e9Ctu7NBI=", "dev": true, "requires": { "trim": "0.0.1" @@ -13801,7 +12876,7 @@ "sparkles": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "integrity": "sha1-AI22XtzmxQ7sDF4ijhlFBh3QQ3w=", "dev": true }, "spdx-correct": { @@ -13817,13 +12892,13 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc=", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -13833,7 +12908,7 @@ "spdx-license-ids": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", - "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", + "integrity": "sha1-pZ78CXhMKlutoTz+r1x13SFARNI=", "dev": true }, "split": { @@ -13848,7 +12923,7 @@ "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==", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -13862,7 +12937,7 @@ "sshpk": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "integrity": "sha1-yUbWvZsaOdDoY1dj9SQtbtbctik=", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -13884,7 +12959,7 @@ "state-toggle": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", + "integrity": "sha1-w8sJdPQKag+OkFuWeJ60Gvoc3jo=", "dev": true }, "static-extend": { @@ -13984,13 +13059,13 @@ "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==", + "integrity": "sha1-rNrI2lnvK8HheiwMz2wyDRIOVV0=", "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==", + "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", "dev": true, "requires": { "builtin-status-codes": "^3.0.0", @@ -14009,7 +13084,7 @@ "streamroller": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", "dev": true, "requires": { "date-format": "^1.2.0", @@ -14085,7 +13160,7 @@ "stringify-entities": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", - "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", + "integrity": "sha1-qYQX5Ucf0iez5F09sYYcEcr2aPc=", "dev": true, "requires": { "character-entities-html4": "^1.0.0", @@ -14097,7 +13172,7 @@ "stringstream": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "integrity": "sha1-eIAiWw1K0Q4wkn0Weh1vL9OzOnI=", "dev": true }, "strip-ansi": { @@ -14186,7 +13261,7 @@ "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", "requires": { "has-flag": "^3.0.0" } @@ -14204,7 +13279,7 @@ "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", "dev": true, "requires": { "ajv": "^5.2.3", @@ -14236,7 +13311,7 @@ "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -14265,7 +13340,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -14286,7 +13361,7 @@ "tapable": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz", - "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", + "integrity": "sha1-ry2LvJsE907hevK02QSPgHrNGKg=", "dev": true }, "ternary-stream": { @@ -14316,7 +13391,7 @@ "textextensions": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz", - "integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==", + "integrity": "sha1-ahQ6mFRkOEzCz/Ea6kSM1bAY5ys=", "dev": true }, "through": { @@ -14328,7 +13403,7 @@ "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" @@ -14365,7 +13440,7 @@ "timers-browserify": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "integrity": "sha1-HSjj0qrfHVpZlsTp+VYBzQU0gK4=", "dev": true, "requires": { "setimmediate": "^1.0.4" @@ -14374,23 +13449,16 @@ "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "integrity": "sha1-b1ethXjgej+5+R2Th9ZWR1VeJcY=", "requires": { "es5-ext": "~0.10.46", "next-tick": "1" } }, - "timespan": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", - "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", - "dev": true, - "optional": 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==", + "integrity": "sha1-n6VHQS8jj+2waO4pWvi2gsmLKqs=", "dev": true, "requires": { "body": "^5.1.0", @@ -14404,7 +13472,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -14461,7 +13529,7 @@ "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { "define-property": "^2.0.2", @@ -14492,7 +13560,7 @@ "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "integrity": "sha1-U/Nto/R3g7CSWvoG/587FlKA94E=", "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" @@ -14520,7 +13588,7 @@ "trim-lines": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.1.tgz", - "integrity": "sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==", + "integrity": "sha1-2nOP9Y+nSBdYhFXjCxG4Uonyo5Y=", "dev": true }, "trim-newlines": { @@ -14538,22 +13606,15 @@ "trim-trailing-lines": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", + "integrity": "sha1-4OwIEP08PxcwUWtF9JCDyq8ndNk=", "dev": true }, "trough": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", - "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", + "integrity": "sha1-4pvRYUxkWNRIafwoslWreFfvfCQ=", "dev": true }, - "tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", - "dev": true, - "optional": true - }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14588,33 +13649,6 @@ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, - "type-is": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", - "integrity": "sha1-uTaKWTzG730GReeLL0xky+zQXpA=", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.0.9" - }, - "dependencies": { - "mime-db": { - "version": "1.12.0", - "resolved": "http://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", - "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=", - "dev": true - }, - "mime-types": { - "version": "2.0.14", - "resolved": "http://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", - "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", - "dev": true, - "requires": { - "mime-db": "~1.12.0" - } - } - } - }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -14709,7 +13743,7 @@ "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", "dev": true }, "unc-path-regex": { @@ -14718,12 +13752,6 @@ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true - }, "undertaker": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", @@ -14750,7 +13778,7 @@ "unherit": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", - "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "integrity": "sha1-EydI2j6I6rdn4I+r+7icXp0oYow=", "dev": true, "requires": { "inherits": "^2.0.1", @@ -14760,7 +13788,7 @@ "unified": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", - "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "integrity": "sha1-f71jD3GRJtZ9QMZEt+P2FwNfbbo=", "dev": true, "requires": { "bail": "^1.0.0", @@ -14819,7 +13847,7 @@ "unist-builder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.3.tgz", - "integrity": "sha512-/KB8GEaoeHRyIqClL+Kam+Y5NWJ6yEiPsAfv1M+O1p+aKGgjR89WwoEHKTyOj17L6kAlqtKpAgv2nWvdbQDEig==", + "integrity": "sha1-qw+dDxCTa3Tz6RNSGVWwR44P8DY=", "dev": true, "requires": { "object-assign": "^4.1.0" @@ -14828,25 +13856,25 @@ "unist-util-generated": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.3.tgz", - "integrity": "sha512-qlPeDqnQnd84KIqwphzOR+l02cxjDzvEYEBl84EjmKRrX4eUmjyAo8xJv1SCDhJqNjyHRnBMZWNKAiBtXE6hBg==", + "integrity": "sha1-ymUEcK7y+8xf5UxGW8JrQcoQnis=", "dev": true }, "unist-util-is": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz", - "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", + "integrity": "sha1-EZP6jyv7u4IVBjPzqNLrmhwdVds=", "dev": true }, "unist-util-position": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.2.tgz", - "integrity": "sha512-npmFu92l/+b1Ao6uGP4I1WFz9hsKv7qleZ4aliw6x0RVu6A9A3tAf57NMpFfzQ02jxRtJZuRn+C8xWT7GWnH0g==", + "integrity": "sha1-gK1KBe/EqwGmaIbMcEk4k7pzxes=", "dev": true }, "unist-util-remove-position": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", - "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", + "integrity": "sha1-hrXa0QTQu/vrHbX1yS81cFdcEss=", "dev": true, "requires": { "unist-util-visit": "^1.1.0" @@ -14855,13 +13883,13 @@ "unist-util-stringify-position": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", + "integrity": "sha1-Pzf881EnncvKdICrWIm7ioMu4cY=", "dev": true }, "unist-util-visit": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", - "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", + "integrity": "sha1-HLdjZHGG3Cb14d9dtr0eSLPML7E=", "dev": true, "requires": { "unist-util-visit-parents": "^2.0.0" @@ -14870,7 +13898,7 @@ "unist-util-visit-parents": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", - "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", + "integrity": "sha1-Y//8iSkCe+4Ev+99LM5HT3HLYhc=", "dev": true, "requires": { "unist-util-is": "^2.1.2" @@ -14950,7 +13978,7 @@ "upath": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0=", "dev": true }, "uri-js": { @@ -14984,10 +14012,16 @@ } } }, + "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.4.4", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", - "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "integrity": "sha1-ysFVbpX6oDA2kf7Fz51aG8NGSPg=", "dev": true, "requires": { "querystringify": "^2.0.0", @@ -14997,7 +14031,7 @@ "querystringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", - "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", + "integrity": "sha1-fe2N+/eHncxg0KZErGdUsoOtF+8=", "dev": true } } @@ -15028,31 +14062,23 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", "dev": true }, "useragent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", - "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { - "lru-cache": "2.2.x", + "lru-cache": "4.1.x", "tmp": "0.0.x" - }, - "dependencies": { - "lru-cache": { - "version": "2.2.4", - "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", - "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", - "dev": true - } } }, "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "integrity": "sha1-OqASW/5mikZy3liFfTrOJ+y3aQE=", "dev": true, "requires": { "inherits": "2.0.3" @@ -15072,14 +14098,7 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - }, - "uws": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", - "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", - "dev": true, - "optional": true + "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE=" }, "v8flags": { "version": "3.1.1", @@ -15093,7 +14112,7 @@ "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==", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -15119,7 +14138,7 @@ "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "integrity": "sha1-5i2OcrIOg8MkvGxnJ47ickiL+Eo=", "dev": true, "requires": { "is-buffer": "^1.1.4", @@ -15131,7 +14150,7 @@ "vfile-location": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.4.tgz", - "integrity": "sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w==", + "integrity": "sha1-Kl5yl90Nni2kOBRk0ErMa4NNPlU=", "dev": true }, "vfile-message": { @@ -15176,19 +14195,19 @@ "vfile-sort": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.0.tgz", - "integrity": "sha512-RgxLXVWrJBWb2GuP8FsSkqK7HmbjXjnI8qx3nD6NTWhsWaelaKvJuxfh1F1d1lkCPD7imo4zzi8cf6IOMgaTnQ==", + "integrity": "sha1-ODqHJ+xMXa83wFaDaEpetoY2bTk=", "dev": true }, "vfile-statistics": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.2.tgz", - "integrity": "sha512-16wAC9eEGXdsD35LX9m/iXCRIZyX5LIrDgDtAF92rbATSqsBRbC4n05e0Rj5vt3XRpcKu0UJeWnTxWsSyvNZ+w==", + "integrity": "sha1-xQEyYn5GaaOvoHxk/x56p2legVE=", "dev": true }, "vinyl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "integrity": "sha1-2FsH2pbkWNJbL/4Z/s6fLKoT7YY=", "dev": true, "requires": { "clone": "^2.1.1", @@ -15202,7 +14221,7 @@ "vinyl-fs": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "integrity": "sha1-yFhJQF9nQo/qu71cXb3WT0fTG8c=", "dev": true, "requires": { "fs-mkdirp-stream": "^1.0.0", @@ -15259,7 +14278,7 @@ "vlq": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.0.tgz", - "integrity": "sha512-o3WmXySo+oI5thgqr7Qy8uBkT/v9Zr+sRyrh1lr8aWPUkgDWdWt4Nae2WKBrLsocgE8BuWWD0jLc+VW8LeU+2g==" + "integrity": "sha1-gQG+kIQ0IpVMKxPrJ/LzEivcyAY=" }, "vm-browserify": { "version": "0.0.4", @@ -15279,22 +14298,16 @@ "walk": { "version": "2.3.14", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", - "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", + "integrity": "sha1-YOyGMc/SMnauHnNjzhHWJkUuHvM=", "dev": true, "requires": { "foreachasync": "^3.0.0" } }, - "watch": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.11.0.tgz", - "integrity": "sha1-6NugkbdFZ5mjr1eXi5hud+EyBAY=", - "dev": true - }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "integrity": "sha1-S8EsLr6KonenHx0/FNaFx7RGzQA=", "dev": true, "requires": { "chokidar": "^2.0.2", @@ -15305,7 +14318,7 @@ "webpack": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", - "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", + "integrity": "sha1-P540NgNwYC/PY56Xk520hvTsDXQ=", "dev": true, "requires": { "acorn": "^5.0.0", @@ -15347,7 +14360,7 @@ "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "integrity": "sha1-skWiPKcZMAROxT+kaqAKPofGphA=", "dev": true, "requires": { "lodash": "^4.17.10" @@ -15431,7 +14444,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -15507,30 +14520,57 @@ } }, "webpack-dev-middleware": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", - "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "version": "2.0.6", + "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { + "loud-rejection": "^1.6.0", "memory-fs": "~0.4.1", - "mime": "^1.5.0", + "mime": "^2.1.0", "path-is-absolute": "^1.0.0", "range-parser": "^1.0.3", - "time-stamp": "^2.0.0" + "url-join": "^2.0.2", + "webpack-log": "^1.0.1" }, "dependencies": { - "time-stamp": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.2.0.tgz", - "integrity": "sha512-zxke8goJQpBeEgD82CXABeMh0LSJcj7CXEd0OHOg45HgcofF7pxNwZm9+RknpxpDhwN4gFpySkApKfFYfRQnUA==", + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true } } }, + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha1-pLNM2msitRjbsKsy5WeWLVxypD0=", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, "webpack-sources": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "integrity": "sha1-KijcufH0X+lg2PFJMlK17mUw+oU=", "dev": true, "requires": { "source-list-map": "^2.0.0", @@ -16053,20 +15093,13 @@ "websocket-extensions": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", "dev": true }, - "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true, - "optional": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", "dev": true, "requires": { "isexe": "^2.0.0" @@ -16084,13 +15117,6 @@ "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", "dev": true }, - "with-callback": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", - "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", - "dev": true, - "optional": true - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -16125,7 +15151,7 @@ "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", "dev": true, "requires": { "async-limiter": "~1.0.0", diff --git a/package.json b/package.json index a03509bf3c3..b592fff1453 100755 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", - "gulp-webserver": "^0.9.1", + "gulp-connect": "^5.7.0", "gulp-coveralls": "^0.1.4", "gulp-eslint": "^4.0.0", "gulp-footer": "github:prebid/gulp-footer#master", @@ -63,9 +63,9 @@ "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", "json-loader": "^0.5.1", - "karma": "^2.0.0", + "karma": "^3.1.3", "karma-babel-preprocessor": "^6.0.1", - "karma-browserstack-launcher": "^1.0.1", + "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^2.2.0", "karma-coverage-istanbul-reporter": "^1.3.0", @@ -75,20 +75,19 @@ "karma-mocha": "^1.3.0", "karma-mocha-reporter": "^2.2.5", "karma-opera-launcher": "^1.0.0", - "karma-requirejs": "^1.1.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.31", - "karma-webpack": "^2.0.3", + "karma-webpack": "^3.0.5", "localtunnel": "^1.3.0", "lodash": "^4.17.4", "mkpath": "^1.0.0", - "mocha": "2.2.5", + "mocha": "^5.0.0", "mock-fs": "^3.11.0", "nightwatch": "^1.0.6", - "open": "0.0.5", + "opn": "^5.4.0", "proxyquire": "^1.7.10", "querystringify": "0.0.3", "requirejs": "^2.1.20", diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index b9c2d445646..163cb326740 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -1,4 +1,4 @@ -import 'mocha'; +import 'mocha/mocha'; import chai from 'chai'; import { getCacheUrl, store } from 'src/videoCache'; import { config } from 'src/config'; From 74dcdfafe7fbdb39103e327210f745dc26b0548a Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 3 Jan 2019 12:12:46 -0500 Subject: [PATCH 0915/1594] Fix #3265 - pbs cookie sync race condition (#3393) * Fix #3265 - pbs cookie sync race condition * add/update jsdoc comments --- modules/prebidServerBidAdapter/index.js | 24 ++++++++++++++++++++---- src/utils.js | 18 ++++++++++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 7ecf61088d4..6e125d6d79f 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -150,7 +150,7 @@ function queueSync(bidderCodes, gdprConsent) { (response) => { try { response = JSON.parse(response); - response.bidder_status.forEach(bidder => doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder)); + doAllSyncs(response.bidder_status); } catch (e) { utils.logError(e); } @@ -162,24 +162,40 @@ function queueSync(bidderCodes, gdprConsent) { }); } +function doAllSyncs(bidders) { + if (bidders.length === 0) { + return; + } + + const thisSync = bidders.pop(); + if (thisSync.no_cookie) { + doBidderSync(thisSync.usersync.type, thisSync.usersync.url, thisSync.bidder, doAllSyncs.bind(null, bidders)); + } else { + doAllSyncs(bidders); + } +} + /** * Run a cookie sync for the given type, url, and bidder * * @param {string} type the type of sync, "image", "redirect", "iframe" * @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 */ -function doBidderSync(type, url, bidder) { +function doBidderSync(type, url, bidder, done) { if (!url) { utils.logError(`No sync url for bidder "${bidder}": ${url}`); + done(); } else if (type === 'image' || type === 'redirect') { utils.logMessage(`Invoking image pixel user sync for bidder: "${bidder}"`); - utils.triggerPixel(url); + utils.triggerPixel(url, done); } else if (type == 'iframe') { utils.logMessage(`Invoking iframe user sync for bidder: "${bidder}"`); - utils.insertUserSyncIframe(url); + utils.insertUserSyncIframe(url, done); } else { utils.logError(`User sync type "${type}" not supported for bidder: "${bidder}"`); + done(); } } diff --git a/src/utils.js b/src/utils.js index a769f588691..0c201b84bab 100644 --- a/src/utils.js +++ b/src/utils.js @@ -568,8 +568,17 @@ exports.insertElement = function(elm, doc, target) { } catch (e) {} }; -exports.triggerPixel = function (url) { +/** + * 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 + */ +exports.triggerPixel = function (url, done) { const img = new Image(); + if (done && exports.isFn(done)) { + img.addEventListener('load', done); + img.addEventListener('error', done); + } img.src = url; }; @@ -615,12 +624,17 @@ exports.insertHtmlIntoIframe = function(htmlCode) { * Inserts empty iframe with the specified `url` for cookie sync * @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 */ -exports.insertUserSyncIframe = function(url) { +exports.insertUserSyncIframe = function(url, done) { let iframeHtml = exports.createTrackPixelIframeHtml(url, false, 'allow-scripts allow-same-origin'); let div = document.createElement('div'); div.innerHTML = iframeHtml; let iframe = div.firstChild; + if (done && exports.isFn(done)) { + iframe.addEventListener('load', done); + iframe.addEventListener('error', done); + } exports.insertElement(iframe); }; From ec8d5a633c166d7a04ff9bced6c30f9a061cd8a1 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Thu, 3 Jan 2019 11:59:24 -0800 Subject: [PATCH 0916/1594] Update conversant adapter support for video playerSize (#3376) --- modules/conversantBidAdapter.js | 60 +++++----- modules/conversantBidAdapter.md | 3 +- .../spec/modules/conversantBidAdapter_spec.js | 108 ++++++++++++++++-- 3 files changed, 129 insertions(+), 42 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index b3d944a99e4..a7616786bb9 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -4,7 +4,7 @@ import { BANNER, VIDEO } from 'src/mediaTypes'; const BIDDER_CODE = 'conversant'; const URL = '//web.hb.ad.cpe.dotomi.com/s2s/header/24'; -const VERSION = '2.2.3'; +const VERSION = '2.2.4'; export const spec = { code: BIDDER_CODE, @@ -62,8 +62,6 @@ export const spec = { siteId = utils.getBidIdParameter('site_id', bid.params); requestId = bid.auctionId; - let format = convertSizes(bid.sizes); - const imp = { id: bid.bidId, secure: secure, @@ -72,29 +70,31 @@ export const spec = { displaymanagerver: VERSION }; - copyOptProperty(bid.params, 'tag_id', imp, 'tagid'); + copyOptProperty(bid.params.tag_id, imp, 'tagid'); if (isVideoRequest(bid)) { - if (bid.mediaTypes.video.playerSize) { - format = convertSizes(bid.mediaTypes.video.playerSize); - } + const videoData = utils.deepAccess(bid, 'mediaTypes.video') || {}; + const format = convertSizes(videoData.playerSize || bid.sizes); + const video = {}; - const video = { - w: format[0].w, - h: format[0].h - }; + if (format && format[0]) { + copyOptProperty(format[0].w, video, 'w'); + copyOptProperty(format[0].h, video, 'h'); + } - copyOptProperty(bid.params, 'position', video, 'pos'); - copyOptProperty(bid.params, 'mimes', video); - copyOptProperty(bid.params, 'maxduration', video); - copyOptProperty(bid.params, 'protocols', video); - copyOptProperty(bid.params, 'api', video); + copyOptProperty(bid.params.position, video, 'pos'); + copyOptProperty(bid.params.mimes || videoData.mimes, video, 'mimes'); + copyOptProperty(bid.params.maxduration, video, 'maxduration'); + copyOptProperty(bid.params.protocols || videoData.protocols, video, 'protocols'); + copyOptProperty(bid.params.api || videoData.api, video, 'api'); imp.video = video; } else { + const bannerData = utils.deepAccess(bid, 'mediaTypes.banner') || {}; + const format = convertSizes(bannerData.sizes || bid.sizes); const banner = {format: format}; - copyOptProperty(bid.params, 'position', banner, 'pos'); + copyOptProperty(bid.params.position, banner, 'pos'); imp.banner = banner; } @@ -253,11 +253,12 @@ function getDevice() { */ function convertSizes(bidSizes) { let format; - - if (bidSizes.length === 2 && typeof bidSizes[0] === 'number' && typeof bidSizes[1] === 'number') { - format = [{w: bidSizes[0], h: bidSizes[1]}]; - } else { - format = utils._map(bidSizes, d => { return {w: d[0], h: d[1]}; }); + if (Array.isArray(bidSizes)) { + if (bidSizes.length === 2 && typeof bidSizes[0] === 'number' && typeof bidSizes[1] === 'number') { + format = [{w: bidSizes[0], h: bidSizes[1]}]; + } else { + format = utils._map(bidSizes, d => { return {w: d[0], h: d[1]}; }); + } } return format; @@ -276,16 +277,13 @@ function isVideoRequest(bid) { /** * Copy property if exists from src to dst * - * @param {object} src - * @param {string} srcName - * @param {object} dst - * @param {string} [dstName] - Optional. If not specified then srcName is used. + * @param {object} src - source object + * @param {object} dst - destination object + * @param {string} dstName - destination property name */ -function copyOptProperty(src, srcName, dst, dstName) { - dstName = dstName || srcName; - const obj = utils.getBidIdParameter(srcName, src); - if (obj !== '') { - dst[dstName] = obj; +function copyOptProperty(src, dst, dstName) { + if (src) { + dst[dstName] = src; } } diff --git a/modules/conversantBidAdapter.md b/modules/conversantBidAdapter.md index 2b1e3ce8d55..3ce83d8c893 100644 --- a/modules/conversantBidAdapter.md +++ b/modules/conversantBidAdapter.md @@ -22,7 +22,6 @@ var adUnits = [ }] },{ code: 'video-test-div', - sizes: [640, 480], mediaTypes: { video: { context: 'instream', @@ -32,7 +31,7 @@ var adUnits = [ bids: [{ bidder: "conversant", params: { - site_id: '88563', + site_id: '108060', api: [2], protocols: [1, 2], mimes: ['video/mp4'] diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index be173279f2d..f4c14032fc5 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -8,6 +8,7 @@ describe('Conversant adapter tests', function() { const siteId = '108060'; const bidRequests = [ + // banner with single size { bidder: 'conversant', params: { @@ -23,19 +24,27 @@ describe('Conversant adapter tests', function() { bidId: 'bid000', bidderRequestId: '117d765b87bed38', auctionId: 'req000' - }, { + }, + // banner with sizes in mediaTypes.banner.sizes + { bidder: 'conversant', params: { site_id: siteId, secure: false }, + mediaTypes: { + banner: { + sizes: [[728, 90], [468, 60]] + } + }, placementCode: 'pcode001', transactionId: 'tx001', - sizes: [[468, 60]], bidId: 'bid001', bidderRequestId: '117d765b87bed38', auctionId: 'req000' - }, { + }, + // banner with tag id and position + { bidder: 'conversant', params: { site_id: siteId, @@ -49,7 +58,9 @@ describe('Conversant adapter tests', function() { bidId: 'bid002', bidderRequestId: '117d765b87bed38', auctionId: 'req000' - }, { + }, + // video with single size + { bidder: 'conversant', params: { site_id: siteId, @@ -70,6 +81,47 @@ describe('Conversant adapter tests', function() { bidId: 'bid003', bidderRequestId: '117d765b87bed38', auctionId: 'req000' + }, + // video with playerSize + { + bidder: 'conversant', + params: { + site_id: siteId, + maxduration: 30, + api: [2, 3] + }, + mediaTypes: { + video: { + context: 'instream', + playerSize: [1024, 768], + api: [1, 2], + protocols: [1, 2, 3], + mimes: ['video/mp4', 'video/x-flv'] + } + }, + placementCode: 'pcode004', + transactionId: 'tx004', + bidId: 'bid004', + bidderRequestId: '117d765b87bed38', + auctionId: 'req000' + }, + // video without sizes + { + bidder: 'conversant', + params: { + site_id: siteId + }, + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mp4', 'video/x-flv'] + } + }, + placementCode: 'pcode005', + transactionId: 'tx005', + bidId: 'bid005', + bidderRequestId: '117d765b87bed38', + auctionId: 'req000' }]; const bidResponses = { @@ -129,6 +181,8 @@ describe('Conversant adapter tests', function() { expect(spec.isBidRequestValid(bidRequests[1])).to.be.true; expect(spec.isBidRequestValid(bidRequests[2])).to.be.true; expect(spec.isBidRequestValid(bidRequests[3])).to.be.true; + expect(spec.isBidRequestValid(bidRequests[4])).to.be.true; + expect(spec.isBidRequestValid(bidRequests[5])).to.be.true; const simpleVideo = JSON.parse(JSON.stringify(bidRequests[3])); simpleVideo.params.site_id = 123; @@ -151,7 +205,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(4); + 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', 0); @@ -169,18 +223,18 @@ describe('Conversant adapter tests', function() { expect(payload.imp[1]).to.have.property('secure', 0); expect(payload.imp[1]).to.have.property('bidfloor', 0); expect(payload.imp[1]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[1]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); expect(payload.imp[1]).to.not.have.property('tagid'); expect(payload.imp[1]).to.have.property('banner'); expect(payload.imp[1].banner).to.not.have.property('pos'); expect(payload.imp[1].banner).to.have.property('format'); - expect(payload.imp[1].banner.format).to.deep.equal([{w: 468, h: 60}]); + expect(payload.imp[1].banner.format).to.deep.equal([{w: 728, h: 90}, {w: 468, h: 60}]); expect(payload.imp[2]).to.have.property('id', 'bid002'); expect(payload.imp[2]).to.have.property('secure', 0); expect(payload.imp[2]).to.have.property('bidfloor', 0); expect(payload.imp[2]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[2]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); expect(payload.imp[2]).to.have.property('banner'); expect(payload.imp[2].banner).to.have.property('pos', 2); expect(payload.imp[2].banner).to.have.property('format'); @@ -190,7 +244,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[3]).to.have.property('secure', 0); expect(payload.imp[3]).to.have.property('bidfloor', 0); expect(payload.imp[3]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[3]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); expect(payload.imp[3]).to.not.have.property('tagid'); expect(payload.imp[3]).to.have.property('video'); expect(payload.imp[3].video).to.not.have.property('pos'); @@ -205,6 +259,42 @@ describe('Conversant adapter tests', function() { expect(payload.imp[3].video).to.have.property('maxduration', 30); expect(payload.imp[3]).to.not.have.property('banner'); + expect(payload.imp[4]).to.have.property('id', 'bid004'); + expect(payload.imp[4]).to.have.property('secure', 0); + expect(payload.imp[4]).to.have.property('bidfloor', 0); + expect(payload.imp[4]).to.have.property('displaymanager', 'Prebid.js'); + expect(payload.imp[4]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[4]).to.not.have.property('tagid'); + expect(payload.imp[4]).to.have.property('video'); + expect(payload.imp[4].video).to.not.have.property('pos'); + expect(payload.imp[4].video).to.have.property('w', 1024); + expect(payload.imp[4].video).to.have.property('h', 768); + expect(payload.imp[4].video).to.have.property('mimes'); + expect(payload.imp[4].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); + expect(payload.imp[4].video).to.have.property('protocols'); + expect(payload.imp[4].video.protocols).to.deep.equal([1, 2, 3]); + expect(payload.imp[4].video).to.have.property('api'); + expect(payload.imp[4].video.api).to.deep.equal([2, 3]); + expect(payload.imp[4].video).to.have.property('maxduration', 30); + expect(payload.imp[4]).to.not.have.property('banner'); + + expect(payload.imp[5]).to.have.property('id', 'bid005'); + expect(payload.imp[5]).to.have.property('secure', 0); + expect(payload.imp[5]).to.have.property('bidfloor', 0); + expect(payload.imp[5]).to.have.property('displaymanager', 'Prebid.js'); + expect(payload.imp[5]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[5]).to.not.have.property('tagid'); + expect(payload.imp[5]).to.have.property('video'); + expect(payload.imp[5].video).to.not.have.property('pos'); + expect(payload.imp[5].video).to.not.have.property('w'); + expect(payload.imp[5].video).to.not.have.property('h'); + expect(payload.imp[5].video).to.have.property('mimes'); + expect(payload.imp[5].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); + expect(payload.imp[5].video).to.not.have.property('protocols'); + expect(payload.imp[5].video).to.not.have.property('api'); + expect(payload.imp[5].video).to.not.have.property('maxduration'); + expect(payload.imp[5]).to.not.have.property('banner'); + 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]); From cda814b46e0779f3d3ec4bb0184649c51d43f907 Mon Sep 17 00:00:00 2001 From: afsheenb Date: Thu, 3 Jan 2019 16:27:20 -0500 Subject: [PATCH 0917/1594] ozone adapter now explicitly sets site.page object, adds debug flag via query string (#3403) --- modules/ozoneBidAdapter.js | 59 +++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index 5ef5d7058b6..9bf4389e323 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -113,9 +113,9 @@ export const spec = { bidderRequest.publisherId = (bidderRequest.publisherId).toString(); } - if (!ozoneRequest.test) { - delete ozoneRequest.test; - } + // if (!ozoneRequest.test) { + delete ozoneRequest.test; // don't allow test to be set in the config - ONLY use $_GET['pbjs_debug'] + // } if (bidderRequest.gdprConsent) { ozoneRequest.regs = {}; ozoneRequest.regs.ext = {}; @@ -124,38 +124,40 @@ export const spec = { ozoneRequest.regs.ext.consent = bidderRequest.gdprConsent.consentString; } } - let tosendtags = validBidRequests.map(ozone => { + let tosendtags = validBidRequests.map(ozoneBidRequest => { var obj = {}; - obj.id = ozone.bidId; - obj.tagid = String(ozone.params.ozoneid); + obj.id = ozoneBidRequest.bidId; + obj.tagid = String(ozoneBidRequest.params.ozoneid); obj.secure = window.location.protocol === 'https:' ? 1 : 0; obj.banner = { topframe: 1, - w: ozone.sizes[0][0] || 0, - h: ozone.sizes[0][1] || 0, - format: ozone.sizes.map(s => { + w: ozoneBidRequest.sizes[0][0] || 0, + h: ozoneBidRequest.sizes[0][1] || 0, + format: ozoneBidRequest.sizes.map(s => { return {w: s[0], h: s[1]}; }) }; - if (ozone.params.hasOwnProperty('customData')) { - obj.customData = ozone.params.customData; + if (ozoneBidRequest.params.hasOwnProperty('customData')) { + obj.customData = ozoneBidRequest.params.customData; } - if (ozone.params.hasOwnProperty('ozoneData')) { - obj.ozoneData = ozone.params.ozoneData; + if (ozoneBidRequest.params.hasOwnProperty('ozoneData')) { + obj.ozoneData = ozoneBidRequest.params.ozoneData; } - if (ozone.params.hasOwnProperty('lotameData')) { - obj.lotameData = ozone.params.lotameData; + if (ozoneBidRequest.params.hasOwnProperty('lotameData')) { + obj.lotameData = ozoneBidRequest.params.lotameData; } - if (ozone.params.hasOwnProperty('publisherId')) { - obj.publisherId = (ozone.params.publisherId).toString(); + if (ozoneBidRequest.params.hasOwnProperty('publisherId')) { + obj.publisherId = (ozoneBidRequest.params.publisherId).toString(); } - if (ozone.params.hasOwnProperty('siteId')) { - obj.siteId = (ozone.params.siteId).toString(); + if (ozoneBidRequest.params.hasOwnProperty('siteId')) { + obj.siteId = (ozoneBidRequest.params.siteId).toString(); } - obj.ext = {'prebid': {'storedrequest': {'id': (ozone.params.placementId).toString()}}}; + obj.ext = {'prebid': {'storedrequest': {'id': (ozoneBidRequest.params.placementId).toString()}}}; return obj; }); ozoneRequest.imp = tosendtags; + ozoneRequest.site = {'publisher': {'id': ozoneRequest.publisherId}, 'page': document.location.href}; + ozoneRequest.test = parseInt(getTestQuerystringValue()); // will be 1 or 0 var ret = { method: 'POST', url: OZONEURI, @@ -255,4 +257,21 @@ export function ozoneAddStandardProperties(seatBid, defaultWidth, defaultHeight) return seatBid; } +/** + * we need to add test=1 or test=0 to the get params sent to the server. + * Get the value set as pbjs_debug= in the url, OR 0. + * @returns {*} + */ +export function getTestQuerystringValue() { + let searchString = window.location.search.substring(1); + let params = searchString.split('&'); + for (let i = 0; i < params.length; i++) { + let val = params[i].split('='); + if (val[0] === 'pbjs_debug') { + return val[1] === 'true' ? 1 : 0; + } + } + return 0; +} + registerBidder(spec); From 460a1e27a873a2dee4e0fbd596334cc45d348662 Mon Sep 17 00:00:00 2001 From: olafbuitelaar Date: Thu, 3 Jan 2019 22:38:47 +0100 Subject: [PATCH 0918/1594] Eslintformatting2 (#3416) * * make eslint fix formatting * * remove double semi-column --- gulpfile.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index abea226d387..5d0ae51504e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -80,10 +80,14 @@ function lint(done) { if (argv.nolint) { return done(); } - return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js']) - .pipe(eslint()) + const isFixed = function(file){ + return file.eslint != null && file.eslint.fixed; + } + return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js'],{base: './'}) + .pipe(eslint({fix: true})) .pipe(eslint.format('stylish')) - .pipe(eslint.failAfterError()); + .pipe(eslint.failAfterError()) + .pipe(gulpif(isFixed, gulp.dest('./'))); }; // View the code coverage report in the browser. From b5041ac4dbe8b9ffa6280c03dcab0e041d7df18c Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Fri, 4 Jan 2019 10:05:41 -0500 Subject: [PATCH 0919/1594] fix spacing in gulp lint command (#3418) --- gulpfile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 5d0ae51504e..ea400abdd6c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -80,10 +80,10 @@ function lint(done) { if (argv.nolint) { return done(); } - const isFixed = function(file){ + const isFixed = function(file) { return file.eslint != null && file.eslint.fixed; } - return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js'],{base: './'}) + return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js'], {base: './'}) .pipe(eslint({fix: true})) .pipe(eslint.format('stylish')) .pipe(eslint.failAfterError()) From 26e88f40eef835119e52794928728ac0fc6d0f31 Mon Sep 17 00:00:00 2001 From: Josh Becker Date: Fri, 4 Jan 2019 11:46:38 -0800 Subject: [PATCH 0920/1594] STR adapter should not hardcode `const` into script content (#3417) A `const` in a string literal like this won't be correctly transpiled by babel, so we'll be limited by the browser support matrix for `const` Fix: harcode a `var` here to be more permissive and widely supported --- modules/sharethroughBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index bda63b5521e..7f05a3e9abd 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -122,7 +122,7 @@ function generateAd(body, req) { `; + bid.mediaType = BANNER; } - bid.ad = `${nurl}`; + + // Common properties bid.adId = bidObject.id; bid.cpm = parseFloat(bidObject.price); bid.creativeId = bidObject.crid; @@ -102,6 +118,15 @@ export const spec = { bid.ttl = 300; bid.width = bidObject.w; + if (!bid.width || !bid.height) { + bid.width = 1; + bid.height = 1; + if (bidRequest.sizes) { + bid.width = bidRequest.sizes[0][0]; + bid.height = bidRequest.sizes[0][1]; + } + } + bids.push(bid); }); return bids; @@ -184,6 +209,56 @@ function getNormalizedBidRequest(bid) { } return normalizedBidRequest; } + +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 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 + native.impressionTrackers = rawNative.imptrackers || []; + native.javascriptTrackers = rawNative.jstracker; + if (rawNative.link) { + native.clickUrl = rawNative.link.url; + native.clickTrackers = rawNative.link.clicktrackers; + } + return native; +} registerBidder(spec); function ImproveDigitalAdServerJSClient(endPoint) { @@ -195,7 +270,7 @@ function ImproveDigitalAdServerJSClient(endPoint) { AD_SERVER_BASE_URL: 'ad.360yield.com', END_POINT: endPoint || 'hb', AD_SERVER_URL_PARAM: 'jsonp=', - CLIENT_VERSION: 'JS-5.1', + CLIENT_VERSION: 'JS-5.2.0', MAX_URL_LENGTH: 2083, ERROR_CODES: { MISSING_PLACEMENT_PARAMS: 2, @@ -308,7 +383,7 @@ function ImproveDigitalAdServerJSClient(endPoint) { return { method: 'GET', url: `//${this.CONSTANTS.AD_SERVER_BASE_URL}/${this.CONSTANTS.END_POINT}`, - data: `${this.CONSTANTS.AD_SERVER_URL_PARAM}${JSON.stringify(bidRequestObject)}` + data: `${this.CONSTANTS.AD_SERVER_URL_PARAM}${encodeURIComponent(JSON.stringify(bidRequestObject))}` }; default: const baseUrl = `${(requestParameters.secure === 1 ? 'https' : 'http')}://` + @@ -348,7 +423,7 @@ function ImproveDigitalAdServerJSClient(endPoint) { if (requestParameters.referrer) { impressionBidRequestObject.referrer = requestParameters.referrer; } - if (requestParameters.gdpr) { + if (requestParameters.gdpr || requestParameters.gdpr === 0) { impressionBidRequestObject.gdpr = requestParameters.gdpr; } if (extraRequestParameters) { diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 3d7f5a86016..8b76bfcbe9c 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -92,7 +92,7 @@ describe('Improve Digital Adapter Tests', function () { expect(request.url).to.equal(URL); expect(request.data.substring(0, PARAM_PREFIX.length)).to.equal(PARAM_PREFIX); - const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); expect(params.bid_request).to.be.an('object'); expect(params.bid_request.id).to.be.a('string'); expect(params.bid_request.version).to.equal(`${spec.version}-${idClient.CONSTANTS.CLIENT_VERSION}`); @@ -108,7 +108,7 @@ describe('Improve Digital Adapter Tests', function () { it('should set placementKey and publisherId for smart tags', function () { const requests = spec.buildRequests([simpleSmartTagBidRequest]); - const params = JSON.parse(requests[0].data.substring(PARAM_PREFIX.length)); + const params = JSON.parse(decodeURIComponent(requests[0].data.substring(PARAM_PREFIX.length))); expect(params.bid_request.imp[0].pubid).to.equal(1032); expect(params.bid_request.imp[0].pkey).to.equal('data_team_test_hb_smoke_test'); }); @@ -122,7 +122,7 @@ describe('Improve Digital Adapter Tests', function () { }; bidRequest.params.keyValues = keyValues; const request = spec.buildRequests([bidRequest])[0]; - const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); expect(params.bid_request.imp[0].kvw).to.deep.equal(keyValues); }); @@ -134,7 +134,7 @@ describe('Improve Digital Adapter Tests', function () { }; bidRequest.params.size = size; const request = spec.buildRequests([bidRequest])[0]; - const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); expect(params.bid_request.imp[0].banner).to.deep.equal(size); }); @@ -142,7 +142,7 @@ describe('Improve Digital Adapter Tests', function () { const bidRequest = Object.assign({}, simpleBidRequest); const getConfigStub = sinon.stub(config, 'getConfig').returns('JPY'); const request = spec.buildRequests([bidRequest])[0]; - const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); expect(params.bid_request.imp[0].currency).to.equal('JPY'); getConfigStub.restore(); }); @@ -150,7 +150,7 @@ describe('Improve Digital Adapter Tests', function () { it('should add GDPR consent string', function () { const bidRequest = Object.assign({}, simpleBidRequest); const request = spec.buildRequests([bidRequest], bidderRequest)[0]; - const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); expect(params.bid_request.gdpr).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); @@ -162,6 +162,18 @@ describe('Improve Digital Adapter Tests', function () { expect(requests).to.be.an('array'); expect(requests.length).to.equal(2); }); + + it('should return one request in a single request mode', function () { + const getConfigStub = sinon.stub(config, 'getConfig'); + getConfigStub.withArgs('improvedigital.singleRequest').returns(true); + const requests = spec.buildRequests([ + simpleBidRequest, + simpleSmartTagBidRequest + ]); + expect(requests).to.be.an('array'); + expect(requests.length).to.equal(1); + getConfigStub.restore(); + }); }); const serverResponse = { @@ -218,6 +230,100 @@ describe('Improve Digital Adapter Tests', function () { } }; + const serverResponseNative = { + body: { + id: '687a06c541d8d1', + site_id: 191642, + bid: [ + { + isNet: false, + id: '33e9500b21129f', + advid: '5279', + price: 1.45888594164456, + nurl: 'http://ad.360yield.com/imp_pixel?ic=wVm', + h: 290, + pid: 1053688, + sync: [ + 'http://link1', + 'http://link2' + ], + crid: '422031', + w: 600, + cid: '99006', + native: { + assets: [ + { + title: { + text: 'Native title' + } + }, + { + data: { + type: 1, + value: 'Improve Digital' + } + }, + { + data: { + type: 2, + value: 'Native body' + } + }, + { + data: { + type: 3, + value: 'Should get ignored' + } + }, + { + data: { + type: 12, + value: 'Do it' + } + }, + { + img: { + type: 1, + url: 'Should get ignored', + h: 300, + w: 400 + } + }, + { + img: { + type: 2, + url: 'http://blah.com/icon.jpg', + h: 30, + w: 40 + } + }, + { + img: { + type: 3, + url: 'http://blah.com/image.jpg', + h: 200, + w: 800 + } + } + ], + link: { + url: 'http://advertiser.com', + clicktrackers: [ + 'http://click.tracker.com/click?impid=123' + ] + }, + imptrackers: [ + 'http://imptrack1.com', + 'http://imptrack2.com' + ], + jstracker: '' + } + } + ], + debug: '' + } + }; + describe('interpretResponse', function () { let expectedBid = [ { @@ -227,6 +333,7 @@ describe('Improve Digital Adapter Tests', function () { 'cpm': 1.45888594164456, 'currency': 'USD', 'height': 290, + 'mediaType': 'banner', 'netRevenue': false, 'requestId': '33e9500b21129f', 'ttl': 300, @@ -243,6 +350,7 @@ describe('Improve Digital Adapter Tests', function () { 'cpm': 1.23, 'currency': 'USD', 'height': 400, + 'mediaType': 'banner', 'netRevenue': true, 'requestId': '1234', 'ttl': 300, @@ -250,6 +358,45 @@ describe('Improve Digital Adapter Tests', function () { } ]; + let expectedBidNative = [ + { + mediaType: 'native', + adId: '33e9500b21129f', + creativeId: '422031', + cpm: 1.45888594164456, + currency: 'USD', + height: 290, + netRevenue: false, + requestId: '33e9500b21129f', + ttl: 300, + width: 600, + native: { + title: 'Native title', + body: 'Native body', + cta: 'Do it', + sponsoredBy: 'Improve Digital', + icon: { + url: 'http://blah.com/icon.jpg', + height: 30, + width: 40 + }, + image: { + url: 'http://blah.com/image.jpg', + height: 200, + width: 800 + }, + clickUrl: 'http://advertiser.com', + clickTrackers: ['http://click.tracker.com/click?impid=123'], + impressionTrackers: [ + 'http://ad.360yield.com/imp_pixel?ic=wVm', + 'http://imptrack1.com', + 'http://imptrack2.com' + ], + javascriptTrackers: '' + } + } + ]; + it('should return a well-formed bid', function () { const bids = spec.interpretResponse(serverResponse); expect(bids).to.deep.equal(expectedBid); @@ -328,7 +475,7 @@ describe('Improve Digital Adapter Tests', function () { bids = spec.interpretResponse(response); expect(bids).to.deep.equal([]); - // Adm missing or bad + // adm and native missing response = JSON.parse(JSON.stringify(serverResponse)); delete response.body.bid[0].adm; bids = spec.interpretResponse(response); @@ -336,12 +483,6 @@ describe('Improve Digital Adapter Tests', function () { response.body.bid[0].adm = null; bids = spec.interpretResponse(response); expect(bids).to.deep.equal([]); - response.body.bid[0].adm = 1234; - bids = spec.interpretResponse(response); - expect(bids).to.deep.equal([]); - response.body.bid[0].adm = {}; - bids = spec.interpretResponse(response); - expect(bids).to.deep.equal([]); }); it('should set netRevenue', function () { @@ -350,6 +491,12 @@ describe('Improve Digital Adapter Tests', function () { const bids = spec.interpretResponse(response); expect(bids[0].netRevenue).to.equal(true); }); + + // Native ads + it('should return a well-formed native ad bid', function () { + const bids = spec.interpretResponse(serverResponseNative); + expect(bids).to.deep.equal(expectedBidNative); + }); }); describe('getUserSyncs', function () { From 41af5005b1c349da7eec74a783a18d8266002d6b Mon Sep 17 00:00:00 2001 From: Deeky Polusani Date: Tue, 8 Jan 2019 09:33:49 -0500 Subject: [PATCH 0923/1594] revert package.lock changes --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 420bd8abe0e..b55faaa4e7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15216,4 +15216,4 @@ "dev": true } } -} +} \ No newline at end of file From e9dea175416caf11ba9d958932d7642fa557319e Mon Sep 17 00:00:00 2001 From: Andrew Bowman Date: Tue, 8 Jan 2019 10:01:09 -0500 Subject: [PATCH 0924/1594] Adding Remaining Native Parameters from AppNexus Native response (#3387) * Adding remaining missing parameters from AppNexus Native response * Removed native video, renamed sale and clickLabel to RTB spec names * drop video from tests --- modules/appnexusBidAdapter.js | 13 +++++++-- src/constants.json | 9 ++++++- test/spec/modules/appnexusBidAdapter_spec.js | 28 ++++++++++++++++++-- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 77a27376bbb..9bdf0adadf1 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -27,7 +27,9 @@ const NATIVE_MAPPING = { minimumParams: { sizes: [{}] }, }, sponsoredBy: 'sponsored_by', - privacyLink: 'privacy_link' + privacyLink: 'privacy_link', + salePrice: 'saleprice', + displayUrl: 'displayurl' }; const SOURCE = 'pbjs'; @@ -338,10 +340,17 @@ function newBid(serverBid, rtbBid, bidderRequest) { 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: nativeAd.javascript_trackers, + javascriptTrackers: nativeAd.javascript_trackers }; if (nativeAd.main_img) { bid['native'].image = { diff --git a/src/constants.json b/src/constants.json index 4edf120b15f..05de0445c08 100644 --- a/src/constants.json +++ b/src/constants.json @@ -74,8 +74,15 @@ "image": "hb_native_image", "icon": "hb_native_icon", "clickUrl": "hb_native_linkurl", + "displayUrl": "hb_native_displayurl", "cta": "hb_native_cta", - "rating": "hb_native_rating" + "rating": "hb_native_rating", + "address": "hb_native_address", + "downloads": "hb_native_downloads", + "likes": "hb_native_likes", + "phone": "hb_native_phone", + "price": "hb_native_price", + "salePrice": "hb_native_saleprice" }, "S2S" : { "SRC" : "s2s", diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 677b45b95a9..b94e574713c 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -184,7 +184,14 @@ describe('AppNexusAdapter', function () { cta: {required: false}, rating: {required: true}, sponsoredBy: {required: true}, - privacyLink: {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} } } ); @@ -200,7 +207,14 @@ describe('AppNexusAdapter', function () { ctatext: {required: false}, rating: {required: true}, sponsored_by: {required: true}, - privacy_link: {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} }); }); @@ -536,6 +550,7 @@ describe('AppNexusAdapter', function () { response1.tags[0].ads[0].rtb.native = { 'title': 'Native Creative', 'desc': 'Cool description great stuff', + 'desc2': 'Additional body text', 'ctatext': 'Do it', 'sponsored': 'AppNexus', 'icon': { @@ -554,6 +569,15 @@ describe('AppNexusAdapter', function () { 'click_trackers': ['http://nym1-ib.adnxs.com/click'] }, 'impression_trackers': ['http://example.com'], + 'rating': '5', + 'displayurl': 'http://AppNexus.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': 'http://appnexus.com/?url=privacy_url' }; let bidderRequest = { bids: [{ From 90656ee38aaebab21329923f9584992b9b930885 Mon Sep 17 00:00:00 2001 From: deekshithraop Date: Tue, 8 Jan 2019 10:14:10 -0500 Subject: [PATCH 0925/1594] Insert iframe as the last child of Html tag (#3415) * 3413-Insert Iframes for user sync in body * Append Iframe as the last child * Add unit test for insertElement * utls insert element at the top by default * add unit tests for utls insert element * Insert iframe as html last child * revert package.lock changes --- src/utils.js | 29 ++++++++++++++++++----------- test/spec/utils_spec.js | 18 +++++++++++++++--- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/utils.js b/src/utils.js index 0c201b84bab..7f0aef01d22 100644 --- a/src/utils.js +++ b/src/utils.js @@ -549,21 +549,28 @@ var hasOwn = function (objectToCheck, propertyToCheckFor) { } }; -exports.insertElement = function(elm, doc, target) { +/* +* Inserts an element(elm) as targets child, by default as first child +* @param {HTMLElement} elm +* @param {HTMLElement} [doc] +* @param {HTMLElement} [target] +* @param {Boolean} [asLastChildChild] +* @return {HTMLElement} +*/ +exports.insertElement = function(elm, doc, target, asLastChildChild) { doc = doc || document; - let elToAppend; - const head = doc.getElementsByTagName('head'); + let parentEl; if (target) { - elToAppend = doc.getElementsByTagName(target); + parentEl = doc.getElementsByTagName(target); } else { - elToAppend = head; + parentEl = doc.getElementsByTagName('head'); } try { - elToAppend = elToAppend.length ? elToAppend : doc.getElementsByTagName('body'); - if (elToAppend.length) { - elToAppend = elToAppend[0]; - const refChild = head && head[0] === elToAppend ? null : elToAppend.firstChild; - return elToAppend.insertBefore(elm, refChild); + parentEl = parentEl.length ? parentEl : doc.getElementsByTagName('body'); + if (parentEl.length) { + parentEl = parentEl[0]; + let insertBeforeEl = asLastChildChild ? null : parentEl.firstChild; + return parentEl.insertBefore(elm, insertBeforeEl); } } catch (e) {} }; @@ -635,7 +642,7 @@ exports.insertUserSyncIframe = function(url, done) { iframe.addEventListener('load', done); iframe.addEventListener('error', done); } - exports.insertElement(iframe); + exports.insertElement(iframe, document, 'html', true); }; /** diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index ea1ea55cd43..1b4dbc1c477 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -916,11 +916,23 @@ describe('Utils', function () { }); describe('insertElement', function () { - it('returns a node at bottom of head if no target is given', function () { + it('returns a node at the top of the target by default', function () { const toInsert = document.createElement('div'); - const head = document.getElementsByTagName('head')[0]; + const target = document.getElementsByTagName('body')[0]; + const inserted = utils.insertElement(toInsert, document, 'body'); + expect(inserted).to.equal(target.firstChild); + }); + it('returns a node at bottom of target if 4th argument is true', function () { + const toInsert = document.createElement('div'); + const target = document.getElementsByTagName('html')[0]; + const inserted = utils.insertElement(toInsert, document, 'html', true); + expect(inserted).to.equal(target.lastChild); + }); + it('returns a node at top of the head if no target is given', function () { + const toInsert = document.createElement('div'); + const target = document.getElementsByTagName('head')[0]; const inserted = utils.insertElement(toInsert); - expect(inserted).to.equal(head.lastChild); + expect(inserted).to.equal(target.firstChild); }); }); }); From 4b5395427fb206d266f9443992b1e65f5b24c749 Mon Sep 17 00:00:00 2001 From: bretg Date: Wed, 9 Jan 2019 12:03:08 -0500 Subject: [PATCH 0926/1594] changing default currency file (#3414) * changing default currency file * using defaultRate in the case of rate file not returning * Adding date macro * added unit tests for date macro support in currency file url, and small fix to date macro in currency.js * replaced string concatenations with string literals * removed unnecessary parens --- modules/currency.js | 29 ++++++++++++++++--- test/spec/modules/currency_spec.js | 46 ++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/modules/currency.js b/modules/currency.js index f66c33bbed8..fbb7a0cf30d 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -5,7 +5,7 @@ import * as utils from 'src/utils'; import { config } from 'src/config'; import { hooks } from 'src/hook.js'; -const DEFAULT_CURRENCY_RATE_URL = 'https://currency.prebid.org/latest.json'; +const DEFAULT_CURRENCY_RATE_URL = 'https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json?date=$$TODAY$$'; const CURRENCY_RATE_PRECISION = 4; var bidResponseQueue = []; @@ -34,7 +34,7 @@ var defaultRates; * { * rubicon: 'USD' * } - * @param {string} [config.conversionRateFile = 'http://currency.prebid.org/latest.json'] + * @param {string} [config.conversionRateFile = 'URL pointing to conversion file'] * Optional path to a file containing currency conversion data. Prebid.org hosts a file that is used as the default, * if not specified. * @param {object} [config.rates] @@ -60,6 +60,10 @@ export function setConfig(config) { if (typeof config.defaultRates === 'object') { defaultRates = config.defaultRates; + + // set up the default rates to be used if the rate file doesn't get loaded in time + currencyRates.conversions = defaultRates; + currencyRatesLoaded = true; } if (typeof config.adServerCurrency === 'string') { @@ -70,6 +74,25 @@ export function setConfig(config) { utils.logInfo('currency using override conversionRateFile:', config.conversionRateFile); url = config.conversionRateFile; } + + // see if the url contains a date macro + // this is a workaround to the fact that jsdelivr doesn't currently support setting a 24-hour HTTP cache header + // So this is an approach to let the browser cache a copy of the file each day + // We should remove the macro once the CDN support a day-level HTTP cache setting + const macroLocation = url.indexOf('$$TODAY$$'); + if (macroLocation !== -1) { + // get the date to resolve the macro + const d = new Date(); + let month = `${d.getMonth() + 1}`; + let day = `${d.getDate()}`; + if (month.length < 2) month = `0${month}`; + if (day.length < 2) day = `0${day}`; + const todaysDate = `${d.getFullYear()}${month}${day}`; + + // replace $$TODAY$$ with todaysDate + url = `${url.substring(0, macroLocation)}${todaysDate}${url.substring(macroLocation + 9, url.length)}`; + } + initCurrency(url); } else { // currency support is disabled, setting defaults @@ -84,8 +107,6 @@ config.getConfig('currency', config => setConfig(config.currency)); function errorSettingsRates(msg) { if (defaultRates) { - currencyRates.conversions = defaultRates; - currencyRatesLoaded = true; utils.logWarn(msg); utils.logWarn('Currency failed loading rates, falling back to currency.defaultRates'); } else { diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index e96b15d11e9..64c966bdf18 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -17,6 +17,8 @@ var expect = require('chai').expect; describe('currency', function () { let fakeCurrencyFileServer; + let sandbox; + let clock; let fn = sinon.spy(); let hookFn = createHook('asyncSeries', fn, 'addBidResponse'); @@ -30,6 +32,16 @@ describe('currency', function () { }); describe('setConfig', function () { + beforeEach(function() { + sandbox = sinon.sandbox.create(); + clock = sinon.useFakeTimers(1047010195974); + }); + + afterEach(function () { + sandbox.restore(); + clock.restore(); + }); + it('results in currencySupportEnabled = false when currency not configured', function () { setConfig({}); expect(currencySupportEnabled).to.equal(false); @@ -42,6 +54,40 @@ describe('currency', function () { expect(currencyRates.dataAsOf).to.equal('2017-04-25'); expect(currencySupportEnabled).to.equal(true); }); + + it('date macro token $$TODAY$$ is replaced by current date (formatted as yyyymmdd)', function () { + // RESET to request currency file (specifically url value for this test) + setConfig({ 'adServerCurrency': undefined }); + + // date macro should replace $$TODAY$$ with date when DEFAULT_CURRENCY_RATE_URL is used + setConfig({ 'adServerCurrency': 'JPY' }); + fakeCurrencyFileServer.respond(); + expect(fakeCurrencyFileServer.requests[0].url).to.equal('https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json?date=20030306'); + + // date macro should not modify 'conversionRateFile' if TOKEN is not found + setConfig({ + 'adServerCurrency': 'JPY', + 'conversionRateFile': 'http://test.net/currency.json?date=foobar' + }); + fakeCurrencyFileServer.respond(); + expect(fakeCurrencyFileServer.requests[1].url).to.equal('http://test.net/currency.json?date=foobar'); + + // date macro should replace $$TODAY$$ with date for 'conversionRateFile' is configured + setConfig({ + 'adServerCurrency': 'JPY', + 'conversionRateFile': 'http://test.net/currency.json?date=$$TODAY$$' + }); + fakeCurrencyFileServer.respond(); + expect(fakeCurrencyFileServer.requests[2].url).to.equal('http://test.net/currency.json?date=20030306'); + + // MULTIPLE TOKENS used in a url is not supported. Only the TOKEN at left-most position is REPLACED + setConfig({ + 'adServerCurrency': 'JPY', + 'conversionRateFile': 'http://test.net/$$TODAY$$/currency.json?date=$$TODAY$$' + }); + fakeCurrencyFileServer.respond(); + expect(fakeCurrencyFileServer.requests[3].url).to.equal('http://test.net/20030306/currency.json?date=$$TODAY$$'); + }); }); describe('bidder override', function () { From cdcb097ef90d99081f31f5e39988f183ae477fb3 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Wed, 9 Jan 2019 12:17:58 -0500 Subject: [PATCH 0927/1594] 1.37.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b592fff1453..87d3d175e9a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.37.0-pre", + "version": "1.37.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4c664e7d84d7b56e6ef19a9f18af0fe240b664c0 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Wed, 9 Jan 2019 15:25:01 -0500 Subject: [PATCH 0928/1594] 1.38-pre --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87d3d175e9a..8ecbfef16f8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.37.0", + "version": "1.38.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From c07e60d06b15c07418244e65da525afb97ed3722 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Wed, 9 Jan 2019 17:17:04 -0500 Subject: [PATCH 0929/1594] Sonobi - Added support for getting the digitrust id (#3422) * added suppor for grabbing digitrust id off the window * added digitrust support --- modules/sonobiBidAdapter.js | 22 ++++++++++++ test/spec/modules/sonobiBidAdapter_spec.js | 41 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index ce925eacc51..eb95fcb050d 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -6,6 +6,7 @@ import { config } from '../src/config'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; const PAGEVIEW_ID = generateUUID(); +const SONOBI_DIGITRUST_KEY = 'fhnS5drwmH'; export const spec = { code: BIDDER_CODE, @@ -75,6 +76,13 @@ export const spec = { } } + const digitrust = _getDigiTrustObject(SONOBI_DIGITRUST_KEY); + + if (digitrust) { + payload.digid = digitrust.id; + payload.digkeyv = digitrust.keyv; + } + // If there is no key_maker data, then don't make the request. if (isEmpty(data)) { return null; @@ -225,4 +233,18 @@ export function _getPlatform(context = window) { return 'desktop'; } +// https://github.com/digi-trust/dt-cdn/wiki/Integration-Guide +function _getDigiTrustObject(key) { + function getDigiTrustId() { + let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: key})); + return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; + } + let digiTrustId = getDigiTrustId(); + // Verify there is an ID and this user has not opted out + if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { + return null; + } + return digiTrustId; +} + registerBidder(spec); diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 463067ffa8a..65ad5b352ff 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -143,6 +143,47 @@ describe('SonobiBidAdapter', function () { 'stack': ['http://example.com'] } }; + it('should include the digitrust id and keyv', () => { + window.DigiTrust = { + getUser: function () { + } + }; + let sandbox = sinon.sandbox.create(); + sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => + ({ + success: true, + identity: { + id: 'Vb0YJIxTMJV4W0GHRdJ3MwyiOVYJjYEgc2QYdBSG', + keyv: 4, + version: 2, + privacy: {} + } + }) + ); + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.data.digid).to.equal('Vb0YJIxTMJV4W0GHRdJ3MwyiOVYJjYEgc2QYdBSG'); + expect(bidRequests.data.digkeyv).to.equal(4); + sandbox.restore(); + delete window.DigiTrust; + }); + + it('should not include the digitrust id and keyv', () => { + window.DigiTrust = { + getUser: function () { + } + }; + let sandbox = sinon.sandbox.create(); + sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => + ({ + success: false + }) + ); + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.data.digid).to.be.undefined; + expect(bidRequests.data.digkeyv).to.be.undefined; + sandbox.restore(); + delete window.DigiTrust; + }) it('should return a properly formatted request', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests) From 7904b4f0a4e36f8155bcf69c090e717ce958cfa5 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Thu, 10 Jan 2019 21:36:58 +0200 Subject: [PATCH 0930/1594] Update gambid aliases (#3410) * Update the Gamoshi Gambid adapter to simply the Gamoshi adapter This is a minor branding change to highlight the Gamoshi brand name. The biddercode "gambid" is still retained in the adapter aliases array. * update whitelabel * Add test that checks support for outstream renderers * Update testing and page ref * Modify bidder's url resolving * Fix lint issue with bidder's url resolving --- ...mbidBidAdapter.js => gamoshiBidAdapter.js} | 119 ++--- ...mbidBidAdapter.md => gamoshiBidAdapter.md} | 16 +- test/spec/modules/gambidBidAdapter_spec.js | 338 --------------- test/spec/modules/gamoshiBidAdapter_spec.js | 406 ++++++++++++++++++ 4 files changed, 476 insertions(+), 403 deletions(-) rename modules/{gambidBidAdapter.js => gamoshiBidAdapter.js} (58%) rename modules/{gambidBidAdapter.md => gamoshiBidAdapter.md} (78%) delete mode 100644 test/spec/modules/gambidBidAdapter_spec.js create mode 100644 test/spec/modules/gamoshiBidAdapter_spec.js diff --git a/modules/gambidBidAdapter.js b/modules/gamoshiBidAdapter.js similarity index 58% rename from modules/gambidBidAdapter.js rename to modules/gamoshiBidAdapter.js index f7026f9c76f..59ff14eb5f9 100644 --- a/modules/gambidBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -1,65 +1,70 @@ import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { config } from 'src/config'; -import { Renderer } from '../src/Renderer'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import {config} from 'src/config'; +import {Renderer} from '../src/Renderer'; -function getTopFrame() { - try { - return window.top === window ? 1 : 0; - } catch (e) { +export const helper = { + + getTopFrame: function () { + try { + return window.top === window ? 1 : 0; + } catch (e) { + } return 0; - } -} + }, -function startsWith(str, search) { - return str.substr(0, search.length) === search; -} + startsWith: function (str, search) { + return str.substr(0, search.length) === search; + }, -function getTopWindowDomain() { - const url = utils.getTopWindowUrl(); - const domainStart = url.indexOf('://') + '://'.length; - return url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)); -} + getTopWindowDomain: function (url) { + const domainStart = url.indexOf('://') + '://'.length; + return url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)); + }, -function getTopWindowReferer() { - try { - return window.top.document.referrer; - } catch (e) { - utils.logMessage('Failed obtaining top window\'s referrer: ', e); + getTopWindowReferer: function () { try { - return window.document.referrer; + return window.top.document.referrer; } catch (e) { - utils.logMessage('Failed obtaining current window\'s referrer: ', e); - return ''; + utils.logMessage('Failed obtaining top window\'s referrer: ', e); + try { + return window.document.referrer; + } catch (e) { + utils.logMessage('Failed obtaining current window\'s referrer: ', e); + } } + return ''; } } export const spec = { - code: 'gambid', - aliases: [], - supportedMediaTypes: [ 'banner', 'video' ], + code: 'gamoshi', + aliases: ['gambid', 'cleanmedia'], + supportedMediaTypes: ['banner', 'video'], - isBidRequestValid: function(bid) { + isBidRequestValid: function (bid) { return !!bid.params.supplyPartnerId && typeof bid.params.supplyPartnerId === 'string' && - (typeof bid.params[ 'rtbEndpoint' ] === 'undefined' || typeof bid.params[ 'rtbEndpoint' ] === 'string') && - (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && - (typeof bid.params[ 'adpos' ] === 'undefined' || typeof bid.params[ 'adpos' ] === 'number') && - (typeof bid.params[ 'protocols' ] === 'undefined' || Array.isArray(bid.params[ 'protocols' ])) && - (typeof bid.params.instl === 'undefined' || bid.params.instl === 0 || bid.params.instl === 1); + (typeof bid.params['rtbEndpoint'] === 'undefined' || typeof bid.params['rtbEndpoint'] === 'string') && + (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && + (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number') && + (typeof bid.params['protocols'] === 'undefined' || Array.isArray(bid.params['protocols'])) && + (typeof bid.params.instl === 'undefined' || bid.params.instl === 0 || bid.params.instl === 1); }, - buildRequests: function(validBidRequests, bidderRequest) { + buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { - const { adUnitCode, auctionId, mediaTypes, params, sizes, transactionId } = bidRequest; - const baseEndpoint = params[ 'rtbEndpoint' ] || 'https://rtb.gambid.io'; + const {adUnitCode, auctionId, mediaTypes, params, sizes, transactionId} = bidRequest; + const baseEndpoint = params['rtbEndpoint'] || 'https://rtb.gamoshi.io'; const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + (params.query ? '&' + params.query : ''); + let referer = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; + let url = config.getConfig('pageUrl') || referer || utils.getTopWindowUrl(); + const rtbBidRequest = { 'id': auctionId, 'site': { - 'domain': getTopWindowDomain(), - 'page': config.getConfig('pageUrl') || utils.getTopWindowUrl(), - 'ref': getTopWindowReferer() + 'domain': helper.getTopWindowDomain(url), + 'page': url, + 'ref': helper.getTopWindowReferer() }, 'device': { 'ua': navigator.userAgent @@ -80,33 +85,33 @@ export const spec = { 'tagid': adUnitCode, 'bidfloor': params.bidfloor || 0, 'bidfloorcur': 'USD', - 'secure': startsWith(utils.getTopWindowUrl().toLowerCase(), 'http://') ? 0 : 1 + 'secure': helper.startsWith(utils.getTopWindowUrl().toLowerCase(), 'http://') ? 0 : 1 }; if (!mediaTypes || mediaTypes.banner) { imp.banner = { - w: sizes.length ? sizes[ 0 ][ 0 ] : 300, - h: sizes.length ? sizes[ 0 ][ 1 ] : 250, + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, pos: params.pos || 0, - topframe: getTopFrame() + topframe: helper.getTopFrame() }; } else if (mediaTypes.video) { imp.video = { - w: sizes.length ? sizes[ 0 ][ 0 ] : 300, - h: sizes.length ? sizes[ 0 ][ 1 ] : 250, + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, protocols: params.protocols || [1, 2, 3, 4, 5, 6], pos: params.pos || 0, - topframe: getTopFrame() + topframe: helper.getTopFrame() }; } else { return; } rtbBidRequest.imp.push(imp); - return { method: 'POST', url: rtbEndpoint, data: rtbBidRequest, bidRequest }; + return {method: 'POST', url: rtbEndpoint, data: rtbBidRequest, bidRequest}; }); }, - interpretResponse: function(serverResponse, bidRequest) { + interpretResponse: function (serverResponse, bidRequest) { const response = serverResponse && serverResponse.body; if (!response) { utils.logError('empty response'); @@ -127,7 +132,7 @@ export const spec = { currency: bid.cur || response.cur }; if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { - outBids.push(Object.assign({}, outBid, { mediaType: 'banner', ad: bid.adm })); + outBids.push(Object.assign({}, outBid, {mediaType: 'banner', ad: bid.adm})); } else if (bidRequest.bidRequest.mediaTypes.video) { const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); outBids.push(Object.assign({}, outBid, { @@ -141,27 +146,27 @@ export const spec = { return outBids; }, - getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + getUserSyncs: function (syncOptions, serverResponses, gdprConsent) { const syncs = []; const gdprApplies = gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : false; const suffix = gdprApplies ? 'gc=' + encodeURIComponent(gdprConsent.consentString) : 'gc=missing'; serverResponses.forEach(resp => { if (resp.body) { const bidResponse = resp.body; - if (bidResponse.ext && Array.isArray(bidResponse.ext[ 'utrk' ])) { - bidResponse.ext[ 'utrk' ].forEach(pixel => { + if (bidResponse.ext && Array.isArray(bidResponse.ext['utrk'])) { + bidResponse.ext['utrk'].forEach(pixel => { const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); - return syncs.push({ type: pixel.type, url }); + return syncs.push({type: pixel.type, url}); }); } if (Array.isArray(bidResponse.seatbid)) { bidResponse.seatbid.forEach(seatBid => { if (Array.isArray(seatBid.bid)) { seatBid.bid.forEach(bid => { - if (bid.ext && Array.isArray(bid.ext[ 'utrk' ])) { - bid.ext[ 'utrk' ].forEach(pixel => { + if (bid.ext && Array.isArray(bid.ext['utrk'])) { + bid.ext['utrk'].forEach(pixel => { const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); - return syncs.push({ type: pixel.type, url }); + return syncs.push({type: pixel.type, url}); }); } }); diff --git a/modules/gambidBidAdapter.md b/modules/gamoshiBidAdapter.md similarity index 78% rename from modules/gambidBidAdapter.md rename to modules/gamoshiBidAdapter.md index b34d05070a9..f88248ef668 100644 --- a/modules/gambidBidAdapter.md +++ b/modules/gamoshiBidAdapter.md @@ -1,16 +1,16 @@ # Overview ``` -Module Name: Gamoshi's Gambid Bid Adapter +Module Name: Gamoshi Bid Adapter Module Type: Bidder Adapter -Maintainer: arik@gamoshi.com +Maintainer: moses@gamoshi.com ``` # Description -Connects to Gamoshi's Gambid platform & exchange for bids. +Connects to Gamoshi's Programmatic advertising platform as a service. -Gambid bid adapter supports Banner & Outstream Video. The *only* required parameter (in the `params` section) is the `supplyPartnerId` parameter. +Gamoshi bid adapter supports Banner & Outstream Video. The *only* required parameter (in the `params` section) is the `supplyPartnerId` parameter. # Test Parameters ``` @@ -21,10 +21,10 @@ var adUnits = [ code: 'banner-div', sizes: [[300, 250]], bids: [{ - bidder: 'gambid', + bidder: 'gamoshi', params: { - // ID of the supply partner you created in the Gambid dashboard + // ID of the supply partner you created in the Gamoshi dashboard supplyPartnerId: '1253', // OPTIONAL: if you have a whitelabel account on Gamoshi, specify it here @@ -55,10 +55,10 @@ var adUnits = [ } }, bids: [ { - bidder: 'gambid', + bidder: 'gamoshi', params: { - // ID of the supply partner you created in the Gambid dashboard + // ID of the supply partner you created in the dashboard supplyPartnerId: '1254', // OPTIONAL: if you have a whitelabel account on Gamoshi, specify it here diff --git a/test/spec/modules/gambidBidAdapter_spec.js b/test/spec/modules/gambidBidAdapter_spec.js deleted file mode 100644 index 06118f7f7d8..00000000000 --- a/test/spec/modules/gambidBidAdapter_spec.js +++ /dev/null @@ -1,338 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/gambidBidAdapter'; -import * as utils from 'src/utils'; - -const supplyPartnerId = '123'; - -describe('GambidAdapter', function () { - describe('isBidRequestValid', function () { - it('should validate supply-partner ID', function () { - expect(spec.isBidRequestValid({ params: {} })).to.equal(false); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: 123 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); - }); - it('should validate RTB endpoint', function () { - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // RTB endpoint has a default - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', rtbEndpoint: 123 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', rtbEndpoint: 'https://some.url.com' } })).to.equal(true); - }); - it('should validate bid floor', function () { - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // bidfloor has a default - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', bidfloor: '123' } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', bidfloor: 0.1 } })).to.equal(true); - }); - it('should validate adpos', function () { - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // adpos has a default - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', adpos: '123' } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', adpos: 0.1 } })).to.equal(true); - }); - it('should validate instl', function () { - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // adpos has a default - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: '123' } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: -1 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: 0 } })).to.equal(true); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: 1 } })).to.equal(true); - expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: 2 } })).to.equal(false); - }); - }); - describe('buildRequests', function () { - const bidRequest = { - 'adUnitCode': 'adunit-code', - 'auctionId': '1d1a030790a475', - 'mediaTypes': { - banner: {} - }, - 'params': { - 'supplyPartnerId': supplyPartnerId - }, - 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], - 'transactionId': 'a123456789' - }; - - it('returns an array', function () { - let response; - - response = spec.buildRequests([]); - expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(0); - - response = spec.buildRequests([ bidRequest ]); - expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(1); - - const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'a' }); - const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'b' }); - response = spec.buildRequests([adUnit1, adUnit2]); - expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); - }); - - it('targets correct endpoint', function () { - let response; - - response = spec.buildRequests([ bidRequest ])[ 0 ]; - expect(response.method).to.equal('POST'); - expect(response.url).to.match(new RegExp(`^https://rtb\\.gambid\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); - expect(response.data.id).to.equal(bidRequest.auctionId); - - const bidRequestWithEndpoint = utils.deepClone(bidRequest); - bidRequestWithEndpoint.params.rtbEndpoint = 'https://rtb2.gambid.io/a12'; - response = spec.buildRequests([ bidRequestWithEndpoint ])[ 0 ]; - expect(response.url).to.match(new RegExp(`^https://rtb2\\.gambid\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); - }); - - it('builds request correctly', function () { - let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); - - let response; - response = spec.buildRequests([ bidRequest ])[ 0 ]; - expect(response.data.site.domain).to.equal('www.test.com'); - expect(response.data.site.page).to.equal('http://www.test.com/page.html'); - expect(response.data.site.ref).to.equal(''); - expect(response.data.imp.length).to.equal(1); - expect(response.data.imp[ 0 ].id).to.equal(bidRequest.transactionId); - expect(response.data.imp[ 0 ].instl).to.equal(0); - expect(response.data.imp[ 0 ].tagid).to.equal(bidRequest.adUnitCode); - expect(response.data.imp[ 0 ].bidfloor).to.equal(0); - expect(response.data.imp[ 0 ].bidfloorcur).to.equal('USD'); - - const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); - bidRequestWithInstlEquals1.params.instl = 1; - response = spec.buildRequests([ bidRequestWithInstlEquals1 ])[ 0 ]; - expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals1.params.instl); - - const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); - bidRequestWithInstlEquals0.params.instl = 1; - response = spec.buildRequests([ bidRequestWithInstlEquals0 ])[ 0 ]; - expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals0.params.instl); - - const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); - bidRequestWithBidfloorEquals1.params.bidfloor = 1; - response = spec.buildRequests([ bidRequestWithBidfloorEquals1 ])[ 0 ]; - expect(response.data.imp[ 0 ].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); - - stub.restore(); - }); - - it('builds request banner object correctly', function () { - let response; - - const bidRequestWithBanner = utils.deepClone(bidRequest); - bidRequestWithBanner.mediaTypes = { - banner: { - sizes: [ [ 300, 250 ], [ 120, 600 ] ] - } - }; - - response = spec.buildRequests([ bidRequestWithBanner ])[ 0 ]; - expect(response.data.imp[ 0 ].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[ 0 ][ 0 ]); - expect(response.data.imp[ 0 ].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[ 0 ][ 1 ]); - expect(response.data.imp[ 0 ].banner.pos).to.equal(0); - expect(response.data.imp[ 0 ].banner.topframe).to.equal(0); - - const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); - bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; - expect(response.data.imp[ 0 ].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); - }); - - it('builds request video object correctly', function () { - let response; - - const bidRequestWithVideo = utils.deepClone(bidRequest); - bidRequestWithVideo.mediaTypes = { - video: { - sizes: [ [ 300, 250 ], [ 120, 600 ] ] - } - }; - - response = spec.buildRequests([ bidRequestWithVideo ])[ 0 ]; - expect(response.data.imp[ 0 ].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[ 0 ][ 0 ]); - expect(response.data.imp[ 0 ].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[ 0 ][ 1 ]); - expect(response.data.imp[ 0 ].video.pos).to.equal(0); - expect(response.data.imp[ 0 ].video.topframe).to.equal(0); - - const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); - bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; - expect(response.data.imp[ 0 ].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); - }); - }); - describe('interpretResponse', function () { - const bannerBidRequest = { - 'adUnitCode': 'adunit-code', - 'auctionId': '1d1a030790a475', - 'mediaTypes': { - banner: {} - }, - 'params': { - 'supplyPartnerId': supplyPartnerId - }, - 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], - 'transactionId': 'a123456789', - 'bidId': '111' - }; - const videoBidRequest = { - 'adUnitCode': 'adunit-code', - 'auctionId': '1d1a030790a475', - 'mediaTypes': { - video: {} - }, - 'params': { - 'supplyPartnerId': supplyPartnerId - }, - 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], - 'transactionId': 'a123456789', - 'bidId': '111' - }; - const rtbResponse = { - 'id': 'imp_5b05b9fde4b09084267a556f', - 'bidid': 'imp_5b05b9fde4b09084267a556f', - 'cur': 'USD', - 'ext': { - 'utrk': [ - { 'type': 'iframe', 'url': '//p.gsh.io/user/sync/1' }, - { 'type': 'image', 'url': '//p.gsh.io/user/sync/2' } - ] - }, - 'seatbid': [ - { - 'seat': 'seat1', - 'group': 0, - 'bid': [ - { - 'id': '0', - 'impid': '1', - 'price': 2.016, - 'adid': '579ef31bfa788b9d2000d562', - 'nurl': 'https://p.gsh.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', - 'adm': ' ', - 'adomain': [ 'aaa.com' ], - 'cid': '579ef268fa788b9d2000d55c', - 'crid': '579ef31bfa788b9d2000d562', - 'attr': [], - 'h': 600, - 'w': 120, - 'ext': { - 'vast_url': 'http://my.vast.com', - 'utrk': [ - { 'type': 'iframe', 'url': '//p.partner1.io/user/sync/1' } - ] - } - } - ] - }, - { - 'seat': 'seat2', - 'group': 0, - 'bid': [ - { - 'id': '1', - 'impid': '1', - 'price': 3, - 'adid': '542jlhdfd2112jnjf3x', - 'nurl': 'https://p.gsh.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', - 'adm': ' ', - 'adomain': [ 'bbb.com' ], - 'cid': 'fgdlwjh2498ydjhg1', - 'crid': 'kjh34297ydh2133d', - 'attr': [], - 'h': 250, - 'w': 300, - 'ext': { - 'utrk': [ - { 'type': 'image', 'url': '//p.partner2.io/user/sync/1' } - ] - } - } - ] - } - ] - }; - it('returns an empty array on missing response', function () { - let response; - - response = spec.interpretResponse(undefined, { bidRequest: bannerBidRequest }); - expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(0); - - response = spec.interpretResponse({}, { bidRequest: bannerBidRequest }); - expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(0); - }); - it('aggregates banner bids from all seat bids', function () { - const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: bannerBidRequest }); - expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); - - const ad0 = response[ 0 ], ad1 = response[ 1 ]; - expect(ad0.requestId).to.equal(bannerBidRequest.bidId); - expect(ad0.cpm).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].price); - expect(ad0.width).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].w); - expect(ad0.height).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].h); - expect(ad0.ttl).to.equal(60 * 10); - expect(ad0.creativeId).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].crid); - expect(ad0.netRevenue).to.equal(true); - expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); - expect(ad0.ad).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); - expect(ad0.vastXml).to.be.an('undefined'); - - expect(ad1.requestId).to.equal(bannerBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].h); - expect(ad1.ttl).to.equal(60 * 10); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); - expect(ad1.vastXml).to.be.an('undefined'); - - // expect(ad1.ad).to.be.an('undefined'); - // expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); - }); - it('aggregates video bids from all seat bids', function () { - const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: videoBidRequest }); - expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); - - const ad0 = response[ 0 ], ad1 = response[ 1 ]; - expect(ad0.requestId).to.equal(videoBidRequest.bidId); - expect(ad0.cpm).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].price); - expect(ad0.width).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].w); - expect(ad0.height).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].h); - expect(ad0.ttl).to.equal(60 * 10); - expect(ad0.creativeId).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].crid); - expect(ad0.netRevenue).to.equal(true); - expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); - expect(ad0.ad).to.be.an('undefined'); - expect(ad0.vastXml).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); - expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.vast_url); - - expect(ad1.requestId).to.equal(videoBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].h); - expect(ad1.ttl).to.equal(60 * 10); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.be.an('undefined'); - expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); - expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.vast_url); - }); - it('aggregates user-sync pixels', function () { - const response = spec.getUserSyncs({}, [ { body: rtbResponse } ]); - expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(4); - expect(response[ 0 ].type).to.equal(rtbResponse.ext.utrk[ 0 ].type); - expect(response[ 0 ].url).to.equal(rtbResponse.ext.utrk[ 0 ].url + '?gc=missing'); - expect(response[ 1 ].type).to.equal(rtbResponse.ext.utrk[ 1 ].type); - expect(response[ 1 ].url).to.equal(rtbResponse.ext.utrk[ 1 ].url + '?gc=missing'); - expect(response[ 2 ].type).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.utrk[ 0 ].type); - expect(response[ 2 ].url).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.utrk[ 0 ].url + '?gc=missing'); - expect(response[ 3 ].type).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.utrk[ 0 ].type); - expect(response[ 3 ].url).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.utrk[ 0 ].url + '?gc=missing'); - }); - }); -}); diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js new file mode 100644 index 00000000000..26d67b70f78 --- /dev/null +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -0,0 +1,406 @@ +import {expect} from 'chai'; +import {spec} from 'modules/gamoshiBidAdapter'; +import {helper} from 'modules/gamoshiBidAdapter'; +import * as utils from 'src/utils'; +import {newBidder} from '../../../src/adapters/bidderFactory'; +import {deepClone} from 'src/utils'; +const supplyPartnerId = '123'; +const adapter = newBidder(spec); +describe('GamoshiAdapter', function () { + describe('Get top Frame', function () { + it('check if you are in the top frame', function () { + expect(helper.getTopFrame()).to.equal(0); + }); + it('verify domain parsing', function () { + expect(helper.getTopWindowDomain('http://www.domain.com')).to.equal('www.domain.com'); + }); + }); + describe('Is String start with search ', function () { + it('check if a string started with', function () { + expect(helper.startsWith('gamoshi.com', 'gamo')).to.equal(true); + }); + }); + + 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 validate supply-partner ID', function () { + expect(spec.isBidRequestValid({params: {}})).to.equal(false); + expect(spec.isBidRequestValid({params: {supplyPartnerId: 123}})).to.equal(false); + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); + }); + + it('should validate RTB endpoint', function () { + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); // RTB endpoint has a default + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', rtbEndpoint: 123}})).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + supplyPartnerId: '123', + rtbEndpoint: 'https://some.url.com' + } + })).to.equal(true); + }); + + it('should validate bid floor', function () { + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); // bidfloor has a default + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', bidfloor: '123'}})).to.equal(false); + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', bidfloor: 0.1}})).to.equal(true); + }); + + it('should validate adpos', function () { + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); // adpos has a default + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', adpos: '123'}})).to.equal(false); + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', adpos: 0.1}})).to.equal(true); + }); + + it('should validate instl', function () { + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); // adpos has a default + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', instl: '123'}})).to.equal(false); + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', instl: -1}})).to.equal(false); + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', instl: 0}})).to.equal(true); + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', instl: 1}})).to.equal(true); + expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', instl: 2}})).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const bidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': '1d1a030790a475', + 'mediaTypes': { + banner: {} + }, + 'params': { + 'supplyPartnerId': supplyPartnerId + }, + 'sizes': [[300, 250], [300, 600]], + 'transactionId': 'a123456789', + refererInfo: {referer: 'http://examplereferer.com'} + }; + it('returns an array', function () { + let response; + response = spec.buildRequests([]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + response = spec.buildRequests([bidRequest]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(1); + const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'a'}); + const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'b'}); + response = spec.buildRequests([adUnit1, adUnit2]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + }); + + it('targets correct endpoint', function () { + let response; + response = spec.buildRequests([bidRequest])[0]; + expect(response.method).to.equal('POST'); + expect(response.url).to.match(new RegExp(`^https://rtb\\.gamoshi\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); + expect(response.data.id).to.equal(bidRequest.auctionId); + const bidRequestWithEndpoint = utils.deepClone(bidRequest); + bidRequestWithEndpoint.params.rtbEndpoint = 'https://rtb2.gamoshi.io/a12'; + response = spec.buildRequests([bidRequestWithEndpoint])[0]; + expect(response.url).to.match(new RegExp(`^https://rtb2\\.gamoshi\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); + }); + + it('builds request correctly', function () { + let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); + let response; + response = spec.buildRequests([bidRequest])[0]; + expect(response.data.site.domain).to.equal('www.test.com'); + expect(response.data.site.page).to.equal('http://www.test.com/page.html'); + expect(response.data.site.ref).to.equal(''); + expect(response.data.imp.length).to.equal(1); + expect(response.data.imp[0].id).to.equal(bidRequest.transactionId); + expect(response.data.imp[0].instl).to.equal(0); + expect(response.data.imp[0].tagid).to.equal(bidRequest.adUnitCode); + expect(response.data.imp[0].bidfloor).to.equal(0); + expect(response.data.imp[0].bidfloorcur).to.equal('USD'); + const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); + bidRequestWithInstlEquals1.params.instl = 1; + response = spec.buildRequests([bidRequestWithInstlEquals1])[0]; + expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals1.params.instl); + const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); + bidRequestWithInstlEquals0.params.instl = 1; + response = spec.buildRequests([bidRequestWithInstlEquals0])[0]; + expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals0.params.instl); + const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); + bidRequestWithBidfloorEquals1.params.bidfloor = 1; + response = spec.buildRequests([bidRequestWithBidfloorEquals1])[0]; + expect(response.data.imp[0].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); + stub.restore(); + }); + + it('builds request banner object correctly', function () { + let response; + const bidRequestWithBanner = utils.deepClone(bidRequest); + bidRequestWithBanner.mediaTypes = { + banner: { + sizes: [[300, 250], [120, 600]] + } + }; + response = spec.buildRequests([bidRequestWithBanner])[0]; + expect(response.data.imp[0].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][0]); + expect(response.data.imp[0].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][1]); + expect(response.data.imp[0].banner.pos).to.equal(0); + expect(response.data.imp[0].banner.topframe).to.equal(0); + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); + bidRequestWithPosEquals1.params.pos = 1; + response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + expect(response.data.imp[0].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); + }); + + it('builds request video object correctly', function () { + let response; + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes = { + video: { + sizes: [[300, 250], [120, 600]] + } + }; + response = spec.buildRequests([bidRequestWithVideo])[0]; + expect(response.data.imp[0].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][0]); + expect(response.data.imp[0].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][1]); + expect(response.data.imp[0].video.pos).to.equal(0); + expect(response.data.imp[0].video.topframe).to.equal(0); + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.params.pos = 1; + response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + expect(response.data.imp[0].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); + }); + }); + + describe('interpretResponse', function () { + const bannerBidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': '1d1a030790a475', + 'mediaTypes': { + banner: {} + }, + 'params': { + 'supplyPartnerId': supplyPartnerId + }, + 'sizes': [[300, 250], [300, 600]], + 'transactionId': 'a123456789', + 'bidId': '111', + refererInfo: { referer: 'http://examplereferer.com' } + }; + + const videoBidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': '1d1a030790a475', + 'mediaTypes': { + video: {} + }, + 'params': { + 'supplyPartnerId': supplyPartnerId + }, + 'sizes': [[300, 250], [300, 600]], + 'transactionId': 'a123456789', + 'bidId': '111', + refererInfo: { referer: 'http://examplereferer.com' } + }; + + const rtbResponse = { + 'id': 'imp_5b05b9fde4b09084267a556f', + 'bidid': 'imp_5b05b9fde4b09084267a556f', + 'cur': 'USD', + 'ext': { + 'utrk': [ + {'type': 'iframe', 'url': '//rtb.gamoshi.io/user/sync/1'}, + {'type': 'image', 'url': '//rtb.gamoshi.io/user/sync/2'} + ] + }, + 'seatbid': [ + { + 'seat': 'seat1', + 'group': 0, + 'bid': [ + { + 'id': '0', + 'impid': '1', + 'price': 2.016, + 'adid': '579ef31bfa788b9d2000d562', + 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', + 'adm': ' ', + 'adomain': ['aaa.com'], + 'cid': '579ef268fa788b9d2000d55c', + 'crid': '579ef31bfa788b9d2000d562', + 'attr': [], + 'h': 600, + 'w': 120, + 'ext': { + 'vast_url': 'http://my.vast.com', + 'utrk': [ + {'type': 'iframe', 'url': '//p.partner1.io/user/sync/1'} + ] + } + } + ] + }, + { + 'seat': 'seat2', + 'group': 0, + 'bid': [ + { + 'id': '1', + 'impid': '1', + 'price': 3, + 'adid': '542jlhdfd2112jnjf3x', + 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', + 'adm': ' ', + 'adomain': ['bbb.com'], + 'cid': 'fgdlwjh2498ydjhg1', + 'crid': 'kjh34297ydh2133d', + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'utrk': [ + {'type': 'image', 'url': '//p.partner2.io/user/sync/1'} + ] + } + } + ] + } + ] + }; + + it('returns an empty array on missing response', function () { + let response; + + response = spec.interpretResponse(undefined, {bidRequest: bannerBidRequest}); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + + response = spec.interpretResponse({}, {bidRequest: bannerBidRequest}); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + }); + + it('aggregates banner bids from all seat bids', function () { + const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: bannerBidRequest}); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + + const ad0 = response[0], ad1 = response[1]; + expect(ad0.requestId).to.equal(bannerBidRequest.bidId); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[0].bid[0].h); + expect(ad0.ttl).to.equal(60 * 10); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[0].bid[0].crid); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.currency).to.equal(rtbResponse.seatbid[0].bid[0].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.equal(rtbResponse.seatbid[0].bid[0].adm); + expect(ad0.vastXml).to.be.an('undefined'); + + expect(ad1.requestId).to.equal(bannerBidRequest.bidId); + expect(ad1.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); + expect(ad1.width).to.equal(rtbResponse.seatbid[1].bid[0].w); + expect(ad1.height).to.equal(rtbResponse.seatbid[1].bid[0].h); + expect(ad1.ttl).to.equal(60 * 10); + expect(ad1.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); + expect(ad1.netRevenue).to.equal(true); + expect(ad1.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); + expect(ad1.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); + expect(ad1.vastXml).to.be.an('undefined'); + }); + + it('aggregates video bids from all seat bids', function () { + const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: videoBidRequest}); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + + const ad0 = response[0], ad1 = response[1]; + expect(ad0.requestId).to.equal(videoBidRequest.bidId); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[0].bid[0].h); + expect(ad0.ttl).to.equal(60 * 10); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[0].bid[0].crid); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.currency).to.equal(rtbResponse.seatbid[0].bid[0].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.be.an('undefined'); + expect(ad0.vastXml).to.equal(rtbResponse.seatbid[0].bid[0].adm); + expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[0].bid[0].ext.vast_url); + + expect(ad1.requestId).to.equal(videoBidRequest.bidId); + expect(ad1.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); + expect(ad1.width).to.equal(rtbResponse.seatbid[1].bid[0].w); + expect(ad1.height).to.equal(rtbResponse.seatbid[1].bid[0].h); + expect(ad1.ttl).to.equal(60 * 10); + expect(ad1.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); + expect(ad1.netRevenue).to.equal(true); + expect(ad1.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); + expect(ad1.ad).to.be.an('undefined'); + expect(ad1.vastXml).to.equal(rtbResponse.seatbid[1].bid[0].adm); + expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[1].bid[0].ext.vast_url); + }); + + it('aggregates user-sync pixels', function () { + const response = spec.getUserSyncs({}, [{body: rtbResponse}]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(4); + expect(response[0].type).to.equal(rtbResponse.ext.utrk[0].type); + expect(response[0].url).to.equal(rtbResponse.ext.utrk[0].url + '?gc=missing'); + expect(response[1].type).to.equal(rtbResponse.ext.utrk[1].type); + expect(response[1].url).to.equal(rtbResponse.ext.utrk[1].url + '?gc=missing'); + expect(response[2].type).to.equal(rtbResponse.seatbid[0].bid[0].ext.utrk[0].type); + expect(response[2].url).to.equal(rtbResponse.seatbid[0].bid[0].ext.utrk[0].url + '?gc=missing'); + expect(response[3].type).to.equal(rtbResponse.seatbid[1].bid[0].ext.utrk[0].type); + expect(response[3].url).to.equal(rtbResponse.seatbid[1].bid[0].ext.utrk[0].url + '?gc=missing'); + }); + + it('supports configuring outstream renderers', function () { + const videoResponse = { + 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', + 'bidid': 'imp_5c24924de4b0d106447af333', + 'cur': 'USD', + 'seatbid': [ + { + 'seat': '3668', + 'group': 0, + 'bid': [ + { + 'id': 'gb_1', + 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + 'price': 5.0, + 'adid': '1274', + 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&p=${AUCTION_PRICE}', + 'adomain': [], + 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'cid': '3668', + 'crid': '1274', + 'cat': [], + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + 'imptrackers': [ + 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] + } + } + ] + } + ], + 'ext': { + 'utrk': [{ + 'type': 'image', + 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' + }] + } + }; + const videoRequest = deepClone(videoBidRequest); + videoRequest.mediaTypes.video.context = 'outstream'; + const result = spec.interpretResponse({body: videoResponse}, {bidRequest: videoRequest}); + expect(result[0].renderer).to.not.equal(undefined); + }); + }); +}); From 10b29e8a1d93282f0837013f4347c5172a694caf Mon Sep 17 00:00:00 2001 From: Fedor Belov Date: Thu, 10 Jan 2019 22:49:02 +0300 Subject: [PATCH 0931/1594] OTM adapter update (#3407) * otm * ALF-95 * otm: modify adapter to support migration to a new ssp * otm: fixed spec --- modules/otmBidAdapter.js | 60 ++++++++++++++----------- modules/otmBidAdapter.md | 4 +- test/spec/modules/otmBidAdapter_spec.js | 41 ++++++++++------- 3 files changed, 60 insertions(+), 45 deletions(-) diff --git a/modules/otmBidAdapter.js b/modules/otmBidAdapter.js index 000985e2889..fe320104a26 100644 --- a/modules/otmBidAdapter.js +++ b/modules/otmBidAdapter.js @@ -5,46 +5,56 @@ export const spec = { code: 'otm', supportedMediaTypes: [BANNER], isBidRequestValid: function (bid) { - return !!bid.params.pid && !!bid.params.tid; + return !!bid.params.tid; }, buildRequests: function (bidRequests) { const requests = bidRequests.map(function (bid) { const params = { - pid: bid.params.pid, - tid: bid.params.tid, - bidfloor: bid.params.bidfloor, - url: encodeURIComponent(window.location.href), - size: bid.sizes[0][0] + 'x' + bid.sizes[0][1], - resp_type: 'json', - rnd: Math.random(), - bidId: bid.bidId, + tz: getTz(), + w: bid.sizes[0][0], + h: bid.sizes[0][1], + s: bid.params.tid, + bidid: bid.bidId, + transactionid: bid.transactionId, + auctionid: bid.auctionId, + bidfloor: bid.params.bidfloor }; - return {method: 'GET', url: 'https://ads2.otm-r.com/banner/hb', data: params} + return {method: 'GET', url: 'https://ssp.otm-r.com/adjson', data: params} }); return requests; }, interpretResponse: function (serverResponse, bidRequest) { - if (!serverResponse || !serverResponse.body || !serverResponse.body.ad) { + if (!serverResponse || !serverResponse.body) { return []; } - const bid = serverResponse.body; - const sizes = bid.size.split('x'); - - return [{ - requestId: bidRequest.data.bidId, - cpm: bid.price, - width: sizes[0], - height: sizes[1], - creativeId: bidRequest.data.bidId, - currency: bid.currency || 'RUB', - netRevenue: true, - ad: bid.ad, - ttl: 360 - }]; + const answer = []; + + serverResponse.body.forEach(bid => { + if (bid.ad) { + answer.push({ + requestId: bid.bidid, + cpm: bid.cpm, + width: bid.w, + height: bid.h, + creativeId: bid.creativeid, + currency: bid.currency || 'RUB', + netRevenue: true, + ad: bid.ad, + ttl: bid.ttl, + transactionId: bid.transactionid + }); + } + }); + + return answer; }, }; +function getTz() { + return new Date().getTimezoneOffset(); +} + registerBidder(spec); diff --git a/modules/otmBidAdapter.md b/modules/otmBidAdapter.md index e51d73443dd..4962d3a8052 100644 --- a/modules/otmBidAdapter.md +++ b/modules/otmBidAdapter.md @@ -21,8 +21,7 @@ About us : http://otm-r.com { bidder: "otm", params: { - pid: 1, - tid: "demo", + tid: "99", bidfloor: 20 } } @@ -33,6 +32,5 @@ About us : http://otm-r.com Where: -* pid - Publisher id * tid - A tag id (should have low cardinality) * bidfloor - Floor price diff --git a/test/spec/modules/otmBidAdapter_spec.js b/test/spec/modules/otmBidAdapter_spec.js index fa047f38109..0fe81a512cb 100644 --- a/test/spec/modules/otmBidAdapter_spec.js +++ b/test/spec/modules/otmBidAdapter_spec.js @@ -1,13 +1,12 @@ -import { expect } from 'chai'; -import { spec } from 'modules/otmBidAdapter'; +import {expect} from 'chai'; +import {spec} from 'modules/otmBidAdapter'; describe('otmBidAdapterTests', function () { it('validate_pub_params', function () { expect(spec.isBidRequestValid({ bidder: 'otm', params: { - pid: 1, - tid: 'demo', + tid: '123', bidfloor: 20 } })).to.equal(true); @@ -18,8 +17,7 @@ describe('otmBidAdapterTests', function () { bidId: 'bid1234', bidder: 'otm', params: { - pid: 1, - tid: 'demo', + tid: '123', bidfloor: 20 }, sizes: [[240, 400]] @@ -28,7 +26,7 @@ describe('otmBidAdapterTests', function () { let request = spec.buildRequests(bidRequestData); let req_data = request[0].data; - expect(req_data.bidId).to.equal('bid1234'); + expect(req_data.bidid).to.equal('bid1234'); }); it('validate_response_params', function () { @@ -39,22 +37,31 @@ describe('otmBidAdapterTests', function () { }; let serverResponse = { - body: { - price: 1.12, - ad: 'Ad html', - size: '250x600' - } + 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' + } + ] }; let bids = spec.interpretResponse(serverResponse, bidRequestData); expect(bids).to.have.lengthOf(1); let bid = bids[0]; - expect(bid.cpm).to.equal(1.12); + expect(bid.cpm).to.equal(847.097); expect(bid.currency).to.equal('RUB'); - expect(bid.width).to.equal('250'); - expect(bid.height).to.equal('600'); + expect(bid.width).to.equal(240); + expect(bid.height).to.equal(400); expect(bid.netRevenue).to.equal(true); - expect(bid.requestId).to.equal('bid1234'); - expect(bid.ad).to.equal('Ad html'); + expect(bid.requestId).to.equal('101f211def7c99'); + expect(bid.ad).to.equal('test html'); }); }); From 8bdcfdfce30452548529fbc286f071a7332344a4 Mon Sep 17 00:00:00 2001 From: PubNX <44992681+prebid-pubnx@users.noreply.github.com> Date: Fri, 11 Jan 2019 03:35:08 +0530 Subject: [PATCH 0932/1594] PubNX new standalone adapter (#3298) * - pubnx new bidder adapter created - pubnx doc file created * - Spec file added. * - Vertoz removed from response text * removed pubnx from serverbid since there will be a standalone adapter, the pubnx alias needs to removed from here * - pubnx response parameters updated * - build request params updated --- modules/pubnxBidAdapter.js | 86 +++++++++++++++++ modules/pubnxBidAdapter.md | 31 ++++++ modules/serverbidBidAdapter.js | 5 +- test/spec/modules/pubnxBidAdapter_spec.js | 112 ++++++++++++++++++++++ 4 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 modules/pubnxBidAdapter.js create mode 100644 modules/pubnxBidAdapter.md create mode 100644 test/spec/modules/pubnxBidAdapter_spec.js diff --git a/modules/pubnxBidAdapter.js b/modules/pubnxBidAdapter.js new file mode 100644 index 00000000000..8511e47b1f1 --- /dev/null +++ b/modules/pubnxBidAdapter.js @@ -0,0 +1,86 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'pubnx'; +const BASE_URI = '//hb.pubnxserv.com/vzhbidder/bid?'; + +export const spec = { + code: BIDDER_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 !!(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(bidRequestsArr) { + var bidRequests = bidRequestsArr || []; + return bidRequests.map(bid => { + let slotBidId = utils.getValue(bid, 'bidId'); + let cb = Math.round(new Date().getTime() / 1000); + let pnxEndPoint = BASE_URI; + let reqParams = bid.params || {}; + let placementId = utils.getValue(reqParams, 'placementId'); + let cpm = utils.getValue(reqParams, 'cpmFloor'); + + if (utils.isEmptyStr(placementId)) { + utils.logError('missing params:', BIDDER_CODE, 'Enter valid vzPlacementId'); + return; + } + + let reqSrc = utils.getTopWindowLocation().href; + var pnxReq = { + _vzPlacementId: placementId, + _rqsrc: reqSrc, + _cb: cb, + _slotBidId: slotBidId, + _cpm: cpm, + _cbn: '' + }; + + let queryParamValue = encodeURIComponent(JSON.stringify(pnxReq)); + + return { + method: 'POST', + data: {q: queryParamValue}, + url: pnxEndPoint + }; + }) + }, + /** + * 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) { + var bidRespObj = serverResponse.body; + const bidResponses = []; + + if (bidRespObj.cpm) { + const bidResponse = { + requestId: bidRespObj.slotBidId, + cpm: Number(bidRespObj.cpm), + width: Number(bidRespObj.adWidth), + height: Number(bidRespObj.adHeight), + netRevenue: true, + mediaType: 'banner', + currency: 'USD', + dealId: null, + creativeId: bidRespObj.bid, + ttl: 300, + ad: bidRespObj.ad + utils.createTrackPixelHtml(decodeURIComponent(bidRespObj.nurl)) + }; + bidResponses.push(bidResponse); + } + return bidResponses; + } +} +registerBidder(spec); 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/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index 44bbb406585..50afa4bc469 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -30,9 +30,6 @@ const CONFIG = { }, 'answermedia': { 'BASE_URI': 'https://e.serverbid.com/api/v2' - }, - 'pubnx': { - 'BASE_URI': 'https://e.serverbid.com/api/v2' } }; @@ -41,7 +38,7 @@ let bidder = 'serverbid'; export const spec = { code: BIDDER_CODE, - aliases: ['connectad', 'onefiftytwo', 'insticator', 'adsparc', 'automatad', 'archon', 'buysellads', 'answermedia', 'pubnx'], + aliases: ['connectad', 'onefiftytwo', 'insticator', 'adsparc', 'automatad', 'archon', 'buysellads', 'answermedia'], /** * Determines whether or not the given bid request is valid. diff --git a/test/spec/modules/pubnxBidAdapter_spec.js b/test/spec/modules/pubnxBidAdapter_spec.js new file mode 100644 index 00000000000..002922fa066 --- /dev/null +++ b/test/spec/modules/pubnxBidAdapter_spec.js @@ -0,0 +1,112 @@ +import { expect } from 'chai'; +import { spec } from 'modules/pubnxBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const BASE_URI = '//hb.pubnxserv.com/vzhbidder/bid?'; + +describe('PubNXAdapter', 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': 'pubnx', + 'params': { + 'placementId': 'PNX-HB-G396432V4809F3' + }, + '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 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 bidRequests = [ + { + 'bidder': 'pubnx', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal(BASE_URI); + expect(request.method).to.equal('POST'); + }); + }); + + describe('interpretResponse', function () { + let response = { + 'vzhPlacementId': 'PNX-HB-G396432V4809F3', + 'bid': '76021e56-adaf-4114-b68d-ccacd1b3e551_1', + 'adWidth': '300', + 'adHeight': '250', + 'cpm': '0.16312590000000002', + 'ad': '', + 'slotBidId': '44b3fcfd24aa93', + 'nurl': '', + 'statusText': 'Success' + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + 'requestId': '44b3fcfd24aa93', + 'cpm': 0.16312590000000002, + 'width': 300, + 'height': 250, + 'netRevenue': true, + 'mediaType': 'banner', + 'currency': 'USD', + 'dealId': null, + 'creativeId': null, + 'ttl': 300, + 'ad': '' + } + ]; + let bidderRequest; + let result = spec.interpretResponse({body: response}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + expect(result[0].cpm).to.not.equal(null); + }); + + it('handles nobid responses', function () { + let response = { + 'vzhPlacementId': 'PNX-HB-G396432V4809F3', + 'slotBidId': 'f00412ac86b79', + 'statusText': 'NO_BIDS' + }; + let bidderRequest; + + let result = spec.interpretResponse({body: response}); + expect(result.length).to.equal(0); + }); + }); +}); From 13982d8422950283059c40e6089ba854aee253c3 Mon Sep 17 00:00:00 2001 From: mefjush Date: Fri, 11 Jan 2019 17:03:34 +0100 Subject: [PATCH 0933/1594] New adapter: Adhese (#3384) * Add Adhese adapter * Support empty impressionCounters * Fix the description * Replace Object.entries with Object.keys * Cleanup * Use const instead of let * Internal functions are no longer exposed * Rename getter * Use the bid parameters pointing to the existing demo position --- modules/adheseBidAdapter.js | 166 ++++++++++++ modules/adheseBidAdapter.md | 40 +++ test/spec/modules/adheseBidAdapter_spec.js | 285 +++++++++++++++++++++ 3 files changed, 491 insertions(+) create mode 100644 modules/adheseBidAdapter.js create mode 100644 modules/adheseBidAdapter.md create mode 100644 test/spec/modules/adheseBidAdapter_spec.js diff --git a/modules/adheseBidAdapter.js b/modules/adheseBidAdapter.js new file mode 100644 index 00000000000..c78af965202 --- /dev/null +++ b/modules/adheseBidAdapter.js @@ -0,0 +1,166 @@ +'use strict'; + +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; + +const BIDDER_CODE = 'adhese'; +const USER_SYNC_BASE_URL = 'https://user-sync.adhese.com/iframe/user_sync.html'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + + isBidRequestValid: function(bid) { + return !!(bid.params.account && bid.params.location && bid.params.format); + }, + + buildRequests: function(validBidRequests, bidderRequest) { + if (validBidRequests.length === 0) { + return null; + } + + const account = getAccount(validBidRequests); + const targets = validBidRequests.map(bid => bid.params.data).reduce(mergeTargets, {}); + const gdprParams = (bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) ? [ 'xt' + bidderRequest.gdprConsent.consentString ] : []; + const targetsParams = Object.keys(targets).map(targetCode => targetCode + targets[targetCode].join(';')); + const slotsParams = validBidRequests.map(bid => 'sl' + bidToSlotName(bid)); + const params = [...slotsParams, ...targetsParams, ...gdprParams].map(s => '/' + s).join(''); + const cacheBuster = '?t=' + new Date().getTime(); + const uri = 'https://ads-' + account + '.adhese.com/json' + params + cacheBuster; + + return { + method: 'GET', + url: uri, + bids: validBidRequests + }; + }, + + interpretResponse: function(serverResponse, request) { + const serverAds = serverResponse.body.reduce(function(map, ad) { + map[ad.slotName] = ad; + return map; + }, {}); + + serverResponse.account = getAccount(request.bids); + + return request.bids + .map(bid => ({ + bid: bid, + ad: serverAds[bidToSlotName(bid)] + })) + .filter(item => item.ad) + .map(item => adResponse(item.bid, item.ad)); + }, + + getUserSyncs: function(syncOptions, serverResponse, gdprConsent) { + const account = serverResponse.account || ''; + if (syncOptions.iframeEnabled) { + let syncurl = USER_SYNC_BASE_URL + '?account=' + account; + if (gdprConsent) { + syncurl += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); + syncurl += '&consentString=' + encodeURIComponent(gdprConsent.consentString || ''); + } + return [{ type: 'iframe', url: syncurl }]; + } + } +}; + +function adResponse(bid, ad) { + const price = getPrice(ad); + const adDetails = getAdDetails(ad); + const markup = getAdMarkup(ad); + + const bidResponse = getbaseAdResponse({ + requestId: bid.bidId, + mediaType: getMediaType(markup), + cpm: Number(price.amount), + currency: price.currency, + width: Number(ad.width), + height: Number(ad.height), + creativeId: adDetails.creativeId, + dealId: adDetails.dealId + }); + + if (bidResponse.mediaType === VIDEO) { + bidResponse.vastXml = markup; + } else { + const counter = ad.impressionCounter ? "" : ''; + bidResponse.ad = markup + counter; + } + return bidResponse; +} + +function mergeTargets(targets, target) { + if (target) { + Object.keys(target).forEach(function (key) { + const val = target[key]; + const values = Array.isArray(val) ? val : [val]; + if (targets[key]) { + const distinctValues = values.filter(v => targets[key].indexOf(v) < 0); + targets[key].push.apply(targets[key], distinctValues); + } else { + targets[key] = values; + } + }); + } + return targets; +} + +function bidToSlotName(bid) { + return bid.params.location + '-' + bid.params.format; +} + +function getAccount(validBidRequests) { + return validBidRequests[0].params.account; +} + +function getbaseAdResponse(response) { + return Object.assign({ netRevenue: true, ttl: 360 }, response); +} + +function isAdheseAd(ad) { + return !ad.origin || ad.origin === 'JERLICIA'; +} + +function getMediaType(markup) { + const isVideo = markup.trim().toLowerCase().match(/<\?xml| { + let bidRequest = { + bids: [ minimalBid() ] + }; + + it('should get correct ssp banner response', () => { + let sspBannerResponse = { + body: [ + { + origin: 'APPNEXUS', + originInstance: '', + ext: 'js', + slotName: '_main_page_-leaderboard', + adType: 'leaderboard', + originData: { + seatbid: [{ + bid: [{ + crid: '60613369', + dealid: null + }], + seat: '958' + }] + }, + width: '728', + height: '90', + body: '
', + tracker: 'https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a', + impressionCounter: 'https://hosts-demo.adhese.com/rtb_gateway/handlers/client/track/?id=a2f39296-6dd0-4b3c-be85-7baa22e7ff4a', + extension: {'prebid': {'cpm': {'amount': '1.000000', 'currency': 'USD'}}} + } + ] + }; + + let expectedResponse = [{ + requestId: BID_ID, + ad: '
', + cpm: 1, + currency: 'USD', + creativeId: '60613369', + dealId: '', + width: 728, + height: 90, + mediaType: 'banner', + netRevenue: NET_REVENUE, + ttl: TTL, + }]; + expect(spec.interpretResponse(sspBannerResponse, bidRequest)).to.deep.equal(expectedResponse); + }); + + it('should get correct ssp video response', () => { + let sspVideoResponse = { + body: [ + { + origin: 'RUBICON', + ext: 'js', + slotName: '_main_page_-leaderboard', + adType: 'leaderboard', + width: '640', + height: '350', + body: '', + extension: {'prebid': {'cpm': {'amount': '2.1', 'currency': 'USD'}}} + } + ] + }; + + let expectedResponse = [{ + requestId: BID_ID, + vastXml: '', + cpm: 2.1, + currency: 'USD', + creativeId: 'RUBICON', + dealId: '', + width: 640, + height: 350, + mediaType: 'video', + netRevenue: NET_REVENUE, + ttl: TTL, + }]; + expect(spec.interpretResponse(sspVideoResponse, bidRequest)).to.deep.equal(expectedResponse); + }); + + it('should get correct Adhese banner response', () => { + const adheseBannerResponse = { + body: [ + { + adType: 'largeleaderboard', // it can differ from the requested slot + adFormat: 'largeleaderboard', + timeStamp: '1544009030000', + orderId: '22051', + adspaceId: '162363', + body: '', + tag: '', + tracker: 'https://hosts-demo.adhese.com/track/tracker', + altText: '', + height: '150', + width: '840', + tagUrl: 'https://pool-demo.adhese.com/pool/lib/90511.js', + libId: '90511', + id: '742898', + advertiserId: '2081', + ext: 'js', + url: 'https://hosts-demo.adhese.com/raylene/url', + clickTag: 'https://hosts-demo.adhese.com/raylene/clickTag', + poolPath: 'https://hosts-demo.adhese.com/pool/lib/', + orderName: 'Luminus boiler comodity-Pareto -201812', + creativeName: 'nl_demo _network_ron_dlbd_840x150_fix_dir_asv_std_dis_brd_nrt_na_red', + slotName: '_main_page_-leaderboard', + slotID: '29306', + impressionCounter: 'https://hosts-demo.adhese.com/track/742898', + origin: 'JERLICIA', + originData: {}, + auctionable: true, + extension: { + prebid: { + cpm: { + amount: '5.96', + currency: 'USD' + } + } + } + } + ] + }; + + let expectedResponse = [{ + requestId: BID_ID, + ad: '', + cpm: 5.96, + currency: 'USD', + creativeId: '742898', + dealId: '22051', + width: 840, + height: 150, + mediaType: 'banner', + netRevenue: NET_REVENUE, + ttl: TTL, + }]; + expect(spec.interpretResponse(adheseBannerResponse, bidRequest)).to.deep.equal(expectedResponse); + }); + + it('should get correct Adhese video response', () => { + const adheseVideoResponse = { + body: [ + { + adType: 'preroll', + adFormat: '', + orderId: '22248', + adspaceId: '164196', + body: '', + height: '360', + width: '640', + tag: "", + libId: '89860', + id: '742470', + advertiserId: '2263', + ext: 'advar', + orderName: 'Smartphoto EOY-20181112', + creativeName: 'PREROLL', + slotName: '_main_page_-leaderboard', + slotID: '41711', + impressionCounter: 'https://hosts-demo.adhese.com/track/742898', + origin: 'JERLICIA', + originData: {}, + auctionable: true + } + ] + }; + + let expectedResponse = [{ + requestId: BID_ID, + vastXml: '', + cpm: 0, + currency: 'USD', + creativeId: '742470', + dealId: '22248', + width: 640, + height: 360, + mediaType: 'video', + netRevenue: NET_REVENUE, + ttl: TTL, + }]; + expect(spec.interpretResponse(adheseVideoResponse, bidRequest)).to.deep.equal(expectedResponse); + }); + + it('should return no bids for empty adserver response', () => { + let adserverResponse = { body: [] }; + expect(spec.interpretResponse(adserverResponse, bidRequest)).to.be.empty; + }); + }); +}); From 99c4bd7ec8cefdd8ed283b23f3b80ceef262f6f8 Mon Sep 17 00:00:00 2001 From: Andrew Muraco Date: Fri, 11 Jan 2019 17:26:44 -0500 Subject: [PATCH 0934/1594] Initial implementation of synacormedia adapter. (#3425) --- modules/synacormediaBidAdapter.js | 121 +++++++++++ modules/synacormediaBidAdapter.md | 43 ++++ .../modules/synacormediaBidAdapter_spec.js | 198 ++++++++++++++++++ 3 files changed, 362 insertions(+) create mode 100644 modules/synacormediaBidAdapter.js create mode 100644 modules/synacormediaBidAdapter.md create mode 100644 test/spec/modules/synacormediaBidAdapter_spec.js diff --git a/modules/synacormediaBidAdapter.js b/modules/synacormediaBidAdapter.js new file mode 100644 index 00000000000..ba5fb0cb23b --- /dev/null +++ b/modules/synacormediaBidAdapter.js @@ -0,0 +1,121 @@ +'use strict'; + +import { getAdUnitSizes, logWarn } from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; +import { REPO_AND_VERSION } from 'src/constants'; + +const SYNACOR_URL = '//prebid.technoratimedia.com'; +export const spec = { + code: 'synacormedia', + supportedMediaTypes: [ BANNER ], + sizeMap: {}, + + isBidRequestValid: function(bid) { + return !!(bid && bid.params && bid.params.placementId && bid.params.seatId); + }, + buildRequests: function(validBidReqs, bidderRequest) { + if (!validBidReqs || !validBidReqs.length || !bidderRequest) { + return; + } + let refererInfo = bidderRequest.refererInfo; + let openRtbBidRequest = { + id: bidderRequest.auctionId, + site: { + domain: location.hostname, + page: refererInfo.referer, + ref: document.referrer + }, + device: { + ua: navigator.userAgent + }, + imp: [] + }; + let seatId = null; + validBidReqs.forEach((bid, i) => { + if (seatId && seatId !== bid.params.seatId) { + logWarn(`Synacormedia: there is an inconsistent seatId: ${bid.params.seatId} but only sending bid requests for ${seatId}, you should double check your configuration`); + return; + } else { + seatId = bid.params.seatId; + } + let placementId = bid.params.placementId; + let size = getAdUnitSizes(bid)[0]; + this.sizeMap[bid.bidId] = size; + openRtbBidRequest.imp.push({ + id: bid.bidId, + tagid: placementId, + banner: { + w: size[0], + h: size[1], + pos: 0 + } + }); + }); + if (openRtbBidRequest.imp.length && seatId) { + return { + method: 'POST', + url: `${SYNACOR_URL}/openrtb/bids/${seatId}?src=${REPO_AND_VERSION}`, + data: openRtbBidRequest, + options: { + contentType: 'application/json', + withCredentials: true + } + }; + } + }, + interpretResponse: function(serverResponse) { + if (!serverResponse.body || typeof serverResponse.body != 'object') { + logWarn('Synacormedia: server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); + return; + } + const {id, seatbid: seatbids} = serverResponse.body; + let bids = []; + if (id && seatbids) { + seatbids.forEach(seatbid => { + seatbid.bid.forEach(bid => { + let size = this.sizeMap[bid.impid] || [0, 0]; + let price = parseFloat(bid.price); + let creative = bid.adm.replace(/\${([^}]*)}/g, (match, key) => { + switch (key) { + case 'AUCTION_SEAT_ID': return seatbid.seat; + case 'AUCTION_ID': return id; + case 'AUCTION_BID_ID': return bid.id; + case 'AUCTION_IMP_ID': return bid.impid; + case 'AUCTION_PRICE': return price; + case 'AUCTION_CURRENCY': return 'USD'; + } + return match; + }); + bids.push({ + requestId: bid.impid, + cpm: price, + width: size[0], + height: size[1], + creativeId: seatbid.seat + '~' + bid.crid, + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: creative, + ttl: 60 + }); + }); + }); + } + return bids; + }, + getUserSyncs: function (syncOptions, serverResponses) { + const syncs = []; + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: `${SYNACOR_URL}/usersync/html?src=${REPO_AND_VERSION}` + }); + } else { + logWarn('Synacormedia: Please enable iframe based user sync.'); + } + return syncs; + } +}; + +registerBidder(spec); diff --git a/modules/synacormediaBidAdapter.md b/modules/synacormediaBidAdapter.md new file mode 100644 index 00000000000..813e14f6be6 --- /dev/null +++ b/modules/synacormediaBidAdapter.md @@ -0,0 +1,43 @@ +# Overview + +``` +Module Name: Synacor Media Bidder Adapter +Module Type: Bidder Adapter +Maintainer: eng-demand@synacor.com +``` + +# Description + +The Synacor Media adapter requires setup and approval from Synacor. +Please reach out to your account manager for more information. + +# Test Parameters + +## Web +``` + var adUnits = [{ + code: 'test-div', + sizes: [ + [300, 250] + ], + bids: [{ + bidder: "synacormedia", + params: { + seatId: "prebid", + placementId: "81416" + } + }] + },{ + code: 'test-div2', + sizes: [ + [300, 250] + ], + bids: [{ + bidder: "synacormedia", + params: { + seatId: "prebid", + placementId: "demo2" + } + }] + }]; +``` \ No newline at end of file diff --git a/test/spec/modules/synacormediaBidAdapter_spec.js b/test/spec/modules/synacormediaBidAdapter_spec.js new file mode 100644 index 00000000000..9a95d1377e8 --- /dev/null +++ b/test/spec/modules/synacormediaBidAdapter_spec.js @@ -0,0 +1,198 @@ +import { assert, expect } from 'chai'; +import { BANNER } from 'src/mediaTypes'; +import { spec } from 'modules/synacormediaBidAdapter'; + +describe('synacormediaBidAdapter ', function () { + describe('isBidRequestValid', function () { + let bid; + beforeEach(function () { + bid = { + params: { + seatId: 'prebid', + placementId: '1234' + } + }; + }); + + it('should return true when params placementId and seatId are truthy', function () { + assert(spec.isBidRequestValid(bid)); + }); + + it('should return false when seatId param is missing', function () { + delete bid.params.seatId; + assert.isFalse(spec.isBidRequestValid(bid)); + }); + it('should return false when placementId param is missing', function () { + delete bid.params.placementId; + assert.isFalse(spec.isBidRequestValid(bid)); + }); + it('should return false when params is missing or null', function () { + assert.isFalse(spec.isBidRequestValid({ params: null })); + assert.isFalse(spec.isBidRequestValid({})); + assert.isFalse(spec.isBidRequestValid(null)); + }); + }); + describe('buildRequests', function () { + let validBidRequest = { + bidId: '9876abcd', + sizes: [[300, 250]], + params: { + seatId: 'prebid', + placementId: '1234' + } + }; + + let bidderRequest = { + auctionId: 'xyz123', + refererInfo: { + referer: 'https://test.com/foo/bar' + } + }; + + let expectedDataImp = { + banner: { + h: 250, + pos: 0, + w: 300, + }, + id: '9876abcd', + tagid: '1234' + }; + + it('should return valid request when valid bids are used', function () { + let req = spec.buildRequests([validBidRequest], bidderRequest); + expect(req).be.an('object'); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?'); + expect(req.data).to.exist.and.to.be.an('object'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([expectedDataImp]); + }); + + it('should return multiple bids when multiple valid requests with the same seatId are used', function () { + let secondBidRequest = { + bidId: 'foobar', + sizes: [[300, 600]], + params: { + seatId: validBidRequest.params.seatId, + placementId: '5678' + } + }; + let req = spec.buildRequests([validBidRequest, secondBidRequest], bidderRequest); + expect(req).to.exist.and.be.an('object'); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([expectedDataImp, { + banner: { + h: 600, + pos: 0, + w: 300, + }, + id: 'foobar', + tagid: '5678' + }]); + }); + + it('should return only first bid when different seatIds are used', function () { + let mismatchedSeatBidRequest = { + bidId: 'foobar', + sizes: [[300, 250]], + params: { + seatId: 'somethingelse', + placementId: '5678' + } + }; + let req = spec.buildRequests([mismatchedSeatBidRequest, validBidRequest], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/somethingelse?'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + banner: { + h: 250, + pos: 0, + w: 300, + }, + id: 'foobar', + tagid: '5678' + } + ]); + }); + + it('should not return a request when no valid bid request used', function () { + expect(spec.buildRequests([], bidderRequest)).to.be.undefined; + expect(spec.buildRequests([validBidRequest], null)).to.be.undefined; + }); + }); + + describe('interpretResponse', function () { + let bidResponse = { + id: '10865933907263896~9998~0', + impid: '9876abcd', + price: 0.13, + crid: '1022-250', + adm: '' + }; + spec.sizeMap['9876abcd'] = [300, 250]; + + let serverResponse; + beforeEach(function() { + serverResponse = { + body: { + id: 'abc123', + seatbid: [{ + seat: '9998', + bid: [], + }] + } + }; + }); + it('should return a bid when bid is in the response', function () { + serverResponse.body.seatbid[0].bid.push(bidResponse); + let resp = spec.interpretResponse(serverResponse); + expect(resp).to.be.an('array').that.is.not.empty; + expect(resp[0]).to.eql({ + requestId: '9876abcd', + cpm: 0.13, + width: 300, + height: 250, + creativeId: '9998~1022-250', + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: '', + ttl: 60 + }); + }); + it('should not return a bid when no bid is in the response', function () { + let resp = spec.interpretResponse(serverResponse); + expect(resp).to.be.an('array').that.is.empty; + }); + it('should not return a bid when there is no response body', function () { + expect(spec.interpretResponse({ body: null })).to.not.exist; + expect(spec.interpretResponse({ body: 'some error text' })).to.not.exist; + }); + }); + describe('getUserSyncs', function () { + it('should return a usersync when iframes is enabled', function () { + let usersyncs = spec.getUserSyncs({ + iframeEnabled: true + }, null); + expect(usersyncs).to.be.an('array').that.is.not.empty; + expect(usersyncs[0]).to.have.property('type', 'iframe'); + expect(usersyncs[0]).to.have.property('url'); + expect(usersyncs[0].url).to.contain('//prebid.technoratimedia.com/usersync/html'); + }); + + it('should not return a usersync when iframes are not enabled', function () { + let usersyncs = spec.getUserSyncs({ + pixelEnabled: true + }, null); + expect(usersyncs).to.be.an('array').that.is.empty; + }); + }); +}); From 3a44263f98b36ad67b7556cb36f5226d7946ec44 Mon Sep 17 00:00:00 2001 From: Valentin Date: Tue, 15 Jan 2019 17:21:21 +0100 Subject: [PATCH 0935/1594] Teads adapter: handle video playerSize (#3423) * Teads adapter: handle playerSize * Handle multiple mediatypes sizes * Clean sizes logic --- modules/teadsBidAdapter.js | 29 +++++++- test/spec/modules/teadsBidAdapter_spec.js | 84 ++++++++++++++++++++--- 2 files changed, 101 insertions(+), 12 deletions(-) diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js index e8dbe4e1c6b..96855e56882 100644 --- a/modules/teadsBidAdapter.js +++ b/modules/teadsBidAdapter.js @@ -116,7 +116,7 @@ function buildRequestObject(bid) { let placementId = utils.getValue(bid.params, 'placementId'); let pageId = utils.getValue(bid.params, 'pageId'); - reqObj.sizes = utils.parseSizesInput(bid.sizes); + reqObj.sizes = getSizes(bid); reqObj.bidId = utils.getBidIdParameter('bidId', bid); reqObj.bidderRequestId = utils.getBidIdParameter('bidderRequestId', bid); reqObj.placementId = parseInt(placementId, 10); @@ -127,6 +127,33 @@ function buildRequestObject(bid) { return reqObj; } +function getSizes(bid) { + return utils.parseSizesInput(concatSizes(bid)); +} + +function concatSizes(bid) { + 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 (utils.isArray(bannerSizes) || utils.isArray(playerSize) || utils.isArray(videoSizes)) { + let mediaTypesSizes = [bannerSizes, videoSizes, playerSize]; + return mediaTypesSizes + .reduce(function(acc, currSize) { + if (utils.isArray(currSize)) { + if (utils.isArray(currSize[0])) { + currSize.forEach(function (childSize) { acc.push(childSize) }) + } else { + acc.push(currSize); + } + } + return acc; + }, []) + } else { + return bid.sizes; + } +} + function _validateId(id) { return (parseInt(id) > 0); } diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js index ab34c600a53..20fdbe947c0 100644 --- a/test/spec/modules/teadsBidAdapter_spec.js +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -3,7 +3,7 @@ import {spec} from 'modules/teadsBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; const ENDPOINT = '//a.teads.tv/hb/bid-request'; -const AD_SCRIPT = '"'; +const AD_SCRIPT = '"'; describe('teadsBidAdapter', function() { const adapter = newBidder(spec); @@ -96,13 +96,14 @@ describe('teadsBidAdapter', function() { } ]; + let bidderResquestDefault = { + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000 + }; + it('sends bid request to ENDPOINT via POST', function() { - let bidderRequest = { - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000 - }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderResquestDefault); expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('POST'); @@ -129,7 +130,7 @@ describe('teadsBidAdapter', function() { expect(payload.gdpr_iab).to.exist; expect(payload.gdpr_iab.consent).to.equal(consentString); expect(payload.gdpr_iab.status).to.equal(12); - }) + }); it('should send GDPR to endpoint with 11 status', function() { let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; @@ -152,7 +153,7 @@ describe('teadsBidAdapter', function() { expect(payload.gdpr_iab).to.exist; expect(payload.gdpr_iab.consent).to.equal(consentString); expect(payload.gdpr_iab.status).to.equal(11); - }) + }); it('should send GDPR to endpoint with 22 status', function() { let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; @@ -173,7 +174,7 @@ describe('teadsBidAdapter', function() { expect(payload.gdpr_iab).to.exist; expect(payload.gdpr_iab.consent).to.equal(''); expect(payload.gdpr_iab.status).to.equal(22); - }) + }); it('should send GDPR to endpoint with 0 status', function() { let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; @@ -196,7 +197,68 @@ describe('teadsBidAdapter', function() { expect(payload.gdpr_iab).to.exist; expect(payload.gdpr_iab.consent).to.equal(consentString); expect(payload.gdpr_iab.status).to.equal(0); - }) + }); + + it('should use good mediaTypes video playerSizes', function() { + const mediaTypesPlayerSize = { + 'mediaTypes': { + 'video': { + 'playerSize': [32, 34] + } + } + }; + checkMediaTypesSizes(mediaTypesPlayerSize, '32x34') + }); + + it('should use good mediaTypes video sizes', function() { + const mediaTypesVideoSizes = { + 'mediaTypes': { + 'video': { + 'sizes': [12, 14] + } + } + }; + checkMediaTypesSizes(mediaTypesVideoSizes, '12x14') + }); + + it('should use good mediaTypes banner sizes', function() { + const mediaTypesBannerSize = { + 'mediaTypes': { + 'banner': { + 'sizes': [46, 48] + } + } + }; + checkMediaTypesSizes(mediaTypesBannerSize, '46x48') + }); + + it('should use good mediaTypes for both video and banner sizes', function() { + const hybridMediaTypes = { + 'mediaTypes': { + 'banner': { + 'sizes': [46, 48] + }, + 'video': { + 'sizes': [[50, 34], [45, 45]] + } + } + }; + checkMediaTypesSizes(hybridMediaTypes, ['46x48', '50x34', '45x45']) + }); + + function checkMediaTypesSizes(mediaTypes, expectedSizes) { + const bidRequestWithBannerSizes = Object.assign(bidRequests[0], mediaTypes); + const requestWithBannerSizes = spec.buildRequests([bidRequestWithBannerSizes], bidderResquestDefault); + const payloadWithBannerSizes = JSON.parse(requestWithBannerSizes.data); + + return payloadWithBannerSizes.data.forEach(bid => { + if (Array.isArray(expectedSizes)) { + expect(JSON.stringify(bid.sizes)).to.equal(JSON.stringify(expectedSizes)); + } else { + expect(bid.sizes[0]).to.equal(expectedSizes); + } + }); + } }); describe('interpretResponse', function() { From 339c93de5df1167faf2a94e83aee11efb4e5b282 Mon Sep 17 00:00:00 2001 From: pm-shashank-jain <40654031+pm-shashank-jain@users.noreply.github.com> Date: Tue, 15 Jan 2019 22:14:35 +0530 Subject: [PATCH 0936/1594] Support for Native in Pubmatic Adapter (#3408) * changes to support native in pubmaticbid adapter * Removed port from endpoint * Removed protocol from endpoint * Formatting * Fix request payload * Updated test case * Changed request and response as per ortb spec * Change in request and response * Removed comments and extra code * Code Review comments * Code Review Comments and Test cases for request and response * Removed data type as all data asset types are handled * Code Review Changes * Code Review Comments * Supporting both banner and native and sending 0x0 in case of native * Bug Fixes * Bug response not processed by prebid * Change warning message * Fixed typo * Do not send request in case of invalid native bid * Do not send request in case of invalid native requests * objects converted to strings in log for debug purposes * Fixed logic to check for required parmas * Fixed typo for stringify * documentation for native * Review comments from Prebid * Typo * Typo * Updated pub id for native * Code Review --- modules/pubmaticBidAdapter.js | 595 ++++++++++++++++--- modules/pubmaticBidAdapter.md | 37 +- test/spec/modules/pubmaticBidAdapter_spec.js | 264 +++++++- 3 files changed, 818 insertions(+), 78 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index eb8a082f61f..cc42031b44d 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -1,6 +1,6 @@ import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER, VIDEO } from 'src/mediaTypes'; +import { BANNER, VIDEO, NATIVE } from 'src/mediaTypes'; import {config} from 'src/config'; const constants = require('src/constants.json'); @@ -11,6 +11,9 @@ const DEFAULT_CURRENCY = 'USD'; const AUCTION_TYPE = 1; const PUBMATIC_DIGITRUST_KEY = 'nFIn8aLzbd'; 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 CUSTOM_PARAMS = { 'kadpageurl': '', // Custom page url 'gender': '', // User gender @@ -25,7 +28,8 @@ const DATA_TYPES = { 'NUMBER': 'number', 'STRING': 'string', 'BOOLEAN': 'boolean', - 'ARRAY': 'array' + 'ARRAY': 'array', + 'OBJECT': 'object' }; const VIDEO_CUSTOM_PARAMS = { 'mimes': DATA_TYPES.ARRAY, @@ -43,6 +47,117 @@ const VIDEO_CUSTOM_PARAMS = { 'minbitrate': DATA_TYPES.NUMBER, 'maxbitrate': DATA_TYPES.NUMBER } + +const NATIVE_ASSET_ID = { + 'TITLE': 1, + 'IMAGE': 2, + 'ICON': 3, + 'SPONSOREDBY': 4, + 'BODY': 5, + 'CLICKURL': 6, + 'VIDEO': 7, + 'EXT': 8, + 'DATA': 9, + 'LOGO': 10, + 'SPONSORED': 11, + 'DESC': 12, + 'RATING': 13, + 'LIKES': 14, + 'DOWNLOADS': 15, + 'PRICE': 16, + 'SALEPRICE': 17, + 'PHONE': 18, + 'ADDRESS': 19, + 'DESC2': 20, + 'DISPLAYURL': 21, + 'CTA': 22 +} + +const NATIVE_ASSET_REVERSE_ID = { + 4: 'sponsoredBy', + 5: 'body', + 6: 'clickUrl', + 7: 'video', + 8: 'ext', + 9: 'data', + 10: 'logo', + 11: 'sponsored', + 12: 'desc', + 13: 'rating', + 14: 'likes', + 15: 'downloads', + 16: 'price', + 17: 'saleprice', + 18: 'phone', + 19: 'address', + 20: 'desc2', + 21: 'displayurl', + 22: 'cta' +} + +const NATIVE_ASSET_KEY = { + 'TITLE': 'title', + 'IMAGE': 'image', + 'ICON': 'icon', + 'SPONSOREDBY': 'sponsoredBy', + 'BODY': 'body', + 'VIDEO': 'video', + 'EXT': 'ext', + 'DATA': 'data', + 'LOGO': 'logo', + 'DESC': 'desc', + 'RATING': 'rating', + 'LIKES': 'likes', + 'DOWNLOADS': 'downloads', + 'PRICE': 'price', + 'SALEPRICE': 'saleprice', + 'PHONE': 'phone', + 'ADDRESS': 'address', + 'DESC2': 'desc2', + 'DISPLAYURL': 'displayurl', + 'CTA': 'cta' +} + +const NATIVE_ASSET_IMAGE_TYPE = { + 'ICON': 1, + 'LOGO': 2, + 'IMAGE': 3 +} + +const NATIVE_ASSET_DATA_TYPE = { + 'SPONSORED': 1, + 'DESC': 2, + 'RATING': 3, + 'LIKES': 4, + 'DOWNLOADS': 5, + 'PRICE': 6, + 'SALEPRICE': 7, + 'PHONE': 8, + 'ADDRESS': 9, + 'DESC2': 10, + 'DISPLAYURL': 11, + 'CTA': 12 +} + +// check if title, image can be added with mandatory field default values +const NATIVE_MINIMUM_REQUIRED_IMAGE_ASSETS = [ + { + id: NATIVE_ASSET_ID.SPONSOREDBY, + required: true, + data: { + type: 1 + } + }, + { + id: NATIVE_ASSET_ID.TITLE, + required: true, + }, + { + id: NATIVE_ASSET_ID.IMAGE, + required: true, + } +] + const NET_REVENUE = false; const dealChannelValues = { 1: 'PMP', @@ -51,6 +166,7 @@ const dealChannelValues = { }; let publisherId = 0; +let isInvalidNativeRequest = false; function _getDomainFromURL(url) { let anchor = document.createElement('a'); @@ -126,10 +242,14 @@ function _parseAdSlot(bid) { } } -function _initConf() { +function _initConf(refererInfo) { var conf = {}; conf.pageURL = utils.getTopWindowUrl(); - conf.refURL = utils.getTopWindowReferrer(); + if (refererInfo && refererInfo.referer) { + conf.refURL = refererInfo.referer; + } else { + conf.refURL = ''; + } return conf; } @@ -217,6 +337,256 @@ function _checkParamDataType(key, value, datatype) { } } +function _createNativeRequest(params) { + var nativeRequestObject = { + assets: [] + }; + for (var key in params) { + if (params.hasOwnProperty(key)) { + var assetObj = {}; + if (!(nativeRequestObject.assets && nativeRequestObject.assets.length > 0 && nativeRequestObject.assets.hasOwnProperty(key))) { + switch (key) { + case NATIVE_ASSET_KEY.TITLE: + if (params[key].len || params[key].length) { + assetObj = { + id: NATIVE_ASSET_ID.TITLE, + required: params[key].required ? 1 : 0, + title: { + len: params[key].len || params[key].length, + ext: params[key].ext + } + }; + } else { + utils.logWarn(BIDDER_CODE + ' Error: Title Length is required for native ad: ' + JSON.stringify(params)); + } + break; + case NATIVE_ASSET_KEY.IMAGE: + if (params[key].sizes && params[key].sizes.length > 0) { + assetObj = { + id: NATIVE_ASSET_ID.IMAGE, + required: params[key].required ? 1 : 0, + img: { + type: NATIVE_ASSET_IMAGE_TYPE.IMAGE, + w: params[key].w || params[key].width || (params[key].sizes ? params[key].sizes[0] : undefined), + h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : undefined), + wmin: params[key].wmin || params[key].minimumWidth || (params[key].minsizes ? params[key].minsizes[0] : undefined), + hmin: params[key].hmin || params[key].minimumHeight || (params[key].minsizes ? params[key].minsizes[1] : undefined), + mimes: params[key].mimes, + ext: params[key].ext, + } + }; + } else { + // Log Warn + utils.logWarn(BIDDER_CODE + ' Error: Image sizes is required for native ad: ' + JSON.stringify(params)); + } + break; + case NATIVE_ASSET_KEY.ICON: + if (params[key].sizes && params[key].sizes.length > 0) { + assetObj = { + id: NATIVE_ASSET_ID.ICON, + required: params[key].required ? 1 : 0, + img: { + type: NATIVE_ASSET_IMAGE_TYPE.ICON, + w: params[key].w || params[key].width || (params[key].sizes ? params[key].sizes[0] : undefined), + h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : undefined), + } + }; + } else { + // Log Warn + utils.logWarn(BIDDER_CODE + ' Error: Icon sizes is required for native ad: ' + JSON.stringify(params)); + }; + break; + case NATIVE_ASSET_KEY.SPONSOREDBY: + assetObj = { + id: NATIVE_ASSET_ID.SPONSOREDBY, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.SPONSORED, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.BODY: + assetObj = { + id: NATIVE_ASSET_ID.BODY, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.DESC, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.VIDEO: + assetObj = { + id: NATIVE_ASSET_ID.VIDEO, + required: params[key].required ? 1 : 0, + video: { + minduration: params[key].minduration, + maxduration: params[key].maxduration, + protocols: params[key].protocols, + mimes: params[key].mimes, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.EXT: + assetObj = { + id: NATIVE_ASSET_ID.EXT, + required: params[key].required ? 1 : 0, + }; + break; + case NATIVE_ASSET_KEY.LOGO: + assetObj = { + id: NATIVE_ASSET_ID.LOGO, + required: params[key].required ? 1 : 0, + img: { + type: NATIVE_ASSET_IMAGE_TYPE.LOGO, + w: params[key].w || params[key].width || (params[key].sizes ? params[key].sizes[0] : undefined), + h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : undefined) + } + }; + break; + case NATIVE_ASSET_KEY.RATING: + assetObj = { + id: NATIVE_ASSET_ID.RATING, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.RATING, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.LIKES: + assetObj = { + id: NATIVE_ASSET_ID.LIKES, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.LIKES, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.DOWNLOADS: + assetObj = { + id: NATIVE_ASSET_ID.DOWNLOADS, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.DOWNLOADS, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.PRICE: + assetObj = { + id: NATIVE_ASSET_ID.PRICE, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.PRICE, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.SALEPRICE: + assetObj = { + id: NATIVE_ASSET_ID.SALEPRICE, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.SALEPRICE, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.PHONE: + assetObj = { + id: NATIVE_ASSET_ID.PHONE, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.PHONE, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.ADDRESS: + assetObj = { + id: NATIVE_ASSET_ID.ADDRESS, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.ADDRESS, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.DESC2: + assetObj = { + id: NATIVE_ASSET_ID.DESC2, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.DESC2, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.DISPLAYURL: + assetObj = { + id: NATIVE_ASSET_ID.DISPLAYURL, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.DISPLAYURL, + len: params[key].len, + ext: params[key].ext + } + }; + break; + case NATIVE_ASSET_KEY.CTA: + assetObj = { + id: NATIVE_ASSET_ID.CTA, + required: params[key].required ? 1 : 0, + data: { + type: NATIVE_ASSET_DATA_TYPE.CTA, + len: params[key].len, + ext: params[key].ext + } + }; + break; + } + } + } + if (assetObj && 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 + var requiredAssetCount = NATIVE_MINIMUM_REQUIRED_IMAGE_ASSETS.length; + var presentrequiredAssetCount = 0; + NATIVE_MINIMUM_REQUIRED_IMAGE_ASSETS.forEach(ele => { + var lengthOfExistingAssets = nativeRequestObject.assets.length; + for (var i = 0; i < lengthOfExistingAssets; i++) { + if (ele.id == nativeRequestObject.assets[i].id) { + presentrequiredAssetCount++; + break; + } + } + }); + if (requiredAssetCount == presentrequiredAssetCount) { + isInvalidNativeRequest = false; + } else { + isInvalidNativeRequest = true; + } + return nativeRequestObject; +} + function _createImpressionObject(bid, conf) { var impObj = {}; var bannerObj = {}; @@ -257,6 +627,9 @@ function _createImpressionObject(bid, conf) { } impObj.video = videoObj; + } else if (bid.nativeParams) { + impObj.native = {}; + impObj.native['request'] = JSON.stringify(_createNativeRequest(bid.nativeParams)); } else { bannerObj = { pos: 0, @@ -268,12 +641,19 @@ function _createImpressionObject(bid, conf) { sizes = sizes.splice(1, sizes.length - 1); var format = []; sizes.forEach(size => { - format.push({w: size[0], h: size[1]}); + format.push({ + w: size[0], + h: size[1] + }); }); bannerObj.format = format; } impObj.banner = bannerObj; } + if (isInvalidNativeRequest && impObj.hasOwnProperty('native')) { + utils.logWarn(BIDDER_CODE + ': Call to OpenBid will not be sent for native ad unit as it does not contain required valid native params.' + JSON.stringify(bid) + ' Refer:' + PREBID_NATIVE_HELP_LINK); + return; + } return impObj; } @@ -295,15 +675,13 @@ function _handleDigitrustId(eids) { if (digiTrustId !== null) { eids.push({ 'source': 'digitru.st', - 'uids': [ - { - 'id': digiTrustId.id || '', - 'atype': 1, - 'ext': { - 'keyv': parseInt(digiTrustId.keyv) || 0 - } + 'uids': [{ + 'id': digiTrustId.id || '', + 'atype': 1, + 'ext': { + 'keyv': parseInt(digiTrustId.keyv) || 0 } - ] + }] }); } } @@ -313,15 +691,13 @@ function _handleTTDId(eids) { if (adsrvrOrgId && utils.isStr(adsrvrOrgId.TDID)) { eids.push({ 'source': 'adserver.org', - 'uids': [ - { - 'id': adsrvrOrgId.TDID, - 'atype': 1, - 'ext': { - 'rtiPartner': 'TDID' - } + 'uids': [{ + 'id': adsrvrOrgId.TDID, + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' } - ] + }] }); } } @@ -335,9 +711,71 @@ function _handleEids(payload) { } } +function _parseNativeResponse(bid, newBid) { + newBid.native = {}; + if (bid.hasOwnProperty('adm')) { + var adm = ''; + try { + adm = JSON.parse(bid.adm.replace(/\\/g, '')); + } catch (ex) { + utils.logWarn(BIDDER_CODE + ' Error: Cannot parse native reponse 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_ASSET_ID.TITLE: + newBid.native.title = adm.native.assets[i].title && adm.native.assets[i].title.text; + break; + case NATIVE_ASSET_ID.IMAGE: + 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_ASSET_ID.ICON: + 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_ASSET_ID.SPONSOREDBY: + case NATIVE_ASSET_ID.BODY: + case NATIVE_ASSET_ID.LIKES: + case NATIVE_ASSET_ID.DOWNLOADS: + case NATIVE_ASSET_ID.PRICE: + case NATIVE_ASSET_ID.SALEPRICE: + case NATIVE_ASSET_ID.PHONE: + case NATIVE_ASSET_ID.ADDRESS: + case NATIVE_ASSET_ID.DESC2: + case NATIVE_ASSET_ID.CTA: + case NATIVE_ASSET_ID.RATING: + case NATIVE_ASSET_ID.DISPLAYURL: + // Remove Redundant code + newBid.native[NATIVE_ASSET_REVERSE_ID[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 || []; + if (!newBid.width) { + newBid.width = DEFAULT_WIDTH; + } + if (!newBid.height) { + newBid.height = DEFAULT_HEIGHT; + } + } + } +} + export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO], + supportedMediaTypes: [BANNER, VIDEO, NATIVE], /** * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid * @@ -347,17 +785,17 @@ export const spec = { isBidRequestValid: bid => { if (bid && bid.params) { if (!utils.isStr(bid.params.publisherId)) { - utils.logWarn(BIDDER_CODE + ' Error: publisherId is mandatory and cannot be numeric. Call to OpenBid will not be sent.'); + utils.logWarn(BIDDER_CODE + ' Error: publisherId is mandatory and cannot be numeric. Call to OpenBid will not be sent for ad unit: ' + JSON.stringify(bid)); return false; } if (!utils.isStr(bid.params.adSlot)) { - utils.logWarn(BIDDER_CODE + ': adSlotId is mandatory and cannot be numeric. Call to OpenBid will not be sent.'); + utils.logWarn(BIDDER_CODE + ': adSlotId is mandatory and cannot be numeric. Call to OpenBid will not be sent for ad unit: ' + JSON.stringify(bid)); return false; } // video ad validation if (bid.params.hasOwnProperty('video')) { if (!bid.params.video.hasOwnProperty('mimes') || !utils.isArray(bid.params.video.mimes) || bid.params.video.mimes.length === 0) { - utils.logWarn(BIDDER_CODE + ': For video ads, mimes is mandatory and must specify atlease 1 mime value. Call to OpenBid will not be sent.'); + utils.logWarn(BIDDER_CODE + ': For video ads, mimes is mandatory and must specify atlease 1 mime value. Call to OpenBid will not be sent for ad unit:' + JSON.stringify(bid)); return false; } } @@ -367,13 +805,17 @@ export const spec = { }, /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @return ServerRequest Info describing the request to the server. - */ + * 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) => { - var conf = _initConf(); + var refererInfo; + if (bidderRequest && bidderRequest.refererInfo) { + refererInfo = bidderRequest.refererInfo; + } + var conf = _initConf(refererInfo); var payload = _createOrtbTemplate(conf); var bidCurrency = ''; var dctr = ''; @@ -385,12 +827,12 @@ export const spec = { _parseAdSlot(bid); if (bid.params.hasOwnProperty('video')) { if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex)) { - utils.logWarn(BIDDER_CODE + ': Skipping the non-standard adslot: ', bid.params.adSlot, bid); + utils.logWarn(BIDDER_CODE + ': Skipping the non-standard adslot: ', bid.params.adSlot, JSON.stringify(bid)); return; } } else { if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height)) { - utils.logWarn(BIDDER_CODE + ': Skipping the non-standard adslot: ', bid.params.adSlot, bid); + utils.logWarn(BIDDER_CODE + ': Skipping the non-standard adslot: ', bid.params.adSlot, JSON.stringify(bid)); return; } } @@ -407,7 +849,10 @@ export const spec = { if (bid.params.hasOwnProperty('dctr') && utils.isStr(bid.params.dctr)) { dctrArr.push(bid.params.dctr); } - payload.imp.push(_createImpressionObject(bid, conf)); + var impObj = _createImpressionObject(bid, conf); + if (impObj) { + payload.imp.push(impObj); + } }); if (payload.imp.length == 0) { @@ -477,7 +922,6 @@ export const spec = { } _handleEids(payload); - return { method: 'POST', url: ENDPOINT, @@ -486,11 +930,11 @@ export const spec = { }, /** - * Unpack the response from the server into a list of bids. - * - * @param {*} response 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 {*} response A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ interpretResponse: (response, request) => { const bidResponses = []; var respCur = DEFAULT_CURRENCY; @@ -500,38 +944,41 @@ export const spec = { respCur = response.body.cur || respCur; response.body.seatbid.forEach(seatbidder => { seatbidder.bid && - utils.isArray(seatbidder.bid) && - seatbidder.bid.forEach(bid => { - let newBid = { - requestId: bid.impid, - cpm: (parseFloat(bid.price) || 0).toFixed(2), - width: bid.w, - height: bid.h, - creativeId: bid.crid || bid.id, - dealId: bid.dealid, - currency: respCur, - netRevenue: NET_REVENUE, - ttl: 300, - referrer: utils.getTopWindowUrl(), - ad: bid.adm - }; - let parsedRequest = JSON.parse(request.data); - if (parsedRequest.imp && parsedRequest.imp.length > 0) { - parsedRequest.imp.forEach(req => { - if (bid.impid === req.id && req.hasOwnProperty('video')) { - newBid.mediaType = 'video'; - newBid.width = bid.hasOwnProperty('w') ? bid.w : req.video.w; - newBid.height = bid.hasOwnProperty('h') ? bid.h : req.video.h; - newBid.vastXml = bid.adm; - } - }); - } - if (bid.ext && bid.ext.deal_channel) { - newBid['dealChannel'] = dealChannelValues[bid.ext.deal_channel] || null; - } + utils.isArray(seatbidder.bid) && + seatbidder.bid.forEach(bid => { + let parsedRequest = JSON.parse(request.data); + let newBid = { + requestId: bid.impid, + cpm: (parseFloat(bid.price) || 0).toFixed(2), + width: bid.w, + height: bid.h, + creativeId: bid.crid || bid.id, + dealId: bid.dealid, + currency: respCur, + netRevenue: NET_REVENUE, + ttl: 300, + referrer: parsedRequest.site && parsedRequest.site.ref ? parsedRequest.site.ref : '', + ad: bid.adm + }; + if (parsedRequest.imp && parsedRequest.imp.length > 0) { + parsedRequest.imp.forEach(req => { + if (bid.impid === req.id && req.hasOwnProperty('video')) { + newBid.mediaType = 'video'; + newBid.width = bid.hasOwnProperty('w') ? bid.w : req.video.w; + newBid.height = bid.hasOwnProperty('h') ? bid.h : req.video.h; + newBid.vastXml = bid.adm; + } + if (bid.impid === req.id && req.hasOwnProperty('native')) { + _parseNativeResponse(bid, newBid); + } + }); + } + if (bid.ext && bid.ext.deal_channel) { + newBid['dealChannel'] = dealChannelValues[bid.ext.deal_channel] || null; + } - bidResponses.push(newBid); - }); + bidResponses.push(newBid); + }); }); } } catch (error) { @@ -541,8 +988,8 @@ export const spec = { }, /** - * Register User Sync. - */ + * Register User Sync. + */ getUserSyncs: (syncOptions, responses, gdprConsent) => { let syncurl = USYNCURL + publisherId; @@ -568,7 +1015,7 @@ export const spec = { * @param {Boolean} isOpenRtb boolean to check openrtb2 protocol * @return {Object} params bid params */ - transformBidParams: function(params, isOpenRtb) { + transformBidParams: function (params, isOpenRtb) { return utils.convertTypes({ 'publisherId': 'string', 'adSlot': 'string' diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 3f28d4586e7..60c45bfd8a9 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -10,7 +10,7 @@ Maintainer: header-bidding@pubmatic.com Connects to PubMatic exchange for bids. -PubMatic bid adapter supports Video and Banner currently. +PubMatic bid adapter supports Video, Banner and Native currently. # Sample Banner Ad Unit: For Publishers ``` @@ -76,7 +76,40 @@ var adVideoAdUnits = [ }] ``` -### Configuration +# Sample Native Ad Unit: For Publishers +``` +var adUnits = [ +{ + code: 'test-div', + mediaTypes: { + native: { + image: { + required: true, + sizes: [150, 50] + }, + title: { + required: true, + len: 80 + }, + sponsoredBy: { + required: true + }, + clickUrl: { + required: true + } + } + }, + bids: [{ + bidder: 'pubmatic', + params: { + publisherId: '156295', // required + adSlot: 'pubmatic_test2@1x1', // required + } + }] +}]; +``` + +# ## Configuration PubMatic recommends the UserSync configuration below. Without it, the PubMatic adapter will not able to perform user syncs, which lowers match rate and reduces monetization. diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 05aaa191207..19996be06bf 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -9,6 +9,15 @@ describe('PubMatic adapter', function () { let videoBidRequests; let multipleMediaRequests; let bidResponses; + let nativeBidRequests; + let nativeBidRequestsWithAllParams; + let nativeBidRequestsWithoutAsset; + let nativeBidRequestsWithRequiredParam; + let nativeBidResponse; + let validnativeBidImpression; + let validnativeBidImpressionWithRequiredParam; + let nativeBidImpressionWithoutRequiredParams; + let validnativeBidImpressionWithAllParams; beforeEach(function () { bidRequests = [ @@ -124,6 +133,145 @@ describe('PubMatic adapter', function () { } ]; + nativeBidRequests = [{ + code: '/19968336/prebid_native_example_1', + sizes: [ + [300, 250] + ], + mediaTypes: { + native: { + title: { + required: true, + length: 80 + }, + image: { + required: true, + sizes: [300, 250] + }, + sponsoredBy: { + required: true + } + } + }, + nativeParams: { + title: { required: true, length: 80 }, + image: { required: true, sizes: [300, 250] }, + sponsoredBy: { required: true } + }, + bidder: 'pubmatic', + params: { + publisherId: '5670', + adSlot: '/43743431/NativeAutomationPrebid@1x1', + }, + bidId: '2a5571261281d4', + requestId: 'B68287E1-DC39-4B38-9790-FE4F179739D6', + bidderRequestId: '1c56ad30b9b8ca8', + }]; + + nativeBidRequestsWithAllParams = [{ + code: '/19968336/prebid_native_example_1', + sizes: [ + [300, 250] + ], + mediaTypes: { + native: { + title: {required: true, len: 80, ext: {'title1': 'title2'}}, + icon: {required: true, sizes: [50, 50], ext: {'icon1': 'icon2'}}, + image: {required: true, sizes: [728, 90], ext: {'image1': 'image2'}, 'mimes': ['image/png', 'image/gif']}, + sponsoredBy: {required: true, len: 10, ext: {'sponsor1': 'sponsor2'}}, + body: {required: true, len: 10, ext: {'body1': 'body2'}}, + rating: {required: true, len: 10, ext: {'rating1': 'rating2'}}, + likes: {required: true, len: 10, ext: {'likes1': 'likes2'}}, + downloads: {required: true, len: 10, ext: {'downloads1': 'downloads2'}}, + price: {required: true, len: 10, ext: {'price1': 'price2'}}, + saleprice: {required: true, len: 10, ext: {'saleprice1': 'saleprice2'}}, + phone: {required: true, len: 10, ext: {'phone1': 'phone2'}}, + address: {required: true, len: 10, ext: {'address1': 'address2'}}, + desc2: {required: true, len: 10, ext: {'desc21': 'desc22'}}, + displayurl: {required: true, len: 10, ext: {'displayurl1': 'displayurl2'}} + } + }, + nativeParams: { + title: {required: true, len: 80, ext: {'title1': 'title2'}}, + icon: {required: true, sizes: [50, 50], ext: {'icon1': 'icon2'}}, + image: {required: true, sizes: [728, 90], ext: {'image1': 'image2'}, 'mimes': ['image/png', 'image/gif']}, + sponsoredBy: {required: true, len: 10, ext: {'sponsor1': 'sponsor2'}}, + body: {required: true, len: 10, ext: {'body1': 'body2'}}, + rating: {required: true, len: 10, ext: {'rating1': 'rating2'}}, + likes: {required: true, len: 10, ext: {'likes1': 'likes2'}}, + downloads: {required: true, len: 10, ext: {'downloads1': 'downloads2'}}, + price: {required: true, len: 10, ext: {'price1': 'price2'}}, + saleprice: {required: true, len: 10, ext: {'saleprice1': 'saleprice2'}}, + phone: {required: true, len: 10, ext: {'phone1': 'phone2'}}, + address: {required: true, len: 10, ext: {'address1': 'address2'}}, + desc2: {required: true, len: 10, ext: {'desc21': 'desc22'}}, + displayurl: {required: true, len: 10, ext: {'displayurl1': 'displayurl2'}} + }, + bidder: 'pubmatic', + params: { + publisherId: '5670', + adSlot: '/43743431/NativeAutomationPrebid@1x1', + }, + bidId: '2a5571261281d4', + requestId: 'B68287E1-DC39-4B38-9790-FE4F179739D6', + bidderRequestId: '1c56ad30b9b8ca8', + }]; + + nativeBidRequestsWithoutAsset = [{ + code: '/19968336/prebid_native_example_1', + sizes: [ + [300, 250] + ], + mediaTypes: { + native: { + type: 'image' + } + }, + nativeParams: { + title: { required: true }, + image: { required: true }, + sponsoredBy: { required: true }, + clickUrl: { required: true } + }, + bidder: 'pubmatic', + params: { + publisherId: '5670', + adSlot: '/43743431/NativeAutomationPrebid@1x1', + } + }]; + + nativeBidRequestsWithRequiredParam = [{ + code: '/19968336/prebid_native_example_1', + sizes: [ + [300, 250] + ], + mediaTypes: { + native: { + title: { + required: false, + length: 80 + }, + image: { + required: false, + sizes: [300, 250] + }, + sponsoredBy: { + required: true + } + } + }, + nativeParams: { + title: { required: false, length: 80 }, + image: { required: false, sizes: [300, 250] }, + sponsoredBy: { required: true } + }, + bidder: 'pubmatic', + params: { + publisherId: '5670', + adSlot: '/43743431/NativeAutomationPrebid@1x1', + } + }]; + bidResponses = { 'body': { 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', @@ -154,6 +302,52 @@ describe('PubMatic adapter', function () { }] } }; + + nativeBidResponse = { + 'body': { + 'id': '1544691825939', + 'seatbid': [{ + 'bid': [{ + 'id': 'B68287E1-DC39-4B38-9790-FE4F179739D6', + 'impid': '2a5571261281d4', + 'price': 0.01, + 'adm': "{\"native\":{\"assets\":[{\"id\":1,\"title\":{\"text\":\"Native Test Title\"}},{\"id\":2,\"img\":{\"h\":627,\"url\":\"http://stagingpub.net/native_ads/PM-Native-Ad-1200x627.png\",\"w\":1200}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":4}],\"imptrackers\":[\"http://imptracker.com/main/9bde02d0-6017-11e4-9df7-005056967c35\",\"http://172.16.4.213/AdServer/AdDisplayTrackerServlet?operId=1&pubId=5890&siteId=5892&adId=6016&adType=12&adServerId=243&kefact=0.010000&kaxefact=0.010000&kadNetFrequecy=0&kadwidth=0&kadheight=0&kadsizeid=7&kltstamp=1544692761&indirectAdId=0&adServerOptimizerId=2&ranreq=0.1&kpbmtpfact=1.000000&dcId=1&tldId=0&passback=0&svr=MADS1107&ekefact=GSQSXOLKDgBAvRnoiNj0LxtpAnNEO30u1ZI5sITloOsP7gzh&ekaxefact=GSQSXAXLDgD0fOZLCjgbnVJiyS3D65dqDkxfs2ArpC3iugXw&ekpbmtpfact=GSQSXCDLDgB5mcooOvXtCKmx7TnNDJDY2YuHFOL3o9ceoU4H&crID=campaign111&lpu=advertiserdomain.com&ucrid=273354366805642829&campaignId=16981&creativeId=0&pctr=0.000000&wDSPByrId=511&wDspId=6&wbId=0&wrId=0&wAdvID=1&isRTB=1&rtbId=C09BB577-B8C1-4C3E-A0FF-73F6F631C80A&imprId=B68287E1-DC39-4B38-9790-FE4F179739D6&oid=B68287E1-DC39-4B38-9790-FE4F179739D6&pageURL=http%3A%2F%2Ftest.com%2FTestPages%2Fnativead.html\"],\"jstracker\":\" - - - `; -}; +} /** * Returns iframe document in a browser agnostic way * @param {Object} iframe reference * @return {Object} iframe `document` reference */ -exports.getIframeDocument = function (iframe) { +export function getIframeDocument(iframe) { if (!iframe) { return; } @@ -710,24 +722,24 @@ exports.getIframeDocument = function (iframe) { doc = iframe.contentDocument; } } catch (e) { - exports.logError('Cannot get iframe document', e); + internal.logError('Cannot get iframe document', e); } return doc; -}; +} -exports.getValueString = function(param, val, defaultValue) { +export function getValueString(param, val, defaultValue) { if (val === undefined || val === null) { return defaultValue; } - if (exports.isStr(val)) { + if (isStr(val)) { return val; } - if (exports.isNumber(val)) { + if (isNumber(val)) { return val.toString(); } - exports.logWarn('Unsuported type for param: ' + param + ' required type: String'); -}; + internal.logWarn('Unsuported type for param: ' + param + ' required type: String'); +} export function uniques(value, index, arry) { return arry.indexOf(value) === index; @@ -764,7 +776,7 @@ export function getBidderCodes(adUnits = $$PREBID_GLOBAL$$.adUnits) { } export function isGptPubadsDefined() { - if (window.googletag && exports.isFn(window.googletag.pubads) && exports.isFn(window.googletag.pubads().getSlots)) { + if (window.googletag && isFn(window.googletag.pubads) && isFn(window.googletag.pubads().getSlots)) { return true; } } @@ -835,7 +847,7 @@ export function deepClone(obj) { export function inIframe() { try { - return exports.getWindowSelf() !== exports.getWindowTop(); + return internal.getWindowSelf() !== internal.getWindowTop(); } catch (e) { return true; } @@ -860,7 +872,7 @@ export function checkCookieSupport() { } } export function cookiesAreEnabled() { - if (exports.checkCookieSupport()) { + if (internal.checkCookieSupport()) { return true; } window.document.cookie = 'prebid.cookieTest'; @@ -1080,7 +1092,7 @@ export function deletePropertyFromObject(object, prop) { * @return {Object} bid */ export function removeRequestId(bid) { - return exports.deletePropertyFromObject(bid, 'requestId'); + return deletePropertyFromObject(bid, 'requestId'); } /** @@ -1115,17 +1127,17 @@ export function convertCamelToUnderscore(value) { export function transformBidderParamKeywords(keywords, paramName = 'keywords') { let arrs = []; - exports._each(keywords, (v, k) => { - if (exports.isArray(v)) { + _each(keywords, (v, k) => { + if (isArray(v)) { let values = []; - exports._each(v, (val) => { - val = exports.getValueString(paramName + '.' + k, val); + _each(v, (val) => { + val = getValueString(paramName + '.' + k, val); if (val || val === '') { values.push(val); } }); v = values; } else { - v = exports.getValueString(paramName + '.' + k, v); - if (exports.isStr(v)) { + v = getValueString(paramName + '.' + k, v); + if (isStr(v)) { v = [v]; } else { return; @@ -1157,7 +1169,7 @@ function tryConvertType(typeToConvert, value) { export function convertTypes(types, params) { Object.keys(types).forEach(key => { if (params[key]) { - if (exports.isFn(types[key])) { + if (isFn(types[key])) { params[key] = types[key](params[key]); } else { params[key] = tryConvertType(types[key], params[key]); diff --git a/src/video.js b/src/video.js index b0d03ab6377..2c1d0ec1569 100644 --- a/src/video.js +++ b/src/video.js @@ -1,4 +1,4 @@ -import { videoAdapters } from './adaptermanager'; +import adapterManager from './adapterManager'; import { getBidRequest, deepAccess, logError } from './utils'; import { config } from '../src/config'; import includes from 'core-js/library/fn/array/includes'; @@ -14,7 +14,7 @@ export const videoAdUnit = adUnit => { const mediaTypes = deepAccess(adUnit, 'mediaTypes.video'); return mediaType || mediaTypes; }; -export const videoBidder = bid => includes(videoAdapters, bid.bidder); +export const videoBidder = bid => includes(adapterManager.videoAdapters, bid.bidder); export const hasNonVideoBidder = adUnit => adUnit.bids.filter(bid => !videoBidder(bid)).length; diff --git a/test/fixtures/allAdapters.js b/test/fixtures/allAdapters.js deleted file mode 100644 index e2baa12cd10..00000000000 --- a/test/fixtures/allAdapters.js +++ /dev/null @@ -1,3 +0,0 @@ -exports.getAllAdaptersString = function () { - return `var AardvarkAdapter = require(\'./adapters/aardvark.js\');\n exports.registerBidAdapter(new AardvarkAdapter(), \'aardvark\');\nvar AdbladeAdapter = require(\'./adapters/adblade.js\');\n exports.registerBidAdapter(new AdbladeAdapter(), \'adblade\');\nvar AdbutlerAdapter = require(\'./adapters/adbutler.js\');\n exports.registerBidAdapter(new AdbutlerAdapter(), \'adbutler\');\nvar AdequantAdapter = require(\'./adapters/adequant.js\');\n exports.registerBidAdapter(new AdequantAdapter(), \'adequant\');\nvar AdformAdapter = require(\'./adapters/adform.js\');\n exports.registerBidAdapter(new AdformAdapter(), \'adform\');\nvar AdmediaAdapter = require(\'./adapters/admedia.js\');\n exports.registerBidAdapter(new AdmediaAdapter(), \'admedia\');\nvar AolAdapter = require(\'./adapters/aol.js\');\n exports.registerBidAdapter(new AolAdapter(), \'aol\');\nvar AppnexusAdapter = require(\'./adapters/appnexus.js\');\n exports.registerBidAdapter(new AppnexusAdapter(), \'appnexus\');\nvar AppnexusAstAdapter = require(\'./adapters/appnexusAst.js\');\n exports.registerBidAdapter(new AppnexusAstAdapter(), \'appnexusAst\');\nvar GetintentAdapter = require(\'./adapters/getintent.js\');\n exports.registerBidAdapter(new GetintentAdapter(), \'getintent\');\nvar HiromediaAdapter = require(\'./adapters/hiromedia.js\');\n exports.registerBidAdapter(new HiromediaAdapter(), \'hiromedia\');\nvar IndexExchangeAdapter = require(\'./adapters/indexExchange.js\');\n exports.registerBidAdapter(new IndexExchangeAdapter(), \'indexExchange\');\nvar KruxlinkAdapter = require(\'./adapters/kruxlink.js\');\n exports.registerBidAdapter(new KruxlinkAdapter(), \'kruxlink\');\nvar KomoonaAdapter = require(\'./adapters/komoona.js\');\n exports.registerBidAdapter(new KomoonaAdapter(), \'komoona\');\nvar OpenxAdapter = require(\'./adapters/openx.js\');\n exports.registerBidAdapter(new OpenxAdapter(), \'openx\');\nvar PiximediaAdapter = require(\'./adapters/piximedia.js\');\n exports.registerBidAdapter(new PiximediaAdapter(), \'piximedia\');\nvar PubmaticAdapter = require(\'./adapters/pubmatic.js\');\n exports.registerBidAdapter(new PubmaticAdapter(), \'pubmatic\');\nvar PulsepointAdapter = require(\'./adapters/pulsepoint.js\');\n exports.registerBidAdapter(new PulsepointAdapter(), \'pulsepoint\');\nvar RubiconAdapter = require(\'./adapters/rubicon.js\');\n exports.registerBidAdapter(new RubiconAdapter(), \'rubicon\');\nvar SonobiAdapter = require(\'./adapters/sonobi.js\');\n exports.registerBidAdapter(new SonobiAdapter(), \'sonobi\');\nvar SovrnAdapter = require(\'./adapters/sovrn.js\');\n exports.registerBidAdapter(new SovrnAdapter(), \'sovrn\');\nvar SpringserveAdapter = require(\'./adapters/springserve.js\');\n exports.registerBidAdapter(new SpringserveAdapter(), \'springserve\');\nvar ThoughtleadrAdapter = require('./adapters/thoughtleadr.js');\n exports.registerBidAdapter(new ThoughtleadrAdapter(), 'thoughtleadr');\nvar TripleliftAdapter = require(\'./adapters/triplelift.js\');\n exports.registerBidAdapter(new TripleliftAdapter(), \'triplelift\');\nvar TwengaAdapter = require(\'./adapters/twenga.js\');\n exports.registerBidAdapter(new TwengaAdapter(), \'twenga\');\nvar YieldbotAdapter = require(\'./adapters/yieldbot.js\');\n exports.registerBidAdapter(new YieldbotAdapter(), \'yieldbot\');\nvar NginadAdapter = require(\'./adapters/nginad.js\');\n exports.registerBidAdapter(new NginadAdapter(), \'nginad\');\nvar BrightcomAdapter = require(\'./adapters/brightcom.js\');\n exports.registerBidAdapter(new BrightcomAdapter(), \'brightcom\');\nvar WideorbitAdapter = require(\'./adapters/wideorbit.js\');\n exports.registerBidAdapter(new WideorbitAdapter(), \'wideorbit\');\nvar JcmAdapter = require(\'./adapters/jcm.js\');\n exports.registerBidAdapter(new JcmAdapter(), \'jcm\');\nvar UnderdogmediaAdapter = require(\'./adapters/underdogmedia.js\');\n exports.registerBidAdapter(new UnderdogmediaAdapter(), \'underdogmedia\');\nvar MemeglobalAdapter = require(\'./adapters/memeglobal.js\');\n exports.registerBidAdapter(new MemeglobalAdapter(), \'memeglobal\');\nvar CentroAdapter = require(\'./adapters/centro.js\');\n exports.registerBidAdapter(new CentroAdapter(), \'centro\');\nvar RoxotAdapter = require(\'./adapters/roxot.js\');\n exports.registerBidAdapter(new RoxotAdapter(), \'roxot\');\nexports.aliasBidAdapter(\'appnexus\',\'brealtime\');\nexports.aliasBidAdapter(\'appnexus\',\'pagescience\');\nexports.aliasBidAdapter(\'appnexus\',\'defymedia\');\nexports.videoAdapters = ["appnexusAst"];`; -}; diff --git a/test/mocks/adloaderStub.js b/test/mocks/adloaderStub.js index 45a7824e71d..9b9e62a4c3b 100644 --- a/test/mocks/adloaderStub.js +++ b/test/mocks/adloaderStub.js @@ -1,4 +1,5 @@ -const adloader = require('src/adloader'); + +import * as adloader from 'src/adloader'; let sandbox; diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 85e37ca512d..232ed04da25 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -3,6 +3,7 @@ import CONSTANTS from 'src/constants.json'; import { adjustBids } from 'src/auction'; import * as auctionModule from 'src/auction'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { createBid } from 'src/bidfactory'; import { config } from 'src/config'; import * as store from 'src/videoCache'; import * as ajaxLib from 'src/ajax'; @@ -14,9 +15,8 @@ var assert = require('assert'); // TODO refactor to use the spec files var utils = require('../../src/utils'); -var bidfactory = require('../../src/bidfactory'); var fixtures = require('../fixtures/fixtures'); -var adaptermanager = require('src/adaptermanager'); +var adapterManager = require('src/adapterManager').default; var events = require('src/events'); const BIDDER_CODE = 'sampleBidder'; @@ -332,7 +332,7 @@ describe('auctionmanager.js', function () { it('Standard bidCpmAdjustment changes the bid of any bidder', function () { const bid = Object.assign({}, - bidfactory.createBid(2), + createBid(2), fixtures.getBidResponses()[5] ); @@ -477,7 +477,7 @@ describe('auctionmanager.js', function () { describe('adjustBids', function () { it('should adjust bids if greater than zero and pass copy of bid object', function () { const bid = Object.assign({}, - bidfactory.createBid(2), + createBid(2), fixtures.getBidResponses()[5] ); @@ -534,14 +534,14 @@ describe('auctionmanager.js', function () { let makeRequestsStub; before(function () { - makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + makeRequestsStub = sinon.stub(adapterManager, 'makeBidRequests'); ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder); }); after(function () { ajaxStub.restore(); - adaptermanager.makeBidRequests.restore(); + adapterManager.makeBidRequests.restore(); }); describe('when auction timeout is 3000', function () { @@ -729,7 +729,7 @@ describe('auctionmanager.js', function () { mockBidRequest(bids[0]), mockBidRequest(bids1[0], { adUnitCode: ADUNIT_CODE1 }) ]; - let makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + let makeRequestsStub = sinon.stub(adapterManager, 'makeBidRequests'); makeRequestsStub.returns(bidRequests); ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder); @@ -737,7 +737,7 @@ describe('auctionmanager.js', function () { after(function () { ajaxStub.restore(); - adaptermanager.makeBidRequests.restore(); + adapterManager.makeBidRequests.restore(); }); beforeEach(function () { diff --git a/test/spec/modules/adgenerationBidAdapter_spec.js b/test/spec/modules/adgenerationBidAdapter_spec.js index 2cd810d7fb4..a2c8125850a 100644 --- a/test/spec/modules/adgenerationBidAdapter_spec.js +++ b/test/spec/modules/adgenerationBidAdapter_spec.js @@ -3,6 +3,7 @@ import {spec} from 'modules/adgenerationBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import {NATIVE} from 'src/mediaTypes'; import {config} from 'src/config'; +import prebid from '../../../package.json'; describe('AdgenerationAdapter', function () { const adapter = newBidder(spec); @@ -91,9 +92,9 @@ describe('AdgenerationAdapter', function () { } }; const data = { - banner: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100¤cy=JPY&pbver=%24prebid.version%24&sdkname=prebidjs&adapterver=1.0.1&imark=1&tp=http%3A%2F%2Fexample.com`, - bannerUSD: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100¤cy=USD&pbver=%24prebid.version%24&sdkname=prebidjs&adapterver=1.0.1&imark=1&tp=http%3A%2F%2Fexample.com`, - native: 'posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=1x1¤cy=JPY&pbver=%24prebid.version%24&sdkname=prebidjs&adapterver=1.0.1&tp=http%3A%2F%2Fexample.com' + banner: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100¤cy=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.0.1&imark=1&tp=http%3A%2F%2Fexample.com`, + bannerUSD: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100¤cy=USD&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.0.1&imark=1&tp=http%3A%2F%2Fexample.com`, + native: 'posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=1x1¤cy=JPY&pbver=' + prebid.version + '&sdkname=prebidjs&adapterver=1.0.1&tp=http%3A%2F%2Fexample.com' }; it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests, bidderRequest)[0]; diff --git a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js index 1291a375fc0..26fd13afd1f 100644 --- a/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js +++ b/test/spec/modules/adkernelAdnAnalyticsAdapter_spec.js @@ -1,7 +1,6 @@ import analyticsAdapter, {ExpiringQueue, getUmtSource, storage} from 'modules/adkernelAdnAnalyticsAdapter'; import {expect} from 'chai'; -import adaptermanager from 'src/adaptermanager'; -import * as ajax from 'src/ajax'; +import adapterManager from 'src/adapterManager'; import CONSTANTS from 'src/constants.json'; const events = require('../../../src/events'); @@ -189,7 +188,7 @@ describe('', function () { let timer; before(function () { - ajaxStub = sandbox.stub(ajax, 'ajax'); + ajaxStub = sandbox.stub(analyticsAdapter, 'ajaxCall'); timer = sandbox.useFakeTimers(0); }); @@ -204,12 +203,12 @@ describe('', function () { }); it('should be configurable', function () { - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'adkernelAdn', adapter: analyticsAdapter }); - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'adkernelAdn', options: { pubId: 777, @@ -254,7 +253,7 @@ describe('', function () { let ev = analyticsAdapter.context.queue.peekAll(); expect(ev).to.have.length(0); expect(ajaxStub.calledOnce).to.be.equal(true); - ev = JSON.parse(ajaxStub.firstCall.args[2]).hb_ev; + ev = JSON.parse(ajaxStub.firstCall.args[0]).hb_ev; expect(ev[3]).to.be.eql({event: 'auctionEnd', time: 0.447}); }); @@ -262,7 +261,7 @@ describe('', function () { events.emit(CONSTANTS.EVENTS.BID_WON, RESPONSE); timer.tick(4500); expect(ajaxStub.calledTwice).to.be.equal(true); - let ev = JSON.parse(ajaxStub.secondCall.args[2]).hb_ev; + let ev = JSON.parse(ajaxStub.secondCall.args[0]).hb_ev; expect(ev[0]).to.be.eql({event: 'bidWon', adapter: 'adapter', tagid: 'container-1', val: 0.015}); }); }); diff --git a/test/spec/modules/adomikAnalyticsAdapter_spec.js b/test/spec/modules/adomikAnalyticsAdapter_spec.js index cb3c30705f4..16480d746b7 100644 --- a/test/spec/modules/adomikAnalyticsAdapter_spec.js +++ b/test/spec/modules/adomikAnalyticsAdapter_spec.js @@ -1,7 +1,7 @@ import adomikAnalytics from 'modules/adomikAnalyticsAdapter'; import {expect} from 'chai'; let events = require('src/events'); -let adaptermanager = require('src/adaptermanager'); +let adapterManager = require('src/adapterManager').default; let constants = require('src/constants.json'); describe('Adomik Prebid Analytic', function () { @@ -28,7 +28,7 @@ describe('Adomik Prebid Analytic', function () { }); it('should catch all events', function (done) { - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'adomik', adapter: adomikAnalytics }); @@ -55,7 +55,7 @@ describe('Adomik Prebid Analytic', function () { } // Step 1: Initialize adapter - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'adomik', options: initOptions }); diff --git a/test/spec/modules/adxcgAnalyticsAdapter_spec.js b/test/spec/modules/adxcgAnalyticsAdapter_spec.js index dfccbf6e87e..605da3bd6bc 100644 --- a/test/spec/modules/adxcgAnalyticsAdapter_spec.js +++ b/test/spec/modules/adxcgAnalyticsAdapter_spec.js @@ -1,7 +1,7 @@ import adxcgAnalyticsAdapter from 'modules/adxcgAnalyticsAdapter'; import { expect } from 'chai'; +import adapterManager from 'src/adapterManager.js'; -let adaptermanager = require('src/adaptermanager'); let events = require('src/events'); let constants = require('src/constants.json'); @@ -159,13 +159,13 @@ describe('adxcg analytics adapter', function () { }] }; - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'adxcg', adapter: adxcgAnalyticsAdapter }); beforeEach(function () { - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'adxcg', options: initOptions }); diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index 6af8c8a4478..33e6eba42f7 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -1,5 +1,5 @@ import {setConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, allowAuction, staticConsentData} from 'modules/consentManagement'; -import {gdprDataHandler} from 'src/adaptermanager'; +import {gdprDataHandler} from 'src/adapterManager'; import * as utils from 'src/utils'; import { config } from 'src/config'; diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index 2628ed6e5c4..74453986ce1 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; import { spec } from 'modules/consumableBidAdapter'; - -var bidFactory = require('src/bidfactory.js'); +import { createBid } from 'src/bidfactory'; const ENDPOINT = 'https://e.serverbid.com/api/v2'; const SMARTSYNC_CALLBACK = 'serverbidCallBids'; @@ -208,7 +207,7 @@ describe('Consumable BidAdapter', function () { describe('interpretResponse validation', function () { it('response should have valid bidderCode', function () { let bidRequest = spec.buildRequests(REQUEST.bidRequest); - let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); + let bid = createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('consumable'); }); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 34fa111260b..90059d5a1aa 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter'; -import * as bidfactory from 'src/bidfactory'; +import { createBid } from 'src/bidfactory'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; @@ -332,7 +332,7 @@ describe('The Criteo bidding adapter', function () { }; const bids = spec.interpretResponse(response, request); expect(bids).to.have.lengthOf(2); - const prebidBids = bids.map(bid => Object.assign(bidfactory.createBid(CONSTANTS.STATUS.GOOD, request.bidRequests[0]), bid)); + const prebidBids = bids.map(bid => Object.assign(createBid(CONSTANTS.STATUS.GOOD, request.bidRequests[0]), bid)); expect(prebidBids[0].adId).to.not.equal(prebidBids[1].adId); }); }); diff --git a/test/spec/modules/eplanningAnalyticsAdapter_spec.js b/test/spec/modules/eplanningAnalyticsAdapter_spec.js index 2b10f10adf2..8609024c7d9 100644 --- a/test/spec/modules/eplanningAnalyticsAdapter_spec.js +++ b/test/spec/modules/eplanningAnalyticsAdapter_spec.js @@ -2,7 +2,7 @@ import eplAnalyticsAdapter from 'modules/eplanningAnalyticsAdapter'; import includes from 'core-js/library/fn/array/includes'; import { expect } from 'chai'; import {parse as parseURL} from 'src/url'; -let adaptermanager = require('src/adaptermanager'); +let adapterManager = require('src/adapterManager').default; let events = require('src/events'); let constants = require('src/constants.json'); @@ -75,12 +75,12 @@ describe('eplanning analytics adapter', function () { } ]; - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'eplanning', adapter: eplAnalyticsAdapter }); - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'eplanning', options: initOptions }); diff --git a/test/spec/modules/googleAnalyticsAdapter_spec.js b/test/spec/modules/googleAnalyticsAdapter_spec.js index 4260a831cad..20517f4138d 100644 --- a/test/spec/modules/googleAnalyticsAdapter_spec.js +++ b/test/spec/modules/googleAnalyticsAdapter_spec.js @@ -1,5 +1,6 @@ +import ga from 'modules/googleAnalyticsAdapter'; + var assert = require('assert'); -var ga = require('modules/googleAnalyticsAdapter'); describe('Ga', function () { describe('enableAnalytics', function () { diff --git a/test/spec/modules/inskinBidAdapter_spec.js b/test/spec/modules/inskinBidAdapter_spec.js index 24ae9321954..8a62a465a5b 100644 --- a/test/spec/modules/inskinBidAdapter_spec.js +++ b/test/spec/modules/inskinBidAdapter_spec.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; import { spec } from 'modules/inskinBidAdapter'; - -var bidFactory = require('src/bidfactory.js'); +import { createBid } from 'src/bidfactory'; const ENDPOINT = 'https://mfad.inskinad.com/api/v2'; @@ -213,7 +212,7 @@ describe('InSkin BidAdapter', function () { describe('interpretResponse validation', function () { it('response should have valid bidderCode', function () { let bidRequest = spec.buildRequests(REQUEST.bidRequest); - let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); + let bid = createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('inskin'); }); diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 3e8bc6c7f92..eb829ce552d 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -1,6 +1,5 @@ import {expect, assert} from 'chai'; import {spec} from 'modules/kargoBidAdapter'; -import {registerBidder} from 'src/adapters/bidderFactory'; import {config} from 'src/config'; describe('kargo adapter tests', function () { diff --git a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js index f7de9cd8101..60fc9bdc1ec 100644 --- a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +++ b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js @@ -3,7 +3,7 @@ import CONSTANTS from 'src/constants.json'; import { config } from 'src/config'; let events = require('src/events'); -let adaptermanager = require('src/adaptermanager'); +let adapterManager = require('src/adapterManager').default; const { EVENTS: { @@ -187,13 +187,13 @@ describe('Livewrapped analytics adapter', function () { }); describe('when handling events', function () { - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'livewrapped', adapter: livewrappedAnalyticsAdapter }); beforeEach(function () { - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'livewrapped', options: { publisherId: 'CC411485-42BC-4F92-8389-42C503EE38D7' diff --git a/test/spec/modules/my6senseBidAdapter_spec.js b/test/spec/modules/my6senseBidAdapter_spec.js index 80671305aca..d2c875dad07 100644 --- a/test/spec/modules/my6senseBidAdapter_spec.js +++ b/test/spec/modules/my6senseBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import spec from 'modules/my6senseBidAdapter'; +import { spec } from 'modules/my6senseBidAdapter'; describe('My6sense Bid adapter test', function () { let bidRequests, serverResponses; diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index cf0e9fafef1..4f7467cf9b1 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { PrebidServer as Adapter, resetSyncedStatus } from 'modules/prebidServerBidAdapter/index.js'; -import adapterManager from 'src/adaptermanager'; +import adapterManager from 'src/adapterManager'; import * as utils from 'src/utils'; import { userSync } from 'src/userSync'; import { ajax } from 'src/ajax'; diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 19996be06bf..912a6696bdd 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -446,7 +446,7 @@ describe('PubMatic adapter', function () { expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude - expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version + expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID @@ -635,7 +635,7 @@ describe('PubMatic adapter', function () { expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude - expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version + expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID @@ -1129,7 +1129,7 @@ describe('PubMatic adapter', function () { expect(data.device.geo.lon).to.equal(parseFloat(multipleMediaRequests[0].params.lon)); // Lognitude expect(data.user.geo.lat).to.equal(parseFloat(multipleMediaRequests[0].params.lat)); // Latitude expect(data.user.geo.lon).to.equal(parseFloat(multipleMediaRequests[0].params.lon)); // Lognitude - expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version + expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version expect(data.ext.wrapper.transactionId).to.equal(multipleMediaRequests[0].transactionId); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(multipleMediaRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID expect(data.ext.wrapper.profile).to.equal(parseInt(multipleMediaRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID diff --git a/test/spec/modules/pubwiseAnalyticsAdapter_spec.js b/test/spec/modules/pubwiseAnalyticsAdapter_spec.js index e7e31fccc43..b77788fff4a 100644 --- a/test/spec/modules/pubwiseAnalyticsAdapter_spec.js +++ b/test/spec/modules/pubwiseAnalyticsAdapter_spec.js @@ -1,6 +1,6 @@ import pubwiseAnalytics from 'modules/pubwiseAnalyticsAdapter'; let events = require('src/events'); -let adaptermanager = require('src/adaptermanager'); +let adapterManager = require('src/adapterManager').default; let constants = require('src/constants.json'); describe('PubWise Prebid Analytics', function () { @@ -27,12 +27,12 @@ describe('PubWise Prebid Analytics', function () { it('should catch all events', function () { sinon.spy(pubwiseAnalytics, 'track'); - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'pubwiseanalytics', adapter: pubwiseAnalytics }); - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'pubwiseanalytics', options: { site: ['test-test-test-test'] diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 4392d9603e3..5a1a905f843 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -341,18 +341,19 @@ describe('Quantcast adapter', function () { }); }); - describe('`onTimeout`', function() { - it('makes a request to the notify endpoint', function() { - const sinonSandbox = sandbox.create(); - const ajaxStub = sinonSandbox.stub(ajax, 'ajax').callsFake(function() {}); - const timeoutData = { - bidder: 'quantcast' - }; - qcSpec.onTimeout(timeoutData); - const expectedUrl = `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb_notify?type=timeout`; - ajaxStub.withArgs(expectedUrl, null, null).calledOnce.should.be.true; - ajaxStub.restore(); - sinonSandbox.restore(); - }); - }); + // can't stub ajax with es6 anymore, need to fix this + // describe('`onTimeout`', function() { + // it('makes a request to the notify endpoint', function() { + // const sinonSandbox = sandbox.create(); + // const ajaxStub = sinonSandbox.stub(ajax, 'ajax').callsFake(function() {}); + // const timeoutData = { + // bidder: 'quantcast' + // }; + // qcSpec.onTimeout(timeoutData); + // const expectedUrl = `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb_notify?type=timeout`; + // ajaxStub.withArgs(expectedUrl, null, null).calledOnce.should.be.true; + // ajaxStub.restore(); + // sinonSandbox.restore(); + // }); + // }); }); diff --git a/test/spec/modules/rivrAnalyticsAdapter_spec.js b/test/spec/modules/rivrAnalyticsAdapter_spec.js index 5bd526579ac..c2c9d0ae9e8 100644 --- a/test/spec/modules/rivrAnalyticsAdapter_spec.js +++ b/test/spec/modules/rivrAnalyticsAdapter_spec.js @@ -17,7 +17,7 @@ import { activelyWaitForBannersToRender, } from 'modules/rivrAnalyticsAdapter'; import {expect} from 'chai'; -import adaptermanager from 'src/adaptermanager'; +import adapterManager from 'src/adapterManager'; import * as ajax from 'src/ajax'; import CONSTANTS from 'src/constants.json'; @@ -59,11 +59,11 @@ describe('RIVR Analytics adapter', () => { ajaxStub = sandbox.stub(ajax, 'ajax'); sinon.stub(events, 'getEvents').returns([]); - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'rivr', adapter: analyticsAdapter }); - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'rivr', options: { clientID: RVR_CLIENT_ID_MOCK, @@ -86,7 +86,7 @@ describe('RIVR Analytics adapter', () => { }); it('enableAnalytics - should call rivraddon enableAnalytics with the correct arguments', () => { - // adaptermanager.enableAnalytics() is called in beforeEach. If just called here it doesn't seem to work. + // adapterManager.enableAnalytics() is called in beforeEach. If just called here it doesn't seem to work. const firstArgument = rivraddonsEnableAnalyticsStub.getCall(0).args[0]; const secondArgument = rivraddonsEnableAnalyticsStub.getCall(0).args[1]; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 282a8a2c369..6507747d7ad 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import adapterManager from 'src/adaptermanager'; +import adapterManager from 'src/adapterManager'; import {spec, masSizeOrdering, resetUserSync, hasVideoMediaType, FASTLANE_ENDPOINT} from 'modules/rubiconBidAdapter'; import {parse as parseQuery} from 'querystring'; import {newBidder} from 'src/adapters/bidderFactory'; diff --git a/test/spec/modules/s2sTesting_spec.js b/test/spec/modules/s2sTesting_spec.js index b2b35a585c7..34de6d9ec38 100644 --- a/test/spec/modules/s2sTesting_spec.js +++ b/test/spec/modules/s2sTesting_spec.js @@ -1,4 +1,4 @@ -import { getSourceBidderMap, calculateBidSources, getSource } from 'modules/s2sTesting'; +import s2sTesting from 'modules/s2sTesting'; import { config } from 'src/config'; import find from 'core-js/library/fn/array/find'; @@ -20,12 +20,12 @@ describe('s2sTesting', function () { mathRandomStub.restore(); }); - describe('getSource', function () { + describe('s2sTesting.getSource', function () { // helper function to set random number and get the source function getExpectedSource(randNumber, sourceWeights, sources) { // set random number for testing randomNumber = randNumber; - return getSource(sourceWeights, sources); + return s2sTesting.getSource(sourceWeights, sources); } it('returns undefined if no sources', function () { @@ -89,7 +89,7 @@ describe('s2sTesting', function () { }); }); - describe('getSourceBidderMap', function () { + describe('s2sTesting.getSourceBidderMap', function () { describe('setting source through s2sConfig', function () { beforeEach(function () { // set random number for testing @@ -102,7 +102,7 @@ describe('s2sTesting', function () { testing: false, bidderControl: {rubicon: {bidSource: {server: 1, client: 1}}} }}); - expect(getSourceBidderMap()).to.eql({ + expect(s2sTesting.getSourceBidderMap()).to.eql({ server: [], client: [] }); @@ -114,7 +114,7 @@ describe('s2sTesting', function () { testing: true, bidderControl: {rubicon: {bidSource: {server: 1, client: 1}}} }}); - expect(getSourceBidderMap()).to.eql({ + expect(s2sTesting.getSourceBidderMap()).to.eql({ server: [], client: ['rubicon'] }); @@ -126,7 +126,7 @@ describe('s2sTesting', function () { testing: true, bidderControl: {rubicon: {bidSource: {server: 4, client: 1}}} }}); - expect(getSourceBidderMap()).to.eql({ + expect(s2sTesting.getSourceBidderMap()).to.eql({ server: ['rubicon'], client: [] }); @@ -137,7 +137,7 @@ describe('s2sTesting', function () { bidders: ['rubicon'], testing: true }}); - expect(getSourceBidderMap()).to.eql({ + expect(s2sTesting.getSourceBidderMap()).to.eql({ server: ['rubicon'], client: [] }); @@ -151,7 +151,7 @@ describe('s2sTesting', function () { rubicon: {bidSource: {server: 3, client: 1}}, appnexus: {bidSource: {server: 1, client: 1}} }}}); - var serverClientBidders = getSourceBidderMap(); + var serverClientBidders = s2sTesting.getSourceBidderMap(); expect(serverClientBidders.server).to.eql(['rubicon']); expect(serverClientBidders.client).to.have.members(['appnexus']); }); @@ -171,7 +171,7 @@ describe('s2sTesting', function () { {bidder: 'rubicon', bidSource: {server: 4, client: 1}} ]} ]; - expect(getSourceBidderMap(adUnits)).to.eql({ + expect(s2sTesting.getSourceBidderMap(adUnits)).to.eql({ server: ['rubicon'], client: [] }); @@ -184,7 +184,7 @@ describe('s2sTesting', function () { {bidder: 'rubicon', bidSource: {server: 1, client: 1}} ]} ]; - expect(getSourceBidderMap(adUnits)).to.eql({ + expect(s2sTesting.getSourceBidderMap(adUnits)).to.eql({ server: [], client: ['rubicon'] }); @@ -199,7 +199,7 @@ describe('s2sTesting', function () { {bidder: 'rubicon', bidSource: {}} ]} ]; - expect(getSourceBidderMap(adUnits)).to.eql({ + expect(s2sTesting.getSourceBidderMap(adUnits)).to.eql({ server: [], client: ['rubicon'] }); @@ -215,7 +215,7 @@ describe('s2sTesting', function () { {bidder: 'appnexus', bidSource: {server: 3, client: 1}} ]} ]; - var serverClientBidders = getSourceBidderMap(adUnits); + var serverClientBidders = s2sTesting.getSourceBidderMap(adUnits); expect(serverClientBidders.server).to.eql(['appnexus']); expect(serverClientBidders.client).to.have.members(['rubicon']); // should have saved the source on the bid @@ -236,7 +236,7 @@ describe('s2sTesting', function () { {bidder: 'bidder3', bidSource: {client: 1}} ]} ]; - var serverClientBidders = getSourceBidderMap(adUnits); + var serverClientBidders = s2sTesting.getSourceBidderMap(adUnits); expect(serverClientBidders.server).to.have.members(['rubicon']); expect(serverClientBidders.server).to.not.have.members(['appnexus', 'bidder3']); expect(serverClientBidders.client).to.have.members(['rubicon', 'appnexus', 'bidder3']); @@ -259,7 +259,7 @@ describe('s2sTesting', function () { {bidder: 'bidder3', calcSource: 'server', bidSource: {client: 1}} ]} ]; - var serverClientBidders = getSourceBidderMap(adUnits); + var serverClientBidders = s2sTesting.getSourceBidderMap(adUnits); expect(serverClientBidders.server).to.have.members(['appnexus', 'bidder3']); expect(serverClientBidders.server).to.not.have.members(['rubicon']); @@ -302,7 +302,7 @@ describe('s2sTesting', function () { } }}); - var serverClientBidders = getSourceBidderMap(adUnits); + var serverClientBidders = s2sTesting.getSourceBidderMap(adUnits); expect(serverClientBidders.server).to.have.members(['rubicon', 'appnexus']); expect(serverClientBidders.client).to.have.members(['rubicon', 'appnexus']); }); diff --git a/test/spec/modules/serverbidBidAdapter_spec.js b/test/spec/modules/serverbidBidAdapter_spec.js index aa40ee31ce5..2e97c43207c 100644 --- a/test/spec/modules/serverbidBidAdapter_spec.js +++ b/test/spec/modules/serverbidBidAdapter_spec.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; import { spec } from 'modules/serverbidBidAdapter'; - -var bidFactory = require('src/bidfactory.js'); +import { createBid } from 'src/bidfactory'; const ENDPOINT = 'https://e.serverbid.com/api/v2'; const SMARTSYNC_CALLBACK = 'serverbidCallBids'; @@ -194,7 +193,7 @@ describe('Serverbid BidAdapter', function () { describe('interpretResponse validation', function () { it('response should have valid bidderCode', function () { let bidRequest = spec.buildRequests(REQUEST.bidRequest); - let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); + let bid = createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('serverbid'); }); diff --git a/test/spec/modules/sigmoidAnalyticsAdapter_spec.js b/test/spec/modules/sigmoidAnalyticsAdapter_spec.js index 0552e02383a..0dee6337e0d 100644 --- a/test/spec/modules/sigmoidAnalyticsAdapter_spec.js +++ b/test/spec/modules/sigmoidAnalyticsAdapter_spec.js @@ -1,7 +1,7 @@ import sigmoidAnalytic from 'modules/sigmoidAnalyticsAdapter'; import { expect } from 'chai'; let events = require('src/events'); -let adaptermanager = require('src/adaptermanager'); +let adapterManager = require('src/adapterManager').default; let constants = require('src/constants.json'); describe('sigmoid Prebid Analytic', function () { @@ -25,12 +25,12 @@ describe('sigmoid Prebid Analytic', function () { events.getEvents.restore(); }); it('should catch all events', function () { - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'sigmoid', adapter: sigmoidAnalytic }); - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'sigmoid', options: { publisherIds: ['test_sigmoid_prebid_analytid_publisher_id'] diff --git a/test/spec/modules/sortableBidAdapter_spec.js b/test/spec/modules/sortableBidAdapter_spec.js index 09f5b4f7514..98695f44ee0 100644 --- a/test/spec/modules/sortableBidAdapter_spec.js +++ b/test/spec/modules/sortableBidAdapter_spec.js @@ -1,10 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/sortableBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -import { REPO_AND_VERSION } from 'src/constants'; import * as utils from 'src/utils'; -const ENDPOINT = `//c.deployads.com/openrtb2/auction?src=${REPO_AND_VERSION}&host=${utils.getTopWindowLocation().host}`; +const ENDPOINT = `//c.deployads.com/openrtb2/auction?src=$$REPO_AND_VERSION$$&host=${utils.getTopWindowLocation().host}`; describe('sortableBidAdapter', function() { const adapter = newBidder(spec); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index a774aa64062..7179ec00bc3 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -1,10 +1,9 @@ import { expect } from 'chai'; import { spec, LogError } from 'modules/sovrnBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -import { REPO_AND_VERSION } from 'src/constants'; import { SSL_OP_SINGLE_ECDH_USE } from 'constants'; -const ENDPOINT = `//ap.lijit.com/rtb/bid?src=${REPO_AND_VERSION}`; +const ENDPOINT = `//ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; describe('sovrnBidAdapter', function() { const adapter = newBidder(spec); diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index f614bdbd31a..171a97bafd9 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -2,6 +2,7 @@ import { expect } from 'chai'; import { tripleliftAdapterSpec } from 'modules/tripleliftBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; +import prebid from '../../../package.json'; const ENDPOINT = document.location.protocol + '//tlx.3lift.com/header/auction?'; @@ -118,7 +119,7 @@ describe('triplelift adapter', function () { expect(url).to.be.a('string'); expect(url).to.match(/(?:tlx.3lift.com\/header\/auction)/) expect(url).to.match(/(?:lib=prebid)/) - expect(url).to.match(/(?:prebid.version)/) + expect(url).to.match(new RegExp('(?:' + prebid.version + ')')) expect(url).to.match(/(?:referrer)/); }); }); diff --git a/test/spec/modules/vubleAnalyticsAdapter_spec.js b/test/spec/modules/vubleAnalyticsAdapter_spec.js index fe84c0a6b04..841a53c6dee 100644 --- a/test/spec/modules/vubleAnalyticsAdapter_spec.js +++ b/test/spec/modules/vubleAnalyticsAdapter_spec.js @@ -1,7 +1,7 @@ import vubleAnalytics from 'modules/vubleAnalyticsAdapter'; import { expect } from 'chai'; let events = require('src/events'); -let adaptermanager = require('src/adaptermanager'); +let adapterManager = require('src/adapterManager').default; let constants = require('src/constants.json'); describe('Vuble Prebid Analytic', function () { @@ -25,12 +25,12 @@ describe('Vuble Prebid Analytic', function () { events.getEvents.restore(); }); it('should catch all events', function () { - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'vuble', adapter: vubleAnalytics }); - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'vuble', options: { pubId: 18, diff --git a/test/spec/modules/yieldbotBidAdapter_spec.js b/test/spec/modules/yieldbotBidAdapter_spec.js index 3f78d4aa688..2548bb31fdc 100644 --- a/test/spec/modules/yieldbotBidAdapter_spec.js +++ b/test/spec/modules/yieldbotBidAdapter_spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import find from 'core-js/library/fn/array/find'; import { newBidder } from 'src/adapters/bidderFactory'; -import AdapterManager from 'src/adaptermanager'; +import AdapterManager from 'src/adapterManager'; import { newAuctionManager } from 'src/auctionManager'; import * as utils from 'src/utils'; import * as urlUtils from 'src/url'; diff --git a/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js b/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js index 2239abcb33f..f6efa077f35 100644 --- a/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js +++ b/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js @@ -1,6 +1,6 @@ import yuktamediaAnalyticsAdapter from 'modules/yuktamediaAnalyticsAdapter'; import { expect } from 'chai'; -let adaptermanager = require('src/adaptermanager'); +let adapterManager = require('src/adapterManager').default; let events = require('src/events'); let constants = require('src/constants.json'); @@ -26,13 +26,13 @@ describe('YuktaMedia analytics adapter', function () { pubKey: 'ZXlKaGJHY2lPaUpJVXpJMU5pSjkuT==' }; - adaptermanager.registerAnalyticsAdapter({ + adapterManager.registerAnalyticsAdapter({ code: 'yuktamedia', adapter: yuktamediaAnalyticsAdapter }); beforeEach(function () { - adaptermanager.enableAnalytics({ + adapterManager.enableAnalytics({ provider: 'yuktamedia', options: initOptions }); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index a7b25d2524d..31209bbf9c7 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -1,6 +1,8 @@ import { expect } from 'chai'; -import AdapterManager from 'src/adaptermanager'; -import { checkBidRequestSizes } from 'src/adaptermanager'; +import adapterManager, { + gdprDataHandler, + checkBidRequestSizes +} from 'src/adapterManager'; import { getAdUnits } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; @@ -9,7 +11,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { setSizeConfig } from 'src/sizeMapping'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -var s2sTesting = require('../../../../modules/s2sTesting'); +import s2sTesting from 'modules/s2sTesting'; var events = require('../../../../src/events'); const CONFIG = { @@ -45,17 +47,17 @@ describe('adapterManager tests', function () { let orgPrebidServerAdapter; let orgRubiconAdapter; before(function () { - orgAppnexusAdapter = AdapterManager.bidderRegistry['appnexus']; - orgAdequantAdapter = AdapterManager.bidderRegistry['adequant']; - orgPrebidServerAdapter = AdapterManager.bidderRegistry['prebidServer']; - orgRubiconAdapter = AdapterManager.bidderRegistry['rubicon']; + orgAppnexusAdapter = adapterManager.bidderRegistry['appnexus']; + orgAdequantAdapter = adapterManager.bidderRegistry['adequant']; + orgPrebidServerAdapter = adapterManager.bidderRegistry['prebidServer']; + orgRubiconAdapter = adapterManager.bidderRegistry['rubicon']; }); after(function () { - AdapterManager.bidderRegistry['appnexus'] = orgAppnexusAdapter; - AdapterManager.bidderRegistry['adequant'] = orgAdequantAdapter; - AdapterManager.bidderRegistry['prebidServer'] = orgPrebidServerAdapter; - AdapterManager.bidderRegistry['rubicon'] = orgRubiconAdapter; + adapterManager.bidderRegistry['appnexus'] = orgAppnexusAdapter; + adapterManager.bidderRegistry['adequant'] = orgAdequantAdapter; + adapterManager.bidderRegistry['prebidServer'] = orgPrebidServerAdapter; + adapterManager.bidderRegistry['rubicon'] = orgRubiconAdapter; config.setConfig({s2sConfig: { enabled: false }}); }); @@ -67,12 +69,12 @@ describe('adapterManager tests', function () { beforeEach(function () { sinon.stub(utils, 'logError'); appnexusAdapterMock.callBids.reset(); - AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; + adapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; }); afterEach(function () { utils.logError.restore(); - delete AdapterManager.bidderRegistry['appnexus']; + delete adapterManager.bidderRegistry['appnexus']; }); it('should log an error if a bidder is used that does not exist', function () { @@ -85,7 +87,7 @@ describe('adapterManager tests', function () { ] }]; - let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + let bidRequests = adapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); expect(bidRequests.length).to.equal(1); expect(bidRequests[0].bidderCode).to.equal('appnexus'); sinon.assert.called(utils.logError); @@ -127,7 +129,7 @@ describe('adapterManager tests', function () { {bidder: 'appnexus', params: {placementId: 'id'}}, ] }]; - AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); + adapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(1); sinon.assert.calledOnce(appnexusAdapterMock.callBids); events.off(CONSTANTS.EVENTS.BID_REQUESTED, count); @@ -145,11 +147,11 @@ describe('adapterManager tests', function () { }); beforeEach(function () { - AdapterManager.bidderRegistry['criteo'] = criteoAdapter; + adapterManager.bidderRegistry['criteo'] = criteoAdapter; }); afterEach(function () { - delete AdapterManager.bidderRegistry['criteo']; + delete adapterManager.bidderRegistry['criteo']; }); it('should call spec\'s onTimeout callback when callTimedOutBidders is called', function () { @@ -166,7 +168,7 @@ describe('adapterManager tests', function () { adUnitCode: adUnits[0].code, auctionId: 'auctionId', }]; - AdapterManager.callTimedOutBidders(adUnits, timedOutBidders, CONFIG.timeout); + adapterManager.callTimedOutBidders(adUnits, timedOutBidders, CONFIG.timeout); sinon.assert.called(criteoSpec.onTimeout); }); }); // end callTimedOutBidders @@ -182,11 +184,11 @@ describe('adapterManager tests', function () { }); beforeEach(function () { - AdapterManager.bidderRegistry['criteo'] = criteoAdapter; + adapterManager.bidderRegistry['criteo'] = criteoAdapter; }); afterEach(function () { - delete AdapterManager.bidderRegistry['criteo']; + delete adapterManager.bidderRegistry['criteo']; }); it('should call spec\'s onBidWon callback when a bid is won', function () { @@ -199,7 +201,7 @@ describe('adapterManager tests', function () { bids }]; - AdapterManager.callBidWonBidder(bids[0].bidder, bids[0], adUnits); + adapterManager.callBidWonBidder(bids[0].bidder, bids[0], adUnits); sinon.assert.called(criteoSpec.onBidWon); }); }); // end onBidWon @@ -215,11 +217,11 @@ describe('adapterManager tests', function () { }); beforeEach(function () { - AdapterManager.bidderRegistry['criteo'] = criteoAdapter; + adapterManager.bidderRegistry['criteo'] = criteoAdapter; }); afterEach(function () { - delete AdapterManager.bidderRegistry['criteo']; + delete adapterManager.bidderRegistry['criteo']; }); it('should call spec\'s onSetTargeting callback when setTargeting is called', function () { @@ -231,7 +233,7 @@ describe('adapterManager tests', function () { sizes: [[728, 90]], bids }]; - AdapterManager.callSetTargetingBidder(bids[0].bidder, bids[0], adUnits); + adapterManager.callSetTargetingBidder(bids[0].bidder, bids[0], adUnits); sinon.assert.called(criteoSpec.onSetTargeting); }); }); // end onSetTargeting @@ -239,7 +241,7 @@ describe('adapterManager tests', function () { describe('S2S tests', function () { beforeEach(function () { config.setConfig({s2sConfig: CONFIG}); - AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; + adapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; prebidServerAdapterMock.callBids.reset(); }); @@ -381,7 +383,7 @@ describe('adapterManager tests', function () { 'start': 1462918897460 }]; - AdapterManager.callBids( + adapterManager.callBids( getAdUnits(), bidRequests, () => {}, @@ -545,7 +547,7 @@ describe('adapterManager tests', function () { 'start': 1462918897460 }]; - AdapterManager.callBids( + adapterManager.callBids( adUnits, bidRequests, () => {}, @@ -575,25 +577,25 @@ describe('adapterManager tests', function () { adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus'], bid.bidder)); return adUnit; }) - let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); - AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); + let bidRequests = adapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + adapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(1); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); }); it('should fire for simultaneous s2s and client requests', function () { - AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; + adapterManager.bidderRegistry['adequant'] = adequantAdapterMock; let adUnits = utils.deepClone(getAdUnits()).map(adUnit => { adUnit.bids = adUnit.bids.filter(bid => includes(['adequant', 'appnexus'], bid.bidder)); return adUnit; }) - let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); - AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); + let bidRequests = adapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + adapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(2); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); sinon.assert.calledOnce(adequantAdapterMock.callBids); adequantAdapterMock.callBids.reset(); - delete AdapterManager.bidderRegistry['adequant']; + delete adapterManager.bidderRegistry['adequant']; }); }); }); // end s2s tests @@ -612,8 +614,8 @@ describe('adapterManager tests', function () { } function callBids(adUnits = getTestAdUnits()) { - let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); - AdapterManager.callBids(adUnits, bidRequests, doneStub, ajaxStub); + let bidRequests = adapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + adapterManager.callBids(adUnits, bidRequests, doneStub, ajaxStub); } function checkServerCalled(numAdUnits, numBids) { @@ -641,10 +643,10 @@ describe('adapterManager tests', function () { beforeEach(function () { config.setConfig({s2sConfig: TESTING_CONFIG}); - AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; - AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; - AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; - AdapterManager.bidderRegistry['rubicon'] = rubiconAdapterMock; + adapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; + adapterManager.bidderRegistry['adequant'] = adequantAdapterMock; + adapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; + adapterManager.bidderRegistry['rubicon'] = rubiconAdapterMock; stubGetSourceBidderMap = sinon.stub(s2sTesting, 'getSourceBidderMap'); @@ -756,10 +758,10 @@ describe('adapterManager tests', function () { it('calls client and server adapters for bidders that go to both', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); var adUnits = getTestAdUnits(); - adUnits[0].bids[0].finalSource = s2sTesting.BOTH; - adUnits[0].bids[1].finalSource = s2sTesting.BOTH; - adUnits[1].bids[0].finalSource = s2sTesting.BOTH; - adUnits[1].bids[1].finalSource = s2sTesting.BOTH; + // adUnits[0].bids[0].finalSource = s2sTesting.BOTH; + // adUnits[0].bids[1].finalSource = s2sTesting.BOTH; + // adUnits[1].bids[0].finalSource = s2sTesting.BOTH; + // adUnits[1].bids[1].finalSource = s2sTesting.BOTH; callBids(adUnits); // server adapter @@ -812,9 +814,9 @@ describe('adapterManager tests', function () { let thisSpec = Object.assign(spec, { supportedMediaTypes: ['video'] }); registerBidder(thisSpec); const alias = 'aliasBidder'; - AdapterManager.aliasBidAdapter(CODE, alias); - expect(AdapterManager.bidderRegistry).to.have.property(alias); - expect(AdapterManager.videoAdapters).to.include(alias); + adapterManager.aliasBidAdapter(CODE, alias); + expect(adapterManager.bidderRegistry).to.have.property(alias); + expect(adapterManager.videoAdapters).to.include(alias); }); }); @@ -833,8 +835,8 @@ describe('adapterManager tests', function () { testS2sConfig.bidders = ['s2sAlias']; config.setConfig({s2sConfig: testS2sConfig}); - AdapterManager.aliasBidAdapter('s2sBidder', 's2sAlias'); - expect(AdapterManager.aliasRegistry).to.have.property('s2sAlias'); + adapterManager.aliasBidAdapter('s2sBidder', 's2sAlias'); + expect(adapterManager.aliasRegistry).to.have.property('s2sAlias'); }); it('should throw an error if alias + bidder are unknown and not part of s2sConfig.bidders', function () { @@ -842,9 +844,9 @@ describe('adapterManager tests', function () { testS2sConfig.bidders = ['s2sAlias']; config.setConfig({s2sConfig: testS2sConfig}); - AdapterManager.aliasBidAdapter('s2sBidder1', 's2sAlias1'); + adapterManager.aliasBidAdapter('s2sBidder1', 's2sAlias1'); sinon.assert.calledOnce(utils.logError); - expect(AdapterManager.aliasRegistry).to.not.have.property('s2sAlias1'); + expect(adapterManager.aliasRegistry).to.not.have.property('s2sAlias1'); }); }); }); @@ -861,7 +863,7 @@ describe('adapterManager tests', function () { it('should make separate bidder request objects for each bidder', () => { adUnits = [utils.deepClone(getAdUnits()[0])]; - let bidRequests = AdapterManager.makeBidRequests( + let bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), @@ -890,7 +892,7 @@ describe('adapterManager tests', function () { it('setting to `random` uses shuffled order of adUnits', function () { config.setConfig({ bidderSequence: 'random' }); - let bidRequests = AdapterManager.makeBidRequests( + let bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), @@ -913,7 +915,7 @@ describe('adapterManager tests', function () { }); it('should not filter bids w/ no labels', function () { - let bidRequests = AdapterManager.makeBidRequests( + let bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), @@ -949,7 +951,7 @@ describe('adapterManager tests', function () { 'labels': ['tablet', 'phone'] }]); - let bidRequests = AdapterManager.makeBidRequests( + let bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), @@ -972,7 +974,7 @@ describe('adapterManager tests', function () { 'labels': ['tablet', 'phone'] }]); - bidRequests = AdapterManager.makeBidRequests( + bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), @@ -990,7 +992,7 @@ describe('adapterManager tests', function () { adUnits[1].bids[0].labelAny = ['mobile']; adUnits[1].bids[1].labelAll = ['desktop']; - let bidRequests = AdapterManager.makeBidRequests( + let bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), @@ -1015,7 +1017,7 @@ describe('adapterManager tests', function () { TESTING_CONFIG.bidders = ['appnexus', 'rubicon']; config.setConfig({ s2sConfig: TESTING_CONFIG }); - let bidRequests = AdapterManager.makeBidRequests( + let bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), @@ -1035,12 +1037,12 @@ describe('adapterManager tests', function () { describe('gdpr consent module', function () { it('inserts gdprConsent object to bidRequest only when module was enabled', function () { - AdapterManager.gdprDataHandler.setConsentData({ + gdprDataHandler.setConsentData({ consentString: 'abc123def456', consentRequired: true }); - let bidRequests = AdapterManager.makeBidRequests( + let bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), @@ -1050,9 +1052,9 @@ describe('adapterManager tests', function () { expect(bidRequests[0].gdprConsent.consentString).to.equal('abc123def456'); expect(bidRequests[0].gdprConsent.consentRequired).to.be.true; - AdapterManager.gdprDataHandler.setConsentData(null); + gdprDataHandler.setConsentData(null); - bidRequests = AdapterManager.makeBidRequests( + bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), utils.getUniqueIdentifierStr(), diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 6cc4a0b172c..5149bbd38a6 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1,5 +1,5 @@ import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; -import adaptermanager from 'src/adaptermanager'; +import adapterManager from 'src/adapterManager'; import * as ajax from 'src/ajax'; import { expect } from 'chai'; import { STATUS } from 'src/constants'; @@ -534,8 +534,8 @@ describe('registerBidder', function () { let aliasBidAdapterStub; beforeEach(function () { - registerBidAdapterStub = sinon.stub(adaptermanager, 'registerBidAdapter'); - aliasBidAdapterStub = sinon.stub(adaptermanager, 'aliasBidAdapter'); + registerBidAdapterStub = sinon.stub(adapterManager, 'registerBidAdapter'); + aliasBidAdapterStub = sinon.stub(adapterManager, 'aliasBidAdapter'); }); afterEach(function () { diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 427ceeca74c..be5e1a93c2f 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -1,10 +1,9 @@ import { expect } from 'chai'; -import { targeting as targetingInstance } from 'src/targeting'; +import { targeting as targetingInstance, filters } from 'src/targeting'; import { config } from 'src/config'; import { getAdUnits, createBidReceived } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; import { auctionManager } from 'src/auctionManager'; -import * as targetingModule from 'src/targeting'; import * as utils from 'src/utils'; const bid1 = { @@ -133,7 +132,7 @@ describe('targeting tests', function () { amGetAdUnitsStub = sandbox.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; }); - bidExpiryStub = sandbox.stub(targetingModule, 'isBidNotExpired').returns(true); + bidExpiryStub = sandbox.stub(filters, 'isBidNotExpired').returns(true); }); describe('when hb_deal is present in bid.adserverTargeting', function () { @@ -187,13 +186,7 @@ describe('targeting tests', function () { amGetAdUnitsStub = sandbox.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; }); - bidExpiryStub = sandbox.stub(targetingModule, 'isBidNotExpired').returns(true); - }); - - afterEach(function () { - auctionManager.getBidsReceived.restore(); - auctionManager.getAdUnitCodes.restore(); - targetingModule.isBidNotExpired.restore(); + bidExpiryStub = sandbox.stub(filters, 'isBidNotExpired').returns(true); }); it('returns targetingSet correctly', function () { @@ -209,7 +202,7 @@ describe('targeting tests', function () { let bidExpiryStub; let auctionManagerStub; beforeEach(function () { - bidExpiryStub = sandbox.stub(targetingModule, 'isBidNotExpired').returns(true); + bidExpiryStub = sandbox.stub(filters, 'isBidNotExpired').returns(true); auctionManagerStub = sandbox.stub(auctionManager, 'getBidsReceived'); }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 44a37e1d161..0edec65da0b 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -9,12 +9,11 @@ import { createBidReceived } from 'test/fixtures/fixtures'; import { auctionManager, newAuctionManager } from 'src/auctionManager'; -import { targeting, newTargeting } from 'src/targeting'; +import { targeting, newTargeting, filters } from 'src/targeting'; import { config as configObj } from 'src/config'; import * as ajaxLib from 'src/ajax'; import * as auctionModule from 'src/auction'; import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; -import * as targetingModule from 'src/targeting'; import find from 'core-js/library/fn/array/find'; var assert = require('chai').assert; @@ -24,10 +23,9 @@ var urlParse = require('url-parse'); var prebid = require('src/prebid'); var utils = require('src/utils'); -// var bidmanager = require('src/bidmanager'); var bidfactory = require('src/bidfactory'); var adloader = require('test/mocks/adloaderStub'); -var adaptermanager = require('src/adaptermanager'); +var adapterManager = require('src/adapterManager').default; var events = require('src/events'); var adserver = require('src/adserver'); var CONSTANTS = require('src/constants.json'); @@ -163,12 +161,12 @@ window.apntag = { describe('Unit: Prebid Module', function () { let bidExpiryStub; before(function () { - bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').callsFake(() => true); + bidExpiryStub = sinon.stub(filters, 'isBidNotExpired').callsFake(() => true); }); after(function() { $$PREBID_GLOBAL$$.adUnits = []; - targetingModule.isBidNotExpired.restore(); + bidExpiryStub.restore(); }); describe('getAdserverTargetingForAdUnitCodeStr', function () { @@ -427,7 +425,7 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.bidderSettings = {}; currentPriceBucket = configObj.getConfig('priceGranularity'); configObj.setConfig({ priceGranularity: customConfigObject }); - sinon.stub(adaptermanager, 'makeBidRequests').callsFake(() => ([{ + sinon.stub(adapterManager, 'makeBidRequests').callsFake(() => ([{ 'bidderCode': 'appnexus', 'auctionId': '20882439e3238c', 'bidderRequestId': '331f3cf3f1d9c8', @@ -461,7 +459,7 @@ describe('Unit: Prebid Module', function () { after(function () { configObj.setConfig({ priceGranularity: currentPriceBucket }); - adaptermanager.makeBidRequests.restore(); + adapterManager.makeBidRequests.restore(); }) beforeEach(function () { @@ -692,7 +690,7 @@ describe('Unit: Prebid Module', function () { before(function () { currentPriceBucket = configObj.getConfig('priceGranularity'); - sinon.stub(adaptermanager, 'makeBidRequests').callsFake(() => ([{ + sinon.stub(adapterManager, 'makeBidRequests').callsFake(() => ([{ 'bidderCode': 'appnexus', 'auctionId': '20882439e3238c', 'bidderRequestId': '331f3cf3f1d9c8', @@ -725,7 +723,7 @@ describe('Unit: Prebid Module', function () { after(function () { configObj.setConfig({ priceGranularity: currentPriceBucket }); - adaptermanager.makeBidRequests.restore(); + adapterManager.makeBidRequests.restore(); }) afterEach(function () { @@ -948,7 +946,7 @@ describe('Unit: Prebid Module', function () { var spyLogError = null; var spyLogMessage = null; var inIframe = true; - let triggerPixelStub; + var triggerPixelStub; function pushBidResponseToAuction(obj) { adResponse = Object.assign({ @@ -988,7 +986,7 @@ describe('Unit: Prebid Module', function () { inIframe = true; sinon.stub(utils, 'inIframe').callsFake(() => inIframe); - triggerPixelStub = sinon.stub(utils, 'triggerPixel'); + triggerPixelStub = sinon.stub(utils.internal, 'triggerPixel'); }); afterEach(function () { @@ -996,7 +994,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); utils.logMessage.restore(); utils.inIframe.restore(); - utils.triggerPixel.restore(); + triggerPixelStub.restore(); }); it('should require doc and id params', function () { @@ -1142,7 +1140,7 @@ describe('Unit: Prebid Module', function () { beforeEach(function () { logMessageSpy = sinon.spy(utils, 'logMessage'); - makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + makeRequestsStub = sinon.stub(adapterManager, 'makeBidRequests'); makeRequestsStub.returns(bidRequests); xhr = sinon.useFakeXMLHttpRequest(); @@ -1165,7 +1163,7 @@ describe('Unit: Prebid Module', function () { afterEach(function () { clock.restore(); - adaptermanager.makeBidRequests.restore(); + adapterManager.makeBidRequests.restore(); auctionModule.newAuction.restore(); utils.logMessage.restore(); xhr.restore(); @@ -1413,21 +1411,21 @@ describe('Unit: Prebid Module', function () { adUnitCodes = ['adUnit-code']; configObj.setConfig({maxRequestsPerOrigin: Number.MAX_SAFE_INTEGER || 99999999}); let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); - spyCallBids = sinon.spy(adaptermanager, 'callBids'); + spyCallBids = sinon.spy(adapterManager, 'callBids'); createAuctionStub = sinon.stub(auctionModule, 'newAuction'); createAuctionStub.returns(auction); }) afterEach(function () { auctionModule.newAuction.restore(); - adaptermanager.callBids.restore(); + adapterManager.callBids.restore(); }); it('bidders that support one of the declared formats are allowed to participate', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + sinon.assert.calledOnce(adapterManager.callBids); - const spyArgs = adaptermanager.callBids.getCall(0); + const spyArgs = adapterManager.callBids.getCall(0); const biddersCalled = spyArgs.args[0][0].bids; // appnexus and sampleBidder both support banner @@ -1438,9 +1436,9 @@ describe('Unit: Prebid Module', function () { delete adUnits[0].mediaTypes.banner; $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + sinon.assert.calledOnce(adapterManager.callBids); - const spyArgs = adaptermanager.callBids.getCall(0); + const spyArgs = adapterManager.callBids.getCall(0); const biddersCalled = spyArgs.args[0][0].bids; // only appnexus supports native @@ -1489,19 +1487,19 @@ describe('Unit: Prebid Module', function () { }); beforeEach(function () { - spyCallBids = sinon.spy(adaptermanager, 'callBids'); + spyCallBids = sinon.spy(adapterManager, 'callBids'); }) afterEach(function () { - adaptermanager.callBids.restore(); + adapterManager.callBids.restore(); }) it('should callBids if a native adUnit has all native bidders', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + sinon.assert.calledOnce(adapterManager.callBids); }); - it('should call callBids function on adaptermanager', function () { + it('should call callBids function on adapterManager', function () { let adUnits = [{ code: 'adUnit-code', sizes: [[300, 250], [300, 600]], @@ -1510,7 +1508,7 @@ describe('Unit: Prebid Module', function () { ] }]; $$PREBID_GLOBAL$$.requestBids({adUnits}); - assert.ok(spyCallBids.called, 'called adaptermanager.callBids'); + assert.ok(spyCallBids.called, 'called adapterManager.callBids'); }); it('splits native type to individual native assets', function () { @@ -1523,7 +1521,7 @@ describe('Unit: Prebid Module', function () { ] }]; $$PREBID_GLOBAL$$.requestBids({adUnits}); - const spyArgs = adaptermanager.callBids.getCall(0); + const spyArgs = adapterManager.callBids.getCall(0); const nativeRequest = spyArgs.args[1][0].bids[0].nativeParams; expect(nativeRequest).to.deep.equal({ image: {required: true}, @@ -1586,7 +1584,7 @@ describe('Unit: Prebid Module', function () { }; beforeEach(function() { - spyCallBids = sinon.spy(adaptermanager, 'callBids'); + spyCallBids = sinon.spy(adapterManager, 'callBids'); auctionManagerStub = sinon.stub(auctionManager, 'createAuction'); auctionManagerStub.onCall(0).returns(auction1); auctionManagerStub.onCall(1).returns(auction2); @@ -1594,7 +1592,7 @@ describe('Unit: Prebid Module', function () { afterEach(function() { auctionManager.createAuction.restore(); - adaptermanager.callBids.restore(); + adapterManager.callBids.restore(); }); it('should not queue bid requests when a previous bid request is in process', function () { @@ -1693,11 +1691,11 @@ describe('Unit: Prebid Module', function () { }); describe('registerBidAdapter', function () { - it('should register bidAdaptor with adaptermanager', function () { - var registerBidAdapterSpy = sinon.spy(adaptermanager, 'registerBidAdapter'); + it('should register bidAdaptor with adapterManager', function () { + var registerBidAdapterSpy = sinon.spy(adapterManager, 'registerBidAdapter'); $$PREBID_GLOBAL$$.registerBidAdapter(Function, 'biddercode'); - assert.ok(registerBidAdapterSpy.called, 'called adaptermanager.registerBidAdapter'); - adaptermanager.registerBidAdapter.restore(); + assert.ok(registerBidAdapterSpy.called, 'called adapterManager.registerBidAdapter'); + adapterManager.registerBidAdapter.restore(); }); it('should catch thrown errors', function () { @@ -1738,14 +1736,14 @@ describe('Unit: Prebid Module', function () { }); describe('aliasBidder', function () { - it('should call adaptermanager.aliasBidder', function () { - const aliasBidAdapterSpy = sinon.spy(adaptermanager, 'aliasBidAdapter'); + it('should call adapterManager.aliasBidder', function () { + const aliasBidAdapterSpy = sinon.spy(adapterManager, 'aliasBidAdapter'); const bidderCode = 'testcode'; const alias = 'testalias'; $$PREBID_GLOBAL$$.aliasBidder(bidderCode, alias); - assert.ok(aliasBidAdapterSpy.calledWith(bidderCode, alias), 'called adaptermanager.aliasBidAdapterSpy'); - adaptermanager.aliasBidAdapter.restore(); + assert.ok(aliasBidAdapterSpy.calledWith(bidderCode, alias), 'called adapterManager.aliasBidAdapterSpy'); + adapterManager.aliasBidAdapter(); }); it('should log error when not passed correct arguments', function () { diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 1b4dbc1c477..df1c9b66b28 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -1,9 +1,9 @@ import { getAdServerTargeting } from 'test/fixtures/fixtures'; import { expect } from 'chai'; import CONSTANTS from 'src/constants.json'; +import * as utils from 'src/utils'; var assert = require('assert'); -var utils = require('src/utils'); describe('Utils', function () { var obj_string = 's', @@ -732,7 +732,7 @@ describe('Utils', function () { }); it('returns window.location if not in iFrame', function () { - sandbox.stub(utils, 'getWindowLocation').returns({ + sandbox.stub(utils.internal, 'getWindowLocation').returns({ href: 'https://www.google.com/', ancestorOrigins: {}, origin: 'https://www.google.com', @@ -745,10 +745,10 @@ describe('Utils', function () { hash: '' }); let windowSelfAndTopObject = { self: 'is same as top' }; - sandbox.stub(utils, 'getWindowSelf').returns( + sandbox.stub(utils.internal, 'getWindowSelf').returns( windowSelfAndTopObject ); - sandbox.stub(utils, 'getWindowTop').returns( + sandbox.stub(utils.internal, 'getWindowTop').returns( windowSelfAndTopObject ); var topWindowLocation = utils.getTopWindowLocation(); @@ -764,13 +764,13 @@ describe('Utils', function () { }); it('returns parsed dom string from ancestorOrigins if in iFrame & ancestorOrigins is populated', function () { - sandbox.stub(utils, 'getWindowSelf').returns( + sandbox.stub(utils.internal, 'getWindowSelf').returns( { self: 'is not same as top' } ); - sandbox.stub(utils, 'getWindowTop').returns( + sandbox.stub(utils.internal, 'getWindowTop').returns( { top: 'is not same as self' } ); - sandbox.stub(utils, 'getAncestorOrigins').returns('https://www.google.com/a/umich.edu/acs'); + sandbox.stub(utils.internal, 'getAncestorOrigins').returns('https://www.google.com/a/umich.edu/acs'); var topWindowLocation = utils.getTopWindowLocation(); expect(topWindowLocation).to.be.a('object'); expect(topWindowLocation.pathname).to.equal('/a/umich.edu/acs'); @@ -785,14 +785,14 @@ describe('Utils', function () { }); it('returns parsed referrer string if in iFrame but no ancestorOrigins', function () { - sandbox.stub(utils, 'getWindowSelf').returns( + sandbox.stub(utils.internal, 'getWindowSelf').returns( { self: 'is not same as top' } ); - sandbox.stub(utils, 'getWindowTop').returns( + sandbox.stub(utils.internal, 'getWindowTop').returns( { top: 'is not same as self' } ); - sandbox.stub(utils, 'getAncestorOrigins').returns(null); - sandbox.stub(utils, 'getTopFrameReferrer').returns('https://www.example.com/'); + sandbox.stub(utils.internal, 'getAncestorOrigins').returns(null); + sandbox.stub(utils.internal, 'getTopFrameReferrer').returns('https://www.example.com/'); var topWindowLocation = utils.getTopWindowLocation(); expect(topWindowLocation).to.be.a('object'); expect(topWindowLocation.href).to.equal('https://www.example.com/'); diff --git a/webpack.conf.js b/webpack.conf.js index 1048cb94386..4e082981197 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -1,5 +1,4 @@ var prebid = require('./package.json'); -var StringReplacePlugin = require('string-replace-webpack-plugin'); var path = require('path'); var webpack = require('webpack'); var helpers = require('./gulpHelpers'); @@ -40,47 +39,10 @@ module.exports = { loader: 'babel-loader', } ], - }, - { - test: /\.json$/, - loader: 'json-loader' - }, - { - test: /\.md$/, - loader: 'ignore-loader' - }, - { - test: /constants.json$/, - include: /(src)/, - loader: StringReplacePlugin.replace({ - replacements: [ - { - pattern: /%%REPO_AND_VERSION%%/g, - replacement: function (match, p1, offset, string) { - return `${prebid.repository.url.split('/')[3]}_prebid_${prebid.version}`; - } - } - ] - }) - }, - { - test: /\.js$/, - include: /(src|test|modules|integrationExamples)/, - loader: StringReplacePlugin.replace({ - replacements: [ - { - pattern: /\$\$PREBID_GLOBAL\$\$/g, - replacement: function (match, p1, offset, string) { - return prebid.globalVarName; - } - } - ] - }) } ] }, plugins: [ - new StringReplacePlugin(), new RequireEnsureWithoutJsonp(), // this plugin must be last so it can be easily removed for karma unit tests From 78f2d22ff1e84a3a25d83cf232a46375e31d49f9 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 15 Jan 2019 14:29:56 -0700 Subject: [PATCH 0940/1594] fix orbidder pathing and test (#3451) --- modules/orbidderBidAdapter.js | 12 ++++++++---- test/spec/modules/orbidderBidAdapter_spec.js | 5 ++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index 9a6cce01f4e..20ccfcfdace 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -1,6 +1,6 @@ -import {detectReferer} from 'src/refererDetection'; -import {ajax} from 'src/ajax'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import {detectReferer} from '../src/refererDetection'; +import {ajax} from '../src/ajax'; +import {registerBidder} from '../src/adapters/bidderFactory'; export const spec = { code: 'orbidder', @@ -70,7 +70,11 @@ export const spec = { const getRefererInfo = detectReferer(window); const refererInfo = getRefererInfo(); winObj.pageUrl = refererInfo.referer; - ajax(`${this.orbidderHost}/win`, null, JSON.stringify(winObj)); + spec.ajaxCall(`${this.orbidderHost}/win`, JSON.stringify(winObj)); + }, + + ajaxCall(endpoint, data) { + ajax(endpoint, null, data); } }; diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 50955404a5e..bf31a6ad7e5 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -1,7 +1,6 @@ import {expect} from 'chai'; import {spec} from 'modules/orbidderBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -import * as ajax from 'src/ajax'; describe('orbidderBidAdapter', () => { const adapter = newBidder(spec); @@ -117,7 +116,7 @@ describe('orbidderBidAdapter', () => { }; beforeEach(() => { - ajaxStub = sinon.stub(ajax, 'ajax'); + ajaxStub = sinon.stub(spec, 'ajaxCall'); }); afterEach(() => { @@ -129,7 +128,7 @@ describe('orbidderBidAdapter', () => { expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0].indexOf('https://')).to.equal(0); expect(ajaxStub.firstCall.args[0]).to.equal(`${spec.orbidderHost}/win`); - expect(ajaxStub.firstCall.args[2]).to.equal(JSON.stringify(winObj)); + expect(ajaxStub.firstCall.args[1]).to.equal(JSON.stringify(winObj)); }); }); From 42cd7ae45cbed4c2ff5a0530164f684be8fc3618 Mon Sep 17 00:00:00 2001 From: Agustin Insua Date: Tue, 15 Jan 2019 21:19:18 -0300 Subject: [PATCH 0941/1594] Update e-planning bid adapter regexp (#3445) * Add eplanningBidAdapter * Add new parameter to request * Fix sync URL parameter * Update cleanName regexp * Update tests for new cleanName --- modules/eplanningBidAdapter.js | 2 +- test/spec/modules/eplanningBidAdapter_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js index f0ea16bd070..01a956d1bd8 100644 --- a/modules/eplanningBidAdapter.js +++ b/modules/eplanningBidAdapter.js @@ -112,7 +112,7 @@ export const spec = { } function cleanName(name) { - return name.replace(/_|\.|-|\//g, '').replace(/\)\(|\(|\)/g, '_').replace(/^_+|_+$/g, ''); + return name.replace(/_|\.|-|\//g, '').replace(/\)\(|\(|\)|:/g, '_').replace(/^_+|_+$/g, ''); } function getUrlConfig(bidRequests) { if (isTestRequest(bidRequests)) { diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js index 80129a03bd2..93290229ce3 100644 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ b/test/spec/modules/eplanningBidAdapter_spec.js @@ -6,10 +6,10 @@ import * as utils from 'src/utils'; describe('E-Planning Adapter', function () { const adapter = newBidder('spec'); const CI = '12345'; - const ADUNIT_CODE = 'adunit-code'; + const ADUNIT_CODE = 'adunit-co:de'; const ADUNIT_CODE2 = 'adunit-code-dos'; const CLEAN_ADUNIT_CODE2 = 'adunitcodedos'; - const CLEAN_ADUNIT_CODE = 'adunitcode'; + const CLEAN_ADUNIT_CODE = 'adunitco_de'; const BID_ID = '123456789'; const BID_ID2 = '987654321'; const CPM = 1.3; From d626c7393ae1ff6cb1bade195d0126d173b579b1 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Wed, 16 Jan 2019 12:00:43 +0000 Subject: [PATCH 0942/1594] Tests: ensure 12:00:00 hour part on fake timestamp (#3452) --- test/spec/modules/currency_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index 64c966bdf18..c7342c2971d 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -34,7 +34,7 @@ describe('currency', function () { describe('setConfig', function () { beforeEach(function() { sandbox = sinon.sandbox.create(); - clock = sinon.useFakeTimers(1047010195974); + clock = sinon.useFakeTimers(1046952000000); // 2003-03-06T12:00:00Z }); afterEach(function () { From 4f88aa6323d6b47cc55a804e1241ba0797c99d9f Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 16 Jan 2019 09:26:09 -0700 Subject: [PATCH 0943/1594] pass esModules flag for istanbul-instrumenter-loader --- karma.conf.maker.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 6073ee2585a..649a13a16fc 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -20,7 +20,10 @@ function newWebpackConfig(codeCoverage) { webpackConfig.module.rules.push({ enforce: 'post', exclude: /(node_modules)|(test)|(integrationExamples)|(build)|polyfill.js|(src\/adapters\/analytics\/ga.js)/, - loader: 'istanbul-instrumenter-loader', + use: { + loader: 'istanbul-instrumenter-loader', + options: { esModules: true } + }, test: /\.js$/ }) } From 55a56d0ba742d17e88f23784fd2bc9cef6eb9844 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Wed, 16 Jan 2019 13:20:12 -0600 Subject: [PATCH 0944/1594] Prebid 1.38.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 328bb91cdf4..a14761f5c51 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.38.0-pre", + "version": "1.38.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 92bfb2904e2633c5da3fd78386f67d82488f490a Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Wed, 16 Jan 2019 14:07:03 -0600 Subject: [PATCH 0945/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a14761f5c51..8170092153a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.38.0", + "version": "1.39.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 53517d342c8b51309584aeccb64e89a3e65533e2 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 18 Jan 2019 11:01:21 -0700 Subject: [PATCH 0946/1594] Bid caching flag (#3402) * remove comment that isn't relevant anymore. tll in targeting code * bid caching option added (default on) * fix typo in config name --- src/auctionManager.js | 3 --- src/config.js | 9 ++++++++ src/prebid.js | 1 + src/targeting.js | 13 ++++++++++- test/spec/unit/core/targeting_spec.js | 31 +++++++++++++++++++++++++++ test/spec/unit/pbjs_api_spec.js | 23 ++++++++++++++++++++ 6 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/auctionManager.js b/src/auctionManager.js index 67f402118e0..15567f24a88 100644 --- a/src/auctionManager.js +++ b/src/auctionManager.js @@ -57,9 +57,6 @@ export function newAuctionManager() { }; auctionManager.getBidsReceived = function() { - // As of now, an old bid which is not used in auction 1 can be used in auction n. - // To prevent this, bid.ttl (time to live) will be added to this logic and bid pool will also be added - // As of now none of the adapters are sending back bid.ttl return _auctions.map((auction) => { if (auction.getAuctionStatus() === AUCTION_COMPLETED) { return auction.getBidsReceived(); diff --git a/src/config.js b/src/config.js index 4e8f45d6805..d9892f5a746 100644 --- a/src/config.js +++ b/src/config.js @@ -18,6 +18,7 @@ const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; const DEFAULT_DISABLE_AJAX_TIMEOUT = false; +const DEFAULT_BID_CACHE = true; const DEFAULT_TIMEOUTBUFFER = 400; @@ -133,6 +134,14 @@ export function newConfig() { this._sendAllBids = val; }, + _useBidCache: DEFAULT_BID_CACHE, + get useBidCache() { + return this._useBidCache; + }, + set useBidCache(val) { + this._useBidCache = val; + }, + _bidderSequence: DEFAULT_BIDDER_SEQUENCE, get bidderSequence() { return this._bidderSequence; diff --git a/src/prebid.js b/src/prebid.js index a6b6e90b883..b87eace95f1 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -396,6 +396,7 @@ $$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHa } const auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout, labels}); + adUnitCodes.forEach(code => targeting.setLatestAuctionForAdUnit(code, auction.getAuctionId())); auction.callBids(); return auction; }); diff --git a/src/targeting.js b/src/targeting.js index 23b0ce630a1..e9d85c07e7d 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -53,6 +53,11 @@ export function getHighestCpmBidsFromBidPool(bidsReceived, highestCpmCallback) { export function newTargeting(auctionManager) { let targeting = {}; + let latestAuctionForAdUnit = {}; + + targeting.setLatestAuctionForAdUnit = function(adUnitCode, auctionId) { + latestAuctionForAdUnit[adUnitCode] = auctionId; + }; targeting.resetPresetTargeting = function(adUnitCode) { if (isGptPubadsDefined()) { @@ -191,7 +196,13 @@ export function newTargeting(auctionManager) { } function getBidsReceived() { - const bidsReceived = auctionManager.getBidsReceived() + let bidsReceived = auctionManager.getBidsReceived(); + + if (!config.getConfig('useBidCache')) { + bidsReceived = bidsReceived.filter(bid => latestAuctionForAdUnit[bid.adUnitCode] === bid.auctionId) + } + + bidsReceived = bidsReceived .filter(bid => bid.mediaType !== 'banner' || sizeSupported([bid.width, bid.height])) .filter(filters.isUnusedBid) .filter(filters.isBidNotExpired) diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index be5e1a93c2f..c7e1ad9e2e7 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -100,15 +100,22 @@ const bid3 = { describe('targeting tests', function () { let sandbox; let enableSendAllBids = false; + let useBidCache; beforeEach(function() { sandbox = sinon.sandbox.create(); + useBidCache = true; + // enableSendAllBids = false; + let origGetConfig = config.getConfig; sandbox.stub(config, 'getConfig').callsFake(function (key) { if (key === 'enableSendAllBids') { return enableSendAllBids; } + if (key === 'useBidCache') { + return useBidCache; + } return origGetConfig.apply(config, arguments); }); }); @@ -222,6 +229,30 @@ describe('targeting tests', function () { expect(bids[1].adId).to.equal('adid-2'); }); + it('should honor useBidCache', function() { + useBidCache = true; + + auctionManagerStub.returns([ + createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), + createBidReceived({bidder: 'appnexus', cpm: 5, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-2'}), + ]); + + let adUnitCodes = ['code-0']; + targetingInstance.setLatestAuctionForAdUnit('code-0', 2); + + let bids = targetingInstance.getWinningBids(adUnitCodes); + + expect(bids.length).to.equal(1); + expect(bids[0].adId).to.equal('adid-1'); + + useBidCache = false; + + bids = targetingInstance.getWinningBids(adUnitCodes); + + expect(bids.length).to.equal(1); + expect(bids[0].adId).to.equal('adid-2'); + }); + 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 0edec65da0b..ff9dac55029 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1361,6 +1361,29 @@ describe('Unit: Prebid Module', function () { .and.to.match(/[a-f0-9\-]{36}/i); }); + it('should notify targeting of the latest auction for each adUnit', function () { + let latestStub = sinon.stub(targeting, 'setLatestAuctionForAdUnit'); + let getAuctionStub = sinon.stub(auction, 'getAuctionId').returns(2); + + $$PREBID_GLOBAL$$.requestBids({ + adUnits: [ + { + code: 'test1', + bids: [] + }, { + code: 'test2', + bids: [] + } + ] + }); + + expect(latestStub.firstCall.calledWith('test1', 2)).to.equal(true); + expect(latestStub.secondCall.calledWith('test2', 2)).to.equal(true); + + latestStub.restore(); + getAuctionStub.restore(); + }); + it('should execute callback immediately if adUnits is empty', function () { var bidsBackHandler = function bidsBackHandlerCallback() {}; var spyExecuteCallback = sinon.spy(bidsBackHandler); From 55de0818132c348913ed3a7d1486d0dc1d4188ee Mon Sep 17 00:00:00 2001 From: devadvenue <45095351+devadvenue@users.noreply.github.com> Date: Tue, 22 Jan 2019 17:20:56 +0200 Subject: [PATCH 0947/1594] New advenue header bidding adapter (#3429) * Create advenueBidAdapter.js * Create advenueBidAdapter.md * Update pbjs_example_gpt.html Add advenue integration example * Advenue test Added test for advenue adapter * changes made * edit * edit * Syntax error corrected * Remove grunt, changed ajv version to 6.2.2 * Edit * Update package-lock.json * removed response validation * removed unused variables * Removed deprecated method * Package-lock.json deleted * https://github.com/devadvenue/Prebid.js.git deleted * del * Add package-lock.json from main repository * Delete package-lock.json * Only pushing original file resolves merge conflict * Update advenueBidAdapter.js Changed URL, used BidderRequest object * Update advenueBidAdapter_spec.js * Update package-lock.json * Update advenueBidAdapter_spec.js --- modules/advenueBidAdapter.js | 86 ++++++++++++++++ modules/advenueBidAdapter.md | 27 +++++ test/spec/modules/advenueBidAdapter_spec.js | 107 ++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 modules/advenueBidAdapter.js create mode 100644 modules/advenueBidAdapter.md create mode 100644 test/spec/modules/advenueBidAdapter_spec.js diff --git a/modules/advenueBidAdapter.js b/modules/advenueBidAdapter.js new file mode 100644 index 00000000000..3e7711cca0d --- /dev/null +++ b/modules/advenueBidAdapter.js @@ -0,0 +1,86 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'advenue'; +const URL_MULTI = '//ssp.advenuemedia.co.uk/?c=o&m=multi'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + + /** + * 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: (bid) => { + return Boolean(bid.bidId && + bid.params && + !isNaN(bid.params.placementId) && + spec.supportedMediaTypes.indexOf(bid.params.traffic) !== -1 + ); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: (validBidRequests, bidderRequest) => { + let winTop; + try { + winTop = window.top; + winTop.location.toString(); + } catch (e) { + utils.logMessage(e); + winTop = window; + }; + + const location = bidderRequest ? new URL(bidderRequest.refererInfo.referer) : winTop.location; + const placements = []; + const request = { + 'secure': (location.protocol === 'https:') ? 1 : 0, + 'deviceWidth': winTop.screen.width, + 'deviceHeight': winTop.screen.height, + 'host': location.host, + 'page': location.pathname, + 'placements': placements + }; + + for (let i = 0; i < validBidRequests.length; i++) { + const bid = validBidRequests[i]; + const params = bid.params; + placements.push({ + placementId: params.placementId, + bidId: bid.bidId, + sizes: bid.sizes, + traffic: params.traffic + }); + } + return { + method: 'POST', + url: URL_MULTI, + data: request + }; + }, + + /** + * 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: (serverResponse) => { + try { + serverResponse = serverResponse.body; + } catch (e) { + utils.logMessage(e); + }; + return serverResponse; + }, +}; + +registerBidder(spec); diff --git a/modules/advenueBidAdapter.md b/modules/advenueBidAdapter.md new file mode 100644 index 00000000000..ec5287330db --- /dev/null +++ b/modules/advenueBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +``` +Module Name: Advenue SSP Bidder Adapter +Module Type: Bidder Adapter +Maintainer: dev.advenue@gmail.com +``` + +# Description + +Module that connects to Advenue SSP demand sources + +# Test Parameters +``` + var adUnits = [{ + code: 'placementCode', + sizes: [[300, 250]], + bids: [{ + bidder: 'advenue', + params: { + placementId: 0, + traffic: 'banner' + } + }] + } + ]; +``` diff --git a/test/spec/modules/advenueBidAdapter_spec.js b/test/spec/modules/advenueBidAdapter_spec.js new file mode 100644 index 00000000000..f6ffb277bf9 --- /dev/null +++ b/test/spec/modules/advenueBidAdapter_spec.js @@ -0,0 +1,107 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/advenueBidAdapter'; + +describe('AdvenueAdapter', function () { + let bid = { + bidId: '2dd581a2b6281d', + bidder: 'advenue', + bidderRequestId: '145e1d6a7837c9', + params: { + placementId: 123, + traffic: 'banner' + }, + placementCode: 'placement_0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' + }; + + describe('isBidRequestValid', function () { + it('Should return true when placementId can be cast to a number', function () { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when placementId is not a number', function () { + bid.params.placementId = 'aaa'; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', function () { + let serverRequest = spec.buildRequests([bid]); + 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('//ssp.advenuemedia.co.uk/?c=o&m=multi'); + }); + 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', 'secure', 'host', 'page', 'placements'); + expect(data.deviceWidth).to.be.a('number'); + expect(data.deviceHeight).to.be.a('number'); + 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', 'bidId', 'traffic', 'sizes'); + 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'); + } + }); + 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 () { + let resObject = { + body: [ { + requestId: '123', + mediaType: 'banner', + cpm: 0.3, + width: 320, + height: 50, + ad: '

Hello ad

', + ttl: 1000, + creativeId: '123asd', + netRevenue: true, + currency: 'USD' + } ] + }; + let serverResponses = spec.interpretResponse(resObject); + it('Returns an array of valid server responses if response object is valid', function () { + 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'); + 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'); + } + it('Returns an empty array if invalid response is passed', function () { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); +}); From f26003dca9b36766ac90be9e2963551cfc5e85e1 Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 22 Jan 2019 15:37:12 -0500 Subject: [PATCH 0948/1594] calling for currency file even when default rates are specified (#3470) * calling for currency file even when default rates are specified * fixed broken unit tests * added unit test to check that currency file is still requested even when default rates are set --- modules/currency.js | 7 +++++- test/spec/modules/currency_spec.js | 40 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/modules/currency.js b/modules/currency.js index 67346535e50..2116e624449 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -11,6 +11,7 @@ const CURRENCY_RATE_PRECISION = 4; var bidResponseQueue = []; var conversionCache = {}; var currencyRatesLoaded = false; +var needToCallForCurrencyFile = true; var adServerCurrency = 'USD'; export var currencySupportEnabled = false; @@ -56,6 +57,7 @@ export function setConfig(config) { if (typeof config.rates === 'object') { currencyRates.conversions = config.rates; currencyRatesLoaded = true; + needToCallForCurrencyFile = false; // don't call if rates are already specified } if (typeof config.defaultRates === 'object') { @@ -122,7 +124,9 @@ function initCurrency(url) { hooks['addBidResponse'].addHook(addBidResponseHook, 100); - if (!currencyRates.conversions) { + // call for the file if we haven't already + if (needToCallForCurrencyFile) { + needToCallForCurrencyFile = false; ajax(url, { success: function (response) { @@ -150,6 +154,7 @@ function resetCurrency() { conversionCache = {}; currencySupportEnabled = false; currencyRatesLoaded = false; + needToCallForCurrencyFile = true; currencyRates = {}; bidderCurrencyDefault = {}; } diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index c7342c2971d..44816dfd078 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -55,6 +55,33 @@ describe('currency', function () { expect(currencySupportEnabled).to.equal(true); }); + it('currency file is called even when default rates are specified', function() { + // RESET to request currency file (specifically url value for this test) + setConfig({ 'adServerCurrency': undefined }); + + // DO NOT SET DEFAULT RATES, currency file should be requested + setConfig({ + 'adServerCurrency': 'JPY' + }); + fakeCurrencyFileServer.respond(); + expect(fakeCurrencyFileServer.requests.length).to.equal(1); + expect(fakeCurrencyFileServer.requests[0].url).to.equal('https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json?date=20030306'); + + // RESET to request currency file (specifically url value for this test) + setConfig({ 'adServerCurrency': undefined }); + + // SET DEFAULT RATES, currency file should STILL be requested + setConfig({ + 'adServerCurrency': 'JPY', + 'defaultRates': { + 'GBP': { 'CNY': 66, 'JPY': 132, 'USD': 264 }, + 'USD': { 'CNY': 60, 'GBP': 120, 'JPY': 240 } + } }); + fakeCurrencyFileServer.respond(); + expect(fakeCurrencyFileServer.requests.length).to.equal(2); + expect(fakeCurrencyFileServer.requests[1].url).to.equal('https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json?date=20030306'); + }); + it('date macro token $$TODAY$$ is replaced by current date (formatted as yyyymmdd)', function () { // RESET to request currency file (specifically url value for this test) setConfig({ 'adServerCurrency': undefined }); @@ -64,6 +91,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); expect(fakeCurrencyFileServer.requests[0].url).to.equal('https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json?date=20030306'); + // RESET to request currency file (specifically url value for this test) + setConfig({ 'adServerCurrency': undefined }); + // date macro should not modify 'conversionRateFile' if TOKEN is not found setConfig({ 'adServerCurrency': 'JPY', @@ -72,6 +102,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); expect(fakeCurrencyFileServer.requests[1].url).to.equal('http://test.net/currency.json?date=foobar'); + // RESET to request currency file (specifically url value for this test) + setConfig({ 'adServerCurrency': undefined }); + // date macro should replace $$TODAY$$ with date for 'conversionRateFile' is configured setConfig({ 'adServerCurrency': 'JPY', @@ -80,6 +113,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); expect(fakeCurrencyFileServer.requests[2].url).to.equal('http://test.net/currency.json?date=20030306'); + // RESET to request currency file (specifically url value for this test) + setConfig({ 'adServerCurrency': undefined }); + // MULTIPLE TOKENS used in a url is not supported. Only the TOKEN at left-most position is REPLACED setConfig({ 'adServerCurrency': 'JPY', @@ -220,6 +256,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 = { 'cpm': 1, 'currency': 'GBP' }; var innerBid; addBidResponseHook('elementId', bid, function(adCodeId, bid) { @@ -241,6 +278,9 @@ describe('currency', function () { }); it('should result in NO_BID when fromCurrency is not supported in file', function () { + // RESET to request currency file + setConfig({ 'adServerCurrency': undefined }); + fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); From b436eb672bc049277c0bb9d20fe3111099acc99d Mon Sep 17 00:00:00 2001 From: tomek-jedro <31707523+tomek-jedro@users.noreply.github.com> Date: Wed, 23 Jan 2019 06:03:58 -0800 Subject: [PATCH 0949/1594] LiveYield Analytics Adapter (#3443) * LiveYield Analytics Adapter * tests corrections * fixed getPlacementOrAdUnitCode function * corrections * paths fixed * adaptermanager import fixed * manager corrections --- modules/liveyieldAnalyticsAdapter.js | 212 ++++++++++ modules/liveyieldAnalyticsAdapter.md | 45 ++ .../modules/liveyieldAnalyticsAdapter_spec.js | 399 ++++++++++++++++++ 3 files changed, 656 insertions(+) create mode 100644 modules/liveyieldAnalyticsAdapter.js create mode 100644 modules/liveyieldAnalyticsAdapter.md create mode 100644 test/spec/modules/liveyieldAnalyticsAdapter_spec.js diff --git a/modules/liveyieldAnalyticsAdapter.js b/modules/liveyieldAnalyticsAdapter.js new file mode 100644 index 00000000000..a6ac9765957 --- /dev/null +++ b/modules/liveyieldAnalyticsAdapter.js @@ -0,0 +1,212 @@ +import adapter from '../src/AnalyticsAdapter'; +import adapterManager from '../src/adapterManager'; +import CONSTANTS from '../src/constants.json'; +import * as utils from '../src/utils'; + +const { + EVENTS: { BID_REQUESTED, BID_TIMEOUT, BID_RESPONSE, BID_WON } +} = CONSTANTS; + +const prebidVersion = '$prebid.version$'; + +const adapterConfig = { + /** Name of the `rta` function, override only when instructed. */ + rtaFunctionName: 'rta', + + /** This is optional but highly recommended. The value returned by the + * function will be used as ad impression ad unit attribute value. + * + * As such if you have placement (10293845) or ad unit codes + * (div-gpt-ad-124984-0) but you want these to be translated to meaningful + * values like 'SIDEBAR-AD-01-MOBILE' then this function shall express this + * mapping. + */ + getAdUnitName: function(placementOrAdUnitCode) { + return placementOrAdUnitCode; + }, + + /** + * Function used to extract placement/adUnitCode (depending on prebid version). + * + * The extracted value will be passed to the `getAdUnitName()` for mapping into + * human friendly value. + */ + getPlacementOrAdUnitCode: function(bid, version) { + return version[0] === '0' ? bid.placementCode : bid.adUnitCode; + } +}; + +const cpmToMicroUSD = v => (isNaN(v) ? 0 : Math.round(v * 1000)); + +const liveyield = Object.assign(adapter({ analyticsType: 'bundle' }), { + track({ eventType, args }) { + switch (eventType) { + case BID_REQUESTED: + args.bids.forEach(function(b) { + try { + window[adapterConfig.rtaFunctionName]( + 'bidRequested', + adapterConfig.getAdUnitName( + adapterConfig.getPlacementOrAdUnitCode(b, prebidVersion) + ), + args.bidderCode + ); + } catch (e) { + utils.logError(e); + } + }); + break; + case BID_RESPONSE: + var cpm = args.statusMessage === 'Bid available' ? args.cpm : null; + try { + window[adapterConfig.rtaFunctionName]( + 'addBid', + adapterConfig.getAdUnitName( + adapterConfig.getPlacementOrAdUnitCode(args, prebidVersion) + ), + args.bidder || 'unknown', + cpmToMicroUSD(cpm), + typeof args.bidder === 'undefined', + args.statusMessage !== 'Bid available' + ) + } catch (e) { + utils.logError(e); + } + break; + case BID_TIMEOUT: + window[adapterConfig.rtaFunctionName]('biddersTimeout', args); + break; + case BID_WON: + try { + const ad = adapterConfig.getAdUnitName( + adapterConfig.getPlacementOrAdUnitCode(args, prebidVersion) + ); + if (!ad) { + utils.logError('Cannot find ad by unit name: ' + + adapterConfig.getAdUnitName( + adapterConfig.getPlacementOrAdUnitCode(args, prebidVersion) + )); + break; + } + if (!args.bidderCode || !args.cpm) { + utils.logError('Bidder code or cpm is not valid'); + break; + } + window[adapterConfig.rtaFunctionName]( + 'resolveSlot', + adapterConfig.getAdUnitName( + adapterConfig.getPlacementOrAdUnitCode(args, prebidVersion) + ), + { + prebidWon: true, + prebidPartner: args.bidderCode, + prebidValue: cpmToMicroUSD(args.cpm) + } + ) + } catch (e) { + utils.logError(e); + } + break; + } + } +}); + +liveyield.originEnableAnalytics = liveyield.enableAnalytics; + +/** + * Minimal valid config: + * + * ``` + * { + * provider: 'liveyield', + * options: { + * // will be provided by the LiveYield team + * customerId: 'UUID', + * // will be provided by the LiveYield team, + * customerName: 'Customer Name', + * // do NOT use window.location.host, use constant value + * customerSite: 'Fixed Site Name', + * // this is used to be inline with GA 'sessionizer' which closes the session on midnight (EST-time). + * sessionTimezoneOffset: '-300' + * } + * } + * ``` + */ +liveyield.enableAnalytics = function(config) { + if (!config || !config.provider || config.provider !== 'liveyield') { + utils.logError('expected config.provider to equal liveyield'); + return; + } + if (!config.options) { + utils.logError('options must be defined'); + return; + } + if (!config.options.customerId) { + utils.logError('options.customerId is required'); + return; + } + if (!config.options.customerName) { + utils.logError('options.customerName is required'); + return; + } + if (!config.options.customerSite) { + utils.logError('options.customerSite is required'); + return; + } + if (!config.options.sessionTimezoneOffset) { + utils.logError('options.sessionTimezoneOffset is required'); + return; + } + Object.assign(adapterConfig, config.options); + if (typeof window[adapterConfig.rtaFunctionName] !== 'function') { + utils.logError(`Function ${adapterConfig.rtaFunctionName} is not defined.` + + `Make sure that LiveYield snippet in included before the Prebid Analytics configuration.`); + return; + } + + const additionalParams = { + customerTimezone: config.options.customerTimezone, + contentId: config.options.contentId, + contentPart: config.options.contentPart, + contentAuthor: config.options.contentAuthor, + contentTitle: config.options.contentTitle, + contentCategory: config.options.contentCategory, + contentLayout: config.options.contentLayout, + contentVariants: config.options.contentVariants, + contentTimezone: config.options.contentTimezone, + cstringDim1: config.options.cstringDim1, + cstringDim2: config.options.cstringDim2, + cintDim1: config.options.cintDim1, + cintDim2: config.options.cintDim2, + cintArrayDim1: config.options.cintArrayDim1, + cintArrayDim2: config.options.cintArrayDim2, + cuniqueStringMet1: config.options.cuniqueStringMet1, + cuniqueStringMet2: config.options.cuniqueStringMet2, + cavgIntMet1: config.options.cavgIntMet1, + cavgIntMet2: config.options.cavgIntMet2, + csumIntMet1: config.options.csumIntMet1, + csumIntMet2: config.options.csumIntMet2 + }; + + Object.keys(additionalParams).forEach( + key => additionalParams[key] == null && delete additionalParams[key] + ); + + window[adapterConfig.rtaFunctionName]( + 'create', + config.options.customerId, + config.options.customerName, + config.options.customerSite, + config.options.sessionTimezoneOffset, + additionalParams + ); + + liveyield.originEnableAnalytics(config); +}; + +adapterManager.registerAnalyticsAdapter({ + adapter: liveyield, + code: 'liveyield' +}); + +export default liveyield; diff --git a/modules/liveyieldAnalyticsAdapter.md b/modules/liveyieldAnalyticsAdapter.md new file mode 100644 index 00000000000..a5e602361a1 --- /dev/null +++ b/modules/liveyieldAnalyticsAdapter.md @@ -0,0 +1,45 @@ +# Overview + +Module Name: LiveYield Analytics Adapter + +Module Type: Analytics Adapter + +Maintainer: liveyield@pubocean.com + +# Description + +To install the LiveYield Tracker following snippet shall be added at the top of +the page. + +``` +(function(i,s,o,g,r,a,m,z){i['RTAAnalyticsObject']=r;i[r]=i[r]||function(){ +z=Array.prototype.slice.call(arguments);z.unshift(+new Date()); +(i[r].q=i[r].q||[]).push(z)},i[r].t=1,i[r].l=1*new Date();a=s.createElement(o), +m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) +})(window,document,'script','https://rta.pubocean.com/lib/pubocean-tracker.min.js','rta'); +``` + +# Test Parameters + +The LiveYield team will provide you configurations for each of your sites, it +will be similar to: + +``` +{ + provider: 'liveyield', + options: { + // will be provided by the LiveYield team + customerId: 'UUID', + // will be provided by the LiveYield team, + customerName: 'Customer Name', + // do NOT use window.location.host, use constant value + customerSite: 'Fixed Site Name', + // this is used to be inline with GA 'sessionizer' which closes the session on midnight (EST-time). + sessionTimezoneOffset: '-300' + } +} +``` + +Additional documentation and support will be provided by the LiveYield team as +part of the onboarding process. + diff --git a/test/spec/modules/liveyieldAnalyticsAdapter_spec.js b/test/spec/modules/liveyieldAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..61d9d9e5de0 --- /dev/null +++ b/test/spec/modules/liveyieldAnalyticsAdapter_spec.js @@ -0,0 +1,399 @@ +import CONSTANTS from 'src/constants.json'; +import liveyield from 'modules/liveyieldAnalyticsAdapter'; +import { expect } from 'chai'; +const events = require('src/events'); + +const { + EVENTS: { BID_REQUESTED, BID_TIMEOUT, BID_RESPONSE, BID_WON } +} = CONSTANTS; + +describe('liveyield analytics adapter', function() { + const rtaCalls = []; + + window.rta = function() { + rtaCalls.push({ callArgs: arguments }); + }; + + beforeEach(function() { + sinon.stub(events, 'getEvents').returns([]); + }); + afterEach(function() { + events.getEvents.restore(); + }); + describe('initialization', function() { + afterEach(function() { + rtaCalls.length = 0; + }); + it('it should require provider', function() { + liveyield.enableAnalytics({}); + expect(rtaCalls).to.be.empty; + }); + it('should require config.options', function() { + liveyield.enableAnalytics({ provider: 'liveyield' }); + expect(rtaCalls).to.be.empty; + }); + it('should require options.customerId', function() { + liveyield.enableAnalytics({ provider: 'liveyield', options: {} }); + expect(rtaCalls).to.be.empty; + }); + it('should require options.customerName', function() { + liveyield.enableAnalytics({ + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa' + } + }) + expect(rtaCalls).to.be.empty; + }); + it('should require options.customerSite', function() { + liveyield.enableAnalytics({ + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean' + } + }); + expect(rtaCalls).to.be.empty; + }); + it('should require options.sessionTimezoneOffset', function() { + liveyield.enableAnalytics({ + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com' + } + }); + expect(rtaCalls).to.be.empty; + }); + it("should throw error, when 'rta' function is not defined ", function() { + const keepMe = window.rta; + + delete window.rta; + + liveyield.enableAnalytics({ + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12 + } + }); + expect(rtaCalls).to.be.empty; + + window.rta = keepMe; + }); + it('should initialize when all required parameters are passed', function() { + liveyield.enableAnalytics({ + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12 + } + }); + expect(rtaCalls[0].callArgs['0']).to.match(/create/); + expect(rtaCalls[0].callArgs['1']).to.match( + /d6a6f8da-190f-47d6-ae11-f1a4469083fa/ + ); + expect(rtaCalls[0].callArgs['2']).to.match(/pubocean/); + expect(rtaCalls[0].callArgs['4']).to.match(/12/); + liveyield.disableAnalytics(); + }); + it('should allow to redefine rta function name', function() { + const keepMe = window.rta; + window.abc = keepMe; + delete window.rta; + liveyield.enableAnalytics({ + provider: 'liveyield', + options: { + rtaFunctionName: 'abc', + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'test', + customerSite: 'scribol.com', + sessionTimezoneOffset: 25 + } + }); + + liveyield.disableAnalytics(); + expect(rtaCalls[0].callArgs['0']).to.match(/create/); + expect(rtaCalls[0].callArgs['1']).to.match( + /d6a6f8da-190f-47d6-ae11-f1a4469083fa/ + ); + expect(rtaCalls[0].callArgs['2']).to.match(/test/); + expect(rtaCalls[0].callArgs['4']).to.match(/25/); + + window.rta = keepMe; + liveyield.disableAnalytics(); + }); + it('should handle custom parameters', function() { + liveyield.enableAnalytics({ + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'test2', + customerSite: 'scribol.com', + sessionTimezoneOffset: 38, + contentTitle: 'testTitle', + contentAuthor: 'testAuthor', + contentCategory: 'testCategory' + } + }); + + liveyield.disableAnalytics(); + expect(rtaCalls[0].callArgs['0']).to.match(/create/); + expect(rtaCalls[0].callArgs['2']).to.match(/test2/); + expect(rtaCalls[0].callArgs['4']).to.match(/38/); + expect(rtaCalls[0].callArgs['5'].contentTitle).to.match(/testTitle/); + expect(rtaCalls[0].callArgs['5'].contentAuthor).to.match(/testAuthor/); + expect(rtaCalls[0].callArgs['5'].contentCategory).to.match( + /testCategory/ + ); + liveyield.disableAnalytics(); + }); + }); + + describe('handling events', function() { + const options = { + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12 + } + }; + beforeEach(function() { + rtaCalls.length = 0; + liveyield.enableAnalytics(options); + }); + afterEach(function() { + liveyield.disableAnalytics(); + }); + it('should handle BID_REQUESTED event', function() { + const bidRequest = { + bidderCode: 'appnexus', + bids: [ + { + params: { + placementId: '10433394' + }, + adUnitCode: 'div-gpt-ad-1438287399331-0', + transactionId: '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', + sizes: '300x250,300x600', + bidId: '2eddfdc0c791dc', + auctionId: 'a5b849e5-87d7-4205-8300-d063084fcfb7' + } + ] + }; + + events.emit(BID_REQUESTED, bidRequest); + expect(rtaCalls[1].callArgs['0']).to.equal('bidRequested'); + expect(rtaCalls[1].callArgs['1']).to.equal('div-gpt-ad-1438287399331-0'); + expect(rtaCalls[1].callArgs['2']).to.equal('appnexus'); + }); + it('should handle BID_REQUESTED event with invalid args', function() { + const bidRequest = { + bids: [ + { + params: { + placementId: '10433394' + }, + transactionId: '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', + sizes: '300x250,300x600', + bidId: '2eddfdc0c791dc', + auctionId: 'a5b849e5-87d7-4205-8300-d063084fcf' + }, + { + params: { + placementId: '31034023' + }, + transactionId: '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', + sizes: '300x250,300x600', + bidId: '3dkg0404fmd0', + auctionId: 'a5b849e5-87d7-4205-8300-d063084fcf' + } + ] + }; + events.emit(BID_REQUESTED, bidRequest); + expect(rtaCalls[1].callArgs['0']).to.equal('bidRequested'); + expect(rtaCalls[1].callArgs['1']).to.equal(undefined); + expect(rtaCalls[1].callArgs['2']).to.equal(undefined); + expect(rtaCalls[1].callArgs['0']).to.equal('bidRequested'); + }); + it('should handle BID_RESPONSE event', function() { + const bidResponse = { + height: 250, + statusMessage: 'Bid available', + adId: '2eddfdc0c791dc', + mediaType: 'banner', + source: 'client', + requestId: '2eddfdc0c791dc', + cpm: 0.5, + creativeId: 29681110, + currency: 'USD', + netRevenue: true, + ttl: 300, + auctionId: 'a5b849e5-87d7-4205-8300-d063084fcfb7', + responseTimestamp: 1522265866110, + requestTimestamp: 1522265863600, + bidder: 'appnexus', + adUnitCode: 'div-gpt-ad-1438287399331-0', + timeToRespond: 2510, + size: '300x250' + }; + + events.emit(BID_RESPONSE, bidResponse); + expect(rtaCalls[1].callArgs['0']).to.equal('addBid'); + expect(rtaCalls[1].callArgs['1']).to.equal('div-gpt-ad-1438287399331-0'); + expect(rtaCalls[1].callArgs['2']).to.equal('appnexus'); + expect(rtaCalls[1].callArgs['3']).to.equal(500); + expect(rtaCalls[1].callArgs['4']).to.equal(false); + expect(rtaCalls[1].callArgs['5']).to.equal(false); + }); + it('should handle BID_RESPONSE event with undefined bidder and cpm', function() { + const bidResponse = { + height: 250, + statusMessage: 'Bid available', + adId: '2eddfdc0c791dc', + mediaType: 'banner', + source: 'client', + requestId: '2eddfdc0c791dc', + creativeId: 29681110, + currency: 'USD', + netRevenue: true, + ttl: 300, + auctionId: 'a5b849e5-87d7-4205-8300-d063084fcfb7', + responseTimestamp: 1522265866110, + requestTimestamp: 1522265863600, + adUnitCode: 'div-gpt-ad-1438287399331-0', + timeToRespond: 2510, + size: '300x250' + }; + events.emit(BID_RESPONSE, bidResponse); + expect(rtaCalls[1].callArgs['0']).to.equal('addBid'); + expect(rtaCalls[1].callArgs['2']).to.equal('unknown'); + expect(rtaCalls[1].callArgs['3']).to.equal(0); + expect(rtaCalls[1].callArgs['4']).to.equal(true); + }); + it('should handle BID_RESPONSE event with undefined status message and adUnitCode', function() { + const bidResponse = { + height: 250, + adId: '2eddfdc0c791dc', + mediaType: 'banner', + source: 'client', + requestId: '2eddfdc0c791dc', + cpm: 0.5, + creativeId: 29681110, + currency: 'USD', + netRevenue: true, + ttl: 300, + auctionId: 'a5b849e5-87d7-4205-8300-d063084fcfb7', + responseTimestamp: 1522265866110, + requestTimestamp: 1522265863600, + bidder: 'appnexus', + timeToRespond: 2510, + size: '300x250' + }; + events.emit(BID_RESPONSE, bidResponse); + expect(rtaCalls[1].callArgs['0']).to.equal('addBid'); + expect(rtaCalls[1].callArgs['1']).to.equal(undefined); + expect(rtaCalls[1].callArgs['3']).to.equal(0); + expect(rtaCalls[1].callArgs['5']).to.equal(true); + }); + it('should handle BID_TIMEOUT', function() { + const bidTimeout = [ + { + bidId: '2baa51527bd015', + bidder: 'bidderOne', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + }, + { + bidId: '6fe3b4c2c23092', + bidder: 'bidderTwo', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + } + ]; + events.emit(BID_TIMEOUT, bidTimeout); + expect(rtaCalls[1].callArgs['0']).to.equal('biddersTimeout'); + expect(rtaCalls[1].callArgs['1'].length).to.equal(2); + }); + it('should handle BID_WON event', function() { + const bidWon = { + adId: '4587fec4900b81', + mediaType: 'banner', + requestId: '4587fec4900b81', + cpm: 1.962, + creativeId: 2126, + currency: 'EUR', + netRevenue: true, + ttl: 302, + auctionId: '914bedad-b145-4e46-ba58-51365faea6cb', + statusMessage: 'Bid available', + responseTimestamp: 1530628534437, + requestTimestamp: 1530628534219, + bidderCode: 'testbidder4', + adUnitCode: 'div-gpt-ad-1438287399331-0', + timeToRespond: 218, + size: '300x250', + status: 'rendered' + }; + events.emit(BID_WON, bidWon); + expect(rtaCalls[1].callArgs['0']).to.equal('resolveSlot'); + expect(rtaCalls[1].callArgs['1']).to.equal( + 'div-gpt-ad-1438287399331-0' + ); + expect(rtaCalls[1].callArgs['2'].prebidWon).to.equal(true); + expect(rtaCalls[1].callArgs['2'].prebidPartner).to.equal('testbidder4'); + expect(rtaCalls[1].callArgs['2'].prebidValue).to.equal(1962); + }); + it('should throw error, invoking BID_WON event without adUnitCode', function() { + const bidWon = { + adId: '4587fec4900b81', + mediaType: 'banner', + requestId: '4587fec4900b81', + cpm: 1.962, + creativeId: 2126, + currency: 'EUR', + netRevenue: true, + ttl: 302, + auctionId: '914bedad-b145-4e46-ba58-51365faea6cb', + statusMessage: 'Bid available', + responseTimestamp: 1530628534437, + requestTimestamp: 1530628534219, + timeToRespond: 218, + bidderCode: 'testbidder4', + size: '300x250', + status: 'rendered' + }; + events.emit(BID_WON, bidWon); + expect(rtaCalls[1]).to.be.undefined; + }); + it('should throw error, invoking BID_WON event without bidderCode', function() { + const bidWon = { + adId: '4587fec4900b81', + mediaType: 'banner', + requestId: '4587fec4900b81', + cpm: 1.962, + creativeId: 2126, + currency: 'EUR', + netRevenue: true, + ttl: 302, + auctionId: '914bedad-b145-4e46-ba58-51365faea6cb', + statusMessage: 'Bid available', + responseTimestamp: 1530628534437, + requestTimestamp: 1530628534219, + adUnitCode: 'div-gpt-ad-1438287399331-0', + timeToRespond: 218, + size: '300x250', + status: 'rendered' + }; + events.emit(BID_WON, bidWon); + expect(rtaCalls[1]).to.be.undefined; + }); + }); +}); From 3cde9952130b1b8bcc5385c5fdc1b0e6e16a24f1 Mon Sep 17 00:00:00 2001 From: Denis Logachov Date: Wed, 23 Jan 2019 20:56:18 +0200 Subject: [PATCH 0950/1594] admarkup html wrapping removed (#3432) --- modules/adkernelAdnBidAdapter.js | 39 +++--- modules/adkernelBidAdapter.js | 31 ++--- .../modules/adkernelAdnBidAdapter_spec.js | 131 ++++++++++++------ test/spec/modules/adkernelBidAdapter_spec.js | 42 ++++-- 4 files changed, 157 insertions(+), 86 deletions(-) diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index 095ad6c585b..63321fb82ee 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -2,6 +2,7 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import {BANNER, VIDEO} from '../src/mediaTypes'; import includes from 'core-js/library/fn/array/includes'; +import {parse as parseUrl} from '../src/url'; const DEFAULT_ADKERNEL_DSP_DOMAIN = 'tag.adkernel.com'; const VIDEO_TARGETING = ['mimes', 'protocols', 'api']; @@ -9,8 +10,8 @@ const DEFAULT_MIMES = ['video/mp4', 'video/webm', 'application/x-shockwave-flash const DEFAULT_PROTOCOLS = [2, 3, 5, 6]; const DEFAULT_APIS = [1, 2]; -function isRtbDebugEnabled() { - return utils.getTopWindowLocation().href.indexOf('adk_debug=true') !== -1; +function isRtbDebugEnabled(refInfo) { + return refInfo.referer.indexOf('adk_debug=true') !== -1; } function buildImp(bidRequest) { @@ -18,14 +19,13 @@ function buildImp(bidRequest) { id: bidRequest.bidId, tagid: bidRequest.adUnitCode }; - if (bidRequest.mediaType === BANNER || utils.deepAccess(bidRequest, `mediaTypes.banner`) || - (bidRequest.mediaTypes === undefined && bidRequest.mediaType === undefined)) { - let sizes = canonicalizeSizesArray(bidRequest.sizes); + if (utils.deepAccess(bidRequest, `mediaTypes.banner`)) { + let sizes = canonicalizeSizesArray(bidRequest.mediaTypes.banner.sizes); imp.banner = { format: utils.parseSizesInput(sizes) } - } else if (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, `mediaTypes.video`)) { - let size = canonicalizeSizesArray(bidRequest.sizes)[0]; + } else if (utils.deepAccess(bidRequest, `mediaTypes.video`)) { + let size = canonicalizeSizesArray(bidRequest.mediaTypes.video.playerSize)[0]; imp.video = { w: size[0], h: size[1], @@ -54,11 +54,11 @@ function canonicalizeSizesArray(sizes) { return sizes; } -function buildRequestParams(tags, auctionId, transactionId, gdprConsent) { +function buildRequestParams(tags, auctionId, transactionId, gdprConsent, refInfo) { let req = { id: auctionId, tid: transactionId, - site: buildSite(), + site: buildSite(refInfo), imp: tags }; @@ -74,13 +74,15 @@ function buildRequestParams(tags, auctionId, transactionId, gdprConsent) { return req; } -function buildSite() { - let loc = utils.getTopWindowLocation(); +function buildSite(refInfo) { + let loc = parseUrl(refInfo.referer); let result = { - page: loc.href, - ref: utils.getTopWindowReferrer(), - secure: ~~(loc.protocol === 'https:') + page: `${loc.protocol}://${loc.hostname}${loc.pathname}`, + secure: ~~(loc.protocol === 'https') }; + if (self === top && document.referrer) { + result.ref = document.referrer; + } let keywords = document.getElementsByTagName('meta')['keywords']; if (keywords && keywords.content) { result.keywords = keywords.content; @@ -101,7 +103,7 @@ function buildBid(tag) { netRevenue: true }; if (tag.tag) { - bid.ad = `${tag.tag}`; + bid.ad = tag.tag; bid.mediaType = BANNER; } else if (tag.vast_url) { bid.vastUrl = tag.vast_url; @@ -117,7 +119,7 @@ export const spec = { isBidRequestValid: function(bidRequest) { return 'params' in bidRequest && (typeof bidRequest.params.host === 'undefined' || typeof bidRequest.params.host === 'string') && - typeof bidRequest.params.pubId === 'number'; + typeof bidRequest.params.pubId === 'number' && 'mediaTypes' in bidRequest && ('banner' in bidRequest.mediaTypes || 'video' in bidRequest.mediaTypes); }, buildRequests: function(bidRequests, bidderRequest) { @@ -134,13 +136,14 @@ export const spec = { let auctionId = bidderRequest.auctionId; let gdprConsent = bidderRequest.gdprConsent; let transactionId = bidderRequest.transactionId; + let refererInfo = bidderRequest.refererInfo; let requests = []; Object.keys(dispatch).forEach(host => { Object.keys(dispatch[host]).forEach(pubId => { - let request = buildRequestParams(dispatch[host][pubId], auctionId, transactionId, gdprConsent); + let request = buildRequestParams(dispatch[host][pubId], auctionId, transactionId, gdprConsent, refererInfo); requests.push({ method: 'POST', - url: `//${host}/tag?account=${pubId}&pb=1${isRtbDebugEnabled() ? '&debug=1' : ''}`, + url: `//${host}/tag?account=${pubId}&pb=1${isRtbDebugEnabled(refererInfo) ? '&debug=1' : ''}`, data: JSON.stringify(request) }) }); diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 13a89e31836..254887dad81 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -3,7 +3,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes'; import {registerBidder} from '../src/adapters/bidderFactory'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -import {parse as parseUrl} from '../src/url' +import {parse as parseUrl} from '../src/url'; const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', @@ -20,7 +20,8 @@ export const spec = { supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bidRequest) { return 'params' in bidRequest && typeof bidRequest.params.host !== 'undefined' && - 'zoneId' in bidRequest.params && !isNaN(Number(bidRequest.params.zoneId)); + 'zoneId' in bidRequest.params && !isNaN(Number(bidRequest.params.zoneId)) && + bidRequest.mediaTypes && (bidRequest.mediaTypes.banner || bidRequest.mediaTypes.video); }, buildRequests: function(bidRequests, bidderRequest) { let impDispatch = dispatchImps(bidRequests, bidderRequest.refererInfo); @@ -31,14 +32,9 @@ export const spec = { Object.keys(impDispatch[host]).forEach(zoneId => { const request = buildRtbRequest(impDispatch[host][zoneId], auctionId, gdprConsent, bidderRequest.refererInfo); requests.push({ - method: 'GET', - url: `${window.location.protocol}//${host}/rtbg`, - data: { - zone: Number(zoneId), - ad_type: 'rtb', - v: VERSION, - r: JSON.stringify(request) - } + method: 'POST', + url: `${window.location.protocol}//${host}/hb?zone=${Number(zoneId)}&v=${VERSION}`, + data: JSON.stringify(request) }); }); }); @@ -50,7 +46,7 @@ export const spec = { return []; } - let rtbRequest = JSON.parse(request.data.r); + let rtbRequest = JSON.parse(request.data); let rtbImps = rtbRequest.imp; let rtbBids = response.seatbid .map(seatbid => seatbid.bid) @@ -120,15 +116,14 @@ function buildImp(bidRequest, secure) { 'tagid': bidRequest.adUnitCode }; - if (bidRequest.mediaType === BANNER || utils.deepAccess(bidRequest, `mediaTypes.banner`) || - (bidRequest.mediaTypes === undefined && bidRequest.mediaType === undefined)) { - let sizes = canonicalizeSizesArray(bidRequest.sizes); + if (utils.deepAccess(bidRequest, `mediaTypes.banner`)) { + let sizes = canonicalizeSizesArray(bidRequest.mediaTypes.banner.sizes); imp.banner = { format: sizes.map(s => ({'w': s[0], 'h': s[1]})), topframe: 0 }; - } else if (bidRequest.mediaType === VIDEO || utils.deepAccess(bidRequest, 'mediaTypes.video')) { - let size = canonicalizeSizesArray(bidRequest.sizes)[0]; + } else if (utils.deepAccess(bidRequest, 'mediaTypes.video')) { + let size = canonicalizeSizesArray(bidRequest.mediaTypes.video.playerSize)[0]; imp.video = { w: size[0], h: size[1] @@ -222,9 +217,9 @@ function createSite(refInfo) { * @param bid rtb Bid object */ function formatAdMarkup(bid) { - var adm = bid.adm; + let adm = bid.adm; if ('nurl' in bid) { adm += utils.createTrackPixelHtml(`${bid.nurl}&px=1`); } - return `${adm}`; + return adm; } diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index 43e2dec7ce9..833a8e27f95 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -1,6 +1,5 @@ import {expect} from 'chai'; import {spec} from 'modules/adkernelAdnBidAdapter'; -import * as utils from 'src/utils'; describe('AdkernelAdn adapter', function () { const bid1_pub1 = { @@ -10,10 +9,15 @@ describe('AdkernelAdn adapter', function () { auctionId: '5c66da22-426a-4bac-b153-77360bef5337', bidId: 'bidid_1', params: { - pubId: 1 + pubId: 1, + host: 'tag.adkernel.com' + }, + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 200]] + } }, adUnitCode: 'ad-unit-1', - sizes: [[300, 250], [300, 200]] }, bid2_pub1 = { bidder: 'adkernelAdn', @@ -25,7 +29,11 @@ describe('AdkernelAdn adapter', function () { pubId: 1 }, adUnitCode: 'ad-unit-2', - sizes: [300, 250] + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + } }, bid1_pub2 = { bidder: 'adkernelAdn', @@ -38,22 +46,30 @@ describe('AdkernelAdn adapter', function () { host: 'dps-test.com' }, adUnitCode: 'ad-unit-2', - sizes: [[728, 90]] + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + } }, bid_video1 = { bidder: 'adkernelAdn', transactionId: 'transact3', bidderRequestId: 'req1', auctionId: '5c66da22-426a-4bac-b153-77360bef5337', bidId: 'bidid_4', - mediaType: 'video', - sizes: [640, 300], + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 300] + } + }, adUnitCode: 'video_wrapper', params: { pubId: 7, video: { - mimes: ['video/mp4', 'video/webm', 'video/x-flv'], - api: [1, 2, 3, 4], - protocols: [1, 2, 3, 4, 5, 6] + mimes: ['video/mp4', 'video/webm'], + api: [1, 2], + protocols: [5, 6] } } }, bid_video2 = { @@ -72,12 +88,7 @@ describe('AdkernelAdn adapter', function () { adUnitCode: 'video_wrapper2', params: { - pubId: 7, - video: { - mimes: ['video/mp4', 'video/webm', 'video/x-flv'], - api: [1, 2, 3, 4], - protocols: [1, 2, 3, 4, 5, 6] - } + pubId: 7 } }; @@ -110,12 +121,26 @@ describe('AdkernelAdn adapter', function () { syncpages: ['https://dsp.adkernel.com/sync'] }; - describe('input parameters validation', function () { - it('empty request shouldn\'t generate exception', function () { + const defaultBidderRequest = { + bidderCode: 'adkernelAdn', + bids: [], + auctionStart: 1545836987704, + timeout: 3000, + refererInfo: { + referer: 'https://example.com/index.html', + reachedTop: true, + numIframes: 0, + stack: ['https://example.com/index.html'] + }, + start: 1545836987707 + }; + + describe('input parameters validation', () => { + it('empty request shouldn\'t generate exception', () => { expect(spec.isBidRequestValid({bidderCode: 'adkernelAdn' })).to.be.equal(false); }); - it('request without pubid should be ignored', function () { + it('request without pubid should be ignored', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', params: {}, @@ -123,7 +148,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] })).to.be.equal(false); }); - it('request with invalid pubid should be ignored', function () { + it('request with invalid pubid should be ignored', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', params: { @@ -133,26 +158,42 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] })).to.be.equal(false); }); - }); - - function buildRequest(bidRequests, bidderRequest = {}) { - let mock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => { - return { - protocol: 'https:', - hostname: 'example.com', - host: 'example.com', - pathname: '/index.html', - href: 'https://example.com/index.html' - }; + it('request with totally invalid host should be ignored', () => { + expect(spec.isBidRequestValid({ + bidder: 'adkernelAdn', + params: { + pubId: 1, + host: 1 + }, + placementCode: 'ad-unit-0', + sizes: [[300, 250]] + })).to.be.equal(false); }); + it('valid request should be accepted', () => { + expect(spec.isBidRequestValid({ + bidder: 'adkernelAdn', + params: { + pubId: 1, + host: 'network.com' + }, + placementCode: 'ad-unit-0', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 200]] + } + } + })).to.be.equal(true); + }); + }); - bidderRequest.auctionId = bidRequests[0].auctionId; - bidderRequest.transactionId = bidRequests[0].transactionId; - bidderRequest.bidderRequestId = bidRequests[0].bidderRequestId; - - let pbRequests = spec.buildRequests(bidRequests, bidderRequest); + function buildRequest(bidRequests, bidderRequestAugments = {}) { + let fullBidderRequest = Object.assign(defaultBidderRequest, bidderRequestAugments); + fullBidderRequest.auctionId = bidRequests[0].auctionId; + fullBidderRequest.transactionId = bidRequests[0].transactionId; + fullBidderRequest.bidderRequestId = bidRequests[0].bidderRequestId; + fullBidderRequest.bids = bidRequests; + let pbRequests = spec.buildRequests(bidRequests, fullBidderRequest); let tagRequests = pbRequests.map(r => JSON.parse(r.data)); - mock.restore(); return [pbRequests, tagRequests]; } @@ -207,24 +248,32 @@ describe('AdkernelAdn adapter', function () { }); }); - describe('video request building', function () { + describe('video request building', () => { let [_, tagRequests] = buildRequest([bid_video1, bid_video2]); let tagRequest = tagRequests[0]; - it('should have video object', function () { + it('should have video object', () => { expect(tagRequest.imp[0]).to.have.property('video'); expect(tagRequest.imp[1]).to.have.property('video'); }); - it('should have tagid', function () { + it('should have tagid', () => { expect(tagRequest.imp[0]).to.have.property('tagid', 'video_wrapper'); expect(tagRequest.imp[1]).to.have.property('tagid', 'video_wrapper2'); }); - it('should have size', function () { + it('should have size', () => { expect(tagRequest.imp[0].video).to.have.property('w', 640); expect(tagRequest.imp[0].video).to.have.property('h', 300); expect(tagRequest.imp[1].video).to.have.property('w', 1920); expect(tagRequest.imp[1].video).to.have.property('h', 1080); }); + it('should have video params', () => { + expect(tagRequest.imp[0].video).to.have.property('mimes'); + expect(tagRequest.imp[0].video.mimes).to.be.eql(['video/mp4', 'video/webm']); + expect(tagRequest.imp[0].video).to.have.property('api'); + expect(tagRequest.imp[0].video.api).to.be.eql([1, 2]); + expect(tagRequest.imp[0].video).to.have.property('protocols'); + expect(tagRequest.imp[0].video.protocols).to.be.eql([5, 6]); + }); }); describe('requests routing', function () { diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index 0668e84869a..1d2d2215f02 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -8,37 +8,61 @@ describe('Adkernel adapter', function () { bidId: 'Bid_01', params: {zoneId: 1, host: 'rtb.adkernel.com'}, adUnitCode: 'ad-unit-1', - sizes: [[300, 250], [300, 200]] + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 200]] + } + } }, bid2_zone2 = { bidder: 'adkernel', bidId: 'Bid_02', params: {zoneId: 2, host: 'rtb.adkernel.com'}, adUnitCode: 'ad-unit-2', - sizes: [728, 90] + mediaTypes: { + banner: { + sizes: [728, 90] + } + } }, bid3_host2 = { bidder: 'adkernel', bidId: 'Bid_02', params: {zoneId: 1, host: 'rtb-private.adkernel.com'}, adUnitCode: 'ad-unit-2', - sizes: [[728, 90]] + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + } }, bid_without_zone = { bidder: 'adkernel', bidId: 'Bid_W', params: {host: 'rtb-private.adkernel.com'}, adUnitCode: 'ad-unit-1', - sizes: [[728, 90]] + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + } }, bid_without_host = { bidder: 'adkernel', bidId: 'Bid_W', params: {zoneId: 1}, adUnitCode: 'ad-unit-1', - sizes: [[728, 90]] + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + } }, bid_with_wrong_zoneId = { bidder: 'adkernel', bidId: 'Bid_02', params: {zoneId: 'wrong id', host: 'rtb.adkernel.com'}, adUnitCode: 'ad-unit-2', - sizes: [[728, 90]] + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + } }, bid_video = { bidder: 'adkernel', transactionId: '866394b8-5d37-4d49-803e-f1bdb595f73e', @@ -120,7 +144,7 @@ describe('Adkernel adapter', function () { let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => dnt); let pbRequests = spec.buildRequests(bidRequests, bidderRequest); dntmock.restore(); - let rtbRequests = pbRequests.map(r => JSON.parse(r.data.r)); + let rtbRequests = pbRequests.map(r => JSON.parse(r.data)); return [pbRequests, rtbRequests]; } @@ -246,8 +270,8 @@ describe('Adkernel adapter', function () { it('should issue a request for each zone', function () { let [pbRequests, _] = buildRequest([bid1_zone1, bid2_zone2]); expect(pbRequests).to.have.length(2); - expect(pbRequests[0].data.zone).to.be.equal(bid1_zone1.params.zoneId); - expect(pbRequests[1].data.zone).to.be.equal(bid2_zone2.params.zoneId); + expect(pbRequests[0].url).to.include(`zone=${bid1_zone1.params.zoneId}`); + expect(pbRequests[1].url).to.include(`zone=${bid2_zone2.params.zoneId}`); }); }); From 584c59ec80eb47d93cbf654ab853d573b9bc5795 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 23 Jan 2019 15:20:43 -0500 Subject: [PATCH 0951/1594] Prebid 1.39.0 release --- package-lock.json | 2753 +++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 1262 insertions(+), 1493 deletions(-) diff --git a/package-lock.json b/package-lock.json index cf034789e8f..c992ef29074 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.37.0", + "version": "1.39.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -44,15 +44,6 @@ "ms": "^2.1.1" } }, - "json5": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", - "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -62,24 +53,18 @@ } }, "@babel/generator": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz", - "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.0.tgz", + "integrity": "sha512-dZTwMvTgWfhmibq4V9X+LMf6Bgl7zAodRn9PvcPdhlzFMbvUutx74dbEv7Atz3ToeEpevYEJtAwfxq/bDCzHWg==", "dev": true, "requires": { - "@babel/types": "^7.2.2", + "@babel/types": "^7.3.0", "jsesc": "^2.5.1", "lodash": "^4.17.10", "source-map": "^0.5.0", "trim-right": "^1.0.1" }, "dependencies": { - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -281,14 +266,14 @@ } }, "@babel/helpers": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.2.0.tgz", - "integrity": "sha512-Fr07N+ea0dMcMN8nFpuK6dUIT7/ivt9yKQdEEnjVS83tG2pHwPi03gYmk/tyuwONnZ+sY+GFFPlWGgCtW1hF9A==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.3.1.tgz", + "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==", "dev": true, "requires": { "@babel/template": "^7.1.2", "@babel/traverse": "^7.1.5", - "@babel/types": "^7.2.0" + "@babel/types": "^7.3.0" } }, "@babel/highlight": { @@ -300,31 +285,12 @@ "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - } } }, "@babel/parser": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", - "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.1.tgz", + "integrity": "sha512-ATz6yX/L8LEnC3dtLQnIx4ydcPxhLcoy9Vl6re00zb2w5lG6itY6Vhnr1KFRPq/FHNsgl/gh2mjNN20f9iJTTA==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -349,9 +315,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-1L5mWLSvR76XYUQJXkd/EEQgjq8HHRP6lQuZTTg0VA4tTGPpGemmCdAfQIz1rzEuWAm+ecP8PyyEm30jC1eQCg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.1.tgz", + "integrity": "sha512-Nmmv1+3LqxJu/V5jU9vJmxR/KIRWFk2qLHmbB56yRRRFhlaSuOVXscX3gUmhaKgUhzA3otOHVubbIEVYsZ0eZg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -377,43 +343,6 @@ "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.0.0", "regexpu-core": "^4.2.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regexpu-core": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", - "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } } }, "@babel/plugin-syntax-async-generators": { @@ -505,14 +434,6 @@ "@babel/helper-replace-supers": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.10.0.tgz", - "integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==", - "dev": true - } } }, "@babel/plugin-transform-computed-properties": { @@ -542,43 +463,6 @@ "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.0.0", "regexpu-core": "^4.1.3" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regexpu-core": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", - "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } } }, "@babel/plugin-transform-duplicate-keys": { @@ -669,6 +553,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz", + "integrity": "sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==", + "dev": true, + "requires": { + "regexp-tree": "^0.1.0" + } + }, "@babel/plugin-transform-new-target": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", @@ -706,17 +599,6 @@ "dev": true, "requires": { "regenerator-transform": "^0.13.3" - }, - "dependencies": { - "regenerator-transform": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", - "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - } } }, "@babel/plugin-transform-shorthand-properties": { @@ -775,59 +657,23 @@ "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.0.0", "regexpu-core": "^4.1.3" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regexpu-core": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", - "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } } }, "@babel/preset-env": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.2.3.tgz", - "integrity": "sha512-AuHzW7a9rbv5WXmvGaPX7wADxFkZIqKlbBh1dmZUQp4iwiPpkE/Qnrji6SC4UQCQzvWY/cpHET29eUhXS9cLPw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.1.tgz", + "integrity": "sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.3.1", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", @@ -847,6 +693,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.2.0", "@babel/plugin-transform-modules-systemjs": "^7.2.0", "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", "@babel/plugin-transform-new-target": "^7.0.0", "@babel/plugin-transform-object-super": "^7.2.0", "@babel/plugin-transform-parameters": "^7.2.0", @@ -861,31 +708,6 @@ "invariant": "^2.2.2", "js-levenshtein": "^1.1.3", "semver": "^5.3.0" - }, - "dependencies": { - "browserslist": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.7.tgz", - "integrity": "sha512-pWQv51Ynb0MNk9JGMCZ8VkM785/4MQNXiFYtPqI7EEP0TJO+/d/NqRVn1uiAN0DNbnlUSpL2sh16Kspasv3pUQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000925", - "electron-to-chromium": "^1.3.96", - "node-releases": "^1.1.3" - } - }, - "caniuse-lite": { - "version": "1.0.30000927", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000927.tgz", - "integrity": "sha512-ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.100", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.100.tgz", - "integrity": "sha512-cEUzis2g/RatrVf8x26L8lK5VEls1AGnLHk6msluBUg/NTB4wcXzExTsGscFq+Vs4WBBU2zbLLySvD4C0C3hwg==", - "dev": true - } } }, "@babel/template": { @@ -924,32 +746,18 @@ "requires": { "ms": "^2.1.1" } - }, - "globals": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.10.0.tgz", - "integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==", - "dev": true } } }, "@babel/types": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.2.tgz", - "integrity": "sha512-fKCuD6UFUMkR541eDWL+2ih/xFZBXPOg/7EQFeTluMDebfqR4jrpaCjLhkWlQS4hT6nRa2PMEgXKbRB5/H2fpg==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.0.tgz", + "integrity": "sha512-QkFPw68QqWU1/RVPyBe8SO7lXbPfjtqAxRYQKpFpaB8yMq7X2qAqfwK5LKoQufEkSmO5NQ70O6Kc3Afk03RwXw==", "dev": true, "requires": { "esutils": "^2.0.2", "lodash": "^4.17.10", "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "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 - } } }, "@gulp-sourcemaps/identity-map": { @@ -979,6 +787,23 @@ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", "dev": true }, + "@sinonjs/commons": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.3.0.tgz", + "integrity": "sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + }, + "dependencies": { + "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 + } + } + }, "@sinonjs/formatio": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", @@ -989,14 +814,22 @@ } }, "@sinonjs/samsam": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.0.tgz", - "integrity": "sha512-5x2kFgJYupaF1ns/RmharQ90lQkd2ELS8A9X0ymkAAdemYHGtI2KiUHG8nX2WU0T1qgnOU5YMqnBM2V7NUanNw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.0.2.tgz", + "integrity": "sha512-m08g4CS3J6lwRQk1pj1EO+KEVWbrbXsmi9Pw0ySmrIbcVxVaedoFgLvFsV8wHLwh01EpROVz3KvVcD1Jmks9FQ==", "dev": true, "requires": { - "array-from": "^2.1.1" + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash.get": "^4.4.2" } }, + "@types/node": { + "version": "8.10.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.39.tgz", + "integrity": "sha512-rE7fktr02J8ybFf6eysife+WF+L4sAHWzw09DgdCebEu+qDwMvv4zl6Bc+825ttGZP73kCKxa3dhJOoGJ8+5mA==", + "dev": true + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1090,7 +923,7 @@ "dependencies": { "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -1500,6 +1333,16 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "dev": true, + "requires": { + "follow-redirects": "^1.2.5", + "is-buffer": "^1.1.5" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -1509,44 +1352,107 @@ "chalk": "^1.1.3", "esutils": "^2.0.2", "js-tokens": "^3.0.2" + }, + "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 + }, + "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" + } + }, + "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, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "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 + } } }, "babel-core": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.22.0.tgz", - "integrity": "sha1-ZD3q61ILzSsGwR45lFyHfgIA0Sg=", + "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.22.0", - "babel-generator": "^6.22.0", - "babel-helpers": "^6.22.0", - "babel-messages": "^6.22.0", - "babel-register": "^6.22.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.22.0", - "babel-traverse": "^6.22.0", - "babel-types": "^6.22.0", - "babylon": "^6.11.0", - "convert-source-map": "^1.1.0", - "debug": "^2.1.1", - "json5": "^0.5.0", - "lodash": "^4.2.0", - "minimatch": "^3.0.2", - "path-is-absolute": "^1.0.0", - "private": "^0.1.6", + "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.0" + "source-map": "^0.5.7" }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" } }, + "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", @@ -1577,6 +1483,12 @@ "trim-right": "^1.0.1" }, "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -2190,6 +2102,40 @@ "babel-helper-regex": "^6.24.1", "babel-runtime": "^6.22.0", "regexpu-core": "^2.0.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + } } }, "babel-plugin-transform-exponentiation-operator": { @@ -2298,6 +2244,19 @@ "dev": true, "requires": { "regenerator-transform": "^0.10.0" + }, + "dependencies": { + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + } } }, "babel-plugin-transform-strict-mode": { @@ -2346,6 +2305,18 @@ "browserslist": "^3.2.6", "invariant": "^2.2.2", "semver": "^5.3.0" + }, + "dependencies": { + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + } } }, "babel-preset-flow": { @@ -2431,56 +2402,6 @@ "lodash": "^4.17.4", "mkdirp": "^0.5.1", "source-map-support": "^0.4.15" - }, - "dependencies": { - "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" - } - }, - "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 - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "babel-runtime": { @@ -2531,6 +2452,12 @@ "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", @@ -2549,6 +2476,14 @@ "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": { @@ -2701,15 +2636,15 @@ } }, "big-integer": { - "version": "1.6.39", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.39.tgz", - "integrity": "sha512-JgwrfTfdSxDQGRPx3j9hHrag/Ih2oCQwE/kMHW5tujSyjLFLk3hbum5ZJhaginvQ2LBw2YxGgP73AquAWNW/ZA==", + "version": "1.6.41", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.41.tgz", + "integrity": "sha512-d5AT9lMTYJ/ZE/4gzxb+5ttPcRWljVsvv7lF1w9KzkPhVUhBtHrjDo1J8swfZKepfLsliDhYa31zRYwcD0Yg9w==", "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==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, "binary": { @@ -2764,6 +2699,68 @@ "safe-json-parse": "~1.0.1" } }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "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" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + } + } + }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", @@ -2905,74 +2902,31 @@ }, "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.5" - } - }, - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } - }, - "browserstack": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.0.tgz", - "integrity": "sha1-tWVCWtYu1ywQgqHrl51TE8fUdU8=", - "dev": true, - "requires": { - "https-proxy-agent": "1.0.0" - }, - "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, - "requires": { - "extend": "~3.0.0", - "semver": "~5.0.1" - } - }, - "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" - } - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true, - "requires": { - "agent-base": "2", - "debug": "2", - "extend": "3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "semver": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - } + "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.5" + } + }, + "browserslist": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.1.tgz", + "integrity": "sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000929", + "electron-to-chromium": "^1.3.103", + "node-releases": "^1.1.3" + } + }, + "browserstack": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", + "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" } }, "browserstacktunnel-wrapper": { @@ -3129,7 +3083,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3195,9 +3149,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000914", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000914.tgz", - "integrity": "sha512-qqj0CL1xANgg6iDOybiPTIxtsmAnfIky9mBC35qgWrnK4WwmhqfpmkDYMYgwXJ8LRZ3/2jXlCntulO8mBaAgSg==", + "version": "1.0.30000930", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000930.tgz", + "integrity": "sha512-KD+pw9DderBLB8CGqBzYyFWpnrPVOEjsjargU/CvkNyg60od3cxSPTcTeMPhxJhDbkQPWvOz5BAyBzNl/St9vg==", "dev": true }, "caseless": { @@ -3260,45 +3214,14 @@ } }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "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 - }, - "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, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "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 - } + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "character-entities": { @@ -3406,6 +3329,17 @@ "restore-cursor": "^2.0.0" } }, + "cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -3413,13 +3347,13 @@ "dev": true }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" } }, @@ -3520,9 +3454,9 @@ "dev": true }, "colors": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", - "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, "combine-lists": { @@ -3553,7 +3487,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -3637,6 +3571,12 @@ } } }, + "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 + }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -3701,9 +3641,9 @@ } }, "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.3.tgz", + "integrity": "sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ==" }, "core-util-is": { "version": "1.0.2", @@ -3847,10 +3787,13 @@ } }, "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.0.tgz", + "integrity": "sha512-YbKCNLPPP4inc0E5If4OaalBc7gpaM2MRv77Pv2VThVComLKfbGYtJcdDCViDyp1Wd4SebhHLz94vp91zbK6bw==", + "dev": true, + "requires": { + "@types/node": "^8.0.7" + } }, "date-format": { "version": "1.2.0", @@ -4238,64 +4181,44 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "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" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.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.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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": { - "ms": "2.0.0" + "number-is-nan": "^1.0.0" } }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -4316,12 +4239,6 @@ } } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -4359,29 +4276,13 @@ "path-type": "^2.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 - }, - "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=", + "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": "^3.0.0" + "ansi-regex": "^2.0.0" } }, "yargs": { @@ -4416,6 +4317,15 @@ } } } + }, + "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" + } } } }, @@ -4508,9 +4418,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.88", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.88.tgz", - "integrity": "sha512-UPV4NuQMKeUh1S0OWRvwg0PI8ASHN9kBC8yDTk1ROXLC85W5GnhTRu/MZu3Teqx3JjlQYuckuHYXSUSgtb3J+A==", + "version": "1.3.106", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.106.tgz", + "integrity": "sha512-eXX45p4q9CRxG0G8D3ZBZYSdN3DnrcZfrFvt6VUr1u7aKITEtRY/xwWzJ/UZcWXa7DMqPu/pYwuZ6Nm+bl0GmA==", "dev": true }, "elliptic": { @@ -4558,7 +4468,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4572,7 +4482,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4588,7 +4498,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4608,7 +4518,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4707,9 +4617,9 @@ } }, "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "version": "0.10.47", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", + "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", @@ -4913,23 +4823,6 @@ "json-schema-traverse": "^0.3.0" } }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -4951,30 +4844,15 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, - "globals": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", - "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", - "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 - }, - "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" - } } } }, @@ -5012,13 +4890,13 @@ } }, "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", + "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", "dev": true, "requires": { "debug": "^2.6.8", - "pkg-dir": "^1.0.0" + "pkg-dir": "^2.0.0" }, "dependencies": { "debug": { @@ -5030,58 +4908,39 @@ "ms": "2.0.0" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "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": "^1.0.0" + "find-up": "^2.1.0" } } } }, "eslint-plugin-import": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.15.0.tgz", + "integrity": "sha512-LEHqgR+RcnpGqYW7h9WMkPb/tP+ekKxWdQDztfTtZeV43IHF+X8lXU+1HOCcR4oXD24qRgEwNSxIweD5uNKGVg==", "dev": true, "requires": { "contains-path": "^0.1.0", - "debug": "^2.6.8", + "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.3.0", + "has": "^1.0.3", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" + "resolve": "^1.9.0" }, "dependencies": { "debug": { @@ -5271,7 +5130,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5282,6 +5141,14 @@ "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 + } } }, "eventemitter3": { @@ -5291,9 +5158,9 @@ "dev": true }, "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", "dev": true }, "evp_bytestokey": { @@ -5738,9 +5605,9 @@ } }, "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz", + "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==", "dev": true, "requires": { "expand-tilde": "^2.0.2", @@ -5751,9 +5618,9 @@ } }, "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, "flat-cache": { @@ -5769,12 +5636,12 @@ }, "dependencies": { "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } } } @@ -5782,7 +5649,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { @@ -5796,9 +5663,9 @@ } }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", + "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", "dev": true, "requires": { "debug": "=3.1.0" @@ -5959,9 +5826,9 @@ "dev": true }, "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", "dev": true, "optional": true, "requires": { @@ -5971,28 +5838,24 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "dev": true }, "aproba": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { - "version": "1.1.4", - "resolved": false, - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "version": "1.1.5", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6002,14 +5865,12 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "bundled": true, "dev": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -6017,41 +5878,35 @@ } }, "chownr": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "version": "1.1.1", + "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "dev": true }, "concat-map": { "version": "0.0.1", - "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": false, - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6059,30 +5914,26 @@ } }, "deep-extend": { - "version": "0.5.1", - "resolved": false, - "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", + "version": "0.6.0", + "bundled": true, "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6091,15 +5942,13 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6114,9 +5963,8 @@ } }, "glob": { - "version": "7.1.2", - "resolved": false, - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6130,25 +5978,22 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true, "optional": true }, "iconv-lite": { - "version": "0.4.21", - "resolved": false, - "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "version": "0.4.24", + "bundled": true, "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": ">= 2.1.2 < 3" } }, "ignore-walk": { "version": "3.0.1", - "resolved": false, - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6157,8 +6002,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6168,21 +6012,18 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, "dev": true }, "ini": { "version": "1.3.5", - "resolved": false, - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "bundled": true, "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "dev": true, "requires": { "number-is-nan": "^1.0.0" @@ -6190,15 +6031,13 @@ }, "isarray": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -6206,24 +6045,21 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "bundled": true, "dev": true }, "minipass": { - "version": "2.2.4", - "resolved": false, - "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", + "version": "2.3.5", + "bundled": true, "dev": true, "requires": { - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "version": "1.2.1", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6232,8 +6068,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "dev": true, "requires": { "minimist": "0.0.8" @@ -6241,15 +6076,13 @@ }, "ms": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "bundled": true, "dev": true, "optional": true }, "needle": { - "version": "2.2.0", - "resolved": false, - "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", + "version": "2.2.4", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6259,19 +6092,18 @@ } }, "node-pre-gyp": { - "version": "0.10.0", - "resolved": false, - "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", + "version": "0.10.3", + "bundled": true, "dev": true, "optional": true, "requires": { "detect-libc": "^1.0.2", "mkdirp": "^0.5.1", - "needle": "^2.2.0", + "needle": "^2.2.1", "nopt": "^4.0.1", "npm-packlist": "^1.1.6", "npmlog": "^4.0.2", - "rc": "^1.1.7", + "rc": "^1.2.7", "rimraf": "^2.6.1", "semver": "^5.3.0", "tar": "^4" @@ -6279,8 +6111,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6289,16 +6120,14 @@ } }, "npm-bundled": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "version": "1.0.5", + "bundled": true, "dev": true, "optional": true }, "npm-packlist": { - "version": "1.1.10", - "resolved": false, - "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "version": "1.2.0", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6308,8 +6137,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6321,21 +6149,18 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "bundled": true, "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": false, - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "dev": true, "requires": { "wrappy": "1" @@ -6343,22 +6168,19 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "bundled": true, "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6368,26 +6190,23 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "bundled": true, "dev": true, "optional": true }, "rc": { - "version": "1.2.7", - "resolved": false, - "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "version": "1.2.8", + "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", + "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" @@ -6395,8 +6214,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "dev": true, "optional": true } @@ -6404,8 +6222,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6419,60 +6236,52 @@ } }, "rimraf": { - "version": "2.6.2", - "resolved": false, - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.6.3", + "bundled": true, "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.1.1", - "resolved": false, - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "version": "5.1.2", + "bundled": true, "dev": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, "dev": true, "optional": true }, "semver": { - "version": "5.5.0", - "resolved": false, - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "5.6.0", + "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "dev": true, "requires": { "code-point-at": "^1.0.0", @@ -6482,8 +6291,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6492,8 +6300,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -6501,54 +6308,48 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "bundled": true, "dev": true, "optional": true }, "tar": { - "version": "4.4.1", - "resolved": false, - "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "version": "4.4.8", + "bundled": true, "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", + "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.2" } }, "util-deprecate": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "dev": true, "optional": true }, "wide-align": { - "version": "1.1.2", - "resolved": false, - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "version": "1.1.3", + "bundled": true, "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "^1.0.2 || 2" } }, "wrappy": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, "dev": true }, "yallist": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "version": "3.0.3", + "bundled": true, "dev": true } } @@ -6662,33 +6463,38 @@ "dev": true }, "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.3.tgz", + "integrity": "sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw==", "dev": true, "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", + "data-uri-to-buffer": "2", + "debug": "4", + "extend": "~3.0.2", "file-uri-to-path": "1", "ftp": "~0.3.10", - "readable-stream": "2" + "readable-stream": "3" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } } } }, @@ -6863,9 +6669,9 @@ } }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.10.0.tgz", + "integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==", "dev": true }, "globals-docs": { @@ -6875,9 +6681,9 @@ "dev": true }, "glogg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", "dev": true, "requires": { "sparkles": "^1.0.0" @@ -6938,12 +6744,29 @@ "vinyl-fs": "^3.0.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 + }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -6980,6 +6803,15 @@ "yargs": "^7.1.0" } }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -7058,6 +6890,26 @@ "read-pkg": "^1.0.0" } }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -7119,59 +6971,11 @@ "vinyl-sourcemaps-apply": "^0.2.0" }, "dependencies": { - "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" - } - }, - "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 - }, "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "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 } } }, @@ -7357,7 +7161,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7374,19 +7178,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", - "dev": true - }, - "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 - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -7402,6 +7194,18 @@ "through2": "^1.1.1" }, "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 + }, "assert-plus": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", @@ -7420,6 +7224,19 @@ "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true }, + "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" + } + }, "coveralls": { "version": "2.13.3", "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", @@ -7452,7 +7269,7 @@ }, "har-validator": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", "dev": true, "requires": { @@ -7462,6 +7279,15 @@ "pinkie-promise": "^2.0.0" } }, + "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, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "http-signature": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", @@ -7515,7 +7341,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -7527,7 +7353,7 @@ }, "request": { "version": "2.79.0", - "resolved": "http://registry.npmjs.org/request/-/request-2.79.0.tgz", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", "dev": true, "requires": { @@ -7555,13 +7381,28 @@ }, "string_decoder": { "version": "0.10.31", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "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=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "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 + }, "through2": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", "dev": true, "requires": { @@ -7571,7 +7412,7 @@ }, "tough-cookie": { "version": "2.3.4", - "resolved": "http://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { @@ -7886,6 +7727,31 @@ "vinyl": "^0.5.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 + }, + "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" + } + }, "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -7904,6 +7770,15 @@ "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", "dev": true }, + "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, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -7969,6 +7844,21 @@ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "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 + }, "vinyl": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", @@ -8047,9 +7937,9 @@ }, "dependencies": { "ajv": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", - "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -8200,9 +8090,9 @@ "dev": true }, "hast-util-sanitize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.2.1.tgz", - "integrity": "sha512-bRyZ316tTETfxkpM0De0Fk5slEtR5hvkzDGbHpEAjZRmfQyT3xMTzMk0/gGWlkqsfafFCaPNbrtPdZBPMK8X8A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.0.tgz", + "integrity": "sha512-rQeetoD08jHmDOUYN6h9vTuE0hQN4wymhtkQZ6whHtcjaLpjw5RYAbcdxx9cMgMWERDsSs79UpqHuBLlUHKeOw==", "dev": true, "requires": { "xtend": "^4.0.1" @@ -8313,7 +8203,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8484,56 +8374,12 @@ "string-width": "^2.1.0", "strip-ansi": "^4.0.0", "through": "^2.3.6" - }, - "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 - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "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" - } - } } }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, "into-stream": { @@ -8749,13 +8595,10 @@ } }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "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 }, "is-glob": { "version": "4.0.0", @@ -8892,9 +8735,9 @@ "dev": true }, "is-ssh": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", - "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", + "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", "dev": true, "requires": { "protocols": "^1.1.0" @@ -9175,12 +9018,12 @@ }, "dependencies": { "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "source-map": { @@ -9222,21 +9065,21 @@ } }, "js-levenshtein": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.5.tgz", - "integrity": "sha512-ap2aTez3WZASzMmJvgvG+nsrCCrtHPQ+4YB+WQjYQpXgLkM+WqwkpzdlVs5l7Xhk128I/CisIk4CdXl7pIchUA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", "dev": true }, "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -9253,9 +9096,9 @@ "integrity": "sha512-gcvGaqerlUJy1Kq6tNgPYteVEoWNemu+9hBe2CdsCIz4rVcwjoTQ72iD1W76/PRMlnkzG0yVh7nwOOMOOUfKmg==" }, "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, "json-buffer": { @@ -9286,15 +9129,6 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -9307,10 +9141,13 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } }, "jsonfile": { "version": "1.0.1", @@ -9318,12 +9155,6 @@ "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", "dev": true }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -9359,15 +9190,15 @@ "dev": true }, "just-extend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-3.0.0.tgz", - "integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9400,89 +9231,19 @@ "useragent": "2.3.0" }, "dependencies": { - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha1-KXhx9jvlB63Pv8pxXQzQ7thOmmM=", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, "mime": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha1-4FH9iBNYWF8yed8zP+aU2gvP/dY=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha1-GzJOzmtXBuFThVvBFIxlu39uoMM=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "glob": "^7.1.3" } } } @@ -9497,13 +9258,13 @@ } }, "karma-browserstack-launcher": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz", - "integrity": "sha512-LrPf5sU/GISkEElWyoy06J8x0c8BcOjjOwf61Wqu6M0aWQu0Eoqm9yh3xON64/ByST/CEr0GsWiREQ/EIEMd4Q==", + "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, "requires": { - "browserstack": "1.5.0", - "browserstacktunnel-wrapper": "~2.0.1", + "browserstack": "~1.5.1", + "browserstacktunnel-wrapper": "~2.0.2", "q": "~1.5.0" } }, @@ -9575,34 +9336,6 @@ "chalk": "^2.1.0", "log-symbols": "^2.1.0", "strip-ansi": "^4.0.0" - }, - "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 - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.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" - } - } } }, "karma-opera-launcher": { @@ -9650,7 +9383,7 @@ "karma-webpack": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.5.tgz", - "integrity": "sha1-H/HjppD7c66V7pX5q1jzQc/HtA8=", + "integrity": "sha512-nRudGJWstvVuA6Tbju9tyGUfXTtI1UXMXoRHVmM2/78D0q6s/Ye2IC157PKNDC15PWFGR0mVIRtWLAdcfsRJoA==", "dev": true, "requires": { "async": "^2.0.0", @@ -9664,7 +9397,7 @@ "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha1-skWiPKcZMAROxT+kaqAKPofGphA=", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { "lodash": "^4.17.10" @@ -9798,20 +9531,31 @@ } }, "loader-runner": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", - "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", + "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": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, "requires": { - "big.js": "^3.1.3", + "big.js": "^5.2.2", "emojis-list": "^2.0.0", - "json5": "^0.5.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.0" + } + } } }, "localtunnel": { @@ -9826,15 +9570,11 @@ "yargs": "6.6.0" }, "dependencies": { - "axios": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", - "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", - "dev": true, - "requires": { - "follow-redirects": "^1.2.5", - "is-buffer": "^1.1.5" - } + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true }, "camelcase": { "version": "3.0.0", @@ -9842,6 +9582,17 @@ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -9861,6 +9612,15 @@ "pinkie-promise": "^2.0.0" } }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -9945,6 +9705,26 @@ "read-pkg": "^1.0.0" } }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -10340,25 +10120,12 @@ "dev": true, "requires": { "chalk": "^2.0.1" - }, - "dependencies": { - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } } }, "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -10371,7 +10138,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true } } @@ -10379,7 +10146,7 @@ "loglevelnext": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", - "integrity": "sha1-NvxPWZbWZA9Tn/IDuoGWQWgNdaI=", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", "dev": true, "requires": { "es6-symbol": "^3.1.1", @@ -10510,9 +10277,9 @@ "dev": true }, "map-stream": { - "version": "0.1.0", - "resolved": "http://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, "map-visit": { @@ -10549,9 +10316,9 @@ } }, "math-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "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": { @@ -10882,7 +10649,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mixin-deep": { @@ -10917,7 +10684,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10932,7 +10699,7 @@ "mocha": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha1-bYrlCPWRZ/lA8rWzxKYSrlDJCuY=", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, "requires": { "browser-stdout": "1.3.1", @@ -10951,7 +10718,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -10960,13 +10727,13 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -10986,7 +10753,7 @@ "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha1-HGszdALCE3YF7+GfEP7DkPb6q1Q=", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -11143,9 +10910,9 @@ "dev": true }, "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", "dev": true, "optional": true }, @@ -11204,9 +10971,9 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nightwatch": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.14.tgz", - "integrity": "sha512-SXJk0BtXAWslcdByueESJ8a265rshGfllCPy9yPdAEGhIjSKsaMw1ASPn+q+msFhpOYRKEjoQ+Qu9e4SlSz2xQ==", + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.18.tgz", + "integrity": "sha512-BKosRh/QqpCCMxjnfP+gb8KMQV0y//TNdYDjB0RrU1pXgx2Xjyp46bK8tQWRFfqaxWDj5EKYFIPgvxFBXodIOA==", "dev": true, "requires": { "assertion-error": "^1.1.0", @@ -11222,50 +10989,6 @@ "proxy-agent": "^3.0.0" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "optional": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, "minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", @@ -11274,86 +10997,37 @@ "requires": { "brace-expansion": "^1.0.0" } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "optional": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": 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, - "optional": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, "nise": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.6.tgz", - "integrity": "sha512-1GedetLKzmqmgwabuMSqPsT7oumdR77SBpDfNNJhADRIeA3LN/2RVqR4fFqwvzhAqcTef6PPCzQwITE/YQ8S8A==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.8.tgz", + "integrity": "sha512-kGASVhuL4tlAV0tvA34yJYZIVihrUt/5bDwpp4tTluigxUr2bBlJeDXmivb6NuEdFkqvdv/Ybb9dm16PSKUhtw==", "dev": true, "requires": { - "@sinonjs/formatio": "3.0.0", - "just-extend": "^3.0.0", + "@sinonjs/formatio": "^3.1.0", + "just-extend": "^4.0.2", "lolex": "^2.3.2", "path-to-regexp": "^1.7.0", "text-encoding": "^0.6.4" }, "dependencies": { "@sinonjs/formatio": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.0.0.tgz", - "integrity": "sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.1.0.tgz", + "integrity": "sha512-ZAR2bPHOl4Xg6eklUGpsdiIJ4+J1SNag1DHHrG/73Uz/nVwXqjgUtRPLoS+aVyieN9cSbc0E4LsU984tWcDyNg==", "dev": true, "requires": { - "@sinonjs/samsam": "2.1.0" + "@sinonjs/samsam": "^2 || ^3" } } } }, "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", + "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", "dev": true, "requires": { "assert": "^1.1.1", @@ -11363,7 +11037,7 @@ "constants-browserify": "^1.0.0", "crypto-browserify": "^3.11.0", "domain-browser": "^1.1.1", - "events": "^1.0.0", + "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "0.0.0", @@ -11377,7 +11051,7 @@ "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", "url": "^0.11.0", - "util": "^0.10.3", + "util": "^0.11.0", "vm-browserify": "0.0.4" }, "dependencies": { @@ -11651,7 +11325,7 @@ "opn": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha1-y1Reeqt4VivrEao7+rxwQuF2EDU=", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -11669,7 +11343,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11700,12 +11374,29 @@ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "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 }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -11716,6 +11407,15 @@ "pinkie-promise": "^2.0.0" } }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -11794,6 +11494,26 @@ "read-pkg": "^1.0.0" } }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -12005,9 +11725,9 @@ } }, "pako": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", - "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", + "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", "dev": true }, "parents": { @@ -12020,16 +11740,17 @@ } }, "parse-asn1": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.3.tgz", + "integrity": "sha512-VrPoetlz7B/FqjBLD2f5wBVZvsZVLnRUrxVLfRYhGXCODa/NWE4p3Wp+6+aV3ZPL3KM7/OZmxDIwwijD7yuucg==", "dev": true, "requires": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, "parse-domain": { @@ -12051,83 +11772,20 @@ "dev": true, "requires": { "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "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, - "requires": { - "type-detect": "^4.0.0" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" } }, - "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==", + "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, "requires": { - "has-flag": "^3.0.0" + "type-detect": "^4.0.0" } }, "type-detect": { @@ -12544,9 +12202,9 @@ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.2.tgz", - "integrity": "sha512-/OLz5F9beZUWwSHZDreXgap1XShX6W+DCHQCqwCF7uZ88s6uTlD2cR3JBE77SegCmNtb1Idst+NfmwcdU6KVhw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, "property-information": { @@ -12556,9 +12214,9 @@ "dev": true }, "protocols": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", - "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.7.tgz", + "integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==", "dev": true }, "proxy-agent": { @@ -12615,9 +12273,9 @@ "dev": true }, "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" }, "public-encrypt": { "version": "4.0.3", @@ -12852,13 +12510,11 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", + "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", "dev": true, "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", "private": "^0.1.6" } }, @@ -12881,6 +12537,39 @@ "safe-regex": "^1.1.0" } }, + "regexp-tree": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.0.tgz", + "integrity": "sha512-rHQv+tzu+0l3KS/ERabas1yK49ahNVxuH40WcPg53CzP5p8TgmmyBgHELLyJcvjhTD0e5ahSY6C76LbEVtr7cg==", + "dev": true, + "requires": { + "cli-table3": "^0.5.0", + "colors": "^1.1.2", + "yargs": "^10.0.3" + }, + "dependencies": { + "yargs": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", + "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^8.1.0" + } + } + } + }, "regexpp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", @@ -12888,26 +12577,29 @@ "dev": true }, "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", + "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", "dev": true, "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^7.0.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.0.2" } }, "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", "dev": true }, "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -13165,12 +12857,12 @@ "dev": true }, "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } }, "resolve-dir": { @@ -13237,7 +12929,7 @@ "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", "dev": true }, "right-align": { @@ -13343,7 +13035,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -13589,14 +13281,6 @@ "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0" - }, - "dependencies": { - "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 - } } }, "smart-buffer": { @@ -13745,7 +13429,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -13759,7 +13443,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13782,7 +13466,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -13804,7 +13488,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13820,7 +13504,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13832,7 +13516,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13942,9 +13626,9 @@ "dev": true }, "spdx-correct": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", - "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -13968,14 +13652,14 @@ } }, "spdx-license-ids": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", - "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", "dev": true }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13997,9 +13681,9 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz", + "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -14090,9 +13774,9 @@ } }, "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, "requires": { "inherits": "~2.0.1", @@ -14101,7 +13785,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -14168,14 +13852,13 @@ "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "string_decoder": { @@ -14205,18 +13888,18 @@ "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": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^3.0.0" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true } } @@ -14306,59 +13989,17 @@ "json-schema-traverse": "^0.3.0" } }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "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 - }, "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 - }, - "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" - } } } }, @@ -14414,9 +14055,9 @@ } }, "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "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": { "through2": "~2.0.0", @@ -14505,9 +14146,9 @@ "dev": true }, "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "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": { @@ -14653,6 +14294,16 @@ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -14867,13 +14518,13 @@ } }, "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "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": "^1.0.0", - "through2-filter": "^2.0.0" + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" } }, "unist-builder": { @@ -14983,9 +14634,9 @@ } }, "unzipper": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.4.tgz", - "integrity": "sha512-kGrkTaphmXE+0/A5Q7rwcm/xHlDkXDOGEh6wuiN3SUQsyVWd7V51rwqttlNTT91JrLkfn34MoBNf38unF0vhRw==", + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.10.tgz", + "integrity": "sha512-dhxTaR67KGyrmxseXTmsyzdlRWkuN0rMPo9j6lxosR/PkzbHNd3smzMobaApx6o/oYvqU1uv+fAPoWr1P4bd8Q==", "dev": true, "requires": { "big-integer": "^1.6.17", @@ -15001,7 +14652,7 @@ "dependencies": { "bluebird": { "version": "3.4.7", - "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true } @@ -15100,7 +14751,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -15108,9 +14759,9 @@ } }, "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, "requires": { "inherits": "2.0.3" @@ -15143,9 +14794,9 @@ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "v8flags": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", - "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", + "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", "dev": true, "requires": { "homedir-polyfill": "^1.0.1" @@ -15196,9 +14847,9 @@ "dev": true }, "vfile-message": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.2.tgz", - "integrity": "sha512-dNdEXHfPCvzyOlEaaQ+DcXpcxEz+pFvdrebKLiAMjobjaBC2bMeWoHOKPwJ+I8A4jQOEUDH7uoVcLWDLF1qhVQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", + "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", "dev": true, "requires": { "unist-util-stringify-position": "^1.1.1" @@ -15217,12 +14868,47 @@ "vfile-statistics": "^1.1.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 + }, "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.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -15394,9 +15080,9 @@ "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "async": { @@ -15408,6 +15094,30 @@ "lodash": "^4.17.10" } }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "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.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -15415,9 +15125,18 @@ "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=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, "load-json-file": { @@ -15483,23 +15202,13 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "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=", + "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": "^3.0.0" + "ansi-regex": "^2.0.0" } }, "supports-color": { @@ -15531,6 +15240,15 @@ "y18n": "^3.2.1", "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" + } } } }, @@ -15563,7 +15281,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -15587,26 +15305,13 @@ "webpack-log": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", - "integrity": "sha1-pLNM2msitRjbsKsy5WeWLVxypD0=", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", "dev": true, "requires": { "chalk": "^2.1.0", "log-symbols": "^2.1.0", "loglevelnext": "^1.0.1", "uuid": "^3.1.0" - }, - "dependencies": { - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } } }, "webpack-sources": { @@ -15665,6 +15370,12 @@ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "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 + }, "braces": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", @@ -15771,6 +15482,12 @@ } } }, + "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", @@ -15871,6 +15588,12 @@ "isarray": "1.0.0" } }, + "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", @@ -16043,6 +15766,15 @@ } } }, + "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" + } + }, "vinyl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", @@ -16173,6 +15905,43 @@ "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" + }, + "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 + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, "wrappy": { @@ -16243,9 +16012,9 @@ "dev": true }, "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", "dev": true, "requires": { "camelcase": "^4.1.0" diff --git a/package.json b/package.json index 8170092153a..c128f010145 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.39.0-pre", + "version": "1.39.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3f5bcf2af251f9d85af33f274e69027822c90399 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 23 Jan 2019 15:31:36 -0500 Subject: [PATCH 0952/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c128f010145..36cfed18bd9 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.39.0", + "version": "1.40.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From a8eb239f858d6232ac57bcdadd8f2af8ab565583 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Thu, 24 Jan 2019 17:13:07 -0800 Subject: [PATCH 0953/1594] Frank fpd issue (#3455) * Changing to requestId in order to align with prebid cores mapping of bidId to responseId * Rubi Bid Adapter: Do not pass non-array FPD to Frank Video * Updating based on review + tests --- modules/rubiconBidAdapter.js | 22 ++++++++++++++------- test/spec/modules/rubiconBidAdapter_spec.js | 14 ++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index c851184ad65..eec078111ad 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -144,18 +144,26 @@ export const spec = { slotData.language = params.video.language; } - if (params.inventory && typeof params.inventory === 'object') { - slotData.inventory = params.inventory; - } + // Add visitor and inventory FPD values + // Frank expects the vales in each inventory and visitor fpd to be an array. so params.inventory.something === [] of some sort, otherwise it 400s + ['inventory', 'visitor'].forEach(function(key) { + if (params[key] && typeof params[key] === 'object') { + slotData[key] = {}; + Object.keys(params[key]).forEach(function(fpdKey) { + let value = params[key][fpdKey]; + if (Array.isArray(value)) { + slotData[key][fpdKey] = value; + } else if ((typeof value === 'string' && value !== '') || typeof value === 'number') { + slotData[key][fpdKey] = [value]; + } + }); + } + }); if (params.keywords && Array.isArray(params.keywords)) { slotData.keywords = params.keywords; } - if (params.visitor && typeof params.visitor === 'object') { - slotData.visitor = params.visitor; - } - data.slots.push(slotData); if (bidderRequest.gdprConsent) { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 6507747d7ad..7e66bc2a301 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -274,7 +274,7 @@ describe('the rubicon adapter', function () { userId: '12346', keywords: ['a', 'b', 'c'], inventory: { - rating: '5-star', + rating: '5-star', // This actually should not be sent to frank!! causes 400 prodtype: ['tech', 'mobile'] }, visitor: { @@ -1146,7 +1146,7 @@ describe('the rubicon adapter', function () { expect(slot.size_id).to.equal(201); expect(slot).to.have.property('inventory').that.is.an('object'); - expect(slot.inventory).to.have.property('rating').that.equals('5-star'); + expect(slot.inventory).to.have.property('rating').that.deep.equals(['5-star']); expect(slot.inventory).to.have.property('prodtype').that.deep.equals(['tech', 'mobile']); expect(slot).to.have.property('keywords') @@ -1155,8 +1155,8 @@ describe('the rubicon adapter', function () { .that.deep.equals(['a', 'b', 'c']); expect(slot).to.have.property('visitor').that.is.an('object'); - expect(slot.visitor).to.have.property('ucat').that.equals('new'); - expect(slot.visitor).to.have.property('lastsearch').that.equals('iphone'); + expect(slot.visitor).to.have.property('ucat').that.deep.equals(['new']); + expect(slot.visitor).to.have.property('lastsearch').that.deep.equals(['iphone']); expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); }); @@ -1210,7 +1210,7 @@ describe('the rubicon adapter', function () { expect(slot.size_id).to.equal(201); expect(slot).to.have.property('inventory').that.is.an('object'); - expect(slot.inventory).to.have.property('rating').that.equals('5-star'); + expect(slot.inventory).to.have.property('rating').that.deep.equals(['5-star']); expect(slot.inventory).to.have.property('prodtype').that.deep.equals(['tech', 'mobile']); expect(slot).to.have.property('keywords') @@ -1219,8 +1219,8 @@ describe('the rubicon adapter', function () { .that.deep.equals(['a', 'b', 'c']); expect(slot).to.have.property('visitor').that.is.an('object'); - expect(slot.visitor).to.have.property('ucat').that.equals('new'); - expect(slot.visitor).to.have.property('lastsearch').that.equals('iphone'); + expect(slot.visitor).to.have.property('ucat').that.deep.equals(['new']); + expect(slot.visitor).to.have.property('lastsearch').that.deep.equals(['iphone']); expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); }); From 2c04c0168b14ec6c6f5a28b831b95c71a46907b5 Mon Sep 17 00:00:00 2001 From: Vedant Seta Date: Mon, 28 Jan 2019 19:07:46 +0530 Subject: [PATCH 0954/1594] Media.net : Native support added (#3442) --- modules/medianetBidAdapter.js | 16 +- modules/medianetBidAdapter.md | 46 ++++- test/spec/modules/medianetBidAdapter_spec.js | 181 +++++++++++++++++++ 3 files changed, 239 insertions(+), 4 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index cc00f7c1ea4..8236fb0888c 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -2,6 +2,7 @@ import { registerBidder } from '../src/adapters/bidderFactory'; import * as utils from '../src/utils'; import { config } from '../src/config'; import * as url from '../src/url'; +import { BANNER, NATIVE } from '../src/mediaTypes'; const BIDDER_CODE = 'medianet'; const BID_URL = '//prebid.media.net/rtb/prebid'; @@ -138,9 +139,18 @@ function slotParams(bidRequest) { dfp_id: bidRequest.adUnitCode, display_count: bidRequest.bidRequestsCount }, - banner: transformSizes(bidRequest.sizes), all: bidRequest.params }; + if (bidRequest.sizes.length > 0) { + params.banner = transformSizes(bidRequest.sizes); + } + if (bidRequest.nativeParams) { + try { + params.native = JSON.stringify(bidRequest.nativeParams); + } catch (e) { + utils.logError((`${BIDDER_CODE} : Incorrect JSON : bidRequest.nativeParams`)); + } + } if (bidRequest.params.crid) { params.tagid = bidRequest.params.crid.toString(); @@ -151,7 +161,7 @@ function slotParams(bidRequest) { params.bidfloor = bidFloor; } const coordinates = getCoordinates(bidRequest.adUnitCode); - if (coordinates) { + if (coordinates && params.banner && params.banner.length !== 0) { let normCoordinates = normalizeCoordinates(coordinates); params.ext.coordinates = normCoordinates; params.ext.viewability = getSlotVisibility(coordinates.top_left, getMinSize(params.banner)); @@ -268,6 +278,8 @@ export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [BANNER, NATIVE], + /** * Determines whether or not the given bid request is valid. * diff --git a/modules/medianetBidAdapter.md b/modules/medianetBidAdapter.md index 2edb120033e..a29ee056a88 100644 --- a/modules/medianetBidAdapter.md +++ b/modules/medianetBidAdapter.md @@ -30,7 +30,7 @@ var adUnits = [{ }]; ``` -# Ad Unit and Setup: For Testing +# Ad Unit and Setup: For Testing (Banner) ```html @@ -56,4 +56,46 @@ var adUnits = [{ pbjs.que = pbjs.que || []; -``` \ No newline at end of file +``` + + +# Ad Unit and Setup: For Testing (Native) + +```html + + + diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 331b36b3217..336a86a7793 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -73,6 +73,101 @@ let VALID_BID_REQUEST = [{ 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'bidRequestsCount': 1 }], + VALID_NATIVE_BID_REQUEST = [{ + 'bidder': 'medianet', + 'params': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + 'sizes': [[300, 250]], + 'bidId': '28f8f8130a583e', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1, + 'nativeParams': { + 'image': { + 'required': true, + 'sizes': [ + 150, + 50 + ], + 'wmin': 50 + }, + 'title': { + 'required': true, + 'len': 80 + }, + 'sponsoredBy': { + 'required': true + }, + 'clickUrl': { + 'required': true + }, + 'body': { + 'required': true + }, + 'icon': { + 'required': true, + 'sizes': [ + 50, + 50 + ] + } + } + }, { + 'bidder': 'medianet', + 'params': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-123', + 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + 'sizes': [[300, 251]], + 'bidId': '3f97ca71b1e5c2', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1, + 'nativeParams': { + 'image': { + 'required': true, + 'sizes': [ + 150, + 50 + ], + 'wmin': 50 + }, + 'title': { + 'required': true, + 'len': 80 + }, + 'sponsoredBy': { + 'required': true + }, + 'clickUrl': { + 'required': true + }, + 'body': { + 'required': true + }, + 'icon': { + 'required': true, + 'sizes': [ + 50, + 50 + ] + } + } + }], VALID_AUCTIONDATA = { 'timeout': config.getConfig('bidderTimeout'), }, @@ -156,6 +251,87 @@ let VALID_BID_REQUEST = [{ }], 'tmax': config.getConfig('bidderTimeout') }, + VALID_PAYLOAD_NATIVE = { + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + }, + 'ext': { + 'customer_id': 'customer_id', + 'prebid_version': $$PREBID_GLOBAL$$.version, + 'gdpr_applies': false, + 'screen': { + 'w': 1000, + 'h': 1000 + } + }, + 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'imp': [{ + 'id': '28f8f8130a583e', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-0', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 + }, + 'banner': [{ + 'w': 300, + 'h': 250 + }], + 'native': '{\"image\":{\"required\":true,\"sizes\":[150,50],\"wmin\":50},\"title\":{\"required\":true,\"len\":80},\"sponsoredBy\":{\"required\":true},\"clickUrl\":{\"required\":true},\"body\":{\"required\":true},\"icon\":{\"required\":true,\"sizes\":[50,50]}}', + 'all': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + } + }, { + 'id': '3f97ca71b1e5c2', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-123', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 + }, + 'banner': [{ + 'w': 300, + 'h': 251 + }], + 'native': '{\"image\":{\"required\":true,\"sizes\":[150,50],\"wmin\":50},\"title\":{\"required\":true,\"len\":80},\"sponsoredBy\":{\"required\":true},\"clickUrl\":{\"required\":true},\"body\":{\"required\":true},\"icon\":{\"required\":true,\"sizes\":[50,50]}}', + 'all': { + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest' + } + } + }], + 'tmax': config.getConfig('bidderTimeout') + }, VALID_PAYLOAD = { 'site': { 'page': 'http://media.net/prebidtest', @@ -562,6 +738,11 @@ describe('Media.net bid adapter', function () { expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_FOR_GDPR); }); + it('should parse params for native request', function () { + let bidReq = spec.buildRequests(VALID_NATIVE_BID_REQUEST, VALID_AUCTIONDATA); + expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_NATIVE); + }); + describe('build requests: when page meta-data is available', () => { beforeEach(() => { spec.clearMnData(); From c729881c8e46f9d8d70e71edccb63a9927c835bb Mon Sep 17 00:00:00 2001 From: RajeshRhythmone <44564178+RajeshRhythmone@users.noreply.github.com> Date: Mon, 28 Jan 2019 19:22:41 +0530 Subject: [PATCH 0955/1594] Support Multi-Format Ads - Banner & Video (#3389) * Support Multi-Format Ads - Banner & Video * Updated gdpr default value to false, updated test placementId in rhythmoneBidAdapter.md file * Version updated --- modules/rhythmoneBidAdapter.js | 278 +++++++++------- modules/rhythmoneBidAdapter.md | 8 +- test/spec/modules/rhythmoneBidAdapter_spec.js | 314 ++++++++++++++---- 3 files changed, 414 insertions(+), 186 deletions(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index bf00323c917..29572c228fe 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -1,5 +1,6 @@ 'use strict'; +import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import { BANNER, VIDEO } from '../src/mediaTypes'; @@ -7,6 +8,17 @@ function RhythmOneBidAdapter() { this.code = 'rhythmone'; this.supportedMediaTypes = [VIDEO, BANNER]; + let SUPPORTED_VIDEO_PROTOCOLS = [2, 3, 5, 6]; + let SUPPORTED_VIDEO_MIMES = ['video/mp4']; + let SUPPORTED_VIDEO_PLAYBACK_METHODS = [1, 2, 3, 4]; + let SUPPORTED_VIDEO_DELIVERY = [1]; + let SUPPORTED_VIDEO_API = [1, 2, 5]; + let slotsToBids = {}; + let that = this; + let version = '1.0.2.1'; + let loadStart = Date.now(); + var win = typeof window !== 'undefined' ? window : {}; + this.isBidRequestValid = function (bid) { return true; }; @@ -53,7 +65,7 @@ function RhythmOneBidAdapter() { data.bidder_version = version; if (gdprConsent) { data.gdpr_consent = gdprConsent.consentString; - data.gdpr = (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : true; + data.gdpr = (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : false; } for (let k in data) { @@ -70,151 +82,165 @@ function RhythmOneBidAdapter() { } }; - function getFirstParam(key, validBidRequests) { - for (let i = 0; i < validBidRequests.length; i++) { - if (validBidRequests[i].params && validBidRequests[i].params[key]) { - return validBidRequests[i].params[key]; + function frameImp(BRs) { + var imp = []; + for (var i = 0; i < BRs.length; i++) { + slotsToBids[BRs[i].adUnitCode || BRs[i].placementCode] = BRs[i]; + var impObj = {}; + impObj.id = BRs[i].adUnitCode; + impObj.bidfloor = parseFloat(utils.deepAccess(BRs[i], 'params.floor')) || 0; + impObj.secure = win.location.protocol === 'https:' ? 1 : 0; + if (utils.deepAccess(BRs[i], 'mediaTypes.banner') || utils.deepAccess(BRs[i], 'mediaType') === 'banner') { + impObj.banner = frameBanner(BRs[i]); } + if (utils.deepAccess(BRs[i], 'mediaTypes.video') || utils.deepAccess(BRs[i], 'mediaType') === 'video') { + impObj.video = frameVideo(BRs[i]); + } + impObj.ext = frameExt(BRs[i]); + imp.push(impObj); } + return imp; } - let slotsToBids = {}; - let that = this; - let version = '1.0.1.0'; - let loadStart = Date.now(); - - this.buildRequests = function (BRs, bidderRequest) { - let fallbackPlacementId = getFirstParam('placementId', BRs); - if (fallbackPlacementId === undefined || BRs.length < 1) { - return []; + function frameSite(bidderRequest) { + return { + domain: attempt(function() { + var d = win.document.location.ancestorOrigins; + if (d && d.length > 0) { + return d[d.length - 1]; + } + return win.top.document.location.hostname; // try/catch is in the attempt function + }, ''), + page: attempt(function() { + var l; + // try/catch is in the attempt function + try { + l = win.top.document.location.href.toString(); + } catch (ex) { + l = win.document.location.href.toString(); + } + return l; + }, ''), + ref: attempt(function() { + if (bidderRequest && bidderRequest.refererInfo) { + return bidderRequest.refererInfo.referer; + } + return ''; + }, '') } + } - loadStart = Date.now(); - slotsToBids = {}; - - let query = []; - let w = (typeof window !== 'undefined' ? window : {}); - - function p(k, v, d) { - if (v instanceof Array) { v = v.join((d || ',')); } - if (typeof v !== 'undefined') { query.push(encodeURIComponent(k) + '=' + encodeURIComponent(v)); } + function frameDevice() { + return { + ua: navigator.userAgent, + devicetype: /(ios|ipod|ipad|iphone|android)/i.test(win.navigator.userAgent) ? 1 : /(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i.test(win.navigator.userAgent) ? 3 : 2, + ip: '', // Empty Ip string is required, server gets the ip from HTTP header + dnt: utils.getDNT() ? 1 : 0, } + } - function attempt(valueFunction, defaultValue) { - try { - return valueFunction(); - } catch (ex) { } - return defaultValue; + function frameBanner(bid) { + var sizes = utils.parseSizesInput(bid.sizes).map(size => size.split('x')); + return { + w: parseInt(sizes[0][0]), + h: parseInt(sizes[0][1]) } + } - p('domain', attempt(function() { - var d = w.document.location.ancestorOrigins; - if (d && d.length > 0) { - return d[d.length - 1]; + function frameVideo(bid) { + var size = []; + if (utils.deepAccess(bid, 'mediaTypes.video.playerSize')) { + if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { + size = bid.mediaTypes.video.playerSize[0]; + } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { + size = bid.mediaTypes.video.playerSize; } - return w.top.document.location.hostname; // try/catch is in the attempt function - }, '')); - p('url', attempt(function() { - var l; - // try/catch is in the attempt function - try { - l = w.top.document.location.href.toString(); - } catch (ex) { - l = w.document.location.href.toString(); + } + return { + 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: 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, + } + } + + function frameExt(bid) { + return { + bidder: { + placementId: (bid.params && bid.params['placementId']) ? bid.params['placementId'] : '', + zone: (bid.params && bid.params['zone']) ? bid.params['zone'] : '1r', + path: (bid.params && bid.params['path']) ? bid.params['path'] : 'mvo' } - return l; - }, '')); - - function getRMPUrl() { - let url = getFirstParam('endpoint', BRs) || '//tag.1rx.io/rmp/{placementId}/0/{path}?z={zone}'; - let defaultZone = getFirstParam('zone', BRs) || '1r'; - let defaultPath = getFirstParam('path', BRs) || 'mvo'; - - url = url.replace(/\{placementId\}/i, fallbackPlacementId); - url = url.replace(/\{zone\}/i, defaultZone); - url = url.replace(/\{path\}/i, defaultPath); - - p('title', attempt(function() { return w.top.document.title; }, '')); // try/catch is in the attempt function - p('dsh', (w.screen ? w.screen.height : '')); - p('dsw', (w.screen ? w.screen.width : '')); - p('tz', (new Date()).getTimezoneOffset()); - p('dtype', ((/(ios|ipod|ipad|iphone|android)/i).test(w.navigator.userAgent) ? 1 : ((/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(w.navigator.userAgent) ? 3 : 2))); - p('flash', attempt(function() { - let n = w.navigator; - let p = n.plugins; - let m = n.mimeTypes; - let t = 'application/x-shockwave-flash'; - let x = w.ActiveXObject; - - if (p && - p['Shockwave Flash'] && - m && - m[t] && - m[t].enabledPlugin) { - return 1; - } + } + } - if (x) { - try { - if ((new w.ActiveXObject('ShockwaveFlash.ShockwaveFlash'))) { - return 1; - } - } catch (e) { } + function frameBid(BRs, bidderRequest) { + return { + id: BRs[0].bidderRequestId, + imp: frameImp(BRs), + site: frameSite(bidderRequest), + device: frameDevice(), + user: { + ext: { + consent: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? bidderRequest.gdprConsent.consentString : '' } + }, + at: 1, + tmax: 1000, + regs: { + ext: { + gdpr: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? Boolean(bidderRequest.gdprConsent.gdprApplies & 1) : false + } + } + }; + } - return 0; - }, 0)); - - let heights = []; - let widths = []; - let floors = []; - let mediaTypes = []; - let i = 0; - let configuredPlacements = []; - let fat = /(^v|(\.0)+$)/gi; - - p('hbv', w.$$PREBID_GLOBAL$$.version.replace(fat, '') + ',' + version.replace(fat, '')); + function getFirstParam(key, validBidRequests) { + for (let i = 0; i < validBidRequests.length; i++) { + if (validBidRequests[i].params && validBidRequests[i].params[key]) { + return validBidRequests[i].params[key]; + } + } + } - for (; i < BRs.length; i++) { - let th = []; - let tw = []; - let params = BRs[i].params || {}; + function attempt(valueFunction, defaultValue) { + try { + return valueFunction(); + } catch (ex) { } + return defaultValue; + } - slotsToBids[BRs[i].adUnitCode || BRs[i].placementCode] = BRs[i]; + this.buildRequests = function (BRs, bidderRequest) { + let fallbackPlacementId = getFirstParam('placementId', BRs); + if (fallbackPlacementId === undefined || BRs.length < 1) { + return []; + } - if (BRs[i].sizes.length > 0 && typeof BRs[i].sizes[0] === 'number') { - BRs[i].sizes = [BRs[i].sizes]; - } + var rmpUrl = getFirstParam('endpoint', BRs) || '//tag.1rx.io/rmp/{placementId}/0/{path}?z={zone}'; + var defaultZone = getFirstParam('zone', BRs) || '1r'; + var defaultPath = getFirstParam('path', BRs) || 'mvo'; - for (let j = 0; j < BRs[i].sizes.length; j++) { - tw.push(BRs[i].sizes[j][0]); - th.push(BRs[i].sizes[j][1]); - } - configuredPlacements.push(BRs[i].adUnitCode || BRs[i].placementCode); - heights.push(th.join('|')); - widths.push(tw.join('|')); - mediaTypes.push((BRs[i].mediaTypes && BRs[i].mediaTypes.video ? 'v' : 'd')); - floors.push(params.floor || 0); - } + rmpUrl = rmpUrl.replace(/\{placementId\}/i, fallbackPlacementId); + rmpUrl = rmpUrl.replace(/\{zone\}/i, defaultZone); + rmpUrl = rmpUrl.replace(/\{path\}/i, defaultPath); - p('imp', configuredPlacements); - p('w', widths); - p('h', heights); - p('floor', floors); - p('t', mediaTypes); - if (bidderRequest && bidderRequest.gdprConsent) { - p('gdpr_consent', bidderRequest.gdprConsent.consentString); - p('gdpr', (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true); - } - url += '&' + query.join('&') + '&'; + var fat = /(^v|(\.0)+$)/gi; + var prebidVersion = '$prebid.version$'; + rmpUrl += '&hbv=' + prebidVersion.replace(fat, '') + ',' + version.replace(fat, ''); - return url; - } + var bidRequest = frameBid(BRs, bidderRequest); + loadStart = Date.now(); - return [{ - method: 'GET', - url: getRMPUrl() - }]; + return { + method: 'POST', + url: rmpUrl, + data: JSON.stringify(bidRequest) + }; }; this.interpretResponse = function (serverResponse) { @@ -244,13 +270,13 @@ function RhythmOneBidAdapter() { creativeId: bid.crid, currency: 'USD', netRevenue: true, - ttl: 1000 + ttl: 350 }; if (bidRequest.mediaTypes && bidRequest.mediaTypes.video) { bidResponse.vastUrl = bid.nurl; bidResponse.mediaType = 'video'; - bidResponse.ttl = 10000; + bidResponse.ttl = 600; } else { bidResponse.ad = bid.adm; } diff --git a/modules/rhythmoneBidAdapter.md b/modules/rhythmoneBidAdapter.md index d08baaecea8..ec3ee4852e5 100644 --- a/modules/rhythmoneBidAdapter.md +++ b/modules/rhythmoneBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: RhythmOne Bidder Adapter Module Type: Bidder Adapter -Maintainer: astocker@rhythmone.com +Maintainer: support@rhythmone.com ``` # Description @@ -23,8 +23,10 @@ const adUnits = [{ bidder: 'rhythmone', params: { - placementId: '411806', - endpoint: "//tag.1rx.io/rmp/72721/0/mvo?z=1r" // only required for testing. this api guarantees no 204 responses + placementId: '80184', // REQUIRED + zone: '1r', // OPTIONAL + path: 'mvo', // OPTIONAL + endpoint: "//tag.1rx.io/rmp/80184/0/mvo?z=1r" // OPTIONAL, only required for testing. this api guarantees no 204 responses } } ] diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index 2f06e7f8288..98a7731c324 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -2,43 +2,74 @@ import {spec} from '../../../modules/rhythmoneBidAdapter'; var assert = require('assert'); describe('rhythmone adapter tests', function () { - describe('auditBeacon', function() { - var z = spec; - var beaconURL = z.getUserSyncs({pixelEnabled: true})[0]; - - it('should contain the correct path', function() { - var u = '//hbevents.1rx.io/audit?' - assert.equal(beaconURL.url.substring(0, u.length), u); - }); - }); - describe('rhythmoneResponse', function () { var z = spec; - var rmpRequest = z.buildRequests( + var rmpBannerRequest = z.buildRequests( [ { 'bidder': 'rhythmone', 'params': { - 'placementId': 'xyz', + 'placementId': 'abc', 'keywords': '', 'categories': [], 'trace': true, - 'method': 'get', - 'endpoint': 'http://fakedomain.com' + 'zone': '2345', + 'path': 'mvo', + 'method': 'POST' }, - 'mediaType': 'video', + 'mediaType': 'banner', 'adUnitCode': 'div-gpt-ad-1438287399331-0', 'sizes': [[300, 250]] } - ] + ], { 'refererInfo': { 'referer': 'Reference Page' } } ); - it('should have one request to RMP', function() { - assert.equal(rmpRequest.length, 1); + it('Verify POST Banner Bid Request', function () { + expect(rmpBannerRequest.url).to.have.string('//tag.1rx.io/rmp/abc/0/mvo?z=2345&hbv='); + expect(rmpBannerRequest.method).to.equal('POST'); + const bidRequest = JSON.parse(rmpBannerRequest.data); + expect(bidRequest.site).to.not.equal(null); + expect(bidRequest.site.ref).to.equal('Reference Page'); + expect(bidRequest.device).to.not.equal(null); + expect(bidRequest.device.ua).to.equal(navigator.userAgent); + expect(bidRequest.device).to.have.property('dnt'); + expect(bidRequest.imp[0].banner).to.not.equal(null); + expect(bidRequest.imp[0].banner.w).to.equal(300); + expect(bidRequest.imp[0].banner.h).to.equal(250); + expect(bidRequest.imp[0].ext.bidder.zone).to.equal('2345'); + expect(bidRequest.imp[0].ext.bidder.path).to.equal('mvo'); + }); + + var bannerBids = z.interpretResponse({ + body: [ + { + 'impid': 'div-gpt-ad-1438287399331-0', + 'w': 300, + 'h': 250, + 'adm': '
My ad4 with cpm of a4ab3485f434f74f
', + 'price': 1, + 'crid': 'cr-cfy24' + } + ] + }); + + it('should register one bid', function() { + assert.equal(bannerBids.length, 1); }); - var mangoRequest = z.buildRequests( + it('Verify parse banner response', function() { + const bid = bannerBids[0]; + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.creativeId).to.equal('cr-cfy24'); + expect(bid.currency).to.equal('USD'); + expect(bid.netRevenue).to.equal(true); + expect(bid.cpm).to.equal(1.0); + expect(bid.ttl).to.equal(350); + }); + + var rmpVideoRequest = z.buildRequests( [ { 'bidder': 'rhythmone', @@ -47,18 +78,70 @@ describe('rhythmone adapter tests', function () { 'keywords': '', 'categories': [], 'trace': true, - 'method': 'get', - 'api': 'mango', - 'endpoint': 'http://fakedomain.com' + 'method': 'POST' }, - 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'mediaTypes': { + 'video': { + 'playerSize': [[640, 480]], + 'context': 'instream' + } + }, + 'placementCode': 'div-gpt-ad-1438287399331-1', 'sizes': [[300, 250]] } - ] + ], { 'refererInfo': { 'referer': 'Reference Page' } } ); - it('should have one request to Mango', function() { - assert.equal(mangoRequest.length, 1); + it('Verify POST Video Bid Request', function () { + expect(rmpVideoRequest.url).to.have.string('//tag.1rx.io/rmp/xyz/0/mvo?z=1r&hbv='); + expect(rmpVideoRequest.method).to.equal('POST'); + const bidRequest = JSON.parse(rmpVideoRequest.data); + expect(bidRequest.site).to.not.equal(null); + expect(bidRequest.device).to.not.equal(null); + expect(bidRequest.device.ua).to.equal(navigator.userAgent); + expect(bidRequest.device).to.have.property('dnt'); + expect(bidRequest.imp[0].video).to.not.equal(null); + expect(bidRequest.imp[0].video.w).to.equal(640); + expect(bidRequest.imp[0].video.h).to.equal(480); + expect(bidRequest.imp[0].video.mimes[0]).to.equal('video/mp4'); + expect(bidRequest.imp[0].video.protocols).to.eql([2, 3, 5, 6]); + expect(bidRequest.imp[0].video.startdelay).to.equal(0); + expect(bidRequest.imp[0].video.skip).to.equal(0); + expect(bidRequest.imp[0].video.playbackmethod).to.eql([1, 2, 3, 4]); + expect(bidRequest.imp[0].video.delivery[0]).to.equal(1); + expect(bidRequest.imp[0].video.api).to.eql([1, 2, 5]); + }); + + var videoBids = z.interpretResponse({ + body: [ + { + 'impid': 'div-gpt-ad-1438287399331-1', + 'price': 1, + 'nurl': 'http://testdomain/rmp/placementid/0/path?reqId=1636037', + 'adomain': ['test.com'], + 'cid': '467415', + 'crid': 'cr-vid', + 'w': 800, + 'h': 600 + } + ] + }); + + it('should register one bid', function() { + assert.equal(videoBids.length, 1); + }); + + it('Verify parse video response', function() { + const bid = videoBids[0]; + expect(bid.width).to.equal(800); + expect(bid.height).to.equal(600); + expect(bid.vastUrl).to.equal('http://testdomain/rmp/placementid/0/path?reqId=1636037'); + expect(bid.mediaType).to.equal('video'); + expect(bid.creativeId).to.equal('cr-vid'); + expect(bid.currency).to.equal('USD'); + expect(bid.netRevenue).to.equal(true); + expect(bid.cpm).to.equal(1.0); + expect(bid.ttl).to.equal(600); }); it('should send GDPR Consent data to RhythmOne tag', function () { @@ -72,48 +155,165 @@ describe('rhythmone adapter tests', function () { 'keywords': '', 'categories': [], 'trace': true, - 'method': 'get', - 'api': 'mango', - 'endpoint': 'http://fakedomain.com?' + 'method': 'POST' }, - 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'adUnitCode': 'div-gpt-ad-1438287399331-3', 'sizes': [[300, 250]] } - ], {gdprConsent: {gdprApplies: 1, consentString: _consentString}} + ], {'gdprConsent': {'gdprApplies': true, 'consentString': _consentString}, 'refererInfo': { 'referer': 'Reference Page' }} ); - assert.equal(getURLParam(request[0].url, 'gdpr'), 'true'); - assert.equal(getURLParam(request[0].url, 'gdpr_consent'), 'testConsentString'); + const bidRequest = JSON.parse(request.data); + expect(bidRequest.user.ext.consent).to.equal(_consentString); + expect(bidRequest.regs.ext.gdpr).to.equal(true); }); - var bids = z.interpretResponse({ - body: [ + var rmpMultiFormatRequest = z.buildRequests( + [ { - 'impid': 'div-gpt-ad-1438287399331-0', - 'w': 300, - 'h': 250, - 'adm': '
My ad4 with cpm of a4ab3485f434f74f
', - 'price': 1, - 'crid': 'cr-cfy24' + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'xyz', + 'keywords': '', + 'categories': [], + 'trace': true, + 'zone': '2345', + 'path': 'mvo', + 'method': 'POST' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [ + [300, 250] + ] + }, + 'video': { + 'playerSize': [[640, 480]], + 'context': 'instream' + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-5', + 'sizes': [[300, 250]] } - ] + ], { 'refererInfo': { 'referer': 'Reference Page' } } + ); + + it('Verify Multi-Format ads Bid Request', function () { + const bidRequest = JSON.parse(rmpMultiFormatRequest.data); + expect(bidRequest.site).to.not.equal(null); + expect(bidRequest.site.ref).to.equal('Reference Page'); + expect(bidRequest.device).to.not.equal(null); + expect(bidRequest.device.ua).to.equal(navigator.userAgent); + expect(bidRequest.device).to.have.property('dnt'); + expect(bidRequest.imp[0].video).to.not.equal(null); + expect(bidRequest.imp[0].video.w).to.equal(640); + expect(bidRequest.imp[0].video.h).to.equal(480); + expect(bidRequest.imp[0].video.mimes[0]).to.equal('video/mp4'); + expect(bidRequest.imp[0].video.protocols).to.eql([2, 3, 5, 6]); + expect(bidRequest.imp[0].video.startdelay).to.equal(0); + expect(bidRequest.imp[0].video.skip).to.equal(0); + expect(bidRequest.imp[0].video.playbackmethod).to.eql([1, 2, 3, 4]); + expect(bidRequest.imp[0].video.delivery[0]).to.equal(1); + expect(bidRequest.imp[0].video.api).to.eql([1, 2, 5]); + expect(bidRequest.imp[0].banner).to.not.equal(null); + expect(bidRequest.imp[0].banner.w).to.equal(300); + expect(bidRequest.imp[0].banner.h).to.equal(250); + expect(bidRequest.imp[0].ext.bidder.zone).to.equal('2345'); + expect(bidRequest.imp[0].ext.bidder.path).to.equal('mvo'); + }); + + var forRMPMultiFormatResponse = z.interpretResponse({ + body: { + 'id': '1e810245dd1779', + 'seatbid': [ { + 'bid': [ { + 'impid': 'div-gpt-ad-1438287399331-5', + 'price': 1, + 'nurl': 'http://testdomain/rmp/placementid/0/path?reqId=1636037', + 'adomain': ['test.com'], + 'cid': '467415', + 'crid': 'cr-vid', + 'w': 800, + 'h': 600 + } ] + } ] + } }); it('should register one bid', function() { - assert.equal(bids.length, 1); - }); - function getURLParam(url, key) { - let val = ''; - if (url.indexOf('?') > -1) { - let qs = url.substr(url.indexOf('?')); - let qsArr = qs.split('&'); - for (let i = 0; i < qsArr.length; i++) { - if (qsArr[i].indexOf(key.toLowerCase() + '=') > -1) { - val = qsArr[i].split('=')[1] - break; + assert.equal(forRMPMultiFormatResponse.length, 1); + }); + + it('Verify parse for multi format ad response', function() { + const bid = forRMPMultiFormatResponse[0]; + expect(bid.width).to.equal(800); + expect(bid.height).to.equal(600); + expect(bid.vastUrl).to.equal('http://testdomain/rmp/placementid/0/path?reqId=1636037'); + expect(bid.mediaType).to.equal('video'); + expect(bid.creativeId).to.equal('cr-vid'); + expect(bid.currency).to.equal('USD'); + expect(bid.netRevenue).to.equal(true); + expect(bid.cpm).to.equal(1.0); + expect(bid.ttl).to.equal(600); + }); + + var noBidResponse = z.interpretResponse({ + body: '' + }); + + it('No bid response', function() { + assert.equal(noBidResponse.length, 0); + }); + describe('isRequiredParamPresent', function () { + var rmpBannerRequest = z.buildRequests( + [ + { + 'bidder': 'rhythmone', + 'params': { + 'keywords': '', + 'categories': [], + 'trace': true, + 'zone': '2345', + 'path': 'mvo', + 'method': 'POST' + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]] } - } - } - return val; - } + ], { 'refererInfo': { 'referer': 'Reference Page' } } + ); + + it('should return empty when required params not found', function () { + expect(rmpBannerRequest).to.be.empty; + }); + }); + }); + describe('auditBeacon', function() { + var z = spec; + var beaconURL = z.getUserSyncs({pixelEnabled: true})[0]; + + it('should contain the correct path', function() { + var u = '//hbevents.1rx.io/audit?'; + assert.equal(beaconURL.url.substring(0, u.length), u); + }); + + beaconURL = z.getUserSyncs({pixelEnabled: true}, null, {'gdprApplies': true, 'consentString': 'testConsentString'})[0]; + it('should send GDPR Consent data to Sync pixel', function () { + expect(beaconURL.url).to.have.string('&gdpr=true&gdpr_consent=testConsentString'); + }); + }); + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'rhythmone', + 'params': { + 'placementId': '469127' + }, + 'adUnitCode': 'bannerDiv', + 'sizes': [[300, 250]] + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); }); }); From 7bb5c7985b75f1eff659e81858e073f022ab2a8c Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Mon, 28 Jan 2019 15:21:19 +0000 Subject: [PATCH 0956/1594] Added 250x600 size (#3486) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index eec078111ad..b076df68474 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -73,6 +73,7 @@ var sizeMap = { 144: '980x600', 145: '980x150', 159: '320x250', + 179: '250x600', 195: '600x300', 198: '640x360', 199: '640x200', From af9ec3fb340d2c25c996a741e3f869dbbf1015d3 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 28 Jan 2019 08:27:13 -0700 Subject: [PATCH 0957/1594] remove old dependencies and solve some peer dependencies (#3456) * remove old dependencies and solve some peer dependencies * resolve package lock conflict * add coveralls dependency --- package-lock.json | 1031 ++++------------- package.json | 25 +- .../e2e/custom-reporter/pbjs-html-reporter.js | 5 +- test/spec/modules/rubiconAnalyticsSchema.json | 4 +- 4 files changed, 225 insertions(+), 840 deletions(-) diff --git a/package-lock.json b/package-lock.json index c992ef29074..a6e0970a93e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.39.0", + "version": "1.40.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -764,6 +764,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "dev": true, "requires": { "acorn": "^5.0.3", "css": "^2.2.1", @@ -776,6 +777,7 @@ "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" @@ -859,7 +861,8 @@ "acorn": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true }, "acorn-dynamic-import": { "version": "2.0.2", @@ -911,11 +914,12 @@ } }, "ajv": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", - "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", + "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" @@ -999,15 +1003,11 @@ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", "dev": true }, - "ansi-regex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", - "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==" - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -1056,6 +1056,7 @@ "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.2" } @@ -1202,6 +1203,7 @@ "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.0" } @@ -1246,7 +1248,8 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true }, "assertion-error": { "version": "1.1.0", @@ -1316,32 +1319,26 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true }, "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=" + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true }, "aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "axios": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", - "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", - "dev": true, - "requires": { - "follow-redirects": "^1.2.5", - "is-buffer": "^1.1.5" - } + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true }, "babel-code-frame": { "version": "6.26.0", @@ -2616,6 +2613,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, "requires": { "tweetnacl": "^0.14.3" } @@ -2761,15 +2759,6 @@ } } }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3083,7 +3072,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3157,7 +3146,8 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true }, "ccount": { "version": "1.0.3", @@ -3438,6 +3428,7 @@ "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, "requires": { "color-name": "1.1.3" } @@ -3445,7 +3436,8 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "color-support": { "version": "1.1.3", @@ -3472,6 +3464,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -3487,7 +3480,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -3614,6 +3607,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -3648,12 +3642,14 @@ "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=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "coveralls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.2.tgz", "integrity": "sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw==", + "dev": true, "requires": { "growl": "~> 1.10.0", "js-yaml": "^3.11.0", @@ -3711,15 +3707,6 @@ "which": "^1.2.9" } }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.x.x" - } - }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -3748,6 +3735,7 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, "requires": { "inherits": "^2.0.3", "source-map": "^0.6.1", @@ -3774,6 +3762,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, "requires": { "es5-ext": "^0.10.9" } @@ -3782,6 +3771,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -3821,6 +3811,7 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, "requires": { "ms": "^2.1.1" } @@ -3829,6 +3820,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "dev": true, "requires": { "debug": "3.X", "memoizee": "0.4.X", @@ -3844,7 +3836,8 @@ "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=" + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true }, "decompress-response": { "version": "3.3.0", @@ -3999,7 +3992,8 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true }, "depd": { "version": "1.1.2", @@ -4050,7 +4044,8 @@ "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true }, "detective": { "version": "4.7.1", @@ -4394,6 +4389,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -4468,7 +4464,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4482,7 +4478,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4498,7 +4494,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4518,7 +4514,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4620,6 +4616,7 @@ "version": "0.10.47", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", + "dev": true, "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", @@ -4636,6 +4633,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, "requires": { "d": "1", "es5-ext": "^0.10.35", @@ -4688,6 +4686,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, "requires": { "d": "1", "es5-ext": "~0.10.14" @@ -4697,6 +4696,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, "requires": { "d": "1", "es5-ext": "^0.10.14", @@ -4844,7 +4844,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -5049,15 +5049,6 @@ "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", "dev": true }, - "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -5077,7 +5068,8 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "esquery": { "version": "1.0.1", @@ -5092,6 +5084,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, "requires": { "estraverse": "^4.1.0" } @@ -5099,7 +5092,8 @@ "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true }, "estree-walker": { "version": "0.3.1", @@ -5123,6 +5117,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, "requires": { "d": "1", "es5-ext": "~0.10.14" @@ -5130,7 +5125,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5308,7 +5303,8 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extend-shallow": { "version": "3.0.2", @@ -5410,7 +5406,8 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true }, "faker": { "version": "3.1.0", @@ -5433,12 +5430,14 @@ "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=" + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -5496,16 +5495,6 @@ "minimatch": "^3.0.3" } }, - "fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - } - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -5649,7 +5638,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", "dev": true }, "flush-write-stream": { @@ -5712,7 +5701,8 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true }, "fork-stream": { "version": "0.0.4", @@ -5724,6 +5714,7 @@ "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, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -6414,24 +6405,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dev": true, - "requires": { - "is-property": "^1.0.2" - } - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "^1.0.0" - } - }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -6508,6 +6481,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -6717,20 +6691,14 @@ "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" - }, - "grunt-coveralls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-coveralls/-/grunt-coveralls-2.0.0.tgz", - "integrity": "sha1-2WkGQB8xIrW30ojr2XP2r6OFuiQ=", - "requires": { - "coveralls": "^3.0.0" - } + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true }, "gulp": { "version": "4.0.0", @@ -6957,28 +6925,6 @@ } } }, - "gulp-babel": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", - "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", - "dev": true, - "requires": { - "babel-core": "^6.23.1", - "object-assign": "^4.0.1", - "plugin-error": "^1.0.1", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - } - } - }, "gulp-clean": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", @@ -7161,7 +7107,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7178,251 +7124,7 @@ "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 - } - } - }, - "gulp-coveralls": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/gulp-coveralls/-/gulp-coveralls-0.1.4.tgz", - "integrity": "sha1-L2IKyN9i0LhrS73mTaNnzEGhkMk=", - "dev": true, - "requires": { - "coveralls": "^2.11.2", - "gulp-util": "^3.0.4", - "through2": "^1.1.1" - }, - "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 - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "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" - } - }, - "coveralls": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", - "dev": true, - "requires": { - "js-yaml": "3.6.1", - "lcov-parse": "0.0.10", - "log-driver": "1.2.5", - "minimist": "1.2.0", - "request": "2.79.0" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" - } - }, - "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, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "js-yaml": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" - } - }, - "log-driver": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "qs": "~6.3.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1", - "uuid": "^3.0.0" - } - }, - "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=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "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 - }, - "through2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", - "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", - "dev": true, - "requires": { - "readable-stream": ">=1.1.13-1 <1.2.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "requires": { - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", "dev": true } } @@ -7620,12 +7322,6 @@ "through2": "^2.0.1" } }, - "gulp-rename": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", - "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", - "dev": true - }, "gulp-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", @@ -7653,6 +7349,7 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "dev": true, "requires": { "@gulp-sourcemaps/identity-map": "1.X", "@gulp-sourcemaps/map-sources": "1.X", @@ -7925,12 +7622,14 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true }, "har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, "requires": { "ajv": "^6.5.5", "har-schema": "^2.0.0" @@ -7940,6 +7639,7 @@ "version": "6.7.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -7958,21 +7658,6 @@ "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-3.0.0.tgz", - "integrity": "sha1-Ngd+8dFfMzSEqn+neihgbxxlWzc=", - "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - } - } - }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", @@ -7999,7 +7684,8 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "has-gulplog": { "version": "0.1.0", @@ -8123,18 +7809,6 @@ "integrity": "sha512-4JT8B0HKPHBMFZdDQzexjxwhKx9TrpV/+uelvmqlPu8RqqDrnNIEHDtDZCmgE+4YmcFAtKVPLmnY3dQGRaN53A==", "dev": true }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } - }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -8158,12 +7832,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", @@ -8203,7 +7871,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8269,6 +7937,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -8346,7 +8015,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true }, "ini": { "version": "1.3.5", @@ -8615,25 +8285,6 @@ "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", "dev": true }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", - "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", - "dev": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" - } - }, "is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", @@ -8696,12 +8347,7 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, "is-regex": { @@ -8761,7 +8407,8 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "is-unc-path": { "version": "1.0.0", @@ -8811,7 +8458,8 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true }, "isbinaryfile": { "version": "3.0.3", @@ -8837,7 +8485,8 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true }, "istanbul": { "version": "0.4.5", @@ -9080,6 +8729,7 @@ "version": "3.12.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -9088,7 +8738,8 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true }, "jsencrypt": { "version": "3.0.0-rc.1", @@ -9122,12 +8773,14 @@ "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -9138,7 +8791,8 @@ "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=" + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true }, "json5": { "version": "2.1.0", @@ -9161,16 +8815,11 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, "jsprim": { "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", @@ -9198,7 +8847,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9234,7 +8883,7 @@ "mime": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "integrity": "sha1-4FH9iBNYWF8yed8zP+aU2gvP/dY=", "dev": true }, "rimraf": { @@ -9469,7 +9118,8 @@ "lcov-parse": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=" + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true }, "lead": { "version": "1.0.0", @@ -9558,220 +9208,6 @@ } } }, - "localtunnel": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.1.tgz", - "integrity": "sha512-HWrhOslklDvxgOGFLxi6fQVnvpl6XdX4sPscfqMZkzi3gtt9V7LKBWYvNUcpHSVvjwCQ6xzXacVvICNbNcyPnQ==", - "dev": true, - "requires": { - "axios": "0.17.1", - "debug": "2.6.9", - "openurl": "1.1.1", - "yargs": "6.6.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 - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "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" - } - }, - "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" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "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=", - "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" - } - }, - "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" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "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" - } - }, - "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 - }, - "yargs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "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": "^4.2.0" - } - }, - "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - } - } - } - }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -10111,7 +9547,8 @@ "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true }, "log-symbols": { "version": "2.2.0", @@ -10125,7 +9562,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -10138,7 +9575,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", "dev": true } } @@ -10210,6 +9647,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, "requires": { "es5-ext": "~0.10.2" } @@ -10420,6 +9858,7 @@ "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, "requires": { "d": "1", "es5-ext": "^0.10.45", @@ -10549,12 +9988,6 @@ } } }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, "merge-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", @@ -10604,12 +10037,14 @@ "mime-db": { "version": "1.37.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true }, "mime-types": { "version": "2.1.21", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, "requires": { "mime-db": "~1.37.0" } @@ -10649,8 +10084,9 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true }, "mixin-deep": { "version": "1.3.1", @@ -10684,7 +10120,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10761,24 +10197,6 @@ } } }, - "mock-fs": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-3.12.1.tgz", - "integrity": "sha1-/yeCTNarJjp+sFoRUjnUHTYx9fg=", - "dev": true, - "requires": { - "rewire": "2.5.2", - "semver": "5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, "module-deps-sortable": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", @@ -10842,16 +10260,11 @@ } } }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true }, "multipipe": { "version": "0.1.2", @@ -10968,7 +10381,8 @@ "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true }, "nightwatch": { "version": "1.0.18", @@ -11097,6 +10511,7 @@ "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" } @@ -11146,12 +10561,14 @@ "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true }, "object-component": { "version": "0.0.3", @@ -11316,16 +10733,10 @@ "mimic-fn": "^1.0.0" } }, - "openurl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", - "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", - "dev": true - }, "opn": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "integrity": "sha1-y1Reeqt4VivrEao7+rxwQuF2EDU=", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -11343,7 +10754,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -12059,7 +11470,8 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true }, "pify": { "version": "3.0.0", @@ -12199,7 +11611,8 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true }, "progress": { "version": "2.0.3", @@ -12241,25 +11654,6 @@ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", "dev": true }, - "proxyquire": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", - "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", - "dev": true, - "requires": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.0", - "resolve": "~1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -12275,7 +11669,8 @@ "psl": { "version": "1.1.31", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true }, "public-encrypt": { "version": "4.0.3", @@ -12315,7 +11710,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "q": { "version": "1.5.1", @@ -12332,7 +11728,8 @@ "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true }, "query-string": { "version": "4.3.4", @@ -12449,6 +11846,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -12744,7 +12142,8 @@ "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=" + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true }, "repeat-element": { "version": "1.1.3", @@ -12799,6 +12198,7 @@ "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -12844,12 +12244,6 @@ "resolve-from": "^1.0.0" } }, - "requirejs": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", - "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", - "dev": true - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -12893,7 +12287,8 @@ "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true }, "responselike": { "version": "1.0.2", @@ -12920,16 +12315,10 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "rewire": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", - "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", - "dev": true - }, "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", "dev": true }, "right-align": { @@ -12984,7 +12373,8 @@ "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==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "safe-json-parse": { "version": "1.0.1", @@ -13004,7 +12394,8 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "samsam": { "version": "1.3.0", @@ -13035,7 +12426,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -13417,19 +12808,10 @@ } } }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { "debug": "~3.1.0", @@ -13443,7 +12825,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13466,7 +12848,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", @@ -13488,7 +12870,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13504,7 +12886,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13516,7 +12898,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13574,12 +12956,14 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, "requires": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", @@ -13608,7 +12992,8 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true }, "space-separated-tokens": { "version": "1.1.2", @@ -13659,7 +13044,7 @@ }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13678,12 +13063,14 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sshpk": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz", - "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -13785,7 +13172,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13865,6 +13252,7 @@ "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" } @@ -13881,12 +13269,6 @@ "is-hexadecimal": "^1.0.0" } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -13913,7 +13295,8 @@ "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=" + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true }, "strip-eof": { "version": "1.0.0", @@ -13949,6 +13332,7 @@ "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" } @@ -13991,7 +13375,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -14049,6 +13433,7 @@ "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" @@ -14095,6 +13480,7 @@ "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.46", "next-tick": "1" @@ -14206,6 +13592,7 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" @@ -14214,7 +13601,8 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true } } }, @@ -14270,6 +13658,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -14277,7 +13666,8 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true }, "type-check": { "version": "0.3.2", @@ -14652,7 +14042,7 @@ "dependencies": { "bluebird": { "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true } @@ -14668,6 +14058,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -14675,7 +14066,8 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true }, "url": { "version": "0.11.0", @@ -14751,7 +14143,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14770,7 +14162,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, "util.promisify": { "version": "1.0.0", @@ -14791,7 +14184,8 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true }, "v8flags": { "version": "3.1.2", @@ -14822,6 +14216,7 @@ "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", @@ -15003,11 +14398,6 @@ } } }, - "vlq": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.0.tgz", - "integrity": "sha512-o3WmXySo+oI5thgqr7Qy8uBkT/v9Zr+sRyrh1lr8aWPUkgDWdWt4Nae2WKBrLsocgE8BuWWD0jLc+VW8LeU+2g==" - }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -15073,6 +14463,18 @@ "yargs": "^8.0.2" }, "dependencies": { + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ajv-keywords": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", @@ -15281,7 +14683,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -15991,7 +15393,8 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true }, "y18n": { "version": "3.2.1", diff --git a/package.json b/package.json index 36cfed18bd9..3848b405560 100755 --- a/package.json +++ b/package.json @@ -26,10 +26,10 @@ "devDependencies": { "@babel/core": "^7.2.2", "@babel/preset-env": "^7.2.3", - "ajv": "6.2.0", + "ajv": "5.5.2", "babel-loader": "^8.0.5", "chai": "^3.3.0", - "coveralls": "^3.0.1", + "coveralls": "^3.0.2", "documentation": "^5.2.2", "ejs": "^2.5.1", "es5-shim": "^4.5.2", @@ -41,20 +41,18 @@ "faker": "^3.1.0", "fs.extra": "^1.3.2", "gulp": "^4.0.0", - "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", "gulp-connect": "^5.7.0", - "gulp-coveralls": "^0.1.4", "gulp-eslint": "^4.0.0", "gulp-footer": "github:prebid/gulp-footer#master", "gulp-header": "^1.7.1", "gulp-if": "^2.0.2", "gulp-js-escape": "^1.0.1", "gulp-optimize-js": "^1.1.0", - "gulp-rename": "^1.2.0", "gulp-replace": "^1.0.0", "gulp-shell": "^0.5.2", + "gulp-sourcemaps": "^2.6.0", "gulp-uglify": "^3.0.0", "gulp-util": "^3.0.0", "is-docker": "^1.1.0", @@ -78,38 +76,23 @@ "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "^0.0.31", "karma-webpack": "^3.0.5", - "localtunnel": "^1.3.0", "lodash": "^4.17.4", - "mkpath": "^1.0.0", "mocha": "^5.0.0", - "mock-fs": "^3.11.0", "nightwatch": "^1.0.6", "opn": "^5.4.0", - "proxyquire": "^1.7.10", "querystringify": "0.0.3", - "requirejs": "^2.1.20", "sinon": "^4.1.3", "through2": "^2.0.3", - "uglify-js": "^2.8.10", "url-parse": "^1.0.5", "webpack": "^3.0.0", "webpack-stream": "^3.2.0", "yargs": "^1.3.1" }, "dependencies": { - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.1", "babel-plugin-transform-object-assign": "^6.22.0", "core-js": "^2.4.1", "crypto-js": "^3.1.9-1", - "eslint-scope": "^4.0.0", - "grunt-coveralls": "^2.0.0", - "gulp-sourcemaps": "^2.6.0", - "has-ansi": "^3.0.0", "jsencrypt": "^3.0.0-rc.1", - "just-clone": "^1.0.2", - "supports-color": "^5.5.0", - "util-deprecate": "^1.0.2", - "vlq": "^1.0.0" + "just-clone": "^1.0.2" } } diff --git a/test/spec/e2e/custom-reporter/pbjs-html-reporter.js b/test/spec/e2e/custom-reporter/pbjs-html-reporter.js index bcd5eab1e21..85be2a397a5 100644 --- a/test/spec/e2e/custom-reporter/pbjs-html-reporter.js +++ b/test/spec/e2e/custom-reporter/pbjs-html-reporter.js @@ -1,5 +1,4 @@ -var fs = require('fs'); -var mkpath = require('mkpath'); +var fs = require('fs.extra'); var path = require('path'); var ejs = require('ejs'); @@ -56,7 +55,7 @@ module.exports = new function() { if (pathParts.length) { output_folder = path.join(output_folder, pathParts.join(path.sep)); - mkpath.sync(output_folder); + fs.mkdirpSync(output_folder); } var filename = path.join(output_folder, opts.filename_prefix + moduleName + '.xml'); diff --git a/test/spec/modules/rubiconAnalyticsSchema.json b/test/spec/modules/rubiconAnalyticsSchema.json index b16b6a01ed8..b856bf584e9 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", @@ -374,4 +374,4 @@ } } } -} \ No newline at end of file +} From e3c652f2013484f80aacd4ee650db1fc882f7490 Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Mon, 28 Jan 2019 21:24:02 +0530 Subject: [PATCH 0958/1594] PulsePoint Adapter: crid fix (#3466) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * PulsePoint crid fix --- modules/pulsepointBidAdapter.js | 4 ++-- test/spec/modules/pulsepointBidAdapter_spec.js | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 7679c2b6a10..206eb734495 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -99,8 +99,8 @@ function bidResponseAvailable(bidRequest, bidResponse) { const bid = { requestId: id, cpm: idToBidMap[id].price, - creative_id: id, - creativeId: id, + creative_id: idToBidMap[id].crid, + creativeId: idToBidMap[id].crid, adId: id, ttl: DEFAULT_BID_TTL, netRevenue: DEFAULT_NET_REVENUE, diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index ebeedde7783..f40a270af11 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -84,7 +84,8 @@ describe('PulsePoint Adapter Tests', function () { bid: [{ impid: ortbRequest.imp[0].id, price: 1.25, - adm: 'This is an Ad' + adm: 'This is an Ad', + crid: 'Creative#123' }] }] }; @@ -97,8 +98,8 @@ describe('PulsePoint Adapter Tests', function () { expect(bid.width).to.equal(300); expect(bid.height).to.equal(250); expect(bid.adId).to.equal('bid12345'); - expect(bid.creative_id).to.equal('bid12345'); - expect(bid.creativeId).to.equal('bid12345'); + expect(bid.creative_id).to.equal('Creative#123'); + expect(bid.creativeId).to.equal('Creative#123'); expect(bid.netRevenue).to.equal(true); expect(bid.currency).to.equal('USD'); expect(bid.ttl).to.equal(20); From afdfecf5f71d3e7bcc8529b59cc5715e09bfd60d Mon Sep 17 00:00:00 2001 From: Mikhail Ivanchenko Date: Mon, 28 Jan 2019 20:28:01 +0300 Subject: [PATCH 0959/1594] Now passbacks are bids with zero CPM (#3473) --- modules/adliveBidAdapter.js | 25 +++++++++++----------- test/spec/modules/adliveBidAdapter_spec.js | 13 +++++++++-- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/modules/adliveBidAdapter.js b/modules/adliveBidAdapter.js index 834951000d5..26f9148d484 100644 --- a/modules/adliveBidAdapter.js +++ b/modules/adliveBidAdapter.js @@ -4,6 +4,7 @@ import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'adlive'; const ENDPOINT_URL = 'https://api.publishers.adlive.io/get?pbjs=1'; + const CURRENCY = 'USD'; const TIME_TO_LIVE = 360; @@ -43,19 +44,17 @@ export const spec = { const bidResponses = []; utils._each(response, function(bidResponse) { - if (!bidResponse.is_passback) { - bidResponses.push({ - requestId: bidRequest.bidId, - cpm: bidResponse.price, - width: bidResponse.size[0], - height: bidResponse.size[1], - creativeId: bidResponse.hash, - currency: CURRENCY, - netRevenue: false, - ttl: TIME_TO_LIVE, - ad: bidResponse.content - }); - } + bidResponses.push({ + requestId: bidRequest.bidId, + cpm: bidResponse.is_passback ? 0 : bidResponse.price, + width: bidResponse.size[0], + height: bidResponse.size[1], + creativeId: bidResponse.hash, + currency: CURRENCY, + netRevenue: false, + ttl: TIME_TO_LIVE, + ad: bidResponse.content + }); }); return bidResponses; diff --git a/test/spec/modules/adliveBidAdapter_spec.js b/test/spec/modules/adliveBidAdapter_spec.js index a048ce6932b..5d9cd753ff1 100644 --- a/test/spec/modules/adliveBidAdapter_spec.js +++ b/test/spec/modules/adliveBidAdapter_spec.js @@ -71,8 +71,17 @@ describe('adliveBidAdapterTests', function() { } ] }; - let bids = spec.interpretResponse(serverResponse); + let bids = spec.interpretResponse(serverResponse, bidRequestData.bids[0]); + + expect(bids).to.have.lengthOf(1); + + let bid = bids[0]; - expect(bids).to.have.lengthOf(0); + expect(bid.creativeId).to.equal('1e100887dd614b0909bf6c49ba7f69fdd1360437'); + expect(bid.ad).to.equal('Ad html passback'); + expect(bid.cpm).to.equal(0); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.currency).to.equal('USD'); }); }); From 0cb3e1a32b6fd93e4cce3f45668fc4499cfb9275 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Mon, 28 Jan 2019 16:03:08 -0500 Subject: [PATCH 0960/1594] add description to RD module (#3464) * add description to RD module * adding some more comments to private functions --- src/refererDetection.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/refererDetection.js b/src/refererDetection.js index fb0b1dbeebb..2acb0b68716 100644 --- a/src/refererDetection.js +++ b/src/refererDetection.js @@ -1,6 +1,20 @@ +/** + * The referer detection module attempts to gather referer information from the current page that prebid.js resides in. + * The information that it tries to collect includes: + * The detected top url in the nav bar, + * Whether it was able to reach the top most window (if for example it was embedded in several iframes), + * The number of iframes it was embedded in if applicable, + * A list of the domains of each embedded window if applicable. + * Canonical URL which refers to an HTML link element, with the attribute of rel="canonical", found in the element of your webpage + */ + import { logWarn } from './utils'; export function detectReferer(win) { + /** + * Returns number of frames to reach top from current frame where prebid.js sits + * @returns {Array} levels + */ function getLevels() { let levels = walkUpWindows(); let ancestors = getAncestorOrigins(); @@ -13,6 +27,11 @@ export function detectReferer(win) { return levels; } + /** + * This function would return a read-only array of hostnames for all the parent frames. + * win.location.ancestorOrigins is only supported in webkit browsers. For non-webkit browsers it will return undefined. + * @returns {(undefined|Array)} Ancestor origins or undefined + */ function getAncestorOrigins() { try { if (!win.location.ancestorOrigins) { @@ -24,6 +43,11 @@ export function detectReferer(win) { } } + /** + * This function would try to get referer and urls for all parent frames in case of win.location.ancestorOrigins undefined. + * @param {Array} levels + * @returns {Object} urls for all parent frames and top most detected referer url + */ function getPubUrlStack(levels) { let stack = []; let defUrl = null; @@ -78,6 +102,10 @@ export function detectReferer(win) { }; } + /** + * This function returns canonical URL which refers to an HTML link element, with the attribute of rel="canonical", found in the element of your webpage + * @param {Object} doc document + */ function getCanonicalUrl(doc) { try { let element = doc.querySelector("link[rel='canonical']"); @@ -89,6 +117,9 @@ export function detectReferer(win) { return null; } + /** + * Walk up to the top of the window to detect origin, number of iframes, ancestor origins and canonical url + */ function walkUpWindows() { let acc = []; let currentWindow; @@ -135,6 +166,7 @@ export function detectReferer(win) { * @property {boolean} reachedTop whether prebid was able to walk upto top window or not * @property {number} numIframes number of iframes * @property {string} stack comma separated urls of all origins + * @property {string} canonicalUrl canonical URL refers to an HTML link element, with the attribute of rel="canonical", found in the element of your webpage */ /** From daf3e98ce25d276612003a1ce56baf223f4747f6 Mon Sep 17 00:00:00 2001 From: deekshithraop Date: Tue, 29 Jan 2019 08:19:27 -0500 Subject: [PATCH 0961/1594] Rad 2626 Add resetPresetTargetingAST (#3474) * 3413-Insert Iframes for user sync in body * Append Iframe as the last child * Add unit test for insertElement * utls insert element at the top by default * add unit tests for utls insert element * Insert iframe as html last child * revert package.lock changes * Override keywords in setTargetingForAst * Add resetPresetTargetingAST for setTargetingForAst --- src/targeting.js | 24 +++++++++++++++++++++ test/spec/unit/pbjs_api_spec.js | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/targeting.js b/src/targeting.js index e9d85c07e7d..1d0a1de2cd7 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -77,6 +77,23 @@ export function newTargeting(auctionManager) { } }; + targeting.resetPresetTargetingAST = function(adUnitCode) { + const adUnitCodes = getAdUnitCodes(adUnitCode); + adUnitCodes.forEach(function(unit) { + const astTag = window.apntag.getTag(unit); + if (astTag && astTag.keywords) { + const currentKeywords = Object.keys(astTag.keywords); + const newKeywords = {}; + currentKeywords.forEach((key) => { + if (!includes(pbTargetingKeys, key.toLowerCase())) { + newKeywords[key] = astTag.keywords[key]; + } + }) + window.apntag.modifyTag(unit, { keywords: newKeywords }) + } + }); + }; + /** * Returns all ad server targeting for all ad units. * @param {string=} adUnitCode @@ -233,6 +250,13 @@ export function newTargeting(auctionManager) { */ targeting.setTargetingForAst = function() { let astTargeting = targeting.getAllTargeting(); + + try { + targeting.resetPresetTargetingAST(); + } catch (e) { + utils.logError('unable to reset targeting for AST' + e) + } + Object.keys(astTargeting).forEach(targetId => Object.keys(astTargeting[targetId]).forEach(key => { utils.logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${astTargeting[targetId][key]}`); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index ff9dac55029..b9d538f1656 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -155,6 +155,22 @@ window.apntag = { } }) } + }, + getTag: function(tagId) { + return this.tags[tagId]; + }, + modifyTag: function(tagId, params) { + var output = {}; + + utils._each(this.tags[tagId], function(tag, id) { + output[id] = tag; + }); + + utils._each(params, function(param, id) { + output[id] = param; + }); + + this.tags[tagId] = output; } } @@ -2062,6 +2078,27 @@ describe('Unit: Prebid Module', function () { expect(newAdserverTargeting).to.deep.equal(window.apntag.tags[adUnitCode].keywords); }); + it('should reset targeting for appnexus apntag object', function () { + const bids = auctionManagerInstance.getBidsReceived(); + const adUnitCode = '/19968336/header-bid-tag-0'; + + var expectedAdserverTargeting = bids[0].adserverTargeting; + var newAdserverTargeting = {}; + let regex = /pt[0-9]/; + + for (var key in expectedAdserverTargeting) { + if (key.search(regex) < 0) { + newAdserverTargeting[key.toUpperCase()] = expectedAdserverTargeting[key]; + } else { + newAdserverTargeting[key] = expectedAdserverTargeting[key]; + } + } + targeting.setTargetingForAst(); + expect(newAdserverTargeting).to.deep.equal(window.apntag.tags[adUnitCode].keywords); + targeting.resetPresetTargetingAST(); + expect(window.apntag.tags[adUnitCode].keywords).to.deep.equal({}); + }); + it('should not find ' + CONSTANTS.TARGETING_KEYS.AD_ID + ' key in lowercase for all bidders', function() { const adUnitCode = '/19968336/header-bid-tag-0'; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); From 0d568e3f62e29553ad179a308f6c8408fd929de2 Mon Sep 17 00:00:00 2001 From: mefjush Date: Tue, 29 Jan 2019 20:12:18 +0100 Subject: [PATCH 0962/1594] Fix Adhese bid adapter user sync (#3453) --- modules/adheseBidAdapter.js | 19 +++++++++++-------- test/spec/modules/adheseBidAdapter_spec.js | 14 ++++++++++---- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/modules/adheseBidAdapter.js b/modules/adheseBidAdapter.js index c5c75d007dd..daea17a2a5b 100644 --- a/modules/adheseBidAdapter.js +++ b/modules/adheseBidAdapter.js @@ -52,16 +52,19 @@ export const spec = { .map(item => adResponse(item.bid, item.ad)); }, - getUserSyncs: function(syncOptions, serverResponse, gdprConsent) { - const account = serverResponse.account || ''; - if (syncOptions.iframeEnabled) { - let syncurl = USER_SYNC_BASE_URL + '?account=' + account; - if (gdprConsent) { - syncurl += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); - syncurl += '&consentString=' + encodeURIComponent(gdprConsent.consentString || ''); + getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + if (syncOptions.iframeEnabled && serverResponses.length > 0) { + const account = serverResponses[0].account; + if (account) { + let syncurl = USER_SYNC_BASE_URL + '?account=' + account; + if (gdprConsent) { + syncurl += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); + syncurl += '&consentString=' + encodeURIComponent(gdprConsent.consentString || ''); + } + return [{type: 'iframe', url: syncurl}]; } - return [{ type: 'iframe', url: syncurl }]; } + return []; } }; diff --git a/test/spec/modules/adheseBidAdapter_spec.js b/test/spec/modules/adheseBidAdapter_spec.js index bbeafe6d3b7..68beedd4b35 100644 --- a/test/spec/modules/adheseBidAdapter_spec.js +++ b/test/spec/modules/adheseBidAdapter_spec.js @@ -25,18 +25,24 @@ let bidWithParams = function(data) { describe('AdheseAdapter', function () { describe('getUserSyncs', function () { - const serverResponse = { + const serverResponses = [{ account: 'demo' - }; + }]; const gdprConsent = { gdprApplies: true, consentString: 'CONSENT_STRING' }; it('should return empty when iframe disallowed', function () { - expect(spec.getUserSyncs({ iframeEnabled: false }, serverResponse, gdprConsent)).to.be.empty; + expect(spec.getUserSyncs({ iframeEnabled: false }, serverResponses, gdprConsent)).to.be.empty; + }); + it('should return empty when no serverResponses present', function () { + expect(spec.getUserSyncs({ iframeEnabled: true }, [], gdprConsent)).to.be.empty; + }); + it('should return empty when no account info present in the response', function () { + expect(spec.getUserSyncs({ iframeEnabled: true }, [{}], gdprConsent)).to.be.empty; }); it('should return usersync url when iframe allowed', function () { - expect(spec.getUserSyncs({ iframeEnabled: true }, serverResponse, gdprConsent)).to.deep.equal([{ type: 'iframe', url: 'https://user-sync.adhese.com/iframe/user_sync.html?account=demo&gdpr=1&consentString=CONSENT_STRING' }]); + expect(spec.getUserSyncs({ iframeEnabled: true }, serverResponses, gdprConsent)).to.deep.equal([{ type: 'iframe', url: 'https://user-sync.adhese.com/iframe/user_sync.html?account=demo&gdpr=1&consentString=CONSENT_STRING' }]); }); }); From abf91a3d66216959efa5791f0b194cd8a6f1fb68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kurre=20St=C3=A5hlberg?= Date: Tue, 29 Jan 2019 21:23:54 +0200 Subject: [PATCH 0963/1594] Fix readpeakBidAdapter to detect currency and device type correctly (#3476) * Update ReadPeak adapter * Replace $$PREBID_GLOBAL$$.version with $prebid.version$ * Fix test * Use utils.getTopWindowReferrer() instead of custom function * Fix device type and currency outgoing request of ReadPeak Bid Adapter * Update tests to check for language and currency for ReadPeakBidAdapter --- modules/readpeakBidAdapter.js | 15 +++++++++++++-- test/spec/modules/readpeakBidAdapter_spec.js | 10 +++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/modules/readpeakBidAdapter.js b/modules/readpeakBidAdapter.js index bdfa17b29a6..f53169aca3e 100644 --- a/modules/readpeakBidAdapter.js +++ b/modules/readpeakBidAdapter.js @@ -27,13 +27,16 @@ export const spec = { ), buildRequests: bidRequests => { + const currencyObj = config.getConfig('currency'); + const currency = (currencyObj && currencyObj.adServerCurrency) || 'USD'; + const request = { id: bidRequests[0].bidderRequestId, imp: bidRequests.map(slot => impression(slot)).filter(imp => imp.native != null), site: site(bidRequests), app: app(bidRequests), device: device(), - cur: config.getConfig('currency') || ['USD'], + cur: [currency], source: { fd: 1, tid: bidRequests[0].transactionId, @@ -191,11 +194,19 @@ function app(bidderRequest) { return undefined; } +function isMobile() { + return (/(ios|ipod|ipad|iphone|android)/i).test(global.navigator.userAgent); +} + +function isConnectedTV() { + return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(global.navigator.userAgent); +} + function device() { return { ua: navigator.userAgent, language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), - devicetype: 1 + devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2 }; } diff --git a/test/spec/modules/readpeakBidAdapter_spec.js b/test/spec/modules/readpeakBidAdapter_spec.js index 572c2b73f8c..5fcdf9b5836 100644 --- a/test/spec/modules/readpeakBidAdapter_spec.js +++ b/test/spec/modules/readpeakBidAdapter_spec.js @@ -1,6 +1,7 @@ import { expect } from 'chai'; import { spec, ENDPOINT } from 'modules/readpeakBidAdapter'; import * as utils from 'src/utils'; +import {config} from 'src/config'; describe('ReadPeakAdapter', function () { let bidRequest @@ -149,6 +150,12 @@ describe('ReadPeakAdapter', function () { }); it('should attach request data', function () { + config.setConfig({ + currency: { + adServerCurrency: 'EUR' + } + }); + const request = spec.buildRequests([ bidRequest ]); const data = JSON.parse(request.data); @@ -167,7 +174,8 @@ describe('ReadPeakAdapter', function () { page: utils.getTopWindowLocation().href, domain: utils.getTopWindowLocation().hostname, }); - expect(data.device).to.deep.contain({ ua: navigator.userAgent }); + expect(data.device).to.deep.contain({ ua: navigator.userAgent, language: navigator.language }); + expect(data.cur).to.deep.equal(['EUR']); }); }); From 9ee9e3e76498e7250dfa0b9efe3212812a6b23e6 Mon Sep 17 00:00:00 2001 From: Mathias Methner Date: Tue, 29 Jan 2019 21:17:01 +0100 Subject: [PATCH 0964/1594] Add adapter specific params to orbidder adapter (#3467) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons --- modules/orbidderBidAdapter.js | 19 ++++++-- modules/orbidderBidAdapter.md | 4 ++ test/spec/modules/orbidderBidAdapter_spec.js | 48 +++++++++++++++----- 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index 20ccfcfdace..de365fe87de 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -4,6 +4,7 @@ import {registerBidder} from '../src/adapters/bidderFactory'; export const spec = { code: 'orbidder', + bidParams: {}, orbidderHost: (() => { let ret = 'https://orbidder.otto.de'; try { @@ -14,7 +15,10 @@ export const spec = { })(), isBidRequestValid(bid) { - return !!(bid.sizes && bid.bidId); + return !!(bid.sizes && bid.bidId && bid.params && + (bid.params.accountId && (typeof bid.params.accountId === 'string')) && + (bid.params.placementId && (typeof bid.params.placementId === 'string')) && + ((typeof bid.params.keyValues === 'undefined') || (typeof bid.params.keyValues === 'object'))); }, buildRequests(validBidRequests, bidderRequest) { @@ -24,7 +28,7 @@ export const spec = { referer = bidderRequest.refererInfo.referer || ''; } const ret = { - url: `${this.orbidderHost}/bid`, + url: `${spec.orbidderHost}/bid`, method: 'POST', data: { pageUrl: referer, @@ -36,6 +40,7 @@ export const spec = { params: bidRequest.params } }; + spec.bidParams[bidRequest.bidId] = bidRequest.params; if (bidRequest && bidRequest.gdprConsent) { ret.data.gdprConsent = { consentString: bidRequest.gdprConsent.consentString, @@ -68,9 +73,13 @@ export const spec = { onBidWon(winObj) { const getRefererInfo = detectReferer(window); - const refererInfo = getRefererInfo(); - winObj.pageUrl = refererInfo.referer; - spec.ajaxCall(`${this.orbidderHost}/win`, JSON.stringify(winObj)); + + winObj.pageUrl = getRefererInfo().referer; + if (spec.bidParams[winObj.adId]) { + winObj.params = spec.bidParams[winObj.adId]; + } + + spec.ajaxCall(`${spec.orbidderHost}/win`, JSON.stringify(winObj)); }, ajaxCall(endpoint, data) { diff --git a/modules/orbidderBidAdapter.md b/modules/orbidderBidAdapter.md index 7a9600142e7..c7676e6774f 100644 --- a/modules/orbidderBidAdapter.md +++ b/modules/orbidderBidAdapter.md @@ -21,6 +21,10 @@ var adUnits = [{ }, bids: [{ bidder: 'orbidder' + params: { + accountId: "someAccount", + placementId: "somePlace" + } }] }]; ``` diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index bf31a6ad7e5..29c6c2c6d9a 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -4,17 +4,22 @@ import {newBidder} from 'src/adapters/bidderFactory'; describe('orbidderBidAdapter', () => { const adapter = newBidder(spec); - const bidRequest = { + const defaultBidRequest = { bidId: 'd66fa86787e0b0ca900a96eacfd5f0bb', auctionId: 'ccc4c7cdfe11cfbd74065e6dd28413d8', transactionId: 'd58851660c0c4461e4aa06344fc9c0c6', adUnitCode: 'adunit-code', sizes: [[300, 250], [300, 600]], params: { - 'foo': 'bar' + 'accountId': 'string1', + 'placementId': 'string2' } }; + const deepClone = function (val) { + return JSON.parse(JSON.stringify(val)); + }; + const buildRequest = function (buildRequest) { return spec.buildRequests( [buildRequest], @@ -23,7 +28,7 @@ describe('orbidderBidAdapter', () => { referer: 'http://localhost:9876/' } })[0]; - } + }; describe('inherited functions', () => { it('exists and is a function', () => { @@ -33,18 +38,36 @@ describe('orbidderBidAdapter', () => { describe('isBidRequestValid', () => { it('should return true when required params found', () => { + expect(spec.isBidRequestValid(defaultBidRequest)).to.equal(true); + }); + + it('accepts optional keyValues object', () => { + const bidRequest = deepClone(defaultBidRequest); + bidRequest.params.keyValues = {'key': 'value'}; expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); + it('performs type checking', () => { + const bidRequest = deepClone(defaultBidRequest); + bidRequest.params.accountId = 1; // supposed to be a string + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + + it('doesn\'t accept malformed keyValues', () => { + const bidRequest = deepClone(defaultBidRequest); + bidRequest.params.keyValues = 'another not usable string'; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + it('should return false when required params are not passed', () => { - let bidRequest = Object.assign({}, bidRequest); + const bidRequest = deepClone(defaultBidRequest); delete bidRequest.params; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); }); describe('buildRequests', () => { - const request = buildRequest(bidRequest); + const request = buildRequest(defaultBidRequest); it('sends bid request to endpoint via https using post', () => { expect(request.method).to.equal('POST'); @@ -54,16 +77,16 @@ describe('orbidderBidAdapter', () => { it('sends correct bid parameters', () => { // we add one, because we add referer information from bidderRequest object - expect(Object.keys(request.data).length).to.equal(Object.keys(bidRequest).length + 1); + expect(Object.keys(request.data).length).to.equal(Object.keys(defaultBidRequest).length + 1); expect(request.data.pageUrl).to.equal('http://localhost:9876/'); // expect(request.data.referrer).to.equal(''); - Object.keys(bidRequest).forEach((key) => { - expect(bidRequest[key]).to.equal(request.data[key]); + Object.keys(defaultBidRequest).forEach((key) => { + expect(defaultBidRequest[key]).to.equal(request.data[key]); }); }); it('handles empty gdpr object', () => { - let bidRequest = Object.assign({}, bidRequest); + const bidRequest = deepClone(defaultBidRequest); bidRequest.gdprConsent = {}; const request = buildRequest(bidRequest); @@ -71,7 +94,7 @@ describe('orbidderBidAdapter', () => { }); it('handles non-existent gdpr object', () => { - let bidRequest = Object.assign({}, bidRequest); + const bidRequest = deepClone(defaultBidRequest); bidRequest.gdprConsent = null; const request = buildRequest(bidRequest); @@ -80,7 +103,7 @@ describe('orbidderBidAdapter', () => { it('handles properly filled gdpr object where gdpr applies', () => { const consentString = 'someWeirdString'; - const bidRequest = Object.assign({}, bidRequest); + const bidRequest = deepClone(defaultBidRequest); bidRequest.gdprConsent = { gdprApplies: true, consentString: 'someWeirdString' @@ -94,7 +117,7 @@ describe('orbidderBidAdapter', () => { it('handles properly filled gdpr object where gdpr does not apply', () => { const consentString = 'someWeirdString'; - const bidRequest = Object.assign({}, bidRequest); + const bidRequest = deepClone(defaultBidRequest); bidRequest.gdprConsent = { gdprApplies: false, consentString: 'someWeirdString' @@ -110,6 +133,7 @@ describe('orbidderBidAdapter', () => { describe('onBidWon', () => { let ajaxStub; const winObj = { + adId: 'testId', test: 1, pageUrl: 'www.someurl.de', referrer: 'www.somereferrer.de' From cbbbc3d1978e470141baf61e213b3b265eac394b Mon Sep 17 00:00:00 2001 From: jddeleon Date: Tue, 29 Jan 2019 13:02:40 -0800 Subject: [PATCH 0965/1594] Add bidfloor param to allow dynamic bid floor CPM (#3431) * Add bidfloor to params to allow dynamic bid floor CPM * polyfill Number.isFinite for IE11/Safari 8 * ADSS-538 Revert changes to package-lock.json --- integrationExamples/gpt/pbjs_example_gpt.html | 3 ++- modules/gumgumBidAdapter.js | 9 +++++++++ modules/gumgumBidAdapter.md | 6 ++++-- test/spec/modules/gumgumBidAdapter_spec.js | 15 +++++++++++++-- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index 6852b9f680a..dcc67ae0f74 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -418,7 +418,8 @@ { bidder: 'gumgum', params: { - inScreen: 'ggumtest' // REQUIRED str Tracking Id + inScreen: 'ggumtest', // REQUIRED str Tracking Id + bidfloor: 0.01 // OPTIONAL number CPM bid } }, { diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 51068d7edb9..846beae2694 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -103,6 +103,12 @@ function isBidRequestValid (bid) { 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))) { + utils.logWarn('[GumGum] bidfloor must be a Number'); + return false; + } + return true; } @@ -126,6 +132,9 @@ function buildRequests (validBidRequests, bidderRequest) { if (pageViewId) { data.pv = pageViewId } + if (params.bidfloor) { + data.fp = params.bidfloor; + } if (params.inScreen) { data.t = params.inScreen; data.pi = 2; diff --git a/modules/gumgumBidAdapter.md b/modules/gumgumBidAdapter.md index 14f2fe40abb..57616a90ac2 100644 --- a/modules/gumgumBidAdapter.md +++ b/modules/gumgumBidAdapter.md @@ -20,7 +20,8 @@ var adUnits = [ { bidder: 'gumgum', params: { - inSlot: '15901' // GumGum Slot ID given to the client + inSlot: '15901', // GumGum Slot ID given to the client, + bidFloor: 0.03 // CPM bid floor } } ] @@ -31,7 +32,8 @@ var adUnits = [ { bidder: 'gumgum', params: { - inScreen: 'dc9d6be1' // GumGum Zone ID given to the client + inScreen: 'dc9d6be1', // GumGum Zone ID given to the client + bidFloor: 0.03 // CPM bid floor } } ] diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 0c1431b71a5..c067f50fa56 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -17,7 +17,8 @@ describe('gumgumAdapter', function () { let bid = { 'bidder': 'gumgum', 'params': { - 'inScreen': '10433394' + 'inScreen': '10433394', + 'bidfloor': 0.05 }, 'adUnitCode': 'adunit-code', 'sizes': [[300, 250], [300, 600], [1, 1]], @@ -40,7 +41,7 @@ describe('gumgumAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', function () { + it('should return false when no unit type is specified', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -48,6 +49,16 @@ describe('gumgumAdapter', function () { }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); + + it('should return false when bidfloor is not a number', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'inSlot': '789', + 'bidfloor': '0.50' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); }); describe('buildRequests', function () { From 4969c6ad3a79f9ae2282b4c10e5194c7dd715d6c Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 29 Jan 2019 16:42:08 -0500 Subject: [PATCH 0966/1594] Prebid 1.40.0 release --- package-lock.json | 111 +++++++++++++++++++++++++++------------------- package.json | 2 +- 2 files changed, 66 insertions(+), 47 deletions(-) diff --git a/package-lock.json b/package-lock.json index a6e0970a93e..fa2a67df987 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.40.0-pre", + "version": "1.40.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3072,7 +3072,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3480,7 +3480,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -4464,7 +4464,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4478,7 +4478,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4494,7 +4494,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4514,7 +4514,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4844,7 +4844,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -5125,7 +5125,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5638,7 +5638,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { @@ -5836,7 +5836,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5857,12 +5858,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5877,17 +5880,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6004,7 +6010,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6016,6 +6023,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6030,6 +6038,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6037,12 +6046,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6061,6 +6072,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6141,7 +6153,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6153,6 +6166,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6238,7 +6252,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6274,6 +6289,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6293,6 +6309,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6336,12 +6353,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -7107,7 +7126,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7124,7 +7143,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -7871,7 +7890,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8847,7 +8866,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -8883,7 +8902,7 @@ "mime": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha1-4FH9iBNYWF8yed8zP+aU2gvP/dY=", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true }, "rimraf": { @@ -9562,7 +9581,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -9575,7 +9594,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true } } @@ -10084,7 +10103,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10120,7 +10139,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10736,7 +10755,7 @@ "opn": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha1-y1Reeqt4VivrEao7+rxwQuF2EDU=", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -10754,7 +10773,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -12318,7 +12337,7 @@ "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", "dev": true }, "right-align": { @@ -12426,7 +12445,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -12811,7 +12830,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -12825,7 +12844,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -12848,7 +12867,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -12870,7 +12889,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -12886,7 +12905,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -12898,7 +12917,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13044,7 +13063,7 @@ }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13172,7 +13191,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13375,7 +13394,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -14042,7 +14061,7 @@ "dependencies": { "bluebird": { "version": "3.4.7", - "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true } @@ -14143,7 +14162,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14683,7 +14702,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { diff --git a/package.json b/package.json index 3848b405560..8e0a617087b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.40.0-pre", + "version": "1.40.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 71ba8f66d9b7593bba62ce82bac391d816deefd2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 29 Jan 2019 16:51:39 -0500 Subject: [PATCH 0967/1594] Increment Pre Version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index fa2a67df987..6108f7ee2c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.40.0", + "version": "2.0.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8e0a617087b..3b5b5b9d58c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "1.40.0", + "version": "2.0.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d266e0d23b5d01cb075ec33f68402e3134ae5bca Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 29 Jan 2019 14:58:12 -0700 Subject: [PATCH 0968/1594] New hooks API for 2.0 (#3378) * added fun-hooks adapter * use npm fun-hooks * some test fixes * have currency module tests clean up hooks after it runs * have config.resetConfig notify listeners that they've been reset * update chai to latest and fix tests * add deprecation warning for createHook * remove old hooks api and pre1api module for 2.0 * remove callback fn from arguments in consentManagement hook * added ready functionality for hooks * update package.json and lock --- modules/consentManagement.js | 6 +- modules/currency.js | 12 +- modules/pre1api.js | 156 ------------------ modules/pubCommonId.js | 8 +- package-lock.json | 39 +++-- package.json | 3 +- src/auction.js | 4 +- src/config.js | 20 ++- src/debugging.js | 21 +-- src/hook.js | 81 +-------- src/prebid.js | 5 +- test/spec/debugging_spec.js | 9 +- test/spec/hook_spec.js | 151 ----------------- test/spec/modules/a4gBidAdapter_spec.js | 2 +- test/spec/modules/adoceanBidAdapter_spec.js | 4 +- test/spec/modules/adxcgBidAdapter_spec.js | 6 +- test/spec/modules/aolBidAdapter_spec.js | 8 +- test/spec/modules/ccxBidAdapter_spec.js | 2 +- test/spec/modules/consentManagement_spec.js | 48 +++--- .../spec/modules/consumableBidAdapter_spec.js | 2 +- .../spec/modules/conversantBidAdapter_spec.js | 10 +- test/spec/modules/criteoBidAdapter_spec.js | 2 +- test/spec/modules/currency_spec.js | 88 +++++----- test/spec/modules/gjirafaBidAdapter_spec.js | 28 ++-- .../spec/modules/lifestreetBidAdapter_spec.js | 2 +- .../modules/prebidServerBidAdapter_spec.js | 2 +- test/spec/modules/pubCommonId_spec.js | 36 ++-- test/spec/modules/rtbhouseBidAdapter_spec.js | 2 +- test/spec/modules/rubiconBidAdapter_spec.js | 4 +- test/spec/modules/serverbidBidAdapter_spec.js | 2 +- .../modules/smartadserverBidAdapter_spec.js | 2 +- .../modules/trafficrootsBidAdapter_spec.js | 2 +- test/spec/modules/unrulyBidAdapter_spec.js | 8 +- test/spec/modules/widespaceBidAdapter_spec.js | 4 +- test/spec/modules/yieldoneBidAdapter_spec.js | 2 +- test/test_index.js | 2 + 36 files changed, 224 insertions(+), 559 deletions(-) delete mode 100644 modules/pre1api.js delete mode 100644 test/spec/hook_spec.js diff --git a/modules/consentManagement.js b/modules/consentManagement.js index f0ec5ed3f6d..94a3b13e383 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -190,11 +190,11 @@ function lookupIabConsent(cmpSuccess, cmpError, hookConfig) { * @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(reqBidsConfigObj, fn) { +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: arguments, + args: [reqBidsConfigObj], nextFn: fn, adUnits: reqBidsConfigObj.adUnits || $$PREBID_GLOBAL$$.adUnits, bidsBackHandler: reqBidsConfigObj.bidsBackHandler, @@ -375,7 +375,7 @@ export function setConfig(config) { } } if (!addedConsentHook) { - $$PREBID_GLOBAL$$.requestBids.addHook(requestBidsHook, 50); + $$PREBID_GLOBAL$$.requestBids.before(requestBidsHook, 50); } addedConsentHook = true; } diff --git a/modules/currency.js b/modules/currency.js index 2116e624449..350b9dcb3f4 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -122,7 +122,7 @@ function initCurrency(url) { utils.logInfo('Installing addBidResponse decorator for currency module', arguments); - hooks['addBidResponse'].addHook(addBidResponseHook, 100); + hooks['addBidResponse'].before(addBidResponseHook, 100); // call for the file if we haven't already if (needToCallForCurrencyFile) { @@ -148,7 +148,7 @@ function initCurrency(url) { function resetCurrency() { utils.logInfo('Uninstalling addBidResponse decorator for currency module', arguments); - hooks['addBidResponse'].removeHook(addBidResponseHook, 100); + hooks['addBidResponse'].getHooks({hook: addBidResponseHook}).remove(); adServerCurrency = 'USD'; conversionCache = {}; @@ -159,9 +159,9 @@ function resetCurrency() { bidderCurrencyDefault = {}; } -export function addBidResponseHook(adUnitCode, bid, fn) { +export function addBidResponseHook(fn, adUnitCode, bid) { if (!bid) { - return fn.apply(this, arguments); // if no bid, call original and let it display warnings + return fn.call(this, adUnitCode); // if no bid, call original and let it display warnings } let bidder = bid.bidderCode || bid.bidder; @@ -190,10 +190,10 @@ export function addBidResponseHook(adUnitCode, bid, fn) { // execute immediately if the bid is already in the desired currency if (bid.currency === adServerCurrency) { - return fn.apply(this, arguments); + return fn.call(this, adUnitCode, bid); } - bidResponseQueue.push(wrapFunction(fn, this, arguments)); + bidResponseQueue.push(wrapFunction(fn, this, [adUnitCode, bid])); if (!currencySupportEnabled || currencyRatesLoaded) { processBidResponseQueue(); } diff --git a/modules/pre1api.js b/modules/pre1api.js deleted file mode 100644 index be05590a5fd..00000000000 --- a/modules/pre1api.js +++ /dev/null @@ -1,156 +0,0 @@ - -/** - pre1api module - - This module supports backwards compatibility for those who need extra time to re-code their pages to work with the - Prebid 1.0 API. Use of this backwards compatibility module is recommended only as an interim solution. - - It provides equivalents for the following variables and functions that were deprecated in PBJS 1.0: - - pbjs._winningBids - - pbjs._bidsReceived - - pbjs._bidsRequested - - pbjs._adUnitCodes - - pbjs._adsReceived - - pbjs.cbTimeout - - pbjs.addCallback() - - pbjs.removeCallback() - - pbjs.allBidsAvailable() - - pbjs.bidderTimeout - - pbjs.logging - - pbjs.publisherDomain - - pbjs.setPriceGranularity() - - pbjs.enableSendAllBids() // and also defaults this value to `false` like pre-1.0 - - pbjs.setBidderSequence() - - pbjs.setS2SConfig() // and makes endpoints optional again (defaulting to the appnexus endpoints) - - This will not support the pre-1.0 sizeMapping feature. - - The drawback is that this module disables concurrency for requestBids(), queueing them as was done in pre-1.0. Anytime - an auction request is queued or one of these APIs is accessed it will display a deprecation warning in the console if - logging is enabled. So while this is useful for those that need more time to migrate, it eliminates one of the best - features of PBJS 1.0 as is required to emulate the old API. - */ - -import {config} from '../src/config'; -import {logWarn, logInfo} from '../src/utils'; - -const MODULE_NAME = 'pre-1.0 API'; - -let pbjs = window['$$PREBID_GLOBAL$$']; - -logInfo(`loading ${MODULE_NAME} module and patching prebid with deprecated APIs.`); - -let auctionQueue = []; - -let emptyFn = () => []; - -Object.defineProperty(pbjs, '_winningBids', { - get: () => pbjs.getAllWinningBids() -}); - -let auctionPropMap = { - _bidsReceived: auction => auction.getBidsReceived(), - _bidsRequested: auction => auction.getBidRequests(), - _adUnitCodes: auction => auction.getAdUnitCodes(), - allBidsAvailable: auction => auction.getBidRequests().every((bidRequest) => bidRequest.doneCbCallCount >= 1) -}; - -let configPropMap = { - cbTimeout: 'bidderTimeout', - bidderTimeout: 'bidderTimeout', - logging: 'debug', - publisherDomain: 'publisherDomain', - enableSendAllBids: 'enableSendAllBids', - setPriceGranularity: 'priceGranularity', - setBidderSequence: 'bidderSequence', - setS2SConfig: 's2sConfig' -}; - -pbjs.addCallback = pbjs.onEvent; -pbjs.removeCallback = pbjs.offEvent; - -// can't see anywhere that this was used, but it is listed in Prebid 1.0 transition guide... -// so just adding as empty array -pbjs._adsReceived = []; - -config.setDefaults({ - enableSendAllBids: false, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } -}); - -let currAuction = { - getBidsReceived: emptyFn, - getBidsRequested: emptyFn, - getAdUnitCodes: emptyFn, - getTimeout: () => config.getConfig('bidderTimeout') -}; - -// we need to intercept s2sConfig rather than call setConfig or setDefaults directly, otherwise the code will fail when -// the server adapter attempts to validate the configuration passed in by the publisher -config.setConfig.addHook((config, next) => { - if (config.s2sConfig) { - config.s2sConfig = Object.assign({ - endpoint: 'https://prebid.adnxs.com/pbs/v1/auction', - syncEndpoint: 'https://prebid.adnxs.com/pbs/v1/cookie_sync' - }, config.s2sConfig); - } - next(config); -}); - -/** - * Hook to queue and disallow concurrent auctions (as Prebid would function pre 1.0) - */ -pbjs.requestBids.addHook((config, next = config) => { - auctionQueue.push(() => { - let oldHandler = config.bidsBackHandler; - config.bidsBackHandler = (...args) => { - if (typeof oldHandler === 'function') { - oldHandler.apply(null, args); - } - - auctionQueue.shift(); - if (auctionQueue[0]) { - auctionQueue[0](); - } - }; - - currAuction = next(config); - }); - - if (auctionQueue.length === 1) { - auctionQueue[0](); - } else { - logWarn(`${MODULE_NAME} module: concurrency has been disabled and "$$PREBID_GLOBAL$$.requestBids" call was queued`); - } -}, 5); - -Object.keys(auctionPropMap).forEach(prop => { - if (prop === 'allBidsAvailable') { - pbjs[prop] = deprecated(prop, () => auctionPropMap[prop](currAuction)); - } - Object.defineProperty(pbjs, prop, { - get: deprecated(prop, () => auctionPropMap[prop](currAuction)) - }); -}); - -Object.keys(configPropMap).forEach(prop => { - if (prop === 'enableSendAllBids') { - pbjs[prop] = deprecated(prop, () => config.setConfig({[prop]: true})); - } else if (prop.lastIndexOf('set', 0) === 0) { - pbjs[prop] = deprecated(prop, value => config.setConfig({[configPropMap[prop]]: value})); - } else { - Object.defineProperty(pbjs, prop, { - get: deprecated(prop, () => config.getConfig(configPropMap[prop])), - set: deprecated(prop, value => config.setConfig({[configPropMap[prop]]: value})) - }); - } -}); - -function deprecated(name, fn) { - return (...args) => { - logWarn(`${MODULE_NAME} module: accessed deprecated API "$$PREBID_GLOBAL$$.${name}"`); - return fn.apply(null, args); - }; -} diff --git a/modules/pubCommonId.js b/modules/pubCommonId.js index f357f9314b4..3175dc22613 100644 --- a/modules/pubCommonId.js +++ b/modules/pubCommonId.js @@ -24,13 +24,13 @@ export function getExpInterval() { return interval; } * @param {function} next The next function in the chain */ -export function requestBidHook(config, next) { +export function requestBidHook(next, config) { let adUnits = config.adUnits || $$PREBID_GLOBAL$$.adUnits; let pubcid = null; // Pass control to the next function if not enabled if (!pubcidEnabled) { - return next.apply(this, arguments); + return next.call(this, config); } if (typeof window[PUB_COMMON] === 'object') { @@ -55,7 +55,7 @@ export function requestBidHook(config, next) { }); }); } - return next.apply(this, arguments); + return next.call(this, config); } // Helper to set a cookie @@ -94,7 +94,7 @@ export function initPubcid() { if (utils.cookiesAreEnabled()) { if (!getCookie('_pubcid_optout')) { - $$PREBID_GLOBAL$$.requestBids.addHook(requestBidHook); + $$PREBID_GLOBAL$$.requestBids.before(requestBidHook); } } } diff --git a/package-lock.json b/package-lock.json index 6108f7ee2c8..31f80c1eed4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -927,7 +927,7 @@ "dependencies": { "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -3166,14 +3166,28 @@ } }, "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", "dev": true, "requires": { - "assertion-error": "^1.0.1", - "deep-eql": "^0.1.3", - "type-detect": "^1.0.0" + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + }, + "dependencies": { + "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, + "requires": { + "type-detect": "^4.0.0" + } + } } }, "chai-nightwatch": { @@ -6412,6 +6426,11 @@ } } }, + "fun-hooks": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.6.5.tgz", + "integrity": "sha512-DV6NAc6zuTukwIiq+4+iWr9bzD19hrbh60C25u3JEpXdzCtrR1UNB81jSBUJP12xKhdRMsoVrOBVnHeWZk6P9g==" + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -13698,9 +13717,9 @@ } }, "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "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-is": { diff --git a/package.json b/package.json index 3b5b5b9d58c..3ec3d7bac46 100755 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@babel/preset-env": "^7.2.3", "ajv": "5.5.2", "babel-loader": "^8.0.5", - "chai": "^3.3.0", + "chai": "^4.2.0", "coveralls": "^3.0.2", "documentation": "^5.2.2", "ejs": "^2.5.1", @@ -92,6 +92,7 @@ "babel-plugin-transform-object-assign": "^6.22.0", "core-js": "^2.4.1", "crypto-js": "^3.1.9-1", + "fun-hooks": "^0.6.5", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2" } diff --git a/src/auction.js b/src/auction.js index 203a725bc4e..d51de45f2ab 100644 --- a/src/auction.js +++ b/src/auction.js @@ -55,7 +55,7 @@ import { getCacheUrl, store } from './videoCache'; import { Renderer } from './Renderer'; import { config } from './config'; import { userSync } from './userSync'; -import { createHook } from './hook'; +import { hook } from './hook'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; import { OUTSTREAM } from './video'; @@ -318,7 +318,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } -export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid) { +export const addBidResponse = hook('async', function(adUnitCode, bid) { this.dispatch.call(this.bidderRequest, adUnitCode, bid); }, 'addBidResponse'); diff --git a/src/config.js b/src/config.js index d9892f5a746..1e94614ddaa 100644 --- a/src/config.js +++ b/src/config.js @@ -10,7 +10,7 @@ import { isValidPriceConfig } from './cpmBucketManager'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -import { createHook } from './hook'; +import { hook } from './hook'; const utils = require('./utils'); const DEFAULT_DEBUG = false; @@ -56,7 +56,7 @@ export function newConfig() { function resetConfig() { defaults = {}; - config = { + let newConfig = { // `debug` is equivalent to legacy `pbjs.logging` property _debug: DEFAULT_DEBUG, get debug() { @@ -173,6 +173,20 @@ export function newConfig() { }; + if (config) { + callSubscribers( + Object.keys(config).reduce((memo, topic) => { + if (config[topic] !== newConfig[topic]) { + memo[topic] = newConfig[topic] || {}; + } + return memo; + }, + {}) + ); + } + + config = newConfig; + function hasGranularity(val) { return find(Object.keys(GRANULARITY_OPTIONS), option => val === GRANULARITY_OPTIONS[option]); } @@ -217,7 +231,7 @@ export function newConfig() { * Sets configuration given an object containing key-value pairs and calls * listeners that were added by the `subscribe` function */ - let setConfig = createHook('asyncSeries', function setConfig(options) { + let setConfig = hook('async', function setConfig(options) { if (typeof options !== 'object') { utils.logError('setConfig options must be an object'); return; diff --git a/src/debugging.js b/src/debugging.js index e66088d019c..98ff67f4707 100644 --- a/src/debugging.js +++ b/src/debugging.js @@ -15,26 +15,27 @@ function logWarn(msg) { utilsLogWarn('DEBUG: ' + msg); } +function removeHook() { + addBidResponse.getHooks({hook: boundHook}).remove() +} + function enableOverrides(overrides, fromSession = false) { config.setConfig({'debug': true}); logMessage(`bidder overrides enabled${fromSession ? ' from session' : ''}`); - if (boundHook) { - addBidResponse.removeHook(boundHook); - } + removeHook(); - boundHook = addBidResponseHook.bind(null, overrides); - addBidResponse.addHook(boundHook, 5); + boundHook = addBidResponseHook.bind(overrides); + addBidResponse.before(boundHook, 5); } export function disableOverrides() { - if (boundHook) { - addBidResponse.removeHook(boundHook); - logMessage('bidder overrides disabled'); - } + removeHook(); + logMessage('bidder overrides disabled'); } -export function addBidResponseHook(overrides, adUnitCode, bid, next) { +export function addBidResponseHook(next, adUnitCode, bid) { + let overrides = this; if (Array.isArray(overrides.bidders) && overrides.bidders.indexOf(bid.bidderCode) === -1) { logWarn(`bidder '${bid.bidderCode}' excluded from auction by bidder overrides`); return; diff --git a/src/hook.js b/src/hook.js index fef62a37c3d..c4e450bf5f2 100644 --- a/src/hook.js +++ b/src/hook.js @@ -1,81 +1,12 @@ -/** - * @typedef {function} HookedFunction - * @property {function(function(), [number])} addHook A method that takes a new function to attach as a hook - * to the HookedFunction - * @property {function(function())} removeHook A method to remove attached hooks - */ +import funHooks from 'fun-hooks'; + +export let hook = funHooks({ + ready: funHooks.SYNC | funHooks.ASYNC | funHooks.QUEUE +}); /** * A map of global hook methods to allow easy extension of hooked functions that are intended to be extended globally * @type {{}} */ -export const hooks = {}; - -/** - * A utility function for allowing a regular function to be extensible with additional hook functions - * @param {string} type The method for applying all attached hooks when this hooked function is called - * @param {function()} fn The function to make hookable - * @param {string} hookName If provided this allows you to register a name for a global hook to have easy access to - * the addHook and removeHook methods for that hook (which are usually accessed as methods on the function itself) - * @returns {HookedFunction} A new function that implements the HookedFunction interface - */ -export function createHook(type, fn, hookName) { - let _hooks = [{fn, priority: 0}]; - - let types = { - sync: function(...args) { - _hooks.forEach(hook => { - hook.fn.apply(this, args); - }); - }, - asyncSeries: function(...args) { - let curr = 0; - - const asyncSeriesNext = (...args) => { - let hook = _hooks[++curr]; - if (typeof hook === 'object' && typeof hook.fn === 'function') { - return hook.fn.apply(this, args.concat(asyncSeriesNext)) - } - }; - - return _hooks[curr].fn.apply(this, args.concat(asyncSeriesNext)); - } - }; - - if (!types[type]) { - throw 'invalid hook type'; - } - - let methods = { - addHook: function(fn, priority = 10) { - if (typeof fn === 'function') { - _hooks.push({ - fn, - priority: priority - }); - - _hooks.sort((a, b) => b.priority - a.priority); - } - }, - removeHook: function(removeFn) { - _hooks = _hooks.filter(hook => hook.fn === fn || hook.fn !== removeFn); - }, - hasHook: function(fn) { - return _hooks.some(hook => hook.fn === fn); - } - }; - - if (typeof hookName === 'string') { - hooks[hookName] = methods; - } - - function hookedFn(...args) { - if (_hooks.length === 1 && _hooks[0].fn === fn) { - return fn.apply(this, args); - } - return types[type].apply(this, args); - } - - return Object.assign(hookedFn, methods); -} +export const hooks = hook.hooks; diff --git a/src/prebid.js b/src/prebid.js index b87eace95f1..f9645c5d9f6 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -8,7 +8,7 @@ import { loadScript } from './adloader'; import { config } from './config'; import { auctionManager } from './auctionManager'; import { targeting, getHighestCpmBidsFromBidPool } from './targeting'; -import { createHook } from './hook'; +import { hook } from './hook'; import { sessionLoader } from './debugging'; import includes from 'core-js/library/fn/array/includes'; import { adunitCounter } from './adUnits'; @@ -328,7 +328,7 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { * @param {Array} requestOptions.labels * @alias module:pbjs.requestBids */ -$$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels } = {}) { +$$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels } = {}) { events.emit(REQUEST_BIDS); const cbTimeout = timeout || config.getConfig('bidderTimeout'); adUnits = adUnits || $$PREBID_GLOBAL$$.adUnits; @@ -752,6 +752,7 @@ function processQueue(queue) { * @alias module:pbjs.processQueue */ $$PREBID_GLOBAL$$.processQueue = function() { + hook.ready(); processQueue($$PREBID_GLOBAL$$.que); processQueue($$PREBID_GLOBAL$$.cmd); }; diff --git a/test/spec/debugging_spec.js b/test/spec/debugging_spec.js index b048382171b..d07f7fc3373 100644 --- a/test/spec/debugging_spec.js +++ b/test/spec/debugging_spec.js @@ -30,14 +30,14 @@ describe('bid overrides', function () { enabled: true }); - expect(addBidResponse.hasHook(boundHook)).to.equal(true); + expect(addBidResponse.getHooks().some(hook => hook.hook === boundHook)).to.equal(true); }); it('should happen when configuration found in sessionStorage', function () { sessionLoader({ getItem: () => ('{"enabled": true}') }); - expect(addBidResponse.hasHook(boundHook)).to.equal(true); + expect(addBidResponse.getHooks().some(hook => hook.hook === boundHook)).to.equal(true); }); it('should not throw if sessionStorage is inaccessible', function () { @@ -80,9 +80,10 @@ describe('bid overrides', function () { function run(overrides) { mockBids.forEach(bid => { - addBidResponseHook(overrides, bid.adUnitCode, bid, (adUnitCode, bid) => { + let next = (adUnitCode, bid) => { bids.push(bid); - }) + }; + addBidResponseHook.bind(overrides)(next, bid.adUnitCode, bid) }); } diff --git a/test/spec/hook_spec.js b/test/spec/hook_spec.js deleted file mode 100644 index 7536f8316d5..00000000000 --- a/test/spec/hook_spec.js +++ /dev/null @@ -1,151 +0,0 @@ - -import { expect } from 'chai'; -import { createHook, hooks } from 'src/hook'; - -describe('the hook module', function () { - let sandbox; - - beforeEach(function () { - sandbox = sinon.sandbox.create(); - }); - - afterEach(function () { - sandbox.restore(); - }); - - it('should call all sync hooks attached to a function', function () { - let called = []; - let calledWith; - - let testFn = () => { - called.push(testFn); - }; - let testHook = (...args) => { - called.push(testHook); - calledWith = args; - }; - let testHook2 = () => { - called.push(testHook2); - }; - let testHook3 = () => { - called.push(testHook3); - }; - - let hookedTestFn = createHook('sync', testFn, 'testHook'); - - hookedTestFn.addHook(testHook, 50); - hookedTestFn.addHook(testHook2, 100); - - // make sure global test hooks work as well (with default priority) - hooks['testHook'].addHook(testHook3); - - hookedTestFn(1, 2, 3); - - expect(called).to.deep.equal([ - testHook2, - testHook, - testHook3, - testFn - ]); - - expect(calledWith).to.deep.equal([1, 2, 3]); - - called = []; - - hookedTestFn.removeHook(testHook); - hooks['testHook'].removeHook(testHook3); - - hookedTestFn(1, 2, 3); - - expect(called).to.deep.equal([ - testHook2, - testFn - ]); - }); - - it('should allow context to be passed to hooks, but keep bound contexts', function () { - let context; - let fn = function() { - context = this; - }; - - let boundContext = {}; - let calledBoundContext; - let hook = function() { - calledBoundContext = this; - }.bind(boundContext); - - let hookFn = createHook('sync', fn); - hookFn.addHook(hook); - - let newContext = {}; - hookFn.bind(newContext)(); - - expect(context).to.equal(newContext); - expect(calledBoundContext).to.equal(boundContext); - }); - - describe('asyncSeries', function () { - it('should call function as normal if no hooks attached', function () { - let fn = sandbox.spy(); - let hookFn = createHook('asyncSeries', fn); - - hookFn(1); - - expect(fn.calledOnce).to.equal(true); - expect(fn.firstCall.args[0]).to.equal(1); - }); - - it('should call hooks correctly applied in asyncSeries', function () { - let called = []; - - let testFn = (called) => { - called.push(testFn); - }; - let testHook = (called, next) => { - called.push(testHook); - next(called); - }; - let testHook2 = (called, next) => { - called.push(testHook2); - next(called); - }; - - let hookedTestFn = createHook('asyncSeries', testFn); - hookedTestFn.addHook(testHook); - hookedTestFn.addHook(testHook2); - - hookedTestFn(called); - - expect(called).to.deep.equal([ - testHook, - testHook2, - testFn - ]); - }); - - it('should allow context to be passed to hooks, but keep bound contexts', function () { - let context; - let fn = function() { - context = this; - }; - - let boundContext1 = {}; - let calledBoundContext1; - let hook1 = function(next) { - calledBoundContext1 = this; - next() - }.bind(boundContext1); - - let hookFn = createHook('asyncSeries', fn); - hookFn.addHook(hook1); - - let newContext = {}; - hookFn = hookFn.bind(newContext); - hookFn(); - - expect(context).to.equal(newContext); - expect(calledBoundContext1).to.equal(boundContext1); - }); - }); -}); diff --git a/test/spec/modules/a4gBidAdapter_spec.js b/test/spec/modules/a4gBidAdapter_spec.js index 4c7520d3b0c..f5aa1014702 100644 --- a/test/spec/modules/a4gBidAdapter_spec.js +++ b/test/spec/modules/a4gBidAdapter_spec.js @@ -70,7 +70,7 @@ describe('a4gAdapterTests', function () { it('bidRequest data', function () { const request = spec.buildRequests(bidRequests); - expect(request.data).to.exists; + expect(request.data).to.exist; }); it('bidRequest zoneIds', function () { diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index 3e6d321e4f9..1fd009ce526 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -86,8 +86,8 @@ describe('AdoceanAdapter', function () { it('should add bidIdMap with correct slaveId => bidId mapping', () => { const requests = spec.buildRequests(bidRequests, bidderRequest); for (let i = 0; i < bidRequests.length; i++) { - expect(requests[i]).to.exists; - expect(requests[i].bidIdMap).to.exists; + expect(requests[i]).to.exist; + expect(requests[i].bidIdMap).to.exist; expect(requests[i].bidIdMap[bidRequests[i].params.slaveId]).to.equal(bidRequests[i].bidId); } }); diff --git a/test/spec/modules/adxcgBidAdapter_spec.js b/test/spec/modules/adxcgBidAdapter_spec.js index faa8db8050a..71fb7bc3776 100644 --- a/test/spec/modules/adxcgBidAdapter_spec.js +++ b/test/spec/modules/adxcgBidAdapter_spec.js @@ -91,7 +91,7 @@ describe('AdxcgAdapter', function () { 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.empty + expect(query.jsonp).to.be.undefined expect(query.prebidBidIds).to.equal('84ab500420319d') }) }) @@ -128,8 +128,8 @@ describe('AdxcgAdapter', function () { let parsedRequestUrl = url.parse(request.url) let query = parsedRequestUrl.search - expect(query.gdpr).to.be.empty - expect(query.gdpr_consent).to.be.empty + expect(query.gdpr).to.be.undefined + expect(query.gdpr_consent).to.be.undefined }) }) diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index 53113d0a67c..7817c939b69 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -146,7 +146,7 @@ describe('AolAdapter', function () { describe('Marketplace', function () { it('should not return request when no bids are present', function () { let [request] = spec.buildRequests([]); - expect(request).to.be.empty; + expect(request).to.be.undefined; }); it('should return request for Marketplace endpoint', function () { @@ -206,7 +206,7 @@ describe('AolAdapter', function () { }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.empty; + expect(request).to.be.undefined; }); it('should return Marketplace URL for eu region', function () { @@ -398,7 +398,7 @@ describe('AolAdapter', function () { params: getMarketplaceBidParams() }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.empty; + expect(request).to.be.undefined; }); it('should return One Mobile url with required params - dcn & pos', function () { @@ -462,7 +462,7 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.empty; + expect(request).to.be.undefined; }); }); }); diff --git a/test/spec/modules/ccxBidAdapter_spec.js b/test/spec/modules/ccxBidAdapter_spec.js index 292503c9e04..a89a0402a97 100644 --- a/test/spec/modules/ccxBidAdapter_spec.js +++ b/test/spec/modules/ccxBidAdapter_spec.js @@ -77,7 +77,7 @@ describe('ccxAdapter', function () { }); describe('buildRequests', function () { it('No valid bids', function () { - expect(spec.buildRequests([])).to.be.empty; + expect(spec.buildRequests([])).to.be.undefined; }); it('Valid bid request - default', function () { diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index 33e6eba42f7..40c96c38eb0 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -30,7 +30,7 @@ describe('consentManagement', function () { describe('valid setConfig value', function () { afterEach(function () { config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); }); it('results in all user settings overriding system defaults', function () { let allConfig = { @@ -49,7 +49,7 @@ describe('consentManagement', function () { describe('static consent string setConfig value', () => { afterEach(() => { config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); }); it('results in user settings overriding system defaults', () => { let staticConfig = { @@ -487,7 +487,7 @@ describe('consentManagement', function () { utils.logWarn.restore(); utils.logError.restore(); config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); resetConsentData(); }); @@ -498,9 +498,9 @@ describe('consentManagement', function () { setConfig(badCMPConfig); expect(userCMP).to.be.equal(badCMPConfig.cmpApi); - requestBidsHook({}, () => { + requestBidsHook(() => { didHookReturn = true; - }); + }, {}); let consent = gdprDataHandler.getConsentData(); sinon.assert.calledOnce(utils.logWarn); expect(didHookReturn).to.be.true; @@ -510,9 +510,9 @@ describe('consentManagement', function () { it('should throw proper errors when CMP is not found', function () { setConfig(goodConfigWithCancelAuction); - requestBidsHook({}, () => { + requestBidsHook(() => { didHookReturn = true; - }); + }, {}); let consent = gdprDataHandler.getConsentData(); // throw 2 errors; one for no bidsBackHandler and for CMP not being found (this is an error due to gdpr config) sinon.assert.calledTwice(utils.logError); @@ -531,7 +531,7 @@ describe('consentManagement', function () { afterEach(function () { config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); cmpStub.restore(); delete window.__cmp; resetConsentData(); @@ -547,7 +547,7 @@ describe('consentManagement', function () { args[2](testConsentData); }); setConfig(goodConfigWithAllowAuction); - requestBidsHook({}, () => {}); + requestBidsHook(() => {}, {}); cmpStub.restore(); // reset the stub to ensure it wasn't called during the second round of calls @@ -555,9 +555,9 @@ describe('consentManagement', function () { args[2](testConsentData); }); - requestBidsHook({}, () => { + requestBidsHook(() => { didHookReturn = true; - }); + }, {}); let consent = gdprDataHandler.getConsentData(); expect(didHookReturn).to.be.true; @@ -585,7 +585,7 @@ describe('consentManagement', function () { afterEach(function () { delete window.$sf; config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); registerStub.restore(); utils.logError.restore(); utils.logWarn.restore(); @@ -611,9 +611,9 @@ describe('consentManagement', function () { }); setConfig(goodConfigWithAllowAuction); - requestBidsHook({adUnits: [{ sizes: [[300, 250]] }]}, () => { + requestBidsHook(() => { didHookReturn = true; - }); + }, {adUnits: [{ sizes: [[300, 250]] }]}); let consent = gdprDataHandler.getConsentData(); sinon.assert.notCalled(utils.logWarn); @@ -637,7 +637,7 @@ describe('consentManagement', function () { afterEach(function () { config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); delete window.__cmp; utils.logError.restore(); utils.logWarn.restore(); @@ -685,14 +685,14 @@ describe('consentManagement', function () { it(`should return the consent string from a postmessage + addEventListener response - ${testName}`, (done) => { stringifyResponse = messageFormatString; setConfig(goodConfigWithAllowAuction); - requestBidsHook({}, () => { + requestBidsHook(() => { let consent = gdprDataHandler.getConsentData(); sinon.assert.notCalled(utils.logWarn); sinon.assert.notCalled(utils.logError); expect(consent.consentString).to.equal('encoded_consent_data_via_post_message'); expect(consent.gdprApplies).to.be.true; done(); - }); + }, {}); }); } }); @@ -709,7 +709,7 @@ describe('consentManagement', function () { afterEach(function () { config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); cmpStub.restore(); utils.logError.restore(); utils.logWarn.restore(); @@ -728,9 +728,9 @@ describe('consentManagement', function () { setConfig(goodConfigWithAllowAuction); - requestBidsHook({}, () => { + requestBidsHook(() => { didHookReturn = true; - }); + }, {}); let consent = gdprDataHandler.getConsentData(); sinon.assert.notCalled(utils.logWarn); @@ -750,9 +750,9 @@ describe('consentManagement', function () { setConfig(goodConfigWithCancelAuction); - requestBidsHook({ bidsBackHandler: () => bidsBackHandlerReturn = true }, () => { + requestBidsHook(() => { didHookReturn = true; - }); + }, { bidsBackHandler: () => bidsBackHandlerReturn = true }); let consent = gdprDataHandler.getConsentData(); sinon.assert.calledOnce(utils.logError); @@ -770,9 +770,9 @@ describe('consentManagement', function () { setConfig(goodConfigWithAllowAuction); - requestBidsHook({}, () => { + requestBidsHook(() => { didHookReturn = true; - }); + }, {}); let consent = gdprDataHandler.getConsentData(); sinon.assert.calledOnce(utils.logWarn); diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index 74453986ce1..832706b2b95 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -256,7 +256,7 @@ describe('Consumable BidAdapter', function () { it('handles empty sync options', function () { let opts = spec.getUserSyncs({}); - expect(opts).to.be.empty; + expect(opts).to.be.undefined; }); it('should return a sync url if iframe syncs are enabled', function () { diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index f4c14032fc5..34991252fa8 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -372,7 +372,7 @@ describe('Conversant adapter tests', function() { }); // construct http post payload const payload = spec.buildRequests(requests).data; - expect(payload).to.have.deep.property('user.ext.fpc', 12345); + expect(payload).to.have.deep.nested.property('user.ext.fpc', 12345); }); it('Verify GDPR bid request', function() { @@ -385,8 +385,8 @@ describe('Conversant adapter tests', function() { }; const payload = spec.buildRequests(bidRequests, bidRequest).data; - expect(payload).to.have.deep.property('user.ext.consent', 'BOJObISOJObISAABAAENAA4AAAAAoAAA'); - expect(payload).to.have.deep.property('regs.ext.gdpr', 1); + expect(payload).to.have.deep.nested.property('user.ext.consent', 'BOJObISOJObISAABAAENAA4AAAAAoAAA'); + expect(payload).to.have.deep.nested.property('regs.ext.gdpr', 1); }); it('Verify GDPR bid request without gdprApplies', function() { @@ -398,7 +398,7 @@ describe('Conversant adapter tests', function() { }; const payload = spec.buildRequests(bidRequests, bidRequest).data; - expect(payload).to.have.deep.property('user.ext.consent', ''); - expect(payload).to.not.have.deep.property('regs.ext.gdpr'); + expect(payload).to.have.deep.nested.property('user.ext.consent', ''); + expect(payload).to.not.have.deep.nested.property('regs.ext.gdpr'); }); }) diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 90059d5a1aa..8a5bea97cb8 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -350,7 +350,7 @@ describe('The Criteo bidding adapter', function () { it('should return undefined with incompatible browsers', function () { // Here use a null hash to make the call to crypto library fail and simulate a browser failure - expect(cryptoVerify(FAST_BID_PUBKEY, null, 'test')).to.equal.undefined; + expect(cryptoVerify(FAST_BID_PUBKEY, null, 'test')).to.be.false; }); }); }); diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index 44816dfd078..9fb32102749 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -10,8 +10,6 @@ import { currencyRates } from 'modules/currency'; -import { createHook } from 'src/hook'; - var assert = require('chai').assert; var expect = require('chai').expect; @@ -21,7 +19,6 @@ describe('currency', function () { let clock; let fn = sinon.spy(); - let hookFn = createHook('asyncSeries', fn, 'addBidResponse'); beforeEach(function () { fakeCurrencyFileServer = sinon.fakeServer.create(); @@ -29,6 +26,7 @@ describe('currency', function () { afterEach(function () { fakeCurrencyFileServer.restore(); + setConfig({}); }); describe('setConfig', function () { @@ -140,9 +138,9 @@ describe('currency', function () { } }); - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.currency).to.equal('GBP'); expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); @@ -162,9 +160,9 @@ describe('currency', function () { } }); - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.currency).to.equal('JPY'); expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); @@ -184,9 +182,9 @@ describe('currency', function () { var bid = { cpm: 100, currency: 'JPY', bidder: 'rubicon' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.cpm).to.equal('1.0000'); expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); @@ -211,9 +209,9 @@ describe('currency', function () { var bid = { cpm: 100, currency: 'JPY', bidder: 'rubicon' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.cpm).to.equal('1.0000'); expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); @@ -232,9 +230,9 @@ describe('currency', function () { setConfig({ 'adServerCurrency': 'JPY' }); var marker = false; - addBidResponseHook('elementId', bid, function() { - marker = true; - }); + addBidResponseHook(function() { + marker = true; + }, 'elementId', bid); expect(marker).to.equal(false); @@ -248,9 +246,9 @@ describe('currency', function () { setConfig({}); var bid = { 'cpm': 1, 'currency': 'USD' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.cpm).to.equal(1); }); @@ -259,9 +257,9 @@ describe('currency', function () { var bid = { 'cpm': 1, 'currency': 'GBP' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); @@ -271,9 +269,9 @@ describe('currency', function () { }); var bid = { 'cpm': 1, 'currency': 'USD' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(bid).to.equal(innerBid); }); @@ -286,9 +284,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); var bid = { 'cpm': 1, 'currency': 'ABC' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); @@ -298,9 +296,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); var bid = { 'cpm': 1, 'currency': 'GBP' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); @@ -310,9 +308,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); var bid = { 'cpm': 1, 'currency': 'JPY' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.cpm).to.equal(1); expect(innerBid.currency).to.equal('JPY'); }); @@ -323,9 +321,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); var bid = { 'cpm': 1, 'currency': 'USD' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.cpm).to.equal('0.7798'); expect(innerBid.currency).to.equal('GBP'); }); @@ -336,9 +334,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); var bid = { 'cpm': 1, 'currency': 'CNY' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.cpm).to.equal('0.1133'); expect(innerBid.currency).to.equal('GBP'); }); @@ -349,9 +347,9 @@ describe('currency', function () { fakeCurrencyFileServer.respond(); var bid = { 'cpm': 1, 'currency': 'JPY' }; var innerBid; - addBidResponseHook('elementId', bid, function(adCodeId, bid) { - innerBid = bid; - }); + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); expect(innerBid.cpm).to.equal('0.0623'); expect(innerBid.currency).to.equal('CNY'); }); diff --git a/test/spec/modules/gjirafaBidAdapter_spec.js b/test/spec/modules/gjirafaBidAdapter_spec.js index d3aaf9765b2..a18ea1b99c3 100644 --- a/test/spec/modules/gjirafaBidAdapter_spec.js +++ b/test/spec/modules/gjirafaBidAdapter_spec.js @@ -53,9 +53,7 @@ describe('gjirafaAdapterTest', function () { 'sizes': [[728, 90], [980, 200], [980, 150], [970, 90], [970, 250]], 'bidId': '10bdc36fe0b48c8', 'bidderRequestId': '70deaff71c281d', - 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc', - 'consent_string': 'consentString', - 'consent_required': 'true' + 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc' }, { 'bidder': 'gjirafa', @@ -69,11 +67,17 @@ describe('gjirafaAdapterTest', function () { 'sizes': [[300, 250]], 'bidId': '81a6dcb65e2bd9', 'bidderRequestId': '70deaff71c281d', - 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc', - 'consent_string': 'consentString', - 'consent_required': 'true' + 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc' }]; + const bidderRequest = { + 'bids': bidRequests, + 'gdprConsent': { + 'consentString': 'consentString', + 'gdprApplies': true + } + }; + it('bidRequest HTTP method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { @@ -92,7 +96,7 @@ describe('gjirafaAdapterTest', function () { it('bidRequest data', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { - expect(requestItem.data).to.exists; + expect(requestItem.data).to.exist; }); }); @@ -103,11 +107,11 @@ describe('gjirafaAdapterTest', function () { }); it('should add GDPR data', function () { - const requests = spec.buildRequests(bidRequests); - expect(requests[0].data.consent_string).to.exists; - expect(requests[0].data.consent_required).to.exists; - expect(requests[1].data.consent_string).to.exists; - expect(requests[1].data.consent_required).to.exists; + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests[0].data.consent_string).to.exist; + expect(requests[0].data.consent_required).to.exist; + expect(requests[1].data.consent_string).to.exist; + expect(requests[1].data.consent_required).to.exist; }); }); diff --git a/test/spec/modules/lifestreetBidAdapter_spec.js b/test/spec/modules/lifestreetBidAdapter_spec.js index 6c9c6eeba31..7f8c5f6c44d 100644 --- a/test/spec/modules/lifestreetBidAdapter_spec.js +++ b/test/spec/modules/lifestreetBidAdapter_spec.js @@ -67,7 +67,7 @@ describe('LifestreetAdapter', function () { it('should not return request when no bids are present', function () { let [request] = spec.buildRequests([]); - expect(request).to.be.empty; + expect(request).to.be.undefined; }); let bidRequest = getDefaultBidRequest(); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 4f7467cf9b1..6b4c206e683 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -406,7 +406,7 @@ describe('S2S Adapter', function () { describe('gdpr tests', function () { afterEach(function () { config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); }); it('adds gdpr consent information to ortb2 request depending on presence of module', function () { diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js index aaf296cfb43..f648e165c93 100644 --- a/test/spec/modules/pubCommonId_spec.js +++ b/test/spec/modules/pubCommonId_spec.js @@ -19,7 +19,7 @@ const TIMEOUT = 2000; describe('Publisher Common ID', function () { afterEach(function () { - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); }); describe('Decorate adUnits', function () { before(function() { @@ -35,16 +35,16 @@ describe('Publisher Common ID', function () { expect(pubcid).to.be.null; // there should be no cookie initially - requestBidHook({adUnits: adUnits1}, (config) => { innerAdUnits1 = config.adUnits }); + requestBidHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); pubcid = getCookie(COOKIE_NAME); // cookies is created after requestbidHook innerAdUnits1.forEach((unit) => { unit.bids.forEach((bid) => { - expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid).to.have.deep.nested.property('crumbs.pubcid'); expect(bid.crumbs.pubcid).to.equal(pubcid); }); }); - requestBidHook({adUnits: adUnits2}, (config) => { innerAdUnits2 = config.adUnits }); + requestBidHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); assert.deepEqual(innerAdUnits1, innerAdUnits2); }); @@ -56,23 +56,23 @@ describe('Publisher Common ID', function () { let pubcid1; let pubcid2; - requestBidHook({adUnits: adUnits1}, (config) => { innerAdUnits1 = config.adUnits }); + requestBidHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); pubcid1 = getCookie(COOKIE_NAME); // get first cookie setCookie(COOKIE_NAME, '', -1); // erase cookie innerAdUnits1.forEach((unit) => { unit.bids.forEach((bid) => { - expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid).to.have.deep.nested.property('crumbs.pubcid'); expect(bid.crumbs.pubcid).to.equal(pubcid1); }); }); - requestBidHook({adUnits: adUnits2}, (config) => { innerAdUnits2 = config.adUnits }); + requestBidHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); pubcid2 = getCookie(COOKIE_NAME); // get second cookie innerAdUnits2.forEach((unit) => { unit.bids.forEach((bid) => { - expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid).to.have.deep.nested.property('crumbs.pubcid'); expect(bid.crumbs.pubcid).to.equal(pubcid2); }); }); @@ -86,10 +86,10 @@ describe('Publisher Common ID', function () { let pubcid = utils.generateUUID(); setCookie(COOKIE_NAME, pubcid, 600); - requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { - expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid).to.have.deep.nested.property('crumbs.pubcid'); expect(bid.crumbs.pubcid).to.equal(pubcid); }); }); @@ -102,11 +102,11 @@ describe('Publisher Common ID', function () { setConfig({}); let adUnits = getAdUnits(); let innerAdUnits; - requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); let pubcid = getCookie(COOKIE_NAME); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { - expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid).to.have.deep.nested.property('crumbs.pubcid'); expect(bid.crumbs.pubcid).to.equal(pubcid); }); }); @@ -119,14 +119,14 @@ describe('Publisher Common ID', function () { let unmodified = getAdUnits(); let innerAdUnits; expect(isPubcidEnabled()).to.be.false; - requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); expect(getCookie(COOKIE_NAME)).to.be.null; assert.deepEqual(innerAdUnits, unmodified); setConfig({enable: true}); // reset - requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { - expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid).to.have.deep.nested.property('crumbs.pubcid'); }); }); }); @@ -137,10 +137,10 @@ describe('Publisher Common ID', function () { expect(getExpInterval()).to.equal(100); let adUnits = getAdUnits(); let innerAdUnits; - requestBidHook({adUnits}, (config) => { innerAdUnits = config.adUnits }); + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); innerAdUnits.every((unit) => { unit.bids.forEach((bid) => { - expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid).to.have.deep.nested.property('crumbs.pubcid'); }); }) }); @@ -187,7 +187,7 @@ describe('Publisher Common ID', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); adUnits.forEach((unit) => { unit.bids.forEach((bid) => { - expect(bid).to.have.deep.property('crumbs.pubcid'); + expect(bid).to.have.deep.nested.property('crumbs.pubcid'); }); }); }); diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index bd341465ab9..707a5f91bec 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -225,7 +225,7 @@ describe('RTBHouseAdapter', () => { } } })); - expect(imp.banner).to.be.empty; + expect(imp.banner).to.be.undefined; }); describe('image sizes', () => { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 7e66bc2a301..839d34d5c57 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1130,7 +1130,7 @@ describe('the rubicon adapter', function () { .that.equals('15'); expect(post).to.have.property('slots') - .with.length.of(1); + .with.a.lengthOf(1); let slot = post.slots[0]; @@ -1194,7 +1194,7 @@ describe('the rubicon adapter', function () { .that.equals('15'); expect(post).to.have.property('slots') - .with.length.of(1); + .with.a.lengthOf(1); let slot = post.slots[0]; diff --git a/test/spec/modules/serverbidBidAdapter_spec.js b/test/spec/modules/serverbidBidAdapter_spec.js index 2e97c43207c..8949463e151 100644 --- a/test/spec/modules/serverbidBidAdapter_spec.js +++ b/test/spec/modules/serverbidBidAdapter_spec.js @@ -241,7 +241,7 @@ describe('Serverbid BidAdapter', function () { it('handles empty sync options', function () { let opts = spec.getUserSyncs({}); - expect(opts).to.be.empty; + expect(opts).to.be.undefined; }); it('should return a sync url if iframe syncs are enabled', function () { diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 91fb4e3e6a7..c5ae9e59054 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -103,7 +103,7 @@ describe('Smart bid adapter tests', function () { describe('gdpr tests', function () { afterEach(function () { config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + $$PREBID_GLOBAL$$.requestBids.removeAll(); }); it('Verify build request with GDPR', function () { diff --git a/test/spec/modules/trafficrootsBidAdapter_spec.js b/test/spec/modules/trafficrootsBidAdapter_spec.js index 40d549e4a5a..54c102d33ef 100644 --- a/test/spec/modules/trafficrootsBidAdapter_spec.js +++ b/test/spec/modules/trafficrootsBidAdapter_spec.js @@ -70,7 +70,7 @@ describe('trafficrootsAdapterTests', () => { it('bidRequest data', () => { const request = spec.buildRequests(bidRequests); - expect(request.data).to.exists; + expect(request.data).to.exist; }); it('bidRequest zoneIds', () => { diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js index 2c8fd9071d6..59f919ed5f5 100644 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -152,8 +152,8 @@ describe('UnrulyAdapter', function () { }); it('should initialize and set the renderer', function () { - expect(Renderer.install).not.to.have.been.called; - expect(fakeRenderer.setRender).not.to.have.been.called; + expect(Renderer.install.called).to.be.false; + expect(fakeRenderer.setRender.called).to.be.false; const mockReturnedBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); const mockRenderer = { url: 'value: mockRendererURL' }; @@ -162,7 +162,7 @@ describe('UnrulyAdapter', function () { adapter.interpretResponse(mockServerResponse); - expect(Renderer.install).to.have.been.calledOnce; + expect(Renderer.install.calledOnce).to.be.true; sinon.assert.calledWithExactly( Renderer.install, Object.assign({}, mockRenderer, {callback: sinon.match.func}) @@ -181,7 +181,7 @@ describe('UnrulyAdapter', function () { sinon.assert.calledOnce(fakeRenderer.setRender); fakeRenderer.setRender.firstCall.args[0](); - expect(window.top).to.have.deep.property('unruly.native.prebid.uq'); + expect(window.top).to.have.deep.nested.property('unruly.native.prebid.uq'); const uq = window.top.unruly.native.prebid.uq; const sentRendererConfig = uq[0][1]; diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js index dc0d547d47a..55afbead72c 100644 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ b/test/spec/modules/widespaceBidAdapter_spec.js @@ -153,7 +153,7 @@ describe('+widespaceAdatperTest', function () { }); it('-bidRequest data exist', function () { - expect(request[0].data).to.exists; + expect(request[0].data).to.exist; }); it('-bidRequest data is form data', function () { @@ -161,7 +161,7 @@ describe('+widespaceAdatperTest', function () { }); it('-bidRequest options have header type', function () { - expect(request[0].options.contentType).to.exists; + expect(request[0].options.contentType).to.exist; }); it('-cookie test for wsCustomData ', function () { diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js index 19756b86bc1..e064b90f059 100644 --- a/test/spec/modules/yieldoneBidAdapter_spec.js +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -210,7 +210,7 @@ describe('yieldoneBidAdapter', function() { describe('getUserSyncs', function () { it('handles empty sync options', function () { - expect(spec.getUserSyncs({})).to.be.empty; + expect(spec.getUserSyncs({})).to.be.undefined; }); it('should return a sync url if iframe syncs are enabled', function () { diff --git a/test/test_index.js b/test/test_index.js index f6a48a7542b..206f1be1f52 100644 --- a/test/test_index.js +++ b/test/test_index.js @@ -3,3 +3,5 @@ require('test/mocks/adloaderStub.js'); var testsContext = require.context('.', true, /_spec$/); testsContext.keys().forEach(testsContext); + +window.$$PREBID_GLOBAL$$.processQueue(); From 4123ea6bdce5fce212ecdb95b22d9e2eee5b12c7 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 29 Jan 2019 15:03:52 -0700 Subject: [PATCH 0969/1594] switch default for useBidCache to false (#3480) --- src/config.js | 2 +- test/spec/unit/pbjs_api_spec.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/config.js b/src/config.js index 1e94614ddaa..a1a8af629d8 100644 --- a/src/config.js +++ b/src/config.js @@ -18,7 +18,7 @@ const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; const DEFAULT_DISABLE_AJAX_TIMEOUT = false; -const DEFAULT_BID_CACHE = true; +const DEFAULT_BID_CACHE = false; const DEFAULT_TIMEOUTBUFFER = 400; diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index b9d538f1656..1a96f134fd1 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -176,13 +176,15 @@ window.apntag = { describe('Unit: Prebid Module', function () { let bidExpiryStub; - before(function () { + beforeEach(function () { bidExpiryStub = sinon.stub(filters, 'isBidNotExpired').callsFake(() => true); + configObj.setConfig({ useBidCache: true }); }); - after(function() { + afterEach(function() { $$PREBID_GLOBAL$$.adUnits = []; bidExpiryStub.restore(); + configObj.setConfig({ useBidCache: false }); }); describe('getAdserverTargetingForAdUnitCodeStr', function () { From 88cca59766520539ea991ffd3a3bf74c8abfa761 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 29 Jan 2019 15:04:32 -0700 Subject: [PATCH 0970/1594] allow globalVarName as babel plugin option (#3491) --- plugins/pbjsGlobals.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/pbjsGlobals.js b/plugins/pbjsGlobals.js index 3e94f13b39f..bf3c9033ee6 100644 --- a/plugins/pbjsGlobals.js +++ b/plugins/pbjsGlobals.js @@ -2,17 +2,17 @@ let t = require('@babel/core').types; let prebid = require('../package.json'); -let replace = { - '$prebid.version$': prebid.version, - '$$PREBID_GLOBAL$$': prebid.globalVarName, - '$$REPO_AND_VERSION$$': `${prebid.repository.url.split('/')[3]}_prebid_${prebid.version}` -}; +module.exports = function(api, options) { + let replace = { + '$prebid.version$': prebid.version, + '$$PREBID_GLOBAL$$': options.globalVarName || prebid.globalVarName, + '$$REPO_AND_VERSION$$': `${prebid.repository.url.split('/')[3]}_prebid_${prebid.version}` + }; -let identifierToStringLiteral = [ - '$$REPO_AND_VERSION$$' -]; + let identifierToStringLiteral = [ + '$$REPO_AND_VERSION$$' + ]; -module.exports = function() { return { visitor: { StringLiteral(path) { From 3ffebe026ebf1e45151a2e45a8af5df40d121e05 Mon Sep 17 00:00:00 2001 From: deekshithraop Date: Tue, 29 Jan 2019 17:39:45 -0500 Subject: [PATCH 0971/1594] Get bid responses (#3492) * 3413-Insert Iframes for user sync in body * Append Iframe as the last child * Add unit test for insertElement * utls insert element at the top by default * add unit tests for utls insert element * Insert iframe as html last child * revert package.lock changes * Override keywords in setTargetingForAst * Add resetPresetTargetingAST for setTargetingForAst * get bidresponses form last auction Id * ignore getbidresponses unit test * Add unit test for getBidResponses * fix typo * Add unit test for getBidResponses * code review changes * add minor check --- src/auctionManager.js | 8 ++++++-- src/prebid.js | 2 +- test/spec/unit/pbjs_api_spec.js | 9 ++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/auctionManager.js b/src/auctionManager.js index 15567f24a88..a8ca246e148 100644 --- a/src/auctionManager.js +++ b/src/auctionManager.js @@ -29,8 +29,8 @@ const CONSTANTS = require('./constants.json'); * @returns {AuctionManager} auctionManagerInstance */ export function newAuctionManager() { - let _auctions = []; - let auctionManager = {}; + const _auctions = []; + const auctionManager = {}; auctionManager.addWinningBid = function(bid) { const auction = find(_auctions, auction => auction.getAuctionId() === bid.auctionId); @@ -100,6 +100,10 @@ export function newAuctionManager() { } } + auctionManager.getLastAuctionId = function() { + return _auctions.length && _auctions[_auctions.length - 1].getAuctionId() + }; + function _addAuction(auction) { _auctions.push(auction); } diff --git a/src/prebid.js b/src/prebid.js index f9645c5d9f6..f94561cc874 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -119,7 +119,7 @@ function getBids(type) { .filter(adUnitsFilter.bind(this, auctionManager.getAdUnitCodes())); // find the last auction id to get responses for most recent auction only - const currentAuctionId = responses && responses.length && responses[responses.length - 1].auctionId; + const currentAuctionId = auctionManager.getLastAuctionId(); return responses .map(bid => bid.adUnitCode) diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 1a96f134fd1..7ee8b27303e 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -792,13 +792,20 @@ describe('Unit: Prebid Module', function () { }); describe('getBidResponses', function () { + it('should return empty obj when last auction Id had no responses', function () { + auctionManager.getLastAuctionId = () => 999994; + var result = $$PREBID_GLOBAL$$.getBidResponses(); + assert.deepEqual(result, {}, 'expected bid responses are returned'); + }); + it('should return expected bid responses when not passed an adunitCode', function () { + auctionManager.getLastAuctionId = () => 654321; var result = $$PREBID_GLOBAL$$.getBidResponses(); var compare = getBidResponsesFromAPI(); assert.deepEqual(result, compare, 'expected bid responses are returned'); }); - it('should return bid responses for most recent requestId only', function () { + it('should return bid responses for most recent auctionId only', function () { const responses = $$PREBID_GLOBAL$$.getBidResponses(); assert.equal(responses[Object.keys(responses)[0]].bids.length, 4); }); From 9b12b55b219c07cccc596b3d0f6f285b0924909a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 29 Jan 2019 17:44:18 -0500 Subject: [PATCH 0972/1594] Prebid 2.0.0 Release --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 31f80c1eed4..bb8e6df15f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.0.0-pre", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -927,7 +927,7 @@ "dependencies": { "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, diff --git a/package.json b/package.json index 3ec3d7bac46..12808e48e5c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.0.0-pre", + "version": "2.0.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 7b792a1e89814afc13b1897f91bdc2d0bc6149e2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 30 Jan 2019 09:53:33 -0500 Subject: [PATCH 0973/1594] Increment Pre release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 12808e48e5c..b01df6f6c83 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.0.0", + "version": "2.1.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 27cc3fe88b1698d0774ec57fdb4e641f85a3bdad Mon Sep 17 00:00:00 2001 From: susyt Date: Wed, 30 Jan 2019 14:12:02 -0800 Subject: [PATCH 0974/1594] updates jcsi.rq value to 8 (#3457) --- modules/gumgumBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 846beae2694..5f18870ae4d 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -47,7 +47,7 @@ function _getBrowserParams() { pu: topUrl, ce: utils.cookiesAreEnabled(), dpr: topWindow.devicePixelRatio || 1, - jcsi: JSON.stringify({ t: 0, rq: 7 }) + jcsi: JSON.stringify({ t: 0, rq: 8 }) } ns = getNetworkSpeed() From fd31534150c05cc2dd63662ea09263531e4b2ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deivydas=20=C5=A0abaras?= Date: Wed, 30 Jan 2019 22:13:56 +0000 Subject: [PATCH 0975/1594] hardcoded bidder code from video bid responses prevent bidderAlias feature to work for video ad units (#3483) --- modules/openxBidAdapter.js | 1 - test/spec/modules/openxBidAdapter_spec.js | 2 -- 2 files changed, 3 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index ecd537f7314..e465e44b25b 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -362,7 +362,6 @@ function createVideoBidResponses(response, {bid, startTime}) { let vastQueryParams = parse(response.vastUrl).search || {}; let bidResponse = {}; bidResponse.requestId = bid.bidId; - bidResponse.bidderCode = BIDDER_CODE; // default 5 mins bidResponse.ttl = 300; // true is net, false is gross diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 7a115ae1096..6ef04ddb9d9 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1437,7 +1437,6 @@ describe('OpenxAdapter', function () { const expectedResponse = [ { 'requestId': '30b31c1838de1e', - 'bidderCode': 'openx', 'cpm': 1, 'width': '640', 'height': '480', @@ -1458,7 +1457,6 @@ describe('OpenxAdapter', function () { const expectedResponse = [ { 'requestId': '30b31c1838de1e', - 'bidderCode': 'openx', 'cpm': 1, 'width': '640', 'height': '480', From 69c4caf375887fce37da2c8023dc6a4bbc061c52 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Thu, 31 Jan 2019 00:16:06 +0200 Subject: [PATCH 0976/1594] YieldNexus: Add multiple media types branch (#3485) * Add support for multiple media types. Add test coverage. * Add support for multiple media types. Add test coverage. * Modify multi-format ads handler. Modify tests. --- modules/yieldNexusBidAdapter.js | 94 ++++-- .../spec/modules/yieldNexusBidAdapter_spec.js | 317 +++++++++++------- 2 files changed, 263 insertions(+), 148 deletions(-) diff --git a/modules/yieldNexusBidAdapter.js b/modules/yieldNexusBidAdapter.js index e1cd3001da3..cf891b025aa 100644 --- a/modules/yieldNexusBidAdapter.js +++ b/modules/yieldNexusBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER, VIDEO } from '../src/mediaTypes'; -import { Renderer } from '../src/Renderer'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER, VIDEO} from '../src/mediaTypes'; +import {Renderer} from '../src/Renderer'; const pixKey = 'utrk'; @@ -9,24 +9,37 @@ function startsWith(str, search) { return str.substr(0, search.length) === search; } +function getMediaType(bid) { + if (bid.ext) { + if (bid.ext.media_type) { + return bid.ext.media_type.toLowerCase(); + } else if (bid.ext.vast_url) { + return VIDEO; + } else { + return BANNER; + } + } + return BANNER; +} + export const spec = { code: 'yieldnexus', aliases: [], supportedMediaTypes: [BANNER, VIDEO], - isBidRequestValid: function(bid) { + isBidRequestValid: function (bid) { if (!bid.params.spid) { return false; } else if (typeof bid.params.spid !== 'string') { return false; } return (typeof bid.params.instl === 'undefined' || bid.params.instl === 0 || bid.params.instl === 1) && - (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && - (typeof bid.params['protocols'] === 'undefined' || Array.isArray(bid.params['protocols'])) && - (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number'); + (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && + (typeof bid.params['protocols'] === 'undefined' || Array.isArray(bid.params['protocols'])) && + (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number'); }, - buildRequests: function(validBidRequests, bidderRequest) { + buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { let referrer = ''; try { @@ -72,24 +85,30 @@ export const spec = { bidfloorcur: 'USD', secure: startsWith(utils.getTopWindowUrl().toLowerCase(), 'http://') ? 0 : 1 }; - if (!bidRequest.mediaTypes || bidRequest.mediaTypes.banner) { - imp.banner = { + + if (bidRequest.mediaTypes && bidRequest.mediaTypes.video) { + imp.video = { w: bidRequest.sizes.length ? bidRequest.sizes[0][0] : 300, h: bidRequest.sizes.length ? bidRequest.sizes[0][1] : 250, + protocols: bidRequest.params.protocols || [1, 2, 3, 4, 5, 6], pos: bidRequest.params.pos || 0, topframe: topFrame }; - } else if (bidRequest.mediaTypes.video) { - imp.video = { + } + + if (!bidRequest.mediaTypes || bidRequest.mediaTypes.banner) { + imp.banner = { w: bidRequest.sizes.length ? bidRequest.sizes[0][0] : 300, h: bidRequest.sizes.length ? bidRequest.sizes[0][1] : 250, - protocols: bidRequest.params.protocols || [1, 2, 3, 4, 5, 6], pos: bidRequest.params.pos || 0, topframe: topFrame }; - } else { + } + + if (!imp.banner && !imp.video) { return; } + req.imp.push(imp); return { method: 'POST', @@ -100,7 +119,7 @@ export const spec = { }); }, - interpretResponse: function(serverResponse, bidRequest) { + interpretResponse: function (serverResponse, bidRequest) { const outBids = []; if (serverResponse && serverResponse.body) { const bids = serverResponse.body.seatbid.reduce((acc, seatBid) => acc.concat(seatBid.bid), []); @@ -113,25 +132,28 @@ export const spec = { ttl: 15 * 60, creativeId: bid.crid, netRevenue: true, - currency: bid.cur || serverResponse.body.cur + currency: bid.cur || serverResponse.body.cur, + mediaType: getMediaType(bid) }; - if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { - outBids.push(Object.assign({}, outBid, { mediaType: 'banner', ad: bid.adm })); - } else if (bidRequest.bidRequest.mediaTypes.video) { - const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); - outBids.push(Object.assign({}, outBid, { - mediaType: 'video', - vastUrl: bid.ext.vast_url, - vastXml: bid.adm, - renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined - })); + + if (utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType)) { + if (outBid.mediaType === VIDEO) { + const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); + outBids.push(Object.assign({}, outBid, { + vastUrl: bid.ext.vast_url, + vastXml: bid.adm, + renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined + })); + } else if (outBid.mediaType === BANNER) { + outBids.push(Object.assign({}, outBid, {ad: bid.adm})); + } } }); } return outBids; }, - getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + getUserSyncs: function (syncOptions, serverResponses, gdprConsent) { const syncs = []; const gdprApplies = gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : false; const suffix = gdprApplies ? 'gc=' + encodeURIComponent(gdprConsent.consentString) : 'gc=missing'; @@ -139,14 +161,20 @@ export const spec = { if (resp.body) { const bidResponse = resp.body; if (bidResponse.ext && Array.isArray(bidResponse.ext[pixKey])) { - bidResponse.ext[pixKey].forEach(pixel => syncs.push({ type: pixel.type, url: pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix) })); + bidResponse.ext[pixKey].forEach(pixel => syncs.push({ + type: pixel.type, + url: pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix) + })); } if (Array.isArray(bidResponse.seatbid)) { bidResponse.seatbid.forEach(seatBid => { if (Array.isArray(seatBid.bid)) { seatBid.bid.forEach(bid => { if (bid.ext && Array.isArray(bid.ext[pixKey])) { - bid.ext[pixKey].forEach(pixel => syncs.push({ type: pixel.type, url: pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix) })); + bid.ext[pixKey].forEach(pixel => syncs.push({ + type: pixel.type, + url: pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix) + })); } }); } @@ -159,21 +187,21 @@ export const spec = { }; function newRenderer(bidRequest, bid, rendererOptions = {}) { - let rendererUrl = '//s.gambid.io/video/latest/renderer.js'; + let rendererUrl = '//s.wlplayer.com/video/latest/renderer.js'; if (bid.ext && bid.ext.renderer_url) { rendererUrl = bid.ext.renderer_url; } if (bidRequest.params && bidRequest.params.rendererUrl) { rendererUrl = bidRequest.params.rendererUrl; } - const renderer = Renderer.install({ url: rendererUrl, config: rendererOptions, loaded: false }); + const renderer = Renderer.install({url: rendererUrl, config: rendererOptions, loaded: false}); renderer.setRender(renderOutstream); return renderer; } function renderOutstream(bid) { bid.renderer.push(() => { - window[ 'GambidPlayer' ].renderAd({ + window['GambidPlayer'].renderAd({ id: bid.adUnitCode + '/' + bid.adId, debug: window.location.href.indexOf('pbjsDebug') >= 0, placement: document.getElementById(bid.adUnitCode), @@ -181,7 +209,7 @@ function renderOutstream(bid) { height: bid.height, events: { ALL_ADS_COMPLETED: () => window.setTimeout(() => { - window[ 'GambidPlayer' ].removeAd(bid.adUnitCode + '/' + bid.adId); + window['GambidPlayer'].removeAd(bid.adUnitCode + '/' + bid.adId); }, 300) }, vastUrl: bid.vastUrl, diff --git a/test/spec/modules/yieldNexusBidAdapter_spec.js b/test/spec/modules/yieldNexusBidAdapter_spec.js index b966d890e7a..40e2bb6c744 100644 --- a/test/spec/modules/yieldNexusBidAdapter_spec.js +++ b/test/spec/modules/yieldNexusBidAdapter_spec.js @@ -1,5 +1,5 @@ -import { expect } from 'chai'; -import { spec } from 'modules/yieldNexusBidAdapter'; +import {expect} from 'chai'; +import {spec} from 'modules/yieldNexusBidAdapter'; import * as utils from 'src/utils'; const spid = '123'; @@ -7,27 +7,27 @@ const spid = '123'; describe('YieldNexusAdapter', () => { describe('isBidRequestValid', () => { it('should validate supply', () => { - expect(spec.isBidRequestValid({ params: {} })).to.equal(false); - expect(spec.isBidRequestValid({ params: { spid: 123 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); + expect(spec.isBidRequestValid({params: {}})).to.equal(false); + expect(spec.isBidRequestValid({params: {spid: 123}})).to.equal(false); + expect(spec.isBidRequestValid({params: {spid: '123'}})).to.equal(true); }); it('should validate bid floor', () => { - expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // bidfloor has a default - expect(spec.isBidRequestValid({ params: { spid: '123', bidfloor: '123' } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { spid: '123', bidfloor: 0.1 } })).to.equal(true); + expect(spec.isBidRequestValid({params: {spid: '123'}})).to.equal(true); // bidfloor has a default + expect(spec.isBidRequestValid({params: {spid: '123', bidfloor: '123'}})).to.equal(false); + expect(spec.isBidRequestValid({params: {spid: '123', bidfloor: 0.1}})).to.equal(true); }); it('should validate adpos', () => { - expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // adpos has a default - expect(spec.isBidRequestValid({ params: { spid: '123', adpos: '123' } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { spid: '123', adpos: 0.1 } })).to.equal(true); + expect(spec.isBidRequestValid({params: {spid: '123'}})).to.equal(true); // adpos has a default + expect(spec.isBidRequestValid({params: {spid: '123', adpos: '123'}})).to.equal(false); + expect(spec.isBidRequestValid({params: {spid: '123', adpos: 0.1}})).to.equal(true); }); it('should validate instl', () => { - expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // adpos has a default - expect(spec.isBidRequestValid({ params: { spid: '123', instl: '123' } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { spid: '123', instl: -1 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { spid: '123', instl: 0 } })).to.equal(true); - expect(spec.isBidRequestValid({ params: { spid: '123', instl: 1 } })).to.equal(true); - expect(spec.isBidRequestValid({ params: { spid: '123', instl: 2 } })).to.equal(false); + expect(spec.isBidRequestValid({params: {spid: '123'}})).to.equal(true); // adpos has a default + expect(spec.isBidRequestValid({params: {spid: '123', instl: '123'}})).to.equal(false); + expect(spec.isBidRequestValid({params: {spid: '123', instl: -1}})).to.equal(false); + expect(spec.isBidRequestValid({params: {spid: '123', instl: 0}})).to.equal(true); + expect(spec.isBidRequestValid({params: {spid: '123', instl: 1}})).to.equal(true); + expect(spec.isBidRequestValid({params: {spid: '123', instl: 2}})).to.equal(false); }); }); describe('buildRequests', () => { @@ -37,8 +37,8 @@ describe('YieldNexusAdapter', () => { 'mediaTypes': { banner: {} }, - 'params': { spid }, - 'sizes': [ [ 300, 250 ], [ 300, 600 ] ] + 'params': {spid}, + 'sizes': [[300, 250], [300, 600]] }; it('returns an array', () => { @@ -48,19 +48,19 @@ describe('YieldNexusAdapter', () => { expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); - response = spec.buildRequests([ bidRequest ]); + response = spec.buildRequests([bidRequest]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); - const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'a' }); - const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'b' }); + const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'a'}); + const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'b'}); response = spec.buildRequests([adUnit1, adUnit2]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); }); it('uses yieldnexus dns', () => { - const response = spec.buildRequests([ bidRequest ])[ 0 ]; + const response = spec.buildRequests([bidRequest])[0]; expect(response.method).to.equal('POST'); expect(response.url).to.match(new RegExp(`^https://ssp\\.ynxs\\.io/r/${spid}/bidr\\?bidder=prebid&rformat=open_rtb&reqformat=rtb_json$`, 'g')); expect(response.data.id).to.equal(bidRequest.auctionId); @@ -70,31 +70,31 @@ describe('YieldNexusAdapter', () => { let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); let response; - response = spec.buildRequests([ bidRequest ])[ 0 ]; + response = spec.buildRequests([bidRequest])[0]; expect(response.data.site.domain).to.equal('www.test.com'); expect(response.data.site.page).to.equal('http://www.test.com/page.html'); expect(response.data.site.ref).to.equal(''); expect(response.data.imp.length).to.equal(1); - expect(response.data.imp[ 0 ].id).to.equal(bidRequest.transactionId); - expect(response.data.imp[ 0 ].instl).to.equal(0); - expect(response.data.imp[ 0 ].tagid).to.equal(bidRequest.adUnitCode); - expect(response.data.imp[ 0 ].bidfloor).to.equal(0); - expect(response.data.imp[ 0 ].bidfloorcur).to.equal('USD'); + expect(response.data.imp[0].id).to.equal(bidRequest.transactionId); + expect(response.data.imp[0].instl).to.equal(0); + expect(response.data.imp[0].tagid).to.equal(bidRequest.adUnitCode); + expect(response.data.imp[0].bidfloor).to.equal(0); + expect(response.data.imp[0].bidfloorcur).to.equal('USD'); const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); bidRequestWithInstlEquals1.params.instl = 1; - response = spec.buildRequests([ bidRequestWithInstlEquals1 ])[ 0 ]; - expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals1.params.instl); + response = spec.buildRequests([bidRequestWithInstlEquals1])[0]; + expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals1.params.instl); const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); bidRequestWithInstlEquals0.params.instl = 1; - response = spec.buildRequests([ bidRequestWithInstlEquals0 ])[ 0 ]; - expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals0.params.instl); + response = spec.buildRequests([bidRequestWithInstlEquals0])[0]; + expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals0.params.instl); const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); bidRequestWithBidfloorEquals1.params.bidfloor = 1; - response = spec.buildRequests([ bidRequestWithBidfloorEquals1 ])[ 0 ]; - expect(response.data.imp[ 0 ].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); + response = spec.buildRequests([bidRequestWithBidfloorEquals1])[0]; + expect(response.data.imp[0].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); stub.restore(); }); @@ -105,20 +105,20 @@ describe('YieldNexusAdapter', () => { const bidRequestWithBanner = utils.deepClone(bidRequest); bidRequestWithBanner.mediaTypes = { banner: { - sizes: [ [ 300, 250 ], [ 120, 600 ] ] + sizes: [[300, 250], [120, 600]] } }; - response = spec.buildRequests([ bidRequestWithBanner ])[ 0 ]; - expect(response.data.imp[ 0 ].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[ 0 ][ 0 ]); - expect(response.data.imp[ 0 ].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[ 0 ][ 1 ]); - expect(response.data.imp[ 0 ].banner.pos).to.equal(0); - expect(response.data.imp[ 0 ].banner.topframe).to.equal(0); + response = spec.buildRequests([bidRequestWithBanner])[0]; + expect(response.data.imp[0].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][0]); + expect(response.data.imp[0].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][1]); + expect(response.data.imp[0].banner.pos).to.equal(0); + expect(response.data.imp[0].banner.topframe).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; - expect(response.data.imp[ 0 ].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); + response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + expect(response.data.imp[0].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); it('builds request video object correctly', () => { @@ -127,20 +127,20 @@ describe('YieldNexusAdapter', () => { const bidRequestWithVideo = utils.deepClone(bidRequest); bidRequestWithVideo.mediaTypes = { video: { - sizes: [ [ 300, 250 ], [ 120, 600 ] ] + sizes: [[300, 250], [120, 600]] } }; - response = spec.buildRequests([ bidRequestWithVideo ])[ 0 ]; - expect(response.data.imp[ 0 ].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[ 0 ][ 0 ]); - expect(response.data.imp[ 0 ].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[ 0 ][ 1 ]); - expect(response.data.imp[ 0 ].video.pos).to.equal(0); - expect(response.data.imp[ 0 ].video.topframe).to.equal(0); + response = spec.buildRequests([bidRequestWithVideo])[0]; + expect(response.data.imp[0].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][0]); + expect(response.data.imp[0].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][1]); + expect(response.data.imp[0].video.pos).to.equal(0); + expect(response.data.imp[0].video.topframe).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; - expect(response.data.imp[ 0 ].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); + response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + expect(response.data.imp[0].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); }); describe('interpretResponse', () => { @@ -153,7 +153,7 @@ describe('YieldNexusAdapter', () => { 'params': { 'spid': spid }, - 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], + 'sizes': [[300, 250], [300, 600]], 'bidId': '111' }; const videoBidRequest = { @@ -165,7 +165,7 @@ describe('YieldNexusAdapter', () => { 'params': { 'spid': spid }, - 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], + 'sizes': [[300, 250], [300, 600]], 'bidId': '111' }; const rtbResponse = { @@ -174,8 +174,8 @@ describe('YieldNexusAdapter', () => { 'cur': 'USD', 'ext': { 'utrk': [ - { 'type': 'iframe', 'url': '//ssp.ynxs.io/user/sync/1' }, - { 'type': 'image', 'url': '//ssp.ynxs.io/user/sync/2' } + {'type': 'iframe', 'url': '//ssp.ynxs.io/user/sync/1'}, + {'type': 'image', 'url': '//ssp.ynxs.io/user/sync/2'} ] }, 'seatbid': [ @@ -187,13 +187,13 @@ describe('YieldNexusAdapter', () => { 'impid': '1', 'price': 2.016, 'adm': '', - 'adomain': [ 'nike.com' ], + 'adomain': ['nike.com'], 'h': 600, 'w': 120, 'ext': { 'vast_url': 'http://vast.tag.com', 'utrk': [ - { 'type': 'iframe', 'url': '//pix.usersync.io/user-sync' } + {'type': 'iframe', 'url': '//pix.usersync.io/user-sync'} ] } } @@ -208,12 +208,12 @@ describe('YieldNexusAdapter', () => { 'price': 3, 'adid': '542jlhdfd2112jnjf3x', 'adm': '', - 'adomain': [ 'adidas.com' ], + 'adomain': ['adidas.com'], 'h': 250, 'w': 300, 'ext': { 'utrk': [ - { 'type': 'image', 'url': '//pix.usersync.io/user-sync' } + {'type': 'image', 'url': '//pix.usersync.io/user-sync'} ] } } @@ -224,87 +224,174 @@ describe('YieldNexusAdapter', () => { it('fails gracefully on empty response body', () => { let response; - response = spec.interpretResponse(undefined, { bidRequest: bannerBidRequest }); + response = spec.interpretResponse(undefined, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); - response = spec.interpretResponse({}, { bidRequest: bannerBidRequest }); + response = spec.interpretResponse({}, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); }); it('collects banner bids', () => { - const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: bannerBidRequest }); + const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); + expect(response.length).to.equal(1); - const ad0 = response[ 0 ], ad1 = response[ 1 ]; + const ad0 = response[0]; expect(ad0.requestId).to.equal(bannerBidRequest.bidId); - expect(ad0.cpm).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].price); - expect(ad0.width).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].w); - expect(ad0.height).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].h); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[1].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[1].bid[0].h); expect(ad0.ttl).to.equal(15 * 60); - expect(ad0.creativeId).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].crid); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); expect(ad0.netRevenue).to.equal(true); - expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); - expect(ad0.ad).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); + expect(ad0.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); expect(ad0.vastXml).to.be.an('undefined'); - - expect(ad1.requestId).to.equal(bannerBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].h); - expect(ad1.ttl).to.equal(15 * 60); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); - expect(ad1.vastXml).to.be.an('undefined'); - - // expect(ad1.ad).to.be.an('undefined'); - // expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + expect(ad0.vastUrl).to.be.an('undefined'); }); it('collects video bids', () => { - const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: videoBidRequest }); + const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: videoBidRequest}); expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); + expect(response.length).to.equal(1); - const ad0 = response[ 0 ], ad1 = response[ 1 ]; + const ad0 = response[0]; expect(ad0.requestId).to.equal(videoBidRequest.bidId); - expect(ad0.cpm).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].price); - expect(ad0.width).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].w); - expect(ad0.height).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].h); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[0].bid[0].h); expect(ad0.ttl).to.equal(15 * 60); - expect(ad0.creativeId).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].crid); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[0].bid[0].crid); expect(ad0.netRevenue).to.equal(true); - expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad0.currency).to.equal(rtbResponse.seatbid[0].bid[0].cur || rtbResponse.cur || 'USD'); expect(ad0.ad).to.be.an('undefined'); - expect(ad0.vastXml).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); - expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.vast_url); - - expect(ad1.requestId).to.equal(videoBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].h); - expect(ad1.ttl).to.equal(15 * 60); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.be.an('undefined'); - expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); - expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.vast_url); + expect(ad0.vastXml).to.equal(rtbResponse.seatbid[0].bid[0].adm); + expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[0].bid[0].ext.vast_url); }); + it('applies user-syncs', () => { - const response = spec.getUserSyncs({}, [ { body: rtbResponse } ]); + const response = spec.getUserSyncs({}, [{body: rtbResponse}]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(4); - expect(response[ 0 ].type).to.equal(rtbResponse.ext.utrk[ 0 ].type); - expect(response[ 0 ].url).to.equal(rtbResponse.ext.utrk[ 0 ].url + '?gc=missing'); - expect(response[ 1 ].type).to.equal(rtbResponse.ext.utrk[ 1 ].type); - expect(response[ 1 ].url).to.equal(rtbResponse.ext.utrk[ 1 ].url + '?gc=missing'); - expect(response[ 2 ].type).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.utrk[ 0 ].type); - expect(response[ 2 ].url).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.utrk[ 0 ].url + '?gc=missing'); - expect(response[ 3 ].type).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.utrk[ 0 ].type); - expect(response[ 3 ].url).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.utrk[ 0 ].url + '?gc=missing'); + expect(response[0].type).to.equal(rtbResponse.ext.utrk[0].type); + expect(response[0].url).to.equal(rtbResponse.ext.utrk[0].url + '?gc=missing'); + expect(response[1].type).to.equal(rtbResponse.ext.utrk[1].type); + expect(response[1].url).to.equal(rtbResponse.ext.utrk[1].url + '?gc=missing'); + expect(response[2].type).to.equal(rtbResponse.seatbid[0].bid[0].ext.utrk[0].type); + expect(response[2].url).to.equal(rtbResponse.seatbid[0].bid[0].ext.utrk[0].url + '?gc=missing'); + expect(response[3].type).to.equal(rtbResponse.seatbid[1].bid[0].ext.utrk[0].type); + expect(response[3].url).to.equal(rtbResponse.seatbid[1].bid[0].ext.utrk[0].url + '?gc=missing'); + }); + + it('supports outstream renderers', function () { + const videoResponse = { + 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', + 'bidid': 'imp_5c24924de4b0d106447af333', + 'cur': 'USD', + 'seatbid': [ + { + 'seat': '3668', + 'group': 0, + 'bid': [ + { + 'id': 'gb_1', + 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + 'price': 5.0, + 'adid': '1274', + 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&p=${AUCTION_PRICE}', + 'adomain': [], + 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'cid': '3668', + 'crid': '1274', + 'cat': [], + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + 'imptrackers': [ + 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] + } + } + ] + } + ], + 'ext': { + 'utrk': [{ + 'type': 'image', + 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' + }] + } + }; + const videoRequest = utils.deepClone(videoBidRequest); + videoRequest.mediaTypes.video.context = 'outstream'; + const result = spec.interpretResponse({body: videoResponse}, {bidRequest: videoRequest}); + expect(result[0].renderer).to.not.equal(undefined); + }); + + it('supports gdpr consent', function () { + let videoResponse = { + 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', + 'bidid': 'imp_5c24924de4b0d106447af333', + 'cur': 'USD', + 'seatbid': [ + { + 'seat': '3668', + 'group': 0, + 'bid': [ + { + 'id': 'gb_1', + 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + 'price': 5.0, + 'adid': '1274', + 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&p=${AUCTION_PRICE}', + 'adomain': [], + 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'cid': '3668', + 'crid': '1274', + 'cat': [], + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + 'imptrackers': [ + 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] + } + } + ] + } + ], + 'ext': { + 'utrk': [{ + 'type': 'image', + 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' + }] + } + }; + let gdprConsent = { + gdprApplies: true, + consentString: 'consent string' + }; + let result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=consent%20string'); + + gdprConsent.gdprApplies = false; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=missing'); + + videoResponse.ext.utrk[0].url = 'https://rtb.gamoshi.io/pix/1275/scm'; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?gc=missing'); }); }); }); From 596af881fd2ae7acbbf34d3bf5d6d6f2b8feeda6 Mon Sep 17 00:00:00 2001 From: Gena Date: Thu, 31 Jan 2019 03:43:05 +0100 Subject: [PATCH 0977/1594] Adtelligent support both userSync types (#3444) * Add user sync pixel logic in Adtelligent adapter * Add gdpr support * Add gdpr support * Update tests * Support both types of user syncs * More logical code with syncs * Remove "only" from test * Update test messages --- modules/adtelligentBidAdapter.js | 26 +++++++---- .../modules/adtelligentBidAdapter_spec.js | 45 +++++++++++++++++-- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/modules/adtelligentBidAdapter.js b/modules/adtelligentBidAdapter.js index e0a65c7a0d8..daa43799edb 100644 --- a/modules/adtelligentBidAdapter.js +++ b/modules/adtelligentBidAdapter.js @@ -20,26 +20,36 @@ export const spec = { getUserSyncs: function (syncOptions, serverResponses) { var syncs = []; - function addSyncs(_s) { - if (_s && _s.length) { - _s.forEach(s => { + function addSyncs(bid) { + const uris = bid.cookieURLs; + const types = bid.cookieURLSTypes || []; + + if (uris && uris.length) { + uris.forEach((uri, i) => { + let type = types[i] || 'image'; + + if ((!syncOptions.pixelEnabled && type == 'image') || + (!syncOptions.iframeEnabled && type == 'iframe')) { + return; + } + syncs.push({ - type: 'image', - url: s + type: type, + url: uri }) }) } } - if (syncOptions.pixelEnabled) { + if (syncOptions.pixelEnabled || syncOptions.iframeEnabled) { serverResponses && serverResponses.length && serverResponses.forEach((response) => { if (response.body) { if (utils.isArray(response.body)) { response.body.forEach(b => { - addSyncs(b.cookieURLs); + addSyncs(b); }) } else { - addSyncs(response.body.cookieURLs) + addSyncs(response.body) } } }) diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js index 0ee2bb2726f..9187d779145 100644 --- a/test/spec/modules/adtelligentBidAdapter_spec.js +++ b/test/spec/modules/adtelligentBidAdapter_spec.js @@ -61,6 +61,21 @@ const SERVER_DISPLAY_RESPONSE = { }], 'cookieURLs': ['link1', 'link2'] }; +const SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'ad': '', + 'requestId': '2e41f65424c87c', + 'creative_id': 342516, + 'cmpId': 342516, + 'height': 250, + 'cur': 'USD', + 'width': 300, + 'cpm': 0.9 + }], + 'cookieURLs': ['link1', 'link2'], + 'cookieURLSTypes': ['image', 'iframe'] +}; const videoBidderRequest = { bidderCode: 'bidderCode', @@ -109,17 +124,39 @@ const displayEqResponse = [{ describe('adtelligentBidAdapter', function () { // todo remove only const adapter = newBidder(spec); - describe('user syncs', function () { + describe('user syncs as image', function () { it('should be returned if pixel enabled', function () { - const syncs = spec.getUserSyncs({pixelEnabled: true}, [{body: SERVER_DISPLAY_RESPONSE}]); + const syncs = spec.getUserSyncs({pixelEnabled: true}, [{body: SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS}]); + + expect(syncs.map(s => s.url)).to.deep.equal([SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS.cookieURLs[0]]); + expect(syncs.map(s => s.type)).to.deep.equal(['image']); + }) + }) + + describe('user syncs as iframe', function () { + it('should be returned if iframe enabled', function () { + const syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS}]); + + expect(syncs.map(s => s.url)).to.deep.equal([SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS.cookieURLs[1]]); + expect(syncs.map(s => s.type)).to.deep.equal(['iframe']); + }) + }) + + describe('user syncs with both types', function () { + it('should be returned if pixel and iframe enabled', function () { + const syncs = spec.getUserSyncs({ + iframeEnabled: true, + pixelEnabled: true + }, [{body: SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS}]); - expect(syncs.map(s => s.url)).to.deep.equal(SERVER_DISPLAY_RESPONSE.cookieURLs); + expect(syncs.map(s => s.url)).to.deep.equal(SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS.cookieURLs); + expect(syncs.map(s => s.type)).to.deep.equal(SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS.cookieURLSTypes); }) }) describe('user syncs', function () { it('should not be returned if pixel not set', function () { - const syncs = spec.getUserSyncs({}, [{body: SERVER_DISPLAY_RESPONSE}]); + const syncs = spec.getUserSyncs({}, [{body: SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS}]); expect(syncs).to.be.empty; }) From ea3d10b502fb42ef03cae4a9e6aa9af11a7376e0 Mon Sep 17 00:00:00 2001 From: Onome Oyibo Date: Thu, 31 Jan 2019 18:50:56 +0000 Subject: [PATCH 0978/1594] feat(unrulyBidAdapter): add userSync functionality (#3460) * feat(unrulyBidAdapter): add userSync functionality * feat(unrulyBidAdapter): add gdpr consent functionality to getUserSyncs * fix(unrulyBidAdapter): fix empty object pattern in tests --- integrationExamples/gpt/unruly_example.html | 4 ++ modules/unrulyBidAdapter.js | 20 +++++++ test/spec/modules/unrulyBidAdapter_spec.js | 60 +++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/integrationExamples/gpt/unruly_example.html b/integrationExamples/gpt/unruly_example.html index 77a9b02b3dd..038951b9eb8 100644 --- a/integrationExamples/gpt/unruly_example.html +++ b/integrationExamples/gpt/unruly_example.html @@ -55,6 +55,10 @@ pbjs.setConfig({ "currency": { "adServerCurrency": "USD", + }, + "userSync": { + "iframeEnabled": true, + "enabledBidders": ['unruly'] } }); }); diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js index 8aa2dba2007..f8e1cc45296 100644 --- a/modules/unrulyBidAdapter.js +++ b/modules/unrulyBidAdapter.js @@ -98,6 +98,26 @@ export const adapter = { return isInvalidResponse ? noBidsResponse : buildPrebidResponseAndInstallRenderer(serverResponseBody.bids); + }, + + getUserSyncs: function(syncOptions, response, gdprConsent) { + let params = ''; + if (gdprConsent && 'gdprApplies' in gdprConsent) { + if (gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { + params += `?gdpr=1&gdpr_consent=${gdprConsent.consentString}`; + } else { + params += `?gdpr=0`; + } + } + + const syncs = [] + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html' + params + }); + } + return syncs; } }; diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js index 59f919ed5f5..2cea833be7e 100644 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -205,4 +205,64 @@ describe('UnrulyAdapter', function () { expect(supplyMode).to.equal('prebid'); }); }); + + describe('getUserSyncs', () => { + it('should push user sync iframe if enabled', () => { + const mockConsent = {} + const response = {} + const syncOptions = { iframeEnabled: true } + const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent) + expect(syncs[0]).to.deep.equal({ + type: 'iframe', + url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html' + }); + }) + + it('should not push user sync iframe if not enabled', () => { + const mockConsent = {} + const response = {} + const syncOptions = { iframeEnabled: false } + const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent); + expect(syncs).to.be.empty; + }); + }); + + it('should not append consent params if gdpr does not apply', () => { + const mockConsent = {} + const response = {} + const syncOptions = { iframeEnabled: true } + const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent) + expect(syncs[0]).to.deep.equal({ + type: 'iframe', + url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html' + }) + }) + + it('should append consent params if gdpr does apply and consent is given', () => { + const mockConsent = { + gdprApplies: true, + consentString: 'hello' + } + const response = {} + const syncOptions = { iframeEnabled: true } + const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent) + expect(syncs[0]).to.deep.equal({ + type: 'iframe', + url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html?gdpr=1&gdpr_consent=hello' + }) + }) + + it('should append consent param if gdpr applies and no consent is given', () => { + const mockConsent = { + gdprApplies: true, + consentString: {} + } + const response = {} + const syncOptions = { iframeEnabled: true } + const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent) + expect(syncs[0]).to.deep.equal({ + type: 'iframe', + url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html?gdpr=0' + }) + }) }); From cbfe3125df65beeb26c8ec429a17d4edc18f8332 Mon Sep 17 00:00:00 2001 From: Joshua Hernandez Date: Thu, 31 Jan 2019 14:49:04 -0700 Subject: [PATCH 0979/1594] New Prebid1.0 adapter for SpotX (#3472) * Add SpotXBidAdapter * Minor updates * Undo testing changes to shared files * Fix relative imports * Remove superfluous imports and write a few more tests --- modules/spotxBidAdapter.js | 417 +++++++++++++++++++++ modules/spotxBidAdapter.md | 135 +++++++ test/spec/modules/spotxBidAdapter_spec.js | 427 ++++++++++++++++++++++ 3 files changed, 979 insertions(+) create mode 100644 modules/spotxBidAdapter.js create mode 100644 modules/spotxBidAdapter.md create mode 100644 test/spec/modules/spotxBidAdapter_spec.js diff --git a/modules/spotxBidAdapter.js b/modules/spotxBidAdapter.js new file mode 100644 index 00000000000..bc109ccc635 --- /dev/null +++ b/modules/spotxBidAdapter.js @@ -0,0 +1,417 @@ +import * as utils from '../src/utils'; +import { Renderer } from '../src/Renderer'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { VIDEO } from '../src/mediaTypes'; + +const BIDDER_CODE = 'spotx'; +const URL = '//search.spotxchange.com/openrtb/2.3/dados/'; +const ORTB_VERSION = '2.3'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['spotx'], + supportedMediaTypes: [VIDEO], + + /** + * Determines whether or not the given bid request is valid. + * From Prebid.js: isBidRequestValid - Verify the the AdUnits.bids, respond with true (valid) or false (invalid). + * + * @param {object} bid The bid to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function(bid) { + if (bid && typeof bid.params !== 'object') { + utils.logError(BIDDER_CODE + ': params is not defined or is incorrect in the bidder settings.'); + return false; + } + + if (!utils.deepAccess(bid, 'mediaTypes.video')) { + utils.logError(BIDDER_CODE + ': mediaTypes.video is not present in the bidder settings.'); + return false; + } + + 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 (!utils.getBidIdParameter('channel_id', bid.params)) { + utils.logError(BIDDER_CODE + ': channel_id is not present in bidder params'); + return false; + } + + 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 (!utils.getBidIdParameter('slot', bid.params.outstream_options)) { + utils.logError(BIDDER_CODE + ': please define parameters slot outstream_options object in the configuration.'); + return false; + } + } + } + + return true; + }, + + /** + * Make a server request from the list of BidRequests. + * from Prebid.js: buildRequests - Takes an array of valid bid requests, all of which are guaranteed to have passed the isBidRequestValid() test. + * + * @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) { + const page = bidderRequest.refererInfo.referer; + const isPageSecure = !!page.match(/^https:/) + + const siteId = ''; + const spotxRequests = bidRequests.map(function(bid) { + const channelId = utils.getBidIdParameter('channel_id', bid.params); + let pubcid = null; + + const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); + const contentWidth = playerSize[0][0]; + const contentHeight = playerSize[0][1]; + + const secure = isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0); + + const ext = { + sdk_name: 'Prebid 1+', + versionOrtb: ORTB_VERSION + }; + + if (utils.getBidIdParameter('ad_volume', bid.params) != '') { + ext.ad_volume = utils.getBidIdParameter('ad_volume', bid.params); + } + + if (utils.getBidIdParameter('ad_unit', bid.params) != '') { + ext.ad_unit = utils.getBidIdParameter('ad_unit', bid.params); + } + + if (utils.getBidIdParameter('outstream_options', bid.params) != '') { + ext.outstream_options = utils.getBidIdParameter('outstream_options', bid.params); + } + + if (utils.getBidIdParameter('outstream_function', bid.params) != '') { + ext.outstream_function = utils.getBidIdParameter('outstream_function', bid.params); + } + + if (utils.getBidIdParameter('custom', bid.params) != '') { + ext.custom = utils.getBidIdParameter('custom', 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]; + let vastStr = ''; + if (preMarketBid['vast_url']) { + vastStr = '' + preMarketBid['vast_url'] + ''; + } else if (preMarketBid['vast_string']) { + vastStr = preMarketBid['vast_string']; + } + ext.pre_market_bids.push({ + id: preMarketBid['deal_id'], + seatbid: [{ + bid: [{ + impid: Date.now(), + dealid: preMarketBid['deal_id'], + price: preMarketBid['price'], + adm: vastStr + }] + }], + cur: preMarketBid['currency'], + ext: { + event_log: [{}] + } + }); + } + } + + const mimes = utils.getBidIdParameter('mimes', bid.params) || ['application/javascript', 'video/mp4', 'video/webm']; + + const spotxReq = { + id: bid.bidId, + secure: secure, + video: { + w: contentWidth, + h: contentHeight, + ext: ext, + mimes: mimes + } + }; + + if (utils.getBidIdParameter('price_floor', bid.params) != '') { + spotxReq.bidfloor = utils.getBidIdParameter('price_floor', bid.params); + } + + if (utils.getBidIdParameter('start_delay', bid.params) != '') { + spotxReq.video.startdelay = 0 + Boolean(utils.getBidIdParameter('start_delay', bid.params)); + } + + if (bid.crumbs && bid.crumbs.pubcid) { + pubcid = bid.crumbs.pubcid; + } + + const language = navigator.language ? 'language' : 'userLanguage'; + const device = { + h: screen.height, + w: screen.width, + dnt: utils.getDNT() ? 1 : 0, + language: navigator[language].split('-')[0], + make: navigator.vendor ? navigator.vendor : '', + ua: navigator.userAgent + }; + + const requestPayload = { + id: channelId, + imp: spotxReq, + site: { + id: siteId, + page: page, + content: 'content', + }, + device: device, + ext: { + wrap_response: 1 + } + }; + + if (utils.getBidIdParameter('number_of_ads', bid.params)) { + requestPayload['ext']['number_of_ads'] = utils.getBidIdParameter('number_of_ads', bid.params); + } + + const userExt = {}; + + // Add GDPR flag and consent string + if (bidderRequest && bidderRequest.gdprConsent) { + userExt.consent = bidderRequest.gdprConsent.consentString; + + if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { + requestPayload.regs = { + ext: { + gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) + } + }; + } + } + + // Add common id if available + if (pubcid) { + userExt.fpc = pubcid; + } + + // Only add the user object if it's not empty + if (!utils.isEmpty(userExt)) { + requestPayload.user = { ext: userExt }; + } + return { + method: 'POST', + url: URL + channelId, + data: requestPayload, + bidRequest: bidderRequest + }; + }); + + return spotxRequests; + }, + + /** + * 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) { + const bidResponses = []; + const serverResponseBody = serverResponse.body; + + 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) { + currentBidRequest = bidderRequest.bidRequest.bids[i]; + } + } + + /** + * Make sure currency and price are the right ones + * TODO: what about the pre_market_bid partners sizes? + */ + utils._each(currentBidRequest.params.pre_market_bids, function(pmb) { + if (pmb.deal_id == spotxBid.id) { + spotxBid.price = pmb.price; + serverResponseBody.cur = pmb.currency; + } + }); + + const bid = { + requestId: currentBidRequest.bidId, + currency: serverResponseBody.cur || 'USD', + cpm: spotxBid.price, + creativeId: spotxBid.crid || '', + ttl: 360, + netRevenue: true, + channel_id: serverResponseBody.id, + cache_key: spotxBid.ext.cache_key, + vastUrl: '//search.spotxchange.com/ad/vast.html?key=' + spotxBid.ext.cache_key, + mediaType: VIDEO, + width: spotxBid.w, + height: spotxBid.h + }; + + const context1 = utils.deepAccess(currentBidRequest, 'mediaTypes.video.context'); + const context2 = utils.deepAccess(currentBidRequest, 'params.ad_unit'); + if (context1 == 'outstream' || context2 == 'outstream') { + const playersize = utils.deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); + const renderer = Renderer.install({ + id: 0, + url: '//', + config: { + adText: 'SpotX Outstream Video Ad via Prebid.js', + player_width: playersize[0][0], + player_height: playersize[0][1], + 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') + } + }); + + try { + renderer.setRender(outstreamRender); + renderer.setEventHandlers({ + impression: function impression() { + return utils.logMessage('SpotX outstream video impression event'); + }, + loaded: function loaded() { + return utils.logMessage('SpotX outstream video loaded event'); + }, + ended: function ended() { + utils.logMessage('SpotX outstream renderer video event'); + } + }); + } catch (err) { + utils.logWarn('Prebid Error calling setRender or setEve,tHandlers on renderer', err); + } + bid.renderer = renderer; + } + + bidResponses.push(bid); + }) + }); + } + + return bidResponses; + } +} + +function createOutstreamScript(bid) { + 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 = '//js.spotx.tv/easi/v1/' + bid.channel_id + '.js'; + let dataSpotXParams = {}; + dataSpotXParams['data-spotx_channel_id'] = '' + bid.channel_id; + dataSpotXParams['data-spotx_vast_url'] = '' + bid.vastUrl; + dataSpotXParams['data-spotx_content_page_url'] = bid.renderer.config.content_page_url; + dataSpotXParams['data-spotx_ad_unit'] = 'incontent'; + + utils.logMessage('[SPOTX][renderer] Default beahavior'); + if (utils.getBidIdParameter('ad_mute', bid.renderer.config.outstream_options)) { + dataSpotXParams['data-spotx_ad_mute'] = '0'; + } + dataSpotXParams['data-spotx_collapse'] = '0'; + dataSpotXParams['data-spotx_autoplay'] = '1'; + dataSpotXParams['data-spotx_blocked_autoplay_override_mode'] = '1'; + dataSpotXParams['data-spotx_video_slot_can_autoplay'] = '1'; + + const playersizeAutoAdapt = utils.getBidIdParameter('playersize_auto_adapt', bid.renderer.config.outstream_options); + if (playersizeAutoAdapt && utils.isBoolean(playersizeAutoAdapt) && playersizeAutoAdapt === true) { + if (bid.width && utils.isNumber(bid.width) && bid.height && utils.isNumber(bid.height)) { + const ratio = bid.width / bid.height; + const slotClientWidth = window.document.getElementById(slot).clientWidth; + let playerWidth = bid.renderer.config.player_width; + let playerHeight = bid.renderer.config.player_height; + let contentWidth = 0; + let contentHeight = 0; + if (slotClientWidth < playerWidth) { + playerWidth = slotClientWidth; + playerHeight = playerWidth / ratio; + } + if (ratio <= 1) { + contentWidth = Math.round(playerHeight * ratio); + contentHeight = playerHeight; + } else { + contentWidth = playerWidth; + contentHeight = Math.round(playerWidth / ratio); + } + + dataSpotXParams['data-spotx_content_width'] = '' + contentWidth; + dataSpotXParams['data-spotx_content_height'] = '' + contentHeight; + } else { + utils.logWarn('[SPOTX][renderer] PlayerSize auto adapt: bid.width and bid.height are incorrect'); + } + } + + const customOverride = utils.getBidIdParameter('custom_override', bid.renderer.config.outstream_options); + if (customOverride && utils.isPlainObject(customOverride)) { + utils.logMessage('[SPOTX][renderer] Custom beahavior.'); + for (let name in customOverride) { + if (customOverride.hasOwnProperty(name)) { + if (name === 'channel_id' || name === 'vast_url' || name === 'content_page_url' || name === 'ad_unit') { + utils.logWarn('[SPOTX][renderer] Custom beahavior: following option cannot be overrided: ' + name); + } else { + dataSpotXParams['data-spotx_' + name] = customOverride[name]; + } + } + } + } + + for (let key in dataSpotXParams) { + if (dataSpotXParams.hasOwnProperty(key)) { + script.setAttribute(key, dataSpotXParams[key]); + } + } + + return script; +} + +function outstreamRender(bid) { + const script = createOutstreamScript(bid); + if (bid.renderer.config.outstream_function != null && typeof bid.renderer.config.outstream_function === 'function') { + bid.renderer.config.outstream_function(bid, script); + } else { + try { + 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; + if (!framedoc && rawframe.contentWindow) { + framedoc = rawframe.contentWindow.document; + } + framedoc.body.appendChild(script); + } else { + const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); + if (slot && window.document.getElementById(slot)) { + window.document.getElementById(slot).appendChild(script); + } else { + window.document.getElementsByTagName('head')[0].appendChild(script); + } + } + } catch (err) { + utils.logError('[SPOTX][renderer] Error:' + err.message) + } + } +} + +registerBidder(spec); diff --git a/modules/spotxBidAdapter.md b/modules/spotxBidAdapter.md new file mode 100644 index 00000000000..db5fd448e04 --- /dev/null +++ b/modules/spotxBidAdapter.md @@ -0,0 +1,135 @@ +# Overview + +``` +Module Name: SpotX Bidder Adapter +Module Type: Bidder Adapter +Maintainer: teameighties@spotx.tv +``` + +# Description + +Connect to SpotX for bids. + +This adapter requires setup and approval from the SpotX team. + +# Test Parameters - Use case #1 - outstream with default rendering options +``` + var adUnits = [{ + code: 'something', + mediaTypes: { + video: { + context: 'outstream', // 'instream' or 'outstream' + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'spotx', + params: { + channel_id: 85394, + ad_unit: 'outstream', + outstream_options: { // Needed for the default outstream renderer - fields video_slot/content_width/content_height are mandatory + slot: 'adSlot1', + content_width: 300, + content_height: 250 + } + } + }] + }]; +``` + +# Test Parameters - Use case #2 - outstream with default rendering options + some other options +``` + var adUnits = [{ + code: 'something', + mediaTypes: { + video: { + context: 'outstream', // 'instream' or 'outstream' + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'spotx', + params: { + channel_id: 85394, + ad_unit: 'outstream', + outstream_options: { + slot: 'adSlot1', + content_width: 300, + content_height: 250, + custom_override: { // This option is not mandatory though used to override default renderer parameters using EASI player options in here: https://developer.spotxchange.com/content/local/docs/sdkDocs/EASI/README.md + collapse: '1', + hide_fullscreen: '1', + unmute_on_mouse: '1', + click_to_replay: '1', + continue_out_of_view: '1', + ad_volume: '100', + content_container_id: 'video1' + } + } + } + }] + }]; +``` + +# Test Parameters - Use case #3 - outstream with your own outstream redering function +``` + var adUnits = [{ + code: 'something', + mediaTypes: { + video: { + context: 'outstream', // 'instream' or 'outstream' + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'spotx', + params: { + channel_id: 79391, + ad_unit: 'outstream', + outstream_function: myOutstreamFunction // Override the default outstream renderer by this referenced function + } + }] + }]; +``` + +# Sample of a custom outstream rendering function +``` +function myOutstreamFunction(bid) { + const videoDiv = 'video1'; + const playerWidth = 300; + const playerHeight = 250; + + window.console.log('[SPOTX][renderer] Handle SpotX custom outstream renderer'); + let script = window.document.createElement('script'); + script.type = 'text/javascript'; + script.src = '//js.spotx.tv/easi/v1/' + bid.channel_id + '.js'; + script.setAttribute('data-spotx_channel_id', '' + bid.channel_id); + script.setAttribute('data-spotx_vast_url', '' + bid.vastUrl); + script.setAttribute('data-spotx_content_width', playerWidth); + script.setAttribute('data-spotx_content_height', playerHeight); + script.setAttribute('data-spotx_content_page_url', bid.renderer.config.content_page_url); + if (bid.renderer.config.ad_mute) { + script.setAttribute('data-spotx_ad_mute', '0'); + } + script.setAttribute('data-spotx_ad_unit', 'incontent'); + script.setAttribute('data-spotx_collapse', '0'); + script.setAttribute('data-spotx_hide_fullscreen', '1'); + script.setAttribute('data-spotx_autoplay', '1'); + script.setAttribute('data-spotx_blocked_autoplay_override_mode', '1'); + script.setAttribute('data-spotx_video_slot_can_autoplay', '1'); + script.setAttribute('data-spotx_unmute_on_mouse', '1'); + script.setAttribute('data-spotx_click_to_replay', '1'); + script.setAttribute('data-spotx_continue_out_of_view', '1'); + script.setAttribute('data-spotx_ad_volume', '100'); + if (bid.renderer.config.inIframe && window.document.getElementById(bid.renderer.config.inIframe).nodeName == 'IFRAME') { + let rawframe = window.document.getElementById(bid.renderer.config.inIframe); + let framedoc = rawframe.contentDocument; + if (!framedoc && rawframe.contentWindow) { + framedoc = rawframe.contentWindow.document; + } + framedoc.body.appendChild(script); + } else { + window.document.getElementById(videoDiv).appendChild(script); + } +}; +``` diff --git a/test/spec/modules/spotxBidAdapter_spec.js b/test/spec/modules/spotxBidAdapter_spec.js new file mode 100644 index 00000000000..ba015331b68 --- /dev/null +++ b/test/spec/modules/spotxBidAdapter_spec.js @@ -0,0 +1,427 @@ +import {expect} from 'chai'; +import {spec} from 'modules/spotxBidAdapter'; + +describe('the spotx adapter', function () { + function getValidBidObject() { + return { + bidId: 123, + mediaTypes: { + video: { + playerSize: [['300', '200']] + } + }, + params: { + channel_id: 12345, + } + }; + }; + + describe('isBidRequestValid', function() { + var bid; + + beforeEach(function() { + bid = getValidBidObject(); + }); + + it('should fail validation if the bid isn\'t defined or not an object', function() { + var result = spec.isBidRequestValid(); + + expect(result).to.equal(false); + + result = spec.isBidRequestValid('not an object'); + + expect(result).to.equal(false); + }); + + it('should succeed validation with all the right parameters', function() { + expect(spec.isBidRequestValid(getValidBidObject())).to.equal(true); + }); + + it('should succeed validation with mediaType and outstream_function or outstream_options', function() { + bid.mediaType = 'video'; + bid.params.outstream_function = 'outstream_func'; + + expect(spec.isBidRequestValid(bid)).to.equal(true); + + delete bid.params.outstream_function; + bid.params.outstream_options = { + slot: 'elemID' + }; + + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should succeed with ad_unit outstream and outstream function set', function() { + bid.params.ad_unit = 'outstream'; + bid.params.outstream_function = function() {}; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should succeed with ad_unit outstream, options set for outstream and slot provided', function() { + bid.params.ad_unit = 'outstream'; + bid.params.outstream_options = {slot: 'ad_container_id'}; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should fail without a channel_id', function() { + delete bid.params.channel_id; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should fail without playerSize', function() { + delete bid.mediaTypes.video.playerSize; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should fail without video', function() { + delete bid.mediaTypes.video; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should fail with ad_unit outstream but no options set for outstream', function() { + bid.params.ad_unit = 'outstream'; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should fail with ad_unit outstream, options set for outstream but no slot provided', function() { + bid.params.ad_unit = 'outstream'; + bid.params.outstream_options = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + describe('buildRequests', function() { + var bid, bidRequestObj; + + beforeEach(function() { + bid = getValidBidObject(); + bidRequestObj = {refererInfo: {referer: 'prebid.js'}}; + }); + + it('should build a very basic request', function() { + var request = spec.buildRequests([bid], bidRequestObj)[0]; + expect(request.method).to.equal('POST'); + expect(request.url).to.equal('//search.spotxchange.com/openrtb/2.3/dados/12345'); + expect(request.bidRequest).to.equal(bidRequestObj); + expect(request.data.id).to.equal(12345); + expect(request.data.ext.wrap_response).to.equal(1); + expect(request.data.imp.id).to.match(/\d+/); + expect(request.data.imp.secure).to.equal(0); + expect(request.data.imp.video).to.deep.equal({ + ext: { + sdk_name: 'Prebid 1+', + versionOrtb: '2.3' + }, + h: '200', + mimes: [ + 'application/javascript', + 'video/mp4', + 'video/webm' + ], + w: '300' + }); + expect(request.data.site).to.deep.equal({ + content: 'content', + id: '', + page: 'prebid.js' + }); + }); + it('should change request parameters based on options sent', function() { + var request = spec.buildRequests([bid], bidRequestObj)[0]; + expect(request.data.imp.video.ext).to.deep.equal({ + sdk_name: 'Prebid 1+', + versionOrtb: '2.3' + }); + + bid.params = { + channel_id: 54321, + ad_mute: 1, + hide_skin: 1, + ad_volume: 1, + ad_unit: 'incontent', + outstream_options: {foo: 'bar'}, + outstream_function: '987', + custom: {bar: 'foo'}, + price_floor: 123, + start_delay: true + }; + + request = spec.buildRequests([bid], bidRequestObj)[0]; + expect(request.data.id).to.equal(54321); + expect(request.data.imp.video.ext).to.deep.equal({ + ad_volume: 1, + ad_unit: 'incontent', + outstream_options: {foo: 'bar'}, + outstream_function: '987', + custom: {bar: 'foo'}, + sdk_name: 'Prebid 1+', + versionOrtb: '2.3' + }); + expect(request.data.imp.video.startdelay).to.equal(1); + expect(request.data.imp.bidfloor).to.equal(123); + }); + + it('should process premarket bids', function() { + var request; + sinon.stub(Date, 'now').returns(1000); + + bid.params.pre_market_bids = [{ + vast_url: 'prebid.js', + deal_id: '123abc', + price: 12, + currency: 'USD' + }]; + + request = spec.buildRequests([bid], bidRequestObj)[0]; + expect(request.data.imp.video.ext.pre_market_bids).to.deep.equal([ + { + 'cur': 'USD', + 'ext': { + 'event_log': [ + {} + ] + }, + 'id': '123abc', + 'seatbid': [ + { + 'bid': [ + { + 'adm': 'prebid.js', + 'dealid': '123abc', + 'impid': 1000, + 'price': 12, + } + ] + } + ] + } + ]); + Date.now.restore(); + }); + + it('should pass GDPR params', function() { + var request; + + bidRequestObj.gdprConsent = { + consentString: 'consent123', + gdprApplies: true + }; + + request = spec.buildRequests([bid], bidRequestObj)[0]; + + expect(request.data.regs.ext.gdpr).to.equal(1); + expect(request.data.user.ext.consent).to.equal('consent123'); + }); + }); + + describe('interpretResponse', function() { + var serverResponse, bidderRequestObj; + + beforeEach(function() { + bidderRequestObj = { + bidRequest: { + bids: [{ + mediaTypes: { + video: { + playerSize: [['400', '300']] + } + }, + bidId: 123, + params: { + player_width: 400, + player_height: 300, + content_page_url: 'prebid.js', + ad_mute: 1, + outstream_options: {foo: 'bar'}, + outstream_function: 'function' + } + }, { + mediaTypes: { + video: { + playerSize: [['200', '100']] + } + }, + bidId: 124, + params: { + player_width: 200, + player_height: 100, + content_page_url: 'prebid.js', + ad_mute: 1, + outstream_options: {foo: 'bar'}, + outstream_function: 'function' + } + }] + } + }; + + serverResponse = { + body: { + id: 12345, + seatbid: [{ + bid: [{ + impid: 123, + cur: 'USD', + price: 12, + crid: 321, + w: 400, + h: 300, + ext: { + cache_key: 'cache123', + slot: 'slot123' + } + }, { + impid: 124, + cur: 'USD', + price: 13, + w: 200, + h: 100, + ext: { + cache_key: 'cache124', + slot: 'slot124' + } + }] + }] + } + }; + }); + + it('should return an array of bid responses', function() { + var responses = spec.interpretResponse(serverResponse, bidderRequestObj); + expect(responses).to.be.an('array').with.length(2); + expect(responses[0].cache_key).to.equal('cache123'); + expect(responses[0].channel_id).to.equal(12345); + expect(responses[0].cpm).to.equal(12); + expect(responses[0].creativeId).to.equal(321); + expect(responses[0].currency).to.equal('USD'); + expect(responses[0].height).to.equal(300); + expect(responses[0].mediaType).to.equal('video'); + expect(responses[0].netRevenue).to.equal(true); + expect(responses[0].requestId).to.equal(123); + expect(responses[0].ttl).to.equal(360); + expect(responses[0].vastUrl).to.equal('//search.spotxchange.com/ad/vast.html?key=cache123'); + expect(responses[0].width).to.equal(400); + expect(responses[1].cache_key).to.equal('cache124'); + expect(responses[1].channel_id).to.equal(12345); + expect(responses[1].cpm).to.equal(13); + expect(responses[1].creativeId).to.equal(''); + expect(responses[1].currency).to.equal('USD'); + expect(responses[1].height).to.equal(100); + expect(responses[1].mediaType).to.equal('video'); + expect(responses[1].netRevenue).to.equal(true); + expect(responses[1].requestId).to.equal(124); + expect(responses[1].ttl).to.equal(360); + expect(responses[1].vastUrl).to.equal('//search.spotxchange.com/ad/vast.html?key=cache124'); + expect(responses[1].width).to.equal(200); + }); + }); + + describe('oustreamRender', function() { + var serverResponse, bidderRequestObj; + + beforeEach(function() { + bidderRequestObj = { + bidRequest: { + bids: [{ + mediaTypes: { + video: { + playerSize: [['400', '300']] + } + }, + bidId: 123, + params: { + ad_unit: 'outstream', + player_width: 400, + player_height: 300, + content_page_url: 'prebid.js', + outstream_options: { + ad_mute: 1, + foo: 'bar', + slot: 'slot123', + playersize_auto_adapt: true, + custom_override: { + digitrust_opt_out: 1, + vast_url: 'bad_vast' + } + }, + } + }] + } + }; + + serverResponse = { + body: { + id: 12345, + seatbid: [{ + bid: [{ + impid: 123, + cur: 'USD', + price: 12, + crid: 321, + w: 400, + h: 300, + ext: { + cache_key: 'cache123', + slot: 'slot123' + } + }] + }] + } + }; + }); + + it('should attempt to insert the EASI script', function() { + var scriptTag; + sinon.stub(window.document, 'getElementById').returns({ + appendChild: sinon.stub().callsFake(function(script) { scriptTag = script }) + }); + var responses = spec.interpretResponse(serverResponse, bidderRequestObj); + + responses[0].renderer.render(responses[0]); + + expect(scriptTag.getAttribute('type')).to.equal('text/javascript'); + expect(scriptTag.getAttribute('src')).to.equal('//js.spotx.tv/easi/v1/12345.js'); + expect(scriptTag.getAttribute('data-spotx_channel_id')).to.equal('12345'); + expect(scriptTag.getAttribute('data-spotx_vast_url')).to.equal('//search.spotxchange.com/ad/vast.html?key=cache123'); + expect(scriptTag.getAttribute('data-spotx_ad_unit')).to.equal('incontent'); + expect(scriptTag.getAttribute('data-spotx_collapse')).to.equal('0'); + expect(scriptTag.getAttribute('data-spotx_autoplay')).to.equal('1'); + expect(scriptTag.getAttribute('data-spotx_blocked_autoplay_override_mode')).to.equal('1'); + expect(scriptTag.getAttribute('data-spotx_video_slot_can_autoplay')).to.equal('1'); + expect(scriptTag.getAttribute('data-spotx_digitrust_opt_out')).to.equal('1'); + expect(scriptTag.getAttribute('data-spotx_content_width')).to.equal('400'); + expect(scriptTag.getAttribute('data-spotx_content_height')).to.equal('300'); + window.document.getElementById.restore(); + }); + + it('should append into an iframe', function() { + var scriptTag; + sinon.stub(window.document, 'getElementById').returns({ + nodeName: 'IFRAME', + contentDocument: { + body: { + appendChild: sinon.stub().callsFake(function(script) { scriptTag = script }) + } + } + }); + + bidderRequestObj.bidRequest.bids[0].params.outstream_options.in_iframe = 'iframeId'; + + var responses = spec.interpretResponse(serverResponse, bidderRequestObj); + + responses[0].renderer.render(responses[0]); + + expect(scriptTag.getAttribute('type')).to.equal('text/javascript'); + expect(scriptTag.getAttribute('src')).to.equal('//js.spotx.tv/easi/v1/12345.js'); + expect(scriptTag.getAttribute('data-spotx_channel_id')).to.equal('12345'); + expect(scriptTag.getAttribute('data-spotx_vast_url')).to.equal('//search.spotxchange.com/ad/vast.html?key=cache123'); + expect(scriptTag.getAttribute('data-spotx_ad_unit')).to.equal('incontent'); + expect(scriptTag.getAttribute('data-spotx_collapse')).to.equal('0'); + expect(scriptTag.getAttribute('data-spotx_autoplay')).to.equal('1'); + expect(scriptTag.getAttribute('data-spotx_blocked_autoplay_override_mode')).to.equal('1'); + expect(scriptTag.getAttribute('data-spotx_video_slot_can_autoplay')).to.equal('1'); + expect(scriptTag.getAttribute('data-spotx_digitrust_opt_out')).to.equal('1'); + expect(scriptTag.getAttribute('data-spotx_content_width')).to.equal('400'); + expect(scriptTag.getAttribute('data-spotx_content_height')).to.equal('300'); + window.document.getElementById.restore(); + }); + }); +}); From e93d17d9d732b65071cc2b184ef47bba75936b7b Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Thu, 31 Jan 2019 23:55:13 +0200 Subject: [PATCH 0980/1594] Enforce video branch (#3478) * Add support for multi-format ad units. Add favoredMediaType property to params. * Add tests for gdpr consent. * Add adId to outbids * Modify media type resolving * Refactor multi-format ad units handler. --- modules/gamoshiBidAdapter.js | 136 +++++++++------ modules/gamoshiBidAdapter.md | 46 ++++- test/spec/modules/gamoshiBidAdapter_spec.js | 182 ++++++++++++++------ 3 files changed, 256 insertions(+), 108 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index fa6632f9abb..4ff304af867 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -1,10 +1,16 @@ import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { config } from '../src/config'; -import { Renderer } from '../src/Renderer'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {config} from '../src/config'; +import {Renderer} from '../src/Renderer'; +import {BANNER, VIDEO} from "../src/mediaTypes"; + +const ENDPOINTS = { + 'cleanmedia': 'https://bidder.cleanmediaads.com', + 'gamoshi': 'https://rtb.gamoshi.io', + 'gambid': 'https://rtb.gamoshi.io', +}; export const helper = { - getTopFrame: function () { try { return window.top === window ? 1 : 0; @@ -12,30 +18,27 @@ export const helper = { } return 0; }, - startsWith: function (str, search) { return str.substr(0, search.length) === search; }, - getTopWindowDomain: function (url) { const domainStart = url.indexOf('://') + '://'.length; return url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)); }, - getTopWindowReferer: function () { - try { - return window.top.document.referrer; - } catch (e) { - utils.logMessage('Failed obtaining top window\'s referrer: ', e); - try { - return window.document.referrer; - } catch (e) { - utils.logMessage('Failed obtaining current window\'s referrer: ', e); + getMediaType: function (bid) { + if (bid.ext) { + if (bid.ext.media_type) { + return bid.ext.media_type.toLowerCase(); + } else if (bid.ext.vast_url) { + return VIDEO; + } else { + return BANNER; } } - return ''; + return BANNER; } -} +}; export const spec = { code: 'gamoshi', @@ -43,7 +46,8 @@ export const spec = { supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - return !!bid.params.supplyPartnerId && typeof bid.params.supplyPartnerId === 'string' && + return !!bid.params.supplyPartnerId && + typeof bid.params.supplyPartnerId === 'string' && (typeof bid.params['rtbEndpoint'] === 'undefined' || typeof bid.params['rtbEndpoint'] === 'string') && (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number') && @@ -54,17 +58,16 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { const {adUnitCode, auctionId, mediaTypes, params, sizes, transactionId} = bidRequest; - const baseEndpoint = params['rtbEndpoint'] || 'https://rtb.gamoshi.io'; + const baseEndpoint = params['rtbEndpoint'] || ENDPOINTS[bidRequest.bidder] || ENDPOINTS['gamoshi']; const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + (params.query ? '&' + params.query : ''); - let referer = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - let url = config.getConfig('pageUrl') || referer || utils.getTopWindowUrl(); + let url = config.getConfig('pageUrl') || bidderRequest.refererInfo.referer; const rtbBidRequest = { 'id': auctionId, 'site': { 'domain': helper.getTopWindowDomain(url), 'page': url, - 'ref': helper.getTopWindowReferer() + 'ref': bidderRequest.refererInfo.referer }, 'device': { 'ua': navigator.userAgent @@ -72,7 +75,8 @@ export const spec = { 'imp': [], 'ext': {} }; - if (bidderRequest && bidderRequest.gdprConsent) { + + if (bidderRequest.gdprConsent) { rtbBidRequest.ext.gdpr_consent = { consent_string: bidderRequest.gdprConsent.consentString, consent_required: bidderRequest.gdprConsent.gdprApplies @@ -88,25 +92,44 @@ export const spec = { 'secure': helper.startsWith(utils.getTopWindowUrl().toLowerCase(), 'http://') ? 0 : 1 }; - if (!mediaTypes || mediaTypes.banner) { - imp.banner = { - w: sizes.length ? sizes[0][0] : 300, - h: sizes.length ? sizes[0][1] : 250, - pos: params.pos || 0, - topframe: helper.getTopFrame() - }; - } else if (mediaTypes.video) { - imp.video = { - w: sizes.length ? sizes[0][0] : 300, - h: sizes.length ? sizes[0][1] : 250, - protocols: params.protocols || [1, 2, 3, 4, 5, 6], - pos: params.pos || 0, - topframe: helper.getTopFrame() - }; - } else { + const hasFavoredMediaType = + params.favoredMediaType && this.supportedMediaTypes.includes(params.favoredMediaType); + + if ((!mediaTypes || mediaTypes.banner)) { + if (!hasFavoredMediaType || params.favoredMediaType === 'banner') { + const bannerImp = Object.assign({}, imp, { + banner: { + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, + pos: params.pos || 0, + topframe: helper.getTopFrame() + } + }); + rtbBidRequest.imp.push(bannerImp); + } + } + + if (mediaTypes && mediaTypes.video) { + if (!hasFavoredMediaType || params.favoredMediaType === 'video') { + const videoImp = Object.assign({}, imp, { + video: { + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, + protocols: params.protocols || [1, 2, 3, 4, 5, 6], + pos: params.pos || 0, + ext: { + context: mediaTypes.video.context + } + } + }); + rtbBidRequest.imp.push(videoImp); + } + } + + if (rtbBidRequest.imp.length === 0) { return; } - rtbBidRequest.imp.push(imp); + return {method: 'POST', url: rtbEndpoint, data: rtbBidRequest, bidRequest}; }); }, @@ -119,9 +142,11 @@ export const spec = { } const bids = response.seatbid.reduce((acc, seatBid) => acc.concat(seatBid.bid), []); - const outBids = []; + let outBids = []; + bids.forEach(bid => { const outBid = { + adId: bidRequest.bidRequest.adUnitCode, requestId: bidRequest.bidRequest.bidId, cpm: bid.price, width: bid.w, @@ -129,18 +154,23 @@ export const spec = { ttl: 60 * 10, creativeId: bid.crid, netRevenue: true, - currency: bid.cur || response.cur + currency: bid.cur || response.cur, + adUnitCode: bidRequest.bidRequest.adUnitCode, + mediaType: helper.getMediaType(bid) + }; - if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { - outBids.push(Object.assign({}, outBid, {mediaType: 'banner', ad: bid.adm})); - } else if (bidRequest.bidRequest.mediaTypes.video) { - const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); - outBids.push(Object.assign({}, outBid, { - mediaType: 'video', - vastUrl: bid.ext.vast_url, - vastXml: bid.adm, - renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined - })); + + 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 = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); + outBids.push(Object.assign({}, outBid, { + vastUrl: bid.ext.vast_url, + vastXml: bid.adm, + renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined + })); + } } }); return outBids; @@ -181,7 +211,7 @@ export const spec = { function newRenderer(bidRequest, bid, rendererOptions = {}) { const renderer = Renderer.install({ - url: (bidRequest.params && bidRequest.params.rendererUrl) || (bid.ext && bid.ext.renderer_url) || '//s.gamoshi.io/video/latest/renderer.js', + url: (bidRequest.params && bidRequest.params.rendererUrl) || (bid.ext && bid.ext.renderer_url) || '//s.wlplayer.com/video/latest/renderer.js', config: rendererOptions, loaded: false, }); diff --git a/modules/gamoshiBidAdapter.md b/modules/gamoshiBidAdapter.md index f88248ef668..6e930375059 100644 --- a/modules/gamoshiBidAdapter.md +++ b/modules/gamoshiBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Gamoshi Bid Adapter Module Type: Bidder Adapter -Maintainer: moses@gamoshi.com +Maintainer: salomon@gamoshi.com ``` # Description @@ -47,7 +47,6 @@ var adUnits = [ // Video outstream adUnit { code: 'video-outstream', - sizes: [[300, 250]], mediaTypes: { video: { context: 'outstream', @@ -76,6 +75,47 @@ var adUnits = [ //instl: 0 } }] - } + }, + + // Multi-Format adUnit + { + code: 'banner-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [300, 250] + }, + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'gamoshi', + params: { + + // ID of the supply partner you created in the Gamoshi dashboard + supplyPartnerId: '1253', + + // OPTIONAL: if you have a whitelabel account on Gamoshi, specify it here + //rtbEndpoint: 'https://my.custom-whitelabel-domain.io', + + // OPTIONAL: custom bid floor + bidfloor: 0.01, + + // OPTIONAL: if you know the ad position on the page, specify it here + // (this corresponds to "Ad Position" in OpenRTB 2.3, section 5.4) + //adpos: 1, + + // OPTIONAL: whether this is an interstitial placement (0 or 1) + // (see "instl" property in "Imp" object in the OpenRTB 2.3, section 3.2.2) + //instl: 0, + + // OPTIONAL: enable enforcement bids of a specific media type (video, banner) + // in this ad placement + // query: 'key1=value1&k2=value2', + // favoredMediaType: 'video', + } + }] + }, ]; ``` diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index 26d67b70f78..896271be4d3 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -4,6 +4,7 @@ import {helper} from 'modules/gamoshiBidAdapter'; import * as utils from 'src/utils'; import {newBidder} from '../../../src/adapters/bidderFactory'; import {deepClone} from 'src/utils'; + const supplyPartnerId = '123'; const adapter = newBidder(spec); describe('GamoshiAdapter', function () { @@ -79,42 +80,47 @@ describe('GamoshiAdapter', function () { }, 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', - refererInfo: {referer: 'http://examplereferer.com'} + refererInfo: {referer: 'http://examplereferer.com'}, + gdprConsent: { + consentString: 'some string', + gdprApplies: true + } }; it('returns an array', function () { let response; response = spec.buildRequests([]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); - response = spec.buildRequests([bidRequest]); + response = spec.buildRequests([bidRequest], bidRequest); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'a'}); const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'b'}); - response = spec.buildRequests([adUnit1, adUnit2]); + response = spec.buildRequests([adUnit1, adUnit2], bidRequest); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); }); it('targets correct endpoint', function () { let response; - response = spec.buildRequests([bidRequest])[0]; + response = spec.buildRequests([bidRequest], bidRequest)[0]; expect(response.method).to.equal('POST'); expect(response.url).to.match(new RegExp(`^https://rtb\\.gamoshi\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); expect(response.data.id).to.equal(bidRequest.auctionId); const bidRequestWithEndpoint = utils.deepClone(bidRequest); bidRequestWithEndpoint.params.rtbEndpoint = 'https://rtb2.gamoshi.io/a12'; - response = spec.buildRequests([bidRequestWithEndpoint])[0]; + response = spec.buildRequests([bidRequestWithEndpoint], bidRequest)[0]; expect(response.url).to.match(new RegExp(`^https://rtb2\\.gamoshi\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); }); it('builds request correctly', function () { let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); - let response; - response = spec.buildRequests([bidRequest])[0]; + let bidRequest2 = deepClone(bidRequest); + bidRequest2.refererInfo.referer = 'http://www.test.com/page.html'; + let response = spec.buildRequests([bidRequest], bidRequest2)[0]; expect(response.data.site.domain).to.equal('www.test.com'); expect(response.data.site.page).to.equal('http://www.test.com/page.html'); - expect(response.data.site.ref).to.equal(''); + expect(response.data.site.ref).to.equal('http://www.test.com/page.html'); expect(response.data.imp.length).to.equal(1); expect(response.data.imp[0].id).to.equal(bidRequest.transactionId); expect(response.data.imp[0].instl).to.equal(0); @@ -123,15 +129,15 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].bidfloorcur).to.equal('USD'); const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); bidRequestWithInstlEquals1.params.instl = 1; - response = spec.buildRequests([bidRequestWithInstlEquals1])[0]; + response = spec.buildRequests([bidRequestWithInstlEquals1], bidRequest2)[0]; expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals1.params.instl); const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); bidRequestWithInstlEquals0.params.instl = 1; - response = spec.buildRequests([bidRequestWithInstlEquals0])[0]; + response = spec.buildRequests([bidRequestWithInstlEquals0], bidRequest2)[0]; expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals0.params.instl); const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); bidRequestWithBidfloorEquals1.params.bidfloor = 1; - response = spec.buildRequests([bidRequestWithBidfloorEquals1])[0]; + response = spec.buildRequests([bidRequestWithBidfloorEquals1], bidRequest2)[0]; expect(response.data.imp[0].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); stub.restore(); }); @@ -144,14 +150,14 @@ describe('GamoshiAdapter', function () { sizes: [[300, 250], [120, 600]] } }; - response = spec.buildRequests([bidRequestWithBanner])[0]; + response = spec.buildRequests([bidRequestWithBanner], bidRequest)[0]; expect(response.data.imp[0].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][0]); expect(response.data.imp[0].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][1]); expect(response.data.imp[0].banner.pos).to.equal(0); expect(response.data.imp[0].banner.topframe).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; expect(response.data.imp[0].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); @@ -163,16 +169,45 @@ describe('GamoshiAdapter', function () { sizes: [[300, 250], [120, 600]] } }; - response = spec.buildRequests([bidRequestWithVideo])[0]; + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; expect(response.data.imp[0].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][0]); expect(response.data.imp[0].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][1]); expect(response.data.imp[0].video.pos).to.equal(0); - expect(response.data.imp[0].video.topframe).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; expect(response.data.imp[0].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); + + it('builds request video object correctly with context', function () { + let response; + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes = { + video: { + context: 'instream' + } + }; + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal('instream'); + bidRequestWithVideo.mediaTypes.video.context = 'outstream'; + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.mediaTypes.video.context = 'outstream'; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal('outstream'); + + const bidRequestWithPosEquals2 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals2.mediaTypes.video.context = null; + response = spec.buildRequests([bidRequestWithPosEquals2], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal(null); + }); + + it('builds request with gdpr consent', function () { + let response = spec.buildRequests([bidRequest], bidRequest)[0]; + expect(response.data.ext).to.have.property('gdpr_consent'); + expect(response.data.ext.gdpr_consent.consent_string).to.equal('some string'); + expect(response.data.ext.gdpr_consent.consent_required).to.equal(true); + }); }); describe('interpretResponse', function () { @@ -188,7 +223,7 @@ describe('GamoshiAdapter', function () { 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', 'bidId': '111', - refererInfo: { referer: 'http://examplereferer.com' } + refererInfo: {referer: 'http://examplereferer.com'} }; const videoBidRequest = { @@ -203,7 +238,7 @@ describe('GamoshiAdapter', function () { 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', 'bidId': '111', - refererInfo: { referer: 'http://examplereferer.com' } + refererInfo: {referer: 'http://examplereferer.com'} }; const rtbResponse = { @@ -227,7 +262,7 @@ describe('GamoshiAdapter', function () { 'price': 2.016, 'adid': '579ef31bfa788b9d2000d562', 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', - 'adm': ' ', + 'adm': '', 'adomain': ['aaa.com'], 'cid': '579ef268fa788b9d2000d55c', 'crid': '579ef31bfa788b9d2000d562', @@ -286,38 +321,28 @@ describe('GamoshiAdapter', function () { it('aggregates banner bids from all seat bids', function () { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); + expect(response.length).to.equal(1); - const ad0 = response[0], ad1 = response[1]; + const ad0 = response[0]; expect(ad0.requestId).to.equal(bannerBidRequest.bidId); - expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); - expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); - expect(ad0.height).to.equal(rtbResponse.seatbid[0].bid[0].h); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[1].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[1].bid[0].h); expect(ad0.ttl).to.equal(60 * 10); - expect(ad0.creativeId).to.equal(rtbResponse.seatbid[0].bid[0].crid); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); expect(ad0.netRevenue).to.equal(true); - expect(ad0.currency).to.equal(rtbResponse.seatbid[0].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad0.ad).to.equal(rtbResponse.seatbid[0].bid[0].adm); + expect(ad0.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); expect(ad0.vastXml).to.be.an('undefined'); - - expect(ad1.requestId).to.equal(bannerBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[1].bid[0].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[1].bid[0].h); - expect(ad1.ttl).to.equal(60 * 10); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); - expect(ad1.vastXml).to.be.an('undefined'); + expect(ad0.vastUrl).to.be.an('undefined'); }); it('aggregates video bids from all seat bids', function () { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: videoBidRequest}); expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); + expect(response.length).to.equal(1); - const ad0 = response[0], ad1 = response[1]; + const ad0 = response[0]; expect(ad0.requestId).to.equal(videoBidRequest.bidId); expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); @@ -329,18 +354,6 @@ describe('GamoshiAdapter', function () { expect(ad0.ad).to.be.an('undefined'); expect(ad0.vastXml).to.equal(rtbResponse.seatbid[0].bid[0].adm); expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[0].bid[0].ext.vast_url); - - expect(ad1.requestId).to.equal(videoBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[1].bid[0].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[1].bid[0].h); - expect(ad1.ttl).to.equal(60 * 10); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.be.an('undefined'); - expect(ad1.vastXml).to.equal(rtbResponse.seatbid[1].bid[0].adm); - expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[1].bid[0].ext.vast_url); }); it('aggregates user-sync pixels', function () { @@ -402,5 +415,70 @@ describe('GamoshiAdapter', function () { const result = spec.interpretResponse({body: videoResponse}, {bidRequest: videoRequest}); expect(result[0].renderer).to.not.equal(undefined); }); + + it('validates in/existing of gdpr consent', function () { + let videoResponse = { + 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', + 'bidid': 'imp_5c24924de4b0d106447af333', + 'cur': 'USD', + 'seatbid': [ + { + 'seat': '3668', + 'group': 0, + 'bid': [ + { + 'id': 'gb_1', + 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + 'price': 5.0, + 'adid': '1274', + 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&p=${AUCTION_PRICE}', + 'adomain': [], + 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'cid': '3668', + 'crid': '1274', + 'cat': [], + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + 'imptrackers': [ + 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] + } + } + ] + } + ], + 'ext': { + 'utrk': [{ + 'type': 'image', + 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' + }] + } + }; + let gdprConsent = { + gdprApplies: true, + consentString: 'consent string' + }; + let result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=consent%20string'); + + gdprConsent.gdprApplies = false; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=missing'); + + videoResponse.ext.utrk[0].url = 'https://rtb.gamoshi.io/pix/1275/scm'; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?gc=missing'); + }); }); }); From 0be342247e7419c771751dc6b8beef4bf534697f Mon Sep 17 00:00:00 2001 From: borisjaskerovich <41855079+borisjaskerovich@users.noreply.github.com> Date: Mon, 4 Feb 2019 09:02:40 +0200 Subject: [PATCH 0981/1594] Timmedia/timadapter 2.0 (#3497) * add tim adapter * add tim spec file * add tim md file * added tests. change adapter. * dummy commit for re-running tests * new code for prebid2.0 * change alias name * change domain name --- modules/timBidAdapter.js | 177 ++++++++++++++++++++++++ modules/timBidAdapter.md | 26 ++++ test/spec/modules/timBidAdapter_spec.js | 152 ++++++++++++++++++++ 3 files changed, 355 insertions(+) create mode 100644 modules/timBidAdapter.js create mode 100644 modules/timBidAdapter.md create mode 100644 test/spec/modules/timBidAdapter_spec.js diff --git a/modules/timBidAdapter.js b/modules/timBidAdapter.js new file mode 100644 index 00000000000..0539f37deef --- /dev/null +++ b/modules/timBidAdapter.js @@ -0,0 +1,177 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import * as bidfactory from '../src/bidfactory'; +var CONSTANTS = require('src/constants.json'); +const BIDDER_CODE = 'tim'; + +function parseBidRequest(bidRequest) { + let params = bidRequest.url.split('?')[1]; + var obj = {}; + var pairs = params.split('&'); + try { + for (var i in pairs) { + var split = pairs[i].split('='); + obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]); + } + } catch (e) { + utils.logError(e); + } + + return JSON.parse(obj.br); +} + +function formatAdMarkup(bid) { + var adm = bid.adm; + if ('nurl' in bid) { + adm += createTrackPixelHtml(bid.nurl); + } + return `${adm}`; +} + +function createTrackPixelHtml(url) { + if (!url) { + return ''; + } + let img = '
'; + img += '
'; + return img; +} + +export const spec = { + code: BIDDER_CODE, + aliases: ['timmedia'], + + isBidRequestValid: function(bid) { + if (bid.params && bid.params.publisherid && bid.params.placementCode) { + return true; + } if (!bid.params) { + utils.logError('bid not valid: params were not provided'); + } else if (!bid.params.publisherid) { + utils.logError('bid not valid: publisherid was not provided'); + } else if (!bid.params.placementCode) { + utils.logError('bid not valid: placementCode was not provided'); + } return false; + }, + + buildRequests: function(validBidRequests, bidderRequest) { + var requests = []; + for (var i = 0; i < validBidRequests.length; i++) { + requests.push(this.createRTBRequestURL(validBidRequests[i])); + } + return requests; + }, + + createRTBRequestURL: function(bidReq) { + // build bid request object + var domain = window.location.host; + var page = window.location.href; + var publisherid = bidReq.params.publisherid; + var bidFloor = bidReq.params.bidfloor; + var placementCode = bidReq.params.placementCode; + + var adW = bidReq.mediaTypes.banner.sizes[0][0]; + var adH = bidReq.mediaTypes.banner.sizes[0][1]; + + // build bid request with impressions + var bidRequest = { + id: utils.getUniqueIdentifierStr(), + imp: [{ + id: bidReq.bidId, + banner: { + w: adW, + h: adH + }, + tagid: placementCode, + bidfloor: bidFloor + }], + site: { + domain: domain, + page: page, + publisher: { + id: publisherid + } + }, + device: { + 'language': this.getLanguage(), + 'w': adW, + 'h': adH, + 'js': 1, + 'ua': navigator.userAgent + } + }; + if (!bidFloor) { + delete bidRequest.imp['bidfloor']; + } + + bidRequest.bidId = bidReq.bidId; + var url = '//hb.timmedia-hb.com/api/v2/services/prebid/' + publisherid + '/' + placementCode + '?' + 'br=' + encodeURIComponent(JSON.stringify(bidRequest)); + return { + method: 'GET', + url: url, + data: '', + options: {withCredentials: false} + }; + }, + + interpretResponse: function(serverResponse, bidRequest) { + bidRequest = parseBidRequest(bidRequest); + var bidResp = serverResponse.body; + const bidResponses = []; + if ((!bidResp || !bidResp.id) || + (!bidResp.seatbid || bidResp.seatbid.length === 0 || !bidResp.seatbid[0].bid || bidResp.seatbid[0].bid.length === 0)) { + return []; + } + bidResp.seatbid[0].bid.forEach(function (bidderBid) { + var responseCPM; + var placementCode = ''; + if (bidRequest) { + var bidResponse = bidfactory.createBid(1); + placementCode = bidRequest.placementCode; + bidRequest.status = CONSTANTS.STATUS.GOOD; + responseCPM = parseFloat(bidderBid.price); + if (responseCPM === 0) { + var bid = bidfactory.createBid(2); + bid.bidderCode = BIDDER_CODE; + bidResponses.push(bid); + return bidResponses; + } + bidResponse.placementCode = placementCode; + bidResponse.size = bidRequest.sizes; + bidResponse.creativeId = bidderBid.id; + bidResponse.bidderCode = BIDDER_CODE; + bidResponse.cpm = responseCPM; + bidResponse.ad = formatAdMarkup(bidderBid); + bidResponse.width = parseInt(bidderBid.w); + bidResponse.height = parseInt(bidderBid.h); + bidResponse.currency = bidResp.cur; + bidResponse.netRevenue = true; + bidResponse.requestId = bidRequest.bidId; + bidResponse.ttl = 180; + bidResponses.push(bidResponse); + } + }); + return bidResponses; + }, + getLanguage: function() { + const language = navigator.language ? 'language' : 'userLanguage'; + return navigator[language].split('-')[0]; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = [] + return syncs; + }, + + onTimeout: function(data) { + // Bidder specifc code + }, + + onBidWon: function(bid) { + // Bidder specific code + }, + + onSetTargeting: function(bid) { + // Bidder specific code + }, +} +registerBidder(spec); diff --git a/modules/timBidAdapter.md b/modules/timBidAdapter.md new file mode 100644 index 00000000000..684f2e5f7c4 --- /dev/null +++ b/modules/timBidAdapter.md @@ -0,0 +1,26 @@ +# Overview + +``` +Module Name: tim Bidder Adapter +Module Type: Bidder Adapter +Maintainer: boris@thetimmedia.com +``` + +# Description + +Module that connects to tim's demand sources + +# Test Parameters +``` + var adUnits = [{ + "code":"99", + "sizes":[[300,250]], + "bids":[{"bidder":"tim", + "params":{ + "placementCode":"testPlacementCode", + "publisherid":"testpublisherid" + } + }] + }] +``` + diff --git a/test/spec/modules/timBidAdapter_spec.js b/test/spec/modules/timBidAdapter_spec.js new file mode 100644 index 00000000000..0dc14bf3e03 --- /dev/null +++ b/test/spec/modules/timBidAdapter_spec.js @@ -0,0 +1,152 @@ +import { expect } from 'chai'; +import { spec } from 'modules/timBidAdapter'; + +describe('timAdapterTests', function () { + describe('bidRequestValidity', function () { + it('bidRequest with publisherid and placementCode params', function () { + expect(spec.isBidRequestValid({ + bidder: 'tim', + params: { + publisherid: 'testid', + placementCode: 'testplacement' + } + })).to.equal(true); + }); + + it('bidRequest with only publisherid', function () { + expect(spec.isBidRequestValid({ + bidder: 'tim', + params: { + publisherid: 'testid' + } + })).to.equal(false); + }); + + it('bidRequest with only placementCode', function () { + expect(spec.isBidRequestValid({ + bidder: 'tim', + params: { + placementCode: 'testplacement' + } + })).to.equal(false); + }); + + it('bidRequest without params', function () { + expect(spec.isBidRequestValid({ + bidder: 'tim', + })).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const validBidRequests = [{ + 'bidder': 'tim', + 'params': {'placementCode': 'placementCode', 'publisherid': 'testpublisherid'}, + 'mediaTypes': {'banner': {'sizes': [[300, 250]]}}, + 'adUnitCode': 'adUnitCode', + 'transactionId': 'transactionId', + 'sizes': [[300, 250]], + 'bidId': 'bidId', + 'bidderRequestId': 'bidderRequestId', + 'auctionId': 'auctionId', + 'src': 'client', + 'bidRequestsCount': 1 + }]; + + it('bidRequest method', function () { + const requests = spec.buildRequests(validBidRequests); + expect(requests[0].method).to.equal('GET'); + }); + + it('bidRequest url', function () { + const requests = spec.buildRequests(validBidRequests); + expect(requests[0].url).to.exist; + }); + + it('bidRequest data', function () { + const requests = spec.buildRequests(validBidRequests); + expect(requests[0].data).to.exist; + }); + + it('bidRequest options', function () { + const requests = spec.buildRequests(validBidRequests); + expect(requests[0].options).to.exist; + }); + }); + + describe('interpretResponse', function () { + const bidRequest = { + 'method': 'GET', + 'url': '//bidder.url/api/prebid/testpublisherid/header-bid-tag-0?br=%7B%22id%22%3A%223a3ac0d7fc2548%22%2C%22imp%22%3A%5B%7B%22id%22%3A%22251b8a6d3aac3e%22%2C%22banner%22%3A%7B%22w%22%3A300%2C%22h%22%3A250%7D%2C%22tagid%22%3A%22header-bid-tag-0%22%7D%5D%2C%22site%22%3A%7B%22domain%22%3A%22www.chinatimes.com%22%2C%22page%22%3A%22http%3A%2F%2Fwww.chinatimes.com%2Fa%22%2C%22publisher%22%3A%7B%22id%22%3A%22testpublisherid%22%7D%7D%2C%22device%22%3A%7B%22language%22%3A%22en%22%2C%22w%22%3A300%2C%22h%22%3A250%2C%22js%22%3A1%2C%22ua%22%3A%22Mozilla%2F5.0%20(Windows%20NT%2010.0%3B%20Win64%3B%20x64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F71.0.3578.98%20Safari%2F537.36%22%7D%2C%22bidId%22%3A%22251b8a6d3aac3e%22%7D', + 'data': '', + 'options': {'withCredentials': false} + }; + + const serverResponse = { + 'body': { + 'id': 'id', + 'seatbid': [] + }, + 'headers': {} + }; + + it('check empty array response', function () { + const result = spec.interpretResponse(serverResponse, bidRequest); + expect(result).to.deep.equal([]); + }); + + const validBidRequest = { + 'method': 'GET', + 'url': '//bidder.url/api/v2/services/prebid/testpublisherid/placementCodeTest?br=%7B%22id%22%3A%2248640869bd9db94%22%2C%22imp%22%3A%5B%7B%22id%22%3A%224746fcaa11197f3%22%2C%22banner%22%3A%7B%22w%22%3A300%2C%22h%22%3A250%7D%2C%22tagid%22%3A%22placementCodeTest%22%7D%5D%2C%22site%22%3A%7B%22domain%22%3A%22mediamart.tv%22%2C%22page%22%3A%22http%3A%2F%2Fmediamart.tv%2Fsas%2Ftests%2FDesktop%2Fcaesar%2Fdfptest.html%22%2C%22publisher%22%3A%7B%22id%22%3A%22testpublisherid%22%7D%7D%2C%22device%22%3A%7B%22language%22%3A%22en%22%2C%22w%22%3A300%2C%22h%22%3A250%2C%22js%22%3A1%2C%22ua%22%3A%22Mozilla%2F5.0%20(Windows%20NT%2010.0%3B%20Win64%3B%20x64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F71.0.3578.98%20Safari%2F537.36%22%7D%2C%22bidId%22%3A%224746fcaa11197f3%22%7D', + 'data': '', + 'options': {'withCredentials': false} + }; + const validServerResponse = { + 'body': {'id': 'id', + 'seatbid': [ + {'bid': [{'id': 'id', + 'impid': 'impid', + 'price': 3, + 'nurl': 'https://bidder.url/api/v1/?price=${AUCTION_PRICE}&bidcur=USD&bidid=bidid=true', + 'adm': '', + 'adomain': [''], + 'cid': '1', + 'crid': '700', + 'w': 300, + 'h': 250 + }]}], + 'bidid': 'bidid', + 'cur': 'USD' + }, + 'headers': {} + }; + it('required keys', function () { + const result = spec.interpretResponse(validServerResponse, validBidRequest); + + let requiredKeys = [ + 'requestId', + 'creativeId', + 'adId', + 'cpm', + 'width', + 'height', + 'currency', + 'netRevenue', + 'ttl', + 'ad' + ]; + + let resultKeys = Object.keys(result[0]); + requiredKeys.forEach(function(key) { + expect(resultKeys.indexOf(key) !== -1).to.equal(true); + }); + }) + }); + + describe('getUserSyncs', function () { + it('check empty response getUserSyncs', function () { + const result = spec.getUserSyncs('', ''); + expect(result).to.deep.equal([]); + }); + }); +}); From 85cbc8884a03fc1fda1198efa5d25860e6f91d63 Mon Sep 17 00:00:00 2001 From: Andrew Muraco Date: Mon, 4 Feb 2019 10:56:05 -0500 Subject: [PATCH 0982/1594] Updated synacormedia bid adaptor to assign a unique adId to each bid returned, and submit bid requests for every sizes instead of just the first size of an ad unit. Added test cases for multi-bid/multi-size (#3487) --- modules/synacormediaBidAdapter.js | 30 ++++---- .../modules/synacormediaBidAdapter_spec.js | 76 ++++++++++++++++--- 2 files changed, 80 insertions(+), 26 deletions(-) diff --git a/modules/synacormediaBidAdapter.js b/modules/synacormediaBidAdapter.js index d987979e1fa..8dd23b5048f 100644 --- a/modules/synacormediaBidAdapter.js +++ b/modules/synacormediaBidAdapter.js @@ -40,18 +40,19 @@ export const spec = { seatId = bid.params.seatId; } let placementId = bid.params.placementId; - let size = getAdUnitSizes(bid)[0]; - this.sizeMap[bid.bidId] = size; - openRtbBidRequest.imp.push({ - id: bid.bidId, - tagid: placementId, - banner: { - w: size[0], - h: size[1], - pos: 0 - } + getAdUnitSizes(bid).forEach((size, i) => { + openRtbBidRequest.imp.push({ + id: bid.bidId + '~' + size[0] + 'x' + size[1], + tagid: placementId, + banner: { + w: size[0], + h: size[1], + pos: 0 + } + }); }); }); + if (openRtbBidRequest.imp.length && seatId) { return { method: 'POST', @@ -74,7 +75,6 @@ export const spec = { if (id && seatbids) { seatbids.forEach(seatbid => { seatbid.bid.forEach(bid => { - let size = this.sizeMap[bid.impid] || [0, 0]; let price = parseFloat(bid.price); let creative = bid.adm.replace(/\${([^}]*)}/g, (match, key) => { switch (key) { @@ -87,11 +87,13 @@ export const spec = { } return match; }); + let [, impid, width, height] = bid.impid.match(/^(.*)~(.*)x(.*)$/); bids.push({ - requestId: bid.impid, + requestId: impid, + adId: bid.id.replace(/~/g, '-'), cpm: price, - width: size[0], - height: size[1], + width: parseInt(width, 10), + height: parseInt(height, 10), creativeId: seatbid.seat + '~' + bid.crid, currency: 'USD', netRevenue: true, diff --git a/test/spec/modules/synacormediaBidAdapter_spec.js b/test/spec/modules/synacormediaBidAdapter_spec.js index 9a95d1377e8..17bad3317e8 100644 --- a/test/spec/modules/synacormediaBidAdapter_spec.js +++ b/test/spec/modules/synacormediaBidAdapter_spec.js @@ -35,7 +35,7 @@ describe('synacormediaBidAdapter ', function () { describe('buildRequests', function () { let validBidRequest = { bidId: '9876abcd', - sizes: [[300, 250]], + sizes: [[300, 250], [300, 600]], params: { seatId: 'prebid', placementId: '1234' @@ -49,13 +49,22 @@ describe('synacormediaBidAdapter ', function () { } }; - let expectedDataImp = { + let expectedDataImp1 = { banner: { h: 250, pos: 0, w: 300, }, - id: '9876abcd', + id: '9876abcd~300x250', + tagid: '1234' + }; + let expectedDataImp2 = { + banner: { + h: 600, + pos: 0, + w: 300, + }, + id: '9876abcd~300x600', tagid: '1234' }; @@ -67,7 +76,7 @@ describe('synacormediaBidAdapter ', function () { expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?'); expect(req.data).to.exist.and.to.be.an('object'); expect(req.data.id).to.equal('xyz123'); - expect(req.data.imp).to.eql([expectedDataImp]); + expect(req.data.imp).to.eql([expectedDataImp1, expectedDataImp2]); }); it('should return multiple bids when multiple valid requests with the same seatId are used', function () { @@ -85,13 +94,13 @@ describe('synacormediaBidAdapter ', function () { expect(req).to.have.property('url'); expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?'); expect(req.data.id).to.equal('xyz123'); - expect(req.data.imp).to.eql([expectedDataImp, { + expect(req.data.imp).to.eql([expectedDataImp1, expectedDataImp2, { banner: { h: 600, pos: 0, w: 300, }, - id: 'foobar', + id: 'foobar~300x600', tagid: '5678' }]); }); @@ -117,7 +126,7 @@ describe('synacormediaBidAdapter ', function () { pos: 0, w: 300, }, - id: 'foobar', + id: 'foobar~300x250', tagid: '5678' } ]); @@ -132,12 +141,18 @@ describe('synacormediaBidAdapter ', function () { describe('interpretResponse', function () { let bidResponse = { id: '10865933907263896~9998~0', - impid: '9876abcd', + impid: '9876abcd~300x250', price: 0.13, crid: '1022-250', adm: '' }; - spec.sizeMap['9876abcd'] = [300, 250]; + let bidResponse2 = { + id: '10865933907263800~9999~0', + impid: '9876abcd~300x600', + price: 1.99, + crid: '9993-013', + adm: '' + }; let serverResponse; beforeEach(function() { @@ -151,12 +166,13 @@ describe('synacormediaBidAdapter ', function () { } }; }); - it('should return a bid when bid is in the response', function () { + it('should return 1 bid when 1 bid is in the response', function () { serverResponse.body.seatbid[0].bid.push(bidResponse); let resp = spec.interpretResponse(serverResponse); - expect(resp).to.be.an('array').that.is.not.empty; + expect(resp).to.be.an('array').to.have.lengthOf(1); expect(resp[0]).to.eql({ requestId: '9876abcd', + adId: '10865933907263896-9998-0', cpm: 0.13, width: 300, height: 250, @@ -164,7 +180,43 @@ describe('synacormediaBidAdapter ', function () { currency: 'USD', netRevenue: true, mediaType: BANNER, - ad: '', + ad: '', + ttl: 60 + }); + }); + + it('should return 2 bids when 2 bids are in the response', function () { + serverResponse.body.seatbid[0].bid.push(bidResponse); + serverResponse.body.seatbid.push({ + seat: '9999', + bid: [bidResponse2], + }); + let resp = spec.interpretResponse(serverResponse); + expect(resp).to.be.an('array').to.have.lengthOf(2); + expect(resp[0]).to.eql({ + requestId: '9876abcd', + adId: '10865933907263896-9998-0', + cpm: 0.13, + width: 300, + height: 250, + creativeId: '9998~1022-250', + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: '', + ttl: 60 + }); + expect(resp[1]).to.eql({ + requestId: '9876abcd', + adId: '10865933907263800-9999-0', + cpm: 1.99, + width: 300, + height: 600, + creativeId: '9999~9993-013', + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: '', ttl: 60 }); }); From cbc2668be2bed53b156716f763ca9d0520fd2df9 Mon Sep 17 00:00:00 2001 From: Lewis Moore Date: Mon, 4 Feb 2019 16:07:57 +0000 Subject: [PATCH 0983/1594] fix(unruly): avoid sending options request (#3500) --- modules/unrulyBidAdapter.js | 2 +- test/spec/modules/unrulyBidAdapter_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js index f8e1cc45296..8fb7e1913b3 100644 --- a/modules/unrulyBidAdapter.js +++ b/modules/unrulyBidAdapter.js @@ -80,7 +80,7 @@ export const adapter = { bidRequests: validBidRequests, bidderRequest }; - const options = { contentType: 'application/json' }; + const options = { contentType: 'text/plain' }; return { url, diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js index 2cea833be7e..b27fdc5c78b 100644 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -107,10 +107,10 @@ describe('UnrulyAdapter', function () { const mockBidRequests = ['mockBid']; expect(adapter.buildRequests(mockBidRequests).method).to.equal('POST'); }); - it('should ensure contentType is `application/json`', function () { + it('should ensure contentType is `text/plain`', function () { const mockBidRequests = ['mockBid']; expect(adapter.buildRequests(mockBidRequests).options).to.deep.equal({ - contentType: 'application/json' + contentType: 'text/plain' }); }); it('should return a server request with valid payload', function () { From 6331c74dfc48ec2661026b124bcaefddace0aa12 Mon Sep 17 00:00:00 2001 From: Michael Callari Date: Mon, 4 Feb 2019 11:18:41 -0500 Subject: [PATCH 0984/1594] Remove cache buster and put call behind CloudFront #3495 (#3499) --- modules/optimeraBidAdapter.js | 7 +++---- modules/optimeraBidAdapter.md | 4 ++-- test/spec/modules/optimeraBidAdapter_spec.js | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/modules/optimeraBidAdapter.js b/modules/optimeraBidAdapter.js index 3e453bff6da..1152cff751a 100644 --- a/modules/optimeraBidAdapter.js +++ b/modules/optimeraBidAdapter.js @@ -1,6 +1,7 @@ -import {registerBidder} from '../src/adapters/bidderFactory'; +import { registerBidder } from 'src/adapters/bidderFactory'; + const BIDDER_CODE = 'optimera'; -const SCORES_BASE_URL = 'https://s3.amazonaws.com/optimera-client/'; +const SCORES_BASE_URL = 'http://dyv1bugovvq1g.cloudfront.net/'; export const spec = { code: BIDDER_CODE, @@ -29,7 +30,6 @@ export const spec = { buildRequests: function (validBidRequests) { let optimeraHost = window.location.host; let optimeraPathName = window.location.pathname; - let timestamp = Math.round(new Date().getTime() / 1000); if (typeof validBidRequests[0].params.clientID !== 'undefined') { let clientID = validBidRequests[0].params.clientID; let scoresURL = SCORES_BASE_URL + clientID + '/' + optimeraHost + optimeraPathName + '.js'; @@ -37,7 +37,6 @@ export const spec = { method: 'GET', url: scoresURL, payload: validBidRequests, - data: {'t': timestamp} }; } }, diff --git a/modules/optimeraBidAdapter.md b/modules/optimeraBidAdapter.md index 8fca42fdac0..84df1d1ad07 100644 --- a/modules/optimeraBidAdapter.md +++ b/modules/optimeraBidAdapter.md @@ -19,7 +19,7 @@ Module that adds ad placement visibility scores for DFP. { bidder: 'optimera', params: { - clientID: '0' + clientID: '9999' } }] },{ @@ -29,7 +29,7 @@ Module that adds ad placement visibility scores for DFP. { bidder: 'optimera', params: { - clientID: '0' + clientID: '9999' } }] }]; diff --git a/test/spec/modules/optimeraBidAdapter_spec.js b/test/spec/modules/optimeraBidAdapter_spec.js index ff5793b5040..d164c4dbb30 100644 --- a/test/spec/modules/optimeraBidAdapter_spec.js +++ b/test/spec/modules/optimeraBidAdapter_spec.js @@ -15,7 +15,7 @@ describe('OptimeraAdapter', function () { let bid = { 'bidder': 'optimera', 'params': { - 'clientID': '0' + 'clientID': '9999' }, 'adUnitCode': 'div-0', 'sizes': [[300, 250], [300, 600]], @@ -47,7 +47,6 @@ describe('OptimeraAdapter', function () { expect(request).to.exist; expect(request.method).to.equal('GET'); expect(request.payload).to.exist; - expect(request.data.t).to.exist; }); }) From 29dd87c3d67bb411968e6f929b1055e26e9fc9a0 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Mon, 4 Feb 2019 18:30:06 +0200 Subject: [PATCH 0985/1594] Gamoshi: Refactor GDPR consent (#3507) * Add support for multi-format ad units. Add favoredMediaType property to params. * Add tests for gdpr consent. * Add adId to outbids * Modify media type resolving * Refactor multi-format ad units handler. * Modify gdpr consent existence. Add viewdeos bidder code. --- modules/gamoshiBidAdapter.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 4ff304af867..307f2d8bc91 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -2,9 +2,10 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import {config} from '../src/config'; import {Renderer} from '../src/Renderer'; -import {BANNER, VIDEO} from "../src/mediaTypes"; +import {BANNER, VIDEO} from '../src/mediaTypes'; const ENDPOINTS = { + 'viewdeos': 'https://rtb.viewdeos.com', 'cleanmedia': 'https://bidder.cleanmediaads.com', 'gamoshi': 'https://rtb.gamoshi.io', 'gambid': 'https://rtb.gamoshi.io', @@ -42,7 +43,7 @@ export const helper = { export const spec = { code: 'gamoshi', - aliases: ['gambid', 'cleanmedia'], + aliases: ['gambid', 'cleanmedia', 'viewdeos'], supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { @@ -76,7 +77,9 @@ export const spec = { 'ext': {} }; - if (bidderRequest.gdprConsent) { + if (bidderRequest.gdprConsent && + bidderRequest.gdprConsent.consentString && + bidderRequest.gdprConsent.gdprApplies) { rtbBidRequest.ext.gdpr_consent = { consent_string: bidderRequest.gdprConsent.consentString, consent_required: bidderRequest.gdprConsent.gdprApplies @@ -96,7 +99,7 @@ export const spec = { params.favoredMediaType && this.supportedMediaTypes.includes(params.favoredMediaType); if ((!mediaTypes || mediaTypes.banner)) { - if (!hasFavoredMediaType || params.favoredMediaType === 'banner') { + if (!hasFavoredMediaType || params.favoredMediaType === BANNER) { const bannerImp = Object.assign({}, imp, { banner: { w: sizes.length ? sizes[0][0] : 300, @@ -110,7 +113,7 @@ export const spec = { } if (mediaTypes && mediaTypes.video) { - if (!hasFavoredMediaType || params.favoredMediaType === 'video') { + if (!hasFavoredMediaType || params.favoredMediaType === VIDEO) { const videoImp = Object.assign({}, imp, { video: { w: sizes.length ? sizes[0][0] : 300, From 880817a354cf6d1878eaa518c4cb3ec9b6feb7b8 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Mon, 4 Feb 2019 14:09:48 -0800 Subject: [PATCH 0986/1594] Update bid response object typedef (#3510) --- src/adapters/bidderFactory.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 13439e2a457..8d67fe098f9 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -97,6 +97,10 @@ import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSiz * @property {number} height The height of the ad, in pixels. * @property {number} width The width of the ad, in pixels. * + * @property {object} [native] Object for storing native creative assets + * @property {object} [video] Object for storing video response data + * @property {object} [meta] Object for storing bid meta data + * @property {string} [meta.iabSubCatId] The IAB subcategory ID * @property [Renderer] renderer A Renderer which can be used as a default for this bid, * if the publisher doesn't override it. This is only relevant for Outstream Video bids. */ From 6c196a0813d5bcffedcc6bb59ef5317fa16e76e5 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Tue, 5 Feb 2019 04:29:20 +0000 Subject: [PATCH 0987/1594] Audience Network: update ad HTML (#3488) --- modules/audienceNetworkBidAdapter.js | 35 +++++++++++++++---- .../modules/audienceNetworkBidAdapter_spec.js | 29 +++++++++++---- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index e3f4688981d..19c5be9d1de 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -18,7 +18,7 @@ const ttl = 600; const videoTtl = 3600; const platver = '$prebid.version$'; const platform = '241394079772386'; -const adapterver = '1.1.0'; +const adapterver = '1.2.0'; /** * Does this bid request contain valid parameters? @@ -138,11 +138,34 @@ const isTestmode = () => Boolean( const createAdHtml = (placementId, format, bidId) => { const nativeStyle = format === 'native' ? '' : ''; const nativeContainer = format === 'native' ? '
' : ''; - return `${nativeStyle}
- -${nativeContainer}
`; + return ` + ${nativeStyle} + +
+ + + ${nativeContainer} +
+ +`; }; /** diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index 2f7e5776354..dad05d07260 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -19,7 +19,7 @@ const placementId = 'test-placement-id'; const playerwidth = 320; const playerheight = 180; const requestId = 'test-request-id'; -const debug = 'adapterver=1.1.0&platform=241394079772386&platver=$prebid.version$&cb=test-uuid'; +const debug = 'adapterver=1.2.0&platform=241394079772386&platver=$prebid.version$&cb=test-uuid'; const pageUrl = encodeURIComponent(utils.getTopWindowUrl()); describe('AudienceNetwork adapter', function () { @@ -241,7 +241,9 @@ describe('AudienceNetwork adapter', function () { expect(bidResponse.width).to.equal(300); expect(bidResponse.height).to.equal(250); expect(bidResponse.ad) - .to.contain(`placementid:'${placementId}',format:'native',bidid:'test-bid-id'`, 'ad missing parameters') + .to.contain(`placementid: '${placementId}',`) + .and.to.contain(`format: 'native',`) + .and.to.contain(`bidid: 'test-bid-id',`) .and.to.contain('getElementsByTagName("style")', 'ad missing native styles') .and.to.contain('
', 'ad missing native container'); expect(bidResponse.ttl).to.equal(600); @@ -280,7 +282,9 @@ describe('AudienceNetwork adapter', function () { expect(bidResponse.width).to.equal(300); expect(bidResponse.height).to.equal(250); expect(bidResponse.ad) - .to.contain(`placementid:'${placementId}',format:'300x250',bidid:'test-bid-id'`, 'ad missing parameters') + .to.contain(`placementid: '${placementId}',`) + .and.to.contain(`format: '300x250',`) + .and.to.contain(`bidid: 'test-bid-id',`) .and.not.to.contain('getElementsByTagName("style")', 'ad should not contain native styles') .and.not.to.contain('
', 'ad should not contain native container'); expect(bidResponse.ttl).to.equal(600); @@ -361,7 +365,10 @@ describe('AudienceNetwork adapter', function () { expect(bidResponseNative.requestId).to.equal(requestId); expect(bidResponseNative.width).to.equal(300); expect(bidResponseNative.height).to.equal(250); - expect(bidResponseNative.ad).to.contain(`placementid:'${placementIdNative}',format:'native',bidid:'test-bid-id-native'`, 'ad missing parameters'); + expect(bidResponseNative.ad) + .to.contain(`placementid: '${placementIdNative}',`) + .and.to.contain(`format: 'native',`) + .and.to.contain(`bidid: 'test-bid-id-native',`); expect(bidResponseNative.ttl).to.equal(600); expect(bidResponseNative.creativeId).to.equal(placementIdNative); expect(bidResponseNative.netRevenue).to.equal(true); @@ -375,7 +382,10 @@ describe('AudienceNetwork adapter', function () { expect(bidResponseIab.requestId).to.equal(requestId); expect(bidResponseIab.width).to.equal(300); expect(bidResponseIab.height).to.equal(250); - expect(bidResponseIab.ad).to.contain(`placementid:'${placementIdIab}',format:'300x250',bidid:'test-bid-id-iab'`, 'ad missing parameters'); + expect(bidResponseIab.ad) + .to.contain(`placementid: '${placementIdIab}',`) + .and.to.contain(`format: '300x250',`) + .and.to.contain(`bidid: 'test-bid-id-iab',`); expect(bidResponseIab.ttl).to.equal(600); expect(bidResponseIab.creativeId).to.equal(placementIdIab); expect(bidResponseIab.netRevenue).to.equal(true); @@ -462,7 +472,10 @@ describe('AudienceNetwork adapter', function () { expect(bidResponseNative.ttl).to.equal(600); expect(bidResponseNative.width).to.equal(300); expect(bidResponseNative.height).to.equal(250); - expect(bidResponseNative.ad).to.contain(`placementid:'${nativePlacementId}',format:'native',bidid:'${nativeBidId}'`); + expect(bidResponseNative.ad) + .to.contain(`placementid: '${nativePlacementId}',`) + .and.to.contain(`format: 'native',`) + .and.to.contain(`bidid: '${nativeBidId}',`); }); it('mixture of valid native bid and error in response', function () { @@ -490,7 +503,9 @@ describe('AudienceNetwork adapter', function () { expect(bidResponse.width).to.equal(300); expect(bidResponse.height).to.equal(250); expect(bidResponse.ad) - .to.contain(`placementid:'${placementId}',format:'native',bidid:'test-bid-id'`, 'ad missing parameters') + .to.contain(`placementid: '${placementId}',`) + .and.to.contain(`format: 'native',`) + .and.to.contain(`bidid: 'test-bid-id',`) .and.to.contain('getElementsByTagName("style")', 'ad missing native styles') .and.to.contain('
', 'ad missing native container'); expect(bidResponse.ttl).to.equal(600); From 90afc1a18bcd32f7f91669cc504a04f120da668e Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Tue, 5 Feb 2019 07:02:53 -0500 Subject: [PATCH 0988/1594] Fix issue where the ${AUCTION_PRICE} macro was not being replaced in secure creatives (#3493) * fixed issue where the creative AUCTION_PRICE macro was not being replaced in secure creatives. * fixed issue where the creative AUCTION_PRICE macro was not being replaced in secure creatives. * removed cpm from postMessage payload] * removed unneeded cpm deconstruct * pulling cpm from the adObject * also macro repalce adUrl * added unit test for secureCreative sendAdToCreative * added more realistic mock values --- src/secureCreatives.js | 12 +++---- test/spec/unit/secureCreatives_spec.js | 45 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 test/spec/unit/secureCreatives_spec.js diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 67579bae76c..32ad27a0496 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -6,7 +6,7 @@ import events from './events'; import { fireNativeTrackers } from './native'; import { EVENTS } from './constants'; -import { isSlotMatchingAdUnitCode, logWarn } from './utils'; +import { isSlotMatchingAdUnitCode, logWarn, replaceAuctionPrice } from './utils'; import { auctionManager } from './auctionManager'; import find from 'core-js/library/fn/array/find'; import { isRendererRequired, executeRenderer } from './Renderer'; @@ -32,7 +32,7 @@ function receiveMessage(ev) { }); if (data.message === 'Prebid Request') { - sendAdToCreative(adObject, data.adServerDomain, ev.source); + _sendAdToCreative(adObject, data.adServerDomain, ev.source); // save winning bids auctionManager.addWinningBid(adObject); @@ -53,8 +53,8 @@ function receiveMessage(ev) { } } -function sendAdToCreative(adObject, remoteDomain, source) { - const { adId, ad, adUrl, width, height, renderer } = adObject; +export function _sendAdToCreative(adObject, remoteDomain, source) { + const { adId, ad, adUrl, width, height, renderer, cpm } = adObject; // rendering for outstream safeframe if (isRendererRequired(renderer)) { executeRenderer(renderer, adObject); @@ -62,8 +62,8 @@ function sendAdToCreative(adObject, remoteDomain, source) { resizeRemoteCreative(adObject); source.postMessage(JSON.stringify({ message: 'Prebid Response', - ad, - adUrl, + ad: replaceAuctionPrice(ad, cpm), + adUrl: replaceAuctionPrice(adUrl, cpm), adId, width, height diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js new file mode 100644 index 00000000000..f0f26bf5653 --- /dev/null +++ b/test/spec/unit/secureCreatives_spec.js @@ -0,0 +1,45 @@ +import { + _sendAdToCreative +} from '../../../src/secureCreatives'; +import { expect } from 'chai'; +import * as utils from 'src/utils'; + +describe('secureCreatives', () => { + describe('_sendAdToCreative', () => { + beforeEach(function () { + sinon.stub(utils, 'logError'); + sinon.stub(utils, 'logWarn'); + }); + + afterEach(function () { + utils.logError.restore(); + utils.logWarn.restore(); + }); + it('should macro replace ${AUCTION_PRICE} with the winning bid for ad and adUrl', () => { + const oldVal = window.googletag; + const oldapntag = window.apntag; + window.apntag = null + window.googletag = null; + const mockAdObject = { + adId: 'someAdId', + ad: '', + adUrl: 'http://creative.prebid.org/${AUCTION_PRICE}', + width: 300, + height: 250, + renderer: null, + cpm: '1.00', + adUnitCode: 'some_dom_id' + }; + const remoteDomain = '*'; + const source = { + postMessage: sinon.stub() + }; + + _sendAdToCreative(mockAdObject, remoteDomain, source); + expect(JSON.parse(source.postMessage.args[0][0]).ad).to.equal(''); + expect(JSON.parse(source.postMessage.args[0][0]).adUrl).to.equal('http://creative.prebid.org/1.00'); + window.googletag = oldVal; + window.apntag = oldapntag; + }); + }); +}); From fbe766e537d46030adde4a16ad08b6ee343a0bab Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 5 Feb 2019 11:45:10 -0800 Subject: [PATCH 0989/1594] Rubicon: updating example to use mediaTypes (#3512) --- modules/rubiconBidAdapter.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.md b/modules/rubiconBidAdapter.md index b1871882a9a..d5beebee31b 100644 --- a/modules/rubiconBidAdapter.md +++ b/modules/rubiconBidAdapter.md @@ -19,7 +19,11 @@ globalsupport@rubiconproject.com for more information. var adUnits = [ { code: 'test-div', - sizes: [[300, 250]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, bids: [ { bidder: "rubicon", @@ -32,7 +36,11 @@ globalsupport@rubiconproject.com for more information. ] },{ code: 'test-div', - sizes: [[300, 50]], + mediaTypes: { + banner: { + sizes: [[300, 50]] + } + }, bids: [ { bidder: "rubicon", From 16ae06997722c25a58f3c1ba2b362d06a6542056 Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Wed, 6 Feb 2019 20:22:26 +0530 Subject: [PATCH 0990/1594] Onevideo adapter support for new params (#3503) * adding playback and hb=1 * export-updateSelectedFilters --- modules/oneVideoBidAdapter.js | 9 +++++++ modules/oneVideoBidAdapter.md | 4 ++- test/spec/modules/oneVideoBidAdapter_spec.js | 27 ++++++++++++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 4ebb3a4ea9e..818c31a84af 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -151,6 +151,9 @@ function getRequestData(bid, consentData) { h: bid.params.video.playerHeight, linearity: 1, protocols: bid.params.video.protocols || [2, 5] + }, + ext: { + hb: 1, } }], site: { @@ -181,6 +184,12 @@ function getRequestData(bid, consentData) { if (bid.params.video.position) { bidData.imp[0].video.pos = bid.params.video.position } + if (bid.params.video.playbackmethod) { + bidData.imp[0].video.playbackmethod = bid.params.video.playbackmethod + } + if (bid.params.video.placement) { + bidData.imp[0].ext.placement = bid.params.video.placement + } if (bid.params.site && bid.params.site.id) { bidData.site.id = bid.params.site.id } diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md index 96399221315..6e34d245c3e 100755 --- a/modules/oneVideoBidAdapter.md +++ b/modules/oneVideoBidAdapter.md @@ -31,7 +31,9 @@ Connects to One Video demand source to fetch bids. protocols: [2,5], api: [2], position: 1, - delivery: [2] + delivery: [2], + playbackmethod: [1,5], + placement: 123 }, site: { id: 1, diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index f67105751df..331a52c1ea0 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -21,7 +21,9 @@ describe('OneVideoBidAdapter', function () { protocols: [2, 5], api: [2], position: 1, - delivery: [2] + delivery: [2], + playbackmethod: [1, 5], + placement: 123 }, site: { id: 1, @@ -54,11 +56,30 @@ describe('OneVideoBidAdapter', function () { protocols: [2, 5], api: [2], position: 1, - delivery: [2] + delivery: [2], + playbackmethod: [1, 5], + placement: 123 } }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); + it('should return true when the "pubId" param is missing', function () { + bidRequest.params = { + video: { + playerWidth: 480, + playerHeight: 640, + mimes: ['video/mp4', 'application/javascript'], + protocols: [2, 5], + api: [2], + position: 1, + delivery: [2], + playbackmethod: [1, 5], + placement: 123 + }, + pubId: 'brxd' + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); it('should return false when no bid params are passed', function () { bidRequest.params = {}; @@ -82,8 +103,10 @@ describe('OneVideoBidAdapter', function () { const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; const [ width, height ] = bidRequest.sizes; + const placement = bidRequest.params.video.placement; expect(data.imp[0].video.w).to.equal(width); expect(data.imp[0].video.h).to.equal(height); + expect(data.imp[0].ext.placement).to.equal(placement); expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); }); From 9c3eaeae306add49671fa96da3c87a712cd1be9a Mon Sep 17 00:00:00 2001 From: Mikhail Ivanchenko Date: Wed, 6 Feb 2019 19:00:38 +0300 Subject: [PATCH 0991/1594] filter passbacks (#3516) --- modules/adliveBidAdapter.js | 24 ++++++++++++---------- test/spec/modules/adliveBidAdapter_spec.js | 11 +--------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/modules/adliveBidAdapter.js b/modules/adliveBidAdapter.js index 26f9148d484..cb3d9579832 100644 --- a/modules/adliveBidAdapter.js +++ b/modules/adliveBidAdapter.js @@ -44,17 +44,19 @@ export const spec = { const bidResponses = []; utils._each(response, function(bidResponse) { - bidResponses.push({ - requestId: bidRequest.bidId, - cpm: bidResponse.is_passback ? 0 : bidResponse.price, - width: bidResponse.size[0], - height: bidResponse.size[1], - creativeId: bidResponse.hash, - currency: CURRENCY, - netRevenue: false, - ttl: TIME_TO_LIVE, - ad: bidResponse.content - }); + if (!bidResponse.is_passback) { + bidResponses.push({ + requestId: bidRequest.bidId, + cpm: bidResponse.price, + width: bidResponse.size[0], + height: bidResponse.size[1], + creativeId: bidResponse.hash, + currency: CURRENCY, + netRevenue: false, + ttl: TIME_TO_LIVE, + ad: bidResponse.content + }); + } }); return bidResponses; diff --git a/test/spec/modules/adliveBidAdapter_spec.js b/test/spec/modules/adliveBidAdapter_spec.js index 5d9cd753ff1..0048fc028b8 100644 --- a/test/spec/modules/adliveBidAdapter_spec.js +++ b/test/spec/modules/adliveBidAdapter_spec.js @@ -73,15 +73,6 @@ describe('adliveBidAdapterTests', function() { }; let bids = spec.interpretResponse(serverResponse, bidRequestData.bids[0]); - expect(bids).to.have.lengthOf(1); - - let bid = bids[0]; - - expect(bid.creativeId).to.equal('1e100887dd614b0909bf6c49ba7f69fdd1360437'); - expect(bid.ad).to.equal('Ad html passback'); - expect(bid.cpm).to.equal(0); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.currency).to.equal('USD'); + expect(bids).to.have.lengthOf(0); }); }); From cf5f5a7e09ab030daf1c69287f5680be3ba63841 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 6 Feb 2019 11:06:56 -0500 Subject: [PATCH 0992/1594] add adpod to mediaTypes (#3523) * add adpod to mediaTypes * add new typedef --- src/mediaTypes.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mediaTypes.js b/src/mediaTypes.js index 7a40030e4e2..eea286f7af5 100644 --- a/src/mediaTypes.js +++ b/src/mediaTypes.js @@ -7,6 +7,7 @@ /** * @typedef {('native'|'video'|'banner')} MediaType + * @typedef {('adpod')} VideoContext */ /** @type MediaType */ @@ -15,3 +16,5 @@ export const NATIVE = 'native'; export const VIDEO = 'video'; /** @type MediaType */ export const BANNER = 'banner'; +/** @type VideoContext */ +export const ADPOD = 'adpod'; From c2ef82b7fcad73fb84eac122655fcc37bab0aded Mon Sep 17 00:00:00 2001 From: bjorn-lw <32431346+bjorn-lw@users.noreply.github.com> Date: Wed, 6 Feb 2019 17:10:59 +0100 Subject: [PATCH 0993/1594] Added support for Publisher Common ID Module (#3458) * Livewrapped bid and analytics adapter * Fixed some tests for browser compatibility * Fixed some tests for browser compatibility * Changed analytics adapter code name * Fix double quote in debug message * modified how gdpr is being passed * Added support for Publisher Common ID Module --- modules/livewrappedBidAdapter.js | 15 +++-- .../modules/livewrappedBidAdapter_spec.js | 61 +++++++++++++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/modules/livewrappedBidAdapter.js b/modules/livewrappedBidAdapter.js index 7affdb34dd9..69a89421a32 100644 --- a/modules/livewrappedBidAdapter.js +++ b/modules/livewrappedBidAdapter.js @@ -40,15 +40,16 @@ export const spec = { */ buildRequests: function(bidRequests, bidderRequest) { const userId = find(bidRequests, hasUserId); + const pubcid = find(bidRequests, hasPubcid); const publisherId = find(bidRequests, hasPublisherId); const auctionId = find(bidRequests, hasAuctionId); let bidUrl = find(bidRequests, hasBidUrl); let url = find(bidRequests, hasUrl); let test = find(bidRequests, hasTestParam); - let seats = find(bidRequests, hasSeatsParam); - let deviceId = find(bidRequests, hasDeviceIdParam); - let ifa = find(bidRequests, hasIfaParam); - let tid = find(bidRequests, hasTidParam); + const seats = find(bidRequests, hasSeatsParam); + const deviceId = find(bidRequests, hasDeviceIdParam); + const ifa = find(bidRequests, hasIfaParam); + const tid = find(bidRequests, hasTidParam); bidUrl = bidUrl ? bidUrl.params.bidUrl : URL; url = url ? url.params.url : (config.getConfig('pageUrl') || utils.getTopWindowUrl()); test = test ? test.params.test : undefined; @@ -57,7 +58,7 @@ export const spec = { const payload = { auctionId: auctionId ? auctionId.auctionId : undefined, publisherId: publisherId ? publisherId.params.publisherId : undefined, - userId: userId ? userId.params.userId : undefined, + userId: userId ? userId.params.userId : (pubcid ? pubcid.crumbs.pubcid : undefined), url: url, test: test, seats: seats ? seats.params.seats : undefined, @@ -167,6 +168,10 @@ function hasTidParam(bid) { return !!bid.params.tid; } +function hasPubcid(bid) { + return !!bid.crumbs && !!bid.crumbs.pubcid; +} + function bidToAdRequest(bid) { return { adUnitId: bid.params.adUnitId, diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js index 072d374ac72..b12ff56c075 100644 --- a/test/spec/modules/livewrappedBidAdapter_spec.js +++ b/test/spec/modules/livewrappedBidAdapter_spec.js @@ -456,6 +456,67 @@ describe('Livewrapped adapter tests', function () { expect(data.url).to.equal('http://www.configurl.com'); }); + + it('should make use of pubcid if available', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + testbidRequest.bids[0].crumbs = {pubcid: 'pubcid 123'}; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('//lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'pubcid 123', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + cookieSupport: true, + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should make userId take precedence over pubcid', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + testbidRequest.bids[0].crumbs = {pubcid: 'pubcid 123'}; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + expect(result.url).to.equal('//lwadm.com/ad'); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + userId: 'user id', + url: 'http://www.domain.com', + seats: {'dsp': ['seat 1']}, + version: '1.1', + cookieSupport: true, + adRequests: [{ + adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37', + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); }); describe('interpretResponse', function () { From d8754c3ca1050fe389c9190cb378cb2b4cd99616 Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Thu, 7 Feb 2019 00:51:59 +0800 Subject: [PATCH 0994/1594] Fix requestId field (#3496) * Fix requestId field after the commit (https://github.com/prebid/Prebid.js/pull/3411/files), Rubicon is no more seeing event for Server side requests. This is due to the requestId not correctly set up as it should be the associatedBidRequest bidid not the bid response bid id. * Update index.js * Update prebidServerBidAdapter_spec.js --- modules/prebidServerBidAdapter/index.js | 4 ++-- test/spec/modules/prebidServerBidAdapter_spec.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 006349b773d..de352dc52b5 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -389,7 +389,7 @@ const LEGACY_PROTOCOL = { if (bidObj.deal_id) { bidObject.dealId = bidObj.deal_id; } - bidObject.requestId = bidObj.bid_id; + bidObject.requestId = bidRequest.bidId || bidRequest.bid_Id; bidObject.creativeId = bidObj.creative_id; // TODO: Remove when prebid-server returns ttl, currency and netRevenue @@ -576,7 +576,7 @@ const OPEN_RTB_PROTOCOL = { bidObject.width = bid.w; bidObject.height = bid.h; if (bid.dealid) { bidObject.dealId = bid.dealid; } - bidObject.requestId = bid.id; + bidObject.requestId = bidRequest.bidId || bidRequest.bid_Id; bidObject.creative_id = bid.crid; bidObject.creativeId = bid.crid; if (bid.burl) { bidObject.burl = bid.burl; } diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 6b4c206e683..881934babdd 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -844,6 +844,7 @@ describe('S2S Adapter', function () { expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); expect(response).to.have.property('adId', '123'); + expect(response).to.have.property('requestId', '123'); expect(response).to.not.have.property('videoCacheKey'); expect(response).to.have.property('cache_id', '7654321'); expect(response).to.have.property('cache_url', 'http://www.test.com/cache?uuid=7654321'); @@ -862,6 +863,7 @@ describe('S2S Adapter', function () { expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); expect(response).to.have.property('adId', '123'); + expect(response).to.have.property('requestId', '123'); expect(response).to.have.property('videoCacheKey', 'video_cache_id'); expect(response).to.have.property('cache_id', 'video_cache_id'); expect(response).to.have.property('cache_url', 'video_cache_url'); @@ -1015,6 +1017,7 @@ describe('S2S Adapter', function () { expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('bidderCode', 'appnexus'); expect(response).to.have.property('adId', '123'); + expect(response).to.have.property('requestId', '123'); expect(response).to.have.property('cpm', 0.5); }); @@ -1035,6 +1038,7 @@ describe('S2S Adapter', function () { expect(response).to.have.property('mediaType', 'video'); expect(response).to.have.property('bidderCode', 'appnexus'); expect(response).to.have.property('adId', '123'); + expect(response).to.have.property('requestId', '123'); expect(response).to.have.property('cpm', 10); }); From e73045731eeaaceda13e42712bd6a403e768e95b Mon Sep 17 00:00:00 2001 From: bretg Date: Wed, 6 Feb 2019 12:31:27 -0500 Subject: [PATCH 0995/1594] updated to reflect the weekly schedule --- RELEASE_SCHEDULE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index 611a98473ff..7b2c6244bd7 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -6,7 +6,7 @@ ## Release Schedule -We push a new release of Prebid.js every other week on Tuesday. During the adoption phase for 1.x, we are releasing updates for 1.x and 0.x at the same time. +We aim to push a new release of Prebid.js every week on Tuesday. While the releases will be available immediately for those using direct Git access, it will be about a week before the Prebid Org [Download Page](http://prebid.org/download.html) will be updated. @@ -128,7 +128,7 @@ Characteristics of a `GA` release: ## FAQs -**1. Is there flexibility in the 2-week schedule?** +**1. Is there flexibility in the schedule?** If a major bug is found in the current release, a maintenance patch will be done as soon as possible. From bdcd0c27c13ad1a19cd6a0ef15640be205b38f66 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 6 Feb 2019 13:10:22 -0500 Subject: [PATCH 0996/1594] Add support to pass custom key in Prebid cache request (#3437) * add support to pass custom key in PBC request * update logic to allow individual custom keys per bid --- src/videoCache.js | 10 ++++++++-- test/spec/videoCache_spec.js | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/videoCache.js b/src/videoCache.js index bc70397fc94..06847012a6e 100644 --- a/src/videoCache.js +++ b/src/videoCache.js @@ -60,11 +60,17 @@ function wrapURI(uri, impUrl) { */ function toStorageRequest(bid) { const vastValue = bid.vastXml ? bid.vastXml : wrapURI(bid.vastUrl, bid.vastImpUrl); - return { + let payload = { type: 'xml', value: vastValue, ttlseconds: Number(bid.ttl) }; + + if (typeof bid.customCacheKey === 'string' && bid.customCacheKey !== '') { + payload.key = bid.customCacheKey; + } + + return payload; } /** @@ -114,7 +120,7 @@ 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 - * the data has been stored in the cache. + * the data has been stored in the cache. */ export function store(bids, done) { const requestData = { diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index 163cb326740..fc4924187e8 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -122,6 +122,43 @@ describe('The video cache', function () { assertRequestMade({ vastXml: vastXml, ttl: 25 }, vastXml); }); + it('should make the expected request when store() is called while supplying a custom key param', function () { + const customKey1 = 'keyword_abc_123'; + const customKey2 = 'other_xyz_789'; + const vastXml1 = 'test1'; + const vastXml2 = 'test2'; + + const bids = [{ + vastXml: vastXml1, + ttl: 25, + customCacheKey: customKey1 + }, { + vastXml: vastXml2, + ttl: 25, + customCacheKey: customKey2 + }]; + + store(bids, function () { }); + const request = requests[0]; + request.method.should.equal('POST'); + request.url.should.equal('https://prebid.adnxs.com/pbc/v1/cache'); + request.requestHeaders['Content-Type'].should.equal('text/plain;charset=utf-8'); + let payload = { + puts: [{ + type: 'xml', + value: vastXml1, + ttlseconds: 25, + key: customKey1 + }, { + type: 'xml', + value: vastXml2, + ttlseconds: 25, + key: customKey2 + }] + }; + JSON.parse(request.requestBody).should.deep.equal(payload); + }); + function assertRequestMade(bid, expectedValue) { store([bid], function() { }); From 8c210bcbea3c71fa29d20c872740755acd245032 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 6 Feb 2019 13:42:30 -0500 Subject: [PATCH 0997/1594] generate bid.adId uniquely instead of using bidRequest.bidId (#3440) * generate bid.adId uniquely * remove stray debugger * update adId reference in currency file --- modules/currency.js | 2 +- src/auction.js | 2 +- src/bidfactory.js | 4 ++-- src/native.js | 2 +- src/utils.js | 3 +++ src/video.js | 2 +- test/spec/auctionmanager_spec.js | 6 +++--- test/spec/modules/prebidServerBidAdapter_spec.js | 8 ++------ test/spec/modules/serverbidServerBidAdapter_spec.js | 8 ++++---- test/spec/native_spec.js | 9 ++++++--- test/spec/unit/core/bidderFactory_spec.js | 8 ++++---- test/spec/video_spec.js | 11 ++++++----- 12 files changed, 34 insertions(+), 31 deletions(-) diff --git a/modules/currency.js b/modules/currency.js index 350b9dcb3f4..700157acdd3 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -222,7 +222,7 @@ function wrapFunction(fn, context, params) { utils.logWarn('Returning NO_BID, getCurrencyConversion threw error: ', e); params[1] = createBid(STATUS.NO_BID, { bidder: bid.bidderCode || bid.bidder, - bidId: bid.adId + bidId: bid.requestId }); } } diff --git a/src/auction.js b/src/auction.js index d51de45f2ab..4866a4d3c26 100644 --- a/src/auction.js +++ b/src/auction.js @@ -396,7 +396,7 @@ function addBidToAuction(auctionInstance, bidResponse) { function tryAddVideoBid(auctionInstance, bidResponse, bidRequests, afterBidAdded) { let addBid = true; - const bidRequest = getBidRequest(bidResponse.adId, [bidRequests]); + const bidRequest = getBidRequest(bidResponse.requestId, [bidRequests]); const videoMediaType = bidRequest && deepAccess(bidRequest, 'mediaTypes.video'); const context = videoMediaType && deepAccess(videoMediaType, 'context'); diff --git a/src/bidfactory.js b/src/bidfactory.js index 86c6557216d..8701184c799 100644 --- a/src/bidfactory.js +++ b/src/bidfactory.js @@ -15,7 +15,6 @@ var utils = require('./utils.js'); priceKeyString; */ function Bid(statusCode, bidRequest) { - var _bidId = (bidRequest && bidRequest.bidId) || utils.getUniqueIdentifierStr(); var _bidSrc = (bidRequest && bidRequest.src) || 'client'; var _statusCode = statusCode || 0; @@ -23,7 +22,8 @@ function Bid(statusCode, bidRequest) { this.width = 0; this.height = 0; this.statusMessage = _getStatus(); - this.adId = _bidId; + this.adId = utils.getUniqueIdentifierStr(); + this.requestId = bidRequest && bidRequest.bidId; this.mediaType = 'banner'; this.source = _bidSrc; diff --git a/src/native.js b/src/native.js index c9d274ddccd..a5609739832 100644 --- a/src/native.js +++ b/src/native.js @@ -69,7 +69,7 @@ export const hasNonNativeBidder = adUnit => * @return {Boolean} If object is valid */ export function nativeBidIsValid(bid, bidRequests) { - const bidRequest = getBidRequest(bid.adId, bidRequests); + const bidRequest = getBidRequest(bid.requestId, bidRequests); if (!bidRequest) { return false; } // all native bid responses must define a landing page url diff --git a/src/utils.js b/src/utils.js index f21c555bbbb..fd710bc829e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -750,6 +750,9 @@ export function flatten(a, b) { } export function getBidRequest(id, bidderRequests) { + if (!id) { + return; + } let bidRequest; bidderRequests.some(bidderRequest => { let result = find(bidderRequest.bids, bid => ['bidId', 'adId', 'bid_id'].some(type => bid[type] === id)); diff --git a/src/video.js b/src/video.js index 2c1d0ec1569..b46bdf1e0df 100644 --- a/src/video.js +++ b/src/video.js @@ -30,7 +30,7 @@ export const hasNonVideoBidder = adUnit => * @return {Boolean} If object is valid */ export function isValidVideoBid(bid, bidRequests) { - const bidRequest = getBidRequest(bid.adId, bidRequests); + const bidRequest = getBidRequest(bid.requestId, bidRequests); const videoMediaType = bidRequest && deepAccess(bidRequest, 'mediaTypes.video'); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 232ed04da25..9110e1fcdc0 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -768,13 +768,13 @@ describe('auctionmanager.js', function () { auctionModule.newAuction.restore(); }); - it('should not alter bid adID', function () { + it('should not alter bid requestID', function () { auction.callBids(); const addedBid2 = auction.getBidsReceived().pop(); - assert.equal(addedBid2.adId, bids1[0].requestId); + assert.equal(addedBid2.requestId, bids1[0].requestId); const addedBid1 = auction.getBidsReceived().pop(); - assert.equal(addedBid1.adId, bids[0].requestId); + assert.equal(addedBid1.requestId, bids[0].requestId); }); it('should not add banner bids that have no width or height', function () { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 881934babdd..8d61f21c731 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -843,7 +843,6 @@ describe('S2S Adapter', function () { const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); - expect(response).to.have.property('adId', '123'); expect(response).to.have.property('requestId', '123'); expect(response).to.not.have.property('videoCacheKey'); expect(response).to.have.property('cache_id', '7654321'); @@ -862,7 +861,6 @@ describe('S2S Adapter', function () { const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); - expect(response).to.have.property('adId', '123'); expect(response).to.have.property('requestId', '123'); expect(response).to.have.property('videoCacheKey', 'video_cache_id'); expect(response).to.have.property('cache_id', 'video_cache_id'); @@ -915,7 +913,7 @@ describe('S2S Adapter', function () { expect(addBidResponse.firstCall.args[0]).to.equal('div-gpt-ad-1460505748561-0'); - expect(addBidResponse.firstCall.args[1]).to.have.property('adId', '123'); + expect(addBidResponse.firstCall.args[1]).to.have.property('requestId', '123'); expect(addBidResponse.firstCall.args[1]) .to.have.property('statusMessage', 'Bid available'); @@ -994,7 +992,7 @@ describe('S2S Adapter', function () { expect(response).to.have.property('source', 's2s'); const bid_request_passed = addBidResponse.firstCall.args[1]; - expect(bid_request_passed).to.have.property('adId', '123'); + expect(bid_request_passed).to.have.property('requestId', '123'); }); it('handles OpenRTB responses and call BIDDER_DONE', function () { @@ -1016,7 +1014,6 @@ describe('S2S Adapter', function () { const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('bidderCode', 'appnexus'); - expect(response).to.have.property('adId', '123'); expect(response).to.have.property('requestId', '123'); expect(response).to.have.property('cpm', 0.5); }); @@ -1037,7 +1034,6 @@ describe('S2S Adapter', function () { expect(response).to.have.property('vastXml', RESPONSE_OPENRTB_VIDEO.seatbid[0].bid[0].adm); expect(response).to.have.property('mediaType', 'video'); expect(response).to.have.property('bidderCode', 'appnexus'); - expect(response).to.have.property('adId', '123'); expect(response).to.have.property('requestId', '123'); expect(response).to.have.property('cpm', 10); }); diff --git a/test/spec/modules/serverbidServerBidAdapter_spec.js b/test/spec/modules/serverbidServerBidAdapter_spec.js index 7c428647f62..1190648bb84 100644 --- a/test/spec/modules/serverbidServerBidAdapter_spec.js +++ b/test/spec/modules/serverbidServerBidAdapter_spec.js @@ -243,7 +243,7 @@ describe('ServerBid S2S Adapter', function () { const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); - expect(response).to.have.property('adId', '123'); + expect(response).to.have.property('requestId', '123'); }); it('registers no-bid response when ad unit not set', function () { @@ -261,7 +261,7 @@ describe('ServerBid S2S Adapter', function () { expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); const bid_request_passed = addBidResponse.firstCall.args[1]; - expect(bid_request_passed).to.have.property('adId', '123'); + expect(bid_request_passed).to.have.property('requestId', '123'); }); it('registers no-bid response when ad unit is set', function () { @@ -291,8 +291,8 @@ describe('ServerBid S2S Adapter', function () { expect(addBidResponse.firstCall.args[0]).to.equal('div-gpt-ad-1460505748561-0'); expect(addBidResponse.secondCall.args[0]).to.equal('div-gpt-ad-1460505748561-1'); - expect(addBidResponse.firstCall.args[1]).to.have.property('adId', '123'); - expect(addBidResponse.secondCall.args[1]).to.have.property('adId', '101111'); + expect(addBidResponse.firstCall.args[1]).to.have.property('requestId', '123'); + expect(addBidResponse.secondCall.args[1]).to.have.property('requestId', '101111'); expect(addBidResponse.firstCall.args[1]) .to.have.property('statusMessage', 'Bid available'); diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 68653808c06..3a016145fd2 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -102,7 +102,8 @@ describe('validate native', function () { }]; let validBid = { - adId: 'test_bid_id', + adId: 'abc123', + requestId: 'test_bid_id', adUnitCode: '123/prebid_native_adunit', bidder: 'test_bidder', native: { @@ -126,7 +127,8 @@ describe('validate native', function () { }; let noIconDimBid = { - adId: 'test_bid_id', + adId: 'abc234', + requestId: 'test_bid_id', adUnitCode: '123/prebid_native_adunit', bidder: 'test_bidder', native: { @@ -150,7 +152,8 @@ describe('validate native', function () { }; let noImgDimBid = { - adId: 'test_bid_id', + adId: 'abc345', + requestId: 'test_bid_id', adUnitCode: '123/prebid_native_adunit', bidder: 'test_bidder', native: { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 5149bbd38a6..b82a6b65c99 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -639,7 +639,7 @@ describe('validate bid response: ', function () { it('should add native bids that do have required assets', function () { let bidRequest = { bids: [{ - bidId: 1, + bidId: '1', auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { @@ -676,7 +676,7 @@ describe('validate bid response: ', function () { it('should not add native bids that do not have required assets', function () { let bidRequest = { bids: [{ - bidId: 1, + bidId: '1', auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { @@ -712,7 +712,7 @@ describe('validate bid response: ', function () { it('should add bid when renderer is present on outstream bids', function () { let bidRequest = { bids: [{ - bidId: 1, + bidId: '1', auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { @@ -747,7 +747,7 @@ describe('validate bid response: ', function () { let bidRequest = { bids: [{ bidder: CODE, - bidId: 1, + bidId: '1', auctionId: 'first-bid-id', adUnitCode: 'mock/placement', params: { diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js index 3d6ed04ffae..dc6c11a7491 100644 --- a/test/spec/video_spec.js +++ b/test/spec/video_spec.js @@ -3,8 +3,9 @@ import { isValidVideoBid } from 'src/video'; describe('video.js', function () { it('validates valid instream bids', function () { const bid = { - adId: '123abc', - vastUrl: 'http://www.example.com/vastUrl' + adId: '456xyz', + vastUrl: 'http://www.example.com/vastUrl', + requestId: '123abc' }; const bidRequests = [{ bids: [{ @@ -21,7 +22,7 @@ describe('video.js', function () { it('catches invalid instream bids', function () { const bid = { - adId: '123abc' + requestId: '123abc' }; const bidRequests = [{ bids: [{ @@ -51,7 +52,7 @@ describe('video.js', function () { it('validates valid outstream bids', function () { const bid = { - adId: '123abc', + requestId: '123abc', renderer: { url: 'render.url', render: () => true, @@ -72,7 +73,7 @@ describe('video.js', function () { it('catches invalid outstream bids', function () { const bid = { - adId: '123abc' + requestId: '123abc' }; const bidRequests = [{ bids: [{ From 0ec997078c355fe091cffb6b840cb1b192d9a9ac Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 6 Feb 2019 14:01:21 -0500 Subject: [PATCH 0998/1594] create some hooks and modify adServerManager function (#3438) * create hooks and modify adservermanager function * remove comment * modify the import path for hook file * move checkAdUnitSetup and refactor video.js hook * update hook code to use new API * change hooks to use sync type * add adpod mediatype and rename native variable * remove unused import from test file * remove adpod reference in utils to avoid merge conflict --- src/adServerManager.js | 12 +- src/adapterManager.js | 62 ------ src/auction.js | 46 ++-- src/prebid.js | 60 ++++- src/utils.js | 4 + src/video.js | 7 +- test/spec/unit/adServerManager_spec.js | 15 +- test/spec/unit/core/adapterManager_spec.js | 209 +---------------- test/spec/unit/pbjs_api_spec.js | 246 ++++++++++++++++++++- 9 files changed, 363 insertions(+), 298 deletions(-) diff --git a/src/adServerManager.js b/src/adServerManager.js index a8340431000..11ce087903d 100644 --- a/src/adServerManager.js +++ b/src/adServerManager.js @@ -46,9 +46,11 @@ const prebid = getGlobal(); export function registerVideoSupport(name, videoSupport) { prebid.adServers = prebid.adServers || { }; prebid.adServers[name] = prebid.adServers[name] || { }; - if (prebid.adServers[name].buildVideoUrl) { - logWarn(`Multiple calls to registerVideoSupport for AdServer ${name}. Expect surprising behavior.`); - return; - } - prebid.adServers[name].buildVideoUrl = videoSupport.buildVideoUrl; + Object.keys(videoSupport).forEach((key) => { + if (prebid.adServers[name][key]) { + logWarn(`Attempting to add an already registered function property ${key} for AdServer ${name}.`); + return; + } + prebid.adServers[name][key] = videoSupport[key]; + }); } diff --git a/src/adapterManager.js b/src/adapterManager.js index b0cbe54195f..4b2cf1dc20a 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -162,8 +162,6 @@ export let gdprDataHandler = { adapterManager.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, labels) { let bidRequests = []; - adUnits = checkBidRequestSizes(adUnits); - let bidderCodes = getBidderCodes(adUnits); if (config.getConfig('bidderSequence') === RANDOM) { bidderCodes = shuffle(bidderCodes); @@ -254,66 +252,6 @@ adapterManager.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTi return bidRequests; }; -export function checkBidRequestSizes(adUnits) { - function isArrayOfNums(val) { - return Array.isArray(val) && val.length === 2 && utils.isInteger(val[0]) && utils.isInteger(val[1]); - } - - adUnits.forEach((adUnit) => { - const mediaTypes = adUnit.mediaTypes; - const normalizedSize = utils.getAdUnitSizes(adUnit); - - if (mediaTypes && mediaTypes.banner) { - const banner = mediaTypes.banner; - if (banner.sizes) { - // make sure we always send [[h,w]] format - banner.sizes = normalizedSize; - adUnit.sizes = normalizedSize; - } else { - utils.logError('Detected a mediaTypes.banner object did not include sizes. This is a required field for the mediaTypes.banner object. Removing invalid mediaTypes.banner object from request.'); - delete adUnit.mediaTypes.banner; - } - } else if (adUnit.sizes) { - utils.logWarn('Usage of adUnits.sizes will eventually be deprecated. Please define size dimensions within the corresponding area of the mediaTypes. (eg mediaTypes.banner.sizes).'); - adUnit.sizes = normalizedSize; - } - - if (mediaTypes && mediaTypes.video) { - const video = mediaTypes.video; - if (video.playerSize) { - if (Array.isArray(video.playerSize) && video.playerSize.length === 1 && video.playerSize.every(isArrayOfNums)) { - adUnit.sizes = video.playerSize; - } else if (isArrayOfNums(video.playerSize)) { - let newPlayerSize = []; - newPlayerSize.push(video.playerSize); - utils.logInfo(`Transforming video.playerSize from ${video.playerSize} to ${newPlayerSize} so it's in the proper format.`); - adUnit.sizes = video.playerSize = newPlayerSize; - } else { - 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 adUnit.mediaTypes.video.playerSize; - } - } - } - - if (mediaTypes && mediaTypes.native) { - const native = mediaTypes.native; - if (native.image && native.image.sizes && !Array.isArray(native.image.sizes)) { - utils.logError('Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request.'); - delete adUnit.mediaTypes.native.image.sizes; - } - if (native.image && native.image.aspect_ratios && !Array.isArray(native.image.aspect_ratios)) { - 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 adUnit.mediaTypes.native.image.aspect_ratios; - } - if (native.icon && native.icon.sizes && !Array.isArray(native.icon.sizes)) { - utils.logError('Please use an array of sizes for native.icon.sizes field. Removing invalid mediaTypes.native.icon.sizes property from request.'); - delete adUnit.mediaTypes.native.icon.sizes; - } - } - }); - return adUnits; -} - adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbacks, requestBidsTimeout) => { if (!bidRequests.length) { utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); diff --git a/src/auction.js b/src/auction.js index 4866a4d3c26..fc8c42023f7 100644 --- a/src/auction.js +++ b/src/auction.js @@ -378,14 +378,14 @@ export function auctionCallbacks(auctionDone, auctionInstance) { } } -function doCallbacksIfTimedout(auctionInstance, bidResponse) { +export function doCallbacksIfTimedout(auctionInstance, bidResponse) { if (bidResponse.timeToRespond > auctionInstance.getTimeout() + config.getConfig('timeoutBuffer')) { auctionInstance.executeCallback(true); } } // Add a bid to the auction. -function addBidToAuction(auctionInstance, bidResponse) { +export function addBidToAuction(auctionInstance, bidResponse) { events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bidResponse); auctionInstance.addBidReceived(bidResponse); @@ -396,28 +396,15 @@ function addBidToAuction(auctionInstance, bidResponse) { function tryAddVideoBid(auctionInstance, bidResponse, bidRequests, afterBidAdded) { let addBid = true; - const bidRequest = getBidRequest(bidResponse.requestId, [bidRequests]); + const bidderRequest = getBidRequest(bidResponse.requestId, [bidRequests]); const videoMediaType = - bidRequest && deepAccess(bidRequest, 'mediaTypes.video'); + bidderRequest && deepAccess(bidderRequest, 'mediaTypes.video'); const context = videoMediaType && deepAccess(videoMediaType, 'context'); if (config.getConfig('cache.url') && context !== OUTSTREAM) { if (!bidResponse.videoCacheKey) { addBid = false; - store([bidResponse], function (error, cacheIds) { - if (error) { - utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); - - doCallbacksIfTimedout(auctionInstance, bidResponse); - } else { - bidResponse.videoCacheKey = cacheIds[0].uuid; - if (!bidResponse.vastUrl) { - bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); - } - addBidToAuction(auctionInstance, bidResponse); - afterBidAdded(); - } - }); + callPrebidCache(auctionInstance, bidResponse, afterBidAdded, bidderRequest); } else if (!bidResponse.vastUrl) { utils.logError('videoCacheKey specified but not required vastUrl for video bid'); addBid = false; @@ -429,6 +416,29 @@ function tryAddVideoBid(auctionInstance, bidResponse, bidRequests, afterBidAdded } } +const callPrebidCache = hook('async', function(auctionInstance, bidResponse, afterBidAdded, bidderRequest) { + store([bidResponse], function (error, cacheIds) { + if (error) { + utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); + + doCallbacksIfTimedout(auctionInstance, bidResponse); + } else { + if (cacheIds[0].uuid === '') { + 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 { + bidResponse.videoCacheKey = cacheIds[0].uuid; + if (!bidResponse.vastUrl) { + bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); + } + addBidToAuction(auctionInstance, bidResponse); + afterBidAdded(); + } + } + }); +}, '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, bidderRequest, auctionId}) { diff --git a/src/prebid.js b/src/prebid.js index f94561cc874..92f6d819ecf 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -1,7 +1,7 @@ /** @module pbjs */ import { getGlobal } from './prebidGlobal'; -import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId, getLatestHighestCpmBid } from './utils'; +import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId, getLatestHighestCpmBid, isArrayOfNums } from './utils'; import { listenMessagesFromCreative } from './secureCreatives'; import { userSync } from './userSync.js'; import { loadScript } from './adloader'; @@ -69,6 +69,62 @@ function setRenderSize(doc, width, height) { } } +const checkAdUnitSetup = hook('sync', function (adUnits) { + adUnits.forEach((adUnit) => { + const mediaTypes = adUnit.mediaTypes; + const normalizedSize = utils.getAdUnitSizes(adUnit); + + if (mediaTypes && mediaTypes.banner) { + const banner = mediaTypes.banner; + if (banner.sizes) { + // make sure we always send [[h,w]] format + banner.sizes = normalizedSize; + adUnit.sizes = normalizedSize; + } else { + utils.logError('Detected a mediaTypes.banner object did not include sizes. This is a required field for the mediaTypes.banner object. Removing invalid mediaTypes.banner object from request.'); + delete adUnit.mediaTypes.banner; + } + } else if (adUnit.sizes) { + utils.logWarn('Usage of adUnits.sizes will eventually be deprecated. Please define size dimensions within the corresponding area of the mediaTypes. (eg mediaTypes.banner.sizes).'); + adUnit.sizes = normalizedSize; + } + + if (mediaTypes && mediaTypes.video) { + const video = mediaTypes.video; + if (video.playerSize) { + if (Array.isArray(video.playerSize) && video.playerSize.length === 1 && video.playerSize.every(plySize => isArrayOfNums(plySize, 2))) { + adUnit.sizes = video.playerSize; + } else if (isArrayOfNums(video.playerSize, 2)) { + let newPlayerSize = []; + newPlayerSize.push(video.playerSize); + utils.logInfo(`Transforming video.playerSize from [${video.playerSize}] to [[${newPlayerSize}]] so it's in the proper format.`); + adUnit.sizes = video.playerSize = newPlayerSize; + } else { + 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 adUnit.mediaTypes.video.playerSize; + } + } + } + + if (mediaTypes && mediaTypes.native) { + const nativeObj = mediaTypes.native; + if (nativeObj.image && nativeObj.image.sizes && !Array.isArray(nativeObj.image.sizes)) { + utils.logError('Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request.'); + delete adUnit.mediaTypes.native.image.sizes; + } + if (nativeObj.image && nativeObj.image.aspect_ratios && !Array.isArray(nativeObj.image.aspect_ratios)) { + 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 adUnit.mediaTypes.native.image.aspect_ratios; + } + if (nativeObj.icon && nativeObj.icon.sizes && !Array.isArray(nativeObj.icon.sizes)) { + utils.logError('Please use an array of sizes for native.icon.sizes field. Removing invalid mediaTypes.native.icon.sizes property from request.'); + delete adUnit.mediaTypes.native.icon.sizes; + } + } + }); + return adUnits; +}, 'checkAdUnitSetup'); + /// /////////////////////////////// // // // Start Public APIs // @@ -343,6 +399,8 @@ $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeo adUnitCodes = adUnits && adUnits.map(unit => unit.code); } + adUnits = checkAdUnitSetup(adUnits); + /* * for a given adunit which supports a set of mediaTypes * and a given bidder which supports a set of mediaTypes diff --git a/src/utils.js b/src/utils.js index fd710bc829e..2abad759e7a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1186,3 +1186,7 @@ export function convertTypes(types, params) { }); return params; } + +export function isArrayOfNums(val, size) { + return (isArray(val)) && ((size) ? val.length === size : true) && (val.every(v => isInteger(v))); +} diff --git a/src/video.js b/src/video.js index b46bdf1e0df..d5fcadd1f38 100644 --- a/src/video.js +++ b/src/video.js @@ -2,6 +2,7 @@ import adapterManager from './adapterManager'; import { getBidRequest, deepAccess, logError } from './utils'; import { config } from '../src/config'; import includes from 'core-js/library/fn/array/includes'; +import { hook } from './hook'; const VIDEO_MEDIA_TYPE = 'video'; export const OUTSTREAM = 'outstream'; @@ -38,6 +39,10 @@ export function isValidVideoBid(bid, bidRequests) { // if context not defined assume default 'instream' for video bids // instream bids require a vast url or vast xml content + return checkVideoBidSetup(bid, bidRequest, videoMediaType, context); +} + +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) { @@ -57,4 +62,4 @@ export function isValidVideoBid(bid, bidRequests) { } return true; -} +}, 'checkVideoBidSetup'); diff --git a/test/spec/unit/adServerManager_spec.js b/test/spec/unit/adServerManager_spec.js index 928050ee93c..4ae475ac013 100644 --- a/test/spec/unit/adServerManager_spec.js +++ b/test/spec/unit/adServerManager_spec.js @@ -5,7 +5,11 @@ import { registerVideoSupport } from 'src/adServerManager'; const prebid = getGlobal(); describe('The ad server manager', function () { - beforeEach(function () { + before(function () { + delete prebid.adServers; + }); + + afterEach(function () { delete prebid.adServers; }); @@ -27,4 +31,13 @@ describe('The ad server manager', function () { expect(prebid.adServers).to.have.property('dfp'); expect(prebid.adServers.dfp).to.have.property('buildVideoUrl', videoSupport); }); + + it('should support any custom named property in the public API', function () { + function getTestAdServerTargetingKeys() { }; + registerVideoSupport('testAdServer', { getTargetingKeys: getTestAdServerTargetingKeys }); + + expect(prebid).to.have.property('adServers'); + expect(prebid.adServers).to.have.property('testAdServer'); + expect(prebid.adServers.testAdServer).to.have.property('getTargetingKeys', getTestAdServerTargetingKeys); + }); }); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 31209bbf9c7..d6b699bd7da 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; import adapterManager, { - gdprDataHandler, - checkBidRequestSizes + gdprDataHandler } from 'src/adapterManager'; import { getAdUnits } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; @@ -1065,210 +1064,4 @@ describe('adapterManager tests', function () { }); }); }); - - describe('isValidBidRequest', function () { - describe('positive tests for validating bid request', function () { - beforeEach(function () { - sinon.stub(utils, 'logInfo'); - }); - - afterEach(function () { - utils.logInfo.restore(); - }); - - it('should maintain adUnit structure and adUnits.sizes is replaced', function () { - let fullAdUnit = [{ - sizes: [[300, 250], [300, 600]], - mediaTypes: { - banner: { - sizes: [[300, 250]] - }, - video: { - playerSize: [[640, 480]] - }, - native: { - image: { - sizes: [150, 150], - aspect_ratios: [140, 140] - }, - icon: { - sizes: [75, 75] - } - } - } - }]; - let result = checkBidRequestSizes(fullAdUnit); - expect(result[0].sizes).to.deep.equal([[640, 480]]); - expect(result[0].mediaTypes.video.playerSize).to.deep.equal([[640, 480]]); - expect(result[0].mediaTypes.native.image.sizes).to.deep.equal([150, 150]); - expect(result[0].mediaTypes.native.icon.sizes).to.deep.equal([75, 75]); - expect(result[0].mediaTypes.native.image.aspect_ratios).to.deep.equal([140, 140]); - - let noOptnlFieldAdUnit = [{ - sizes: [[300, 250], [300, 600]], - mediaTypes: { - banner: { - sizes: [[300, 250]] - }, - video: { - context: 'outstream' - }, - native: { - image: { - required: true - }, - icon: { - required: true - } - } - } - }]; - result = checkBidRequestSizes(noOptnlFieldAdUnit); - expect(result[0].sizes).to.deep.equal([[300, 250]]); - expect(result[0].mediaTypes.video).to.exist; - - let mixedAdUnit = [{ - sizes: [[300, 250], [300, 600]], - mediaTypes: { - video: { - context: 'outstream', - playerSize: [[400, 350]] - }, - native: { - image: { - aspect_ratios: [200, 150], - required: true - } - } - } - }]; - result = checkBidRequestSizes(mixedAdUnit); - expect(result[0].sizes).to.deep.equal([[400, 350]]); - expect(result[0].mediaTypes.video).to.exist; - - let altVideoPlayerSize = [{ - sizes: [[600, 600]], - mediaTypes: { - video: { - playerSize: [640, 480] - } - } - }]; - result = checkBidRequestSizes(altVideoPlayerSize); - expect(result[0].sizes).to.deep.equal([[640, 480]]); - expect(result[0].mediaTypes.video.playerSize).to.deep.equal([[640, 480]]); - expect(result[0].mediaTypes.video).to.exist; - sinon.assert.calledOnce(utils.logInfo); - }); - - it('should normalize adUnit.sizes and adUnit.mediaTypes.banner.sizes', function () { - let fullAdUnit = [{ - sizes: [300, 250], - mediaTypes: { - banner: { - sizes: [300, 250] - } - } - }]; - let result = checkBidRequestSizes(fullAdUnit); - expect(result[0].sizes).to.deep.equal([[300, 250]]); - expect(result[0].mediaTypes.banner.sizes).to.deep.equal([[300, 250]]); - }); - }); - - describe('negative tests for validating bid requests', function () { - beforeEach(function () { - sinon.stub(utils, 'logError'); - }); - - afterEach(function () { - utils.logError.restore(); - }); - - it('should throw error message and delete an object/property', function () { - let badBanner = [{ - sizes: [[300, 250], [300, 600]], - mediaTypes: { - banner: { - name: 'test' - } - } - }]; - let result = checkBidRequestSizes(badBanner); - expect(result[0].sizes).to.deep.equal([[300, 250], [300, 600]]); - expect(result[0].mediaTypes.banner).to.be.undefined; - sinon.assert.called(utils.logError); - - let badVideo1 = [{ - sizes: [[600, 600]], - mediaTypes: { - video: { - playerSize: ['600x400'] - } - } - }]; - result = checkBidRequestSizes(badVideo1); - expect(result[0].sizes).to.deep.equal([[600, 600]]); - expect(result[0].mediaTypes.video.playerSize).to.be.undefined; - expect(result[0].mediaTypes.video).to.exist; - sinon.assert.called(utils.logError); - - let badVideo2 = [{ - sizes: [[600, 600]], - mediaTypes: { - video: { - playerSize: [['300', '200']] - } - } - }]; - result = checkBidRequestSizes(badVideo2); - expect(result[0].sizes).to.deep.equal([[600, 600]]); - expect(result[0].mediaTypes.video.playerSize).to.be.undefined; - expect(result[0].mediaTypes.video).to.exist; - sinon.assert.called(utils.logError); - - let badNativeImgSize = [{ - mediaTypes: { - native: { - image: { - sizes: '300x250' - } - } - } - }]; - result = checkBidRequestSizes(badNativeImgSize); - expect(result[0].mediaTypes.native.image.sizes).to.be.undefined; - expect(result[0].mediaTypes.native.image).to.exist; - sinon.assert.called(utils.logError); - - let badNativeImgAspRat = [{ - mediaTypes: { - native: { - image: { - aspect_ratios: '300x250' - } - } - } - }]; - result = checkBidRequestSizes(badNativeImgAspRat); - expect(result[0].mediaTypes.native.image.aspect_ratios).to.be.undefined; - expect(result[0].mediaTypes.native.image).to.exist; - sinon.assert.called(utils.logError); - - let badNativeIcon = [{ - mediaTypes: { - native: { - icon: { - sizes: '300x250' - } - } - } - }]; - result = checkBidRequestSizes(badNativeIcon); - expect(result[0].mediaTypes.native.icon.sizes).to.be.undefined; - expect(result[0].mediaTypes.native.icon).to.exist; - sinon.assert.called(utils.logError); - }); - }); - }); }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 7ee8b27303e..22737745eb7 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1325,7 +1325,9 @@ describe('Unit: Prebid Module', function () { }); var adUnitsBackup; var auctionManagerStub; - let logMessageSpy + let logMessageSpy; + let logInfoSpy; + let logErrorSpy; let spec = { code: 'sampleBidder', @@ -1346,12 +1348,16 @@ describe('Unit: Prebid Module', function () { return auction; }); logMessageSpy = sinon.spy(utils, 'logMessage'); + logInfoSpy = sinon.spy(utils, 'logInfo'); + logErrorSpy = sinon.spy(utils, 'logError'); }); afterEach(function () { auction.getAdUnits = adUnitsBackup; auctionManager.createAuction.restore(); utils.logMessage.restore(); + utils.logInfo.restore(); + utils.logError.restore(); resetAuction(); }); @@ -1436,6 +1442,240 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.requestBids(requestObj); }).not.to.throw(); }); + + describe('checkAdUnitSetup', function() { + describe('positive tests for validating adUnits', function() { + it('should maintain adUnit structure and adUnit.sizes is replaced', function () { + let fullAdUnit = [{ + code: 'test1', + sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + playerSize: [[640, 480]] + }, + native: { + image: { + sizes: [150, 150], + aspect_ratios: [140, 140] + }, + icon: { + sizes: [75, 75] + } + } + }, + bids: [] + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: fullAdUnit + }); + expect(auctionArgs.adUnits[0].sizes).to.deep.equal([[640, 480]]); + expect(auctionArgs.adUnits[0].mediaTypes.video.playerSize).to.deep.equal([[640, 480]]); + expect(auctionArgs.adUnits[0].mediaTypes.native.image.sizes).to.deep.equal([150, 150]); + expect(auctionArgs.adUnits[0].mediaTypes.native.icon.sizes).to.deep.equal([75, 75]); + expect(auctionArgs.adUnits[0].mediaTypes.native.image.aspect_ratios).to.deep.equal([140, 140]); + + let noOptnlFieldAdUnit = [{ + code: 'test2', + bids: [], + sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + context: 'outstream' + }, + native: { + image: { + required: true + }, + icon: { + required: true + } + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: noOptnlFieldAdUnit + }); + expect(auctionArgs.adUnits[0].sizes).to.deep.equal([[300, 250]]); + expect(auctionArgs.adUnits[0].mediaTypes.video).to.exist; + + let mixedAdUnit = [{ + code: 'test3', + bids: [], + sizes: [[300, 250], [300, 600]], + mediaTypes: { + video: { + context: 'outstream', + playerSize: [[400, 350]] + }, + native: { + image: { + aspect_ratios: [200, 150], + required: true + } + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: mixedAdUnit + }); + expect(auctionArgs.adUnits[0].sizes).to.deep.equal([[400, 350]]); + expect(auctionArgs.adUnits[0].mediaTypes.video).to.exist; + + let altVideoPlayerSize = [{ + code: 'test4', + bids: [], + sizes: [[600, 600]], + mediaTypes: { + video: { + playerSize: [640, 480] + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: altVideoPlayerSize + }); + expect(auctionArgs.adUnits[0].sizes).to.deep.equal([[640, 480]]); + expect(auctionArgs.adUnits[0].mediaTypes.video.playerSize).to.deep.equal([[640, 480]]); + expect(auctionArgs.adUnits[0].mediaTypes.video).to.exist; + assert.ok(logInfoSpy.calledWith('Transforming video.playerSize from [640,480] to [[640,480]] so it\'s in the proper format.'), 'expected message was logged'); + }); + + it('should normalize adUnit.sizes and adUnit.mediaTypes.banner.sizes', function () { + let normalizeAdUnit = [{ + code: 'test5', + bids: [], + sizes: [300, 250], + mediaTypes: { + banner: { + sizes: [300, 250] + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: normalizeAdUnit + }); + expect(auctionArgs.adUnits[0].sizes).to.deep.equal([[300, 250]]); + expect(auctionArgs.adUnits[0].mediaTypes.banner.sizes).to.deep.equal([[300, 250]]); + }); + }); + + describe('negative tests for validating adUnits', function() { + it('should throw error message and delete an object/property', function () { + let badBanner = [{ + code: 'testb1', + bids: [], + sizes: [[300, 250], [300, 600]], + mediaTypes: { + banner: { + name: 'test' + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: badBanner + }); + expect(auctionArgs.adUnits[0].sizes).to.deep.equal([[300, 250], [300, 600]]); + expect(auctionArgs.adUnits[0].mediaTypes.banner).to.be.undefined; + assert.ok(logErrorSpy.calledWith('Detected a mediaTypes.banner object did not include sizes. This is a required field for the mediaTypes.banner object. Removing invalid mediaTypes.banner object from request.')); + + let badVideo1 = [{ + code: 'testb2', + bids: [], + sizes: [[600, 600]], + mediaTypes: { + video: { + playerSize: ['600x400'] + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: badVideo1 + }); + expect(auctionArgs.adUnits[0].sizes).to.deep.equal([[600, 600]]); + expect(auctionArgs.adUnits[0].mediaTypes.video.playerSize).to.be.undefined; + expect(auctionArgs.adUnits[0].mediaTypes.video).to.exist; + assert.ok(logErrorSpy.calledWith('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.')); + + let badVideo2 = [{ + code: 'testb3', + bids: [], + sizes: [[600, 600]], + mediaTypes: { + video: { + playerSize: [['300', '200']] + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: badVideo2 + }); + expect(auctionArgs.adUnits[0].sizes).to.deep.equal([[600, 600]]); + expect(auctionArgs.adUnits[0].mediaTypes.video.playerSize).to.be.undefined; + expect(auctionArgs.adUnits[0].mediaTypes.video).to.exist; + assert.ok(logErrorSpy.calledWith('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.')); + + let badNativeImgSize = [{ + code: 'testb4', + bids: [], + mediaTypes: { + native: { + image: { + sizes: '300x250' + } + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: badNativeImgSize + }); + expect(auctionArgs.adUnits[0].mediaTypes.native.image.sizes).to.be.undefined; + expect(auctionArgs.adUnits[0].mediaTypes.native.image).to.exist; + assert.ok(logErrorSpy.calledWith('Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request.')); + + let badNativeImgAspRat = [{ + code: 'testb5', + bids: [], + mediaTypes: { + native: { + image: { + aspect_ratios: '300x250' + } + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: badNativeImgAspRat + }); + expect(auctionArgs.adUnits[0].mediaTypes.native.image.aspect_ratios).to.be.undefined; + expect(auctionArgs.adUnits[0].mediaTypes.native.image).to.exist; + assert.ok(logErrorSpy.calledWith('Please use an array of sizes for native.image.aspect_ratios field. Removing invalid mediaTypes.native.image.aspect_ratios property from request.')); + + let badNativeIcon = [{ + code: 'testb6', + bids: [], + mediaTypes: { + native: { + icon: { + sizes: '300x250' + } + } + } + }]; + $$PREBID_GLOBAL$$.requestBids({ + adUnits: badNativeIcon + }); + expect(auctionArgs.adUnits[0].mediaTypes.native.icon.sizes).to.be.undefined; + expect(auctionArgs.adUnits[0].mediaTypes.native.icon).to.exist; + assert.ok(logErrorSpy.calledWith('Please use an array of sizes for native.icon.sizes field. Removing invalid mediaTypes.native.icon.sizes property from request.')); + }); + }); + }); }); describe('multiformat requests', function () { @@ -1447,7 +1687,9 @@ describe('Unit: Prebid Module', function () { adUnits = [{ code: 'adUnit-code', mediaTypes: { - banner: {}, + banner: { + sizes: [[300, 250]] + }, native: {}, }, sizes: [[300, 250], [300, 600]], From 1b41d638b0baef3428dc8d8a19f8bcff89a89aff Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Wed, 6 Feb 2019 23:03:55 +0200 Subject: [PATCH 0999/1594] YieldNexus: Rename adapter's name (#3508) * Add support for multiple media types. Add test coverage. * Add support for multiple media types. Add test coverage. * Modify multi-format ads handler. Modify tests. * Rename yieldnexus bid adapter to fix download issue --- modules/{yieldNexusBidAdapter.js => yieldnexusBidAdapter.js} | 0 modules/{yieldNexusBidAdapter.md => yieldnexusBidAdapter.md} | 0 ...ieldNexusBidAdapter_spec.js => yieldnexusBidAdapter_spec.js} | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename modules/{yieldNexusBidAdapter.js => yieldnexusBidAdapter.js} (100%) rename modules/{yieldNexusBidAdapter.md => yieldnexusBidAdapter.md} (100%) rename test/spec/modules/{yieldNexusBidAdapter_spec.js => yieldnexusBidAdapter_spec.js} (99%) diff --git a/modules/yieldNexusBidAdapter.js b/modules/yieldnexusBidAdapter.js similarity index 100% rename from modules/yieldNexusBidAdapter.js rename to modules/yieldnexusBidAdapter.js diff --git a/modules/yieldNexusBidAdapter.md b/modules/yieldnexusBidAdapter.md similarity index 100% rename from modules/yieldNexusBidAdapter.md rename to modules/yieldnexusBidAdapter.md diff --git a/test/spec/modules/yieldNexusBidAdapter_spec.js b/test/spec/modules/yieldnexusBidAdapter_spec.js similarity index 99% rename from test/spec/modules/yieldNexusBidAdapter_spec.js rename to test/spec/modules/yieldnexusBidAdapter_spec.js index 40e2bb6c744..3d36291f136 100644 --- a/test/spec/modules/yieldNexusBidAdapter_spec.js +++ b/test/spec/modules/yieldnexusBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import {spec} from 'modules/yieldNexusBidAdapter'; +import {spec} from 'modules/yieldnexusBidAdapter'; import * as utils from 'src/utils'; const spid = '123'; From 621470989a70a2e2201dd207819952f3be0e3f12 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Wed, 6 Feb 2019 16:16:23 -0500 Subject: [PATCH 1000/1594] Prebid 2.1.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b01df6f6c83..8ff1bd0bbab 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.1.0-pre", + "version": "2.1.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 069d5f7a05957b191a2a10df9aba4948f68ddb9c Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Wed, 6 Feb 2019 16:30:30 -0500 Subject: [PATCH 1001/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ff1bd0bbab..8437e395be5 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.1.0", + "version": "2.2.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From c2734a73fc907dc6c97d7694e3740e19b8749d3c Mon Sep 17 00:00:00 2001 From: Rich Audience Date: Thu, 7 Feb 2019 23:51:45 +0100 Subject: [PATCH 1002/1594] Rich Audience Bidder Adapter (#3518) * Rich Audience Bidder Adapter * Rich Audience Bidder Adapter * Rich Audience Bidder Adapter * Changes in UserSyncs * Changes in package-lock.json --- modules/richAudienceBidAdapter.js | 139 +++++++ modules/richAudienceBidAdapter.md | 91 +++++ .../modules/richAudienceBidAdapter_spec.js | 344 ++++++++++++++++++ 3 files changed, 574 insertions(+) create mode 100644 modules/richAudienceBidAdapter.js create mode 100644 modules/richAudienceBidAdapter.md create mode 100644 test/spec/modules/richAudienceBidAdapter_spec.js diff --git a/modules/richAudienceBidAdapter.js b/modules/richAudienceBidAdapter.js new file mode 100644 index 00000000000..9701bb4ec48 --- /dev/null +++ b/modules/richAudienceBidAdapter.js @@ -0,0 +1,139 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +import {config} from '../src/config'; +import {BANNER, VIDEO} from '../src/mediaTypes'; +import * as utils from '../src/utils'; + +const BIDDER_CODE = 'richaudience'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['ra'], + supportedMediaTypes: [BANNER, VIDEO], + + /*** + * Determines whether or not the given bid request is valid + * + * @param {bidRequest} bid The bid params to validate. + * @returns {boolean} True if this is a valid bid, and false otherwise + */ + isBidRequestValid: function (bid) { + return !!(bid.params && bid.params.pid && bid.params.supplyType); + }, + /*** + * Build a server request from the list of valid BidRequests + * @param {validBidRequests} is an array of the valid bids + * @param {bidderRequest} bidder request object + * @returns {ServerRequest} Info describing the request to the server + */ + buildRequests: function (validBidRequests, bidderRequest) { + return validBidRequests.map(bid => { + var payload = { + bidfloor: bid.params.bidfloor, + ifa: bid.params.ifa, + pid: bid.params.pid, + supplyType: bid.params.supplyType, + currencyCode: config.getConfig('currency.adServerCurrency'), + auctionId: bid.auctionId, + bidId: bid.bidId, + BidRequestsCount: bid.bidRequestsCount, + bidder: bid.bidder, + bidderRequestId: bid.bidderRequestId, + tagId: bid.adUnitCode, + sizes: bid.sizes.map(size => ({ + w: size[0], + h: size[1], + })), + referer: (typeof bidderRequest.refererInfo.referer != 'undefined' ? encodeURIComponent(bidderRequest.refererInfo.referer) : null), + numIframes: (typeof bidderRequest.refererInfo.numIframes != 'undefined' ? bidderRequest.refererInfo.numIframes : null), + transactionId: bid.transactionId, + timeout: config.getConfig('bidderTimeout'), + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr_consent = bidderRequest.gdprConsent.consentString; + payload.gdpr = bidderRequest.gdprConsent.gdprApplies; // we're handling the undefined case server side + } else { + payload.gdpr_consent = ''; + payload.gdpr = null; + } + + var payloadString = JSON.stringify(payload); + + var endpoint = 'https://shb.richaudience.com/hb/'; + + return { + method: 'POST', + url: endpoint, + data: payloadString, + }; + }); + }, + /*** + * Read the response from the server and build a list of bids + * @param {serverResponse} Response from the server. + * @param {bidRequest} Bid request object + * @returns {bidResponses} Array of bids which were nested inside the server + */ + interpretResponse: function (serverResponse, bidRequest) { + const bidResponses = []; + + var response = serverResponse.body; + + try { + if (response) { + var bidResponse = { + requestId: JSON.parse(bidRequest.data).bidId, + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.creative_id, + mediaType: response.media_type, + netRevenue: response.netRevenue, + currency: response.currency, + ttl: response.ttl, + }; + + if (response.media_type === 'video') { + bidResponse.vastXml = response.vastXML; + } else { + bidResponse.ad = response.adm + } + + bidResponses.push(bidResponse); + } + } catch (error) { + utils.logError('Error while parsing Rich Audience response', error); + } + return bidResponses + }, + /*** + * User Syncs + * + * @param {syncOptions} Publisher prebid configuration + * @param {serverResponses} Response from the server + * @param {gdprConsent} GPDR consent object + * @returns {Array} + */ + getUserSyncs: function (syncOptions, serverResponses, gdprConsent) { + const syncs = []; + + var rand = Math.floor(Math.random() * 9999999999); + var syncUrl = ''; + + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + syncUrl = 'https://sync.richaudience.com/dcf3528a0b8aa83634892d50e91c306e/?ord=' + rand + '&pubconsent=' + gdprConsent.consentString + '&euconsent=' + gdprConsent.consentString; + } else { + syncUrl = 'https://sync.richaudience.com/dcf3528a0b8aa83634892d50e91c306e/?ord=' + rand; + } + + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: syncUrl + }); + } + return syncs + }, +}; + +registerBidder(spec); diff --git a/modules/richAudienceBidAdapter.md b/modules/richAudienceBidAdapter.md new file mode 100644 index 00000000000..11c60efc9dc --- /dev/null +++ b/modules/richAudienceBidAdapter.md @@ -0,0 +1,91 @@ +# Overview + +``` +Module Name: Rich Audience Bidder Adapter +Module Type: Bidder Adapter +Maintainer: cert@richaudience.com +``` + +# Description + +Connects to Rich Audience Marketplace for bids. This adapter supports Display and Video. + +The Rich Audience adapter requires setup and approval from the Rich Audience team. +Please reach out to your account manager for more information. + +# Test Parameters + +## Web +``` + var adUnits = [ + { + code: 'test-div1', + sizes: [[300, 250],[300, 600]], + bids: [{ + bidder: 'richaudience', + params: { + "pid":"ADb1f40rmi", + "supplyType":"site", + "bidfloor":0.70, + } + }] + }, + { + code: 'test-div2', + sizes: [[728, 90],[970, 250]], + bids: [{ + bidder: 'richaudience', + params: { + "pid":"ADb1f40rmo", + "supplyType":"site", + "bidfloor":0.40, + } + }] + } + ]; +``` + +## In-app +``` + var adUnits = [ + { + code: 'test-div1', + sizes: [[300, 250],[300, 600]], + bids: [{ + bidder: 'richaudience', + params: { + "pid":"ADb1f40rmi", + "supplyType":"app", + "ifa":"AAAAAAAAA-BBBB-CCCC-1111-222222220000", + "bidfloor":0.70, + } + }] + }, + { + code: 'test-div2', + sizes: [[728, 90],[970, 250]], + }, + bids: [{ + bidder: 'richaudience', + params: { + "pid":"ADb1f40rmo", + "supplyType":"app", + "ifa":"AAAAAAAAA-BBBB-CCCC-1111-222222220000", + "bidfloor":0.40, + } + }] + } + ]; +``` + +# Configuration +Add the following code to enable user syncing. By default, Prebid.js version 0.34.0+ turns off user syncing through iframes. +Rich Audience strongly recommends enabling user syncing through iframes. Be sure to call `pbjs.setConfig()` only once. + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true + } +}); +``` diff --git a/test/spec/modules/richAudienceBidAdapter_spec.js b/test/spec/modules/richAudienceBidAdapter_spec.js new file mode 100644 index 00000000000..12d98698222 --- /dev/null +++ b/test/spec/modules/richAudienceBidAdapter_spec.js @@ -0,0 +1,344 @@ +// 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/richAudienceBidAdapter'; +import { + spec +} from 'modules/richAudienceBidAdapter'; +import {config} from 'src/config'; +import * as utils from 'src/utils'; + +describe('Rich Audience adapter tests', function () { + var DEFAULT_PARAMS = [{ + adUnitCode: 'test-div', + bidId: '2c7c8e9c900244', + sizes: [ + [300, 250], + [300, 600], + [728, 90], + [970, 250] + ], + bidder: 'richaudience', + params: { + bidfloor: 0.5, + pid: 'ADb1f40rmi', + supplyType: 'site' + }, + auctionId: '0cb3144c-d084-4686-b0d6-f5dbe917c563', + bidRequestsCount: 1, + bidderRequestId: '1858b7382993ca', + transactionId: '29df2112-348b-4961-8863-1b33684d95e6' + }]; + + var DEFAULT_PARAMS_APP = [{ + adUnitCode: 'test-div', + bidId: '2c7c8e9c900244', + sizes: [ + [300, 250], + [300, 600], + [728, 90], + [970, 250] + ], + bidder: 'richaudience', + params: { + bidfloor: 0.5, + ifa: 'AAAAAAAAA-BBBB-CCCC-1111-222222220000', + pid: 'ADb1f40rmi', + supplyType: 'app', + }, + auctionId: '0cb3144c-d084-4686-b0d6-f5dbe917c563', + bidRequestsCount: 1, + bidderRequestId: '1858b7382993ca', + transactionId: '29df2112-348b-4961-8863-1b33684d95e6' + }]; + + var DEFAULT_PARAMS_WO_OPTIONAL = [{ + adUnitCode: 'test-div', + bidId: '2c7c8e9c900244', + sizes: [ + [300, 250], + [300, 600], + [728, 90], + [970, 250] + ], + bidder: 'richaudience', + params: { + pid: 'ADb1f40rmi', + supplyType: 'site', + }, + auctionId: '851adee7-d843-48f9-a7e9-9ff00573fcbf', + bidRequestsCount: 1, + bidderRequestId: '1858b7382993ca', + transactionId: '29df2112-348b-4961-8863-1b33684d95e6' + }]; + + var BID_RESPONSE = { + body: { + cpm: 1.50, + adm: '', + media_type: 'js', + width: 300, + height: 250, + creative_id: '189198063', + netRevenue: true, + currency: 'USD', + ttl: 300 + } + }; + + var BID_RESPONSE_VIDEO = { + body: { + cpm: 1.50, + media_type: 'video', + width: 1, + height: 1, + creative_id: '189198063', + netRevenue: true, + currency: 'USD', + ttl: 300, + vastXML: '' + } + }; + + it('Verify build request', function () { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'USD' + } + }); + + const request = spec.buildRequests(DEFAULT_PARAMS, { + 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: { + referer: 'http://domain.com', + numIframes: 0 + } + }); + + expect(request[0]).to.have.property('method').and.to.equal('POST'); + const requestContent = JSON.parse(request[0].data); + expect(requestContent).to.have.property('bidfloor').and.to.equal(0.5); + expect(requestContent).to.have.property('pid').and.to.equal('ADb1f40rmi'); + expect(requestContent).to.have.property('supplyType').and.to.equal('site'); + expect(requestContent).to.have.property('auctionId').and.to.equal('0cb3144c-d084-4686-b0d6-f5dbe917c563'); + expect(requestContent).to.have.property('bidId').and.to.equal('2c7c8e9c900244'); + expect(requestContent).to.have.property('BidRequestsCount').and.to.equal(1); + expect(requestContent).to.have.property('bidder').and.to.equal('richaudience'); + expect(requestContent).to.have.property('bidderRequestId').and.to.equal('1858b7382993ca'); + expect(requestContent).to.have.property('tagId').and.to.equal('test-div'); + expect(requestContent).to.have.property('referer').and.to.equal('http%3A%2F%2Fdomain.com'); + expect(requestContent).to.have.property('sizes'); + expect(requestContent.sizes[0]).to.have.property('w').and.to.equal(300); + expect(requestContent.sizes[0]).to.have.property('h').and.to.equal(250); + expect(requestContent.sizes[1]).to.have.property('w').and.to.equal(300); + expect(requestContent.sizes[1]).to.have.property('h').and.to.equal(600); + expect(requestContent).to.have.property('transactionId').and.to.equal('29df2112-348b-4961-8863-1b33684d95e6'); + expect(requestContent).to.have.property('timeout').and.to.equal(3000); + }); + + describe('gdpr test', function () { + it('Verify build request with GDPR', function () { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'USD' + }, + consentManagement: { + cmpApi: 'iab', + timeout: 8000, + allowAuctionWithoutConsent: true + } + }); + + const request = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL, { + 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: { + referer: 'http://domain.com', + numIframes: 0 + } + }); + const requestContent = JSON.parse(request[0].data); + expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA'); + }); + + it('Verify adding ifa when supplyType equal to app', function () { + const request = spec.buildRequests(DEFAULT_PARAMS_APP, { + 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: { + referer: 'http://domain.com', + numIframes: 0 + } + }); + }); + + it('Verify build request with GDPR without gdprApplies', function () { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + }, + consentManagement: { + cmp: 'iab', + consentRequired: true, + timeout: 8000, + allowAuctionWithoutConsent: true + } + }); + const request = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL, { + gdprConsent: { + consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA' + }, + refererInfo: { + referer: 'http://domain.com', + numIframes: 0 + } + }); + const requestContent = JSON.parse(request[0].data); + expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA'); + }); + }); + + it('Verify interprete response', function () { + const request = spec.buildRequests(DEFAULT_PARAMS, { + 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: { + referer: 'http://domain.com', + numIframes: 0 + } + }); + + const bids = spec.interpretResponse(BID_RESPONSE, request[0]); + expect(bids).to.have.lengthOf(1); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.50); + expect(bid.ad).to.equal(''); + expect(bid.mediaType).to.equal('js'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.creativeId).to.equal('189198063'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(300); + }); + + it('no banner media response', function () { + const request = spec.buildRequests(DEFAULT_PARAMS, { + 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: { + referer: 'http://domain.com', + numIframes: 0 + } + }); + + const bids = spec.interpretResponse(BID_RESPONSE_VIDEO, request[0]); + const bid = bids[0]; + expect(bid.vastXml).to.equal(''); + }); + + it('Verifies bidder_code', function () { + expect(spec.code).to.equal('richaudience'); + }); + + it('Verifies bidder aliases', function () { + expect(spec.aliases).to.have.lengthOf(1); + expect(spec.aliases[0]).to.equal('ra'); + }); + + it('Verifies if bid request is valid', function () { + expect(spec.isBidRequestValid(DEFAULT_PARAMS[0])).to.equal(true); + expect(spec.isBidRequestValid(DEFAULT_PARAMS_WO_OPTIONAL[0])).to.equal(true); + expect(spec.isBidRequestValid({})).to.equal(false); + expect(spec.isBidRequestValid({ + params: {} + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + pid: 'ADb1f40rmi' + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + supplyType: 'site' + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + supplyType: 'app' + } + })).to.equal(false); + expect(spec.isBidRequestValid({ + params: { + pid: 'ADb1f40rmi', + supplyType: 'site' + } + })).to.equal(true); + expect(spec.isBidRequestValid({ + params: { + pid: ['1gCB5ZC4XL', '1a40xk8qSV'], + supplyType: 'site' + } + })).to.equal(true); + expect(spec.isBidRequestValid({ + params: { + pid: 'ADb1f40rmi', + supplyType: 'site' + } + })).to.equal(true); + expect(spec.isBidRequestValid({ + params: { + pid: 'ADb1f40rmi', + supplyType: 'app', + ifa: 'AAAAAAAAA-BBBB-CCCC-1111-222222220000', + } + })).to.equal(true); + expect(spec.isBidRequestValid({ + params: { + pid: 'ADb1f40rmi', + supplyType: 'site', + bidfloor: 0.50, + } + })).to.equal(true); + expect(spec.isBidRequestValid({ + params: { + pid: 'ADb1f40rmi', + supplyType: 'site', + bidfloor: 0.50, + } + })).to.equal(true); + }); + + it('Verifies user sync', function () { + var syncs = spec.getUserSyncs({ + iframeEnabled: true + }, [BID_RESPONSE] , { + consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', + gdprApplies: true + }); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('iframe'); + syncs = spec.getUserSyncs({ + iframeEnabled: false + }, [BID_RESPONSE], { + consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', + gdprApplies: true + }); + expect(syncs).to.have.lengthOf(0); + + syncs = spec.getUserSyncs({ + iframeEnabled: true + }, [],{consentString:"",gdprApplies:false}); + expect(syncs).to.have.lengthOf(1); + }); +}); From 5ecf54b0a981f440023d83ff443f709dff4f8334 Mon Sep 17 00:00:00 2001 From: skazedo Date: Mon, 11 Feb 2019 11:51:29 -0500 Subject: [PATCH 1003/1594] Support new param in tag call to ZEDO (#3471) * initial commit * updated contact and tag details * changes ti support the renderers * changes to pass dimId * fixed names of internal mapping * added comment * added gdpr param to request and other fixes * modified api url * fix * fixed the secure api call * rolled back video event callback till we support it * updated doc with video details * added bid won and timeout pixel * added testcase for bid events * modified testcase * fixed the url logged * tag param values passed ot renderer * added a conditioal check * changes to support new param to adserver for purpose of tracking * passed param to renderer * missing variable defined --- integrationExamples/gpt/pbjs_example_gpt.html | 3 ++- modules/zedoBidAdapter.js | 9 ++++++--- modules/zedoBidAdapter.md | 10 ++++++---- test/spec/modules/zedoBidAdapter_spec.js | 9 +++++---- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index dcc67ae0f74..32452d33fd9 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -300,7 +300,8 @@ bidder: 'zedo', params: { channelCode: 2264002816, //REQUIRED - dimId: 9 //REQUIRED + dimId: 9, //REQUIRED + pubId: 1 // OPTIONAL } }, { diff --git a/modules/zedoBidAdapter.js b/modules/zedoBidAdapter.js index db65f147698..b09913ecf60 100644 --- a/modules/zedoBidAdapter.js +++ b/modules/zedoBidAdapter.js @@ -60,6 +60,7 @@ export const spec = { id: bidRequest.bidId, network: network, channel: channel, + publisher: bidRequest.params.pubId ? bidRequest.params.pubId : 0, width: dim[0], height: dim[1], dimension: bidRequest.params.dimId, @@ -258,11 +259,12 @@ function videoRenderer(bid) { bid.renderer.push(() => { let channelCode = utils.deepAccess(bid, 'params.0.channelCode') || 0; let dimId = utils.deepAccess(bid, 'params.0.dimId') || 0; + let publisher = utils.deepAccess(bid, 'params.0.pubId') || 0; let options = utils.deepAccess(bid, 'params.0.options') || {}; let channel = (channelCode > 0) ? (channelCode - (bid.network * 1000000)) : 0; var rndr = new ZdPBTag(bid.adUnitCode, bid.network, bid.width, bid.height, bid.adType, bid.vastXml, channel, dimId, (encodeURI(utils.getTopWindowUrl()) || ''), options); - rndr.renderAd(); + rndr.renderAd(publisher); }); } @@ -288,18 +290,19 @@ function getLoggingData(eid, data) { data = (utils.isArray(data) && data) || []; let params = {}; - let channel, network, dim, adunitCode, timeToRespond, cpm; + let channel, network, dim, publisher, adunitCode, timeToRespond, cpm; data.map((adunit) => { adunitCode = adunit.adUnitCode; channel = utils.deepAccess(adunit, 'params.0.channelCode') || 0; network = channel > 0 ? parseInt(channel / 1000000) : 0; dim = utils.deepAccess(adunit, 'params.0.dimId') * 256 || 0; + publisher = utils.deepAccess(adunit, 'params.0.pubId') || 0; timeToRespond = adunit.timeout ? adunit.timeout : adunit.timeToRespond; cpm = adunit.cpm; }); params.n = network; params.c = channel; - params.s = '0'; + params.s = publisher; params.x = dim; params.ai = encodeURI('Prebid^zedo^' + adunitCode + '^' + cpm + '^' + timeToRespond); params.pu = encodeURI(utils.getTopWindowUrl()) || ''; diff --git a/modules/zedoBidAdapter.md b/modules/zedoBidAdapter.md index 1ea35585a64..e0f9101deaa 100644 --- a/modules/zedoBidAdapter.md +++ b/modules/zedoBidAdapter.md @@ -26,8 +26,9 @@ ZEDO has its own renderer and will render the video unit if not defined in the c { bidder: 'zedo', params: { - channelCode: 2264004118 - dimId: 9 + channelCode: 2264004118, // required + dimId: 9, // required + pubId: 1 // optional } } ] @@ -53,8 +54,9 @@ ZEDO has its own renderer and will render the video unit if not defined in the c bidder: 'zedo', params: { - channelCode: 2264004593, - dimId: 85 + channelCode: 2264004593, // required + dimId: 85, // required + pubId: 1 // optional } } ] diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js index 8e6578d9b2c..76301ba9018 100644 --- a/test/spec/modules/zedoBidAdapter_spec.js +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -38,7 +38,8 @@ describe('The ZEDO bidding adapter', function () { sizes: [[300, 200]], params: { channelCode: 20000000, - dimId: 10 + dimId: 10, + pubId: 1 }, }, ]; @@ -46,7 +47,7 @@ describe('The ZEDO bidding adapter', function () { expect(request.url).to.match(/^\/\/saxp.zedo.com\/asw\/fmh.json/); expect(request.method).to.equal('GET'); const zedoRequest = request.data; - expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}]}'); + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"publisher":1,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}]}'); }); it('should properly build a channelCode request for video with type defined', function () { @@ -71,7 +72,7 @@ describe('The ZEDO bidding adapter', function () { expect(request.url).to.match(/^\/\/saxp.zedo.com\/asw\/fmh.json/); expect(request.method).to.equal('GET'); const zedoRequest = request.data; - expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":640,"height":480,"dimension":85,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"Inarticle"}]}]}'); + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"publisher":0,"width":640,"height":480,"dimension":85,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"Inarticle"}]}]}'); }); describe('buildGDPRRequests', function () { @@ -100,7 +101,7 @@ describe('The ZEDO bidding adapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.method).to.equal('GET'); const zedoRequest = request.data; - expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}],"gdpr":1,"gdpr_consent":"BOJ8RZsOJ8RZsABAB8AAAAAZ+A=="}'); + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"publisher":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}],"gdpr":1,"gdpr_consent":"BOJ8RZsOJ8RZsABAB8AAAAAZ+A=="}'); }); }); }); From 429c65ed2f98d215c4691bb6005a600ab1b5145b Mon Sep 17 00:00:00 2001 From: Elardzhi Date: Mon, 11 Feb 2019 13:05:46 -0800 Subject: [PATCH 1004/1594] Admedia adapter (#3481) * Admedia adapter * Removed a commented line --- modules/admediaBidAdapter.js | 71 ++++++++++ modules/admediaBidAdapter.md | 42 ++++++ test/spec/modules/admediaBidAdapter_spec.js | 138 ++++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 modules/admediaBidAdapter.js create mode 100644 modules/admediaBidAdapter.md create mode 100644 test/spec/modules/admediaBidAdapter_spec.js diff --git a/modules/admediaBidAdapter.js b/modules/admediaBidAdapter.js new file mode 100644 index 00000000000..73d6ea08eea --- /dev/null +++ b/modules/admediaBidAdapter.js @@ -0,0 +1,71 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; + +const BIDDER_CODE = 'admedia'; +const ENDPOINT_URL = '//prebid.admedia.com/bidder/'; + +export const spec = { + code: BIDDER_CODE, + + isBidRequestValid: function (bid) { + return bid.params && !!bid.params.aid; + }, + + buildRequests: function (validBidRequests, bidderRequest) { + let payload = {}; + + if (bidderRequest && bidderRequest.refererInfo) { + payload.referer = encodeURIComponent(bidderRequest.refererInfo.referer); + } + + payload.tags = []; + + utils._each(validBidRequests, function (bid) { + const tag = { + id: bid.bidId, + sizes: bid.sizes, + aid: bid.params.aid + }; + payload.tags.push(tag); + }); + + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: ENDPOINT_URL, + data: payloadString, + }; + }, + + interpretResponse: function (serverResponse, bidRequest) { + const bidResponses = []; + + if (!serverResponse.body.tags) { + return bidResponses; + } + + utils._each(serverResponse.body.tags, function (response) { + if (!response.error && response.cpm > 0) { + const bidResponse = { + requestId: response.id, + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.id, + dealId: response.id, + currency: 'USD', + netRevenue: true, + ttl: 120, + // referrer: REFERER, + ad: response.ad + }; + + bidResponses.push(bidResponse); + } + }); + + return bidResponses; + } +}; + +registerBidder(spec); diff --git a/modules/admediaBidAdapter.md b/modules/admediaBidAdapter.md new file mode 100644 index 00000000000..a03a7b49529 --- /dev/null +++ b/modules/admediaBidAdapter.md @@ -0,0 +1,42 @@ +# Overview + +``` +Module Name: Admedia Bidder Adapter +Module Type: Bidder Adapter +Maintainer: developers@admedia.com +``` + +# Description + +Admedia Bidder Adapter for Prebid.js. +Only Banner format is supported. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div-0', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: 'admedia', + params: { + aid: 86858 + } + } + ] + }, + { + code: 'test-div-1', + sizes: [[300, 50]], // a mobile size + bids: [ + { + bidder: 'admedia', + params: { + aid: 86858 + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/admediaBidAdapter_spec.js b/test/spec/modules/admediaBidAdapter_spec.js new file mode 100644 index 00000000000..2e14eee938c --- /dev/null +++ b/test/spec/modules/admediaBidAdapter_spec.js @@ -0,0 +1,138 @@ +import { expect } from 'chai'; +import { spec } from 'modules/admediaBidAdapter'; + +describe('admediaAdapterTests', function () { + describe('bidRequestValidity', function () { + it('bidRequest with aid', function () { + expect(spec.isBidRequestValid({ + bidder: 'admedia', + params: { + aid: 86858, + } + })).to.equal(true); + }); + + it('bidRequest without aid', function () { + expect(spec.isBidRequestValid({ + bidder: 'a4g', + params: { + key: 86858 + } + })).to.equal(false); + }); + }); + + describe('bidRequest', function () { + const validBidRequests = [{ + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'auctionId': 'e3010a3c-5b95-4475-9ba2-1b004c737c30', + 'bidId': '2758de47c84ab58', + 'bidRequestsCount': 1, + 'bidder': 'admedia', + 'bidderRequestId': '1033407c6af0c7', + 'params': { + 'aid': 86858, + }, + 'sizes': [[300, 250], [300, 600]], + 'transactionId': '5851b2cf-ee2d-4022-abd2-d581ef01604e' + }, { + 'adUnitCode': 'div-gpt-ad-1460505748561-1', + 'auctionId': 'e3010a3c-5b95-4475-9ba2-1b004c737c30', + 'bidId': '3d2aaa400371fa', + 'bidRequestsCount': 1, + 'bidder': 'admedia', + 'bidderRequestId': '1033407c6af0c7', + 'params': { + 'aid': 84977, + }, + 'sizes': [[728, 90]], + 'transactionId': 'f8b5247e-7715-4e60-9d51-33153e78c190' + }]; + + const bidderRequest = { + 'auctionId': 'e3010a3c-5b95-4475-9ba2-1b004c737c30', + 'bidderCode': 'admedia', + 'bidderRequestId': '1033407c6af0c7', + 'refererInfo': { + 'numIframes': 0, + 'reachedTop': true, + 'referer': 'http://test.com/index.html?pbjs_debug=true' + } + + }; + + const request = spec.buildRequests(validBidRequests, bidderRequest); + + it('bidRequest method', function () { + expect(request.method).to.equal('POST'); + }); + + it('bidRequest url', function () { + expect(request.url).to.equal('//prebid.admedia.com/bidder/'); + }); + + it('bidRequest data', function () { + const data = JSON.parse(request.data); + expect(decodeURIComponent(data.referer)).to.be.eql(bidderRequest.refererInfo.referer); + expect(data.tags).to.be.an('array'); + expect(data.tags[0].aid).to.be.eql(validBidRequests[0].params.aid); + expect(data.tags[0].id).to.be.eql(validBidRequests[0].bidId); + expect(data.tags[0].sizes).to.be.eql(validBidRequests[0].sizes); + expect(data.tags[1].aid).to.be.eql(validBidRequests[1].params.aid); + expect(data.tags[1].id).to.be.eql(validBidRequests[1].bidId); + expect(data.tags[1].sizes).to.be.eql(validBidRequests[1].sizes); + }); + }); + + describe('interpretResponse', function () { + const serverResponse = { + body: { + tags: [ + { + ad: '', + cpm: 0.9, + height: 250, + id: '5582180864bc41', + width: 300, + }, + { + error: 'Error message', + id: '6dc6ee4e157749' + }, + { + ad: '', + cpm: 0, + height: 728, + id: '5762180864bc41', + width: 90, + } + ] + }, + headers: {} + }; + + const bidRequest = {}; + + const result = spec.interpretResponse(serverResponse, bidRequest); + + it('Should return an empty array if empty or no tags in response', function () { + expect(spec.interpretResponse({body: ''}, {}).length).to.equal(0); + }); + + it('Should have only one bid', function () { + expect(result.length).to.equal(1); + }); + + it('Should have required keys', function () { + expect(result[0].requestId).to.be.eql(serverResponse.body.tags[0].id); + expect(result[0].cpm).to.be.eql(serverResponse.body.tags[0].cpm); + expect(result[0].width).to.be.eql(serverResponse.body.tags[0].width); + expect(result[0].height).to.be.eql(serverResponse.body.tags[0].height); + expect(result[0].creativeId).to.be.eql(serverResponse.body.tags[0].id); + expect(result[0].dealId).to.be.eql(serverResponse.body.tags[0].id); + expect(result[0].netRevenue).to.be.eql(true); + expect(result[0].ttl).to.be.eql(120); + expect(result[0].ad).to.be.eql(serverResponse.body.tags[0].ad); + }) + }); +}); From a2a231dd24417f72fe530c604b6d364547a63182 Mon Sep 17 00:00:00 2001 From: HolzAndrew Date: Mon, 11 Feb 2019 21:26:11 -0500 Subject: [PATCH 1005/1594] Update openxoutstream adapter (#3509) * use unit id being sent instead of hard coded auid * make multiple requests * removes commented out code. adds aus param back * hardcodes vht, vwd, aus * arrays should have commas * adds aus check to test * updates md file with new sizes syntax * updates md file with new sizes syntax * adds note on md about size option * size updates --- modules/openxoutstreamBidAdapter.js | 12 ++++++++---- modules/openxoutstreamBidAdapter.md | 11 +++++++---- test/spec/modules/openxoutstreamBidAdapter_spec.js | 12 ++++++++---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js index f5a79324fc6..42c7a3fff32 100644 --- a/modules/openxoutstreamBidAdapter.js +++ b/modules/openxoutstreamBidAdapter.js @@ -66,6 +66,9 @@ function getViewportDimensions(isIfr) { function buildCommonQueryParamsFromBids(bid, bidderRequest) { const isInIframe = utils.inIframe(); let defaultParams; + const height = '184'; + const width = '414'; + const aus = '304x184%7C412x184%7C375x184%7C414x184'; defaultParams = { ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), jr: utils.getTopWindowReferrer(), @@ -80,8 +83,9 @@ function buildCommonQueryParamsFromBids(bid, bidderRequest) { dddid: bid.transactionId, openrtb: '%7B%22mimes%22%3A%5B%22video%2Fmp4%22%5D%7D', nocache: new Date().getTime(), - vht: bid.params.height || bid.sizes[0][1], - vwd: bid.params.width || bid.sizes[0][0] + vht: height, + vwd: width, + aus: aus }; if (utils.deepAccess(bidderRequest, 'gdprConsent')) { @@ -105,7 +109,6 @@ function buildCommonQueryParamsFromBids(bid, bidderRequest) { function buildOXBannerRequest(bid, bidderRequest) { let queryParams = buildCommonQueryParamsFromBids(bid, bidderRequest); - queryParams.aus = utils.parseSizesInput(bid.sizes).join(','); if (bid.params.doNotTrack) { queryParams.ns = 1; @@ -178,7 +181,8 @@ function createPlacementDiv() { */ const getTemplateAdResponse = (vastUrl) => { return { - availability_zone: 'us-east-1a', + loader: 'openxoutstream', + availability_zone: '', data: [ { ads: [ diff --git a/modules/openxoutstreamBidAdapter.md b/modules/openxoutstreamBidAdapter.md index 16d66b92409..0eebb28463b 100644 --- a/modules/openxoutstreamBidAdapter.md +++ b/modules/openxoutstreamBidAdapter.md @@ -13,21 +13,24 @@ Module that connects to OpenX's demand sources for outstream to Yieldmo. This bid adapter supports Banner. +Note that the only supported size for demand is currently 400 x 300. + # Example ```javascript var adUnits = [ { code: 'test-div', - sizes: [[300, 250]], // a display size - mediaTypes: {'banner': {}}, + mediaTypes: { + 'banner': { + sizes: [[400, 300], // a display size + } + }, bids: [ { bidder: 'openxoutstream', params: { unit: '540141567', delDomain: 'se-demo-d.openx.net', - width: '300', - height: '250', } } ] diff --git a/test/spec/modules/openxoutstreamBidAdapter_spec.js b/test/spec/modules/openxoutstreamBidAdapter_spec.js index 9b189856e1a..634df1c8c6a 100644 --- a/test/spec/modules/openxoutstreamBidAdapter_spec.js +++ b/test/spec/modules/openxoutstreamBidAdapter_spec.js @@ -92,7 +92,7 @@ describe('OpenXOutstreamAdapter', function () { 'bidder': BIDDER, 'params': { 'unit': '540141567', - 'height': '300', + 'height': '200', 'width': '250', 'delDomain': 'test-del-domain' }, @@ -124,8 +124,11 @@ describe('OpenXOutstreamAdapter', function () { }]; const request = spec.buildRequests(bidRequestsWithUnitIds); expect(request[0].data.auid).to.equal(`${bidRequestsWithUnitIds[0].params.unit}`); - expect(request[0].data.vht).to.equal(`${bidRequestsWithUnitIds[0].params.height}`); - expect(request[0].data.vwd).to.equal(`${bidRequestsWithUnitIds[0].params.width}`); + expect(request[0].data.vht).to.not.equal(`${bidRequestsWithUnitIds[0].params.height}`); + expect(request[0].data.vwd).to.not.equal(`${bidRequestsWithUnitIds[0].params.width}`); + expect(request[0].data.vht).to.equal('184'); + expect(request[0].data.vwd).to.equal('414'); + expect(request[0].data.aus).to.equal('304x184%7C412x184%7C375x184%7C414x184'); }); describe('interpretResponse', function () { @@ -207,7 +210,8 @@ describe('OpenXOutstreamAdapter', function () { } const getTemplateAdResponse = (vastUrl) => { return { - availability_zone: 'us-east-1a', + loader: 'openxoutstream', + availability_zone: '', data: [ { ads: [ From ae665ece11fa2bad89fc970ee3834348d25b9354 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 12 Feb 2019 12:18:33 -0500 Subject: [PATCH 1006/1594] fix formatting to avoid lint errors (#3551) --- test/spec/modules/richAudienceBidAdapter_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/richAudienceBidAdapter_spec.js b/test/spec/modules/richAudienceBidAdapter_spec.js index 12d98698222..689c29a2646 100644 --- a/test/spec/modules/richAudienceBidAdapter_spec.js +++ b/test/spec/modules/richAudienceBidAdapter_spec.js @@ -322,7 +322,7 @@ describe('Rich Audience adapter tests', function () { it('Verifies user sync', function () { var syncs = spec.getUserSyncs({ iframeEnabled: true - }, [BID_RESPONSE] , { + }, [BID_RESPONSE], { consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', gdprApplies: true }); @@ -338,7 +338,7 @@ describe('Rich Audience adapter tests', function () { syncs = spec.getUserSyncs({ iframeEnabled: true - }, [],{consentString:"",gdprApplies:false}); + }, [], {consentString: '', gdprApplies: false}); expect(syncs).to.have.lengthOf(1); }); }); From 57cb15f419a141f15d74cd538b20af7e3d37cf60 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 12 Feb 2019 10:50:19 -0800 Subject: [PATCH 1007/1594] Prebid Server Adapter - support User ID module (#3530) * added universal id support * fixed universal id for oRTB section only * added unit test for universal id support in bid adapter * added universal id support * fixed universal id for oRTB section only * added unit test for universal id support in bid adapter * renamed universalID to userId * reverted merge error --- modules/prebidServerBidAdapter/index.js | 13 ++++++++++++ .../modules/prebidServerBidAdapter_spec.js | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index de352dc52b5..5938c493871 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -496,6 +496,19 @@ const OPEN_RTB_PROTOCOL = { request.ext = { prebid: { aliases } }; } + if (bidRequests && bidRequests[0].userId && typeof bidRequests[0].userId === 'object') { + if (!request.user) { + request.user = {}; + } + if (!request.user.ext) { + request.user.ext = {} + } + if (!request.user.ext.tpid) { + request.user.ext.tpid = {} + } + Object.assign(request.user.ext.tpid, bidRequests[0].userId); + } + if (bidRequests && bidRequests[0].gdprConsent) { // note - gdprApplies & consentString may be undefined in certain use-cases for consentManagement module let gdprApplies; diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 8d61f21c731..457d768f7a4 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -802,6 +802,26 @@ describe('S2S Adapter', function () { expect(requestBid.imp[0].ext.appnexus).to.haveOwnProperty('key'); expect(requestBid.imp[0].ext.appnexus.key).to.be.equal('value') }); + + it('when userId is defined on bids, it\'s properties should be copied to user.ext.tpid properties', function () { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + + let consentConfig = { s2sConfig: ortb2Config }; + config.setConfig(consentConfig); + + let userIdBidRequest = utils.deepClone(BID_REQUESTS); + userIdBidRequest[0].userId = { + foo: 'abc123', + unifiedid: '1234' + }; + + adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); + expect(typeof requestBid.user.ext.tpid).is.equal('object'); + expect(requestBid.user.ext.tpid.foo).is.equal('abc123'); + expect(requestBid.user.ext.tpid.unifiedid).is.equal('1234'); + }) }); describe('response handler', function () { From 18c9fed866b5752c59154cfd978cf8b2638d3464 Mon Sep 17 00:00:00 2001 From: Christian Shum-Harden Date: Tue, 12 Feb 2019 11:12:23 -0800 Subject: [PATCH 1008/1594] fixes #3536 map video.playerSize to bid.sizes (#3537) --- src/adapterManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapterManager.js b/src/adapterManager.js index 4b2cf1dc20a..75415c4035f 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -95,7 +95,7 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels, src}) bids.push(Object.assign({}, bid, { adUnitCode: adUnit.code, transactionId: adUnit.transactionId, - sizes: utils.deepAccess(mediaTypes, 'banner.sizes') || [], + sizes: utils.deepAccess(mediaTypes, 'banner.sizes') || utils.deepAccess(mediaTypes, 'video.playerSize') || [], bidId: bid.bid_id || utils.getUniqueIdentifierStr(), bidderRequestId, auctionId, From ae14a6a195fb507089535727e2ed947d84e6ae0c Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 12 Feb 2019 11:35:39 -0800 Subject: [PATCH 1009/1594] Allow root configs when building with analytics (#3539) --- gulpHelpers.js | 29 ++++++++++++++++++++++++----- gulpfile.js | 6 ++---- webpack.conf.js | 1 + 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/gulpHelpers.js b/gulpHelpers.js index a7d4333fd64..33169da3773 100644 --- a/gulpHelpers.js +++ b/gulpHelpers.js @@ -11,6 +11,7 @@ const gutil = require('gulp-util'); const MODULE_PATH = './modules'; const BUILD_PATH = './build/dist'; const DEV_PATH = './build/dev'; +const ANALYTICS_PATH = '../analytics'; // get only subdirectories that contain package.json with 'main' property @@ -126,18 +127,36 @@ module.exports = { * Invoke with gulp --analytics * Returns an array of source files for inclusion in build process */ - getAnalyticsSources: function(directory) { + getAnalyticsSources: function() { if (!argv.analytics) {return [];} // empty arrays won't affect a standard build - const directoryContents = fs.readdirSync(directory); + const directoryContents = fs.readdirSync(ANALYTICS_PATH); return directoryContents - .filter(file => isModuleDirectory(path.join(directory, file))) + .filter(file => isModuleDirectory(path.join(ANALYTICS_PATH, file))) .map(moduleDirectory => { - const module = require(path.join(directory, moduleDirectory, MANIFEST)); - return path.join(directory, moduleDirectory, module.main); + const module = require(path.join(ANALYTICS_PATH, moduleDirectory, MANIFEST)); + return path.join(ANALYTICS_PATH, moduleDirectory, module.main); }); }, + /* + * Returns the babel options object necessary for allowing analytics packages + * to have their own configs. Gets added to prebid's webpack config with the + * flag --analytics + */ + getAnalyticsOptions: function() { + let options; + + if (argv.analytics) { + // https://babeljs.io/docs/en/options#babelrcroots + options = { + babelrcRoots: ['.', ANALYTICS_PATH], + } + } + + return options; + }, + createEnd2EndTestReport : function(targetDestinationDir) { var browsers = require('./browsers.json'); var env = []; diff --git a/gulpfile.js b/gulpfile.js index 772f09e7493..8775b651b9f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -30,7 +30,6 @@ var jsEscape = require('gulp-js-escape'); 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 analyticsDirectory = '../analytics'; var port = 9999; // these modules must be explicitly listed in --modules to be included in the build, won't be part of "all" modules @@ -135,7 +134,7 @@ function makeDevpackPkg() { cloned.devtool = 'source-map'; var externalModules = helpers.getArgModules(); - const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); + const analyticsSources = helpers.getAnalyticsSources(); const moduleSources = helpers.getModulePaths(externalModules); return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) @@ -147,12 +146,11 @@ function makeDevpackPkg() { function makeWebpackPkg() { var cloned = _.cloneDeep(webpackConfig); - delete cloned.devtool; var externalModules = helpers.getArgModules(); - const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); + const analyticsSources = helpers.getAnalyticsSources(); const moduleSources = helpers.getModulePaths(externalModules); return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) diff --git a/webpack.conf.js b/webpack.conf.js index 4e082981197..9518b972b1b 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -28,6 +28,7 @@ module.exports = { use: [ { loader: 'babel-loader', + options: helpers.getAnalyticsOptions(), } ] }, From 95318c93754a97eb62fefc1b99c5491d9a7f0bde Mon Sep 17 00:00:00 2001 From: Kamoris Date: Tue, 12 Feb 2019 20:51:11 +0100 Subject: [PATCH 1010/1594] Update rtbhouseBidAdapter.md (#3549) Added "len" param to show we support it. --- modules/rtbhouseBidAdapter.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/rtbhouseBidAdapter.md b/modules/rtbhouseBidAdapter.md index c847e688941..b8410fe8bb6 100644 --- a/modules/rtbhouseBidAdapter.md +++ b/modules/rtbhouseBidAdapter.md @@ -35,13 +35,15 @@ Please reach out to pmp@rtbhouse.com to receive your own mediaTypes: { native: { title: { - required: true + required: true, + len: 25 }, image: { required: true }, body: { - required: true + required: true, + len: 90 } } }, From b55dacfa9c1b37338b1be1f8ee8a771a6f995ea3 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Wed, 13 Feb 2019 01:34:58 +0530 Subject: [PATCH 1011/1594] checking usConfig.enableOverride value before returning (#3542) --- src/userSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/userSync.js b/src/userSync.js index e2b480541a8..8e0b919572e 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -61,7 +61,7 @@ export function newUserSync(userSyncDependencies) { * @private */ function fireSyncs() { - if (!usConfig.syncEnabled || !userSyncDependencies.browserSupportsCookies || hasFired) { + if (!usConfig.syncEnabled || !userSyncDependencies.browserSupportsCookies || (!usConfig.enableOverride && hasFired)) { return; } From 3e3828501e8c2c5b8e9642ad3a7ff5e84f3e64d8 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 12 Feb 2019 15:58:39 -0500 Subject: [PATCH 1012/1594] Prebid 2.2.0 Release --- package-lock.json | 1724 +++++++++++++++++++++++++++------------------ package.json | 2 +- 2 files changed, 1031 insertions(+), 695 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb8e6df15f0..64ec08e0ca3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.0.0", + "version": "2.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -33,44 +33,19 @@ "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "@babel/generator": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.0.tgz", - "integrity": "sha512-dZTwMvTgWfhmibq4V9X+LMf6Bgl7zAodRn9PvcPdhlzFMbvUutx74dbEv7Atz3ToeEpevYEJtAwfxq/bDCzHWg==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.2.tgz", + "integrity": "sha512-f3QCuPppXxtZOEm5GWPra/uYUjmNQlu9pbAD8D/9jze4pTY83rTtB1igTBSwvkeNlC5gR24zFFkz+2WHLFQhqQ==", "dev": true, "requires": { - "@babel/types": "^7.3.0", + "@babel/types": "^7.3.2", "jsesc": "^2.5.1", "lodash": "^4.17.10", "source-map": "^0.5.0", "trim-right": "^1.0.1" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "@babel/helper-annotate-as-pure": { @@ -288,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.1.tgz", - "integrity": "sha512-ATz6yX/L8LEnC3dtLQnIx4ydcPxhLcoy9Vl6re00zb2w5lG6itY6Vhnr1KFRPq/FHNsgl/gh2mjNN20f9iJTTA==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.2.tgz", + "integrity": "sha512-QzNUC2RO1gadg+fs21fi0Uu0OuGNzRKEmgCxoLNzbCdoprLwjfmZwzUrpUNfJPaVRwBpDY47A17yYEGWyRelnQ==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -315,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.1.tgz", - "integrity": "sha512-Nmmv1+3LqxJu/V5jU9vJmxR/KIRWFk2qLHmbB56yRRRFhlaSuOVXscX3gUmhaKgUhzA3otOHVubbIEVYsZ0eZg==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.2.tgz", + "integrity": "sha512-DjeMS+J2+lpANkYLLO+m6GjoTMygYglKmRe6cDTbFv3L9i6mmiE8fe6B8MtCSLZpVXscD5kn7s6SgtHrDoBWoA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -446,9 +421,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.2.0.tgz", - "integrity": "sha512-coVO2Ayv7g0qdDbrNiadE4bU7lvCd9H539m2gMknyVjjMdwF/iCOM7R+E8PkntoqLkltO0rk+3axhpp/0v68VQ==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.3.2.tgz", + "integrity": "sha512-Lrj/u53Ufqxl/sGxyjsJ2XNtNuEjDyjpqdhMNh5aZ+XFOdThL46KBj27Uem4ggoezSYBxKWAil6Hu8HtwqesYw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -736,23 +711,12 @@ "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.10" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } } }, "@babel/types": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.0.tgz", - "integrity": "sha512-QkFPw68QqWU1/RVPyBe8SO7lXbPfjtqAxRYQKpFpaB8yMq7X2qAqfwK5LKoQufEkSmO5NQ70O6Kc3Afk03RwXw==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.2.tgz", + "integrity": "sha512-3Y6H8xlUlpbGR+XvawiH0UXehqydTmNmEpozWcXymqwcrwYAl5KMvKtQ+TF6f6E08V6Jur7v/ykdDSF+WDEIXQ==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -771,6 +735,23 @@ "normalize-path": "^2.1.1", "source-map": "^0.6.0", "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" + } + }, + "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 + } } }, "@gulp-sourcemaps/map-sources": { @@ -781,6 +762,17 @@ "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" + } + } } }, "@sindresorhus/is": { @@ -796,14 +788,6 @@ "dev": true, "requires": { "type-detect": "4.0.8" - }, - "dependencies": { - "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 - } } }, "@sinonjs/formatio": { @@ -816,9 +800,9 @@ } }, "@sinonjs/samsam": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.0.2.tgz", - "integrity": "sha512-m08g4CS3J6lwRQk1pj1EO+KEVWbrbXsmi9Pw0ySmrIbcVxVaedoFgLvFsV8wHLwh01EpROVz3KvVcD1Jmks9FQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.1.0.tgz", + "integrity": "sha512-IXio+GWY+Q8XUjHUOgK7wx8fpvr7IFffgyXb1bnJFfX3001KmHt35Zq4tp7MXZyjJPCLPuadesDYNk41LYtVjw==", "dev": true, "requires": { "@sinonjs/commons": "^1.0.2", @@ -827,9 +811,9 @@ } }, "@types/node": { - "version": "8.10.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.39.tgz", - "integrity": "sha512-rE7fktr02J8ybFf6eysife+WF+L4sAHWzw09DgdCebEu+qDwMvv4zl6Bc+825ttGZP73kCKxa3dhJOoGJ8+5mA==", + "version": "8.10.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.40.tgz", + "integrity": "sha512-RRSjdwz63kS4u7edIwJUn8NqKLLQ6LyqF/X4+4jp38MBT3Vwetewi2N4dgJEshLbDwNgOJXNYoOwzVZUSSLhkQ==", "dev": true }, "JSONStream": { @@ -923,20 +907,6 @@ "fast-deep-equal": "^1.0.0", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.3.0" - }, - "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": { @@ -983,9 +953,9 @@ } }, "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, "ansi-gray": { @@ -1003,6 +973,12 @@ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", "dev": true }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -1026,6 +1002,17 @@ "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, "append-buffer": { @@ -1264,9 +1251,9 @@ "dev": true }, "ast-types": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.7.tgz", - "integrity": "sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.12.2.tgz", + "integrity": "sha512-8c83xDLJM/dLDyXNLiR6afRRm4dPKN6KAnKqytRK3DBJul9lA+atxdQkNDkSVPdTqea5HiRq3lnnOIZ0MBpvdg==", "dev": true }, "async": { @@ -1376,15 +1363,6 @@ "supports-color": "^2.0.0" } }, - "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, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -1455,12 +1433,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "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 } } }, @@ -1485,12 +1457,6 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "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 } } }, @@ -2656,9 +2622,9 @@ } }, "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", + "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==", "dev": true }, "binaryextensions": { @@ -2997,12 +2963,6 @@ "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", "dev": true }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -3047,6 +3007,12 @@ "responselike": "1.0.2" }, "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", @@ -3114,9 +3080,9 @@ "dev": true }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "dev": true }, "camelcase-keys": { @@ -3138,9 +3104,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000930", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000930.tgz", - "integrity": "sha512-KD+pw9DderBLB8CGqBzYyFWpnrPVOEjsjargU/CvkNyg60od3cxSPTcTeMPhxJhDbkQPWvOz5BAyBzNl/St9vg==", + "version": "1.0.30000936", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000936.tgz", + "integrity": "sha512-orX4IdpbFhdNO7bTBhSbahp1EBpqzBc+qrvTRVUFfZgA4zta7TdM6PN5ZxkEUgDnz36m+PfWGcdX7AVfFWItJw==", "dev": true }, "caseless": { @@ -3177,17 +3143,6 @@ "get-func-name": "^2.0.0", "pathval": "^1.1.0", "type-detect": "^4.0.5" - }, - "dependencies": { - "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, - "requires": { - "type-detect": "^4.0.0" - } - } } }, "chai-nightwatch": { @@ -3205,6 +3160,21 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", "dev": true + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + } + }, + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true } } }, @@ -3265,24 +3235,23 @@ "dev": true }, "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.1.tgz", + "integrity": "sha512-gfw3p2oQV2wEt+8VuMlNsPjCxDxvvgnm/kz+uATu805mWVF8IJN7uz9DN7iBz+RMJISmiVbCOBFs9qBGMjtPfQ==", "dev": true, "requires": { "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", "glob-parent": "^3.1.0", - "inherits": "^2.0.1", + "inherits": "^2.0.3", "is-binary-path": "^1.0.0", "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", + "normalize-path": "^3.0.0", "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "readdirp": "^2.2.1", + "upath": "^1.1.0" } }, "cipher-base": { @@ -3547,6 +3516,14 @@ "dev": true, "requires": { "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "connect": { @@ -3649,9 +3626,9 @@ } }, "core-js": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.3.tgz", - "integrity": "sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ==" + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.4.tgz", + "integrity": "sha512-05qQ5hXShcqGkPZpXEFLIpxayZscVD2kuMBZewxiIPPEagukO4mqgPA9CWhUvFBJfy3ODdK2p9xyHh7FTU9/7A==" }, "core-util-is": { "version": "1.0.2", @@ -3711,12 +3688,14 @@ } }, "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=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } @@ -3755,6 +3734,14 @@ "source-map": "^0.6.1", "source-map-resolve": "^0.5.2", "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "currently-unhandled": { @@ -3822,9 +3809,9 @@ } }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -3839,6 +3826,17 @@ "debug": "3.X", "memoizee": "0.4.X", "object-assign": "4.X" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, "decamelize": { @@ -3863,20 +3861,12 @@ } }, "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "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, "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } + "type-detect": "^4.0.0" } }, "deep-is": { @@ -4195,6 +4185,12 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -4219,6 +4215,53 @@ } } }, + "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.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "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.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "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-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "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 + }, "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", @@ -4228,6 +4271,15 @@ "number-is-nan": "^1.0.0" } }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -4248,6 +4300,60 @@ } } }, + "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" + } + }, + "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.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "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.1.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": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -4294,6 +4400,12 @@ "ansi-regex": "^2.0.0" } }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", @@ -4378,9 +4490,9 @@ "dev": true }, "duplexify": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "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", @@ -4428,9 +4540,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.106.tgz", - "integrity": "sha512-eXX45p4q9CRxG0G8D3ZBZYSdN3DnrcZfrFvt6VUr1u7aKITEtRY/xwWzJ/UZcWXa7DMqPu/pYwuZ6Nm+bl0GmA==", + "version": "1.3.113", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz", + "integrity": "sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==", "dev": true }, "elliptic": { @@ -4825,16 +4937,24 @@ "text-table": "~0.2.0" }, "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "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": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" } }, "doctrine": { @@ -4845,28 +4965,6 @@ "requires": { "esutils": "^2.0.2" } - }, - "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, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "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 } } }, @@ -4922,16 +5020,59 @@ "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 - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "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.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "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.1.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 + }, + "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" @@ -4940,9 +5081,9 @@ } }, "eslint-plugin-import": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.15.0.tgz", - "integrity": "sha512-LEHqgR+RcnpGqYW7h9WMkPb/tP+ekKxWdQDztfTtZeV43IHF+X8lXU+1HOCcR4oXD24qRgEwNSxIweD5uNKGVg==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", + "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", "dev": true, "requires": { "contains-path": "^0.1.0", @@ -4966,6 +5107,15 @@ "ms": "2.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" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -4978,12 +5128,46 @@ "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" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "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.1.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": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -5063,6 +5247,16 @@ "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", "dev": true }, + "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, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -5183,13 +5377,13 @@ } }, "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", @@ -5442,9 +5636,9 @@ } }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { @@ -5576,12 +5770,12 @@ } }, "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "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": "^2.0.0" + "locate-path": "^3.0.0" } }, "findup-sync": { @@ -5656,13 +5850,13 @@ "dev": true }, "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "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, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" } }, "follow-redirects": { @@ -5850,8 +6044,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -5872,14 +6065,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5894,20 +6085,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6024,8 +6212,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6037,7 +6224,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6052,7 +6238,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6060,14 +6245,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6086,7 +6269,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6167,8 +6349,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6180,7 +6361,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6266,8 +6446,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -6303,7 +6482,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6323,7 +6501,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6367,14 +6544,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -6427,9 +6602,9 @@ } }, "fun-hooks": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.6.5.tgz", - "integrity": "sha512-DV6NAc6zuTukwIiq+4+iWr9bzD19hrbh60C25u3JEpXdzCtrR1UNB81jSBUJP12xKhdRMsoVrOBVnHeWZk6P9g==" + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.6.6.tgz", + "integrity": "sha512-Q+UdtGIpteY7Wd6z4T9MZ4GlqHtrRY1gCk+XuLyRxqgLsCaPKOOBY7EKJRFlXm1oQoNIrg2b7W55dEN55O8FBA==" }, "function-bind": { "version": "1.1.1", @@ -6468,10 +6643,13 @@ "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 + "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-uri": { "version": "2.0.3", @@ -6487,15 +6665,6 @@ "readable-stream": "3" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, "readable-stream": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", @@ -6681,9 +6850,9 @@ } }, "globals": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.10.0.tgz", - "integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", "dev": true }, "globals-docs": { @@ -6724,6 +6893,14 @@ "timed-out": "^4.0.1", "url-parse-lax": "^3.0.0", "url-to-options": "^1.0.1" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } } }, "graceful-fs": { @@ -6809,6 +6986,12 @@ "yargs": "^7.1.0" } }, + "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 + }, "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", @@ -6818,6 +7001,15 @@ "number-is-nan": "^1.0.0" } }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -6931,6 +7123,12 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", @@ -7400,6 +7598,14 @@ "source-map": "~0.6.0", "strip-bom-string": "1.X", "through2": "2.X" + }, + "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 + } } }, "gulp-uglify": { @@ -7416,24 +7622,6 @@ "through2": "^2.0.0", "uglify-js": "^3.0.5", "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", - "dev": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1" - } - } } }, "gulp-util": { @@ -7505,15 +7693,6 @@ "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", "dev": true }, - "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, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -7617,9 +7796,9 @@ } }, "handlebars": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", - "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", + "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", "dev": true, "requires": { "async": "^2.5.0", @@ -7637,23 +7816,11 @@ "lodash": "^4.17.10" } }, - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true, - "optional": true - }, - "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", - "dev": true, - "optional": true, - "requires": { - "commander": "~2.17.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 } } }, @@ -7674,9 +7841,9 @@ }, "dependencies": { "ajv": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", - "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -7684,6 +7851,18 @@ "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true } } }, @@ -7696,6 +7875,23 @@ "function-bind": "^1.1.1" } }, + "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, + "requires": { + "ansi-regex": "^2.0.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 + } + } + }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", @@ -7854,9 +8050,9 @@ "dev": true }, "highlight.js": { - "version": "9.13.1", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz", - "integrity": "sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.14.2.tgz", + "integrity": "sha512-Nc6YNECYpxyJABGYJAyw7dBAYbXEuIzwzkqoJnwbc1nIpCiN+3ioYf0XrBnLiyyG0JLuJhpPtt2iTSbXiKLoyA==", "dev": true }, "hmac-drbg": { @@ -7996,6 +8192,17 @@ "requires": { "agent-base": "^4.1.0", "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, "iconv-lite": { @@ -8098,6 +8305,14 @@ "requires": { "from2": "^2.1.1", "p-is-promise": "^1.1.0" + }, + "dependencies": { + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + } } }, "invariant": { @@ -8110,9 +8325,9 @@ } }, "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=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "ip": { @@ -8194,15 +8409,6 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", @@ -8704,6 +8910,15 @@ "source-map": "^0.5.3" }, "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -8712,12 +8927,6 @@ "requires": { "glob": "^7.1.3" } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true } } }, @@ -8815,9 +9024,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -8932,6 +9141,12 @@ "requires": { "glob": "^7.1.3" } + }, + "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 } } }, @@ -9089,12 +9304,6 @@ "requires": { "lodash": "^4.17.10" } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true } } }, @@ -9145,12 +9354,12 @@ } }, "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "^2.0.0" } }, "lcov-parse": { @@ -9247,12 +9456,12 @@ } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "p-locate": "^2.0.0", + "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, @@ -9459,12 +9668,6 @@ "lodash._isiterateecall": "^3.0.0" } }, - "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 - }, "lodash.defaults": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", @@ -9615,6 +9818,15 @@ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -9697,14 +9909,6 @@ "dev": true, "requires": { "vlq": "^0.2.1" - }, - "dependencies": { - "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true - } } }, "make-dir": { @@ -9740,6 +9944,15 @@ "kind-of": "^6.0.2" } }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -9884,12 +10097,14 @@ "dev": true }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", + "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" } }, "memoizee": { @@ -10422,34 +10637,29 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "nightwatch": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.18.tgz", - "integrity": "sha512-BKosRh/QqpCCMxjnfP+gb8KMQV0y//TNdYDjB0RrU1pXgx2Xjyp46bK8tQWRFfqaxWDj5EKYFIPgvxFBXodIOA==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.19.tgz", + "integrity": "sha512-Dl+EN4wFp927nn7KRkCIJ7b0Th9PVjiwflzqsoqJOwLPcLuzSBz4FYBvHXQtUkaL4/nELVgXurw/KXqj2gcFSg==", "dev": true, "requires": { "assertion-error": "^1.1.0", "chai-nightwatch": "0.2.1", "ejs": "^2.5.9", - "lodash.clone": "^3.0.3", + "lodash.clone": "3.0.3", "lodash.defaultsdeep": "^4.6.0", "lodash.merge": "^4.6.1", - "minimatch": "3.0.3", + "minimatch": "3.0.4", "mkpath": "1.0.0", "mocha": "^5.1.1", "optimist": "^0.6.1", "proxy-agent": "^3.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "dev": true, - "requires": { - "brace-expansion": "^1.0.0" - } - } } }, "nise": { @@ -10516,9 +10726,9 @@ } }, "node-releases": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.3.tgz", - "integrity": "sha512-6VrvH7z6jqqNFY200kdB6HdzkgM96Oaj9v3dqGfgp6mF+cHmU4wyQKZ2/WPDRVoR0Jz9KqbamaBN0ZhdUaysUQ==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.7.tgz", + "integrity": "sha512-bKdrwaqJUPHqlCzDD7so/R+Nk0jGv9a11ZhLrD9f6i947qGLrGAhU3OxRENa19QQmwzGy/g6zCDEuLGDO8HPvA==", "dev": true, "requires": { "semver": "^5.3.0" @@ -10534,25 +10744,22 @@ } }, "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", + "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "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" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true }, "normalize-url": { "version": "1.9.1", @@ -10646,9 +10853,9 @@ } }, "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", "dev": true }, "object-visit": { @@ -10856,6 +11063,12 @@ "pinkie-promise": "^2.0.0" } }, + "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 + }, "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", @@ -10865,6 +11078,15 @@ "number-is-nan": "^1.0.0" } }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -10978,6 +11200,12 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", @@ -11048,14 +11276,14 @@ "dev": true }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" } }, "os-tmpdir": { @@ -11070,6 +11298,12 @@ "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", "dev": true }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -11077,27 +11311,27 @@ "dev": true }, "p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", "dev": true }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { - "p-try": "^1.0.0" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "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": "^1.1.0" + "p-limit": "^2.0.0" } }, "p-timeout": { @@ -11110,9 +11344,9 @@ } }, "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.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, "pac-proxy-agent": { @@ -11137,6 +11371,15 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", @@ -11212,37 +11455,6 @@ "got": "^8.3.2", "mkdirp": "^0.5.1", "mocha": "^5.2.0" - }, - "dependencies": { - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "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, - "requires": { - "type-detect": "^4.0.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 - } } }, "parse-entities": { @@ -11319,9 +11531,9 @@ } }, "parse-node-version": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", - "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==", + "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 }, "parse-passwd": { @@ -11539,51 +11751,6 @@ "dev": true, "requires": { "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", - "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", - "dev": true - } } }, "plugin-error": { @@ -11684,6 +11851,17 @@ "pac-proxy-agent": "^3.0.0", "proxy-from-env": "^1.0.0", "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, "proxy-from-env": { @@ -11725,9 +11903,9 @@ } }, "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "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", @@ -11743,6 +11921,18 @@ "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" + }, + "dependencies": { + "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" + } + } } }, "punycode": { @@ -11878,6 +12068,51 @@ "requires": { "find-up": "^2.0.0", "read-pkg": "^3.0.0" + }, + "dependencies": { + "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" + } + }, + "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.1.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 + } } }, "readable-stream": { @@ -11974,34 +12209,34 @@ } }, "regexp-tree": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.0.tgz", - "integrity": "sha512-rHQv+tzu+0l3KS/ERabas1yK49ahNVxuH40WcPg53CzP5p8TgmmyBgHELLyJcvjhTD0e5ahSY6C76LbEVtr7cg==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.1.tgz", + "integrity": "sha512-HwRjOquc9QOwKTgbxvZTcddS5mlNlwePMQ3NFL8broajMLD5CXDAqas8Y5yxJH5QtZp5iRor3YCILd5pz71Cgw==", "dev": true, "requires": { "cli-table3": "^0.5.0", "colors": "^1.1.2", - "yargs": "^10.0.3" + "yargs": "^12.0.5" }, "dependencies": { "yargs": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", - "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "dev": true, "requires": { "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "os-locale": "^3.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^2.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^8.1.0" + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" } } } @@ -12448,32 +12683,6 @@ "dev": true, "requires": { "ajv": "^5.0.0" - }, - "dependencies": { - "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" - } - }, - "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 - } } }, "semver": { @@ -12688,12 +12897,6 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "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 } } }, @@ -12713,9 +12916,9 @@ } }, "smart-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", - "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", + "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==", "dev": true }, "snapdragon": { @@ -12766,12 +12969,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "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 } } }, @@ -12957,13 +13154,13 @@ } }, "socks": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.2.tgz", - "integrity": "sha512-g6wjBnnMOZpE0ym6e0uHSddz9p3a+WsBaaYQaBaSCJYvrC4IXykQR9MNGjLQf38e9iIIhp3b1/Zk8YZI3KGJ0Q==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.3.tgz", + "integrity": "sha512-+2r83WaRT3PXYoO/1z+RDEBE7Z2f9YcdQnJ0K/ncXXbV5gJ6wYfNAebYFYiiUjM6E4JyXnPY8cimwyvFYHVUUA==", "dev": true, "requires": { "ip": "^1.1.5", - "smart-buffer": "^4.0.1" + "smart-buffer": "4.0.2" } }, "socks-proxy-agent": { @@ -12992,9 +13189,9 @@ "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==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { @@ -13017,14 +13214,6 @@ "dev": true, "requires": { "source-map": "^0.5.6" - }, - "dependencies": { - "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-url": { @@ -13262,6 +13451,17 @@ "debug": "^3.1.0", "mkdirp": "^0.5.1", "readable-stream": "^2.3.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, "strict-uri-encode": { @@ -13314,14 +13514,6 @@ "dev": true, "requires": { "ansi-regex": "^3.0.0" - }, - "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 - } } }, "strip-bom": { @@ -13397,32 +13589,6 @@ "lodash": "^4.17.4", "slice-ansi": "1.0.0", "string-width": "^2.1.1" - }, - "dependencies": { - "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" - } - }, - "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 - } } }, "tapable": { @@ -13536,6 +13702,17 @@ "livereload-js": "^2.3.0", "object-assign": "^4.1.0", "qs": "^6.4.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, "tmp": { @@ -13739,14 +13916,44 @@ "dev": true }, "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "dev": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "commander": "~2.17.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "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 + } + } + }, + "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 + }, + "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": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" }, "dependencies": { "camelcase": { @@ -13766,11 +13973,16 @@ "wordwrap": "0.0.2" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "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.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } }, "window-size": { "version": "0.1.0", @@ -13798,31 +14010,6 @@ } } }, - "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 - }, - "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": { - "source-map": "^0.5.6", - "uglify-js": "^2.8.29", - "webpack-sources": "^1.0.1" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", @@ -14417,6 +14604,17 @@ "now-and-later": "^2.0.0", "remove-bom-buffer": "^3.0.0", "vinyl": "^2.0.0" + }, + "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" + } + } } }, "vinyl-sourcemaps-apply": { @@ -14426,16 +14624,14 @@ "dev": true, "requires": { "source-map": "^0.5.1" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -14502,9 +14698,9 @@ }, "dependencies": { "ajv": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", - "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -14514,9 +14710,9 @@ } }, "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "dev": true }, "ansi-regex": { @@ -14534,6 +14730,12 @@ "lodash": "^4.17.10" } }, + "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", @@ -14558,12 +14760,65 @@ } } }, + "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.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "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.0.1", + "get-stream": "^3.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" + } + }, + "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 + }, + "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-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 }, + "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 + }, "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", @@ -14573,12 +14828,27 @@ "number-is-nan": "^1.0.0" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -14591,6 +14861,60 @@ "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" + } + }, + "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.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "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.1.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": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -14636,12 +14960,6 @@ "read-pkg": "^2.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 - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -14660,6 +14978,12 @@ "has-flag": "^2.0.0" } }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -14762,6 +15086,14 @@ "requires": { "source-list-map": "^2.0.0", "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "webpack-stream": { @@ -15123,6 +15455,15 @@ "vm-browserify": "0.0.4" } }, + "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" + } + }, "os-browserify": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", @@ -15159,12 +15500,6 @@ "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", "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 - }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -15435,9 +15770,9 @@ "dev": true }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { @@ -15453,12 +15788,13 @@ "dev": true }, "yargs-parser": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", - "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, "yeast": { diff --git a/package.json b/package.json index 8437e395be5..84b5f961541 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.2.0-pre", + "version": "2.2.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 080beb23e61de51e051e06b18e967738538e7f90 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 12 Feb 2019 16:05:34 -0500 Subject: [PATCH 1013/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 84b5f961541..88cc52f8e95 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.2.0", + "version": "2.3.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3fa81fc01abd7f64e0b19017dbbbb97b8f4e15d2 Mon Sep 17 00:00:00 2001 From: Itay Nave <38345760+itaynave@users.noreply.github.com> Date: Wed, 13 Feb 2019 00:05:43 +0200 Subject: [PATCH 1014/1594] New bid adapter for aniview (#3522) * Support new aniview bid adapter * Support new aniview bid adapter * Support new aniview bid adapter * Support new aniview bid adapter * Fix Consent parameters --- modules/aniviewBidAdapter.js | 191 ++++++++++++++++++++ modules/aniviewBidAdapter.md | 36 ++++ test/spec/modules/aniviewBidAdapter_spec.js | 183 +++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 modules/aniviewBidAdapter.js create mode 100644 modules/aniviewBidAdapter.md create mode 100644 test/spec/modules/aniviewBidAdapter_spec.js diff --git a/modules/aniviewBidAdapter.js b/modules/aniviewBidAdapter.js new file mode 100644 index 00000000000..0d53ca8dded --- /dev/null +++ b/modules/aniviewBidAdapter.js @@ -0,0 +1,191 @@ +import { VIDEO } from '../src/mediaTypes'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { Renderer } from '../src/Renderer'; + +const BIDDER_CODE = 'aniview'; +const TTL = 600; + +function avRenderer(bid) { + bid.renderer.push(function() { + let eventCallback = bid && bid.renderer && bid.renderer.handleVideoEvent ? bid.renderer.handleVideoEvent : null; + window.aniviewRenderer.renderAd({ + id: bid.adUnitCode + '_' + bid.adId, + debug: window.location.href.indexOf('pbjsDebug') >= 0, + placement: bid.adUnitCode, + width: bid.width, + height: bid.height, + vastUrl: bid.vastUrl, + vastXml: bid.vastXml, + config: bid.params[0].rendererConfig, + eventsCallback: eventCallback, + bid: bid + }); + }); +} + +function newRenderer(bidRequest) { + const renderer = Renderer.install({ + url: 'https://player.aniview.com/script/6.1/prebidRenderer.js', + config: {}, + loaded: false, + }); + + try { + renderer.setRender(avRenderer); + } catch (err) { + } + + return renderer; +} + +function isBidRequestValid(bid) { + if (!bid.params || !bid.params.AV_PUBLISHERID || !bid.params.AV_CHANNELID) { return false; } + + return true; +} + +function buildRequests(validBidRequests, bidderRequest) { + let bidRequests = []; + + for (let i = 0; i < validBidRequests.length; i++) { + let bidRequest = validBidRequests[i]; + + if (!bidRequest.sizes || !bidRequest.sizes.length) { + bidRequest.sizes = [[640, 480]]; + } + + if (bidRequest.sizes.length === 2 && typeof bidRequest.sizes[0] === 'number' && typeof bidRequest.sizes[1] === 'number') { + let adWidth = bidRequest.sizes[0]; + let adHeight = bidRequest.sizes[1]; + bidRequest.sizes = [[adWidth, adHeight]]; + } + + for (let j = 0; j < bidRequest.sizes.length; j++) { + let size = bidRequest.sizes[j]; + let playerWidth; + let playerHeight; + if (size && size.length == 2) { + playerWidth = size[0]; + playerHeight = size[1]; + } else { + playerWidth = 640; + playerHeight = 480; + } + + let s2sParams = {}; + + for (var attrname in bidRequest.params) { + if (bidRequest.params.hasOwnProperty(attrname) && attrname.indexOf('AV_') == 0) { + s2sParams[attrname] = bidRequest.params[attrname]; + } + }; + + if (s2sParams.AV_APPPKGNAME && !s2sParams.AV_URL) { s2sParams.AV_URL = s2sParams.AV_APPPKGNAME; } + if (!s2sParams.AV_IDFA && !s2sParams.AV_URL) { s2sParams.AV_URL = utils.getTopWindowUrl(); } + if (s2sParams.AV_IDFA && !s2sParams.AV_AID) { s2sParams.AV_AID = s2sParams.AV_IDFA; } + if (s2sParams.AV_AID && !s2sParams.AV_IDFA) { s2sParams.AV_IDFA = s2sParams.AV_AID; } + + s2sParams.pbjs = 1; + s2sParams.cb = Math.floor(Math.random() * 999999999); + s2sParams.AV_WIDTH = playerWidth; + s2sParams.AV_HEIGHT = playerHeight; + s2sParams.s2s = '1'; + s2sParams.bidId = bidRequest.bidId; + s2sParams.bidWidth = playerWidth; + s2sParams.bidHeight = playerHeight; + + if (bidderRequest && bidderRequest.gdprConsent) { + if (bidderRequest.gdprConsent.gdprApplies) { + s2sParams.AV_GDPR = 1; + s2sParams.AV_CONSENT = bidderRequest.gdprConsent.consentString + } + } + + let serverDomain = bidRequest.params && bidRequest.params.serverDomain ? bidRequest.params.serverDomain : 'gov.aniview.com'; + let serverUrl = 'https://' + serverDomain + '/api/adserver/vast3/'; + + bidRequests.push({ + method: 'GET', + url: serverUrl, + data: s2sParams, + bidRequest + }); + } + } + + return bidRequests; +} +function getCpmData(xml) { + let ret = {cpm: 0, currency: 'USD'}; + if (xml) { + let ext = xml.getElementsByTagName('Extensions'); + if (ext && ext.length > 0) { + ext = ext[0].getElementsByTagName('Extension'); + if (ext && ext.length > 0) { + for (var i = 0; i < ext.length; i++) { + if (ext[i].getAttribute('type') == 'ANIVIEW') { + let price = ext[i].getElementsByTagName('Cpm'); + if (price && price.length == 1) { + ret.cpm = price[0].textContent; + } + break; + } + } + } + } + } + return ret; +} +function interpretResponse(serverResponse, bidRequest) { + let bidResponses = []; + if (serverResponse && serverResponse.body) { + if (serverResponse.error) { + return bidResponses; + } else { + try { + let bidResponse = {}; + if (bidRequest && bidRequest.data && bidRequest.data.bidId && bidRequest.data.bidId !== '') { + let xmlStr = serverResponse.body; + let xml = new window.DOMParser().parseFromString(xmlStr, 'text/xml'); + if (xml && xml.getElementsByTagName('parsererror').length == 0) { + let cpmData = getCpmData(xml); + if (cpmData && cpmData.cpm > 0) { + bidResponse.requestId = bidRequest.data.bidId; + bidResponse.bidderCode = BIDDER_CODE; + bidResponse.ad = ''; + bidResponse.cpm = cpmData.cpm; + bidResponse.width = bidRequest.data.AV_WIDTH; + bidResponse.height = bidRequest.data.AV_HEIGHT; + bidResponse.ttl = TTL; + bidResponse.creativeId = xml.getElementsByTagName('Ad') && xml.getElementsByTagName('Ad')[0] && xml.getElementsByTagName('Ad')[0].getAttribute('id') ? xml.getElementsByTagName('Ad')[0].getAttribute('id') : 'creativeId'; + bidResponse.currency = cpmData.currency; + bidResponse.netRevenue = true; + var blob = new Blob([xmlStr], { + type: 'application/xml' + }); + bidResponse.vastUrl = window.URL.createObjectURL(blob); + bidResponse.vastXml = xmlStr; + bidResponse.mediaType = VIDEO; + if (bidRequest.bidRequest && bidRequest.bidRequest.mediaTypes && bidRequest.bidRequest.mediaTypes.video && bidRequest.bidRequest.mediaTypes.video.context === 'outstream') { bidResponse.renderer = newRenderer(bidRequest); } + + bidResponses.push(bidResponse); + } + } else {} + } else {} + } catch (e) {} + } + } else {} + + return bidResponses; +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [VIDEO], + isBidRequestValid, + buildRequests, + interpretResponse +} + +registerBidder(spec); diff --git a/modules/aniviewBidAdapter.md b/modules/aniviewBidAdapter.md new file mode 100644 index 00000000000..412b8fc3016 --- /dev/null +++ b/modules/aniviewBidAdapter.md @@ -0,0 +1,36 @@ +# Overview + +``` +Module Name: ANIVIEW Bidder Adapter +Module Type: Bidder Adapter +Maintainer: support@aniview.com +``` + +# Description + +Connects to ANIVIEW Ad server for bids. + +ANIVIEW bid adapter supports Video ads currently. + +For more information about [Aniview](http://www.aniview.com), please contact [support@aniview.com](support@aniview.com). + +# Sample Ad Unit: For Publishers +```javascript +var videoAdUnit = [ +{ + code: 'video1', + sizes: [ + [300, 250], + [640, 480] + ], + bids: [{ + bidder: 'aniview', + params: { + AV_PUBLISHERID: '55b78633181f4603178b4568', + AV_CHANNELID: '55b7904d181f46410f8b4568' + } + }] +}]; +``` + +``` diff --git a/test/spec/modules/aniviewBidAdapter_spec.js b/test/spec/modules/aniviewBidAdapter_spec.js new file mode 100644 index 00000000000..ce8a34509c4 --- /dev/null +++ b/test/spec/modules/aniviewBidAdapter_spec.js @@ -0,0 +1,183 @@ +import { spec } from 'modules/aniviewBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +const { expect } = require('chai'); + +describe('ANIVIEW Bid Adapter Test', 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': 'aniview', + 'params': { + 'AV_PUBLISHERID': '123456', + 'AV_CHANNELID': '123456' + }, + 'adUnitCode': 'video1', + 'sizes': [[300, 250], [640, 480]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'requestId': 'a09c66c3-53e3-4428-b296-38fc08e7cd2a', + 'transactionId': 'd6f6b392-54a9-454c-85fb-a2fd882c4a2d', + }; + + 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 = { + something: 'is wrong' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const ENDPOINT = 'https://v.lkqd.net/ad'; + let bid2Requests = [ + { + 'bidder': 'aniview', + 'params': { + 'AV_PUBLISHERID': '123456', + 'AV_CHANNELID': '123456' + }, + 'adUnitCode': 'test1', + 'sizes': [[300, 250], [640, 480]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'requestId': 'a09c66c3-53e3-4428-b296-38fc08e7cd2a', + 'transactionId': 'd6f6b392-54a9-454c-85fb-a2fd882c4a2d', + } + ]; + let bid1Request = [ + { + 'bidder': 'aniview', + 'params': { + 'AV_PUBLISHERID': '123456', + 'AV_CHANNELID': '123456' + }, + 'adUnitCode': 'test1', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'requestId': 'a09c66c3-53e3-4428-b296-38fc08e7cd2a', + 'transactionId': 'd6f6b392-54a9-454c-85fb-a2fd882c4a2d', + } + ]; + + it('Test 2 requests', function () { + const requests = spec.buildRequests(bid2Requests); + expect(requests.length).to.equal(2); + const r1 = requests[0]; + const d1 = requests[0].data; + expect(d1).to.have.property('AV_PUBLISHERID'); + expect(d1.AV_PUBLISHERID).to.equal('123456'); + expect(d1).to.have.property('AV_CHANNELID'); + expect(d1.AV_CHANNELID).to.equal('123456'); + expect(d1).to.have.property('AV_WIDTH'); + expect(d1.AV_WIDTH).to.equal(300); + expect(d1).to.have.property('AV_HEIGHT'); + expect(d1.AV_HEIGHT).to.equal(250); + expect(d1).to.have.property('AV_URL'); + expect(d1).to.have.property('cb'); + expect(d1).to.have.property('s2s'); + expect(d1.s2s).to.equal('1'); + expect(d1).to.have.property('pbjs'); + expect(d1.pbjs).to.equal(1); + expect(r1).to.have.property('url'); + expect(r1.url).to.contain('https://gov.aniview.com/api/adserver/vast3/'); + const r2 = requests[1]; + const d2 = requests[1].data; + expect(d2).to.have.property('AV_PUBLISHERID'); + expect(d2.AV_PUBLISHERID).to.equal('123456'); + expect(d2).to.have.property('AV_CHANNELID'); + expect(d2.AV_CHANNELID).to.equal('123456'); + expect(d2).to.have.property('AV_WIDTH'); + expect(d2.AV_WIDTH).to.equal(640); + expect(d2).to.have.property('AV_HEIGHT'); + expect(d2.AV_HEIGHT).to.equal(480); + expect(d2).to.have.property('AV_URL'); + expect(d2).to.have.property('cb'); + expect(d2).to.have.property('s2s'); + expect(d2.s2s).to.equal('1'); + expect(d2).to.have.property('pbjs'); + expect(d2.pbjs).to.equal(1); + expect(r2).to.have.property('url'); + expect(r2.url).to.contain('https://gov.aniview.com/api/adserver/vast3/'); + }); + + it('Test 1 request', function () { + const requests = spec.buildRequests(bid1Request); + expect(requests.length).to.equal(1); + const r = requests[0]; + const d = requests[0].data; + expect(d).to.have.property('AV_PUBLISHERID'); + expect(d.AV_PUBLISHERID).to.equal('123456'); + expect(d).to.have.property('AV_CHANNELID'); + expect(d.AV_CHANNELID).to.equal('123456'); + expect(d).to.have.property('AV_WIDTH'); + expect(d.AV_WIDTH).to.equal(640); + expect(d).to.have.property('AV_HEIGHT'); + expect(d.AV_HEIGHT).to.equal(480); + expect(d).to.have.property('AV_URL'); + expect(d).to.have.property('cb'); + expect(d).to.have.property('s2s'); + expect(d.s2s).to.equal('1'); + expect(d).to.have.property('pbjs'); + expect(d.pbjs).to.equal(1); + expect(r).to.have.property('url'); + expect(r.url).to.contain('https://gov.aniview.com/api/adserver/vast3/'); + }); + }); + + describe('interpretResponse', function () { + let bidRequest = { + 'url': 'https://gov.aniview.com/api/adserver/vast3/', + 'data': { + 'bidId': '253dcb69fb2577', + AV_PUBLISHERID: '55b78633181f4603178b4568', + AV_CHANNELID: '55b7904d181f46410f8b4568', + } + }; + let serverResponse = {}; + serverResponse.body = 'FORDFORD00:00:15'; + + it('Check bid interpretResponse', function () { + const BIDDER_CODE = 'aniview'; + let bidResponses = spec.interpretResponse(serverResponse, bidRequest); + expect(bidResponses.length).to.equal(1); + let bidResponse = bidResponses[0]; + expect(bidResponse.requestId).to.equal(bidRequest.data.bidId); + expect(bidResponse.bidderCode).to.equal(BIDDER_CODE); + expect(bidResponse.cpm).to.equal('2'); + expect(bidResponse.ttl).to.equal(600); + expect(bidResponse.currency).to.equal('USD'); + expect(bidResponse.netRevenue).to.equal(true); + expect(bidResponse.mediaType).to.equal('video'); + }); + + it('safely handles XML parsing failure from invalid bid response', function () { + let invalidServerResponse = {}; + invalidServerResponse.body = ''; + + let result = spec.interpretResponse(invalidServerResponse, bidRequest); + expect(result.length).to.equal(0); + }); + + it('handles nobid responses', function () { + let nobidResponse = {}; + nobidResponse.body = ''; + + let result = spec.interpretResponse(nobidResponse, bidRequest); + expect(result.length).to.equal(0); + }); + }); +}); From 6b1ef58ad94edf1408b2836796acd2575b6b4bad Mon Sep 17 00:00:00 2001 From: Alexandr Date: Wed, 13 Feb 2019 01:12:16 +0200 Subject: [PATCH 1015/1594] New Bid Adapter DecenterAds (#3468) * #feature (modules/decenteradsBidAdapter.js, modules/decenteradsBidAdapter.md,test/spec/modules/decenteradsBidAdapter_spec.js) added DecenterAds adapter * #fix (modules/decenteradsBidAdapter.js) minor fixes --- modules/decenteradsBidAdapter.js | 90 ++++++++ modules/decenteradsBidAdapter.md | 27 +++ .../modules/decenteradsBidAdapter_spec.js | 207 ++++++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 modules/decenteradsBidAdapter.js create mode 100644 modules/decenteradsBidAdapter.md create mode 100644 test/spec/modules/decenteradsBidAdapter_spec.js diff --git a/modules/decenteradsBidAdapter.js b/modules/decenteradsBidAdapter.js new file mode 100644 index 00000000000..65d3032d3f8 --- /dev/null +++ b/modules/decenteradsBidAdapter.js @@ -0,0 +1,90 @@ +import { registerBidder } from '../src/adapters/bidderFactory' +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes' +import * as utils from '../src/utils' + +const BIDDER_CODE = 'decenterads' +const URL = '//supply.decenterads.com/?c=o&m=multi' +const URL_SYNC = '//supply.decenterads.com/?c=o&m=cookie' + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO, NATIVE], + + isBidRequestValid: function (opts) { + return Boolean(opts.bidId && opts.params && !isNaN(opts.params.placementId)) + }, + + buildRequests: function (validBidRequests) { + validBidRequests = validBidRequests || [] + let winTop = window + try { + window.top.location.toString() + winTop = window.top + } catch (e) { utils.logMessage(e) } + + const location = utils.getTopWindowLocation() + const placements = [] + + for (let i = 0; i < validBidRequests.length; i++) { + const p = validBidRequests[i] + + placements.push({ + placementId: p.params.placementId, + bidId: p.bidId, + traffic: p.params.traffic || BANNER + }) + } + + return { + method: 'POST', + url: URL, + data: { + deviceWidth: winTop.screen.width, + deviceHeight: winTop.screen.height, + language: (navigator && navigator.language) ? navigator.language : '', + secure: +(location.protocol === 'https:'), + host: location.host, + page: location.pathname, + placements: placements + } + } + }, + + interpretResponse: function (opts) { + const body = opts.body + const response = [] + + for (let i = 0; i < body.length; i++) { + const item = body[i] + if (isBidResponseValid(item)) { + delete item.mediaType + response.push(item) + } + } + + return response + }, + + getUserSyncs: function (syncOptions, serverResponses) { + return [{ type: 'image', url: URL_SYNC }] + } +} + +registerBidder(spec) + +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.title && bid.image && bid.impressionTrackers) + default: + return false + } +} diff --git a/modules/decenteradsBidAdapter.md b/modules/decenteradsBidAdapter.md new file mode 100644 index 00000000000..04260a9da58 --- /dev/null +++ b/modules/decenteradsBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +``` +Module Name: DecenterAds Bidder Adapter +Module Type: Bidder Adapter +Maintainer: publishers@decenterads.com +``` + +# Description + +Module that connects to DecenterAds' demand sources + +# Test Parameters +``` + var adUnits = [{ + code: 'placementId_0', + sizes: [[300, 250]], + bids: [{ + bidder: 'decenterads', + params: { + placementId: 0, + traffic: 'banner' + } + }] + } + ]; +``` diff --git a/test/spec/modules/decenteradsBidAdapter_spec.js b/test/spec/modules/decenteradsBidAdapter_spec.js new file mode 100644 index 00000000000..3c8569b3b61 --- /dev/null +++ b/test/spec/modules/decenteradsBidAdapter_spec.js @@ -0,0 +1,207 @@ +import { expect } from 'chai' +import { spec } from '../../../modules/decenteradsBidAdapter' +import { deepStrictEqual, notEqual, ok, strictEqual } from 'assert' + +describe('DecenteradsAdapter', () => { + const bid = { + bidId: '9ec5b177515ee2e5', + bidder: 'decenterads', + params: { + placementId: 0, + traffic: 'banner' + } + } + + describe('isBidRequestValid', () => { + it('Should return true if there are bidId, params and placementId parameters present', () => { + strictEqual(true, spec.isBidRequestValid(bid)) + }) + + it('Should return false if at least one of parameters is not present', () => { + const b = { ...bid } + delete b.params.placementId + strictEqual(false, spec.isBidRequestValid(b)) + }) + }) + + describe('buildRequests', () => { + const serverRequest = spec.buildRequests([bid]) + + it('Creates a ServerRequest object with method, URL and data', () => { + ok(serverRequest) + ok(serverRequest.method) + ok(serverRequest.url) + ok(serverRequest.data) + }) + + it('Returns POST method', () => { + strictEqual('POST', serverRequest.method) + }) + + it('Returns valid URL', () => { + strictEqual('//supply.decenterads.com/?c=o&m=multi', serverRequest.url) + }) + + it('Returns valid data if array of bids is valid', () => { + const { data } = serverRequest + strictEqual('object', typeof data) + deepStrictEqual(['deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements'], Object.keys(data)) + strictEqual('number', typeof data.deviceWidth) + strictEqual('number', typeof data.deviceHeight) + strictEqual('string', typeof data.language) + strictEqual('string', typeof data.host) + strictEqual('string', typeof data.page) + notEqual(-1, [0, 1].indexOf(data.secure)) + + const placement = data.placements[0] + deepStrictEqual(['placementId', 'bidId', 'traffic'], Object.keys(placement)) + strictEqual(0, placement.placementId) + strictEqual('9ec5b177515ee2e5', placement.bidId) + strictEqual('banner', placement.traffic) + }) + + it('Returns empty data if no valid requests are passed', () => { + const { placements } = spec.buildRequests([]).data + + expect(spec.buildRequests([]).data.placements).to.be.an('array') + strictEqual(0, placements.length) + }) + }) + + describe('interpretResponse', () => { + const validData = [ + { + body: [{ + mediaType: 'banner', + width: 300, + height: 250, + cpm: 0.4, + ad: 'Test', + requestId: '9ec5b177515ee2e5', + ttl: 120, + creativeId: '2', + netRevenue: true, + currency: 'USD', + dealId: '1' + }] + }, + { + body: [{ + vastUrl: 'decenterads.com', + mediaType: 'video', + cpm: 0.5, + requestId: '9ec5b177515ee2e5', + ttl: 120, + creativeId: '2', + netRevenue: true, + currency: 'USD', + dealId: '1' + }] + }, + { + body: [{ + mediaType: 'native', + clickUrl: 'decenterads.com', + title: 'Test', + image: 'decenterads.com', + creativeId: '2', + impressionTrackers: ['decenterads.com'], + ttl: 120, + cpm: 0.4, + requestId: '9ec5b177515ee2e5', + netRevenue: true, + currency: 'USD', + }] + } + ] + + for (const obj of validData) { + const { mediaType } = obj.body[0] + + it(`Should interpret ${mediaType} response`, () => { + const response = spec.interpretResponse(obj) + + expect(response).to.be.an('array') + strictEqual(1, response.length) + + const copy = { ...obj.body[0] } + delete copy.mediaType + deepStrictEqual(copy, response[0]) + }) + } + + const invalidData = [ + { + body: [{ + width: 300, + cpm: 0.4, + ad: 'Test', + requestId: '9ec5b177515ee2e5', + ttl: 120, + creativeId: '2', + netRevenue: true, + currency: 'USD', + dealId: '1' + }] + }, + { + body: [{ + mediaType: 'video', + cpm: 0.5, + requestId: '9ec5b177515ee2e5', + ttl: 120, + creativeId: '2', + netRevenue: true, + currency: 'USD', + dealId: '1' + }] + }, + { + body: [{ + mediaType: 'native', + clickUrl: 'decenterads.com', + title: 'Test', + impressionTrackers: ['decenterads.com'], + ttl: 120, + requestId: '9ec5b177515ee2e5', + creativeId: '2', + netRevenue: true, + currency: 'USD', + }] + } + ] + + for (const obj of invalidData) { + const { mediaType } = obj.body[0] + + it(`Should return an empty array if invalid ${mediaType} response is passed `, () => { + const response = spec.interpretResponse(obj) + + expect(response).to.be.an('array') + strictEqual(0, response.length) + }) + } + + it('Should return an empty array if invalid response is passed', () => { + const response = spec.interpretResponse({ + body: [{ + ttl: 120, + creativeId: '2', + netRevenue: true, + currency: 'USD', + dealId: '1' + }] + }) + + expect(response).to.be.an('array') + strictEqual(0, response.length) + }) + }) + + describe('getUserSyncs', () => { + it('Returns valid URL and type', () => { + const expectedResult = [{ type: 'image', url: '//supply.decenterads.com/?c=o&m=cookie' }] + deepStrictEqual(expectedResult, spec.getUserSyncs()) + }) + }) +}) From ba0313712bdd2b6f1f2fdebb69eae6cb630bbd4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deivydas=20=C5=A0abaras?= Date: Wed, 13 Feb 2019 14:14:17 +0000 Subject: [PATCH 1016/1594] Because bidId is not equal adId bid was always undefined inside OnBidResponse event and error was thrown. This issue was fixed (#3546) --- modules/openxAnalyticsAdapter.js | 25 ++++++++++++------- .../modules/openxAnalyticsAdapter_spec.js | 12 ++++++--- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/modules/openxAnalyticsAdapter.js b/modules/openxAnalyticsAdapter.js index 41a986f4d66..2afd9a34d83 100644 --- a/modules/openxAnalyticsAdapter.js +++ b/modules/openxAnalyticsAdapter.js @@ -47,11 +47,12 @@ function onBidRequested({ auctionId, auctionStart, bids, start }) { function onBidResponse({ auctionId, adUnitCode, - adId: bidId, + requestId: bidId, cpm, creativeId, responseTimestamp, - ts + ts, + adId }) { const adUnit = auctionMap[auctionId]['adUnitMap'][adUnitCode]; const bid = adUnit['bidMap'][bidId]; @@ -59,6 +60,7 @@ function onBidResponse({ bid.creativeId = creativeId; bid.responseTimestamp = responseTimestamp; bid.ts = ts; + bid.adId = adId; } function onBidTimeout(args) { @@ -71,7 +73,7 @@ function onBidTimeout(args) { }); } -function onBidWon({ auctionId, adUnitCode, adId: bidId }) { +function onBidWon({ auctionId, adUnitCode, requestId: bidId }) { const adUnit = auctionMap[auctionId]['adUnitMap'][adUnitCode]; const bid = adUnit['bidMap'][bidId]; bid.won = true; @@ -87,9 +89,12 @@ function onSlotLoaded({ slot }) { targeting ); - const bidId = slot.getTargeting('hb_adid')[0]; - const adUnit = getAdUnitByBidId(bidId); + const adId = slot.getTargeting('hb_adid')[0]; + if (!adId) { + return; + } + const adUnit = getAdUnitByAdId(adId); if (!adUnit) { return; } @@ -106,14 +111,16 @@ function onSlotLoaded({ slot }) { sendEvent(data); } -function getAdUnitByBidId(bidId) { +function getAdUnitByAdId(adId) { let result; utils._map(auctionMap, value => value).forEach(auction => { utils._map(auction.adUnitMap, value => value).forEach(adUnit => { - if (bidId in adUnit.bidMap) { - result = adUnit; - } + utils._map(adUnit.bidMap, value => value).forEach(bid => { + if (adId === bid.adId) { + result = adUnit; + } + }) }); }); diff --git a/test/spec/modules/openxAnalyticsAdapter_spec.js b/test/spec/modules/openxAnalyticsAdapter_spec.js index 7b73b11887f..88ab3c4c580 100644 --- a/test/spec/modules/openxAnalyticsAdapter_spec.js +++ b/test/spec/modules/openxAnalyticsAdapter_spec.js @@ -59,7 +59,8 @@ describe('openx analytics adapter', function() { }; const bidResponseOpenX = { - adId: '2f0c647b904e25', + requestId: '2f0c647b904e25', + adId: '33dddbb61d359a', adUnitCode: 'div-1', auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79', cpm: 0.5, @@ -69,7 +70,8 @@ describe('openx analytics adapter', function() { }; const bidResponseCloseX = { - adId: '43d454020e9409', + requestId: '43d454020e9409', + adId: '43dddbb61d359a', adUnitCode: 'div-1', auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79', cpm: 0.3, @@ -95,13 +97,15 @@ describe('openx analytics adapter', function() { }; const bidWonOpenX = { - adId: '2f0c647b904e25', + requestId: '2f0c647b904e25', + adId: '33dddbb61d359a', adUnitCode: 'div-1', auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79' }; const bidWonCloseX = { - adId: '43d454020e9409', + requestId: '43d454020e9409', + adId: '43dddbb61d359a', adUnitCode: 'div-1', auctionId: 'add5eb0f-587d-441d-86ec-bbb722c70f79' }; From fb1aa57ddab8c50a01d73e260a82bb9d99d6cae7 Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Thu, 14 Feb 2019 03:42:24 +0800 Subject: [PATCH 1017/1594] fix IAS issue (#3554) IAS is no passing their key when the currency module is used. Indeed the letter case is important as the module will look for "USD" not "usd" and then return no bid --- modules/iasBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/iasBidAdapter.js b/modules/iasBidAdapter.js index 5fa34a4a609..bda5af1f4ec 100644 --- a/modules/iasBidAdapter.js +++ b/modules/iasBidAdapter.js @@ -103,7 +103,7 @@ function interpretResponse(serverResponse, request) { height: 200, creativeId: 434, dealId: 42, - currency: 'usd', + currency: 'USD', netRevenue: true, ttl: 360 }; From 520e0a8a91fc51b9d28bfc8ff1ef34c4ce178efc Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Thu, 14 Feb 2019 09:15:22 -0500 Subject: [PATCH 1018/1594] Sonobi - Outstream Support (#3559) * added support for outstream in sonobi adapter * added remote url for outstream renderer * renamed remote url for sbi renderer outstream * outstream renderer is not loaded by default * remove unsed import * getting outstream size from params.sizes * sizes is an array of arrays * added unit test for outstream bid response * mediaType is video if there is no mediaType context and sbi_ct is video * simplify if else conditions around video mediaTypes * fixed issue when calling Array.find in IE11 * fixed issue in IE11 and mac when using for of... --- modules/sonobiBidAdapter.js | 84 ++++++++++++++++++++-- test/spec/modules/sonobiBidAdapter_spec.js | 52 +++++++++++++- 2 files changed, 129 insertions(+), 7 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index e1059ad5930..ab4058b1978 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -1,12 +1,14 @@ import { registerBidder } from '../src/adapters/bidderFactory'; -import { parseSizesInput, logError, generateUUID, isEmpty, deepAccess } from '../src/utils'; +import { parseSizesInput, logError, generateUUID, isEmpty, deepAccess, logWarn, logMessage } from '../src/utils'; import { BANNER, VIDEO } from '../src/mediaTypes'; import { config } from '../src/config'; +import { Renderer } from '../src/Renderer'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; const PAGEVIEW_ID = generateUUID(); const SONOBI_DIGITRUST_KEY = 'fhnS5drwmH'; +const OUTSTREAM_REDNERER_URL = 'https://mtrx.go.sonobi.com/sbi_outstream_renderer.js'; export const spec = { code: BIDDER_CODE, @@ -107,7 +109,6 @@ export const spec = { const bidResponse = serverResponse.body; const bidsReturned = []; const referrer = bidderRequest.data.ref; - if (Object.keys(bidResponse.slots).length === 0) { return bidsReturned; } @@ -115,7 +116,16 @@ export const spec = { Object.keys(bidResponse.slots).forEach(slot => { const bid = bidResponse.slots[slot]; const bidId = _getBidIdFromTrinityKey(slot); - const mediaType = (bid.sbi_ct === 'video') ? 'video' : null; + const bidRequest = _findBidderRequest(bidderRequest.bidderRequests, bidId); + let mediaType = null; + if (bid.sbi_ct === 'video') { + mediaType = 'video'; + const context = deepAccess(bidRequest, 'mediaTypes.video.context'); + if (context === 'outstream') { + mediaType = 'outstream'; + } + } + const createCreative = _creative(mediaType, referrer); if (bid.sbi_aid && bid.sbi_mouse && bid.sbi_size) { const [ @@ -145,6 +155,21 @@ export const spec = { delete bids.ad; delete bids.width; delete bids.height; + } else if (mediaType === 'outstream' && bidRequest) { + bids.mediaType = 'video'; + bids.vastUrl = createCreative(bidResponse.sbi_dc, bid.sbi_aid); + bids.renderer = newRenderer(bidRequest.adUnitCode, bids, deepAccess( + bidRequest, + 'renderer.options' + )); + let videoSize = deepAccess(bidRequest, 'params.sizes'); + if (Array.isArray(videoSize) && Array.isArray(videoSize[0])) { // handle case of multiple sizes + videoSize = videoSize[0] // Only take the first size for outstream + } + if (videoSize) { + bids.width = videoSize[0]; + bids.height = videoSize[1]; + } } bidsReturned.push(bids); } @@ -170,6 +195,14 @@ export const spec = { } }; +function _findBidderRequest(bidderRequests, bidId) { + for (let i = 0; i < bidderRequests.length; i++) { + if (bidderRequests[i].bidId === bidId) { + return bidderRequests[i]; + } + } +} + function _validateSize (bid) { if (bid.params.sizes) { return parseSizesInput(bid.params.sizes).join(','); @@ -192,7 +225,7 @@ function _validateFloor (bid) { } const _creative = (mediaType, referer) => (sbiDc, sbiAid) => { - if (mediaType === 'video') { + if (mediaType === 'video' || mediaType === 'outstream') { return _videoCreative(sbiDc, sbiAid, referer) } const src = `https://${sbiDc}apex.go.sonobi.com/sbi.js?aid=${sbiAid}&as=null&ref=${encodeURIComponent(referer)}`; @@ -247,4 +280,47 @@ function _getDigiTrustObject(key) { return digiTrustId; } +function newRenderer(adUnitCode, bid, rendererOptions = {}) { + const renderer = Renderer.install({ + id: bid.aid, + url: OUTSTREAM_REDNERER_URL, + config: rendererOptions, + loaded: false, + adUnitCode + }); + + try { + renderer.setRender(outstreamRender); + } catch (err) { + logWarn('Prebid Error calling setRender on renderer', err); + } + + renderer.setEventHandlers({ + impression: () => logMessage('Sonobi outstream video impression event'), + loaded: () => logMessage('Sonobi outstream video loaded event'), + ended: () => { + logMessage('Sonobi outstream renderer video event'); + // document.querySelector(`#${adUnitCode}`).style.display = 'none'; + } + }); + return renderer; +} + +function outstreamRender(bid) { + // push to render queue because SbiOutstreamRenderer may not be loaded yet + bid.renderer.push(() => { + const [ + width, + height + ] = bid.getSize().split('x'); + const renderer = new window.SbiOutstreamRenderer(); + renderer.init({ + vastUrl: bid.vastUrl, + height, + width, + }); + renderer.setRootElement(bid.adUnitCode); + }); +} + registerBidder(spec); diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 65ad5b352ff..4fe9d92b2d4 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -344,6 +344,20 @@ describe('SonobiBidAdapter', function () { 'adUnitCode': 'adunit-code-3', 'sizes': [[120, 600], [300, 600], [160, 600]], 'bidId': '30b31c1838de1g' + }, + { + 'bidId': '30b31c1838de1zzzz', + 'adUnitCode': 'outstream-dom-id', + bidder: 'sonobi', + mediaTypes: { + video: { + context: 'outstream' + } + }, + params: { + placement_id: '92e95368e86639dbd86d', + sizes: [[640, 480]] + } } ] }; @@ -374,6 +388,17 @@ describe('SonobiBidAdapter', function () { 'sbi_mouse': 1.07, }, '/7780971/sparks_prebid_LB|30b31c1838de1g': {}, + '30b31c1838de1zzzz': { + sbi_aid: 'force_1550072228_da1c5d030cb49150c5db8a2136175755', + sbi_apoc: 'premium', + sbi_ct: 'video', + sbi_curr: 'USD', + sbi_mouse: 1.25, + sbi_size: 'preroll', + 'sbi_crid': 'somecrid', + + } + }, 'sbi_dc': 'mco-1-', 'sbi_px': [{ @@ -404,13 +429,14 @@ describe('SonobiBidAdapter', function () { 'cpm': 1.25, 'width': 300, 'height': 250, - 'ad': 'https://mco-1-apex.go.sonobi.com/vast.xml?vid=30292e432662bd5f86d90774b944b038&ref=http%3A%2F%2Flocalhost%2F', + 'vastUrl': 'https://mco-1-apex.go.sonobi.com/vast.xml?vid=30292e432662bd5f86d90774b944b038&ref=http%3A%2F%2Flocalhost%2F', 'ttl': 500, 'creativeId': '30292e432662bd5f86d90774b944b038', 'netRevenue': true, 'currency': 'USD', 'dealId': 'dozerkey', - 'aid': '30292e432662bd5f86d90774b944b038' + 'aid': '30292e432662bd5f86d90774b944b038', + 'mediaType': 'video' }, { 'requestId': '30b31c1838de1g', @@ -424,6 +450,21 @@ describe('SonobiBidAdapter', function () { 'currency': 'USD', 'aid': '30292e432662bd5f86d90774b944b038' }, + { + 'requestId': '30b31c1838de1zzzz', + 'cpm': 1.25, + 'width': 640, + 'height': 480, + 'vastUrl': 'https://mco-1-apex.go.sonobi.com/vast.xml?vid=30292e432662bd5f86d90774b944b038&ref=http%3A%2F%2Flocalhost%2F', + 'ttl': 500, + 'creativeId': 'somecrid', + 'netRevenue': true, + 'currency': 'USD', + 'dealId': 'dozerkey', + 'aid': 'force_1550072228_da1c5d030cb49150c5db8a2136175755', + 'mediaType': 'video', + renderer: () => {} + }, ]; it('should map bidResponse to prebidResponse', function () { @@ -437,7 +478,12 @@ describe('SonobiBidAdapter', function () { expect(resp.netRevenue).to.equal(prebidResponse[i].netRevenue); expect(resp.currency).to.equal(prebidResponse[i].currency); expect(resp.aid).to.equal(prebidResponse[i].aid); - if (resp.mediaType === 'video') { + if (resp.mediaType === 'video' && resp.renderer) { + expect(resp.vastUrl.indexOf('vast.xml')).to.be.greaterThan(0); + expect(resp.width).to.equal(prebidResponse[i].width); + expect(resp.height).to.equal(prebidResponse[i].height); + expect(resp.renderer).to.be.ok; + } else if (resp.mediaType === 'video') { expect(resp.vastUrl.indexOf('vast.xml')).to.be.greaterThan(0); expect(resp.ad).to.be.undefined; expect(resp.width).to.be.undefined; From 9b08b152c21f36f55d28cc4605b247933b0720f4 Mon Sep 17 00:00:00 2001 From: Mike Groh Date: Thu, 14 Feb 2019 11:50:18 -0500 Subject: [PATCH 1019/1594] minor safety check added (#3543) * Adding files associated with the trion adapter update to the newest prebid version(1.0). * Updating pull request with safer checks for user sync and general clean up/consistency of tests. * removing a call to bidder code for pull request review. also removing the test that requires it * there were some changes to the bid factory after our initial release that we didn't account for. Changing adapter to account for response body and required params. * Revert "there were some changes to the bid factory after our initial release that we didn't account for. Changing adapter to account for response body and required params." This reverts commit 324d15785fb61c92db9c0a37f1001f47721e3a25. * there were some changes to the bid factory after our initial release that we didn't account for. Changing adapter to account for response body and required params. * adding safety checks to Trion adapter --- modules/trionBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/trionBidAdapter.js b/modules/trionBidAdapter.js index a314a12f871..97f82f57b85 100644 --- a/modules/trionBidAdapter.js +++ b/modules/trionBidAdapter.js @@ -147,7 +147,7 @@ export function setStorageData(key, item) { export function acceptPostMessage(e) { var message = e.data || ''; - if (message.indexOf(BASE_KEY + 'userId') !== 0) { + if (!message.indexOf || !message.split || message.indexOf(BASE_KEY + 'userId') !== 0) { return; } var intT = message.split(BASE_KEY + 'userId=')[1]; From d69c982e145f82b5bc76d4b9f04b07499db149e9 Mon Sep 17 00:00:00 2001 From: Julien Ricard Date: Fri, 15 Feb 2019 14:51:32 +0100 Subject: [PATCH 1020/1594] bugfix for Firefox for some ads that use document.write (#3524) * bugfix for Firefox for some ads that use document.write * testing that the doc.open method is called..... * added a sinon.spy() for the doc.open method --- src/prebid.js | 1 + test/spec/unit/pbjs_api_spec.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/prebid.js b/src/prebid.js index 92f6d819ecf..bb9004a67c6 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -326,6 +326,7 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { const message = `Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`; emitAdRenderFail(PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid); } else if (ad) { + doc.open('text/html', 'replace'); doc.write(ad); doc.close(); setRenderSize(doc, width, height); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 22737745eb7..9cbad1d6b80 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -990,6 +990,7 @@ describe('Unit: Prebid Module', function () { beforeEach(function () { doc = { + open: sinon.spy(), write: sinon.spy(), close: sinon.spy(), defaultView: { @@ -1040,6 +1041,7 @@ describe('Unit: Prebid Module', function () { }); adResponse.ad = ""; $$PREBID_GLOBAL$$.renderAd(doc, bidId); + assert.ok(doc.open, 'open method called'); assert.ok(doc.write.calledWith(adResponse.ad), 'ad was written to doc'); assert.ok(doc.close.called, 'close method called'); }); From f45aa8a3fd2b6f2b128e833b0bc6137a158aa090 Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Tue, 19 Feb 2019 17:51:29 +0300 Subject: [PATCH 1021/1594] Add video support in Grid Bid Adapter (#3545) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Add video support in Grid Bid Adapter * Added test parameter for video slot * update Grid Bid Adapter to set size in response bid --- modules/gridBidAdapter.js | 57 ++++++++++++++- modules/gridBidAdapter.md | 16 +++- test/spec/modules/gridBidAdapter_spec.js | 93 +++++++++++++++++++++++- 3 files changed, 158 insertions(+), 8 deletions(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index bb3bba5b550..fd1a382d995 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -1,8 +1,13 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; +import { Renderer } from '../src/Renderer'; +import { VIDEO, BANNER } from '../src/mediaTypes'; + const BIDDER_CODE = 'grid'; const ENDPOINT_URL = '//grid.bidswitch.net/hb'; const TIME_TO_LIVE = 360; +const RENDERER_URL = '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js'; + const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', noAdm: 'Bid from response has no adm parameter - ', @@ -16,6 +21,7 @@ const LOG_ERROR_MESS = { }; export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, VIDEO ], /** * Determines whether or not the given bid request is valid. * @@ -124,19 +130,39 @@ function _addBidResponse(serverBid, bidsMap, bidResponses) { const awaitingBids = bidsMap[serverBid.auid]; if (awaitingBids) { awaitingBids.forEach(bid => { + const size = bid.sizes[0]; + if (serverBid.w && serverBid.h) { + size[0] = serverBid.w; + size[1] = serverBid.h; + } const bidResponse = { requestId: bid.bidId, // bid.bidderRequestId, bidderCode: spec.code, cpm: serverBid.price, - width: serverBid.w, - height: serverBid.h, + width: size[0], + height: size[1], creativeId: serverBid.auid, // bid.bidId, currency: 'USD', netRevenue: false, ttl: TIME_TO_LIVE, - ad: serverBid.adm, dealId: serverBid.dealid }; + if (serverBid.content_type === 'video') { + 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, + url: RENDERER_URL + }); + } + } else { + bidResponse.ad = serverBid.adm; + bidResponse.mediaType = BANNER; + } bidResponses.push(bidResponse); }); } else { @@ -148,4 +174,29 @@ function _addBidResponse(serverBid, bidsMap, bidResponses) { } } +function outstreamRender (bid) { + bid.renderer.push(() => { + window.ANOutstreamVideo.renderAd({ + targetId: bid.adUnitCode, + adResponse: bid.adResponse + }); + }); +} + +function createRenderer (bid, rendererParams) { + const renderer = Renderer.install({ + id: rendererParams.id, + url: rendererParams.url, + loaded: false + }); + + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + + return renderer; +} + registerBidder(spec); diff --git a/modules/gridBidAdapter.md b/modules/gridBidAdapter.md index 9b7b0e0515e..4720ee3d808 100755 --- a/modules/gridBidAdapter.md +++ b/modules/gridBidAdapter.md @@ -7,6 +7,7 @@ Maintainer: grid-tech@themediagrid.com # Description Module that connects to Grid demand source to fetch bids. +Grid bid adapter supports Banner and Video (instream and outstream). # Test Parameters ``` @@ -35,6 +36,19 @@ Module that connects to Grid demand source to fetch bids. } } ] - } + }, + { + code: 'test-div', + sizes: [[728, 90]], + mediaTypes: { video: {} }, + bids: [ + { + bidder: "grid", + params: { + uid: 11 + } + } + ] + } ]; ``` \ No newline at end of file diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index f4401dfe677..9be195b4bd2 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -128,7 +128,7 @@ describe('TheMediaGrid Adapter', function () { describe('interpretResponse', function () { const responses = [ - {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300, dealid: 11}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 2, 'h': 90, 'w': 728}], 'seat': '1'}, {'bid': [{'price': 0, 'auid': 3, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, @@ -157,12 +157,13 @@ describe('TheMediaGrid Adapter', function () { 'requestId': '659423fff799cb', 'cpm': 1.15, 'creativeId': 1, - 'dealId': undefined, + 'dealId': 11, 'width': 300, 'height': 250, 'ad': '
test content 1
', 'bidderCode': 'grid', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': false, 'ttl': 360, } @@ -214,12 +215,13 @@ describe('TheMediaGrid Adapter', function () { 'requestId': '300bfeb0d71a5b', 'cpm': 1.15, 'creativeId': 1, - 'dealId': undefined, + 'dealId': 11, 'width': 300, 'height': 250, 'ad': '
test content 1
', 'bidderCode': 'grid', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': false, 'ttl': 360, }, @@ -227,12 +229,13 @@ describe('TheMediaGrid Adapter', function () { 'requestId': '5703af74d0472a', 'cpm': 1.15, 'creativeId': 1, - 'dealId': undefined, + 'dealId': 11, 'width': 300, 'height': 250, 'ad': '
test content 1
', 'bidderCode': 'grid', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': false, 'ttl': 360, }, @@ -246,6 +249,7 @@ describe('TheMediaGrid Adapter', function () { 'ad': '
test content 2
', 'bidderCode': 'grid', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': false, 'ttl': 360, } @@ -255,6 +259,87 @@ describe('TheMediaGrid Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); + it('should get correct video bid response', function () { + const bidRequests = [ + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + } + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '2' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '2bc598e42b6a', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + } + } + ]; + const response = [ + {'bid': [{'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 1, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, + {'bid': [{'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 2, content_type: 'video'}], 'seat': '2'} + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 1, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'bidderCode': 'grid', + 'currency': 'USD', + 'mediaType': 'video', + 'netRevenue': false, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + } + }, + { + 'requestId': '2bc598e42b6a', + 'cpm': 1.00, + 'creativeId': 2, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'bidderCode': 'grid', + 'currency': 'USD', + 'mediaType': 'video', + 'netRevenue': false, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + } + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': response}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + it('handles wrong and nobid responses', function () { const bidRequests = [ { From 8b13af051795580ce281b61568dda39530065387 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 19 Feb 2019 15:47:23 -0500 Subject: [PATCH 1022/1594] Prebid 2.3.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 88cc52f8e95..21ded7a014f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.3.0-pre", + "version": "2.3.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d175960969100d7ea41a4096a841a35f9b6ebd6e Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 19 Feb 2019 16:20:24 -0500 Subject: [PATCH 1023/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 21ded7a014f..6d597aeca8c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.3.0", + "version": "2.4.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 6ea6a3a66a752db8fe56038aebf3ee855c265841 Mon Sep 17 00:00:00 2001 From: Gena Date: Wed, 20 Feb 2019 05:52:51 -0800 Subject: [PATCH 1024/1594] Add Adtelligent gdpr support (#3561) * add adtelligent gdpr support * Fix test --- modules/adtelligentBidAdapter.js | 2 +- test/spec/modules/adtelligentBidAdapter_spec.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/adtelligentBidAdapter.js b/modules/adtelligentBidAdapter.js index daa43799edb..0db8394ee0f 100644 --- a/modules/adtelligentBidAdapter.js +++ b/modules/adtelligentBidAdapter.js @@ -126,7 +126,7 @@ function bidToTag(bidRequests, bidderRequest) { domain: utils.getTopWindowLocation().hostname }; - if (bidderRequest && bidderRequest.gdprConsent) { + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { tag.gdpr = 1; tag.gdpr_consent = bidderRequest.gdprConsent.consentString; } diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js index 9187d779145..28bb057dffe 100644 --- a/test/spec/modules/adtelligentBidAdapter_spec.js +++ b/test/spec/modules/adtelligentBidAdapter_spec.js @@ -91,6 +91,7 @@ const displayBidderRequestWithGdpr = { bidderCode: 'bidderCode', bids: [{bidId: '2e41f65424c87c'}], gdprConsent: { + gdprApplies: true, consentString: 'test' } }; From b247aeb51bad23a467f0e4da0da8689d558eda15 Mon Sep 17 00:00:00 2001 From: pwecker Date: Wed, 20 Feb 2019 15:18:54 -0500 Subject: [PATCH 1025/1594] New Adapter VMG (#3525) * New Adapter VMG * anticipate absence of "buildRequests >> bidderRequest.refererInfo" in prebid_1_0 --- modules/vmgBidAdapter.js | 86 ++++++++++++++++++++++ modules/vmgBidAdapter.md | 28 +++++++ test/spec/modules/vmgBidAdapter_spec.js | 98 +++++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 modules/vmgBidAdapter.js create mode 100644 modules/vmgBidAdapter.md create mode 100644 test/spec/modules/vmgBidAdapter_spec.js diff --git a/modules/vmgBidAdapter.js b/modules/vmgBidAdapter.js new file mode 100644 index 00000000000..2bed62c5d67 --- /dev/null +++ b/modules/vmgBidAdapter.js @@ -0,0 +1,86 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +const BIDDER_CODE = 'vmg'; +const ENDPOINT = 'https://predict.vmg.nyc'; + +export const spec = { + code: BIDDER_CODE, + /** + * Determines whether or not the given bid request is valid. + * + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function (bidRequest) { + if (typeof bidRequest !== 'undefined') { + return true; + } else { + return false; + } + }, + /** + * 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 bidRequests = []; + let referer = window.location.href; + try { + referer = typeof bidderRequest.refererInfo === 'undefined' + ? window.top.location.href + : bidderRequest.refererInfo.referer; + } catch (e) {} + + validBidRequests.forEach(function(validBidRequest) { + bidRequests.push({ + adUnitCode: validBidRequest.adUnitCode, + referer: referer, + bidId: validBidRequest.bidId + }); + }); + + return { + method: 'POST', + url: ENDPOINT, + data: JSON.stringify(bidRequests) + }; + }, + /** + * Unpack the response from the server into a list of bids. + * + * Some required bid params are not needed for this so default + * values are used. + * + * @param {*} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function (serverResponse, bidRequest) { + const validBids = JSON.parse(bidRequest.data); + let bidResponses = []; + if (typeof serverResponse.body !== 'undefined') { + const deals = serverResponse.body; + validBids.forEach(function(validBid) { + if (typeof deals[validBid.adUnitCode] !== 'undefined') { + const bidResponse = { + requestId: validBid.bidId, + ad: '
', + cpm: 0.01, + width: 0, + height: 0, + dealId: deals[validBid.adUnitCode], + ttl: 300, + creativeId: '1', + netRevenue: '0', + currency: 'USD' + }; + + bidResponses.push(bidResponse); + } + }); + } + + return bidResponses; + } +} + +registerBidder(spec); diff --git a/modules/vmgBidAdapter.md b/modules/vmgBidAdapter.md new file mode 100644 index 00000000000..3ebfce91dee --- /dev/null +++ b/modules/vmgBidAdapter.md @@ -0,0 +1,28 @@ +# Overview + +``` +Module Name: VMG Bidder Adapter +Module Type: Bidder Adapter +Maintainer: paul@vmgood.com +``` + +# Description + +Connects DFP to the VMG Predict engine. + +# Test Parameters +``` + var adUnits = [{ + code: 'div-0', + mediaTypes: { + banner: { + sizes: sizes + } + }, + bids: [ + { + bidder: 'vmg' + } + ] + }]; +``` diff --git a/test/spec/modules/vmgBidAdapter_spec.js b/test/spec/modules/vmgBidAdapter_spec.js new file mode 100644 index 00000000000..688c03577fd --- /dev/null +++ b/test/spec/modules/vmgBidAdapter_spec.js @@ -0,0 +1,98 @@ +import { expect } from 'chai'; +import { spec } from 'modules/vmgBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('VmgAdapter', 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 bidRequest = { + adUnitCode: 'div-0', + auctionId: 'd69cdd3f-75e3-42dc-b313-e54c0a99c757', + bidId: '280e2eb8ac3891', + bidRequestsCount: 1, + bidder: 'vmg', + bidderRequestId: '14690d27b056c8', + mediaTypes: { + banner: { + sizes: [ [ 970, 250 ] ] + } + }, + sizes: [ 970, 250 ], + src: 'client', + transactionId: 'af62f065-dfa7-4564-8cb2-d277dc6069f2' + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + }) + + describe('buildRequests', function () { + let validBidRequests = [ + { + adUnitCode: 'div-0', + auctionId: 'd69cdd3f-75e3-42dc-b313-e54c0a99c757', + bidId: '280e2eb8ac3891', + bidRequestsCount: 1, + bidder: 'vmg', + bidderRequestId: '14690d27b056c8', + mediaTypes: { + banner: { + sizes: [ [ 970, 250 ] ] + } + }, + sizes: [ 970, 250 ], + src: 'client', + transactionId: 'af62f065-dfa7-4564-8cb2-d277dc6069f2' + } + ]; + + let bidderRequest = { + auctionId: 'd69cdd3f-75e3-42dc-b313-e54c0a99c757', + auctionStart: 1549316149227, + bidderCode: 'vmg', + bidderRequestId: '14690d27b056c8', + refererInfo: { + canonicalUrl: undefined, + numIframes: 0, + reachedTop: true, + referer: 'https://vmg.nyc/public_assets/adapt/prebid.html', + stack: [ 'https://vmg.nyc/public_assets/adapt/prebid.html' ] + }, + start: 1549316149229, + timeout: 1000 + }; + + it('buildRequests fires', function () { + let request = spec.buildRequests(validBidRequests, bidderRequest); + expect(request).to.exist; + expect(request.method).to.equal('POST'); + expect(request.data).to.exist; + }); + }) + + describe('interpretResponse', function () { + let serverResponse = {}; + serverResponse.body = { + 'div-0': ['test'] + }; + + var bidRequest = { + data: '[{"adUnitCode":"div-0","referer":"https://vmg.nyc/public_assets/adapt/prebid.html","bidId":"280e2eb8ac3891"}]', + method: 'POST', + url: 'https://predict.vmg.nyc' + }; + + it('interpresResponse fires', function () { + let bidResponses = spec.interpretResponse(serverResponse, bidRequest); + expect(bidResponses[0].dealId[0]).to.equal('test'); + }); + }); +}); From 240c606b276e909f3016b446d361610f31bbfb38 Mon Sep 17 00:00:00 2001 From: Aiichiro Kida <42924010+aiichiro@users.noreply.github.com> Date: Fri, 22 Feb 2019 02:31:33 +0900 Subject: [PATCH 1026/1594] New bid adapter for OPEN8 (#3521) * add open8 adapter * slotkey and fix * add maintainer address * add bidwon * check field populated --- modules/open8BidAdapter.js | 185 ++++++++++++++++ modules/open8BidAdapter.md | 50 +++++ test/spec/modules/open8BidAdapter_spec.js | 251 ++++++++++++++++++++++ 3 files changed, 486 insertions(+) create mode 100644 modules/open8BidAdapter.js create mode 100644 modules/open8BidAdapter.md create mode 100644 test/spec/modules/open8BidAdapter_spec.js diff --git a/modules/open8BidAdapter.js b/modules/open8BidAdapter.js new file mode 100644 index 00000000000..be616d0ec30 --- /dev/null +++ b/modules/open8BidAdapter.js @@ -0,0 +1,185 @@ +import { Renderer } from 'src/Renderer'; +import {ajax} from '../src/ajax'; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { VIDEO, BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'open8'; +const URL = '//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 = utils.getBidIdParameter('slotKey', bid.params); + queryString = utils.tryAppendQueryString(queryString, 'slot_key', slotKey); + queryString = utils.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 + } + + 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 = utils.createTrackPixelHtml(impTrackUrl); + bid.ad += tracker; + }); + } catch (error) { + utils.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) { + utils.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/open8BidAdapter.md b/modules/open8BidAdapter.md new file mode 100644 index 00000000000..2c69e174ee6 --- /dev/null +++ b/modules/open8BidAdapter.md @@ -0,0 +1,50 @@ +# Overview + +**Module Name**: Open8 Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: tdd-adtech@open8.com + + # Description + +Innity Bidder Adapter for Prebid.js. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250] + ], + } + }, + bids: [{ + bidder: 'open8', + params: { + slotKey: '504c2e89' + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + sizes: [ + [640, 360] + ], + mediaTypes: { + video: { + context: 'outstream' + } + }, + bids: [{ + bidder: 'open8', + params: { + slotKey: '2ae5a533' + } + }] + }]; + +``` \ No newline at end of file diff --git a/test/spec/modules/open8BidAdapter_spec.js b/test/spec/modules/open8BidAdapter_spec.js new file mode 100644 index 00000000000..e26811ed71c --- /dev/null +++ b/test/spec/modules/open8BidAdapter_spec.js @@ -0,0 +1,251 @@ +import { spec } from 'modules/open8BidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//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 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'] + } + } + }; + 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 + }, + } + }; + + 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 + }]; + + let bidderRequest; + let result = spec.interpretResponse({ body: bannerResponse }, { bidderRequest }); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + 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 + }]; + + let bidderRequest; + let result = spec.interpretResponse({ body: videoResponse }, { bidderRequest }); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + 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([]); + }); + }); +}); From 753f76ab15f62cc75a1c3b9a7354107bb1e5c999 Mon Sep 17 00:00:00 2001 From: deekshithraop Date: Thu, 21 Feb 2019 12:42:51 -0500 Subject: [PATCH 1027/1594] Update removeAdUnit (#3527) * Add removeAllAdUnits to the API * revert package.loc * Update removeAdUnit and remove removeAllAdUnts * update var to let --- src/prebid.js | 24 +++++++++++--- test/spec/unit/pbjs_api_spec.js | 59 +++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index bb9004a67c6..ff780d6deda 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -361,19 +361,33 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { }; /** - * Remove adUnit from the $$PREBID_GLOBAL$$ configuration - * @param {string} adUnitCode the adUnitCode to remove + * Remove adUnit from the $$PREBID_GLOBAL$$ configuration, if there are no addUnitCode(s) it will remove all + * @param {string| Array} adUnitCode the adUnitCode(s) to remove * @alias module:pbjs.removeAdUnit */ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.removeAdUnit', arguments); - if (adUnitCode) { - for (var i = 0; i < $$PREBID_GLOBAL$$.adUnits.length; i++) { + + if (!adUnitCode) { + $$PREBID_GLOBAL$$.adUnits = []; + return; + } + + let adUnitCodes; + + if (utils.isArray(adUnitCode)) { + adUnitCodes = adUnitCode; + } else { + adUnitCodes = [adUnitCode]; + } + + adUnitCodes.forEach((adUnitCode) => { + for (let i = 0; i < $$PREBID_GLOBAL$$.adUnits.length; i++) { if ($$PREBID_GLOBAL$$.adUnits[i].code === adUnitCode) { $$PREBID_GLOBAL$$.adUnits.splice(i, 1); } } - } + }) }; /** diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 9cbad1d6b80..3172ec9c514 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -2140,6 +2140,65 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.removeAdUnit('adUnit1'); assert.deepEqual($$PREBID_GLOBAL$$.adUnits, [adUnit2]); }); + it('should remove all adUnits in adUnits array if no adUnits are given', function () { + const adUnit1 = { + code: 'adUnit1', + bids: [{ + bidder: 'appnexus', + params: { placementId: '123' } + }] + }; + const adUnit2 = { + code: 'adUnit2', + bids: [{ + bidder: 'rubicon', + params: { + accountId: '1234', + siteId: '1234', + zoneId: '1234' + } + }] + }; + const adUnits = [adUnit1, adUnit2]; + $$PREBID_GLOBAL$$.adUnits = adUnits; + $$PREBID_GLOBAL$$.removeAdUnit(); + assert.deepEqual($$PREBID_GLOBAL$$.adUnits, []); + }); + it('should remove adUnits which match addUnitCodes in adUnit array argument', function () { + const adUnit1 = { + code: 'adUnit1', + bids: [{ + bidder: 'appnexus', + params: { placementId: '123' } + }] + }; + const adUnit2 = { + code: 'adUnit2', + bids: [{ + bidder: 'rubicon', + params: { + accountId: '1234', + siteId: '1234', + zoneId: '1234' + } + }] + }; + const adUnit3 = { + code: 'adUnit3', + bids: [{ + bidder: 'rubicon3', + params: { + accountId: '12345', + siteId: '12345', + zoneId: '12345' + } + }] + }; + const adUnits = [adUnit1, adUnit2, adUnit3]; + $$PREBID_GLOBAL$$.adUnits = adUnits; + $$PREBID_GLOBAL$$.removeAdUnit([adUnit1.code, adUnit2.code]); + assert.deepEqual($$PREBID_GLOBAL$$.adUnits, [adUnit3]); + }); }); describe('getDealTargeting', function () { From b12e6ddbcc1a09c8f3a1f85330d31f5dcd389380 Mon Sep 17 00:00:00 2001 From: afsheenb Date: Thu, 21 Feb 2019 23:35:51 -0500 Subject: [PATCH 1028/1594] added setTargeting code for custom key-value pairs (#3550) * added setTargeting code for custom key-value pairs * v1.4.3 - refactored setTargeting code, includes support for pub common ID being passed inside ext.ozone object, refactored the ext.ozone object to carry any data objects defined in on-page bidder config * Update to setTargeting functionality per feedback from prebid.org. * switching from // to https:// to match unit test --- modules/ozoneBidAdapter.js | 297 +++++++++++++++------- test/spec/modules/ozoneBidAdapter_spec.js | 51 ++++ 2 files changed, 252 insertions(+), 96 deletions(-) diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index 06b831fe21c..7a7033a79ac 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -1,11 +1,13 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; +import {config} from '../src/config'; const BIDDER_CODE = 'ozone'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; - +const OZONEVERSION = '1.4.4'; export const spec = { code: BIDDER_CODE, @@ -63,59 +65,17 @@ export const spec = { } return true; }, - /** - * Interpret the response if the array contains BIDDER elements, in the format: [ [bidder1 bid 1, bidder1 bid 2], [bidder2 bid 1, bidder2 bid 2] ] - * @param serverResponse - * @param request - * @returns {*} - */ - interpretResponse(serverResponse, request) { - utils.logInfo('ozone interpretResponse version 2018-12-05 16:46'); - serverResponse = serverResponse.body || {}; - if (serverResponse.seatbid) { - if (utils.isArray(serverResponse.seatbid)) { - // serverResponse seems good, let's get the list of bids from the request object: - let arrRequestBids = request.bidderRequest.bids; - // build up a list of winners, one for each bidId in arrBidIds - let arrWinners = []; - for (let i = 0; i < arrRequestBids.length; i++) { - let winner = ozoneGetWinnerForRequestBid(arrRequestBids[i], serverResponse.seatbid); - if (winner !== null) { - const {defaultWidth, defaultHeight} = defaultSize(arrRequestBids[i]); - winner = ozoneAddStandardProperties(winner, defaultWidth, defaultHeight); - arrWinners.push(winner); - } - } - let winnersClean = arrWinners.filter(w => { - return (w.bidId); // will be cast to boolean - }); - utils.logInfo(['going to return winnersClean:', winnersClean]); - return winnersClean; - } else { - return []; - } - } else { - return []; - } - }, buildRequests(validBidRequests, bidderRequest) { - let ozoneRequest = validBidRequests[0].params; - ozoneRequest['id'] = utils.generateUUID(); - ozoneRequest['auctionId'] = bidderRequest['auctionId']; - - if (bidderRequest.hasOwnProperty('placementId')) { - bidderRequest.placementId = (bidderRequest.placementId).toString(); - } - if (bidderRequest.hasOwnProperty('siteId')) { - bidderRequest.siteId = (bidderRequest.siteId).toString(); - } - if (bidderRequest.hasOwnProperty('publisherId')) { - bidderRequest.publisherId = (bidderRequest.publisherId).toString(); - } + utils.logInfo('ozone v' + OZONEVERSION + ' validBidRequests', validBidRequests, 'bidderRequest', bidderRequest); + utils.logInfo('buildRequests setting auctionId', bidderRequest.auctionId); + let singleRequest = config.getConfig('ozone.singleRequest'); + singleRequest = singleRequest !== false; // undefined & true will be true + utils.logInfo('config ozone.singleRequest : ', singleRequest); + let htmlParams = validBidRequests[0].params; // the html page config params will be included in each element + let ozoneRequest = {}; // we only want to set specific properties on this, not validBidRequests[0].params + // ozoneRequest['id'] = utils.generateUUID(); - // if (!ozoneRequest.test) { delete ozoneRequest.test; // don't allow test to be set in the config - ONLY use $_GET['pbjs_debug'] - // } if (bidderRequest.gdprConsent) { ozoneRequest.regs = {}; ozoneRequest.regs.ext = {}; @@ -126,25 +86,49 @@ export const spec = { } let tosendtags = validBidRequests.map(ozoneBidRequest => { var obj = {}; - obj.id = ozoneBidRequest.bidId; - obj.tagid = String(ozoneBidRequest.params.ozoneid); + obj.id = ozoneBidRequest.bidId; // this causes a failure if we change it to something else + // obj.id = ozoneBidRequest.adUnitCode; // (eg. 'mpu' or 'leaderboard') A unique identifier for this impression within the context of the bid request (typically, starts with 1 and increments. + obj.tagid = (ozoneBidRequest.params.placementId).toString(); obj.secure = window.location.protocol === 'https:' ? 1 : 0; - obj.banner = { - topframe: 1, - w: ozoneBidRequest.sizes[0][0] || 0, - h: ozoneBidRequest.sizes[0][1] || 0, - format: ozoneBidRequest.sizes.map(s => { - return {w: s[0], h: s[1]}; - }) - }; - if (ozoneBidRequest.params.hasOwnProperty('customData')) { - obj.customData = ozoneBidRequest.params.customData; + // is there a banner (or nothing declared, so banner is the default)? + let arrBannerSizes = []; + /* NOTE - if there is sizes element in the config root then there will be a mediaTypes.banner element automatically generated for us, so this code is deprecated */ + if (!ozoneBidRequest.hasOwnProperty('mediaTypes')) { + if (ozoneBidRequest.hasOwnProperty('sizes')) { + utils.logInfo('no mediaTypes detected - will use the sizes array in the config root'); + arrBannerSizes = ozoneBidRequest.sizes; + } else { + 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 */ + utils.logInfo('setting banner size from the mediaTypes.banner element for bidId ' + obj.id + ': ', arrBannerSizes); + } + // Video integration is not complete yet + if (ozoneBidRequest.mediaTypes.hasOwnProperty(VIDEO)) { + obj.video = ozoneBidRequest.mediaTypes[VIDEO]; + utils.logInfo('setting video object from the mediaTypes.video element: ' + obj.id + ':', obj.video); + } + // Native integration is not complete yet + if (ozoneBidRequest.mediaTypes.hasOwnProperty(NATIVE)) { + obj.native = ozoneBidRequest.mediaTypes[NATIVE]; + utils.logInfo('setting native object from the mediaTypes.native element: ' + obj.id + ':', obj.native); + } } - if (ozoneBidRequest.params.hasOwnProperty('ozoneData')) { - obj.ozoneData = ozoneBidRequest.params.ozoneData; + // build the banner request using banner sizes we found in either possible location: + if (arrBannerSizes.length > 0) { + obj.banner = { + topframe: 1, + w: arrBannerSizes[0][0] || 0, + h: arrBannerSizes[0][1] || 0, + format: arrBannerSizes.map(s => { + return {w: s[0], h: s[1]}; + }) + }; } - if (ozoneBidRequest.params.hasOwnProperty('lotameData')) { - obj.lotameData = ozoneBidRequest.params.lotameData; + if (ozoneBidRequest.params.hasOwnProperty('placementId')) { + obj.placementId = (ozoneBidRequest.params.placementId).toString(); } if (ozoneBidRequest.params.hasOwnProperty('publisherId')) { obj.publisherId = (ozoneBidRequest.params.publisherId).toString(); @@ -152,22 +136,132 @@ export const spec = { if (ozoneBidRequest.params.hasOwnProperty('siteId')) { obj.siteId = (ozoneBidRequest.params.siteId).toString(); } - obj.ext = {'prebid': {'storedrequest': {'id': (ozoneBidRequest.params.placementId).toString()}}}; + // build the imp['ext'] object + obj.ext = {'prebid': {'storedrequest': {'id': (ozoneBidRequest.params.placementId).toString()}}, 'ozone': {}}; + obj.ext.ozone.adUnitCode = ozoneBidRequest.adUnitCode; // eg. 'mpu' + obj.ext.ozone.transactionId = ozoneBidRequest.transactionId; // this is the transactionId PER adUnit, common across bidders for this unit + if (ozoneBidRequest.params.hasOwnProperty('customData')) { + obj.ext.ozone.customData = ozoneBidRequest.params.customData; + } + if (ozoneBidRequest.params.hasOwnProperty('ozoneData')) { + obj.ext.ozone.ozoneData = ozoneBidRequest.params.ozoneData; + } + if (ozoneBidRequest.params.hasOwnProperty('lotameData')) { + obj.ext.ozone.lotameData = ozoneBidRequest.params.lotameData; + } + if (ozoneBidRequest.hasOwnProperty('crumbs') && ozoneBidRequest.crumbs.hasOwnProperty('pubcid')) { + obj.ext.ozone.pubcid = ozoneBidRequest.crumbs.pubcid; + } return obj; }); - ozoneRequest.imp = tosendtags; - ozoneRequest.site = {'publisher': {'id': ozoneRequest.publisherId}, 'page': document.location.href}; + utils.logInfo('tosendtags = ', tosendtags); + + ozoneRequest.site = {'publisher': {'id': htmlParams.publisherId}, 'page': document.location.href}; ozoneRequest.test = parseInt(getTestQuerystringValue()); // will be 1 or 0 - var ret = { - method: 'POST', - url: OZONEURI, - data: JSON.stringify(ozoneRequest), - bidderRequest: bidderRequest - }; - utils.logInfo(['buildRequests going to return', ret]); - return ret; + // utils.logInfo('_ozoneInternal is', _ozoneInternal); + // return the single request object OR the array: + if (singleRequest) { + 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.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). + var ret = { + method: 'POST', + url: OZONEURI, + data: JSON.stringify(ozoneRequest), + bidderRequest: bidderRequest + }; + utils.logInfo('buildRequests ozoneRequest for single = ', ozoneRequest); + utils.logInfo('buildRequests going to return for single: ', 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 => { + utils.logInfo('buildRequests starting to generate non-single response, working on imp : ', imp); + let ozoneRequestSingle = Object.assign({}, ozoneRequest); + imp.ext.ozone.pageAuctionId = bidderRequest['auctionId']; // make a note in the ext object of what the original auctionId was, in the bidderRequest object + ozoneRequestSingle.id = imp.ext.ozone.transactionId; // Unique ID of the bid request, provided by the exchange. + ozoneRequestSingle.auctionId = imp.ext.ozone.transactionId; // not sure if this should be here? + ozoneRequestSingle.imp = [imp]; + ozoneRequestSingle.source = {'tid': imp.ext.ozone.transactionId}; + utils.logInfo('buildRequests ozoneRequestSingle (for non-single) = ', ozoneRequestSingle); + return { + method: 'POST', + url: OZONEURI, + data: JSON.stringify(ozoneRequestSingle), + bidderRequest: bidderRequest + }; + }); + utils.logInfo('buildRequests going to return for non-single: ', arrRet); + return arrRet; }, + /** + * Interpret the response if the array contains BIDDER elements, in the format: [ [bidder1 bid 1, bidder1 bid 2], [bidder2 bid 1, bidder2 bid 2] ] + * NOte that in singleRequest mode this will be called once, else it will be called for each adSlot's response + * @param serverResponse + * @param request + * @returns {*} + */ + interpretResponse(serverResponse, request) { + utils.logInfo('ozone v' + OZONEVERSION + ' interpretResponse', serverResponse, request); + serverResponse = serverResponse.body || {}; + if (serverResponse.seatbid) { + if (utils.isArray(serverResponse.seatbid)) { + // serverResponse seems good, let's get the list of bids from the request object: + let arrRequestBids = request.bidderRequest.bids; + // build up a list of winners, one for each bidId in arrBidIds + let arrWinners = []; + for (let i = 0; i < arrRequestBids.length; i++) { + let thisBid = arrRequestBids[i]; + let ozoneInternalKey = thisBid.bidId; + let {seat: winningSeat, bid: winningBid} = ozoneGetWinnerForRequestBid(thisBid, serverResponse.seatbid); + + if (winningBid == null) { + utils.logInfo('FAILED to get winning bid for bid : ', thisBid, 'will skip. Possibly a non-single request, which will be missing some bid IDs'); + continue; + } + const {defaultWidth, defaultHeight} = defaultSize(arrRequestBids[i]); + winningBid = ozoneAddStandardProperties(winningBid, defaultWidth, defaultHeight); + + utils.logInfo('Going to add the adserverTargeting custom parameters for key: ', ozoneInternalKey); + let adserverTargeting = {}; + let allBidsForThisBidid = ozoneGetAllBidsForBidId(ozoneInternalKey, serverResponse.seatbid); + // add all the winning & non-winning bids for this bidId: + Object.keys(allBidsForThisBidid).forEach(function(bidderName, index, ar2) { + utils.logInfo('inside allBidsForThisBidid:foreach', bidderName, index, ar2, allBidsForThisBidid); + adserverTargeting['oz_' + bidderName] = bidderName; + adserverTargeting['oz_' + bidderName + '_pb'] = String(allBidsForThisBidid[bidderName].price); + adserverTargeting['oz_' + bidderName + '_crid'] = String(allBidsForThisBidid[bidderName].crid); + adserverTargeting['oz_' + bidderName + '_adv'] = String(allBidsForThisBidid[bidderName].adomain); + adserverTargeting['oz_' + bidderName + '_imp_id'] = String(allBidsForThisBidid[bidderName].impid); + }); + // now add the winner data: + adserverTargeting['oz_auc_id'] = String(request.bidderRequest.auctionId); + adserverTargeting['oz_winner'] = String(winningSeat); + adserverTargeting['oz_winner_auc_id'] = String(winningBid.id); + adserverTargeting['oz_winner_imp_id'] = String(winningBid.impid); + adserverTargeting['oz_response_id'] = String(serverResponse.id); + + winningBid.adserverTargeting = adserverTargeting; + utils.logInfo('winner is', winningBid); + arrWinners.push(winningBid); + utils.logInfo('arrWinners is', arrWinners); + } + let winnersClean = arrWinners.filter(w => { + return (w.bidId); // will be cast to boolean + }); + utils.logInfo('going to return winnersClean:', winnersClean); + return winnersClean; + } else { + return []; + } + } else { + return []; + } + }, getUserSyncs(optionsType, serverResponse) { if (!serverResponse || serverResponse.length === 0) { return []; @@ -180,22 +274,6 @@ export const spec = { } } } - -/** - * Function matchRequest(id: string, BidRequest: object) - * @param id - * @type string - * @param bidRequest - * @type Object - * @returns Object - * - */ -export function matchRequest(id, bidRequest) { - const {bids} = bidRequest.bidderRequest; - const [returnValue] = bids.filter(bid => bid.bidId === id); - return returnValue; -} - export function checkDeepArray(Arr) { if (Array.isArray(Arr)) { if (Array.isArray(Arr[0])) { @@ -223,19 +301,45 @@ export function defaultSize(thebidObj) { */ export function ozoneGetWinnerForRequestBid(requestBid, serverResponseSeatBid) { let thisBidWinner = null; + let winningSeat = null; for (let j = 0; j < serverResponseSeatBid.length; j++) { let theseBids = serverResponseSeatBid[j].bid; let thisSeat = serverResponseSeatBid[j].seat; for (let k = 0; k < theseBids.length; k++) { if (theseBids[k].impid === requestBid.bidId) { // we've found a matching server response bid for this request bid + // if (theseBids[k].impid === requestBid.adUnitCode) { // we've found a matching server response bid for this request bid if ((thisBidWinner == null) || (thisBidWinner.price < theseBids[k].price)) { thisBidWinner = theseBids[k]; - thisBidWinner.seat = thisSeat; // we need to add this here - it's the name of the winning bidder, not guaranteed to be available in the bid object. + winningSeat = thisSeat; + break; } } } } - return thisBidWinner; + return {'seat': winningSeat, 'bid': thisBidWinner}; +} + +/** + * Get a list of all the bids, for this bidId + * @param matchBidId + * @param serverResponseSeatBid + * @returns {} = {ozone:{obj}, appnexus:{obj}, ... } + */ +export function ozoneGetAllBidsForBidId(matchBidId, serverResponseSeatBid) { + utils.logInfo('ozoneGetAllBidsForBidId - starting, with: ', matchBidId, serverResponseSeatBid); + let objBids = {}; + for (let j = 0; j < serverResponseSeatBid.length; j++) { + let theseBids = serverResponseSeatBid[j].bid; + let thisSeat = serverResponseSeatBid[j].seat; + for (let k = 0; k < theseBids.length; k++) { + if (theseBids[k].impid === matchBidId) { // we've found a matching server response bid for the request bid we're looking for + utils.logInfo('ozoneGetAllBidsForBidId - found matching bid: ', matchBidId, theseBids[k]); + objBids[thisSeat] = theseBids[k]; + } + } + } + utils.logInfo('ozoneGetAllBidsForBidId - going to return: ', objBids); + return objBids; } /** @@ -275,3 +379,4 @@ export function getTestQuerystringValue() { } registerBidder(spec); +utils.logInfo('ozoneBidAdapter ended'); diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index 6b4f6c88bdd..c404d9003fe 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -2,6 +2,7 @@ import { expect } from 'chai'; import { spec } from 'modules/ozoneBidAdapter'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; +// const OZONEURI = 'https://www.1in39.co.uk/openrtb2/auction'; const BIDDER_CODE = 'ozone'; /* @@ -22,6 +23,34 @@ var validBidRequests = [ transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; +var validBidRequestsNoSizes = [ + { + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + bidId: '2899ec066a91ff8', + bidRequestsCount: 1, + bidder: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' + } +]; + +var validBidRequestsWithMediaTypes = [ + { + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + bidId: '2899ec066a91ff8', + bidRequestsCount: 1, + bidder: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + mediaTypes: {banner: {sizes: [[300, 250], [300, 600]]}}, + transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' + } +]; var validBidderRequest = { auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', @@ -211,6 +240,18 @@ describe('ozone Adapter', function () { expect(spec.isBidRequestValid(xMissingPublisher)).to.equal(false); }); + var xMissingSiteId = { + bidder: BIDDER_CODE, + params: { + publisherId: '9876abcd12-3', + placementId: '1234567890', + } + }; + + it('should not validate missing sitetId', function () { + expect(spec.isBidRequestValid(xMissingSiteId)).to.equal(false); + }); + var xBadPublisherTooShort = { bidder: BIDDER_CODE, params: { @@ -419,6 +460,16 @@ describe('ozone Adapter', function () { const request = spec.buildRequests(validBidRequests, validBidderRequest); expect(request.bidderRequest.bids[0].bidder).to.equal(BIDDER_CODE); }); + + it('handles mediaTypes element correctly', function () { + const request = spec.buildRequests(validBidRequestsWithMediaTypes, validBidderRequest); + expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); + }); + + it('should not crash when there is no sizes element at all', function () { + const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest); + expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); + }); }); describe('interpretResponse', function () { From 849ae8f092268823a2cc98cca58056451ac47518 Mon Sep 17 00:00:00 2001 From: Gaudeamus Date: Fri, 22 Feb 2019 06:40:31 +0200 Subject: [PATCH 1029/1594] mgidAdapter (#3562) * mgidAdapter * mgidAdapter description * mgidAdapter test fixes * mgidAdapter test fixes * mgidAdapter test fixes * mgidAdapter test fixes * mgidAdapter test fixes * mgidAdapter test fixes * mgidAdapter test fixes * mgidAdapter test fixes * mgidAdapter test fixes * mgidAdapter gdpr + ver * test params * test params changed * revert * revert --- modules/mgidBidAdapter.js | 247 +++++++++++++++++++++++ modules/mgidBidAdapter.md | 86 ++++++++ test/spec/modules/mgidBidAdapter_spec.js | 243 ++++++++++++++++++++++ 3 files changed, 576 insertions(+) create mode 100644 modules/mgidBidAdapter.js create mode 100644 modules/mgidBidAdapter.md create mode 100644 test/spec/modules/mgidBidAdapter_spec.js diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js new file mode 100644 index 00000000000..5a91cccde9e --- /dev/null +++ b/modules/mgidBidAdapter.js @@ -0,0 +1,247 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import * as urlUtils from '../src/url'; +import { BANNER } from 'src/mediaTypes'; +const BIDDER_CODE = 'mgid'; +const ENDPOINT_URL = '//dsp.mgid.com/prebid/'; + +export const spec = { + VERSION: '1.0', + code: BIDDER_CODE, + aliases: ['mgid'], // short code + supportedMediaTypes: [BANNER], + reId: /^[0-9]+$/, + /** + * 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 = utils.deepAccess(bid, 'mediaTypes.banner'); + const sizes = utils.deepAccess(banner, 'sizes'); + let sizesOk = typeof (sizes) == 'object' && sizes.length > 0; + for (let f = 0; sizesOk && f < sizes.length; f++) { + sizesOk = sizes[f].length == 2; + } + return typeof (bid.params) == 'object' && !!bid.params.accountId && !!bid.params.placementId && + typeof (bid.params.accountId) == 'string' && typeof (bid.params.placementId) == 'string' && + bid.params.accountId.length > 0 && bid.params.placementId.length > 0 && + bid.params.accountId.toString().match(spec.reId) > 0 && bid.params.placementId.toString().match(spec.reId) && + typeof (banner) == 'object' && sizesOk; + }, + /** + * 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) => { + utils.logInfo(`MGID DEBUG: buildRequests`); + if (validBidRequests.length == 0) { + return null; + } + const referer = utils.deepAccess(bidderRequest, 'refererInfo.referer'); + const hostname = urlUtils.parse(referer).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 (muid != null && typeof (muid) == 'string' && muid.length > 0) { + url += '?muid=' + muid; + } + const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || referer; + const secure = window.location.protocol === 'https:' ? 1 : 0; + const imp = validBidRequests.map((bid, id) => { + const placeId = utils.deepAccess(bid, 'params.placementId'); + const sizes = utils.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]}); + } + } + } + return { + id: bid.bidId, + tagid: placeId, + banner: { + w: sizes && sizes[0][0], + h: sizes && sizes[0][1], + format, + }, + secure, + }; + }); + + let ext = {mgid_ver: spec.VERSION, prebid_ver: $$PREBID_GLOBAL$$.version}; + let user = {}; + let regs = {}; + if (bidderRequest && bidderRequest.gdprConsent) { + user.ext = { + consent: bidderRequest.gdprConsent.consentString + }; + + regs.ext = { + gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) + }; + } + + const request = { + id: utils.deepAccess(bidderRequest, 'bidderRequestId'), + site: { domain, page }, + cur: ['USD'], + 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() + }, + user, + regs, + ext, + imp + }; + utils.logInfo(`MGID DEBUG: buildRequests\n${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) => { + if (serverResponse == null || serverResponse.body == null || serverResponse.body == '' || !serverResponse.body.seatbid || !serverResponse.body.seatbid[0]) { + return []; + } + utils.logInfo(`MGID DEBUG: interpretResponse`); + const returnedBids = []; + const muidn = utils.deepAccess(serverResponse.body, 'ext.muidn') + if (muidn != null && typeof (muidn) == 'string' && muidn.length > 0) { + setLocalStorageSafely('mgMuidn', muidn) + } + serverResponse.body.seatbid[0].bid.forEach((value, index) => { + returnedBids.push(prebidBid(value, serverResponse.body.cur)); + }); + + utils.logInfo(`MGID DEBUG:\n${returnedBids}`); + return returnedBids; + }, + onBidWon: (bid) => { + const cpm = bid.pbMg; + if (bid.nurl != '') { + bid.nurl = bid.nurl.replace( + /\$\{AUCTION_PRICE\}/, + cpm + ); + pixel(bid.nurl); + }; + if (bid.isBurl) { + bid.ad = bid.ad.replace( + /\$\{AUCTION_PRICE\}/, + cpm + ); + } + utils.logInfo(`MGID DEBUG: onBidWon`); + }, + getUserSyncs: (syncOptions, serverResponses) => { + utils.logInfo(`MGID DEBUG: getUserSyncs`); + } +}; + +registerBidder(spec); + +function setOnAny(collection, key) { + for (let i = 0, result; i < collection.length; i++) { + result = utils.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 (cur == null || cur == '') { + cur = 'USD'; + } + 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 || '', + isBurl: typeof (serverBid.burl) == 'string' && serverBid.burl.length > 0, + }; + + return bid; +} + +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 pixel(url) { + (document.createElement('IMG')).src = url; +} + +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 localStorage.getItem(key); + } catch (e) { + return null; + } +} + +function setLocalStorageSafely(key, val) { + try { + return localStorage.setItem(key, val); + } catch (e) { + return null; + } +} diff --git a/modules/mgidBidAdapter.md b/modules/mgidBidAdapter.md new file mode 100644 index 00000000000..8ab59c2247f --- /dev/null +++ b/modules/mgidBidAdapter.md @@ -0,0 +1,86 @@ +# Overview + +``` +Module Name: Mgid Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@mgid.com +``` + +# Description + +One of the easiest way to gain access to MGID demand sources - MGID header bidding adapter. + +MGID header bidding adapter connects with MGID demand sources to fetch bids for display placements + +# Test Parameters + + +300x600 banner test +``` +var adUnits = [{ + code: 'div-prebid', + mediaTypes: { + banner: { + sizes: [[300, 600]] + } + }, + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'mgid', + params : { + accountId : "219", //test accountId, please replace after test + placementId : "331749" // 300x600 test placementId, please replace after test + } + }] +}]; +``` + +300x250 banner test +``` +var adUnits = [{ + code: 'div-prebid', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'mgid', + params : { + accountId : "219", //test accountId, please replace after test + placementId : "331748" // 300x250 test placementId, please replace after test + } + }] +}]; +``` + +# Bid Parameters +## Banner + +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `accountId` | required | String | The account ID from Mgid | "123" +| `placementId` | required | String | The placement ID from Mgid | "123456" + + +# Ad Unit and page Setup: + +```html + + + +``` diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js new file mode 100644 index 00000000000..4c67447489d --- /dev/null +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -0,0 +1,243 @@ +import {expect} from 'chai'; +import {spec} from 'modules/mgidBidAdapter'; +import * as utils from '../../../src/utils'; +import * as urlUtils from '../../../src/url'; + +describe('Mgid bid adapter', function () { + let sandbox; + beforeEach(function () { + sandbox = sinon.sandbox.create(); + }); + + afterEach(function () { + sandbox.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 prebid_ver = $$PREBID_GLOBAL$$.version; + + describe('isBidRequestValid', function () { + let bid = { + '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 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', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = {accountId: '1', placementId: '1'}; + bid.mediaTypes = { + banner: { + sizes: [[300, 250]] + } + }; + 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: '//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('//newbidurl.com/1'); + }); + }); + + describe('buildRequests', function () { + let abid = { + bidder: 'mgid', + params: { + accountId: '1', + placementId: '2', + }, + }; + it('should return proper imp', function () { + let bid = Object.assign({}, abid); + bid.mediaTypes = { + banner: { + sizes: [[300, 250]] + } + }; + let bidRequests = [bid]; + const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); + const domain = urlUtils.parse(referer).hostname; + const request = spec.buildRequests(bidRequests); + expect(request.url).deep.equal('//dsp.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.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'); + expect(data.imp[0].banner).to.deep.equal({w: 300, h: 250, format: []}); + expect(data.imp[0].secure).to.deep.equal(secure); + expect(request).to.deep.equal({ + 'method': 'POST', + 'url': '//dsp.mgid.com/prebid/1', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"banner\":{\"w\":300,\"h\":250,\"format\":[]},\"secure\":' + secure + '}]}', + }); + }); + it('should return proper request', function () { + let bid = Object.assign({}, abid); + bid.mediaTypes = { + banner: { + sizes: [[300, 600], [300, 250]], + } + }; + let bidRequests = [bid]; + const request = spec.buildRequests(bidRequests); + + const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); + const domain = urlUtils.parse(referer).hostname; + expect(request.url).deep.equal('//dsp.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.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'); + expect(data.imp[0].banner).to.deep.equal({w: 300, h: 600, format: [{w: 300, h: 600}, {w: 300, h: 250}]}); + expect(data.imp[0].secure).to.deep.equal(secure); + + expect(request).to.deep.equal({ + 'method': 'POST', + 'url': '//dsp.mgid.com/prebid/1', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]},\"secure\":' + secure + '}]}', + }); + }); + }); + describe('interpretResponse', function () { + it('should not push bid response', function () { + let bids = spec.interpretResponse(); + expect(bids).to.deep.equal([]); + }); + it('should push proper bid response', function () { + let resp = { + body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'USD', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'http: nurl', 'burl': 'http: nurl', 'adm': 'html: adm', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2']}], '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', + 'netRevenue': true, + 'nurl': 'http: nurl', + 'requestId': '61e40632c53fc2', + 'ttl': 300, + 'width': 300, + } + ]); + }); + }); +}); From 88a7fe98cebf5884f64d4337318221a0e2f9aeff Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Fri, 22 Feb 2019 05:59:49 +0000 Subject: [PATCH 1030/1594] Audience Network: upgrade bid requests to use latest SDK (#3571) --- modules/audienceNetworkBidAdapter.js | 4 ++-- test/spec/modules/audienceNetworkBidAdapter_spec.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 19c5be9d1de..b4cf93363f6 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -18,7 +18,7 @@ const ttl = 600; const videoTtl = 3600; const platver = '$prebid.version$'; const platform = '241394079772386'; -const adapterver = '1.2.0'; +const adapterver = '1.3.0'; /** * Does this bid request contain valid parameters? @@ -108,7 +108,7 @@ const isFullWidth = format => format === 'fullwidth'; * @param {String} format * @returns {String} */ -const sdkVersion = format => isVideo(format) ? '' : '5.5.web'; +const sdkVersion = format => isVideo(format) ? '' : '6.0.web'; /** * Which platform identifier should be used? diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index dad05d07260..a495b33438c 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -19,7 +19,7 @@ const placementId = 'test-placement-id'; const playerwidth = 320; const playerheight = 180; const requestId = 'test-request-id'; -const debug = 'adapterver=1.2.0&platform=241394079772386&platver=$prebid.version$&cb=test-uuid'; +const debug = 'adapterver=1.3.0&platform=241394079772386&platver=$prebid.version$&cb=test-uuid'; const pageUrl = encodeURIComponent(utils.getTopWindowUrl()); describe('AudienceNetwork adapter', function () { @@ -141,7 +141,7 @@ describe('AudienceNetwork adapter', function () { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debug}` + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=6.0.web&${debug}` }]); }); @@ -179,7 +179,7 @@ describe('AudienceNetwork adapter', function () { requestIds: [requestId], sizes: ['728x90'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debug}` + data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=${pageUrl}&sdk[]=6.0.web&${debug}` }]); }); @@ -202,7 +202,7 @@ describe('AudienceNetwork adapter', function () { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debugPlatform}` + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=6.0.web&${debugPlatform}` }]); }); }); From 2feb988a96ba41656df2d19f338de710b1d06760 Mon Sep 17 00:00:00 2001 From: PWyrembak Date: Fri, 22 Feb 2019 21:47:21 +0300 Subject: [PATCH 1031/1594] Update TrustX Bid Adapter (#3563) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Add support of gdpr to Trustx Bid Adapter * Add wtimeout to ad request params for TrustX Bid Adapter * TrustX Bid Adapter: remove last ampersand in the ad request * Update TrustX Bid Adapter to support identical uids in parameters * Update TrustX Bid Adapter to ignore bids that sizes do not match the size of the request --- modules/trustxBidAdapter.js | 61 +++++- test/spec/modules/trustxBidAdapter_spec.js | 240 +++++++++++++++++++-- 2 files changed, 274 insertions(+), 27 deletions(-) diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index b61a870c2a4..bd5f63e5302 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -36,6 +36,8 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { const auids = []; const bidsMap = {}; + const slotsMapByUid = {}; + const sizeMap = {}; const bids = validBidRequests || []; let priceType = 'net'; let reqId; @@ -45,18 +47,41 @@ export const spec = { priceType = 'gross'; } reqId = bid.bidderRequestId; - if (!bidsMap[bid.params.uid]) { - bidsMap[bid.params.uid] = [bid]; - auids.push(bid.params.uid); + const {params: {uid}, adUnitCode} = bid; + auids.push(uid); + const sizesId = utils.parseSizesInput(bid.sizes); + + if (!slotsMapByUid[uid]) { + slotsMapByUid[uid] = {}; + } + const slotsMap = slotsMapByUid[uid]; + if (!slotsMap[adUnitCode]) { + slotsMap[adUnitCode] = {adUnitCode, bids: [bid], parents: []}; } else { - bidsMap[bid.params.uid].push(bid); + 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 = { u: utils.getTopWindowUrl(), pt: priceType, auids: auids.join(','), + sizes: utils.getKeys(sizeMap).join(','), r: reqId }; @@ -138,8 +163,12 @@ function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { else { const awaitingBids = bidsMap[serverBid.auid]; if (awaitingBids) { - awaitingBids.forEach(bid => { - const bidResponse = { + const sizeId = `${serverBid.w}x${serverBid.h}`; + if (awaitingBids[sizeId]) { + const slot = awaitingBids[sizeId][0]; + + const bid = slot.bids.shift(); + bidResponses.push({ requestId: bid.bidId, // bid.bidderRequestId, bidderCode: spec.code, cpm: serverBid.price, @@ -151,9 +180,23 @@ function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { ttl: TIME_TO_LIVE, ad: serverBid.adm, dealId: serverBid.dealid - }; - 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 (!utils.getKeys(parent).length) { + delete bidsMap[uid]; + } + } + }); + } + } } else { errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; } diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index 9f2fdca6a99..207d3a068ba 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -65,7 +65,7 @@ describe('TrustXAdapter', function () { 'uid': '43' }, 'adUnitCode': 'adunit-code-2', - 'sizes': [[728, 90]], + 'sizes': [[728, 90], [300, 250]], 'bidId': '3150ccb55da321', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', @@ -90,16 +90,18 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('u').that.is.a('string'); 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'); }); - it('auids must not be duplicated', function () { + it('sizes must not be duplicated', function () { const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '43,45'); + 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'); }); @@ -110,7 +112,8 @@ describe('TrustXAdapter', function () { const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'gross'); - expect(payload).to.have.property('auids', '43,45'); + 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; }); @@ -122,7 +125,8 @@ describe('TrustXAdapter', function () { const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '43,45'); + 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; }); @@ -155,9 +159,10 @@ describe('TrustXAdapter', function () { describe('interpretResponse', function () { const responses = [ {'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': 90, 'w': 728}], '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 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300}], 'seat': '1'}, undefined, {'bid': [], 'seat': '1'}, {'seat': '1'}, @@ -250,26 +255,26 @@ describe('TrustXAdapter', function () { 'ttl': 360, }, { - 'requestId': '5703af74d0472a', - 'cpm': 1.15, - 'creativeId': 43, + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 44, 'dealId': undefined, 'width': 300, - 'height': 250, - 'ad': '
test content 1
', + 'height': 600, + 'ad': '
test content 2
', 'bidderCode': 'trustx', 'currency': 'USD', 'netRevenue': true, 'ttl': 360, }, { - 'requestId': '4dff80cc4ee346', - 'cpm': 0.5, - 'creativeId': 44, + 'requestId': '5703af74d0472a', + 'cpm': 0.15, + 'creativeId': 43, 'dealId': undefined, 'width': 728, 'height': 90, - 'ad': '
test content 2
', + 'ad': '
test content 3
', 'bidderCode': 'trustx', 'currency': 'USD', 'netRevenue': true, @@ -277,7 +282,7 @@ describe('TrustXAdapter', function () { } ]; - const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(0, 3)}}, request); expect(result).to.deep.equal(expectedResponse); }); @@ -318,8 +323,207 @@ describe('TrustXAdapter', function () { } ]; const request = spec.buildRequests(bidRequests); - const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(3)}}, request); expect(result.length).to.equal(0); }); + + it('complicated case', function () { + const fullResponse = [ + {'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 = [ + { + 'bidder': 'trustx', + 'params': { + 'uid': '43' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '2164be6358b9', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '43' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '326bde7fbf69', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '44' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4e111f1b66e4', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '43' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '26d6f897b516', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '44' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '1751cd90161', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '2164be6358b9', + 'cpm': 1.15, + 'creativeId': 43, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'trustx', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4e111f1b66e4', + 'cpm': 0.5, + 'creativeId': 44, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'ad': '
test content 2
', + 'bidderCode': 'trustx', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '26d6f897b516', + 'cpm': 0.15, + 'creativeId': 43, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 3
', + 'bidderCode': 'trustx', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '326bde7fbf69', + 'cpm': 0.15, + 'creativeId': 43, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'ad': '
test content 4
', + 'bidderCode': 'trustx', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('dublicate uids and sizes in one slot', function () { + const fullResponse = [ + {'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 = [ + { + 'bidder': 'trustx', + 'params': { + 'uid': '43' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '5126e301f4be', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '43' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '57b2ebe70e16', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '43' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '225fcd44b18c', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '5126e301f4be', + 'cpm': 1.15, + 'creativeId': 43, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'trustx', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '57b2ebe70e16', + 'cpm': 0.5, + 'creativeId': 43, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 2
', + 'bidderCode': 'trustx', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + expect(result).to.deep.equal(expectedResponse); + }); }); }); From 68dfb641a2ee27d9b538910ed92f253a4f6e3685 Mon Sep 17 00:00:00 2001 From: mustafa kemal Date: Sat, 23 Feb 2019 04:14:03 +0300 Subject: [PATCH 1032/1594] New bid adapter for TheAdx (#3547) * theAdx BidAdapter module and test spec added * requested changes from reviewer --- modules/theAdxBidAdapter.js | 498 ++++++++++++++++ modules/theAdxBidAdapter.md | 91 +++ test/spec/modules/theAdxBidAdapter_spec.js | 642 +++++++++++++++++++++ 3 files changed, 1231 insertions(+) create mode 100644 modules/theAdxBidAdapter.js create mode 100644 modules/theAdxBidAdapter.md create mode 100644 test/spec/modules/theAdxBidAdapter_spec.js diff --git a/modules/theAdxBidAdapter.js b/modules/theAdxBidAdapter.js new file mode 100644 index 00000000000..aeec32620ad --- /dev/null +++ b/modules/theAdxBidAdapter.js @@ -0,0 +1,498 @@ +import * as utils from '../src/utils'; +import { + BANNER, + NATIVE, + VIDEO +} from '../src/mediaTypes'; +import { + registerBidder +} from '../src/adapters/bidderFactory'; +import { + parse as parseUrl +} from '../src/url'; + +const BIDDER_CODE = 'theadx'; +const ENDPOINT_URL = '//ssp.theadx.com/request'; + +const NATIVEASSETNAMES = { + 0: 'title', + 1: 'cta', + 2: 'icon', + 3: 'image', + 4: 'body', + 5: 'sponsoredBy', + 6: 'body2', + 7: 'phone', + 8: 'privacyLink', + 9: 'displayurl', + 10: 'rating', + 11: 'address', + 12: 'downloads', + 13: 'likes', + 14: 'price', + 15: 'saleprice', + +}; +const NATIVEPROBS = { + title: { + id: 0, + name: 'title' + }, + body: { + id: 4, + name: 'data', + type: 2 + }, + body2: { + id: 6, + name: 'data', + type: 10 + }, + privacyLink: { + id: 8, + name: 'data', + type: 501 + }, + sponsoredBy: { + id: 5, + name: 'data', + type: 1 + }, + image: { + id: 3, + type: 3, + name: 'img' + }, + icon: { + id: 2, + type: 1, + name: 'img' + }, + displayurl: { + id: 9, + name: 'data', + type: 11 + }, + cta: { + id: 1, + type: 12, + name: 'data' + }, + rating: { + id: 7, + name: 'data', + type: 3 + }, + address: { + id: 11, + name: 'data', + type: 5 + }, + downloads: { + id: 12, + name: 'data', + type: 5 + }, + likes: { + id: 13, + name: 'data', + type: 4 + }, + phone: { + id: 7, + name: 'data', + type: 8 + }, + price: { + id: 14, + name: 'data', + type: 6 + }, + saleprice: { + id: 15, + name: 'data', + type: 7 + }, + +}; + +export const spec = { + code: BIDDER_CODE, + aliases: ['theadx'], // short code + supportedMediaTypes: [BANNER, VIDEO, 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 (bid) { + utils.logInfo('theadx.isBidRequestValid', bid); + let res = false; + if (bid && bid.params) { + res = !!(bid.params.pid && bid.params.tagId); + } + + return res; + }, + + /** + * 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) { + utils.logInfo('theadx.buildRequests', 'validBidRequests', validBidRequests, 'bidderRequest', bidderRequest); + let results = []; + const requestType = 'POST'; + if (!utils.isEmpty(validBidRequests)) { + results = validBidRequests.map( + bidRequest => { + return { + method: requestType, + type: requestType, + url: `${ENDPOINT_URL}?tagid=${bidRequest.params.tagId}`, + options: { + withCredentials: true, + }, + bidder: 'theadx', + referrer: encodeURIComponent(bidderRequest.refererInfo.referer), + data: generatePayload(bidRequest, bidderRequest), + mediaTypes: bidRequest['mediaTypes'], + requestId: bidderRequest.bidderRequestId, + bidId: bidRequest.bidId, + adUnitCode: bidRequest['adUnitCode'], + auctionId: bidRequest['auctionId'], + }; + } + ); + } + return results; + }, + + /** + * 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, request) => { + utils.logInfo('theadx.interpretResponse', 'serverResponse', serverResponse, ' request', request); + + let responses = []; + + if (serverResponse.body) { + let responseBody = serverResponse.body; + + let seatBids = responseBody.seatbid; + + if (!(utils.isEmpty(seatBids) || + utils.isEmpty(seatBids[0].bid))) { + let seatBid = seatBids[0]; + let bid = seatBid.bid[0]; + + // handle any values that may end up undefined + let nullify = (value) => typeof value === 'undefined' ? null : parseInt(value); + + let ttl = null; + if (bid.ext) { + ttl = nullify(bid.ext.ttl) ? nullify(bid.ext.ttl) : 2000; + } + + let bidWidth = nullify(bid.w); + let bidHeight = nullify(bid.h); + + let creative = null + let videoXml = null; + let mediaType = null; + let native = null; + + if (request.mediaTypes && request.mediaTypes.video) { + videoXml = bid.ext.vast_url; + mediaType = VIDEO; + } else if (request.mediaTypes && request.mediaTypes.banner) { + mediaType = BANNER; + creative = bid.adm; + } else if (request.mediaTypes && request.mediaTypes.native) { + mediaType = NATIVE; + const { + assets, + link, + imptrackers, + jstracker + } = bid.ext.native; + native = { + clickUrl: link.url, + clickTrackers: link.clicktrackers || bid.ext.cliu ? [] : undefined, + impressionTrackers: imptrackers || bid.nurl ? [] : undefined, + javascriptTrackers: jstracker ? [jstracker] : undefined + }; + if (bid.nurl) { + native.impressionTrackers.unshift(bid.ext.impu); + native.impressionTrackers.unshift(bid.nurl); + if (native.clickTrackers) { + native.clickTrackers.unshift(bid.ext.cliu); + } + } + + assets.forEach(asset => { + const kind = NATIVEASSETNAMES[asset.id]; + const content = kind && asset[NATIVEPROBS[kind].name]; + if (content) { + native[kind] = content.text || content.value || { + url: content.url, + width: content.w, + height: content.h + }; + } + }); + } + + let response = { + bidderCode: BIDDER_CODE, + requestId: request.bidId, + cpm: bid.price, + width: bidWidth | 0, + height: bidHeight | 0, + ad: creative, + ttl: ttl || 3000, + creativeId: bid.crid, + netRevenue: true, + currency: responseBody.cur, + mediaType: mediaType, + native: native, + }; + if (mediaType == VIDEO && videoXml) { + response.vastUrl = videoXml; + response.videoCacheKey = bid.ext.rid; + } + + responses.push(response); + } + } + return responses; + }, + + /** + * 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) { + utils.logInfo('theadx.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses) + const syncs = []; + + if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { + return syncs; + } + + serverResponses.forEach(resp => { + 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({ + type: 'iframe', + url: syncIframeUrl + }); + }); + } + if (syncOptions.pixelEnabled && syncImageUrls) { + syncImageUrls.forEach(syncImageUrl => { + syncs.push({ + type: 'image', + url: syncImageUrl + }); + }); + } + }); + + return syncs; + }, + +} + +let buildSiteComponent = (bidRequest, bidderRequest) => { + let loc = parseUrl(bidderRequest.refererInfo.referer, { + decodeSearchAsString: true + }); + + let site = { + domain: loc.hostname, + page: loc.href, + id: bidRequest.params.wid, + publisher: { + id: bidRequest.params.pid, + } + }; + if (loc.search) { + site.search = loc.search; + } + if (document) { + let keywords = document.getElementsByTagName('meta')['keywords']; + if (keywords && keywords.content) { + site.keywords = keywords.content; + } + } + + return site; +} + +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); +} + +let buildDeviceComponent = (bidRequest, bidderRequest) => { + let device = { + js: 1, + language: ('language' in navigator) ? navigator.language : null, + ua: ('userAgent' in navigator) ? navigator.userAgent : null, + devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, + dnt: utils.getDNT() ? 1 : 0, + }; + // Include connection info if available + const CONNECTION = navigator.connection || navigator.webkitConnection; + if (CONNECTION && CONNECTION.type) { + device['connectiontype'] = CONNECTION.type; + if (CONNECTION.downlinkMax) { + device['connectionDownlinkMax'] = CONNECTION.downlinkMax; + } + } + + return device; +}; + +let determineOptimalRequestId = (bidRequest, bidderRequest) => { + return bidRequest.bidId; +} + +let extractValidSize = (bidRequest, bidderRequest) => { + let width = null; + let height = null; + + let requestedSizes = []; + let mediaTypes = bidRequest.mediaTypes; + if (mediaTypes && ((mediaTypes.banner && mediaTypes.banner.sizes) || (mediaTypes.video && mediaTypes.video.sizes))) { + if (mediaTypes.banner) { + requestedSizes = mediaTypes.banner.sizes; + } else { + requestedSizes = mediaTypes.video.sizes; + } + } else if (!utils.isEmpty(bidRequest.sizes)) { + requestedSizes = bidRequest.sizes + } + + // Ensure the size array is normalized + let conformingSize = utils.parseSizesInput(requestedSizes); + + if (!utils.isEmpty(conformingSize) && conformingSize[0] != null) { + // Currently only the first size is utilized + let splitSizes = conformingSize[0].split('x'); + + width = parseInt(splitSizes[0]); + height = parseInt(splitSizes[1]); + } + + return { + w: width, + h: height + }; +}; + +let generateVideoComponent = (bidRequest, bidderRequest) => { + let impSize = extractValidSize(bidRequest); + + return { + w: impSize.w, + h: impSize.h + } +} + +let generateBannerComponent = (bidRequest, bidderRequest) => { + let impSize = extractValidSize(bidRequest); + + return { + w: impSize.w, + h: impSize.h + } +} + +let generateNativeComponent = (bidRequest, bidderRequest) => { + const assets = utils._map(bidRequest.mediaTypes.native, (bidParams, key) => { + const props = NATIVEPROBS[key]; + const asset = { + required: bidParams.required & 1, + }; + if (props) { + asset.id = props.id; + asset[props.name] = { + len: bidParams.len, + wmin: bidParams.sizes && bidParams.sizes[0], + hmin: bidParams.sizes && bidParams.sizes[1], + type: props.type + }; + + return asset; + } + }).filter(Boolean); + return { + request: { + assets + } + } +} + +let generateImpBody = (bidRequest, bidderRequest) => { + let mediaTypes = bidRequest.mediaTypes; + + let banner = null; + let video = null; + let native = null; + + if (mediaTypes && mediaTypes.video) { + video = generateVideoComponent(bidRequest, bidderRequest); + } else if (mediaTypes && mediaTypes.banner) { + banner = generateBannerComponent(bidRequest, bidderRequest); + } else if (mediaTypes && mediaTypes.native) { + native = generateNativeComponent(bidRequest, bidderRequest); + } + + const result = { + id: bidRequest.index, + tagid: bidRequest.params.tagId + '', + }; + if (banner) { + result['banner'] = banner; + } + if (video) { + result['video'] = video; + } + if (native) { + result['native'] = native; + } + + return result; +} + +let generatePayload = (bidRequest, bidderRequest) => { + // Generate the expected OpenRTB payload + + let payload = { + id: determineOptimalRequestId(bidRequest, bidderRequest), + site: buildSiteComponent(bidRequest, bidderRequest), + device: buildDeviceComponent(bidRequest, bidderRequest), + imp: [generateImpBody(bidRequest, bidderRequest)], + }; + // return payload; + return JSON.stringify(payload); +}; + +registerBidder(spec); diff --git a/modules/theAdxBidAdapter.md b/modules/theAdxBidAdapter.md new file mode 100644 index 00000000000..2392bfaa819 --- /dev/null +++ b/modules/theAdxBidAdapter.md @@ -0,0 +1,91 @@ +# Overview + +``` +Module Name: TheAdx Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@theadx.com +``` + +# Description + +Module that connects to TheAdx demand sources + +# Test Parameters + +``` + var adUnits = [ + { + code: 'test-div', + sizes: [640,480], + mediaTypes: { + video: { + sizes: [[640, 480]], + } + }, + bids: [ + { + bidder: "theadx", + params: { + pid: 1000, // publisher id + wid: 2000, //website id + tagId: 5000, //zone id + } + } + ] + },{ + code: 'test-div2', + mediaTypes: { + banner: { + sizes: [[320, 50]], + }, + }, + bids: [ + { + bidder: "theadx", + params: { + pid: 1000, // publisher id + wid: 2000, //website id + tagId: 5000, //zone id + } + } + ] + },{ + code: 'test-div3', + 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: "theadx", + params: { + pid: 1000, // publisher id + wid: 2000, //website id + tagId: 5000, //zone id + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/theAdxBidAdapter_spec.js b/test/spec/modules/theAdxBidAdapter_spec.js new file mode 100644 index 00000000000..5381709369c --- /dev/null +++ b/test/spec/modules/theAdxBidAdapter_spec.js @@ -0,0 +1,642 @@ +import { + expect +} from 'chai'; +import { + spec, + internals +} from 'modules/theAdxBidAdapter'; +import { + newBidder +} from 'src/adapters/bidderFactory'; + +describe('TheAdxAdapter', function () { + const adapter = newBidder(spec); + + describe('getUserSyncs', () => { + const USER_SYNC_IFRAME_URL = '//ssp.theadx.com/async_usersync_iframe.html' + const USER_SYNC_IMAGE_URL = '//ssp.theadx.com/async_usersync_image.gif' + + expect(spec.getUserSyncs({ + iframeEnabled: true, + pixelEnabled: true, + }, [{ + body: { + ext: { + sync: { + iframe: [USER_SYNC_IFRAME_URL], + image: [USER_SYNC_IMAGE_URL], + } + } + } + }])).to.deep.equal([{ + type: 'iframe', + url: USER_SYNC_IFRAME_URL + }, + { + type: 'image', + url: USER_SYNC_IMAGE_URL + }, + ]); + }); + + describe('bid validator', function () { + it('rejects a bid that is missing the placementId', function () { + let testBid = {}; + expect(spec.isBidRequestValid(testBid)).to.be.false; + }); + + it('accepts a bid with all the expected parameters', function () { + let testBid = { + params: { + pid: '1', + tagId: '1', + } + }; + + expect(spec.isBidRequestValid(testBid)).to.be.true; + }); + }); + + describe('request builder', function () { + // Taken from the docs, so used as much as is valid + const sampleBidRequest = { + 'bidder': 'tests', + 'bidId': '51ef8751f9aead', + 'params': { + 'pid': '1', + 'tagId': '1', + }, + 'adUnitCode': 'div-gpt-ad-sample', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [ + [300, 250] + ], + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'mediaTypes': { + banner: { + 'sizes': [ + [320, 50], + [300, 250], + [300, 600] + ] + } + } + }; + + const sampleBidderRequest = { + bidderRequestId: 'sample', + refererInfo: { + canonicalUrl: 'http://domain.com/to', + referer: 'http://domain.com/from' + } + } + + it('successfully generates a URL', function () { + const placementId = '1'; + + const bidRequests = [sampleBidRequest]; + + let results = spec.buildRequests(bidRequests, sampleBidderRequest); + let result = results.pop(); + + expect(result.url).to.not.be.undefined; + expect(result.url).to.not.be.null; + + expect(result.url).to.include('tagid=' + placementId); + }); + + it('uses the bidId id as the openRtb request ID', function () { + const bidId = '51ef8751f9aead'; + + let bidRequests = [ + sampleBidRequest + ]; + + let results = spec.buildRequests(bidRequests, sampleBidderRequest); + let result = results.pop(); + + // Double encoded JSON + let payload = JSON.parse(result.data); + + expect(payload).to.not.be.null; + expect(payload.id).to.equal(bidId); + }); + + it('generates the device payload as expected', function () { + let bidRequests = [ + sampleBidRequest + ]; + + let results = spec.buildRequests(bidRequests, sampleBidderRequest); + let result = results.pop(); + + // Double encoded JSON + let payload = JSON.parse(result.data); + + expect(payload).to.not.be.null; + let userData = payload.user; + + expect(userData).to.not.be.null; + }); + + it('generates multiple requests with single imp bodies', function () { + const SECOND_PLACEMENT_ID = '2'; + let firstBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + let secondBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + secondBidRequest.params.tagId = SECOND_PLACEMENT_ID; + + let bidRequests = [ + firstBidRequest, + secondBidRequest + ]; + + let results = spec.buildRequests(bidRequests, sampleBidderRequest); + + expect(results instanceof Array).to.be.true; + expect(results.length).to.equal(2); + + let firstRequest = results[0]; + + // Double encoded JSON + let firstPayload = JSON.parse(firstRequest.data); + + expect(firstPayload).to.not.be.null; + expect(firstPayload.imp).to.not.be.null; + expect(firstPayload.imp.length).to.equal(1); + + expect(firstRequest.url).to.not.be.null; + expect(firstRequest.url.indexOf('tagid=1')).to.be.gt(0); + + let secondRequest = results[1]; + + // Double encoded JSON + let secondPayload = JSON.parse(secondRequest.data); + + expect(secondPayload).to.not.be.null; + expect(secondPayload.imp).to.not.be.null; + expect(secondPayload.imp.length).to.equal(1); + + expect(secondRequest.url).to.not.be.null; + expect(secondRequest.url.indexOf(`tagid=${SECOND_PLACEMENT_ID}`)).to.be.gte(0); + }); + + it('generates a banner request as expected', function () { + // clone the sample for stability + let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + + let results = spec.buildRequests([localBidRequest], sampleBidderRequest); + let result = results.pop(); + + // Double encoded JSON + let payload = JSON.parse(result.data); + + expect(payload).to.not.be.null; + + let imps = payload.imp; + + let firstImp = imps[0]; + + expect(firstImp.banner).to.not.be.null; + + let bannerData = firstImp.banner; + + expect(bannerData.w).to.equal(320); + expect(bannerData.h).to.equal(50); + }); + + it('generates a banner request using a singular adSize instead of an array', function () { + // clone the sample for stability + let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + localBidRequest.sizes = [320, 50]; + localBidRequest.mediaTypes = { + banner: {} + }; + + let results = spec.buildRequests([localBidRequest], sampleBidderRequest); + let result = results.pop(); + + // Double encoded JSON + let payload = JSON.parse(result.data); + + expect(payload).to.not.be.null; + + let imps = payload.imp; + + let firstImp = imps[0]; + + expect(firstImp.banner).to.not.be.null; + + let bannerData = firstImp.banner; + + expect(bannerData.w).to.equal(320); + expect(bannerData.h).to.equal(50); + }); + + it('fails gracefully on an invalid size', function () { + // clone the sample for stability + let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + localBidRequest.sizes = ['x', 'w']; + + localBidRequest.mediaTypes = { + banner: { + sizes: ['y', 'z'] + } + }; + + let results = spec.buildRequests([localBidRequest], sampleBidderRequest); + let result = results.pop(); + + // Double encoded JSON + let payload = JSON.parse(result.data); + + expect(payload).to.not.be.null; + + let imps = payload.imp; + + let firstImp = imps[0]; + + expect(firstImp.banner).to.not.be.null; + + let bannerData = firstImp.banner; + + expect(bannerData.w).to.equal(null); + expect(bannerData.h).to.equal(null); + }); + + it('generates a video request as expected', function () { + // clone the sample for stability + let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + + localBidRequest.mediaTypes = { + video: { + sizes: [ + [326, 256] + ] + } + }; + + let results = spec.buildRequests([localBidRequest], sampleBidderRequest); + let result = results.pop(); + + // Double encoded JSON + let payload = JSON.parse(result.data); + + expect(payload).to.not.be.null; + + let imps = payload.imp; + + let firstImp = imps[0]; + + expect(firstImp.video).to.not.be.null; + + let videoData = firstImp.video; + expect(videoData.w).to.equal(326); + expect(videoData.h).to.equal(256); + }); + + it('generates a native request as expected', function () { + // clone the sample for stability + let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + + localBidRequest.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] + }, + } + }; + + let results = spec.buildRequests([localBidRequest], sampleBidderRequest); + let result = results.pop(); + + // Double encoded JSON + let payload = JSON.parse(result.data); + + expect(payload).to.not.be.null; + + let imps = payload.imp; + + let firstImp = imps[0]; + + expect(firstImp.native).to.not.be.null; + }); + + it('propagates the mediaTypes object in the built request', function () { + let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + + localBidRequest.mediaTypes = { + video: {} + }; + + let results = spec.buildRequests([localBidRequest], sampleBidderRequest); + let result = results.pop(); + + let mediaTypes = result.mediaTypes; + + expect(mediaTypes).to.not.be.null; + expect(mediaTypes).to.not.be.undefined; + expect(mediaTypes.video).to.not.be.null; + expect(mediaTypes.video).to.not.be.undefined; + }); + }); + + describe('response interpreter', function () { + it('returns an empty array when no bids present', function () { + // an empty JSON body indicates no ad was found + + let result = spec.interpretResponse({ + body: '' + }, {}) + + expect(result).to.eql([]); + }); + + it('gracefully fails when a non-JSON body is present', function () { + let result = spec.interpretResponse({ + body: 'THIS IS NOT ' + }, {}) + + expect(result).to.eql([]); + }); + + it('returns a valid bid response on sucessful banner request', function () { + let incomingRequestId = 'XXtestingXX'; + let responsePrice = 3.14 + + let responseCreative = 'sample_creative&{FOR_COVARAGE}'; + + let responseCreativeId = '274'; + let responseCurrency = 'TRY'; + + let responseWidth = 300; + let responseHeight = 250; + let responseTtl = 213; + + let sampleResponse = { + id: '66043f5ca44ecd8f8769093b1615b2d9', + seatbid: [{ + bid: [{ + id: 'c21bab0e-7668-4d8f-908a-63e094c09197', + impid: '1', + price: responsePrice, + adid: responseCreativeId, + crid: responseCreativeId, + adm: responseCreative, + adomain: [ + 'www.domain.com' + ], + cid: '274', + attr: [], + w: responseWidth, + h: responseHeight, + ext: { + ttl: responseTtl + } + }], + seat: '201', + group: 0 + }], + bidid: 'c21bab0e-7668-4d8f-908a-63e094c09197', + cur: responseCurrency + }; + + let sampleRequest = { + bidId: incomingRequestId, + mediaTypes: { + banner: {} + }, + requestId: incomingRequestId + }; + let serverResponse = { + body: sampleResponse + } + let result = spec.interpretResponse(serverResponse, sampleRequest); + + expect(result.length).to.equal(1); + + let processedBid = result[0]; + + // expect(processedBid.requestId).to.equal(incomingRequestId); + expect(processedBid.cpm).to.equal(responsePrice); + expect(processedBid.width).to.equal(responseWidth); + expect(processedBid.height).to.equal(responseHeight); + expect(processedBid.ad).to.equal(responseCreative); + expect(processedBid.ttl).to.equal(responseTtl); + expect(processedBid.creativeId).to.equal(responseCreativeId); + expect(processedBid.netRevenue).to.equal(true); + expect(processedBid.currency).to.equal(responseCurrency); + }); + + it('returns an valid bid response on sucessful video request', function () { + let incomingRequestId = 'XXtesting-275XX'; + let responsePrice = 6 + let vast_url = 'http://theadx.com/vast?rid=a8ae0b48-a8db-4220-ba0c-7458f452b1f5&{FOR_COVARAGE}' + + let responseCreativeId = '1556'; + let responseCurrency = 'TRY'; + + let responseWidth = 284; + let responseHeight = 285; + let responseTtl = 286; + + let sampleResponse = { + id: '1234567890', + seatbid: [{ + bid: [{ + id: 'a8ae0b48-a8db-4220-ba0c-7458f452b1f5', + impid: '1', + price: responsePrice, + adid: responseCreativeId, + crid: responseCreativeId, + cid: '270', + attr: [], + w: responseWidth, + h: responseHeight, + ext: { + vast_url: vast_url, + ttl: responseTtl + } + }], + seat: '201', + group: 0 + }], + bidid: 'a8ae0b48-a8db-4220-ba0c-7458f452b1f5', + cur: 'TRY' + }; + + let sampleRequest = { + bidId: incomingRequestId, + mediaTypes: { + video: {} + }, + requestId: incomingRequestId + }; + + let result = spec.interpretResponse({ + body: sampleResponse + }, + sampleRequest + ); + + expect(result.length).to.equal(1); + + let processedBid = result[0]; + // expect(processedBid.requestId).to.equal(incomingRequestId); + expect(processedBid.cpm).to.equal(responsePrice); + expect(processedBid.width).to.equal(responseWidth); + expect(processedBid.height).to.equal(responseHeight); + expect(processedBid.ad).to.equal(null); + expect(processedBid.ttl).to.equal(responseTtl); + expect(processedBid.creativeId).to.equal(responseCreativeId); + expect(processedBid.netRevenue).to.equal(true); + expect(processedBid.currency).to.equal(responseCurrency); + expect(processedBid.vastUrl).to.equal(vast_url); + }); + + it('returns an valid bid response on sucessful native request', function () { + let incomingRequestId = 'XXtesting-275XX'; + let responsePrice = 6 + let nurl = 'https://app.theadx.com/ixc?rid=02aefd80-2df9-11e9-896d-d33384d77f5c&time=v-1549888312715&sp=1WzMjcRpeyk%3D'; + let linkUrl = 'https%3A%2F%2Fapp.theadx.com%2Fgclick%3Frid%3D02aefd80-2df9-11e9-896d-d33384d77f5c%26url%3Dhttps%253A%252F%252Fwww.theadx.com%252Ftr%252Fhedeflemeler' + let responseCreativeId = '1556'; + let responseCurrency = 'TRY'; + + let responseTtl = 286; + + let sampleResponse = { + id: '1234567890', + seatbid: [{ + bid: [{ + id: 'a8ae0b48-a8db-4220-ba0c-7458f452b1f5', + impid: '1', + nurl: nurl, + price: responsePrice, + adid: responseCreativeId, + crid: responseCreativeId, + cid: '270', + attr: [], + ext: { + ttl: responseTtl, + native: { + ver: 1, + link: { + url: linkUrl + }, + assets: [{ + id: 3, + img: { + url: '//ads.theadx.com/winwords/120/17508/154712307258.73.jpg', + h: 627, + w: 1200 + } + }, { + id: 0, + title: { + ext: 'SELF-MANAGED DSP' + } + }, { + id: 5, + data: { + value: 'Sponsored by Theadx' + } + }, { + id: 4, + data: { + value: 'Gerçek Zamanlı Self-Managed DSP ile kampanya oluşturmak ve yönetmek çok kolay ' + } + }, { + id: 2, + img: { + url: '//ads.theadx.com/winwords/120/17508/154712307258.74.png', + h: 128, + w: 128 + } + }] + }, + + rid: '02ac3e60-2df9-11e9-9d09-bba751e172da', + impu: 'https://ssp.theadx.com/ixc?rid=02ac3e60-2df9-11e9-9d09-bba751e172da&time=1549888312719&tid=1', + cliu: 'https://ssp.theadx.com/click?trid=02ac3e60-2df9-11e9-9d09-bba751e172da' + + } + }], + seat: '201', + group: 0 + }], + bidid: 'a8ae0b48-a8db-4220-ba0c-7458f452b1f5', + cur: 'TRY' + }; + + let sampleRequest = { + bidId: incomingRequestId, + 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] + } + + }, + }, + requestId: incomingRequestId + }; + + let result = spec.interpretResponse({ + body: sampleResponse + }, + sampleRequest + ); + + expect(result.length).to.equal(1); + + let processedBid = result[0]; + // expect(processedBid.requestId).to.equal(incomingRequestId); + expect(processedBid.cpm).to.equal(responsePrice); + expect(processedBid.width).to.equal(0); + expect(processedBid.height).to.equal(0); + expect(processedBid.ad).to.equal(null); + expect(processedBid.ttl).to.equal(responseTtl); + expect(processedBid.creativeId).to.equal(responseCreativeId); + expect(processedBid.netRevenue).to.equal(true); + expect(processedBid.currency).to.equal(responseCurrency); + expect(processedBid.native.impressionTrackers[0]).to.equal(nurl); + expect(processedBid.native.clickUrl).to.equal(linkUrl); + }); + }); +}); From edf6f405915f0c19349b8ecf547df77427a40c80 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Tue, 26 Feb 2019 17:46:40 +0200 Subject: [PATCH 1033/1594] Cleanmedianet: Add cleanmedianet bidder adapter (#3582) * Add cleanmedianet bidder adapter * Use passed in url & utils url parsing function --- modules/cleanmedianetBidAdapter.js | 292 +++++++++ modules/cleanmedianetBidAdapter.md | 66 ++ .../modules/cleanmedianetBidAdapter_spec.js | 583 ++++++++++++++++++ 3 files changed, 941 insertions(+) create mode 100644 modules/cleanmedianetBidAdapter.js create mode 100644 modules/cleanmedianetBidAdapter.md create mode 100644 test/spec/modules/cleanmedianetBidAdapter_spec.js diff --git a/modules/cleanmedianetBidAdapter.js b/modules/cleanmedianetBidAdapter.js new file mode 100644 index 00000000000..325b17ec543 --- /dev/null +++ b/modules/cleanmedianetBidAdapter.js @@ -0,0 +1,292 @@ +import * as utils from '../src/utils'; +import { parse } from '../src/url'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; +import { Renderer } from '../src/Renderer'; +import { BANNER, VIDEO } from '../src/mediaTypes'; + +export const helper = { + startsWith: function(str, search) { + return str.substr(0, search.length) === search; + }, + getMediaType: function(bid) { + if (bid.ext) { + if (bid.ext.media_type) { + return bid.ext.media_type.toLowerCase(); + } else if (bid.ext.vast_url) { + return VIDEO; + } else { + return BANNER; + } + } + return BANNER; + } +}; + +export const spec = { + code: 'cleanmedianet', + aliases: [], + supportedMediaTypes: [BANNER, VIDEO], + + isBidRequestValid: function(bid) { + return ( + !!bid.params.supplyPartnerId && + typeof bid.params.supplyPartnerId === 'string' && + (typeof bid.params.bidfloor === 'undefined' || + typeof bid.params.bidfloor === 'number') && + (typeof bid.params['adpos'] === 'undefined' || + typeof bid.params['adpos'] === 'number') && + (typeof bid.params['protocols'] === 'undefined' || + Array.isArray(bid.params['protocols'])) && + (typeof bid.params.instl === 'undefined' || + bid.params.instl === 0 || + bid.params.instl === 1) + ); + }, + + buildRequests: function(validBidRequests, bidderRequest) { + return validBidRequests.map(bidRequest => { + const { + adUnitCode, + auctionId, + mediaTypes, + params, + sizes, + transactionId + } = bidRequest; + const baseEndpoint = 'https://bidder.cleanmediaads.com'; + const rtbEndpoint = + `${baseEndpoint}/r/${ + params.supplyPartnerId + }/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + + (params.query ? '&' + params.query : ''); + let url = + config.getConfig('pageUrl') || bidderRequest.refererInfo.referer; + + const rtbBidRequest = { + id: auctionId, + site: { + domain: parse(url).hostname, + page: url, + ref: bidderRequest.refererInfo.referer + }, + device: { + ua: navigator.userAgent + }, + imp: [], + ext: {} + }; + + if ( + bidderRequest.gdprConsent && + bidderRequest.gdprConsent.consentString && + bidderRequest.gdprConsent.gdprApplies + ) { + rtbBidRequest.ext.gdpr_consent = { + consent_string: bidderRequest.gdprConsent.consentString, + consent_required: bidderRequest.gdprConsent.gdprApplies + }; + } + + const imp = { + id: transactionId, + instl: params.instl === 1 ? 1 : 0, + tagid: adUnitCode, + bidfloor: params.bidfloor || 0, + bidfloorcur: 'USD', + secure: helper.startsWith( + utils.getTopWindowUrl().toLowerCase(), + 'http://' + ) + ? 0 + : 1 + }; + + const hasFavoredMediaType = + params.favoredMediaType && + this.supportedMediaTypes.includes(params.favoredMediaType); + + if (!mediaTypes || mediaTypes.banner) { + if (!hasFavoredMediaType || params.favoredMediaType === BANNER) { + const bannerImp = Object.assign({}, imp, { + banner: { + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, + pos: params.pos || 0, + topframe: bidderRequest.refererInfo.reachedTop + } + }); + rtbBidRequest.imp.push(bannerImp); + } + } + + if (mediaTypes && mediaTypes.video) { + if (!hasFavoredMediaType || params.favoredMediaType === VIDEO) { + const videoImp = Object.assign({}, imp, { + video: { + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, + protocols: params.protocols || [1, 2, 3, 4, 5, 6], + pos: params.pos || 0, + ext: { + context: mediaTypes.video.context + } + } + }); + rtbBidRequest.imp.push(videoImp); + } + } + + if (rtbBidRequest.imp.length === 0) { + return; + } + + return { + method: 'POST', + url: rtbEndpoint, + data: rtbBidRequest, + bidRequest + }; + }); + }, + + interpretResponse: function(serverResponse, bidRequest) { + const response = serverResponse && serverResponse.body; + if (!response) { + utils.logError('empty response'); + return []; + } + + const bids = response.seatbid.reduce( + (acc, seatBid) => acc.concat(seatBid.bid), + [] + ); + let outBids = []; + + bids.forEach(bid => { + const outBid = { + adId: bidRequest.bidRequest.adUnitCode, + requestId: bidRequest.bidRequest.bidId, + cpm: bid.price, + width: bid.w, + height: bid.h, + ttl: 60 * 10, + creativeId: bid.crid, + netRevenue: true, + currency: bid.cur || response.cur, + adUnitCode: bidRequest.bidRequest.adUnitCode, + mediaType: helper.getMediaType(bid) + }; + + 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 = utils.deepAccess( + bidRequest.bidRequest, + 'mediaTypes.video.context' + ); + outBids.push( + Object.assign({}, outBid, { + vastUrl: bid.ext.vast_url, + vastXml: bid.adm, + renderer: + context === 'outstream' + ? newRenderer(bidRequest.bidRequest, bid) + : undefined + }) + ); + } + } + }); + return outBids; + }, + + getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + const syncs = []; + const gdprApplies = + gdprConsent && typeof gdprConsent.gdprApplies === 'boolean' + ? gdprConsent.gdprApplies + : false; + const suffix = gdprApplies + ? 'gc=' + encodeURIComponent(gdprConsent.consentString) + : 'gc=missing'; + serverResponses.forEach(resp => { + if (resp.body) { + const bidResponse = resp.body; + if (bidResponse.ext && Array.isArray(bidResponse.ext['utrk'])) { + bidResponse.ext['utrk'].forEach(pixel => { + const url = + pixel.url + + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); + return syncs.push({ type: pixel.type, url }); + }); + } + if (Array.isArray(bidResponse.seatbid)) { + bidResponse.seatbid.forEach(seatBid => { + if (Array.isArray(seatBid.bid)) { + seatBid.bid.forEach(bid => { + if (bid.ext && Array.isArray(bid.ext['utrk'])) { + bid.ext['utrk'].forEach(pixel => { + const url = + pixel.url + + (pixel.url.indexOf('?') > 0 + ? '&' + suffix + : '?' + suffix); + return syncs.push({ type: pixel.type, url }); + }); + } + }); + } + }); + } + } + }); + return syncs; + } +}; + +function newRenderer(bidRequest, bid, rendererOptions = {}) { + const renderer = Renderer.install({ + url: + (bidRequest.params && bidRequest.params.rendererUrl) || + (bid.ext && bid.ext.renderer_url) || + '//s.wlplayer.com/video/latest/renderer.js', + config: rendererOptions, + loaded: false + }); + try { + renderer.setRender(renderOutstream); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + return renderer; +} + +function renderOutstream(bid) { + bid.renderer.push(() => { + const unitId = bid.adUnitCode + '/' + bid.adId; + window['GamoshiPlayer'].renderAd({ + id: unitId, + debug: window.location.href.indexOf('pbjsDebug') >= 0, + placement: document.getElementById(bid.adUnitCode), + width: bid.width, + height: bid.height, + events: { + ALL_ADS_COMPLETED: () => + window.setTimeout(() => { + window['GamoshiPlayer'].removeAd(unitId); + }, 300) + }, + vastUrl: bid.vastUrl, + vastXml: bid.vastXml + }); + }); +} + +registerBidder(spec); diff --git a/modules/cleanmedianetBidAdapter.md b/modules/cleanmedianetBidAdapter.md new file mode 100644 index 00000000000..f2bc8feb0f0 --- /dev/null +++ b/modules/cleanmedianetBidAdapter.md @@ -0,0 +1,66 @@ +# Overview + +``` +Module Name: Clean Media Net Adapter +Module Type: Bidder Adapter +Maintainer: dev@cleanmedia.net +``` + +# Description + +Connects to Clean Media Net's Programmatic advertising platform as a service. + +Clean Media bid adapter supports Banner & Video (Instream and Outstream). +The *only* required parameter (in the `params` section) is the `supplyPartnerId` parameter. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'cleanmedianet', + params: { + // ID of the supply partner you created in the Clean Media Net dashboard + supplyPartnerId: '1253', + // OPTIONAL: custom bid floor + bidfloor: 0.01, + // OPTIONAL: if you know the ad position on the page, specify it here + // (this corresponds to "Ad Position" in OpenRTB 2.3, section 5.4) + //adpos: 1, + // OPTIONAL: whether this is an interstitial placement (0 or 1) + // (see "instl" property in "Imp" object in the OpenRTB 2.3, section 3.2.2) + //instl: 0 + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + sizes: [[300, 250]], + mediaTypes: { + video: { + context: 'outstream', + playerSize: [300, 250] + } + }, + bids: [ { + bidder: 'cleanmedianet', + params: { + // ID of the supply partner you created in the dashboard + supplyPartnerId: '1254', + // OPTIONAL: custom bid floor + bidfloor: 0.01, + // OPTIONAL: if you know the ad position on the page, specify it here + // (this corresponds to "Ad Position" in OpenRTB 2.3, section 5.4) + //adpos: 1, + // OPTIONAL: whether this is an interstitial placement (0 or 1) + // (see "instl" property in "Imp" object in the OpenRTB 2.3, section 3.2.2) + //instl: 0 + } + }] + } +]; +``` diff --git a/test/spec/modules/cleanmedianetBidAdapter_spec.js b/test/spec/modules/cleanmedianetBidAdapter_spec.js new file mode 100644 index 00000000000..d68505604bc --- /dev/null +++ b/test/spec/modules/cleanmedianetBidAdapter_spec.js @@ -0,0 +1,583 @@ +import { expect } from 'chai'; +import { spec } from 'modules/cleanmedianetBidAdapter'; +import { helper } from 'modules/cleanmedianetBidAdapter'; +import * as utils from 'src/utils'; +import { newBidder } from '../../../src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +const supplyPartnerId = '123'; +const adapter = newBidder(spec); +describe('CleanmedianetAdapter', function() { + describe('Is String start with search ', function() { + it('check if a string started with', function() { + expect(helper.startsWith('cleanmediaads.com', 'cleanmediaads')).to.equal( + true + ); + }); + }); + + 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 validate supply-partner ID', function() { + expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect( + spec.isBidRequestValid({ params: { supplyPartnerId: 123 } }) + ).to.equal(false); + expect( + spec.isBidRequestValid({ params: { supplyPartnerId: '123' } }) + ).to.equal(true); + }); + + it('should validate bid floor', function() { + expect( + spec.isBidRequestValid({ params: { supplyPartnerId: '123' } }) + ).to.equal(true); // bidfloor has a default + expect( + spec.isBidRequestValid({ + params: { supplyPartnerId: '123', bidfloor: '123' } + }) + ).to.equal(false); + expect( + spec.isBidRequestValid({ + params: { supplyPartnerId: '123', bidfloor: 0.1 } + }) + ).to.equal(true); + }); + + it('should validate adpos', function() { + expect( + spec.isBidRequestValid({ params: { supplyPartnerId: '123' } }) + ).to.equal(true); // adpos has a default + expect( + spec.isBidRequestValid({ + params: { supplyPartnerId: '123', adpos: '123' } + }) + ).to.equal(false); + expect( + spec.isBidRequestValid({ + params: { supplyPartnerId: '123', adpos: 0.1 } + }) + ).to.equal(true); + }); + + it('should validate instl', function() { + expect( + spec.isBidRequestValid({ params: { supplyPartnerId: '123' } }) + ).to.equal(true); // adpos has a default + expect( + spec.isBidRequestValid({ + params: { supplyPartnerId: '123', instl: '123' } + }) + ).to.equal(false); + expect( + spec.isBidRequestValid({ + params: { supplyPartnerId: '123', instl: -1 } + }) + ).to.equal(false); + expect( + spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: 0 } }) + ).to.equal(true); + expect( + spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: 1 } }) + ).to.equal(true); + expect( + spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: 2 } }) + ).to.equal(false); + }); + }); + + describe('buildRequests', function() { + const bidRequest = { + adUnitCode: 'adunit-code', + auctionId: '1d1a030790a475', + mediaTypes: { + banner: {} + }, + params: { + supplyPartnerId: supplyPartnerId + }, + sizes: [[300, 250], [300, 600]], + transactionId: 'a123456789', + refererInfo: { referer: 'http://examplereferer.com' }, + gdprConsent: { + consentString: 'some string', + gdprApplies: true + } + }; + it('returns an array', function() { + let response; + response = spec.buildRequests([]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + response = spec.buildRequests([bidRequest], bidRequest); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(1); + const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), { + auctionId: '1', + adUnitCode: 'a' + }); + const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), { + auctionId: '1', + adUnitCode: 'b' + }); + response = spec.buildRequests([adUnit1, adUnit2], bidRequest); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + }); + + it('builds request correctly', function() { + let stub = sinon + .stub(utils, 'getTopWindowUrl') + .returns('http://www.test.com/page.html'); + let bidRequest2 = deepClone(bidRequest); + bidRequest2.refererInfo.referer = 'http://www.test.com/page.html'; + let response = spec.buildRequests([bidRequest], bidRequest2)[0]; + expect(response.data.site.domain).to.equal('www.test.com'); + expect(response.data.site.page).to.equal('http://www.test.com/page.html'); + expect(response.data.site.ref).to.equal('http://www.test.com/page.html'); + expect(response.data.imp.length).to.equal(1); + expect(response.data.imp[0].id).to.equal(bidRequest.transactionId); + expect(response.data.imp[0].instl).to.equal(0); + expect(response.data.imp[0].tagid).to.equal(bidRequest.adUnitCode); + expect(response.data.imp[0].bidfloor).to.equal(0); + expect(response.data.imp[0].bidfloorcur).to.equal('USD'); + const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); + bidRequestWithInstlEquals1.params.instl = 1; + response = spec.buildRequests( + [bidRequestWithInstlEquals1], + bidRequest2 + )[0]; + expect(response.data.imp[0].instl).to.equal( + bidRequestWithInstlEquals1.params.instl + ); + const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); + bidRequestWithInstlEquals0.params.instl = 1; + response = spec.buildRequests( + [bidRequestWithInstlEquals0], + bidRequest2 + )[0]; + expect(response.data.imp[0].instl).to.equal( + bidRequestWithInstlEquals0.params.instl + ); + const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); + bidRequestWithBidfloorEquals1.params.bidfloor = 1; + response = spec.buildRequests( + [bidRequestWithBidfloorEquals1], + bidRequest2 + )[0]; + expect(response.data.imp[0].bidfloor).to.equal( + bidRequestWithBidfloorEquals1.params.bidfloor + ); + stub.restore(); + }); + + it('builds request banner object correctly', function() { + let response; + const bidRequestWithBanner = utils.deepClone(bidRequest); + bidRequestWithBanner.mediaTypes = { + banner: { + sizes: [[300, 250], [120, 600]] + } + }; + response = spec.buildRequests([bidRequestWithBanner], bidRequest)[0]; + expect(response.data.imp[0].banner.w).to.equal( + bidRequestWithBanner.mediaTypes.banner.sizes[0][0] + ); + expect(response.data.imp[0].banner.h).to.equal( + bidRequestWithBanner.mediaTypes.banner.sizes[0][1] + ); + expect(response.data.imp[0].banner.pos).to.equal(0); + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); + bidRequestWithPosEquals1.params.pos = 1; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; + expect(response.data.imp[0].banner.pos).to.equal( + bidRequestWithPosEquals1.params.pos + ); + }); + + it('builds request video object correctly', function() { + let response; + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes = { + video: { + sizes: [[300, 250], [120, 600]] + } + }; + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[0].video.w).to.equal( + bidRequestWithVideo.mediaTypes.video.sizes[0][0] + ); + expect(response.data.imp[0].video.h).to.equal( + bidRequestWithVideo.mediaTypes.video.sizes[0][1] + ); + expect(response.data.imp[0].video.pos).to.equal(0); + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.params.pos = 1; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; + expect(response.data.imp[0].video.pos).to.equal( + bidRequestWithPosEquals1.params.pos + ); + }); + + it('builds request video object correctly with context', function() { + let response; + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes = { + video: { + context: 'instream' + } + }; + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal('instream'); + bidRequestWithVideo.mediaTypes.video.context = 'outstream'; + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.mediaTypes.video.context = 'outstream'; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal('outstream'); + + const bidRequestWithPosEquals2 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals2.mediaTypes.video.context = null; + response = spec.buildRequests([bidRequestWithPosEquals2], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal(null); + }); + + it('builds request with gdpr consent', function() { + let response = spec.buildRequests([bidRequest], bidRequest)[0]; + expect(response.data.ext).to.have.property('gdpr_consent'); + expect(response.data.ext.gdpr_consent.consent_string).to.equal( + 'some string' + ); + expect(response.data.ext.gdpr_consent.consent_required).to.equal(true); + }); + }); + + describe('interpretResponse', function() { + const bannerBidRequest = { + adUnitCode: 'adunit-code', + auctionId: '1d1a030790a475', + mediaTypes: { + banner: {} + }, + params: { + supplyPartnerId: supplyPartnerId + }, + sizes: [[300, 250], [300, 600]], + transactionId: 'a123456789', + bidId: '111', + refererInfo: { referer: 'http://examplereferer.com' } + }; + + const videoBidRequest = { + adUnitCode: 'adunit-code', + auctionId: '1d1a030790a475', + mediaTypes: { + video: {} + }, + params: { + supplyPartnerId: supplyPartnerId + }, + sizes: [[300, 250], [300, 600]], + transactionId: 'a123456789', + bidId: '111', + refererInfo: { referer: 'http://examplereferer.com' } + }; + + const rtbResponse = { + id: 'imp_5b05b9fde4b09084267a556f', + bidid: 'imp_5b05b9fde4b09084267a556f', + cur: 'USD', + ext: { + utrk: [ + { type: 'iframe', url: '//bidder.cleanmediaads.com/user/sync/1' }, + { type: 'image', url: '//bidder.cleanmediaads.com/user/sync/2' } + ] + }, + seatbid: [ + { + seat: 'seat1', + group: 0, + bid: [ + { + id: '0', + impid: '1', + price: 2.016, + adid: '579ef31bfa788b9d2000d562', + nurl: + 'https://bidder.cleanmediaads.com/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', + adm: + '', + adomain: ['aaa.com'], + cid: '579ef268fa788b9d2000d55c', + crid: '579ef31bfa788b9d2000d562', + attr: [], + h: 600, + w: 120, + ext: { + vast_url: 'http://my.vast.com', + utrk: [{ type: 'iframe', url: '//p.partner1.io/user/sync/1' }] + } + } + ] + }, + { + seat: 'seat2', + group: 0, + bid: [ + { + id: '1', + impid: '1', + price: 3, + adid: '542jlhdfd2112jnjf3x', + nurl: + 'https://bidder.cleanmediaads.com/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', + adm: + ' ', + adomain: ['bbb.com'], + cid: 'fgdlwjh2498ydjhg1', + crid: 'kjh34297ydh2133d', + attr: [], + h: 250, + w: 300, + ext: { + utrk: [{ type: 'image', url: '//p.partner2.io/user/sync/1' }] + } + } + ] + } + ] + }; + + it('returns an empty array on missing response', function() { + let response; + + response = spec.interpretResponse(undefined, { + bidRequest: bannerBidRequest + }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + + response = spec.interpretResponse({}, { bidRequest: bannerBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + }); + + it('aggregates banner bids from all seat bids', function() { + const response = spec.interpretResponse( + { body: rtbResponse }, + { bidRequest: bannerBidRequest } + ); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(1); + + const ad0 = response[0]; + expect(ad0.requestId).to.equal(bannerBidRequest.bidId); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[1].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[1].bid[0].h); + expect(ad0.ttl).to.equal(60 * 10); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.currency).to.equal( + rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD' + ); + expect(ad0.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); + expect(ad0.vastXml).to.be.an('undefined'); + expect(ad0.vastUrl).to.be.an('undefined'); + }); + + it('aggregates video bids from all seat bids', function() { + const response = spec.interpretResponse( + { body: rtbResponse }, + { bidRequest: videoBidRequest } + ); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(1); + + const ad0 = response[0]; + expect(ad0.requestId).to.equal(videoBidRequest.bidId); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[0].bid[0].h); + expect(ad0.ttl).to.equal(60 * 10); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[0].bid[0].crid); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.currency).to.equal( + rtbResponse.seatbid[0].bid[0].cur || rtbResponse.cur || 'USD' + ); + expect(ad0.ad).to.be.an('undefined'); + expect(ad0.vastXml).to.equal(rtbResponse.seatbid[0].bid[0].adm); + expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[0].bid[0].ext.vast_url); + }); + + it('aggregates user-sync pixels', function() { + const response = spec.getUserSyncs({}, [{ body: rtbResponse }]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(4); + expect(response[0].type).to.equal(rtbResponse.ext.utrk[0].type); + expect(response[0].url).to.equal( + rtbResponse.ext.utrk[0].url + '?gc=missing' + ); + expect(response[1].type).to.equal(rtbResponse.ext.utrk[1].type); + expect(response[1].url).to.equal( + rtbResponse.ext.utrk[1].url + '?gc=missing' + ); + expect(response[2].type).to.equal( + rtbResponse.seatbid[0].bid[0].ext.utrk[0].type + ); + expect(response[2].url).to.equal( + rtbResponse.seatbid[0].bid[0].ext.utrk[0].url + '?gc=missing' + ); + expect(response[3].type).to.equal( + rtbResponse.seatbid[1].bid[0].ext.utrk[0].type + ); + expect(response[3].url).to.equal( + rtbResponse.seatbid[1].bid[0].ext.utrk[0].url + '?gc=missing' + ); + }); + + it('supports configuring outstream renderers', function() { + const videoResponse = { + id: '64f32497-b2f7-48ec-9205-35fc39894d44', + bidid: 'imp_5c24924de4b0d106447af333', + cur: 'USD', + seatbid: [ + { + seat: '3668', + group: 0, + bid: [ + { + id: 'gb_1', + impid: 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + price: 5.0, + adid: '1274', + nurl: + 'https://bidder.cleanmediaads.com/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&p=${AUCTION_PRICE}', + adomain: [], + adm: + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + cid: '3668', + crid: '1274', + cat: [], + attr: [], + h: 250, + w: 300, + ext: { + vast_url: + 'https://bidder.cleanmediaads.com/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + imptrackers: [ + 'https://bidder.cleanmediaads.com/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1' + ] + } + } + ] + } + ], + ext: { + utrk: [ + { + type: 'image', + url: + 'https://bidder.cleanmediaads.com/pix/1275/scm?cb=1545900621675' + } + ] + } + }; + const videoRequest = deepClone(videoBidRequest); + videoRequest.mediaTypes.video.context = 'outstream'; + const result = spec.interpretResponse( + { body: videoResponse }, + { bidRequest: videoRequest } + ); + expect(result[0].renderer).to.not.equal(undefined); + }); + + it('validates in/existing of gdpr consent', function() { + let videoResponse = { + id: '64f32497-b2f7-48ec-9205-35fc39894d44', + bidid: 'imp_5c24924de4b0d106447af333', + cur: 'USD', + seatbid: [ + { + seat: '3668', + group: 0, + bid: [ + { + id: 'gb_1', + impid: 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + price: 5.0, + adid: '1274', + nurl: + 'https://bidder.cleanmediaads.com/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&p=${AUCTION_PRICE}', + adomain: [], + adm: + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + cid: '3668', + crid: '1274', + cat: [], + attr: [], + h: 250, + w: 300, + ext: { + vast_url: + 'https://bidder.cleanmediaads.com/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + imptrackers: [ + 'https://bidder.cleanmediaads.com/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1' + ] + } + } + ] + } + ], + ext: { + utrk: [ + { + type: 'image', + url: + 'https://bidder.cleanmediaads.com/pix/1275/scm?cb=1545900621675' + } + ] + } + }; + let gdprConsent = { + gdprApplies: true, + consentString: 'consent string' + }; + let result = spec.getUserSyncs( + {}, + [{ body: videoResponse }], + gdprConsent + ); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal( + 'https://bidder.cleanmediaads.com/pix/1275/scm?cb=1545900621675&gc=consent%20string' + ); + + gdprConsent.gdprApplies = false; + result = spec.getUserSyncs({}, [{ body: videoResponse }], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal( + 'https://bidder.cleanmediaads.com/pix/1275/scm?cb=1545900621675&gc=missing' + ); + + videoResponse.ext.utrk[0].url = + 'https://bidder.cleanmediaads.com/pix/1275/scm'; + result = spec.getUserSyncs({}, [{ body: videoResponse }], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal( + 'https://bidder.cleanmediaads.com/pix/1275/scm?gc=missing' + ); + }); + }); +}); From eb50bd908224b7950a2461d0a6ddcc85fad9b26a Mon Sep 17 00:00:00 2001 From: Maciej Lopacinski Date: Tue, 26 Feb 2019 18:00:04 +0100 Subject: [PATCH 1034/1594] LiveYield Analytics Adapter DfP Support (#3506) * LiveYield Analytics Adapter * tests corrections * fixed getPlacementOrAdUnitCode function * DFP support * SRTA-399 WIP * DFP handler corrections, tests added * test added * docs added * SRTA-399 LiveYield DfP support SRTA-399 Minor reformats impression value fixed changed path to rta params corrections resolveSlot fixed postprocess() param fixed docs update imprVal(), imprPartner() impl added SRTA-399 Docs, no console.log * SRTA-410 Default implementations based on hb_adid * SRTA-399 chai usage fix --- modules/liveyieldAnalyticsAdapter.js | 302 +++++++++++++++-- .../modules/liveyieldAnalyticsAdapter_spec.js | 313 +++++++++++++++++- 2 files changed, 581 insertions(+), 34 deletions(-) diff --git a/modules/liveyieldAnalyticsAdapter.js b/modules/liveyieldAnalyticsAdapter.js index a6ac9765957..75e06dd56a2 100644 --- a/modules/liveyieldAnalyticsAdapter.js +++ b/modules/liveyieldAnalyticsAdapter.js @@ -26,28 +26,174 @@ const adapterConfig = { }, /** - * Function used to extract placement/adUnitCode (depending on prebid version). + * Function used to extract placement/adUnitCode (depending on prebid + * version). * * The extracted value will be passed to the `getAdUnitName()` for mapping into * human friendly value. */ getPlacementOrAdUnitCode: function(bid, version) { return version[0] === '0' ? bid.placementCode : bid.adUnitCode; + }, + + /** + * Optional reference to Google Publisher Tag (gpt) + */ + googlePublisherTag: false, + + /** + * Do not override unless instructed. Useful for testing. Allows to redefined + * the event that triggers the ad impression event. + */ + wireGooglePublisherTag: function(gpt, cb) { + gpt.pubads().addEventListener('slotRenderEnded', function(event) { + cb(event.slot); + }); + }, + + /** + * Map which keeps BID_WON events. Keyed by adId property. + */ + prebidWinnersCache: {}, + + /** + * Map which keeps all BID_RESPONSE events. Keyed by adId property. + */ + prebidBidResponsesCache: {}, + + /** + * Decides if the GPT slot contains prebid ad impression or not. + * + * When BID_WON event is emitted adid is added to prebidWinnersCache, + * then we check if prebidWinnersCache contains slot.hb_adid. + * + * This function is optional and used only when googlePublisherTag is provided. + * + * Default implementation uses slot's `hb_adid` targeting parameter. + * + * @param slot the gpt slot + */ + isPrebidAdImpression: function(slot) { + const hbAdIdTargeting = slot.getTargeting('hb_adid'); + if (hbAdIdTargeting.length > 0) { + const hbAdId = hbAdIdTargeting[0]; + return typeof this.prebidWinnersCache[hbAdId] !== 'undefined'; + } + return false; + }, + + /** + * If isPrebidAdImpression decides that slot contain prebid ad impression, + * this function should return prebids highest ad impression partner for that + * slot. + * + * Default implementation uses slot's `hb_adid` targeting value to find + * highest bid response and when present then returns `bidder`. + * + * @param instanceConfig merged analytics adapter instance configuration + * @param slot the gpt slot for which the name of the highest bidder shall be + * returned + * @param version the version of the prebid.js library + */ + getHighestPrebidAdImpressionPartner: function(instanceConfig, slot, version) { + const bid = getHighestPrebidBidResponseBySlotTargeting( + instanceConfig, + slot, + version + ); + + // this is bid response event has `bidder` while bid won has bidderCode property + return bid ? bid.bidderCode || bid.bidder : null; + }, + + /** + * If isPrebidAdImpression decides that slot contain prebid ad impression, + * this function should return prebids highest ad impression value for that + * slot. + * + * Default implementation uses slot's `hb_adid` targeting value to find + * highest bid response and when present then returns `cpm`. + * + * @param instanceConfig merged analytics adapter instance configuration + * @param slot the gpt slot for which the highest ad impression value shall be + * returned + * @param version the version of the prebid.js library + */ + getHighestPrebidAdImpressionValue: function(instanceConfig, slot, version) { + const bid = getHighestPrebidBidResponseBySlotTargeting( + instanceConfig, + slot, + version + ); + + return bid ? bid.cpm : null; + }, + + /** + * This function should return proper ad unit name for slot given as a + * parameter. Unit names returned by this function should be meaningful, for + * example 'FOO_728x90_TOP'. The values returned shall be inline with + * `getAdUnitName`. + * + * Required when googlePublisherTag is defined. + * + * @param slot the gpt slot to translate into friendly name + * @param version the version of the prebid.js library + */ + getAdUnitNameByGooglePublisherTagSlot: (slot, version) => { + throw 'Required when googlePublisherTag is defined.'; + }, + + /** + * Function used to prepare and return parameters provided to rta. + * More information will be in docs given by LiveYield team. + * + * When googlePublisherTag is not provided, second parameter(slot) will always + * equal null. + * + * @param resolution the original ad impression details + * @param slot gpt slot, will be empty in pure Prebid.js-case (when + * googlePublisherTag is not provided) + * @param hbPartner the name of the highest bidding partner + * @param hbValue the value of the highest bid + * @param version version of the prebid.js library + */ + postProcessResolution: (resolution, slot, hbPartner, hbValue, version) => { + return resolution; } }; const cpmToMicroUSD = v => (isNaN(v) ? 0 : Math.round(v * 1000)); +const getHighestPrebidBidResponseBySlotTargeting = function( + instanceConfig, + slot, + version +) { + const hbAdIdTargeting = slot.getTargeting('hb_adid'); + if (hbAdIdTargeting.length > 0) { + const hbAdId = hbAdIdTargeting[0]; + return ( + instanceConfig.prebidWinnersCache[hbAdId] || + instanceConfig.prebidBidResponsesCache[hbAdId] + ); + } + return null; +}; + const liveyield = Object.assign(adapter({ analyticsType: 'bundle' }), { track({ eventType, args }) { switch (eventType) { case BID_REQUESTED: args.bids.forEach(function(b) { try { - window[adapterConfig.rtaFunctionName]( + window[liveyield.instanceConfig.rtaFunctionName]( 'bidRequested', - adapterConfig.getAdUnitName( - adapterConfig.getPlacementOrAdUnitCode(b, prebidVersion) + liveyield.instanceConfig.getAdUnitName( + liveyield.instanceConfig.getPlacementOrAdUnitCode( + b, + prebidVersion + ) ), args.bidderCode ); @@ -57,52 +203,82 @@ const liveyield = Object.assign(adapter({ analyticsType: 'bundle' }), { }); break; case BID_RESPONSE: + liveyield.instanceConfig.prebidBidResponsesCache[args.adId] = args; var cpm = args.statusMessage === 'Bid available' ? args.cpm : null; try { - window[adapterConfig.rtaFunctionName]( + window[liveyield.instanceConfig.rtaFunctionName]( 'addBid', - adapterConfig.getAdUnitName( - adapterConfig.getPlacementOrAdUnitCode(args, prebidVersion) + liveyield.instanceConfig.getAdUnitName( + liveyield.instanceConfig.getPlacementOrAdUnitCode( + args, + prebidVersion + ) ), args.bidder || 'unknown', cpmToMicroUSD(cpm), typeof args.bidder === 'undefined', args.statusMessage !== 'Bid available' - ) + ); } catch (e) { utils.logError(e); } break; case BID_TIMEOUT: - window[adapterConfig.rtaFunctionName]('biddersTimeout', args); + window[liveyield.instanceConfig.rtaFunctionName]( + 'biddersTimeout', + args + ); break; case BID_WON: + liveyield.instanceConfig.prebidWinnersCache[args.adId] = args; + if (liveyield.instanceConfig.googlePublisherTag) { + break; + } + try { - const ad = adapterConfig.getAdUnitName( - adapterConfig.getPlacementOrAdUnitCode(args, prebidVersion) + const ad = liveyield.instanceConfig.getAdUnitName( + liveyield.instanceConfig.getPlacementOrAdUnitCode( + args, + prebidVersion + ) ); if (!ad) { - utils.logError('Cannot find ad by unit name: ' + - adapterConfig.getAdUnitName( - adapterConfig.getPlacementOrAdUnitCode(args, prebidVersion) - )); + utils.logError( + 'Cannot find ad by unit name: ' + + liveyield.instanceConfig.getAdUnitName( + liveyield.instanceConfig.getPlacementOrAdUnitCode( + args, + prebidVersion + ) + ) + ); break; } if (!args.bidderCode || !args.cpm) { utils.logError('Bidder code or cpm is not valid'); break; } - window[adapterConfig.rtaFunctionName]( + const resolution = { targetings: [] }; + resolution.prebidWon = true; + resolution.prebidPartner = args.bidderCode; + resolution.prebidValue = cpmToMicroUSD(parseFloat(args.cpm)); + const resolutionToUse = liveyield.instanceConfig.postProcessResolution( + resolution, + null, + resolution.prebidPartner, + resolution.prebidValue, + prebidVersion + ); + window[liveyield.instanceConfig.rtaFunctionName]( 'resolveSlot', - adapterConfig.getAdUnitName( - adapterConfig.getPlacementOrAdUnitCode(args, prebidVersion) + liveyield.instanceConfig.getAdUnitName( + liveyield.instanceConfig.getPlacementOrAdUnitCode( + args, + prebidVersion + ) ), - { - prebidWon: true, - prebidPartner: args.bidderCode, - prebidValue: cpmToMicroUSD(args.cpm) - } - ) + resolutionToUse + ); } catch (e) { utils.logError(e); } @@ -157,12 +333,25 @@ liveyield.enableAnalytics = function(config) { utils.logError('options.sessionTimezoneOffset is required'); return; } - Object.assign(adapterConfig, config.options); - if (typeof window[adapterConfig.rtaFunctionName] !== 'function') { - utils.logError(`Function ${adapterConfig.rtaFunctionName} is not defined.` + - `Make sure that LiveYield snippet in included before the Prebid Analytics configuration.`); + liveyield.instanceConfig = Object.assign( + { prebidWinnersCache: {}, prebidBidResponsesCache: {} }, + adapterConfig, + config.options + ); + + if (typeof window[liveyield.instanceConfig.rtaFunctionName] !== 'function') { + utils.logError( + `Function ${liveyield.instanceConfig.rtaFunctionName} is not defined.` + + `Make sure that LiveYield snippet in included before the Prebid Analytics configuration.` + ); return; } + if (liveyield.instanceConfig.googlePublisherTag) { + liveyield.instanceConfig.wireGooglePublisherTag( + liveyield.instanceConfig.googlePublisherTag, + onSlotRenderEnded(liveyield.instanceConfig) + ); + } const additionalParams = { customerTimezone: config.options.customerTimezone, @@ -192,7 +381,7 @@ liveyield.enableAnalytics = function(config) { key => additionalParams[key] == null && delete additionalParams[key] ); - window[adapterConfig.rtaFunctionName]( + window[liveyield.instanceConfig.rtaFunctionName]( 'create', config.options.customerId, config.options.customerName, @@ -200,10 +389,63 @@ liveyield.enableAnalytics = function(config) { config.options.sessionTimezoneOffset, additionalParams ); - liveyield.originEnableAnalytics(config); }; +const onSlotRenderEnded = function(instanceConfig) { + const addDfpDetails = (resolution, slot) => { + const responseInformation = slot.getResponseInformation(); + if (responseInformation) { + resolution.dfpAdvertiserId = responseInformation.advertiserId; + resolution.dfpLineItemId = responseInformation.sourceAgnosticLineItemId; + resolution.dfpCreativeId = responseInformation.creativeId; + } + }; + + const addPrebidDetails = (resolution, slot) => { + if (instanceConfig.isPrebidAdImpression(slot)) { + resolution.prebidWon = true; + } + const highestPrebidAdImpPartner = instanceConfig.getHighestPrebidAdImpressionPartner( + instanceConfig, + slot, + prebidVersion + ); + const highestPrebidAdImpValue = instanceConfig.getHighestPrebidAdImpressionValue( + instanceConfig, + slot, + prebidVersion + ); + if (highestPrebidAdImpPartner) { + resolution.prebidPartner = highestPrebidAdImpPartner; + } + if (highestPrebidAdImpValue) { + resolution.prebidValue = cpmToMicroUSD( + parseFloat(highestPrebidAdImpValue) + ); + } + }; + return slot => { + const resolution = { targetings: [] }; + + addDfpDetails(resolution, slot); + addPrebidDetails(resolution, slot); + + const resolutionToUse = instanceConfig.postProcessResolution( + resolution, + slot, + resolution.highestPrebidAdImpPartner, + resolution.highestPrebidAdImpValue, + prebidVersion + ); + window[instanceConfig.rtaFunctionName]( + 'resolveSlot', + instanceConfig.getAdUnitNameByGooglePublisherTagSlot(slot, prebidVersion), + resolutionToUse + ); + }; +}; + adapterManager.registerAnalyticsAdapter({ adapter: liveyield, code: 'liveyield' diff --git a/test/spec/modules/liveyieldAnalyticsAdapter_spec.js b/test/spec/modules/liveyieldAnalyticsAdapter_spec.js index 61d9d9e5de0..36ade5ce67b 100644 --- a/test/spec/modules/liveyieldAnalyticsAdapter_spec.js +++ b/test/spec/modules/liveyieldAnalyticsAdapter_spec.js @@ -20,6 +20,7 @@ describe('liveyield analytics adapter', function() { afterEach(function() { events.getEvents.restore(); }); + describe('initialization', function() { afterEach(function() { rtaCalls.length = 0; @@ -42,7 +43,7 @@ describe('liveyield analytics adapter', function() { options: { customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa' } - }) + }); expect(rtaCalls).to.be.empty; }); it('should require options.customerSite', function() { @@ -190,6 +191,7 @@ describe('liveyield analytics adapter', function() { }; events.emit(BID_REQUESTED, bidRequest); + expect(rtaCalls[1].callArgs['0']).to.equal('bidRequested'); expect(rtaCalls[1].callArgs['1']).to.equal('div-gpt-ad-1438287399331-0'); expect(rtaCalls[1].callArgs['2']).to.equal('appnexus'); @@ -344,9 +346,7 @@ describe('liveyield analytics adapter', function() { }; events.emit(BID_WON, bidWon); expect(rtaCalls[1].callArgs['0']).to.equal('resolveSlot'); - expect(rtaCalls[1].callArgs['1']).to.equal( - 'div-gpt-ad-1438287399331-0' - ); + expect(rtaCalls[1].callArgs['1']).to.equal('div-gpt-ad-1438287399331-0'); expect(rtaCalls[1].callArgs['2'].prebidWon).to.equal(true); expect(rtaCalls[1].callArgs['2'].prebidPartner).to.equal('testbidder4'); expect(rtaCalls[1].callArgs['2'].prebidValue).to.equal(1962); @@ -396,4 +396,309 @@ describe('liveyield analytics adapter', function() { expect(rtaCalls[1]).to.be.undefined; }); }); + + describe('googletag use case', function() { + beforeEach(function() { + rtaCalls.length = 0; + }); + afterEach(function() { + liveyield.disableAnalytics(); + }); + it('should ignore BID_WON events when gpt is provided', function() { + const options = { + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12, + googlePublisherTag: true, + wireGooglePublisherTag: function() { + return null; + } + } + }; + liveyield.enableAnalytics(options); + + const bidWon = { + adId: 'ignore_me', + mediaType: 'banner', + requestId: '4587fec4900b81', + cpm: 1.962, + creativeId: 2126, + currency: 'EUR', + netRevenue: true, + ttl: 302, + auctionId: '914bedad-b145-4e46-ba58-51365faea6cb', + statusMessage: 'Bid available', + responseTimestamp: 1530628534437, + requestTimestamp: 1530628534219, + bidderCode: 'hello', + adUnitCode: 'div-gpt-ad-1438287399331-0', + timeToRespond: 218, + size: '300x250', + status: 'rendered' + }; + events.emit(BID_WON, bidWon); + + expect(rtaCalls.length).to.equal(1); + }); + it('should subscribe to slotRenderEnded', function() { + var googletag; + var callback; + const options = { + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12, + googlePublisherTag: 'testGPT', + wireGooglePublisherTag: function(gpt, cb) { + googletag = gpt; + callback = cb; + } + } + }; + liveyield.enableAnalytics(options); + expect(googletag).to.equal('testGPT'); + expect(typeof callback).to.equal('function'); + }); + it('should handle BID_WON event for prebid', function() { + var call; + const slot = { + getResponseInformation: function() { + const dfpInfo = { + dfpAdvertiserId: 1, + dfpLineItemId: 2, + dfpCreativeId: 3 + }; + return dfpInfo; + }, + getTargeting: function(v) { + return ['4587fec4900b81']; + } + }; + const options = { + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12, + googlePublisherTag: 'testGPT', + wireGooglePublisherTag: function(gpt, cb) { + call = cb; + }, + getHighestPrebidAdImpressionPartner: function(slot, version) { + return 'testbidder4'; + }, + getHighestPrebidAdImpressionValue: function(slot, version) { + return 12; + }, + postProcessResolution: function( + resolution, + slot, + hbPartner, + hbValue, + version + ) { + return resolution; + }, + getAdUnitNameByGooglePublisherTagSlot: function(slot, version) { + return 'testUnit'; + } + } + }; + liveyield.enableAnalytics(options); + const bidWon = { + adId: '4587fec4900b81' + }; + events.emit(BID_WON, bidWon); + call(slot); + expect(rtaCalls[1].callArgs['2'].prebidWon).to.equal(true); + expect(rtaCalls[1].callArgs['2'].prebidPartner).to.equal('testbidder4'); + }); + it('should handle BID_WON event for dfp', function() { + let call; + const slot = { + getResponseInformation: function() { + const dfpInfo = { + dfpAdvertiserId: 1, + dfpLineItemId: 2, + dfpCreativeId: 3 + }; + return dfpInfo; + } + }; + const options = { + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12, + googlePublisherTag: 'testGPT', + wireGooglePublisherTag: function(gpt, cb) { + call = cb; + }, + getHighestPrebidAdImpressionPartner: function(slot, version) { + return 'testbidder4'; + }, + getHighestPrebidAdImpressionValue: function(slot, version) { + return 12; + }, + postProcessResolution: function(slot, version) { + return { partner: slot.prebidPartner, value: slot.prebidValue }; + }, + getAdUnitNameByGooglePublisherTagSlot: function(slot, version) { + return 'testUnit'; + }, + isPrebidAdImpression: function(slot) { + return true; + } + } + }; + liveyield.enableAnalytics(options); + call(slot); + expect(rtaCalls.length).to.equal(2); + expect(rtaCalls[1].callArgs[0]).to.equal('resolveSlot'); + expect(rtaCalls[1].callArgs[1]).to.equal('testUnit'); + expect(rtaCalls[1].callArgs[2].partner).to.equal('testbidder4'); + expect(rtaCalls[1].callArgs[2].value).to.equal(12000); + }); + it('should work with defaults: prebid won', () => { + let call; + const options = { + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12, + googlePublisherTag: 'testGPT', + wireGooglePublisherTag: (gpt, cb) => (call = cb), + getAdUnitName: adUnitCode => + adUnitCode === 'PREBID_UNIT' ? 'ADUNIT' : null, + getAdUnitNameByGooglePublisherTagSlot: slot => + slot.getSlotElementId() === 'div-gpt-ad-1438287399331-0' + ? 'ADUNIT' + : null + } + }; + liveyield.enableAnalytics(options); + + const bidResponse = { + adId: 'defaults_with_cache', + statusMessage: 'Bid available', + cpm: 0.5, + bidder: 'appnexus', + adUnitCode: 'PREBID_UNIT' + }; + events.emit(BID_RESPONSE, bidResponse); + + const bidWon = { + adId: bidResponse.adId, + cpm: 1.962, // adjusted, this one shall be used, not the one from bidResponse + bidderCode: 'appnexus_from_bid_won_event', + adUnitCode: 'PREBID_UNIT' + }; + events.emit(BID_WON, bidWon); + + const slot = { + getTargeting: key => (key === 'hb_adid' ? [bidResponse.adId] : []), + getResponseInformation: () => null, + getSlotElementId: () => 'div-gpt-ad-1438287399331-0' + }; + call(slot); + + expect(rtaCalls[2].callArgs[0]).to.equal('resolveSlot'); + expect(rtaCalls[2].callArgs[1]).to.equal('ADUNIT'); + expect(rtaCalls[2].callArgs[2]).to.deep.equal({ + targetings: [], + prebidWon: true, + prebidPartner: 'appnexus_from_bid_won_event', + prebidValue: 1962 + }); + }); + it('should work with defaults: dfp won, prebid bid response', () => { + let call; + const options = { + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12, + googlePublisherTag: 'testGPT', + wireGooglePublisherTag: (gpt, cb) => (call = cb), + getAdUnitName: adUnitCode => + adUnitCode === 'PREBID_UNIT' ? 'ADUNIT' : null, + getAdUnitNameByGooglePublisherTagSlot: slot => + slot.getSlotElementId() === 'div-gpt-ad-1438287399331-0' + ? 'ADUNIT' + : null + } + }; + liveyield.enableAnalytics(options); + + const bidResponse = { + adId: 'defaults_with_cache_no_prebid_win', + statusMessage: 'Bid available', + cpm: 0.5, + bidder: 'appnexus', + adUnitCode: 'PREBID_UNIT' + }; + events.emit(BID_RESPONSE, bidResponse); + + const slot = { + getTargeting: key => (key === 'hb_adid' ? [bidResponse.adId] : []), + getResponseInformation: () => null, + getSlotElementId: () => 'div-gpt-ad-1438287399331-0' + }; + call(slot); + + expect(rtaCalls[2].callArgs[0]).to.equal('resolveSlot'); + expect(rtaCalls[2].callArgs[1]).to.equal('ADUNIT'); + expect(rtaCalls[2].callArgs[2]).to.deep.equal({ + targetings: [], + prebidPartner: 'appnexus', + prebidValue: 500 + }); + }); + it('should work with defaults: dfp won, without prebid', () => { + let call; + const options = { + provider: 'liveyield', + options: { + customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', + customerName: 'pubocean', + customerSite: 'scribol.com', + sessionTimezoneOffset: 12, + googlePublisherTag: 'testGPT', + wireGooglePublisherTag: (gpt, cb) => (call = cb), + getAdUnitName: adUnitCode => + adUnitCode === 'PREBID_UNIT' ? 'ADUNIT' : null, + getAdUnitNameByGooglePublisherTagSlot: slot => + slot.getSlotElementId() === 'div-gpt-ad-1438287399331-0' + ? 'ADUNIT' + : null + } + }; + liveyield.enableAnalytics(options); + + const slot = { + getTargeting: key => (key === 'hb_adid' ? ['does-not-exist'] : []), + getResponseInformation: () => null, + getSlotElementId: () => 'div-gpt-ad-1438287399331-0' + }; + call(slot); + + expect(rtaCalls[1].callArgs[0]).to.equal('resolveSlot'); + expect(rtaCalls[1].callArgs[1]).to.equal('ADUNIT'); + expect(rtaCalls[1].callArgs[2]).to.deep.equal({ + targetings: [] + }); + }); + }); }); From b6c56448b105a49424ad4049c2e146f5eeab6fa6 Mon Sep 17 00:00:00 2001 From: Michael Callari Date: Tue, 26 Feb 2019 14:53:10 -0500 Subject: [PATCH 1035/1594] Updating network call to use https. #3580 (#3581) --- modules/optimeraBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/optimeraBidAdapter.js b/modules/optimeraBidAdapter.js index 1152cff751a..ab4c75c1c1f 100644 --- a/modules/optimeraBidAdapter.js +++ b/modules/optimeraBidAdapter.js @@ -1,7 +1,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'optimera'; -const SCORES_BASE_URL = 'http://dyv1bugovvq1g.cloudfront.net/'; +const SCORES_BASE_URL = 'https://dyv1bugovvq1g.cloudfront.net/'; export const spec = { code: BIDDER_CODE, From 36f1230dd55f7c1e182ddb4e8fa2eabdf1f87c94 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 27 Feb 2019 08:54:26 -0700 Subject: [PATCH 1036/1594] update fun-hooks to latest and update api (#3574) * use custom bind where non-standard mootools bind could cause issues * replace missing 'rest' with implementation * latest fun-hooks * update package-lock.json * update fun-hooks to latest and update api * update fun-hooks to latest, fixes: #3576 * update package-lock.json --- modules/currency.js | 6 +-- modules/prebidServerBidAdapter/index.js | 2 +- package-lock.json | 70 ++++++++++++------------- package.json | 2 +- src/auction.js | 2 +- src/hook.js | 6 +-- src/prebid.js | 2 +- src/utils.js | 11 ++++ 8 files changed, 54 insertions(+), 47 deletions(-) diff --git a/modules/currency.js b/modules/currency.js index 700157acdd3..17c38b17a98 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -3,7 +3,7 @@ import { STATUS } from '../src/constants'; import { ajax } from '../src/ajax'; import * as utils from '../src/utils'; import { config } from '../src/config'; -import { hooks } from '../src/hook.js'; +import { getHook } from '../src/hook.js'; const DEFAULT_CURRENCY_RATE_URL = 'https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json?date=$$TODAY$$'; const CURRENCY_RATE_PRECISION = 4; @@ -122,7 +122,7 @@ function initCurrency(url) { utils.logInfo('Installing addBidResponse decorator for currency module', arguments); - hooks['addBidResponse'].before(addBidResponseHook, 100); + getHook('addBidResponse').before(addBidResponseHook, 100); // call for the file if we haven't already if (needToCallForCurrencyFile) { @@ -148,7 +148,7 @@ function initCurrency(url) { function resetCurrency() { utils.logInfo('Uninstalling addBidResponse decorator for currency module', arguments); - hooks['addBidResponse'].getHooks({hook: addBidResponseHook}).remove(); + getHook('addBidResponse').getHooks({hook: addBidResponseHook}).remove(); adServerCurrency = 'USD'; conversionCache = {}; diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 5938c493871..47c51ad9280 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -169,7 +169,7 @@ function doAllSyncs(bidders) { const thisSync = bidders.pop(); if (thisSync.no_cookie) { - doBidderSync(thisSync.usersync.type, thisSync.usersync.url, thisSync.bidder, doAllSyncs.bind(null, bidders)); + doBidderSync(thisSync.usersync.type, thisSync.usersync.url, thisSync.bidder, utils.bind.call(doAllSyncs, null, bidders)); } else { doAllSyncs(bidders); } diff --git a/package-lock.json b/package-lock.json index 64ec08e0ca3..69e270c5505 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.2.0", + "version": "2.4.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3038,7 +3038,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3463,7 +3463,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -4590,7 +4590,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4604,7 +4604,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4620,7 +4620,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4640,7 +4640,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -5333,7 +5333,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5846,7 +5846,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", "dev": true }, "flush-write-stream": { @@ -6602,9 +6602,9 @@ } }, "fun-hooks": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.6.6.tgz", - "integrity": "sha512-Q+UdtGIpteY7Wd6z4T9MZ4GlqHtrRY1gCk+XuLyRxqgLsCaPKOOBY7EKJRFlXm1oQoNIrg2b7W55dEN55O8FBA==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.8.1.tgz", + "integrity": "sha512-qhyQAO6vhmzzwOJ2SvqeCvL2dqBCw3NeuIpNOfMPv2bucFYXLur9UbXTiUAbm7EE2TrdLgIKJZkO0DfwEY+KVQ==" }, "function-bind": { "version": "1.1.1", @@ -7343,7 +7343,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7360,7 +7360,7 @@ "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==", + "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", "dev": true } } @@ -8105,7 +8105,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -9094,7 +9094,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9130,7 +9130,7 @@ "mime": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "integrity": "sha1-4FH9iBNYWF8yed8zP+aU2gvP/dY=", "dev": true }, "rimraf": { @@ -9803,7 +9803,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -9816,7 +9816,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", "dev": true }, "debug": { @@ -10337,7 +10337,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10373,7 +10373,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10981,7 +10981,7 @@ "opn": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "integrity": "sha1-y1Reeqt4VivrEao7+rxwQuF2EDU=", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -10999,7 +10999,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -12591,7 +12591,7 @@ "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", "dev": true }, "right-align": { @@ -13046,7 +13046,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { "debug": "~3.1.0", @@ -13060,7 +13060,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13083,7 +13083,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", @@ -13105,7 +13105,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13121,7 +13121,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13133,7 +13133,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13271,7 +13271,7 @@ }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13399,7 +13399,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -14267,7 +14267,7 @@ "dependencies": { "bluebird": { "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true } @@ -14368,7 +14368,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -15045,7 +15045,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { diff --git a/package.json b/package.json index 6d597aeca8c..6983a742bb8 100755 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "babel-plugin-transform-object-assign": "^6.22.0", "core-js": "^2.4.1", "crypto-js": "^3.1.9-1", - "fun-hooks": "^0.6.5", + "fun-hooks": "^0.8.1", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2" } diff --git a/src/auction.js b/src/auction.js index fc8c42023f7..f99d3bf0eb8 100644 --- a/src/auction.js +++ b/src/auction.js @@ -157,7 +157,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) const adUnitCodes = _adUnitCodes; const bids = _bidsReceived - .filter(adUnitsFilter.bind(this, adUnitCodes)) + .filter(utils.bind.call(adUnitsFilter, this, adUnitCodes)) .reduce(groupByPlacement, {}); _callback.apply($$PREBID_GLOBAL$$, [bids, timedOut]); } catch (e) { diff --git a/src/hook.js b/src/hook.js index c4e450bf5f2..d8d52b97dc8 100644 --- a/src/hook.js +++ b/src/hook.js @@ -5,8 +5,4 @@ export let hook = funHooks({ ready: funHooks.SYNC | funHooks.ASYNC | funHooks.QUEUE }); -/** - * A map of global hook methods to allow easy extension of hooked functions that are intended to be extended globally - * @type {{}} - */ -export const hooks = hook.hooks; +export const getHook = hook.get; diff --git a/src/prebid.js b/src/prebid.js index ff780d6deda..75f0cd9a6d9 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -172,7 +172,7 @@ $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { function getBids(type) { const responses = auctionManager[type]() - .filter(adUnitsFilter.bind(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(); diff --git a/src/utils.js b/src/utils.js index 2abad759e7a..30b9b746bc7 100644 --- a/src/utils.js +++ b/src/utils.js @@ -40,6 +40,17 @@ export const internal = { logInfo }; +var uniqueRef = {}; +export let bind = function(a, b) { return b; }.bind(null, 1, uniqueRef)() === uniqueRef + ? Function.prototype.bind + : function(bind) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + return function() { + return self.apply(bind, args.concat(Array.prototype.slice.call(arguments))); + }; + }; + /* * Substitutes into a string from a given map using the token * Usage From e96d58e46979150205640c052744a3a58e07cfc6 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 27 Feb 2019 12:42:25 -0500 Subject: [PATCH 1037/1594] Adpod module (#3511) * initial version of adpod module * fix hooks, clean-up and uncomment unit tests * correct issues in unit tests * add missing custom key fields in fake bids for unit tests * several updates to module and unit tests * update logic to only add hooks once * update targeting keys to new name * add module description * fix typo * add adunit check in case of multi-format * add exports for adpod targeting keys * move ADPOD constant to mediaTypes.js * undo mediaTypes change * fix unit tests * updates based on initial feedback * add msg when PBC rejects bid due to duplicate key * fix issue in videoBidCheck hook * add buffer logic when rounding bidDuration * add logic for deferCaching * update logic around brandCategoryExclusion * update support to new hook api and update logic when checking iab category field --- modules/adpod.js | 414 ++++++++++++++ src/auction.js | 2 +- src/hook.js | 7 + src/prebid.js | 2 +- src/video.js | 2 +- test/spec/modules/adpod_spec.js | 982 ++++++++++++++++++++++++++++++++ 6 files changed, 1406 insertions(+), 3 deletions(-) create mode 100644 modules/adpod.js create mode 100644 test/spec/modules/adpod_spec.js diff --git a/modules/adpod.js b/modules/adpod.js new file mode 100644 index 00000000000..87e5869e17b --- /dev/null +++ b/modules/adpod.js @@ -0,0 +1,414 @@ +/** + * This module houses the functionality to evaluate and process adpod adunits/bids. Specifically there are several hooked functions, + * that either supplement the base function (ie to check something additional or unique to adpod objects) or to replace the base funtion + * entirely when appropriate. + * + * Brief outline of each hook: + * - `callPrebidCacheHook` - for any adpod bids, this function will temporarily hold them in a queue in order to send the bids to Prebid Cache in bulk + * - `checkAdUnitSetupHook` - evaluates the adUnits to ensure that required fields for adpod adUnits are present. Invalid adpod adUntis are removed from the array. + * - `checkVideoBidSetupHook` - evaluates the adpod bid returned from an adaptor/bidder to ensure required fields are populated; also initializes duration bucket field. + * + * To initialize the module, there is an `initAdpodHooks()` function that should be imported and executed by a corresponding `...AdServerVideo` + * module that designed to support adpod video type ads. This import process allows this module to effectively act as a sub-module. + */ + +import * as utils from '../src/utils'; +import { addBidToAuction, doCallbacksIfTimedout, AUCTION_IN_PROGRESS, callPrebidCache } from '../src/auction'; +import { checkAdUnitSetup } from '../src/prebid'; +import { checkVideoBidSetup } from '../src/video'; +import { setupBeforeHookFnOnce } from '../src/hook'; +import { store } from '../src/videoCache'; +import { config } from '../src/config'; +import { ADPOD } from '../src/mediaTypes'; +import Set from 'core-js/library/fn/set'; +import find from 'core-js/library/fn/array/find'; +const from = require('core-js/library/fn/array/from'); + +export const TARGETING_KEY_PB_CAT_DUR = 'hb_pb_cat_dur'; +export const TARGETING_KEY_CACHE_ID = 'hb_cache_id' + +let queueTimeDelay = 50; +let queueSizeLimit = 5; +let bidCacheRegistry = createBidCacheRegistry(); + +/** + * Create a registry object that stores/manages bids while be held in queue for Prebid Cache. + * @returns registry object with defined accessor functions + */ +function createBidCacheRegistry() { + let registry = {}; + + function setupRegistrySlot(auctionId) { + registry[auctionId] = {}; + registry[auctionId].bidStorage = new Set(); + registry[auctionId].queueDispatcher = createDispatcher(queueTimeDelay); + registry[auctionId].initialCacheKey = utils.generateUUID(); + } + + return { + addBid: function (bid) { + // create parent level object based on auction ID (in case there are concurrent auctions running) to store objects for that auction + if (!registry[bid.auctionId]) { + setupRegistrySlot(bid.auctionId); + } + registry[bid.auctionId].bidStorage.add(bid); + }, + removeBid: function (bid) { + registry[bid.auctionId].bidStorage.delete(bid); + }, + getBids: function (bid) { + return registry[bid.auctionId] && registry[bid.auctionId].bidStorage.values(); + }, + getQueueDispatcher: function(bid) { + return registry[bid.auctionId] && registry[bid.auctionId].queueDispatcher; + }, + setupInitialCacheKey: function(bid) { + if (!registry[bid.auctionId]) { + registry[bid.auctionId] = {}; + registry[bid.auctionId].initialCacheKey = utils.generateUUID(); + } + }, + getInitialCacheKey: function(bid) { + return registry[bid.auctionId] && registry[bid.auctionId].initialCacheKey; + } + } +} + +/** + * Creates a function that when called updates the bid queue and extends the running timer (when called subsequently). + * Once the time threshold for the queue (defined by queueSizeLimit) is reached, the queue will be flushed by calling the `firePrebidCacheCall` function. + * If there is a long enough time between calls (based on timeoutDration), the queue will automatically flush itself. + * @param {Number} timeoutDuration number of milliseconds to pass before timer expires and current bid queue is flushed + * @returns {Function} + */ +function createDispatcher(timeoutDuration) { + let timeout; + let counter = 1; + + return function(auctionInstance, bidListArr, afterBidAdded, killQueue) { + const context = this; + + var callbackFn = function() { + firePrebidCacheCall.call(context, auctionInstance, bidListArr, afterBidAdded); + }; + + clearTimeout(timeout); + + if (!killQueue) { + // want to fire off the queue if either: size limit is reached or time has passed since last call to dispatcher + if (counter === queueSizeLimit) { + counter = 1; + callbackFn(); + } else { + counter++; + timeout = setTimeout(callbackFn, timeoutDuration); + } + } else { + counter = 1; + } + }; +} + +/** + * This function reads certain fields from the bid to generate a specific key used for caching the bid in Prebid Cache + * @param {Object} bid bid object to update + * @param {Boolean} brandCategoryExclusion value read from setConfig; influences whether category is required or not + */ +function attachPriceIndustryDurationKeyToBid(bid, brandCategoryExclusion) { + let initialCacheKey = bidCacheRegistry.getInitialCacheKey(bid); + let duration = utils.deepAccess(bid, 'video.durationBucket'); + let cpmFixed = bid.cpm.toFixed(2); + let pcd; + + if (brandCategoryExclusion) { + let category = utils.deepAccess(bid, 'meta.adServerCatId'); + pcd = `${cpmFixed}_${category}_${duration}s`; + } else { + pcd = `${cpmFixed}_${duration}s`; + } + + if (!bid.adserverTargeting) { + bid.adserverTargeting = {}; + } + bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] = pcd; + bid.adserverTargeting[TARGETING_KEY_CACHE_ID] = initialCacheKey; + bid.customCacheKey = `${pcd}_${initialCacheKey}`; +} + +/** + * Updates the running queue for the associated auction. + * Does a check to ensure the auction is still running; if it's not - the previously running queue is killed. + * @param {*} auctionInstance running context of the auction + * @param {Object} bidResponse bid object being added to queue + * @param {Function} afterBidAdded callback function used when Prebid Cache responds + */ +function updateBidQueue(auctionInstance, bidResponse, afterBidAdded) { + let bidListIter = bidCacheRegistry.getBids(bidResponse); + + if (bidListIter) { + let bidListArr = from(bidListIter); + let callDispatcher = bidCacheRegistry.getQueueDispatcher(bidResponse); + let killQueue = !!(auctionInstance.getAuctionStatus() !== AUCTION_IN_PROGRESS); + callDispatcher(auctionInstance, bidListArr, afterBidAdded, killQueue); + } else { + utils.logWarn('Attempted to cache a bid from an unknown auction. Bid:', bidResponse); + } +} + +/** + * Small helper function to remove bids from internal storage; normally b/c they're about to sent to Prebid Cache for processing. + * @param {Array[Object]} bidResponses list of bids to remove + */ +function removeBidsFromStorage(bidResponses) { + for (let i = 0; i < bidResponses.length; i++) { + bidCacheRegistry.removeBid(bidResponses[i]); + } +} + +/** + * This function will send a list of bids to Prebid Cache. It also removes the same bids from the internal bidCacheRegistry + * to maintain which bids are in queue. + * If the bids are successfully cached, they will be added to the respective auction. + * @param {*} auctionInstance running context of the auction + * @param {Array[Object]} bidList list of bid objects that need to be sent to Prebid Cache + * @param {Function} afterBidAdded callback function used when Prebid Cache responds + */ +function firePrebidCacheCall(auctionInstance, bidList, afterBidAdded) { + // remove entries now so other incoming bids won't accidentally have a stale version of the list while PBC is processing the current submitted list + removeBidsFromStorage(bidList); + + store(bidList, function (error, cacheIds) { + if (error) { + 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]); + } + } else { + for (let i = 0; i < cacheIds.length; i++) { + // when uuid in response is empty string then the key already existed, so this bid wasn't cached + if (cacheIds[i].uuid !== '') { + addBidToAuction(auctionInstance, bidList[i]); + } else { + 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(); + } + } + }); +} + +/** + * This is the main hook function to handle adpod bids; maintains the logic to temporarily hold bids in a queue in order to send bulk requests to Prebid Cache. + * @param {Function} fn reference to original function (used by hook logic) + * @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} bidderRequest copy of bid's associated bidderRequest object + */ +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 = utils.deepAccess(bidResponse, 'meta.adServerCatId'); + if (!adServerCatId && brandCategoryExclusion) { + utils.logWarn('Detected a bid without meta.adServerCatId while setConfig({adpod.brandCategoryExclusion}) was enabled. This bid has been rejected:', bidResponse) + afterBidAdded(); + } + + if (config.getConfig('adpod.deferCaching') === false) { + bidCacheRegistry.addBid(bidResponse); + attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); + + updateBidQueue(auctionInstance, bidResponse, afterBidAdded); + } else { + // generate targeting keys for bid + bidCacheRegistry.setupInitialCacheKey(bidResponse); + attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); + + // add bid to auction + addBidToAuction(auctionInstance, bidResponse); + afterBidAdded(); + } + } else { + fn.call(this, auctionInstance, bidResponse, afterBidAdded, bidderRequest); + } +} + +/** + * This hook function will review the adUnit setup and verify certain required values are present in any adpod adUnits. + * If the fields are missing or incorrectly setup, the adUnit is removed from the list. + * @param {Function} fn reference to original function (used by hook logic) + * @param {Array[Object]} adUnits list of adUnits to be evaluated + * @returns {Array[Object]} list of adUnits that passed the check + */ +export function checkAdUnitSetupHook(fn, adUnits) { + let goodAdUnits = adUnits.filter(adUnit => { + 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) { + 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; + } + + let errMsg = `Detected missing or incorrectly setup fields for an adpod adUnit. Please review the following fields of adUnitCode: ${adUnit.code}. This adUnit will be removed from the auction.`; + + let playerSize = !!(videoConfig.playerSize && utils.isArrayOfNums(videoConfig.playerSize)); + let adPodDurationSec = !!(videoConfig.adPodDurationSec && utils.isNumber(videoConfig.adPodDurationSec)); + let durationRangeSec = !!(videoConfig.durationRangeSec && utils.isArrayOfNums(videoConfig.durationRangeSec)); + + if (!playerSize || !adPodDurationSec || !durationRangeSec) { + errMsg += (!playerSize) ? '\nmediaTypes.video.playerSize' : ''; + errMsg += (!adPodDurationSec) ? '\nmediaTypes.video.adPodDurationSec' : ''; + errMsg += (!durationRangeSec) ? '\nmediaTypes.video.durationRangeSec' : ''; + utils.logWarn(errMsg); + return false; + } + } + return true; + }); + adUnits = goodAdUnits; + fn.call(this, adUnits); +} + +/** + * This check evaluates the incoming bid's `video.durationSeconds` field and tests it against specific logic depending on adUnit config. Summary of logic below: + * when adUnit.mediaTypes.video.requireExactDuration is true + * - only bids that exactly match those listed values are accepted (don't round at all). + * - populate the `bid.video.durationBucket` field with the matching duration value + * when adUnit.mediaTypes.video.requireExactDuration is false + * - round the duration to the next highest specified duration value based on adunit. If the duration is above a range within a set buffer, that bid falls down into that bucket. + * (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} 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(bidderRequest, bidResponse) { + const buffer = 2; + 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 (!videoConfig.requireExactDuration) { + let max = Math.max(...adUnitRanges); + if (bidDuration <= (max + buffer)) { + let nextHighestRange = find(adUnitRanges, range => (range + buffer) >= bidDuration); + bidResponse.video.durationBucket = nextHighestRange; + } else { + 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 { + 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; + } + } + return true; +} + +/** + * This hooked function evaluates an adpod bid and determines if the required fields are present. + * 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} 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, bidRequest, videoMediaType, context) { + if (context === ADPOD) { + let result = true; + let brandCategoryExclusion = config.getConfig('adpod.brandCategoryExclusion'); + if (brandCategoryExclusion && !utils.deepAccess(bid, 'meta.iabSubCatId')) { + result = false; + } + + if (utils.deepAccess(bid, 'video')) { + if (!utils.deepAccess(bid, 'video.context') || bid.video.context !== ADPOD) { + result = false; + } + + if (!utils.deepAccess(bid, 'video.durationSeconds') || bid.video.durationSeconds <= 0) { + result = false; + } else { + let isBidGood = checkBidDuration(bidRequest, bid); + if (!isBidGood) result = false; + } + } + + if (!config.getConfig('cache.url') && bid.vastXml && !bid.vastUrl) { + 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: "..."} }); + `); + result = false; + }; + + fn.bail(result); + } else { + fn.call(this, bid, bidRequest, videoMediaType, context); + } +} + +/** + * This function reads the (optional) settings for the adpod as set from the setConfig() + * @param {Object} config contains the config settings for adpod module + */ +export function adpodSetConfig(config) { + if (config.bidQueueTimeDelay !== undefined) { + if (typeof config.bidQueueTimeDelay === 'number' && config.bidQueueTimeDelay > 0) { + queueTimeDelay = config.bidQueueTimeDelay; + } else { + utils.logWarn(`Detected invalid value for adpod.bidQueueTimeDelay in setConfig; must be a positive number. Using default: ${queueTimeDelay}`) + } + } + + if (config.bidQueueSizeLimit !== undefined) { + if (typeof config.bidQueueSizeLimit === 'number' && config.bidQueueSizeLimit > 0) { + queueSizeLimit = config.bidQueueSizeLimit; + } else { + utils.logWarn(`Detected invalid value for adpod.bidQueueSizeLimit in setConfig; must be a positive number. Using default: ${queueSizeLimit}`) + } + } +} +config.getConfig('adpod', config => adpodSetConfig(config.adpod)); + +/** + * This function initializes the adpod module's hooks. This is called by the corresponding adserver video module. + */ +export function initAdpodHooks() { + setupBeforeHookFnOnce(callPrebidCache, callPrebidCacheHook); + setupBeforeHookFnOnce(checkAdUnitSetup, checkAdUnitSetupHook); + setupBeforeHookFnOnce(checkVideoBidSetup, checkVideoBidSetupHook); +} + +/** + * + * @param {Array[Object]} bids list of 'winning' bids that need to be cached + * @param {Function} callback send the cached bids (or error) back to adserverVideoModule for further processing + }} + */ +export function callPrebidCacheAfterAuction(bids, callback) { + // will call PBC here and execute cb param to initialize player code + store(bids, function(error, cacheIds) { + if (error) { + callback(error, null); + } else { + let successfulCachedBids = []; + for (let i = 0; i < cacheIds.length; i++) { + if (cacheIds[i] !== '') { + successfulCachedBids.push(bids[i]); + } + } + callback(null, successfulCachedBids); + } + }) +} diff --git a/src/auction.js b/src/auction.js index f99d3bf0eb8..e83f7d061af 100644 --- a/src/auction.js +++ b/src/auction.js @@ -416,7 +416,7 @@ function tryAddVideoBid(auctionInstance, bidResponse, bidRequests, afterBidAdded } } -const callPrebidCache = hook('async', function(auctionInstance, bidResponse, afterBidAdded, bidderRequest) { +export const callPrebidCache = hook('async', function(auctionInstance, bidResponse, afterBidAdded, bidderRequest) { store([bidResponse], function (error, cacheIds) { if (error) { utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); diff --git a/src/hook.js b/src/hook.js index d8d52b97dc8..7727155e8aa 100644 --- a/src/hook.js +++ b/src/hook.js @@ -6,3 +6,10 @@ export let hook = funHooks({ }); export const getHook = hook.get; + +export function setupBeforeHookFnOnce(baseFn, hookFn, priority = 15) { + let result = baseFn.getHooks({hook: hookFn}); + if (result.length === 0) { + baseFn.before(hookFn, priority); + } +} diff --git a/src/prebid.js b/src/prebid.js index 75f0cd9a6d9..0374649c47c 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -69,7 +69,7 @@ function setRenderSize(doc, width, height) { } } -const checkAdUnitSetup = hook('sync', function (adUnits) { +export const checkAdUnitSetup = hook('sync', function (adUnits) { adUnits.forEach((adUnit) => { const mediaTypes = adUnit.mediaTypes; const normalizedSize = utils.getAdUnitSizes(adUnit); diff --git a/src/video.js b/src/video.js index d5fcadd1f38..9cf25016d46 100644 --- a/src/video.js +++ b/src/video.js @@ -42,7 +42,7 @@ export function isValidVideoBid(bid, bidRequests) { return checkVideoBidSetup(bid, bidRequest, videoMediaType, context); } -const checkVideoBidSetup = hook('sync', function(bid, bidRequest, videoMediaType, context) { +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) { diff --git a/test/spec/modules/adpod_spec.js b/test/spec/modules/adpod_spec.js new file mode 100644 index 00000000000..16e94fd569f --- /dev/null +++ b/test/spec/modules/adpod_spec.js @@ -0,0 +1,982 @@ +import * as utils from 'src/utils'; +import { config } from 'src/config'; +import * as videoCache from 'src/videoCache'; +import * as auction from 'src/auction'; +import { ADPOD } from 'src/mediaTypes'; + +import { callPrebidCacheHook, checkAdUnitSetupHook, checkVideoBidSetupHook, adpodSetConfig } from 'modules/adpod'; + +let expect = require('chai').expect; + +describe('adpod.js', function () { + let logErrorStub; + let logWarnStub; + let logInfoStub; + + describe('callPrebidCacheHook', function () { + let callbackResult; + let clock; + let addBidToAuctionStub; + let doCallbacksIfTimedoutStub; + let storeStub; + let afterBidAddedSpy; + let auctionBids = []; + + let callbackFn = function() { + callbackResult = true; + }; + + let auctionInstance = { + getAuctionStatus: function() { + return auction.AUCTION_IN_PROGRESS; + } + } + + const fakeStoreFn = function(bids, callback) { + let payload = []; + bids.forEach(bid => payload.push({uuid: bid.customCacheKey})); + callback(null, payload); + }; + + beforeEach(function() { + callbackResult = null; + afterBidAddedSpy = sinon.spy(); + storeStub = sinon.stub(videoCache, 'store'); + logWarnStub = sinon.stub(utils, 'logWarn'); + logInfoStub = sinon.stub(utils, 'logInfo'); + addBidToAuctionStub = sinon.stub(auction, 'addBidToAuction').callsFake(function (auctionInstance, bid) { + auctionBids.push(bid); + }); + doCallbacksIfTimedoutStub = sinon.stub(auction, 'doCallbacksIfTimedout'); + clock = sinon.useFakeTimers(); + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); + }); + + afterEach(function() { + storeStub.restore(); + logWarnStub.restore(); + logInfoStub.restore(); + addBidToAuctionStub.restore(); + doCallbacksIfTimedoutStub.restore(); + clock.restore(); + config.resetConfig(); + auctionBids = []; + }) + + it('should redirect back to the original function if bid is not an adpod video', function () { + let bid = { + adId: 'testAdId_123', + mediaType: 'video' + }; + + let bidderRequest = { + adUnitCode: 'adUnit_123', + mediaTypes: { + video: { + context: 'outstream' + } + } + } + + callPrebidCacheHook(callbackFn, auctionInstance, bid, function () {}, bidderRequest); + expect(callbackResult).to.equal(true); + }); + + it('should immediately add the adpod bid to auction if adpod.deferCaching in config is true', function() { + config.setConfig({ + adpod: { + deferCaching: true, + brandCategoryExclusion: true + } + }); + + let bidResponse1 = { + adId: 'adId01277', + auctionId: 'no_defer_123', + mediaType: 'video', + cpm: 5, + meta: { + adServerCatId: 'test' + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + + let bidResponse2 = { + adId: 'adId46547', + auctionId: 'no_defer_123', + mediaType: 'video', + cpm: 12, + meta: { + adServerCatId: 'value' + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + + 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, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); + + // check if bid adsereverTargeting is setup + expect(callbackResult).to.be.null; + expect(storeStub.called).to.equal(false); + expect(afterBidAddedSpy.calledTwice).to.equal(true); + expect(auctionBids.length).to.equal(2); + expect(auctionBids[0].adId).to.equal(bidResponse1.adId); + expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^5\.00_test_15s_.*/); + expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('5.00_test_15s'); + expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; + expect(auctionBids[1].adId).to.equal(bidResponse2.adId); + expect(auctionBids[1].customCacheKey).to.exist.and.to.match(/^12\.00_value_15s_.*/); + expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('12.00_value_15s'); + expect(auctionBids[1].adserverTargeting.hb_cache_id).to.exist; + expect(auctionBids[1].adserverTargeting.hb_cache_id).to.equal(auctionBids[0].adserverTargeting.hb_cache_id); + }); + + it('should send prebid cache call once bid queue is full', function () { + storeStub.callsFake(fakeStoreFn); + + config.setConfig({ + adpod: { + bidQueueSizeLimit: 2, + deferCaching: false, + brandCategoryExclusion: true + } + }); + + let bidResponse1 = { + adId: 'adId123', + auctionId: 'full_abc123', + mediaType: 'video', + cpm: 10, + meta: { + adServerCatId: 'airline' + }, + video: { + context: ADPOD, + durationSeconds: 20, + durationBucket: 30 + } + }; + let bidResponse2 = { + adId: 'adId234', + auctionId: 'full_abc123', + mediaType: 'video', + cpm: 15, + meta: { + adServerCatId: 'airline' + }, + video: { + context: ADPOD, + durationSeconds: 25, + durationBucket: 30 + } + }; + 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, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); + + expect(callbackResult).to.be.null; + expect(afterBidAddedSpy.calledTwice).to.equal(true); + expect(auctionBids.length).to.equal(2); + expect(auctionBids[0].adId).to.equal('adId123'); + expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^10\.00_airline_30s_.*/); + expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('10.00_airline_30s'); + expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; + expect(auctionBids[1].adId).to.equal('adId234'); + expect(auctionBids[1].customCacheKey).to.exist.and.to.match(/^15\.00_airline_30s_.*/); + expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_airline_30s'); + expect(auctionBids[1].adserverTargeting.hb_cache_id).to.exist; + }); + + it('should send prebid cache call after set period of time (even if queue is not full)', function () { + storeStub.callsFake(fakeStoreFn); + + config.setConfig({ + adpod: { + bidQueueSizeLimit: 2, + bidQueueTimeDelay: 30, + deferCaching: false, + brandCategoryExclusion: true + } + }); + + let bidResponse = { + adId: 'adId234', + auctionId: 'timer_abc234', + mediaType: 'video', + cpm: 15, + meta: { + adServerCatId: 'airline' + }, + video: { + context: ADPOD, + durationSeconds: 30, + durationBucket: 30 + } + }; + 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, bidderRequest); + clock.tick(31); + + expect(callbackResult).to.be.null; + expect(afterBidAddedSpy.calledOnce).to.equal(true); + expect(auctionBids.length).to.equal(1); + expect(auctionBids[0].adId).to.equal('adId234'); + expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^15\.00_airline_30s_.*/); + expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_airline_30s'); + expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; + }); + + it('should execute multiple prebid cache calls when number of bids exceeds queue size', function () { + storeStub.callsFake(fakeStoreFn); + + config.setConfig({ + adpod: { + bidQueueSizeLimit: 2, + bidQueueTimeDelay: 30, + deferCaching: false, + brandCategoryExclusion: true + } + }); + + let bidResponse1 = { + adId: 'multi_ad1', + auctionId: 'multi_call_abc345', + mediaType: 'video', + cpm: 15, + meta: { + adServerCatId: 'airline' + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + let bidResponse2 = { + adId: 'multi_ad2', + auctionId: 'multi_call_abc345', + mediaType: 'video', + cpm: 15, + meta: { + adServerCatId: 'news' + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + let bidResponse3 = { + adId: 'multi_ad3', + auctionId: 'multi_call_abc345', + mediaType: 'video', + cpm: 10, + meta: { + adServerCatId: 'sports' + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + + 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, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse3, afterBidAddedSpy, bidderRequest); + clock.next(); + + expect(callbackResult).to.be.null; + expect(afterBidAddedSpy.calledThrice).to.equal(true); + expect(storeStub.calledTwice).to.equal(true); + expect(auctionBids.length).to.equal(3); + expect(auctionBids[0].adId).to.equal('multi_ad1'); + expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^15\.00_airline_15s_.*/); + expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_airline_15s'); + expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; + expect(auctionBids[1].adId).to.equal('multi_ad2'); + expect(auctionBids[1].customCacheKey).to.exist.and.to.match(/^15\.00_news_15s_.*/); + expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_news_15s'); + expect(auctionBids[1].adserverTargeting.hb_cache_id).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id); + expect(auctionBids[2].adId).to.equal('multi_ad3'); + expect(auctionBids[2].customCacheKey).to.exist.and.to.match(/^10\.00_sports_15s_.*/); + expect(auctionBids[2].adserverTargeting.hb_pb_cat_dur).to.equal('10.00_sports_15s'); + expect(auctionBids[2].adserverTargeting.hb_cache_id).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id); + }); + + it('should cache the bids with a shortened custom key when adpod.brandCategoryExclusion is false', function() { + storeStub.callsFake(fakeStoreFn); + + config.setConfig({ + adpod: { + bidQueueSizeLimit: 2, + bidQueueTimeDelay: 30, + deferCaching: false, + brandCategoryExclusion: false + } + }); + + let bidResponse1 = { + adId: 'nocat_ad1', + auctionId: 'no_category_abc345', + mediaType: 'video', + cpm: 10, + meta: { + adServerCatId: undefined + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + let bidResponse2 = { + adId: 'nocat_ad2', + auctionId: 'no_category_abc345', + mediaType: 'video', + cpm: 15, + meta: { + adServerCatId: undefined + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + + 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, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); + + expect(callbackResult).to.be.null; + expect(afterBidAddedSpy.calledTwice).to.equal(true); + expect(storeStub.calledOnce).to.equal(true); + expect(auctionBids.length).to.equal(2); + expect(auctionBids[0].adId).to.equal('nocat_ad1'); + expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^10\.00_15s_.*/); + expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('10.00_15s'); + expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; + expect(auctionBids[1].adId).to.equal('nocat_ad2'); + expect(auctionBids[1].customCacheKey).to.exist.and.to.match(/^15\.00_15s_.*/); + expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_15s'); + expect(auctionBids[1].adserverTargeting.hb_cache_id).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id); + }); + + it('should not add bid to auction when config adpod.brandCategoryExclusion is true but bid is missing adServerCatId', function() { + storeStub.callsFake(fakeStoreFn); + + config.setConfig({ + adpod: { + bidQueueSizeLimit: 2, + bidQueueTimeDelay: 30, + deferCaching: false, + brandCategoryExclusion: true + } + }); + + let bidResponse1 = { + adId: 'missingCat_ad1', + auctionId: 'missing_category_abc345', + mediaType: 'video', + cpm: 10, + meta: { + adServerCatId: undefined + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + + 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, bidderRequest); + + expect(callbackResult).to.be.null; + expect(afterBidAddedSpy.calledOnce).to.equal(true); + expect(storeStub.called).to.equal(false); + expect(logWarnStub.calledOnce).to.equal(true); + expect(auctionBids.length).to.equal(0); + }); + + it('should not add bid to auction when Prebid Cache detects an existing key', function () { + storeStub.callsFake(function(bids, callback) { + let payload = []; + bids.forEach(bid => payload.push({uuid: bid.customCacheKey})); + + // fake a duplicate bid response from PBC (sets an empty string for the uuid) + payload[1].uuid = ''; + callback(null, payload); + }); + + config.setConfig({ + adpod: { + bidQueueSizeLimit: 2, + deferCaching: false, + brandCategoryExclusion: true + } + }); + + let bidResponse1 = { + adId: 'dup_ad_1', + auctionId: 'duplicate_def123', + mediaType: 'video', + cpm: 5, + meta: { + adServerCatId: 'tech' + }, + video: { + context: ADPOD, + durationSeconds: 45, + durationBucket: 45 + } + }; + let bidResponse2 = { + adId: 'dup_ad_2', + auctionId: 'duplicate_def123', + mediaType: 'video', + cpm: 5, + meta: { + adServerCatId: 'tech' + }, + video: { + context: ADPOD, + durationSeconds: 45, + durationBucket: 45 + } + }; + 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, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); + + expect(callbackResult).to.be.null; + expect(afterBidAddedSpy.calledTwice).to.equal(true); + expect(storeStub.calledOnce).to.equal(true); + expect(logInfoStub.calledOnce).to.equal(true); + expect(auctionBids.length).to.equal(1); + expect(auctionBids[0].adId).to.equal('dup_ad_1'); + expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^5\.00_tech_45s_.*/); + expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('5.00_tech_45s'); + expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; + }); + + it('should not add bids to auction if PBC returns an error', function() { + storeStub.callsFake(function(bids, callback) { + let payload = []; + let errmsg = 'invalid json'; + + callback(errmsg, payload); + }); + + config.setConfig({ + adpod: { + bidQueueSizeLimit: 2, + deferCaching: false, + brandCategoryExclusion: true + } + }); + + let bidResponse1 = { + adId: 'err_ad_1', + auctionId: 'error_xyz123', + mediaType: 'video', + cpm: 5, + meta: { + adServerCatId: 'tech' + }, + video: { + context: ADPOD, + durationSeconds: 30, + durationBucket: 30 + } + }; + let bidResponse2 = { + adId: 'err_ad_2', + auctionId: 'error_xyz123', + mediaType: 'video', + cpm: 5, + meta: { + adServerCatId: 'tech' + }, + video: { + context: ADPOD, + durationSeconds: 30, + durationBucket: 30 + } + }; + 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, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); + + expect(doCallbacksIfTimedoutStub.calledTwice).to.equal(true); + expect(logWarnStub.calledOnce).to.equal(true); + expect(auctionBids.length).to.equal(0); + }); + }); + + describe('checkAdUnitSetupHook', function () { + let results; + let callbackFn = function (adUnits) { + results = adUnits; + }; + + beforeEach(function () { + logWarnStub = sinon.stub(utils, 'logWarn'); + results = null; + }); + + afterEach(function() { + utils.logWarn.restore(); + }); + + it('removes an incorrectly setup adpod adunit - required fields are missing', function() { + let adUnits = [{ + code: 'test1', + mediaTypes: { + video: { + context: ADPOD + } + } + }, { + code: 'test2', + mediaTypes: { + video: { + context: 'instream' + } + } + }]; + + checkAdUnitSetupHook(callbackFn, adUnits); + + expect(results).to.deep.equal([{ + code: 'test2', + mediaTypes: { + video: { + context: 'instream' + } + } + }]); + expect(logWarnStub.calledOnce).to.equal(true); + }); + + it('removes an incorrectly setup adpod adunit - attempting to use multi-format adUnit', function() { + let adUnits = [{ + code: 'multi_test1', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + }, + video: { + context: 'adpod', + playerSize: [300, 250], + durationRangeSec: [15, 30, 45], + adPodDurationSec: 300 + } + } + }]; + + checkAdUnitSetupHook(callbackFn, adUnits); + + expect(results).to.deep.equal([]); + expect(logWarnStub.calledOnce).to.equal(true); + }); + + it('accepts mixed set of adunits', function() { + let adUnits = [{ + code: 'test3', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [300, 300], + adPodDurationSec: 360, + durationRangeSec: [15, 30, 45], + requireExactDuration: true + } + } + }, { + code: 'test4', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + } + }]; + + checkAdUnitSetupHook(callbackFn, adUnits); + + expect(results).to.deep.equal(adUnits); + expect(logWarnStub.called).to.equal(false); + }); + }); + + describe('checkVideoBidSetupHook', function () { + let callbackResult; + let bailResult; + const callbackFn = { + call: function(context, bid) { + callbackResult = bid; + }, + bail: function(result) { + bailResult = result; + } + } + const adpodTestBid = { + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + }, + meta: { + iabSubCatId: 'testCategory_123' + }, + vastXml: 'test XML here' + }; + const bidderRequestNoExact = { + mediaTypes: { + video: { + context: ADPOD, + playerSize: [300, 400], + durationRangeSec: [15, 45], + requireExactDuration: false, + adPodDurationSec: 300 + } + } + }; + const bidderRequestWithExact = { + mediaTypes: { + video: { + context: ADPOD, + playerSize: [300, 400], + durationRangeSec: [15, 30, 45, 60], + requireExactDuration: true, + adPodDurationSec: 300 + } + } + }; + + beforeEach(function() { + callbackResult = null; + bailResult = null; + config.setConfig({ + cache: { + url: 'http://test.cache.url/endpoint' + }, + adpod: { + brandCategoryExclusion: true + } + }); + logWarnStub = sinon.stub(utils, 'logWarn'); + logErrorStub = sinon.stub(utils, 'logError'); + }); + + afterEach(function() { + config.resetConfig(); + logWarnStub.restore(); + logErrorStub.restore(); + }) + + it('redirects to original function for non-adpod type video bids', function() { + let bannerTestBid = { + mediaType: 'video' + }; + checkVideoBidSetupHook(callbackFn, bannerTestBid, {}, {}, 'instream'); + expect(callbackResult).to.deep.equal(bannerTestBid); + expect(bailResult).to.be.null; + expect(logErrorStub.called).to.equal(false); + }); + + it('returns true when adpod bid is properly setup', function() { + config.setConfig({ + cache: { + url: 'http://test.cache.url/endpoint' + }, + adpod: { + brandCategoryExclusion: false + } + }); + + let goodBid = utils.deepClone(adpodTestBid); + goodBid.meta.iabSubCatId = undefined; + checkVideoBidSetupHook(callbackFn, goodBid, bidderRequestNoExact, {}, ADPOD); + expect(callbackResult).to.be.null; + expect(bailResult).to.equal(true); + expect(logErrorStub.called).to.equal(false); + }); + + 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, bidderRequestNoExact, {}, ADPOD); + expect(callbackResult).to.be.null; + expect(bailResult).to.equal(true); + expect(logErrorStub.called).to.equal(false); + }); + + it('returns false when a required property from an adpod bid is missing', function() { + function testInvalidAdpodBid(badTestBid, shouldErrorBeLogged) { + checkVideoBidSetupHook(callbackFn, badTestBid, bidderRequestNoExact, {}, ADPOD); + expect(callbackResult).to.be.null; + expect(bailResult).to.equal(false); + expect(logErrorStub.called).to.equal(shouldErrorBeLogged); + } + + let noCatBid = utils.deepClone(adpodTestBid); + noCatBid.meta.iabSubCatId = undefined; + testInvalidAdpodBid(noCatBid, false); + + let noContextBid = utils.deepClone(adpodTestBid); + delete noContextBid.video.context; + testInvalidAdpodBid(noContextBid, false); + + let wrongContextBid = utils.deepClone(adpodTestBid); + wrongContextBid.video.context = 'instream'; + testInvalidAdpodBid(wrongContextBid, false); + + let noDurationBid = utils.deepClone(adpodTestBid); + delete noDurationBid.video.durationSeconds; + testInvalidAdpodBid(noDurationBid, false); + + config.resetConfig(); + let noCacheUrlBid = utils.deepClone(adpodTestBid); + testInvalidAdpodBid(noCacheUrlBid, true); + }); + + describe('checkBidDuration', function() { + const basicBid = { + video: { + context: ADPOD, + durationSeconds: 30 + }, + meta: { + iabSubCatId: 'testCategory_123' + }, + vastXml: '' + }; + + it('when requireExactDuration is true', function() { + let goodBid = utils.deepClone(basicBid); + checkVideoBidSetupHook(callbackFn, goodBid, bidderRequestWithExact, {}, ADPOD); + + expect(callbackResult).to.be.null; + expect(goodBid.video.durationBucket).to.equal(30); + expect(bailResult).to.equal(true); + expect(logWarnStub.called).to.equal(false); + + let badBid = utils.deepClone(basicBid); + badBid.video.durationSeconds = 14; + checkVideoBidSetupHook(callbackFn, badBid, bidderRequestWithExact, {}, ADPOD); + + expect(callbackResult).to.be.null; + expect(badBid.video.durationBucket).to.be.undefined; + expect(bailResult).to.equal(false); + expect(logWarnStub.calledOnce).to.equal(true); + }); + + it('when requireExactDuration is false and bids are bucketed properly', function() { + function testRoundingForGoodBId(bid, bucketValue) { + checkVideoBidSetupHook(callbackFn, bid, bidderRequestNoExact, {}, ADPOD); + expect(callbackResult).to.be.null; + expect(bid.video.durationBucket).to.equal(bucketValue); + expect(bailResult).to.equal(true); + expect(logWarnStub.called).to.equal(false); + } + + let goodBid45 = utils.deepClone(basicBid); + goodBid45.video.durationSeconds = 45; + testRoundingForGoodBId(goodBid45, 45); + + let goodBid30 = utils.deepClone(basicBid); + goodBid30.video.durationSeconds = 30; + testRoundingForGoodBId(goodBid30, 45); + + let goodBid10 = utils.deepClone(basicBid); + goodBid10.video.durationSeconds = 10; + testRoundingForGoodBId(goodBid10, 15); + + let goodBid16 = utils.deepClone(basicBid); + goodBid16.video.durationSeconds = 16; + testRoundingForGoodBId(goodBid16, 15); + + let goodBid47 = utils.deepClone(basicBid); + goodBid47.video.durationSeconds = 47; + testRoundingForGoodBId(goodBid47, 45); + }); + + it('when requireExactDuration is false and bid duration exceeds listed buckets', function() { + function testRoundingForBadBid(bid) { + checkVideoBidSetupHook(callbackFn, bid, bidderRequestNoExact, {}, ADPOD); + expect(callbackResult).to.be.null; + expect(bid.video.durationBucket).to.be.undefined; + expect(bailResult).to.equal(false); + expect(logWarnStub.called).to.equal(true); + } + + let badBid100 = utils.deepClone(basicBid); + badBid100.video.durationSeconds = 100; + testRoundingForBadBid(badBid100); + + let badBid48 = utils.deepClone(basicBid); + badBid48.video.durationSeconds = 48; + testRoundingForBadBid(badBid48); + }); + }); + }); + + describe('adpodSetConfig', function () { + let logWarnStub; + beforeEach(function() { + logWarnStub = sinon.stub(utils, 'logWarn'); + }); + + afterEach(function () { + logWarnStub.restore(); + }); + + it('should log a warning when values other than numbers are used in setConfig', function() { + adpodSetConfig({ + bidQueueSizeLimit: '2', + bidQueueTimeDelay: '50' + }); + expect(logWarnStub.calledTwice).to.equal(true); + }); + + it('should log a warning when numbers less than or equal to zero are used in setConfig', function() { + adpodSetConfig({ + bidQueueSizeLimit: 0, + bidQueueTimeDelay: -2 + }); + expect(logWarnStub.calledTwice).to.equal(true); + }); + + it('should not log any warning when using a valid config', function() { + adpodSetConfig({ + bidQueueSizeLimit: 10 + }); + expect(logWarnStub.called).to.equal(false); + + adpodSetConfig({ + bidQueueTimeDelay: 100, + bidQueueSizeLimit: 20 + }); + expect(logWarnStub.called).to.equal(false); + }) + }); +}); From d4ff1ec888762a95142a00e7485436b28bfe6fa2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Wed, 27 Feb 2019 12:43:51 -0500 Subject: [PATCH 1038/1594] Adding freewheel module (#3489) * adding freewheel module * adding commented references to adpod module * upadate some properties and refactor * updated adpod import and competitive exclusion logic * add hook to freewheel module * add logic for deferCaching * refactor targeting logic for deferCaching and activate commented code * modify import for test file * update hook --- modules/freeWheelAdserverVideo.js | 166 +++++++++++ .../modules/freeWheelAdserverVideo_spec.js | 259 ++++++++++++++++++ 2 files changed, 425 insertions(+) create mode 100644 modules/freeWheelAdserverVideo.js create mode 100644 test/spec/modules/freeWheelAdserverVideo_spec.js diff --git a/modules/freeWheelAdserverVideo.js b/modules/freeWheelAdserverVideo.js new file mode 100644 index 00000000000..01ed145b00b --- /dev/null +++ b/modules/freeWheelAdserverVideo.js @@ -0,0 +1,166 @@ +/** + * This module adds Freewheel support for Video to Prebid. + */ + +import { registerVideoSupport } from '../src/adServerManager'; +import { auctionManager } from '../src/auctionManager'; +import { groupBy, deepAccess, logError } from '../src/utils'; +import { config } from '../src/config'; +import { ADPOD } from '../src/mediaTypes'; +import { initAdpodHooks, TARGETING_KEY_PB_CAT_DUR, TARGETING_KEY_CACHE_ID, callPrebidCacheAfterAuction } from './adpod'; +import { getHook } from '../src/hook'; + +export function notifyTranslationModule(fn) { + fn.call(this, 'freewheel'); +} + +getHook('registerAdserver').before(notifyTranslationModule); + +/** + * This function returns targeting keyvalue pairs for freewheel adserver module + * @param {Object} options + * @param {Array[string]} codes + * @param {function} callback + * @returns targeting kvs for adUnitCodes + */ +export function getTargeting({codes, callback} = {}) { + if (!callback) { + logError('No callback function was defined in the getTargeting call. Aborting getTargeting().'); + return; + } + codes = codes || []; + const adPodAdUnits = getAdPodAdUnits(codes); + const bidsReceived = auctionManager.getBidsReceived(); + const competiveExclusionEnabled = config.getConfig('adpod.brandCategoryExclusion'); + const deferCachingSetting = config.getConfig('adpod.deferCaching'); + const deferCachingEnabled = (typeof deferCachingSetting === 'boolean') ? deferCachingSetting : true; + + let bids = getBidsForAdpod(bidsReceived, adPodAdUnits); + bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids; + bids.sort(compareOn('cpm')); + + let targeting = {}; + if (deferCachingEnabled === false) { + adPodAdUnits.forEach((adUnit) => { + let adPodTargeting = []; + let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); + + bids + .filter((bid) => bid.adUnitCode === adUnit.code) + .forEach((bid, index, arr) => { + if (bid.video.durationBucket <= adPodDurationSeconds) { + adPodTargeting.push({ + [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] + }); + adPodDurationSeconds -= bid.video.durationBucket; + } + if (index === arr.length - 1 && adPodTargeting.length > 0) { + adPodTargeting.push({ + [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] + }); + } + }); + targeting[adUnit.code] = adPodTargeting; + }); + + callback(null, targeting); + } else { + let bidsToCache = []; + adPodAdUnits.forEach((adUnit) => { + let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); + + bids + .filter((bid) => bid.adUnitCode === adUnit.code) + .forEach((bid) => { + if (bid.video.durationBucket <= adPodDurationSeconds) { + bidsToCache.push(bid); + adPodDurationSeconds -= bid.video.durationBucket; + } + }); + }); + + callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) { + if (error) { + callback(error, null); + } else { + let groupedBids = groupBy(bidsSuccessfullyCached, 'adUnitCode'); + Object.keys(groupedBids).forEach((adUnitCode) => { + let adPodTargeting = []; + + groupedBids[adUnitCode].forEach((bid, index, arr) => { + adPodTargeting.push({ + [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] + }); + + if (index === arr.length - 1 && adPodTargeting.length > 0) { + adPodTargeting.push({ + [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] + }); + } + }); + targeting[adUnitCode] = adPodTargeting; + }); + + callback(null, targeting); + } + }); + } + return targeting; +} + +/** + * This function returns the adunit of mediaType adpod + * @param {Array} codes adUnitCodes + * @returns {Array[Object]} adunits of mediaType adpod + */ +function getAdPodAdUnits(codes) { + return auctionManager.getAdUnits() + .filter((adUnit) => deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) + .filter((adUnit) => (codes.length > 0) ? codes.indexOf(adUnit.code) != -1 : true); +} + +function compareOn(property) { + return function compare(a, b) { + if (a[property] < b[property]) { + return 1; + } + if (a[property] > b[property]) { + return -1; + } + return 0; + } +} + +/** + * This function removes bids of same freewheel category. It will be used when competitive exclusion is enabled. + * @param {Array[Object]} bidsReceived + * @returns {Array[Object]} unique freewheel category bids + */ +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); + let filteredBids = []; + Object.keys(bids).forEach((targetingKey) => { + bids[targetingKey].sort(compareOn('responseTimestamp')); + filteredBids.push(bids[targetingKey][0]); + }); + return filteredBids; +} + +/** + * This function returns bids for adpod adunits + * @param {Array[Object]} bidsReceived + * @param {Array[Object]} adPodAdUnits + * @returns {Array[Object]} bids of mediaType adpod + */ +function getBidsForAdpod(bidsReceived, adPodAdUnits) { + let adUnitCodes = adPodAdUnits.map((adUnit) => adUnit.code); + return bidsReceived + .filter((bid) => adUnitCodes.indexOf(bid.adUnitCode) != -1 && (bid.video && bid.video.context === ADPOD)) +} + +initAdpodHooks(); +registerVideoSupport('freewheel', { + getTargeting: getTargeting +}); diff --git a/test/spec/modules/freeWheelAdserverVideo_spec.js b/test/spec/modules/freeWheelAdserverVideo_spec.js new file mode 100644 index 00000000000..7f1c8857285 --- /dev/null +++ b/test/spec/modules/freeWheelAdserverVideo_spec.js @@ -0,0 +1,259 @@ +import { expect } from 'chai'; +import { getTargeting } from 'modules/freeWheelAdserverVideo'; +import { auctionManager } from 'src/auctionManager'; +import { config } from 'src/config'; +import * as adpod from 'modules/adpod'; + +describe('freeWheel adserver module', function() { + let amStub; + let amGetAdUnitsStub; + let pbcStub; + + before(function () { + let adUnits = [{ + code: 'preroll_1', + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480], + adPodDurationSec: 60, + durationRangeSec: [15, 30], + requireExactDuration: true + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 14542875, + } + } + ] + }, { + code: 'midroll_1', + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480], + adPodDurationSec: 60, + durationRangeSec: [15, 30], + requireExactDuration: true + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 14542875, + } + } + ] + }]; + + amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits'); + amGetAdUnitsStub.returns(adUnits); + amStub = sinon.stub(auctionManager, 'getBidsReceived'); + pbcStub = sinon.stub(adpod, 'callPrebidCacheAfterAuction').callsFake(function (...args) { + args[1](null, getBidsReceived()); + }); + }); + + beforeEach(function () { + config.setConfig({ + adpod: { + brandCategoryExclusion: false, + deferCaching: false + } + }); + }) + + afterEach(function() { + config.resetConfig(); + }); + + after(function () { + amGetAdUnitsStub.restore(); + amStub.restore(); + }); + + it('should return targeting for all adunits', function() { + amStub.returns(getBidsReceived()); + let targeting; + getTargeting({ + callback: function(errorMsg, targetingResult) { + targeting = targetingResult; + } + }); + + expect(targeting['preroll_1'].length).to.equal(3); + expect(targeting['midroll_1'].length).to.equal(2); + }); + + it('should return targeting for passed adunit code', function() { + amStub.returns(getBidsReceived()); + let targeting; + getTargeting({ + codes: ['preroll_1'], + callback: function(errorMsg, targetingResult) { + targeting = targetingResult; + } + }); + + expect(targeting['preroll_1']).to.exist; + expect(targeting['midroll_1']).to.not.exist; + }); + + it('should only use adpod bids', function() { + let bannerBid = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'requestId': '1', + 'creativeId': 'some-id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + 'bidderCode': 'appnexus', + 'statusMessage': 'Bid available', + 'adId': '28f24ced14586c', + 'adUnitCode': 'preroll_1' + }]; + amStub.returns(getBidsReceived().concat(bannerBid)); + let targeting; + getTargeting({ + callback: function(errorMsg, targetingResult) { + targeting = targetingResult; + } + }); + + expect(targeting['preroll_1'].length).to.equal(3); + expect(targeting['midroll_1'].length).to.equal(2); + }); + + it('should return unique category bids when competitive exclusion is enabled', function() { + config.setConfig({ + adpod: { + brandCategoryExclusion: true, + deferCaching: false + } + }); + amStub.returns([ + createBid(10, 'preroll_1', 30, '10.00_airline_30s', '123', 'airline'), + createBid(15, 'preroll_1', 30, '15.00_airline_30s', '123', 'airline'), + createBid(15, 'midroll_1', 60, '15.00_travel_60s', '123', 'travel'), + createBid(10, 'preroll_1', 30, '10.00_airline_30s', '123', 'airline') + ]); + let targeting; + getTargeting({ + callback: function(errorMsg, targetingResult) { + targeting = targetingResult; + } + }); + + expect(targeting['preroll_1'].length).to.equal(3); + expect(targeting['midroll_1'].length).to.equal(2); + }); + + it('should only select bids less than adpod duration', function() { + amStub.returns([ + createBid(10, 'preroll_1', 90, '10.00_airline_90s', '123', 'airline'), + createBid(15, 'preroll_1', 90, '15.00_airline_90s', '123', 'airline'), + createBid(15, 'midroll_1', 90, '15.00_travel_90s', '123', 'travel') + ]); + let targeting; + getTargeting({ + callback: function(errorMsg, targetingResult) { + targeting = targetingResult; + } + }); + + expect(targeting['preroll_1']).to.be.empty; + expect(targeting['midroll_1']).to.be.empty; + }); + + it('should select bids when deferCaching is enabled', function() { + config.setConfig({ + adpod: { + deferCaching: true + } + }); + amStub.returns(getBidsReceived()); + let targeting; + getTargeting({ + callback: function(errorMsg, targetingResult) { + targeting = targetingResult; + } + }); + + expect(pbcStub.called).to.equal(true); + expect(targeting['preroll_1'].length).to.equal(3); + expect(targeting['midroll_1'].length).to.equal(4); + }); +}); + +function getBidsReceived() { + return [ + createBid(10, 'preroll_1', 15, '10.00_airline_15s', '123', 'airline'), + createBid(15, 'preroll_1', 15, '15.00_airline_15s', '123', 'airline'), + createBid(15, 'midroll_1', 30, '15.00_travel_30s', '123', 'travel'), + createBid(5, 'midroll_1', 5, '5.00_travel_5s', '123', 'travel'), + createBid(20, 'midroll_1', 60, '20.00_travel_60s', '123', 'travel'), + ] +} + +function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, industry) { + return { + 'bidderCode': 'appnexus', + 'width': 640, + 'height': 360, + 'statusMessage': 'Bid available', + 'adId': '28f24ced14586c', + 'mediaType': 'video', + 'source': 'client', + 'requestId': '28f24ced14586c', + 'cpm': cpm, + 'creativeId': 97517771, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 3600, + 'adUnitCode': adUnitCode, + 'video': { + 'context': 'adpod', + 'durationBucket': durationBucket + }, + 'appnexus': { + 'buyerMemberId': 9325 + }, + 'vastUrl': 'http://nym1-ib.adnxs.com/ab?ro=1&referrer=http%3A%2F%2Fprebid.org%2Fexamples%2Fvideo%2FjwPlayerPrebid.html&e=wqT_3QKQCKAQBAAAAwDWAAUBCOC2reIFENXVz86_iKrdKRiyjp7_7P7s0GQqNgkAAAECCBRAEQEHNAAAFEAZAAAA4HoUFEAhERIAKREJADERG6gw6dGnBjjtSEDtSEgCUMuBwC5YnPFbYABozbp1eIHdBIABAYoBA1VTRJIBAQbwUJgBAaABAagBAbABALgBA8ABBMgBAtABANgBAOABAPABAIoCO3VmKCdhJywgMjUyOTg4NSwgMTU0ODQ0MjQ2NCk7dWYoJ3InLCA5NzUxNzc3MTYeAPQAAZIC8QEhOXpPdkVBaTItTHdLRU11QndDNFlBQ0NjOFZzd0FEZ0FRQVJJN1VoUTZkR25CbGdBWUVwb0FIQ0FBWGdBZ0FHMEFvZ0JBSkFCQVpnQkFhQUJBYWdCQTdBQkFMa0I4NjFxcEFBQUZFREJBZk90YXFRQUFCUkF5UUhWSVlsRnN5SDRQOWtCQUFBQUFBQUE4RF9nQVFEMUFRQUFBQUNZQWdDZ0FnQzFBZ0FBQUFDOUFnQUFBQURBQWdESUFnRGdBZ0RvQWdENEFnQ0FBd0dRQXdDWUF3R29BN2I0dkFxNkF3bE9XVTB5T2pRd016SGdBODBGmgJhIU53M1VaUWkyLvQAKG5QRmJJQVFvQURFCY1cQUFVUURvSlRsbE5Nam8wTURNeFFNMEZTBZwYQUFBUEFfVREMDEFBQVcdDPBMwgI_aHR0cDovL3ByZWJpZC5vcmcvZGV2LWRvY3Mvc2hvdy12aWRlby13aXRoLWEtZGZwLXZpZGVvLXRhZy5odG1s2AIA4AKtmEjqAjRGSgAgZXhhbXBsZXMvBUUkL2p3UGxheWVyUAlseGh0bWzyAhMKD0NVU1RPTV9NT0RFTF9JRBIA8gIaChYyFgAgTEVBRl9OQU1FAR0IHgoaNh0ACEFTVAE-4ElGSUVEEgCAAwCIAwGQAwCYAxegAwGqAwDAA-CoAcgDANgDAOADAOgDAPgDAYAEAJIEDS91dC92Mw3-8E6YBACiBAsxMC4xLjEyLjE4MKgEjq4IsgQSCAEQAhiABSDoAigBKAIwADgDuAQAwAQAyAQA0gQOOTMyNSNOWU0yOjQwMzHaBAIIAeAEAPAEYTYgiAUBmAUAoAX_EQEUAcAFAMkFaXAU8D_SBQkJCQx4AADYBQHgBQHwBcOVC_oFBAgAEACQBgGYBgC4BgDBBgklJPA_yAYA2gYWChAJEDQAAAAAAAAAAAAAEAAYAA..&s=539bcaeb9ce05a13a8c4a6cab3c000194a8e8f53', + 'vastImpUrl': 'http://nym1-ib.adnxs.com/vast_track/v2?info=ZQAAAAMArgAFAQlgW0tcAAAAABHV6tP5Q6i6KRlgW0tcAAAAACDLgcAuKAAw7Ug47UhA0-hISLuv1AFQ6dGnBljDlQtiAkZSaAFwAXgAgAEBiAEBkAGABZgB6AKgAQCoAcuBwC4.&s=61db1767c8c362ef1a58d2c5587dd6a9b1015aeb&event_type=1', + 'auctionId': 'ec266b31-d652-49c5-8295-e83fafe5532b', + 'responseTimestamp': 1548442460888, + 'requestTimestamp': 1548442460827, + 'bidder': 'appnexus', + 'timeToRespond': 61, + 'pbLg': '5.00', + 'pbMg': '5.00', + 'pbHg': '5.00', + 'pbAg': '5.00', + 'pbDg': '5.00', + 'pbCg': '', + 'size': '640x360', + 'adserverTargeting': { + 'hb_bidder': 'appnexus', + 'hb_adid': '28f24ced14586c', + 'hb_pb': '5.00', + 'hb_size': '640x360', + 'hb_source': 'client', + 'hb_format': 'video', + 'hb_pb_cat_dur': priceIndustryDuration, + 'hb_cache_id': uuid + }, + 'customCacheKey': `${priceIndustryDuration}_${uuid}`, + 'meta': { + 'iabSubCatId': 'iab-1', + 'adServerCatId': industry + }, + 'videoCacheKey': '4cf395af-8fee-4960-af0e-88d44e399f14' + } +} From 1f04f557eb20c4bfd4111f67d43cd29700ecf00f Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Wed, 27 Feb 2019 12:44:45 -0500 Subject: [PATCH 1039/1594] Category translation module for adpod (#3513) * category translation module * update function name, refactor code and add getIabSubCategory function * move hook init and import adpod * bugfix in getting adapter spec * add hook for adserver in use * updated getting iab subcategory code * bugfix * Use individual mapping file for translation * Update default mapping url * add hook only once * update mapping url * Update brandCategoryExclusion logic * wrap in try catch * update todos and add default refreshInDays * udpate hooks * update hook --- modules/appnexusBidAdapter.js | 38 +++++- modules/categoryTranslation.js | 96 +++++++++++++ package-lock.json | 103 ++++++++------ src/adapters/bidderFactory.js | 74 +++++++++- src/utils.js | 20 +++ test/spec/modules/categoryTranslation_spec.js | 98 ++++++++++++++ test/spec/unit/core/bidderFactory_spec.js | 127 +++++++++++++++++- 7 files changed, 510 insertions(+), 46 deletions(-) create mode 100644 modules/categoryTranslation.js create mode 100644 test/spec/modules/categoryTranslation_spec.js diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index d330c09aa10..375c7d45c78 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -1,7 +1,7 @@ import { Renderer } from '../src/Renderer'; import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; +import { registerBidder, getIabSubCategory } from '../src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO, ADPOD } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; @@ -32,6 +32,7 @@ const NATIVE_MAPPING = { displayUrl: 'displayurl' }; const SOURCE = 'pbjs'; +const mappingFileUrl = '//acdn.adnxs.com/prebid/appnexus-mapping/mappings.json'; export const spec = { code: BIDDER_CODE, @@ -209,6 +210,24 @@ export const spec = { 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: 7 + } + }, + getUserSyncs: function(syncOptions) { if (syncOptions.iframeEnabled) { return [{ @@ -316,6 +335,21 @@ function newBid(serverBid, rtbBid, bidderRequest) { vastImpUrl: rtbBid.notify_url, ttl: 3600 }); + + const videoContext = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); + if (videoContext === ADPOD) { + const iabSubCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); + + bid.meta = { + iabSubCatId + }; + + bid.video = { + context: ADPOD, + durationSeconds: Math.ceil(rtbBid.rtb.video.duration_ms / 1000), + }; + } + // This supports Outstream Video if (rtbBid.renderer_url) { const rendererOptions = utils.deepAccess( diff --git a/modules/categoryTranslation.js b/modules/categoryTranslation.js new file mode 100644 index 00000000000..ee1b088e408 --- /dev/null +++ b/modules/categoryTranslation.js @@ -0,0 +1,96 @@ +/** + * This module translates iab category to freewheel industry using translation mapping file + * Publisher can set translation file by using setConfig method + * + * Example: + * config.setConfig({ + * 'brandCategoryTranslation': { + * 'translationFile': 'http://sample.com' + * } + * }); + * If publisher has not defined translation file than prebid will use default prebid translation file provided here //cdn.jsdelivr.net/gh/prebid/category-mapping-file@1/freewheel-mapping.json + */ + +import { config } from '../src/config'; +import { setupBeforeHookFnOnce, hook } from '../src/hook'; +import { ajax } from '../src/ajax'; +import { timestamp, logError, setDataInLocalStorage, getDataFromLocalStorage } from '../src/utils'; +import { addBidResponse } from '../src/auction'; + +const DEFAULT_TRANSLATION_FILE_URL = '//cdn.jsdelivr.net/gh/prebid/category-mapping-file@1/freewheel-mapping.json'; +const DEFAULT_IAB_TO_FW_MAPPING_KEY = 'iabToFwMappingkey'; +const DEFAULT_IAB_TO_FW_MAPPING_KEY_PUB = 'iabToFwMappingkeyPub'; +const refreshInDays = 1; + +export const registerAdserver = hook('async', function(adServer) { + let url; + if (adServer === 'freewheel') { + url = DEFAULT_TRANSLATION_FILE_URL; + } + initTranslation(url, DEFAULT_IAB_TO_FW_MAPPING_KEY); +}, 'registerAdserver'); +registerAdserver(); + +export function getAdserverCategoryHook(fn, adUnitCode, bid) { + if (!bid) { + return fn.call(this, adUnitCode); // if no bid, call original and let it display warnings + } + + if (!config.getConfig('adpod.brandCategoryExclusion')) { + return fn.call(this, adUnitCode, bid); + } + + let localStorageKey = (config.getConfig('brandCategoryTranslation.translationFile')) ? DEFAULT_IAB_TO_FW_MAPPING_KEY_PUB : DEFAULT_IAB_TO_FW_MAPPING_KEY; + + if (bid.meta && !bid.meta.adServerCatId) { + let mapping = getDataFromLocalStorage(localStorageKey); + if (mapping) { + try { + mapping = JSON.parse(mapping); + } catch (error) { + logError('Failed to parse translation mapping file'); + } + if (bid.meta.iabSubCatId && mapping['mapping'] && mapping['mapping'][bid.meta.iabSubCatId]) { + bid.meta.adServerCatId = mapping['mapping'][bid.meta.iabSubCatId]['id']; + } else { + // This bid will be automatically ignored by adpod module as adServerCatId was not found + bid.meta.adServerCatId = undefined; + } + } else { + logError('Translation mapping data not found in local storage'); + } + } + fn.call(this, adUnitCode, bid); +} + +export function initTranslation(url, localStorageKey) { + setupBeforeHookFnOnce(addBidResponse, getAdserverCategoryHook, 50); + let mappingData = getDataFromLocalStorage(localStorageKey); + if (!mappingData || timestamp() < mappingData.lastUpdated + refreshInDays * 24 * 60 * 60 * 1000) { + ajax(url, + { + success: (response) => { + try { + response = JSON.parse(response); + response['lastUpdated'] = timestamp(); + setDataInLocalStorage(localStorageKey, JSON.stringify(response)); + } catch (error) { + logError('Failed to parse translation mapping file'); + } + }, + error: () => { + logError('Failed to load brand category translation file.') + } + }, + ); + } +} + +function setConfig(config) { + if (config.translationFile) { + // if publisher has defined the translation file, preload that file here + initTranslation(config.translationFile, DEFAULT_IAB_TO_FW_MAPPING_KEY_PUB); + } +} + +config.getConfig('brandCategoryTranslation', config => setConfig(config.brandCategoryTranslation)); diff --git a/package-lock.json b/package-lock.json index 69e270c5505..d51bb4a9dab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3038,7 +3038,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3463,7 +3463,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -4590,7 +4590,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4604,7 +4604,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4620,7 +4620,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4640,7 +4640,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -5333,7 +5333,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5846,7 +5846,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { @@ -6044,7 +6044,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6065,12 +6066,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6085,17 +6088,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6212,7 +6218,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6224,6 +6231,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6238,6 +6246,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6245,12 +6254,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6269,6 +6280,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6349,7 +6361,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6361,6 +6374,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6446,7 +6460,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6482,6 +6497,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6501,6 +6517,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6544,12 +6561,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -7343,7 +7362,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7360,7 +7379,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -8105,7 +8124,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -9094,7 +9113,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9130,7 +9149,7 @@ "mime": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha1-4FH9iBNYWF8yed8zP+aU2gvP/dY=", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true }, "rimraf": { @@ -9803,7 +9822,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -9816,7 +9835,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true }, "debug": { @@ -10337,7 +10356,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10373,7 +10392,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10981,7 +11000,7 @@ "opn": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha1-y1Reeqt4VivrEao7+rxwQuF2EDU=", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -10999,7 +11018,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -12591,7 +12610,7 @@ "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", "dev": true }, "right-align": { @@ -13046,7 +13065,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -13060,7 +13079,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13083,7 +13102,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -13105,7 +13124,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13121,7 +13140,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13133,7 +13152,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13271,7 +13290,7 @@ }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13399,7 +13418,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -14267,7 +14286,7 @@ "dependencies": { "bluebird": { "version": "3.4.7", - "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true } @@ -14368,7 +14387,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -15045,7 +15064,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 8d67fe098f9..a65c657cbb5 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -8,7 +8,10 @@ import { isValidVideoBid } from '../video'; import CONSTANTS from '../constants.json'; import events from '../events'; import includes from 'core-js/library/fn/array/includes'; -import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest } from '../utils'; +import { ajax } from '../ajax'; +import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, setDataInLocalStorage, getDataFromLocalStorage, deepAccess } from '../utils'; +import { ADPOD } from '../mediaTypes'; +import { getHook } from '../hook'; /** * This file aims to support Adapters during the Prebid 0.x -> 1.x transition. @@ -126,6 +129,8 @@ import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSiz // common params for all mediaTypes const COMMON_BID_RESPONSE_KEYS = ['requestId', 'cpm', 'ttl', 'creativeId', 'netRevenue', 'currency']; +const DEFAULT_REFRESHIN_DAYS = 1; + /** * Register a bidder with prebid, using the given spec. * @@ -345,6 +350,73 @@ export function newBidder(spec) { } } +export function preloadBidderMappingFile(fn, adUnits) { + if (!config.getConfig('adpod.brandCategoryExclusion')) { + return fn.call(this, adUnits); + } + let adPodBidders = adUnits + .filter((adUnit) => deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) + .map((adUnit) => adUnit.bids.map((bid) => bid.bidder)) + .reduce(flatten, []) + .filter(uniques); + + adPodBidders.forEach(bidder => { + let bidderSpec = adapterManager.getBidAdapter(bidder); + if (bidderSpec.getSpec().getMappingFileInfo) { + let info = bidderSpec.getSpec().getMappingFileInfo(); + let refreshInDays = (info.refreshInDays) ? info.refreshInDays : DEFAULT_REFRESHIN_DAYS; + let key = (info.localStorageKey) ? info.localStorageKey : bidderSpec.getSpec().code; + let mappingData = getDataFromLocalStorage(key); + if (!mappingData || timestamp() < mappingData.lastUpdated + refreshInDays * 24 * 60 * 60 * 1000) { + ajax(info.url, + { + success: (response) => { + try { + response = JSON.parse(response); + let mapping = { + lastUpdated: timestamp(), + mapping: response.mapping + } + setDataInLocalStorage(key, JSON.stringify(mapping)); + } catch (error) { + logError(`Failed to parse ${bidder} bidder translation mapping file`); + } + }, + error: () => { + logError(`Failed to load ${bidder} bidder translation file`) + } + }, + ); + } + } + }); + fn.call(this, adUnits); +} + +getHook('checkAdUnitSetup').before(preloadBidderMappingFile); + +/** + * Reads the data stored in localstorage and returns iab subcategory + * @param {string} bidderCode bidderCode + * @param {string} category bidders category + */ +export function getIabSubCategory(bidderCode, category) { + let bidderSpec = adapterManager.getBidAdapter(bidderCode); + if (bidderSpec.getSpec().getMappingFileInfo) { + let info = bidderSpec.getSpec().getMappingFileInfo(); + let key = (info.localStorageKey) ? info.localStorageKey : bidderSpec.getBidderCode(); + let data = getDataFromLocalStorage(key); + if (data) { + try { + data = JSON.parse(data); + } catch (error) { + logError(`Failed to parse ${bidderCode} mapping data stored in local storage`); + } + return (data.mapping[category]) ? data.mapping[category] : null; + } + } +} + // check that the bid has a width and height set function validBidSize(adUnitCode, bid, bidRequests) { if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) { diff --git a/src/utils.js b/src/utils.js index 30b9b746bc7..a1de77499b4 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1198,6 +1198,26 @@ export function convertTypes(types, params) { return params; } +export function setDataInLocalStorage(key, value) { + if (hasLocalStorage()) { + window.localStorage.setItem(key, value); + } +} + +export function getDataFromLocalStorage(key) { + if (hasLocalStorage()) { + return window.localStorage.getItem(key); + } +} + +export function hasLocalStorage() { + try { + return !!window.localStorage; + } catch (e) { + logError('Local storage api disabled'); + } +} + export function isArrayOfNums(val, size) { return (isArray(val)) && ((size) ? val.length === size : true) && (val.every(v => isInteger(v))); } diff --git a/test/spec/modules/categoryTranslation_spec.js b/test/spec/modules/categoryTranslation_spec.js new file mode 100644 index 00000000000..17cc07269b0 --- /dev/null +++ b/test/spec/modules/categoryTranslation_spec.js @@ -0,0 +1,98 @@ +import { getAdserverCategoryHook, initTranslation } from 'modules/categoryTranslation'; +import { config } from 'src/config'; +import * as utils from 'src/utils'; +import { expect } from 'chai'; + +describe('category translation', function () { + let fakeTranslationServer; + let getLocalStorageStub; + + beforeEach(function () { + fakeTranslationServer = sinon.fakeServer.create(); + getLocalStorageStub = sinon.stub(utils, 'getDataFromLocalStorage'); + }); + + afterEach(function() { + fakeTranslationServer.reset(); + getLocalStorageStub.restore(); + config.resetConfig(); + }); + + it('should translate iab category to adserver category', function () { + config.setConfig({ + 'adpod': { + 'brandCategoryExclusion': true + } + }); + getLocalStorageStub.returns(JSON.stringify({ + 'mapping': { + 'iab-1': { + 'id': 1, + 'name': 'sample' + } + } + })); + let bid = { + meta: { + iabSubCatId: 'iab-1' + } + } + getAdserverCategoryHook(sinon.spy(), 'code', bid); + expect(bid.meta.adServerCatId).to.equal(1); + }); + + it('should set adserverCatId to undefined if not found in mapping file', function() { + config.setConfig({ + 'adpod': { + 'brandCategoryExclusion': true + } + }); + getLocalStorageStub.returns(JSON.stringify({ + 'mapping': { + 'iab-1': { + 'id': 1, + 'name': 'sample' + } + } + })); + let bid = { + meta: { + iabSubCatId: 'iab-2' + } + } + getAdserverCategoryHook(sinon.spy(), 'code', bid); + expect(bid.meta.adServerCatId).to.equal(undefined); + }); + + it('should not make ajax call to update mapping file if data found in localstorage and is not expired', function () { + let clock = sinon.useFakeTimers(utils.timestamp()); + getLocalStorageStub.returns(JSON.stringify({ + lastUpdated: utils.timestamp(), + mapping: { + 'iab-1': '1' + } + })); + initTranslation(); + expect(fakeTranslationServer.requests.length).to.equal(0); + clock.restore(); + }); + + it('should use default mapping file if publisher has not defined in config', function () { + getLocalStorageStub.returns(null); + initTranslation('http://sample.com', 'somekey'); + expect(fakeTranslationServer.requests.length).to.equal(1); + expect(fakeTranslationServer.requests[0].url).to.equal('http://sample.com'); + }); + + it('should use publisher defined defined mapping file', function () { + config.setConfig({ + 'brandCategoryTranslation': { + 'translationFile': 'http://sample.com' + } + }); + getLocalStorageStub.returns(null); + initTranslation('http://sample.com', 'somekey'); + expect(fakeTranslationServer.requests.length).to.equal(2); + expect(fakeTranslationServer.requests[0].url).to.equal('http://sample.com'); + }); +}); diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index b82a6b65c99..9e201afbe6c 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1,4 +1,4 @@ -import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; +import { newBidder, registerBidder, preloadBidderMappingFile } from 'src/adapters/bidderFactory'; import adapterManager from 'src/adapterManager'; import * as ajax from 'src/ajax'; import { expect } from 'chai'; @@ -775,3 +775,128 @@ describe('validate bid response: ', function () { expect(logErrorSpy.callCount).to.equal(0); }); }); + +describe('preload mapping url hook', function() { + let fakeTranslationServer; + let getLocalStorageStub; + let adapterManagerStub; + + beforeEach(function () { + fakeTranslationServer = sinon.fakeServer.create(); + getLocalStorageStub = sinon.stub(utils, 'getDataFromLocalStorage'); + adapterManagerStub = sinon.stub(adapterManager, 'getBidAdapter'); + }); + + afterEach(function() { + getLocalStorageStub.restore(); + adapterManagerStub.restore(); + config.resetConfig(); + }); + + it('should preload mapping url file', function() { + config.setConfig({ + 'adpod': { + 'brandCategoryExclusion': true + } + }); + let adUnits = [{ + code: 'midroll_1', + mediaTypes: { + video: { + context: 'adpod' + } + }, + bids: [ + { + bidder: 'sampleBidder1', + params: { + placementId: 14542875, + } + } + ] + }]; + getLocalStorageStub.returns(null); + adapterManagerStub.withArgs('sampleBidder1').returns({ + getSpec: function() { + return { + 'getMappingFileInfo': function() { + return { + url: 'http://sample.com', + refreshInDays: 7, + key: `sampleBidder1MappingFile` + } + } + } + } + }); + preloadBidderMappingFile(sinon.spy(), adUnits); + expect(fakeTranslationServer.requests.length).to.equal(1); + }); + + it('should preload mapping url file for all bidders', function() { + config.setConfig({ + 'adpod': { + 'brandCategoryExclusion': true + } + }); + let adUnits = [{ + code: 'midroll_1', + mediaTypes: { + video: { + context: 'adpod' + } + }, + bids: [ + { + bidder: 'sampleBidder1', + params: { + placementId: 14542875, + } + }, + { + bidder: 'sampleBidder2', + params: { + placementId: 123456, + } + } + ] + }]; + getLocalStorageStub.returns(null); + adapterManagerStub.withArgs('sampleBidder1').returns({ + getSpec: function() { + return { + 'getMappingFileInfo': function() { + return { + url: 'http://sample.com', + refreshInDays: 7, + key: `sampleBidder1MappingFile` + } + } + } + } + }); + adapterManagerStub.withArgs('sampleBidder2').returns({ + getSpec: function() { + return { + 'getMappingFileInfo': function() { + return { + url: 'http://sample.com', + refreshInDays: 7, + key: `sampleBidder2MappingFile` + } + } + } + } + }); + preloadBidderMappingFile(sinon.spy(), adUnits); + expect(fakeTranslationServer.requests.length).to.equal(2); + + config.setConfig({ + 'adpod': { + 'brandCategoryExclusion': false + } + }); + preloadBidderMappingFile(sinon.spy(), adUnits); + expect(fakeTranslationServer.requests.length).to.equal(2); + }); +}); From 621a057d69c9a623b89b37bd735214e0705e0f61 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Wed, 27 Feb 2019 09:58:29 -0800 Subject: [PATCH 1040/1594] Add adpod support to AppNexus adapter (#3484) * Add new context type * Write request duplication test * Duplicate adpod placement for request * Write requireExactDuration duplication test * Duplicate adpod placement when requireExactDuration is set * Add brandCategoryExclusion config to request * Add adpod fields to bid response object * Split large requests into batches * Get context from correct object * Use util function to get request subsets * Use correct mediaType.video configuration names * Rename category prop to iabSubCatId * Comment sub function usage * Round down placements when config uneven * Set max/min duration across tags when config numbers are uneven * Account for multiple adpod adUnits * Round durationSeconds up if remainder * Use adpod constant * Update subCat usage comment * Update subCat usage comment * Change ceil to floor * fix unit test * correct flag name * uncomment todos --- modules/appnexusBidAdapter.js | 114 +++++++++- src/utils.js | 44 +++- test/spec/modules/appnexusBidAdapter_spec.js | 220 +++++++++++++++++++ 3 files changed, 368 insertions(+), 10 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 375c7d45c78..0dc05ced08a 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -1,5 +1,6 @@ import { Renderer } from '../src/Renderer'; import * as utils from '../src/utils'; +import { config } from '../src/config'; import { registerBidder, getIabSubCategory } from '../src/adapters/bidderFactory'; import { BANNER, NATIVE, VIDEO, ADPOD } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; @@ -32,6 +33,7 @@ const NATIVE_MAPPING = { displayUrl: 'displayurl' }; const SOURCE = 'pbjs'; +const MAX_IMPS_PER_REQUEST = 15; const mappingFileUrl = '//acdn.adnxs.com/prebid/appnexus-mapping/mappings.json'; export const spec = { @@ -120,6 +122,7 @@ export const spec = { version: '$prebid.version$' } }; + if (member > 0) { payload.member_id = member; } @@ -131,6 +134,10 @@ export const spec = { payload.app = appIdObj; } + if (config.getConfig('adpod.brandCategoryExclusion')) { + payload.brand_category_uniqueness = true; + } + if (debugObjParams.enabled) { payload.debug = debugObjParams; utils.logInfo('AppNexus Debug Auction Settings:\n\n' + JSON.stringify(debugObjParams, null, 4)); @@ -154,13 +161,18 @@ export const spec = { payload.referrer_detection = refererinfo; } - const payloadString = JSON.stringify(payload); - return { - method: 'POST', - url: URL, - data: payloadString, - bidderRequest - }; + 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]; + }); + } + + const request = formatRequest(payload, bidderRequest); + return request; }, /** @@ -276,6 +288,35 @@ function deleteValues(keyPairObj) { } } +function formatRequest(payload, bidderRequest) { + let request = []; + + if (payload.tags.length > MAX_IMPS_PER_REQUEST) { + const clonedPayload = utils.deepClone(payload); + + utils.chunk(payload.tags, MAX_IMPS_PER_REQUEST).forEach(tags => { + clonedPayload.tags = tags; + const payloadString = JSON.stringify(clonedPayload); + request.push({ + method: 'POST', + url: URL, + data: payloadString, + bidderRequest + }); + }); + } else { + const payloadString = JSON.stringify(payload); + request = { + method: 'POST', + url: URL, + data: payloadString, + bidderRequest + }; + } + + return request; +} + function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { const renderer = Renderer.install({ id: rtbBid.renderer_id, @@ -339,14 +380,13 @@ function newBid(serverBid, rtbBid, bidderRequest) { const videoContext = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); if (videoContext === ADPOD) { const iabSubCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); - bid.meta = { iabSubCatId }; bid.video = { context: ADPOD, - durationSeconds: Math.ceil(rtbBid.rtb.video.duration_ms / 1000), + durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), }; } @@ -553,6 +593,62 @@ function hasDebug(bid) { return !!bid.debug } +function hasAdPod(bid) { + return ( + bid.mediaTypes && + bid.mediaTypes.video && + bid.mediaTypes.video.context === ADPOD + ); +} + +/** + * 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 = utils.getMaxValueFromArray(durationRangeSec); + + const tagToDuplicate = tags.filter(tag => tag.uuid === adPodBid.bidId); + let request = utils.fill(...tagToDuplicate, numberOfPlacements); + + if (requireExactDuration) { + const divider = Math.ceil(numberOfPlacements / durationRangeSec.length); + const chunked = utils.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 = utils.getMinValueFromArray(durationRangeSec); + const numberOfPlacements = Math.floor(adPodDurationSec / minAllowedDuration); + + return requireExactDuration + ? Math.max(numberOfPlacements, durationRangeSec.length) + : numberOfPlacements; +} + +function setVideoProperty(tag, key, value) { + if (utils.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); } diff --git a/src/utils.js b/src/utils.js index a1de77499b4..3581b94cb25 100644 --- a/src/utils.js +++ b/src/utils.js @@ -997,7 +997,7 @@ export function getDefinedParams(object, params) { */ export function isValidMediaTypes(mediaTypes) { const SUPPORTED_MEDIA_TYPES = ['banner', 'native', 'video']; - const SUPPORTED_STREAM_TYPES = ['instream', 'outstream']; + const SUPPORTED_STREAM_TYPES = ['instream', 'outstream', 'adpod']; const types = Object.keys(mediaTypes); @@ -1221,3 +1221,45 @@ export function hasLocalStorage() { export function isArrayOfNums(val, size) { return (isArray(val)) && ((size) ? val.length === size : true) && (val.every(v => isInteger(v))); } + +/** + * Creates an array of n length and fills each item with the given value + */ +export function fill(value, length) { + let newArray = []; + + for (let i = 0; i < length; i++) { + let valueToPush = isPlainObject(value) ? deepClone(value) : value; + newArray.push(valueToPush); + } + + return newArray; +} + +/** + * http://npm.im/chunk + * Returns an array with *size* chunks from given array + * + * Example: + * ['a', 'b', 'c', 'd', 'e'] chunked by 2 => + * [['a', 'b'], ['c', 'd'], ['e']] + */ +export function chunk(array, size) { + let newArray = []; + + for (let i = 0; i < Math.ceil(array.length / size); i++) { + let start = i * size; + let end = start + size; + newArray.push(array.slice(start, end)); + } + + return newArray; +} + +export function getMinValueFromArray(array) { + return Math.min(...array); +} + +export function getMaxValueFromArray(array) { + return Math.max(...array); +} diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index b94e574713c..d2094217c70 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -1,7 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/appnexusBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; +import * as bidderFactory from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; +import { config } from 'src/config'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; @@ -171,6 +173,178 @@ describe('AppNexusAdapter', function () { }); }); + 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('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('should attach native params to the request', function () { let bidRequest = Object.assign({}, bidRequests[0], @@ -425,6 +599,15 @@ describe('AppNexusAdapter', function () { }) describe('interpretResponse', function () { + let bfStub; + before(function() { + bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); + }); + + after(function() { + bfStub.restore(); + }); + let response = { 'version': '3.0.0', 'tags': [ @@ -544,6 +727,43 @@ describe('AppNexusAdapter', function () { 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': { + 'content': '', + 'duration_ms': 30000, + } + } + }] + }] + }; + + let bidderRequest = { + bids: [{ + bidId: '84ab500420319d', + adUnitCode: 'code', + mediaTypes: { + video: { + context: 'adpod' + } + } + }] + }; + bfStub.returns('1'); + + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + 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'; From fcbaa4cd03ed31ce21e770ebca54e36b2eb7da06 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 27 Feb 2019 12:59:15 -0500 Subject: [PATCH 1041/1594] update targeting to not include adpod bids (#3558) --- src/targeting.js | 4 +++- test/spec/unit/core/targeting_spec.js | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/targeting.js b/src/targeting.js index 1d0a1de2cd7..90897b8d956 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -1,8 +1,9 @@ -import { uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp } from './utils'; +import { uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp, deepAccess } from './utils'; import { config } from './config'; import { NATIVE_TARGETING_KEYS } from './native'; import { auctionManager } from './auctionManager'; import { sizeSupported } from './sizeMapping'; +import { ADPOD } from './mediaTypes'; import includes from 'core-js/library/fn/array/includes'; const utils = require('./utils.js'); @@ -220,6 +221,7 @@ export function newTargeting(auctionManager) { } bidsReceived = bidsReceived + .filter(bid => deepAccess(bid, 'video.context') !== ADPOD) .filter(bid => bid.mediaType !== 'banner' || sizeSupported([bid.width, bid.height])) .filter(filters.isUnusedBid) .filter(filters.isBidNotExpired) diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index c7e1ad9e2e7..13ebfd7dc4e 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -179,6 +179,17 @@ describe('targeting tests', function () { // expect the winning CPM to be equal to the sendAllBidCPM expect(targeting['/123456/header-bid-tag-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]); }); + + it('does not include adpod type bids in the getBidsReceived results', function () { + let adpodBid = utils.deepClone(bid1); + adpodBid.video = { context: 'adpod', durationSeconds: 15, durationBucket: 15 }; + adpodBid.cpm = 5; + bidsReceived.push(adpodBid); + + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + expect(targeting['/123456/header-bid-tag-0']).to.contain.keys('hb_deal', 'hb_adid', 'hb_bidder'); + expect(targeting['/123456/header-bid-tag-0']['hb_adid']).to.equal(bid1.adId); + }); }); // end getAllTargeting tests describe('getAllTargeting without bids return empty object', function () { From 99977a9d61cee1fb6e25ed97068b06a15e99ea7a Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Wed, 27 Feb 2019 11:07:22 -0800 Subject: [PATCH 1042/1594] Send placeholders for configured native assets (#3573) * Send placeholders for configured native assets * Post native assets on replacement request * Update names * Change config name --- src/auction.js | 6 +++--- src/native.js | 35 +++++++++++++++++++++++++++++++++-- src/secureCreatives.js | 8 +++++++- src/utils.js | 13 +++++++++++++ test/spec/native_spec.js | 40 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 95 insertions(+), 7 deletions(-) diff --git a/src/auction.js b/src/auction.js index e83f7d061af..96c59f43eef 100644 --- a/src/auction.js +++ b/src/auction.js @@ -488,7 +488,7 @@ function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) { // if there is any key value pairs to map do here var keyValues; if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) { - keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject); + keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq); } // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs @@ -563,7 +563,7 @@ export function getStandardBidderSettings(mediaType) { return bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; } -export function getKeyValueTargetingPairs(bidderCode, custBidObj) { +export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) { if (!custBidObj) { return {}; } @@ -586,7 +586,7 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj) { // set native key value targeting if (custBidObj['native']) { - keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj)); + keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj, bidReq)); } return keyValues; diff --git a/src/native.js b/src/native.js index a5609739832..f30df7e3ef7 100644 --- a/src/native.js +++ b/src/native.js @@ -1,4 +1,4 @@ -import { deepAccess, getBidRequest, logError, triggerPixel, insertHtmlIntoIframe } from './utils'; +import { deepAccess, getBidRequest, getKeyByValue, insertHtmlIntoIframe, logError, triggerPixel } from './utils'; import includes from 'core-js/library/fn/array/includes'; const CONSTANTS = require('./constants.json'); @@ -151,7 +151,7 @@ export function fireNativeTrackers(message, adObject) { * @param {Object} bid * @return {Object} targeting */ -export function getNativeTargeting(bid) { +export function getNativeTargeting(bid, bidReq) { let keyValues = {}; Object.keys(bid['native']).forEach(asset => { @@ -163,6 +163,16 @@ export function getNativeTargeting(bid) { value = value.url; } + const sendPlaceholder = deepAccess( + bidReq, + `mediaTypes.native.${asset}.sendId` + ); + + if (sendPlaceholder) { + const placeholder = `${key}:${bid.adId}`; + value = placeholder; + } + if (key && value) { keyValues[key] = value; } @@ -170,3 +180,24 @@ export function getNativeTargeting(bid) { return keyValues; } + +/** + * Constructs a message object containing asset values for each of the + * requested data keys. + */ +export function getAssetMessage(data, adObject) { + const message = { + message: 'assetResponse', + adId: data.adId, + assets: [], + }; + + data.assets.forEach(asset => { + const key = getKeyByValue(CONSTANTS.NATIVE_KEYS, asset); + const value = adObject.native[key]; + + message.assets.push({ key, value }); + }); + + return message; +} diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 32ad27a0496..3b5f6128ee9 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -4,7 +4,7 @@ */ import events from './events'; -import { fireNativeTrackers } from './native'; +import { fireNativeTrackers, getAssetMessage } from './native'; import { EVENTS } from './constants'; import { isSlotMatchingAdUnitCode, logWarn, replaceAuctionPrice } from './utils'; import { auctionManager } from './auctionManager'; @@ -46,6 +46,12 @@ function receiveMessage(ev) { // adId: '%%PATTERN:hb_adid%%' // }), '*'); if (data.message === 'Prebid Native') { + if (data.action === 'assetRequest') { + const message = getAssetMessage(data, adObject); + ev.source.postMessage(JSON.stringify(message), ev.origin); + return; + } + fireNativeTrackers(data, adObject); auctionManager.addWinningBid(adObject); events.emit(BID_WON, adObject); diff --git a/src/utils.js b/src/utils.js index 3581b94cb25..5e70b31b0b2 100644 --- a/src/utils.js +++ b/src/utils.js @@ -783,6 +783,19 @@ export function getValue(obj, key) { return obj[key]; } +/** + * Get the key of an object for a given value + */ +export function getKeyByValue(obj, value) { + for (let prop in obj) { + if (obj.hasOwnProperty(prop)) { + if (obj[prop] === value) { + return prop; + } + } + } +} + export function getBidderCodes(adUnits = $$PREBID_GLOBAL$$.adUnits) { // this could memoize adUnits return adUnits.map(unit => unit.bids.map(bid => bid.bidder) diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 3a016145fd2..d68d6c21958 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -1,9 +1,10 @@ import { expect } from 'chai'; -import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid } from 'src/native'; +import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid, getAssetMessage } from 'src/native'; import CONSTANTS from 'src/constants.json'; const utils = require('src/utils'); const bid = { + adId: '123', native: { title: 'Native Creative', body: 'Cool description great stuff', @@ -50,6 +51,22 @@ describe('native.js', function () { expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal(bid.native.clickUrl); }); + it('sends placeholders for configured assets', function () { + const bidRequest = { + mediaTypes: { + native: { + body: { sendId: true }, + clickUrl: { sendId: true }, + } + } + }; + 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'); + expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal('hb_native_linkurl:123'); + }); + it('should only include native targeting keys with values', function () { const targeting = getNativeTargeting(bidWithUndefinedFields); @@ -72,6 +89,27 @@ describe('native.js', function () { sinon.assert.calledOnce(triggerPixelStub); sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]); }); + + it('creates native asset message', function() { + const messageRequest = { + message: 'Prebid Native', + action: 'assetRequest', + adId: '123', + assets: ['hb_native_body', 'hb_native_linkurl'], + }; + + const message = getAssetMessage(messageRequest, bid); + + expect(message.assets.length).to.equal(2); + expect(message.assets).to.deep.include({ + key: 'body', + value: bid.native.body + }); + expect(message.assets).to.deep.include({ + key: 'clickUrl', + value: bid.native.clickUrl + }); + }); }); describe('validate native', function () { From 54b4188122f969dfe3c91a8b258d18378cfae021 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 27 Feb 2019 14:11:37 -0500 Subject: [PATCH 1043/1594] fix two issues related to hb_uuid and hb_cache_id targeting keys (#3568) * move logic that assigns bid targeting params * switch order of targeting keys assignment in dfpAdServerVideo * remove redundant cache key assignment in dfp module and update unit tests * refactor logic when adding cache targeting keys --- modules/dfpAdServerVideo.js | 3 -- src/auction.js | 20 +++++++++---- test/spec/modules/dfpAdServerVideo_spec.js | 33 ++++++++++++---------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 1b5f8509559..17a8f0f1144 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -160,9 +160,6 @@ function getCustParams(bid, options) { let customParams = Object.assign({}, allTargetingData, adserverTargeting, - { hb_uuid: bid && bid.videoCacheKey }, - // hb_uuid will be deprecated and replaced by hb_cache_id - { hb_cache_id: bid && bid.videoCacheKey }, optCustParams, ); return encodeURIComponent(formatQS(customParams)); diff --git a/src/auction.js b/src/auction.js index 96c59f43eef..9b52d26676b 100644 --- a/src/auction.js +++ b/src/auction.js @@ -386,6 +386,8 @@ export function doCallbacksIfTimedout(auctionInstance, bidResponse) { // Add a bid to the auction. export function addBidToAuction(auctionInstance, bidResponse) { + setupBidTargeting(bidResponse); + events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bidResponse); auctionInstance.addBidReceived(bidResponse); @@ -429,6 +431,7 @@ export const callPrebidCache = hook('async', function(auctionInstance, bidRespon doCallbacksIfTimedout(auctionInstance, bidResponse); } else { bidResponse.videoCacheKey = cacheIds[0].uuid; + if (!bidResponse.vastUrl) { bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); } @@ -485,16 +488,23 @@ function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) { bidObject.pbDg = priceStringsObj.dense; bidObject.pbCg = priceStringsObj.custom; - // if there is any key value pairs to map do here - var keyValues; + return bidObject; +} + +function setupBidTargeting(bidObject) { + let keyValues; if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) { keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq); } - // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs - bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); + let cacheTargetKeys = {}; + if (bidObject.videoCacheKey) { + cacheTargetKeys.hb_uuid = bidObject.videoCacheKey; + cacheTargetKeys.hb_cache_id = bidObject.videoCacheKey; + } - return bidObject; + // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs + bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, cacheTargetKeys, keyValues); } export function getStandardBidderSettings(mediaType) { diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 8afc597d3b4..ab988ec0fe3 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -10,7 +10,10 @@ import { targeting } from 'src/targeting'; const bid = { videoCacheKey: 'abc', - adserverTargeting: { }, + adserverTargeting: { + hb_uuid: 'abc', + hb_cache_id: 'abc', + }, }; describe('The DFP video support module', function () { @@ -40,7 +43,7 @@ describe('The DFP video support module', function () { }); it('can take an adserver url as a parameter', function () { - const bidCopy = Object.assign({ }, bid); + const bidCopy = utils.deepClone(bid); bidCopy.vastUrl = 'vastUrl.example'; const url = parse(buildDfpVideoUrl({ @@ -90,10 +93,10 @@ describe('The DFP video support module', function () { }); it('should include the cache key and adserver targeting in cust_params', function () { - const bidCopy = Object.assign({ }, bid); - bidCopy.adserverTargeting = { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { hb_adid: 'ad_id', - }; + }); const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -160,10 +163,10 @@ describe('The DFP video support module', function () { } }); - const bidCopy = Object.assign({ }, bid); - bidCopy.adserverTargeting = { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { hb_adid: 'ad_id', - }; + }); const url = parse(buildDfpVideoUrl({ adUnit: adUnitsCopy, @@ -184,10 +187,10 @@ describe('The DFP video support module', function () { }); it('should merge the user-provided cust_params with the default ones', function () { - const bidCopy = Object.assign({ }, bid); - bidCopy.adserverTargeting = { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { hb_adid: 'ad_id', - }; + }); const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -207,10 +210,10 @@ describe('The DFP video support module', function () { }); it('should merge the user-provided cust-params with the default ones when using url object', function () { - const bidCopy = Object.assign({ }, bid); - bidCopy.adserverTargeting = { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { hb_adid: 'ad_id', - }; + }); const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -229,7 +232,7 @@ describe('The DFP video support module', function () { }); it('should not overwrite an existing description_url for object input and cache disabled', function () { - const bidCopy = Object.assign({}, bid); + const bidCopy = utils.deepClone(bid); bidCopy.vastUrl = 'vastUrl.example'; const url = parse(buildDfpVideoUrl({ From 48172be4c72073694d497768950e56e04b0b83b8 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 27 Feb 2019 14:30:41 -0500 Subject: [PATCH 1044/1594] Revert "fix two issues related to hb_uuid and hb_cache_id targeting keys (#3568)" (#3595) This reverts commit 54b4188122f969dfe3c91a8b258d18378cfae021. --- modules/dfpAdServerVideo.js | 3 ++ src/auction.js | 20 ++++--------- test/spec/modules/dfpAdServerVideo_spec.js | 33 ++++++++++------------ 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 17a8f0f1144..1b5f8509559 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -160,6 +160,9 @@ function getCustParams(bid, options) { let customParams = Object.assign({}, allTargetingData, adserverTargeting, + { hb_uuid: bid && bid.videoCacheKey }, + // hb_uuid will be deprecated and replaced by hb_cache_id + { hb_cache_id: bid && bid.videoCacheKey }, optCustParams, ); return encodeURIComponent(formatQS(customParams)); diff --git a/src/auction.js b/src/auction.js index 9b52d26676b..96c59f43eef 100644 --- a/src/auction.js +++ b/src/auction.js @@ -386,8 +386,6 @@ export function doCallbacksIfTimedout(auctionInstance, bidResponse) { // Add a bid to the auction. export function addBidToAuction(auctionInstance, bidResponse) { - setupBidTargeting(bidResponse); - events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bidResponse); auctionInstance.addBidReceived(bidResponse); @@ -431,7 +429,6 @@ export const callPrebidCache = hook('async', function(auctionInstance, bidRespon doCallbacksIfTimedout(auctionInstance, bidResponse); } else { bidResponse.videoCacheKey = cacheIds[0].uuid; - if (!bidResponse.vastUrl) { bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); } @@ -488,23 +485,16 @@ function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) { bidObject.pbDg = priceStringsObj.dense; bidObject.pbCg = priceStringsObj.custom; - return bidObject; -} - -function setupBidTargeting(bidObject) { - let keyValues; + // if there is any key value pairs to map do here + var keyValues; if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) { keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq); } - let cacheTargetKeys = {}; - if (bidObject.videoCacheKey) { - cacheTargetKeys.hb_uuid = bidObject.videoCacheKey; - cacheTargetKeys.hb_cache_id = bidObject.videoCacheKey; - } - // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs - bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, cacheTargetKeys, keyValues); + bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); + + return bidObject; } export function getStandardBidderSettings(mediaType) { diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index ab988ec0fe3..8afc597d3b4 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -10,10 +10,7 @@ import { targeting } from 'src/targeting'; const bid = { videoCacheKey: 'abc', - adserverTargeting: { - hb_uuid: 'abc', - hb_cache_id: 'abc', - }, + adserverTargeting: { }, }; describe('The DFP video support module', function () { @@ -43,7 +40,7 @@ describe('The DFP video support module', function () { }); it('can take an adserver url as a parameter', function () { - const bidCopy = utils.deepClone(bid); + const bidCopy = Object.assign({ }, bid); bidCopy.vastUrl = 'vastUrl.example'; const url = parse(buildDfpVideoUrl({ @@ -93,10 +90,10 @@ describe('The DFP video support module', function () { }); it('should include the cache key and adserver targeting in cust_params', function () { - const bidCopy = utils.deepClone(bid); - bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { + const bidCopy = Object.assign({ }, bid); + bidCopy.adserverTargeting = { hb_adid: 'ad_id', - }); + }; const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -163,10 +160,10 @@ describe('The DFP video support module', function () { } }); - const bidCopy = utils.deepClone(bid); - bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { + const bidCopy = Object.assign({ }, bid); + bidCopy.adserverTargeting = { hb_adid: 'ad_id', - }); + }; const url = parse(buildDfpVideoUrl({ adUnit: adUnitsCopy, @@ -187,10 +184,10 @@ describe('The DFP video support module', function () { }); it('should merge the user-provided cust_params with the default ones', function () { - const bidCopy = utils.deepClone(bid); - bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { + const bidCopy = Object.assign({ }, bid); + bidCopy.adserverTargeting = { hb_adid: 'ad_id', - }); + }; const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -210,10 +207,10 @@ describe('The DFP video support module', function () { }); it('should merge the user-provided cust-params with the default ones when using url object', function () { - const bidCopy = utils.deepClone(bid); - bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { + const bidCopy = Object.assign({ }, bid); + bidCopy.adserverTargeting = { hb_adid: 'ad_id', - }); + }; const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -232,7 +229,7 @@ describe('The DFP video support module', function () { }); it('should not overwrite an existing description_url for object input and cache disabled', function () { - const bidCopy = utils.deepClone(bid); + const bidCopy = Object.assign({}, bid); bidCopy.vastUrl = 'vastUrl.example'; const url = parse(buildDfpVideoUrl({ From 4f63887a153a8db7ce889d574b910075f6348087 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 27 Feb 2019 14:46:18 -0500 Subject: [PATCH 1045/1594] Prebid 2.4.0 release --- package-lock.json | 1329 +++++++++++++++------------------------------ package.json | 2 +- 2 files changed, 431 insertions(+), 900 deletions(-) diff --git a/package-lock.json b/package-lock.json index d51bb4a9dab..54eddd62325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.4.0-pre", + "version": "2.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,36 +14,36 @@ } }, "@babel/core": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.2.2.tgz", - "integrity": "sha512-59vB0RWt09cAct5EIe58+NzGP4TFSD3Bz//2/ELy3ZeTeKF6VTD1AXlH8BGGbCX0PuobZBsIzO7IAI9PH67eKw==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.3.4.tgz", + "integrity": "sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.2.2", + "@babel/generator": "^7.3.4", "@babel/helpers": "^7.2.0", - "@babel/parser": "^7.2.2", + "@babel/parser": "^7.3.4", "@babel/template": "^7.2.2", - "@babel/traverse": "^7.2.2", - "@babel/types": "^7.2.2", + "@babel/traverse": "^7.3.4", + "@babel/types": "^7.3.4", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" } }, "@babel/generator": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.2.tgz", - "integrity": "sha512-f3QCuPppXxtZOEm5GWPra/uYUjmNQlu9pbAD8D/9jze4pTY83rTtB1igTBSwvkeNlC5gR24zFFkz+2WHLFQhqQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "^7.3.2", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -198,15 +198,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz", - "integrity": "sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.3.4.tgz", + "integrity": "sha512-pvObL9WVf2ADs+ePg0jrqlhHoxRXlOa+SHRHzAXIz2xkYuOHfGl+fKxPMaS4Fq+uje8JQPobnertBBvyrWnQ1A==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.0.0", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.2.3", - "@babel/types": "^7.0.0" + "@babel/traverse": "^7.3.4", + "@babel/types": "^7.3.4" } }, "@babel/helper-simple-access": { @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.2.tgz", - "integrity": "sha512-QzNUC2RO1gadg+fs21fi0Uu0OuGNzRKEmgCxoLNzbCdoprLwjfmZwzUrpUNfJPaVRwBpDY47A17yYEGWyRelnQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.4.tgz", + "integrity": "sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -290,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.2.tgz", - "integrity": "sha512-DjeMS+J2+lpANkYLLO+m6GjoTMygYglKmRe6cDTbFv3L9i6mmiE8fe6B8MtCSLZpVXscD5kn7s6SgtHrDoBWoA==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.4.tgz", + "integrity": "sha512-j7VQmbbkA+qrzNqbKHrBsW3ddFnOeva6wzSe/zB7T+xaxGc+RCpwo44wCmRixAIGRoIpmVgvzFzNJqQcO3/9RA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -366,9 +366,9 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz", - "integrity": "sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.3.4.tgz", + "integrity": "sha512-Y7nCzv2fw/jEZ9f678MuKdMo99MFDJMT/PvD9LisrR5JDFcJH6vYeH6RnjVt3p5tceyGRvTtEN0VOlU+rgHZjA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -386,19 +386,19 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz", - "integrity": "sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.3.4.tgz", + "integrity": "sha512-blRr2O8IOZLAOJklXLV4WhcEzpYafYQKSGT3+R26lWG41u/FODJuBggehtOwilVAcFu393v3OFj+HmaE6tVjhA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/plugin-transform-classes": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.2.tgz", - "integrity": "sha512-gEZvgTy1VtcDOaQty1l10T3jQmJKlNVxLDCs+3rCVPr6nMkODLELxViq5X9l+rfxbie3XrfrMCYYY6eX3aOcOQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.3.4.tgz", + "integrity": "sha512-J9fAvCFBkXEvBimgYxCjvaVDzL6thk0j0dBvCeZmIUDBwyt+nv6HfbImsSrWsYXfDNDivyANgJlFXDUWRTZBuA==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -406,7 +406,7 @@ "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-replace-supers": "^7.3.4", "@babel/helper-split-export-declaration": "^7.0.0", "globals": "^11.1.0" } @@ -509,9 +509,9 @@ } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz", - "integrity": "sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.3.4.tgz", + "integrity": "sha512-VZ4+jlGOF36S7TjKs8g4ojp4MEI+ebCQZdswWb/T9I4X84j8OtFAyjXjt/M16iIm5RIZn0UMQgg/VgIwo/87vw==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.0.0", @@ -557,9 +557,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz", - "integrity": "sha512-kB9+hhUidIgUoBQ0MsxMewhzr8i60nMa2KgeJKQWYrqQpqcBYtnpR+JgkadZVZoaEZ/eKu9mclFaVwhRpLNSzA==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.3.3.tgz", + "integrity": "sha512-IrIP25VvXWu/VlBWTpsjGptpomtIkYrN/3aDp4UKm7xK6UxZY88kcJ1UwETbzHAlwN21MnNfwlar0u8y3KpiXw==", "dev": true, "requires": { "@babel/helper-call-delegate": "^7.1.0", @@ -568,12 +568,12 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", - "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.3.4.tgz", + "integrity": "sha512-hvJg8EReQvXT6G9H2MvNPXkv9zK36Vxa1+csAVTpE1J3j0zlHplw76uudEbJxgvqZzAq9Yh45FLD4pk5mKRFQA==", "dev": true, "requires": { - "regenerator-transform": "^0.13.3" + "regenerator-transform": "^0.13.4" } }, "@babel/plugin-transform-shorthand-properties": { @@ -635,16 +635,16 @@ } }, "@babel/preset-env": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.1.tgz", - "integrity": "sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.4.tgz", + "integrity": "sha512-2mwqfYMK8weA0g0uBKOt4FE3iEodiHy9/CW0b+nWXcbL+pGzLx8ESYc+j9IIxr6LTDHWKgPm71i9smo02bw+gA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.3.1", + "@babel/plugin-proposal-object-rest-spread": "^7.3.4", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", "@babel/plugin-syntax-async-generators": "^7.2.0", @@ -652,10 +652,10 @@ "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.3.4", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.2.0", - "@babel/plugin-transform-classes": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.3.4", + "@babel/plugin-transform-classes": "^7.3.4", "@babel/plugin-transform-computed-properties": "^7.2.0", "@babel/plugin-transform-destructuring": "^7.2.0", "@babel/plugin-transform-dotall-regex": "^7.2.0", @@ -666,13 +666,13 @@ "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-modules-amd": "^7.2.0", "@babel/plugin-transform-modules-commonjs": "^7.2.0", - "@babel/plugin-transform-modules-systemjs": "^7.2.0", + "@babel/plugin-transform-modules-systemjs": "^7.3.4", "@babel/plugin-transform-modules-umd": "^7.2.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", "@babel/plugin-transform-new-target": "^7.0.0", "@babel/plugin-transform-object-super": "^7.2.0", "@babel/plugin-transform-parameters": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.3.4", "@babel/plugin-transform-shorthand-properties": "^7.2.0", "@babel/plugin-transform-spread": "^7.2.0", "@babel/plugin-transform-sticky-regex": "^7.2.0", @@ -697,30 +697,30 @@ } }, "@babel/traverse": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", - "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.2.2", + "@babel/generator": "^7.3.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.2.3", - "@babel/types": "^7.2.2", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.2.tgz", - "integrity": "sha512-3Y6H8xlUlpbGR+XvawiH0UXehqydTmNmEpozWcXymqwcrwYAl5KMvKtQ+TF6f6E08V6Jur7v/ykdDSF+WDEIXQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -800,16 +800,22 @@ } }, "@sinonjs/samsam": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.1.0.tgz", - "integrity": "sha512-IXio+GWY+Q8XUjHUOgK7wx8fpvr7IFffgyXb1bnJFfX3001KmHt35Zq4tp7MXZyjJPCLPuadesDYNk41LYtVjw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.2.0.tgz", + "integrity": "sha512-j5F1rScewLtx6pbTK0UAjA3jJj4RYiSKOix53YWv+Jzy/AZ69qHxUpU8fwVLjyKbEEud9QrLpv6Ggs7WqTimYw==", "dev": true, "requires": { "@sinonjs/commons": "^1.0.2", "array-from": "^2.1.1", - "lodash.get": "^4.4.2" + "lodash": "^4.17.11" } }, + "@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 + }, "@types/node": { "version": "8.10.40", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.40.tgz", @@ -974,9 +980,9 @@ "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "ansi-styles": { @@ -1338,12 +1344,6 @@ "js-tokens": "^3.0.2" }, "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", @@ -1369,15 +1369,6 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -2600,9 +2591,9 @@ } }, "big-integer": { - "version": "1.6.41", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.41.tgz", - "integrity": "sha512-d5AT9lMTYJ/ZE/4gzxb+5ttPcRWljVsvv7lF1w9KzkPhVUhBtHrjDo1J8swfZKepfLsliDhYa31zRYwcD0Yg9w==", + "version": "1.6.42", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.42.tgz", + "integrity": "sha512-3UQFKcRMx+5Z+IK5vYTMYK2jzLRJkt+XqyDdacgWgtMjjuifKpKTFneJLEgeBElOE2/lXZ1LcMcb5s8pwG2U8Q==", "dev": true }, "big.js": { @@ -2865,14 +2856,14 @@ } }, "browserslist": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.1.tgz", - "integrity": "sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.2.tgz", + "integrity": "sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000929", - "electron-to-chromium": "^1.3.103", - "node-releases": "^1.1.3" + "caniuse-lite": "^1.0.30000939", + "electron-to-chromium": "^1.3.113", + "node-releases": "^1.1.8" } }, "browserstack": { @@ -3007,12 +2998,6 @@ "responselike": "1.0.2" }, "dependencies": { - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", @@ -3080,9 +3065,9 @@ "dev": true }, "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "camelcase-keys": { @@ -3104,9 +3089,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000936", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000936.tgz", - "integrity": "sha512-orX4IdpbFhdNO7bTBhSbahp1EBpqzBc+qrvTRVUFfZgA4zta7TdM6PN5ZxkEUgDnz36m+PfWGcdX7AVfFWItJw==", + "version": "1.0.30000939", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000939.tgz", + "integrity": "sha512-oXB23ImDJOgQpGjRv1tCtzAvJr4/OvrHi5SO2vUgB0g0xpdZZoA/BxfImiWfdwoYdUTtQrPsXsvYU/dmCSM8gg==", "dev": true }, "caseless": { @@ -3235,9 +3220,9 @@ "dev": true }, "chokidar": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.1.tgz", - "integrity": "sha512-gfw3p2oQV2wEt+8VuMlNsPjCxDxvvgnm/kz+uATu805mWVF8IJN7uz9DN7iBz+RMJISmiVbCOBFs9qBGMjtPfQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz", + "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -3302,17 +3287,6 @@ "restore-cursor": "^2.0.0" } }, - "cli-table3": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", - "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", - "dev": true, - "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - } - }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -3320,13 +3294,13 @@ "dev": true }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", "wrap-ansi": "^2.0.0" } }, @@ -3626,9 +3600,9 @@ } }, "core-js": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.4.tgz", - "integrity": "sha512-05qQ5hXShcqGkPZpXEFLIpxayZscVD2kuMBZewxiIPPEagukO4mqgPA9CWhUvFBJfy3ODdK2p9xyHh7FTU9/7A==" + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" }, "core-util-is": { "version": "1.0.2", @@ -3637,9 +3611,9 @@ "dev": true }, "coveralls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.2.tgz", - "integrity": "sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.3.tgz", + "integrity": "sha512-viNfeGlda2zJr8Gj1zqXpDMRjw9uM54p7wzZdvLRyOgnAfCe974Dq4veZkjJdxQXbmdppu6flEajFYseHYaUhg==", "dev": true, "requires": { "growl": "~> 1.10.0", @@ -3647,7 +3621,7 @@ "lcov-parse": "^0.0.10", "log-driver": "^1.2.7", "minimist": "^1.2.0", - "request": "^2.85.0" + "request": "^2.86.0" } }, "create-ecdh": { @@ -3688,14 +3662,12 @@ } }, "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "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": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", + "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", "which": "^1.2.9" } @@ -4180,67 +4152,11 @@ }, "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 - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, - "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.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "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.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "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.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -4250,35 +4166,11 @@ "locate-path": "^2.0.0" } }, - "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 - }, - "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 - }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "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 }, "load-json-file": { "version": "2.0.0", @@ -4310,26 +4202,6 @@ "path-exists": "^3.0.0" } }, - "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.0.0" - } - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -4391,20 +4263,24 @@ "path-type": "^2.0.0" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "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": { - "ansi-regex": "^2.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "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": { + "ansi-regex": "^3.0.0" + } }, "yargs": { "version": "9.0.1", @@ -4438,15 +4314,6 @@ } } } - }, - "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" - } } } }, @@ -4739,9 +4606,9 @@ } }, "es5-ext": { - "version": "0.10.47", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", - "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", + "version": "0.10.48", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.48.tgz", + "integrity": "sha512-CdRvPlX/24Mj5L4NVxTs4804sxiS2CjVprgCmrgoDkdmjdY4D+ySHa7K3jJf8R40dFg0tIm3z/dk326LrnuSGw==", "dev": true, "requires": { "es6-iterator": "~2.0.3", @@ -4781,9 +4648,9 @@ } }, "es6-promise": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", "dev": true }, "es6-promisify": { @@ -4937,16 +4804,11 @@ "text-table": "~0.2.0" }, "dependencies": { - "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.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true }, "debug": { "version": "3.2.6", @@ -4965,6 +4827,15 @@ "requires": { "esutils": "^2.0.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" + } } } }, @@ -5377,13 +5248,13 @@ } }, "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", @@ -5860,28 +5731,22 @@ } }, "follow-redirects": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", - "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, "requires": { - "debug": "=3.1.0" + "debug": "^3.2.6" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, @@ -6044,8 +5909,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6066,14 +5930,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6088,20 +5950,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6218,8 +6077,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6231,7 +6089,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6246,7 +6103,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6254,14 +6110,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6280,7 +6134,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6361,8 +6214,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6374,7 +6226,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6460,8 +6311,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -6497,7 +6347,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6517,7 +6366,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6561,14 +6409,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -6662,13 +6508,10 @@ "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" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true }, "get-uri": { "version": "2.0.3", @@ -6912,14 +6755,6 @@ "timed-out": "^4.0.1", "url-parse-lax": "^3.0.0", "url-to-options": "^1.0.1" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - } } }, "graceful-fs": { @@ -6946,29 +6781,12 @@ "vinyl-fs": "^3.0.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 - }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -7005,30 +6823,6 @@ "yargs": "^7.1.0" } }, - "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 - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -7107,30 +6901,10 @@ "read-pkg": "^1.0.0" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "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" @@ -7142,12 +6916,6 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yargs": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", @@ -7601,9 +7369,9 @@ } }, "gulp-sourcemaps": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.5.tgz", + "integrity": "sha512-SYLBRzPTew8T5Suh2U8jCSDKY+4NARua4aqjj8HOysBh2tSgT9u4jc1FYirAdPx1akUxxDeK++fqw6Jg0LkQRg==", "dev": true, "requires": { "@gulp-sourcemaps/identity-map": "1.X", @@ -7669,12 +7437,6 @@ "vinyl": "^0.5.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", @@ -7777,15 +7539,6 @@ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -7827,12 +7580,12 @@ }, "dependencies": { "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "source-map": { @@ -7860,9 +7613,9 @@ }, "dependencies": { "ajv": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", - "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz", + "integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -7901,14 +7654,6 @@ "dev": true, "requires": { "ansi-regex": "^2.0.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 - } } }, "has-binary2": { @@ -8069,9 +7814,9 @@ "dev": true }, "highlight.js": { - "version": "9.14.2", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.14.2.tgz", - "integrity": "sha512-Nc6YNECYpxyJABGYJAyw7dBAYbXEuIzwzkqoJnwbc1nIpCiN+3ioYf0XrBnLiyyG0JLuJhpPtt2iTSbXiKLoyA==", + "version": "9.15.6", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.6.tgz", + "integrity": "sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==", "dev": true }, "hmac-drbg": { @@ -8096,9 +7841,9 @@ } }, "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "requires": { "parse-passwd": "^1.0.0" @@ -8308,6 +8053,39 @@ "string-width": "^2.1.0", "strip-ansi": "^4.0.0", "through": "^2.3.6" + }, + "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" + } + } } }, "interpret": { @@ -8324,14 +8102,6 @@ "requires": { "from2": "^2.1.1", "p-is-promise": "^1.1.0" - }, - "dependencies": { - "p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true - } } }, "invariant": { @@ -8344,9 +8114,9 @@ } }, "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "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 }, "ip": { @@ -8528,10 +8298,13 @@ } }, "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 + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { "version": "4.0.0", @@ -8835,12 +8608,12 @@ }, "dependencies": { "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } } } @@ -8992,9 +8765,9 @@ "dev": true }, "js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.2.tgz", + "integrity": "sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -9257,6 +9030,23 @@ "chalk": "^2.1.0", "log-symbols": "^2.1.0", "strip-ansi": "^4.0.0" + }, + "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 + }, + "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" + } + } } }, "karma-opera-launcher": { @@ -9316,12 +9106,12 @@ }, "dependencies": { "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } } } @@ -9373,12 +9163,12 @@ } }, "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "^2.0.0" + "invert-kv": "^1.0.0" } }, "lcov-parse": { @@ -9963,15 +9753,6 @@ "kind-of": "^6.0.2" } }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -10093,14 +9874,26 @@ "dev": true }, "mdast-util-toc": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-3.0.1.tgz", - "integrity": "sha512-Z8lKq6sQr/vDNIcUkIWzPwKo5JQIzlDLouZuzIMVajOdUAyjnkA+s98RhjVpFt7SiuJzase9oh6Iw7n4zhVNDQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-3.1.0.tgz", + "integrity": "sha512-Za0hqL1PqWrvxGtA/3NH9D5nhGAUS9grMM4obEAz5+zsk1RIw/vWUchkaoDLNdrwk05A0CSC5eEXng36/1qE5w==", "dev": true, "requires": { - "github-slugger": "^1.1.1", - "mdast-util-to-string": "^1.0.2", + "github-slugger": "^1.2.1", + "mdast-util-to-string": "^1.0.5", + "unist-util-is": "^2.1.2", "unist-util-visit": "^1.1.0" + }, + "dependencies": { + "github-slugger": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.1.tgz", + "integrity": "sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ==", + "dev": true, + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + } + } } }, "mdurl": { @@ -10116,14 +9909,12 @@ "dev": true }, "mem": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", - "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^2.0.0" + "mimic-fn": "^1.0.0" } }, "memoizee": { @@ -10307,18 +10098,18 @@ "dev": true }, "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", "dev": true }, "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", "dev": true, "requires": { - "mime-db": "~1.37.0" + "mime-db": "~1.38.0" } }, "mimic-fn": { @@ -10656,12 +10447,6 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, "nightwatch": { "version": "1.0.19", "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.19.tgz", @@ -10682,16 +10467,16 @@ } }, "nise": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.8.tgz", - "integrity": "sha512-kGASVhuL4tlAV0tvA34yJYZIVihrUt/5bDwpp4tTluigxUr2bBlJeDXmivb6NuEdFkqvdv/Ybb9dm16PSKUhtw==", + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.10.tgz", + "integrity": "sha512-sa0RRbj53dovjc7wombHmVli9ZihXbXCQ2uH3TNm03DyvOSIQbxg+pbqDKrk2oxMK1rtLGVlKxcB9rrc6X5YjA==", "dev": true, "requires": { "@sinonjs/formatio": "^3.1.0", + "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", "lolex": "^2.3.2", - "path-to-regexp": "^1.7.0", - "text-encoding": "^0.6.4" + "path-to-regexp": "^1.7.0" }, "dependencies": { "@sinonjs/formatio": { @@ -10745,9 +10530,9 @@ } }, "node-releases": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.7.tgz", - "integrity": "sha512-bKdrwaqJUPHqlCzDD7so/R+Nk0jGv9a11ZhLrD9f6i947qGLrGAhU3OxRENa19QQmwzGy/g6zCDEuLGDO8HPvA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.8.tgz", + "integrity": "sha512-gQm+K9mGCiT/NXHy+V/ZZS1N/LOaGGqRAAJJs3X9Ah1g+CIbRcBgNyoNYQ+SEtcyAtB9KqDruu+fF7nWjsqRaA==", "dev": true, "requires": { "semver": "^5.3.0" @@ -11049,29 +10834,12 @@ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "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 }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -11082,30 +10850,6 @@ "pinkie-promise": "^2.0.0" } }, - "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 - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -11184,26 +10928,6 @@ "read-pkg": "^1.0.0" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -11219,12 +10943,6 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yargs": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", @@ -11295,14 +11013,14 @@ "dev": true }, "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "os-tmpdir": { @@ -11317,12 +11035,6 @@ "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", "dev": true }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -11330,9 +11042,9 @@ "dev": true }, "p-is-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", - "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", "dev": true }, "p-limit": { @@ -11451,9 +11163,9 @@ } }, "parse-asn1": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.3.tgz", - "integrity": "sha512-VrPoetlz7B/FqjBLD2f5wBVZvsZVLnRUrxVLfRYhGXCODa/NWE4p3Wp+6+aV3ZPL3KM7/OZmxDIwwijD7yuucg==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", "dev": true, "requires": { "asn1.js": "^4.0.0", @@ -11477,9 +11189,9 @@ } }, "parse-entities": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.0.tgz", - "integrity": "sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.1.tgz", + "integrity": "sha512-NBWYLQm1KSoDKk7GAHyioLTvCZ5QjdH/ASBBQTD3iLiAWJXS5bg1jEWI8nIJ+vgVvsceBVBcDGRWSo0KVQBvvg==", "dev": true, "requires": { "character-entities": "^1.0.0", @@ -11922,9 +11634,9 @@ } }, "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "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", @@ -11940,18 +11652,6 @@ "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" - }, - "dependencies": { - "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" - } - } } }, "punycode": { @@ -12026,9 +11726,9 @@ } }, "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" @@ -12200,9 +11900,9 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", - "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz", + "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", "dev": true, "requires": { "private": "^0.1.6" @@ -12228,37 +11928,10 @@ } }, "regexp-tree": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.1.tgz", - "integrity": "sha512-HwRjOquc9QOwKTgbxvZTcddS5mlNlwePMQ3NFL8broajMLD5CXDAqas8Y5yxJH5QtZp5iRor3YCILd5pz71Cgw==", - "dev": true, - "requires": { - "cli-table3": "^0.5.0", - "colors": "^1.1.2", - "yargs": "^12.0.5" - }, - "dependencies": { - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - } - } + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.5.tgz", + "integrity": "sha512-nUmxvfJyAODw+0B13hj8CFVAxhe7fDEAgJgaotBu3nnR+IgGgZq59YedJP5VYTlkEfqjuK6TuRpnymKdatLZfQ==", + "dev": true }, "regexpp": { "version": "1.1.0", @@ -12932,6 +12605,14 @@ "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "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 + } } }, "smart-buffer": { @@ -13496,13 +13177,14 @@ "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -13527,12 +13209,12 @@ } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "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": "^3.0.0" + "ansi-regex": "^2.0.0" } }, "strip-bom": { @@ -13608,6 +13290,39 @@ "lodash": "^4.17.4", "slice-ansi": "1.0.0", "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" + } + } } }, "tapable": { @@ -13628,12 +13343,6 @@ "through2": "^2.0.1" } }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "dev": true - }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14268,9 +13977,9 @@ } }, "unzipper": { - "version": "0.9.10", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.10.tgz", - "integrity": "sha512-dhxTaR67KGyrmxseXTmsyzdlRWkuN0rMPo9j6lxosR/PkzbHNd3smzMobaApx6o/oYvqU1uv+fAPoWr1P4bd8Q==", + "version": "0.9.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.11.tgz", + "integrity": "sha512-G0z5zv8LYv4/XwpOiXgTGTcN4jyxgyg3P1DfdIeCN2QGOd6ZBl49BSbOe9JsIEvKh3tG7/b0bdJvz+UmwA+BRg==", "dev": true, "requires": { "big-integer": "^1.6.17", @@ -14507,47 +14216,12 @@ "vfile-statistics": "^1.1.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 - }, "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.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -14717,9 +14391,9 @@ }, "dependencies": { "ajv": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", - "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz", + "integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -14735,74 +14409,18 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "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.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.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.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "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=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "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.0.1", - "get-stream": "^3.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" + "lodash": "^4.17.11" } }, "fast-deep-equal": { @@ -14820,32 +14438,17 @@ "locate-path": "^2.0.0" } }, - "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 }, - "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 - }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "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 }, "json-schema-traverse": { "version": "0.4.1", @@ -14859,15 +14462,6 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -14890,26 +14484,6 @@ "path-exists": "^3.0.0" } }, - "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.0.0" - } - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -14979,13 +14553,23 @@ "read-pkg": "^2.0.0" } }, + "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": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "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": "^2.0.0" + "ansi-regex": "^3.0.0" } }, "supports-color": { @@ -14997,12 +14581,6 @@ "has-flag": "^2.0.0" } }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -15023,15 +14601,6 @@ "y18n": "^3.2.1", "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" - } } } }, @@ -15699,43 +15268,6 @@ "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" - }, - "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 - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } } }, "wrappy": { @@ -15789,9 +15321,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, "yallist": { @@ -15807,13 +15339,12 @@ "dev": true }, "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "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": "^5.0.0", - "decamelize": "^1.2.0" + "camelcase": "^4.1.0" } }, "yeast": { diff --git a/package.json b/package.json index 6983a742bb8..212f81ad55e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.4.0-pre", + "version": "2.4.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From bc9faeb2c000e023285d4ac3a9522464a2ae123d Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 27 Feb 2019 14:55:31 -0500 Subject: [PATCH 1046/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 212f81ad55e..565a4c98ff1 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.4.0", + "version": "2.5.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d36d4584f7d1ce0dce559d8c1f948ad08cbba16e Mon Sep 17 00:00:00 2001 From: nkmt <45026101+strong-zero@users.noreply.github.com> Date: Fri, 1 Mar 2019 06:53:13 +0900 Subject: [PATCH 1047/1594] New bidder adapter for MicroAd (#3565) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Correct procudtion endpoint for prebid --- modules/microadBidAdapter.js | 151 ++++++++ modules/microadBidAdapter.md | 28 ++ test/spec/modules/microadBidAdapter_spec.js | 381 ++++++++++++++++++++ 3 files changed, 560 insertions(+) create mode 100644 modules/microadBidAdapter.js create mode 100644 modules/microadBidAdapter.md create mode 100644 test/spec/modules/microadBidAdapter_spec.js diff --git a/modules/microadBidAdapter.js b/modules/microadBidAdapter.js new file mode 100644 index 00000000000..d42e4053fda --- /dev/null +++ b/modules/microadBidAdapter.js @@ -0,0 +1,151 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'microad'; + +const ENDPOINT_URLS = { + 'production': '//s-rtb-pb.send.microad.jp/prebid', + 'test': 'https://rtbtest.send.microad.jp/prebid' +}; +export let ENVIRONMENT = 'production'; + +/* eslint-disable no-template-curly-in-string */ +const EXT_URL_STRING = '${COMPASS_EXT_URL}'; +const EXT_REF_STRING = '${COMPASS_EXT_REF}'; +const EXT_IFA_STRING = '${COMPASS_EXT_IFA}'; +const EXT_APPID_STRING = '${COMPASS_EXT_APPID}'; +const EXT_GEO_STRING = '${COMPASS_EXT_GEO}'; +/* eslint-enable no-template-curly-in-string */ + +const BANNER_CODE = 1; +const NATIVE_CODE = 2; +const VIDEO_CODE = 4; + +function createCBT() { + const randomValue = Math.floor(Math.random() * Math.pow(10, 18)).toString(16); + const date = new Date().getTime().toString(16); + return randomValue + date; +} + +function createBitSequenceFromMediaType(hi, code) { + return (hi ? -1 : 0) & code; +} + +function convertMediaTypes(bid) { + return createBitSequenceFromMediaType(bid.mediaTypes.banner, BANNER_CODE) | + createBitSequenceFromMediaType(bid.mediaTypes.native, NATIVE_CODE) | + createBitSequenceFromMediaType(bid.mediaTypes.video, VIDEO_CODE); +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + isBidRequestValid: function(bid) { + return !!(bid && bid.params && bid.params.spot && bid.mediaTypes && (bid.mediaTypes.banner || bid.mediaTypes.native || bid.mediaTypes.video)); + }, + buildRequests: function(validBidRequests, bidderRequest) { + const requests = []; + + validBidRequests.forEach(bid => { + const bidParams = bid.params; + const params = { + spot: bidParams.spot, + url: bidderRequest.refererInfo.canonicalUrl || window.location.href, + referrer: bidderRequest.refererInfo.referer, + bid_id: bid.bidId, + transaction_id: bid.transactionId, + media_types: convertMediaTypes(bid), + cbt: createCBT() + }; + + if (bidParams.url) { + params['url_macro'] = bidParams.url.replace(EXT_URL_STRING, ''); + } + + if (bidParams.referrer) { + params['referrer_macro'] = bidParams.referrer.replace(EXT_REF_STRING, ''); + } + + if (bidParams.ifa) { + params['ifa'] = bidParams.ifa.replace(EXT_IFA_STRING, ''); + } + + if (bidParams.appid) { + params['appid'] = bidParams.appid.replace(EXT_APPID_STRING, ''); + } + + if (bidParams.geo) { + const geo = bidParams.geo.replace(EXT_GEO_STRING, ''); + if (/^[0-9.\-]+,[0-9.\-]+$/.test(geo)) { + params['geo'] = geo; + } + } + + requests.push({ + method: 'GET', + url: ENDPOINT_URLS[ENVIRONMENT], + data: params, + options: { Accept: 'application/json' } + }); + }); + return requests; + }, + interpretResponse: function(serverResponse) { + const body = serverResponse.body; + const bidResponses = []; + + if (body.cpm && body.cpm > 0) { + const bidResponse = { + requestId: body.requestId, + cpm: body.cpm, + width: body.width, + height: body.height, + ad: body.ad, + ttl: body.ttl, + creativeId: body.creativeId, + netRevenue: body.netRevenue, + currency: body.currency, + }; + + if (body.dealId) { + bidResponse['dealId'] = body.dealId; + } + + bidResponses.push(bidResponse); + } + + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = []; + + if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { + return syncs; + } + + serverResponses.forEach(resp => { + const syncIframeUrls = resp.body.syncUrls.iframe; + const syncImageUrls = resp.body.syncUrls.image; + if (syncOptions.iframeEnabled && syncIframeUrls) { + syncIframeUrls.forEach(syncIframeUrl => { + syncs.push({ + type: 'iframe', + url: syncIframeUrl + }); + }); + } + if (syncOptions.pixelEnabled && syncImageUrls) { + syncImageUrls.forEach(syncImageUrl => { + syncs.push({ + type: 'image', + url: syncImageUrl + }); + }); + } + }); + + return syncs; + } +}; + +registerBidder(spec); diff --git a/modules/microadBidAdapter.md b/modules/microadBidAdapter.md new file mode 100644 index 00000000000..c805e5cf6fb --- /dev/null +++ b/modules/microadBidAdapter.md @@ -0,0 +1,28 @@ +# Overview + +Module Name: MicroAd SSP Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@microad.co.jp + +# Description + +Module that connects to MicroAd SSP demand sources. + +# Test Parameters + +```javascript + var adUnits = [ + code: '209e56872ae8b0442a60477ae0c58be9', + mediaTypes: { + banner: { + sizes: [[200, 200]] + } + }, + bids: [{ + bidder: 'microad', + params: { + spot: '209e56872ae8b0442a60477ae0c58be9' + } + }] + ]; +``` diff --git a/test/spec/modules/microadBidAdapter_spec.js b/test/spec/modules/microadBidAdapter_spec.js new file mode 100644 index 00000000000..a6d1aa1d266 --- /dev/null +++ b/test/spec/modules/microadBidAdapter_spec.js @@ -0,0 +1,381 @@ +import { expect } from 'chai'; +import { spec } from 'modules/microadBidAdapter'; +import * as utils from 'src/utils'; + +describe('microadBidAdapter', () => { + const bidRequestTemplate = { + bidder: 'microad', + mediaTypes: { + banner: {} + }, + params: { + spot: 'spot-code' + }, + bidId: 'bid-id', + transactionId: 'transaction-id' + }; + + describe('isBidRequestValid', () => { + it('should return true when required parameters are set', () => { + const validBids = [ + bidRequestTemplate, + Object.assign({}, bidRequestTemplate, { + mediaTypes: { + native: {} + } + }), + Object.assign({}, bidRequestTemplate, { + mediaTypes: { + video: {} + } + }) + ]; + validBids.forEach(validBid => { + expect(spec.isBidRequestValid(validBid)).to.equal(true); + }); + }); + + it('should return false when required parameters are not set', () => { + const bidWithoutParams = utils.deepClone(bidRequestTemplate); + delete bidWithoutParams.params; + const bidWithoutSpot = utils.deepClone(bidRequestTemplate); + delete bidWithoutSpot.params.spot; + const bidWithoutMediaTypes = utils.deepClone(bidRequestTemplate); + delete bidWithoutMediaTypes.mediaTypes; + + const invalidBids = [ + {}, + bidWithoutParams, + bidWithoutSpot, + bidWithoutMediaTypes, + Object.assign({}, bidRequestTemplate, { + mediaTypes: {} + }) + ]; + invalidBids.forEach(invalidBid => { + expect(spec.isBidRequestValid(invalidBid)).to.equal(false); + }); + }); + }); + + describe('buildRequests', () => { + const bidderRequest = { + refererInfo: { + canonicalUrl: 'http://example.com/to', + referer: 'http://example.com/from' + } + }; + const expectedResultTemplate = { + spot: 'spot-code', + url: 'http://example.com/to', + referrer: 'http://example.com/from', + bid_id: 'bid-id', + transaction_id: 'transaction-id', + media_types: 1 + }; + + it('should generate valid media_types', () => { + const bidRequests = [ + bidRequestTemplate, + Object.assign({}, bidRequestTemplate, { + mediaTypes: { + banner: {}, native: {} + } + }), + Object.assign({}, bidRequestTemplate, { + mediaTypes: { + banner: {}, native: {}, video: {} + } + }), + Object.assign({}, bidRequestTemplate, { + mediaTypes: { + native: {} + } + }), + Object.assign({}, bidRequestTemplate, { + mediaTypes: { + native: {}, video: {} + } + }), + Object.assign({}, bidRequestTemplate, { + mediaTypes: { + video: {} + } + }), + Object.assign({}, bidRequestTemplate, { + mediaTypes: { + banner: {}, video: {} + } + }) + ]; + + const results = bidRequests.map(bid => { + const requests = spec.buildRequests([bid], bidderRequest); + return requests[0].data.media_types; + }); + expect(results).to.deep.equal([ + 1, // BANNER + 3, // BANNER + NATIVE + 7, // BANNER + NATIVE + VIDEO + 2, // NATIVE + 6, // NATIVE + VIDEO + 4, // VIDEO + 5 // BANNER + VIDEO + ]); + }); + + it('should use window.location.href if there is no canonicalUrl', () => { + const bidderRequestWithoutCanonicalUrl = { + refererInfo: { + referer: 'http://example.com/from' + } + }; + const requests = spec.buildRequests([bidRequestTemplate], bidderRequestWithoutCanonicalUrl); + requests.forEach(request => { + expect(request.data).to.deep.equal( + Object.assign({}, expectedResultTemplate, { + cbt: request.data.cbt, + url: window.location.href + }) + ); + }); + }); + + it('should generate valid request with no optional parameters', () => { + const requests = spec.buildRequests([bidRequestTemplate], bidderRequest); + requests.forEach(request => { + expect(request.data).to.deep.equal( + Object.assign({}, expectedResultTemplate, { + cbt: request.data.cbt + }) + ); + }); + }); + + it('should add url_macro parameter to response if request parameters contain url', () => { + const bidRequestWithUrl = Object.assign({}, bidRequestTemplate, { + params: { + spot: 'spot-code', + url: '${COMPASS_EXT_URL}url-macro' + } + }); + const requests = spec.buildRequests([bidRequestWithUrl], bidderRequest); + requests.forEach(request => { + expect(request.data).to.deep.equal( + Object.assign({}, expectedResultTemplate, { + cbt: request.data.cbt, + url_macro: 'url-macro' + }) + ); + }); + }); + + it('should add referrer_macro parameter to response if request parameters contain referrer', () => { + const bidRequestWithReferrer = Object.assign({}, bidRequestTemplate, { + params: { + spot: 'spot-code', + referrer: '${COMPASS_EXT_REF}referrer-macro' + } + }); + const requests = spec.buildRequests([bidRequestWithReferrer], bidderRequest); + requests.forEach(request => { + expect(request.data).to.deep.equal( + Object.assign({}, expectedResultTemplate, { + cbt: request.data.cbt, + referrer_macro: 'referrer-macro' + }) + ); + }); + }); + + it('should add ifa parameter to response if request parameters contain ifa', () => { + const bidRequestWithIfa = Object.assign({}, bidRequestTemplate, { + params: { + spot: 'spot-code', + ifa: '${COMPASS_EXT_IFA}ifa' + } + }); + const requests = spec.buildRequests([bidRequestWithIfa], bidderRequest); + requests.forEach(request => { + expect(request.data).to.deep.equal( + Object.assign({}, expectedResultTemplate, { + cbt: request.data.cbt, + ifa: 'ifa' + }) + ); + }); + }); + + it('should add appid parameter to response if request parameters contain appid', () => { + const bidRequestWithAppid = Object.assign({}, bidRequestTemplate, { + params: { + spot: 'spot-code', + appid: '${COMPASS_EXT_APPID}appid' + } + }); + const requests = spec.buildRequests([bidRequestWithAppid], bidderRequest); + requests.forEach(request => { + expect(request.data).to.deep.equal( + Object.assign({}, expectedResultTemplate, { + cbt: request.data.cbt, + appid: 'appid' + }) + ); + }); + }); + + it('should add geo parameter to response if request parameters contain geo', () => { + const bidRequestWithGeo = Object.assign({}, bidRequestTemplate, { + params: { + spot: 'spot-code', + geo: '${COMPASS_EXT_GEO}35.655275,139.693771' + } + }); + const requests = spec.buildRequests([bidRequestWithGeo], bidderRequest); + requests.forEach(request => { + expect(request.data).to.deep.equal( + Object.assign({}, expectedResultTemplate, { + cbt: request.data.cbt, + geo: '35.655275,139.693771' + }) + ); + }); + }); + + it('should not add geo parameter to response if request parameters contain invalid geo', () => { + const bidRequestWithGeo = Object.assign({}, bidRequestTemplate, { + params: { + spot: 'spot-code', + geo: '${COMPASS_EXT_GEO}invalid format geo' + } + }); + const requests = spec.buildRequests([bidRequestWithGeo], bidderRequest); + requests.forEach(request => { + expect(request.data).to.deep.equal( + Object.assign({}, expectedResultTemplate, { + cbt: request.data.cbt + }) + ); + }); + }); + }); + + describe('interpretResponse', () => { + const serverResponseTemplate = { + body: { + requestId: 'request-id', + cpm: 0.1, + width: 200, + height: 100, + ad: '
test
', + ttl: 10, + creativeId: 'creative-id', + netRevenue: true, + currency: 'JPY' + } + }; + const expectedBidResponseTemplate = { + requestId: 'request-id', + cpm: 0.1, + width: 200, + height: 100, + ad: '
test
', + ttl: 10, + creativeId: 'creative-id', + netRevenue: true, + currency: 'JPY' + }; + + it('should return nothing if server response body does not contain cpm', () => { + const emptyResponse = { + body: {} + }; + + expect(spec.interpretResponse(emptyResponse)).to.deep.equal([]); + }); + + it('should return nothing if returned cpm is zero', () => { + const serverResponse = { + body: { + cpm: 0 + } + }; + + expect(spec.interpretResponse(serverResponse)).to.deep.equal([]); + }); + + it('should return a valid bidResponse without deal id if serverResponse is valid, has a nonzero cpm and no deal id', () => { + expect(spec.interpretResponse(serverResponseTemplate)).to.deep.equal([expectedBidResponseTemplate]); + }); + + it('should return a valid bidResponse with deal id if serverResponse is valid, has a nonzero cpm and a deal id', () => { + const serverResponseWithDealId = Object.assign({}, utils.deepClone(serverResponseTemplate)); + serverResponseWithDealId.body['dealId'] = 10001; + const expectedBidResponse = Object.assign({}, expectedBidResponseTemplate, { + dealId: 10001 + }); + + expect(spec.interpretResponse(serverResponseWithDealId)).to.deep.equal([expectedBidResponse]); + }); + }); + + describe('getUserSyncs', () => { + const BOTH_ENABLED = { + iframeEnabled: true, pixelEnabled: true + }; + const IFRAME_ENABLED = { + iframeEnabled: true, pixelEnabled: false + }; + const PIXEL_ENABLED = { + iframeEnabled: false, pixelEnabled: true + }; + const BOTH_DISABLED = { + iframeEnabled: false, pixelEnabled: false + }; + const serverResponseTemplate = { + body: { + syncUrls: { + iframe: ['https://www.exmaple.com/iframe1', 'https://www.exmaple.com/iframe2'], + image: ['https://www.exmaple.com/image1', 'https://www.exmaple.com/image2'] + } + } + }; + const expectedIframeSyncs = [ + {type: 'iframe', url: 'https://www.exmaple.com/iframe1'}, + {type: 'iframe', url: 'https://www.exmaple.com/iframe2'} + ]; + const expectedImageSyncs = [ + {type: 'image', url: 'https://www.exmaple.com/image1'}, + {type: 'image', url: 'https://www.exmaple.com/image2'} + ]; + + it('should return nothing if no sync urls are set', () => { + const serverResponse = utils.deepClone(serverResponseTemplate); + serverResponse.body.syncUrls.iframe = []; + serverResponse.body.syncUrls.image = []; + + const syncs = spec.getUserSyncs(BOTH_ENABLED, [serverResponse]); + expect(syncs).to.deep.equal([]); + }); + + it('should return nothing if sync is disabled', () => { + const syncs = spec.getUserSyncs(BOTH_DISABLED, [serverResponseTemplate]); + expect(syncs).to.deep.equal([]); + }); + + it('should register iframe and image sync urls if sync is enabled', () => { + const syncs = spec.getUserSyncs(BOTH_ENABLED, [serverResponseTemplate]); + expect(syncs).to.deep.equal(expectedIframeSyncs.concat(expectedImageSyncs)); + }); + + it('should register iframe sync urls if iframe is enabled', () => { + const syncs = spec.getUserSyncs(IFRAME_ENABLED, [serverResponseTemplate]); + expect(syncs).to.deep.equal(expectedIframeSyncs); + }); + + it('should register image sync urls if image is enabled', () => { + const syncs = spec.getUserSyncs(PIXEL_ENABLED, [serverResponseTemplate]); + expect(syncs).to.deep.equal(expectedImageSyncs); + }); + }); +}); From 51129505007d75d55f0d29b3511556a4aa5e6ef3 Mon Sep 17 00:00:00 2001 From: "Evgen A. Epanchin" Date: Fri, 1 Mar 2019 16:29:48 +0200 Subject: [PATCH 1048/1594] Added LoopMe Adapter (#3586) * Added LoopMe Adapter * Replace Object.entries with entries --- modules/loopmeBidAdapter.js | 99 ++++++++++++++++++++ modules/loopmeBidAdapter.md | 29 ++++++ test/spec/modules/loopmeBidAdapter_spec.js | 101 +++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 modules/loopmeBidAdapter.js create mode 100644 modules/loopmeBidAdapter.md create mode 100644 test/spec/modules/loopmeBidAdapter_spec.js diff --git a/modules/loopmeBidAdapter.js b/modules/loopmeBidAdapter.js new file mode 100644 index 00000000000..fb2f891d3b0 --- /dev/null +++ b/modules/loopmeBidAdapter.js @@ -0,0 +1,99 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const LOOPME_ENDPOINT = 'https://loopme.me/api/hb'; + +const entries = (obj) => { + let output = []; + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + output.push([key, obj[key]]) + } + } + return output; +} + +export const spec = { + code: 'loopme', + supportedMediaTypes: [BANNER], + /** + * @param {object} bid + * @return boolean + */ + isBidRequestValid: function(bid) { + if (typeof bid.params !== 'object') { + return false; + } + + return !!bid.params.ak; + }, + /** + * @param {BidRequest[]} bidRequests + * @param bidderRequest + * @return ServerRequest[] + */ + buildRequests: function(bidRequests, bidderRequest) { + return bidRequests.map(bidRequest => { + bidRequest.startTime = new Date().getTime(); + let payload = bidRequest.params; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.user_consent = bidderRequest.gdprConsent.consentString; + } + + let queryString = entries(payload) + .map(item => `${item[0]}=${encodeURI(item[1])}`) + .join('&'); + + const sizes = + '&sizes=' + + utils + .getAdUnitSizes(bidRequest) + .map(size => `${size[0]}x${size[1]}`) + .join('&sizes='); + + queryString = `${queryString}${sizes}`; + + return { + method: 'GET', + url: `${LOOPME_ENDPOINT}`, + options: { withCredentials: false }, + bidId: bidRequest.bidId, + data: queryString + }; + }); + }, + /** + * @param {*} responseObj + * @param {BidRequest} bidRequest + * @return {Bid[]} An array of bids which + */ + interpretResponse: function(response = {}, bidRequest) { + const responseObj = response.body; + + if ( + responseObj == null || + typeof responseObj !== 'object' || + !responseObj.hasOwnProperty('ad') + ) { + return []; + } + + return [ + { + requestId: bidRequest.bidId, + cpm: responseObj.cpm, + width: responseObj.width, + height: responseObj.height, + ad: responseObj.ad, + ttl: responseObj.ttl, + currency: responseObj.currency, + creativeId: responseObj.creativeId, + dealId: responseObj.dealId, + netRevenue: responseObj.netRevenue + } + ]; + } +}; +registerBidder(spec); diff --git a/modules/loopmeBidAdapter.md b/modules/loopmeBidAdapter.md new file mode 100644 index 00000000000..be8c20cfade --- /dev/null +++ b/modules/loopmeBidAdapter.md @@ -0,0 +1,29 @@ +# Overview + +``` +Module Name: LoopMe Bid Adapter +Module Type: Bidder Adapter +Maintainer: support@loopme.com +``` + +# Description + +Connect to LoopMe's exchange for bids. + +# Test Parameters +``` +var adUnits = [{ + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + }, + bids: [{ + bidder: 'loopme', + params: { + ak: 'cc885e3acc' + } + }] +}]; +``` diff --git a/test/spec/modules/loopmeBidAdapter_spec.js b/test/spec/modules/loopmeBidAdapter_spec.js new file mode 100644 index 00000000000..6d612746299 --- /dev/null +++ b/test/spec/modules/loopmeBidAdapter_spec.js @@ -0,0 +1,101 @@ +import { expect } from 'chai'; +import { spec } from '../../../modules/loopmeBidAdapter'; +import * as utils from 'src/utils'; + +describe('LoopMeAdapter', function () { + const bidRequests = [{ + bidder: 'loopme', + params: { + ak: 'b510d5bcda' + }, + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + adUnitCode: 'ad-1', + bidId: '2652ca954bce9' + }]; + + describe('isBidRequestValid', function () { + it('should return true if the ak parameter is present', function () { + expect(spec.isBidRequestValid(bidRequests[0])).to.be.true; + }); + + it('should return false if the ak parameter is not present', function () { + let bidRequest = utils.deepClone(bidRequests[0]); + delete bidRequest.params.ak; + expect(spec.isBidRequestValid(bidRequest)).to.be.false; + }); + + it('should return false if the params object is not present', function () { + let bidRequest = utils.deepClone(bidRequests); + delete bidRequest[0].params; + expect(spec.isBidRequestValid(bidRequest)).to.be.false; + }); + }); + + describe('buildRequests', function () { + it('should generate a valid single GET request for multiple bid requests', function () { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.method).to.equal('GET'); + expect(request.url).to.equal('https://loopme.me/api/hb'); + expect(request.bidId).to.equal('2652ca954bce9'); + expect(request.data).to.exist; + + const requestData = request.data; + expect(requestData).to.contain('ak=b510d5bcda'); + expect(requestData).to.contain('sizes=300x250'); + }); + + it('should add GDPR data to request if available', function () { + const bidderRequest = { + gdprConsent: { + consentString: 'AAABBB' + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + const requestData = request.data; + + expect(requestData).to.contain('user_consent=AAABBB'); + }); + }); + + describe('interpretResponse', function () { + it('should return an empty array if an invalid response is passed', function () { + const interpretedResponse = spec.interpretResponse({}); + expect(interpretedResponse).to.be.an('array').that.is.empty; + }); + + it('should return valid response when passed valid server response', function () { + const serverResponse = { + body: { + 'requestId': '2652ca954bce9', + 'cpm': 1, + 'width': 480, + 'height': 320, + 'creativeId': '20154', + 'currency': 'USD', + 'netRevenue': false, + 'ttl': 360, + 'ad': `
Hello
` + } + }; + + const request = spec.buildRequests(bidRequests)[0]; + const interpretedResponse = spec.interpretResponse(serverResponse, request); + + expect(interpretedResponse).to.have.lengthOf(1); + + expect(interpretedResponse[0].requestId).to.equal(serverResponse.body.requestId); + expect(interpretedResponse[0].cpm).to.equal(serverResponse.body.cpm); + expect(interpretedResponse[0].width).to.equal(serverResponse.body.width); + expect(interpretedResponse[0].height).to.equal(serverResponse.body.height); + expect(interpretedResponse[0].creativeId).to.equal(serverResponse.body.creativeId); + expect(interpretedResponse[0].currency).to.equal(serverResponse.body.currency); + expect(interpretedResponse[0].netRevenue).to.equal(serverResponse.body.netRevenue); + expect(interpretedResponse[0].ad).to.equal(serverResponse.body.ad); + expect(interpretedResponse[0].ttl).to.equal(serverResponse.body.ttl); + }); + }); +}); From dd26503f8c9afd6bb0df6340b088ffce8da4ee10 Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Fri, 1 Mar 2019 11:47:08 -0800 Subject: [PATCH 1049/1594] Fix event firing on native click (#3589) --- src/native.js | 1 + src/secureCreatives.js | 4 +++- test/spec/native_spec.js | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/native.js b/src/native.js index f30df7e3ef7..8ebe4c8eca6 100644 --- a/src/native.js +++ b/src/native.js @@ -144,6 +144,7 @@ export function fireNativeTrackers(message, adObject) { } (trackers || []).forEach(triggerPixel); + return message.action; } /** diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 3b5f6128ee9..8505923c493 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -52,7 +52,9 @@ function receiveMessage(ev) { return; } - fireNativeTrackers(data, adObject); + const trackerType = fireNativeTrackers(data, adObject); + if (trackerType === 'click') { return; } + auctionManager.addWinningBid(adObject); events.emit(BID_WON, adObject); } diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index d68d6c21958..ed21b5f681b 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -85,7 +85,8 @@ describe('native.js', function () { }); it('fires click trackers', function () { - fireNativeTrackers({ action: 'click' }, bid); + const trackerType = fireNativeTrackers({ action: 'click' }, bid); + expect(trackerType).to.equal('click'); sinon.assert.calledOnce(triggerPixelStub); sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]); }); From aa6afa87c5f7f71d644653166e3563021393c1a5 Mon Sep 17 00:00:00 2001 From: Eric Nolte Date: Mon, 4 Mar 2019 10:19:10 -0500 Subject: [PATCH 1050/1594] Return mediaType:video in unruly adapter (#3591) --- modules/unrulyBidAdapter.js | 3 ++- test/spec/modules/unrulyBidAdapter_spec.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js index 8fb7e1913b3..5647d2cd6a3 100644 --- a/modules/unrulyBidAdapter.js +++ b/modules/unrulyBidAdapter.js @@ -29,7 +29,8 @@ const serverResponseToBid = (bid, rendererInstance) => ({ creativeId: bid.bidId, ttl: 360, currency: 'USD', - renderer: rendererInstance + renderer: rendererInstance, + mediaType: VIDEO }); const buildPrebidResponseAndInstallRenderer = bids => diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js index b27fdc5c78b..e39f9a8e996 100644 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -146,7 +146,8 @@ describe('UnrulyAdapter', function () { creativeId: 'mockBidId', ttl: 360, currency: 'USD', - renderer: fakeRenderer + renderer: fakeRenderer, + mediaType: 'video' } ]) }); From 0db21ffae97f49606e373810351d3f804f8d44b7 Mon Sep 17 00:00:00 2001 From: trchandraprakash <47793448+trchandraprakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 10:26:52 -0800 Subject: [PATCH 1051/1594] Submit Advangelists Prebid Adapter (#3588) * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Submit Advangelists Prebid Adapter Changes --- modules/advangelistsBidAdapter.js | 379 ++++++++++++++++++ modules/advangelistsBidAdapter.md | 65 +++ .../modules/advangelistsBidAdapter_spec.js | 137 +++++++ 3 files changed, 581 insertions(+) create mode 100644 modules/advangelistsBidAdapter.js create mode 100644 modules/advangelistsBidAdapter.md create mode 100644 test/spec/modules/advangelistsBidAdapter_spec.js diff --git a/modules/advangelistsBidAdapter.js b/modules/advangelistsBidAdapter.js new file mode 100644 index 00000000000..926be211649 --- /dev/null +++ b/modules/advangelistsBidAdapter.js @@ -0,0 +1,379 @@ +import * as utils from '../src/utils'; +import { parse as parseUrl } from '../src/url'; +import { config } from '../src/config'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { VIDEO, BANNER } from '../src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; + +const ADAPTER_VERSION = '1.0'; +const BIDDER_CODE = 'avng'; + +export const VIDEO_ENDPOINT = '//nep.advangelists.com/xp/get?pubid=';// 0cf8d6d643e13d86a5b6374148a4afac'; +export const BANNER_ENDPOINT = '//nep.advangelists.com/xp/get?pubid=';// 0cf8d6d643e13d86a5b6374148a4afac'; +export const OUTSTREAM_SRC = '//player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; +export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration', 'skip']; +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 && utils.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, + 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, + mediaType: BANNER, + netRevenue: true + } + } + } + } +}; + +function isBannerBid(bid) { + return utils.deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid); +} + +function isVideoBid(bid) { + return utils.deepAccess(bid, 'mediaTypes.video'); +} + +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 utils.deepAccess(bid, 'params.video.' + key) || utils.deepAccess(bid, 'params.' + key); +} + +function getBannerBidParam(bid, key) { + return utils.deepAccess(bid, 'params.banner.' + key) || utils.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 utils.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(utils.deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes); +} + +function getBannerSizes(bid) { + return parseSizes(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes); +} + +function getTopWindowReferrer() { + try { + return window.top.document.referrer; + } catch (e) { + return ''; + } +} + +function getVideoTargetingParams(bid) { + return Object.keys(Object(bid.params.video)) + .filter(param => includes(VIDEO_TARGETING, param)) + .reduce((obj, param) => { + obj[ param ] = bid.params.video[ param ]; + return obj; + }, {}); +} + +function createVideoRequestData(bid, bidderRequest) { + let topLocation = getTopWindowLocation(bidderRequest); + let topReferrer = getTopWindowReferrer(); + + let sizes = getVideoSizes(bid); + let firstSize = getFirstSize(sizes); + + 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': 2.0, + 'bidfloorcur': 'USD', + 'secure': secure, + 'video': Object.assign({ + 'id': utils.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); + + 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': 2.0, + 'bidfloorcur': 'USD', + 'secure': secure, + 'banner': { + 'id': utils.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 new file mode 100644 index 00000000000..14e2befd48f --- /dev/null +++ b/modules/advangelistsBidAdapter.md @@ -0,0 +1,65 @@ +# Overview + +``` +Module Name: Advangelists Bidder Adapter +Module Type: Bidder Adapter +Maintainer: lokesh@advangelists.com +``` + +# Description + +Connects to Advangelists exchange for bids. + +Advangelists bid adapter supports Banner and Video ads currently. + +For more informatio + +# Sample Display Ad Unit: For Publishers +```javascript +var displayAdUnit = [ +{ + code: 'display', + sizes: [ + [300, 250], + [320, 50] + ], + bids: [{ + bidder: 'avng', + params: { + pubid: '0cf8d6d643e13d86a5b6374148a4afac', + placement: 1234 + } + }] +}]; +``` + +# Sample Video Ad Unit: For Publishers +```javascript + +var videoAdUnit = { + code: 'video', + sizes: [320,480], + mediaTypes: { + video: { + playerSize : [[320, 480]], + context: 'instream' + } + }, + bids: [ + { + bidder: 'avng', + params: { + pubid: '8537f00948fc37cc03c5f0f88e198a76', + placement: 1234, + video: { + id: 123, + skip: 1, + mimes : ['video/mp4', 'application/javascript'], + playbackmethod : [2,6], + maxduration: 30 + } + } + } + ] + }; +``` \ No newline at end of file diff --git a/test/spec/modules/advangelistsBidAdapter_spec.js b/test/spec/modules/advangelistsBidAdapter_spec.js new file mode 100644 index 00000000000..f7a49ef995f --- /dev/null +++ b/test/spec/modules/advangelistsBidAdapter_spec.js @@ -0,0 +1,137 @@ +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': 'avng', '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': 'avng', 'params': {'pubid': '8537f00948fc37cc03c5f0f88e198a76', 'placement': 1234, 'video': {'id': 123, 'skip': 1, 'mimes': ['video/mp4', 'application/javascript'], 'playbackmethod': [2, 6], 'maxduration': 30}}, 'crumbs': {'pubcid': '979fde13-c71e-4ac2-98b7-28c90f99b449'}, 'mediaTypes': {'video': {'playerSize': [[320, 480]], 'context': 'instream'}}, '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 avngbidreqVid = {'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.ar'], '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 }, avngbidreqVid); + delete bidResponseVid['vastUrl']; + delete bidResponseVid['ad']; + expect(bidResponseVid).to.deep.equal({ + requestId: bidRequestsVid[0].bidId, + bidderCode: 'avng', + 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', + currency: 'USD', + netRevenue: true, + ttl: 60 + }); + }); + + it('should return valid banner bid responses', function () { + const avngbidreq = {bids: {}}; + bidRequests.forEach(bid => { + let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); + avngbidreq.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': '
', 'adomain': ['advertiserdomain.com'], 'iurl': '', 'cid': 'campaign1', 'crid': 'abcde-12345', 'w': 300, 'h': 250}], 'seat': '19513bcfca8006'}], 'bidid': '19513bcfca8006', 'cur': 'USD', 'w': 300, 'h': 250}; + + const bidResponse = spec.interpretResponse({ body: serverResponse }, avngbidreq); + expect(bidResponse).to.deep.equal({ + requestId: bidRequests[0].bidId, + ad: serverResponse.seatbid[0].bid[0].adm, + bidderCode: 'avng', + 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', + currency: 'USD', + netRevenue: true, + ttl: 60 + }); + }); + }); + }); +}); From 6bc6394d865dd4c35bdb69cdb502f9eadd787d8b Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 4 Mar 2019 15:05:12 -0500 Subject: [PATCH 1052/1594] fix two issues related to hb_uuid and hb_cache_id targeting keys (#3605) * move logic that assigns bid targeting params * switch order of targeting keys assignment in dfpAdServerVideo * remove redundant cache key assignment in dfp module and update unit tests * refactor logic when adding cache targeting keys * fix issue caused by refactor from another PR --- modules/dfpAdServerVideo.js | 3 -- src/auction.js | 23 +++++++++++---- test/spec/modules/dfpAdServerVideo_spec.js | 33 ++++++++++++---------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 1b5f8509559..17a8f0f1144 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -160,9 +160,6 @@ function getCustParams(bid, options) { let customParams = Object.assign({}, allTargetingData, adserverTargeting, - { hb_uuid: bid && bid.videoCacheKey }, - // hb_uuid will be deprecated and replaced by hb_cache_id - { hb_cache_id: bid && bid.videoCacheKey }, optCustParams, ); return encodeURIComponent(formatQS(customParams)); diff --git a/src/auction.js b/src/auction.js index 96c59f43eef..0ddb2450561 100644 --- a/src/auction.js +++ b/src/auction.js @@ -386,6 +386,10 @@ export function doCallbacksIfTimedout(auctionInstance, bidResponse) { // Add a bid to the auction. export function addBidToAuction(auctionInstance, 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); @@ -429,6 +433,7 @@ export const callPrebidCache = hook('async', function(auctionInstance, bidRespon doCallbacksIfTimedout(auctionInstance, bidResponse); } else { bidResponse.videoCacheKey = cacheIds[0].uuid; + if (!bidResponse.vastUrl) { bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); } @@ -485,16 +490,24 @@ function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) { bidObject.pbDg = priceStringsObj.dense; bidObject.pbCg = priceStringsObj.custom; - // if there is any key value pairs to map do here - var keyValues; + return bidObject; +} + +function setupBidTargeting(bidObject, bidderRequest) { + let keyValues; 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 - bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); + let cacheTargetKeys = {}; + if (bidObject.videoCacheKey) { + cacheTargetKeys.hb_uuid = bidObject.videoCacheKey; + cacheTargetKeys.hb_cache_id = bidObject.videoCacheKey; + } - return bidObject; + // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs + bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, cacheTargetKeys, keyValues); } export function getStandardBidderSettings(mediaType) { diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 8afc597d3b4..ab988ec0fe3 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -10,7 +10,10 @@ import { targeting } from 'src/targeting'; const bid = { videoCacheKey: 'abc', - adserverTargeting: { }, + adserverTargeting: { + hb_uuid: 'abc', + hb_cache_id: 'abc', + }, }; describe('The DFP video support module', function () { @@ -40,7 +43,7 @@ describe('The DFP video support module', function () { }); it('can take an adserver url as a parameter', function () { - const bidCopy = Object.assign({ }, bid); + const bidCopy = utils.deepClone(bid); bidCopy.vastUrl = 'vastUrl.example'; const url = parse(buildDfpVideoUrl({ @@ -90,10 +93,10 @@ describe('The DFP video support module', function () { }); it('should include the cache key and adserver targeting in cust_params', function () { - const bidCopy = Object.assign({ }, bid); - bidCopy.adserverTargeting = { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { hb_adid: 'ad_id', - }; + }); const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -160,10 +163,10 @@ describe('The DFP video support module', function () { } }); - const bidCopy = Object.assign({ }, bid); - bidCopy.adserverTargeting = { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { hb_adid: 'ad_id', - }; + }); const url = parse(buildDfpVideoUrl({ adUnit: adUnitsCopy, @@ -184,10 +187,10 @@ describe('The DFP video support module', function () { }); it('should merge the user-provided cust_params with the default ones', function () { - const bidCopy = Object.assign({ }, bid); - bidCopy.adserverTargeting = { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { hb_adid: 'ad_id', - }; + }); const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -207,10 +210,10 @@ describe('The DFP video support module', function () { }); it('should merge the user-provided cust-params with the default ones when using url object', function () { - const bidCopy = Object.assign({ }, bid); - bidCopy.adserverTargeting = { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { hb_adid: 'ad_id', - }; + }); const url = parse(buildDfpVideoUrl({ adUnit: adUnit, @@ -229,7 +232,7 @@ describe('The DFP video support module', function () { }); it('should not overwrite an existing description_url for object input and cache disabled', function () { - const bidCopy = Object.assign({}, bid); + const bidCopy = utils.deepClone(bid); bidCopy.vastUrl = 'vastUrl.example'; const url = parse(buildDfpVideoUrl({ From 01e68e1de877293232a2d4fcf4bc480f3f73aec0 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Mon, 4 Mar 2019 20:41:39 -0800 Subject: [PATCH 1053/1594] Rubicon Adapter: Switching Video Endpoint to Rubicon PBS (#3610) * updates to both the rubicon adapter and the prebid server for ORTB requirements * updates to bid and auction data to reflect oRTB structure * merged pbjs commits * reverted karma conf * always add ext.prebid.targeting.includewinners: true for openrtb * add unit test for ext.prebid.targeting.includewinners for openrtb * added s2sConfig 'video.ext.prebid' support and unit test * added code comments for changes to ORTB * handle response.ext.prebid.cache values and added unit test * update to merged video.ext.prebid with request.ext.prebid * update to merge includewinners * added test for override used in s2sConfig for ext.prebid.targeting.includewinners value * fixes for response cache logic * added support for targeting cache props HB-3740 * added test for adserverTargeting change * updates to address Jira ticket revision * update to build the vastUrl object by utilizing hb_cache_host + hb_cache_path, since the hb_cache_hostpath will be suppressed soon * removed single quotes around object literal keys to match formatting * Splitting into a new branch * Enforce new required params + remove legacy mediaType support * Fixing per Eric's request * Revert "Merge branch 'HB-3018_pbs-adapter-enhancements' of https://github.com/rubicon-project/Prebid.js into Rubicon_PBS_Video" This reverts commit 712e5669fe685dabf453330d12e74510836059c4, reversing changes made to 4f59e483150b8b0c1627c89503612af278f5d28c. --- modules/rubiconBidAdapter.js | 355 +++++++++--- test/spec/modules/rubiconBidAdapter_spec.js | 572 +++++++------------- 2 files changed, 483 insertions(+), 444 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index b076df68474..c5fb4486d20 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -11,11 +11,9 @@ function isSecure() { // use protocol relative urls for http or https export const FASTLANE_ENDPOINT = '//fastlane.rubiconproject.com/a/api/fastlane.json'; -export const VIDEO_ENDPOINT = '//fastlane-adv.rubiconproject.com/v1/auction/video'; +export const VIDEO_ENDPOINT = '//prebid-server.rubiconproject.com/openrtb2/auction'; export const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html'; -const TIMEOUT_BUFFER = 500; - var sizeMap = { 1: '468x60', 2: '728x90', @@ -87,7 +85,6 @@ utils._each(sizeMap, (item, key) => sizeMap[item] = key); export const spec = { code: 'rubicon', - aliases: ['rubiconLite'], supportedMediaTypes: [BANNER, VIDEO], /** * @param {object} bid @@ -97,15 +94,28 @@ export const spec = { if (typeof bid.params !== 'object') { return false; } - if (!/^\d+$/.test(bid.params.accountId)) { + // validate account, site, zone have numeric values + 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]])) { + utils.logError('Rubicon bid adapter Error: wrong format of accountId or siteId or zoneId.') + return false + } + } + let bidFormat = bidType(bid, true); + // bidType is undefined? Return false + if (!bidFormat) { return false; + } else if (bidFormat === 'video') { // bidType is video, make sure it has required params + return hasValidVideoParams(bid); } - return !!bidType(bid, true); + // bidType is banner? return true + return true; }, /** * @param {BidRequest[]} bidRequests * @param bidderRequest - * @return ServerRequest[] + * @return BidRequest[] */ buildRequests: function (bidRequests, bidderRequest) { // separate video bids because the requests are structured differently @@ -113,66 +123,82 @@ export const spec = { const videoRequests = bidRequests.filter(bidRequest => bidType(bidRequest) === 'video').map(bidRequest => { bidRequest.startTime = new Date().getTime(); - let params = bidRequest.params; - let size = parseSizes(bidRequest, 'video'); - - let data = { - page_url: _getPageUrl(bidRequest, bidderRequest), - resolution: _getScreenResolution(), - account_id: params.accountId, - integration: INTEGRATION, - 'x_source.tid': bidRequest.transactionId, - timeout: bidderRequest.timeout - (Date.now() - bidderRequest.auctionStart + TIMEOUT_BUFFER), - stash_creatives: true, - slots: [] - }; - - // Define the slot object - let slotData = { - site_id: params.siteId, - zone_id: params.zoneId, - position: params.position === 'atf' || params.position === 'btf' ? params.position : 'unknown', - floor: parseFloat(params.floor) > 0.01 ? params.floor : 0.01, - element_id: bidRequest.adUnitCode, - name: bidRequest.adUnitCode, - width: size[0], - height: size[1], - size_id: determineRubiconVideoSizeId(bidRequest) - }; - - if (params.video) { - data.ae_pass_through_parameters = params.video.aeParams; - slotData.language = params.video.language; - } - - // Add visitor and inventory FPD values - // Frank expects the vales in each inventory and visitor fpd to be an array. so params.inventory.something === [] of some sort, otherwise it 400s - ['inventory', 'visitor'].forEach(function(key) { - if (params[key] && typeof params[key] === 'object') { - slotData[key] = {}; - Object.keys(params[key]).forEach(function(fpdKey) { - let value = params[key][fpdKey]; - if (Array.isArray(value)) { - slotData[key][fpdKey] = value; - } else if ((typeof value === 'string' && value !== '') || typeof value === 'number') { - slotData[key][fpdKey] = [value]; + const data = { + id: bidRequest.transactionId, + test: config.getConfig('debug') ? 1 : 0, + cur: ['USD'], + source: { + tid: bidRequest.transactionId + }, + tmax: config.getConfig('TTL') || 1000, + imp: [{ + exp: 300, + id: bidRequest.adUnitCode, + secure: isSecure() || bidRequest.params.secure ? 1 : 0, + ext: { + rubicon: bidRequest.params + }, + video: utils.deepAccess(bidRequest, 'mediaTypes.video') || {} + }], + ext: { + prebid: { + cache: { + vastxml: { + returnCreative: false // don't return the VAST + } + }, + targeting: { + includewinners: true, + // includebidderkeys always false for openrtb + includebidderkeys: false, + priceGranularity: getPriceGranularity(config) } - }); + } } - }); - - if (params.keywords && Array.isArray(params.keywords)) { - slotData.keywords = params.keywords; } + // if value is set, will overwrite with same value + data.imp[0].ext.rubicon.video.size_id = determineRubiconVideoSizeId(bidRequest) - data.slots.push(slotData); + appendSiteAppDevice(data, bidRequest, bidderRequest); + + addVideoParameters(data, bidRequest); + + const digiTrust = getDigiTrustQueryParams(); + if (digiTrust) { + data.user = { + ext: { + digitrust: digiTrust + } + }; + } if (bidderRequest.gdprConsent) { - // add 'gdpr' only if 'gdprApplies' is defined + // note - gdprApplies & consentString may be undefined in certain use-cases for consentManagement module + let gdprApplies; if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { - data.gdpr = Number(bidderRequest.gdprConsent.gdprApplies); + gdprApplies = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; + } + + if (data.regs) { + if (data.regs.ext) { + data.regs.ext.gdpr = gdprApplies; + } else { + data.regs.ext = {gdpr: gdprApplies}; + } + } else { + data.regs = {ext: {gdpr: gdprApplies}}; + } + + const consentString = bidderRequest.gdprConsent.consentString; + if (data.user) { + if (data.user.ext) { + data.user.ext.consent = consentString; + } else { + data.user.ext = {consent: consentString}; + } + } else { + data.user = {ext: {consent: consentString}}; } - data.gdpr_consent = bidderRequest.gdprConsent.consentString; } return { @@ -390,6 +416,72 @@ export const spec = { return []; } + // video response from PBS Java openRTB + if (responseObj.seatbid) { + const responseErrors = utils.deepAccess(responseObj, 'ext.errors.rubicon'); + if (Array.isArray(responseErrors) && responseErrors.length > 0) { + responseErrors.forEach(error => { + utils.logError('Got error from PBS Java openRTB: ' + error); + }); + } + const bids = []; + responseObj.seatbid.forEach(seatbid => { + (seatbid.bid || []).forEach(bid => { + let bidObject = { + requestId: bidRequest.bidId, + currency: responseObj.cur || 'USD', + creativeId: bid.crid, + cpm: bid.price || 0, + bidderCode: seatbid.seat, + ttl: 300, + netRevenue: config.getConfig('rubicon.netRevenue') || false, + 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.dealid) { + bidObject.dealId = bid.dealid; + } + + let serverResponseTimeMs = utils.deepAccess(responseObj, 'ext.responsetimemillis.rubicon'); + if (bidRequest && serverResponseTimeMs) { + bidRequest.serverResponseTimeMs = serverResponseTimeMs; + } + + if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { + bidObject.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') { + bidObject.adserverTargeting = extPrebidTargeting; + } + + // try to get cache values from 'response.ext.prebid.cache' + // else try 'bid.ext.prebid.targeting' as fallback + if (bid.ext.prebid.cache && typeof bid.ext.prebid.cache.vastXml === 'object' && bid.ext.prebid.cache.vastXml.cacheId && bid.ext.prebid.cache.vastXml.url) { + bidObject.videoCacheKey = bid.ext.prebid.cache.vastXml.cacheId; + bidObject.vastUrl = bid.ext.prebid.cache.vastXml.url; + } else if (extPrebidTargeting && extPrebidTargeting.hb_uuid && extPrebidTargeting.hb_cache_host && extPrebidTargeting.hb_cache_path) { + bidObject.videoCacheKey = extPrebidTargeting.hb_uuid; + // build url using key and cache host + bidObject.vastUrl = `https://${extPrebidTargeting.hb_cache_host}${extPrebidTargeting.hb_cache_path}?uuid=${extPrebidTargeting.hb_uuid}`; + } + + if (bid.adm) { bidObject.vastXml = bid.adm; } + if (bid.nurl) { bidObject.vastUrl = bid.nurl; } + if (!bidObject.vastUrl && bid.nurl) { bidObject.vastUrl = bid.nurl; } + } else { + utils.logError('Prebid Server Java openRTB returns response with media type other than video for video request.'); + } + + bids.push(bidObject); + }); + }); + + return bids; + } + let ads = responseObj.ads; // video ads array is wrapped in an object @@ -516,6 +608,7 @@ function _getDigiTrustQueryParams() { /** * @param {BidRequest} bidRequest + * @param bidderRequest * @returns {string} */ function _getPageUrl(bidRequest, bidderRequest) { @@ -572,6 +665,77 @@ function parseSizes(bid, mediaType) { return masSizeOrdering(sizes); } +function getDigiTrustQueryParams() { + function getDigiTrustId() { + let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); + return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; + } + + let digiTrustId = getDigiTrustId(); + // Verify there is an ID and this user has not opted out + if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { + return null; + } + return { + id: digiTrustId.id, + keyv: digiTrustId.keyv, + pref: 0 + }; +} + +/** + * @param {Object} data + * @param bidRequest + * @param bidderRequest + */ +function appendSiteAppDevice(data, bidRequest, bidderRequest) { + if (!data) return; + + // ORTB specifies app OR site + if (typeof config.getConfig('app') === 'object') { + data.app = config.getConfig('app'); + } else { + data.site = { + page: _getPageUrl(bidRequest, bidderRequest) + } + } + if (typeof config.getConfig('device') === 'object') { + data.device = config.getConfig('device'); + } + // Add language to site and device objects if there + if (bidRequest.params.video.language) { + ['site', 'device'].forEach(function(param) { + if (data[param]) { + data[param].content = Object.assign({language: bidRequest.params.video.language}, data[param].content) + } + }); + } +} + +/** + * @param {Object} data + * @param {BidRequest} bidRequest + */ +function addVideoParameters(data, bidRequest) { + if (typeof data.imp[0].video === 'object' && data.imp[0].video.skip === undefined) { + data.imp[0].video.skip = bidRequest.params.video.skip; + } + if (typeof data.imp[0].video === 'object' && data.imp[0].video.skipafter === undefined) { + data.imp[0].video.skipafter = bidRequest.params.video.skipdelay; + } + if (typeof data.imp[0].video === 'object' && data.imp[0].video.pos === undefined) { + data.imp[0].video.pos = bidRequest.params.position === 'atf' ? 1 : (bidRequest.params.position === 'btf' ? 3 : 0); + } + + const size = parseSizes(bidRequest, 'video') + data.imp[0].video.w = size[0] + data.imp[0].video.h = size[1] +} + +/** + * @param sizes + * @returns {*} + */ function mapSizes(sizes) { return utils.parseSizesInput(sizes) // map sizes while excluding non-matches @@ -594,7 +758,7 @@ export function hasVideoMediaType(bidRequest) { if (typeof utils.deepAccess(bidRequest, 'params.video') !== 'object') { return false; } - return (bidRequest.mediaType === VIDEO || typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'); + return (typeof utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`) !== 'undefined'); } /** @@ -606,27 +770,15 @@ export function hasVideoMediaType(bidRequest) { function bidType(bid, log = false) { // Is it considered video ad unit by rubicon if (hasVideoMediaType(bid)) { - // legacy mediaType or the new mediaTypes - // this is the preffered "new" way to define mediaTypes - if (typeof utils.deepAccess(bid, `mediaTypes.${VIDEO}`) !== 'undefined') { - // We require either context as instream or outstream - if (['outstream', 'instream'].indexOf(utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`)) === -1) { - if (log) { - utils.logError('Rubicon bid adapter requires mediaTypes.video.context to be one of outstream or instream'); - } - return; - } - } else { // Otherwise its the legacy way where mediaType == 'video' + // 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(utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`)) === -1) { if (log) { - utils.logWarn('Rubicon video bid requested using legacy `adUnit.mediaType = `video``\nThis is deprecated\nPlease move towards the PBJS standard using mediaTypes object!'); - } - if (isNaN(parseInt(utils.deepAccess(bid, 'params.video.size_id')))) { - if (log) { - utils.logError('Rubicon bid adapter needs params.video.size_id to be declared and an integer in order to process a legacy video request using mediaType == video'); - } - return; + utils.logError('Rubicon bid adapter requires mediaTypes.video.context to be one of outstream or instream'); } + return; } + // 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) { @@ -691,6 +843,53 @@ export function determineRubiconVideoSizeId(bid) { return utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream' ? 203 : 201; } +export function getPriceGranularity(config) { + const granularityMappings = { + low: [{max: 5.00, increment: 0.50}], + medium: [{max: 20.00, increment: 0.10}], + high: [{max: 20.00, increment: 0.01}], + auto: [ + {max: 5.00, increment: 0.05}, + {min: 5.00, max: 10.00, increment: 0.10}, + {min: 10.00, max: 20.00, increment: 0.50} + ], + dense: [ + {max: 3.00, increment: 0.01}, + {min: 3.00, max: 8.00, increment: 0.05}, + {min: 8.00, max: 20.00, increment: 0.50} + ] + } + if (config.getConfig('priceGranularity') === 'custom') { + return {ranges: config.getConfig('customPriceGranularity').buckets} + } else { + return {ranges: granularityMappings[config.getConfig('priceGranularity')]} + } +} + +// Function to validate the required video params +export function hasValidVideoParams(bid) { + let isValid = true; + // incase future javascript changes the string represenation of the array or number classes! + let arrayType = Object.prototype.toString.call([]); + let numberType = Object.prototype.toString.call(0); + // required params and their associated object type + var requiredParams = { + mimes: arrayType, + protocols: arrayType, + maxduration: numberType, + linearity: numberType, + api: arrayType + } + // loop through each param and verify it has the correct + Object.keys(requiredParams).forEach(function(param) { + if (Object.prototype.toString.call(utils.deepAccess(bid, 'mediaTypes.video.' + param)) !== requiredParams[param]) { + isValid = false; + utils.logError('Rubicon Bid Adapter: mediaTypes.video.' + param + ' is required and must be of type: ' + requiredParams[param]); + } + }) + return isValid; +} + var hasSynced = false; export function resetUserSync() { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 839d34d5c57..81816d42407 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -149,40 +149,28 @@ describe('the rubicon adapter', function () { let bid = bidderRequest.bids[0]; bid.mediaTypes = { video: { - context: 'instream' + context: 'instream', + mimes: ['video/mp4', 'video/x-flv'], + api: [2], + minduration: 15, + playerSize: [640, 480], + maxduration: 30, + startdelay: 0, + playbackmethod: [2], + linearity: 1, + skip: 1, + skipafter: 15, + pos: 1, + protocols: [1, 2, 3, 4, 5, 6] } }; bid.params.video = { 'language': 'en', - 'p_aso.video.ext.skip': true, - 'p_aso.video.ext.skipdelay': 15, - 'playerHeight': 320, - 'playerWidth': 640, - 'size_id': 201, - 'aeParams': { - 'p_aso.video.ext.skip': '1', - 'p_aso.video.ext.skipdelay': '15' - } - }; - } - - function createLegacyVideoBidderRequest() { - createGdprBidderRequest(true); - - let bid = bidderRequest.bids[0]; - // Legacy property (Prebid <1.0) - bid.mediaType = 'video'; - bid.params.video = { - 'language': 'en', - 'p_aso.video.ext.skip': true, - 'p_aso.video.ext.skipdelay': 15, - 'playerHeight': 320, + 'skip': 1, + 'skipafter': 15, + 'playerHeight': 480, 'playerWidth': 640, 'size_id': 201, - 'aeParams': { - 'p_aso.video.ext.skip': '1', - 'p_aso.video.ext.skipdelay': '15' - } }; } @@ -196,64 +184,35 @@ describe('the rubicon adapter', function () { bid.params.video = ''; } - function createLegacyVideoBidderRequestNoVideo() { - let bid = bidderRequest.bids[0]; - bid.mediaType = 'video'; - bid.params.video = ''; - } - function createVideoBidderRequestOutstream() { let bid = bidderRequest.bids[0]; bid.mediaTypes = { video: { - context: 'outstream' + context: 'outstream', + mimes: ['video/mp4', 'video/x-flv'], + api: [2], + minduration: 15, + playerSize: [640, 480], + maxduration: 30, + startdelay: 0, + playbackmethod: [2], + linearity: 1, + skip: 1, + skipafter: 15, + pos: 1, + protocols: [1, 2, 3, 4, 5, 6] }, }; + bid.params.accountId = 14062; + bid.params.siteId = 70608; + bid.params.zoneId = 335918; bid.params.video = { 'language': 'en', - 'p_aso.video.ext.skip': true, - 'p_aso.video.ext.skipdelay': 15, + 'skip': 1, + 'skipafter': 15, 'playerHeight': 320, 'playerWidth': 640, - 'size_id': 203, - 'aeParams': { - 'p_aso.video.ext.skip': '1', - 'p_aso.video.ext.skipdelay': '15' - } - }; - } - - function createVideoBidderRequestNoPlayer() { - let bid = bidderRequest.bids[0]; - bid.mediaTypes = { - video: { - context: 'instream' - }, - }; - bid.params.video = { - 'language': 'en', - 'p_aso.video.ext.skip': true, - 'p_aso.video.ext.skipdelay': 15, - 'size_id': 201, - 'aeParams': { - 'p_aso.video.ext.skip': '1', - 'p_aso.video.ext.skipdelay': '15' - } - }; - } - - function createLegacyVideoBidderRequestNoPlayer() { - let bid = bidderRequest.bids[0]; - bid.mediaType = 'video'; - bid.params.video = { - 'language': 'en', - 'p_aso.video.ext.skip': true, - 'p_aso.video.ext.skipdelay': 15, - 'size_id': 201, - 'aeParams': { - 'p_aso.video.ext.skip': '1', - 'p_aso.video.ext.skipdelay': '15' - } + 'size_id': 203 }; } @@ -434,8 +393,8 @@ describe('the rubicon adapter', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); delete bidderRequest.bids[0].params.latLong; - [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - data = parseQuery(request.data); + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + let data = parseQuery(request.data); expect(request.url).to.equal('//fastlane.rubiconproject.com/a/api/fastlane.json'); @@ -450,8 +409,8 @@ describe('the rubicon adapter', function () { }); bidderRequest.bids[0].params.latLong = []; - let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - let data = parseQuery(request.data); + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + data = parseQuery(request.data); expect(request.url).to.equal('//fastlane.rubiconproject.com/a/api/fastlane.json'); @@ -480,7 +439,6 @@ describe('the rubicon adapter', function () { bidderRequest = Object.assign({refererInfo}, bidderRequest); delete bidderRequest.bids[0].params.referrer; let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - let data = parseQuery(request.data); expect(parseQuery(request.data).rf).to.exist; expect(parseQuery(request.data).rf).to.equal('http://www.prebid.org'); @@ -655,7 +613,6 @@ describe('the rubicon adapter', function () { }); describe('digiTrustId config', function () { - var origGetConfig; beforeEach(function () { window.DigiTrust = { getUser: sandbox.spy() @@ -1074,7 +1031,17 @@ describe('the rubicon adapter', function () { bidderRequest.bids.push(bidCopy3); const bidCopy4 = clone(bidderRequest.bids[0]); - bidCopy4.mediaType = 'video'; + bidCopy4.mediaTypes = { + video: { + context: 'instream', + playerSize: [640, 480], + mimes: ['video/mp4', 'video/x-ms-wmv'], + protocols: [2, 5], + maxduration: 30, + linearity: 1, + api: [2] + } + }; bidCopy4.params.video = { 'language': 'en', 'p_aso.video.ext.skip': true, @@ -1096,70 +1063,6 @@ describe('the rubicon adapter', function () { }); describe('for video requests', function () { - it('should make a well-formed video request with legacy mediaType config', function () { - createLegacyVideoBidderRequest(); - - sandbox.stub(Date, 'now').callsFake(() => - bidderRequest.auctionStart + 100 - ); - - let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - let post = request.data; - - let url = request.url; - - expect(url).to.equal('//fastlane-adv.rubiconproject.com/v1/auction/video'); - - expect(post).to.have.property('page_url').that.is.a('string'); - expect(post.resolution).to.match(/\d+x\d+/); - expect(post.account_id).to.equal('14062'); - expect(post.integration).to.equal(INTEGRATION); - expect(post['x_source.tid']).to.equal('d45dd707-a418-42ec-b8a7-b70a6c6fab0b'); - expect(post).to.have.property('timeout').that.is.a('number'); - expect(post.timeout < 5000).to.equal(true); - expect(post.stash_creatives).to.equal(true); - expect(post.gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); - expect(post.gdpr).to.equal(1); - - expect(post).to.have.property('ae_pass_through_parameters'); - expect(post.ae_pass_through_parameters) - .to.have.property('p_aso.video.ext.skip') - .that.equals('1'); - expect(post.ae_pass_through_parameters) - .to.have.property('p_aso.video.ext.skipdelay') - .that.equals('15'); - - expect(post).to.have.property('slots') - .with.a.lengthOf(1); - - let slot = post.slots[0]; - - expect(slot.site_id).to.equal('70608'); - expect(slot.zone_id).to.equal('335918'); - expect(slot.position).to.equal('atf'); - expect(slot.floor).to.equal(0.01); - expect(slot.element_id).to.equal(bidderRequest.bids[0].adUnitCode); - expect(slot.name).to.equal(bidderRequest.bids[0].adUnitCode); - expect(slot.language).to.equal('en'); - expect(slot.width).to.equal(640); - expect(slot.height).to.equal(320); - expect(slot.size_id).to.equal(201); - - expect(slot).to.have.property('inventory').that.is.an('object'); - expect(slot.inventory).to.have.property('rating').that.deep.equals(['5-star']); - expect(slot.inventory).to.have.property('prodtype').that.deep.equals(['tech', 'mobile']); - - expect(slot).to.have.property('keywords') - .that.is.an('array') - .of.length(3) - .that.deep.equals(['a', 'b', 'c']); - - expect(slot).to.have.property('visitor').that.is.an('object'); - expect(slot.visitor).to.have.property('ucat').that.deep.equals(['new']); - expect(slot.visitor).to.have.property('lastsearch').that.deep.equals(['iphone']); - expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); - }); - it('should make a well-formed video request', function () { createVideoBidderRequest(); @@ -1170,152 +1073,84 @@ describe('the rubicon adapter', function () { let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let post = request.data; - let url = request.url; - - expect(url).to.equal('//fastlane-adv.rubiconproject.com/v1/auction/video'); - - expect(post).to.have.property('page_url').that.is.a('string'); - expect(post.resolution).to.match(/\d+x\d+/); - expect(post.account_id).to.equal('14062'); - expect(post.integration).to.equal(INTEGRATION); - expect(post['x_source.tid']).to.equal('d45dd707-a418-42ec-b8a7-b70a6c6fab0b'); - expect(post).to.have.property('timeout').that.is.a('number'); - expect(post.timeout < 5000).to.equal(true); - expect(post.stash_creatives).to.equal(true); - expect(post.gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); - expect(post.gdpr).to.equal(1); - - expect(post).to.have.property('ae_pass_through_parameters'); - expect(post.ae_pass_through_parameters) - .to.have.property('p_aso.video.ext.skip') - .that.equals('1'); - expect(post.ae_pass_through_parameters) - .to.have.property('p_aso.video.ext.skipdelay') - .that.equals('15'); - - expect(post).to.have.property('slots') - .with.a.lengthOf(1); - - let slot = post.slots[0]; - - expect(slot.site_id).to.equal('70608'); - expect(slot.zone_id).to.equal('335918'); - expect(slot.position).to.equal('atf'); - expect(slot.floor).to.equal(0.01); - expect(slot.element_id).to.equal(bidderRequest.bids[0].adUnitCode); - expect(slot.name).to.equal(bidderRequest.bids[0].adUnitCode); - expect(slot.language).to.equal('en'); - expect(slot.width).to.equal(640); - expect(slot.height).to.equal(320); - expect(slot.size_id).to.equal(201); - - expect(slot).to.have.property('inventory').that.is.an('object'); - expect(slot.inventory).to.have.property('rating').that.deep.equals(['5-star']); - expect(slot.inventory).to.have.property('prodtype').that.deep.equals(['tech', 'mobile']); - - expect(slot).to.have.property('keywords') - .that.is.an('array') - .of.length(3) - .that.deep.equals(['a', 'b', 'c']); - - expect(slot).to.have.property('visitor').that.is.an('object'); - expect(slot.visitor).to.have.property('ucat').that.deep.equals(['new']); - expect(slot.visitor).to.have.property('lastsearch').that.deep.equals(['iphone']); - expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); + expect(post).to.have.property('imp') + // .with.length.of(1); + let imp = post.imp[0]; + expect(imp.id).to.equal(bidderRequest.bids[0].adUnitCode); + expect(imp.exp).to.equal(300); + expect(imp.video.w).to.equal(640); + expect(imp.video.h).to.equal(480); + expect(imp.video.pos).to.equal(1); + expect(imp.video.context).to.equal('instream'); + expect(imp.video.minduration).to.equal(15); + expect(imp.video.maxduration).to.equal(30); + expect(imp.video.startdelay).to.equal(0); + expect(imp.video.skip).to.equal(1); + expect(imp.video.skipafter).to.equal(15); + expect(imp.ext.rubicon.video.playerWidth).to.equal(640); + expect(imp.ext.rubicon.video.playerHeight).to.equal(480); + expect(imp.ext.rubicon.video.size_id).to.equal(201); + expect(imp.ext.rubicon.video.language).to.equal('en'); + // Also want it to be in post.site.content.language + expect(post.site.content.language).to.equal('en'); + expect(imp.ext.rubicon.video.skip).to.equal(1); + expect(imp.ext.rubicon.video.skipafter).to.equal(15); + expect(post.user.ext.consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + expect(post.regs.ext.gdpr).to.equal(1); + expect(post).to.have.property('ext').that.is.an('object'); + expect(post.ext.prebid.targeting.includewinners).to.equal(true); + expect(post.ext.prebid).to.have.property('cache').that.is.an('object') + expect(post.ext.prebid.cache).to.have.property('vastxml').that.is.an('object') + expect(post.ext.prebid.cache.vastxml).to.have.property('returnCreative').that.is.an('boolean') + expect(post.ext.prebid.cache.vastxml.returnCreative).to.equal(false) }); it('should send request with proper ad position', function () { createVideoBidderRequest(); - var positionBidderRequest = clone(bidderRequest); - positionBidderRequest.bids[0].params.position = 'atf'; + let positionBidderRequest = clone(bidderRequest); + positionBidderRequest.bids[0].mediaTypes.video.pos = 1; let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); - let post = request.data; - let slot = post.slots[0]; - - expect(slot.position).to.equal('atf'); - - positionBidderRequest = clone(bidderRequest); - positionBidderRequest.bids[0].params.position = 'btf'; - [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); - post = request.data; - slot = post.slots[0]; + expect(request.data.imp[0].video.pos).to.equal(1); + }); - expect(slot.position).to.equal('btf'); + it('should send request with proper ad position when mediaTypes.video.pos is not defined', function () { + createVideoBidderRequest(); + let positionBidderRequest = clone(bidderRequest); + positionBidderRequest.bids[0].params.position = undefined; + positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; + let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); + expect(request.data.imp[0].video.pos).to.equal(0); positionBidderRequest = clone(bidderRequest); - positionBidderRequest.bids[0].params.position = 'unknown'; + positionBidderRequest.bids[0].params.position = 'atf' + positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); - post = request.data; - slot = post.slots[0]; - - expect(slot.position).to.equal('unknown'); + expect(request.data.imp[0].video.pos).to.equal(1); positionBidderRequest = clone(bidderRequest); - positionBidderRequest.bids[0].params.position = '123'; + positionBidderRequest.bids[0].params.position = 'btf'; + positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); - post = request.data; - slot = post.slots[0]; - - expect(slot.position).to.equal('unknown'); + expect(request.data.imp[0].video.pos).to.equal(3); positionBidderRequest = clone(bidderRequest); - delete positionBidderRequest.bids[0].params.position; - expect(positionBidderRequest.bids[0].params.position).to.equal(undefined); + positionBidderRequest.bids[0].params.position = 'foobar'; + positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); - post = request.data; - slot = post.slots[0]; - - expect(slot.position).to.equal('unknown'); - }); - - it('should allow a floor price override', function () { - createVideoBidderRequest(); - - sandbox.stub(Date, 'now').callsFake(() => - bidderRequest.auctionStart + 100 - ); - - var floorBidderRequest = clone(bidderRequest); - - // enter an explicit floor price // - floorBidderRequest.bids[0].params.floor = 3.25; - - let [request] = spec.buildRequests(floorBidderRequest.bids, floorBidderRequest); - let post = request.data; - - let floor = post.slots[0].floor; - - expect(floor).to.equal(3.25); - }); - - it('should validate bid request with invalid video if a mediaTypes banner property is defined', function () { - const bidRequest = { - mediaTypes: { - video: { - context: 'instream' - }, - banner: { - sizes: [[300, 250]] - } - }, - params: { - accountId: 1001, - video: { - size_id: 201 - } - }, - sizes: [[300, 250]] - } - sandbox.stub(Date, 'now').callsFake(() => - bidderRequest.auctionStart + 100 - ); - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + expect(request.data.imp[0].video.pos).to.equal(0); }); - it('should not validate bid request when a params.video object is present but no context instream or outstream is passed in', function () { + it('should properly enforce video.context to be either instream or outstream', function () { let bid = bidderRequest.bids[0]; bid.mediaTypes = { - video: {} + video: { + context: 'instream', + mimes: ['video/mp4', 'video/x-ms-wmv'], + protocols: [2, 5], + maxduration: 30, + linearity: 1, + api: [2] + } } bid.params.video = {}; @@ -1324,48 +1159,83 @@ describe('the rubicon adapter', function () { ); const bidRequestCopy = clone(bidderRequest.bids[0]); - expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(true); - bidRequestCopy.params.video = {sizeId: 201}; - expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); + // change context to outstream, still true + bidRequestCopy.mediaTypes.video.context = 'outstream'; + expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(true); - bidRequestCopy.mediaTypes.video = {context: undefined}; + // change context to random, false now + bidRequestCopy.mediaTypes.video.context = 'random'; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - bidRequestCopy.mediaTypes.video = {context: ''}; + // change context to undefined, still false + bidRequestCopy.mediaTypes.video.context = undefined; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - bidRequestCopy.mediaTypes.video = {context: 'random'}; + // remove context, still false + delete bidRequestCopy.mediaTypes.video.context; expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); - - bidRequestCopy.mediaTypes.video = {context: 'instream'}; - expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(true); - - bidRequestCopy.mediaTypes.video = {context: 'outstream'}; - expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(true); }); - it('should not validate bid request when an invalid video object is passed in with legacy config mediaType', function () { - createLegacyVideoBidderRequestNoVideo(); + it('should enforce the new required mediaTypes.video params', function () { + createVideoBidderRequest(); + sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 ); - const bidderRequestCopy = clone(bidderRequest); - bidderRequestCopy.bids[0].params.video = {}; - expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(true); + + // change mimes to a non array, no good + createVideoBidderRequest(); + bidderRequest.bids[0].mediaTypes.video.mimes = 'video/mp4'; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); + + // delete mimes, no good + createVideoBidderRequest(); + delete bidderRequest.bids[0].mediaTypes.video.mimes; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); + + // change protocols to an int not array of ints, no good + createVideoBidderRequest(); + bidderRequest.bids[0].mediaTypes.video.protocols = 1; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); + + // delete protocols, no good + createVideoBidderRequest(); + delete bidderRequest.bids[0].mediaTypes.video.protocols; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); + + // change maxduration to an string, no good + createVideoBidderRequest(); + bidderRequest.bids[0].mediaTypes.video.maxduration = 'string'; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); - bidderRequestCopy.bids[0].params.video = {size_id: undefined}; - expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + // delete maxduration, no good + createVideoBidderRequest(); + delete bidderRequest.bids[0].mediaTypes.video.maxduration; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); - bidderRequestCopy.bids[0].params.video = {size_id: 'size'}; - expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); + // change linearity to an string, no good + createVideoBidderRequest(); + bidderRequest.bids[0].mediaTypes.video.linearity = 'string'; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); - bidderRequestCopy.bids[0].params.video = {size_id: '201'}; - expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(true); + // delete linearity, no good + createVideoBidderRequest(); + delete bidderRequest.bids[0].mediaTypes.video.linearity; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); - bidderRequestCopy.bids[0].params.video = {size_id: 201}; - expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(true); + // change api to an string, no good + createVideoBidderRequest(); + bidderRequest.bids[0].mediaTypes.video.api = 'string'; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); + + // delete api, no good + createVideoBidderRequest(); + delete bidderRequest.bids[0].mediaTypes.video.api; + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); }); it('bid request is valid when video context is outstream', function () { @@ -1378,11 +1248,10 @@ describe('the rubicon adapter', function () { let [request] = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(true); - expect(request.data.slots[0].size_id).to.equal(203); + expect(request.data.imp[0].ext.rubicon.video.size_id).to.equal(203); }); it('should send banner request when outstream or instream video included but no rubicon video obect is present', function () { - let bid = bidderRequest.bids[0]; // add banner and video mediaTypes bidderRequest.mediaTypes = { banner: { @@ -1429,34 +1298,6 @@ describe('the rubicon adapter', function () { expect(requests.length).to.equal(1); expect(requests[0].url).to.equal(FASTLANE_ENDPOINT); }); - - it('should get size from bid.sizes too', () => { - createVideoBidderRequestNoPlayer(); - sandbox.stub(Date, 'now').callsFake(() => - bidderRequest.auctionStart + 100 - ); - - const bidRequestCopy = clone(bidderRequest); - - let [request] = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); - - expect(request.data.slots[0].width).to.equal(300); - expect(request.data.slots[0].height).to.equal(250); - }); - - it('should get size from bid.sizes too with legacy config mediaType', function () { - createLegacyVideoBidderRequestNoPlayer(); - sandbox.stub(Date, 'now').callsFake(() => - bidderRequest.auctionStart + 100 - ); - - const bidRequestCopy = clone(bidderRequest); - - let [request] = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); - - expect(request.data.slots[0].width).to.equal(300); - expect(request.data.slots[0].height).to.equal(250); - }); }); describe('combineSlotUrlParams', function () { @@ -1531,14 +1372,12 @@ describe('the rubicon adapter', function () { expect(legacyVideoTypeBidRequest).is.equal(true); }); - it('should return false if mediaType is video and size_id is not defined', function () { - expect(spec.isBidRequestValid({ - bid: 99, - mediaType: 'video', - params: { - video: {} - } - })).is.equal(false); + it('should return false if trying to use legacy mediaType with video', function () { + createVideoBidderRequest(); + delete bidderRequest.bids[0].mediaTypes; + bidderRequest.bids[0].mediaType = 'video'; + const legacyVideoTypeBidRequest = hasVideoMediaType(bidderRequest.bids[0]); + expect(legacyVideoTypeBidRequest).is.equal(false); }); it('should return false if bidRequest.mediaType is not equal to video', function () { @@ -2069,30 +1908,31 @@ describe('the rubicon adapter', function () { it('should register a successful bid', function () { let response = { - 'status': 'ok', - 'ads': { - '/19968336/header-bid-tag-0': [ - { - 'status': 'ok', - 'cpm': 1, - 'tier': 'tier0200', - 'targeting': { - 'rpfl_8000': '201_tier0200', - 'rpfl_elemid': '/19968336/header-bid-tag-0' + cur: 'USD', + seatbid: [{ + bid: [{ + id: '0', + impid: 'instream_video1', + price: 2, + crid: '4259970', + ext: { + bidder: { + rp: { + mime: 'application/javascript', + size_id: 201 + } }, - 'impression_id': 'a40fe16e-d08d-46a9-869d-2e1573599e0c', - 'site_id': 88888, - 'zone_id': 54321, - 'creative_type': 'video', - 'creative_depot_url': 'https://fastlane-adv.rubiconproject.com/v1/creative/a40fe16e-d08d-46a9-869d-2e1573599e0c.xml', - 'ad_id': 999999, - 'creative_id': 'crid-999999', - 'size_id': 201, - 'advertiser': 12345 + prebid: { + targeting: { + hb_uuid: '0c498f63-5111-4bed-98e2-9be7cb932a64' + }, + type: 'video' + } } - ] - }, - 'account_id': 7780 + }], + group: 0, + seat: 'rubicon' + }], }; let bids = spec.interpretResponse({body: response}, { @@ -2101,16 +1941,16 @@ describe('the rubicon adapter', function () { expect(bids).to.be.lengthOf(1); - expect(bids[0].creativeId).to.equal('crid-999999'); - expect(bids[0].cpm).to.equal(1); + expect(bids[0].creativeId).to.equal('4259970'); + expect(bids[0].cpm).to.equal(2); expect(bids[0].ttl).to.equal(300); expect(bids[0].netRevenue).to.equal(false); - expect(bids[0].vastUrl).to.equal( - 'https://fastlane-adv.rubiconproject.com/v1/creative/a40fe16e-d08d-46a9-869d-2e1573599e0c.xml' - ); - expect(bids[0].impression_id).to.equal('a40fe16e-d08d-46a9-869d-2e1573599e0c'); + expect(bids[0].adserverTargeting).to.deep.equal({hb_uuid: '0c498f63-5111-4bed-98e2-9be7cb932a64'}); expect(bids[0].mediaType).to.equal('video'); - expect(bids[0].videoCacheKey).to.equal('a40fe16e-d08d-46a9-869d-2e1573599e0c'); + expect(bids[0].bidderCode).to.equal('rubicon'); + expect(bids[0].currency).to.equal('USD'); + expect(bids[0].width).to.equal(640); + expect(bids[0].height).to.equal(480); }); }); }); From 9868bc34426d2e4e1623ff00687489a79aa7b634 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 5 Mar 2019 10:28:20 -0500 Subject: [PATCH 1054/1594] jsDelivr only supports https (#3608) --- modules/categoryTranslation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/categoryTranslation.js b/modules/categoryTranslation.js index ee1b088e408..f4d0a281f57 100644 --- a/modules/categoryTranslation.js +++ b/modules/categoryTranslation.js @@ -17,7 +17,7 @@ import { ajax } from '../src/ajax'; import { timestamp, logError, setDataInLocalStorage, getDataFromLocalStorage } from '../src/utils'; import { addBidResponse } from '../src/auction'; -const DEFAULT_TRANSLATION_FILE_URL = '//cdn.jsdelivr.net/gh/prebid/category-mapping-file@1/freewheel-mapping.json'; +const DEFAULT_TRANSLATION_FILE_URL = 'https://cdn.jsdelivr.net/gh/prebid/category-mapping-file@1/freewheel-mapping.json'; const DEFAULT_IAB_TO_FW_MAPPING_KEY = 'iabToFwMappingkey'; const DEFAULT_IAB_TO_FW_MAPPING_KEY_PUB = 'iabToFwMappingkeyPub'; const refreshInDays = 1; From 7dd9f8aa0aead65428e924ee40344578d132ab36 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 5 Mar 2019 13:56:58 -0500 Subject: [PATCH 1055/1594] add default sizes value for appnexus native requests (#3602) --- modules/appnexusBidAdapter.js | 3 + test/spec/modules/appnexusBidAdapter_spec.js | 24 ++++++ test/spec/unit/core/adapterManager_spec.js | 81 +++++++++++++++++++- 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 0dc05ced08a..0f295dadef1 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -508,6 +508,9 @@ function bidToTag(bid) { if (bid.mediaType === NATIVE || utils.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); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index d2094217c70..71f7e74fe47 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -443,6 +443,30 @@ describe('AppNexusAdapter', function () { }); }); + 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], diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index d6b699bd7da..f52aadba647 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -913,7 +913,7 @@ describe('adapterManager tests', function () { setSizeConfig([]); }); - it('should not filter bids w/ no labels', function () { + it('should not filter banner bids w/ no labels', function () { let bidRequests = adapterManager.makeBidRequests( adUnits, Date.now(), @@ -933,6 +933,85 @@ describe('adapterManager tests', function () { expect(appnexusBidRequests.bids[1].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).sizes); }); + it('should not filter video bids', function () { + setSizeConfig([{ + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250] + ], + 'labels': ['tablet', 'phone'] + }]); + + let videoAdUnits = [{ + code: 'test_video', + mediaTypes: { + video: { + playerSize: [300, 300], + context: 'outstream' + } + }, + bids: [{ + bidder: 'appnexus', + params: { + placementId: 13232385, + video: { + skippable: true, + playback_method: ['auto_play_sound_off'] + } + } + }] + }]; + let bidRequests = adapterManager.makeBidRequests( + videoAdUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + expect(bidRequests[0].bids[0].sizes).to.deep.equal([300, 300]); + }); + + it('should not filter native bids', function () { + setSizeConfig([{ + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250] + ], + 'labels': ['tablet', 'phone'] + }]); + + let nativeAdUnits = [{ + code: 'test_native', + sizes: [[1, 1]], + mediaTypes: { + native: { + title: { required: true }, + body: { required: false }, + image: { required: true }, + icon: { required: false }, + sponsoredBy: { required: true }, + clickUrl: { required: true }, + }, + }, + bids: [ + { + bidder: 'appnexus', + params: { placementId: 13232354 } + }, + ] + }]; + let bidRequests = adapterManager.makeBidRequests( + nativeAdUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + expect(bidRequests[0].bids[0].sizes).to.deep.equal([]); + }); + it('should filter sizes using size config', function () { let validSizes = [ [728, 90], From 1a4c9646094f7f152abaa31956e790fd12489c1a Mon Sep 17 00:00:00 2001 From: Matt Lane Date: Tue, 5 Mar 2019 11:02:25 -0800 Subject: [PATCH 1056/1594] Send url value when replacing image and icons types (#3609) --- src/native.js | 21 ++++++++++++++------- test/spec/native_spec.js | 18 ++++++++++++++++-- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/native.js b/src/native.js index 8ebe4c8eca6..c9a67ca7541 100644 --- a/src/native.js +++ b/src/native.js @@ -157,12 +157,7 @@ export function getNativeTargeting(bid, bidReq) { Object.keys(bid['native']).forEach(asset => { const key = CONSTANTS.NATIVE_KEYS[asset]; - let value = bid['native'][asset]; - - // native image-type assets can be a string or an object with a url prop - if (typeof value === 'object' && value.url) { - value = value.url; - } + let value = getAssetValue(bid['native'][asset]); const sendPlaceholder = deepAccess( bidReq, @@ -195,10 +190,22 @@ export function getAssetMessage(data, adObject) { data.assets.forEach(asset => { const key = getKeyByValue(CONSTANTS.NATIVE_KEYS, asset); - const value = adObject.native[key]; + const value = getAssetValue(adObject.native[key]); message.assets.push({ key, value }); }); return message; } + +/** + * Native assets can be a string or an object with a url prop. Returns the value + * appropriate for sending in adserver targeting or placeholder replacement. + */ +function getAssetValue(value) { + if (typeof value === 'object' && value.url) { + return value.url; + } + + return value; +} diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index ed21b5f681b..2fb2fd810fa 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -9,6 +9,16 @@ const bid = { title: 'Native Creative', body: 'Cool description great stuff', cta: 'Do it', + image: { + url: 'http://cdn.example.com/p/creative-image/image.png', + height: 83, + width: 127 + }, + icon: { + url: 'http://cdn.example.com/p/creative-image/icon.jpg', + height: 742, + width: 989 + }, sponsoredBy: 'AppNexus', clickUrl: 'https://www.link.example', clickTrackers: ['https://tracker.example'], @@ -96,16 +106,20 @@ describe('native.js', function () { message: 'Prebid Native', action: 'assetRequest', adId: '123', - assets: ['hb_native_body', 'hb_native_linkurl'], + assets: ['hb_native_body', 'hb_native_image', 'hb_native_linkurl'], }; const message = getAssetMessage(messageRequest, bid); - expect(message.assets.length).to.equal(2); + expect(message.assets.length).to.equal(3); expect(message.assets).to.deep.include({ key: 'body', value: bid.native.body }); + expect(message.assets).to.deep.include({ + key: 'image', + value: bid.native.image.url + }); expect(message.assets).to.deep.include({ key: 'clickUrl', value: bid.native.clickUrl From 9d5b9b48a8f3c1156da93f0a7965af668f19ccda Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 5 Mar 2019 11:23:40 -0800 Subject: [PATCH 1057/1594] PBS Bid Adapter oRTB caching and video updates (#3528) * updates to both the rubicon adapter and the prebid server for ORTB requirements * updates to bid and auction data to reflect oRTB structure * merged pbjs commits * reverted karma conf * always add ext.prebid.targeting.includewinners: true for openrtb * add unit test for ext.prebid.targeting.includewinners for openrtb * added s2sConfig 'video.ext.prebid' support and unit test * added code comments for changes to ORTB * handle response.ext.prebid.cache values and added unit test * update to merged video.ext.prebid with request.ext.prebid * update to merge includewinners * added test for override used in s2sConfig for ext.prebid.targeting.includewinners value * fixes for response cache logic * added support for targeting cache props HB-3740 * added test for adserverTargeting change * updates to address Jira ticket revision * update to build the vastUrl object by utilizing hb_cache_host + hb_cache_path, since the hb_cache_hostpath will be suppressed soon * removed single quotes around object literal keys to match formatting * added new standard targeting keys for video * removed code added by jsnellbaker per his recommendation because our change should make it unnecessary --- modules/prebidServerBidAdapter/index.js | 39 ++- src/auction.js | 19 +- src/constants.json | 4 +- .../modules/prebidServerBidAdapter_spec.js | 227 ++++++++++++++++++ 4 files changed, 279 insertions(+), 10 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 47c51ad9280..fdcab82d247 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -71,6 +71,7 @@ config.setDefaults({ * @property {boolean} [cacheMarkup] whether to cache the adm result * @property {string} [adapter] adapter code to use for S2S * @property {string} [syncEndpoint] endpoint URL for syncing cookies + * @property {Object} [extPrebid] properties will be merged into request.ext.prebid * @property {AdapterOptions} [adapterOptions] adds arguments to resulting OpenRTB payload to Prebid Server */ function setS2sConfig(options) { @@ -483,8 +484,23 @@ const OPEN_RTB_PROTOCOL = { tmax: _s2sConfig.timeout, imp: imps, test: getConfig('debug') ? 1 : 0, + ext: { + prebid: { + targeting: { + // includewinners is always true for openrtb + includewinners: true, + // includebidderkeys always false for openrtb + includebidderkeys: false + } + } + } }; + // s2sConfig video.ext.prebid is passed through openrtb to PBS + if (_s2sConfig.extPrebid && typeof _s2sConfig.extPrebid === 'object') { + request.ext.prebid = Object.assign(request.ext.prebid, _s2sConfig.extPrebid); + } + _appendSiteAppDevice(request); const digiTrust = _getDigiTrustQueryParams(); @@ -493,7 +509,7 @@ const OPEN_RTB_PROTOCOL = { } if (!utils.isEmpty(aliases)) { - request.ext = { prebid: { aliases } }; + request.ext.prebid.aliases = aliases; } if (bidRequests && bidRequests[0].userId && typeof bidRequests[0].userId === 'object') { @@ -571,10 +587,29 @@ const OPEN_RTB_PROTOCOL = { bidRequest.serverResponseTimeMs = serverResponseTimeMs; } + 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') { + bidObject.adserverTargeting = extPrebidTargeting; + } + if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { bidObject.mediaType = VIDEO; + + // try to get cache values from 'response.ext.prebid.cache' + // else try 'bid.ext.prebid.targeting' as fallback + if (bid.ext.prebid.cache && typeof bid.ext.prebid.cache.vastXml === 'object' && bid.ext.prebid.cache.vastXml.cacheId && bid.ext.prebid.cache.vastXml.url) { + bidObject.videoCacheKey = bid.ext.prebid.cache.vastXml.cacheId; + bidObject.vastUrl = bid.ext.prebid.cache.vastXml.url; + } else if (extPrebidTargeting && extPrebidTargeting.hb_uuid && extPrebidTargeting.hb_cache_host && extPrebidTargeting.hb_cache_path) { + bidObject.videoCacheKey = extPrebidTargeting.hb_uuid; + // build url using key and cache host + bidObject.vastUrl = `https://${extPrebidTargeting.hb_cache_host}${extPrebidTargeting.hb_cache_path}?uuid=${extPrebidTargeting.hb_uuid}`; + } + if (bid.adm) { bidObject.vastXml = bid.adm; } - if (bid.nurl) { bidObject.vastUrl = bid.nurl; } + if (!bidObject.vastUrl && bid.nurl) { bidObject.vastUrl = bid.nurl; } } else { // banner if (bid.adm && bid.nurl) { bidObject.ad = bid.adm; diff --git a/src/auction.js b/src/auction.js index 0ddb2450561..bf3f1bb1b71 100644 --- a/src/auction.js +++ b/src/auction.js @@ -500,14 +500,8 @@ function setupBidTargeting(bidObject, bidderRequest) { keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq); } - let cacheTargetKeys = {}; - if (bidObject.videoCacheKey) { - cacheTargetKeys.hb_uuid = bidObject.videoCacheKey; - cacheTargetKeys.hb_cache_id = bidObject.videoCacheKey; - } - // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs - bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, cacheTargetKeys, keyValues); + bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); } export function getStandardBidderSettings(mediaType) { @@ -572,6 +566,17 @@ export function getStandardBidderSettings(mediaType) { } }, ] + + if (mediaType === 'video') { + [CONSTANTS.TARGETING_KEYS.UUID, CONSTANTS.TARGETING_KEYS.CACHE_ID].forEach(item => { + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push({ + key: item, + val: function val(bidResponse) { + return bidResponse.videoCacheKey; + } + }) + }); + } } return bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; } diff --git a/src/constants.json b/src/constants.json index 4e946d9c593..1a78e376150 100644 --- a/src/constants.json +++ b/src/constants.json @@ -62,7 +62,9 @@ "SIZE": "hb_size", "DEAL": "hb_deal", "SOURCE": "hb_source", - "FORMAT": "hb_format" + "FORMAT": "hb_format", + "UUID": "hb_uuid", + "CACHE_ID": "hb_cache_id" }, "NATIVE_KEYS": { "title": "hb_native_title", diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 457d768f7a4..f14c171ee6c 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -654,6 +654,10 @@ describe('S2S Adapter', function () { prebid: { aliases: { brealtime: 'appnexus' + }, + targeting: { + includebidderkeys: false, + includewinners: true } } }); @@ -684,6 +688,10 @@ describe('S2S Adapter', function () { prebid: { aliases: { [alias]: 'appnexus' + }, + targeting: { + includebidderkeys: false, + includewinners: true } } }); @@ -822,6 +830,146 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.tpid.foo).is.equal('abc123'); expect(requestBid.user.ext.tpid.unifiedid).is.equal('1234'); }) + + it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', + adapterOptions: { + appnexus: { + key: 'value' + } + } + }); + const _config = { + s2sConfig: s2sConfig, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.ext.prebid.targeting).to.haveOwnProperty('includebidderkeys'); + expect(requestBid.ext.prebid.targeting.includebidderkeys).to.equal(false); + }); + + it('always add ext.prebid.targeting.includewinners: true for ORTB', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', + adapterOptions: { + appnexus: { + key: 'value' + } + } + }); + const _config = { + s2sConfig: s2sConfig, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.ext.prebid.targeting).to.haveOwnProperty('includewinners'); + expect(requestBid.ext.prebid.targeting.includewinners).to.equal(true); + }); + + it('adds s2sConfig video.ext.prebid to request for ORTB', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', + extPrebid: { + foo: 'bar' + } + }); + const _config = { + s2sConfig: s2sConfig, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid).to.haveOwnProperty('ext'); + expect(requestBid.ext).to.haveOwnProperty('prebid'); + expect(requestBid.ext.prebid).to.deep.equal({ + foo: 'bar', + targeting: { + includewinners: true, + includebidderkeys: false + } + }); + }); + + it('overrides request.ext.prebid properties using s2sConfig video.ext.prebid values for ORTB', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', + extPrebid: { + targeting: { + includewinners: false, + includebidderkeys: true + } + } + }); + const _config = { + s2sConfig: s2sConfig, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid).to.haveOwnProperty('ext'); + expect(requestBid.ext).to.haveOwnProperty('prebid'); + expect(requestBid.ext.prebid).to.deep.equal({ + targeting: { + includewinners: false, + includebidderkeys: true + } + }); + }); + + it('overrides request.ext.prebid properties using s2sConfig video.ext.prebid values for ORTB', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', + extPrebid: { + cache: { + vastxml: 'vastxml-set-though-extPrebid.cache.vastXml' + }, + targeting: { + includewinners: false, + includebidderkeys: false + } + } + }); + const _config = { + s2sConfig: s2sConfig, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid).to.haveOwnProperty('ext'); + expect(requestBid.ext).to.haveOwnProperty('prebid'); + expect(requestBid.ext.prebid).to.deep.equal({ + cache: { + vastxml: 'vastxml-set-though-extPrebid.cache.vastXml' + }, + targeting: { + includewinners: false, + includebidderkeys: false + } + }); + }); }); describe('response handler', function () { @@ -1058,6 +1206,85 @@ describe('S2S Adapter', function () { expect(response).to.have.property('cpm', 10); }); + it('handles response cache from ext.prebid.cache.vastXml', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' + }); + config.setConfig({s2sConfig}); + const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); + cacheResponse.seatbid.forEach(item => { + item.bid[0].ext.prebid.cache = { + vastXml: { + cacheId: 'abcd1234', + url: 'https://prebid-cache.net/cache?uuid=abcd1234' + } + } + }); + server.respondWith(JSON.stringify(cacheResponse)); + adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(addBidResponse); + const response = addBidResponse.firstCall.args[1]; + + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('videoCacheKey', 'abcd1234'); + expect(response).to.have.property('vastUrl', 'https://prebid-cache.net/cache?uuid=abcd1234'); + }); + + it('add adserverTargeting object to bids when ext.prebid.targeting is defined', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' + }); + config.setConfig({s2sConfig}); + const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); + const targetingTestData = { + hb_cache_path: '/cache', + hb_cache_host: 'prebid-cache.testurl.com' + }; + + cacheResponse.seatbid.forEach(item => { + item.bid[0].ext.prebid.targeting = targetingTestData + }); + server.respondWith(JSON.stringify(cacheResponse)); + adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(addBidResponse); + const response = addBidResponse.firstCall.args[1]; + + expect(response).to.have.property('adserverTargeting'); + expect(response.adserverTargeting).to.deep.equal({ + 'hb_cache_path': '/cache', + 'hb_cache_host': 'prebid-cache.testurl.com' + }); + }); + + it('handles response cache from ext.prebid.targeting', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' + }); + config.setConfig({s2sConfig}); + const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); + cacheResponse.seatbid.forEach(item => { + item.bid[0].ext.prebid.targeting = { + hb_uuid: 'a5ad3993', + hb_cache_host: 'prebid-cache.net', + hb_cache_path: '/cache' + } + }); + server.respondWith(JSON.stringify(cacheResponse)); + adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(addBidResponse); + const response = addBidResponse.firstCall.args[1]; + + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('videoCacheKey', 'a5ad3993'); + expect(response).to.have.property('vastUrl', 'https://prebid-cache.net/cache?uuid=a5ad3993'); + }); + it('should log warning for unsupported bidder', function () { server.respondWith(JSON.stringify(RESPONSE_UNSUPPORTED_BIDDER)); From 35c58e00f554e6366c7bce854bd4b27994caa6a9 Mon Sep 17 00:00:00 2001 From: Vladimir Fedoseev Date: Tue, 5 Mar 2019 23:08:14 +0300 Subject: [PATCH 1058/1594] Added myTarget Adapter (#3599) * Add myTargetBidAdapter * myTargetBidAdapter: replace legacy substr function --- modules/mytargetBidAdapter.js | 108 ++++++++++ modules/mytargetBidAdapter.md | 40 ++++ test/spec/modules/mytargetBidAdapter_spec.js | 199 +++++++++++++++++++ 3 files changed, 347 insertions(+) create mode 100644 modules/mytargetBidAdapter.js create mode 100644 modules/mytargetBidAdapter.md create mode 100644 test/spec/modules/mytargetBidAdapter_spec.js diff --git a/modules/mytargetBidAdapter.js b/modules/mytargetBidAdapter.js new file mode 100644 index 00000000000..e5b6cc735ef --- /dev/null +++ b/modules/mytargetBidAdapter.js @@ -0,0 +1,108 @@ +import * as utils from '../src/utils'; +import * as url from '../src/url'; +import { config } from '../src/config'; +import { registerBidder } from '../src/adapters/bidderFactory'; + +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) { + sitename = url.parse(referrer).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: utils._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 utils._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 + } + + if (bid.adm) { + bidResponse.ad = bid.adm; + } else { + bidResponse.adUrl = bid.displayUrl; + } + + return bidResponse; + }); + } + + return []; + } +} + +registerBidder(spec); diff --git a/modules/mytargetBidAdapter.md b/modules/mytargetBidAdapter.md new file mode 100644 index 00000000000..3292ff561fa --- /dev/null +++ b/modules/mytargetBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +``` +Module Name: myTarget Bidder Adapter +Module Type: Bidder Adapter +Maintainer: support_target@corp.my.com +``` + +# Description + +Module that connects to myTarget demand sources. + +# Test Parameters + +``` + var adUnits = [{ + code: 'placementCode', + mediaTypes: { + banner: { + sizes: [[240, 400]], + } + }, + bids: [{ + bidder: 'mytarget', + params: { + placementId: '379783', + + // OPTIONAL: custom bid floor + bidfloor: 10000, + + // OPTIONAL: if you know the ad position on the page, specify it here + // (this corresponds to "Ad Position" in OpenRTB 2.3, section 5.4) + position: 0, + + // OPTIONAL: bid response type: 0 - ad url (default), 1 - ad markup + response: 0 + } + }] + }]; +``` diff --git a/test/spec/modules/mytargetBidAdapter_spec.js b/test/spec/modules/mytargetBidAdapter_spec.js new file mode 100644 index 00000000000..211d1df79a7 --- /dev/null +++ b/test/spec/modules/mytargetBidAdapter_spec.js @@ -0,0 +1,199 @@ +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'); + }); + }); +}); From 6dc809493c18f2159a982dcf71b6a2fc0e702d7e Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 5 Mar 2019 12:16:00 -0800 Subject: [PATCH 1059/1594] Add HTML5 video support param to bid requests (#3596) * Add HTML5 video support param to bid requests * Use const instead of var for consistency --- modules/sharethroughBidAdapter.js | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index ee97ac739c4..ec97649df6d 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -12,12 +12,13 @@ export const sharethroughAdapterSpec = { buildRequests: (bidRequests, bidderRequest) => { return bidRequests.map(bid => { let query = { - bidId: bid.bidId, placement_key: bid.params.pkey, - hbVersion: '$prebid.version$', - strVersion: VERSION, + bidId: bid.bidId, + consent_required: false, + instant_play_capable: canAutoPlayHTML5Video(), hbSource: 'prebid', - consent_required: false + hbVersion: '$prebid.version$', + strVersion: VERSION }; if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) { @@ -148,4 +149,25 @@ function b64EncodeUnicode(str) { })); } +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; + } +} + registerBidder(sharethroughAdapterSpec); From efdee9c729450451ec053fa23dfd854eef6265a3 Mon Sep 17 00:00:00 2001 From: Mirko Feddern Date: Tue, 5 Mar 2019 21:47:57 +0100 Subject: [PATCH 1060/1594] Add support for External Id (#3594) The External Id is a dynamic reporting dimension, that can be passed through Yieldlab's adtag via the "id"-parameter. E.g. https://ad.yieldlab.net/d/1111/2222/728x90?ts=123456789&id=abc --- modules/yieldlabBidAdapter.js | 6 ++++-- modules/yieldlabBidAdapter.md | 3 ++- test/spec/modules/yieldlabBidAdapter_spec.js | 6 +++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index cb5535bb165..1bbb3f11a2e 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -77,6 +77,7 @@ export const spec = { if (matchedBid) { const primarysize = bidRequest.sizes.length === 2 && !utils.isArray(bidRequest.sizes[0]) ? bidRequest.sizes : bidRequest.sizes[0] const customsize = bidRequest.params.adSize !== undefined ? parseSize(bidRequest.params.adSize) : primarysize + const extId = bidRequest.params.extId !== undefined ? '&id=' + bidRequest.params.extId : '' const bidResponse = { requestId: bidRequest.bidId, cpm: matchedBid.price / 100, @@ -88,11 +89,12 @@ export const spec = { netRevenue: false, ttl: BID_RESPONSE_TTL_SEC, referrer: '', - ad: `` + ad: `` } + if (isVideo(bidRequest)) { bidResponse.mediaType = VIDEO - bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/${customsize[0]}x${customsize[1]}?ts=${timestamp}` + bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/${customsize[0]}x${customsize[1]}?ts=${timestamp}${extId}` } bidResponses.push(bidResponse) diff --git a/modules/yieldlabBidAdapter.md b/modules/yieldlabBidAdapter.md index 96b62f5cf8c..de93baf42ae 100644 --- a/modules/yieldlabBidAdapter.md +++ b/modules/yieldlabBidAdapter.md @@ -25,7 +25,8 @@ Module that connects to Yieldlab's demand sources targeting: { key1: "value1", key2: "value2" - } + }, + extId: "abc" } }] }, { diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index 497e9c7b894..c2e12408cdd 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -11,7 +11,8 @@ const REQUEST = { 'targeting': { 'key1': 'value1', 'key2': 'value2' - } + }, + 'extId': 'abc' }, 'bidderRequestId': '143346cf0f1731', 'auctionId': '2e41f65424c87c', @@ -104,6 +105,7 @@ describe('yieldlabBidAdapter', function () { expect(result[0].ttl).to.equal(300) expect(result[0].referrer).to.equal('') expect(result[0].ad).to.include('' + oad; - ad += ''; - ad += ''; - ad += '' + let ad = decision.contents && decision.contents[0] && decision.contents[0].body + utils.createTrackPixelHtml(decision.impressionUrl); return ad; } diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index 832706b2b95..fc5e1d1b45a 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -43,6 +43,10 @@ const REQUEST = { 'bidderRequestId': '109f2a181342a9', 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' }], + 'gdprConsent': { + 'consentString': 'consent-test', + 'gdprApplies': true + }, 'start': 1487883186070, 'auctionStart': 1487883186069, 'timeout': 3000 @@ -52,6 +56,7 @@ const RESPONSE = { 'headers': null, 'body': { 'user': { 'key': 'ue1-2d33e91b71e74929b4aeecc23f4376f1' }, + 'pixels': [{ 'type': 'image', 'url': '//sync.serverbid.com/ss/' }], 'decisions': { '2b0f82502298c9': { 'adId': 2364764, @@ -206,7 +211,7 @@ describe('Consumable BidAdapter', function () { }); describe('interpretResponse validation', function () { it('response should have valid bidderCode', function () { - let bidRequest = spec.buildRequests(REQUEST.bidRequest); + let bidRequest = spec.buildRequests(REQUEST.bidRequest, REQUEST); let bid = createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('consumable'); @@ -264,5 +269,12 @@ describe('Consumable BidAdapter', function () { 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, [RESPONSE]); + + expect(opts.length).to.equal(1); + }); }); }); From 0c5fbabfd64c784a50834d75b63c19583809148e Mon Sep 17 00:00:00 2001 From: Hendrik Iseke <39734979+hiseke@users.noreply.github.com> Date: Fri, 15 Mar 2019 15:20:21 +0100 Subject: [PATCH 1080/1594] add bidfloor to params object (#3641) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons * add bidfloor parameter to params object --- modules/orbidderBidAdapter.js | 1 + test/spec/modules/orbidderBidAdapter_spec.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index de365fe87de..e316f3ef212 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -18,6 +18,7 @@ export const spec = { return !!(bid.sizes && bid.bidId && bid.params && (bid.params.accountId && (typeof bid.params.accountId === 'string')) && (bid.params.placementId && (typeof bid.params.placementId === 'string')) && + ((typeof bid.params.bidfloor === 'undefined') || (typeof bid.params.bidfloor === 'number')) && ((typeof bid.params.keyValues === 'undefined') || (typeof bid.params.keyValues === 'object'))); }, diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 29c6c2c6d9a..0761ed8d31e 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -64,6 +64,21 @@ describe('orbidderBidAdapter', () => { delete bidRequest.params; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); + + it('accepts optional bidfloor', () => { + const bidRequest = deepClone(defaultBidRequest); + bidRequest.params.bidfloor = 123; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + + bidRequest.params.bidfloor = 1.23; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('doesn\'t accept malformed bidfloor', () => { + const bidRequest = deepClone(defaultBidRequest); + bidRequest.params.bidfloor = 'another not usable string'; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); }); describe('buildRequests', () => { From 879789ba4e2c8ee988f4c368d3e1e94bc112e6ec Mon Sep 17 00:00:00 2001 From: Finteza Analytics <45741245+finteza@users.noreply.github.com> Date: Fri, 15 Mar 2019 20:37:07 +0200 Subject: [PATCH 1081/1594] Add finteza analytics adapter (#3555) * Add finteza analytics adapter * Fix PR issues --- modules/fintezaAnalyticsAdapter.js | 406 ++++++++++++++++++ modules/fintezaAnalyticsAdapter.md | 28 ++ .../modules/fintezaAnalyticsAdapter_spec.js | 209 +++++++++ 3 files changed, 643 insertions(+) create mode 100644 modules/fintezaAnalyticsAdapter.js create mode 100644 modules/fintezaAnalyticsAdapter.md create mode 100644 test/spec/modules/fintezaAnalyticsAdapter_spec.js diff --git a/modules/fintezaAnalyticsAdapter.js b/modules/fintezaAnalyticsAdapter.js new file mode 100644 index 00000000000..2b5cd0421c2 --- /dev/null +++ b/modules/fintezaAnalyticsAdapter.js @@ -0,0 +1,406 @@ +import { ajax } from '../src/ajax'; +import adapter from '../src/AnalyticsAdapter'; +import adapterManager from '../src/adapterManager'; +import * as utils from '../src/utils'; +import { parse as parseURL } from '../src/url'; + +const CONSTANTS = require('../src/constants.json'); + +const ANALYTICS_TYPE = 'endpoint'; +const FINTEZA_HOST = 'https://content.mql5.com/tr'; +const BID_REQUEST_TRACK = 'Bid Request %BIDDER%'; +const BID_RESPONSE_TRACK = 'Bid Response %BIDDER%'; +const BID_TIMEOUT_TRACK = 'Bid Timeout %BIDDER%'; +const BID_WON_TRACK = 'Bid Won %BIDDER%'; + +const FIRST_VISIT_DATE = '_fz_fvdt'; +const SESSION_ID = '_fz_ssn'; +const SESSION_DURATION = 30 * 60 * 1000; +const SESSION_RAND_PART = 9; +const TRACK_TIME_KEY = '_fz_tr'; + +function getPageInfo() { + const pageInfo = { + domain: window.location.hostname, + } + + if (document.referrer) { + pageInfo.referrerDomain = parseURL(document.referrer).hostname; + } + + return pageInfo; +} + +function initFirstVisit() { + let now; + let visitDate; + let cookies; + + try { + cookies = parseCookies(document.cookie); + } catch (a) { + cookies = {}; + } + + visitDate = cookies[ FIRST_VISIT_DATE ]; + + if (!visitDate) { + now = new Date(); + + visitDate = parseInt(now.getTime() / 1000, 10); + + now.setFullYear(now.getFullYear() + 20); + + try { + document.cookie = FIRST_VISIT_DATE + '=' + visitDate + '; path=/; expires=' + now.toUTCString(); + } catch (e) {} + } + + return visitDate; +} + +function trim(string) { + if (string.trim) { + return string.trim(); + } + return string.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); +} + +function parseCookies(cookie) { + let values = {}; + let arr, item; + let param, value; + let i, j; + + if (!cookie) { + return {}; + } + + arr = cookie.split(';'); + + for (i = 0, j = arr.length; i < j; i++) { + item = arr[ i ]; + if (!item) { + continue; + } + + param = item.split('='); + if (param.length <= 1) { + continue; + } + + value = decodeURIComponent(param[0]); + value = trim(value); + + values[value] = decodeURIComponent(param[1]); + } + + return values; +} + +function getRandAsStr(digits) { + let str = ''; + let rand = 0; + let i; + + digits = digits || 4; + + for (i = 0; i < digits; i++) { + rand = (Math.random() * 10) >>> 0; + str += '' + rand; + } + + return str; +} + +function getSessionBegin(session) { + if (!session || (typeof session !== 'string')) { + return 0; + } + + const len = session.length; + if (len && len <= SESSION_RAND_PART) { + return 0; + } + + const timestamp = session.substring(0, len - SESSION_RAND_PART); + + return parseInt(timestamp, 10); +} + +function initSession() { + const now = new Date(); + const expires = new Date(now.getTime() + SESSION_DURATION); + const timestamp = Math.floor(now.getTime() / 1000); + let begin = 0; + let cookies; + let sessionId; + let sessionDuration; + let isNew = false; + + try { + cookies = parseCookies(document.cookie); + } catch (a) { + cookies = {}; + } + + sessionId = cookies[ SESSION_ID ]; + + if (!sessionId || + !checkSessionByExpires() || + !checkSessionByReferer() || + !checkSessionByDay()) { + sessionId = '' + timestamp + getRandAsStr(SESSION_RAND_PART); + begin = timestamp; + + isNew = true; + } else { + begin = getSessionBegin(sessionId); + } + + if (begin > 0) { + sessionDuration = Math.floor(timestamp - begin); + } else { + sessionDuration = -1; + } + + try { + document.cookie = SESSION_ID + '=' + sessionId + '; path=/; expires=' + expires.toUTCString(); + } catch (e) {} + + return { + isNew: isNew, + id: sessionId, + duration: sessionDuration + }; +} + +function checkSessionByExpires() { + const timestamp = getTrackRequestLastTime(); + const now = new Date().getTime(); + + if (now > timestamp + SESSION_DURATION) { + return false; + } + return true; +} + +function checkSessionByReferer() { + const referrer = fntzAnalyticsAdapter.context.pageInfo.referrerDomain; + const domain = fntzAnalyticsAdapter.context.pageInfo.domain; + + return referrer === '' || domain === referrer; +} + +function checkSessionByDay() { + let last = getTrackRequestLastTime(); + if (last) { + last = new Date(last); + const now = new Date(); + + return last.getUTCDate() === now.getUTCDate() && + last.getUTCMonth() === now.getUTCMonth() && + last.getUTCFullYear() === now.getUTCFullYear(); + } + + return false; +} + +function saveTrackRequestTime() { + const now = new Date().getTime(); + const expires = new Date(now + SESSION_DURATION); + + try { + if (window.localStorage) { + window.localStorage.setItem(TRACK_TIME_KEY, now.toString()); + } else { + document.cookie = TRACK_TIME_KEY + '=' + now + '; path=/; expires=' + expires.toUTCString(); + } + } catch (a) {} +} + +function getTrackRequestLastTime() { + let cookie; + + try { + if (window.localStorage) { + return parseInt( + window.localStorage.getItem(TRACK_TIME_KEY) || 0, + 10, + ); + } + + cookie = parseCookies(document.cookie); + cookie = cookie[ TRACK_TIME_KEY ]; + if (cookie) { + return parseInt(cookie, 10); + } + } catch (e) {} + + return 0; +} + +function getAntiCacheParam() { + const date = new Date(); + const rand = (Math.random() * 99999 + 1) >>> 0; + + return ([ date.getTime(), rand ].join('')); +} + +function replaceBidder(str, bidder) { + let _str = str; + _str = _str.replace(/\%bidder\%/, bidder.toLowerCase()); + _str = _str.replace(/\%BIDDER\%/, bidder.toUpperCase()); + _str = _str.replace(/\%Bidder\%/, bidder.charAt(0).toUpperCase() + bidder.slice(1).toLowerCase()); + + return _str; +} + +function prepareBidRequestedParams(args) { + return [{ + event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidRequestTrack, args.bidderCode)), + ref: encodeURIComponent(window.location.href), + }]; +} + +function prepareBidResponseParams(args) { + return [{ + event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidResponseTrack, args.bidderCode)), + c1_value: args.timeToRespond, + c1_unit: 'ms', + c2_value: args.cpm, + c2_unit: 'usd', + }]; +} + +function prepareBidWonParams(args) { + return [{ + event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidWonTrack, args.bidderCode)), + c1_value: args.cpm, + c1_unit: 'usd', + }]; +} + +function prepareBidTimeoutParams(args) { + return args.map(function(bid) { + return { + event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidTimeoutTrack, bid.bidder)), + c1_value: bid.timeout, + c1_unit: 'ms', + }; + }) +} + +function prepareTrackData(evtype, args) { + let prepareParams = null; + + switch (evtype) { + case CONSTANTS.EVENTS.BID_REQUESTED: + prepareParams = prepareBidRequestedParams; + break; + case CONSTANTS.EVENTS.BID_RESPONSE: + prepareParams = prepareBidResponseParams; + break; + case CONSTANTS.EVENTS.BID_WON: + prepareParams = prepareBidWonParams; + break; + case CONSTANTS.EVENTS.BID_TIMEOUT: + prepareParams = prepareBidTimeoutParams; + break; + } + + if (!prepareParams) { return null; } + + const data = prepareParams(args); + + if (!data) { return null; } + + const session = initSession(); + + return data.map(d => { + const trackData = Object.assign(d, { + id: fntzAnalyticsAdapter.context.id, + ref: encodeURIComponent(window.location.href), + title: encodeURIComponent(document.title), + scr_res: fntzAnalyticsAdapter.context.screenResolution, + fv_date: fntzAnalyticsAdapter.context.firstVisit, + ac: getAntiCacheParam(), + }) + + if (session.id) { + trackData.ssn = session.id; + } + if (session.isNew) { + session.isNew = false; + trackData.ssn_start = 1; + } + trackData.ssn_dr = session.duration; + + return trackData; + }); +} + +function sendTrackRequest(trackData) { + try { + ajax( + fntzAnalyticsAdapter.context.host, + null, // Callback + trackData, + { + method: 'GET', + contentType: 'application/x-www-form-urlencoded', + // preflight: true, + }, + ); + saveTrackRequestTime(); + } catch (err) { + utils.logError('Error on send data: ', err); + } +} + +const fntzAnalyticsAdapter = Object.assign( + adapter({ + FINTEZA_HOST, + ANALYTICS_TYPE + }), + { + track({ eventType, args }) { + if (typeof args !== 'undefined') { + const trackData = prepareTrackData(eventType, args); + if (!trackData) { return; } + + trackData.forEach(sendTrackRequest); + } + } + } +); + +fntzAnalyticsAdapter.originEnableAnalytics = fntzAnalyticsAdapter.enableAnalytics; + +fntzAnalyticsAdapter.enableAnalytics = function (config) { + if (!config.options.id) { + utils.logError('Client ID (id) option is not defined. Analytics won\'t work'); + return; + } + + fntzAnalyticsAdapter.context = { + host: config.options.host || FINTEZA_HOST, + id: config.options.id, + bidRequestTrack: config.options.bidRequestTrack || BID_REQUEST_TRACK, + bidResponseTrack: config.options.bidResponseTrack || BID_RESPONSE_TRACK, + bidTimeoutTrack: config.options.bidTimeoutTrack || BID_TIMEOUT_TRACK, + bidWonTrack: config.options.bidWonTrack || BID_WON_TRACK, + firstVisit: initFirstVisit(), + screenResolution: `${window.screen.width}x${window.screen.height}`, + pageInfo: getPageInfo(), + }; + + fntzAnalyticsAdapter.originEnableAnalytics(config); +}; + +adapterManager.registerAnalyticsAdapter({ + adapter: fntzAnalyticsAdapter, + code: 'finteza' +}); + +export default fntzAnalyticsAdapter; diff --git a/modules/fintezaAnalyticsAdapter.md b/modules/fintezaAnalyticsAdapter.md new file mode 100644 index 00000000000..22525f55366 --- /dev/null +++ b/modules/fintezaAnalyticsAdapter.md @@ -0,0 +1,28 @@ +# Overview + +``` +Module Name: Finteza Analytics Adapter +Module Type: Analytics Adapter +Maintainer: renat@finteza.com +``` + +# Description + +The Finteza adapter for integration with Prebid is an analytics tool for publishers who use the Header Bidding technology. The adapter tracks auction opening, offer sending to advertisers, receipt of bids by the publisher and auction winner selection. All tracks are sent to Finteza and enable visual advertiser quality evaluation: how many offers partners accept, what prices they provide, how fast they respond and how often their bids win. + +For more information, visit the [official Finteza website](https://www.finteza.com/). + +# Test Parameters + +``` +{ + provider: 'finteza', + options: { + id: 'xxxxx', // Website ID (required) + bidRequestTrack: 'Bid Request %BIDDER%', + bidResponseTrack: 'Bid Response %BIDDER%', + bidTimeoutTrack: 'Bid Timeout %BIDDER%', + bidWonTrack: 'Bid Won %BIDDER%' + } +} +``` diff --git a/test/spec/modules/fintezaAnalyticsAdapter_spec.js b/test/spec/modules/fintezaAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..95600e84a9f --- /dev/null +++ b/test/spec/modules/fintezaAnalyticsAdapter_spec.js @@ -0,0 +1,209 @@ +import fntzAnalyticsAdapter from 'modules/fintezaAnalyticsAdapter'; +import includes from 'core-js/library/fn/array/includes'; +import { expect } from 'chai'; +import { parse as parseURL } from 'src/url'; +let adapterManager = require('src/adapterManager').default; +let events = require('src/events'); +let constants = require('src/constants.json'); + +describe('finteza analytics adapter', function () { + const clientId = 'fntz-client-32145'; + + let xhr; + let requests; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => { requests.push(request) }; + sinon.stub(events, 'getEvents').returns([]); + sinon.spy(fntzAnalyticsAdapter, 'track'); + + adapterManager.registerAnalyticsAdapter({ + code: 'finteza', + adapter: fntzAnalyticsAdapter + }); + + adapterManager.enableAnalytics({ + provider: 'finteza', + options: { + id: clientId, // Client ID (required) + bidRequestTrack: 'Bid Request %BIDDER%', + bidResponseTrack: 'Bid Response %bidder%', + bidTimeoutTrack: 'Bid Timeout %Bidder%', + bidWonTrack: 'Bid Won %BIDDER%', + } + }); + }); + + afterEach(function () { + xhr.restore(); + events.getEvents.restore(); + fntzAnalyticsAdapter.track.restore(); + fntzAnalyticsAdapter.disableAnalytics(); + }); + + describe('track', () => { + describe('bid request', () => { + it('builds and sends data', function () { + const bidderCode = 'Bidder789'; + const pauctionId = '5018eb39-f900-4370-b71e-3bb5b48d324f'; + + const bidRequest = { + bidderCode: bidderCode, + auctionId: pauctionId, + bidderRequestId: '1a6fc81528d0f6', + bids: [{ + bidder: bidderCode, + placementCode: 'container-1', + bidId: '208750227436c1', + bidderRequestId: '1a6fc81528d0f6', + auctionId: pauctionId, + startTime: 1509369418389, + sizes: [[300, 250]], + }], + auctionStart: 1509369418387, + timeout: 3000, + start: 1509369418389 + }; + + // Emit the events with the "real" arguments + events.emit(constants.EVENTS.BID_REQUESTED, bidRequest); + + expect(requests.length).to.equal(1); + + expect(requests[0].method).to.equal('GET'); + + const url = parseURL(requests[0].url); + + expect(url.protocol).to.equal('https'); + expect(url.hostname).to.equal('content.mql5.com'); + expect(url.pathname).to.equal('/tr'); + expect(url.search.id).to.equal(clientId); + expect(decodeURIComponent(url.search.event)).to.equal(`Bid Request ${bidderCode.toUpperCase()}`); + + sinon.assert.callCount(fntzAnalyticsAdapter.track, 1); + }); + }); + + describe('bid response', () => { + it('builds and sends data', function () { + const bidderCode = 'Bidder789'; + const pauctionId = '5018eb39-f900-4370-b71e-3bb5b48d324f'; + + const timeToRespond = 443; + const cpm = 0.015; + + const bidResponse = { + bidderCode: bidderCode, + adId: '208750227436c1', + cpm: cpm, + auctionId: pauctionId, + responseTimestamp: 1509369418832, + requestTimestamp: 1509369418389, + bidder: bidderCode, + timeToRespond: timeToRespond, + size: '300x250', + width: 300, + height: 250, + }; + + // Emit the events with the "real" arguments + events.emit(constants.EVENTS.BID_RESPONSE, bidResponse); + + expect(requests.length).to.equal(1); + + expect(requests[0].method).to.equal('GET'); + + const url = parseURL(requests[0].url); + + expect(url.protocol).to.equal('https'); + expect(url.hostname).to.equal('content.mql5.com'); + expect(url.pathname).to.equal('/tr'); + expect(url.search.id).to.equal(clientId); + expect(decodeURIComponent(url.search.event)).to.equal(`Bid Response ${bidderCode.toLowerCase()}`); + expect(url.search.c1_value).to.equal(String(timeToRespond)); + expect(url.search.c1_unit).to.equal('ms'); + expect(url.search.c2_value).to.equal(String(cpm)); + expect(url.search.c2_unit).to.equal('usd'); + + sinon.assert.callCount(fntzAnalyticsAdapter.track, 1); + }); + }); + + describe('bid won', () => { + it('builds and sends data', function () { + const bidderCode = 'Bidder789'; + const pauctionId = '5018eb39-f900-4370-b71e-3bb5b48d324f'; + + const cpm = 0.015; + + const bidWon = { + bidderCode: bidderCode, + cpm: cpm, + adId: 'adIdData', + ad: 'adContent', + auctionId: pauctionId, + width: 300, + height: 250 + } + + // Emit the events with the "real" arguments + events.emit(constants.EVENTS.BID_WON, bidWon); + + expect(requests.length).to.equal(1); + + expect(requests[0].method).to.equal('GET'); + + const url = parseURL(requests[0].url); + + expect(url.protocol).to.equal('https'); + expect(url.hostname).to.equal('content.mql5.com'); + expect(url.pathname).to.equal('/tr'); + expect(url.search.id).to.equal(clientId); + expect(decodeURIComponent(url.search.event)).to.equal(`Bid Won ${bidderCode.toUpperCase()}`); + expect(url.search.c1_value).to.equal(String(cpm)); + expect(url.search.c1_unit).to.equal('usd'); + + sinon.assert.callCount(fntzAnalyticsAdapter.track, 1); + }); + }); + + describe('bid timeout', () => { + it('builds and sends data', function () { + const bidderCode = 'biDDer789'; + const pauctionId = '5018eb39-f900-4370-b71e-3bb5b48d324f'; + + const timeout = 2540; + + const bidTimeout = [ + { + bidId: '208750227436c1', + bidder: bidderCode, + auctionId: pauctionId, + timeout: timeout, + } + ]; + + // Emit the events with the "real" arguments + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeout); + + expect(requests.length).to.equal(1); + + expect(requests[0].method).to.equal('GET'); + + const url = parseURL(requests[0].url); + + expect(url.protocol).to.equal('https'); + expect(url.hostname).to.equal('content.mql5.com'); + expect(url.pathname).to.equal('/tr'); + expect(url.search.id).to.equal(clientId); + expect(decodeURIComponent(url.search.event)).to.equal(`Bid Timeout Bidder789`); + expect(url.search.c1_value).to.equal(String(timeout)); + expect(url.search.c1_unit).to.equal('ms'); + + sinon.assert.callCount(fntzAnalyticsAdapter.track, 1); + }); + }); + }); +}); From 8c5f26ea949267c2c19c752f2fcb714d665bf9f7 Mon Sep 17 00:00:00 2001 From: PWyrembak Date: Fri, 15 Mar 2019 22:25:41 +0300 Subject: [PATCH 1082/1594] Add video support in TrustX Bid Adapter (#3632) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Add support of gdpr to Trustx Bid Adapter * Add wtimeout to ad request params for TrustX Bid Adapter * TrustX Bid Adapter: remove last ampersand in the ad request * Update TrustX Bid Adapter to support identical uids in parameters * Update TrustX Bid Adapter to ignore bids that sizes do not match the size of the request * Update TrustX Bid Adapter to support instream and outstream video --- modules/trustxBidAdapter.js | 60 +++++- modules/trustxBidAdapter.md | 13 ++ test/spec/modules/trustxBidAdapter_spec.js | 207 +++++++++++++++++++++ 3 files changed, 274 insertions(+), 6 deletions(-) diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index bd5f63e5302..b0593e5c7d7 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -1,9 +1,14 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; +import { Renderer } from '../src/Renderer'; +import { VIDEO, BANNER } from '../src/mediaTypes'; + const BIDDER_CODE = 'trustx'; const ENDPOINT_URL = '//sofia.trustx.org/hb'; const TIME_TO_LIVE = 360; const ADAPTER_SYNC_URL = '//sofia.trustx.org/push_sync'; +const RENDERER_URL = '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js'; + const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', noAdm: 'Bid from response has no adm parameter - ', @@ -17,6 +22,7 @@ const LOG_ERROR_MESS = { }; export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, VIDEO ], /** * Determines whether or not the given bid request is valid. * @@ -113,7 +119,7 @@ export const spec = { * @param {*} bidRequest * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse: function(serverResponse, bidRequest) { + interpretResponse: function(serverResponse, bidRequest, RendererConst = Renderer) { serverResponse = serverResponse && serverResponse.body; const bidResponses = []; const bidsMap = bidRequest.bidsMap; @@ -128,7 +134,7 @@ export const spec = { if (!errorMessage && serverResponse.seatbid) { serverResponse.seatbid.forEach(respItem => { - _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses); + _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses, RendererConst); }); } if (errorMessage) utils.logError(errorMessage); @@ -155,7 +161,7 @@ function _getBidFromResponse(respItem) { return respItem && respItem.bid && respItem.bid[0]; } -function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { +function _addBidResponse(serverBid, bidsMap, priceType, bidResponses, RendererConst) { if (!serverBid) return; let errorMessage; if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); @@ -168,7 +174,7 @@ function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { const slot = awaitingBids[sizeId][0]; const bid = slot.bids.shift(); - bidResponses.push({ + const bidResponse = { requestId: bid.bidId, // bid.bidderRequestId, bidderCode: spec.code, cpm: serverBid.price, @@ -178,9 +184,26 @@ function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { currency: 'USD', netRevenue: priceType !== 'gross', ttl: TIME_TO_LIVE, - ad: serverBid.adm, dealId: serverBid.dealid - }); + }; + if (serverBid.content_type === 'video') { + 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, + url: RENDERER_URL + }, RendererConst); + } + } else { + bidResponse.ad = serverBid.adm; + bidResponse.mediaType = BANNER; + } + + bidResponses.push(bidResponse); if (!slot.bids.length) { slot.parents.forEach(({parent, key, uid}) => { @@ -206,4 +229,29 @@ function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) { } } +function outstreamRender (bid) { + bid.renderer.push(() => { + window.ANOutstreamVideo.renderAd({ + targetId: bid.adUnitCode, + adResponse: bid.adResponse + }); + }); +} + +function createRenderer (bid, rendererParams, RendererConst) { + const rendererInst = RendererConst.install({ + id: rendererParams.id, + url: rendererParams.url, + loaded: false + }); + + try { + rendererInst.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + + return rendererInst; +} + registerBidder(spec); diff --git a/modules/trustxBidAdapter.md b/modules/trustxBidAdapter.md index ca407b0c5e8..d6b660c6248 100755 --- a/modules/trustxBidAdapter.md +++ b/modules/trustxBidAdapter.md @@ -7,6 +7,7 @@ Maintainer: paul@trustx.org # Description Module that connects to TrustX demand source to fetch bids. +TrustX Bid Adapter supports Banner and Video (instream and outstream). # Test Parameters ``` @@ -35,6 +36,18 @@ Module that connects to TrustX demand source to fetch bids. } } ] + },{ + code: 'test-div', + sizes: [[640, 360]], + mediaTypes: { video: {} }, + bids: [ + { + bidder: "trustx", + params: { + uid: 7697 + } + } + ] } ]; ``` \ No newline at end of file diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index 207d3a068ba..de0d1c8a530 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -194,6 +194,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 1
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, } @@ -251,6 +252,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 1
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, }, @@ -264,6 +266,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 2
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, }, @@ -277,6 +280,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 3
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, } @@ -404,6 +408,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 1
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, }, @@ -417,6 +422,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 2
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, }, @@ -430,6 +436,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 3
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, }, @@ -443,6 +450,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 4
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, } @@ -504,6 +512,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 1
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, }, @@ -517,6 +526,7 @@ describe('TrustXAdapter', function () { 'ad': '
test content 2
', 'bidderCode': 'trustx', 'currency': 'USD', + 'mediaType': 'banner', 'netRevenue': true, 'ttl': 360, } @@ -526,4 +536,201 @@ describe('TrustXAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); }); + + it('should get correct video bid response', function () { + const bidRequests = [ + { + 'bidder': 'trustx', + 'params': { + 'uid': '50' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '57dfefb80eca', + 'bidderRequestId': '20394420a762a2', + 'auctionId': '140132d07b031', + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + } + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '51' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'e893c787c22dd', + 'bidderRequestId': '20394420a762a2', + 'auctionId': '140132d07b031', + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + } + } + ]; + const response = [ + {'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 expectedResponse = [ + { + 'requestId': '57dfefb80eca', + 'cpm': 1.15, + 'creativeId': 50, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'bidderCode': 'trustx', + 'currency': 'USD', + 'mediaType': 'video', + 'netRevenue': true, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + } + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': response}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should have right renderer in the bid response', function () { + const spySetRenderer = sinon.spy(); + const stubRenderer = { + setRender: spySetRenderer + }; + const spyRendererInstall = sinon.spy(function() { return stubRenderer; }); + const stubRendererConst = { + install: spyRendererInstall + }; + const bidRequests = [ + { + 'bidder': 'trustx', + 'params': { + 'uid': '50' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'e6e65553fc8', + 'bidderRequestId': '1380f393215dc7', + 'auctionId': '10b8d2f3c697e3', + 'mediaTypes': { + 'video': { + 'context': 'outstream' + } + } + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '51' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'c8fdcb3f269f', + 'bidderRequestId': '1380f393215dc7', + 'auctionId': '10b8d2f3c697e3' + }, + { + 'bidder': 'trustx', + 'params': { + 'uid': '52' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '1de036c37685', + 'bidderRequestId': '1380f393215dc7', + 'auctionId': '10b8d2f3c697e3', + 'renderer': {} + } + ]; + const response = [ + {'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 expectedResponse = [ + { + 'requestId': 'e6e65553fc8', + 'cpm': 1.15, + 'creativeId': 50, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'bidderCode': 'trustx', + 'currency': 'USD', + 'mediaType': 'video', + 'netRevenue': true, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + }, + 'renderer': stubRenderer + }, + { + 'requestId': 'c8fdcb3f269f', + 'cpm': 1.00, + 'creativeId': 51, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'bidderCode': 'trustx', + 'currency': 'USD', + 'mediaType': 'video', + 'netRevenue': true, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + }, + 'renderer': stubRenderer + }, + { + 'requestId': '1de036c37685', + 'cpm': 1.20, + 'creativeId': 52, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'bidderCode': 'trustx', + 'currency': 'USD', + 'mediaType': 'video', + 'netRevenue': true, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + } + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': response}}, request, stubRendererConst); + + expect(spySetRenderer.calledTwice).to.equal(true); + expect(spySetRenderer.getCall(0).args[0]).to.be.a('function'); + expect(spySetRenderer.getCall(1).args[0]).to.be.a('function'); + + expect(spyRendererInstall.calledTwice).to.equal(true); + expect(spyRendererInstall.getCall(0).args[0]).to.deep.equal({ + id: 'e6e65553fc8', + url: '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + loaded: false + }); + expect(spyRendererInstall.getCall(1).args[0]).to.deep.equal({ + id: 'c8fdcb3f269f', + url: '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + loaded: false + }); + + expect(result).to.deep.equal(expectedResponse); + }); }); From 7cfb94b00179678be3b66c618c2a5014aff7cff9 Mon Sep 17 00:00:00 2001 From: Fedor Belov Date: Fri, 15 Mar 2019 23:41:39 +0300 Subject: [PATCH 1083/1594] otm prioritize sizes (#3642) --- modules/otmBidAdapter.js | 43 ++++++++++++++++++++++--- test/spec/modules/otmBidAdapter_spec.js | 38 ++++++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/modules/otmBidAdapter.js b/modules/otmBidAdapter.js index 78015d69594..57ac414c7b6 100644 --- a/modules/otmBidAdapter.js +++ b/modules/otmBidAdapter.js @@ -1,5 +1,5 @@ -import {BANNER} from '../src/mediaTypes'; -import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER} from 'src/mediaTypes'; +import {registerBidder} from 'src/adapters/bidderFactory'; export const spec = { code: 'otm', @@ -9,10 +9,11 @@ export const spec = { }, buildRequests: function (bidRequests) { const requests = bidRequests.map(function (bid) { + const size = getMaxPrioritySize(bid.sizes); const params = { tz: getTz(), - w: bid.sizes[0][0], - h: bid.sizes[0][1], + w: size[0], + h: size[1], s: bid.params.tid, bidid: bid.bidId, transactionid: bid.transactionId, @@ -57,4 +58,38 @@ function getTz() { return new Date().getTimezoneOffset(); } +function getMaxPrioritySize(sizes) { + var maxPrioritySize = null; + + const sizesByPriority = [ + [300, 250], + [240, 400], + [728, 90], + [300, 600], + [970, 250], + [300, 50], + [320, 100] + ]; + + const sizeToString = (size) => { + return size[0] + 'x' + size[1]; + }; + + const sizesAsString = sizes.map(sizeToString); + + sizesByPriority.forEach(size => { + if (!maxPrioritySize) { + if (sizesAsString.indexOf(sizeToString(size)) !== -1) { + maxPrioritySize = size; + } + } + }); + + if (maxPrioritySize) { + return maxPrioritySize; + } else { + return sizes[0]; + } +} + registerBidder(spec); diff --git a/test/spec/modules/otmBidAdapter_spec.js b/test/spec/modules/otmBidAdapter_spec.js index 0fe81a512cb..f3a98d43e57 100644 --- a/test/spec/modules/otmBidAdapter_spec.js +++ b/test/spec/modules/otmBidAdapter_spec.js @@ -29,6 +29,44 @@ describe('otmBidAdapterTests', function () { expect(req_data.bidid).to.equal('bid1234'); }); + it('validate_best_size_select', function () { + // when: + let bidRequestData = [{ + bidId: 'bid1234', + bidder: 'otm', + params: { + tid: '123', + bidfloor: 20 + }, + sizes: [[300, 500], [300, 600], [240, 400], [300, 50]] + }]; + + let request = spec.buildRequests(bidRequestData); + let req_data = request[0].data; + + // then: + expect(req_data.w).to.equal(240); + expect(req_data.h).to.equal(400); + + // when: + bidRequestData = [{ + bidId: 'bid1234', + bidder: 'otm', + params: { + tid: '123', + bidfloor: 20 + }, + sizes: [[200, 240], [400, 440]] + }]; + + request = spec.buildRequests(bidRequestData); + req_data = request[0].data; + + // then: + expect(req_data.w).to.equal(200); + expect(req_data.h).to.equal(240); + }); + it('validate_response_params', function () { let bidRequestData = { data: { From 966cff186400e93316788d2de0bd9f6f6d813123 Mon Sep 17 00:00:00 2001 From: adxcgcom <31470944+adxcgcom@users.noreply.github.com> Date: Mon, 18 Mar 2019 14:51:40 +0000 Subject: [PATCH 1084/1594] adxcgBidAdapter native update (#3647) * adxcgBidAdapter native fix * removed comment --- modules/adxcgBidAdapter.js | 21 ++++++++++++++++++--- test/spec/modules/adxcgBidAdapter_spec.js | 18 +++++++++++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/modules/adxcgBidAdapter.js b/modules/adxcgBidAdapter.js index 73b70fe8e72..23808fa3be7 100644 --- a/modules/adxcgBidAdapter.js +++ b/modules/adxcgBidAdapter.js @@ -10,6 +10,7 @@ import includes from 'core-js/library/fn/array/includes' * 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 */ const BIDDER_CODE = 'adxcg' @@ -210,8 +211,10 @@ export const spec = { let nativeResponse = serverResponseOneItem.nativeResponse bid['native'] = { - clickUrl: encodeURIComponent(nativeResponse.link.url), - impressionTrackers: nativeResponse.imptrackers + clickUrl: nativeResponse.link.url, + impressionTrackers: nativeResponse.imptrackers, + clickTrackers: nativeResponse.clktrackers, + javascriptTrackers: nativeResponse.jstrackers } nativeResponse.assets.forEach(asset => { @@ -220,7 +223,19 @@ export const spec = { } if (asset.img && asset.img.url) { - bid['native'].image = asset.img.url + let nativeImage = {} + nativeImage.url = asset.img.url + nativeImage.height = asset.img.h + nativeImage.width = asset.img.w + bid['native'].image = nativeImage + } + + if (asset.icon && asset.icon.url) { + let nativeIcon = {} + nativeIcon.url = asset.icon.url + nativeIcon.height = asset.icon.h + nativeIcon.width = asset.icon.w + bid['native'].icon = nativeIcon } if (asset.data && asset.data.label === 'DESC' && asset.data.value) { diff --git a/test/spec/modules/adxcgBidAdapter_spec.js b/test/spec/modules/adxcgBidAdapter_spec.js index 71fb7bc3776..0277e0ab964 100644 --- a/test/spec/modules/adxcgBidAdapter_spec.js +++ b/test/spec/modules/adxcgBidAdapter_spec.js @@ -235,6 +235,14 @@ describe('AdxcgAdapter', function () { 'label': 'SPONSORED', 'value': 'sponsoredByContent' } + }, { + 'id': 5, + 'required': 0, + 'icon': { + 'url': 'iconContent', + 'w': 400, + 'h': 400 + } }], 'link': { 'url': 'linkContent' @@ -307,7 +315,15 @@ describe('AdxcgAdapter', function () { 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).to.equal('imageContent') + + 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') }) From f584653a685ec910cea79e0d50c5c2ac31a321d6 Mon Sep 17 00:00:00 2001 From: trchandraprakash <47793448+trchandraprakash@users.noreply.github.com> Date: Mon, 18 Mar 2019 08:04:52 -0700 Subject: [PATCH 1085/1594] Update Bidder Code (#3646) --- modules/advangelistsBidAdapter.js | 2 +- modules/advangelistsBidAdapter.md | 4 ++-- .../modules/advangelistsBidAdapter_spec.js | 18 +++++++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) mode change 100644 => 100755 modules/advangelistsBidAdapter.js mode change 100644 => 100755 modules/advangelistsBidAdapter.md mode change 100644 => 100755 test/spec/modules/advangelistsBidAdapter_spec.js diff --git a/modules/advangelistsBidAdapter.js b/modules/advangelistsBidAdapter.js old mode 100644 new mode 100755 index 926be211649..e98de8dd77e --- a/modules/advangelistsBidAdapter.js +++ b/modules/advangelistsBidAdapter.js @@ -7,7 +7,7 @@ import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; const ADAPTER_VERSION = '1.0'; -const BIDDER_CODE = 'avng'; +const BIDDER_CODE = 'advangelists'; export const VIDEO_ENDPOINT = '//nep.advangelists.com/xp/get?pubid=';// 0cf8d6d643e13d86a5b6374148a4afac'; export const BANNER_ENDPOINT = '//nep.advangelists.com/xp/get?pubid=';// 0cf8d6d643e13d86a5b6374148a4afac'; diff --git a/modules/advangelistsBidAdapter.md b/modules/advangelistsBidAdapter.md old mode 100644 new mode 100755 index 14e2befd48f..1765241eaf3 --- a/modules/advangelistsBidAdapter.md +++ b/modules/advangelistsBidAdapter.md @@ -24,7 +24,7 @@ var displayAdUnit = [ [320, 50] ], bids: [{ - bidder: 'avng', + bidder: 'advangelists', params: { pubid: '0cf8d6d643e13d86a5b6374148a4afac', placement: 1234 @@ -47,7 +47,7 @@ var videoAdUnit = { }, bids: [ { - bidder: 'avng', + bidder: 'advangelists', params: { pubid: '8537f00948fc37cc03c5f0f88e198a76', placement: 1234, diff --git a/test/spec/modules/advangelistsBidAdapter_spec.js b/test/spec/modules/advangelistsBidAdapter_spec.js old mode 100644 new mode 100755 index f7a49ef995f..fbdfc9f30ee --- a/test/spec/modules/advangelistsBidAdapter_spec.js +++ b/test/spec/modules/advangelistsBidAdapter_spec.js @@ -7,9 +7,9 @@ describe('advangelistsBidAdapter', function () { let bidRequestsVid; beforeEach(function () { - bidRequests = [{'bidder': 'avng', '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'}]; + 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': 'avng', 'params': {'pubid': '8537f00948fc37cc03c5f0f88e198a76', 'placement': 1234, 'video': {'id': 123, 'skip': 1, 'mimes': ['video/mp4', 'application/javascript'], 'playbackmethod': [2, 6], 'maxduration': 30}}, 'crumbs': {'pubcid': '979fde13-c71e-4ac2-98b7-28c90f99b449'}, 'mediaTypes': {'video': {'playerSize': [[320, 480]], 'context': 'instream'}}, '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'}]; + bidRequestsVid = [{'bidder': 'advangelists', 'params': {'pubid': '8537f00948fc37cc03c5f0f88e198a76', 'placement': 1234, 'video': {'id': 123, 'skip': 1, 'mimes': ['video/mp4', 'application/javascript'], 'playbackmethod': [2, 6], 'maxduration': 30}}, 'crumbs': {'pubcid': '979fde13-c71e-4ac2-98b7-28c90f99b449'}, 'mediaTypes': {'video': {'playerSize': [[320, 480]], 'context': 'instream'}}, '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 () { @@ -86,14 +86,14 @@ describe('advangelistsBidAdapter', function () { it('should return valid video bid responses', function () { let _mediaTypes = VIDEO; - const avngbidreqVid = {'bidRequest': {'mediaTypes': {'video': {'w': 320, 'h': 480}}}}; + 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.ar'], '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 }, avngbidreqVid); + const bidResponseVid = spec.interpretResponse({ body: serverResponseVid }, advangelistsbidreqVid); delete bidResponseVid['vastUrl']; delete bidResponseVid['ad']; expect(bidResponseVid).to.deep.equal({ requestId: bidRequestsVid[0].bidId, - bidderCode: 'avng', + bidderCode: 'advangelists', creativeId: serverResponseVid.seatbid[0].bid[0].crid, cpm: serverResponseVid.seatbid[0].bid[0].price, width: serverResponseVid.seatbid[0].bid[0].w, @@ -106,10 +106,10 @@ describe('advangelistsBidAdapter', function () { }); it('should return valid banner bid responses', function () { - const avngbidreq = {bids: {}}; + const advangelistsbidreq = {bids: {}}; bidRequests.forEach(bid => { let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); - avngbidreq.bids[bid.bidId] = {mediaTypes: _mediaTypes, + 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] @@ -117,11 +117,11 @@ describe('advangelistsBidAdapter', function () { }); const serverResponse = {'id': '2aa73f571eaf29', 'seatbid': [{'bid': [{'id': '2c5e8a1a84522d', 'impid': '2c5e8a1a84522d', 'price': 0.81, 'adid': 'abcde-12345', 'nurl': '', 'adm': '
', 'adomain': ['advertiserdomain.com'], 'iurl': '', 'cid': 'campaign1', 'crid': 'abcde-12345', 'w': 300, 'h': 250}], 'seat': '19513bcfca8006'}], 'bidid': '19513bcfca8006', 'cur': 'USD', 'w': 300, 'h': 250}; - const bidResponse = spec.interpretResponse({ body: serverResponse }, avngbidreq); + const bidResponse = spec.interpretResponse({ body: serverResponse }, advangelistsbidreq); expect(bidResponse).to.deep.equal({ requestId: bidRequests[0].bidId, ad: serverResponse.seatbid[0].bid[0].adm, - bidderCode: 'avng', + bidderCode: 'advangelists', creativeId: serverResponse.seatbid[0].bid[0].crid, cpm: serverResponse.seatbid[0].bid[0].price, width: serverResponse.seatbid[0].bid[0].w, From 70d28081623555d0af881ea3727bc072a3858778 Mon Sep 17 00:00:00 2001 From: Kelvin Chappell Date: Mon, 18 Mar 2019 20:45:55 +0000 Subject: [PATCH 1086/1594] Add brand ID to OpenX bid responses (#3630) --- modules/openxBidAdapter.js | 5 +++++ test/spec/modules/openxBidAdapter_spec.js | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index e465e44b25b..4671f054042 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -116,6 +116,11 @@ function createBannerBidResponses(oxResponseObj, {bids, startTime}) { } bidResponse.ts = adUnit.ts; + bidResponse.meta = {}; + if (adUnit.brand_id) { + bidResponse.meta.brandId = adUnit.brand_id; + } + bidResponses.push(bidResponse); registerBeacon(BANNER, adUnit, startTime); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 6ef04ddb9d9..8e12a3bb7e4 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1190,6 +1190,10 @@ describe('OpenxAdapter', function () { expect(bid.ts).to.equal(adUnitOverride.ts); }); + it('should return a brand ID', function () { + expect(bid.meta.brandId).to.equal(DEFAULT_TEST_ARJ_AD_UNIT.brand_id); + }); + it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequest); From 4fd7c474399ab86712c822bbe843e616b6fa6031 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Mon, 18 Mar 2019 17:14:49 -0400 Subject: [PATCH 1087/1594] Sonobi - Analytics Adapter (#3615) * Initial release of Sonobi Analytics adapter. * Removed withCredentials on the sendData requests. Improved unit tests * unit tests working. * remove unneeded array.from --- modules/sonobiAnalyticsAdapter.js | 277 ++++++++++++++++++ modules/sonobiAnalyticsAdapter.md | 24 ++ .../modules/sonobiAnalyticsAdapter_spec.js | 89 ++++++ 3 files changed, 390 insertions(+) create mode 100644 modules/sonobiAnalyticsAdapter.js create mode 100644 modules/sonobiAnalyticsAdapter.md create mode 100644 test/spec/modules/sonobiAnalyticsAdapter_spec.js diff --git a/modules/sonobiAnalyticsAdapter.js b/modules/sonobiAnalyticsAdapter.js new file mode 100644 index 00000000000..ab110cb4d01 --- /dev/null +++ b/modules/sonobiAnalyticsAdapter.js @@ -0,0 +1,277 @@ +import adapter from '../src/AnalyticsAdapter'; +import CONSTANTS from '../src/constants.json'; +import adapterManager from '../src/adapterManager'; +import {ajaxBuilder} from '../src/ajax'; + +const utils = require('../src/utils'); +let ajax = ajaxBuilder(0); + +const DEFAULT_EVENT_URL = 'apex.go.sonobi.com/keymaker'; +const analyticsType = 'endpoint'; +const QUEUE_TIMEOUT_DEFAULT = 200; +const { + EVENTS: { + AUCTION_INIT, + AUCTION_END, + BID_REQUESTED, + BID_ADJUSTMENT, + BIDDER_DONE, + BID_WON, + BID_RESPONSE, + BID_TIMEOUT + } +} = CONSTANTS; + +let initOptions = {}; +let auctionCache = {}; +let auctionTtl = 60 * 60 * 1000; + +function deleteOldAuctions() { + for (let auctionId in auctionCache) { + let auction = auctionCache[auctionId]; + if (Date.now() - auction.start > auctionTtl) { + delete auctionCache[auctionId]; + } + } +} + +function buildAuctionEntity(args) { + return { + 'id': args.auctionId, + 'start': args.timestamp, + 'timeout': args.timeout, + 'adUnits': {}, + 'stats': {}, + 'queue': [], + 'qTimeout': false + }; +} +function buildAdUnit(data) { + return `/${initOptions.pubId}/${initOptions.siteId}/${data.adUnitCode.toLowerCase()}`; +} +function getLatency(data) { + if (!data.responseTimestamp) { + return -1; + } else { + return data.responseTimestamp - data.requestTimestamp; + } +} +function getBid(data) { + if (data.cpm) { + return Math.round(data.cpm * 100); + } else { + return 0; + } +} +function buildItem(data, response, phase = 1) { + let size = data.width ? {width: data.width, height: data.height} : {width: data.sizes[0][0], height: data.sizes[0][1]}; + return { + 'bidid': data.bidId || data.requestId, + 'p': phase, + 'buyerid': data.bidder.toLowerCase(), + 'bid': getBid(data), + 'adunit_code': buildAdUnit(data), + 's': `${size.width}x${size.height}`, + 'latency': getLatency(data), + 'response': response, + 'jsLatency': getLatency(data), + 'buyername': data.bidder.toLowerCase() + }; +} +function sendQueue(auctionId) { + let auction = auctionCache[auctionId]; + let data = auction.queue; + auction.queue = []; + auction.qTimeout = false; + sonobiAdapter.sendData(auction, data); +} +function addToAuctionQueue(auctionId, id) { + let auction = auctionCache[auctionId]; + auction.queue = auction.queue.filter((item) => { + if (item.bidid !== id) { return true; } + return auction.stats[id].data.p !== item.p; + }); + auction.queue.push(utils.deepClone(auction.stats[id].data)); + if (!auction.qTimeout) { + auction.qTimeout = setTimeout(() => { + sendQueue(auctionId); + }, initOptions.delay) + } +} +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]); + return auction.stats[id]; +} + +function handleOtherEvents(eventType, args) { + logInfo('Other Event: ' + eventType, args); +} + +function handlerAuctionInit(args) { + auctionCache[args.auctionId] = buildAuctionEntity(args); + deleteOldAuctions(); + logInfo('Auction Init', args); +} +function handlerBidRequested(args) { + let auction = auctionCache[args.auctionId]; + let data = []; + let phase = 1; + let response = 1; + args.bids.forEach(function (bidRequest) { + auction = auctionCache[bidRequest.auctionId] + let built = buildItem(bidRequest, response, phase); + auction.stats[built.bidid] = {id: built.bidid, adUnitCode: bidRequest.adUnitCode, data: built}; + addToAuctionQueue(args.auctionId, built.bidid); + }) + + logInfo('Bids Requested ', data); +} + +function handlerBidAdjustment(args) { + logInfo('Bid Adjustment', args); +} +function handlerBidderDone(args) { + logInfo('Bidder Done', args); +} + +function handlerAuctionEnd(args) { + let winners = {}; + args.bidsReceived.forEach((bid) => { + if (!winners[bid.adUnitCode]) { + winners[bid.adUnitCode] = {bidId: bid.requestId, cpm: bid.cpm}; + } else if (winners[bid.adUnitCode].cpm < bid.cpm) { + winners[bid.adUnitCode] = {bidId: bid.requestId, cpm: bid.cpm}; + } + }) + args.adUnitCodes.forEach((adUnitCode) => { + if (winners[adUnitCode]) { + let bidId = winners[adUnitCode].bidId; + updateBidStats(args.auctionId, bidId, {response: 4}); + } + }) + 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); +} +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); +} +function handlerBidTimeout(args) { + let {auctionId, bidId} = 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}), { + track({eventType, args}) { + switch (eventType) { + case AUCTION_INIT: + handlerAuctionInit(args); + break; + case BID_REQUESTED: + handlerBidRequested(args); + break; + case BID_ADJUSTMENT: + handlerBidAdjustment(args); + break; + case BIDDER_DONE: + handlerBidderDone(args); + break; + case AUCTION_END: + handlerAuctionEnd(args); + break; + case BID_WON: + handlerBidWon(args); + break; + case BID_RESPONSE: + handlerBidResponse(args); + break; + case BID_TIMEOUT: + handlerBidTimeout(args); + break; + default: + handleOtherEvents(eventType, args); + break; + } + }, + +}); + +sonobiAdapter.originEnableAnalytics = sonobiAdapter.enableAnalytics; + +sonobiAdapter.enableAnalytics = function (config) { + if (this.initConfig(config)) { + logInfo('Analytics adapter enabled', initOptions); + sonobiAdapter.originEnableAnalytics(config); + } +}; + +sonobiAdapter.initConfig = function (config) { + let isCorrectConfig = true; + initOptions = {}; + 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'); + isCorrectConfig = false; + } + if (!initOptions.siteId) { + logError('"options.siteId" is empty'); + isCorrectConfig = false; + } + + initOptions.server = DEFAULT_EVENT_URL; + initOptions.host = initOptions.options.host || window.location.hostname; + this.initOptions = initOptions; + return isCorrectConfig; +}; + +sonobiAdapter.getOptions = function () { + return initOptions; +}; + +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); }, + JSON.stringify(data), + { + method: 'POST', + // withCredentials: true, + contentType: 'text/plain' + } + ); +} + +function logInfo(message, meta) { + utils.logInfo(buildLogMessage(message), meta); +} + +function logError(message) { + utils.logError(buildLogMessage(message)); +} + +function buildLogMessage(message) { + return 'Sonobi Prebid Analytics: ' + message; +} + +adapterManager.registerAnalyticsAdapter({ + adapter: sonobiAdapter, + code: 'sonobi' +}); + +export default sonobiAdapter; diff --git a/modules/sonobiAnalyticsAdapter.md b/modules/sonobiAnalyticsAdapter.md new file mode 100644 index 00000000000..1ef46bac833 --- /dev/null +++ b/modules/sonobiAnalyticsAdapter.md @@ -0,0 +1,24 @@ +# Overview + +``` +Module Name: Sonobi Analytics Adapter +Module Type: Analytics Adapter +Maintainer: apex@sonobi.com +``` + +# Description + +Module that connects to Sonobi's Analytics service + +# Test Parameters +``` + + pbjs.enableAnalytics({ + provider: 'sonobi', + options: { + pubId: 'ffBB352', + siteId: 57463, + delay: 300 + } + }); +``` diff --git a/test/spec/modules/sonobiAnalyticsAdapter_spec.js b/test/spec/modules/sonobiAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..389dfee34f9 --- /dev/null +++ b/test/spec/modules/sonobiAnalyticsAdapter_spec.js @@ -0,0 +1,89 @@ +import sonobiAnalytics from 'modules/sonobiAnalyticsAdapter'; +import {expect} from 'chai'; +let events = require('src/events'); +let adapterManager = require('src/adapterManager').default; +let constants = require('src/constants.json'); + +describe('Sonobi Prebid Analytic', function () { + let xhr; + let requests = []; + var clock; + + describe('enableAnalytics', function () { + beforeEach(function () { + requests = []; + xhr = sinon.useFakeXMLHttpRequest(); + xhr.onCreate = request => requests.push(request); + sinon.stub(events, 'getEvents').returns([]); + clock = sinon.useFakeTimers(Date.now()); + }); + + afterEach(function () { + xhr.restore(); + events.getEvents.restore(); + clock.restore(); + }); + + after(function () { + sonobiAnalytics.disableAnalytics(); + }); + + it('should catch all events', function (done) { + const initOptions = { + pubId: 'A3B254F', + siteId: '1234', + delay: 100 + }; + + sonobiAnalytics.enableAnalytics(initOptions) + + const bid = { + bidderCode: 'sonobi_test_bid', + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '1234', + auctionId: '13', + responseTimestamp: 1496410856397, + requestTimestamp: 1496410856295, + cpm: 1.13, + bidder: 'sonobi', + adUnitCode: 'dom-sample-id', + timeToRespond: 100, + placementCode: 'placementtest' + }; + + // Step 1: Initialize adapter + adapterManager.enableAnalytics({ + provider: 'sonobi', + options: initOptions + }); + + // Step 2: Send init auction event + events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions, auctionId: '13', timestamp: Date.now()}); + + expect(sonobiAnalytics.initOptions).to.have.property('pubId', 'A3B254F'); + expect(sonobiAnalytics.initOptions).to.have.property('siteId', '1234'); + expect(sonobiAnalytics.initOptions).to.have.property('delay', 100); + // Step 3: Send bid requested event + events.emit(constants.EVENTS.BID_REQUESTED, { bids: [bid], auctionId: '13' }); + + // Step 4: Send bid response event + events.emit(constants.EVENTS.BID_RESPONSE, bid); + + // Step 5: Send bid won event + events.emit(constants.EVENTS.BID_WON, bid); + + // Step 6: Send bid timeout event + events.emit(constants.EVENTS.BID_TIMEOUT, {auctionId: '13'}); + + // Step 7: Send auction end event + events.emit(constants.EVENTS.AUCTION_END, {auctionId: '13', bidsReceived: [bid]}); + + clock.tick(5000); + expect(requests).to.have.length(1); + expect(JSON.parse(requests[0].requestBody)).to.have.length(3) + done(); + }); + }); +}); From 63c1d366ce24bab9b2e14780d0005551826ab3f9 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 19 Mar 2019 10:06:14 -0700 Subject: [PATCH 1088/1594] add 'hb_cache_host' and 'hb_cache_path' targeting for video bids using cache (#3652) --- src/auction.js | 114 +++++++++++++++---------------- src/constants.json | 4 +- test/spec/auctionmanager_spec.js | 16 +++++ 3 files changed, 76 insertions(+), 58 deletions(-) diff --git a/src/auction.js b/src/auction.js index bf3f1bb1b71..10594dc3f32 100644 --- a/src/auction.js +++ b/src/auction.js @@ -48,7 +48,8 @@ * @property {function(): void} callBids - sends requests to all adapters for bids */ -import { uniques, flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest } from './utils'; +import { uniques, flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest, getValue } from './utils'; +import { parse as parseURL } from './url'; import { getPriceBucketString } from './cpmBucketManager'; import { getNativeTargeting } from './native'; import { getCacheUrl, store } from './videoCache'; @@ -505,6 +506,19 @@ function setupBidTargeting(bidObject, bidderRequest) { } export function getStandardBidderSettings(mediaType) { + // 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); + } + }; + } // Use the config value 'mediaTypeGranularity' if it has been set for mediaType, else use 'priceGranularity' const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${mediaType}`); const granularity = (typeof mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); @@ -514,68 +528,54 @@ export function getStandardBidderSettings(mediaType) { bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; } if (!bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + const TARGETING_KEYS = CONSTANTS.TARGETING_KEYS; + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [ - { - key: CONSTANTS.TARGETING_KEYS.BIDDER, - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: CONSTANTS.TARGETING_KEYS.AD_ID, - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, - val: function (bidResponse) { - if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { - return bidResponse.pbAg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { - return bidResponse.pbDg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { - return bidResponse.pbLg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { - return bidResponse.pbMg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { - return bidResponse.pbHg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { - return bidResponse.pbCg; - } - } - }, { - key: CONSTANTS.TARGETING_KEYS.SIZE, - val: function (bidResponse) { - return bidResponse.size; - } - }, { - key: CONSTANTS.TARGETING_KEYS.DEAL, - val: function (bidResponse) { - return bidResponse.dealId; - } - }, - { - key: CONSTANTS.TARGETING_KEYS.SOURCE, - val: function (bidResponse) { - return bidResponse.source; + createKeyVal(TARGETING_KEYS.BIDDER, 'bidderCode'), + createKeyVal(TARGETING_KEYS.AD_ID, 'adId'), + createKeyVal(TARGETING_KEYS.PRICE_BUCKET, function(bidResponse) { + if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { + return bidResponse.pbAg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { + return bidResponse.pbDg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { + return bidResponse.pbLg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { + return bidResponse.pbMg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { + return bidResponse.pbHg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { + return bidResponse.pbCg; } - }, - { - key: CONSTANTS.TARGETING_KEYS.FORMAT, - val: function (bidResponse) { - return bidResponse.mediaType; - } - }, + }), + createKeyVal(TARGETING_KEYS.SIZE, 'size'), + createKeyVal(TARGETING_KEYS.DEAL, 'dealId'), + createKeyVal(TARGETING_KEYS.SOURCE, 'source'), + createKeyVal(TARGETING_KEYS.FORMAT, 'mediaType'), ] if (mediaType === 'video') { - [CONSTANTS.TARGETING_KEYS.UUID, CONSTANTS.TARGETING_KEYS.CACHE_ID].forEach(item => { - bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push({ - key: item, - val: function val(bidResponse) { - return bidResponse.videoCacheKey; - } - }) + // Adding hb_uuid + hb_cache_id + [TARGETING_KEYS.UUID, TARGETING_KEYS.CACHE_ID].forEach(targetingKey => { + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push(createKeyVal(targetingKey, 'videoCacheKey')); }); + + // Adding hb_cache_host + hb_cache_path + if (config.getConfig('cache.url')) { + const urlInfo = parseURL(config.getConfig('cache.url')); + + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push(createKeyVal(TARGETING_KEYS.CACHE_HOST, function(bidResponse) { + return utils.deepAccess(bidResponse, `adserverTargeting.${TARGETING_KEYS.CACHE_HOST}`) + ? bidResponse.adserverTargeting[TARGETING_KEYS.CACHE_HOST] + : urlInfo.hostname; + })); + + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push(createKeyVal(TARGETING_KEYS.CACHE_PATH, function(bidResponse) { + return utils.deepAccess(bidResponse, `adserverTargeting.${TARGETING_KEYS.CACHE_PATH}`) + ? bidResponse.adserverTargeting[TARGETING_KEYS.CACHE_PATH] + : urlInfo.pathname; + })); + } } } return bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; diff --git a/src/constants.json b/src/constants.json index 1a78e376150..b3a0e4a9ce6 100644 --- a/src/constants.json +++ b/src/constants.json @@ -64,7 +64,9 @@ "SOURCE": "hb_source", "FORMAT": "hb_format", "UUID": "hb_uuid", - "CACHE_ID": "hb_cache_id" + "CACHE_ID": "hb_cache_id", + "CACHE_HOST": "hb_cache_host", + "CACHE_PATH": "hb_cache_path" }, "NATIVE_KEYS": { "title": "hb_native_title", diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index aab1da11653..eb1310e523c 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -142,6 +142,8 @@ describe('auctionmanager.js', function () { if (bid.mediaType === 'video') { expected[ CONSTANTS.TARGETING_KEYS.UUID ] = bid.videoCacheKey; expected[ CONSTANTS.TARGETING_KEYS.CACHE_ID ] = bid.videoCacheKey; + expected[ CONSTANTS.TARGETING_KEYS.CACHE_HOST ] = 'prebid.adnxs.com'; + expected[ CONSTANTS.TARGETING_KEYS.CACHE_PATH ] = '/pbc/v1/cache'; } if (!keys) { return expected; @@ -167,6 +169,11 @@ describe('auctionmanager.js', function () { }); it('No bidder level configuration defined - default for video', function () { + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); $$PREBID_GLOBAL$$.bidderSettings = {}; let videoBid = utils.deepClone(bid); videoBid.mediaType = 'video'; @@ -229,6 +236,11 @@ describe('auctionmanager.js', function () { }); it('Custom configuration for all bidders with video bid', function () { + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); let videoBid = utils.deepClone(bid); videoBid.mediaType = 'video'; videoBid.videoCacheKey = 'abc123def'; @@ -288,6 +300,10 @@ describe('auctionmanager.js', function () { }; let expected = getDefaultExpected(videoBid); + // Since we are effectively overwriting the bidderSettings above... + // we are not including the new host / path logic. So we will expect them to be gone. + delete expected['hb_cache_host']; + delete expected['hb_cache_path']; let response = getKeyValueTargetingPairs(videoBid.bidderCode, videoBid); assert.deepEqual(response, expected); }); From 9e0f11f4679ac7085766bbc3492b3bb07e2b4986 Mon Sep 17 00:00:00 2001 From: Michael Callari Date: Tue, 19 Mar 2019 13:13:00 -0400 Subject: [PATCH 1089/1594] Adding Optimera/AppNexus workaround documentation #3597 (#3598) --- modules/optimeraBidAdapter.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/modules/optimeraBidAdapter.md b/modules/optimeraBidAdapter.md index 84df1d1ad07..909c0a46cd6 100644 --- a/modules/optimeraBidAdapter.md +++ b/modules/optimeraBidAdapter.md @@ -34,3 +34,23 @@ Module that adds ad placement visibility scores for DFP. }] }]; ``` + +# AppNexus Issue +There is an issue where the plugin sometimes doesn't return impressions with AppNexus. + +There is an open issue here: [#3597](https://github.com/prebid/Prebid.js/issues/3597) + +## Configuration Workaround + +Optimera's configuration requires the use of size 0,0 which, in some instances, causes the AppNexus ad server to respond to ad requests but not fill impressions. AppNexus and vendors using the AppNexus ad server should monitor 3rd party numbers to ensure there is no decline in fill rate. + +Configuration Example: + +``` +code: ‘leaderboard', +mediaTypes: { + banner: { + sizes: [[970, 250],[970, 90],[970, 66],[728, 90],[320, 50],[320, 100],[300, 250],[0, 0]], + } +} +``` From b5b27aa0ad6aba4b23e6e99bd5f9044bcc9af2eb Mon Sep 17 00:00:00 2001 From: Kelvin Chappell Date: Tue, 19 Mar 2019 17:13:40 +0000 Subject: [PATCH 1090/1594] Add buyer data to Pubmatic bid responses (#3619) --- modules/pubmaticBidAdapter.js | 11 +++++++++++ test/spec/modules/pubmaticBidAdapter_spec.js | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 9044597c742..d80d6c5c810 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -977,6 +977,17 @@ export const spec = { newBid['dealChannel'] = dealChannelValues[bid.ext.deal_channel] || null; } + newBid.meta = {}; + if (bid.ext && bid.ext.dspid) { + newBid.meta.networkId = bid.ext.dspid; + } + if (bid.ext && bid.ext.advid) { + newBid.meta.buyerId = bid.ext.advid; + } + if (bid.adomain && bid.adomain.length > 0) { + newBid.meta.clickUrl = bid.adomain[0]; + } + bidResponses.push(newBid); }); }); diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 912a6696bdd..0042ef5211e 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -281,10 +281,13 @@ describe('PubMatic adapter', function () { 'impid': '22bddb28db77d', 'price': 1.3, 'adm': 'image3.pubmatic.com Layer based creative', + 'adomain': ['blackrock.com'], 'h': 250, 'w': 300, 'ext': { - 'deal_channel': 6 + 'deal_channel': 6, + 'advid': 976, + 'dspid': 123 } }] }, { @@ -293,10 +296,13 @@ describe('PubMatic adapter', function () { 'impid': '22bddb28db77e', 'price': 1.7, 'adm': 'image3.pubmatic.com Layer based creative', + 'adomain': ['hivehome.com'], 'h': 250, 'w': 300, 'ext': { - 'deal_channel': 5 + 'deal_channel': 5, + 'advid': 832, + 'dspid': 422 } }] }] @@ -1323,6 +1329,9 @@ describe('PubMatic adapter', function () { expect(response[0].currency).to.equal('USD'); expect(response[0].netRevenue).to.equal(false); expect(response[0].ttl).to.equal(300); + expect(response[0].meta.networkId).to.equal(123); + expect(response[0].meta.buyerId).to.equal(976); + expect(response[0].meta.clickUrl).to.equal('blackrock.com'); expect(response[0].referrer).to.include(data.site.ref); expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm); @@ -1339,6 +1348,9 @@ describe('PubMatic adapter', function () { expect(response[1].currency).to.equal('USD'); expect(response[1].netRevenue).to.equal(false); expect(response[1].ttl).to.equal(300); + expect(response[1].meta.networkId).to.equal(422); + expect(response[1].meta.buyerId).to.equal(832); + expect(response[1].meta.clickUrl).to.equal('hivehome.com'); expect(response[1].referrer).to.include(data.site.ref); expect(response[1].ad).to.equal(bidResponses.body.seatbid[1].bid[0].adm); }); From 90cefb8a5257fb51a7ee6e7cf76b4540929fa5d1 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 19 Mar 2019 10:44:10 -0700 Subject: [PATCH 1091/1594] Revert "add 'hb_cache_host' and 'hb_cache_path' targeting for video bids using cache (#3652)" (#3653) This reverts commit 63c1d366ce24bab9b2e14780d0005551826ab3f9. --- src/auction.js | 114 +++++++++++++++---------------- src/constants.json | 4 +- test/spec/auctionmanager_spec.js | 16 ----- 3 files changed, 58 insertions(+), 76 deletions(-) diff --git a/src/auction.js b/src/auction.js index 10594dc3f32..bf3f1bb1b71 100644 --- a/src/auction.js +++ b/src/auction.js @@ -48,8 +48,7 @@ * @property {function(): void} callBids - sends requests to all adapters for bids */ -import { uniques, flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest, getValue } from './utils'; -import { parse as parseURL } from './url'; +import { uniques, flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest } from './utils'; import { getPriceBucketString } from './cpmBucketManager'; import { getNativeTargeting } from './native'; import { getCacheUrl, store } from './videoCache'; @@ -506,19 +505,6 @@ function setupBidTargeting(bidObject, bidderRequest) { } export function getStandardBidderSettings(mediaType) { - // 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); - } - }; - } // Use the config value 'mediaTypeGranularity' if it has been set for mediaType, else use 'priceGranularity' const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${mediaType}`); const granularity = (typeof mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); @@ -528,54 +514,68 @@ export function getStandardBidderSettings(mediaType) { bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; } if (!bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - const TARGETING_KEYS = CONSTANTS.TARGETING_KEYS; - 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, function(bidResponse) { - if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { - return bidResponse.pbAg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { - return bidResponse.pbDg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { - return bidResponse.pbLg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { - return bidResponse.pbMg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { - return bidResponse.pbHg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { - return bidResponse.pbCg; + { + key: CONSTANTS.TARGETING_KEYS.BIDDER, + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: CONSTANTS.TARGETING_KEYS.AD_ID, + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, + val: function (bidResponse) { + if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { + return bidResponse.pbAg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { + return bidResponse.pbDg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { + return bidResponse.pbLg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { + return bidResponse.pbMg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { + return bidResponse.pbHg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { + return bidResponse.pbCg; + } + } + }, { + key: CONSTANTS.TARGETING_KEYS.SIZE, + val: function (bidResponse) { + return bidResponse.size; + } + }, { + key: CONSTANTS.TARGETING_KEYS.DEAL, + val: function (bidResponse) { + return bidResponse.dealId; + } + }, + { + key: CONSTANTS.TARGETING_KEYS.SOURCE, + val: function (bidResponse) { + return bidResponse.source; } - }), - createKeyVal(TARGETING_KEYS.SIZE, 'size'), - createKeyVal(TARGETING_KEYS.DEAL, 'dealId'), - createKeyVal(TARGETING_KEYS.SOURCE, 'source'), - createKeyVal(TARGETING_KEYS.FORMAT, 'mediaType'), + }, + { + key: CONSTANTS.TARGETING_KEYS.FORMAT, + val: function (bidResponse) { + return bidResponse.mediaType; + } + }, ] if (mediaType === 'video') { - // Adding hb_uuid + hb_cache_id - [TARGETING_KEYS.UUID, TARGETING_KEYS.CACHE_ID].forEach(targetingKey => { - bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push(createKeyVal(targetingKey, 'videoCacheKey')); + [CONSTANTS.TARGETING_KEYS.UUID, CONSTANTS.TARGETING_KEYS.CACHE_ID].forEach(item => { + bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push({ + key: item, + val: function val(bidResponse) { + return bidResponse.videoCacheKey; + } + }) }); - - // Adding hb_cache_host + hb_cache_path - if (config.getConfig('cache.url')) { - const urlInfo = parseURL(config.getConfig('cache.url')); - - bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push(createKeyVal(TARGETING_KEYS.CACHE_HOST, function(bidResponse) { - return utils.deepAccess(bidResponse, `adserverTargeting.${TARGETING_KEYS.CACHE_HOST}`) - ? bidResponse.adserverTargeting[TARGETING_KEYS.CACHE_HOST] - : urlInfo.hostname; - })); - - bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push(createKeyVal(TARGETING_KEYS.CACHE_PATH, function(bidResponse) { - return utils.deepAccess(bidResponse, `adserverTargeting.${TARGETING_KEYS.CACHE_PATH}`) - ? bidResponse.adserverTargeting[TARGETING_KEYS.CACHE_PATH] - : urlInfo.pathname; - })); - } } } return bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; diff --git a/src/constants.json b/src/constants.json index b3a0e4a9ce6..1a78e376150 100644 --- a/src/constants.json +++ b/src/constants.json @@ -64,9 +64,7 @@ "SOURCE": "hb_source", "FORMAT": "hb_format", "UUID": "hb_uuid", - "CACHE_ID": "hb_cache_id", - "CACHE_HOST": "hb_cache_host", - "CACHE_PATH": "hb_cache_path" + "CACHE_ID": "hb_cache_id" }, "NATIVE_KEYS": { "title": "hb_native_title", diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index eb1310e523c..aab1da11653 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -142,8 +142,6 @@ describe('auctionmanager.js', function () { if (bid.mediaType === 'video') { expected[ CONSTANTS.TARGETING_KEYS.UUID ] = bid.videoCacheKey; expected[ CONSTANTS.TARGETING_KEYS.CACHE_ID ] = bid.videoCacheKey; - expected[ CONSTANTS.TARGETING_KEYS.CACHE_HOST ] = 'prebid.adnxs.com'; - expected[ CONSTANTS.TARGETING_KEYS.CACHE_PATH ] = '/pbc/v1/cache'; } if (!keys) { return expected; @@ -169,11 +167,6 @@ describe('auctionmanager.js', function () { }); it('No bidder level configuration defined - default for video', function () { - config.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); $$PREBID_GLOBAL$$.bidderSettings = {}; let videoBid = utils.deepClone(bid); videoBid.mediaType = 'video'; @@ -236,11 +229,6 @@ describe('auctionmanager.js', function () { }); it('Custom configuration for all bidders with video bid', function () { - config.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); let videoBid = utils.deepClone(bid); videoBid.mediaType = 'video'; videoBid.videoCacheKey = 'abc123def'; @@ -300,10 +288,6 @@ describe('auctionmanager.js', function () { }; let expected = getDefaultExpected(videoBid); - // Since we are effectively overwriting the bidderSettings above... - // we are not including the new host / path logic. So we will expect them to be gone. - delete expected['hb_cache_host']; - delete expected['hb_cache_path']; let response = getKeyValueTargetingPairs(videoBid.bidderCode, videoBid); assert.deepEqual(response, expected); }); From c0fdf028761906bb66940aedaffdf701a112c112 Mon Sep 17 00:00:00 2001 From: evanmsmrtb Date: Tue, 19 Mar 2019 12:45:44 -0500 Subject: [PATCH 1092/1594] modules: Implement SmartRTB adapter and spec. (#3575) * modules: Implement SmartRTB adapter and spec. * Fix for-loop syntax to support IE; refactor getDomain out of exported set. --- modules/smartrtbBidAdapter.js | 111 +++++++++++++++++++ modules/smartrtbBidAdapter.md | 34 ++++++ test/spec/modules/smartrtbBidAdapter_spec.js | 109 ++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 modules/smartrtbBidAdapter.js create mode 100644 modules/smartrtbBidAdapter.md create mode 100644 test/spec/modules/smartrtbBidAdapter_spec.js diff --git a/modules/smartrtbBidAdapter.js b/modules/smartrtbBidAdapter.js new file mode 100644 index 00000000000..561ce58e016 --- /dev/null +++ b/modules/smartrtbBidAdapter.js @@ -0,0 +1,111 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +const BIDDER_CODE = 'smartrtb'; + +function getDomain () { + if (!utils.inIframe()) { + return window.location.hostname + } + let origins = window.document.location.ancestorOrigins + if (origins && origins.length > 0) { + return origins[origins.length - 1] + } +} + +export const spec = { + code: BIDDER_CODE, + aliases: ['smrtb'], + isBidRequestValid: function(bid) { + return (bid.params.pubId !== null && + bid.params.medId !== null && + bid.params.zoneId !== null); + }, + buildRequests: function(validBidRequests, bidderRequest) { + let stack = (bidderRequest.refererInfo && + bidderRequest.refererInfo.stack ? bidderRequest.refererInfo + : []) + + const payload = { + start_time: utils.timestamp(), + tmax: 120, + language: window.navigator.userLanguage || window.navigator.language, + site: { + domain: getDomain(), + iframe: !bidderRequest.refererInfo.reachedTop, + url: stack && stack.length > 0 ? [stack.length - 1] : null, + https: (window.location.protocol === 'https:'), + referrer: bidderRequest.refererInfo.referer + }, + imps: [] + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr = { + applies: bidderRequest.gdprConsent.gdprApplies, + consent: bidderRequest.gdprConsent.consentString + }; + } + + for (let x = 0; x < validBidRequests.length; x++) { + let req = validBidRequests[x] + + payload.imps.push({ + pub_id: req.params.pubId, + med_id: req.params.medId, + zone_id: req.params.zoneId, + bid_id: req.bidId, + imp_id: req.transactionId, + sizes: req.sizes, + force_bid: req.params.forceBid + }); + } + + return { + method: 'POST', + url: '//pubs.smrtb.com/json/publisher/prebid', + data: JSON.stringify(payload) + }; + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + let res = serverResponse.body; + if (!res.bids || !res.bids.length) { + return [] + } + + for (let x = 0; x < serverResponse.body.bids.length; x++) { + let bid = serverResponse.body.bids[x] + + bidResponses.push({ + requestId: bid.bid_id, + cpm: bid.cpm, + width: bid.w, + height: bid.h, + ad: bid.html, + ttl: 120, + creativeId: bid.crid, + netRevenue: true, + currency: 'USD' + }) + } + + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = [] + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: '//ads.smrtb.com/sync' + }); + } else if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: '//ads.smrtb.com/sync' + }); + } + return syncs; + } +}; + +registerBidder(spec); diff --git a/modules/smartrtbBidAdapter.md b/modules/smartrtbBidAdapter.md new file mode 100644 index 00000000000..f043e277d0d --- /dev/null +++ b/modules/smartrtbBidAdapter.md @@ -0,0 +1,34 @@ +# Overview + +``` +Module Name: Smart RTB (smrtb.com) Bidder Adapter +Module Type: Bidder Adapter +Maintainer: evanm@smrtb.com +``` + +# Description + +Prebid adapter for Smart RTB. Requires approval and account setup. + +# Test Parameters + +## Web +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "smartrtb", + params: { + pubId: 123, + medId: "m_00a95d003340dbb2fcb8ee668a84fa", + zoneId: "z_261b6c7e7d4d4985393b293cc903d1", + force_bid: true + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/smartrtbBidAdapter_spec.js b/test/spec/modules/smartrtbBidAdapter_spec.js new file mode 100644 index 00000000000..8f1fb9efc1e --- /dev/null +++ b/test/spec/modules/smartrtbBidAdapter_spec.js @@ -0,0 +1,109 @@ +import { expect } from 'chai' +import { spec, _getPlatform } from 'modules/smartrtbBidAdapter' +import { newBidder } from 'src/adapters/bidderFactory' + +describe('SmartRTBBidAdapter', function () { + const adapter = newBidder(spec) + + let bidRequest = { + bidId: '123', + transactionId: '456', + sizes: [[ 300, 250 ]], + params: { + pubId: 123, + medId: 'm_00a95d003340dbb2fcb8ee668a84fa', + zoneId: 'z_261b6c7e7d4d4985393b293cc903d1' + } + } + + describe('codes', function () { + it('should return a bidder code of smartrtb', function () { + expect(spec.code).to.equal('smartrtb') + }) + it('should alias smrtb', function () { + expect(spec.aliases.length > 0 && spec.aliases[0] === 'smrtb').to.be.true + }) + }) + + describe('isBidRequestValid', function () { + it('should return true if all params present', function () { + expect(spec.isBidRequestValid(bidRequest)).to.be.true + }) + + it('should return false if any parameter missing', function () { + expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { pubId: null } }))).to.be.false + expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { medId: null } }))).to.be.false + expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { zoneId: null } }))).to.be.false + }) + }) + + describe('buildRequests', function () { + let req = spec.buildRequests([ bidRequest ], { refererInfo: { } }) + 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 = JSON.parse(req.data) + expect(rdata.imps.length).to.equal(1) + }) + + it('should include all publisher params', function () { + let r = rdata.imps[0] + expect(r.pub_id !== null && r.med_id !== null && r.zone_id !== null).to.be.true + }) + }) + + describe('interpretResponse', function () { + it('should form compliant bid object response', function () { + let res = { + body: { + bids: [{ + bid_id: '123', + cpm: 1.23, + w: 300, + h: 250, + html: 'deadbeef', + crid: 'crid' + }] + } + } + + let ir = spec.interpretResponse(res, bidRequest) + + expect(ir.length).to.equal(1) + + let en = ir[0] + + expect(en.requestId != null && + en.cpm != null && typeof en.cpm === 'number' && + en.width != null && typeof en.width === 'number' && + en.height != null && typeof en.height === 'number' && + en.ad != null && + en.creativeId != null + ).to.be.true + }) + }) + + describe('getUserSyncs', function () { + it('should return iframe sync', function () { + let sync = spec.getUserSyncs({ iframeEnabled: true }) + expect(sync.length).to.equal(1) + expect(sync[0].type === 'iframe') + expect(typeof sync[0].url === 'string') + }) + + it('should return pixel sync', function () { + let sync = spec.getUserSyncs({ pixelEnabled: true }) + expect(sync.length).to.equal(1) + expect(sync[0].type === 'image') + expect(typeof sync[0].url === 'string') + }) + }) +}) From 2163303ece53fcec429a8f284642dd88a39a48b1 Mon Sep 17 00:00:00 2001 From: kusapan Date: Wed, 20 Mar 2019 02:57:44 +0900 Subject: [PATCH 1093/1594] add tmax to BidRequest params (#3626) --- modules/yieldoneBidAdapter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index 487cd3a306d..7abb94736df 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -22,6 +22,7 @@ export const spec = { const referrer = encodeURIComponent(utils.getTopWindowUrl()); const bidId = bidRequest.bidId; const unitCode = bidRequest.adUnitCode; + const timeout = config.getConfig('bidderTimeout'); const payload = { v: 'hb1', p: placementId, @@ -29,6 +30,7 @@ export const spec = { r: referrer, uid: bidId, uc: unitCode, + tmax: timeout, t: 'i' }; From 633b9b966ba0b5545937edb53d467f0bd468043f Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 19 Mar 2019 14:30:45 -0400 Subject: [PATCH 1094/1594] Prebid 2.7.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 82f92b5045f..84eb70695e8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.7.0-pre", + "version": "2.7.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 6cd91f980cd64686cc7a76edd6c9f1cd39d13020 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 19 Mar 2019 14:49:25 -0400 Subject: [PATCH 1095/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 84eb70695e8..d73d9014d99 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.7.0", + "version": "2.8.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 97eb9d63a12f1a020ab208120c56071ba6bef17b Mon Sep 17 00:00:00 2001 From: lambdarho Date: Thu, 21 Mar 2019 08:00:35 -0400 Subject: [PATCH 1096/1594] OpenX: Bugfix/update custom floors (#3658) * [BID-3477] - Update customFloor value * [BID-3477] - Update test spec --- modules/openxBidAdapter.js | 2 +- test/spec/modules/openxBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 4671f054042..52a97a98952 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -278,7 +278,7 @@ function buildOXBannerRequest(bids, bidderRequest) { let hasCustomFloor = false; bids.forEach(function (bid) { if (bid.params.customFloor) { - customFloorsForAllBids.push(bid.params.customFloor * 1000); + customFloorsForAllBids.push((Math.round(bid.params.customFloor * 100) / 100) * 1000); hasCustomFloor = true; } else { customFloorsForAllBids.push(0); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 8e12a3bb7e4..468d9cc33a7 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -550,7 +550,7 @@ describe('OpenxAdapter', function () { params: { 'unit': '12345678', 'delDomain': 'test-del-domain', - 'customFloor': 1.5 + 'customFloor': 1.500001 } } ); From 460740b32f25cbd5740f2b5e59356e199ab22fc9 Mon Sep 17 00:00:00 2001 From: Sergio Date: Fri, 22 Mar 2019 18:23:46 +0100 Subject: [PATCH 1097/1594] Adpone Bid Adapter + test (#3663) --- modules/adponeBidAdapter.js | 66 +++++++++++++ modules/adponeBidAdapter.md | 32 +++++++ test/spec/modules/adponeBidAdapter_spec.js | 102 +++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 modules/adponeBidAdapter.js create mode 100644 modules/adponeBidAdapter.md create mode 100644 test/spec/modules/adponeBidAdapter_spec.js diff --git a/modules/adponeBidAdapter.js b/modules/adponeBidAdapter.js new file mode 100644 index 00000000000..cd30f663b16 --- /dev/null +++ b/modules/adponeBidAdapter.js @@ -0,0 +1,66 @@ +import {BANNER} from '../src/mediaTypes'; +import {registerBidder} from '../src/adapters/bidderFactory'; + +const ADPONE_CODE = 'adpone'; +const ADPONE_ENDPOINT = 'https://rtb.adpone.com/bid-request'; +const ADPONE_REQUEST_METHOD = 'POST'; +const ADPONE_CURRENCY = 'EUR'; + +export const spec = { + code: ADPONE_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: bid => { + return !!bid.params.placementId && !!bid.bidId; + }, + + buildRequests: bidRequests => { + return bidRequests.map(bid => { + const url = ADPONE_ENDPOINT + '?pid=' + bid.params.placementId; + const data = { + at: 1, + id: bid.bidId, + imp: bid.sizes.map((size, index) => ( + { + id: bid.bidId + '_' + index, + banner: { + w: size[0], + h: size[1] + } + })) + }; + + return { method: ADPONE_REQUEST_METHOD, url, data } + }); + }, + + interpretResponse: (serverResponse, bidRequest) => { + if (!serverResponse || !serverResponse.body) { + return []; + } + + let answer = []; + + serverResponse.body.seatbid.forEach(seatbid => { + if (seatbid.bid.length) { + answer = [...answer, ...seatbid.bid.filter(bid => bid.price > 0).map(bid => ({ + id: bid.id, + requestId: bidRequest.data.id, + cpm: bid.price, + ad: bid.adm, + width: bid.w || 0, + height: bid.h || 0, + currency: serverResponse.body.cur || ADPONE_CURRENCY, + netRevenue: true, + ttl: 300, + creativeId: bid.crid || 0 + }))]; + } + }); + + return answer; + } + +}; + +registerBidder(spec); diff --git a/modules/adponeBidAdapter.md b/modules/adponeBidAdapter.md new file mode 100644 index 00000000000..575b1620bac --- /dev/null +++ b/modules/adponeBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +Module Name: Adpone Bidder Adapter + +Module Type: Bidder Adapter + +Maintainer: tech@adpone.com + +# Description + +You can use this adapter to get a bid from adpone.com. + +About us : https://www.adpone.com + + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'div-adpone-example', + sizes: [[300, 250]], + bids: [ + { + bidder: "adpone", + params: { + placementId: "1234" + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/adponeBidAdapter_spec.js b/test/spec/modules/adponeBidAdapter_spec.js new file mode 100644 index 00000000000..1c64c60bd5c --- /dev/null +++ b/test/spec/modules/adponeBidAdapter_spec.js @@ -0,0 +1,102 @@ +import { expect } from 'chai'; +import { spec } from 'modules/adponeBidAdapter'; + +describe('adponeBidAdapter', function () { + let bid = { + bidder: 'adpone', + adUnitCode: 'adunit-code', + sizes: [[300, 250]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + params: { + placementId: '1', + } + }; + + describe('isBidRequestValid', function () { + it('should return true when necessary information is found', function () { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + + it('should return false when necessary information is not found', function () { + // empty bid + expect(spec.isBidRequestValid({bidId: '', params: {}})).to.be.false; + + // empty bidId + bid.bidId = ''; + expect(spec.isBidRequestValid(bid)).to.be.false; + + // empty placementId + bid.bidId = '30b31c1838de1e'; + bid.params.placementId = ''; + expect(spec.isBidRequestValid(bid)).to.be.false; + + bid.adUnitCode = 'adunit-code'; + }); + }); +}); + +describe('interpretResponse', function () { + let serverResponse; + let bidRequest = { data: {id: '1234'} }; + + beforeEach(function () { + serverResponse = { + body: { + id: '2579e20c0bb89', + seatbid: [ + { + bid: [ + { + id: '613673EF-A07C-4486-8EE9-3FC71A7DC73D', + impid: '2579e20c0bb89_0', + price: 1, + adm: '', + adomain: [ + 'www.addomain.com' + ], + iurl: 'http://localhost11', + crid: 'creative111', + h: 250, + w: 300, + ext: { + dspid: 6 + } + } + ], + seat: 'adpone' + } + ], + cur: 'USD' + }, + }; + }); + + it('should correctly reorder the server response', function () { + const newResponse = spec.interpretResponse(serverResponse, bidRequest); + expect(newResponse.length).to.be.equal(1); + expect(newResponse[0]).to.deep.equal({ + id: '613673EF-A07C-4486-8EE9-3FC71A7DC73D', + requestId: '1234', + cpm: 1, + width: 300, + height: 250, + creativeId: 'creative111', + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: '' + }); + }); + + it('should not add responses if the cpm is 0 or null', function () { + serverResponse.body.seatbid[0].bid[0].price = 0; + let response = spec.interpretResponse(serverResponse, bidRequest); + expect(response).to.deep.equal([]); + + serverResponse.body.seatbid[0].bid[0].price = null; + response = spec.interpretResponse(serverResponse, bidRequest); + expect(response).to.deep.equal([]) + }); +}); From e604ab3e3c6341bbb6c49c71527e46dbac3c031e Mon Sep 17 00:00:00 2001 From: ADman Media Date: Fri, 22 Mar 2019 18:27:42 +0100 Subject: [PATCH 1098/1594] ADman Media new bidder adapter (#3639) * Add Adman bid adapter * Add supportedMediaTypes property * Update ADman Media bidder adapter * Remove console.log --- modules/admanBidAdapter.js | 79 ++++++++ modules/admanBidAdapter.md | 35 ++++ test/spec/modules/admanBidAdapter_spec.js | 215 ++++++++++++++++++++++ 3 files changed, 329 insertions(+) create mode 100644 modules/admanBidAdapter.js create mode 100644 modules/admanBidAdapter.md create mode 100644 test/spec/modules/admanBidAdapter_spec.js diff --git a/modules/admanBidAdapter.js b/modules/admanBidAdapter.js new file mode 100644 index 00000000000..2fd8c2e96f0 --- /dev/null +++ b/modules/admanBidAdapter.js @@ -0,0 +1,79 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +import * as utils from '../src/utils'; + +const BIDDER_CODE = 'adman'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['video', 'banner'], + isBidRequestValid: function(bid) { + const isValid = _validateId(utils.deepAccess(bid, 'params.id')); + if (!isValid) { + utils.logError('Adman id parameter is required. Bid aborted.'); + } + return isValid; + }, + buildRequests: function(validBidRequests, bidderRequest) { + const ENDPOINT_URL = '//bidtor.admanmedia.com/prebid'; + const bids = validBidRequests.map(buildRequestObject); + const payload = { + referrer: utils.getTopWindowUrl(), + bids, + deviceWidth: screen.width + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr = { + consent: bidderRequest.gdprConsent.consentString, + applies: bidderRequest.gdprConsent.gdprApplies + }; + } else { + payload.gdpr = { + consent: '' + } + } + + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: ENDPOINT_URL, + data: payloadString, + }; + }, + interpretResponse: function(serverResponse) { + serverResponse = serverResponse.body; + if (serverResponse && typeof serverResponse.bids === 'object') { + return serverResponse.bids; + } + return []; + }, + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//cs.admanmedia.com/sync_tag/html' + }]; + } + } +}; + +function buildRequestObject(bid) { + return { + params: { + id: utils.getValue(bid.params, 'id'), + bidId: bid.bidId + }, + sizes: bid.sizes, + bidId: utils.getBidIdParameter('bidId', bid), + bidderRequestId: utils.getBidIdParameter('bidderRequestId', bid), + adUnitCode: utils.getBidIdParameter('adUnitCode', bid), + auctionId: utils.getBidIdParameter('auctionId', bid), + transactionId: utils.getBidIdParameter('transactionId', bid) + }; +} + +function _validateId(id = '') { + return (id.length === 8); +} + +registerBidder(spec); diff --git a/modules/admanBidAdapter.md b/modules/admanBidAdapter.md new file mode 100644 index 00000000000..900c828ea5c --- /dev/null +++ b/modules/admanBidAdapter.md @@ -0,0 +1,35 @@ +# Overview + +**Module Name**: Adman Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: prebid@admanmedia.com + +# Description + +Use `adman` as bidder. + +`id` is required and must be 8 alphanumeric characters. + +## AdUnits configuration example +``` + var adUnits = [{ + code: 'test-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'adman', + params: { + id: 1234asdf + } + }] + },{ + code: 'test-div, + sizes: [[600, 338]], + bids: [{ + bidder: 'adman', + params: { + id: asdf1234 + } + }] + }]; +``` + diff --git a/test/spec/modules/admanBidAdapter_spec.js b/test/spec/modules/admanBidAdapter_spec.js new file mode 100644 index 00000000000..2af040103cc --- /dev/null +++ b/test/spec/modules/admanBidAdapter_spec.js @@ -0,0 +1,215 @@ +import {expect} from 'chai'; +import {spec} from 'modules/admanBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//bidtor.admanmedia.com/prebid'; +const BANNER = '"'; +const VAST = ''; +const USER_SYNC_IFRAME_URL = '//cs.admanmedia.com/sync_tag/html'; + +describe('admanBidAdapter', 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': 'adman', + 'params': { + 'id': '1234asdf' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'creativeId': 'er2ee' + }; + + it('should return true when required params found', function() { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when id is not valid (not string)', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'id': 1234 + }; + + 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': 'adman', + 'bidId': '51ef8751f9aead', + 'params': { + 'id': '1234asdf' + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [[320, 50], [300, 250], [300, 600]], + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1 + } + ]; + + 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 + } + }); + + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('POST'); + + 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.referrer).to.exist; + + const bid = payload.bids[0]; + expect(bid).to.exist; + expect(bid.params).to.exist; + expect(bid.params.id).to.exist; + expect(bid.params.bidId).to.exist; + expect(bid.sizes).to.exist.and.to.be.an('array').and.to.have.lengthOf(3); + bid.sizes.forEach(size => { + expect(size).to.be.an('array').and.to.have.lengthOf(2); + expect(size[0]).to.be.a('number'); + expect(size[1]).to.be.a('number'); + }) + }); + + it('should send GDPR to endpoint and honor gdprApplies value', function() { + let consentString = 'bogusConsent'; + let bidderRequest = { + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.gdpr).to.exist; + expect(payload.gdpr.consent).to.equal(consentString); + expect(payload.gdpr.applies).to.equal(true); + + let bidderRequest2 = { + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': false + } + }; + + const request2 = spec.buildRequests(bidRequests, bidderRequest2); + const payload2 = JSON.parse(request2.data); + + expect(payload2.gdpr).to.exist; + expect(payload2.gdpr.consent).to.equal(consentString); + expect(payload2.gdpr.applies).to.equal(false); + }); + }); + + describe('interpretResponse', function() { + let bids = { + 'body': { + 'bids': [{ + 'ad': BANNER, + 'height': 250, + 'cpm': 0.5, + 'currency': 'USD', + 'netRevenue': true, + 'requestId': '3ede2a3fa0db94', + 'ttl': 3599, + 'width': 300, + 'creativeId': 'er2ee' + }, + { + 'vastXml': VAST, + 'cpm': 0.5, + 'currency': 'USD', + 'height': 250, + 'netRevenue': true, + 'requestId': '3ede2a3fa0db95', + 'ttl': 3599, + 'width': 300, + 'creativeId': 'er2ef' + }] + } + }; + + it('should get correct bid response', function() { + let expectedResponse = [{ + 'ad': BANNER, + 'cpm': 0.5, + 'creativeId': 'er2ee', + 'currency': 'USD', + 'height': 250, + 'netRevenue': true, + 'requestId': '3ede2a3fa0db94', + 'ttl': 3599, + 'width': 300, + }, + { + 'vastXml': VAST, + 'cpm': 0.5, + 'creativeId': 'er2ef', + 'currency': 'USD', + 'height': 250, + 'netRevenue': true, + 'requestId': '3ede2a3fa0db95', + 'ttl': 3599, + 'width': 300, + }]; + // los bids vienen formateados de server + let result = spec.interpretResponse(bids); + + expect(result[0]).to.deep.equal(expectedResponse[0]); + expect(result[1]).to.deep.equal(expectedResponse[1]); + // expect(Object.keys(result[1])).to.deep.equal(Object.keys(bids[1])); + }); + + it('handles nobid responses', function() { + let bids = { + 'body': { + 'bids': [] + } + }; + + let result = spec.interpretResponse(bids); + expect(result.length).to.equal(0); + }); + }); + describe('getUserSyncs', () => { + it('should get correct user sync iframe url', function() { + expect(spec.getUserSyncs({ + iframeEnabled: true + }, [{}])).to.deep.equal([{ + type: 'iframe', + url: USER_SYNC_IFRAME_URL + }]); + }); + }); +}); From eba2ab56bfa2077d2ab0cba6175edf90f45b6e5d Mon Sep 17 00:00:00 2001 From: Dmitriy Leonov Date: Fri, 22 Mar 2019 21:53:26 +0300 Subject: [PATCH 1099/1594] sortable bidadapter replace syncurl to camel case (#3667) --- modules/sortableBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/sortableBidAdapter.js b/modules/sortableBidAdapter.js index 38a3f2e156d..3909487fd48 100644 --- a/modules/sortableBidAdapter.js +++ b/modules/sortableBidAdapter.js @@ -136,8 +136,8 @@ export const spec = { let syncUrl = `//${SERVER_URL}/sync?f=html&s=${sortableConfig.siteId}&u=${encodeURIComponent(utils.getTopWindowLocation())}`; if (gdprConsent) { - syncurl += '&g=' + (gdprConsent.gdprApplies ? 1 : 0); - syncurl += '&cs=' + encodeURIComponent(gdprConsent.consentString || ''); + syncUrl += '&g=' + (gdprConsent.gdprApplies ? 1 : 0); + syncUrl += '&cs=' + encodeURIComponent(gdprConsent.consentString || ''); } return [{ From 033e76b6f41fac1601eeb13278513c10085b51a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E9=9B=A8=E8=BB=92=20=D0=9F=D0=B5=D1=82=D1=80?= Date: Sun, 24 Mar 2019 05:23:57 +0100 Subject: [PATCH 1100/1594] Update Adikteev adapter (PR updated) (#3391) Update Adikteev adapter (PR updated) --- ...adikteev.html => hello_world_emoteev.html} | 10 +- integrationExamples/gpt/pbjs_example_gpt.html | 8 +- modules/adikteevBidAdapter.js | 94 ----- ...eevBidAdapter.md => emokteevBidAdapter.md} | 13 +- modules/emoteevBidAdapter.js | 214 +++++++++++ test/spec/modules/adikteevBidAdapter_spec.js | 235 ------------ test/spec/modules/emoteevBidAdapter_spec.js | 349 ++++++++++++++++++ 7 files changed, 576 insertions(+), 347 deletions(-) rename integrationExamples/gpt/{hello_world_adikteev.html => hello_world_emoteev.html} (91%) delete mode 100644 modules/adikteevBidAdapter.js rename modules/{adikteevBidAdapter.md => emokteevBidAdapter.md} (55%) create mode 100644 modules/emoteevBidAdapter.js delete mode 100644 test/spec/modules/adikteevBidAdapter_spec.js create mode 100644 test/spec/modules/emoteevBidAdapter_spec.js diff --git a/integrationExamples/gpt/hello_world_adikteev.html b/integrationExamples/gpt/hello_world_emoteev.html similarity index 91% rename from integrationExamples/gpt/hello_world_adikteev.html rename to integrationExamples/gpt/hello_world_emoteev.html index 7372ff12d7f..5e4d0716d2b 100644 --- a/integrationExamples/gpt/hello_world_adikteev.html +++ b/integrationExamples/gpt/hello_world_emoteev.html @@ -21,12 +21,10 @@ } }, bids: [{ - bidder: 'adikteev', - params: { - placementId: 13144370, - stagingEnvironment: true, - bidFloorPrice: 0.1, - } + bidder: 'emoteev', + params: { + adSpaceId: 5084, + } }] }]; diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index 32452d33fd9..3a32eb5dbd6 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -314,12 +314,10 @@ height: '250', } }, - { - bidder: 'adikteev', + { + bidder: 'emoteev', params: { - placementId: 12345, - currency: 'EUR', - bidFloorPrice: 0.1, + adSpaceId: 5084, } }, ] diff --git a/modules/adikteevBidAdapter.js b/modules/adikteevBidAdapter.js deleted file mode 100644 index a0b0ed9cdcf..00000000000 --- a/modules/adikteevBidAdapter.js +++ /dev/null @@ -1,94 +0,0 @@ -import {registerBidder} from '../src/adapters/bidderFactory'; -import {BANNER} from '../src/mediaTypes'; -import * as utils from '../src/utils'; -import {config} from '../src/config'; - -export const BIDDER_CODE = 'adikteev'; -export const ENDPOINT_URL = 'https://serve-adserver.adikteev.com/api/prebid/bid'; -export const ENDPOINT_URL_STAGING = 'https://serve-adserver-staging.adikteev.com/api/prebid/bid'; -export const USER_SYNC_IFRAME_URL = 'https://serve-adserver.adikteev.com/api/prebid/sync-iframe'; -export const USER_SYNC_IFRAME_URL_STAGING = 'https://serve-adserver-staging.adikteev.com/api/prebid/sync-iframe'; -export const USER_SYNC_IMAGE_URL = 'https://serve-adserver.adikteev.com/api/prebid/sync-image'; -export const USER_SYNC_IMAGE_URL_STAGING = 'https://serve-adserver-staging.adikteev.com/api/prebid/sync-image'; - -export let stagingEnvironmentSwitch = false; // Don't use it. Allow us to make tests on staging - -export function setstagingEnvironmentSwitch(value) { - stagingEnvironmentSwitch = value; -} - -function validateSizes(sizes) { - if (!utils.isArray(sizes) || typeof sizes[0] === 'undefined') { - return false; - } - return sizes.every(size => utils.isArray(size) && size.length === 2); -} - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER], - - isBidRequestValid: (bid) => { - setstagingEnvironmentSwitch(stagingEnvironmentSwitch || !!bid.params.stagingEnvironment); - return !!( - bid && - bid.params && - bid.params.bidFloorPrice && - bid.params.placementId && - bid.bidder === BIDDER_CODE && - validateSizes(bid.mediaTypes.banner.sizes) - ); - }, - - buildRequests: (validBidRequests, bidderRequest) => { - const payload = { - validBidRequests, - bidderRequest, - refererInfo: bidderRequest.refererInfo, - currency: config.getConfig('currency'), - userAgent: navigator.userAgent, - screen: { - width: window.screen.width, - height: window.screen.height - }, - language: navigator.language, - cookies: document.cookie.split(';'), - prebidUpdateVersion: '1.29.0', - }; - return { - method: 'POST', - url: stagingEnvironmentSwitch ? ENDPOINT_URL_STAGING : ENDPOINT_URL, - data: JSON.stringify(payload), - }; - }, - - interpretResponse: (serverResponse, bidRequests) => { - const returnedBids = []; - const validBidRequests = JSON.parse(bidRequests.data).validBidRequests; - serverResponse.body.forEach((value, index) => { - const overrides = { - requestId: validBidRequests[index].bidId, - }; - returnedBids.push(Object.assign({}, value, overrides)); - }); - return returnedBids; - }, - - getUserSyncs: (syncOptions, serverResponses) => { - const syncs = []; - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: stagingEnvironmentSwitch ? USER_SYNC_IFRAME_URL_STAGING : USER_SYNC_IFRAME_URL, - }); - } - if (syncOptions.pixelEnabled && serverResponses.length > 0) { - syncs.push({ - type: 'image', - url: stagingEnvironmentSwitch ? USER_SYNC_IMAGE_URL_STAGING : USER_SYNC_IMAGE_URL, - }); - } - return syncs; - }, -}; -registerBidder(spec); diff --git a/modules/adikteevBidAdapter.md b/modules/emokteevBidAdapter.md similarity index 55% rename from modules/adikteevBidAdapter.md rename to modules/emokteevBidAdapter.md index d5008f61b03..88b0b21a96f 100644 --- a/modules/adikteevBidAdapter.md +++ b/modules/emokteevBidAdapter.md @@ -1,14 +1,14 @@ # Overview ``` -Module Name: Adikteev Bidder Adapter +Module Name: Emoteev Bidder Adapter Module Type: Bidder Adapter -Maintainer: adnetwork@adikteev.com +Maintainer: engineering@emoteev.io ``` # Description -Module that connects to Adikteev's demand sources +Module that connects to Emoteev's demand sources # Test Parameters @@ -18,15 +18,14 @@ Module that connects to Adikteev's demand sources code: 'test-div', mediaTypes: { banner: { - sizes: [[750, 200]], // a display size + sizes: [[300, 250]], } }, bids: [ { - bidder: 'adikteev', + bidder: 'emoteev', params: { - placementId: 12345, - bidFloorPrice: 0.1, + adSpaceId: 5084 } } ] diff --git a/modules/emoteevBidAdapter.js b/modules/emoteevBidAdapter.js new file mode 100644 index 00000000000..9b03b357818 --- /dev/null +++ b/modules/emoteevBidAdapter.js @@ -0,0 +1,214 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER} from '../src/mediaTypes'; +import * as utils from '../src/utils'; +import {config} from '../src/config'; + +export const BIDDER_CODE = 'emoteev'; +export const AK_PBJS_VERSION = '1.35.0'; + +export const EMOTEEV_BASE_URL = 'https://prebid.emoteev.io'; +export const EMOTEEV_BASE_URL_STAGING = 'https://prebid-staging.emoteev.io'; +export const EMOTEEV_BASE_URL_DEVELOPMENT = 'http://localhost:3000'; + +export const ENDPOINT_PATH = '/api/prebid/bid'; +export const USER_SYNC_IFRAME_URL_PATH = '/api/prebid/sync-iframe'; +export const USER_SYNC_IMAGE_URL_PATH = '/api/prebid/sync-image'; + +export const PRODUCTION = 'production'; +export const STAGING = 'staging'; +export const DEVELOPMENT = 'development'; +export const DEFAULT_ENV = PRODUCTION; + +export const conformBidRequest = bidRequest => { + return { + params: bidRequest.params, + crumbs: bidRequest.crumbs, + sizes: bidRequest.sizes, + bidId: bidRequest.bidId, + bidderRequestId: bidRequest.bidderRequestId, + }; +}; + +export const emoteevDebug = (parameterDebug, configDebug) => { + if (parameterDebug && parameterDebug.length && parameterDebug.length > 0) return JSON.parse(parameterDebug); + else if (configDebug) return configDebug; + else return false; +}; + +export const emoteevEnv = (parameteremoteevEnv, configemoteevEnv) => { + if (utils.contains([PRODUCTION, STAGING, DEVELOPMENT], parameteremoteevEnv)) return parameteremoteevEnv; + else if (utils.contains([PRODUCTION, STAGING, DEVELOPMENT], configemoteevEnv)) return configemoteevEnv; + else return DEFAULT_ENV; +}; + +export const emoteevOverrides = (parameteremoteevOverrides, configemoteevOverrides) => { + if (parameteremoteevOverrides && parameteremoteevOverrides.length !== 0) { + let parsedParams = null; + try { + parsedParams = JSON.parse(parameteremoteevOverrides); + } catch (error) { + parsedParams = null; + } + if (parsedParams) return parsedParams; + } + if (configemoteevOverrides && Object.keys(configemoteevOverrides).length !== 0) return configemoteevOverrides; + else return {}; +}; + +export const akUrl = (environment) => { + switch (environment) { + case DEVELOPMENT: + return EMOTEEV_BASE_URL_DEVELOPMENT; + case STAGING: + return EMOTEEV_BASE_URL_STAGING; + default: + return EMOTEEV_BASE_URL; + } +}; + +export const endpointUrl = (parameteremoteevEnv, configemoteevEnv) => akUrl(emoteevEnv(parameteremoteevEnv, configemoteevEnv)).concat(ENDPOINT_PATH); +export const userSyncIframeUrl = (parameteremoteevEnv, configemoteevEnv) => akUrl(emoteevEnv(parameteremoteevEnv, configemoteevEnv)).concat(USER_SYNC_IFRAME_URL_PATH); +export const userSyncImageUrl = (parameteremoteevEnv, configemoteevEnv) => akUrl(emoteevEnv(parameteremoteevEnv, configemoteevEnv)).concat(USER_SYNC_IMAGE_URL_PATH); + +export const getViewDimensions = () => { + let w = window; + let prefix = 'inner'; + + if (window.innerWidth === undefined || window.innerWidth === null) { + w = document.documentElement || document.body; + prefix = 'client'; + } + + return { + width: w[`${prefix}Width`], + height: w[`${prefix}Height`], + }; +}; + +export const getDeviceDimensions = () => { + return { + width: window.screen ? window.screen.width : '', + height: window.screen ? window.screen.height : '', + }; +}; + +export const getDocumentDimensions = () => { + const de = document.documentElement; + const be = document.body; + + const bodyHeight = be ? Math.max(be.offsetHeight, be.scrollHeight) : 0; + + const w = Math.max(de.clientWidth, de.offsetWidth, de.scrollWidth); + const h = Math.max( + de.clientHeight, + de.offsetHeight, + de.scrollHeight, + bodyHeight + ); + + return { + width: isNaN(w) ? '' : w, + height: isNaN(h) ? '' : h, + }; +}; + +export const isWebGLEnabled = () => { + // Create test canvas + let canvas = document.createElement('canvas'); + + // The gl context + let gl = null; + + // Try to get the regular WebGL + try { + gl = canvas.getContext('webgl'); + } catch (ex) { + canvas = undefined; + return false; + } + + // No regular WebGL found + if (!gl) { + // Try experimental WebGL + try { + gl = canvas.getContext('experimental-webgl'); + } catch (ex) { + canvas = undefined; + return false; + } + } + + return !!gl; +}; + +export const getDeviceInfo = (deviceDimensions, viewDimensions, documentDimensions, webGL) => { + return { + browserWidth: viewDimensions.width, + browserHeight: viewDimensions.height, + deviceWidth: deviceDimensions.width, + deviceHeight: deviceDimensions.height, + documentWidth: documentDimensions.width, + documentHeight: documentDimensions.height, + webGL: webGL, + }; +}; + +const validateSizes = sizes => utils.isArray(sizes) && sizes.some(size => utils.isArray(size) && size.length === 2); + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: (bid) => { + return !!( + bid && + bid.params && + bid.params.adSpaceId && + bid.bidder === BIDDER_CODE && + validateSizes(bid.mediaTypes.banner.sizes) + ); + }, + + buildRequests: (validBidRequests, bidderRequest) => { + const payload = Object.assign({}, + { + akPbjsVersion: AK_PBJS_VERSION, + bidRequests: validBidRequests.map(conformBidRequest), + currency: config.getConfig('currency'), + debug: emoteevDebug(utils.getParameterByName('emoteevDebug'), config.getConfig('emoteev.debug')), + language: navigator.language, + refererInfo: bidderRequest.refererInfo, + deviceInfo: getDeviceInfo(getDeviceDimensions(), getViewDimensions(), getDocumentDimensions(), isWebGLEnabled()), + userAgent: navigator.userAgent, + }, + emoteevOverrides(utils.getParameterByName('emoteevOverrides'), config.getConfig('emoteev.overrides'))); + + return { + method: 'POST', + url: endpointUrl(utils.getParameterByName('emoteevEnv'), config.getConfig('emoteev.env')), + data: JSON.stringify(payload), + }; + }, + + interpretResponse: (serverResponse) => serverResponse.body, + + getUserSyncs: (syncOptions, serverResponses) => { + const parameteremoteevEnv = utils.getParameterByName('emoteev.env'); + const configemoteevEnv = config.getConfig('emoteev.env'); + const syncs = []; + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: userSyncIframeUrl(parameteremoteevEnv, configemoteevEnv), + }); + } + if (syncOptions.pixelEnabled && serverResponses.length > 0) { + syncs.push({ + type: 'image', + url: userSyncImageUrl(parameteremoteevEnv, configemoteevEnv), + }); + } + return syncs; + }, +}; +registerBidder(spec); diff --git a/test/spec/modules/adikteevBidAdapter_spec.js b/test/spec/modules/adikteevBidAdapter_spec.js deleted file mode 100644 index 243cbe2a9c5..00000000000 --- a/test/spec/modules/adikteevBidAdapter_spec.js +++ /dev/null @@ -1,235 +0,0 @@ -import {expect} from 'chai'; -import { - ENDPOINT_URL, - ENDPOINT_URL_STAGING, - setstagingEnvironmentSwitch, - spec, - stagingEnvironmentSwitch, - USER_SYNC_IFRAME_URL, - USER_SYNC_IFRAME_URL_STAGING, - USER_SYNC_IMAGE_URL, - USER_SYNC_IMAGE_URL_STAGING, -} from 'modules/adikteevBidAdapter'; -import {newBidder} from 'src/adapters/bidderFactory'; -import * as utils from '../../../src/utils'; - -describe('adikteevBidAdapter', () => { - const adapter = newBidder(spec); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - it('exists and is a function', () => { - expect(setstagingEnvironmentSwitch).to.exist.and.to.be.a('function'); - }); - it('exists and is correctly set', () => { - expect(stagingEnvironmentSwitch).to.exist.and.to.equal(false); - }); - }); - - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { - const validBid = { - bidder: 'adikteev', - params: { - placementId: 12345, - bidFloorPrice: 0.1, - }, - mediaTypes: { - banner: { - sizes: [[750, 200]] - } - }, - }; - expect(spec.isBidRequestValid(validBid)).to.equal(true); - }); - - it('should mutate stagingEnvironmentSwitch when required params found', () => { - const withstagingEnvironmentSwitch = { - params: { - stagingEnvironment: true, - }, - }; - spec.isBidRequestValid(withstagingEnvironmentSwitch); - expect(stagingEnvironmentSwitch).to.equal(true); - setstagingEnvironmentSwitch(false); - }); - - it('should return false when required params are invalid', () => { - expect(spec.isBidRequestValid({ - bidder: '', // invalid bidder - params: { - placementId: 12345, - bidFloorPrice: 0.1, - }, - mediaTypes: { - banner: { - sizes: [[750, 200]] - } - }, - })).to.equal(false); - expect(spec.isBidRequestValid({ - bidder: 'adikteev', - params: { - placementId: '', // invalid placementId - bidFloorPrice: 0.1, - }, - mediaTypes: { - banner: { - sizes: [[750, 200]] - } - }, - })).to.equal(false); - expect(spec.isBidRequestValid({ - bidder: 'adikteev', - params: { - placementId: 12345, - bidFloorPrice: 0.1, - }, - mediaTypes: { - banner: { - sizes: [[750]] // invalid size - } - }, - })).to.equal(false); - }); - }); - - describe('buildRequests', () => { - const validBidRequests = []; - const bidderRequest = {}; - const serverRequest = spec.buildRequests(validBidRequests, bidderRequest); - it('creates a request object with correct method, url and data', () => { - expect(serverRequest).to.exist.and.have.all.keys( - 'method', - 'url', - 'data', - ); - expect(serverRequest.method).to.equal('POST'); - expect(serverRequest.url).to.equal(ENDPOINT_URL); - - let requestData = JSON.parse(serverRequest.data); - expect(requestData).to.exist.and.have.all.keys( - 'validBidRequests', - 'bidderRequest', - 'userAgent', - 'screen', - 'language', - 'cookies', - // 'refererInfo', - // 'currency', - 'prebidUpdateVersion', - ); - expect(requestData.validBidRequests).to.deep.equal(validBidRequests); - expect(requestData.bidderRequest).to.deep.equal(bidderRequest); - expect(requestData.userAgent).to.deep.equal(navigator.userAgent); - expect(requestData.screen.width).to.deep.equal(window.screen.width); - expect(requestData.screen.height).to.deep.equal(window.screen.height); - expect(requestData.language).to.deep.equal(navigator.language); - expect(requestData.prebidUpdateVersion).to.deep.equal('1.29.0'); - }); - - describe('staging environment', () => { - setstagingEnvironmentSwitch(true); - const serverRequest = spec.buildRequests(validBidRequests, bidderRequest); - expect(serverRequest.url).to.equal(ENDPOINT_URL_STAGING); - setstagingEnvironmentSwitch(false); - }); - }); - - describe('interpretResponse', () => { - it('bid objects from response', () => { - const serverResponse = - { - body: [ - { - cpm: 1, - width: 300, - height: 250, - ad: '
', - ttl: 360, - creativeId: 123, - netRevenue: false, - currency: 'EUR', - } - ] - }; - const payload = { - validBidRequests: [{ - bidId: '2ef7bb021ac847' - }], - }; - const bidRequests = { - method: 'POST', - url: stagingEnvironmentSwitch ? ENDPOINT_URL_STAGING : ENDPOINT_URL, - data: JSON.stringify(payload), - }; - const bidResponses = spec.interpretResponse(serverResponse, bidRequests); - expect(bidResponses).to.be.an('array').that.is.not.empty; // yes, syntax is correct - expect(bidResponses[0]).to.have.all.keys( - 'requestId', - 'cpm', - 'width', - 'height', - 'ad', - 'ttl', - 'creativeId', - 'netRevenue', - 'currency', - ); - - expect(bidResponses[0].requestId).to.equal(payload.validBidRequests[0].bidId); - expect(bidResponses[0].cpm).to.equal(serverResponse.body[0].cpm); - expect(bidResponses[0].width).to.equal(serverResponse.body[0].width); - expect(bidResponses[0].height).to.equal(serverResponse.body[0].height); - expect(bidResponses[0].ad).to.equal(serverResponse.body[0].ad); - expect(bidResponses[0].ttl).to.equal(serverResponse.body[0].ttl); - expect(bidResponses[0].creativeId).to.equal(serverResponse.body[0].creativeId); - expect(bidResponses[0].netRevenue).to.equal(serverResponse.body[0].netRevenue); - expect(bidResponses[0].currency).to.equal(serverResponse.body[0].currency); - }); - }); - - describe('getUserSyncs', () => { - expect(spec.getUserSyncs({ - iframeEnabled: true - }, [{}])).to.deep.equal([{ - type: 'iframe', - url: USER_SYNC_IFRAME_URL - }]); - - expect(spec.getUserSyncs({ - pixelEnabled: true - }, [{}])).to.deep.equal([{ - type: 'image', - url: USER_SYNC_IMAGE_URL - }]); - - expect(spec.getUserSyncs({ - iframeEnabled: true, - pixelEnabled: true - }, [{}])).to.deep.equal([{ - type: 'iframe', - url: USER_SYNC_IFRAME_URL - }, { - type: 'image', - url: USER_SYNC_IMAGE_URL - }]); - - describe('staging environment', () => { - setstagingEnvironmentSwitch(true); - expect(spec.getUserSyncs({ - iframeEnabled: true, - pixelEnabled: true - }, [{}])).to.deep.equal([{ - type: 'iframe', - url: USER_SYNC_IFRAME_URL_STAGING - }, { - type: 'image', - url: USER_SYNC_IMAGE_URL_STAGING - }]); - setstagingEnvironmentSwitch(false); - }); - }); -}); diff --git a/test/spec/modules/emoteevBidAdapter_spec.js b/test/spec/modules/emoteevBidAdapter_spec.js new file mode 100644 index 00000000000..a5f5c439e6f --- /dev/null +++ b/test/spec/modules/emoteevBidAdapter_spec.js @@ -0,0 +1,349 @@ +import {expect} from 'chai'; +import { + AK_PBJS_VERSION, + EMOTEEV_BASE_URL, + EMOTEEV_BASE_URL_STAGING, + emoteevDebug, + emoteevEnv, + emoteevOverrides, + akUrl, + conformBidRequest, + DEFAULT_ENV, + ENDPOINT_PATH, + endpointUrl, + PRODUCTION, + spec, + STAGING, + USER_SYNC_IFRAME_URL_PATH, + USER_SYNC_IMAGE_URL_PATH, + userSyncIframeUrl, + userSyncImageUrl, +} from 'modules/emoteevBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +import {config} from 'src/config'; + +const cannedValidBidRequests = [{ + adUnitCode: '/19968336/header-bid-tag-1', + auctionId: 'fcbf2b27-a951-496f-b5bb-1324ce7c0558', + bidId: '2b8de6572e8193', + bidRequestsCount: 1, + bidder: 'emoteev', + bidderRequestId: '1203b39fecc6a5', + crumbs: {pubcid: 'f3371d16-4e8b-42b5-a770-7e5be1fdf03d'}, + params: {adSpaceId: 5084}, + sizes: [[300, 250], [250, 300], [300, 600]], + transactionId: '58dbd732-7a39-45f1-b23e-1c24051a941c', +}]; +const cannedBidderRequest = { + auctionId: 'fcbf2b27-a951-496f-b5bb-1324ce7c0558', + auctionStart: 1544200122837, + bidderCode: 'emoteev', + bidderRequestId: '1203b39fecc6a5', + doneCbCallCount: 0, + refererInfo: { + canonicalUrl: undefined, + numIframes: 0, + reachedTop: true, + referer: 'http://localhost:9999/integrationExamples/gpt/hello_world_emoteev.html', + stack: ['http://localhost:9999/integrationExamples/gpt/hello_world_emoteev.html'] + }, + start: 1544200012839, + timeout: 3000 +}; +const serverResponse = + { + body: [ + { + requestId: cannedValidBidRequests[0].bidId, + cpm: 1, + width: cannedValidBidRequests[0].sizes[0][0], + height: cannedValidBidRequests[0].sizes[0][1], + ad: '
', + ttl: 360, + creativeId: 123, + netRevenue: false, + currency: 'EUR', + } + ] + }; + +describe('emoteevBidAdapter', 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('conformBidRequest', function () { + it('returns a bid-request', function () { + expect(conformBidRequest(cannedValidBidRequests[0])).to.deep.equal({ + params: cannedValidBidRequests[0].params, + crumbs: cannedValidBidRequests[0].crumbs, + sizes: cannedValidBidRequests[0].sizes, + bidId: cannedValidBidRequests[0].bidId, + bidderRequestId: cannedValidBidRequests[0].bidderRequestId, + }); + }) + }); + + describe('emoteevDebug', function () { + expect(emoteevDebug(null, null)).to.deep.equal(false) + }); + describe('emoteevDebug', function () { + expect(emoteevDebug(null, true)).to.deep.equal(true) + }); + describe('emoteevDebug', function () { + expect(emoteevDebug(JSON.stringify(true), null)).to.deep.equal(true) + }); + + describe('emoteevEnv', function () { + expect(emoteevEnv(null, null)).to.deep.equal(DEFAULT_ENV) + }); + describe('emoteevEnv', function () { + expect(emoteevEnv(null, STAGING)).to.deep.equal(STAGING) + }); + describe('emoteevEnv', function () { + expect(emoteevEnv(STAGING, null)).to.deep.equal(STAGING) + }); + + describe('emoteevOverrides', function () { + expect(emoteevOverrides(null, null)).to.deep.equal({}) + }); + describe('emoteevOverrides', function () { + expect(emoteevOverrides(JSON.stringify({a: 1}), null)).to.deep.equal({a: 1}) + }); + describe('emoteevOverrides', function () { + expect(emoteevOverrides('incorrect', null)).to.deep.equal({}) + }); // expect no exception + describe('emoteevOverrides', function () { + expect(emoteevOverrides(null, {a: 1})).to.deep.equal({a: 1}) + }); + + describe('akUrl', function () { + expect(akUrl(null)).to.deep.equal(EMOTEEV_BASE_URL) + }); + describe('akUrl', function () { + expect(akUrl('anything')).to.deep.equal(EMOTEEV_BASE_URL) + }); + describe('akUrl', function () { + expect(akUrl(STAGING)).to.deep.equal(EMOTEEV_BASE_URL_STAGING) + }); + describe('akUrl', function () { + expect(akUrl('production')).to.deep.equal(EMOTEEV_BASE_URL) + }); + + describe('endpointUrl', function () { + expect(endpointUrl(null, null)).to.deep.equal(EMOTEEV_BASE_URL.concat(ENDPOINT_PATH)) + }); + describe('endpointUrl', function () { + expect(endpointUrl(null, STAGING)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(ENDPOINT_PATH)) + }); + describe('endpointUrl', function () { + expect(endpointUrl(STAGING, null)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(ENDPOINT_PATH)) + }); + + describe('userSyncIframeUrl', function () { + expect(userSyncIframeUrl(null, null)).to.deep.equal(EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH)) + }); + describe('userSyncIframeUrl', function () { + expect(userSyncIframeUrl(null, STAGING)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(USER_SYNC_IFRAME_URL_PATH)) + }); + describe('userSyncIframeUrl', function () { + expect(userSyncIframeUrl(STAGING, null)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(USER_SYNC_IFRAME_URL_PATH)) + }); + + describe('userSyncImageUrl', function () { + expect(userSyncImageUrl(null, null)).to.deep.equal(EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH)) + }); + describe('userSyncImageUrl', function () { + expect(userSyncImageUrl(null, STAGING)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(USER_SYNC_IMAGE_URL_PATH)) + }); + describe('userSyncImageUrl', function () { + expect(userSyncImageUrl(STAGING, null)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(USER_SYNC_IMAGE_URL_PATH)) + }); + + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + const validBid = { + bidder: 'emoteev', + params: { + adSpaceId: 12345, + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + }; + expect(spec.isBidRequestValid(validBid)).to.equal(true); + }); + + it('should return false when required params are invalid', function () { + expect(spec.isBidRequestValid({ + bidder: '', // invalid bidder + params: { + adSpaceId: 12345, + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + })).to.equal(false); + expect(spec.isBidRequestValid({ + bidder: 'emoteev', + params: { + adSpaceId: '', // invalid adSpaceId + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + })).to.equal(false); + expect(spec.isBidRequestValid({ + bidder: 'emoteev', + params: { + adSpaceId: 12345, + }, + mediaTypes: { + banner: { + sizes: [[750]] // invalid size + } + }, + })).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const + currency = 'EUR', + emoteevEnv = STAGING, + emoteevDebug = true, + emoteevOverrides = { + iAmOverride: 'iAmOverride' + }; + config.setConfig({ // asynchronous + currency, + emoteev: { + env: STAGING, + debug: emoteevDebug, + overrides: emoteevOverrides + } + }); + + config.getConfig('emoteev', function () { + const request = spec.buildRequests(cannedValidBidRequests, cannedBidderRequest); + + it('creates a request object with correct method, url and data', function () { + expect(request).to.exist.and.have.all.keys( + 'method', + 'url', + 'data', + ); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(endpointUrl(emoteevEnv, emoteevEnv)); + + let requestData = JSON.parse(request.data); + expect(requestData).to.exist.and.have.all.keys( + 'akPbjsVersion', + 'bidRequests', + 'currency', + 'debug', + 'iAmOverride', + 'language', + 'refererInfo', + 'deviceInfo', + 'userAgent', + ); + + expect(requestData.bidRequests[0]).to.exist.and.have.all.keys( + 'params', + 'crumbs', + 'sizes', + 'bidId', + 'bidderRequestId', + ); + + expect(requestData.akPbjsVersion).to.deep.equal(AK_PBJS_VERSION); + expect(requestData.bidRequests[0].params).to.deep.equal(cannedValidBidRequests[0].params); + expect(requestData.bidRequests[0].crumbs).to.deep.equal(cannedValidBidRequests[0].crumbs); + expect(requestData.bidRequests[0].mediaTypes).to.deep.equal(cannedValidBidRequests[0].mediaTypes); + expect(requestData.bidRequests[0].bidId).to.deep.equal(cannedValidBidRequests[0].bidId); + expect(requestData.bidRequests[0].bidderRequestId).to.deep.equal(cannedValidBidRequests[0].bidderRequestId); + expect(requestData.currency).to.deep.equal(currency); + expect(requestData.debug).to.deep.equal(emoteevDebug); + expect(requestData.iAmOverride).to.deep.equal('iAmOverride'); + expect(requestData.language).to.deep.equal(navigator.language); + expect(requestData.deviceInfo).to.exist.and.have.all.keys( + 'browserWidth', + 'browserHeight', + 'deviceWidth', + 'deviceHeight', + 'documentWidth', + 'documentHeight', + 'webGL', + ); + expect(requestData.userAgent).to.deep.equal(navigator.userAgent); + }); + }); + }); + + describe('interpretResponse', function () { + it('bid objects from response', function () { + const bidResponses = spec.interpretResponse(serverResponse); + expect(bidResponses).to.be.an('array').that.is.not.empty; // yes, syntax is correct + expect(bidResponses[0]).to.have.all.keys( + 'requestId', + 'cpm', + 'width', + 'height', + 'ad', + 'ttl', + 'creativeId', + 'netRevenue', + 'currency', + ); + + expect(bidResponses[0].requestId).to.equal(cannedValidBidRequests[0].bidId); + expect(bidResponses[0].cpm).to.equal(serverResponse.body[0].cpm); + expect(bidResponses[0].width).to.equal(serverResponse.body[0].width); + expect(bidResponses[0].height).to.equal(serverResponse.body[0].height); + expect(bidResponses[0].ad).to.equal(serverResponse.body[0].ad); + expect(bidResponses[0].ttl).to.equal(serverResponse.body[0].ttl); + expect(bidResponses[0].creativeId).to.equal(serverResponse.body[0].creativeId); + expect(bidResponses[0].netRevenue).to.equal(serverResponse.body[0].netRevenue); + expect(bidResponses[0].currency).to.equal(serverResponse.body[0].currency); + }); + }); + + describe('getUserSyncs', function () { + config.setConfig({emoteevEnv: PRODUCTION}); + expect(spec.getUserSyncs({ + iframeEnabled: true + }, [{}])).to.deep.equal([{ + type: 'iframe', + url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) + }]); + + expect(spec.getUserSyncs({ + pixelEnabled: true + }, [{}])).to.deep.equal([{ + type: 'image', + url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) + }]); + + expect(spec.getUserSyncs({ + iframeEnabled: true, + pixelEnabled: true + }, [{}])).to.deep.equal([{ + type: 'iframe', + url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) + }, { + type: 'image', + url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) + }]); + }); +}); From b46e0b59647afae5e596b73a29283a6a28e8048e Mon Sep 17 00:00:00 2001 From: Andrew Muraco Date: Sun, 24 Mar 2019 00:30:49 -0400 Subject: [PATCH 1101/1594] Synacormedia new features (position & bid floor) (#3662) * SynacormediaBidAdapter: Update user sync url and repo_and_version and related tests * SynacormediaBidAdapter: added bidfloor to prebid adapter * SynacormediaBidAdapter: added pos to prebid --- modules/synacormediaBidAdapter.js | 27 +++- modules/synacormediaBidAdapter.md | 8 +- .../modules/synacormediaBidAdapter_spec.js | 132 ++++++++++++++++-- 3 files changed, 150 insertions(+), 17 deletions(-) diff --git a/modules/synacormediaBidAdapter.js b/modules/synacormediaBidAdapter.js index 8dd23b5048f..dcaa2c35f4f 100644 --- a/modules/synacormediaBidAdapter.js +++ b/modules/synacormediaBidAdapter.js @@ -3,9 +3,9 @@ import { getAdUnitSizes, logWarn } from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { BANNER } from '../src/mediaTypes'; -import { REPO_AND_VERSION } from '../src/constants'; -const SYNACOR_URL = '//prebid.technoratimedia.com'; +const BID_HOST = '//prebid.technoratimedia.com'; +const USER_SYNC_HOST = '//ad-cdn.technoratimedia.com'; export const spec = { code: 'synacormedia', supportedMediaTypes: [ BANNER ], @@ -40,23 +40,36 @@ export const spec = { seatId = bid.params.seatId; } let placementId = bid.params.placementId; + let bidFloor = bid.params.bidfloor ? parseFloat(bid.params.bidfloor) : null; + if (isNaN(bidFloor)) { + logWarn(`Synacormedia: there is an invalid bid floor: ${bid.params.bidfloor}`); + } + let pos = parseInt(bid.params.pos); + if (isNaN(pos)) { + logWarn(`Synacormedia: there is an invalid POS: ${bid.params.pos}`); + pos = 0; + } getAdUnitSizes(bid).forEach((size, i) => { - openRtbBidRequest.imp.push({ + let request = { id: bid.bidId + '~' + size[0] + 'x' + size[1], tagid: placementId, banner: { w: size[0], h: size[1], - pos: 0 + pos } - }); + }; + if (bidFloor !== null && !isNaN(bidFloor)) { + request.bidfloor = bidFloor; + } + openRtbBidRequest.imp.push(request); }); }); if (openRtbBidRequest.imp.length && seatId) { return { method: 'POST', - url: `${SYNACOR_URL}/openrtb/bids/${seatId}?src=${REPO_AND_VERSION}`, + url: `${BID_HOST}/openrtb/bids/${seatId}?src=$$REPO_AND_VERSION$$`, data: openRtbBidRequest, options: { contentType: 'application/json', @@ -111,7 +124,7 @@ export const spec = { if (syncOptions.iframeEnabled) { syncs.push({ type: 'iframe', - url: `${SYNACOR_URL}/usersync/html?src=${REPO_AND_VERSION}` + url: `${USER_SYNC_HOST}/html/usersync.html?src=$$REPO_AND_VERSION$$` }); } else { logWarn('Synacormedia: Please enable iframe based user sync.'); diff --git a/modules/synacormediaBidAdapter.md b/modules/synacormediaBidAdapter.md index 813e14f6be6..279cc48bcc1 100644 --- a/modules/synacormediaBidAdapter.md +++ b/modules/synacormediaBidAdapter.md @@ -24,7 +24,9 @@ Please reach out to your account manager for more information. bidder: "synacormedia", params: { seatId: "prebid", - placementId: "81416" + placementId: "81416", + bidfloor: "0.10", + pos: 1 } }] },{ @@ -37,7 +39,9 @@ Please reach out to your account manager for more information. params: { seatId: "prebid", placementId: "demo2" + bidfloor: "0.10", + pos: 1 } }] }]; -``` \ No newline at end of file +``` diff --git a/test/spec/modules/synacormediaBidAdapter_spec.js b/test/spec/modules/synacormediaBidAdapter_spec.js index 17bad3317e8..b91e8cc9fc1 100644 --- a/test/spec/modules/synacormediaBidAdapter_spec.js +++ b/test/spec/modules/synacormediaBidAdapter_spec.js @@ -38,7 +38,8 @@ describe('synacormediaBidAdapter ', function () { sizes: [[300, 250], [300, 600]], params: { seatId: 'prebid', - placementId: '1234' + placementId: '1234', + bidfloor: '0.50' } }; @@ -56,7 +57,8 @@ describe('synacormediaBidAdapter ', function () { w: 300, }, id: '9876abcd~300x250', - tagid: '1234' + tagid: '1234', + bidfloor: 0.5 }; let expectedDataImp2 = { banner: { @@ -65,7 +67,8 @@ describe('synacormediaBidAdapter ', function () { w: 300, }, id: '9876abcd~300x600', - tagid: '1234' + tagid: '1234', + bidfloor: 0.5 }; it('should return valid request when valid bids are used', function () { @@ -85,7 +88,8 @@ describe('synacormediaBidAdapter ', function () { sizes: [[300, 600]], params: { seatId: validBidRequest.params.seatId, - placementId: '5678' + placementId: '5678', + bidfloor: '0.50' } }; let req = spec.buildRequests([validBidRequest, secondBidRequest], bidderRequest); @@ -101,7 +105,8 @@ describe('synacormediaBidAdapter ', function () { w: 300, }, id: 'foobar~300x600', - tagid: '5678' + tagid: '5678', + bidfloor: 0.5 }]); }); @@ -111,7 +116,8 @@ describe('synacormediaBidAdapter ', function () { sizes: [[300, 250]], params: { seatId: 'somethingelse', - placementId: '5678' + placementId: '5678', + bidfloor: '0.50' } }; let req = spec.buildRequests([mismatchedSeatBidRequest, validBidRequest], bidderRequest); @@ -127,11 +133,121 @@ describe('synacormediaBidAdapter ', function () { w: 300, }, id: 'foobar~300x250', - tagid: '5678' + tagid: '5678', + bidfloor: 0.5 } ]); }); + it('should not use bidfloor when the value is not a number', function () { + let badFloorBidRequest = { + bidId: '9876abcd', + sizes: [[300, 250]], + params: { + seatId: 'prebid', + placementId: '1234', + bidfloor: 'abcd' + } + }; + let req = spec.buildRequests([badFloorBidRequest], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?src=$$REPO_AND_VERSION$$'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + banner: { + h: 250, + pos: 0, + w: 300, + }, + id: '9876abcd~300x250', + tagid: '1234', + } + ]); + }); + + it('should not use bidfloor when there is no value', function () { + let badFloorBidRequest = { + bidId: '9876abcd', + sizes: [[300, 250]], + params: { + seatId: 'prebid', + placementId: '1234' + } + }; + let req = spec.buildRequests([badFloorBidRequest], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?src=$$REPO_AND_VERSION$$'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + banner: { + h: 250, + pos: 0, + w: 300, + }, + id: '9876abcd~300x250', + tagid: '1234', + } + ]); + }); + + it('should use the pos given by the bid request', function () { + let newPosBidRequest = { + bidId: '9876abcd', + sizes: [[300, 250]], + params: { + seatId: 'prebid', + placementId: '1234', + pos: 1 + } + }; + let req = spec.buildRequests([newPosBidRequest], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?src=$$REPO_AND_VERSION$$'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + banner: { + h: 250, + w: 300, + pos: 1, + }, + id: '9876abcd~300x250', + tagid: '1234' + } + ]); + }); + + it('should use the default pos if none in bid request', function () { + let newPosBidRequest = { + bidId: '9876abcd', + sizes: [[300, 250]], + params: { + seatId: 'prebid', + placementId: '1234', + } + }; + let req = spec.buildRequests([newPosBidRequest], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?src=$$REPO_AND_VERSION$$'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + banner: { + h: 250, + w: 300, + pos: 0, + }, + id: '9876abcd~300x250', + tagid: '1234' + } + ]); + }); it('should not return a request when no valid bid request used', function () { expect(spec.buildRequests([], bidderRequest)).to.be.undefined; expect(spec.buildRequests([validBidRequest], null)).to.be.undefined; @@ -237,7 +353,7 @@ describe('synacormediaBidAdapter ', function () { expect(usersyncs).to.be.an('array').that.is.not.empty; expect(usersyncs[0]).to.have.property('type', 'iframe'); expect(usersyncs[0]).to.have.property('url'); - expect(usersyncs[0].url).to.contain('//prebid.technoratimedia.com/usersync/html'); + expect(usersyncs[0].url).to.contain('//ad-cdn.technoratimedia.com/html/usersync.html'); }); it('should not return a usersync when iframes are not enabled', function () { From 04b1ec2f93de5f7687126eb2d90a280707af74f0 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Mon, 25 Mar 2019 15:47:15 +0100 Subject: [PATCH 1102/1594] Improve Digital adapter: use Prebid sizes param (#3648) * Adding GDPR support * Always drop user syncs when available * Set dealID based on buying type * Native ads, single request option * Send ad unit sizes to Improve ad server * adapter version -> 5.1 * Adding usePrebidSizes config param --- modules/improvedigitalBidAdapter.js | 38 +++++++++++++---- .../modules/improvedigitalBidAdapter_spec.js | 42 ++++++++++++++++++- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index c7360e6a8d6..fdfe5970572 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -6,7 +6,7 @@ import { BANNER, NATIVE } from '../src/mediaTypes'; const BIDDER_CODE = 'improvedigital'; export const spec = { - version: '5.0.0', + version: '5.1.0', code: BIDDER_CODE, aliases: ['id'], supportedMediaTypes: [BANNER, NATIVE], @@ -170,7 +170,7 @@ function getNormalizedBidRequest(bid) { placementKey = utils.getBidIdParameter('placementKey', bid.params) || null; } let keyValues = utils.getBidIdParameter('keyValues', bid.params) || null; - let localSize = utils.getBidIdParameter('size', bid.params) || null; + let singleSizeFilter = utils.getBidIdParameter('size', bid.params) || null; let bidId = utils.getBidIdParameter('bidId', bid); let transactionId = utils.getBidIdParameter('transactionId', bid); const currency = config.getConfig('currency.adServerCurrency'); @@ -190,11 +190,15 @@ function getNormalizedBidRequest(bid) { if (keyValues) { normalizedBidRequest.keyValues = keyValues; } - if (localSize && localSize.w && localSize.h) { + + if (config.getConfig('improvedigital.usePrebidSizes') === true && bid.sizes && bid.sizes.length > 0) { + normalizedBidRequest.format = bid.sizes; + } else if (singleSizeFilter && singleSizeFilter.w && singleSizeFilter.h) { normalizedBidRequest.size = {}; - normalizedBidRequest.size.h = localSize.h; - normalizedBidRequest.size.w = localSize.w; + normalizedBidRequest.size.h = singleSizeFilter.h; + normalizedBidRequest.size.w = singleSizeFilter.w; } + if (bidId) { normalizedBidRequest.id = bidId; } @@ -270,7 +274,7 @@ export function ImproveDigitalAdServerJSClient(endPoint) { AD_SERVER_BASE_URL: 'ad.360yield.com', END_POINT: endPoint || 'hb', AD_SERVER_URL_PARAM: 'jsonp=', - CLIENT_VERSION: 'JS-5.2.0', + CLIENT_VERSION: 'JS-5.3.0', MAX_URL_LENGTH: 2083, ERROR_CODES: { MISSING_PLACEMENT_PARAMS: 2, @@ -472,12 +476,28 @@ export function ImproveDigitalAdServerJSClient(endPoint) { } } } + + impressionObject.banner = {}; if (placementObject.size && placementObject.size.w && placementObject.size.h) { - impressionObject.banner = {}; impressionObject.banner.w = placementObject.size.w; impressionObject.banner.h = placementObject.size.h; - } else { - impressionObject.banner = {}; + } + + // 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; + } } if (!impressionObject.pid && diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 8b76bfcbe9c..61ba56ab822 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -19,7 +19,8 @@ describe('Improve Digital Adapter Tests', function () { transactionId: 'f183e871-fbed-45f0-a427-c8a63c4c01eb', bidId: '33e9500b21129f', bidderRequestId: '2772c1e566670b', - auctionId: '192721e36a0239' + auctionId: '192721e36a0239', + sizes: [[300, 250], [160, 600], ['blah', 150], [-1, 300], [300, -5]] }; const simpleSmartTagBidRequest = { @@ -126,7 +127,7 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.imp[0].kvw).to.deep.equal(keyValues); }); - it('should add size', function () { + it('should add single size filter', function () { let bidRequest = Object.assign({}, simpleBidRequest); const size = { w: 800, @@ -136,6 +137,9 @@ describe('Improve Digital Adapter Tests', function () { const request = spec.buildRequests([bidRequest])[0]; const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); expect(params.bid_request.imp[0].banner).to.deep.equal(size); + // When single size filter is set, format shouldn't be populated. This + // is to maintain backward compatibily + expect(params.bid_request.imp[0].banner.format).to.not.exist; }); it('should add currency', function () { @@ -174,6 +178,40 @@ describe('Improve Digital Adapter Tests', function () { expect(requests.length).to.equal(1); getConfigStub.restore(); }); + + it('should set Prebid sizes in bid request', function () { + const getConfigStub = sinon.stub(config, 'getConfig'); + getConfigStub.withArgs('improvedigital.usePrebidSizes').returns(true); + const request = spec.buildRequests([simpleBidRequest])[0]; + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].banner).to.deep.equal({ + format: [ + { w: 300, h: 250 }, + { w: 160, h: 600 } + ] + }); + getConfigStub.restore(); + }); + + it('should not add single size filter when using Prebid sizes', function () { + const getConfigStub = sinon.stub(config, 'getConfig'); + getConfigStub.withArgs('improvedigital.usePrebidSizes').returns(true); + const bidRequest = Object.assign({}, simpleBidRequest); + const size = { + w: 800, + h: 600 + }; + bidRequest.params.size = size; + const request = spec.buildRequests([bidRequest])[0]; + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].banner).to.deep.equal({ + format: [ + { w: 300, h: 250 }, + { w: 160, h: 600 } + ] + }); + getConfigStub.restore(); + }); }); const serverResponse = { From f77b78c2cd0d8d711b0b27fad015599d6f2e87b3 Mon Sep 17 00:00:00 2001 From: thomas-33across <44033452+thomas-33across@users.noreply.github.com> Date: Mon, 25 Mar 2019 10:57:38 -0400 Subject: [PATCH 1103/1594] Add new s2s config option (#3643) * - add new s2s params to do sync url modifier * add unit test case for s2s config * - add additional condition check for _s2sConfig.syncUrlModifier --- modules/prebidServerBidAdapter/index.js | 22 +++++++++++++++++-- .../modules/prebidServerBidAdapter_spec.js | 11 ++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index fdcab82d247..586d78ed2ca 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -53,7 +53,8 @@ const s2sDefaultConfig = { timeout: 1000, maxBids: 1, adapter: 'prebidServer', - adapterOptions: {} + adapterOptions: {}, + syncUrlModifier: {} }; config.setDefaults({ @@ -170,12 +171,29 @@ function doAllSyncs(bidders) { const thisSync = bidders.pop(); if (thisSync.no_cookie) { - doBidderSync(thisSync.usersync.type, thisSync.usersync.url, thisSync.bidder, utils.bind.call(doAllSyncs, null, bidders)); + doPreBidderSync(thisSync.usersync.type, thisSync.usersync.url, thisSync.bidder, utils.bind.call(doAllSyncs, null, bidders)); } else { doAllSyncs(bidders); } } +/** + * Modify the cookie sync url from prebid server to add new params. + * + * @param {string} type the type of sync, "image", "redirect", "iframe" + * @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 + */ +function doPreBidderSync(type, url, bidder, done) { + if (_s2sConfig.syncUrlModifier && typeof _s2sConfig.syncUrlModifier[bidder] === 'function') { + const newSyncUrl = _s2sConfig.syncUrlModifier[bidder](type, url, bidder); + doBidderSync(type, newSyncUrl, bidder, done) + } else { + doBidderSync(type, url, bidder, done) + } +} + /** * Run a cookie sync for the given type, url, and bidder * diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index f14c171ee6c..47d0084d86a 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1460,5 +1460,16 @@ describe('S2S Adapter', function () { } }) }); + + it('should set syncUrlModifier', function () { + config.setConfig({ + s2sConfig: { + syncUrlModifier: { + appnexus: () => {} + } + } + }); + expect(typeof config.getConfig('s2sConfig').syncUrlModifier.appnexus).to.equal('function') + }); }); }); From 3e5190dc4c1d813f85b1993bb73895e8a7f96990 Mon Sep 17 00:00:00 2001 From: Paris Holley Date: Mon, 25 Mar 2019 16:02:40 -0400 Subject: [PATCH 1104/1594] Adjust TTL for MANTIS adapter (#3676) * support dynamic TTL from server * version bump --- modules/mantisBidAdapter.js | 4 +- test/spec/modules/mantisBidAdapter_spec.js | 75 ++++++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/modules/mantisBidAdapter.js b/modules/mantisBidAdapter.js index 4d40dc3af76..2f6b892194a 100644 --- a/modules/mantisBidAdapter.js +++ b/modules/mantisBidAdapter.js @@ -168,7 +168,7 @@ function buildMantisUrl(path, data, domain) { tz: new Date().getTimezoneOffset(), buster: new Date().getTime(), secure: isSecure(), - version: 8 + version: 9 }; if (!inIframe() || isAmp()) { params.mobile = !isAmp() && isDesktop(true) ? 'false' : 'true'; @@ -252,7 +252,7 @@ const spec = { width: ad.width, height: ad.height, ad: ad.html, - ttl: 86400, + ttl: ad.ttl || serverResponse.body.ttl || 86400, creativeId: ad.view, netRevenue: true, currency: 'USD' diff --git a/test/spec/modules/mantisBidAdapter_spec.js b/test/spec/modules/mantisBidAdapter_spec.js index 464cea2aab3..df2c6bb9a13 100644 --- a/test/spec/modules/mantisBidAdapter_spec.js +++ b/test/spec/modules/mantisBidAdapter_spec.js @@ -128,6 +128,81 @@ describe('MantisAdapter', function () { }); describe('interpretResponse', function () { + it('use ad ttl if provided', function () { + let response = { + body: { + ttl: 360, + uuid: 'uuid', + ads: [ + { + bid: 'bid', + cpm: 1, + view: 'view', + width: 300, + ttl: 250, + height: 250, + html: '' + } + ] + } + }; + + let expectedResponse = [ + { + requestId: 'bid', + cpm: 1, + width: 300, + height: 250, + ttl: 250, + ad: '', + creativeId: 'view', + netRevenue: true, + currency: 'USD' + } + ]; + let bidderRequest; + + let result = spec.interpretResponse(response, {bidderRequest}); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + it('use global ttl if provded', function () { + let response = { + body: { + ttl: 360, + uuid: 'uuid', + ads: [ + { + bid: 'bid', + cpm: 1, + view: 'view', + width: 300, + height: 250, + html: '' + } + ] + } + }; + + let expectedResponse = [ + { + requestId: 'bid', + cpm: 1, + width: 300, + height: 250, + ttl: 360, + ad: '', + creativeId: 'view', + netRevenue: true, + currency: 'USD' + } + ]; + let bidderRequest; + + let result = spec.interpretResponse(response, {bidderRequest}); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + it('display ads returned', function () { let response = { body: { From b9fb264f27a20e74051de3af27908f79ec92a932 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 26 Mar 2019 08:41:49 -0400 Subject: [PATCH 1105/1594] Add hb_uuid and hb_cache_id back to dfp module (#3668) * Add hb_uuid and hb_cache_id back to module * added comment --- modules/dfpAdServerVideo.js | 4 +++ test/spec/modules/dfpAdServerVideo_spec.js | 40 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 17a8f0f1144..d8cd6e099ee 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -158,6 +158,10 @@ function getCustParams(bid, options) { const optCustParams = deepAccess(options, 'params.cust_params'); let customParams = Object.assign({}, + // Why are we adding standard keys here ? Refer https://github.com/prebid/Prebid.js/issues/3664 + { hb_uuid: bid && bid.videoCacheKey }, + // hb_uuid will be deprecated and replaced by hb_cache_id + { hb_cache_id: bid && bid.videoCacheKey }, allTargetingData, adserverTargeting, optCustParams, diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index ab988ec0fe3..30cf91c2e17 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -256,4 +256,44 @@ describe('The DFP video support module', function () { expect(url).to.be.a('string'); }); + + it('should include hb_uuid and hb_cache_id in cust_params when both keys are exluded from overwritten bidderSettings', function () { + const bidCopy = utils.deepClone(bid); + delete bidCopy.adserverTargeting.hb_uuid; + delete bidCopy.adserverTargeting.hb_cache_id; + + const url = parse(buildDfpVideoUrl({ + adUnit: adUnit, + bid: bidCopy, + params: { + 'iu': 'my/adUnit' + } + })); + const queryObject = parseQS(url.query); + const customParams = parseQS('?' + decodeURIComponent(queryObject.cust_params)); + + expect(customParams).to.have.property('hb_uuid', bid.videoCacheKey); + expect(customParams).to.have.property('hb_cache_id', bid.videoCacheKey); + }); + + it('should include hb_uuid and hb_cache_id in cust params from overwritten standard bidderSettings', function () { + const bidCopy = utils.deepClone(bid); + bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, { + hb_uuid: 'def', + hb_cache_id: 'def' + }); + + const url = parse(buildDfpVideoUrl({ + adUnit: adUnit, + bid: bidCopy, + params: { + 'iu': 'my/adUnit' + } + })); + const queryObject = parseQS(url.query); + const customParams = parseQS('?' + decodeURIComponent(queryObject.cust_params)); + + expect(customParams).to.have.property('hb_uuid', 'def'); + expect(customParams).to.have.property('hb_cache_id', 'def'); + }); }); From 12882f9f99ed2e8cc3726f50a909cd946a71144b Mon Sep 17 00:00:00 2001 From: Paul Schreiber Date: Tue, 26 Mar 2019 10:06:09 -0400 Subject: [PATCH 1106/1594] fix spelling of 'country' (#3679) --- modules/etargetBidAdapter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/etargetBidAdapter.js b/modules/etargetBidAdapter.js index 4b1c6b21d79..bdf07742497 100644 --- a/modules/etargetBidAdapter.js +++ b/modules/etargetBidAdapter.js @@ -28,18 +28,18 @@ export const spec = { var i, l, bid, reqParams, netRevenue, gdprObject; var request = []; var bids = JSON.parse(JSON.stringify(validBidRequests)); - var lastContry = 'sk'; + var lastCountry = 'sk'; for (i = 0, l = bids.length; i < l; i++) { bid = bids[i]; if (countryMap[bid.params.country]) { - lastContry = countryMap[bid.params.country]; + lastCountry = countryMap[bid.params.country]; } reqParams = bid.params; reqParams.transactionId = bid.transactionId; request.push(formRequestUrl(reqParams)); } - request.unshift('//' + lastContry + '.search.etargetnet.com/hb/?hbget=1'); + request.unshift('//' + lastCountry + '.search.etargetnet.com/hb/?hbget=1'); netRevenue = 'net'; if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { From 010f2032dce4e447887e06b047cc8654c8d34b7e Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Tue, 26 Mar 2019 10:31:45 -0400 Subject: [PATCH 1107/1594] Kargo migration to localstorage alternatives (#3672) * moving kargo adaptor away from cookie usage * kargo adapter should fall back to cookies --- modules/kargoBidAdapter.js | 50 ++++---- test/spec/modules/kargoBidAdapter_spec.js | 137 ++++++++++++---------- 2 files changed, 97 insertions(+), 90 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index b987f9a760a..ecd26f49509 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -91,40 +91,37 @@ export const spec = { return null; }, - _getCrbIds() { + _getCrbFromCookie() { try { const crb = JSON.parse(decodeURIComponent(spec._readCookie('krg_crb'))); - let syncIds = {}; - if (crb && crb.v) { let vParsed = JSON.parse(atob(crb.v)); - - if (vParsed && vParsed.syncIds) { - syncIds = vParsed.syncIds; + if (vParsed) { + return vParsed; } } - - return syncIds; + return {}; } catch (e) { return {}; } }, - _getUid() { + _getCrbFromLocalStorage() { try { - const uid = JSON.parse(decodeURIComponent(spec._readCookie('krg_uid'))); - let vData = {}; - - if (uid && uid.v) { - vData = uid.v; - } - - return vData; + return JSON.parse(atob(spec._getLocalStorageSafely('krg_crb'))); } catch (e) { return {}; } }, + _getCrb() { + let localStorageCrb = spec._getCrbFromLocalStorage(); + if (Object.keys(localStorageCrb).length) { + return localStorageCrb; + } + return spec._getCrbFromCookie(); + }, + _getKruxUserId() { return spec._getLocalStorageSafely('kxkar_user'); }, @@ -156,20 +153,18 @@ export const spec = { }, _getUserIds() { - const uid = spec._getUid(); - const crbIds = spec._getCrbIds(); - + const crb = spec._getCrb(); return { - kargoID: uid.userId, - clientID: uid.clientId, - crbIDs: crbIds, - optOut: uid.optOut + kargoID: crb.userId, + clientID: crb.clientId, + crbIDs: crb.syncIds || {}, + optOut: crb.optOut }; }, _getClientId() { - const uid = spec._getUid(); - return uid.clientId; + const crb = spec._getCrb(); + return crb.clientId; }, _getAllMetadata() { @@ -177,7 +172,8 @@ export const spec = { userIDs: spec._getUserIds(), krux: spec._getKrux(), pageURL: window.location.href, - rawCRB: spec._readCookie('krg_crb') + rawCRB: spec._readCookie('krg_crb'), + rawCRBLocalStorage: spec._getLocalStorageSafely('krg_crb') }; }, diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index eb829ce552d..28cb386242f 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -134,20 +134,19 @@ describe('kargo adapter tests', function () { setLocalStorageItem('kxkar_segs', 'qv9v984dy,rpx2gy365,qrd5u4axv,rnub9nmtd,reha00jnu'); } - function initializeKrgUid() { - setCookie('krg_uid', '%7B%22v%22%3A%7B%22userId%22%3A%225f108831-302d-11e7-bf6b-4595acd3bf6c%22%2C%22clientId%22%3A%222410d8f2-c111-4811-88a5-7b5e190e475f%22%2C%22optOut%22%3Afalse%7D%7D'); - } - function getKrgCrb() { - return '%7B%22v%22%3A%22eyJzeW5jSWRzIjp7IjIiOiI4MmZhMjU1NS01OTY5LTQ2MTQtYjRjZS00ZGNmMTA4MGU5ZjkiLCIxNiI6IlZveElrOEFvSnowQUFFZENleUFBQUFDMiY1MDIiLCIyMyI6ImQyYTg1NWE1LTFiMWMtNDMwMC05NDBlLWE3MDhmYTFmMWJkZSIsIjI0IjoiVm94SWs4QW9KejBBQUVkQ2V5QUFBQUMyJjUwMiIsIjI1IjoiNWVlMjQxMzgtNWUwMy00YjlkLWE5NTMtMzhlODMzZjI4NDlmIiwiMl84MCI6ImQyYTg1NWE1LTFiMWMtNDMwMC05NDBlLWE3MDhmYTFmMWJkZSIsIjJfOTMiOiI1ZWUyNDEzOC01ZTAzLTRiOWQtYTk1My0zOGU4MzNmMjg0OWYifSwiZXhwaXJlVGltZSI6MTQ5NzQ0OTM4MjY2OCwibGFzdFN5bmNlZEF0IjoxNDk3MzYyOTc5MDEyfQ%3D%3D%22%7D'; + return 'eyJzeW5jSWRzIjp7IjIiOiI4MmZhMjU1NS01OTY5LTQ2MTQtYjRjZS00ZGNmMTA4MGU5ZjkiLCIxNiI6IlZveElrOEFvSnowQUFFZENleUFBQUFDMiY1MDIiLCIyMyI6ImQyYTg1NWE1LTFiMWMtNDMwMC05NDBlLWE3MDhmYTFmMWJkZSIsIjI0IjoiVm94SWs4QW9KejBBQUVkQ2V5QUFBQUMyJjUwMiIsIjI1IjoiNWVlMjQxMzgtNWUwMy00YjlkLWE5NTMtMzhlODMzZjI4NDlmIiwiMl84MCI6ImQyYTg1NWE1LTFiMWMtNDMwMC05NDBlLWE3MDhmYTFmMWJkZSIsIjJfOTMiOiI1ZWUyNDEzOC01ZTAzLTRiOWQtYTk1My0zOGU4MzNmMjg0OWYifSwidXNlcklkIjoiNWYxMDg4MzEtMzAyZC0xMWU3LWJmNmItNDU5NWFjZDNiZjZjIiwiY2xpZW50SWQiOiIyNDEwZDhmMi1jMTExLTQ4MTEtODhhNS03YjVlMTkwZTQ3NWYiLCJvcHRPdXQiOmZhbHNlLCJleHBpcmVUaW1lIjoxNDk3NDQ5MzgyNjY4LCJsYXN0U3luY2VkQXQiOjE0OTczNjI5NzkwMTJ9'; } - function initializeKrgCrb() { - setCookie('krg_crb', getKrgCrb()); + function getKrgCrbOldStyle() { + return '%7B%22v%22%3A%22eyJzeW5jSWRzIjp7IjIiOiI4MmZhMjU1NS01OTY5LTQ2MTQtYjRjZS00ZGNmMTA4MGU5ZjkiLCIxNiI6IlZveElrOEFvSnowQUFFZENleUFBQUFDMiY1MDIiLCIyMyI6ImQyYTg1NWE1LTFiMWMtNDMwMC05NDBlLWE3MDhmYTFmMWJkZSIsIjI0IjoiVm94SWs4QW9KejBBQUVkQ2V5QUFBQUMyJjUwMiIsIjI1IjoiNWVlMjQxMzgtNWUwMy00YjlkLWE5NTMtMzhlODMzZjI4NDlmIiwiMl84MCI6ImQyYTg1NWE1LTFiMWMtNDMwMC05NDBlLWE3MDhmYTFmMWJkZSIsIjJfOTMiOiI1ZWUyNDEzOC01ZTAzLTRiOWQtYTk1My0zOGU4MzNmMjg0OWYifSwidXNlcklkIjoiNWYxMDg4MzEtMzAyZC0xMWU3LWJmNmItNDU5NWFjZDNiZjZjIiwiY2xpZW50SWQiOiIyNDEwZDhmMi1jMTExLTQ4MTEtODhhNS03YjVlMTkwZTQ3NWYiLCJvcHRPdXQiOmZhbHNlLCJleHBpcmVUaW1lIjoxNDk3NDQ5MzgyNjY4LCJsYXN0U3luY2VkQXQiOjE0OTczNjI5NzkwMTJ9%22%7D'; } - function initializeInvalidKrgUid() { - setCookie('krg_uid', 'invalid-krg-uid'); + function initializeKrgCrb(cookieOnly) { + if (!cookieOnly) { + setLocalStorageItem('krg_crb', getKrgCrb()); + } + setCookie('krg_crb', getKrgCrbOldStyle()); } function getInvalidKrgCrbType1() { @@ -155,38 +154,54 @@ describe('kargo adapter tests', function () { } function initializeInvalidKrgCrbType1() { + setLocalStorageItem('krg_crb', getInvalidKrgCrbType1()); + } + + function initializeInvalidKrgCrbType1Cookie() { setCookie('krg_crb', getInvalidKrgCrbType1()); } function getInvalidKrgCrbType2() { + return 'Ly8v'; + } + + function getInvalidKrgCrbType2OldStyle() { return '%7B%22v%22%3A%22%26%26%26%26%26%26%22%7D'; } function initializeInvalidKrgCrbType2() { - setCookie('krg_crb', getInvalidKrgCrbType2()); + setLocalStorageItem('krg_crb', getInvalidKrgCrbType2()); } - function getInvalidKrgCrbType3() { - return '%7B%22v%22%3A%22Ly8v%22%7D'; + function initializeInvalidKrgCrbType2Cookie() { + setCookie('krg_crb', getInvalidKrgCrbType2OldStyle()); } - function initializeInvalidKrgCrbType3() { - setCookie('krg_crb', getInvalidKrgCrbType3()); + function getInvalidKrgCrbType3OldStyle() { + return '%7B%22v%22%3A%22Ly8v%22%7D'; } - function initializeEmptyKrgUid() { - setCookie('krg_uid', '%7B%7D'); + function initializeInvalidKrgCrbType3Cookie() { + setCookie('krg_crb', getInvalidKrgCrbType3OldStyle()); } function getEmptyKrgCrb() { + return 'eyJleHBpcmVUaW1lIjoxNDk3NDQ5MzgyNjY4LCJsYXN0U3luY2VkQXQiOjE0OTczNjI5NzkwMTJ9'; + } + + function getEmptyKrgCrbOldStyle() { return '%7B%22v%22%3A%22eyJleHBpcmVUaW1lIjoxNDk3NDQ5MzgyNjY4LCJsYXN0U3luY2VkQXQiOjE0OTczNjI5NzkwMTJ9%22%7D'; } function initializeEmptyKrgCrb() { - setCookie('krg_crb', getEmptyKrgCrb()); + setLocalStorageItem('krg_crb', getEmptyKrgCrb()); } - function getExpectedKrakenParams(excludeUserIds, excludeKrux, expectedRawCRB) { + function initializeEmptyKrgCrbCookie() { + setCookie('krg_crb', getEmptyKrgCrbOldStyle()); + } + + function getExpectedKrakenParams(excludeUserIds, excludeKrux, expectedRawCRB, expectedRawCRBCookie) { var base = { timeout: 200, currency: 'USD', @@ -226,23 +241,14 @@ describe('kargo adapter tests', function () { ] }, pageURL: window.location.href, - rawCRB: expectedRawCRB + rawCRB: expectedRawCRBCookie, + rawCRBLocalStorage: expectedRawCRB }; if (excludeUserIds === true) { base.userIDs = { crbIDs: {} }; - } else if (excludeUserIds) { - if (excludeUserIds.uid) { - delete base.userIDs.kargoID; - delete base.userIDs.clientID; - delete base.userIDs.optOut; - } - - if (excludeUserIds.crb) { - base.userIDs.crbIDs = {}; - } } if (excludeKrux) { @@ -267,81 +273,86 @@ describe('kargo adapter tests', function () { expect(krakenParams).to.deep.equal(expected); } - it('works when all params and cookies are correctly set', function() { + it('works when all params and localstorage and cookies are correctly set', function() { initializeKruxUser(); initializeKruxSegments(); - initializeKrgUid(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb())); + testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); + }); + + it('works when all params and cookies are correctly set but no localstorage', function() { + initializeKruxUser(); + initializeKruxSegments(); + initializeKrgCrb(true); + testBuildRequests(getExpectedKrakenParams(undefined, undefined, null, getKrgCrbOldStyle())); }); it('gracefully handles nothing being set', function() { - testBuildRequests(getExpectedKrakenParams(true, true, null)); + testBuildRequests(getExpectedKrakenParams(true, true, null, null)); }); it('gracefully handles browsers without localStorage', function() { simulateNoLocalStorage(); - initializeKrgUid(); - initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(false, true, getKrgCrb())); + testBuildRequests(getExpectedKrakenParams(true, true, null, null)); }); - it('handles empty yet valid Kargo CRBs and UIDs', function() { + it('handles empty yet valid Kargo CRB', function() { initializeKruxUser(); initializeKruxSegments(); - initializeEmptyKrgUid(); initializeEmptyKrgCrb(); - testBuildRequests(getExpectedKrakenParams(true, undefined, getEmptyKrgCrb())); + initializeEmptyKrgCrbCookie(); + testBuildRequests(getExpectedKrakenParams(true, undefined, getEmptyKrgCrb(), getEmptyKrgCrbOldStyle())); }); - it('handles broken Kargo UIDs', function() { + it('handles broken Kargo CRBs where base64 encoding is invalid', function() { initializeKruxUser(); initializeKruxSegments(); - initializeInvalidKrgUid(); - initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams({uid: true}, undefined, getKrgCrb())); + initializeInvalidKrgCrbType1(); + testBuildRequests(getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType1(), null)); }); - it('handles broken Kargo CRBs where top level JSON is invalid', function() { + it('handles broken Kargo CRBs where top level JSON is invalid on cookie', function() { initializeKruxUser(); initializeKruxSegments(); - initializeKrgUid(); - initializeInvalidKrgCrbType1(); - testBuildRequests(getExpectedKrakenParams({crb: true}, undefined, getInvalidKrgCrbType1())); + initializeInvalidKrgCrbType1Cookie(); + testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType1())); }); - it('handles broken Kargo CRBs where inner base 64 is invalid', function() { + it('handles broken Kargo CRBs where decoded JSON is invalid', function() { initializeKruxUser(); initializeKruxSegments(); - initializeKrgUid(); initializeInvalidKrgCrbType2(); - testBuildRequests(getExpectedKrakenParams({crb: true}, undefined, getInvalidKrgCrbType2())); + testBuildRequests(getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType2(), null)); + }); + + it('handles broken Kargo CRBs where inner base 64 is invalid on cookie', function() { + initializeKruxUser(); + initializeKruxSegments(); + initializeInvalidKrgCrbType2Cookie(); + testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType2OldStyle())); }); - it('handles broken Kargo CRBs where inner JSON is invalid', function() { + it('handles broken Kargo CRBs where inner JSON is invalid on cookie', function() { initializeKruxUser(); initializeKruxSegments(); - initializeKrgUid(); - initializeInvalidKrgCrbType3(); - testBuildRequests(getExpectedKrakenParams({crb: true}, undefined, getInvalidKrgCrbType3())); + initializeInvalidKrgCrbType3Cookie(); + testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType3OldStyle())); }); it('handles a non-existant currency object on the config', function() { simulateNoCurrencyObject(); initializeKruxUser(); initializeKruxSegments(); - initializeKrgUid(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb())); + testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); }); it('handles no ad server currency being set on the currency object in the config', function() { simulateNoAdServerCurrency(); initializeKruxUser(); initializeKruxSegments(); - initializeKrgUid(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb())); + testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); }); }); @@ -429,10 +440,10 @@ describe('kargo adapter tests', function () { describe('user sync handler', function() { const clientId = '74c81cbb-7d07-46d9-be9b-68ccb291c949'; - var shouldSimulateOutdatedBrowser, uid, isActuallyOutdatedBrowser; + var shouldSimulateOutdatedBrowser, crb, isActuallyOutdatedBrowser; beforeEach(() => { - uid = {}; + crb = {}; shouldSimulateOutdatedBrowser = false; isActuallyOutdatedBrowser = false; @@ -455,8 +466,8 @@ describe('kargo adapter tests', function () { }); } - sandbox.stub(spec, '_getUid').callsFake(function() { - return uid; + sandbox.stub(spec, '_getCrb').callsFake(function() { + return crb; }); }); @@ -469,7 +480,7 @@ describe('kargo adapter tests', function () { } function turnOnClientId() { - uid.clientId = clientId; + crb.clientId = clientId; } function simulateOutdatedBrowser() { From 876a714d7cadd402ae98b3ba0342d94bf884cdb0 Mon Sep 17 00:00:00 2001 From: ReklamStoreIT <48473631+ReklamStoreIT@users.noreply.github.com> Date: Tue, 26 Mar 2019 17:35:41 +0300 Subject: [PATCH 1108/1594] ReklamStore Bid Adapter (#3634) * ReklamStore Bid Adapter ReklamStore Bid Adapter * Added unit test for user sync Added unit test for user sync * Update bid adapter Update bid adapter --- modules/reklamstoreBidAdapter.js | 149 ++++++++++++++++++ modules/reklamstoreBidAdapter.md | 32 ++++ .../modules/reklamstoreBidAdapter_spec.js | 85 ++++++++++ 3 files changed, 266 insertions(+) create mode 100644 modules/reklamstoreBidAdapter.js create mode 100644 modules/reklamstoreBidAdapter.md create mode 100644 test/spec/modules/reklamstoreBidAdapter_spec.js diff --git a/modules/reklamstoreBidAdapter.js b/modules/reklamstoreBidAdapter.js new file mode 100644 index 00000000000..be484822860 --- /dev/null +++ b/modules/reklamstoreBidAdapter.js @@ -0,0 +1,149 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'reklamstore'; +const ENDPOINT_URL = '//ads.rekmob.com/m/prebid'; +const CURRENCY = 'USD'; +const TIME_TO_LIVE = 360; + +export const spec = { + code: BIDDER_CODE, + 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 !!(bid.params.regionId); + }, + /** + * 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 url = bidderRequest.refererInfo.referer; + let requests = []; + utils._each(validBidRequests, function(bid) { + requests.push({ + method: 'GET', + url: ENDPOINT_URL, + data: { + regionId: bid.params.regionId, + dt: getDeviceType(), + os: getOS(), + dbg: 1, + ref: extractDomain(url), + _: (new Date().getTime()), + mobile_web: 1 + }, + bidId: bid.bidId + }); + }); + return requests; + }, + + /** + * 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) { + try { + const bidResponse = serverResponse.body; + const bidResponses = []; + if (bidResponse) { + bidResponses.push({ + requestId: bidRequest.bidId, + cpm: parseFloat(bidResponse.cpm), + width: bidResponse.w, + height: bidResponse.h, + creativeId: bidResponse.adId || 1, + currency: CURRENCY, + netRevenue: false, + ttl: TIME_TO_LIVE, + ad: bidResponse.ad + }); + } + return bidResponses; + } catch (err) { + utils.logError(err); + return []; + } + }, + /** + * 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) { + const syncs = []; + utils._each(serverResponses, function(bidResponse) { + utils._each(bidResponse.body.syncs, function(sync) { + if (syncOptions.pixelEnabled && sync.type == 'image') { + syncs.push({ + type: sync.type, + url: sync.url + }); + } else if (syncOptions.iframeEnabled && sync.type == 'iframe') { + syncs.push({ + type: sync.type, + url: sync.url + }); + } + }); + }); + return syncs; + } +} +registerBidder(spec); + +function getDeviceType() { + let PHONE = 0; + let TABLET = 2; + let DESKTOP = 3; + if (isPhone()) { + return PHONE; + } else if (isTablet()) { + return TABLET; + } else { + return DESKTOP; + } +} +function isPhone() { + var check = false; + (function (a) { if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true })(navigator.userAgent || navigator.vendor || window.opera); + return check; +} +function isTablet() { + var check = false; + (function(a) { if (/ipad|android|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(a)) { check = true; } })(navigator.userAgent || navigator.vendor || window.opera); + return check; +} +function getOS() { + var ua = navigator.userAgent; + if (ua.match(/(iPhone|iPod|iPad)/)) { + return '1'; + } else if (ua.match(/Android/)) { + return '0'; + } else { + return '3'; + } +} +function extractDomain(url) { + var domain; + if (url.indexOf('://') > -1) { + domain = url.split('/')[2]; + } else { + domain = url.split('/')[0]; + } + domain = domain.split(':')[0]; + return domain; +} diff --git a/modules/reklamstoreBidAdapter.md b/modules/reklamstoreBidAdapter.md new file mode 100644 index 00000000000..8615341f5cc --- /dev/null +++ b/modules/reklamstoreBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +Module Name: ReklamStore Bidder Adapter +Module Type: Bidder Adapter +Maintainer: it@reklamstore.com + +# Description + +Module that connects to ReklamStore's demand sources. + +ReklamStore supports display. + + +# Test Parameters +# display +``` + + var adUnits = [ + { + code: 'banner-ad-div', + sizes: [[300, 250]], + bids: [ + { + bidder: 'reklamstore', + params: { + regionId:532211 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/reklamstoreBidAdapter_spec.js b/test/spec/modules/reklamstoreBidAdapter_spec.js new file mode 100644 index 00000000000..3ac40e20eaf --- /dev/null +++ b/test/spec/modules/reklamstoreBidAdapter_spec.js @@ -0,0 +1,85 @@ +import { expect } from 'chai'; +import { spec } from 'modules/reklamstoreBidAdapter'; + +describe('reklamstoreBidAdapterTests', function() { + let bidRequestData = { + bids: [ + { + bidder: 'reklamstore', + params: { + regionId: 532211 + }, + sizes: [[300, 250]] + } + ] + }; + let request = []; + + it('validate_params', function() { + expect( + spec.isBidRequestValid({ + bidder: 'reklamstore', + params: { + regionId: 532211 + } + }) + ).to.equal(true); + }); + + it('validate_generated_params', function() { + let bidderRequest = { + refererInfo: { + referer: 'http://reklamstore.com' + } + }; + request = spec.buildRequests(bidRequestData.bids, bidderRequest); + let req_data = request[0].data; + + expect(req_data.regionId).to.equal(532211); + }); + + const serverResponse = { + body: + { + cpm: 1.2, + ad: 'Ad html', + w: 300, + h: 250, + syncs: [{ + type: 'image', + url: 'http://link1' + }, + { + type: 'iframe', + url: 'http://link2' + } + ] + } + }; + + it('validate_response_params', function() { + let bids = spec.interpretResponse(serverResponse, bidRequestData.bids[0]); + expect(bids).to.have.lengthOf(1); + + let bid = bids[0]; + expect(bid.ad).to.equal('Ad html'); + expect(bid.cpm).to.equal(1.2); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.currency).to.equal('USD'); + }); + + it('should return no syncs when pixel syncing is disabled', function () { + const syncs = spec.getUserSyncs({ pixelEnabled: false }, [serverResponse]); + expect(syncs).to.deep.equal([]); + }); + + it('should return user syncs', function () { + const syncs = spec.getUserSyncs({pixelEnabled: true, iframeEnabled: true}, [serverResponse]); + const expected = [ + { type: 'image', url: 'http://link1' }, + { type: 'iframe', url: 'http://link2' }, + ]; + expect(syncs).to.deep.equal(expected); + }); +}); From cc80fe3257489ab0a458d87480f2819bf8a2d1fc Mon Sep 17 00:00:00 2001 From: HolzAndrew Date: Tue, 26 Mar 2019 10:42:02 -0400 Subject: [PATCH 1109/1594] support userId module (#3675) * use unit id being sent instead of hard coded auid * make multiple requests * removes commented out code. adds aus param back * hardcodes vht, vwd, aus * arrays should have commas * adds aus check to test * updates md file with new sizes syntax * updates md file with new sizes syntax * adds note on md about size option * size updates * adds prebid consortium id --- modules/yieldmoBidAdapter.js | 16 ++++++++++++ test/spec/modules/yieldmoBidAdapter_spec.js | 28 +++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 556249cd73b..d904791d29a 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -40,8 +40,16 @@ export const spec = { w: localWindow.innerWidth, h: localWindow.innerHeight }; + bidRequests.forEach((request) => { serverRequest.p.push(addPlacement(request)); + const userId = getUserId(request) + if (userId) { + const pubcid = userId.pubcid; + serverRequest.pubcid = pubcid; + } else { + serverRequest.pubcid = request.crumbs.pubcid; + } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { @@ -302,3 +310,11 @@ function isSuperSandboxedIframe() { function isMraid() { return !!(window.mraid); } + +function getUserId(request) { + let userId; + if (request && request.userId && typeof request.userId === 'object') { + userId = request.userId; + } + return userId; +} diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 45baecf9617..80a9265a5c2 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -14,7 +14,10 @@ describe('YieldmoAdapter', function () { sizes: [[300, 250], [300, 600]], bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' + auctionId: '1d1a030790a475', + crumbs: { + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' + } }; let bidArray = [bid]; @@ -58,7 +61,11 @@ describe('YieldmoAdapter', function () { sizes: [[300, 250], [300, 600]], bidId: '123456789', bidderRequestId: '987654321', - auctionId: '0246810' + auctionId: '0246810', + crumbs: { + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' + } + }); // multiple placements @@ -91,6 +98,23 @@ describe('YieldmoAdapter', function () { expect(data.hasOwnProperty('h')).to.be.true; expect(data.hasOwnProperty('w')).to.be.true; }) + + it('should add pubcid as parameter of request', function () { + const pubcidBid = { + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + userId: { + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2' + } + }; + const data = spec.buildRequests([pubcidBid]).data; + expect(data.pubcid).to.deep.equal('c604130c-0144-4b63-9bf2-c2bd8c8d86da2'); + }) }); describe('interpretResponse', function () { From c1fbba26c1803f8f24b21492c295593aec8ff916 Mon Sep 17 00:00:00 2001 From: alexkh13 Date: Tue, 26 Mar 2019 17:46:16 +0200 Subject: [PATCH 1110/1594] Cedato new bid adapter (#3629) * Cedato new bid adapter * Added GDPR support for Cedato bid adapter --- modules/cedatoBidAdapter.js | 154 +++++++++++++++++++++ modules/cedatoBidAdapter.md | 53 +++++++ test/spec/modules/cedatoBidAdapter_spec.js | 87 ++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 modules/cedatoBidAdapter.js create mode 100644 modules/cedatoBidAdapter.md create mode 100644 test/spec/modules/cedatoBidAdapter_spec.js diff --git a/modules/cedatoBidAdapter.js b/modules/cedatoBidAdapter.js new file mode 100644 index 00000000000..03ee93792c7 --- /dev/null +++ b/modules/cedatoBidAdapter.js @@ -0,0 +1,154 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'cedato'; +const BID_URL = '//h.cedatoplayer.com/hb'; +const SYNC_URL = '//h.cedatoplayer.com/hb_usync?uid={UUID}'; +const COOKIE_NAME = 'hb-cedato-id'; +const UUID_LEN = 36; +const TTL = 10000; +const CURRENCY = 'USD'; +const FIRST_PRICE = 1; +const NET_REVENUE = true; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: function(bid) { + return !!( + bid && + bid.params && + bid.params.player_id && + utils.checkCookieSupport() && + utils.cookiesAreEnabled() + ); + }, + + buildRequests: function(bidRequests, bidderRequest) { + const req = bidRequests[Math.floor(Math.random() * bidRequests.length)]; + const params = req.params; + const at = FIRST_PRICE; + const site = { id: params.player_id, domain: document.domain }; + const device = { ua: navigator.userAgent, ip: '' }; + const user = { id: getUserID() } + const cur = [ CURRENCY ]; + const tmax = bidderRequest.timeout; + + const imp = bidRequests.map(req => { + const banner = { 'format': getFormats(utils.deepAccess(req, 'mediaTypes.banner.sizes')) }; + const bidfloor = params.bidfloor !== undefined + ? Number(params.bidfloor) : 1; + const bidfloorcur = CURRENCY; + const bidId = req.bidId; + + return { + bidId, + banner, + bidfloor, + bidfloorcur, + }; + }); + + const payload = { + at, + site, + device, + user, + imp, + cur, + tmax, + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr_consent = { + consent_string: bidderRequest.gdprConsent.consentString, + consent_required: bidderRequest.gdprConsent.gdprApplies + }; + } + + return { + method: 'POST', + url: BID_URL, + data: JSON.stringify(payload), + }; + }, + + interpretResponse: function(resp) { + if (resp.body === '') return []; + + const bids = resp.body.seatbid[0].bid.map(bid => { + const cpm = bid.price; + const requestId = bid.uuid; + const width = bid.w; + const height = bid.h; + const creativeId = bid.crid; + const dealId = bid.dealid; + const currency = resp.body.cur; + const netRevenue = NET_REVENUE; + const ttl = TTL; + const ad = bid.adm; + + return { + cpm, + requestId, + width, + height, + creativeId, + dealId, + currency, + netRevenue, + ttl, + ad, + }; + }); + + return bids; + }, + + getUserSyncs: function(syncOptions, resps, gdprConsent) { + const syncs = []; + if (syncOptions.pixelEnabled) { + resps.forEach(() => { + const uuid = getUserID(); + const syncUrl = SYNC_URL; + let params = ''; + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + if (typeof gdprConsent.gdprApplies === 'boolean') { + params += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + params += `?gdpr_consent=${gdprConsent.consentString}`; + } + } + syncs.push({ + type: 'image', + url: syncUrl.replace('{UUID}', uuid) + params, + }); + }); + } + return syncs; + } +} + +const getUserID = () => { + const cookieName = COOKIE_NAME; + const uuidLen = UUID_LEN; + + const i = document.cookie.indexOf(cookieName); + + if (i === -1) { + const uuid = utils.generateUUID(); + document.cookie = `${cookieName}=${uuid}; path=/`; + return uuid; + } + + const j = i + cookieName.length + 1; + return document.cookie.substring(j, j + uuidLen); +}; + +const getFormats = arr => arr.map((s) => { + return { w: s[0], h: s[1] }; +}); + +registerBidder(spec); diff --git a/modules/cedatoBidAdapter.md b/modules/cedatoBidAdapter.md new file mode 100644 index 00000000000..99f8d839220 --- /dev/null +++ b/modules/cedatoBidAdapter.md @@ -0,0 +1,53 @@ +# Overview + +``` +Module Name: Cedato Bidder Adapter +Module Type: Bidder Adapter +Maintainer: alexk@cedato.com +``` + +# Description + +Connects to Cedato bidder. +Cedato adapter supports only Banner at the moment. + +# Test Parameters +``` +var adUnits = [ + // Banner + { + code: 'div-gpt-ad-1460505748561-0', + mediaTypes: { + banner: { + // You can choose one of them + sizes: [ + [300, 250], + [300, 600], + [240, 400], + [728, 90], + ] + } + }, + bids: [ + { + bidder: "cedato", + params: { + player_id: 1450133326, + } + } + ] + } +]; + +pbjs.que.push(() => { + pbjs.setConfig({ + userSync: { + syncEnabled: true, + enabledBidders: ['cedato'], + pixelEnabled: true, + syncsPerBidder: 200, + syncDelay: 100, + }, + }); +}); +``` diff --git a/test/spec/modules/cedatoBidAdapter_spec.js b/test/spec/modules/cedatoBidAdapter_spec.js new file mode 100644 index 00000000000..d6c1333c262 --- /dev/null +++ b/test/spec/modules/cedatoBidAdapter_spec.js @@ -0,0 +1,87 @@ +import {expect} from 'chai'; +import {spec} from 'modules/cedatoBidAdapter'; + +describe('the cedato adapter', function () { + function getValidBidObject() { + return { + bidId: 123, + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + params: { + player_id: 1450133326, + } + }; + }; + + describe('isBidRequestValid', function() { + var bid; + + beforeEach(function() { + bid = getValidBidObject(); + }); + + it('should fail validation if the bid isn\'t defined or not an object', function() { + var result = spec.isBidRequestValid(); + + expect(result).to.equal(false); + + result = spec.isBidRequestValid('not an object'); + + expect(result).to.equal(false); + }); + }); + describe('buildRequests', function() { + var bid, bidRequestObj; + + beforeEach(function() { + bid = getValidBidObject(); + bidRequestObj = {refererInfo: {referer: 'prebid.js'}}; + }); + + it('should build a very basic request', function() { + var request = spec.buildRequests([bid], bidRequestObj); + expect(request.method).to.equal('POST'); + }); + }); + + describe('interpretResponse', function() { + var serverResponse; + + beforeEach(function() { + serverResponse = { + body: { + bidid: '0.36157306192821', + seatbid: [ + { + seat: '0', + bid: [{ + gp: { + 'negative': 0.496954, + 'positive': 0.503046, + 'class': '0' + }, + id: '0.75549202124378', + adomain: 'cedato.com', + uuid: '2f4a613a702b6c', + crid: '1450133326', + adm: "
\n\n\n", + h: 250, + w: 300, + price: '0.1' + }] + } + ], + cur: 'USD' + } + }; + }); + + it('should return an array of bid responses', function() { + var responses = spec.interpretResponse(serverResponse); + expect(responses).to.be.an('array').with.length(1); + }); + }); +}); From 0f01ce3ed55137bee78339f80836c72982184822 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 26 Mar 2019 11:23:21 -0700 Subject: [PATCH 1111/1594] Rubicon Bid Adapter: custom price granularity fix (#3670) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * Fix rubicon adapter price granularity, rename config property name customPriceBucket from customPriceGranularity * add unit test for getPriceGranularity * update getPriceGranularity function for better readability * Update rubiconBidAdapter.js updating per review * adding check before setting custom --- modules/rubiconBidAdapter.js | 42 +++++++++++---------- test/spec/modules/rubiconBidAdapter_spec.js | 36 +++++++++++++++++- 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index c5fb4486d20..69da9ab6db3 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -843,27 +843,29 @@ export function determineRubiconVideoSizeId(bid) { return utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`) === 'outstream' ? 203 : 201; } +/** + * @param {PrebidConfig} config + * @returns {{ranges: {ranges: Object[]}}} + */ export function getPriceGranularity(config) { - const granularityMappings = { - low: [{max: 5.00, increment: 0.50}], - medium: [{max: 20.00, increment: 0.10}], - high: [{max: 20.00, increment: 0.01}], - auto: [ - {max: 5.00, increment: 0.05}, - {min: 5.00, max: 10.00, increment: 0.10}, - {min: 10.00, max: 20.00, increment: 0.50} - ], - dense: [ - {max: 3.00, increment: 0.01}, - {min: 3.00, max: 8.00, increment: 0.05}, - {min: 8.00, max: 20.00, increment: 0.50} - ] - } - if (config.getConfig('priceGranularity') === 'custom') { - return {ranges: config.getConfig('customPriceGranularity').buckets} - } else { - return {ranges: granularityMappings[config.getConfig('priceGranularity')]} - } + return { + ranges: { + low: [{max: 5.00, increment: 0.50}], + medium: [{max: 20.00, increment: 0.10}], + high: [{max: 20.00, increment: 0.01}], + auto: [ + {max: 5.00, increment: 0.05}, + {min: 5.00, max: 10.00, increment: 0.10}, + {min: 10.00, max: 20.00, increment: 0.50} + ], + dense: [ + {max: 3.00, increment: 0.01}, + {min: 3.00, max: 8.00, increment: 0.05}, + {min: 8.00, max: 20.00, increment: 0.50} + ], + custom: config.getConfig('customPriceBucket') && config.getConfig('customPriceBucket').buckets + }[config.getConfig('priceGranularity')] + }; } // Function to validate the required video params diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 81816d42407..53fa45e89ae 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1,6 +1,6 @@ import {expect} from 'chai'; import adapterManager from 'src/adapterManager'; -import {spec, masSizeOrdering, resetUserSync, hasVideoMediaType, FASTLANE_ENDPOINT} from 'modules/rubiconBidAdapter'; +import {spec, getPriceGranularity, masSizeOrdering, resetUserSync, hasVideoMediaType, FASTLANE_ENDPOINT} from 'modules/rubiconBidAdapter'; import {parse as parseQuery} from 'querystring'; import {newBidder} from 'src/adapters/bidderFactory'; import {userSync} from 'src/userSync'; @@ -2042,6 +2042,40 @@ describe('the rubicon adapter', function () { }); }); }); + + describe('get price granularity', function() { + it('should return correct buckets for all price granularity values', function() { + const CUSTOM_PRICE_BUCKET_ITEM = {min: 0, max: 5, increment: 0.5}; + + const mockConfig = { + priceGranularity: undefined, + customPriceBucket: { + buckets: [CUSTOM_PRICE_BUCKET_ITEM] + } + }; + sandbox.stub(config, 'getConfig').callsFake(key => { + return mockConfig[key]; + }); + + [ + {key: 'low', val: {max: 5.00, increment: 0.50}}, + {key: 'medium', val: {max: 20.00, increment: 0.10}}, + {key: 'high', val: {max: 20.00, increment: 0.01}}, + {key: 'auto', val: {max: 5.00, increment: 0.05}}, + {key: 'dense', val: {max: 3.00, increment: 0.01}}, + {key: 'custom', val: CUSTOM_PRICE_BUCKET_ITEM}, + + ].forEach(kvPair => { + mockConfig.priceGranularity = kvPair.key; + const result = getPriceGranularity(config); + expect(typeof result).to.equal('object'); + expect(result).to.haveOwnProperty('ranges'); + expect(Array.isArray(result.ranges)).to.equal(true); + expect(result.ranges.length).to.be.greaterThan(0) + expect(result.ranges[0]).to.deep.equal(kvPair.val); + }); + }); + }); }); function clone(obj) { From 9d8a37b4a6cec55e7277e37903f0a403c2356092 Mon Sep 17 00:00:00 2001 From: Igor Aksenov Date: Tue, 26 Mar 2019 21:27:26 +0300 Subject: [PATCH 1112/1594] Added MediaFuse Lift alias to Orbitsoft adapter (#3682) --- modules/orbitsoftBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/orbitsoftBidAdapter.js b/modules/orbitsoftBidAdapter.js index 9f79a691df1..927c285f7f0 100644 --- a/modules/orbitsoftBidAdapter.js +++ b/modules/orbitsoftBidAdapter.js @@ -25,7 +25,7 @@ let styleParamsMap = { }; export const spec = { code: BIDDER_CODE, - aliases: ['oas', '152media'], // short code and customer aliases + aliases: ['oas', 'mediafuseLift'], // short code and customer aliases isBidRequestValid: function (bid) { switch (true) { case !('params' in bid): From e74bf6cb7e88f3e6f653cc5f370f585cfb0c0f2c Mon Sep 17 00:00:00 2001 From: Kelvin Chappell Date: Tue, 26 Mar 2019 18:39:19 +0000 Subject: [PATCH 1113/1594] Add buyer data to Index bid responses (#3585) Following format specified in https://github.com/prebid/Prebid.js/issues/3115 --- modules/ixBidAdapter.js | 5 +++++ test/spec/modules/ixBidAdapter_spec.js | 28 ++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index 37a3dccbb9f..b1cc459d972 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -77,6 +77,11 @@ function parseBid(rawBid, currency) { bid.currency = currency; bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-'; + bid.meta = {}; + bid.meta.networkId = utils.deepAccess(rawBid, 'ext.dspid'); + bid.meta.brandId = utils.deepAccess(rawBid, 'ext.advbrandid'); + bid.meta.brandName = utils.deepAccess(rawBid, 'ext.advbrand'); + return bid; } diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 6bf7a0331a8..d88b783a785 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -424,7 +424,12 @@ describe('IndexexchangeAdapter', function () { currency: 'USD', ttl: 35, netRevenue: true, - dealId: undefined + dealId: undefined, + meta: { + networkId: 50, + brandId: 303325, + brandName: 'OECTA' + } } ]; const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }); @@ -445,7 +450,12 @@ describe('IndexexchangeAdapter', function () { currency: 'USD', ttl: 35, netRevenue: true, - dealId: undefined + dealId: undefined, + meta: { + networkId: 50, + brandId: 303325, + brandName: 'OECTA' + } } ]; const result = spec.interpretResponse({ body: bidResponse }); @@ -466,7 +476,12 @@ describe('IndexexchangeAdapter', function () { currency: 'JPY', ttl: 35, netRevenue: true, - dealId: undefined + dealId: undefined, + meta: { + networkId: 50, + brandId: 303325, + brandName: 'OECTA' + } } ]; const result = spec.interpretResponse({ body: bidResponse }); @@ -487,7 +502,12 @@ describe('IndexexchangeAdapter', function () { currency: 'USD', ttl: 35, netRevenue: true, - dealId: 'deal' + dealId: 'deal', + meta: { + networkId: 50, + brandId: 303325, + brandName: 'OECTA' + } } ]; const result = spec.interpretResponse({ body: bidResponse }); From cce5b6e3b694ed2691ad51d2dde6380c0bd73dc2 Mon Sep 17 00:00:00 2001 From: Benjamin Clot Date: Tue, 26 Mar 2019 19:48:22 +0100 Subject: [PATCH 1114/1594] Ensure width and height are integers (#3674) * Ensure width and height are integers Some bidders (like OpenX) return bid responses with width and height as strings. Let's follow the docs and ensure that they indeed are integers, avoiding some strict comparison surprises. * lint * typo * Update bidderFactory.js * Update bidderFactory.js * Update bidderFactory.js --- src/adapters/bidderFactory.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index a65c657cbb5..3306011d6aa 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -419,7 +419,9 @@ export function getIabSubCategory(bidderCode, category) { // check that the bid has a width and height set function validBidSize(adUnitCode, bid, bidRequests) { - if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) { + 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; } @@ -432,8 +434,8 @@ function validBidSize(adUnitCode, bid, bidRequests) { // response that does not explicitly set width or height if (parsedSizes.length === 1) { const [ width, height ] = parsedSizes[0].split('x'); - bid.width = width; - bid.height = height; + bid.width = parseInt(width, 10); + bid.height = parseInt(height, 10); return true; } From 6d8ad70f4234872904aef9cad95e9bb0fd3a5108 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 26 Mar 2019 16:02:33 -0400 Subject: [PATCH 1115/1594] Prebid 2.8.0 Release --- package-lock.json | 826 +++++++++++++++++++++++++--------------------- package.json | 2 +- 2 files changed, 444 insertions(+), 384 deletions(-) diff --git a/package-lock.json b/package-lock.json index 54eddd62325..00f5427b9f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.4.0", + "version": "2.8.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,18 +14,18 @@ } }, "@babel/core": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.3.4.tgz", - "integrity": "sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.0.tgz", + "integrity": "sha512-Dzl7U0/T69DFOTwqz/FJdnOSWS57NpjNfCwMKHABr589Lg8uX1RrlBIJ7L5Dubt/xkLsx0xH5EBFzlBVes1ayA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.3.4", - "@babel/helpers": "^7.2.0", - "@babel/parser": "^7.3.4", - "@babel/template": "^7.2.2", - "@babel/traverse": "^7.3.4", - "@babel/types": "^7.3.4", + "@babel/generator": "^7.4.0", + "@babel/helpers": "^7.4.0", + "@babel/parser": "^7.4.0", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.0", + "@babel/types": "^7.4.0", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -36,12 +36,12 @@ } }, "@babel/generator": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", - "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", + "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", "dev": true, "requires": { - "@babel/types": "^7.3.4", + "@babel/types": "^7.4.0", "jsesc": "^2.5.1", "lodash": "^4.17.11", "source-map": "^0.5.0", @@ -68,25 +68,25 @@ } }, "@babel/helper-call-delegate": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", - "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.0.tgz", + "integrity": "sha512-SdqDfbVdNQCBp3WhK2mNdDvHd3BD6qbmIc43CAyjnsfCmgHMeqgDcM3BzY2lchi7HBJGJ2CVdynLWbezaE4mmQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-hoist-variables": "^7.4.0", + "@babel/traverse": "^7.4.0", + "@babel/types": "^7.4.0" } }, "@babel/helper-define-map": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", - "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.0.tgz", + "integrity": "sha512-wAhQ9HdnLIywERVcSvX40CEJwKdAa1ID4neI9NXQPDOHwwA+57DqwLiPEVy2AIyWzAk0CQ8qx4awO0VUURwLtA==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" + "@babel/types": "^7.4.0", + "lodash": "^4.17.11" } }, "@babel/helper-explode-assignable-expression": { @@ -120,12 +120,12 @@ } }, "@babel/helper-hoist-variables": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", - "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.0.tgz", + "integrity": "sha512-/NErCuoe/et17IlAQFKWM24qtyYYie7sFIrW/tIQXpck6vAu2hhtYYsKLBWQV+BQZMbcIYPU/QMYuTufrY4aQw==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.4.0" } }, "@babel/helper-member-expression-to-functions": { @@ -198,15 +198,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.3.4.tgz", - "integrity": "sha512-pvObL9WVf2ADs+ePg0jrqlhHoxRXlOa+SHRHzAXIz2xkYuOHfGl+fKxPMaS4Fq+uje8JQPobnertBBvyrWnQ1A==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.0.tgz", + "integrity": "sha512-PVwCVnWWAgnal+kJ+ZSAphzyl58XrFeSKSAJRiqg5QToTsjL+Xu1f9+RJ+d+Q0aPhPfBGaYfkox66k86thxNSg==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.0.0", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.3.4", - "@babel/types": "^7.3.4" + "@babel/traverse": "^7.4.0", + "@babel/types": "^7.4.0" } }, "@babel/helper-simple-access": { @@ -220,12 +220,12 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz", + "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.4.0" } }, "@babel/helper-wrap-function": { @@ -241,14 +241,14 @@ } }, "@babel/helpers": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.3.1.tgz", - "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.2.tgz", + "integrity": "sha512-gQR1eQeroDzFBikhrCccm5Gs2xBjZ57DNjGbqTaHo911IpmSxflOQWMAHPw/TXk8L3isv7s9lYzUkexOeTQUYg==", "dev": true, "requires": { - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.5", - "@babel/types": "^7.3.0" + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.0", + "@babel/types": "^7.4.0" } }, "@babel/highlight": { @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.4.tgz", - "integrity": "sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.2.tgz", + "integrity": "sha512-9fJTDipQFvlfSVdD/JBtkiY0br9BtfvW2R8wo6CX/Ej2eMuV0gWPk1M67Mt3eggQvBqYW1FCEk8BN7WvGm/g5g==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -290,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.4.tgz", - "integrity": "sha512-j7VQmbbkA+qrzNqbKHrBsW3ddFnOeva6wzSe/zB7T+xaxGc+RCpwo44wCmRixAIGRoIpmVgvzFzNJqQcO3/9RA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.0.tgz", + "integrity": "sha512-uTNi8pPYyUH2eWHyYWWSYJKwKg34hhgl4/dbejEjL+64OhbHjTX7wEVWMQl82tEmdDsGeu77+s8HHLS627h6OQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -310,14 +310,14 @@ } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz", - "integrity": "sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.0.tgz", + "integrity": "sha512-h/KjEZ3nK9wv1P1FSNb9G079jXrNYR0Ko+7XkOx85+gM24iZbPn0rh4vCftk+5QKY7y1uByFataBTmX7irEF1w==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.2.0" + "regexpu-core": "^4.5.4" } }, "@babel/plugin-syntax-async-generators": { @@ -366,9 +366,9 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.3.4.tgz", - "integrity": "sha512-Y7nCzv2fw/jEZ9f678MuKdMo99MFDJMT/PvD9LisrR5JDFcJH6vYeH6RnjVt3p5tceyGRvTtEN0VOlU+rgHZjA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.0.tgz", + "integrity": "sha512-EeaFdCeUULM+GPFEsf7pFcNSxM7hYjoj5fiYbyuiXobW4JhFnjAv9OWzNwHyHcKoPNpAfeRDuW6VyaXEDUBa7g==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -386,9 +386,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.3.4.tgz", - "integrity": "sha512-blRr2O8IOZLAOJklXLV4WhcEzpYafYQKSGT3+R26lWG41u/FODJuBggehtOwilVAcFu393v3OFj+HmaE6tVjhA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.0.tgz", + "integrity": "sha512-AWyt3k+fBXQqt2qb9r97tn3iBwFpiv9xdAiG+Gr2HpAZpuayvbL55yWrsV3MyHvXk/4vmSiedhDRl1YI2Iy5nQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -396,18 +396,18 @@ } }, "@babel/plugin-transform-classes": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.3.4.tgz", - "integrity": "sha512-J9fAvCFBkXEvBimgYxCjvaVDzL6thk0j0dBvCeZmIUDBwyt+nv6HfbImsSrWsYXfDNDivyANgJlFXDUWRTZBuA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.0.tgz", + "integrity": "sha512-XGg1Mhbw4LDmrO9rSTNe+uI79tQPdGs0YASlxgweYRLZqo/EQktjaOV4tchL/UZbM0F+/94uOipmdNGoaGOEYg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.1.0", + "@babel/helper-define-map": "^7.4.0", "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.3.4", - "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/helper-replace-supers": "^7.4.0", + "@babel/helper-split-export-declaration": "^7.4.0", "globals": "^11.1.0" } }, @@ -421,9 +421,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.3.2.tgz", - "integrity": "sha512-Lrj/u53Ufqxl/sGxyjsJ2XNtNuEjDyjpqdhMNh5aZ+XFOdThL46KBj27Uem4ggoezSYBxKWAil6Hu8HtwqesYw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.0.tgz", + "integrity": "sha512-HySkoatyYTY3ZwLI8GGvkRWCFrjAGXUHur5sMecmCIdIharnlcWWivOqDJI76vvmVZfzwb6G08NREsrY96RhGQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -460,9 +460,9 @@ } }, "@babel/plugin-transform-for-of": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz", - "integrity": "sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.0.tgz", + "integrity": "sha512-vWdfCEYLlYSxbsKj5lGtzA49K3KANtb8qCPQ1em07txJzsBwY+cKJzBHizj5fl3CCx7vt+WPdgDLTHmydkbQSQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -498,9 +498,9 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz", - "integrity": "sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.0.tgz", + "integrity": "sha512-iWKAooAkipG7g1IY0eah7SumzfnIT3WNhT4uYB2kIsvHnNSB6MDYVa5qyICSwaTBDBY2c4SnJ3JtEa6ltJd6Jw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", @@ -509,12 +509,12 @@ } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.3.4.tgz", - "integrity": "sha512-VZ4+jlGOF36S7TjKs8g4ojp4MEI+ebCQZdswWb/T9I4X84j8OtFAyjXjt/M16iIm5RIZn0UMQgg/VgIwo/87vw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.0.tgz", + "integrity": "sha512-gjPdHmqiNhVoBqus5qK60mWPp1CmYWp/tkh11mvb0rrys01HycEGD7NvvSoKXlWEfSM9TcL36CpsK8ElsADptQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.0.0", + "@babel/helper-hoist-variables": "^7.4.0", "@babel/helper-plugin-utils": "^7.0.0" } }, @@ -529,18 +529,18 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz", - "integrity": "sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.2.tgz", + "integrity": "sha512-NsAuliSwkL3WO2dzWTOL1oZJHm0TM8ZY8ZSxk2ANyKkt5SQlToGA4pzctmq1BEjoacurdwZ3xp2dCQWJkME0gQ==", "dev": true, "requires": { "regexp-tree": "^0.1.0" } }, "@babel/plugin-transform-new-target": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", - "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.0.tgz", + "integrity": "sha512-6ZKNgMQmQmrEX/ncuCwnnw1yVGoaOW5KpxNhoWI7pCQdA0uZ0HqHGqenCUIENAnxRjy2WwNQ30gfGdIgqJXXqw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -557,20 +557,20 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.3.3.tgz", - "integrity": "sha512-IrIP25VvXWu/VlBWTpsjGptpomtIkYrN/3aDp4UKm7xK6UxZY88kcJ1UwETbzHAlwN21MnNfwlar0u8y3KpiXw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.0.tgz", + "integrity": "sha512-Xqv6d1X+doyiuCGDoVJFtlZx0onAX0tnc3dY8w71pv/O0dODAbusVv2Ale3cGOwfiyi895ivOBhYa9DhAM8dUA==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.1.0", + "@babel/helper-call-delegate": "^7.4.0", "@babel/helper-get-function-arity": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-regenerator": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.3.4.tgz", - "integrity": "sha512-hvJg8EReQvXT6G9H2MvNPXkv9zK36Vxa1+csAVTpE1J3j0zlHplw76uudEbJxgvqZzAq9Yh45FLD4pk5mKRFQA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.0.tgz", + "integrity": "sha512-SZ+CgL4F0wm4npojPU6swo/cK4FcbLgxLd4cWpHaNXY/NJ2dpahODCqBbAwb2rDmVszVb3SSjnk9/vik3AYdBw==", "dev": true, "requires": { "regenerator-transform": "^0.13.4" @@ -635,88 +635,90 @@ } }, "@babel/preset-env": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.4.tgz", - "integrity": "sha512-2mwqfYMK8weA0g0uBKOt4FE3iEodiHy9/CW0b+nWXcbL+pGzLx8ESYc+j9IIxr6LTDHWKgPm71i9smo02bw+gA==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.2.tgz", + "integrity": "sha512-OEz6VOZaI9LW08CWVS3d9g/0jZA6YCn1gsKIy/fut7yZCJti5Lm1/Hi+uo/U+ODm7g4I6gULrCP+/+laT8xAsA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.3.4", + "@babel/plugin-proposal-object-rest-spread": "^7.4.0", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.0", "@babel/plugin-syntax-async-generators": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.3.4", + "@babel/plugin-transform-async-to-generator": "^7.4.0", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.3.4", - "@babel/plugin-transform-classes": "^7.3.4", + "@babel/plugin-transform-block-scoping": "^7.4.0", + "@babel/plugin-transform-classes": "^7.4.0", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.4.0", "@babel/plugin-transform-dotall-regex": "^7.2.0", "@babel/plugin-transform-duplicate-keys": "^7.2.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.4.0", "@babel/plugin-transform-function-name": "^7.2.0", "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.2.0", - "@babel/plugin-transform-modules-systemjs": "^7.3.4", + "@babel/plugin-transform-modules-commonjs": "^7.4.0", + "@babel/plugin-transform-modules-systemjs": "^7.4.0", "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", - "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.2", + "@babel/plugin-transform-new-target": "^7.4.0", "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.3.4", + "@babel/plugin-transform-parameters": "^7.4.0", + "@babel/plugin-transform-regenerator": "^7.4.0", "@babel/plugin-transform-shorthand-properties": "^7.2.0", "@babel/plugin-transform-spread": "^7.2.0", "@babel/plugin-transform-sticky-regex": "^7.2.0", "@babel/plugin-transform-template-literals": "^7.2.0", "@babel/plugin-transform-typeof-symbol": "^7.2.0", "@babel/plugin-transform-unicode-regex": "^7.2.0", - "browserslist": "^4.3.4", + "@babel/types": "^7.4.0", + "browserslist": "^4.4.2", + "core-js-compat": "^3.0.0", "invariant": "^2.2.2", "js-levenshtein": "^1.1.3", "semver": "^5.3.0" } }, "@babel/template": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", - "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz", + "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.2.2", - "@babel/types": "^7.2.2" + "@babel/parser": "^7.4.0", + "@babel/types": "^7.4.0" } }, "@babel/traverse": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", - "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.0.tgz", + "integrity": "sha512-/DtIHKfyg2bBKnIN+BItaIlEg5pjAnzHOIQe5w+rHAw/rg9g0V7T4rqPX8BJPfW11kt3koyjAnTNwCzb28Y1PA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.3.4", + "@babel/generator": "^7.4.0", "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.3.4", - "@babel/types": "^7.3.4", + "@babel/helper-split-export-declaration": "^7.4.0", + "@babel/parser": "^7.4.0", + "@babel/types": "^7.4.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", - "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -782,9 +784,9 @@ "dev": true }, "@sinonjs/commons": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.3.0.tgz", - "integrity": "sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", + "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -797,12 +799,20 @@ "dev": true, "requires": { "samsam": "1.3.0" + }, + "dependencies": { + "samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "dev": true + } } }, "@sinonjs/samsam": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.2.0.tgz", - "integrity": "sha512-j5F1rScewLtx6pbTK0UAjA3jJj4RYiSKOix53YWv+Jzy/AZ69qHxUpU8fwVLjyKbEEud9QrLpv6Ggs7WqTimYw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.1.tgz", + "integrity": "sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==", "dev": true, "requires": { "@sinonjs/commons": "^1.0.2", @@ -817,9 +827,9 @@ "dev": true }, "@types/node": { - "version": "8.10.40", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.40.tgz", - "integrity": "sha512-RRSjdwz63kS4u7edIwJUn8NqKLLQ6LyqF/X4+4jp38MBT3Vwetewi2N4dgJEshLbDwNgOJXNYoOwzVZUSSLhkQ==", + "version": "8.10.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.45.tgz", + "integrity": "sha512-tGVTbA+i3qfXsLbq9rEq/hezaHY55QxQLeXQL2ejNgFAxxrgu8eMmYIOsRcl7hN1uTLVsKOOYacV/rcJM3sfgQ==", "dev": true }, "JSONStream": { @@ -1289,9 +1299,9 @@ } }, "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.2.tgz", + "integrity": "sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==", "dev": true }, "async-limiter": { @@ -2590,28 +2600,12 @@ "callsite": "1.0.0" } }, - "big-integer": { - "version": "1.6.42", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.42.tgz", - "integrity": "sha512-3UQFKcRMx+5Z+IK5vYTMYK2jzLRJkt+XqyDdacgWgtMjjuifKpKTFneJLEgeBElOE2/lXZ1LcMcb5s8pwG2U8Q==", - "dev": true - }, "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 }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, "binary-extensions": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", @@ -2856,14 +2850,14 @@ } }, "browserslist": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.2.tgz", - "integrity": "sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.2.tgz", + "integrity": "sha512-zmJVLiKLrzko0iszd/V4SsjTaomFeoVzQGYYOYgRgsbh7WNh95RgDB0CmBdFWYs/3MyFSt69NypjL/h3iaddKQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000939", - "electron-to-chromium": "^1.3.113", - "node-releases": "^1.1.8" + "caniuse-lite": "^1.0.30000951", + "electron-to-chromium": "^1.3.116", + "node-releases": "^1.1.11" } }, "browserstack": { @@ -2875,14 +2869,31 @@ "https-proxy-agent": "^2.2.1" } }, - "browserstacktunnel-wrapper": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.4.tgz", - "integrity": "sha512-GCV599FUUxNOCFl3WgPnfc5dcqq9XTmMXoxWpqkvmk0R9TOIoqmjENNU6LY6DtgIL6WfBVbg/jmWtnM5K6UYSg==", + "browserstack-local": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.3.7.tgz", + "integrity": "sha512-ilZlmiy7XYJxsztYan7XueHVr3Ix9EVh/mCiYN1G53wRPEW/hg1KMsseM6UExzVbexEqFEfwjkBLeFlSqxh+bQ==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1", - "unzipper": "^0.9.3" + "is-running": "^2.0.0", + "ps-tree": "=1.1.1", + "sinon": "^1.17.6", + "temp-fs": "^0.9.9" + }, + "dependencies": { + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": ">=0.10.3 <1" + } + } } }, "buffer": { @@ -2930,12 +2941,6 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "buffer-indexof-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz", - "integrity": "sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8=", - "dev": true - }, "buffer-shims": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", @@ -2948,12 +2953,6 @@ "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", @@ -3089,9 +3088,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000939", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000939.tgz", - "integrity": "sha512-oXB23ImDJOgQpGjRv1tCtzAvJr4/OvrHi5SO2vUgB0g0xpdZZoA/BxfImiWfdwoYdUTtQrPsXsvYU/dmCSM8gg==", + "version": "1.0.30000953", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000953.tgz", + "integrity": "sha512-2stdF/q5MZTDhQ6uC65HWbSgI9UMKbc7+HKvlwH5JBIslKoD/J9dvabP4J4Uiifu3NljbHj3iMpfYflLSNt09A==", "dev": true }, "caseless": { @@ -3163,15 +3162,6 @@ } } }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3220,9 +3210,9 @@ "dev": true }, "chokidar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz", - "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -3236,7 +3226,7 @@ "normalize-path": "^3.0.0", "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", - "upath": "^1.1.0" + "upath": "^1.1.1" } }, "cipher-base": { @@ -3604,6 +3594,32 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" }, + "core-js-compat": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.0.0.tgz", + "integrity": "sha512-W/Ppz34uUme3LmXWjMgFlYyGnbo1hd9JvA0LNQ4EmieqVjg2GPYbj3H6tcdP2QGPGWdRKUqZVbVKLNIFVs/HiA==", + "dev": true, + "requires": { + "browserslist": "^4.5.1", + "core-js": "3.0.0", + "core-js-pure": "3.0.0", + "semver": "^5.6.0" + }, + "dependencies": { + "core-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0.tgz", + "integrity": "sha512-WBmxlgH2122EzEJ6GH8o9L/FeoUKxxxZ6q6VUxoTlsE4EvbTWKJb447eyVxTEuq0LpXjlq/kCB2qgBvsYRkLvQ==", + "dev": true + } + } + }, + "core-js-pure": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.0.0.tgz", + "integrity": "sha512-yPiS3fQd842RZDgo/TAKGgS0f3p2nxssF1H65DIZvZv0Od5CygP8puHXn3IQiM/39VAvgCbdaMQpresrbGgt9g==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -4252,6 +4268,12 @@ } } }, + "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": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -4407,9 +4429,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.113", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz", - "integrity": "sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==", + "version": "1.3.119", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.119.tgz", + "integrity": "sha512-3mtqcAWa4HgG+Djh/oNXlPH0cOH6MmtwxN1nHSaReb9P0Vn51qYPqYwLeoSuAX9loU1wrOBhFbiX3CkeIxPfgg==", "dev": true }, "elliptic": { @@ -4606,14 +4628,14 @@ } }, "es5-ext": { - "version": "0.10.48", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.48.tgz", - "integrity": "sha512-CdRvPlX/24Mj5L4NVxTs4804sxiS2CjVprgCmrgoDkdmjdY4D+ySHa7K3jJf8R40dFg0tIm3z/dk326LrnuSGw==", + "version": "0.10.49", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.49.tgz", + "integrity": "sha512-3NMEhi57E31qdzmYp2jwRArIUsj1HI/RxbQ4bgnSB+AIKIxsAmTiK83bYMifIcpWvEc3P1X30DhUKOqEtF/kvg==", "dev": true, "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", - "next-tick": "1" + "next-tick": "^1.0.0" } }, "es5-shim": { @@ -5630,13 +5652,13 @@ } }, "find-cache-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, "requires": { "commondir": "^1.0.1", - "make-dir": "^1.0.0", + "make-dir": "^2.0.0", "pkg-dir": "^3.0.0" } }, @@ -5650,26 +5672,15 @@ } }, "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "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": "^3.1.0", + "is-glob": "^4.0.0", "micromatch": "^3.0.4", "resolve-dir": "^1.0.1" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } } }, "fined": { @@ -5794,6 +5805,15 @@ "mime-types": "^2.1.12" } }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "~1.1" + } + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -6418,18 +6438,6 @@ } } }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, "ftp": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", @@ -6528,9 +6536,9 @@ }, "dependencies": { "readable-stream": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", - "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -6755,6 +6763,14 @@ "timed-out": "^4.0.1", "url-parse-lax": "^3.0.0", "url-to-options": "^1.0.1" + }, + "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": { @@ -6798,9 +6814,9 @@ } }, "gulp-cli": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", - "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.1.0.tgz", + "integrity": "sha512-txzgdFVlEPShBZus6JJyGyKJoBVDq6Do0ZQgIgx5RAsmhNVTDjymmOxpQvo3c20m66FldilS68ZXj2Q9w5dKbA==", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -6813,7 +6829,7 @@ "gulplog": "^1.0.0", "interpret": "^1.1.0", "isobject": "^3.0.1", - "liftoff": "^2.5.0", + "liftoff": "^3.1.0", "matchdep": "^2.0.0", "mute-stdout": "^1.0.0", "pretty-hrtime": "^1.0.0", @@ -7396,14 +7412,16 @@ } }, "gulp-uglify": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.1.tgz", - "integrity": "sha512-KVffbGY9d4Wv90bW/B1KZJyunLMyfHTBbilpDvmcrj5Go0/a1G3uVpt+1gRBWSw/11dqR3coJ1oWNTt1AiXuWQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", "dev": true, "requires": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", "gulplog": "^1.0.0", "has-gulplog": "^0.1.0", - "lodash": "^4.13.1", + "isobject": "^3.0.1", "make-error-cause": "^1.1.1", "safe-buffer": "^5.1.2", "through2": "^2.0.0", @@ -7568,26 +7586,17 @@ } }, "handlebars": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", - "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", + "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", "dev": true, "requires": { - "async": "^2.5.0", + "neo-async": "^2.6.0", "optimist": "^0.6.1", "source-map": "^0.6.1", "uglify-js": "^3.1.4" }, "dependencies": { - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7613,9 +7622,9 @@ }, "dependencies": { "ajv": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz", - "integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -7979,9 +7988,9 @@ } }, "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, "ignore": { @@ -8416,6 +8425,12 @@ "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", "dev": true }, + "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 + }, "is-ssh": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", @@ -8765,9 +8780,9 @@ "dev": true }, "js-yaml": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.2.tgz", - "integrity": "sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", + "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -8952,13 +8967,13 @@ } }, "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==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.5.0.tgz", + "integrity": "sha512-WFJaVwF+1DAgdS81Kbv1/UG1eIfEEzlt9CWLqzm306/MqrIYOxjUVmOdXrEpCefDR7gTl6CQ5Ym+t8RwUPGvJQ==", "dev": true, "requires": { "browserstack": "~1.5.1", - "browserstacktunnel-wrapper": "~2.0.2", + "browserstack-local": "^1.3.7", "q": "~1.5.0" } }, @@ -9197,13 +9212,13 @@ } }, "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", "dev": true, "requires": { "extend": "^3.0.0", - "findup-sync": "^2.0.0", + "findup-sync": "^3.0.0", "fined": "^1.0.1", "flagged-respawn": "^1.0.0", "is-plain-object": "^2.0.4", @@ -9212,12 +9227,6 @@ "resolve": "^1.1.7" } }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, "livereload-js": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", @@ -9234,6 +9243,14 @@ "parse-json": "^4.0.0", "pify": "^3.0.0", "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "loader-runner": { @@ -9650,9 +9667,9 @@ } }, "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, "longest": { @@ -9721,12 +9738,13 @@ } }, "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" } }, "make-error": { @@ -9802,6 +9820,29 @@ "micromatch": "^3.0.4", "resolve": "^1.4.0", "stack-trace": "0.0.10" + }, + "dependencies": { + "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" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } } }, "math-random": { @@ -10386,9 +10427,9 @@ "dev": true }, "nan": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", - "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", "dev": true, "optional": true }, @@ -10480,13 +10521,20 @@ }, "dependencies": { "@sinonjs/formatio": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.1.0.tgz", - "integrity": "sha512-ZAR2bPHOl4Xg6eklUGpsdiIJ4+J1SNag1DHHrG/73Uz/nVwXqjgUtRPLoS+aVyieN9cSbc0E4LsU984tWcDyNg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", "dev": true, "requires": { - "@sinonjs/samsam": "^2 || ^3" + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" } + }, + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true } } }, @@ -10530,9 +10578,9 @@ } }, "node-releases": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.8.tgz", - "integrity": "sha512-gQm+K9mGCiT/NXHy+V/ZZS1N/LOaGGqRAAJJs3X9Ah1g+CIbRcBgNyoNYQ+SEtcyAtB9KqDruu+fF7nWjsqRaA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.11.tgz", + "integrity": "sha512-8v1j5KfP+s5WOTa1spNUAOfreajQPN12JXbRR0oDE+YrJBQCXBnNqUDj27EKpPLOoSiU3tKi3xGPB+JaOdUEQQ==", "dev": true, "requires": { "semver": "^5.3.0" @@ -10783,9 +10831,9 @@ } }, "opn": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -11048,9 +11096,9 @@ "dev": true }, "p-limit": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", - "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -11075,9 +11123,9 @@ } }, "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", "dev": true }, "pac-proxy-agent": { @@ -11148,9 +11196,9 @@ } }, "pako": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", - "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, "parents": { @@ -11412,6 +11460,14 @@ "dev": true, "requires": { "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "pathval": { @@ -11455,9 +11511,9 @@ "dev": true }, "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, "pinkie": { @@ -11569,9 +11625,9 @@ "dev": true }, "proxy-agent": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", - "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.0.tgz", + "integrity": "sha512-IkbZL4ClW3wwBL/ABFD2zJ8iP84CY0uKMvBPk/OceQe/cEjrxzN1pMHsLwhbzUoRhG9QbSxYC+Z7LBkTiBNvrA==", "dev": true, "requires": { "agent-base": "^4.2.0", @@ -11607,6 +11663,15 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, + "ps-tree": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.1.tgz", + "integrity": "sha512-kef7fYYSKVqQffmzTMsVcUD1ObNJMp8sNSmHGlGKsZQyL/ht9MZKk86u0Rd1NhpTOAuhqwKCLLpktwkqz+MF8A==", + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -11886,9 +11951,9 @@ "dev": true }, "regenerate-unicode-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", - "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", + "integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", "dev": true, "requires": { "regenerate": "^1.4.0" @@ -11940,17 +12005,17 @@ "dev": true }, "regexpu-core": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", - "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", "dev": true, "requires": { "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", + "regenerate-unicode-properties": "^8.0.2", "regjsgen": "^0.5.0", "regjsparser": "^0.6.0", "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" + "unicode-match-property-value-ecmascript": "^1.1.0" } }, "regjsgen": { @@ -12363,9 +12428,9 @@ "dev": true }, "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", "dev": true }, "schema-utils": { @@ -12589,6 +12654,12 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true + }, + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true } } }, @@ -12854,9 +12925,9 @@ } }, "socks": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.3.tgz", - "integrity": "sha512-+2r83WaRT3PXYoO/1z+RDEBE7Z2f9YcdQnJ0K/ncXXbV5gJ6wYfNAebYFYiiUjM6E4JyXnPY8cimwyvFYHVUUA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz", + "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==", "dev": true, "requires": { "ip": "^1.1.5", @@ -12864,13 +12935,13 @@ } }, "socks-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", - "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", "dev": true, "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" + "agent-base": "~4.2.1", + "socks": "~2.3.2" } }, "sort-keys": { @@ -13331,6 +13402,26 @@ "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", "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=", + "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" + } + } + } + }, "ternary-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", @@ -13549,12 +13640,6 @@ } } }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -13644,19 +13729,19 @@ "dev": true }, "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.2.tgz", + "integrity": "sha512-imog1WIsi9Yb56yRt5TfYVxGmnWs3WSGU73ieSOlMVFwhJCA9W8fqFFMMj4kgDqiS/80LGdsYnWL7O9UcjEBlg==", "dev": true, "requires": { - "commander": "~2.17.1", + "commander": "~2.19.0", "source-map": "~0.6.1" }, "dependencies": { "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", "dev": true }, "source-map": { @@ -13800,15 +13885,15 @@ } }, "unicode-match-property-value-ecmascript": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", - "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", "dev": true }, "unicode-property-aliases-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", - "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", "dev": true }, "unified": { @@ -13976,35 +14061,10 @@ } } }, - "unzipper": { - "version": "0.9.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.11.tgz", - "integrity": "sha512-G0z5zv8LYv4/XwpOiXgTGTcN4jyxgyg3P1DfdIeCN2QGOd6ZBl49BSbOe9JsIEvKh3tG7/b0bdJvz+UmwA+BRg==", - "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.10", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - }, - "dependencies": { - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - } - } - }, "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", "dev": true }, "uri-js": { @@ -14057,9 +14117,9 @@ }, "dependencies": { "querystringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", - "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "dev": true } } @@ -14391,9 +14451,9 @@ }, "dependencies": { "ajv": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz", - "integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", diff --git a/package.json b/package.json index d73d9014d99..5ec2245de88 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.8.0-pre", + "version": "2.8.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 68a342cd0fc999098e38c021881dabba18a2b860 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 26 Mar 2019 16:10:19 -0400 Subject: [PATCH 1116/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ec2245de88..a1e2dc2a94b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.8.0", + "version": "2.9.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b06919c8a6a051def784be2d14d9a31f5417c8b2 Mon Sep 17 00:00:00 2001 From: naoto yamaguchi Date: Wed, 27 Mar 2019 11:02:23 +0900 Subject: [PATCH 1117/1594] add privacyLink for native (#3680) --- modules/ajaBidAdapter.js | 1 + modules/ajaBidAdapter.md | 6 +++++- test/spec/modules/ajaBidAdapter_spec.js | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/ajaBidAdapter.js b/modules/ajaBidAdapter.js index 5b826d1e725..58008fe864a 100644 --- a/modules/ajaBidAdapter.js +++ b/modules/ajaBidAdapter.js @@ -103,6 +103,7 @@ export const spec = { sponsoredBy: assets.sponsor, clickUrl: assets.lp_link, impressionTrackers: nativeAd.imps, + privacyLink: assets.adchoice_url, }; if (assets.img_main !== undefined) { diff --git a/modules/ajaBidAdapter.md b/modules/ajaBidAdapter.md index 4f5aa7074cb..66155875f4d 100644 --- a/modules/ajaBidAdapter.md +++ b/modules/ajaBidAdapter.md @@ -74,7 +74,11 @@ var adUnits = [ icon: { required: false, sendId: false - } + }, + privacyLink: { + required: true, + sendId: true + }, } }, bids: [{ diff --git a/test/spec/modules/ajaBidAdapter_spec.js b/test/spec/modules/ajaBidAdapter_spec.js index 7539848d5bd..f2a85ba1ff1 100644 --- a/test/spec/modules/ajaBidAdapter_spec.js +++ b/test/spec/modules/ajaBidAdapter_spec.js @@ -210,7 +210,8 @@ describe('AjaAdapter', function () { 'clickUrl': 'https://example.com/lp?k=v', 'impressionTrackers': [ 'https://example.com/imp' - ] + ], + 'privacyLink': 'https://aja-kk.co.jp/optout', } } ]; From 155b42abdf2ab9be611d111654c79856f1ea9036 Mon Sep 17 00:00:00 2001 From: Finteza Analytics <45741245+finteza@users.noreply.github.com> Date: Fri, 29 Mar 2019 19:28:00 +0200 Subject: [PATCH 1118/1594] Finteza adapter: fix request params (#3690) --- modules/fintezaAnalyticsAdapter.js | 26 +++++---- modules/fintezaAnalyticsAdapter.md | 57 ++++++++++--------- .../modules/fintezaAnalyticsAdapter_spec.js | 35 ++++++++---- 3 files changed, 67 insertions(+), 51 deletions(-) diff --git a/modules/fintezaAnalyticsAdapter.js b/modules/fintezaAnalyticsAdapter.js index 2b5cd0421c2..097d56e05f3 100644 --- a/modules/fintezaAnalyticsAdapter.js +++ b/modules/fintezaAnalyticsAdapter.js @@ -9,7 +9,8 @@ const CONSTANTS = require('../src/constants.json'); const ANALYTICS_TYPE = 'endpoint'; const FINTEZA_HOST = 'https://content.mql5.com/tr'; const BID_REQUEST_TRACK = 'Bid Request %BIDDER%'; -const BID_RESPONSE_TRACK = 'Bid Response %BIDDER%'; +const BID_RESPONSE_PRICE_TRACK = 'Bid Response Price %BIDDER%'; +const BID_RESPONSE_TIME_TRACK = 'Bid Response Time %BIDDER%'; const BID_TIMEOUT_TRACK = 'Bid Timeout %BIDDER%'; const BID_WON_TRACK = 'Bid Won %BIDDER%'; @@ -265,19 +266,21 @@ function prepareBidRequestedParams(args) { function prepareBidResponseParams(args) { return [{ - event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidResponseTrack, args.bidderCode)), - c1_value: args.timeToRespond, - c1_unit: 'ms', - c2_value: args.cpm, - c2_unit: 'usd', + event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidResponsePriceTrack, args.bidderCode)), + value: args.cpm, + unit: 'usd' + }, { + event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidResponseTimeTrack, args.bidderCode)), + value: args.timeToRespond, + unit: 'ms' }]; } function prepareBidWonParams(args) { return [{ event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidWonTrack, args.bidderCode)), - c1_value: args.cpm, - c1_unit: 'usd', + value: args.cpm, + unit: 'usd' }]; } @@ -285,8 +288,8 @@ function prepareBidTimeoutParams(args) { return args.map(function(bid) { return { event: encodeURIComponent(replaceBidder(fntzAnalyticsAdapter.context.bidTimeoutTrack, bid.bidder)), - c1_value: bid.timeout, - c1_unit: 'ms', + value: bid.timeout, + unit: 'ms' }; }) } @@ -387,7 +390,8 @@ fntzAnalyticsAdapter.enableAnalytics = function (config) { host: config.options.host || FINTEZA_HOST, id: config.options.id, bidRequestTrack: config.options.bidRequestTrack || BID_REQUEST_TRACK, - bidResponseTrack: config.options.bidResponseTrack || BID_RESPONSE_TRACK, + bidResponsePriceTrack: config.options.bidResponsePriceTrack || BID_RESPONSE_PRICE_TRACK, + bidResponseTimeTrack: config.options.bidResponseTimeTrack || BID_RESPONSE_TIME_TRACK, bidTimeoutTrack: config.options.bidTimeoutTrack || BID_TIMEOUT_TRACK, bidWonTrack: config.options.bidWonTrack || BID_WON_TRACK, firstVisit: initFirstVisit(), diff --git a/modules/fintezaAnalyticsAdapter.md b/modules/fintezaAnalyticsAdapter.md index 22525f55366..7c07861d89f 100644 --- a/modules/fintezaAnalyticsAdapter.md +++ b/modules/fintezaAnalyticsAdapter.md @@ -1,28 +1,29 @@ -# Overview - -``` -Module Name: Finteza Analytics Adapter -Module Type: Analytics Adapter -Maintainer: renat@finteza.com -``` - -# Description - -The Finteza adapter for integration with Prebid is an analytics tool for publishers who use the Header Bidding technology. The adapter tracks auction opening, offer sending to advertisers, receipt of bids by the publisher and auction winner selection. All tracks are sent to Finteza and enable visual advertiser quality evaluation: how many offers partners accept, what prices they provide, how fast they respond and how often their bids win. - -For more information, visit the [official Finteza website](https://www.finteza.com/). - -# Test Parameters - -``` -{ - provider: 'finteza', - options: { - id: 'xxxxx', // Website ID (required) - bidRequestTrack: 'Bid Request %BIDDER%', - bidResponseTrack: 'Bid Response %BIDDER%', - bidTimeoutTrack: 'Bid Timeout %BIDDER%', - bidWonTrack: 'Bid Won %BIDDER%' - } -} -``` +# Overview + +``` +Module Name: Finteza Analytics Adapter +Module Type: Analytics Adapter +Maintainer: renat@finteza.com +``` + +# Description + +The Finteza adapter for integration with Prebid is an analytics tool for publishers who use the Header Bidding technology. The adapter tracks auction opening, offer sending to advertisers, receipt of bids by the publisher and auction winner selection. All tracks are sent to Finteza and enable visual advertiser quality evaluation: how many offers partners accept, what prices they provide, how fast they respond and how often their bids win. + +For more information, visit the [official Finteza website](https://www.finteza.com/). + +# Test Parameters + +``` +{ + provider: 'finteza', + options: { + id: 'xxxxx', // Website ID (required) + bidRequestTrack: 'Bid Request %BIDDER%', + bidResponsePriceTrack: 'Bid Response Price %BIDDER%', + bidResponseTimeTrack: 'Bid Response Time %BIDDER%', + bidTimeoutTrack: 'Bid Timeout %BIDDER%', + bidWonTrack: 'Bid Won %BIDDER%' + } +} +``` diff --git a/test/spec/modules/fintezaAnalyticsAdapter_spec.js b/test/spec/modules/fintezaAnalyticsAdapter_spec.js index 95600e84a9f..33b24f5f50f 100644 --- a/test/spec/modules/fintezaAnalyticsAdapter_spec.js +++ b/test/spec/modules/fintezaAnalyticsAdapter_spec.js @@ -29,7 +29,8 @@ describe('finteza analytics adapter', function () { options: { id: clientId, // Client ID (required) bidRequestTrack: 'Bid Request %BIDDER%', - bidResponseTrack: 'Bid Response %bidder%', + bidResponseTimeTrack: 'Bid Response Time %bidder%', + bidResponsePriceTrack: 'Bid Response Price %bidder%', bidTimeoutTrack: 'Bid Timeout %Bidder%', bidWonTrack: 'Bid Won %BIDDER%', } @@ -111,21 +112,31 @@ describe('finteza analytics adapter', function () { // Emit the events with the "real" arguments events.emit(constants.EVENTS.BID_RESPONSE, bidResponse); - expect(requests.length).to.equal(1); + expect(requests.length).to.equal(2); expect(requests[0].method).to.equal('GET'); - const url = parseURL(requests[0].url); + let url = parseURL(requests[0].url); + + expect(url.protocol).to.equal('https'); + expect(url.hostname).to.equal('content.mql5.com'); + expect(url.pathname).to.equal('/tr'); + expect(url.search.id).to.equal(clientId); + expect(decodeURIComponent(url.search.event)).to.equal(`Bid Response Price ${bidderCode.toLowerCase()}`); + expect(url.search.value).to.equal(String(cpm)); + expect(url.search.unit).to.equal('usd'); + + expect(requests[1].method).to.equal('GET'); + + url = parseURL(requests[1].url); expect(url.protocol).to.equal('https'); expect(url.hostname).to.equal('content.mql5.com'); expect(url.pathname).to.equal('/tr'); expect(url.search.id).to.equal(clientId); - expect(decodeURIComponent(url.search.event)).to.equal(`Bid Response ${bidderCode.toLowerCase()}`); - expect(url.search.c1_value).to.equal(String(timeToRespond)); - expect(url.search.c1_unit).to.equal('ms'); - expect(url.search.c2_value).to.equal(String(cpm)); - expect(url.search.c2_unit).to.equal('usd'); + expect(decodeURIComponent(url.search.event)).to.equal(`Bid Response Time ${bidderCode.toLowerCase()}`); + expect(url.search.value).to.equal(String(timeToRespond)); + expect(url.search.unit).to.equal('ms'); sinon.assert.callCount(fntzAnalyticsAdapter.track, 1); }); @@ -162,8 +173,8 @@ describe('finteza analytics adapter', function () { expect(url.pathname).to.equal('/tr'); expect(url.search.id).to.equal(clientId); expect(decodeURIComponent(url.search.event)).to.equal(`Bid Won ${bidderCode.toUpperCase()}`); - expect(url.search.c1_value).to.equal(String(cpm)); - expect(url.search.c1_unit).to.equal('usd'); + expect(url.search.value).to.equal(String(cpm)); + expect(url.search.unit).to.equal('usd'); sinon.assert.callCount(fntzAnalyticsAdapter.track, 1); }); @@ -199,8 +210,8 @@ describe('finteza analytics adapter', function () { expect(url.pathname).to.equal('/tr'); expect(url.search.id).to.equal(clientId); expect(decodeURIComponent(url.search.event)).to.equal(`Bid Timeout Bidder789`); - expect(url.search.c1_value).to.equal(String(timeout)); - expect(url.search.c1_unit).to.equal('ms'); + expect(url.search.value).to.equal(String(timeout)); + expect(url.search.unit).to.equal('ms'); sinon.assert.callCount(fntzAnalyticsAdapter.track, 1); }); From 9b0fd37bac1b13f125fbdd8a7892d6929887dc32 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 1 Apr 2019 11:10:01 -0400 Subject: [PATCH 1119/1594] update stalebot labels (#3697) --- .github/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/stale.yml b/.github/stale.yml index 0925c69c703..2afa7ecf0ec 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -8,6 +8,7 @@ exemptLabels: - security - bug - feature + - on hold # Label to use when marking an issue as stale staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable From d3f4d28aed6ca78da829cd20592e3eca92fe28a2 Mon Sep 17 00:00:00 2001 From: AlessandroDG Date: Mon, 1 Apr 2019 17:51:38 +0200 Subject: [PATCH 1120/1594] Rvr 2369 Refactor events handling (#3683) * Rvr 2369 Refactor events handling (#9) * RVR-2177 - Refactor events handling * RVR-2087 - Inject pbjsGlobalVariable into rivraddon * RVR-2087 - update adapterManager dependency * RVR-2087 - Add ADD_AD_UNITS to Prebid.JS trackable events * RVR-2369 - Update package-lock.json * Rvr 2369 prevent duplicate events (#10) ## Type of change - [x] Refactoring (no functional changes, no api changes) ## Description of change Refactor rivrAnalyticsAdapter.js events handling. ## History * RVR-2087 - update adapterManager dependency * RVR-2369 - Update package-lock.json * RVR-2369 - Revert changes in main Analytics adapter It will be handled in a separate PR * RVR-2369 - Use relative import paths Needed for https://github.com/prebid/Prebid.js/pull/3435 --- modules/rivrAnalyticsAdapter.js | 26 ++------ .../spec/modules/rivrAnalyticsAdapter_spec.js | 61 +++++-------------- 2 files changed, 19 insertions(+), 68 deletions(-) diff --git a/modules/rivrAnalyticsAdapter.js b/modules/rivrAnalyticsAdapter.js index c5ff7757f82..e1cfa5c70bc 100644 --- a/modules/rivrAnalyticsAdapter.js +++ b/modules/rivrAnalyticsAdapter.js @@ -1,6 +1,5 @@ import {ajax} from '../src/ajax'; import adapter from '../src/AnalyticsAdapter'; -import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager'; import * as utils from '../src/utils'; @@ -8,24 +7,9 @@ const analyticsType = 'endpoint'; let rivrAnalytics = Object.assign(adapter({analyticsType}), { track({ eventType, args }) { - if (!window.rivraddon || !window.rivraddon.analytics || !window.rivraddon.analytics.getContext()) { - return; - } - utils.logInfo(`ARGUMENTS FOR TYPE: ============= ${eventType}`, args); - let handler = null; - switch (eventType) { - case CONSTANTS.EVENTS.AUCTION_INIT: - handler = window.rivraddon.analytics.trackAuctionInit; - break; - case CONSTANTS.EVENTS.AUCTION_END: - handler = window.rivraddon.analytics.trackAuctionEnd; - break; - case CONSTANTS.EVENTS.BID_WON: - handler = window.rivraddon.analytics.trackBidWon; - break; - } - if (handler) { - handler(args) + if (window.rivraddon && window.rivraddon.analytics && window.rivraddon.analytics.getContext() && window.rivraddon.analytics.trackPbjsEvent) { + utils.logInfo(`ARGUMENTS FOR TYPE: ============= ${eventType}`, args); + window.rivraddon.analytics.trackPbjsEvent({ eventType, args }); } } }); @@ -36,7 +20,7 @@ rivrAnalytics.originEnableAnalytics = rivrAnalytics.enableAnalytics; // override enableAnalytics so we can get access to the config passed in from the page rivrAnalytics.enableAnalytics = (config) => { if (window.rivraddon && window.rivraddon.analytics) { - window.rivraddon.analytics.enableAnalytics(config, {utils, ajax}); + window.rivraddon.analytics.enableAnalytics(config, {utils, ajax, pbjsGlobalVariable: $$PREBID_GLOBAL$$}); rivrAnalytics.originEnableAnalytics(config); } }; @@ -46,4 +30,4 @@ adapterManager.registerAnalyticsAdapter({ code: 'rivr' }); -export default rivrAnalytics +export default rivrAnalytics; diff --git a/test/spec/modules/rivrAnalyticsAdapter_spec.js b/test/spec/modules/rivrAnalyticsAdapter_spec.js index c2c9d0ae9e8..2676c3a59b6 100644 --- a/test/spec/modules/rivrAnalyticsAdapter_spec.js +++ b/test/spec/modules/rivrAnalyticsAdapter_spec.js @@ -35,9 +35,7 @@ describe('RIVR Analytics adapter', () => { let sandbox; let ajaxStub; let rivraddonsEnableAnalyticsStub; - let rivraddonsTrackAuctionInitStub; - let rivraddonsTrackAuctionEndStub; - let rivraddonsTrackBidWonStub; + let rivraddonsTrackPbjsEventStub; let timer; before(() => { @@ -46,9 +44,7 @@ describe('RIVR Analytics adapter', () => { analytics: { enableAnalytics: () => {}, getContext: () => { return MOCK_RIVRADDON_CONTEXT; }, - trackAuctionInit: () => {}, - trackAuctionEnd: () => {}, - trackBidWon: () => {}, + trackPbjsEvent: () => {}, } }; rivraddonsEnableAnalyticsStub = sandbox.stub(window.rivraddon.analytics, 'enableAnalytics'); @@ -98,61 +94,32 @@ describe('RIVR Analytics adapter', () => { it('Firing an event when rivraddon context is not defined it should do nothing', () => { let rivraddonsGetContextStub = sandbox.stub(window.rivraddon.analytics, 'getContext'); - rivraddonsTrackAuctionInitStub = sandbox.stub(window.rivraddon.analytics, 'trackAuctionInit'); + rivraddonsTrackPbjsEventStub = sandbox.stub(window.rivraddon.analytics, 'trackPbjsEvent'); - expect(rivraddonsTrackAuctionInitStub.callCount).to.be.equal(0); + expect(rivraddonsTrackPbjsEventStub.callCount).to.be.equal(0); events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: EMITTED_AUCTION_ID, config: {}, timeout: 3000}); - expect(rivraddonsTrackAuctionInitStub.callCount).to.be.equal(0); + expect(rivraddonsTrackPbjsEventStub.callCount).to.be.equal(0); window.rivraddon.analytics.getContext.restore(); - window.rivraddon.analytics.trackAuctionInit.restore(); + window.rivraddon.analytics.trackPbjsEvent.restore(); }); - it('Firing AUCTION_INIT should call rivraddon trackAuctionInit passing the parameters', () => { - rivraddonsTrackAuctionInitStub = sandbox.stub(window.rivraddon.analytics, 'trackAuctionInit'); + it('Firing AUCTION_INIT should call rivraddon trackPbjsEvent passing the parameters', () => { + rivraddonsTrackPbjsEventStub = sandbox.stub(window.rivraddon.analytics, 'trackPbjsEvent'); - expect(rivraddonsTrackAuctionInitStub.callCount).to.be.equal(0); + expect(rivraddonsTrackPbjsEventStub.callCount).to.be.equal(0); events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: EMITTED_AUCTION_ID, config: {}, timeout: 3000}); - expect(rivraddonsTrackAuctionInitStub.callCount).to.be.equal(1); + expect(rivraddonsTrackPbjsEventStub.callCount).to.be.equal(1); - const firstArgument = rivraddonsTrackAuctionInitStub.getCall(0).args[0]; - expect(firstArgument.auctionId).to.be.equal(EMITTED_AUCTION_ID); + const firstArgument = rivraddonsTrackPbjsEventStub.getCall(0).args[0]; + expect(firstArgument.eventType).to.be.equal(CONSTANTS.EVENTS.AUCTION_INIT); + expect(firstArgument.args.auctionId).to.be.equal(EMITTED_AUCTION_ID); - window.rivraddon.analytics.trackAuctionInit.restore(); - }); - - it('Firing AUCTION_END should call rivraddon trackAuctionEnd passing the parameters', () => { - rivraddonsTrackAuctionEndStub = sandbox.stub(window.rivraddon.analytics, 'trackAuctionEnd'); - - expect(rivraddonsTrackAuctionEndStub.callCount).to.be.equal(0); - - events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: EMITTED_AUCTION_ID}); - - expect(rivraddonsTrackAuctionEndStub.callCount).to.be.equal(1); - - const firstArgument = rivraddonsTrackAuctionEndStub.getCall(0).args[0]; - expect(firstArgument.auctionId).to.be.equal(EMITTED_AUCTION_ID); - - window.rivraddon.analytics.trackAuctionEnd.restore(); - }); - - it('Firing BID_WON should call rivraddon trackBidWon passing the parameters', () => { - rivraddonsTrackBidWonStub = sandbox.stub(window.rivraddon.analytics, 'trackBidWon'); - - expect(rivraddonsTrackBidWonStub.callCount).to.be.equal(0); - - events.emit(CONSTANTS.EVENTS.BID_WON, {auctionId: EMITTED_AUCTION_ID}); - - expect(rivraddonsTrackBidWonStub.callCount).to.be.equal(1); - - const firstArgument = rivraddonsTrackBidWonStub.getCall(0).args[0]; - expect(firstArgument.auctionId).to.be.equal(EMITTED_AUCTION_ID); - - window.rivraddon.analytics.trackBidWon.restore(); + window.rivraddon.analytics.trackPbjsEvent.restore(); }); const BANNER_AD_UNITS_MOCK = [ From 3b43f25e817174ffcd812967423b7d478c26816b Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 1 Apr 2019 09:55:46 -0700 Subject: [PATCH 1121/1594] Native related code refactor (#3637) * changes for multiformat support * added new constant NATIVE_ASSETS in PubMatic adapter * removed NATIVE_ASSET_KEY reference in PubMatic adapter * removed reference of const NATIVE_ASSET_ID from PubMatic adapter * removed reference of const NATIVE_ASSET_DATA_TYPE in PubMatic adapter * using _commonNativeRequestObject in PubMatic adapter to avoid repeating code block * removed new-lines in const declaration * generating NATIVE_ASSET_REVERSE_ID from NATIVE_ASSETS * renamed NATIVE_ASSET_REVERSE_ID to NATIVE_ASSET_ID_TO_KEY_MAP * little modification in _checkParamDataType in PubMatic adapter * a minor improvement * using let instead of var * added NATIVE_ASSET_KEY_TO_ASSET_MAP and combining switch cases * lint update * removed some stale comments * using LOG_WARN_PREFIX * using const UNDEFINED * added a logWarn in catch * using arrow functions * code review changes * changes to checkMediaType function * suppress warning of missing mediaTypes.banner for native and video impression * ignore fluid size, if present, in banner impression * fix for ignoring fluid size in banner impression * added relevant comments and test cases for fluid case in banner request * added sample config for multiformat adunit --- modules/pubmaticBidAdapter.js | 622 +++++++++---------- modules/pubmaticBidAdapter.md | 67 ++ test/spec/modules/pubmaticBidAdapter_spec.js | 522 +++++++++++++++- 3 files changed, 869 insertions(+), 342 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index d80d6c5c810..737ab1dadae 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -48,75 +48,30 @@ const VIDEO_CUSTOM_PARAMS = { 'maxbitrate': DATA_TYPES.NUMBER } -const NATIVE_ASSET_ID = { - 'TITLE': 1, - 'IMAGE': 2, - 'ICON': 3, - 'SPONSOREDBY': 4, - 'BODY': 5, - 'CLICKURL': 6, - 'VIDEO': 7, - 'EXT': 8, - 'DATA': 9, - 'LOGO': 10, - 'SPONSORED': 11, - 'DESC': 12, - 'RATING': 13, - 'LIKES': 14, - 'DOWNLOADS': 15, - 'PRICE': 16, - 'SALEPRICE': 17, - 'PHONE': 18, - 'ADDRESS': 19, - 'DESC2': 20, - 'DISPLAYURL': 21, - 'CTA': 22 -} - -const NATIVE_ASSET_REVERSE_ID = { - 4: 'sponsoredBy', - 5: 'body', - 6: 'clickUrl', - 7: 'video', - 8: 'ext', - 9: 'data', - 10: 'logo', - 11: 'sponsored', - 12: 'desc', - 13: 'rating', - 14: 'likes', - 15: 'downloads', - 16: 'price', - 17: 'saleprice', - 18: 'phone', - 19: 'address', - 20: 'desc2', - 21: 'displayurl', - 22: 'cta' -} - -const NATIVE_ASSET_KEY = { - 'TITLE': 'title', - 'IMAGE': 'image', - 'ICON': 'icon', - 'SPONSOREDBY': 'sponsoredBy', - 'BODY': 'body', - 'VIDEO': 'video', - 'EXT': 'ext', - 'DATA': 'data', - 'LOGO': 'logo', - 'DESC': 'desc', - 'RATING': 'rating', - 'LIKES': 'likes', - 'DOWNLOADS': 'downloads', - 'PRICE': 'price', - 'SALEPRICE': 'saleprice', - 'PHONE': 'phone', - 'ADDRESS': 'address', - 'DESC2': 'desc2', - 'DISPLAYURL': 'displayurl', - 'CTA': 'cta' -} +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 + 'BODY': { ID: 5, KEY: 'body', TYPE: 2 }, // please note that type of DESC is also set to 2 + 'CLICKURL': { ID: 6, KEY: 'clickUrl', TYPE: 0 }, + 'VIDEO': { ID: 7, KEY: 'video', TYPE: 0 }, + 'EXT': { ID: 8, KEY: 'ext', TYPE: 0 }, + 'DATA': { ID: 9, KEY: 'data', TYPE: 0 }, + 'LOGO': { ID: 10, KEY: 'logo', TYPE: 0 }, + 'SPONSORED': { ID: 11, KEY: 'sponsored', TYPE: 1 }, // please note that type of SPONSOREDBY is also set to 1 + 'DESC': { ID: 12, KEY: 'data', TYPE: 2 }, // please note that type of BODY is also set to 2 + 'RATING': { ID: 13, KEY: 'rating', TYPE: 3 }, + 'LIKES': { ID: 14, KEY: 'likes', TYPE: 4 }, + 'DOWNLOADS': { ID: 15, KEY: 'downloads', TYPE: 5 }, + 'PRICE': { ID: 16, KEY: 'price', TYPE: 6 }, + 'SALEPRICE': { ID: 17, KEY: 'saleprice', TYPE: 7 }, + 'PHONE': { ID: 18, KEY: 'phone', TYPE: 8 }, + 'ADDRESS': { ID: 19, KEY: 'address', TYPE: 9 }, + 'DESC2': { ID: 20, KEY: 'desc2', TYPE: 10 }, + 'DISPLAYURL': { ID: 21, KEY: 'displayurl', TYPE: 11 }, + 'CTA': { ID: 22, KEY: 'cta', TYPE: 12 } +}; const NATIVE_ASSET_IMAGE_TYPE = { 'ICON': 1, @@ -124,36 +79,21 @@ const NATIVE_ASSET_IMAGE_TYPE = { 'IMAGE': 3 } -const NATIVE_ASSET_DATA_TYPE = { - 'SPONSORED': 1, - 'DESC': 2, - 'RATING': 3, - 'LIKES': 4, - 'DOWNLOADS': 5, - 'PRICE': 6, - 'SALEPRICE': 7, - 'PHONE': 8, - 'ADDRESS': 9, - 'DESC2': 10, - 'DISPLAYURL': 11, - 'CTA': 12 -} - // check if title, image can be added with mandatory field default values const NATIVE_MINIMUM_REQUIRED_IMAGE_ASSETS = [ { - id: NATIVE_ASSET_ID.SPONSOREDBY, + id: NATIVE_ASSETS.SPONSOREDBY.ID, required: true, data: { type: 1 } }, { - id: NATIVE_ASSET_ID.TITLE, + id: NATIVE_ASSETS.TITLE.ID, required: true, }, { - id: NATIVE_ASSET_ID.IMAGE, + id: NATIVE_ASSETS.IMAGE.ID, required: true, } ] @@ -167,6 +107,13 @@ const dealChannelValues = { let publisherId = 0; let isInvalidNativeRequest = false; +let NATIVE_ASSET_ID_TO_KEY_MAP = {}; +let NATIVE_ASSET_KEY_TO_ASSET_MAP = {}; + +// loading NATIVE_ASSET_ID_TO_KEY_MAP +utils._each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] = anAsset.KEY }); +// loading NATIVE_ASSET_KEY_TO_ASSET_MAP +utils._each(NATIVE_ASSETS, anAsset => { NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); function _getDomainFromURL(url) { let anchor = document.createElement('a'); @@ -208,7 +155,6 @@ function _parseAdSlot(bid) { bid.params.adUnitIndex = '0'; bid.params.width = 0; bid.params.height = 0; - var sizesArrayExists = (bid.hasOwnProperty('sizes') && utils.isArray(bid.sizes) && bid.sizes.length >= 1); bid.params.adSlot = _cleanSlot(bid.params.adSlot); var slot = bid.params.adSlot; @@ -220,14 +166,9 @@ function _parseAdSlot(bid) { } // check if size is mentioned in sizes array. in that case do not check for @ in adslot splits = slot.split('@'); - if (splits.length != 2) { - if (!(sizesArrayExists)) { - utils.logWarn(LOG_WARN_PREFIX + 'AdSlot Error: adSlot not in required format'); - return; - } - } bid.params.adUnit = splits[0]; - if (splits.length > 1) { // i.e size is specified in adslot, so consider that and ignore sizes array + if (splits.length > 1) { + // i.e size is specified in adslot, so consider that and ignore sizes array splits = splits[1].split('x'); if (splits.length != 2) { utils.logWarn(LOG_WARN_PREFIX + 'AdSlot Error: adSlot not in required format'); @@ -235,10 +176,24 @@ function _parseAdSlot(bid) { } bid.params.width = parseInt(splits[0]); bid.params.height = parseInt(splits[1]); - delete bid.sizes; - } else if (sizesArrayExists) { - bid.params.width = parseInt(bid.sizes[0][0]); - bid.params.height = parseInt(bid.sizes[0][1]); + } else if (bid.hasOwnProperty('mediaTypes') && + bid.mediaTypes.hasOwnProperty(BANNER) && + bid.mediaTypes.banner.hasOwnProperty('sizes')) { + var i = 0; + var sizeArray = []; + for (;i < bid.mediaTypes.banner.sizes.length; i++) { + if (bid.mediaTypes.banner.sizes[i].length === 2) { // sizes[i].length will not be 2 in case where size is set as fluid, we want to skip that entry + sizeArray.push(bid.mediaTypes.banner.sizes[i]); + } + } + bid.mediaTypes.banner.sizes = sizeArray; + if (bid.mediaTypes.banner.sizes.length >= 1) { + // set the first size in sizes array in bid.params.width and bid.params.height. These will be sent as primary size. + // The rest of the sizes will be sent in format array. + bid.params.width = bid.mediaTypes.banner.sizes[0][0]; + bid.params.height = bid.mediaTypes.banner.sizes[0][1]; + bid.mediaTypes.banner.sizes = bid.mediaTypes.banner.sizes.splice(1, bid.mediaTypes.banner.sizes.length - 1); + } } } @@ -306,35 +261,41 @@ function _createOrtbTemplate(conf) { }; } -// similar functionality as parseSlotParam. Check if the 2 functions can be clubbed. function _checkParamDataType(key, value, datatype) { - var errMsg = 'PubMatic: Ignoring param key: ' + key + ', expects ' + datatype + ', found ' + typeof value; + var errMsg = 'Ignoring param key: ' + key + ', expects ' + datatype + ', found ' + typeof value; + var functionToExecute; switch (datatype) { case DATA_TYPES.BOOLEAN: - if (!utils.isBoolean(value)) { - utils.logWarn(LOG_WARN_PREFIX + errMsg); - return UNDEFINED; - } - return value; + functionToExecute = utils.isBoolean; + break; case DATA_TYPES.NUMBER: - if (!utils.isNumber(value)) { - utils.logWarn(LOG_WARN_PREFIX + errMsg); - return UNDEFINED; - } - return value; + functionToExecute = utils.isNumber; + break; case DATA_TYPES.STRING: - if (!utils.isStr(value)) { - utils.logWarn(LOG_WARN_PREFIX + errMsg); - return UNDEFINED; - } - return value; + functionToExecute = utils.isStr; + break; case DATA_TYPES.ARRAY: - if (!utils.isArray(value)) { - utils.logWarn(LOG_WARN_PREFIX + errMsg); - return UNDEFINED; - } - return value; + functionToExecute = utils.isArray; + break; } + if (functionToExecute(value)) { + return value; + } + utils.logWarn(LOG_WARN_PREFIX + errMsg); + return UNDEFINED; +} + +function _commonNativeRequestObject(nativeAsset, params) { + var 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 _createNativeRequest(params) { @@ -346,10 +307,10 @@ function _createNativeRequest(params) { var assetObj = {}; if (!(nativeRequestObject.assets && nativeRequestObject.assets.length > 0 && nativeRequestObject.assets.hasOwnProperty(key))) { switch (key) { - case NATIVE_ASSET_KEY.TITLE: + case NATIVE_ASSETS.TITLE.KEY: if (params[key].len || params[key].length) { assetObj = { - id: NATIVE_ASSET_ID.TITLE, + id: NATIVE_ASSETS.TITLE.ID, required: params[key].required ? 1 : 0, title: { len: params[key].len || params[key].length, @@ -360,67 +321,43 @@ function _createNativeRequest(params) { utils.logWarn(LOG_WARN_PREFIX + 'Error: Title Length is required for native ad: ' + JSON.stringify(params)); } break; - case NATIVE_ASSET_KEY.IMAGE: + case NATIVE_ASSETS.IMAGE.KEY: if (params[key].sizes && params[key].sizes.length > 0) { assetObj = { - id: NATIVE_ASSET_ID.IMAGE, + 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 || (params[key].sizes ? params[key].sizes[0] : undefined), - h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : undefined), - wmin: params[key].wmin || params[key].minimumWidth || (params[key].minsizes ? params[key].minsizes[0] : undefined), - hmin: params[key].hmin || params[key].minimumHeight || (params[key].minsizes ? params[key].minsizes[1] : undefined), + w: params[key].w || params[key].width || (params[key].sizes ? params[key].sizes[0] : UNDEFINED), + h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : UNDEFINED), + wmin: params[key].wmin || params[key].minimumWidth || (params[key].minsizes ? params[key].minsizes[0] : UNDEFINED), + hmin: params[key].hmin || params[key].minimumHeight || (params[key].minsizes ? params[key].minsizes[1] : UNDEFINED), mimes: params[key].mimes, ext: params[key].ext, } }; } else { - // Log Warn utils.logWarn(LOG_WARN_PREFIX + 'Error: Image sizes is required for native ad: ' + JSON.stringify(params)); } break; - case NATIVE_ASSET_KEY.ICON: + case NATIVE_ASSETS.ICON.KEY: if (params[key].sizes && params[key].sizes.length > 0) { assetObj = { - id: NATIVE_ASSET_ID.ICON, + 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 || (params[key].sizes ? params[key].sizes[0] : undefined), - h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : undefined), + w: params[key].w || params[key].width || (params[key].sizes ? params[key].sizes[0] : UNDEFINED), + h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : UNDEFINED), } }; } else { - // Log Warn utils.logWarn(LOG_WARN_PREFIX + 'Error: Icon sizes is required for native ad: ' + JSON.stringify(params)); }; break; - case NATIVE_ASSET_KEY.SPONSOREDBY: - assetObj = { - id: NATIVE_ASSET_ID.SPONSOREDBY, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.SPONSORED, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.BODY: - assetObj = { - id: NATIVE_ASSET_ID.BODY, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.DESC, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.VIDEO: + case NATIVE_ASSETS.VIDEO.KEY: assetObj = { - id: NATIVE_ASSET_ID.VIDEO, + id: NATIVE_ASSETS.VIDEO.ID, required: params[key].required ? 1 : 0, video: { minduration: params[key].minduration, @@ -431,132 +368,36 @@ function _createNativeRequest(params) { } }; break; - case NATIVE_ASSET_KEY.EXT: + case NATIVE_ASSETS.EXT.KEY: assetObj = { - id: NATIVE_ASSET_ID.EXT, + id: NATIVE_ASSETS.EXT.ID, required: params[key].required ? 1 : 0, }; break; - case NATIVE_ASSET_KEY.LOGO: + case NATIVE_ASSETS.LOGO.KEY: assetObj = { - id: NATIVE_ASSET_ID.LOGO, + id: NATIVE_ASSETS.LOGO.ID, required: params[key].required ? 1 : 0, img: { type: NATIVE_ASSET_IMAGE_TYPE.LOGO, - w: params[key].w || params[key].width || (params[key].sizes ? params[key].sizes[0] : undefined), - h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : undefined) - } - }; - break; - case NATIVE_ASSET_KEY.RATING: - assetObj = { - id: NATIVE_ASSET_ID.RATING, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.RATING, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.LIKES: - assetObj = { - id: NATIVE_ASSET_ID.LIKES, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.LIKES, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.DOWNLOADS: - assetObj = { - id: NATIVE_ASSET_ID.DOWNLOADS, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.DOWNLOADS, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.PRICE: - assetObj = { - id: NATIVE_ASSET_ID.PRICE, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.PRICE, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.SALEPRICE: - assetObj = { - id: NATIVE_ASSET_ID.SALEPRICE, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.SALEPRICE, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.PHONE: - assetObj = { - id: NATIVE_ASSET_ID.PHONE, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.PHONE, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.ADDRESS: - assetObj = { - id: NATIVE_ASSET_ID.ADDRESS, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.ADDRESS, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.DESC2: - assetObj = { - id: NATIVE_ASSET_ID.DESC2, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.DESC2, - len: params[key].len, - ext: params[key].ext - } - }; - break; - case NATIVE_ASSET_KEY.DISPLAYURL: - assetObj = { - id: NATIVE_ASSET_ID.DISPLAYURL, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.DISPLAYURL, - len: params[key].len, - ext: params[key].ext + w: params[key].w || params[key].width || (params[key].sizes ? params[key].sizes[0] : UNDEFINED), + h: params[key].h || params[key].height || (params[key].sizes ? params[key].sizes[1] : UNDEFINED) } }; break; - case NATIVE_ASSET_KEY.CTA: - assetObj = { - id: NATIVE_ASSET_ID.CTA, - required: params[key].required ? 1 : 0, - data: { - type: NATIVE_ASSET_DATA_TYPE.CTA, - len: params[key].len, - ext: params[key].ext - } - }; + case NATIVE_ASSETS.SPONSOREDBY.KEY: + case NATIVE_ASSETS.BODY.KEY: + case NATIVE_ASSETS.RATING.KEY: + case NATIVE_ASSETS.LIKES.KEY: + case NATIVE_ASSETS.DOWNLOADS.KEY: + case NATIVE_ASSETS.PRICE.KEY: + case NATIVE_ASSETS.SALEPRICE.KEY: + case NATIVE_ASSETS.PHONE.KEY: + case NATIVE_ASSETS.ADDRESS.KEY: + case NATIVE_ASSETS.DESC2.KEY: + case NATIVE_ASSETS.DISPLAYURL.KEY: + case NATIVE_ASSETS.CTA.KEY: + assetObj = _commonNativeRequestObject(NATIVE_ASSET_KEY_TO_ASSET_MAP[key], params); break; } } @@ -587,11 +428,86 @@ function _createNativeRequest(params) { return nativeRequestObject; } +function _createBannerRequest(bid) { + var sizes = bid.mediaTypes.banner.sizes; + var format = []; + var bannerObj; + 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; + 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]); + bannerObj.h = parseInt(sizes[0][1]); + sizes = sizes.splice(1, sizes.length - 1); + } + } else { + bannerObj.w = bid.params.width; + bannerObj.h = bid.params.height; + } + if (sizes.length > 0) { + format = []; + sizes.forEach(function (size) { + if (size.length > 1) { + format.push({ w: size[0], h: size[1] }); + } + }); + if (format.length > 0) { + bannerObj.format = format; + } + } + bannerObj.pos = 0; + bannerObj.topframe = utils.inIframe() ? 0 : 1; + } else { + 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; +} + +function _createVideoRequest(bid) { + var videoData = bid.params.video; + var videoObj; + + if (videoData !== UNDEFINED) { + videoObj = {}; + 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 (utils.isArray(bid.mediaTypes.video.playerSize[0])) { + videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0][0]); + videoObj.h = parseInt(bid.mediaTypes.video.playerSize[0][1]); + } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { + videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0]); + videoObj.h = parseInt(bid.mediaTypes.video.playerSize[1]); + } + if (bid.params.video.hasOwnProperty('skippable')) { + videoObj.ext = { + 'video_skippable': bid.params.video.skippable ? 1 : 0 + }; + } + } else { + videoObj = UNDEFINED; + 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; +} + function _createImpressionObject(bid, conf) { var impObj = {}; - var bannerObj = {}; - var videoObj = {}; + var bannerObj; + var videoObj; + var nativeObj = {}; var sizes = bid.hasOwnProperty('sizes') ? bid.sizes : []; + var mediaTypes = ''; + var format = []; impObj = { id: bid.bidId, @@ -604,42 +520,42 @@ function _createImpressionObject(bid, conf) { bidfloorcur: bid.params.currency ? _parseSlotParam('currency', bid.params.currency) : DEFAULT_CURRENCY }; - if (bid.params.hasOwnProperty('video')) { - var videoData = bid.params.video; - - 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 (utils.isArray(bid.mediaTypes.video.playerSize[0])) { - videoObj.w = bid.mediaTypes.video.playerSize[0][0]; - videoObj.h = bid.mediaTypes.video.playerSize[0][1]; - } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { - videoObj.w = bid.mediaTypes.video.playerSize[0]; - videoObj.h = bid.mediaTypes.video.playerSize[1]; - } - if (bid.params.video.hasOwnProperty('skippable')) { - videoObj.ext = { - 'video_skippable': bid.params.video.skippable ? 1 : 0 + if (bid.hasOwnProperty('mediaTypes')) { + for (mediaTypes in bid.mediaTypes) { + switch (mediaTypes) { + case BANNER: + bannerObj = _createBannerRequest(bid); + if (bannerObj !== UNDEFINED) { + impObj.banner = bannerObj; + } + break; + case NATIVE: + nativeObj['request'] = JSON.stringify(_createNativeRequest(bid.nativeParams)); + if (!isInvalidNativeRequest) { + impObj.native = nativeObj; + } else { + 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: + videoObj = _createVideoRequest(bid); + if (videoObj !== UNDEFINED) { + impObj.video = videoObj; + } + break; } } - - impObj.video = videoObj; - } else if (bid.nativeParams) { - impObj.native = {}; - impObj.native['request'] = JSON.stringify(_createNativeRequest(bid.nativeParams)); } else { + // mediaTypes is not present, so this is a banner only impression + // this part of code is required for older testcases with no 'mediaTypes' to run succesfully. bannerObj = { pos: 0, w: bid.params.width, h: bid.params.height, - topframe: utils.inIframe() ? 0 : 1, - } + topframe: utils.inIframe() ? 0 : 1 + }; if (utils.isArray(sizes) && sizes.length > 1) { sizes = sizes.splice(1, sizes.length - 1); - var format = []; sizes.forEach(size => { format.push({ w: size[0], @@ -650,11 +566,10 @@ function _createImpressionObject(bid, conf) { } impObj.banner = bannerObj; } - if (isInvalidNativeRequest && impObj.hasOwnProperty('native')) { - utils.logWarn(LOG_WARN_PREFIX + 'Call to OpenBid will not be sent for native ad unit as it does not contain required valid native params.' + JSON.stringify(bid) + ' Refer:' + PREBID_NATIVE_HELP_LINK); - return; - } - return impObj; + + return impObj.hasOwnProperty(BANNER) || + impObj.hasOwnProperty(NATIVE) || + impObj.hasOwnProperty(VIDEO) ? impObj : UNDEFINED; } function _getDigiTrustObject(key) { @@ -711,6 +626,26 @@ function _handleEids(payload) { } } +function _checkMediaType(adm, newBid) { + // Create a regex here to check the strings + var admStr = ''; + var videoRegex = new RegExp(/VAST\s+version/); + if (adm.indexOf('span class="PubAPIAd"') >= 0) { + newBid.mediaType = BANNER; + } else if (videoRegex.test(adm)) { + newBid.mediaType = VIDEO; + } else { + try { + admStr = JSON.parse(adm.replace(/\\/g, '')); + if (admStr && admStr.native) { + newBid.mediaType = NATIVE; + } + } catch (e) { + utils.logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native reponse for ad response: ' + adm); + } + } +} + function _parseNativeResponse(bid, newBid) { newBid.native = {}; if (bid.hasOwnProperty('adm')) { @@ -722,40 +657,39 @@ function _parseNativeResponse(bid, newBid) { return; } if (adm && adm.native && adm.native.assets && adm.native.assets.length > 0) { - newBid.mediaType = 'native'; + newBid.mediaType = NATIVE; for (let i = 0, len = adm.native.assets.length; i < len; i++) { switch (adm.native.assets[i].id) { - case NATIVE_ASSET_ID.TITLE: + case NATIVE_ASSETS.TITLE.ID: newBid.native.title = adm.native.assets[i].title && adm.native.assets[i].title.text; break; - case NATIVE_ASSET_ID.IMAGE: + 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_ASSET_ID.ICON: + 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_ASSET_ID.SPONSOREDBY: - case NATIVE_ASSET_ID.BODY: - case NATIVE_ASSET_ID.LIKES: - case NATIVE_ASSET_ID.DOWNLOADS: - case NATIVE_ASSET_ID.PRICE: - case NATIVE_ASSET_ID.SALEPRICE: - case NATIVE_ASSET_ID.PHONE: - case NATIVE_ASSET_ID.ADDRESS: - case NATIVE_ASSET_ID.DESC2: - case NATIVE_ASSET_ID.CTA: - case NATIVE_ASSET_ID.RATING: - case NATIVE_ASSET_ID.DISPLAYURL: - // Remove Redundant code - newBid.native[NATIVE_ASSET_REVERSE_ID[adm.native.assets[i].id]] = adm.native.assets[i].data && adm.native.assets[i].data.value; + case NATIVE_ASSETS.SPONSOREDBY.ID: + case NATIVE_ASSETS.BODY.ID: + case NATIVE_ASSETS.LIKES.ID: + case NATIVE_ASSETS.DOWNLOADS.ID: + case NATIVE_ASSETS.PRICE: + case NATIVE_ASSETS.SALEPRICE.ID: + case NATIVE_ASSETS.PHONE.ID: + case NATIVE_ASSETS.ADDRESS.ID: + case NATIVE_ASSETS.DESC2.ID: + case NATIVE_ASSETS.CTA.ID: + case NATIVE_ASSETS.RATING.ID: + case NATIVE_ASSETS.DISPLAYURL.ID: + newBid.native[NATIVE_ASSET_ID_TO_KEY_MAP[adm.native.assets[i].id]] = adm.native.assets[i].data && adm.native.assets[i].data.value; break; } } @@ -831,7 +765,13 @@ export const spec = { return; } } else { - if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height)) { + if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex)) { + utils.logWarn(LOG_WARN_PREFIX + 'Skipping the non-standard adslot: ', bid.params.adSlot, JSON.stringify(bid)); + return; + } + // 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) { utils.logWarn(LOG_WARN_PREFIX + 'Skipping the non-standard adslot: ', bid.params.adSlot, JSON.stringify(bid)); return; } @@ -840,7 +780,7 @@ export const spec = { conf = _handleCustomParams(bid.params, conf); conf.transactionId = bid.transactionId; if (bidCurrency === '') { - bidCurrency = bid.params.currency || undefined; + bidCurrency = bid.params.currency || UNDEFINED; } else if (bid.params.hasOwnProperty('currency') && bidCurrency !== bid.params.currency) { utils.logWarn(LOG_WARN_PREFIX + 'Currency specifier ignored. Only one currency permitted.'); } @@ -887,9 +827,7 @@ export const spec = { payload.user.geo.lat = _parseSlotParam('lat', conf.lat); payload.user.geo.lon = _parseSlotParam('lon', conf.lon); payload.user.yob = _parseSlotParam('yob', conf.yob); - payload.device.geo = {}; - payload.device.geo.lat = _parseSlotParam('lat', conf.lat); - payload.device.geo.lon = _parseSlotParam('lon', conf.lon); + payload.device.geo = payload.user.geo; payload.site.page = conf.kadpageurl.trim() || payload.site.page.trim(); payload.site.domain = _getDomainFromURL(payload.site.page); @@ -962,14 +900,20 @@ export const spec = { }; if (parsedRequest.imp && parsedRequest.imp.length > 0) { parsedRequest.imp.forEach(req => { - if (bid.impid === req.id && req.hasOwnProperty('video')) { - newBid.mediaType = 'video'; - newBid.width = bid.hasOwnProperty('w') ? bid.w : req.video.w; - newBid.height = bid.hasOwnProperty('h') ? bid.h : req.video.h; - newBid.vastXml = bid.adm; - } - if (bid.impid === req.id && req.hasOwnProperty('native')) { - _parseNativeResponse(bid, newBid); + if (bid.impid === req.id) { + _checkMediaType(bid.adm, newBid); + switch (newBid.mediaType) { + case BANNER: + break; + case VIDEO: + newBid.width = bid.hasOwnProperty('w') ? bid.w : req.video.w; + newBid.height = bid.hasOwnProperty('h') ? bid.h : req.video.h; + newBid.vastXml = bid.adm; + break; + case NATIVE: + _parseNativeResponse(bid, newBid); + break; + } } }); } diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 60c45bfd8a9..e864689d0a1 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -108,6 +108,73 @@ var adUnits = [ }] }]; ``` +# Sample Configuration for Multi-format Ad Unit: For Publishers +``` +var adUnits = [ +{ + code: 'test-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + }, + video: { + playerSize: [640, 480], // required + context: 'instream' + }, + native: { + image: { + required: true, + sizes: [150, 50] + }, + title: { + required: true, + len: 80 + }, + sponsoredBy: { + required: true + }, + clickUrl: { + required: true + } + } + }, + bids: [{ + bidder: 'pubmatic', + params: { + publisherId: '156209', // required + adSlot: 'pubmatic_test2@300x250', // required + pmzoneid: 'zone1, zone11', // optional + lat: '40.712775', // optional + lon: '-74.005973', // optional + yob: '1982', // optional + kadpageurl: 'www.test.com', // optional + gender: 'M', // optional + kadfloor: '0.50', // optional + currency: 'AUD', // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) + dctr: 'key1=123|key2=345', // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) + 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 + } + } + }] +}]; +``` + # ## Configuration diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 0042ef5211e..8173f88bda8 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -18,11 +18,22 @@ describe('PubMatic adapter', function () { let validnativeBidImpressionWithRequiredParam; let nativeBidImpressionWithoutRequiredParams; let validnativeBidImpressionWithAllParams; + let bannerAndVideoBidRequests; + let bannerAndNativeBidRequests; + let videoAndNativeBidRequests; + let bannerVideoAndNativeBidRequests; + let bannerBidResponse; + let videoBidResponse; beforeEach(function () { bidRequests = [ { bidder: 'pubmatic', + mediaTypes: { + banner: { + sizes: [[728, 90], [160, 600]] + } + }, params: { publisherId: '301', adSlot: '/15671365/DMDemo@300x250:0', @@ -59,6 +70,7 @@ describe('PubMatic adapter', function () { } }, bidder: 'pubmatic', + bidId: '22bddb28db77d', params: { publisherId: '5890', adSlot: 'Div1@0x0', // ad_id or tagid @@ -81,8 +93,7 @@ describe('PubMatic adapter', function () { } ]; - multipleMediaRequests = - [ + multipleMediaRequests = [ { bidder: 'pubmatic', params: { @@ -272,6 +283,232 @@ describe('PubMatic adapter', function () { } }]; + bannerAndVideoBidRequests = [ + { + code: 'div-banner-video', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + }, + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 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,val2|key2:val1', + video: { + mimes: ['video/mp4', 'video/x-flv'], + skippable: true, + minduration: 5, + maxduration: 30, + startdelay: 15, + playbackmethod: [1, 3], + api: [1, 2], + protocols: [2, 3], + w: 640, + h: 480, + battr: [13, 14], + linearity: 1, + placement: 2, + minbitrate: 100, + maxbitrate: 4096 + } + }, + placementCode: '/19968336/header-bid-tag-1', + sizes: [[728, 90]], + bidId: '23acc48ad47af5', + requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ]; + + bannerAndNativeBidRequests = [ + { + code: 'div-banner-native', + mediaTypes: { + native: { + title: { + required: true, + length: 80 + }, + image: { + required: true, + sizes: [300, 250] + }, + sponsoredBy: { + required: true + } + }, + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + nativeParams: { + title: { required: true, length: 80 }, + image: { required: true, sizes: [300, 250] }, + sponsoredBy: { required: true } + }, + 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,val2|key2:val1' + }, + placementCode: '/19968336/header-bid-tag-1', + sizes: [[728, 90]], + bidId: '23acc48ad47af5', + requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ]; + + videoAndNativeBidRequests = [ + { + code: 'div-video-native', + mediaTypes: { + native: { + title: { + required: true, + length: 80 + }, + image: { + required: true, + sizes: [300, 250] + }, + sponsoredBy: { + required: true + } + }, + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + nativeParams: { + title: { required: true, length: 80 }, + image: { required: true, sizes: [300, 250] }, + sponsoredBy: { required: true } + }, + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + video: { + mimes: ['video/mp4', 'video/x-flv'], + skippable: true, + minduration: 5, + maxduration: 30, + startdelay: 15, + playbackmethod: [1, 3], + api: [1, 2], + protocols: [2, 3], + w: 640, + h: 480, + battr: [13, 14], + linearity: 1, + placement: 2, + minbitrate: 100, + maxbitrate: 4096 + } + }, + placementCode: '/19968336/header-bid-tag-1', + sizes: [[728, 90]], + bidId: '23acc48ad47af5', + requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ]; + + bannerVideoAndNativeBidRequests = [ + { + code: 'div-video-native', + mediaTypes: { + native: { + title: { + required: true, + length: 80 + }, + image: { + required: true, + sizes: [300, 250] + }, + sponsoredBy: { + required: true + } + }, + video: { + playerSize: [640, 480], + context: 'instream' + }, + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + nativeParams: { + title: { required: true, length: 80 }, + image: { required: true, sizes: [300, 250] }, + sponsoredBy: { required: true } + }, + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + video: { + mimes: ['video/mp4', 'video/x-flv'], + skippable: true, + minduration: 5, + maxduration: 30, + startdelay: 15, + playbackmethod: [1, 3], + api: [1, 2], + protocols: [2, 3], + w: 640, + h: 480, + battr: [13, 14], + linearity: 1, + placement: 2, + minbitrate: 100, + maxbitrate: 4096 + } + }, + placementCode: '/19968336/header-bid-tag-1', + sizes: [[728, 90]], + bidId: '23acc48ad47af5', + requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ]; + bidResponses = { 'body': { 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', @@ -354,6 +591,44 @@ describe('PubMatic adapter', function () { 'request': '{"assets":[{"id":1,"required":1,"title":{"len":80,"ext":{"title1":"title2"}}},{"id":3,"required":1,"img":{"type":1,"w":50,"h":50}},{"id":2,"required":1,"img":{"type":3,"w":728,"h":90,"mimes":["image/png","image/gif"],"ext":{"image1":"image2"}}},{"id":4,"required":1,"data":{"type":1,"len":10,"ext":{"sponsor1":"sponsor2"}}},{"id":5,"required":1,"data":{"type":2,"len":10,"ext":{"body1":"body2"}}},{"id":13,"required":1,"data":{"type":3,"len":10,"ext":{"rating1":"rating2"}}},{"id":14,"required":1,"data":{"type":4,"len":10,"ext":{"likes1":"likes2"}}},{"id":15,"required":1,"data":{"type":5,"len":10,"ext":{"downloads1":"downloads2"}}},{"id":16,"required":1,"data":{"type":6,"len":10,"ext":{"price1":"price2"}}},{"id":17,"required":1,"data":{"type":7,"len":10,"ext":{"saleprice1":"saleprice2"}}},{"id":18,"required":1,"data":{"type":8,"len":10,"ext":{"phone1":"phone2"}}},{"id":19,"required":1,"data":{"type":9,"len":10,"ext":{"address1":"address2"}}},{"id":20,"required":1,"data":{"type":10,"len":10,"ext":{"desc21":"desc22"}}},{"id":21,"required":1,"data":{"type":11,"len":10,"ext":{"displayurl1":"displayurl2"}}}]}' } } + + bannerBidResponse = { + 'body': { + 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', + 'seatbid': [{ + 'bid': [{ + 'id': '74858439-49D7-4169-BA5D-44A046315B2F', + 'impid': '23acc48ad47af5', + 'price': 1.3, + 'adm': ' ', + 'h': 250, + 'w': 300, + 'ext': { + 'deal_channel': 6 + } + }] + }] + } + }; + + 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.pubmatic.com', + 'h': 250, + 'w': 300, + 'ext': { + 'deal_channel': 6 + } + }] + }] + } + } }); describe('implementation', function () { @@ -502,6 +777,11 @@ describe('PubMatic adapter', function () { /* case 2 - size passed in adslot as well as in sizes array */ bidRequests[0].sizes = [[300, 600], [300, 250]]; + bidRequests[0].mediaTypes = { + banner: { + sizes: [[300, 600], [300, 250]] + } + }; request = spec.buildRequests(bidRequests); data = JSON.parse(request.data); @@ -511,6 +791,11 @@ describe('PubMatic adapter', function () { /* case 3 - size passed in sizes but not in adslot */ bidRequests[0].params.adSlot = '/15671365/DMDemo'; bidRequests[0].sizes = [[300, 250], [300, 600]]; + bidRequests[0].mediaTypes = { + banner: { + sizes: [[300, 250], [300, 600]] + } + }; request = spec.buildRequests(bidRequests); data = JSON.parse(request.data); @@ -1225,6 +1510,216 @@ describe('PubMatic adapter', function () { expect(data.imp[0]['native']['request']).to.exist.and.to.be.an('string'); expect(data.imp[0]['native']['request']).to.exist.and.to.equal(validnativeBidImpressionWithAllParams.native.request); }); + + it('Request params - should handle banner and video format in single adunit', function() { + let request = spec.buildRequests(bannerAndVideoBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + expect(data.banner).to.exist; + expect(data.banner.w).to.equal(300); + expect(data.banner.h).to.equal(250); + expect(data.banner.format).to.exist; + expect(data.banner.format.length).to.equal(bannerAndVideoBidRequests[0].mediaTypes.banner.sizes.length); + + // Case: when size is not present in adslo + bannerAndVideoBidRequests[0].params.adSlot = '/15671365/DMDemo'; + request = spec.buildRequests(bannerAndVideoBidRequests); + data = JSON.parse(request.data); + data = data.imp[0]; + expect(data.banner).to.exist; + expect(data.banner.w).to.equal(bannerAndVideoBidRequests[0].mediaTypes.banner.sizes[0][0]); + expect(data.banner.h).to.equal(bannerAndVideoBidRequests[0].mediaTypes.banner.sizes[0][1]); + expect(data.banner.format).to.exist; + expect(data.banner.format.length).to.equal(bannerAndVideoBidRequests[0].mediaTypes.banner.sizes.length - 1); + + expect(data.video).to.exist; + expect(data.video.w).to.equal(bannerAndVideoBidRequests[0].mediaTypes.video.playerSize[0]); + expect(data.video.h).to.equal(bannerAndVideoBidRequests[0].mediaTypes.video.playerSize[1]); + }); + + it('Request params - banner and video req in single adslot - should ignore banner imp if banner size is set to fluid and send video imp object', function () { + /* Adslot configured for banner and video. + banner size is set to [['fluid'], [300, 250]] + adslot specifies a size as 300x250 + => banner imp object should have primary w and h set to 300 and 250. fluid is ignored + */ + bannerAndVideoBidRequests[0].mediaTypes.banner.sizes = [['fluid'], [160, 600]]; + + let request = spec.buildRequests(bannerAndVideoBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.banner).to.exist; + expect(data.banner.w).to.equal(300); + expect(data.banner.h).to.equal(250); + expect(data.banner.format).to.exist; + expect(data.banner.format[0].w).to.equal(160); + expect(data.banner.format[0].h).to.equal(600); + + /* Adslot configured for banner and video. + banner size is set to [['fluid'], [300, 250]] + adslot does not specify any size + => banner imp object should have primary w and h set to 300 and 250. fluid is ignored + */ + bannerAndVideoBidRequests[0].mediaTypes.banner.sizes = [['fluid'], [160, 600]]; + bannerAndVideoBidRequests[0].params.adSlot = '/15671365/DMDemo'; + + request = spec.buildRequests(bannerAndVideoBidRequests); + data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.banner).to.exist; + expect(data.banner.w).to.equal(160); + expect(data.banner.h).to.equal(600); + expect(data.banner.format).to.not.exist; + + /* Adslot configured for banner and video. + banner size is set to [[728 90], ['fluid'], [300, 250]] + adslot does not specify any size + => banner imp object should have primary w and h set to 728 and 90. + banner.format should have 300, 250 set in it + fluid is ignore + */ + + bannerAndVideoBidRequests[0].mediaTypes.banner.sizes = [[728, 90], ['fluid'], [300, 250]]; + request = spec.buildRequests(bannerAndVideoBidRequests); + data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.banner).to.exist; + expect(data.banner.w).to.equal(728); + expect(data.banner.h).to.equal(90); + expect(data.banner.format).to.exist; + expect(data.banner.format[0].w).to.equal(300); + expect(data.banner.format[0].h).to.equal(250); + + /* Adslot configured for banner and video. + banner size is set to [['fluid']] + adslot does not specify any size + => banner object should not be sent in the request. only video should be sent. + */ + + bannerAndVideoBidRequests[0].mediaTypes.banner.sizes = [['fluid']]; + request = spec.buildRequests(bannerAndVideoBidRequests); + data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.banner).to.not.exist; + expect(data.video).to.exist; + }); + + it('Request params - should not contain banner imp if mediaTypes.banner is not present and sizes is specified in bid.sizes', function() { + delete bannerAndVideoBidRequests[0].mediaTypes.banner; + bannerAndVideoBidRequests[0].params.sizes = [300, 250]; + + let request = spec.buildRequests(bannerAndVideoBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + expect(data.banner).to.not.exist; + }); + + it('Request params - should handle banner and native format in single adunit', function() { + let request = spec.buildRequests(bannerAndNativeBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.banner).to.exist; + expect(data.banner.w).to.equal(300); + expect(data.banner.h).to.equal(250); + expect(data.banner.format).to.exist; + expect(data.banner.format.length).to.equal(bannerAndNativeBidRequests[0].mediaTypes.banner.sizes.length); + + expect(data.native).to.exist; + expect(data.native.request).to.exist; + }); + + it('Request params - should handle video and native format in single adunit', function() { + let request = spec.buildRequests(videoAndNativeBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.video).to.exist; + expect(data.video.w).to.equal(bannerAndVideoBidRequests[0].mediaTypes.video.playerSize[0]); + expect(data.video.h).to.equal(bannerAndVideoBidRequests[0].mediaTypes.video.playerSize[1]); + + expect(data.native).to.exist; + expect(data.native.request).to.exist; + }); + + it('Request params - should handle banner, video and native format in single adunit', function() { + let request = spec.buildRequests(bannerVideoAndNativeBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.banner).to.exist; + expect(data.banner.w).to.equal(300); + expect(data.banner.h).to.equal(250); + expect(data.banner.format).to.exist; + expect(data.banner.format.length).to.equal(bannerAndNativeBidRequests[0].mediaTypes.banner.sizes.length); + + expect(data.video).to.exist; + expect(data.video.w).to.equal(bannerAndVideoBidRequests[0].mediaTypes.video.playerSize[0]); + expect(data.video.h).to.equal(bannerAndVideoBidRequests[0].mediaTypes.video.playerSize[1]); + + expect(data.native).to.exist; + expect(data.native.request).to.exist; + }); + + it('Request params - should not add banner object if mediaTypes.banner is missing, but adunits.sizes is present', function() { + delete bannerAndNativeBidRequests[0].mediaTypes.banner; + bannerAndNativeBidRequests[0].sizes = [729, 90]; + + let request = spec.buildRequests(bannerAndNativeBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.banner).to.not.exist; + + expect(data.native).to.exist; + expect(data.native.request).to.exist; + }); + + it('Request params - banner and native multiformat request - should not have native object incase of invalid config present', function() { + bannerAndNativeBidRequests[0].mediaTypes.native = { + title: { required: true }, + image: { required: true }, + sponsoredBy: { required: true }, + clickUrl: { required: true } + }; + bannerAndNativeBidRequests[0].nativeParams = { + title: { required: true }, + image: { required: true }, + sponsoredBy: { required: true }, + clickUrl: { required: true } + } + let request = spec.buildRequests(bannerAndNativeBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.banner).to.exist; + expect(data.native).to.not.exist; + }); + + it('Request params - video and native multiformat request - should not have native object incase of invalid config present', function() { + videoAndNativeBidRequests[0].mediaTypes.native = { + title: { required: true }, + image: { required: true }, + sponsoredBy: { required: true }, + clickUrl: { required: true } + }; + videoAndNativeBidRequests[0].nativeParams = { + title: { required: true }, + image: { required: true }, + sponsoredBy: { required: true }, + clickUrl: { required: true } + } + let request = spec.buildRequests(videoAndNativeBidRequests); + let data = JSON.parse(request.data); + data = data.imp[0]; + + expect(data.video).to.exist; + expect(data.native).to.not.exist; + }); }); it('Request params dctr check', function () { @@ -1390,7 +1885,28 @@ describe('PubMatic adapter', function () { expect(response[0].native.image.width).to.exist; expect(response[0].native.sponsoredBy).to.exist.and.to.be.an('string'); expect(response[0].native.clickUrl).to.exist.and.to.be.an('string'); - }) + }); + + it('should check for valid banner mediaType in case of multiformat request', function() { + let request = spec.buildRequests(bidRequests); + let response = spec.interpretResponse(bannerBidResponse, request); + + expect(response[0].mediaType).to.equal('banner'); + }); + + it('should check for valid video mediaType in case of multiformat request', function() { + let request = spec.buildRequests(videoBidRequests); + let response = spec.interpretResponse(videoBidResponse, request); + + expect(response[0].mediaType).to.equal('video'); + }); + + it('should check for valid native mediaType in case of multiformat request', function() { + let request = spec.buildRequests(nativeBidRequests); + let response = spec.interpretResponse(nativeBidResponse, request); + + expect(response[0].mediaType).to.equal('native'); + }); }); }); }); From 6723904d59acccb245d8b9ecb5f07a1dcedf5a7e Mon Sep 17 00:00:00 2001 From: AlessandroDG Date: Mon, 1 Apr 2019 20:09:17 +0200 Subject: [PATCH 1122/1594] Rvr 2369 add trackable add ad units event (#3691) * RVR-2177 - Refactor events handling * RVR-2087 - Inject pbjsGlobalVariable into rivraddon * RVR-2087 - update adapterManager dependency * RVR-2087 - Add ADD_AD_UNITS to Prebid.JS trackable events * RVR-2369 - Update package-lock.json * RVR-2369 - Revert rivrAnalyticsAdapter changed Handled in separate PR https://github.com/prebid/Prebid.js/pull/3683 * RVR-2369 - Add REQUEST_BIDS to trackable events --- src/AnalyticsAdapter.js | 6 +++++- test/spec/AnalyticsAdapter_spec.js | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/AnalyticsAdapter.js b/src/AnalyticsAdapter.js index 5565ba2ed18..16d56725e39 100644 --- a/src/AnalyticsAdapter.js +++ b/src/AnalyticsAdapter.js @@ -8,6 +8,7 @@ const { EVENTS: { AUCTION_INIT, AUCTION_END, + REQUEST_BIDS, BID_REQUESTED, BID_TIMEOUT, BID_RESPONSE, @@ -16,7 +17,8 @@ const { BID_ADJUSTMENT, BIDDER_DONE, SET_TARGETING, - AD_RENDER_FAILED + AD_RENDER_FAILED, + ADD_AD_UNITS } } = CONSTANTS; @@ -99,6 +101,7 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } // Next register event listeners to send data immediately _handlers = { + [REQUEST_BIDS]: args => this.enqueue({ eventType: REQUEST_BIDS, args }), [BID_REQUESTED]: args => this.enqueue({ eventType: BID_REQUESTED, args }), [BID_RESPONSE]: args => this.enqueue({ eventType: BID_RESPONSE, args }), [NO_BID]: args => this.enqueue({ eventType: NO_BID, args }), @@ -109,6 +112,7 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } [SET_TARGETING]: args => this.enqueue({ eventType: SET_TARGETING, args }), [AUCTION_END]: args => this.enqueue({ eventType: AUCTION_END, args }), [AD_RENDER_FAILED]: args => this.enqueue({ eventType: AD_RENDER_FAILED, args }), + [ADD_AD_UNITS]: args => this.enqueue({ eventType: ADD_AD_UNITS, args }), [AUCTION_INIT]: args => { args.config = typeof config === 'object' ? config.options || {} : {}; // enableAnaltyics configuration object this.enqueue({ eventType: AUCTION_INIT, args }); diff --git a/test/spec/AnalyticsAdapter_spec.js b/test/spec/AnalyticsAdapter_spec.js index 39096c0c4a3..59138b03e61 100644 --- a/test/spec/AnalyticsAdapter_spec.js +++ b/test/spec/AnalyticsAdapter_spec.js @@ -2,11 +2,13 @@ import { expect } from 'chai'; import events from 'src/events'; import CONSTANTS from 'src/constants.json'; +const REQUEST_BIDS = CONSTANTS.EVENTS.REQUEST_BIDS; const BID_REQUESTED = CONSTANTS.EVENTS.BID_REQUESTED; const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; const BID_WON = CONSTANTS.EVENTS.BID_WON; const BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; const AD_RENDER_FAILED = CONSTANTS.EVENTS.AD_RENDER_FAILED; +const ADD_AD_UNITS = CONSTANTS.EVENTS.ADD_AD_UNITS; const AnalyticsAdapter = require('src/AnalyticsAdapter').default; const config = { @@ -86,6 +88,28 @@ FEATURE: Analytics Adapters API expect(result).to.deep.equal({args: {call: 'adRenderFailed'}, eventType: 'adRenderFailed'}); }); + it('SHOULD call global when an addAdUnits event occurs', function () { + const eventType = ADD_AD_UNITS; + const args = { call: 'addAdUnits' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'addAdUnits'}, eventType: 'addAdUnits'}); + }); + + it('SHOULD call global when a requestBids event occurs', function () { + const eventType = REQUEST_BIDS; + const args = { call: 'request' }; + + adapter.enableAnalytics(); + events.emit(eventType, args); + + let result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({args: {call: 'request'}, eventType: 'requestBids'}); + }); + it('SHOULD call global when a bidRequest event occurs', function () { const eventType = BID_REQUESTED; const args = { call: 'request' }; From 14ecb8a2a47a2410381e40a135c77700bfa8f83e Mon Sep 17 00:00:00 2001 From: bidphysics <48674658+bidphysics@users.noreply.github.com> Date: Tue, 2 Apr 2019 01:16:15 +0700 Subject: [PATCH 1123/1594] Bidphysics Bid Adapter (#3666) * Bidphysics Bid Adapter * BidPhysics bid-adapter tests fix * removed empty functions * minor update - added publisherId and networkId params --- modules/bidphysicsBidAdapter.js | 134 +++++++++ modules/bidphysicsBidAdapter.md | 33 +++ .../spec/modules/bidphysicsBidAdapter_spec.js | 261 ++++++++++++++++++ 3 files changed, 428 insertions(+) create mode 100644 modules/bidphysicsBidAdapter.js create mode 100644 modules/bidphysicsBidAdapter.md create mode 100644 test/spec/modules/bidphysicsBidAdapter_spec.js diff --git a/modules/bidphysicsBidAdapter.js b/modules/bidphysicsBidAdapter.js new file mode 100644 index 00000000000..260a473c631 --- /dev/null +++ b/modules/bidphysicsBidAdapter.js @@ -0,0 +1,134 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import {BANNER} from '../src/mediaTypes'; + +const ENDPOINT_URL = '//exchange.bidphysics.com/auction'; + +const DEFAULT_BID_TTL = 30; +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_NET_REVENUE = true; + +export const spec = { + code: 'bidphysics', + aliases: ['yieldlift', 'padsquad'], + supportedMediaTypes: [BANNER], + + isBidRequestValid: function (bid) { + return (!!bid.params.unitId && typeof bid.params.unitId === 'string') || + (!!bid.params.networkId && typeof bid.params.networkId === 'string') || + (!!bid.params.publisherId && typeof bid.params.publisherId === 'string'); + }, + + buildRequests: function (validBidRequests, bidderRequest) { + if (!validBidRequests || !bidderRequest) { + return; + } + const publisherId = validBidRequests[0].params.publisherId; + const networkId = validBidRequests[0].params.networkId; + const impressions = validBidRequests.map(bidRequest => ({ + id: bidRequest.bidId, + banner: { + format: bidRequest.sizes.map(sizeArr => ({ + w: sizeArr[0], + h: sizeArr[1] + })) + }, + ext: { + bidphysics: { + unitId: bidRequest.params.unitId + } + } + })); + + const openrtbRequest = { + id: bidderRequest.auctionId, + imp: impressions, + site: { + domain: window.location.hostname, + page: window.location.href, + ref: bidderRequest.refererInfo ? bidderRequest.refererInfo.referer || null : null + }, + ext: { + bidphysics: { + publisherId: publisherId, + networkId: networkId, + } + } + }; + + // apply gdpr + if (bidderRequest.gdprConsent) { + openrtbRequest.regs = {ext: {gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0}}; + openrtbRequest.user = {ext: {consent: bidderRequest.gdprConsent.consentString}}; + } + + const payloadString = JSON.stringify(openrtbRequest); + return { + method: 'POST', + url: ENDPOINT_URL, + data: payloadString, + }; + }, + + interpretResponse: function (serverResponse, request) { + const bidResponses = []; + const response = (serverResponse || {}).body; + // response is always one seat (bidphysics) with (optional) bids for each impression + if (response && response.seatbid && response.seatbid.length === 1 && response.seatbid[0].bid && response.seatbid[0].bid.length) { + response.seatbid[0].bid.forEach(bid => { + bidResponses.push({ + requestId: bid.impid, + cpm: bid.price, + width: bid.w, + height: bid.h, + ad: bid.adm, + ttl: DEFAULT_BID_TTL, + creativeId: bid.crid, + netRevenue: DEFAULT_NET_REVENUE, + currency: DEFAULT_CURRENCY, + }) + }) + } else { + utils.logInfo('bidphysics.interpretResponse :: no valid responses to interpret'); + } + return bidResponses; + }, + getUserSyncs: function (syncOptions, serverResponses) { + utils.logInfo('bidphysics.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses); + let syncs = []; + + if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { + return syncs; + } + + serverResponses.forEach(resp => { + const userSync = utils.deepAccess(resp, 'body.ext.usersync'); + if (userSync) { + let syncDetails = []; + Object.keys(userSync).forEach(key => { + const value = userSync[key]; + if (value.syncs && value.syncs.length) { + syncDetails = syncDetails.concat(value.syncs); + } + }); + syncDetails.forEach(syncDetails => { + syncs.push({ + type: syncDetails.type === 'iframe' ? 'iframe' : 'image', + url: syncDetails.url + }); + }); + + if (!syncOptions.iframeEnabled) { + syncs = syncs.filter(s => s.type !== 'iframe') + } + if (!syncOptions.pixelEnabled) { + syncs = syncs.filter(s => s.type !== 'image') + } + } + }); + utils.logInfo('bidphysics.getUserSyncs result=%o', syncs); + return syncs; + }, + +}; +registerBidder(spec); diff --git a/modules/bidphysicsBidAdapter.md b/modules/bidphysicsBidAdapter.md new file mode 100644 index 00000000000..d7d8b355027 --- /dev/null +++ b/modules/bidphysicsBidAdapter.md @@ -0,0 +1,33 @@ +# Overview + +``` +Module Name: BidPhysics Bid Adapter +Module Type: Bidder Adapter +Maintainer: info@bidphysics.com +``` + +# Description + +Connects to BidPhysics exchange for bids. + +BidPhysics bid adapter supports Banner ads. + +# Test Parameters +``` +var adUnits = [ + { + code: 'banner-ad-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'bidphysics', + params: { + unitId: 'bidphysics-test' + } + }] + } +]; +``` diff --git a/test/spec/modules/bidphysicsBidAdapter_spec.js b/test/spec/modules/bidphysicsBidAdapter_spec.js new file mode 100644 index 00000000000..ba93642ad81 --- /dev/null +++ b/test/spec/modules/bidphysicsBidAdapter_spec.js @@ -0,0 +1,261 @@ +import {expect} from 'chai'; +import {spec} from 'modules/bidphysicsBidAdapter'; + +const REQUEST = { + 'bidderCode': 'bidphysics', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708', + 'bidderRequestId': 'requestId', + 'bidRequest': [{ + 'bidder': 'bidphysics', + 'params': { + 'unitId': 123456, + }, + 'placementCode': 'div-gpt-dummy-placement-code', + 'sizes': [ + [300, 250] + ], + 'bidId': 'bidId1', + 'bidderRequestId': 'bidderRequestId', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708' + }, + { + 'bidder': 'bidphysics', + 'params': { + 'unitId': 123456, + }, + 'placementCode': 'div-gpt-dummy-placement-code', + 'sizes': [ + [300, 250] + ], + 'bidId': 'bidId2', + 'bidderRequestId': 'bidderRequestId', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708' + }], + 'start': 1487883186070, + 'auctionStart': 1487883186069, + 'timeout': 3000 +}; + +const RESPONSE = { + 'headers': null, + 'body': { + 'id': 'responseId', + 'seatbid': [ + { + 'bid': [ + { + 'id': 'bidId1', + 'impid': 'bidId1', + 'price': 0.18, + 'adm': '', + 'adid': '144762342', + 'adomain': [ + 'http://dummydomain.com' + ], + 'iurl': 'iurl', + 'cid': '109', + 'crid': 'creativeId', + 'cat': [], + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 334553, + 'auction_id': 514667951122925701, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + }, + { + 'id': 'bidId2', + 'impid': 'bidId2', + 'price': 0.1, + 'adm': '', + 'adid': '144762342', + 'adomain': [ + 'http://dummydomain.com' + ], + 'iurl': 'iurl', + 'cid': '109', + 'crid': 'creativeId', + 'cat': [], + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 386046, + 'auction_id': 517067951122925501, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + } + ], + 'seat': 'bidphysics' + } + ], + 'ext': { + 'usersync': { + 'sovrn': { + 'status': 'none', + 'syncs': [ + { + 'url': 'urlsovrn', + 'type': 'iframe' + } + ] + }, + 'appnexus': { + 'status': 'none', + 'syncs': [ + { + 'url': 'urlappnexus', + 'type': 'pixel' + } + ] + } + }, + 'responsetimemillis': { + 'appnexus': 127 + } + } + } +}; + +describe('BidPhysics bid adapter', function () { + describe('isBidRequestValid', function () { + it('should accept request if only unitId is passed', function () { + let bid = { + bidder: 'bidphysics', + params: { + unitId: 'unitId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should accept request if only networkId is passed', function () { + let bid = { + bidder: 'bidphysics', + params: { + networkId: 'networkId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should accept request if only publisherId is passed', function () { + let bid = { + bidder: 'bidphysics', + params: { + publisherId: 'publisherId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('reject requests without params', function () { + let bid = { + bidder: 'bidphysics', + params: {} + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + it('creates request data', function () { + let request = spec.buildRequests(REQUEST.bidRequest, REQUEST); + + expect(request).to.exist.and.to.be.a('object'); + const payload = JSON.parse(request.data); + expect(payload.imp[0]).to.have.property('id', REQUEST.bidRequest[0].bidId); + expect(payload.imp[1]).to.have.property('id', REQUEST.bidRequest[1].bidId); + }); + + it('has gdpr data if applicable', function () { + const req = Object.assign({}, REQUEST, { + gdprConsent: { + consentString: 'consentString', + gdprApplies: true, + } + }); + let request = spec.buildRequests(REQUEST.bidRequest, req); + + const payload = JSON.parse(request.data); + expect(payload.user.ext).to.have.property('consent', req.gdprConsent.consentString); + expect(payload.regs.ext).to.have.property('gdpr', 1); + }); + }); + + describe('interpretResponse', function () { + it('have bids', function () { + let bids = spec.interpretResponse(RESPONSE, REQUEST); + expect(bids).to.be.an('array').that.is.not.empty; + validateBidOnIndex(0); + validateBidOnIndex(1); + + function validateBidOnIndex(index) { + expect(bids[index]).to.have.property('currency', 'USD'); + expect(bids[index]).to.have.property('requestId', RESPONSE.body.seatbid[0].bid[index].impid); + expect(bids[index]).to.have.property('cpm', RESPONSE.body.seatbid[0].bid[index].price); + expect(bids[index]).to.have.property('width', RESPONSE.body.seatbid[0].bid[index].w); + expect(bids[index]).to.have.property('height', RESPONSE.body.seatbid[0].bid[index].h); + expect(bids[index]).to.have.property('ad', RESPONSE.body.seatbid[0].bid[index].adm); + expect(bids[index]).to.have.property('creativeId', RESPONSE.body.seatbid[0].bid[index].crid); + expect(bids[index]).to.have.property('ttl', 30); + expect(bids[index]).to.have.property('netRevenue', true); + } + }); + + it('handles empty response', function () { + const EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {}}); + const bids = spec.interpretResponse(EMPTY_RESP, REQUEST); + + expect(bids).to.be.empty; + }); + }); + + describe('getUserSyncs', function () { + it('handles no parameters', function () { + let opts = spec.getUserSyncs({}); + expect(opts).to.be.an('array').that.is.empty; + }); + it('returns non if sync is not allowed', function () { + let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false}); + + expect(opts).to.be.an('array').that.is.empty; + }); + + it('iframe sync enabled should return results', function () { + let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [RESPONSE]); + + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('iframe'); + expect(opts[0].url).to.equal(RESPONSE.body.ext.usersync['sovrn'].syncs[0].url); + }); + + it('pixel sync enabled should return results', function () { + let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [RESPONSE]); + + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('image'); + expect(opts[0].url).to.equal(RESPONSE.body.ext.usersync['appnexus'].syncs[0].url); + }); + + it('all sync enabled should return all results', function () { + let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [RESPONSE]); + + expect(opts.length).to.equal(2); + }); + }); +}); From 95872c1ff7ba2ea83f8c5e52b0c887f1d1f33cf4 Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Tue, 2 Apr 2019 06:43:03 +0300 Subject: [PATCH 1124/1594] Update vidazooBidAdapter.js (#3689) New ad server domain --- modules/vidazooBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/vidazooBidAdapter.js b/modules/vidazooBidAdapter.js index acfaf8b3bfc..693d6f9724d 100644 --- a/modules/vidazooBidAdapter.js +++ b/modules/vidazooBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import {BANNER} from '../src/mediaTypes'; -export const URL = '//prebid.nininin.com'; +export const URL = '//prebid.cootlogix.com'; const BIDDER_CODE = 'vidazoo'; const CURRENCY = 'USD'; const TTL_SECONDS = 60 * 5; @@ -92,7 +92,7 @@ function getUserSyncs(syncOptions, responses) { if (iframeEnabled) { return [{ type: 'iframe', - url: '//static.nininin.com/basev/sync/user_sync.html' + url: '//static.cootlogix.com/basev/sync/user_sync.html' }]; } From f95267b8cf0435bb30b5f58b0dc824d97939d28a Mon Sep 17 00:00:00 2001 From: Xiaofeng Chen Date: Tue, 2 Apr 2019 14:45:16 -0400 Subject: [PATCH 1125/1594] Add gdpr_consented_providers for google gdpr (#3688) --- modules/freewheel-sspBidAdapter.js | 4 ++++ test/spec/modules/freewheel-sspBidAdapter_spec.js | 2 ++ 2 files changed, 6 insertions(+) diff --git a/modules/freewheel-sspBidAdapter.js b/modules/freewheel-sspBidAdapter.js index f7d647e0569..3e52ba2cbe9 100644 --- a/modules/freewheel-sspBidAdapter.js +++ b/modules/freewheel-sspBidAdapter.js @@ -252,6 +252,10 @@ export const spec = { } } + if (currentBidRequest.params.gdpr_consented_providers) { + requestParams._fw_gdpr_consented_providers = currentBidRequest.params.gdpr_consented_providers; + } + var vastParams = currentBidRequest.params.vastUrlParams; if (typeof vastParams === 'object') { for (var key in vastParams) { diff --git a/test/spec/modules/freewheel-sspBidAdapter_spec.js b/test/spec/modules/freewheel-sspBidAdapter_spec.js index 177deaca7e7..45754d0250c 100644 --- a/test/spec/modules/freewheel-sspBidAdapter_spec.js +++ b/test/spec/modules/freewheel-sspBidAdapter_spec.js @@ -46,6 +46,7 @@ describe('freewheel-ssp BidAdapter Test', function () { 'bidder': 'freewheel-ssp', 'params': { 'zoneId': '277225', + 'gdpr_consented_providers': '123,345', 'vastUrlParams': {'ownerId': 'kombRJ'} }, 'adUnitCode': 'adunit-code', @@ -71,6 +72,7 @@ describe('freewheel-ssp BidAdapter Test', function () { expect(payload.playerSize).to.equal('300x600'); expect(payload._fw_gdpr).to.equal(true); expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + expect(payload._fw_gdpr_consented_providers).to.equal('123,345'); }); it('sends bid request to ENDPOINT via GET', function () { From c060a5ce9087f48f257c4a383f854e989e49dab4 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 2 Apr 2019 13:39:12 -0700 Subject: [PATCH 1126/1594] Add 'hb_cache_host' targeting for video bids when cache is set (#3654) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * add 'hb_cache_host' and 'hb_cache_path' targeting for video bids using cache * update with requested changes from pull request, changed hb_cache_host so it will be defined even if adserverTargeting was defined, removed hb_cache_path. * update to not add hb_cache_host targeting if sendStandardTargeting is false * update condition logic to add hb_cache_host if bidderCode does not have add-video-cache-targeting-host-path value --- src/auction.js | 125 ++++++++++++++++--------------- src/constants.json | 3 +- test/spec/auctionmanager_spec.js | 14 ++++ 3 files changed, 80 insertions(+), 62 deletions(-) diff --git a/src/auction.js b/src/auction.js index bf3f1bb1b71..7cb08af7402 100644 --- a/src/auction.js +++ b/src/auction.js @@ -48,7 +48,8 @@ * @property {function(): void} callBids - sends requests to all adapters for bids */ -import { uniques, flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest } from './utils'; +import { uniques, flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest, getValue } from './utils'; +import { parse as parseURL } from './url'; import { getPriceBucketString } from './cpmBucketManager'; import { getNativeTargeting } from './native'; import { getCacheUrl, store } from './videoCache'; @@ -504,7 +505,26 @@ function setupBidTargeting(bidObject, bidderRequest) { bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); } -export function getStandardBidderSettings(mediaType) { +/** + * @param {string} mediaType + * @param {string} bidderCode + * @returns {*} + */ +export function getStandardBidderSettings(mediaType, bidderCode) { + // 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; // Use the config value 'mediaTypeGranularity' if it has been set for mediaType, else use 'priceGranularity' const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${mediaType}`); const granularity = (typeof mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); @@ -515,67 +535,50 @@ export function getStandardBidderSettings(mediaType) { } 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] = [ - { - key: CONSTANTS.TARGETING_KEYS.BIDDER, - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: CONSTANTS.TARGETING_KEYS.AD_ID, - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: CONSTANTS.TARGETING_KEYS.PRICE_BUCKET, - val: function (bidResponse) { - if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { - return bidResponse.pbAg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { - return bidResponse.pbDg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { - return bidResponse.pbLg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { - return bidResponse.pbMg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { - return bidResponse.pbHg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { - return bidResponse.pbCg; - } - } - }, { - key: CONSTANTS.TARGETING_KEYS.SIZE, - val: function (bidResponse) { - return bidResponse.size; - } - }, { - key: CONSTANTS.TARGETING_KEYS.DEAL, - val: function (bidResponse) { - return bidResponse.dealId; + createKeyVal(TARGETING_KEYS.BIDDER, 'bidderCode'), + createKeyVal(TARGETING_KEYS.AD_ID, 'adId'), + createKeyVal(TARGETING_KEYS.PRICE_BUCKET, function(bidResponse) { + if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { + return bidResponse.pbAg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { + return bidResponse.pbDg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { + return bidResponse.pbLg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { + return bidResponse.pbMg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { + return bidResponse.pbHg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { + return bidResponse.pbCg; } - }, - { - key: CONSTANTS.TARGETING_KEYS.SOURCE, - val: function (bidResponse) { - return bidResponse.source; - } - }, - { - key: CONSTANTS.TARGETING_KEYS.FORMAT, - val: function (bidResponse) { - return bidResponse.mediaType; - } - }, + }), + createKeyVal(TARGETING_KEYS.SIZE, 'size'), + createKeyVal(TARGETING_KEYS.DEAL, 'dealId'), + createKeyVal(TARGETING_KEYS.SOURCE, 'source'), + createKeyVal(TARGETING_KEYS.FORMAT, 'mediaType'), ] + } - if (mediaType === 'video') { - [CONSTANTS.TARGETING_KEYS.UUID, CONSTANTS.TARGETING_KEYS.CACHE_ID].forEach(item => { - bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].push({ - key: item, - val: function val(bidResponse) { - return bidResponse.videoCacheKey; - } - }) - }); + if (mediaType === 'video') { + 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 => { + if (typeof find(adserverTargeting, kvPair => kvPair.key === targetingKeyVal) === 'undefined') { + adserverTargeting.push(createKeyVal(targetingKeyVal, 'videoCacheKey')); + } + }); + + // Adding hb_cache_host + 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 utils.deepAccess(bidResponse, `adserverTargeting.${TARGETING_KEYS.CACHE_HOST}`) + ? bidResponse.adserverTargeting[TARGETING_KEYS.CACHE_HOST] : urlInfo.hostname; + })); + } } } return bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; @@ -592,7 +595,7 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) { // 1) set the keys from "standard" setting or from prebid defaults if (bidderSettings) { // initialize default if not set - const standardSettings = getStandardBidderSettings(custBidObj.mediaType); + const standardSettings = getStandardBidderSettings(custBidObj.mediaType, bidderCode); setKeys(keyValues, standardSettings, custBidObj); // 2) set keys from specific bidder setting override if they exist diff --git a/src/constants.json b/src/constants.json index 1a78e376150..a181df3f684 100644 --- a/src/constants.json +++ b/src/constants.json @@ -64,7 +64,8 @@ "SOURCE": "hb_source", "FORMAT": "hb_format", "UUID": "hb_uuid", - "CACHE_ID": "hb_cache_id" + "CACHE_ID": "hb_cache_id", + "CACHE_HOST": "hb_cache_host" }, "NATIVE_KEYS": { "title": "hb_native_title", diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index aab1da11653..9c936ace421 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -142,6 +142,7 @@ describe('auctionmanager.js', function () { if (bid.mediaType === 'video') { expected[ CONSTANTS.TARGETING_KEYS.UUID ] = bid.videoCacheKey; expected[ CONSTANTS.TARGETING_KEYS.CACHE_ID ] = bid.videoCacheKey; + expected[ CONSTANTS.TARGETING_KEYS.CACHE_HOST ] = 'prebid.adnxs.com'; } if (!keys) { return expected; @@ -162,11 +163,18 @@ describe('auctionmanager.js', function () { it('No bidder level configuration defined - default', function () { $$PREBID_GLOBAL$$.bidderSettings = {}; let expected = getDefaultExpected(bid); + // remove hb_cache_host from expected + delete expected.hb_cache_host; let response = getKeyValueTargetingPairs(bid.bidderCode, bid); assert.deepEqual(response, expected); }); it('No bidder level configuration defined - default for video', function () { + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); $$PREBID_GLOBAL$$.bidderSettings = {}; let videoBid = utils.deepClone(bid); videoBid.mediaType = 'video'; @@ -229,6 +237,11 @@ describe('auctionmanager.js', function () { }); it('Custom configuration for all bidders with video bid', function () { + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); let videoBid = utils.deepClone(bid); videoBid.mediaType = 'video'; videoBid.videoCacheKey = 'abc123def'; @@ -288,6 +301,7 @@ describe('auctionmanager.js', function () { }; let expected = getDefaultExpected(videoBid); + let response = getKeyValueTargetingPairs(videoBid.bidderCode, videoBid); assert.deepEqual(response, expected); }); From 3b2093ae5c5d5625c3447061e9d4353976c69104 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 3 Apr 2019 13:26:32 -0400 Subject: [PATCH 1127/1594] remove removeRequestId logic (#3698) --- src/prebid.js | 17 ++++++----------- src/utils.js | 9 --------- test/fixtures/fixtures.js | 15 ++++++++++++++- test/spec/unit/pbjs_api_spec.js | 8 ++++---- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 0374649c47c..21be22e5376 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -1,7 +1,7 @@ /** @module pbjs */ import { getGlobal } from './prebidGlobal'; -import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, removeRequestId, getLatestHighestCpmBid, isArrayOfNums } from './utils'; +import { flatten, uniques, isGptPubadsDefined, adUnitsFilter, getLatestHighestCpmBid, isArrayOfNums } from './utils'; import { listenMessagesFromCreative } from './secureCreatives'; import { userSync } from './userSync.js'; import { loadScript } from './adloader'; @@ -184,7 +184,7 @@ function getBids(type) { .filter(bids => bids && bids[0] && bids[0].adUnitCode) .map(bids => { return { - [bids[0].adUnitCode]: { bids: bids.map(removeRequestId) } + [bids[0].adUnitCode]: { bids } }; }) .reduce((a, b) => Object.assign(a, b), {}); @@ -221,9 +221,7 @@ $$PREBID_GLOBAL$$.getBidResponses = function () { $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode = function (adUnitCode) { const bids = auctionManager.getBidsReceived().filter(bid => bid.adUnitCode === adUnitCode); - return { - bids: bids.map(removeRequestId) - }; + return { bids }; }; /** @@ -663,8 +661,7 @@ $$PREBID_GLOBAL$$.aliasBidder = function (bidderCode, alias) { * @return {Array} A list of bids that have been rendered. */ $$PREBID_GLOBAL$$.getAllWinningBids = function () { - return auctionManager.getAllWinningBids() - .map(removeRequestId); + return auctionManager.getAllWinningBids(); }; /** @@ -673,8 +670,7 @@ $$PREBID_GLOBAL$$.getAllWinningBids = function () { */ $$PREBID_GLOBAL$$.getAllPrebidWinningBids = function () { return auctionManager.getBidsReceived() - .filter(bid => bid.status === CONSTANTS.BID_STATUS.BID_TARGETING_SET) - .map(removeRequestId); + .filter(bid => bid.status === CONSTANTS.BID_STATUS.BID_TARGETING_SET); }; /** @@ -686,8 +682,7 @@ $$PREBID_GLOBAL$$.getAllPrebidWinningBids = function () { */ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { let bidsReceived = getHighestCpmBidsFromBidPool(auctionManager.getBidsReceived(), getLatestHighestCpmBid); - return targeting.getWinningBids(adUnitCode, bidsReceived) - .map(removeRequestId); + return targeting.getWinningBids(adUnitCode, bidsReceived); }; /** diff --git a/src/utils.js b/src/utils.js index a93e25356bd..f8ac56bb6a1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1113,15 +1113,6 @@ export function deletePropertyFromObject(object, prop) { return result; } -/** - * Delete requestId from external bid object. - * @param {Object} bid - * @return {Object} bid - */ -export function removeRequestId(bid) { - return deletePropertyFromObject(bid, 'requestId'); -} - /** * Checks input is integer or not * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index 816363f5eea..050ff90bc7a 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -340,6 +340,7 @@ export function getBidResponses() { 'pbAg': '0.10', 'size': '0x0', 'auctionId': 123456, + 'requestId': '1144e2f0de84363', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'triplelift', 'hb_adid': '222bb26f9e8bd', @@ -372,6 +373,7 @@ export function getBidResponses() { 'size': '300x250', 'alwaysUseBid': true, 'auctionId': 123456, + 'requestId': '4dccdc37746135', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'appnexus', 'hb_adid': '233bcbee889d46d', @@ -404,6 +406,7 @@ export function getBidResponses() { 'size': '728x90', 'alwaysUseBid': true, 'auctionId': 123456, + 'requestId': '392b5a6b05d648', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'appnexus', 'hb_adid': '24bd938435ec3fc', @@ -435,6 +438,7 @@ export function getBidResponses() { 'pbAg': '0.50', 'size': '300x250', 'auctionId': 123456, + 'requestId': '192c8c1df0f5d1d', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'pagescience', 'hb_adid': '25bedd4813632d7', @@ -465,6 +469,7 @@ export function getBidResponses() { 'pbAg': '0.15', 'size': '300x250', 'auctionId': 654321, + 'requestId': '135e89c039705da', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'brightcom', 'hb_adid': '26e0795ab963896', @@ -496,6 +501,7 @@ export function getBidResponses() { 'pbAg': '0.50', 'size': '300x250', 'auctionId': 654321, + 'requestId': '17dd1d869bed44e', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'brealtime', 'hb_adid': '275bd666f5a5a5d', @@ -528,6 +534,7 @@ export function getBidResponses() { 'pbAg': '5.90', 'size': '300x250', 'auctionId': 654321, + 'requestId': '6d11aa2d5b3659', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'pubmatic', 'hb_adid': '28f4039c636b6a7', @@ -558,6 +565,7 @@ export function getBidResponses() { 'pbAg': '2.70', 'size': '300x600', 'auctionId': 654321, + 'requestId': '96aff279720d39', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'rubicon', 'hb_adid': '29019e2ab586a5a', @@ -1062,6 +1070,7 @@ export function getBidResponsesFromAPI() { 'pbAg': '0.15', 'size': '300x250', 'auctionId': 654321, + 'requestId': '135e89c039705da', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'brightcom', 'hb_adid': '26e0795ab963896', @@ -1093,6 +1102,7 @@ export function getBidResponsesFromAPI() { 'pbAg': '0.50', 'size': '300x250', 'auctionId': 654321, + 'requestId': '17dd1d869bed44e', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'brealtime', 'hb_adid': '275bd666f5a5a5d', @@ -1125,6 +1135,7 @@ export function getBidResponsesFromAPI() { 'pbAg': '5.90', 'size': '300x250', 'auctionId': 654321, + 'requestId': '6d11aa2d5b3659', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'pubmatic', 'hb_adid': '28f4039c636b6a7', @@ -1155,6 +1166,7 @@ export function getBidResponsesFromAPI() { 'pbAg': '2.70', 'size': '300x600', 'auctionId': 654321, + 'requestId': '96aff279720d39', 'adserverTargeting': convertTargetingsFromOldToNew({ 'hb_bidder': 'rubicon', 'hb_adid': '29019e2ab586a5a', @@ -1434,7 +1446,7 @@ export function getCurrencyRates() { }; } -export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, adUnitCode, adId, status, ttl}) { +export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, adUnitCode, adId, status, ttl, requestId}) { let bid = { 'bidderCode': bidder, 'width': '300', @@ -1448,6 +1460,7 @@ export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, ad 'requestTimestamp': 1454535718610, 'responseTimestamp': responseTimestamp, 'auctionId': auctionId, + 'requestId': requestId, 'timeToRespond': 123, 'pbLg': '0.50', 'pbMg': '0.50', diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 3172ec9c514..b734faf9dd5 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -2466,10 +2466,10 @@ describe('Unit: Prebid Module', function () { it('should return prebid auction winning bids', function () { let bidsReceived = [ - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'targetingSet'}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), - createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4'}), + createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'targetingSet', requestId: 'reqid-1'}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2', requestId: 'reqid-2'}), + createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3', requestId: 'reqid-3'}), + createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4', requestId: 'reqid-4'}), ]; auctionManagerStub.returns(bidsReceived) let bids = $$PREBID_GLOBAL$$.getAllPrebidWinningBids(); From 19bdc65e60c6aed4707aafefcd138a7ef6bfc009 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Wed, 3 Apr 2019 13:48:59 -0400 Subject: [PATCH 1128/1594] Prebid 2.9.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a1e2dc2a94b..ae33c3b15d7 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.9.0-pre", + "version": "2.9.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 98b7f7e65ec486c2e664fad80a2bf479204c8120 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Wed, 3 Apr 2019 14:07:55 -0400 Subject: [PATCH 1129/1594] increment prebid version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae33c3b15d7..c46c75c4dce 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.9.0", + "version": "2.10.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From eeddc24712738e1e535410ccb0df2fec2f2521ae Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Thu, 4 Apr 2019 10:39:11 -0700 Subject: [PATCH 1130/1594] User ID Module (#3424) * add initial files * add local storage and cookie browser support functions * added additional test cases for functions related to local storage and cookie browser support * added validate config function and first unit test * add validate config test * updated local storage key value to match change to requirements/spec * updated submodule config key names to match requirements/spec * added TODO with validation logic breakdown as well as a question on how to handle both 'value' and 'storage' existing in config * add TODO addressing use-case: Publisher has integrated with OpenID on their own * fixed comment * rearranged unit tests for config functions to be grouped correctly * added logic to valid that a submodule contains a config with a value or storage obj * removed sinon mock of config.getConfig, replaced with obj literal definition in function arguments * additional use cases added to validateConfig tests * refactored init function * refactored to remove a function and reduce number of iterations of submodules and configs * add logic to pass config value obj data to adapter, also a small amount of refactoring/formatting cleanup * added configuration examples to markdown file * add add request bid hook to the initSubmodules function * added requestBidBook in preparation to test mock setup/configuration. add test for one storage type active with only one module configured to use that type * refactored requestBidHook with dependency injection for unit testing * had to revert revision to use dependency injection in the requestBidHook due to necessary use of prebid global object affecting following tests * created initial file for integration example * updated integration using brett's test page. * updated extendedBidRequestData to be a function expression, which allows watching the first element added to add the bid request hook * removed redundant constant for enabled submodules within init submodules * added retrieve storage value and logic to call submodule.getId if stored value does not exist * added submodule getId fallback when storage value does not exist * extended addUnit bid requests with universalId data, add logging for invalid config storage type, revised commenting * add logic to set storage and pass decoded data in getId response handler * updated initModules unit test mock data to fix broken tests from previous module additions/updates * updated comments for consistency * fixed module description comment * add overrideId interface and implementation to the pubCommonId submodule * fix to only check for override method value if submodule has a configKey set in the config * added unit test for submodule override method implementation * completed the pubCommonId submodule getId implementation; changed pubCommonId submodule default expires value to today + 8 years * changed openId submodule default expires value to today + 8 years; added final todo comments, pertaining to openId submodule decode and getId methods * fixed formatting to correct linting errors during building * update jsdoc comments for IdSubmodule * added jsdoc comments for overrideId submodule interface method * changed the overrideId return value conditional to require a valid object, added a todo note to investigate using separate instance callbacks to handle multiple timers for syncDelay/auctionDelay * add ajax request to openId submodule getId, awaiting values for request params and response structure and format for storage and structure for adding to bid requests * updated openId submodule getId error logging and callback handling * fix obj path access for syncDelay, updated example file with pubCommonId configured * fix for broken unit tests resulting from update of overrideId addition to submodule interface * replace use of built-in array find method, with import of 'core-js/library/fn/array/find', fixes/updates for integration example for module * refactored config handling in initSubmodules to accept a plain js object opposed to a prebid Config object (this simplifies testing setup) * created init method to wrap initSubmodules with config * refactored module's config to watch/handle changes * removed overrideId submodule interface, change openId to unifiedId * update getId and decode uid data structure also updated integration example * updated object structure for universal ids that is added to bid request, add universalID object handling to rubiconBidAdapter * updated markdown example configuration * fix for syncDelay, added auction end listener before setting syncDelay timer * update to prepare universalID object if adUnits exists * add gdpr consent data to request bids hook, warn on not found, info if found * add test for valid gdpr consent string, exits universal id module on fail * update gdpr consent to check gdprApplies, add cmp code to integration example. update init to use dependency injection * implemented test for gdpr consent to store locally (purpose #1) * added consentString decode to check for purpose #1 (user consents to have data stored locally) * fix initSubmodule function arguments for changed signature * changed submodule getId method signature to pass a consentData argument * tests update with dependency container * update spec to un-comment disabled expect statement * in-progress DI conversion * update to fix test missing dependency for utils * removed getIdCallbackHandler function because it was inlined within initSubmodules. refactored dependencyContainer argument names to dependencies * add unit test case for configurations that define invalid storage.type values (only cookie or html5 are valid) * fixes for html5 storage in module and unit tests. temp comment-out for gdpr test in requestBid hook as it's being refactored into getId submodule methods * fixes for html5 storage in module and unit tests. temp comment-out for gdpr test in requestBid hook as it's being refactored into getId submodule methods * added opt_out cookie logic to init * in-progress commit to update getId method signature with initialized consentManagement data * changed priority to consent management module's value + 1 * updated both submodule getId functions with consent data handling. * update hasGDPRConsent to remove unnecessary test for consentData obj since it's tested outside of function, removed utils from dependency injection * update to move local declarations outside if block, added local var for log prefix since it was accessed more than twice * changed log prefix to build the string locally instead of passing through getIdData obj * bug fix for request bid hook priority race condition * removed consentData prop from init dependencies obj, updated jsdoc comments removing consentData prop * removed consentData prop from init arguments * update integration example to test gdpr cmpApi type of 'static' * refactor to combine request bid hooks into single hook, also other opts and formatting changes * additions/updates to logging, additions/updates to jsdoc comments, various refactoring and formatting updates * fixed how GDPR purpose 1 permission is checked, removed decode function and read from consentData.vendorConsents.purposeConsents[1] (key value 1 is for "purpose 1") * fix for hasGDPRConsent functions, changed object prop accessor name from 'consentData.vendorConsent' to 'consentData.vendorData' * small changes to log messages and code formatting * changed submodule property configKey to configName for consistency with the submodule config property name * updated logging message text and small format change * updated jsdoc comment to reduce line length * formatting fix and jsdoc update * reverted changes to support universal id in rubiconBidAdapter, will open a separate PR for the adapter code changes. * added logging messages to catch statements * fix unit tests using the document cookie * fix to extra module name in log message * changed function return type array to undefined on invalid config * moved encodeURIComponenent and decodeURIComponenent into setCookie and getCookie * refactor to resolve issues creating certain unit tests * add tests for config variations, small fixes for issues found writing tests * removed debug console.log statements * removed set initializedSubmodules value in init * fix to remove test cookie from spec, updated example with submodule config value object * added tests checking that config submodule props create correct number of submodules * added test for syncDelay config update * fixes for LGTM and imports for src are now relative * formatting fix semicolon * test reverted to debug circleci failure * changed request bids hook priority to load after consentManagement * test to resolve circle ci errors * test to resolve circle ci errors * fixed name camel case error * changed unifiedid decode test property name from pubcid to ttid * add universal id support to pbs bid adapter * moved universal id pbs adapter support from this branch to it's own branch pbs-adapter-universal-id-support * reverted pbs adapter removal * always add ext.prebid.targeting.includewinners: true for openrtb * removed unnecessary code * renamed * more renaming * rename comment * bugfixes and code removal * reverted changes * renamed * fix * formatting update * bugfix for syncDelay in bidHook * fix syncDelay === 0 * revisions from review with e.harper * fix for storing unifiedid obj in local storage * bug fix for expires days conversion * changed default syncDelay * removed comment example since it's in the markdown file * added/updated comments * tiny update to logic adding data to bids * removed commented code * formatting adjusted for consistency and comments added/updated * bugfix changed conditional to use and instead of or * optimization code removal * updated bidRequestHook to reflect changes made in hooks.js, ect * fixes for unit tests * added more unit tests as well as small fixes for tests * fixed import path * removed unused import and sinon sandbox * remove exports for unnecessary objects * fix for circleci tests * fix for util.setCookie exp format * renamed module name references to User ID * removed test for cookies enabled around the opt out, since the cookie will not be returned if not enabled. comments mentioning local storage updated with 'and cookies' * add try catch around pubcommonid external function call, removed unused code, updated docs with other configuration examples * fix for pub common id getId try catch * Add microadBidAdapter * change unified id to require either a url or partner config param * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * updating example pubcid * added support to opt-out with _pubcid_optout * clear _pubcid_optout before tests * disabled test that keeps timing out on circleci * added logic for optout set in html5 local storage * update fix conditional typeo * removed skip on userId test * added async done function call for failed circleci test * update done called in bidsBackHandler in failed circleci test * fix for lint error missing space after property name * removed test that passes locally but fails with a timeout exceeded error on cirlceci for the Safari Browsers --- integrationExamples/gpt/userId_example.html | 212 ++++++++++ modules/userId.js | 429 ++++++++++++++++++++ modules/userId.md | 72 ++++ src/utils.js | 16 + test/spec/modules/userId_spec.js | 396 ++++++++++++++++++ 5 files changed, 1125 insertions(+) create mode 100644 integrationExamples/gpt/userId_example.html create mode 100644 modules/userId.js create mode 100644 modules/userId.md create mode 100644 test/spec/modules/userId_spec.js diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html new file mode 100644 index 00000000000..d64e22e44c7 --- /dev/null +++ b/integrationExamples/gpt/userId_example.html @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + +

Rubicon Project Prebid

+ +
+ +
+ + diff --git a/modules/userId.js b/modules/userId.js new file mode 100644 index 00000000000..bddada7ffbc --- /dev/null +++ b/modules/userId.js @@ -0,0 +1,429 @@ +/** + * This module adds User ID support to prebid.js + */ +import {ajax} from '../src/ajax.js'; +import {config} from '../src/config.js'; +import events from '../src/events.js'; +import * as utils from '../src/utils.js'; +import find from 'core-js/library/fn/array/find'; +import {gdprDataHandler} from '../src/adapterManager.js'; + +const CONSTANTS = require('../src/constants.json'); + +/** + * @typedef {Object} SubmoduleConfig + * @property {string} name - the User ID submodule name + * @property {SubmoduleStorage} storage - browser storage config + * @property {SubmoduleParams} params - params config for use by the submodule.getId function + * @property {Object} value - all object properties will be appended to the User ID bid data + */ + +/** + * @typedef {Object} SubmoduleStorage + * @property {string} type - browser storage type (html5 or cookie) + * @property {string} name - key name to use when saving/reading to local storage or cookies + * @property {number} expires - time to live for browser cookie + */ + +/** + * @typedef {Object} SubmoduleParams + * @property {string} partner - partner url param value + * @property {string} url - webservice request url used to load Id data + */ + +/** + * @typedef {Object} Submodule + * @property {string} name - submodule and config have matching name prop + * @property {decode} decode - decode a stored value for passing to bid requests + * @property {getId} getId - performs action to obtain id and return a value in the callback's response argument + */ + +/** + * @callback getId + * @param {SubmoduleParams} [submoduleConfigParams] + * @param {Object} [consentData] + * @returns {(Function|Object|string)} + */ + +/** + * @callback decode + * @param {Object|string} idData + * @returns {Object} + */ + +/** + * @typedef {Object} SubmoduleContainer + * @property {Submodule} submodule + * @property {SubmoduleConfig} submoduleConfig + * @property {Object} idObj - decoded User ID data that will be appended to bids + * @property {function} callback + */ + +const MODULE_NAME = 'User ID'; +const COOKIE = 'cookie'; +const LOCAL_STORAGE = 'html5'; +const DEFAULT_SYNC_DELAY = 500; + +// @type {number} delay after auction to make webrequests for id data +export let syncDelay; + +// @type {SubmoduleContainer[]} +export let submodules; + +// @type {SubmoduleContainer[]} +let initializedSubmodules; + +// @type {Submodule} +export const unifiedIdSubmodule = { + name: 'unifiedId', + decode(value) { + return (value && typeof value['TDID'] === 'string') ? { 'tdid': value['TDID'] } : undefined; + }, + getId(submoduleConfigParams, consentData) { + if (!submoduleConfigParams || (typeof submoduleConfigParams.partner !== 'string' && typeof submoduleConfigParams.url !== 'string')) { + utils.logError(`${MODULE_NAME} - unifiedId submodule requires either partner or url to be defined`); + return; + } + const url = submoduleConfigParams.url || `http://match.adsrvr.org/track/rid?ttd_pid=${submoduleConfigParams.partner}&fmt=json`; + + return function (callback) { + ajax(url, response => { + let responseObj; + if (response) { + try { + responseObj = JSON.parse(response); + } catch (error) { + utils.logError(error); + } + } + callback(responseObj); + }, undefined, { method: 'GET' }); + } + } +}; + +// @type {Submodule} +export const pubCommonIdSubmodule = { + name: 'pubCommonId', + decode(value) { + return { + 'pubcid': value + } + }, + getId() { + // If the page includes its own pubcid object, then use that instead. + let pubcid; + try { + if (typeof window['PublisherCommonId'] === 'object') { + pubcid = window['PublisherCommonId'].getId(); + } + } catch (e) {} + // check pubcid and return if valid was otherwise create a new id + return (pubcid) || utils.generateUUID(); + } +}; + +/** + * @param {SubmoduleStorage} storage + * @param {string} value + * @param {number|string} expires + */ +export function setStoredValue(storage, value, expires) { + try { + const valueStr = (typeof value === 'object') ? JSON.stringify(value) : value; + const expiresStr = (new Date(Date.now() + (expires * (60 * 60 * 24 * 1000)))).toUTCString(); + + if (storage.type === COOKIE) { + utils.setCookie(storage.name, valueStr, expiresStr); + } else if (storage.type === LOCAL_STORAGE) { + localStorage.setItem(`${storage.name}_exp`, expiresStr); + localStorage.setItem(storage.name, encodeURIComponent(valueStr)); + } + } catch (error) { + utils.logError(error); + } +} + +/** + * @param {SubmoduleStorage} storage + * @returns {string} + */ +export function getStoredValue(storage) { + let storedValue; + try { + if (storage.type === COOKIE) { + storedValue = utils.getCookie(storage.name); + } else if (storage.type === LOCAL_STORAGE) { + const storedValueExp = localStorage.getItem(`${storage.name}_exp`); + // empty string means no expiration set + if (storedValueExp === '') { + storedValue = localStorage.getItem(storage.name); + } else if (storedValueExp) { + if ((new Date(storedValueExp)).getTime() - Date.now() > 0) { + storedValue = decodeURIComponent(localStorage.getItem(storage.name)); + } + } + } + // we support storing either a string or a stringified object, + // so we test if the string contains an stringified object, and if so convert to an object + if (typeof storedValue === 'string' && storedValue.charAt(0) === '{') { + storedValue = JSON.parse(storedValue); + } + } catch (e) { + utils.logError(e); + } + return storedValue; +} + +/** + * test if consent module is present, applies, and is valid for local storage or cookies (purpose 1) + * @param {Object} consentData + * @returns {boolean} + */ +export function hasGDPRConsent(consentData) { + if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) { + if (!consentData.consentString) { + return false; + } + if (consentData.vendorData && consentData.vendorData.purposeConsents && consentData.vendorData.purposeConsents['1'] === false) { + return false; + } + } + return true; +} + +/** + * @param {Object[]} submodules + */ +export function processSubmoduleCallbacks(submodules) { + submodules.forEach(function(submodule) { + submodule.callback(function callbackCompleted (idObj) { + // clear callback, this prop is used to test if all submodule callbacks are complete below + submodule.callback = undefined; + + // if valid, id data should be saved to cookie/html storage + if (idObj) { + setStoredValue(submodule.config.storage, idObj, submodule.config.storage.expires); + + // cache decoded value (this is copied to every adUnit bid) + submodule.idObj = submodule.submodule.decode(idObj); + } else { + utils.logError(`${MODULE_NAME}: ${submodule.submodule.name} - request id responded with an empty value`); + } + }); + }); +} + +/** + * @param {Object[]} adUnits + * @param {Object[]} submodules + */ +export function addIdDataToAdUnitBids(adUnits, submodules) { + const submodulesWithIds = submodules.filter(item => typeof item.idObj === 'object' && item.idObj !== null); + if (submodulesWithIds.length) { + if (adUnits) { + adUnits.forEach(adUnit => { + adUnit.bids.forEach(bid => { + // append the User ID property to bid + bid.userId = submodulesWithIds.reduce((carry, item) => { + Object.keys(item.idObj).forEach(key => { + carry[key] = item.idObj[key]; + }); + return carry; + }, {}); + }); + }); + } + } +} + +/** + * 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. + * The two main actions handled by the hook are: + * 1. check gdpr consentData and handle submodule initialization. + * 2. append user id data (loaded from cookied/html or from the getId method) to bids to be accessed in adapters. + * @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) { + // initialize submodules only when undefined + if (typeof initializedSubmodules === 'undefined') { + initializedSubmodules = initSubmodules(submodules, gdprDataHandler.getConsentData()); + if (initializedSubmodules.length) { + // list of sumodules that have callbacks that need to be executed + const submodulesWithCallbacks = initializedSubmodules.filter(item => typeof item.callback === 'function'); + + if (submodulesWithCallbacks.length) { + // 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 dealy process with a setTimeout + if (syncDelay > 0) { + setTimeout(function() { + processSubmoduleCallbacks(submodulesWithCallbacks); + }, syncDelay); + } else { + processSubmoduleCallbacks(submodulesWithCallbacks); + } + }); + } + } + } + + // pass available user id data to bid adapters + addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || $$PREBID_GLOBAL$$.adUnits, initializedSubmodules); + + // calling fn allows prebid to continue processing + return fn.call(this, reqBidsConfigObj); +} + +/** + * @param {Object[]} submodules + * @param {Object} consentData + * @returns {string[]} initialized submodules + */ +export function initSubmodules(submodules, consentData) { + // gdpr consent with purpose one is required, otherwise exit immediately + if (!hasGDPRConsent(consentData)) { + utils.logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`); + return []; + } + return submodules.reduce((carry, item) => { + // There are two submodule configuration types to handle: storage or value + // 1. storage: retrieve user id data from cookie/html storage or with the submodule's getId method + // 2. value: pass directly to bids + if (item.config && item.config.storage) { + const storedId = getStoredValue(item.config.storage); + if (storedId) { + // cache decoded value (this is copied to every adUnit bid) + item.idObj = item.submodule.decode(storedId); + } else { + // getId will return user id data or a function that will load the data + const getIdResult = item.submodule.getId(item.config.params, consentData); + + // If the getId result has a type of function, it is asynchronous and cannot be called until later + if (typeof getIdResult === 'function') { + item.callback = getIdResult; + } else { + // A getId result that is not a function is assumed to be valid user id data, which should be saved to users local storage or cookies + setStoredValue(item.config.storage, getIdResult, item.config.storage.expires); + + // cache decoded value (this is copied to every adUnit bid) + item.idObj = item.submodule.decode(getIdResult); + } + } + } else if (item.config.value) { + // cache decoded value (this is copied to every adUnit bid) + item.idObj = item.config.value; + } + + carry.push(item); + return carry; + }, []); +} + +/** + * list of submodule configurations with valid 'storage' or 'value' obj definitions + * * storage config: contains values for storing/retrieving User ID data in browser storage + * * value config: object properties that are copied to bids (without saving to storage) + * @param {SubmoduleConfig[]} submoduleConfigs + * @param {Submodule[]} enabledSubmodules + * @returns {SubmoduleConfig[]} + */ +export function getValidSubmoduleConfigs(submoduleConfigs, enabledSubmodules) { + if (!Array.isArray(submoduleConfigs)) { + return []; + } + + // list of browser enabled storage types + const validStorageTypes = []; + if (utils.localStorageIsEnabled()) { + // check if optout exists in local storage (null if returned if key does not exist) + if (!localStorage.getItem('_pbjs_id_optout') && !localStorage.getItem('_pubcid_optout')) { + validStorageTypes.push(LOCAL_STORAGE); + } else { + utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); + } + } + if (utils.cookiesAreEnabled()) { + validStorageTypes.push(COOKIE); + } + + return submoduleConfigs.reduce((carry, submoduleConfig) => { + // every submodule config obj must contain a valid 'name' + if (!submoduleConfig || typeof submoduleConfig.name !== 'string' || !submoduleConfig.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 (submoduleConfig.storage && + typeof submoduleConfig.storage.type === 'string' && submoduleConfig.storage.type && + typeof submoduleConfig.storage.name === 'string' && submoduleConfig.storage.name && + validStorageTypes.indexOf(submoduleConfig.storage.type) !== -1) { + carry.push(submoduleConfig); + } else if (submoduleConfig.value !== null && typeof submoduleConfig.value === 'object') { + // Validate value config + // must be valid object with at least one property + carry.push(submoduleConfig); + } + return carry; + }, []); +} + +/** + * @param config + * @param {Submodule[]} enabledSubmodules + */ +export function init (config, enabledSubmodules) { + submodules = []; + initializedSubmodules = undefined; + + // exit immediately if opt out cookie exists. _pubcid_optout is checked for compatiblility with pubCommonId module opt out + if (utils.getCookie('_pbjs_id_optout')) { + utils.logInfo(`${MODULE_NAME} - opt-out cookie found, exit module`); + return; + } + + // listen for config userSyncs to be set + config.getConfig('usersync', ({usersync}) => { + if (usersync) { + syncDelay = (typeof usersync.syncDelay !== 'undefined') ? usersync.syncDelay : DEFAULT_SYNC_DELAY; + + // filter any invalid configs out + const submoduleConfigs = getValidSubmoduleConfigs(usersync.userIds, enabledSubmodules); + if (submoduleConfigs.length === 0) { + // exit module, if no valid configurations exist + return; + } + + // get list of submodules with valid configurations + submodules = enabledSubmodules.reduce((carry, enabledSubmodule) => { + // try to find submodule configuration for submodule, if config exists it should be enabled + const submoduleConfig = find(submoduleConfigs, item => item.name === enabledSubmodule.name); + + if (submoduleConfig) { + // append {SubmoduleContainer} containing the submodule and config + carry.push({ + submodule: enabledSubmodule, + config: submoduleConfig, + idObj: undefined + }); + } + return carry; + }, []); + + // complete initialization if any submodules exist + if (submodules.length) { + // priority has been set so it loads after consentManagement (which has a priority of 50) + $$PREBID_GLOBAL$$.requestBids.before(requestBidsHook, 40); + utils.logInfo(`${MODULE_NAME} - usersync config updated for ${submodules.length} submodules`); + } + } + }); +} + +init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); diff --git a/modules/userId.md b/modules/userId.md new file mode 100644 index 00000000000..a873a76674f --- /dev/null +++ b/modules/userId.md @@ -0,0 +1,72 @@ +## User ID Example Configuration + +Example showing `cookie` storage for user id data for both submodules +``` +pbjs.setConfig({ + usersync: { + userIds: [{ + name: "unifiedId", + params: { + partner: "prebid", + url: "http://match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" + }, + storage: { + type: "cookie", + name: "unifiedid", + expires: 60 + } + }, { + name: "pubCommonId", + storage: { + type: "cookie", + name: "_pubcid", + expires: 60 + } + }], + syncDelay: 5000 + } +}); +``` + +Example showing `localStorage` for user id data for both submodules +``` +pbjs.setConfig({ + usersync: { + userIds: [{ + name: "unifiedId", + params: { + partner: "prebid", + url: "http://match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" + }, + storage: { + type: "html5", + name: "unifiedid", + expires: 60 + } + }, { + name: "pubCommonId", + storage: { + type: "html5", + name: "pubcid", + expires: 60 + } + }], + syncDelay: 5000 + } +}); +``` + +Example showing how to configure a `value` object to pass directly to bid adapters +``` +pbjs.setConfig({ + usersync: { + userIds: [{ + name: "pubCommonId", + value: { + "providedPubCommonId": "1234567890" + } + }], + syncDelay: 5000 + } +}); +``` diff --git a/src/utils.js b/src/utils.js index f8ac56bb6a1..ea80e970786 100644 --- a/src/utils.js +++ b/src/utils.js @@ -911,6 +911,22 @@ export function getCookie(name) { return m ? decodeURIComponent(m[2]) : null; } +export function setCookie(key, value, expires) { + document.cookie = `${key}=${encodeURIComponent(value)}${(expires !== '') ? `; expires=${expires}` : ''}; path=/`; +} + +/** + * @returns {boolean} + */ +export function localStorageIsEnabled () { + try { + localStorage.setItem('prebid.cookieTest', '1'); + return localStorage.getItem('prebid.cookieTest') === '1'; + } catch (error) { + return false; + } +} + /** * Given a function, return a function which only executes the original after * it's been called numRequiredCalls times. diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js new file mode 100644 index 00000000000..6acab4d2b6c --- /dev/null +++ b/test/spec/modules/userId_spec.js @@ -0,0 +1,396 @@ +import { + init, + syncDelay, + submodules, + pubCommonIdSubmodule, + unifiedIdSubmodule, + requestBidsHook +} from 'modules/userId'; +import {config} from 'src/config'; +import * as utils from 'src/utils'; +import * as auctionModule from 'src/auction'; +import {getAdUnits} from 'test/fixtures/fixtures'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +let assert = require('chai').assert; +let expect = require('chai').expect; + +describe('User ID', function() { + const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; + + function createStorageConfig(name = 'pubCommonId', key = 'pubcid', type = 'cookie', expires = 30) { + return { name: name, storage: { name: key, type: type, expires: expires } } + } + + before(function() { + utils.setCookie('_pubcid_optout', '', EXPIRED_COOKIE_DATE); + }); + + describe('Decorate Ad Units', function() { + beforeEach(function() { + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('pubcid_alt', 'altpubcid200000', (new Date(Date.now() + 5000).toUTCString())); + }); + + afterEach(function () { + $$PREBID_GLOBAL$$.requestBids.removeAll(); + config.resetConfig(); + }); + + after(function() { + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('pubcid_alt', '', EXPIRED_COOKIE_DATE); + }); + + it('Check same cookie behavior', function () { + let adUnits1 = getAdUnits(); + let adUnits2 = getAdUnits(); + let innerAdUnits1; + let innerAdUnits2; + + let pubcid = utils.getCookie('pubcid'); + expect(pubcid).to.be.null; // there should be no cookie initially + + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + + requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); + pubcid = utils.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); + }); + }); + + requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); + assert.deepEqual(innerAdUnits1, innerAdUnits2); + }); + + it('Check different cookies', function () { + let adUnits1 = getAdUnits(); + let adUnits2 = getAdUnits(); + let innerAdUnits1; + let innerAdUnits2; + let pubcid1; + let pubcid2; + + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); + pubcid1 = utils.getCookie('pubcid'); // get first cookie + utils.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); + }); + }); + + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); + + pubcid2 = utils.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(pubcid1).to.not.equal(pubcid2); + }); + + it('Check new cookie', function () { + let adUnits = getAdUnits(); + let innerAdUnits; + + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ + usersync: { + syncDelay: 0, + userIds: [createStorageConfig('pubCommonId', 'pubcid_alt', 'cookie')]} + }); + requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal('altpubcid200000'); + }); + }); + }); + }); + + describe('Opt out', function () { + before(function () { + utils.setCookie('_pbjs_id_optout', '1', (new Date(Date.now() + 5000).toUTCString())); + }); + + beforeEach(function () { + sinon.stub(utils, 'logInfo'); + }); + + afterEach(function () { + // removed cookie + utils.setCookie('_pbjs_id_optout', '', EXPIRED_COOKIE_DATE); + $$PREBID_GLOBAL$$.requestBids.removeAll(); + utils.logInfo.restore(); + config.resetConfig(); + }); + + after(function () { + utils.setCookie('_pbjs_id_optout', '', EXPIRED_COOKIE_DATE); + }); + + it('fails initialization if opt out cookie exists', function () { + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + 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, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); + }); + }); + + describe('Handle variations of config values', function () { + beforeEach(function () { + sinon.stub(utils, 'logInfo'); + }); + + afterEach(function () { + $$PREBID_GLOBAL$$.requestBids.removeAll(); + utils.logInfo.restore(); + config.resetConfig(); + }); + + it('handles config with no usersync object', function () { + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + 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 () { + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ usersync: {} }); + expect(typeof utils.logInfo.args[0]).to.equal('undefined'); + }); + + it('handles config with usersync and userIds that are empty objs', function () { + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ + usersync: { + userIds: [{}] + } + }); + expect(typeof utils.logInfo.args[0]).to.equal('undefined'); + }); + + it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () { + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ + usersync: { + userIds: [{ + name: '', + value: { test: '1' } + }, { + name: 'foo', + value: { test: '1' } + }] + } + }); + expect(typeof utils.logInfo.args[0]).to.equal('undefined'); + }); + + it('config with 1 configurations should create 1 submodules', function () { + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ + usersync: { + syncDelay: 0, + userIds: [{ + name: 'unifiedId', + storage: { name: 'unifiedid', type: 'cookie' } + }] + } + }); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); + }); + + it('config with 2 configurations should result in 2 submodules add', function () { + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ + usersync: { + syncDelay: 0, + userIds: [{ + name: 'pubCommonId', value: {'pubcid': '11111'} + }, { + name: 'unifiedId', + storage: { name: 'unifiedid', type: 'cookie' } + }] + } + }); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 2 submodules'); + }); + + it('config syncDelay updates module correctly', function () { + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + config.setConfig({ + usersync: { + syncDelay: 99, + userIds: [{ + name: 'unifiedId', + storage: { name: 'unifiedid', type: 'cookie' } + }] + } + }); + expect(syncDelay).to.equal(99); + }); + }); + + describe('Invoking requestBid', function () { + let storageResetCount = 0; + let createAuctionStub; + let adUnits; + let adUnitCodes; + let sampleSpec = { + code: 'sampleBidder', + isBidRequestValid: () => {}, + buildRequest: (reqs) => {}, + interpretResponse: () => {}, + getUserSyncs: () => {} + }; + + beforeEach(function () { + // simulate existing browser cookie values + utils.setCookie('pubcid', `testpubcid${storageResetCount}`, (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('unifiedid', JSON.stringify({ + 'TDID': `testunifiedid${storageResetCount}` + }), (new Date(Date.now() + 5000).toUTCString())); + + // simulate existing browser local storage values + localStorage.setItem('unifiedid_alt', JSON.stringify({ + 'TDID': `testunifiedid_alt${storageResetCount}` + })); + localStorage.setItem('unifiedid_alt_exp', ''); + + adUnits = [{ + code: 'adUnit-code', + mediaTypes: { + banner: {}, + native: {}, + }, + sizes: [[300, 200], [300, 600]], + bids: [ + {bidder: 'sampleBidder', params: {placementId: 'banner-only-bidder'}} + ] + }]; + adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 1999}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + + registerBidder(sampleSpec); + }); + + afterEach(function () { + storageResetCount++; + + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + localStorage.removeItem('unifiedid_alt'); + localStorage.removeItem('unifiedid_alt_exp'); + auctionModule.newAuction.restore(); + $$PREBID_GLOBAL$$.requestBids.removeAll(); + config.resetConfig(); + }); + + it('test hook from pubcommonid cookie', function() { + config.setConfig({ + usersync: { + syncDelay: 0, + userIds: [createStorageConfig('pubCommonId', 'pubcid', 'cookie')] + } + }); + + $$PREBID_GLOBAL$$.requestBids({adUnits}); + + adUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal(`testpubcid${storageResetCount}`); + }); + }); + }); + + it('test hook from pubcommonid config value object', function() { + config.setConfig({ + usersync: { + syncDelay: 0, + userIds: [{ + name: 'pubCommonId', + value: {'pubcidvalue': 'testpubcidvalue'} + }]} + }); + + $$PREBID_GLOBAL$$.requestBids({adUnits}); + + adUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.pubcidvalue'); + expect(bid.userId.pubcidvalue).to.equal('testpubcidvalue'); + }); + }); + }); + + it('test hook from pubcommonid html5', function() { + config.setConfig({ + usersync: { + syncDelay: 0, + userIds: [createStorageConfig('unifiedId', 'unifiedid_alt', 'html5')]} + }); + + $$PREBID_GLOBAL$$.requestBids({adUnits}); + + adUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.tdid'); + expect(bid.userId.tdid).to.equal(`testunifiedid_alt${storageResetCount}`); + }); + }); + }); + + it('test hook when both pubCommonId and unifiedId have data to pass', function() { + config.setConfig({ + usersync: { + syncDelay: 0, + userIds: [ + createStorageConfig('pubCommonId', 'pubcid', 'cookie'), + createStorageConfig('unifiedId', 'unifiedid', 'cookie') + ]} + }); + + $$PREBID_GLOBAL$$.requestBids({adUnits}); + + 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${storageResetCount}`); + + // 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(`testunifiedid${storageResetCount}`); + }); + }); + }); + }); +}); From edbe587dc8652b9584d719a0860e7f17c719acf0 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Thu, 4 Apr 2019 14:53:52 -0700 Subject: [PATCH 1131/1594] Rubicon Adapter - support User ID module (#3531) * add initial files * add local storage and cookie browser support functions * added additional test cases for functions related to local storage and cookie browser support * added validate config function and first unit test * add validate config test * updated local storage key value to match change to requirements/spec * updated submodule config key names to match requirements/spec * added TODO with validation logic breakdown as well as a question on how to handle both 'value' and 'storage' existing in config * add TODO addressing use-case: Publisher has integrated with OpenID on their own * fixed comment * rearranged unit tests for config functions to be grouped correctly * added logic to valid that a submodule contains a config with a value or storage obj * removed sinon mock of config.getConfig, replaced with obj literal definition in function arguments * additional use cases added to validateConfig tests * refactored init function * refactored to remove a function and reduce number of iterations of submodules and configs * add logic to pass config value obj data to adapter, also a small amount of refactoring/formatting cleanup * added configuration examples to markdown file * add add request bid hook to the initSubmodules function * added requestBidBook in preparation to test mock setup/configuration. add test for one storage type active with only one module configured to use that type * refactored requestBidHook with dependency injection for unit testing * had to revert revision to use dependency injection in the requestBidHook due to necessary use of prebid global object affecting following tests * created initial file for integration example * updated integration using brett's test page. * updated extendedBidRequestData to be a function expression, which allows watching the first element added to add the bid request hook * removed redundant constant for enabled submodules within init submodules * added retrieve storage value and logic to call submodule.getId if stored value does not exist * added submodule getId fallback when storage value does not exist * extended addUnit bid requests with universalId data, add logging for invalid config storage type, revised commenting * add logic to set storage and pass decoded data in getId response handler * updated initModules unit test mock data to fix broken tests from previous module additions/updates * updated comments for consistency * fixed module description comment * add overrideId interface and implementation to the pubCommonId submodule * fix to only check for override method value if submodule has a configKey set in the config * added unit test for submodule override method implementation * completed the pubCommonId submodule getId implementation; changed pubCommonId submodule default expires value to today + 8 years * changed openId submodule default expires value to today + 8 years; added final todo comments, pertaining to openId submodule decode and getId methods * fixed formatting to correct linting errors during building * update jsdoc comments for IdSubmodule * added jsdoc comments for overrideId submodule interface method * changed the overrideId return value conditional to require a valid object, added a todo note to investigate using separate instance callbacks to handle multiple timers for syncDelay/auctionDelay * add ajax request to openId submodule getId, awaiting values for request params and response structure and format for storage and structure for adding to bid requests * updated openId submodule getId error logging and callback handling * fix obj path access for syncDelay, updated example file with pubCommonId configured * fix for broken unit tests resulting from update of overrideId addition to submodule interface * replace use of built-in array find method, with import of 'core-js/library/fn/array/find', fixes/updates for integration example for module * refactored config handling in initSubmodules to accept a plain js object opposed to a prebid Config object (this simplifies testing setup) * created init method to wrap initSubmodules with config * refactored module's config to watch/handle changes * removed overrideId submodule interface, change openId to unifiedId * update getId and decode uid data structure also updated integration example * updated object structure for universal ids that is added to bid request, add universalID object handling to rubiconBidAdapter * updated markdown example configuration * fix for syncDelay, added auction end listener before setting syncDelay timer * update to prepare universalID object if adUnits exists * add gdpr consent data to request bids hook, warn on not found, info if found * add test for valid gdpr consent string, exits universal id module on fail * update gdpr consent to check gdprApplies, add cmp code to integration example. update init to use dependency injection * implemented test for gdpr consent to store locally (purpose #1) * added consentString decode to check for purpose #1 (user consents to have data stored locally) * fix initSubmodule function arguments for changed signature * changed submodule getId method signature to pass a consentData argument * tests update with dependency container * update spec to un-comment disabled expect statement * in-progress DI conversion * update to fix test missing dependency for utils * removed getIdCallbackHandler function because it was inlined within initSubmodules. refactored dependencyContainer argument names to dependencies * add unit test case for configurations that define invalid storage.type values (only cookie or html5 are valid) * fixes for html5 storage in module and unit tests. temp comment-out for gdpr test in requestBid hook as it's being refactored into getId submodule methods * fixes for html5 storage in module and unit tests. temp comment-out for gdpr test in requestBid hook as it's being refactored into getId submodule methods * added opt_out cookie logic to init * in-progress commit to update getId method signature with initialized consentManagement data * changed priority to consent management module's value + 1 * updated both submodule getId functions with consent data handling. * update hasGDPRConsent to remove unnecessary test for consentData obj since it's tested outside of function, removed utils from dependency injection * update to move local declarations outside if block, added local var for log prefix since it was accessed more than twice * changed log prefix to build the string locally instead of passing through getIdData obj * bug fix for request bid hook priority race condition * removed consentData prop from init dependencies obj, updated jsdoc comments removing consentData prop * removed consentData prop from init arguments * update integration example to test gdpr cmpApi type of 'static' * refactor to combine request bid hooks into single hook, also other opts and formatting changes * additions/updates to logging, additions/updates to jsdoc comments, various refactoring and formatting updates * fixed how GDPR purpose 1 permission is checked, removed decode function and read from consentData.vendorConsents.purposeConsents[1] (key value 1 is for "purpose 1") * fix for hasGDPRConsent functions, changed object prop accessor name from 'consentData.vendorConsent' to 'consentData.vendorData' * small changes to log messages and code formatting * changed submodule property configKey to configName for consistency with the submodule config property name * updated logging message text and small format change * updated jsdoc comment to reduce line length * formatting fix and jsdoc update * reverted changes to support universal id in rubiconBidAdapter, will open a separate PR for the adapter code changes. * added logging messages to catch statements * fix unit tests using the document cookie * fix to extra module name in log message * changed function return type array to undefined on invalid config * moved encodeURIComponenent and decodeURIComponenent into setCookie and getCookie * refactor to resolve issues creating certain unit tests * add tests for config variations, small fixes for issues found writing tests * removed debug console.log statements * removed set initializedSubmodules value in init * fix to remove test cookie from spec, updated example with submodule config value object * added tests checking that config submodule props create correct number of submodules * added test for syncDelay config update * fixes for LGTM and imports for src are now relative * formatting fix semicolon * test reverted to debug circleci failure * changed request bids hook priority to load after consentManagement * test to resolve circle ci errors * test to resolve circle ci errors * fixed name camel case error * changed unifiedid decode test property name from pubcid to ttid * added universal id support to bid adapter * added unit test for universal id support in bid adapter * optimized last unit test added * add initial files * add local storage and cookie browser support functions * added additional test cases for functions related to local storage and cookie browser support * added validate config function and first unit test * add validate config test * updated local storage key value to match change to requirements/spec * updated submodule config key names to match requirements/spec * added TODO with validation logic breakdown as well as a question on how to handle both 'value' and 'storage' existing in config * add TODO addressing use-case: Publisher has integrated with OpenID on their own * fixed comment * rearranged unit tests for config functions to be grouped correctly * added logic to valid that a submodule contains a config with a value or storage obj * removed sinon mock of config.getConfig, replaced with obj literal definition in function arguments * additional use cases added to validateConfig tests * refactored init function * refactored to remove a function and reduce number of iterations of submodules and configs * add logic to pass config value obj data to adapter, also a small amount of refactoring/formatting cleanup * added configuration examples to markdown file * add add request bid hook to the initSubmodules function * added requestBidBook in preparation to test mock setup/configuration. add test for one storage type active with only one module configured to use that type * refactored requestBidHook with dependency injection for unit testing * had to revert revision to use dependency injection in the requestBidHook due to necessary use of prebid global object affecting following tests * created initial file for integration example * updated integration using brett's test page. * updated extendedBidRequestData to be a function expression, which allows watching the first element added to add the bid request hook * removed redundant constant for enabled submodules within init submodules * added retrieve storage value and logic to call submodule.getId if stored value does not exist * added submodule getId fallback when storage value does not exist * extended addUnit bid requests with universalId data, add logging for invalid config storage type, revised commenting * add logic to set storage and pass decoded data in getId response handler * updated initModules unit test mock data to fix broken tests from previous module additions/updates * updated comments for consistency * fixed module description comment * add overrideId interface and implementation to the pubCommonId submodule * fix to only check for override method value if submodule has a configKey set in the config * added unit test for submodule override method implementation * completed the pubCommonId submodule getId implementation; changed pubCommonId submodule default expires value to today + 8 years * changed openId submodule default expires value to today + 8 years; added final todo comments, pertaining to openId submodule decode and getId methods * fixed formatting to correct linting errors during building * update jsdoc comments for IdSubmodule * added jsdoc comments for overrideId submodule interface method * changed the overrideId return value conditional to require a valid object, added a todo note to investigate using separate instance callbacks to handle multiple timers for syncDelay/auctionDelay * add ajax request to openId submodule getId, awaiting values for request params and response structure and format for storage and structure for adding to bid requests * updated openId submodule getId error logging and callback handling * fix obj path access for syncDelay, updated example file with pubCommonId configured * fix for broken unit tests resulting from update of overrideId addition to submodule interface * replace use of built-in array find method, with import of 'core-js/library/fn/array/find', fixes/updates for integration example for module * refactored config handling in initSubmodules to accept a plain js object opposed to a prebid Config object (this simplifies testing setup) * created init method to wrap initSubmodules with config * refactored module's config to watch/handle changes * removed overrideId submodule interface, change openId to unifiedId * update getId and decode uid data structure also updated integration example * updated object structure for universal ids that is added to bid request, add universalID object handling to rubiconBidAdapter * updated markdown example configuration * fix for syncDelay, added auction end listener before setting syncDelay timer * update to prepare universalID object if adUnits exists * add gdpr consent data to request bids hook, warn on not found, info if found * add test for valid gdpr consent string, exits universal id module on fail * update gdpr consent to check gdprApplies, add cmp code to integration example. update init to use dependency injection * implemented test for gdpr consent to store locally (purpose #1) * added consentString decode to check for purpose #1 (user consents to have data stored locally) * fix initSubmodule function arguments for changed signature * changed submodule getId method signature to pass a consentData argument * tests update with dependency container * update spec to un-comment disabled expect statement * in-progress DI conversion * update to fix test missing dependency for utils * removed getIdCallbackHandler function because it was inlined within initSubmodules. refactored dependencyContainer argument names to dependencies * add unit test case for configurations that define invalid storage.type values (only cookie or html5 are valid) * fixes for html5 storage in module and unit tests. temp comment-out for gdpr test in requestBid hook as it's being refactored into getId submodule methods * fixes for html5 storage in module and unit tests. temp comment-out for gdpr test in requestBid hook as it's being refactored into getId submodule methods * added opt_out cookie logic to init * in-progress commit to update getId method signature with initialized consentManagement data * changed priority to consent management module's value + 1 * updated both submodule getId functions with consent data handling. * update hasGDPRConsent to remove unnecessary test for consentData obj since it's tested outside of function, removed utils from dependency injection * update to move local declarations outside if block, added local var for log prefix since it was accessed more than twice * changed log prefix to build the string locally instead of passing through getIdData obj * bug fix for request bid hook priority race condition * removed consentData prop from init dependencies obj, updated jsdoc comments removing consentData prop * removed consentData prop from init arguments * update integration example to test gdpr cmpApi type of 'static' * refactor to combine request bid hooks into single hook, also other opts and formatting changes * additions/updates to logging, additions/updates to jsdoc comments, various refactoring and formatting updates * fixed how GDPR purpose 1 permission is checked, removed decode function and read from consentData.vendorConsents.purposeConsents[1] (key value 1 is for "purpose 1") * fix for hasGDPRConsent functions, changed object prop accessor name from 'consentData.vendorConsent' to 'consentData.vendorData' * small changes to log messages and code formatting * changed submodule property configKey to configName for consistency with the submodule config property name * updated logging message text and small format change * updated jsdoc comment to reduce line length * formatting fix and jsdoc update * reverted changes to support universal id in rubiconBidAdapter, will open a separate PR for the adapter code changes. * added logging messages to catch statements * fix unit tests using the document cookie * fix to extra module name in log message * changed function return type array to undefined on invalid config * moved encodeURIComponenent and decodeURIComponenent into setCookie and getCookie * refactor to resolve issues creating certain unit tests * add tests for config variations, small fixes for issues found writing tests * removed debug console.log statements * removed set initializedSubmodules value in init * fix to remove test cookie from spec, updated example with submodule config value object * added tests checking that config submodule props create correct number of submodules * added test for syncDelay config update * fixes for LGTM and imports for src are now relative * formatting fix semicolon * test reverted to debug circleci failure * changed request bids hook priority to load after consentManagement * test to resolve circle ci errors * test to resolve circle ci errors * fixed name camel case error * changed unifiedid decode test property name from pubcid to ttid * added universal id support to bid adapter * added unit test for universal id support in bid adapter * optimized last unit test added * renamed universalID to userId * removed file from universal id branch --- modules/rubiconBidAdapter.js | 5 +++++ test/spec/modules/rubiconBidAdapter_spec.js | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 69da9ab6db3..034b861f0f7 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -265,6 +265,7 @@ export const spec = { const containsTgI = /^tg_i/ const orderedParams = [ + 'tpid_tdid', 'account_id', 'site_id', 'zone_id', @@ -367,6 +368,10 @@ export const spec = { 'rf': _getPageUrl(bidRequest, bidderRequest) }; + if ((bidRequest.userId || {}).tdid) { + data['tpid_tdid'] = bidRequest.userId.tdid; + } + if (bidderRequest.gdprConsent) { // add 'gdpr' only if 'gdprApplies' is defined if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 53fa45e89ae..f3b244b1bc1 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1060,6 +1060,19 @@ describe('the rubicon adapter', function () { expect(serverRequests).that.is.an('array').of.length(3); }); }); + + describe('user id config', function() { + it('should send tpid_tdid when userId defines tdid', function () { + const clonedBid = clone(bidderRequest.bids[0]); + clonedBid.userId = { + tdid: 'abcd-efgh-ijkl-mnop-1234' + }; + let [request] = spec.buildRequests([clonedBid], bidderRequest); + let data = parseQuery(request.data); + + expect(data['tpid_tdid']).to.equal('abcd-efgh-ijkl-mnop-1234'); + }); + }) }); describe('for video requests', function () { From 2ff422625f6fba0d18dcafa2ebfeb4cf75816027 Mon Sep 17 00:00:00 2001 From: Claudio Herrera <35111171+thesuperhomie@users.noreply.github.com> Date: Thu, 4 Apr 2019 21:06:15 -0700 Subject: [PATCH 1132/1594] Report og:url when present (#3699) --- modules/gumgumBidAdapter.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 5f18870ae4d..98bf6b17552 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -1,8 +1,8 @@ import * as utils from '../src/utils' import { config } from '../src/config' -import { registerBidder } from '../src/adapters/bidderFactory' import includes from 'core-js/library/fn/array/includes'; +import { registerBidder } from '../src/adapters/bidderFactory' const BIDDER_CODE = 'gumgum' const ALIAS_BIDDER_CODE = ['gg'] @@ -25,6 +25,14 @@ function _getBrowserParams() { const Mbps = connection && (connection.downlink || connection.bandwidth) return Mbps ? Math.round(Mbps * 1024) : null // 1 megabit -> 1024 kilobits } + 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 + } if (browserParams.vw) { // we've already initialized browserParams, just return it. return browserParams @@ -47,7 +55,8 @@ function _getBrowserParams() { pu: topUrl, ce: utils.cookiesAreEnabled(), dpr: topWindow.devicePixelRatio || 1, - jcsi: JSON.stringify({ t: 0, rq: 8 }) + jcsi: JSON.stringify({ t: 0, rq: 8 }), + og_url: getOgURL() } ns = getNetworkSpeed() From 111b82f72bab1b75cfa6bcdcd26df81a8db8f820 Mon Sep 17 00:00:00 2001 From: Telaria Engineering <36203956+telariaEng@users.noreply.github.com> Date: Thu, 4 Apr 2019 21:17:53 -0700 Subject: [PATCH 1133/1594] Telaria Adapter: GDPR support (#3701) * Added telaria bid adapter * more documentation * Added more test cases. And improved some code in the adapter * Removed the check for optional params, they are handled in the server. Also updated certain param names used in the test spec. * added some spaces to fix CircleCI tests * added some spaces to fix CircleCI tests * fixed code indentation in /spec/AnalyticsAdapter_spec.js which causing the CircleCI tests to fail. * Reverted the changes * merged with prebid master. * creative Id is required when we build a response but our server doesn't always have the crid, so using a sentinel value when we don't have the crid. * - removed an un used method - Removed the package-lock file. * merging to master * updated telaria bid adapter to use player size provided by the bid.mediaTypes.video.playerSize instead of bid.sizes. https://github.com/prebid/Prebid.js/issues/3331 * - removed the requirement for having player size - updated the test spec to reflect the above change - removed changes to the package-lock.json file. * added a param to the ad call url to let us know that the request is coming via hb. * to lower casing the bidder code. * Merge branch 'master' of https://github.com/prebid/Prebid.js # Conflicts: # modules/telariaBidAdapter.js Added GDPR support * Sending the gdpr & gdpr consent string only if they're defined --- modules/telariaBidAdapter.js | 16 +++++++++++++++- test/spec/modules/telariaBidAdapter_spec.js | 4 ++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/telariaBidAdapter.js b/modules/telariaBidAdapter.js index 58253b4570a..12698f0ce56 100644 --- a/modules/telariaBidAdapter.js +++ b/modules/telariaBidAdapter.js @@ -154,7 +154,21 @@ function generateUrl(bid, bidderRequest) { } url += ('&transactionId=' + bid.transactionId + '&hb=1'); - url += ('&referrer=' + encodeURIComponent(bidderRequest.refererInfo.referer)); + + if (bidderRequest) { + if (bidderRequest.gdprConsent) { + if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { + url += ('&gdpr=' + (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + } + if (bidderRequest.gdprConsent.consentString) { + url += ('&gdpr_consent=' + bidderRequest.gdprConsent.consentString); + } + } + + if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + url += ('&referrer=' + encodeURIComponent(bidderRequest.refererInfo.referer)); + } + } return (url + '&fmt=json'); } diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js index 88b61844ea4..fdb63675224 100644 --- a/test/spec/modules/telariaBidAdapter_spec.js +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -27,6 +27,10 @@ const REQUEST = { const BIDDER_REQUEST = { 'refererInfo': { 'referer': 'www.test.com' + }, + 'gdprConsent': { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'gdprApplies': true } }; From e7c39f96f2dffa5b1a9a45020eeb7dfb84d998c0 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Thu, 4 Apr 2019 21:39:44 -0700 Subject: [PATCH 1134/1594] PubMatic adapter: adding support for IAB bcat parameter (#3702) * changes for multiformat support * added new constant NATIVE_ASSETS in PubMatic adapter * removed NATIVE_ASSET_KEY reference in PubMatic adapter * removed reference of const NATIVE_ASSET_ID from PubMatic adapter * removed reference of const NATIVE_ASSET_DATA_TYPE in PubMatic adapter * using _commonNativeRequestObject in PubMatic adapter to avoid repeating code block * removed new-lines in const declaration * generating NATIVE_ASSET_REVERSE_ID from NATIVE_ASSETS * renamed NATIVE_ASSET_REVERSE_ID to NATIVE_ASSET_ID_TO_KEY_MAP * little modification in _checkParamDataType in PubMatic adapter * a minor improvement * using let instead of var * added NATIVE_ASSET_KEY_TO_ASSET_MAP and combining switch cases * lint update * removed some stale comments * using LOG_WARN_PREFIX * using const UNDEFINED * added a logWarn in catch * using arrow functions * code review changes * supporting bcat parameter * added details of bcat param for PubMatic adapter * changing log statement on selecting bcat * updated logs * fixed some typos * changes to checkMediaType function * suppress warning of missing mediaTypes.banner for native and video impression * ignore fluid size, if present, in banner impression * fix for ignoring fluid size in banner impression * added relevant comments and test cases for fluid case in banner request * added sample config for multiformat adunit * array length should be > 0 --- modules/pubmaticBidAdapter.js | 29 ++++++ modules/pubmaticBidAdapter.md | 3 +- test/spec/modules/pubmaticBidAdapter_spec.js | 94 ++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 737ab1dadae..6891285fcc2 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -707,6 +707,30 @@ function _parseNativeResponse(bid, newBid) { } } +function _blockedIabCategoriesValidation(payload, blockedIabCategories) { + blockedIabCategories = blockedIabCategories + .filter(function(category) { + if (typeof category === 'string') { // only strings + return true; + } else { + utils.logWarn(LOG_WARN_PREFIX + 'bcat: Each category should be a string, ignoring category: ' + category); + return false; + } + }) + .map(category => category.trim()) // trim all + .filter(function(category, index, arr) { // minimum 3 charaters length + if (category.length > 3) { + return arr.indexOf(category) === index; // unique value only + } else { + 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) { + utils.logWarn(LOG_WARN_PREFIX + 'bcat: Selected: ', blockedIabCategories); + payload.bcat = blockedIabCategories; + } +} + export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER, VIDEO, NATIVE], @@ -756,6 +780,7 @@ export const spec = { var dctrLen; var dctrArr = []; var bid; + var blockedIabCategories = []; validBidRequests.forEach(originalBid => { bid = utils.deepClone(originalBid); _parseAdSlot(bid); @@ -789,6 +814,9 @@ export const spec = { if (bid.params.hasOwnProperty('dctr') && utils.isStr(bid.params.dctr)) { dctrArr.push(bid.params.dctr); } + if (bid.params.hasOwnProperty('bcat') && utils.isArray(bid.params.bcat)) { + blockedIabCategories = blockedIabCategories.concat(bid.params.bcat); + } var impObj = _createImpressionObject(bid, conf); if (impObj) { payload.imp.push(impObj); @@ -860,6 +888,7 @@ export const spec = { } _handleEids(payload); + _blockedIabCategoriesValidation(payload, blockedIabCategories); return { method: 'POST', url: ENDPOINT, diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index e864689d0a1..0f92e1756a5 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -34,7 +34,8 @@ var adUnits = [ gender: 'M', // optional kadfloor: '0.50', // optional currency: 'AUD' // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) - dctr: 'key1=123|key2=345' // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) + dctr: 'key1=123|key2=345', // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) + bcat: ['IAB1-5', 'IAB1-7'] // Optional: Blocked IAB Categories. (Values from all slots will be combined and only unique values will be passed. An array of strings only. Each category should be a string of a length of more than 3 characters.) } }] }]; diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 8173f88bda8..bf008574027 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1805,6 +1805,100 @@ describe('PubMatic adapter', function () { expect(data.site.ext).to.not.exist; }); + describe('Request param bcat 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('bcat: pass only strings', function() { + multipleBidRequests[0].params.bcat = [1, 2, 3, 'IAB1', 'IAB2']; + let request = spec.buildRequests(multipleBidRequests); + let data = JSON.parse(request.data); + expect(data.bcat).to.exist.and.to.deep.equal(['IAB1', 'IAB2']); + }); + + it('bcat: pass strings with length greater than 3', function() { + multipleBidRequests[0].params.bcat = ['AB', 'CD', 'IAB1', 'IAB2']; + let request = spec.buildRequests(multipleBidRequests); + let data = JSON.parse(request.data); + expect(data.bcat).to.exist.and.to.deep.equal(['IAB1', 'IAB2']); + }); + + it('bcat: trim the strings', function() { + multipleBidRequests[0].params.bcat = [' IAB1 ', ' IAB2 ']; + let request = spec.buildRequests(multipleBidRequests); + let data = JSON.parse(request.data); + expect(data.bcat).to.exist.and.to.deep.equal(['IAB1', 'IAB2']); + }); + + it('bcat: pass only unique strings', function() { + // multi slot + multipleBidRequests[0].params.bcat = ['IAB1', 'IAB2', 'IAB1', 'IAB2', 'IAB1', 'IAB2']; + multipleBidRequests[1].params.bcat = ['IAB1', 'IAB2', 'IAB1', 'IAB2', 'IAB1', 'IAB3']; + let request = spec.buildRequests(multipleBidRequests); + let data = JSON.parse(request.data); + expect(data.bcat).to.exist.and.to.deep.equal(['IAB1', 'IAB2', 'IAB3']); + }); + + it('bcat: do not pass bcat if all entries are invalid', function() { + // multi slot + multipleBidRequests[0].params.bcat = ['', 'IAB', 'IAB']; + multipleBidRequests[1].params.bcat = [' ', 22, 99999, 'IA']; + let request = spec.buildRequests(multipleBidRequests); + let data = JSON.parse(request.data); + expect(data.bcat).to.deep.equal(undefined); + }); + }); + describe('Response checking', function () { it('should check for valid response values', function () { let request = spec.buildRequests(bidRequests); From b6f0e6c413c4ffc95d1e18e57f84a187d1ea713b Mon Sep 17 00:00:00 2001 From: alexkh13 Date: Fri, 5 Apr 2019 07:50:50 +0300 Subject: [PATCH 1135/1594] Update Cedato bid adapter (#3704) --- modules/cedatoBidAdapter.js | 10 ++++------ modules/cedatoBidAdapter.md | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/modules/cedatoBidAdapter.js b/modules/cedatoBidAdapter.js index 03ee93792c7..8c049410b3a 100644 --- a/modules/cedatoBidAdapter.js +++ b/modules/cedatoBidAdapter.js @@ -33,31 +33,29 @@ export const spec = { const site = { id: params.player_id, domain: document.domain }; const device = { ua: navigator.userAgent, ip: '' }; const user = { id: getUserID() } - const cur = [ CURRENCY ]; + const currency = CURRENCY; const tmax = bidderRequest.timeout; const imp = bidRequests.map(req => { const banner = { 'format': getFormats(utils.deepAccess(req, 'mediaTypes.banner.sizes')) }; - const bidfloor = params.bidfloor !== undefined - ? Number(params.bidfloor) : 1; - const bidfloorcur = CURRENCY; + const bidfloor = params.bidfloor; const bidId = req.bidId; return { bidId, banner, bidfloor, - bidfloorcur, }; }); const payload = { + version: '$prebid.version$', at, site, device, user, imp, - cur, + currency, tmax, }; diff --git a/modules/cedatoBidAdapter.md b/modules/cedatoBidAdapter.md index 99f8d839220..088f8a4baef 100644 --- a/modules/cedatoBidAdapter.md +++ b/modules/cedatoBidAdapter.md @@ -8,8 +8,8 @@ Maintainer: alexk@cedato.com # Description -Connects to Cedato bidder. -Cedato adapter supports only Banner at the moment. +Connects to Cedato Bidder. +Player ID must be replaced. You can approach your Cedato account manager to get one. # Test Parameters ``` From f6cf5e8cefdf5a68a8e230b2e5a822edb160b88b Mon Sep 17 00:00:00 2001 From: John Salis Date: Fri, 5 Apr 2019 01:01:17 -0400 Subject: [PATCH 1136/1594] Add user id support to Beachfront adapter (#3708) --- modules/beachfrontBidAdapter.js | 28 +++++++++++++++--- modules/beachfrontBidAdapter.md | 4 +-- .../spec/modules/beachfrontBidAdapter_spec.js | 29 ++++++++++++++++++- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 7944ac191aa..552413f4878 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -294,15 +294,31 @@ function createVideoRequestData(bid, bidderRequest) { js: 1, geo: {} }, - regs: {}, - user: {}, + regs: { + ext: {} + }, + user: { + ext: {} + }, cur: ['USD'] }; if (bidderRequest && bidderRequest.gdprConsent) { let { gdprApplies, consentString } = bidderRequest.gdprConsent; - payload.regs.ext = { gdpr: gdprApplies ? 1 : 0 }; - payload.user.ext = { consent: consentString }; + payload.regs.ext.gdpr = gdprApplies ? 1 : 0; + payload.user.ext.consent = consentString; + } + + if (bid.userId && bid.userId.tdid) { + payload.user.ext.eids = [{ + source: 'adserver.org', + uids: [{ + id: bid.userId.tdid, + ext: { + rtiPartner: 'TDID' + } + }] + }]; } return payload; @@ -340,6 +356,10 @@ function createBannerRequestData(bids, bidderRequest) { payload.gdprConsent = consentString; } + if (bids[0] && bids[0].userId && bids[0].userId.tdid) { + payload.tdid = bids[0].userId.tdid; + } + return payload; } diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index 5defb358f7b..fb14db59710 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -4,7 +4,7 @@ Module Name: Beachfront Bid Adapter Module Type: Bidder Adapter -Maintainer: johnsalis@beachfront.com +Maintainer: john@beachfront.com # Description @@ -85,4 +85,4 @@ Module that connects to Beachfront's demand sources ] } ]; -``` \ No newline at end of file +``` diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index b369ed1f941..652dae4a74a 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,6 +1,5 @@ import { expect } from 'chai'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; -import * as utils from 'src/utils'; import { parse as parseUrl } from 'src/url'; describe('BeachfrontAdapter', function () { @@ -248,6 +247,24 @@ describe('BeachfrontAdapter', function () { expect(data.regs.ext.gdpr).to.equal(1); expect(data.user.ext.consent).to.equal(consentString); }); + + it('must add the Trade Desk User ID to the request', () => { + const tdid = '4321'; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { video: {} }; + bidRequest.userId = { tdid }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.user.ext.eids[0]).to.deep.equal({ + source: 'adserver.org', + uids: [{ + id: tdid, + ext: { + rtiPartner: 'TDID' + } + }] + }); + }); }); describe('for banner bids', function () { @@ -368,6 +385,16 @@ describe('BeachfrontAdapter', function () { expect(data.gdpr).to.equal(1); expect(data.gdprConsent).to.equal(consentString); }); + + it('must add the Trade Desk User ID to the request', () => { + const tdid = '4321'; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { banner: {} }; + bidRequest.userId = { tdid }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.tdid).to.equal(tdid); + }); }); describe('for multi-format bids', function () { From 0664a1881f29cad8ea4324e9809531f713ae2938 Mon Sep 17 00:00:00 2001 From: elebruchec-adux <49271296+elebruchec-adux@users.noreply.github.com> Date: Fri, 5 Apr 2019 07:09:28 +0200 Subject: [PATCH 1137/1594] [QuantumBidAdapter][Other] Change maintainer email and resize service url from elasticad.net to adux.com (#3710) --- modules/quantumBidAdapter.js | 2 +- modules/quantumBidAdapter.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/quantumBidAdapter.js b/modules/quantumBidAdapter.js index 0ad8f70082f..7f35b996d48 100644 --- a/modules/quantumBidAdapter.js +++ b/modules/quantumBidAdapter.js @@ -203,7 +203,7 @@ export const spec = { ad['clicktrackers'] = link.clicktrackers; } - ad['main_image'] = '//resize-ssp.elasticad.net/scalecrop-290x130/' + window.btoa(ad['main_image']) + '/external'; + ad['main_image'] = '//resize-ssp.adux.com/scalecrop-290x130/' + window.btoa(ad['main_image']) + '/external'; bid.ad = '
' + '
' + diff --git a/modules/quantumBidAdapter.md b/modules/quantumBidAdapter.md index ac64ab371c5..572ca9ecd37 100644 --- a/modules/quantumBidAdapter.md +++ b/modules/quantumBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Quantum Advertising Bid Adapter Module Type: Bidder Adapter -Maintainer: sami@elasticad.com +Maintainer: support.mediareporting@adux.com ``` # Description From df312c1e9e761e7903cea200f775e25b2180a15a Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Fri, 5 Apr 2019 01:18:03 -0400 Subject: [PATCH 1138/1594] add console message when number of adunits exceeds point (#3707) * add console message when number of adunits exceeds point * include additional information in log message --- src/prebid.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/prebid.js b/src/prebid.js index 21be22e5376..7b8548d8070 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -467,6 +467,12 @@ $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeo } const auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout, labels}); + + let adUnitsLen = adUnits.length; + if (adUnitsLen > 15) { + utils.logInfo(`Current auction ${auction.getAuctionId()} contains ${adUnitsLen} adUnits.`, adUnits); + } + adUnitCodes.forEach(code => targeting.setLatestAuctionForAdUnit(code, auction.getAuctionId())); auction.callBids(); return auction; From 140f73cf6211710431c02d40038f17be156759e3 Mon Sep 17 00:00:00 2001 From: elebruchec-adux <49271296+elebruchec-adux@users.noreply.github.com> Date: Fri, 5 Apr 2019 07:23:57 +0200 Subject: [PATCH 1139/1594] [QuantumBidAdapter][Feature] Add eventrackers field in response interpretation. (#3709) --- modules/quantumBidAdapter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/quantumBidAdapter.js b/modules/quantumBidAdapter.js index 7f35b996d48..e3fa6771a8b 100644 --- a/modules/quantumBidAdapter.js +++ b/modules/quantumBidAdapter.js @@ -137,6 +137,7 @@ export const spec = { let ad = {}; ad['trackers'] = trackers; ad['jstrackers'] = jstracker; + ad['eventtrackers'] = serverBody.native.eventtrackers || []; for (let i = 0; i < assets.length; i++) { let asset = assets[i]; @@ -281,6 +282,7 @@ export const spec = { if (link.clicktrackers) { native.clickTrackers = link.clicktrackers; } + native.eventtrackers = native.eventtrackers || []; bid.qtx_native = utils.deepClone(serverBody.native); bid.native = native; From 711016d01b2a0ebd53ac923243897452d7a2c879 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Fri, 5 Apr 2019 09:29:15 -0700 Subject: [PATCH 1140/1594] Sonobi Adapter - support User ID module (#3532) * added universal id support to bid adapter * added unit test for universal id support in bid adapter * added universal id support to bid adapter * added unit test for universal id support in bid adapter * renamed universalID to userId * removed merge error * test fix remove userId prop when completed * updated to prioritize hfa value from hfa over userId.pubcid or crumbs.pubcid * updated userId conditional as recommended --- modules/sonobiBidAdapter.js | 8 ++++++-- test/spec/modules/sonobiBidAdapter_spec.js | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index ab4058b1978..0d949fed25a 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -62,8 +62,12 @@ export const spec = { payload.us = config.getConfig('userSync').syncsPerBidder; } - if (deepAccess(validBidRequests[0], 'crumbs.pubcid') || deepAccess(validBidRequests[0], 'params.hfa')) { - payload.hfa = deepAccess(validBidRequests[0], 'params.hfa') ? deepAccess(validBidRequests[0], 'params.hfa') : `PRE-${deepAccess(validBidRequests[0], 'crumbs.pubcid')}`; + if (deepAccess(validBidRequests[0], 'params.hfa')) { + payload.hfa = deepAccess(validBidRequests[0], 'params.hfa'); + } else if (deepAccess(validBidRequests[0], 'userId.pubcid')) { + payload.hfa = `PRE-${validBidRequests[0].userId.pubcid}`; + } else if (deepAccess(validBidRequests[0], 'crumbs.pubcid')) { + payload.hfa = `PRE-${validBidRequests[0].crumbs.pubcid}`; } if (validBidRequests[0].params.referrer) { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 4fe9d92b2d4..010d07f1c37 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -291,6 +291,21 @@ describe('SonobiBidAdapter', function () { expect(bidRequests.data.hfa).to.equal('PRE-abcd-efg-0101'); }) + it('should return a properly formatted request with commonid from User ID as hfa', function () { + delete bidRequest[0].params.hfa; + delete bidRequest[1].params.hfa; + bidRequest[0].userId = {'pubcid': 'abcd-efg-0101'}; + bidRequest[1].userId = {'pubcid': 'abcd-efg-0101'}; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests) + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json') + expect(bidRequests.method).to.equal('GET') + expect(bidRequests.data.ref).not.to.be.empty + expect(bidRequests.data.s).not.to.be.empty + expect(bidRequests.data.hfa).to.equal('PRE-abcd-efg-0101'); + delete bidRequest[0].userId; + delete bidRequest[1].userId; + }) + it('should return a properly formatted request with hfa preferred over commonid', function () { bidRequest[0].params.hfa = 'hfakey'; bidRequest[1].params.hfa = 'hfakey'; From d877177fcfede57b7e15f4920b47fc6c3cbb5190 Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Tue, 9 Apr 2019 18:57:02 +0300 Subject: [PATCH 1141/1594] Update Grid Bid Adapter (#3681) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Add video support in Grid Bid Adapter * Added test parameter for video slot * update Grid Bid Adapter to set size in response bid * Update Grid Bid Adapter to support identical uids in parameters * Fix typo in test file for Grid Bid Adapter --- modules/gridBidAdapter.js | 69 ++++-- test/spec/modules/gridBidAdapter_spec.js | 263 +++++++++++++++++++---- 2 files changed, 282 insertions(+), 50 deletions(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index fd1a382d995..f02ec58fd68 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -41,22 +41,47 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { const auids = []; const bidsMap = {}; + const slotsMapByUid = {}; + const sizeMap = {}; const bids = validBidRequests || []; let reqId; bids.forEach(bid => { reqId = bid.bidderRequestId; - if (!bidsMap[bid.params.uid]) { - bidsMap[bid.params.uid] = [bid]; - auids.push(bid.params.uid); + const {params: {uid}, adUnitCode} = bid; + auids.push(uid); + const sizesId = utils.parseSizesInput(bid.sizes); + + if (!slotsMapByUid[uid]) { + slotsMapByUid[uid] = {}; + } + const slotsMap = slotsMapByUid[uid]; + if (!slotsMap[adUnitCode]) { + slotsMap[adUnitCode] = {adUnitCode, bids: [bid], parents: []}; } else { - bidsMap[bid.params.uid].push(bid); + 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 = { u: utils.getTopWindowUrl(), auids: auids.join(','), + sizes: utils.getKeys(sizeMap).join(','), r: reqId }; @@ -108,7 +133,7 @@ export const spec = { if (errorMessage) utils.logError(errorMessage); return bidResponses; } -} +}; function _getBidFromResponse(respItem) { if (!respItem) { @@ -129,24 +154,25 @@ function _addBidResponse(serverBid, bidsMap, bidResponses) { else { const awaitingBids = bidsMap[serverBid.auid]; if (awaitingBids) { - awaitingBids.forEach(bid => { - const size = bid.sizes[0]; - if (serverBid.w && serverBid.h) { - size[0] = serverBid.w; - size[1] = serverBid.h; - } + const sizeId = `${serverBid.w}x${serverBid.h}`; + if (awaitingBids[sizeId]) { + const slot = awaitingBids[sizeId][0]; + + const bid = slot.bids.shift(); + const bidResponse = { requestId: bid.bidId, // bid.bidderRequestId, bidderCode: spec.code, cpm: serverBid.price, - width: size[0], - height: size[1], + width: serverBid.w, + height: serverBid.h, creativeId: serverBid.auid, // bid.bidId, currency: 'USD', netRevenue: false, ttl: TIME_TO_LIVE, dealId: serverBid.dealid }; + if (serverBid.content_type === 'video') { bidResponse.vastXml = serverBid.adm; bidResponse.mediaType = VIDEO; @@ -164,7 +190,22 @@ function _addBidResponse(serverBid, bidsMap, bidResponses) { bidResponse.mediaType = BANNER; } 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 (!utils.getKeys(parent).length) { + delete bidsMap[uid]; + } + } + }); + } + } } else { errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; } diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index 9be195b4bd2..53560a9ac6f 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -89,6 +89,7 @@ describe('TheMediaGrid Adapter', function () { const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('auids', '1'); + expect(payload).to.have.property('sizes', '300x250,300x600'); expect(payload).to.have.property('r', '22edbae2733bf6'); }); @@ -97,7 +98,8 @@ describe('TheMediaGrid Adapter', function () { expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); - expect(payload).to.have.property('auids', '1,2'); + expect(payload).to.have.property('auids', '1,1,2'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); }); @@ -129,9 +131,10 @@ describe('TheMediaGrid Adapter', function () { describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300, dealid: 11}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 2, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 2, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 1, 'h': 90, 'w': 728}], 'seat': '1'}, {'bid': [{'price': 0, 'auid': 3, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0, 'adm': '
test content 4
', 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300}], 'seat': '1'}, undefined, {'bid': [], 'seat': '1'}, {'seat': '1'}, @@ -226,13 +229,13 @@ describe('TheMediaGrid Adapter', function () { 'ttl': 360, }, { - 'requestId': '5703af74d0472a', - 'cpm': 1.15, - 'creativeId': 1, - 'dealId': 11, + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 2, + 'dealId': undefined, 'width': 300, - 'height': 250, - 'ad': '
test content 1
', + 'height': 600, + 'ad': '
test content 2
', 'bidderCode': 'grid', 'currency': 'USD', 'mediaType': 'banner', @@ -240,13 +243,13 @@ describe('TheMediaGrid Adapter', function () { 'ttl': 360, }, { - 'requestId': '4dff80cc4ee346', - 'cpm': 0.5, - 'creativeId': 2, + 'requestId': '5703af74d0472a', + 'cpm': 0.15, + 'creativeId': 1, 'dealId': undefined, 'width': 728, 'height': 90, - 'ad': '
test content 2
', + 'ad': '
test content 3
', 'bidderCode': 'grid', 'currency': 'USD', 'mediaType': 'banner', @@ -255,7 +258,7 @@ describe('TheMediaGrid Adapter', function () { } ]; - const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(0, 3)}}, request); expect(result).to.deep.equal(expectedResponse); }); @@ -264,7 +267,7 @@ describe('TheMediaGrid Adapter', function () { { 'bidder': 'grid', 'params': { - 'uid': '1' + 'uid': '11' }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -280,7 +283,7 @@ describe('TheMediaGrid Adapter', function () { { 'bidder': 'grid', 'params': { - 'uid': '2' + 'uid': '12' }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -295,15 +298,15 @@ describe('TheMediaGrid Adapter', function () { } ]; const response = [ - {'bid': [{'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 1, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, - {'bid': [{'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 2, content_type: 'video'}], 'seat': '2'} + {'bid': [{'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 11, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, + {'bid': [{'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 12, content_type: 'video'}], 'seat': '2'} ]; const request = spec.buildRequests(bidRequests); const expectedResponse = [ { 'requestId': '659423fff799cb', 'cpm': 1.15, - 'creativeId': 1, + 'creativeId': 11, 'dealId': undefined, 'width': 300, 'height': 600, @@ -316,23 +319,6 @@ describe('TheMediaGrid Adapter', function () { 'adResponse': { 'content': '\n<\/Ad>\n<\/VAST>' } - }, - { - 'requestId': '2bc598e42b6a', - 'cpm': 1.00, - 'creativeId': 2, - 'dealId': undefined, - 'width': 300, - 'height': 250, - 'bidderCode': 'grid', - 'currency': 'USD', - 'mediaType': 'video', - 'netRevenue': false, - 'ttl': 360, - 'vastXml': '\n<\/Ad>\n<\/VAST>', - 'adResponse': { - 'content': '\n<\/Ad>\n<\/VAST>' - } } ]; @@ -380,5 +366,210 @@ describe('TheMediaGrid Adapter', function () { const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); expect(result.length).to.equal(0); }); + + it('complicated case', function () { + const fullResponse = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300, dealid: 11}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 2, 'h': 600, 'w': 300, dealid: 12}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 1, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 4
', 'auid': 1, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 5
', 'auid': 2, 'h': 600, 'w': 350}], 'seat': '1'}, + ]; + const bidRequests = [ + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '2164be6358b9', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '326bde7fbf69', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '2' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4e111f1b66e4', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '26d6f897b516', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '2' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '1751cd90161', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '2164be6358b9', + 'cpm': 1.15, + 'creativeId': 1, + 'dealId': 11, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': false, + 'ttl': 360, + }, + { + 'requestId': '4e111f1b66e4', + 'cpm': 0.5, + 'creativeId': 2, + 'dealId': 12, + 'width': 300, + 'height': 600, + 'ad': '
test content 2
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': false, + 'ttl': 360, + }, + { + 'requestId': '26d6f897b516', + 'cpm': 0.15, + 'creativeId': 1, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
test content 3
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': false, + 'ttl': 360, + }, + { + 'requestId': '326bde7fbf69', + 'cpm': 0.15, + 'creativeId': 1, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'ad': '
test content 4
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': false, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('dublicate uids and sizes in one slot', function () { + const fullResponse = [ + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 1, 'h': 250, 'w': 300}], 'seat': '1'}, + ]; + const bidRequests = [ + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '5126e301f4be', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '57b2ebe70e16', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + }, + { + 'bidder': 'grid', + 'params': { + 'uid': '1' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '225fcd44b18c', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '5126e301f4be', + 'cpm': 1.15, + 'creativeId': 1, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 1
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': false, + 'ttl': 360, + }, + { + 'requestId': '57b2ebe70e16', + 'cpm': 0.5, + 'creativeId': 1, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
test content 2
', + 'bidderCode': 'grid', + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': false, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + expect(result).to.deep.equal(expectedResponse); + }); }); }); From 9b7b407c31e9d903591b8c81df9fa82fba60b410 Mon Sep 17 00:00:00 2001 From: Jeremy Hernandez Date: Tue, 9 Apr 2019 17:59:56 +0200 Subject: [PATCH 1142/1594] feat(adyoulikeAdapter): use only https protocol (#3692) --- modules/adyoulikeBidAdapter.js | 2 +- test/spec/modules/adyoulikeBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index 4bca9b58fe5..4624bdba8b5 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -132,7 +132,7 @@ function getPageRefreshed() { function createEndpoint(bidRequests, bidderRequest) { let host = getHostname(bidRequests); return format({ - protocol: (document.location.protocol === 'https:') ? 'https' : 'http', + protocol: 'https', host: `${DEFAULT_DC}${host}.omnitagjs.com`, pathname: '/hb-api/prebid/v1', search: createEndpointQS(bidderRequest) diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js index 26898d3f57e..3f28acaaf97 100644 --- a/test/spec/modules/adyoulikeBidAdapter_spec.js +++ b/test/spec/modules/adyoulikeBidAdapter_spec.js @@ -134,7 +134,7 @@ describe('Adyoulike Adapter', function () { ]; const adapter = newBidder(spec); - let getEndpoint = (dc = defaultDC) => `http://${dc}.omnitagjs.com/hb-api/prebid`; + let getEndpoint = (dc = defaultDC) => `https://${dc}.omnitagjs.com/hb-api/prebid`; describe('inherited functions', function () { it('exists and is a function', function () { From a53deb93cd9abcfa46d15076dfe441e450952905 Mon Sep 17 00:00:00 2001 From: Pascal S Date: Tue, 9 Apr 2019 19:41:32 +0200 Subject: [PATCH 1143/1594] added an auctionId parameter to requestBids (#3622) --- src/auction.js | 4 ++-- src/auctionManager.js | 4 ++-- src/prebid.js | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/auction.js b/src/auction.js index 7cb08af7402..db7b82201c5 100644 --- a/src/auction.js +++ b/src/auction.js @@ -90,7 +90,7 @@ const queuedCalls = []; * * @returns {Auction} auction instance */ -export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) { +export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, auctionId}) { let _adUnits = adUnits; let _labels = labels; let _adUnitCodes = adUnitCodes; @@ -99,7 +99,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) let _noBids = []; let _auctionStart; let _auctionEnd; - let _auctionId = utils.generateUUID(); + let _auctionId = auctionId || utils.generateUUID(); let _auctionStatus; let _callback = callback; let _timer; diff --git a/src/auctionManager.js b/src/auctionManager.js index a8ca246e148..53ff154bfd1 100644 --- a/src/auctionManager.js +++ b/src/auctionManager.js @@ -76,8 +76,8 @@ export function newAuctionManager() { .filter(uniques); }; - auctionManager.createAuction = function({ adUnits, adUnitCodes, callback, cbTimeout, labels }) { - const auction = newAuction({ adUnits, adUnitCodes, callback, cbTimeout, labels }); + auctionManager.createAuction = function({ adUnits, adUnitCodes, callback, cbTimeout, labels, auctionId }) { + const auction = newAuction({ adUnits, adUnitCodes, callback, cbTimeout, labels, auctionId }); _addAuction(auction); return auction; }; diff --git a/src/prebid.js b/src/prebid.js index 7b8548d8070..d475a715bbf 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -395,9 +395,10 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { * @param {Array} requestOptions.adUnits * @param {Array} requestOptions.adUnitCodes * @param {Array} requestOptions.labels + * @param {String} requestOptions.auctionId * @alias module:pbjs.requestBids */ -$$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels } = {}) { +$$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels, auctionId } = {}) { events.emit(REQUEST_BIDS); const cbTimeout = timeout || config.getConfig('bidderTimeout'); adUnits = adUnits || $$PREBID_GLOBAL$$.adUnits; @@ -466,7 +467,7 @@ $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeo return; } - const auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout, labels}); + const auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout, labels, auctionId}); let adUnitsLen = adUnits.length; if (adUnitsLen > 15) { From ac2ef45467dc4caed06c3a9dc27d2be64b6b1182 Mon Sep 17 00:00:00 2001 From: Oz Weiss Date: Tue, 9 Apr 2019 20:43:57 +0300 Subject: [PATCH 1144/1594] fix bidTimeout event (#3696) --- src/adapterManager.js | 4 +- src/adapters/bidderFactory.js | 6 +- src/auction.js | 30 +++----- test/spec/auctionmanager_spec.js | 92 +++++++++++++++++------ test/spec/unit/core/bidderFactory_spec.js | 54 +++++++------ 5 files changed, 114 insertions(+), 72 deletions(-) diff --git a/src/adapterManager.js b/src/adapterManager.js index 75415c4035f..7cf0122f669 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -252,7 +252,7 @@ adapterManager.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTi return bidRequests; }; -adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbacks, requestBidsTimeout) => { +adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, requestCallbacks, requestBidsTimeout, onTimelyResponse) => { if (!bidRequests.length) { utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); return; @@ -323,7 +323,7 @@ adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, request request: requestCallbacks.request.bind(null, bidRequest.bidderCode), done: requestCallbacks.done } : undefined); - adapter.callBids(bidRequest, addBidResponse.bind(bidRequest), doneCb.bind(bidRequest), ajax); + adapter.callBids(bidRequest, addBidResponse.bind(bidRequest), doneCb.bind(bidRequest), ajax, onTimelyResponse); }); } diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 3306011d6aa..90cab154fd4 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -168,7 +168,7 @@ export function newBidder(spec) { return Object.freeze(spec); }, registerSyncs, - callBids: function(bidderRequest, addBidResponse, done, ajax) { + callBids: function(bidderRequest, addBidResponse, done, ajax, onTimelyResponse) { if (!Array.isArray(bidderRequest.bids)) { return; } @@ -267,6 +267,8 @@ export function newBidder(spec) { // 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); + try { response = JSON.parse(response); } catch (e) { /* response might not be JSON... that's ok. */ } @@ -316,6 +318,8 @@ export function newBidder(spec) { // 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(); } diff --git a/src/auction.js b/src/auction.js index db7b82201c5..1d758997035 100644 --- a/src/auction.js +++ b/src/auction.js @@ -48,7 +48,7 @@ * @property {function(): void} callBids - sends requests to all adapters for bids */ -import { uniques, flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest, getValue } from './utils'; +import { flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest, getValue } from './utils'; import { parse as parseURL } from './url'; import { getPriceBucketString } from './cpmBucketManager'; import { getNativeTargeting } from './native'; @@ -58,7 +58,6 @@ import { config } from './config'; import { userSync } from './userSync'; import { hook } from './hook'; import find from 'core-js/library/fn/array/find'; -import includes from 'core-js/library/fn/array/includes'; import { OUTSTREAM } from './video'; const { syncUsers } = userSync; @@ -105,6 +104,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a let _timer; let _timeout = cbTimeout; let _winningBids = []; + let _timelyBidders = new Set(); function addBidRequests(bidderRequests) { _bidderRequests = _bidderRequests.concat(bidderRequests) }; function addBidReceived(bidsReceived) { _bidsReceived = _bidsReceived.concat(bidsReceived); } @@ -144,7 +144,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a let timedOutBidders = []; if (timedOut) { utils.logMessage(`Auction ${_auctionId} timedOut`); - timedOutBidders = getTimedOutBids(_bidderRequests, _bidsReceived); + timedOutBidders = getTimedOutBids(_bidderRequests, _timelyBidders); if (timedOutBidders.length) { events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); } @@ -186,6 +186,10 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a executeCallback(false, true); } + function onTimelyResponse(bidderCode) { + _timelyBidders.add(bidderCode); + } + function callBids() { _auctionStatus = AUCTION_STARTED; _auctionStart = Date.now(); @@ -240,7 +244,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a } } } - }, _timeout); + }, _timeout, onTimelyResponse); } }; @@ -690,7 +694,7 @@ function groupByPlacement(bidsByPlacement, bid) { /** * Returns a list of bids that we haven't received a response yet where the bidder did not call done * @param {BidRequest[]} bidderRequests List of bids requested for auction instance - * @param {BidReceived[]} bidsReceived List of bids received for auction instance + * @param {Set} timelyBidders Set of bidders which responded in time * * @typedef {Object} TimedOutBid * @property {string} bidId The id representing the bid @@ -700,21 +704,9 @@ function groupByPlacement(bidsByPlacement, bid) { * * @return {Array} List of bids that Prebid hasn't received a response for */ -function getTimedOutBids(bidderRequests, bidsReceived) { - const bidRequestedWithoutDoneCodes = bidderRequests - .filter(bidderRequest => !bidderRequest.doneCbCallCount) - .map(bid => bid.bidderCode) - .filter(uniques); - - const bidReceivedCodes = bidsReceived - .map(bid => bid.bidder) - .filter(uniques); - - const timedOutBidderCodes = bidRequestedWithoutDoneCodes - .filter(bidder => !includes(bidReceivedCodes, bidder)); - +function getTimedOutBids(bidderRequests, timelyBidders) { const timedOutBids = bidderRequests - .map(bid => (bid.bids || []).filter(bid => includes(timedOutBidderCodes, bid.bidder))) + .map(bid => (bid.bids || []).filter(bid => !timelyBidders.has(bid.bidder))) .reduce(flatten, []) .map(bid => ({ bidId: bid.bidId, diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 9c936ace421..2d8ee562ce4 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -628,17 +628,15 @@ describe('auctionmanager.js', function () { before(function () { makeRequestsStub = sinon.stub(adapterManager, 'makeBidRequests'); - - ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder); }); after(function () { - ajaxStub.restore(); adapterManager.makeBidRequests.restore(); }); describe('when auction timeout is 3000', function () { before(function () { + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockAjaxBuilder); makeRequestsStub.returns(TEST_BID_REQS); }); beforeEach(function () { @@ -661,6 +659,10 @@ describe('auctionmanager.js', function () { auctionModule.newAuction.restore(); }); + after(function () { + ajaxStub.restore(); + }); + function checkPbDg(cpm, expected, msg) { return function() { bids[0].cpm = cpm; @@ -755,6 +757,7 @@ describe('auctionmanager.js', function () { describe('when auction timeout is 20', function () { let eventsEmitSpy; + let server; before(function () { bids = [mockBid(), mockBid({ bidderCode: BIDDER_CODE1 })]; @@ -764,6 +767,8 @@ describe('auctionmanager.js', function () { }); beforeEach(function () { + server = sinon.createFakeServer(); + adUnits = [{ code: ADUNIT_CODE, bids: [ @@ -772,35 +777,72 @@ describe('auctionmanager.js', function () { }]; adUnitCodes = [ADUNIT_CODE]; - auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 20}); - createAuctionStub = sinon.stub(auctionModule, 'newAuction'); - createAuctionStub.returns(auction); + eventsEmitSpy = sinon.spy(events, 'emit'); + }); + afterEach(function () { + server.restore(); + events.emit.restore(); + }); + it('should emit BID_TIMEOUT for timed out bids', function (done) { + const spec1 = mockBidder(BIDDER_CODE, [bids[0]]); + registerBidder(spec1); + const spec2 = mockBidder(BIDDER_CODE1, [bids[1]]); + registerBidder(spec2); - spec = mockBidder(BIDDER_CODE, [bids[0]]); - registerBidder(spec); + function respondToRequest(requestIndex) { + server.requests[requestIndex].respond(200, {}, 'response body'); + } + function auctionCallback() { + const bidTimeoutCall = eventsEmitSpy.withArgs(CONSTANTS.EVENTS.BID_TIMEOUT).getCalls()[0]; + const timedOutBids = bidTimeoutCall.args[1]; + assert.equal(timedOutBids.length, 1); + assert.equal(timedOutBids[0].bidder, BIDDER_CODE1); + done(); + } + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: auctionCallback, cbTimeout: 20}); - // Timeout is checked when bid is received. If that bid is the only one - // auction is waiting for, timeout is not emitted, so we need to add a - // second bidder to get timeout event. - let spec1 = mockBidder(BIDDER_CODE1, [bids[1]]); + auction.callBids(); + respondToRequest(0); + }); + it('should NOT emit BID_TIMEOUT when all bidders responded in time', function (done) { + const spec1 = mockBidder(BIDDER_CODE, [bids[0]]); registerBidder(spec1); + const spec2 = mockBidder(BIDDER_CODE1, [bids[1]]); + registerBidder(spec2); - eventsEmitSpy = sinon.spy(events, 'emit'); + function respondToRequest(requestIndex) { + server.requests[requestIndex].respond(200, {}, 'response body'); + } + function auctionCallback() { + assert.ok(eventsEmitSpy.withArgs(CONSTANTS.EVENTS.BID_TIMEOUT).notCalled, 'did not emit event BID_TIMEOUT'); + done(); + } + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: auctionCallback, cbTimeout: 20}); - // make all timestamp calls 5 minutes apart - let callCount = 0; - sinon.stub(utils, 'timestamp').callsFake(function() { - return new Date().getTime() + (callCount++ * 1000 * 60 * 5); - }); - }); - afterEach(function () { - auctionModule.newAuction.restore(); - events.emit.restore(); - utils.timestamp.restore(); + auction.callBids(); + respondToRequest(0); + respondToRequest(1); }); - it('should emit BID_TIMEOUT for timed out bids', function () { + it('should NOT emit BID_TIMEOUT for bidders which responded in time but with an empty bid', function (done) { + const spec1 = mockBidder(BIDDER_CODE, []); + registerBidder(spec1); + const spec2 = mockBidder(BIDDER_CODE1, []); + registerBidder(spec2); + + function respondToRequest(requestIndex) { + server.requests[requestIndex].respond(200, {}, 'response body'); + } + function auctionCallback() { + const bidTimeoutCall = eventsEmitSpy.withArgs(CONSTANTS.EVENTS.BID_TIMEOUT).getCalls()[0]; + const timedOutBids = bidTimeoutCall.args[1]; + assert.equal(timedOutBids.length, 1); + assert.equal(timedOutBids[0].bidder, BIDDER_CODE1); + done(); + } + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: auctionCallback, cbTimeout: 20}); + auction.callBids(); - assert.ok(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BID_TIMEOUT), 'emitted events BID_TIMEOUT'); + respondToRequest(0); }); }); }); diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 9e201afbe6c..fd54d2911e1 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -29,6 +29,10 @@ const MOCK_BIDS_REQUEST = { ] } +function onTimelyResponseStub() { + +} + describe('bidders created by newBidder', function () { let spec; let bidder; @@ -67,7 +71,7 @@ describe('bidders created by newBidder', function () { spec.getUserSyncs.returns([]); bidder.callBids({}); - bidder.callBids({ bids: 'nothing useful' }, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids({ bids: 'nothing useful' }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.called).to.equal(false); @@ -81,7 +85,7 @@ describe('bidders created by newBidder', function () { spec.isBidRequestValid.returns(true); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -95,7 +99,7 @@ describe('bidders created by newBidder', function () { spec.isBidRequestValid.returns(false); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -109,7 +113,7 @@ describe('bidders created by newBidder', function () { spec.isBidRequestValid.onSecondCall().returns(false); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -123,7 +127,7 @@ describe('bidders created by newBidder', function () { spec.isBidRequestValid.returns(true); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.called).to.equal(false); }); @@ -139,7 +143,7 @@ describe('bidders created by newBidder', function () { data: data }); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(url); @@ -164,7 +168,7 @@ describe('bidders created by newBidder', function () { options: options }); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(url); @@ -187,7 +191,7 @@ describe('bidders created by newBidder', function () { data: data }); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2&`); @@ -211,7 +215,7 @@ describe('bidders created by newBidder', function () { options: opt }); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2&`); @@ -240,7 +244,7 @@ describe('bidders created by newBidder', function () { } ]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(ajaxStub.calledTwice).to.equal(true); }); @@ -253,7 +257,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns([]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(addBidResponseStub.callCount).to.equal(0); }); @@ -293,7 +297,7 @@ describe('bidders created by newBidder', function () { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(spec.interpretResponse.calledOnce).to.equal(true); const response = spec.interpretResponse.firstCall.args[0] @@ -325,7 +329,7 @@ describe('bidders created by newBidder', function () { ]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(spec.interpretResponse.calledTwice).to.equal(true); expect(doneStub.calledOnce).to.equal(true); @@ -356,7 +360,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); @@ -375,7 +379,7 @@ describe('bidders created by newBidder', function () { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1].length).to.equal(1); @@ -394,7 +398,7 @@ describe('bidders created by newBidder', function () { url: 'usersync.com' }]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(userSyncStub.called).to.equal(true); expect(userSyncStub.firstCall.args[0]).to.equal('iframe'); @@ -423,7 +427,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(logErrorSpy.calledOnce).to.equal(true); }); @@ -453,7 +457,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(logErrorSpy.calledOnce).to.equal(true); }); @@ -485,7 +489,7 @@ describe('bidders created by newBidder', function () { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(spec.interpretResponse.called).to.equal(false); expect(doneStub.calledOnce).to.equal(true); @@ -503,7 +507,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns([]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(addBidResponseStub.callCount).to.equal(0); expect(doneStub.calledOnce).to.equal(true); @@ -520,7 +524,7 @@ describe('bidders created by newBidder', function () { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]); @@ -666,7 +670,7 @@ describe('validate bid response: ', function () { const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); @@ -703,7 +707,7 @@ describe('validate bid response: ', function () { const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(addBidResponseStub.calledOnce).to.equal(false); expect(logErrorSpy.callCount).to.equal(1); @@ -736,7 +740,7 @@ describe('validate bid response: ', function () { const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); @@ -768,7 +772,7 @@ describe('validate bid response: ', function () { const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); From 0b1486e3e28a683a48cda1618cbf57a89bd082d5 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 9 Apr 2019 11:55:51 -0600 Subject: [PATCH 1145/1594] Default debug change and remove setConfig hook (#3714) * set DEFAULT_DEBUG immediately based off of URL query string * fix debugging module to work with queued setConfig * remove setConfig hook which was added for removed pre1api * remove tests that expected setConfig not to work * on second though debugging module should use setConfig in case there are listeners --- src/config.js | 8 +-- src/utils.js | 8 --- test/spec/debugging_spec.js | 2 + test/spec/modules/emoteevBidAdapter_spec.js | 55 +++++++++++---------- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/config.js b/src/config.js index a1a8af629d8..db47fee0687 100644 --- a/src/config.js +++ b/src/config.js @@ -10,10 +10,10 @@ import { isValidPriceConfig } from './cpmBucketManager'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -import { hook } from './hook'; const utils = require('./utils'); +const CONSTANTS = require('./constants'); -const DEFAULT_DEBUG = false; +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; @@ -231,7 +231,7 @@ export function newConfig() { * Sets configuration given an object containing key-value pairs and calls * listeners that were added by the `subscribe` function */ - let setConfig = hook('async', function setConfig(options) { + function setConfig(options) { if (typeof options !== 'object') { utils.logError('setConfig options must be an object'); return; @@ -251,7 +251,7 @@ export function newConfig() { }); callSubscribers(topicalConfig); - }); + } /** * Sets configuration defaults which setConfig values can be applied on top of diff --git a/src/utils.js b/src/utils.js index ea80e970786..162c7f1844f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,8 +5,6 @@ import includes from 'core-js/library/fn/array/includes'; import { parse } from './url'; const CONSTANTS = require('./constants'); -var _loggingChecked = false; - var tArr = 'Array'; var tStr = 'String'; var tFn = 'Function'; @@ -354,12 +352,6 @@ export function hasConsoleLogger() { } export function debugTurnedOn() { - if (config.getConfig('debug') === false && _loggingChecked === false) { - const debug = getParameterByName(CONSTANTS.DEBUG_MODE).toUpperCase() === 'TRUE'; - config.setConfig({ debug }); - _loggingChecked = true; - } - return !!config.getConfig('debug'); } diff --git a/test/spec/debugging_spec.js b/test/spec/debugging_spec.js index d07f7fc3373..e41e81439cd 100644 --- a/test/spec/debugging_spec.js +++ b/test/spec/debugging_spec.js @@ -3,6 +3,7 @@ import { expect } from 'chai'; import { sessionLoader, addBidResponseHook, getConfig, disableOverrides, boundHook } from 'src/debugging'; import { addBidResponse } from 'src/auction'; import { config } from 'src/config'; +import * as utils from 'src/utils'; describe('bid overrides', function () { let sandbox; @@ -13,6 +14,7 @@ describe('bid overrides', function () { afterEach(function () { window.sessionStorage.clear(); + config.resetConfig(); sandbox.restore(); }); diff --git a/test/spec/modules/emoteevBidAdapter_spec.js b/test/spec/modules/emoteevBidAdapter_spec.js index a5f5c439e6f..81f69a10ad3 100644 --- a/test/spec/modules/emoteevBidAdapter_spec.js +++ b/test/spec/modules/emoteevBidAdapter_spec.js @@ -319,31 +319,32 @@ describe('emoteevBidAdapter', function () { }); }); - describe('getUserSyncs', function () { - config.setConfig({emoteevEnv: PRODUCTION}); - expect(spec.getUserSyncs({ - iframeEnabled: true - }, [{}])).to.deep.equal([{ - type: 'iframe', - url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) - }]); - - expect(spec.getUserSyncs({ - pixelEnabled: true - }, [{}])).to.deep.equal([{ - type: 'image', - url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) - }]); - - expect(spec.getUserSyncs({ - iframeEnabled: true, - pixelEnabled: true - }, [{}])).to.deep.equal([{ - type: 'iframe', - url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) - }, { - type: 'image', - url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) - }]); - }); + // TODO: these tests need to be fixed, they were somehow dependent on setConfig queueing and not being set... + // describe('getUserSyncs', function () { + // config.setConfig({emoteevEnv: PRODUCTION}); + // expect(spec.getUserSyncs({ + // iframeEnabled: true + // }, [{}])).to.deep.equal([{ + // type: 'iframe', + // url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) + // }]); + // + // expect(spec.getUserSyncs({ + // pixelEnabled: true + // }, [{}])).to.deep.equal([{ + // type: 'image', + // url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) + // }]); + // + // expect(spec.getUserSyncs({ + // iframeEnabled: true, + // pixelEnabled: true + // }, [{}])).to.deep.equal([{ + // type: 'iframe', + // url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) + // }, { + // type: 'image', + // url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) + // }]); + // }); }); From 538d46d7038c935fc45268f69710c93debcf7df5 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Tue, 9 Apr 2019 13:57:07 -0400 Subject: [PATCH 1146/1594] Sonobi - Add ius param to bid request endpoint (#3657) * added param to sonobi bid request bid url that lets sonobi know if its ok to drop iframe pixels. * added case to isFilterConfigValid to check if it is falsey * fixed eslint issues. * refactor userSync checking if a bidder can drop a sync pixel to publicAPI function canBidderRegisterSync * fixed lint error --- modules/sonobiBidAdapter.js | 12 +++ sonobi_video.html | 0 src/userSync.js | 25 +++-- test/spec/modules/sonobiBidAdapter_spec.js | 19 ++++ test/spec/userSync_spec.js | 101 +++++++++++++++++++++ 5 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 sonobi_video.html diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 0d949fed25a..a82d19a485c 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -3,6 +3,7 @@ import { parseSizesInput, logError, generateUUID, isEmpty, deepAccess, logWarn, import { BANNER, VIDEO } from '../src/mediaTypes'; import { config } from '../src/config'; import { Renderer } from '../src/Renderer'; +import { userSync } from '../src/userSync'; const BIDDER_CODE = 'sonobi'; const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json'; @@ -62,6 +63,13 @@ export const spec = { payload.us = config.getConfig('userSync').syncsPerBidder; } + // use userSync's internal function to determine if we can drop an iframe sync pixel + if (_iframeAllowed()) { + payload.ius = 1; + } else { + payload.ius = 0; + } + if (deepAccess(validBidRequests[0], 'params.hfa')) { payload.hfa = deepAccess(validBidRequests[0], 'params.hfa'); } else if (deepAccess(validBidRequests[0], 'userId.pubcid')) { @@ -327,4 +335,8 @@ function outstreamRender(bid) { }); } +function _iframeAllowed() { + return userSync.canBidderRegisterSync('iframe', BIDDER_CODE); +} + registerBidder(spec); diff --git a/sonobi_video.html b/sonobi_video.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/userSync.js b/src/userSync.js index 8e0b919572e..3cbdc58a075 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -156,13 +156,9 @@ export function newUserSync(userSyncDependencies) { return utils.logWarn(`Number of user syncs exceeded for "${bidder}"`); } - if (usConfig.filterSettings) { - if (shouldBidderBeBlocked(type, bidder)) { - return utils.logWarn(`Bidder '${bidder}' is not permitted to register their userSync ${type} pixels as per filterSettings config.`); - } - // TODO remove this else if code that supports deprecated fields (sometime in 2.x); for now - only run if filterSettings config is not present - } else if (usConfig.enabledBidders && usConfig.enabledBidders.length && usConfig.enabledBidders.indexOf(bidder) < 0) { - return utils.logWarn(`Bidder "${bidder}" not permitted to register their userSync pixels.`); + const canBidderRegisterSync = publicApi.canBidderRegisterSync(type, bidder); + if (!canBidderRegisterSync) { + 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 @@ -262,6 +258,21 @@ export function newUserSync(userSyncDependencies) { } }; + publicApi.canBidderRegisterSync = (type, bidder) => { + if (usConfig.filterSettings) { + if (shouldBidderBeBlocked(type, bidder)) { + return false; + } + // TODO remove this else if code that supports deprecated fields (sometime in 2.x); for now - only run if filterSettings config is not present + } else if (usConfig.enabledBidders && usConfig.enabledBidders.length && usConfig.enabledBidders.indexOf(bidder) < 0) { + return false + } else if (type === 'iframe' && !(usConfig.iframeEnabled || permittedPixels.iframe)) { + return false; + } else if (type === 'image' && !(usConfig.pixelEnabled || permittedPixels.image)) { + return false; + } + return true; + } return publicApi; } diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 010d07f1c37..6a0729649fc 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -1,6 +1,7 @@ import { expect } from 'chai' import { spec, _getPlatform } from 'modules/sonobiBidAdapter' import { newBidder } from 'src/adapters/bidderFactory' +import {userSync} from '../../../src/userSync'; describe('SonobiBidAdapter', function () { const adapter = newBidder(spec) @@ -101,6 +102,12 @@ describe('SonobiBidAdapter', function () { }) describe('.buildRequests', function () { + beforeEach(function() { + sinon.stub(userSync, 'canBidderRegisterSync'); + }); + afterEach(function() { + userSync.canBidderRegisterSync.restore(); + }); let bidRequest = [{ 'bidder': 'sonobi', 'params': { @@ -318,6 +325,18 @@ describe('SonobiBidAdapter', function () { expect(bidRequests.data.s).not.to.be.empty expect(bidRequests.data.hfa).to.equal('hfakey') }) + + it('should set ius as 0 if Sonobi cannot drop iframe pixels', function () { + userSync.canBidderRegisterSync.returns(false); + const bidRequests = spec.buildRequests(bidRequest, bidderRequests); + expect(bidRequests.data.ius).to.equal(0); + }); + + it('should set ius as 1 if Sonobi can drop iframe pixels', function() { + userSync.canBidderRegisterSync.returns(true); + const bidRequests = spec.buildRequests(bidRequest, bidderRequests); + expect(bidRequests.data.ius).to.equal(1); + }); }) describe('.interpretResponse', function () { diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index dfe6372288f..f330be4c2f4 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -355,4 +355,105 @@ describe('user sync', function () { expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); expect(insertUserSyncIframeStub.getCall(0)).to.be.null; }); + + describe('publicAPI', function () { + describe('canBidderRegisterSync', function() { + describe('with filterSettings', function() { + it('should return false if filter settings does not allow it', function () { + const userSync = newUserSync({ + config: { + filterSettings: { + image: { + bidders: '*', + filter: 'include' + }, + iframe: { + bidders: ['testBidder'], + filter: 'include' + } + } + } + }); + expect(userSync.canBidderRegisterSync('iframe', 'otherTestBidder')).to.equal(false); + }); + it('should return true if filter settings does allow it', function () { + const userSync = newUserSync({ + config: { + filterSettings: { + image: { + bidders: '*', + filter: 'include' + }, + iframe: { + bidders: ['testBidder'], + filter: 'include' + } + } + } + }); + expect(userSync.canBidderRegisterSync('iframe', 'testBidder')).to.equal(true); + }); + }); + describe('almost deprecated - without filterSettings', function() { + describe('enabledBidders contains testBidder', function() { + it('should return false if type is iframe and iframeEnabled is false', function () { + const userSync = newUserSync({ + config: { + pixelEnabled: true, + iframeEnabled: false, + enabledBidders: ['testBidder'], + } + }); + expect(userSync.canBidderRegisterSync('iframe', 'testBidder')).to.equal(false); + }); + + it('should return true if type is iframe and iframeEnabled is true', function () { + const userSync = newUserSync({ + config: { + pixelEnabled: true, + iframeEnabled: true, + enabledBidders: ['testBidder'], + } + }); + expect(userSync.canBidderRegisterSync('iframe', 'testBidder')).to.equal(true); + }); + + it('should return false if type is image and pixelEnabled is false', function () { + const userSync = newUserSync({ + config: { + pixelEnabled: false, + iframeEnabled: true, + enabledBidders: ['testBidder'], + } + }); + expect(userSync.canBidderRegisterSync('image', 'testBidder')).to.equal(false); + }); + + it('should return true if type is image and pixelEnabled is true', function () { + const userSync = newUserSync({ + config: { + pixelEnabled: true, + iframeEnabled: true, + enabledBidders: ['testBidder'], + } + }); + expect(userSync.canBidderRegisterSync('image', 'testBidder')).to.equal(true); + }); + }); + + describe('enabledBidders does not container testBidder', function() { + it('should return false since testBidder is not in enabledBidders', function() { + const userSync = newUserSync({ + config: { + pixelEnabled: true, + iframeEnabled: true, + enabledBidders: ['otherTestBidder'], + } + }); + expect(userSync.canBidderRegisterSync('iframe', 'testBidder')).to.equal(false); + }); + }); + }); + }); + }); }); From 0af99c6151312a5f73e5639931282cd0436ad958 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Tue, 9 Apr 2019 21:08:16 +0300 Subject: [PATCH 1147/1594] Add support for getting video player size from playerSize property. (#3720) Add unit test. --- modules/cleanmedianetBidAdapter.js | 52 +++++++++++-------- .../modules/cleanmedianetBidAdapter_spec.js | 20 +++++++ 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/modules/cleanmedianetBidAdapter.js b/modules/cleanmedianetBidAdapter.js index 325b17ec543..00fb5aa5325 100644 --- a/modules/cleanmedianetBidAdapter.js +++ b/modules/cleanmedianetBidAdapter.js @@ -1,15 +1,15 @@ import * as utils from '../src/utils'; -import { parse } from '../src/url'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { config } from '../src/config'; -import { Renderer } from '../src/Renderer'; -import { BANNER, VIDEO } from '../src/mediaTypes'; +import {parse} from '../src/url'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {config} from '../src/config'; +import {Renderer} from '../src/Renderer'; +import {BANNER, VIDEO} from '../src/mediaTypes'; export const helper = { - startsWith: function(str, search) { + startsWith: function (str, search) { return str.substr(0, search.length) === search; }, - getMediaType: function(bid) { + getMediaType: function (bid) { if (bid.ext) { if (bid.ext.media_type) { return bid.ext.media_type.toLowerCase(); @@ -28,7 +28,7 @@ export const spec = { aliases: [], supportedMediaTypes: [BANNER, VIDEO], - isBidRequestValid: function(bid) { + isBidRequestValid: function (bid) { return ( !!bid.params.supplyPartnerId && typeof bid.params.supplyPartnerId === 'string' && @@ -44,7 +44,7 @@ export const spec = { ); }, - buildRequests: function(validBidRequests, bidderRequest) { + buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { const { adUnitCode, @@ -122,17 +122,27 @@ export const spec = { if (mediaTypes && mediaTypes.video) { if (!hasFavoredMediaType || params.favoredMediaType === VIDEO) { - const videoImp = Object.assign({}, imp, { + let videoImp = { video: { - w: sizes.length ? sizes[0][0] : 300, - h: sizes.length ? sizes[0][1] : 250, protocols: params.protocols || [1, 2, 3, 4, 5, 6], pos: params.pos || 0, - ext: { - context: mediaTypes.video.context - } + ext: {context: mediaTypes.video.context} } - }); + }; + + let playerSize = mediaTypes.video.playerSize || sizes; + if (utils.isArray(playerSize[0])) { + videoImp.video.w = playerSize[0][0]; + videoImp.video.h = playerSize[0][1]; + } else if (utils.isNumber(playerSize[0])) { + videoImp.video.w = playerSize[0]; + videoImp.video.h = playerSize[1]; + } else { + videoImp.video.w = 300; + videoImp.video.h = 250; + } + + videoImp = Object.assign({}, imp, videoImp); rtbBidRequest.imp.push(videoImp); } } @@ -150,7 +160,7 @@ export const spec = { }); }, - interpretResponse: function(serverResponse, bidRequest) { + interpretResponse: function (serverResponse, bidRequest) { const response = serverResponse && serverResponse.body; if (!response) { utils.logError('empty response'); @@ -185,7 +195,7 @@ export const spec = { ) ) { if (outBid.mediaType === BANNER) { - outBids.push(Object.assign({}, outBid, { ad: bid.adm })); + outBids.push(Object.assign({}, outBid, {ad: bid.adm})); } else if (outBid.mediaType === VIDEO) { const context = utils.deepAccess( bidRequest.bidRequest, @@ -207,7 +217,7 @@ export const spec = { return outBids; }, - getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { + getUserSyncs: function (syncOptions, serverResponses, gdprConsent) { const syncs = []; const gdprApplies = gdprConsent && typeof gdprConsent.gdprApplies === 'boolean' @@ -224,7 +234,7 @@ export const spec = { const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); - return syncs.push({ type: pixel.type, url }); + return syncs.push({type: pixel.type, url}); }); } if (Array.isArray(bidResponse.seatbid)) { @@ -238,7 +248,7 @@ export const spec = { (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); - return syncs.push({ type: pixel.type, url }); + return syncs.push({type: pixel.type, url}); }); } }); diff --git a/test/spec/modules/cleanmedianetBidAdapter_spec.js b/test/spec/modules/cleanmedianetBidAdapter_spec.js index d68505604bc..09f76806fd7 100644 --- a/test/spec/modules/cleanmedianetBidAdapter_spec.js +++ b/test/spec/modules/cleanmedianetBidAdapter_spec.js @@ -246,6 +246,26 @@ describe('CleanmedianetAdapter', function() { response = spec.buildRequests([bidRequestWithPosEquals2], bidRequest)[0]; expect(response.data.imp[0].video.ext.context).to.equal(null); }); + it('builds request video object correctly with multi-dimensions size array', function () { + let bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes.video = { + playerSize: [[304, 254], [305, 255]], + context: 'instream' + }; + + let response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[1].video.w).to.equal(304); + expect(response.data.imp[1].video.h).to.equal(254); + + bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes.video = { + playerSize: [304, 254] + }; + + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[1].video.w).to.equal(304); + expect(response.data.imp[1].video.h).to.equal(254); + }); it('builds request with gdpr consent', function() { let response = spec.buildRequests([bidRequest], bidRequest)[0]; From 40efe8a00ff0fe13cc1f58719cb71ec2f0f51ac8 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 10 Apr 2019 10:48:34 -0400 Subject: [PATCH 1148/1594] reject invalid values in adpod adunit (#3729) --- modules/adpod.js | 4 ++-- test/spec/modules/adpod_spec.js | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/modules/adpod.js b/modules/adpod.js index fe49c10e193..021d4722f53 100644 --- a/modules/adpod.js +++ b/modules/adpod.js @@ -256,8 +256,8 @@ export function checkAdUnitSetupHook(fn, adUnits) { let errMsg = `Detected missing or incorrectly setup fields for an adpod adUnit. Please review the following fields of adUnitCode: ${adUnit.code}. This adUnit will be removed from the auction.`; let playerSize = !!(videoConfig.playerSize && utils.isArrayOfNums(videoConfig.playerSize)); - let adPodDurationSec = !!(videoConfig.adPodDurationSec && utils.isNumber(videoConfig.adPodDurationSec)); - let durationRangeSec = !!(videoConfig.durationRangeSec && utils.isArrayOfNums(videoConfig.durationRangeSec)); + 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' : ''; diff --git a/test/spec/modules/adpod_spec.js b/test/spec/modules/adpod_spec.js index a47c77d25ac..507a3be9f14 100644 --- a/test/spec/modules/adpod_spec.js +++ b/test/spec/modules/adpod_spec.js @@ -689,6 +689,32 @@ describe('adpod.js', function () { expect(logWarnStub.calledOnce).to.equal(true); }); + it('removes an incorrectly setup adpod adunit - required fields are using invalid values', function() { + let adUnits = [{ + code: 'test1', + mediaTypes: { + video: { + context: ADPOD, + durationRangeSec: [-5, 15, 30, 45], + adPodDurationSec: 300 + } + } + }]; + + checkAdUnitSetupHook(callbackFn, adUnits); + + expect(results).to.deep.equal([]); + expect(logWarnStub.calledOnce).to.equal(true); + + adUnits[0].mediaTypes.video.durationRangeSec = [15, 30, 45]; + adUnits[0].mediaTypes.video.adPodDurationSec = 0; + + checkAdUnitSetupHook(callbackFn, adUnits); + + expect(results).to.deep.equal([]); + expect(logWarnStub.calledTwice).to.equal(true); + }); + it('removes an incorrectly setup adpod adunit - attempting to use multi-format adUnit', function() { let adUnits = [{ code: 'multi_test1', From cde8f166224b3c74b78f79bbf019367be8adf8e6 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 10 Apr 2019 16:02:15 -0400 Subject: [PATCH 1149/1594] Revert "Default debug change and remove setConfig hook (#3714)" (#3736) This reverts commit 0b1486e3e28a683a48cda1618cbf57a89bd082d5. --- src/config.js | 8 +-- src/utils.js | 8 +++ test/spec/debugging_spec.js | 2 - test/spec/modules/emoteevBidAdapter_spec.js | 55 ++++++++++----------- 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/config.js b/src/config.js index db47fee0687..a1a8af629d8 100644 --- a/src/config.js +++ b/src/config.js @@ -10,10 +10,10 @@ import { isValidPriceConfig } from './cpmBucketManager'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; +import { hook } from './hook'; const utils = require('./utils'); -const CONSTANTS = require('./constants'); -const DEFAULT_DEBUG = utils.getParameterByName(CONSTANTS.DEBUG_MODE).toUpperCase() === 'TRUE'; +const DEFAULT_DEBUG = false; const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; @@ -231,7 +231,7 @@ export function newConfig() { * Sets configuration given an object containing key-value pairs and calls * listeners that were added by the `subscribe` function */ - function setConfig(options) { + let setConfig = hook('async', function setConfig(options) { if (typeof options !== 'object') { utils.logError('setConfig options must be an object'); return; @@ -251,7 +251,7 @@ export function newConfig() { }); callSubscribers(topicalConfig); - } + }); /** * Sets configuration defaults which setConfig values can be applied on top of diff --git a/src/utils.js b/src/utils.js index 162c7f1844f..ea80e970786 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,6 +5,8 @@ import includes from 'core-js/library/fn/array/includes'; import { parse } from './url'; const CONSTANTS = require('./constants'); +var _loggingChecked = false; + var tArr = 'Array'; var tStr = 'String'; var tFn = 'Function'; @@ -352,6 +354,12 @@ export function hasConsoleLogger() { } export function debugTurnedOn() { + if (config.getConfig('debug') === false && _loggingChecked === false) { + const debug = getParameterByName(CONSTANTS.DEBUG_MODE).toUpperCase() === 'TRUE'; + config.setConfig({ debug }); + _loggingChecked = true; + } + return !!config.getConfig('debug'); } diff --git a/test/spec/debugging_spec.js b/test/spec/debugging_spec.js index e41e81439cd..d07f7fc3373 100644 --- a/test/spec/debugging_spec.js +++ b/test/spec/debugging_spec.js @@ -3,7 +3,6 @@ import { expect } from 'chai'; import { sessionLoader, addBidResponseHook, getConfig, disableOverrides, boundHook } from 'src/debugging'; import { addBidResponse } from 'src/auction'; import { config } from 'src/config'; -import * as utils from 'src/utils'; describe('bid overrides', function () { let sandbox; @@ -14,7 +13,6 @@ describe('bid overrides', function () { afterEach(function () { window.sessionStorage.clear(); - config.resetConfig(); sandbox.restore(); }); diff --git a/test/spec/modules/emoteevBidAdapter_spec.js b/test/spec/modules/emoteevBidAdapter_spec.js index 81f69a10ad3..a5f5c439e6f 100644 --- a/test/spec/modules/emoteevBidAdapter_spec.js +++ b/test/spec/modules/emoteevBidAdapter_spec.js @@ -319,32 +319,31 @@ describe('emoteevBidAdapter', function () { }); }); - // TODO: these tests need to be fixed, they were somehow dependent on setConfig queueing and not being set... - // describe('getUserSyncs', function () { - // config.setConfig({emoteevEnv: PRODUCTION}); - // expect(spec.getUserSyncs({ - // iframeEnabled: true - // }, [{}])).to.deep.equal([{ - // type: 'iframe', - // url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) - // }]); - // - // expect(spec.getUserSyncs({ - // pixelEnabled: true - // }, [{}])).to.deep.equal([{ - // type: 'image', - // url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) - // }]); - // - // expect(spec.getUserSyncs({ - // iframeEnabled: true, - // pixelEnabled: true - // }, [{}])).to.deep.equal([{ - // type: 'iframe', - // url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) - // }, { - // type: 'image', - // url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) - // }]); - // }); + describe('getUserSyncs', function () { + config.setConfig({emoteevEnv: PRODUCTION}); + expect(spec.getUserSyncs({ + iframeEnabled: true + }, [{}])).to.deep.equal([{ + type: 'iframe', + url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) + }]); + + expect(spec.getUserSyncs({ + pixelEnabled: true + }, [{}])).to.deep.equal([{ + type: 'image', + url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) + }]); + + expect(spec.getUserSyncs({ + iframeEnabled: true, + pixelEnabled: true + }, [{}])).to.deep.equal([{ + type: 'iframe', + url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) + }, { + type: 'image', + url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) + }]); + }); }); From 94897e4465ff1130f57c2435bc6401b5087c133b Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 10 Apr 2019 16:10:23 -0400 Subject: [PATCH 1150/1594] Prebid 2.10.0 Release --- package-lock.json | 360 +++++++++++++++++++++++++--------------------- package.json | 2 +- 2 files changed, 199 insertions(+), 163 deletions(-) diff --git a/package-lock.json b/package-lock.json index 00f5427b9f1..655363b9949 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.8.0", + "version": "2.10.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,17 +14,17 @@ } }, "@babel/core": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.0.tgz", - "integrity": "sha512-Dzl7U0/T69DFOTwqz/FJdnOSWS57NpjNfCwMKHABr589Lg8uX1RrlBIJ7L5Dubt/xkLsx0xH5EBFzlBVes1ayA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.3.tgz", + "integrity": "sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "@babel/generator": "^7.4.0", - "@babel/helpers": "^7.4.0", - "@babel/parser": "^7.4.0", + "@babel/helpers": "^7.4.3", + "@babel/parser": "^7.4.3", "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.0", + "@babel/traverse": "^7.4.3", "@babel/types": "^7.4.0", "convert-source-map": "^1.1.0", "debug": "^4.1.0", @@ -147,9 +147,9 @@ } }, "@babel/helper-module-transforms": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.2.2.tgz", - "integrity": "sha512-YRD7I6Wsv+IHuTPkAmAS4HhY0dkPobgLftHp0cRGZSdrRvmZY8rFvae/GVu3bD00qscuvK3WPHB3YdNpBXUqrA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.3.tgz", + "integrity": "sha512-H88T9IySZW25anu5uqyaC1DaQre7ofM+joZtAaO2F8NBdFfupH0SZ4gKjgSFVcvtx/aAirqA9L9Clio2heYbZA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -157,7 +157,7 @@ "@babel/helper-split-export-declaration": "^7.0.0", "@babel/template": "^7.2.2", "@babel/types": "^7.2.2", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/helper-optimise-call-expression": { @@ -176,12 +176,12 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", - "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.3.tgz", + "integrity": "sha512-hnoq5u96pLCfgjXuj8ZLX3QQ+6nAulS+zSgi6HulUwFbEruRAKwbGLU5OvXkE14L8XW6XsQEKsIDfgthKLRAyA==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/helper-remap-async-to-generator": { @@ -241,13 +241,13 @@ } }, "@babel/helpers": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.2.tgz", - "integrity": "sha512-gQR1eQeroDzFBikhrCccm5Gs2xBjZ57DNjGbqTaHo911IpmSxflOQWMAHPw/TXk8L3isv7s9lYzUkexOeTQUYg==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.3.tgz", + "integrity": "sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q==", "dev": true, "requires": { "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.0", + "@babel/traverse": "^7.4.3", "@babel/types": "^7.4.0" } }, @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.2.tgz", - "integrity": "sha512-9fJTDipQFvlfSVdD/JBtkiY0br9BtfvW2R8wo6CX/Ej2eMuV0gWPk1M67Mt3eggQvBqYW1FCEk8BN7WvGm/g5g==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", + "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -290,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.0.tgz", - "integrity": "sha512-uTNi8pPYyUH2eWHyYWWSYJKwKg34hhgl4/dbejEjL+64OhbHjTX7wEVWMQl82tEmdDsGeu77+s8HHLS627h6OQ==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.3.tgz", + "integrity": "sha512-xC//6DNSSHVjq8O2ge0dyYlhshsH4T7XdCVoxbi5HzLYWfsC5ooFlJjrXk8RcAT+hjHAK9UjBXdylzSoDK3t4g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -396,9 +396,9 @@ } }, "@babel/plugin-transform-classes": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.0.tgz", - "integrity": "sha512-XGg1Mhbw4LDmrO9rSTNe+uI79tQPdGs0YASlxgweYRLZqo/EQktjaOV4tchL/UZbM0F+/94uOipmdNGoaGOEYg==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.3.tgz", + "integrity": "sha512-PUaIKyFUDtG6jF5DUJOfkBdwAS/kFFV3XFk7Nn0a6vR7ZT8jYw5cGtIlat77wcnd0C6ViGqo/wyNf4ZHytF/nQ==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -421,23 +421,23 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.0.tgz", - "integrity": "sha512-HySkoatyYTY3ZwLI8GGvkRWCFrjAGXUHur5sMecmCIdIharnlcWWivOqDJI76vvmVZfzwb6G08NREsrY96RhGQ==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.3.tgz", + "integrity": "sha512-rVTLLZpydDFDyN4qnXdzwoVpk1oaXHIvPEOkOLyr88o7oHxVc/LyrnDx+amuBWGOwUb7D1s/uLsKBNTx08htZg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz", - "integrity": "sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.3.tgz", + "integrity": "sha512-9Arc2I0AGynzXRR/oPdSALv3k0rM38IMFyto7kOCwb5F9sLUt2Ykdo3V9yUPR+Bgr4kb6bVEyLkPEiBhzcTeoA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" + "@babel/helper-regex": "^7.4.3", + "regexpu-core": "^4.5.4" } }, "@babel/plugin-transform-duplicate-keys": { @@ -460,18 +460,18 @@ } }, "@babel/plugin-transform-for-of": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.0.tgz", - "integrity": "sha512-vWdfCEYLlYSxbsKj5lGtzA49K3KANtb8qCPQ1em07txJzsBwY+cKJzBHizj5fl3CCx7vt+WPdgDLTHmydkbQSQ==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.3.tgz", + "integrity": "sha512-UselcZPwVWNSURnqcfpnxtMehrb8wjXYOimlYQPBnup/Zld426YzIhNEvuRsEWVHfESIECGrxoI6L5QqzuLH5Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-function-name": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz", - "integrity": "sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.3.tgz", + "integrity": "sha512-uT5J/3qI/8vACBR9I1GlAuU/JqBtWdfCrynuOkrWG6nCDieZd5przB1vfP59FRHBZQ9DC2IUfqr/xKqzOD5x0A==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -487,6 +487,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", + "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-transform-modules-amd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", @@ -498,12 +507,12 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.0.tgz", - "integrity": "sha512-iWKAooAkipG7g1IY0eah7SumzfnIT3WNhT4uYB2kIsvHnNSB6MDYVa5qyICSwaTBDBY2c4SnJ3JtEa6ltJd6Jw==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.3.tgz", + "integrity": "sha512-sMP4JqOTbMJMimqsSZwYWsMjppD+KRyDIUVW91pd7td0dZKAvPmhCaxhOzkzLParKwgQc7bdL9UNv+rpJB0HfA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-module-transforms": "^7.4.3", "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-simple-access": "^7.1.0" } @@ -557,9 +566,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.0.tgz", - "integrity": "sha512-Xqv6d1X+doyiuCGDoVJFtlZx0onAX0tnc3dY8w71pv/O0dODAbusVv2Ale3cGOwfiyi895ivOBhYa9DhAM8dUA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.3.tgz", + "integrity": "sha512-ULJYC2Vnw96/zdotCZkMGr2QVfKpIT/4/K+xWWY0MbOJyMZuk660BGkr3bEKWQrrciwz6xpmft39nA4BF7hJuA==", "dev": true, "requires": { "@babel/helper-call-delegate": "^7.4.0", @@ -567,15 +576,33 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-property-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", + "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-transform-regenerator": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.0.tgz", - "integrity": "sha512-SZ+CgL4F0wm4npojPU6swo/cK4FcbLgxLd4cWpHaNXY/NJ2dpahODCqBbAwb2rDmVszVb3SSjnk9/vik3AYdBw==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.3.tgz", + "integrity": "sha512-kEzotPuOpv6/iSlHroCDydPkKYw7tiJGKlmYp6iJn4a6C/+b2FdttlJsLKYxolYHgotTJ5G5UY5h0qey5ka3+A==", "dev": true, "requires": { "regenerator-transform": "^0.13.4" } }, + "@babel/plugin-transform-reserved-words": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", + "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-transform-shorthand-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", @@ -624,27 +651,27 @@ } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz", - "integrity": "sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.3.tgz", + "integrity": "sha512-lnSNgkVjL8EMtnE8eSS7t2ku8qvKH3eqNf/IwIfnSPUqzgqYmRwzdsQWv4mNQAN9Nuo6Gz1Y0a4CSmdpu1Pp6g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" + "@babel/helper-regex": "^7.4.3", + "regexpu-core": "^4.5.4" } }, "@babel/preset-env": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.2.tgz", - "integrity": "sha512-OEz6VOZaI9LW08CWVS3d9g/0jZA6YCn1gsKIy/fut7yZCJti5Lm1/Hi+uo/U+ODm7g4I6gULrCP+/+laT8xAsA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.3.tgz", + "integrity": "sha512-FYbZdV12yHdJU5Z70cEg0f6lvtpZ8jFSDakTm7WXeJbLXh4R0ztGEu/SW7G1nJ2ZvKwDhz8YrbA84eYyprmGqw==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.0", + "@babel/plugin-proposal-object-rest-spread": "^7.4.3", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.0", "@babel/plugin-syntax-async-generators": "^7.2.0", @@ -655,36 +682,39 @@ "@babel/plugin-transform-async-to-generator": "^7.4.0", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", "@babel/plugin-transform-block-scoping": "^7.4.0", - "@babel/plugin-transform-classes": "^7.4.0", + "@babel/plugin-transform-classes": "^7.4.3", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.0", - "@babel/plugin-transform-dotall-regex": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.4.3", + "@babel/plugin-transform-dotall-regex": "^7.4.3", "@babel/plugin-transform-duplicate-keys": "^7.2.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.0", - "@babel/plugin-transform-function-name": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.4.3", + "@babel/plugin-transform-function-name": "^7.4.3", "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-member-expression-literals": "^7.2.0", "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.0", + "@babel/plugin-transform-modules-commonjs": "^7.4.3", "@babel/plugin-transform-modules-systemjs": "^7.4.0", "@babel/plugin-transform-modules-umd": "^7.2.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.2", "@babel/plugin-transform-new-target": "^7.4.0", "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.4.0", - "@babel/plugin-transform-regenerator": "^7.4.0", + "@babel/plugin-transform-parameters": "^7.4.3", + "@babel/plugin-transform-property-literals": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.4.3", + "@babel/plugin-transform-reserved-words": "^7.2.0", "@babel/plugin-transform-shorthand-properties": "^7.2.0", "@babel/plugin-transform-spread": "^7.2.0", "@babel/plugin-transform-sticky-regex": "^7.2.0", "@babel/plugin-transform-template-literals": "^7.2.0", "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.4.3", "@babel/types": "^7.4.0", - "browserslist": "^4.4.2", + "browserslist": "^4.5.2", "core-js-compat": "^3.0.0", "invariant": "^2.2.2", "js-levenshtein": "^1.1.3", - "semver": "^5.3.0" + "semver": "^5.5.0" } }, "@babel/template": { @@ -699,16 +729,16 @@ } }, "@babel/traverse": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.0.tgz", - "integrity": "sha512-/DtIHKfyg2bBKnIN+BItaIlEg5pjAnzHOIQe5w+rHAw/rg9g0V7T4rqPX8BJPfW11kt3koyjAnTNwCzb28Y1PA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz", + "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "@babel/generator": "^7.4.0", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.0", - "@babel/parser": "^7.4.0", + "@babel/parser": "^7.4.3", "@babel/types": "^7.4.0", "debug": "^4.1.0", "globals": "^11.1.0", @@ -1267,9 +1297,9 @@ "dev": true }, "ast-types": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.12.2.tgz", - "integrity": "sha512-8c83xDLJM/dLDyXNLiR6afRRm4dPKN6KAnKqytRK3DBJul9lA+atxdQkNDkSVPdTqea5HiRq3lnnOIZ0MBpvdg==", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.12.3.tgz", + "integrity": "sha512-wJUcAfrdW+IgDoMGNz5MmcvahKgB7BwIbLupdKVVHxHNYt+HVR2k35swdYNv9aZpF8nvlkjbnkp2rrNwxGckZA==", "dev": true }, "async": { @@ -2607,9 +2637,9 @@ "dev": true }, "binary-extensions": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", - "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true }, "binaryextensions": { @@ -2625,9 +2655,9 @@ "dev": true }, "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", + "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==", "dev": true }, "bn.js": { @@ -2850,14 +2880,14 @@ } }, "browserslist": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.2.tgz", - "integrity": "sha512-zmJVLiKLrzko0iszd/V4SsjTaomFeoVzQGYYOYgRgsbh7WNh95RgDB0CmBdFWYs/3MyFSt69NypjL/h3iaddKQ==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.4.tgz", + "integrity": "sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000951", - "electron-to-chromium": "^1.3.116", - "node-releases": "^1.1.11" + "caniuse-lite": "^1.0.30000955", + "electron-to-chromium": "^1.3.122", + "node-releases": "^1.1.13" } }, "browserstack": { @@ -3088,9 +3118,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000953", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000953.tgz", - "integrity": "sha512-2stdF/q5MZTDhQ6uC65HWbSgI9UMKbc7+HKvlwH5JBIslKoD/J9dvabP4J4Uiifu3NljbHj3iMpfYflLSNt09A==", + "version": "1.0.30000957", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000957.tgz", + "integrity": "sha512-8wxNrjAzyiHcLXN/iunskqQnJquQQ6VX8JHfW5kLgAPRSiSuKZiNfmIkP5j7jgyXqAQBSoXyJxfnbCFS0ThSiQ==", "dev": true }, "caseless": { @@ -3595,29 +3625,35 @@ "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" }, "core-js-compat": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.0.0.tgz", - "integrity": "sha512-W/Ppz34uUme3LmXWjMgFlYyGnbo1hd9JvA0LNQ4EmieqVjg2GPYbj3H6tcdP2QGPGWdRKUqZVbVKLNIFVs/HiA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.0.1.tgz", + "integrity": "sha512-2pC3e+Ht/1/gD7Sim/sqzvRplMiRnFQVlPpDVaHtY9l7zZP7knamr3VRD6NyGfHd84MrDC0tAM9ulNxYMW0T3g==", "dev": true, "requires": { - "browserslist": "^4.5.1", - "core-js": "3.0.0", - "core-js-pure": "3.0.0", - "semver": "^5.6.0" + "browserslist": "^4.5.4", + "core-js": "3.0.1", + "core-js-pure": "3.0.1", + "semver": "^6.0.0" }, "dependencies": { "core-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0.tgz", - "integrity": "sha512-WBmxlgH2122EzEJ6GH8o9L/FeoUKxxxZ6q6VUxoTlsE4EvbTWKJb447eyVxTEuq0LpXjlq/kCB2qgBvsYRkLvQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", + "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", + "dev": true + }, + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", "dev": true } } }, "core-js-pure": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.0.0.tgz", - "integrity": "sha512-yPiS3fQd842RZDgo/TAKGgS0f3p2nxssF1H65DIZvZv0Od5CygP8puHXn3IQiM/39VAvgCbdaMQpresrbGgt9g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.0.1.tgz", + "integrity": "sha512-mSxeQ6IghKW3MoyF4cz19GJ1cMm7761ON+WObSyLfTu/Jn3x7w4NwNFnrZxgl4MTSvYYepVLNuRtlB4loMwJ5g==", "dev": true }, "core-util-is": { @@ -3766,9 +3802,9 @@ } }, "data-uri-to-buffer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.0.tgz", - "integrity": "sha512-YbKCNLPPP4inc0E5If4OaalBc7gpaM2MRv77Pv2VThVComLKfbGYtJcdDCViDyp1Wd4SebhHLz94vp91zbK6bw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.1.tgz", + "integrity": "sha512-OkVVLrerfAKZlW2ZZ3Ve2y65jgiWqBKsTfUIAFbn8nVbPcCZg6l6gikKlEYv0kXcmzqGm6mFq/Jf2vriuEkv8A==", "dev": true, "requires": { "@types/node": "^8.0.7" @@ -4429,9 +4465,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.119", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.119.tgz", - "integrity": "sha512-3mtqcAWa4HgG+Djh/oNXlPH0cOH6MmtwxN1nHSaReb9P0Vn51qYPqYwLeoSuAX9loU1wrOBhFbiX3CkeIxPfgg==", + "version": "1.3.124", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz", + "integrity": "sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w==", "dev": true }, "elliptic": { @@ -4639,9 +4675,9 @@ } }, "es5-shim": { - "version": "4.5.12", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.12.tgz", - "integrity": "sha512-MjoCAHE6P2Dirme70Cxd9i2Ng8rhXiaVSsxDWdSwimfLERJL/ypR2ed2rTYkeeYrMk8gq281dzKLiGcdrmc8qg==", + "version": "4.5.13", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.13.tgz", + "integrity": "sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw==", "dev": true }, "es6-iterator": { @@ -6536,9 +6572,9 @@ }, "dependencies": { "readable-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", - "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", + "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -8316,9 +8352,9 @@ } }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "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" @@ -8780,9 +8816,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", - "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -8935,9 +8971,9 @@ }, "dependencies": { "mime": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", + "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==", "dev": true }, "rimraf": { @@ -8967,9 +9003,9 @@ } }, "karma-browserstack-launcher": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.5.0.tgz", - "integrity": "sha512-WFJaVwF+1DAgdS81Kbv1/UG1eIfEEzlt9CWLqzm306/MqrIYOxjUVmOdXrEpCefDR7gTl6CQ5Ym+t8RwUPGvJQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.5.1.tgz", + "integrity": "sha512-zt9Ukow5A9WZHZXCFVO/h5kRsAdaZYeMNJK9Uan8v42amQXt3B/DZVxl24NCcAIxufKjW13UWd9iJ9knG9OCYw==", "dev": true, "requires": { "browserstack": "~1.5.1", @@ -10578,9 +10614,9 @@ } }, "node-releases": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.11.tgz", - "integrity": "sha512-8v1j5KfP+s5WOTa1spNUAOfreajQPN12JXbRR0oDE+YrJBQCXBnNqUDj27EKpPLOoSiU3tKi3xGPB+JaOdUEQQ==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.14.tgz", + "integrity": "sha512-d58EpVZRhQE60kWiWUaaPlK9dyC4zg3ZoMcHcky2d4hDksyQj0rUozwInOl0C66mBsqo01Tuns8AvxnL5S7PKg==", "dev": true, "requires": { "semver": "^5.3.0" @@ -10626,9 +10662,9 @@ } }, "now-and-later": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", - "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "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, "requires": { "once": "^1.3.2" @@ -10705,9 +10741,9 @@ } }, "object-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", - "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, "object-visit": { @@ -11123,9 +11159,9 @@ } }, "p-try": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", - "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "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 }, "pac-proxy-agent": { @@ -12443,9 +12479,9 @@ } }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "semver-greatest-satisfied-range": { @@ -13035,9 +13071,9 @@ } }, "spdx-license-ids": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", - "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", "dev": true }, "split": { @@ -13729,19 +13765,19 @@ "dev": true }, "uglify-js": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.2.tgz", - "integrity": "sha512-imog1WIsi9Yb56yRt5TfYVxGmnWs3WSGU73ieSOlMVFwhJCA9W8fqFFMMj4kgDqiS/80LGdsYnWL7O9UcjEBlg==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.4.tgz", + "integrity": "sha512-GpKo28q/7Bm5BcX9vOu4S46FwisbPbAmkkqPnGIpKvKTM96I85N6XHQV+k4I6FA2wxgLhcsSyHoNhzucwCflvA==", "dev": true, "requires": { - "commander": "~2.19.0", + "commander": "~2.20.0", "source-map": "~0.6.1" }, "dependencies": { "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true }, "source-map": { @@ -13836,9 +13872,9 @@ "dev": true }, "undertaker": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", - "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", "dev": true, "requires": { "arr-flatten": "^1.0.1", @@ -14707,9 +14743,9 @@ }, "dependencies": { "mime": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", + "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==", "dev": true } } diff --git a/package.json b/package.json index c46c75c4dce..47ff222f09e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.10.0-pre", + "version": "2.10.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b7bd1eda910108789c8d53d3bd87c3351f3d9182 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 10 Apr 2019 16:19:37 -0400 Subject: [PATCH 1151/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 47ff222f09e..79aa74cfa28 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.10.0", + "version": "2.11.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 481c79a97702de56502ab973a2a8579885599c02 Mon Sep 17 00:00:00 2001 From: nwlosinski Date: Thu, 11 Apr 2019 14:38:08 +0200 Subject: [PATCH 1152/1594] removed depricated function and added referer to request (#3728) --- modules/justpremiumBidAdapter.js | 6 ++---- test/spec/modules/justpremiumBidAdapter_spec.js | 15 ++++++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index b5a2a5ac120..6fbf5454b91 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -1,9 +1,8 @@ import { registerBidder } from '../src/adapters/bidderFactory' -import { getTopWindowLocation } from '../src/utils' const BIDDER_CODE = 'justpremium' const ENDPOINT_URL = '//pre.ads.justpremium.com/v/2.0/t/xhr' -const JP_ADAPTER_VERSION = '1.3' +const JP_ADAPTER_VERSION = '1.4' const pixels = [] const TRACK_START_TIME = Date.now() let LAST_PAYLOAD = {} @@ -31,8 +30,7 @@ export const spec = { }).filter((value, index, self) => { return self.indexOf(value) === index }), - hostname: getTopWindowLocation().hostname, - protocol: getTopWindowLocation().protocol.replace(':', ''), + referer: bidderRequest.refererInfo.referer, sw: dim.screenWidth, sh: dim.screenHeight, ww: dim.innerWidth, diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index 8167c29e5c2..feaf593fe25 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -33,6 +33,12 @@ describe('justpremium adapter', function () { }, ] + let bidderRequest = { + refererInfo: { + referer: 'http://justpremium.com' + } + } + describe('isBidRequestValid', function () { it('Verifies bidder code', function () { expect(spec.code).to.equal('justpremium') @@ -48,15 +54,14 @@ describe('justpremium adapter', function () { describe('buildRequests', function () { it('Verify build request and parameters', function () { - const request = spec.buildRequests(adUnits) + const request = spec.buildRequests(adUnits, bidderRequest) expect(request.method).to.equal('POST') expect(request.url).to.match(/pre.ads.justpremium.com\/v\/2.0\/t\/xhr/) const jpxRequest = JSON.parse(request.data) expect(jpxRequest).to.not.equal(null) expect(jpxRequest.zone).to.not.equal('undefined') - expect(jpxRequest.hostname).to.equal(top.document.location.hostname) - expect(jpxRequest.protocol).to.equal(top.document.location.protocol.replace(':', '')) + expect(bidderRequest.refererInfo.referer).to.equal('http://justpremium.com') expect(jpxRequest.sw).to.equal(window.top.screen.width) expect(jpxRequest.sh).to.equal(window.top.screen.height) expect(jpxRequest.ww).to.equal(window.top.innerWidth) @@ -65,12 +70,12 @@ describe('justpremium adapter', function () { expect(jpxRequest.id).to.equal(adUnits[0].params.zone) expect(jpxRequest.sizes).to.not.equal('undefined') expect(jpxRequest.version.prebid).to.equal('$prebid.version$') - expect(jpxRequest.version.jp_adapter).to.equal('1.3') + expect(jpxRequest.version.jp_adapter).to.equal('1.4') }) }) describe('interpretResponse', function () { - const request = spec.buildRequests(adUnits) + const request = spec.buildRequests(adUnits, bidderRequest) it('Verify server response', function () { let response = { 'bid': { From a55528a8585755d7a7bd189e7ccc367d29fc60f7 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Thu, 11 Apr 2019 15:50:09 +0300 Subject: [PATCH 1153/1594] Gamoshi: Fix video player size (#3718) * Add support for multi-format ad units. Add favoredMediaType property to params. * Add tests for gdpr consent. * Add adId to outbids * Modify media type resolving * Refactor multi-format ad units handler. * Fix video player size to take values from video ad definition. Add test for video playerSize. --- modules/gamoshiBidAdapter.js | 5 ++-- test/spec/modules/gamoshiBidAdapter_spec.js | 29 ++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 307f2d8bc91..c831f4db522 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -114,10 +114,11 @@ export const spec = { if (mediaTypes && mediaTypes.video) { if (!hasFavoredMediaType || params.favoredMediaType === VIDEO) { + const playerSize = mediaTypes.video.playerSize; const videoImp = Object.assign({}, imp, { video: { - w: sizes.length ? sizes[0][0] : 300, - h: sizes.length ? sizes[0][1] : 250, + w: playerSize ? playerSize[0][0] : 300, + h: playerSize ? playerSize[0][1] : 250, protocols: params.protocols || [1, 2, 3, 4, 5, 6], pos: params.pos || 0, ext: { diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index 896271be4d3..b657dac34b6 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -166,12 +166,12 @@ describe('GamoshiAdapter', function () { const bidRequestWithVideo = utils.deepClone(bidRequest); bidRequestWithVideo.mediaTypes = { video: { - sizes: [[300, 250], [120, 600]] + playerSize: [302, 252] } }; response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; - expect(response.data.imp[0].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][0]); - expect(response.data.imp[0].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][1]); + expect(response.data.imp[0].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.playerSize[0][0]); + expect(response.data.imp[0].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.playerSize[0][1]); expect(response.data.imp[0].video.pos).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); bidRequestWithPosEquals1.params.pos = 1; @@ -202,6 +202,29 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].video.ext.context).to.equal(null); }); + it('builds request video object correctly with multi-dimensions size array', function () { + let response; + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes.video = { + playerSize: [[304, 254], [305, 255]], + context: 'instream' + }; + + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[1].video.ext.context).to.equal('instream'); + bidRequestWithVideo.mediaTypes.video.context = 'outstream'; + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.mediaTypes.video.context = 'outstream'; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; + expect(response.data.imp[1].video.ext.context).to.equal('outstream'); + + const bidRequestWithPosEquals2 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals2.mediaTypes.video.context = null; + response = spec.buildRequests([bidRequestWithPosEquals2], bidRequest)[0]; + expect(response.data.imp[1].video.ext.context).to.equal(null); + }); + it('builds request with gdpr consent', function () { let response = spec.buildRequests([bidRequest], bidRequest)[0]; expect(response.data.ext).to.have.property('gdpr_consent'); From 8a5fb798ee45e2aed4cb5119757e392f94df146a Mon Sep 17 00:00:00 2001 From: Claudio Herrera <35111171+thesuperhomie@users.noreply.github.com> Date: Thu, 11 Apr 2019 06:06:44 -0700 Subject: [PATCH 1154/1594] Update og:url param key (#3732) --- modules/gumgumBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 98bf6b17552..8c2b6415505 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -56,7 +56,7 @@ function _getBrowserParams() { ce: utils.cookiesAreEnabled(), dpr: topWindow.devicePixelRatio || 1, jcsi: JSON.stringify({ t: 0, rq: 8 }), - og_url: getOgURL() + ogu: getOgURL() } ns = getNetworkSpeed() From 220f80fbf8b03f434238b4493755ae55bd241b04 Mon Sep 17 00:00:00 2001 From: onlsol <48312668+onlsol@users.noreply.github.com> Date: Thu, 11 Apr 2019 22:22:20 +0400 Subject: [PATCH 1155/1594] add stv adapter (#3737) * add stv adapter * remove comments from adapter file --- modules/stvBidAdapter.js | 150 ++++++++++++++++++++++++ modules/stvBidAdapter.md | 43 +++++++ test/spec/modules/stvBidAdapter_spec.js | 138 ++++++++++++++++++++++ 3 files changed, 331 insertions(+) create mode 100644 modules/stvBidAdapter.js create mode 100644 modules/stvBidAdapter.md create mode 100644 test/spec/modules/stvBidAdapter_spec.js diff --git a/modules/stvBidAdapter.js b/modules/stvBidAdapter.js new file mode 100644 index 00000000000..ac655f2013d --- /dev/null +++ b/modules/stvBidAdapter.js @@ -0,0 +1,150 @@ + +import * as utils from '../src/utils'; +import {config} from '../src/config'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; + +const BIDDER_CODE = 'stv'; +const VADS_ENDPOINT_URL = 'https://ads.smartstream.tv/r/'; +const DEFAULT_VIDEO_SOURCE = 'vads'; +const DEFAULT_BANNER_FORMAT = 'vast2'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['vads'], + supportedMediaTypes: [BANNER, VIDEO], + isBidRequestValid: function(bid) { + return !!(bid.params.placement); + }, + buildRequests: function(validBidRequests, bidderRequest) { + return validBidRequests.map(bidRequest => { + const params = bidRequest.params; + + const videoData = utils.deepAccess(bidRequest, 'mediaTypes.video') || {}; + const sizes = utils.parseSizesInput(videoData.playerSize || bidRequest.sizes)[0]; + const width = sizes.split('x')[0]; + const height = sizes.split('x')[1]; + + const placementId = params.placement; + + const rnd = Math.floor(Math.random() * 99999999999); + const referrer = encodeURIComponent(bidderRequest.refererInfo.referer); + const bidId = bidRequest.bidId; + let endpoint = VADS_ENDPOINT_URL; + + let payload = {}; + if (isVideoRequest(bidRequest)) { + const source = params.source || DEFAULT_VIDEO_SOURCE; + if (source === 'vads') { + payload = { + _f: 'vast2', + alternative: 'prebid_js', + _ps: placementId, + srw: width, + srh: height, + idt: 100, + rnd: rnd, + ref: referrer, + bid_id: bidId, + }; + endpoint = VADS_ENDPOINT_URL; + } + } else { + const outputFormat = params.format || DEFAULT_BANNER_FORMAT; + payload = { + _f: outputFormat, + alternative: 'prebid_js', + inventory_item_id: placementId, + srw: width, + srh: height, + idt: 100, + rnd: rnd, + ref: referrer, + bid_id: bidId, + }; + } + prepareExtraParams(params, payload); + + return { + method: 'GET', + url: endpoint, + data: objectToQueryString(payload), + } + }); + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + const response = serverResponse.body; + const crid = response.crid || 0; + const cpm = response.cpm / 1000000 || 0; + if (cpm !== 0 && crid !== 0) { + const dealId = response.dealid || ''; + const currency = response.currency || 'EUR'; + const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; + const bidResponse = { + requestId: response.bid_id, + cpm: cpm, + width: response.width, + height: response.height, + creativeId: crid, + dealId: dealId, + currency: currency, + netRevenue: netRevenue, + ttl: config.getConfig('_bidderTimeout') + }; + + if (response.vastXml) { + bidResponse.vastXml = response.vastXml; + bidResponse.mediaType = 'video'; + } else { + bidResponse.ad = response.adTag; + } + + bidResponses.push(bidResponse); + } + return bidResponses; + } +} + +function objectToQueryString(obj, prefix) { + let str = []; + let p; + for (p in obj) { + if (obj.hasOwnProperty(p)) { + let k = prefix ? prefix + '[' + p + ']' : p; + let v = obj[p]; + str.push((v !== null && typeof v === 'object') + ? objectToQueryString(v, k) + : encodeURIComponent(k) + '=' + (k == '_ps' ? v : encodeURIComponent(v))); + } + } + return str.join('&'); +} + +/** + * Check if it's a video bid request + * + * @param {BidRequest} bid - Bid request generated from ad slots + * @returns {boolean} True if it's a video bid + */ +function isVideoRequest(bid) { + return bid.mediaType === 'video' || !!utils.deepAccess(bid, 'mediaTypes.video'); +} + +function prepareExtraParams(params, payload) { + if (params.pfilter !== undefined) { + payload.pfilter = params.pfilter; + } + if (params.bcat !== undefined) { + payload.bcat = params.bcat; + } + if (params.noskip !== undefined) { + payload.noskip = params.noskip; + } + + if (params.dvt !== undefined) { + payload.dvt = params.dvt; + } +} + +registerBidder(spec); diff --git a/modules/stvBidAdapter.md b/modules/stvBidAdapter.md new file mode 100644 index 00000000000..79e958c3bba --- /dev/null +++ b/modules/stvBidAdapter.md @@ -0,0 +1,43 @@ +# Overview + +``` +Module Name: STV Video Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@dspx.tv +``` + +# Description + +STV video adapter for Prebid.js 1.x + +# Parameters +``` + var adUnits = [ + { + // video settings + code: 'video-obj', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [ + { + bidder: "stv", + params: { + placement: "", // placement ID of inventory with STV + noskip: 1, // 0 or 1 + pfilter: {/* + min_duration: 10, // min duration + max_duration: 30, // max duration + min_bitrate: 300, // min bitrate + max_bitrate: 1600, // max bitrate + */} + } + } + ] + } + ]; +``` + diff --git a/test/spec/modules/stvBidAdapter_spec.js b/test/spec/modules/stvBidAdapter_spec.js new file mode 100644 index 00000000000..72ea428304a --- /dev/null +++ b/test/spec/modules/stvBidAdapter_spec.js @@ -0,0 +1,138 @@ +import { expect } from 'chai'; +import { spec } from 'modules/stvBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const VADS_ENDPOINT_URL = 'https://ads.smartstream.tv/r/'; + +describe('stvAdapter', function () { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'stv', + 'params': { + 'placement': '6682', + 'pfilter': { + 'floorprice': 1000000 + }, + 'bcat': 'IAB2,IAB4', + 'dvt': 'desktop' + }, + 'sizes': [ + [300, 250] + ], + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'someIncorrectParam': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [{ + 'bidder': 'stv', + 'params': { + 'source': 'vads', + 'placement': 'prer0-0%3D4137', + 'pfilter': { + 'min_duration': 1, + 'max_duration': 100, + 'min_bitrate': 32, + 'max_bitrate': 128, + }, + 'noskip': 1 + }, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'context': 'instream' + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + let bidderRequest = { + refererInfo: { + referer: 'some_referrer.net' + } + } + + const request = spec.buildRequests(bidRequests, bidderRequest); + it('sends bid video request to our vads endpoint via GET', function () { + expect(request[0].method).to.equal('GET'); + let data = request[0].data.replace(/rnd=\d+\&/g, '').replace(/ref=.*\&bid/g, 'bid'); + expect(data).to.equal('_f=vast2&alternative=prebid_js&_ps=prer0-0%3D4137&srw=640&srh=480&idt=100&bid_id=30b31c1838de1e&pfilter%5Bmin_duration%5D=1&pfilter%5Bmax_duration%5D=100&pfilter%5Bmin_bitrate%5D=32&pfilter%5Bmax_bitrate%5D=128&noskip=1'); + }); + }); + + describe('interpretResponse', function () { + let vadsServerVideoResponse = { + 'body': { + 'cpm': 5000000, + 'crid': 100500, + 'width': '300', + 'height': '250', + 'vastXml': '{"reason":7001,"status":"accepted"}', + 'requestId': '220ed41385952a', + 'currency': 'EUR', + 'ttl': 60, + 'netRevenue': true, + 'zone': '6682' + } + }; + + let expectedResponse = [{ + requestId: '23beaa6af6cdde', + cpm: 0.5, + width: 0, + height: 0, + creativeId: 100500, + dealId: '', + currency: 'EUR', + netRevenue: true, + ttl: 300, + vastXml: '{"reason":7001,"status":"accepted"}', + mediaType: 'video' + }]; + + it('should get the correct vads video bid response by display ad', function () { + let bidRequest = [{ + 'method': 'GET', + 'url': VADS_ENDPOINT_URL, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'context': 'instream' + } + }, + 'data': { + 'bid_id': '30b31c1838de1e' + } + }]; + let result = spec.interpretResponse(vadsServerVideoResponse, bidRequest[0]); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles empty bid response', function () { + let response = { + body: {} + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From f9eca7787dff0013294a85fe7b07a4c1088547c5 Mon Sep 17 00:00:00 2001 From: kusapan Date: Sat, 13 Apr 2019 04:40:46 +0900 Subject: [PATCH 1156/1594] YIELDONE adapter - add outstream video renderer (#3655) * add video renderer * change priority of size params of bidrequest * video js change to production * add unit test --- modules/yieldoneBidAdapter.js | 36 +++++++++++++++++--- test/spec/modules/yieldoneBidAdapter_spec.js | 9 ++++- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index 7abb94736df..1e6abf22838 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -1,11 +1,13 @@ import * as utils from '../src/utils'; import {config} from '../src/config'; import {registerBidder} from '../src/adapters/bidderFactory'; +import { Renderer } from 'src/Renderer'; import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'yieldone'; const ENDPOINT_URL = '//y.one.impact-ad.jp/h_bid'; const USER_SYNC_URL = '//y.one.impact-ad.jp/push_sync'; +const VIDEO_PLAYER_URL = '//img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/dac-video-prebid.min.js'; export const spec = { code: BIDDER_CODE, @@ -35,15 +37,15 @@ export const spec = { }; const videoMediaType = utils.deepAccess(bidRequest, 'mediaTypes.video'); - if (bidRequest.mediaType === VIDEO || videoMediaType) { + 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]; - } else 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(','); } return { @@ -84,6 +86,7 @@ export const spec = { } else if (response.adm) { bidResponse.mediaType = VIDEO; bidResponse.vastXml = response.adm; + bidResponse.renderer = newRenderer(response); } bidResponses.push(bidResponse); @@ -97,6 +100,29 @@ export const spec = { url: USER_SYNC_URL }]; } + }, +} + +function newRenderer(response) { + const renderer = Renderer.install({ + id: response.uid, + url: VIDEO_PLAYER_URL, + loaded: false, + }); + + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on newRenderer', err); } + + return renderer; } + +function outstreamRender(bid) { + bid.renderer.push(() => { + window.DACIVTPREBID.renderPrebid(bid); + }); +} + registerBidder(spec); diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js index e91eeab1369..d06029c7f26 100644 --- a/test/spec/modules/yieldoneBidAdapter_spec.js +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -4,6 +4,7 @@ import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = '//y.one.impact-ad.jp/h_bid'; const USER_SYNC_URL = '//y.one.impact-ad.jp/push_sync'; +const VIDEO_PLAYER_URL = '//img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/dac-video-prebid.min.js'; describe('yieldoneBidAdapter', function() { const adapter = newBidder(spec); @@ -190,11 +191,17 @@ describe('yieldoneBidAdapter', function() { 'ttl': 3000, 'referrer': '', 'mediaType': 'video', - 'vastXml': '' + 'vastXml': '', + 'renderer': { + id: '23beaa6af6cdde', + url: VIDEO_PLAYER_URL + } }]; let result = spec.interpretResponse(serverResponseVideo, bidRequestVideo[0]); expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); expect(result[0].mediaType).to.equal(expectedResponse[0].mediaType); + expect(result[0].renderer.id).to.equal(expectedResponse[0].renderer.id); + expect(result[0].renderer.url).to.equal(expectedResponse[0].renderer.url); }); it('handles empty bid response', function () { From ac389576328d2b01585a856b6837f8aa07f8ae87 Mon Sep 17 00:00:00 2001 From: ix-prebid-development <49417285+ix-prebid-development@users.noreply.github.com> Date: Mon, 15 Apr 2019 14:20:26 -0400 Subject: [PATCH 1157/1594] Updated IX Adapter (#3744) * Added Support For Identity * Added Tests For Identity --- modules/ixBidAdapter.js | 28 +++- test/spec/modules/ixBidAdapter_spec.js | 178 +++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 4 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index b1cc459d972..c63b920dc93 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -185,8 +185,10 @@ export const spec = { */ buildRequests: function (validBidRequests, options) { const bannerImps = []; + const userEids = []; let validBidRequest = null; let bannerImp = null; + // Always start by assuming the protocol is HTTPS. This way, it will work // whether the page protocol is HTTP or HTTPS. Then check if the page is // actually HTTP.If we can guarantee it is, then, and only then, set protocol to @@ -201,6 +203,21 @@ export const spec = { bannerImps.push(bannerImp); } + // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded + // and if the data for the partner exist + if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { + let identityInfo = window.headertag.getIdentityInfo(); + if (identityInfo && typeof identityInfo === 'object') { + for (const partnerName in identityInfo) { + if (identityInfo.hasOwnProperty(partnerName)) { + let response = identityInfo[partnerName]; + if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { + userEids.push(response.data); + } + } + } + } + } const r = {}; // Since bidderRequestId are the same for different bid request, just use the first one. @@ -210,6 +227,10 @@ export const spec = { r.site = {}; r.ext = {}; r.ext.source = 'prebid'; + if (userEids.length > 0) { + r.user = {}; + r.user.eids = userEids; + } if (document.referrer && document.referrer !== '') { r.site.ref = document.referrer; @@ -229,10 +250,9 @@ export const spec = { } if (gdprConsent.hasOwnProperty('consentString')) { - r.user = { - ext: { - consent: gdprConsent.consentString || '' - } + r.user = r.user || {}; + r.user.ext = { + consent: gdprConsent.consentString || '' }; } } diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index d88b783a785..38e64e8d338 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -69,6 +69,19 @@ describe('IndexexchangeAdapter', function () { } ] }; + const DEFAULT_IDENTITY_RESPONSE = { + IdentityIp: { + responsePending: false, + data: { + source: 'identityinc.com', + uids: [ + { + id: 'identityid' + } + ] + } + } + }; describe('inherited functions', function () { it('should exists and is a function', function () { @@ -209,6 +222,171 @@ describe('IndexexchangeAdapter', function () { }); }); + describe('buildRequestsIdentity', function () { + let request; + let query; + let testCopy; + + beforeEach(function() { + window.headertag = {}; + window.headertag.getIdentityInfo = function() { + return testCopy; + }; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + query = request.data; + }); + afterEach(function() { + delete window.headertag; + }); + describe('buildRequestSingleRTI', function() { + before(function() { + testCopy = JSON.parse(JSON.stringify(DEFAULT_IDENTITY_RESPONSE)); + }); + it('payload should have correct format and value (single identity partner)', function () { + const payload = JSON.parse(query.r); + + expect(payload.user).to.exist; + expect(payload.user.eids).to.exist; + expect(payload.user.eids).to.be.an('array'); + expect(payload.user.eids).to.have.lengthOf(1); + }); + + it('identity data in impression should have correct format and value (single identity partner)', function () { + const impression = JSON.parse(query.r).user.eids; + expect(impression[0].source).to.equal(testCopy.IdentityIp.data.source); + expect(impression[0].uids[0].id).to.equal(testCopy.IdentityIp.data.uids[0].id); + }); + }); + + describe('buildRequestMultipleIds', function() { + before(function() { + testCopy = JSON.parse(JSON.stringify(DEFAULT_IDENTITY_RESPONSE)); + testCopy.IdentityIp.data.uids.push({ + id: '1234567' + }, + { + id: '2019-04-01TF2:34:41' + }); + }); + it('payload should have correct format and value (single identity w/ multi ids)', function () { + const payload = JSON.parse(query.r); + + expect(payload.user).to.exist; + expect(payload.user.eids).to.exist; + expect(payload.user.eids).to.be.an('array'); + expect(payload.user.eids).to.have.lengthOf(1); + }); + + it('identity data in impression should have correct format and value (single identity w/ multi ids)', function () { + const impression = JSON.parse(query.r).user.eids; + + expect(impression[0].source).to.equal(testCopy.IdentityIp.data.source); + expect(impression[0].uids).to.have.lengthOf(3); + }); + }); + + describe('buildRequestMultipleRTI', function() { + before(function() { + testCopy = JSON.parse(JSON.stringify(DEFAULT_IDENTITY_RESPONSE)); + testCopy.JackIp = { + responsePending: false, + data: { + source: 'jackinc.com', + uids: [ + { + id: 'jackid' + } + ] + } + } + testCopy.GenericIp = { + responsePending: false, + data: { + source: 'genericip.com', + uids: [ + { + id: 'genericipenvelope' + } + ] + } + } + }); + it('payload should have correct format and value (multiple identity partners)', function () { + const payload = JSON.parse(query.r); + + expect(payload.user).to.exist; + expect(payload.user.eids).to.exist; + expect(payload.user.eids).to.be.an('array'); + expect(payload.user.eids).to.have.lengthOf(3); + }); + + it('identity data in impression should have correct format and value (multiple identity partners)', function () { + const impression = JSON.parse(query.r).user.eids; + + expect(impression[0].source).to.equal(testCopy.IdentityIp.data.source); + expect(impression[0].uids).to.have.lengthOf(1); + + expect(impression[1].source).to.equal(testCopy.JackIp.data.source); + expect(impression[1].uids).to.have.lengthOf(1); + + expect(impression[2].source).to.equal(testCopy.GenericIp.data.source); + expect(impression[2].uids).to.have.lengthOf(1); + }); + }); + + describe('buildRequestNoData', function() { + beforeEach(function() { + testCopy = JSON.parse(JSON.stringify(DEFAULT_IDENTITY_RESPONSE)); + }); + + it('payload should not have any user eids with an undefined identity data response', function () { + window.headertag.getIdentityInfo = function() { + return undefined; + }; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + query = request.data; + const payload = JSON.parse(query.r); + + expect(payload.user).to.exist; + expect(payload.user.eids).to.not.exist; + }); + + it('payload should have user eids if least one partner data is available', function () { + testCopy.GenericIp = { + responsePending: true, + data: {} + } + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + query = request.data; + const payload = JSON.parse(query.r); + + expect(payload.user).to.exist; + expect(payload.user.eids).to.exist; + }); + + it('payload should not have any user eids if identity data is pending for all partners', function () { + testCopy.IdentityIp.responsePending = true; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + query = request.data; + const payload = JSON.parse(query.r); + + expect(payload.user).to.exist; + expect(payload.user.eids).to.not.exist; + }); + + it('payload should not have any user eids if identity data is pending or not available for all partners', function () { + testCopy.IdentityIp.responsePending = false; + testCopy.IdentityIp.data = {}; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + query = request.data; + const payload = JSON.parse(query.r); + + expect(payload.user).to.exist; + expect(payload.user.eids).to.not.exist; + }); + }); + }); + describe('buildRequestsBanner', function () { const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const requestUrl = request.url; From 24317157acf285d5a88e6aa6557af0b1021e074e Mon Sep 17 00:00:00 2001 From: Daniel Rodriguez Date: Tue, 16 Apr 2019 12:05:55 -0400 Subject: [PATCH 1158/1594] Sortable - Analytics Adapter (#3705) --- modules/sortableAnalyticsAdapter.js | 534 ++++++++++++++++++ modules/sortableAnalyticsAdapter.md | 9 + .../modules/sortableAnalyticsAdapter_spec.js | 307 ++++++++++ 3 files changed, 850 insertions(+) create mode 100644 modules/sortableAnalyticsAdapter.js create mode 100644 modules/sortableAnalyticsAdapter.md create mode 100644 test/spec/modules/sortableAnalyticsAdapter_spec.js diff --git a/modules/sortableAnalyticsAdapter.js b/modules/sortableAnalyticsAdapter.js new file mode 100644 index 00000000000..4682dc09b49 --- /dev/null +++ b/modules/sortableAnalyticsAdapter.js @@ -0,0 +1,534 @@ +import adapter from 'src/AnalyticsAdapter'; +import CONSTANTS from 'src/constants.json'; +import adapterManager from 'src/adapterManager'; +import * as utils from 'src/utils'; +import {ajax} from 'src/ajax'; +import {getGlobal} from 'src/prebidGlobal'; +import { config } from 'src/config'; + +const DEFAULT_PROTOCOL = 'https'; +const DEFAULT_HOST = 'pa.deployads.com'; +const DEFAULT_URL = `${DEFAULT_PROTOCOL}://${DEFAULT_HOST}/pae`; +const ANALYTICS_TYPE = 'endpoint'; +const UTM_STORE_KEY = 'sortable_utm'; + +export const DEFAULT_PBID_TIMEOUT = 1000; +export const TIMEOUT_FOR_REGISTRY = 250; + +const settings = {}; +const { + EVENTS: { + AUCTION_INIT, + AUCTION_END, + BID_REQUESTED, + BID_ADJUSTMENT, + BID_WON, + BID_TIMEOUT, + } +} = CONSTANTS; + +const minsToMillis = mins => mins * 60 * 1000; +const UTM_TTL = minsToMillis(30); + +const SORTABLE_EVENTS = { + BID_WON: 'pbrw', + BID_TIMEOUT: 'pbto', + ERROR: 'pber', + PB_BID: 'pbid' +}; + +const UTM_PARAMS = [ + 'utm_campaign', + 'utm_source', + 'utm_medium', + 'utm_content', + 'utm_term' +]; + +const EVENT_KEYS_SHORT_NAMES = { + 'auctionId': 'ai', + 'adUnitCode': 'ac', + 'adId': 'adi', + 'bidderAlias': 'bs', + 'bidFactor': 'bif', + 'bidId': 'bid', + 'bidRequestCount': 'brc', + 'bidderRequestId': 'brid', + 'bidRequestedSizes': 'rs', + 'bidTopCpm': 'btcp', + 'bidTopCpmCurrency': 'btcc', + 'bidTopIsNetRevenue': 'btin', + 'bidTopFactor': 'btif', + 'bidTopSrc': 'btsrc', + 'cpm': 'c', + 'currency': 'cc', + 'dealId': 'did', + 'isNetRevenue': 'inr', + 'isTop': 'it', + 'isWinner': 'iw', + 'isTimeout': 'ito', + 'mediaType': 'mt', + 'reachedTop': 'rtp', + 'numIframes': 'nif', + 'size': 'siz', + 'start': 'st', + 'tagId': 'tgid', + 'transactionId': 'trid', + 'ttl': 'ttl', + 'ttr': 'ttr', + 'url': 'u', + 'utm_campaign': 'uc', + 'utm_source': 'us', + 'utm_medium': 'um', + 'utm_content': 'un', + 'utm_term': 'ut' +}; + +const auctionCache = {}; + +let bidderFactors = null; + +let timeoutId = null; +let eventsToBeSent = []; + +function getStorage() { + try { + return window['sessionStorage']; + } catch (e) { + return null; + } +} + +function putParams(k, v) { + try { + const storage = getStorage(); + if (!storage) { + return false; + } + if (v === null) { + storage.removeItem(k); + } else { + storage.setItem(k, JSON.stringify(v)); + } + return true; + } catch (e) { + return false; + } +} + +function getParams(k) { + try { + let storage = getStorage(); + if (!storage) { + return null; + } + let value = storage.getItem(k); + return value === null ? null : JSON.parse(value); + } catch (e) { + return null; + } +} + +function storeParams(key, paramsToSave) { + if (!settings.disableSessionTracking) { + for (let property in paramsToSave) { + if (paramsToSave.hasOwnProperty(property)) { + putParams(key, paramsToSave); + break; + } + } + } +} + +function getSiteKey(options) { + const sortableConfig = config.getConfig('sortable') || {}; + const globalSiteId = sortableConfig.siteId; + return globalSiteId || options.siteId; +} + +function generateRandomId() { + let s = (+new Date()).toString(36); + for (let i = 0; i < 6; ++i) { s += (Math.random() * 36 | 0).toString(36); } + return s; +} + +function getSessionParams() { + const stillValid = paramsFromStorage => (paramsFromStorage.created) < (+new Date() + UTM_TTL); + let sessionParams = null; + if (!settings.disableSessionTracking) { + const paramsFromStorage = getParams(UTM_STORE_KEY); + sessionParams = paramsFromStorage && stillValid(paramsFromStorage) ? paramsFromStorage : null; + } + sessionParams = sessionParams || {'created': +new Date(), 'sessionId': generateRandomId()}; + 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(); + storeParams(UTM_STORE_KEY, sessionParams); + } + return sessionParams; +} + +function getPrebidVersion() { + return getGlobal().version; +} + +function getFactor(bidder) { + if (bidder && bidder.bidCpmAdjustment) { + return bidder.bidCpmAdjustment(1.0); + } else { + return null; + } +} + +function getBiddersFactors() { + const pb = getGlobal(); + const result = {}; + 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; + } + }); + } + return result; +} + +function getBaseEvent(auctionId, adUnitCode, bidderCode) { + const event = {}; + event.s = settings.key; + event.ai = auctionId; + event.ac = adUnitCode; + event.bs = bidderCode; + return event; +} + +function getBidBaseEvent(auctionId, adUnitCode, bidderCode) { + const sessionParams = getSessionParams(); + const prebidVersion = getPrebidVersion(); + const event = getBaseEvent(auctionId, adUnitCode, bidderCode); + event.sid = sessionParams.sessionId; + event.pv = settings.pageviewId; + event.to = auctionCache[auctionId].timeout; + event.pbv = prebidVersion; + UTM_PARAMS.filter(k => sessionParams[k]).forEach(k => event[EVENT_KEYS_SHORT_NAMES[k]] = sessionParams[k]); + return event; +} + +function createPBBidEvent(bid) { + const event = getBidBaseEvent(bid.auctionId, bid.adUnitCode, bid.bidderAlias); + Object.keys(bid).forEach(k => { + const shortName = EVENT_KEYS_SHORT_NAMES[k]; + if (shortName) { + event[shortName] = bid[k]; + } + }); + event._type = SORTABLE_EVENTS.PB_BID; + return event; +} + +function getBidFactor(bidderAlias) { + if (!bidderFactors) { + bidderFactors = getBiddersFactors(); + } + const factor = bidderFactors[bidderAlias]; + return typeof factor !== 'undefined' ? factor : 1.0; +} + +function createPrebidBidWonEvent({auctionId, adUnitCode, bidderAlias, cpm, currency, isNetRevenue}) { + const bidFactor = getBidFactor(bidderAlias); + const event = getBaseEvent(auctionId, adUnitCode, bidderAlias); + event.bif = bidFactor; + bidderFactors = null; + event.c = cpm; + event.cc = currency; + event.inr = isNetRevenue; + event._type = SORTABLE_EVENTS.BID_WON; + return event; +} + +function createPrebidTimeoutEvent({auctionId, adUnitCode, bidderAlias}) { + const event = getBaseEvent(auctionId, adUnitCode, bidderAlias); + event._type = SORTABLE_EVENTS.BID_TIMEOUT; + return event; +} + +function getDistinct(arr) { + return arr.filter((v, i, a) => a.indexOf(v) === i); +} + +function groupBy(list, keyGetterFn) { + const map = {}; + list.forEach(item => { + const key = keyGetterFn(item); + map[key] = map[key] ? map[key].concat(item) : [item]; + }); + return map; +} + +function mergeAndCompressEventsByType(events, type) { + if (!events.length) { + return {}; + } + const allKeys = getDistinct(events.map(ev => Object.keys(ev)).reduce((prev, curr) => prev.concat(curr), [])); + const eventsAsMap = {}; + allKeys.forEach(k => { + events.forEach(ev => eventsAsMap[k] = eventsAsMap[k] ? eventsAsMap[k].concat(ev[k]) : [ev[k]]); + }); + const allSame = arr => arr.every(el => arr[0] === el); + Object.keys(eventsAsMap) + .forEach(k => eventsAsMap[k] = (eventsAsMap[k].length && allSame(eventsAsMap[k])) ? eventsAsMap[k][0] : eventsAsMap[k]); + eventsAsMap._count = events.length; + const result = {}; + result[type] = eventsAsMap; + return result; +} + +function mergeAndCompressEvents(events) { + const types = getDistinct(events.map(e => e._type)); + const groupedEvents = groupBy(events, e => e._type); + const results = types.map(t => groupedEvents[t]) + .map(events => mergeAndCompressEventsByType(events, events[0]._type)); + return results.reduce((prev, eventMap) => { + const key = Object.keys(eventMap)[0]; + prev[key] = eventMap[key]; + return prev; + }, {}); +} + +function registerEvents(events) { + eventsToBeSent = eventsToBeSent.concat(events); + if (!timeoutId) { + timeoutId = setTimeout(() => { + const _eventsToBeSent = eventsToBeSent.slice(); + eventsToBeSent = []; + sendEvents(_eventsToBeSent); + timeoutId = null; + }, TIMEOUT_FOR_REGISTRY); + } +} + +function sendEvents(events) { + const url = settings.url; + const mergedEvents = mergeAndCompressEvents(events); + const options = { + 'contentType': 'text/plain', + 'method': 'POST', + 'withCredentials': true + }; + const onSend = () => utils.logInfo('Sortable Analytics data sent'); + ajax(url, onSend, JSON.stringify(mergedEvents), options); +} + +// converts [[300, 250], [728, 90]] to '300x250,728x90' +function sizesToString(sizes) { + return sizes.map(s => s.join('x')).join(','); +} + +function dimsToSizeString(width, height) { + return `${width}x${height}`; +} + +function handleBidRequested(event) { + const refererInfo = event.refererInfo; + const url = refererInfo.referer; + const reachedTop = refererInfo.reachedTop; + const numIframes = refererInfo.numIframes; + event.bids.forEach(bid => { + const auctionId = bid.auctionId; + const adUnitCode = bid.adUnitCode; + const tagId = bid.bidder === 'sortable' ? bid.params.tagId : ''; + if (!auctionCache[auctionId].adUnits[adUnitCode]) { + auctionCache[auctionId].adUnits[adUnitCode] = {bids: {}}; + } + const adUnit = auctionCache[auctionId].adUnits[adUnitCode]; + const bids = adUnit.bids; + const newBid = { + adUnitCode: bid.adUnitCode, + auctionId: event.auctionId, + bidderAlias: bid.bidder, + bidId: bid.bidId, + bidderRequestId: bid.bidderRequestId, + bidRequestCount: bid.bidRequestsCount, + bidRequestedSizes: sizesToString(bid.sizes), + currency: bid.currency, + cpm: 0.0, + isTimeout: false, + isTop: false, + isWinner: false, + numIframes: numIframes, + start: event.start, + tagId: tagId, + transactionId: bid.transactionId, + reachedTop: reachedTop, + url: encodeURI(url) + }; + bids[newBid.bidderAlias] = newBid; + }); +} + +function handleBidAdjustment(event) { + const auctionId = event.auctionId; + const adUnitCode = event.adUnitCode; + const adUnit = auctionCache[auctionId].adUnits[adUnitCode]; + const bid = adUnit.bids[event.bidderCode]; + const bidFactor = getBidFactor(event.bidderCode); + bid.adId = event.adId; + bid.adUnitCode = event.adUnitCode; + bid.auctionId = event.auctionId; + bid.bidderAlias = event.bidderCode; + bid.bidFactor = bidFactor; + bid.cpm = event.cpm; + bid.currency = event.currency; + bid.dealId = event.dealId; + bid.isNetRevenue = event.netRevenue; + bid.mediaType = event.mediaType; + bid.responseTimestamp = event.responseTimestamp; + bid.size = dimsToSizeString(event.width, event.height); + bid.ttl = event.ttl; + bid.ttr = event.timeToRespond; +} + +function handleBidWon(event) { + const auctionId = event.auctionId; + const auction = auctionCache[auctionId]; + if (auction) { + const adUnitCode = event.adUnitCode; + const adUnit = auction.adUnits[adUnitCode]; + Object.keys(adUnit.bids).forEach(bidderCode => { + const bidFromUnit = adUnit.bids[bidderCode]; + bidFromUnit.isWinner = event.bidderCode === bidderCode; + }); + } else { + const ev = createPrebidBidWonEvent({ + adUnitCode: event.adUnitCode, + auctionId: event.auctionId, + bidderAlias: event.bidderCode, + currency: event.currency, + cpm: event.cpm, + isNetRevenue: event.netRevenue, + }); + registerEvents([ev]); + } +} + +function handleBidTimeout(event) { + event.forEach(timeout => { + const auctionId = timeout.auctionId; + const adUnitCode = timeout.adUnitCode; + const bidderAlias = timeout.bidder; + const auction = auctionCache[auctionId]; + if (auction) { + const adUnit = auction.adUnits[adUnitCode]; + const bid = adUnit.bids[bidderAlias]; + bid.isTimeout = true; + } else { + const prebidTimeoutEvent = createPrebidTimeoutEvent({auctionId, adUnitCode, bidderAlias}); + registerEvents([prebidTimeoutEvent]); + } + }); +} + +function handleAuctionInit(event) { + const auctionId = event.auctionId; + const timeout = event.timeout; + auctionCache[auctionId] = {timeout: timeout, auctionId: auctionId, adUnits: {}}; +} + +function handleAuctionEnd(event) { + const auction = auctionCache[event.auctionId]; + const adUnits = auction.adUnits; + setTimeout(() => { + 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(utils.getOldestHighestCpmBid) : null; + return bidderKeys.map(bidderCode => { + const bid = auction.adUnits[adUnitCode].bids[bidderCode]; + if (highestBid && highestBid.cpm) { + bid.isTop = highestBid.bidderAlias === bid.bidderAlias; + bid.bidTopFactor = getBidFactor(highestBid.bidderAlias); + bid.bidTopCpm = highestBid.cpm; + bid.bidTopCpmCurrency = highestBid.currency; + bid.bidTopIsNetRevenue = highestBid.isNetRevenue; + bid.bidTopSrc = highestBid.bidderAlias; + } + return createPBBidEvent(bid); + }); + }).reduce((prev, curr) => prev.concat(curr), []); + bidderFactors = null; + sendEvents(events); + delete auctionCache[event.auctionId]; + }, settings.timeoutForPbid); +} + +function handleError(eventType, event, e) { + const ev = {}; + ev.s = settings.key; + ev.ti = eventType; + ev.args = JSON.stringify(event); + ev.msg = e.message; + ev._type = SORTABLE_EVENTS.ERROR; + registerEvents([ev]); +} + +const sortableAnalyticsAdapter = Object.assign(adapter({url: DEFAULT_URL, ANALYTICS_TYPE}), { + track({eventType, args}) { + try { + switch (eventType) { + case AUCTION_INIT: + handleAuctionInit(args); + break; + case AUCTION_END: + handleAuctionEnd(args); + break; + case BID_REQUESTED: + handleBidRequested(args); + break; + case BID_ADJUSTMENT: + handleBidAdjustment(args); + break; + case BID_WON: + handleBidWon(args); + break; + case BID_TIMEOUT: + handleBidTimeout(args); + break; + } + } catch (e) { + handleError(eventType, args, e); + } + } +}); + +sortableAnalyticsAdapter.originEnableAnalytics = sortableAnalyticsAdapter.enableAnalytics; + +sortableAnalyticsAdapter.enableAnalytics = function (setupConfig) { + if (this.initConfig(setupConfig)) { + utils.logInfo('Sortable Analytics adapter enabled'); + sortableAnalyticsAdapter.originEnableAnalytics(setupConfig); + } +}; + +sortableAnalyticsAdapter.initConfig = function (setupConfig) { + settings.disableSessionTracking = setupConfig.disableSessionTracking === undefined ? false : setupConfig.disableSessionTracking; + settings.key = getSiteKey(setupConfig.options); + settings.protocol = setupConfig.options.protocol || DEFAULT_PROTOCOL; + settings.url = `${settings.protocol}://${setupConfig.options.eventHost || DEFAULT_HOST}/pae/${settings.key}`; + settings.pageviewId = generateRandomId(); + settings.timeoutForPbid = setupConfig.timeoutForPbid ? Math.max(setupConfig.timeoutForPbid, 0) : DEFAULT_PBID_TIMEOUT; + return !!settings.key; +}; + +sortableAnalyticsAdapter.getOptions = function () { + return settings; +}; + +adapterManager.registerAnalyticsAdapter({ + adapter: sortableAnalyticsAdapter, + code: 'sortable' +}); + +export default sortableAnalyticsAdapter; diff --git a/modules/sortableAnalyticsAdapter.md b/modules/sortableAnalyticsAdapter.md new file mode 100644 index 00000000000..a4aa8019031 --- /dev/null +++ b/modules/sortableAnalyticsAdapter.md @@ -0,0 +1,9 @@ +# Overview + +Module Name: Sortable Analytics Adapter +Module Type: Analytics Adapter +Maintainer: prebid@sortable.com + +# Description + +Analytics adapter for Sortable. Contact prebid@sortable.com for information. diff --git a/test/spec/modules/sortableAnalyticsAdapter_spec.js b/test/spec/modules/sortableAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..90bd5fcdf22 --- /dev/null +++ b/test/spec/modules/sortableAnalyticsAdapter_spec.js @@ -0,0 +1,307 @@ +import {expect} from 'chai'; +import sortableAnalyticsAdapter, {TIMEOUT_FOR_REGISTRY, DEFAULT_PBID_TIMEOUT} from 'modules/sortableAnalyticsAdapter'; +import events from 'src/events'; +import CONSTANTS from 'src/constants.json'; +import * as prebidGlobal from 'src/prebidGlobal'; + +describe('Sortable Analytics Adapter', function() { + let requests; + let sandbox; + let xhr; + let clock; + + const initialConfig = { + provider: 'sortable', + options: { + siteId: 'testkey' + } + }; + + const TEST_DATA = { + AUCTION_INIT: { + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + timeout: 3000 + }, + BID_REQUESTED: { + refererInfo: { + referer: 'test.com', + reachedTop: true, + numIframes: 1 + }, + bidderCode: 'sortable', + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + bids: [{ + bidder: 'sortable', + params: { + tagId: 'medrec_1' + }, + adUnitCode: '300x250', + transactionId: 'aa02b498-8a99-418e-bc59-6b6fd45f32de', + sizes: [ + [300, 250] + ], + bidId: '26721042674416', + bidderRequestId: '10141593b1d84a', + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + bidRequestsCount: 1 + }, { + bidder: 'sortable', + params: { + tagId: 'lead_1' + }, + adUnitCode: '728x90', + transactionId: 'b7e9e957-af4f-4c47-8ca7-41f01cb4f105', + sizes: [ + [728, 90] + ], + bidId: '50fa575b41e596', + bidderRequestId: '37a8760be6db23', + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + bidRequestsCount: 1 + }], + start: 1553529405788 + }, + BID_ADJUSTMENT_1: { + bidderCode: 'sortable', + adId: '88221d316425f7', + mediaType: 'banner', + cpm: 0.70, + dealId: null, + currency: 'USD', + netRevenue: true, + ttl: 60, + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + responseTimestamp: 1553534161763, + bidder: 'sortable', + adUnitCode: '300x250', + timeToRespond: 331, + width: '300', + height: '250' + }, + AUCTION_END: { + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e' + }, + BID_ADJUSTMENT_2: { + bidderCode: 'sortable', + adId: '88221d316425f8', + mediaType: 'banner', + cpm: 0.50, + dealId: null, + currency: 'USD', + netRevenue: true, + ttl: 60, + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + responseTimestamp: 1553534161770, + bidder: 'sortable', + adUnitCode: '728x90', + timeToRespond: 338, + width: '728', + height: '90' + }, + BID_WON_1: { + bidderCode: 'sortable', + adId: '88221d316425f7', + mediaType: 'banner', + cpm: 0.70, + dealId: null, + currency: 'USD', + netRevenue: true, + ttl: 60, + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + responseTimestamp: 1553534161763, + bidder: 'sortable', + adUnitCode: '300x250', + timeToRespond: 331 + }, + BID_WON_2: { + bidderCode: 'sortable', + adId: '88221d316425f8', + mediaType: 'banner', + cpm: 0.50, + dealId: null, + currency: 'USD', + netRevenue: true, + ttl: 60, + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + responseTimestamp: 1553534161770, + bidder: 'sortable', + adUnitCode: '728x90', + timeToRespond: 338 + }, + BID_TIMEOUT: [{ + auctionId: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + adUnitCode: '300x250', + bidder: 'sortable' + }] + }; + + beforeEach(function() { + sandbox = sinon.sandbox.create(); + xhr = sandbox.useFakeXMLHttpRequest(); + xhr.onCreate = (request) => requests.push(request); + clock = sandbox.useFakeTimers(); + sandbox.stub(events, 'getEvents').returns([]); + sandbox.stub(prebidGlobal, 'getGlobal').returns({ + version: '1.0', + bidderSettings: { + 'sortable': { + bidCpmAdjustment: function (number) { + return number * 0.95; + } + } + } + }); + + requests = []; + sortableAnalyticsAdapter.enableAnalytics(initialConfig); + }); + + afterEach(function() { + sandbox.restore(); + sortableAnalyticsAdapter.disableAnalytics(); + }); + + describe('initialize adapter', function() { + const settings = sortableAnalyticsAdapter.getOptions(); + + it('should init settings correctly and apply defaults', function() { + expect(settings).to.include({ + 'disableSessionTracking': false, + 'key': initialConfig.options.siteId, + 'protocol': 'https', + 'url': `https://pa.deployads.com/pae/${initialConfig.options.siteId}`, + 'timeoutForPbid': DEFAULT_PBID_TIMEOUT + }); + }); + it('should assign a pageview ID', function() { + expect(settings).to.have.own.property('pageviewId'); + }); + }); + + describe('events tracking', function() { + it('should send the PBID event', function() { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, TEST_DATA.AUCTION_INIT); + events.emit(CONSTANTS.EVENTS.BID_REQUESTED, TEST_DATA.BID_REQUESTED); + events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, TEST_DATA.BID_ADJUSTMENT_1); + events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, TEST_DATA.BID_ADJUSTMENT_2); + events.emit(CONSTANTS.EVENTS.AUCTION_END, TEST_DATA.AUCTION_END); + events.emit(CONSTANTS.EVENTS.BID_WON, TEST_DATA.BID_WON_1); + events.emit(CONSTANTS.EVENTS.BID_WON, TEST_DATA.BID_WON_2); + + clock.tick(DEFAULT_PBID_TIMEOUT); + + expect(requests.length).to.equal(1); + let result = JSON.parse(requests[0].requestBody); + expect(result).to.have.own.property('pbid'); + expect(result.pbid).to.deep.include({ + ai: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + ac: ['300x250', '728x90'], + adi: ['88221d316425f7', '88221d316425f8'], + bs: 'sortable', + bid: ['26721042674416', '50fa575b41e596'], + bif: 0.95, + brc: 1, + brid: ['10141593b1d84a', '37a8760be6db23'], + rs: ['300x250', '728x90'], + btcp: [0.70, 0.50], + btcc: 'USD', + btin: true, + btsrc: 'sortable', + c: [0.70, 0.50], + cc: 'USD', + did: null, + inr: true, + it: true, + iw: true, + ito: false, + mt: 'banner', + rtp: true, + nif: 1, + pbv: '1.0', + siz: ['300x250', '728x90'], + st: 1553529405788, + tgid: ['medrec_1', 'lead_1'], + to: 3000, + trid: ['aa02b498-8a99-418e-bc59-6b6fd45f32de', 'b7e9e957-af4f-4c47-8ca7-41f01cb4f105'], + ttl: 60, + ttr: [331, 338], + u: 'test.com', + _count: 2 + }); + }); + + it('should track a late bidWon event', function() { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, TEST_DATA.AUCTION_INIT); + events.emit(CONSTANTS.EVENTS.BID_REQUESTED, TEST_DATA.BID_REQUESTED); + events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, TEST_DATA.BID_ADJUSTMENT_1); + events.emit(CONSTANTS.EVENTS.AUCTION_END, TEST_DATA.AUCTION_END); + + clock.tick(DEFAULT_PBID_TIMEOUT); + + events.emit(CONSTANTS.EVENTS.BID_WON, TEST_DATA.BID_WON_1); + + clock.tick(TIMEOUT_FOR_REGISTRY); + + expect(requests.length).to.equal(2); + const pbid_req = JSON.parse(requests[0].requestBody); + expect(pbid_req).to.have.own.property('pbid'); + const pbwon_req = JSON.parse(requests[1].requestBody); + expect(pbwon_req).to.have.own.property('pbrw'); + expect(pbwon_req.pbrw).to.deep.equal({ + ac: '300x250', + ai: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + bif: 0.95, + bs: 'sortable', + s: initialConfig.options.siteId, + cc: 'USD', + c: 0.70, + inr: true, + _count: 1, + _type: 'pbrw' + }); + }); + + it('should track late bidder timeouts', function() { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, TEST_DATA.AUCTION_INIT); + events.emit(CONSTANTS.EVENTS.BID_REQUESTED, TEST_DATA.BID_REQUESTED); + events.emit(CONSTANTS.EVENTS.AUCTION_END, TEST_DATA.AUCTION_END); + clock.tick(DEFAULT_PBID_TIMEOUT); + events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, TEST_DATA.BID_TIMEOUT); + + clock.tick(TIMEOUT_FOR_REGISTRY); + + expect(requests.length).to.equal(2); + const pbid_req = JSON.parse(requests[0].requestBody); + expect(pbid_req).to.have.own.property('pbid'); + const pbto_req = JSON.parse(requests[1].requestBody); + expect(pbto_req).to.have.own.property('pbto'); + expect(pbto_req.pbto).to.deep.equal({ + ai: 'fb8d579a-5c3f-4705-ab94-3cff39005d9e', + s: initialConfig.options.siteId, + ac: '300x250', + bs: 'sortable', + _type: 'pbto', + _count: 1 + }); + }); + + it('should track errors', function() { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, TEST_DATA.AUCTION_INIT); + events.emit(CONSTANTS.EVENTS.BID_REQUESTED, {}); + + clock.tick(TIMEOUT_FOR_REGISTRY); + + expect(requests.length).to.equal(1); + const err_req = JSON.parse(requests[0].requestBody); + expect(err_req).to.have.own.property('pber'); + expect(err_req.pber).to.include({ + args: '{}', + s: initialConfig.options.siteId, + _count: 1, + ti: 'bidRequested', + _type: 'pber' + }); + expect(err_req.pber.msg).to.be.a('string'); + }); + }); +}); From cc2f394edb1a45f3fd57a66e4de77da1ee5cb0a1 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Tue, 16 Apr 2019 19:07:48 +0300 Subject: [PATCH 1159/1594] Yieldnexus: Add video player size (#3727) * Add support for multiple media types. Add test coverage. * Add support for multiple media types. Add test coverage. * Modify multi-format ads handler. Modify tests. * Rename yieldnexus bid adapter to fix download issue * Set video player according to playerSize (if given). Add unit test. * Fix lint issues --- modules/yieldnexusBidAdapter.js | 15 +++++++++++-- .../spec/modules/yieldnexusBidAdapter_spec.js | 21 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/modules/yieldnexusBidAdapter.js b/modules/yieldnexusBidAdapter.js index cf891b025aa..23b1d21334b 100644 --- a/modules/yieldnexusBidAdapter.js +++ b/modules/yieldnexusBidAdapter.js @@ -88,12 +88,23 @@ export const spec = { if (bidRequest.mediaTypes && bidRequest.mediaTypes.video) { imp.video = { - w: bidRequest.sizes.length ? bidRequest.sizes[0][0] : 300, - h: bidRequest.sizes.length ? bidRequest.sizes[0][1] : 250, protocols: bidRequest.params.protocols || [1, 2, 3, 4, 5, 6], pos: bidRequest.params.pos || 0, topframe: topFrame }; + + let playerSize = bidRequest.mediaTypes.video.playerSize; + if (playerSize && utils.isArray(playerSize[0])) { + imp.video.w = playerSize[0][0]; + imp.video.h = playerSize[0][1]; + } else if (playerSize && utils.isNumber(playerSize[0])) { + imp.video.w = playerSize[0]; + imp.video.h = playerSize[1]; + } else { + playerSize = utils.isArray(bidRequest.sizes) ? bidRequest.sizes[0] : [300, 250]; + imp.video.w = playerSize[0]; + imp.video.h = playerSize[1]; + } } if (!bidRequest.mediaTypes || bidRequest.mediaTypes.banner) { diff --git a/test/spec/modules/yieldnexusBidAdapter_spec.js b/test/spec/modules/yieldnexusBidAdapter_spec.js index 3d36291f136..8f2e40d1810 100644 --- a/test/spec/modules/yieldnexusBidAdapter_spec.js +++ b/test/spec/modules/yieldnexusBidAdapter_spec.js @@ -142,6 +142,27 @@ describe('YieldNexusAdapter', () => { response = spec.buildRequests([bidRequestWithPosEquals1])[0]; expect(response.data.imp[0].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); + + it('builds request video object correctly with multi-dimensions size array', function () { + let bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes.video = { + playerSize: [[304, 254], [305, 255]], + context: 'instream' + }; + + let response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[0].video.w).to.equal(304); + expect(response.data.imp[0].video.h).to.equal(254); + + bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes.video = { + playerSize: [304, 254] + }; + + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[0].video.w).to.equal(304); + expect(response.data.imp[0].video.h).to.equal(254); + }); }); describe('interpretResponse', () => { const bannerBidRequest = { From f3244db12729ef7ec053e3e98685a5805f24dd13 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 16 Apr 2019 11:38:48 -0700 Subject: [PATCH 1160/1594] Update rubiconBidAdapter.js (#3753) Prebid-Server expects price granularity param to be all lowercase, Camel case causes it to not consider it. --- modules/rubiconBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 034b861f0f7..c57e10aede7 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -151,7 +151,7 @@ export const spec = { includewinners: true, // includebidderkeys always false for openrtb includebidderkeys: false, - priceGranularity: getPriceGranularity(config) + pricegranularity: getPriceGranularity(config) } } } From 2f0e98d580cb455ad46972346b34d58f269a0484 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 16 Apr 2019 15:07:49 -0700 Subject: [PATCH 1161/1594] Prebid 2.11.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 79aa74cfa28..b3c42a4a601 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.11.0-pre", + "version": "2.11.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 8de1fac1580e9327ff6b93dffabf12b71a57606f Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Wed, 17 Apr 2019 08:10:27 -0700 Subject: [PATCH 1162/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b3c42a4a601..c3b4e5cd042 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.11.0", + "version": "2.12.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 984dfb1f47aedcc7bad651d337c50613c2432e07 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Thu, 18 Apr 2019 10:16:51 -0700 Subject: [PATCH 1163/1594] PubCommonId - Add support for localStorage (#3661) * Add support for localStorage * Pubcid uses local storage first --- modules/pubCommonId.js | 192 +++++++++++++++++++++++--- modules/pubCommonId.md | 37 +++++ test/spec/modules/pubCommonId_spec.js | 175 ++++++++++++++++++++--- 3 files changed, 366 insertions(+), 38 deletions(-) create mode 100644 modules/pubCommonId.md diff --git a/modules/pubCommonId.js b/modules/pubCommonId.js index 3175dc22613..5b92592f07a 100644 --- a/modules/pubCommonId.js +++ b/modules/pubCommonId.js @@ -6,15 +6,126 @@ import * as utils from '../src/utils' import { config } from '../src/config'; -const COOKIE_NAME = '_pubcid'; -const DEFAULT_EXPIRES = 2628000; // 5-year worth of minutes +const ID_NAME = '_pubcid'; +const OPTOUT_NAME = '_pubcid_optout'; +const DEFAULT_EXPIRES = 525600; // 1-year worth of minutes const PUB_COMMON = 'PublisherCommonId'; +const EXP_SUFFIX = '_exp'; +const COOKIE = 'cookie'; +const LOCAL_STORAGE = 'html5'; -var pubcidEnabled = true; -var interval = DEFAULT_EXPIRES; +let pubcidConfig = { + enabled: true, + interval: DEFAULT_EXPIRES, + typeEnabled: LOCAL_STORAGE, + readOnly: false +}; -export function isPubcidEnabled() { return pubcidEnabled; } -export function getExpInterval() { return interval; } +/** + * Set an item in the storage with expiry time. + * @param {string} key Key of the item to be stored + * @param {string} val Value of the item to be stored + * @param {number} expires Expiry time in minutes + */ + +export function setStorageItem(key, val, expires) { + try { + if (expires !== undefined && expires != null) { + const expStr = (new Date(Date.now() + (expires * 60 * 1000))).toUTCString(); + localStorage.setItem(key + EXP_SUFFIX, expStr); + } + + localStorage.setItem(key, val); + } catch (e) { + utils.logMessage(e); + } +} + +/** + * Retrieve an item from storage if it exists and hasn't expired. + * @param {string} key Key of the item. + * @returns {string|null} Value of the item. + */ +export function getStorageItem(key) { + let val = null; + + try { + const expVal = localStorage.getItem(key + EXP_SUFFIX); + + if (!expVal) { + // If there is no expiry time, then just return the item + val = localStorage.getItem(key); + } else { + // Only return the item if it hasn't expired yet. + // Otherwise delete the item. + const expDate = new Date(expVal); + const isValid = (expDate.getTime() - Date.now()) > 0; + if (isValid) { + val = localStorage.getItem(key); + } else { + removeStorageItem(key); + } + } + } catch (e) { + utils.logMessage(e); + } + + return val; +} + +/** + * Remove an item from storage + * @param {string} key Key of the item to be removed + */ +export function removeStorageItem(key) { + try { + localStorage.removeItem(key + EXP_SUFFIX); + localStorage.removeItem(key); + } catch (e) { + utils.logMessage(e); + } +} + +/** + * Read a value either from cookie or local storage + * @param {string} name Name of the item + * @returns {string|null} a string if item exists + */ +function readValue(name) { + let value; + if (pubcidConfig.typeEnabled === COOKIE) { + value = getCookie(name); + } else if (pubcidConfig.typeEnabled === LOCAL_STORAGE) { + value = getStorageItem(name); + if (!value) { + value = getCookie(name); + } + } + + if (value === 'undefined' || value === 'null') { return null; } + + return value; +} + +/** + * Write a value to either cookies or local storage + * @param {string} name Name of the item + * @param {string} value Value to be stored + * @param {number} expInterval Expiry time in minutes + */ +function writeValue(name, value, expInterval) { + if (name && value) { + if (pubcidConfig.typeEnabled === COOKIE) { + setCookie(name, value, expInterval); + } else if (pubcidConfig.typeEnabled === LOCAL_STORAGE) { + setStorageItem(name, value, expInterval); + } + } +} + +export function isPubcidEnabled() { return pubcidConfig.enabled; } +export function getExpInterval() { return pubcidConfig.interval; } +export function getPubcidConfig() { return pubcidConfig; } /** * Decorate ad units with pubcid. This hook function is called before the @@ -29,7 +140,7 @@ export function requestBidHook(next, config) { let pubcid = null; // Pass control to the next function if not enabled - if (!pubcidEnabled) { + if (!pubcidConfig.enabled || !pubcidConfig.typeEnabled) { return next.call(this, config); } @@ -38,11 +149,22 @@ export function requestBidHook(next, config) { pubcid = window[PUB_COMMON].getId(); utils.logMessage(PUB_COMMON + ': pubcid = ' + pubcid); } else { - // Otherwise get the existing cookie or create a new id - pubcid = getCookie(COOKIE_NAME) || utils.generateUUID(); + // Otherwise get the existing cookie + pubcid = readValue(ID_NAME); + + if (!pubcidConfig.readOnly) { + if (!pubcid) { + pubcid = utils.generateUUID(); + // Update the cookie/storage with the latest expiration date + writeValue(ID_NAME, pubcid, pubcidConfig.interval); + // Only return pubcid if it is saved successfully + pubcid = readValue(ID_NAME); + } else { + // Update the cookie/storage with the latest expiration date + writeValue(ID_NAME, pubcid, pubcidConfig.interval); + } + } - // Update the cookie with the latest expiration date - setCookie(COOKIE_NAME, pubcid, interval); utils.logMessage('pbjs: pubcid = ' + pubcid); } @@ -68,21 +190,49 @@ export function setCookie(name, value, expires) { // Helper to read a cookie export function getCookie(name) { - let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); - return m ? decodeURIComponent(m[2]) : null; + if (name && window.document.cookie) { + let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); + return m ? decodeURIComponent(m[2]) : null; + } + return null; } /** * Configuration function * @param {boolean} enable Enable or disable pubcid. By default the module is enabled. * @param {number} expInterval Expiration interval of the cookie in minutes. + * @param {string} type Type of storage to use + * @param {boolean} readOnly Read but not update id */ -export function setConfig({ enable = true, expInterval = DEFAULT_EXPIRES } = {}) { - pubcidEnabled = enable; - interval = parseInt(expInterval, 10); - if (isNaN(interval)) { - interval = DEFAULT_EXPIRES; +export function setConfig({ enable = true, expInterval = DEFAULT_EXPIRES, type = 'html5,cookie', readOnly = false } = {}) { + pubcidConfig.enabled = enable; + pubcidConfig.interval = parseInt(expInterval, 10); + if (isNaN(pubcidConfig.interval)) { + pubcidConfig.interval = DEFAULT_EXPIRES; + } + + pubcidConfig.readOnly = readOnly; + + // Default is to use local storage. Fall back to + // cookie only if local storage is not supported. + + pubcidConfig.typeEnabled = null; + + const typeArray = type.split(','); + for (let i = 0; i < typeArray.length; ++i) { + const name = typeArray[i].trim(); + if (name === COOKIE) { + if (utils.cookiesAreEnabled()) { + pubcidConfig.typeEnabled = COOKIE; + break; + } + } else if (name === LOCAL_STORAGE) { + if (utils.hasLocalStorage()) { + pubcidConfig.typeEnabled = LOCAL_STORAGE; + break; + } + } } } @@ -92,10 +242,8 @@ export function setConfig({ enable = true, expInterval = DEFAULT_EXPIRES } = {}) export function initPubcid() { config.getConfig('pubcid', config => setConfig(config.pubcid)); - if (utils.cookiesAreEnabled()) { - if (!getCookie('_pubcid_optout')) { - $$PREBID_GLOBAL$$.requestBids.before(requestBidHook); - } + if (!readValue(OPTOUT_NAME)) { + $$PREBID_GLOBAL$$.requestBids.before(requestBidHook); } } diff --git a/modules/pubCommonId.md b/modules/pubCommonId.md new file mode 100644 index 00000000000..79531bfe87c --- /dev/null +++ b/modules/pubCommonId.md @@ -0,0 +1,37 @@ +## Publisher Common ID Example Configuration + +When the module is included, it's automatically enabled and saves an id to both cookie and local storage with an expiration time of 1 year. + +Example of disabling publisher common id. + +``` +pbjs.setConfig( + pubcid: { + enable: false + } +); +``` + +Example of setting expiration interval to 30 days. The interval is expressed in minutes. + +``` +pbjs.setConfig( + pubcid: { + expInterval: 43200 + } +); +``` + +Example of using local storage only and setting expiration interval to 30 days. + +``` +pbjs.setConfig( + pubcid: { + expInterval: 43200, + type: 'html5' + } +); +``` + + + diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js index f648e165c93..fb4a58377c3 100644 --- a/test/spec/modules/pubCommonId_spec.js +++ b/test/spec/modules/pubCommonId_spec.js @@ -5,7 +5,11 @@ import { setConfig, isPubcidEnabled, getExpInterval, - initPubcid } from 'modules/pubCommonId'; + initPubcid, + setStorageItem, + getStorageItem, + removeStorageItem, + getPubcidConfig } from 'modules/pubCommonId'; import { getAdUnits } from 'test/fixtures/fixtures'; import * as auctionModule from 'src/auction'; import { registerBidder } from 'src/adapters/bidderFactory'; @@ -14,16 +18,28 @@ import * as utils from 'src/utils'; var assert = require('chai').assert; var expect = require('chai').expect; -const COOKIE_NAME = '_pubcid'; +const ID_NAME = '_pubcid'; +const EXP = '_exp'; const TIMEOUT = 2000; +const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89a-f][0-9a-f]{3}-[0-9a-f]{12}$/; + +function cleanUp() { + window.document.cookie = ID_NAME + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + localStorage.removeItem(ID_NAME); + localStorage.removeItem(ID_NAME + EXP); +} + describe('Publisher Common ID', function () { afterEach(function () { $$PREBID_GLOBAL$$.requestBids.removeAll(); }); describe('Decorate adUnits', function () { - before(function() { - window.document.cookie = COOKIE_NAME + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + beforeEach(function() { + cleanUp(); + }); + afterEach(function() { + cleanUp(); }); it('Check same cookie', function () { @@ -31,12 +47,13 @@ describe('Publisher Common ID', function () { let adUnits2 = getAdUnits(); let innerAdUnits1; let innerAdUnits2; - let pubcid = getCookie(COOKIE_NAME); + let pubcid; - expect(pubcid).to.be.null; // there should be no cookie initially + expect(getCookie(ID_NAME)).to.be.null; // there should be no cookie initially + expect(localStorage.getItem(ID_NAME)).to.be.null; // there should be no local storage item either requestBidHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); - pubcid = getCookie(COOKIE_NAME); // cookies is created after requestbidHook + pubcid = localStorage.getItem(ID_NAME); // local storage item is created after requestbidHook innerAdUnits1.forEach((unit) => { unit.bids.forEach((bid) => { @@ -44,6 +61,11 @@ describe('Publisher Common ID', function () { expect(bid.crumbs.pubcid).to.equal(pubcid); }); }); + + // verify cookie is null + expect(getCookie(ID_NAME)).to.be.null; + + // verify same pubcid is preserved requestBidHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); assert.deepEqual(innerAdUnits1, innerAdUnits2); }); @@ -57,8 +79,10 @@ describe('Publisher Common ID', function () { let pubcid2; requestBidHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); - pubcid1 = getCookie(COOKIE_NAME); // get first cookie - setCookie(COOKIE_NAME, '', -1); // erase cookie + pubcid1 = localStorage.getItem(ID_NAME); // get first pubcid + removeStorageItem(ID_NAME); // remove storage + + expect(pubcid1).to.not.be.null; innerAdUnits1.forEach((unit) => { unit.bids.forEach((bid) => { @@ -68,7 +92,7 @@ describe('Publisher Common ID', function () { }); requestBidHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); - pubcid2 = getCookie(COOKIE_NAME); // get second cookie + pubcid2 = localStorage.getItem(ID_NAME); // get second pubcid innerAdUnits2.forEach((unit) => { unit.bids.forEach((bid) => { @@ -77,6 +101,7 @@ describe('Publisher Common ID', function () { }); }); + expect(pubcid2).to.not.be.null; expect(pubcid1).to.not.equal(pubcid2); }); @@ -85,7 +110,7 @@ describe('Publisher Common ID', function () { let innerAdUnits; let pubcid = utils.generateUUID(); - setCookie(COOKIE_NAME, pubcid, 600); + setCookie(ID_NAME, pubcid, 600); requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { @@ -94,16 +119,79 @@ describe('Publisher Common ID', function () { }); }); }); + + it('Replicate cookie to storage', function() { + let adUnits = getAdUnits(); + let innerAdUnits; + let pubcid = utils.generateUUID(); + + setCookie(ID_NAME, pubcid, 600); + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + expect(getStorageItem(ID_NAME)).to.equal(pubcid); + }); + + it('Does not replicate storage to cookie', function() { + let adUnits = getAdUnits(); + let innerAdUnits; + let pubcid = utils.generateUUID(); + + setStorageItem(ID_NAME, pubcid, 600); + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + expect(getCookie(ID_NAME)).to.be.null; + }); + + it('Cookie only', function() { + setConfig({type: 'cookie'}); + let adUnits = getAdUnits(); + let innerAdUnits; + + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + expect(getCookie(ID_NAME)).to.match(uuidPattern); + expect(getStorageItem(ID_NAME)).to.be.null; + }); + + it('Storage only', function() { + setConfig({type: 'html5'}); + let adUnits = getAdUnits(); + let innerAdUnits; + + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + expect(getCookie(ID_NAME)).to.be.null; + expect(getStorageItem(ID_NAME)).to.match(uuidPattern); + }); + + it('Bad id recovery', function() { + let adUnits = getAdUnits(); + let innerAdUnits; + + setStorageItem(ID_NAME, 'undefined', 600); + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + expect(getStorageItem(ID_NAME)).to.match(uuidPattern); + }); }); describe('Configuration', function () { + beforeEach(() => { + setConfig(); + cleanUp(); + }); + afterEach(() => { + setConfig(); + cleanUp(); + }); + it('empty config', function () { // this should work as usual setConfig({}); let adUnits = getAdUnits(); let innerAdUnits; requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - let pubcid = getCookie(COOKIE_NAME); + let pubcid = localStorage.getItem(ID_NAME); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { expect(bid).to.have.deep.nested.property('crumbs.pubcid'); @@ -114,13 +202,12 @@ describe('Publisher Common ID', function () { it('disable', function () { setConfig({enable: false}); - setCookie(COOKIE_NAME, '', -1); // erase cookie let adUnits = getAdUnits(); let unmodified = getAdUnits(); let innerAdUnits; expect(isPubcidEnabled()).to.be.false; requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - expect(getCookie(COOKIE_NAME)).to.be.null; + expect(getCookie(ID_NAME)).to.be.null; assert.deepEqual(innerAdUnits, unmodified); setConfig({enable: true}); // reset requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); @@ -133,7 +220,6 @@ describe('Publisher Common ID', function () { it('change expiration time', function () { setConfig({expInterval: 100}); - setCookie(COOKIE_NAME, '', -1); // erase cookie expect(getExpInterval()).to.equal(100); let adUnits = getAdUnits(); let innerAdUnits; @@ -142,7 +228,24 @@ describe('Publisher Common ID', function () { unit.bids.forEach((bid) => { expect(bid).to.have.deep.nested.property('crumbs.pubcid'); }); - }) + }); + }); + + it('read only', function() { + setConfig({ + readOnly: true + }); + + const config = getPubcidConfig(); + expect(config.readOnly).to.be.true; + expect(config.typeEnabled).to.equal('html5'); + + let adUnits = getAdUnits(); + let innerAdUnits; + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + const pubcid = localStorage.getItem(ID_NAME); + expect(pubcid).to.be.null; }); }); @@ -192,4 +295,44 @@ describe('Publisher Common ID', function () { }); }); }); + + describe('Storage item functions', () => { + beforeEach(() => { cleanUp(); }); + afterEach(() => { cleanUp(); }); + + it('Test set', () => { + const key = ID_NAME; + const val = 'test-set-value'; + // Set item in localStorage + const now = Date.now(); + setStorageItem(key, val, 100); + // Check both item and expiry time are stored + const expVal = localStorage.getItem(key + EXP); + const storedVal = localStorage.getItem(key); + // Verify expiry + expect(expVal).to.not.be.null; + const expDate = new Date(expVal); + expect((expDate.getTime() - now) / 1000).to.be.closeTo(100 * 60, 5); + // Verify value + expect(storedVal).to.equal(val); + }); + + it('Test get and remove', () => { + const key = ID_NAME; + const val = 'test-get-remove'; + setStorageItem(key, val, 10); + expect(getStorageItem(key)).to.equal(val); + removeStorageItem(key); + expect(getStorageItem(key)).to.be.null; + }); + + it('Test expiry', () => { + const key = ID_NAME; + const val = 'test-expiry'; + setStorageItem(key, val, -1); + expect(localStorage.getItem(key)).to.equal(val); + expect(getStorageItem(key)).to.be.null; + expect(localStorage.getItem(key)).to.be.null; + }); + }); }); From e119938c80a34fec237d1a0c8a97429f88fab4b5 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Thu, 18 Apr 2019 10:31:28 -0700 Subject: [PATCH 1164/1594] Rubicon BidAdapter - SRA support for >10 bids (#3514) * added support to use multiple requests for SRA requests with more than 10 bids * updated unit test to test SRA dividing 100 bids into 10 requests --- modules/rubiconBidAdapter.js | 58 ++++++++++++--------- test/spec/modules/rubiconBidAdapter_spec.js | 41 ++++++++++----- 2 files changed, 63 insertions(+), 36 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index c57e10aede7..55937a3feda 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -232,30 +232,30 @@ export const spec = { return groupedBids; }, {}); - requests = videoRequests.concat(Object.keys(groupedBidRequests).map(bidGroupKey => { - let bidsInGroup = groupedBidRequests[bidGroupKey]; - - // fastlane SRA has a limit of 10 slots - if (bidsInGroup.length > 10) { - utils.logWarn(`Rubicon bid adapter Warning: single request mode has a limit of 10 bids: ${bidsInGroup.length - 10} bids were not sent`); - bidsInGroup = bidsInGroup.slice(0, 10); - } - - const combinedSlotParams = spec.combineSlotUrlParams(bidsInGroup.map(bidRequest => { - return spec.createSlotParams(bidRequest, bidderRequest); - })); - - // SRA request returns grouped bidRequest arrays not a plain bidRequest - return { - method: 'GET', - url: FASTLANE_ENDPOINT, - data: spec.getOrderedParams(combinedSlotParams).reduce((paramString, key) => { - const propValue = combinedSlotParams[key]; - return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${key}=${encodeURIComponent(propValue)}&` : paramString; - }, '') + `slots=${bidsInGroup.length}&rand=${Math.random()}`, - bidRequest: bidsInGroup, - }; - })); + // fastlane SRA has a limit of 10 slots + const SRA_BID_LIMIT = 10; + + // multiple requests are used if bids groups have more than 10 bids + requests = videoRequests.concat(Object.keys(groupedBidRequests).reduce((aggregate, bidGroupKey) => { + // for each partioned bidGroup, append a bidRequest to requests list + partitionArray(groupedBidRequests[bidGroupKey], SRA_BID_LIMIT).forEach(bidsInGroup => { + const combinedSlotParams = spec.combineSlotUrlParams(bidsInGroup.map(bidRequest => { + return spec.createSlotParams(bidRequest, bidderRequest); + })); + + // SRA request returns grouped bidRequest arrays not a plain bidRequest + aggregate.push({ + method: 'GET', + url: FASTLANE_ENDPOINT, + data: spec.getOrderedParams(combinedSlotParams).reduce((paramString, key) => { + const propValue = combinedSlotParams[key]; + return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${key}=${encodeURIComponent(propValue)}&` : paramString; + }, '') + `slots=${bidsInGroup.length}&rand=${Math.random()}`, + bidRequest: bidsInGroup + }); + }); + return aggregate; + }, [])); } return requests; }, @@ -897,6 +897,16 @@ export function hasValidVideoParams(bid) { return isValid; } +/** + * split array into multiple arrays of defined size + * @param {Array} array + * @param {number} size + * @returns {Array} + */ +function partitionArray(array, size) { + return array.map((e, i) => (i % size === 0) ? array.slice(i, i + size) : null).filter((e) => e) +} + var hasSynced = false; export function resetUserSync() { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index f3b244b1bc1..33e5d04466a 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -957,7 +957,7 @@ describe('the rubicon adapter', function () { }); }); - it('should not send more than 10 bids in a request', function () { + it('should not send more than 10 bids in a request (split into separate requests with <= 10 bids each)', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { const config = { 'rubicon.singleRequest': true @@ -965,27 +965,44 @@ describe('the rubicon adapter', function () { return config[key]; }); - for (let i = 0; i < 20; i++) { + let serverRequests; + let data; + + // TEST '10' BIDS, add 9 to 1 existing bid + for (let i = 0; i < 9; i++) { let bidCopy = clone(bidderRequest.bids[0]); bidCopy.params.zoneId = `${i}0000`; bidderRequest.bids.push(bidCopy); } - - const serverRequests = spec.buildRequests(bidderRequest.bids, bidderRequest); - - // if bids are greater than 10, additional bids are dropped + serverRequests = spec.buildRequests(bidderRequest.bids, bidderRequest); + // '10' bids per SRA request: so there should be 1 request + expect(serverRequests.length).to.equal(1); + // and that one request should have data from 10 bids expect(serverRequests[0].bidRequest).to.have.lengthOf(10); - // check that slots param value matches - const foundSlotsCount = serverRequests[0].data.indexOf('&slots=10&'); - expect(foundSlotsCount !== -1).to.equal(true); - + expect(serverRequests[0].data.indexOf('&slots=10&') !== -1).to.equal(true); // check that zone_id has 10 values (since all zone_ids are unique all should exist in get param) - const data = parseQuery(serverRequests[0].data); - + data = parseQuery(serverRequests[0].data); expect(data).to.be.a('object'); expect(data).to.have.property('zone_id'); expect(data.zone_id.split(';')).to.have.lengthOf(10); + + // TEST '100' BIDS, add 90 to the previously added 10 + for (let i = 0; i < 90; i++) { + let bidCopy = clone(bidderRequest.bids[0]); + bidCopy.params.zoneId = `${(i + 10)}0000`; + bidderRequest.bids.push(bidCopy); + } + serverRequests = spec.buildRequests(bidderRequest.bids, bidderRequest); + // '100' bids: should be '10' SRA requests + expect(serverRequests.length).to.equal(10); + // check that each request has 10 items + serverRequests.forEach((serverRequest) => { + // and that one request should have data from 10 bids + expect(serverRequest.bidRequest).to.have.lengthOf(10); + // check that slots param value matches + expect(serverRequest.data.indexOf('&slots=10&') !== -1).to.equal(true); + }); }); it('should not group bid requests if singleRequest does not equal true', function () { From 8016edbdea4ce446c58f55f8cd46cab78344aef4 Mon Sep 17 00:00:00 2001 From: Andrew Slagle <42588549+spotxslagle@users.noreply.github.com> Date: Thu, 18 Apr 2019 18:16:18 -0600 Subject: [PATCH 1165/1594] SpotX: Add hide_skin parameter (#3760) --- modules/spotxBidAdapter.js | 4 ++++ modules/spotxBidAdapter.md | 4 +++- test/spec/modules/spotxBidAdapter_spec.js | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/spotxBidAdapter.js b/modules/spotxBidAdapter.js index bc109ccc635..6e374b991d3 100644 --- a/modules/spotxBidAdapter.js +++ b/modules/spotxBidAdapter.js @@ -84,6 +84,10 @@ export const spec = { versionOrtb: ORTB_VERSION }; + if (utils.getBidIdParameter('hide_skin', bid.params) != '') { + ext.hide_skin = +!!utils.getBidIdParameter('hide_skin', bid.params); + } + if (utils.getBidIdParameter('ad_volume', bid.params) != '') { ext.ad_volume = utils.getBidIdParameter('ad_volume', bid.params); } diff --git a/modules/spotxBidAdapter.md b/modules/spotxBidAdapter.md index db5fd448e04..b9907e5bbd2 100644 --- a/modules/spotxBidAdapter.md +++ b/modules/spotxBidAdapter.md @@ -63,7 +63,8 @@ This adapter requires setup and approval from the SpotX team. click_to_replay: '1', continue_out_of_view: '1', ad_volume: '100', - content_container_id: 'video1' + content_container_id: 'video1', + hide_skin: '1' } } } @@ -121,6 +122,7 @@ function myOutstreamFunction(bid) { script.setAttribute('data-spotx_click_to_replay', '1'); script.setAttribute('data-spotx_continue_out_of_view', '1'); script.setAttribute('data-spotx_ad_volume', '100'); + script.setAttribute('data-spotx_hide_skin', '1'); if (bid.renderer.config.inIframe && window.document.getElementById(bid.renderer.config.inIframe).nodeName == 'IFRAME') { let rawframe = window.document.getElementById(bid.renderer.config.inIframe); let framedoc = rawframe.contentDocument; diff --git a/test/spec/modules/spotxBidAdapter_spec.js b/test/spec/modules/spotxBidAdapter_spec.js index ba015331b68..33cf85a855e 100644 --- a/test/spec/modules/spotxBidAdapter_spec.js +++ b/test/spec/modules/spotxBidAdapter_spec.js @@ -150,6 +150,7 @@ describe('the spotx adapter', function () { expect(request.data.imp.video.ext).to.deep.equal({ ad_volume: 1, ad_unit: 'incontent', + hide_skin: 1, outstream_options: {foo: 'bar'}, outstream_function: '987', custom: {bar: 'foo'}, From 9ffff943bc14ffa39fdd95c3ee2a9c04b5a1e98e Mon Sep 17 00:00:00 2001 From: Rich Audience Date: Fri, 19 Apr 2019 02:18:50 +0200 Subject: [PATCH 1166/1594] Added dealId to response (#3762) --- modules/richAudienceBidAdapter.js | 1 + test/spec/modules/richAudienceBidAdapter_spec.js | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/richAudienceBidAdapter.js b/modules/richAudienceBidAdapter.js index 9701bb4ec48..bd47e481a76 100644 --- a/modules/richAudienceBidAdapter.js +++ b/modules/richAudienceBidAdapter.js @@ -91,6 +91,7 @@ export const spec = { netRevenue: response.netRevenue, currency: response.currency, ttl: response.ttl, + dealId: response.dealId, }; if (response.media_type === 'video') { diff --git a/test/spec/modules/richAudienceBidAdapter_spec.js b/test/spec/modules/richAudienceBidAdapter_spec.js index 689c29a2646..c974ff70ce3 100644 --- a/test/spec/modules/richAudienceBidAdapter_spec.js +++ b/test/spec/modules/richAudienceBidAdapter_spec.js @@ -81,7 +81,9 @@ describe('Rich Audience adapter tests', function () { creative_id: '189198063', netRevenue: true, currency: 'USD', - ttl: 300 + ttl: 300, + dealId: 'dealId' + } }; @@ -95,7 +97,8 @@ describe('Rich Audience adapter tests', function () { netRevenue: true, currency: 'USD', ttl: 300, - vastXML: '' + vastXML: '', + dealId: 'dealId' } }; @@ -228,6 +231,7 @@ describe('Rich Audience adapter tests', function () { expect(bid.netRevenue).to.equal(true); expect(bid.currency).to.equal('USD'); expect(bid.ttl).to.equal(300); + expect(bid.dealId).to.equal('dealId'); }); it('no banner media response', function () { From 12eceeabf984fbf4c706b5c6f3f606ea8e45f420 Mon Sep 17 00:00:00 2001 From: Vadim Mazzherin Date: Fri, 19 Apr 2019 20:22:05 +0600 Subject: [PATCH 1167/1594] add ShowHeroes Adapter (#3733) --- modules/shBidAdapter.js | 184 ++++++++++++++++++++++++ modules/shBidAdapter.md | 69 +++++++++ test/spec/modules/shBidAdapter_spec.js | 187 +++++++++++++++++++++++++ 3 files changed, 440 insertions(+) create mode 100644 modules/shBidAdapter.js create mode 100644 modules/shBidAdapter.md create mode 100644 test/spec/modules/shBidAdapter_spec.js diff --git a/modules/shBidAdapter.js b/modules/shBidAdapter.js new file mode 100644 index 00000000000..94d28770548 --- /dev/null +++ b/modules/shBidAdapter.js @@ -0,0 +1,184 @@ +import * as utils from '../src/utils'; +import { config } from '../src/config'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { VIDEO, BANNER } from '../src/mediaTypes'; + +const PROD_ENDPOINT = 'https://bs1.showheroes.com/api/v1/bid'; +const STAGE_ENDPOINT = 'https://bid-service.stage.showheroes.com/api/v1/bid'; +const PROD_PUBLISHER_TAG = 'https://static.showheroes.com/publishertag.js'; +const STAGE_PUBLISHER_TAG = 'https://pubtag.stage.showheroes.com/publishertag.js'; +const PROD_VL = 'https://video-library.showheroes.com'; +const STAGE_VL = 'https://video-library.stage.showheroes.com'; +const BIDDER_CODE = 'showheroes-bs'; +const TTL = 300; + +export const spec = { + code: BIDDER_CODE, + aliases: ['showheroesBs'], + supportedMediaTypes: [VIDEO, BANNER], + isBidRequestValid: function(bid) { + return !!bid.params.playerId; + }, + buildRequests: function(validBidRequests, bidderRequest) { + const pageURL = validBidRequests[0].params.contentPageUrl || bidderRequest.refererInfo.referer; + const isStage = !!validBidRequests[0].params.stage; + const isBanner = !!validBidRequests[0].mediaTypes.banner; + + let adUnits = validBidRequests.map((bid) => { + const vpaidMode = utils.getBidIdParameter('vpaidMode', bid.params); + + let sizes = bid.sizes.length === 1 ? bid.sizes[0] : bid.sizes; + if (sizes && !sizes.length) { + let mediaSize; + if (!isBanner) { + mediaSize = bid.mediaTypes.video.playerSize; + } else { + mediaSize = bid.mediaTypes.banner.sizes; + } + if (utils.isArray(mediaSize[0])) { + sizes = mediaSize[0]; + } else if (utils.isNumber(mediaSize[0])) { + sizes = mediaSize; + } + } + + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + + let streamType = 2; + + if (vpaidMode && context === 'instream') { + streamType = 1; + } + if (context === 'outstream' || isBanner) { + streamType = 5; + } + + return { + type: streamType, + bidId: bid.bidId, + mediaType: isBanner ? BANNER : VIDEO, + playerId: utils.getBidIdParameter('playerId', bid.params), + auctionId: bidderRequest.auctionId, + bidderCode: BIDDER_CODE, + gdprConsent: bidderRequest.gdprConsent, + start: +new Date(), + timeout: 3000, + video: { + width: sizes[0], + height: sizes[1] + }, + }; + }); + + return { + url: isStage ? STAGE_ENDPOINT : PROD_ENDPOINT, + method: 'POST', + options: {contentType: 'application/json', accept: 'application/json'}, + data: { + 'user': [], + 'meta': { + 'pageURL': encodeURIComponent(pageURL), + 'vastCacheEnabled': (!!config.getConfig('cache') && !isBanner) || false, + 'isDesktop': utils.getWindowTop().document.documentElement.clientWidth > 700, + 'stage': isStage || undefined + }, + 'requests': adUnits, + 'debug': validBidRequests[0].params.debug || false, + } + }; + }, + interpretResponse: function(response, request) { + return createBids(response.body, request.data); + }, + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = []; + + if (!serverResponses.length || !serverResponses[0].body.userSync) { + return syncs; + } + + const userSync = serverResponses[0].body.userSync; + + if (syncOptions.iframeEnabled) { + (userSync.iframes || []).forEach(url => { + syncs.push({ + type: 'iframe', + url + }); + }); + } + + if (syncOptions.pixelEnabled) { + (userSync.pixels || []).forEach(url => { + syncs.push({ + type: 'image', + url + }); + }); + } + return syncs; + }, +}; + +function createBids(bidRes, reqData) { + if (bidRes && (!Array.isArray(bidRes.bids) || bidRes.bids.length < 1)) { + return []; + } + + const bids = []; + const bidMap = {}; + (reqData.requests || []).forEach((bid) => { + bidMap[bid.bidId] = bid; + }); + + bidRes.bids.forEach(function (bid) { + const reqBid = bidMap[bid.bidId]; + let bidUnit = {}; + bidUnit.cpm = bid.cpm; + bidUnit.requestId = bid.bidId; + bidUnit.currency = bid.currency; + bidUnit.mediaType = reqBid.mediaType || VIDEO; + bidUnit.ttl = TTL; + bidUnit.creativeId = 'c_' + bid.bidId; + bidUnit.netRevenue = true; + bidUnit.width = bid.video.width; + bidUnit.height = bid.video.height; + if (bid.vastXml) { + bidUnit.vastXml = bid.vastXml; + bidUnit.adResponse = { + content: bid.vastXml, + }; + } + if (bid.vastTag) { + bidUnit.vastUrl = bid.vastTag; + } + if (reqBid.mediaType === BANNER) { + bidUnit.ad = getBannerHtml(bid, reqBid, reqData); + } + bids.push(bidUnit); + }); + + return bids; +} + +function getBannerHtml (bid, reqBid, reqData) { + const isStage = !!reqData.meta.stage; + const pubTag = isStage ? STAGE_PUBLISHER_TAG : PROD_PUBLISHER_TAG; + const vlHost = isStage ? STAGE_VL : PROD_VL; + return ` + + + +
+ + `; +} + +registerBidder(spec); diff --git a/modules/shBidAdapter.md b/modules/shBidAdapter.md new file mode 100644 index 00000000000..b1ca1782725 --- /dev/null +++ b/modules/shBidAdapter.md @@ -0,0 +1,69 @@ +# Overview + +Module Name: ShowHeroes Bidder Adapter + +Module Type: Bidder Adapter + +Maintainer: tech@showheroes.com + +# Description + +Module that connects to ShowHeroes demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'video', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream', + } + }, + bids: [ + { + bidder: "showheroes-bs", + params: { + playerId: '0151f985-fb1a-4f37-bb26-cfc62e43ec05', + vpaidMode: true // by default is 'false' + } + } + ] + }, + { + code: 'video', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream', + } + }, + bids: [ + { + bidder: "showheroes-bs", + params: { + playerId: '0151f985-fb1a-4f37-bb26-cfc62e43ec05', + vpaidMode: true // by default is 'false' + } + } + ] + }, + { + code: 'banner', + mediaTypes: { + banner: { + sizes: [[640, 480]], + } + }, + bids: [ + { + bidder: "showheroes-bs", + params: { + playerId: '0151f985-fb1a-4f37-bb26-cfc62e43ec05', + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/shBidAdapter_spec.js b/test/spec/modules/shBidAdapter_spec.js new file mode 100644 index 00000000000..588d4c54150 --- /dev/null +++ b/test/spec/modules/shBidAdapter_spec.js @@ -0,0 +1,187 @@ +import {expect} from 'chai' +import {spec} from 'modules/shBidAdapter' +import {newBidder} from 'src/adapters/bidderFactory' +import {VIDEO, BANNER} from 'src/mediaTypes' + +const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } +} + +const gdpr = { + 'gdprConsent': { + 'consentString': 'BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA', + 'gdprApplies': true + } +} + +const bidRequestVideo = { + 'bidder': 'showheroes-bs', + 'params': { + 'playerId': '47427aa0-f11a-4d24-abca-1295a46a46cd', + }, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'context': 'instream', + } + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[640, 480]], + 'bidId': '38b373e1e31c18', + 'bidderRequestId': '12e3ade2543ba6', + 'auctionId': '43aa080090a47f', +} + +const bidRequestVideoVpaid = { + 'bidder': 'showheroes-bs', + 'params': { + 'playerId': '47427aa0-f11a-4d24-abca-1295a46a46cd', + 'vpaidMode': true, + }, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'context': 'instream', + } + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[640, 480]], + 'bidId': '38b373e1e31c18', + 'bidderRequestId': '12e3ade2543ba6', + 'auctionId': '43aa080090a47f', +} + +const bidRequestBanner = { + 'bidder': 'showheroes-bs', + 'params': { + 'playerId': '47427aa0-f11a-4d24-abca-1295a46a46cd', + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[640, 360]] + } + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[640, 480]], + 'bidId': '38b373e1e31c18', + 'bidderRequestId': '12e3ade2543ba6', + 'auctionId': '43aa080090a47f', +} + +describe('shBidAdapter', 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 () { + const request = { + 'params': { + 'playerId': '47427aa0-f11a-4d24-abca-1295a46a46cd', + } + } + expect(spec.isBidRequestValid(request)).to.equal(true) + }) + + it('should return false when required params are not passed', function () { + const request = { + 'params': {} + } + expect(spec.isBidRequestValid(request)).to.equal(false) + }) + }) + + describe('buildRequests', function () { + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests([bidRequestVideo], bidderRequest) + expect(request.method).to.equal('POST') + }) + + it('should attach valid params to the payload when type is video', function () { + const request = spec.buildRequests([bidRequestVideo], bidderRequest) + const payload = request.data.requests[0]; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('playerId', '47427aa0-f11a-4d24-abca-1295a46a46cd'); + expect(payload).to.have.property('mediaType', VIDEO); + expect(payload).to.have.property('type', 2); + }) + + it('should attach valid params to the payload when type is video & vpaid mode on', function () { + const request = spec.buildRequests([bidRequestVideoVpaid], bidderRequest) + const payload = request.data.requests[0]; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('playerId', '47427aa0-f11a-4d24-abca-1295a46a46cd'); + expect(payload).to.have.property('mediaType', VIDEO); + expect(payload).to.have.property('type', 1); + }) + + it('should attach valid params to the payload when type is banner', function () { + const request = spec.buildRequests([bidRequestBanner], bidderRequest) + const payload = request.data.requests[0]; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('playerId', '47427aa0-f11a-4d24-abca-1295a46a46cd'); + expect(payload).to.have.property('mediaType', BANNER); + expect(payload).to.have.property('type', 5); + }) + + it('passes gdpr if present', function () { + const request = spec.buildRequests([bidRequestVideo], {...bidderRequest, ...gdpr}) + const payload = request.data.requests[0]; + expect(payload).to.be.an('object'); + expect(payload.gdprConsent).to.eql(gdpr.gdprConsent) + }) + }) + + describe('interpretResponse', function () { + it('handles nobid responses', function () { + expect(spec.interpretResponse({body: {}}, {data: {meta: {}}}).length).to.equal(0) + expect(spec.interpretResponse({body: []}, {data: {meta: {}}}).length).to.equal(0) + }) + + const response = { + 'bids': [{ + 'cpm': 5, + 'currency': 'EUR', + 'bidId': '38b373e1e31c18', + 'video': {'width': 640, 'height': 480}, + 'vastTag': 'https:\/\/video-library.stage.showheroes.com\/commercial\/wrapper?player_id=47427aa0-f11a-4d24-abca-1295a46a46cd&ad_bidder=showheroes-bs&master_shadt=1&description_url=https%3A%2F%2Fbid-service.stage.showheroes.com%2Fvast%2Fad%2Fcache%2F4840b920-40e1-4e09-9231-60bbf088c8d6', + }], + } + + it('should get correct bid response when type is video', function () { + const request = spec.buildRequests([bidRequestVideo], bidderRequest) + const expectedResponse = [ + { + 'cpm': 5, + 'creativeId': 'c_38b373e1e31c18', + 'currency': 'EUR', + 'width': 640, + 'height': 480, + 'mediaType': 'video', + 'netRevenue': true, + 'vastUrl': 'https://video-library.stage.showheroes.com/commercial/wrapper?player_id=47427aa0-f11a-4d24-abca-1295a46a46cd&ad_bidder=showheroes-bs&master_shadt=1&description_url=https%3A%2F%2Fbid-service.stage.showheroes.com%2Fvast%2Fad%2Fcache%2F4840b920-40e1-4e09-9231-60bbf088c8d6', + 'requestId': '38b373e1e31c18', + 'ttl': 300, + } + ] + + const result = spec.interpretResponse({'body': response}, request) + expect(result).to.deep.equal(expectedResponse) + }) + + it('should get correct bid response when type is banner', function () { + const request = spec.buildRequests([bidRequestBanner], bidderRequest) + + const result = spec.interpretResponse({'body': response}, request) + expect(result[0]).to.have.property('mediaType', BANNER); + expect(result[0].ad).to.include('' + adm: '', + nurl: '//uat-net.technoratimedia.com/openrtb/tags?ID=k5JkFVQ1RJT05fSU1QX0lEPXYyZjczN&AUCTION_PRICE=${AUCTION_PRICE}' }; let bidResponse2 = { id: '10865933907263800~9999~0', - impid: '9876abcd~300x600', + impid: 'b9876abcd-300x600', price: 1.99, crid: '9993-013', - adm: '' + adm: '', + nurl: '//uat-net.technoratimedia.com/openrtb/tags?ID=OTk5OX4wJkFVQ1RJT05fU0VBVF9JR&AUCTION_PRICE=${AUCTION_PRICE}' }; let serverResponse; @@ -282,6 +436,52 @@ describe('synacormediaBidAdapter ', function () { } }; }); + + it('should return 1 video bid when 1 bid is in the video response', function () { + let serverRespVideo = { + body: { + id: 'abcd1234', + seatbid: [ + { + bid: [ + { + id: '11339128001692337~9999~0', + impid: 'v2da7322b2df61f-640x480', + price: 0.45, + nurl: 'https://uat-net.technoratimedia.com/openrtb/tags?ID=QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk&AUCTION_PRICE=${AUCTION_PRICE}', + adm: '\n\n\n\nSynacor Media Ad Server - 9999\nhttps://uat-net.technoratimedia.com/openrtb/tags?ID=QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk&AUCTION_PRICE=${AUCTION_PRICE}\n\n\n', + adomain: [ 'psacentral.org' ], + cid: 'bidder-crid', + crid: 'bidder-cid', + cat: [] + } + ], + seat: '9999' + } + ] + } + }; + + // serverResponse.body.seatbid[0].bid.push(bidResponse); + let resp = spec.interpretResponse(serverRespVideo); + expect(resp).to.be.an('array').to.have.lengthOf(1); + expect(resp[0]).to.eql({ + requestId: '2da7322b2df61f', + adId: '11339128001692337-9999-0', + cpm: 0.45, + width: 640, + height: 480, + creativeId: '9999_bidder-cid', + currency: 'USD', + 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: 60, + videoCacheKey: 'QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk', + vastUrl: 'https://uat-net.technoratimedia.com/openrtb/tags?ID=QVVDVElPTl9JRD1lOTBhYWU1My1hZDkwLTRkNDEtYTQxMC1lZDY1MjIxMDc0ZGMmQVVDVElPTl9CSURfSUQ9MTEzMzkxMjgwMDE2OTIzMzd-OTk5OX4wJkFVQ1RJT05fU0VBVF9JRD05OTk5JkFVQ1RJT05fSU1QX0lEPXYyZGE3MzIyYjJkZjYxZi02NDB4NDgwJkFDVE9SX1JFRj1ha2thLnRjcDovL2F3cy1lYXN0MUBhZHMxMy5jYXAtdXNlMS5zeW5hY29yLmNvbToyNTUxL3VzZXIvJGNMYmZiIy0xOTk4NTIzNTk3JlNFQVRfSUQ9cHJlYmlk&AUCTION_PRICE=0.45' + }); + }); + it('should return 1 bid when 1 bid is in the response', function () { serverResponse.body.seatbid[0].bid.push(bidResponse); let resp = spec.interpretResponse(serverResponse); @@ -292,11 +492,11 @@ describe('synacormediaBidAdapter ', function () { cpm: 0.13, width: 300, height: 250, - creativeId: '9998~1022-250', + creativeId: '9998_1022-250', currency: 'USD', netRevenue: true, mediaType: BANNER, - ad: '', + ad: '', ttl: 60 }); }); @@ -315,31 +515,34 @@ describe('synacormediaBidAdapter ', function () { cpm: 0.13, width: 300, height: 250, - creativeId: '9998~1022-250', + creativeId: '9998_1022-250', currency: 'USD', netRevenue: true, mediaType: BANNER, - ad: '', + ad: '', ttl: 60 }); + expect(resp[1]).to.eql({ requestId: '9876abcd', adId: '10865933907263800-9999-0', cpm: 1.99, width: 300, height: 600, - creativeId: '9999~9993-013', + creativeId: '9999_9993-013', currency: 'USD', netRevenue: true, mediaType: BANNER, - ad: '', + ad: '', ttl: 60 }); }); + it('should not return a bid when no bid is in the response', function () { let resp = spec.interpretResponse(serverResponse); expect(resp).to.be.an('array').that.is.empty; }); + it('should not return a bid when there is no response body', function () { expect(spec.interpretResponse({ body: null })).to.not.exist; expect(spec.interpretResponse({ body: 'some error text' })).to.not.exist; From 253cbf4de5d575a70a288b3249d7bf4f1f7ddfc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E9=9B=A8=E8=BB=92=20=D0=9F=D0=B5=D1=82=D1=80?= Date: Mon, 22 Apr 2019 20:09:08 +0200 Subject: [PATCH 1178/1594] Improve emoteevBidAdapter (#3673) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Improve emoteevBidAdapter ** Squash several pending changes - Improve test coverage - Extreme programming: 100% test coverage - Document important constants - Extreme programming: document all functions - Imperative shell, functional core - Send events onBidWon and onTimeout - Report GDPR relevance and consent Code documentation uses JSDoc tags wherever possible. See the following link for general explanation of the notation used: https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler ** Test coverage - 100% Statements 110/110 - 100% Branches 55/55 - 100% Functions 28/28 - 100% Lines 99/99 ** Integration tests Tested against production endpoint with the possible combinations of these following parameters: - Browser: · Chrome Canary 75.0.3739.0 · Firefox Developer Edition 67.0b3 (64-bit) · Safari version 12.0.3 (14606.4.5) · Tor Browser 8.0.6 (based on Mozilla Firefox 60.5.1esr) - Integration page: · integrationExamples/gpt/hello_world_emoteev.html · https://jsfiddle.net/8aqotw1k/6/ Localhost test server launched with: $ npm install && gulp serve * Tentative CI fix for IE and Edge webGL test https://circleci.com/gh/prebid/Prebid.js/2052 * Tentative CI fix for IE and Edge webGL test #2 * Give up on webGL tests Has anybody an idea to make it pass? https://circleci.com/gh/prebid/Prebid.js/2056 New test coverage: - 94.5% Statements 103/109 - 98.18% Branches 54/55 - 100% Functions 28/28 - 93.88% Lines 92/98 * Avoid useless noice in diff * Remove unallowed metric pixel ON_ADAPTER_CALLED --- .../gpt/hello_world_emoteev.html | 117 ++- modules/emoteevBidAdapter.js | 465 ++++++++-- ...teevBidAdapter.md => emoteevBidAdapter.md} | 0 test/spec/modules/emoteevBidAdapter_spec.js | 860 +++++++++++++----- 4 files changed, 1056 insertions(+), 386 deletions(-) rename modules/{emokteevBidAdapter.md => emoteevBidAdapter.md} (100%) diff --git a/integrationExamples/gpt/hello_world_emoteev.html b/integrationExamples/gpt/hello_world_emoteev.html index 5e4d0716d2b..5a33e2d9701 100644 --- a/integrationExamples/gpt/hello_world_emoteev.html +++ b/integrationExamples/gpt/hello_world_emoteev.html @@ -5,74 +5,69 @@ + setTimeout(function () { + initAdserver(); + }, FAILSAFE_TIMEOUT); + googletag.cmd.push(function () { + googletag.defineSlot('/19968336/header-bid-tag-1', sizes, 'div-1') + .addService(googletag.pubads()); + googletag.pubads().enableSingleRequest(); + googletag.enableServices(); + }); + @@ -80,9 +75,9 @@

Basic Prebid.js Example

Div-1
diff --git a/modules/emoteevBidAdapter.js b/modules/emoteevBidAdapter.js index 9b03b357818..4436d39bb70 100644 --- a/modules/emoteevBidAdapter.js +++ b/modules/emoteevBidAdapter.js @@ -1,76 +1,322 @@ +/** + * This file contains Emoteev bid adpater. + * + * It is organised as follows: + * - Constants values; + * - Spec API functions, which should be pristine pure; + * - Ancillary functions, which should be as pure as possible; + * - Adapter API, where unpure side-effects happen. + * + * The code style is « functional core, imperative shell ». + * + * @link https://www.emoteev.io + * @file This files defines the spec of EmoteevBidAdapter. + * @author Emoteev Engineering . + */ + import {registerBidder} from '../src/adapters/bidderFactory'; import {BANNER} from '../src/mediaTypes'; -import * as utils from '../src/utils'; +import { + triggerPixel, + getUniqueIdentifierStr, + contains, + deepAccess, + isArray, + getParameterByName +} from '../src/utils'; import {config} from '../src/config'; +import * as url from '../src/url'; +import {getCookie} from './pubCommonId'; export const BIDDER_CODE = 'emoteev'; -export const AK_PBJS_VERSION = '1.35.0'; -export const EMOTEEV_BASE_URL = 'https://prebid.emoteev.io'; -export const EMOTEEV_BASE_URL_STAGING = 'https://prebid-staging.emoteev.io'; -export const EMOTEEV_BASE_URL_DEVELOPMENT = 'http://localhost:3000'; +/** + * Version number of the adapter API. + */ +export const ADAPTER_VERSION = '1.35.0'; + +export const DOMAIN = 'prebid.emoteev.io'; +export const DOMAIN_STAGING = 'prebid-staging.emoteev.io'; +export const DOMAIN_DEVELOPMENT = 'localhost:3000'; -export const ENDPOINT_PATH = '/api/prebid/bid'; -export const USER_SYNC_IFRAME_URL_PATH = '/api/prebid/sync-iframe'; -export const USER_SYNC_IMAGE_URL_PATH = '/api/prebid/sync-image'; +/** + * Path of Emoteev endpoint for events. + */ +export const EVENTS_PATH = '/api/ad_event.json'; + +/** + * Path of Emoteev bidder. + */ +export const BIDDER_PATH = '/api/prebid/bid'; +export const USER_SYNC_IFRAME_PATH = '/api/prebid/sync-iframe'; +export const USER_SYNC_IMAGE_PATH = '/api/prebid/sync-image'; export const PRODUCTION = 'production'; export const STAGING = 'staging'; export const DEVELOPMENT = 'development'; export const DEFAULT_ENV = PRODUCTION; -export const conformBidRequest = bidRequest => { +export const ON_ADAPTER_CALLED = 'on_adapter_called'; +export const ON_BID_WON = 'on_bid_won'; +export const ON_BIDDER_TIMEOUT = 'on_bidder_timeout'; + +/** + * Pure function. See http://prebid.org/dev-docs/bidder-adaptor.html#valid-build-requests-array for detailed semantic. + * + * @param {AdUnit.bidRequest} bidRequest + * @returns {boolean} Is this bidRequest valid? + */ +export const isBidRequestValid = (bidRequest) => { + return !!( + bidRequest && + bidRequest.params && + deepAccess(bidRequest, 'params.adSpaceId') && + bidRequest.bidder === BIDDER_CODE && + validateSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes'))); +}; + +/** + * Pure function. See http://prebid.org/dev-docs/bidder-adaptor.html#serverrequest-objects for detailed semantic. + * + * @param {string} env Emoteev environment parameter + * @param {boolean} debug Pbjs debug parameter. + * @param {string} currency See http://prebid.org/dev-docs/modules/currency.html for detailed semantic. + * @param {Array} validBidRequests Takes an array of bid requests, which are guaranteed to have passed the isBidRequestValid() test. + * @param bidderRequest General context for a bidder request being constructed + * @returns {ServerRequest} + */ +export const buildRequests = (env, debug, currency, validBidRequests, bidderRequest) => { return { - params: bidRequest.params, - crumbs: bidRequest.crumbs, - sizes: bidRequest.sizes, - bidId: bidRequest.bidId, - bidderRequestId: bidRequest.bidderRequestId, + method: 'POST', + url: bidderUrl(env), + data: JSON.stringify(requestsPayload(debug, currency, validBidRequests, bidderRequest)) }; }; -export const emoteevDebug = (parameterDebug, configDebug) => { - if (parameterDebug && parameterDebug.length && parameterDebug.length > 0) return JSON.parse(parameterDebug); - else if (configDebug) return configDebug; - else return false; -}; +/** + * Pure function. See http://prebid.org/dev-docs/bidder-adaptor.html#interpreting-the-response for detailed semantic. + * + * @param {Array} serverResponse.body The body of the server response is an array of bid objects. + * @returns {Array} + */ +export const interpretResponse = (serverResponse) => serverResponse.body; -export const emoteevEnv = (parameteremoteevEnv, configemoteevEnv) => { - if (utils.contains([PRODUCTION, STAGING, DEVELOPMENT], parameteremoteevEnv)) return parameteremoteevEnv; - else if (utils.contains([PRODUCTION, STAGING, DEVELOPMENT], configemoteevEnv)) return configemoteevEnv; - else return DEFAULT_ENV; +/** + * Pure function. See http://prebid.org/dev-docs/bidder-adaptor.html#registering-on-set-targeting for detailed semantic. + * + * @param {string} env Emoteev environment parameter. + * @param {BidRequest} bidRequest + * @returns {UrlObject} + */ +export function onAdapterCalled(env, bidRequest) { + return { + protocol: 'https', + hostname: domain(env), + pathname: EVENTS_PATH, + search: { + eventName: ON_ADAPTER_CALLED, + pubcId: deepAccess(bidRequest, 'crumbs.pubcid'), + bidId: bidRequest.bidId, + adSpaceId: deepAccess(bidRequest, 'params.adSpaceId'), + cache_buster: getUniqueIdentifierStr() + } + }; +} + +/** + * Pure function. See http://prebid.org/dev-docs/bidder-adaptor.html#registering-on-bid-won for detailed semantic. + * + * @param {string} env Emoteev environment parameter. + * @param {string} pubcId Publisher common id. See http://prebid.org/dev-docs/modules/pubCommonId.html for detailed semantic. + * @param bidObject + * @returns {UrlObject} + */ +export const onBidWon = (env, pubcId, bidObject) => { + const bidId = bidObject.requestId; + return { + protocol: 'https', + hostname: domain(env), + pathname: EVENTS_PATH, + search: { + eventName: ON_BID_WON, + pubcId, + bidId, + cache_buster: getUniqueIdentifierStr() + } + }; }; -export const emoteevOverrides = (parameteremoteevOverrides, configemoteevOverrides) => { - if (parameteremoteevOverrides && parameteremoteevOverrides.length !== 0) { - let parsedParams = null; - try { - parsedParams = JSON.parse(parameteremoteevOverrides); - } catch (error) { - parsedParams = null; +/** + * Pure function. See http://prebid.org/dev-docs/bidder-adaptor.html#registering-on-timeout for detailed semantic. + * + * @param {string} env Emoteev environment parameter. + * @param {BidRequest} bidRequest + * @returns {UrlObject} + */ +export const onTimeout = (env, bidRequest) => { + return { + protocol: 'https', + hostname: domain(env), + pathname: EVENTS_PATH, + search: { + eventName: ON_BIDDER_TIMEOUT, + pubcId: deepAccess(bidRequest, 'crumbs.pubcid'), + bidId: bidRequest.bidId, + adSpaceId: deepAccess(bidRequest, 'params.adSpaceId'), + timeout: bidRequest.timeout, + cache_buster: getUniqueIdentifierStr() } - if (parsedParams) return parsedParams; } - if (configemoteevOverrides && Object.keys(configemoteevOverrides).length !== 0) return configemoteevOverrides; - else return {}; }; -export const akUrl = (environment) => { - switch (environment) { +/** + * Pure function. See http://prebid.org/dev-docs/bidder-adaptor.html#registering-user-syncs for detailed semantic. + * + * @param {string} env Emoteev environment parameter + * @param {SyncOptions} syncOptions + * @returns userSyncs + */ +export const getUserSyncs = (env, syncOptions) => { + let syncs = []; + if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: userSyncImageUrl(env), + }); + } + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: userSyncIframeUrl(env), + }); + } + return syncs; +}; + +/** + * Pure function. + * + * @param {string} env Emoteev environment parameter + * @returns {string} The domain for network calls to Emoteev. + */ +export const domain = (env) => { + switch (env) { case DEVELOPMENT: - return EMOTEEV_BASE_URL_DEVELOPMENT; + return DOMAIN_DEVELOPMENT; case STAGING: - return EMOTEEV_BASE_URL_STAGING; + return DOMAIN_STAGING; default: - return EMOTEEV_BASE_URL; + return DOMAIN; } }; -export const endpointUrl = (parameteremoteevEnv, configemoteevEnv) => akUrl(emoteevEnv(parameteremoteevEnv, configemoteevEnv)).concat(ENDPOINT_PATH); -export const userSyncIframeUrl = (parameteremoteevEnv, configemoteevEnv) => akUrl(emoteevEnv(parameteremoteevEnv, configemoteevEnv)).concat(USER_SYNC_IFRAME_URL_PATH); -export const userSyncImageUrl = (parameteremoteevEnv, configemoteevEnv) => akUrl(emoteevEnv(parameteremoteevEnv, configemoteevEnv)).concat(USER_SYNC_IMAGE_URL_PATH); +/** + * Pure function. + * + * @param {string} env Emoteev environment parameter + * @returns {string} The full URL which events is sent to. + */ +export const eventsUrl = env => url.format({ + protocol: (env === DEVELOPMENT) ? 'http' : 'https', + hostname: domain(env), + pathname: EVENTS_PATH +}); -export const getViewDimensions = () => { +/** + * Pure function. + * + * @param {string} env Emoteev environment parameter + * @returns {string} The full URL which bidderRequest is sent to. + */ +export const bidderUrl = env => url.format({ + protocol: (env === DEVELOPMENT) ? 'http' : 'https', + hostname: domain(env), + pathname: BIDDER_PATH +}); + +/** + * Pure function. + * + * @param {string} env Emoteev environment parameter + * @returns {string} The full URL called for iframe-based user sync + */ +export const userSyncIframeUrl = env => url.format({ + protocol: (env === DEVELOPMENT) ? 'http' : 'https', + hostname: domain(env), + pathname: USER_SYNC_IFRAME_PATH +}); + +/** + * Pure function. + * + * @param {string} env Emoteev environment parameter + * @returns {string} The full URL called for image-based user sync + */ +export const userSyncImageUrl = env => url.format({ + protocol: (env === DEVELOPMENT) ? 'http' : 'https', + hostname: domain(env), + pathname: USER_SYNC_IMAGE_PATH +}); + +/** + * Pure function. + * + * @param {Array>} sizes + * @returns {boolean} are sizes valid? + */ +const validateSizes = sizes => isArray(sizes) && sizes.some(size => isArray(size) && size.length === 2); + +/** + * Pure function. + * + * @param {BidRequest} bidRequest + * @returns {object} An object which represents a BidRequest for Emoteev server side. + */ +export const conformBidRequest = bidRequest => { + return { + params: bidRequest.params, + crumbs: bidRequest.crumbs, + sizes: bidRequest.sizes, + bidId: bidRequest.bidId, + bidderRequestId: bidRequest.bidderRequestId, + }; +}; + +/** + * Pure function. + * + * @param {boolean} debug Pbjs debug parameter + * @param {string} currency See http://prebid.org/dev-docs/modules/currency.html for detailed information + * @param {BidRequest} validBidRequests + * @param {object} bidderRequest + * @returns + */ +export const requestsPayload = (debug, currency, validBidRequests, bidderRequest) => { + return { + akPbjsVersion: ADAPTER_VERSION, + bidRequests: validBidRequests.map(conformBidRequest), + currency: currency, + debug: debug, + language: navigator.language, + refererInfo: bidderRequest.refererInfo, + deviceInfo: getDeviceInfo( + getDeviceDimensions(window), + getViewDimensions(window, document), + getDocumentDimensions(document), + isWebGLEnabled(document)), + userAgent: navigator.userAgent, + gdprApplies: deepAccess(bidderRequest, 'gdprConsent.gdprApplies'), + gdprConsent: deepAccess(bidderRequest, 'gdprConsent.consentString'), + }; +}; + +/** + * Pure function + * @param {Window} window + * @param {Document} document + * @returns {{width: number, height: number}} View dimensions + */ +export const getViewDimensions = (window, document) => { let w = window; let prefix = 'inner'; @@ -85,14 +331,24 @@ export const getViewDimensions = () => { }; }; -export const getDeviceDimensions = () => { +/** + * Pure function + * @param {Window} window + * @returns {{width: number, height: number}} Device dimensions + */ +export const getDeviceDimensions = (window) => { return { width: window.screen ? window.screen.width : '', height: window.screen ? window.screen.height : '', }; }; -export const getDocumentDimensions = () => { +/** + * Pure function + * @param {Document} document + * @returns {{width: number, height: number}} Document dimensions + */ +export const getDocumentDimensions = (document) => { const de = document.documentElement; const be = document.body; @@ -112,7 +368,12 @@ export const getDocumentDimensions = () => { }; }; -export const isWebGLEnabled = () => { +/** + * Unpure function + * @param {Document} document + * @returns {boolean} Is WebGL enabled? + */ +export const isWebGLEnabled = (document) => { // Create test canvas let canvas = document.createElement('canvas'); @@ -141,6 +402,14 @@ export const isWebGLEnabled = () => { return !!gl; }; +/** + * Pure function + * @param {{width: number, height: number}} deviceDimensions + * @param {{width: number, height: number}} viewDimensions + * @param {{width: number, height: number}} documentDimensions + * @param {boolean} webGL + * @returns {object} Device information + */ export const getDeviceInfo = (deviceDimensions, viewDimensions, documentDimensions, webGL) => { return { browserWidth: viewDimensions.width, @@ -153,62 +422,62 @@ export const getDeviceInfo = (deviceDimensions, viewDimensions, documentDimensio }; }; -const validateSizes = sizes => utils.isArray(sizes) && sizes.some(size => utils.isArray(size) && size.length === 2); +/** + * Pure function + * @param {object} config pbjs config value + * @param {string} parameter Environment override from URL query param. + * @returns One of [PRODUCTION, STAGING, DEVELOPMENT]. + */ +export const resolveEnv = (config, parameter) => { + const configEnv = deepAccess(config, 'emoteev.env'); + + if (contains([PRODUCTION, STAGING, DEVELOPMENT], parameter)) return parameter; + else if (contains([PRODUCTION, STAGING, DEVELOPMENT], configEnv)) return configEnv; + else return DEFAULT_ENV; +}; + +/** + * Pure function + * @param {object} config pbjs config value + * @param {string} parameter Debug override from URL query param. + * @returns {boolean} + */ +export const resolveDebug = (config, parameter) => { + if (parameter && parameter.length && parameter.length > 0) return JSON.parse(parameter); + else if (config.debug) return config.debug; + else return false; +}; +/** + * EmoteevBidAdapter spec + * @access public + * @type {BidderSpec} + */ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], - - isBidRequestValid: (bid) => { - return !!( - bid && - bid.params && - bid.params.adSpaceId && - bid.bidder === BIDDER_CODE && - validateSizes(bid.mediaTypes.banner.sizes) - ); - }, - - buildRequests: (validBidRequests, bidderRequest) => { - const payload = Object.assign({}, - { - akPbjsVersion: AK_PBJS_VERSION, - bidRequests: validBidRequests.map(conformBidRequest), - currency: config.getConfig('currency'), - debug: emoteevDebug(utils.getParameterByName('emoteevDebug'), config.getConfig('emoteev.debug')), - language: navigator.language, - refererInfo: bidderRequest.refererInfo, - deviceInfo: getDeviceInfo(getDeviceDimensions(), getViewDimensions(), getDocumentDimensions(), isWebGLEnabled()), - userAgent: navigator.userAgent, - }, - emoteevOverrides(utils.getParameterByName('emoteevOverrides'), config.getConfig('emoteev.overrides'))); - - return { - method: 'POST', - url: endpointUrl(utils.getParameterByName('emoteevEnv'), config.getConfig('emoteev.env')), - data: JSON.stringify(payload), - }; - }, - - interpretResponse: (serverResponse) => serverResponse.body, - - getUserSyncs: (syncOptions, serverResponses) => { - const parameteremoteevEnv = utils.getParameterByName('emoteev.env'); - const configemoteevEnv = config.getConfig('emoteev.env'); - const syncs = []; - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: userSyncIframeUrl(parameteremoteevEnv, configemoteevEnv), - }); - } - if (syncOptions.pixelEnabled && serverResponses.length > 0) { - syncs.push({ - type: 'image', - url: userSyncImageUrl(parameteremoteevEnv, configemoteevEnv), - }); - } - return syncs; - }, + isBidRequestValid: isBidRequestValid, + buildRequests: (validBidRequests, bidderRequest) => + buildRequests( + resolveEnv(config.getConfig(), getParameterByName('emoteevEnv')), + resolveDebug(config.getConfig(), getParameterByName('debug')), + config.getConfig('currency'), + validBidRequests, + bidderRequest), + interpretResponse: interpretResponse, + onBidWon: (bidObject) => + triggerPixel(url.format(onBidWon( + resolveEnv(config.getConfig(), getParameterByName('emoteevEnv')), + getCookie('_pubcid'), + bidObject))), + onTimeout: (bidRequest) => + triggerPixel(url.format(onTimeout( + resolveEnv(config.getConfig(), getParameterByName('emoteevEnv')), + bidRequest))), + getUserSyncs: (syncOptions) => + getUserSyncs( + resolveEnv(config.getConfig(), getParameterByName('emoteevEnv')), + syncOptions), }; + registerBidder(spec); diff --git a/modules/emokteevBidAdapter.md b/modules/emoteevBidAdapter.md similarity index 100% rename from modules/emokteevBidAdapter.md rename to modules/emoteevBidAdapter.md diff --git a/test/spec/modules/emoteevBidAdapter_spec.js b/test/spec/modules/emoteevBidAdapter_spec.js index a5f5c439e6f..a5460ab939d 100644 --- a/test/spec/modules/emoteevBidAdapter_spec.js +++ b/test/spec/modules/emoteevBidAdapter_spec.js @@ -1,26 +1,49 @@ -import {expect} from 'chai'; import { - AK_PBJS_VERSION, - EMOTEEV_BASE_URL, - EMOTEEV_BASE_URL_STAGING, - emoteevDebug, - emoteevEnv, - emoteevOverrides, - akUrl, + assert, expect +} from 'chai'; +import { + ADAPTER_VERSION, + DOMAIN, + DOMAIN_DEVELOPMENT, + DOMAIN_STAGING, + domain, + BIDDER_PATH, + bidderUrl, + buildRequests, conformBidRequest, DEFAULT_ENV, - ENDPOINT_PATH, - endpointUrl, + DEVELOPMENT, + EVENTS_PATH, + eventsUrl, + getDeviceDimensions, + getDeviceInfo, + getDocumentDimensions, + getUserSyncs, + getViewDimensions, + interpretResponse, + isBidRequestValid, + isWebGLEnabled, + ON_ADAPTER_CALLED, + ON_BID_WON, + ON_BIDDER_TIMEOUT, + onBidWon, + onAdapterCalled, + onTimeout, PRODUCTION, + requestsPayload, + resolveDebug, + resolveEnv, spec, STAGING, - USER_SYNC_IFRAME_URL_PATH, - USER_SYNC_IMAGE_URL_PATH, + USER_SYNC_IFRAME_PATH, + USER_SYNC_IMAGE_PATH, userSyncIframeUrl, userSyncImageUrl, } from 'modules/emoteevBidAdapter'; -import {newBidder} from 'src/adapters/bidderFactory'; -import {config} from 'src/config'; +import * as url from '../../../src/url'; +import * as utils from '../../../src/utils'; +import * as pubCommonId from '../../../modules/pubCommonId'; +import {config} from '../../../src/config'; const cannedValidBidRequests = [{ adUnitCode: '/19968336/header-bid-tag-1', @@ -48,7 +71,11 @@ const cannedBidderRequest = { stack: ['http://localhost:9999/integrationExamples/gpt/hello_world_emoteev.html'] }, start: 1544200012839, - timeout: 3000 + timeout: 3000, + gdprConsent: { + gdprApplies: true, + consentString: 'my consentString' + } }; const serverResponse = { @@ -68,106 +95,11 @@ const serverResponse = }; describe('emoteevBidAdapter', 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('conformBidRequest', function () { - it('returns a bid-request', function () { - expect(conformBidRequest(cannedValidBidRequests[0])).to.deep.equal({ - params: cannedValidBidRequests[0].params, - crumbs: cannedValidBidRequests[0].crumbs, - sizes: cannedValidBidRequests[0].sizes, - bidId: cannedValidBidRequests[0].bidId, - bidderRequestId: cannedValidBidRequests[0].bidderRequestId, - }); - }) - }); - - describe('emoteevDebug', function () { - expect(emoteevDebug(null, null)).to.deep.equal(false) - }); - describe('emoteevDebug', function () { - expect(emoteevDebug(null, true)).to.deep.equal(true) - }); - describe('emoteevDebug', function () { - expect(emoteevDebug(JSON.stringify(true), null)).to.deep.equal(true) - }); - - describe('emoteevEnv', function () { - expect(emoteevEnv(null, null)).to.deep.equal(DEFAULT_ENV) - }); - describe('emoteevEnv', function () { - expect(emoteevEnv(null, STAGING)).to.deep.equal(STAGING) - }); - describe('emoteevEnv', function () { - expect(emoteevEnv(STAGING, null)).to.deep.equal(STAGING) - }); - - describe('emoteevOverrides', function () { - expect(emoteevOverrides(null, null)).to.deep.equal({}) - }); - describe('emoteevOverrides', function () { - expect(emoteevOverrides(JSON.stringify({a: 1}), null)).to.deep.equal({a: 1}) - }); - describe('emoteevOverrides', function () { - expect(emoteevOverrides('incorrect', null)).to.deep.equal({}) - }); // expect no exception - describe('emoteevOverrides', function () { - expect(emoteevOverrides(null, {a: 1})).to.deep.equal({a: 1}) - }); - - describe('akUrl', function () { - expect(akUrl(null)).to.deep.equal(EMOTEEV_BASE_URL) - }); - describe('akUrl', function () { - expect(akUrl('anything')).to.deep.equal(EMOTEEV_BASE_URL) - }); - describe('akUrl', function () { - expect(akUrl(STAGING)).to.deep.equal(EMOTEEV_BASE_URL_STAGING) - }); - describe('akUrl', function () { - expect(akUrl('production')).to.deep.equal(EMOTEEV_BASE_URL) - }); - - describe('endpointUrl', function () { - expect(endpointUrl(null, null)).to.deep.equal(EMOTEEV_BASE_URL.concat(ENDPOINT_PATH)) - }); - describe('endpointUrl', function () { - expect(endpointUrl(null, STAGING)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(ENDPOINT_PATH)) - }); - describe('endpointUrl', function () { - expect(endpointUrl(STAGING, null)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(ENDPOINT_PATH)) - }); - - describe('userSyncIframeUrl', function () { - expect(userSyncIframeUrl(null, null)).to.deep.equal(EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH)) - }); - describe('userSyncIframeUrl', function () { - expect(userSyncIframeUrl(null, STAGING)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(USER_SYNC_IFRAME_URL_PATH)) - }); - describe('userSyncIframeUrl', function () { - expect(userSyncIframeUrl(STAGING, null)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(USER_SYNC_IFRAME_URL_PATH)) - }); - - describe('userSyncImageUrl', function () { - expect(userSyncImageUrl(null, null)).to.deep.equal(EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH)) - }); - describe('userSyncImageUrl', function () { - expect(userSyncImageUrl(null, STAGING)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(USER_SYNC_IMAGE_URL_PATH)) - }); - describe('userSyncImageUrl', function () { - expect(userSyncImageUrl(STAGING, null)).to.deep.equal(EMOTEEV_BASE_URL_STAGING.concat(USER_SYNC_IMAGE_URL_PATH)) - }); - describe('isBidRequestValid', function () { - it('should return true when required params found', function () { + it('should return true when valid', function () { const validBid = { bidder: 'emoteev', + bidId: '23a45b4e3', params: { adSpaceId: 12345, }, @@ -177,11 +109,14 @@ describe('emoteevBidAdapter', function () { } }, }; - expect(spec.isBidRequestValid(validBid)).to.equal(true); + expect(isBidRequestValid(validBid)).to.equal(true); + + expect(spec.isBidRequestValid(validBid)).to.exist.and.to.be.a('boolean'); + expect(spec.isBidRequestValid({})).to.exist.and.to.be.a('boolean'); }); it('should return false when required params are invalid', function () { - expect(spec.isBidRequestValid({ + expect(isBidRequestValid({ bidder: '', // invalid bidder params: { adSpaceId: 12345, @@ -192,7 +127,7 @@ describe('emoteevBidAdapter', function () { } }, })).to.equal(false); - expect(spec.isBidRequestValid({ + expect(isBidRequestValid({ bidder: 'emoteev', params: { adSpaceId: '', // invalid adSpaceId @@ -203,7 +138,7 @@ describe('emoteevBidAdapter', function () { } }, })).to.equal(false); - expect(spec.isBidRequestValid({ + expect(isBidRequestValid({ bidder: 'emoteev', params: { adSpaceId: 12345, @@ -219,131 +154,602 @@ describe('emoteevBidAdapter', function () { describe('buildRequests', function () { const + env = DEFAULT_ENV, + debug = true, currency = 'EUR', - emoteevEnv = STAGING, - emoteevDebug = true, - emoteevOverrides = { - iAmOverride: 'iAmOverride' - }; - config.setConfig({ // asynchronous - currency, - emoteev: { - env: STAGING, - debug: emoteevDebug, - overrides: emoteevOverrides - } - }); + request = buildRequests(env, debug, currency, cannedValidBidRequests, cannedBidderRequest); - config.getConfig('emoteev', function () { - const request = spec.buildRequests(cannedValidBidRequests, cannedBidderRequest); - - it('creates a request object with correct method, url and data', function () { - expect(request).to.exist.and.have.all.keys( - 'method', - 'url', - 'data', - ); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(endpointUrl(emoteevEnv, emoteevEnv)); - - let requestData = JSON.parse(request.data); - expect(requestData).to.exist.and.have.all.keys( - 'akPbjsVersion', - 'bidRequests', - 'currency', - 'debug', - 'iAmOverride', - 'language', - 'refererInfo', - 'deviceInfo', - 'userAgent', - ); - - expect(requestData.bidRequests[0]).to.exist.and.have.all.keys( - 'params', - 'crumbs', - 'sizes', - 'bidId', - 'bidderRequestId', - ); - - expect(requestData.akPbjsVersion).to.deep.equal(AK_PBJS_VERSION); - expect(requestData.bidRequests[0].params).to.deep.equal(cannedValidBidRequests[0].params); - expect(requestData.bidRequests[0].crumbs).to.deep.equal(cannedValidBidRequests[0].crumbs); - expect(requestData.bidRequests[0].mediaTypes).to.deep.equal(cannedValidBidRequests[0].mediaTypes); - expect(requestData.bidRequests[0].bidId).to.deep.equal(cannedValidBidRequests[0].bidId); - expect(requestData.bidRequests[0].bidderRequestId).to.deep.equal(cannedValidBidRequests[0].bidderRequestId); - expect(requestData.currency).to.deep.equal(currency); - expect(requestData.debug).to.deep.equal(emoteevDebug); - expect(requestData.iAmOverride).to.deep.equal('iAmOverride'); - expect(requestData.language).to.deep.equal(navigator.language); - expect(requestData.deviceInfo).to.exist.and.have.all.keys( - 'browserWidth', - 'browserHeight', - 'deviceWidth', - 'deviceHeight', - 'documentWidth', - 'documentHeight', - 'webGL', - ); - expect(requestData.userAgent).to.deep.equal(navigator.userAgent); - }); - }); + expect(request).to.exist.and.have.all.keys( + 'method', + 'url', + 'data', + ); + + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(bidderUrl(env)); + + expect(spec.buildRequests(cannedValidBidRequests, cannedBidderRequest)).to.exist.and.to.be.an('object'); }); describe('interpretResponse', function () { it('bid objects from response', function () { - const bidResponses = spec.interpretResponse(serverResponse); - expect(bidResponses).to.be.an('array').that.is.not.empty; // yes, syntax is correct - expect(bidResponses[0]).to.have.all.keys( - 'requestId', - 'cpm', - 'width', - 'height', - 'ad', - 'ttl', - 'creativeId', - 'netRevenue', - 'currency', - ); - - expect(bidResponses[0].requestId).to.equal(cannedValidBidRequests[0].bidId); - expect(bidResponses[0].cpm).to.equal(serverResponse.body[0].cpm); - expect(bidResponses[0].width).to.equal(serverResponse.body[0].width); - expect(bidResponses[0].height).to.equal(serverResponse.body[0].height); - expect(bidResponses[0].ad).to.equal(serverResponse.body[0].ad); - expect(bidResponses[0].ttl).to.equal(serverResponse.body[0].ttl); - expect(bidResponses[0].creativeId).to.equal(serverResponse.body[0].creativeId); - expect(bidResponses[0].netRevenue).to.equal(serverResponse.body[0].netRevenue); - expect(bidResponses[0].currency).to.equal(serverResponse.body[0].currency); + const bidResponses = interpretResponse(serverResponse); + expect(bidResponses).to.be.an('array').that.is.not.empty; + expect(bidResponses[0]).to.have.property('requestId', cannedValidBidRequests[0].bidId); + expect(bidResponses[0]).to.have.property('cpm', serverResponse.body[0].cpm); + expect(bidResponses[0]).to.have.property('width', serverResponse.body[0].width); + expect(bidResponses[0]).to.have.property('height', serverResponse.body[0].height); + expect(bidResponses[0]).to.have.property('ad', serverResponse.body[0].ad); + expect(bidResponses[0]).to.have.property('ttl', serverResponse.body[0].ttl); + expect(bidResponses[0]).to.have.property('creativeId', serverResponse.body[0].creativeId); + expect(bidResponses[0]).to.have.property('netRevenue', serverResponse.body[0].netRevenue); + expect(bidResponses[0]).to.have.property('currency', serverResponse.body[0].currency); }); }); - describe('getUserSyncs', function () { - config.setConfig({emoteevEnv: PRODUCTION}); - expect(spec.getUserSyncs({ - iframeEnabled: true - }, [{}])).to.deep.equal([{ - type: 'iframe', - url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) - }]); + describe('onAdapterCalled', function () { + const + bidRequest = cannedValidBidRequests[0], + url = onAdapterCalled(DEFAULT_ENV, bidRequest); + + expect(url).to.have.property('protocol'); + expect(url).to.have.property('hostname'); + expect(url).to.have.property('pathname', EVENTS_PATH); + expect(url).to.have.nested.property('search.eventName', ON_ADAPTER_CALLED); + expect(url).to.have.nested.property('search.pubcId', bidRequest.crumbs.pubcid); + expect(url).to.have.nested.property('search.bidId', bidRequest.bidId); + expect(url).to.have.nested.property('search.adSpaceId', bidRequest.params.adSpaceId); + expect(url).to.have.nested.property('search.cache_buster'); + }); + + describe('onBidWon', function () { + const + pubcId = cannedValidBidRequests[0].crumbs.pubcid, + bidObject = serverResponse.body[0], + url = onBidWon(DEFAULT_ENV, pubcId, bidObject); + + expect(url).to.have.property('protocol'); + expect(url).to.have.property('hostname'); + expect(url).to.have.property('pathname', EVENTS_PATH); + expect(url).to.have.nested.property('search.eventName', ON_BID_WON); + expect(url).to.have.nested.property('search.pubcId', pubcId); + expect(url).to.have.nested.property('search.bidId', bidObject.requestId); + expect(url).to.have.nested.property('search.cache_buster'); + }); + + describe('onTimeout', function () { + const + data = { + ...cannedValidBidRequests[0], + timeout: 123, + }, + url = onTimeout(DEFAULT_ENV, data); - expect(spec.getUserSyncs({ - pixelEnabled: true - }, [{}])).to.deep.equal([{ + expect(url).to.have.property('protocol'); + expect(url).to.have.property('hostname'); + expect(url).to.have.property('pathname', EVENTS_PATH); + expect(url).to.have.nested.property('search.eventName', ON_BIDDER_TIMEOUT); + expect(url).to.have.nested.property('search.bidId', data.bidId); + expect(url).to.have.nested.property('search.pubcId', data.crumbs.pubcid); + expect(url).to.have.nested.property('search.adSpaceId', data.params.adSpaceId); + expect(url).to.have.nested.property('search.timeout', data.timeout); + expect(url).to.have.nested.property('search.cache_buster'); + }); + + describe('getUserSyncs', function () { + expect(getUserSyncs( + DEFAULT_ENV, + { + iframeEnabled: false, + pixelEnabled: false + })).to.deep.equal([]); + expect(getUserSyncs( + PRODUCTION, + { + iframeEnabled: false, + pixelEnabled: true + })).to.deep.equal([{ type: 'image', - url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) + url: userSyncImageUrl(PRODUCTION) }]); - - expect(spec.getUserSyncs({ - iframeEnabled: true, - pixelEnabled: true - }, [{}])).to.deep.equal([{ + expect(getUserSyncs( + STAGING, + { + iframeEnabled: true, + pixelEnabled: false + })).to.deep.equal([{ type: 'iframe', - url: EMOTEEV_BASE_URL.concat(USER_SYNC_IFRAME_URL_PATH) - }, { + url: userSyncIframeUrl(STAGING) + }]); + expect(getUserSyncs( + DEVELOPMENT, + { + iframeEnabled: true, + pixelEnabled: true + })).to.deep.equal([{ type: 'image', - url: EMOTEEV_BASE_URL.concat(USER_SYNC_IMAGE_URL_PATH) + url: userSyncImageUrl(DEVELOPMENT) + }, { + type: 'iframe', + url: userSyncIframeUrl(DEVELOPMENT) }]); }); + + describe('domain', function () { + expect(domain(null)).to.deep.equal(DOMAIN); + expect(domain('anything')).to.deep.equal(DOMAIN); + expect(domain(PRODUCTION)).to.deep.equal(DOMAIN); + expect(domain(STAGING)).to.deep.equal(DOMAIN_STAGING); + expect(domain(DEVELOPMENT)).to.deep.equal(DOMAIN_DEVELOPMENT); + }); + + describe('eventsUrl', function () { + expect(eventsUrl(null)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(DEFAULT_ENV), + pathname: EVENTS_PATH + })); + expect(eventsUrl('anything')).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(DEFAULT_ENV), + pathname: EVENTS_PATH + })); + expect(eventsUrl(PRODUCTION)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(PRODUCTION), + pathname: EVENTS_PATH + })); + expect(eventsUrl(STAGING)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(STAGING), + pathname: EVENTS_PATH + })); + expect(eventsUrl(DEVELOPMENT)).to.deep.equal(url.format({ + hostname: domain(DEVELOPMENT), + pathname: EVENTS_PATH + })); + }); + + describe('bidderUrl', function () { + expect(bidderUrl(null)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(DEFAULT_ENV), + pathname: BIDDER_PATH + })); + expect(bidderUrl('anything')).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(DEFAULT_ENV), + pathname: BIDDER_PATH + })); + expect(bidderUrl(PRODUCTION)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(PRODUCTION), + pathname: BIDDER_PATH + })); + expect(bidderUrl(STAGING)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(STAGING), + pathname: BIDDER_PATH + })); + expect(bidderUrl(DEVELOPMENT)).to.deep.equal(url.format({ + hostname: domain(DEVELOPMENT), + pathname: BIDDER_PATH + })); + }); + + describe('userSyncIframeUrl', function () { + expect(userSyncIframeUrl(null)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(DEFAULT_ENV), + pathname: USER_SYNC_IFRAME_PATH + })); + expect(userSyncIframeUrl('anything')).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(DEFAULT_ENV), + pathname: USER_SYNC_IFRAME_PATH + })); + expect(userSyncIframeUrl(PRODUCTION)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(PRODUCTION), + pathname: USER_SYNC_IFRAME_PATH + })); + expect(userSyncIframeUrl(STAGING)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(STAGING), + pathname: USER_SYNC_IFRAME_PATH + })); + expect(userSyncIframeUrl(DEVELOPMENT)).to.deep.equal(url.format({ + hostname: domain(DEVELOPMENT), + pathname: USER_SYNC_IFRAME_PATH + })); + }); + + describe('userSyncImageUrl', function () { + expect(userSyncImageUrl(null)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(DEFAULT_ENV), + pathname: USER_SYNC_IMAGE_PATH + })); + expect(userSyncImageUrl('anything')).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(DEFAULT_ENV), + pathname: USER_SYNC_IMAGE_PATH + })); + expect(userSyncImageUrl(PRODUCTION)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(PRODUCTION), + pathname: USER_SYNC_IMAGE_PATH + })); + expect(userSyncImageUrl(STAGING)).to.deep.equal(url.format({ + protocol: 'https', + hostname: domain(STAGING), + pathname: USER_SYNC_IMAGE_PATH + })); + expect(userSyncImageUrl(DEVELOPMENT)).to.deep.equal(url.format({ + hostname: domain(DEVELOPMENT), + pathname: USER_SYNC_IMAGE_PATH + })); + }); + + describe('conformBidRequest', function () { + expect(conformBidRequest(cannedValidBidRequests[0])).to.deep.equal({ + params: cannedValidBidRequests[0].params, + crumbs: cannedValidBidRequests[0].crumbs, + sizes: cannedValidBidRequests[0].sizes, + bidId: cannedValidBidRequests[0].bidId, + bidderRequestId: cannedValidBidRequests[0].bidderRequestId, + }); + }); + + describe('requestsPayload', function () { + const + currency = 'EUR', + debug = true; + + const payload = requestsPayload(debug, currency, cannedValidBidRequests, cannedBidderRequest); + + expect(payload).to.exist.and.have.all.keys( + 'akPbjsVersion', + 'bidRequests', + 'currency', + 'debug', + 'language', + 'refererInfo', + 'deviceInfo', + 'userAgent', + 'gdprApplies', + 'gdprConsent' + ); + + expect(payload.bidRequests[0]).to.exist.and.have.all.keys( + 'params', + 'crumbs', + 'sizes', + 'bidId', + 'bidderRequestId', + ); + + expect(payload.akPbjsVersion).to.deep.equal(ADAPTER_VERSION); + expect(payload.bidRequests[0].params).to.deep.equal(cannedValidBidRequests[0].params); + expect(payload.bidRequests[0].crumbs).to.deep.equal(cannedValidBidRequests[0].crumbs); + expect(payload.bidRequests[0].mediaTypes).to.deep.equal(cannedValidBidRequests[0].mediaTypes); + expect(payload.bidRequests[0].bidId).to.deep.equal(cannedValidBidRequests[0].bidId); + expect(payload.bidRequests[0].bidderRequestId).to.deep.equal(cannedValidBidRequests[0].bidderRequestId); + expect(payload.currency).to.deep.equal(currency); + expect(payload.debug).to.deep.equal(debug); + expect(payload.language).to.deep.equal(navigator.language); + expect(payload.deviceInfo).to.exist.and.have.all.keys( + 'browserWidth', + 'browserHeight', + 'deviceWidth', + 'deviceHeight', + 'documentWidth', + 'documentHeight', + 'webGL', + ); + expect(payload.userAgent).to.deep.equal(navigator.userAgent); + expect(payload.gdprApplies).to.deep.equal(cannedBidderRequest.gdprConsent.gdprApplies); + expect(payload.gdprConsent).to.deep.equal(cannedBidderRequest.gdprConsent.consentString); + }); + + describe('getViewDimensions', function () { + const window = { + innerWidth: 1024, + innerHeight: 768 + }; + const documentWithElement = { + documentElement: + { + clientWidth: 512, + clientHeight: 384 + } + }; + const documentWithBody = { + body: + { + clientWidth: 512, + clientHeight: 384 + } + }; + expect(getViewDimensions(window, documentWithElement)).to.deep.equal({ + width: 1024, + height: 768 + }); + expect(getViewDimensions(window, documentWithBody)).to.deep.equal({width: 1024, height: 768}); + expect(getViewDimensions(window, documentWithElement)).to.deep.equal({ + width: 1024, + height: 768 + }); + expect(getViewDimensions(window, documentWithBody)).to.deep.equal({width: 1024, height: 768}); + expect(getViewDimensions({}, documentWithElement)).to.deep.equal({width: 512, height: 384}); + expect(getViewDimensions({}, documentWithBody)).to.deep.equal({width: 512, height: 384}); + }); + + describe('getDeviceDimensions', function () { + const window = {screen: {width: 1024, height: 768}}; + expect(getDeviceDimensions(window)).to.deep.equal({width: 1024, height: 768}); + expect(getDeviceDimensions({})).to.deep.equal({width: '', height: ''}); + }); + + describe('getDocumentDimensions', function () { + expect(getDocumentDimensions({ + documentElement: { + clientWidth: 1, + clientHeight: 1, + offsetWidth: 0, + offsetHeight: 0, + scrollWidth: 0, + scrollHeight: 0, + }, + })).to.deep.equal({width: 1, height: 1}); + + expect(getDocumentDimensions({ + documentElement: { + clientWidth: 1, + clientHeight: 1, + offsetWidth: 0, + offsetHeight: 0, + scrollWidth: 0, + scrollHeight: 0, + }, + body: { + scrollHeight: 0, + offsetHeight: 0, + } + })).to.deep.equal({width: 1, height: 1}); + + expect(getDocumentDimensions({ + documentElement: { + clientWidth: 0, + clientHeight: 0, + offsetWidth: 1, + offsetHeight: 1, + scrollWidth: 0, + scrollHeight: 0, + }, + body: { + scrollHeight: 0, + offsetHeight: 0, + } + })).to.deep.equal({width: 1, height: 1}); + + expect(getDocumentDimensions({ + documentElement: { + clientWidth: 0, + clientHeight: 0, + offsetWidth: 0, + offsetHeight: 0, + scrollWidth: 1, + scrollHeight: 1, + }, + body: { + scrollHeight: 0, + offsetHeight: 0, + } + })).to.deep.equal({width: 1, height: 1}); + + expect(getDocumentDimensions({ + documentElement: { + clientWidth: undefined, + clientHeight: undefined, + offsetWidth: undefined, + offsetHeight: undefined, + scrollWidth: undefined, + scrollHeight: undefined, + }, + body: { + scrollHeight: undefined, + offsetHeight: undefined, + } + })).to.deep.equal({width: '', height: ''}); + }); + + // describe('isWebGLEnabled', function () { + // it('handles no webgl', function () { + // const + // document = new Document(), + // canvas = sinon.createStubInstance(HTMLCanvasElement); + // sinon.stub(document, 'createElement').withArgs('canvas').returns(canvas); + // canvas.getContext.withArgs('webgl').returns(undefined); + // canvas.getContext.withArgs('experimental-webgl').returns(undefined); + // expect(isWebGLEnabled(document)).to.equal(false); + // }); + // + // it('handles webgl exception', function () { + // const + // document = new Document(), + // canvas = sinon.createStubInstance(HTMLCanvasElement); + // sinon.stub(document, 'createElement').withArgs('canvas').returns(canvas); + // canvas.getContext.withArgs('webgl').throws(DOMException); + // expect(isWebGLEnabled(document)).to.equal(false); + // }); + // + // it('handles experimental webgl', function () { + // const + // document = new Document(), + // canvas = sinon.createStubInstance(HTMLCanvasElement); + // sinon.stub(document, 'createElement').withArgs('canvas').returns(canvas); + // canvas.getContext.withArgs('webgl').returns(undefined); + // canvas.getContext.withArgs('experimental-webgl').returns(true); + // expect(isWebGLEnabled(document)).to.equal(true); + // }); + // + // it('handles experimental webgl exception', function () { + // const + // document = new Document(), + // canvas = sinon.createStubInstance(HTMLCanvasElement); + // sinon.stub(document, 'createElement').withArgs('canvas').returns(canvas); + // canvas.getContext.withArgs('webgl').returns(undefined); + // canvas.getContext.withArgs('experimental-webgl').throws(DOMException); + // expect(isWebGLEnabled(document)).to.equal(false); + // }); + // + // it('handles webgl', function () { + // const + // document = new Document(), + // canvas = sinon.createStubInstance(HTMLCanvasElement); + // sinon.stub(document, 'createElement').withArgs('canvas').returns(canvas); + // canvas.getContext.withArgs('webgl').returns(true); + // expect(isWebGLEnabled(document)).to.equal(true); + // }); + // }); + + describe('getDeviceInfo', function () { + expect(getDeviceInfo( + {width: 1, height: 2}, + {width: 3, height: 4}, + {width: 5, height: 6}, + true + )).to.deep.equal({ + deviceWidth: 1, + deviceHeight: 2, + browserWidth: 3, + browserHeight: 4, + documentWidth: 5, + documentHeight: 6, + webGL: true + }); + }); + + describe('resolveEnv', function () { + it('defaults to production', function () { + expect(resolveEnv({}, null)).to.deep.equal(DEFAULT_ENV); + }); + expect(resolveEnv({}, PRODUCTION)).to.deep.equal(PRODUCTION); + expect(resolveEnv({}, STAGING)).to.deep.equal(STAGING); + expect(resolveEnv({}, DEVELOPMENT)).to.deep.equal(DEVELOPMENT); + expect(resolveEnv({emoteev: {env: PRODUCTION}}, null)).to.deep.equal(PRODUCTION); + expect(resolveEnv({emoteev: {env: STAGING}}, null)).to.deep.equal(STAGING); + expect(resolveEnv({emoteev: {env: DEVELOPMENT}}, null)).to.deep.equal(DEVELOPMENT); + it('prioritizes parameter over configuration', function () { + expect(resolveEnv({emoteev: {env: STAGING}}, DEVELOPMENT)).to.deep.equal(DEVELOPMENT); + }); + }); + + describe('resolveDebug', function () { + it('defaults to production', function () { + expect(resolveDebug({}, null)).to.deep.equal(false); + }); + expect(resolveDebug({}, 'false')).to.deep.equal(false); + expect(resolveDebug({}, 'true')).to.deep.equal(true); + expect(resolveDebug({debug: true}, null)).to.deep.equal(true); + it('prioritizes parameter over configuration', function () { + expect(resolveDebug({debug: true}, 'false')).to.deep.equal(false); + }); + }); + + describe('side effects', function () { + let triggerPixelSpy; + let getCookieSpy; + let getConfigSpy; + let getParameterByNameSpy; + beforeEach(function () { + triggerPixelSpy = sinon.spy(utils, 'triggerPixel'); + getCookieSpy = sinon.spy(pubCommonId, 'getCookie'); + getConfigSpy = sinon.spy(config, 'getConfig'); + getParameterByNameSpy = sinon.spy(utils, 'getParameterByName'); + }); + afterEach(function () { + triggerPixelSpy.restore(); + getCookieSpy.restore(); + getConfigSpy.restore(); + getParameterByNameSpy.restore(); + }); + + describe('isBidRequestValid', function () { + it('has intended side-effects', function () { + const validBidRequest = { + bidder: 'emoteev', + bidId: '23a45b4e3', + params: { + adSpaceId: 12345, + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + }; + spec.isBidRequestValid(validBidRequest); + sinon.assert.notCalled(utils.triggerPixel); + sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(config.getConfig); + sinon.assert.notCalled(utils.getParameterByName); + }); + it('has intended side-effects', function () { + const invalidBidRequest = {}; + spec.isBidRequestValid(invalidBidRequest); + sinon.assert.notCalled(utils.triggerPixel); + sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(config.getConfig); + sinon.assert.notCalled(utils.getParameterByName); + }); + }); + describe('buildRequests', function () { + it('has intended side-effects', function () { + spec.buildRequests(cannedValidBidRequests, cannedBidderRequest); + sinon.assert.notCalled(utils.triggerPixel); + sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.callCount(config.getConfig, 3); + sinon.assert.callCount(utils.getParameterByName, 2); + }); + }); + describe('interpretResponse', function () { + it('has intended side-effects', function () { + spec.interpretResponse(serverResponse); + sinon.assert.notCalled(utils.triggerPixel); + sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(config.getConfig); + sinon.assert.notCalled(utils.getParameterByName); + }); + }); + describe('onBidWon', function () { + it('has intended side-effects', function () { + const bidObject = serverResponse.body[0]; + spec.onBidWon(bidObject); + sinon.assert.calledOnce(utils.triggerPixel); + sinon.assert.calledOnce(pubCommonId.getCookie); + sinon.assert.calledOnce(config.getConfig); + sinon.assert.calledOnce(utils.getParameterByName); + }); + }); + describe('onTimeout', function () { + it('has intended side-effects', function () { + spec.onTimeout(cannedValidBidRequests[0]); + sinon.assert.calledOnce(utils.triggerPixel); + sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.calledOnce(config.getConfig); + sinon.assert.calledOnce(utils.getParameterByName); + }); + }); + describe('getUserSyncs', function () { + it('has intended side-effects', function () { + spec.getUserSyncs({}); + sinon.assert.notCalled(utils.triggerPixel); + sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.calledOnce(config.getConfig); + sinon.assert.calledOnce(utils.getParameterByName); + }); + }); + }); }); From c14f915e9529445effb1ba38cc7400c617e1872c Mon Sep 17 00:00:00 2001 From: Hendrik Iseke <39734979+hiseke@users.noreply.github.com> Date: Tue, 23 Apr 2019 20:56:00 +0200 Subject: [PATCH 1179/1594] fix handling of gdpr object (#3756) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons * add bidfloor parameter to params object * fix gdpr object handling --- modules/orbidderBidAdapter.js | 8 +-- test/spec/modules/orbidderBidAdapter_spec.js | 57 ++++++++++---------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index e316f3ef212..fc5eecbab08 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -42,11 +42,11 @@ export const spec = { } }; spec.bidParams[bidRequest.bidId] = bidRequest.params; - if (bidRequest && bidRequest.gdprConsent) { + if (bidderRequest && bidderRequest.gdprConsent) { ret.data.gdprConsent = { - consentString: bidRequest.gdprConsent.consentString, - consentRequired: (typeof bidRequest.gdprConsent.gdprApplies === 'boolean') - ? bidRequest.gdprConsent.gdprApplies + consentString: bidderRequest.gdprConsent.consentString, + consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') + ? bidderRequest.gdprConsent.gdprApplies : true }; } diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 0761ed8d31e..bc88090095b 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -20,14 +20,17 @@ describe('orbidderBidAdapter', () => { return JSON.parse(JSON.stringify(val)); }; - const buildRequest = function (buildRequest) { - return spec.buildRequests( - [buildRequest], - { - refererInfo: { - referer: 'http://localhost:9876/' - } - })[0]; + const buildRequest = (buildRequest, bidderRequest) => { + if (!Array.isArray(buildRequest)) { + buildRequest = [buildRequest]; + } + + return spec.buildRequests(buildRequest, { + ...bidderRequest || {}, + refererInfo: { + referer: 'http://localhost:9876/' + } + })[0]; }; describe('inherited functions', () => { @@ -101,30 +104,28 @@ describe('orbidderBidAdapter', () => { }); it('handles empty gdpr object', () => { - const bidRequest = deepClone(defaultBidRequest); - bidRequest.gdprConsent = {}; - - const request = buildRequest(bidRequest); + const request = buildRequest(defaultBidRequest, { + gdprConsent: {} + }); expect(request.data.gdprConsent.consentRequired).to.be.equal(true); }); it('handles non-existent gdpr object', () => { - const bidRequest = deepClone(defaultBidRequest); - bidRequest.gdprConsent = null; - - const request = buildRequest(bidRequest); + const request = buildRequest(defaultBidRequest, { + gdprConsent: null + }); expect(request.data.gdprConsent).to.be.undefined; }); it('handles properly filled gdpr object where gdpr applies', () => { const consentString = 'someWeirdString'; - const bidRequest = deepClone(defaultBidRequest); - bidRequest.gdprConsent = { - gdprApplies: true, - consentString: 'someWeirdString' - }; + const request = buildRequest(defaultBidRequest, { + gdprConsent: { + gdprApplies: true, + consentString: consentString + } + }); - const request = buildRequest(bidRequest); const gdprConsent = request.data.gdprConsent; expect(gdprConsent.consentRequired).to.be.equal(true); expect(gdprConsent.consentString).to.be.equal(consentString); @@ -132,13 +133,13 @@ describe('orbidderBidAdapter', () => { it('handles properly filled gdpr object where gdpr does not apply', () => { const consentString = 'someWeirdString'; - const bidRequest = deepClone(defaultBidRequest); - bidRequest.gdprConsent = { - gdprApplies: false, - consentString: 'someWeirdString' - }; + const request = buildRequest(defaultBidRequest, { + gdprConsent: { + gdprApplies: false, + consentString: consentString + } + }); - const request = buildRequest(bidRequest); const gdprConsent = request.data.gdprConsent; expect(gdprConsent.consentRequired).to.be.equal(false); expect(gdprConsent.consentString).to.be.equal(consentString); From b491a05ed49c9fa2c7febe161cc9d336223f16fe Mon Sep 17 00:00:00 2001 From: Vladislav Yatsun Date: Tue, 23 Apr 2019 22:58:45 +0400 Subject: [PATCH 1180/1594] Add NAF Digital Bidder Adapter (#3750) --- modules/nafdigitalBidAdapter.js | 246 +++++++++++++++ modules/nafdigitalBidAdapter.md | 38 +++ .../spec/modules/nafdigitalBidAdapter_spec.js | 283 ++++++++++++++++++ 3 files changed, 567 insertions(+) create mode 100644 modules/nafdigitalBidAdapter.js create mode 100644 modules/nafdigitalBidAdapter.md create mode 100644 test/spec/modules/nafdigitalBidAdapter_spec.js diff --git a/modules/nafdigitalBidAdapter.js b/modules/nafdigitalBidAdapter.js new file mode 100644 index 00000000000..7bbfd8b38dd --- /dev/null +++ b/modules/nafdigitalBidAdapter.js @@ -0,0 +1,246 @@ +import * as utils from '../src/utils'; +import * as url from '../src/url'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; +import { config } from '../src/config'; + +const BIDDER_CODE = 'nafdigital'; +const URL = 'https://nafdigitalbidder.com/hb'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + isBidRequestValid, + buildRequests, + interpretResponse, + getUserSyncs +}; + +function buildRequests(bidReqs, bidderRequest) { + try { + let referrer = ''; + if (bidderRequest && bidderRequest.refererInfo) { + referrer = bidderRequest.refererInfo.referer; + } + const nafdigitalImps = []; + const publisherId = utils.getBidIdParameter('publisherId', bidReqs[0].params); + utils._each(bidReqs, 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)); + const processedSizes = bid.sizes.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, utils.getWindowTop(), minSize) + : 'na'; + const viewabilityAmountRounded = isNaN(viewabilityAmount) ? viewabilityAmount : Math.round(viewabilityAmount); + + const imp = { + id: bid.bidId, + banner: { + format: processedSizes, + ext: { + viewability: viewabilityAmountRounded + } + }, + tagid: String(bid.adUnitCode) + }; + const bidFloor = utils.getBidIdParameter('bidFloor', bid.params); + if (bidFloor) { + imp.bidfloor = bidFloor; + } + nafdigitalImps.push(imp); + }); + const nafdigitalBidReq = { + id: utils.getUniqueIdentifierStr(), + imp: nafdigitalImps, + site: { + domain: url.parse(referrer).host, + page: referrer, + publisher: { + id: publisherId + } + }, + device: { + devicetype: _getDeviceType(), + w: screen.width, + h: screen.height + }, + tmax: config.getConfig('bidderTimeout') + }; + + return { + method: 'POST', + url: URL, + data: JSON.stringify(nafdigitalBidReq), + options: {contentType: 'text/plain', withCredentials: false} + }; + } catch (e) { + utils.logError(e, {bidReqs, bidderRequest}); + } +} + +function isBidRequestValid(bid) { + if (bid.bidder !== BIDDER_CODE || typeof bid.params === 'undefined') { + return false; + } + + if (typeof bid.params.publisherId === 'undefined') { + return false; + } + + return true; +} + +function interpretResponse(serverResponse) { + if (!serverResponse.body || typeof serverResponse.body != 'object') { + utils.logWarn('NAF digital server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); + return []; + } + const { body: {id, seatbid} } = serverResponse; + try { + const nafdigitalBidResponses = []; + if (id && + seatbid && + seatbid.length > 0 && + seatbid[0].bid && + seatbid[0].bid.length > 0) { + seatbid[0].bid.map(nafdigitalBid => { + nafdigitalBidResponses.push({ + requestId: nafdigitalBid.impid, + cpm: parseFloat(nafdigitalBid.price), + width: parseInt(nafdigitalBid.w), + height: parseInt(nafdigitalBid.h), + creativeId: nafdigitalBid.crid || nafdigitalBid.id, + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: _getAdMarkup(nafdigitalBid), + ttl: 60 + }); + }); + } + return nafdigitalBidResponses; + } catch (e) { + utils.logError(e, {id, seatbid}); + } +} + +// Don't do user sync for now +function getUserSyncs(syncOptions, responses, gdprConsent) { + return []; +} + +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 _getDeviceType() { + return _isMobile() ? 1 : _isConnectedTV() ? 3 : 2; +} + +function _getAdMarkup(bid) { + let adm = bid.adm; + if ('nurl' in bid) { + adm += utils.createTrackPixelHtml(bid.nurl); + } + return adm; +} + +function _isViewabilityMeasurable(element) { + return !_isIframe() && element !== null; +} + +function _getViewability(element, topWin, { w, h } = {}) { + return utils.getWindowTop().document.visibilityState === 'visible' + ? _getPercentInView(element, topWin, { w, h }) + : 0; +} + +function _isIframe() { + try { + return utils.getWindowSelf() !== utils.getWindowTop(); + } catch (e) { + return true; + } +} + +function _getMinSize(sizes) { + return sizes.reduce((min, size) => size.h * size.w < min.h * min.w ? size : min); +} + +function _getBoundingBox(element, { w, h } = {}) { + let { width, height, left, top, right, bottom } = element.getBoundingClientRect(); + + if ((width === 0 || height === 0) && w && h) { + width = w; + height = h; + right = left + w; + bottom = top + h; + } + + return { width, height, left, top, right, bottom }; +} + +function _getIntersectionOfRects(rects) { + const bbox = { + left: rects[0].left, + right: rects[0].right, + top: rects[0].top, + bottom: rects[0].bottom + }; + + for (let i = 1; i < rects.length; ++i) { + bbox.left = Math.max(bbox.left, rects[i].left); + bbox.right = Math.min(bbox.right, rects[i].right); + + if (bbox.left >= bbox.right) { + return null; + } + + bbox.top = Math.max(bbox.top, rects[i].top); + bbox.bottom = Math.min(bbox.bottom, rects[i].bottom); + + if (bbox.top >= bbox.bottom) { + return null; + } + } + + bbox.width = bbox.right - bbox.left; + bbox.height = bbox.bottom - bbox.top; + + return bbox; +} + +function _getPercentInView(element, topWin, { w, h } = {}) { + const elementBoundingBox = _getBoundingBox(element, { w, h }); + + // Obtain the intersection of the element and the viewport + const elementInViewBoundingBox = _getIntersectionOfRects([ { + left: 0, + top: 0, + right: topWin.innerWidth, + bottom: topWin.innerHeight + }, elementBoundingBox ]); + + let elementInViewArea, elementTotalArea; + + if (elementInViewBoundingBox !== null) { + // Some or all of the element is in view + elementInViewArea = elementInViewBoundingBox.width * elementInViewBoundingBox.height; + elementTotalArea = elementBoundingBox.width * elementBoundingBox.height; + + return ((elementInViewArea / elementTotalArea) * 100); + } + + // No overlap between element and the viewport; therefore, the element + // lies completely out of view + return 0; +} + +registerBidder(spec); diff --git a/modules/nafdigitalBidAdapter.md b/modules/nafdigitalBidAdapter.md new file mode 100644 index 00000000000..b17b1f13e1e --- /dev/null +++ b/modules/nafdigitalBidAdapter.md @@ -0,0 +1,38 @@ +# Overview + +``` +Module Name: NAF Digital Bid Adapter +Module Type: Bidder Adapter +Maintainer: vyatsun@gmail.com +``` + +# Description + +NAF Digital adapter integration to the Prebid library. + +# Test Parameters + +``` +var adUnits = [ + { + code: 'test-leaderboard', + sizes: [[728, 90]], + bids: [{ + bidder: 'nafdigital', + params: { + publisherId: 2141020, + bidFloor: 0.01 + } + }] + }, { + code: 'test-banner', + sizes: [[300, 250]], + bids: [{ + bidder: 'nafdigital', + params: { + publisherId: 2141020 + } + }] + } +] +``` diff --git a/test/spec/modules/nafdigitalBidAdapter_spec.js b/test/spec/modules/nafdigitalBidAdapter_spec.js new file mode 100644 index 00000000000..ca486c632c7 --- /dev/null +++ b/test/spec/modules/nafdigitalBidAdapter_spec.js @@ -0,0 +1,283 @@ +import { expect } from 'chai'; +import * as utils from 'src/utils'; +import { spec } from 'modules/nafdigitalBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const URL = 'https://nafdigitalbidder.com/hb'; + +describe('nafdigitalBidAdapter', function() { + const adapter = newBidder(spec); + let element, win; + let bidRequests; + let sandbox; + + beforeEach(function() { + element = { + x: 0, + y: 0, + + width: 0, + height: 0, + + getBoundingClientRect: () => { + return { + width: element.width, + height: element.height, + + left: element.x, + top: element.y, + right: element.x + element.width, + bottom: element.y + element.height + }; + } + }; + win = { + document: { + visibilityState: 'visible' + }, + + innerWidth: 800, + innerHeight: 600 + }; + bidRequests = [{ + 'bidder': 'nafdigital', + 'params': { + 'publisherId': 1234567 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '5fb26ac22bde4', + 'bidderRequestId': '4bf93aeb730cb9', + 'auctionId': 'ffe9a1f7-7b67-4bda-a8e0-9ee5dc9f442e' + }]; + + sandbox = sinon.sandbox.create(); + sandbox.stub(document, 'getElementById').withArgs('adunit-code').returns(element); + sandbox.stub(utils, 'getWindowTop').returns(win); + sandbox.stub(utils, 'getWindowSelf').returns(win); + }); + + afterEach(function() { + sandbox.restore(); + }); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'nafdigital', + 'params': { + 'publisherId': 1234567 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '5fb26ac22bde4', + 'bidderRequestId': '4bf93aeb730cb9', + 'auctionId': 'ffe9a1f7-7b67-4bda-a8e0-9ee5dc9f442e', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when tagid not passed correctly', function () { + bid.params.publisherId = undefined; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when require params are not passed', function () { + let bid = Object.assign({}, bid); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + it('sends bid request to our endpoint via POST', function () { + const request = spec.buildRequests(bidRequests); + expect(request.method).to.equal('POST'); + }); + + it('request url should match our endpoint url', function () { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(URL); + }); + + it('sets the proper banner object', function() { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + }); + + it('accepts a single array as a size', function() { + bidRequests[0].sizes = [300, 250]; + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]); + }); + + it('sends bidfloor param if present', function () { + bidRequests[0].params.bidFloor = 0.05; + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].bidfloor).to.equal(0.05); + }); + + it('sends tagid', function () { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].tagid).to.equal('adunit-code'); + }); + + it('sends publisher id', function () { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.site.publisher.id).to.equal(1234567); + }); + + context('when element is fully in view', function() { + it('returns 100', function() { + Object.assign(element, { width: 600, height: 400 }); + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.ext.viewability).to.equal(100); + }); + }); + + context('when element is out of view', function() { + it('returns 0', function() { + Object.assign(element, { x: -300, y: 0, width: 207, height: 320 }); + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.ext.viewability).to.equal(0); + }); + }); + + context('when element is partially in view', function() { + it('returns percentage', function() { + Object.assign(element, { width: 800, height: 800 }); + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.ext.viewability).to.equal(75); + }); + }); + + context('when width or height of the element is zero', function() { + it('try to use alternative values', function() { + Object.assign(element, { width: 0, height: 0 }); + bidRequests[0].sizes = [[800, 2400]]; + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.ext.viewability).to.equal(25); + }); + }); + + context('when nested iframes', function() { + it('returns \'na\'', function() { + Object.assign(element, { width: 600, height: 400 }); + + utils.getWindowTop.restore(); + utils.getWindowSelf.restore(); + sandbox.stub(utils, 'getWindowTop').returns(win); + sandbox.stub(utils, 'getWindowSelf').returns({}); + + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.ext.viewability).to.equal('na'); + }); + }); + + context('when tab is inactive', function() { + it('returns 0', function() { + Object.assign(element, { width: 600, height: 400 }); + + utils.getWindowTop.restore(); + win.document.visibilityState = 'hidden'; + sandbox.stub(utils, 'getWindowTop').returns(win); + + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.ext.viewability).to.equal(0); + }); + }); + }); + + describe('interpretResponse', function () { + let response; + beforeEach(function () { + response = { + body: { + 'id': '37386aade21a71', + 'seatbid': [{ + 'bid': [{ + 'id': '376874781', + 'impid': '283a9f4cd2415d', + 'price': 0.35743275, + 'nurl': '', + 'adm': '', + 'w': 300, + 'h': 250 + }] + }] + } + }; + }); + + it('should get the correct bid response', function () { + let expectedResponse = [{ + 'requestId': '283a9f4cd2415d', + 'cpm': 0.35743275, + 'width': 300, + 'height': 250, + 'creativeId': '376874781', + 'currency': 'USD', + 'netRevenue': true, + 'mediaType': 'banner', + 'ad': `
`, + 'ttl': 60 + }]; + + let result = spec.interpretResponse(response); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + it('crid should default to the bid id if not on the response', function () { + let expectedResponse = [{ + 'requestId': '283a9f4cd2415d', + 'cpm': 0.35743275, + 'width': 300, + 'height': 250, + 'creativeId': response.body.seatbid[0].bid[0].id, + 'currency': 'USD', + 'netRevenue': true, + 'mediaType': 'banner', + 'ad': `
`, + 'ttl': 60 + }]; + + let result = spec.interpretResponse(response); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + it('handles empty bid response', function () { + let response = { + body: '' + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs ', () => { + let syncOptions = {iframeEnabled: true, pixelEnabled: true}; + + it('should not return', () => { + let returnStatement = spec.getUserSyncs(syncOptions, []); + expect(returnStatement).to.be.empty; + }); + }); +}); From 49afe637a9a0a194955500252682481bd65f99fd Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 23 Apr 2019 15:04:47 -0400 Subject: [PATCH 1181/1594] Automated functional tests for longform testpages (#3659) * initial changes for longform e2e testing * added old safari browsers back, test spec file, and updated test pages * add retries settings to e2e tests, lower timeout thresholds * remove commented code * additional clean-up * update browser versions for more stable e2e tests * support host param in gulp command and other updates * refactor how host param was handled * add ie11 to browsers but remove it for e2e tests * update gulp task name to e2e-test * update e2e variable --- browsers.json | 40 +- gulpHelpers.js | 78 +- gulpfile.js | 77 +- .../basic_w_custom_adserver_translation.html | 132 ++ .../basic_w_requireExactDuration.html | 130 ++ .../basic_wo_brandCategoryExclusion.html | 130 ++ .../basic_wo_requireExactDuration.html | 131 ++ .../longform/custom_adserver_translation.json | 1180 +++++++++++++++++ .../longform/longformTestUtils.js | 66 + .../longform/longform_testpages_style.css | 34 + karma.conf.maker.js | 3 +- package.json | 8 +- test/helpers/testing-utils.js | 4 + test/spec/e2e/common/globals.js | 9 - test/spec/e2e/common/utils.js | 16 - test/spec/e2e/custom-assertions/first.js | 64 - test/spec/e2e/custom-reporter/junit.xml.ejs | 32 - .../e2e/custom-reporter/pbjs-html-reporter.js | 113 -- .../all_bidders_instant_load.html | 830 ------------ test/spec/e2e/gpt-examples/e2e_default.html | 117 -- test/spec/e2e/gpt-examples/gpt_default.html | 684 ---------- test/spec/e2e/gpt-examples/gpt_outstream.html | 250 ---- test/spec/e2e/gpt-examples/gpt_yieldbot.html | 241 ---- .../dom-group/allbidders_dom_spec.js | 125 -- test/spec/e2e/testcase1/dom-group/dom_spec.js | 51 - .../pbjsapi-group/adservertargeting_spec.js | 62 - .../pbjsapi-group/getbidresponses_spec.js | 34 - ...asic_w_custom_adserver_translation.spec.js | 68 + .../basic_w_requireExactDuration.spec.js | 68 + .../basic_wo_brandCategoryExclusion.spec.js | 63 + .../basic_wo_requireExactDuration.spec.js | 68 + wdio.conf.js | 55 + 32 files changed, 2197 insertions(+), 2766 deletions(-) create mode 100644 integrationExamples/longform/basic_w_custom_adserver_translation.html create mode 100644 integrationExamples/longform/basic_w_requireExactDuration.html create mode 100644 integrationExamples/longform/basic_wo_brandCategoryExclusion.html create mode 100644 integrationExamples/longform/basic_wo_requireExactDuration.html create mode 100644 integrationExamples/longform/custom_adserver_translation.json create mode 100644 integrationExamples/longform/longformTestUtils.js create mode 100644 integrationExamples/longform/longform_testpages_style.css create mode 100644 test/helpers/testing-utils.js delete mode 100644 test/spec/e2e/common/globals.js delete mode 100644 test/spec/e2e/common/utils.js delete mode 100644 test/spec/e2e/custom-assertions/first.js delete mode 100644 test/spec/e2e/custom-reporter/junit.xml.ejs delete mode 100644 test/spec/e2e/custom-reporter/pbjs-html-reporter.js delete mode 100644 test/spec/e2e/gpt-examples/all_bidders_instant_load.html delete mode 100644 test/spec/e2e/gpt-examples/e2e_default.html delete mode 100644 test/spec/e2e/gpt-examples/gpt_default.html delete mode 100644 test/spec/e2e/gpt-examples/gpt_outstream.html delete mode 100644 test/spec/e2e/gpt-examples/gpt_yieldbot.html delete mode 100644 test/spec/e2e/testcase1/dom-group/allbidders_dom_spec.js delete mode 100644 test/spec/e2e/testcase1/dom-group/dom_spec.js delete mode 100644 test/spec/e2e/testcase1/pbjsapi-group/adservertargeting_spec.js delete mode 100644 test/spec/e2e/testcase1/pbjsapi-group/getbidresponses_spec.js create mode 100644 test/spec/lfe2e/specs/basic_w_custom_adserver_translation.spec.js create mode 100644 test/spec/lfe2e/specs/basic_w_requireExactDuration.spec.js create mode 100644 test/spec/lfe2e/specs/basic_wo_brandCategoryExclusion.spec.js create mode 100644 test/spec/lfe2e/specs/basic_wo_requireExactDuration.spec.js create mode 100644 wdio.conf.js diff --git a/browsers.json b/browsers.json index 703bf44d41d..8604e44a7b8 100644 --- a/browsers.json +++ b/browsers.json @@ -1,9 +1,17 @@ { - "bs_ie_14_windows_10": { + "bs_edge_16_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "edge", - "browser_version": "14.0", + "browser_version": "16.0", + "device": null, + "os": "Windows" + }, + "bs_edge_17_windows_10": { + "base": "BrowserStack", + "os_version": "10", + "browser": "edge", + "browser_version": "17.0", "device": null, "os": "Windows" }, @@ -15,51 +23,51 @@ "device": null, "os": "Windows" }, - "bs_chrome_62_windows_10": { + "bs_chrome_72_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "62.0", + "browser_version": "72.0", "device": null, "os": "Windows" }, - "bs_chrome_61_windows_10": { + "bs_chrome_71_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "61.0", + "browser_version": "71.0", "device": null, "os": "Windows" }, - "bs_firefox_58_windows_10": { + "bs_firefox_65_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "firefox", - "browser_version": "58.0", + "browser_version": "65.0", "device": null, "os": "Windows" }, - "bs_firefox_57_windows_10": { + "bs_firefox_64_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "firefox", - "browser_version": "57.0", + "browser_version": "64.0", "device": null, "os": "Windows" }, - "bs_safari_9.1_mac_elcapitan": { + "bs_safari_11_mac_high_sierra": { "base": "BrowserStack", - "os_version": "El Capitan", + "os_version": "High Sierra", "browser": "safari", - "browser_version": "9.1", + "browser_version": "11.1", "device": null, "os": "OS X" }, - "bs_safari_8_mac_yosemite": { + "bs_safari_12_mac_mojave": { "base": "BrowserStack", - "os_version": "Yosemite", + "os_version": "Mojave", "browser": "safari", - "browser_version": "8.0", + "browser_version": "12.0", "device": null, "os": "OS X" } diff --git a/gulpHelpers.js b/gulpHelpers.js index 33169da3773..f20a2673ade 100644 --- a/gulpHelpers.js +++ b/gulpHelpers.js @@ -3,7 +3,6 @@ const fs = require('fs.extra'); const path = require('path'); const argv = require('yargs').argv; const MANIFEST = 'package.json'; -const exec = require('child_process').exec; const through = require('through2'); const _ = require('lodash'); const gutil = require('gulp-util'); @@ -13,7 +12,6 @@ const BUILD_PATH = './build/dist'; const DEV_PATH = './build/dev'; const ANALYTICS_PATH = '../analytics'; - // get only subdirectories that contain package.json with 'main' property function isModuleDirectory(filePath) { try { @@ -22,8 +20,7 @@ function isModuleDirectory(filePath) { const module = require(manifestPath); return module && module.main; } - } - catch (error) {} + } catch (error) {} } module.exports = { @@ -38,8 +35,8 @@ module.exports = { jsonifyHTML: function (str) { console.log(arguments); return str.replace(/\n/g, '') - .replace(/<\//g, '<\\/') - .replace(/\/>/g, '\\/>'); + .replace(/<\//g, '<\\/') + .replace(/\/>/g, '\\/>'); }, getArgModules() { var modules = (argv.modules || '').split(',').filter(module => !!module); @@ -52,7 +49,7 @@ module.exports = { fs.readFileSync(moduleFile, 'utf8') ); } - } catch(e) { + } catch (e) { throw new gutil.PluginError({ plugin: 'modules', message: 'failed reading: ' + argv.modules @@ -72,19 +69,19 @@ module.exports = { var moduleName = file.split(new RegExp('[.\\' + path.sep + ']'))[0]; var modulePath = path.join(absoluteModulePath, file); if (fs.lstatSync(modulePath).isDirectory()) { - modulePath = path.join(modulePath, "index.js") + modulePath = path.join(modulePath, 'index.js') } memo[modulePath] = moduleName; return memo; }, {}); - } catch(err) { + } catch (err) { internalModules = {}; } return Object.assign(externalModules.reduce((memo, module) => { try { var modulePath = require.resolve(module); memo[modulePath] = module; - } catch(err) { + } catch (err) { // do something } return memo; @@ -93,7 +90,7 @@ module.exports = { getBuiltModules: function(dev, externalModules) { var modules = this.getModuleNames(externalModules); - if(Array.isArray(externalModules)) { + if (Array.isArray(externalModules)) { modules = _.intersection(modules, externalModules); } return modules.map(name => path.join(__dirname, dev ? DEV_PATH : BUILD_PATH, name + '.js')); @@ -128,7 +125,7 @@ module.exports = { * Returns an array of source files for inclusion in build process */ getAnalyticsSources: function() { - if (!argv.analytics) {return [];} // empty arrays won't affect a standard build + if (!argv.analytics) { return []; } // empty arrays won't affect a standard build const directoryContents = fs.readdirSync(ANALYTICS_PATH); return directoryContents @@ -155,62 +152,5 @@ module.exports = { } return options; - }, - - createEnd2EndTestReport : function(targetDestinationDir) { - var browsers = require('./browsers.json'); - var env = []; - var input = 'bs'; - for(var key in browsers) { - if(key.substring(0, input.length) === input && browsers[key].browser !== 'iphone') { - env.push(key); - } - } - - //create new directory structure - fs.rmrfSync(targetDestinationDir); - env.forEach(item => { - fs.mkdirpSync(targetDestinationDir + '/' + item); - }); - - //move xml files to newly created directory - var walker = fs.walk('./build/coverage/e2e/reports'); - walker.on("file", function (root, stat, next) { - env.forEach(item => { - if(stat.name.search(item) !== -1) { - var src = root + '/' + stat.name; - var dest = targetDestinationDir + '/' + item + '/' + stat.name; - fs.copy(src, dest, {replace: true}, function(err) { - if(err) { - throw err; - } - }); - } - }); - next(); - }); - - //run junit-viewer to read xml and create html - env.forEach(item => { - //junit-viewer --results="./custom-reports/chrome51" --save="./chrome.html" - var cmd = 'junit-viewer --results="' + targetDestinationDir + '/' + item + '" --save="' + targetDestinationDir + '/' + item +'.html"'; - exec(cmd); - }); - - //create e2e-results.html - var html = 'End to End Testing Result
Note: Refresh in 2-3 seconds if it says "Cannot get ....."
'; - var li = ''; - var tabs = ''; - env.forEach(function(item,i) { - i++; - li = li + '
  • '+item+'
  • '; - tabs = tabs + '
    '; - }); - html = html + '
      ' + li + '
    ' + tabs; - html = html + '
    '; - - var filepath = targetDestinationDir + '/results.html'; - fs.openSync(filepath, 'w+'); - fs.writeFileSync(filepath, html); } }; diff --git a/gulpfile.js b/gulpfile.js index d3b29aa66a7..0170df80c62 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -26,6 +26,8 @@ var sourcemaps = require('gulp-sourcemaps'); var through = require('through2'); var fs = require('fs'); var jsEscape = require('gulp-js-escape'); +const path = require('path'); +const execa = require('execa'); var prebid = require('./package.json'); var dateString = 'Updated : ' + (new Date()).toISOString().substring(0, 10); @@ -51,22 +53,6 @@ function clean() { .pipe(gulpClean()); } -function e2etestReport() { - var reportPort = 9010; - var targetDestinationDir = './e2etest-report'; - helpers.createEnd2EndTestReport(targetDestinationDir); - connect.server({ - port: reportPort, - root: './', - livereload: true - }); - - setTimeout(function() { - opens('http://localhost:' + reportPort + '/' + targetDestinationDir.slice(2) + '/results.html'); - }, 5000); -}; -e2etestReport.displayName = 'e2etest-report'; - // Dependant task for building postbid. It escapes postbid-config file. function escapePostbidConfig() { gulp.src('./integrationExamples/postbid/oas/postbid-config.js') @@ -92,13 +78,14 @@ function lint(done) { // View the code coverage report in the browser. function viewCoverage(done) { var coveragePort = 1999; + var mylocalhost = (argv.host) ? argv.host : 'localhost'; connect.server({ port: coveragePort, root: 'build/coverage/karma_html', livereload: false }); - opens('http://localhost:' + coveragePort); + opens('http://' + mylocalhost + ':' + coveragePort); done(); }; @@ -244,6 +231,13 @@ function newKarmaCallback(done) { 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 = [ + wdioConf + ]; + return execa(wdioCmd, wdioOpts, { stdio: 'inherit' }); } else { var karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch, argv.file); @@ -268,35 +262,6 @@ function coveralls() { // 2nd arg is a dependency: 'test' must be finished .pipe(shell('cat build/coverage/lcov.info | node_modules/coveralls/bin/coveralls.js')); } -function e2eTest() { - var cmdQueue = []; - if (argv.browserstack) { - var browsers = require('./browsers.json'); - delete browsers['bs_ie_9_windows_7']; - - var cmdStr = ' --config nightwatch.conf.js'; - if (argv.group) { - cmdStr = cmdStr + ' --group ' + argv.group; - } - cmdStr = cmdStr + ' --reporter ./test/spec/e2e/custom-reporter/pbjs-html-reporter.js'; - - var startWith = 'bs'; - - Object.keys(browsers).filter(function(v) { - return v.substring(0, startWith.length) === startWith && browsers[v].browser !== 'iphone'; - }).map(function(v, i, arr) { - var newArr = (i % 2 === 0) ? arr.slice(i, i + 2) : null; - if (newArr) { - var cmd = 'nightwatch --env ' + newArr.join(',') + cmdStr; - cmdQueue.push(cmd); - } - }); - } - - return gulp.src('') - .pipe(shell(cmdQueue.join(';'))); -} - // This task creates postbid.js. Postbid setup is different from prebid.js // More info can be found here http://prebid.org/overview/what-is-post-bid.html @@ -308,6 +273,21 @@ function buildPostbid() { .pipe(gulp.dest('build/postbid/')); } +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') + }); + } + process.env.TEST_SERVER_HOST = argv.host; + if (argv.https) { + process.env.TEST_SERVER_PROTOCOL = argv.https; + } + argv.e2e = true; + done(); +} + // support tasks gulp.task(lint); gulp.task(watch); @@ -333,12 +313,9 @@ gulp.task('build-postbid', gulp.series(escapePostbidConfig, buildPostbid)); gulp.task('serve', gulp.series(clean, lint, gulp.parallel('build-bundle-dev', watch, test))); gulp.task('default', gulp.series(clean, makeWebpackPkg)); -gulp.task(e2etestReport); -gulp.task('e2etest', gulp.series(clean, gulp.parallel(makeDevpackPkg, makeWebpackPkg), e2eTest)); - +gulp.task('e2e-test', gulp.series(clean, setupE2e, gulp.parallel('build-bundle-dev', watch), test)) // other tasks gulp.task(bundleToStdout); gulp.task('bundle', gulpBundle.bind(null, false)); // used for just concatenating pre-built files with no build step -gulp.task('serve-nw', gulp.parallel(lint, watch, 'e2etest')); module.exports = nodeBundle; diff --git a/integrationExamples/longform/basic_w_custom_adserver_translation.html b/integrationExamples/longform/basic_w_custom_adserver_translation.html new file mode 100644 index 00000000000..995ea822da4 --- /dev/null +++ b/integrationExamples/longform/basic_w_custom_adserver_translation.html @@ -0,0 +1,132 @@ + + + + + Prebid Freewheel Integration Demo + + + + + + + + + + + + + + + + + + +

    Prebid Freewheel Integration Demo

    +

    custom adserver translation file

    +
    +
    + +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/integrationExamples/longform/basic_w_requireExactDuration.html b/integrationExamples/longform/basic_w_requireExactDuration.html new file mode 100644 index 00000000000..016b51d09c4 --- /dev/null +++ b/integrationExamples/longform/basic_w_requireExactDuration.html @@ -0,0 +1,130 @@ + + + + + Prebid Freewheel Integration Demo + + + + + + + + + + + + + + + + + + +

    Prebid Freewheel Test Page

    +

    requireExactDuration = true

    +
    +
    + +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/integrationExamples/longform/basic_wo_brandCategoryExclusion.html b/integrationExamples/longform/basic_wo_brandCategoryExclusion.html new file mode 100644 index 00000000000..c8af5801406 --- /dev/null +++ b/integrationExamples/longform/basic_wo_brandCategoryExclusion.html @@ -0,0 +1,130 @@ + + + + + Prebid Freewheel Integration Demo + + + + + + + + + + + + + + + + + + +

    Prebid Freewheel Test Page

    +

    brandCategoryExclusion = false

    +
    +
    + +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/integrationExamples/longform/basic_wo_requireExactDuration.html b/integrationExamples/longform/basic_wo_requireExactDuration.html new file mode 100644 index 00000000000..215138479cc --- /dev/null +++ b/integrationExamples/longform/basic_wo_requireExactDuration.html @@ -0,0 +1,131 @@ + + + + + Prebid Freewheel Integration Demo + + + + + + + + + + + + + + + + + + +

    Prebid Freewheel Test Page

    +

    requireExactDuration = false

    +
    +
    + +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/integrationExamples/longform/custom_adserver_translation.json b/integrationExamples/longform/custom_adserver_translation.json new file mode 100644 index 00000000000..377fe9cdeda --- /dev/null +++ b/integrationExamples/longform/custom_adserver_translation.json @@ -0,0 +1,1180 @@ +{ + "mapping":{ + "IAB1-1":{ + "id":404, + "name":"Publishing" + }, + "IAB1-2":{ + "id":392, + "name":"Entertainment" + }, + "IAB1-5":{ + "id":419, + "name":"Filmed Entertainment" + }, + "IAB1-6":{ + "id":392, + "name":"Entertainment" + }, + "IAB1-7":{ + "id":392, + "name":"Entertainment" + }, + "IAB2-1":{ + "id":399, + "name":"Automotive" + }, + "IAB2-2":{ + "id":399, + "name":"Automotive" + }, + "IAB2-3":{ + "id":399, + "name":"Automotive" + }, + "IAB2-4":{ + "id":399, + "name":"Automotive" + }, + "IAB2-5":{ + "id":399, + "name":"Automotive" + }, + "IAB2-6":{ + "id":399, + "name":"Automotive" + }, + "IAB2-7":{ + "id":399, + "name":"Automotive" + }, + "IAB2-8":{ + "id":399, + "name":"Automotive" + }, + "IAB2-9":{ + "id":399, + "name":"Automotive" + }, + "IAB2-10":{ + "id":399, + "name":"Automotive" + }, + "IAB2-11":{ + "id":399, + "name":"Automotive" + }, + "IAB2-12":{ + "id":399, + "name":"Automotive" + }, + "IAB2-13":{ + "id":399, + "name":"Automotive" + }, + "IAB2-14":{ + "id":399, + "name":"Automotive" + }, + "IAB2-15":{ + "id":399, + "name":"Automotive" + }, + "IAB2-16":{ + "id":399, + "name":"Automotive" + }, + "IAB2-17":{ + "id":399, + "name":"Automotive" + }, + "IAB2-18":{ + "id":399, + "name":"Automotive" + }, + "IAB2-19":{ + "id":399, + "name":"Automotive" + }, + "IAB2-20":{ + "id":399, + "name":"Automotive" + }, + "IAB2-21":{ + "id":399, + "name":"Automotive" + }, + "IAB2-22":{ + "id":399, + "name":"Automotive" + }, + "IAB2-23":{ + "id":399, + "name":"Automotive" + }, + "IAB3-1":{ + "id":393, + "name":"Business Services" + }, + "IAB3-2":{ + "id":393, + "name":"Business Services" + }, + "IAB3-3":{ + "id":393, + "name":"Business Services" + }, + "IAB3-4":{ + "id":409, + "name":"Computing Product" + }, + "IAB3-5":{ + "id":393, + "name":"Business Services" + }, + "IAB3-6":{ + "id":393, + "name":"Business Services" + }, + "IAB3-7":{ + "id":398, + "name":"Government/Municipal" + }, + "IAB3-8":{ + "id":393, + "name":"Business Services" + }, + "IAB3-9":{ + "id":393, + "name":"Business Services" + }, + "IAB3-10":{ + "id":393, + "name":"Business Services" + }, + "IAB3-11":{ + "id":393, + "name":"Business Services" + }, + "IAB3-12":{ + "id":393, + "name":"Business Services" + }, + "IAB4-1":{ + "id":393, + "name":"Business Services" + }, + "IAB4-2":{ + "id":405, + "name":"Educational Services" + }, + "IAB4-3":{ + "id":405, + "name":"Educational Services" + }, + "IAB4-4":{ + "id":393, + "name":"Business Services" + }, + "IAB4-5":{ + "id":393, + "name":"Business Services" + }, + "IAB4-6":{ + "id":393, + "name":"Business Services" + }, + "IAB4-7":{ + "id":406, + "name":"Health Care Services" + }, + "IAB4-8":{ + "id":405, + "name":"Educational Services" + }, + "IAB4-9":{ + "id":417, + "name":"Telecommunications" + }, + "IAB4-10":{ + "id":429, + "name":"Military" + }, + "IAB4-11":{ + "id":393, + "name":"Business Services" + }, + "IAB5-1":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-2":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-3":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-4":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-5":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-6":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-7":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-8":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-9":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-10":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-11":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-12":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-13":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-14":{ + "id":405, + "name":"Educational Services" + }, + "IAB5-15":{ + "id":405, + "name":"Educational Services" + }, + "IAB7-1":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-2":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-3":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-4":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-5":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-6":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-7":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-8":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-9":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-10":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-11":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-12":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-13":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-14":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-15":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-16":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-17":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-18":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-19":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-20":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-21":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-22":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-23":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-24":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-25":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-26":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-27":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-28":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-29":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-30":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-31":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-32":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-33":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-34":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-35":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-36":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-37":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-38":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-39":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-40":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-41":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-42":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-43":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-44":{ + "id":406, + "name":"Health Care Services" + }, + "IAB7-45":{ + "id":406, + "name":"Health Care Services" + }, + "IAB8-1":{ + "id":394, + "name":"Food" + }, + "IAB8-2":{ + "id":394, + "name":"Food" + }, + "IAB8-3":{ + "id":394, + "name":"Food" + }, + "IAB8-4":{ + "id":394, + "name":"Food" + }, + "IAB8-5":{ + "id":400, + "name":"Beer/Wine/Liquor" + }, + "IAB8-6":{ + "id":401, + "name":"Beverages" + }, + "IAB8-7":{ + "id":394, + "name":"Food" + }, + "IAB8-8":{ + "id":394, + "name":"Food" + }, + "IAB8-9":{ + "id":407, + "name":"Restaurant/Fast Food" + }, + "IAB8-10":{ + "id":394, + "name":"Food" + }, + "IAB8-11":{ + "id":394, + "name":"Food" + }, + "IAB8-12":{ + "id":394, + "name":"Food" + }, + "IAB8-13":{ + "id":394, + "name":"Food" + }, + "IAB8-14":{ + "id":394, + "name":"Food" + }, + "IAB8-15":{ + "id":394, + "name":"Food" + }, + "IAB8-16":{ + "id":394, + "name":"Food" + }, + "IAB8-17":{ + "id":394, + "name":"Food" + }, + "IAB8-18":{ + "id":400, + "name":"Beer/Wine/Liquor" + }, + "IAB9-1":{ + "id":392, + "name":"Entertainment" + }, + "IAB9-3":{ + "id":418, + "name":"Jewelry" + }, + "IAB9-5":{ + "id":413, + "name":"Gaming" + }, + "IAB9-6":{ + "id":412, + "name":"Household Products" + }, + "IAB9-9":{ + "id":426, + "name":"Tobacco" + }, + "IAB9-11":{ + "id":404, + "name":"Publishing" + }, + "IAB9-15":{ + "id":404, + "name":"Publishing" + }, + "IAB9-16":{ + "id":392, + "name":"Entertainment" + }, + "IAB9-18":{ + "id":393, + "name":"Business Services" + }, + "IAB9-19":{ + "id":418, + "name":"Jewelry" + }, + "IAB9-23":{ + "id":424, + "name":"Photographic Equipment" + }, + "IAB9-24":{ + "id":392, + "name":"Entertainment" + }, + "IAB9-25":{ + "id":392, + "name":"Entertainment" + }, + "IAB9-30":{ + "id":392, + "name":"Entertainment" + }, + "IAB10-1":{ + "id":415, + "name":"Appliances" + }, + "IAB10-5":{ + "id":434, + "name":"Home Furnishings" + }, + "IAB10-6":{ + "id":434, + "name":"Home Furnishings" + }, + "IAB10-7":{ + "id":434, + "name":"Home Furnishings" + }, + "IAB10-8":{ + "id":393, + "name":"Business Services" + }, + "IAB10-9":{ + "id":434, + "name":"Home Furnishings" + }, + "IAB11-1":{ + "id":398, + "name":"Government/Municipal" + }, + "IAB11-2":{ + "id":398, + "name":"Government/Municipal" + }, + "IAB11-3":{ + "id":398, + "name":"Government/Municipal" + }, + "IAB11-4":{ + "id":398, + "name":"Government/Municipal" + }, + "IAB11-5":{ + "id":398, + "name":"Government/Municipal" + }, + "IAB12-1":{ + "id":438, + "name":"News" + }, + "IAB12-2":{ + "id":438, + "name":"News" + }, + "IAB12-3":{ + "id":438, + "name":"News" + }, + "IAB13-1":{ + "id":393, + "name":"Business Services" + }, + "IAB13-2":{ + "id":393, + "name":"Business Services" + }, + "IAB13-3":{ + "id":438, + "name":"News" + }, + "IAB13-4":{ + "id":391, + "name":"Financial Services" + }, + "IAB13-5":{ + "id":393, + "name":"Business Services" + }, + "IAB13-6":{ + "id":436, + "name":"Insurance" + }, + "IAB13-7":{ + "id":393, + "name":"Business Services" + }, + "IAB13-8":{ + "id":393, + "name":"Business Services" + }, + "IAB13-9":{ + "id":393, + "name":"Business Services" + }, + "IAB13-10":{ + "id":393, + "name":"Business Services" + }, + "IAB13-11":{ + "id":393, + "name":"Business Services" + }, + "IAB13-12":{ + "id":393, + "name":"Business Services" + }, + "IAB16-1":{ + "id":423, + "name":"Pet Food/Supplies" + }, + "IAB16-2":{ + "id":423, + "name":"Pet Food/Supplies" + }, + "IAB16-3":{ + "id":423, + "name":"Pet Food/Supplies" + }, + "IAB16-4":{ + "id":423, + "name":"Pet Food/Supplies" + }, + "IAB16-5":{ + "id":423, + "name":"Pet Food/Supplies" + }, + "IAB16-6":{ + "id":423, + "name":"Pet Food/Supplies" + }, + "IAB16-7":{ + "id":423, + "name":"Pet Food/Supplies" + }, + "IAB17-1":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-2":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-3":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-4":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-5":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-6":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-7":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-8":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-9":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-10":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-11":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-12":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-13":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-14":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-15":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-16":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-17":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-18":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-19":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-20":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-21":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-22":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-23":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-24":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-25":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-26":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-27":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-28":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-29":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-30":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-31":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-32":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-33":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-34":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-35":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-36":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-37":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-38":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-39":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-40":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-41":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-42":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-43":{ + "id":425, + "name":"Professional Sports" + }, + "IAB17-44":{ + "id":425, + "name":"Professional Sports" + }, + "IAB18-1":{ + "id":411, + "name":"Cosmetics/Toiletries" + }, + "IAB18-2":{ + "id":397, + "name":"Apparel" + }, + "IAB18-3":{ + "id":397, + "name":"Apparel" + }, + "IAB18-4":{ + "id":418, + "name":"Jewelry" + }, + "IAB18-5":{ + "id":397, + "name":"Apparel" + }, + "IAB18-6":{ + "id":397, + "name":"Apparel" + }, + "IAB19-2":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-3":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-4":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-5":{ + "id":424, + "name":"Photographic Equipment" + }, + "IAB19-6":{ + "id":417, + "name":"Telecommunications" + }, + "IAB19-7":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-8":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-9":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-10":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-11":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-12":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-13":{ + "id":404, + "name":"Publishing" + }, + "IAB19-14":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-15":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-16":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-17":{ + "id":419, + "name":"Filmed Entertainment" + }, + "IAB19-18":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-19":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-20":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-21":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-22":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-23":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-24":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-25":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-26":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-27":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-28":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-29":{ + "id":392, + "name":"Entertainment" + }, + "IAB19-30":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-31":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-32":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-33":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-34":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-35":{ + "id":409, + "name":"Computing Product" + }, + "IAB19-36":{ + "id":409, + "name":"Computing Product" + }, + "IAB20-1":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-2":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-3":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-4":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-5":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-6":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-7":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-8":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-9":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-10":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-11":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-12":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-13":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-14":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-15":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-16":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-17":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-18":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-19":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-20":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-21":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-22":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-23":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-24":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-25":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-26":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB20-27":{ + "id":395, + "name":"Travel/Hotels/Airlines" + }, + "IAB21-1":{ + "id":416, + "name":"Real Estate" + }, + "IAB21-2":{ + "id":416, + "name":"Real Estate" + }, + "IAB21-3":{ + "id":416, + "name":"Real Estate" + }, + "IAB22-1":{ + "id":403, + "name":"Retail Stores/Chains" + }, + "IAB22-2":{ + "id":403, + "name":"Retail Stores/Chains" + }, + "IAB22-3":{ + "id":403, + "name":"Retail Stores/Chains" + } + } +} \ No newline at end of file diff --git a/integrationExamples/longform/longformTestUtils.js b/integrationExamples/longform/longformTestUtils.js new file mode 100644 index 00000000000..096be91bb77 --- /dev/null +++ b/integrationExamples/longform/longformTestUtils.js @@ -0,0 +1,66 @@ +var prebidTestUtils = prebidTestUtils || {}; + +function getIndustry(id) { + var mapping = window.localStorage.getItem('iabToFwMappingkey'); + if (mapping) { + try { + mapping = JSON.parse(mapping); + } catch (error) { + // + } + var industry; + mapping = mapping['mapping']; + for (var v in mapping) { + if (mapping[v]['id'] == id) { + industry = mapping[v]['name']; + break; + } + } + return industry; + } +} + +prebidTestUtils.loadKv = function (targetingArr) { + var div = document.getElementById('collapseThree').children[0]; + var html = ''; + Object.keys(targetingArr).forEach(function(adUnitCode) { + targetingArr[adUnitCode].forEach(function (targeting) { + Object.keys(targeting).forEach(function (key) { + html += '' + }); + }); + }); + html += '
    ' + key + '' + targeting[key] + '
    '; + div.innerHTML = html; +} + +prebidTestUtils.loadBids = function (targetingArr, brandCatExclusion) { + var div = document.getElementById('collapseTwo').children[0]; + var html = ''; + var index = 1; + Object.keys(targetingArr).forEach(function(adUnitCode) { + targetingArr[adUnitCode].forEach(function (targeting) { + Object.keys(targeting).forEach(function (key) { + if (key !== 'hb_cache_id') { + var result = targeting[key].split('_'); + html += ''; + html += ''; + html += ''; + if (brandCatExclusion) { + html += ''; + html += ''; + } else { + html += ''; + html += ''; + } + html += ''; + html += ''; + html += ''; + index++; + } + }); + }); + }); + html += '
    #CPMIndustryDurationStatusComm Break #
    ' + index + '' + result[0] + '' + getIndustry(result[1]) + '' + result[2] + '' + result[1] + '
    '; + div.innerHTML = html; +} diff --git a/integrationExamples/longform/longform_testpages_style.css b/integrationExamples/longform/longform_testpages_style.css new file mode 100644 index 00000000000..fe8105edcfa --- /dev/null +++ b/integrationExamples/longform/longform_testpages_style.css @@ -0,0 +1,34 @@ +#videoPlayer { + height: 480px; + width: 100%; + background-color: #000; +} + +.outer { + position: relative; +} + +#skip { + position: absolute; + right: 20px; + bottom: 20px; + display: none; + color: white; + background-color: black; + border: 1px solid gray; +} + +#adCount { + color: white; + position: absolute; + left: 20px; + bottom: 20px; + display: none; +} + +#showad { + color: white; + position: absolute; + left: 20px; + top: 20px; +} \ No newline at end of file diff --git a/karma.conf.maker.js b/karma.conf.maker.js index 649a13a16fc..9aa416375b5 100644 --- a/karma.conf.maker.js +++ b/karma.conf.maker.js @@ -85,7 +85,8 @@ function setBrowsers(karmaConf, browserstack) { if (browserstack) { karmaConf.browserStack = { username: process.env.BROWSERSTACK_USERNAME, - accessKey: process.env.BROWSERSTACK_ACCESS_KEY + accessKey: process.env.BROWSERSTACK_ACCESS_KEY, + build: 'Prebidjs Unit Tests ' + new Date().toLocaleString() } if (process.env.TRAVIS) { karmaConf.browserStack.startTunnel = false; diff --git a/package.json b/package.json index c3b4e5cd042..1e1c130b6fe 100755 --- a/package.json +++ b/package.json @@ -31,13 +31,13 @@ "chai": "^4.2.0", "coveralls": "^3.0.2", "documentation": "^5.2.2", - "ejs": "^2.5.1", "es5-shim": "^4.5.2", "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.2.0", "eslint-plugin-node": "^5.1.0", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", + "execa": "^1.0.0", "faker": "^3.1.0", "fs.extra": "^1.3.2", "gulp": "^4.0.0", @@ -78,12 +78,16 @@ "karma-webpack": "^3.0.5", "lodash": "^4.17.4", "mocha": "^5.0.0", - "nightwatch": "^1.0.6", "opn": "^5.4.0", "querystringify": "0.0.3", "sinon": "^4.1.3", "through2": "^2.0.3", "url-parse": "^1.0.5", + "wdio-browserstack-service": "^0.1.17", + "wdio-concise-reporter": "^0.1.2", + "wdio-mocha-framework": "^0.6.3", + "wdio-spec-reporter": "^0.1.5", + "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-stream": "^3.2.0", "yargs": "^1.3.1" diff --git a/test/helpers/testing-utils.js b/test/helpers/testing-utils.js new file mode 100644 index 00000000000..21d5992873e --- /dev/null +++ b/test/helpers/testing-utils.js @@ -0,0 +1,4 @@ +module.exports = { + host: (process.env.TEST_SERVER_HOST) ? process.env.TEST_SERVER_HOST : 'localhost', + protocol: (process.env.TEST_SERVER_PROTOCOL) ? 'https' : 'http' +} diff --git a/test/spec/e2e/common/globals.js b/test/spec/e2e/common/globals.js deleted file mode 100644 index 3e781d5fa21..00000000000 --- a/test/spec/e2e/common/globals.js +++ /dev/null @@ -1,9 +0,0 @@ -var HtmlReporter = require('nightwatch-html-reporter'); -var reporter = new HtmlReporter({ - openBrowser: true, - reportsDirectory: __dirname + '/reports', - themeName: 'cover', -}); -module.exports = { - reporter: reporter.fn -}; diff --git a/test/spec/e2e/common/utils.js b/test/spec/e2e/common/utils.js deleted file mode 100644 index 2c9fee68eda..00000000000 --- a/test/spec/e2e/common/utils.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - findIframeInDiv: function(divid) { - var div = document.getElementById(divid); - var iframes = div.getElementsByTagName('iframe'); - console.log(iframes.length); - try { - if (iframes.length === 1 && iframes[0].contentWindow.document.body.innerHTML === '') { - return false; - } else { - return true; - } - } catch (e) { - return true; - } - } -}; diff --git a/test/spec/e2e/custom-assertions/first.js b/test/spec/e2e/custom-assertions/first.js deleted file mode 100644 index e393e8c15a0..00000000000 --- a/test/spec/e2e/custom-assertions/first.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Checks if the given attribute of an element has the expected value. - * - * ``` - * this.demoTest = function (client) { - * browser.assert.attributeEquals('body', 'data-attr', 'some value'); - * }; - * ``` - * - * @method attributeEquals - * @param {string} selector The selector (CSS / Xpath) used to locate the element. - * @param {string} attribute The attribute name - * @param {string} expected The expected value of the attribute to check. - * @param {string} [message] Optional log message to display in the output. If missing, one is displayed by default. - * @api assertions - */ - -var util = require('util'); -exports.assertion = function(expected, msg) { - var DEFAULT_MSG = 'Testing if attribute %s of <%s> equals "%s".'; - - this.message = msg; - - this.expected = function() { - return expected; - }; - - this.pass = function(value) { - return value === expected; - }; - - this.failure = function(result) { - var failed = false; - return failed; - }; - - this.value = function(result) { - console.log('**********'); - console.log(result); - return result.value; - }; - - this.command = function(callback) { - var _this = this; - var execcallback = function(result) { - // console.log(_this); - console.log('**********'); - console.log(result); - console.log(callback.toString()); - if (callback) { - return callback.call(_this, result.value); - } - }; - - this.api.execute(function() { - // cusotm logic - return 'hello'; - }, [], execcallback); - - // var result = {'value':'hello'}; - - return this; - }; -}; diff --git a/test/spec/e2e/custom-reporter/junit.xml.ejs b/test/spec/e2e/custom-reporter/junit.xml.ejs deleted file mode 100644 index f03e0ee38e5..00000000000 --- a/test/spec/e2e/custom-reporter/junit.xml.ejs +++ /dev/null @@ -1,32 +0,0 @@ - - - - - <% for (var item in module.completed) { - var testcase = module.completed[item]; - var assertions = testcase.assertions %> - <% - for (var i = 0; i < assertions.length; i++) { %><% if (assertions[i].failure) { %> <%= assertions[i].stackTrace %><% } %> -<% if (assertions[i].screenshots && assertions[i].screenshots.length > 0) { %><% for (var j = 0; j < assertions[i].screenshots.length; j++) { %>[[ATTACHMENT|<%= assertions[i].screenshots[j] %>]]<% } %><% } %> - <% } - if (testcase.failed > 0 && testcase.stackTrace) { - %><%= testcase.stackTrace %><% } %> - <% if (systemerr != '') {%> - - <%= systemerr %> - <% } %> - <% } %> - <% if (module.skipped && (module.skipped.length > 0)) { %> - <% for (var j = 0; j < module.skipped.length; j++) { %> - - - - <% } %> - <% } %> - - diff --git a/test/spec/e2e/custom-reporter/pbjs-html-reporter.js b/test/spec/e2e/custom-reporter/pbjs-html-reporter.js deleted file mode 100644 index 85be2a397a5..00000000000 --- a/test/spec/e2e/custom-reporter/pbjs-html-reporter.js +++ /dev/null @@ -1,113 +0,0 @@ -var fs = require('fs.extra'); -var path = require('path'); -var ejs = require('ejs'); - -module.exports = new function() { - var tmpl = __dirname + '/junit.xml.ejs'; - var tmplData; - var globalResults; - - function loadTemplate(cb) { - if (tmplData) { - cb(tmplData); - return; - } - fs.readFile(tmpl, function (err, data) { - if (err) { - throw err; - } - tmplData = data.toString(); - cb(tmplData); - }); - } - - function adaptAssertions(module) { - Object.keys(module.completed).forEach(function(item) { - var testcase = module.completed[item]; - var assertions = testcase.assertions; - for (var i = 0; i < assertions.length; i++) { - if (assertions[i].stackTrace) { - assertions[i].stackTrace = stackTraceFilter(assertions[i].stackTrace.split('\n')); - } - } - - if (testcase.failed > 0 && testcase.stackTrace) { - var stackParts = testcase.stackTrace.split('\n'); - var errorMessage = stackParts.shift(); - testcase.stackTrace = stackTraceFilter(stackParts); - testcase.message = errorMessage; - } - }); - } - - function writeReport(moduleKey, data, opts, callback) { - var module = globalResults.modules[moduleKey]; - var pathParts = moduleKey.split(path.sep); - var moduleName = pathParts.pop(); - var output_folder = opts.output_folder; - adaptAssertions(module); - - var rendered = ejs.render(data, { - module: module, - moduleName: moduleName, - systemerr: globalResults.errmessages.join('\n'), - }); - - if (pathParts.length) { - output_folder = path.join(output_folder, pathParts.join(path.sep)); - fs.mkdirpSync(output_folder); - } - - var filename = path.join(output_folder, opts.filename_prefix + moduleName + '.xml'); - fs.writeFile(filename, rendered, function(err) { - callback(err); - globalResults.errmessages.length = 0; - }); - } - - function stackTraceFilter(parts) { - var stack = parts.reduce(function(list, line) { - if (contains(line, [ - 'node_modules', - '(node.js:', - '(events.js:' - ])) { - return list; - } - - list.push(line); - return list; - }, []); - - return stack.join('\n'); - } - - function contains(str, text) { - if (Object.prototype.toString.call(text) === '[object Array]') { - for (var i = 0; i < text.length; i++) { - if (contains(str, text[i])) { - return true; - } - } - } - return str.indexOf(text) > -1; - } - - this.write = function(results, options, callback) { - options.filename_prefix = process.env.__NIGHTWATCH_ENV + '_'; - globalResults = results; - var keys = Object.keys(results.modules); - - loadTemplate(function createReport(data) { - var moduleKey = keys.shift(); - - writeReport(moduleKey, data, options, function(err) { - if (err || (keys.length === 0)) { - callback(err); - } else { - createReport(data); - } - }); - }); - }; -}(); diff --git a/test/spec/e2e/gpt-examples/all_bidders_instant_load.html b/test/spec/e2e/gpt-examples/all_bidders_instant_load.html deleted file mode 100644 index bf31b769431..00000000000 --- a/test/spec/e2e/gpt-examples/all_bidders_instant_load.html +++ /dev/null @@ -1,830 +0,0 @@ - - - - - - - - - -

    Prebid.js Test3

    - -

    adequant

    -
    -

    No response

    - -
    - -

    adform

    -
    -

    No response

    - -
    - - -

    aol

    -
    -

    No response

    - -
    - -

    appnexus

    -
    -

    No response

    - -
    - -

    indexExchange

    -
    -

    No response

    - -
    - -

    openx

    -
    -

    No response

    - -
    - -

    pubmatic

    -
    -

    No response

    - -
    - -

    pulsepoint

    -
    -

    No response

    - -
    - -

    rubicon

    -
    -

    No response

    - -
    - -

    sonobi

    -
    -

    No response

    - -
    - -

    sovrn

    -
    -

    No response

    - -
    - -

    springserve

    -
    -

    No response

    - -
    - -

    triplelift

    -
    -

    No response

    - -
    - -

    yieldbot

    -
    -

    No response

    - -
    - -

    nginad

    -
    -

    No response

    - -
    - -

    brightcom

    -
    -

    No response

    - -
    - -

    sekindo

    -
    -

    No response

    - -
    - -

    kruxlink

    -
    -

    No response

    - -
    - -

    AdMedia

    -
    -

    No response

    - -
    - - - - - - - - - - diff --git a/test/spec/e2e/gpt-examples/e2e_default.html b/test/spec/e2e/gpt-examples/e2e_default.html deleted file mode 100644 index 9e0437d6275..00000000000 --- a/test/spec/e2e/gpt-examples/e2e_default.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - -

    Prebid.js TestCase1

    - - -
    - -
    -
    - -
    - - - \ No newline at end of file diff --git a/test/spec/e2e/gpt-examples/gpt_default.html b/test/spec/e2e/gpt-examples/gpt_default.html deleted file mode 100644 index 93ec054b59a..00000000000 --- a/test/spec/e2e/gpt-examples/gpt_default.html +++ /dev/null @@ -1,684 +0,0 @@ - - - - - - - - - - -

    Prebid.js Test3

    - - -
    - -
    - -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - - -
    - -
    - -
    - -
    -
    - -
    -
    - -
    - - - -
    - -
    - - - - - - - - - diff --git a/test/spec/e2e/gpt-examples/gpt_outstream.html b/test/spec/e2e/gpt-examples/gpt_outstream.html deleted file mode 100644 index 42ba48c98e7..00000000000 --- a/test/spec/e2e/gpt-examples/gpt_outstream.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - Prebid.js outstream video example - - - - - -

    Prebid Outstream Video Ads

    - -
    -

    -In scelerisque sem sed tortor posuere sagittis. Fusce scelerisque odio at tincidunt ultricies. Fusce egestas, erat non finibus dictum, nulla arcu viverra nibh, at bibendum ligula nisi egestas magna. Nulla eu finibus nulla. Pellentesque at mi eget turpis consequat scelerisque. Sed lacinia, nisi sit amet egestas vestibulum, elit odio iaculis leo, et lacinia risus enim non lacus. Cras nec neque eget nunc gravida maximus. Ut hendrerit convallis sollicitudin. Donec cursus erat vel metus gravida, et pretium justo iaculis. Curabitur condimentum blandit augue, quis interdum leo. Vivamus dapibus est nec dui efficitur, eu imperdiet nulla sollicitudin. Suspendisse laoreet velit vitae arcu mollis, ac interdum lorem venenatis. Aenean nec purus varius, accumsan ex at, luctus arcu. Quisque consectetur tortor eros, placerat lacinia eros aliquam a. Proin non porttitor libero. -

    -

    -Proin eget vulputate est. Nunc sit amet neque a tortor ullamcorper suscipit non eu neque. Quisque at massa in metus feugiat rutrum. Nulla et orci orci. Aliquam erat volutpat. Cras tincidunt metus lectus, sed suscipit augue mollis vitae. Sed quis condimentum tortor, sit amet consectetur erat. Nulla pellentesque turpis lacus, eu venenatis massa fringilla at. Duis sed pharetra turpis. Maecenas vel porttitor neque. Praesent quis felis sapien. Donec suscipit euismod dui, vitae fermentum nisi ornare in. -

    -

    -Suspendisse tempor felis accumsan orci finibus, imperdiet mollis arcu imperdiet. In eu dolor condimentum, pulvinar nisl a, sollicitudin nunc. Ut vel lectus libero. Praesent rhoncus leo tortor, at mollis nulla sagittis eget. Quisque tempus tempor augue sed rutrum. Sed vitae volutpat quam. Proin vestibulum eros metus, a luctus erat condimentum eu. Vivamus ullamcorper ultricies dui, ac malesuada leo finibus semper. Cras diam augue, imperdiet sed efficitur id, aliquam sed purus. Praesent eget turpis quis sapien interdum sagittis. Vivamus placerat nunc a tempus fermentum. Praesent laoreet leo at tellus porta, ut viverra tortor pharetra. Quisque elit velit, eleifend eget imperdiet vel, suscipit ac nisi. Aliquam egestas mauris ut massa fringilla laoreet. -

    -

    -Quisque ac luctus nisi, vitae ornare arcu. Proin fermentum sapien vitae odio vestibulum porta. Suspendisse faucibus sapien enim, et faucibus urna tempus et. Integer porttitor justo sed faucibus blandit. Morbi semper lectus vitae semper facilisis. Quisque molestie accumsan arcu, eget bibendum dui euismod et. Sed in mattis lacus, nec lacinia sem. Fusce sed tortor posuere, iaculis justo varius, elementum est. -

    -

    -Etiam condimentum, eros commodo semper tristique, lorem leo pharetra massa, eget cursus justo enim id urna. Sed imperdiet mauris vitae ante bibendum elementum. Etiam eu dui porttitor leo imperdiet cursus. Maecenas consequat, neque a dapibus viverra, nunc velit volutpat nibh, ut cursus sem tortor ac arcu. Praesent convallis lacus vel nisi aliquam, in posuere libero scelerisque. Curabitur et lacinia nisl. Nunc id ligula neque. Phasellus non eros et leo ultrices ultricies. Nulla facilisi. Donec ut augue urna. Suspendisse sodales nisi at ex faucibus, et tempus magna fermentum. Proin non arcu interdum, pulvinar est at, vehicula odio. Morbi nec maximus sem. Ut eu tristique urna. -

    -

    -Pellentesque eget quam sem. Nam interdum eleifend leo, mattis sagittis metus ornare tristique. Cras pretium odio lectus, vitae viverra massa consequat eget. Suspendisse porttitor pretium lectus in scelerisque. Phasellus euismod porta lectus eget pharetra. Ut et viverra mi, ut imperdiet lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nunc tempus sapien sit amet tortor rhoncus dignissim. Sed at augue et sem lacinia feugiat. Nulla vitae convallis urna. Morbi scelerisque erat quis nibh pretium, non elementum elit consectetur. Proin in feugiat nisl. -

    -

    -Morbi et ipsum purus. Integer ut pulvinar metus. Fusce maximus ex nec purus sollicitudin gravida. Vivamus dapibus volutpat erat nec tristique. Aliquam mi dolor, pretium non elementum quis, viverra non est. Pellentesque egestas, lectus a posuere imperdiet, nisi sem elementum neque, eu volutpat arcu turpis venenatis magna. Curabitur non neque consectetur, vulputate urna sed, vestibulum lacus. Aenean mollis, risus non pulvinar egestas, lectus lectus finibus dui, sit amet pretium metus mauris vitae nibh. In non ultricies odio. -

    -

    -Donec dictum sem ac risus molestie lobortis. Maecenas at justo vehicula, iaculis orci eget, eleifend nunc. In non justo imperdiet, blandit leo in, interdum mi. Proin feugiat libero et erat dictum efficitur. Nunc auctor lacus feugiat erat euismod cursus. Sed vehicula ante vel quam pretium blandit. Maecenas congue quis mauris vitae efficitur. Cras sit amet justo at sem dictum ornare vitae eu ex. Nunc ornare odio nec leo consectetur cursus. Mauris eu dolor tellus. Etiam dignissim ut nunc et mollis. Cras at pulvinar velit, ut tincidunt velit. Cras vitae fermentum ante. Aenean interdum dolor in scelerisque consectetur. -

    -

    -Curabitur auctor leo sit amet massa faucibus ultrices. Maecenas dignissim libero ac cursus cursus. Curabitur eget sapien leo. Phasellus pretium blandit facilisis. Proin egestas urna a sagittis tempus. Donec in nibh ex. Vestibulum efficitur felis aliquam urna ultrices, at gravida nibh pretium. Morbi dictum vulputate pretium. Donec at nisi rutrum, pharetra nunc a, placerat felis. Quisque rhoncus congue fermentum. Quisque pharetra est at nisl sagittis suscipit. Maecenas scelerisque porta eleifend. Mauris nulla leo, consectetur at eros vel, elementum pretium diam. -

    -

    -In nisi libero, porta ut ullamcorper a, dapibus nec velit. Vestibulum congue rhoncus congue. Nulla a libero sit amet risus feugiat hendrerit id placerat ex. In hac habitasse platea dictumst. Pellentesque ut ullamcorper risus. Nunc et ipsum nisi. Vivamus a interdum diam, hendrerit pellentesque orci. -

    -

    -Vestibulum ut massa blandit, maximus sem vitae, vulputate mauris. Nam condimentum velit a facilisis dignissim. Nunc venenatis pharetra dapibus. Praesent ullamcorper risus sit amet molestie consectetur. Cras mauris felis, consequat et enim a, ultricies pretium enim. Nulla porttitor nunc mi, sed posuere magna venenatis non. Donec lobortis consectetur mauris, fermentum auctor dui dignissim sed. Sed vel venenatis urna. Donec velit velit, imperdiet non vulputate non, eleifend sed nisi. -

    -

    -Proin et turpis velit. Donec tempus dictum dolor, eget eleifend lacus. Donec eu felis in ante iaculis ultrices. Mauris varius, turpis quis venenatis convallis, enim dolor ornare justo, in dictum ipsum purus quis dolor. Ut condimentum feugiat lectus ut auctor. Maecenas luctus consequat erat, nec pretium urna pulvinar in. Donec gravida rhoncus aliquet. Cras aliquet odio eget orci hendrerit, non posuere velit dignissim. Nunc tempus aliquam iaculis. Nunc viverra lobortis mauris et malesuada. Donec congue suscipit mauris. Phasellus efficitur, leo at mollis maximus, lorem mauris pretium urna, nec scelerisque ante neque eu erat. Nam rhoncus malesuada velit nec ultricies. -

    -
    -

    Prebid Outstream Video Ad

    - -
    - -

    -Proin blandit in arcu sed porttitor. Morbi in erat vel risus mollis interdum. Proin vel odio semper, porttitor risus sed, tristique odio. Donec viverra massa et dui scelerisque, ac sagittis odio viverra. Aliquam lacinia enim sit amet dapibus ultrices. Nulla mollis, massa eget interdum egestas, lectus eros pretium eros, vel consectetur velit odio vel odio. Proin euismod aliquam finibus. Phasellus facilisis mollis est, non consequat lectus volutpat nec. -

    -

    -Ut vel ultricies erat. Pellentesque non ipsum quis odio ornare tempus in cursus ex. In a turpis non quam pulvinar tincidunt. Maecenas tortor neque, dapibus a quam aliquet, dictum pellentesque leo. Sed aliquet tellus est, in tempus magna congue ut. Phasellus at tincidunt lorem, id fringilla risus. Nunc vel pulvinar massa. Aliquam erat volutpat. Phasellus semper interdum justo at eleifend. Curabitur feugiat quam sed mollis facilisis. -

    -

    -Quisque consectetur sem a elit aliquet facilisis. Quisque dignissim velit at quam rhoncus dignissim. Proin feugiat sem at turpis ultrices imperdiet. Integer vel eros vel ante ultricies dapibus vitae eget dui. Fusce sollicitudin semper tortor at molestie. Pellentesque nec metus sed mauris aliquet iaculis. Mauris malesuada tortor nec mi dictum, feugiat euismod enim gravida. Vestibulum dapibus ut nulla vel euismod. Nunc lobortis, mauris at pretium faucibus, ligula diam venenatis nulla, in mattis sapien arcu feugiat dolor. In at dui leo. Cras elementum condimentum turpis. -

    -

    -Donec eget dolor ac nulla lobortis bibendum. Praesent commodo accumsan ligula eget commodo. Suspendisse sit amet dignissim metus. Sed ut eros viverra, viverra lectus eget, ornare eros. Mauris elementum lacinia dapibus. Donec magna nisl, suscipit quis mattis eget, tincidunt sed sapien. Curabitur elementum nulla eget lorem gravida dapibus. Nunc vel dolor et libero pretium interdum vitae eget mauris. Vestibulum et erat in nulla sollicitudin luctus ut quis nulla. -

    -

    -Maecenas iaculis pellentesque quam at fringilla. Donec dui elit, suscipit eget varius id, suscipit efficitur metus. Nulla rutrum ultrices tempor. Vivamus hendrerit justo ac fermentum euismod. Vestibulum tempus pulvinar tempus. Curabitur congue neque luctus dolor vehicula, non efficitur metus fringilla. Nam a imperdiet ex. Integer at est hendrerit, rutrum justo eu, ornare odio. Etiam convallis sapien a purus vehicula, eget gravida purus semper. Fusce ex enim, volutpat ac feugiat et, rhoncus vel tortor. Aenean ultrices libero sed neque fermentum tempor. Morbi tincidunt dui turpis, non mollis est dignissim at. Suspendisse molestie convallis interdum. Donec sit amet fermentum purus. -

    -

    -Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam et ex orci. Vivamus rutrum est vel porta imperdiet. Cras ultricies tortor dolor, nec mollis felis ullamcorper vel. Praesent scelerisque vehicula sem, nec feugiat mauris tempus ac. Donec at enim non sem commodo sodales. Ut sit amet risus sit amet ante viverra venenatis. Aliquam sodales mollis est eget ultricies. Etiam pulvinar sapien et ipsum elementum pharetra. -

    -

    -Nam blandit metus erat, sit amet congue ipsum cursus sed. In a commodo ante, sit amet tincidunt quam. Aenean lobortis et nibh in venenatis. Aliquam faucibus purus quis neque consectetur, quis consequat risus maximus. Proin mollis imperdiet felis, eget tempus ipsum scelerisque ut. Sed euismod interdum augue sed varius. Sed volutpat tellus ut risus porta accumsan. -

    -

    -Mauris aliquet eu arcu sed pharetra. Duis nec leo volutpat libero finibus malesuada in eget velit. Aliquam facilisis urna mauris, et aliquam ipsum dictum finibus. Donec eget mi fermentum, vehicula odio at, molestie orci. In a hendrerit lectus. Aenean congue ipsum ac imperdiet suscipit. Maecenas eleifend pretium metus id mollis. -

    -
    -

    Prebid Outstream Video Ad

    - -
    - -

    -Ut vel ultricies erat. Pellentesque non ipsum quis odio ornare tempus in cursus ex. In a turpis non quam pulvinar tincidunt. Maecenas tortor neque, dapibus a quam aliquet, dictum pellentesque leo. Sed aliquet tellus est, in tempus magna congue ut. Phasellus at tincidunt lorem, id fringilla risus. Nunc vel pulvinar massa. Aliquam erat volutpat. Phasellus semper interdum justo at eleifend. Curabitur feugiat quam sed mollis facilisis. -

    -

    -Quisque consectetur sem a elit aliquet facilisis. Quisque dignissim velit at quam rhoncus dignissim. Proin feugiat sem at turpis ultrices imperdiet. Integer vel eros vel ante ultricies dapibus vitae eget dui. Fusce sollicitudin semper tortor at molestie. Pellentesque nec metus sed mauris aliquet iaculis. Mauris malesuada tortor nec mi dictum, feugiat euismod enim gravida. Vestibulum dapibus ut nulla vel euismod. Nunc lobortis, mauris at pretium faucibus, ligula diam venenatis nulla, in mattis sapien arcu feugiat dolor. In at dui leo. Cras elementum condimentum turpis. -

    -

    -Donec eget dolor ac nulla lobortis bibendum. Praesent commodo accumsan ligula eget commodo. Suspendisse sit amet dignissim metus. Sed ut eros viverra, viverra lectus eget, ornare eros. Mauris elementum lacinia dapibus. Donec magna nisl, suscipit quis mattis eget, tincidunt sed sapien. Curabitur elementum nulla eget lorem gravida dapibus. Nunc vel dolor et libero pretium interdum vitae eget mauris. Vestibulum et erat in nulla sollicitudin luctus ut quis nulla. -

    -

    -Maecenas iaculis pellentesque quam at fringilla. Donec dui elit, suscipit eget varius id, suscipit efficitur metus. Nulla rutrum ultrices tempor. Vivamus hendrerit justo ac fermentum euismod. Vestibulum tempus pulvinar tempus. Curabitur congue neque luctus dolor vehicula, non efficitur metus fringilla. Nam a imperdiet ex. Integer at est hendrerit, rutrum justo eu, ornare odio. Etiam convallis sapien a purus vehicula, eget gravida purus semper. Fusce ex enim, volutpat ac feugiat et, rhoncus vel tortor. Aenean ultrices libero sed neque fermentum tempor. Morbi tincidunt dui turpis, non mollis est dignissim at. Suspendisse molestie convallis interdum. Donec sit amet fermentum purus. -

    - -
    - - - diff --git a/test/spec/e2e/gpt-examples/gpt_yieldbot.html b/test/spec/e2e/gpt-examples/gpt_yieldbot.html deleted file mode 100644 index 12766c537f6..00000000000 --- a/test/spec/e2e/gpt-examples/gpt_yieldbot.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - - - - - -
    -
    - Yieldbot integration test mode: - -
      -
    • START (i.e.force bids to be returned)
    • -
    • STOP
    • -
    -
    - -

    Prebid.js Yieldbot Adapter Test

    -
    -
    - -
    -

    Lorem ipsum dolor. Sit amet proin. Integer cursus mi mus curabitur euismod vel quos duis bibendum nec interdum porta dolor a viverra nisl fusce. Volutpat sit at. Donec nisl taciti. Eget eu lobortis. Excepteur diam orci lacus nibh pharetra. Justo neque maecenas. Viverra molestie dolor ante rutrum vivamus libero urna suscipit leo praesent ultricies. In dignissim qui ante bibendum in. Habitasse ac arcu non nulla augue. Felis lectus non tempus in aliquam. Sit porttitor nec. Sodales non sit eu duis.

    -
    - -
    -

    Donec feugiat ornare a amet optio. Vitae sit sapien. Vitae nec justo. Fusce ac in semper ligula duis eget vel sit. Augue mauris sit. A adipisicing orci est augue dapibus ullamcorper faucibus fermentum. Et phasellus in tempus vivamus praesent. Nisl dui porttitor. Iaculis vulputate eros ut interdum eu. Lacus quis magna varius in quis. Congue erat porttitor sit eu vitae pharetra scelerisque nec. Dolor dui vel ut velit vestibulum. Lectus ullamcorper mi. Curabitur ipsum pellentesque sed erat est est sapien in tempor sodales viverra. Dui volutpat morbi eleifend fringilla quis. Neque erat erat. Rhoncus sed posuere. Dapibus fusce ut lacus mus est pede sed quisquam. Quis aliquam pellentesque. Wisi ac odio eu wisi amet ut ipsum a erat aliquam nunc.

    -

    Dis vitae penatibus. Mollis mauris bibendum. Porta orci amet dolor sed felis in neque per cursus molestie pellentesque. Quis accusamus vel sed dapibus orci congue ut eros. Nec faucibus inceptos. Hendrerit in eget nulla tellus lacinia. Fusce ut ut mattis.

    -

    Vivamus mauris metus. Ridiculus habitant lorem in nulla in quam eros ut. Libero aliquam platea. In enim consectetuer eget mattis accumsan aenean faucibus tincidunt. Amet donec vitae wisi pellentesque magna non lacinia qui. In erat in maecenas amet dui. Aliquam elit vel. Ligula sodales lacus. Nisl a purus. Pharetra velit porttitor vel vel non turpis viverra fringilla lorem arcu pellentesque sed aliquet nonummy quisque dapibus ullamcorper. Mollis ipsum nulla. Tempor tempus vitae. Luctus amet vel. Suspendisse sagittis vestibulum fusce eu.

    -

    Urna et felis bibendum felis sit vestibulum wisi pharetra quisque ac quis cursus suspendisse quisque aenean luctus curabitur. Eget nec leo. Mi placerat cras nulla et integer eget in sed. Non magni parturient. Egestas iaculis malesuada. Nec a duis. Pede condimentum ullamcorper. Augue arcu tellus. In velit in in duis odio dictum wisi proin quis eget sit. Felis tempus inceptos. Turpis risus eu. Mi vivamus consequat. Lectus dui imperdiet amet orci vehicula in vel pellentesque habitant suscipit aliquam. Proin porttitor vitae ultricies a in. Est duis pede. Tristique velit vestibulum odio sodales morbi magna ut vitae. Elementum imperdiet sodales ultrices tortor mollis vehicula lorem varius pellentesque mi ut sit turpis feugiat. In convallis urna. Justo aliquam sed quis scelerisque nonummy. Lobortis rhoncus ornare. Pellentesque leo quam at beatae in. Erat lorem tempus. Molestie faucibus a id mauris montes. Sed orci vulputate. Libero justo curabitur. Amet orci ante. Non felis est erat cras purus id at id nibh nunc facilisis amet metus sagittis pellentesque eros amet. Vitae sit nulla vitae wisi diam. Tincidunt ipsum eleifend semper tortor non. Tellus amet aliquet.

    -

    Dis vitae penatibus. Mollis mauris bibendum. Porta orci amet dolor sed felis in neque per cursus molestie pellentesque. Quis accusamus vel sed dapibus orci congue ut eros. Nec faucibus inceptos. Hendrerit in eget nulla tellus lacinia. Fusce ut ut mattis.

    -

    Vivamus mauris metus. Ridiculus habitant lorem in nulla in quam eros ut. Libero aliquam platea. In enim consectetuer eget mattis accumsan aenean faucibus tincidunt. Amet donec vitae wisi pellentesque magna non lacinia qui. In erat in maecenas amet dui. Aliquam elit vel. Ligula sodales lacus. Nisl a purus. Pharetra velit porttitor vel vel non turpis viverra fringilla lorem arcu pellentesque sed aliquet nonummy quisque dapibus ullamcorper. Mollis ipsum nulla. Tempor tempus vitae. Luctus amet vel. Suspendisse sagittis vestibulum fusce eu.

    -

    Urna et felis bibendum felis sit vestibulum wisi pharetra quisque ac quis cursus suspendisse quisque aenean luctus curabitur. Eget nec leo. Mi placerat cras nulla et integer eget in sed. Non magni parturient. Egestas iaculis malesuada. Nec a duis. Pede condimentum ullamcorper. Augue arcu tellus. In velit in in duis odio dictum wisi proin quis eget sit. Felis tempus inceptos. Turpis risus eu. Mi vivamus consequat. Lectus dui imperdiet amet orci vehicula in vel pellentesque habitant suscipit aliquam. Proin porttitor vitae ultricies a in. Est duis pede. Tristique velit vestibulum odio sodales morbi magna ut vitae. Elementum imperdiet sodales ultrices tortor mollis vehicula lorem varius pellentesque mi ut sit turpis feugiat. In convallis urna. Justo aliquam sed quis scelerisque nonummy. Lobortis rhoncus ornare. Pellentesque leo quam at beatae in. Erat lorem tempus. Molestie faucibus a id mauris montes. Sed orci vulputate. Libero justo curabitur. Amet orci ante. Non felis est erat cras purus id at id nibh nunc facilisis amet metus sagittis pellentesque eros amet. Vitae sit nulla vitae wisi diam. Tincidunt ipsum eleifend semper tortor non. Tellus amet aliquet.

    -
    -
    - -
    -
    - -
    -
    -

    Dis vitae penatibus. Mollis mauris bibendum. Porta orci amet dolor sed felis in neque per cursus molestie pellentesque. Quis accusamus vel sed dapibus orci congue ut eros. Nec faucibus inceptos. Hendrerit in eget nulla tellus lacinia. Fusce ut ut mattis.

    -
    - - diff --git a/test/spec/e2e/testcase1/dom-group/allbidders_dom_spec.js b/test/spec/e2e/testcase1/dom-group/allbidders_dom_spec.js deleted file mode 100644 index 5803ad5ceb3..00000000000 --- a/test/spec/e2e/testcase1/dom-group/allbidders_dom_spec.js +++ /dev/null @@ -1,125 +0,0 @@ -// var verify = require('verify'); -var util = require('../../common/utils.js'); - -module.exports = { - 'adequant ad rendering': function (browser) { - browser - .url('http://an.localhost:9999/test/spec/e2e/gpt-examples/all_bidders_instant_load.html') - .waitForElementVisible('body', 5000) - .pause(7000) - .execute(util.findIframeInDiv, ['div-1'], function(result) { - this.verify.equal(result.value, true, 'adequant ad not rendered'); - }); - }, - 'adform ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-2'], function(result) { - this.verify.equal(result.value, true, 'adform ad not rendered'); - }); - }, - 'aol ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-3'], function(result) { - this.verify.equal(result.value, true, 'aol ad not rendered'); - }); - }, - 'appnexus ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-4'], function(result) { - this.verify.equal(result.value, true, 'appnexus ad not rendered'); - }); - }, - 'indexExchange ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-5'], function(result) { - this.verify.equal(result.value, true, 'indexExchange ad not rendered'); - }); - }, - 'openx ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-6'], function(result) { - this.verify.equal(result.value, true, 'openx ad not rendered'); - }); - }, - 'pubmatic ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-7'], function(result) { - this.verify.equal(result.value, true, 'pubmatic ad not rendered'); - }); - }, - 'pulsepoint ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-8'], function(result) { - this.verify.equal(result.value, true, 'pulsepoint ad not rendered'); - }); - }, - 'rubicon ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-9'], function(result) { - this.verify.equal(result.value, true, 'rubicon ad not rendered'); - }); - }, - 'sonobi ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-10'], function(result) { - this.verify.equal(result.value, true, 'sonobi ad not rendered'); - }); - }, - 'sovrn ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-11'], function(result) { - this.verify.equal(result.value, true, 'sovrn ad not rendered'); - }); - }, - 'springserve ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-12'], function(result) { - this.verify.equal(result.value, true, 'springserve ad not rendered'); - }); - }, - 'triplelift ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-13'], function(result) { - this.verify.equal(result.value, true, 'triplelift ad not rendered'); - }); - }, - 'yieldbot ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-14'], function(result) { - this.verify.equal(result.value, true, 'yieldbot ad not rendered'); - }); - }, - 'nginad ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-15'], function(result) { - this.verify.equal(result.value, true, 'nginad ad not rendered'); - }); - }, - 'brightcom ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-16'], function(result) { - this.verify.equal(result.value, true, 'brightcom ad not rendered'); - }); - }, - 'sekindo ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-17'], function(result) { - this.verify.equal(result.value, true, 'sekindo ad not rendered'); - }); - }, - 'kruxlink ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-18'], function(result) { - this.verify.equal(result.value, true, 'kruxlink ad not rendered'); - }); - }, - 'AdMedia ad rendering': function (browser) { - browser - .execute(util.findIframeInDiv, ['div-19'], function(result) { - this.verify.equal(result.value, true, 'AdMedia ad not rendered'); - }); - }, - after: function(browser) { - browser.end(); - } -}; diff --git a/test/spec/e2e/testcase1/dom-group/dom_spec.js b/test/spec/e2e/testcase1/dom-group/dom_spec.js deleted file mode 100644 index a58030c32b7..00000000000 --- a/test/spec/e2e/testcase1/dom-group/dom_spec.js +++ /dev/null @@ -1,51 +0,0 @@ -// var assert = require('assert'); - -module.exports = { - - 'Test rendering ad div-2': function (browser) { - var checkAdRendering2 = function() { - var div = document.getElementById('div-2'); - var iframes = div.getElementsByTagName('iframe'); - try { - if (iframes.length == 1 && iframes[0].contentWindow.document.body.innerHTML == '') { - return false; - } else { - return true; - } - } catch (e) { - return true; - } - } - - browser - .url('http://an.localhost:9999/test/spec/e2e/gpt-examples/e2e_default.html') - .waitForElementVisible('body', 3000) - .pause(3000) - .execute(checkAdRendering2, [], function(result) { - this.assert.equal(result.value, true, 'Ad of div-2 not rendered'); - }); - }, - 'Test rendering ad div-1': function (browser) { - var checkAdRendering = function() { - var div = document.getElementById('div-1'); - var iframes = div.getElementsByTagName('iframe'); - try { - if (iframes.length == 1 && iframes[0].contentWindow.document.body.innerHTML == '') { - return false; - } else { - return true; - } - } catch (e) { - return true; - } - } - - browser - .execute(checkAdRendering, [], function(result) { - this.assert.equal(result.value, true, 'Ad of div-1 not rendered'); - }); - }, - after: function(browser) { - browser.end(); - } -}; diff --git a/test/spec/e2e/testcase1/pbjsapi-group/adservertargeting_spec.js b/test/spec/e2e/testcase1/pbjsapi-group/adservertargeting_spec.js deleted file mode 100644 index 796707641cd..00000000000 --- a/test/spec/e2e/testcase1/pbjsapi-group/adservertargeting_spec.js +++ /dev/null @@ -1,62 +0,0 @@ -var assert = require('assert'); -var utils = require('util'); - -module.exports = { - 'AdserverTargeting Test Case 1': function (browser) { - browser - .url('http://localhost:9999/test/spec/e2e/gpt-examples/gpt_default.html') - .waitForElementVisible('body', 3000) - .pause(3000) - .execute(function() { - if (typeof window.pbjs.bidderSettings === 'undefined') { - var pbjsBidderSettingsObject = [ - 'hb_bidder', - 'hb_adid', - 'hb_pb', - 'hb_size' - ]; - } else { - var pbjsBidderSettings = window.pbjs.bidderSettings; - var pbjsBidderSettingsObject = {}; - Object.keys(pbjsBidderSettings).forEach(function (prop) { - // if(prop == 'standard') return; - var value = pbjsBidderSettings[prop]; - var bs = value.adserverTargeting.map(function(item) { - return item.key; - }); - pbjsBidderSettings.standard.adserverTargeting.map(function(value) { - if (bs.indexOf(value.key) == -1) { - bs.push(value.key) - } - }); - pbjsBidderSettingsObject[prop] = bs; - }); - } - - var adserverTargetingObject = {}; - var adserverTargeting = window.pbjs.getAdserverTargeting(); - Object.keys(adserverTargeting).forEach(function(value) { - if (Object.keys(adserverTargeting[value]).length == 0) return; - adserverTargetingObject[adserverTargeting[value].hb_bidder] = Object.keys(adserverTargeting[value]) - }); - - return [pbjsBidderSettingsObject, adserverTargetingObject]; - }, [], function(result) { - Object.keys(result.value[1]).forEach(function(key) { - if (utils.isArray(result.value[0])) { - assert.deepEqual(result.value[0].sort(), result.value[1][key].sort()); - } else { - if (result.value[0].hasOwnProperty(key)) { - var obj1 = result.value[0][key].sort(); - } else { - var obj1 = result.value[0]['standard'].sort(); - } - assert.deepEqual(obj1, result.value[1][key].sort()); - } - }); - }); - }, - after: function(browser) { - browser.end(); - } -}; diff --git a/test/spec/e2e/testcase1/pbjsapi-group/getbidresponses_spec.js b/test/spec/e2e/testcase1/pbjsapi-group/getbidresponses_spec.js deleted file mode 100644 index c7921709c0f..00000000000 --- a/test/spec/e2e/testcase1/pbjsapi-group/getbidresponses_spec.js +++ /dev/null @@ -1,34 +0,0 @@ -// var assert = require('assert'); -var assert = require('chai').assert; -var utils = require('util'); - -module.exports = { - 'bidReceived not empty': function(browser) { - browser - .url('http://localhost:9999/test/spec/e2e/gpt-examples/gpt_default.html') - .waitForElementVisible('body', 3000) - .pause(5000) - .execute(function() { - return window.pbjs._bidsReceived.length; - }, [], function(result) { - // browser.assert.first(false, 'Bid response empty'); - assert.isOk(result.value, 'Bid response empty'); - }); - }, - 'check keys': function(browser) { - browser - .execute(function() { - return window.pbjs._bidsReceived; - }, [], function(result) { - // minimum expected keys in bid received - var expected = ['bidderCode', 'width', 'height', 'adId', 'cpm', 'requestId', 'bidder', 'adUnitCode', 'timeToRespond']; - Object.keys(result.value).forEach(function(key) { - var compare = Object.keys(result.value[key]); - assert.includeMembers(compare, expected, 'include members'); - }); - }); - }, - after: function(browser) { - browser.end(); - } -}; diff --git a/test/spec/lfe2e/specs/basic_w_custom_adserver_translation.spec.js b/test/spec/lfe2e/specs/basic_w_custom_adserver_translation.spec.js new file mode 100644 index 00000000000..82310738246 --- /dev/null +++ b/test/spec/lfe2e/specs/basic_w_custom_adserver_translation.spec.js @@ -0,0 +1,68 @@ +const includes = require('core-js/library/fn/array/includes'); +const expect = require('chai').expect; +const testServer = require('../../../helpers/testing-utils'); + +const host = testServer.host; +const protocol = testServer.protocol; + +const validDurations = ['15s', '30s']; +const validCats = ['Food', 'Retail Stores/Chains', 'Pet Food/Supplies', 'Travel/Hotels/Airlines', 'Automotive', 'Health Care Services']; +const validCpms = ['15.00', '14.00', '13.00', '10.00']; +const customKeyRegex = /\d{2}\.\d{2}_\d{1,3}_\d{2}s/; +const uuidRegex = /(\d|\w){8}-((\d|\w){4}-){3}(\d|\w){12}/; + +describe('longform ads using custom adserver translation file', function() { + this.retries(3); + it('process the bids successfully', function() { + browser + .url(protocol + '://' + host + ':9999/integrationExamples/longform/basic_w_custom_adserver_translation.html?pbjs_debug=true') + .pause(10000); + + const loadPrebidBtnXpath = '//*[@id="loadPrebidRequestBtn"]'; + browser.waitForExist(loadPrebidBtnXpath); + $(loadPrebidBtnXpath).click(); + browser.pause(3000); + + const listOfCpmsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[2]'; + const listOfCategoriesXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[3]'; + const listOfDurationsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[4]'; + + browser.waitForExist(listOfCpmsXpath); + + let listOfCpms = $$(listOfCpmsXpath); + let listOfCats = $$(listOfCategoriesXpath); + let listOfDuras = $$(listOfDurationsXpath); + + expect(listOfCpms.length).to.equal(listOfCats.length).and.to.equal(listOfDuras.length); + for (let i = 0; i < listOfCpms.length; i++) { + let cpm = listOfCpms[i].getText(); + let cat = listOfCats[i].getText(); + let dura = listOfDuras[i].getText(); + expect(includes(validCpms, cpm), `Could not find CPM ${cpm} in accepted list`).to.equal(true); + expect(includes(validCats, cat), `Could not find Category ${cat} in accepted list`).to.equal(true); + expect(includes(validDurations, dura), `Could not find Duration ${dura} in accepted list`).to.equal(true); + } + }); + + it('formats the targeting keys properly', function () { + const listOfKeyElementsXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[1]'; + const listOfKeyValuesXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[2]'; + browser.waitForExist(listOfKeyElementsXpath); + browser.waitForExist(listOfKeyValuesXpath); + + let listOfKeyElements = $$(listOfKeyElementsXpath); + let listOfKeyValues = $$(listOfKeyValuesXpath); + + let firstKey = listOfKeyElements[0].getText(); + expect(firstKey).to.equal('hb_pb_cat_dur'); + + let firstKeyValue = listOfKeyValues[0].getText(); + expect(firstKeyValue).match(customKeyRegex); + + let lastKey = listOfKeyElements[listOfKeyElements.length - 1].getText(); + expect(lastKey).to.equal('hb_cache_id'); + + let lastKeyValue = listOfKeyValues[listOfKeyValues.length - 1].getText(); + expect(lastKeyValue).to.match(uuidRegex); + }); +}) diff --git a/test/spec/lfe2e/specs/basic_w_requireExactDuration.spec.js b/test/spec/lfe2e/specs/basic_w_requireExactDuration.spec.js new file mode 100644 index 00000000000..224ff1cbc34 --- /dev/null +++ b/test/spec/lfe2e/specs/basic_w_requireExactDuration.spec.js @@ -0,0 +1,68 @@ +const includes = require('core-js/library/fn/array/includes'); +const expect = require('chai').expect; +const testServer = require('../../../helpers/testing-utils'); + +const host = testServer.host; +const protocol = testServer.protocol; + +const validDurations = ['15s', '30s']; +const validCats = ['Food', 'Retail Stores/Chains', 'Pet Food/Supplies', 'Travel/Hotels/Airlines', 'Automotive', 'Health Care Services']; +const validCpms = ['15.00', '14.00', '13.00', '10.00']; +const customKeyRegex = /\d{2}\.\d{2}_\d{1,3}_\d{2}s/; +const uuidRegex = /(\d|\w){8}-((\d|\w){4}-){3}(\d|\w){12}/; + +describe('longform ads using requireExactDuration field', function() { + this.retries(3); + it('process the bids successfully', function() { + browser + .url(protocol + '://' + host + ':9999/integrationExamples/longform/basic_w_requireExactDuration.html?pbjs_debug=true') + .pause(10000); + + const loadPrebidBtnXpath = '//*[@id="loadPrebidRequestBtn"]'; + browser.waitForExist(loadPrebidBtnXpath); + $(loadPrebidBtnXpath).click(); + browser.pause(3000); + + const listOfCpmsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[2]'; + const listOfCategoriesXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[3]'; + const listOfDurationsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[4]'; + + browser.waitForExist(listOfCpmsXpath); + + let listOfCpms = $$(listOfCpmsXpath); + let listOfCats = $$(listOfCategoriesXpath); + let listOfDuras = $$(listOfDurationsXpath); + + expect(listOfCpms.length).to.equal(listOfCats.length).and.to.equal(listOfDuras.length); + for (let i = 0; i < listOfCpms.length; i++) { + let cpm = listOfCpms[i].getText(); + let cat = listOfCats[i].getText(); + let dura = listOfDuras[i].getText(); + expect(includes(validCpms, cpm), `Could not find CPM ${cpm} in accepted list`).to.equal(true); + expect(includes(validCats, cat), `Could not find Category ${cat} in accepted list`).to.equal(true); + expect(includes(validDurations, dura), `Could not find Duration ${dura} in accepted list`).to.equal(true); + } + }); + + it('formats the targeting keys properly', function () { + const listOfKeyElementsXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[1]'; + const listOfKeyValuesXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[2]'; + browser.waitForExist(listOfKeyElementsXpath); + browser.waitForExist(listOfKeyValuesXpath); + + let listOfKeyElements = $$(listOfKeyElementsXpath); + let listOfKeyValues = $$(listOfKeyValuesXpath); + + let firstKey = listOfKeyElements[0].getText(); + expect(firstKey).to.equal('hb_pb_cat_dur'); + + let firstKeyValue = listOfKeyValues[0].getText(); + expect(firstKeyValue).match(customKeyRegex); + + let lastKey = listOfKeyElements[listOfKeyElements.length - 1].getText(); + expect(lastKey).to.equal('hb_cache_id'); + + let lastKeyValue = listOfKeyValues[listOfKeyValues.length - 1].getText(); + expect(lastKeyValue).to.match(uuidRegex); + }); +}) diff --git a/test/spec/lfe2e/specs/basic_wo_brandCategoryExclusion.spec.js b/test/spec/lfe2e/specs/basic_wo_brandCategoryExclusion.spec.js new file mode 100644 index 00000000000..95237366d0e --- /dev/null +++ b/test/spec/lfe2e/specs/basic_wo_brandCategoryExclusion.spec.js @@ -0,0 +1,63 @@ +const includes = require('core-js/library/fn/array/includes'); +const expect = require('chai').expect; +const testServer = require('../../../helpers/testing-utils'); + +const host = testServer.host; +const protocol = testServer.protocol; + +const validDurations = ['15s', '30s']; +const validCpms = ['15.00', '14.00', '13.00', '10.00']; +const customKeyRegex = /\d{2}\.\d{2}_\d{2}s/; +const uuidRegex = /(\d|\w){8}-((\d|\w){4}-){3}(\d|\w){12}/; + +describe('longform ads without using brandCategoryExclusion', function() { + this.retries(3); + it('process the bids successfully', function() { + browser + .url(protocol + '://' + host + ':9999/integrationExamples/longform/basic_wo_brandCategoryExclusion.html?pbjs_debug=true') + .pause(10000); + + const loadPrebidBtnXpath = '//*[@id="loadPrebidRequestBtn"]'; + browser.waitForExist(loadPrebidBtnXpath); + $(loadPrebidBtnXpath).click(); + browser.pause(3000); + + const listOfCpmsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[2]'; + const listOfDurationsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[4]'; + + browser.waitForExist(listOfCpmsXpath); + + let listOfCpms = $$(listOfCpmsXpath); + let listOfDuras = $$(listOfDurationsXpath); + + expect(listOfCpms.length).to.equal(listOfDuras.length); + for (let i = 0; i < listOfCpms.length; i++) { + let cpm = listOfCpms[i].getText(); + let dura = listOfDuras[i].getText(); + expect(includes(validCpms, cpm), `Could not find CPM ${cpm} in accepted list`).to.equal(true); + expect(includes(validDurations, dura), `Could not find Duration ${dura} in accepted list`).to.equal(true); + } + }); + + it('formats the targeting keys properly', function () { + const listOfKeyElementsXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[1]'; + const listOfKeyValuesXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[2]'; + browser.waitForExist(listOfKeyElementsXpath); + browser.waitForExist(listOfKeyValuesXpath); + + let listOfKeyElements = $$(listOfKeyElementsXpath); + let listOfKeyValues = $$(listOfKeyValuesXpath); + + let firstKey = listOfKeyElements[0].getText(); + expect(firstKey).to.equal('hb_pb_cat_dur'); + + let firstKeyValue = listOfKeyValues[0].getText(); + expect(firstKeyValue).match(customKeyRegex); + + let lastKey = listOfKeyElements[listOfKeyElements.length - 1].getText(); + expect(lastKey).to.equal('hb_cache_id'); + + let lastKeyValue = listOfKeyValues[listOfKeyValues.length - 1].getText(); + expect(lastKeyValue).to.match(uuidRegex); + }); +}) diff --git a/test/spec/lfe2e/specs/basic_wo_requireExactDuration.spec.js b/test/spec/lfe2e/specs/basic_wo_requireExactDuration.spec.js new file mode 100644 index 00000000000..6b628067138 --- /dev/null +++ b/test/spec/lfe2e/specs/basic_wo_requireExactDuration.spec.js @@ -0,0 +1,68 @@ +const includes = require('core-js/library/fn/array/includes'); +const expect = require('chai').expect; +const testServer = require('../../../helpers/testing-utils'); + +const host = testServer.host; +const protocol = testServer.protocol; + +const validDurations = ['15s', '30s']; +const validCats = ['Food', 'Retail Stores/Chains', 'Pet Food/Supplies', 'Travel/Hotels/Airlines', 'Automotive', 'Health Care Services']; +const validCpms = ['15.00', '14.00', '13.00', '10.00']; +const customKeyRegex = /\d{2}\.\d{2}_\d{1,3}_\d{2}s/; +const uuidRegex = /(\d|\w){8}-((\d|\w){4}-){3}(\d|\w){12}/; + +describe('longform ads not using requireExactDuration field', function() { + this.retries(3); + it('process the bids successfully', function() { + browser + .url(protocol + '://' + host + ':9999/integrationExamples/longform/basic_wo_requireExactDuration.html?pbjs_debug=true') + .pause(10000); + + const loadPrebidBtnXpath = '//*[@id="loadPrebidRequestBtn"]'; + browser.waitForExist(loadPrebidBtnXpath); + $(loadPrebidBtnXpath).click(); + browser.pause(3000); + + const listOfCpmsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[2]'; + const listOfCategoriesXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[3]'; + const listOfDurationsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[4]'; + + browser.waitForExist(listOfCpmsXpath); + + let listOfCpms = $$(listOfCpmsXpath); + let listOfCats = $$(listOfCategoriesXpath); + let listOfDuras = $$(listOfDurationsXpath); + + expect(listOfCpms.length).to.equal(listOfCats.length).and.to.equal(listOfDuras.length); + for (let i = 0; i < listOfCpms.length; i++) { + let cpm = listOfCpms[i].getText(); + let cat = listOfCats[i].getText(); + let dura = listOfDuras[i].getText(); + expect(includes(validCpms, cpm), `Could not find CPM ${cpm} in accepted list`).to.equal(true); + expect(includes(validCats, cat), `Could not find Category ${cat} in accepted list`).to.equal(true); + expect(includes(validDurations, dura), `Could not find Duration ${dura} in accepted list`).to.equal(true); + } + }); + + it('formats the targeting keys properly', function () { + const listOfKeyElementsXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[1]'; + const listOfKeyValuesXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[2]'; + browser.waitForExist(listOfKeyElementsXpath); + browser.waitForExist(listOfKeyValuesXpath); + + let listOfKeyElements = $$(listOfKeyElementsXpath); + let listOfKeyValues = $$(listOfKeyValuesXpath); + + let firstKey = listOfKeyElements[0].getText(); + expect(firstKey).to.equal('hb_pb_cat_dur'); + + let firstKeyValue = listOfKeyValues[0].getText(); + expect(firstKeyValue).match(customKeyRegex); + + let lastKey = listOfKeyElements[listOfKeyElements.length - 1].getText(); + expect(lastKey).to.equal('hb_cache_id'); + + let lastKeyValue = listOfKeyValues[listOfKeyValues.length - 1].getText(); + expect(lastKeyValue).to.match(uuidRegex); + }); +}) diff --git a/wdio.conf.js b/wdio.conf.js new file mode 100644 index 00000000000..4e50e68af2e --- /dev/null +++ b/wdio.conf.js @@ -0,0 +1,55 @@ +const browsers = require('./browsers.json'); + +function getCapabilities() { + function getPlatform(os) { + const platformMap = { + 'Windows': 'WINDOWS', + 'OS X': 'MAC', + } + return platformMap[os]; + } + + // remove the IE11 browser from functional tests + delete browsers['bs_ie_11_windows_10']; + + let capabilities = [] + Object.keys(browsers).forEach(key => { + let browser = browsers[key]; + capabilities.push({ + browserName: browser.browser, + platform: getPlatform(browser.os), + version: browser.browser_version, + acceptSslCerts: true, + 'browserstack.networkLogs': true, + 'browserstack.console': 'verbose', + build: 'Prebidjs E2E ' + new Date().toLocaleString() + }); + }); + return capabilities; +} + +exports.config = { + specs: [ + './test/spec/lfe2e/specs/*.js' + ], + services: ['browserstack'], + user: process.env.BROWSERSTACK_USERNAME, + key: process.env.BROWSERSTACK_ACCESS_KEY, + browserstackLocal: true, + // Do not increase this, since we have only 5 parallel tests in browserstack account + maxInstances: 5, + capabilities: getCapabilities(), + logLevel: 'silent', // Level of logging verbosity: silent | verbose | command | data | result | error + coloredLogs: true, + waitforTimeout: 60000, // Default timeout for all waitFor* commands. + connectionRetryTimeout: 60000, // Default timeout in milliseconds for request if Selenium Grid doesn't send response + connectionRetryCount: 3, // Default request retries count + framework: 'mocha', + mochaOpts: { + ui: 'bdd', + timeout: 60000, + compilers: ['js:babel-register'], + }, + // if you see error, update this to spec reporter and logLevel above to get detailed report. + reporters: ['concise'] +}; From 449fc72e3459701d5c1077b04931f025dd53546c Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 23 Apr 2019 16:56:44 -0400 Subject: [PATCH 1182/1594] Prebid 2.12.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1e1c130b6fe..a26453b0e67 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.12.0-pre", + "version": "2.12.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b42627b4b5205d0b11bd92b123abe44363d41060 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 23 Apr 2019 17:03:22 -0400 Subject: [PATCH 1183/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a26453b0e67..1419f99c65f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.12.0", + "version": "2.13.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 2741f95389d59320e41bd4eaaed5498ebdc074e9 Mon Sep 17 00:00:00 2001 From: aprakash-sovrn Date: Thu, 25 Apr 2019 07:15:29 -0600 Subject: [PATCH 1184/1594] Sovrn Analytics Adapter (#3761) * Sovrn Analytics Adapter * unit test fix * use relative paths for imports --- modules/sovrnAnalyticsAdapter.js | 277 ++++++++++ modules/sovrnAnalyticsAdapter.md | 23 + .../modules/sovrnAnalyticsAdapter_spec.js | 472 ++++++++++++++++++ 3 files changed, 772 insertions(+) create mode 100644 modules/sovrnAnalyticsAdapter.js create mode 100644 modules/sovrnAnalyticsAdapter.md create mode 100644 test/spec/modules/sovrnAnalyticsAdapter_spec.js diff --git a/modules/sovrnAnalyticsAdapter.js b/modules/sovrnAnalyticsAdapter.js new file mode 100644 index 00000000000..3113f7ff5af --- /dev/null +++ b/modules/sovrnAnalyticsAdapter.js @@ -0,0 +1,277 @@ +import adapter from '../src/AnalyticsAdapter' +import adaptermanager from '../src/adapterManager' +import CONSTANTS from '../src/constants.json' +import {ajaxBuilder} from '../src/ajax' +import * as utils from '../src/utils' +import {config} from '../src/config' +import find from 'core-js/library/fn/array/find' +import includes from 'core-js/library/fn/array/includes' + +const ajax = ajaxBuilder(0) + +const { + EVENTS: { + AUCTION_END, + BID_REQUESTED, + BID_ADJUSTMENT, + BID_RESPONSE, + BID_WON + } +} = CONSTANTS + +let pbaUrl = 'https://pba.aws.lijit.com/analytics' +let currentAuctions = {}; +const analyticsType = 'endpoint' + +let sovrnAnalyticsAdapter = Object.assign(adapter({url: pbaUrl, analyticsType}), { + track({ eventType, args }) { + try { + if (eventType === BID_WON) { + new BidWinner(this.sovrnId, args).send(); + return + } + if (args && args.auctionId && currentAuctions[args.auctionId] && currentAuctions[args.auctionId].status === 'complete') { + throw new Error('Event Received after Auction Close Auction Id ' + args.auctionId) + } + if (args && args.auctionId && currentAuctions[args.auctionId] === undefined) { + currentAuctions[args.auctionId] = new AuctionData(this.sovrnId, args.auctionId) + } + switch (eventType) { + case BID_REQUESTED: + currentAuctions[args.auctionId].bidRequested(args) + break + case BID_ADJUSTMENT: + currentAuctions[args.auctionId].originalBid(args) + break + case BID_RESPONSE: + currentAuctions[args.auctionId].adjustedBid(args) + break + case AUCTION_END: + currentAuctions[args.auctionId].send(); + break + } + } catch (e) { + new LogError(e, this.sovrnId, {eventType, args}).send() + } + }, +}) + +sovrnAnalyticsAdapter.getAuctions = function () { + return currentAuctions; +}; + +sovrnAnalyticsAdapter.originEnableAnalytics = sovrnAnalyticsAdapter.enableAnalytics; + +// override enableAnalytics so we can get access to the config passed in from the page +sovrnAnalyticsAdapter.enableAnalytics = function (config) { + let sovrnId = '' + if (config && config.options && (config.options.sovrnId || config.options.affiliateId)) { + sovrnId = config.options.sovrnId || config.options.affiliateId; + } else { + 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; + if (config.options.pbaUrl) { + pbaUrl = config.options.pbaUrl; + } + sovrnAnalyticsAdapter.originEnableAnalytics(config) // call the base class function +}; + +adaptermanager.registerAnalyticsAdapter({ + adapter: sovrnAnalyticsAdapter, + code: 'sovrn' +}); + +/** Class Representing a Winning Bid */ +class BidWinner { + /** + * Creates a new bid winner + * @param {string} sovrnId - the affiliate id from the analytics config + * @param {*} event - the args object from the auction event + */ + constructor(sovrnId, event) { + this.body = {} + this.body.prebidVersion = $$REPO_AND_VERSION$$ + this.body.sovrnId = sovrnId + this.body.winningBid = JSON.parse(JSON.stringify(event)) + this.body.url = utils.getTopWindowLocation().href + this.body.payload = 'winner' + delete this.body.winningBid.ad + } + + /** + * Sends the auction to the the ingest server + */ + send() { + this.body.ts = utils.timestamp() + ajax( + pbaUrl, + null, + JSON.stringify(this.body), + { + contentType: 'application/json', + method: 'POST', + } + ) + } +} + +/** Class representing an Auction */ +class AuctionData { + /** + * Create a new auction data collector + * @param {string} sovrnId - the affiliate id from the analytics config + * @param {string} auctionId - the auction id from the auction event + */ + constructor(sovrnId, auctionId) { + this.auction = {} + this.auction.prebidVersion = $$REPO_AND_VERSION$$ + this.auction.sovrnId = sovrnId + this.auction.auctionId = auctionId + this.auction.payload = 'auction' + this.auction.timeouts = { + buffer: config.getConfig('timeoutBuffer'), + bidder: config.getConfig('bidderTimeout'), + } + this.auction.priceGranularity = config.getConfig('priceGranularity') + this.auction.url = utils.getTopWindowLocation().href + this.auction.requests = [] + this.auction.unsynced = [] + this.dropBidFields = ['auctionId', 'ad', 'requestId', 'bidderCode'] + + setTimeout(function(id) { + delete currentAuctions[id] + }, 300000, this.auction.auctionId) + } + + /** + * Record a bid request event + * @param {*} event - the args object from the auction event + */ + bidRequested(event) { + const eventCopy = JSON.parse(JSON.stringify(event)) + delete eventCopy.doneCbCallCount + delete eventCopy.auctionId + this.auction.requests.push(eventCopy) + } + + /** + * Finds the bid from the auction that the event is associated with + * @param {*} event - the args object from the auction event + * @return {*} - the bid + */ + findBid(event) { + const bidder = find(this.auction.requests, r => (r.bidderCode === event.bidderCode)) + if (!bidder) { + this.auction.unsynced.push(JSON.parse(JSON.stringify(event))) + } + let bid = find(bidder.bids, b => (b.bidId === event.requestId)) + + if (!bid) { + event.unmatched = true + bidder.bids.push(JSON.parse(JSON.stringify(event))) + } + return bid + } + + /** + * Records the original bid before any adjustments have been made + * @param {*} event - the args object from the auction event + * NOTE: the bid adjustment occurs before the bid response + * the bid adjustment seems to be the bid ready to be adjusted + */ + originalBid(event) { + let bid = this.findBid(event) + if (bid) { + Object.assign(bid, JSON.parse(JSON.stringify(event))) + this.dropBidFields.forEach((f) => delete bid[f]) + } + } + + /** + * Replaces original values with adjusted values and records the original values for changed values + * in bid.originalValues + * @param {*} event - the args object from the auction event + */ + adjustedBid(event) { + let bid = this.findBid(event) + if (bid) { + bid.originalValues = Object.keys(event).reduce((o, k) => { + if (JSON.stringify(bid[k]) !== JSON.stringify(event[k]) && !includes(this.dropBidFields, k)) { + o[k] = bid[k] + bid[k] = event[k] + } + return o + }, {}) + } + } + + /** + * Sends the auction to the the ingest server + */ + send() { + let maxbid = {cpm: 0} + this.auction.requests.forEach(request => { + request.bids.forEach(bid => { + if (bid.cpm > maxbid.cpm) { + maxbid = bid + } + }) + }) + maxbid.isAuctionWinner = true + this.auction.ts = utils.timestamp() + ajax( + pbaUrl, + () => { + currentAuctions[this.auction.auctionId] = {status: 'complete', auctionId: this.auction.auctionId} + }, + JSON.stringify(this.auction), + { + contentType: 'application/json', + method: 'POST', + } + ) + } +} +class LogError { + constructor(e, sovrnId, data) { + this.error = {} + this.error.payload = 'error' + this.error.message = e.message + this.error.stack = e.stack + this.error.data = data + this.error.prebidVersion = $$REPO_AND_VERSION$$ + this.error.sovrnId = sovrnId + this.error.url = utils.getTopWindowLocation().href + this.error.userAgent = navigator.userAgent + } + send() { + if (this.error.data && this.error.data.requests) { + this.error.data.requests.forEach(request => { + if (request.bids) { + request.bids.forEach(bid => { + if (bid.ad) { + delete bid.ad + } + }) + } + }) + } + if (ErrorEvent.data && error.data.ad) { + delete error.data.ad + } + this.error.ts = utils.timestamp() + ajax( + pbaUrl, + null, + JSON.stringify(this.error), + { + contentType: 'application/json', + method: 'POST', + } + ) + } +} + +export default sovrnAnalyticsAdapter; diff --git a/modules/sovrnAnalyticsAdapter.md b/modules/sovrnAnalyticsAdapter.md new file mode 100644 index 00000000000..80bc6d7f6b1 --- /dev/null +++ b/modules/sovrnAnalyticsAdapter.md @@ -0,0 +1,23 @@ +# Overview + +``` +Module Name: Sovrn Analytics Adapter +Module Type: Analytics Adapter +Maintainer: jrosendahl@sovrn.com +``` + +# Description + +Sovrn's analytics adaptor allows you to view detailed auction information in Meridian. + +For more information, visit Sovrn.com. + +# Test Parameters +``` +{ + provider: 'sovrn', + options: { + sovrnId: 'xxxxx', // Sovrn ID (required) you can get this by contacting Sovrn support. + } +} +``` diff --git a/test/spec/modules/sovrnAnalyticsAdapter_spec.js b/test/spec/modules/sovrnAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..404833f0177 --- /dev/null +++ b/test/spec/modules/sovrnAnalyticsAdapter_spec.js @@ -0,0 +1,472 @@ +import sovrnAnalyticsAdapter from '../../../modules/sovrnAnalyticsAdapter' +import { expect } from 'chai' +import {config} from 'src/config' +import adaptermanager from 'src/adapterManager' +var assert = require('assert'); + +let events = require('src/events'); +let constants = require('src/constants.json'); + +/** + * Emit analytics events + * @param {array} eventArr - array of objects to define the events that will fire + * @param {object} eventObj - key is eventType, value is event + * @param {string} auctionId - the auction id to attached to the events + */ +function emitEvent(eventType, event, auctionId) { + event.auctionId = auctionId; + events.emit(constants.EVENTS[eventType], event); +} + +let auctionStartTimestamp = Date.now(); +let timeout = 3000; +let auctionInit = { + timestamp: auctionStartTimestamp, + timeout: timeout +}; +let bidderCode = 'sovrn'; +let bidderRequestId = '123bri'; +let adUnitCode = 'div'; +let bidId = 'bidid'; +let tId = '7aafa3ee-a80a-46d7-a4a0-cbcba463d97a'; +let bidRequested = { + auctionStart: auctionStartTimestamp, + bidderCode: bidderCode, + bidderRequestId: bidderRequestId, + bids: [ + { + adUnitCode: adUnitCode, + bidId: bidId, + bidder: bidderCode, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 100, + transactionId: tId + } + ], + doneCbCallCount: 1, + start: auctionStartTimestamp, + timeout: timeout +}; +let bidResponse = { + bidderCode: bidderCode, + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '3870e27a5752fb', + mediaType: 'banner', + source: 'client', + requestId: bidId, + cpm: 0.8584999918937682, + creativeId: 'cridprebidrtb', + dealId: null, + currency: 'USD', + netRevenue: true, + ad: '
    divvy mcdiv
    ', + ttl: 60000, + responseTimestamp: auctionStartTimestamp + 150, + requestTimestamp: auctionStartTimestamp + 100, + bidder: bidderCode, + adUnitCode: adUnitCode, + timeToRespond: 50, + pbLg: '0.50', + pbMg: '0.80', + pbHg: '0.85', + pbAg: '0.85', + pbDg: '0.85', + pbCg: '', + size: '300x250', + adserverTargeting: { + hb_bidder: bidderCode, + hb_adid: '3870e27a5752fb', + hb_pb: '0.85' + }, + status: 'rendered' +}; +let bidAdjustment = {}; +for (var k in bidResponse) bidAdjustment[k] = bidResponse[k]; +bidAdjustment.cpm = 0.8; +let bidAdjustmentNoMatchingRequest = { + bidderCode: 'not-sovrn', + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '1', + mediaType: 'banner', + source: 'client', + requestId: '1', + cpm: 0.10, + creativeId: '', + dealId: null, + currency: 'USD', + netRevenue: true, + ad: '
    divvy mcdiv
    ', + ttl: 60000, + responseTimestamp: auctionStartTimestamp + 150, + requestTimestamp: auctionStartTimestamp + 100, + bidder: 'not-sovrn', + adUnitCode: '', + timeToRespond: 50, + pbLg: '0.00', + pbMg: '0.10', + pbHg: '0.10', + pbAg: '0.10', + pbDg: '0.10', + pbCg: '', + size: '300x250', + adserverTargeting: { + hb_bidder: 'not-sovrn', + hb_adid: '1', + hb_pb: '0.10' + }, +}; +let bidResponseNoMatchingRequest = bidAdjustmentNoMatchingRequest; + +describe('Sovrn Analytics Adapter', function () { + let xhr; + let requests; + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + xhr.onCreate = request => requests.push(request); + requests = []; + sinon.stub(events, 'getEvents').returns([]); + }); + afterEach(() => { + xhr.restore(); + events.getEvents.restore(); + }); + + describe('enableAnalytics ', function () { + beforeEach(() => { + sinon.spy(sovrnAnalyticsAdapter, 'track'); + }); + afterEach(() => { + sovrnAnalyticsAdapter.disableAnalytics(); + sovrnAnalyticsAdapter.track.restore(); + }); + + it('should catch all events if affiliate id present', function () { + adaptermanager.enableAnalytics({ + provider: 'sovrn', + options: { + sovrnId: 123 + } + }); + + events.emit(constants.EVENTS.AUCTION_INIT, {}); + events.emit(constants.EVENTS.AUCTION_END, {}); + events.emit(constants.EVENTS.BID_REQUESTED, {}); + events.emit(constants.EVENTS.BID_RESPONSE, {}); + events.emit(constants.EVENTS.BID_WON, {}); + + sinon.assert.callCount(sovrnAnalyticsAdapter.track, 5); + }); + + it('should catch no events if no affiliate id', function () { + adaptermanager.enableAnalytics({ + provider: 'sovrn', + options: { + } + }); + + events.emit(constants.EVENTS.AUCTION_INIT, {}); + events.emit(constants.EVENTS.AUCTION_END, {}); + events.emit(constants.EVENTS.BID_REQUESTED, {}); + events.emit(constants.EVENTS.BID_RESPONSE, {}); + events.emit(constants.EVENTS.BID_WON, {}); + + sinon.assert.callCount(sovrnAnalyticsAdapter.track, 0); + }); + }); + + describe('sovrnAnalyticsAdapter ', function() { + beforeEach(() => { + sovrnAnalyticsAdapter.enableAnalytics({ + provider: 'sovrn', + options: { + sovrnId: 123 + } + }); + sinon.spy(sovrnAnalyticsAdapter, 'track'); + }); + afterEach(() => { + sovrnAnalyticsAdapter.disableAnalytics(); + sovrnAnalyticsAdapter.track.restore(); + }); + it('should have correct type', function () { + assert.equal(sovrnAnalyticsAdapter.getAdapterType(), 'endpoint') + }) + }); + + describe('auction data collector ', function() { + beforeEach(() => { + sovrnAnalyticsAdapter.enableAnalytics({ + provider: 'sovrn', + options: { + sovrnId: 123 + } + }); + sinon.spy(sovrnAnalyticsAdapter, 'track'); + }); + afterEach(() => { + sovrnAnalyticsAdapter.disableAnalytics(); + sovrnAnalyticsAdapter.track.restore(); + }); + it('should create auctiondata record from init ', function () { + let auctionId = '123.123.123.123'; + emitEvent('AUCTION_INIT', auctionInit, auctionId); + + let auctionData = sovrnAnalyticsAdapter.getAuctions(); + let currentAuction = auctionData[auctionId]; + assert(currentAuction); + let expectedTimeOutData = { + buffer: config.getConfig('timeoutBuffer'), + bidder: config.getConfig('bidderTimeout'), + }; + expect(currentAuction.auction.timeouts).to.deep.equal(expectedTimeOutData); + assert.equal(currentAuction.auction.payload, 'auction'); + assert.equal(currentAuction.auction.priceGranularity, config.getConfig('priceGranularity')) + assert.equal(currentAuction.auction.auctionId, auctionId); + assert.equal(currentAuction.auction.sovrnId, 123); + }); + it('should create a bidrequest object ', function() { + let auctionId = '234.234.234.234'; + emitEvent('AUCTION_INIT', auctionInit, auctionId); + emitEvent('BID_REQUESTED', bidRequested, auctionId); + + let auctionData = sovrnAnalyticsAdapter.getAuctions(); + let currentAuction = auctionData[auctionId]; + assert(currentAuction); + let requests = currentAuction.auction.requests; + assert(requests); + assert.equal(requests.length, 1); + assert.equal(requests[0].bidderCode, bidderCode); + assert.equal(requests[0].bidderRequestId, bidderRequestId); + assert.equal(requests[0].timeout, timeout); + let bids = requests[0].bids; + assert(bids); + assert.equal(bids.length, 1); + assert.equal(bids[0].bidId, bidId); + assert.equal(bids[0].bidder, bidderCode); + assert.equal(bids[0].transactionId, tId); + assert.equal(bids[0].sizes.length, 1); + assert.equal(bids[0].sizes[0][0], 300); + assert.equal(bids[0].sizes[0][1], 250); + expect(requests[0]).to.not.have.property('doneCbCallCount'); + expect(requests[0]).to.not.have.property('auctionId'); + }); + it('should add results to the bid with response ', function () { + let auctionId = '345.345.345.345'; + emitEvent('AUCTION_INIT', auctionInit, auctionId); + emitEvent('BID_REQUESTED', bidRequested, auctionId); + emitEvent('BID_RESPONSE', bidResponse, auctionId); + + let auctionData = sovrnAnalyticsAdapter.getAuctions(); + let currentAuction = auctionData[auctionId]; + let returnedBid = currentAuction.auction.requests[0].bids[0]; + assert.equal(returnedBid.bidId, bidId); + assert.equal(returnedBid.bidder, bidderCode); + assert.equal(returnedBid.transactionId, tId); + assert.equal(returnedBid.sizes.length, 1); + assert.equal(returnedBid.sizes[0][0], 300); + assert.equal(returnedBid.sizes[0][1], 250); + assert.equal(returnedBid.adserverTargeting.hb_adid, '3870e27a5752fb'); + assert.equal(returnedBid.adserverTargeting.hb_bidder, bidderCode); + assert.equal(returnedBid.adserverTargeting.hb_pb, '0.85'); + assert.equal(returnedBid.cpm, 0.8584999918937682); + }); + it('should add new unsynced bid if no request exists for response ', function () { + let auctionId = '456.456.456.456'; + emitEvent('AUCTION_INIT', auctionInit, auctionId); + emitEvent('BID_REQUESTED', bidRequested, auctionId); + emitEvent('BID_RESPONSE', bidResponseNoMatchingRequest, auctionId); + + let auctionData = sovrnAnalyticsAdapter.getAuctions(); + let currentAuction = auctionData[auctionId]; + let requests = currentAuction.auction.requests; + assert(requests); + assert.equal(requests.length, 1); + let bidRequest = requests[0].bids[0]; + expect(bidRequest).to.not.have.property('adserverTargeting'); + expect(bidRequest).to.not.have.property('cpm'); + expect(currentAuction.auction.unsynced[0]).to.deep.equal(bidResponseNoMatchingRequest); + }); + it('should adjust the bid ', function () { + let auctionId = '567.567.567.567'; + emitEvent('AUCTION_INIT', auctionInit, auctionId); + emitEvent('BID_REQUESTED', bidRequested, auctionId); + emitEvent('BID_ADJUSTMENT', bidResponse, auctionId); + emitEvent('BID_RESPONSE', bidAdjustment, auctionId); + + let auctionData = sovrnAnalyticsAdapter.getAuctions(); + let currentAuction = auctionData[auctionId]; + let returnedBid = currentAuction.auction.requests[0].bids[0]; + assert.equal(returnedBid.cpm, 0.8); + assert.equal(returnedBid.originalValues.cpm, 0.8584999918937682); + }); + }); + describe('auction data send ', function() { + let expectedPostBody = { + sovrnId: 123, + auctionId: '678.678.678.678', + payload: 'auction', + priceGranularity: 'medium', + }; + let expectedRequests = { + bidderCode: 'sovrn', + bidderRequestId: '123bri', + timeout: 3000 + }; + let expectedBids = { + adUnitCode: 'div', + bidId: 'bidid', + bidder: 'sovrn', + bidderRequestId: '10340af0c7dc72', + transactionId: '7aafa3ee-a80a-46d7-a4a0-cbcba463d97a', + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '3870e27a5752fb', + mediaType: 'banner', + source: 'client', + cpm: 0.8584999918937682, + creativeId: 'cridprebidrtb', + dealId: null, + currency: 'USD', + netRevenue: true, + ttl: 60000, + timeToRespond: 50, + size: '300x250', + status: 'rendered', + isAuctionWinner: true + }; + let expectedAdServerTargeting = { + hb_bidder: 'sovrn', + hb_adid: '3870e27a5752fb', + hb_pb: '0.85' + }; + beforeEach(() => { + sovrnAnalyticsAdapter.enableAnalytics({ + provider: 'sovrn', + options: { + sovrnId: 123 + } + }); + sinon.spy(sovrnAnalyticsAdapter, 'track'); + }); + afterEach(() => { + sovrnAnalyticsAdapter.disableAnalytics(); + sovrnAnalyticsAdapter.track.restore(); + }); + it('should send auction data ', function () { + let auctionId = '678.678.678.678'; + emitEvent('AUCTION_INIT', auctionInit, auctionId); + emitEvent('BID_REQUESTED', bidRequested, auctionId); + emitEvent('BID_RESPONSE', bidResponse, auctionId); + emitEvent('AUCTION_END', {}, auctionId); + let requestBody = JSON.parse(requests[0].requestBody); + let requestsFromRequestBody = requestBody.requests[0]; + let bidsFromRequests = requestsFromRequestBody.bids[0]; + expect(requestBody).to.deep.include(expectedPostBody); + expect(requestBody.timeouts).to.deep.equal({buffer: 400, bidder: 3000}); + expect(requestsFromRequestBody).to.deep.include(expectedRequests); + expect(bidsFromRequests).to.deep.include(expectedBids); + expect(bidsFromRequests.adserverTargeting).to.deep.include(expectedAdServerTargeting); + }); + }); + describe('bid won data send ', function() { + let auctionId = '789.789.789.789'; + let creativeId = 'cridprebidrtb'; + let requestId = 'requestId69'; + let bidWonEvent = { + ad: 'html', + adId: 'adId', + adUnitCode: adUnitCode, + auctionId: auctionId, + bidder: bidderCode, + bidderCode: bidderCode, + cpm: 1.01, + creativeId: creativeId, + currency: 'USD', + height: 250, + mediaType: 'banner', + requestId: requestId, + size: '300x250', + source: 'client', + status: 'rendered', + statusMessage: 'Bid available', + timeToRespond: 421, + ttl: 60, + width: 300 + }; + let expectedBidWonBody = { + sovrnId: 123, + payload: 'winner' + }; + let expectedWinningBid = { + bidderCode: bidderCode, + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: 'adId', + mediaType: 'banner', + source: 'client', + requestId: requestId, + cpm: 1.01, + creativeId: creativeId, + currency: 'USD', + ttl: 60, + auctionId: auctionId, + bidder: bidderCode, + adUnitCode: adUnitCode, + timeToRespond: 421, + size: '300x250', + }; + beforeEach(() => { + sovrnAnalyticsAdapter.enableAnalytics({ + provider: 'sovrn', + options: { + sovrnId: 123 + } + }); + sinon.spy(sovrnAnalyticsAdapter, 'track'); + }); + afterEach(() => { + sovrnAnalyticsAdapter.disableAnalytics(); + sovrnAnalyticsAdapter.track.restore(); + }); + it('should send bid won data ', function () { + emitEvent('AUCTION_INIT', auctionInit, auctionId); + emitEvent('BID_WON', bidWonEvent, auctionId); + let requestBody = JSON.parse(requests[0].requestBody); + expect(requestBody).to.deep.include(expectedBidWonBody); + expect(requestBody.winningBid).to.deep.include(expectedWinningBid); + }); + }); + describe('Error Tracking', function() { + beforeEach(() => { + sovrnAnalyticsAdapter.enableAnalytics({ + provider: 'sovrn', + options: { + sovrnId: 123 + } + }); + sinon.spy(sovrnAnalyticsAdapter, 'track'); + }); + afterEach(() => { + sovrnAnalyticsAdapter.disableAnalytics() + sovrnAnalyticsAdapter.track.restore() + }); + it('should send an error message when a bid is received for a closed auction', function() { + let auctionId = '678.678.678.678'; + emitEvent('AUCTION_INIT', auctionInit, auctionId) + emitEvent('BID_REQUESTED', bidRequested, auctionId) + emitEvent('AUCTION_END', {}, auctionId) + requests[0].respond(200) + emitEvent('BID_RESPONSE', bidResponse, auctionId) + let requestBody = JSON.parse(requests[1].requestBody) + expect(requestBody.payload).to.equal('error') + expect(requestBody.message).to.include('Event Received after Auction Close Auction Id') + }) + }) +}) From f1aeb85671b527e654ace19ee559872fdeeb2576 Mon Sep 17 00:00:00 2001 From: Michael Kuryshev Date: Thu, 25 Apr 2019 15:31:26 +0200 Subject: [PATCH 1185/1594] Update VIS.X bid adapter (#3777) * update VIS.X bid adapter to support identical uids in the parameters * added wrapperType and wrapperVersion parameters in the ad request for VIS.X bid adapter * added second iteration of the response processing to ignore requested sizes in VIS.X bid adapter --- modules/visxBidAdapter.js | 76 ++++++- test/spec/modules/visxBidAdapter_spec.js | 272 +++++++++++++++++++++-- 2 files changed, 312 insertions(+), 36 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 574061b6ce3..740c08111bc 100755 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -25,6 +25,8 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { const auids = []; const bidsMap = {}; + const slotsMapByUid = {}; + const sizeMap = {}; const bids = validBidRequests || []; const currency = config.getConfig(`currency.bidderCurrencyDefault.${BIDDER_CODE}`) || @@ -33,21 +35,46 @@ export const spec = { let reqId; bids.forEach(bid => { - if (!bidsMap[bid.params.uid]) { - bidsMap[bid.params.uid] = [bid]; - auids.push(bid.params.uid); + reqId = bid.bidderRequestId; + const {params: {uid}, adUnitCode} = bid; + auids.push(uid); + const sizesId = utils.parseSizesInput(bid.sizes); + + if (!slotsMapByUid[uid]) { + slotsMapByUid[uid] = {}; + } + const slotsMap = slotsMapByUid[uid]; + if (!slotsMap[adUnitCode]) { + slotsMap[adUnitCode] = {adUnitCode, bids: [bid], parents: []}; } else { - bidsMap[bid.params.uid].push(bid); + slotsMap[adUnitCode].bids.push(bid); } - reqId = bid.bidderRequestId; + 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 = { u: utils.getTopWindowUrl(), pt: 'net', auids: auids.join(','), + sizes: utils.getKeys(sizeMap).join(','), r: reqId, cur: currency, + wrapperType: 'Prebid_js', + wrapperVersion: '$prebid.version$' }; if (bidderRequest && bidderRequest.gdprConsent) { @@ -69,6 +96,7 @@ export const spec = { interpretResponse: function(serverResponse, bidRequest) { serverResponse = serverResponse && serverResponse.body; const bidResponses = []; + const bidsWithoutSizeMatching = []; const bidsMap = bidRequest.bidsMap; const currency = bidRequest.data.cur; @@ -81,7 +109,10 @@ 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) utils.logError(errorMessage); @@ -117,7 +148,7 @@ 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); @@ -125,9 +156,14 @@ function _addBidResponse(serverBid, bidsMap, currency, bidResponses) { else { const awaitingBids = bidsMap[serverBid.auid]; if (awaitingBids) { - awaitingBids.forEach(bid => { - const bidResponse = { + 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(); + bidResponses.push({ requestId: bid.bidId, + bidderCode: spec.code, cpm: serverBid.price, width: serverBid.w, height: serverBid.h, @@ -137,9 +173,25 @@ function _addBidResponse(serverBid, bidsMap, currency, bidResponses) { ttl: TIME_TO_LIVE, ad: serverBid.adm, dealId: serverBid.dealid - }; - 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 (!utils.getKeys(parent).length) { + delete bidsMap[uid]; + } + } + }); + } + } else { + bidsWithoutSizeMatching && bidsWithoutSizeMatching.push(serverBid); + } } else { errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; } diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 93dbe5626c2..aa9b2b553ed 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -58,7 +58,7 @@ describe('VisxAdapter', function () { 'uid': '903535' }, 'adUnitCode': 'adunit-code-2', - 'sizes': [[728, 90]], + 'sizes': [[728, 90], [300, 250]], 'bidId': '3150ccb55da321', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', @@ -83,17 +83,19 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('u').that.is.a('string'); 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'); }); - it('auids must not be duplicated', function () { + it('sizes must not be duplicated', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('auids', '903535,903535,903536'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); expect(payload).to.have.property('cur', 'EUR'); }); @@ -105,12 +107,12 @@ describe('VisxAdapter', function () { expect(payload).to.be.an('object'); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('auids', '903535,903535,903536'); + 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); @@ -118,7 +120,8 @@ describe('VisxAdapter', function () { expect(payload).to.be.an('object'); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('auids', '903535,903535,903536'); + 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; @@ -131,7 +134,8 @@ describe('VisxAdapter', function () { expect(payload).to.be.an('object'); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('auids', '903535,903535,903536'); + 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; @@ -145,7 +149,8 @@ describe('VisxAdapter', function () { expect(payload).to.be.an('object'); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('auids', '903535,903535,903536'); + expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); expect(payload).to.have.property('cur', 'JPY'); getConfigStub.restore(); @@ -159,7 +164,8 @@ describe('VisxAdapter', function () { expect(payload).to.be.an('object'); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903536'); + expect(payload).to.have.property('auids', '903535,903535,903536'); + 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(); @@ -193,9 +199,10 @@ describe('VisxAdapter', function () { describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903536, 'h': 90, 'w': 728}], 'seat': '1'}, - {'bid': [{'price': 0, 'auid': 903536, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0, 'adm': '
    test content 4
    ', 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903536, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 3
    ', 'auid': 903535, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 903537, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
    test content 5
    ', 'h': 250, 'w': 300}], 'seat': '1'}, undefined, {'bid': [], 'seat': '1'}, {'seat': '1'}, @@ -225,6 +232,7 @@ describe('VisxAdapter', function () { 'width': 300, 'height': 250, 'ad': '
    test content 1
    ', + 'bidderCode': 'visx', 'currency': 'EUR', 'netRevenue': true, 'ttl': 360, @@ -281,37 +289,40 @@ describe('VisxAdapter', function () { 'width': 300, 'height': 250, 'ad': '
    test content 1
    ', + 'bidderCode': 'visx', 'currency': 'EUR', 'netRevenue': true, 'ttl': 360, }, { - 'requestId': '5703af74d0472a', - 'cpm': 1.15, - 'creativeId': 903535, + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 903536, 'dealId': undefined, 'width': 300, - 'height': 250, - 'ad': '
    test content 1
    ', + 'height': 600, + 'ad': '
    test content 2
    ', + 'bidderCode': 'visx', 'currency': 'EUR', 'netRevenue': true, 'ttl': 360, }, { - 'requestId': '4dff80cc4ee346', - 'cpm': 0.5, - 'creativeId': 903536, + 'requestId': '5703af74d0472a', + 'cpm': 0.15, + 'creativeId': 903535, 'dealId': undefined, 'width': 728, 'height': 90, - 'ad': '
    test content 2
    ', + 'ad': '
    test content 3
    ', + 'bidderCode': 'visx', 'currency': 'EUR', 'netRevenue': true, 'ttl': 360, } ]; - const result = spec.interpretResponse({'body': {'seatbid': [responses[0], responses[1]]}}, request); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(0, 3)}}, request); expect(result).to.deep.equal(expectedResponse); }); @@ -340,6 +351,7 @@ describe('VisxAdapter', function () { 'width': 300, 'height': 250, 'ad': '
    test content 1
    ', + 'bidderCode': 'visx', 'currency': 'JPY', 'netRevenue': true, 'ttl': 360, @@ -356,7 +368,7 @@ describe('VisxAdapter', function () { { 'bidder': 'visx', 'params': { - 'uid': '903536' + 'uid': '903537' }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -388,8 +400,220 @@ describe('VisxAdapter', function () { } ]; const request = spec.buildRequests(bidRequests); - const result = spec.interpretResponse({'body': {'seatbid': responses.slice(2)}}, request); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(3)}}, request); expect(result.length).to.equal(0); }); + + it('complicated case', function () { + const fullResponse = [ + {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903536, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 3
    ', 'auid': 903535, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 4
    ', 'auid': 903535, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 5
    ', 'auid': 903536, 'h': 600, 'w': 350}], 'seat': '1'}, + ]; + const bidRequests = [ + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '2164be6358b9', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '326bde7fbf69', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903536' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4e111f1b66e4', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '26d6f897b516', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903536' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '1751cd90161', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '2164be6358b9', + 'cpm': 1.15, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
    test content 1
    ', + 'bidderCode': 'visx', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4e111f1b66e4', + 'cpm': 0.5, + 'creativeId': 903536, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'ad': '
    test content 2
    ', + 'bidderCode': 'visx', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '26d6f897b516', + 'cpm': 0.15, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
    test content 3
    ', + 'bidderCode': 'visx', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '326bde7fbf69', + 'cpm': 0.15, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'ad': '
    test content 4
    ', + 'bidderCode': 'visx', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '1751cd90161', + 'cpm': 0.5, + 'creativeId': 903536, + 'dealId': undefined, + 'width': 350, + 'height': 600, + 'ad': '
    test content 5
    ', + 'bidderCode': 'visx', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('dublicate uids and sizes in one slot', function () { + const fullResponse = [ + {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, + ]; + const bidRequests = [ + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '5126e301f4be', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '57b2ebe70e16', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + }, + { + 'bidder': 'visx', + 'params': { + 'uid': '903535' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '225fcd44b18c', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '5126e301f4be', + 'cpm': 1.15, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
    test content 1
    ', + 'bidderCode': 'visx', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '57b2ebe70e16', + 'cpm': 0.5, + 'creativeId': 903535, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
    test content 2
    ', + 'bidderCode': 'visx', + 'currency': 'EUR', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + expect(result).to.deep.equal(expectedResponse); + }); }); }); From 16b46ae3ff5e6c73356d0d7aaec86357863d5f5b Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Fri, 26 Apr 2019 06:58:12 -0700 Subject: [PATCH 1186/1594] Debug Unit Test Issue in CircleCI (#3754) * add skip to last test * change skip to describe block * updated tests to be more stable by removing prebid global calls in tests --- test/spec/modules/userId_spec.js | 184 +++++++++++++------------------ 1 file changed, 79 insertions(+), 105 deletions(-) diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 6acab4d2b6c..c7901106538 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -1,16 +1,12 @@ import { init, syncDelay, - submodules, pubCommonIdSubmodule, unifiedIdSubmodule, requestBidsHook } from 'modules/userId'; import {config} from 'src/config'; import * as utils from 'src/utils'; -import * as auctionModule from 'src/auction'; -import {getAdUnits} from 'test/fixtures/fixtures'; -import {registerBidder} from 'src/adapters/bidderFactory'; let assert = require('chai').assert; let expect = require('chai').expect; @@ -22,6 +18,15 @@ describe('User ID', function() { return { name: name, storage: { name: key, type: type, expires: expires } } } + function createAdUnit(code = 'adUnit-code') { + return { + code, + mediaTypes: {banner: {}, native: {}}, + sizes: [[300, 200], [300, 600]], + bids: [{bidder: 'sampleBidder', params: {placementId: 'banner-only-bidder'}}] + }; + } + before(function() { utils.setCookie('_pubcid_optout', '', EXPIRED_COOKIE_DATE); }); @@ -43,8 +48,8 @@ describe('User ID', function() { }); it('Check same cookie behavior', function () { - let adUnits1 = getAdUnits(); - let adUnits2 = getAdUnits(); + let adUnits1 = [createAdUnit()]; + let adUnits2 = [createAdUnit()]; let innerAdUnits1; let innerAdUnits2; @@ -54,23 +59,23 @@ describe('User ID', function() { init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); - requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); + requestBidsHook(config => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); pubcid = utils.getCookie('pubcid'); // cookies is created after requestbidHook - innerAdUnits1.forEach((unit) => { - unit.bids.forEach((bid) => { + innerAdUnits1.forEach(unit => { + unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.pubcid'); expect(bid.userId.pubcid).to.equal(pubcid); }); }); - requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); + requestBidsHook(config => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); assert.deepEqual(innerAdUnits1, innerAdUnits2); }); it('Check different cookies', function () { - let adUnits1 = getAdUnits(); - let adUnits2 = getAdUnits(); + let adUnits1 = [createAdUnit()]; + let adUnits2 = [createAdUnit()]; let innerAdUnits1; let innerAdUnits2; let pubcid1; @@ -106,7 +111,7 @@ describe('User ID', function() { }); it('Check new cookie', function () { - let adUnits = getAdUnits(); + let adUnits = [createAdUnit()]; let innerAdUnits; init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); @@ -254,66 +259,17 @@ describe('User ID', function() { }); }); - describe('Invoking requestBid', function () { - let storageResetCount = 0; - let createAuctionStub; + describe('Request bids hook appends userId to bid objs in adapters', function() { let adUnits; - let adUnitCodes; - let sampleSpec = { - code: 'sampleBidder', - isBidRequestValid: () => {}, - buildRequest: (reqs) => {}, - interpretResponse: () => {}, - getUserSyncs: () => {} - }; - - beforeEach(function () { - // simulate existing browser cookie values - utils.setCookie('pubcid', `testpubcid${storageResetCount}`, (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('unifiedid', JSON.stringify({ - 'TDID': `testunifiedid${storageResetCount}` - }), (new Date(Date.now() + 5000).toUTCString())); - - // simulate existing browser local storage values - localStorage.setItem('unifiedid_alt', JSON.stringify({ - 'TDID': `testunifiedid_alt${storageResetCount}` - })); - localStorage.setItem('unifiedid_alt_exp', ''); - - adUnits = [{ - code: 'adUnit-code', - mediaTypes: { - banner: {}, - native: {}, - }, - sizes: [[300, 200], [300, 600]], - bids: [ - {bidder: 'sampleBidder', params: {placementId: 'banner-only-bidder'}} - ] - }]; - adUnitCodes = ['adUnit-code']; - let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 1999}); - createAuctionStub = sinon.stub(auctionModule, 'newAuction'); - createAuctionStub.returns(auction); - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); - - registerBidder(sampleSpec); + beforeEach(function() { + adUnits = [createAdUnit()]; }); - afterEach(function () { - storageResetCount++; - - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); - localStorage.removeItem('unifiedid_alt'); - localStorage.removeItem('unifiedid_alt_exp'); - auctionModule.newAuction.restore(); - $$PREBID_GLOBAL$$.requestBids.removeAll(); - config.resetConfig(); - }); + it('test hook from pubcommonid cookie', function(done) { + utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 100000).toUTCString())); - it('test hook from pubcommonid cookie', function() { + init(config, [pubCommonIdSubmodule]); config.setConfig({ usersync: { syncDelay: 0, @@ -321,17 +277,20 @@ describe('User ID', function() { } }); - $$PREBID_GLOBAL$$.requestBids({adUnits}); - - adUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('userId.pubcid'); - expect(bid.userId.pubcid).to.equal(`testpubcid${storageResetCount}`); + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal('testpubcid'); + }); }); - }); + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); }); - it('test hook from pubcommonid config value object', function() { + it('test hook from pubcommonid config value object', function(done) { + init(config, [pubCommonIdSubmodule]); config.setConfig({ usersync: { syncDelay: 0, @@ -341,34 +300,47 @@ describe('User ID', function() { }]} }); - $$PREBID_GLOBAL$$.requestBids({adUnits}); - - adUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('userId.pubcidvalue'); - expect(bid.userId.pubcidvalue).to.equal('testpubcidvalue'); + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.pubcidvalue'); + expect(bid.userId.pubcidvalue).to.equal('testpubcidvalue'); + }); }); - }); + done(); + }, {adUnits}); }); - it('test hook from pubcommonid html5', function() { + it('test hook from pubcommonid html5', function(done) { + // simulate existing browser local storage values + localStorage.setItem('unifiedid_alt', JSON.stringify({'TDID': 'testunifiedid_alt'})); + localStorage.setItem('unifiedid_alt_exp', ''); + + init(config, [unifiedIdSubmodule]); config.setConfig({ usersync: { syncDelay: 0, userIds: [createStorageConfig('unifiedId', 'unifiedid_alt', 'html5')]} }); - $$PREBID_GLOBAL$$.requestBids({adUnits}); - - adUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('userId.tdid'); - expect(bid.userId.tdid).to.equal(`testunifiedid_alt${storageResetCount}`); + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.tdid'); + expect(bid.userId.tdid).to.equal('testunifiedid_alt'); + }); }); - }); + localStorage.removeItem('unifiedid_alt'); + localStorage.removeItem('unifiedid_alt_exp'); + done(); + }, {adUnits}); }); - it('test hook when both pubCommonId and unifiedId have data to pass', function() { + it('test hook when both pubCommonId and unifiedId have data to pass', function(done) { + utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); + + init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); config.setConfig({ usersync: { syncDelay: 0, @@ -378,19 +350,21 @@ describe('User ID', function() { ]} }); - $$PREBID_GLOBAL$$.requestBids({adUnits}); - - 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${storageResetCount}`); - - // 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(`testunifiedid${storageResetCount}`); + 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('testunifiedid'); + }); }); - }); + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); }); - }); + }) }); From 6ca459d620cf4937dd419718742be0dba0ea78d7 Mon Sep 17 00:00:00 2001 From: Michael Wilson Date: Mon, 29 Apr 2019 10:05:19 -0600 Subject: [PATCH 1187/1594] fixed gumgums example params in readme (#3779) --- modules/gumgumBidAdapter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/gumgumBidAdapter.md b/modules/gumgumBidAdapter.md index 57616a90ac2..3abc8a246c9 100644 --- a/modules/gumgumBidAdapter.md +++ b/modules/gumgumBidAdapter.md @@ -21,7 +21,7 @@ var adUnits = [ bidder: 'gumgum', params: { inSlot: '15901', // GumGum Slot ID given to the client, - bidFloor: 0.03 // CPM bid floor + bidfloor: 0.03 // CPM bid floor } } ] @@ -33,7 +33,7 @@ var adUnits = [ bidder: 'gumgum', params: { inScreen: 'dc9d6be1', // GumGum Zone ID given to the client - bidFloor: 0.03 // CPM bid floor + bidfloor: 0.03 // CPM bid floor } } ] From c6069f1f55efa05755f05132d7e3cd6b3610e975 Mon Sep 17 00:00:00 2001 From: ReklamStoreIT <48473631+ReklamStoreIT@users.noreply.github.com> Date: Mon, 29 Apr 2019 20:05:49 +0300 Subject: [PATCH 1188/1594] ReklamStore Adapter Update (#3784) * ReklamStore Bid Adapter ReklamStore Bid Adapter * Added unit test for user sync Added unit test for user sync * Update bid adapter Update bid adapter * Reklamstore Adapter Update Reklamstore Adapter Update --- modules/reklamstoreBidAdapter.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/reklamstoreBidAdapter.js b/modules/reklamstoreBidAdapter.js index be484822860..49f08ab0473 100644 --- a/modules/reklamstoreBidAdapter.js +++ b/modules/reklamstoreBidAdapter.js @@ -36,7 +36,6 @@ export const spec = { regionId: bid.params.regionId, dt: getDeviceType(), os: getOS(), - dbg: 1, ref: extractDomain(url), _: (new Date().getTime()), mobile_web: 1 @@ -65,7 +64,7 @@ export const spec = { height: bidResponse.h, creativeId: bidResponse.adId || 1, currency: CURRENCY, - netRevenue: false, + netRevenue: true, ttl: TIME_TO_LIVE, ad: bidResponse.ad }); From f350bbab99a29d4e335e4ab45b945c5393904448 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Mon, 29 Apr 2019 10:06:42 -0700 Subject: [PATCH 1189/1594] Update PubMatic banner and video examples to use adSlot without (#3786) appended size --- modules/pubmaticBidAdapter.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 0f92e1756a5..16a3b203e20 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -25,7 +25,7 @@ var adUnits = [ bidder: 'pubmatic', params: { publisherId: '156209', // required - adSlot: 'pubmatic_test2@300x250', // required + adSlot: 'pubmatic_test2', // required pmzoneid: 'zone1, zone11', // optional lat: '40.712775', // optional lon: '-74.005973', // optional @@ -33,7 +33,7 @@ var adUnits = [ kadpageurl: 'www.test.com', // optional gender: 'M', // optional kadfloor: '0.50', // optional - currency: 'AUD' // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) + currency: 'AUD', // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) dctr: 'key1=123|key2=345', // optional (Value configured only in the 1st adunit will be passed on. < br/> Values if present in subsequent adunits, will be ignored.) bcat: ['IAB1-5', 'IAB1-7'] // Optional: Blocked IAB Categories. (Values from all slots will be combined and only unique values will be passed. An array of strings only. Each category should be a string of a length of more than 3 characters.) } @@ -55,8 +55,8 @@ var adVideoAdUnits = [ bids: [{ bidder: 'pubmatic', params: { - publisherId: '351', // required - adSlot: '1363568@300x250', // required + publisherId: '156209', // required + adSlot: 'pubmatic_video1', // required video: { mimes: ['video/mp4','video/x-flv'], // required skippable: true, // optional From e31b9d8887af8ea73cce3e6a8e6dcb359497ca28 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Mon, 29 Apr 2019 10:11:43 -0700 Subject: [PATCH 1190/1594] Conversant Adapter - support User ID module (#3533) * added universal id support to bid adapter * added unit test for universal id support * added universal id support to bid adapter * added unit test for universal id support * renamed universalId to userId * removed old code from merge mistake * test for unit test --- modules/conversantBidAdapter.js | 4 +++- test/spec/modules/conversantBidAdapter_spec.js | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index cb0661c4417..90865493d8d 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -99,7 +99,9 @@ export const spec = { imp.banner = banner; } - if (bid.crumbs && bid.crumbs.pubcid) { + if (bid.userId && bid.userId.pubcid) { + pubcid = bid.userId.pubcid; + } else if (bid.crumbs && bid.crumbs.pubcid) { pubcid = bid.crumbs.pubcid; } diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 34991252fa8..bfe3c6e8fa1 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -375,6 +375,19 @@ describe('Conversant adapter tests', function() { expect(payload).to.have.deep.nested.property('user.ext.fpc', 12345); }); + it('Verify User ID publisher commond id support', function() { + // clone bidRequests + let requests = utils.deepClone(bidRequests) + + // add pubcid to every entry + requests.forEach((unit) => { + Object.assign(unit, {userId: {pubcid: 67890}}); + }); + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.have.deep.nested.property('user.ext.fpc', 67890); + }); + it('Verify GDPR bid request', function() { // add gdpr info const bidRequest = { From d6eeb3157f2adf58ad41c1dc357f823706612232 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Tue, 30 Apr 2019 05:55:37 -0400 Subject: [PATCH 1191/1594] kargo sizes and full bid request object (#3771) --- modules/kargoBidAdapter.js | 10 ++++- test/spec/modules/kargoBidAdapter_spec.js | 52 +++++++++++++++++++++-- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index ecd26f49509..2c602186547 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -17,7 +17,11 @@ export const spec = { const currencyObj = config.getConfig('currency'); const currency = (currencyObj && currencyObj.adServerCurrency) || 'USD'; const bidIds = {}; - utils._each(validBidRequests, bid => bidIds[bid.bidId] = bid.params.placementId); + const bidSizes = {}; + utils._each(validBidRequests, bid => { + bidIds[bid.bidId] = bid.params.placementId; + bidSizes[bid.bidId] = bid.sizes; + }); const transformedParams = Object.assign({}, { timeout: bidderRequest.timeout, currency: currency, @@ -27,7 +31,9 @@ export const spec = { floor: 0, ceil: 20 }, - bidIDs: bidIds + bidIDs: bidIds, + bidSizes: bidSizes, + prebidRawBidRequests: validBidRequests }, spec._getAllMetadata()); const encodedParams = encodeURIComponent(JSON.stringify(transformedParams)); return Object.assign({}, bidderRequest, { diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 28cb386242f..5d53a4e9c95 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -57,19 +57,22 @@ describe('kargo adapter tests', function () { params: { placementId: 'foo' }, - bidId: 1 + bidId: 1, + sizes: [[320, 50], [300, 250], [300, 600]] }, { params: { placementId: 'bar' }, - bidId: 2 + bidId: 2, + sizes: [[320, 50], [300, 250], [300, 600]] }, { params: { placementId: 'bar' }, - bidId: 3 + bidId: 3, + sizes: [[320, 50], [300, 250], [300, 600]] } ]; }); @@ -185,6 +188,14 @@ describe('kargo adapter tests', function () { setCookie('krg_crb', getInvalidKrgCrbType3OldStyle()); } + function getInvalidKrgCrbType4OldStyle() { + return '%7B%22v%22%3A%22bnVsbA%3D%3D%22%7D'; + } + + function initializeInvalidKrgCrbType4Cookie() { + setCookie('krg_crb', getInvalidKrgCrbType4OldStyle()); + } + function getEmptyKrgCrb() { return 'eyJleHBpcmVUaW1lIjoxNDk3NDQ5MzgyNjY4LCJsYXN0U3luY2VkQXQiOjE0OTczNjI5NzkwMTJ9'; } @@ -216,6 +227,11 @@ describe('kargo adapter tests', function () { 2: 'bar', 3: 'bar' }, + bidSizes: { + 1: [[320, 50], [300, 250], [300, 600]], + 2: [[320, 50], [300, 250], [300, 600]], + 3: [[320, 50], [300, 250], [300, 600]] + }, userIDs: { kargoID: '5f108831-302d-11e7-bf6b-4595acd3bf6c', clientID: '2410d8f2-c111-4811-88a5-7b5e190e475f', @@ -241,6 +257,29 @@ describe('kargo adapter tests', function () { ] }, pageURL: window.location.href, + prebidRawBidRequests: [ + { + bidId: 1, + params: { + placementId: 'foo' + }, + sizes: [[320, 50], [300, 250], [300, 600]] + }, + { + bidId: 2, + params: { + placementId: 'bar' + }, + sizes: [[320, 50], [300, 250], [300, 600]] + }, + { + bidId: 3, + params: { + placementId: 'bar' + }, + sizes: [[320, 50], [300, 250], [300, 600]] + } + ], rawCRB: expectedRawCRBCookie, rawCRBLocalStorage: expectedRawCRB }; @@ -339,6 +378,13 @@ describe('kargo adapter tests', function () { testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType3OldStyle())); }); + it('handles broken Kargo CRBs where inner JSON is falsey', function() { + initializeKruxUser(); + initializeKruxSegments(); + initializeInvalidKrgCrbType4Cookie(); + testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType4OldStyle())); + }); + it('handles a non-existant currency object on the config', function() { simulateNoCurrencyObject(); initializeKruxUser(); From 4155553988101b9ad17ef6668599fc71be14ae3c Mon Sep 17 00:00:00 2001 From: Eric Nolte Date: Tue, 30 Apr 2019 05:59:59 -0400 Subject: [PATCH 1192/1594] fix ref error on yieldmo adapter (#3776) * fix ref error on yieldmo adapter * Delete yarn.lock --- modules/yieldmoBidAdapter.js | 2 +- test/spec/modules/yieldmoBidAdapter_spec.js | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index d904791d29a..b2d13e88c80 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -47,7 +47,7 @@ export const spec = { if (userId) { const pubcid = userId.pubcid; serverRequest.pubcid = pubcid; - } else { + } else if (request.crumbs) { serverRequest.pubcid = request.crumbs.pubcid; } }); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 80a9265a5c2..12dd87e1517 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { spec } from 'modules/yieldmoBidAdapter'; -import {newBidder} from 'src/adapters/bidderFactory'; +import { newBidder } from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; describe('YieldmoAdapter', function () { @@ -50,6 +50,13 @@ describe('YieldmoAdapter', function () { expect(request.url).to.be.equal(ENDPOINT); }); + it('should not blow up if crumbs is undefined', function () { + let bidArray = [ + { ...bid, crumbs: undefined } + ] + expect(function () { spec.buildRequests(bidArray) }).not.to.throw() + }) + it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray).data.p; expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]]}]'); From 40a4ac6f516f8ecf667e529e5721b864778c452d Mon Sep 17 00:00:00 2001 From: bjorn-lw <32431346+bjorn-lw@users.noreply.github.com> Date: Tue, 30 Apr 2019 15:41:34 +0200 Subject: [PATCH 1193/1594] Detect ad blocker recovered requests + send dynamic parameters to adapter + minor fixes (#3749) * Livewrapped bid and analytics adapter * Fixed some tests for browser compatibility * Fixed some tests for browser compatibility * Changed analytics adapter code name * Fix double quote in debug message * modified how gdpr is being passed * Added support for Publisher Common ID Module * Corrections for ttr in analytics * ANalytics updates * Auction start time stamp changed * Detect recovered ad blocked requests Make it possible to pass dynamic parameters to adapter --- modules/livewrappedAnalyticsAdapter.js | 31 +++++++--- modules/livewrappedBidAdapter.js | 11 +++- .../livewrappedAnalyticsAdapter_spec.js | 55 +++++++++++++++++- .../modules/livewrappedBidAdapter_spec.js | 58 +++++++++++++++++++ 4 files changed, 143 insertions(+), 12 deletions(-) diff --git a/modules/livewrappedAnalyticsAdapter.js b/modules/livewrappedAnalyticsAdapter.js index 272ccadfbcf..ec0ddb6fd54 100644 --- a/modules/livewrappedAnalyticsAdapter.js +++ b/modules/livewrappedAnalyticsAdapter.js @@ -21,6 +21,7 @@ const cache = { let livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTYPE}), { track({eventType, args}) { + const time = utils.timestamp(); utils.logInfo('LIVEWRAPPED_EVENT:', [eventType, args]); switch (eventType) { @@ -30,16 +31,18 @@ let livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTYPE break; case CONSTANTS.EVENTS.BID_REQUESTED: utils.logInfo('LIVEWRAPPED_BID_REQUESTED:', args); + cache.auctions[args.auctionId].timeStamp = args.start; args.bids.forEach(function(bidRequest) { - cache.auctions[args.auctionId].timeStamp = args.start; cache.auctions[args.auctionId].bids[bidRequest.bidId] = { bidder: bidRequest.bidder, adUnit: bidRequest.adUnitCode, isBid: false, won: false, timeout: false, - sendStatus: 0 + sendStatus: 0, + readyToSend: 0, + start: args.start } utils.logInfo(bidRequest); @@ -49,25 +52,30 @@ let livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTYPE case CONSTANTS.EVENTS.BID_RESPONSE: utils.logInfo('LIVEWRAPPED_BID_RESPONSE:', args); - let bidResponse = cache.auctions[args.auctionId].bids[args.adId]; + let bidResponse = cache.auctions[args.auctionId].bids[args.requestId]; bidResponse.isBid = args.getStatusCode() === CONSTANTS.STATUS.GOOD; bidResponse.width = args.width; bidResponse.height = args.height; bidResponse.cpm = args.cpm; bidResponse.ttr = args.timeToRespond; + bidResponse.readyToSend = 1; + if (!bidResponse.ttr) { + bidResponse.ttr = time - bidResponse.start; + } break; case CONSTANTS.EVENTS.BIDDER_DONE: utils.logInfo('LIVEWRAPPED_BIDDER_DONE:', args); args.bids.forEach(doneBid => { - let bid = cache.auctions[doneBid.auctionId].bids[doneBid.bidId]; + let bid = cache.auctions[doneBid.auctionId].bids[doneBid.bidId || doneBid.requestId]; if (!bid.ttr) { - bid.ttr = Date.now() - args.auctionStart; + bid.ttr = time - bid.start; } + bid.readyToSend = 1; }); break; case CONSTANTS.EVENTS.BID_WON: utils.logInfo('LIVEWRAPPED_BID_WON:', args); - let wonBid = cache.auctions[args.auctionId].bids[args.adId]; + let wonBid = cache.auctions[args.auctionId].bids[args.requestId]; wonBid.won = true; if (wonBid.sendStatus != 0) { livewrappedAnalyticsAdapter.sendEvents(); @@ -105,7 +113,8 @@ livewrappedAnalyticsAdapter.sendEvents = function() { requests: getSentRequests(), responses: getResponses(), wins: getWins(), - timeouts: getTimeouts() + timeouts: getTimeouts(), + rcv: getAdblockerRecovered() }; if (events.requests.length == 0 && @@ -118,6 +127,12 @@ livewrappedAnalyticsAdapter.sendEvents = function() { ajax(URL, undefined, JSON.stringify(events), {method: 'POST'}); } +function getAdblockerRecovered() { + try { + return utils.getWindowTop().I12C && utils.getWindowTop().I12C.Morph === 1; + } catch (e) {} +} + function getSentRequests() { var sentRequests = []; @@ -147,7 +162,7 @@ function getResponses() { Object.keys(cache.auctions[auctionId].bids).forEach(bidId => { let auction = cache.auctions[auctionId]; let bid = auction.bids[bidId]; - if (!(bid.sendStatus & RESPONSESENT) && !bid.timeout) { + if (bid.readyToSend && !(bid.sendStatus & RESPONSESENT) && !bid.timeout) { bid.sendStatus |= RESPONSESENT; responses.push({ diff --git a/modules/livewrappedBidAdapter.js b/modules/livewrappedBidAdapter.js index 69a89421a32..1ad18cb15eb 100644 --- a/modules/livewrappedBidAdapter.js +++ b/modules/livewrappedBidAdapter.js @@ -24,6 +24,7 @@ export const spec = { * seats: List of bidders and seats Optional. {"bidder name": ["seat 1", "seat 2"], ...} * deviceId: Device id if available Optional. * ifa: Advertising ID Optional. + * options Dynamic data Optional. Optional data to send into adapter. * * @param {BidRequest} bid The bid params to validate. * @return boolean True if this is a valid bid, and false otherwise. @@ -69,6 +70,7 @@ export const spec = { gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, gdprConsent: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined, cookieSupport: !utils.isSafariBrowser() && utils.cookiesAreEnabled(), + rcv: getAdblockerRecovered(), adRequests: [...adRequests] }; const payloadString = JSON.stringify(payload); @@ -178,7 +180,8 @@ function bidToAdRequest(bid) { callerAdUnitId: bid.params.adUnitName || bid.adUnitCode || bid.placementCode, bidId: bid.bidId, transactionId: bid.transactionId, - formats: bid.sizes.map(sizeToFormat) + formats: bid.sizes.map(sizeToFormat), + options: bid.params.options }; } @@ -189,4 +192,10 @@ function sizeToFormat(size) { } } +function getAdblockerRecovered() { + try { + return utils.getWindowTop().I12C && utils.getWindowTop().I12C.Morph === 1; + } catch (e) {} +} + registerBidder(spec); diff --git a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js index 60fc9bdc1ec..92c1c4d3ab3 100644 --- a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +++ b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js @@ -3,6 +3,7 @@ import CONSTANTS from 'src/constants.json'; import { config } from 'src/config'; let events = require('src/events'); +let utils = require('src/utils'); let adapterManager = require('src/adapterManager').default; const { @@ -27,6 +28,7 @@ const BID1 = { cpm: 1.1, timeToRespond: 200, bidId: '2ecff0db240757', + requestId: '2ecff0db240757', adId: '2ecff0db240757', auctionId: '25c6d7f5-699a-4bfc-87c9-996f915341fa', getStatusCode() { @@ -40,9 +42,20 @@ const BID2 = Object.assign({}, BID1, { cpm: 2.2, timeToRespond: 300, bidId: '3ecff0db240757', + requestId: '3ecff0db240757', adId: '3ecff0db240757', }); +const BID3 = { + bidId: '4ecff0db240757', + requestId: '4ecff0db240757', + adId: '4ecff0db240757', + auctionId: '25c6d7f5-699a-4bfc-87c9-996f915341fa', + getStatusCode() { + return CONSTANTS.STATUS.NO_BID; + } +}; + const MOCK = { AUCTION_INIT: { 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', @@ -61,6 +74,11 @@ const MOCK = { 'bidder': 'livewrapped', 'adUnitCode': 'box_d_1', 'bidId': '3ecff0db240757', + }, + { + 'bidder': 'livewrapped', + 'adUnitCode': 'box_d_2', + 'bidId': '4ecff0db240757', } ], 'start': 1519149562216 @@ -73,17 +91,20 @@ const MOCK = { }, BID_WON: [ Object.assign({}, BID1, { - 'status': 'rendered' + 'status': 'rendered', + 'requestId': '2ecff0db240757' }), Object.assign({}, BID2, { - 'status': 'rendered' + 'status': 'rendered', + 'requestId': '3ecff0db240757' }) ], BIDDER_DONE: { 'bidderCode': 'livewrapped', 'bids': [ BID1, - BID2 + BID2, + BID3 ] }, BID_TIMEOUT: [ @@ -106,6 +127,11 @@ const ANALYTICS_MESSAGE = { adUnit: 'box_d_1', bidder: 'livewrapped', timeStamp: 1519149562216 + }, + { + adUnit: 'box_d_2', + bidder: 'livewrapped', + timeStamp: 1519149562216 } ], responses: [ @@ -128,6 +154,13 @@ const ANALYTICS_MESSAGE = { cpm: 2.2, ttr: 300, IsBid: true + }, + { + timeStamp: 1519149562216, + adUnit: 'box_d_2', + bidder: 'livewrapped', + ttr: 200, + IsBid: false } ], timeouts: [], @@ -177,6 +210,7 @@ describe('Livewrapped analytics adapter', function () { xhr.onCreate = request => requests.push(request); sandbox.stub(events, 'getEvents').returns([]); + sandbox.stub(utils, 'timestamp').returns(1519149562416); clock = sandbox.useFakeTimers(1519767013781); }); @@ -206,6 +240,7 @@ describe('Livewrapped analytics adapter', function () { }); it('should build a batched message from prebid events', function () { + sandbox.stub(utils, 'getWindowTop').returns({}); performStandardAuction(); clock.tick(BID_WON_TIMEOUT + 1000); @@ -261,5 +296,19 @@ describe('Livewrapped analytics adapter', function () { expect(message.timeouts[0].bidder).to.equal('livewrapped'); expect(message.timeouts[0].adUnit).to.equal('panorama_d_1'); }); + + it('should detect adblocker recovered request', function () { + sandbox.stub(utils, 'getWindowTop').returns({ I12C: { Morph: 1 } }); + performStandardAuction(); + + clock.tick(BID_WON_TIMEOUT + 1000); + + expect(requests.length).to.equal(1); + let request = requests[0]; + + let message = JSON.parse(request.requestBody); + + expect(message.rcv).to.equal(true); + }); }); }); diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js index b12ff56c075..855eb2ee3f9 100644 --- a/test/spec/modules/livewrappedBidAdapter_spec.js +++ b/test/spec/modules/livewrappedBidAdapter_spec.js @@ -303,6 +303,64 @@ describe('Livewrapped adapter tests', function () { expect(data).to.deep.equal(expectedQuery); }); + it('should make a well-formed single request object with optional parameters', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + delete testbidRequest.bids[0].params.seats; + delete testbidRequest.bids[0].params.adUnitId; + testbidRequest.bids[0].params.options = {keyvalues: [{key: 'key', value: 'value'}]}; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + url: 'http://www.domain.com', + version: '1.1', + cookieSupport: true, + adRequests: [{ + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}], + options: {keyvalues: [{key: 'key', value: 'value'}]} + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + + it('should make a well-formed single request object with ad blocker revovered parameter', function() { + sandbox.stub(utils, 'getWindowTop').returns({ I12C: { Morph: 1 } }); + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + delete testbidRequest.bids[0].params.seats; + delete testbidRequest.bids[0].params.adUnitId; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + let expectedQuery = { + auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + publisherId: '26947112-2289-405D-88C1-A7340C57E63E', + url: 'http://www.domain.com', + version: '1.1', + cookieSupport: true, + rcv: true, + adRequests: [{ + callerAdUnitId: 'panorama_d_1', + bidId: '2ffb201a808da7', + transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D', + formats: [{width: 980, height: 240}, {width: 980, height: 120}] + }] + }; + + expect(data).to.deep.equal(expectedQuery); + }); + it('should pass gdpr true parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); From 8f5ea4c2efb047353dd0ddbbcc304fa88ddf92fd Mon Sep 17 00:00:00 2001 From: mefjush Date: Tue, 30 Apr 2019 16:02:33 +0200 Subject: [PATCH 1194/1594] Add support for bidderRequest.refererInfo in Adhese Adapter (#3725) * Add support for bidderRequest.refererInfo in Adhese Adapter. * Apply code review suggestions --- modules/adheseBidAdapter.js | 10 ++++++++-- test/spec/modules/adheseBidAdapter_spec.js | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/modules/adheseBidAdapter.js b/modules/adheseBidAdapter.js index daea17a2a5b..6ca8c8a6aa6 100644 --- a/modules/adheseBidAdapter.js +++ b/modules/adheseBidAdapter.js @@ -18,13 +18,15 @@ export const spec = { if (validBidRequests.length === 0) { return null; } + const { gdprConsent, refererInfo } = bidderRequest; const account = getAccount(validBidRequests); const targets = validBidRequests.map(bid => bid.params.data).reduce(mergeTargets, {}); - const gdprParams = (bidderRequest.gdprConsent && bidderRequest.gdprConsent.consentString) ? [ 'xt' + bidderRequest.gdprConsent.consentString ] : []; + const gdprParams = (gdprConsent && gdprConsent.consentString) ? [`xt${gdprConsent.consentString}`] : []; + const refererParams = (refererInfo && refererInfo.referer) ? [`xf${base64urlEncode(refererInfo.referer)}`] : []; const targetsParams = Object.keys(targets).map(targetCode => targetCode + targets[targetCode].join(';')); const slotsParams = validBidRequests.map(bid => 'sl' + bidToSlotName(bid)); - const params = [...slotsParams, ...targetsParams, ...gdprParams].map(s => '/' + s).join(''); + const params = [...slotsParams, ...targetsParams, ...gdprParams, ...refererParams].map(s => `/${s}`).join(''); const cacheBuster = '?t=' + new Date().getTime(); const uri = 'https://ads-' + account + '.adhese.com/json' + params + cacheBuster; @@ -166,4 +168,8 @@ function getAdDetails(ad) { return { creativeId: creativeId, dealId: dealId }; } +function base64urlEncode(s) { + return btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); +} + registerBidder(spec); diff --git a/test/spec/modules/adheseBidAdapter_spec.js b/test/spec/modules/adheseBidAdapter_spec.js index 68beedd4b35..348fb772319 100644 --- a/test/spec/modules/adheseBidAdapter_spec.js +++ b/test/spec/modules/adheseBidAdapter_spec.js @@ -64,6 +64,9 @@ describe('AdheseAdapter', function () { gdprConsent: { gdprApplies: true, consentString: 'CONSENT_STRING' + }, + refererInfo: { + referer: 'http://prebid.org/dev-docs/subjects?_d=1' } }; @@ -91,6 +94,12 @@ describe('AdheseAdapter', function () { expect(req.url).to.contain('/xtCONSENT_STRING'); }); + it('should include referer param in base64url format', function () { + let req = spec.buildRequests([ minimalBid() ], bidderRequest); + + expect(req.url).to.contain('/xfaHR0cDovL3ByZWJpZC5vcmcvZGV2LWRvY3Mvc3ViamVjdHM_X2Q9MQ'); + }); + it('should include bids', function () { let bid = minimalBid(); let req = spec.buildRequests([ bid ], bidderRequest); From e741cf8f5ad6f8c27109f109c7b796599820ed4d Mon Sep 17 00:00:00 2001 From: Prebid Manager <49466873+Prebid-Manager@users.noreply.github.com> Date: Wed, 1 May 2019 01:39:33 +0700 Subject: [PATCH 1195/1594] PrebidManager Analytics: init module (#3735) * PrebidManager Analytics: init module * PrebidManager Analytics: tests fix * PrebidManager Analytics: fix test * PrebidManager Analytics: renamed file names * PrebidManager Analytics: work on PR comments - default url, version, tests * PrebidManager Analytics: bring back ver * PrebidManager Analytics: setInterval for flush in enable analytics, fix empty config options, prebid function pageViewId * PrebidManager Analytics: disable analytics --- modules/prebidmanagerAnalyticsAdapter.js | 191 ++++++++++++++++++ modules/prebidmanagerAnalyticsAdapter.md | 9 + .../prebidmanagerAnalyticsAdapter_spec.js | 117 +++++++++++ 3 files changed, 317 insertions(+) create mode 100644 modules/prebidmanagerAnalyticsAdapter.js create mode 100644 modules/prebidmanagerAnalyticsAdapter.md create mode 100644 test/spec/modules/prebidmanagerAnalyticsAdapter_spec.js diff --git a/modules/prebidmanagerAnalyticsAdapter.js b/modules/prebidmanagerAnalyticsAdapter.js new file mode 100644 index 00000000000..eb9ad344253 --- /dev/null +++ b/modules/prebidmanagerAnalyticsAdapter.js @@ -0,0 +1,191 @@ +import {ajaxBuilder} from '../src/ajax'; +import adapter from '../src/AnalyticsAdapter'; +import adapterManager from '../src/adapterManager'; + +/** + * prebidmanagerAnalyticsAdapter.js - analytics adapter for prebidmanager + */ +const DEFAULT_EVENT_URL = 'https://endpoint.prebidmanager.com/endpoint' +const analyticsType = 'endpoint'; +const analyticsName = 'Prebid Manager Analytics: '; + +var utils = require('src/utils'); +var CONSTANTS = require('src/constants.json'); +let ajax = ajaxBuilder(0); + +var _VERSION = 1; +var initOptions = null; +var _pageViewId = utils.generateUUID(); +var _startAuction = 0; +var _bidRequestTimeout = 0; +let flushInterval; +var pmAnalyticsEnabled = false; + +var w = window; +var d = document; +var e = d.documentElement; +var g = d.getElementsByTagName('body')[0]; +var x = w.innerWidth || e.clientWidth || g.clientWidth; +var y = w.innerHeight || e.clientHeight || g.clientHeight; + +var _pageView = { + eventType: 'pageView', + userAgent: window.navigator.userAgent, + timestamp: Date.now(), + timezoneOffset: new Date().getTimezoneOffset(), + language: window.navigator.language, + vendor: window.navigator.vendor, + screenWidth: x, + screenHeight: y +}; + +var _eventQueue = [ + _pageView +]; + +let prebidmanagerAnalytics = Object.assign(adapter({url: DEFAULT_EVENT_URL, analyticsType}), { + track({eventType, args}) { + handleEvent(eventType, args); + } +}); + +prebidmanagerAnalytics.originEnableAnalytics = prebidmanagerAnalytics.enableAnalytics; +prebidmanagerAnalytics.enableAnalytics = function (config) { + initOptions = config.options || {}; + initOptions.url = initOptions.url || DEFAULT_EVENT_URL; + pmAnalyticsEnabled = true; + prebidmanagerAnalytics.originEnableAnalytics(config); + flushInterval = setInterval(flush, 1000); +}; + +prebidmanagerAnalytics.originDisableAnalytics = prebidmanagerAnalytics.disableAnalytics; +prebidmanagerAnalytics.disableAnalytics = function() { + if (!pmAnalyticsEnabled) { + return; + } + flush(); + clearInterval(flushInterval); + prebidmanagerAnalytics.originDisableAnalytics(); +}; + +function flush() { + if (!pmAnalyticsEnabled) { + return; + } + + if (_eventQueue.length > 1) { + var data = { + pageViewId: _pageViewId, + ver: _VERSION, + bundleId: initOptions.bundleId, + events: _eventQueue + }; + + ajax( + initOptions.url, + () => utils.logInfo(`${analyticsName} sent events batch`), + _VERSION + ':' + JSON.stringify(data), + { + contentType: 'text/plain', + method: 'POST', + withCredentials: true + } + ); + _eventQueue = [ + _pageView + ]; + } +} + +function handleEvent(eventType, eventArgs) { + eventArgs = eventArgs ? JSON.parse(JSON.stringify(eventArgs)) : {}; + var pmEvent = {}; + + switch (eventType) { + case CONSTANTS.EVENTS.AUCTION_INIT: { + pmEvent = eventArgs; + _startAuction = pmEvent.timestamp; + _bidRequestTimeout = pmEvent.timeout; + break; + } + case CONSTANTS.EVENTS.AUCTION_END: { + pmEvent = eventArgs; + pmEvent.start = _startAuction; + pmEvent.end = Date.now(); + break; + } + case CONSTANTS.EVENTS.BID_ADJUSTMENT: { + pmEvent.bidders = eventArgs; + break; + } + case CONSTANTS.EVENTS.BID_TIMEOUT: { + pmEvent.bidders = eventArgs; + pmEvent.duration = _bidRequestTimeout; + break; + } + case CONSTANTS.EVENTS.BID_REQUESTED: { + pmEvent = eventArgs; + break; + } + case CONSTANTS.EVENTS.BID_RESPONSE: { + pmEvent = eventArgs; + delete pmEvent.ad; + break; + } + case CONSTANTS.EVENTS.BID_WON: { + pmEvent = eventArgs; + delete pmEvent.ad; + delete pmEvent.adUrl; + break; + } + case CONSTANTS.EVENTS.BIDDER_DONE: { + pmEvent = eventArgs; + break; + } + case CONSTANTS.EVENTS.SET_TARGETING: { + pmEvent.targetings = eventArgs; + break; + } + case CONSTANTS.EVENTS.REQUEST_BIDS: { + pmEvent = eventArgs; + break; + } + case CONSTANTS.EVENTS.ADD_AD_UNITS: { + pmEvent = eventArgs; + break; + } + case CONSTANTS.EVENTS.AD_RENDER_FAILED: { + pmEvent = eventArgs; + break; + } + default: + return; + } + + pmEvent.eventType = eventType; + pmEvent.timestamp = pmEvent.timestamp || Date.now(); + + sendEvent(pmEvent); +} + +function sendEvent(event) { + _eventQueue.push(event); + utils.logInfo(`${analyticsName}Event ${event.eventType}:`, event); + + if (event.eventType === CONSTANTS.EVENTS.AUCTION_END) { + flush(); + } +} + +adapterManager.registerAnalyticsAdapter({ + adapter: prebidmanagerAnalytics, + code: 'prebidmanager' +}); + +prebidmanagerAnalytics.getOptions = function () { + return initOptions; +}; + +prebidmanagerAnalytics.flush = flush; + +export default prebidmanagerAnalytics; diff --git a/modules/prebidmanagerAnalyticsAdapter.md b/modules/prebidmanagerAnalyticsAdapter.md new file mode 100644 index 00000000000..030e79b406f --- /dev/null +++ b/modules/prebidmanagerAnalyticsAdapter.md @@ -0,0 +1,9 @@ +# Overview + +Module Name: Prebid Manager Analytics Adapter +Module Type: Analytics Adapter +Maintainer: admin@prebidmanager.com + +# Description + +Analytics adapter for Prebid Manager. Contact admin@prebidmanager.com for information. diff --git a/test/spec/modules/prebidmanagerAnalyticsAdapter_spec.js b/test/spec/modules/prebidmanagerAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..cd414a70236 --- /dev/null +++ b/test/spec/modules/prebidmanagerAnalyticsAdapter_spec.js @@ -0,0 +1,117 @@ +import prebidmanagerAnalytics from 'modules/prebidmanagerAnalyticsAdapter'; +import {expect} from 'chai'; +let events = require('src/events'); +let constants = require('src/constants.json'); + +describe('Prebid Manager Analytics Adapter', function () { + let xhr; + let requests; + + let bidWonEvent = { + 'bidderCode': 'appnexus', + 'width': 300, + 'height': 250, + 'adId': '1ebb82ec35375e', + 'mediaType': 'banner', + 'cpm': 0.5, + 'requestId': '1582271863760569973', + 'creative_id': '96846035', + 'creativeId': '96846035', + 'ttl': 60, + 'currency': 'USD', + 'netRevenue': true, + 'auctionId': '9c7b70b9-b6ab-4439-9e71-b7b382797c18', + 'responseTimestamp': 1537521629657, + 'requestTimestamp': 1537521629331, + 'bidder': 'appnexus', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'timeToRespond': 326, + 'size': '300x250', + 'status': 'rendered', + 'eventType': 'bidWon', + 'ad': 'some ad', + 'adUrl': 'ad url' + }; + + before(function () { + xhr = sinon.useFakeXMLHttpRequest(); + xhr.onCreate = request => requests.push(request); + }); + + after(function () { + xhr.restore(); + }); + + describe('Prebid Manager Analytic tests', function () { + beforeEach(function () { + requests = []; + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(function () { + prebidmanagerAnalytics.disableAnalytics(); + events.getEvents.restore(); + }); + + it('support custom endpoint', function () { + let custom_url = 'custom url'; + prebidmanagerAnalytics.enableAnalytics({ + provider: 'prebidmanager', + options: { + url: custom_url, + bundleId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + } + }); + + expect(prebidmanagerAnalytics.getOptions().url).to.equal(custom_url); + }); + + it('bid won event', function() { + xhr.onCreate = request => requests.push(request); + let bundleId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'; + prebidmanagerAnalytics.enableAnalytics({ + provider: 'prebidmanager', + options: { + bundleId: bundleId + } + }); + + events.emit(constants.EVENTS.BID_WON, bidWonEvent); + prebidmanagerAnalytics.flush(); + + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal('https://endpoint.prebidmanager.com/endpoint'); + expect(requests[0].requestBody.substring(0, 2)).to.equal('1:'); + + const pmEvents = JSON.parse(requests[0].requestBody.substring(2)); + expect(pmEvents.pageViewId).to.exist; + expect(pmEvents.bundleId).to.equal(bundleId); + expect(pmEvents.ver).to.equal(1); + expect(pmEvents.events.length).to.equal(2); + expect(pmEvents.events[0].eventType).to.equal('pageView'); + expect(pmEvents.events[1].eventType).to.equal('bidWon'); + expect(pmEvents.events[1].ad).to.be.undefined; + expect(pmEvents.events[1].adUrl).to.be.undefined; + }); + + it('track event without errors', function () { + sinon.spy(prebidmanagerAnalytics, 'track'); + + prebidmanagerAnalytics.enableAnalytics({ + provider: 'prebidmanager', + options: { + bundleId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + } + }); + + events.emit(constants.EVENTS.AUCTION_INIT, {}); + events.emit(constants.EVENTS.BID_REQUESTED, {}); + events.emit(constants.EVENTS.BID_RESPONSE, {}); + events.emit(constants.EVENTS.BID_WON, {}); + events.emit(constants.EVENTS.AUCTION_END, {}); + events.emit(constants.EVENTS.BID_TIMEOUT, {}); + + sinon.assert.callCount(prebidmanagerAnalytics.track, 6); + }); + }); +}); From 352da36418323c9dba2d10663739f1857c0a5595 Mon Sep 17 00:00:00 2001 From: phtechno Date: Tue, 30 Apr 2019 23:21:33 +0200 Subject: [PATCH 1196/1594] smartadserverBidAdapter.js - make bid.params.domain optional (#3781) https://prg.smartadserver.com is the standard domain for smartadserver. This update make the "bid.params.domain"-parameter optional. --- modules/smartadserverBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 00d617b3c92..401c72bffaf 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -16,7 +16,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - return !!(bid.params && bid.params.siteId && bid.params.pageId && bid.params.formatId && bid.params.domain); + return !!(bid.params && bid.params.siteId && bid.params.pageId && bid.params.formatId); }, /** * Make a server request from the list of BidRequests. @@ -63,7 +63,7 @@ export const spec = { var payloadString = JSON.stringify(payload); return { method: 'POST', - url: bid.params.domain + '/prebid/v1', + url: (bid.params.domain !== undefined ? bid.params.domain : 'https://prg.smartadserver.com') + '/prebid/v1', data: payloadString, }; }); From c48817ca4b54389cc53c2f26e84a02bfa03f0209 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 1 May 2019 09:27:51 -0400 Subject: [PATCH 1197/1594] update e2e tests in README (#3778) * update e2e tests in README * add clarifying note * added note about Prebid.org members + browserstack --- README.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 62c835f8eb3..f802efecfcf 100644 --- a/README.md +++ b/README.md @@ -207,10 +207,20 @@ gulp test-coverage gulp view-coverage ``` -For end-to-end testing, edit the example file `./integrationExamples/gpt/pbjs_example_gpt.html`: +For Prebid.org members with access to BrowserStack, additional end-to-end testing can be done with: -1. Change `{id}` values appropriately to set up ad units and bidders -2. Set the path to Prebid.js in your example file as shown below (see `pbs.src`). +```bash +gulp e2e-test --host=test.localhost +``` + +To run these tests, the following items are required: +- setup an alias of localhost in your `hosts` file (eg `127.0.0.1 test.localhost`); note - you can use any alias. Use this alias in the command-line argument above. +- access to [BrowserStack](https://www.browserstack.com/) account. Assign the following variables in your bash_profile: +```bash +export BROWSERSTACK_USERNAME='YourUserNameHere' +export BROWSERSTACK_ACCESS_KEY='YourAccessKeyHere' +``` +You can get these BrowserStack values from your profile page. For development: From 1357e96a71e6cb7b6c850b5e5f555ea951828337 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Wed, 1 May 2019 06:49:32 -0700 Subject: [PATCH 1198/1594] OpenX Adapter - support User ID module (#3529) * added universal id support to bid adapter * added unit test for universal id support in bid adapter * added universal id support to bid adapter * added unit test for universal id support in bid adapter * renamed universalID to userId * removed merge mistake * fix old code in test --- modules/openxBidAdapter.js | 4 +++- test/spec/modules/openxBidAdapter_spec.js | 24 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 52a97a98952..9719fbb635a 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -233,7 +233,9 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { } } - if (bids[0].crumbs && bids[0].crumbs.pubcid) { + if ((bids[0].userId && bids[0].userId.pubcid)) { + defaultParams.pubcid = bids[0].userId.pubcid; + } else if (bids[0].crumbs && bids[0].crumbs.pubcid) { defaultParams.pubcid = bids[0].crumbs.pubcid; } diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 468d9cc33a7..ee8e452f707 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -940,6 +940,30 @@ describe('OpenxAdapter', function () { const request = spec.buildRequests(bidRequestsWithPubcid); expect(request[0].data.pubcid).to.equal('c4a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); }); + + it('should send a pubcid query param when userId.pubcid is defined in the bid requests', function () { + const bidRequestsWithPubcid = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain' + }, + userId: { + pubcid: 'c1a4c843-2368-4b5e-b3b1-6ee4702b9ad6' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }]; + const request = spec.buildRequests(bidRequestsWithPubcid); + expect(request[0].data.pubcid).to.equal('c1a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); + }); }) }); From 293619775702f7e867322679ca963112c874e483 Mon Sep 17 00:00:00 2001 From: bretg Date: Wed, 1 May 2019 10:12:25 -0400 Subject: [PATCH 1199/1594] Delete sonobi_video.html (#3791) not sure how this empty file got placed in the root. removing --- sonobi_video.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 sonobi_video.html diff --git a/sonobi_video.html b/sonobi_video.html deleted file mode 100644 index e69de29bb2d..00000000000 From 8e2ee4aece18ccb7a470f8da0d8b147877a67f7b Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 1 May 2019 09:06:24 -0600 Subject: [PATCH 1200/1594] remove optimize.js from build process (#3789) --- gulpfile.js | 2 - package-lock.json | 1104 ++++++++++++++++++--------------------------- package.json | 1 - 3 files changed, 445 insertions(+), 662 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 0170df80c62..a89f570e496 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -19,7 +19,6 @@ var header = require('gulp-header'); var footer = require('gulp-footer'); var replace = require('gulp-replace'); var shell = require('gulp-shell'); -var optimizejs = require('gulp-optimize-js'); var eslint = require('gulp-eslint'); var gulpif = require('gulp-if'); var sourcemaps = require('gulp-sourcemaps'); @@ -145,7 +144,6 @@ function makeWebpackPkg() { .pipe(webpackStream(cloned, webpack)) .pipe(uglify()) .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid }))) - .pipe(optimizejs()) .pipe(gulp.dest('build/dist')); } diff --git a/package-lock.json b/package-lock.json index 655363b9949..c3bd739008f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.10.0", + "version": "2.13.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -856,12 +856,6 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@types/node": { - "version": "8.10.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.45.tgz", - "integrity": "sha512-tGVTbA+i3qfXsLbq9rEq/hezaHY55QxQLeXQL2ejNgFAxxrgu8eMmYIOsRcl7hN1uTLVsKOOYacV/rcJM3sfgQ==", - "dev": true - }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1079,6 +1073,58 @@ "default-require-extensions": "^1.0.0" } }, + "archiver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", + "dev": true, + "requires": { + "archiver-utils": "^1.3.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^1.2.0" + }, + "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + } + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "dev": true, + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash": "^4.8.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "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" + } + } + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -1296,12 +1342,6 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "ast-types": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.12.3.tgz", - "integrity": "sha512-wJUcAfrdW+IgDoMGNz5MmcvahKgB7BwIbLupdKVVHxHNYt+HVR2k35swdYNv9aZpF8nvlkjbnkp2rrNwxGckZA==", - "dev": true - }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -2648,6 +2688,16 @@ "integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==", "dev": true }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", @@ -2953,6 +3003,12 @@ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, + "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 + }, "buffer-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", @@ -3159,39 +3215,6 @@ "type-detect": "^4.0.5" } }, - "chai-nightwatch": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.2.1.tgz", - "integrity": "sha512-2lprSMi72sHq2ZGyPTYUDQNsd2O4z81SicascbI4bkU54Xzk5Ofunn2CbrExADGC7jBH2D8r66X/aSEl+/agXQ==", - "dev": true, - "requires": { - "assertion-error": "1.0.0", - "deep-eql": "0.1.3" - }, - "dependencies": { - "assertion-error": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", - "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", - "dev": true - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - } - }, - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3485,6 +3508,29 @@ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", "dev": true }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "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" + } + } + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3676,6 +3722,37 @@ "request": "^2.86.0" } }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "requires": { + "buffer": "^5.1.0" + }, + "dependencies": { + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + } + } + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "dev": true, + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } + }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -3768,6 +3845,21 @@ } } }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "^2.0.0" + } + }, + "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 + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -3801,15 +3893,6 @@ "assert-plus": "^1.0.0" } }, - "data-uri-to-buffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.1.tgz", - "integrity": "sha512-OkVVLrerfAKZlW2ZZ3Ve2y65jgiWqBKsTfUIAFbn8nVbPcCZg6l6gikKlEYv0kXcmzqGm6mFq/Jf2vriuEkv8A==", - "dev": true, - "requires": { - "@types/node": "^8.0.7" - } - }, "date-format": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", @@ -3899,6 +3982,12 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "deepmerge": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.0.1.tgz", + "integrity": "sha512-VIPwiMJqJ13ZQfaCsIFnp5Me9tnjURiaIFxfz7EH0Ci0dTSQpZtSLrqOicXqEd/z2r+z+Klk9GzmnRsgpgbOsQ==", + "dev": true + }, "default-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", @@ -3998,25 +4087,6 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4069,6 +4139,12 @@ "repeating": "^2.0.0" } }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true + }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -4458,12 +4534,6 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, - "ejs": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", - "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", - "dev": true - }, "electron-to-chromium": { "version": "1.3.124", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz", @@ -5232,12 +5302,6 @@ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, - "estree-walker": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", - "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", - "dev": true - }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", @@ -5306,18 +5370,52 @@ } }, "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "get-stream": { + "version": "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" + } + }, + "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" + } + } } }, "expand-braces": { @@ -5591,6 +5689,15 @@ "websocket-driver": ">=0.5.1" } }, + "fibers": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fibers/-/fibers-3.1.1.tgz", + "integrity": "sha512-dl3Ukt08rHVQfY8xGD0ODwyjwrRALtaghuqGH2jByYX1wpY+nAnRQjJ6Dbqq0DnVgNVQ9yibObzbF4IlPyiwPw==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3" + } + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -5610,12 +5717,6 @@ "object-assign": "^4.0.1" } }, - "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 - }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -5890,6 +5991,12 @@ "null-check": "^1.0.0" } }, + "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 + }, "fs-extra": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", @@ -6474,42 +6581,6 @@ } } }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, "fun-hooks": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.8.1.tgz", @@ -6527,6 +6598,15 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -6557,33 +6637,6 @@ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, - "get-uri": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.3.tgz", - "integrity": "sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw==", - "dev": true, - "requires": { - "data-uri-to-buffer": "2", - "debug": "4", - "extend": "~3.0.2", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "3" - }, - "dependencies": { - "readable-stream": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", - "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -6767,6 +6820,17 @@ "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", "dev": true }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, "glogg": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", @@ -6815,6 +6879,12 @@ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, + "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 + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -7385,18 +7455,6 @@ "minimatch": "^3.0.3" } }, - "gulp-optimize-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-optimize-js/-/gulp-optimize-js-1.1.0.tgz", - "integrity": "sha1-X9FcaLNvbh5zh3hPhXhDX3VpYkU=", - "dev": true, - "requires": { - "gulp-util": "^3.0.7", - "lodash": "^4.16.2", - "optimize-js": "^1.0.0", - "through2": "^2.0.1" - } - }, "gulp-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", @@ -7949,33 +8007,6 @@ "requires-port": "^1.0.0" } }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -8014,6 +8045,12 @@ } } }, + "humanize-duration": { + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.15.3.tgz", + "integrity": "sha512-BMz6w8p3NVa6QP9wDtqUkXfwgBqDaZ5z/np0EYdoWrLqL849Onp6JWMXMhbHtuvO9jUThLN5H1ThRQ8dUWnYkA==", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -8164,12 +8201,6 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -9333,80 +9364,12 @@ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, - "lodash._arraycopy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", - "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", - "dev": true - }, - "lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - }, - "dependencies": { - "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.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - } - } - }, - "lodash._baseclone": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", - "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "dev": true, - "requires": { - "lodash._arraycopy": "^3.0.0", - "lodash._arrayeach": "^3.0.0", - "lodash._baseassign": "^3.0.0", - "lodash._basefor": "^3.0.0", - "lodash.isarray": "^3.0.0", - "lodash.keys": "^3.0.0" - }, - "dependencies": { - "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.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - } - } - }, "lodash._basecopy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", "dev": true }, - "lodash._basefor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", - "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", - "dev": true - }, "lodash._basetostring": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", @@ -9419,12 +9382,6 @@ "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", "dev": true }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, "lodash._escapehtmlchar": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", @@ -9513,23 +9470,6 @@ "lodash._objecttypes": "~2.4.1" } }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "lodash.clone": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", - "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true, - "requires": { - "lodash._baseclone": "^3.0.0", - "lodash._bindcallback": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } - }, "lodash.defaults": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", @@ -9540,12 +9480,6 @@ "lodash.keys": "~2.4.1" } }, - "lodash.defaultsdeep": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.0.tgz", - "integrity": "sha1-vsECT4WxvZbL6kBbI8FK1kQ6b4E=", - "dev": true - }, "lodash.escape": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", @@ -9595,12 +9529,6 @@ "lodash.isobject": "~2.4.1" } }, - "lodash.merge": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", - "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", - "dev": true - }, "lodash.restparam": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", @@ -9764,15 +9692,6 @@ "es5-ext": "~0.10.2" } }, - "magic-string": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz", - "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=", - "dev": true, - "requires": { - "vlq": "^0.2.1" - } - }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -10266,12 +10185,6 @@ } } }, - "mkpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", - "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", - "dev": true - }, "mocha": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", @@ -10512,36 +10425,17 @@ "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", "dev": true }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true - }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, - "nightwatch": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.0.19.tgz", - "integrity": "sha512-Dl+EN4wFp927nn7KRkCIJ7b0Th9PVjiwflzqsoqJOwLPcLuzSBz4FYBvHXQtUkaL4/nELVgXurw/KXqj2gcFSg==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "chai-nightwatch": "0.2.1", - "ejs": "^2.5.9", - "lodash.clone": "3.0.3", - "lodash.defaultsdeep": "^4.6.0", - "lodash.merge": "^4.6.1", - "minimatch": "3.0.4", - "mkpath": "1.0.0", - "mocha": "^5.1.1", - "optimist": "^0.6.1", - "proxy-agent": "^3.0.0" - } + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true }, "nise": { "version": "1.4.10", @@ -10670,6 +10564,12 @@ "once": "^1.3.2" } }, + "npm-install-package": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", + "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", + "dev": true + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -10899,168 +10799,6 @@ } } }, - "optimize-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/optimize-js/-/optimize-js-1.0.3.tgz", - "integrity": "sha1-QyavhlfEpf8y2vcmYxdU9yq3/bw=", - "dev": true, - "requires": { - "acorn": "^3.3.0", - "concat-stream": "^1.5.1", - "estree-walker": "^0.3.0", - "magic-string": "^0.16.0", - "yargs": "^4.8.1" - }, - "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 - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "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" - } - }, - "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" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "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=", - "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" - } - }, - "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" - } - }, - "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" - } - }, - "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 - }, - "yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, - "requires": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "lodash.assign": "^4.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.1", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.1" - } - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "lodash.assign": "^4.0.6" - } - } - } - }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -11105,6 +10843,23 @@ "execa": "^0.7.0", "lcid": "^1.0.0", "mem": "^1.1.0" + }, + "dependencies": { + "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.0.1", + "get-stream": "^3.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" + } + } } }, "os-tmpdir": { @@ -11164,73 +10919,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "pac-proxy-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", - "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, "pako": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", @@ -11660,39 +11348,6 @@ "integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==", "dev": true }, - "proxy-agent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.0.tgz", - "integrity": "sha512-IkbZL4ClW3wwBL/ABFD2zJ8iP84CY0uKMvBPk/OceQe/cEjrxzN1pMHsLwhbzUoRhG9QbSxYC+Z7LBkTiBNvrA==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^3.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true - }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -12288,6 +11943,27 @@ "uuid": "^3.3.2" } }, + "request-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", + "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -12387,6 +12063,12 @@ "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", "dev": true }, + "rgb2hex": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.9.tgz", + "integrity": "sha512-32iuQzhOjyT+cv9aAFRBJ19JgHwzQwbjUhH3Fj2sWW2EEGAW8fpFrDFP5ndoKDxJaLO06x1hE3kyuIFrUQtybQ==", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -12722,12 +12404,6 @@ } } }, - "smart-buffer": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", - "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -12960,26 +12636,6 @@ } } }, - "socks": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz", - "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==", - "dev": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "4.0.2" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", - "dev": true, - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - } - }, "sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", @@ -13156,6 +12812,12 @@ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", "dev": true }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, "stream-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", @@ -13438,6 +13100,21 @@ "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", "dev": true }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, "temp-fs": { "version": "0.9.9", "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", @@ -13508,12 +13185,6 @@ "xtend": "~4.0.0" } }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true - }, "time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", @@ -13601,6 +13272,12 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -14415,12 +14092,6 @@ "source-map": "^0.5.1" } }, - "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true - }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -14456,6 +14127,115 @@ "neo-async": "^2.5.0" } }, + "wdio-browserstack-service": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/wdio-browserstack-service/-/wdio-browserstack-service-0.1.18.tgz", + "integrity": "sha512-6tISYMKzwr2oxx0yi2Q4GoFC2Mbq81iHhqxayacC4XgFR7QbmQkxwV8JPeq590AXhuhPqqmyuEGkMqc9fo/UoQ==", + "dev": true, + "requires": { + "browserstack-local": "^1.3.7", + "request": "^2.81.0", + "request-promise": "^4.2.1" + } + }, + "wdio-concise-reporter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/wdio-concise-reporter/-/wdio-concise-reporter-0.1.2.tgz", + "integrity": "sha1-+kmA768kszWfHqQz73thYxVDphQ=", + "dev": true + }, + "wdio-dot-reporter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/wdio-dot-reporter/-/wdio-dot-reporter-0.0.10.tgz", + "integrity": "sha512-A0TCk2JdZEn3M1DSG9YYbNRcGdx/YRw19lTiRpgwzH4qqWkO/oRDZRmi3Snn4L2j54KKTfPalBhlOtc8fojVgg==", + "dev": true + }, + "wdio-mocha-framework": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/wdio-mocha-framework/-/wdio-mocha-framework-0.6.4.tgz", + "integrity": "sha512-GZsXwoW60/fkkfqZJR/ZAdiALaM+hW+BbnTT9x214qPR4Pe5XeyYxhJNEdyf0dNI9625cMdkyZYaWoFHN5zDcA==", + "dev": true, + "requires": { + "babel-runtime": "^6.23.0", + "mocha": "^5.2.0", + "wdio-sync": "0.7.3" + } + }, + "wdio-spec-reporter": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/wdio-spec-reporter/-/wdio-spec-reporter-0.1.5.tgz", + "integrity": "sha512-MqvgTow8hFwhFT47q67JwyJyeynKodGRQCxF7ijKPGfsaG1NLssbXYc0JhiL7SiAyxnQxII0UxzTCd3I6sEdkg==", + "dev": true, + "requires": { + "babel-runtime": "~6.26.0", + "chalk": "^2.3.0", + "humanize-duration": "~3.15.0" + } + }, + "wdio-sync": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/wdio-sync/-/wdio-sync-0.7.3.tgz", + "integrity": "sha512-ukASSHOQmOxaz5HTILR0jykqlHBtAPsBpMtwhpiG0aW9uc7SO7PF+E5LhVvTG4ypAh+UGmY3rTjohOsqDr39jw==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "fibers": "^3.0.0", + "object.assign": "^4.0.3" + } + }, + "webdriverio": { + "version": "4.14.4", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", + "integrity": "sha512-Knp2vzuzP5c5ybgLu+zTwy/l1Gh0bRP4zAr8NWcrStbuomm9Krn9oRF0rZucT6AyORpXinETzmeowFwIoo7mNA==", + "dev": true, + "requires": { + "archiver": "~2.1.0", + "babel-runtime": "^6.26.0", + "css-parse": "^2.0.0", + "css-value": "~0.0.1", + "deepmerge": "~2.0.1", + "ejs": "~2.5.6", + "gaze": "~1.1.2", + "glob": "~7.1.1", + "grapheme-splitter": "^1.0.2", + "inquirer": "~3.3.0", + "json-stringify-safe": "~5.0.1", + "mkdirp": "~0.5.1", + "npm-install-package": "~2.1.0", + "optimist": "~0.6.1", + "q": "~1.5.0", + "request": "^2.83.0", + "rgb2hex": "^0.1.9", + "safe-buffer": "~5.1.1", + "supports-color": "~5.0.0", + "url": "~0.11.0", + "wdio-dot-reporter": "~0.0.8", + "wgxpath": "~1.0.0" + }, + "dependencies": { + "ejs": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", + "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", + "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 + }, + "supports-color": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", + "integrity": "sha512-7FQGOlSQ+AQxBNXJpVDj8efTA/FtyB5wcNE1omXXJ0cq6jm1jjDwuROlYDbnzHqdNPqliWFhcioCWSyav+xBnA==", + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, "webpack": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", @@ -15329,6 +15109,12 @@ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", "dev": true }, + "wgxpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", + "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", + "dev": true + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -15344,12 +15130,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -15404,12 +15184,6 @@ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true - }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", @@ -15448,6 +15222,18 @@ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", "dev": true + }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "dev": true, + "requires": { + "archiver-utils": "^1.3.0", + "compress-commons": "^1.2.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0" + } } } } diff --git a/package.json b/package.json index 1419f99c65f..13a35296e0b 100755 --- a/package.json +++ b/package.json @@ -49,7 +49,6 @@ "gulp-header": "^1.7.1", "gulp-if": "^2.0.2", "gulp-js-escape": "^1.0.1", - "gulp-optimize-js": "^1.1.0", "gulp-replace": "^1.0.0", "gulp-shell": "^0.5.2", "gulp-sourcemaps": "^2.6.0", From 23023365c9467167ab3e594ab486adb6f8b142cc Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Wed, 1 May 2019 11:29:16 -0700 Subject: [PATCH 1201/1594] Pubmatic: Making Adslot param optional (#3788) * changes for multiformat support * added new constant NATIVE_ASSETS in PubMatic adapter * removed NATIVE_ASSET_KEY reference in PubMatic adapter * removed reference of const NATIVE_ASSET_ID from PubMatic adapter * removed reference of const NATIVE_ASSET_DATA_TYPE in PubMatic adapter * using _commonNativeRequestObject in PubMatic adapter to avoid repeating code block * removed new-lines in const declaration * generating NATIVE_ASSET_REVERSE_ID from NATIVE_ASSETS * renamed NATIVE_ASSET_REVERSE_ID to NATIVE_ASSET_ID_TO_KEY_MAP * little modification in _checkParamDataType in PubMatic adapter * a minor improvement * using let instead of var * added NATIVE_ASSET_KEY_TO_ASSET_MAP and combining switch cases * lint update * removed some stale comments * using LOG_WARN_PREFIX * using const UNDEFINED * added a logWarn in catch * using arrow functions * code review changes * making adSlot parameter optional * added a test case for without adSlot config * changes to checkMediaType function * suppress warning of missing mediaTypes.banner for native and video impression * ignore fluid size, if present, in banner impression * fix for ignoring fluid size in banner impression * added relevant comments and test cases for fluid case in banner request * added sample config for multiformat adunit * commented redundant check * marking adSlot param as optional in examples * fixed some lint errors * removed commnented code * removed a trailing white space * removed a todo comment as suggested in review * deleting commented test cases --- modules/pubmaticBidAdapter.js | 16 ++---- modules/pubmaticBidAdapter.md | 8 +-- test/spec/modules/pubmaticBidAdapter_spec.js | 51 ++++++++++++++------ 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 6891285fcc2..c791acd9485 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -511,7 +511,7 @@ function _createImpressionObject(bid, conf) { impObj = { id: bid.bidId, - tagid: bid.params.adUnit, + tagid: bid.params.adUnit || undefined, bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor), secure: window.location.protocol === 'https:' ? 1 : 0, ext: { @@ -746,10 +746,6 @@ export const spec = { utils.logWarn(LOG_WARN_PREFIX + 'Error: publisherId is mandatory and cannot be numeric. Call to OpenBid will not be sent for ad unit: ' + JSON.stringify(bid)); return false; } - if (!utils.isStr(bid.params.adSlot)) { - utils.logWarn(LOG_WARN_PREFIX + 'Error: adSlotId is mandatory and cannot be numeric. Call to OpenBid will not be sent for ad unit: ' + JSON.stringify(bid)); - return false; - } // video ad validation if (bid.params.hasOwnProperty('video')) { if (!bid.params.video.hasOwnProperty('mimes') || !utils.isArray(bid.params.video.mimes) || bid.params.video.mimes.length === 0) { @@ -783,17 +779,11 @@ export const spec = { var blockedIabCategories = []; validBidRequests.forEach(originalBid => { bid = utils.deepClone(originalBid); + bid.params.adSlot = bid.params.adSlot || ''; _parseAdSlot(bid); if (bid.params.hasOwnProperty('video')) { - if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex)) { - utils.logWarn(LOG_WARN_PREFIX + 'Skipping the non-standard adslot: ', bid.params.adSlot, JSON.stringify(bid)); - return; - } + // Nothing to do } else { - if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex)) { - utils.logWarn(LOG_WARN_PREFIX + 'Skipping the non-standard adslot: ', bid.params.adSlot, JSON.stringify(bid)); - return; - } // 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) { diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 16a3b203e20..1948acba40f 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -25,7 +25,7 @@ var adUnits = [ bidder: 'pubmatic', params: { publisherId: '156209', // required - adSlot: 'pubmatic_test2', // required + adSlot: 'pubmatic_test2', // optional pmzoneid: 'zone1, zone11', // optional lat: '40.712775', // optional lon: '-74.005973', // optional @@ -56,7 +56,7 @@ var adVideoAdUnits = [ bidder: 'pubmatic', params: { publisherId: '156209', // required - adSlot: 'pubmatic_video1', // required + adSlot: 'pubmatic_video1', // optional video: { mimes: ['video/mp4','video/x-flv'], // required skippable: true, // optional @@ -104,7 +104,7 @@ var adUnits = [ bidder: 'pubmatic', params: { publisherId: '156295', // required - adSlot: 'pubmatic_test2@1x1', // required + adSlot: 'pubmatic_test2@1x1', // optional } }] }]; @@ -146,7 +146,7 @@ var adUnits = [ bidder: 'pubmatic', params: { publisherId: '156209', // required - adSlot: 'pubmatic_test2@300x250', // required + adSlot: 'pubmatic_test2@300x250', // optional pmzoneid: 'zone1, zone11', // optional lat: '40.712775', // optional lon: '-74.005973', // optional diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index bf008574027..b25fd22f822 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -668,27 +668,15 @@ describe('PubMatic adapter', function () { expect(isValid).to.equal(false); }); - it('invalid bid case: adSlot not passed', function () { - let validBid = { - bidder: 'pubmatic', - params: { - publisherId: '301' - } - }, - isValid = spec.isBidRequestValid(validBid); - expect(isValid).to.equal(false); - }); - - it('invalid bid case: adSlot is not string', function () { + it('valid bid case: adSlot is not passed', function () { let validBid = { bidder: 'pubmatic', params: { - publisherId: '301', - adSlot: 15671365 + publisherId: '301' } }, isValid = spec.isBidRequestValid(validBid); - expect(isValid).to.equal(false); + expect(isValid).to.equal(true); }); }); @@ -742,6 +730,39 @@ describe('PubMatic adapter', function () { expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); }); + it('Request params check: without adSlot', function () { + delete bidRequests[0].params.adSlot; + let request = spec.buildRequests(bidRequests); + let data = JSON.parse(request.data); + expect(data.at).to.equal(1); // auction type + expect(data.cur[0]).to.equal('USD'); // currency + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.page).to.equal(bidRequests[0].params.kadpageurl); // forced pageURL + expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id + expect(data.site.ext).to.exist.and.to.be.an('object'); // dctr parameter + expect(data.site.ext.key_val).to.exist.and.to.equal(bidRequests[0].params.dctr); + expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB + expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender + expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID + expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID + expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID + + expect(data.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id + expect(data.imp[0].bidfloor).to.equal(parseFloat(bidRequests[0].params.kadfloor)); // kadfloor + expect(data.imp[0].tagid).to.deep.equal(undefined); // tagid + expect(data.imp[0].banner.w).to.equal(728); // width + expect(data.imp[0].banner.h).to.equal(90); // height + expect(data.imp[0].banner.format).to.deep.equal([{w: 160, h: 600}]); + expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid + expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); + }); + it('Request params multi size format object check', function () { let bidRequests = [ { From ef45260a202f31b5d1ad9331f5d30e4128ff393a Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Wed, 1 May 2019 15:06:04 -0400 Subject: [PATCH 1202/1594] Prebid 2.13.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 13a35296e0b..0768304e10b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.13.0-pre", + "version": "2.13.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 1c245444c5bec189b05798920035d98fe1195d7e Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Wed, 1 May 2019 15:43:10 -0400 Subject: [PATCH 1203/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0768304e10b..72ddc2e6e53 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.13.0", + "version": "2.14.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 5ba930d20f2aeb4318372af9afda0b676fc820e0 Mon Sep 17 00:00:00 2001 From: sumit116 Date: Thu, 2 May 2019 17:23:00 +0530 Subject: [PATCH 1204/1594] add adUnitCodes as param for setTargetingForAst() (#3792) --- src/prebid.js | 5 +++-- src/targeting.js | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index d475a715bbf..1b6a40aff97 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -260,16 +260,17 @@ $$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit, customSlotMatching /** * Set query string targeting on all AST (AppNexus Seller Tag) ad units. Note that this function has to be called after all ad units on page are defined. For working example code, see [Using Prebid.js with AppNexus Publisher Ad Server](http://prebid.org/dev-docs/examples/use-prebid-with-appnexus-ad-server.html). + * @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes * @alias module:pbjs.setTargetingForAst */ -$$PREBID_GLOBAL$$.setTargetingForAst = function() { +$$PREBID_GLOBAL$$.setTargetingForAst = function(adUnitCodes) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.setTargetingForAn', arguments); if (!targeting.isApntagDefined()) { utils.logError('window.apntag is not defined on the page'); return; } - targeting.setTargetingForAst(); + targeting.setTargetingForAst(adUnitCodes); // emit event events.emit(SET_TARGETING, targeting.getAllTargeting()); diff --git a/src/targeting.js b/src/targeting.js index 90897b8d956..6caa4029c9c 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -248,10 +248,11 @@ export function newTargeting(auctionManager) { }; /** + * @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes * Sets targeting for AST */ - targeting.setTargetingForAst = function() { - let astTargeting = targeting.getAllTargeting(); + targeting.setTargetingForAst = function(adUnitCodes) { + let astTargeting = targeting.getAllTargeting(adUnitCodes); try { targeting.resetPresetTargetingAST(); From f04f91282e5b0e209bee1921d25dd62a7302106a Mon Sep 17 00:00:00 2001 From: Alexander Fominov Date: Fri, 3 May 2019 01:16:02 +0300 Subject: [PATCH 1205/1594] Add HPMD Network bid adapter (#3764) --- modules/hpmdnetworkBidAdapter.js | 96 ++++++++++++ modules/hpmdnetworkBidAdapter.md | 32 ++++ .../modules/hpmdnetworkBidAdapter_spec.js | 148 ++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 modules/hpmdnetworkBidAdapter.js create mode 100644 modules/hpmdnetworkBidAdapter.md create mode 100644 test/spec/modules/hpmdnetworkBidAdapter_spec.js diff --git a/modules/hpmdnetworkBidAdapter.js b/modules/hpmdnetworkBidAdapter.js new file mode 100644 index 00000000000..ad17caba7bc --- /dev/null +++ b/modules/hpmdnetworkBidAdapter.js @@ -0,0 +1,96 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; + +const BIDDER_CODE = 'hpmdnetwork'; +const BIDDER_CODE_ALIAS = 'hpmd'; +const HPMDNETWORK_HOST = '//banner.hpmdnetwork.ru/bidder/request'; +const DEFAULT_TTL = 300; +const DEFAULT_CURRENCY = 'RUB'; + +export const spec = { + code: BIDDER_CODE, + aliases: [ BIDDER_CODE_ALIAS ], + supportedMediaTypes: [ BANNER ], + isBidRequestValid: isBidRequestValid, + buildRequests: buildRequests, + interpretResponse: interpretResponse, +}; + +function isBidRequestValid(bid) { + const { placementId } = bid.params; + return !!placementId; +} + +function buildRequests(validBidRequests, bidderRequest) { + const payload = {}; + payload.places = []; + + validBidRequests.forEach((bidRequest) => { + const place = { + id: bidRequest.bidId, + placementId: bidRequest.params.placementId + '', + }; + payload.places.push(place); + }); + + payload.url = bidderRequest.refererInfo.referer; + payload.settings = { currency: DEFAULT_CURRENCY }; + + return { + method: 'POST', + url: HPMDNETWORK_HOST, + data: payload, + }; +} + +function interpretResponse(serverResponse) { + const { body } = serverResponse; + const bidResponses = []; + + if (body.bids) { + body.bids.forEach((bid) => { + const size = getCreativeSize(bid); + const bidResponse = { + requestId: bid.id, + cpm: bid.cpm, + ad: wrapDisplayUrl(bid.displayUrl), + width: size.width, + height: size.height, + creativeId: bid.creativeId || generateRandomInt(), + currency: bid.currency || DEFAULT_CURRENCY, + netRevenue: true, + ttl: bid.ttl || DEFAULT_TTL, + }; + + bidResponses.push(bidResponse); + }); + } + + return bidResponses; +} + +function wrapDisplayUrl(displayUrl) { + return ``; +} + +function getCreativeSize(creativeSize) { + const size = { + width: 1, + height: 1, + }; + + if (!!creativeSize.width && creativeSize.width !== -1) { + size.width = creativeSize.width; + } + if (!!creativeSize.height && creativeSize.height !== -1) { + size.height = creativeSize.height; + } + + return size; +} + +function generateRandomInt() { + return Math.random().toString(16).substring(2); +} + +registerBidder(spec); diff --git a/modules/hpmdnetworkBidAdapter.md b/modules/hpmdnetworkBidAdapter.md new file mode 100644 index 00000000000..b7ac51a9311 --- /dev/null +++ b/modules/hpmdnetworkBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +Module Name: HPMD Network Bidder Adapter + +Module Type: Bidder Adapter + +Maintainer: a.fominov@hpmdnetwork.ru + +# Description + +You can use this adapter to get a bid from HPMD Network. + +About us : https://www.hpmdnetwork.ru/ + + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'test-div', + bids: [ + { + bidder: "hpmdnetwork", + params: { + placementId: "123" + } + } + ] + } + ]; +``` + diff --git a/test/spec/modules/hpmdnetworkBidAdapter_spec.js b/test/spec/modules/hpmdnetworkBidAdapter_spec.js new file mode 100644 index 00000000000..37ec44f07c4 --- /dev/null +++ b/test/spec/modules/hpmdnetworkBidAdapter_spec.js @@ -0,0 +1,148 @@ +import { expect } from 'chai'; +import { spec } from 'modules/hpmdnetworkBidAdapter'; + +describe('HPMDNetwork Adapter', function() { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + const validBid = { + bidder: 'hpmdnetwork', + params: { + placementId: '1' + } + }; + + expect(spec.isBidRequestValid(validBid)).to.equal(true); + }); + + it('should return false for when required params are not passed', function () { + const invalidBid = { + bidder: 'hpmdnetwork', + params: {} + }; + + expect(spec.isBidRequestValid(invalidBid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const bidRequests = [ + { + bidId: 'bid1', + bidder: 'hpmdnetwork', + params: { + placementId: '1' + } + }, + { + bidId: 'bid2', + bidder: 'hpmdnetwork', + params: { + placementId: '2', + } + } + ]; + const bidderRequest = { + refererInfo: { + referer: 'https://example.com?foo=bar' + } + }; + + const 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('//banner.hpmdnetwork.ru/bidder/request'); + 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() { + const place1 = bidRequest.data.places[0]; + const 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 site parameters', function() { + const url = bidRequest.data.url; + + expect(url).to.be.an('String'); + expect(url).to.equal('https://example.com?foo=bar'); + }); + + it('should pass settings', function() { + const settings = bidRequest.data.settings; + + expect(settings).to.be.an('object'); + expect(settings.currency).to.equal('RUB'); + }); + }); + + describe('interpretResponse', function () { + const serverResponse = { + body: { + 'bids': + [ + { + 'cpm': 20, + 'currency': 'RUB', + 'displayUrl': '//banner.hpmdnetwork.ru/bidder/display?dbid=0&vbid=168', + 'id': '1', + 'creativeId': '11111', + }, + { + 'cpm': 30, + 'currency': 'RUB', + 'displayUrl': '//banner.hpmdnetwork.ru/bidder/display?dbid=0&vbid=170', + 'id': '2', + 'creativeId': '22222', + 'width': 300, + 'height': 250, + }, + ] + } + }; + + const bids = spec.interpretResponse(serverResponse); + + it('should return empty array for response with no bids', function() { + const 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 without sizes', function() { + expect(bids[0].requestId).to.equal('1'); + expect(bids[0].cpm).to.equal(20); + expect(bids[0].width).to.equal(1); + expect(bids[0].height).to.equal(1); + expect(bids[0].ttl).to.equal(300); + expect(bids[0].currency).to.equal('RUB'); + expect(bids[0]).to.have.property('creativeId'); + expect(bids[0].creativeId).to.equal('11111'); + expect(bids[0].netRevenue).to.equal(true); + expect(bids[0].ad).to.include(''); + }); + + it('should parse bid with sizes', function() { + expect(bids[1].requestId).to.equal('2'); + expect(bids[1].cpm).to.equal(30); + expect(bids[1].width).to.equal(300); + expect(bids[1].height).to.equal(250); + expect(bids[1].ttl).to.equal(300); + expect(bids[1].currency).to.equal('RUB'); + expect(bids[1]).to.have.property('creativeId'); + expect(bids[1].creativeId).to.equal('22222'); + expect(bids[1].netRevenue).to.equal(true); + expect(bids[1].ad).to.include(''); + }); + }); +}); From 38e50d2a72f551f92fa4741385e3aff8d47ba7bb Mon Sep 17 00:00:00 2001 From: Alex Pashkov Date: Fri, 3 May 2019 18:19:28 +0300 Subject: [PATCH 1206/1594] VI Bid Adapter Changes (#3748) * Add new viBidAdapter * Change request schema * Min area is 1 * Send bidId * Refactor getDocumentHeight * Add getDocumentHeight test * Remove getWindowHeight * Add getOffset tests * Add getWindowParents tests * Add getTopmostReachableWindow test * Add curWindow * Add more tests * Add getIframeType tests * Rename hostile->nonfriendly * Add more params to bid request * Add getFrameElements tests * Add area tests * Add more tests * Add more tests * Add getViUserId * Add fallback to localStorage * Change bid URL * Add media-types * Remove user id * withCredentials: true * Add https * Remove getViUserId from spec * Add mergeSizes * Add useSizes param --- modules/viBidAdapter.js | 423 +++++++++-- modules/viBidAdapter.md | 1 + test/spec/modules/viBidAdapter_spec.js | 997 ++++++++++++++++++++++--- 3 files changed, 1248 insertions(+), 173 deletions(-) diff --git a/modules/viBidAdapter.js b/modules/viBidAdapter.js index 5166277ff81..93ead1c2380 100644 --- a/modules/viBidAdapter.js +++ b/modules/viBidAdapter.js @@ -1,69 +1,388 @@ -import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER } from '../src/mediaTypes'; +import * as mediaTypes from '../src/mediaTypes'; -const BIDDER_CODE = 'vi'; -const SUPPORTED_MEDIA_TYPES = [BANNER]; +export function get(path, obj, notFound) { + path = typeof path === 'string' ? path.split('.') : path; -function isBidRequestValid(bid) { - return !!(bid.params.pubId); + while (path.length) { + const [key] = path; + if (!(obj instanceof Object) || !(key in obj)) return notFound; + obj = obj[key]; + path = path.slice(1); + } + + return obj; } -function buildRequests(bidReqs) { - let imps = []; - utils._each(bidReqs, function (bid) { - imps.push({ - id: bid.bidId, - sizes: utils.parseSizesInput(bid.sizes).map(size => size.split('x')), - bidFloor: parseFloat(bid.params.bidFloor) > 0 ? bid.params.bidFloor : 0 - }); - }); +export function merge(a, b, fn = a => a) { + const res = {}; + + for (const key in a) { + if (key in b) { + res[key] = fn(a[key], b[key]); + } else { + res[key] = a[key]; + } + } + + for (const key in b) { + if (!(key in a)) res[key] = b[key]; + } + + return res; +} + +export function ratioToPercentageCeil(x) { + return Math.ceil(x * 100); +} - const bidRequest = { - id: bidReqs[0].requestId, - imps: imps, - publisherId: utils.getBidIdParameter('pubId', bidReqs[0].params), - siteId: utils.getBidIdParameter('siteId', bidReqs[0].params), - cat: utils.getBidIdParameter('cat', bidReqs[0].params), - language: utils.getBidIdParameter('lang', bidReqs[0].params), - domain: utils.getTopWindowLocation().hostname, - page: utils.getTopWindowUrl(), - referrer: utils.getTopWindowReferrer() +export function getDocumentHeight(curDocument = document) { + return Math.max( + get('body.clientHeight', curDocument, 0), + get('body.scrollHeight', curDocument, 0), + get('body.offsetHeight', curDocument, 0), + get('documentElement.clientHeight', curDocument, 0), + get('documentElement.scrollHeight', curDocument, 0), + get('documentElement.offsetHeight', curDocument, 0) + ); +} + +export function getOffset(element) { + const rect = element.getBoundingClientRect(); + const elementWindow = getElementWindow(element); + if (!elementWindow) throw new Error('cannot get element window'); + const scrollLeft = + elementWindow.pageXOffset || get('documentElement.scrollLeft', document, 0); + const scrollTop = + elementWindow.pageYOffset || get('documentElement.scrollTop', document, 0); + return { + top: rect.top + scrollTop, + right: rect.right + scrollLeft, + bottom: rect.bottom + scrollTop, + left: rect.left + scrollLeft }; +} + +var IframeType; + +(function(IframeType) { + IframeType['safeframe'] = 'safeframe'; + IframeType['friendly'] = 'friendly'; + IframeType['nonfriendly'] = 'nonfriendly'; +})(IframeType || (IframeType = {})); + +export function getWindowParents(curWindow = window) { + const parents = []; + + while (curWindow && curWindow.parent && curWindow !== curWindow.parent) { + parents.push(curWindow.parent); + curWindow = curWindow.parent; + } + + return parents; +} + +export function getTopmostReachableWindow(curWindow = window) { + const parents = getWindowParents(curWindow); + return parents.length ? parents[parents.length - 1] : curWindow; +} + +export function topDocumentIsReachable(curWindow = window) { + if (!isInsideIframe(curWindow)) return true; + const windowParents = getWindowParents(curWindow); + + try { + const topWindow = windowParents[windowParents.length - 1]; + + return topWindow === curWindow.top && !!curWindow.top.document; + } catch (e) { + return false; + } +} + +export function isInsideIframe(curWindow = window) { + return curWindow !== curWindow.top; +} + +export function isInsideSafeframe(curWindow = window) { + return !topDocumentIsReachable(curWindow) && !!curWindow.$sf; +} + +export function isInsideFriendlyIframe(curWindow = window) { + return isInsideIframe(curWindow) && topDocumentIsReachable(curWindow); +} + +export function getIframeType(curWindow = window) { + if (!isInsideIframe(curWindow)) return; + if (isInsideSafeframe(curWindow)) return IframeType.safeframe; + if (isInsideFriendlyIframe(curWindow)) return IframeType.friendly; + return IframeType.nonfriendly; +} + +function getElementWindow(element) { + return element.ownerDocument + ? element.ownerDocument.defaultView + : element.defaultView; +} + +const NO_CUTS = { + top: 0, + right: 0, + bottom: 0, + left: 0 +}; + +export function getRectCuts(rect, vh, vw, vCuts = NO_CUTS) { + let { top, left } = rect; + const { bottom, right } = rect; + top = top + vCuts.top; + left = left + vCuts.left; + vh = vh + vCuts.bottom; + vw = vw + vCuts.right; return { - method: 'POST', - url: `//pb.vi-serve.com/prebid/bid`, - data: JSON.stringify(bidRequest), - options: {contentType: 'application/json', withCredentials: false} + bottom: Math.min(0, vh - bottom), + left: Math.min(0, left), + right: Math.min(0, vw - right), + top: Math.min(0, top) }; } -function interpretResponse(bids) { - let responses = []; - utils._each(bids.body, function(bid) { - responses.push({ - requestId: bid.id, - cpm: parseFloat(bid.price), - width: parseInt(bid.width, 10), - height: parseInt(bid.height, 10), - creativeId: bid.creativeId, - dealId: bid.dealId || null, - currency: 'USD', - netRevenue: true, - mediaType: BANNER, - ad: decodeURIComponent(`${bid.ad}`), - ttl: 60000 +export function getFrameElements(curWindow = window) { + const frameElements = []; + + while (curWindow && curWindow.frameElement) { + frameElements.unshift(curWindow.frameElement); + curWindow = + curWindow.frameElement.ownerDocument && + curWindow.frameElement.ownerDocument.defaultView; + } + + return frameElements; +} + +export function getElementCuts(element, vCuts) { + const window = getElementWindow(element); + return getRectCuts( + element.getBoundingClientRect(), + window ? window.innerHeight : 0, + window ? window.innerWidth : 0, + vCuts + ); +} + +export function area(width, height, areaCuts = NO_CUTS) { + const { top, right, bottom, left } = areaCuts; + return Math.max(0, (width + left + right) * (height + top + bottom)); +} + +export function getInViewRatio(element) { + const elements = [...getFrameElements(getElementWindow(element)), element]; + const vCuts = elements.reduce( + (vCuts, element) => getElementCuts(element, vCuts), + NO_CUTS + ); + return ( + area(element.offsetWidth || 1, element.offsetHeight || 1, vCuts) / + area(element.offsetWidth || 1, element.offsetHeight || 1) + ); +} + +export function getInViewRatioInsideTopFrame(element) { + const elements = [...getFrameElements().slice(1), element]; + const vCuts = elements.reduce( + (vCuts, element) => getElementCuts(element, vCuts), + NO_CUTS + ); + return ( + area(element.offsetWidth, element.offsetHeight, vCuts) / + area(element.offsetWidth, element.offsetHeight) + ); +} + +export function getMayBecomeVisible(element) { + return !isInsideIframe() || !!getInViewRatioInsideTopFrame(element); +} + +export function getInViewPercentage(element) { + return ratioToPercentageCeil(getInViewRatio(element)); +} + +export function getOffsetTopDocument(element) { + return [...getFrameElements(getElementWindow(element)), element].reduce( + (acc, elem) => merge(acc, getOffset(elem), (a, b) => a + b), + { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + ); +} + +export function getOffsetTopDocumentPercentage(element) { + const elementWindow = getElementWindow(element); + if (!elementWindow) throw new Error('cannot get element window'); + if (!topDocumentIsReachable(elementWindow)) { + throw new Error("top window isn't reachable"); + } + const topWindow = getTopmostReachableWindow(elementWindow); + const documentHeight = getDocumentHeight(topWindow.document); + return ratioToPercentageCeil( + getOffsetTopDocument(element).top / documentHeight + ); +} + +export function getOffsetToView(element) { + const elemWindow = getElementWindow(element); + if (!elemWindow) throw new Error('cannot get element window'); + const topWindow = getTopmostReachableWindow(elemWindow); + const { top, bottom } = getOffsetTopDocument(element); + const topWindowHeight = topWindow.innerHeight; + + if (bottom < topWindow.scrollY) return bottom - topWindow.scrollY; + + if (top > topWindow.scrollY + topWindowHeight) { + return top - topWindow.scrollY - topWindowHeight; + } + + return 0; +} + +export function getOffsetToViewPercentage(element) { + return ratioToPercentageCeil( + getOffsetToView(element) / + getDocumentHeight( + getTopmostReachableWindow(getElementWindow(element)).document + ) + ); +} + +export function getViewabilityDescription(element) { + let iframeType; + try { + if (!element) { + return { + error: 'no element' + }; + } + iframeType = getIframeType(getElementWindow(element)); + if (!iframeType || iframeType === IframeType.friendly) { + const inViewPercentage = getInViewPercentage(element); + return { + inView: inViewPercentage, + hidden: !inViewPercentage && !getMayBecomeVisible(element), + offsetTop: getOffsetTopDocumentPercentage(element), + offsetView: getOffsetToViewPercentage(element), + iframeType + }; + } + return { + iframeType + }; + } catch (error) { + return { + iframeType, + error: error.message + }; + } +} + +export function mergeArrays(hashFn, ...args) { + const seen = {}; + const merged = []; + args.forEach(sizes => { + sizes.forEach(size => { + const key = hashFn(size); + if (!(key in seen)) { + seen[key] = true; + merged.push(size); + } }); }); - return responses; + return merged; } -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: SUPPORTED_MEDIA_TYPES, - isBidRequestValid, - buildRequests, - interpretResponse -} +const spec = { + code: 'vi', + supportedMediaTypes: [mediaTypes.VIDEO, mediaTypes.BANNER], + + isBidRequestValid({ adUnitCode, params: { pubId, lang, cat } = {} }) { + return [pubId, lang, cat].every(x => typeof x === 'string'); + }, + + /** + * + * @param bidRequests + * @param bidderRequest + * @return { + * {method: string, + * data: { + imps: { + bidId: string, + adUnitCode: string, + sizes: [[number, number]], + pubId: string, + lang: string, + cat: string, + iframeType: string | undefined, + error: string | null, + inView: number, + offsetTop: number, + offsetView: number, + hidden: boolean, + bidFloor: number + }[], + refererInfo: { + referer: string + reachedTop: boolean, + numIframes: number, + stack: string[] + canonicalUrl: string + } + }, + * options: {withCredentials: boolean, contentType: string}, url: string}} + */ + buildRequests(bidRequests, bidderRequest) { + return { + method: 'POST', + url: 'https://pb.vi-serve.com/prebid/bid', + data: { + refererInfo: bidderRequest.refererInfo, + imps: bidRequests.map( + ({ bidId, adUnitCode, sizes, params, mediaTypes }) => { + const slot = document.getElementById(adUnitCode); + const bannerSizes = get('banner.sizes', mediaTypes); + const playerSize = get('video.playerSize', mediaTypes); + + const sizesToMerge = []; + if (!params.useSizes) { + if (sizes) sizesToMerge.push(sizes); + if (bannerSizes) sizesToMerge.push(bannerSizes); + if (playerSize) sizesToMerge.push(playerSize); + } else if (params.useSizes === 'banner' && bannerSizes) { + sizesToMerge.push(bannerSizes); + } else if (params.useSizes === 'video' && playerSize) { + sizesToMerge.push(playerSize); + } + return { + bidId, + adUnitCode, + sizes: mergeArrays(x => x.join(','), ...sizesToMerge), + ...getViewabilityDescription(slot), + ...params + }; + } + ) + }, + options: { + contentType: 'application/json', + withCredentials: true + } + }; + }, + interpretResponse({ body }) { + return body; + } +}; registerBidder(spec); diff --git a/modules/viBidAdapter.md b/modules/viBidAdapter.md index 23288024fcc..2608ccc4adb 100644 --- a/modules/viBidAdapter.md +++ b/modules/viBidAdapter.md @@ -38,4 +38,5 @@ var adUnits = [{ | `lang` | required | Ad language, in ISO 639-1 language code format | 'en-US', 'es-ES', 'de' | | `cat` | required | Ad IAB category (top-level or subcategory), single one supported | 'IAB1', 'IAB9-1' | | `bidFloor` | optional | Lowest value of expected bid price | 0.001 | +| `useSizes` | optional | Specifies from which section of the config sizes are taken, possible values are 'banner', 'video'. If omitted, sizes from both sections are merged. | 'banner' | diff --git a/test/spec/modules/viBidAdapter_spec.js b/test/spec/modules/viBidAdapter_spec.js index 2468da0cfaf..b12d534ff02 100644 --- a/test/spec/modules/viBidAdapter_spec.js +++ b/test/spec/modules/viBidAdapter_spec.js @@ -1,139 +1,894 @@ -import { expect } from 'chai'; -import { spec } from 'modules/viBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; - -const ENDPOINT = `//pb.vi-serve.com/prebid/bid`; - -describe('viBidAdapter', function() { - newBidder(spec); - - describe('isBidRequestValid', function () { - let bid = { - 'bidder': 'vi', - 'params': { - 'pubId': 'sb_test', - 'lang': 'en-US', - 'cat': 'IAB1', - 'bidFloor': 0.05 - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [320, 480] - ], - 'bidId': '29b891ad542377', - 'bidderRequestId': '1dc9a08206a57b', - 'requestId': '24176695-e3f0-44db-815b-ed97cf5ad49b', - 'placementCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '474da635-9cf0-4188-a3d9-58961be8f905' - }; +import { + ratioToPercentageCeil, + merge, + getDocumentHeight, + getOffset, + getWindowParents, + getRectCuts, + getTopmostReachableWindow, + topDocumentIsReachable, + isInsideIframe, + isInsideSafeframe, + getIframeType, + getFrameElements, + getElementCuts, + getInViewRatio, + getMayBecomeVisible, + getInViewPercentage, + getInViewRatioInsideTopFrame, + getOffsetTopDocument, + getOffsetTopDocumentPercentage, + getOffsetToView, + getOffsetToViewPercentage, + area, + get, + getViewabilityDescription, + mergeArrays +} from 'modules/viBidAdapter'; - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); +describe('ratioToPercentageCeil', () => { + it('1 converts to percentage', () => + expect(ratioToPercentageCeil(0.01)).to.equal(1)); + it('2 converts to percentage', () => + expect(ratioToPercentageCeil(0.00000000001)).to.equal(1)); + it('3 converts to percentage', () => + expect(ratioToPercentageCeil(0.5)).to.equal(50)); + it('4 converts to percentage', () => + expect(ratioToPercentageCeil(1)).to.equal(100)); + it('5 converts to percentage', () => + expect(ratioToPercentageCeil(0.99)).to.equal(99)); + it('6 converts to percentage', () => + expect(ratioToPercentageCeil(0.990000000000001)).to.equal(100)); +}); - it('should return false when pubId not passed', function () { - bid.params.pubId = undefined; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); +describe('merge', () => { + it('merges two objects', () => { + expect( + merge({ a: 1, b: 2, d: 0 }, { a: 2, b: 2, c: 3 }, (a, b) => a + b) + ).to.deep.equal({ a: 3, b: 4, c: 3, d: 0 }); }); +}); - describe('buildRequests', function () { - let bidRequests = [{ - 'bidder': 'vi', - 'params': { - 'pubId': 'sb_test', - 'lang': 'en-US', - 'cat': 'IAB1', - 'bidFloor': 0.05 +describe('getDocumentHeight', () => { + [ + { + curDocument: { + body: { + clientHeight: 0, + offsetHeight: 0, + scrollHeight: 0 + }, + documentElement: { + clientHeight: 0, + offsetHeight: 0, + scrollHeight: 0 + } }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [320, 480] - ], - 'bidId': '29b891ad542377', - 'bidderRequestId': '1dc9a08206a57b', - 'requestId': '24176695-e3f0-44db-815b-ed97cf5ad49b', - 'placementCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '474da635-9cf0-4188-a3d9-58961be8f905' - }]; - - const request = spec.buildRequests(bidRequests); - - it('POST bid request to vi', function () { - expect(request.method).to.equal('POST'); - }); + expected: 0 + }, + { + curDocument: { + body: { + clientHeight: 0, + offsetHeight: 13, + scrollHeight: 24 + }, + documentElement: { + clientHeight: 0, + offsetHeight: 0, + scrollHeight: 0 + } + }, + expected: 24 + }, + { + curDocument: { + body: { + clientHeight: 0, + offsetHeight: 13, + scrollHeight: 24 + }, + documentElement: { + clientHeight: 100, + offsetHeight: 50, + scrollHeight: 30 + } + }, + expected: 100 + } + ].forEach(({ curDocument, expected }) => + expect(getDocumentHeight(curDocument)).to.be.equal(expected) + ); +}); - it('check endpoint URL', function () { - expect(request.url).to.equal(ENDPOINT) - }); +describe('getOffset', () => { + [ + { + element: { + ownerDocument: { + defaultView: { + pageXOffset: 0, + pageYOffset: 0 + } + }, + getBoundingClientRect: () => ({ + top: 0, + right: 0, + bottom: 0, + left: 0 + }) + }, + expected: { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } + ].forEach(({ description, element, expected }, i) => + it( + 'returns element offsets from the document edges (including scroll): ' + + i, + () => expect(getOffset(element)).to.be.deep.equal(expected) + ) + ); + it('Throws when there is no window', () => + expect( + getOffset.bind(null, { + ownerDocument: { + defaultView: null + }, + getBoundingClientRect: () => ({ + top: 0, + right: 0, + bottom: 0, + left: 0 + }) + }) + ).to.throw()); +}); + +describe('getWindowParents', () => { + const win = {}; + win.top = win; + win.parent = win; + const win1 = { top: win, parent: win }; + const win2 = { top: win, parent: win1 }; + const win3 = { top: win, parent: win2 }; + + it('get parents up to the top', () => + expect(getWindowParents(win3)).to.be.deep.equal([win2, win1, win])); +}); + +describe('getTopmostReachableWindow', () => { + const win = {}; + win.top = win; + win.parent = win; + const win1 = { top: win, parent: win }; + const win2 = { top: win, parent: win1 }; + const win3 = { top: win, parent: win2 }; + + it('get parents up to the top', () => + expect(getTopmostReachableWindow(win3)).to.be.equal(win)); +}); + +const topWindow = { document, frameElement: 0 }; +topWindow.top = topWindow; +topWindow.parent = topWindow; +const topFrameElement = { + ownerDocument: { + defaultView: topWindow + } +}; +const frameWindow1 = { + top: topWindow, + parent: topWindow, + frameElement: topFrameElement +}; +const frameElement1 = { + ownerDocument: { + defaultView: frameWindow1 + } +}; +const frameWindow2 = { + top: topWindow, + parent: frameWindow1, + frameElement: frameElement1 +}; +const frameElement2 = { + ownerDocument: { + defaultView: frameWindow2 + } +}; +const frameWindow3 = { + top: topWindow, + parent: frameWindow2, + frameElement: frameElement2 +}; + +describe('topDocumentIsReachable', () => { + it('returns true if it no inside iframe', () => + expect(topDocumentIsReachable(topWindow)).to.be.true); + it('returns true if it can access top document', () => + expect(topDocumentIsReachable(frameWindow3)).to.be.true); +}); + +describe('isInsideIframe', () => { + it('returns true if window !== window.top', () => + expect(isInsideIframe(topWindow)).to.be.false); + it('returns true if window !== window.top', () => + expect(isInsideIframe(frameWindow1)).to.be.true); +}); + +const safeframeWindow = { $sf: {} }; + +describe('isInsideSafeframe', () => { + it('returns true if top window is not reachable and window.$sf is defined', () => + expect(isInsideSafeframe(safeframeWindow)).to.be.true); +}); + +const hostileFrameWindow = {}; + +describe('getIframeType', () => { + it('returns undefined when is not inside iframe', () => + expect(getIframeType(topWindow)).to.be.undefined); + it("returns 'safeframe' when inside sf", () => + expect(getIframeType(safeframeWindow)).to.be.equal('safeframe')); + it("returns 'friendly' when inside friendly iframe and can reach top window", () => + expect(getIframeType(frameWindow3)).to.be.equal('friendly')); + it("returns 'nonfriendly' when cannot get top window", () => + expect(getIframeType(hostileFrameWindow)).to.be.equal('nonfriendly')); +}); + +describe('getFrameElements', () => { + it('it returns a list iframe elements up to the top, topmost goes first', () => { + expect(getFrameElements(frameWindow3)).to.be.deep.equal([ + topFrameElement, + frameElement1, + frameElement2 + ]); + }); +}); + +describe('area', () => { + it('calculates area', () => expect(area(10, 10)).to.be.equal(100)); + it('calculates area', () => + expect( + area(10, 10, { top: -2, left: -2, bottom: 0, right: 0 }) + ).to.be.equal(64)); +}); + +describe('getElementCuts', () => { + it('returns element cuts', () => + expect( + getElementCuts({ + getBoundingClientRect() { + return { + top: 0, + right: 200, + bottom: 200, + left: 0 + }; + }, + ownerDocument: { + defaultView: { + innerHeight: 1000, + innerWidth: 1000 + } + } + }) + ).to.be.deep.equal({ + top: 0, + right: 0, + bottom: 0, + left: 0 + })); +}); + +describe('getInViewRatio', () => { + it('returns inViewRatio', () => + expect( + getInViewRatio({ + ownerDocument: { + defaultView: { + innerHeight: 1000, + innerWidth: 1000 + } + }, + offsetWidth: 200, + offsetHeight: 200, + getBoundingClientRect() { + return { + top: 0, + right: 200, + bottom: 200, + left: 0 + }; + } + }) + ).to.be.deep.equal(1)); +}); + +describe('getMayBecomeVisible', () => { + it('returns true if not inside iframe of visible inside the iframe', () => + expect( + getMayBecomeVisible({ + ownerDocument: { + defaultView: { + innerHeight: 1000, + innerWidth: 1000 + } + }, + offsetWidth: 200, + offsetHeight: 200, + getBoundingClientRect() { + return { + top: 0, + right: 200, + bottom: 200, + left: 0 + }; + } + }) + ).to.be.true); +}); + +describe('getInViewPercentage', () => { + it('returns inViewRatioPercentage', () => + expect( + getInViewPercentage({ + ownerDocument: { + defaultView: { + innerHeight: 1000, + innerWidth: 1000 + } + }, + offsetWidth: 200, + offsetHeight: 200, + getBoundingClientRect() { + return { + top: 0, + right: 200, + bottom: 200, + left: 0 + }; + } + }) + ).to.be.deep.equal(100)); +}); + +describe('getInViewRatioInsideTopFrame', () => { + it('returns inViewRatio', () => + expect( + getInViewRatioInsideTopFrame({ + ownerDocument: { + defaultView: { + innerHeight: 1000, + innerWidth: 1000 + } + }, + offsetWidth: 200, + offsetHeight: 200, + getBoundingClientRect() { + return { + top: 0, + right: 200, + bottom: 200, + left: 0 + }; + } + }) + ).to.be.deep.equal(1)); +}); + +describe('getOffsetTopDocument', () => { + it('returns offset relative to the top document', () => + expect( + getOffsetTopDocument({ + ownerDocument: { + defaultView: { + pageXOffset: 0, + pageYOffset: 0 + } + }, + getBoundingClientRect: () => ({ + top: 0, + right: 0, + bottom: 0, + left: 0 + }) + }) + ).to.be.deep.equal({ + top: 0, + right: 0, + bottom: 0, + left: 0 + })); +}); + +describe('getOffsetTopDocumentPercentage', () => { + it('returns offset from the top as a percentage of the page length', () => { + const topWindow = { + pageXOffset: 0, + pageYOffset: 100, + document: { + body: { + clientHeight: 1000 + } + } + }; + topWindow.top = topWindow; + topWindow.parent = topWindow; + expect( + getOffsetTopDocumentPercentage({ + ownerDocument: { + defaultView: topWindow + }, + getBoundingClientRect: () => ({ + top: 100, + right: 0, + bottom: 0, + left: 0 + }) + }) + ).to.be.equal(20); + }); + it('throws when cannot get window', () => + expect(() => + getOffsetTopDocumentPercentage({ + ownerDocument: {} + }) + ).to.throw()); + it("throw when top document isn't reachable", () => { + const topWindow = { ...topWindow, document: null }; + expect(() => + getOffsetTopDocumentPercentage({ + ownerDocument: { + defaultView: { + top: topWindow + } + } + }) + ).to.throw(); }); +}); + +describe('getOffsetToView', () => { + expect( + getOffsetToView({ + ownerDocument: { + defaultView: { + scrollY: 0, + pageXOffset: 0, + pageYOffset: 0 + } + }, + getBoundingClientRect: () => ({ + top: 0, + right: 0, + bottom: 0, + left: 0 + }) + }) + ).to.be.equal(0); +}); - describe('buildRequests can handle size in 1-dim array', function () { - let bidRequests = [{ - 'bidder': 'vi', - 'params': { - 'pubId': 'sb_test', - 'lang': 'en-US', - 'cat': 'IAB1', - 'bidFloor': 0.05 +describe('getOffsetToView', () => { + expect( + getOffsetToViewPercentage({ + ownerDocument: { + defaultView: { + scrollY: 0, + pageXOffset: 0, + pageYOffset: 0, + document: { + body: { + clientHeight: 1000 + } + } + } }, - 'adUnitCode': 'adunit-code', - 'sizes': [320, 480], - 'bidId': '29b891ad542377', - 'bidderRequestId': '1dc9a08206a57b', - 'requestId': '24176695-e3f0-44db-815b-ed97cf5ad49b', - 'placementCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '474da635-9cf0-4188-a3d9-58961be8f905' - }]; - - const request = spec.buildRequests(bidRequests); - - it('POST bid request to vi', function () { - expect(request.method).to.equal('POST'); + getBoundingClientRect: () => ({ + top: 0, + right: 0, + bottom: 0, + left: 0 + }) + }) + ).to.be.equal(0); +}); + +describe('getCuts without vCuts', () => { + const cases = { + 'completely in view 1': { + top: 0, + bottom: 200, + right: 200, + left: 0, + vw: 300, + vh: 300, + expected: { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + }, + 'completely in view 2': { + top: 100, + bottom: 200, + right: 200, + left: 0, + vw: 300, + vh: 300, + expected: { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + }, + 'half cut from the top': { + top: -200, + bottom: 200, + right: 200, + left: 0, + vw: 300, + vh: 300, + expected: { + top: -200, + right: 0, + bottom: 0, + left: 0 + } + }, + 'half cut from the bottom': { + top: 0, + bottom: 600, + right: 200, + left: 0, + vw: 300, + vh: 300, + expected: { + top: 0, + right: 0, + bottom: -300, + left: 0 + } + }, + 'quarter cut from top and bottom': { + top: -25, + bottom: 75, + right: 200, + left: 0, + vw: 300, + vh: 50, + expected: { + top: -25, + right: 0, + bottom: -25, + left: 0 + } + }, + 'out of view top': { + top: -200, + bottom: -5, + right: 200, + left: 0, + vw: 300, + vh: 200, + expected: { + top: -200, + right: 0, + bottom: 0, + left: 0 + } + }, + 'out of view bottom': { + top: 250, + bottom: 500, + right: 200, + left: 0, + vw: 300, + vh: 200, + expected: { + top: 0, + right: 0, + bottom: -300, + left: 0 + } + }, + 'half cut from left': { + top: 0, + bottom: 200, + left: -200, + right: 200, + vw: 300, + vh: 300, + expected: { + top: 0, + right: 0, + bottom: 0, + left: -200 + } + }, + 'half cut from left and top': { + top: -100, + bottom: 100, + left: -200, + right: 200, + vw: 300, + vh: 300, + expected: { + top: -100, + right: 0, + bottom: 0, + left: -200 + } + }, + 'quarter cut from all sides': { + top: -100, + left: -100, + bottom: 300, + right: 300, + vw: 200, + vh: 200, + expected: { + top: -100, + right: -100, + bottom: -100, + left: -100 + } + } + }; + for (let descr in cases) { + it(descr, () => { + const { expected, vh, vw, ...rect } = cases[descr]; + expect(getRectCuts(rect, vh, vw)).to.deep.equal(expected); }); + } +}); - it('check endpoint URL', function () { - expect(request.url).to.equal(ENDPOINT) +describe('getCuts with vCuts', () => { + const cases = { + 'completely in view 1, half-cut viewport from top': { + top: 0, + right: 200, + bottom: 200, + left: 0, + vw: 200, + vh: 200, + vCuts: { + top: -100, + right: 0, + bottom: 0, + left: 0 + }, + expected: { + top: -100, + right: 0, + bottom: 0, + left: 0 + } + }, + 'completely in view 2, half-cut viewport from bottom': { + top: 100, + bottom: 200, + right: 200, + left: 0, + vw: 300, + vh: 300, + vCuts: { + top: 0, + right: 0, + bottom: -150, + left: 0 + }, + expected: { + top: 0, + right: 0, + bottom: -50, + left: 0 + } + }, + 'half cut from the top, 1/3 viewport cut from the bottom': { + top: -200, + bottom: 200, + right: 200, + left: 0, + vw: 300, + vh: 300, + vCuts: { + top: 0, + right: 0, + bottom: -100, + left: 0 + }, + expected: { + top: -200, + right: 0, + bottom: 0, + left: 0 + } + }, + 'half cut from the bottom': { + top: 0, + bottom: 600, + right: 200, + left: 0, + vw: 300, + vh: 300, + expected: { + top: 0, + right: 0, + bottom: -300, + left: 0 + } + }, + 'quarter cut from top and bottom': { + top: -25, + bottom: 75, + right: 200, + left: 0, + vw: 300, + vh: 50, + expected: { + top: -25, + right: 0, + bottom: -25, + left: 0 + } + }, + 'out of view top': { + top: -200, + bottom: -5, + right: 200, + left: 0, + vw: 300, + vh: 200, + expected: { + top: -200, + right: 0, + bottom: 0, + left: 0 + } + }, + 'out of view bottom': { + top: 250, + bottom: 500, + right: 200, + left: 0, + vw: 300, + vh: 200, + expected: { + top: 0, + right: 0, + bottom: -300, + left: 0 + } + }, + 'half cut from left': { + top: 0, + bottom: 200, + left: -200, + right: 200, + vw: 300, + vh: 300, + expected: { + top: 0, + right: 0, + bottom: 0, + left: -200 + } + }, + 'half cut from left and top': { + top: -100, + bottom: 100, + left: -200, + right: 200, + vw: 300, + vh: 300, + expected: { + top: -100, + right: 0, + bottom: 0, + left: -200 + } + }, + 'quarter cut from all sides': { + top: -100, + left: -100, + bottom: 300, + right: 300, + vw: 200, + vh: 200, + expected: { + top: -100, + right: -100, + bottom: -100, + left: -100 + } + } + }; + for (let descr in cases) { + it(descr, () => { + const { expected, vh, vw, vCuts, ...rect } = cases[descr]; + expect(getRectCuts(rect, vh, vw, vCuts)).to.deep.equal(expected); }); - }); + } +}); - describe('interpretResponse', function () { - let response = { - body: [{ - 'id': '29b891ad542377', - 'price': 0.1, - 'width': 320, - 'height': 480, - 'ad': '', - 'creativeId': 'dZsPGv' - }] - }; +describe('get', () => { + it('returns a property in a nested object 1', () => + expect(get(['a'], { a: 1 })).to.equal(1)); + it('returns a property in a nested object 2', () => + expect(get(['a', 'b'], { a: { b: 1 } })).to.equal(1)); + it('returns a property in a nested object 3', () => + expect(get(['a', 'b'], { a: { b: 1 } })).to.equal(1)); + it('returns undefined if property does not exist', () => + expect(get(['a', 'b'], { b: 1 })).to.equal(undefined)); + it('returns undefined if property does not exist', () => + expect(get(['a', 'b'], undefined)).to.equal(undefined)); + it('returns undefined if property does not exist', () => + expect(get(['a', 'b'], 1213)).to.equal(undefined)); + const DEFAULT = -5; + it('returns defaultValue if property does not exist', () => + expect(get(['a', 'b'], { b: 1 }, DEFAULT)).to.equal(DEFAULT)); + it('returns defaultValue if property does not exist', () => + expect(get(['a', 'b'], undefined, DEFAULT)).to.equal(DEFAULT)); + it('returns defaultValue if property does not exist', () => + expect(get(['a', 'b'], 1213, DEFAULT)).to.equal(DEFAULT)); + it('can work with arrays 1', () => expect(get([0, 1], [[1, 2]])).to.equal(2)); + it('can work with arrays 2', () => + expect(get([0, 'a'], [{ a: 42 }])).to.equal(42)); +}); - it('should get the correct bid response', function () { - let expectedResponse = [{ - 'requestId': '29b891ad542377', - 'cpm': 0.1, - 'width': 320, - 'height': 480, - 'creativeId': 'dZsPGv', - 'dealId': null, - 'currency': 'USD', - 'netRevenue': true, - 'mediaType': 'banner', - 'ad': decodeURIComponent(``), - 'ttl': 60000 - }]; - - let result = spec.interpretResponse(response); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); +describe('getViewabilityDescription', () => { + it('returns error when there is no element', () => { + expect(getViewabilityDescription(null)).to.deep.equal({ + error: 'no element' }); - - it('handles empty bid response', function () { - let response = { - body: [] - }; - let result = spec.interpretResponse(response); - expect(result.length).to.equal(0); + }); + it('returns only iframe type for nonfrienly iframe', () => { + expect( + getViewabilityDescription({ + ownerDocument: { + defaultView: {} + } + }) + ).to.deep.equal({ + iframeType: 'nonfriendly' + }); + }); + it('returns only iframe type for safeframe iframe', () => { + expect( + getViewabilityDescription({ + ownerDocument: { + defaultView: { + $sf: true + } + } + }) + ).to.deep.equal({ + iframeType: 'safeframe' }); }); }); + +describe('mergeSizes', () => { + it('merges provides arrays of tuples, leaving only unique', () => { + expect( + mergeArrays(x => x.join(','), [[1, 2], [2, 4]], [[1, 2]]) + ).to.deep.equal([[1, 2], [2, 4]]); + }); + it('merges provides arrays of tuples, leaving only unique', () => { + expect( + mergeArrays( + x => x.join(','), + [[1, 2], [2, 4]], + [[1, 2]], + [[400, 500], [500, 600]] + ) + ).to.deep.equal([[1, 2], [2, 4], [400, 500], [500, 600]]); + }); +}); From 10ec9a599f46502b14ef41bf09173c36c959d7d5 Mon Sep 17 00:00:00 2001 From: Stefano <50023896+bkse-stefanodechicchis@users.noreply.github.com> Date: Tue, 7 May 2019 10:34:12 -0400 Subject: [PATCH 1207/1594] Add bucksense Adapter (#3785) * Add bucksense Adapter * fixed first revision for new Bucksense adapter approval https://circleci.com/gh/prebid/Prebid.js/2365? * fixed second revision for new Bucksense adapter approval from jsnellbaker https://github.com/prebid/Prebid.js/pull/3785 * fixed third revision for new Bucksense adapter approval. https://github.com/prebid/Prebid.js/pull/3785 * fixed 4th revision from jsnellbaker - removed console.log and using utils.logInfo(); - removed bksdebug params; pending issue: - gulp test-coverage still under 80% --- modules/bucksenseBidAdapter.js | 124 +++++++++++++++ modules/bucksenseBidAdapter.md | 38 +++++ test/spec/modules/bucksenseBidAdapter_spec.js | 147 ++++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 modules/bucksenseBidAdapter.js create mode 100644 modules/bucksenseBidAdapter.md create mode 100644 test/spec/modules/bucksenseBidAdapter_spec.js diff --git a/modules/bucksenseBidAdapter.js b/modules/bucksenseBidAdapter.js new file mode 100644 index 00000000000..12a9e287f38 --- /dev/null +++ b/modules/bucksenseBidAdapter.js @@ -0,0 +1,124 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; +import * as utils from '../src/utils'; + +const WHO = 'BKSHBID-005'; +const BIDDER_CODE = 'bucksense'; +const URL = 'https://prebid.bksn.se:445/prebidjs/'; + +export const spec = { + code: BIDDER_CODE, + 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) { + utils.logInfo(WHO + ' isBidRequestValid() - INPUT bid:', bid); + if (bid.bidder !== BIDDER_CODE || typeof bid.params === 'undefined') { + return false; + } + if (typeof bid.params.placementId === 'undefined') { + return false; + } + return true; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (validBidRequests, bidderRequest) { + utils.logInfo(WHO + ' buildRequests() - INPUT validBidRequests:', validBidRequests, 'INPUT bidderRequest:', bidderRequest); + let requests = []; + const len = validBidRequests.length; + for (let i = 0; i < len; i++) { + var bid = validBidRequests[i]; + var params = {}; + for (var key in bid.params) { + if (bid.params.hasOwnProperty(key)) { + params[key] = encodeURI(bid.params[key]); + } + } + delete bid.params; + var sizes = bid.sizes; + delete bid.sizes; + var sendData = { + 'pub_id': location.host, + 'pl_id': '' + params.placementId, + 'secure': (location.protocol === 'https:') ? 1 : 0, + 'href': encodeURI(location.href), + 'bid_id': bid.bidId, + 'params': params, + 'sizes': sizes, + '_bid': bidderRequest + }; + requests.push({ + method: 'POST', + url: URL, + data: sendData + }); + } + utils.logInfo(WHO + ' buildRequests() - requests:', requests); + return requests; + }, + + /** + * 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) { + utils.logInfo(WHO + ' interpretResponse() - INPUT serverResponse:', serverResponse, 'INPUT request:', request); + + const bidResponses = []; + if (serverResponse.body) { + var oResponse = serverResponse.body; + + var sRequestID = oResponse.requestId || ''; + var nCPM = oResponse.cpm || 0; + var nWidth = oResponse.width || 0; + var nHeight = oResponse.height || 0; + var nTTL = oResponse.ttl || 0; + var sCreativeID = oResponse.creativeId || 0; + var sCurrency = oResponse.currency || 'USD'; + var bNetRevenue = oResponse.netRevenue || true; + var sAd = oResponse.ad || ''; + + if (request && sRequestID.length == 0) { + utils.logInfo(WHO + ' interpretResponse() - use RequestID from Placments'); + sRequestID = request.data.bid_id || ''; + } + + if (request && request.data.params.hasOwnProperty('testcpm')) { + utils.logInfo(WHO + ' interpretResponse() - use Test CPM '); + nCPM = request.data.params.testcpm; + } + + let bidResponse = { + requestId: sRequestID, + cpm: nCPM, + width: nWidth, + height: nHeight, + ttl: nTTL, + creativeId: sCreativeID, + currency: sCurrency, + netRevenue: bNetRevenue, + ad: sAd + }; + bidResponses.push(bidResponse); + } else { + utils.logInfo(WHO + ' interpretResponse() - serverResponse not valid'); + } + utils.logInfo(WHO + ' interpretResponse() - return', bidResponses); + return bidResponses; + }, + +}; +registerBidder(spec); diff --git a/modules/bucksenseBidAdapter.md b/modules/bucksenseBidAdapter.md new file mode 100644 index 00000000000..a240a2c31d8 --- /dev/null +++ b/modules/bucksenseBidAdapter.md @@ -0,0 +1,38 @@ +# Overview + +``` +Module Name: Bucksense Bidder Adapter +Module Type: Bidder Adapter +Maintainer: stefano.dechicchis@bucksense.com +``` + +# Description + +Use `bucksense` as bidder. + +`placementId` is required, use the Placement ID received by Bucksense. + + +Module that connects to Example's demand sources + +## AdUnits configuration example +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + bids: [ + { + bidder: "bucksense", + params: { + placementId : 1000 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/bucksenseBidAdapter_spec.js b/test/spec/modules/bucksenseBidAdapter_spec.js new file mode 100644 index 00000000000..17b5c3ceff5 --- /dev/null +++ b/test/spec/modules/bucksenseBidAdapter_spec.js @@ -0,0 +1,147 @@ +import {expect} from 'chai'; +import {spec} from 'modules/bucksenseBidAdapter'; + +describe('Bucksense Adapter', function() { + const BIDDER_CODE = 'bucksense'; + const BID_ID = '12345'; + const PLACE_ID = '1000'; + + function getValidBidObject() { + return { + bidder: BIDDER_CODE, + params: { + placementId: PLACE_ID, + } + } + }; + + describe('isBidRequestValid', function() { + var bid; + + beforeEach(function() { + bid = getValidBidObject(); + }); + + it('returns true when valid bid request is sent', function() { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + + it('returns true when valid test bid request is sent', function() { + bid.params['test'] = 1; + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + + it('returns false when bidder not set to "bucksense"', function() { + bid.bidder = 'dummy'; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + + it('returns false when params not set', function() { + delete bid.params; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', function() { + var bid, bidRequestObj; + + beforeEach(function() { + bid = getValidBidObject(); + bidRequestObj = { + 'bidderCode': 'bucksense', + 'auctionId': '73540558-86cb-4eef-895f-bf99c5353bd7', + 'bidderRequestId': '1feebcb5938c7e', + 'bids': [ + { + 'bidder': 'bucksense', + 'params': { + 'placementId': 1000 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ] + } + }, + 'adUnitCode': 'test-div', + 'transactionId': '52b3ed07-2a09-4f58-a426-75acc7602c96', + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], + 'bidId': '22aecdacdcd773', + 'bidderRequestId': '1feebcb5938c7e', + 'auctionId': '73540558-86cb-4eef-895f-bf99c5353bd7', + 'src': 'client', + 'bidRequestsCount': 1 + } + ], + 'auctionStart': 1557176022728, + 'timeout': 1000, + 'refererInfo': { + 'referer': 'http://stefanod.hera.pe/prebid/?pbjs_debug=true', + 'reachedTop': true, + 'numIframes': 0, + 'stack': [ + 'http://stefanod.hera.pe/prebid/?pbjs_debug=true' + ] + }, + 'start': 1557176022731 + }; + }); + + it('should build a very basic request', function() { + var request = spec.buildRequests([bid], bidRequestObj); + expect(request[0].method).to.equal('POST'); + }); + + it('bidRequest data', function () { + var request = spec.buildRequests([bid], bidRequestObj); + expect(request[0].data).to.exist; + }); + }); + + describe('interpretResponse', function() { + var serverResponse; + var serverRequest; + + beforeEach(function() { + serverRequest = { + 'method': 'POST', + 'url': 'https://prebid.bksn.se:445/prebidjs/', + 'data': { + 'pub_id': 'prebid.org', + 'pl_id': '1000', + 'secure': 0, + 'href': 'http://prebid.org/developers.html', + 'bid_id': '27aaf8e96d9fd5', + 'params': { + 'placementId': '1000' + }, + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ] + } + }; + + serverResponse = { + body: { + 'requestId': '', + 'cpm': 0.3, + 'width': 300, + 'height': 250, + 'ttl': 360, + 'creativeId': 'creative002', + 'currency': 'USD', + 'netRevenue': false, + 'ad': '
    ' + } + }; + }); + + it('should return an array of bid responses', function() { + var responses = spec.interpretResponse(serverResponse, serverRequest); + expect(responses).to.be.an('array').with.length(1); + }); + + it('should return an array of bid responses', function() { + serverResponse = {}; + var responses = spec.interpretResponse(serverResponse, serverRequest); + expect(responses).to.be.an('array').with.length(0); + }); + }); +}); From 7406f1a1bd64e709e07a04ecfbd6cd76173fb9c7 Mon Sep 17 00:00:00 2001 From: VideoReach <49446045+VideoReach@users.noreply.github.com> Date: Tue, 7 May 2019 20:29:41 +0200 Subject: [PATCH 1208/1594] Add Video Reach adapter (#3766) * Add Video Reach adapter * Add Video Reach adapter * Add Video Reach adapter --- modules/videoreachBidAdapter.js | 97 ++++++++++++ modules/videoreachBidAdapter.md | 27 ++++ .../spec/modules/videoreachBidAdapter_spec.js | 141 ++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 modules/videoreachBidAdapter.js create mode 100644 modules/videoreachBidAdapter.md create mode 100644 test/spec/modules/videoreachBidAdapter_spec.js diff --git a/modules/videoreachBidAdapter.js b/modules/videoreachBidAdapter.js new file mode 100644 index 00000000000..03290c9b79c --- /dev/null +++ b/modules/videoreachBidAdapter.js @@ -0,0 +1,97 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +const utils = require('../src/utils'); +const BIDDER_CODE = 'videoreach'; +const ENDPOINT_URL = '//a.videoreach.de/hb/'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['banner'], + + isBidRequestValid: function(bid) { + return !!(bid.params.TagId); + }, + + buildRequests: function(validBidRequests, bidderRequest) { + var data = { + referrer: utils.getTopWindowUrl(), + data: validBidRequests.map(function(bid) { + return { + TagId: utils.getValue(bid.params, 'TagId'), + bidId: utils.getBidIdParameter('bidId', bid), + bidderRequestId: utils.getBidIdParameter('bidderRequestId', bid), + auctionId: utils.getBidIdParameter('auctionId', bid), + transactionId: utils.getBidIdParameter('transactionId', bid) + } + }) + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + data.gdpr = { + consent_string: bidderRequest.gdprConsent.consentString, + consent_required: bidderRequest.gdprConsent.gdprApplies + }; + } + + return { + method: 'POST', + url: ENDPOINT_URL, + data: JSON.stringify(data) + }; + }, + + interpretResponse: function(serverResponse) { + 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: true, + ttl: bid.ttl, + ad: bid.ad, + requestId: bid.bidId, + creativeId: bid.creativeId + }; + bidResponses.push(bidResponse); + }); + } + return bidResponses; + }, + + getUserSyncs: function(syncOptions, responses, gdprConsent) { + const syncs = []; + + if (syncOptions.pixelEnabled && responses.length) { + const SyncPixels = responses[0].body.responses[0].sync; + + let params = ''; + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + if (typeof gdprConsent.gdprApplies === 'boolean') { + params += 'gdpr=' + gdprConsent.gdprApplies + '&gdpr_consent=' + gdprConsent.consentString; + } else { + params += 'gdpr_consent=' + gdprConsent.consentString; + } + } + + var gdpr; + if (SyncPixels) { + SyncPixels.forEach(sync => { + gdpr = (params) ? ((sync.split('?')[1] ? '&' : '?') + params) : ''; + + syncs.push({ + type: 'image', + url: sync + gdpr + }); + }); + } + } + + return syncs; + } +}; + +registerBidder(spec); diff --git a/modules/videoreachBidAdapter.md b/modules/videoreachBidAdapter.md new file mode 100644 index 00000000000..cdd1ecc04c5 --- /dev/null +++ b/modules/videoreachBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +**Module Name**: Video Reach Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: hello@videoreach.de + +# Description + +Video Reach Bidder Adapter for Prebid.js. + +Use `videoreach` as bidder. + +`TagId` ist required. + +## AdUnits configuration example +``` + var adUnits = [{ + code: 'your-slot', //use exactly the same code as your slot div id. + sizes: [[1, 1]], + bids: [{ + bidder: 'videoreach', + params: { + TagId: 'XXXXX' + } + }] + }]; +``` diff --git a/test/spec/modules/videoreachBidAdapter_spec.js b/test/spec/modules/videoreachBidAdapter_spec.js new file mode 100644 index 00000000000..b74a0236551 --- /dev/null +++ b/test/spec/modules/videoreachBidAdapter_spec.js @@ -0,0 +1,141 @@ +import {expect} from 'chai'; +import {spec} from 'modules/videoreachBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT_URL = '//a.videoreach.de/hb/'; + +describe('videoreachBidAdapter', function () { + describe('isBidRequestValid', function () { + let bid = { + 'params': { + 'TagId': 'ABCDE' + }, + 'bidId': '242d506d4e4f15', + 'bidderRequestId': '1893a2136a84a2', + 'auctionId': '8fb7b1c7-317b-4edf-83f0-c4669a318522', + 'transactionId': '85a2e190-0684-4f95-ad32-6c90757ed622' + }; + + 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 = { + 'TagId': '' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'videoreach', + 'params': { + 'TagId': 'ABCDE' + }, + 'adUnitCode': 'adzone', + 'auctionId': '8fb7b1c7-317b-4edf-83f0-c4669a318522', + 'sizes': [[1, 1]], + 'bidId': '242d506d4e4f15', + 'bidderRequestId': '1893a2136a84a2', + 'transactionId': '85a2e190-0684-4f95-ad32-6c90757ed622', + 'mediaTypes': { + 'banner': { + 'sizes': [1, 1] + }, + } + } + ]; + + it('send bid request to endpoint', function () { + const request = spec.buildRequests(bidRequests); + + expect(request.url).to.equal(ENDPOINT_URL); + expect(request.method).to.equal('POST'); + }); + + it('send bid request with GDPR to endpoint', function () { + let consentString = 'BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA'; + + let bidderRequest = { + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.gdpr.consent_required).to.exist; + expect(payload.gdpr.consent_string).to.equal(consentString); + }); + }); + + describe('interpretResponse', function () { + let serverResponse = + { + 'body': { + 'responses': [{ + 'bidId': '242d506d4e4f15', + 'transactionId': '85a2e190-0684-4f95-ad32-6c90757ed622', + 'cpm': 10.0, + 'width': '1', + 'height': '1', + 'ad': '', + 'ttl': 360, + 'creativeId': '5cb5dc9375c0e', + 'netRevenue': true, + 'currency': 'EUR', + 'sync': ['https:\/\/SYNC_URL'] + }] + } + }; + + it('should handle response', function() { + let expectedResponse = [ + { + cpm: 10.0, + width: '1', + height: '1', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: '', + requestId: '242d506d4e4f15', + creativeId: '5cb5dc9375c0e' + } + ]; + + let result = spec.interpretResponse(serverResponse); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('should handles empty response', function() { + let serverResponse = { + 'body': { + 'responses': [] + } + }; + + let result = spec.interpretResponse(serverResponse); + expect(result.length).to.equal(0); + }); + + describe('getUserSyncs', () => { + it('should push user sync images if enabled', () => { + const syncOptions = { pixelEnabled: true }; + const syncs = spec.getUserSyncs(syncOptions, [serverResponse]); + + expect(syncs[0]).to.deep.equal({ + type: 'image', + url: 'https://SYNC_URL' + }); + }) + }); + }); +}); From 7050fb17343650b0fe5a84c382a6b30bb4387d2b Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 7 May 2019 21:39:24 +0200 Subject: [PATCH 1209/1594] onBidWon implementation (#3801) --- modules/adponeBidAdapter.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/adponeBidAdapter.js b/modules/adponeBidAdapter.js index cd30f663b16..2d27c9c4240 100644 --- a/modules/adponeBidAdapter.js +++ b/modules/adponeBidAdapter.js @@ -59,6 +59,13 @@ export const spec = { }); return answer; + }, + + onBidWon: bid => { + const bidString = JSON.stringify(bid); + const encodedBuf = window.btoa(bidString); + const img = new Image(1, 1); + img.src = `https://rtb.adpone.com/prebid/analytics?q=${encodedBuf}`; } }; From 8776afe35b878891bde3018d32f3a0387fa15ea9 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 7 May 2019 15:52:23 -0400 Subject: [PATCH 1210/1594] Prebid 2.14.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 72ddc2e6e53..1a2042b2332 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.14.0-pre", + "version": "2.14.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From f5e6e3aace89534a66e3c3bf19eb4b40186ebdd5 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 7 May 2019 16:11:34 -0400 Subject: [PATCH 1211/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a2042b2332..b772f2eccdb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.14.0", + "version": "2.15.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From bd1636ada243f30c309bd8212e4446d39d86659b Mon Sep 17 00:00:00 2001 From: Mathias Methner Date: Wed, 8 May 2019 07:03:06 +0200 Subject: [PATCH 1212/1594] Orbidder uses onSetTargeting callback (#3804) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons * add bidfloor parameter to params object * fix gdpr object handling * default to consentRequired: false when not explicitly given * wip - use onSetTargeting callback * add tests for onSetTargeting callback --- modules/orbidderBidAdapter.js | 22 ++++++++------ package-lock.json | 30 ++++++++++++++------ test/spec/modules/orbidderBidAdapter_spec.js | 19 +++++++++---- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index fc5eecbab08..1123cc5d50e 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -45,9 +45,7 @@ export const spec = { if (bidderRequest && bidderRequest.gdprConsent) { ret.data.gdprConsent = { consentString: bidderRequest.gdprConsent.consentString, - consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') - ? bidderRequest.gdprConsent.gdprApplies - : true + consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') && bidderRequest.gdprConsent.gdprApplies }; } return ret; @@ -72,15 +70,23 @@ export const spec = { return bidResponses; }, - onBidWon(winObj) { + onBidWon(bid) { + this.onHandler(bid, '/win'); + }, + + onSetTargeting (bid) { + this.onHandler(bid, '/targeting'); + }, + + onHandler (bid, route) { const getRefererInfo = detectReferer(window); - winObj.pageUrl = getRefererInfo().referer; - if (spec.bidParams[winObj.adId]) { - winObj.params = spec.bidParams[winObj.adId]; + bid.pageUrl = getRefererInfo().referer; + if (spec.bidParams[bid.adId]) { + bid.params = spec.bidParams[bid.adId]; } - spec.ajaxCall(`${spec.orbidderHost}/win`, JSON.stringify(winObj)); + spec.ajaxCall(`${spec.orbidderHost}${route}`, JSON.stringify(bid)); }, ajaxCall(endpoint, data) { diff --git a/package-lock.json b/package-lock.json index c3bd739008f..6f908eeba52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.13.0-pre", + "version": "2.14.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -6093,12 +6093,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6113,17 +6115,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6240,7 +6245,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6252,6 +6258,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6266,6 +6273,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6273,12 +6281,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6297,6 +6307,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6377,7 +6388,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6389,6 +6401,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6510,6 +6523,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index bc88090095b..3818f502901 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec} from 'modules/orbidderBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; +import openxAdapter from '../../../modules/openxAnalyticsAdapter'; describe('orbidderBidAdapter', () => { const adapter = newBidder(spec); @@ -107,7 +108,7 @@ describe('orbidderBidAdapter', () => { const request = buildRequest(defaultBidRequest, { gdprConsent: {} }); - expect(request.data.gdprConsent.consentRequired).to.be.equal(true); + expect(request.data.gdprConsent.consentRequired).to.be.equal(false); }); it('handles non-existent gdpr object', () => { @@ -146,9 +147,9 @@ describe('orbidderBidAdapter', () => { }); }); - describe('onBidWon', () => { + describe('onCallbackHandler', () => { let ajaxStub; - const winObj = { + const bidObj = { adId: 'testId', test: 1, pageUrl: 'www.someurl.de', @@ -163,12 +164,18 @@ describe('orbidderBidAdapter', () => { ajaxStub.restore(); }); - it('calls orbidder\'s win endpoint', () => { - spec.onBidWon(winObj); + it('calls orbidder\'s callback endpoint', () => { + spec.onBidWon(bidObj); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0].indexOf('https://')).to.equal(0); expect(ajaxStub.firstCall.args[0]).to.equal(`${spec.orbidderHost}/win`); - expect(ajaxStub.firstCall.args[1]).to.equal(JSON.stringify(winObj)); + expect(ajaxStub.firstCall.args[1]).to.equal(JSON.stringify(bidObj)); + + spec.onSetTargeting(bidObj); + expect(ajaxStub.calledTwice).to.equal(true); + expect(ajaxStub.secondCall.args[0].indexOf('https://')).to.equal(0); + expect(ajaxStub.secondCall.args[0]).to.equal(`${spec.orbidderHost}/targeting`); + expect(ajaxStub.secondCall.args[1]).to.equal(JSON.stringify(bidObj)); }); }); From ad7b59d62b89da45b638e23d74d96df5f043d03c Mon Sep 17 00:00:00 2001 From: imonomy <49719148+imonomy@users.noreply.github.com> Date: Thu, 9 May 2019 20:30:11 +0300 Subject: [PATCH 1213/1594] Add Imonomy network BidAdapter (#3765) * Add Imonomy network BidAdapter * add changes due to the comments on Prebid --- modules/imonomyBidAdapter.js | 130 ++++++++++++++++ modules/imonomyBidAdapter.md | 29 ++++ test/spec/modules/imonomyBidAdapter_spec.js | 164 ++++++++++++++++++++ 3 files changed, 323 insertions(+) create mode 100644 modules/imonomyBidAdapter.js create mode 100644 modules/imonomyBidAdapter.md create mode 100644 test/spec/modules/imonomyBidAdapter_spec.js diff --git a/modules/imonomyBidAdapter.js b/modules/imonomyBidAdapter.js new file mode 100644 index 00000000000..fa3ad0cfea2 --- /dev/null +++ b/modules/imonomyBidAdapter.js @@ -0,0 +1,130 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'imonomy'; +const ENDPOINT = '//b.imonomy.com/openrtb/hb/00000'; +const USYNCURL = '//b.imonomy.com/UserMatching/b/'; + +export const spec = { + code: BIDDER_CODE, + + /** + * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid + * + * @param {BidRequest} bid The bid params to validate. + * @return {boolean} True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: bid => { + return !!(bid && bid.params && bid.params.placementId && bid.params.hbid); + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: validBidRequests => { + const tags = validBidRequests.map(bid => { + // map each bid id to bid object to retrieve adUnit code in callback + let tag = { + uuid: bid.bidId, + sizes: bid.sizes, + trid: bid.transactionId, + hbid: bid.params.hbid, + placementid: bid.params.placementId + }; + + // add floor price if specified (not mandatory) + if (bid.params.floorPrice) { + tag.floorprice = bid.params.floorPrice; + } + + return tag; + }); + + // Imonomy server config + const time = new Date().getTime(); + const kbConf = { + ts_as: time, + hb_placements: [], + hb_placement_bidids: {}, + hb_floors: {}, + cb: _generateCb(time), + tz: new Date().getTimezoneOffset(), + }; + + validBidRequests.forEach(bid => { + kbConf.hdbdid = kbConf.hdbdid || bid.params.hbid; + kbConf.encode_bid = kbConf.encode_bid || bid.params.encode_bid; + kbConf.hb_placement_bidids[bid.params.placementId] = bid.bidId; + if (bid.params.floorPrice) { + kbConf.hb_floors[bid.params.placementId] = bid.params.floorPrice; + } + kbConf.hb_placements.push(bid.params.placementId); + }); + + let payload = {}; + if (!utils.isEmpty(tags)) { + payload = { bids: [...tags], kbConf }; + } + + let endpointToUse = ENDPOINT; + if (kbConf.hdbdid) { + endpointToUse = endpointToUse.replace('00000', kbConf.hdbdid); + } + + return { + method: 'POST', + url: endpointToUse, + data: JSON.stringify(payload) + }; + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} response A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: (response) => { + const bidResponses = []; + if (response && response.body && response.body.bids) { + response.body.bids.forEach(bid => { + // The bid ID. Used to tie this bid back to the request. + if (bid.uuid) { + bid.requestId = bid.uuid; + } else { + utils.logError('No uuid for bid'); + } + // The creative payload of the returned bid. + if (bid.creative) { + bid.ad = bid.creative; + } else { + utils.logError('No creative for bid'); + } + bidResponses.push(bid); + }); + } + return bidResponses; + }, + /** + * Register User Sync. + */ + getUserSyncs: syncOptions => { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: USYNCURL + }]; + } + } +}; + +/** +* Generated cache baster value to be sent to bid server +* @param {*} time current time to use for creating cb. +*/ +function _generateCb(time) { + return Math.floor((time % 65536) + (Math.floor(Math.random() * 65536) * 65536)); +} + +registerBidder(spec); diff --git a/modules/imonomyBidAdapter.md b/modules/imonomyBidAdapter.md new file mode 100644 index 00000000000..451eb0994d8 --- /dev/null +++ b/modules/imonomyBidAdapter.md @@ -0,0 +1,29 @@ +# Overview + +**Module Name**: Imonomy Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: support@imonomy.com + +# Description + +Connects to Imonomy demand source to fetch bids. + +# Test Parameters +``` + var adUnits = [{ + code: 'banner-ad-div', + sizes: [[300, 250]], + + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'imonomy', + params: { + placementId: 'e69148e0ba6c4c07977dc2daae5e1577', + hbid: '14567718624', + floorPrice: 0.5 + } + }] + }]; +``` + + diff --git a/test/spec/modules/imonomyBidAdapter_spec.js b/test/spec/modules/imonomyBidAdapter_spec.js new file mode 100644 index 00000000000..206e227a3b1 --- /dev/null +++ b/test/spec/modules/imonomyBidAdapter_spec.js @@ -0,0 +1,164 @@ +import { expect } from 'chai'; +import { spec } from 'modules/imonomyBidAdapter'; + +describe('Imonomy Adapter Tests', function () { + const bidsRequest = [ + { + bidder: 'imonomy', + params: { + placementId: '170577', + hbid: '14567718624', + }, + placementCode: 'div-gpt-ad-1460505748561-0', + transactionId: '9f801c02-bbe8-4683-8ed4-bc816ea186bb', + sizes: [ + [300, 250] + ], + bidId: '2faedf1095f815', + bidderRequestId: '18065867f8ae39', + auctionId: '529e1518-b872-45cf-807c-2d41dfa5bcd3' + }, + { + bidder: 'imonomy', + params: { + placementId: '281277', + hbid: '14567718624', + floorPrice: 0.5 + }, + placementCode: 'div-gpt-ad-1460505748561-0', + transactionId: '9f801c02-bbe8-4683-8ed4-bc816ea186bb', + sizes: [ + [728, 90] + ], + bidId: '3c34e2367a3f59', + bidderRequestId: '18065867f8ae39', + auctionId: '529e1518-b872-45cf-807c-2d41dfa5bcd3' + }]; + + const bidsResponse = { + body: { + bids: [ + { + placementid: '170577', + uuid: '2faedf1095f815', + width: 300, + height: 250, + cpm: 0.51, + creative: '', + ttl: 360, + currency: 'USD', + netRevenue: true, + creativeId: 'd30b58c2ba' + } + ] + } + }; + + it('Verifies imonomyAdapter bidder code', function () { + expect(spec.code).to.equal('imonomy'); + }); + + it('Verifies imonomyAdapter bid request validation', function () { + expect(spec.isBidRequestValid(bidsRequest[0])).to.equal(true); + expect(spec.isBidRequestValid(bidsRequest[1])).to.equal(true); + expect(spec.isBidRequestValid({})).to.equal(false); + expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect(spec.isBidRequestValid({ params: { hbid: 12345 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { placementid: 12345 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { hbid: 12345, placementId: 67890 } })).to.equal(true); + expect(spec.isBidRequestValid({ params: { hbid: 12345, placementId: 67890, floorPrice: 0.8 } })).to.equal(true); + }); + + it('Verify imonomyAdapter build request', function () { + var startTime = new Date().getTime(); + + const request = spec.buildRequests(bidsRequest); + expect(request.url).to.equal('//b.imonomy.com/openrtb/hb/14567718624'); + expect(request.method).to.equal('POST'); + const requestData = JSON.parse(request.data); + + // bids object + let bids = requestData.bids; + expect(bids).to.have.lengthOf(2); + + // first bid request: no floor price + expect(bids[0].uuid).to.equal('2faedf1095f815'); + expect(bids[0].floorprice).to.be.undefined; + expect(bids[0].placementid).to.equal('170577'); + expect(bids[0].hbid).to.equal('14567718624'); + expect(bids[0].trid).to.equal('9f801c02-bbe8-4683-8ed4-bc816ea186bb'); + expect(bids[0].sizes).to.have.lengthOf(1); + expect(bids[0].sizes[0][0]).to.equal(300); + expect(bids[0].sizes[0][1]).to.equal(250); + + // second bid request: with floor price + expect(bids[1].uuid).to.equal('3c34e2367a3f59'); + expect(bids[1].floorprice).to.equal(0.5); + expect(bids[1].placementid).to.equal('281277'); + expect(bids[1].hbid).to.equal('14567718624'); + expect(bids[1].trid).to.equal('9f801c02-bbe8-4683-8ed4-bc816ea186bb'); + expect(bids[1]).to.have.property('sizes') + .that.is.an('array') + .of.length(1) + .that.deep.equals([[728, 90]]); + + // kbConf object + let kbConf = requestData.kbConf; + expect(kbConf.hdbdid).to.equal(bids[0].hbid); + expect(kbConf.hdbdid).to.equal(bids[1].hbid); + expect(kbConf.encode_bid).to.be.undefined; + // kbConf timezone and cb + expect(kbConf.cb).not.to.be.undefined; + expect(kbConf.ts_as).to.be.above(startTime - 1); + expect(kbConf.tz).to.equal(new Date().getTimezoneOffset()); + // kbConf bid ids + expect(kbConf.hb_placement_bidids) + .to.have.property(bids[0].placementid) + .that.equal(bids[0].uuid); + expect(kbConf.hb_placement_bidids) + .to.have.property(bids[1].placementid) + .that.equal(bids[1].uuid); + // kbConf floor price + expect(kbConf.hb_floors).not.to.have.property(bids[0].placementid) + expect(kbConf.hb_floors).to.have.property(bids[1].placementid).that.equal(bids[1].floorprice); + // kbConf placement ids + expect(kbConf.hb_placements).to.have.lengthOf(2); + expect(kbConf.hb_placements[0]).to.equal(bids[0].placementid); + expect(kbConf.hb_placements[1]).to.equal(bids[1].placementid); + }); + + it('Verify imonomyAdapter build response', function () { + const request = spec.buildRequests(bidsRequest); + const bids = spec.interpretResponse(bidsResponse, request); + + // 'server' return single bid + expect(bids).to.have.lengthOf(1); + + // verify bid object + const bid = bids[0]; + const responseBids = bidsResponse.body.bids; + + expect(bid.cpm).to.equal(responseBids[0].cpm); + expect(bid.ad).to.equal(responseBids[0].creative); + expect(bid.requestId).equal(responseBids[0].uuid); + expect(bid.uuid).equal(responseBids[0].uuid); + expect(bid.width).to.equal(responseBids[0].width); + expect(bid.height).to.equal(responseBids[0].height); + expect(bid.ttl).to.equal(responseBids[0].ttl); + expect(bid.currency).to.equal('USD'); + expect(bid.netRevenue).to.equal(true); + expect(bid.creativeId).to.equal(responseBids[0].creativeId); + }); + + it('Verifies imonomyAdapter sync options', function () { + // user sync disabled + expect(spec.getUserSyncs({})).to.be.undefined; + expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; + // user sync enabled + const options = spec.getUserSyncs({ iframeEnabled: true }); + expect(options).to.not.be.undefined; + expect(options).to.have.lengthOf(1); + expect(options[0].type).to.equal('iframe'); + expect(options[0].url).to.equal('//b.imonomy.com/UserMatching/b/'); + }); +}); From f78b8e96cfbc459963b8b03308896fc9af7e9312 Mon Sep 17 00:00:00 2001 From: sumit116 Date: Fri, 10 May 2019 20:15:36 +0530 Subject: [PATCH 1214/1594] Rad 2751/specify ad units set targeting for ast (#3805) * add adUnitCodes as param for setTargetingForAst() * unit tests for setTargetingForAst * refactor * Revert "refactor" This reverts commit 1a89d024cb561f44cc59fe85d3f0adea11e24381. * refactor to add more tests --- src/targeting.js | 2 +- test/spec/unit/core/targeting_spec.js | 40 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/targeting.js b/src/targeting.js index 6caa4029c9c..4ac993cf94a 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -255,7 +255,7 @@ export function newTargeting(auctionManager) { let astTargeting = targeting.getAllTargeting(adUnitCodes); try { - targeting.resetPresetTargetingAST(); + targeting.resetPresetTargetingAST(adUnitCodes); } catch (e) { utils.logError('unable to reset targeting for AST' + e) } diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 13ebfd7dc4e..727c790c991 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -326,4 +326,44 @@ describe('targeting tests', function () { }); }); }); + + describe('setTargetingForAst', function () { + let sandbox, + apnTagStub; + beforeEach(function() { + sandbox = sinon.createSandbox(); + sandbox.stub(targetingInstance, 'resetPresetTargetingAST'); + apnTagStub = sandbox.stub(window.apntag, 'setKeywords'); + }); + afterEach(function () { + sandbox.restore(); + }); + + it('should set single addUnit code', function() { + let adUnitCode = 'testdiv-abc-ad-123456-0'; + sandbox.stub(targetingInstance, 'getAllTargeting').returns({ + 'testdiv1-abc-ad-123456-0': {hb_bidder: 'appnexus'} + }); + targetingInstance.setTargetingForAst(adUnitCode); + expect(targetingInstance.getAllTargeting.called).to.equal(true); + expect(targetingInstance.resetPresetTargetingAST.called).to.equal(true); + expect(apnTagStub.callCount).to.equal(1); + expect(apnTagStub.getCall(0).args[0]).to.deep.equal('testdiv1-abc-ad-123456-0'); + expect(apnTagStub.getCall(0).args[1]).to.deep.equal({HB_BIDDER: 'appnexus'}); + }); + + it('should set array of addUnit codes', function() { + let adUnitCodes = ['testdiv1-abc-ad-123456-0', 'testdiv2-abc-ad-123456-0'] + sandbox.stub(targetingInstance, 'getAllTargeting').returns({ + 'testdiv1-abc-ad-123456-0': {hb_bidder: 'appnexus'}, + 'testdiv2-abc-ad-123456-0': {hb_bidder: 'appnexus'} + }); + targetingInstance.setTargetingForAst(adUnitCodes); + expect(targetingInstance.getAllTargeting.called).to.equal(true); + expect(targetingInstance.resetPresetTargetingAST.called).to.equal(true); + expect(apnTagStub.callCount).to.equal(2); + expect(apnTagStub.getCall(1).args[0]).to.deep.equal('testdiv2-abc-ad-123456-0'); + expect(apnTagStub.getCall(1).args[1]).to.deep.equal({HB_BIDDER: 'appnexus'}); + }); + }); }); From ed21da1a4adc2a9bf6eda6327c9970862011608f Mon Sep 17 00:00:00 2001 From: werowe Date: Mon, 13 May 2019 14:47:26 +0200 Subject: [PATCH 1215/1594] fixed misspelled word (#3816) fixed spelled of installd to installed --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f802efecfcf..21e02ebee7f 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ prebid.requestBids({ *Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To compily with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in it's setup. -If you have a previous version of `gulp` installed globally, you'll need to remove it before installing `gulp-cli`. You can check if this is installed by running `gulp -v` and seeing the version that's listed in the `CLI` field of the output. If you have the `gulp` package installd globally, it's likely the same version that you'll see in the `Local` field. If you already have `gulp-cli` installed, it should be a lower major version (it's at version `2.0.1` at the time of the transition). +If you have a previous version of `gulp` installed globally, you'll need to remove it before installing `gulp-cli`. You can check if this is installed by running `gulp -v` and seeing the version that's listed in the `CLI` field of the output. If you have the `gulp` package installed globally, it's likely the same version that you'll see in the `Local` field. If you already have `gulp-cli` installed, it should be a lower major version (it's at version `2.0.1` at the time of the transition). To remove the old package, you can use the command: `npm rm gulp -g` From acd3077136fef7f672ffba9ee404a5fac48f599c Mon Sep 17 00:00:00 2001 From: Rich Audience Date: Mon, 13 May 2019 16:23:07 +0200 Subject: [PATCH 1216/1594] RichAudience: Files name updated (#3793) * Files name updated * uploading bidder --- .../{richAudienceBidAdapter.js => richaudienceBidAdapter.js} | 0 .../{richAudienceBidAdapter.md => richaudienceBidAdapter.md} | 0 ...enceBidAdapter_spec.js => richaudienceBidAdapter_spec.js} | 5 ++--- 3 files changed, 2 insertions(+), 3 deletions(-) rename modules/{richAudienceBidAdapter.js => richaudienceBidAdapter.js} (100%) rename modules/{richAudienceBidAdapter.md => richaudienceBidAdapter.md} (100%) rename test/spec/modules/{richAudienceBidAdapter_spec.js => richaudienceBidAdapter_spec.js} (98%) diff --git a/modules/richAudienceBidAdapter.js b/modules/richaudienceBidAdapter.js similarity index 100% rename from modules/richAudienceBidAdapter.js rename to modules/richaudienceBidAdapter.js diff --git a/modules/richAudienceBidAdapter.md b/modules/richaudienceBidAdapter.md similarity index 100% rename from modules/richAudienceBidAdapter.md rename to modules/richaudienceBidAdapter.md diff --git a/test/spec/modules/richAudienceBidAdapter_spec.js b/test/spec/modules/richaudienceBidAdapter_spec.js similarity index 98% rename from test/spec/modules/richAudienceBidAdapter_spec.js rename to test/spec/modules/richaudienceBidAdapter_spec.js index c974ff70ce3..16d67ce7ceb 100644 --- a/test/spec/modules/richAudienceBidAdapter_spec.js +++ b/test/spec/modules/richaudienceBidAdapter_spec.js @@ -1,13 +1,12 @@ // 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/richAudienceBidAdapter'; import { spec -} from 'modules/richAudienceBidAdapter'; +} from 'modules/richaudienceBidAdapter'; import {config} from 'src/config'; import * as utils from 'src/utils'; -describe('Rich Audience adapter tests', function () { +describe('Richaudience adapter tests', function () { var DEFAULT_PARAMS = [{ adUnitCode: 'test-div', bidId: '2c7c8e9c900244', From 6b8d0873a3370aa64ebdb8ed72a98be2821a24f4 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Mon, 13 May 2019 17:46:16 +0200 Subject: [PATCH 1217/1594] Improve Digital adapter: Endpoint update (#3811) * Adding GDPR support * Always drop user syncs when available * Set dealID based on buying type * Native ads, single request option * Send ad unit sizes to Improve ad server * adapter version -> 5.1 * Adding usePrebidSizes config param * New ad server endpoint --- modules/improvedigitalBidAdapter.js | 4 ++-- .../modules/improvedigitalBidAdapter_spec.js | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index fdfe5970572..0c9028133e0 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -271,10 +271,10 @@ export function ImproveDigitalAdServerJSClient(endPoint) { STANDARD: 0, SECURE: 1 }, - AD_SERVER_BASE_URL: 'ad.360yield.com', + AD_SERVER_BASE_URL: 'ice.360yield.com', END_POINT: endPoint || 'hb', AD_SERVER_URL_PARAM: 'jsonp=', - CLIENT_VERSION: 'JS-5.3.0', + CLIENT_VERSION: 'JS-6.0.0', MAX_URL_LENGTH: 2083, ERROR_CODES: { MISSING_PLACEMENT_PARAMS: 2, diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 61ba56ab822..6c78afca6b2 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -7,7 +7,7 @@ describe('Improve Digital Adapter Tests', function () { let idClient = new ImproveDigitalAdServerJSClient('hb'); const METHOD = 'GET'; - const URL = '//ad.360yield.com/hb'; + const URL = '//ice.360yield.com/hb'; const PARAM_PREFIX = 'jsonp='; const simpleBidRequest = { @@ -224,7 +224,7 @@ describe('Improve Digital Adapter Tests', function () { 'id': '33e9500b21129f', 'advid': '5279', 'price': 1.45888594164456, - 'nurl': 'http://ad.360yield.com/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', + 'nurl': 'http://ice.360yield.com/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', 'h': 290, 'pid': 1053688, 'sync': [ @@ -234,7 +234,7 @@ describe('Improve Digital Adapter Tests', function () { 'crid': '422031', 'w': 600, 'cid': '99006', - 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' + 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' } ], 'debug': '' @@ -261,7 +261,7 @@ describe('Improve Digital Adapter Tests', function () { 'crid': '422033', 'w': 700, 'cid': '99006', - 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' + 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' } ], 'debug': '' @@ -278,7 +278,7 @@ describe('Improve Digital Adapter Tests', function () { id: '33e9500b21129f', advid: '5279', price: 1.45888594164456, - nurl: 'http://ad.360yield.com/imp_pixel?ic=wVm', + nurl: 'http://ice.360yield.com/imp_pixel?ic=wVm', h: 290, pid: 1053688, sync: [ @@ -365,7 +365,7 @@ describe('Improve Digital Adapter Tests', function () { describe('interpretResponse', function () { let expectedBid = [ { - 'ad': '', + 'ad': '', 'adId': '33e9500b21129f', 'creativeId': '422031', 'cpm': 1.45888594164456, @@ -382,7 +382,7 @@ describe('Improve Digital Adapter Tests', function () { let expectedTwoBids = [ expectedBid[0], { - 'ad': '', + 'ad': '', 'adId': '1234', 'creativeId': '422033', 'cpm': 1.23, @@ -426,7 +426,7 @@ describe('Improve Digital Adapter Tests', function () { clickUrl: 'http://advertiser.com', clickTrackers: ['http://click.tracker.com/click?impid=123'], impressionTrackers: [ - 'http://ad.360yield.com/imp_pixel?ic=wVm', + 'http://ice.360yield.com/imp_pixel?ic=wVm', 'http://imptrack1.com', 'http://imptrack2.com' ], From 54ac989fec68e421c15e0be40bf8acd8e714f945 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 13 May 2019 15:53:37 -0700 Subject: [PATCH 1218/1594] Support Prebid.js User ID module in Sharethrough bid adapter (#3819) * Add HTML5 video support param to bid requests * Use const instead of var for consistency * Update supported sizes - Default size returned changed from 0x0 to 1x1 to support PrebidServer - Now will always respect the bid sizes supported when configured Co-authored-by: Josh Becker * Update maintainer contact email * Support Prebid.js User ID module - Add support for Unified ID solution of User ID module by checking for `bidRequest.userId.tdid` param in `buildRequests` method of Sharethrough's adapter - Update specs, maintain 80%+ code coverage * Update logic for changing userAgent string in tests --- modules/sharethroughBidAdapter.js | 16 ++-- .../modules/sharethroughBidAdapter_spec.js | 78 ++++++++++++++++--- 2 files changed, 76 insertions(+), 18 deletions(-) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index 34682e4eb79..8c0c98bceae 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -11,10 +11,10 @@ export const sharethroughAdapterSpec = { isBidRequestValid: bid => !!bid.params.pkey && bid.bidder === BIDDER_CODE, buildRequests: (bidRequests, bidderRequest) => { - return bidRequests.map(bid => { + return bidRequests.map(bidRequest => { let query = { - placement_key: bid.params.pkey, - bidId: bid.bidId, + placement_key: bidRequest.params.pkey, + bidId: bidRequest.bidId, consent_required: false, instant_play_capable: canAutoPlayHTML5Video(), hbSource: 'prebid', @@ -30,12 +30,16 @@ export const sharethroughAdapterSpec = { query.consent_required = !!bidderRequest.gdprConsent.gdprApplies; } + if (bidRequest.userId && bidRequest.userId.tdid) { + query.ttduid = bidRequest.userId.tdid; + } + // Data that does not need to go to the server, // but we need as part of interpretResponse() const strData = { - stayInIframe: bid.params.iframe, - iframeSize: bid.params.iframeSize, - sizes: bid.sizes + stayInIframe: bidRequest.params.iframe, + iframeSize: bidRequest.params.iframeSize, + sizes: bidRequest.sizes } return { diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index f91c40f302e..825e42273cf 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -3,7 +3,7 @@ import { sharethroughAdapterSpec } from 'modules/sharethroughBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; const spec = newBidder(sharethroughAdapterSpec).getSpec(); -const bidderRequest = [ +const bidRequests = [ { bidder: 'sharethrough', bidId: 'bidId1', @@ -11,7 +11,8 @@ const bidderRequest = [ placementCode: 'foo', params: { pkey: 'aaaa1111' - } + }, + userId: { tdid: 'fake-tdid' } }, { bidder: 'sharethrough', @@ -128,6 +129,12 @@ const b64EncodeUnicode = (str) => { })); } +const setUserAgent = (str) => { + window.navigator['__defineGetter__']('userAgent', function () { + return str; + }); +} + describe('sharethrough adapter spec', function () { describe('.code', function () { it('should return a bidder code of sharethrough', function () { @@ -157,36 +164,78 @@ describe('sharethrough adapter spec', function () { }); it('should return true if req is correct', function () { - expect(spec.isBidRequestValid(bidderRequest[0])).to.eq(true); - expect(spec.isBidRequestValid(bidderRequest[1])).to.eq(true); + expect(spec.isBidRequestValid(bidRequests[0])).to.eq(true); + expect(spec.isBidRequestValid(bidRequests[1])).to.eq(true); }) }); describe('.buildRequests', function () { it('should return an array of requests', function () { - const bidRequests = spec.buildRequests(bidderRequest); + const builtBidRequests = spec.buildRequests(bidRequests); - expect(bidRequests[0].url).to.eq( + expect(builtBidRequests[0].url).to.eq( 'http://btlr.sharethrough.com/header-bid/v1'); - expect(bidRequests[1].url).to.eq( + expect(builtBidRequests[1].url).to.eq( 'http://btlr.sharethrough.com/header-bid/v1') - expect(bidRequests[0].method).to.eq('GET'); + expect(builtBidRequests[0].method).to.eq('GET'); + }); + + 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; + + setUserAgent('iPhone Version/11'); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.true; + + setUserAgent('iPhone CriOS/60'); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.true; + + setUserAgent('Android Chrome/50'); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.false; + + setUserAgent('Android Chrome'); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.false; + + setUserAgent(undefined); + builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0].data.instant_play_capable).to.be.false; }); it('should add consent parameters if gdprConsent is present', function () { const gdprConsent = { consentString: 'consent_string123', gdprApplies: true }; - const fakeBidRequest = { gdprConsent: gdprConsent }; - const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; + 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'); }); it('should handle gdprConsent is present but values are undefined case', function () { const gdprConsent = { consent_string: undefined, gdprApplies: undefined }; - const fakeBidRequest = { gdprConsent: gdprConsent }; - const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; + const bidderRequest = { gdprConsent: gdprConsent }; + const bidRequest = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(bidRequest.data).to.not.include.any.keys('consent_string') }); + + 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'); + }); + + it('should add Sharethrough specific parameters', function () { + const builtBidRequests = spec.buildRequests(bidRequests); + expect(builtBidRequests[0]).to.deep.include({ + strData: { + stayInIframe: undefined, + iframeSize: undefined, + sizes: [[600, 300]] + } + }); + }); }); describe('.interpretResponse', function () { @@ -319,6 +368,11 @@ describe('sharethrough adapter spec', function () { ); }); + it('returns an empty array if serverResponses is empty', function () { + const syncArray = spec.getUserSyncs({ pixelEnabled: true }, []); + expect(syncArray).to.be.an('array').that.is.empty; + }); + it('returns an empty array if the body is null', function () { const syncArray = spec.getUserSyncs({ pixelEnabled: true }, [{ body: null }]); expect(syncArray).to.be.an('array').that.is.empty; From 0877946ff4db97f9e8f9e6f397015f3def97ff78 Mon Sep 17 00:00:00 2001 From: Alex Khmelnitsky Date: Tue, 14 May 2019 02:02:32 +0300 Subject: [PATCH 1219/1594] Added iframe user sync support (#3822) --- modules/cedatoBidAdapter.js | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/modules/cedatoBidAdapter.js b/modules/cedatoBidAdapter.js index 8c049410b3a..78bb7b45c7b 100644 --- a/modules/cedatoBidAdapter.js +++ b/modules/cedatoBidAdapter.js @@ -109,26 +109,35 @@ export const spec = { const syncs = []; if (syncOptions.pixelEnabled) { resps.forEach(() => { - const uuid = getUserID(); - const syncUrl = SYNC_URL; - let params = ''; - if (gdprConsent && typeof gdprConsent.consentString === 'string') { - if (typeof gdprConsent.gdprApplies === 'boolean') { - params += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - params += `?gdpr_consent=${gdprConsent.consentString}`; - } - } - syncs.push({ - type: 'image', - url: syncUrl.replace('{UUID}', uuid) + params, - }); + syncs.push(getSync('image', gdprConsent)); + }); + } + if (syncOptions.iframeEnabled) { + resps.forEach(() => { + syncs.push(getSync('iframe', gdprConsent)); }); } return syncs; } } +const getSync = (type, gdprConsent) => { + const uuid = getUserID(); + const syncUrl = SYNC_URL; + let params = '&type=' + type; + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + if (typeof gdprConsent.gdprApplies === 'boolean') { + params += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + params += `&gdpr_consent=${gdprConsent.consentString}`; + } + } + return { + type: type, + url: syncUrl.replace('{UUID}', uuid) + params, + }; +} + const getUserID = () => { const cookieName = COOKIE_NAME; const uuidLen = UUID_LEN; From be8d83211efffa134a5632069c661756f003def1 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Tue, 14 May 2019 17:48:24 +0300 Subject: [PATCH 1220/1594] Gamoshi: Remove and update some bid response properties (#3806) * Add support for multi-format ad units. Add favoredMediaType property to params. * Add tests for gdpr consent. * Add adId to outbids * Modify media type resolving * Refactor multi-format ad units handler. * Remove adId from bid response * Add DEFAULT_TTL const for ttl property * Modify TTL const to 360 --- modules/gamoshiBidAdapter.js | 11 +++++------ test/spec/modules/gamoshiBidAdapter_spec.js | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index c831f4db522..67475f8d8d9 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -11,6 +11,8 @@ const ENDPOINTS = { 'gambid': 'https://rtb.gamoshi.io', }; +const DEFAULT_TTL = 360; + export const helper = { getTopFrame: function () { try { @@ -114,7 +116,7 @@ export const spec = { if (mediaTypes && mediaTypes.video) { if (!hasFavoredMediaType || params.favoredMediaType === VIDEO) { - const playerSize = mediaTypes.video.playerSize; + const playerSize = mediaTypes.video.playerSize || sizes; const videoImp = Object.assign({}, imp, { video: { w: playerSize ? playerSize[0][0] : 300, @@ -150,18 +152,15 @@ export const spec = { bids.forEach(bid => { const outBid = { - adId: bidRequest.bidRequest.adUnitCode, requestId: bidRequest.bidRequest.bidId, cpm: bid.price, width: bid.w, height: bid.h, - ttl: 60 * 10, - creativeId: bid.crid, + ttl: DEFAULT_TTL, + creativeId: bid.crid || bid.adid, netRevenue: true, currency: bid.cur || response.cur, - adUnitCode: bidRequest.bidRequest.adUnitCode, mediaType: helper.getMediaType(bid) - }; if (utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType)) { diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index b657dac34b6..a2c4eebc213 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -329,6 +329,8 @@ describe('GamoshiAdapter', function () { ] }; + const TTL = 360; + it('returns an empty array on missing response', function () { let response; @@ -345,13 +347,12 @@ describe('GamoshiAdapter', function () { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); - const ad0 = response[0]; expect(ad0.requestId).to.equal(bannerBidRequest.bidId); expect(ad0.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); expect(ad0.width).to.equal(rtbResponse.seatbid[1].bid[0].w); expect(ad0.height).to.equal(rtbResponse.seatbid[1].bid[0].h); - expect(ad0.ttl).to.equal(60 * 10); + expect(ad0.ttl).to.equal(TTL); expect(ad0.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); expect(ad0.netRevenue).to.equal(true); expect(ad0.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); @@ -364,13 +365,12 @@ describe('GamoshiAdapter', function () { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: videoBidRequest}); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); - const ad0 = response[0]; expect(ad0.requestId).to.equal(videoBidRequest.bidId); expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); expect(ad0.height).to.equal(rtbResponse.seatbid[0].bid[0].h); - expect(ad0.ttl).to.equal(60 * 10); + expect(ad0.ttl).to.equal(TTL); expect(ad0.creativeId).to.equal(rtbResponse.seatbid[0].bid[0].crid); expect(ad0.netRevenue).to.equal(true); expect(ad0.currency).to.equal(rtbResponse.seatbid[0].bid[0].cur || rtbResponse.cur || 'USD'); From a4f247c2e6147ce321ce7cdd57855a7c8ac14911 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 14 May 2019 08:49:11 -0600 Subject: [PATCH 1221/1594] update fun-hooks and use no-eval version for CSP (#3814) * update fun-hooks and use no-eval version for CSP * update fun-hooks to version with proper assign for ie --- package-lock.json | 92 ++++++++++++++++++++--------------------------- package.json | 2 +- src/hook.js | 2 +- 3 files changed, 41 insertions(+), 55 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6f908eeba52..262d67c052d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.14.0-pre", + "version": "2.15.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3108,7 +3108,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3480,7 +3480,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -4585,7 +4585,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4599,7 +4599,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4615,7 +4615,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4635,7 +4635,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -5326,7 +5326,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5865,7 +5865,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", "dev": true }, "flush-write-stream": { @@ -6093,14 +6093,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6115,20 +6113,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6245,8 +6240,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6258,7 +6252,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6273,7 +6266,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6281,14 +6273,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6307,7 +6297,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6388,8 +6377,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6401,7 +6389,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6523,7 +6510,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6596,9 +6582,9 @@ } }, "fun-hooks": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.8.1.tgz", - "integrity": "sha512-qhyQAO6vhmzzwOJ2SvqeCvL2dqBCw3NeuIpNOfMPv2bucFYXLur9UbXTiUAbm7EE2TrdLgIKJZkO0DfwEY+KVQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.2.tgz", + "integrity": "sha512-Bbhqg3zj/joiHsmU9z/DBPofMN8yN4P7m2cE4sqZqaL+C6YcAXKjwa7Cu8rUs3roBiAhgWwQOAALZZodpmBglw==" }, "function-bind": { "version": "1.1.1", @@ -7266,7 +7252,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7283,7 +7269,7 @@ "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==", + "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", "dev": true } } @@ -7986,7 +7972,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8982,7 +8968,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9607,7 +9593,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -9620,7 +9606,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", "dev": true }, "debug": { @@ -10157,7 +10143,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10193,7 +10179,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10801,7 +10787,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -12074,7 +12060,7 @@ "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", "dev": true }, "rgb2hex": { @@ -12543,7 +12529,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { "debug": "~3.1.0", @@ -12557,7 +12543,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12580,7 +12566,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", @@ -12602,7 +12588,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12618,7 +12604,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -12630,7 +12616,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12748,7 +12734,7 @@ }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -12882,7 +12868,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13883,7 +13869,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14523,7 +14509,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { diff --git a/package.json b/package.json index b772f2eccdb..6d29154f310 100755 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "babel-plugin-transform-object-assign": "^6.22.0", "core-js": "^2.4.1", "crypto-js": "^3.1.9-1", - "fun-hooks": "^0.8.1", + "fun-hooks": "^0.9.2", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2" } diff --git a/src/hook.js b/src/hook.js index 7727155e8aa..ddf0d134357 100644 --- a/src/hook.js +++ b/src/hook.js @@ -1,5 +1,5 @@ -import funHooks from 'fun-hooks'; +import funHooks from 'fun-hooks/no-eval'; export let hook = funHooks({ ready: funHooks.SYNC | funHooks.ASYNC | funHooks.QUEUE From 9166db810dba45320c488d6cfe5b283816be4b53 Mon Sep 17 00:00:00 2001 From: Gaudeamus Date: Tue, 14 May 2019 18:17:47 +0300 Subject: [PATCH 1222/1594] mgid adapter: native support, minor changes (#3774) * native support & minor changes * native support & minor changes * increase test coverage * fix win price value * fix win price value tests * fix alias, fix bidfloor * remove alias --- modules/mgidBidAdapter.js | 435 +++++++++++++++++++---- test/spec/modules/mgidBidAdapter_spec.js | 370 ++++++++++++++++++- 2 files changed, 729 insertions(+), 76 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 5a91cccde9e..b7759ea1e0a 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -1,16 +1,70 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import * as utils from '../src/utils'; import * as urlUtils from '../src/url'; -import { BANNER } from 'src/mediaTypes'; +import {BANNER, NATIVE} from 'src/mediaTypes'; +const DEFAULT_CUR = 'USD'; const BIDDER_CODE = 'mgid'; -const ENDPOINT_URL = '//dsp.mgid.com/prebid/'; +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 +utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] = anAsset.KEY }); +// loading _NATIVE_ASSET_KEY_TO_ASSET_MAP +utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); export const spec = { - VERSION: '1.0', + VERSION: '1.1', code: BIDDER_CODE, - aliases: ['mgid'], // short code - supportedMediaTypes: [BANNER], + supportedMediaTypes: [BANNER, NATIVE], reId: /^[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. * @@ -19,16 +73,38 @@ export const spec = { */ isBidRequestValid: (bid) => { const banner = utils.deepAccess(bid, 'mediaTypes.banner'); - const sizes = utils.deepAccess(banner, 'sizes'); - let sizesOk = typeof (sizes) == 'object' && sizes.length > 0; - for (let f = 0; sizesOk && f < sizes.length; f++) { - sizesOk = sizes[f].length == 2; - } - return typeof (bid.params) == 'object' && !!bid.params.accountId && !!bid.params.placementId && - typeof (bid.params.accountId) == 'string' && typeof (bid.params.placementId) == 'string' && - bid.params.accountId.length > 0 && bid.params.placementId.length > 0 && + const native = utils.deepAccess(bid, 'mediaTypes.native'); + let nativeOk = utils.isPlainObject(native); + if (nativeOk) { + const nativeParams = utils.deepAccess(bid, 'nativeParams'); + let assetsCount = 0; + if (utils.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 (!utils.isPlainObject(v) || (!supportProp && utils.deepAccess(v, 'required'))) { + nativeOk = false; + break; + } + } + } + nativeOk = nativeOk && (assetsCount > 0); + } + let bannerOk = utils.isPlainObject(banner); + if (bannerOk) { + const sizes = utils.deepAccess(banner, 'sizes'); + bannerOk = utils.isArray(sizes) && sizes.length > 0; + for (let f = 0; bannerOk && f < sizes.length; f++) { + bannerOk = sizes[f].length === 2; + } + } + return utils.isPlainObject(bid.params) && !!bid.params.accountId && !!bid.params.placementId && + utils.isStr(bid.params.accountId) && utils.isStr(bid.params.placementId) && bid.params.accountId.toString().match(spec.reId) > 0 && bid.params.placementId.toString().match(spec.reId) && - typeof (banner) == 'object' && sizesOk; + (bannerOk || nativeOk); }, /** * Make a server request from the list of BidRequests. @@ -37,9 +113,9 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: (validBidRequests, bidderRequest) => { - utils.logInfo(`MGID DEBUG: buildRequests`); - if (validBidRequests.length == 0) { - return null; + utils.logInfo(LOG_INFO_PREFIX + `buildRequests`); + if (validBidRequests.length === 0) { + return; } const referer = utils.deepAccess(bidderRequest, 'refererInfo.referer'); const hostname = urlUtils.parse(referer).hostname; @@ -47,34 +123,45 @@ export const spec = { const accountId = setOnAny(validBidRequests, 'params.accountId'); const muid = getLocalStorageSafely('mgMuidn'); let url = (setOnAny(validBidRequests, 'params.bidUrl') || ENDPOINT_URL) + accountId; - if (muid != null && typeof (muid) == 'string' && muid.length > 0) { + if (utils.isStr(muid) && muid.length > 0) { url += '?muid=' + muid; } const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || referer; const secure = window.location.protocol === 'https:' ? 1 : 0; - const imp = validBidRequests.map((bid, id) => { - const placeId = utils.deepAccess(bid, 'params.placementId'); - const sizes = utils.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]}); - } - } - } - return { + let imp = []; + validBidRequests.forEach(bid => { + let impObj = { id: bid.bidId, - tagid: placeId, - banner: { - w: sizes && sizes[0][0], - h: sizes && sizes[0][1], - format, - }, + tagid: utils.deepAccess(bid, 'params.placementId'), secure, }; + const bidFloor = utils.deepAccess(bid, 'params.bidFloor') || utils.deepAccess(bid, 'params.bidfloor') || 0; + if (bidFloor && utils.isNumber(bidFloor)) { + impObj.bidfloor = bidFloor; + } + 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 ext = {mgid_ver: spec.VERSION, prebid_ver: $$PREBID_GLOBAL$$.version}; let user = {}; let regs = {}; @@ -87,15 +174,14 @@ export const spec = { gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) }; } - - const request = { + let request = { id: utils.deepAccess(bidderRequest, 'bidderRequestId'), site: { domain, page }, - cur: ['USD'], + cur: [setOnAny(validBidRequests, 'params.currency') || setOnAny(validBidRequests, 'params.cur') || DEFAULT_CUR], device: { ua: navigator.userAgent, js: 1, - dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0, + dnt: (navigator.doNotTrack === 'yes' || navigator.doNotTrack === '1' || navigator.msDoNotTrack === '1') ? 1 : 0, h: screen.height, w: screen.width, language: getLanguage() @@ -105,7 +191,7 @@ export const spec = { ext, imp }; - utils.logInfo(`MGID DEBUG: buildRequests\n${request}`); + utils.logInfo(LOG_INFO_PREFIX + `buildRequest:`, request); return { method: 'POST', url: url, @@ -119,41 +205,55 @@ export const spec = { * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: (serverResponse, bidRequests) => { - if (serverResponse == null || serverResponse.body == null || serverResponse.body == '' || !serverResponse.body.seatbid || !serverResponse.body.seatbid[0]) { - return []; + utils.logInfo(LOG_INFO_PREFIX + `interpretResponse`, serverResponse); + if (serverResponse == null || serverResponse.body == null || serverResponse.body === '' || !utils.isArray(serverResponse.body.seatbid) || !serverResponse.body.seatbid.length) { + return; } - utils.logInfo(`MGID DEBUG: interpretResponse`); const returnedBids = []; const muidn = utils.deepAccess(serverResponse.body, 'ext.muidn') - if (muidn != null && typeof (muidn) == 'string' && muidn.length > 0) { + if (utils.isStr(muidn) && muidn.length > 0) { setLocalStorageSafely('mgMuidn', muidn) } - serverResponse.body.seatbid[0].bid.forEach((value, index) => { - returnedBids.push(prebidBid(value, serverResponse.body.cur)); + serverResponse.body.seatbid.forEach((bids) => { + bids.bid.forEach((bid) => { + const pbid = prebidBid(bid, serverResponse.body.cur); + if (pbid.mediaType === NATIVE && utils.isEmpty(pbid.native)) { + return; + } + returnedBids.push(pbid); + }) }); - utils.logInfo(`MGID DEBUG:\n${returnedBids}`); + utils.logInfo(LOG_INFO_PREFIX + `interpretedResponse`, returnedBids); return returnedBids; }, onBidWon: (bid) => { - const cpm = bid.pbMg; - if (bid.nurl != '') { + const cpm = utils.deepAccess(bid, 'adserverTargeting.hb_pb') || ''; + if (utils.isStr(bid.nurl) && bid.nurl !== '') { bid.nurl = bid.nurl.replace( - /\$\{AUCTION_PRICE\}/, + /\${AUCTION_PRICE}/, cpm ); pixel(bid.nurl); - }; + } if (bid.isBurl) { - bid.ad = bid.ad.replace( - /\$\{AUCTION_PRICE\}/, - cpm - ); + if (bid.mediaType === BANNER) { + bid.ad = bid.ad.replace( + /\${AUCTION_PRICE}/, + cpm + ) + } else { + bid.burl = bid.burl.replace( + /\${AUCTION_PRICE}/, + cpm + ); + pixel(bid.burl); + } } - utils.logInfo(`MGID DEBUG: onBidWon`); + utils.logInfo(LOG_INFO_PREFIX + `onBidWon`); }, getUserSyncs: (syncOptions, serverResponses) => { - utils.logInfo(`MGID DEBUG: getUserSyncs`); + utils.logInfo(LOG_INFO_PREFIX + `getUserSyncs`); } }; @@ -174,8 +274,8 @@ function setOnAny(collection, key) { * @return Bid */ function prebidBid(serverBid, cur) { - if (cur == null || cur == '') { - cur = 'USD'; + if (!utils.isStr(cur) || cur === '') { + cur = DEFAULT_CUR; } const bid = { requestId: serverBid.impid, @@ -190,12 +290,28 @@ function prebidBid(serverBid, cur) { netRevenue: true, ttl: serverBid.ttl || 300, nurl: serverBid.nurl || '', - isBurl: typeof (serverBid.burl) == 'string' && serverBid.burl.length > 0, + burl: serverBid.burl || '', + isBurl: utils.isStr(serverBid.burl) && serverBid.burl.length > 0, }; - + setMediaType(serverBid, bid); + switch (bid.mediaType) { + case BANNER: + break; + case NATIVE: + parseNativeResponse(serverBid, bid); + break; + } return bid; } +function setMediaType(bid, newBid) { + if (utils.deepAccess(bid, 'ext.crtype') === 'native') { + newBid.mediaType = NATIVE; + } else { + newBid.mediaType = BANNER; + } +} + function extractDomainFromHost(pageHost) { if (pageHost == 'localhost') { return 'localhost' @@ -224,7 +340,7 @@ function pixel(url) { function getLanguage() { const language = navigator.language ? 'language' : 'userLanguage'; const lang2 = navigator[language].split('-')[0]; - if (lang2.length == 2 || lang2.length == 3) { + if (lang2.length === 2 || lang2.length === 3) { return lang2; } return ''; @@ -245,3 +361,196 @@ function setLocalStorageSafely(key, val) { return null; } } + +function createBannerRequest(bid) { + const sizes = utils.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]}); + } + } + } + return { + w: sizes && sizes[0][0], + h: sizes && sizes[0][1], + format, + } +} + +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 || (utils.isArray(params[key].minsizes) && params[key].minsizes.length > 0 ? params[key].minsizes[0] : 0); + const hmin = params[key].hmin || params[key].minimumHeight || (utils.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 || (utils.isArray(params[key].sizes) && params[key].sizes.length > 0 ? params[key].sizes[0] : 0), + h: params[key].h || params[key].height || (utils.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 || (utils.isArray(params[key].sizes) && params[key].sizes.length > 0 ? params[key].sizes[0] : 0), + h: params[key].h || params[key].height || (utils.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 (utils.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) { + utils.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; + } + } +} diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index 4c67447489d..2b1a0739537 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -1,16 +1,22 @@ -import {expect} from 'chai'; +import {assert, expect} from 'chai'; import {spec} from 'modules/mgidBidAdapter'; import * as utils from '../../../src/utils'; import * as urlUtils from '../../../src/url'; 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; @@ -53,6 +59,30 @@ describe('Mgid bid adapter', function () { 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.mediaTypes = { + banner: { + sizes: [[300, 250]] + } + }; + bid.params = {accountId: 2, placementId: 1}; + 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.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; @@ -100,6 +130,76 @@ describe('Mgid bid adapter', function () { }; 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.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 () { @@ -138,6 +238,46 @@ describe('Mgid bid adapter', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.include('//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 () { @@ -148,7 +288,7 @@ describe('Mgid bid adapter', function () { placementId: '2', }, }; - it('should return proper imp', function () { + it('should return proper banner imp', function () { let bid = Object.assign({}, abid); bid.mediaTypes = { banner: { @@ -159,7 +299,7 @@ describe('Mgid bid adapter', function () { const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); const domain = urlUtils.parse(referer).hostname; const request = spec.buildRequests(bidRequests); - expect(request.url).deep.equal('//dsp.mgid.com/prebid/1'); + 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); @@ -174,11 +314,94 @@ describe('Mgid bid adapter', function () { expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', - 'url': '//dsp.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"banner\":{\"w\":300,\"h\":250,\"format\":[]},\"secure\":' + secure + '}]}', + 'url': 'https://prebid.mgid.com/prebid/1', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250,\"format\":[]}}]}', }); }); - it('should return proper request', function () { + 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 referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); + const domain = urlUtils.parse(referer).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.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'); + 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 + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"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 sponsoredBy', function () { + let bid = Object.assign({}, abid); + bid.mediaTypes = { + native: '', + }; + bid.nativeParams = { + title: {required: true}, + image: {sizes: [80, 80]}, + sponsoredBy: { }, + }; + + let bidRequests = [bid]; + const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); + const domain = urlUtils.parse(referer).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.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'); + 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 + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"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: { @@ -190,7 +413,7 @@ describe('Mgid bid adapter', function () { const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); const domain = urlUtils.parse(referer).hostname; - expect(request.url).deep.equal('//dsp.mgid.com/prebid/1'); + 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); @@ -206,19 +429,19 @@ describe('Mgid bid adapter', function () { expect(request).to.deep.equal({ 'method': 'POST', - 'url': '//dsp.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]},\"secure\":' + secure + '}]}', + 'url': 'https://prebid.mgid.com/prebid/1', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', }); }); }); - describe('interpretResponse', function () { + describe('interpretResponse banner', function () { it('should not push bid response', function () { let bids = spec.interpretResponse(); - expect(bids).to.deep.equal([]); + expect(bids).to.be.undefined; }); - it('should push proper bid response', function () { + it('should push proper banner bid response', function () { let resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'USD', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'http: nurl', 'burl': 'http: nurl', 'adm': 'html: adm', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2']}], 'seat': '44082'}]} + 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': 'http: nurl', 'burl': 'http: burl', 'adm': 'html: adm', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2']}], 'seat': '44082'}]} }; let bids = spec.interpretResponse(resp); expect(bids).to.deep.equal([ @@ -233,6 +456,7 @@ describe('Mgid bid adapter', function () { 'mediaType': 'banner', 'netRevenue': true, 'nurl': 'http: nurl', + 'burl': 'http: burl', 'requestId': '61e40632c53fc2', 'ttl': 300, 'width': 300, @@ -240,4 +464,124 @@ describe('Mgid bid adapter', function () { ]); }); }); + describe('interpretResponse native', 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': 'http: nurl', 'burl': 'http: burl', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}}], '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': 'http: nurl', 'burl': 'http: 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'}}], 'seat': '44082'}]} + }; + let bids = spec.interpretResponse(resp); + expect(bids).to.deep.equal([]) + }); + it('should push proper native bid response', 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': 'http: nurl', 'burl': 'http: 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'}}], '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': 'http: burl', + 'cpm': 1.5, + 'creativeId': '2898532/2419121/2592854/2499195', + 'currency': 'GBP', + 'dealId': '', + 'height': 0, + 'isBurl': true, + 'mediaType': 'native', + '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': 'http: nurl', + 'requestId': '61e40632c53fc2', + 'ttl': 300, + 'width': 0 + }]) + }); + it('should push proper native bid response', 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': 'http: nurl', 'burl': 'http: 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'}}], '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', + 'netRevenue': true, + 'nurl': 'http: nurl', + 'burl': 'http: 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', + } + } + ]); + }); + }); + + describe('on bidWon', function () { + 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'); + }); + }); }); From af729970d9df46ff37f8afc4d3ea9fceecbe02c0 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 14 May 2019 15:51:06 -0400 Subject: [PATCH 1223/1594] Prebid 2.15.0 release --- package-lock.json | 200 ++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 134 insertions(+), 68 deletions(-) diff --git a/package-lock.json b/package-lock.json index 262d67c052d..b00be53f565 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.15.0-pre", + "version": "2.15.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -6065,24 +6065,28 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, "requires": { @@ -6092,12 +6096,14 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "brace-expansion": { "version": "1.1.11", - "bundled": true, + "resolved": false, + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -6106,34 +6112,40 @@ }, "chownr": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, "core-util-is": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "bundled": true, + "resolved": false, + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "optional": true, "requires": { @@ -6142,25 +6154,29 @@ }, "deep-extend": { "version": "0.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, "requires": { @@ -6169,13 +6185,15 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, "requires": { @@ -6191,7 +6209,8 @@ }, "glob": { "version": "7.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, "requires": { @@ -6205,13 +6224,15 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "bundled": true, + "resolved": false, + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, "requires": { @@ -6220,7 +6241,8 @@ }, "ignore-walk": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, "requires": { @@ -6229,7 +6251,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, "requires": { @@ -6239,18 +6262,21 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "ini": { "version": "1.3.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { "number-is-nan": "^1.0.0" @@ -6258,13 +6284,15 @@ }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -6272,12 +6300,14 @@ }, "minimist": { "version": "0.0.8", - "bundled": true, + "resolved": false, + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "minipass": { "version": "2.3.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -6286,7 +6316,8 @@ }, "minizlib": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, "requires": { @@ -6295,7 +6326,8 @@ }, "mkdirp": { "version": "0.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { "minimist": "0.0.8" @@ -6303,13 +6335,15 @@ }, "ms": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "optional": true }, "needle": { "version": "2.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "dev": true, "optional": true, "requires": { @@ -6320,7 +6354,8 @@ }, "node-pre-gyp": { "version": "0.10.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", "dev": true, "optional": true, "requires": { @@ -6338,7 +6373,8 @@ }, "nopt": { "version": "4.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, "requires": { @@ -6348,13 +6384,15 @@ }, "npm-bundled": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", "dev": true, "optional": true, "requires": { @@ -6364,7 +6402,8 @@ }, "npmlog": { "version": "4.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, "requires": { @@ -6376,18 +6415,21 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1" @@ -6395,19 +6437,22 @@ }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, "requires": { @@ -6417,19 +6462,22 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, "requires": { @@ -6441,7 +6489,8 @@ "dependencies": { "minimist": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true } @@ -6449,7 +6498,8 @@ }, "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, "requires": { @@ -6464,7 +6514,8 @@ }, "rimraf": { "version": "2.6.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, "requires": { @@ -6473,42 +6524,49 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "safer-buffer": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", @@ -6518,7 +6576,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, "requires": { @@ -6527,7 +6586,8 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -6535,13 +6595,15 @@ }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, "requires": { @@ -6556,13 +6618,15 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, "requires": { @@ -6571,12 +6635,14 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "yallist": { "version": "3.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true } } diff --git a/package.json b/package.json index 6d29154f310..5469fc5880a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.15.0-pre", + "version": "2.15.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b58d49c1cc582370d3bd7f30a8c0c676d9c7d29e Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 14 May 2019 16:03:47 -0400 Subject: [PATCH 1224/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5469fc5880a..6bb0b49fab0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.15.0", + "version": "2.16.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 90accd8dcb28d9239db6a0059b9074d73817c77b Mon Sep 17 00:00:00 2001 From: jacekburys-quantcast <44467819+jacekburys-quantcast@users.noreply.github.com> Date: Wed, 15 May 2019 14:11:13 +0100 Subject: [PATCH 1225/1594] updating maintainer email address in quantcastBidAdapter.md (#3830) --- modules/quantcastBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quantcastBidAdapter.md b/modules/quantcastBidAdapter.md index 5d0c2e10fc0..2b55eae9026 100644 --- a/modules/quantcastBidAdapter.md +++ b/modules/quantcastBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Quantcast Bidder Adapter Module Type: Bidder Adapter -Maintainer: igor.soarez@quantcast.com +Maintainer: inventoryteam@quantcast.com ``` # Description From 3b9f9e11dbe90e78deb582cbe4fda72ac00c3bf7 Mon Sep 17 00:00:00 2001 From: mafernandez80 <50341807+mafernandez80@users.noreply.github.com> Date: Wed, 15 May 2019 13:19:49 -0300 Subject: [PATCH 1226/1594] Reload Adapter: New (#3812) * Reload Adapter: New * Reload Adapter - Spec * Reload Adapter and Spec - Changes according comments * Reload Adapter & Spec: lint errors fixed * Reload Adapter: Example updated --- modules/reloadBidAdapter.js | 422 +++++++++++++++++++++ modules/reloadBidAdapter.md | 48 +++ test/spec/modules/reloadBidAdapter_spec.js | 293 ++++++++++++++ 3 files changed, 763 insertions(+) create mode 100644 modules/reloadBidAdapter.js create mode 100644 modules/reloadBidAdapter.md create mode 100644 test/spec/modules/reloadBidAdapter_spec.js diff --git a/modules/reloadBidAdapter.js b/modules/reloadBidAdapter.js new file mode 100644 index 00000000000..a50949825a9 --- /dev/null +++ b/modules/reloadBidAdapter.js @@ -0,0 +1,422 @@ +import { + BANNER +} + from 'src/mediaTypes'; +import { + registerBidder +} + from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'reload'; + +const VERSION_ADAPTER = '1.0'; + +export const spec = { + code: BIDDER_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 !!(bid.params && bid.params.plcmID && bid.params.partID && 'opdomID' in bid.params && + 'bsrvID' in bid.params && bid.params.bsrvID >= 0 && bid.params.bsrvID <= 99); + }, + /** + * 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 vRequests = []; + + let bidReq = { + id: Math.random().toString(10).substring(2), + imp: [] + }; + + let vPrxClientTool = null; + for (let vIdx = 0; vIdx < validBidRequests.length; vIdx++) { + let bidRequest = validBidRequests[vIdx]; + + if (BANNER in bidRequest.mediaTypes !== true) continue; + if (bidRequest.mediaTypes.banner.sizes.length <= 0) continue; + + let vDim = bidRequest.mediaTypes.banner.sizes[0]; + + vPrxClientTool = new ReloadClientTool({ + prxVer: VERSION_ADAPTER, + prxType: 'bd', + + plcmID: bidRequest.params.plcmID, + partID: bidRequest.params.partID, + opdomID: bidRequest.params.opdomID, + bsrvID: bidRequest.params.bsrvID + }); + + let vImpression = { + id: bidRequest.bidId, + bidId: bidRequest.bidId, + adUnitCode: bidRequest.adUnitCode, + transactionId: bidRequest.transactionId, + bidderRequestId: bidRequest.bidderRequestId, + auctionId: bidRequest.auctionId, + + banner: { + h: vDim[1], + w: vDim[0], + ext: { + type: bidRequest.params.type || 'pcm', + pcmdata: vPrxClientTool.getPCMObj() + } + } + }; + bidReq.imp.push(vImpression); + } + + if (bidReq.imp.length > 0) { + const payloadString = JSON.stringify(bidReq); + vRequests.push({ + method: 'POST', + url: vPrxClientTool.getSrvUrl(), + data: payloadString + }); + } + return vRequests; + }, + /** + * 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 = []; + + for (let vIdx = 0; vIdx < serverBody.seatbid.length; vIdx++) { + let vSeatBid = serverBody.seatbid[vIdx]; + + for (let vIdxBid = 0; vIdxBid < vSeatBid.bid.length; vIdxBid++) { + let vBid = vSeatBid.bid[vIdxBid]; + + let vPrxClientTool = new ReloadClientTool({ + plcmID: vBid.ext.plcmID, + partID: vBid.ext.partID, + opdomID: vBid.ext.opdomID, + bsrvID: vBid.ext.bsrvID + }); + + vPrxClientTool.setPCMObj(vBid.ext.pcmdata); + + if (vPrxClientTool.getBP() > 0) { + let bidResponse = { + requestId: vBid.impid, + ad: vPrxClientTool.getAM(), + cpm: vPrxClientTool.getBP() / 100, + width: vBid.ext.banner.w, + height: vBid.ext.banner.h, + creativeId: vBid.id, + currency: vPrxClientTool.getBC(), + ttl: 300, + netRevenue: true + }; + bidResponses.push(bidResponse); + } + } + } + + return bidResponses; + } +}; + +/** + * Reload Client Tool + * @param {json} args + */ + +function ReloadClientTool(args) { + var that = this; + + var _pcmClientVersion = '120'; + var _pcmFilePref = 'prx_root_'; + var _resFilePref = 'prx_pnws_'; + + var _pcmInputObjVers = '100'; + + var _instObj = null; + var _status = 'NA'; + var _message = ''; + var _log = ''; + + var _memFile = _getMemFile(); + + if (_memFile.status !== 'ok') { + _log += 'WARNING: clnt-int mem file initialized\n'; + } + + that.getPCMObj = function () { + return { + thisVer: _pcmInputObjVers, + + statStr: _memFile.statStr, + plcmData: _getPlcmData(), + clntData: _getClientData(), + resultData: _getRD(), + + proxetString: null, + dboData: null, + plcmSett: null, + }; + }; + + that.setPCMObj = function (obj) { + if (obj.thisVer !== '100') { + _status = 'error'; + _message = 'incomp_output_obj_version'; + _log += ' ERROR incomp_output_obj_version'; + return; + } + + _status = obj.status; + _message = obj.message; + _log += ' ' + obj.log; + + if (obj.status !== 'ok') return; + + _saveMemFile(obj.statStr, obj.srvUrl); + _instObj = obj.instr; + }; + + that.getSrvUrl = function () { + var effSrvUrl = getBidServerUrl(0); + + if (isNaN(parseInt(args.bsrvID)) !== true) effSrvUrl = getBidServerUrl(parseInt(args.bsrvID)); + + if (typeof _memFile.srvUrl === 'string' && _memFile.srvUrl !== '') effSrvUrl = _memFile.srvUrl; + + return _getProtocolString() + effSrvUrl + '/bid'; + + function getBidServerUrl (idx) { + return 'bidsrv' + getTwoDigitString(idx) + '.reload.net'; + + function getTwoDigitString (idx) { + if (idx >= 10) return '' + idx; + else return '0' + idx; + } + } + }; + + that.getBP = function () { + if (_instObj === null) return 0; + if (typeof _instObj === 'undefined') return 0; + if (_instObj.go !== true) return 0; + return _instObj.prc; + }; + + that.getBC = function () { + if (_instObj === null) return 0; + if (typeof _instObj === 'undefined') return 0; + if (_instObj.go !== true) return 0; + return _instObj.cur; + }; + + that.getAM = function () { + if (_instObj === null) return null; + if (typeof _instObj === 'undefined') return null; + if (_instObj.go !== true) return null; + return _instObj.am; + }; + + that.getPM = function () { + if (_instObj === null) return null; + if (typeof _instObj === 'undefined') return null; + if (_instObj.go === true) return null; + return _instObj.pbm; + }; + + that.setRD = function (data) { + return _setRD(data); + }; + + that.getStat = function () { + return _status; + }; + + that.getMsg = function () { + return _message; + }; + + that.getLog = function () { + return _log; + }; + + function _getPlcmData () { + return { + prxVer: args.prxVer, + prxType: args.prxType, + plcmID: args.plcmID, + partID: args.partID, + opdomID: args.opdomID, + bsrvID: args.bsrvID, + dmod: args.dmod, + lmod: args.lmod, + lplcmID: args.lplcmID, + }; + } + + function _getClientData () { + return { + version: 100, + locTime: Date.now(), + + winInfo: _genWinInfo(), + envInfo: getEnvInfo(), + confined: detectConfined(), + protStr: _getProtocolString(), + + hostDomain: decodeURIComponent(window.location.host), + hostPagePath: decodeURIComponent(window.location.pathname), + hostPageUrl: decodeURIComponent(window.location.href), + hostPageTitle: document.title, + }; + + function _genWinInfo () { + var winInfo = { + physicalWidth: window.screen.width, + physicalHeight: window.screen.height, + screenWidth: window.screen.availWidth, + screenHeight: window.screen.availHeight, + windowWidth: window.innerWidth, + windowHeight: window.innerHeight, + bodyHeight: document.body.clientHeight + }; + return winInfo; + } + + function getEnvInfo() { + return { + userAgent: navigator.userAgent, + appName: navigator.appName, + appVersion: navigator.appVersion + }; + } + + function detectConfined () { + var confined = true; + try { if (window.top === window.self) confined = false; } catch (err) {} + return confined; + } + } + + function _getMemFile () { + try { + var memFileObj = _getItem(_getMemFileName()); + + if (memFileObj === null) throw { s: 'init' }; + + if (typeof memFileObj.statStr !== 'string') throw { s: 'error' }; + if (typeof memFileObj.srvUrl !== 'string') throw { s: 'error' }; + + memFileObj.status = 'ok'; + + return memFileObj; + } catch (err) { + var retObj = { + statStr: null, + srvUrl: null + }; + retObj.status = err.s; + + return retObj; + } + } + + function _saveMemFile (statStr, srvUrl) { + try { + var fileData = { + statStr: statStr, + srvUrl: srvUrl, + }; + _setItem(_getMemFileName(), fileData); + return true; + } catch (err) { + return false; + } + } + + function _getMemFileName () { + return _pcmFilePref + args.plcmID + '_' + args.partID; + } + + function _getRD () { + try { + return _getItem(_getResltStatusFileName()); + } catch (err) { + return null; + } + } + + function _setRD (fileData) { + try { + _setItem(_getResltStatusFileName(), fileData); + return true; + } catch (err) { + return false; + } + } + + function _getResltStatusFileName () { + return _resFilePref + args.plcmID + '_' + args.partID; + } + + function _setItem (name, data) { + var stgFileObj = { + ver: _pcmClientVersion, + ts: Date.now(), + }; + + if (typeof data === 'string') { + stgFileObj.objtype = false; + stgFileObj.memdata = data; + } else { + stgFileObj.objtype = true; + stgFileObj.memdata = JSON.stringify(data); + } + + var stgFileStr = JSON.stringify(stgFileObj); + + localStorage.setItem(name, stgFileStr); + + return true; + } + + function _getItem (name) { + try { + var obStgFileStr = localStorage.getItem(name); + if (obStgFileStr === null) return null; + + var stgFileObj = JSON.parse(obStgFileStr); + + if (stgFileObj.ver !== _pcmClientVersion) throw { message: 'version_error' }; + + if (stgFileObj.objtype === true) return JSON.parse(stgFileObj.memdata); + else return '' + stgFileObj.memdata; + } catch (err) { + return null; + } + } + + function _getProtocolString () { + var wnd = null; + try { wnd = top; } catch (err) { wnd = window; } + + if (wnd.location.protocol.toLowerCase().indexOf('http:') >= 0) return 'http://'; + else return 'https://'; + } +}; + +registerBidder(spec); diff --git a/modules/reloadBidAdapter.md b/modules/reloadBidAdapter.md new file mode 100644 index 00000000000..42fe11b40b3 --- /dev/null +++ b/modules/reloadBidAdapter.md @@ -0,0 +1,48 @@ +# Overview + +Module Name: Reload Bid Adapter + +Module Type: Bidder Adapter + +Maintainer: prebid@reload.net + +# Description + +Prebid module for connecting to Reload + +# Parameters +## Banner + +| Name | Scope | Description | Example | +| :------------ | :------- | :---------------------------------------------- | :--------------------------------- | +| `plcmID` | required | Placement ID (provided by Reload) | "4234897234" | +| `partID` | required | Partition ID (provided by Reload) | "part_01" | +| `opdomID` | required | Internal parameter (provided by Reload) | 0 | +| `bsrvID` | required | Internal parameter (provided by Reload) | 12 | +| `type` | optional | Internal parameter (provided by Reload) | "pcm" | + +# Example ad units +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250] + ], + } + }, + bids: [{ + bidder: 'reload', + params: { + plcmID: 'prebid_check', + partID: 'part_4', + opdomID: '0', + bsrvID: 0, + type: 'pcm' + } + }] + }]; \ No newline at end of file diff --git a/test/spec/modules/reloadBidAdapter_spec.js b/test/spec/modules/reloadBidAdapter_spec.js new file mode 100644 index 00000000000..ebf7308caf2 --- /dev/null +++ b/test/spec/modules/reloadBidAdapter_spec.js @@ -0,0 +1,293 @@ +import { expect } from 'chai'; +import { spec } from 'modules/reloadBidAdapter'; + +let getParams = () => { + return JSON.parse(JSON.stringify({ + 'plcmID': 'placement_01', + 'partID': 'part00', + 'opdomID': 1, + 'bsrvID': 1, + 'type': 'pcm' + })); +}; + +let getBidderRequest = () => { + return JSON.parse(JSON.stringify({ + bidderCode: 'reload', + auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + bidderRequestId: '7101db09af0db2', + start: new Date().getTime(), + bids: [{ + bidder: 'reload', + bidId: '84ab500420319d', + bidderRequestId: '7101db09af0db2', + auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + params: getParams() + }] + })); +}; + +let getValidBidRequests = () => { + return JSON.parse(JSON.stringify([ + { + 'bidder': 'reload', + 'params': getParams(), + 'mediaTypes': { + 'banner': { + 'sizes': [[160, 600]] + } + }, + 'adUnitCode': '1b243858-3c53-43dc-9fdf-89f839ea4a0f', + 'transactionId': '8cbafa10-123d-4673-a1a5-04a1c7d62ded', + 'sizes': [[160, 600]], + 'bidId': '2236e11dc09931', + 'bidderRequestId': '1266bb886c2267', + 'auctionId': '4fb72c4d-94dc-4db1-8fac-3c2090ceeec0', + 'src': 'client', + 'bidRequestsCount': 1 + } + ])); +} + +let getExt1ServerResponse = () => { + return JSON.parse(JSON.stringify({ + 'pcmdata': { + 'thisVer': '100', + 'plcmSett': { + 'name': 'zz_test_mariano_adapter', + 'Version': '210', + 'lifeSpan': '100', + 'versionFolder': 'v4.14q', + 'versionFolderA': 'v4.14q', + 'versionFolderB': '', + 'stage': 'zz_test_mariano_adapter', + 'synchro': 1556916507000, + 'localCache': 'true', + 'testCase': 'A:00_B:100', + 'opdomain': '1', + 'checksum': '6378', + 'cmp': '0', + 'bstfct': '100', + 'totstop': 'false', + 'pcmurl': 'bidsrv01.reload.net' + }, + 'srvUrl': 'bidsrv01.reload.net', + 'instr': {'go': true, 'prc': 32, 'cur': 'USD'}, + 'statStr': 'eyN4aHYnQCk5OTotOC', + 'status': 'ok', + 'message': '', + 'log': '---- LOG ----' + }, + 'plcmID': 'zz_test_mariano_adapter', + 'partID': 'prx_part', + 'opdomID': '0', + 'bsrvID': 1, + 'banner': {'w': 300, 'h': 250} + })); +} + +let getExt2ServerResponse = () => { + return JSON.parse(JSON.stringify({ + 'pcmdata': { + 'thisVer': '100', + 'plcmSett': { + 'name': 'placement_01', + 'Version': '210', + 'lifeSpan': '100', + 'versionFolder': 'v4.14q', + 'versionFolderA': 'v4.14q', + 'versionFolderB': '', + 'stage': 'placement_01', + 'synchro': 1556574760000, + 'localCache': 'true', + 'testCase': 'A:00_B:100', + 'opdomain': '1', + 'checksum': '6378', + 'cmp': '0', + 'bstfct': '100', + 'totstop': 'false', + 'pcmurl': 'bidsrv00.reload.net' + }, + 'srvUrl': 'bidsrv00.reload.net', + 'log': 'incomp_input_obj_version', + 'message': 'incomp_input_obj_version', + 'status': 'error' + }, + 'plcmID': 'placement_01', + 'partID': 'prx_part', + 'opdomID': '0', + 'bsrvID': 1, + 'banner': {'w': 160, 'h': 600} + })); +} + +let getServerResponse = (pExt) => { + return JSON.parse(JSON.stringify({ + 'body': { + 'id': '2759340f70210d', + 'bidid': 'fbs-br-3mzdbycetjv8f8079', + 'seatbid': [ + { + 'bid': [ + { + 'id': 'fbs-br-stbd-bd-3mzdbycetjv8f807b', + 'price': 0, + 'nurl': '', + 'adm': '', + 'ext': pExt + } + ], + 'seat': 'fbs-br-stbd-3mzdbycetjv8f807a', + 'group': 0 + } + ] + }, + 'headers': {} + })); +} + +describe('ReloadAdapter', function () { + describe('isBidRequestValid', function () { + var bid = { + 'bidder': 'reload', + 'params': { + 'plcmID': 'placement_01', + 'partID': 'part00', + 'opdomID': 1, + 'bsrvID': 23, + 'type': 'pcm' + }, + '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 false when bsrvID is not number', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'plcmID': 'placement_01', + 'partID': 'part00', + 'opdomID': 1, + 'bsrvID': 'abc' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when bsrvID > 99', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'plcmID': 'placement_01', + 'partID': 'part00', + 'opdomID': 1, + 'bsrvID': 230 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when bsrvID < 0', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'plcmID': 'placement_01', + 'partID': 'part00', + 'opdomID': 1, + 'bsrvID': -3, + 'type': 'pcm' + }; + 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 = { + 'plcmID': 'placement_01' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests()', function () { + let vRequests = spec.buildRequests(getValidBidRequests(), {}); + let vData = JSON.parse(vRequests[0].data); + + it('should send one requests', () => { + expect(vRequests.length).to.equal(1); + }); + + it('should send one requests, one impression', () => { + expect(vData.imp.length).to.equal(1); + }); + + it('should exists ext.type and ext.pcmdata', () => { + expect(vData.imp[0].banner).to.exist; + expect(vData.imp[0].banner.ext).to.exist; + expect(vData.imp[0].banner.ext.type).to.exist; + expect(vData.imp[0].banner.ext.pcmdata).to.exist; + expect(vData.imp[0].banner.ext.type).to.equal('pcm'); + }); + }); + + describe('interpretResponse()', function () { + it('Returns an empty array', () => { + let vData = spec.interpretResponse(getServerResponse(getExt2ServerResponse()), {}); + + expect(vData.length).to.equal(0); + }); + + it('Returns an array with one response', () => { + let vData = spec.interpretResponse(getServerResponse(getExt1ServerResponse()), {}); + expect(vData.length).to.equal(1); + }); + + it('required fileds', () => { + let vData = spec.interpretResponse(getServerResponse(getExt1ServerResponse()), {}); + expect(vData.length).to.equal(1); + expect(vData[0]).to.have.all.keys(['requestId', 'ad', 'cpm', 'width', 'height', 'creativeId', 'currency', 'ttl', 'netRevenue']); + }); + + it('CPM great than 0', () => { + let vData = spec.interpretResponse(getServerResponse(getExt1ServerResponse()), {}); + expect(vData[0].cpm).to.greaterThan(0); + }); + + it('instruction empty', () => { + let vResponse = Object.assign({}, getServerResponse(getExt1ServerResponse())); + vResponse.body.seatbid[0].bid[0].ext.pcmdata.instr = null; + let vData = spec.interpretResponse(vResponse, {}); + expect(vData.length).to.equal(0); + + vResponse = Object.assign({}, getServerResponse(getExt1ServerResponse())); + vResponse.body.seatbid[0].bid[0].ext.pcmdata.instr = undefined; + vData = spec.interpretResponse(vResponse, {}); + expect(vData.length).to.equal(0); + + vResponse = Object.assign({}, getServerResponse(getExt1ServerResponse())); + vResponse.body.seatbid[0].bid[0].ext.pcmdata.instr.go = undefined; + vData = spec.interpretResponse(vResponse, {}); + expect(vData.length).to.equal(0); + }); + + it('instruction with go = false', () => { + let vResponse = getServerResponse(getExt1ServerResponse()); + vResponse.body.seatbid[0].bid[0].ext.pcmdata.instr.go = false; + let vData = spec.interpretResponse(vResponse, {}); + expect(vData.length).to.equal(0); + }); + + it('incompatibility output object version (thisVer)', () => { + let vResponse = getServerResponse(getExt1ServerResponse()); + vResponse.body.seatbid[0].bid[0].ext.pcmdata.thisVer = '200'; + let vData = spec.interpretResponse(vResponse, {}); + expect(vData.length).to.equal(0); + }); + }); +}); From 141ae9fc56c6c3d2858c4d76599ad8b13d80225c Mon Sep 17 00:00:00 2001 From: Valentin Date: Thu, 16 May 2019 15:04:41 +0200 Subject: [PATCH 1227/1594] Teads-Adapter: Update way to find referrer (#3829) * Update way to find referrer * Add test * Delete npm-debug.log --- modules/teadsBidAdapter.js | 10 +++++++++- test/spec/modules/teadsBidAdapter_spec.js | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js index 13e6da40d97..92cfce312b1 100644 --- a/modules/teadsBidAdapter.js +++ b/modules/teadsBidAdapter.js @@ -40,7 +40,7 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { const bids = validBidRequests.map(buildRequestObject); const payload = { - referrer: utils.getTopWindowUrl(), + referrer: getReferrerInfo(bidderRequest), data: bids, deviceWidth: screen.width }; @@ -102,6 +102,14 @@ export const spec = { } }; +function getReferrerInfo(bidderRequest) { + let ref = ''; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + ref = bidderRequest.refererInfo.referer; + } + return ref; +} + function findGdprStatus(gdprApplies, gdprData) { let status = gdprStatus.GDPR_APPLIES_PUBLISHER; diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js index 20fdbe947c0..57484d79b05 100644 --- a/test/spec/modules/teadsBidAdapter_spec.js +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -132,6 +132,22 @@ describe('teadsBidAdapter', function() { expect(payload.gdpr_iab.status).to.equal(12); }); + it('should add referer info to payload', function () { + const bidRequest = Object.assign({}, bidRequests[0]) + const bidderRequest = { + refererInfo: { + referer: 'http://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('http://example.com/page.html') + }); + it('should send GDPR to endpoint with 11 status', function() { let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; let bidderRequest = { From d0b391f316a6ea4c69380802f9d3b47b6173f039 Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Mon, 20 May 2019 13:32:55 +0100 Subject: [PATCH 1228/1594] Added size id 265 (1920x1080) (#3839) --- modules/rubiconBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 55937a3feda..eaa5b322811 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -79,7 +79,8 @@ var sizeMap = { 214: '980x360', 229: '320x180', 232: '580x400', - 257: '400x600' + 257: '400x600', + 265: '1920x1080' }; utils._each(sizeMap, (item, key) => sizeMap[item] = key); From 034b57e5f4e3a02419e6a9ba6705cafef3ec605e Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 20 May 2019 08:37:41 -0400 Subject: [PATCH 1229/1594] add renderer param in appnexus adapter request (#3836) --- modules/appnexusBidAdapter.js | 4 ++ test/spec/modules/appnexusBidAdapter_spec.js | 42 ++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 4fe5aec3f7a..a27a10d4372 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -538,6 +538,10 @@ function bidToTag(bid) { .forEach(param => tag.video[param] = bid.params.video[param]); } + if (bid.renderer) { + tag.video = Object.assign({}, tag.video, {custom_renderer_present: true}); + } + if ( (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) || (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER])) diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index a800d4b0f93..312201e347d 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -150,6 +150,48 @@ describe('AppNexusAdapter', function () { }); }); + 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: 'http://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: ['auto_play_sound_off'], + custom_renderer_present: true + }); + expect(payload.tags[1].video).to.deep.equal({ + skippable: true, + playback_method: ['auto_play_sound_off'] + }); + }); + it('should attach valid user params to the tag', function () { let bidRequest = Object.assign({}, bidRequests[0], From 45b519a9b589376f8f496789bf94b46600500ee4 Mon Sep 17 00:00:00 2001 From: Alexander Pykhteyev Date: Mon, 20 May 2019 15:51:37 +0300 Subject: [PATCH 1230/1594] Project Limelight bidder adapter (#3835) * Add Project Limelight adapter * Change to relative paths --- modules/projectLimeLightBidAdapter.js | 125 +++++++++++++ modules/projectLimeLightBidAdapter.md | 55 ++++++ .../projectLimeLightBidAdapter_spec.js | 170 ++++++++++++++++++ 3 files changed, 350 insertions(+) create mode 100644 modules/projectLimeLightBidAdapter.js create mode 100644 modules/projectLimeLightBidAdapter.md create mode 100644 test/spec/modules/projectLimeLightBidAdapter_spec.js diff --git a/modules/projectLimeLightBidAdapter.js b/modules/projectLimeLightBidAdapter.js new file mode 100644 index 00000000000..b0de181315e --- /dev/null +++ b/modules/projectLimeLightBidAdapter.js @@ -0,0 +1,125 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import {ajax} from '../src/ajax'; +import * as utils from '../src/utils'; + +const BIDDER_CODE = 'project-limelight'; +const URL = '//ads.project-limelight.com/hb'; + +/** + * Determines whether or not the given bid response is valid. + * + * @param {object} bid The bid to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ +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.vastXml || bid.vastUrl); + } + return false; +} + +function extractBidSizes(bid) { + const bidSizes = []; + + bid.sizes.forEach(size => { + bidSizes.push({ + width: size[0], + height: size[1] + }); + }); + + return bidSizes; +} + +export const spec = { + code: BIDDER_CODE, + 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: (bid) => { + return Boolean(bid.bidId && bid.params); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: (validBidRequests, bidderRequest) => { + let winTop; + try { + winTop = window.top; + winTop.location.toString(); + } catch (e) { + utils.logMessage(e); + winTop = window; + }; + const placements = []; + const request = { + 'secure': (location.protocol === 'https:'), + 'deviceWidth': winTop.screen.width, + 'deviceHeight': winTop.screen.height, + 'adUnits': placements + }; + for (let i = 0; i < validBidRequests.length; i++) { + const bid = validBidRequests[i]; + const params = bid.params; + placements.push({ + id: params.adUnitId, + bidId: bid.bidId, + transactionId: bid.transactionId, + sizes: extractBidSizes(bid), + type: params.adUnitType.toUpperCase() + }); + } + return { + method: 'POST', + url: URL, + data: request + }; + }, + + onBidWon: (bid) => { + const cpm = bid.pbMg; + if (bid.nurl !== '') { + bid.nurl = bid.nurl.replace( + /\$\{AUCTION_PRICE\}/, + cpm + ); + ajax(bid.nurl, null); + }; + }, + + /** + * 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: (bidResponses) => { + const res = []; + const bidResponsesBody = bidResponses.body; + const len = bidResponsesBody.length; + for (let i = 0; i < len; i++) { + const bid = bidResponsesBody[i]; + if (isBidResponseValid(bid)) { + res.push(bid); + } + } + return res; + }, +}; + +registerBidder(spec); diff --git a/modules/projectLimeLightBidAdapter.md b/modules/projectLimeLightBidAdapter.md new file mode 100644 index 00000000000..71621983b89 --- /dev/null +++ b/modules/projectLimeLightBidAdapter.md @@ -0,0 +1,55 @@ +# Overview + +``` +Module Name: Project LimeLight SSP Adapter +Module Type: Bidder Adapter +Maintainer: engineering@project-limelight.com +``` + +# Description + +Module that connects to Project Limelight SSP demand sources + +# Test Parameters for banner +``` + var adUnits = [{ + code: 'placementCode', + sizes: [[300, 250]], + bids: [{ + bidder: 'project-limelight', + params: { + adUnitId: 0, + adUnitType: 'banner' + } + }] + } + ]; +``` + +# Test Parameters for video +``` +var videoAdUnit = [{ + code: 'video1', + sizes: [[300, 250]], + bids: [{ + bidder: 'project-limelight', + params: { + adUnitId: 0, + adUnitType: 'video' + } + }] + }]; +``` + +# Configuration + +The Project Limelight Bid Adapter expects Prebid Cache(for video) to be enabled so that we can store and retrieve a single vastXml. + +``` +pbjs.setConfig({ + usePrebidCache: true, + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } +}); +``` diff --git a/test/spec/modules/projectLimeLightBidAdapter_spec.js b/test/spec/modules/projectLimeLightBidAdapter_spec.js new file mode 100644 index 00000000000..434b3fbccb5 --- /dev/null +++ b/test/spec/modules/projectLimeLightBidAdapter_spec.js @@ -0,0 +1,170 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/projectLimeLightBidAdapter'; + +describe('ProjectLimeLightAdapter', function () { + let bid = { + bidId: '2dd581a2b6281d', + bidder: 'project-limelight', + bidderRequestId: '145e1d6a7837c9', + params: { + adUnitId: 123, + adUnitType: 'banner' + }, + placementCode: 'placement_0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' + }; + + describe('buildRequests', function () { + let serverRequest = spec.buildRequests([bid]); + 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('//ads.project-limelight.com/hb'); + }); + 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', 'secure', 'adUnits'); + expect(data.deviceWidth).to.be.a('number'); + expect(data.deviceHeight).to.be.a('number'); + expect(data.secure).to.be.a('boolean'); + let adUnits = data['adUnits']; + for (let i = 0; i < adUnits.length; i++) { + let adUnit = adUnits[i]; + expect(adUnit).to.have.all.keys('id', 'bidId', 'type', 'sizes', 'transactionId'); + expect(adUnit.id).to.be.a('number'); + expect(adUnit.bidId).to.be.a('string'); + expect(adUnit.type).to.be.a('string'); + expect(adUnit.transactionId).to.be.a('string'); + expect(adUnit.sizes).to.be.an('array'); + } + }); + it('Returns empty data if no valid requests are passed', function () { + serverRequest = spec.buildRequests([]); + let data = serverRequest.data; + expect(data.adUnits).to.be.an('array').that.is.empty; + }); + }); + describe('interpretBannerResponse', function () { + let resObject = { + body: [ { + requestId: '123', + mediaType: 'banner', + cpm: 0.3, + width: 320, + height: 50, + ad: '

    Hello ad

    ', + ttl: 1000, + creativeId: '123asd', + netRevenue: true, + currency: 'USD' + } ] + }; + let serverResponses = spec.interpretResponse(resObject); + it('Returns an array of valid server responses if response object is valid', function () { + 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'); + 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'); + } + it('Returns an empty array if invalid response is passed', function () { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); + describe('interpretVideoResponse', function () { + let resObject = { + body: [ { + requestId: '123', + mediaType: 'video', + cpm: 0.3, + width: 320, + height: 50, + vastXml: '', + ttl: 1000, + creativeId: '123asd', + netRevenue: true, + currency: 'USD' + } ] + }; + let serverResponses = spec.interpretResponse(resObject); + it('Returns an array of valid server responses if response object is valid', function () { + 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', 'vastXml', 'ttl', 'creativeId', + 'netRevenue', 'currency', 'mediaType'); + 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.vastXml).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'); + } + it('Returns an empty array if invalid response is passed', function () { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); + describe('isBidRequestValid', function() { + let bid = { + bidId: '2dd581a2b6281d', + bidder: 'project-limelight', + bidderRequestId: '145e1d6a7837c9', + params: { + adUnitId: 123, + adUnitType: 'banner' + }, + placementCode: 'placement_0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' + }; + + 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 bidFailed = { + bidder: 'project-limelight', + bidderRequestId: '145e1d6a7837c9', + params: { + adUnitId: 123, + adUnitType: 'banner' + }, + placementCode: 'placement_0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' + }; + expect(spec.isBidRequestValid(bidFailed)).to.equal(false); + }); + }); +}); From 006eecc004a30c82b678ffd9d9b5b84dd009da63 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 20 May 2019 14:12:38 -0700 Subject: [PATCH 1231/1594] PubMatic adapter support to read TTD Id from UserId module (#3834) * in-dev * added unit test cases * adding isStr check on userId.tdid * review suggestion --- modules/pubmaticBidAdapter.js | 19 ++++-- test/spec/modules/pubmaticBidAdapter_spec.js | 70 ++++++++++++++++++++ 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index c791acd9485..1f9ea06cad2 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -601,13 +601,20 @@ function _handleDigitrustId(eids) { } } -function _handleTTDId(eids) { +function _handleTTDId(eids, validBidRequests) { + let ttdId = null; let adsrvrOrgId = config.getConfig('adsrvrOrgId'); - if (adsrvrOrgId && utils.isStr(adsrvrOrgId.TDID)) { + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) { + ttdId = validBidRequests[0].userId.tdid; + } else if (adsrvrOrgId && utils.isStr(adsrvrOrgId.TDID)) { + ttdId = adsrvrOrgId.TDID; + } + + if (ttdId !== null) { eids.push({ 'source': 'adserver.org', 'uids': [{ - 'id': adsrvrOrgId.TDID, + 'id': ttdId, 'atype': 1, 'ext': { 'rtiPartner': 'TDID' @@ -617,10 +624,10 @@ function _handleTTDId(eids) { } } -function _handleEids(payload) { +function _handleEids(payload, validBidRequests) { let eids = []; _handleDigitrustId(eids); - _handleTTDId(eids); + _handleTTDId(eids, validBidRequests); if (eids.length > 0) { payload.user.eids = eids; } @@ -877,7 +884,7 @@ export const spec = { } } - _handleEids(payload); + _handleEids(payload, validBidRequests); _blockedIabCategoriesValidation(payload, blockedIabCategories); return { method: 'POST', diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index b25fd22f822..6126c0f9fd8 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1235,6 +1235,76 @@ describe('PubMatic adapter', function () { }); }); + describe('AdsrvrOrgId from userId module', function() { + let sandbox; + beforeEach(() => { + sandbox = sinon.sandbox.create(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('Request should have AdsrvrOrgId config params', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.tdid = 'TTD_ID_FROM_USER_ID_MODULE'; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'adserver.org', + 'uids': [{ + 'id': 'TTD_ID_FROM_USER_ID_MODULE', + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' + } + }] + }]); + }); + + it('Request should have adsrvrOrgId from UserId Module if config and userId module both have TTD ID', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + var config = { + adsrvrOrgId: { + 'TDID': 'TTD_ID_FROM_CONFIG', + 'TDID_LOOKUP': 'TRUE', + 'TDID_CREATED_AT': '2018-10-01T07:05:40' + } + }; + return config[key]; + }); + bidRequests[0].userId = {}; + bidRequests[0].userId.tdid = 'TTD_ID_FROM_USER_ID_MODULE'; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'adserver.org', + 'uids': [{ + 'id': 'TTD_ID_FROM_USER_ID_MODULE', + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' + } + }] + }]); + }); + + it('Request should NOT have adsrvrOrgId params if userId is NOT object', function() { + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + }); + + it('Request should NOT have adsrvrOrgId params if userId.tdid is NOT string', function() { + bidRequests[0].userId = { + tdid: 1234 + }; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal(undefined); + }); + }); + describe('AdsrvrOrgId and Digitrust', function() { // here we are considering cases only of accepting DigiTrustId from config let sandbox; From d3faa6ac65381bb29375c105a11ba73a999c64d1 Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Mon, 20 May 2019 22:15:34 +0100 Subject: [PATCH 1232/1594] Added 240x400 size (#3809) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index eaa5b322811..aeb6418eea8 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -25,6 +25,7 @@ var sizeMap = { 14: '250x250', 15: '300x250', 16: '336x280', + 17: '240x400', 19: '300x100', 31: '980x120', 32: '250x360', From 7846560af7f8f982aed1d48e64d68b8b9b4ae28c Mon Sep 17 00:00:00 2001 From: CPMStar Date: Tue, 21 May 2019 08:35:26 -0700 Subject: [PATCH 1233/1594] CPMStar Bid Adapter (#3820) * Added CPMStar Bid Adapter * Updated getPlayerSize for cpmstarBidAdapter * Improved cpmstarBidAdapter code coverage * updated test spec, removed empty functions, made imports relative, added warnings to erroneous server responses, and removed the default value for ad in bid response. * added test video ad unit --- modules/cpmstarBidAdapter.js | 118 +++++++++++++++ modules/cpmstarBidAdapter.md | 50 +++++++ test/spec/modules/cpmstarBidAdapter_spec.js | 158 ++++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100755 modules/cpmstarBidAdapter.js create mode 100755 modules/cpmstarBidAdapter.md create mode 100755 test/spec/modules/cpmstarBidAdapter_spec.js diff --git a/modules/cpmstarBidAdapter.js b/modules/cpmstarBidAdapter.js new file mode 100755 index 00000000000..84b76cbbc35 --- /dev/null +++ b/modules/cpmstarBidAdapter.js @@ -0,0 +1,118 @@ + +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import {VIDEO, BANNER} from '../src/mediaTypes'; + +const BIDDER_CODE = 'cpmstar'; + +const ENDPOINT_DEV = '//dev.server.cpmstar.com/view.aspx'; +const ENDPOINT_STAGING = '//staging.server.cpmstar.com/view.aspx'; +const ENDPOINT_PRODUCTION = '//server.cpmstar.com/view.aspx'; + +const DEFAULT_TTL = 300; +const DEFAULT_CURRENCY = 'USD'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + pageID: Math.floor(Math.random() * 10e6), + + getMediaType: function(bidRequest) { + if (bidRequest == null) return BANNER; + return !utils.deepAccess(bidRequest, 'mediaTypes.video') ? BANNER : VIDEO; + }, + + getPlayerSize: function(bidRequest) { + 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]; + return playerSize; + }, + + isBidRequestValid: function (bid) { + return ((typeof bid.params.placementId === 'string') && !!bid.params.placementId.length) || (typeof bid.params.placementId === 'number'); + }, + + buildRequests: function (validBidRequests, bidderRequest) { + var requests = []; + // This reference to window.top can cause issues when loaded in an iframe if not protected with a try/catch. + + for (var i = 0; i < validBidRequests.length; i++) { + var bidRequest = validBidRequests[i]; + var referer = encodeURIComponent(bidderRequest.refererInfo.referer); + 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]) : ''); + requests.push({ + method: 'GET', + url: ENDPOINT + '?media=' + mediaType + (mediaType == VIDEO ? videoArgs : '') + '&json=c_b&mv=1&poolid=' + utils.getBidIdParameter('placementId', bidRequest.params) + '&reachedTop=' + encodeURIComponent(bidderRequest.refererInfo.reachedTop) + '&requestid=' + bidRequest.bidId + '&referer=' + referer, + bidRequest: bidRequest, + }); + } + + return requests; + }, + + interpretResponse: function (serverResponse, request) { + var bidRequest = request.bidRequest; + var mediaType = spec.getMediaType(bidRequest); + + var bidResponses = []; + + if (!Array.isArray(serverResponse.body)) { + serverResponse.body = [serverResponse.body]; + } + + for (var i = 0; i < serverResponse.body.length; i++) { + var raw = serverResponse.body[i]; + var rawBid = raw.creatives[0]; + if (!rawBid) { + utils.logWarn('cpmstarBidAdapter: server response failed check'); + return; + } + var cpm = (parseFloat(rawBid.cpm) || 0); + + if (!cpm) { + utils.logWarn('cpmstarBidAdapter: server response failed check. Missing cpm') + return; + } + + var bidResponse = { + requestId: rawBid.requestid, + cpm: cpm, + width: rawBid.width || 0, + height: rawBid.height || 0, + currency: rawBid.currency ? rawBid.currency : DEFAULT_CURRENCY, + netRevenue: rawBid.netRevenue ? rawBid.netRevenue : true, + ttl: rawBid.ttl ? rawBid.ttl : DEFAULT_TTL, + creativeId: rawBid.creativeid || 0, + }; + + if (rawBid.hasOwnProperty('dealId')) { + bidResponse.dealId = rawBid.dealId + } + + if (mediaType == BANNER && rawBid.code) { + bidResponse.ad = rawBid.code + (rawBid.px_cr ? "\n" : ''); + } else if (mediaType == VIDEO && rawBid.creativemacros && rawBid.creativemacros.HTML5VID_VASTSTRING) { + var playerSize = spec.getPlayerSize(bidRequest); + if (playerSize != null) { + bidResponse.width = playerSize[0]; + bidResponse.height = playerSize[1]; + } + bidResponse.mediaType = VIDEO; + bidResponse.vastXml = rawBid.creativemacros.HTML5VID_VASTSTRING; + } else { + return utils.logError('bad response', rawBid); + } + + bidResponses.push(bidResponse); + } + + return bidResponses; + } +}; +registerBidder(spec); diff --git a/modules/cpmstarBidAdapter.md b/modules/cpmstarBidAdapter.md new file mode 100755 index 00000000000..7dab435b0f0 --- /dev/null +++ b/modules/cpmstarBidAdapter.md @@ -0,0 +1,50 @@ +# Overview + +``` +Module Name: Cpmstar Bidder Adapter +Module Type: Bidder Adapter +Maintainer: josh@cpmstar.com +``` + +# Description + +Module that connects to Cpmstar's demand sources + +# Test Parameters +``` +var adUnits = [ + { + code: 'banner-ad-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + bids: [ + { + bidder: 'cpmstar', + params: { + placementId: 81006 + } + }, + ] + }, + { + code: 'video-ad-div', + mediaTypes: { + video: { + context: 'instream', + sizes: [[640, 480]] + } + }, + bids:[ + { + bidder: 'cpmstar', + params: { + placementId: 81007 + } + } + ] + } +]; +``` \ No newline at end of file diff --git a/test/spec/modules/cpmstarBidAdapter_spec.js b/test/spec/modules/cpmstarBidAdapter_spec.js new file mode 100755 index 00000000000..3dd06a484d9 --- /dev/null +++ b/test/spec/modules/cpmstarBidAdapter_spec.js @@ -0,0 +1,158 @@ +import { expect } from 'chai'; +import { spec } from 'modules/cpmstarBidAdapter'; +import { deepClone } from 'src/utils'; + +describe('Cpmstar Bid Adapter', function () { + describe('isBidRequestValid', function () { + it('should return true since the bid is valid', + function () { + var bid = { params: { placementId: 123456 } }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }) + + it('should return false since the bid is invalid', function () { + var bid = { params: { placementId: '' } }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }) + + it('should return a valid player size', function() { + var bid = { mediaTypes: { + video: { + playerSize: [[960, 540]] + } + }} + expect(spec.getPlayerSize(bid)[0]).to.equal(960); + expect(spec.getPlayerSize(bid)[1]).to.equal(540); + }) + + it('should return a default player size', function() { + var bid = { mediaTypes: { + video: { + playerSize: null + } + }} + expect(spec.getPlayerSize(bid)[0]).to.equal(640); + expect(spec.getPlayerSize(bid)[1]).to.equal(440); + }) + }); + + describe('buildRequests', function () { + const valid_bid_requests = [{ + 'bidder': 'cpmstar', + 'params': { + 'placementId': '57' + }, + 'sizes': [[300, 250]], + 'bidId': 'bidId' + }]; + + const bidderRequest = { + refererInfo: { + referer: 'referer', + reachedTop: false, + } + + }; + + it('should produce a valid production request', function () { + var requests = spec.buildRequests(valid_bid_requests, bidderRequest); + expect(requests[0]).to.have.property('method'); + expect(requests[0]).to.have.property('url'); + expect(requests[0]).to.have.property('bidRequest'); + expect(requests[0].url).to.include('//server.cpmstar.com/view.aspx'); + }); + it('should produce a valid staging request', function () { + var stgReq = deepClone(valid_bid_requests); + stgReq[0].params.endpoint = 'staging'; + var requests = spec.buildRequests(stgReq, bidderRequest); + expect(requests[0]).to.have.property('method'); + expect(requests[0]).to.have.property('url'); + expect(requests[0]).to.have.property('bidRequest'); + expect(requests[0].url).to.include('//staging.server.cpmstar.com/view.aspx'); + }); + it('should produce a valid dev request', function () { + var devReq = deepClone(valid_bid_requests); + devReq[0].params.endpoint = 'dev'; + var requests = spec.buildRequests(devReq, bidderRequest); + expect(requests[0]).to.have.property('method'); + expect(requests[0]).to.have.property('url'); + expect(requests[0]).to.have.property('bidRequest'); + expect(requests[0].url).to.include('//dev.server.cpmstar.com/view.aspx'); + }); + }) + + describe('interpretResponse', function () { + const request = { + bidRequest: { + mediaType: 'BANNER' + } + }; + const serverResponse = { + body: [{ + creatives: [{ + cpm: 1, + width: 0, + height: 0, + currency: 'USD', + netRevenue: true, + ttl: 1, + creativeid: '1234', + requestid: '11123', + code: 'no idea', + media: 'banner', + } + ], + }] + }; + + it('should return a valid bidresponse array', function () { + var r = spec.interpretResponse(serverResponse, request) + var c = serverResponse.body[0].creatives[0]; + expect(r[0].length).to.not.equal(0); + expect(r[0].requestId).equal(c.requestid); + expect(r[0].creativeId).equal(c.creativeid); + expect(r[0].cpm).equal(c.cpm); + expect(r[0].width).equal(c.width); + expect(r[0].height).equal(c.height); + expect(r[0].currency).equal(c.currency); + expect(r[0].netRevenue).equal(c.netRevenue); + expect(r[0].ttl).equal(c.ttl); + expect(r[0].ad).equal(c.code); + }); + + it('should return a valid bidresponse array from a non-array-body', function () { + var r = spec.interpretResponse({ body: serverResponse.body[0] }, request) + var c = serverResponse.body[0].creatives[0]; + expect(r[0].length).to.not.equal(0); + expect(r[0].requestId).equal(c.requestid); + expect(r[0].creativeId).equal(c.creativeid); + expect(r[0].cpm).equal(c.cpm); + expect(r[0].width).equal(c.width); + expect(r[0].height).equal(c.height); + expect(r[0].currency).equal(c.currency); + expect(r[0].netRevenue).equal(c.netRevenue); + expect(r[0].ttl).equal(c.ttl); + expect(r[0].ad).equal(c.code); + }); + + it('should return undefined due to an invalid cpm value', function () { + var badServer = deepClone(serverResponse); + badServer.body[0].creatives[0].cpm = 0; + var c = spec.interpretResponse(badServer, request); + expect(c).to.be.undefined; + }); + + it('should return undefined due to a bad response', function () { + var badServer = deepClone(serverResponse); + badServer.body[0].creatives[0].code = null; + var c = spec.interpretResponse(badServer, request); + expect(c).to.be.undefined; + }); + + it('should return a valid response with a dealId', function () { + var dealServer = deepClone(serverResponse); + dealServer.body[0].creatives[0].dealId = 'deal'; + expect(spec.interpretResponse(dealServer, request)[0].dealId).to.equal('deal'); + }); + }); +}); From d55b253dd52fb7f4708e10da60393de55d6c8b6f Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 21 May 2019 12:08:39 -0700 Subject: [PATCH 1234/1594] support external userId sub-modules (#3831) --- modules/pubCommonIdSystem.js | 42 ++++ modules/unifiedIdSystem.js | 55 ++++ modules/userId.js | 419 +++++++++++++++---------------- modules/userId.md | 4 +- test/spec/modules/userId_spec.js | 226 ++++++++++++----- 5 files changed, 464 insertions(+), 282 deletions(-) create mode 100644 modules/pubCommonIdSystem.js create mode 100644 modules/unifiedIdSystem.js diff --git a/modules/pubCommonIdSystem.js b/modules/pubCommonIdSystem.js new file mode 100644 index 00000000000..39d1feea0ad --- /dev/null +++ b/modules/pubCommonIdSystem.js @@ -0,0 +1,42 @@ +/** + * This module adds PubCommonId to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/pubCommonIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils.js' + +/** @type {Submodule} */ +export const pubCommonIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'pubCommonId', + /** + * decode the stored id value for passing to bid requests + * @function + * @param {string} value + * @returns {{pubcid:string}} + */ + decode(value) { + return { 'pubcid': value } + }, + /** + * performs action to obtain id + * @function + * @returns {string} + */ + getId() { + // If the page includes its own pubcid object, then use that instead. + let pubcid; + try { + if (typeof window['PublisherCommonId'] === 'object') { + pubcid = window['PublisherCommonId'].getId(); + } + } catch (e) {} + // check pubcid and return if valid was otherwise create a new id + return (pubcid) || utils.generateUUID(); + } +}; diff --git a/modules/unifiedIdSystem.js b/modules/unifiedIdSystem.js new file mode 100644 index 00000000000..6b67b7bf5f1 --- /dev/null +++ b/modules/unifiedIdSystem.js @@ -0,0 +1,55 @@ +/** + * This module adds UnifiedId to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/unifiedIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils.js' +import {ajax} from '../src/ajax.js'; + +/** @type {Submodule} */ +export const unifiedIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'unifiedId', + /** + * decode the stored id value for passing to bid requests + * @function + * @param {{TDID:string}} value + * @returns {{tdid:Object}} + */ + decode(value) { + return (value && typeof value['TDID'] === 'string') ? { 'tdid': value['TDID'] } : undefined; + }, + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @param {SubmoduleParams} [configParams] + * @returns {function(callback:function)} + */ + getId(configParams) { + if (!configParams || (typeof configParams.partner !== 'string' && typeof configParams.url !== 'string')) { + utils.logError('User ID - unifiedId submodule requires either partner or url to be defined'); + return; + } + // use protocol relative urls for http or https + const url = configParams.url || `//match.adsrvr.org/track/rid?ttd_pid=${configParams.partner}&fmt=json`; + + return function (callback) { + ajax(url, response => { + let responseObj; + if (response) { + try { + responseObj = JSON.parse(response); + } catch (error) { + utils.logError(error); + } + } + callback(responseObj); + }, undefined, { method: 'GET' }); + } + } +}; diff --git a/modules/userId.js b/modules/userId.js index bddada7ffbc..ae06dfc4027 100644 --- a/modules/userId.js +++ b/modules/userId.js @@ -1,138 +1,122 @@ /** * This module adds User ID support to prebid.js + * @module modules/userId */ -import {ajax} from '../src/ajax.js'; -import {config} from '../src/config.js'; -import events from '../src/events.js'; -import * as utils from '../src/utils.js'; -import find from 'core-js/library/fn/array/find'; -import {gdprDataHandler} from '../src/adapterManager.js'; -const CONSTANTS = require('../src/constants.json'); +/** + * @interface Submodule + */ /** - * @typedef {Object} SubmoduleConfig - * @property {string} name - the User ID submodule name - * @property {SubmoduleStorage} storage - browser storage config - * @property {SubmoduleParams} params - params config for use by the submodule.getId function - * @property {Object} value - all object properties will be appended to the User ID bid data + * @function + * @summary performs action to obtain id and return a value in the callback's response argument + * @name Submodule#getId + * @param {SubmoduleParams} configParams + * @param {ConsentData} consentData + * @return {(Object|function} id data or a callback, the callback is called on the auction end event */ /** - * @typedef {Object} SubmoduleStorage - * @property {string} type - browser storage type (html5 or cookie) - * @property {string} name - key name to use when saving/reading to local storage or cookies - * @property {number} expires - time to live for browser cookie + * @function + * @summary decode a stored value for passing to bid requests + * @name Submodule#decode + * @param {Object|string} value + * @return {(Object|undefined} */ /** - * @typedef {Object} SubmoduleParams - * @property {string} partner - partner url param value - * @property {string} url - webservice request url used to load Id data + * @property + * @summary used to link submodule with config + * @name Submodule#name + * @type {string} */ /** - * @typedef {Object} Submodule - * @property {string} name - submodule and config have matching name prop - * @property {decode} decode - decode a stored value for passing to bid requests - * @property {getId} getId - performs action to obtain id and return a value in the callback's response argument + * @typedef {Object} SubmoduleConfig + * @property {string} name - the User ID submodule name (used to link submodule with config) + * @property {(SubmoduleStorage|undefined)} storage - browser storage config + * @property {(SubmoduleParams|undefined)} params - params config for use by the submodule.getId function + * @property {(Object|undefined)} value - if not empty, this value is added to bid requests for access in adapters */ /** - * @callback getId - * @param {SubmoduleParams} [submoduleConfigParams] - * @param {Object} [consentData] - * @returns {(Function|Object|string)} + * @typedef {Object} SubmoduleStorage + * @property {string} type - browser storage type (html5 or cookie) + * @property {string} name - key name to use when saving/reading to local storage or cookies + * @property {(number|undefined)} expires - time to live for browser cookie */ /** - * @callback decode - * @param {Object|string} idData - * @returns {Object} + * @typedef {Object} SubmoduleParams + * @property {(string|undefined)} partner - partner url param value + * @property {(string|undefined)} url - webservice request url used to load Id data */ /** * @typedef {Object} SubmoduleContainer * @property {Submodule} submodule - * @property {SubmoduleConfig} submoduleConfig - * @property {Object} idObj - decoded User ID data that will be appended to bids - * @property {function} callback + * @property {SubmoduleConfig} config + * @property {(Object|undefined)} idObj - cache decoded id value (this is copied to every adUnit bid) + * @property {(function|undefined)} callback - holds reference to submodule.getId() result if it returned a function. Will be set to undefined after callback executes */ +/** + * @typedef {Object} ConsentData + * @property {(string|undefined)} consentString + * @property {(Object|undefined)} vendorData + * @property {(boolean|undefined)} gdprApplies + */ + +import find from 'core-js/library/fn/array/find'; +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 {unifiedIdSubmodule} from './unifiedIdSystem.js'; +import {pubCommonIdSubmodule} from './pubCommonIdSystem.js'; +import CONSTANTS from '../src/constants.json'; + const MODULE_NAME = 'User ID'; const COOKIE = 'cookie'; const LOCAL_STORAGE = 'html5'; const DEFAULT_SYNC_DELAY = 500; -// @type {number} delay after auction to make webrequests for id data -export let syncDelay; +/** @type {string[]} */ +let validStorageTypes = []; -// @type {SubmoduleContainer[]} -export let submodules; +/** @type {boolean} */ +let addedUserIdHook = false; -// @type {SubmoduleContainer[]} +/** @type {SubmoduleContainer[]} */ +let submodules = []; + +/** @type {SubmoduleContainer[]} */ let initializedSubmodules; -// @type {Submodule} -export const unifiedIdSubmodule = { - name: 'unifiedId', - decode(value) { - return (value && typeof value['TDID'] === 'string') ? { 'tdid': value['TDID'] } : undefined; - }, - getId(submoduleConfigParams, consentData) { - if (!submoduleConfigParams || (typeof submoduleConfigParams.partner !== 'string' && typeof submoduleConfigParams.url !== 'string')) { - utils.logError(`${MODULE_NAME} - unifiedId submodule requires either partner or url to be defined`); - return; - } - const url = submoduleConfigParams.url || `http://match.adsrvr.org/track/rid?ttd_pid=${submoduleConfigParams.partner}&fmt=json`; - - return function (callback) { - ajax(url, response => { - let responseObj; - if (response) { - try { - responseObj = JSON.parse(response); - } catch (error) { - utils.logError(error); - } - } - callback(responseObj); - }, undefined, { method: 'GET' }); - } - } -}; - -// @type {Submodule} -export const pubCommonIdSubmodule = { - name: 'pubCommonId', - decode(value) { - return { - 'pubcid': value - } - }, - getId() { - // If the page includes its own pubcid object, then use that instead. - let pubcid; - try { - if (typeof window['PublisherCommonId'] === 'object') { - pubcid = window['PublisherCommonId'].getId(); - } - } catch (e) {} - // check pubcid and return if valid was otherwise create a new id - return (pubcid) || utils.generateUUID(); - } -}; +/** @type {SubmoduleConfig[]} */ +let configRegistry = []; + +/** @type {Submodule[]} */ +let submoduleRegistry = []; + +/** @type {(number|undefined)} */ +export let syncDelay; + +/** @param {Submodule[]} submodules */ +export function setSubmoduleRegistry(submodules) { + submoduleRegistry = submodules; +} /** * @param {SubmoduleStorage} storage * @param {string} value - * @param {number|string} expires + * @param {(number|string)} expires */ -export function setStoredValue(storage, value, expires) { +function setStoredValue(storage, value, expires) { try { - const valueStr = (typeof value === 'object') ? JSON.stringify(value) : value; + const valueStr = utils.isPlainObject(value) ? JSON.stringify(value) : value; const expiresStr = (new Date(Date.now() + (expires * (60 * 60 * 24 * 1000)))).toUTCString(); - if (storage.type === COOKIE) { utils.setCookie(storage.name, valueStr, expiresStr); } else if (storage.type === LOCAL_STORAGE) { @@ -148,7 +132,7 @@ export function setStoredValue(storage, value, expires) { * @param {SubmoduleStorage} storage * @returns {string} */ -export function getStoredValue(storage) { +function getStoredValue(storage) { let storedValue; try { if (storage.type === COOKIE) { @@ -164,8 +148,7 @@ export function getStoredValue(storage) { } } } - // we support storing either a string or a stringified object, - // so we test if the string contains an stringified object, and if so convert to an object + // support storing a string or a stringified object if (typeof storedValue === 'string' && storedValue.charAt(0) === '{') { storedValue = JSON.parse(storedValue); } @@ -177,10 +160,10 @@ export function getStoredValue(storage) { /** * test if consent module is present, applies, and is valid for local storage or cookies (purpose 1) - * @param {Object} consentData + * @param {ConsentData} consentData * @returns {boolean} */ -export function hasGDPRConsent(consentData) { +function hasGDPRConsent(consentData) { if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) { if (!consentData.consentString) { return false; @@ -193,18 +176,16 @@ export function hasGDPRConsent(consentData) { } /** - * @param {Object[]} submodules + * @param {SubmoduleContainer[]} submodules */ -export function processSubmoduleCallbacks(submodules) { +function processSubmoduleCallbacks(submodules) { submodules.forEach(function(submodule) { - submodule.callback(function callbackCompleted (idObj) { + submodule.callback(function callbackCompleted(idObj) { // clear callback, this prop is used to test if all submodule callbacks are complete below submodule.callback = undefined; - // if valid, id data should be saved to cookie/html storage if (idObj) { setStoredValue(submodule.config.storage, idObj, submodule.config.storage.expires); - // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.submodule.decode(idObj); } else { @@ -215,25 +196,26 @@ export function processSubmoduleCallbacks(submodules) { } /** - * @param {Object[]} adUnits - * @param {Object[]} submodules + * @param {AdUnit[]} adUnits + * @param {SubmoduleContainer[]} submodules */ -export function addIdDataToAdUnitBids(adUnits, submodules) { - const submodulesWithIds = submodules.filter(item => typeof item.idObj === 'object' && item.idObj !== null); - if (submodulesWithIds.length) { - if (adUnits) { - adUnits.forEach(adUnit => { - adUnit.bids.forEach(bid => { - // append the User ID property to bid - bid.userId = submodulesWithIds.reduce((carry, item) => { - Object.keys(item.idObj).forEach(key => { - carry[key] = item.idObj[key]; - }); - return carry; - }, {}); - }); +function addIdDataToAdUnitBids(adUnits, submodules) { + if ([adUnits, submodules].some(i => !Array.isArray(i) || !i.length)) { + return; + } + 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]; + }); + return carry; + }, {}); + if (Object.keys(combinedSubmoduleIds).length) { + adUnits.forEach(adUnit => { + adUnit.bids.forEach(bid => { + // create a User ID object on the bid, + bid.userId = combinedSubmoduleIds; }); - } + }); } } @@ -243,7 +225,7 @@ export function addIdDataToAdUnitBids(adUnits, submodules) { * The two main actions handled by the hook are: * 1. check gdpr consentData and handle submodule initialization. * 2. append user id data (loaded from cookied/html or from the getId method) to bids to be accessed in adapters. - * @param {object} reqBidsConfigObj required; This is the same param that's used in pbjs.requestBids. + * @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) { @@ -252,7 +234,7 @@ export function requestBidsHook(fn, reqBidsConfigObj) { initializedSubmodules = initSubmodules(submodules, gdprDataHandler.getConsentData()); if (initializedSubmodules.length) { // list of sumodules that have callbacks that need to be executed - const submodulesWithCallbacks = initializedSubmodules.filter(item => typeof item.callback === 'function'); + const submodulesWithCallbacks = initializedSubmodules.filter(item => utils.isFn(item.callback)); if (submodulesWithCallbacks.length) { // wait for auction complete before processing submodule callbacks @@ -273,53 +255,51 @@ export function requestBidsHook(fn, reqBidsConfigObj) { } // pass available user id data to bid adapters - addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || $$PREBID_GLOBAL$$.adUnits, initializedSubmodules); + addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || getGlobal().adUnits, initializedSubmodules); // calling fn allows prebid to continue processing return fn.call(this, reqBidsConfigObj); } /** - * @param {Object[]} submodules - * @param {Object} consentData - * @returns {string[]} initialized submodules + * @param {SubmoduleContainer[]} submodules + * @param {ConsentData} consentData + * @returns {SubmoduleContainer[]} initialized submodules */ -export function initSubmodules(submodules, consentData) { +function initSubmodules(submodules, consentData) { // gdpr consent with purpose one is required, otherwise exit immediately if (!hasGDPRConsent(consentData)) { utils.logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`); return []; } - return submodules.reduce((carry, item) => { + return submodules.reduce((carry, submodule) => { // There are two submodule configuration types to handle: storage or value // 1. storage: retrieve user id data from cookie/html storage or with the submodule's getId method // 2. value: pass directly to bids - if (item.config && item.config.storage) { - const storedId = getStoredValue(item.config.storage); + if (submodule.config.storage) { + const storedId = getStoredValue(submodule.config.storage); if (storedId) { // cache decoded value (this is copied to every adUnit bid) - item.idObj = item.submodule.decode(storedId); + submodule.idObj = submodule.submodule.decode(storedId); } else { // getId will return user id data or a function that will load the data - const getIdResult = item.submodule.getId(item.config.params, consentData); + const getIdResult = submodule.submodule.getId(submodule.config.params, consentData); // If the getId result has a type of function, it is asynchronous and cannot be called until later if (typeof getIdResult === 'function') { - item.callback = getIdResult; + submodule.callback = getIdResult; } else { // A getId result that is not a function is assumed to be valid user id data, which should be saved to users local storage or cookies - setStoredValue(item.config.storage, getIdResult, item.config.storage.expires); - + setStoredValue(submodule.config.storage, getIdResult, submodule.config.storage.expires); // cache decoded value (this is copied to every adUnit bid) - item.idObj = item.submodule.decode(getIdResult); + submodule.idObj = submodule.submodule.decode(getIdResult); } } - } else if (item.config.value) { + } else if (submodule.config.value) { // cache decoded value (this is copied to every adUnit bid) - item.idObj = item.config.value; + submodule.idObj = submodule.config.value; } - - carry.push(item); + carry.push(submodule); return carry; }, []); } @@ -328,102 +308,117 @@ export function initSubmodules(submodules, consentData) { * list of submodule configurations with valid 'storage' or 'value' obj definitions * * storage config: contains values for storing/retrieving User ID data in browser storage * * value config: object properties that are copied to bids (without saving to storage) - * @param {SubmoduleConfig[]} submoduleConfigs - * @param {Submodule[]} enabledSubmodules + * @param {SubmoduleConfig[]} configRegistry + * @param {Submodule[]} submoduleRegistry + * @param {string[]} activeStorageTypes * @returns {SubmoduleConfig[]} */ -export function getValidSubmoduleConfigs(submoduleConfigs, enabledSubmodules) { - if (!Array.isArray(submoduleConfigs)) { +function getValidSubmoduleConfigs(configRegistry, submoduleRegistry, activeStorageTypes) { + if (!Array.isArray(configRegistry)) { return []; } - - // list of browser enabled storage types - const validStorageTypes = []; - if (utils.localStorageIsEnabled()) { - // check if optout exists in local storage (null if returned if key does not exist) - if (!localStorage.getItem('_pbjs_id_optout') && !localStorage.getItem('_pubcid_optout')) { - validStorageTypes.push(LOCAL_STORAGE); - } else { - utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); - } - } - if (utils.cookiesAreEnabled()) { - validStorageTypes.push(COOKIE); - } - - return submoduleConfigs.reduce((carry, submoduleConfig) => { + return configRegistry.reduce((carry, config) => { // every submodule config obj must contain a valid 'name' - if (!submoduleConfig || typeof submoduleConfig.name !== 'string' || !submoduleConfig.name) { + if (!config || utils.isEmptyStr(config.name)) { return carry; } - - // Validate storage config - // contains 'type' and 'name' properties with non-empty string values + // alidate storage config contains 'type' and 'name' properties with non-empty string values // 'type' must be a value currently enabled in the browser - if (submoduleConfig.storage && - typeof submoduleConfig.storage.type === 'string' && submoduleConfig.storage.type && - typeof submoduleConfig.storage.name === 'string' && submoduleConfig.storage.name && - validStorageTypes.indexOf(submoduleConfig.storage.type) !== -1) { - carry.push(submoduleConfig); - } else if (submoduleConfig.value !== null && typeof submoduleConfig.value === 'object') { - // Validate value config - // must be valid object with at least one property - carry.push(submoduleConfig); + if (config.storage && + !utils.isEmptyStr(config.storage.type) && + !utils.isEmptyStr(config.storage.name) && + activeStorageTypes.indexOf(config.storage.type) !== -1) { + carry.push(config); + } else if (utils.isPlainObject(config.value)) { + carry.push(config); } return carry; }, []); } /** - * @param config - * @param {Submodule[]} enabledSubmodules + * update submodules by validating against existing configs and storage types */ -export function init (config, enabledSubmodules) { +function updateSubmodules() { + const configs = getValidSubmoduleConfigs(configRegistry, submoduleRegistry, validStorageTypes); + if (!configs.length) { + return; + } + // do this to avoid reprocessing submodules + const addedSubmodules = submoduleRegistry.filter(i => !find(submodules, j => j.name === i.name)); + + // find submodule and the matching configuration, if found create and append a SubmoduleContainer + submodules = addedSubmodules.map(i => { + const submoduleConfig = find(configs, j => j.name === i.name); + return submoduleConfig ? { + submodule: i, + config: submoduleConfig, + callback: undefined, + idObj: undefined + } : null; + }).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); + utils.logInfo(`${MODULE_NAME} - usersync config updated for ${submodules.length} submodules`); + addedUserIdHook = true; + } +} + +/** + * enable submodule in User ID + * @param {Submodule} submodule + */ +export function attachIdSystem(submodule) { + if (!find(submoduleRegistry, i => i.name === submodule.name)) { + submoduleRegistry.push(submodule); + updateSubmodules(); + } +} + +/** + * test browser support for storage config types (local storage or cookie), initializes submodules but consentManagement is required, + * so a callback is added to fire after the consentManagement module. + * @param {{getConfig:function}} config + */ +export function init(config) { submodules = []; + configRegistry = []; + addedUserIdHook = false; initializedSubmodules = undefined; - // exit immediately if opt out cookie exists. _pubcid_optout is checked for compatiblility with pubCommonId module opt out - if (utils.getCookie('_pbjs_id_optout')) { + // list of browser enabled storage types + validStorageTypes = [ + utils.localStorageIsEnabled() ? LOCAL_STORAGE : null, + utils.cookiesAreEnabled() ? COOKIE : null + ].filter(i => i !== null); + + // exit immediately if opt out cookie or local storage keys exists. + if (validStorageTypes.indexOf(COOKIE) !== -1 && utils.getCookie('_pbjs_id_optout')) { utils.logInfo(`${MODULE_NAME} - opt-out cookie found, exit module`); return; } - + // _pubcid_optout is checked for compatiblility with pubCommonId + if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (localStorage.getItem('_pbjs_id_optout') && localStorage.getItem('_pubcid_optout'))) { + utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); + return; + } // listen for config userSyncs to be set - config.getConfig('usersync', ({usersync}) => { - if (usersync) { - syncDelay = (typeof usersync.syncDelay !== 'undefined') ? usersync.syncDelay : DEFAULT_SYNC_DELAY; - - // filter any invalid configs out - const submoduleConfigs = getValidSubmoduleConfigs(usersync.userIds, enabledSubmodules); - if (submoduleConfigs.length === 0) { - // exit module, if no valid configurations exist - return; - } - - // get list of submodules with valid configurations - submodules = enabledSubmodules.reduce((carry, enabledSubmodule) => { - // try to find submodule configuration for submodule, if config exists it should be enabled - const submoduleConfig = find(submoduleConfigs, item => item.name === enabledSubmodule.name); - - if (submoduleConfig) { - // append {SubmoduleContainer} containing the submodule and config - carry.push({ - submodule: enabledSubmodule, - config: submoduleConfig, - idObj: undefined - }); - } - return carry; - }, []); - - // complete initialization if any submodules exist - if (submodules.length) { - // priority has been set so it loads after consentManagement (which has a priority of 50) - $$PREBID_GLOBAL$$.requestBids.before(requestBidsHook, 40); - utils.logInfo(`${MODULE_NAME} - usersync config updated for ${submodules.length} submodules`); - } + config.getConfig(conf => { + // Note: support for both 'userSync' and 'usersync' will be deprecated with Prebid.js 3.0 + const userSync = conf.userSync || conf.usersync; + if (userSync && userSync.userIds) { + configRegistry = userSync.userIds; + syncDelay = utils.isNumber(userSync.syncDelay) ? userSync.syncDelay : DEFAULT_SYNC_DELAY; + updateSubmodules(); } - }); + }) } -init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); +// init config update listener to start the application +init(config); + +// add submodules after init has been called +attachIdSystem(pubCommonIdSubmodule); +attachIdSystem(unifiedIdSubmodule); diff --git a/modules/userId.md b/modules/userId.md index a873a76674f..782e7782554 100644 --- a/modules/userId.md +++ b/modules/userId.md @@ -3,12 +3,12 @@ Example showing `cookie` storage for user id data for both submodules ``` pbjs.setConfig({ - usersync: { + userSync: { userIds: [{ name: "unifiedId", params: { partner: "prebid", - url: "http://match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" + url: "//match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" }, storage: { type: "cookie", diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index c7901106538..d0f5e06cdad 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -1,24 +1,34 @@ import { init, + requestBidsHook, + setSubmoduleRegistry, syncDelay, - pubCommonIdSubmodule, - unifiedIdSubmodule, - requestBidsHook + attachIdSystem } from 'modules/userId'; import {config} from 'src/config'; import * as utils from 'src/utils'; - +import {unifiedIdSubmodule} from 'modules/unifiedIdSystem'; +import {pubCommonIdSubmodule} from 'modules/pubCommonIdSystem'; let assert = require('chai').assert; let expect = require('chai').expect; +const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; describe('User ID', function() { - const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; - - function createStorageConfig(name = 'pubCommonId', key = 'pubcid', type = 'cookie', expires = 30) { + function getConfigMock(configArr1, configArr2) { + return { + userSync: { + syncDelay: 0, + userIds: [ + (configArr1 && configArr1.length === 3) ? getStorageMock.apply(null, configArr1) : null, + (configArr2 && configArr2.length === 3) ? getStorageMock.apply(null, configArr2) : null + ].filter(i => i)} + } + } + function getStorageMock(name = 'pubCommonId', key = 'pubcid', type = 'cookie', expires = 30) { return { name: name, storage: { name: key, type: type, expires: expires } } } - function createAdUnit(code = 'adUnit-code') { + function getAdUnitMock(code = 'adUnit-code') { return { code, mediaTypes: {banner: {}, native: {}}, @@ -29,6 +39,8 @@ describe('User ID', function() { before(function() { utils.setCookie('_pubcid_optout', '', EXPIRED_COOKIE_DATE); + localStorage.removeItem('_pbjs_id_optout'); + localStorage.removeItem('_pubcid_optout'); }); describe('Decorate Ad Units', function() { @@ -48,16 +60,17 @@ describe('User ID', function() { }); it('Check same cookie behavior', function () { - let adUnits1 = [createAdUnit()]; - let adUnits2 = [createAdUnit()]; + let adUnits1 = [getAdUnitMock()]; + let adUnits2 = [getAdUnitMock()]; let innerAdUnits1; let innerAdUnits2; let pubcid = utils.getCookie('pubcid'); expect(pubcid).to.be.null; // there should be no cookie initially - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); - config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook(config => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); pubcid = utils.getCookie('pubcid'); // cookies is created after requestbidHook @@ -74,15 +87,16 @@ describe('User ID', function() { }); it('Check different cookies', function () { - let adUnits1 = [createAdUnit()]; - let adUnits2 = [createAdUnit()]; + let adUnits1 = [getAdUnitMock()]; + let adUnits2 = [getAdUnitMock()]; let innerAdUnits1; let innerAdUnits2; let pubcid1; let pubcid2; - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); - config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); pubcid1 = utils.getCookie('pubcid'); // get first cookie utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); // erase cookie @@ -94,8 +108,9 @@ describe('User ID', function() { }); }); - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); - config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); pubcid2 = utils.getCookie('pubcid'); // get second cookie @@ -111,15 +126,12 @@ describe('User ID', function() { }); it('Check new cookie', function () { - let adUnits = [createAdUnit()]; + let adUnits = [getAdUnitMock()]; let innerAdUnits; - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); - config.setConfig({ - usersync: { - syncDelay: 0, - userIds: [createStorageConfig('pubCommonId', 'pubcid_alt', 'cookie')]} - }); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie'])); requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { @@ -152,14 +164,16 @@ describe('User ID', function() { }); it('fails initialization if opt out cookie exists', function () { - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); - config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + 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, [pubCommonIdSubmodule, unifiedIdSubmodule]); - config.setConfig({ usersync: { syncDelay: 0, userIds: [ createStorageConfig() ] } }); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); }); }); @@ -176,20 +190,23 @@ describe('User ID', function() { }); it('handles config with no usersync object', function () { - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); 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 () { - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); config.setConfig({ usersync: {} }); expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); it('handles config with usersync and userIds that are empty objs', function () { - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); config.setConfig({ usersync: { userIds: [{}] @@ -199,7 +216,8 @@ describe('User ID', function() { }); it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () { - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); config.setConfig({ usersync: { userIds: [{ @@ -215,21 +233,16 @@ describe('User ID', function() { }); it('config with 1 configurations should create 1 submodules', function () { - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); - config.setConfig({ - usersync: { - syncDelay: 0, - userIds: [{ - name: 'unifiedId', - storage: { name: 'unifiedid', type: 'cookie' } - }] - } - }); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie'])); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); }); it('config with 2 configurations should result in 2 submodules add', function () { - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); config.setConfig({ usersync: { syncDelay: 0, @@ -245,7 +258,8 @@ describe('User ID', function() { }); it('config syncDelay updates module correctly', function () { - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); config.setConfig({ usersync: { syncDelay: 99, @@ -263,19 +277,15 @@ describe('User ID', function() { let adUnits; beforeEach(function() { - adUnits = [createAdUnit()]; + adUnits = [getAdUnitMock()]; }); it('test hook from pubcommonid cookie', function(done) { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 100000).toUTCString())); - init(config, [pubCommonIdSubmodule]); - config.setConfig({ - usersync: { - syncDelay: 0, - userIds: [createStorageConfig('pubCommonId', 'pubcid', 'cookie')] - } - }); + setSubmoduleRegistry([pubCommonIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -290,7 +300,8 @@ describe('User ID', function() { }); it('test hook from pubcommonid config value object', function(done) { - init(config, [pubCommonIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule]); + init(config); config.setConfig({ usersync: { syncDelay: 0, @@ -316,12 +327,9 @@ describe('User ID', function() { localStorage.setItem('unifiedid_alt', JSON.stringify({'TDID': 'testunifiedid_alt'})); localStorage.setItem('unifiedid_alt_exp', ''); - init(config, [unifiedIdSubmodule]); - config.setConfig({ - usersync: { - syncDelay: 0, - userIds: [createStorageConfig('unifiedId', 'unifiedid_alt', 'html5')]} - }); + setSubmoduleRegistry([unifiedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['unifiedId', 'unifiedid_alt', 'html5'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -340,29 +348,111 @@ describe('User ID', function() { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); - init(config, [pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', '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('testunifiedid'); + }); + }); + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + + it('test hook when pubCommonId and unifiedId have their modules added before and after init', function(done) { + utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + + setSubmoduleRegistry([]); + + // attaching before init + attachIdSystem(pubCommonIdSubmodule); + + init(config); + + // attaching after init + attachIdSystem(unifiedIdSubmodule); + + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', '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'); + }); + }); + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + + it('should add new id system ', function(done) { + utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + utils.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); + + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig({ usersync: { syncDelay: 0, - userIds: [ - createStorageConfig('pubCommonId', 'pubcid', 'cookie'), - createStorageConfig('unifiedId', 'unifiedid', 'cookie') - ]} + userIds: [{ + name: 'pubCommonId', storage: { name: 'pubcid', type: 'cookie' } + }, { + name: 'unifiedId', storage: { name: 'unifiedid', type: 'cookie' } + }, { + name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + }] + } + }); + + // Add new submodule named 'mockId' + attachIdSystem({ + name: 'mockId', + decode: function(value) { + return { + 'mid': value['MOCKID'] + }; + }, + getId: function() { + return {'MOCKID': '1234'} + } }); requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { - // verify that the PubCommonId id data was copied to bid + // check 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 + // check UnifiedId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.tdid'); - expect(bid.userId.tdid).to.equal('testunifiedid'); + expect(bid.userId.tdid).to.equal('cookie-value-add-module-variations'); + // check MockId data was copied to bid + expect(bid).to.have.deep.nested.property('userId.mid'); + expect(bid.userId.mid).to.equal('123456778'); }); }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); From 72c8e4f7f88ef7a95d4cacb909e965b0275e1f27 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Wed, 22 May 2019 09:33:11 -0400 Subject: [PATCH 1235/1594] Adding advertiserId to appnexus adapter (#3833) --- modules/appnexusBidAdapter.js | 9 +- package-lock.json | 231 ++++++++++--------- test/spec/modules/appnexusBidAdapter_spec.js | 14 ++ 3 files changed, 144 insertions(+), 110 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index a27a10d4372..2dafd8fb293 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -368,6 +368,10 @@ function newBid(serverBid, rtbBid, bidderRequest) { } }; + if (rtbBid.advertiser_id) { + bid.meta = Object.assign({}, bid.meta, { advertiserId: rtbBid.advertiser_id }); + } + if (rtbBid.rtb.video) { Object.assign(bid, { width: rtbBid.rtb.video.player_width, @@ -380,10 +384,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { const videoContext = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); if (videoContext === ADPOD) { const iabSubCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); - bid.meta = { - iabSubCatId - }; - + bid.meta = Object.assign({}, bid.meta, { iabSubCatId }); bid.video = { context: ADPOD, durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), diff --git a/package-lock.json b/package-lock.json index b00be53f565..d313ff22ea0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.15.0", + "version": "2.16.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3108,7 +3108,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3480,7 +3480,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -4585,7 +4585,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4599,7 +4599,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4615,7 +4615,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4635,7 +4635,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -5326,7 +5326,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5865,7 +5865,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { @@ -6065,27 +6065,28 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, @@ -6096,15 +6097,17 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6112,39 +6115,42 @@ }, "chownr": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": false, + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "optional": true, @@ -6154,28 +6160,28 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -6185,14 +6191,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -6209,7 +6215,7 @@ }, "glob": { "version": "7.1.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, @@ -6224,14 +6230,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, @@ -6241,7 +6247,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -6251,7 +6257,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -6262,53 +6268,58 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6316,7 +6327,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, @@ -6326,23 +6337,24 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } }, "ms": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "optional": true }, "needle": { "version": "2.2.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "dev": true, "optional": true, @@ -6354,7 +6366,7 @@ }, "node-pre-gyp": { "version": "0.10.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz", "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", "dev": true, "optional": true, @@ -6373,7 +6385,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -6384,14 +6396,14 @@ }, "npm-bundled": { "version": "1.0.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz", "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.2.0.tgz", "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", "dev": true, "optional": true, @@ -6402,7 +6414,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -6415,43 +6427,45 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, + "optional": true, "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -6462,21 +6476,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, @@ -6489,7 +6503,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -6498,7 +6512,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -6514,7 +6528,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, @@ -6524,50 +6538,52 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.6.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6576,7 +6592,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -6586,23 +6602,24 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, @@ -6618,14 +6635,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, @@ -6635,15 +6652,17 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true + "dev": true, + "optional": true } } }, @@ -7318,7 +7337,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7335,7 +7354,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -8038,7 +8057,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -9034,7 +9053,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9659,7 +9678,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -9672,7 +9691,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true }, "debug": { @@ -10209,7 +10228,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10245,7 +10264,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10853,7 +10872,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -12126,7 +12145,7 @@ "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", "dev": true }, "rgb2hex": { @@ -12595,7 +12614,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -12609,7 +12628,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -12632,7 +12651,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -12654,7 +12673,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -12670,7 +12689,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -12682,7 +12701,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -12800,7 +12819,7 @@ }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -12934,7 +12953,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13935,7 +13954,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14575,7 +14594,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 312201e347d..c912122b25d 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -915,5 +915,19 @@ describe('AppNexusAdapter', function () { let result = spec.interpretResponse({ body: responseWithDeal }, {bidderRequest}); expect(Object.keys(result[0].appnexus)).to.include.members(['buyerMemberId', 'dealPriority', 'dealCode']); }); + + 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']); + }) }); }); From 50de3d4280d60f81da50caf47a25d3144ced63f1 Mon Sep 17 00:00:00 2001 From: afsheenb Date: Wed, 22 May 2019 11:28:21 -0400 Subject: [PATCH 1236/1594] updated ozone adapter from v1.4.4 -> v2.0.0 (#3828) * updated ozone adapter from v1.4.4 -> v2.0.0 * unruly renderer fixes after prebid team feedback, md update * updating docs and spec to account for customData changes * fixing whitespace --- modules/ozoneBidAdapter.js | 254 ++++++++++++++++------ modules/ozoneBidAdapter.md | 42 +++- test/spec/modules/ozoneBidAdapter_spec.js | 116 +++++++++- 3 files changed, 336 insertions(+), 76 deletions(-) diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index 406bffdf4df..c5d9f16ef58 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -2,14 +2,20 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; import {config} from '../src/config'; +import {getPriceBucketString} from '../src/cpmBucketManager'; +import { Renderer } from '../src/Renderer' const BIDDER_CODE = 'ozone'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; +const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js' + const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; -const OZONEVERSION = '1.4.7'; +const OZONEVERSION = '2.0.0'; + export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [VIDEO, BANNER], /** * Basic check to see whether required parameters are in the request. @@ -63,19 +69,26 @@ export const spec = { return false; } } + if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) { + if (!bid.mediaTypes.video.hasOwnProperty('context')) { + utils.logInfo('OZONE: [WARNING] No context key/value in bid. Rejecting bid: ', ozoneBidRequest); + return false; + } + if (bid.mediaTypes.video.context !== 'outstream') { + utils.logInfo('OZONE: [WARNING] Only outstream video is supported. Rejecting bid: ', ozoneBidRequest); + return false; + } + } return true; }, + buildRequests(validBidRequests, bidderRequest) { utils.logInfo('OZONE: ozone v' + OZONEVERSION + ' validBidRequests', validBidRequests, 'bidderRequest', bidderRequest); - utils.logInfo('OZONE: buildRequests setting auctionId', bidderRequest.auctionId); let singleRequest = config.getConfig('ozone.singleRequest'); - singleRequest = singleRequest !== false; // undefined & true will be true utils.logInfo('OZONE: config ozone.singleRequest : ', singleRequest); let htmlParams = validBidRequests[0].params; // the html page config params will be included in each element let ozoneRequest = {}; // we only want to set specific properties on this, not validBidRequests[0].params - // ozoneRequest['id'] = utils.generateUUID(); - delete ozoneRequest.test; // don't allow test to be set in the config - ONLY use $_GET['pbjs_debug'] if (bidderRequest.gdprConsent) { utils.logInfo('OZONE: ADDING GDPR info'); @@ -92,8 +105,7 @@ export const spec = { ozoneRequest.device = {'w': window.innerWidth, 'h': window.innerHeight}; let tosendtags = validBidRequests.map(ozoneBidRequest => { var obj = {}; - obj.id = ozoneBidRequest.bidId; // this causes a failure if we change it to something else - // obj.id = ozoneBidRequest.adUnitCode; // (eg. 'mpu' or 'leaderboard') A unique identifier for this impression within the context of the bid request (typically, starts with 1 and increments. + 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 = (ozoneBidRequest.params.placementId).toString(); obj.secure = window.location.protocol === 'https:' ? 1 : 0; // is there a banner (or nothing declared, so banner is the default)? @@ -141,6 +153,7 @@ export const spec = { obj.ext = {'prebid': {'storedrequest': {'id': (ozoneBidRequest.params.placementId).toString()}}, 'ozone': {}}; obj.ext.ozone.adUnitCode = ozoneBidRequest.adUnitCode; // eg. 'mpu' obj.ext.ozone.transactionId = ozoneBidRequest.transactionId; // this is the transactionId PER adUnit, common across bidders for this unit + obj.ext.ozone.oz_pb_v = OZONEVERSION; if (ozoneBidRequest.params.hasOwnProperty('customData')) { obj.ext.ozone.customData = ozoneBidRequest.params.customData; } @@ -150,16 +163,14 @@ export const spec = { if (ozoneBidRequest.params.hasOwnProperty('lotameData')) { obj.ext.ozone.lotameData = ozoneBidRequest.params.lotameData; } - if (ozoneBidRequest.hasOwnProperty('crumbs') && ozoneBidRequest.crumbs.hasOwnProperty('pubcid')) { + if (utils.deepAccess(ozoneBidRequest, 'crumbs.pubcid')) { obj.ext.ozone.pubcid = ozoneBidRequest.crumbs.pubcid; } return obj; }); - utils.logInfo('tosendtags = ', tosendtags); ozoneRequest.site = {'publisher': {'id': htmlParams.publisherId}, 'page': document.location.href}; ozoneRequest.test = parseInt(getTestQuerystringValue()); // will be 1 or 0 - // utils.logInfo('_ozoneInternal is', _ozoneInternal); // return the single request object OR the array: if (singleRequest) { utils.logInfo('OZONE: buildRequests starting to generate response for a single request'); @@ -177,7 +188,6 @@ export const spec = { utils.logInfo('OZONE: buildRequests going to return for single: ', 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 => { utils.logInfo('OZONE: buildRequests starting to generate non-single response, working on imp : ', imp); @@ -201,67 +211,65 @@ export const spec = { /** * Interpret the response if the array contains BIDDER elements, in the format: [ [bidder1 bid 1, bidder1 bid 2], [bidder2 bid 1, bidder2 bid 2] ] * NOte that in singleRequest mode this will be called once, else it will be called for each adSlot's response + * + * Updated April 2019 to return all bids, not just the one we decide is the 'winner' + * * @param serverResponse * @param request * @returns {*} */ interpretResponse(serverResponse, request) { - utils.logInfo('OZONE: version' + OZONEVERSION + ' interpretResponse', serverResponse, request); serverResponse = serverResponse.body || {}; - if (serverResponse.seatbid) { - if (utils.isArray(serverResponse.seatbid)) { - // serverResponse seems good, let's get the list of bids from the request object: - let arrRequestBids = request.bidderRequest.bids; - // build up a list of winners, one for each bidId in arrBidIds - let arrWinners = []; - for (let i = 0; i < arrRequestBids.length; i++) { - let thisBid = arrRequestBids[i]; - let ozoneInternalKey = thisBid.bidId; - let {seat: winningSeat, bid: winningBid} = ozoneGetWinnerForRequestBid(thisBid, serverResponse.seatbid); - - if (winningBid == null) { - utils.logInfo('OZONE: FAILED to get winning bid for bid : ', thisBid, 'will skip. Possibly a non-single request, which will be missing some bid IDs'); - continue; - } - - const {defaultWidth, defaultHeight} = defaultSize(arrRequestBids[i]); - winningBid = ozoneAddStandardProperties(winningBid, defaultWidth, defaultHeight); - - utils.logInfo('OZONE: Going to add the adserverTargeting custom parameters for key: ', ozoneInternalKey); - let adserverTargeting = {}; - let allBidsForThisBidid = ozoneGetAllBidsForBidId(ozoneInternalKey, serverResponse.seatbid); - // add all the winning & non-winning bids for this bidId: - Object.keys(allBidsForThisBidid).forEach(function(bidderName, index, ar2) { - utils.logInfo('OZONE: inside allBidsForThisBidid:foreach', bidderName, index, ar2, allBidsForThisBidid); - adserverTargeting['oz_' + bidderName] = bidderName; - adserverTargeting['oz_' + bidderName + '_pb'] = String(allBidsForThisBidid[bidderName].price); - adserverTargeting['oz_' + bidderName + '_crid'] = String(allBidsForThisBidid[bidderName].crid); - adserverTargeting['oz_' + bidderName + '_adv'] = String(allBidsForThisBidid[bidderName].adomain); - adserverTargeting['oz_' + bidderName + '_imp_id'] = String(allBidsForThisBidid[bidderName].impid); - }); - // now add the winner data: - adserverTargeting['oz_auc_id'] = String(request.bidderRequest.auctionId); - adserverTargeting['oz_winner'] = String(winningSeat); - adserverTargeting['oz_winner_auc_id'] = String(winningBid.id); - adserverTargeting['oz_winner_imp_id'] = String(winningBid.impid); - adserverTargeting['oz_response_id'] = String(serverResponse.id); + if (!serverResponse.hasOwnProperty('seatbid')) { return []; } + if (typeof serverResponse.seatbid !== 'object') { return []; } + let arrAllBids = []; + serverResponse.seatbid = injectAdIdsIntoAllBidResponses(serverResponse.seatbid); // we now make sure that each bid in the bidresponse has a unique (within page) adId attribute. + for (let i = 0; i < serverResponse.seatbid.length; i++) { + let sb = serverResponse.seatbid[i]; + const {defaultWidth, defaultHeight} = defaultSize(request.bidderRequest.bids[i]); + for (let j = 0; j < sb.bid.length; j++) { + let thisBid = ozoneAddStandardProperties(sb.bid[j], defaultWidth, defaultHeight); - winningBid.adserverTargeting = adserverTargeting; - utils.logInfo('OZONE: winner is', winningBid); - arrWinners.push(winningBid); - utils.logInfo('OZONE: arrWinners is', arrWinners); + // from https://github.com/prebid/Prebid.js/pull/1082 + if (utils.deepAccess(thisBid, 'ext.prebid.type') === VIDEO) { + utils.logInfo('OZONE: going to attach a renderer to:', j); + let renderConf = createObjectForInternalVideoRender(thisBid); + thisBid.renderer = Renderer.install(renderConf); + } else { + utils.logInfo('OZONE: bid is not a video, will not attach a renderer: ', j); } - let winnersClean = arrWinners.filter(w => { - return (w.bidId); // will be cast to boolean + + let ozoneInternalKey = thisBid.bidId; + let adserverTargeting = {}; + // all keys for all bidders for this bid have to be added to all objects returned, else some keys will not be sent to ads? + let allBidsForThisBidid = ozoneGetAllBidsForBidId(ozoneInternalKey, serverResponse.seatbid); + // add all the winning & non-winning bids for this bidId: + utils.logInfo('OZONE: Going to iterate allBidsForThisBidId', allBidsForThisBidid); + Object.keys(allBidsForThisBidid).forEach(function(bidderName, index, ar2) { + adserverTargeting['oz_' + bidderName] = bidderName; + adserverTargeting['oz_' + bidderName + '_pb'] = String(allBidsForThisBidid[bidderName].price); + adserverTargeting['oz_' + bidderName + '_crid'] = String(allBidsForThisBidid[bidderName].crid); + adserverTargeting['oz_' + bidderName + '_adv'] = String(allBidsForThisBidid[bidderName].adomain); + adserverTargeting['oz_' + bidderName + '_imp_id'] = String(allBidsForThisBidid[bidderName].impid); + adserverTargeting['oz_' + bidderName + '_adId'] = String(allBidsForThisBidid[bidderName].adId); + adserverTargeting['oz_' + bidderName + '_pb_r'] = getRoundedBid(allBidsForThisBidid[bidderName].price, allBidsForThisBidid[bidderName].ext.prebid.type); + if (allBidsForThisBidid[bidderName].hasOwnProperty('dealid')) { + adserverTargeting['oz_' + bidderName + '_dealid'] = String(allBidsForThisBidid[bidderName].dealid); + } }); - utils.logInfo('OZONE: going to return winnersClean:', winnersClean); - return winnersClean; - } else { - return []; + // also add in the winning bid, to be sent to dfp + let {seat: winningSeat, bid: winningBid} = ozoneGetWinnerForRequestBid(ozoneInternalKey, serverResponse.seatbid); + adserverTargeting['oz_auc_id'] = String(request.bidderRequest.auctionId); + adserverTargeting['oz_winner'] = String(winningSeat); + adserverTargeting['oz_winner_auc_id'] = String(winningBid.id); + adserverTargeting['oz_winner_imp_id'] = String(winningBid.impid); + adserverTargeting['oz_response_id'] = String(serverResponse.id); + adserverTargeting['oz_pb_v'] = OZONEVERSION; + thisBid.adserverTargeting = adserverTargeting; + arrAllBids.push(thisBid); } - } else { - return []; } + return arrAllBids; }, getUserSyncs(optionsType, serverResponse) { if (!serverResponse || serverResponse.length === 0) { @@ -275,6 +283,21 @@ export const spec = { } } } +/** + * add a page-level-unique adId element to all server response bids. + * NOTE that this is distructive - it mutates the serverResponse object sent in as a parameter + * @param seatbid object (serverResponse.seatbid) + * @returns seatbid object + */ +export function injectAdIdsIntoAllBidResponses(seatbid) { + for (let i = 0; i < seatbid.length; i++) { + let sb = seatbid[i]; + for (let j = 0; j < sb.bid.length; j++) { + sb.bid[j]['adId'] = sb.bid[j]['impid'] + '-' + i; // modify the bidId per-bid, so each bid has a unique adId within this response, and dfp can select one. + } + } + return seatbid; +} export function checkDeepArray(Arr) { if (Array.isArray(Arr)) { if (Array.isArray(Arr[0])) { @@ -300,15 +323,14 @@ export function defaultSize(thebidObj) { * @param serverResponseSeatBid * @returns {*} bid object */ -export function ozoneGetWinnerForRequestBid(requestBid, serverResponseSeatBid) { +export function ozoneGetWinnerForRequestBid(requestBidId, serverResponseSeatBid) { let thisBidWinner = null; let winningSeat = null; for (let j = 0; j < serverResponseSeatBid.length; j++) { let theseBids = serverResponseSeatBid[j].bid; let thisSeat = serverResponseSeatBid[j].seat; for (let k = 0; k < theseBids.length; k++) { - if (theseBids[k].impid === requestBid.bidId) { // we've found a matching server response bid for this request bid - // if (theseBids[k].impid === requestBid.adUnitCode) { // we've found a matching server response bid for this request bid + 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; @@ -327,22 +349,88 @@ export function ozoneGetWinnerForRequestBid(requestBid, serverResponseSeatBid) { * @returns {} = {ozone:{obj}, appnexus:{obj}, ... } */ export function ozoneGetAllBidsForBidId(matchBidId, serverResponseSeatBid) { - utils.logInfo('OZONE: ozoneGetAllBidsForBidId - starting, with: ', matchBidId, serverResponseSeatBid); let objBids = {}; for (let j = 0; j < serverResponseSeatBid.length; j++) { let theseBids = serverResponseSeatBid[j].bid; let thisSeat = serverResponseSeatBid[j].seat; for (let k = 0; k < theseBids.length; k++) { if (theseBids[k].impid === matchBidId) { // we've found a matching server response bid for the request bid we're looking for - utils.logInfo('ozoneGetAllBidsForBidId - found matching bid: ', matchBidId, theseBids[k]); objBids[thisSeat] = theseBids[k]; } } } - utils.logInfo('OZONE: ozoneGetAllBidsForBidId - going to return: ', objBids); return objBids; } +/** + * Round the bid price down according to the granularity + * @param price + * @param mediaType = video, banner or native + */ +export function getRoundedBid(price, mediaType) { + const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${mediaType}`); // might be string or object or nothing; if set then this takes precedence over 'priceGranularity' + let objBuckets = config.getConfig('customPriceBucket'); // this is always an object - {} if strBuckets is not 'custom' + let strBuckets = config.getConfig('priceGranularity'); // priceGranularity value, always a string ** if priceGranularity is set to an object then it's always 'custom' + let theConfigObject = getGranularityObject(mediaType, mediaTypeGranularity, strBuckets, objBuckets); + let theConfigKey = getGranularityKeyName(mediaType, mediaTypeGranularity, 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') + ); + utils.logInfo('priceStringsObj', priceStringsObj); + // by default, without any custom granularity set, you get granularity name : 'medium' + let granularityNamePriceStringsKeyMapping = { + 'medium': 'med', + 'custom': 'custom', + 'high': 'high', + 'low': 'low', + 'dense': 'dense' + }; + if (granularityNamePriceStringsKeyMapping.hasOwnProperty(theConfigKey)) { + let priceStringsKey = granularityNamePriceStringsKeyMapping[theConfigKey]; + utils.logInfo('OZONE: looking for priceStringsKey:', priceStringsKey); + return priceStringsObj[priceStringsKey]; + } + return priceStringsObj['auto']; +} + +/** + * return the key to use to get the value out of the priceStrings object, taking into account anything at + * config.priceGranularity level or config.mediaType.xxx level + * I've noticed that the key specified by prebid core : config.getConfig('priceGranularity') does not properly + * take into account the 2-levels of config + */ +export function getGranularityKeyName(mediaType, mediaTypeGranularity, strBuckets) { + if (typeof mediaTypeGranularity === 'string') { + return mediaTypeGranularity; + } + if (typeof mediaTypeGranularity === 'object') { + return 'custom'; + } + if (typeof strBuckets === 'string') { + return strBuckets; + } + return 'auto'; // fall back to a default key - should literally never be needed though. +} + +/** + * return the object to use to create the custom value of the priceStrings object, taking into account anything at + * config.priceGranularity level or config.mediaType.xxx level + */ +export function getGranularityObject(mediaType, mediaTypeGranularity, strBuckets, objBuckets) { + if (typeof mediaTypeGranularity === 'object') { + return mediaTypeGranularity; + } + if (strBuckets === 'custom') { + return objBuckets; + } + return ''; +} + /** * We expect to be able to find a standard set of properties on winning bid objects; add them here. * @param seatBid @@ -379,5 +467,37 @@ export function getTestQuerystringValue() { return 0; } +/** + * Generate a random number per ad; I'll use the current ms timestamp, then append 8 random alpha/numeric characters + * Randomness : 1 in 208 billion random combinations per-millisecond, non-repeating sequence. + * + * @returns {*} + */ +export function pgGuid() { + return new Date().getTime() + 'xxxxxxxx'.replace(/x/g, function(c) { + return Math.round((Math.random() * 36)).toString(36); + }); +} + +function createObjectForInternalVideoRender(bid) { + let obj = { + url: OZONE_RENDERER_URL, + callback: () => onOutstreamRendererLoaded(bid) + } + return obj; +} + +function onOutstreamRendererLoaded(bid) { + try { + bid.renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err) + } +} + +function outstreamRender(bid) { + window.ozoneVideo.outstreamRender(bid); +} + registerBidder(spec); utils.logInfo('OZONE: ozoneBidAdapter ended'); diff --git a/modules/ozoneBidAdapter.md b/modules/ozoneBidAdapter.md index c013a4d558c..89760697088 100644 --- a/modules/ozoneBidAdapter.md +++ b/modules/ozoneBidAdapter.md @@ -1,4 +1,4 @@ - + # Overview ``` @@ -12,7 +12,7 @@ Maintainer: engineering@ozoneproject.com Module that connects to the Ozone Project's demand source(s). -The Ozone Project bid adapter supports Banner mediaTypes ONLY. +The Ozone Project bid adapter supports Banner and Outstream Video mediaTypes ONLY. # Test Parameters @@ -36,9 +36,43 @@ adUnits = [{ publisherId: 'OZONENUK0001', /* an ID to identify the publisher account - required */ siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ placementId: '0420420421', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */ - customData: {"key1": "value1", "key2": "value2}, /* optional JSON placeholder for passing publisher key-values for targeting. */ + customData": [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"],}}] /* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ + ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ + lotameData: {"key1": "value1", "key2": "value2"} /* optional JSON placeholder for passing Lotame DMP data */ + } + }] + }]; +``` + + +``` + +//Outstream Video adUnit + +adUnits = [{ + code: 'id-of-your-video-div', + mediaTypes: { + video: { + playerSize: [640, 480], + mimes: ['video/mp4'], + context: 'outstream', + } + }, + bids: [{ + bidder: 'ozone', + params: { + publisherId: 'OZONENUK0001', /* an ID to identify the publisher account - required */ + siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ + customData: [{"settings": {}, "targeting": { "key": "value", "key2": ["value1", "value2"]}}] + placementId: '0440440442', /* an ID used to identify the piece of inventory - required - for unruly test use 0440440442. */ + customData": [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"],}}] /* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ - lotameData: {"key1": "value1", "key2": "value2} /* optional JSON placeholder for passing Lotame DMP data */ + lotameData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for passing Lotame DMP data */ + video: { + skippable: true, /* optional */ + playback_method: ['auto_play_sound_off'], /* optional */ + targetDiv: 'some-different-div-id-to-my-adunitcode' /* optional */ + } } }] }]; diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index a910ef391b0..b0f252d4469 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -1,6 +1,7 @@ import { expect } from 'chai'; import { spec } from 'modules/ozoneBidAdapter'; import { config } from 'src/config'; +import {Renderer} from '../../../src/Renderer'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; const BIDDER_CODE = 'ozone'; /* @@ -63,7 +64,7 @@ var validBidRequestsWithBannerMediaType = [ transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; -var validBidRequestsWithNonBannerMediaTypes = [ +var validBidRequestsWithNonBannerMediaTypesAndValidOutstreamVideo = [ { adUnitCode: 'div-gpt-ad-1460505748561-0', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', @@ -72,8 +73,8 @@ var validBidRequestsWithNonBannerMediaTypes = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, - mediaTypes: {video: {info: 'dummy data'}, native: {info: 'dummy data'}}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: {skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode'} } ] }, + mediaTypes: {video: {mimes: ['video/mp4'], 'context': 'outstream'}, native: {info: 'dummy data'}}, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; @@ -154,6 +155,67 @@ var validResponse = { } }, 'headers': {} +}; +var validOutstreamResponse = { + 'body': { + 'id': 'd6198807-7a53-4141-b2db-d2cb754d68ba', + 'seatbid': [ + { + 'bid': [ + { + 'id': '677903815252395017', + 'impid': '2899ec066a91ff8', + 'price': 0.5, + 'adm': '', + 'adid': '98493581', + 'adomain': [ + 'http://prebid.org' + ], + 'iurl': 'https://fra1-ib.adnxs.com/cr?id=98493581', + 'cid': '9325', + 'crid': '98493581', + 'cat': [ + 'IAB3-1' + ], + 'w': 300, + 'h': 600, + 'ext': { + 'prebid': { + 'type': 'video' + }, + 'bidder': { + 'unruly': { + 'renderer': { + 'config': { + 'targetingUUID': 'aafd3388-afaf-41f4-b271-0ac8e0325a7f', + 'siteId': 1052815, + 'featureOverrides': {} + }, + 'url': 'https://video.unrulymedia.com/native/native-loader.js#supplyMode=prebid?cb=6284685353877994', + 'id': 'unruly_inarticle' + }, + 'vast_url': 'data:text/xml;base64,PD94bWwgdmVyc2lvbj0i' + } + } + } + } + ], + 'seat': 'unruly' + } + ], + 'ext': { + 'responsetimemillis': { + 'appnexus': 47, + 'openx': 30 + } + }, + 'timing': { + 'start': 1536848078.089177, + 'end': 1536848078.142203, + 'TimeTaken': 0.05302619934082031 + } + }, + 'headers': {} } describe('ozone Adapter', function () { @@ -463,6 +525,43 @@ describe('ozone Adapter', function () { it('should not validate lotameData being sent', function () { expect(spec.isBidRequestValid(xBadLotame)).to.equal(false); }); + + var xBadVideoContext = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'lotameData': 'this should be an object', + siteId: '1234567890' + }, + mediaTypes: { + video: { + mimes: ['video/mp4'], + 'context': 'instream'}, + } + }; + + it('should not validate video instream being sent', function () { + expect(spec.isBidRequestValid(xBadVideoContext)).to.equal(false); + }); + + let validVideoBidReq = { + bidder: BIDDER_CODE, + params: { + placementId: '1310000099', + publisherId: '9876abcd12-3', + siteId: '1234567890' + }, + mediaTypes: { + video: { + mimes: ['video/mp4'], + 'context': 'outstream'}, + } + }; + + it('should not validate video instream being sent', function () { + expect(spec.isBidRequestValid(validVideoBidReq)).to.equal(true); + }); }); describe('buildRequests', function () { @@ -509,8 +608,8 @@ describe('ozone Adapter', function () { expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); }); - it('handles missing banner mediaType element correctly', function () { - const request = spec.buildRequests(validBidRequestsWithNonBannerMediaTypes, validBidderRequest); + it('handles video mediaType element correctly, with outstream video', function () { + const request = spec.buildRequests(validBidRequestsWithNonBannerMediaTypesAndValidOutstreamVideo, validBidderRequest); expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); }); @@ -584,6 +683,13 @@ describe('ozone Adapter', function () { expect(result).to.be.an('array'); expect(result).to.be.empty; }); + + it('should have video renderer', function () { + const request = spec.buildRequests(validBidRequestsWithNonBannerMediaTypesAndValidOutstreamVideo, validBidderRequest); + const result = spec.interpretResponse(validOutstreamResponse, request); + const bid = result[0]; + expect(bid.renderer).to.be.an.instanceOf(Renderer); + }); }); describe('userSyncs', function () { From c6c20a2d5a2245bd883d20b5e0df4c650ccab0d3 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 22 May 2019 14:52:26 -0400 Subject: [PATCH 1237/1594] fix how native sizes are passed in AppNexus adapter (#3832) --- modules/appnexusBidAdapter.js | 24 +++------ test/spec/modules/appnexusBidAdapter_spec.js | 55 ++------------------ 2 files changed, 11 insertions(+), 68 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 2dafd8fb293..e0ae19187b2 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -19,13 +19,11 @@ const NATIVE_MAPPING = { cta: 'ctatext', image: { serverName: 'main_image', - requiredParams: { required: true }, - minimumParams: { sizes: [{}] }, + requiredParams: { required: true } }, icon: { serverName: 'icon', - requiredParams: { required: true }, - minimumParams: { sizes: [{}] }, + requiredParams: { required: true } }, sponsoredBy: 'sponsored_by', privacyLink: 'privacy_link', @@ -680,18 +678,12 @@ function buildNativeRequest(params) { const requiredParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].requiredParams; request[requestKey] = Object.assign({}, requiredParams, params[key]); - // minimum params are passed if no non-required params given on adunit - const minimumParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].minimumParams; - - if (requiredParams && minimumParams) { - // subtract required keys from adunit keys - const adunitKeys = Object.keys(params[key]); - const requiredKeys = Object.keys(requiredParams); - const remaining = adunitKeys.filter(key => !includes(requiredKeys, key)); - - // if none are left over, the minimum params needs to be sent - if (remaining.length === 0) { - request[requestKey] = Object.assign({}, request[requestKey], minimumParams); + // 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 (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/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index c912122b25d..9e37f6cbffb 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -396,7 +396,8 @@ describe('AppNexusAdapter', function () { title: {required: true}, body: {required: true}, body2: {required: true}, - image: {required: true, sizes: [{ width: 100, height: 100 }]}, + image: {required: true, sizes: [100, 100]}, + icon: {required: true}, cta: {required: false}, rating: {required: true}, sponsoredBy: {required: true}, @@ -420,6 +421,7 @@ describe('AppNexusAdapter', function () { 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}, @@ -434,57 +436,6 @@ describe('AppNexusAdapter', function () { }); }); - it('sets minimum native asset params when not provided on adunit', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: {required: true}, - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: {required: true, sizes: [{}]}, - }); - }); - - it('does not overwrite native ad unit params with mimimum params', function () { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: { - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: { - required: true, - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - }, - }); - }); - it('should always populated tags[].sizes with 1,1 for native if otherwise not defined', function () { let bidRequest = Object.assign({}, bidRequests[0], From 612cd3d99aef856166e3df3a79585467b0126b0a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 22 May 2019 16:36:56 -0400 Subject: [PATCH 1238/1594] Prebid 2.16.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6bb0b49fab0..4f5085a7dc5 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.16.0-pre", + "version": "2.16.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From c006a6a6fafc29ef009a0a76404895c6996cd9ac Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 22 May 2019 16:48:13 -0400 Subject: [PATCH 1239/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f5085a7dc5..ab415a03ea0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.16.0", + "version": "2.17.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From a7953e442b16ba46a2b457de8249d03e54aa608d Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Mon, 27 May 2019 19:17:56 +0300 Subject: [PATCH 1240/1594] Refactor bid response - remove unnecessary properties (#3807) --- modules/cleanmedianetBidAdapter.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/cleanmedianetBidAdapter.js b/modules/cleanmedianetBidAdapter.js index 00fb5aa5325..15871e1a6ae 100644 --- a/modules/cleanmedianetBidAdapter.js +++ b/modules/cleanmedianetBidAdapter.js @@ -175,16 +175,14 @@ export const spec = { bids.forEach(bid => { const outBid = { - adId: bidRequest.bidRequest.adUnitCode, requestId: bidRequest.bidRequest.bidId, cpm: bid.price, width: bid.w, height: bid.h, ttl: 60 * 10, - creativeId: bid.crid, + creativeId: bid.crid || bid.adid, netRevenue: true, currency: bid.cur || response.cur, - adUnitCode: bidRequest.bidRequest.adUnitCode, mediaType: helper.getMediaType(bid) }; From 3f5a5981c714f30acf0fbb3435d86efdd90dbb5b Mon Sep 17 00:00:00 2001 From: Michele Nasti Date: Mon, 27 May 2019 18:29:03 +0200 Subject: [PATCH 1241/1594] change in Aardvark adapter to handle additional data (#3821) * added property ex to rawBid * removed utils.getTopWindowUrl() --- modules/aardvarkBidAdapter.js | 6 +++- test/spec/modules/aardvarkBidAdapter_spec.js | 35 ++++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index 49095b1cfc1..108e56ac06a 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -25,7 +25,7 @@ export const spec = { var auctionCodes = []; var requests = []; var requestsMap = {}; - var referer = utils.getTopWindowUrl(); + var referer = bidderRequest.refererInfo.referer; var pageCategories = []; // This reference to window.top can cause issues when loaded in an iframe if not protected with a try/catch. @@ -124,6 +124,10 @@ export const spec = { bidResponse.dealId = rawBid.dealId } + if (rawBid.hasOwnProperty('ex')) { + bidResponse.ex = rawBid.ex; + } + switch (rawBid.media) { case 'banner': bidResponse.ad = rawBid.adm + utils.createTrackPixelHtml(decodeURIComponent(rawBid.nurl)); diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js index 628f19f8fd2..8ce4aa85561 100644 --- a/test/spec/modules/aardvarkBidAdapter_spec.js +++ b/test/spec/modules/aardvarkBidAdapter_spec.js @@ -54,21 +54,27 @@ describe('aardvarkAdapterTest', function () { auctionId: 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' }]; + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; + it('should use HTTP GET method', function () { - const requests = spec.buildRequests(bidRequests); + const requests = spec.buildRequests(bidRequests, bidderRequest); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); it('should call the correct bidRequest url', function () { - const requests = spec.buildRequests(bidRequests); + const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests.length).to.equal(1); expect(requests[0].url).to.match(new RegExp('^\/\/adzone.pub.com/xiby/TdAx_RAZd/aardvark\?')); }); it('should have correct data', function () { - const requests = spec.buildRequests(bidRequests); + const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests.length).to.equal(1); expect(requests[0].data.version).to.equal(1); expect(requests[0].data.jsonp).to.equal(false); @@ -108,22 +114,28 @@ describe('aardvarkAdapterTest', function () { auctionId: 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' }]; + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; + it('should use HTTP GET method', function () { - const requests = spec.buildRequests(bidRequests); + const requests = spec.buildRequests(bidRequests, bidderRequest); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); it('should call the correct bidRequest urls for each auction', function () { - const requests = spec.buildRequests(bidRequests); + const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests[0].url).to.match(new RegExp('^\/\/bidder.rtk.io/Toby/TdAx/aardvark\?')); expect(requests[0].data.categories.length).to.equal(2); expect(requests[1].url).to.match(new RegExp('^\/\/adzone.pub.com/xiby/RAZd/aardvark\?')); }); it('should have correct data', function () { - const requests = spec.buildRequests(bidRequests); + const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests.length).to.equal(2); expect(requests[0].data.version).to.equal(1); expect(requests[0].data.jsonp).to.equal(false); @@ -157,6 +169,9 @@ describe('aardvarkAdapterTest', function () { gdprConsent: { consentString: 'awefasdfwefasdfasd', gdprApplies: true + }, + refererInfo: { + referer: 'http://example.com' } }; @@ -184,7 +199,10 @@ describe('aardvarkAdapterTest', function () { }]; const bidderRequest = { - gdprConsent: undefined + gdprConsent: undefined, + refererInfo: { + referer: 'http://example.com' + } }; it('should transmit correct data', function () { @@ -219,6 +237,7 @@ describe('aardvarkAdapterTest', function () { cid: '1abgs362e0x48a8', adm: '', ttl: 200, + ex: 'extraproperty' } ], headers: {} @@ -234,6 +253,7 @@ describe('aardvarkAdapterTest', function () { expect(result[0].currency).to.equal('USD'); expect(result[0].ttl).to.equal(200); expect(result[0].dealId).to.equal('dealing'); + expect(result[0].ex).to.be.undefined; expect(result[0].ad).to.not.be.undefined; expect(result[1].requestId).to.equal('1abgs362e0x48a8'); @@ -243,6 +263,7 @@ describe('aardvarkAdapterTest', function () { expect(result[1].currency).to.equal('USD'); expect(result[1].ttl).to.equal(200); expect(result[1].ad).to.not.be.undefined; + expect(result[1].ex).to.equal('extraproperty'); }); it('should handle nobid responses', function () { From 96aae26eb2e31b65cd43e5533c15f00f4696220c Mon Sep 17 00:00:00 2001 From: Telaria Engineering <36203956+telariaEng@users.noreply.github.com> Date: Mon, 27 May 2019 09:35:29 -0700 Subject: [PATCH 1242/1594] Updated the bidder code in the test ad unit. (#3844) * - Updated the test ad unit to use 'telaria' as the bidder code. - Added an example URL. * using the bidder code constant --- modules/telariaBidAdapter.js | 2 +- modules/telariaBidAdapter.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/telariaBidAdapter.js b/modules/telariaBidAdapter.js index 12698f0ce56..0dd2e5e6edb 100644 --- a/modules/telariaBidAdapter.js +++ b/modules/telariaBidAdapter.js @@ -84,7 +84,7 @@ export const spec = { utils.logError(errorMessage); } else if (bidResult.seatbid && bidResult.seatbid.length > 0) { bidResult.seatbid[0].bid.forEach(tag => { - bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, bidResult.seatbid[0].seat.toLowerCase())); + bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, BIDDER_CODE)); }); } diff --git a/modules/telariaBidAdapter.md b/modules/telariaBidAdapter.md index 6a34a14a6b2..6a5e24e9a5e 100644 --- a/modules/telariaBidAdapter.md +++ b/modules/telariaBidAdapter.md @@ -23,7 +23,7 @@ Telaria bid adapter supports insteream Video. } }, bids: [{ - bidder: 'tremor', + bidder: 'telaria', params: { supplyCode: 'ssp-demo-rm6rh', adCode: 'ssp-!demo!-lufip', @@ -33,3 +33,5 @@ Telaria bid adapter supports insteream Video. } ``` +# Example: +https://console.telaria.com/examples/hb/headerbidding.jsp From d7af6dbaa666c69ac7fca3e196fb495d8dac94c8 Mon Sep 17 00:00:00 2001 From: Kamoris Date: Mon, 27 May 2019 18:46:10 +0200 Subject: [PATCH 1243/1594] Update rtbhouseBidAdapter.md (#3857) Explicit native.image.sizes in doc --- modules/rtbhouseBidAdapter.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/rtbhouseBidAdapter.md b/modules/rtbhouseBidAdapter.md index b8410fe8bb6..233ed34053a 100644 --- a/modules/rtbhouseBidAdapter.md +++ b/modules/rtbhouseBidAdapter.md @@ -39,7 +39,8 @@ Please reach out to pmp@rtbhouse.com to receive your own len: 25 }, image: { - required: true + required: true, + sizes: [300, 250] }, body: { required: true, From 3f1b73908884260dc5c71b86a85e853f1cca3ff5 Mon Sep 17 00:00:00 2001 From: dpapworth-qc <50959025+dpapworth-qc@users.noreply.github.com> Date: Mon, 27 May 2019 17:52:01 +0100 Subject: [PATCH 1244/1594] Added optional dealId parameter to bid response. (#3858) --- modules/quantcastBidAdapter.js | 6 +++++- test/spec/modules/quantcastBidAdapter_spec.js | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 022122b5a2e..64cec7e231a 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -182,7 +182,7 @@ export const spec = { } const bidResponsesList = response.bids.map(bid => { - const { ad, cpm, width, height, creativeId, currency, videoUrl } = bid; + const { ad, cpm, width, height, creativeId, currency, videoUrl, dealId } = bid; const result = { requestId: response.requestId, @@ -201,6 +201,10 @@ export const spec = { result['mediaType'] = 'video'; } + if (dealId !== undefined && dealId) { + result['dealId'] = dealId; + } + return result; }); diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 5a1a905f843..662641de17b 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -305,6 +305,26 @@ describe('Quantcast adapter', function () { expect(interpretedResponse[0]).to.deep.equal(expectedResponse); }); + it('should include dealId in bid response', function () { + response.body.bids[0].dealId = 'test-dealid'; + const expectedResponse = { + requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', + cpm: 4.5, + width: 300, + height: 250, + ad: + '
    Quantcast
    ', + ttl: QUANTCAST_TTL, + creativeId: 1001, + netRevenue: QUANTCAST_NET_REVENUE, + currency: 'USD', + dealId: 'test-dealid' + }; + const interpretedResponse = qcSpec.interpretResponse(response); + + expect(interpretedResponse[0]).to.deep.equal(expectedResponse); + }); + it('should get correct bid response for instream video', function() { const expectedResponse = { requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', From 0ee3cc638327e6f1926499bb3116a3b041283193 Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Tue, 28 May 2019 11:58:42 -0400 Subject: [PATCH 1245/1594] adding Outstream mediaType to EMX Digital (#3840) * addressed feedback from #3731 ticket * removed commented code from emx test spec * logging removed from spec * flip h & w values from playerSize for video requests * adding Outstream mediaType to EMX Digital --- modules/emx_digitalBidAdapter.js | 62 +++++++++++++++---- modules/emx_digitalBidAdapter.md | 4 +- .../modules/emx_digitalBidAdapter_spec.js | 48 ++++++++++++-- 3 files changed, 96 insertions(+), 18 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 4bffd8e1e00..75ce47aae0a 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -1,11 +1,13 @@ -import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER, VIDEO } from '../src/mediaTypes'; -import { config } from '../src/config'; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER, VIDEO } from 'src/mediaTypes'; +import { config } from 'src/config'; +import { Renderer } from 'src/Renderer'; import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; const ENDPOINT = 'hb.emxdgt.com'; +const RENDERER_URL = '//js.brealtime.com/outstream/1.30.0/bundle.js'; export const emxAdapter = { validateSizes: (sizes) => { @@ -16,7 +18,7 @@ export const emxAdapter = { return sizes.every(size => utils.isArray(size) && size.length === 2); }, checkVideoContext: (bid) => { - return (bid && bid.mediaTypes && bid.mediaTypes.video && bid.mediaTypes.video.context && bid.mediaTypes.video.context === 'instream'); + return ((bid && bid.mediaTypes && bid.mediaTypes.video && bid.mediaTypes.video.context) && ((bid.mediaTypes.video.context === 'instream') || (bid.mediaTypes.video.context === 'outstream'))); }, buildBanner: (bid) => { let sizes = []; @@ -38,20 +40,56 @@ export const emxAdapter = { }, formatVideoResponse: (bidResponse, emxBid) => { bidResponse.vastXml = emxBid.adm; + if (!emxBid.renderer && (!emxBid.mediaTypes || !emxBid.mediaTypes.video || !emxBid.mediaTypes.video.context || emxBid.mediaTypes.video.context === 'outstream')) { + bidResponse.renderer = emxAdapter.createRenderer(bidResponse, { + id: emxBid.bidId, + url: RENDERER_URL + }); + } return bidResponse; }, - buildVideo: (bid) => { - bid.params.video.h = bid.mediaTypes.video.playerSize[0][1]; - bid.params.video.w = bid.mediaTypes.video.playerSize[0][0]; - return emxAdapter.cleanProtocols(bid.params.video); - }, cleanProtocols: (video) => { if (video.protocols && includes(video.protocols, 7)) { + // not supporting VAST protocol 7 (VAST 4.0); utils.logWarn(BIDDER_CODE + ': VAST 4.0 is currently not supported. This protocol has been filtered out of the request.'); video.protocols = video.protocols.filter(protocol => protocol !== 7); } return video; }, + outstreamRender: (bid) => { + bid.renderer.push(function () { + let params = (bid && bid.params && bid.params[0] && bid.params[0].video) ? bid.params[0].video : {}; + window.emxVideoQueue = window.emxVideoQueue || []; + window.queueEmxVideo({ + id: bid.adUnitCode, + adsResponses: bid.vastXml, + options: params + }); + if (window.emxVideoReady && window.videojs) { + window.emxVideoReady(); + } + }); + }, + createRenderer: (bid, rendererParams) => { + const renderer = Renderer.install({ + id: rendererParams.id, + url: RENDERER_URL, + loaded: false + }); + try { + renderer.setRender(emxAdapter.outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + + return renderer; + }, + buildVideo: (bid) => { + bid.params.video = bid.params.video || {}; + bid.params.video.h = bid.mediaTypes.video.playerSize[0][0]; + bid.params.video.w = bid.mediaTypes.video.playerSize[0][1]; + return emxAdapter.cleanProtocols(bid.params.video); + }, getGdpr: (bidRequests, emxData) => { if (bidRequests.gdprConsent) { emxData.regs = { @@ -100,7 +138,7 @@ export const spec = { } } else if (bid.mediaTypes && bid.mediaTypes.video) { if (!emxAdapter.checkVideoContext(bid)) { - utils.logWarn(BIDDER_CODE + ': Missing video context: instream'); + utils.logWarn(BIDDER_CODE + ': Missing video context: instream or outstream'); return false; } @@ -146,7 +184,7 @@ export const spec = { domain: window.top.document.location.host, page: page }, - version: '1.21.1' + version: '1.30.0' }; emxData = emxAdapter.getGdpr(bidderRequest, Object.assign({}, emxData)); diff --git a/modules/emx_digitalBidAdapter.md b/modules/emx_digitalBidAdapter.md index b0acdbcada8..03ba554c5ad 100644 --- a/modules/emx_digitalBidAdapter.md +++ b/modules/emx_digitalBidAdapter.md @@ -8,7 +8,7 @@ Maintainer: git@emxdigital.com # Description -The EMX Digital adapter provides publishers with access to the EMX Marketplace. The adapter is GDPR compliant. Please note that the adapter supports Banner and Video (Instream) media types only. +The EMX Digital adapter provides publishers with access to the EMX Marketplace. The adapter is GDPR compliant. Please note that the adapter supports Banner and Video (Instream & Outstream) media types. Note: The EMX Digital adapter requires approval and implementation guidelines from the EMX team, including existing publishers that work with EMX Digital. Please reach out to your account manager or prebid@emxdigital.com for more information. @@ -43,7 +43,7 @@ var adUnits = [{ code: 'video-div', mediaTypes: { video: { - context: 'instream', + context: 'instream', // also applicable for 'outstream' playerSize: [640, 480] } }, diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js index dfb11ad82cd..170e5676f43 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -138,9 +138,32 @@ describe('emx_digital Adapter', function () { 'auctionId': '1d1a01234a475' }; + let outstreamBid = { + 'bidder': 'emx_digital', + 'params': { + 'tagid': '25251', + 'video': {} + }, + 'mediaTypes': { + 'video': { + 'context': 'outstream', + 'playerSize': [640, 480] + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c2501de1e', + 'bidderRequestId': '22edbae3120bf6', + 'auctionId': '1d1a01234a475' + }; + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); expect(spec.isBidRequestValid(noInstreamBid)).to.equal(false); + expect(spec.isBidRequestValid(outstreamBid)).to.equal(true); }); it('should contain tagid param', function () { @@ -283,8 +306,24 @@ describe('emx_digital Adapter', function () { let request = spec.buildRequests(bidRequestWithVideo, bidderRequest); const data = JSON.parse(request.data); expect(data.imp[0].video).to.exist.and.to.be.a('object'); - expect(data.imp[0].video.h).to.equal(bidRequestWithVideo[0].mediaTypes.video.playerSize[0][1]); - expect(data.imp[0].video.w).to.equal(bidRequestWithVideo[0].mediaTypes.video.playerSize[0][0]); + expect(data.imp[0].video.h).to.equal(bidRequestWithVideo[0].mediaTypes.video.playerSize[0][0]); + expect(data.imp[0].video.w).to.equal(bidRequestWithVideo[0].mediaTypes.video.playerSize[0][1]); + }); + + it('builds correctly formatted request video object for outstream', function () { + let bidRequestWithOutstreamVideo = utils.deepClone(bidderRequest.bids); + bidRequestWithOutstreamVideo[0].mediaTypes = { + video: { + context: 'outstream', + playerSize: [640, 480] + }, + }; + bidRequestWithOutstreamVideo[0].params.video = {}; + let request = spec.buildRequests(bidRequestWithOutstreamVideo, bidderRequest); + const data = JSON.parse(request.data); + expect(data.imp[0].video).to.exist.and.to.be.a('object'); + expect(data.imp[0].video.h).to.equal(bidRequestWithOutstreamVideo[0].mediaTypes.video.playerSize[0][0]); + expect(data.imp[0].video.w).to.equal(bidRequestWithOutstreamVideo[0].mediaTypes.video.playerSize[0][1]); }); it('shouldn\'t contain a user obj without GDPR information', function () { @@ -452,6 +491,7 @@ describe('emx_digital Adapter', function () { expect(ad1.vastXml).to.equal(serverResponse.seatbid[1].bid[0].adm); expect(ad1.ad).to.exist.and.to.be.a('string'); }); + it('handles nobid responses', function () { let serverResponse = { 'bids': [] @@ -464,10 +504,10 @@ describe('emx_digital Adapter', function () { }); }); - describe('getUserSyncs', function() { + describe('getUserSyncs', function () { let syncOptionsIframe = { iframeEnabled: true }; let syncOptionsPixel = { pixelEnabled: true }; - it('Should push the correct sync type depending on the config', function() { + it('Should push the correct sync type depending on the config', function () { let iframeSync = spec.getUserSyncs(syncOptionsIframe); expect(iframeSync.length).to.equal(1); expect(iframeSync[0].type).to.equal('iframe'); From 445df80dabbfcef9aff811ae7be9e3fa061d5cac Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 28 May 2019 13:01:18 -0700 Subject: [PATCH 1246/1594] Adding bidfloor to video imp req (#3863) --- modules/rubiconBidAdapter.js | 1 + test/spec/modules/rubiconBidAdapter_spec.js | 28 +++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index aeb6418eea8..dd1c815150e 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -134,6 +134,7 @@ export const spec = { }, tmax: config.getConfig('TTL') || 1000, imp: [{ + bidfloor: utils.deepAccess(bidRequest, 'params.floor') ? parseFloat(bidRequest.params.floor) : 0.0, exp: 300, id: bidRequest.adUnitCode, secure: isSecure() || bidRequest.params.secure ? 1 : 0, diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 33e5d04466a..0f29afe0069 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1143,6 +1143,34 @@ describe('the rubicon adapter', function () { expect(request.data.imp[0].video.pos).to.equal(1); }); + it('should send correct bidfloor to PBS', function() { + createVideoBidderRequest(); + + bidderRequest.bids[0].params.floor = 0.1; + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(request.data.imp[0].bidfloor).to.equal(0.1); + + bidderRequest.bids[0].params.floor = 5.5; + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(request.data.imp[0].bidfloor).to.equal(5.5); + + bidderRequest.bids[0].params.floor = '1.7'; + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(request.data.imp[0].bidfloor).to.equal(1.7); + + bidderRequest.bids[0].params.floor = 0; + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(request.data.imp[0].bidfloor).to.equal(0.0); + + bidderRequest.bids[0].params.floor = undefined; + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(request.data.imp[0].bidfloor).to.equal(0.0); + + bidderRequest.bids[0].params.floor = null; + [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(request.data.imp[0].bidfloor).to.equal(0.0); + }); + it('should send request with proper ad position when mediaTypes.video.pos is not defined', function () { createVideoBidderRequest(); let positionBidderRequest = clone(bidderRequest); From c1f6ce41cb078c45c93d0bc9a2d276bbc3295abd Mon Sep 17 00:00:00 2001 From: rhythmonebhaines <49991465+rhythmonebhaines@users.noreply.github.com> Date: Tue, 28 May 2019 13:32:53 -0700 Subject: [PATCH 1247/1594] Rhythmone Adapter - Multiple ad size support, rewrite tests, update docs. (#3854) --- modules/rhythmoneBidAdapter.js | 60 +- modules/rhythmoneBidAdapter.md | 40 +- test/spec/modules/rhythmoneBidAdapter_spec.js | 759 +++++++++++++----- 3 files changed, 629 insertions(+), 230 deletions(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 29572c228fe..6e7a935c71c 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -15,12 +15,12 @@ function RhythmOneBidAdapter() { let SUPPORTED_VIDEO_API = [1, 2, 5]; let slotsToBids = {}; let that = this; - let version = '1.0.2.1'; + let version = '2.0.0.0'; let loadStart = Date.now(); var win = typeof window !== 'undefined' ? window : {}; this.isBidRequestValid = function (bid) { - return true; + return !!(bid.params && bid.params.placementId); }; this.getUserSyncs = function (syncOptions, responses, gdprConsent) { @@ -90,6 +90,7 @@ function RhythmOneBidAdapter() { impObj.id = BRs[i].adUnitCode; impObj.bidfloor = parseFloat(utils.deepAccess(BRs[i], 'params.floor')) || 0; impObj.secure = win.location.protocol === 'https:' ? 1 : 0; + if (utils.deepAccess(BRs[i], 'mediaTypes.banner') || utils.deepAccess(BRs[i], 'mediaType') === 'banner') { impObj.banner = frameBanner(BRs[i]); } @@ -139,21 +140,58 @@ function RhythmOneBidAdapter() { } } - function frameBanner(bid) { - var sizes = utils.parseSizesInput(bid.sizes).map(size => size.split('x')); - return { - w: parseInt(sizes[0][0]), - h: parseInt(sizes[0][1]) + function getValidSizeSet(dimensionList) { + let w = parseInt(dimensionList[0]); + let h = parseInt(dimensionList[1]); + // clever check for NaN + if (! (w !== w || h !== h)) { // eslint-disable-line + return [w, h]; + } + return false; + } + + function frameBanner(adUnit) { + // adUnit.sizes is scheduled to be deprecated, continue its support but prefer adUnit.mediaTypes.banner + var sizeList = adUnit.sizes; + if (adUnit.mediaTypes && adUnit.mediaTypes.banner) { + sizeList = adUnit.mediaTypes.banner.sizes; + } + var sizeStringList = utils.parseSizesInput(sizeList); + if (!Array.isArray(sizeStringList)) { + return {}; } + + var format = []; + sizeStringList.forEach(function(size) { + if (!size) { + return; + } + var dimensionList = getValidSizeSet(size.split('x')); + if (dimensionList) { + format.push({ + 'w': dimensionList[0], + 'h': dimensionList[1], + }); + } + }); + if (format.length) { + return { + 'format': format + }; + } + return {}; } function frameVideo(bid) { var size = []; if (utils.deepAccess(bid, 'mediaTypes.video.playerSize')) { + var dimensionSet = bid.mediaTypes.video.playerSize; if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { - size = bid.mediaTypes.video.playerSize[0]; - } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { - size = bid.mediaTypes.video.playerSize; + dimensionSet = bid.mediaTypes.video.playerSize[0]; + } + var validSize = getValidSizeSet(dimensionSet) + if (validSize) { + size = validSize; } } return { @@ -172,7 +210,7 @@ function RhythmOneBidAdapter() { function frameExt(bid) { return { bidder: { - placementId: (bid.params && bid.params['placementId']) ? bid.params['placementId'] : '', + placementId: bid.params['placementId'], zone: (bid.params && bid.params['zone']) ? bid.params['zone'] : '1r', path: (bid.params && bid.params['path']) ? bid.params['path'] : 'mvo' } diff --git a/modules/rhythmoneBidAdapter.md b/modules/rhythmoneBidAdapter.md index ec3ee4852e5..df657ed2651 100644 --- a/modules/rhythmoneBidAdapter.md +++ b/modules/rhythmoneBidAdapter.md @@ -14,15 +14,41 @@ This module relays Prebid bids from Rhythm Exchange, RhythmOne's ad exchange. ```js const adUnits = [{ - code: 'uuddlrlrbass', - sizes: [ - [300, 250] - ], + code: 'adSlot-1', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + }, bids: [ { bidder: 'rhythmone', - params: - { + params: + { + placementId: '80184', // REQUIRED + zone: '1r', // OPTIONAL + path: 'mvo', // OPTIONAL + endpoint: "//tag.1rx.io/rmp/80184/0/mvo?z=1r" // OPTIONAL, only required for testing. this api guarantees no 204 responses + } + } + ] +}, +{ + code: 'adSlot-2', + mediaTypes: { + video: { + context: "instream", + playerSize: [640, 480] + } + }, + bids: [ + { + bidder: 'rhythmone', + params: + { placementId: '80184', // REQUIRED zone: '1r', // OPTIONAL path: 'mvo', // OPTIONAL @@ -31,4 +57,4 @@ const adUnits = [{ } ] }]; -``` \ No newline at end of file +``` diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index 98a7731c324..e909827b2df 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -1,64 +1,73 @@ import {spec} from '../../../modules/rhythmoneBidAdapter'; -var assert = require('assert'); +import * as utils from '../../../src/utils'; +import * as sinon from 'sinon'; + +var r1adapter = spec; describe('rhythmone adapter tests', function () { - describe('rhythmoneResponse', function () { - var z = spec; + beforeEach(function() { + this.defaultBidderRequest = { + 'refererInfo': { + 'referer': 'Reference Page' + } + }; + }); - var rmpBannerRequest = z.buildRequests( - [ + describe('Verify 1.0 POST Banner Bid Request', function () { + it('buildRequests works', function () { + var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { - 'placementId': 'abc', - 'keywords': '', - 'categories': [], - 'trace': true, - 'zone': '2345', - 'path': 'mvo', - 'method': 'POST' + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' }, 'mediaType': 'banner', 'adUnitCode': 'div-gpt-ad-1438287399331-0', - 'sizes': [[300, 250]] + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' } - ], { 'refererInfo': { 'referer': 'Reference Page' } } - ); - - it('Verify POST Banner Bid Request', function () { - expect(rmpBannerRequest.url).to.have.string('//tag.1rx.io/rmp/abc/0/mvo?z=2345&hbv='); - expect(rmpBannerRequest.method).to.equal('POST'); - const bidRequest = JSON.parse(rmpBannerRequest.data); - expect(bidRequest.site).to.not.equal(null); - expect(bidRequest.site.ref).to.equal('Reference Page'); - expect(bidRequest.device).to.not.equal(null); - expect(bidRequest.device.ua).to.equal(navigator.userAgent); - expect(bidRequest.device).to.have.property('dnt'); - expect(bidRequest.imp[0].banner).to.not.equal(null); - expect(bidRequest.imp[0].banner.w).to.equal(300); - expect(bidRequest.imp[0].banner.h).to.equal(250); - expect(bidRequest.imp[0].ext.bidder.zone).to.equal('2345'); - expect(bidRequest.imp[0].ext.bidder.path).to.equal('mvo'); - }); + ]; - var bannerBids = z.interpretResponse({ - body: [ - { - 'impid': 'div-gpt-ad-1438287399331-0', - 'w': 300, - 'h': 250, - 'adm': '
    My ad4 with cpm of a4ab3485f434f74f
    ', - 'price': 1, - 'crid': 'cr-cfy24' - } - ] - }); + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - it('should register one bid', function() { - assert.equal(bannerBids.length, 1); + expect(bidRequest.url).to.have.string('//tag.1rx.io/rmp/myplacement/0/mypath?z=myzone&hbv='); + expect(bidRequest.method).to.equal('POST'); + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.site).to.not.equal(null); + expect(openrtbRequest.site.ref).to.equal('Reference Page'); + expect(openrtbRequest.device).to.not.equal(null); + expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); + expect(openrtbRequest.device.dnt).to.equal(0); + expect(openrtbRequest.imp[0].banner).to.not.equal(null); + expect(openrtbRequest.imp[0].banner.format[0].w).to.equal(300); + expect(openrtbRequest.imp[0].banner.format[0].h).to.equal(250); + expect(openrtbRequest.imp[0].ext.bidder.zone).to.equal('myzone'); + expect(openrtbRequest.imp[0].ext.bidder.path).to.equal('mypath'); }); - it('Verify parse banner response', function() { + it('interpretResponse works', function() { + var bidList = { + 'body': [ + { + 'impid': 'div-gpt-ad-1438287399331-0', + 'w': 300, + 'h': 250, + 'adm': '
    My Compelling Ad
    ', + 'price': 1, + 'crid': 'cr-cfy24' + } + ] + }; + + var bannerBids = r1adapter.interpretResponse(bidList); + + expect(bannerBids.length).to.equal(1); const bid = bannerBids[0]; expect(bid.width).to.equal(300); expect(bid.height).to.equal(250); @@ -68,70 +77,80 @@ describe('rhythmone adapter tests', function () { expect(bid.cpm).to.equal(1.0); expect(bid.ttl).to.equal(350); }); + }); - var rmpVideoRequest = z.buildRequests( - [ + describe('Verify POST Video Bid Request', function() { + it('buildRequests works', function () { + var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { - 'placementId': 'xyz', - 'keywords': '', - 'categories': [], - 'trace': true, - 'method': 'POST' + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' }, 'mediaTypes': { 'video': { - 'playerSize': [[640, 480]], + 'playerSize': [ + [640, 480] + ], 'context': 'instream' } }, - 'placementCode': 'div-gpt-ad-1438287399331-1', - 'sizes': [[300, 250]] + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'sizes': [ + [300, 250] + ], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' } - ], { 'refererInfo': { 'referer': 'Reference Page' } } - ); - - it('Verify POST Video Bid Request', function () { - expect(rmpVideoRequest.url).to.have.string('//tag.1rx.io/rmp/xyz/0/mvo?z=1r&hbv='); - expect(rmpVideoRequest.method).to.equal('POST'); - const bidRequest = JSON.parse(rmpVideoRequest.data); - expect(bidRequest.site).to.not.equal(null); - expect(bidRequest.device).to.not.equal(null); - expect(bidRequest.device.ua).to.equal(navigator.userAgent); - expect(bidRequest.device).to.have.property('dnt'); - expect(bidRequest.imp[0].video).to.not.equal(null); - expect(bidRequest.imp[0].video.w).to.equal(640); - expect(bidRequest.imp[0].video.h).to.equal(480); - expect(bidRequest.imp[0].video.mimes[0]).to.equal('video/mp4'); - expect(bidRequest.imp[0].video.protocols).to.eql([2, 3, 5, 6]); - expect(bidRequest.imp[0].video.startdelay).to.equal(0); - expect(bidRequest.imp[0].video.skip).to.equal(0); - expect(bidRequest.imp[0].video.playbackmethod).to.eql([1, 2, 3, 4]); - expect(bidRequest.imp[0].video.delivery[0]).to.equal(1); - expect(bidRequest.imp[0].video.api).to.eql([1, 2, 5]); - }); + ]; - var videoBids = z.interpretResponse({ - body: [ - { - 'impid': 'div-gpt-ad-1438287399331-1', - 'price': 1, - 'nurl': 'http://testdomain/rmp/placementid/0/path?reqId=1636037', - 'adomain': ['test.com'], - 'cid': '467415', - 'crid': 'cr-vid', - 'w': 800, - 'h': 600 - } - ] - }); + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - it('should register one bid', function() { - assert.equal(videoBids.length, 1); + expect(bidRequest.url).to.have.string('//tag.1rx.io/rmp/myplacement/0/mypath?z=myzone&hbv='); + expect(bidRequest.method).to.equal('POST'); + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.site).to.not.equal(null); + expect(openrtbRequest.device).to.not.equal(null); + expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); + expect(openrtbRequest.device).to.have.property('dnt'); + expect(openrtbRequest.imp[0].video).to.not.equal(null); + expect(openrtbRequest.imp[0].video.w).to.equal(640); + expect(openrtbRequest.imp[0].video.h).to.equal(480); + expect(openrtbRequest.imp[0].video.mimes[0]).to.equal('video/mp4'); + expect(openrtbRequest.imp[0].video.protocols).to.eql([2, 3, 5, 6]); + expect(openrtbRequest.imp[0].video.startdelay).to.equal(0); + expect(openrtbRequest.imp[0].video.skip).to.equal(0); + expect(openrtbRequest.imp[0].video.playbackmethod).to.eql([1, 2, 3, 4]); + expect(openrtbRequest.imp[0].video.delivery[0]).to.equal(1); + expect(openrtbRequest.imp[0].video.api).to.eql([1, 2, 5]); }); - it('Verify parse video response', function() { + it('interpretResponse works', function() { + var bidList = { + 'body': [ + { + 'impid': 'div-gpt-ad-1438287399331-1', + 'price': 1, + 'nurl': 'http://testdomain/rmp/placementid/0/path?reqId=1636037', + 'adomain': [ + 'test.com' + ], + 'cid': '467415', + 'crid': 'cr-vid', + 'w': 800, + 'h': 600 + } + ] + }; + + var videoBids = r1adapter.interpretResponse(bidList); + + expect(videoBids.length).to.equal(1); const bid = videoBids[0]; expect(bid.width).to.equal(800); expect(bid.height).to.equal(600); @@ -143,47 +162,23 @@ describe('rhythmone adapter tests', function () { expect(bid.cpm).to.equal(1.0); expect(bid.ttl).to.equal(600); }); + }); - it('should send GDPR Consent data to RhythmOne tag', function () { - let _consentString = 'testConsentString'; - var request = z.buildRequests( - [ - { - 'bidder': 'rhythmone', - 'params': { - 'placementId': 'xyz', - 'keywords': '', - 'categories': [], - 'trace': true, - 'method': 'POST' - }, - 'adUnitCode': 'div-gpt-ad-1438287399331-3', - 'sizes': [[300, 250]] - } - ], {'gdprConsent': {'gdprApplies': true, 'consentString': _consentString}, 'refererInfo': { 'referer': 'Reference Page' }} - ); - const bidRequest = JSON.parse(request.data); - expect(bidRequest.user.ext.consent).to.equal(_consentString); - expect(bidRequest.regs.ext.gdpr).to.equal(true); - }); - - var rmpMultiFormatRequest = z.buildRequests( - [ + describe('Verify Multi-Format ads and Multiple Size Bid Request', function() { + it('buildRequests works', function () { + var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { - 'placementId': 'xyz', - 'keywords': '', - 'categories': [], - 'trace': true, - 'zone': '2345', - 'path': 'mvo', - 'method': 'POST' + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath', }, 'mediaTypes': { 'banner': { 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ] }, 'video': { @@ -192,58 +187,69 @@ describe('rhythmone adapter tests', function () { } }, 'adUnitCode': 'div-gpt-ad-1438287399331-5', - 'sizes': [[300, 250]] + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' } - ], { 'refererInfo': { 'referer': 'Reference Page' } } - ); - - it('Verify Multi-Format ads Bid Request', function () { - const bidRequest = JSON.parse(rmpMultiFormatRequest.data); - expect(bidRequest.site).to.not.equal(null); - expect(bidRequest.site.ref).to.equal('Reference Page'); - expect(bidRequest.device).to.not.equal(null); - expect(bidRequest.device.ua).to.equal(navigator.userAgent); - expect(bidRequest.device).to.have.property('dnt'); - expect(bidRequest.imp[0].video).to.not.equal(null); - expect(bidRequest.imp[0].video.w).to.equal(640); - expect(bidRequest.imp[0].video.h).to.equal(480); - expect(bidRequest.imp[0].video.mimes[0]).to.equal('video/mp4'); - expect(bidRequest.imp[0].video.protocols).to.eql([2, 3, 5, 6]); - expect(bidRequest.imp[0].video.startdelay).to.equal(0); - expect(bidRequest.imp[0].video.skip).to.equal(0); - expect(bidRequest.imp[0].video.playbackmethod).to.eql([1, 2, 3, 4]); - expect(bidRequest.imp[0].video.delivery[0]).to.equal(1); - expect(bidRequest.imp[0].video.api).to.eql([1, 2, 5]); - expect(bidRequest.imp[0].banner).to.not.equal(null); - expect(bidRequest.imp[0].banner.w).to.equal(300); - expect(bidRequest.imp[0].banner.h).to.equal(250); - expect(bidRequest.imp[0].ext.bidder.zone).to.equal('2345'); - expect(bidRequest.imp[0].ext.bidder.path).to.equal('mvo'); - }); + ]; - var forRMPMultiFormatResponse = z.interpretResponse({ - body: { - 'id': '1e810245dd1779', - 'seatbid': [ { - 'bid': [ { - 'impid': 'div-gpt-ad-1438287399331-5', - 'price': 1, - 'nurl': 'http://testdomain/rmp/placementid/0/path?reqId=1636037', - 'adomain': ['test.com'], - 'cid': '467415', - 'crid': 'cr-vid', - 'w': 800, - 'h': 600 - } ] - } ] - } - }); + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - it('should register one bid', function() { - assert.equal(forRMPMultiFormatResponse.length, 1); + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.site).to.not.equal(null); + expect(openrtbRequest.site.ref).to.equal('Reference Page'); + expect(openrtbRequest.device).to.not.equal(null); + expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); + expect(openrtbRequest.device).to.have.property('dnt'); + expect(openrtbRequest.imp[0].video).to.not.equal(null); + expect(openrtbRequest.imp[0].video.w).to.equal(640); + expect(openrtbRequest.imp[0].video.h).to.equal(480); + expect(openrtbRequest.imp[0].video.mimes[0]).to.equal('video/mp4'); + expect(openrtbRequest.imp[0].video.protocols).to.eql([2, 3, 5, 6]); + expect(openrtbRequest.imp[0].video.startdelay).to.equal(0); + expect(openrtbRequest.imp[0].video.skip).to.equal(0); + expect(openrtbRequest.imp[0].video.playbackmethod).to.eql([1, 2, 3, 4]); + expect(openrtbRequest.imp[0].video.delivery[0]).to.equal(1); + expect(openrtbRequest.imp[0].video.api).to.eql([1, 2, 5]); + expect(openrtbRequest.imp[0].banner).to.not.equal(null); + expect(openrtbRequest.imp[0].banner.format[0].w).to.equal(300); + expect(openrtbRequest.imp[0].banner.format[0].h).to.equal(250); + expect(openrtbRequest.imp[0].banner.format[1].w).to.equal(300); + expect(openrtbRequest.imp[0].banner.format[1].h).to.equal(600); + expect(openrtbRequest.imp[0].ext.bidder.zone).to.equal('myzone'); + expect(openrtbRequest.imp[0].ext.bidder.path).to.equal('mypath'); }); - it('Verify parse for multi format ad response', function() { + it('interpretResponse works', function() { + var bidList = { + 'body': { + 'id': '1e810245dd1779', + 'seatbid': [ + { + 'bid': [ + { + 'impid': 'div-gpt-ad-1438287399331-5', + 'price': 1, + 'nurl': 'http://testdomain/rmp/placementid/0/path?reqId=1636037', + 'adomain': [ + 'test.com' + ], + 'cid': '467415', + 'crid': 'cr-vid', + 'w': 800, + 'h': 600 + } + ] + } + ] + } + }; + + var forRMPMultiFormatResponse = r1adapter.interpretResponse(bidList); + + expect(forRMPMultiFormatResponse.length).to.equal(1); const bid = forRMPMultiFormatResponse[0]; expect(bid.width).to.equal(800); expect(bid.height).to.equal(600); @@ -255,65 +261,394 @@ describe('rhythmone adapter tests', function () { expect(bid.cpm).to.equal(1.0); expect(bid.ttl).to.equal(600); }); + }); + + describe('misc buildRequests', function() { + it('should send GDPR Consent data to RhythmOne tag', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-3', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var consentString = 'testConsentString'; + var gdprBidderRequest = this.defaultBidderRequest; + gdprBidderRequest.gdprConsent = { + 'gdprApplies': true, + 'consentString': consentString + }; + + var bidRequest = r1adapter.buildRequests(bidRequestList, gdprBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.user.ext.consent).to.equal(consentString); + expect(openrtbRequest.regs.ext.gdpr).to.equal(true); + }); + + it('prefer 2.0 sizes', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 600]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; - var noBidResponse = z.interpretResponse({ - body: '' + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].banner.format[0].w).to.equal(300); + expect(openrtbRequest.imp[0].banner.format[0].h).to.equal(600); }); - it('No bid response', function() { - assert.equal(noBidResponse.length, 0); + it('survives size misconfiguration', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].banner.format).to.be.undefined; + }); + + it('dnt is correctly set to 1', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 600]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var dntStub = sinon.stub(utils, 'getDNT').returns(1); + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + dntStub.restore(); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.device.dnt).to.equal(1); }); - describe('isRequiredParamPresent', function () { - var rmpBannerRequest = z.buildRequests( - [ - { - 'bidder': 'rhythmone', - 'params': { - 'keywords': '', - 'categories': [], - 'trace': true, - 'zone': '2345', - 'path': 'mvo', - 'method': 'POST' - }, - 'mediaType': 'banner', - 'adUnitCode': 'div-gpt-ad-1438287399331-0', - 'sizes': [[300, 250]] - } - ], { 'refererInfo': { 'referer': 'Reference Page' } } - ); - it('should return empty when required params not found', function () { - expect(rmpBannerRequest).to.be.empty; + it('sets floor', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'floor': 100.0 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 600]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].bidfloor).to.equal(100.0); + }); + + it('support for correct video size definition', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + }, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'context': 'instream' + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].video.w).to.equal(640); + expect(openrtbRequest.imp[0].video.h).to.equal(480); + }); + + it('supports string video sizes', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + }, + 'mediaTypes': { + 'video': { + 'context': 'instream', + 'playerSize': ['600', '300'] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].video.w).to.equal(600); + expect(openrtbRequest.imp[0].video.h).to.equal(300); + }); + + it('rejects bad video sizes', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + }, + 'mediaTypes': { + 'video': { + 'context': 'instream', + 'playerSize': ['badWidth', 'badHeight'] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].video.w).to.be.undefined; + expect(openrtbRequest.imp[0].video.h).to.be.undefined; + }); + + it('supports missing video size', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + }, + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].video.w).to.be.undefined; + expect(openrtbRequest.imp[0].video.h).to.be.undefined; + }); + + it('uses default zone and path', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [ + [300, 600] + ] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].ext.bidder.zone).to.equal('1r'); + expect(openrtbRequest.imp[0].ext.bidder.path).to.equal('mvo'); + }); + + it('should return empty when required params not found', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [ + [300, 250] + ] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-3', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + expect(bidRequest).to.be.empty; + }); + }); + + describe('misc interpretResponse', function () { + it('No bid response', function() { + var noBidResponse = r1adapter.interpretResponse({ + 'body': '' }); + expect(noBidResponse.length).to.equal(0); }); }); - describe('auditBeacon', function() { - var z = spec; - var beaconURL = z.getUserSyncs({pixelEnabled: true})[0]; + describe('auditBeacon', function() { it('should contain the correct path', function() { - var u = '//hbevents.1rx.io/audit?'; - assert.equal(beaconURL.url.substring(0, u.length), u); + var syncList = r1adapter.getUserSyncs({pixelEnabled: true}); + expect(syncList.length).to.equal(1); + var syncData = syncList[0]; + var expectedURL = '//hbevents.1rx.io/audit?'; + assert.equal(syncData.url.substring(0, expectedURL.length), expectedURL); }); - beaconURL = z.getUserSyncs({pixelEnabled: true}, null, {'gdprApplies': true, 'consentString': 'testConsentString'})[0]; it('should send GDPR Consent data to Sync pixel', function () { - expect(beaconURL.url).to.have.string('&gdpr=true&gdpr_consent=testConsentString'); + var syncList = r1adapter.getUserSyncs({pixelEnabled: true}, null, {'gdprApplies': true, 'consentString': 'testConsentString'}); + expect(syncList.length).to.equal(1); + var syncData = syncList[0]; + expect(syncData.url).to.have.string('&gdpr=true&gdpr_consent=testConsentString'); + }); + + it('should not return anything when pixelEnabled is false', function () { + var syncList = r1adapter.getUserSyncs({pixelEnabled: false}, null, {'gdprApplies': true, 'consentString': 'testConsentString'}); + expect(syncList).to.be.undefined; }); }); + describe('isBidRequestValid', function () { - let bid = { + var bid = { 'bidder': 'rhythmone', 'params': { - 'placementId': '469127' + 'placementId': 'myplacement', + 'path': 'mypath', + 'zone': 'myzone' }, - 'adUnitCode': 'bannerDiv', - 'sizes': [[300, 250]] + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'adUnitCode': 'bannerDiv' }; it('should return true when required params found', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true); + expect(r1adapter.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when placementId missing', function () { + delete bid.params.placementId; + expect(r1adapter.isBidRequestValid(bid)).to.equal(false); }); }); }); From dc3134ce1cec7d0461fb95a2e44647226a768a7e Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 28 May 2019 17:17:31 -0400 Subject: [PATCH 1248/1594] minor updates to consentManagement tests (#3849) --- integrationExamples/gpt/gdpr_hello_world.html | 10 ++++-- modules/consentManagement.js | 4 +-- test/spec/modules/consentManagement_spec.js | 32 +++++++++---------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/integrationExamples/gpt/gdpr_hello_world.html b/integrationExamples/gpt/gdpr_hello_world.html index 084310b57d2..84efb5b7596 100644 --- a/integrationExamples/gpt/gdpr_hello_world.html +++ b/integrationExamples/gpt/gdpr_hello_world.html @@ -82,13 +82,17 @@ var adUnits = [{ code: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300,600]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, // Replace this object to test a new Adapter! bids: [{ - bidder: 'appnexusAst', + bidder: 'appnexus', params: { - placementId: '10433394' + placementId: 13144370 } }] diff --git a/modules/consentManagement.js b/modules/consentManagement.js index 94a3b13e383..1e2a6648145 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -342,7 +342,7 @@ export function resetConsentData() { * A configuration function that initializes some module variables, as well as add a hook into the requestBids function * @param {object} config required; consentManagement module config settings; cmp (string), timeout (int), allowAuctionWithoutConsent (boolean) */ -export function setConfig(config) { +export function setConsentConfig(config) { if (utils.isStr(config.cmpApi)) { userCMP = config.cmpApi; } else { @@ -379,4 +379,4 @@ export function setConfig(config) { } addedConsentHook = true; } -config.getConfig('consentManagement', config => setConfig(config.consentManagement)); +config.getConfig('consentManagement', config => setConsentConfig(config.consentManagement)); diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index 40c96c38eb0..6be96427750 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -1,4 +1,4 @@ -import {setConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, allowAuction, staticConsentData} from 'modules/consentManagement'; +import {setConsentConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, allowAuction, staticConsentData} from 'modules/consentManagement'; import {gdprDataHandler} from 'src/adapterManager'; import * as utils from 'src/utils'; import { config } from 'src/config'; @@ -7,8 +7,8 @@ let assert = require('chai').assert; let expect = require('chai').expect; describe('consentManagement', function () { - describe('setConfig tests:', function () { - describe('empty setConfig value', function () { + describe('setConsentConfig tests:', function () { + describe('empty setConsentConfig value', function () { beforeEach(function () { sinon.stub(utils, 'logInfo'); }); @@ -19,7 +19,7 @@ describe('consentManagement', function () { }); it('should use system default values', function () { - setConfig({}); + setConsentConfig({}); expect(userCMP).to.be.equal('iab'); expect(consentTimeout).to.be.equal(10000); expect(allowAuction).to.be.true; @@ -27,7 +27,7 @@ describe('consentManagement', function () { }); }); - describe('valid setConfig value', function () { + describe('valid setConsentConfig value', function () { afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeAll(); @@ -39,14 +39,14 @@ describe('consentManagement', function () { allowAuctionWithoutConsent: false }; - setConfig(allConfig); + setConsentConfig(allConfig); expect(userCMP).to.be.equal('iab'); expect(consentTimeout).to.be.equal(7500); expect(allowAuction).to.be.false; }); }); - describe('static consent string setConfig value', () => { + describe('static consent string setConsentConfig value', () => { afterEach(() => { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeAll(); @@ -447,7 +447,7 @@ describe('consentManagement', function () { } }; - setConfig(staticConfig); + setConsentConfig(staticConfig); expect(userCMP).to.be.equal('static'); expect(consentTimeout).to.be.equal(0); // should always return without a timeout when config is used expect(allowAuction).to.be.false; @@ -495,7 +495,7 @@ describe('consentManagement', function () { let badCMPConfig = { cmpApi: 'bad' }; - setConfig(badCMPConfig); + setConsentConfig(badCMPConfig); expect(userCMP).to.be.equal(badCMPConfig.cmpApi); requestBidsHook(() => { @@ -508,7 +508,7 @@ describe('consentManagement', function () { }); it('should throw proper errors when CMP is not found', function () { - setConfig(goodConfigWithCancelAuction); + setConsentConfig(goodConfigWithCancelAuction); requestBidsHook(() => { didHookReturn = true; @@ -546,7 +546,7 @@ describe('consentManagement', function () { cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { args[2](testConsentData); }); - setConfig(goodConfigWithAllowAuction); + setConsentConfig(goodConfigWithAllowAuction); requestBidsHook(() => {}, {}); cmpStub.restore(); @@ -610,7 +610,7 @@ describe('consentManagement', function () { args[2](testConsentData.data.msgName, testConsentData.data); }); - setConfig(goodConfigWithAllowAuction); + setConsentConfig(goodConfigWithAllowAuction); requestBidsHook(() => { didHookReturn = true; }, {adUnits: [{ sizes: [[300, 250]] }]}); @@ -684,7 +684,7 @@ describe('consentManagement', function () { function testIFramedPage(testName, messageFormatString) { it(`should return the consent string from a postmessage + addEventListener response - ${testName}`, (done) => { stringifyResponse = messageFormatString; - setConfig(goodConfigWithAllowAuction); + setConsentConfig(goodConfigWithAllowAuction); requestBidsHook(() => { let consent = gdprDataHandler.getConsentData(); sinon.assert.notCalled(utils.logWarn); @@ -726,7 +726,7 @@ describe('consentManagement', function () { args[2](testConsentData); }); - setConfig(goodConfigWithAllowAuction); + setConsentConfig(goodConfigWithAllowAuction); requestBidsHook(() => { didHookReturn = true; @@ -748,7 +748,7 @@ describe('consentManagement', function () { args[2](testConsentData); }); - setConfig(goodConfigWithCancelAuction); + setConsentConfig(goodConfigWithCancelAuction); requestBidsHook(() => { didHookReturn = true; @@ -768,7 +768,7 @@ describe('consentManagement', function () { args[2](testConsentData); }); - setConfig(goodConfigWithAllowAuction); + setConsentConfig(goodConfigWithAllowAuction); requestBidsHook(() => { didHookReturn = true; From e88dec19d31f2fe0b63823f3a68118718f01adec Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 28 May 2019 19:33:55 -0400 Subject: [PATCH 1249/1594] auction key limiter feature (#3825) * auction key limiter feature - initial commit * Updated config name --- src/targeting.js | 91 ++++++++++++++- test/spec/unit/core/targeting_spec.js | 160 +++++++++++++++++++++++++- 2 files changed, 248 insertions(+), 3 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index 4ac993cf94a..a8c989bdf37 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -1,4 +1,4 @@ -import { uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp, deepAccess } from './utils'; +import { uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp, deepAccess, deepClone, logError, logWarn, logInfo } from './utils'; import { config } from './config'; import { NATIVE_TARGETING_KEYS } from './native'; import { auctionManager } from './auctionManager'; @@ -43,6 +43,40 @@ export function getHighestCpmBidsFromBidPool(bidsReceived, highestCpmCallback) { return bids; } +/** +* A descending sort function that will sort the list of objects based on the following two dimensions: +* - bids with a deal are sorted before bids w/o a deal +* - then sort bids in each grouping based on the hb_pb value +* eg: the following list of bids would be sorted like: +* [{ +* "hb_adid": "vwx", +* "hb_pb": "28", +* "hb_deal": "7747" +* }, { +* "hb_adid": "jkl", +* "hb_pb": "10", +* "hb_deal": "9234" +* }, { +* "hb_adid": "stu", +* "hb_pb": "50" +* }, { +* "hb_adid": "def", +* "hb_pb": "2" +* }] +*/ +export function sortByDealAndPriceBucket(a, b) { + if (a.adUnitTargeting.hb_deal !== undefined && b.adUnitTargeting.hb_deal === undefined) { + return -1; + } + + if ((a.adUnitTargeting.hb_deal === undefined && b.adUnitTargeting.hb_deal !== undefined)) { + return 1; + } + + // assuming both values either have a deal or don't have a deal - sort by the hb_pb param + return b.adUnitTargeting.hb_pb - a.adUnitTargeting.hb_pb; +} + /** * @typedef {Object.} targeting * @property {string} targeting_key @@ -122,8 +156,13 @@ export function newTargeting(auctionManager) { targeting = flattenTargeting(targeting); - // make sure at least there is a entry per adUnit code in the targetingSet so receivers of SET_TARGETING call's can know what ad units are being invoked + const auctionKeysThreshold = config.getConfig('targetingControls.auctionKeyMaxChars'); + if (auctionKeysThreshold) { + logInfo(`Detected 'targetingControls.auctionKeyMaxChars' was active for this auction; set with a limit of ${auctionKeysThreshold} characters. Running checks on auction keys...`); + targeting = filterTargetingKeys(targeting, auctionKeysThreshold); + } + // make sure at least there is a entry per adUnit code in the targetingSet so receivers of SET_TARGETING call's can know what ad units are being invoked adUnitCodes.forEach(code => { if (!targeting[code]) { targeting[code] = {}; @@ -133,6 +172,54 @@ export function newTargeting(auctionManager) { return targeting; }; + // 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) { + return Object.keys(keyMap).reduce(function (queryString, key) { + let encodedKeyPair = `${key}%3d${encodeURIComponent(keyMap[key])}%26`; + return queryString += encodedKeyPair; + }, ''); + } + + function filterTargetingKeys(targeting, auctionKeysThreshold) { + // read each targeting.adUnit object and sort the adUnits into a list of adUnitCodes based on priorization setting (eg CPM) + let targetingCopy = deepClone(targeting); + + let targetingMap = Object.keys(targetingCopy).map(adUnitCode => { + return { + adUnitCode, + adUnitTargeting: targetingCopy[adUnitCode] + }; + }).sort(sortByDealAndPriceBucket); + + // iterate through the targeting based on above list and transform the keys into the query-equivalent and count characters + return targetingMap.reduce(function (accMap, currMap, index, arr) { + let adUnitQueryString = convertKeysToQueryForm(currMap.adUnitTargeting); + + // for the last adUnit - trim last encoded ampersand from the converted query string + if ((index + 1) === arr.length) { + adUnitQueryString = adUnitQueryString.slice(0, -3); + } + + // if under running threshold add to result + let code = currMap.adUnitCode; + let querySize = adUnitQueryString.length; + if (querySize <= auctionKeysThreshold) { + auctionKeysThreshold -= querySize; + logInfo(`AdUnit '${code}' auction keys comprised of ${querySize} characters. Deducted from running threshold; new limit is ${auctionKeysThreshold}`, targetingCopy[code]); + + accMap[code] = targetingCopy[code]; + } else { + logWarn(`The following keys for adUnitCode '${code}' exceeded the current limit of the 'auctionKeyMaxChars' setting.\nThe key-set size was ${querySize}, the current allotted amount was ${auctionKeysThreshold}.\n`, targetingCopy[code]); + } + + if ((index + 1) === arr.length && Object.keys(accMap).length === 0) { + logError('No auction targeting keys were permitted due to the setting in setConfig(targetingControls.auctionKeyMaxChars). Please review setup and consider adjusting.'); + } + return accMap; + }, {}); + } + /** * Converts targeting array and flattens to make it easily iteratable * e.g: Sample input to this function diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 727c790c991..bc5958f0495 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { targeting as targetingInstance, filters } from 'src/targeting'; +import { targeting as targetingInstance, filters, sortByDealAndPriceBucket } from 'src/targeting'; import { config } from 'src/config'; import { getAdUnits, createBidReceived } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; @@ -128,6 +128,8 @@ describe('targeting tests', function () { let amBidsReceivedStub; let amGetAdUnitsStub; let bidExpiryStub; + let logWarnStub; + let logErrorStub; let bidsReceived; beforeEach(function () { @@ -140,6 +142,14 @@ describe('targeting tests', function () { return ['/123456/header-bid-tag-0']; }); bidExpiryStub = sandbox.stub(filters, 'isBidNotExpired').returns(true); + logWarnStub = sinon.stub(utils, 'logWarn'); + logErrorStub = sinon.stub(utils, 'logError'); + }); + + afterEach(function() { + config.resetConfig(); + logWarnStub.restore(); + logErrorStub.restore(); }); describe('when hb_deal is present in bid.adserverTargeting', function () { @@ -165,6 +175,34 @@ describe('targeting tests', function () { }); }); + it('will enforce a limit on the number of auction keys when auctionKeyMaxChars setting is active', function () { + config.setConfig({ + targetingControls: { + auctionKeyMaxChars: 150 + } + }); + + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0', '/123456/header-bid-tag-1']); + expect(targeting['/123456/header-bid-tag-1']).to.deep.equal({}); + expect(targeting['/123456/header-bid-tag-0']).to.contain.keys('hb_pb', 'hb_adid', 'hb_bidder', 'hb_deal'); + expect(targeting['/123456/header-bid-tag-0']['hb_adid']).to.equal(bid1.adId); + expect(logWarnStub.calledOnce).to.be.true; + }); + + it('will return an error when auctionKeyMaxChars setting is set too low for any auction keys to be allowed', function () { + config.setConfig({ + targetingControls: { + auctionKeyMaxChars: 50 + } + }); + + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0', '/123456/header-bid-tag-1']); + expect(targeting['/123456/header-bid-tag-1']).to.deep.equal({}); + expect(targeting['/123456/header-bid-tag-0']).to.deep.equal({}); + expect(logWarnStub.calledTwice).to.be.true; + expect(logErrorStub.calledOnce).to.be.true; + }); + it('selects the top bid when enableSendAllBids true', function () { enableSendAllBids = true; let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); @@ -327,6 +365,126 @@ describe('targeting tests', function () { }); }); + describe('sortByDealAndPriceBucket', function() { + it('will properly sort bids when some bids have deals and some do not', function () { + let bids = [{ + adUnitTargeting: { + hb_adid: 'abc', + hb_pb: '1.00', + hb_deal: '1234' + } + }, { + adUnitTargeting: { + hb_adid: 'def', + hb_pb: '0.50', + } + }, { + adUnitTargeting: { + hb_adid: 'ghi', + hb_pb: '20.00', + hb_deal: '4532' + } + }, { + adUnitTargeting: { + hb_adid: 'jkl', + hb_pb: '9.00', + hb_deal: '9864' + } + }, { + adUnitTargeting: { + hb_adid: 'mno', + hb_pb: '50.00', + } + }, { + adUnitTargeting: { + hb_adid: 'pqr', + hb_pb: '100.00', + } + }]; + bids.sort(sortByDealAndPriceBucket); + expect(bids[0].adUnitTargeting.hb_adid).to.equal('ghi'); + expect(bids[1].adUnitTargeting.hb_adid).to.equal('jkl'); + expect(bids[2].adUnitTargeting.hb_adid).to.equal('abc'); + expect(bids[3].adUnitTargeting.hb_adid).to.equal('pqr'); + expect(bids[4].adUnitTargeting.hb_adid).to.equal('mno'); + expect(bids[5].adUnitTargeting.hb_adid).to.equal('def'); + }); + + it('will properly sort bids when all bids have deals', function () { + let bids = [{ + adUnitTargeting: { + hb_adid: 'abc', + hb_pb: '1.00', + hb_deal: '1234' + } + }, { + adUnitTargeting: { + hb_adid: 'def', + hb_pb: '0.50', + hb_deal: '4321' + } + }, { + adUnitTargeting: { + hb_adid: 'ghi', + hb_pb: '2.50', + hb_deal: '4532' + } + }, { + adUnitTargeting: { + hb_adid: 'jkl', + hb_pb: '2.00', + hb_deal: '9864' + } + }]; + bids.sort(sortByDealAndPriceBucket); + expect(bids[0].adUnitTargeting.hb_adid).to.equal('ghi'); + expect(bids[1].adUnitTargeting.hb_adid).to.equal('jkl'); + expect(bids[2].adUnitTargeting.hb_adid).to.equal('abc'); + expect(bids[3].adUnitTargeting.hb_adid).to.equal('def'); + }); + + it('will properly sort bids when no bids have deals', function () { + let bids = [{ + adUnitTargeting: { + hb_adid: 'abc', + hb_pb: '1.00' + } + }, { + adUnitTargeting: { + hb_adid: 'def', + hb_pb: '0.10' + } + }, { + adUnitTargeting: { + hb_adid: 'ghi', + hb_pb: '10.00' + } + }, { + adUnitTargeting: { + hb_adid: 'jkl', + hb_pb: '10.01' + } + }, { + adUnitTargeting: { + hb_adid: 'mno', + hb_pb: '1.00' + } + }, { + adUnitTargeting: { + hb_adid: 'pqr', + hb_pb: '100.00' + } + }]; + bids.sort(sortByDealAndPriceBucket); + expect(bids[0].adUnitTargeting.hb_adid).to.equal('pqr'); + expect(bids[1].adUnitTargeting.hb_adid).to.equal('jkl'); + expect(bids[2].adUnitTargeting.hb_adid).to.equal('ghi'); + expect(bids[3].adUnitTargeting.hb_adid).to.equal('abc'); + expect(bids[4].adUnitTargeting.hb_adid).to.equal('mno'); + expect(bids[5].adUnitTargeting.hb_adid).to.equal('def'); + }); + }); + describe('setTargetingForAst', function () { let sandbox, apnTagStub; From a2f8500f14989beeffa2ecfd8405e5275d74dc75 Mon Sep 17 00:00:00 2001 From: Aleksa Trajkovic Date: Wed, 29 May 2019 05:02:00 +0200 Subject: [PATCH 1250/1594] aardvark tdid support (#3860) * aardvark tdid support * increase aardvark test coverage --- modules/aardvarkBidAdapter.js | 9 +++ test/spec/modules/aardvarkBidAdapter_spec.js | 70 ++++++++++++++++++-- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index 108e56ac06a..239800ce7fa 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -27,6 +27,7 @@ export const spec = { var requestsMap = {}; var referer = bidderRequest.refererInfo.referer; var pageCategories = []; + var tdId = ''; // This reference to window.top can cause issues when loaded in an iframe if not protected with a try/catch. try { @@ -35,6 +36,10 @@ export const spec = { } } catch (e) {} + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) { + tdId = validBidRequests[0].userId.tdid; + } + utils._each(validBidRequests, function(b) { var rMap = requestsMap[b.params.ai]; if (!rMap) { @@ -48,6 +53,10 @@ export const spec = { endpoint: DEFAULT_ENDPOINT }; + if (tdId) { + rMap.payload.tdid = tdId; + } + if (pageCategories && pageCategories.length) { rMap.payload.categories = pageCategories.slice(0); } diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js index 8ce4aa85561..727527acf29 100644 --- a/test/spec/modules/aardvarkBidAdapter_spec.js +++ b/test/spec/modules/aardvarkBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec } from 'modules/aardvarkBidAdapter'; +import { spec, resetUserSync } from 'modules/aardvarkBidAdapter'; describe('aardvarkAdapterTest', function () { describe('forming valid bidRequests', function () { @@ -37,7 +37,8 @@ describe('aardvarkAdapterTest', function () { sizes: [300, 250], bidId: '1abgs362e0x48a8', bidderRequestId: '70deaff71c281d', - auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + auctionId: '5c66da22-426a-4bac-b153-77360bef5337', + userId: { tdid: 'eff98622-b5fd-44fa-9a49-6e846922d532' } }, { bidder: 'aardvark', @@ -62,7 +63,7 @@ describe('aardvarkAdapterTest', function () { it('should use HTTP GET method', function () { const requests = spec.buildRequests(bidRequests, bidderRequest); - requests.forEach(function(requestItem) { + requests.forEach(function (requestItem) { expect(requestItem.method).to.equal('GET'); }); }); @@ -82,6 +83,13 @@ describe('aardvarkAdapterTest', function () { expect(requests[0].data.rtkreferer).to.not.be.undefined; expect(requests[0].data.RAZd).to.equal('22aidtbx5eabd9'); }); + + it('should have tdid, it is available in bidRequest', function () { + const requests = spec.buildRequests(bidRequests, bidderRequest); + requests.forEach(function (requestItem) { + expect(requestItem.data.tdid).to.equal('eff98622-b5fd-44fa-9a49-6e846922d532'); + }); + }); }); describe('splitting multi-auction ad units into own requests', function () { @@ -122,7 +130,7 @@ describe('aardvarkAdapterTest', function () { it('should use HTTP GET method', function () { const requests = spec.buildRequests(bidRequests, bidderRequest); - requests.forEach(function(requestItem) { + requests.forEach(function (requestItem) { expect(requestItem.method).to.equal('GET'); }); }); @@ -148,6 +156,13 @@ describe('aardvarkAdapterTest', function () { expect(requests[1].data.rtkreferer).to.not.be.undefined; expect(requests[1].data.RAZd).to.equal('22aidtbx5eabd9'); }); + + it('should have no tdid, it is not available in bidRequest', function () { + const requests = spec.buildRequests(bidRequests, bidderRequest); + requests.forEach(function (requestItem) { + expect(requestItem.data.tdid).to.be.undefined; + }); + }); }); describe('GDPR conformity', function () { @@ -281,4 +296,51 @@ describe('aardvarkAdapterTest', function () { expect(result.length).to.equal(0); }); }); + + describe('getUserSyncs', function () { + const syncOptions = { + iframeEnabled: true + }; + + it('should produce sync url', function () { + const syncs = spec.getUserSyncs(syncOptions); + expect(syncs.length).to.equal(1); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.equal('//sync.rtk.io/cs'); + }); + + it('should return empty, as we sync only once', function () { + const syncs = spec.getUserSyncs(syncOptions); + expect(syncs.length).to.equal(0); + }); + + it('should reset hasSynced flag, allowing another sync', function () { + resetUserSync(); + + const syncs = spec.getUserSyncs(syncOptions); + expect(syncs.length).to.equal(1); + }); + + it('should return empty when iframe disallowed', function () { + resetUserSync(); + + const noIframeOptions = { iframeEnabled: false }; + const syncs = spec.getUserSyncs(noIframeOptions); + expect(syncs.length).to.equal(0); + }); + + it('should produce sync url with gdpr params', function () { + const gdprConsent = { + gdprApplies: true, + consentString: 'BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA' + }; + + resetUserSync(); + + const syncs = spec.getUserSyncs(syncOptions, null, gdprConsent); + expect(syncs.length).to.equal(1); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.equal('//sync.rtk.io/cs?g=1&c=BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA'); + }); + }); }); From bec741de7174f6b3371635f9fc3a9a66c0eed220 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Wed, 29 May 2019 08:53:50 -0700 Subject: [PATCH 1251/1594] We want to remove bidfloor if not set by pb (#3866) --- modules/rubiconBidAdapter.js | 5 ++++- test/spec/modules/rubiconBidAdapter_spec.js | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index dd1c815150e..48ce6ae9648 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -134,7 +134,6 @@ export const spec = { }, tmax: config.getConfig('TTL') || 1000, imp: [{ - bidfloor: utils.deepAccess(bidRequest, 'params.floor') ? parseFloat(bidRequest.params.floor) : 0.0, exp: 300, id: bidRequest.adUnitCode, secure: isSecure() || bidRequest.params.secure ? 1 : 0, @@ -159,6 +158,10 @@ export const spec = { } } } + const bidFloor = parseFloat(utils.deepAccess(bidRequest, 'params.floor')); + if (!isNaN(bidFloor)) { + data.imp[0].bidfloor = bidFloor; + } // if value is set, will overwrite with same value data.imp[0].ext.rubicon.video.size_id = determineRubiconVideoSizeId(bidRequest) diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 0f29afe0069..67a92d4a26e 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1160,15 +1160,15 @@ describe('the rubicon adapter', function () { bidderRequest.bids[0].params.floor = 0; [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - expect(request.data.imp[0].bidfloor).to.equal(0.0); + expect(request.data.imp[0].bidfloor).to.equal(0); bidderRequest.bids[0].params.floor = undefined; [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - expect(request.data.imp[0].bidfloor).to.equal(0.0); + expect(request.data.imp[0]).to.not.haveOwnProperty('bidfloor'); bidderRequest.bids[0].params.floor = null; [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - expect(request.data.imp[0].bidfloor).to.equal(0.0); + expect(request.data.imp[0]).to.not.haveOwnProperty('bidfloor'); }); it('should send request with proper ad position when mediaTypes.video.pos is not defined', function () { From efd5ed614f0c554ec3261cbaf4a701670ab06d37 Mon Sep 17 00:00:00 2001 From: Gaudeamus Date: Wed, 29 May 2019 19:08:34 +0300 Subject: [PATCH 1252/1594] mgid adapter: add support of currency.adServerCurrency (#3850) * native support & minor changes * native support & minor changes * increase test coverage * fix win price value * fix win price value tests * fix alias, fix bidfloor * remove alias * use currency.adServerCurrency * update version --- modules/mgidBidAdapter.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index b7759ea1e0a..e1b15ef4b51 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -2,6 +2,7 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import * as utils from '../src/utils'; import * as urlUtils from '../src/url'; import {BANNER, NATIVE} from 'src/mediaTypes'; +import {config} from '../src/config'; const DEFAULT_CUR = 'USD'; const BIDDER_CODE = 'mgid'; const ENDPOINT_URL = 'https://prebid.mgid.com/prebid/'; @@ -59,7 +60,7 @@ utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); export const spec = { - VERSION: '1.1', + VERSION: '1.2', code: BIDDER_CODE, supportedMediaTypes: [BANNER, NATIVE], reId: /^[0-9]+$/, @@ -126,6 +127,7 @@ export const spec = { if (utils.isStr(muid) && muid.length > 0) { url += '?muid=' + muid; } + const cur = [config.getConfig('currency.adServerCurrency') || setOnAny(validBidRequests, 'params.currency') || setOnAny(validBidRequests, 'params.cur') || DEFAULT_CUR]; const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || referer; const secure = window.location.protocol === 'https:' ? 1 : 0; let imp = []; @@ -177,7 +179,7 @@ export const spec = { let request = { id: utils.deepAccess(bidderRequest, 'bidderRequestId'), site: { domain, page }, - cur: [setOnAny(validBidRequests, 'params.currency') || setOnAny(validBidRequests, 'params.cur') || DEFAULT_CUR], + cur: cur, device: { ua: navigator.userAgent, js: 1, From 7094e082cf40aec76fba2c1dd7deda2a401aa906 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Wed, 29 May 2019 11:44:55 -0700 Subject: [PATCH 1253/1594] Prebid 2.17.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab415a03ea0..cda4e7d6b0a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.17.0-pre", + "version": "2.17.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From dc8f6d50acf1d8af796b49ad2e423d5e02d447fd Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Wed, 29 May 2019 12:05:34 -0700 Subject: [PATCH 1254/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cda4e7d6b0a..e84e1698434 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.17.0", + "version": "2.18.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 582ecdf89b21cc4b78d9059151a344f89ebf8e78 Mon Sep 17 00:00:00 2001 From: adxcgcom <31470944+adxcgcom@users.noreply.github.com> Date: Thu, 30 May 2019 17:11:07 +0000 Subject: [PATCH 1255/1594] adxcgBidAdapter - added pubcid (#3824) * adxcgBidAdapter - added pubcid * mini fix * Update adxcgBidAdapter Added minimal change to restart CI process * added passing tdid, updated pubcid * unit test for userid support - pubcid, tdid * Update adxcgBidAdapter.js just to restart CircleCI * Update adxcgBidAdapter.js just to restart CircleCI --- modules/adxcgBidAdapter.js | 9 ++++ test/spec/modules/adxcgBidAdapter_spec.js | 50 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/modules/adxcgBidAdapter.js b/modules/adxcgBidAdapter.js index 23808fa3be7..34b5ea25fb0 100644 --- a/modules/adxcgBidAdapter.js +++ b/modules/adxcgBidAdapter.js @@ -11,6 +11,7 @@ import includes from 'core-js/library/fn/array/includes' * 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 */ const BIDDER_CODE = 'adxcg' @@ -159,6 +160,14 @@ export const spec = { beaconParams.prebidBidIds = prebidBidIds.join(',') beaconParams.bidfloors = bidfloors.join(',') + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.pubcid'))) { + beaconParams.pubcid = validBidRequests[0].userId.pubcid; + } + + if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) { + beaconParams.tdid = validBidRequests[0].userId.tdid; + } + let adxcgRequestUrl = url.format({ protocol: secure ? 'https' : 'http', hostname: secure ? 'hbps.adxcg.net' : 'hbp.adxcg.net', diff --git a/test/spec/modules/adxcgBidAdapter_spec.js b/test/spec/modules/adxcgBidAdapter_spec.js index 0277e0ab964..5bac9523b18 100644 --- a/test/spec/modules/adxcgBidAdapter_spec.js +++ b/test/spec/modules/adxcgBidAdapter_spec.js @@ -133,6 +133,56 @@ describe('AdxcgAdapter', function () { }) }) + describe('userid pubcid should be passed to querystring', function () { + let bid = [{ + 'bidder': 'adxcg', + 'params': { + 'adzoneid': '1' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [640, 360], [1, 1]], + 'bidId': '84ab500420319d', + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '1d1a030790a475', + }] + + let bidderRequests = {}; + + bid[0].userId = {'pubcid': 'pubcidabcd'}; + + it('should send pubcid if available', function () { + let request = spec.buildRequests(bid, bidderRequests) + let parsedRequestUrl = url.parse(request.url) + let query = parsedRequestUrl.search + expect(query.pubcid).to.equal('pubcidabcd') + }) + }) + + describe('userid tdid should be passed to querystring', function () { + let bid = [{ + 'bidder': 'adxcg', + 'params': { + 'adzoneid': '1' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [640, 360], [1, 1]], + 'bidId': '84ab500420319d', + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '1d1a030790a475', + }] + + let bidderRequests = {}; + + bid[0].userId = {'tdid': 'tdidabcd'}; + + it('should send pubcid if available', function () { + let request = spec.buildRequests(bid, bidderRequests) + let parsedRequestUrl = url.parse(request.url) + let query = parsedRequestUrl.search + expect(query.tdid).to.equal('tdidabcd'); + }) + }) + describe('response handler', function () { let BIDDER_REQUEST = { 'bidder': 'adxcg', From 7aa0e0d4a0bd36351d5d095c5d7556c4dc0b346b Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 3 Jun 2019 08:29:00 -0700 Subject: [PATCH 1256/1594] getCpmInNewCurrency to use current value of bid.cpm and bid.currency (#3845) * getCpmInNewCurrency to use current value of bid.cpm and bid.currency * added a test case for boosted bid, this test fails with old code --- modules/currency.js | 5 +---- test/spec/modules/currency_spec.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/modules/currency.js b/modules/currency.js index 17c38b17a98..a3e2c223072 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -180,12 +180,9 @@ export function addBidResponseHook(fn, adUnitCode, bid) { bid.currency = 'USD'; } - let fromCurrency = bid.currency; - let cpm = bid.cpm; - // used for analytics bid.getCpmInNewCurrency = function(toCurrency) { - return (parseFloat(cpm) * getCurrencyConversion(fromCurrency, toCurrency)).toFixed(3); + return (parseFloat(this.cpm) * getCurrencyConversion(this.currency, toCurrency)).toFixed(3); }; // execute immediately if the bid is already in the desired currency diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index 9fb32102749..98f51b72251 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -191,6 +191,34 @@ describe('currency', function () { expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000'); }); + it('uses rates specified in json when provided and consider boosted bid', function () { + setConfig({ + adServerCurrency: 'USD', + rates: { + USD: { + JPY: 100 + } + } + }); + + var bid = { cpm: 100, currency: 'JPY', bidder: 'rubicon' }; + var innerBid; + + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bid); + + expect(innerBid.cpm).to.equal('1.0000'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000'); + + // Boosting the bid now + innerBid.cpm *= 10; + expect(innerBid.cpm).to.equal(10.0000); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('1000.000'); + }); + it('uses default rates when currency file fails to load', function () { setConfig({}); From ac658124afeba062b41cb07b81921f6ac1878d50 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 3 Jun 2019 08:36:21 -0700 Subject: [PATCH 1257/1594] always adding originalCpm and originalCurrency to bid object (#3856) --- modules/currency.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/currency.js b/modules/currency.js index a3e2c223072..ae2f9ac1f1b 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -185,6 +185,9 @@ export function addBidResponseHook(fn, adUnitCode, bid) { return (parseFloat(this.cpm) * getCurrencyConversion(this.currency, toCurrency)).toFixed(3); }; + bid.originalCpm = bid.cpm; + bid.originalCurrency = bid.currency; + // execute immediately if the bid is already in the desired currency if (bid.currency === adServerCurrency) { return fn.call(this, adUnitCode, bid); @@ -209,8 +212,6 @@ function wrapFunction(fn, context, params) { let fromCurrency = bid.currency; try { let conversion = getCurrencyConversion(fromCurrency); - bid.originalCpm = bid.cpm; - bid.originalCurrency = bid.currency; if (conversion !== 1) { bid.cpm = (parseFloat(bid.cpm) * conversion).toFixed(4); bid.currency = adServerCurrency; From db167c0ff28f9a9b07ba94783161a61366df2aac Mon Sep 17 00:00:00 2001 From: "Antoine Jacquemin (Rubicon)" Date: Tue, 4 Jun 2019 05:13:13 +0800 Subject: [PATCH 1258/1594] new size Rubicon (#3877) add size 288 (640x380) --- modules/rubiconBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 48ce6ae9648..a0e9c89a221 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -81,7 +81,8 @@ var sizeMap = { 229: '320x180', 232: '580x400', 257: '400x600', - 265: '1920x1080' + 265: '1920x1080', + 288: '640x380' }; utils._each(sizeMap, (item, key) => sizeMap[item] = key); From 2f208f86d620b3a83bdf75e5943c41075e2d58bd Mon Sep 17 00:00:00 2001 From: AdmixerTech <35560933+AdmixerTech@users.noreply.github.com> Date: Tue, 4 Jun 2019 17:38:35 +0300 Subject: [PATCH 1259/1594] BIDDER_CODE check removed (#3862) --- modules/admixerBidAdapter.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/admixerBidAdapter.js b/modules/admixerBidAdapter.js index ee224dc6a5c..c6d6dd34a11 100644 --- a/modules/admixerBidAdapter.js +++ b/modules/admixerBidAdapter.js @@ -29,9 +29,7 @@ export const spec = { referrer: encodeURIComponent(utils.getTopWindowUrl()), }; bidderRequest.forEach((bid) => { - if (bid.bidder === BIDDER_CODE || ALIASES.indexOf(bid.bidder) > -1) { - payload.imps.push(bid); - } + payload.imps.push(bid); }); const payloadString = JSON.stringify(payload); return { From 2a10388dc44f5cc792bed72a2d3e3cfae07cd769 Mon Sep 17 00:00:00 2001 From: Arne Schulz Date: Tue, 4 Jun 2019 17:16:02 +0200 Subject: [PATCH 1260/1594] Bugfix add bid parameters if not present (#3808) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons * add bidfloor parameter to params object * fix gdpr object handling * default to consentRequired: false when not explicitly given * wip - use onSetTargeting callback * add tests for onSetTargeting callback * fix params and respective tests --- modules/orbidderBidAdapter.js | 5 ++--- test/spec/modules/orbidderBidAdapter_spec.js | 14 +++++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index 1123cc5d50e..e085a14c6b8 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -82,10 +82,9 @@ export const spec = { const getRefererInfo = detectReferer(window); bid.pageUrl = getRefererInfo().referer; - if (spec.bidParams[bid.adId]) { - bid.params = spec.bidParams[bid.adId]; + if (spec.bidParams[bid.requestId] && (typeof bid.params === 'undefined')) { + bid.params = [spec.bidParams[bid.requestId]]; } - spec.ajaxCall(`${spec.orbidderHost}${route}`, JSON.stringify(bid)); }, diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 3818f502901..55f5e2cae4c 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -2,6 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/orbidderBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import openxAdapter from '../../../modules/openxAnalyticsAdapter'; +import {detectReferer} from 'src/refererDetection'; describe('orbidderBidAdapter', () => { const adapter = newBidder(spec); @@ -153,9 +154,16 @@ describe('orbidderBidAdapter', () => { adId: 'testId', test: 1, pageUrl: 'www.someurl.de', - referrer: 'www.somereferrer.de' + referrer: 'www.somereferrer.de', + requestId: '123req456' }; + spec.bidParams['123req456'] = {'accountId': '123acc456'}; + + let bidObjClone = deepClone(bidObj); + bidObjClone.pageUrl = detectReferer(window)().referer; + bidObjClone.params = [{'accountId': '123acc456'}]; + beforeEach(() => { ajaxStub = sinon.stub(spec, 'ajaxCall'); }); @@ -169,13 +177,13 @@ describe('orbidderBidAdapter', () => { expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0].indexOf('https://')).to.equal(0); expect(ajaxStub.firstCall.args[0]).to.equal(`${spec.orbidderHost}/win`); - expect(ajaxStub.firstCall.args[1]).to.equal(JSON.stringify(bidObj)); + expect(ajaxStub.firstCall.args[1]).to.equal(JSON.stringify(bidObjClone)); spec.onSetTargeting(bidObj); expect(ajaxStub.calledTwice).to.equal(true); expect(ajaxStub.secondCall.args[0].indexOf('https://')).to.equal(0); expect(ajaxStub.secondCall.args[0]).to.equal(`${spec.orbidderHost}/targeting`); - expect(ajaxStub.secondCall.args[1]).to.equal(JSON.stringify(bidObj)); + expect(ajaxStub.secondCall.args[1]).to.equal(JSON.stringify(bidObjClone)); }); }); From 1f9937e1f4503f414f192466d43789409f83e4db Mon Sep 17 00:00:00 2001 From: guiann Date: Wed, 5 Jun 2019 16:23:02 +0200 Subject: [PATCH 1261/1594] Remove useless bidderCode in bid response (#3864) --- modules/adyoulikeBidAdapter.js | 1 - test/spec/modules/adyoulikeBidAdapter_spec.js | 5 ----- 2 files changed, 6 deletions(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index 4624bdba8b5..fd7a1697bac 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -187,7 +187,6 @@ function createBid(response) { return { requestId: response.BidID, - bidderCode: spec.code, width: response.Width, height: response.Height, ad: response.Ad, diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js index 3f28acaaf97..7edb9416b03 100644 --- a/test/spec/modules/adyoulikeBidAdapter_spec.js +++ b/test/spec/modules/adyoulikeBidAdapter_spec.js @@ -7,7 +7,6 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('Adyoulike Adapter', function () { const canonicalUrl = 'http://canonical.url/?t=%26'; const defaultDC = 'hb-api'; - const bidderCode = 'adyoulike'; const bidRequestWithEmptyPlacement = [ { 'bidId': 'bid_id_0', @@ -18,7 +17,6 @@ describe('Adyoulike Adapter', function () { } ]; const bidRequestWithEmptySizes = { - 'bidderCode': 'adyoulike', 'bids': [ { 'bidId': 'bid_id_0', @@ -193,7 +191,6 @@ describe('Adyoulike Adapter', function () { it('should add gdpr consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { - 'bidderCode': 'adyoulike', 'auctionId': '1d1a030790a475', 'bidderRequestId': '22edbae2733bf6', 'timeout': 3000, @@ -306,13 +303,11 @@ describe('Adyoulike Adapter', function () { expect(result.length).to.equal(2); - expect(result[0].bidderCode).to.equal(bidderCode); expect(result[0].cpm).to.equal(0.5); expect(result[0].ad).to.equal('placement_0'); expect(result[0].width).to.equal(300); expect(result[0].height).to.equal(300); - expect(result[1].bidderCode).to.equal(bidderCode); expect(result[1].cpm).to.equal(0.6); expect(result[1].ad).to.equal('placement_1'); expect(result[1].width).to.equal(300); From 3ac37f8c7bd3677105bebb947454abffad591bbf Mon Sep 17 00:00:00 2001 From: Michael Rooke Date: Wed, 5 Jun 2019 10:38:40 -0400 Subject: [PATCH 1262/1594] Use actual global object name in log message (#3874) - The global Prebid.js object name can be something other than 'pbjs'. Update log messages to reference the specified prebid global object name. --- modules/dfpAdServerVideo.js | 2 +- src/video.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index d8cd6e099ee..79c11c5c886 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -58,7 +58,7 @@ const defaultParamConstants = { */ export default function buildDfpVideoUrl(options) { if (!options.params && !options.url) { - logError(`A params object or a url is required to use pbjs.adServers.dfp.buildVideoUrl`); + logError(`A params object or a url is required to use $$PREBID_GLOBAL$$.adServers.dfp.buildVideoUrl`); return; } diff --git a/src/video.js b/src/video.js index 9cf25016d46..f59ff78a32a 100644 --- a/src/video.js +++ b/src/video.js @@ -48,7 +48,7 @@ export const checkVideoBidSetup = hook('sync', function(bid, bidRequest, videoMe if (!config.getConfig('cache.url') && bid.vastXml && !bid.vastUrl) { 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: "..."} }); + Try enabling prebid cache with $$PREBID_GLOBAL$$.setConfig({ cache: {url: "..."} }); `); return false; } From 2cf64989037c837a89cd4832b41a6c08981990d1 Mon Sep 17 00:00:00 2001 From: Chris Cole Date: Wed, 5 Jun 2019 08:59:12 -0700 Subject: [PATCH 1263/1594] Digitrust submodule (#3867) * Initial checkin with submodule support for DigiTrust. * Addition of simple example file * DigiTrust submodule now functioning with new userId system. * Addition of Full example and confirming to work with or without DigiTrust library. * Update based upon code review requests. * Revert "Initial checkin with submodule support for DigiTrust." This reverts commit c1fc37a888958150ce9ebd528ad910cc217ff6aa. # Conflicts: # modules/digiTrustIdSystem.js # modules/digiTrustIdSystem.md --- integrationExamples/gpt/digitrust_Full.html | 222 +++++++++++++ integrationExamples/gpt/digitrust_Simple.html | 220 +++++++++++++ modules/digiTrustIdSystem.js | 307 ++++++++++++++++++ modules/digiTrustIdSystem.md | 154 +++++++++ 4 files changed, 903 insertions(+) create mode 100644 integrationExamples/gpt/digitrust_Full.html create mode 100644 integrationExamples/gpt/digitrust_Simple.html create mode 100644 modules/digiTrustIdSystem.js create mode 100644 modules/digiTrustIdSystem.md diff --git a/integrationExamples/gpt/digitrust_Full.html b/integrationExamples/gpt/digitrust_Full.html new file mode 100644 index 00000000000..7ec268a619a --- /dev/null +++ b/integrationExamples/gpt/digitrust_Full.html @@ -0,0 +1,222 @@ + + + Full DigiTrust Prebid Sample + + + + + + + + + + + + + +

    DigiTrust Prebid Full Sample

    + + +

    + This sample shows the simplest integration path for using DigiTrust ID with Prebid. + You can use DigiTrust ID without integrating the entire DigiTrust suite. +

    + +
    + +
    + +
    + + + + diff --git a/integrationExamples/gpt/digitrust_Simple.html b/integrationExamples/gpt/digitrust_Simple.html new file mode 100644 index 00000000000..c9a8c1d2ad6 --- /dev/null +++ b/integrationExamples/gpt/digitrust_Simple.html @@ -0,0 +1,220 @@ + + + Simple DigiTrust Prebid - No Framework + + + + + + + + + + + + + + +

    DigiTrust Prebid Sample - No Framework

    + +

    + This sample shows the simplest integration path for using DigiTrust ID with Prebid. + You can use DigiTrust ID without integrating the entire DigiTrust suite. +

    +
    + +
    + +
    + + diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js new file mode 100644 index 00000000000..b587913e1ed --- /dev/null +++ b/modules/digiTrustIdSystem.js @@ -0,0 +1,307 @@ +/** + * This module adds DigiTrust ID support to the User ID module + * The {@link module:modules/userId} module is required + * If the full DigiTrust Id library is included the standard functions + * will be invoked to obtain the user's DigiTrust Id. + * When the full library is not included this will fall back to the + * DigiTrust Identity API and generate a mock DigiTrust object. + * @module modules/digiTrustIdSystem + * @requires module:modules/userId + */ + +// import { config } from 'src/config'; +import * as utils from '../src/utils' +import { ajax } from 'src/ajax'; +import { attachIdSystem } from '../modules/userId'; +// import { getGlobal } from 'src/prebidGlobal'; + +/** + * Checks to see if the DigiTrust framework is initialized. + * @function + */ +function isInitialized() { + if (window.DigiTrust == null) { + return false; + } + return DigiTrust.isClient; // this is set to true after init +} + +/** + * Tests for presence of the DigiTrust object + * */ +function isPresent() { + return (window.DigiTrust != null); +} + +var noop = function () { +}; + +const MAX_RETRIES = 2; +const DT_ID_SVC = 'https://prebid.digitru.st/id/v1'; + +var isFunc = function (fn) { + return typeof (fn) === 'function'; +} + +function callApi(options) { + ajax( + DT_ID_SVC, + { + success: options.success, + error: options.fail + }, + null, + { + method: 'GET' + } + ); +} + +/** + * Encode the Id per DigiTrust lib + * @param {any} id + */ +function encId(id) { + try { + if (typeof (id) !== 'string') { + id = JSON.stringify(id); + } + return encodeURIComponent(btoa(id)); + } catch (ex) { + return id; + } +} + +/** + * Writes the Identity into the expected DigiTrust cookie + * @param {any} id + */ +function writeDigiId(id) { + var key = 'DigiTrust.v1.identity'; + var date = new Date(); + date.setTime(date.getTime() + 604800000); + var exp = 'expires=' + date.toUTCString(); + document.cookie = key + '=' + encId(id) + '; ' + exp + '; path=/;'; +} + +/** + * Set up a DigiTrust fascade object to mimic the API + * + */ +function initDigitrustFascade(config) { + var _savedId = null; // closure variable for storing Id to avoid additional requests + var fascade = { + isClient: true, + isMock: true, + _internals: { + callCount: 0, + initCallback: null + }, + getUser: function (obj, callback) { + var cb = callback || noop; + var inter = fascade._internals; + inter.callCount++; + + // wrap the initializer callback, if present + var checkCallInitializeCb = function (idResponse) { + if (inter.callCount <= 1 && isFunc(inter.initCallback)) { + try { + inter.initCallback(idResponse); + } catch (ex) { + utils.logError('Exception in passed DigiTrust init callback'); + } + } + } + + if (_savedId != null) { + checkCallInitializeCb(_savedId); + cb(_savedId); + return; + } + + var opts = { + success: function (respText, result) { + var idResult = { + success: true + } + try { + writeDigiId(respText); + idResult.identity = JSON.parse(respText); + _savedId = idResult; + } catch (ex) { + idResult.success = false; + } + checkCallInitializeCb(idResult); + cb(idResult); + }, + fail: function (statusErr, result) { + utils.logError('DigiTrustId API error: ' + statusErr); + } + } + + callApi(opts); + } + } + + if (window && window.DigiTrust == null) { + window.DigiTrust = fascade; + } +} + +/** + * Encapsulation of needed info for the callback return. + * + * @param {any} opts + */ +var ResultWrapper = function (opts) { + var me = this; + this.idObj = null; + + var idSystemFn = null; + + /** + * Callback method that is passed back to the userId module. + * + * @param {function} callback + */ + this.userIdCallback = function (callback) { + idSystemFn = callback; + if (me.idObj != null && isFunc(callback)) { + callback(wrapIdResult()); + } + } + + /** + * Return a wrapped result formatted for userId system + */ + function wrapIdResult() { + if (me.idObj == null) { + return null; + } + + var cp = me.configParams; + var exp = (cp && cp.storage && cp.storage.expires) || 60; + + var rslt = { + data: null, + expires: exp + }; + if (me.idObj && me.idObj.success && me.idObj.identity) { + rslt.data = me.idObj.identity; + } else { + rslt.err = 'Failure getting id'; + } + + return rslt; + } + + this.retries = 0; + this.retryId = 0; + + this.executeIdRequest = function (configParams) { + DigiTrust.getUser({ member: 'prebid' }, function (idResult) { + me.idObj = idResult; + var cb = function () { + if (isFunc(idSystemFn)) { + idSystemFn(wrapIdResult()); + } + } + + cb(); + if (configParams && configParams.callback && isFunc(configParams.callback)) { + try { + configParams.callback(idResult); + } catch (ex) { + utils.logError('Failure in DigiTrust executeIdRequest', ex); + } + } + }); + } +} + +// An instance of the result wrapper object. +var resultHandler = new ResultWrapper(); + +/* + * Internal implementation to get the Id and trigger callback + */ +function getDigiTrustId(configParams) { + if (resultHandler.configParams == null) { + resultHandler.configParams = configParams; + } + + // First see if we should initialize DigiTrust framework + if (isPresent() && !isInitialized()) { + initializeDigiTrust(configParams); + resultHandler.retryId = setTimeout(function () { + getDigiTrustId(configParams); + }, 100 * (1 + resultHandler.retries++)); + return resultHandler.userIdCallback; + } else if (!isInitialized()) { // Second see if we should build a fascade object + if (resultHandler.retries >= MAX_RETRIES) { + initDigitrustFascade(configParams); // initialize a fascade object that relies on the AJAX call + resultHandler.executeIdRequest(configParams); + } else { + // use expanding envelope + if (resultHandler.retryId != 0) { + clearTimeout(resultHandler.retryId); + } + resultHandler.retryId = setTimeout(function () { + getDigiTrustId(configParams); + }, 100 * (1 + resultHandler.retries++)); + } + return resultHandler.userIdCallback; + } else { // Third get the ID + resultHandler.executeIdRequest(configParams); + return resultHandler.userIdCallback; + } +} + +function initializeDigiTrust(config) { + utils.logInfo('Digitrust Init'); + var dt = window.DigiTrust; + if (dt && !dt.isClient && config != null) { + dt.initialize(config.init, config.callback); + } else if (dt == null) { + // Assume we are already on a delay and DigiTrust is not on page + initDigitrustFascade(config); + } +} + +var testHook = {}; + +/** + * Exposes the test hook object by attaching to the digitrustIdModule. + * This method is called in the unit tests to surface internals. + */ +function surfaceTestHook() { + digitrustIdModule['_testHook'] = testHook; +} + +testHook.initDigitrustFascade = initDigitrustFascade; + +/** @type {Submodule} */ +export const digiTrustIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'digitrust', + /** + * decode the stored id value for passing to bid requests + * @function + * @param {string} value + * @returns {{pubcid:string}} + */ + decode: function (idData) { + try { + return { 'digitrustid': idData }; + } catch (e) { + utils.logError('DigiTrust ID submodule decode error'); + } + }, + getId: getDigiTrustId, + _testInit: surfaceTestHook +}; + +attachIdSystem(digiTrustIdSubmodule); diff --git a/modules/digiTrustIdSystem.md b/modules/digiTrustIdSystem.md new file mode 100644 index 00000000000..8fe3c6652d9 --- /dev/null +++ b/modules/digiTrustIdSystem.md @@ -0,0 +1,154 @@ +## DigiTrust Universal Id Integration + +Setup +----- +The DigiTrust Id integration for Prebid may be used with or without the full +DigiTrust library. This is an optional module that must be used in conjunction +with the userId module. + +See the [Prebid Integration Guide for DigiTrust](https://github.com/digi-trust/dt-cdn/wiki/Prebid-Integration-for-DigiTrust-Id) +and the [DigiTrust wiki](https://github.com/digi-trust/dt-cdn/wiki) +for further instructions. + + +## Example Prebid Configuration for Digitrust Id +``` + pbjs.que.push(function() { + pbjs.setConfig({ + usersync: { + userIds: [{ + name: "digitrust", + params: { + init: { + member: 'example_member_id', + site: 'example_site_id' + }, + callback: function (digiTrustResult) { + // This callback method is optional + if (digiTrustResult.success) { + // Success in Digitrust init; + // 'DigiTrust Id (encrypted): ' + digiTrustResult.identity.id; + } + else { + // Digitrust init failed + } + } + }, + storage: { + type: "html5", + name: "pbjsdigitrust", + expires: 60 + } + }] + } + }); + pbjs.addAdUnits(adUnits); + pbjs.requestBids({ + bidsBackHandler: sendAdserverRequest + }); + }); + +``` + + +## Building Prebid with DigiTrust Support +Your Prebid build must include the modules for both **userId** and **digitrustIdLoader**. Follow the build instructions for Prebid as +explained in the top level README.md file of the Prebid source tree. + +ex: $ gulp build --modules=userId,digitrustIdLoader + +### Step by step Prebid build instructions for DigiTrust + +1. Download the Prebid source from [Prebid Git Repo](https://github.com/prebid/Prebid.js) +2. Set up your environment as outlined in the [Readme File](https://github.com/prebid/Prebid.js/blob/master/README.md#Build) +3. Execute the build command either with all modules or with the `userId` and `digitrustIdLoader` modules. + ``` + $ gulp build --modules=userId,digitrustIdLoader + ``` +4. (Optional) Concatenate the DigiTrust source code to the end of your `prebid.js` file for a single source distribution. +5. Upload the resulting source file to your CDN. + + +## Deploying Prebid with DigiTrust ID support +**Precondition:** You must be a DigiTrust member and have registered through the [DigiTrust Signup Process](http://www.digitru.st/signup/). +Your assigned publisher ID will be required in the configuration settings for all deployment scenarios. + +There are three supported approaches to deploying the Prebid-integrated DigiTrust package: + +* "Bare bones" deployment using only the integrated DigiTrust module code. +* Full DigiTrust with CDN referenced DigiTrust.js library. +* Full DigiTrust packaged with Prebid or site js. + +### Bare Bones Deployment + +This deployment results in the smallest Javascript package and is the simplest deployment. +It is appropriate for testing or deployments where simplicity is key. This approach +utilizes the REST API for ID generation. While there is less Javascript in use, +the user may experience more network requests than the scenarios that include the full +DigiTrust library. + +1. Build your Prebid package as above, skipping step 4. +2. Add the DigiTrust initializer section to your Prebid initialization object as below, + using your Member ID and Site ID. +3. Add a reference to your Prebid package and the initialization code on all pages you wish + to utilize Prebid with integrated DigiTrust ID. + + + + +### Full DigiTrust with CDN referenced DigiTrust library + +Both "Full DigiTrust" deployments will result in a larger initial Javascript payload. +The end user may experience fewer overall network requests as the encrypted and anonymous +DigiTrust ID can often be generated fully in client-side code. Utilizing the CDN reference +to the official DigiTrust distribution insures you will be running the latest version of the library. + +The Full DigiTrust deployment is designed to work with both new DigiTrust with Prebid deployments, and with +Prebid deployments by existing DigiTrust members. This allows you to migrate your code more slowly +without losing DigiTrust support in the process. + +1. Deploy your built copy of `prebid.js` to your CDN. +2. On each page reference both your `prebid.js` and a copy of the **DigiTrust** library. + This may either be a copy downloaded from the [DigiTrust CDN](https://cdn.digitru.st/prod/1/digitrust.min.js) to your CDN, + or directly referenced from the URL https://cdn.digitru.st/prod/1/digitrust.min.js. These may be added to the page in any order. +3. Add a configuration section for Prebid that includes the `usersync` settings and the `digitrust` settings. + +### Full DigiTrust packaged with Prebid + + +1. Deploy your built copy of `prebid.js` to your CDN. Be sure to perform *Step 4* of the build to concatenate or + integrate the full DigiTrust library code with your Prebid package. +2. On each page reference your `prebid.js` +3. Add a configuration section for Prebid that includes the `usersync` settings and the `digitrust` settings. + This code may also be appended to your Prebid package or placed in other initialization methods. + + + +## Parameter Descriptions for the `usersync` Configuration Section +The below parameters apply only to the DigiTrust ID integration. + +{: .table .table-bordered .table-striped } +| Param under usersync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | ID value for the DigiTrust module - `"digitrust"` | `"digitrust"` | +| params | Required | Object | Details for DigiTrust initialization. | | +| params.init | Required | Object | Initialization parameters, including the DigiTrust Publisher ID and Site ID. | | +| params.init.member | Required | String | DigiTrust Publisher Id | "A897dTzB" | +| params.init.site | Required | String | DigiTrust Site Id | "MM2123" | +| params.callback | Optional | Function | Callback method to fire after initialization of the DigiTrust framework. The argument indicates failure and success and the identity object upon success. | | +| 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. | `"pbjsdigitrust"` | +| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. Default is 30 for UnifiedId and 1825 for PubCommonID | `365` | +| value | Optional | Object | Used only if the page has a separate mechanism for storing the Unified 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 | `{"tdid": "D6885E90-2A7A-4E0F-87CB-7734ED1B99A3"}` | + + + +## Further Reading + ++ [DigiTrust Home Page](http://digitru.st) + ++ [DigiTrust integration guide](https://github.com/digi-trust/dt-cdn/wiki/Integration-Guide) + ++ [DigiTrust ID Encryption](https://github.com/digi-trust/dt-cdn/wiki/ID-encryption) + From 45e5be75e8db071c107118d1e9feccbb43c901f4 Mon Sep 17 00:00:00 2001 From: Malkov Mikhail Date: Wed, 5 Jun 2019 22:25:15 +0300 Subject: [PATCH 1264/1594] changed name company (#3875) * changed name company * changed name company in test --- ...leniumBidAdapter.js => nextMillenniumBidAdapter.js} | 2 +- ...leniumBidAdapter.md => nextMillenniumBidAdapter.md} | 6 +++--- ...dapter_spec.js => nextMillenniumBidAdapter_spec.js} | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) rename modules/{nextMilleniumBidAdapter.js => nextMillenniumBidAdapter.js} (98%) rename modules/{nextMilleniumBidAdapter.md => nextMillenniumBidAdapter.md} (76%) rename test/spec/modules/{nextMilleniumBidAdapter_spec.js => nextMillenniumBidAdapter_spec.js} (91%) diff --git a/modules/nextMilleniumBidAdapter.js b/modules/nextMillenniumBidAdapter.js similarity index 98% rename from modules/nextMilleniumBidAdapter.js rename to modules/nextMillenniumBidAdapter.js index 46f5a42b3c0..8093f6e8f7c 100644 --- a/modules/nextMilleniumBidAdapter.js +++ b/modules/nextMillenniumBidAdapter.js @@ -2,7 +2,7 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { BANNER } from '../src/mediaTypes'; -const BIDDER_CODE = 'nextMillenium'; +const BIDDER_CODE = 'nextMillennium'; const HOST = 'https://brainlyads.com'; const CURRENCY = 'USD'; const TIME_TO_LIVE = 360; diff --git a/modules/nextMilleniumBidAdapter.md b/modules/nextMillenniumBidAdapter.md similarity index 76% rename from modules/nextMilleniumBidAdapter.md rename to modules/nextMillenniumBidAdapter.md index a89e7e30822..c583969b4af 100644 --- a/modules/nextMilleniumBidAdapter.md +++ b/modules/nextMillenniumBidAdapter.md @@ -1,12 +1,12 @@ # Overview ``` -Module Name: NextMillenium Bid Adapter +Module Name: NextMillennium Bid Adapter Module Type: Bidder Adapter Maintainer: mikhail.ivanchenko@iageengineering.net ``` # Description -Module that connects to NextMillenium's server for bids. +Module that connects to NextMillennium's server for bids. Currently module supports only banner mediaType. # Test Parameters @@ -19,7 +19,7 @@ Currently module supports only banner mediaType. } }, bids: [{ - bidder: 'nextMillenium', + bidder: 'nextMillennium', params: { placement_id: -1 } diff --git a/test/spec/modules/nextMilleniumBidAdapter_spec.js b/test/spec/modules/nextMillenniumBidAdapter_spec.js similarity index 91% rename from test/spec/modules/nextMilleniumBidAdapter_spec.js rename to test/spec/modules/nextMillenniumBidAdapter_spec.js index 74c8ff5dfd9..087f06d7e8e 100644 --- a/test/spec/modules/nextMilleniumBidAdapter_spec.js +++ b/test/spec/modules/nextMillenniumBidAdapter_spec.js @@ -1,12 +1,12 @@ import { expect } from 'chai'; -import { spec } from 'modules/nextMilleniumBidAdapter'; +import { spec } from 'modules/nextMillenniumBidAdapter'; -describe('nextMilleniumBidAdapterTests', function() { +describe('nextMillenniumBidAdapterTests', function() { let bidRequestData = { bids: [ { bidId: 'transaction_1234', - bidder: 'nextMillenium', + bidder: 'nextMillennium', params: { placement_id: 12345 }, @@ -19,7 +19,7 @@ describe('nextMilleniumBidAdapterTests', function() { it('validate_pub_params', function() { expect( spec.isBidRequestValid({ - bidder: 'nextMillenium', + bidder: 'nextMillennium', params: { placement_id: 12345 } @@ -31,7 +31,7 @@ describe('nextMilleniumBidAdapterTests', function() { let bidRequestData = [ { bidId: 'bid1234', - bidder: 'nextMillenium', + bidder: 'nextMillennium', params: { placement_id: -1 }, sizes: [[300, 250]] } From 81932cd9e3d5c9c51518b658d0dc5cf540094883 Mon Sep 17 00:00:00 2001 From: Matt Quirion Date: Wed, 5 Jun 2019 16:06:43 -0400 Subject: [PATCH 1265/1594] New STAQ analytics adapter (#3772) * initial dev * fix staq adapter name * fix hello world staq call * get hello world working again * add user agent collection * fix some unite tests * Add STAQ Analytics Adapter doc * clean up hello world * fix tests to play nice with browserstack * fix around issues with browserstack and deep equals of objects * dump variable env testing since we can't mod user agent stuff in browserstack * Update STAQ adapter to stop using deprecated utils for referrer * remove package-lock.json changes via master rebase * improve call frequency for ref util * change ajax content type * adjust ajax request to not expect whitelisting * remove superflous commented-out code --- modules/staqAnalyticsAdapter.js | 429 ++++++++++++++++++ modules/staqAnalyticsAdapter.md | 23 + .../spec/modules/staqAnalyticsAdapter_spec.js | 301 ++++++++++++ 3 files changed, 753 insertions(+) create mode 100644 modules/staqAnalyticsAdapter.js create mode 100644 modules/staqAnalyticsAdapter.md create mode 100644 test/spec/modules/staqAnalyticsAdapter_spec.js diff --git a/modules/staqAnalyticsAdapter.js b/modules/staqAnalyticsAdapter.js new file mode 100644 index 00000000000..4d8b81b7be2 --- /dev/null +++ b/modules/staqAnalyticsAdapter.js @@ -0,0 +1,429 @@ +import adapter from '../src/AnalyticsAdapter'; +import CONSTANTS from '../src/constants.json'; +import adapterManager from '../src/adapterManager'; +import {getRefererInfo} from '../src/refererDetection'; +import {parse} from '../src/url'; +import * as utils from '../src/utils'; +import {ajax} from '../src/ajax'; + +const ANALYTICS_VERSION = '1.0.0'; +const DEFAULT_QUEUE_TIMEOUT = 4000; +const DEFAULT_HOST = 'tag.staq.com'; + +let staqAdapterRefWin; + +const STAQ_EVENTS = { + AUCTION_INIT: 'auctionInit', + BID_REQUEST: 'bidRequested', + BID_RESPONSE: 'bidResponse', + BID_WON: 'bidWon', + AUCTION_END: 'auctionEnd', + TIMEOUT: 'adapterTimedOut' +} + +function buildRequestTemplate(connId) { + const url = staqAdapterRefWin.referer; + const ref = staqAdapterRefWin.referer; + const topLocation = staqAdapterRefWin.referer; + + return { + ver: ANALYTICS_VERSION, + domain: topLocation.hostname, + path: topLocation.pathname, + userAgent: navigator.userAgent, + connId: connId, + env: { + screen: { + w: window.screen.width, + h: window.screen.height + }, + lang: navigator.language + }, + src: getUmtSource(url, ref) + } +} + +let analyticsAdapter = Object.assign(adapter({analyticsType: 'endpoint'}), + { + track({ eventType, args }) { + if (!analyticsAdapter.context) { + return; + } + let handler = null; + switch (eventType) { + case CONSTANTS.EVENTS.AUCTION_INIT: + if (analyticsAdapter.context.queue) { + analyticsAdapter.context.queue.init(); + } + handler = trackAuctionInit; + break; + case CONSTANTS.EVENTS.BID_REQUESTED: + handler = trackBidRequest; + break; + case CONSTANTS.EVENTS.BID_RESPONSE: + handler = trackBidResponse; + break; + case CONSTANTS.EVENTS.BID_WON: + handler = trackBidWon; + break; + case CONSTANTS.EVENTS.BID_TIMEOUT: + handler = trackBidTimeout; + break; + case CONSTANTS.EVENTS.AUCTION_END: + handler = trackAuctionEnd; + break; + } + if (handler) { + let events = handler(args); + if (analyticsAdapter.context.queue) { + analyticsAdapter.context.queue.push(events); + if (eventType === CONSTANTS.EVENTS.BID_WON) { + analyticsAdapter.context.queue.updateWithWins(events); + } + } + if (eventType === CONSTANTS.EVENTS.AUCTION_END) { + sendAll(); + } + } + } + }); + +analyticsAdapter.context = {}; + +analyticsAdapter.originEnableAnalytics = analyticsAdapter.enableAnalytics; + +analyticsAdapter.enableAnalytics = (config) => { + utils.logInfo('Enabling STAQ Adapter'); + staqAdapterRefWin = getRefererInfo(window); + if (!config.options.connId) { + utils.logError('ConnId is not defined. STAQ Analytics won\'t work'); + return; + } + if (!config.options.url) { + utils.logError('URL is not defined. STAQ Analytics won\'t work'); + return; + } + analyticsAdapter.context = { + host: config.options.host || DEFAULT_HOST, + url: config.options.url, + connectionId: config.options.connId, + requestTemplate: buildRequestTemplate(config.options.connId), + queue: new ExpiringQueue(sendAll, config.options.queueTimeout || DEFAULT_QUEUE_TIMEOUT) + }; + analyticsAdapter.originEnableAnalytics(config); +}; + +adapterManager.registerAnalyticsAdapter({ + adapter: analyticsAdapter, + code: 'staq' +}); + +export default analyticsAdapter; + +function sendAll() { + let events = analyticsAdapter.context.queue.popAll(); + if (events.length !== 0) { + let req = events.map(event => { + return Object.assign({}, event, analyticsAdapter.context.requestTemplate) + }); + analyticsAdapter.ajaxCall(JSON.stringify(req)); + } +} + +analyticsAdapter.ajaxCall = function ajaxCall(data) { + utils.logInfo('SENDING DATA: ' + data); + ajax(`//${analyticsAdapter.context.url}/prebid/${analyticsAdapter.context.connectionId}`, () => { + }, data, {contentType: 'text/plain'}); +}; + +function trackAuctionInit(args) { + analyticsAdapter.context.auctionTimeStart = Date.now(); + analyticsAdapter.context.auctionId = args.auctionId; + const event = createHbEvent(args.auctionId, undefined, STAQ_EVENTS.AUCTION_INIT); + return [event]; +} + +function trackBidRequest(args) { + return args.bids.map(bid => + createHbEvent(args.auctionId, args.bidderCode, STAQ_EVENTS.BID_REQUEST, bid.adUnitCode)); +} + +function trackBidResponse(args) { + const event = createHbEvent(args.auctionId, args.bidderCode, STAQ_EVENTS.BID_RESPONSE, + args.adUnitCode, args.cpm, args.timeToRespond / 1000, false, args); + return [event]; +} + +function trackBidWon(args) { + const event = createHbEvent(args.auctionId, args.bidderCode, STAQ_EVENTS.BID_WON, args.adUnitCode, args.cpm, undefined, true, args); + return [event]; +} + +function trackAuctionEnd(args) { + const event = createHbEvent(args.auctionId, undefined, STAQ_EVENTS.AUCTION_END, undefined, + undefined, (Date.now() - analyticsAdapter.context.auctionTimeStart) / 1000); + return [event]; +} + +function trackBidTimeout(args) { + return args.map(arg => + createHbEvent(arg.auctionId, arg.bidderCode, STAQ_EVENTS.TIMEOUT) + ); +} + +function createHbEvent(auctionId, adapter, event, adUnitCode = undefined, value = 0, time = 0, bidWon = undefined, eventArgs) { + let ev = { event: event }; + if (adapter) { + ev.adapter = adapter; + ev.bidderName = adapter; + } + if (adUnitCode) { + ev.adUnitCode = adUnitCode; + } + if (value) { + ev.cpm = value; + } + if (time) { + ev.timeToRespond = time; + } + if (typeof bidWon !== 'undefined') { + ev.bidWon = bidWon; + } else if (event === 'bidResponse') { + ev.bidWon = false; + } + ev.auctionId = auctionId; + + if (eventArgs) { + if (STAQ_EVENTS.BID_RESPONSE == event || STAQ_EVENTS.BID_WON == event) { + ev.width = eventArgs.width; + ev.height = eventArgs.height; + + ev.adId = eventArgs.adId; + } + } + + return ev; +} + +const UTM_TAGS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', + 'utm_c1', 'utm_c2', 'utm_c3', 'utm_c4', 'utm_c5']; +const STAQ_PREBID_KEY = 'staq_analytics'; +const DIRECT = '(direct)'; +const REFERRAL = '(referral)'; +const ORGANIC = '(organic)'; + +export let storage = { + getItem: (name) => { + return localStorage.getItem(name); + }, + setItem: (name, value) => { + localStorage.setItem(name, value); + } +}; + +export function getUmtSource(pageUrl, referrer) { + let prevUtm = getPreviousTrafficSource(); + let currUtm = getCurrentTrafficSource(pageUrl, referrer); + let [updated, actual] = chooseActualUtm(prevUtm, currUtm); + if (updated) { + storeUtm(actual); + } + return actual; + + function getPreviousTrafficSource() { + let val = storage.getItem(STAQ_PREBID_KEY); + if (!val) { + return getDirect(); + } + return JSON.parse(val); + } + + function getCurrentTrafficSource(pageUrl, referrer) { + var source = getUTM(pageUrl); + if (source) { + return source; + } + if (referrer) { + let se = getSearchEngine(referrer); + if (se) { + return asUtm(se, ORGANIC, ORGANIC); + } + let parsedUrl = parse(pageUrl); + let [refHost, refPath] = getReferrer(referrer); + if (refHost && refHost !== parsedUrl.hostname) { + return asUtm(refHost, REFERRAL, REFERRAL, '', refPath); + } + } + return getDirect(); + } + + function getSearchEngine(pageUrl) { + let engines = { + 'google': /^https?\:\/\/(?:www\.)?(?:google\.(?:com?\.)?(?:com|cat|[a-z]{2})|g.cn)\//i, + 'yandex': /^https?\:\/\/(?:www\.)?ya(?:ndex\.(?:com|net)?\.?(?:asia|mobi|org|[a-z]{2})?|\.ru)\//i, + 'bing': /^https?\:\/\/(?:www\.)?bing\.com\//i, + 'duckduckgo': /^https?\:\/\/(?:www\.)?duckduckgo\.com\//i, + 'ask': /^https?\:\/\/(?:www\.)?ask\.com\//i, + 'yahoo': /^https?\:\/\/(?:[-a-z]+\.)?(?:search\.)?yahoo\.com\//i + }; + + for (let engine in engines) { + if (engines.hasOwnProperty(engine) && engines[engine].test(pageUrl)) { + return engine; + } + } + } + + function getReferrer(referrer) { + let ref = parse(referrer); + return [ref.hostname, ref.pathname]; + } + + function getUTM(pageUrl) { + let urlParameters = parse(pageUrl).search; + if (!urlParameters['utm_campaign'] || !urlParameters['utm_source']) { + return; + } + let utmArgs = []; + utils._each(UTM_TAGS, (utmTagName) => { + let utmValue = urlParameters[utmTagName] || ''; + utmArgs.push(utmValue); + }); + return asUtm.apply(this, utmArgs); + } + + function getDirect() { + return asUtm(DIRECT, DIRECT, DIRECT); + } + + function storeUtm(utm) { + let val = JSON.stringify(utm); + storage.setItem(STAQ_PREBID_KEY, val); + } + + function asUtm(source, medium, campaign, term = '', content = '', c1 = '', c2 = '', c3 = '', c4 = '', c5 = '') { + let result = { + source: source, + medium: medium, + campaign: campaign + }; + if (term) { + result.term = term; + } + if (content) { + result.content = content; + } + if (c1) { + result.c1 = c1; + } + if (c2) { + result.c2 = c2; + } + if (c3) { + result.c3 = c3; + } + if (c4) { + result.c4 = c4; + } + if (c5) { + result.c5 = c5; + } + return result; + } + + function chooseActualUtm(prev, curr) { + if (ord(prev) < ord(curr)) { + return [true, curr]; + } if (ord(prev) > ord(curr)) { + return [false, prev]; + } else { + if (prev.campaign === REFERRAL && prev.content !== curr.content) { + return [true, curr]; + } else if (prev.campaign === ORGANIC && prev.source !== curr.source) { + return [true, curr]; + } else if (isCampaignTraffic(prev) && (prev.campaign !== curr.campaign || prev.source !== curr.source)) { + return [true, curr]; + } + } + return [false, prev]; + } + + function ord(utm) { + switch (utm.campaign) { + case DIRECT: + return 0; + case ORGANIC: + return 1; + case REFERRAL: + return 2; + default: + return 3; + } + } + + function isCampaignTraffic(utm) { + return [DIRECT, REFERRAL, ORGANIC].indexOf(utm.campaign) === -1; + } +} + +/** + * Expiring queue implementation. Fires callback on elapsed timeout since last last update or creation. + * @param callback + * @param ttl + * @constructor + */ +export function ExpiringQueue(callback, ttl) { + let queue = []; + let timeoutId; + + this.push = (event) => { + if (event instanceof Array) { + queue.push.apply(queue, event); + } else { + queue.push(event); + } + reset(); + }; + + this.updateWithWins = (winEvents) => { + winEvents.forEach(winEvent => { + queue.forEach(prevEvent => { + if (prevEvent.event === 'bidResponse' && + prevEvent.auctionId == winEvent.auctionId && + prevEvent.adUnitCode == winEvent.adUnitCode && + prevEvent.adId == winEvent.adId && + prevEvent.adapter == winEvent.adapter) { + prevEvent.bidWon = true; + } + }); + }); + } + + this.popAll = () => { + let result = queue; + queue = []; + reset(); + return result; + }; + + /** + * For test/debug purposes only + * @return {Array} + */ + this.peekAll = () => { + return queue; + }; + + this.init = reset; + + function reset() { + if (timeoutId) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(() => { + if (queue.length) { + callback(); + } + }, ttl); + } +} diff --git a/modules/staqAnalyticsAdapter.md b/modules/staqAnalyticsAdapter.md new file mode 100644 index 00000000000..c3d2e9ce3a8 --- /dev/null +++ b/modules/staqAnalyticsAdapter.md @@ -0,0 +1,23 @@ +# Overview +Module Name: STAQ Analytics Adapter + +Module Type: Analytics Adapter + +Maintainer: dev@staq.com + +# Description + +Analytics adapter for STAQ. Contact support@staq.com for information. + +# Test Parameters + +``` +{ + provider: 'staq', + options: { + host: , // HOST URL of site. Optional. Only required for whitelisting. + url: 'localhost:3000', // REQUIRED host URL for delivery of information to STAQ + connId: '5678' // REQUIRED STAQ connection ID + } +} +``` diff --git a/test/spec/modules/staqAnalyticsAdapter_spec.js b/test/spec/modules/staqAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..33c85d11431 --- /dev/null +++ b/test/spec/modules/staqAnalyticsAdapter_spec.js @@ -0,0 +1,301 @@ +import analyticsAdapter, {ExpiringQueue, getUmtSource, storage} from 'modules/staqAnalyticsAdapter'; +import {expect} from 'chai'; +import adapterManager from 'src/adapterManager'; +import CONSTANTS from 'src/constants.json'; + +const events = require('../../../src/events'); + +const DIRECT = { + source: '(direct)', + medium: '(direct)', + campaign: '(direct)' +}; +const REFERRER = { + source: 'lander.com', + medium: '(referral)', + campaign: '(referral)', + content: '/lander.html' +}; +const GOOGLE_ORGANIC = { + source: 'google', + medium: '(organic)', + campaign: '(organic)' +}; +const CAMPAIGN = { + source: 'adkernel', + medium: 'email', + campaign: 'new_campaign', + c1: '1', + c2: '2', + c3: '3', + c4: '4', + c5: '5' + +}; +describe('', function () { + let sandbox; + + before(function () { + sandbox = sinon.sandbox.create(); + }); + + after(function () { + sandbox.restore(); + analyticsAdapter.disableAnalytics(); + }); + + describe('UTM source parser', function () { + let stubSetItem; + let stubGetItem; + + before(function () { + stubSetItem = sandbox.stub(storage, 'setItem'); + stubGetItem = sandbox.stub(storage, 'getItem'); + }); + + afterEach(function () { + sandbox.reset(); + }); + + it('should parse first direct visit as (direct)', function () { + stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); + stubSetItem.returns(undefined); + let source = getUmtSource('http://example.com'); + expect(source).to.be.eql(DIRECT); + }); + + it('should parse visit from google as organic', function () { + stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); + stubSetItem.returns(undefined); + let source = getUmtSource('http://example.com', 'https://www.google.com/search?q=pikachu'); + expect(source).to.be.eql(GOOGLE_ORGANIC); + }); + + it('should parse referral visit', function () { + stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); + stubSetItem.returns(undefined); + let source = getUmtSource('http://example.com', 'http://lander.com/lander.html'); + expect(source).to.be.eql(REFERRER); + }); + + it('should parse referral visit from same domain as direct', function () { + stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); + stubSetItem.returns(undefined); + let source = getUmtSource('http://lander.com/news.html', 'http://lander.com/lander.html'); + expect(source).to.be.eql(DIRECT); + }); + + it('should parse campaign visit', function () { + stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); + stubSetItem.returns(undefined); + let source = getUmtSource('http://lander.com/index.html?utm_campaign=new_campaign&utm_source=adkernel&utm_medium=email&utm_c1=1&utm_c2=2&utm_c3=3&utm_c4=4&utm_c5=5'); + expect(source).to.be.eql(CAMPAIGN); + }); + }); + + describe('ExpiringQueue', function () { + let timer; + before(function () { + timer = sandbox.useFakeTimers(0); + }); + after(function () { + timer.restore(); + }); + + it('should notify after timeout period', (done) => { + let queue = new ExpiringQueue(() => { + let elements = queue.popAll(); + expect(elements).to.be.eql([1, 2, 3, 4]); + elements = queue.popAll(); + expect(elements).to.have.lengthOf(0); + expect(Date.now()).to.be.equal(200); + done(); + }, 100); + + queue.push(1); + setTimeout(() => { + queue.push([2, 3]); + timer.tick(50); + }, 50); + setTimeout(() => { + queue.push([4]); + timer.tick(100); + }, 100); + timer.tick(50); + }); + }); + + const REQUEST = { + bidderCode: 'AppNexus', + bidderName: 'AppNexus', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + bidderRequestId: '1a6fc81528d0f6', + bids: [{ + bidder: 'AppNexus', + params: {}, + adUnitCode: 'container-1', + transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', + sizes: [[300, 250]], + bidId: '208750227436c1', + bidderRequestId: '1a6fc81528d0f6', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' + }], + auctionStart: 1509369418387, + timeout: 3000, + start: 1509369418389 + }; + + const RESPONSE = { + bidderCode: 'AppNexus', + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '208750227436c1', + mediaType: 'banner', + cpm: 0.015, + ad: '', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + responseTimestamp: 1509369418832, + requestTimestamp: 1509369418389, + bidder: 'AppNexus', + adUnitCode: 'container-1', + timeToRespond: 443, + size: '300x250' + }; + + const bidTimeoutArgsV1 = [{ + bidId: '2baa51527bd015', + bidderCode: 'AppNexus', + adUnitCode: 'container-1', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + }, + { + bidId: '6fe3b4c2c23092', + bidderCode: 'AppNexus', + adUnitCode: 'container-2', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + }]; + + describe('Analytics adapter', function () { + let ajaxStub; + let timer; + + before(function () { + ajaxStub = sandbox.stub(analyticsAdapter, 'ajaxCall'); + timer = sandbox.useFakeTimers(0); + }); + + beforeEach(function () { + sandbox.stub(events, 'getEvents').callsFake(() => { + return [] + }); + }); + + afterEach(function () { + events.getEvents.restore(); + }); + + it('should be configurable', function () { + adapterManager.registerAnalyticsAdapter({ + code: 'staq', + adapter: analyticsAdapter + }); + + adapterManager.enableAnalytics({ + provider: 'staq', + options: { + connId: 777, + queueTimeout: 1000, + url: 'http://localhost/prebid' + } + }); + + expect(analyticsAdapter.context).to.have.property('connectionId', 777); + }); + + it('should handle auction init event', function () { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {config: {}, timeout: 3000}); + const ev = analyticsAdapter.context.queue.peekAll(); + expect(ev).to.have.length(1); + expect(ev[0]).to.be.eql({event: 'auctionInit', auctionId: undefined}); + }); + + it('should handle bid request event', function () { + events.emit(CONSTANTS.EVENTS.BID_REQUESTED, REQUEST); + const ev = analyticsAdapter.context.queue.peekAll(); + expect(ev).to.have.length(2); + expect(ev[1]).to.be.eql({ + adUnitCode: 'container-1', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + event: 'bidRequested', + adapter: 'AppNexus', + bidderName: 'AppNexus' + }); + }); + + it('should handle bid response event', function () { + events.emit(CONSTANTS.EVENTS.BID_RESPONSE, RESPONSE); + const ev = analyticsAdapter.context.queue.peekAll(); + expect(ev).to.have.length(3); + expect(ev[2]).to.be.eql({ + adId: '208750227436c1', + event: 'bidResponse', + adapter: 'AppNexus', + bidderName: 'AppNexus', + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + adUnitCode: 'container-1', + cpm: 0.015, + timeToRespond: 0.443, + height: 250, + width: 300, + bidWon: false, + }); + }); + + it('should handle timeouts properly', function() { + events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, bidTimeoutArgsV1); + + const ev = analyticsAdapter.context.queue.peekAll(); + expect(ev).to.have.length(5); // remember, we added 2 timeout events + expect(ev[3]).to.be.eql({ + adapter: 'AppNexus', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f', + bidderName: 'AppNexus', + event: 'adapterTimedOut' + }) + }); + + it('should handle winning bid', function () { + events.emit(CONSTANTS.EVENTS.BID_WON, RESPONSE); + const ev = analyticsAdapter.context.queue.peekAll(); + expect(ev).to.have.length(6); + expect(ev[5]).to.be.eql({ + auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f', + adId: '208750227436c1', + event: 'bidWon', + adapter: 'AppNexus', + bidderName: 'AppNexus', + adUnitCode: 'container-1', + cpm: 0.015, + height: 250, + width: 300, + bidWon: true, + }); + }); + + it('should handle auction end event', function () { + timer.tick(447); + events.emit(CONSTANTS.EVENTS.AUCTION_END, RESPONSE); + let ev = analyticsAdapter.context.queue.peekAll(); + expect(ev).to.have.length(0); + expect(ajaxStub.calledOnce).to.be.equal(true); + let firstCallArgs0 = ajaxStub.firstCall.args[0]; + ev = JSON.parse(firstCallArgs0); + // console.log('AUCTION END EVENT SHAPE ' + JSON.stringify(ev)); + const ev6 = ev[6]; + expect(ev6.connId).to.be.eql(777); + expect(ev6.auctionId).to.be.eql('5018eb39-f900-4370-b71e-3bb5b48d324f'); + expect(ev6.event).to.be.eql('auctionEnd'); + }); + }); +}); From 8b6fbd798cabf51aa6ee7636f8762ee02e42ae19 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 5 Jun 2019 16:57:27 -0400 Subject: [PATCH 1266/1594] Prebid 2.18.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e84e1698434..299cc8f8620 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.18.0-pre", + "version": "2.18.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From a40835cbe7b382d9a84abadfdd67ad6642503d6e Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 5 Jun 2019 17:10:29 -0400 Subject: [PATCH 1267/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 299cc8f8620..468b16c0ebb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.18.0", + "version": "2.19.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 5a4b25ac80e912a41fe9c4e6ab372e434e7f9534 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Fri, 7 Jun 2019 07:27:55 -0700 Subject: [PATCH 1268/1594] removed the non-working setting on table (#3890) --- modules/digiTrustIdSystem.md | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/digiTrustIdSystem.md b/modules/digiTrustIdSystem.md index 8fe3c6652d9..6ddbad4aea4 100644 --- a/modules/digiTrustIdSystem.md +++ b/modules/digiTrustIdSystem.md @@ -127,7 +127,6 @@ without losing DigiTrust support in the process. ## Parameter Descriptions for the `usersync` Configuration Section The below parameters apply only to the DigiTrust ID integration. -{: .table .table-bordered .table-striped } | Param under usersync.userIds[] | Scope | Type | Description | Example | | --- | --- | --- | --- | --- | | name | Required | String | ID value for the DigiTrust module - `"digitrust"` | `"digitrust"` | From 3cb73424b5b815ffa2d3cc43773f8397a53372fc Mon Sep 17 00:00:00 2001 From: kd-appier <45807878+kd-appier@users.noreply.github.com> Date: Tue, 11 Jun 2019 00:08:41 +0800 Subject: [PATCH 1269/1594] Implement Appier Analytics Adapter. (#3871) --- modules/appierAnalyticsAdapter.js | 244 ++++++ modules/appierAnalyticsAdapter.md | 23 + .../modules/appierAnalyticsAdapter_spec.js | 709 ++++++++++++++++++ 3 files changed, 976 insertions(+) create mode 100644 modules/appierAnalyticsAdapter.js create mode 100644 modules/appierAnalyticsAdapter.md create mode 100644 test/spec/modules/appierAnalyticsAdapter_spec.js diff --git a/modules/appierAnalyticsAdapter.js b/modules/appierAnalyticsAdapter.js new file mode 100644 index 00000000000..76811b598e0 --- /dev/null +++ b/modules/appierAnalyticsAdapter.js @@ -0,0 +1,244 @@ +import {ajax} from '../src/ajax'; +import adapter from '../src/AnalyticsAdapter'; +import CONSTANTS from '../src/constants.json'; +import adapterManager from '../src/adapterManager'; +import {logError, logInfo, deepClone} from '../src/utils'; + +const analyticsType = 'endpoint'; + +export const ANALYTICS_VERSION = '1.0.0'; + +const DEFAULT_SERVER = 'https://prebid-analytics.c.appier.net/v1'; + +const { + EVENTS: { + AUCTION_END, + BID_WON, + BID_TIMEOUT + } +} = CONSTANTS; + +export const BIDDER_STATUS = { + BID: 'bid', + NO_BID: 'noBid', + BID_WON: 'bidWon', + TIMEOUT: 'timeout' +}; + +export const getCpmInUsd = function (bid) { + if (bid.currency === 'USD') { + return bid.cpm; + } else { + return bid.getCpmInNewCurrency('USD'); + } +}; + +const analyticsOptions = {}; + +export const parseBidderCode = function (bid) { + let bidderCode = bid.bidderCode || bid.bidder; + return bidderCode.toLowerCase(); +}; + +export const parseAdUnitCode = function (bidResponse) { + return bidResponse.adUnitCode.toLowerCase(); +}; + +export const appierAnalyticsAdapter = Object.assign(adapter({DEFAULT_SERVER, analyticsType}), { + + cachedAuctions: {}, + + initConfig(config) { + /** + * Required option: affiliateId + * Required option: configId + * + * Optional option: server + * Optional option: sampling + * Optional option: adSampling + * Optional option: autoPick + * Optional option: predictionId + * @type {boolean} + */ + analyticsOptions.options = deepClone(config.options); + if (typeof config.options.affiliateId !== 'string' || config.options.affiliateId.length < 1) { + logError('"options.affiliateId" is required.'); + return false; + } + if (typeof config.options.configId !== 'string' || config.options.configId.length < 1) { + logError('"options.configId" is required.'); + return false; + } + + analyticsOptions.affiliateId = config.options.affiliateId; + analyticsOptions.configId = config.options.configId; + analyticsOptions.server = config.options.server || DEFAULT_SERVER; + + analyticsOptions.sampled = true; + if (typeof config.options.sampling === 'number') { + analyticsOptions.sampled = Math.random() < parseFloat(config.options.sampling); + } + analyticsOptions.adSampled = false; + if (typeof config.options.adSampling === 'number') { + analyticsOptions.adSampled = Math.random() < parseFloat(config.options.adSampling); + } + analyticsOptions.autoPick = config.options.autoPick || null; + analyticsOptions.predictionId = config.options.predictionId || null; + + return true; + }, + sendEventMessage(endPoint, data) { + logInfo(`AJAX: ${endPoint}: ` + JSON.stringify(data)); + + ajax(`${analyticsOptions.server}/${endPoint}`, null, JSON.stringify(data), { + contentType: 'application/json', + withCredentials: true + }); + }, + createCommonMessage(auctionId) { + return { + version: ANALYTICS_VERSION, + auctionId: auctionId, + affiliateId: analyticsOptions.affiliateId, + configId: analyticsOptions.configId, + referrer: window.location.href, + sampling: analyticsOptions.options.sampling, + adSampling: analyticsOptions.options.adSampling, + prebid: '$prebid.version$', + autoPick: analyticsOptions.autoPick, + predictionId: analyticsOptions.predictionId, + adUnits: {}, + }; + }, + serializeBidResponse(bid, status) { + const result = { + prebidWon: (status === BIDDER_STATUS.BID_WON), + isTimeout: (status === BIDDER_STATUS.TIMEOUT), + status: status, + }; + if (status === BIDDER_STATUS.BID || status === BIDDER_STATUS.BID_WON) { + Object.assign(result, { + time: bid.timeToRespond, + cpm: bid.cpm, + currency: bid.currency, + originalCpm: bid.originalCpm || bid.cpm, + cpmUsd: getCpmInUsd(bid), + originalCurrency: bid.originalCurrency || bid.currency, + }); + } + return result; + }, + addBidResponseToMessage(message, bid, status) { + const adUnitCode = parseAdUnitCode(bid); + message.adUnits[adUnitCode] = message.adUnits[adUnitCode] || {}; + const bidder = parseBidderCode(bid); + const bidResponse = this.serializeBidResponse(bid, status); + message.adUnits[adUnitCode][bidder] = bidResponse; + }, + createBidMessage(auctionEndArgs, winningBids, timeoutBids) { + const {auctionId, timestamp, timeout, auctionEnd, adUnitCodes, bidsReceived, noBids} = auctionEndArgs; + const message = this.createCommonMessage(auctionId); + + message.auctionElapsed = (auctionEnd - timestamp); + message.timeout = timeout; + + adUnitCodes.forEach((adUnitCode) => { + message.adUnits[adUnitCode] = {}; + }); + + // We handled noBids first because when currency conversion is enabled, a bid with a foreign currency + // will be set to NO_BID initially, and then set to BID after the currency rate json file is fully loaded. + // In this situation, the bid exists in both noBids and bids arrays. + noBids.forEach(bid => this.addBidResponseToMessage(message, bid, BIDDER_STATUS.NO_BID)); + + // This array may contain some timeout bids (responses come back after auction timeout) + bidsReceived.forEach(bid => this.addBidResponseToMessage(message, bid, BIDDER_STATUS.BID)); + + // We handle timeout after bids since it's possible that a bid has a response, but the response comes back + // after auction end. In this case, the bid exists in both bidsReceived and timeoutBids arrays. + timeoutBids.forEach(bid => this.addBidResponseToMessage(message, bid, BIDDER_STATUS.TIMEOUT)); + + // mark the winning bids with prebidWon = true + winningBids.forEach(bid => { + const adUnitCode = parseAdUnitCode(bid); + const bidder = parseBidderCode(bid); + message.adUnits[adUnitCode][bidder].prebidWon = true; + }); + return message; + }, + createImpressionMessage(bid) { + const message = this.createCommonMessage(bid.auctionId); + this.addBidResponseToMessage(message, bid, BIDDER_STATUS.BID_WON); + return message; + }, + createCreativeMessage(auctionId, bids) { + const message = this.createCommonMessage(auctionId); + bids.forEach((bid) => { + const adUnitCode = parseAdUnitCode(bid); + const bidder = parseBidderCode(bid); + message.adUnits[adUnitCode] = message.adUnits[adUnitCode] || {}; + message.adUnits[adUnitCode][bidder] = {ad: bid.ad}; + }); + return message; + }, + getCachedAuction(auctionId) { + this.cachedAuctions[auctionId] = this.cachedAuctions[auctionId] || { + timeoutBids: [], + }; + return this.cachedAuctions[auctionId]; + }, + handleAuctionEnd(auctionEndArgs) { + const cachedAuction = this.getCachedAuction(auctionEndArgs.auctionId); + const highestCpmBids = pbjs.getHighestCpmBids(); + this.sendEventMessage('bid', + this.createBidMessage(auctionEndArgs, highestCpmBids, cachedAuction.timeoutBids) + ); + if (analyticsOptions.adSampled) { + this.sendEventMessage('cr', + this.createCreativeMessage(auctionEndArgs.auctionId, auctionEndArgs.bidsReceived) + ); + } + }, + handleBidTimeout(timeoutBids) { + timeoutBids.forEach((bid) => { + const cachedAuction = this.getCachedAuction(bid.auctionId); + cachedAuction.timeoutBids.push(bid); + }); + }, + handleBidWon(bidWonArgs) { + this.sendEventMessage('imp', this.createImpressionMessage(bidWonArgs)); + }, + track({eventType, args}) { + if (analyticsOptions.sampled) { + switch (eventType) { + case BID_WON: + this.handleBidWon(args); + break; + case BID_TIMEOUT: + this.handleBidTimeout(args); + break; + case AUCTION_END: + this.handleAuctionEnd(args); + break; + } + } + }, + getAnalyticsOptions() { + return analyticsOptions; + }, +}); + +// save the base class function +appierAnalyticsAdapter.originEnableAnalytics = appierAnalyticsAdapter.enableAnalytics; + +// override enableAnalytics so we can get access to the config passed in from the page +appierAnalyticsAdapter.enableAnalytics = function (config) { + if (this.initConfig(config)) { + appierAnalyticsAdapter.originEnableAnalytics(config); // call the base class function + } +}; + +adapterManager.registerAnalyticsAdapter({ + adapter: appierAnalyticsAdapter, + code: 'appierAnalytics' +}); diff --git a/modules/appierAnalyticsAdapter.md b/modules/appierAnalyticsAdapter.md new file mode 100644 index 00000000000..09f0676d054 --- /dev/null +++ b/modules/appierAnalyticsAdapter.md @@ -0,0 +1,23 @@ +# Overview + +Module Name: Appier Analytics Adapter +Module Type: Analytics Adapter +Maintainer: apn-dev@appier.com + +# Description + +Analytics adapter for Appier + +# Test Parameters + +``` +{ + provider: 'appierAnalytics', + options: { + 'configId': 'YOUR_CONFIG_ID', + 'affiliateId': 'YOUR_AFFILIATE_ID', + } +} +``` + +PS. [Prebid currency module](http://prebid.org/dev-docs/modules/currency.html) is required, please make sure your prebid code contains currency module code. diff --git a/test/spec/modules/appierAnalyticsAdapter_spec.js b/test/spec/modules/appierAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..07b9796a4cb --- /dev/null +++ b/test/spec/modules/appierAnalyticsAdapter_spec.js @@ -0,0 +1,709 @@ +import { + appierAnalyticsAdapter, getCpmInUsd, parseBidderCode, parseAdUnitCode, + ANALYTICS_VERSION, BIDDER_STATUS +} from 'modules/appierAnalyticsAdapter'; +import {expect} from 'chai'; +const events = require('src/events'); +const constants = require('src/constants.json'); + +const affiliateId = 'WhctHaViHtI'; +const configId = 'd9cc9a9be9b240eda17cf1c9a8a4b29c'; +const serverUrl = 'https://analytics.server.url/v1'; +const autoPick = 'none'; +const predictionId = '2a91ca5de54a4a2e89950af439f7a27f'; +const auctionId = 'b0b39610-b941-4659-a87c-de9f62d3e13e'; + +describe('Appier Prebid AnalyticsAdapter Testing', function () { + describe('event tracking and message cache manager', function () { + let xhr; + + beforeEach(function () { + const configOptions = { + affiliateId: affiliateId, + configId: configId, + server: serverUrl, + autoPick: autoPick, + predictionId: predictionId, + sampling: 0, + adSampling: 1, + }; + + appierAnalyticsAdapter.enableAnalytics({ + provider: 'appierAnalytics', + options: configOptions + }); + xhr = sinon.useFakeXMLHttpRequest(); + }); + + afterEach(function () { + appierAnalyticsAdapter.disableAnalytics(); + xhr.restore(); + }); + + describe('#getCpmInUsd()', function() { + it('should get bid cpm as currency is USD', function() { + const receivedBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_1', + bidder: 'appier', + bidderCode: 'APPIER', + requestId: 'a1b2c3d4', + timeToRespond: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + ad: 'fake ad1' + }, + ] + const result = getCpmInUsd(receivedBids[0]); + expect(result).to.equal(0.1); + }); + }); + + describe('#parseBidderCode()', function() { + it('should get lower case bidder code from bidderCode field value', function() { + const receivedBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_1', + bidder: 'appier', + bidderCode: 'APPIER', + requestId: 'a1b2c3d4', + timeToRespond: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + ad: 'fake ad1' + }, + ]; + const result = parseBidderCode(receivedBids[0]); + expect(result).to.equal('appier'); + }); + it('should get lower case bidder code from bidder field value as bidderCode field is missing', function() { + const receivedBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_1', + bidder: 'APPIER', + bidderCode: '', + requestId: 'a1b2c3d4', + timeToRespond: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + ad: 'fake ad1' + }, + ]; + const result = parseBidderCode(receivedBids[0]); + expect(result).to.equal('appier'); + }); + }); + + describe('#parseAdUnitCode()', function() { + it('should get lower case adUnit code from adUnitCode field value', function() { + const receivedBids = [ + { + auctionId: auctionId, + adUnitCode: 'ADUNIT', + bidder: 'appier', + bidderCode: 'APPIER', + requestId: 'a1b2c3d4', + timeToRespond: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + ad: 'fake ad1' + }, + ]; + const result = parseAdUnitCode(receivedBids[0]); + expect(result).to.equal('adunit'); + }); + }); + + describe('#getCachedAuction()', function() { + const existing = {timeoutBids: [{}]}; + appierAnalyticsAdapter.cachedAuctions['test_auction_id'] = existing; + + it('should get the existing cached object if it exists', function() { + const result = appierAnalyticsAdapter.getCachedAuction('test_auction_id'); + + expect(result).to.equal(existing); + }); + + it('should create a new object and store it in the cache on cache miss', function() { + const result = appierAnalyticsAdapter.getCachedAuction('no_such_id'); + + expect(result).to.deep.include({ + timeoutBids: [], + }); + }); + }); + + describe('when formatting JSON payload sent to backend', function() { + const receivedBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_1', + bidder: 'appier', + bidderCode: 'appier', + requestId: 'a1b2c3d4', + timeToRespond: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + ad: 'fake ad1' + }, + { + auctionId: auctionId, + adUnitCode: 'adunit_1', + bidder: 'reippa', + bidderCode: 'reippa', + requestId: 'b2c3d4e5', + timeToRespond: 100, + cpm: 0.08, + currency: 'USD', + originalCpm: 0.08, + originalCurrency: 'USD', + ad: 'fake ad2' + }, + { + auctionId: auctionId, + adUnitCode: 'adunit_2', + bidder: 'appier', + bidderCode: 'appier', + requestId: 'c3d4e5f6', + timeToRespond: 120, + cpm: 0.09, + currency: 'USD', + originalCpm: 0.09, + originalCurrency: 'USD', + ad: 'fake ad3' + }, + ]; + const highestCpmBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_1', + bidder: 'appier', + bidderCode: 'appier', + // No requestId + timeToRespond: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + ad: 'fake ad1' + } + ]; + const noBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_2', + bidder: 'appier', + bidderCode: 'appier', + bidId: 'a1b2c3d4', + } + ]; + const timeoutBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_2', + bidder: 'reippa', + bidderCode: 'reippa', + bidId: '00123d4c', + } + ]; + const withoutOriginalCpmBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_2', + bidder: 'appier', + bidderCode: 'appier', + requestId: 'c3d4e5f6', + timeToRespond: 120, + cpm: 0.29, + currency: 'USD', + originalCpm: '', + originalCurrency: 'USD', + ad: 'fake ad3' + }, + ]; + const withoutOriginalCurrencyBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_2', + bidder: 'appier', + bidderCode: 'appier', + requestId: 'c3d4e5f6', + timeToRespond: 120, + cpm: 0.09, + currency: 'USD', + originalCpm: 0.09, + originalCurrency: '', + ad: 'fake ad3' + }, + ]; + function assertHavingRequiredMessageFields(message) { + expect(message).to.include({ + version: ANALYTICS_VERSION, + auctionId: auctionId, + affiliateId: affiliateId, + configId: configId, + // referrer: window.location.href, + sampling: 0, + adSampling: 1, + prebid: '$prebid.version$', + // autoPick: 'manual', + }); + } + + describe('#createCommonMessage', function() { + it('should correctly serialize some common fields', function() { + const message = appierAnalyticsAdapter.createCommonMessage(auctionId); + + assertHavingRequiredMessageFields(message); + }); + }); + + describe('#serializeBidResponse', function() { + it('should handle BID properly and serialize bid price related fields', function() { + const result = appierAnalyticsAdapter.serializeBidResponse(receivedBids[0], BIDDER_STATUS.BID); + + expect(result).to.include({ + prebidWon: false, + isTimeout: false, + status: BIDDER_STATUS.BID, + time: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + cpmUsd: 0.1, + }); + }); + + it('should handle NO_BID properly and set status to noBid', function() { + const result = appierAnalyticsAdapter.serializeBidResponse(noBids[0], BIDDER_STATUS.NO_BID); + + expect(result).to.include({ + prebidWon: false, + isTimeout: false, + status: BIDDER_STATUS.NO_BID, + }); + }); + + it('should handle BID_WON properly and serialize bid price related fields', function() { + const result = appierAnalyticsAdapter.serializeBidResponse(receivedBids[0], BIDDER_STATUS.BID_WON); + + expect(result).to.include({ + prebidWon: true, + isTimeout: false, + status: BIDDER_STATUS.BID_WON, + time: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + cpmUsd: 0.1, + }); + }); + + it('should handle TIMEOUT properly and set status to timeout and isTimeout to true', function() { + const result = appierAnalyticsAdapter.serializeBidResponse(noBids[0], BIDDER_STATUS.TIMEOUT); + + expect(result).to.include({ + prebidWon: false, + isTimeout: true, + status: BIDDER_STATUS.TIMEOUT, + }); + }); + + it('should handle BID_WON properly and fill originalCpm field with cpm in missing originalCpm case', function() { + const result = appierAnalyticsAdapter.serializeBidResponse(withoutOriginalCpmBids[0], BIDDER_STATUS.BID_WON); + + expect(result).to.include({ + prebidWon: true, + isTimeout: false, + status: BIDDER_STATUS.BID_WON, + time: 120, + cpm: 0.29, + currency: 'USD', + originalCpm: 0.29, + originalCurrency: 'USD', + cpmUsd: 0.29, + }); + }); + + it('should handle BID_WON properly and fill originalCurrency field with currency in missing originalCurrency case', function() { + const result = appierAnalyticsAdapter.serializeBidResponse(withoutOriginalCurrencyBids[0], BIDDER_STATUS.BID_WON); + expect(result).to.include({ + prebidWon: true, + isTimeout: false, + status: BIDDER_STATUS.BID_WON, + time: 120, + cpm: 0.09, + currency: 'USD', + originalCpm: 0.09, + originalCurrency: 'USD', + cpmUsd: 0.09, + }); + }); + }); + + describe('#addBidResponseToMessage()', function() { + it('should add a bid response in the output message, grouped by adunit_id and bidder', function() { + const message = { + adUnits: {} + }; + appierAnalyticsAdapter.addBidResponseToMessage(message, noBids[0], BIDDER_STATUS.NO_BID); + + expect(message.adUnits).to.deep.include({ + 'adunit_2': { + 'appier': { + prebidWon: false, + isTimeout: false, + status: BIDDER_STATUS.NO_BID, + } + } + }); + }); + }); + + describe('#createBidMessage()', function() { + it('should format auction message sent to the backend', function() { + const args = { + auctionId: auctionId, + timestamp: 1234567890, + timeout: 3000, + auctionEnd: 1234567990, + adUnitCodes: ['adunit_1', 'adunit_2'], + bidsReceived: receivedBids, + noBids: noBids + }; + + const result = appierAnalyticsAdapter.createBidMessage(args, highestCpmBids, timeoutBids); + + assertHavingRequiredMessageFields(result); + expect(result).to.deep.include({ + auctionElapsed: 100, + timeout: 3000, + adUnits: { + 'adunit_1': { + 'appier': { + prebidWon: true, + isTimeout: false, + status: BIDDER_STATUS.BID, + time: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + cpmUsd: 0.1, + }, + 'reippa': { + prebidWon: false, + isTimeout: false, + status: BIDDER_STATUS.BID, + time: 100, + cpm: 0.08, + currency: 'USD', + originalCpm: 0.08, + originalCurrency: 'USD', + cpmUsd: 0.08, + } + }, + 'adunit_2': { + // this bid result exists in both bid and noBid arrays and should be treated as bid + 'appier': { + prebidWon: false, + isTimeout: false, + time: 120, + cpm: 0.09, + currency: 'USD', + originalCpm: 0.09, + originalCurrency: 'USD', + cpmUsd: 0.09, + status: BIDDER_STATUS.BID, + }, + 'reippa': { + prebidWon: false, + isTimeout: true, + status: BIDDER_STATUS.TIMEOUT, + } + } + } + }); + }); + }); + + describe('#createImpressionMessage()', function() { + it('should format message sent to the backend with the bid result', function() { + const bid = receivedBids[0]; + const result = appierAnalyticsAdapter.createImpressionMessage(bid); + + assertHavingRequiredMessageFields(result); + expect(result.adUnits).to.deep.include({ + 'adunit_1': { + 'appier': { + prebidWon: true, + isTimeout: false, + status: BIDDER_STATUS.BID_WON, + time: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + cpmUsd: 0.1, + } + } + }); + }); + }); + + describe('#createCreativeMessage()', function() { + it('should generate message sent to the backend with ad html grouped by adunit and bidder', function() { + const result = appierAnalyticsAdapter.createCreativeMessage(auctionId, receivedBids); + + assertHavingRequiredMessageFields(result); + expect(result.adUnits).to.deep.include({ + 'adunit_1': { + 'appier': { + ad: 'fake ad1' + }, + 'reippa': { + ad: 'fake ad2' + }, + }, + 'adunit_2': { + 'appier': { + ad: 'fake ad3' + } + } + }); + }); + }); + describe('#handleBidTimeout()', function() { + it('should cached the timeout bid as BID_TIMEOUT event was triggered', function() { + appierAnalyticsAdapter.cachedAuctions['test_timeout_auction_id'] = { 'timeoutBids': [] }; + const args = [{ + auctionId: 'test_timeout_auction_id', + timestamp: 1234567890, + timeout: 3000, + auctionEnd: 1234567990, + bidsReceived: receivedBids, + noBids: noBids + }]; + + appierAnalyticsAdapter.handleBidTimeout(args); + const result = appierAnalyticsAdapter.getCachedAuction('test_timeout_auction_id'); + expect(result).to.deep.include({ + timeoutBids: [{ + auctionId: 'test_timeout_auction_id', + timestamp: 1234567890, + timeout: 3000, + auctionEnd: 1234567990, + bidsReceived: receivedBids, + noBids: noBids + }] + }); + }); + }); + describe('#handleBidWon()', function() { + it('should call createImpressionMessage once as BID_WON event was triggered', function() { + sinon.spy(appierAnalyticsAdapter, 'createImpressionMessage'); + const receivedBids = [ + { + auctionId: auctionId, + adUnitCode: 'adunit_1', + bidder: 'appier', + bidderCode: 'appier', + requestId: 'a1b2c3d4', + timeToRespond: 72, + cpm: 0.1, + currency: 'USD', + originalCpm: 0.1, + originalCurrency: 'USD', + ad: 'fake ad1' + }, + ] + + appierAnalyticsAdapter.handleBidWon(receivedBids[0]); + sinon.assert.callCount(appierAnalyticsAdapter.createImpressionMessage, 1); + appierAnalyticsAdapter.createImpressionMessage.restore(); + }); + }); + }); + }); + + describe('Appier Analytics Adapter track handler ', function () { + const configOptions = { + affiliateId: affiliateId, + configId: configId, + server: serverUrl, + autoPick: autoPick, + sampling: 1, + adSampling: 1, + }; + + beforeEach(function () { + sinon.stub(events, 'getEvents').returns([]); + appierAnalyticsAdapter.enableAnalytics({ + provider: 'appierAnalytics', + options: configOptions + }); + }); + + afterEach(function () { + appierAnalyticsAdapter.disableAnalytics(); + events.getEvents.restore(); + }); + + it('should call handleBidWon as BID_WON trigger event', function() { + sinon.spy(appierAnalyticsAdapter, 'handleBidWon'); + events.emit(constants.EVENTS.BID_WON, {}); + sinon.assert.callCount(appierAnalyticsAdapter.handleBidWon, 1); + appierAnalyticsAdapter.handleBidWon.restore(); + }); + + it('should call handleBidTimeout as BID_TIMEOUT trigger event', function() { + sinon.spy(appierAnalyticsAdapter, 'handleBidTimeout'); + events.emit(constants.EVENTS.BID_TIMEOUT, {}); + sinon.assert.callCount(appierAnalyticsAdapter.handleBidTimeout, 1); + appierAnalyticsAdapter.handleBidTimeout.restore(); + }); + + it('should call handleAuctionEnd as AUCTION_END trigger event', function() { + sinon.spy(appierAnalyticsAdapter, 'handleAuctionEnd'); + events.emit(constants.EVENTS.AUCTION_END, {}); + sinon.assert.callCount(appierAnalyticsAdapter.handleAuctionEnd, 1); + appierAnalyticsAdapter.handleAuctionEnd.restore(); + }); + + it('should call createCreativeMessage as AUCTION_END trigger event in adSampled is true', function() { + const configOptions = { + options: { + affiliateId: affiliateId, + configId: configId, + server: serverUrl, + autoPick: autoPick, + sampling: 1, + adSampling: 1, + adSampled: true, + } + }; + const args = { + auctionId: 'test_timeout_auction_id', + timestamp: 1234567890, + timeout: 3000, + auctionEnd: 1234567990, + }; + appierAnalyticsAdapter.initConfig(configOptions); + sinon.stub(appierAnalyticsAdapter, 'sendEventMessage').returns({}); + sinon.stub(appierAnalyticsAdapter, 'createBidMessage').returns({}); + sinon.spy(appierAnalyticsAdapter, 'createCreativeMessage'); + events.emit(constants.EVENTS.AUCTION_END, args); + sinon.assert.callCount(appierAnalyticsAdapter.createCreativeMessage, 1); + appierAnalyticsAdapter.sendEventMessage.restore(); + appierAnalyticsAdapter.createBidMessage.restore(); + appierAnalyticsAdapter.createCreativeMessage.restore(); + }); + }); + + describe('enableAnalytics and config parser', function () { + const configOptions = { + affiliateId: affiliateId, + configId: configId, + server: serverUrl, + autoPick: autoPick, + sampling: 0, + adSampling: 1, + }; + + beforeEach(function () { + appierAnalyticsAdapter.enableAnalytics({ + provider: 'appierAnalytics', + options: configOptions + }); + }); + + afterEach(function () { + appierAnalyticsAdapter.disableAnalytics(); + }); + + it('should parse config correctly with optional values', function () { + expect(appierAnalyticsAdapter.getAnalyticsOptions().options).to.deep.equal(configOptions); + expect(appierAnalyticsAdapter.getAnalyticsOptions().affiliateId).to.equal(configOptions.affiliateId); + expect(appierAnalyticsAdapter.getAnalyticsOptions().configId).to.equal(configOptions.configId); + expect(appierAnalyticsAdapter.getAnalyticsOptions().server).to.equal(configOptions.server); + expect(appierAnalyticsAdapter.getAnalyticsOptions().autoPick).to.equal(configOptions.autoPick); + expect(appierAnalyticsAdapter.getAnalyticsOptions().sampled).to.equal(false); + expect(appierAnalyticsAdapter.getAnalyticsOptions().adSampled).to.equal(true); + }); + + it('should not enable Analytics when affiliateId is missing', function () { + const configOptions = { + options: { + configId: configId + } + }; + const validConfig = appierAnalyticsAdapter.initConfig(configOptions); + expect(validConfig).to.equal(false); + }); + + it('should use DEFAULT_SERVER when server is missing', function () { + const configOptions = { + options: { + configId: configId, + affiliateId: affiliateId + } + }; + appierAnalyticsAdapter.initConfig(configOptions); + expect(appierAnalyticsAdapter.getAnalyticsOptions().server).to.equal('https://prebid-analytics.c.appier.net/v1'); + }); + + it('should use null when autoPick is missing', function () { + const configOptions = { + options: { + configId: configId, + affiliateId: affiliateId + } + }; + appierAnalyticsAdapter.initConfig(configOptions); + expect(appierAnalyticsAdapter.getAnalyticsOptions().autoPick).to.equal(null); + }); + + it('should not enable Analytics when configId is missing', function () { + const configOptions = { + options: { + affiliateId: affiliateId + } + }; + const validConfig = appierAnalyticsAdapter.initConfig(configOptions); + expect(validConfig).to.equal(false); + }); + + it('should fall back to default value when sampling factor is not number', function () { + const configOptions = { + options: { + affiliateId: affiliateId, + configId: configId, + sampling: 'string', + adSampling: 'string' + } + }; + appierAnalyticsAdapter.enableAnalytics({ + provider: 'appierAnalytics', + options: configOptions + }); + + expect(appierAnalyticsAdapter.getAnalyticsOptions().sampled).to.equal(false); + expect(appierAnalyticsAdapter.getAnalyticsOptions().adSampled).to.equal(true); + }); + }); +}); From cacb6e7deb7ac75b33048b3e2cc176be9f980875 Mon Sep 17 00:00:00 2001 From: naegelin Date: Mon, 10 Jun 2019 21:33:41 +0200 Subject: [PATCH 1270/1594] Adding aliases for adsparc and safereach to aardvark adapter (#3848) * Update aardvark adapter Adding aliases for adsparc and safereach * Update aardvarkBidAdapter.js * Removing adsparc from serverbid adapters Per request of @sanjayamolligoda at adsparc. Removing alias from serverbid. --- modules/aardvarkBidAdapter.js | 1 + modules/serverbidBidAdapter.js | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index 239800ce7fa..81d393a3859 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -15,6 +15,7 @@ export function resetUserSync() { export const spec = { code: BIDDER_CODE, + aliases: ['adsparc', 'safereach'], isBidRequestValid: function(bid) { return ((typeof bid.params.ai === 'string') && !!bid.params.ai.length && diff --git a/modules/serverbidBidAdapter.js b/modules/serverbidBidAdapter.js index 037721061e2..faeeafdd53f 100644 --- a/modules/serverbidBidAdapter.js +++ b/modules/serverbidBidAdapter.js @@ -16,9 +16,6 @@ const CONFIG = { 'insticator': { 'BASE_URI': 'https://e.serverbid.com/api/v2' }, - 'adsparc': { - 'BASE_URI': 'https://e.serverbid.com/api/v2' - }, 'automatad': { 'BASE_URI': 'https://e.serverbid.com/api/v2' }, @@ -38,7 +35,7 @@ let bidder = 'serverbid'; export const spec = { code: BIDDER_CODE, - aliases: ['connectad', 'onefiftytwo', 'insticator', 'adsparc', 'automatad', 'archon', 'buysellads', 'answermedia'], + aliases: ['connectad', 'onefiftytwo', 'insticator', 'automatad', 'archon', 'buysellads', 'answermedia'], /** * Determines whether or not the given bid request is valid. From 2794cd8f203b155ef6d2e7218489a92a1c2f90c5 Mon Sep 17 00:00:00 2001 From: mcamustlr <51314002+mcamustlr@users.noreply.github.com> Date: Wed, 12 Jun 2019 18:04:40 +0200 Subject: [PATCH 1271/1594] Add slimCut bid adapter (#3880) --- modules/slimcutBidAdapter.js | 128 ++++++++++++ modules/slimcutBidAdapter.md | 45 +++++ test/spec/modules/slimcutBidAdapter_spec.js | 212 ++++++++++++++++++++ 3 files changed, 385 insertions(+) create mode 100644 modules/slimcutBidAdapter.js create mode 100644 modules/slimcutBidAdapter.md create mode 100644 test/spec/modules/slimcutBidAdapter_spec.js diff --git a/modules/slimcutBidAdapter.js b/modules/slimcutBidAdapter.js new file mode 100644 index 00000000000..def490d6ab9 --- /dev/null +++ b/modules/slimcutBidAdapter.js @@ -0,0 +1,128 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { ajax } from 'src/ajax'; + +const BIDDER_CODE = 'slimcut'; +const ENDPOINT_URL = '//sb.freeskreen.com/pbr'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['scm'], + 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(utils.getValue(bid.params, 'placementId'))) && parseInt(utils.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 + }; + bidResponses.push(bidResponse); + }); + } + return bidResponses; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//sb.freeskreen.com/async_usersync.html' + }]; + } + return []; + }, + + onBidWon: function(bid) { + ajax(bid.winUrl + bid.cpm, null); + } +} + +function buildRequestObject(bid) { + const reqObj = {}; + let placementId = utils.getValue(bid.params, 'placementId'); + + reqObj.sizes = utils.parseSizesInput(bid.sizes); + reqObj.bidId = utils.getBidIdParameter('bidId', bid); + reqObj.bidderRequestId = utils.getBidIdParameter('bidderRequestId', bid); + reqObj.placementId = parseInt(placementId); + reqObj.adUnitCode = utils.getBidIdParameter('adUnitCode', bid); + reqObj.auctionId = utils.getBidIdParameter('auctionId', bid); + reqObj.transactionId = utils.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/slimcutBidAdapter.md b/modules/slimcutBidAdapter.md new file mode 100644 index 00000000000..1d83c8cae6f --- /dev/null +++ b/modules/slimcutBidAdapter.md @@ -0,0 +1,45 @@ +# Overview + +**Module Name**: Slimcut Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: support@slimcut.com + +# Description + +Use `slimcut` as bidder. + +`placementId` is required and must be integer. + +The Slimcut adapter requires setup and approval from the Slimcut team. +Please reach out to your account manager for more information. + +# Test Parameters + +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[640, 480]], + bids: [ + { + bidder: "slimcut", + params: { + placementId: 1234 + } + } + ] + } + ]; +``` + +## UserSync example + +``` +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + syncEnabled: true, + syncDelay: 1 + } +}); +``` diff --git a/test/spec/modules/slimcutBidAdapter_spec.js b/test/spec/modules/slimcutBidAdapter_spec.js new file mode 100644 index 00000000000..92649bf3556 --- /dev/null +++ b/test/spec/modules/slimcutBidAdapter_spec.js @@ -0,0 +1,212 @@ +import {expect} from 'chai'; +import {spec} from 'modules/slimcutBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//sb.freeskreen.com/pbr'; +const AD_SCRIPT = '"'; + +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: 'http://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('http://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('//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' + }]; + + 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); + }); + }); +}); From 5715a026eae27e07ab6edc3a2593bfc97ec35204 Mon Sep 17 00:00:00 2001 From: Rafal Pastuszak Date: Wed, 12 Jun 2019 21:53:37 +0100 Subject: [PATCH 1272/1594] feat(unruly-bid-adapter): use bidResponse siteId when configuring the renderer (#3865) * feat(unruly-bid-adapter): use bidResponse siteId when configuring the renderer * feat(unruly-bid-adapter): bail if siteId is missing * feat(unruly-bid-adapter): log (but don't throw) when siteId is no present --- modules/unrulyBidAdapter.js | 16 ++++- test/spec/modules/unrulyBidAdapter_spec.js | 81 +++++++++++++++++++--- 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js index 5647d2cd6a3..580357a1978 100644 --- a/modules/unrulyBidAdapter.js +++ b/modules/unrulyBidAdapter.js @@ -4,9 +4,12 @@ import { registerBidder } from '../src/adapters/bidderFactory' import { VIDEO } from '../src/mediaTypes' function configureUniversalTag (exchangeRenderer) { + if (!exchangeRenderer.config) throw new Error('UnrulyBidAdapter: Missing renderer config.') + if (!exchangeRenderer.config.siteId) throw new Error('UnrulyBidAdapter: Missing renderer siteId.') + parent.window.unruly = parent.window.unruly || {}; parent.window.unruly['native'] = parent.window.unruly['native'] || {}; - parent.window.unruly['native'].siteId = parent.window.unruly['native'].siteId || exchangeRenderer.siteId; + parent.window.unruly['native'].siteId = parent.window.unruly['native'].siteId || exchangeRenderer.config.siteId; parent.window.unruly['native'].supplyMode = 'prebid'; } @@ -35,9 +38,18 @@ const serverResponseToBid = (bid, rendererInstance) => ({ const buildPrebidResponseAndInstallRenderer = bids => bids - .filter(serverBid => !!utils.deepAccess(serverBid, 'ext.renderer')) + .filter(serverBid => { + const hasConfig = !!utils.deepAccess(serverBid, 'ext.renderer.config'); + const hasSiteId = !!utils.deepAccess(serverBid, 'ext.renderer.config.siteId'); + + if (!hasConfig) utils.logError(new Error('UnrulyBidAdapter: Missing renderer config.')); + if (!hasSiteId) utils.logError(new Error('UnrulyBidAdapter: Missing renderer siteId.')); + + return hasSiteId + }) .map(serverBid => { const exchangeRenderer = utils.deepAccess(serverBid, 'ext.renderer'); + configureUniversalTag(exchangeRenderer); configureRendererQueue(); diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js index e39f9a8e996..cb30fcf1a9d 100644 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -18,7 +18,10 @@ describe('UnrulyAdapter', function () { 'statusCode': statusCode, 'renderer': { 'id': 'unruly_inarticle', - 'config': {}, + 'config': { + 'siteId': 123456, + 'targetingUUID': 'xxx-yyy-zzz' + }, 'url': 'https://video.unrulymedia.com/native/prebid-loader.js' }, 'adUnitCode': adUnitCode @@ -125,10 +128,10 @@ describe('UnrulyAdapter', function () { it('should be a function', function () { expect(typeof adapter.interpretResponse).to.equal('function'); }); - it('should return empty array when serverResponse is undefined', function () { + it('should return [] when serverResponse is undefined', function () { expect(adapter.interpretResponse()).to.deep.equal([]); }); - it('should return empty array when serverResponse has no bids', function () { + it('should return [] when serverResponse has no bids', function () { const mockServerResponse = { body: { bids: [] } }; expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]) }); @@ -157,7 +160,13 @@ describe('UnrulyAdapter', function () { expect(fakeRenderer.setRender.called).to.be.false; const mockReturnedBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); - const mockRenderer = { url: 'value: mockRendererURL' }; + const mockRenderer = { + url: 'value: mockRendererURL', + config: { + siteId: 123456, + targetingUUID: 'xxx-yyy-zzz' + } + }; mockReturnedBid.ext.renderer = mockRenderer; const mockServerResponse = createExchangeResponse(mockReturnedBid); @@ -173,6 +182,58 @@ describe('UnrulyAdapter', function () { sinon.assert.calledWithExactly(fakeRenderer.setRender, sinon.match.func) }); + it('should return [] and log if bidResponse renderer config is not available', function () { + sinon.assert.notCalled(utils.logError) + + expect(Renderer.install.called).to.be.false; + expect(fakeRenderer.setRender.called).to.be.false; + + const mockReturnedBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); + const mockRenderer = { + url: 'value: mockRendererURL' + }; + mockReturnedBid.ext.renderer = mockRenderer; + const mockServerResponse = createExchangeResponse(mockReturnedBid); + + expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]); + + const logErrorCalls = utils.logError.getCalls(); + expect(logErrorCalls.length).to.equal(2); + + const [ configErrorCall, siteIdErrorCall ] = logErrorCalls; + + expect(configErrorCall.args.length).to.equal(1); + expect(configErrorCall.args[0].message).to.equal('UnrulyBidAdapter: Missing renderer config.'); + + expect(siteIdErrorCall.args.length).to.equal(1); + expect(siteIdErrorCall.args[0].message).to.equal('UnrulyBidAdapter: Missing renderer siteId.'); + }); + + it('should return [] and log if siteId is not available', function () { + sinon.assert.notCalled(utils.logError) + + expect(Renderer.install.called).to.be.false; + expect(fakeRenderer.setRender.called).to.be.false; + + const mockReturnedBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); + const mockRenderer = { + url: 'value: mockRendererURL', + config: {} + }; + mockReturnedBid.ext.renderer = mockRenderer; + const mockServerResponse = createExchangeResponse(mockReturnedBid); + + expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]); + + const logErrorCalls = utils.logError.getCalls(); + expect(logErrorCalls.length).to.equal(1); + + const [ siteIdErrorCall ] = logErrorCalls; + + expect(siteIdErrorCall.args.length).to.equal(1); + expect(siteIdErrorCall.args[0].message).to.equal('UnrulyBidAdapter: Missing renderer siteId.'); + }); + it('bid is placed on the bid queue when render is called', function () { const exchangeBid = createOutStreamExchangeBid({ adUnitCode: 'video', vastUrl: 'value: vastUrl' }); const exchangeResponse = createExchangeResponse(exchangeBid); @@ -191,7 +252,7 @@ describe('UnrulyAdapter', function () { expect(sentRendererConfig.vastUrl).to.equal('value: vastUrl'); expect(sentRendererConfig.renderer).to.equal(fakeRenderer); expect(sentRendererConfig.adUnitCode).to.equal('video') - }) + }); it('should ensure that renderer is placed in Prebid supply mode', function () { const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); @@ -237,13 +298,13 @@ describe('UnrulyAdapter', function () { type: 'iframe', url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html' }) - }) + }); it('should append consent params if gdpr does apply and consent is given', () => { const mockConsent = { gdprApplies: true, consentString: 'hello' - } + }; const response = {} const syncOptions = { iframeEnabled: true } const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent) @@ -251,14 +312,14 @@ describe('UnrulyAdapter', function () { type: 'iframe', url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html?gdpr=1&gdpr_consent=hello' }) - }) + }); it('should append consent param if gdpr applies and no consent is given', () => { const mockConsent = { gdprApplies: true, consentString: {} - } - const response = {} + }; + const response = {}; const syncOptions = { iframeEnabled: true } const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent) expect(syncs[0]).to.deep.equal({ From 9598148f3f6dfb129b3193718e3cd5c2767afe5b Mon Sep 17 00:00:00 2001 From: Joshua Casingal Date: Wed, 12 Jun 2019 17:04:28 -0400 Subject: [PATCH 1273/1594] [BID-3479] - Add BidResponse.meta.dspid for OpenX (#3895) * [BID-3479] - Add BidResponse.meta.dspid for OpenX * Update version number to 2.1.7 --- modules/openxBidAdapter.js | 6 +++++- test/spec/modules/openxBidAdapter_spec.js | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 9719fbb635a..8236be8c2e5 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from '../src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.6'; +const BIDDER_VERSION = '2.1.7'; let shouldSendBoPixel = true; @@ -121,6 +121,10 @@ function createBannerBidResponses(oxResponseObj, {bids, startTime}) { bidResponse.meta.brandId = adUnit.brand_id; } + if (adUnit.adv_id) { + bidResponse.meta.dspid = adUnit.adv_id; + } + bidResponses.push(bidResponse); registerBeacon(BANNER, adUnit, startTime); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index ee8e452f707..0fda846faa1 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1218,6 +1218,10 @@ describe('OpenxAdapter', function () { expect(bid.meta.brandId).to.equal(DEFAULT_TEST_ARJ_AD_UNIT.brand_id); }); + it('should return a brand ID', function () { + expect(bid.meta.dspid).to.equal(DEFAULT_TEST_ARJ_AD_UNIT.adv_id); + }); + it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequest); From 96d46b159887a0f0a1f4d43e760e571ba5f9bfe7 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Wed, 12 Jun 2019 17:12:08 -0400 Subject: [PATCH 1274/1594] kargo session id (#3897) --- modules/kargoBidAdapter.js | 8 ++++++++ test/spec/modules/kargoBidAdapter_spec.js | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 2c602186547..5c3d59bd241 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -23,6 +23,7 @@ export const spec = { bidSizes[bid.bidId] = bid.sizes; }); const transformedParams = Object.assign({}, { + sessionId: spec._getSessionId(), timeout: bidderRequest.timeout, currency: currency, cpmGranularity: 1, @@ -183,6 +184,13 @@ export const spec = { }; }, + _getSessionId() { + if (!spec._sessionId) { + spec._sessionId = spec._generateRandomUuid(); + } + return spec._sessionId; + }, + _generateRandomUuid() { try { // crypto.getRandomValues is supported everywhere but Opera Mini for years diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 5d53a4e9c95..a6779f518a0 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -34,7 +34,7 @@ describe('kargo adapter tests', function () { }); describe('build request', function() { - var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = []; + var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = [], sessionIds = []; beforeEach(function () { undefinedCurrency = false; @@ -212,6 +212,10 @@ describe('kargo adapter tests', function () { setCookie('krg_crb', getEmptyKrgCrbOldStyle()); } + function getSessionId() { + return spec._sessionId; + } + function getExpectedKrakenParams(excludeUserIds, excludeKrux, expectedRawCRB, expectedRawCRBCookie) { var base = { timeout: 200, @@ -302,6 +306,8 @@ describe('kargo adapter tests', function () { function testBuildRequests(expected) { var request = spec.buildRequests(bids, {timeout: 200, foo: 'bar'}); + expected.sessionId = getSessionId(); + sessionIds.push(expected.sessionId); var krakenParams = JSON.parse(decodeURIComponent(request.data.slice(5))); expect(request.data.slice(0, 5)).to.equal('json='); expect(request.url).to.equal('https://krk.kargo.com/api/v2/bid'); @@ -310,6 +316,14 @@ describe('kargo adapter tests', function () { expect(request.timeout).to.equal(200); expect(request.foo).to.equal('bar'); expect(krakenParams).to.deep.equal(expected); + // Make sure session ID stays the same across requests simulating multiple auctions on one page load + for (let i in sessionIds) { + if (i == 0) { + continue; + } + let sessionId = sessionIds[i]; + expect(sessionIds[0]).to.equal(sessionId); + } } it('works when all params and localstorage and cookies are correctly set', function() { From 98db99cf7a7e4db2ad6fcd122bee1ddc0cc4eca7 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 12 Jun 2019 15:35:26 -0600 Subject: [PATCH 1275/1594] allow endpoint configuration for rdn adapter (#3902) --- modules/rdnBidAdapter.js | 3 ++- test/spec/modules/rdnBidAdapter_spec.js | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/modules/rdnBidAdapter.js b/modules/rdnBidAdapter.js index f93145b5377..d85b307263d 100644 --- a/modules/rdnBidAdapter.js +++ b/modules/rdnBidAdapter.js @@ -1,6 +1,7 @@ import { registerBidder } from '../src/adapters/bidderFactory' import * as utils from '../src/utils' import { BANNER } from '../src/mediaTypes' +import { config } from '../src/config' const BIDDER_CODE = 'rdn' const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h' @@ -14,7 +15,7 @@ export const spec = { const params = bid.params bidRequests.push({ method: 'GET', - url: ENDPOINT, + url: config.getConfig('rdn.endpoint') || ENDPOINT, data: { bi: bid.bidId, t: params.adSpotId, diff --git a/test/spec/modules/rdnBidAdapter_spec.js b/test/spec/modules/rdnBidAdapter_spec.js index 1c5958c8065..1fef1c7bf3d 100644 --- a/test/spec/modules/rdnBidAdapter_spec.js +++ b/test/spec/modules/rdnBidAdapter_spec.js @@ -2,10 +2,20 @@ import { expect } from 'chai' import * as utils from 'src/utils' import { spec } from 'modules/rdnBidAdapter' import { newBidder } from 'src/adapters/bidderFactory' +import {config} from '../../../src/config'; describe('rdnBidAdapter', function() { const adapter = newBidder(spec); const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h'; + let sandbox; + + beforeEach(function() { + config.resetConfig(); + }); + + afterEach(function () { + config.resetConfig(); + }); describe('inherited functions', () => { it('exists and is a function', () => { @@ -53,6 +63,16 @@ describe('rdnBidAdapter', function() { expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET') }) + + it('allows url override', () => { + config.setConfig({ + rdn: { + endpoint: '//test.rakuten.com' + } + }); + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal('//test.rakuten.com'); + }) }); describe('interpretResponse', () => { From 83aa229ea2a2747a329ca831d1ab74547d8a2eb6 Mon Sep 17 00:00:00 2001 From: Aleksa Trajkovic Date: Thu, 13 Jun 2019 18:08:45 +0200 Subject: [PATCH 1276/1594] aardvark adapter, add width & height params (#3892) --- modules/aardvarkBidAdapter.js | 13 +++- test/spec/modules/aardvarkBidAdapter_spec.js | 76 ++++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index 81d393a3859..9caaaaa747c 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -29,12 +29,17 @@ export const spec = { var referer = bidderRequest.refererInfo.referer; var pageCategories = []; var tdId = ''; + var width = window.innerWidth; + var height = window.innerHeight; // This reference to window.top can cause issues when loaded in an iframe if not protected with a try/catch. try { - if (window.top.rtkcategories && Array.isArray(window.top.rtkcategories)) { - pageCategories = window.top.rtkcategories; + var topWin = utils.getWindowTop(); + if (topWin.rtkcategories && Array.isArray(topWin.rtkcategories)) { + pageCategories = topWin.rtkcategories; } + width = topWin.innerWidth; + height = topWin.innerHeight; } catch (e) {} if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) { @@ -49,7 +54,9 @@ export const spec = { payload: { version: 1, jsonp: false, - rtkreferer: referer + rtkreferer: referer, + w: width, + h: height }, endpoint: DEFAULT_ENDPOINT }; diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js index 727527acf29..b532fa4264a 100644 --- a/test/spec/modules/aardvarkBidAdapter_spec.js +++ b/test/spec/modules/aardvarkBidAdapter_spec.js @@ -1,4 +1,5 @@ import { expect } from 'chai'; +import * as utils from 'src/utils'; import { spec, resetUserSync } from 'modules/aardvarkBidAdapter'; describe('aardvarkAdapterTest', function () { @@ -343,4 +344,79 @@ describe('aardvarkAdapterTest', function () { expect(syncs[0].url).to.equal('//sync.rtk.io/cs?g=1&c=BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA'); }); }); + + describe('reading window.top properties', function () { + const bidCategories = ['bcat1', 'bcat2', 'bcat3']; + const bidRequests = [{ + bidder: 'aardvark', + params: { + ai: 'xiby', + sc: 'TdAx', + host: 'adzone.pub.com', + categories: bidCategories + }, + adUnitCode: 'RTK_aaaa', + transactionId: '1b8389fe-615c-482d-9f1a-177fb8f7d5b0', + sizes: [300, 250], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337', + userId: { tdid: 'eff98622-b5fd-44fa-9a49-6e846922d532' } + }]; + + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; + + const topWin = { + innerWidth: 1366, + innerHeight: 768, + rtkcategories: ['cat1', 'cat2', 'cat3'] + }; + + let sandbox; + beforeEach(function () { + sandbox = sinon.createSandbox(); + }); + + afterEach(function () { + sandbox.restore(); + }); + + it('should have window.top dimensions', function () { + sandbox.stub(utils, 'getWindowTop').returns(topWin); + + const requests = spec.buildRequests(bidRequests, bidderRequest); + requests.forEach(function (requestItem) { + expect(requestItem.data.w).to.equal(topWin.innerWidth); + expect(requestItem.data.h).to.equal(topWin.innerHeight); + }); + }); + + it('should have window dimensions, as backup', function () { + sandbox.stub(utils, 'getWindowTop').returns(undefined); + + const requests = spec.buildRequests(bidRequests, bidderRequest); + requests.forEach(function (requestItem) { + expect(requestItem.data.w).to.equal(window.innerWidth); + expect(requestItem.data.h).to.equal(window.innerHeight); + }); + }); + + it('should have window.top & bid categories', function () { + sandbox.stub(utils, 'getWindowTop').returns(topWin); + + const requests = spec.buildRequests(bidRequests, bidderRequest); + requests.forEach(function (requestItem) { + utils._each(topWin.categories, function (cat) { + expect(requestItem.data.categories).to.contain(cat); + }); + utils._each(bidCategories, function (cat) { + expect(requestItem.data.categories).to.contain(cat); + }); + }); + }); + }); }); From a9dc89691993bbd91be3062d7ce47fca2d8fb9e7 Mon Sep 17 00:00:00 2001 From: nwlosinski Date: Thu, 13 Jun 2019 19:12:14 +0200 Subject: [PATCH 1277/1594] cache buster for user sync (#3838) --- modules/justpremiumBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 6fbf5454b91..f8419f06faf 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -97,9 +97,9 @@ export const spec = { }, getUserSyncs: function getUserSyncs(syncOptions, responses, gdprConsent) { - let url = '//pre.ads.justpremium.com/v/1.0/t/sync' + let url = '//pre.ads.justpremium.com/v/1.0/t/sync' + '?_c=' + 'a' + Math.random().toString(36).substring(7) + Date.now(); if (gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean')) { - url = url + '?consentString=' + encodeURIComponent(gdprConsent.consentString) + url = url + '&consentString=' + encodeURIComponent(gdprConsent.consentString) } if (syncOptions.iframeEnabled) { pixels.push({ From efe74f8a0a90d3e929d68bcc87169f6583cba676 Mon Sep 17 00:00:00 2001 From: HolzAndrew Date: Thu, 13 Jun 2019 13:14:41 -0400 Subject: [PATCH 1278/1594] Add bidFloor to Yieldmo Adapter (#3886) * change userid to pubcid * removes consolelogs * removes .txt file * fixes test * make the if statement useful * fix indentation * move return back to the correct place * fix indent --- modules/yieldmoBidAdapter.js | 28 +++++++++++++-------- modules/yieldmoBidAdapter.md | 3 ++- test/spec/modules/yieldmoBidAdapter_spec.js | 21 ++++++++++------ 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index b2d13e88c80..299baf49042 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -43,12 +43,13 @@ export const spec = { bidRequests.forEach((request) => { serverRequest.p.push(addPlacement(request)); - const userId = getUserId(request) - if (userId) { - const pubcid = userId.pubcid; + const pubcid = getPubcId(request) + if (pubcid) { serverRequest.pubcid = pubcid; } else if (request.crumbs) { - serverRequest.pubcid = request.crumbs.pubcid; + if (request.crumbs.pubcid) { + serverRequest.pubcid = request.crumbs.pubcid; + } } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; @@ -103,8 +104,13 @@ function addPlacement(request) { callback_id: request.bidId, sizes: request.sizes } - if (request.params && request.params.placementId) { - placementInfo.ym_placement_id = request.params.placementId + if (request.params) { + if (request.params.placementId) { + placementInfo.ym_placement_id = request.params.placementId; + } + if (request.params.bidFloor) { + placementInfo.bidFloor = request.params.bidFloor; + } } return JSON.stringify(placementInfo); } @@ -311,10 +317,10 @@ function isMraid() { return !!(window.mraid); } -function getUserId(request) { - let userId; - if (request && request.userId && typeof request.userId === 'object') { - userId = request.userId; +function getPubcId(request) { + let pubcid; + if (request && request.userId && request.userId.pubcid && typeof request.userId === 'object') { + pubcid = request.userId.pubcid; } - return userId; + return pubcid; } diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index 8c60202d7ea..7221f2ebdd0 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -23,7 +23,8 @@ var adUnits = [ bids: [{ bidder: 'yieldmo', params: { - placementId: '1779781193098233305' // string with at most 19 characters (may include numbers only) + placementId: '1779781193098233305', // string with at most 19 characters (may include numbers only) + bidFloor: .28 // optional param } }] } diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 12dd87e1517..2a94dc7e5c9 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -9,7 +9,9 @@ describe('YieldmoAdapter', function () { let bid = { bidder: 'yieldmo', - params: {}, + params: { + bidFloor: 0.1 + }, adUnitCode: 'adunit-code', sizes: [[300, 250], [300, 600]], bidId: '30b31c1838de1e', @@ -59,11 +61,13 @@ describe('YieldmoAdapter', function () { it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]]}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); bidArray.push({ bidder: 'yieldmo', - params: {}, + params: { + bidFloor: 0.2 + }, adUnitCode: 'adunit-code-1', sizes: [[300, 250], [300, 600]], bidId: '123456789', @@ -77,19 +81,19 @@ describe('YieldmoAdapter', function () { // multiple placements placementInfo = spec.buildRequests(bidArray).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]]},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]]}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); }); it('should add placement id if given', function () { bidArray[0].params.placementId = 'ym_1293871298'; let placementInfo = spec.buildRequests(bidArray).data.p; - expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"}'); - expect(placementInfo).not.to.include('"ym_placement_id":"ym_0987654321"}'); + expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); + expect(placementInfo).not.to.include('"ym_placement_id":"ym_0987654321"'); bidArray[1].params.placementId = 'ym_0987654321'; placementInfo = spec.buildRequests(bidArray).data.p; - expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"}'); - expect(placementInfo).to.include('"ym_placement_id":"ym_0987654321"}'); + expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); + expect(placementInfo).to.include('"ym_placement_id":"ym_0987654321"'); }); it('should add additional information to data parameter of request', function () { @@ -104,6 +108,7 @@ describe('YieldmoAdapter', function () { expect(data.hasOwnProperty('title')).to.be.true; expect(data.hasOwnProperty('h')).to.be.true; expect(data.hasOwnProperty('w')).to.be.true; + expect(data.hasOwnProperty('pubcid')).to.be.true; }) it('should add pubcid as parameter of request', function () { From 40f032cc3aa4944126417c3bfbb459a28eefbaa1 Mon Sep 17 00:00:00 2001 From: John Salis Date: Thu, 13 Jun 2019 13:33:32 -0400 Subject: [PATCH 1279/1594] Add beachfront bidder params to set outstream player settings (#3868) * Add beachfront bidder params to set outstream player settings * Add example for outstream player params * Run ci again --- modules/beachfrontBidAdapter.js | 32 +++++----- modules/beachfrontBidAdapter.md | 32 ++++++++++ .../spec/modules/beachfrontBidAdapter_spec.js | 58 +++++++++++++++++++ 3 files changed, 108 insertions(+), 14 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 552413f4878..efc7dfeda8d 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -7,7 +7,7 @@ import { VIDEO, BANNER } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.4'; +const ADAPTER_VERSION = '1.5'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; @@ -143,21 +143,20 @@ function createRenderer(bidRequest) { loaded: false }); - renderer.setRender(outstreamRender); - - return renderer; -} - -function outstreamRender(bid) { - bid.renderer.push(() => { - window.Beachfront.Player(bid.adUnitCode, { - ad_tag_url: bid.vastUrl, - width: bid.width, - height: bid.height, - expand_in_view: false, - collapse_on_complete: true + renderer.setRender(bid => { + bid.renderer.push(() => { + window.Beachfront.Player(bid.adUnitCode, { + adTagUrl: bid.vastUrl, + width: bid.width, + height: bid.height, + expandInView: getPlayerBidParam(bidRequest, 'expandInView', false), + collapseOnComplete: getPlayerBidParam(bidRequest, 'collapseOnComplete', true), + progressColor: getPlayerBidParam(bidRequest, 'progressColor') + }); }); }); + + return renderer; } function getFirstSize(sizes) { @@ -231,6 +230,11 @@ function getBannerBidParam(bid, key) { return utils.deepAccess(bid, 'params.banner.' + key) || utils.deepAccess(bid, 'params.' + key); } +function getPlayerBidParam(bid, key, defaultValue) { + let param = utils.deepAccess(bid, 'params.player.' + key); + return param === undefined ? defaultValue : param; +} + function isVideoBidValid(bid) { return isVideoBid(bid) && getVideoBidParam(bid, 'appId') && getVideoBidParam(bid, 'bidfloor'); } diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index fb14db59710..3f827fe9241 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -86,3 +86,35 @@ Module that connects to Beachfront's demand sources } ]; ``` + +# Outstream Player Params Example +```javascript + var adUnits = [ + { + code: 'test-video-outstream', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [ 640, 360 ] + } + }, + bids: [ + { + bidder: 'beachfront', + params: { + video: { + bidfloor: 0.01, + appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76', + mimes: [ 'video/mp4', 'application/javascript' ] + }, + player: { + progressColor: '#50A8FA', + expandInView: false, + collapseOnComplete: true + } + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 652dae4a74a..f5890cb6475 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,4 +1,5 @@ import { expect } from 'chai'; +import sinon from 'sinon'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import { parse as parseUrl } from 'src/url'; @@ -531,6 +532,63 @@ describe('BeachfrontAdapter', function () { url: OUTSTREAM_SRC }); }); + + it('should initialize a player for outstream bids', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [ width, height ] + } + }; + const serverResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + cmpId: '123abc' + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + window.Beachfront = { Player: sinon.spy() }; + bidResponse.adUnitCode = bidRequest.adUnitCode; + bidResponse.renderer.render(bidResponse); + sinon.assert.calledWith(window.Beachfront.Player, bidResponse.adUnitCode, sinon.match({ + adTagUrl: bidResponse.vastUrl, + width: bidResponse.width, + height: bidResponse.height, + expandInView: false, + collapseOnComplete: true + })); + delete window.Beachfront; + }); + + it('should configure outstream player settings from the bidder params', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [ width, height ] + } + }; + bidRequest.params.player = { + expandInView: true, + collapseOnComplete: false, + progressColor: 'green' + }; + const serverResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + cmpId: '123abc' + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + window.Beachfront = { Player: sinon.spy() }; + bidResponse.adUnitCode = bidRequest.adUnitCode; + bidResponse.renderer.render(bidResponse); + sinon.assert.calledWith(window.Beachfront.Player, bidResponse.adUnitCode, sinon.match(bidRequest.params.player)); + delete window.Beachfront; + }); }); describe('for banner bids', function () { From b617aa3e4153c0bd1c9d8db80987cd3972501560 Mon Sep 17 00:00:00 2001 From: Chris Connors Date: Thu, 13 Jun 2019 14:00:16 -0400 Subject: [PATCH 1280/1594] Adding Scaleable Analytics Adapter (#3846) * Adding Scaleable Analytics Adapter * Removed commented out code --- modules/scaleableAnalyticsAdapter.js | 153 ++++++++++++++++++ modules/scaleableAnalyticsAdapter.md | 20 +++ .../modules/scaleableAnalyticsAdapter_spec.js | 136 ++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 modules/scaleableAnalyticsAdapter.js create mode 100644 modules/scaleableAnalyticsAdapter.md create mode 100644 test/spec/modules/scaleableAnalyticsAdapter_spec.js diff --git a/modules/scaleableAnalyticsAdapter.js b/modules/scaleableAnalyticsAdapter.js new file mode 100644 index 00000000000..c875dab7e18 --- /dev/null +++ b/modules/scaleableAnalyticsAdapter.js @@ -0,0 +1,153 @@ +/* COPYRIGHT SCALEABLE LLC 2019 */ + +import { ajax } from '../src/ajax'; +import CONSTANTS from '../src/constants.json'; +import adapter from '../src/AnalyticsAdapter'; +import adapterManager from '../src/adapterManager'; +import * as utils from '../src/utils'; + +const BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; +const AUCTION_INIT = CONSTANTS.EVENTS.AUCTION_INIT; +const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; +const BID_WON = CONSTANTS.EVENTS.BID_WON; +const AUCTION_END = CONSTANTS.EVENTS.AUCTION_END; + +const URL = 'https://auction.scaleable.ai/'; +const ANALYTICS_TYPE = 'endpoint'; + +let auctionData = {}; + +let scaleableAnalytics = Object.assign({}, + adapter({ + URL, + ANALYTICS_TYPE + }), + { + // Override AnalyticsAdapter functions by supplying custom methods + track({ eventType, args }) { + switch (eventType) { + case AUCTION_INIT: + onAuctionInit(args); + break; + case AUCTION_END: + onAuctionEnd(args); + break; + case BID_WON: + onBidWon(args); + break; + case BID_RESPONSE: + onBidResponse(args); + break; + case BID_TIMEOUT: + onBidTimeout(args); + break; + default: + break; + } + } + } +); + +scaleableAnalytics.config = {}; +scaleableAnalytics.originEnableAnalytics = scaleableAnalytics.enableAnalytics; +scaleableAnalytics.enableAnalytics = config => { + scaleableAnalytics.config = config; + + scaleableAnalytics.originEnableAnalytics(config); + + scaleableAnalytics.enableAnalytics = function _enable() { + return utils.logMessage(`Analytics adapter for "${global}" already enabled, unnecessary call to \`enableAnalytics\`.`); + }; +} + +scaleableAnalytics.getAuctionData = () => { + return auctionData; +}; + +const sendDataToServer = data => ajax(URL, () => {}, JSON.stringify(data)); + +// Track auction initiated +const onAuctionInit = args => { + const config = scaleableAnalytics.config || {options: {}}; + + for (let idx = args.adUnitCodes.length; idx--;) { + const data = { + event: 'request', + site: config.options.site, + adunit: args.adUnitCodes[idx] + }; + + sendDataToServer(data); + } +} + +// Handle all events besides requests and wins +const onAuctionEnd = args => { + for (let adunit in auctionData) { + sendDataToServer(auctionData[adunit]); + } +} + +// Bid Win Events occur after auction end +const onBidWon = args => { + const config = scaleableAnalytics.config || {options: {}}; + + const data = { + event: 'win', + site: config.options.site, + adunit: args.adUnitCode, + code: args.bidderCode, + cpm: args.cpm, + ttr: args.timeToRespond + }; + + sendDataToServer(data); +} + +const onBidResponse = args => { + const config = scaleableAnalytics.config || {options: {}}; + + if (!auctionData[args.adUnitCode]) { + auctionData[args.adUnitCode] = { + event: 'bids', + bids: [], + adunit: args.adUnitCode, + site: config.options.site + }; + } + + const currBidData = { + code: args.bidderCode, + cpm: args.cpm, + ttr: args.timeToRespond + }; + + auctionData[args.adUnitCode].bids.push(currBidData); +} + +const onBidTimeout = args => { + const config = scaleableAnalytics.config || {options: {}}; + + for (let i = args.length; i--;) { + let currObj = args[i]; + + if (!auctionData[currObj.adUnitCode]) { + auctionData[currObj.adUnitCode] = { + event: 'bids', + bids: [], + timeouts: [], + adunit: currObj.adUnitCode, + site: config.options.site + }; + } + + auctionData[currObj.adUnitCode].timeouts.push(currObj.bidder); + } +} + +adapterManager.registerAnalyticsAdapter({ + adapter: scaleableAnalytics, + code: 'scaleable' +}) + +export default scaleableAnalytics; diff --git a/modules/scaleableAnalyticsAdapter.md b/modules/scaleableAnalyticsAdapter.md new file mode 100644 index 00000000000..0f6fbada55a --- /dev/null +++ b/modules/scaleableAnalyticsAdapter.md @@ -0,0 +1,20 @@ +# Overview + +Module Name: Scaleable Analytics Adapter +Module Type: Analytics Adapter +Maintainer: chris@scaleable.ai + +# Description + +Analytics adapter for scaleable.ai. Contact team@scaleable.ai for more information or to sign up for analytics. + +# Implementation Code + +``` +pbjs.enableAnalytics({ + provider: 'scaleable', + options: { + site: '' // Contact Scaleable to receive your unique site id + } +}); +``` diff --git a/test/spec/modules/scaleableAnalyticsAdapter_spec.js b/test/spec/modules/scaleableAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..300f72751a4 --- /dev/null +++ b/test/spec/modules/scaleableAnalyticsAdapter_spec.js @@ -0,0 +1,136 @@ +import scaleableAnalytics from 'modules/scaleableAnalyticsAdapter'; +import { expect } from 'chai'; +import events from 'src/events'; +import CONSTANTS from 'src/constants.json'; +import adapterManager from 'src/adapterManager'; + +const BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; +const AUCTION_INIT = CONSTANTS.EVENTS.AUCTION_INIT; +const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; +const BID_WON = CONSTANTS.EVENTS.BID_WON; +const AUCTION_END = CONSTANTS.EVENTS.AUCTION_END; + +describe('Scaleable Analytics Adapter', function() { + const MOCK_DATA = { + adUnitCode: '12345', + site: '5c4fab7a829e955d6c265e72', + bidResponse: { + adUnitCode: '12345', + bidderCode: 'test-code', + cpm: 3.14, + timeToRespond: 285 + }, + bidTimeout: [ + { + adUnitCode: '67890', + bidder: 'test-code' + } + ] + }; + + MOCK_DATA.expectedBidResponse = { + event: 'bids', + bids: [{ + code: MOCK_DATA.bidResponse.bidderCode, + cpm: MOCK_DATA.bidResponse.cpm, + ttr: MOCK_DATA.bidResponse.timeToRespond + }], + adunit: MOCK_DATA.adUnitCode, + site: MOCK_DATA.site + }; + + MOCK_DATA.expectedBidTimeout = { + event: 'bids', + bids: [], + timeouts: [MOCK_DATA.bidTimeout[0].bidder], + adunit: MOCK_DATA.bidTimeout[0].adUnitCode, + site: MOCK_DATA.site + }; + + let xhr; + let requests; + + before(function() { + xhr = sinon.useFakeXMLHttpRequest(); + xhr.onCreate = request => requests.push(request); + }); + + after(function() { + xhr.restore(); + }); + + describe('Event Handling', function() { + beforeEach(function() { + requests = []; + sinon.stub(events, 'getEvents').returns([]); + + scaleableAnalytics.enableAnalytics({ + provider: 'scaleable', + options: { + site: MOCK_DATA.site + } + }); + }); + + afterEach(function() { + events.getEvents.restore(); + scaleableAnalytics.disableAnalytics(); + }); + + it('should handle the auction init event', function(done) { + events.emit(AUCTION_INIT, { + adUnitCodes: [MOCK_DATA.adUnitCode] + }); + + const result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({ + event: 'request', + site: MOCK_DATA.site, + adunit: MOCK_DATA.adUnitCode + }); + + done(); + }); + + it('should handle the bid response event', function() { + events.emit(BID_RESPONSE, MOCK_DATA.bidResponse); + + const actual = scaleableAnalytics.getAuctionData(); + + expect(actual[MOCK_DATA.adUnitCode]).to.deep.equal(MOCK_DATA.expectedBidResponse); + }); + + it('should handle the bid timeout event', function() { + events.emit(BID_TIMEOUT, MOCK_DATA.bidTimeout); + + const actual = scaleableAnalytics.getAuctionData(); + + expect(actual[MOCK_DATA.bidTimeout[0].adUnitCode]).to.deep.equal(MOCK_DATA.expectedBidTimeout); + }); + + it('should handle the bid won event', function(done) { + events.emit(BID_WON, MOCK_DATA.bidResponse); + + const result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({ + adunit: MOCK_DATA.adUnitCode, + code: MOCK_DATA.bidResponse.bidderCode, + cpm: MOCK_DATA.bidResponse.cpm, + ttr: MOCK_DATA.bidResponse.timeToRespond, + event: 'win', + site: MOCK_DATA.site + }); + + done(); + }); + + it('should handle the auction end event', function(done) { + events.emit(AUCTION_END, {}); + + const result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal(MOCK_DATA.expectedBidResponse); + + done(); + }); + }); +}); From 1dc47c8c5fd0c8854d2070178ec463ecb69f3e4e Mon Sep 17 00:00:00 2001 From: Luis Date: Thu, 13 Jun 2019 14:04:44 -0400 Subject: [PATCH 1281/1594] Fix filepath reference (#3905) --- modules/optimeraBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/optimeraBidAdapter.js b/modules/optimeraBidAdapter.js index ab4c75c1c1f..7025045c7de 100644 --- a/modules/optimeraBidAdapter.js +++ b/modules/optimeraBidAdapter.js @@ -1,4 +1,4 @@ -import { registerBidder } from 'src/adapters/bidderFactory'; +import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'optimera'; const SCORES_BASE_URL = 'https://dyv1bugovvq1g.cloudfront.net/'; From 81e87186164f0a427e2aaefd189b23d65434340e Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Thu, 13 Jun 2019 15:14:21 -0400 Subject: [PATCH 1282/1594] Prebid 2.19.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 468b16c0ebb..5125a45ef16 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.19.0-pre", + "version": "2.19.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 20d8c8b2cbfaf080f8eb39e55ae27b8eabc3cdb4 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Thu, 13 Jun 2019 15:38:03 -0400 Subject: [PATCH 1283/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5125a45ef16..4a3d8b2c959 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.19.0", + "version": "2.20.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 842cc19f712c644db84aae10d7d3567514d481e8 Mon Sep 17 00:00:00 2001 From: Chris Cole Date: Mon, 17 Jun 2019 10:19:09 -0700 Subject: [PATCH 1284/1594] digiTrustIdSystem.js add the synchronous behavior to facade call of DigiTrust.getId. Fix spelling error of facade in code. (#3913) --- modules/digiTrustIdSystem.js | 56 ++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index b587913e1ed..07792cc49d3 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -85,12 +85,12 @@ function writeDigiId(id) { } /** - * Set up a DigiTrust fascade object to mimic the API + * Set up a DigiTrust facade object to mimic the API * */ -function initDigitrustFascade(config) { +function initDigitrustFacade(config) { var _savedId = null; // closure variable for storing Id to avoid additional requests - var fascade = { + var facade = { isClient: true, isMock: true, _internals: { @@ -98,8 +98,10 @@ function initDigitrustFascade(config) { initCallback: null }, getUser: function (obj, callback) { - var cb = callback || noop; - var inter = fascade._internals; + var isAsync = !!isFunc(callback); + var cb = isAsync ? callback : noop; + var errResp = { success: false }; + var inter = facade._internals; inter.callCount++; // wrap the initializer callback, if present @@ -113,10 +115,23 @@ function initDigitrustFascade(config) { } } + if (!isMemberIdValid) { + if (!isAsync) { + return errResp + } else { + cb(errResp); + return; + } + } + if (_savedId != null) { checkCallInitializeCb(_savedId); - cb(_savedId); - return; + if (isAsync) { + cb(_savedId); + return; + } else { + return _savedId; + } } var opts = { @@ -140,14 +155,31 @@ function initDigitrustFascade(config) { } callApi(opts); + + if (!isAsync) { + return errResp; // even if it will be successful later, without a callback we report a "failure in this moment" + } } } if (window && window.DigiTrust == null) { - window.DigiTrust = fascade; + window.DigiTrust = facade; } } +/** + * Tests to see if a member ID is valid within facade + * @param {any} memberId + */ +var isMemberIdValid = function (memberId) { + if (memberId && memberId.length > 0) { + return true; + } else { + utils.logError('[DigiTrust Prebid Client Error] Missing member ID, add the member ID to the function call options'); + return false; + } +}; + /** * Encapsulation of needed info for the callback return. * @@ -237,9 +269,9 @@ function getDigiTrustId(configParams) { getDigiTrustId(configParams); }, 100 * (1 + resultHandler.retries++)); return resultHandler.userIdCallback; - } else if (!isInitialized()) { // Second see if we should build a fascade object + } else if (!isInitialized()) { // Second see if we should build a facade object if (resultHandler.retries >= MAX_RETRIES) { - initDigitrustFascade(configParams); // initialize a fascade object that relies on the AJAX call + initDigitrustFacade(configParams); // initialize a facade object that relies on the AJAX call resultHandler.executeIdRequest(configParams); } else { // use expanding envelope @@ -264,7 +296,7 @@ function initializeDigiTrust(config) { dt.initialize(config.init, config.callback); } else if (dt == null) { // Assume we are already on a delay and DigiTrust is not on page - initDigitrustFascade(config); + initDigitrustFacade(config); } } @@ -278,7 +310,7 @@ function surfaceTestHook() { digitrustIdModule['_testHook'] = testHook; } -testHook.initDigitrustFascade = initDigitrustFascade; +testHook.initDigitrustFacade = initDigitrustFacade; /** @type {Submodule} */ export const digiTrustIdSubmodule = { From 1c1035aa1995f9d098c55b0aa1c22df7560eecfa Mon Sep 17 00:00:00 2001 From: ujuettner Date: Tue, 18 Jun 2019 16:42:36 +0200 Subject: [PATCH 1285/1594] Feature/remove on set targeting (#3919) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons * add bidfloor parameter to params object * fix gdpr object handling * default to consentRequired: false when not explicitly given * wip - use onSetTargeting callback * add tests for onSetTargeting callback * fix params and respective tests * Remove onSetTargeting --- modules/orbidderBidAdapter.js | 4 ---- test/spec/modules/orbidderBidAdapter_spec.js | 6 ------ 2 files changed, 10 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index e085a14c6b8..fc6eac6e479 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -74,10 +74,6 @@ export const spec = { this.onHandler(bid, '/win'); }, - onSetTargeting (bid) { - this.onHandler(bid, '/targeting'); - }, - onHandler (bid, route) { const getRefererInfo = detectReferer(window); diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 55f5e2cae4c..4a972c42d30 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -178,12 +178,6 @@ describe('orbidderBidAdapter', () => { expect(ajaxStub.firstCall.args[0].indexOf('https://')).to.equal(0); expect(ajaxStub.firstCall.args[0]).to.equal(`${spec.orbidderHost}/win`); expect(ajaxStub.firstCall.args[1]).to.equal(JSON.stringify(bidObjClone)); - - spec.onSetTargeting(bidObj); - expect(ajaxStub.calledTwice).to.equal(true); - expect(ajaxStub.secondCall.args[0].indexOf('https://')).to.equal(0); - expect(ajaxStub.secondCall.args[0]).to.equal(`${spec.orbidderHost}/targeting`); - expect(ajaxStub.secondCall.args[1]).to.equal(JSON.stringify(bidObjClone)); }); }); From 4b84beb1a326adb2b918e81d281af2433f310831 Mon Sep 17 00:00:00 2001 From: couchcrew-thomas Date: Tue, 18 Jun 2019 16:59:36 +0200 Subject: [PATCH 1286/1594] FeedAd bidder adapter (#3891) * added file scaffold * added isBidRequestValid implementation * added local prototype of ad integration * added implementation for placement ID validation * fixed video context filter * applied lint to feedad bid adapter * added unit test for bid request validation * added buildRequest unit test * added unit tests for timeout and bid won callbacks * updated bid request to FeedAd API * added parsing of feedad api bid response * added transmisison of tracking events to FeedAd Api * code cleanup * updated feedad unit tests for buildRequest method * added unit tests for event tracking implementation * added unit test for interpretResponse method * added adapter documentation * added dedicated feedad example page * updated feedad adapter to use live system * updated FeedAd adapter placement ID regex * removed groups from FeedAd adapter placement ID regex * removed dedicated feedad example page * updated imports in FeedAd adapter file to use relative paths * updated FeedAd adapter unit test to use sinon.useFakeXMLHttpRequest() --- modules/feedadBidAdapter.js | 290 ++++++++++++++ modules/feedadBidAdapter.md | 44 +++ test/spec/modules/feedadBidAdapter_spec.js | 433 +++++++++++++++++++++ 3 files changed, 767 insertions(+) create mode 100644 modules/feedadBidAdapter.js create mode 100644 modules/feedadBidAdapter.md create mode 100644 test/spec/modules/feedadBidAdapter_spec.js diff --git a/modules/feedadBidAdapter.js b/modules/feedadBidAdapter.js new file mode 100644 index 00000000000..1e995ee8914 --- /dev/null +++ b/modules/feedadBidAdapter.js @@ -0,0 +1,290 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER, VIDEO} from '../src/mediaTypes'; +import {ajax} from '../src/ajax'; + +/** + * Version of the FeedAd bid adapter + * @type {string} + */ +const VERSION = '1.0.0'; + +/** + * @typedef {object} FeedAdApiBidRequest + * @inner + * + * @property {number} ad_type + * @property {string} client_token + * @property {string} placement_id + * @property {string} sdk_version + * @property {boolean} app_hybrid + * + * @property {string} [app_bundle_id] + * @property {string} [app_name] + * @property {object} [custom_params] + * @property {number} [connectivity] + * @property {string} [device_adid] + * @property {string} [device_platform] + */ + +/** + * @typedef {object} FeedAdApiBidResponse + * @inner + * + * @property {string} ad - Ad HTML payload + * @property {number} cpm - number / float + * @property {string} creativeId - ID of creative for tracking + * @property {string} currency - 3-letter ISO 4217 currency-code + * @property {number} height - Height of creative returned in [].ad + * @property {boolean} netRevenue - Is the CPM net (true) or gross (false)? + * @property {string} requestId - bids[].bidId + * @property {number} ttl - Time to live for this ad + * @property {number} width - Width of creative returned in [].ad + */ + +/** + * @typedef {object} FeedAdApiTrackingParams + * @inner + * + * @property app_hybrid {boolean} + * @property client_token {string} + * @property klass {'prebid_bidWon'|'prebid_bidTimeout'} + * @property placement_id {string} + * @property prebid_auction_id {string} + * @property prebid_bid_id {string} + * @property prebid_transaction_id {string} + * @property referer {string} + * @property sdk_version {string} + * @property [app_bundle_id] {string} + * @property [app_name] {string} + * @property [device_adid] {string} + * @property [device_platform] {1|2|3} 1 - Android | 2 - iOS | 3 - Windows + */ + +/** + * Bidder network identity code + * @type {string} + */ +const BIDDER_CODE = 'feedad'; + +/** + * The media types supported by FeedAd + * @type {MediaType[]} + */ +const MEDIA_TYPES = [VIDEO, BANNER]; + +/** + * Tag for logging + * @type {string} + */ +const TAG = '[FeedAd]'; + +/** + * Pattern for valid placement IDs + * @type {RegExp} + */ +const PLACEMENT_ID_PATTERN = /^[a-z0-9][a-z0-9_-]+[a-z0-9]$/; + +const API_ENDPOINT = 'https://api.feedad.com'; +const API_PATH_BID_REQUEST = '/1/prebid/web/bids'; +const API_PATH_TRACK_REQUEST = '/1/prebid/web/events'; + +/** + * Stores temporary auction metadata + * @type {Object.} + */ +const BID_METADATA = {}; + +/** + * Checks if the bid is compatible with FeedAd. + * + * @param {BidRequest} bid - the bid to check + * @return {boolean} true if the bid is valid + */ +function isBidRequestValid(bid) { + const clientToken = utils.deepAccess(bid, 'params.clientToken'); + if (!clientToken || !isValidClientToken(clientToken)) { + utils.logWarn(TAG, "missing or invalid parameter 'clientToken'. found value:", clientToken); + return false; + } + + const placementId = utils.deepAccess(bid, 'params.placementId'); + if (!placementId || !isValidPlacementId(placementId)) { + utils.logWarn(TAG, "missing or invalid parameter 'placementId'. found value:", placementId); + return false; + } + + return true; +} + +/** + * Checks if a client token is valid + * @param {string} clientToken - the client token + * @return {boolean} true if the token is valid + */ +function isValidClientToken(clientToken) { + return typeof clientToken === 'string' && clientToken.length > 0; +} + +/** + * Checks if the given placement id is of a correct format. + * Valid IDs are words of lowercase letters from a to z and numbers from 0 to 9. + * The words can be separated by hyphens or underscores. + * Multiple separators must not follow each other. + * The whole placement ID must not be larger than 256 characters. + * + * @param placementId - the placement id to verify + * @returns if the placement ID is valid. + */ +function isValidPlacementId(placementId) { + return typeof placementId === 'string' && + placementId.length > 0 && + placementId.length <= 256 && + PLACEMENT_ID_PATTERN.test(placementId); +} + +/** + * Checks if the given media types contain unsupported settings + * @param {MediaTypes} mediaTypes - the media types to check + * @return {MediaTypes} the unsupported settings, empty when all types are supported + */ +function filterSupportedMediaTypes(mediaTypes) { + return { + banner: mediaTypes.banner, + video: mediaTypes.video && mediaTypes.video.context === 'outstream' ? mediaTypes.video : undefined, + native: undefined + }; +} + +/** + * Checks if the given media types are empty + * @param {MediaTypes} mediaTypes - the types to check + * @return {boolean} true if the types are empty + */ +function isMediaTypesEmpty(mediaTypes) { + return Object.keys(mediaTypes).every(type => mediaTypes[type] === undefined); +} + +/** + * Creates the bid request params the api expects from the prebid bid request + * @param {BidRequest} request - the validated prebid bid request + * @return {FeedAdApiBidRequest} + */ +function createApiBidRParams(request) { + return { + ad_type: 0, + client_token: request.params.clientToken, + placement_id: request.params.placementId, + sdk_version: `prebid_${VERSION}`, + app_hybrid: false, + }; +} + +/** + * Builds the bid request to the FeedAd Server + * @param {BidRequest[]} validBidRequests - all validated bid requests + * @param {object} bidderRequest - meta information + * @return {ServerRequest|ServerRequest[]} + */ +function buildRequests(validBidRequests, bidderRequest) { + if (!bidderRequest) { + return []; + } + let acceptableRequests = validBidRequests.filter(request => !isMediaTypesEmpty(filterSupportedMediaTypes(request.mediaTypes))); + if (acceptableRequests.length === 0) { + return []; + } + let data = Object.assign({}, bidderRequest, { + bids: acceptableRequests.map(req => { + req.params = createApiBidRParams(req); + return req; + }) + }); + data.bids.forEach(bid => BID_METADATA[bid.bidId] = { + referer: data.refererInfo.referer, + transactionId: bid.transactionId + }); + return { + method: 'POST', + url: `${API_ENDPOINT}${API_PATH_BID_REQUEST}`, + data, + options: { + contentType: 'application/json' + } + }; +} + +/** + * Adapts the FeedAd server response to Prebid format + * @param {ServerResponse} serverResponse - the FeedAd server response + * @param {BidRequest} request - the initial bid request + * @returns {Bid[]} the FeedAd bids + */ +function interpretResponse(serverResponse, request) { + /** + * @type FeedAdApiBidResponse[] + */ + return typeof serverResponse.body === 'string' ? JSON.parse(serverResponse.body) : serverResponse.body; +} + +/** + * Creates the parameters for the FeedAd tracking call + * @param {object} data - prebid data + * @param {'prebid_bidWon'|'prebid_bidTimeout'} klass - type of tracking call + * @return {FeedAdApiTrackingParams|null} + */ +function createTrackingParams(data, klass) { + const bidId = data.bidId || data.requestId; + if (!BID_METADATA.hasOwnProperty(bidId)) { + return null; + } + const {referer, transactionId} = BID_METADATA[bidId]; + delete BID_METADATA[bidId]; + return { + app_hybrid: false, + client_token: data.params[0].clientToken, + placement_id: data.params[0].placementId, + klass, + prebid_auction_id: data.auctionId, + prebid_bid_id: bidId, + prebid_transaction_id: transactionId, + referer, + sdk_version: VERSION + }; +} + +/** + * Creates a tracking handler for the given event type + * @param klass - the event type + * @return {Function} the tracking handler function + */ +function trackingHandlerFactory(klass) { + return (data) => { + if (!data) { + return; + } + let params = createTrackingParams(data, klass); + if (params) { + ajax(`${API_ENDPOINT}${API_PATH_TRACK_REQUEST}`, null, JSON.stringify(params), { + withCredentials: true, + method: 'POST', + contentType: 'application/json' + }); + } + } +} + +/** + * @type {BidderSpec} + */ +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: MEDIA_TYPES, + isBidRequestValid, + buildRequests, + interpretResponse, + onTimeout: trackingHandlerFactory('prebid_bidTimeout'), + onBidWon: trackingHandlerFactory('prebid_bidWon') +}; + +registerBidder(spec); diff --git a/modules/feedadBidAdapter.md b/modules/feedadBidAdapter.md new file mode 100644 index 00000000000..fd57025c29e --- /dev/null +++ b/modules/feedadBidAdapter.md @@ -0,0 +1,44 @@ +# Overview + +``` +Module Name: FeedAd Adapter +Module Type: Bidder Adapter +Maintainer: mail@feedad.com +``` + +# Description + +Prebid.JS adapter that connects to the FeedAd demand sources. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { // supports all banner sizes + sizes: [[300, 250]], + }, + video: { // supports only outstream video + context: 'outstream' + } + }, + bids: [ + { + bidder: "feedad", + params: { + clientToken: 'your-client-token' // see below for more info + placementId: 'your-placement-id' // see below for more info + } + } + ] + } + ]; +``` + +# Required Parameters + +| Parameter | Description | +| --------- | ----------- | +| `clientToken` | Your FeedAd web client token. You can view your client token inside the FeedAd admin panel. | +| `placementId` | You can choose placement IDs yourself. A placement ID should be named after the ad position inside your product. For example, if you want to display an ad inside a list of news articles, you could name it "ad-news-overview".
    A placement ID may consist of lowercase `a-z`, `0-9`, `-` and `_`. You do not have to manually create the placement IDs before using them. Just specify them within the code, and they will appear in the FeedAd admin panel after the first request.
    [Learn more](/concept/feed_ad/index.html) about Placement IDs and how they are grouped to play the same Creative. | diff --git a/test/spec/modules/feedadBidAdapter_spec.js b/test/spec/modules/feedadBidAdapter_spec.js new file mode 100644 index 00000000000..3432a40eca4 --- /dev/null +++ b/test/spec/modules/feedadBidAdapter_spec.js @@ -0,0 +1,433 @@ +import {expect} from 'chai'; +import {spec} from 'modules/feedadBidAdapter'; +import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes'; +import * as sinon from 'sinon'; + +const CODE = 'feedad'; + +describe('FeedAdAdapter', function () { + describe('Public API', function () { + it('should have the FeedAd bidder code', function () { + expect(spec.code).to.equal(CODE); + }); + it('should only support video and banner ads', function () { + expect(spec.supportedMediaTypes).to.be.a('array'); + expect(spec.supportedMediaTypes).to.include(BANNER); + expect(spec.supportedMediaTypes).to.include(VIDEO); + expect(spec.supportedMediaTypes).not.to.include(NATIVE); + }); + it('should export the BidderSpec functions', function () { + expect(spec.isBidRequestValid).to.be.a('function'); + expect(spec.buildRequests).to.be.a('function'); + expect(spec.interpretResponse).to.be.a('function'); + expect(spec.onTimeout).to.be.a('function'); + expect(spec.onBidWon).to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + it('should detect missing params', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [] + }); + expect(result).to.equal(false); + }); + it('should detect missing client token', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {placementId: 'placement'} + }); + expect(result).to.equal(false); + }); + it('should detect zero length client token', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: '', placementId: 'placement'} + }); + expect(result).to.equal(false); + }); + it('should detect missing placement id', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken'} + }); + expect(result).to.equal(false); + }); + it('should detect zero length placement id', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken', placementId: ''} + }); + expect(result).to.equal(false); + }); + it('should detect too long placement id', function () { + var placementId = ''; + for (var i = 0; i < 300; i++) { + placementId += 'a'; + } + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken', placementId} + }); + expect(result).to.equal(false); + }); + it('should detect invalid placement id', function () { + [ + 'placement id with spaces', + 'some|id', + 'PLACEMENTID', + 'placeme:ntId' + ].forEach(id => { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken', placementId: id} + }); + expect(result).to.equal(false); + }); + }); + it('should accept valid parameters', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }); + expect(result).to.equal(true); + }); + }); + + describe('buildRequests', function () { + const bidderRequest = { + refererInfo: { + referer: 'the referer' + }, + some: 'thing' + }; + + it('should accept empty lists', function () { + let result = spec.buildRequests([], bidderRequest); + expect(result).to.be.empty; + }); + it('should filter native media types', function () { + let bid = { + code: 'feedad', + mediaTypes: { + native: { + sizes: [[300, 250], [300, 600]], + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result).to.be.empty; + }); + it('should filter video media types without outstream context', function () { + let bid = { + code: 'feedad', + mediaTypes: { + video: { + context: 'instream' + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result).to.be.empty; + }); + it('should pass through outstream video media', function () { + let bid = { + code: 'feedad', + mediaTypes: { + video: { + context: 'outstream' + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.data.bids).to.be.lengthOf(1); + expect(result.data.bids[0]).to.deep.equal(bid); + }); + it('should pass through banner media', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.data.bids).to.be.lengthOf(1); + expect(result.data.bids[0]).to.deep.equal(bid); + }); + it('should detect empty media types', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: undefined, + video: undefined, + native: undefined + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result).to.be.empty; + }); + it('should use POST', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.method).to.equal('POST'); + }); + it('should use the correct URL', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.url).to.equal('https://api.feedad.com/1/prebid/web/bids'); + }); + it('should specify the content type explicitly', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.options).to.deep.equal({ + contentType: 'application/json' + }) + }); + it('should include the bidder request', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid, bid, bid], bidderRequest); + expect(result.data).to.deep.include(bidderRequest); + }); + it('should detect missing bidder request parameter', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid, bid, bid]); + expect(result).to.be.empty; + }); + }); + + describe('interpretResponse', function () { + const body = [{ + foo: 'bar', + sub: { + obj: 5 + } + }, { + bar: 'foo' + }]; + + it('should convert string bodies to JSON', function () { + let result = spec.interpretResponse({body: JSON.stringify(body)}); + expect(result).to.deep.equal(body); + }); + + it('should pass through body objects', function () { + let result = spec.interpretResponse({body}); + expect(result).to.deep.equal(body); + }); + }); + + describe('event tracking calls', function () { + const clientToken = 'clientToken'; + const placementId = 'placement id'; + const auctionId = 'the auction id'; + const bidId = 'the bid id'; + const transactionId = 'the transaction id'; + const referer = 'the referer'; + const bidderRequest = { + refererInfo: { + referer: referer + }, + some: 'thing' + }; + const bid = { + 'bidder': 'feedad', + 'params': { + 'clientToken': 'fupp', + 'placementId': 'prebid-test' + }, + 'crumbs': { + 'pubcid': '6254a85f-bded-489a-9736-83c45d45ef1d' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ + 300, + 250 + ] + ] + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': transactionId, + 'sizes': [ + [ + 300, + 250 + ] + ], + 'bidId': bidId, + 'bidderRequestId': '10739fe6fe2127', + 'auctionId': '5ac67dff-d971-4b56-84a3-345a87a1f786', + 'src': 'client', + 'bidRequestsCount': 1 + }; + const timeoutData = { + 'bidId': bidId, + 'bidder': 'feedad', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'auctionId': auctionId, + 'params': [ + { + 'clientToken': clientToken, + 'placementId': placementId + } + ], + 'timeout': 3000 + }; + const bidWonData = { + 'bidderCode': 'feedad', + 'width': 300, + 'height': 250, + 'statusMessage': 'Bid available', + 'adId': '3a4529aa05114d', + 'requestId': bidId, + 'mediaType': 'banner', + 'source': 'client', + 'cpm': 0.5, + 'ad': 'ad content', + 'ttl': 60, + 'creativeId': 'feedad-21-0', + 'netRevenue': true, + 'currency': 'EUR', + 'auctionId': auctionId, + 'responseTimestamp': 1558365914596, + 'requestTimestamp': 1558365914506, + 'bidder': 'feedad', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'timeToRespond': 90, + 'pbLg': '0.50', + 'pbMg': '0.50', + 'pbHg': '0.50', + 'pbAg': '0.50', + 'pbDg': '0.50', + 'pbCg': '', + 'size': '300x250', + 'adserverTargeting': { + 'hb_bidder': 'feedad', + 'hb_adid': '3a4529aa05114d', + 'hb_pb': '0.50', + 'hb_size': '300x250', + 'hb_source': 'client', + 'hb_format': 'banner' + }, + 'status': 'rendered', + 'params': [ + { + 'clientToken': clientToken, + 'placementId': placementId + } + ] + }; + const cases = [ + ['onTimeout', timeoutData, 'prebid_bidTimeout'], + ['onBidWon', bidWonData, 'prebid_bidWon'], + ]; + + cases.forEach(([name, data, eventKlass]) => { + let subject = spec[name]; + describe(name + ' handler', function () { + let xhr; + let requests; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = xhr => requests.push(xhr); + }); + + afterEach(function () { + xhr.restore(); + }); + + it('should do nothing on empty data', function () { + subject(undefined); + subject(null); + expect(requests.length).to.equal(0); + }); + + it('should do nothing when bid metadata is not set', function () { + subject(data); + expect(requests.length).to.equal(0); + }); + + it('should send tracking params when correct metadata was set', function () { + spec.buildRequests([bid], bidderRequest); + let expectedData = { + app_hybrid: false, + client_token: clientToken, + placement_id: placementId, + klass: eventKlass, + prebid_auction_id: auctionId, + prebid_bid_id: bidId, + prebid_transaction_id: transactionId, + referer, + sdk_version: '1.0.0' + }; + subject(data); + expect(requests.length).to.equal(1); + let call = requests[0]; + expect(call.url).to.equal('https://api.feedad.com/1/prebid/web/events'); + expect(JSON.parse(call.requestBody)).to.deep.equal(expectedData); + expect(call.method).to.equal('POST'); + expect(call.requestHeaders).to.include({'Content-Type': 'application/json;charset=utf-8'}); + }) + }); + }); + }); +}); From 6e7eb3b81a2acf60e8c0171e10a520e5b2c11d7d Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 18 Jun 2019 12:04:44 -0400 Subject: [PATCH 1287/1594] Fix #3813 move auctionEnd events so it always executes when auction completes (#3841) * move auctionEnd events so it always executes * remove some commented code --- src/auction.js | 25 +++++++++++++------------ test/spec/auctionmanager_spec.js | 11 +++++++++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/auction.js b/src/auction.js index 1d758997035..a1e8c33adfb 100644 --- a/src/auction.js +++ b/src/auction.js @@ -140,7 +140,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a clearTimeout(_timer); } - if (_callback != null) { + if (_auctionEnd === undefined) { let timedOutBidders = []; if (timedOut) { utils.logMessage(`Auction ${_auctionId} timedOut`); @@ -150,17 +150,19 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a } } - try { - _auctionStatus = AUCTION_COMPLETED; - _auctionEnd = Date.now(); - - events.emit(CONSTANTS.EVENTS.AUCTION_END, getProperties()); + _auctionStatus = AUCTION_COMPLETED; + _auctionEnd = Date.now(); - const adUnitCodes = _adUnitCodes; - const bids = _bidsReceived - .filter(utils.bind.call(adUnitsFilter, this, adUnitCodes)) - .reduce(groupByPlacement, {}); - _callback.apply($$PREBID_GLOBAL$$, [bids, timedOut]); + events.emit(CONSTANTS.EVENTS.AUCTION_END, getProperties()); + try { + if (_callback != null) { + const adUnitCodes = _adUnitCodes; + const bids = _bidsReceived + .filter(utils.bind.call(adUnitsFilter, this, adUnitCodes)) + .reduce(groupByPlacement, {}); + _callback.apply($$PREBID_GLOBAL$$, [bids, timedOut]); + _callback = null; + } } catch (e) { utils.logError('Error executing bidsBackHandler', null, e); } finally { @@ -175,7 +177,6 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a syncUsers(userSyncConfig.syncDelay); } } - _callback = null; } } diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 2d8ee562ce4..577b1bec333 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -1,4 +1,4 @@ -import { getKeyValueTargetingPairs, auctionCallbacks } from 'src/auction'; +import { getKeyValueTargetingPairs, auctionCallbacks, AUCTION_COMPLETED } from 'src/auction'; import CONSTANTS from 'src/constants.json'; import { adjustBids } from 'src/auction'; import * as auctionModule from 'src/auction'; @@ -783,7 +783,8 @@ describe('auctionmanager.js', function () { server.restore(); events.emit.restore(); }); - it('should emit BID_TIMEOUT for timed out bids', function (done) { + + it('should emit BID_TIMEOUT and AUCTION_END for timed out bids', function (done) { const spec1 = mockBidder(BIDDER_CODE, [bids[0]]); registerBidder(spec1); const spec2 = mockBidder(BIDDER_CODE1, [bids[1]]); @@ -797,6 +798,12 @@ describe('auctionmanager.js', function () { const timedOutBids = bidTimeoutCall.args[1]; assert.equal(timedOutBids.length, 1); assert.equal(timedOutBids[0].bidder, BIDDER_CODE1); + + const auctionEndCall = eventsEmitSpy.withArgs(CONSTANTS.EVENTS.AUCTION_END).getCalls()[0]; + const auctionProps = auctionEndCall.args[1]; + assert.equal(auctionProps.adUnits, adUnits); + assert.equal(auctionProps.timeout, 20); + assert.equal(auctionProps.auctionStatus, AUCTION_COMPLETED) done(); } auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: auctionCallback, cbTimeout: 20}); From bd5f2a0f18990e21e29309f4dcbad3591b0b666b Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 18 Jun 2019 12:14:39 -0400 Subject: [PATCH 1288/1594] fix import paths for various adapters (#3921) --- modules/advenueBidAdapter.js | 6 +++--- modules/bidphysicsBidAdapter.js | 2 +- modules/cedatoBidAdapter.js | 6 +++--- modules/digiTrustIdSystem.js | 2 +- modules/emx_digitalBidAdapter.js | 10 +++++----- modules/imonomyBidAdapter.js | 4 ++-- modules/loopmeBidAdapter.js | 6 +++--- modules/mgidBidAdapter.js | 4 ++-- modules/microadBidAdapter.js | 4 ++-- modules/open8BidAdapter.js | 6 +++--- modules/otmBidAdapter.js | 4 ++-- modules/prebidmanagerAnalyticsAdapter.js | 4 ++-- modules/reklamstoreBidAdapter.js | 6 +++--- modules/slimcutBidAdapter.js | 6 +++--- modules/smartrtbBidAdapter.js | 4 ++-- modules/sortableAnalyticsAdapter.js | 14 +++++++------- modules/timBidAdapter.js | 6 +++--- modules/yieldoneBidAdapter.js | 2 +- 18 files changed, 48 insertions(+), 48 deletions(-) diff --git a/modules/advenueBidAdapter.js b/modules/advenueBidAdapter.js index 3e7711cca0d..6dc5856eacb 100644 --- a/modules/advenueBidAdapter.js +++ b/modules/advenueBidAdapter.js @@ -1,6 +1,6 @@ -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; -import * as utils from 'src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; +import * as utils from '../src/utils'; const BIDDER_CODE = 'advenue'; const URL_MULTI = '//ssp.advenuemedia.co.uk/?c=o&m=multi'; diff --git a/modules/bidphysicsBidAdapter.js b/modules/bidphysicsBidAdapter.js index 260a473c631..9f1dc83d427 100644 --- a/modules/bidphysicsBidAdapter.js +++ b/modules/bidphysicsBidAdapter.js @@ -1,4 +1,4 @@ -import {registerBidder} from 'src/adapters/bidderFactory'; +import {registerBidder} from '../src/adapters/bidderFactory'; import * as utils from '../src/utils'; import {BANNER} from '../src/mediaTypes'; diff --git a/modules/cedatoBidAdapter.js b/modules/cedatoBidAdapter.js index 78bb7b45c7b..c367c57fc25 100644 --- a/modules/cedatoBidAdapter.js +++ b/modules/cedatoBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'cedato'; const BID_URL = '//h.cedatoplayer.com/hb'; diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index 07792cc49d3..454e6864846 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -11,7 +11,7 @@ // import { config } from 'src/config'; import * as utils from '../src/utils' -import { ajax } from 'src/ajax'; +import { ajax } from '../src/ajax'; import { attachIdSystem } from '../modules/userId'; // import { getGlobal } from 'src/prebidGlobal'; diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 75ce47aae0a..69e02d5c860 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -1,8 +1,8 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER, VIDEO } from 'src/mediaTypes'; -import { config } from 'src/config'; -import { Renderer } from 'src/Renderer'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import { config } from '../src/config'; +import { Renderer } from '../src/Renderer'; import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; diff --git a/modules/imonomyBidAdapter.js b/modules/imonomyBidAdapter.js index fa3ad0cfea2..9a0d29a1374 100644 --- a/modules/imonomyBidAdapter.js +++ b/modules/imonomyBidAdapter.js @@ -1,5 +1,5 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'imonomy'; const ENDPOINT = '//b.imonomy.com/openrtb/hb/00000'; diff --git a/modules/loopmeBidAdapter.js b/modules/loopmeBidAdapter.js index fb2f891d3b0..fcfe1fd0687 100644 --- a/modules/loopmeBidAdapter.js +++ b/modules/loopmeBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const LOOPME_ENDPOINT = 'https://loopme.me/api/hb'; diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index e1b15ef4b51..c6744d28f45 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -1,7 +1,7 @@ -import {registerBidder} from 'src/adapters/bidderFactory'; +import {registerBidder} from '../src/adapters/bidderFactory'; import * as utils from '../src/utils'; import * as urlUtils from '../src/url'; -import {BANNER, NATIVE} from 'src/mediaTypes'; +import {BANNER, NATIVE} from '../src/mediaTypes'; import {config} from '../src/config'; const DEFAULT_CUR = 'USD'; const BIDDER_CODE = 'mgid'; diff --git a/modules/microadBidAdapter.js b/modules/microadBidAdapter.js index d42e4053fda..391be2c465b 100644 --- a/modules/microadBidAdapter.js +++ b/modules/microadBidAdapter.js @@ -1,5 +1,5 @@ -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'microad'; diff --git a/modules/open8BidAdapter.js b/modules/open8BidAdapter.js index be616d0ec30..3c2b94a528a 100644 --- a/modules/open8BidAdapter.js +++ b/modules/open8BidAdapter.js @@ -1,8 +1,8 @@ -import { Renderer } from 'src/Renderer'; +import { Renderer } from '../src/Renderer'; import {ajax} from '../src/ajax'; import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { VIDEO, BANNER } from 'src/mediaTypes'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { VIDEO, BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'open8'; const URL = '//as.vt.open8.com/v1/control/prebid'; diff --git a/modules/otmBidAdapter.js b/modules/otmBidAdapter.js index 57ac414c7b6..ddb4d356f5c 100644 --- a/modules/otmBidAdapter.js +++ b/modules/otmBidAdapter.js @@ -1,5 +1,5 @@ -import {BANNER} from 'src/mediaTypes'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import {BANNER} from '../src/mediaTypes'; +import {registerBidder} from '../src/adapters/bidderFactory'; export const spec = { code: 'otm', diff --git a/modules/prebidmanagerAnalyticsAdapter.js b/modules/prebidmanagerAnalyticsAdapter.js index eb9ad344253..f3474abe95a 100644 --- a/modules/prebidmanagerAnalyticsAdapter.js +++ b/modules/prebidmanagerAnalyticsAdapter.js @@ -9,8 +9,8 @@ const DEFAULT_EVENT_URL = 'https://endpoint.prebidmanager.com/endpoint' const analyticsType = 'endpoint'; const analyticsName = 'Prebid Manager Analytics: '; -var utils = require('src/utils'); -var CONSTANTS = require('src/constants.json'); +var utils = require('../src/utils'); +var CONSTANTS = require('../src/constants.json'); let ajax = ajaxBuilder(0); var _VERSION = 1; diff --git a/modules/reklamstoreBidAdapter.js b/modules/reklamstoreBidAdapter.js index 49f08ab0473..2a659ec0f07 100644 --- a/modules/reklamstoreBidAdapter.js +++ b/modules/reklamstoreBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'reklamstore'; const ENDPOINT_URL = '//ads.rekmob.com/m/prebid'; diff --git a/modules/slimcutBidAdapter.js b/modules/slimcutBidAdapter.js index def490d6ab9..1f52e2cbc30 100644 --- a/modules/slimcutBidAdapter.js +++ b/modules/slimcutBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { ajax } from 'src/ajax'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { ajax } from '../src/ajax'; const BIDDER_CODE = 'slimcut'; const ENDPOINT_URL = '//sb.freeskreen.com/pbr'; diff --git a/modules/smartrtbBidAdapter.js b/modules/smartrtbBidAdapter.js index 561ce58e016..1cdef1c474b 100644 --- a/modules/smartrtbBidAdapter.js +++ b/modules/smartrtbBidAdapter.js @@ -1,5 +1,5 @@ -import * as utils from 'src/utils'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'smartrtb'; function getDomain () { diff --git a/modules/sortableAnalyticsAdapter.js b/modules/sortableAnalyticsAdapter.js index 4682dc09b49..17458065f9a 100644 --- a/modules/sortableAnalyticsAdapter.js +++ b/modules/sortableAnalyticsAdapter.js @@ -1,10 +1,10 @@ -import adapter from 'src/AnalyticsAdapter'; -import CONSTANTS from 'src/constants.json'; -import adapterManager from 'src/adapterManager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {getGlobal} from 'src/prebidGlobal'; -import { config } from 'src/config'; +import adapter from '../src/AnalyticsAdapter'; +import CONSTANTS from '../src/constants.json'; +import adapterManager from '../src/adapterManager'; +import * as utils from '../src/utils'; +import {ajax} from '../src/ajax'; +import {getGlobal} from '../src/prebidGlobal'; +import { config } from '../src/config'; const DEFAULT_PROTOCOL = 'https'; const DEFAULT_HOST = 'pa.deployads.com'; diff --git a/modules/timBidAdapter.js b/modules/timBidAdapter.js index 0539f37deef..449254671f4 100644 --- a/modules/timBidAdapter.js +++ b/modules/timBidAdapter.js @@ -1,7 +1,7 @@ -import * as utils from 'src/utils'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; import * as bidfactory from '../src/bidfactory'; -var CONSTANTS = require('src/constants.json'); +var CONSTANTS = require('../src/constants.json'); const BIDDER_CODE = 'tim'; function parseBidRequest(bidRequest) { diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index 1e6abf22838..1caf44e790f 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from '../src/utils'; import {config} from '../src/config'; import {registerBidder} from '../src/adapters/bidderFactory'; -import { Renderer } from 'src/Renderer'; +import { Renderer } from '../src/Renderer'; import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'yieldone'; From e53dad0fedbcca91dffc31279551955e8bdc9595 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 18 Jun 2019 10:49:40 -0600 Subject: [PATCH 1289/1594] add --analyze arg for webpack bundle analyzing (#3914) --- package-lock.json | 517 ++++++++++++++++++++++++++++++++++++++++------ package.json | 1 + webpack.conf.js | 35 ++-- 3 files changed, 482 insertions(+), 71 deletions(-) diff --git a/package-lock.json b/package-lock.json index d313ff22ea0..199aff8c33b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.16.0-pre", + "version": "2.20.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -922,6 +922,12 @@ } } }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -1194,6 +1200,12 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, "array-from": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", @@ -2670,6 +2682,18 @@ "callsite": "1.0.0" } }, + "bfj": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", + "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "check-types": "^7.3.0", + "hoopy": "^0.1.2", + "tryer": "^1.0.0" + } + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -3108,7 +3132,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3262,6 +3286,12 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "check-types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", + "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", + "dev": true + }, "chokidar": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", @@ -3480,7 +3510,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -3622,6 +3652,15 @@ "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -3649,6 +3688,12 @@ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", "dev": true }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -4534,6 +4579,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "dev": true + }, "electron-to-chromium": { "version": "1.3.124", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz", @@ -4585,7 +4636,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4599,7 +4650,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4615,7 +4666,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4635,7 +4686,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -5326,7 +5377,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5535,6 +5586,249 @@ "homedir-polyfill": "^1.0.1" } }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "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", + "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.5", + "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": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "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" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "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" + } + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "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=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "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", + "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==", + "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==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "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==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -5733,6 +6027,12 @@ "minimatch": "^3.0.3" } }, + "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": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -5865,7 +6165,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", "dev": true }, "flush-write-stream": { @@ -5951,6 +6251,12 @@ "samsam": "~1.1" } }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -6074,8 +6380,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6099,15 +6404,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true, - "optional": true + "dev": true }, "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, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6124,22 +6427,19 @@ "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, - "optional": true + "dev": true }, "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, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6270,8 +6570,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6285,7 +6584,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6302,7 +6600,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6311,15 +6608,13 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6340,7 +6635,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6429,8 +6723,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6444,7 +6737,6 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6540,8 +6832,7 @@ "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, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -6583,7 +6874,6 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6605,7 +6895,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6654,15 +6943,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true, - "optional": true + "dev": true } } }, @@ -7337,7 +7624,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7354,7 +7641,7 @@ "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==", + "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", "dev": true } } @@ -7764,6 +8051,16 @@ "glogg": "^1.0.0" } }, + "gzip-size": { + "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.1", + "pify": "^4.0.1" + } + }, "handlebars": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", @@ -8037,6 +8334,12 @@ "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.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", @@ -8057,7 +8360,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8286,6 +8589,12 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "ipaddr.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "dev": true + }, "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -9053,7 +9362,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9678,7 +9987,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -9691,7 +10000,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", "dev": true }, "debug": { @@ -10132,6 +10441,12 @@ } } }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, "merge-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", @@ -10141,6 +10456,12 @@ "readable-stream": "^2.0.1" } }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -10228,7 +10549,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10264,7 +10585,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10851,6 +11172,12 @@ "mimic-fn": "^1.0.0" } }, + "opener": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", + "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", + "dev": true + }, "opn": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", @@ -10872,7 +11199,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11433,6 +11760,16 @@ "integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==", "dev": true }, + "proxy-addr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -12145,7 +12482,7 @@ "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", "dev": true }, "rgb2hex": { @@ -12614,7 +12951,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { "debug": "~3.1.0", @@ -12628,7 +12965,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12651,7 +12988,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", @@ -12673,7 +13010,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12689,7 +13026,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -12701,7 +13038,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12819,7 +13156,7 @@ }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -12953,7 +13290,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13420,6 +13757,12 @@ "through2": "^2.0.3" } }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -13474,6 +13817,12 @@ "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", "dev": true }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "dev": true + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -13954,7 +14303,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14023,6 +14372,12 @@ "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=", + "dev": true + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -14565,6 +14920,50 @@ } } }, + "webpack-bundle-analyzer": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", + "integrity": "sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-walk": "^6.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.10", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, "webpack-core": { "version": "0.6.9", "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", @@ -14594,7 +14993,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { diff --git a/package.json b/package.json index 4a3d8b2c959..11d5ee5901f 100755 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "wdio-spec-reporter": "^0.1.5", "webdriverio": "^4.13.2", "webpack": "^3.0.0", + "webpack-bundle-analyzer": "^3.3.2", "webpack-stream": "^3.2.0", "yargs": "^1.3.1" }, diff --git a/webpack.conf.js b/webpack.conf.js index 9518b972b1b..61cdf82df32 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -3,12 +3,34 @@ var path = require('path'); var webpack = require('webpack'); var helpers = require('./gulpHelpers'); var RequireEnsureWithoutJsonp = require('./plugins/RequireEnsureWithoutJsonp.js'); +var { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +var argv = require('yargs').argv; // list of module names to never include in the common bundle chunk var neverBundle = [ 'AnalyticsAdapter.js' ]; +var plugins = [ + new RequireEnsureWithoutJsonp() +]; + +if (argv.analyze) { + plugins.push( + new BundleAnalyzerPlugin() + ) +} + +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, count) { + return !(count < 2 || neverBundle.indexOf(path.basename(module.resource)) !== -1) + } + }) +); + module.exports = { devtool: 'source-map', resolve: { @@ -43,16 +65,5 @@ module.exports = { } ] }, - plugins: [ - new RequireEnsureWithoutJsonp(), - - // 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, count) { - return !(count < 2 || neverBundle.indexOf(path.basename(module.resource)) !== -1) - } - }) - ] + plugins }; From f6239dea8941c957169e31ea62d1723645a0a741 Mon Sep 17 00:00:00 2001 From: Michael Rooke Date: Tue, 18 Jun 2019 12:50:17 -0400 Subject: [PATCH 1290/1594] Standardize permission bits (#3872) * Standardize the perimssion bits used for modules - Most adapters use 664 (i.e. read/write, but are not executable), but some use 775. Make all adapters use 664. * Update link in documentation --- CONTRIBUTING.md | 2 +- modules/advangelistsBidAdapter.js | 0 modules/advangelistsBidAdapter.md | 0 modules/cpmstarBidAdapter.js | 0 modules/cpmstarBidAdapter.md | 0 modules/criteoBidAdapter.js | 0 modules/criteoBidAdapter.md | 0 modules/danmarketBidAdapter.md | 0 modules/fairtradeBidAdapter.md | 0 modules/gridBidAdapter.md | 0 modules/gxoneBidAdapter.md | 0 modules/oneVideoBidAdapter.md | 0 modules/saraBidAdapter.md | 0 modules/sekindoUMBidAdapter.md | 0 modules/supply2BidAdapter.md | 0 modules/trustxBidAdapter.md | 0 modules/visxBidAdapter.js | 0 modules/visxBidAdapter.md | 0 18 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 modules/advangelistsBidAdapter.js mode change 100755 => 100644 modules/advangelistsBidAdapter.md mode change 100755 => 100644 modules/cpmstarBidAdapter.js mode change 100755 => 100644 modules/cpmstarBidAdapter.md mode change 100755 => 100644 modules/criteoBidAdapter.js mode change 100755 => 100644 modules/criteoBidAdapter.md mode change 100755 => 100644 modules/danmarketBidAdapter.md mode change 100755 => 100644 modules/fairtradeBidAdapter.md mode change 100755 => 100644 modules/gridBidAdapter.md mode change 100755 => 100644 modules/gxoneBidAdapter.md mode change 100755 => 100644 modules/oneVideoBidAdapter.md mode change 100755 => 100644 modules/saraBidAdapter.md mode change 100755 => 100644 modules/sekindoUMBidAdapter.md mode change 100755 => 100644 modules/supply2BidAdapter.md mode change 100755 => 100644 modules/trustxBidAdapter.md mode change 100755 => 100644 modules/visxBidAdapter.js mode change 100755 => 100644 modules/visxBidAdapter.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b82b249fa36..9c00a2bf51a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ commit your changes, and [open a pull request](https://help.github.com/articles/ master branch. Pull requests must have 80% code coverage before beign considered for merge. -Additional details about the process can be found [here](./pr_review.md). +Additional details about the process can be found [here](./PR_REVIEW.md). ## Issues [prebid.org](http://prebid.org/) contains documentation that may help answer questions you have about using Prebid.js. diff --git a/modules/advangelistsBidAdapter.js b/modules/advangelistsBidAdapter.js old mode 100755 new mode 100644 diff --git a/modules/advangelistsBidAdapter.md b/modules/advangelistsBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/cpmstarBidAdapter.js b/modules/cpmstarBidAdapter.js old mode 100755 new mode 100644 diff --git a/modules/cpmstarBidAdapter.md b/modules/cpmstarBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js old mode 100755 new mode 100644 diff --git a/modules/criteoBidAdapter.md b/modules/criteoBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/danmarketBidAdapter.md b/modules/danmarketBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/fairtradeBidAdapter.md b/modules/fairtradeBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/gridBidAdapter.md b/modules/gridBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/gxoneBidAdapter.md b/modules/gxoneBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/saraBidAdapter.md b/modules/saraBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/sekindoUMBidAdapter.md b/modules/sekindoUMBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/supply2BidAdapter.md b/modules/supply2BidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/trustxBidAdapter.md b/modules/trustxBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js old mode 100755 new mode 100644 diff --git a/modules/visxBidAdapter.md b/modules/visxBidAdapter.md old mode 100755 new mode 100644 From 6baa819e85a92a907b641b10b9e8f17ae04d68ad Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 18 Jun 2019 15:45:48 -0400 Subject: [PATCH 1291/1594] Prebid 2.20.0 release --- package-lock.json | 2933 +++++++++++++++++++++++++++------------------ package.json | 2 +- 2 files changed, 1758 insertions(+), 1177 deletions(-) diff --git a/package-lock.json b/package-lock.json index 199aff8c33b..4c03303a050 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.20.0-pre", + "version": "2.20.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,18 +14,18 @@ } }, "@babel/core": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.3.tgz", - "integrity": "sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", + "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.0", - "@babel/helpers": "^7.4.3", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", + "@babel/generator": "^7.4.4", + "@babel/helpers": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.5", + "@babel/types": "^7.4.4", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -36,12 +36,12 @@ } }, "@babel/generator": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", - "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", "dev": true, "requires": { - "@babel/types": "^7.4.0", + "@babel/types": "^7.4.4", "jsesc": "^2.5.1", "lodash": "^4.17.11", "source-map": "^0.5.0", @@ -68,24 +68,24 @@ } }, "@babel/helper-call-delegate": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.0.tgz", - "integrity": "sha512-SdqDfbVdNQCBp3WhK2mNdDvHd3BD6qbmIc43CAyjnsfCmgHMeqgDcM3BzY2lchi7HBJGJ2CVdynLWbezaE4mmQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", + "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.4.0", - "@babel/traverse": "^7.4.0", - "@babel/types": "^7.4.0" + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/helper-define-map": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.0.tgz", - "integrity": "sha512-wAhQ9HdnLIywERVcSvX40CEJwKdAa1ID4neI9NXQPDOHwwA+57DqwLiPEVy2AIyWzAk0CQ8qx4awO0VUURwLtA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", + "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.4.0", + "@babel/types": "^7.4.4", "lodash": "^4.17.11" } }, @@ -120,12 +120,12 @@ } }, "@babel/helper-hoist-variables": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.0.tgz", - "integrity": "sha512-/NErCuoe/et17IlAQFKWM24qtyYYie7sFIrW/tIQXpck6vAu2hhtYYsKLBWQV+BQZMbcIYPU/QMYuTufrY4aQw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", + "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", "dev": true, "requires": { - "@babel/types": "^7.4.0" + "@babel/types": "^7.4.4" } }, "@babel/helper-member-expression-to-functions": { @@ -147,16 +147,16 @@ } }, "@babel/helper-module-transforms": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.3.tgz", - "integrity": "sha512-H88T9IySZW25anu5uqyaC1DaQre7ofM+joZtAaO2F8NBdFfupH0SZ4gKjgSFVcvtx/aAirqA9L9Clio2heYbZA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", + "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/template": "^7.2.2", - "@babel/types": "^7.2.2", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.4.4", "lodash": "^4.17.11" } }, @@ -176,9 +176,9 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.3.tgz", - "integrity": "sha512-hnoq5u96pLCfgjXuj8ZLX3QQ+6nAulS+zSgi6HulUwFbEruRAKwbGLU5OvXkE14L8XW6XsQEKsIDfgthKLRAyA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", + "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", "dev": true, "requires": { "lodash": "^4.17.11" @@ -198,15 +198,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.0.tgz", - "integrity": "sha512-PVwCVnWWAgnal+kJ+ZSAphzyl58XrFeSKSAJRiqg5QToTsjL+Xu1f9+RJ+d+Q0aPhPfBGaYfkox66k86thxNSg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", + "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.0.0", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.4.0", - "@babel/types": "^7.4.0" + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/helper-simple-access": { @@ -220,12 +220,12 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz", - "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", "dev": true, "requires": { - "@babel/types": "^7.4.0" + "@babel/types": "^7.4.4" } }, "@babel/helper-wrap-function": { @@ -241,14 +241,14 @@ } }, "@babel/helpers": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.3.tgz", - "integrity": "sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", "dev": true, "requires": { - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0" + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/highlight": { @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", - "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -290,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.3.tgz", - "integrity": "sha512-xC//6DNSSHVjq8O2ge0dyYlhshsH4T7XdCVoxbi5HzLYWfsC5ooFlJjrXk8RcAT+hjHAK9UjBXdylzSoDK3t4g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", + "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -310,13 +310,13 @@ } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.0.tgz", - "integrity": "sha512-h/KjEZ3nK9wv1P1FSNb9G079jXrNYR0Ko+7XkOx85+gM24iZbPn0rh4vCftk+5QKY7y1uByFataBTmX7irEF1w==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", + "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", + "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" } }, @@ -366,9 +366,9 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.0.tgz", - "integrity": "sha512-EeaFdCeUULM+GPFEsf7pFcNSxM7hYjoj5fiYbyuiXobW4JhFnjAv9OWzNwHyHcKoPNpAfeRDuW6VyaXEDUBa7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", + "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -386,9 +386,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.0.tgz", - "integrity": "sha512-AWyt3k+fBXQqt2qb9r97tn3iBwFpiv9xdAiG+Gr2HpAZpuayvbL55yWrsV3MyHvXk/4vmSiedhDRl1YI2Iy5nQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", + "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -396,18 +396,18 @@ } }, "@babel/plugin-transform-classes": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.3.tgz", - "integrity": "sha512-PUaIKyFUDtG6jF5DUJOfkBdwAS/kFFV3XFk7Nn0a6vR7ZT8jYw5cGtIlat77wcnd0C6ViGqo/wyNf4ZHytF/nQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", + "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.0", + "@babel/helper-define-map": "^7.4.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.0", - "@babel/helper-split-export-declaration": "^7.4.0", + "@babel/helper-replace-supers": "^7.4.4", + "@babel/helper-split-export-declaration": "^7.4.4", "globals": "^11.1.0" } }, @@ -421,22 +421,22 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.3.tgz", - "integrity": "sha512-rVTLLZpydDFDyN4qnXdzwoVpk1oaXHIvPEOkOLyr88o7oHxVc/LyrnDx+amuBWGOwUb7D1s/uLsKBNTx08htZg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", + "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.3.tgz", - "integrity": "sha512-9Arc2I0AGynzXRR/oPdSALv3k0rM38IMFyto7kOCwb5F9sLUt2Ykdo3V9yUPR+Bgr4kb6bVEyLkPEiBhzcTeoA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", + "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.3", + "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" } }, @@ -460,18 +460,18 @@ } }, "@babel/plugin-transform-for-of": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.3.tgz", - "integrity": "sha512-UselcZPwVWNSURnqcfpnxtMehrb8wjXYOimlYQPBnup/Zld426YzIhNEvuRsEWVHfESIECGrxoI6L5QqzuLH5Q==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", + "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-function-name": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.3.tgz", - "integrity": "sha512-uT5J/3qI/8vACBR9I1GlAuU/JqBtWdfCrynuOkrWG6nCDieZd5przB1vfP59FRHBZQ9DC2IUfqr/xKqzOD5x0A==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", + "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -507,23 +507,23 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.3.tgz", - "integrity": "sha512-sMP4JqOTbMJMimqsSZwYWsMjppD+KRyDIUVW91pd7td0dZKAvPmhCaxhOzkzLParKwgQc7bdL9UNv+rpJB0HfA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", + "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.4.3", + "@babel/helper-module-transforms": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-simple-access": "^7.1.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.0.tgz", - "integrity": "sha512-gjPdHmqiNhVoBqus5qK60mWPp1CmYWp/tkh11mvb0rrys01HycEGD7NvvSoKXlWEfSM9TcL36CpsK8ElsADptQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", + "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.4.0", + "@babel/helper-hoist-variables": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0" } }, @@ -538,18 +538,18 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.2.tgz", - "integrity": "sha512-NsAuliSwkL3WO2dzWTOL1oZJHm0TM8ZY8ZSxk2ANyKkt5SQlToGA4pzctmq1BEjoacurdwZ3xp2dCQWJkME0gQ==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", + "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", "dev": true, "requires": { - "regexp-tree": "^0.1.0" + "regexp-tree": "^0.1.6" } }, "@babel/plugin-transform-new-target": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.0.tgz", - "integrity": "sha512-6ZKNgMQmQmrEX/ncuCwnnw1yVGoaOW5KpxNhoWI7pCQdA0uZ0HqHGqenCUIENAnxRjy2WwNQ30gfGdIgqJXXqw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", + "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -566,12 +566,12 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.3.tgz", - "integrity": "sha512-ULJYC2Vnw96/zdotCZkMGr2QVfKpIT/4/K+xWWY0MbOJyMZuk660BGkr3bEKWQrrciwz6xpmft39nA4BF7hJuA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", + "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.4.0", + "@babel/helper-call-delegate": "^7.4.4", "@babel/helper-get-function-arity": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0" } @@ -586,12 +586,12 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.3.tgz", - "integrity": "sha512-kEzotPuOpv6/iSlHroCDydPkKYw7tiJGKlmYp6iJn4a6C/+b2FdttlJsLKYxolYHgotTJ5G5UY5h0qey5ka3+A==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", + "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", "dev": true, "requires": { - "regenerator-transform": "^0.13.4" + "regenerator-transform": "^0.14.0" } }, "@babel/plugin-transform-reserved-words": { @@ -632,9 +632,9 @@ } }, "@babel/plugin-transform-template-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz", - "integrity": "sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", + "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -651,104 +651,104 @@ } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.3.tgz", - "integrity": "sha512-lnSNgkVjL8EMtnE8eSS7t2ku8qvKH3eqNf/IwIfnSPUqzgqYmRwzdsQWv4mNQAN9Nuo6Gz1Y0a4CSmdpu1Pp6g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", + "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.3", + "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" } }, "@babel/preset-env": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.3.tgz", - "integrity": "sha512-FYbZdV12yHdJU5Z70cEg0f6lvtpZ8jFSDakTm7WXeJbLXh4R0ztGEu/SW7G1nJ2ZvKwDhz8YrbA84eYyprmGqw==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", + "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.3", + "@babel/plugin-proposal-object-rest-spread": "^7.4.4", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-syntax-async-generators": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.0", + "@babel/plugin-transform-async-to-generator": "^7.4.4", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.0", - "@babel/plugin-transform-classes": "^7.4.3", + "@babel/plugin-transform-block-scoping": "^7.4.4", + "@babel/plugin-transform-classes": "^7.4.4", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.3", - "@babel/plugin-transform-dotall-regex": "^7.4.3", + "@babel/plugin-transform-destructuring": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/plugin-transform-duplicate-keys": "^7.2.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.3", - "@babel/plugin-transform-function-name": "^7.4.3", + "@babel/plugin-transform-for-of": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.4.4", "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.3", - "@babel/plugin-transform-modules-systemjs": "^7.4.0", + "@babel/plugin-transform-modules-commonjs": "^7.4.4", + "@babel/plugin-transform-modules-systemjs": "^7.4.4", "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.2", - "@babel/plugin-transform-new-target": "^7.4.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", + "@babel/plugin-transform-new-target": "^7.4.4", "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.4.3", + "@babel/plugin-transform-parameters": "^7.4.4", "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.3", + "@babel/plugin-transform-regenerator": "^7.4.5", "@babel/plugin-transform-reserved-words": "^7.2.0", "@babel/plugin-transform-shorthand-properties": "^7.2.0", "@babel/plugin-transform-spread": "^7.2.0", "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.3", - "@babel/types": "^7.4.0", - "browserslist": "^4.5.2", - "core-js-compat": "^3.0.0", + "@babel/plugin-transform-unicode-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", "invariant": "^2.2.2", "js-levenshtein": "^1.1.3", "semver": "^5.5.0" } }, "@babel/template": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz", - "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.0", - "@babel/types": "^7.4.0" + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/traverse": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz", - "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.0", + "@babel/generator": "^7.4.4", "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/types": "^7.4.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", - "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -840,9 +840,9 @@ } }, "@sinonjs/samsam": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.1.tgz", - "integrity": "sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", + "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", "dev": true, "requires": { "@sinonjs/commons": "^1.0.2", @@ -873,13 +873,13 @@ "dev": true }, "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "dev": true, "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" } }, "acorn": { @@ -935,9 +935,9 @@ "dev": true }, "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { "es6-promisify": "^5.0.0" @@ -990,13 +990,10 @@ "dev": true }, "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" - } + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true }, "ansi-escapes": { "version": "3.2.0", @@ -1194,6 +1191,12 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1212,6 +1215,16 @@ "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", "dev": true }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", @@ -1247,6 +1260,18 @@ } } }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -1311,11 +1336,12 @@ } }, "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { + "object-assign": "^4.1.1", "util": "0.10.3" }, "dependencies": { @@ -1361,29 +1387,21 @@ "dev": true }, "async-done": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", - "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.2", - "process-nextick-args": "^1.0.7", + "process-nextick-args": "^2.0.0", "stream-exhaust": "^1.0.1" - }, - "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 - } } }, "async-each": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.2.tgz", - "integrity": "sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==", + "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 }, "async-limiter": { @@ -1715,15 +1733,15 @@ } }, "babel-loader": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz", - "integrity": "sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", + "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", "dev": true, "requires": { "find-cache-dir": "^2.0.0", "loader-utils": "^1.0.2", "mkdirp": "^0.5.1", - "util.promisify": "^1.0.0" + "pify": "^4.0.1" } }, "babel-messages": { @@ -2568,9 +2586,9 @@ "dev": true }, "bail": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.4.tgz", + "integrity": "sha512-S8vuDB4w6YpRhICUDET3guPlQpaJl7od94tpZ0Fvnyp+MKW/HyDTcRDck+29C9g+d/qQHnddRH3+94kZdrW0Ww==", "dev": true }, "balanced-match": { @@ -2729,9 +2747,9 @@ "dev": true }, "bluebird": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", - "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", "dev": true }, "bn.js": { @@ -2753,27 +2771,27 @@ } }, "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, "requires": { - "bytes": "3.0.0", + "bytes": "3.1.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" }, "dependencies": { "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, "debug": { @@ -2785,13 +2803,17 @@ "ms": "2.0.0" } }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" } }, "ms": { @@ -2800,17 +2822,29 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "unpipe": "1.0.0" } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true } } }, @@ -2954,14 +2988,14 @@ } }, "browserslist": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.4.tgz", - "integrity": "sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", + "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000955", - "electron-to-chromium": "^1.3.122", - "node-releases": "^1.1.13" + "caniuse-lite": "^1.0.30000975", + "electron-to-chromium": "^1.3.164", + "node-releases": "^1.1.23" } }, "browserstack": { @@ -2974,9 +3008,9 @@ } }, "browserstack-local": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.3.7.tgz", - "integrity": "sha512-ilZlmiy7XYJxsztYan7XueHVr3Ix9EVh/mCiYN1G53wRPEW/hg1KMsseM6UExzVbexEqFEfwjkBLeFlSqxh+bQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", + "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1", @@ -3001,14 +3035,13 @@ } }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", "dev": true, "requires": { "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "ieee754": "^1.1.4" } }, "buffer-alloc": { @@ -3132,7 +3165,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3174,9 +3207,9 @@ "dev": true }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "camelcase-keys": { @@ -3198,9 +3231,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000957", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000957.tgz", - "integrity": "sha512-8wxNrjAzyiHcLXN/iunskqQnJquQQ6VX8JHfW5kLgAPRSiSuKZiNfmIkP5j7jgyXqAQBSoXyJxfnbCFS0ThSiQ==", + "version": "1.0.30000975", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", + "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", "dev": true }, "caseless": { @@ -3210,9 +3243,9 @@ "dev": true }, "ccount": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.4.tgz", + "integrity": "sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w==", "dev": true }, "center-align": { @@ -3251,27 +3284,27 @@ } }, "character-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz", + "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==", "dev": true }, "character-entities-html4": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.3.tgz", + "integrity": "sha512-SwnyZ7jQBCRHELk9zf2CN5AnGEc2nA+uKMZLHvcqhpPprjkYhiLn0DywMHgN5ttFZuITMATbh68M6VIVKwJbcg==", "dev": true }, "character-entities-legacy": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz", + "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==", "dev": true }, "character-reference-invalid": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz", + "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==", "dev": true }, "chardet": { @@ -3293,9 +3326,9 @@ "dev": true }, "chokidar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", - "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -3367,14 +3400,31 @@ "dev": true }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" + }, + "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 + }, + "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" + } + } } }, "clone": { @@ -3405,9 +3455,9 @@ "dev": true }, "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "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, "requires": { "inherits": "^2.0.1", @@ -3428,9 +3478,9 @@ "dev": true }, "collapse-white-space": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.5.tgz", + "integrity": "sha512-703bOOmytCYAX9cXYqoikYIx6twmFCXsnzRQheBcTG3nzKYBR4P/+wkYeH+Mvj7qUz8zZDtdyzbxfnEi/kYzRQ==", "dev": true }, "collection-map": { @@ -3491,27 +3541,24 @@ } }, "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, "comma-separated-tokens": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", - "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "dev": true, - "requires": { - "trim": "0.0.1" - } + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.7.tgz", + "integrity": "sha512-Jrx3xsP4pPv4AwJUDWY9wOXGtwPXARej6Xd99h4TUGotmf8APuquKMpK+dnD3UgyxK7OEWaisjZz+3b5jtL6xQ==", + "dev": true }, "commander": { - "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true }, "commondir": { @@ -3527,9 +3574,9 @@ "dev": true }, "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, "component-inherit": { @@ -3597,14 +3644,14 @@ } }, "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, "requires": { "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", "utils-merge": "1.0.1" }, "dependencies": { @@ -3711,40 +3758,33 @@ } }, "core-js": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", - "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==" }, "core-js-compat": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.0.1.tgz", - "integrity": "sha512-2pC3e+Ht/1/gD7Sim/sqzvRplMiRnFQVlPpDVaHtY9l7zZP7knamr3VRD6NyGfHd84MrDC0tAM9ulNxYMW0T3g==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", + "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", "dev": true, "requires": { - "browserslist": "^4.5.4", - "core-js": "3.0.1", - "core-js-pure": "3.0.1", - "semver": "^6.0.0" + "browserslist": "^4.6.2", + "core-js-pure": "3.1.4", + "semver": "^6.1.1" }, "dependencies": { - "core-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", - "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", - "dev": true - }, "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", "dev": true } } }, "core-js-pure": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.0.1.tgz", - "integrity": "sha512-mSxeQ6IghKW3MoyF4cz19GJ1cMm7761ON+WObSyLfTu/Jn3x7w4NwNFnrZxgl4MTSvYYepVLNuRtlB4loMwJ5g==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.1.4.tgz", + "integrity": "sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA==", "dev": true }, "core-util-is": { @@ -3754,9 +3794,9 @@ "dev": true }, "coveralls": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.3.tgz", - "integrity": "sha512-viNfeGlda2zJr8Gj1zqXpDMRjw9uM54p7wzZdvLRyOgnAfCe974Dq4veZkjJdxQXbmdppu6flEajFYseHYaUhg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.4.tgz", + "integrity": "sha512-eyqUWA/7RT0JagiL0tThVhjbIjoiEUyWCjtUJoOPcWoeofP5WK/jb2OJYoBFrR6DvplR+AxOyuBqk4JHkk5ykA==", "dev": true, "requires": { "growl": "~> 1.10.0", @@ -3774,18 +3814,6 @@ "dev": true, "requires": { "buffer": "^5.1.0" - }, - "dependencies": { - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - } } }, "crc32-stream": { @@ -3836,12 +3864,14 @@ } }, "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=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } @@ -3921,12 +3951,13 @@ "dev": true }, "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "requires": { - "es5-ext": "^0.10.9" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, "dashdash": { @@ -4161,9 +4192,9 @@ "dev": true }, "detab": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", - "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.2.tgz", + "integrity": "sha512-Q57yPrxScy816TTE1P/uLRXLDKjXhvYTbfxS/e6lPD+YrqghbsMlGB9nQzj/zVtSPaF0DFPSdO916EWO4sQUyQ==", "dev": true, "requires": { "repeat-string": "^1.5.4" @@ -4324,12 +4355,62 @@ "yargs": "^9.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=", + "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.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.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.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "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.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "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.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -4339,12 +4420,36 @@ "locate-path": "^2.0.0" } }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "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 + }, + "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 }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -4375,6 +4480,32 @@ "path-exists": "^3.0.0" } }, + "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.0.0" + } + }, + "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 + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -4442,24 +4573,17 @@ "path-type": "^2.0.0" } }, - "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" - } + "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": "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" - } + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true }, "yargs": { "version": "9.0.1", @@ -4493,6 +4617,15 @@ } } } + }, + "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" + } } } }, @@ -4580,15 +4713,15 @@ "dev": true }, "ejs": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", - "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", + "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", "dev": true }, "electron-to-chromium": { - "version": "1.3.124", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz", - "integrity": "sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w==", + "version": "1.3.164", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", + "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", "dev": true }, "elliptic": { @@ -4607,9 +4740,9 @@ } }, "emoji-regex": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", - "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "emojis-list": { @@ -4636,7 +4769,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4650,7 +4783,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4666,7 +4799,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4683,10 +4816,16 @@ "yeast": "0.1.2" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4785,9 +4924,9 @@ } }, "es5-ext": { - "version": "0.10.49", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.49.tgz", - "integrity": "sha512-3NMEhi57E31qdzmYp2jwRArIUsj1HI/RxbQ4bgnSB+AIKIxsAmTiK83bYMifIcpWvEc3P1X30DhUKOqEtF/kvg==", + "version": "0.10.50", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", + "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", "dev": true, "requires": { "es6-iterator": "~2.0.3", @@ -4827,9 +4966,9 @@ } }, "es6-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", - "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", + "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 }, "es6-promisify": { @@ -4865,14 +5004,14 @@ } }, "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, "requires": { "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.1" } }, @@ -4989,6 +5128,17 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "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.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -5052,9 +5202,9 @@ } }, "eslint-module-utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", - "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", + "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", "dev": true, "requires": { "debug": "^2.6.8", @@ -5131,21 +5281,22 @@ } }, "eslint-plugin-import": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", - "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", + "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", "dev": true, "requires": { + "array-includes": "^3.0.3", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.3.0", + "eslint-module-utils": "^2.4.0", "has": "^1.0.3", "lodash": "^4.17.11", "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.9.0" + "resolve": "^1.11.0" }, "dependencies": { "debug": { @@ -5377,7 +5528,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5399,9 +5550,9 @@ } }, "eventemitter3": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", "dev": true }, "events": { @@ -5435,19 +5586,6 @@ "strip-eof": "^1.0.0" }, "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -5456,16 +5594,6 @@ "requires": { "pump": "^3.0.0" } - }, - "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" - } } } }, @@ -5624,40 +5752,6 @@ "vary": "~1.1.2" }, "dependencies": { - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - }, "cookie": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", @@ -5673,21 +5767,6 @@ "ms": "2.0.0" } }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "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" - } - }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -5701,39 +5780,12 @@ "toidentifier": "1.0.0" } }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", - "dev": true - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true, - "requires": { - "mime-db": "1.40.0" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -5746,24 +5798,6 @@ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true }, - "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==", - "dev": true - }, - "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==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -5793,39 +5827,11 @@ } } }, - "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==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "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==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } } } }, @@ -6057,17 +6063,17 @@ } }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.1", + "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", "unpipe": "~1.0.0" }, "dependencies": { @@ -6121,9 +6127,9 @@ } }, "fined": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz", - "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==", + "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", @@ -6139,6 +6145,23 @@ "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, "flat-cache": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", @@ -6165,7 +6188,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { @@ -6359,40 +6382,36 @@ "dev": true }, "fsevents": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", - "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" }, "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "dev": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6402,14 +6421,12 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "bundled": true, "dev": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -6418,71 +6435,61 @@ }, "chownr": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "dev": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "dev": true, "optional": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.1.1", + "bundled": true, "dev": true, "optional": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "bundled": true, "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6491,15 +6498,13 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6515,8 +6520,7 @@ }, "glob": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6530,15 +6534,13 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6547,8 +6549,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6557,8 +6558,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6568,21 +6568,18 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, "dev": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "bundled": true, "dev": true, "optional": 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=", + "bundled": true, "dev": true, "requires": { "number-is-nan": "^1.0.0" @@ -6590,15 +6587,13 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -6606,14 +6601,12 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "bundled": true, "dev": true }, "minipass": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "bundled": true, "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -6622,8 +6615,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6632,36 +6624,32 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "dev": true, "requires": { "minimist": "0.0.8" } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "bundled": true, "dev": true, "optional": true }, "needle": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", - "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", + "version": "2.3.0", + "bundled": true, "dev": true, "optional": true, "requires": { - "debug": "^2.1.2", + "debug": "^4.1.0", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, "node-pre-gyp": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz", - "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", + "version": "0.12.0", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6679,8 +6667,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6689,16 +6676,14 @@ } }, "npm-bundled": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz", - "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", + "version": "1.0.6", + "bundled": true, "dev": true, "optional": true }, "npm-packlist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.2.0.tgz", - "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", + "version": "1.4.1", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6708,8 +6693,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6721,21 +6705,18 @@ }, "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=", + "bundled": true, "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "dev": true, "requires": { "wrappy": "1" @@ -6743,22 +6724,19 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true, "optional": true }, "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=", + "bundled": true, "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6768,22 +6746,19 @@ }, "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=", + "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "bundled": true, "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6795,8 +6770,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "dev": true, "optional": true } @@ -6804,8 +6778,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6820,8 +6793,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6830,49 +6802,42 @@ }, "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==", + "bundled": true, "dev": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, "dev": true, "optional": true }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "5.7.0", + "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "dev": true, "requires": { "code-point-at": "^1.0.0", @@ -6882,8 +6847,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==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6892,8 +6856,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -6901,15 +6864,13 @@ }, "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=", + "bundled": true, "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6924,15 +6885,13 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6941,22 +6900,20 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, "dev": true }, "yallist": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "bundled": true, "dev": true } } }, "fun-hooks": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.2.tgz", - "integrity": "sha512-Bbhqg3zj/joiHsmU9z/DBPofMN8yN4P7m2cE4sqZqaL+C6YcAXKjwa7Cu8rUs3roBiAhgWwQOAALZZodpmBglw==" + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.3.tgz", + "integrity": "sha512-MC/zsGf+duq8lI6xym+H8HuL6DE1fLyE90FRzU/j2lTDmjDJ//+KC7M8vLzG9y/mhkLOH5u9wK4QEf3lBqIo4w==" }, "function-bind": { "version": "1.1.1", @@ -6980,9 +6937,9 @@ } }, "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==", + "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 }, "get-func-name": { @@ -7051,12 +7008,20 @@ "dev": true, "requires": { "emoji-regex": ">=6.0.0 <=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.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -7181,9 +7146,9 @@ } }, "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "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 }, "globals-docs": { @@ -7264,23 +7229,43 @@ "dev": true }, "gulp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", - "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, "requires": { - "glob-watcher": "^5.0.0", - "gulp-cli": "^2.0.0", - "undertaker": "^1.0.0", + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", "vinyl-fs": "^3.0.0" }, "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" + } + }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -7291,10 +7276,16 @@ "pinkie-promise": "^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 + }, "gulp-cli": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.1.0.tgz", - "integrity": "sha512-txzgdFVlEPShBZus6JJyGyKJoBVDq6Do0ZQgIgx5RAsmhNVTDjymmOxpQvo3c20m66FldilS68ZXj2Q9w5dKbA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", + "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -7317,6 +7308,30 @@ "yargs": "^7.1.0" } }, + "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 + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -7395,6 +7410,23 @@ "read-pkg": "^1.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 + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -7410,6 +7442,12 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", @@ -7624,7 +7662,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7641,7 +7679,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -8062,9 +8100,9 @@ } }, "handlebars": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", - "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -8253,15 +8291,15 @@ } }, "hast-util-is-element": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.2.tgz", - "integrity": "sha512-4MEtyofNi3ZunPFrp9NpTQdNPN24xvLX3M+Lr/RGgPX6TLi+wR4/DqeoyQ7lwWcfUp4aevdt4RR0r7ZQPFbHxw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.3.tgz", + "integrity": "sha512-C62CVn7jbjp89yOhhy7vrkSaB7Vk906Gtcw/Ihd+Iufnq+2pwOZjdPmpzpKLWJXPJBMDX3wXg4FqmdOayPcewA==", "dev": true }, "hast-util-sanitize": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.0.tgz", - "integrity": "sha512-rQeetoD08jHmDOUYN6h9vTuE0hQN4wymhtkQZ6whHtcjaLpjw5RYAbcdxx9cMgMWERDsSs79UpqHuBLlUHKeOw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.1.tgz", + "integrity": "sha512-AIeKHuHx0Wk45nSkGVa2/ujQYTksnDl8gmmKo/mwQi7ag7IBZ8cM3nJ2G86SajbjGP/HRpud6kMkPtcM2i0Tlw==", "dev": true, "requires": { "xtend": "^4.0.1" @@ -8284,24 +8322,32 @@ "stringify-entities": "^1.0.1", "unist-util-is": "^2.0.0", "xtend": "^4.0.1" + }, + "dependencies": { + "unist-util-is": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.3.tgz", + "integrity": "sha512-4WbQX2iwfr/+PfM4U3zd2VNXY+dWtZsN1fLnWEi2QQXA4qyDYAZcDMfXUX0Cu6XZUHHAO9q4nyxxLT4Awk1qUA==", + "dev": true + } } }, "hast-util-whitespace": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.2.tgz", - "integrity": "sha512-4JT8B0HKPHBMFZdDQzexjxwhKx9TrpV/+uelvmqlPu8RqqDrnNIEHDtDZCmgE+4YmcFAtKVPLmnY3dQGRaN53A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.3.tgz", + "integrity": "sha512-AlkYiLTTwPOyxZ8axq2/bCwRUPjIPBfrHkXuCR92B38b3lSdU22R5F/Z4DL6a2kxWpekWq1w6Nj48tWat6GeRA==", "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": { - "version": "9.15.6", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.6.tgz", - "integrity": "sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==", + "version": "9.15.8", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz", + "integrity": "sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA==", "dev": true }, "hmac-drbg": { @@ -8347,9 +8393,9 @@ "dev": true }, "html-void-elements": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.3.tgz", - "integrity": "sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.4.tgz", + "integrity": "sha512-yMk3naGPLrfvUV9TdDbuYXngh/TpHbA6TrOw3HL9kS8yhwx7i309BReNg7CbAJXGE+UMJ6je5OqJ7lC63o6YuQ==", "dev": true }, "http-cache-semantics": { @@ -8360,7 +8406,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8368,20 +8414,12 @@ "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" - }, - "dependencies": { - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - } } }, "http-parser-js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", - "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", "dev": true }, "http-proxy": { @@ -8531,22 +8569,6 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "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", @@ -8584,9 +8606,9 @@ } }, "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=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "ipaddr.js": { @@ -8626,9 +8648,9 @@ } }, "is-alphabetical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", - "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", + "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==", "dev": true }, "is-alphanumeric": { @@ -8638,15 +8660,21 @@ "dev": true }, "is-alphanumerical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", - "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", + "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", "dev": true, "requires": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8701,9 +8729,9 @@ "dev": true }, "is-decimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz", + "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==", "dev": true }, "is-descriptor": { @@ -8768,13 +8796,16 @@ } }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "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 + }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true }, "is-glob": { "version": "4.0.1", @@ -8786,9 +8817,9 @@ } }, "is-hexadecimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz", + "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==", "dev": true }, "is-negated-glob": { @@ -8944,9 +8975,9 @@ "dev": true }, "is-whitespace-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", - "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.3.tgz", + "integrity": "sha512-SNPgMLz9JzPccD3nPctcj8sZlX9DAMJSKH8bP7Z6bohCwuNgX8xbWr1eTAYXX9Vpi/aSn8Y1akL9WgM3t43YNQ==", "dev": true }, "is-windows": { @@ -8956,9 +8987,9 @@ "dev": true }, "is-word-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", - "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.3.tgz", + "integrity": "sha512-0wfcrFgOOOBdgRNT9H33xe6Zi6yhX/uoc4U8NBZGeQQB0ctU1dnlNTyL9JM2646bHDTpsDm1Brb3VPoCIMrd/A==", "dev": true }, "is-wsl": { @@ -9324,6 +9355,12 @@ "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", "dev": true }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -9362,7 +9399,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9396,9 +9433,9 @@ }, "dependencies": { "mime": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", - "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, "rimraf": { @@ -9639,12 +9676,12 @@ } }, "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "^2.0.0" } }, "lcov-parse": { @@ -9864,6 +9901,12 @@ "lodash._objecttypes": "~2.4.1" } }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, "lodash.defaults": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", @@ -9987,7 +10030,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -10000,7 +10043,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true }, "debug": { @@ -10037,9 +10080,9 @@ "dev": true }, "longest-streak": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.3.tgz", + "integrity": "sha512-9lz5IVdpwsKLMzQi0MQ+oD9EA0mIGcWYP7jXMTZVXP8D42PwuAk+M/HBFYQoxt1G5OR8m7aSIgb1UymfWGBWEw==", "dev": true }, "loose-envify": { @@ -10120,6 +10163,15 @@ "kind-of": "^6.0.2" } }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -10148,15 +10200,15 @@ } }, "markdown-escapes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.3.tgz", + "integrity": "sha512-XUi5HJhhV5R74k8/0H2oCbCiYf/u4cO/rX8tnGkRvrqhsr5BRNU6Mg0yt/8UIx1iIS8220BNJsDb7XnILhLepw==", "dev": true }, "markdown-table": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", - "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", "dev": true }, "matchdep": { @@ -10212,18 +10264,18 @@ } }, "mdast-util-compact": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz", - "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz", + "integrity": "sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w==", "dev": true, "requires": { "unist-util-visit": "^1.1.0" } }, "mdast-util-definitions": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.3.tgz", - "integrity": "sha512-P6wpRO8YVQ1iv30maMc93NLh7COvufglBE8/ldcOyYmk5EbfF0YeqlLgtqP/FOBU501Kqar1x5wYWwB3Nga74g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.4.tgz", + "integrity": "sha512-HfUArPog1j4Z78Xlzy9Q4aHLnrF/7fb57cooTHypyGoe2XFNbcx/kWZDoOz+ra8CkUzvg3+VHV434yqEd1DRmA==", "dev": true, "requires": { "unist-util-visit": "^1.0.0" @@ -10258,9 +10310,9 @@ } }, "mdast-util-to-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz", - "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.6.tgz", + "integrity": "sha512-868pp48gUPmZIhfKrLbaDneuzGiw3OTDjHc5M1kAepR2CWBJ+HpEsm252K4aXdiP5coVZaJPOqGtVU6Po8xnXg==", "dev": true }, "mdast-util-toc": { @@ -10275,6 +10327,12 @@ "unist-util-visit": "^1.1.0" }, "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 + }, "github-slugger": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.1.tgz", @@ -10283,6 +10341,12 @@ "requires": { "emoji-regex": ">=6.0.0 <=6.1.1" } + }, + "unist-util-is": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.3.tgz", + "integrity": "sha512-4WbQX2iwfr/+PfM4U3zd2VNXY+dWtZsN1fLnWEi2QQXA4qyDYAZcDMfXUX0Cu6XZUHHAO9q4nyxxLT4Awk1qUA==", + "dev": true } } }, @@ -10299,12 +10363,22 @@ "dev": true }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "dependencies": { + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + } } }, "memoizee": { @@ -10333,6 +10407,12 @@ "readable-stream": "^2.0.1" } }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -10500,24 +10580,24 @@ "dev": true }, "mime-db": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", - "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", "dev": true }, "mime-types": { - "version": "2.1.22", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", - "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "dev": true, "requires": { - "mime-db": "~1.38.0" + "mime-db": "1.40.0" } }, "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==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "mimic-response": { @@ -10549,7 +10629,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10585,7 +10665,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10610,6 +10690,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", @@ -10639,6 +10725,12 @@ "path-is-absolute": "^1.0.0" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -10720,9 +10812,9 @@ } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "multipipe": { @@ -10782,9 +10874,9 @@ "dev": true }, "nan": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", - "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true, "optional": true }, @@ -10820,15 +10912,15 @@ "dev": true }, "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", "dev": true }, "neo-async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, "next-tick": { @@ -10844,15 +10936,15 @@ "dev": true }, "nise": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.10.tgz", - "integrity": "sha512-sa0RRbj53dovjc7wombHmVli9ZihXbXCQ2uH3TNm03DyvOSIQbxg+pbqDKrk2oxMK1rtLGVlKxcB9rrc6X5YjA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz", + "integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==", "dev": true, "requires": { "@sinonjs/formatio": "^3.1.0", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", - "lolex": "^2.3.2", + "lolex": "^4.1.0", "path-to-regexp": "^1.7.0" }, "dependencies": { @@ -10867,17 +10959,27 @@ } }, "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz", + "integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==", "dev": true } } }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, "node-libs-browser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", - "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", + "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.1.1", @@ -10890,7 +10992,7 @@ "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", + "path-browserify": "0.0.1", "process": "^0.11.10", "punycode": "^1.2.4", "querystring-es3": "^0.2.0", @@ -10902,21 +11004,41 @@ "tty-browserify": "0.0.0", "url": "^0.11.0", "util": "^0.11.0", - "vm-browserify": "0.0.4" + "vm-browserify": "^1.0.1" }, "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "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 + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } } } }, "node-releases": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.14.tgz", - "integrity": "sha512-d58EpVZRhQE60kWiWUaaPlK9dyC4zg3ZoMcHcky2d4hDksyQj0rUozwInOl0C66mBsqo01Tuns8AvxnL5S7PKg==", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", + "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", "dev": true, "requires": { "semver": "^5.3.0" @@ -10976,6 +11098,23 @@ "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", "dev": true }, + "npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -11085,6 +11224,18 @@ "isobject": "^3.0.0" } }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -11170,6 +11321,14 @@ "dev": true, "requires": { "mimic-fn": "^1.0.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 + } } }, "opener": { @@ -11199,7 +11358,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11247,31 +11406,14 @@ "dev": true }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - }, - "dependencies": { - "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.0.1", - "get-stream": "^3.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" - } - } + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" } }, "os-tmpdir": { @@ -11286,6 +11428,12 @@ "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", "dev": true }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -11361,21 +11509,144 @@ } }, "parse-domain": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.7.tgz", - "integrity": "sha512-yb0VWRwDCe96ML49b3xg+4wScbocpIrFSAdkml8eKq/deH3FiFPBpsC6RTC9ZUtnDhInmXPfNIHsN/v62+TAMA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.1.tgz", + "integrity": "sha512-k/tkc7tfcoGfaUOCG5DuPNX+dt6UBqRWU9EtR0rA9esi5GpOY0OGEgprfylmYx8pykQbdBTYHLaM/UwFHXuZKA==", "dev": true, "requires": { "chai": "^4.2.0", "got": "^8.3.2", "mkdirp": "^0.5.1", - "mocha": "^5.2.0" + "mocha": "^6.1.4", + "npm-run-all": "^4.1.5" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mocha": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", + "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", + "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + } + } } }, "parse-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.1.tgz", - "integrity": "sha512-NBWYLQm1KSoDKk7GAHyioLTvCZ5QjdH/ASBBQTD3iLiAWJXS5bg1jEWI8nIJ+vgVvsceBVBcDGRWSo0KVQBvvg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", "dev": true, "requires": { "character-entities": "^1.0.0", @@ -11498,9 +11769,9 @@ } }, "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, "pascalcase": { @@ -11510,9 +11781,9 @@ "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=", + "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": { @@ -11646,6 +11917,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "pidtree": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", + "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", + "dev": true + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -11686,6 +11963,17 @@ "arr-diff": "^4.0.0", "arr-union": "^3.1.0", "extend-shallow": "^3.0.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" + } + } } }, "pluralize": { @@ -11792,9 +12080,9 @@ "dev": true }, "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "version": "1.1.32", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", + "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", "dev": true }, "public-encrypt": { @@ -11812,9 +12100,9 @@ } }, "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "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", @@ -11830,6 +12118,18 @@ "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" + }, + "dependencies": { + "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" + } + } } }, "punycode": { @@ -11923,9 +12223,9 @@ } }, "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true }, "raw-body": { @@ -12064,9 +12364,9 @@ "dev": true }, "regenerate-unicode-properties": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", - "integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", "dev": true, "requires": { "regenerate": "^1.4.0" @@ -12078,9 +12378,9 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz", - "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", + "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", "dev": true, "requires": { "private": "^0.1.6" @@ -12106,9 +12406,9 @@ } }, "regexp-tree": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.5.tgz", - "integrity": "sha512-nUmxvfJyAODw+0B13hj8CFVAxhe7fDEAgJgaotBu3nnR+IgGgZq59YedJP5VYTlkEfqjuK6TuRpnymKdatLZfQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", + "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", "dev": true }, "regexpp": { @@ -12201,18 +12501,18 @@ } }, "remark-reference-links": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.3.tgz", - "integrity": "sha512-Q9d7JaK5r0JDBo3TInfrodBuI3xulI8htCr8jlX+0oXosF3GaebJbo5y228VYFoV6xJ+syDukkUGMKNlwSJWjQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.4.tgz", + "integrity": "sha512-+2X8hwSQqxG4tvjYZNrTcEC+bXp8shQvwRGG6J/rnFTvBoU4G0BBviZoqKGZizLh/DG+0gSYhiDDWCqyxXW1iQ==", "dev": true, "requires": { "unist-util-visit": "^1.0.0" } }, "remark-slug": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.1.tgz", - "integrity": "sha512-r591rdoDPJkSSAVvEaTVUkqbMp7c7AyZfif14V0Dp66GQkOHzaPAS6wyhawSbqpS0ZdTnfJS+TltFoxzi6bdIA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.2.tgz", + "integrity": "sha512-DWX+Kd9iKycqyD+/B+gEFO3jjnt7Yg1O05lygYSNTe5i5PIxxxPjp5qPBDxPIzp5wreF7+1ROCwRgjEcqmzr3A==", "dev": true, "requires": { "github-slugger": "^1.0.0", @@ -12393,9 +12693,9 @@ "dev": true }, "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=", + "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": { @@ -12415,9 +12715,9 @@ "dev": true }, "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -12480,9 +12780,9 @@ "dev": true }, "rfdc": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", "dev": true }, "rgb2hex": { @@ -12680,16 +12980,81 @@ } }, "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } + "parseurl": "~1.3.3", + "send": "0.17.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" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "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", + "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" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + } + } }, "set-blocking": { "version": "2.0.0", @@ -12757,6 +13122,18 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, "shelljs": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", @@ -12816,14 +13193,6 @@ "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - } } }, "snapdragon": { @@ -12951,7 +13320,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -12965,7 +13334,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -12988,7 +13357,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -13007,10 +13376,16 @@ "to-array": "0.1.4" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13026,7 +13401,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13035,10 +13410,16 @@ "isarray": "2.0.1" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13108,13 +13489,10 @@ "dev": true }, "space-separated-tokens": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", - "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "dev": true, - "requires": { - "trim": "0.0.1" - } + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.4.tgz", + "integrity": "sha512-UyhMSmeIqZrQn2UdjYpxEkwY9JUrn8pP+7L4f91zRzOQuI8MF1FGLfYU9DKCYeLdo7LXMxwrX5zKFy7eeeVHuA==", + "dev": true }, "sparkles": { "version": "1.0.1", @@ -13156,7 +13534,7 @@ }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13202,9 +13580,9 @@ "dev": true }, "state-toggle": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.2.tgz", + "integrity": "sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==", "dev": true }, "static-extend": { @@ -13229,9 +13607,9 @@ } }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, "stealthy-require": { @@ -13290,7 +13668,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13368,14 +13746,41 @@ "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "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" + }, + "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 + }, + "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" + } + } + } + }, + "string.prototype.padend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", + "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.4.3", + "function-bind": "^1.0.2" } }, "string_decoder": { @@ -13481,39 +13886,6 @@ "lodash": "^4.17.4", "slice-ansi": "1.0.0", "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" - } - } } }, "tapable": { @@ -13788,9 +14160,9 @@ "dev": true }, "trim-lines": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.1.tgz", - "integrity": "sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.2.tgz", + "integrity": "sha512-3GOuyNeTqk3FAqc3jOJtw7FTjYl94XBR5aD9QnDbK/T4CA9sW/J0l9RoaRPE9wyPP7NF331qnHnvJFBJ+IDkmQ==", "dev": true }, "trim-newlines": { @@ -13806,15 +14178,15 @@ "dev": true }, "trim-trailing-lines": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz", + "integrity": "sha512-MUjYItdrqqj2zpcHFTkMa9WAv4JHTI6gnRQGPFLrt5L9a6tRMiDnIqYl8JBvu2d2Tc3lWJKQwlGCp0K8AvCM+Q==", "dev": true }, "trough": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", - "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.4.tgz", + "integrity": "sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==", "dev": true }, "tryer": { @@ -13844,6 +14216,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/type/-/type-1.0.1.tgz", + "integrity": "sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw==", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -13860,13 +14238,13 @@ "dev": true }, "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "mime-types": "~2.1.24" } }, "typedarray": { @@ -13876,21 +14254,15 @@ "dev": true }, "uglify-js": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.4.tgz", - "integrity": "sha512-GpKo28q/7Bm5BcX9vOu4S46FwisbPbAmkkqPnGIpKvKTM96I85N6XHQV+k4I6FA2wxgLhcsSyHoNhzucwCflvA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", "dev": true, "requires": { "commander": "~2.20.0", "source-map": "~0.6.1" }, "dependencies": { - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -13944,12 +14316,6 @@ "yargs": "~3.10.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 - }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", @@ -14006,9 +14372,9 @@ "dev": true }, "unherit": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", - "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", + "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -14103,36 +14469,36 @@ } }, "unist-builder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.3.tgz", - "integrity": "sha512-/KB8GEaoeHRyIqClL+Kam+Y5NWJ6yEiPsAfv1M+O1p+aKGgjR89WwoEHKTyOj17L6kAlqtKpAgv2nWvdbQDEig==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.4.tgz", + "integrity": "sha512-v6xbUPP7ILrT15fHGrNyHc1Xda8H3xVhP7/HAIotHOhVPjH5dCXA097C3Rry1Q2O+HbOLCao4hfPB+EYEjHgVg==", "dev": true, "requires": { "object-assign": "^4.1.0" } }, "unist-util-generated": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.3.tgz", - "integrity": "sha512-qlPeDqnQnd84KIqwphzOR+l02cxjDzvEYEBl84EjmKRrX4eUmjyAo8xJv1SCDhJqNjyHRnBMZWNKAiBtXE6hBg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.4.tgz", + "integrity": "sha512-SA7Sys3h3X4AlVnxHdvN/qYdr4R38HzihoEVY2Q2BZu8NHWDnw5OGcC/tXWjQfd4iG+M6qRFNIRGqJmp2ez4Ww==", "dev": true }, "unist-util-is": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz", - "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", "dev": true }, "unist-util-position": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.2.tgz", - "integrity": "sha512-npmFu92l/+b1Ao6uGP4I1WFz9hsKv7qleZ4aliw6x0RVu6A9A3tAf57NMpFfzQ02jxRtJZuRn+C8xWT7GWnH0g==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.3.tgz", + "integrity": "sha512-28EpCBYFvnMeq9y/4w6pbnFmCUfzlsc41NJui5c51hOFjBA1fejcwc+5W4z2+0ECVbScG3dURS3JTVqwenzqZw==", "dev": true }, "unist-util-remove-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", - "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.3.tgz", + "integrity": "sha512-CtszTlOjP2sBGYc2zcKA/CvNdTdEs3ozbiJ63IPBxh8iZg42SCCb8m04f8z2+V1aSk5a7BxbZKEdoDjadmBkWA==", "dev": true, "requires": { "unist-util-visit": "^1.1.0" @@ -14145,21 +14511,21 @@ "dev": true }, "unist-util-visit": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", - "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", "dev": true, "requires": { "unist-util-visit-parents": "^2.0.0" } }, "unist-util-visit-parents": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", - "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", "dev": true, "requires": { - "unist-util-is": "^2.1.2" + "unist-util-is": "^3.0.0" } }, "unpipe": { @@ -14254,12 +14620,12 @@ "dev": true }, "url-parse": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", - "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", "dev": true, "requires": { - "querystringify": "^2.0.0", + "querystringify": "^2.1.1", "requires-port": "^1.0.0" }, "dependencies": { @@ -14303,7 +14669,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14311,12 +14677,16 @@ } }, "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", + "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "object.entries": "^1.1.0", + "safe-buffer": "^5.1.2" } }, "util-deprecate": { @@ -14325,16 +14695,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -14348,9 +14708,9 @@ "dev": true }, "v8flags": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", - "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", "dev": true, "requires": { "homedir-polyfill": "^1.0.1" @@ -14402,9 +14762,9 @@ } }, "vfile-location": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.4.tgz", - "integrity": "sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.5.tgz", + "integrity": "sha512-Pa1ey0OzYBkLPxPZI3d9E+S4BmvfVwNAAXrrqGbwTVXWaX2p9kM1zZ+n35UtVM06shmWKH4RPRN8KI80qE3wNQ==", "dev": true }, "vfile-message": { @@ -14435,6 +14795,26 @@ "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.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -14447,15 +14827,15 @@ } }, "vfile-sort": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.0.tgz", - "integrity": "sha512-RgxLXVWrJBWb2GuP8FsSkqK7HmbjXjnI8qx3nD6NTWhsWaelaKvJuxfh1F1d1lkCPD7imo4zzi8cf6IOMgaTnQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.1.tgz", + "integrity": "sha512-5dt7xEhC44h0uRQKhbM2JAe0z/naHphIZlMOygtMBM9Nn0pZdaX5fshhwWit9wvsuP8t/wp43nTDRRErO1WK8g==", "dev": true }, "vfile-statistics": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.2.tgz", - "integrity": "sha512-16wAC9eEGXdsD35LX9m/iXCRIZyX5LIrDgDtAF92rbATSqsBRbC4n05e0Rj5vt3XRpcKu0UJeWnTxWsSyvNZ+w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.3.tgz", + "integrity": "sha512-CstaK/ebTz1W3Qp41Bt9Lj/2DmumFsCwC2sKahDNSPh0mPh7/UyMLCoU8ZBX34CRU0d61B4W41yIFsV0NKMZeA==", "dev": true }, "vinyl": { @@ -14533,13 +14913,10 @@ } }, "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": { - "indexof": "0.0.1" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "dev": true }, "void-elements": { "version": "2.0.1", @@ -14653,12 +15030,6 @@ "wgxpath": "~1.0.0" }, "dependencies": { - "ejs": { - "version": "2.5.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", - "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", - "dev": true - }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -14724,12 +15095,6 @@ "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "dev": true }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, "async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", @@ -14739,6 +15104,62 @@ "lodash": "^4.17.11" } }, + "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.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.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.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "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.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "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.0.1", + "get-stream": "^3.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" + } + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -14754,18 +15175,33 @@ "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 + }, "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": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "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 }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -14778,6 +15214,15 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -14800,6 +15245,32 @@ "path-exists": "^3.0.0" } }, + "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.0.0" + } + }, + "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 + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -14869,24 +15340,11 @@ "read-pkg": "^2.0.0" } }, - "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" - } + "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 }, "supports-color": { "version": "4.5.0", @@ -14897,6 +15355,12 @@ "has-flag": "^2.0.0" } }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -14917,6 +15381,15 @@ "y18n": "^3.2.1", "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" + } } } }, @@ -14947,10 +15420,10 @@ "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "ejs": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz", + "integrity": "sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==", "dev": true }, "ws": { @@ -14993,7 +15466,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -15007,9 +15480,9 @@ }, "dependencies": { "mime": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", - "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true } } @@ -15125,6 +15598,17 @@ "pako": "~0.2.0" } }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", @@ -15335,12 +15819,6 @@ "object-assign": "^4.0.1" } }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, "memory-fs": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", @@ -15424,6 +15902,12 @@ "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", @@ -15509,6 +15993,15 @@ "replace-ext": "0.0.1" } }, + "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": { + "indexof": "0.0.1" + } + }, "watchpack": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", @@ -15551,12 +16044,6 @@ "webpack-core": "~0.6.9" } }, - "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 - }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", @@ -15578,12 +16065,13 @@ } }, "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", + "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", "dev": true, "requires": { - "http-parser-js": ">=0.4.0", + "http-parser-js": ">=0.4.0 <0.4.11", + "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" } }, @@ -15614,6 +16102,21 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "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 + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -15628,6 +16131,28 @@ "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, "wrappy": { @@ -15675,9 +16200,9 @@ "dev": true }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { @@ -15693,12 +16218,68 @@ "dev": true }, "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, + "dependencies": { + "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 + }, + "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 + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } }, "yeast": { diff --git a/package.json b/package.json index 11d5ee5901f..0a68cb6d5d9 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.20.0-pre", + "version": "2.20.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 7e5bda28964b461d4b539478637b0d8a8df57664 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 18 Jun 2019 15:58:57 -0400 Subject: [PATCH 1292/1594] increment pre version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4c03303a050..1d224cebc76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.20.0", + "version": "2.21.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0a68cb6d5d9..a4e2985e1bd 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.20.0", + "version": "2.21.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 92fb453b1962f2ccf057d9cf965dc74e7306ac17 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 18 Jun 2019 13:12:06 -0700 Subject: [PATCH 1293/1594] always secure (#3922) changed serevr end-point to HTTPS changed user-sync end-point to HTTPS changed imp.secure to 1 hard-coded Also corrected test case --- modules/pubmaticBidAdapter.js | 6 +++--- test/spec/modules/pubmaticBidAdapter_spec.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 1f9ea06cad2..245ca3e60c9 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -5,8 +5,8 @@ import {config} from '../src/config'; const BIDDER_CODE = 'pubmatic'; const LOG_WARN_PREFIX = 'PubMatic: '; -const ENDPOINT = '//hbopenbid.pubmatic.com/translator?source=prebid-client'; -const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; +const ENDPOINT = 'https://hbopenbid.pubmatic.com/translator?source=prebid-client'; +const USYNCURL = 'https://ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const DEFAULT_CURRENCY = 'USD'; const AUCTION_TYPE = 1; const PUBMATIC_DIGITRUST_KEY = 'nFIn8aLzbd'; @@ -513,7 +513,7 @@ function _createImpressionObject(bid, conf) { id: bid.bidId, tagid: bid.params.adUnit || undefined, bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor), - secure: window.location.protocol === 'https:' ? 1 : 0, + secure: 1, ext: { pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) }, diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 6126c0f9fd8..289e0f461ec 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -695,7 +695,7 @@ describe('PubMatic adapter', function () { it('Endpoint checking', function () { let request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//hbopenbid.pubmatic.com/translator?source=prebid-client'); + expect(request.url).to.equal('https://hbopenbid.pubmatic.com/translator?source=prebid-client'); expect(request.method).to.equal('POST'); }); From ce095e02e90ca58be59d9bcd5daa435ee65d1faf Mon Sep 17 00:00:00 2001 From: susyt Date: Thu, 20 Jun 2019 08:15:40 -0700 Subject: [PATCH 1294/1594] GumGum: adds tradedesk id param (#3896) * adds tradedesk id param * adds more tests * removes only from test spec * linting fix * updates one of the unit tests --- modules/gumgumBidAdapter.js | 10 +++- test/spec/modules/gumgumBidAdapter_spec.js | 54 ++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 8c2b6415505..496941e3c1f 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -75,6 +75,14 @@ function getWrapperCode(wrapper, data) { return wrapper.replace('AD_JSON', window.btoa(JSON.stringify(data))) } +function _getTradeDeskIDParam(bidRequest) { + const unifiedIdObj = {}; + if (bidRequest.userId && bidRequest.userId.tdid) { + unifiedIdObj.tdid = bidRequest.userId.tdid; + } + return unifiedIdObj; +} + // TODO: use getConfig() function _getDigiTrustQueryParams() { function getDigiTrustId () { @@ -170,7 +178,7 @@ function buildRequests (validBidRequests, bidderRequest) { sizes: bidRequest.sizes, url: BID_ENDPOINT, method: 'GET', - data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams()) + data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) }) }); return bids; diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index c067f50fa56..a7a588afd13 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -80,6 +80,35 @@ describe('gumgumAdapter', function () { expect(request.method).to.equal('GET'); expect(request.id).to.equal('30b31c1838de1e'); }); + it('should correctly set the request paramters depending on params field', function () { + const request = Object.assign({}, bidRequests[0]); + delete request.params; + request.params = { + 'inScreen': '10433394', + 'bidfloor': 0.05 + }; + const bidRequest = spec.buildRequests([request])[0]; + expect(bidRequest.data.pi).to.equal(2); + expect(bidRequest.data).to.include.any.keys('t'); + expect(bidRequest.data).to.include.any.keys('fp'); + }); + it('should correctly set the request paramters depending on params field', function () { + const request = Object.assign({}, bidRequests[0]); + delete request.params; + request.params = { + 'ICV': '10433395' + }; + const bidRequest = spec.buildRequests([request])[0]; + expect(bidRequest.data.pi).to.equal(5); + expect(bidRequest.data).to.include.any.keys('ni'); + }); + it('should not add additional parameters depending on params field', function () { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.data).to.not.include.any.keys('ni'); + expect(request.data).to.not.include.any.keys('t'); + expect(request.data).to.not.include.any.keys('eAdBuyId'); + expect(request.data).to.not.include.any.keys('adBuyId'); + }); it('should add consent parameters if gdprConsent is present', function () { const gdprConsent = { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', gdprApplies: true }; const fakeBidRequest = { gdprConsent: gdprConsent }; @@ -93,6 +122,31 @@ describe('gumgumAdapter', function () { const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; expect(bidRequest.data).to.not.include.any.keys('gdprConsent') }); + it('should add a tdid parameter if request contains unified id from TradeDesk', function () { + const unifiedId = { + 'userId': { + 'tdid': 'tradedesk-id' + } + } + const request = Object.assign(unifiedId, bidRequests[0]); + const bidRequest = spec.buildRequests([request])[0]; + expect(bidRequest.data.tdid).to.eq(unifiedId.userId.tdid); + }); + it('should not add a tdid parameter if unified id is not found', function () { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.data).to.not.include.any.keys('tdid'); + }); + it('should send ns parameter if browser contains navigator.connection property', function () { + const bidRequest = spec.buildRequests(bidRequests)[0]; + const connection = window.navigator && window.navigator.connection; + if (connection) { + const downlink = connection.downlink || connection.bandwidth; + expect(bidRequest.data).to.include.any.keys('ns'); + expect(bidRequest.data.ns).to.eq(Math.round(downlink * 1024)); + } else { + expect(bidRequest.data).to.not.include.any.keys('ns'); + } + }); }) describe('interpretResponse', function () { From bbd73ce0689949877a0c37c4279a55e944aa92f9 Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Fri, 21 Jun 2019 17:23:57 -0400 Subject: [PATCH 1295/1594] Digitrust support in PBS bid adapter and Rubicon bid adapter (#3935) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * - Get digitrust data from bid request - Send UnifiedID and PubCommon data to OpenRTB * - Replace lodash with Prebid util functions - Updated pubcommon id location when sending to OpenRTB * Remove pref property when sending DigiTrust to OpenRTB * Updated tests to check new user external id locations in request * Remove use of array find from unit test --- modules/prebidServerBidAdapter/index.js | 64 ++++++----- modules/rubiconBidAdapter.js | 107 +++++++++++------- src/utils.js | 17 +++ .../modules/prebidServerBidAdapter_spec.js | 58 +++++----- 4 files changed, 146 insertions(+), 100 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 586d78ed2ca..028f02d9662 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -232,20 +232,24 @@ function doClientSideSyncs(bidders) { }); } -function _getDigiTrustQueryParams() { - function getDigiTrustId() { - let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); +function _getDigiTrustQueryParams(bidRequest = {}) { + function getDigiTrustId(bidRequest) { + const bidRequestDigitrust = utils.deepAccess(bidRequest, 'bids.0.userId.digitrustid.data'); + if (bidRequestDigitrust) { + return bidRequestDigitrust; + } + + const digiTrustUser = config.getConfig('digiTrustId'); return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; } - let digiTrustId = getDigiTrustId(); + let digiTrustId = getDigiTrustId(bidRequest); // Verify there is an ID and this user has not opted out if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { return null; } return { id: digiTrustId.id, - keyv: digiTrustId.keyv, - pref: 0 + keyv: digiTrustId.keyv }; } @@ -334,7 +338,7 @@ const LEGACY_PROTOCOL = { _appendSiteAppDevice(request); - let digiTrust = _getDigiTrustQueryParams(); + let digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); if (digiTrust) { request.digiTrust = digiTrust; } @@ -521,26 +525,39 @@ const OPEN_RTB_PROTOCOL = { _appendSiteAppDevice(request); - const digiTrust = _getDigiTrustQueryParams(); + const digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); if (digiTrust) { - request.user = { ext: { digitrust: digiTrust } }; + utils.deepSetValue(request, 'user.ext.digitrust', digiTrust); } if (!utils.isEmpty(aliases)) { request.ext.prebid.aliases = aliases; } - if (bidRequests && bidRequests[0].userId && typeof bidRequests[0].userId === 'object') { - if (!request.user) { - request.user = {}; - } - if (!request.user.ext) { - request.user.ext = {} + const bidUserId = utils.deepAccess(bidRequests, '0.bids.0.userId'); + if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid)) { + utils.deepSetValue(request, 'user.ext.eids', []); + + if (bidUserId.tdid) { + request.user.ext.eids.push({ + source: 'adserver.org', + uids: [{ + id: bidUserId.tdid, + ext: { + rtiPartner: 'TDID' + } + }] + }); } - if (!request.user.ext.tpid) { - request.user.ext.tpid = {} + + if (bidUserId.pubcid) { + request.user.ext.eids.push({ + source: 'pubcommon', + uids: [{ + id: bidUserId.pubcid, + }] + }); } - Object.assign(request.user.ext.tpid, bidRequests[0].userId); } if (bidRequests && bidRequests[0].gdprConsent) { @@ -560,16 +577,7 @@ const OPEN_RTB_PROTOCOL = { request.regs = { ext: { gdpr: gdprApplies } }; } - let consentString = bidRequests[0].gdprConsent.consentString; - if (request.user) { - if (request.user.ext) { - request.user.ext.consent = consentString; - } else { - request.user.ext = { consent: consentString }; - } - } else { - request.user = { ext: { consent: consentString } }; - } + utils.deepSetValue(request, 'user.ext.consent', bidRequests[0].gdprConsent.consentString); } return request; diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index a0e9c89a221..abeebd2e1b2 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -14,6 +14,18 @@ export const FASTLANE_ENDPOINT = '//fastlane.rubiconproject.com/a/api/fastlane.j export const VIDEO_ENDPOINT = '//prebid-server.rubiconproject.com/openrtb2/auction'; export const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html'; +const DIGITRUST_PROP_NAMES = { + FASTLANE: { + id: 'dt.id', + keyv: 'dt.keyv', + pref: 'dt.pref' + }, + PREBID_SERVER: { + id: 'id', + keyv: 'keyv' + } +}; + var sizeMap = { 1: '468x60', 2: '728x90', @@ -170,13 +182,9 @@ export const spec = { addVideoParameters(data, bidRequest); - const digiTrust = getDigiTrustQueryParams(); + const digiTrust = _getDigiTrustQueryParams(bidRequest, 'PREBID_SERVER'); if (digiTrust) { - data.user = { - ext: { - digitrust: digiTrust - } - }; + utils.deepSetValue(data, 'user.ext.digitrust', digiTrust); } if (bidderRequest.gdprConsent) { @@ -196,15 +204,32 @@ export const spec = { data.regs = {ext: {gdpr: gdprApplies}}; } - const consentString = bidderRequest.gdprConsent.consentString; - if (data.user) { - if (data.user.ext) { - data.user.ext.consent = consentString; - } else { - data.user.ext = {consent: consentString}; - } - } else { - data.user = {ext: {consent: consentString}}; + utils.deepSetValue(data, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + } + + if (bidRequest.userId && typeof bidRequest.userId === 'object' && + (bidRequest.userId.tdid || bidRequest.userId.pubcid)) { + utils.deepSetValue(data, 'user.ext.eids', []); + + if (bidRequest.userId.tdid) { + data.user.ext.eids.push({ + source: 'adserver.org', + uids: [{ + id: bidRequest.userId.tdid, + ext: { + rtiPartner: 'TDID' + } + }] + }); + } + + if (bidRequest.userId.pubcid) { + data.user.ext.eids.push({ + source: 'pubcommon', + uids: [{ + id: bidRequest.userId.pubcid, + }] + }); } } @@ -406,10 +431,8 @@ export const spec = { } // digitrust properties - const digitrustParams = _getDigiTrustQueryParams(); - Object.keys(digitrustParams).forEach(paramKey => { - data[paramKey] = digitrustParams[paramKey]; - }); + const digitrustParams = _getDigiTrustQueryParams(bidRequest, 'FASTLANE'); + Object.assign(data, digitrustParams); return data; }, @@ -600,22 +623,36 @@ function _getScreenResolution() { return [window.screen.width, window.screen.height].join('x'); } -function _getDigiTrustQueryParams() { +function _getDigiTrustQueryParams(bidRequest = {}, endpointName) { + if (!endpointName || !DIGITRUST_PROP_NAMES[endpointName]) { + return null; + } + const propNames = DIGITRUST_PROP_NAMES[endpointName]; + function getDigiTrustId() { - let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); + const bidRequestDigitrust = utils.deepAccess(bidRequest, 'userId.digitrustid.data'); + if (bidRequestDigitrust) { + return bidRequestDigitrust; + } + + let digiTrustUser = (window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'}))); return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; } let digiTrustId = getDigiTrustId(); // Verify there is an ID and this user has not opted out if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { - return []; + return null; } - return { - 'dt.id': digiTrustId.id, - 'dt.keyv': digiTrustId.keyv, - 'dt.pref': 0 + + const digiTrustQueryParams = { + [propNames.id]: digiTrustId.id, + [propNames.keyv]: digiTrustId.keyv }; + if (propNames.pref) { + digiTrustQueryParams[propNames.pref] = 0; + } + return digiTrustQueryParams; } /** @@ -677,24 +714,6 @@ function parseSizes(bid, mediaType) { return masSizeOrdering(sizes); } -function getDigiTrustQueryParams() { - function getDigiTrustId() { - let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); - return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; - } - - let digiTrustId = getDigiTrustId(); - // Verify there is an ID and this user has not opted out - if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { - return null; - } - return { - id: digiTrustId.id, - keyv: digiTrustId.keyv, - pref: 0 - }; -} - /** * @param {Object} data * @param bidRequest diff --git a/src/utils.js b/src/utils.js index ea80e970786..b5a46d174f4 100644 --- a/src/utils.js +++ b/src/utils.js @@ -986,6 +986,23 @@ export function deepAccess(obj, path) { return obj; } +/** + * @param {Object} obj The object to set a deep property value in + * @param {(string|Array.)} path Object path to the value you would like ot set. + * @param {*} value The value you would like to set + */ +export function deepSetValue(obj, path, value) { + let i; + path = path.split('.'); + for (i = 0; i < path.length - 1; i++) { + if (i !== path.length - 1 && typeof obj[path[i]] === 'undefined') { + obj[path[i]] = {}; + } + obj = obj[path[i]]; + } + obj[path[i]] = value; +} + /** * Returns content for a friendly iframe to execute a URL in script tag * @param {string} url URL to be executed in a script tag in a friendly iframe diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 47d0084d86a..e2a3a5b111a 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -513,38 +513,37 @@ describe('S2S Adapter', function () { }); it('adds digitrust id is present and user is not optout', function () { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + + let consentConfig = { s2sConfig: ortb2Config }; + config.setConfig(consentConfig); + let digiTrustObj = { - success: true, - identity: { - privacy: { - optout: false - }, - id: 'testId', - keyv: 'testKeyV' - } + privacy: { + optout: false + }, + id: 'testId', + keyv: 'testKeyV' }; - window.DigiTrust = { - getUser: () => digiTrustObj - }; + let digiTrustBidRequest = utils.deepClone(BID_REQUESTS); + digiTrustBidRequest[0].bids[0].userId = { digitrustid: { data: digiTrustObj } }; - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids(REQUEST, digiTrustBidRequest, addBidResponse, done, ajax); let requestBid = JSON.parse(requests[0].requestBody); - expect(requestBid.digiTrust).to.deep.equal({ - id: digiTrustObj.identity.id, - keyv: digiTrustObj.identity.keyv, - pref: 0 + expect(requestBid.user.ext.digitrust).to.deep.equal({ + id: digiTrustObj.id, + keyv: digiTrustObj.keyv }); - digiTrustObj.identity.privacy.optout = true; + digiTrustObj.privacy.optout = true; - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids(REQUEST, digiTrustBidRequest, addBidResponse, done, ajax); requestBid = JSON.parse(requests[1].requestBody); - expect(requestBid.digiTrust).to.not.exist; - - delete window.DigiTrust; + expect(requestBid.user && request.user.ext && requestBid.user.ext.digitrust).to.not.exist; }); it('adds device and app objects to request', function () { @@ -813,22 +812,25 @@ describe('S2S Adapter', function () { it('when userId is defined on bids, it\'s properties should be copied to user.ext.tpid properties', function () { let ortb2Config = utils.deepClone(CONFIG); - ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; let consentConfig = { s2sConfig: ortb2Config }; config.setConfig(consentConfig); let userIdBidRequest = utils.deepClone(BID_REQUESTS); - userIdBidRequest[0].userId = { - foo: 'abc123', - unifiedid: '1234' + userIdBidRequest[0].bids[0].userId = { + tdid: 'abc123', + pubcid: '1234' }; adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); let requestBid = JSON.parse(requests[0].requestBody); - expect(typeof requestBid.user.ext.tpid).is.equal('object'); - expect(requestBid.user.ext.tpid.foo).is.equal('abc123'); - expect(requestBid.user.ext.tpid.unifiedid).is.equal('1234'); + expect(typeof requestBid.user.ext.eids).is.equal('object'); + expect(Array.isArray(requestBid.user.ext.eids)).to.be.true; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')).is.not.empty; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; ; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); }) it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () { From de8381f3552bee10c2eec80564dec3a26b433e65 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Durgeat Date: Mon, 24 Jun 2019 19:05:50 +0200 Subject: [PATCH 1296/1594] ID5 userId submodule (#3798) * Extract GDPRApplies in userId.js to make it available to cookie-sync requiring it * Adding id5 userId submodule, tests and documentation * Fixed typo in test name for unifiedid * Adding test to userId for ID5 * Follow correct naming convention for GDPRApplies: renamed to isGDPRApplicable * Refactoring of id5 module following refactoring of userId module. * Moved init of id5 user module at the end of the id5 module itself * regroup import to avoid a CircleCI Bug --- integrationExamples/gpt/userId_example.html | 12 ++- modules/id5IdSystem.js | 60 +++++++++++++ modules/userId.js | 13 ++- modules/userId.md | 24 +++++- test/spec/modules/userId_spec.js | 95 +++++++++++++++------ 5 files changed, 175 insertions(+), 29 deletions(-) create mode 100644 modules/id5IdSystem.js diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index d64e22e44c7..febe61628fe 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -140,7 +140,17 @@ name: "unifiedid", expires: 30 }, - + }, { + name: "id5Id", + params: { + partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one contact@id5.io + }, + storage: { + type: "cookie", + name: "id5id", + expires: 90 + }, + }, { name: "pubCommonId", storage: { diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js new file mode 100644 index 00000000000..39ab256a81e --- /dev/null +++ b/modules/id5IdSystem.js @@ -0,0 +1,60 @@ +/** + * This module adds ID5 to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/unifiedIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils.js' +import {ajax} from '../src/ajax.js'; +import {isGDPRApplicable, attachIdSystem} from './userId.js'; + +/** @type {Submodule} */ +export const id5IdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'id5Id', + /** + * decode the stored id value for passing to bid requests + * @function + * @param {{ID5ID:Object}} value + * @returns {{id5id:String}} + */ + decode(value) { + return (value && typeof value['ID5ID'] === 'string') ? { 'id5id': value['ID5ID'] } : undefined; + }, + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @param {SubmoduleParams} [configParams] + * @param {ConsentData} [consentData] + * @returns {function(callback:function)} + */ + getId(configParams, consentData) { + if (!configParams || typeof configParams.partner !== 'number') { + utils.logError(`User ID - ID5 submodule requires partner to be defined as a number`); + return; + } + const hasGdpr = isGDPRApplicable(consentData) ? 1 : 0; + const gdprConsentString = hasGdpr ? consentData.consentString : ''; + const url = `https://id5-sync.com/g/v1/${configParams.partner}.json?gdpr=${hasGdpr}&gdpr_consent=${gdprConsentString}`; + + return function (callback) { + ajax(url, response => { + let responseObj; + if (response) { + try { + responseObj = JSON.parse(response); + } catch (error) { + utils.logError(error); + } + } + callback(responseObj); + }, undefined, { method: 'GET' }); + } + } +}; + +attachIdSystem(id5IdSubmodule); diff --git a/modules/userId.js b/modules/userId.js index ae06dfc4027..c80ea21a0a0 100644 --- a/modules/userId.js +++ b/modules/userId.js @@ -158,13 +158,22 @@ function getStoredValue(storage) { return storedValue; } +/** + * test if consent module is present, and if GDPR applies + * @param {ConsentData} consentData + * @returns {boolean} + */ +export function isGDPRApplicable(consentData) { + return consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies; +} + /** * test if consent module is present, applies, and is valid for local storage or cookies (purpose 1) * @param {ConsentData} consentData * @returns {boolean} */ -function hasGDPRConsent(consentData) { - if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) { +export function hasGDPRConsent(consentData) { + if (isGDPRApplicable(consentData)) { if (!consentData.consentString) { return false; } diff --git a/modules/userId.md b/modules/userId.md index 782e7782554..b36b9b1007c 100644 --- a/modules/userId.md +++ b/modules/userId.md @@ -3,12 +3,12 @@ Example showing `cookie` storage for user id data for both submodules ``` pbjs.setConfig({ - userSync: { + usersync: { userIds: [{ name: "unifiedId", params: { partner: "prebid", - url: "//match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" + url: "http://match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" }, storage: { type: "cookie", @@ -28,6 +28,26 @@ pbjs.setConfig({ }); ``` +Example showing `cookie` storage for user id data for id5 submodule +``` +pbjs.setConfig({ + usersync: { + userIds: [{ + name: "id5Id", + params: { + partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one contact@id5.io + }, + storage: { + type: "cookie", + name: "id5id", + expires: 90 + } + }], + syncDelay: 5000 + } +}); +``` + Example showing `localStorage` for user id data for both submodules ``` pbjs.setConfig({ diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index d0f5e06cdad..60df468a903 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -9,18 +9,20 @@ import {config} from 'src/config'; import * as utils from 'src/utils'; import {unifiedIdSubmodule} from 'modules/unifiedIdSystem'; import {pubCommonIdSubmodule} from 'modules/pubCommonIdSystem'; +import {id5IdSubmodule} from 'modules/id5IdSystem'; let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; describe('User ID', function() { - function getConfigMock(configArr1, configArr2) { + function getConfigMock(configArr1, configArr2, configArr3) { return { userSync: { syncDelay: 0, userIds: [ (configArr1 && configArr1.length === 3) ? getStorageMock.apply(null, configArr1) : null, - (configArr2 && configArr2.length === 3) ? getStorageMock.apply(null, configArr2) : null + (configArr2 && configArr2.length === 3) ? getStorageMock.apply(null, configArr2) : null, + (configArr3 && configArr3.length === 3) ? getStorageMock.apply(null, configArr3) : null ].filter(i => i)} } } @@ -68,7 +70,7 @@ describe('User ID', function() { let pubcid = utils.getCookie('pubcid'); expect(pubcid).to.be.null; // there should be no cookie initially - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); @@ -94,7 +96,7 @@ describe('User ID', function() { let pubcid1; let pubcid2; - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); @@ -108,7 +110,7 @@ describe('User ID', function() { }); }); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); @@ -129,7 +131,7 @@ describe('User ID', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie'])); requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); @@ -164,14 +166,14 @@ describe('User ID', function() { }); it('fails initialization if opt out cookie exists', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); 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 () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); @@ -190,7 +192,7 @@ describe('User ID', function() { }); it('handles config with no usersync object', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({}); // usersync is undefined, and no logInfo message for 'User ID - usersync config updated' @@ -198,14 +200,14 @@ describe('User ID', function() { }); it('handles config with empty usersync object', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); 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([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: { @@ -216,7 +218,7 @@ describe('User ID', function() { }); it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: { @@ -233,15 +235,15 @@ describe('User ID', function() { }); it('config with 1 configurations should create 1 submodules', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); }); - it('config with 2 configurations should result in 2 submodules add', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + it('config with 3 configurations should result in 3 submodules add', function () { + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: { @@ -251,14 +253,17 @@ describe('User ID', function() { }, { name: 'unifiedId', storage: { name: 'unifiedid', type: 'cookie' } + }, { + name: 'id5Id', + storage: { name: 'id5id', type: 'cookie' } }] } }); - expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 2 submodules'); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 3 submodules'); }); it('config syncDelay updates module correctly', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: { @@ -322,7 +327,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from pubcommonid html5', function(done) { + it('test hook from unifiedid html5', function(done) { // simulate existing browser local storage values localStorage.setItem('unifiedid_alt', JSON.stringify({'TDID': 'testunifiedid_alt'})); localStorage.setItem('unifiedid_alt_exp', ''); @@ -344,13 +349,36 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook when both pubCommonId and unifiedId have data to pass', function(done) { + it('test hook from id5id cookies', function(done) { + // simulate existing browser local storage values + utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + + setSubmoduleRegistry([id5IdSubmodule]); + init(config); + config.setConfig(getConfigMock(['id5Id', 'id5id', 'cookie'])); + + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); + }); + }); + utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + + it('test hook when pubCommonId, unifiedId and id5Id have data to pass', function(done) { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); - config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'])); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], + ['unifiedId', 'unifiedid', 'cookie'], + ['id5Id', 'id5id', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -361,17 +389,22 @@ describe('User ID', function() { // 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('testunifiedid'); + // also check that Id5Id id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); }); }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); - it('test hook when pubCommonId and unifiedId have their modules added before and after init', function(done) { + it('test hook when pubCommonId, unifiedId and id5Id have their modules added before and after init', function(done) { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([]); @@ -382,8 +415,11 @@ describe('User ID', function() { // attaching after init attachIdSystem(unifiedIdSubmodule); + attachIdSystem(id5IdSubmodule); - config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'])); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], + ['unifiedId', 'unifiedid', 'cookie'], + ['id5Id', 'id5id', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -394,10 +430,14 @@ describe('User ID', function() { // 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'); + expect(bid.userId.id5id).to.equal('testid5id'); }); }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -405,9 +445,10 @@ describe('User ID', function() { it('should add new id system ', function(done) { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ @@ -417,6 +458,8 @@ describe('User ID', function() { name: 'pubCommonId', storage: { name: 'pubcid', type: 'cookie' } }, { name: 'unifiedId', storage: { name: 'unifiedid', type: 'cookie' } + }, { + name: 'id5Id', storage: { name: 'id5id', type: 'cookie' } }, { name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } }] @@ -445,6 +488,9 @@ describe('User ID', function() { // check 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'); + expect(bid.userId.id5id).to.equal('testid5id'); // check MockId data was copied to bid expect(bid).to.have.deep.nested.property('userId.mid'); expect(bid.userId.mid).to.equal('123456778'); @@ -452,6 +498,7 @@ describe('User ID', function() { }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); utils.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); From 37232c79d9e606324b673bb65d51e9a4a3c93311 Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Mon, 24 Jun 2019 15:39:48 -0400 Subject: [PATCH 1297/1594] EMX Digital: Device info and Video parameter updates (#3929) * EMX Digital - device info and video parameter updates * update timeout value to grab from bidderRequest arg * removing unused import * removing object spread use. quote fix for lint * remove space --- modules/emx_digitalBidAdapter.js | 85 +++++++++++++------ .../modules/emx_digitalBidAdapter_spec.js | 7 +- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 69e02d5c860..2ca595151f9 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -1,13 +1,14 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { BANNER, VIDEO } from '../src/mediaTypes'; -import { config } from '../src/config'; import { Renderer } from '../src/Renderer'; import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; const ENDPOINT = 'hb.emxdgt.com'; const RENDERER_URL = '//js.brealtime.com/outstream/1.30.0/bundle.js'; +const ADAPTER_VERSION = '1.40.2'; +const DEFAULT_CUR = 'USD'; export const emxAdapter = { validateSizes: (sizes) => { @@ -48,6 +49,23 @@ export const emxAdapter = { } return bidResponse; }, + isMobile: () => { + return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent); + }, + isConnectedTV: () => { + return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent); + }, + getDevice: () => { + return { + ua: navigator.userAgent, + js: 1, + dnt: (navigator.doNotTrack === 'yes' || navigator.doNotTrack === '1' || navigator.msDoNotTrack === '1') ? 1 : 0, + h: screen.height, + w: screen.width, + devicetype: emxAdapter.isMobile() ? 1 : emxAdapter.isConnectedTV() ? 3 : 2, + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), + }; + }, cleanProtocols: (video) => { if (video.protocols && includes(video.protocols, 7)) { // not supporting VAST protocol 7 (VAST 4.0); @@ -85,10 +103,22 @@ export const emxAdapter = { return renderer; }, buildVideo: (bid) => { - bid.params.video = bid.params.video || {}; - bid.params.video.h = bid.mediaTypes.video.playerSize[0][0]; - bid.params.video.w = bid.mediaTypes.video.playerSize[0][1]; - return emxAdapter.cleanProtocols(bid.params.video); + let videoObj = Object.assign(bid.mediaTypes.video, bid.params.video) + return emxAdapter.cleanProtocols(videoObj); + }, + parseResponse: (bidResponseAdm) => { + try { + return decodeURIComponent(bidResponseAdm); + } catch (err) { + utils.logError('emx_digitalBidAdapter', 'error', err); + } + }, + getReferrer: () => { + try { + return window.top.document.referrer; + } catch (err) { + return document.referrer; + } }, getGdpr: (bidRequests, emxData) => { if (bidRequests.gdprConsent) { @@ -151,40 +181,44 @@ export const spec = { return true; }, buildRequests: function (validBidRequests, bidderRequest) { - const page = bidderRequest.refererInfo.referer; - let emxImps = []; - const timeout = config.getConfig('bidderTimeout'); + const emxImps = []; + const timeout = bidderRequest.timeout || ''; const timestamp = Date.now(); - const url = location.protocol + '//' + ENDPOINT + ('?t=' + timeout + '&ts=' + timestamp); - const networkProtocol = location.protocol.indexOf('https') > -1 ? 1 : 0; + const url = location.protocol + '//' + ENDPOINT + ('?t=' + timeout + '&ts=' + timestamp + '&src=pbjs'); + const secure = location.protocol.indexOf('https') > -1 ? 1 : 0; + const domain = utils.getTopWindowLocation().hostname; + const page = bidderRequest.refererInfo.referer; + const device = emxAdapter.getDevice(); + const ref = emxAdapter.getReferrer(); utils._each(validBidRequests, function (bid) { - let tagId = utils.getBidIdParameter('tagid', bid.params); - let bidFloor = parseFloat(utils.getBidIdParameter('bidfloor', bid.params)) || 0; + let tagid = utils.getBidIdParameter('tagid', bid.params); + let bidfloor = parseFloat(utils.getBidIdParameter('bidfloor', bid.params)) || 0; let isVideo = !!bid.mediaTypes.video; let data = { id: bid.bidId, tid: bid.transactionId, - tagid: tagId, - secure: networkProtocol + tagid, + secure }; let typeSpecifics = isVideo ? { video: emxAdapter.buildVideo(bid) } : { banner: emxAdapter.buildBanner(bid) }; - let emxBid = Object.assign(data, typeSpecifics); + let bidfloorObj = bidfloor > 0 ? { bidfloor, bidfloorcur: DEFAULT_CUR } : {}; + let emxBid = Object.assign(data, typeSpecifics, bidfloorObj); - if (bidFloor > 0) { - emxBid.bidfloor = bidFloor - } emxImps.push(emxBid); }); let emxData = { id: bidderRequest.auctionId, imp: emxImps, + device, site: { - domain: window.top.document.location.host, - page: page + domain, + page, + ref }, - version: '1.30.0' + cur: DEFAULT_CUR, + version: ADAPTER_VERSION }; emxData = emxAdapter.getGdpr(bidderRequest, Object.assign({}, emxData)); @@ -204,6 +238,7 @@ export const spec = { response.seatbid.forEach(function (emxBid) { emxBid = emxBid.bid[0]; let isVideo = false; + let adm = emxAdapter.parseResponse(emxBid.adm) || ''; let bidResponse = { requestId: emxBid.id, cpm: emxBid.price, @@ -214,7 +249,7 @@ export const spec = { currency: 'USD', netRevenue: true, ttl: emxBid.ttl, - ad: decodeURIComponent(emxBid.adm) + ad: adm }; if (emxBid.adm && emxBid.adm.indexOf(' -1) { isVideo = true; @@ -234,12 +269,6 @@ export const spec = { url: '//biddr.brealtime.com/check.html' }); } - if (syncOptions.pixelEnabled) { - syncs.push({ - type: 'image', - url: '//edba.brealtime.com/' - }); - } return syncs; } }; diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js index 170e5676f43..10d0d74c49c 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -276,8 +276,9 @@ describe('emx_digital Adapter', function () { it('properly sends site information and protocol', function () { request = spec.buildRequests(bidderRequest.bids, bidderRequest); request = JSON.parse(request.data); - expect(request.site.domain).to.equal(window.top.document.location.host); + expect(request.site.domain).to.equal(utils.getTopWindowLocation().hostname); expect(decodeURIComponent(request.site.page)).to.equal(bidderRequest.refererInfo.referer); + expect(request.site.ref).to.equal(window.top.document.referrer); }); it('builds correctly formatted request banner object', function () { @@ -511,10 +512,6 @@ describe('emx_digital Adapter', function () { let iframeSync = spec.getUserSyncs(syncOptionsIframe); expect(iframeSync.length).to.equal(1); expect(iframeSync[0].type).to.equal('iframe'); - - let pixelSync = spec.getUserSyncs(syncOptionsPixel); - expect(pixelSync.length).to.equal(1); - expect(pixelSync[0].type).to.equal('image'); }); }); }); From 75aca43bc2c9f05db2483bcd4661c32682fa0dcc Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 24 Jun 2019 13:40:40 -0600 Subject: [PATCH 1298/1594] update placementId to be number instead of string (#3941) --- integrationExamples/gpt/prebidServer_example.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrationExamples/gpt/prebidServer_example.html b/integrationExamples/gpt/prebidServer_example.html index f13c93963c6..db61a6a46d6 100644 --- a/integrationExamples/gpt/prebidServer_example.html +++ b/integrationExamples/gpt/prebidServer_example.html @@ -41,7 +41,7 @@ { bidder: 'appnexus', params: { - placementId: '13144370' + placementId: 13144370 } } ] From b6aaf644b2239da3f85b73737a5a06c6fa327d01 Mon Sep 17 00:00:00 2001 From: Gleb Glushtsov Date: Mon, 24 Jun 2019 20:21:30 -0400 Subject: [PATCH 1299/1594] [33Across adapter] Map ad unit path to element id (#3920) * fix return of _mapAdUnitPathToElementId() * improve logging of _mapAdUnitPathToElementId() * do not use Array.find() * return id once element is found * return id once element is found * let -> const --- modules/33acrossBidAdapter.js | 48 ++++++++++++++------ modules/33acrossBidAdapter.md | 2 +- test/spec/modules/33acrossBidAdapter_spec.js | 4 +- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 1cf885ed6e4..801a5d564a3 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -1,8 +1,7 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; import * as utils from '../src/utils'; -const { registerBidder } = require('../src/adapters/bidderFactory'); -const { config } = require('../src/config'); - const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch&rt=html'; @@ -32,17 +31,43 @@ function _isViewabilityMeasurable(element) { } function _getViewability(element, topWin, { w, h } = {}) { - return utils.getWindowTop().document.visibilityState === 'visible' + return topWin.document.visibilityState === 'visible' ? _getPercentInView(element, topWin, { w, h }) : 0; } +function _mapAdUnitPathToElementId(adUnitCode) { + if (utils.isGptPubadsDefined()) { + const adSlots = googletag.pubads().getSlots(); + const isMatchingAdSlot = utils.isSlotMatchingAdUnitCode(adUnitCode); + + for (let i = 0; i < adSlots.length; i++) { + if (isMatchingAdSlot(adSlots[i])) { + const id = adSlots[i].getSlotElementId(); + + utils.logInfo(`[33Across Adapter] Map ad unit path to HTML element id: '${adUnitCode}' -> ${id}`); + + return id; + } + } + } + + utils.logWarn(`[33Across Adapter] Unable to locate element for ad unit code: '${adUnitCode}'`); + + return null; +} + +function _getAdSlotHTMLElement(adUnitCode) { + return document.getElementById(adUnitCode) || + document.getElementById(_mapAdUnitPathToElementId(adUnitCode)); +} + // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request // NOTE: At this point, TTX only accepts request for a single impression function _createServerRequest(bidRequest, gdprConsent) { const ttxRequest = {}; const params = bidRequest.params; - const element = document.getElementById(bidRequest.adUnitCode); + const element = _getAdSlotHTMLElement(bidRequest.adUnitCode); const sizes = _transformSizes(bidRequest.sizes); const minSize = _getMinSize(sizes); @@ -52,10 +77,6 @@ function _createServerRequest(bidRequest, gdprConsent) { const contributeViewability = ViewabilityContributor(viewabilityAmount); - if (element === null) { - utils.logWarn(`Unable to locate element with id: '${bidRequest.adUnitCode}'`); - } - /* * Infer data for the request payload */ @@ -264,13 +285,14 @@ function isBidRequestValid(bid) { // - the server, at this point, also doesn't need the consent string to handle gdpr compliance. So passing // value whether set or not, for the sake of future dev. function buildRequests(bidRequests, bidderRequest) { - const gdprConsent = Object.assign({ consentString: undefined, gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent); + const gdprConsent = Object.assign({ + consentString: undefined, + gdprApplies: false + }, bidderRequest && bidderRequest.gdprConsent); adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(utils.uniques); - return bidRequests.map((req) => { - return _createServerRequest(req, gdprConsent); - }); + return bidRequests.map(req => _createServerRequest(req, gdprConsent)); } // NOTE: At this point, the response from 33exchange will only ever contain one bid i.e. the highest bid diff --git a/modules/33acrossBidAdapter.md b/modules/33acrossBidAdapter.md index bdb2b944861..58e3b2b273a 100644 --- a/modules/33acrossBidAdapter.md +++ b/modules/33acrossBidAdapter.md @@ -16,7 +16,7 @@ Connects to 33Across's exchange for bids. ``` var adUnits = [ { - code: '33across-hb-ad-123456-1', + code: '33across-hb-ad-123456-1', // ad slot HTML element ID sizes: [ [300, 250], [728, 90] diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 1fc77a7e14d..7e1a8619c63 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -337,8 +337,8 @@ describe('33acrossBidAdapter:', function () { utils.getWindowTop.restore(); utils.getWindowSelf.restore(); - sandbox.stub(utils, 'getWindowTop').returns(win); - sandbox.stub(utils, 'getWindowSelf').returns({}); + sandbox.stub(utils, 'getWindowTop').returns({}); + sandbox.stub(utils, 'getWindowSelf').returns(win); expect(spec.buildRequests(bidRequests)).to.deep.equal([ serverRequest ]); }); From 9d2f06c79e0a84207fb72e36329a894ee221c5b1 Mon Sep 17 00:00:00 2001 From: Daniel Liebner Date: Tue, 25 Jun 2019 13:36:02 -0400 Subject: [PATCH 1300/1594] New Adapter: bidglass (#3861) * Added bidglass adapter + test * PR Review Updates: - Added formal params to getUserSyncs function definition - getUserSyncs now always returns an array - Improved unit test coverage * PR Review Updates: - Removed unused methods: getUserSyncs, onTimeout, onBidWon, onSetTargeting - Removed getUserSyncs unit test - Removed "dead code" - Removed some unnecessary comments - Fixed usage of parseInt --- modules/bidglassBidAdapter.js | 134 ++++++++++++++++++++++ modules/bidglassBidAdapter.md | 34 ++++++ test/spec/modules/bidglassAdapter_spec.js | 103 +++++++++++++++++ 3 files changed, 271 insertions(+) create mode 100644 modules/bidglassBidAdapter.js create mode 100644 modules/bidglassBidAdapter.md create mode 100644 test/spec/modules/bidglassAdapter_spec.js diff --git a/modules/bidglassBidAdapter.js b/modules/bidglassBidAdapter.js new file mode 100644 index 00000000000..1898d1220fa --- /dev/null +++ b/modules/bidglassBidAdapter.js @@ -0,0 +1,134 @@ +import * as utils from 'src/utils'; +// import {config} from 'src/config'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'bidglass'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['bg'], // 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 !!(bid.params.adUnitId && !isNaN(parseFloat(bid.params.adUnitId)) && isFinite(bid.params.adUnitId)); + }, + /** + * 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) { + /* + Sample array entry for validBidRequests[]: + [{ + "bidder": "bidglass", + "bidId": "51ef8751f9aead", + "params": { + "adUnitId": 11, + ... + }, + "adUnitCode": "div-gpt-ad-1460505748561-0", + "transactionId": "d7b773de-ceaa-484d-89ca-d9f51b8d61ec", + "sizes": [[320,50],[300,250],[300,600]], + "bidderRequestId": "418b37f85e772c", + "auctionId": "18fd8b8b0bd757", + "bidRequestsCount": 1 + }] + */ + + let imps = []; + let getReferer = function() { + return window === window.top ? window.location.href : window.parent === window.top ? document.referrer : null; + }; + let getOrigins = function() { + var ori = [window.location.protocol + '//' + window.location.hostname]; + + if (window.location.ancestorOrigins) { + for (var i = 0; i < window.location.ancestorOrigins.length; i++) { + ori.push(window.location.ancestorOrigins[i]); + } + } else if (window !== window.top) { + // Derive the parent origin + var parts = document.referrer.split('/'); + + ori.push(parts[0] + '//' + parts[2]); + + if (window.parent !== window.top) { + // Additional unknown origins exist + ori.push('null'); + } + } + + return ori; + }; + + 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)); + + // Stuff to send: [bid id, sizes, adUnitId] + imps.push({ + bidId: bid.bidId, + sizes: bid.sizes, + adUnitId: utils.getBidIdParameter('adUnitId', bid.params) + }); + }); + + // Stuff to send: page URL + const bidReq = { + reqId: utils.getUniqueIdentifierStr(), + imps: imps, + ref: getReferer(), + ori: getOrigins() + }; + + let url = 'https://bid.glass/ad/hb.php?' + + `src=$$REPO_AND_VERSION$$`; + + return { + method: 'POST', + url: url, + data: JSON.stringify(bidReq), + options: { + contentType: 'text/plain', + 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: function(serverResponse) { + const bidResponses = []; + + utils._each(serverResponse.body.bidResponses, function(bid) { + bidResponses.push({ + requestId: bid.requestId, + cpm: parseFloat(bid.cpm), + width: parseInt(bid.width, 10), + height: parseInt(bid.height, 10), + creativeId: bid.creativeId, + dealId: bid.dealId || null, + currency: bid.currency || 'USD', + mediaType: bid.mediaType || 'banner', + netRevenue: true, + ttl: bid.ttl || 10, + ad: bid.ad + }); + }); + + return bidResponses; + } + +} + +registerBidder(spec); diff --git a/modules/bidglassBidAdapter.md b/modules/bidglassBidAdapter.md new file mode 100644 index 00000000000..5384a095314 --- /dev/null +++ b/modules/bidglassBidAdapter.md @@ -0,0 +1,34 @@ +# Overview + +``` +Module Name: Bid Glass Bid Adapter +Module Type: Bidder Adapter +Maintainer: dliebner@gmail.com +``` + +# Description + +Connects to Bid Glass and allows bids on ad units to compete within prebid. + +# Sample Ad Unit: For Publishers +``` +var adUnits = [{ + code: 'bg-test-rectangle', + sizes: [[300, 250]], + bids: [{ + bidder: 'bidglass', + params: { + adUnitId: '-1' + } + }] +},{ + code: 'bg-test-leaderboard', + sizes: [[728, 90]], + bids: [{ + bidder: 'bidglass', + params: { + adUnitId: '-1' + } + }] +}] +``` \ No newline at end of file diff --git a/test/spec/modules/bidglassAdapter_spec.js b/test/spec/modules/bidglassAdapter_spec.js new file mode 100644 index 00000000000..00a47fc997a --- /dev/null +++ b/test/spec/modules/bidglassAdapter_spec.js @@ -0,0 +1,103 @@ +import { expect } from 'chai'; +import { spec } from 'modules/bidglassBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('Bid Glass Adapter', function () { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'bidglass', + 'params': { + 'adUnitId': '3' + }, + 'adUnitCode': 'bidglass-testunit', + '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 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 () { + const bidRequests = [{ + 'bidder': 'bidglass', + 'params': { + 'adUnitId': '3' + }, + 'adUnitCode': 'bidglass-testunit', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }]; + + const request = spec.buildRequests(bidRequests); + + it('sends bid request to our endpoint via POST', function () { + expect(request.method).to.equal('POST'); + }); + + it('sets withCredentials to false', function () { + expect(request.options.withCredentials).to.equal(false); + }); + }); + + describe('interpretResponse', function () { + let response; + beforeEach(function () { + response = { + body: { + 'bidResponses': [{ + 'ad': '', + 'cpm': '0.01', + 'creativeId': '-1', + 'width': '300', + 'height': '250', + 'requestId': '30b31c1838de1e' + }] + } + }; + }); + + it('should get the correct bid response', function () { + let expectedResponse = [{ + 'requestId': '30b31c1838de1e', + 'cpm': 0.01, + 'width': 300, + 'height': 250, + 'creativeId': '-1', + 'dealId': null, + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 10, + 'ad': '' + }]; + + let result = spec.interpretResponse(response); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles empty bid response', function () { + let response = { + body: { + 'bidResponses': [] + } + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From e64360ccdd3613dbffebd29212367ffc6b72c3e6 Mon Sep 17 00:00:00 2001 From: Index Exchange 3 Prebid Team Date: Tue, 25 Jun 2019 13:37:06 -0400 Subject: [PATCH 1301/1594] Prebid.js Video (#3901) * Implemented changes required to provide support for video in the IX bidding adapter for Instream and Outstream contexts. * Implemented changes required to provide support for video in the IX bidding adapter for Instream and Outstream contexts. * fix find module --- modules/ixBidAdapter.js | 366 ++++++++++++++++--------- modules/ixBidAdapter.md | 128 ++++++++- test/spec/modules/ixBidAdapter_spec.js | 344 ++++++++++++++++++----- 3 files changed, 628 insertions(+), 210 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index c63b920dc93..f26c5e413c5 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -1,38 +1,75 @@ import * as utils from '../src/utils'; -import { BANNER } from '../src/mediaTypes'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; import { config } from '../src/config'; import isArray from 'core-js/library/fn/array/is-array'; import isInteger from 'core-js/library/fn/number/is-integer'; import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'ix'; -const BANNER_SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; -const BANNER_INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; -const SUPPORTED_AD_TYPES = [BANNER]; -const ENDPOINT_VERSION = 7.2; +const SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; +const INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; +const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const BANNER_ENDPOINT_VERSION = 7.2; +const VIDEO_ENDPOINT_VERSION = 8.1; + const CENT_TO_DOLLAR_FACTOR = 100; -const TIME_TO_LIVE = 35; +const BANNER_TIME_TO_LIVE = 35; +const VIDEO_TIME_TO_LIVE = 3600; // 1hr const NET_REVENUE = true; const PRICE_TO_DOLLAR_FACTOR = { JPY: 1 }; /** - * Transform valid bid request config object to impression object that will be sent to ad server. + * Transform valid bid request config object to banner impression object that will be sent to ad server. * * @param {object} bid A valid bid request config object. * @return {object} A impression object that will be sent to ad server. */ function bidToBannerImp(bid) { - const imp = {}; - - imp.id = bid.bidId; + const imp = bidToImp(bid); imp.banner = {}; imp.banner.w = bid.params.size[0]; imp.banner.h = bid.params.size[1]; imp.banner.topframe = utils.inIframe() ? 0 : 1; + return imp; +} + +/** + * Transform valid bid request config object to video impression object that will be sent to ad server. + * + * @param {object} bid A valid bid request config object. + * @return {object} A impression object that will be sent to ad server. + */ +function bidToVideoImp(bid) { + const imp = bidToImp(bid); + + imp.video = utils.deepClone(bid.params.video) + imp.video.w = bid.params.size[0]; + imp.video.h = bid.params.size[1]; + + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + if (context) { + if (context === 'instream') { + imp.video.placement = 1; + } else if (context === 'outstream') { + imp.video.placement = 4; + } else { + utils.logWarn(`ix bidder params: video context '${context}' is not supported`); + } + } + + return imp; +} + +function bidToImp(bid) { + const imp = {}; + + imp.id = bid.bidId; + imp.ext = {}; imp.ext.siteID = bid.params.siteId; @@ -58,7 +95,7 @@ function bidToBannerImp(bid) { * @param {string} currency Global currency in bid response. * @return {object} bid The parsed bid. */ -function parseBid(rawBid, currency) { +function parseBid(rawBid, currency, bidRequest) { const bid = {}; if (PRICE_TO_DOLLAR_FACTOR.hasOwnProperty(currency)) { @@ -68,15 +105,27 @@ function parseBid(rawBid, currency) { } bid.requestId = rawBid.impid; - bid.width = rawBid.w; - bid.height = rawBid.h; - bid.ad = rawBid.adm; + bid.dealId = utils.deepAccess(rawBid, 'ext.dealid'); - bid.ttl = TIME_TO_LIVE; bid.netRevenue = NET_REVENUE; bid.currency = currency; bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-'; + // in the event of a video + if (utils.deepAccess(rawBid, 'ext.vasturl')) { + bid.vastUrl = rawBid.ext.vasturl + bid.width = bidRequest.video.w; + bid.height = bidRequest.video.h; + bid.mediaType = VIDEO; + bid.ttl = VIDEO_TIME_TO_LIVE; + } else { + bid.ad = rawBid.adm; + bid.width = rawBid.w; + bid.height = rawBid.h; + bid.mediaType = BANNER; + bid.ttl = BANNER_TIME_TO_LIVE; + } + bid.meta = {}; bid.meta.networkId = utils.deepAccess(rawBid, 'ext.dspid'); bid.meta.brandId = utils.deepAccess(rawBid, 'ext.advbrandid'); @@ -133,6 +182,143 @@ function isValidBidFloorParams(bidFloor, bidFloorCur) { bidFloorCur.match(curRegex)); } +/** + * Finds the impression with the associated id. + * + * @param {*} id Id of the impression. + * @param {array} impressions List of impressions sent in the request. + * @return {object} The impression with the associated id. + */ +function getBidRequest(id, impressions) { + if (!id) { + return; + } + return find(impressions, imp => imp.id === id); +} + +/** + * Builds a request object to be sent to the ad server based on bid requests. + * + * @param {array} validBidRequests A list of valid bid request config objects. + * @param {object} bidderRequest An object containing other info like gdprConsent. + * @param {array} impressions List of impression objects describing the bids. + * @param {array} version Endpoint version denoting banner or video. + * @return {object} Info describing the request to the server. + * + */ +function buildRequest(validBidRequests, bidderRequest, impressions, version) { + const userEids = []; + + // Always start by assuming the protocol is HTTPS. This way, it will work + // whether the page protocol is HTTP or HTTPS. Then check if the page is + // actually HTTP.If we can guarantee it is, then, and only then, set protocol to + // HTTP. + let baseUrl = SECURE_BID_URL; + + // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded + // and if the data for the partner exist + if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { + let identityInfo = window.headertag.getIdentityInfo(); + if (identityInfo && typeof identityInfo === 'object') { + for (const partnerName in identityInfo) { + if (identityInfo.hasOwnProperty(partnerName)) { + let response = identityInfo[partnerName]; + if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { + userEids.push(response.data); + } + } + } + } + } + const r = {}; + + // Since bidderRequestId are the same for different bid request, just use the first one. + r.id = validBidRequests[0].bidderRequestId; + + r.imp = impressions; + + r.site = {}; + r.ext = {}; + r.ext.source = 'prebid'; + if (userEids.length > 0) { + r.user = {}; + r.user.eids = userEids; + } + + if (document.referrer && document.referrer !== '') { + r.site.ref = document.referrer; + } + + // Apply GDPR information to the request if GDPR is enabled. + if (bidderRequest) { + if (bidderRequest.gdprConsent) { + const gdprConsent = bidderRequest.gdprConsent; + + if (gdprConsent.hasOwnProperty('gdprApplies')) { + r.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + }; + } + + if (gdprConsent.hasOwnProperty('consentString')) { + r.user = r.user || {}; + r.user.ext = { + consent: gdprConsent.consentString || '' + }; + } + } + + if (bidderRequest.refererInfo) { + r.site.page = bidderRequest.refererInfo.referer; + + if (bidderRequest.refererInfo.referer && bidderRequest.refererInfo.referer.indexOf('https') !== 0) { + baseUrl = INSECURE_BID_URL; + } + } + } + + const payload = {}; + + // Parse additional runtime configs. + const otherIxConfig = config.getConfig('ix'); + if (otherIxConfig) { + // Append firstPartyData to r.site.page if firstPartyData exists. + if (typeof otherIxConfig.firstPartyData === 'object') { + const firstPartyData = otherIxConfig.firstPartyData; + let firstPartyString = '?'; + for (const key in firstPartyData) { + if (firstPartyData.hasOwnProperty(key)) { + firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; + } + } + firstPartyString = firstPartyString.slice(0, -1); + + r.site.page += firstPartyString; + } + + // Create t in payload if timeout is configured. + if (typeof otherIxConfig.timeout === 'number') { + payload.t = otherIxConfig.timeout; + } + } + + // Use the siteId in the first bid request as the main siteId. + payload.s = validBidRequests[0].params.siteId; + payload.v = version; + payload.r = JSON.stringify(r); + payload.ac = 'j'; + payload.sd = 1; + payload.nf = 1; + + return { + method: 'GET', + url: baseUrl, + data: payload + }; +} + export const spec = { code: BIDDER_CODE, @@ -146,22 +332,25 @@ export const spec = { */ isBidRequestValid: function (bid) { if (!isValidSize(bid.params.size)) { + utils.logError('ix bidder params: bid size has invalid format.'); return false; } if (!includesSize(bid.sizes, bid.params.size)) { + utils.logError('ix bidder params: bid size is not included in ad unit sizes.'); return false; } - if (bid.hasOwnProperty('mediaType') && bid.mediaType !== 'banner') { + if (bid.hasOwnProperty('mediaType') && !(utils.contains(SUPPORTED_AD_TYPES, bid.mediaType))) { return false; } - if (bid.hasOwnProperty('mediaTypes') && !utils.deepAccess(bid, 'mediaTypes.banner.sizes')) { + if (bid.hasOwnProperty('mediaTypes') && !(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || utils.deepAccess(bid, 'mediaTypes.video.playerSize'))) { return false; } if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') { + utils.logError('ix bidder params: siteId must be string or number value.'); return false; } @@ -169,8 +358,10 @@ export const spec = { const hasBidFloorCur = bid.params.hasOwnProperty('bidFloorCur'); if (hasBidFloor || hasBidFloorCur) { - return hasBidFloor && hasBidFloorCur && - isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur); + if (!(hasBidFloor && hasBidFloorCur && isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur))) { + utils.logError('ix bidder params: bidFloor / bidFloorCur parameter has invalid format.'); + return false; + } } return true; @@ -180,139 +371,49 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {array} validBidRequests A list of valid bid request config objects. - * @param {object} options A object contains bids and other info like gdprConsent. + * @param {object} bidderRequest A object contains bids and other info like gdprConsent. * @return {object} Info describing the request to the server. */ - buildRequests: function (validBidRequests, options) { - const bannerImps = []; - const userEids = []; + buildRequests: function (validBidRequests, bidderRequest) { + let reqs = []; + let bannerImps = []; + let videoImps = []; let validBidRequest = null; - let bannerImp = null; - - // Always start by assuming the protocol is HTTPS. This way, it will work - // whether the page protocol is HTTP or HTTPS. Then check if the page is - // actually HTTP.If we can guarantee it is, then, and only then, set protocol to - // HTTP. - let baseUrl = BANNER_SECURE_BID_URL; for (let i = 0; i < validBidRequests.length; i++) { validBidRequest = validBidRequests[i]; - // Transform the bid request based on the banner format. - bannerImp = bidToBannerImp(validBidRequest); - bannerImps.push(bannerImp); - } - - // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded - // and if the data for the partner exist - if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { - let identityInfo = window.headertag.getIdentityInfo(); - if (identityInfo && typeof identityInfo === 'object') { - for (const partnerName in identityInfo) { - if (identityInfo.hasOwnProperty(partnerName)) { - let response = identityInfo[partnerName]; - if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { - userEids.push(response.data); - } - } - } - } - } - const r = {}; - - // Since bidderRequestId are the same for different bid request, just use the first one. - r.id = validBidRequests[0].bidderRequestId; - - r.imp = bannerImps; - r.site = {}; - r.ext = {}; - r.ext.source = 'prebid'; - if (userEids.length > 0) { - r.user = {}; - r.user.eids = userEids; - } - - if (document.referrer && document.referrer !== '') { - r.site.ref = document.referrer; - } - - // Apply GDPR information to the request if GDPR is enabled. - if (options) { - if (options.gdprConsent) { - const gdprConsent = options.gdprConsent; - - if (gdprConsent.hasOwnProperty('gdprApplies')) { - r.regs = { - ext: { - gdpr: gdprConsent.gdprApplies ? 1 : 0 - } - }; - } - - if (gdprConsent.hasOwnProperty('consentString')) { - r.user = r.user || {}; - r.user.ext = { - consent: gdprConsent.consentString || '' - }; + if (validBidRequest.mediaType === VIDEO || utils.deepAccess(validBidRequest, 'mediaTypes.video')) { + if (validBidRequest.mediaType === VIDEO || includesSize(validBidRequest.mediaTypes.video.playerSize, validBidRequest.params.size)) { + videoImps.push(bidToVideoImp(validBidRequest)); + } else { + utils.logError('Bid size is not included in video playerSize') } } - - if (options.refererInfo) { - r.site.page = options.refererInfo.referer; - - if (options.refererInfo.referer && options.refererInfo.referer.indexOf('https') !== 0) { - baseUrl = BANNER_INSECURE_BID_URL; - } + if (validBidRequest.mediaType === BANNER || utils.deepAccess(validBidRequest, 'mediaTypes.banner') || + (!validBidRequest.mediaType && !validBidRequest.mediaTypes)) { + bannerImps.push(bidToBannerImp(validBidRequest)); } } - const payload = {}; - - // Parse additional runtime configs. - const otherIxConfig = config.getConfig('ix'); - if (otherIxConfig) { - // Append firstPartyData to r.site.page if firstPartyData exists. - if (typeof otherIxConfig.firstPartyData === 'object') { - const firstPartyData = otherIxConfig.firstPartyData; - let firstPartyString = '?'; - for (const key in firstPartyData) { - if (firstPartyData.hasOwnProperty(key)) { - firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; - } - } - firstPartyString = firstPartyString.slice(0, -1); - - r.site.page += firstPartyString; - } - - // Create t in payload if timeout is configured. - if (typeof otherIxConfig.timeout === 'number') { - payload.t = otherIxConfig.timeout; - } + if (bannerImps.length > 0) { + reqs.push(buildRequest(validBidRequests, bidderRequest, bannerImps, BANNER_ENDPOINT_VERSION)); + } + if (videoImps.length > 0) { + reqs.push(buildRequest(validBidRequests, bidderRequest, videoImps, VIDEO_ENDPOINT_VERSION)); } - // Use the siteId in the first bid request as the main siteId. - payload.s = validBidRequests[0].params.siteId; - - payload.v = ENDPOINT_VERSION; - payload.r = JSON.stringify(r); - payload.ac = 'j'; - payload.sd = 1; - - return { - method: 'GET', - url: baseUrl, - data: payload - }; + return reqs; }, /** * Unpack the response from the server into a list of bids. * * @param {object} serverResponse A successful response from the server. + * @param {object} bidderRequest The bid request sent to the server. * @return {array} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse) { + interpretResponse: function (serverResponse, bidderRequest) { const bids = []; let bid = null; @@ -329,8 +430,11 @@ export const spec = { // Transform rawBid in bid response to the format that will be accepted by prebid. const innerBids = seatbid[i].bid; + let requestBid = JSON.parse(bidderRequest.data.r); + for (let j = 0; j < innerBids.length; j++) { - bid = parseBid(innerBids[j], responseBody.cur); + const bidRequest = getBidRequest(innerBids[j].impid, requestBid.imp); + bid = parseBid(innerBids[j], responseBody.cur, bidRequest); bids.push(bid); } } diff --git a/modules/ixBidAdapter.md b/modules/ixBidAdapter.md index e99c42408f2..7bd60ac413b 100644 --- a/modules/ixBidAdapter.md +++ b/modules/ixBidAdapter.md @@ -42,16 +42,21 @@ var adUnits = [{ ```javascript var adUnits = [{ // ... - mediaTypes: { banner: { sizes: [ [300, 250], [300, 600] ] + }, + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] } - } - + }, // ... }]; ``` @@ -61,7 +66,7 @@ var adUnits = [{ | Type | Support | --- | --- | Banner | Fully supported for all IX approved sizes. -| Video | Not supported. +| Video | Fully supported for all IX approved sizes. | Native | Not supported. # Bid Parameters @@ -76,6 +81,17 @@ object are detailed here. | siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` | size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.banner.sizes`. Examples: `[300, 250]`, `[300, 600]`, `[728, 90]` +### Video + +| Key | Scope | Type | Description +| --- | --- | --- | --- +| siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` +| size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.video.playerSize`. Examples: `[300, 250]`, `[300, 600]` +| video | Required | Hash | The video object will serve as the properties of the video ad. You can create any field under the video object that is mentioned in the `OpenRTB Spec v2.5`. Some fields like `mimes, protocols, minduration, maxduration` are required. +| video.mimes | Required | String[] | Array list of content MIME types supported. Popular MIME types include, but are not limited to, `"video/x-ms- wmv"` for Windows Media and `"video/x-flv"` for Flash Video. +|video.minduration| Required | Integer | Minimum video ad duration in seconds. +|video.maxduration| Required | Integer | Maximum video ad duration in seconds. +|video.protocol / video.protocols| Required | Integer / Integer[] | Either a single protocol provided as an integer, or protocols provided as a list of integers. `2` - VAST 2.0, `3` - VAST 3.0, `5` - VAST 2.0 Wrapper, `6` - VAST 3.0 Wrapper Setup Guide @@ -84,7 +100,9 @@ Setup Guide Follow these steps to configure and add the IX module to your Prebid.js integration. -The examples in this guide assume the following starting configuration: +The examples in this guide assume the following starting configuration (you may remove banner or video, if either does not apply). + +In regards to video, `context` can either be `'instream'` or `'outstream'`. Note that `outstream` requires additional configuration on the adUnit. ```javascript var adUnits = [{ @@ -98,6 +116,19 @@ var adUnits = [{ } }, bids: [] +}, +{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [] }]; ``` @@ -119,7 +150,9 @@ bid objects under `adUnits[].bids`: Set `params.siteId` and `params.size` in each bid object to the values provided by your IX representative. -**Example** +**Examples** + +**Banner:** ```javascript var adUnits = [{ code: 'banner-div-a', @@ -146,18 +179,94 @@ var adUnits = [{ }] }]; ``` - +**Video (Instream):** +```javascript +var adUnits = [{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 250], + video: { + skippable: false, + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0, + maxduration: 60, + protocols: [6] + } + } + }, { + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 600], + video: { + // openrtb v2.5 compatible video obj + } + } + }] +}]; +``` Please note that you can re-use the existing `siteId` within the same flex position. +**Video (Outstream):** +Note that currently, outstream video rendering must be configured by the publisher. In the adUnit, a `renderer` object must be defined, which includes a `url` pointing to the video rendering script, and a `render` function for creating the video player. See http://prebid.org/dev-docs/show-outstream-video-ads.html for more information. +```javascript +var adUnits = [{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [[300, 250]] + } + }, + renderer: { + url: 'https://test.com/my-video-player.js', + render: function (bid) { + ... + } + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 250], + video: { + skippable: false, + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0, + maxduration: 60, + protocols: [6] + } + } + }] +}]; +``` ##### 2. Include `ixBidAdapter` in your build process -When running the build command, include `ixBidAdapter` as a module. +When running the build command, include `ixBidAdapter` as a module, as well as `dfpAdServerVideo` if you require video support. ``` -gulp build --modules=ixBidAdapter,fooBidAdapter,bazBidAdapter +gulp build --modules=ixBidAdapter,dfpAdServerVideo,fooBidAdapter,bazBidAdapter ``` If a JSON file is being used to specify the bidder modules, add `"ixBidAdapter"` @@ -166,6 +275,7 @@ to the top-level array in that file. ```json [ "ixBidAdapter", + "dfpAdServerVideo", "fooBidAdapter", "bazBidAdapter" ] diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 38e64e8d338..634d5041e6e 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -7,7 +7,8 @@ import { spec } from 'modules/ixBidAdapter'; describe('IndexexchangeAdapter', function () { const IX_INSECURE_ENDPOINT = 'http://as.casalemedia.com/cygnus'; const IX_SECURE_ENDPOINT = 'https://as-sec.casalemedia.com/cygnus'; - const BIDDER_VERSION = 7.2; + const VIDEO_ENDPOINT_VERSION = 8.1; + const BANNER_ENDPOINT_VERSION = 7.2; const DEFAULT_BANNER_VALID_BID = [ { @@ -29,17 +30,37 @@ describe('IndexexchangeAdapter', function () { auctionId: '1aa2bb3cc4dd' } ]; - const DEFAULT_BANNER_OPTION = { - gdprConsent: { - gdprApplies: true, - consentString: '3huaa11=qu3198ae', - vendorData: {} - }, - refererInfo: { - referer: 'http://www.prebid.org', - canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' + + const DEFAULT_VIDEO_VALID_BID = [ + { + bidder: 'ix', + params: { + siteId: '456', + video: { + skippable: false, + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0 + }, + size: [400, 100] + }, + sizes: [[400, 100], [200, 400]], + mediaTypes: { + video: { + context: 'instream', + playerSize: [[400, 100], [200, 400]] + } + }, + adUnitCode: 'div-gpt-ad-1460505748562-0', + transactionId: '173f49a8-7549-4218-a23c-e7ba59b47230', + bidId: '1a2b3c4e', + bidderRequestId: '11a22b33c44e', + auctionId: '1aa2bb3cc4de' } - }; + ]; + const DEFAULT_BANNER_BID_RESPONSE = { cur: 'USD', id: '11a22b33c44d', @@ -69,6 +90,48 @@ describe('IndexexchangeAdapter', function () { } ] }; + + const DEFAULT_VIDEO_BID_RESPONSE = { + cur: 'USD', + id: '1aa2bb3cc4de', + seatbid: [ + { + bid: [ + { + crid: '12346', + adomain: ['www.abcd.com'], + adid: '14851456', + impid: '1a2b3c4e', + cid: '3051267', + price: 110, + id: '2', + ext: { + vasturl: 'www.abcd.com/vast', + errorurl: 'www.abcd.com/error', + dspid: 51, + pricelevel: '_110', + advbrandid: 303326, + advbrand: 'OECTB' + } + } + ], + seat: '3971' + } + ] + }; + + const DEFAULT_OPTION = { + gdprConsent: { + gdprApplies: true, + consentString: '3huaa11=qu3198ae', + vendorData: {} + }, + refererInfo: { + referer: 'http://www.prebid.org', + canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' + } + }; + const DEFAULT_IDENTITY_RESPONSE = { IdentityIp: { responsePending: false, @@ -83,6 +146,31 @@ describe('IndexexchangeAdapter', function () { } }; + const DEFAULT_BIDDER_REQUEST_DATA = { + ac: 'j', + r: JSON.stringify({ + id: '345', + imp: [ + { + id: '1a2b3c4e', + video: { + w: 640, + h: 480, + placement: 1 + } + } + ], + site: { + ref: 'http://ref.com/ref.html', + page: 'http://page.com' + }, + }), + s: '21', + sd: 1, + t: 1000, + v: 8.1 + }; + describe('inherited functions', function () { it('should exists and is a function', function () { const adapter = newBidder(spec); @@ -91,11 +179,12 @@ describe('IndexexchangeAdapter', function () { }); describe('isBidRequestValid', function () { - it('should return true when required params found for a banner ad', function () { + it('should return true when required params found for a banner or video ad', function () { expect(spec.isBidRequestValid(DEFAULT_BANNER_VALID_BID[0])).to.equal(true); + expect(spec.isBidRequestValid(DEFAULT_VIDEO_VALID_BID[0])).to.equal(true); }); - it('should return true when optional params found for a banner ad', function () { + it('should return true when optional bidFloor params found for an ad', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; @@ -136,10 +225,10 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes is not banner', function () { + it('should return false when mediaTypes is not banner or video', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.mediaTypes = { - video: { + native: { sizes: [[300, 250]] } }; @@ -156,19 +245,13 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaType is not banner', function () { - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); - delete bid.params.mediaTypes; - bid.mediaType = 'banne'; - bid.sizes = [[300, 250]]; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when mediaType is video', function () { - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); - delete bid.params.mediaTypes; - bid.mediaType = 'video'; - bid.sizes = [[300, 250]]; + it('should return false when mediaTypes.video does not have sizes', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + bid.mediaTypes = { + video: { + size: [[300, 250]] + } + }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -195,6 +278,14 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); + it('should return true when mediaType is video', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + delete bid.mediaTypes; + bid.mediaType = 'video'; + bid.sizes = [[400, 100]]; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should return false when there is only bidFloor', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; @@ -232,7 +323,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return testCopy; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; }); afterEach(function() { @@ -343,7 +434,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return undefined; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -356,7 +447,7 @@ describe('IndexexchangeAdapter', function () { responsePending: true, data: {} } - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -366,7 +457,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending for all partners', function () { testCopy.IdentityIp.responsePending = true; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -377,7 +468,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending or not available for all partners', function () { testCopy.IdentityIp.responsePending = false; testCopy.IdentityIp.data = {}; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -387,8 +478,8 @@ describe('IndexexchangeAdapter', function () { }); }); - describe('buildRequestsBanner', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + describe('buildRequests', function () { + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const requestUrl = request.url; const requestMethod = request.method; const query = request.data; @@ -396,7 +487,7 @@ describe('IndexexchangeAdapter', function () { const bidWithoutMediaType = utils.deepClone(DEFAULT_BANNER_VALID_BID); delete bidWithoutMediaType[0].mediaTypes; bidWithoutMediaType[0].sizes = [[300, 250], [300, 600]]; - const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_BANNER_OPTION); + const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_OPTION)[0]; const queryWithoutMediaType = requestWithoutMediaType.data; it('request should be made to IX endpoint with GET method', function () { @@ -405,11 +496,12 @@ describe('IndexexchangeAdapter', function () { }); it('query object (version, siteID and request) should be correct', function () { - expect(query.v).to.equal(BIDDER_VERSION); + expect(query.v).to.equal(BANNER_ENDPOINT_VERSION); expect(query.s).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId); expect(query.r).to.exist; expect(query.ac).to.equal('j'); expect(query.sd).to.equal(1); + expect(query.nf).to.equal(1); }); it('payload should have correct format and value', function () { @@ -417,7 +509,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -445,7 +537,7 @@ describe('IndexexchangeAdapter', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.bidfloor).to.equal(bid.params.bidFloor); @@ -457,7 +549,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -484,7 +576,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 50; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); @@ -501,7 +593,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as string', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 'abc'; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); expect(impression.banner).to.exist; @@ -526,9 +618,9 @@ describe('IndexexchangeAdapter', function () { } }); - const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; - const expectedPageUrl = DEFAULT_BANNER_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; + const expectedPageUrl = DEFAULT_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; expect(pageUrl).to.equal(expectedPageUrl); }); @@ -540,10 +632,10 @@ describe('IndexexchangeAdapter', function () { } }); - const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestFirstPartyDataNumber.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); }); it('should not set first party or timeout if it is not present', function () { @@ -551,18 +643,18 @@ describe('IndexexchangeAdapter', function () { ix: {} }); - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); it('should not set first party or timeout if it is setConfig is not called', function () { - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); @@ -572,7 +664,7 @@ describe('IndexexchangeAdapter', function () { timeout: 500 } }); - const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; expect(requestWithTimeout.data.t).to.equal(500); }); @@ -583,14 +675,98 @@ describe('IndexexchangeAdapter', function () { timeout: '500' } }); - const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; expect(requestStringTimeout.data.t).to.be.undefined; }); + + it('request should contain both banner and video requests', function () { + const request = spec.buildRequests([DEFAULT_BANNER_VALID_BID[0], DEFAULT_VIDEO_VALID_BID[0]]); + + const bannerImp = JSON.parse(request[0].data.r).imp[0]; + expect(JSON.parse(request[0].data.v)).to.equal(BANNER_ENDPOINT_VERSION); + expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(bannerImp.banner).to.exist; + expect(bannerImp.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); + expect(bannerImp.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); + + const videoImp = JSON.parse(request[1].data.r).imp[0]; + expect(JSON.parse(request[1].data.v)).to.equal(VIDEO_ENDPOINT_VERSION); + expect(videoImp.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(videoImp.video).to.exist; + expect(videoImp.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(videoImp.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + }); }); - describe('interpretResponseBanner', function () { - it('should get correct bid response', function () { + describe('buildRequestVideo', function () { + const request = spec.buildRequests(DEFAULT_VIDEO_VALID_BID, DEFAULT_OPTION); + const query = request[0].data; + + it('query object (version, siteID and request) should be correct', function () { + expect(query.v).to.equal(VIDEO_ENDPOINT_VERSION); + expect(query.s).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId); + expect(query.r).to.exist; + expect(query.ac).to.equal('j'); + expect(query.sd).to.equal(1); + }); + + it('impression should have correct format and value', function () { + const impression = JSON.parse(query.r).imp[0]; + const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + expect(impression.video.placement).to.exist; + expect(impression.video.placement).to.equal(1); + expect(impression.video.minduration).to.exist; + expect(impression.video.minduration).to.equal(0); + expect(impression.video.mimes).to.exist; + expect(impression.video.mimes[0]).to.equal('video/mp4'); + expect(impression.video.mimes[1]).to.equal('video/webm'); + + expect(impression.video.skippable).to.equal(false); + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal(sidValue); + }); + + it('impression should have correct format when mediaType is specified.', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + delete bid.mediaTypes; + bid.mediaType = 'video'; + const requestBidFloor = spec.buildRequests([bid])[0]; + const impression = JSON.parse(requestBidFloor.data.r).imp[0]; + const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + expect(impression.video.placement).to.not.exist; + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal(sidValue); + }); + + it('should set correct placement if context is outstream', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + bid.mediaTypes.video.context = 'outstream'; + const request = spec.buildRequests([bid])[0]; + const impression = JSON.parse(request.data.r).imp[0]; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.placement).to.exist; + expect(impression.video.placement).to.equal(4); + }); + }); + + describe('interpretResponse', function () { + it('should get correct bid response for banner ad', function () { const expectedParse = [ { requestId: '1a2b3c4d', @@ -598,6 +774,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '
    ', currency: 'USD', ttl: 35, @@ -610,7 +787,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }); + const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -624,6 +801,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '-', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -636,8 +814,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); - expect(result[0]).to.deep.equal(expectedParse[0]); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); }); it('should set Japanese price correctly', function () { @@ -650,6 +827,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'JPY', ttl: 35, @@ -662,7 +840,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -676,6 +854,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -688,13 +867,38 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + expect(result[0]).to.deep.equal(expectedParse[0]); + }); + + it('should get correct bid response for video ad', function () { + const expectedParse = [ + { + requestId: '1a2b3c4e', + cpm: 1.1, + creativeId: '12346', + mediaType: 'video', + width: 640, + height: 480, + currency: 'USD', + ttl: 3600, + netRevenue: true, + dealId: undefined, + vastUrl: 'www.abcd.com/vast', + meta: { + networkId: 51, + brandId: 303326, + brandName: 'OECTB' + } + } + ]; + const result = spec.interpretResponse({ body: DEFAULT_VIDEO_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); it('bidrequest should have consent info if gdprApplies and consentString exist', function () { - const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -708,7 +912,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user).to.be.undefined; @@ -722,7 +926,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -731,7 +935,7 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have consent info if options.gdprConsent is undefined', function () { const options = {}; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user).to.be.undefined; @@ -740,10 +944,10 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have page if options is undefined', function () { const options = {}; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should not have page if options.refererInfo is an empty object', function () { @@ -751,10 +955,10 @@ describe('IndexexchangeAdapter', function () { refererInfo: {} }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should sent to secure endpoint if page url is secure', function () { @@ -764,10 +968,10 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.equal(options.refererInfo.referer); - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); }); }); From 8e198bb41e3e10aaa5b8ec5b3e63a50e5704651d Mon Sep 17 00:00:00 2001 From: Mirko Feddern Date: Tue, 25 Jun 2019 20:14:11 +0200 Subject: [PATCH 1302/1594] Add Outstream Renderer for Yieldlab Adapter (#3910) * Add Outstream Renderer * Fix playerSize overwrite Prebid is translating the playerSize to an array of arrays, so we have to return accordingly --- modules/yieldlabBidAdapter.js | 53 +++++++++++++++++++- modules/yieldlabBidAdapter.md | 2 +- test/spec/modules/yieldlabBidAdapter_spec.js | 17 +++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 1bbb3f11a2e..116f1aae0a8 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -2,11 +2,13 @@ import * as utils from '../src/utils' import { registerBidder } from '../src/adapters/bidderFactory' import find from 'core-js/library/fn/array/find' import { VIDEO, BANNER } from '../src/mediaTypes' +import { Renderer } from 'src/Renderer' const ENDPOINT = 'https://ad.yieldlab.net' const BIDDER_CODE = 'yieldlab' const BID_RESPONSE_TTL_SEC = 300 const CURRENCY_CODE = 'EUR' +const OUTSTREAMPLAYER_URL = 'https://ad2.movad.net/dynamic.ad?a=o193092&ma_loadEvent=ma-start-event' export const spec = { code: BIDDER_CODE, @@ -93,8 +95,23 @@ export const spec = { } if (isVideo(bidRequest)) { + const playersize = getPlayerSize(bidRequest) + if (playersize) { + bidResponse.width = playersize[0] + bidResponse.height = playersize[1] + } bidResponse.mediaType = VIDEO bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/${customsize[0]}x${customsize[1]}?ts=${timestamp}${extId}` + + if (isOutstream(bidRequest)) { + const renderer = Renderer.install({ + id: bidRequest.bidId, + url: OUTSTREAMPLAYER_URL, + loaded: false + }) + renderer.setRender(outstreamRender) + bidResponse.renderer = renderer + } } bidResponses.push(bidResponse) @@ -106,13 +123,33 @@ export const spec = { /** * Is this a video format? - * @param {String} format + * @param {Object} format * @returns {Boolean} */ function isVideo (format) { return utils.deepAccess(format, 'mediaTypes.video') } +/** + * Is this an outstream context? + * @param {Object} format + * @returns {Boolean} + */ +function isOutstream (format) { + let context = utils.deepAccess(format, 'mediaTypes.video.context') + return (context === 'outstream') +} + +/** + * Gets optional player size + * @param {Object} format + * @returns {Array} + */ +function getPlayerSize (format) { + let playerSize = utils.deepAccess(format, 'mediaTypes.video.playerSize') + return (playerSize && utils.isArray(playerSize[0])) ? playerSize[0] : playerSize +} + /** * Expands a 'WxH' string as a 2-element [W, H] array * @param {String} size @@ -137,4 +174,18 @@ function createQueryString (obj) { return str.join('&') } +/** + * Handles an outstream response after the library is loaded + * @param {Object} bid + */ +function outstreamRender(bid) { + bid.renderer.push(() => { + window.ma_width = bid.width + window.ma_height = bid.height + window.ma_vastUrl = bid.vastUrl + window.ma_container = bid.adUnitCode + window.document.dispatchEvent(new Event('ma-start-event')) + }); +} + registerBidder(spec) diff --git a/modules/yieldlabBidAdapter.md b/modules/yieldlabBidAdapter.md index de93baf42ae..37897b83f12 100644 --- a/modules/yieldlabBidAdapter.md +++ b/modules/yieldlabBidAdapter.md @@ -34,7 +34,7 @@ Module that connects to Yieldlab's demand sources sizes: [[640, 480]], mediaTypes: { video: { - context: "instream" + context: "instream" // or "outstream" } }, bids: [{ diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index c2e12408cdd..c8709969e00 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -148,5 +148,22 @@ describe('yieldlabBidAdapter', function () { expect(result[0].vastUrl).to.include('https://ad.yieldlab.net/d/1111/2222/728x90?ts=') expect(result[0].vastUrl).to.include('&id=abc') }) + + it('should add renderer if outstream context', function () { + const OUTSTREAM_REQUEST = Object.assign({}, REQUEST, { + 'mediaTypes': { + 'video': { + 'playerSize': [[640, 480]], + 'context': 'outstream' + } + } + }) + const result = spec.interpretResponse({body: [RESPONSE]}, {validBidRequests: [OUTSTREAM_REQUEST]}) + + expect(result[0].renderer.id).to.equal('2d925f27f5079f') + expect(result[0].renderer.url).to.equal('https://ad2.movad.net/dynamic.ad?a=o193092&ma_loadEvent=ma-start-event') + expect(result[0].width).to.equal(640) + expect(result[0].height).to.equal(480) + }) }) }) From 64a258a7d2b29198cd16b946c780ad0c82670552 Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Tue, 25 Jun 2019 14:44:32 -0400 Subject: [PATCH 1303/1594] Standardized COPPA support (#3936) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * Send coppa flag on requests to OpenRTB from Prebid server * Support coppa flag being set in Prebid config * Add unit tests for deepSetValue util function --- modules/arteebeeBidAdapter.js | 2 +- modules/openxBidAdapter.js | 2 +- modules/openxoutstreamBidAdapter.js | 2 +- modules/prebidServerBidAdapter/index.js | 4 ++++ modules/rubiconBidAdapter.js | 8 ++++++++ test/spec/utils_spec.js | 23 +++++++++++++++++++++++ 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/modules/arteebeeBidAdapter.js b/modules/arteebeeBidAdapter.js index ddf728a143e..74d5d5d3d52 100644 --- a/modules/arteebeeBidAdapter.js +++ b/modules/arteebeeBidAdapter.js @@ -96,7 +96,7 @@ function makeRtbRequest(req, bidderRequest) { 'tmax': config.getConfig('bidderTimeout') }; - if (req.params.coppa) { + if (config.getConfig('coppa') === true || req.params.coppa) { rtbReq.regs = {coppa: 1}; } diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 8236be8c2e5..ef60d6e1856 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -262,7 +262,7 @@ function buildOXBannerRequest(bids, bidderRequest) { queryParams.ns = 1; } - if (bids.some(bid => bid.params.coppa)) { + if (config.getConfig('coppa') === true || bids.some(bid => bid.params.coppa)) { queryParams.tfcd = 1; } diff --git a/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js index 42c7a3fff32..9011a949e7b 100644 --- a/modules/openxoutstreamBidAdapter.js +++ b/modules/openxoutstreamBidAdapter.js @@ -114,7 +114,7 @@ function buildOXBannerRequest(bid, bidderRequest) { queryParams.ns = 1; } - if (bid.params.coppa) { + if (config.getConfig('coppa') === true || bid.params.coppa) { queryParams.tfcd = 1; } diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 028f02d9662..4ac1bccaeda 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -580,6 +580,10 @@ const OPEN_RTB_PROTOCOL = { utils.deepSetValue(request, 'user.ext.consent', bidRequests[0].gdprConsent.consentString); } + if (getConfig('coppa') === true) { + utils.deepSetValue(request, 'regs.coppa', 1); + } + return request; }, diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index abeebd2e1b2..c3d0b48f14b 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -233,6 +233,10 @@ export const spec = { } } + if (config.getConfig('coppa') === true) { + utils.deepSetValue(request, 'regs.coppa', 1); + } + return { method: 'POST', url: VIDEO_ENDPOINT, @@ -434,6 +438,10 @@ export const spec = { const digitrustParams = _getDigiTrustQueryParams(bidRequest, 'FASTLANE'); Object.assign(data, digitrustParams); + if (config.getConfig('coppa') === true) { + data['coppa'] = 1; + } + return data; }, diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index df1c9b66b28..ff9b6ec2371 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -626,6 +626,29 @@ describe('Utils', function () { }); }); + describe('deepSetValue', function() { + it('should set existing properties at various depths', function() { + const testObj = { + prop: 'value', + nestedObj: { + nestedProp: 'nestedValue' + } + }; + utils.deepSetValue(testObj, 'prop', 'newValue'); + assert.equal(testObj.prop, 'newValue'); + utils.deepSetValue(testObj, 'nestedObj.nestedProp', 'newNestedValue'); + assert.equal(testObj.nestedObj.nestedProp, 'newNestedValue'); + }); + + it('should create object levels between top and bottom of given path if they do not exist', function() { + const testObj = {}; + utils.deepSetValue(testObj, 'level1.level2', 'value'); + assert.notEqual(testObj.level1, undefined); + assert.notEqual(testObj.level1.level2, undefined); + assert.equal(testObj.level1.level2, 'value'); + }); + }); + describe('createContentToExecuteExtScriptInFriendlyFrame', function () { it('should return empty string if url is not passed', function () { var output = utils.createContentToExecuteExtScriptInFriendlyFrame(); From e55684b0d7cf61dfb817022978d3ca5561d4b4da Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 25 Jun 2019 15:12:04 -0400 Subject: [PATCH 1304/1594] Adding privacy_supported flag (#3943) --- modules/appnexusBidAdapter.js | 4 ++++ test/spec/modules/appnexusBidAdapter_spec.js | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index e0ae19187b2..50c5a0e6f04 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -686,6 +686,10 @@ function buildNativeRequest(params) { request[requestKey].sizes = transformSizes(request[requestKey].sizes); } } + + if (requestKey === NATIVE_MAPPING.privacyLink) { + request.privacy_supported = true; + } }); return request; diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 9e37f6cbffb..e55e3e32029 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -432,7 +432,8 @@ describe('AppNexusAdapter', function () { likes: {required: true}, phone: {required: true}, price: {required: true}, - saleprice: {required: true} + saleprice: {required: true}, + privacy_supported: true }); }); From 5e1d88986acdc902a0b0a919ad33db2d61fac30f Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 25 Jun 2019 15:47:00 -0400 Subject: [PATCH 1305/1594] Prebid 2.21.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4e2985e1bd..6c0d2ace797 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.21.0-pre", + "version": "2.21.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 426676c829fbd398b2605df44537ca5f15fcd88b Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 25 Jun 2019 16:06:35 -0400 Subject: [PATCH 1306/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c0d2ace797..ae1d5ba514a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.21.0", + "version": "2.22.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 6e0264908d9fd2dcb97aa53bda955eb815eb8ed2 Mon Sep 17 00:00:00 2001 From: Ryo Kato Date: Wed, 26 Jun 2019 21:44:07 +0900 Subject: [PATCH 1307/1594] Fix import paths in adapters (#3946) --- modules/bidglassBidAdapter.js | 4 ++-- modules/hpmdnetworkBidAdapter.js | 4 ++-- modules/open8BidAdapter.js | 2 +- modules/reloadBidAdapter.js | 4 ++-- modules/yieldlabBidAdapter.js | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/bidglassBidAdapter.js b/modules/bidglassBidAdapter.js index 1898d1220fa..f5991f7f3a5 100644 --- a/modules/bidglassBidAdapter.js +++ b/modules/bidglassBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; +import * as utils from '../src/utils'; // import {config} from 'src/config'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import {registerBidder} from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'bidglass'; diff --git a/modules/hpmdnetworkBidAdapter.js b/modules/hpmdnetworkBidAdapter.js index ad17caba7bc..b23d17a7bf3 100644 --- a/modules/hpmdnetworkBidAdapter.js +++ b/modules/hpmdnetworkBidAdapter.js @@ -1,5 +1,5 @@ -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'hpmdnetwork'; const BIDDER_CODE_ALIAS = 'hpmd'; diff --git a/modules/open8BidAdapter.js b/modules/open8BidAdapter.js index 3c2b94a528a..bac95f4499e 100644 --- a/modules/open8BidAdapter.js +++ b/modules/open8BidAdapter.js @@ -1,6 +1,6 @@ import { Renderer } from '../src/Renderer'; import {ajax} from '../src/ajax'; -import * as utils from 'src/utils'; +import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { VIDEO, BANNER } from '../src/mediaTypes'; diff --git a/modules/reloadBidAdapter.js b/modules/reloadBidAdapter.js index a50949825a9..a5f5ba43c60 100644 --- a/modules/reloadBidAdapter.js +++ b/modules/reloadBidAdapter.js @@ -1,11 +1,11 @@ import { BANNER } - from 'src/mediaTypes'; + from '../src/mediaTypes'; import { registerBidder } - from 'src/adapters/bidderFactory'; + from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'reload'; diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 116f1aae0a8..9af3de24cb1 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -2,7 +2,7 @@ import * as utils from '../src/utils' import { registerBidder } from '../src/adapters/bidderFactory' import find from 'core-js/library/fn/array/find' import { VIDEO, BANNER } from '../src/mediaTypes' -import { Renderer } from 'src/Renderer' +import { Renderer } from '../src/Renderer' const ENDPOINT = 'https://ad.yieldlab.net' const BIDDER_CODE = 'yieldlab' From 5cdd5a37574dcd007718978b60b0528e3ca8f23d Mon Sep 17 00:00:00 2001 From: afsheenb Date: Wed, 26 Jun 2019 09:02:35 -0400 Subject: [PATCH 1308/1594] ozone adapter 2.1 - bug fix for multi bids + GDPR parameter handling (#3916) * bug fix for multi bids + GDPR parameter handling * Updated spec files and adapter files to remove references to ozoneData and more stringent GDPR checks. --- modules/ozoneBidAdapter.js | 67 +++-- modules/ozoneBidAdapter.md | 6 +- test/spec/modules/ozoneBidAdapter_spec.js | 300 ++++++++++++++++++---- 3 files changed, 304 insertions(+), 69 deletions(-) diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index c5d9f16ef58..7ab69f1e37a 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -8,10 +8,10 @@ import { Renderer } from '../src/Renderer' const BIDDER_CODE = 'ozone'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; -const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js' - const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; -const OZONEVERSION = '2.0.0'; +const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js'; + +const OZONEVERSION = '2.1.1'; export const spec = { code: BIDDER_CODE, @@ -57,12 +57,6 @@ export const spec = { utils.logInfo('OZONE: OZONE BID ADAPTER VALIDATION FAILED : customParams should be renamed to customData'); return false; } - if (bid.params.hasOwnProperty('ozoneData')) { - if (typeof bid.params.ozoneData !== 'object') { - utils.logInfo('OZONE: OZONE BID ADAPTER VALIDATION FAILED : ozoneData is not an object'); - return false; - } - } if (bid.params.hasOwnProperty('lotameData')) { if (typeof bid.params.lotameData !== 'object') { utils.logInfo('OZONE: OZONE BID ADAPTER VALIDATION FAILED : lotameData is not an object'); @@ -90,18 +84,35 @@ export const spec = { let htmlParams = validBidRequests[0].params; // the html page config params will be included in each element 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'] - if (bidderRequest.gdprConsent) { + + if (bidderRequest && bidderRequest.gdprConsent) { utils.logInfo('OZONE: ADDING GDPR info'); ozoneRequest.regs = {}; ozoneRequest.regs.ext = {}; - ozoneRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; + ozoneRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; if (ozoneRequest.regs.ext.gdpr) { - ozoneRequest.user = {}; - ozoneRequest.user.ext = {'consent': bidderRequest.gdprConsent.consentString}; + ozoneRequest.user = ozoneRequest.user || {}; + if ( + bidderRequest.gdprConsent.vendorData && + bidderRequest.gdprConsent.vendorData.vendorConsents && + typeof bidderRequest.gdprConsent.consentString !== 'undefined' + ) { + utils.logInfo('OZONE: found all info we need for GDPR - will add info to request object'); + ozoneRequest.user.ext = {'consent': bidderRequest.gdprConsent.consentString}; + // are we able to make this request? + let vendorConsents = bidderRequest.gdprConsent.vendorData.vendorConsents; + let boolGdprConsentForOzone = vendorConsents[524]; + let arrGdprConsents = toFlatArray(bidderRequest.gdprConsent.vendorData.purposeConsents); + ozoneRequest.regs.ext.oz_con = boolGdprConsentForOzone ? 1 : 0; + ozoneRequest.regs.ext.gap = arrGdprConsents; + } + } else { + utils.logInfo('OZONE: **** Failed to find required info for GDPR for request object, even though bidderRequest.gdprConsent is TRUE ****'); } } else { - utils.logInfo('OZONE: WILL NOT ADD GDPR info'); + utils.logInfo('OZONE: WILL NOT ADD GDPR info; no bidderRequest.gdprConsent object was present.'); } + ozoneRequest.device = {'w': window.innerWidth, 'h': window.innerHeight}; let tosendtags = validBidRequests.map(ozoneBidRequest => { var obj = {}; @@ -157,9 +168,6 @@ export const spec = { if (ozoneBidRequest.params.hasOwnProperty('customData')) { obj.ext.ozone.customData = ozoneBidRequest.params.customData; } - if (ozoneBidRequest.params.hasOwnProperty('ozoneData')) { - obj.ext.ozone.ozoneData = ozoneBidRequest.params.ozoneData; - } if (ozoneBidRequest.params.hasOwnProperty('lotameData')) { obj.ext.ozone.lotameData = ozoneBidRequest.params.lotameData; } @@ -226,8 +234,8 @@ export const spec = { serverResponse.seatbid = injectAdIdsIntoAllBidResponses(serverResponse.seatbid); // we now make sure that each bid in the bidresponse has a unique (within page) adId attribute. for (let i = 0; i < serverResponse.seatbid.length; i++) { let sb = serverResponse.seatbid[i]; - const {defaultWidth, defaultHeight} = defaultSize(request.bidderRequest.bids[i]); for (let j = 0; j < sb.bid.length; j++) { + const {defaultWidth, defaultHeight} = defaultSize(request.bidderRequest.bids[j]); // there should be the same number of bids as requests, so index [j] should always exist. let thisBid = ozoneAddStandardProperties(sb.bid[j], defaultWidth, defaultHeight); // from https://github.com/prebid/Prebid.js/pull/1082 @@ -310,6 +318,13 @@ export function checkDeepArray(Arr) { } } export function defaultSize(thebidObj) { + if (!thebidObj) { + utils.logInfo('defaultSize received empty bid obj! going to return fixed default size'); + return { + 'defaultHeight': 250, + 'defaultWidth': 300 + }; + } const {sizes} = thebidObj; const returnObject = {}; returnObject.defaultWidth = checkDeepArray(sizes)[0]; @@ -499,5 +514,21 @@ function outstreamRender(bid) { window.ozoneVideo.outstreamRender(bid); } +/** + * convert {1: true, + 2: true, + 3: true, + 4: true, + 5: true} + to : [1,2,3,4,5] + * @param obj + */ +function toFlatArray(obj) { + let ret = []; + Object.keys(obj).forEach(function(key) { if (obj[key]) { ret.push(parseInt(key)); } }); + utils.logInfo('toFlatArray:', obj, 'returning', ret); + return ret; +} + registerBidder(spec); utils.logInfo('OZONE: ozoneBidAdapter ended'); diff --git a/modules/ozoneBidAdapter.md b/modules/ozoneBidAdapter.md index 89760697088..1fe5e681e25 100644 --- a/modules/ozoneBidAdapter.md +++ b/modules/ozoneBidAdapter.md @@ -36,8 +36,7 @@ adUnits = [{ publisherId: 'OZONENUK0001', /* an ID to identify the publisher account - required */ siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ placementId: '0420420421', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */ - customData": [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"],}}] /* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ - ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ + customData: [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}],/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ lotameData: {"key1": "value1", "key2": "value2"} /* optional JSON placeholder for passing Lotame DMP data */ } }] @@ -65,8 +64,7 @@ adUnits = [{ siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ customData: [{"settings": {}, "targeting": { "key": "value", "key2": ["value1", "value2"]}}] placementId: '0440440442', /* an ID used to identify the piece of inventory - required - for unruly test use 0440440442. */ - customData": [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"],}}] /* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ - ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ + customData: [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}],/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ lotameData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for passing Lotame DMP data */ video: { skippable: true, /* optional */ diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index b0f252d4469..e17d51804a1 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -18,7 +18,7 @@ var validBidRequests = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -45,7 +45,7 @@ var validBidRequestsNoSizes = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; @@ -59,7 +59,7 @@ var validBidRequestsWithBannerMediaType = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, mediaTypes: {banner: {sizes: [[300, 250], [300, 600]]}}, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -73,7 +73,7 @@ var validBidRequestsWithNonBannerMediaTypesAndValidOutstreamVideo = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: {skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode'} } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: {skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode'} } ] }, mediaTypes: {video: {mimes: ['video/mp4'], 'context': 'outstream'}, native: {info: 'dummy data'}}, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -92,7 +92,7 @@ var validBidderRequest = { bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' }], @@ -100,6 +100,65 @@ var validBidderRequest = { start: 1536838908987, timeout: 3000 }; + +// 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) +var bidderRequestWithFullGdpr = { + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + auctionStart: 1536838908986, + bidderCode: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + bids: [{ + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + bidId: '2899ec066a91ff8', + bidRequestsCount: 1, + bidder: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + sizes: [[300, 250], [300, 600]], + transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' + }], + doneCbCallCount: 1, + start: 1536838908987, + timeout: 3000, + gdprConsent: { + 'consentString': 'BOh7mtYOh7mtYAcABBENCU-AAAAncgPIXJiiAoao0PxBFkgCAC8ACIAAQAQQAAIAAAIAAAhBGAAAQAQAEQgAAAAAAABAAAAAAAAAAAAAAACAAAAAAAACgAAAAABAAAAQAAAAAAA', + 'vendorData': { + 'metadata': 'BOh7mtYOh7mtYAcABBENCU-AAAAncgPIXJiiAoao0PxBFkgCAC8ACIAAQAQQAAIAAAIAAAhBGAAAQAQAEQgAAAAAAABAAAAAAAAAAAAAAACAAAAAAAACgAAAAABAAAAQAAAAAAA', + 'gdprApplies': true, + 'hasGlobalScope': false, + 'cookieVersion': '1', + 'created': '2019-05-31T12:46:48.825', + 'lastUpdated': '2019-05-31T12:46:48.825', + 'cmpId': '28', + 'cmpVersion': '1', + 'consentLanguage': 'en', + 'consentScreen': '1', + 'vendorListVersion': 148, + 'maxVendorId': 631, + 'purposeConsents': { + '1': true, + '2': true, + '3': true, + '4': true, + '5': true + }, + 'vendorConsents': { + '468': true, + '522': true, + '524': true, /* 524 is ozone */ + '565': true, + '591': true + } + }, + 'gdprApplies': true + }, +}; + // make sure the impid matches the request bidId var validResponse = { 'body': { @@ -216,7 +275,97 @@ var validOutstreamResponse = { } }, 'headers': {} -} +}; +var validBidResponse1adWith2Bidders = { + 'body': { + 'id': '91221f96-b931-4acc-8f05-c2a1186fa5ac', + 'seatbid': [ + { + 'bid': [ + { + 'id': 'd6198807-7a53-4141-b2db-d2cb754d68ba', + 'impid': '2899ec066a91ff8', + 'price': 0.36754, + 'adm': '', + 'adid': '134928661', + 'adomain': [ + 'somecompany.com' + ], + 'iurl': 'https:\/\/ams1-ib.adnxs.com\/cr?id=134928661', + 'cid': '8825', + 'crid': '134928661', + 'cat': [ + 'IAB8-15', + 'IAB8-16', + 'IAB8-4', + 'IAB8-1', + 'IAB8-14', + 'IAB8-6', + 'IAB8-13', + 'IAB8-3', + 'IAB8-17', + 'IAB8-12', + 'IAB8-8', + 'IAB8-7', + 'IAB8-2', + 'IAB8-9', + 'IAB8', + 'IAB8-11' + ], + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 14640, + 'auction_id': 1.8369641905139e+18, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + } + ], + 'seat': 'appnexus' + }, + { + 'bid': [ + { + 'id': '75665207-a1ca-49db-ba0e-a5e9c7d26f32', + 'impid': '37fff511779365a', + 'price': 1.046, + 'adm': '
    removed
    ', + 'adomain': [ + 'kx.com' + ], + 'crid': '13005', + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + } + } + } + ], + 'seat': 'openx' + } + ], + 'ext': { + 'responsetimemillis': { + 'appnexus': 91, + 'openx': 109, + 'ozappnexus': 46, + 'ozbeeswax': 2, + 'pangaea': 91 + } + } + }, + 'headers': {} +}; describe('ozone Adapter', function () { describe('isBidRequestValid', function () { @@ -242,7 +391,6 @@ describe('ozone Adapter', function () { publisherId: '9876abcd12-3', siteId: '1234567890', customData: {'gender': 'bart', 'age': 'low'}, - ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, }, siteId: 1234567890 @@ -485,20 +633,6 @@ describe('ozone Adapter', function () { expect(spec.isBidRequestValid(xCustomParams)).to.equal(false); }); - var xBadOzoneData = { - bidder: BIDDER_CODE, - params: { - 'placementId': '1234567890', - 'publisherId': '9876abcd12-3', - 'ozoneData': 'this should be an object', - siteId: '1234567890' - } - }; - - it('should not validate ozoneData being sent', function () { - expect(spec.isBidRequestValid(xBadOzoneData)).to.equal(false); - }); - var xBadCustomData = { bidder: BIDDER_CODE, params: { @@ -508,10 +642,10 @@ describe('ozone Adapter', function () { siteId: '1234567890' } }; - it('should not validate ozoneData being sent', function () { expect(spec.isBidRequestValid(xBadCustomData)).to.equal(false); }); + var xBadLotame = { bidder: BIDDER_CODE, params: { @@ -521,7 +655,6 @@ describe('ozone Adapter', function () { siteId: '1234567890' } }; - it('should not validate lotameData being sent', function () { expect(spec.isBidRequestValid(xBadLotame)).to.equal(false); }); @@ -585,10 +718,21 @@ describe('ozone Adapter', function () { const request = spec.buildRequests(validBidRequests, validBidderRequest); expect(request.data).to.be.a('string'); var data = JSON.parse(request.data); - expect(data.imp[0].ext.ozone.ozoneData).to.be.an('object'); expect(data.imp[0].ext.ozone.lotameData).to.be.an('object'); expect(data.imp[0].ext.ozone.customData).to.be.an('object'); - expect(request).not.to.have.key('ozoneData'); + expect(request).not.to.have.key('lotameData'); + expect(request).not.to.have.key('customData'); + }); + + it('ignores ozoneData in & after version 2.1.1', function () { + let validBidRequestsWithOzoneData = validBidRequests; + validBidRequestsWithOzoneData[0].params.ozoneData = {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}; + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request.data).to.be.a('string'); + var data = JSON.parse(request.data); + expect(data.imp[0].ext.ozone.lotameData).to.be.an('object'); + expect(data.imp[0].ext.ozone.customData).to.be.an('object'); + expect(data.imp[0].ext.ozone.ozoneData).to.be.undefined; expect(request).not.to.have.key('lotameData'); expect(request).not.to.have.key('customData'); }); @@ -618,28 +762,6 @@ describe('ozone Adapter', function () { expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); }); - it('should add gdpr consent information to the request', function () { - let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; - let bidderRequest = { - 'bidderCode': 'ozone', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'gdprConsent': { - consentString: consentString, - gdprApplies: true - } - }; - bidderRequest.bids = validBidRequests; - - const request = spec.buildRequests(validBidRequests, bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.user.ext).to.exist; - expect(payload.user.ext.consent).to.exist.and.to.equal(consentString); - expect(payload.regs.ext.gdpr).to.exist.and.to.equal(1); - }); - it('should be able to handle non-single requests', function () { config.setConfig({'ozone': {'singleRequest': false}}); const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest); @@ -648,6 +770,82 @@ describe('ozone Adapter', function () { // need to reset the singleRequest config flag: config.setConfig({'ozone': {'singleRequest': true}}); }); + + it('should add gdpr consent information to the request when ozone is true', 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.gdprConsent = { + consentString: consentString, + gdprApplies: true, + vendorData: { + vendorConsents: {524: true}, + purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + } + } + + const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.regs.ext.gdpr).to.equal(1); + expect(payload.regs.ext.oz_con).to.exist.and.to.equal(1); + expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 2, 3, 4, 5]); + }); + + it('should add correct gdpr consent information to the request when user has accepted only some purpose consents', 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.gdprConsent = { + consentString: consentString, + gdprApplies: true, + vendorData: { + vendorConsents: {524: true}, + purposeConsents: {1: true, 4: true, 5: true} + } + } + + const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.regs.ext.gdpr).to.equal(1); + expect(payload.regs.ext.oz_con).to.exist.and.to.equal(1); + expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 4, 5]); + }); + + it('should add gdpr consent information to the request when ozone is false', 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.gdprConsent = { + consentString: consentString, + gdprApplies: true, + vendorData: { + vendorConsents: {}, /* 524 is not present */ + purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + } + }; + + const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.regs.ext.gdpr).to.equal(1); + expect(payload.regs.ext.oz_con).to.exist.and.to.equal(0); + expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 2, 3, 4, 5]); + }); + + it('should set regs.ext.gdpr flag to 0 when gdprApplies is false', 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.gdprConsent = { + consentString: consentString, + gdprApplies: false, + vendorData: { + vendorConsents: {}, /* 524 is not present */ + purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + } + }; + + const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.regs.ext.gdpr).to.equal(0); + expect(payload.regs.ext.oz_con).to.be.undefined; + expect(payload.regs.ext.gap).to.be.undefined; + }); }); describe('interpretResponse', function () { @@ -673,11 +871,13 @@ describe('ozone Adapter', function () { const result = spec.interpretResponse(validResponse, request); expect(result.length).to.equal(1); }); + it('should fail ok if no seatbid in server response', function () { const result = spec.interpretResponse({}, {}); expect(result).to.be.an('array'); expect(result).to.be.empty; }); + it('should fail ok if seatbid is not an array', function () { const result = spec.interpretResponse({'body': {'seatbid': 'nothing_here'}}, {}); expect(result).to.be.an('array'); @@ -690,6 +890,12 @@ describe('ozone Adapter', function () { const bid = result[0]; expect(bid.renderer).to.be.an.instanceOf(Renderer); }); + + it('should correctly parse response where there are more bidders than ad slots', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + const result = spec.interpretResponse(validBidResponse1adWith2Bidders, request); + expect(result.length).to.equal(2); + }); }); describe('userSyncs', function () { From 7b70c14750bac886ba7e34c2ccc3189392a1747b Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Thu, 27 Jun 2019 12:53:04 -0700 Subject: [PATCH 1309/1594] added cur to ortb --- modules/prebidServerBidAdapter/index.js | 8 +++++ .../modules/prebidServerBidAdapter_spec.js | 31 ++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 4ac1bccaeda..1d177464b9f 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -523,6 +523,14 @@ const OPEN_RTB_PROTOCOL = { request.ext.prebid = Object.assign(request.ext.prebid, _s2sConfig.extPrebid); } + /** + * @type {(string[]|undefined)} - OpenRTB property 'cur', currencies available for bids + */ + const adServerCur = config.getConfig('currency.adServerCurrency'); + if (Array.isArray(adServerCur) && adServerCur.length) { + request.cur = adServerCur.slice(); + } + _appendSiteAppDevice(request); const digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index e2a3a5b111a..61db09b6451 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -831,7 +831,36 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; ; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); - }) + }); + + it('setting currency.adServerCurrency results in the openRTB JSON containing cur: ["AAA"]', function () { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + config.setConfig({ + currency: {adServerCurrency: ['USD', 'GB', 'UK', 'AU']}, + s2sConfig: ortb2Config + }); + + const userIdBidRequest = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); + + const parsedRequestBody = JSON.parse(requests[0].requestBody); + expect(parsedRequestBody.cur).to.deep.equal(['USD', 'GB', 'UK', 'AU']); + }); + + it('when currency.adServerCurrency is unset, the OpenRTB JSON should not contain cur', function () { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + config.setConfig({ + s2sConfig: ortb2Config + }); + + const userIdBidRequest = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); + + const parsedRequestBody = JSON.parse(requests[0].requestBody); + expect(typeof parsedRequestBody.cur).to.equal('undefined'); + }); it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () { const s2sConfig = Object.assign({}, CONFIG, { From 99a165af280584324a074f19abf674481f89aa6c Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Thu, 27 Jun 2019 13:10:52 -0700 Subject: [PATCH 1310/1594] Revert "added cur to ortb" This reverts commit 7b70c14750bac886ba7e34c2ccc3189392a1747b. --- modules/prebidServerBidAdapter/index.js | 8 ----- .../modules/prebidServerBidAdapter_spec.js | 31 +------------------ 2 files changed, 1 insertion(+), 38 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 1d177464b9f..4ac1bccaeda 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -523,14 +523,6 @@ const OPEN_RTB_PROTOCOL = { request.ext.prebid = Object.assign(request.ext.prebid, _s2sConfig.extPrebid); } - /** - * @type {(string[]|undefined)} - OpenRTB property 'cur', currencies available for bids - */ - const adServerCur = config.getConfig('currency.adServerCurrency'); - if (Array.isArray(adServerCur) && adServerCur.length) { - request.cur = adServerCur.slice(); - } - _appendSiteAppDevice(request); const digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 61db09b6451..e2a3a5b111a 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -831,36 +831,7 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; ; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); - }); - - it('setting currency.adServerCurrency results in the openRTB JSON containing cur: ["AAA"]', function () { - let ortb2Config = utils.deepClone(CONFIG); - ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; - config.setConfig({ - currency: {adServerCurrency: ['USD', 'GB', 'UK', 'AU']}, - s2sConfig: ortb2Config - }); - - const userIdBidRequest = utils.deepClone(BID_REQUESTS); - adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); - - const parsedRequestBody = JSON.parse(requests[0].requestBody); - expect(parsedRequestBody.cur).to.deep.equal(['USD', 'GB', 'UK', 'AU']); - }); - - it('when currency.adServerCurrency is unset, the OpenRTB JSON should not contain cur', function () { - let ortb2Config = utils.deepClone(CONFIG); - ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; - config.setConfig({ - s2sConfig: ortb2Config - }); - - const userIdBidRequest = utils.deepClone(BID_REQUESTS); - adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); - - const parsedRequestBody = JSON.parse(requests[0].requestBody); - expect(typeof parsedRequestBody.cur).to.equal('undefined'); - }); + }) it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () { const s2sConfig = Object.assign({}, CONFIG, { From cec25d584e6f1e2f744a74f7683e61146ba16d5b Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Fri, 28 Jun 2019 16:04:00 +0100 Subject: [PATCH 1311/1594] Added 640x320 size (#3954) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index c3d0b48f14b..881ce480aef 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -83,6 +83,7 @@ var sizeMap = { 126: '200x600', 144: '980x600', 145: '980x150', + 156: '640x320', 159: '320x250', 179: '250x600', 195: '600x300', From bac5e3bf33a2c99f42174e5623618b0dc5ecc2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deivydas=20=C5=A0abaras?= Date: Fri, 28 Jun 2019 19:45:04 +0100 Subject: [PATCH 1312/1594] OpenX should run only banner auction if it is multi format solution (#3940) --- modules/openxBidAdapter.js | 2 +- test/spec/modules/openxBidAdapter_spec.js | 35 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index ef60d6e1856..7be1023450f 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -75,7 +75,7 @@ export const spec = { }; function isVideoRequest(bidRequest) { - return utils.deepAccess(bidRequest, 'mediaTypes.video') || bidRequest.mediaType === VIDEO; + return (utils.deepAccess(bidRequest, 'mediaTypes.video') && !utils.deepAccess(bidRequest, 'mediaTypes.banner')) || bidRequest.mediaType === VIDEO; } function createBannerBidResponses(oxResponseObj, {bids, startTime}) { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 0fda846faa1..cf8f4f8d62b 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -178,6 +178,41 @@ describe('OpenxAdapter', function () { }); }); + describe('when request is for a multiformat ad', function () { + describe('and request config uses mediaTypes video and banner', () => { + const multiformatBid = { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + playerSize: [300, 250] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; + it('should return true multisize when required params found', function () { + expect(spec.isBidRequestValid(multiformatBid)).to.equal(true); + }); + + it('should send bid request to openx url via GET, with mediaType specified as banner', function () { + const request = spec.buildRequests([multiformatBid]); + expect(request[0].url).to.equal(`//${multiformatBid.params.delDomain}${URLBASE}`); + expect(request[0].data.ph).to.be.undefined; + expect(request[0].method).to.equal('GET'); + }); + }); + }); + describe('when request is for a video ad', function () { describe('and request config uses mediaTypes', () => { const videoBidWithMediaTypes = { From 2bd04a1f9b7f706d9c60d8b1f401d9b743a8c8a3 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Fri, 28 Jun 2019 12:21:42 -0700 Subject: [PATCH 1313/1594] Update creative.html (#3955) Updating for the new safe frame issue discovered, see https://github.com/prebid/prebid-universal-creative/pull/64/ for more details! --- integrationExamples/gpt/x-domain/creative.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integrationExamples/gpt/x-domain/creative.html b/integrationExamples/gpt/x-domain/creative.html index 3b0058f2ee8..a6981706227 100644 --- a/integrationExamples/gpt/x-domain/creative.html +++ b/integrationExamples/gpt/x-domain/creative.html @@ -2,10 +2,11 @@ // 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 +let windowLocation = window.location; var urlParser = document.createElement('a'); urlParser.href = '%%PATTERN:url%%'; var publisherDomain = urlParser.protocol + '//' + urlParser.hostname; -var adServerDomain = urlParser.protocol + '//tpc.googlesyndication.com'; +var adServerDomain = windowLocation.protocol + '//tpc.googlesyndication.com'; function renderAd(ev) { var key = ev.message ? 'message' : 'data'; From 9c736313c3181adbf2cce3e84a8fa1946fa3f946 Mon Sep 17 00:00:00 2001 From: ix-certification Date: Mon, 1 Jul 2019 15:34:18 -0400 Subject: [PATCH 1314/1594] Revert addition of video support to IX adapter as it is still in testing (#3956) --- modules/ixBidAdapter.js | 366 +++++++++---------------- modules/ixBidAdapter.md | 128 +-------- test/spec/modules/ixBidAdapter_spec.js | 344 +++++------------------ 3 files changed, 210 insertions(+), 628 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index f26c5e413c5..c63b920dc93 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -1,75 +1,38 @@ import * as utils from '../src/utils'; -import { BANNER, VIDEO } from '../src/mediaTypes'; -import find from 'core-js/library/fn/array/find'; +import { BANNER } from '../src/mediaTypes'; import { config } from '../src/config'; import isArray from 'core-js/library/fn/array/is-array'; import isInteger from 'core-js/library/fn/number/is-integer'; import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'ix'; -const SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; -const INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; -const BANNER_ENDPOINT_VERSION = 7.2; -const VIDEO_ENDPOINT_VERSION = 8.1; - +const BANNER_SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; +const BANNER_INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; +const SUPPORTED_AD_TYPES = [BANNER]; +const ENDPOINT_VERSION = 7.2; const CENT_TO_DOLLAR_FACTOR = 100; -const BANNER_TIME_TO_LIVE = 35; -const VIDEO_TIME_TO_LIVE = 3600; // 1hr +const TIME_TO_LIVE = 35; const NET_REVENUE = true; const PRICE_TO_DOLLAR_FACTOR = { JPY: 1 }; /** - * Transform valid bid request config object to banner impression object that will be sent to ad server. + * Transform valid bid request config object to impression object that will be sent to ad server. * * @param {object} bid A valid bid request config object. * @return {object} A impression object that will be sent to ad server. */ function bidToBannerImp(bid) { - const imp = bidToImp(bid); + const imp = {}; + + imp.id = bid.bidId; imp.banner = {}; imp.banner.w = bid.params.size[0]; imp.banner.h = bid.params.size[1]; imp.banner.topframe = utils.inIframe() ? 0 : 1; - return imp; -} - -/** - * Transform valid bid request config object to video impression object that will be sent to ad server. - * - * @param {object} bid A valid bid request config object. - * @return {object} A impression object that will be sent to ad server. - */ -function bidToVideoImp(bid) { - const imp = bidToImp(bid); - - imp.video = utils.deepClone(bid.params.video) - imp.video.w = bid.params.size[0]; - imp.video.h = bid.params.size[1]; - - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (context) { - if (context === 'instream') { - imp.video.placement = 1; - } else if (context === 'outstream') { - imp.video.placement = 4; - } else { - utils.logWarn(`ix bidder params: video context '${context}' is not supported`); - } - } - - return imp; -} - -function bidToImp(bid) { - const imp = {}; - - imp.id = bid.bidId; - imp.ext = {}; imp.ext.siteID = bid.params.siteId; @@ -95,7 +58,7 @@ function bidToImp(bid) { * @param {string} currency Global currency in bid response. * @return {object} bid The parsed bid. */ -function parseBid(rawBid, currency, bidRequest) { +function parseBid(rawBid, currency) { const bid = {}; if (PRICE_TO_DOLLAR_FACTOR.hasOwnProperty(currency)) { @@ -105,27 +68,15 @@ function parseBid(rawBid, currency, bidRequest) { } bid.requestId = rawBid.impid; - + bid.width = rawBid.w; + bid.height = rawBid.h; + bid.ad = rawBid.adm; bid.dealId = utils.deepAccess(rawBid, 'ext.dealid'); + bid.ttl = TIME_TO_LIVE; bid.netRevenue = NET_REVENUE; bid.currency = currency; bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-'; - // in the event of a video - if (utils.deepAccess(rawBid, 'ext.vasturl')) { - bid.vastUrl = rawBid.ext.vasturl - bid.width = bidRequest.video.w; - bid.height = bidRequest.video.h; - bid.mediaType = VIDEO; - bid.ttl = VIDEO_TIME_TO_LIVE; - } else { - bid.ad = rawBid.adm; - bid.width = rawBid.w; - bid.height = rawBid.h; - bid.mediaType = BANNER; - bid.ttl = BANNER_TIME_TO_LIVE; - } - bid.meta = {}; bid.meta.networkId = utils.deepAccess(rawBid, 'ext.dspid'); bid.meta.brandId = utils.deepAccess(rawBid, 'ext.advbrandid'); @@ -182,143 +133,6 @@ function isValidBidFloorParams(bidFloor, bidFloorCur) { bidFloorCur.match(curRegex)); } -/** - * Finds the impression with the associated id. - * - * @param {*} id Id of the impression. - * @param {array} impressions List of impressions sent in the request. - * @return {object} The impression with the associated id. - */ -function getBidRequest(id, impressions) { - if (!id) { - return; - } - return find(impressions, imp => imp.id === id); -} - -/** - * Builds a request object to be sent to the ad server based on bid requests. - * - * @param {array} validBidRequests A list of valid bid request config objects. - * @param {object} bidderRequest An object containing other info like gdprConsent. - * @param {array} impressions List of impression objects describing the bids. - * @param {array} version Endpoint version denoting banner or video. - * @return {object} Info describing the request to the server. - * - */ -function buildRequest(validBidRequests, bidderRequest, impressions, version) { - const userEids = []; - - // Always start by assuming the protocol is HTTPS. This way, it will work - // whether the page protocol is HTTP or HTTPS. Then check if the page is - // actually HTTP.If we can guarantee it is, then, and only then, set protocol to - // HTTP. - let baseUrl = SECURE_BID_URL; - - // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded - // and if the data for the partner exist - if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { - let identityInfo = window.headertag.getIdentityInfo(); - if (identityInfo && typeof identityInfo === 'object') { - for (const partnerName in identityInfo) { - if (identityInfo.hasOwnProperty(partnerName)) { - let response = identityInfo[partnerName]; - if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { - userEids.push(response.data); - } - } - } - } - } - const r = {}; - - // Since bidderRequestId are the same for different bid request, just use the first one. - r.id = validBidRequests[0].bidderRequestId; - - r.imp = impressions; - - r.site = {}; - r.ext = {}; - r.ext.source = 'prebid'; - if (userEids.length > 0) { - r.user = {}; - r.user.eids = userEids; - } - - if (document.referrer && document.referrer !== '') { - r.site.ref = document.referrer; - } - - // Apply GDPR information to the request if GDPR is enabled. - if (bidderRequest) { - if (bidderRequest.gdprConsent) { - const gdprConsent = bidderRequest.gdprConsent; - - if (gdprConsent.hasOwnProperty('gdprApplies')) { - r.regs = { - ext: { - gdpr: gdprConsent.gdprApplies ? 1 : 0 - } - }; - } - - if (gdprConsent.hasOwnProperty('consentString')) { - r.user = r.user || {}; - r.user.ext = { - consent: gdprConsent.consentString || '' - }; - } - } - - if (bidderRequest.refererInfo) { - r.site.page = bidderRequest.refererInfo.referer; - - if (bidderRequest.refererInfo.referer && bidderRequest.refererInfo.referer.indexOf('https') !== 0) { - baseUrl = INSECURE_BID_URL; - } - } - } - - const payload = {}; - - // Parse additional runtime configs. - const otherIxConfig = config.getConfig('ix'); - if (otherIxConfig) { - // Append firstPartyData to r.site.page if firstPartyData exists. - if (typeof otherIxConfig.firstPartyData === 'object') { - const firstPartyData = otherIxConfig.firstPartyData; - let firstPartyString = '?'; - for (const key in firstPartyData) { - if (firstPartyData.hasOwnProperty(key)) { - firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; - } - } - firstPartyString = firstPartyString.slice(0, -1); - - r.site.page += firstPartyString; - } - - // Create t in payload if timeout is configured. - if (typeof otherIxConfig.timeout === 'number') { - payload.t = otherIxConfig.timeout; - } - } - - // Use the siteId in the first bid request as the main siteId. - payload.s = validBidRequests[0].params.siteId; - payload.v = version; - payload.r = JSON.stringify(r); - payload.ac = 'j'; - payload.sd = 1; - payload.nf = 1; - - return { - method: 'GET', - url: baseUrl, - data: payload - }; -} - export const spec = { code: BIDDER_CODE, @@ -332,25 +146,22 @@ export const spec = { */ isBidRequestValid: function (bid) { if (!isValidSize(bid.params.size)) { - utils.logError('ix bidder params: bid size has invalid format.'); return false; } if (!includesSize(bid.sizes, bid.params.size)) { - utils.logError('ix bidder params: bid size is not included in ad unit sizes.'); return false; } - if (bid.hasOwnProperty('mediaType') && !(utils.contains(SUPPORTED_AD_TYPES, bid.mediaType))) { + if (bid.hasOwnProperty('mediaType') && bid.mediaType !== 'banner') { return false; } - if (bid.hasOwnProperty('mediaTypes') && !(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || utils.deepAccess(bid, 'mediaTypes.video.playerSize'))) { + if (bid.hasOwnProperty('mediaTypes') && !utils.deepAccess(bid, 'mediaTypes.banner.sizes')) { return false; } if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') { - utils.logError('ix bidder params: siteId must be string or number value.'); return false; } @@ -358,10 +169,8 @@ export const spec = { const hasBidFloorCur = bid.params.hasOwnProperty('bidFloorCur'); if (hasBidFloor || hasBidFloorCur) { - if (!(hasBidFloor && hasBidFloorCur && isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur))) { - utils.logError('ix bidder params: bidFloor / bidFloorCur parameter has invalid format.'); - return false; - } + return hasBidFloor && hasBidFloorCur && + isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur); } return true; @@ -371,49 +180,139 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {array} validBidRequests A list of valid bid request config objects. - * @param {object} bidderRequest A object contains bids and other info like gdprConsent. + * @param {object} options A object contains bids and other info like gdprConsent. * @return {object} Info describing the request to the server. */ - buildRequests: function (validBidRequests, bidderRequest) { - let reqs = []; - let bannerImps = []; - let videoImps = []; + buildRequests: function (validBidRequests, options) { + const bannerImps = []; + const userEids = []; let validBidRequest = null; + let bannerImp = null; + + // Always start by assuming the protocol is HTTPS. This way, it will work + // whether the page protocol is HTTP or HTTPS. Then check if the page is + // actually HTTP.If we can guarantee it is, then, and only then, set protocol to + // HTTP. + let baseUrl = BANNER_SECURE_BID_URL; for (let i = 0; i < validBidRequests.length; i++) { validBidRequest = validBidRequests[i]; - if (validBidRequest.mediaType === VIDEO || utils.deepAccess(validBidRequest, 'mediaTypes.video')) { - if (validBidRequest.mediaType === VIDEO || includesSize(validBidRequest.mediaTypes.video.playerSize, validBidRequest.params.size)) { - videoImps.push(bidToVideoImp(validBidRequest)); - } else { - utils.logError('Bid size is not included in video playerSize') + // Transform the bid request based on the banner format. + bannerImp = bidToBannerImp(validBidRequest); + bannerImps.push(bannerImp); + } + + // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded + // and if the data for the partner exist + if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { + let identityInfo = window.headertag.getIdentityInfo(); + if (identityInfo && typeof identityInfo === 'object') { + for (const partnerName in identityInfo) { + if (identityInfo.hasOwnProperty(partnerName)) { + let response = identityInfo[partnerName]; + if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { + userEids.push(response.data); + } + } } } - if (validBidRequest.mediaType === BANNER || utils.deepAccess(validBidRequest, 'mediaTypes.banner') || - (!validBidRequest.mediaType && !validBidRequest.mediaTypes)) { - bannerImps.push(bidToBannerImp(validBidRequest)); - } } + const r = {}; + + // Since bidderRequestId are the same for different bid request, just use the first one. + r.id = validBidRequests[0].bidderRequestId; + + r.imp = bannerImps; + r.site = {}; + r.ext = {}; + r.ext.source = 'prebid'; + if (userEids.length > 0) { + r.user = {}; + r.user.eids = userEids; + } + + if (document.referrer && document.referrer !== '') { + r.site.ref = document.referrer; + } + + // Apply GDPR information to the request if GDPR is enabled. + if (options) { + if (options.gdprConsent) { + const gdprConsent = options.gdprConsent; + + if (gdprConsent.hasOwnProperty('gdprApplies')) { + r.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + }; + } + + if (gdprConsent.hasOwnProperty('consentString')) { + r.user = r.user || {}; + r.user.ext = { + consent: gdprConsent.consentString || '' + }; + } + } + + if (options.refererInfo) { + r.site.page = options.refererInfo.referer; - if (bannerImps.length > 0) { - reqs.push(buildRequest(validBidRequests, bidderRequest, bannerImps, BANNER_ENDPOINT_VERSION)); + if (options.refererInfo.referer && options.refererInfo.referer.indexOf('https') !== 0) { + baseUrl = BANNER_INSECURE_BID_URL; + } + } } - if (videoImps.length > 0) { - reqs.push(buildRequest(validBidRequests, bidderRequest, videoImps, VIDEO_ENDPOINT_VERSION)); + + const payload = {}; + + // Parse additional runtime configs. + const otherIxConfig = config.getConfig('ix'); + if (otherIxConfig) { + // Append firstPartyData to r.site.page if firstPartyData exists. + if (typeof otherIxConfig.firstPartyData === 'object') { + const firstPartyData = otherIxConfig.firstPartyData; + let firstPartyString = '?'; + for (const key in firstPartyData) { + if (firstPartyData.hasOwnProperty(key)) { + firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; + } + } + firstPartyString = firstPartyString.slice(0, -1); + + r.site.page += firstPartyString; + } + + // Create t in payload if timeout is configured. + if (typeof otherIxConfig.timeout === 'number') { + payload.t = otherIxConfig.timeout; + } } - return reqs; + // Use the siteId in the first bid request as the main siteId. + payload.s = validBidRequests[0].params.siteId; + + payload.v = ENDPOINT_VERSION; + payload.r = JSON.stringify(r); + payload.ac = 'j'; + payload.sd = 1; + + return { + method: 'GET', + url: baseUrl, + data: payload + }; }, /** * Unpack the response from the server into a list of bids. * * @param {object} serverResponse A successful response from the server. - * @param {object} bidderRequest The bid request sent to the server. * @return {array} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse, bidderRequest) { + interpretResponse: function (serverResponse) { const bids = []; let bid = null; @@ -430,11 +329,8 @@ export const spec = { // Transform rawBid in bid response to the format that will be accepted by prebid. const innerBids = seatbid[i].bid; - let requestBid = JSON.parse(bidderRequest.data.r); - for (let j = 0; j < innerBids.length; j++) { - const bidRequest = getBidRequest(innerBids[j].impid, requestBid.imp); - bid = parseBid(innerBids[j], responseBody.cur, bidRequest); + bid = parseBid(innerBids[j], responseBody.cur); bids.push(bid); } } diff --git a/modules/ixBidAdapter.md b/modules/ixBidAdapter.md index 7bd60ac413b..e99c42408f2 100644 --- a/modules/ixBidAdapter.md +++ b/modules/ixBidAdapter.md @@ -42,21 +42,16 @@ var adUnits = [{ ```javascript var adUnits = [{ // ... + mediaTypes: { banner: { sizes: [ [300, 250], [300, 600] ] - }, - video: { - context: 'instream', - playerSize: [ - [300, 250], - [300, 600] - ] } - }, + } + // ... }]; ``` @@ -66,7 +61,7 @@ var adUnits = [{ | Type | Support | --- | --- | Banner | Fully supported for all IX approved sizes. -| Video | Fully supported for all IX approved sizes. +| Video | Not supported. | Native | Not supported. # Bid Parameters @@ -81,17 +76,6 @@ object are detailed here. | siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` | size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.banner.sizes`. Examples: `[300, 250]`, `[300, 600]`, `[728, 90]` -### Video - -| Key | Scope | Type | Description -| --- | --- | --- | --- -| siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` -| size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.video.playerSize`. Examples: `[300, 250]`, `[300, 600]` -| video | Required | Hash | The video object will serve as the properties of the video ad. You can create any field under the video object that is mentioned in the `OpenRTB Spec v2.5`. Some fields like `mimes, protocols, minduration, maxduration` are required. -| video.mimes | Required | String[] | Array list of content MIME types supported. Popular MIME types include, but are not limited to, `"video/x-ms- wmv"` for Windows Media and `"video/x-flv"` for Flash Video. -|video.minduration| Required | Integer | Minimum video ad duration in seconds. -|video.maxduration| Required | Integer | Maximum video ad duration in seconds. -|video.protocol / video.protocols| Required | Integer / Integer[] | Either a single protocol provided as an integer, or protocols provided as a list of integers. `2` - VAST 2.0, `3` - VAST 3.0, `5` - VAST 2.0 Wrapper, `6` - VAST 3.0 Wrapper Setup Guide @@ -100,9 +84,7 @@ Setup Guide Follow these steps to configure and add the IX module to your Prebid.js integration. -The examples in this guide assume the following starting configuration (you may remove banner or video, if either does not apply). - -In regards to video, `context` can either be `'instream'` or `'outstream'`. Note that `outstream` requires additional configuration on the adUnit. +The examples in this guide assume the following starting configuration: ```javascript var adUnits = [{ @@ -116,19 +98,6 @@ var adUnits = [{ } }, bids: [] -}, -{ - code: 'video-div-a', - mediaTypes: { - video: { - context: 'instream', - playerSize: [ - [300, 250], - [300, 600] - ] - } - }, - bids: [] }]; ``` @@ -150,9 +119,7 @@ bid objects under `adUnits[].bids`: Set `params.siteId` and `params.size` in each bid object to the values provided by your IX representative. -**Examples** - -**Banner:** +**Example** ```javascript var adUnits = [{ code: 'banner-div-a', @@ -179,94 +146,18 @@ var adUnits = [{ }] }]; ``` -**Video (Instream):** -```javascript -var adUnits = [{ - code: 'video-div-a', - mediaTypes: { - video: { - context: 'instream', - playerSize: [ - [300, 250], - [300, 600] - ] - } - }, - bids: [{ - bidder: 'ix', - params: { - siteId: '12345', - size: [300, 250], - video: { - skippable: false, - mimes: [ - 'video/mp4', - 'video/webm' - ], - minduration: 0, - maxduration: 60, - protocols: [6] - } - } - }, { - bidder: 'ix', - params: { - siteId: '12345', - size: [300, 600], - video: { - // openrtb v2.5 compatible video obj - } - } - }] -}]; -``` + Please note that you can re-use the existing `siteId` within the same flex position. -**Video (Outstream):** -Note that currently, outstream video rendering must be configured by the publisher. In the adUnit, a `renderer` object must be defined, which includes a `url` pointing to the video rendering script, and a `render` function for creating the video player. See http://prebid.org/dev-docs/show-outstream-video-ads.html for more information. -```javascript -var adUnits = [{ - code: 'video-div-a', - mediaTypes: { - video: { - context: 'outstream', - playerSize: [[300, 250]] - } - }, - renderer: { - url: 'https://test.com/my-video-player.js', - render: function (bid) { - ... - } - }, - bids: [{ - bidder: 'ix', - params: { - siteId: '12345', - size: [300, 250], - video: { - skippable: false, - mimes: [ - 'video/mp4', - 'video/webm' - ], - minduration: 0, - maxduration: 60, - protocols: [6] - } - } - }] -}]; -``` ##### 2. Include `ixBidAdapter` in your build process -When running the build command, include `ixBidAdapter` as a module, as well as `dfpAdServerVideo` if you require video support. +When running the build command, include `ixBidAdapter` as a module. ``` -gulp build --modules=ixBidAdapter,dfpAdServerVideo,fooBidAdapter,bazBidAdapter +gulp build --modules=ixBidAdapter,fooBidAdapter,bazBidAdapter ``` If a JSON file is being used to specify the bidder modules, add `"ixBidAdapter"` @@ -275,7 +166,6 @@ to the top-level array in that file. ```json [ "ixBidAdapter", - "dfpAdServerVideo", "fooBidAdapter", "bazBidAdapter" ] diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 634d5041e6e..38e64e8d338 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -7,8 +7,7 @@ import { spec } from 'modules/ixBidAdapter'; describe('IndexexchangeAdapter', function () { const IX_INSECURE_ENDPOINT = 'http://as.casalemedia.com/cygnus'; const IX_SECURE_ENDPOINT = 'https://as-sec.casalemedia.com/cygnus'; - const VIDEO_ENDPOINT_VERSION = 8.1; - const BANNER_ENDPOINT_VERSION = 7.2; + const BIDDER_VERSION = 7.2; const DEFAULT_BANNER_VALID_BID = [ { @@ -30,37 +29,17 @@ describe('IndexexchangeAdapter', function () { auctionId: '1aa2bb3cc4dd' } ]; - - const DEFAULT_VIDEO_VALID_BID = [ - { - bidder: 'ix', - params: { - siteId: '456', - video: { - skippable: false, - mimes: [ - 'video/mp4', - 'video/webm' - ], - minduration: 0 - }, - size: [400, 100] - }, - sizes: [[400, 100], [200, 400]], - mediaTypes: { - video: { - context: 'instream', - playerSize: [[400, 100], [200, 400]] - } - }, - adUnitCode: 'div-gpt-ad-1460505748562-0', - transactionId: '173f49a8-7549-4218-a23c-e7ba59b47230', - bidId: '1a2b3c4e', - bidderRequestId: '11a22b33c44e', - auctionId: '1aa2bb3cc4de' + const DEFAULT_BANNER_OPTION = { + gdprConsent: { + gdprApplies: true, + consentString: '3huaa11=qu3198ae', + vendorData: {} + }, + refererInfo: { + referer: 'http://www.prebid.org', + canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' } - ]; - + }; const DEFAULT_BANNER_BID_RESPONSE = { cur: 'USD', id: '11a22b33c44d', @@ -90,48 +69,6 @@ describe('IndexexchangeAdapter', function () { } ] }; - - const DEFAULT_VIDEO_BID_RESPONSE = { - cur: 'USD', - id: '1aa2bb3cc4de', - seatbid: [ - { - bid: [ - { - crid: '12346', - adomain: ['www.abcd.com'], - adid: '14851456', - impid: '1a2b3c4e', - cid: '3051267', - price: 110, - id: '2', - ext: { - vasturl: 'www.abcd.com/vast', - errorurl: 'www.abcd.com/error', - dspid: 51, - pricelevel: '_110', - advbrandid: 303326, - advbrand: 'OECTB' - } - } - ], - seat: '3971' - } - ] - }; - - const DEFAULT_OPTION = { - gdprConsent: { - gdprApplies: true, - consentString: '3huaa11=qu3198ae', - vendorData: {} - }, - refererInfo: { - referer: 'http://www.prebid.org', - canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' - } - }; - const DEFAULT_IDENTITY_RESPONSE = { IdentityIp: { responsePending: false, @@ -146,31 +83,6 @@ describe('IndexexchangeAdapter', function () { } }; - const DEFAULT_BIDDER_REQUEST_DATA = { - ac: 'j', - r: JSON.stringify({ - id: '345', - imp: [ - { - id: '1a2b3c4e', - video: { - w: 640, - h: 480, - placement: 1 - } - } - ], - site: { - ref: 'http://ref.com/ref.html', - page: 'http://page.com' - }, - }), - s: '21', - sd: 1, - t: 1000, - v: 8.1 - }; - describe('inherited functions', function () { it('should exists and is a function', function () { const adapter = newBidder(spec); @@ -179,12 +91,11 @@ describe('IndexexchangeAdapter', function () { }); describe('isBidRequestValid', function () { - it('should return true when required params found for a banner or video ad', function () { + it('should return true when required params found for a banner ad', function () { expect(spec.isBidRequestValid(DEFAULT_BANNER_VALID_BID[0])).to.equal(true); - expect(spec.isBidRequestValid(DEFAULT_VIDEO_VALID_BID[0])).to.equal(true); }); - it('should return true when optional bidFloor params found for an ad', function () { + it('should return true when optional params found for a banner ad', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; @@ -225,10 +136,10 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes is not banner or video', function () { + it('should return false when mediaTypes is not banner', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.mediaTypes = { - native: { + video: { sizes: [[300, 250]] } }; @@ -245,13 +156,19 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes.video does not have sizes', function () { - const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); - bid.mediaTypes = { - video: { - size: [[300, 250]] - } - }; + it('should return false when mediaType is not banner', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.mediaTypes; + bid.mediaType = 'banne'; + bid.sizes = [[300, 250]]; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when mediaType is video', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.mediaTypes; + bid.mediaType = 'video'; + bid.sizes = [[300, 250]]; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -278,14 +195,6 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when mediaType is video', function () { - const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); - delete bid.mediaTypes; - bid.mediaType = 'video'; - bid.sizes = [[400, 100]]; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - it('should return false when there is only bidFloor', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; @@ -323,7 +232,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return testCopy; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; }); afterEach(function() { @@ -434,7 +343,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return undefined; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; const payload = JSON.parse(query.r); @@ -447,7 +356,7 @@ describe('IndexexchangeAdapter', function () { responsePending: true, data: {} } - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; const payload = JSON.parse(query.r); @@ -457,7 +366,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending for all partners', function () { testCopy.IdentityIp.responsePending = true; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; const payload = JSON.parse(query.r); @@ -468,7 +377,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending or not available for all partners', function () { testCopy.IdentityIp.responsePending = false; testCopy.IdentityIp.data = {}; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; const payload = JSON.parse(query.r); @@ -478,8 +387,8 @@ describe('IndexexchangeAdapter', function () { }); }); - describe('buildRequests', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + describe('buildRequestsBanner', function () { + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const requestUrl = request.url; const requestMethod = request.method; const query = request.data; @@ -487,7 +396,7 @@ describe('IndexexchangeAdapter', function () { const bidWithoutMediaType = utils.deepClone(DEFAULT_BANNER_VALID_BID); delete bidWithoutMediaType[0].mediaTypes; bidWithoutMediaType[0].sizes = [[300, 250], [300, 600]]; - const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_OPTION)[0]; + const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_BANNER_OPTION); const queryWithoutMediaType = requestWithoutMediaType.data; it('request should be made to IX endpoint with GET method', function () { @@ -496,12 +405,11 @@ describe('IndexexchangeAdapter', function () { }); it('query object (version, siteID and request) should be correct', function () { - expect(query.v).to.equal(BANNER_ENDPOINT_VERSION); + expect(query.v).to.equal(BIDDER_VERSION); expect(query.s).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId); expect(query.r).to.exist; expect(query.ac).to.equal('j'); expect(query.sd).to.equal(1); - expect(query.nf).to.equal(1); }); it('payload should have correct format and value', function () { @@ -509,7 +417,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -537,7 +445,7 @@ describe('IndexexchangeAdapter', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; - const requestBidFloor = spec.buildRequests([bid])[0]; + const requestBidFloor = spec.buildRequests([bid]); const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.bidfloor).to.equal(bid.params.bidFloor); @@ -549,7 +457,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -576,7 +484,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 50; - const requestBidFloor = spec.buildRequests([bid])[0]; + const requestBidFloor = spec.buildRequests([bid]); const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); @@ -593,7 +501,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as string', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 'abc'; - const requestBidFloor = spec.buildRequests([bid])[0]; + const requestBidFloor = spec.buildRequests([bid]); const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); expect(impression.banner).to.exist; @@ -618,9 +526,9 @@ describe('IndexexchangeAdapter', function () { } }); - const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; - const expectedPageUrl = DEFAULT_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; + const expectedPageUrl = DEFAULT_BANNER_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; expect(pageUrl).to.equal(expectedPageUrl); }); @@ -632,10 +540,10 @@ describe('IndexexchangeAdapter', function () { } }); - const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestFirstPartyDataNumber.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); }); it('should not set first party or timeout if it is not present', function () { @@ -643,18 +551,18 @@ describe('IndexexchangeAdapter', function () { ix: {} }); - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); it('should not set first party or timeout if it is setConfig is not called', function () { - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); @@ -664,7 +572,7 @@ describe('IndexexchangeAdapter', function () { timeout: 500 } }); - const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; + const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); expect(requestWithTimeout.data.t).to.equal(500); }); @@ -675,98 +583,14 @@ describe('IndexexchangeAdapter', function () { timeout: '500' } }); - const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; + const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); expect(requestStringTimeout.data.t).to.be.undefined; }); - - it('request should contain both banner and video requests', function () { - const request = spec.buildRequests([DEFAULT_BANNER_VALID_BID[0], DEFAULT_VIDEO_VALID_BID[0]]); - - const bannerImp = JSON.parse(request[0].data.r).imp[0]; - expect(JSON.parse(request[0].data.v)).to.equal(BANNER_ENDPOINT_VERSION); - expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); - expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); - expect(bannerImp.banner).to.exist; - expect(bannerImp.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); - expect(bannerImp.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); - - const videoImp = JSON.parse(request[1].data.r).imp[0]; - expect(JSON.parse(request[1].data.v)).to.equal(VIDEO_ENDPOINT_VERSION); - expect(videoImp.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); - expect(videoImp.video).to.exist; - expect(videoImp.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); - expect(videoImp.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); - }); }); - describe('buildRequestVideo', function () { - const request = spec.buildRequests(DEFAULT_VIDEO_VALID_BID, DEFAULT_OPTION); - const query = request[0].data; - - it('query object (version, siteID and request) should be correct', function () { - expect(query.v).to.equal(VIDEO_ENDPOINT_VERSION); - expect(query.s).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId); - expect(query.r).to.exist; - expect(query.ac).to.equal('j'); - expect(query.sd).to.equal(1); - }); - - it('impression should have correct format and value', function () { - const impression = JSON.parse(query.r).imp[0]; - const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; - - expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); - expect(impression.video).to.exist; - expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); - expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); - expect(impression.video.placement).to.exist; - expect(impression.video.placement).to.equal(1); - expect(impression.video.minduration).to.exist; - expect(impression.video.minduration).to.equal(0); - expect(impression.video.mimes).to.exist; - expect(impression.video.mimes[0]).to.equal('video/mp4'); - expect(impression.video.mimes[1]).to.equal('video/webm'); - - expect(impression.video.skippable).to.equal(false); - expect(impression.ext).to.exist; - expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); - expect(impression.ext.sid).to.equal(sidValue); - }); - - it('impression should have correct format when mediaType is specified.', function () { - const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); - delete bid.mediaTypes; - bid.mediaType = 'video'; - const requestBidFloor = spec.buildRequests([bid])[0]; - const impression = JSON.parse(requestBidFloor.data.r).imp[0]; - const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; - - expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); - expect(impression.video).to.exist; - expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); - expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); - expect(impression.video.placement).to.not.exist; - expect(impression.ext).to.exist; - expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); - expect(impression.ext.sid).to.equal(sidValue); - }); - - it('should set correct placement if context is outstream', function () { - const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); - bid.mediaTypes.video.context = 'outstream'; - const request = spec.buildRequests([bid])[0]; - const impression = JSON.parse(request.data.r).imp[0]; - - expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); - expect(impression.video).to.exist; - expect(impression.video.placement).to.exist; - expect(impression.video.placement).to.equal(4); - }); - }); - - describe('interpretResponse', function () { - it('should get correct bid response for banner ad', function () { + describe('interpretResponseBanner', function () { + it('should get correct bid response', function () { const expectedParse = [ { requestId: '1a2b3c4d', @@ -774,7 +598,6 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, - mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -787,7 +610,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -801,7 +624,6 @@ describe('IndexexchangeAdapter', function () { creativeId: '-', width: 300, height: 250, - mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -814,7 +636,8 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + const result = spec.interpretResponse({ body: bidResponse }); + expect(result[0]).to.deep.equal(expectedParse[0]); }); it('should set Japanese price correctly', function () { @@ -827,7 +650,6 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, - mediaType: 'banner', ad: '', currency: 'JPY', ttl: 35, @@ -840,7 +662,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + const result = spec.interpretResponse({ body: bidResponse }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -854,7 +676,6 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, - mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -867,38 +688,13 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); - expect(result[0]).to.deep.equal(expectedParse[0]); - }); - - it('should get correct bid response for video ad', function () { - const expectedParse = [ - { - requestId: '1a2b3c4e', - cpm: 1.1, - creativeId: '12346', - mediaType: 'video', - width: 640, - height: 480, - currency: 'USD', - ttl: 3600, - netRevenue: true, - dealId: undefined, - vastUrl: 'www.abcd.com/vast', - meta: { - networkId: 51, - brandId: 303326, - brandName: 'OECTB' - } - } - ]; - const result = spec.interpretResponse({ body: DEFAULT_VIDEO_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + const result = spec.interpretResponse({ body: bidResponse }); expect(result[0]).to.deep.equal(expectedParse[0]); }); it('bidrequest should have consent info if gdprApplies and consentString exist', function () { - const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION); - const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -912,7 +708,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user).to.be.undefined; @@ -926,7 +722,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -935,7 +731,7 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have consent info if options.gdprConsent is undefined', function () { const options = {}; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user).to.be.undefined; @@ -944,10 +740,10 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have page if options is undefined', function () { const options = {}; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should not have page if options.refererInfo is an empty object', function () { @@ -955,10 +751,10 @@ describe('IndexexchangeAdapter', function () { refererInfo: {} }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should sent to secure endpoint if page url is secure', function () { @@ -968,10 +764,10 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); expect(requestWithoutreferInfo.site.page).to.equal(options.refererInfo.referer); - expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); }); }); }); From be7668259b30ab8da17352fca917ceb183e08af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E9=9B=A8=E8=BB=92=20=D0=9F=D0=B5=D1=82=D1=80?= Date: Mon, 1 Jul 2019 23:38:29 +0200 Subject: [PATCH 1315/1594] Update emoteevBidAdapter.js (#3928) * Update emoteevBidAdapter.js Retrieve various data from the adapter configuration, and ensure they are properly formatted: - GDPR vendor consent - Metadata: intended to be used as an ID for external partners - Context: describe the context of the current ad unit Test coverage for emoteevBidAdapter.js: - Statements 94.83% - Branches 98.39% - Functions 100% - Lines 94.34% fixup! Update emoteevBidAdapter.js * remove pubCommonId import from emoteevBidAdapter * Format indentation * More detailed integration page example * Rename attribute to externalId * Simplify names of constants * Minor tweak * Update context value --- .../gpt/hello_world_emoteev.html | 145 +++++++++++------- modules/emoteevBidAdapter.js | 52 ++++++- modules/emoteevBidAdapter.md | 6 +- test/spec/modules/emoteevBidAdapter_spec.js | 139 +++++++++++++++-- 4 files changed, 263 insertions(+), 79 deletions(-) diff --git a/integrationExamples/gpt/hello_world_emoteev.html b/integrationExamples/gpt/hello_world_emoteev.html index 5a33e2d9701..f41ef308332 100644 --- a/integrationExamples/gpt/hello_world_emoteev.html +++ b/integrationExamples/gpt/hello_world_emoteev.html @@ -5,68 +5,99 @@ @@ -75,9 +106,9 @@

    Basic Prebid.js Example

    Div-1
    diff --git a/modules/emoteevBidAdapter.js b/modules/emoteevBidAdapter.js index 4436d39bb70..db84b6ea36d 100644 --- a/modules/emoteevBidAdapter.js +++ b/modules/emoteevBidAdapter.js @@ -22,11 +22,12 @@ import { contains, deepAccess, isArray, - getParameterByName + isInteger, + getParameterByName, + getCookie } from '../src/utils'; import {config} from '../src/config'; import * as url from '../src/url'; -import {getCookie} from './pubCommonId'; export const BIDDER_CODE = 'emoteev'; @@ -60,6 +61,19 @@ export const ON_ADAPTER_CALLED = 'on_adapter_called'; export const ON_BID_WON = 'on_bid_won'; export const ON_BIDDER_TIMEOUT = 'on_bidder_timeout'; +export const IN_CONTENT = 'content'; +export const FOOTER = 'footer'; +export const OVERLAY = 'overlay'; +export const WALLPAPER = 'wallpaper'; + +/** + * Vendor ID assigned to Emoteev from the Global Vendor & CMP List. + * + * See https://vendorlist.consensu.org/vendorinfo.json for more information. + * @type {number} + */ +export const VENDOR_ID = 15; + /** * Pure function. See http://prebid.org/dev-docs/bidder-adaptor.html#valid-build-requests-array for detailed semantic. * @@ -71,6 +85,8 @@ export const isBidRequestValid = (bidRequest) => { bidRequest && bidRequest.params && deepAccess(bidRequest, 'params.adSpaceId') && + validateContext(deepAccess(bidRequest, 'params.context')) && + validateExternalId(deepAccess(bidRequest, 'params.externalId')) && bidRequest.bidder === BIDDER_CODE && validateSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes'))); }; @@ -89,7 +105,7 @@ export const buildRequests = (env, debug, currency, validBidRequests, bidderRequ return { method: 'POST', url: bidderUrl(env), - data: JSON.stringify(requestsPayload(debug, currency, validBidRequests, bidderRequest)) + data: JSON.stringify(requestsPayload(debug, currency, validBidRequests, bidderRequest)) // Keys with undefined values will be filtered out. }; }; @@ -264,7 +280,23 @@ export const userSyncImageUrl = env => url.format({ * @param {Array>} sizes * @returns {boolean} are sizes valid? */ -const validateSizes = sizes => isArray(sizes) && sizes.some(size => isArray(size) && size.length === 2); +export const validateSizes = sizes => isArray(sizes) && sizes.length > 0 && sizes.every(size => isArray(size) && size.length === 2); + +/** + * Pure function. + * + * @param {string} context + * @returns {boolean} is param `context` valid? + */ +export const validateContext = context => contains([IN_CONTENT, FOOTER, OVERLAY, WALLPAPER], context); + +/** + * Pure function. + * + * @param {(number|null|undefined)} externalId + * @returns {boolean} is param `externalId` valid? + */ +export const validateExternalId = externalId => externalId === undefined || externalId === null || (isInteger(externalId) && externalId > 0); /** * Pure function. @@ -282,6 +314,14 @@ export const conformBidRequest = bidRequest => { }; }; +/** + * Pure function. + * + * @param {object} bidderRequest + * @returns {(boolean|undefined)} raw consent data. + */ +export const gdprConsent = (bidderRequest) => (deepAccess(bidderRequest, 'gdprConsent.vendorData.vendorConsents') || {})[VENDOR_ID]; + /** * Pure function. * @@ -306,7 +346,7 @@ export const requestsPayload = (debug, currency, validBidRequests, bidderRequest isWebGLEnabled(document)), userAgent: navigator.userAgent, gdprApplies: deepAccess(bidderRequest, 'gdprConsent.gdprApplies'), - gdprConsent: deepAccess(bidderRequest, 'gdprConsent.consentString'), + gdprConsent: gdprConsent(bidderRequest), }; }; @@ -426,7 +466,7 @@ export const getDeviceInfo = (deviceDimensions, viewDimensions, documentDimensio * Pure function * @param {object} config pbjs config value * @param {string} parameter Environment override from URL query param. - * @returns One of [PRODUCTION, STAGING, DEVELOPMENT]. + * @returns {string} One of [PRODUCTION, STAGING, DEVELOPMENT]. */ export const resolveEnv = (config, parameter) => { const configEnv = deepAccess(config, 'emoteev.env'); diff --git a/modules/emoteevBidAdapter.md b/modules/emoteevBidAdapter.md index 88b0b21a96f..226a8374369 100644 --- a/modules/emoteevBidAdapter.md +++ b/modules/emoteevBidAdapter.md @@ -18,14 +18,16 @@ Module that connects to Emoteev's demand sources code: 'test-div', mediaTypes: { banner: { - sizes: [[300, 250]], + sizes: [[720, 90]], } }, bids: [ { bidder: 'emoteev', params: { - adSpaceId: 5084 + adSpaceId: 5084, + context: 'footer', + externalId: 42, } } ] diff --git a/test/spec/modules/emoteevBidAdapter_spec.js b/test/spec/modules/emoteevBidAdapter_spec.js index a5460ab939d..aa97b58ec38 100644 --- a/test/spec/modules/emoteevBidAdapter_spec.js +++ b/test/spec/modules/emoteevBidAdapter_spec.js @@ -15,20 +15,23 @@ import { DEVELOPMENT, EVENTS_PATH, eventsUrl, + FOOTER, + gdprConsent, getDeviceDimensions, getDeviceInfo, getDocumentDimensions, getUserSyncs, getViewDimensions, + IN_CONTENT, interpretResponse, isBidRequestValid, - isWebGLEnabled, ON_ADAPTER_CALLED, ON_BID_WON, ON_BIDDER_TIMEOUT, onBidWon, onAdapterCalled, onTimeout, + OVERLAY, PRODUCTION, requestsPayload, resolveDebug, @@ -39,10 +42,14 @@ import { USER_SYNC_IMAGE_PATH, userSyncIframeUrl, userSyncImageUrl, + validateSizes, + validateContext, + validateExternalId, + VENDOR_ID, + WALLPAPER, } from 'modules/emoteevBidAdapter'; import * as url from '../../../src/url'; import * as utils from '../../../src/utils'; -import * as pubCommonId from '../../../modules/pubCommonId'; import {config} from '../../../src/config'; const cannedValidBidRequests = [{ @@ -53,7 +60,11 @@ const cannedValidBidRequests = [{ bidder: 'emoteev', bidderRequestId: '1203b39fecc6a5', crumbs: {pubcid: 'f3371d16-4e8b-42b5-a770-7e5be1fdf03d'}, - params: {adSpaceId: 5084}, + params: { + adSpaceId: 5084, + context: IN_CONTENT, + externalId: 42 + }, sizes: [[300, 250], [250, 300], [300, 600]], transactionId: '58dbd732-7a39-45f1-b23e-1c24051a941c', }]; @@ -74,7 +85,7 @@ const cannedBidderRequest = { timeout: 3000, gdprConsent: { gdprApplies: true, - consentString: 'my consentString' + vendorData: {vendorConsents: {[VENDOR_ID]: true}}, } }; const serverResponse = @@ -102,6 +113,8 @@ describe('emoteevBidAdapter', function () { bidId: '23a45b4e3', params: { adSpaceId: 12345, + context: IN_CONTENT, + externalId: 42 }, mediaTypes: { banner: { @@ -120,6 +133,8 @@ describe('emoteevBidAdapter', function () { bidder: '', // invalid bidder params: { adSpaceId: 12345, + context: IN_CONTENT, + externalId: 42 }, mediaTypes: { banner: { @@ -131,6 +146,21 @@ describe('emoteevBidAdapter', function () { bidder: 'emoteev', params: { adSpaceId: '', // invalid adSpaceId + context: IN_CONTENT, + externalId: 42 + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + })).to.equal(false); + expect(isBidRequestValid({ + bidder: 'emoteev', + params: { + adSpaceId: 12345, + context: 'something', // invalid context + externalId: 42 }, mediaTypes: { banner: { @@ -142,6 +172,21 @@ describe('emoteevBidAdapter', function () { bidder: 'emoteev', params: { adSpaceId: 12345, + context: IN_CONTENT, + externalId: 'lol' // invalid externalId + }, + mediaTypes: { + banner: { + sizes: [[750, 200]] + } + }, + })).to.equal(false); + expect(isBidRequestValid({ + bidder: 'emoteev', + params: { + adSpaceId: 12345, + context: IN_CONTENT, + externalId: 42 }, mediaTypes: { banner: { @@ -401,6 +446,39 @@ describe('emoteevBidAdapter', function () { }); }); + describe('gdprConsent', function () { + describe('gdpr applies, consent given', function () { + const bidderRequest = { + ...cannedBidderRequest, + gdprConsent: { + gdprApplies: true, + vendorData: {vendorConsents: {[VENDOR_ID]: true}}, + } + }; + expect(gdprConsent(bidderRequest)).to.deep.equal(true); + }); + describe('gdpr applies, consent withdrawn', function () { + const bidderRequest = { + ...cannedBidderRequest, + gdprConsent: { + gdprApplies: true, + vendorData: {vendorConsents: {[VENDOR_ID]: false}}, + } + }; + expect(gdprConsent(bidderRequest)).to.deep.equal(false); + }); + describe('gdpr applies, consent unknown', function () { + const bidderRequest = { + ...cannedBidderRequest, + gdprConsent: { + gdprApplies: true, + vendorData: {}, + } + }; + expect(gdprConsent(bidderRequest)).to.deep.equal(undefined); + }); + }); + describe('requestsPayload', function () { const currency = 'EUR', @@ -418,7 +496,7 @@ describe('emoteevBidAdapter', function () { 'deviceInfo', 'userAgent', 'gdprApplies', - 'gdprConsent' + 'gdprConsent', ); expect(payload.bidRequests[0]).to.exist.and.have.all.keys( @@ -449,7 +527,6 @@ describe('emoteevBidAdapter', function () { ); expect(payload.userAgent).to.deep.equal(navigator.userAgent); expect(payload.gdprApplies).to.deep.equal(cannedBidderRequest.gdprConsent.gdprApplies); - expect(payload.gdprConsent).to.deep.equal(cannedBidderRequest.gdprConsent.consentString); }); describe('getViewDimensions', function () { @@ -665,7 +742,7 @@ describe('emoteevBidAdapter', function () { let getParameterByNameSpy; beforeEach(function () { triggerPixelSpy = sinon.spy(utils, 'triggerPixel'); - getCookieSpy = sinon.spy(pubCommonId, 'getCookie'); + getCookieSpy = sinon.spy(utils, 'getCookie'); getConfigSpy = sinon.spy(config, 'getConfig'); getParameterByNameSpy = sinon.spy(utils, 'getParameterByName'); }); @@ -692,7 +769,7 @@ describe('emoteevBidAdapter', function () { }; spec.isBidRequestValid(validBidRequest); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(utils.getCookie); sinon.assert.notCalled(config.getConfig); sinon.assert.notCalled(utils.getParameterByName); }); @@ -700,7 +777,7 @@ describe('emoteevBidAdapter', function () { const invalidBidRequest = {}; spec.isBidRequestValid(invalidBidRequest); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(utils.getCookie); sinon.assert.notCalled(config.getConfig); sinon.assert.notCalled(utils.getParameterByName); }); @@ -709,7 +786,7 @@ describe('emoteevBidAdapter', function () { it('has intended side-effects', function () { spec.buildRequests(cannedValidBidRequests, cannedBidderRequest); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(utils.getCookie); sinon.assert.callCount(config.getConfig, 3); sinon.assert.callCount(utils.getParameterByName, 2); }); @@ -718,7 +795,7 @@ describe('emoteevBidAdapter', function () { it('has intended side-effects', function () { spec.interpretResponse(serverResponse); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(utils.getCookie); sinon.assert.notCalled(config.getConfig); sinon.assert.notCalled(utils.getParameterByName); }); @@ -728,7 +805,7 @@ describe('emoteevBidAdapter', function () { const bidObject = serverResponse.body[0]; spec.onBidWon(bidObject); sinon.assert.calledOnce(utils.triggerPixel); - sinon.assert.calledOnce(pubCommonId.getCookie); + sinon.assert.calledOnce(utils.getCookie); sinon.assert.calledOnce(config.getConfig); sinon.assert.calledOnce(utils.getParameterByName); }); @@ -737,7 +814,7 @@ describe('emoteevBidAdapter', function () { it('has intended side-effects', function () { spec.onTimeout(cannedValidBidRequests[0]); sinon.assert.calledOnce(utils.triggerPixel); - sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(utils.getCookie); sinon.assert.calledOnce(config.getConfig); sinon.assert.calledOnce(utils.getParameterByName); }); @@ -746,10 +823,44 @@ describe('emoteevBidAdapter', function () { it('has intended side-effects', function () { spec.getUserSyncs({}); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(pubCommonId.getCookie); + sinon.assert.notCalled(utils.getCookie); sinon.assert.calledOnce(config.getConfig); sinon.assert.calledOnce(utils.getParameterByName); }); }); }); + + describe('validateSizes', function () { + it('only accepts valid array of sizes', function () { + expect(validateSizes([])).to.deep.equal(false); + expect(validateSizes([[]])).to.deep.equal(false); + expect(validateSizes([[450, 450], undefined])).to.deep.equal(false); + expect(validateSizes([[450, 450], 'size'])).to.deep.equal(false); + expect(validateSizes([[1, 1]])).to.deep.equal(true); + expect(validateSizes([[1, 1], [450, 450]])).to.deep.equal(true); + }); + }); + + describe('validateContext', function () { + it('only accepts valid context', function () { + expect(validateContext(IN_CONTENT)).to.deep.equal(true); + expect(validateContext(FOOTER)).to.deep.equal(true); + expect(validateContext(OVERLAY)).to.deep.equal(true); + expect(validateContext(WALLPAPER)).to.deep.equal(true); + expect(validateContext(null)).to.deep.equal(false); + expect(validateContext('anything else')).to.deep.equal(false); + }); + }); + + describe('validateExternalId', function () { + it('only accepts a positive integer or null', function () { + expect(validateExternalId(0)).to.deep.equal(false); + expect(validateExternalId(42)).to.deep.equal(true); + expect(validateExternalId(42.0)).to.deep.equal(true); // edge case: valid externalId + expect(validateExternalId(3.14159)).to.deep.equal(false); + expect(validateExternalId('externalId')).to.deep.equal(false); + expect(validateExternalId(undefined)).to.deep.equal(true); + expect(validateExternalId(null)).to.deep.equal(true); + }); + }); }); From 113cfe9865f154486b659c4e21f4186284adb4fb Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 2 Jul 2019 12:04:40 -0600 Subject: [PATCH 1316/1594] Submodule system using hooks (#3924) * prebid-core only contains src and a few node_modules * add back removed neverBundle to webpack build * add module and submodule hooks * allow vargs for submodules for flexibility * fix jsdoc type syntax * updated id5 userid submodule for submodule bundle size duplication fix * add id5 userid submodule to .submodules * fix opt out logic * spelling fix to comment * update to automatically include 'pubcommon' and 'unifiedid' (uncomment to optional submodule for prebid3.0) * additional update to automatically include 'pubcommon' and 'unifiedid' * additional update to automatically include 'pubcommon' and 'unifiedid' * merged differences from master * adpod changes to support submodules * fix --modules argument with .json to work correctly with submodules * fix to remove included and duplicated submodules --- gulpHelpers.js | 15 +++++++- modules/.submodules.json | 9 +++++ modules/adpod.js | 31 +++++++++++++--- modules/digiTrustIdSystem.js | 4 +-- modules/freeWheelAdserverVideo.js | 23 ++++++------ modules/id5IdSystem.js | 10 +++--- modules/{userId.js => userId/index.js} | 36 ++++++++----------- modules/{ => userId}/pubCommonIdSystem.js | 2 +- modules/{ => userId}/unifiedIdSystem.js | 4 +-- modules/{ => userId}/userId.md | 24 ++----------- src/hook.js | 13 +++++++ .../modules/freeWheelAdserverVideo_spec.js | 5 ++- test/spec/modules/userId_spec.js | 8 ++--- webpack.conf.js | 10 ++++-- 14 files changed, 116 insertions(+), 78 deletions(-) create mode 100644 modules/.submodules.json rename modules/{userId.js => userId/index.js} (94%) rename modules/{ => userId}/pubCommonIdSystem.js (96%) rename modules/{ => userId}/unifiedIdSystem.js (95%) rename modules/{ => userId}/userId.md (72%) diff --git a/gulpHelpers.js b/gulpHelpers.js index f20a2673ade..04428133347 100644 --- a/gulpHelpers.js +++ b/gulpHelpers.js @@ -6,12 +6,14 @@ const MANIFEST = 'package.json'; const through = require('through2'); const _ = require('lodash'); const gutil = require('gulp-util'); +const submodules = require('./modules/.submodules.json'); const MODULE_PATH = './modules'; const BUILD_PATH = './build/dist'; const DEV_PATH = './build/dev'; const ANALYTICS_PATH = '../analytics'; + // get only subdirectories that contain package.json with 'main' property function isModuleDirectory(filePath) { try { @@ -39,7 +41,9 @@ module.exports = { .replace(/\/>/g, '\\/>'); }, getArgModules() { - var modules = (argv.modules || '').split(',').filter(module => !!module); + var modules = (argv.modules || '') + .split(',') + .filter(module => !!module); try { if (modules.length === 1 && path.extname(modules[0]).toLowerCase() === '.json') { @@ -56,6 +60,15 @@ module.exports = { }); } + Object.keys(submodules).forEach(parentModule => { + if ( + !modules.includes(parentModule) && + modules.some(module => submodules[parentModule].includes(module)) + ) { + modules.unshift(parentModule); + } + }); + return modules; }, getModules: _.memoize(function(externalModules) { diff --git a/modules/.submodules.json b/modules/.submodules.json new file mode 100644 index 00000000000..f321e075208 --- /dev/null +++ b/modules/.submodules.json @@ -0,0 +1,9 @@ +{ + "userId": [ + "digiTrustIdSystem", + "id5IdSystem" + ], + "adpod": [ + "freeWheelAdserverVideo" + ] +} diff --git a/modules/adpod.js b/modules/adpod.js index 021d4722f53..46671e9fb0a 100644 --- a/modules/adpod.js +++ b/modules/adpod.js @@ -16,16 +16,17 @@ import * as utils from '../src/utils'; import { addBidToAuction, doCallbacksIfTimedout, AUCTION_IN_PROGRESS, callPrebidCache } from '../src/auction'; import { checkAdUnitSetup } from '../src/prebid'; import { checkVideoBidSetup } from '../src/video'; -import { setupBeforeHookFnOnce } from '../src/hook'; +import { setupBeforeHookFnOnce, module } from '../src/hook'; import { store } from '../src/videoCache'; import { config } from '../src/config'; import { ADPOD } from '../src/mediaTypes'; import Set from 'core-js/library/fn/set'; import find from 'core-js/library/fn/array/find'; + const from = require('core-js/library/fn/array/from'); -export const TARGETING_KEY_PB_CAT_DUR = 'hb_pb_cat_dur'; -export const TARGETING_KEY_CACHE_ID = 'hb_cache_id' +const TARGETING_KEY_PB_CAT_DUR = 'hb_pb_cat_dur'; +const TARGETING_KEY_CACHE_ID = 'hb_cache_id'; let queueTimeDelay = 50; let queueSizeLimit = 5; @@ -385,12 +386,13 @@ config.getConfig('adpod', config => adpodSetConfig(config.adpod)); /** * This function initializes the adpod module's hooks. This is called by the corresponding adserver video module. */ -export function initAdpodHooks() { +function initAdpodHooks() { setupBeforeHookFnOnce(callPrebidCache, callPrebidCacheHook); setupBeforeHookFnOnce(checkAdUnitSetup, checkAdUnitSetupHook); setupBeforeHookFnOnce(checkVideoBidSetup, checkVideoBidSetupHook); } +initAdpodHooks() /** * * @param {Array[Object]} bids list of 'winning' bids that need to be cached @@ -428,3 +430,24 @@ export function sortByPricePerSecond(a, b) { } return 0; } + +const sharedMethods = { + TARGETING_KEY_PB_CAT_DUR: TARGETING_KEY_PB_CAT_DUR, + TARGETING_KEY_CACHE_ID: TARGETING_KEY_CACHE_ID, + 'sortByPricePerSecond': sortByPricePerSecond, + 'callPrebidCacheAfterAuction': callPrebidCacheAfterAuction +} +Object.freeze(sharedMethods); + +module('adpod', function shareAdpodUtilities(...args) { + if (!utils.isPlainObject(args[0])) { + utils.logError('Adpod module needs plain object to share methods with submodule'); + return; + } + function addMethods(object, func) { + for (let name in func) { + object[name] = func[name]; + } + } + addMethods(args[0], sharedMethods); +}); diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index 454e6864846..1db65031848 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -12,7 +12,7 @@ // import { config } from 'src/config'; import * as utils from '../src/utils' import { ajax } from '../src/ajax'; -import { attachIdSystem } from '../modules/userId'; +import { submodule } from '../src/hook'; // import { getGlobal } from 'src/prebidGlobal'; /** @@ -336,4 +336,4 @@ export const digiTrustIdSubmodule = { _testInit: surfaceTestHook }; -attachIdSystem(digiTrustIdSubmodule); +submodule('userId', digiTrustIdSubmodule); diff --git a/modules/freeWheelAdserverVideo.js b/modules/freeWheelAdserverVideo.js index c81f3356d71..a93e5ab9159 100644 --- a/modules/freeWheelAdserverVideo.js +++ b/modules/freeWheelAdserverVideo.js @@ -7,8 +7,7 @@ import { auctionManager } from '../src/auctionManager'; import { groupBy, deepAccess, logError, compareOn } from '../src/utils'; import { config } from '../src/config'; import { ADPOD } from '../src/mediaTypes'; -import { initAdpodHooks, TARGETING_KEY_PB_CAT_DUR, TARGETING_KEY_CACHE_ID, callPrebidCacheAfterAuction, sortByPricePerSecond } from './adpod'; -import { getHook } from '../src/hook'; +import { getHook, submodule } from '../src/hook'; export function notifyTranslationModule(fn) { fn.call(this, 'freewheel'); @@ -37,7 +36,7 @@ export function getTargeting({codes, callback} = {}) { let bids = getBidsForAdpod(bidsReceived, adPodAdUnits); bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids; - bids.sort(sortByPricePerSecond); + bids.sort(adpodUtils.sortByPricePerSecond); let targeting = {}; if (deferCachingEnabled === false) { @@ -50,13 +49,13 @@ export function getTargeting({codes, callback} = {}) { .forEach((bid, index, arr) => { if (bid.video.durationBucket <= adPodDurationSeconds) { adPodTargeting.push({ - [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] + [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR] }); adPodDurationSeconds -= bid.video.durationBucket; } if (index === arr.length - 1 && adPodTargeting.length > 0) { adPodTargeting.push({ - [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] + [adpodUtils.TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_CACHE_ID] }); } }); @@ -79,7 +78,7 @@ export function getTargeting({codes, callback} = {}) { }); }); - callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) { + adpodUtils.callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) { if (error) { callback(error, null); } else { @@ -89,12 +88,12 @@ export function getTargeting({codes, callback} = {}) { groupedBids[adUnitCode].forEach((bid, index, arr) => { adPodTargeting.push({ - [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] + [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR] }); if (index === arr.length - 1 && adPodTargeting.length > 0) { adPodTargeting.push({ - [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] + [adpodUtils.TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_CACHE_ID] }); } }); @@ -126,8 +125,8 @@ 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); + .map((bid) => Object.assign({}, bid, {[adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR]})); + bids = groupBy(bids, adpodUtils.TARGETING_KEY_PB_CAT_DUR); let filteredBids = []; Object.keys(bids).forEach((targetingKey) => { bids[targetingKey].sort(compareOn('responseTimestamp')); @@ -148,7 +147,9 @@ function getBidsForAdpod(bidsReceived, adPodAdUnits) { .filter((bid) => adUnitCodes.indexOf(bid.adUnitCode) != -1 && (bid.video && bid.video.context === ADPOD)) } -initAdpodHooks(); registerVideoSupport('freewheel', { getTargeting: getTargeting }); + +export const adpodUtils = {}; +submodule('adpod', adpodUtils); diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js index 39ab256a81e..7ed1fdf6bf3 100644 --- a/modules/id5IdSystem.js +++ b/modules/id5IdSystem.js @@ -5,9 +5,9 @@ * @requires module:modules/userId */ -import * as utils from '../src/utils.js' -import {ajax} from '../src/ajax.js'; -import {isGDPRApplicable, attachIdSystem} from './userId.js'; +import * as utils from '../src/utils' +import {ajax} from '../src/ajax'; +import {submodule} from '../src/hook'; /** @type {Submodule} */ export const id5IdSubmodule = { @@ -37,7 +37,7 @@ export const id5IdSubmodule = { utils.logError(`User ID - ID5 submodule requires partner to be defined as a number`); return; } - const hasGdpr = isGDPRApplicable(consentData) ? 1 : 0; + const hasGdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0; const gdprConsentString = hasGdpr ? consentData.consentString : ''; const url = `https://id5-sync.com/g/v1/${configParams.partner}.json?gdpr=${hasGdpr}&gdpr_consent=${gdprConsentString}`; @@ -57,4 +57,4 @@ export const id5IdSubmodule = { } }; -attachIdSystem(id5IdSubmodule); +submodule('userId', id5IdSubmodule); diff --git a/modules/userId.js b/modules/userId/index.js similarity index 94% rename from modules/userId.js rename to modules/userId/index.js index c80ea21a0a0..2091a6a763a 100644 --- a/modules/userId.js +++ b/modules/userId/index.js @@ -13,7 +13,7 @@ * @name Submodule#getId * @param {SubmoduleParams} configParams * @param {ConsentData} consentData - * @return {(Object|function} id data or a callback, the callback is called on the auction end event + * @return {(Object|function)} id data or a callback, the callback is called on the auction end event */ /** @@ -21,7 +21,7 @@ * @summary decode a stored value for passing to bid requests * @name Submodule#decode * @param {Object|string} value - * @return {(Object|undefined} + * @return {(Object|undefined)} */ /** @@ -68,14 +68,15 @@ */ import find from 'core-js/library/fn/array/find'; -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 {config} from '../../src/config'; +import events from '../../src/events'; +import * as utils from '../../src/utils'; +import {getGlobal} from '../../src/prebidGlobal'; +import {gdprDataHandler} from '../../src/adapterManager'; +import CONSTANTS from '../../src/constants.json'; +import {module} from '../../src/hook'; import {unifiedIdSubmodule} from './unifiedIdSystem.js'; import {pubCommonIdSubmodule} from './pubCommonIdSystem.js'; -import CONSTANTS from '../src/constants.json'; const MODULE_NAME = 'User ID'; const COOKIE = 'cookie'; @@ -158,22 +159,13 @@ function getStoredValue(storage) { return storedValue; } -/** - * test if consent module is present, and if GDPR applies - * @param {ConsentData} consentData - * @returns {boolean} - */ -export function isGDPRApplicable(consentData) { - return consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies; -} - /** * test if consent module is present, applies, and is valid for local storage or cookies (purpose 1) * @param {ConsentData} consentData * @returns {boolean} */ -export function hasGDPRConsent(consentData) { - if (isGDPRApplicable(consentData)) { +function hasGDPRConsent(consentData) { + if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) { if (!consentData.consentString) { return false; } @@ -331,7 +323,7 @@ function getValidSubmoduleConfigs(configRegistry, submoduleRegistry, activeStora if (!config || utils.isEmptyStr(config.name)) { return carry; } - // alidate storage config contains 'type' and 'name' properties with non-empty string values + // 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 && !utils.isEmptyStr(config.storage.type) && @@ -409,7 +401,7 @@ export function init(config) { return; } // _pubcid_optout is checked for compatiblility with pubCommonId - if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (localStorage.getItem('_pbjs_id_optout') && localStorage.getItem('_pubcid_optout'))) { + if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (localStorage.getItem('_pbjs_id_optout') || localStorage.getItem('_pubcid_optout'))) { utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); return; } @@ -431,3 +423,5 @@ init(config); // add submodules after init has been called attachIdSystem(pubCommonIdSubmodule); attachIdSystem(unifiedIdSubmodule); + +module('userId', attachIdSystem); diff --git a/modules/pubCommonIdSystem.js b/modules/userId/pubCommonIdSystem.js similarity index 96% rename from modules/pubCommonIdSystem.js rename to modules/userId/pubCommonIdSystem.js index 39d1feea0ad..f4d6b41a127 100644 --- a/modules/pubCommonIdSystem.js +++ b/modules/userId/pubCommonIdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import * as utils from '../src/utils.js' +import * as utils from '../../src/utils'; /** @type {Submodule} */ export const pubCommonIdSubmodule = { diff --git a/modules/unifiedIdSystem.js b/modules/userId/unifiedIdSystem.js similarity index 95% rename from modules/unifiedIdSystem.js rename to modules/userId/unifiedIdSystem.js index 6b67b7bf5f1..cf86c049d2a 100644 --- a/modules/unifiedIdSystem.js +++ b/modules/userId/unifiedIdSystem.js @@ -5,8 +5,8 @@ * @requires module:modules/userId */ -import * as utils from '../src/utils.js' -import {ajax} from '../src/ajax.js'; +import * as utils from '../../src/utils' +import {ajax} from '../../src/ajax'; /** @type {Submodule} */ export const unifiedIdSubmodule = { diff --git a/modules/userId.md b/modules/userId/userId.md similarity index 72% rename from modules/userId.md rename to modules/userId/userId.md index b36b9b1007c..782e7782554 100644 --- a/modules/userId.md +++ b/modules/userId/userId.md @@ -3,12 +3,12 @@ Example showing `cookie` storage for user id data for both submodules ``` pbjs.setConfig({ - usersync: { + userSync: { userIds: [{ name: "unifiedId", params: { partner: "prebid", - url: "http://match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" + url: "//match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" }, storage: { type: "cookie", @@ -28,26 +28,6 @@ pbjs.setConfig({ }); ``` -Example showing `cookie` storage for user id data for id5 submodule -``` -pbjs.setConfig({ - usersync: { - userIds: [{ - name: "id5Id", - params: { - partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one contact@id5.io - }, - storage: { - type: "cookie", - name: "id5id", - expires: 90 - } - }], - syncDelay: 5000 - } -}); -``` - Example showing `localStorage` for user id data for both submodules ``` pbjs.setConfig({ diff --git a/src/hook.js b/src/hook.js index ddf0d134357..220e1c39111 100644 --- a/src/hook.js +++ b/src/hook.js @@ -13,3 +13,16 @@ export function setupBeforeHookFnOnce(baseFn, hookFn, priority = 15) { baseFn.before(hookFn, priority); } } + +export function module(name, install) { + hook('async', function (submodules) { + submodules.forEach(args => install(...args)); + }, name)([]); // will be queued until hook.ready() called in pbjs.processQueue(); +} + +export function submodule(name, ...args) { + getHook(name).before((next, modules) => { + modules.push(args); + next(modules); + }); +} diff --git a/test/spec/modules/freeWheelAdserverVideo_spec.js b/test/spec/modules/freeWheelAdserverVideo_spec.js index 5846774c8b1..ffc690e5a92 100644 --- a/test/spec/modules/freeWheelAdserverVideo_spec.js +++ b/test/spec/modules/freeWheelAdserverVideo_spec.js @@ -1,8 +1,7 @@ import { expect } from 'chai'; -import { getTargeting } from 'modules/freeWheelAdserverVideo'; +import { getTargeting, adpodUtils } from 'modules/freeWheelAdserverVideo'; import { auctionManager } from 'src/auctionManager'; import { config } from 'src/config'; -import * as adpod from 'modules/adpod'; describe('freeWheel adserver module', function() { let amStub; @@ -53,7 +52,7 @@ describe('freeWheel adserver module', function() { amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits'); amGetAdUnitsStub.returns(adUnits); amStub = sinon.stub(auctionManager, 'getBidsReceived'); - pbcStub = sinon.stub(adpod, 'callPrebidCacheAfterAuction').callsFake(function (...args) { + pbcStub = sinon.stub(adpodUtils, 'callPrebidCacheAfterAuction').callsFake(function (...args) { args[1](null, getBidsReceived()); }); }); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 60df468a903..a158d2e9fed 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -4,11 +4,11 @@ import { setSubmoduleRegistry, syncDelay, attachIdSystem -} from 'modules/userId'; +} from 'modules/userId/index.js'; import {config} from 'src/config'; import * as utils from 'src/utils'; -import {unifiedIdSubmodule} from 'modules/unifiedIdSystem'; -import {pubCommonIdSubmodule} from 'modules/pubCommonIdSystem'; +import {unifiedIdSubmodule} from 'modules/userId/unifiedIdSystem'; +import {pubCommonIdSubmodule} from 'modules/userId/pubCommonIdSystem'; import {id5IdSubmodule} from 'modules/id5IdSystem'; let assert = require('chai').assert; let expect = require('chai').expect; @@ -327,7 +327,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from unifiedid html5', function(done) { + it('test hook from pubcommonid html5', function(done) { // simulate existing browser local storage values localStorage.setItem('unifiedid_alt', JSON.stringify({'TDID': 'testunifiedid_alt'})); localStorage.setItem('unifiedid_alt_exp', ''); diff --git a/webpack.conf.js b/webpack.conf.js index 61cdf82df32..8e1787de329 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -25,8 +25,14 @@ plugins.push( // this plugin must be last so it can be easily removed for karma new webpack.optimize.CommonsChunkPlugin({ name: 'prebid', filename: 'prebid-core.js', - minChunks: function(module, count) { - return !(count < 2 || neverBundle.indexOf(path.basename(module.resource)) !== -1) + minChunks: function(module) { + return ( + ( + module.context && module.context === path.resolve('./src') && + !(module.resource && neverBundle.some(name => module.resource.includes(name))) + ) || + module.resource && module.resource.includes(path.resolve('./node_modules/core-js')) + ); } }) ); From 1087329579096f7b3d45564aeeb01b40b45ea7a1 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Tue, 2 Jul 2019 21:19:23 +0300 Subject: [PATCH 1317/1594] Gamoshi: Add adasta new bidder alias (#3949) * Add support for multi-format ad units. Add favoredMediaType property to params. * Add tests for gdpr consent. * Add adId to outbids * Modify media type resolving * Refactor multi-format ad units handler. * Add adasta - new bidder alias for gamoshi * Unify rtb endpoints * Modify adasta alias code --- modules/gamoshiBidAdapter.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 67475f8d8d9..3fb045cd7c2 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -5,10 +5,7 @@ import {Renderer} from '../src/Renderer'; import {BANNER, VIDEO} from '../src/mediaTypes'; const ENDPOINTS = { - 'viewdeos': 'https://rtb.viewdeos.com', - 'cleanmedia': 'https://bidder.cleanmediaads.com', - 'gamoshi': 'https://rtb.gamoshi.io', - 'gambid': 'https://rtb.gamoshi.io', + 'gamoshi': 'https://rtb.gamoshi.io' }; const DEFAULT_TTL = 360; @@ -45,7 +42,7 @@ export const helper = { export const spec = { code: 'gamoshi', - aliases: ['gambid', 'cleanmedia', 'viewdeos'], + aliases: ['gambid', 'cleanmedia', 'viewdeos', 'adastaMedia'], supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { @@ -61,7 +58,7 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { const {adUnitCode, auctionId, mediaTypes, params, sizes, transactionId} = bidRequest; - const baseEndpoint = params['rtbEndpoint'] || ENDPOINTS[bidRequest.bidder] || ENDPOINTS['gamoshi']; + const baseEndpoint = params['rtbEndpoint'] || ENDPOINTS['gamoshi']; const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + (params.query ? '&' + params.query : ''); let url = config.getConfig('pageUrl') || bidderRequest.refererInfo.referer; From d418f61e7d1790238b3c1f9152492ccbd9292073 Mon Sep 17 00:00:00 2001 From: Carlos Barreiro Mata Date: Tue, 2 Jul 2019 20:22:44 +0200 Subject: [PATCH 1318/1594] Added bid adapter for seedtag (#3915) * Added bid adapter for seedtag * Revert changes to package-lock * added safe check --- modules/seedtagBidAdapter.js | 205 ++++++++++ modules/seedtagBidAdapter.md | 79 ++++ test/spec/modules/seedtagBidAdapter_spec.js | 396 ++++++++++++++++++++ 3 files changed, 680 insertions(+) create mode 100644 modules/seedtagBidAdapter.js create mode 100644 modules/seedtagBidAdapter.md create mode 100644 test/spec/modules/seedtagBidAdapter_spec.js diff --git a/modules/seedtagBidAdapter.js b/modules/seedtagBidAdapter.js new file mode 100644 index 00000000000..845d8ffec9d --- /dev/null +++ b/modules/seedtagBidAdapter.js @@ -0,0 +1,205 @@ +import * as utils from '../src/utils' +import { registerBidder } from '../src/adapters/bidderFactory' +import { VIDEO, BANNER } from '../src/mediaTypes' + +const BIDDER_CODE = 'seedtag'; +const SEEDTAG_ALIAS = 'st'; +const SEEDTAG_SSP_ENDPOINT = 'https://s.seedtag.com/c/hb/bid'; +const SEEDTAG_SSP_ONTIMEOUT_ENDPOINT = 'https://s.seedtag.com/se/hb/timeout'; + +const mediaTypesMap = { + [BANNER]: 'display', + [VIDEO]: 'video' +}; + +function mapMediaType(seedtagMediaType) { + if (seedtagMediaType === 'display') return BANNER; + if (seedtagMediaType === 'video') return VIDEO; + else return seedtagMediaType; +} + +function getMediaTypeFromBid(bid) { + return bid.mediaTypes && Object.keys(bid.mediaTypes)[0] +} + +function hasMandatoryParams(params) { + return ( + !!params.publisherId && + !!params.adUnitId && + !!params.placement && + (params.placement === 'inImage' || + params.placement === 'inScreen' || + params.placement === 'banner' || + params.placement === 'video') + ); +} + +function hasVideoMandatoryParams(mediaTypes) { + const isVideoInStream = + !!mediaTypes.video && mediaTypes.video.context === 'instream'; + const isPlayerSize = + !!utils.deepAccess(mediaTypes, 'video.playerSize') && + utils.isArray(utils.deepAccess(mediaTypes, 'video.playerSize')); + return isVideoInStream && isPlayerSize; +} + +function buildBidRequests(validBidRequests) { + return utils._map(validBidRequests, function(validBidRequest) { + const params = validBidRequest.params; + const mediaTypes = utils._map( + Object.keys(validBidRequest.mediaTypes), + function(pbjsType) { + return mediaTypesMap[pbjsType]; + } + ); + const bidRequest = { + id: validBidRequest.bidId, + transactionId: validBidRequest.transactionId, + sizes: validBidRequest.sizes, + supplyTypes: mediaTypes, + adUnitId: params.adUnitId, + placement: params.placement + }; + + if (params.adPosition) { + bidRequest.adPosition = params.adPosition; + } + + if (params.video) { + bidRequest.videoParams = params.video || {}; + bidRequest.videoParams.w = + validBidRequest.mediaTypes.video.playerSize[0][0]; + bidRequest.videoParams.h = + validBidRequest.mediaTypes.video.playerSize[0][1]; + } + + return bidRequest; + }) +} + +function buildBid(seedtagBid) { + const mediaType = mapMediaType(seedtagBid.mediaType); + const bid = { + requestId: seedtagBid.bidId, + cpm: seedtagBid.price, + width: seedtagBid.width, + height: seedtagBid.height, + creativeId: seedtagBid.creativeId, + currency: seedtagBid.currency, + netRevenue: true, + mediaType: mediaType, + ttl: seedtagBid.ttl + }; + if (mediaType === VIDEO) { + bid.vastXml = seedtagBid.content; + } else { + bid.ad = seedtagBid.content; + } + return bid; +} + +export function getTimeoutUrl (data) { + let queryParams = ''; + if ( + utils.isArray(data) && data[0] && + utils.isArray(data[0].params) && data[0].params[0] + ) { + const params = data[0].params[0]; + queryParams = + '?publisherToken=' + params.publisherId + + '&adUnitId=' + params.adUnitId; + } + return SEEDTAG_SSP_ONTIMEOUT_ENDPOINT + queryParams; +} + +export const spec = { + code: BIDDER_CODE, + aliases: [SEEDTAG_ALIAS], + 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(bid) { + return getMediaTypeFromBid(bid) === VIDEO + ? hasMandatoryParams(bid.params) && hasVideoMandatoryParams(bid.mediaTypes) + : hasMandatoryParams(bid.params); + }, + + /** + * 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) { + const payload = { + url: bidderRequest.refererInfo.referer, + publisherToken: validBidRequests[0].params.publisherId, + cmp: !!bidderRequest.gdprConsent, + timeout: bidderRequest.timeout, + version: '$prebid.version$', + bidRequests: buildBidRequests(validBidRequests) + }; + + if (payload.cmp) { + const gdprApplies = bidderRequest.gdprConsent.gdprApplies; + if (gdprApplies !== undefined) payload['ga'] = gdprApplies; + payload['cd'] = bidderRequest.gdprConsent.consentString; + } + + const payloadString = JSON.stringify(payload) + return { + method: 'POST', + url: SEEDTAG_SSP_ENDPOINT, + 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) { + const serverBody = serverResponse.body; + if (serverBody && serverBody.bids && utils.isArray(serverBody.bids)) { + return utils._map(serverBody.bids, function(bid) { + return buildBid(bid); + }); + } else { + return []; + } + }, + + /** + * 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(syncOptions, serverResponses) { + const serverResponse = serverResponses[0]; + if (syncOptions.iframeEnabled && serverResponse) { + const cookieSyncUrl = serverResponse.body.cookieSync; + return cookieSyncUrl ? [{ type: 'iframe', url: cookieSyncUrl }] : []; + } else { + return []; + } + }, + + /** + * Register bidder specific code, which will execute if bidder timed out after an auction + * @param {data} Containing timeout specific data + */ + onTimeout(data) { + getTimeoutUrl(data); + utils.triggerPixel(SEEDTAG_SSP_ONTIMEOUT_ENDPOINT); + } +} +registerBidder(spec); diff --git a/modules/seedtagBidAdapter.md b/modules/seedtagBidAdapter.md new file mode 100644 index 00000000000..627ff8333ad --- /dev/null +++ b/modules/seedtagBidAdapter.md @@ -0,0 +1,79 @@ +# Overview + +``` +Module Name: Seedtag Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@seedtag.com +``` + +# Description + +Module that connects to Seedtag demand sources to fetch bids. + +# Test Parameters + +## Sample Banner Ad Unit + +```js +const adUnits = [ + { + code: '/21804003197/prebid_test_300x250', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: 'seedtag', + params: { + publisherId: '0000-0000-01', // required + adUnitId: '0000', // required + placement: 'banner', // required + adPosition: 0 // optional + } + } + ] + } +] +``` + +## Sample inStream Video Ad Unit + +```js +var adUnits = [{ + code: 'video', + mediaTypes: { + video: { + context: 'instream', // required + playerSize: [600, 300] // required + } + }, + bids: [ + { + bidder: 'seedtag', + params: { + publisherId: '0000-0000-01', // required + adUnitId: '0000', // required + placement: 'video', // required + adPosition: 0, // optional + // Video object as specified in OpenRTB 2.5 + video: { + mimes: ['video/mp4'], // recommended + minduration: 5, // optional + maxduration: 60, // optional + boxingallowed: 1, // optional + skip: 1, // optional + startdelay: 1, // optional + linearity: 1, // optional + battr: [1, 2], // optional + maxbitrate: 10, // optional + playbackmethod: [1], // optional + delivery: [1], // optional + placement: 1, // optional + } + } + } + ] +}]; +``` diff --git a/test/spec/modules/seedtagBidAdapter_spec.js b/test/spec/modules/seedtagBidAdapter_spec.js new file mode 100644 index 00000000000..4bd4b599c55 --- /dev/null +++ b/test/spec/modules/seedtagBidAdapter_spec.js @@ -0,0 +1,396 @@ +import { expect } from 'chai' +import { spec, getTimeoutUrl } from 'modules/seedtagBidAdapter' + +function getSlotConfigs(mediaTypes, params) { + return { + params: params, + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + bidRequestsCount: 1, + bidder: 'seedtag', + mediaTypes: mediaTypes, + src: 'client', + transactionId: 'd704d006-0d6e-4a09-ad6c-179e7e758096' + } +} + +describe('Seedtag Adapter', function() { + describe('isBidRequestValid method', function() { + const PUBLISHER_ID = '0000-0000-01' + const ADUNIT_ID = '000000' + describe('returns true', function() { + describe('when banner slot config has all mandatory params', () => { + describe('and placement has the correct value', function() { + const createBannerSlotConfig = placement => { + return getSlotConfigs( + { banner: {} }, + { + publisherId: PUBLISHER_ID, + adUnitId: ADUNIT_ID, + placement + } + ) + } + const placements = ['banner', 'video', 'inImage', 'inScreen'] + 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() { + it('should return true, when video mediatype object are correct.', function() { + const slotConfig = getSlotConfigs( + { + video: { + context: 'instream', + playerSize: [[600, 200]] + } + }, + { + publisherId: PUBLISHER_ID, + adUnitId: ADUNIT_ID, + placement: 'video' + } + ) + 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) + } + it('does not have the PublisherToken.', function() { + const isBidRequestValid = spec.isBidRequestValid( + createSlotconfig({ + adUnitId: '000000', + placement: 'banner' + }) + ) + expect(isBidRequestValid).to.equal(false) + }) + it('does not have the AdUnitId.', function() { + const isBidRequestValid = spec.isBidRequestValid( + createSlotconfig({ + publisherId: '0000-0000-01', + placement: 'banner' + }) + ) + expect(isBidRequestValid).to.equal(false) + }) + it('does not have the placement.', function() { + const isBidRequestValid = spec.isBidRequestValid( + createSlotconfig({ + publisherId: '0000-0000-01', + adUnitId: '000000' + }) + ) + expect(isBidRequestValid).to.equal(false) + }) + it('does not have a the correct placement.', function() { + const isBidRequestValid = spec.isBidRequestValid( + createSlotconfig({ + publisherId: '0000-0000-01', + adUnitId: '000000', + placement: 'another_thing' + }) + ) + 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' + }) + } + it('is a void object', function() { + const isBidRequestValid = spec.isBidRequestValid( + createVideoSlotconfig({ video: {} }) + ) + expect(isBidRequestValid).to.equal(false) + }) + it('does not have playerSize.', function() { + const isBidRequestValid = spec.isBidRequestValid( + createVideoSlotconfig({ video: { context: 'instream' } }) + ) + expect(isBidRequestValid).to.equal(false) + }) + it('is not instream ', function() { + const isBidRequestValid = spec.isBidRequestValid( + createVideoSlotconfig({ + video: { + context: 'outstream', + playerSize: [[600, 200]] + } + }) + ) + expect(isBidRequestValid).to.equal(false) + }) + }) + }) + }) + + describe('buildRequests method', function() { + const bidderRequest = { + refererInfo: { referer: 'referer' }, + timeout: 1000 + } + const mandatoryParams = { + publisherId: '0000-0000-01', + adUnitId: '000000', + placement: 'banner' + } + const inStreamParams = Object.assign({}, mandatoryParams, { + video: { + 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('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') + }) + + 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() { + 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) + }) + }) + + 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() { + 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') + }) + }) + }) + + 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) + }) + 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) + }) + }) + }) + + 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 not got 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: [ + { + bidId: '2159a54dc2566f', + price: 0.5, + currency: 'USD', + content: 'content', + width: 728, + height: 90, + mediaType: 'display', + ttl: 360 + } + ], + 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') + }) + }) + describe('the bid is a video', function() { + it('should return a instream bid', function() { + const request = { data: JSON.stringify({}) } + const serverResponse = { + body: { + bids: [ + { + bidId: '2159a54dc2566f', + price: 0.5, + currency: 'USD', + content: 'content', + width: 728, + height: 90, + mediaType: 'video', + ttl: 360 + } + ], + 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') + }) + }) + }) + }) + + 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 () { + it('should return the correct endpoint', function () { + 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 + ) + }) + }) +}) From f6059313fde741701752846eeb7696fbf9d7c33c Mon Sep 17 00:00:00 2001 From: Aparna Rao-Hegde Date: Tue, 2 Jul 2019 14:24:00 -0400 Subject: [PATCH 1319/1594] 33Across: Update GDPR handling (#3944) * check gdpr in buildRequest * User sync based on whether gdpr applies or not * check if consent data exists during user sync * split user sync into further branches: 1) when gdpr does not apply 2) when consent data is unavailable * contribute viewability to ttxRequest * update tests * remove window mock from tests * use local variables * introduce ServerRequestBuilder * add withOptions() method to ServerRequestBuilder * add semicolons * sync up package-lock.json with upstream/master * stub window.top in tests * introduce getTopWindowSize() for test purpose * reformat code * add withSite() method to TtxRequestBuilder add withSite() method to TtxRequestBuilder * add isIframe() and _isViewabilityMeasurable() * handle NON_MEASURABLE viewability in nested iframes * consider page visibility, stub utils functions getWindowTop() and getWindowSelf() * contribute viewability as 0 for inactive tab * add prebidjs version to ttx request * send caller as an array * fix JSDoc in utils.js * send viewability as non measurable when unable to locate target HTMLElement, add warning message * introduce mapAdSlotPathToElementId() * introduce getAdSlotHTMLElement(), add logging * introduce mapAdSlotPathToElementId() * update logging in ad unit path to element id mapping * rephrase logging, fix tests * update adapter documentation * remove excessive logging * improve logging * revert change * fix return of _mapAdUnitPathToElementId() * improve logging of _mapAdUnitPathToElementId() * do not use Array.find() * return id once element is found * return id once element is found * let -> const * Removing killswitch behavior for GDPR * Updated comments to reflect current gdpr logic * URI encode consent string * Updated example site ID to help Prebid team e2e test our adapter --- modules/33acrossBidAdapter.js | 30 ++-- modules/33acrossBidAdapter.md | 2 +- test/spec/modules/33acrossBidAdapter_spec.js | 147 ++++++++++++++----- 3 files changed, 125 insertions(+), 54 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 801a5d564a3..f53bf8b9d17 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -64,7 +64,7 @@ function _getAdSlotHTMLElement(adUnitCode) { // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request // NOTE: At this point, TTX only accepts request for a single impression -function _createServerRequest(bidRequest, gdprConsent) { +function _createServerRequest(bidRequest, gdprConsent = {}) { const ttxRequest = {}; const params = bidRequest.params; const element = _getAdSlotHTMLElement(bidRequest.adUnitCode); @@ -143,14 +143,22 @@ function _createServerRequest(bidRequest, gdprConsent) { } // Sync object will always be of type iframe for TTX -function _createSync(siteId) { +function _createSync({siteId, gdprConsent = {}}) { const ttxSettings = config.getConfig('ttxSettings'); const syncUrl = (ttxSettings && ttxSettings.syncUrl) || SYNC_ENDPOINT; - return { + const {consentString, gdprApplies} = gdprConsent; + + const sync = { type: 'iframe', - url: `${syncUrl}&id=${siteId}` + url: `${syncUrl}&id=${siteId}&gdpr_consent=${encodeURIComponent(consentString)}` + }; + + if (typeof gdprApplies === 'boolean') { + sync.url += `&gdpr=${Number(gdprApplies)}`; } + + return sync; } function _getSize(size) { @@ -282,8 +290,6 @@ function isBidRequestValid(bid) { // NOTE: With regards to gdrp consent data, // - the server independently infers gdpr applicability therefore, setting the default value to false -// - the server, at this point, also doesn't need the consent string to handle gdpr compliance. So passing -// value whether set or not, for the sake of future dev. function buildRequests(bidRequests, bidderRequest) { const gdprConsent = Object.assign({ consentString: undefined, @@ -307,14 +313,12 @@ function interpretResponse(serverResponse, bidRequest) { return bidResponses; } -// Register one sync per unique guid -// NOTE: If gdpr applies do not sync +// Register one sync per unique guid so long as iframe is enable +// Else no syncs +// For logic on how we handle gdpr data see _createSyncs and module's unit tests +// '33acrossBidAdapter#getUserSyncs' function getUserSyncs(syncOptions, responses, gdprConsent) { - if (gdprConsent && gdprConsent.gdprApplies === true) { - return [] - } else { - return (syncOptions.iframeEnabled) ? adapterState.uniqueSiteIds.map(_createSync) : ([]); - } + return (syncOptions.iframeEnabled) ? adapterState.uniqueSiteIds.map((siteId) => _createSync({gdprConsent, siteId})) : ([]); } export const spec = { diff --git a/modules/33acrossBidAdapter.md b/modules/33acrossBidAdapter.md index 58e3b2b273a..c313f3b6e0b 100644 --- a/modules/33acrossBidAdapter.md +++ b/modules/33acrossBidAdapter.md @@ -24,7 +24,7 @@ var adUnits = [ bids: [{ bidder: '33across', params: { - siteId: 'examplePub1234', + siteId: 'cxBE0qjUir6iopaKkGJozW', productId: 'siab' } }] diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 7e1a8619c63..08ea0a863ee 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -618,73 +618,140 @@ describe('33acrossBidAdapter:', function () { ]; }); - context('when gdpr does not apply', function() { - let gdprConsent; + context('when iframe is not enabled', function() { + it('returns empty sync array', function() { + const syncOptions = {}; + + spec.buildRequests(bidRequests); + + expect(spec.getUserSyncs(syncOptions)).to.deep.equal([]); + }); + }); + context('when iframe is enabled', function() { + let syncOptions; beforeEach(function() { - gdprConsent = { - gdprApplies: false + syncOptions = { + iframeEnabled: true }; }); - context('when iframe is not enabled', function() { - it('returns empty sync array', function() { - const syncOptions = {}; + context('when there is no gdpr consent data', function() { + it('returns sync urls with undefined consent string as param', function() { + spec.buildRequests(bidRequests); + + const syncResults = spec.getUserSyncs(syncOptions, {}, undefined); + const expectedSyncs = [ + { + type: 'iframe', + url: `${syncs[0].url}&gdpr_consent=undefined` + }, + { + type: 'iframe', + url: `${syncs[1].url}&gdpr_consent=undefined` + } + ] + + expect(syncResults).to.deep.equal(expectedSyncs); + }) + }); + context('when gdpr applies but there is no consent string', function() { + it('returns sync urls with undefined consent string as param and gdpr=1', function() { spec.buildRequests(bidRequests); - expect(spec.getUserSyncs(syncOptions, {}, gdprConsent)).to.deep.equal([]); + const syncResults = spec.getUserSyncs(syncOptions, {}, {gdprApplies: true}); + const expectedSyncs = [ + { + type: 'iframe', + url: `${syncs[0].url}&gdpr_consent=undefined&gdpr=1` + }, + { + type: 'iframe', + url: `${syncs[1].url}&gdpr_consent=undefined&gdpr=1` + } + ]; + + expect(syncResults).to.deep.equal(expectedSyncs); }); }); - context('when iframe is enabled', function() { - it('returns sync array equal to number of unique siteIDs', function() { - const syncOptions = { - iframeEnabled: true - }; - + context('when gdpr applies and there is consent string', function() { + it('returns sync urls with gdpr_consent=consent string as param and gdpr=1', function() { spec.buildRequests(bidRequests); - expect(spec.getUserSyncs(syncOptions, {}, gdprConsent)).to.deep.equal(syncs); + const syncResults = spec.getUserSyncs(syncOptions, {}, {gdprApplies: true, consentString: 'consent123A'}); + const expectedSyncs = [ + { + type: 'iframe', + url: `${syncs[0].url}&gdpr_consent=consent123A&gdpr=1` + }, + { + type: 'iframe', + url: `${syncs[1].url}&gdpr_consent=consent123A&gdpr=1` + } + ]; + + expect(syncResults).to.deep.equal(expectedSyncs); }); }); - }); - - context('when consent data is not defined', function() { - context('when iframe is not enabled', function() { - it('returns empty sync array', function() { - const syncOptions = {}; + context('when gdpr does not apply and there is no consent string', function() { + it('returns sync urls with undefined consent string as param and gdpr=0', function() { spec.buildRequests(bidRequests); - expect(spec.getUserSyncs(syncOptions)).to.deep.equal([]); + const syncResults = spec.getUserSyncs(syncOptions, {}, {gdprApplies: false}); + const expectedSyncs = [ + { + type: 'iframe', + url: `${syncs[0].url}&gdpr_consent=undefined&gdpr=0` + }, + { + type: 'iframe', + url: `${syncs[1].url}&gdpr_consent=undefined&gdpr=0` + } + ]; + expect(syncResults).to.deep.equal(expectedSyncs); }); }); - context('when iframe is enabled', function() { - it('returns sync array equal to number of unique siteIDs', function() { - const syncOptions = { - iframeEnabled: true - }; - + context('when gdpr is unknown and there is consent string', function() { + it('returns sync urls with only consent string as param', function() { spec.buildRequests(bidRequests); - expect(spec.getUserSyncs(syncOptions)).to.deep.equal(syncs); + const syncResults = spec.getUserSyncs(syncOptions, {}, {consentString: 'consent123A'}); + const expectedSyncs = [ + { + type: 'iframe', + url: `${syncs[0].url}&gdpr_consent=consent123A` + }, + { + type: 'iframe', + url: `${syncs[1].url}&gdpr_consent=consent123A` + } + ]; + expect(syncResults).to.deep.equal(expectedSyncs); }); }); - }); - context('when gdpr applies', function() { - it('returns empty sync array', function() { - const syncOptions = {}; - const gdprConsent = { - gdprApplies: true - }; - - spec.buildRequests(bidRequests); + context('when gdpr does not apply and there is consent string (yikes!)', function() { + it('returns sync urls with consent string as param and gdpr=0', function() { + spec.buildRequests(bidRequests); - expect(spec.getUserSyncs(syncOptions, {}, gdprConsent)).to.deep.equal([]); + const syncResults = spec.getUserSyncs(syncOptions, {}, {gdprApplies: false, consentString: 'consent123A'}); + const expectedSyncs = [ + { + type: 'iframe', + url: `${syncs[0].url}&gdpr_consent=consent123A&gdpr=0` + }, + { + type: 'iframe', + url: `${syncs[1].url}&gdpr_consent=consent123A&gdpr=0` + } + ]; + expect(syncResults).to.deep.equal(expectedSyncs); + }); }); - }) + }); }); }); From 0a96baf1ed8a00b88aaf2c3ca89cca925e45a855 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 2 Jul 2019 15:40:11 -0400 Subject: [PATCH 1320/1594] Prebid 2.22.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae1d5ba514a..75618208b5c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.22.0-pre", + "version": "2.22.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b02a00c67b76a741424c785d10b0ce106da45ce4 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 2 Jul 2019 15:54:22 -0400 Subject: [PATCH 1321/1594] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75618208b5c..5e2806fe5f4 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.22.0", + "version": "2.23.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 2e0ea780d1ef8e8b9142234c83c2700c4511cfc5 Mon Sep 17 00:00:00 2001 From: Scott Date: Tue, 9 Jul 2019 15:24:42 +0200 Subject: [PATCH 1322/1594] adding back the ID5 documentation in `userId.md` that had been accidentally removed (#3975) --- modules/userId/userId.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 782e7782554..cd7aaf92d39 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -1,10 +1,17 @@ ## User ID Example Configuration -Example showing `cookie` storage for user id data for both submodules +Example showing `cookie` storage for user id data for each of the submodules ``` pbjs.setConfig({ userSync: { userIds: [{ + name: "pubCommonId", + storage: { + type: "cookie", + name: "_pubcid", + expires: 60 + } + }, { name: "unifiedId", params: { partner: "prebid", @@ -16,11 +23,14 @@ pbjs.setConfig({ expires: 60 } }, { - name: "pubCommonId", + name: "id5Id", + params: { + partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one at http://id5.io/prebid + }, storage: { type: "cookie", - name: "_pubcid", - expires: 60 + name: "id5id", + expires: 5 } }], syncDelay: 5000 @@ -28,7 +38,7 @@ pbjs.setConfig({ }); ``` -Example showing `localStorage` for user id data for both submodules +Example showing `localStorage` for user id data for some submodules ``` pbjs.setConfig({ usersync: { @@ -65,6 +75,10 @@ pbjs.setConfig({ value: { "providedPubCommonId": "1234567890" } + }, + { + name: "id5Id", + value: { "id5id": "ID5-abcdef" } }], syncDelay: 5000 } From 3e6460ddb7db1d2c4254121645e25b3094e86cbc Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Tue, 9 Jul 2019 22:36:02 +0530 Subject: [PATCH 1323/1594] Support of outstream renderer in oneVideo Adaptor (#3959) * outstream changes * removing global filtet * reverting page * message * adapter change * remove space * testcases * testpage * spaces for test page * renderer exist case * reverting package-lock.json --- modules/oneVideoBidAdapter.js | 22 ++++++++++++++++++-- test/pages/video.html | 2 +- test/spec/modules/oneVideoBidAdapter_spec.js | 16 +++++++++++--- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 818c31a84af..c05158f28c4 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -76,19 +76,22 @@ export const spec = { requestId: bidRequest.bidId, bidderCode: spec.code, cpm: bid.price, - creativeId: bid.id, + adId: bid.adid, + creativeId: bid.crid, width: size.width, height: size.height, mediaType: 'video', currency: response.cur, ttl: 100, - netRevenue: true + netRevenue: true, + adUnitCode: bidRequest.adUnitCode }; if (bid.nurl) { bidResponse.vastUrl = bid.nurl; } else if (bid.adm) { bidResponse.vastXml = bid.adm; } + bidResponse.renderer = (bidRequest.mediaTypes.video.context === 'outstream') ? newRenderer(bidRequest, bidResponse) : undefined; return bidResponse; }, /** @@ -216,5 +219,20 @@ function getRequestData(bid, consentData) { function isSecure() { return document.location.protocol === 'https:'; } +/** + * Create oneVideo renderer + * @returns {*} + */ +function newRenderer(bidRequest, bid) { + if (!bidRequest.renderer) { + bidRequest.renderer = {}; + bidRequest.renderer.url = 'https://cdn.vidible.tv/prod/hb-outstream-renderer/renderer.js'; + bidRequest.renderer.render = function(bid) { + setTimeout(function () { + o2PlayerRender(bid); + }, 700) + }; + } +} registerBidder(spec); diff --git a/test/pages/video.html b/test/pages/video.html index e040b65fe23..09e75379e69 100644 --- a/test/pages/video.html +++ b/test/pages/video.html @@ -133,4 +133,4 @@

    Prebid Video -- video.js

    - + \ No newline at end of file diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 331a52c1ea0..09118bba1d2 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -10,9 +10,16 @@ describe('OneVideoBidAdapter', function () { beforeEach(function () { bidRequest = { + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, bidder: 'oneVideo', sizes: [640, 480], bidId: '30b3efwfwe1e', + adUnitCode: 'video1', params: { video: { playerWidth: 640, @@ -140,20 +147,23 @@ describe('OneVideoBidAdapter', function () { }); it('should return a valid bid response with just "adm"', function () { - const serverResponse = {seatbid: [{bid: [{id: 1, price: 6.01, adm: ''}]}], cur: 'USD'}; + const serverResponse = {seatbid: [{bid: [{id: 1, adid: 123, crid: 2, price: 6.01, adm: ''}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { requestId: bidRequest.bidId, bidderCode: spec.code, cpm: serverResponse.seatbid[0].bid[0].price, - creativeId: serverResponse.seatbid[0].bid[0].id, + adId: serverResponse.seatbid[0].bid[0].adid, + creativeId: serverResponse.seatbid[0].bid[0].crid, vastXml: serverResponse.seatbid[0].bid[0].adm, width: 640, height: 480, mediaType: 'video', currency: 'USD', ttl: 100, - netRevenue: true + netRevenue: true, + adUnitCode: bidRequest.adUnitCode, + renderer: (bidRequest.mediaTypes.video.context === 'outstream') ? newRenderer(bidRequest, bidResponse) : undefined, }; expect(bidResponse).to.deep.equal(o); }); From 3709e47ff47a0d0a53d5c12971d4e10d71925906 Mon Sep 17 00:00:00 2001 From: John Salis Date: Tue, 9 Jul 2019 13:06:31 -0400 Subject: [PATCH 1324/1594] Beachfront Adapter: Add secure protocol to endpoints (#3979) --- modules/beachfrontBidAdapter.js | 10 +++++----- test/spec/modules/beachfrontBidAdapter_spec.js | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index efc7dfeda8d..9e3da9dc7a1 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -7,12 +7,12 @@ import { VIDEO, BANNER } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.5'; +const ADAPTER_VERSION = '1.6'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; -export const VIDEO_ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; -export const BANNER_ENDPOINT = '//display.bfmio.com/prebid_display'; +export const VIDEO_ENDPOINT = 'https://reachms.bfmio.com/bid.json?exchange_id='; +export const BANNER_ENDPOINT = 'https://display.bfmio.com/prebid_display'; export const OUTSTREAM_SRC = '//player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration']; @@ -123,12 +123,12 @@ export const spec = { } else if (syncOptions.iframeEnabled) { syncs.push({ type: 'iframe', - url: `//sync.bfmio.com/sync_iframe?ifg=1&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` + url: `https://sync.bfmio.com/sync_iframe?ifg=1&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` }); } else if (syncOptions.pixelEnabled) { syncs.push({ type: 'image', - url: `//sync.bfmio.com/syncb?pid=144&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` + url: `https://sync.bfmio.com/syncb?pid=144&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` }); } diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index f5890cb6475..c01a5a3a47c 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -719,7 +719,7 @@ describe('BeachfrontAdapter', function () { }); it('should return user syncs defined the bid response', function () { - const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; + const syncUrl = 'https://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; const syncOptions = { iframeEnabled: true, pixelEnabled: true @@ -737,7 +737,7 @@ describe('BeachfrontAdapter', function () { }); it('should not return user syncs if iframes are disabled', function () { - const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; + const syncUrl = 'https://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; const syncOptions = { iframeEnabled: false, pixelEnabled: true From 242d19fe38debf36af7a3a44f10ee13f3ab70566 Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Tue, 9 Jul 2019 20:06:59 +0300 Subject: [PATCH 1325/1594] TheMediaGrid Bid Adapter: use referrer from refererInfo (#3968) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Add video support in Grid Bid Adapter * Added test parameter for video slot * update Grid Bid Adapter to set size in response bid * Update Grid Bid Adapter to support identical uids in parameters * Fix typo in test file for Grid Bid Adapter * Update The Grid Media Bidder Adapter to send refererInfo.referer as 'u' parameter in ad request --- modules/gridBidAdapter.js | 4 +++- test/spec/modules/gridBidAdapter_spec.js | 13 ++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index f02ec58fd68..ee1ae85e7ee 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -79,13 +79,15 @@ export const spec = { }); const payload = { - u: utils.getTopWindowUrl(), auids: auids.join(','), sizes: utils.getKeys(sizeMap).join(','), r: reqId }; if (bidderRequest) { + if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + } if (bidderRequest.timeout) { payload.wtimeout = bidderRequest.timeout; } diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index 53560a9ac6f..d9bfb9e971a 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -47,6 +47,8 @@ describe('TheMediaGrid Adapter', function () { }); return res; } + const bidderRequest = {refererInfo: {referer: 'http://example.com'}}; + const encodedReferer = encodeURIComponent(bidderRequest.refererInfo.referer); let bidRequests = [ { 'bidder': 'grid', @@ -84,29 +86,30 @@ describe('TheMediaGrid Adapter', function () { ]; it('should attach valid params to the tag', function () { - const request = spec.buildRequests([bidRequests[0]]); + const request = spec.buildRequests([bidRequests[0]], bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferer); expect(payload).to.have.property('auids', '1'); expect(payload).to.have.property('sizes', '300x250,300x600'); expect(payload).to.have.property('r', '22edbae2733bf6'); }); it('auids must not be duplicated', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferer); expect(payload).to.have.property('auids', '1,1,2'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); }); it('if gdprConsent is present payload must have gdpr params', function () { - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}, refererInfo: bidderRequest.refererInfo}); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); + expect(payload).to.have.property('u', encodedReferer); expect(payload).to.have.property('gdpr_consent', 'AAA'); expect(payload).to.have.property('gdpr_applies', '1'); }); From e28792ef250b4906937762a578d4c664c70a230f Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Tue, 9 Jul 2019 22:46:54 +0530 Subject: [PATCH 1326/1594] PulsePoint adapter - Video support + userId module support (#3937) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * initial commit * Adding ortb params * Outstream fixes * Minor fixes * Test fixes * Minor refactor * Minor changes * Removing yarn lock file * battr fix and added test * PulsePoint adapter - user id module support (#10) * Making user sync pixels https as well. * fixing review comment --- modules/pulsepointBidAdapter.js | 146 ++++++++- modules/pulsepointBidAdapter.md | 54 +++- .../spec/modules/pulsepointBidAdapter_spec.js | 277 +++++++++++++++++- 3 files changed, 445 insertions(+), 32 deletions(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 206eb734495..9c0d67d9612 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -1,6 +1,7 @@ /* eslint dot-notation:0, quote-props:0 */ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; +import { Renderer } from '../src/Renderer'; const NATIVE_DEFAULTS = { TITLE_LEN: 100, @@ -13,13 +14,14 @@ const NATIVE_DEFAULTS = { const DEFAULT_BID_TTL = 20; const DEFAULT_CURRENCY = 'USD'; const DEFAULT_NET_REVENUE = true; +const KNOWN_PARAMS = ['cp', 'ct', 'cf', 'video', 'battr', 'bcat', 'badv', 'bidfloor']; /** * PulsePoint Bid Adapter. * Contact: ExchangeTeam@pulsepoint.com * * Aliases - pulseLite and pulsepointLite are supported for backwards compatibility. - * Formats - Display/Native/Outstream formats supported. + * Formats - Display/Native/Video formats supported. * */ export const spec = { @@ -28,7 +30,7 @@ export const spec = { aliases: ['pulseLite', 'pulsepointLite'], - supportedMediaTypes: ['banner', 'native'], + supportedMediaTypes: ['banner', 'native', 'video'], isBidRequestValid: bid => ( !!(bid && bid.params && bid.params.cp && bid.params.ct) @@ -41,12 +43,16 @@ export const spec = { site: site(bidRequests), app: app(bidRequests), device: device(), + bcat: bidRequests[0].params.bcat, + badv: bidRequests[0].params.badv, + user: user(bidRequests[0], bidderRequest), + regs: regs(bidderRequest), }; - applyGdpr(bidderRequest, request); return { method: 'POST', - url: '//bid.contextweb.com/header/ortb', - data: JSON.stringify(request), + url: 'https://bid.contextweb.com/header/ortb?src=prebid', + data: request, + bidderRequest }; }, @@ -58,12 +64,12 @@ export const spec = { if (syncOptions.iframeEnabled) { return [{ type: 'iframe', - url: '//bh.contextweb.com/visitormatch' + url: 'https://bh.contextweb.com/visitormatch' }]; } else if (syncOptions.pixelEnabled) { return [{ type: 'image', - url: '//bh.contextweb.com/visitormatch/prebid' + url: 'https://bh.contextweb.com/visitormatch/prebid' }]; } }, @@ -79,12 +85,13 @@ export const spec = { /** * Callback for bids, after the call to PulsePoint completes. */ -function bidResponseAvailable(bidRequest, bidResponse) { +function bidResponseAvailable(request, response) { const idToImpMap = {}; const idToBidMap = {}; - bidResponse = bidResponse.body + const idToSlotConfig = {}; + const bidResponse = response.body // extract the request bids and the response bids, keyed by impr-id - const ortbRequest = parse(bidRequest.data); + const ortbRequest = request.data; ortbRequest.imp.forEach(imp => { idToImpMap[imp.id] = imp; }); @@ -93,6 +100,11 @@ function bidResponseAvailable(bidRequest, bidResponse) { idToBidMap[bid.impid] = bid; })); } + if (request.bidderRequest) { + request.bidderRequest.bids.forEach(bid => { + idToSlotConfig[bid.bidId] = bid; + }); + } const bids = []; Object.keys(idToImpMap).forEach(id => { if (idToBidMap[id]) { @@ -109,6 +121,15 @@ function bidResponseAvailable(bidRequest, bidResponse) { if (idToImpMap[id]['native']) { bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); bid.mediaType = 'native'; + } else if (idToImpMap[id].video) { + // for outstream, a renderer is specified + 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'; + bid.width = idToBidMap[id].w; + bid.height = idToBidMap[id].h; } else { bid.ad = idToBidMap[id].adm; bid.width = idToImpMap[id].banner.w; @@ -138,6 +159,9 @@ function impression(slot) { banner: banner(slot), 'native': nativeImpression(slot), tagid: slot.params.ct.toString(), + video: video(slot), + bidfloor: slot.params.bidfloor, + ext: ext(slot), }; } @@ -146,12 +170,66 @@ function impression(slot) { */ function banner(slot) { const size = adSize(slot); - return slot.nativeParams ? null : { + return (slot.nativeParams || slot.params.video) ? null : { w: size[0], h: size[1], + battr: slot.params.battr, }; } +/** + * Produces an OpenRTB Video object for the slot given + */ +function video(slot) { + if (slot.params.video) { + return Object.assign({}, slot.params.video, {battr: slot.params.battr}); + } + return null; +} + +/** + * Unknown params are captured and sent on ext + */ +function ext(slot) { + const ext = {}; + const knownParamsMap = {}; + KNOWN_PARAMS.forEach(value => knownParamsMap[value] = 1); + Object.keys(slot.params).forEach(key => { + if (!knownParamsMap[key]) { + ext[key] = slot.params[key]; + } + }); + return Object.keys(ext).length > 0 ? { prebid: ext } : null; +} + +/** + * Sets up the renderer on the bid, for outstream bid responses. + */ +function outstreamRenderer(rendererOptions, outstreamExtOptions) { + const renderer = Renderer.install({ + url: outstreamExtOptions.rendererUrl, + config: { + defaultOptions: outstreamExtOptions.config, + rendererOptions, + type: outstreamExtOptions.type + }, + loaded: false, + }); + renderer.setRender((bid) => { + bid.renderer.push(() => { + const config = bid.renderer.getConfig(); + new window.PulsePointOutstreamRenderer().render({ + adUnitCode: bid.adUnitCode, + vastXml: bid.vastXml, + type: config.type, + defaultOptions: config.defaultOptions, + rendererOptions + }); + }); + }); + return renderer; +} + /** * Produces an OpenRTB Native object for the slot given. */ @@ -166,6 +244,7 @@ function nativeImpression(slot) { return { request: JSON.stringify({ assets }), ver: '1.1', + battr: slot.params.battr, }; } return null; @@ -312,13 +391,50 @@ function adSize(slot) { } /** - * Applies GDPR parameters to request. + * Handles the user level attributes and produces + * an openrtb User object. */ -function applyGdpr(bidderRequest, ortbRequest) { +function user(bidRequest, bidderRequest) { + var ext = {}; + if (bidderRequest) { + if (bidderRequest.gdprConsent) { + ext.consent = bidderRequest.gdprConsent.consentString; + } + } + if (bidRequest) { + if (bidRequest.userId) { + ext.eids = []; + addExternalUserId(ext.eids, bidRequest.userId.pubcid, 'pubcommon'); + addExternalUserId(ext.eids, bidRequest.userId.tdid, 'ttdid'); + addExternalUserId(ext.eids, utils.deepAccess(bidRequest.userId.digitrustid, 'data.id'), 'digitrust'); + addExternalUserId(ext.eids, bidRequest.userId.id5id, 'id5id'); + } + } + return { ext }; +} + +/** + * Produces external userid object in ortb 3.0 model. + */ +function addExternalUserId(eids, value, source) { + if (value) { + eids.push({ + source, + uids: [{ + id: value + }] + }); + } +} + +/** + * Produces the regulations ortb object + */ +function regs(bidderRequest) { if (bidderRequest && bidderRequest.gdprConsent) { - ortbRequest.regs = { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0 } }; - ortbRequest.user = { ext: { consent: bidderRequest.gdprConsent.consentString } }; + return { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0 } }; } + return null; } /** diff --git a/modules/pulsepointBidAdapter.md b/modules/pulsepointBidAdapter.md index 1b119f0499f..36d4ef6cce5 100644 --- a/modules/pulsepointBidAdapter.md +++ b/modules/pulsepointBidAdapter.md @@ -7,7 +7,7 @@ # Description Connects to PulsePoint demand source to fetch bids. -Banner, Outstream and Native formats are supported. +Banner, Video and Native formats are supported. Please use ```pulsepoint``` as the bidder code. ```pulseLite``` and ```pulsepointLite``` aliases also supported as well. @@ -40,5 +40,57 @@ Please use ```pulsepoint``` as the bidder code. ct: 505642 } }] + },{ + code: 'outstream-div', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream' + } + }, + bids: [{ + bidder: 'pulsepoint', + params: { + cp: 512379, + ct: 505642, + video: { + h: 300, + w: 400, + minduration: 1, + maxduration: 210, + linearity: 1, + mimes: ["video/mp4", "video/ogg", "video/webm"], + pos: 3 + } + } + }], + renderer: { + options: { + text: "PulsePoint Outstream" + } + } + },{ + code: 'instream', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'pulsepoint', + params: { + cp: 512379, + ct: 694973, + video: { + battr: [1,3], + h: 300, + w: 400, + minduration: 1, + maxduration: 210, + protocols: [2,3,5] + } + } + }] }]; ``` diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index f40a270af11..1d22ca6eadc 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -1,8 +1,7 @@ /* eslint dot-notation:0, quote-props:0 */ import {expect} from 'chai'; import {spec} from 'modules/pulsepointBidAdapter'; -import {getTopWindowLocation} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; +import {deepClone, getTopWindowLocation} from 'src/utils'; describe('PulsePoint Adapter Tests', function () { const slotConfigs = [{ @@ -48,12 +47,103 @@ describe('PulsePoint Adapter Tests', function () { } } }]; + const videoSlotConfig = [{ + placementCode: '/DfpAccount1/slotVideo', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + video: { + w: 400, + h: 300, + minduration: 5, + maxduration: 10, + startdelay: 0, + skip: 1, + minbitrate: 200, + protocols: [1, 2, 4] + } + } + }]; + const additionalParamsConfig = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '1x1', + extra_key1: 'extra_val1', + extra_key2: 12345, + extra_key3: { + key1: 'val1', + key2: 23456, + }, + extra_key4: [1, 2, 3] + } + }]; + + const ortbParamsSlotConfig = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '1x1', + bcat: ['IAB-1', 'IAB-20'], + battr: [1, 2, 3], + bidfloor: 1.5, + badv: ['cocacola.com', 'lays.com'] + } + }, { + placementCode: '/DfpAccount1/slotVideo', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + video: { + w: 400, + h: 300, + minduration: 5, + maxduration: 10, + }, + battr: [2, 3, 4], + bidfloor: 2.5, + } + }]; + + const outstreamSlotConfig = [{ + placementCode: '/DfpAccount1/slot1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream' + } + }, + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '1x1', + video: { + h: 300, + w: 400, + minduration: 1, + maxduration: 210, + linearity: 1, + } + }, + renderer: { + options: { + text: 'PulsePoint Outstream' + } + } + }]; it('Verify build request', function () { const request = spec.buildRequests(slotConfigs); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; // site object expect(ortbRequest.site).to.not.equal(null); expect(ortbRequest.site.publisher).to.not.equal(null); @@ -78,7 +168,7 @@ describe('PulsePoint Adapter Tests', function () { it('Verify parse response', function () { const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; const ortbResponse = { seatbid: [{ bid: [{ @@ -107,7 +197,7 @@ describe('PulsePoint Adapter Tests', function () { it('Verify use ttl in ext', function () { const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; const ortbResponse = { seatbid: [{ bid: [{ @@ -139,9 +229,9 @@ describe('PulsePoint Adapter Tests', function () { it('Verify Native request', function () { const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; // native impression expect(ortbRequest.imp[0].tagid).to.equal('t10000'); expect(ortbRequest.imp[0].banner).to.equal(null); @@ -177,9 +267,9 @@ describe('PulsePoint Adapter Tests', function () { it('Verify Native response', function () { const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; const nativeResponse = { 'native': { assets: [ @@ -229,8 +319,10 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verifies supported media types', function () { - expect(spec.supportedMediaTypes).to.have.lengthOf(2); + expect(spec.supportedMediaTypes).to.have.lengthOf(3); + expect(spec.supportedMediaTypes[0]).to.equal('banner'); expect(spec.supportedMediaTypes[1]).to.equal('native'); + expect(spec.supportedMediaTypes[2]).to.equal('video'); }); it('Verifies if bid request valid', function () { @@ -251,7 +343,7 @@ describe('PulsePoint Adapter Tests', function () { expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); expect(options[0].type).to.equal('iframe'); - expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch'); + expect(options[0].url).to.equal('https://bh.contextweb.com/visitormatch'); }); it('Verifies image pixel sync', function () { @@ -259,12 +351,12 @@ describe('PulsePoint Adapter Tests', function () { expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); expect(options[0].type).to.equal('image'); - expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch/prebid'); + expect(options[0].url).to.equal('https://bh.contextweb.com/visitormatch/prebid'); }); it('Verify app requests', function () { const request = spec.buildRequests(appSlotConfig); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; // site object expect(ortbRequest.site).to.equal(null); expect(ortbRequest.app).to.not.be.null; @@ -283,9 +375,9 @@ describe('PulsePoint Adapter Tests', function () { } }; const request = spec.buildRequests(slotConfigs, bidderRequest); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; // user object expect(ortbRequest.user).to.not.equal(null); expect(ortbRequest.user.ext).to.not.equal(null); @@ -295,4 +387,157 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.regs.ext).to.not.equal(null); expect(ortbRequest.regs.ext.gdpr).to.equal(1); }); + + it('Verify Video request', function () { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].video).to.not.be.null; + expect(ortbRequest.imp[0].native).to.be.null; + expect(ortbRequest.imp[0].banner).to.be.null; + expect(ortbRequest.imp[0].video.w).to.equal(400); + expect(ortbRequest.imp[0].video.h).to.equal(300); + expect(ortbRequest.imp[0].video.minduration).to.equal(5); + expect(ortbRequest.imp[0].video.maxduration).to.equal(10); + expect(ortbRequest.imp[0].video.startdelay).to.equal(0); + expect(ortbRequest.imp[0].video.skip).to.equal(1); + expect(ortbRequest.imp[0].video.minbitrate).to.equal(200); + expect(ortbRequest.imp[0].video.protocols).to.eql([1, 2, 4]); + }); + + it('Verify Video response', function () { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'http://pulsepoint.video.mp4' + }] + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid['native']).to.be.undefined; + expect(bid.mediaType).to.equal('video'); + expect(bid.vastXml).to.equal(ortbResponse.seatbid[0].bid[0].adm); + }); + + it('Verify extra parameters', function () { + let request = spec.buildRequests(additionalParamsConfig); + let ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].ext).to.not.equal(null); + expect(ortbRequest.imp[0].ext.prebid).to.not.equal(null); + expect(ortbRequest.imp[0].ext.prebid).to.not.be.null; + expect(ortbRequest.imp[0].ext.prebid.extra_key1).to.equal('extra_val1'); + expect(ortbRequest.imp[0].ext.prebid.extra_key2).to.equal(12345); + expect(ortbRequest.imp[0].ext.prebid.extra_key3).to.not.be.null; + expect(ortbRequest.imp[0].ext.prebid.extra_key3.key1).to.equal('val1'); + expect(ortbRequest.imp[0].ext.prebid.extra_key3.key2).to.equal(23456); + expect(ortbRequest.imp[0].ext.prebid.extra_key4).to.eql([1, 2, 3]); + expect(Object.keys(ortbRequest.imp[0].ext.prebid)).to.eql(['extra_key1', 'extra_key2', 'extra_key3', 'extra_key4']); + // attempting with a configuration with no unknown params. + request = spec.buildRequests(outstreamSlotConfig); + ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].ext).to.equal(null); + }); + + it('Verify ortb parameters', function () { + const request = spec.buildRequests(ortbParamsSlotConfig); + const ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.bcat).to.eql(['IAB-1', 'IAB-20']); + expect(ortbRequest.badv).to.eql(['cocacola.com', 'lays.com']); + expect(ortbRequest.imp).to.have.lengthOf(2); + expect(ortbRequest.imp[0].bidfloor).to.equal(1.5); + expect(ortbRequest.imp[0].banner.battr).to.eql([1, 2, 3]); + expect(ortbRequest.imp[0].ext).to.be.null; + // slot 2 + expect(ortbRequest.imp[1].bidfloor).to.equal(2.5); + expect(ortbRequest.imp[1].video.battr).to.eql([2, 3, 4]); + expect(ortbRequest.imp[1].ext).to.be.null; + }); + + it('Verify outstream renderer', function () { + const request = spec.buildRequests(outstreamSlotConfig, {bids: [outstreamSlotConfig[0]]}); + const ortbRequest = request.data; + expect(ortbRequest).to.not.be.null; + expect(ortbRequest.imp[0]).to.not.be.null; + expect(ortbRequest.imp[0].video).to.not.be.null; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'http://pulsepoint.video.mp4', + ext: { + outstream: { + type: 'Inline', + config: { + text: 'ADVERTISEMENT', + skipaftersec: 5 + }, + rendererUrl: 'http://tag.contextweb.com/hb-outstr-renderer.js' + } + } + }] + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.renderer).to.not.be.null; + expect(bid.renderer.url).to.equal('http://tag.contextweb.com/hb-outstr-renderer.js'); + expect(bid.renderer.getConfig()).to.not.be.null; + expect(bid.renderer.getConfig().defaultOptions).to.eql(ortbResponse.seatbid[0].bid[0].ext.outstream.config); + expect(bid.renderer.getConfig().rendererOptions).to.eql(outstreamSlotConfig[0].renderer.options); + expect(bid.renderer.getConfig().type).to.equal('Inline'); + }); + it('Verify common id parameters', function () { + const bidRequests = deepClone(slotConfigs); + 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); + 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(3); + 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('ttdid'); + 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[2].source).to.equal('digitrust'); + expect(ortbRequest.user.ext.eids[2].uids).to.have.lengthOf(1); + expect(ortbRequest.user.ext.eids[2].uids[0].id).to.equal('userid_digitrust'); + }); }); From 748f651b6770e3b03af80658869f6b4bc0ca91a9 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 9 Jul 2019 13:17:46 -0400 Subject: [PATCH 1327/1594] Criteo real time user sync (#3930) * add criteo rtus submodule and user id changes * update appnexus adapter to include criteo user id * updated to submodules pattern --- modules/.submodules.json | 3 +- modules/appnexusBidAdapter.js | 10 ++ modules/criteortusIdSystem.js | 105 +++++++++++++++++++ modules/userId/index.js | 13 ++- test/spec/modules/appnexusBidAdapter_spec.js | 16 +++ test/spec/modules/criteortusIdSystem_spec.js | 88 ++++++++++++++++ 6 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 modules/criteortusIdSystem.js create mode 100644 test/spec/modules/criteortusIdSystem_spec.js diff --git a/modules/.submodules.json b/modules/.submodules.json index f321e075208..097fe4b1f3b 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -1,7 +1,8 @@ { "userId": [ "digiTrustIdSystem", - "id5IdSystem" + "id5IdSystem", + "criteortusIdSystem" ], "adpod": [ "freeWheelAdserverVideo" diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 50c5a0e6f04..67388848815 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -169,6 +169,16 @@ export const spec = { }); } + const rtusId = utils.deepAccess(bidRequests[0], `userId.criteortus.${BIDDER_CODE}.userid`); + if (rtusId) { + let tpuids = []; + tpuids.push({ + 'provider': 'criteo', + 'user_id': rtusId + }); + payload.tpuids = tpuids; + } + const request = formatRequest(payload, bidderRequest); return request; }, diff --git a/modules/criteortusIdSystem.js b/modules/criteortusIdSystem.js new file mode 100644 index 00000000000..02edf0ef06e --- /dev/null +++ b/modules/criteortusIdSystem.js @@ -0,0 +1,105 @@ +/** + * This module adds Criteo Real Time User Sync to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/criteortusIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils' +import { ajax } from '../src/ajax'; +import { submodule } from '../src/hook'; + +const key = '__pbjs_criteo_rtus'; + +/** @type {Submodule} */ +export const criteortusIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'criteortus', + /** + * decode the stored id value for passing to bid requests + * @function + * @returns {{criteortus:Object}} + */ + decode() { + let uid = utils.getCookie(key); + try { + uid = JSON.parse(uid); + return { 'criteortus': uid }; + } catch (error) { + utils.logError('Error in parsing criteo rtus data', error); + } + }, + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @param {SubmoduleParams} [configParams] + * @returns {function(callback:function)} + */ + getId(configParams) { + if (!configParams || !utils.isPlainObject(configParams.clientIdentifier)) { + utils.logError('User ID - Criteo rtus requires client identifier to be defined'); + return; + } + + let uid = utils.getCookie(key); + if (uid) { + return uid; + } else { + let userIds = {}; + return function(callback) { + let bidders = Object.keys(configParams.clientIdentifier); + + function afterAllResponses() { + // criteo rtus user id expires in 1 hour + const expiresStr = (new Date(Date.now() + (60 * 60 * 1000))).toUTCString(); + utils.setCookie(key, JSON.stringify(userIds), expiresStr); + callback(userIds); + } + + const onResponse = utils.delayExecution(afterAllResponses, bidders.length); + + bidders.forEach((bidder) => { + let url = `https://gum.criteo.com/sync?c=${configParams.clientIdentifier[bidder]}&r=3`; + const getSuccessHandler = (bidder) => { + return function onSuccess(response) { + if (response) { + try { + response = JSON.parse(response); + userIds[bidder] = response; + onResponse(); + } catch (error) { + utils.logError(error); + } + } + } + } + + const getFailureHandler = (bidder) => { + return function onFailure(error) { + utils.logError(`Criteo RTUS server call failed for ${bidder}`, error); + onResponse(); + } + } + + ajax( + url, + { + success: getSuccessHandler(bidder), + error: getFailureHandler(bidder) + }, + undefined, + Object.assign({ + method: 'GET', + withCredentials: true + }) + ); + }) + } + } + } +}; + +submodule('userId', criteortusIdSubmodule); diff --git a/modules/userId/index.js b/modules/userId/index.js index 2091a6a763a..e83258a4e02 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -186,7 +186,9 @@ function processSubmoduleCallbacks(submodules) { submodule.callback = undefined; // if valid, id data should be saved to cookie/html storage if (idObj) { - setStoredValue(submodule.config.storage, idObj, submodule.config.storage.expires); + if (submodule.config.storage) { + setStoredValue(submodule.config.storage, idObj, submodule.config.storage.expires); + } // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.submodule.decode(idObj); } else { @@ -299,6 +301,13 @@ function initSubmodules(submodules, consentData) { } else if (submodule.config.value) { // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.config.value; + } else { + const result = submodule.submodule.getId(submodule.config.params, consentData); + if (typeof result === 'function') { + submodule.callback = result; + } else { + submodule.idObj = submodule.submodule.decode(); + } } carry.push(submodule); return carry; @@ -332,6 +341,8 @@ function getValidSubmoduleConfigs(configRegistry, submoduleRegistry, activeStora carry.push(config); } else if (utils.isPlainObject(config.value)) { carry.push(config); + } else if (!config.storage && !config.value) { + carry.push(config); } return carry; }, []); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index e55e3e32029..30d2dc08159 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -614,6 +614,22 @@ describe('AppNexusAdapter', function () { rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') }); }); + + it('should populate tpids array when userId is available', function () { + const bidRequest = Object.assign({}, bidRequests[0], { + userId: { + criteortus: { + appnexus: { + userid: 'sample-userid' + } + } + } + }); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.tpuids).to.deep.equal([{provider: 'criteo', user_id: 'sample-userid'}]); + }); }) describe('interpretResponse', function () { diff --git a/test/spec/modules/criteortusIdSystem_spec.js b/test/spec/modules/criteortusIdSystem_spec.js new file mode 100644 index 00000000000..578f14d066d --- /dev/null +++ b/test/spec/modules/criteortusIdSystem_spec.js @@ -0,0 +1,88 @@ +import { criteortusIdSubmodule } from 'modules/criteortusIdSystem'; +import * as utils from 'src/utils'; + +describe('Criteo RTUS', function() { + let xhr; + let requests; + let getCookieStub; + let logErrorStub; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + getCookieStub = sinon.stub(utils, 'getCookie'); + logErrorStub = sinon.stub(utils, 'logError'); + }); + + afterEach(function () { + xhr.restore(); + getCookieStub.restore(); + logErrorStub.restore(); + }); + + it('should log error when configParams are not passed', function() { + criteortusIdSubmodule.getId(); + expect(logErrorStub.calledOnce).to.be.true; + }) + + it('should call criteo endpoint to get user id', function() { + getCookieStub.returns(null); + let configParams = { + clientIdentifier: { + 'sampleBidder': 1 + } + } + + let response = { 'status': 'ok', 'userid': 'sample-userid' } + let callBackSpy = sinon.spy(); + let submoduleCallback = criteortusIdSubmodule.getId(configParams); + submoduleCallback(callBackSpy); + requests[0].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify(response) + ); + expect(callBackSpy.calledOnce).to.be.true; + expect(callBackSpy.calledWith({'sampleBidder': response})).to.be.true; + }) + + it('should get uid from cookie and not call endpoint', function() { + let response = {'appnexus': {'status': 'ok', 'userid': 'sample-userid'}} + getCookieStub.returns(JSON.stringify(response)); + let configParams = { + clientIdentifier: { + 'sampleBidder': 1 + } + } + let uid = criteortusIdSubmodule.getId(configParams); + expect(requests.length).to.equal(0); + }) + + it('should call criteo endpoint for multiple bidders', function() { + getCookieStub.returns(null); + let configParams = { + clientIdentifier: { + 'sampleBidder': 1, + 'sampleBidder2': 2 + } + } + + let response = { 'status': 'ok', 'userid': 'sample-userid' } + let callBackSpy = sinon.spy(); + let submoduleCallback = criteortusIdSubmodule.getId(configParams); + submoduleCallback(callBackSpy); + requests[0].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify(response) + ); + expect(callBackSpy.calledOnce).to.be.false; + requests[1].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify(response) + ); + expect(callBackSpy.calledOnce).to.be.true; + }) +}); From d44fe458f2e53e93f6c8b8a6991084f2cf921e28 Mon Sep 17 00:00:00 2001 From: Samuel Adu Date: Tue, 9 Jul 2019 18:20:22 +0100 Subject: [PATCH 1328/1594] AOL Adapter: Perform requests over https by default. (#3957) * Perform requests over https by default. Preserve insecure requests only if explicitly specified via the server override parameter (to aid with testing). * Slight refactor. --- modules/aolBidAdapter.js | 21 ++++++---- test/spec/modules/aolBidAdapter_spec.js | 56 ++++++++++++++++++------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 5b8a76db4fc..c065828c10d 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -29,17 +29,18 @@ const SYNC_TYPES = { } }; -const pubapiTemplate = template`//${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'};${'dynamicParams'}`; -const nexageBaseApiTemplate = template`//${'host'}/bidRequest?`; +const pubapiTemplate = template`${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'};${'dynamicParams'}`; +const nexageBaseApiTemplate = template`${'host'}/bidRequest?`; const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'dynamicParams'}`; const MP_SERVER_MAP = { us: 'adserver-us.adtech.advertising.com', eu: 'adserver-eu.adtech.advertising.com', as: 'adserver-as.adtech.advertising.com' }; -const NEXAGE_SERVER = 'hb.nexage.com'; +const NEXAGE_SERVER = 'c2shb.ssp.yahoo.com'; const ONE_DISPLAY_TTL = 60; const ONE_MOBILE_TTL = 3600; +const DEFAULT_PROTO = 'https'; const NUMERIC_VALUES = { TRUE: 1, @@ -198,7 +199,7 @@ export const spec = { // Set region param, used by AOL analytics. params.region = regionParam; - return pubapiTemplate({ + return this.applyProtocol(pubapiTemplate({ host: server, network: params.network, placement: parseInt(params.placement), @@ -207,7 +208,7 @@ export const spec = { alias: params.alias || utils.getUniqueIdentifierStr(), misc: new Date().getTime(), // cache busting dynamicParams: this.formatMarketplaceDynamicParams(params, consentData) - }); + })); }, buildOneMobileGetUrl(bid, consentData) { let {dcn, pos, ext} = bid.params; @@ -219,9 +220,15 @@ export const spec = { return nexageApi; }, buildOneMobileBaseUrl(bid) { - return nexageBaseApiTemplate({ + return this.applyProtocol(nexageBaseApiTemplate({ host: bid.params.host || NEXAGE_SERVER - }); + })); + }, + applyProtocol(url) { + if (/^https?:\/\//i.test(url)) { + return url; + } + return (url.indexOf('//') === 0) ? `${DEFAULT_PROTO}:${url}` : `${DEFAULT_PROTO}://${url}`; }, formatMarketplaceDynamicParams(params = {}, consentData) { let queryParams = {}; diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index 7817c939b69..8386c2c2462 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -76,8 +76,8 @@ let getPixels = () => { }; describe('AolAdapter', function () { - const MARKETPLACE_URL = '//adserver-us.adtech.advertising.com/pubapi/3.0/'; - const NEXAGE_URL = '//hb.nexage.com/bidRequest?'; + const MARKETPLACE_URL = 'https://adserver-us.adtech.advertising.com/pubapi/3.0/'; + const NEXAGE_URL = 'https://c2shb.ssp.yahoo.com/bidRequest?'; const ONE_DISPLAY_TTL = 60; const ONE_MOBILE_TTL = 3600; @@ -152,7 +152,7 @@ describe('AolAdapter', function () { it('should return request for Marketplace endpoint', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should return request for Marketplace via onedisplay bidder code', function () { @@ -164,7 +164,7 @@ describe('AolAdapter', function () { }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should return Marketplace request via onedisplay bidder code when' + @@ -178,7 +178,7 @@ describe('AolAdapter', function () { }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should return Marketplace request via onedisplay bidder code when' + @@ -192,7 +192,7 @@ describe('AolAdapter', function () { }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should not resolve endpoint for onedisplay bidder code ' + @@ -218,10 +218,37 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); + expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) + .to.equal(0); }); - it('should return Marketplace URL for eu region when server option is present', function () { + it('should return insecure MP URL if insecure server option is present', function () { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + server: 'http://adserver-eu.adtech.advertising.com' + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url.indexOf('http://adserver-eu.adtech.advertising.com/pubapi/3.0/')) + .to.equal(0); + }); + + it('should return a secure MP URL if relative proto server option is present', function () { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + server: '//adserver-eu.adtech.advertising.com' + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) + .to.equal(0); + }); + + it('should return a secure MP URL when server option without protocol is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -230,7 +257,8 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); + expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) + .to.equal(0); }); it('should return default Marketplace URL in case of unknown region config option', function () { @@ -242,7 +270,7 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should return url with pubapi bid option', function () { @@ -358,13 +386,13 @@ describe('AolAdapter', function () { it('should return One Mobile url with different host when host option is present', function () { let bidParams = Object.assign({ - host: 'qa-hb.nexage.com' + host: 'http://qa-hb.nexage.com' }, getNexageGetBidParams()); let bidRequest = createCustomBidRequest({ params: bidParams }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('qa-hb.nexage.com/bidRequest?'); + expect(request.url).to.contain('http://qa-hb.nexage.com/bidRequest?'); }); it('should return One Mobile url when One Mobile and Marketplace params are present', function () { @@ -431,7 +459,7 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('hb.nexage.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid' + + expect(request.url).to.equal('https://c2shb.ssp.yahoo.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid' + '¶m1=val1¶m2=val2¶m3=val3¶m4=val4'); }); @@ -455,7 +483,7 @@ describe('AolAdapter', function () { }); it('should not return request object for One Mobile POST endpoint' + - 'if required parameterers are missed', () => { + 'if required parameters are missed', () => { let bidRequest = createCustomBidRequest({ params: { imp: [] From 7d110079ac6de4a50ce29acd3d4715a0fc9d070d Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Tue, 9 Jul 2019 13:21:06 -0400 Subject: [PATCH 1329/1594] Rubicon add meta fields to bids (#3947) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * Added meta fields to bids in response from Rubicon exchange --- modules/rubiconBidAdapter.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 881ce480aef..b4b8e98e393 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -557,6 +557,9 @@ export const spec = { netRevenue: config.getConfig('rubicon.netRevenue') || false, rubicon: { advertiserId: ad.advertiser, networkId: ad.network + }, + meta: { + advertiserId: ad.advertiser, networkId: ad.network } }; From ca16968c0ca8b6cfaaeb8554f06a9375c0a5232b Mon Sep 17 00:00:00 2001 From: John Rosendahl Date: Tue, 9 Jul 2019 11:25:55 -0600 Subject: [PATCH 1330/1594] Sovrn Analytics : Calculate highest bid based on ad unit (#3973) --- modules/sovrnAnalyticsAdapter.js | 11 ++- .../modules/sovrnAnalyticsAdapter_spec.js | 76 ++++++++++++++++++- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/modules/sovrnAnalyticsAdapter.js b/modules/sovrnAnalyticsAdapter.js index 3113f7ff5af..bb9051b5a8a 100644 --- a/modules/sovrnAnalyticsAdapter.js +++ b/modules/sovrnAnalyticsAdapter.js @@ -211,15 +211,18 @@ class AuctionData { * Sends the auction to the the ingest server */ send() { - let maxbid = {cpm: 0} + let maxBids = {} this.auction.requests.forEach(request => { request.bids.forEach(bid => { - if (bid.cpm > maxbid.cpm) { - maxbid = bid + maxBids[bid.adUnitCode] = maxBids[bid.adUnitCode] || {cpm: 0} + if (bid.cpm > maxBids[bid.adUnitCode].cpm) { + maxBids[bid.adUnitCode] = bid } }) }) - maxbid.isAuctionWinner = true + Object.keys(maxBids).forEach(unit => { + maxBids[unit].isAuctionWinner = true + }) this.auction.ts = utils.timestamp() ajax( pbaUrl, diff --git a/test/spec/modules/sovrnAnalyticsAdapter_spec.js b/test/spec/modules/sovrnAnalyticsAdapter_spec.js index 404833f0177..299e22ca790 100644 --- a/test/spec/modules/sovrnAnalyticsAdapter_spec.js +++ b/test/spec/modules/sovrnAnalyticsAdapter_spec.js @@ -27,8 +27,11 @@ let auctionInit = { let bidderCode = 'sovrn'; let bidderRequestId = '123bri'; let adUnitCode = 'div'; +let adUnitCode2 = 'div2'; let bidId = 'bidid'; +let bidId2 = 'bidid2'; let tId = '7aafa3ee-a80a-46d7-a4a0-cbcba463d97a'; +let tId2 = '99dca3ee-a80a-46d7-a4a0-cbcba463d97e'; let bidRequested = { auctionStart: auctionStartTimestamp, bidderCode: bidderCode, @@ -42,6 +45,15 @@ let bidRequested = { sizes: [[300, 250]], startTime: auctionStartTimestamp + 100, transactionId: tId + }, + { + adUnitCode: adUnitCode2, + bidId: bidId2, + bidder: bidderCode, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 100, + transactionId: tId2 } ], doneCbCallCount: 1, @@ -83,6 +95,42 @@ let bidResponse = { }, status: 'rendered' }; + +let bidResponse2 = { + bidderCode: bidderCode, + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '9999e27a5752fb', + mediaType: 'banner', + source: 'client', + requestId: bidId2, + cpm: 0.12, + creativeId: 'cridprebidrtb', + dealId: null, + currency: 'USD', + netRevenue: true, + ad: '
    divvy mcdiv
    ', + ttl: 60000, + responseTimestamp: auctionStartTimestamp + 150, + requestTimestamp: auctionStartTimestamp + 100, + bidder: bidderCode, + adUnitCode: adUnitCode2, + timeToRespond: 50, + pbLg: '0.10', + pbMg: '0.10', + pbHg: '0.10', + pbAg: '0.10', + pbDg: '0.10', + pbCg: '', + size: '300x250', + adserverTargeting: { + hb_bidder: bidderCode, + hb_adid: '9999e27a5752fb', + hb_pb: '0.10' + }, + status: 'rendered' +}; let bidAdjustment = {}; for (var k in bidResponse) bidAdjustment[k] = bidResponse[k]; bidAdjustment.cpm = 0.8; @@ -245,7 +293,7 @@ describe('Sovrn Analytics Adapter', function () { assert.equal(requests[0].timeout, timeout); let bids = requests[0].bids; assert(bids); - assert.equal(bids.length, 1); + assert.equal(bids.length, 2); assert.equal(bids[0].bidId, bidId); assert.equal(bids[0].bidder, bidderCode); assert.equal(bids[0].transactionId, tId); @@ -340,6 +388,29 @@ describe('Sovrn Analytics Adapter', function () { status: 'rendered', isAuctionWinner: true }; + let SecondAdUnitExpectedBids = { + adUnitCode: 'div2', + bidId: 'bidid2', + bidder: 'sovrn', + bidderRequestId: '10340af0c7dc72', + transactionId: '99dca3ee-a80a-46d7-a4a0-cbcba463d97e', + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '9999e27a5752fb', + mediaType: 'banner', + source: 'client', + cpm: 0.12, + creativeId: 'cridprebidrtb', + dealId: null, + currency: 'USD', + netRevenue: true, + ttl: 60000, + timeToRespond: 50, + size: '300x250', + status: 'rendered', + isAuctionWinner: true + }; let expectedAdServerTargeting = { hb_bidder: 'sovrn', hb_adid: '3870e27a5752fb', @@ -363,6 +434,7 @@ describe('Sovrn Analytics Adapter', function () { emitEvent('AUCTION_INIT', auctionInit, auctionId); emitEvent('BID_REQUESTED', bidRequested, auctionId); emitEvent('BID_RESPONSE', bidResponse, auctionId); + emitEvent('BID_RESPONSE', bidResponse2, auctionId) emitEvent('AUCTION_END', {}, auctionId); let requestBody = JSON.parse(requests[0].requestBody); let requestsFromRequestBody = requestBody.requests[0]; @@ -371,6 +443,8 @@ describe('Sovrn Analytics Adapter', function () { expect(requestBody.timeouts).to.deep.equal({buffer: 400, bidder: 3000}); expect(requestsFromRequestBody).to.deep.include(expectedRequests); expect(bidsFromRequests).to.deep.include(expectedBids); + let bidsFromRequests2 = requestsFromRequestBody.bids[1]; + expect(bidsFromRequests2).to.deep.include(SecondAdUnitExpectedBids); expect(bidsFromRequests.adserverTargeting).to.deep.include(expectedAdServerTargeting); }); }); From f2b0f5217102ccecb449d66b214d697095daea63 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 9 Jul 2019 13:29:21 -0400 Subject: [PATCH 1331/1594] update sizeConfig logic around multiformat bids (#3938) --- src/sizeMapping.js | 4 +- test/spec/sizeMapping_spec.js | 105 ++++++++++++++++++++++++++++++---- 2 files changed, 95 insertions(+), 14 deletions(-) diff --git a/src/sizeMapping.js b/src/sizeMapping.js index 04c9773a1af..cde3b4a4d15 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -88,9 +88,9 @@ export function resolveStatus({labels = [], labelAll = false, activeLabels = []} let results = { active: ( - allMediaTypes.length > 1 || (allMediaTypes.length === 1 && allMediaTypes[0] !== 'banner') + allMediaTypes.every(type => type !== 'banner') ) || ( - allMediaTypes[0] === 'banner' && deepAccess(mediaTypes, 'banner.sizes.length') > 0 && ( + allMediaTypes.some(type => type === 'banner') && deepAccess(mediaTypes, 'banner.sizes.length') > 0 && ( labels.length === 0 || ( (!labelAll && ( labels.some(label => maps.labels[label]) || diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index f85da4cba0b..254dcb8003e 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -66,13 +66,6 @@ describe('sizeMapping', function () { } return matchMediaOverride; }); - - sandbox.stub(window, 'matchMedia').callsFake((...args) => { - if (typeof matchMediaOverride === 'function') { - return matchMediaOverride.apply(window, args); - } - return matchMediaOverride; - }); }); afterEach(function () { @@ -161,15 +154,14 @@ describe('sizeMapping', function () { }); }); - it('should filter all banner sizes but not disable adUnit if multiple mediaTypes are present', function () { + it('should filter all banner sizes and should disable the adUnit even if other mediaTypes are present', function () { matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; - let status = resolveStatus(undefined, Object.assign({}, testSizes, { native: { type: 'image' } }), undefined, sizeConfig); - expect(status.active).to.equal(true); + expect(status.active).to.equal(false); expect(status.mediaTypes).to.deep.equal({ banner: { sizes: [] @@ -210,12 +202,101 @@ describe('sizeMapping', function () { expect(status.mediaTypes).to.deep.equal(testSizes); }); + it('should activate/decactivate adUnits/bidders based on labels with multiformat ads', function () { + matchMediaOverride = (str) => str === '(min-width: 768px) and (max-width: 1199px)' ? {matches: true} : {matches: false}; + + let multiFormatSizes = { + banner: { + sizes: [[728, 90], [300, 300]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }; + + let status = resolveStatus({ + labels: ['tablet', 'test'], + labelAll: true + }, multiFormatSizes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[728, 90]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }); + + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[728, 90]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }); + + multiFormatSizes.banner.sizes.splice(0, 1, [728, 80]); + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }); + + delete multiFormatSizes.banner; + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }); + }); + it('should active/deactivate adUnits/bidders based on requestBids labels', function () { let activeLabels = ['us-visitor', 'desktop', 'smart']; let status = resolveStatus({ - labels: ['uk-visitor'], - activeLabels + labels: ['uk-visitor'], // from adunit + activeLabels // from requestBids.labels }, testSizes, undefined, sizeConfigWithLabels); expect(status.active).to.equal(false); From 95495bfd0193cb4e62634b0e6ec8a7a8b5d9927a Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 9 Jul 2019 12:45:31 -0600 Subject: [PATCH 1332/1594] add eslint plugin for checking imports (#3976) --- .eslintrc.js | 34 ++++++++++++++++- modules/ixBidAdapter.js | 3 +- package.json | 2 + plugins/eslint/package.json | 8 ++++ plugins/eslint/validateImports.js | 61 ++++++++++++++++++++++++++++++ src/adapters/analytics/example2.js | 2 +- 6 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 plugins/eslint/package.json create mode 100644 plugins/eslint/validateImports.js diff --git a/.eslintrc.js b/.eslintrc.js index 02ff81614c7..22b4f29d4e9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,13 @@ + +const sharedWhiteList = [ + "core-js/library/fn/array/find", // no ie11 + "core-js/library/fn/array/includes", // no ie11 + "core-js/library/fn/set", // ie11 supports Set but not Set#values + "core-js/library/fn/string/includes", // no ie11 + "core-js/library/fn/number/is-integer", // no ie11, + "core-js/library/fn/array/from" // no ie11 +]; + module.exports = { "env": { "browser": true, @@ -11,6 +21,9 @@ module.exports = { } }, "extends": "standard", + "plugins": [ + "prebid" + ], "globals": { "$$PREBID_GLOBAL$$": false }, @@ -31,5 +44,24 @@ module.exports = { "no-throw-literal": "off", "no-undef": "off", "no-useless-escape": "off", - } + }, + "overrides": [{ + "files": "modules/**/*.js", + "rules": { + "prebid/validate-imports": ["error", [ + ...sharedWhiteList, + "jsencrypt", + "crypto-js" + ]] + } + }, { + "files": "src/**/*.js", + "rules": { + "prebid/validate-imports": ["error", [ + ...sharedWhiteList, + "fun-hooks/no-eval", + "just-clone" + ]] + } + }] }; diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index c63b920dc93..8d76d862655 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -1,7 +1,6 @@ import * as utils from '../src/utils'; import { BANNER } from '../src/mediaTypes'; import { config } from '../src/config'; -import isArray from 'core-js/library/fn/array/is-array'; import isInteger from 'core-js/library/fn/number/is-integer'; import { registerBidder } from '../src/adapters/bidderFactory'; @@ -92,7 +91,7 @@ function parseBid(rawBid, currency) { * @return {boolean} True if this is a valid size format, and false otherwise. */ function isValidSize(size) { - return isArray(size) && size.length === 2 && isInteger(size[0]) && isInteger(size[1]); + return Array.isArray(size) && size.length === 2 && isInteger(size[0]) && isInteger(size[1]); } /** diff --git a/package.json b/package.json index 5e2806fe5f4..b386981d85d 100755 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "eslint-plugin-node": "^5.1.0", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", + "eslint-plugin-prebid": "file:./plugins/eslint", "execa": "^1.0.0", "faker": "^3.1.0", "fs.extra": "^1.3.2", @@ -79,6 +80,7 @@ "mocha": "^5.0.0", "opn": "^5.4.0", "querystringify": "0.0.3", + "resolve-from": "^5.0.0", "sinon": "^4.1.3", "through2": "^2.0.3", "url-parse": "^1.0.5", diff --git a/plugins/eslint/package.json b/plugins/eslint/package.json new file mode 100644 index 00000000000..fa18ad83718 --- /dev/null +++ b/plugins/eslint/package.json @@ -0,0 +1,8 @@ +{ + "name": "eslint-plugin-prebid", + "version": "1.0.0", + "description": "validates module imports can be found without custom webpack resolvers, are in module whitelist, and not module entry points", + "main": "validateImports.js", + "author": "the prebid.js contributors", + "license": "Apache-2.0" +} diff --git a/plugins/eslint/validateImports.js b/plugins/eslint/validateImports.js new file mode 100644 index 00000000000..c655902f7d3 --- /dev/null +++ b/plugins/eslint/validateImports.js @@ -0,0 +1,61 @@ + +let path = require('path'); +let _ = require('lodash'); +let resolveFrom = require('resolve-from'); + +function flagErrors(context, node, importPath) { + let absFileDir = path.dirname(context.getFilename()); + let absImportPath = path.resolve(absFileDir, importPath); + + try { + resolveFrom(absFileDir, importPath); + } catch (e) { + return context.report(node, `import "${importPath}" cannot be resolved`); + } + + if ( + Array.isArray(_.get(context, ['options', 0])) && + importPath.match(/^\w+/) && + !context.options[0].some(name => importPath.startsWith(name)) + ) { + context.report(node, `import "${importPath}" not in import whitelist`); + } else { + let absModulePath = path.resolve(__dirname, '../../modules'); + + // don't allow import of any files directly within modules folder or index.js files within modules' sub-folders + if ( + path.dirname(absImportPath) === absModulePath || ( + absImportPath.startsWith(absModulePath) && + path.basename(absImportPath) === 'index.js' + ) + ) { + context.report(node, `import "${importPath}" cannot require module entry point`); + } + } +} + +module.exports = { + rules: { + 'validate-imports': { + meta: { + docs: { + description: 'validates module imports can be found without custom webpack resolvers, are in module whitelist, and not module entry points' + } + }, + create: function(context) { + return { + "CallExpression[callee.name='require']"(node) { + let importPath = _.get(node, ['arguments', 0, 'value']); + if (importPath) { + flagErrors(context, node, importPath); + } + }, + ImportDeclaration(node) { + let importPath = node.source.value.trim(); + flagErrors(context, node, importPath); + } + } + } + } + } +}; diff --git a/src/adapters/analytics/example2.js b/src/adapters/analytics/example2.js index 6888507010d..b04e8874e48 100644 --- a/src/adapters/analytics/example2.js +++ b/src/adapters/analytics/example2.js @@ -1,4 +1,4 @@ -import { ajax } from 'src/ajax'; +import { ajax } from '../../../src/ajax'; /** * example2.js - analytics adapter for Example2 Analytics Endpoint example From 1086def641160551ae169540b58d08a894ebf6d4 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 9 Jul 2019 14:57:04 -0400 Subject: [PATCH 1333/1594] Fix #3939 - update firefox specific code in renderAd function (#3980) * update browser specific code in renderAd function * update TODO comment --- src/prebid.js | 11 ++++++++++- test/spec/unit/pbjs_api_spec.js | 2 -- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 1b6a40aff97..90f6365585e 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -325,7 +325,16 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { const message = `Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`; emitAdRenderFail(PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid); } else if (ad) { - doc.open('text/html', 'replace'); + // 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); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index b734faf9dd5..d4daec0c266 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -990,7 +990,6 @@ describe('Unit: Prebid Module', function () { beforeEach(function () { doc = { - open: sinon.spy(), write: sinon.spy(), close: sinon.spy(), defaultView: { @@ -1041,7 +1040,6 @@ describe('Unit: Prebid Module', function () { }); adResponse.ad = ""; $$PREBID_GLOBAL$$.renderAd(doc, bidId); - assert.ok(doc.open, 'open method called'); assert.ok(doc.write.calledWith(adResponse.ad), 'ad was written to doc'); assert.ok(doc.close.called, 'close method called'); }); From a52232e047acd97ef4dee40af1f6573df5a73bff Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 9 Jul 2019 14:05:09 -0700 Subject: [PATCH 1334/1594] Prebid 2.23.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b386981d85d..06cd486c14c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.23.0-pre", + "version": "2.23.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b777ae1a269abb5968893987b29be445f74a1e69 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 9 Jul 2019 14:20:12 -0700 Subject: [PATCH 1335/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 06cd486c14c..5ca8c03783d 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.23.0", + "version": "2.24.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b26e6adb2414d64f5bb551c1698ee0fd5e3d00a2 Mon Sep 17 00:00:00 2001 From: Andrew Muraco Date: Thu, 11 Jul 2019 14:58:28 -0400 Subject: [PATCH 1336/1594] Synacor media bidder updates: filter bad sizes & extra video parameters (#3885) * Synacor media bidder updates: - Filter out 1x1 & 1x2 adsizes that we don't support - Added a bunch of openrtb video params * SynacormediaBidAdapter: Replace let with const * SynacormediaBidAdapter: Replace let with const * SynacormediaBidAdapter: Updated setValidVideoParams Updated setValidVideoParams so that the length check works correctly. --- modules/synacormediaBidAdapter.js | 99 ++++++++------ modules/synacormediaBidAdapter.md | 16 +-- .../modules/synacormediaBidAdapter_spec.js | 129 ++++++++++++++++++ 3 files changed, 195 insertions(+), 49 deletions(-) diff --git a/modules/synacormediaBidAdapter.js b/modules/synacormediaBidAdapter.js index 3339ecfb04f..ca533f8cff8 100644 --- a/modules/synacormediaBidAdapter.js +++ b/modules/synacormediaBidAdapter.js @@ -7,8 +7,11 @@ import includes from 'core-js/library/fn/array/includes'; const BID_HOST = '//prebid.technoratimedia.com'; const USER_SYNC_HOST = '//ad-cdn.technoratimedia.com'; -const VIDEO_PARAMS = [ 'minduration', 'maxduration' ]; - +const VIDEO_PARAMS = [ 'minduration', 'maxduration', 'startdelay', 'placement', 'linearity', 'mimes', 'protocols', 'api' ]; +const BLOCKED_AD_SIZES = [ + '1x1', + '1x2' +]; export const spec = { code: 'synacormedia', supportedMediaTypes: [ BANNER, VIDEO ], @@ -19,15 +22,17 @@ export const spec = { bid.mediaTypes.hasOwnProperty('video'); }, isBidRequestValid: function(bid) { - return !!(bid && bid.params && bid.params.placementId && bid.params.seatId); + const hasRequiredParams = bid && bid.params && bid.params.hasOwnProperty('placementId') && bid.params.hasOwnProperty('seatId'); + const hasAdSizes = bid && getAdUnitSizes(bid).filter(size => BLOCKED_AD_SIZES.indexOf(size.join('x')) === -1).length > 0 + return !!(hasRequiredParams && hasAdSizes); }, buildRequests: function(validBidReqs, bidderRequest) { if (!validBidReqs || !validBidReqs.length || !bidderRequest) { return; } - let refererInfo = bidderRequest.refererInfo; - let openRtbBidRequest = { + const refererInfo = bidderRequest.refererInfo; + const openRtbBidRequest = { id: bidderRequest.auctionId, site: { domain: location.hostname, @@ -40,6 +45,7 @@ export const spec = { imp: [] }; let seatId = null; + validBidReqs.forEach((bid, i) => { if (seatId && seatId !== bid.params.seatId) { logWarn(`Synacormedia: there is an inconsistent seatId: ${bid.params.seatId} but only sending bid requests for ${seatId}, you should double check your configuration`); @@ -47,8 +53,8 @@ export const spec = { } else { seatId = bid.params.seatId; } - let placementId = bid.params.placementId; - let bidFloor = bid.params.bidfloor ? parseFloat(bid.params.bidfloor) : null; + const placementId = bid.params.placementId; + const bidFloor = bid.params.bidfloor ? parseFloat(bid.params.bidfloor) : null; if (isNaN(bidFloor)) { logWarn(`Synacormedia: there is an invalid bid floor: ${bid.params.bidfloor}`); } @@ -57,34 +63,39 @@ export const spec = { logWarn(`Synacormedia: there is an invalid POS: ${bid.params.pos}`); pos = 0; } - let videoOrBannerKey = this.isVideoBid(bid) ? 'video' : 'banner'; - getAdUnitSizes(bid).forEach((size, i) => { - if (!size || size.length != 2) { - return; - } - let size0 = size[0]; - let size1 = size[1]; - let imp = { - id: `${videoOrBannerKey.substring(0, 1)}${bid.bidId}-${size0}x${size1}`, - tagid: placementId - }; - if (bidFloor !== null && !isNaN(bidFloor)) { - imp.bidfloor = bidFloor; - } + const videoOrBannerKey = this.isVideoBid(bid) ? 'video' : 'banner'; + getAdUnitSizes(bid) + .filter(size => BLOCKED_AD_SIZES.indexOf(size.join('x')) === -1) + .forEach((size, i) => { + if (!size || size.length != 2) { + return; + } + const size0 = size[0]; + const size1 = size[1]; + const imp = { + id: `${videoOrBannerKey.substring(0, 1)}${bid.bidId}-${size0}x${size1}`, + tagid: placementId + }; + if (bidFloor !== null && !isNaN(bidFloor)) { + imp.bidfloor = bidFloor; + } - let videoOrBannerValue = { - w: size0, - h: size1, - pos - }; - if (videoOrBannerKey === 'video' && bid.params.video) { - Object.keys(bid.params.video) - .filter(param => includes(VIDEO_PARAMS, param) && !isNaN(parseInt(bid.params.video[param], 10))) - .forEach(param => videoOrBannerValue[param] = parseInt(bid.params.video[param], 10)); - } - imp[videoOrBannerKey] = videoOrBannerValue; - openRtbBidRequest.imp.push(imp); - }); + const videoOrBannerValue = { + w: size0, + h: size1, + pos + }; + if (videoOrBannerKey === 'video') { + if (bid.mediaTypes.video) { + this.setValidVideoParams(bid.mediaTypes.video, bid.params.video); + } + if (bid.params.video) { + this.setValidVideoParams(bid.params.video, videoOrBannerValue); + } + } + imp[videoOrBannerKey] = videoOrBannerValue; + openRtbBidRequest.imp.push(imp); + }); }); if (openRtbBidRequest.imp.length && seatId) { @@ -99,8 +110,14 @@ export const spec = { }; } }, + + setValidVideoParams: function (sourceObj, destObj) { + Object.keys(sourceObj) + .filter(param => includes(VIDEO_PARAMS, param) && sourceObj[param] !== null && (!isNaN(parseInt(sourceObj[param], 10)) || !(sourceObj[param].length < 1))) + .forEach(param => destObj[param] = Array.isArray(sourceObj[param]) ? sourceObj[param] : parseInt(sourceObj[param], 10)); + }, interpretResponse: function(serverResponse) { - var updateMacros = (bid, r) => { + const updateMacros = (bid, r) => { return r ? r.replace(/\${AUCTION_PRICE}/g, bid.price) : r; }; @@ -114,11 +131,11 @@ export const spec = { if (id && seatbids) { seatbids.forEach(seatbid => { seatbid.bid.forEach(bid => { - let creative = updateMacros(bid, bid.adm); - let nurl = updateMacros(bid, bid.nurl); - let [, impType, impid, width, height] = bid.impid.match(/^([vb])(.*)-(.*)x(.*)$/); - let isVideo = impType == 'v'; - let bidObj = { + const creative = updateMacros(bid, bid.adm); + const nurl = updateMacros(bid, bid.nurl); + const [, impType, impid, width, height] = bid.impid.match(/^([vb])(.*)-(.*)x(.*)$/); + const isVideo = impType == 'v'; + const bidObj = { requestId: impid, adId: bid.id.replace(/~/g, '-'), cpm: parseFloat(bid.price), @@ -132,7 +149,7 @@ export const spec = { ttl: 60 }; if (isVideo) { - let [, uuid] = nurl.match(/ID=([^&]*)&?/); + const [, uuid] = nurl.match(/ID=([^&]*)&?/); bidObj.videoCacheKey = encodeURIComponent(uuid); bidObj.vastUrl = nurl; } diff --git a/modules/synacormediaBidAdapter.md b/modules/synacormediaBidAdapter.md index 1f225aa0b2a..3a00aa45fed 100644 --- a/modules/synacormediaBidAdapter.md +++ b/modules/synacormediaBidAdapter.md @@ -38,26 +38,26 @@ https://track.technoratimedia.com/openrtb/tags?ID=%%PATTERN:hb_cache_id_synacorm }] },{ code: 'test-div2', - mediaType: { + mediaTypes: { video: { - context: 'instream', - playerSizes: [ - [300, 250] - ], + context: 'instream', + playerSize: [[300, 250]], } }, bids: [{ bidder: "synacormedia", params: { seatId: "prebid", - placementId: "demo1" + placementId: "demo1", bidfloor: 0.20, pos: 1, video: { minduration: 15, - maxduration: 30 + maxduration: 30, + startdelay: 1, + linearity: 1 } } }] - }]; + }]; ``` diff --git a/test/spec/modules/synacormediaBidAdapter_spec.js b/test/spec/modules/synacormediaBidAdapter_spec.js index e86bf81a6a7..d2f024181a4 100644 --- a/test/spec/modules/synacormediaBidAdapter_spec.js +++ b/test/spec/modules/synacormediaBidAdapter_spec.js @@ -7,6 +7,7 @@ describe('synacormediaBidAdapter ', function () { let bid; beforeEach(function () { bid = { + sizes: [300, 250], params: { seatId: 'prebid', placementId: '1234' @@ -18,14 +19,26 @@ describe('synacormediaBidAdapter ', function () { assert(spec.isBidRequestValid(bid)); }); + it('should return false when sizes are missing', function () { + delete bid.sizes; + assert.isFalse(spec.isBidRequestValid(bid)); + }); + + it('should return false when the only size is unwanted', function () { + bid.sizes = [[1, 1]]; + assert.isFalse(spec.isBidRequestValid(bid)); + }); + it('should return false when seatId param is missing', function () { delete bid.params.seatId; assert.isFalse(spec.isBidRequestValid(bid)); }); + it('should return false when placementId param is missing', function () { delete bid.params.placementId; assert.isFalse(spec.isBidRequestValid(bid)); }); + it('should return false when params is missing or null', function () { assert.isFalse(spec.isBidRequestValid({ params: null })); assert.isFalse(spec.isBidRequestValid({})); @@ -404,6 +417,122 @@ describe('synacormediaBidAdapter ', function () { req = spec.buildRequests([validBidReqInvalidSize], bidderRequest); assert.isUndefined(req); }); + it('should use all the video params in the impression request', function () { + let validBidRequestVideo = { + bidder: 'synacormedia', + params: { + seatId: 'prebid', + placementId: '1234', + video: { + minduration: 30, + maxduration: 45, + startdelay: 1, + linearity: 1, + placement: 1, + mimes: ['video/mp4'], + protocols: [1], + api: 1 + } + }, + mediaTypes: { + video: { + context: 'instream', + playerSize: [[ 640, 480 ]] + } + }, + adUnitCode: 'video1', + transactionId: '93e5def8-29aa-4fe8-bd3a-0298c39f189a', + sizes: [[ 640, 480 ]], + bidId: '2624fabbb078e8', + bidderRequestId: '117954d20d7c9c', + auctionId: 'defd525f-4f1e-4416-a4cb-ae53be90e706', + src: 'client', + bidRequestsCount: 1 + }; + + let req = spec.buildRequests([validBidRequestVideo], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?src=$$REPO_AND_VERSION$$'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + video: { + h: 480, + pos: 0, + w: 640, + minduration: 30, + maxduration: 45, + startdelay: 1, + linearity: 1, + placement: 1, + mimes: ['video/mp4'], + protocols: [1], + api: 1 + }, + id: 'v2624fabbb078e8-640x480', + tagid: '1234', + } + ]); + }); + it('should move any video params in the mediaTypes object to params.video object', function () { + let validBidRequestVideo = { + bidder: 'synacormedia', + params: { + seatId: 'prebid', + placementId: '1234', + video: { + minduration: 30, + maxduration: 45, + protocols: [1], + api: 1 + } + }, + mediaTypes: { + video: { + context: 'instream', + playerSize: [[ 640, 480 ]], + startdelay: 1, + linearity: 1, + placement: 1, + mimes: ['video/mp4'] + } + }, + adUnitCode: 'video1', + transactionId: '93e5def8-29aa-4fe8-bd3a-0298c39f189a', + sizes: [[ 640, 480 ]], + bidId: '2624fabbb078e8', + bidderRequestId: '117954d20d7c9c', + auctionId: 'defd525f-4f1e-4416-a4cb-ae53be90e706', + src: 'client', + bidRequestsCount: 1 + }; + + let req = spec.buildRequests([validBidRequestVideo], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?src=$$REPO_AND_VERSION$$'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + video: { + h: 480, + pos: 0, + w: 640, + minduration: 30, + maxduration: 45, + startdelay: 1, + linearity: 1, + placement: 1, + mimes: ['video/mp4'], + protocols: [1], + api: 1 + }, + id: 'v2624fabbb078e8-640x480', + tagid: '1234', + } + ]); + }); }); describe('interpretResponse', function () { From 2be5cc7ccbc89c940c1e2e253a989e4a351167e2 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Thu, 11 Jul 2019 12:03:04 -0700 Subject: [PATCH 1337/1594] Adding a method pbjs.getUserIds to share userIds in Prebid to external codes (#3889) * Adding a mthod pbjs.getUserIds to share userIds in Prebid to external codes - Need an API to share the UserIds retrieved by Prebid with external codes - Use casse: UserIds can be passed to Wrappers like A9/EB - Added pbjs.getUserIds method - Moved the cide that initalizes all sub-modules and calls passbacks into a separate function - Moved code to combine submodule ids in an object into a separate function * implemented code suggestion chnages * fixed eslint issue --- modules/userId/index.js | 60 +++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index e83258a4e02..16421e39e20 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -199,12 +199,12 @@ function processSubmoduleCallbacks(submodules) { } /** - * @param {AdUnit[]} adUnits + * This function will create a combined object for all subModule Ids * @param {SubmoduleContainer[]} submodules */ -function addIdDataToAdUnitBids(adUnits, submodules) { - if ([adUnits, submodules].some(i => !Array.isArray(i) || !i.length)) { - return; +function getCombinedSubmoduleIds(submodules) { + if (!Array.isArray(submodules) || !submodules.length) { + return {}; } const combinedSubmoduleIds = submodules.filter(i => utils.isPlainObject(i.idObj) && Object.keys(i.idObj).length).reduce((carry, i) => { Object.keys(i.idObj).forEach(key => { @@ -212,6 +212,19 @@ function addIdDataToAdUnitBids(adUnits, submodules) { }); return carry; }, {}); + + return combinedSubmoduleIds; +} + +/** + * @param {AdUnit[]} adUnits + * @param {SubmoduleContainer[]} submodules + */ +function addIdDataToAdUnitBids(adUnits, submodules) { + if ([adUnits].some(i => !Array.isArray(i) || !i.length)) { + return; + } + const combinedSubmoduleIds = getCombinedSubmoduleIds(submodules); if (Object.keys(combinedSubmoduleIds).length) { adUnits.forEach(adUnit => { adUnit.bids.forEach(bid => { @@ -223,15 +236,9 @@ function addIdDataToAdUnitBids(adUnits, submodules) { } /** - * 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. - * The two main actions handled by the hook are: - * 1. check gdpr consentData and handle submodule initialization. - * 2. append user id data (loaded from cookied/html or from the getId method) to bids to be accessed in adapters. - * @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 + * This is a common function that will initalize subModules if not already done and it will also execute subModule callbacks */ -export function requestBidsHook(fn, reqBidsConfigObj) { +function initializeSubmodulesAndExecuteCallbacks() { // initialize submodules only when undefined if (typeof initializedSubmodules === 'undefined') { initializedSubmodules = initSubmodules(submodules, gdprDataHandler.getConsentData()); @@ -256,14 +263,36 @@ export function requestBidsHook(fn, reqBidsConfigObj) { } } } +} +/** + * 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. + * The two main actions handled by the hook are: + * 1. check gdpr consentData and handle submodule initialization. + * 2. append user id data (loaded from cookied/html or from the getId method) to bids to be accessed in adapters. + * @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) { + // initialize submodules only when undefined + initializeSubmodulesAndExecuteCallbacks(); // pass available user id data to bid adapters addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || getGlobal().adUnits, initializedSubmodules); - // calling fn allows prebid to continue processing return fn.call(this, reqBidsConfigObj); } +/** + * 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 + */ +function getUserIds() { + // initialize submodules only when undefined + initializeSubmodulesAndExecuteCallbacks(); + return getCombinedSubmoduleIds(initializedSubmodules); +}; + /** * @param {SubmoduleContainer[]} submodules * @param {ConsentData} consentData @@ -425,7 +454,10 @@ export function init(config) { syncDelay = utils.isNumber(userSync.syncDelay) ? userSync.syncDelay : DEFAULT_SYNC_DELAY; updateSubmodules(); } - }) + }); + + // exposing getUserIds function in global-name-space so that userIds stored in Prebid can be used by external codes. + (getGlobal()).getUserIds = getUserIds; } // init config update listener to start the application From d17e437affd00929649bdd759e7d2737ede78cad Mon Sep 17 00:00:00 2001 From: sumit116 Date: Fri, 12 Jul 2019 18:22:41 +0530 Subject: [PATCH 1338/1594] restrict outstream w/o renderer to PBS (#3881) * restrict outstream w/o renderer to PBS * reject Request to Prebid Server for invalid media types * add player height and width to response --- modules/prebidServerBidAdapter/index.js | 42 +++++++---- .../modules/prebidServerBidAdapter_spec.js | 75 +++++++++++++++++++ 2 files changed, 103 insertions(+), 14 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 4ac1bccaeda..e857bf1d665 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -495,11 +495,21 @@ const OPEN_RTB_PROTOCOL = { const imp = { id: adUnit.code, ext, secure: _s2sConfig.secure }; if (banner) { imp.banner = banner; } - if (video) { imp.video = video; } - - imps.push(imp); + if (video) { + if (video.context === 'outstream' && !adUnit.renderer) { + // Don't push oustream w/o renderer to request object. + utils.logError('Outstream bid without renderer cannot be sent to Prebid Server.'); + } else { + imp.video = video; + } + } + if (imp.banner || imp.video) { imps.push(imp); } }); + if (!imps.length) { + utils.logError('Request to Prebid Server rejected due to invalid media type(s) in adUnit.') + return; + } const request = { id: s2sBidRequest.tid, source: {tid: s2sBidRequest.tid}, @@ -626,6 +636,9 @@ const OPEN_RTB_PROTOCOL = { if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { bidObject.mediaType = VIDEO; + let sizes = bidRequest.sizes && bidRequest.sizes[0]; + bidObject.playerHeight = sizes[0]; + bidObject.playerWidth = sizes[1]; // try to get cache values from 'response.ext.prebid.cache' // else try 'bid.ext.prebid.targeting' as fallback @@ -721,17 +734,18 @@ export function PrebidServer() { } const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, adUnitsWithSizes); - const requestJson = JSON.stringify(request); - - ajax( - _s2sConfig.endpoint, - { - success: response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done), - error: done - }, - requestJson, - { contentType: 'text/plain', withCredentials: true } - ); + const requestJson = request && JSON.stringify(request); + if (request && requestJson) { + ajax( + _s2sConfig.endpoint, + { + success: response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done), + error: done + }, + requestJson, + { contentType: 'text/plain', withCredentials: true } + ); + } }; /* Notify Prebid of bid responses so bids can get in the auction */ diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index e2a3a5b111a..9562b2f4c07 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -80,6 +80,69 @@ const VIDEO_REQUEST = { ] }; +const OUTSTREAM_VIDEO_REQUEST = { + 'account_id': '1', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'max_bids': 1, + 'timeout_millis': 1000, + 'secure': 0, + 'url': '', + 'prebid_version': '1.4.0-pre', + 'ad_units': [ + { + 'code': 'div-gpt-ad-1460505748561-0', + 'sizes': [640, 480], + 'mediaTypes': { + 'video': { + playerSize: [[ 640, 480 ]], + context: 'outstream', + mimes: ['video/mp4'] + }, + banner: { sizes: [[300, 250]] } + }, + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'bids': [ + { + 'bid_id': '123', + 'bidder': 'appnexus', + 'params': { 'placementId': '12349520' } + } + ] + }, + { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream', + mimes: ['video/mp4'] + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 13232385, + video: { + skippable: true, + playback_method: ['auto_play_sound_off'] + } + } + } + ], + renderer: { + url: 'http://cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + render: function (bid) { + ANOutstreamVideo.renderAd({ + targetId: bid.adUnitCode, + adResponse: bid.adResponse, + }); + } + } + } + ] +}; + let BID_REQUESTS; const RESPONSE = { @@ -390,6 +453,18 @@ describe('S2S Adapter', function () { xhr.restore(); }); + it('should not add outstrean without renderer', function() { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + + config.setConfig({s2sConfig: ortb2Config}); + adapter.callBids(OUTSTREAM_VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.imp[0].banner).to.exist; + expect(requestBid.imp[0].video).to.not.exist; + }); + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); From c70f4e2516b05060abe3455dee7a802331bc8578 Mon Sep 17 00:00:00 2001 From: bidphysics <48674658+bidphysics@users.noreply.github.com> Date: Fri, 12 Jul 2019 21:19:49 +0200 Subject: [PATCH 1339/1594] bidphysics adapter update aliases (#3985) --- modules/bidphysicsBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/bidphysicsBidAdapter.js b/modules/bidphysicsBidAdapter.js index 9f1dc83d427..cbd76c8bc10 100644 --- a/modules/bidphysicsBidAdapter.js +++ b/modules/bidphysicsBidAdapter.js @@ -10,7 +10,7 @@ const DEFAULT_NET_REVENUE = true; export const spec = { code: 'bidphysics', - aliases: ['yieldlift', 'padsquad'], + aliases: ['yieldlift'], supportedMediaTypes: [BANNER], isBidRequestValid: function (bid) { From b9e49d558e2ba0f6e8ba0ba63c3f9acb01922eaf Mon Sep 17 00:00:00 2001 From: ADman Media Date: Mon, 15 Jul 2019 14:53:37 +0200 Subject: [PATCH 1340/1594] Fix typo (#3986) * Add Adman bid adapter * Add supportedMediaTypes property * Update ADman Media bidder adapter * Remove console.log * Fix typo * revert package-json.lock * Delete package-lock.json * back to original package-lock.json --- modules/admanBidAdapter.js | 2 +- test/spec/modules/admanBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/admanBidAdapter.js b/modules/admanBidAdapter.js index 2fd8c2e96f0..4720d06d094 100644 --- a/modules/admanBidAdapter.js +++ b/modules/admanBidAdapter.js @@ -17,7 +17,7 @@ export const spec = { const ENDPOINT_URL = '//bidtor.admanmedia.com/prebid'; const bids = validBidRequests.map(buildRequestObject); const payload = { - referrer: utils.getTopWindowUrl(), + referer: utils.getTopWindowUrl(), bids, deviceWidth: screen.width }; diff --git a/test/spec/modules/admanBidAdapter_spec.js b/test/spec/modules/admanBidAdapter_spec.js index 2af040103cc..37a097427d5 100644 --- a/test/spec/modules/admanBidAdapter_spec.js +++ b/test/spec/modules/admanBidAdapter_spec.js @@ -86,7 +86,7 @@ describe('admanBidAdapter', function() { expect(payload.gdpr).to.exist; expect(payload.bids).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); - expect(payload.referrer).to.exist; + expect(payload.referer).to.exist; const bid = payload.bids[0]; expect(bid).to.exist; From e07d2dc3d32a048a9190fe719d3a8f90cdb83235 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Mon, 15 Jul 2019 12:29:17 -0700 Subject: [PATCH 1341/1594] Fixing the issue introduced in #3845 for rubi analytics adapter (#3996) * Fixing the issue introduced in #3845 for rubi analytics adapter * using utils.deepClone instead of custom clone --- modules/rubiconAnalyticsAdapter.js | 10 ++-- .../modules/rubiconAnalyticsAdapter_spec.js | 35 +++++++++++- test/spec/modules/rubiconBidAdapter_spec.js | 56 +++++++++---------- 3 files changed, 65 insertions(+), 36 deletions(-) diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index 6c4e1b88d8b..a00c727d470 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -232,17 +232,17 @@ function sendMessage(auctionId, bidWonId) { ); } -function parseBidResponse(bid) { +export function parseBidResponse(bid) { return _pick(bid, [ - 'getCpmInNewCurrency as bidPriceUSD', (fn) => { + 'bidPriceUSD', () => { if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === 'USD') { return Number(bid.cpm); } // use currency conversion function if present - if (typeof fn === 'function') { - return Number(fn('USD')); + if (typeof bid.getCpmInNewCurrency === 'function') { + return Number(bid.getCpmInNewCurrency('USD')); } - // TODO: throw error or something if not USD and currency module wasn't present? + utils.logWarn('Rubicon Analytics Adapter: Could not determine the bidPriceUSD of the bid ', bid); }, 'dealId', 'status', diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index efb7a1725e7..c6b0ca8d29f 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -1,7 +1,12 @@ -import rubiconAnalyticsAdapter, { SEND_TIMEOUT } from 'modules/rubiconAnalyticsAdapter'; +import rubiconAnalyticsAdapter, { SEND_TIMEOUT, parseBidResponse } from 'modules/rubiconAnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import { config } from 'src/config'; +import { + setConfig, + addBidResponseHook, +} from 'modules/currency'; + let Ajv = require('ajv'); let schema = require('./rubiconAnalyticsSchema.json'); let ajv = new Ajv({ @@ -694,5 +699,33 @@ describe('rubicon analytics adapter', function () { expect(timedOutBid.error.code).to.equal('timeout-error'); expect(timedOutBid).to.not.have.property('bidResponse'); }); + + it('should successfully convert bid price to USD in parseBidResponse', function () { + // Set the rates + setConfig({ + adServerCurrency: 'JPY', + rates: { + USD: { + JPY: 100 + } + } + }); + + // set our bid response to JPY + const bidCopy = utils.deepClone(BID2); + bidCopy.currency = 'JPY'; + bidCopy.cpm = 100; + + // Now add the bidResponse hook which hooks on the currenct conversion function onto the bid response + let innerBid; + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bidCopy); + + // Use the rubi analytics parseBidResponse Function to get the resulting cpm from the bid response! + const bidResponseObj = parseBidResponse(innerBid); + expect(bidResponseObj).to.have.property('bidPriceUSD'); + expect(bidResponseObj.bidPriceUSD).to.equal(1.0); + }); }); }); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 67a92d4a26e..0ad20001536 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -470,7 +470,7 @@ describe('the rubicon adapter', function () { }); it('should use rubicon sizes if present (including non-mappable sizes)', function () { - var sizesBidderRequest = clone(bidderRequest); + var sizesBidderRequest = utils.deepClone(bidderRequest); sizesBidderRequest.bids[0].params.sizes = [55, 57, 59, 801]; let [request] = spec.buildRequests(sizesBidderRequest.bids, sizesBidderRequest); @@ -481,7 +481,7 @@ describe('the rubicon adapter', function () { }); it('should not validate bid request if no valid sizes', function () { - var sizesBidderRequest = clone(bidderRequest); + var sizesBidderRequest = utils.deepClone(bidderRequest); sizesBidderRequest.bids[0].sizes = [[621, 250], [300, 251]]; let result = spec.isBidRequestValid(sizesBidderRequest.bids[0]); @@ -490,7 +490,7 @@ describe('the rubicon adapter', function () { }); it('should not validate bid request if no account id is present', function () { - var noAccountBidderRequest = clone(bidderRequest); + var noAccountBidderRequest = utils.deepClone(bidderRequest); delete noAccountBidderRequest.bids[0].params.accountId; let result = spec.isBidRequestValid(noAccountBidderRequest.bids[0]); @@ -499,7 +499,7 @@ describe('the rubicon adapter', function () { }); it('should allow a floor override', function () { - var floorBidderRequest = clone(bidderRequest); + var floorBidderRequest = utils.deepClone(bidderRequest); floorBidderRequest.bids[0].params.floor = 2; let [request] = spec.buildRequests(floorBidderRequest.bids, floorBidderRequest); @@ -876,17 +876,17 @@ describe('the rubicon adapter', function () { 'rf': 'localhost' }; - const bidCopy = clone(bidderRequest.bids[0]); + const bidCopy = utils.deepClone(bidderRequest.bids[0]); bidCopy.params.siteId = '70608'; bidCopy.params.zoneId = '1111'; bidderRequest.bids.push(bidCopy); - const bidCopy2 = clone(bidderRequest.bids[0]); + const bidCopy2 = utils.deepClone(bidderRequest.bids[0]); bidCopy2.params.siteId = '99999'; bidCopy2.params.zoneId = '2222'; bidderRequest.bids.push(bidCopy2); - const bidCopy3 = clone(bidderRequest.bids[0]); + const bidCopy3 = utils.deepClone(bidderRequest.bids[0]); bidCopy3.params.siteId = '99999'; bidCopy3.params.zoneId = '3333'; bidderRequest.bids.push(bidCopy3); @@ -970,7 +970,7 @@ describe('the rubicon adapter', function () { // TEST '10' BIDS, add 9 to 1 existing bid for (let i = 0; i < 9; i++) { - let bidCopy = clone(bidderRequest.bids[0]); + let bidCopy = utils.deepClone(bidderRequest.bids[0]); bidCopy.params.zoneId = `${i}0000`; bidderRequest.bids.push(bidCopy); } @@ -989,7 +989,7 @@ describe('the rubicon adapter', function () { // TEST '100' BIDS, add 90 to the previously added 10 for (let i = 0; i < 90; i++) { - let bidCopy = clone(bidderRequest.bids[0]); + let bidCopy = utils.deepClone(bidderRequest.bids[0]); bidCopy.params.zoneId = `${(i + 10)}0000`; bidderRequest.bids.push(bidCopy); } @@ -1013,14 +1013,14 @@ describe('the rubicon adapter', function () { return config[key]; }); - const bidCopy = clone(bidderRequest.bids[0]); + const bidCopy = utils.deepClone(bidderRequest.bids[0]); bidderRequest.bids.push(bidCopy); - const bidCopy2 = clone(bidderRequest.bids[0]); + const bidCopy2 = utils.deepClone(bidderRequest.bids[0]); bidCopy2.params.siteId = '32001'; bidderRequest.bids.push(bidCopy2); - const bidCopy3 = clone(bidderRequest.bids[0]); + const bidCopy3 = utils.deepClone(bidderRequest.bids[0]); bidCopy3.params.siteId = '32001'; bidderRequest.bids.push(bidCopy3); @@ -1036,18 +1036,18 @@ describe('the rubicon adapter', function () { return config[key]; }); - const bidCopy = clone(bidderRequest.bids[0]); + const bidCopy = utils.deepClone(bidderRequest.bids[0]); bidderRequest.bids.push(bidCopy); - const bidCopy2 = clone(bidderRequest.bids[0]); + const bidCopy2 = utils.deepClone(bidderRequest.bids[0]); bidCopy2.params.siteId = '32001'; bidderRequest.bids.push(bidCopy2); - const bidCopy3 = clone(bidderRequest.bids[0]); + const bidCopy3 = utils.deepClone(bidderRequest.bids[0]); bidCopy3.params.siteId = '32001'; bidderRequest.bids.push(bidCopy3); - const bidCopy4 = clone(bidderRequest.bids[0]); + const bidCopy4 = utils.deepClone(bidderRequest.bids[0]); bidCopy4.mediaTypes = { video: { context: 'instream', @@ -1080,7 +1080,7 @@ describe('the rubicon adapter', function () { describe('user id config', function() { it('should send tpid_tdid when userId defines tdid', function () { - const clonedBid = clone(bidderRequest.bids[0]); + const clonedBid = utils.deepClone(bidderRequest.bids[0]); clonedBid.userId = { tdid: 'abcd-efgh-ijkl-mnop-1234' }; @@ -1137,7 +1137,7 @@ describe('the rubicon adapter', function () { it('should send request with proper ad position', function () { createVideoBidderRequest(); - let positionBidderRequest = clone(bidderRequest); + let positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].mediaTypes.video.pos = 1; let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); expect(request.data.imp[0].video.pos).to.equal(1); @@ -1173,25 +1173,25 @@ describe('the rubicon adapter', function () { it('should send request with proper ad position when mediaTypes.video.pos is not defined', function () { createVideoBidderRequest(); - let positionBidderRequest = clone(bidderRequest); + let positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = undefined; positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); expect(request.data.imp[0].video.pos).to.equal(0); - positionBidderRequest = clone(bidderRequest); + positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = 'atf' positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); expect(request.data.imp[0].video.pos).to.equal(1); - positionBidderRequest = clone(bidderRequest); + positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = 'btf'; positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); expect(request.data.imp[0].video.pos).to.equal(3); - positionBidderRequest = clone(bidderRequest); + positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = 'foobar'; positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); @@ -1216,7 +1216,7 @@ describe('the rubicon adapter', function () { bidderRequest.auctionStart + 100 ); - const bidRequestCopy = clone(bidderRequest.bids[0]); + const bidRequestCopy = utils.deepClone(bidderRequest.bids[0]); expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(true); // change context to outstream, still true @@ -1302,7 +1302,7 @@ describe('the rubicon adapter', function () { bidderRequest.auctionStart + 100 ); - const bidRequestCopy = clone(bidderRequest); + const bidRequestCopy = utils.deepClone(bidderRequest); let [request] = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(true); @@ -1350,7 +1350,7 @@ describe('the rubicon adapter', function () { bidderRequest.auctionStart + 100 ); - const bidRequestCopy = clone(bidderRequest); + const bidRequestCopy = utils.deepClone(bidderRequest); let requests = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); expect(requests.length).to.equal(1); @@ -1801,7 +1801,7 @@ describe('the rubicon adapter', function () { }; let bids = spec.interpretResponse({ body: response }, { - bidRequest: [clone(bidderRequest.bids[0])] + bidRequest: [utils.deepClone(bidderRequest.bids[0])] }); expect(bids).to.be.lengthOf(1); @@ -2135,7 +2135,3 @@ describe('the rubicon adapter', function () { }); }); }); - -function clone(obj) { - return JSON.parse(JSON.stringify(obj)); -} From 6399ab1ab1c7215149389ac2a36ef4be6dce8826 Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 16 Jul 2019 18:05:27 +0530 Subject: [PATCH 1342/1594] update karma and webpack-stream packages (#3966) --- package-lock.json | 1569 +++++++++++++++++++++------------------------ package.json | 4 +- 2 files changed, 742 insertions(+), 831 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d224cebc76..d0bfdfee34e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.21.0-pre", + "version": "2.23.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -856,6 +856,194 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@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 + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -955,6 +1143,12 @@ "json-schema-traverse": "^0.3.0" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, "ajv-keywords": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", @@ -987,7 +1181,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "dev": true, + "optional": true }, "ansi-colors": { "version": "3.2.3", @@ -1076,6 +1271,12 @@ "default-require-extensions": "^1.0.0" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -3108,6 +3309,54 @@ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, + "cacache": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", + "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "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, + "requires": { + "yallist": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3345,6 +3594,21 @@ "upath": "^1.1.1" } }, + "chownr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", + "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3531,15 +3795,6 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3741,6 +3996,31 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -3950,6 +4230,12 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -3970,9 +4256,9 @@ } }, "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz", + "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==", "dev": true }, "date-now": { @@ -5597,40 +5883,6 @@ } } }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "dependencies": { - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } - } - } - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -5681,30 +5933,6 @@ } } }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - }, - "dependencies": { - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -5998,6 +6226,12 @@ "detect-libc": "^1.0.3" } }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -6017,12 +6251,6 @@ "object-assign": "^4.0.1" } }, - "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 - }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", @@ -6186,9 +6414,9 @@ } }, "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, "flush-write-stream": { @@ -6356,6 +6584,18 @@ "through2": "^2.0.3" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, "fs.extra": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", @@ -6401,7 +6641,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6422,12 +6663,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6442,17 +6685,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6569,7 +6815,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6581,6 +6828,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6595,6 +6843,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6602,12 +6851,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6626,6 +6877,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6706,7 +6958,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6718,6 +6971,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6803,7 +7057,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6839,6 +7094,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6858,6 +7114,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6901,12 +7158,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -7032,42 +7291,6 @@ "path-is-absolute": "^1.0.0" } }, - "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": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "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.0" - } - }, - "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": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -8492,6 +8715,12 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -8759,21 +8988,6 @@ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", "dev": true }, - "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-primitive": "^2.0.0" - } - }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -8869,18 +9083,6 @@ "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": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -9397,28 +9599,27 @@ "dev": true }, "karma": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz", + "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", + "braces": "^2.3.2", "chokidar": "^2.0.3", "colors": "^1.1.0", - "combine-lists": "^1.0.0", "connect": "^3.6.0", "core-js": "^2.2.0", "di": "^0.0.1", "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.5", - "log4js": "^3.0.0", + "lodash": "^4.17.11", + "log4js": "^4.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", @@ -10028,33 +10229,16 @@ } }, "log4js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.4.0.tgz", + "integrity": "sha512-xwRvmxFsq8Hb7YeS+XKfvCrsH114bXex6mIwJ2+KmYVi23pB3+hlzyGq1JPycSFTJWNLhD/7PCtM0RfPy6/2yg==", "dev": true, "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" - }, - "dependencies": { - "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.5" } }, "loglevelnext": { @@ -10163,6 +10347,12 @@ "kind-of": "^6.0.2" } }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -10246,12 +10436,6 @@ } } }, - "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", @@ -10633,6 +10817,24 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", @@ -10811,6 +11013,31 @@ } } }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11256,27 +11483,6 @@ "make-iterator": "^1.0.0" } }, - "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.4", - "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.1" - } - } - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -11485,6 +11691,17 @@ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -11677,35 +11894,6 @@ "ini": "^1.3.3" } }, - "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.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "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", @@ -11905,12 +12093,6 @@ "sha.js": "^2.4.8" } }, - "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 - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -12000,12 +12182,6 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12036,6 +12212,12 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12184,25 +12366,6 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "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.0", - "math-random": "^1.0.1" - }, - "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", @@ -12386,15 +12549,6 @@ "private": "^0.1.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", @@ -12825,6 +12979,15 @@ "is-promise": "^2.1.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -12947,6 +13110,12 @@ } } }, + "serialize-javascript": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", + "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -13573,6 +13742,15 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -13685,6 +13863,16 @@ "readable-stream": "^2.0.2" } }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, "stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", @@ -13711,17 +13899,27 @@ "dev": true }, "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.5.tgz", + "integrity": "sha512-iGVaMcyF5PcUY0cPbW3xFQUXnr9O4RZXNBBjhuLZgrjLO4XCLLGfx4T2sGqygSeylUjwgWRsnNbT9aV0Zb8AYw==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.11" }, "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -13730,6 +13928,26 @@ "requires": { "ms": "^2.1.1" } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } } } }, @@ -13941,6 +14159,102 @@ "through2": "^2.0.1" } }, + "terser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.0.2.tgz", + "integrity": "sha512-IWLuJqTvx97KP3uTYkFVn93cXO+EtlzJu8TdJylq+H0VBDlPMIfQA9MBS5Vc5t3xTEUG1q0hIfHMpAP2R+gWTw==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.10" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", + "dev": true, + "requires": { + "cacache": "^11.3.2", + "find-cache-dir": "^2.0.0", + "is-wsl": "^1.1.0", + "loader-utils": "^1.2.3", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1", + "terser": "^4.0.0", + "webpack-sources": "^1.3.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "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 + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14195,6 +14509,12 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14275,7 +14595,8 @@ "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 + "dev": true, + "optional": true }, "uglifyjs-webpack-plugin": { "version": "0.4.6", @@ -14458,6 +14779,24 @@ } } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", @@ -14528,6 +14867,12 @@ "unist-util-is": "^3.0.0" } }, + "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 + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -15437,46 +15782,19 @@ } } }, - "webpack-core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", - "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", + "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": { - "source-list-map": "~0.1.7", - "source-map": "~0.4.1" - }, - "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": ">=0.0.4" - } - } - } - }, - "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": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "url-join": "^2.0.2", + "webpack-log": "^1.0.1" }, "dependencies": { "mime": { @@ -15518,548 +15836,132 @@ } }, "webpack-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", - "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-5.2.1.tgz", + "integrity": "sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==", "dev": true, "requires": { - "gulp-util": "^3.0.7", + "fancy-log": "^1.3.3", "lodash.clone": "^4.3.2", "lodash.some": "^4.2.2", - "memory-fs": "^0.3.0", + "memory-fs": "^0.4.1", + "plugin-error": "^1.0.1", + "supports-color": "^5.5.0", "through": "^2.3.8", - "vinyl": "^1.1.0", - "webpack": "^1.12.9" + "vinyl": "^2.1.0", + "webpack": "^4.26.1" }, "dependencies": { "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", + "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", "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.1.5", - "normalize-path": "^2.0.0" - } - }, - "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.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "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 - }, - "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.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "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.1" - } - }, - "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.0" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", "dev": true }, - "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.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "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=", + "ajv-keywords": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "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" - } - }, "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "memory-fs": "^0.2.0", - "tapable": "^0.1.8" - }, - "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.0" - } - }, - "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.1.0" - } - }, - "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" + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" } }, - "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==", + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "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.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "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-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": { + "fast-deep-equal": { "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" - } - }, - "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" - } - }, - "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" - } - }, - "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.5" - } - }, - "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.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.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.3", - "readable-stream": "^2.0.1" - } - }, - "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.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "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.1.1", - "browserify-zlib": "^0.1.4", - "buffer": "^4.9.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "3.3.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "0.0.1", - "os-browserify": "^0.2.0", - "path-browserify": "0.0.0", - "process": "^0.11.0", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.0.5", - "stream-browserify": "^2.0.1", - "stream-http": "^2.3.1", - "string_decoder": "^0.10.25", - "timers-browserify": "^2.0.2", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - } - }, - "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" - } - }, - "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 - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "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=", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "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 }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "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": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "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 - } - } - }, - "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" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "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": { - "indexof": "0.0.1" - } - }, - "watchpack": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", - "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", - "dev": true, - "requires": { - "async": "^0.9.0", - "chokidar": "^1.0.0", - "graceful-fs": "^4.1.2" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "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.0.0", - "async": "^1.3.0", - "clone": "^1.0.2", - "enhanced-resolve": "~0.9.0", - "interpret": "^0.6.4", - "loader-utils": "^0.2.11", - "memory-fs": "~0.3.0", + "version": "4.35.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.35.2.tgz", + "integrity": "sha512-TZAmorNymV4q66gAM/h90cEjG+N3627Q2MnkSgKlX/z3DlNVKUtqy57lz1WmZU2+FUZwzM+qm7cGaO95PyrX5A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.0.5", + "acorn-dynamic-import": "^4.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", "mkdirp": "~0.5.0", - "node-libs-browser": "^0.7.0", - "optimist": "~0.6.0", - "supports-color": "^3.1.0", - "tapable": "~0.1.8", - "uglify-js": "~2.7.3", - "watchpack": "^0.2.1", - "webpack-core": "~0.6.9" - } - }, - "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.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^1.0.0", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" } } } @@ -16123,6 +16025,15 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index 5ca8c03783d..deafd23c1b7 100755 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", - "karma": "^3.1.3", + "karma": "^4.1.0", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", @@ -91,7 +91,7 @@ "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-bundle-analyzer": "^3.3.2", - "webpack-stream": "^3.2.0", + "webpack-stream": "^5.2.1", "yargs": "^1.3.1" }, "dependencies": { From f6b7a9084d1ff8a14b1bf849feb9fa2515d9f41f Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 16 Jul 2019 13:46:37 -0400 Subject: [PATCH 1343/1594] Revert "update karma and webpack-stream packages (#3966)" (#4003) This reverts commit 6399ab1ab1c7215149389ac2a36ef4be6dce8826. --- package-lock.json | 1567 ++++++++++++++++++++++++--------------------- package.json | 4 +- 2 files changed, 830 insertions(+), 741 deletions(-) diff --git a/package-lock.json b/package-lock.json index d0bfdfee34e..1d224cebc76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.23.0-pre", + "version": "2.21.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -856,194 +856,6 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@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 - }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1143,12 +955,6 @@ "json-schema-traverse": "^0.3.0" } }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, "ajv-keywords": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", @@ -1181,8 +987,7 @@ "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": "3.2.3", @@ -1271,12 +1076,6 @@ "default-require-extensions": "^1.0.0" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -3309,54 +3108,6 @@ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, - "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - }, - "dependencies": { - "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, - "requires": { - "yallist": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3594,21 +3345,6 @@ "upath": "^1.1.1" } }, - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3795,6 +3531,15 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true, + "requires": { + "lodash": "^4.5.0" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3996,31 +3741,6 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -4230,12 +3950,6 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -4256,9 +3970,9 @@ } }, "date-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz", - "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, "date-now": { @@ -5883,6 +5597,40 @@ } } }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } + } + } + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -5933,6 +5681,30 @@ } } }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + }, + "dependencies": { + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -6226,12 +5998,6 @@ "detect-libc": "^1.0.3" } }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", - "dev": true - }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -6251,6 +6017,12 @@ "object-assign": "^4.0.1" } }, + "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 + }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", @@ -6414,9 +6186,9 @@ } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { @@ -6584,18 +6356,6 @@ "through2": "^2.0.3" } }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, "fs.extra": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", @@ -6641,8 +6401,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6663,14 +6422,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6685,20 +6442,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6815,8 +6569,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6828,7 +6581,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6843,7 +6595,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6851,14 +6602,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6877,7 +6626,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6958,8 +6706,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6971,7 +6718,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7057,8 +6803,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7094,7 +6839,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7114,7 +6858,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7158,14 +6901,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -7291,6 +7032,42 @@ "path-is-absolute": "^1.0.0" } }, + "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": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "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.0" + } + }, + "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": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -8715,12 +8492,6 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -8988,6 +8759,21 @@ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", "dev": true }, + "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-primitive": "^2.0.0" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -9083,9 +8869,21 @@ "isobject": "^3.0.1" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "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": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, @@ -9599,27 +9397,28 @@ "dev": true }, "karma": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz", - "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", - "braces": "^2.3.2", "chokidar": "^2.0.3", "colors": "^1.1.0", + "combine-lists": "^1.0.0", "connect": "^3.6.0", "core-js": "^2.2.0", "di": "^0.0.1", "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.11", - "log4js": "^4.0.0", + "lodash": "^4.17.5", + "log4js": "^3.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", @@ -10229,16 +10028,33 @@ } }, "log4js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.4.0.tgz", - "integrity": "sha512-xwRvmxFsq8Hb7YeS+XKfvCrsH114bXex6mIwJ2+KmYVi23pB3+hlzyGq1JPycSFTJWNLhD/7PCtM0RfPy6/2yg==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { - "date-format": "^2.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.0", - "rfdc": "^1.1.4", - "streamroller": "^1.0.5" + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", + "streamroller": "0.7.0" + }, + "dependencies": { + "circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, "loglevelnext": { @@ -10347,12 +10163,6 @@ "kind-of": "^6.0.2" } }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", - "dev": true - }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -10436,6 +10246,12 @@ } } }, + "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", @@ -10817,24 +10633,6 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", @@ -11013,31 +10811,6 @@ } } }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11483,6 +11256,27 @@ "make-iterator": "^1.0.0" } }, + "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.4", + "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.1" + } + } + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -11691,17 +11485,6 @@ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -11894,6 +11677,35 @@ "ini": "^1.3.3" } }, + "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.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "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", @@ -12093,6 +11905,12 @@ "sha.js": "^2.4.8" } }, + "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 + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -12182,6 +12000,12 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12212,12 +12036,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12366,6 +12184,25 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "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.0", + "math-random": "^1.0.1" + }, + "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", @@ -12549,6 +12386,15 @@ "private": "^0.1.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", @@ -12979,15 +12825,6 @@ "is-promise": "^2.1.0" } }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -13110,12 +12947,6 @@ } } }, - "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", - "dev": true - }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -13742,15 +13573,6 @@ "tweetnacl": "~0.14.0" } }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -13863,16 +13685,6 @@ "readable-stream": "^2.0.2" } }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, "stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", @@ -13899,27 +13711,17 @@ "dev": true }, "streamroller": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.5.tgz", - "integrity": "sha512-iGVaMcyF5PcUY0cPbW3xFQUXnr9O4RZXNBBjhuLZgrjLO4XCLLGfx4T2sGqygSeylUjwgWRsnNbT9aV0Zb8AYw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, "requires": { - "async": "^2.6.2", - "date-format": "^2.0.0", - "debug": "^3.2.6", - "fs-extra": "^7.0.1", - "lodash": "^4.17.11" + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" }, "dependencies": { - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -13928,26 +13730,6 @@ "requires": { "ms": "^2.1.1" } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } } } }, @@ -14159,102 +13941,6 @@ "through2": "^2.0.1" } }, - "terser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.0.2.tgz", - "integrity": "sha512-IWLuJqTvx97KP3uTYkFVn93cXO+EtlzJu8TdJylq+H0VBDlPMIfQA9MBS5Vc5t3xTEUG1q0hIfHMpAP2R+gWTw==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.10" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "terser-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", - "dev": true, - "requires": { - "cacache": "^11.3.2", - "find-cache-dir": "^2.0.0", - "is-wsl": "^1.1.0", - "loader-utils": "^1.2.3", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", - "source-map": "^0.6.1", - "terser": "^4.0.0", - "webpack-sources": "^1.3.0", - "worker-farm": "^1.7.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "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 - } - } - }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14509,12 +14195,6 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14595,8 +14275,7 @@ "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, - "optional": true + "dev": true }, "uglifyjs-webpack-plugin": { "version": "0.4.6", @@ -14779,24 +14458,6 @@ } } }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", @@ -14867,12 +14528,6 @@ "unist-util-is": "^3.0.0" } }, - "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 - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -15782,15 +15437,42 @@ } } }, - "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==", + "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": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", + "source-list-map": "~0.1.7", + "source-map": "~0.4.1" + }, + "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": ">=0.0.4" + } + } + } + }, + "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": { + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", "path-is-absolute": "^1.0.0", "range-parser": "^1.0.3", "url-join": "^2.0.2", @@ -15836,132 +15518,548 @@ } }, "webpack-stream": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-5.2.1.tgz", - "integrity": "sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", "dev": true, "requires": { - "fancy-log": "^1.3.3", + "gulp-util": "^3.0.7", "lodash.clone": "^4.3.2", "lodash.some": "^4.2.2", - "memory-fs": "^0.4.1", - "plugin-error": "^1.0.1", - "supports-color": "^5.5.0", + "memory-fs": "^0.3.0", "through": "^2.3.8", - "vinyl": "^2.1.0", - "webpack": "^4.26.1" + "vinyl": "^1.1.0", + "webpack": "^1.12.9" }, "dependencies": { "acorn": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", - "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "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.1.5", + "normalize-path": "^2.0.0" + } + }, + "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.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, - "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "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 + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, - "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "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.1" + } + }, + "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.0" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "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.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "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.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "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 + }, + "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" + } + }, "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "version": "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.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" + "memory-fs": "^0.2.0", + "tapable": "^0.1.8" + }, + "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 + } } }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "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": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "is-posix-bracket": "^0.1.0" } }, - "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=", + "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.1.0" + } + }, + "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": "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": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.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.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, - "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==", + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", "dev": true }, - "schema-utils": { + "interpret": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", + "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", + "dev": true + }, + "is-extglob": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "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" + } + }, + "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" + } + }, + "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" + } + }, + "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.5" + } + }, + "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.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.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.3", + "readable-stream": "^2.0.1" + } + }, + "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.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "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.1.1", + "browserify-zlib": "^0.1.4", + "buffer": "^4.9.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "0.0.1", + "os-browserify": "^0.2.0", + "path-browserify": "0.0.0", + "process": "^0.11.0", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.0.5", + "stream-browserify": "^2.0.1", + "stream-http": "^2.3.1", + "string_decoder": "^0.10.25", + "timers-browserify": "^2.0.2", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + } + }, + "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": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "remove-trailing-separator": "^1.0.1" + } + }, + "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 + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "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": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" } }, "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", "dev": true }, + "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": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "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 + } + } + }, + "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" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "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": { + "indexof": "0.0.1" + } + }, + "watchpack": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", + "dev": true, + "requires": { + "async": "^0.9.0", + "chokidar": "^1.0.0", + "graceful-fs": "^4.1.2" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, "webpack": { - "version": "4.35.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.35.2.tgz", - "integrity": "sha512-TZAmorNymV4q66gAM/h90cEjG+N3627Q2MnkSgKlX/z3DlNVKUtqy57lz1WmZU2+FUZwzM+qm7cGaO95PyrX5A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.0.5", - "acorn-dynamic-import": "^4.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", + "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.0.0", + "async": "^1.3.0", + "clone": "^1.0.2", + "enhanced-resolve": "~0.9.0", + "interpret": "^0.6.4", + "loader-utils": "^0.2.11", + "memory-fs": "~0.3.0", "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "node-libs-browser": "^0.7.0", + "optimist": "~0.6.0", + "supports-color": "^3.1.0", + "tapable": "~0.1.8", + "uglify-js": "~2.7.3", + "watchpack": "^0.2.1", + "webpack-core": "~0.6.9" + } + }, + "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.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" } } } @@ -16025,15 +16123,6 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index deafd23c1b7..5ca8c03783d 100755 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", - "karma": "^4.1.0", + "karma": "^3.1.3", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", @@ -91,7 +91,7 @@ "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-bundle-analyzer": "^3.3.2", - "webpack-stream": "^5.2.1", + "webpack-stream": "^3.2.0", "yargs": "^1.3.1" }, "dependencies": { From 08fd1a5cac9fc996ad463ff4887257ce9fa21dbb Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 16 Jul 2019 14:03:51 -0400 Subject: [PATCH 1344/1594] resize correct div (#3988) --- src/secureCreatives.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 8505923c493..f8ba9477b52 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -81,7 +81,7 @@ export function _sendAdToCreative(adObject, remoteDomain, source) { function resizeRemoteCreative({ adUnitCode, width, height }) { // resize both container div + iframe - ['div', 'iframe'].forEach(elmType => { + ['div:last-child', 'div:last-child iframe'].forEach(elmType => { let element = getElementByAdUnit(elmType); if (element) { let elementStyle = element.style; From 406d2a5d1eba36c3847ef543057f03942f8b4237 Mon Sep 17 00:00:00 2001 From: Ryan McNierney <45180751+rmcnierney@users.noreply.github.com> Date: Tue, 16 Jul 2019 14:07:53 -0400 Subject: [PATCH 1345/1594] Triplelift adapter tdid support (#3983) * Add user support in _buildPostBody * Add tdid check to test spec * Remove comments * Removing package-lock.json changes --- modules/tripleliftBidAdapter.js | 28 +++++++++++++++++-- .../spec/modules/tripleliftBidAdapter_spec.js | 10 +++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 748c5087201..ab6180cf45d 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -17,7 +17,7 @@ export const tripleliftAdapterSpec = { buildRequests: function(bidRequests, bidderRequest) { let tlCall = STR_ENDPOINT; - let data = _buildPostBody(bidRequests); + let data = _buildPostBody(bidRequests, bidderRequest); tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); @@ -78,7 +78,7 @@ export const tripleliftAdapterSpec = { } } -function _buildPostBody(bidRequests) { +function _buildPostBody(bidRequests, bidderRequest) { let data = {}; data.imp = bidRequests.map(function(bid, index) { return { @@ -91,6 +91,13 @@ function _buildPostBody(bidRequests) { } }); + let eids = handleConsortiaUserIds(bidderRequest) + if (eids.length > 0) { + data.user = { + ext: {eids} + } + } + return data; } @@ -108,6 +115,23 @@ function _isValidSize(size) { return (size.length === 2 && typeof size[0] === 'number' && typeof size[1] === 'number'); } +function handleConsortiaUserIds(bidderRequest) { + let eids = []; + if (bidderRequest.userId && bidderRequest.userId.tdid) { + eids.push({ + source: 'adserver.org', + uids: [{ + id: bidderRequest.userId.tdid, + ext: { + rtiPartner: 'TDID' + } + }] + }) + } + + return eids; +} + function _buildResponseObject(bidderRequest, bid) { let bidResponse = {}; let width = bid.width || 1; diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 171a97bafd9..dbae392f941 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -89,6 +89,9 @@ describe('triplelift adapter', function () { gdprConsent: { consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', gdprApplies: true + }, + userId: { + tdid: '6bca7f6b-a98a-46c0-be05-6020f7604598' } }; @@ -112,6 +115,13 @@ describe('triplelift adapter', function () { expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); }); + it('should add tdid to the payload if included', function () { + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); + const payload = request.data; + expect(payload).to.exist; + expect(payload.user).to.deep.equal({ext: {eids: [{source: 'adserver.org', uids: [{id: '6bca7f6b-a98a-46c0-be05-6020f7604598', ext: {rtiPartner: 'TDID'}}]}]}}); + }); + it('should return a query string for TL call', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const url = request.url; From 3623913cf2a66b4d524dcf1b4fca6205a884d00a Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Tue, 16 Jul 2019 14:17:28 -0400 Subject: [PATCH 1346/1594] adding tdid support (#3981) --- modules/kargoBidAdapter.js | 18 +++++++--- test/spec/modules/kargoBidAdapter_spec.js | 42 +++++++++++++++-------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 5c3d59bd241..63406bf3ce4 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -22,6 +22,10 @@ export const spec = { bidIds[bid.bidId] = bid.params.placementId; bidSizes[bid.bidId] = bid.sizes; }); + let tdid; + if (validBidRequests.length > 0 && validBidRequests[0].userId && validBidRequests[0].userId.tdid) { + tdid = validBidRequests[0].userId.tdid; + } const transformedParams = Object.assign({}, { sessionId: spec._getSessionId(), timeout: bidderRequest.timeout, @@ -35,7 +39,7 @@ export const spec = { bidIDs: bidIds, bidSizes: bidSizes, prebidRawBidRequests: validBidRequests - }, spec._getAllMetadata()); + }, spec._getAllMetadata(tdid)); const encodedParams = encodeURIComponent(JSON.stringify(transformedParams)); return Object.assign({}, bidderRequest, { method: 'GET', @@ -159,14 +163,18 @@ export const spec = { } }, - _getUserIds() { + _getUserIds(tdid) { const crb = spec._getCrb(); - return { + const userIds = { kargoID: crb.userId, clientID: crb.clientId, crbIDs: crb.syncIds || {}, optOut: crb.optOut }; + if (tdid) { + userIds.tdID = tdid; + } + return userIds; }, _getClientId() { @@ -174,9 +182,9 @@ export const spec = { return crb.clientId; }, - _getAllMetadata() { + _getAllMetadata(tdid) { return { - userIDs: spec._getUserIds(), + userIDs: spec._getUserIds(tdid), krux: spec._getKrux(), pageURL: window.location.href, rawCRB: spec._readCookie('krg_crb'), diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index a6779f518a0..92f68fd9b91 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -58,6 +58,9 @@ describe('kargo adapter tests', function () { placementId: 'foo' }, bidId: 1, + userId: { + tdid: 'fake-tdid' + }, sizes: [[320, 50], [300, 250], [300, 600]] }, { @@ -239,6 +242,7 @@ describe('kargo adapter tests', function () { userIDs: { kargoID: '5f108831-302d-11e7-bf6b-4595acd3bf6c', clientID: '2410d8f2-c111-4811-88a5-7b5e190e475f', + tdID: 'fake-tdid', crbIDs: { 2: '82fa2555-5969-4614-b4ce-4dcf1080e9f9', 16: 'VoxIk8AoJz0AAEdCeyAAAAC2&502', @@ -267,6 +271,9 @@ describe('kargo adapter tests', function () { params: { placementId: 'foo' }, + userId: { + tdid: 'fake-tdid' + }, sizes: [[320, 50], [300, 250], [300, 600]] }, { @@ -292,6 +299,7 @@ describe('kargo adapter tests', function () { base.userIDs = { crbIDs: {} }; + delete base.prebidRawBidRequests[0].userId.tdid; } if (excludeKrux) { @@ -304,8 +312,12 @@ describe('kargo adapter tests', function () { return base; } - function testBuildRequests(expected) { - var request = spec.buildRequests(bids, {timeout: 200, foo: 'bar'}); + function testBuildRequests(excludeTdid, expected) { + var clonedBids = JSON.parse(JSON.stringify(bids)); + if (excludeTdid) { + delete clonedBids[0].userId.tdid; + } + var request = spec.buildRequests(clonedBids, {timeout: 200, foo: 'bar'}); expected.sessionId = getSessionId(); sessionIds.push(expected.sessionId); var krakenParams = JSON.parse(decodeURIComponent(request.data.slice(5))); @@ -330,23 +342,23 @@ describe('kargo adapter tests', function () { initializeKruxUser(); initializeKruxSegments(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); + testBuildRequests(false, getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); }); it('works when all params and cookies are correctly set but no localstorage', function() { initializeKruxUser(); initializeKruxSegments(); initializeKrgCrb(true); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, null, getKrgCrbOldStyle())); + testBuildRequests(false, getExpectedKrakenParams(undefined, undefined, null, getKrgCrbOldStyle())); }); it('gracefully handles nothing being set', function() { - testBuildRequests(getExpectedKrakenParams(true, true, null, null)); + testBuildRequests(true, getExpectedKrakenParams(true, true, null, null)); }); it('gracefully handles browsers without localStorage', function() { simulateNoLocalStorage(); - testBuildRequests(getExpectedKrakenParams(true, true, null, null)); + testBuildRequests(true, getExpectedKrakenParams(true, true, null, null)); }); it('handles empty yet valid Kargo CRB', function() { @@ -354,49 +366,49 @@ describe('kargo adapter tests', function () { initializeKruxSegments(); initializeEmptyKrgCrb(); initializeEmptyKrgCrbCookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, getEmptyKrgCrb(), getEmptyKrgCrbOldStyle())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, getEmptyKrgCrb(), getEmptyKrgCrbOldStyle())); }); it('handles broken Kargo CRBs where base64 encoding is invalid', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType1(); - testBuildRequests(getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType1(), null)); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType1(), null)); }); it('handles broken Kargo CRBs where top level JSON is invalid on cookie', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType1Cookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType1())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType1())); }); it('handles broken Kargo CRBs where decoded JSON is invalid', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType2(); - testBuildRequests(getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType2(), null)); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType2(), null)); }); it('handles broken Kargo CRBs where inner base 64 is invalid on cookie', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType2Cookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType2OldStyle())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType2OldStyle())); }); it('handles broken Kargo CRBs where inner JSON is invalid on cookie', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType3Cookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType3OldStyle())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType3OldStyle())); }); it('handles broken Kargo CRBs where inner JSON is falsey', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType4Cookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType4OldStyle())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType4OldStyle())); }); it('handles a non-existant currency object on the config', function() { @@ -404,7 +416,7 @@ describe('kargo adapter tests', function () { initializeKruxUser(); initializeKruxSegments(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); + testBuildRequests(false, getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); }); it('handles no ad server currency being set on the currency object in the config', function() { @@ -412,7 +424,7 @@ describe('kargo adapter tests', function () { initializeKruxUser(); initializeKruxSegments(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); + testBuildRequests(false, getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); }); }); From 5a80bbf4a7b2b64a35d69bc27cb84f9938721140 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 16 Jul 2019 14:20:48 -0400 Subject: [PATCH 1347/1594] update PR_REVIEW with some docs notes (#3994) * update PR_REVIEW with some docs notes * adding note about COPPA change --- PR_REVIEW.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PR_REVIEW.md b/PR_REVIEW.md index d5799472377..4ad8b8ec372 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -14,6 +14,11 @@ For modules and core platform updates, the initial reviewer should request an ad - Review for obvious errors or bad coding practice / use best judgement here. - If the change is a new feature / change to core prebid.js - review the change with a Tech Lead on the project and make sure they agree with the nature of change. - If the change results in needing updates to docs (such as public API change, module interface etc), add a label for "needs docs" and inform the submitter they must submit a docs PR to update the appropriate area of Prebid.org **before the PR can merge**. Help them with finding where the docs are located on prebid.org if needed. + - Below are some examples of bidder specific updates that should require docs update (in their dev-docs/bidders/bidder.md file): + - Add support for GDPR consentManagement module > add `gdpr_supported: true` + - Add support for userId module > add `userId: pubCommon, digitrust, newProviderHere` + - Add support for video and/or native mediaTypes > add `media_types: video, native` + - Add support for COPPA > add `coppa_supported: true` - If all above is good, add a `LGTM` comment and request 1 additional core member to review. - Once there is 2 `LGTM` on the PR, merge to master - Ask the submitter to add a PR for documentation if applicable. From 50d779af3c0dd98cbf05baba09ea693d54cfd71f Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 16 Jul 2019 12:58:34 -0700 Subject: [PATCH 1348/1594] Kargo Adapter: fix extensible error (#3998) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * add '_sessionId' to the object literal for spec * removed error merge * replaced obj property with sibling variable * updated test for changes to sessionId --- modules/kargoBidAdapter.js | 9 ++++++--- test/spec/modules/kargoBidAdapter_spec.js | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 63406bf3ce4..74494ce66c9 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -5,6 +5,9 @@ const BIDDER_CODE = 'kargo'; const HOST = 'https://krk.kargo.com'; const SYNC = 'https://crb.kargo.com/api/v1/initsyncrnd/{UUID}?seed={SEED}&idx={INDEX}'; const SYNC_COUNT = 5; + +let sessionId; + export const spec = { code: BIDDER_CODE, isBidRequestValid: function(bid) { @@ -193,10 +196,10 @@ export const spec = { }, _getSessionId() { - if (!spec._sessionId) { - spec._sessionId = spec._generateRandomUuid(); + if (!sessionId) { + sessionId = spec._generateRandomUuid(); } - return spec._sessionId; + return sessionId; }, _generateRandomUuid() { diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 92f68fd9b91..7ff28a72c58 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -216,7 +216,7 @@ describe('kargo adapter tests', function () { } function getSessionId() { - return spec._sessionId; + return spec._getSessionId(); } function getExpectedKrakenParams(excludeUserIds, excludeKrux, expectedRawCRB, expectedRawCRBCookie) { From 66e45ea904c50c6f2c2fa9229244def03b9de471 Mon Sep 17 00:00:00 2001 From: Gaudeamus Date: Tue, 16 Jul 2019 23:19:16 +0300 Subject: [PATCH 1349/1594] Mgid Adapter: make placementId optional (#3992) --- modules/mgidBidAdapter.js | 16 +++-- test/spec/modules/mgidBidAdapter_spec.js | 86 +++++++++++++++++++++--- 2 files changed, 86 insertions(+), 16 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index c6744d28f45..c3f88106893 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -60,10 +60,10 @@ utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); export const spec = { - VERSION: '1.2', + VERSION: '1.3', code: BIDDER_CODE, supportedMediaTypes: [BANNER, NATIVE], - reId: /^[0-9]+$/, + 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, /** @@ -102,10 +102,10 @@ export const spec = { bannerOk = sizes[f].length === 2; } } - return utils.isPlainObject(bid.params) && !!bid.params.accountId && !!bid.params.placementId && - utils.isStr(bid.params.accountId) && utils.isStr(bid.params.placementId) && - bid.params.accountId.toString().match(spec.reId) > 0 && bid.params.placementId.toString().match(spec.reId) && - (bannerOk || nativeOk); + let acc = Number(bid.params.accountId); + let plcmt = Number(bid.params.placementId); + return (bannerOk || nativeOk) && utils.isPlainObject(bid.params) && !!bid.adUnitCode && utils.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. @@ -132,9 +132,11 @@ export const spec = { const secure = window.location.protocol === 'https:' ? 1 : 0; let imp = []; validBidRequests.forEach(bid => { + let tagid = utils.deepAccess(bid, 'params.placementId') || 0; + tagid = !tagid ? bid.adUnitCode : tagid + '/' + bid.adUnitCode; let impObj = { id: bid.bidId, - tagid: utils.deepAccess(bid, 'params.placementId'), + tagid, secure, }; const bidFloor = utils.deepAccess(bid, 'params.bidFloor') || utils.deepAccess(bid, 'params.bidfloor') || 0; diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index 2b1a0739537..2216122da18 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -33,6 +33,7 @@ describe('Mgid bid adapter', function () { describe('isBidRequestValid', function () { let bid = { + 'adUnitCode': 'div', 'bidder': 'mgid', 'params': { 'property': '10433394', @@ -62,6 +63,7 @@ describe('Mgid bid adapter', function () { 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]] @@ -71,6 +73,32 @@ describe('Mgid bid adapter', function () { 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; @@ -119,9 +147,10 @@ describe('Mgid bid adapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true when valid params are passed', function () { + 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: { @@ -185,6 +214,7 @@ describe('Mgid bid adapter', function () { 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: { @@ -281,13 +311,46 @@ describe('Mgid bid adapter', function () { }); describe('buildRequests', function () { + it('should return undefined if no validBidRequests passed', function () { + expect(spec.buildRequests([])).to.be.undefined; + }); + let abid = { + adUnitCode: 'div', bidder: 'mgid', params: { accountId: '1', placementId: '2', }, }; + it('should return proper request url', function () { + localStorage.setItem('mgMuidn', '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'); + localStorage.removeItem('mgMuidn') + }); + 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 = { @@ -309,13 +372,13 @@ describe('Mgid bid adapter', function () { 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'); + expect(data.imp[0].tagid).to.deep.equal('2/div'); expect(data.imp[0].banner).to.deep.equal({w: 300, h: 250, format: []}); 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 + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250,\"format\":[]}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250,\"format\":[]}}]}', }); }); it('should not return native imp if minimum asset list not requested', function () { @@ -357,13 +420,13 @@ describe('Mgid bid adapter', function () { 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'); + 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 + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"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}}]}}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"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 sponsoredBy', function () { @@ -392,13 +455,13 @@ describe('Mgid bid adapter', function () { 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'); + 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 + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"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}}]}}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"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 () { @@ -423,14 +486,14 @@ describe('Mgid bid adapter', function () { 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'); + 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}]}); 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 + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', }); }); }); @@ -565,6 +628,11 @@ describe('Mgid bid adapter', function () { }); }); + describe('getUserSyncs', function () { + it('should do nothing on getUserSyncs', function () { + spec.getUserSyncs() + }); + }); describe('on bidWon', function () { it('should replace nurl and burl for native', function () { const burl = 'burl&s=${' + 'AUCTION_PRICE}'; From 565e3c939bed9870144b3c94dfdd2a737b08efe9 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Wed, 17 Jul 2019 13:29:20 -0400 Subject: [PATCH 1350/1594] Google ad manager support for long-form video (#3787) * gam support * update gam module to use submodules pattern * Fix unit tests * bug fix: do not add bid if it is rejected and revert gulphelpers --- gulpHelpers.js | 1 - modules/.submodules.json | 3 +- modules/adpod.js | 163 ++++++++++-- modules/categoryTranslation.js | 2 +- modules/dfpAdServerVideo.js | 98 ++++++- modules/freeWheelAdserverVideo.js | 140 +--------- test/spec/modules/dfpAdServerVideo_spec.js | 246 +++++++++++++++++- .../modules/freeWheelAdserverVideo_spec.js | 34 ++- 8 files changed, 515 insertions(+), 172 deletions(-) diff --git a/gulpHelpers.js b/gulpHelpers.js index 04428133347..3814bd8f554 100644 --- a/gulpHelpers.js +++ b/gulpHelpers.js @@ -13,7 +13,6 @@ const BUILD_PATH = './build/dist'; const DEV_PATH = './build/dev'; const ANALYTICS_PATH = '../analytics'; - // get only subdirectories that contain package.json with 'main' property function isModuleDirectory(filePath) { try { diff --git a/modules/.submodules.json b/modules/.submodules.json index 097fe4b1f3b..c0e30037660 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -5,6 +5,7 @@ "criteortusIdSystem" ], "adpod": [ - "freeWheelAdserverVideo" + "freeWheelAdserverVideo", + "dfpAdServerVideo" ] } diff --git a/modules/adpod.js b/modules/adpod.js index 46671e9fb0a..c678c854dc1 100644 --- a/modules/adpod.js +++ b/modules/adpod.js @@ -22,6 +22,7 @@ import { config } from '../src/config'; import { ADPOD } from '../src/mediaTypes'; import Set from 'core-js/library/fn/set'; import find from 'core-js/library/fn/array/find'; +import { auctionManager } from '../src/auctionManager'; const from = require('core-js/library/fn/array/from'); @@ -215,21 +216,21 @@ export function callPrebidCacheHook(fn, auctionInstance, bidResponse, afterBidAd if (!adServerCatId && brandCategoryExclusion) { utils.logWarn('Detected a bid without meta.adServerCatId while setConfig({adpod.brandCategoryExclusion}) was enabled. This bid has been rejected:', bidResponse) afterBidAdded(); - } - - if (config.getConfig('adpod.deferCaching') === false) { - bidCacheRegistry.addBid(bidResponse); - attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); - - updateBidQueue(auctionInstance, bidResponse, afterBidAdded); } else { - // generate targeting keys for bid - bidCacheRegistry.setupInitialCacheKey(bidResponse); - attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); + if (config.getConfig('adpod.deferCaching') === false) { + bidCacheRegistry.addBid(bidResponse); + attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); - // add bid to auction - addBidToAuction(auctionInstance, bidResponse); - afterBidAdded(); + updateBidQueue(auctionInstance, bidResponse, afterBidAdded); + } else { + // generate targeting keys for bid + bidCacheRegistry.setupInitialCacheKey(bidResponse); + attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); + + // add bid to auction + addBidToAuction(auctionInstance, bidResponse); + afterBidAdded(); + } } } else { fn.call(this, auctionInstance, bidResponse, afterBidAdded, bidderRequest); @@ -393,6 +394,7 @@ function initAdpodHooks() { } initAdpodHooks() + /** * * @param {Array[Object]} bids list of 'winning' bids that need to be cached @@ -431,11 +433,142 @@ export function sortByPricePerSecond(a, b) { return 0; } +/** + * This function returns targeting keyvalue pairs for long-form adserver modules. Freewheel and GAM are currently supporting Prebid long-form + * @param {Object} options + * @param {Array[string]} codes + * @param {function} callback + * @returns targeting kvs for adUnitCodes + */ +export function getTargeting({codes, callback} = {}) { + if (!callback) { + utils.logError('No callback function was defined in the getTargeting call. Aborting getTargeting().'); + return; + } + codes = codes || []; + const adPodAdUnits = getAdPodAdUnits(codes); + const bidsReceived = auctionManager.getBidsReceived(); + const competiveExclusionEnabled = config.getConfig('adpod.brandCategoryExclusion'); + const deferCachingSetting = config.getConfig('adpod.deferCaching'); + const deferCachingEnabled = (typeof deferCachingSetting === 'boolean') ? deferCachingSetting : true; + + let bids = getBidsForAdpod(bidsReceived, adPodAdUnits); + bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids; + bids.sort(sortByPricePerSecond); + + let targeting = {}; + if (deferCachingEnabled === false) { + adPodAdUnits.forEach((adUnit) => { + let adPodTargeting = []; + let adPodDurationSeconds = utils.deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); + + bids + .filter((bid) => bid.adUnitCode === adUnit.code) + .forEach((bid, index, arr) => { + if (bid.video.durationBucket <= adPodDurationSeconds) { + adPodTargeting.push({ + [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] + }); + adPodDurationSeconds -= bid.video.durationBucket; + } + if (index === arr.length - 1 && adPodTargeting.length > 0) { + adPodTargeting.push({ + [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] + }); + } + }); + targeting[adUnit.code] = adPodTargeting; + }); + + callback(null, targeting); + } else { + let bidsToCache = []; + adPodAdUnits.forEach((adUnit) => { + let adPodDurationSeconds = utils.deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); + + bids + .filter((bid) => bid.adUnitCode === adUnit.code) + .forEach((bid) => { + if (bid.video.durationBucket <= adPodDurationSeconds) { + bidsToCache.push(bid); + adPodDurationSeconds -= bid.video.durationBucket; + } + }); + }); + + callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) { + if (error) { + callback(error, null); + } else { + let groupedBids = utils.groupBy(bidsSuccessfullyCached, 'adUnitCode'); + Object.keys(groupedBids).forEach((adUnitCode) => { + let adPodTargeting = []; + + groupedBids[adUnitCode].forEach((bid, index, arr) => { + adPodTargeting.push({ + [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] + }); + + if (index === arr.length - 1 && adPodTargeting.length > 0) { + adPodTargeting.push({ + [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] + }); + } + }); + targeting[adUnitCode] = adPodTargeting; + }); + + callback(null, targeting); + } + }); + } + return targeting; +} + +/** + * This function returns the adunit of mediaType adpod + * @param {Array} codes adUnitCodes + * @returns {Array[Object]} adunits of mediaType adpod + */ +function getAdPodAdUnits(codes) { + return auctionManager.getAdUnits() + .filter((adUnit) => utils.deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) + .filter((adUnit) => (codes.length > 0) ? codes.indexOf(adUnit.code) != -1 : true); +} + +/** + * This function removes bids of same category. It will be used when competitive exclusion is enabled. + * @param {Array[Object]} bidsReceived + * @returns {Array[Object]} unique category bids + */ +function getExclusiveBids(bidsReceived) { + let bids = bidsReceived + .map((bid) => Object.assign({}, bid, {[TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR]})); + bids = utils.groupBy(bids, TARGETING_KEY_PB_CAT_DUR); + let filteredBids = []; + Object.keys(bids).forEach((targetingKey) => { + bids[targetingKey].sort(utils.compareOn('responseTimestamp')); + filteredBids.push(bids[targetingKey][0]); + }); + return filteredBids; +} + +/** + * This function returns bids for adpod adunits + * @param {Array[Object]} bidsReceived + * @param {Array[Object]} adPodAdUnits + * @returns {Array[Object]} bids of mediaType adpod + */ +function getBidsForAdpod(bidsReceived, adPodAdUnits) { + let adUnitCodes = adPodAdUnits.map((adUnit) => adUnit.code); + return bidsReceived + .filter((bid) => adUnitCodes.indexOf(bid.adUnitCode) != -1 && (bid.video && bid.video.context === ADPOD)) +} + const sharedMethods = { TARGETING_KEY_PB_CAT_DUR: TARGETING_KEY_PB_CAT_DUR, TARGETING_KEY_CACHE_ID: TARGETING_KEY_CACHE_ID, - 'sortByPricePerSecond': sortByPricePerSecond, - 'callPrebidCacheAfterAuction': callPrebidCacheAfterAuction + 'getTargeting': getTargeting } Object.freeze(sharedMethods); diff --git a/modules/categoryTranslation.js b/modules/categoryTranslation.js index f4d0a281f57..091b16c8211 100644 --- a/modules/categoryTranslation.js +++ b/modules/categoryTranslation.js @@ -26,8 +26,8 @@ export const registerAdserver = hook('async', function(adServer) { let url; if (adServer === 'freewheel') { url = DEFAULT_TRANSLATION_FILE_URL; + initTranslation(url, DEFAULT_IAB_TO_FW_MAPPING_KEY); } - initTranslation(url, DEFAULT_IAB_TO_FW_MAPPING_KEY); }, 'registerAdserver'); registerAdserver(); diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 79c11c5c886..1614dbe6b0d 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -7,6 +7,8 @@ import { targeting } from '../src/targeting'; import { formatQS, format as buildUrl, parse } from '../src/url'; import { deepAccess, isEmpty, logError, parseSizesInput } from '../src/utils'; import { config } from '../src/config'; +import { getHook, submodule } from '../src/hook'; +import { auctionManager } from '../src/auctionManager'; /** * @typedef {Object} DfpVideoParams @@ -45,6 +47,8 @@ const defaultParamConstants = { unviewed_position_start: 1, }; +export const adpodUtils = {}; + /** * Merge all the bid data and publisher-supplied options into a single URL, and then return it. * @@ -56,7 +60,7 @@ const defaultParamConstants = { * (or the auction's winning bid for this adUnit, if undefined) compete alongside the rest of the * demand in DFP. */ -export default function buildDfpVideoUrl(options) { +export function buildDfpVideoUrl(options) { if (!options.params && !options.url) { logError(`A params object or a url is required to use $$PREBID_GLOBAL$$.adServers.dfp.buildVideoUrl`); return; @@ -103,6 +107,92 @@ export default function buildDfpVideoUrl(options) { }); } +export function notifyTranslationModule(fn) { + fn.call(this, 'dfp'); +} + +getHook('registerAdserver').before(notifyTranslationModule); + +/** + * @typedef {Object} DfpAdpodOptions + * + * @param {string} code Ad Unit code + * @param {Object} params Query params which should be set on the DFP request. + * These will override this module's defaults whenever they conflict. + * @param {function} callback Callback function to execute when master tag is ready + */ + +/** + * Creates master tag url for long-form + * @param {DfpAdpodOptions} options + * @returns {string} A URL which calls DFP with custom adpod targeting key values to compete with rest of the demand in DFP + */ +export function buildAdpodVideoUrl({code, params, callback} = {}) { + if (!params || !callback) { + logError(`A params object and a callback is required to use pbjs.adServers.dfp.buildAdpodVideoUrl`); + return; + } + + const derivedParams = { + correlator: Date.now(), + sz: getSizeForAdUnit(code), + url: encodeURIComponent(location.href), + }; + + function getSizeForAdUnit(code) { + let adUnit = auctionManager.getAdUnits() + .filter((adUnit) => adUnit.code === code) + let sizes = deepAccess(adUnit[0], 'mediaTypes.video.playerSize'); + return parseSizesInput(sizes).join('|'); + } + + adpodUtils.getTargeting({ + 'codes': [code], + 'callback': createMasterTag + }); + + function createMasterTag(err, targeting) { + if (err) { + callback(err, null); + return; + } + + let initialValue = { + [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: undefined, + [adpodUtils.TARGETING_KEY_CACHE_ID]: undefined + } + let customParams; + if (targeting[code]) { + customParams = targeting[code].reduce((acc, curValue) => { + if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_PB_CAT_DUR) { + acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] = (typeof acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] !== 'undefined') ? acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] + ',' + curValue[adpodUtils.TARGETING_KEY_PB_CAT_DUR] : curValue[adpodUtils.TARGETING_KEY_PB_CAT_DUR]; + } else if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_CACHE_ID) { + acc[adpodUtils.TARGETING_KEY_CACHE_ID] = curValue[adpodUtils.TARGETING_KEY_CACHE_ID] + } + return acc; + }, initialValue); + } + + let encodedCustomParams = encodeURIComponent(formatQS(customParams)); + + const queryParams = Object.assign({}, + defaultParamConstants, + derivedParams, + params, + { cust_params: encodedCustomParams } + ); + + const masterTag = buildUrl({ + protocol: 'https', + host: 'pubads.g.doubleclick.net', + pathname: '/gampad/ads', + search: queryParams + }); + + callback(null, masterTag); + } +} + /** * Builds a video url from a base dfp video url and a winning bid, appending * Prebid-specific key-values. @@ -170,5 +260,9 @@ function getCustParams(bid, options) { } registerVideoSupport('dfp', { - buildVideoUrl: buildDfpVideoUrl + buildVideoUrl: buildDfpVideoUrl, + buildAdpodVideoUrl: buildAdpodVideoUrl, + getAdpodTargeting: (args) => adpodUtils.getTargeting(args) }); + +submodule('adpod', adpodUtils); diff --git a/modules/freeWheelAdserverVideo.js b/modules/freeWheelAdserverVideo.js index a93e5ab9159..03217b1165d 100644 --- a/modules/freeWheelAdserverVideo.js +++ b/modules/freeWheelAdserverVideo.js @@ -3,153 +3,17 @@ */ import { registerVideoSupport } from '../src/adServerManager'; -import { auctionManager } from '../src/auctionManager'; -import { groupBy, deepAccess, logError, compareOn } from '../src/utils'; -import { config } from '../src/config'; -import { ADPOD } from '../src/mediaTypes'; import { getHook, submodule } from '../src/hook'; +export const adpodUtils = {}; export function notifyTranslationModule(fn) { fn.call(this, 'freewheel'); } getHook('registerAdserver').before(notifyTranslationModule); -/** - * This function returns targeting keyvalue pairs for freewheel adserver module - * @param {Object} options - * @param {Array[string]} codes - * @param {function} callback - * @returns targeting kvs for adUnitCodes - */ -export function getTargeting({codes, callback} = {}) { - if (!callback) { - logError('No callback function was defined in the getTargeting call. Aborting getTargeting().'); - return; - } - codes = codes || []; - const adPodAdUnits = getAdPodAdUnits(codes); - const bidsReceived = auctionManager.getBidsReceived(); - const competiveExclusionEnabled = config.getConfig('adpod.brandCategoryExclusion'); - const deferCachingSetting = config.getConfig('adpod.deferCaching'); - const deferCachingEnabled = (typeof deferCachingSetting === 'boolean') ? deferCachingSetting : true; - - let bids = getBidsForAdpod(bidsReceived, adPodAdUnits); - bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids; - bids.sort(adpodUtils.sortByPricePerSecond); - - let targeting = {}; - if (deferCachingEnabled === false) { - adPodAdUnits.forEach((adUnit) => { - let adPodTargeting = []; - let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); - - bids - .filter((bid) => bid.adUnitCode === adUnit.code) - .forEach((bid, index, arr) => { - if (bid.video.durationBucket <= adPodDurationSeconds) { - adPodTargeting.push({ - [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR] - }); - adPodDurationSeconds -= bid.video.durationBucket; - } - if (index === arr.length - 1 && adPodTargeting.length > 0) { - adPodTargeting.push({ - [adpodUtils.TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_CACHE_ID] - }); - } - }); - targeting[adUnit.code] = adPodTargeting; - }); - - callback(null, targeting); - } else { - let bidsToCache = []; - adPodAdUnits.forEach((adUnit) => { - let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); - - bids - .filter((bid) => bid.adUnitCode === adUnit.code) - .forEach((bid) => { - if (bid.video.durationBucket <= adPodDurationSeconds) { - bidsToCache.push(bid); - adPodDurationSeconds -= bid.video.durationBucket; - } - }); - }); - - adpodUtils.callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) { - if (error) { - callback(error, null); - } else { - let groupedBids = groupBy(bidsSuccessfullyCached, 'adUnitCode'); - Object.keys(groupedBids).forEach((adUnitCode) => { - let adPodTargeting = []; - - groupedBids[adUnitCode].forEach((bid, index, arr) => { - adPodTargeting.push({ - [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR] - }); - - if (index === arr.length - 1 && adPodTargeting.length > 0) { - adPodTargeting.push({ - [adpodUtils.TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_CACHE_ID] - }); - } - }); - targeting[adUnitCode] = adPodTargeting; - }); - - callback(null, targeting); - } - }); - } - return targeting; -} - -/** - * This function returns the adunit of mediaType adpod - * @param {Array} codes adUnitCodes - * @returns {Array[Object]} adunits of mediaType adpod - */ -function getAdPodAdUnits(codes) { - return auctionManager.getAdUnits() - .filter((adUnit) => deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) - .filter((adUnit) => (codes.length > 0) ? codes.indexOf(adUnit.code) != -1 : true); -} - -/** - * This function removes bids of same freewheel category. It will be used when competitive exclusion is enabled. - * @param {Array[Object]} bidsReceived - * @returns {Array[Object]} unique freewheel category bids - */ -function getExclusiveBids(bidsReceived) { - let bids = bidsReceived - .map((bid) => Object.assign({}, bid, {[adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR]})); - bids = groupBy(bids, adpodUtils.TARGETING_KEY_PB_CAT_DUR); - let filteredBids = []; - Object.keys(bids).forEach((targetingKey) => { - bids[targetingKey].sort(compareOn('responseTimestamp')); - filteredBids.push(bids[targetingKey][0]); - }); - return filteredBids; -} - -/** - * This function returns bids for adpod adunits - * @param {Array[Object]} bidsReceived - * @param {Array[Object]} adPodAdUnits - * @returns {Array[Object]} bids of mediaType adpod - */ -function getBidsForAdpod(bidsReceived, adPodAdUnits) { - let adUnitCodes = adPodAdUnits.map((adUnit) => adUnit.code); - return bidsReceived - .filter((bid) => adUnitCodes.indexOf(bid.adUnitCode) != -1 && (bid.video && bid.video.context === ADPOD)) -} - registerVideoSupport('freewheel', { - getTargeting: getTargeting + getTargeting: (args) => adpodUtils.getTargeting(args) }); -export const adpodUtils = {}; submodule('adpod', adpodUtils); diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 30cf91c2e17..62b0a752f50 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -1,12 +1,14 @@ import { expect } from 'chai'; import parse from 'url-parse'; -import buildDfpVideoUrl from 'modules/dfpAdServerVideo'; +import { buildDfpVideoUrl, buildAdpodVideoUrl } from 'modules/dfpAdServerVideo'; import { parseQS } from 'src/url'; import adUnit from 'test/fixtures/video/adUnit'; import * as utils from 'src/utils'; import { config } from 'src/config'; import { targeting } from 'src/targeting'; +import { auctionManager } from 'src/auctionManager'; +import * as adpod from 'modules/adpod'; const bid = { videoCacheKey: 'abc', @@ -296,4 +298,246 @@ describe('The DFP video support module', function () { expect(customParams).to.have.property('hb_uuid', 'def'); expect(customParams).to.have.property('hb_cache_id', 'def'); }); + + describe('adpod unit tests', function () { + let amStub; + let amGetAdUnitsStub; + let xhr; + let requests; + + before(function () { + let adUnits = [{ + code: 'adUnitCode-1', + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480], + adPodDurationSec: 60, + durationRangeSec: [15, 30], + requireExactDuration: true + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 14542875, + } + } + ] + }]; + + amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits'); + amGetAdUnitsStub.returns(adUnits); + amStub = sinon.stub(auctionManager, 'getBidsReceived'); + }); + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + + config.setConfig({ + adpod: { + brandCategoryExclusion: true, + deferCaching: false + } + }); + }) + + afterEach(function() { + config.resetConfig(); + xhr.restore(); + }); + + after(function () { + amGetAdUnitsStub.restore(); + amStub.restore(); + }); + + it('should return masterTag url', function() { + amStub.returns(getBidsReceived()); + let url; + parse(buildAdpodVideoUrl({ + code: 'adUnitCode-1', + callback: handleResponse, + params: { + 'iu': 'my/adUnit', + 'description_url': 'someUrl.com', + } + })); + + function handleResponse(err, masterTag) { + if (err) { + return; + } + url = parse(masterTag); + + expect(url.protocol).to.equal('https:'); + expect(url.host).to.equal('pubads.g.doubleclick.net'); + + const queryParams = parseQS(url.query); + expect(queryParams).to.have.property('correlator'); + expect(queryParams).to.have.property('description_url', 'someUrl.com'); + expect(queryParams).to.have.property('env', 'vp'); + expect(queryParams).to.have.property('gdfp_req', '1'); + expect(queryParams).to.have.property('iu', 'my/adUnit'); + expect(queryParams).to.have.property('output', 'xml_vast3'); + expect(queryParams).to.have.property('sz', '640x480'); + expect(queryParams).to.have.property('unviewed_position_start', '1'); + expect(queryParams).to.have.property('url'); + expect(queryParams).to.have.property('cust_params'); + + const custParams = parseQS(decodeURIComponent(queryParams.cust_params)); + expect(custParams).to.have.property('hb_cache_id', '123'); + expect(custParams).to.have.property('hb_pb_cat_dur', '15.00_395_15s,15.00_406_30s,10.00_395_15s'); + } + }); + + it('should return masterTag url with correct custom params when brandCategoryExclusion is false', function() { + config.setConfig({ + adpod: { + brandCategoryExclusion: false, + } + }); + function getBids() { + let bids = [ + createBid(10, 'adUnitCode-1', 15, '10.00_15s', '123', '395'), + createBid(15, 'adUnitCode-1', 15, '15.00_15s', '123', '395'), + createBid(25, 'adUnitCode-1', 30, '15.00_30s', '123', '406'), + ]; + bids.forEach((bid) => { + delete bid.meta; + }); + return bids; + } + amStub.returns(getBids()); + let url; + parse(buildAdpodVideoUrl({ + code: 'adUnitCode-1', + callback: handleResponse, + params: { + 'iu': 'my/adUnit', + 'description_url': 'someUrl.com', + } + })); + + function handleResponse(err, masterTag) { + if (err) { + return; + } + url = parse(masterTag); + expect(url.protocol).to.equal('https:'); + expect(url.host).to.equal('pubads.g.doubleclick.net'); + + const queryParams = parseQS(url.query); + expect(queryParams).to.have.property('correlator'); + expect(queryParams).to.have.property('description_url', 'someUrl.com'); + expect(queryParams).to.have.property('env', 'vp'); + expect(queryParams).to.have.property('gdfp_req', '1'); + expect(queryParams).to.have.property('iu', 'my/adUnit'); + expect(queryParams).to.have.property('output', 'xml_vast3'); + expect(queryParams).to.have.property('sz', '640x480'); + expect(queryParams).to.have.property('unviewed_position_start', '1'); + expect(queryParams).to.have.property('url'); + expect(queryParams).to.have.property('cust_params'); + + const custParams = parseQS(decodeURIComponent(queryParams.cust_params)); + expect(custParams).to.have.property('hb_cache_id', '123'); + expect(custParams).to.have.property('hb_pb_cat_dur', '10.00_15s,15.00_15s,15.00_30s'); + } + }); + + it('should handle error when cache fails', function() { + config.setConfig({ + adpod: { + brandCategoryExclusion: true, + deferCaching: true + } + }); + amStub.returns(getBidsReceived()); + + parse(buildAdpodVideoUrl({ + code: 'adUnitCode-1', + callback: handleResponse, + params: { + 'iu': 'my/adUnit', + 'description_url': 'someUrl.com', + } + })); + + requests[0].respond(503, { + 'Content-Type': 'plain/text', + }, 'The server could not save anything at the moment.'); + + function handleResponse(err, masterTag) { + expect(masterTag).to.be.null; + expect(err).to.be.an('error'); + } + }); + }) }); + +function getBidsReceived() { + return [ + createBid(10, 'adUnitCode-1', 15, '10.00_395_15s', '123', '395'), + createBid(15, 'adUnitCode-1', 15, '15.00_395_15s', '123', '395'), + createBid(25, 'adUnitCode-1', 30, '15.00_406_30s', '123', '406'), + ] +} + +function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, label) { + return { + 'bidderCode': 'appnexus', + 'width': 640, + 'height': 360, + 'statusMessage': 'Bid available', + 'adId': '28f24ced14586c', + 'mediaType': 'video', + 'source': 'client', + 'requestId': '28f24ced14586c', + 'cpm': cpm, + 'creativeId': 97517771, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 3600, + 'adUnitCode': adUnitCode, + 'video': { + 'context': 'adpod', + 'durationBucket': durationBucket + }, + 'appnexus': { + 'buyerMemberId': 9325 + }, + 'vastUrl': 'http://some-vast-url.com', + 'vastImpUrl': 'http://some-vast-imp-url.com', + 'auctionId': 'ec266b31-d652-49c5-8295-e83fafe5532b', + 'responseTimestamp': 1548442460888, + 'requestTimestamp': 1548442460827, + 'bidder': 'appnexus', + 'timeToRespond': 61, + 'pbLg': '5.00', + 'pbMg': '5.00', + 'pbHg': '5.00', + 'pbAg': '5.00', + 'pbDg': '5.00', + 'pbCg': '', + 'size': '640x360', + 'adserverTargeting': { + 'hb_bidder': 'appnexus', + 'hb_adid': '28f24ced14586c', + 'hb_pb': '5.00', + 'hb_size': '640x360', + 'hb_source': 'client', + 'hb_format': 'video', + 'hb_pb_cat_dur': priceIndustryDuration, + 'hb_cache_id': uuid + }, + 'customCacheKey': `${priceIndustryDuration}_${uuid}`, + 'meta': { + 'iabSubCatId': 'iab-1', + 'adServerCatId': label + }, + 'videoCacheKey': '4cf395af-8fee-4960-af0e-88d44e399f14' + } +} diff --git a/test/spec/modules/freeWheelAdserverVideo_spec.js b/test/spec/modules/freeWheelAdserverVideo_spec.js index ffc690e5a92..f958a2733db 100644 --- a/test/spec/modules/freeWheelAdserverVideo_spec.js +++ b/test/spec/modules/freeWheelAdserverVideo_spec.js @@ -1,12 +1,13 @@ import { expect } from 'chai'; -import { getTargeting, adpodUtils } from 'modules/freeWheelAdserverVideo'; +import { adpodUtils } from 'modules/freeWheelAdserverVideo'; import { auctionManager } from 'src/auctionManager'; import { config } from 'src/config'; describe('freeWheel adserver module', function() { let amStub; let amGetAdUnitsStub; - let pbcStub; + let xhr; + let requests; before(function () { let adUnits = [{ @@ -52,12 +53,13 @@ describe('freeWheel adserver module', function() { amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits'); amGetAdUnitsStub.returns(adUnits); amStub = sinon.stub(auctionManager, 'getBidsReceived'); - pbcStub = sinon.stub(adpodUtils, 'callPrebidCacheAfterAuction').callsFake(function (...args) { - args[1](null, getBidsReceived()); - }); }); beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + config.setConfig({ adpod: { brandCategoryExclusion: false, @@ -68,6 +70,7 @@ describe('freeWheel adserver module', function() { afterEach(function() { config.resetConfig(); + xhr.restore(); }); after(function () { @@ -78,7 +81,7 @@ describe('freeWheel adserver module', function() { it('should return targeting for all adunits', function() { amStub.returns(getBidsReceived()); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } @@ -91,7 +94,7 @@ describe('freeWheel adserver module', function() { it('should return targeting for passed adunit code', function() { amStub.returns(getBidsReceived()); let targeting; - getTargeting({ + adpodUtils.getTargeting({ codes: ['preroll_1'], callback: function(errorMsg, targetingResult) { targeting = targetingResult; @@ -120,7 +123,7 @@ describe('freeWheel adserver module', function() { }]; amStub.returns(getBidsReceived().concat(bannerBid)); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } @@ -144,7 +147,7 @@ describe('freeWheel adserver module', function() { createBid(10, 'preroll_1', 30, '10.00_395_30s', '123', '395') ]); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } @@ -161,7 +164,7 @@ describe('freeWheel adserver module', function() { createBid(15, 'midroll_1', 90, '15.00_406_90s', '123', '406') ]); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } @@ -179,15 +182,20 @@ describe('freeWheel adserver module', function() { }); amStub.returns(getBidsReceived()); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } }); - expect(pbcStub.called).to.equal(true); + requests[0].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify({'responses': getBidsReceived().slice(0, 4)}) + ); + expect(targeting['preroll_1'].length).to.equal(3); - expect(targeting['midroll_1'].length).to.equal(4); + expect(targeting['midroll_1'].length).to.equal(3); }); }); From 7fb982f489f53d639602b508b3d22f2125a89f0a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 17 Jul 2019 13:34:03 -0400 Subject: [PATCH 1351/1594] Prebid 2.24.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ca8c03783d..11e9b857234 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.24.0-pre", + "version": "2.24.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d3643fd4a1a5d89743751a2c3c5909ef365e09ce Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 17 Jul 2019 13:50:53 -0400 Subject: [PATCH 1352/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 11e9b857234..1cc2da9abc2 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.24.0", + "version": "2.25.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3740de3e4a43fb74dfa7a950052b4c496cac8bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Fri, 19 Jul 2019 15:11:00 +0200 Subject: [PATCH 1353/1594] Added 'ceh' config property in Criteo bid adapter (#3969) * Added 'ceh' config property and mapped it to CDB request Added 'ceh' config property and mapped it to CDB request * Added config.resetConfig() to ensure that call to setConfig won't have an impact on any other test * Missed the ';' --- modules/criteoBidAdapter.js | 9 ++++++- modules/criteoBidAdapter.md | 10 ++++++++ test/spec/modules/criteoBidAdapter_spec.js | 28 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index ff612aff905..0507ba428be 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -5,8 +5,9 @@ import * as utils from '../src/utils'; import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; +import { config } from '../src/config'; -const ADAPTER_VERSION = 16; +const ADAPTER_VERSION = 17; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -47,6 +48,8 @@ export const spec = { let url; let data; + Object.assign(bidderRequest, { ceh: config.getConfig('criteo.ceh') }); + // If publisher tag not already loaded try to get it from fast bid if (!publisherTagAvailable()) { window.Criteo = window.Criteo || {}; @@ -239,6 +242,10 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { if (networkId) { request.publisher.networkid = networkId; } + request.user = {}; + if (bidderRequest && bidderRequest.ceh) { + request.user.ceh = bidderRequest.ceh; + } if (bidderRequest && bidderRequest.gdprConsent) { request.gdprConsent = {}; if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { diff --git a/modules/criteoBidAdapter.md b/modules/criteoBidAdapter.md index 796c70a980f..e4c441c758d 100644 --- a/modules/criteoBidAdapter.md +++ b/modules/criteoBidAdapter.md @@ -25,3 +25,13 @@ Module that connects to Criteo's demand sources. } ]; ``` + +# Additional Config (Optional) +Set the "ceh" property to provides the user's hashed email if available +``` + pbjs.setConfig({ + criteo: { + ceh: 'hashed mail' + } + }); +``` \ No newline at end of file diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 8a5bea97cb8..ac9ae53af07 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -3,12 +3,14 @@ import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter'; import { createBid } from 'src/bidfactory'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; +import { config } from '../../../src/config'; describe('The Criteo bidding adapter', function () { beforeEach(function () { // Remove FastBid to avoid side effects. localStorage.removeItem('criteo_fast_bid'); }); + describe('isBidRequestValid', function () { it('should return false when given an invalid bid', function () { const bid = { @@ -66,6 +68,10 @@ describe('The Criteo bidding adapter', function () { }, }; + afterEach(function () { + config.resetConfig(); + }); + it('should properly build a zoneId request', function () { const bidRequests = [ { @@ -198,6 +204,28 @@ describe('The Criteo bidding adapter', function () { expect(ortbRequest.gdprConsent.gdprApplies).to.equal(undefined); expect(ortbRequest.gdprConsent.consentGiven).to.equal(undefined); }); + + it('should properly build a request with ceh', function () { + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + params: { + zoneId: 123, + }, + }, + ]; + config.setConfig({ + criteo: { + ceh: 'hashedemail' + } + }); + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.user).to.not.be.null; + expect(request.data.user.ceh).to.equal('hashedemail'); + }); }); describe('interpretResponse', function () { From 1d92d401e1cf7c706850de733ff091a8169b33d1 Mon Sep 17 00:00:00 2001 From: afsheenb Date: Fri, 19 Jul 2019 09:21:58 -0400 Subject: [PATCH 1354/1594] ozone adapter - minor fix to add w/h to video requests (#3953) * minor fix to add w/h to video requests * fixing padding/spacing errors caught by circleCI * fixing padding/spacing errors caught by circleCI, take two --- modules/ozoneBidAdapter.js | 91 ++++++++++++++++++++--- test/spec/modules/ozoneBidAdapter_spec.js | 89 +++++++++++++++++++++- 2 files changed, 167 insertions(+), 13 deletions(-) diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index 7ab69f1e37a..9bd4f21ff96 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -11,7 +11,7 @@ const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js'; -const OZONEVERSION = '2.1.1'; +const OZONEVERSION = '2.1.2'; export const spec = { code: BIDDER_CODE, @@ -65,11 +65,11 @@ export const spec = { } if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) { if (!bid.mediaTypes.video.hasOwnProperty('context')) { - utils.logInfo('OZONE: [WARNING] No context key/value in bid. Rejecting bid: ', ozoneBidRequest); + utils.logInfo('OZONE: [WARNING] No context key/value in bid. Rejecting bid: ', bid); return false; } if (bid.mediaTypes.video.context !== 'outstream') { - utils.logInfo('OZONE: [WARNING] Only outstream video is supported. Rejecting bid: ', ozoneBidRequest); + utils.logInfo('OZONE: [WARNING] Only outstream video is supported. Rejecting bid: ', bid); return false; } } @@ -134,10 +134,24 @@ export const spec = { arrBannerSizes = ozoneBidRequest.mediaTypes[BANNER].sizes; /* Note - if there is a sizes element in the config root it will be pushed into here */ utils.logInfo('OZONE: setting banner size from the mediaTypes.banner element for bidId ' + obj.id + ': ', arrBannerSizes); } - // Video integration is not complete yet if (ozoneBidRequest.mediaTypes.hasOwnProperty(VIDEO)) { obj.video = ozoneBidRequest.mediaTypes[VIDEO]; - utils.logInfo('OZONE: setting video object from the mediaTypes.video element: ' + obj.id + ':', obj.video); + // we need to duplicate some of the video values + let wh = getWidthAndHeightFromVideoObject(obj.video); + utils.logInfo('OZONE: 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. + utils.logInfo('OZONE: setting obj.video.format to be an array of objects'); + obj.video.format = [wh]; + } else { + utils.logInfo('OZONE: setting obj.video.format to be an object'); + obj.video.format = wh; + } + } else { + utils.logInfo('OZONE: cannot set w, h & format values for video; the config is not right'); + } } // Native integration is not complete yet if (ozoneBidRequest.mediaTypes.hasOwnProperty(NATIVE)) { @@ -319,7 +333,7 @@ export function checkDeepArray(Arr) { } export function defaultSize(thebidObj) { if (!thebidObj) { - utils.logInfo('defaultSize received empty bid obj! going to return fixed default size'); + utils.logInfo('OZONE: defaultSize received empty bid obj! going to return fixed default size'); return { 'defaultHeight': 250, 'defaultWidth': 300 @@ -389,14 +403,14 @@ export function getRoundedBid(price, mediaType) { let theConfigObject = getGranularityObject(mediaType, mediaTypeGranularity, strBuckets, objBuckets); let theConfigKey = getGranularityKeyName(mediaType, mediaTypeGranularity, strBuckets); - utils.logInfo('getRoundedBid. price:', price, 'mediaType:', mediaType, 'configkey:', theConfigKey, 'configObject:', theConfigObject, 'mediaTypeGranularity:', mediaTypeGranularity, 'strBuckets:', strBuckets); + utils.logInfo('OZONE: getRoundedBid. price:', price, 'mediaType:', mediaType, 'configkey:', theConfigKey, 'configObject:', theConfigObject, 'mediaTypeGranularity:', mediaTypeGranularity, 'strBuckets:', strBuckets); let priceStringsObj = getPriceBucketString( price, theConfigObject, config.getConfig('currency.granularityMultiplier') ); - utils.logInfo('priceStringsObj', priceStringsObj); + utils.logInfo('OZONE: priceStringsObj', priceStringsObj); // by default, without any custom granularity set, you get granularity name : 'medium' let granularityNamePriceStringsKeyMapping = { 'medium': 'med', @@ -526,9 +540,68 @@ function outstreamRender(bid) { function toFlatArray(obj) { let ret = []; Object.keys(obj).forEach(function(key) { if (obj[key]) { ret.push(parseInt(key)); } }); - utils.logInfo('toFlatArray:', obj, 'returning', ret); + utils.logInfo('OZONE: toFlatArray:', obj, 'returning', ret); return ret; } +/** + * + * @param objVideo will be like {"playerSize":[640,480],"mimes":["video/mp4"],"context":"outstream"} or POSSIBLY {"playerSize":[[640,480]],"mimes":["video/mp4"],"context":"outstream"} + * @return object {w,h} or null + */ +export function getWidthAndHeightFromVideoObject(objVideo) { + let playerSize = getPlayerSizeFromObject(objVideo); + if (!playerSize) { + return null; + } + if (playerSize[0] && typeof playerSize[0] === 'object') { + utils.logInfo('OZONE: getWidthAndHeightFromVideoObject found nested array inside playerSize.', playerSize[0]); + playerSize = playerSize[0]; + if (typeof playerSize[0] !== 'number' && typeof playerSize[0] !== 'string') { + utils.logInfo('OZONE: 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) { + utils.logInfo('OZONE: getWidthAndHeightFromVideoObject found playerSize with length of ' + playerSize.length + '. This is totally wrong - cannot continue.'); + return null; + } + return ({'w': playerSize[0], 'h': playerSize[1]}); +} + +/** + * @param objVideo will be like {"playerSize":[640,480],"mimes":["video/mp4"],"context":"outstream"} or POSSIBLY {"playerSize":[[640,480]],"mimes":["video/mp4"],"context":"outstream"} + * @return object {w,h} or null + */ +export function playerSizeIsNestedArray(objVideo) { + let playerSize = getPlayerSizeFromObject(objVideo); + if (!playerSize) { + return null; + } + if (playerSize.length < 1) { + return null; + } + return (playerSize[0] && typeof playerSize[0] === 'object'); +} + +/** + * Common functionality when looking at a video object, to get the playerSize + * @param objVideo + * @returns {*} + */ +function getPlayerSizeFromObject(objVideo) { + utils.logInfo('OZONE: getPlayerSizeFromObject received object', objVideo); + if (!objVideo.hasOwnProperty('playerSize')) { + utils.logError('OZONE: getPlayerSizeFromObject FAILED: no playerSize in video object', objVideo); + return null; + } + let playerSize = objVideo.playerSize; + if (typeof playerSize !== 'object') { + utils.logError('OZONE: getPlayerSizeFromObject FAILED: playerSize is not an object/array', objVideo); + return null; + } + return playerSize; +} + registerBidder(spec); utils.logInfo('OZONE: ozoneBidAdapter ended'); diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index e17d51804a1..a0b51ff7a9f 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec } from 'modules/ozoneBidAdapter'; +import { spec, getWidthAndHeightFromVideoObject, playerSizeIsNestedArray, defaultSize } from 'modules/ozoneBidAdapter'; import { config } from 'src/config'; import {Renderer} from '../../../src/Renderer'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; @@ -74,7 +74,7 @@ var validBidRequestsWithNonBannerMediaTypesAndValidOutstreamVideo = [ bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: {skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode'} } ] }, - mediaTypes: {video: {mimes: ['video/mp4'], 'context': 'outstream'}, native: {info: 'dummy data'}}, + mediaTypes: {video: {mimes: ['video/mp4'], 'context': 'outstream', 'sizes': [640, 480]}, native: {info: 'dummy data'}}, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; @@ -664,7 +664,7 @@ describe('ozone Adapter', function () { params: { 'placementId': '1234567890', 'publisherId': '9876abcd12-3', - 'lotameData': 'this should be an object', + 'lotameData': {}, siteId: '1234567890' }, mediaTypes: { @@ -678,6 +678,24 @@ describe('ozone Adapter', function () { expect(spec.isBidRequestValid(xBadVideoContext)).to.equal(false); }); + var xBadVideoContext2 = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'lotameData': {}, + siteId: '1234567890' + }, + mediaTypes: { + video: { + mimes: ['video/mp4']} + } + }; + + it('should not validate video without context attribute', function () { + expect(spec.isBidRequestValid(xBadVideoContext2)).to.equal(false); + }); + let validVideoBidReq = { bidder: BIDDER_CODE, params: { @@ -692,7 +710,7 @@ describe('ozone Adapter', function () { } }; - it('should not validate video instream being sent', function () { + it('should validate video outstream being sent', function () { expect(spec.isBidRequestValid(validVideoBidReq)).to.equal(true); }); }); @@ -908,4 +926,67 @@ describe('ozone Adapter', function () { expect(result).to.be.empty; }); }); + + describe('video object utils', function () { + it('should find width & height from video object', function () { + let obj = {'playerSize': [640, 480], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result.w).to.equal(640); + expect(result.h).to.equal(480); + }); + it('should find null from bad video object', function () { + let obj = {'playerSize': [], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result).to.be.null; + }); + it('should find null from bad video object2', function () { + let obj = {'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result).to.be.null; + }); + it('should find null from bad video object3', function () { + let obj = {'playerSize': 'should be an array', 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result).to.be.null; + }); + it('should find that player size is nested', function () { + let obj = {'playerSize': [[640, 480]], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result.w).to.equal(640); + expect(result.h).to.equal(480); + }); + it('should fail if player size is 2 x nested', function () { + let obj = {'playerSize': [[[640, 480]]], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result).to.be.null; + }); + it('should find that player size is nested', function () { + let obj = {'playerSize': [[640, 480]], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = playerSizeIsNestedArray(obj); + expect(result).to.be.true; + }); + it('should find null from bad video object', function () { + let obj = {'playerSize': [], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = playerSizeIsNestedArray(obj); + expect(result).to.be.null; + }); + it('should find null from bad video object2', function () { + let obj = {'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = playerSizeIsNestedArray(obj); + expect(result).to.be.null; + }); + it('should find null from bad video object3', function () { + let obj = {'playerSize': 'should be an array', 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = playerSizeIsNestedArray(obj); + expect(result).to.be.null; + }); + }); + describe('default size', function () { + it('should should return default sizes if no obj is sent', function () { + let obj = ''; + const result = defaultSize(obj); + expect(result.defaultHeight).to.equal(250); + expect(result.defaultWidth).to.equal(300); + }); + }); }); From 1b331f34cae64bec9db392ed74fd2093a5fa8b09 Mon Sep 17 00:00:00 2001 From: rhythmonebhaines <49991465+rhythmonebhaines@users.noreply.github.com> Date: Fri, 19 Jul 2019 06:33:11 -0700 Subject: [PATCH 1355/1594] Rhythmone Adapter - Remove usersync, do not send device, do not send bad banners (#3927) --- modules/rhythmoneBidAdapter.js | 103 +++++------------- test/spec/modules/rhythmoneBidAdapter_spec.js | 90 ++++++++------- 2 files changed, 68 insertions(+), 125 deletions(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 6e7a935c71c..84caca5508a 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -15,8 +15,7 @@ function RhythmOneBidAdapter() { let SUPPORTED_VIDEO_API = [1, 2, 5]; let slotsToBids = {}; let that = this; - let version = '2.0.0.0'; - let loadStart = Date.now(); + let version = '2.0.1.0'; var win = typeof window !== 'undefined' ? window : {}; this.isBidRequestValid = function (bid) { @@ -24,66 +23,11 @@ function RhythmOneBidAdapter() { }; this.getUserSyncs = function (syncOptions, responses, gdprConsent) { - let slots = []; - let placementIds = []; - - for (let k in slotsToBids) { - slots.push(k); - placementIds.push(getFirstParam('placementId', [slotsToBids[k]])); - } - - let data = { - doc_version: 1, - doc_type: 'Prebid Audit', - placement_id: placementIds.join(',').replace(/[,]+/g, ',').replace(/^,|,$/g, '') - }; - let w = typeof (window) !== 'undefined' ? window : {document: {location: {href: ''}}}; - let ao = w.document.location.ancestorOrigins; - let q = []; - let u = '//hbevents.1rx.io/audit?'; - - if (ao && ao.length > 0) { - data.ancestor_origins = ao[ao.length - 1]; - } - - data.popped = w.opener !== null ? 1 : 0; - data.framed = w.top === w ? 0 : 1; - - try { - data.url = w.top.document.location.href.toString(); - } catch (ex) { - data.url = w.document.location.href.toString(); - } - - try { - data.prebid_version = '$prebid.version$'; - data.prebid_timeout = config.getConfig('bidderTimeout'); - } catch (ex) { } - - data.response_ms = Date.now() - loadStart; - data.placement_codes = slots.join(','); - data.bidder_version = version; - if (gdprConsent) { - data.gdpr_consent = gdprConsent.consentString; - data.gdpr = (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : false; - } - - for (let k in data) { - q.push(encodeURIComponent(k) + '=' + encodeURIComponent((typeof data[k] === 'object' ? JSON.stringify(data[k]) : data[k]))); - } - - q.sort(); - - if (syncOptions.pixelEnabled) { - return [{ - type: 'image', - url: u + q.join('&') - }]; - } + return []; }; function frameImp(BRs) { - var imp = []; + var impList = []; for (var i = 0; i < BRs.length; i++) { slotsToBids[BRs[i].adUnitCode || BRs[i].placementCode] = BRs[i]; var impObj = {}; @@ -92,15 +36,21 @@ function RhythmOneBidAdapter() { impObj.secure = win.location.protocol === 'https:' ? 1 : 0; if (utils.deepAccess(BRs[i], 'mediaTypes.banner') || utils.deepAccess(BRs[i], 'mediaType') === 'banner') { - impObj.banner = frameBanner(BRs[i]); + let banner = frameBanner(BRs[i]); + if (banner) { + impObj.banner = banner; + } } if (utils.deepAccess(BRs[i], 'mediaTypes.video') || utils.deepAccess(BRs[i], 'mediaType') === 'video') { impObj.video = frameVideo(BRs[i]); } + if (!(impObj.banner || impObj.video)) { + continue; + } impObj.ext = frameExt(BRs[i]); - imp.push(impObj); + impList.push(impObj); } - return imp; + return impList; } function frameSite(bidderRequest) { @@ -134,7 +84,6 @@ function RhythmOneBidAdapter() { function frameDevice() { return { ua: navigator.userAgent, - devicetype: /(ios|ipod|ipad|iphone|android)/i.test(win.navigator.userAgent) ? 1 : /(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i.test(win.navigator.userAgent) ? 3 : 2, ip: '', // Empty Ip string is required, server gets the ip from HTTP header dnt: utils.getDNT() ? 1 : 0, } @@ -157,21 +106,16 @@ function RhythmOneBidAdapter() { sizeList = adUnit.mediaTypes.banner.sizes; } var sizeStringList = utils.parseSizesInput(sizeList); - if (!Array.isArray(sizeStringList)) { - return {}; - } - var format = []; sizeStringList.forEach(function(size) { - if (!size) { - return; - } - var dimensionList = getValidSizeSet(size.split('x')); - if (dimensionList) { - format.push({ - 'w': dimensionList[0], - 'h': dimensionList[1], - }); + if (size) { + var dimensionList = getValidSizeSet(size.split('x')); + if (dimensionList) { + format.push({ + 'w': dimensionList[0], + 'h': dimensionList[1], + }); + } } }); if (format.length) { @@ -179,7 +123,8 @@ function RhythmOneBidAdapter() { 'format': format }; } - return {}; + + return false; } function frameVideo(bid) { @@ -272,7 +217,9 @@ function RhythmOneBidAdapter() { rmpUrl += '&hbv=' + prebidVersion.replace(fat, '') + ',' + version.replace(fat, ''); var bidRequest = frameBid(BRs, bidderRequest); - loadStart = Date.now(); + if (!bidRequest.imp.length) { + return {}; + } return { method: 'POST', diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index e909827b2df..6b414db47ab 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -91,9 +91,7 @@ describe('rhythmone adapter tests', function () { }, 'mediaTypes': { 'video': { - 'playerSize': [ - [640, 480] - ], + 'playerSize': [640, 480], 'context': 'instream' } }, @@ -332,7 +330,7 @@ describe('rhythmone adapter tests', function () { expect(openrtbRequest.imp[0].banner.format[0].h).to.equal(600); }); - it('survives size misconfiguration', function () { + it('does not return request for invalid banner size configuration', function () { var bidRequestList = [ { 'bidder': 'rhythmone', @@ -356,22 +354,20 @@ describe('rhythmone adapter tests', function () { ]; var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - - const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.imp[0].banner.format).to.be.undefined; + expect(bidRequest.method).to.be.undefined; }); - it('dnt is correctly set to 1', function () { + it('does not return request for missing banner size configuration', function () { var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' }, 'mediaTypes': { - 'banner': { - 'sizes': [[300, 600]] - } + 'banner': {} }, 'adUnitCode': 'div-gpt-ad-1438287399331-0', 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', @@ -382,23 +378,42 @@ describe('rhythmone adapter tests', function () { } ]; - var dntStub = sinon.stub(utils, 'getDNT').returns(1); - var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + expect(bidRequest.method).to.be.undefined; + }); - dntStub.restore(); + it('reject bad sizes', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaTypes': { + 'banner': {'sizes': [['400', '500'], ['4n0', '5g0']]} + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.device.dnt).to.equal(1); + expect(openrtbRequest.imp[0].banner.format.length).to.equal(1); }); - it('sets floor', function () { + it('dnt is correctly set to 1', function () { var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { 'placementId': 'myplacement', - 'floor': 100.0 }, 'mediaTypes': { 'banner': { @@ -414,26 +429,30 @@ describe('rhythmone adapter tests', function () { } ]; + var dntStub = sinon.stub(utils, 'getDNT').returns(1); + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + dntStub.restore(); + const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.imp[0].bidfloor).to.equal(100.0); + expect(openrtbRequest.device.dnt).to.equal(1); }); - it('support for correct video size definition', function () { + it('sets floor', function () { var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { 'placementId': 'myplacement', + 'floor': 100.0 }, 'mediaTypes': { - 'video': { - 'playerSize': [640, 480], - 'context': 'instream' + 'banner': { + 'sizes': [[300, 600]] } }, - 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', 'bidderRequestId': '418b37f85e772c', 'auctionId': '18fd8b8b0bd757', @@ -445,8 +464,7 @@ describe('rhythmone adapter tests', function () { var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.imp[0].video.w).to.equal(640); - expect(openrtbRequest.imp[0].video.h).to.equal(480); + expect(openrtbRequest.imp[0].bidfloor).to.equal(100.0); }); it('supports string video sizes', function () { @@ -604,28 +622,6 @@ describe('rhythmone adapter tests', function () { }); }); - describe('auditBeacon', function() { - it('should contain the correct path', function() { - var syncList = r1adapter.getUserSyncs({pixelEnabled: true}); - expect(syncList.length).to.equal(1); - var syncData = syncList[0]; - var expectedURL = '//hbevents.1rx.io/audit?'; - assert.equal(syncData.url.substring(0, expectedURL.length), expectedURL); - }); - - it('should send GDPR Consent data to Sync pixel', function () { - var syncList = r1adapter.getUserSyncs({pixelEnabled: true}, null, {'gdprApplies': true, 'consentString': 'testConsentString'}); - expect(syncList.length).to.equal(1); - var syncData = syncList[0]; - expect(syncData.url).to.have.string('&gdpr=true&gdpr_consent=testConsentString'); - }); - - it('should not return anything when pixelEnabled is false', function () { - var syncList = r1adapter.getUserSyncs({pixelEnabled: false}, null, {'gdprApplies': true, 'consentString': 'testConsentString'}); - expect(syncList).to.be.undefined; - }); - }); - describe('isBidRequestValid', function () { var bid = { 'bidder': 'rhythmone', From fa9d4be6a513783eb75865713a2f2e41520294c6 Mon Sep 17 00:00:00 2001 From: my6sense Date: Mon, 22 Jul 2019 17:58:06 +0300 Subject: [PATCH 1356/1594] My6Sense: Endpoint subdomain changed. (#3982) * My6sense new adapter * endpoint fix * Code fix * Added changes in adapter md file * Changed the end point * supportedMediaTypes values added * md file was updated with a valid widget key * endpoint changed * indentation issues fixed --- modules/my6senseBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/my6senseBidAdapter.js b/modules/my6senseBidAdapter.js index 38aa1da8573..1f6080d82b9 100644 --- a/modules/my6senseBidAdapter.js +++ b/modules/my6senseBidAdapter.js @@ -2,7 +2,7 @@ import { BANNER, NATIVE } from '../src/mediaTypes'; const {registerBidder} = require('../src/adapters/bidderFactory'); const BIDDER_CODE = 'my6sense'; -const END_POINT = '//papi.mynativeplatform.com/pub2/web/v1.15.0/hbwidget.json'; +const END_POINT = '//hb.mynativeplatform.com/pub2/web/v1.15.0/hbwidget.json'; const END_POINT_METHOD = 'POST'; // called first From 46cdbefd12f950f74e7f6f83503a5ce49c6d002e Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 22 Jul 2019 09:15:29 -0600 Subject: [PATCH 1357/1594] update user sync to allow for multiple auction syncs (#3984) --- src/userSync.js | 30 +++++++++++++++++++----------- test/spec/userSync_spec.js | 7 +++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/userSync.js b/src/userSync.js index 3cbdc58a075..2d5dfbd9a28 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -24,8 +24,8 @@ export function newUserSync(userSyncDependencies) { // Let getDefaultQueue() set the defaults let queue = getDefaultQueue(); - // Whether or not user syncs have been trigger on this page load - let hasFired = false; + // Whether or not user syncs have been trigger on this page load for a specific bidder + let hasFiredBidder = new Set(); // How many bids for each adapter let numAdapterBids = {}; @@ -33,7 +33,7 @@ export function newUserSync(userSyncDependencies) { let permittedPixels = { image: false, iframe: false - } + }; // Use what is in config by default let usConfig = userSyncDependencies.config; @@ -61,7 +61,7 @@ export function newUserSync(userSyncDependencies) { * @private */ function fireSyncs() { - if (!usConfig.syncEnabled || !userSyncDependencies.browserSupportsCookies || (!usConfig.enableOverride && hasFired)) { + if (!usConfig.syncEnabled || !userSyncDependencies.browserSupportsCookies) { return; } @@ -75,7 +75,16 @@ export function newUserSync(userSyncDependencies) { } // Reset the user sync queue queue = getDefaultQueue(); - hasFired = true; + } + + function forEachFire(queue, fn) { + // 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 + utils.shuffle(queue).forEach((sync) => { + fn(sync); + hasFiredBidder.add(sync[0]); + }); } /** @@ -87,10 +96,7 @@ export function newUserSync(userSyncDependencies) { if (!(usConfig.pixelEnabled || permittedPixels.image)) { return; } - // 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 - utils.shuffle(queue.image).forEach((sync) => { + forEachFire(queue.image, (sync) => { let [bidderName, trackingPixelUrl] = sync; utils.logMessage(`Invoking image pixel user sync for bidder: ${bidderName}`); // Create image object and add the src url @@ -107,8 +113,7 @@ export function newUserSync(userSyncDependencies) { if (!(usConfig.iframeEnabled || permittedPixels.iframe)) { return; } - // Randomize the order of these syncs just like the pixels above - utils.shuffle(queue.iframe).forEach((sync) => { + forEachFire(queue.iframe, (sync) => { let [bidderName, iframeUrl] = sync; utils.logMessage(`Invoking iframe user sync for bidder: ${bidderName}`); // Insert iframe into DOM @@ -146,6 +151,9 @@ export function newUserSync(userSyncDependencies) { * userSync.registerSync('image', 'rubicon', 'http://example.com/pixel') */ publicApi.registerSync = (type, bidder, url) => { + if (hasFiredBidder.has(bidder)) { + return utils.logWarn(`already registered syncs for "${bidder}"`); + } if (!usConfig.syncEnabled || !utils.isArray(queue[type])) { return utils.logWarn(`User sync type "${type}" not supported`); } diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index f330be4c2f4..f55fe13c528 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -98,15 +98,18 @@ describe('user sync', function () { expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); }); - it('should only trigger syncs once per page', function () { + it('should only trigger syncs once per page per bidder', function () { const userSync = newTestUserSync({pixelEnabled: true}); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.syncUsers(); userSync.registerSync('image', 'testBidder', 'http://example.com/2'); + userSync.registerSync('image', 'testBidder2', 'http://example.com/3'); userSync.syncUsers(); + expect(triggerPixelStub.callCount).to.equal(2); expect(triggerPixelStub.getCall(0)).to.not.be.null; expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); - expect(triggerPixelStub.getCall(1)).to.be.null; + expect(triggerPixelStub.getCall(1)).to.not.be.null; + expect(triggerPixelStub.getCall(1).args[0]).to.exist.and.to.equal('http://example.com/3'); }); it('should not fire syncs if cookies are not supported', function () { From e6e080a7097677288a472a05fcfbb92da8242aeb Mon Sep 17 00:00:00 2001 From: yeeldpadsquad <52921150+yeeldpadsquad@users.noreply.github.com> Date: Mon, 22 Jul 2019 18:45:54 +0200 Subject: [PATCH 1358/1594] Padsquad bid adapter (#4002) * padsquad bid adapter * padsquad bid adapter * removed unnecessary log line --- modules/padsquadBidAdapter.js | 132 ++++++++++ modules/padsquadBidAdapter.md | 33 +++ test/spec/modules/padsquadBidAdapter_spec.js | 261 +++++++++++++++++++ 3 files changed, 426 insertions(+) create mode 100644 modules/padsquadBidAdapter.js create mode 100644 modules/padsquadBidAdapter.md create mode 100644 test/spec/modules/padsquadBidAdapter_spec.js diff --git a/modules/padsquadBidAdapter.js b/modules/padsquadBidAdapter.js new file mode 100644 index 00000000000..f5800bed7c9 --- /dev/null +++ b/modules/padsquadBidAdapter.js @@ -0,0 +1,132 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import {BANNER} from '../src/mediaTypes'; + +const ENDPOINT_URL = '//x.padsquad.com/auction'; + +const DEFAULT_BID_TTL = 30; +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_NET_REVENUE = true; + +export const spec = { + code: 'padsquad', + supportedMediaTypes: [BANNER], + + isBidRequestValid: function (bid) { + return (!!bid.params.unitId && typeof bid.params.unitId === 'string') || + (!!bid.params.networkId && typeof bid.params.networkId === 'string') || + (!!bid.params.publisherId && typeof bid.params.publisherId === 'string'); + }, + + buildRequests: function (validBidRequests, bidderRequest) { + if (!validBidRequests || !bidderRequest) { + return; + } + const publisherId = validBidRequests[0].params.publisherId; + const networkId = validBidRequests[0].params.networkId; + const impressions = validBidRequests.map(bidRequest => ({ + id: bidRequest.bidId, + banner: { + format: bidRequest.sizes.map(sizeArr => ({ + w: sizeArr[0], + h: sizeArr[1] + })) + }, + ext: { + exchange: { + unitId: bidRequest.params.unitId + } + } + })); + + const openrtbRequest = { + id: bidderRequest.auctionId, + imp: impressions, + site: { + domain: window.location.hostname, + page: window.location.href, + ref: bidderRequest.refererInfo ? bidderRequest.refererInfo.referer || null : null + }, + ext: { + exchange: { + publisherId: publisherId, + networkId: networkId, + } + } + }; + + // apply gdpr + if (bidderRequest.gdprConsent) { + openrtbRequest.regs = {ext: {gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0}}; + openrtbRequest.user = {ext: {consent: bidderRequest.gdprConsent.consentString}}; + } + + const payloadString = JSON.stringify(openrtbRequest); + return { + method: 'POST', + url: ENDPOINT_URL, + data: payloadString, + }; + }, + + interpretResponse: function (serverResponse, request) { + const bidResponses = []; + const response = (serverResponse || {}).body; + // response is always one seat with (optional) bids for each impression + if (response && response.seatbid && response.seatbid.length === 1 && response.seatbid[0].bid && response.seatbid[0].bid.length) { + response.seatbid[0].bid.forEach(bid => { + bidResponses.push({ + requestId: bid.impid, + cpm: bid.price, + width: bid.w, + height: bid.h, + ad: bid.adm, + ttl: DEFAULT_BID_TTL, + creativeId: bid.crid, + netRevenue: DEFAULT_NET_REVENUE, + currency: DEFAULT_CURRENCY, + }) + }) + } else { + utils.logInfo('padsquad.interpretResponse :: no valid responses to interpret'); + } + return bidResponses; + }, + getUserSyncs: function (syncOptions, serverResponses) { + utils.logInfo('padsquad.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses); + let syncs = []; + + if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { + return syncs; + } + + serverResponses.forEach(resp => { + const userSync = utils.deepAccess(resp, 'body.ext.usersync'); + if (userSync) { + let syncDetails = []; + Object.keys(userSync).forEach(key => { + const value = userSync[key]; + if (value.syncs && value.syncs.length) { + syncDetails = syncDetails.concat(value.syncs); + } + }); + syncDetails.forEach(syncDetails => { + syncs.push({ + type: syncDetails.type === 'iframe' ? 'iframe' : 'image', + url: syncDetails.url + }); + }); + + if (!syncOptions.iframeEnabled) { + syncs = syncs.filter(s => s.type !== 'iframe') + } + if (!syncOptions.pixelEnabled) { + syncs = syncs.filter(s => s.type !== 'image') + } + } + }); + return syncs; + }, + +}; +registerBidder(spec); diff --git a/modules/padsquadBidAdapter.md b/modules/padsquadBidAdapter.md new file mode 100644 index 00000000000..0a69db42ce3 --- /dev/null +++ b/modules/padsquadBidAdapter.md @@ -0,0 +1,33 @@ +# Overview + +``` +Module Name: Padsquad Bid Adapter +Module Type: Bidder Adapter +Maintainer: yeeldpadsquad@gmail.com +``` + +# Description + +Connects to Padsquad exchange for bids. + +Padsquad bid adapter supports Banner ads. + +# Test Parameters +``` +var adUnits = [ + { + code: 'banner-ad-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'padsquad', + params: { + unitId: 'test' + } + }] + } +]; +``` diff --git a/test/spec/modules/padsquadBidAdapter_spec.js b/test/spec/modules/padsquadBidAdapter_spec.js new file mode 100644 index 00000000000..aba1efea32f --- /dev/null +++ b/test/spec/modules/padsquadBidAdapter_spec.js @@ -0,0 +1,261 @@ +import {expect} from 'chai'; +import {spec} from 'modules/padsquadBidAdapter'; + +const REQUEST = { + 'bidderCode': 'padsquad', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708', + 'bidderRequestId': 'requestId', + 'bidRequest': [{ + 'bidder': 'padsquad', + 'params': { + 'unitId': 123456, + }, + 'placementCode': 'div-gpt-dummy-placement-code', + 'sizes': [ + [300, 250] + ], + 'bidId': 'bidId1', + 'bidderRequestId': 'bidderRequestId', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708' + }, + { + 'bidder': 'padsquad', + 'params': { + 'unitId': 123456, + }, + 'placementCode': 'div-gpt-dummy-placement-code', + 'sizes': [ + [300, 250] + ], + 'bidId': 'bidId2', + 'bidderRequestId': 'bidderRequestId', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708' + }], + 'start': 1487883186070, + 'auctionStart': 1487883186069, + 'timeout': 3000 +}; + +const RESPONSE = { + 'headers': null, + 'body': { + 'id': 'responseId', + 'seatbid': [ + { + 'bid': [ + { + 'id': 'bidId1', + 'impid': 'bidId1', + 'price': 0.18, + 'adm': '', + 'adid': '144762342', + 'adomain': [ + 'http://dummydomain.com' + ], + 'iurl': 'iurl', + 'cid': '109', + 'crid': 'creativeId', + 'cat': [], + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 334553, + 'auction_id': 514667951122925701, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + }, + { + 'id': 'bidId2', + 'impid': 'bidId2', + 'price': 0.1, + 'adm': '', + 'adid': '144762342', + 'adomain': [ + 'http://dummydomain.com' + ], + 'iurl': 'iurl', + 'cid': '109', + 'crid': 'creativeId', + 'cat': [], + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 386046, + 'auction_id': 517067951122925501, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + } + ], + 'seat': 'seat' + } + ], + 'ext': { + 'usersync': { + 'sovrn': { + 'status': 'none', + 'syncs': [ + { + 'url': 'urlsovrn', + 'type': 'iframe' + } + ] + }, + 'appnexus': { + 'status': 'none', + 'syncs': [ + { + 'url': 'urlappnexus', + 'type': 'pixel' + } + ] + } + }, + 'responsetimemillis': { + 'appnexus': 127 + } + } + } +}; + +describe('Padsquad bid adapter', function () { + describe('isBidRequestValid', function () { + it('should accept request if only unitId is passed', function () { + let bid = { + bidder: 'padsquad', + params: { + unitId: 'unitId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should accept request if only networkId is passed', function () { + let bid = { + bidder: 'padsquad', + params: { + networkId: 'networkId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should accept request if only publisherId is passed', function () { + let bid = { + bidder: 'padsquad', + params: { + publisherId: 'publisherId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('reject requests without params', function () { + let bid = { + bidder: 'padsquad', + params: {} + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + it('creates request data', function () { + let request = spec.buildRequests(REQUEST.bidRequest, REQUEST); + + expect(request).to.exist.and.to.be.a('object'); + const payload = JSON.parse(request.data); + expect(payload.imp[0]).to.have.property('id', REQUEST.bidRequest[0].bidId); + expect(payload.imp[1]).to.have.property('id', REQUEST.bidRequest[1].bidId); + }); + + it('has gdpr data if applicable', function () { + const req = Object.assign({}, REQUEST, { + gdprConsent: { + consentString: 'consentString', + gdprApplies: true, + } + }); + let request = spec.buildRequests(REQUEST.bidRequest, req); + + const payload = JSON.parse(request.data); + expect(payload.user.ext).to.have.property('consent', req.gdprConsent.consentString); + expect(payload.regs.ext).to.have.property('gdpr', 1); + }); + }); + + describe('interpretResponse', function () { + it('have bids', function () { + let bids = spec.interpretResponse(RESPONSE, REQUEST); + expect(bids).to.be.an('array').that.is.not.empty; + validateBidOnIndex(0); + validateBidOnIndex(1); + + function validateBidOnIndex(index) { + expect(bids[index]).to.have.property('currency', 'USD'); + expect(bids[index]).to.have.property('requestId', RESPONSE.body.seatbid[0].bid[index].impid); + expect(bids[index]).to.have.property('cpm', RESPONSE.body.seatbid[0].bid[index].price); + expect(bids[index]).to.have.property('width', RESPONSE.body.seatbid[0].bid[index].w); + expect(bids[index]).to.have.property('height', RESPONSE.body.seatbid[0].bid[index].h); + expect(bids[index]).to.have.property('ad', RESPONSE.body.seatbid[0].bid[index].adm); + expect(bids[index]).to.have.property('creativeId', RESPONSE.body.seatbid[0].bid[index].crid); + expect(bids[index]).to.have.property('ttl', 30); + expect(bids[index]).to.have.property('netRevenue', true); + } + }); + + it('handles empty response', function () { + const EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {}}); + const bids = spec.interpretResponse(EMPTY_RESP, REQUEST); + + expect(bids).to.be.empty; + }); + }); + + describe('getUserSyncs', function () { + it('handles no parameters', function () { + let opts = spec.getUserSyncs({}); + expect(opts).to.be.an('array').that.is.empty; + }); + it('returns non if sync is not allowed', function () { + let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false}); + + expect(opts).to.be.an('array').that.is.empty; + }); + + it('iframe sync enabled should return results', function () { + let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [RESPONSE]); + + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('iframe'); + expect(opts[0].url).to.equal(RESPONSE.body.ext.usersync['sovrn'].syncs[0].url); + }); + + it('pixel sync enabled should return results', function () { + let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [RESPONSE]); + + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('image'); + expect(opts[0].url).to.equal(RESPONSE.body.ext.usersync['appnexus'].syncs[0].url); + }); + + it('all sync enabled should return all results', function () { + let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [RESPONSE]); + + expect(opts.length).to.equal(2); + }); + }); +}); From adc15767f22da062e7d021da5c6baaf3e6e1eb8a Mon Sep 17 00:00:00 2001 From: Sudhanshu patel Date: Tue, 23 Jul 2019 05:12:41 +0530 Subject: [PATCH 1359/1594] SRE-1994: s3 http domain migration (#4012) --- .../modules/adgenerationBidAdapter_spec.js | 22 +++++++++---------- test/spec/modules/kummaBidAdapter_spec.js | 8 +++---- .../spec/modules/platformioBidAdapter_spec.js | 8 +++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/spec/modules/adgenerationBidAdapter_spec.js b/test/spec/modules/adgenerationBidAdapter_spec.js index 28bccd7844e..2b8834f1e1d 100644 --- a/test/spec/modules/adgenerationBidAdapter_spec.js +++ b/test/spec/modules/adgenerationBidAdapter_spec.js @@ -199,7 +199,7 @@ describe('AdgenerationAdapter', function () { results: [], }, banner: { - ad: '
    ', + ad: '
    ', beacon: '', cpm: 36.0008, displaytype: '1', @@ -215,11 +215,11 @@ describe('AdgenerationAdapter', function () { dealid: 'fd5sa5fa7f', ttl: 1000, results: [ - {ad: '
    '}, + {ad: '
    '}, ] }, native: { - ad: '↵ ↵ ↵ ↵ ↵
    ↵ ', + ad: '↵ ↵ ↵ ↵ ↵
    ↵ ', beacon: '', cpm: 36.0008, displaytype: '1', @@ -261,7 +261,7 @@ describe('AdgenerationAdapter', function () { id: 2, img: { h: 250, - url: 'https://s3-ap-northeast-1.amazonaws.com/sdk-temp/adg-sample-ad/img/300x250.png', + url: 'https://sdk-temp.s3-ap-northeast-1.amazonaws.com/adg-sample-ad/img/300x250.png', w: 300 }, required: 1 @@ -291,10 +291,10 @@ describe('AdgenerationAdapter', function () { required: 0 } ], - imptrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1.gif'], + imptrackers: ['https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1.gif'], link: { clicktrackers: [ - 'https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1_clicktracker_access.gif' + 'https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1_clicktracker_access.gif' ], url: 'https://supership.jp' }, @@ -322,7 +322,7 @@ describe('AdgenerationAdapter', function () { currency: 'JPY', netRevenue: true, ttl: 1000, - ad: '
    ', + ad: '
    ', }, native: { requestId: '2f6ac468a9c15e', @@ -334,11 +334,11 @@ describe('AdgenerationAdapter', function () { currency: 'JPY', netRevenue: true, ttl: 1000, - ad: '↵
    ', + ad: '↵
    ', native: { title: 'Title', image: { - url: 'https://s3-ap-northeast-1.amazonaws.com/sdk-temp/adg-sample-ad/img/300x250.png', + url: 'https://sdk-temp.s3-ap-northeast-1.amazonaws.com/adg-sample-ad/img/300x250.png', height: 250, width: 300 }, @@ -352,8 +352,8 @@ describe('AdgenerationAdapter', function () { cta: 'CTA', privacyLink: 'https://supership.jp/optout/#', clickUrl: 'https://supership.jp', - clickTrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1_clicktracker_access.gif'], - impressionTrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1.gif'] + clickTrackers: ['https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1_clicktracker_access.gif'], + impressionTrackers: ['https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1.gif'] }, mediaType: NATIVE } diff --git a/test/spec/modules/kummaBidAdapter_spec.js b/test/spec/modules/kummaBidAdapter_spec.js index 82076717dcc..7d33bd085b5 100644 --- a/test/spec/modules/kummaBidAdapter_spec.js +++ b/test/spec/modules/kummaBidAdapter_spec.js @@ -192,8 +192,8 @@ describe('Kumma Adapter Tests', function () { { id: 1, title: { text: 'Ad Title' } }, { id: 2, data: { value: 'Test description' } }, { id: 3, data: { value: 'Brand' } }, - { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, - { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + { id: 4, img: { url: 'https://adx1public.s3.amazonaws.com/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://adx1public.s3.amazonaws.com/creatives_image.png', w: 300, h: 300 } } ], link: { url: 'http://brand.com/' } } @@ -220,8 +220,8 @@ describe('Kumma Adapter Tests', function () { expect(nativeBid).to.not.equal(null); expect(nativeBid.title).to.equal('Ad Title'); expect(nativeBid.sponsoredBy).to.equal('Brand'); - expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); - expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.icon.url).to.equal('https://adx1public.s3.amazonaws.com/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://adx1public.s3.amazonaws.com/creatives_image.png'); expect(nativeBid.image.width).to.equal(300); expect(nativeBid.image.height).to.equal(300); expect(nativeBid.icon.width).to.equal(100); diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index f3754654cf1..4ef2dc1bba0 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -192,8 +192,8 @@ describe('Platform.io Adapter Tests', function () { { id: 1, title: { text: 'Ad Title' } }, { id: 2, data: { value: 'Test description' } }, { id: 3, data: { value: 'Brand' } }, - { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, - { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + { id: 4, img: { url: 'https://adx1public.s3.amazonaws.com/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://adx1public.s3.amazonaws.com/creatives_image.png', w: 300, h: 300 } } ], link: { url: 'http://brand.com/' } } @@ -220,8 +220,8 @@ describe('Platform.io Adapter Tests', function () { expect(nativeBid).to.not.equal(null); expect(nativeBid.title).to.equal('Ad Title'); expect(nativeBid.sponsoredBy).to.equal('Brand'); - expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); - expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.icon.url).to.equal('https://adx1public.s3.amazonaws.com/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://adx1public.s3.amazonaws.com/creatives_image.png'); expect(nativeBid.image.width).to.equal(300); expect(nativeBid.image.height).to.equal(300); expect(nativeBid.icon.width).to.equal(100); From c202a13a0ec3df708dfeb944dc1358a58754c52c Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 22 Jul 2019 20:28:42 -0400 Subject: [PATCH 1360/1594] Debug update and remove setConfig hook (#4007) * Debug update and remove setConfig hook * fix config failing on circular dependency with utils --- src/config.js | 10 ++++++---- src/utils.js | 8 -------- test/spec/debugging_spec.js | 1 + 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/config.js b/src/config.js index a1a8af629d8..7645da18d8f 100644 --- a/src/config.js +++ b/src/config.js @@ -10,10 +10,12 @@ import { isValidPriceConfig } from './cpmBucketManager'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -import { hook } from './hook'; +import { parseQS } from './url'; + const utils = require('./utils'); +const CONSTANTS = require('./constants'); -const DEFAULT_DEBUG = false; +const DEFAULT_DEBUG = (parseQS(window.location.search)[CONSTANTS.DEBUG_MODE] || '').toUpperCase() === 'TRUE'; const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; @@ -231,7 +233,7 @@ export function newConfig() { * Sets configuration given an object containing key-value pairs and calls * listeners that were added by the `subscribe` function */ - let setConfig = hook('async', function setConfig(options) { + function setConfig(options) { if (typeof options !== 'object') { utils.logError('setConfig options must be an object'); return; @@ -251,7 +253,7 @@ export function newConfig() { }); callSubscribers(topicalConfig); - }); + } /** * Sets configuration defaults which setConfig values can be applied on top of diff --git a/src/utils.js b/src/utils.js index b5a46d174f4..09bb5435d56 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,8 +5,6 @@ import includes from 'core-js/library/fn/array/includes'; import { parse } from './url'; const CONSTANTS = require('./constants'); -var _loggingChecked = false; - var tArr = 'Array'; var tStr = 'String'; var tFn = 'Function'; @@ -354,12 +352,6 @@ export function hasConsoleLogger() { } export function debugTurnedOn() { - if (config.getConfig('debug') === false && _loggingChecked === false) { - const debug = getParameterByName(CONSTANTS.DEBUG_MODE).toUpperCase() === 'TRUE'; - config.setConfig({ debug }); - _loggingChecked = true; - } - return !!config.getConfig('debug'); } diff --git a/test/spec/debugging_spec.js b/test/spec/debugging_spec.js index d07f7fc3373..ba9702b0324 100644 --- a/test/spec/debugging_spec.js +++ b/test/spec/debugging_spec.js @@ -13,6 +13,7 @@ describe('bid overrides', function () { afterEach(function () { window.sessionStorage.clear(); + config.resetConfig(); sandbox.restore(); }); From 517c2526aaa0ad1eea901e1881d8c6f1f0d0ce21 Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Mon, 22 Jul 2019 21:11:58 -0400 Subject: [PATCH 1361/1594] Rubicon integration type (#4008) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * reverted error merge * Update Rubicon Bid and Analytics Adapters to read int_type from config * Unit tests for changes to Rubicon bid and analytics adapters --- modules/rubiconAnalyticsAdapter.js | 4 +-- modules/rubiconBidAdapter.js | 6 +++-- .../modules/rubiconAnalyticsAdapter_spec.js | 27 +++++++++++++++++++ test/spec/modules/rubiconBidAdapter_spec.js | 13 +++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index a00c727d470..e9e7daa59b3 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -28,7 +28,7 @@ config.getConfig('s2sConfig', ({s2sConfig}) => { }); export const SEND_TIMEOUT = 3000; -const INTEGRATION = 'pbjs'; +const DEFAULT_INTEGRATION = 'pbjs'; const cache = { auctions: {}, @@ -139,7 +139,7 @@ function sendMessage(auctionId, bidWonId) { let referrer = config.getConfig('pageUrl') || utils.getTopWindowUrl(); let message = { eventTimeMillis: Date.now(), - integration: INTEGRATION, + integration: config.getConfig('rubicon.int_type') || DEFAULT_INTEGRATION, version: '$prebid.version$', referrerUri: referrer }; diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index b4b8e98e393..d8b101b6318 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory'; import {config} from '../src/config'; import {BANNER, VIDEO} from '../src/mediaTypes'; -const INTEGRATION = 'pbjs_lite_v$prebid.version$'; +const DEFAULT_INTEGRATION = 'pbjs_lite'; function isSecure() { return location.protocol === 'https:'; @@ -385,6 +385,8 @@ export const spec = { const [latitude, longitude] = params.latLong || []; + const configIntType = config.getConfig('rubicon.int_type'); + const data = { 'account_id': params.accountId, 'site_id': params.siteId, @@ -394,7 +396,7 @@ export const spec = { 'p_pos': params.position === 'atf' || params.position === 'btf' ? params.position : 'unknown', 'rp_floor': (params.floor = parseFloat(params.floor)) > 0.01 ? params.floor : 0.01, 'rp_secure': isSecure() ? '1' : '0', - 'tk_flint': INTEGRATION, + 'tk_flint': `${configIntType || DEFAULT_INTEGRATION}_v$prebid.version$`, 'x_source.tid': bidRequest.transactionId, 'p_screen_res': _getScreenResolution(), 'kw': Array.isArray(params.keywords) ? params.keywords.join(',') : '', diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index c6b0ca8d29f..5fb7fd7bf79 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -728,4 +728,31 @@ describe('rubicon analytics adapter', function () { expect(bidResponseObj.bidPriceUSD).to.equal(1.0); }); }); + + describe('config with integration type', () => { + it('should use the integration type provided in the config instead of the default', () => { + sandbox.stub(config, 'getConfig').callsFake(function (key) { + const config = { + 'rubicon.int_type': 'testType' + }; + return config[key]; + }); + + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001 + } + }); + + performStandardAuction(); + + expect(requests.length).to.equal(1); + const request = requests[0]; + const message = JSON.parse(request.requestBody); + expect(message.integration).to.equal('testType'); + + rubiconAnalyticsAdapter.disableAnalytics(); + }); + }); }); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 0ad20001536..988b518f348 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -2011,6 +2011,19 @@ describe('the rubicon adapter', function () { expect(bids[0].height).to.equal(480); }); }); + + describe('config with integration type', () => { + it('should use the integration type provided in the config instead of the default', () => { + sandbox.stub(config, 'getConfig').callsFake(function (key) { + const config = { + 'rubicon.int_type': 'testType' + }; + return config[key]; + }); + const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(parseQuery(request.data).tk_flint).to.equal('testType_v$prebid.version$'); + }); + }); }); }); From 2ceeb38e3825c7979db7d19b6d88cd2e4af412d3 Mon Sep 17 00:00:00 2001 From: Catalin Ciocov Date: Tue, 23 Jul 2019 17:39:41 +0300 Subject: [PATCH 1362/1594] Inskin Bid Adapter - New Feature (#4011) * Add support for different publisher payment models. * Add Inskin integration example. * Append pubcpm to impression tracker. * Added unit tests for pubCMP vs clearPrice. --- integrationExamples/gpt/inskin_example.html | 102 ++++++++++++++++++++ modules/inskinBidAdapter.js | 9 +- test/spec/modules/inskinBidAdapter_spec.js | 10 ++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 integrationExamples/gpt/inskin_example.html diff --git a/integrationExamples/gpt/inskin_example.html b/integrationExamples/gpt/inskin_example.html new file mode 100644 index 00000000000..197a5b1ffe1 --- /dev/null +++ b/integrationExamples/gpt/inskin_example.html @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + +

    Prebid.js Test

    +
    Div-1
    +
    + +
    + + diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js index fbd87083b58..ae8eebcb7ae 100644 --- a/modules/inskinBidAdapter.js +++ b/modules/inskinBidAdapter.js @@ -116,9 +116,15 @@ export const spec = { if (serverResponse) { const decision = serverResponse.decisions && serverResponse.decisions[bidId]; - const price = decision && decision.pricing && decision.pricing.clearPrice; + const data = decision && decision.contents && decision.contents[0] && decision.contents[0].data; + const pubCPM = data && data.customData && data.customData.pubCPM; + const clearPrice = decision && decision.pricing && decision.pricing.clearPrice; + const price = pubCPM || clearPrice; if (decision && price) { + decision.impressionUrl += ('&property:pubcpm=' + price); + bidObj.price = price; + bid.requestId = bidId; bid.cpm = price; bid.width = decision.width; @@ -149,6 +155,7 @@ export const spec = { const id = 'ism_tag_' + Math.floor((Math.random() * 10e16)); window[id] = { bidId: e.data.bidId, + bidPrice: bidsMap[e.data.bidId].price, serverResponse }; const script = document.createElement('script'); diff --git a/test/spec/modules/inskinBidAdapter_spec.js b/test/spec/modules/inskinBidAdapter_spec.js index 8a62a465a5b..896fe36d443 100644 --- a/test/spec/modules/inskinBidAdapter_spec.js +++ b/test/spec/modules/inskinBidAdapter_spec.js @@ -82,6 +82,9 @@ const RESPONSE = { 'type': 'html', 'body': '', 'data': { + 'customData': { + 'pubCPM': 1 + }, 'height': 90, 'width': 728, 'imageUrl': 'https://static.adzerk.net/Advertisers/b0ab77db8a7848c8b78931aed022a5ef.gif', @@ -241,6 +244,13 @@ describe('InSkin BidAdapter', function () { }); }); + it('cpm is correctly set', function () { + let bids = spec.interpretResponse(RESPONSE, REQUEST); + + expect(bids[0].cpm).to.equal(0.5); + expect(bids[1].cpm).to.equal(1); + }); + it('handles nobid responses', function () { let EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {'decisions': null}}) let bids = spec.interpretResponse(EMPTY_RESP, REQUEST); From 2aa8846fd5081db5b22bb8de7dd940589356bb5b Mon Sep 17 00:00:00 2001 From: logicad Date: Wed, 24 Jul 2019 00:33:16 +0900 Subject: [PATCH 1363/1594] Add Logicad for Publishers bid adapter (#4010) * Add Logicad for Publishers bid adapter * Add test code --- modules/logicadBidAdapter.js | 68 +++++++++++ modules/logicadBidAdapter.md | 25 ++++ test/spec/modules/logicadBidAdapter_spec.js | 119 ++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 modules/logicadBidAdapter.js create mode 100644 modules/logicadBidAdapter.md create mode 100644 test/spec/modules/logicadBidAdapter_spec.js diff --git a/modules/logicadBidAdapter.js b/modules/logicadBidAdapter.js new file mode 100644 index 00000000000..65d765c30a3 --- /dev/null +++ b/modules/logicadBidAdapter.js @@ -0,0 +1,68 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER} from '../src/mediaTypes'; + +const BIDDER_CODE = 'logicad'; +const ENDPOINT_URL = 'https://pb.ladsp.com/adrequest/prebid'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + isBidRequestValid: function (bid) { + return !!(bid.params && bid.params.tid); + }, + buildRequests: function (bidRequests, bidderRequest) { + const requests = []; + for (let i = 0, len = bidRequests.length; i < len; i++) { + const request = { + method: 'POST', + url: ENDPOINT_URL, + data: JSON.stringify(newBidRequest(bidRequests[i], bidderRequest)), + options: {}, + bidderRequest + }; + requests.push(request); + } + return requests; + }, + interpretResponse: function (serverResponse, bidderRequest) { + serverResponse = serverResponse.body; + const bids = []; + if (!serverResponse || serverResponse.error) { + return bids; + } + serverResponse.seatbid.forEach(function (seatbid) { + bids.push(seatbid.bid); + }) + return bids; + }, + getUserSyncs: function (syncOptions, serverResponses) { + if (serverResponses.length > 0 && serverResponses[0].body.userSync && + syncOptions.pixelEnabled && serverResponses[0].body.userSync.type == 'image') { + return [{ + type: 'image', + url: serverResponses[0].body.userSync.url + }]; + } + return []; + }, +}; + +function newBidRequest(bid, bidderRequest) { + return { + auctionId: bid.auctionId, + bidderRequestId: bid.bidderRequestId, + bids: [{ + adUnitCode: bid.adUnitCode, + bidId: bid.bidId, + transactionId: bid.transactionId, + sizes: bid.sizes, + params: bid.params, + mediaTypes: bid.mediaTypes + }], + prebidJsVersion: '$prebid.version$', + referrer: bidderRequest.refererInfo.referer, + auctionStartTime: bidderRequest.auctionStart, + }; +} + +registerBidder(spec); diff --git a/modules/logicadBidAdapter.md b/modules/logicadBidAdapter.md new file mode 100644 index 00000000000..32d40a7d3cd --- /dev/null +++ b/modules/logicadBidAdapter.md @@ -0,0 +1,25 @@ +# Overview +``` +Module Name: Logicad for Publishers +Module Type: Bidder Adapter +Maintainer: prebid@so-netmedia.jp +``` + +# Description +Module that connects to Logicad's demand sources. +Currently module supports only banner mediaType. + +# Test Parameters +``` + var adUnits = [{ + code: 'test-code', + sizes: [[300, 250],[300, 600]], + bids: [{ + bidder: 'logicad', + params: { + tid: 'test', + page: 'url', + } + }] + }]; +``` diff --git a/test/spec/modules/logicadBidAdapter_spec.js b/test/spec/modules/logicadBidAdapter_spec.js new file mode 100644 index 00000000000..7d2916e3e0f --- /dev/null +++ b/test/spec/modules/logicadBidAdapter_spec.js @@ -0,0 +1,119 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/logicadBidAdapter'; +import * as utils from 'src/utils'; + +describe('LogicadAdapter', function () { + const bidRequests = [{ + bidder: 'logicad', + bidId: '51ef8751f9aead', + params: { + tid: 'PJ2P', + page: 'http://www.logicad.com/' + }, + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + sizes: [[300, 250], [300, 600]], + bidderRequestId: '418b37f85e772c', + auctionId: '18fd8b8b0bd757', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + } + }]; + const bidderRequest = { + refererInfo: { + referer: 'fakeReferer', + reachedTop: true, + numIframes: 1, + stack: [] + }, + auctionStart: 1563337198010 + }; + const serverResponse = { + body: { + seatbid: + [{ + bid: { + requestId: '51ef8751f9aead', + cpm: 101.0234, + width: 300, + height: 250, + creativeId: '2019', + currency: 'JPY', + netRevenue: true, + ttl: 60, + ad: '
    TEST
    ' + } + }], + userSync: { + type: 'image', + url: 'https://cr-p31.ladsp.jp/cookiesender/31' + } + } + }; + + describe('isBidRequestValid', function () { + it('should return true if the tid parameter is present', function () { + expect(spec.isBidRequestValid(bidRequests[0])).to.be.true; + }); + + it('should return false if the tid parameter is not present', function () { + let bidRequest = utils.deepClone(bidRequests[0]); + delete bidRequest.params.tid; + expect(spec.isBidRequestValid(bidRequest)).to.be.false; + }); + + it('should return false if the params object is not present', function () { + let bidRequest = utils.deepClone(bidRequests); + delete bidRequest[0].params; + expect(spec.isBidRequestValid(bidRequest)).to.be.false; + }); + }); + + describe('buildRequests', function () { + it('should generate a valid single POST request for multiple bid requests', function () { + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + expect(request.method).to.equal('POST'); + expect(request.url).to.equal('https://pb.ladsp.com/adrequest/prebid'); + expect(request.data).to.exist; + }); + }); + + describe('interpretResponse', function () { + it('should return an empty array if an invalid response is passed', function () { + const interpretedResponse = spec.interpretResponse({}, {}); + expect(interpretedResponse).to.be.an('array').that.is.empty; + }); + + it('should return valid response when passed valid server response', function () { + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; + const interpretedResponse = spec.interpretResponse(serverResponse, request); + + expect(interpretedResponse).to.have.lengthOf(1); + + expect(interpretedResponse[0].requestId).to.equal(serverResponse.body.seatbid[0].bid.requestId); + expect(interpretedResponse[0].cpm).to.equal(serverResponse.body.seatbid[0].bid.cpm); + expect(interpretedResponse[0].width).to.equal(serverResponse.body.seatbid[0].bid.width); + expect(interpretedResponse[0].height).to.equal(serverResponse.body.seatbid[0].bid.height); + expect(interpretedResponse[0].creativeId).to.equal(serverResponse.body.seatbid[0].bid.creativeId); + expect(interpretedResponse[0].currency).to.equal(serverResponse.body.seatbid[0].bid.currency); + expect(interpretedResponse[0].netRevenue).to.equal(serverResponse.body.seatbid[0].bid.netRevenue); + expect(interpretedResponse[0].ad).to.equal(serverResponse.body.seatbid[0].bid.ad); + expect(interpretedResponse[0].ttl).to.equal(serverResponse.body.seatbid[0].bid.ttl); + }); + }); + + describe('getUserSyncs', function () { + it('should perform usersync', function () { + let syncs = spec.getUserSyncs({pixelEnabled: false}, [serverResponse]); + expect(syncs).to.have.length(0); + console.log(serverResponse); + syncs = spec.getUserSyncs({pixelEnabled: true}, [serverResponse]); + expect(syncs).to.have.length(1); + + expect(syncs[0]).to.have.property('type', 'image'); + expect(syncs[0]).to.have.property('url', 'https://cr-p31.ladsp.jp/cookiesender/31'); + }); + }); +}); From 0663a8af0b9bcbcc9e477df2097e9a98a9bb7ae1 Mon Sep 17 00:00:00 2001 From: Igor Tchibirev Date: Tue, 23 Jul 2019 12:04:13 -0400 Subject: [PATCH 1364/1594] Realvu adapter: Remove _ps in _f=conf request (#3995) * Remove _ps in _f=conf request * Replace " * realvuAnalyticsAdapter_spec updated --- modules/realvuAnalyticsAdapter.js | 36 +++++++++---------- .../modules/realvuAnalyticsAdapter_spec.js | 23 ++++++++++++ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/modules/realvuAnalyticsAdapter.js b/modules/realvuAnalyticsAdapter.js index 64df6f655b7..51c5a106f1f 100644 --- a/modules/realvuAnalyticsAdapter.js +++ b/modules/realvuAnalyticsAdapter.js @@ -40,7 +40,7 @@ export let lib = { let z = this; let u = navigator.userAgent; z.device = u.match(/iPad|Tablet/gi) ? 'tablet' : u.match(/iPhone|iPod|Android|Opera Mini|IEMobile/gi) ? 'mobile' : 'desktop'; - if (typeof (z.len) == 'undefined') z.len = 0; // check, meybe too much, just make it len:0, + if (typeof (z.len) == 'undefined') z.len = 0; z.ie = navigator.appVersion.match(/MSIE/); z.saf = (u.match(/Safari/) && !u.match(/Chrome/)); z.ff = u.match(/Firefox/i); @@ -54,21 +54,20 @@ export let lib = { } } z.add_evt(window.top1, 'focus', function () { - window.top1.realvu_aa.foc = 1; /* window.top1.realvu_aa.log('focus',-1); */ + window.top1.realvu_aa.foc = 1; + }); + z.add_evt(window.top1, 'scroll', function () { + window.top1.realvu_aa.foc = 1; }); - // z.add_evt(window.top1, "scroll", function(){window.top1.realvu_aa.foc=1;window.top1.realvu_aa.log('scroll focus',-1);}); z.add_evt(window.top1, 'blur', function () { - window.top1.realvu_aa.foc = 0; /* window.top1.realvu_aa.log('blur',-1); */ + window.top1.realvu_aa.foc = 0; }); - // + http://www.w3.org/TR/page-visibility/ z.add_evt(window.top1.document, 'blur', function () { - window.top1.realvu_aa.foc = 0; /* window.top1.realvu_aa.log('blur',-1); */ + window.top1.realvu_aa.foc = 0; }); z.add_evt(window.top1, 'visibilitychange', function () { window.top1.realvu_aa.foc = !window.top1.document.hidden; - /* window.top1.realvu_aa.log('vis-ch '+window.top1.realvu_aa.foc,-1); */ }); - // - z.doLog = (window.top1.location.search.match(/boost_log/) || document.referrer.match(/boost_log/)) ? 1 : 0; if (z.doLog) { window.setTimeout(z.scr(window.top1.location.protocol + '//ac.realvu.net/realvu_aa_viz.js'), 500); @@ -84,11 +83,12 @@ export let lib = { update: function () { let z = this; - let de = window.top1.document.documentElement; - z.x1 = window.top1.pageXOffset ? window.top1.pageXOffset : de.scrollLeft; - z.y1 = window.top1.pageYOffset ? window.top1.pageYOffset : de.scrollTop; - let w1 = window.top1.innerWidth ? window.top1.innerWidth : de.clientWidth; - let h1 = window.top1.innerHeight ? window.top1.innerHeight : de.clientHeight; + let t = window.top1; + let de = t.document.documentElement; + z.x1 = t.pageXOffset ? t.pageXOffset : de.scrollLeft; + z.y1 = t.pageYOffset ? t.pageYOffset : de.scrollTop; + let w1 = t.innerWidth ? t.innerWidth : de.clientWidth; + let h1 = t.innerHeight ? t.innerHeight : de.clientHeight; z.x2 = z.x1 + w1; z.y2 = z.y1 + h1; }, @@ -152,7 +152,7 @@ export let lib = { let bk = z.beacons.shift(); while (typeof bk != 'undefined') { bk.s1 = bk.s1.replace(/_sr=0*_/, '_sr=' + z.sr + '_'); - z.log(' ' + bk.a.riff + ' ' + bk.a.unit_id + /* " "+pin.mode+ */ ' ' + bk.a.w + 'x' + bk.a.h + '@' + bk.a.x + ',' + bk.a.y + + z.log(' ' + bk.a.riff + ' ' + bk.a.unit_id + /* ' '+pin.mode+ */ ' ' + bk.a.w + 'x' + bk.a.h + '@' + bk.a.x + ',' + bk.a.y + ' ' + bk.f + '', bk.a.num); if (bk.a.rnd < Math.pow(10, 1 - (z.sr.charCodeAt(0) & 7))) { z.scr(bk.s1, bk.a); @@ -181,8 +181,8 @@ export let lib = { '_f=' + f + '_r=' + a.riff + '_s=' + a.w + 'x' + a.h; if (a.p) s2 += '_p=' + a.p; - s2 += '_ps=' + this.enc(a.unit_id) + // 08-Jun-15 - _p= is replaced with _ps= - p-number, ps-string - '_dv=' + this.device + + if (f != 'conf') s2 += '_ps=' + this.enc(a.unit_id); + s2 += '_dv=' + this.device + // + '_a=' + this.enc(a.a) '_d=' + pin.mode + '_sr=' + this.sr + @@ -191,7 +191,7 @@ export let lib = { }, enc: function (s1) { - // return escape(s1).replace(/[0-9a-f]{5,}/gi,'RANDOM').replace(/\*/g, "%2A").replace(/_/g, "%5F").replace(/\+/g, + // return escape(s1).replace(/[0-9a-f]{5,}/gi,'RANDOM').replace(/\*/g, '%2A').replace(/_/g, '%5F').replace(/\+/g, return escape(s1).replace(/\*/g, '%2A').replace(/_/g, '%5F').replace(/\+/g, '%2B').replace(/\./g, '%2E').replace(/\x2F/g, '%2F'); }, @@ -467,7 +467,7 @@ export let lib = { return null; }, - doc: function(f) { // return document of f-iframe, keep here "n" as a parameter because of call from setTimeout() + doc: function(f) { // return document of f-iframe let d = null; try { if (f.contentDocument) d = f.contentDocument; // DOM diff --git a/test/spec/modules/realvuAnalyticsAdapter_spec.js b/test/spec/modules/realvuAnalyticsAdapter_spec.js index 1aa1c4be8a5..359fb329359 100644 --- a/test/spec/modules/realvuAnalyticsAdapter_spec.js +++ b/test/spec/modules/realvuAnalyticsAdapter_spec.js @@ -164,5 +164,28 @@ describe('RealVu', function() { let r = boost.readPos(a); expect(r).to.equal(true); }); + + it('send_track', function () { + const a = boost.ads[boost.len - 1]; + boost.track(a, 'show', ''); + boost.sr = 'a'; + boost.send_track(); + expect(boost.beacons.length).to.equal(0); + }); + + it('questA text', function () { + let p = document.createElement('p'); + p.innerHTML = 'ABC'; + document.body.appendChild(p); + let r = boost.questA(p.firstChild); + document.body.removeChild(p); + expect(r).to.not.equal(null); + }); + + it('_f=conf', function () { + const a = boost.ads[boost.len - 1]; + let r = boost.tru(a, 'conf'); + expect(r).to.not.include('_ps='); + }); }); }); From 5dfdd8acd060f8446f9ce76ddb391cc570364a5a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 23 Jul 2019 12:33:57 -0400 Subject: [PATCH 1365/1594] init as empty object (#4017) --- modules/dfpAdServerVideo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 1614dbe6b0d..6f3c23f1f3d 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -161,7 +161,7 @@ export function buildAdpodVideoUrl({code, params, callback} = {}) { [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: undefined, [adpodUtils.TARGETING_KEY_CACHE_ID]: undefined } - let customParams; + let customParams = {}; if (targeting[code]) { customParams = targeting[code].reduce((acc, curValue) => { if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_PB_CAT_DUR) { From 99132d8b5c9a22cc1625587b2edae26e555aa953 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 23 Jul 2019 15:07:40 -0400 Subject: [PATCH 1366/1594] Prebid 2.25.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1cc2da9abc2..9696efefabb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.25.0-pre", + "version": "2.25.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3a7590ac7148d863a0e845e8591b3a2c97e35b3e Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 23 Jul 2019 15:25:55 -0400 Subject: [PATCH 1367/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9696efefabb..db638ee7baa 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.25.0", + "version": "2.26.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4a3372d9e4bd7b0495e22c15c24f6fba47954eeb Mon Sep 17 00:00:00 2001 From: Chris Cole Date: Tue, 23 Jul 2019 13:57:03 -0700 Subject: [PATCH 1368/1594] DigiTrust Facade init GH Issue 3911 (#3918) * GH Issue 3911 Fix to init the DigiTrust facade object if the userId framework would not normally execute the call due to an ID being found. * Fixed superfluous trailing arg issue. * Addition of unit test for digiTrustIdSystem. Fix init error in facade callback. * Uncommenting init code. * Reverting package-lock.json file. * Removed extraneous function parameter. * Removing unused code. Fixing file casing issue causing unit test to fail. * Adding support for SameSite=none to cookie * Tweaking unit test. * Removing Promise from unit test as IE doesn't like it. * Cleanup of unused code lines * Minor comment changes. * Commenting out unit tests to see if this fixes Safari timeout issue. * Reenable test. Fixing where done was not being called. * Whitespace changes for lint * Capture and clear fallback timer to fix unit tests. * Removing unused function * Comment improvements. Retry CircleCI for unassociated failure. * Removed old call to attachIdSystem. --- modules/digiTrustIdSystem.js | 36 ++++++++++++--- modules/digiTrustIdSystem.md | 5 ++- test/spec/modules/digitrustIdSystem_spec.js | 50 +++++++++++++++++++++ 3 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 test/spec/modules/digitrustIdSystem_spec.js diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index 1db65031848..17f6fd9f737 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -9,11 +9,12 @@ * @requires module:modules/userId */ -// import { config } from 'src/config'; import * as utils from '../src/utils' import { ajax } from '../src/ajax'; import { submodule } from '../src/hook'; -// import { getGlobal } from 'src/prebidGlobal'; + +var fallbackTimeout = 1550; // timeout value that allows userId system to execute first +var fallbackTimer = 0; // timer Id for fallback init so we don't double call /** * Checks to see if the DigiTrust framework is initialized. @@ -81,7 +82,7 @@ function writeDigiId(id) { var date = new Date(); date.setTime(date.getTime() + 604800000); var exp = 'expires=' + date.toUTCString(); - document.cookie = key + '=' + encId(id) + '; ' + exp + '; path=/;'; + document.cookie = key + '=' + encId(id) + '; ' + exp + '; path=/;SameSite=none;'; } /** @@ -90,6 +91,10 @@ function writeDigiId(id) { */ function initDigitrustFacade(config) { var _savedId = null; // closure variable for storing Id to avoid additional requests + + clearTimeout(fallbackTimer); + fallbackTimer = 0; + var facade = { isClient: true, isMock: true, @@ -162,6 +167,10 @@ function initDigitrustFacade(config) { } } + if (config && isFunc(config.callback)) { + facade._internals.initCallback = config.callback; + } + if (window && window.DigiTrust == null) { window.DigiTrust = facade; } @@ -306,11 +315,12 @@ var testHook = {}; * Exposes the test hook object by attaching to the digitrustIdModule. * This method is called in the unit tests to surface internals. */ -function surfaceTestHook() { - digitrustIdModule['_testHook'] = testHook; +export function surfaceTestHook() { + digiTrustIdSubmodule['_testHook'] = testHook; + return testHook; } -testHook.initDigitrustFacade = initDigitrustFacade; +testHook.initDigitrustFacade = initDigitrustFacade; // expose for unit tests /** @type {Submodule} */ export const digiTrustIdSubmodule = { @@ -336,4 +346,18 @@ export const digiTrustIdSubmodule = { _testInit: surfaceTestHook }; +// check for fallback init of DigiTrust +function fallbackInit() { + if (resultHandler.retryId == 0 && !isInitialized()) { + // this triggers an init + var conf = { + member: 'fallback', + callback: noop + }; + getDigiTrustId(conf); + } +} + +fallbackTimer = setTimeout(fallbackInit, fallbackTimeout); + submodule('userId', digiTrustIdSubmodule); diff --git a/modules/digiTrustIdSystem.md b/modules/digiTrustIdSystem.md index 6ddbad4aea4..c0b274d3292 100644 --- a/modules/digiTrustIdSystem.md +++ b/modules/digiTrustIdSystem.md @@ -24,7 +24,9 @@ for further instructions. site: 'example_site_id' }, callback: function (digiTrustResult) { - // This callback method is optional + // This callback method is optional and used for error handling + // in many if not most cases. + /* if (digiTrustResult.success) { // Success in Digitrust init; // 'DigiTrust Id (encrypted): ' + digiTrustResult.identity.id; @@ -32,6 +34,7 @@ for further instructions. else { // Digitrust init failed } + */ } }, storage: { diff --git a/test/spec/modules/digitrustIdSystem_spec.js b/test/spec/modules/digitrustIdSystem_spec.js new file mode 100644 index 00000000000..55035bc4b4e --- /dev/null +++ b/test/spec/modules/digitrustIdSystem_spec.js @@ -0,0 +1,50 @@ +import { + digiTrustIdSubmodule, + surfaceTestHook +} from 'modules/digiTrustIdSystem'; + +let assert = require('chai').assert; +let expect = require('chai').expect; + +var testHook = null; + +describe('DigiTrust Id System', function () { + it('Should create the test hook', function (done) { + testHook = surfaceTestHook(); + assert.isNotNull(testHook, 'The test hook failed to surface'); + var conf = { + init: { + member: 'unit_test', + site: 'foo' + }, + callback: function (result) { + } + }; + testHook.initDigitrustFacade(conf); + window.DigiTrust.getUser(conf); + expect(window.DigiTrust).to.exist; + expect(window.DigiTrust.isMock).to.be.true; + done(); + }); + + it('Should report as client', function (done) { + delete window.DigiTrust; + testHook = surfaceTestHook(); + + var conf = { + init: { + member: 'unit_test', + site: 'foo' + }, + callback: function (result) { + expect(window.DigiTrust).to.exist; + expect(result).to.exist; + expect(window.DigiTrust.isMock).to.be.true; + } + }; + testHook.initDigitrustFacade(conf); + expect(window.DigiTrust).to.exist; + expect(window.DigiTrust.isClient).to.be.true; + done(); + }); +}); From 05cf0d2bceae6ec7d3fbfbe4ca82969cc4764618 Mon Sep 17 00:00:00 2001 From: mamatic <52153441+mamatic@users.noreply.github.com> Date: Tue, 23 Jul 2019 23:00:08 +0200 Subject: [PATCH 1369/1594] Integrate id link system (#3965) * idLink - integrate new submodule idLinkSystem in to userId module * idLink - Fix unit tests * identityLink - Change submodule name from idLink to identityLink * Identity Link - Remove identity link to be default submodule --- integrationExamples/gpt/userId_example.html | 10 ++ modules/identityLinkSystem.js | 58 +++++++++++ modules/userId/index.js | 1 + modules/userId/userId.md | 20 ++++ test/spec/modules/userId_spec.js | 107 ++++++++++++++++---- 5 files changed, 175 insertions(+), 21 deletions(-) create mode 100644 modules/identityLinkSystem.js diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index febe61628fe..5878d05aecd 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -162,6 +162,16 @@ // foo: '9879878907987', // bar:'93939' // } + }, { + name: 'identityLink', + params: { + pid: '14' // Set your real identityLink placement ID here + }, + storage: { + type: 'cookie', + name: 'idl_env', + expires: 60 + } }], syncDelay: 5000 } diff --git a/modules/identityLinkSystem.js b/modules/identityLinkSystem.js new file mode 100644 index 00000000000..8b8fa491bad --- /dev/null +++ b/modules/identityLinkSystem.js @@ -0,0 +1,58 @@ +/** + * This module adds IdentityLink to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/identityLinkSubmodule + * @requires module:modules/userId + */ + +import * as utils from '../src/utils.js' +import {ajax} from '../src/ajax.js'; +import {submodule} from '../src/hook'; + +/** @type {Submodule} */ +export const identityLinkSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'identityLink', + /** + * decode the stored id value for passing to bid requests + * @function + * @param {string} value + * @returns {{idl_env:string}} + */ + decode(value) { + return { 'idl_env': value } + }, + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @param {SubmoduleParams} [configParams] + * @returns {function(callback:function)} + */ + getId(configParams) { + if (!configParams || typeof configParams.pid !== 'string') { + utils.logError('identityLink submodule requires partner id to be defined'); + return; + } + // use protocol relative urls for http or https + const url = `https://api.rlcdn.com/api/identity?pid=${configParams.pid}&rt=envelope`; + + return function (callback) { + ajax(url, response => { + let responseObj; + if (response) { + try { + responseObj = JSON.parse(response); + } catch (error) { + utils.logError(error); + } + } + callback(responseObj.envelope); + }, undefined, { method: 'GET' }); + } + } +}; + +submodule('userId', identityLinkSubmodule); diff --git a/modules/userId/index.js b/modules/userId/index.js index 16421e39e20..98d99f7d333 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -50,6 +50,7 @@ * @typedef {Object} SubmoduleParams * @property {(string|undefined)} partner - partner url param value * @property {(string|undefined)} url - webservice request url used to load Id data + * @property {(string|undefined)} pid - placement id url param value */ /** diff --git a/modules/userId/userId.md b/modules/userId/userId.md index cd7aaf92d39..04bd34d13b9 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -32,6 +32,16 @@ pbjs.setConfig({ name: "id5id", expires: 5 } + }, { + name: 'identityLink', + params: { + pid: '999' // Set your real identityLink placement ID here + }, + storage: { + type: 'cookie', + name: 'idl_env', + expires: 60 + } }], syncDelay: 5000 } @@ -60,6 +70,16 @@ pbjs.setConfig({ name: "pubcid", expires: 60 } + }, { + name: 'identityLink', + params: { + pid: '999' // Set your real identityLink placement ID here + }, + storage: { + type: 'html5', + name: 'idl_env', + expires: 60 + } }], syncDelay: 5000 } diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index a158d2e9fed..b581873089a 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -10,19 +10,21 @@ import * as utils from 'src/utils'; import {unifiedIdSubmodule} from 'modules/userId/unifiedIdSystem'; import {pubCommonIdSubmodule} from 'modules/userId/pubCommonIdSystem'; import {id5IdSubmodule} from 'modules/id5IdSystem'; +import {identityLinkSubmodule} from 'modules/identityLinkSystem'; let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; describe('User ID', function() { - function getConfigMock(configArr1, configArr2, configArr3) { + function getConfigMock(configArr1, configArr2, configArr3, configArr4) { return { userSync: { syncDelay: 0, userIds: [ (configArr1 && configArr1.length === 3) ? getStorageMock.apply(null, configArr1) : null, (configArr2 && configArr2.length === 3) ? getStorageMock.apply(null, configArr2) : null, - (configArr3 && configArr3.length === 3) ? getStorageMock.apply(null, configArr3) : null + (configArr3 && configArr3.length === 3) ? getStorageMock.apply(null, configArr3) : null, + (configArr4 && configArr4.length === 3) ? getStorageMock.apply(null, configArr4) : null ].filter(i => i)} } } @@ -70,7 +72,7 @@ describe('User ID', function() { let pubcid = utils.getCookie('pubcid'); expect(pubcid).to.be.null; // there should be no cookie initially - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); @@ -96,7 +98,7 @@ describe('User ID', function() { let pubcid1; let pubcid2; - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); @@ -110,7 +112,7 @@ describe('User ID', function() { }); }); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); @@ -131,7 +133,7 @@ describe('User ID', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie'])); requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); @@ -166,14 +168,14 @@ describe('User ID', function() { }); it('fails initialization if opt out cookie exists', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); 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 () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); @@ -192,7 +194,7 @@ describe('User ID', function() { }); it('handles config with no usersync object', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig({}); // usersync is undefined, and no logInfo message for 'User ID - usersync config updated' @@ -200,14 +202,14 @@ describe('User ID', function() { }); it('handles config with empty usersync object', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); 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([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig({ usersync: { @@ -218,7 +220,7 @@ describe('User ID', function() { }); it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig({ usersync: { @@ -235,15 +237,15 @@ describe('User ID', function() { }); it('config with 1 configurations should create 1 submodules', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); }); - it('config with 3 configurations should result in 3 submodules add', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + it('config with 4 configurations should result in 4 submodules add', function () { + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig({ usersync: { @@ -256,14 +258,17 @@ describe('User ID', function() { }, { name: 'id5Id', storage: { name: 'id5id', type: 'cookie' } + }, { + name: 'identityLink', + storage: { name: 'idl_env', type: 'cookie' } }] } }); - expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 3 submodules'); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 4 submodules'); }); it('config syncDelay updates module correctly', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig({ usersync: { @@ -349,6 +354,46 @@ describe('User ID', function() { }, {adUnits}); }); + it('test hook from identityLink html5', function(done) { + // simulate existing browser local storage values + localStorage.setItem('idl_env', 'AiGNC8Z5ONyZKSpIPf'); + localStorage.setItem('idl_env_exp', ''); + + setSubmoduleRegistry([identityLinkSubmodule]); + init(config); + config.setConfig(getConfigMock(['identityLink', 'idl_env', 'html5'])); + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.idl_env'); + expect(bid.userId.idl_env).to.equal('AiGNC8Z5ONyZKSpIPf'); + }); + }); + localStorage.removeItem('idl_env'); + localStorage.removeItem('idl_env_exp'); + done(); + }, {adUnits}); + }); + + it('test hook from identityLink cookie', function(done) { + utils.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 100000).toUTCString())); + + setSubmoduleRegistry([identityLinkSubmodule]); + init(config); + config.setConfig(getConfigMock(['identityLink', 'idl_env', 'cookie'])); + + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.idl_env'); + expect(bid.userId.idl_env).to.equal('AiGNC8Z5ONyZKSpIPf'); + }); + }); + utils.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + it('test hook from id5id cookies', function(done) { // simulate existing browser local storage values utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -373,12 +418,14 @@ describe('User ID', function() { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'], - ['id5Id', 'id5id', 'cookie'])); + ['id5Id', 'id5id', 'cookie'], + ['identityLink', 'idl_env', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -392,11 +439,15 @@ describe('User ID', function() { // also check that Id5Id id data was copied to bid expect(bid).to.have.deep.nested.property('userId.id5id'); expect(bid.userId.id5id).to.equal('testid5id'); + // 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'); }); }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + utils.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -405,6 +456,7 @@ describe('User ID', function() { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); setSubmoduleRegistry([]); @@ -416,10 +468,12 @@ describe('User ID', function() { // attaching after init attachIdSystem(unifiedIdSubmodule); attachIdSystem(id5IdSubmodule); + attachIdSystem(identityLinkSubmodule); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'], - ['id5Id', 'id5id', 'cookie'])); + ['id5Id', 'id5id', 'cookie'], + ['identityLink', 'idl_env', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -433,11 +487,15 @@ describe('User ID', function() { // also check that Id5Id id data was copied to bid expect(bid).to.have.deep.nested.property('userId.id5id'); expect(bid.userId.id5id).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'); }); }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + utils.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -446,9 +504,10 @@ describe('User ID', function() { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); utils.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig({ @@ -460,6 +519,8 @@ describe('User ID', function() { name: 'unifiedId', storage: { name: 'unifiedid', type: 'cookie' } }, { name: 'id5Id', storage: { name: 'id5id', type: 'cookie' } + }, { + name: 'identityLink', storage: { name: 'idl_env', type: 'cookie' } }, { name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } }] @@ -491,6 +552,9 @@ describe('User ID', function() { // also check that Id5Id id data was copied to bid expect(bid).to.have.deep.nested.property('userId.id5id'); expect(bid.userId.id5id).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'); // check MockId data was copied to bid expect(bid).to.have.deep.nested.property('userId.mid'); expect(bid.userId.mid).to.equal('123456778'); @@ -499,6 +563,7 @@ describe('User ID', function() { utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + utils.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); utils.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); From c2bdb94ca20af4a0d8b7daba5c68700dc3dfd582 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 23 Jul 2019 15:56:25 -0700 Subject: [PATCH 1370/1594] Update rubicon analytics adapter with wrapper name (#3990) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * changed to only send wrapperName with event when it has a value * changed wrapperName to use value from config 'rubicon.wrapperName' * update tests for wrapperName * update wrapperName as let for consistency * updated wrapperName from let to const --- modules/rubiconAnalyticsAdapter.js | 4 ++++ test/spec/modules/rubiconAnalyticsAdapter_spec.js | 6 +++++- test/spec/modules/rubiconAnalyticsSchema.json | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index e9e7daa59b3..b165741b49d 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -143,6 +143,10 @@ function sendMessage(auctionId, bidWonId) { version: '$prebid.version$', referrerUri: referrer }; + const wrapperName = config.getConfig('rubicon.wrapperName'); + if (wrapperName) { + message.wrapperName = wrapperName; + } let auctionCache = cache.auctions[auctionId]; if (auctionCache && !auctionCache.sent) { let adUnitMap = Object.keys(auctionCache.bids).reduce((adUnits, bidId) => { diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 5fb7fd7bf79..9c005c3394f 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -453,7 +453,8 @@ const ANALYTICS_MESSAGE = { }, 'bidwonStatus': 'success' } - ] + ], + 'wrapperName': '10000_fakewrapper_test' }; function performStandardAuction() { @@ -492,6 +493,9 @@ describe('rubicon analytics adapter', function () { s2sConfig: { timeout: 1000, accountId: 10000, + }, + rubicon: { + wrapperName: '10000_fakewrapper_test' } }) }); diff --git a/test/spec/modules/rubiconAnalyticsSchema.json b/test/spec/modules/rubiconAnalyticsSchema.json index b856bf584e9..686aced840f 100644 --- a/test/spec/modules/rubiconAnalyticsSchema.json +++ b/test/spec/modules/rubiconAnalyticsSchema.json @@ -191,6 +191,9 @@ } ] } + }, + "wrapperName": { + "type": "string" } }, "definitions": { From bfc12a1d7acacc8a774e4da974d1df3a61b7406d Mon Sep 17 00:00:00 2001 From: PWyrembak Date: Wed, 24 Jul 2019 22:29:03 +0300 Subject: [PATCH 1371/1594] TrustX Bid Adapter updating to use referrerInfo (#3972) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Add support of gdpr to Trustx Bid Adapter * Add wtimeout to ad request params for TrustX Bid Adapter * TrustX Bid Adapter: remove last ampersand in the ad request * Update TrustX Bid Adapter to support identical uids in parameters * Update TrustX Bid Adapter to ignore bids that sizes do not match the size of the request * Update TrustX Bid Adapter to support instream and outstream video * Added wrapperType and wrapperVersion parameters in ad request for TrustX Bid Adapter * Update TrustX Bid Adapter to use refererInfo instead depricated function utils.getTopWindowUrl --- modules/trustxBidAdapter.js | 4 ++- test/spec/modules/trustxBidAdapter_spec.js | 33 ++++++++++++++-------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index 1a501faf74b..e9eb175671e 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -84,7 +84,6 @@ export const spec = { }); const payload = { - u: utils.getTopWindowUrl(), pt: priceType, auids: auids.join(','), sizes: utils.getKeys(sizeMap).join(','), @@ -94,6 +93,9 @@ export const spec = { }; if (bidderRequest) { + if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + } if (bidderRequest.timeout) { payload.wtimeout = bidderRequest.timeout; } diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index a15ae94cfad..0a4fddcb852 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -47,6 +47,14 @@ describe('TrustXAdapter', function () { }); return res; } + + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; + const encodedReferer = encodeURIComponent(bidderRequest.refererInfo.referer); + let bidRequests = [ { 'bidder': 'trustx', @@ -84,10 +92,10 @@ describe('TrustXAdapter', function () { ]; it('should attach valid params to the tag', function () { - const request = spec.buildRequests([bidRequests[0]]); + const request = spec.buildRequests([bidRequests[0]], bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43'); expect(payload).to.have.property('sizes', '300x250,300x600'); @@ -97,10 +105,10 @@ describe('TrustXAdapter', function () { }); it('sizes must not be duplicated', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferer); 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'); @@ -109,10 +117,10 @@ describe('TrustXAdapter', function () { it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferer); 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'); @@ -122,10 +130,10 @@ describe('TrustXAdapter', function () { it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferer); 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'); @@ -134,7 +142,8 @@ describe('TrustXAdapter', function () { }); it('if gdprConsent is present payload must have gdpr params', function () { - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); + const bidderRequestWithGDPR = Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: true}}, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('gdpr_consent', 'AAA'); @@ -142,7 +151,8 @@ describe('TrustXAdapter', function () { }); it('if gdprApplies is false gdpr_applies must be 0', function () { - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); + const bidderRequestWithGDPR = Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: false}}, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('gdpr_consent', 'AAA'); @@ -150,7 +160,8 @@ describe('TrustXAdapter', function () { }); it('if gdprApplies is undefined gdpr_applies must be 1', function () { - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); + const bidderRequestWithGDPR = Object.assign({gdprConsent: {consentString: 'AAA'}}, bidderRequest); + const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); expect(payload).to.have.property('gdpr_consent', 'AAA'); From df7020b79f3c9d8747276bc6a0cfcb12cfc5ccfa Mon Sep 17 00:00:00 2001 From: Denis Logachov Date: Wed, 24 Jul 2019 22:45:05 +0300 Subject: [PATCH 1372/1594] Adkernel adapter minor update (#4000) * Updated maintainer email * Minor refactoring & more unit tests * Unit tests for new utility function --- modules/adkernelBidAdapter.js | 37 ++++++----- modules/adkernelBidAdapter.md | 64 +++++++++--------- src/utils.js | 18 +++++- test/spec/modules/adkernelBidAdapter_spec.js | 68 +++++++++++++++++--- test/spec/utils_spec.js | 50 ++++++++++++++ 5 files changed, 178 insertions(+), 59 deletions(-) diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 254887dad81..02b9d2a7967 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -19,21 +19,24 @@ export const spec = { aliases: ['headbidding'], supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bidRequest) { - return 'params' in bidRequest && typeof bidRequest.params.host !== 'undefined' && - 'zoneId' in bidRequest.params && !isNaN(Number(bidRequest.params.zoneId)) && - bidRequest.mediaTypes && (bidRequest.mediaTypes.banner || bidRequest.mediaTypes.video); + return 'params' in bidRequest && + typeof bidRequest.params.host !== 'undefined' && + 'zoneId' in bidRequest.params && + !isNaN(Number(bidRequest.params.zoneId)) && + bidRequest.params.zoneId > 0 && + bidRequest.mediaTypes && + (bidRequest.mediaTypes.banner || bidRequest.mediaTypes.video); }, buildRequests: function(bidRequests, bidderRequest) { let impDispatch = dispatchImps(bidRequests, bidderRequest.refererInfo); - const gdprConsent = bidderRequest.gdprConsent; - const auctionId = bidderRequest.auctionId; + const {gdprConsent, auctionId} = bidderRequest; const requests = []; Object.keys(impDispatch).forEach(host => { Object.keys(impDispatch[host]).forEach(zoneId => { const request = buildRtbRequest(impDispatch[host][zoneId], auctionId, gdprConsent, bidderRequest.refererInfo); requests.push({ method: 'POST', - url: `${window.location.protocol}//${host}/hb?zone=${Number(zoneId)}&v=${VERSION}`, + url: `${window.location.protocol}//${host}/hb?zone=${zoneId}&v=${VERSION}`, data: JSON.stringify(request) }); }); @@ -47,13 +50,12 @@ export const spec = { } let rtbRequest = JSON.parse(request.data); - let rtbImps = rtbRequest.imp; let rtbBids = response.seatbid .map(seatbid => seatbid.bid) .reduce((a, b) => a.concat(b), []); return rtbBids.map(rtbBid => { - let imp = find(rtbImps, imp => imp.id === rtbBid.impid); + let imp = find(rtbRequest.imp, imp => imp.id === rtbBid.impid); let prBid = { requestId: rtbBid.impid, cpm: rtbBid.price, @@ -119,19 +121,16 @@ function buildImp(bidRequest, secure) { if (utils.deepAccess(bidRequest, `mediaTypes.banner`)) { let sizes = canonicalizeSizesArray(bidRequest.mediaTypes.banner.sizes); imp.banner = { - format: sizes.map(s => ({'w': s[0], 'h': s[1]})), + format: sizes.map(wh => utils.parseGPTSingleSizeArrayToRtbSize(wh)), topframe: 0 }; } else if (utils.deepAccess(bidRequest, 'mediaTypes.video')) { let size = canonicalizeSizesArray(bidRequest.mediaTypes.video.playerSize)[0]; - imp.video = { - w: size[0], - h: size[1] - }; + imp.video = utils.parseGPTSingleSizeArrayToRtbSize(size); if (bidRequest.params.video) { Object.keys(bidRequest.params.video) - .filter(param => includes(VIDEO_TARGETING, param)) - .forEach(param => imp.video[param] = bidRequest.params.video[param]); + .filter(key => includes(VIDEO_TARGETING, key)) + .forEach(key => imp.video[key] = bidRequest.params.video[key]); } } if (secure) { @@ -198,18 +197,18 @@ function getLanguage() { */ function createSite(refInfo) { let url = parseUrl(refInfo.referer); - let result = { + let site = { 'domain': url.hostname, 'page': url.protocol + '://' + url.hostname + url.pathname }; if (self === top && document.referrer) { - result.ref = document.referrer; + site.ref = document.referrer; } let keywords = document.getElementsByTagName('meta')['keywords']; if (keywords && keywords.content) { - result.keywords = keywords.content; + site.keywords = keywords.content; } - return result; + return site; } /** diff --git a/modules/adkernelBidAdapter.md b/modules/adkernelBidAdapter.md index 902be481473..f89fa5a26df 100644 --- a/modules/adkernelBidAdapter.md +++ b/modules/adkernelBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: AdKernel Bidder Adapter Module Type: Bidder Adapter -Maintainer: denis@adkernel.com +Maintainer: prebid-dev@adkernel.com ``` # Description @@ -14,32 +14,38 @@ Banner and video formats are supported. # Test Parameters ``` - var adUnits = [ - { - code: 'banner-ad-div', - sizes: [[300, 250]], // banner size - bids: [ - { - bidder: 'adkernel', - params: { - zoneId: '30164', //required parameter - host: 'cpm.metaadserving.com' //required parameter - } - } - ] - }, { - code: 'video-ad-player', - sizes: [640, 480], // video player size - bids: [ - { - bidder: 'adkernel', - mediaType : 'video', - params: { - zoneId: '30164', //required parameter - host: 'cpm.metaadserving.com' //required parameter - } - } - ] - } - ]; + var adUnits = [{ + code: 'banner-ad-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], // banner size + } + }, + bids: [ + { + bidder: 'adkernel', + params: { + zoneId: '30164', //required parameter + host: 'cpm.metaadserving.com' //required parameter + } + } + ] + }, { + code: 'video-ad-player', + mediaTypes: { + video: { + context: 'instream', // or 'outstream' + playerSize: [640, 480] // video player size + } + }, + bids: [ + { + bidder: 'adkernel', + params: { + zoneId: '30164', //required parameter + host: 'cpm.metaadserving.com' //required parameter + } + } + ] + }]; ``` diff --git a/src/utils.js b/src/utils.js index 09bb5435d56..4da24e12968 100644 --- a/src/utils.js +++ b/src/utils.js @@ -219,15 +219,27 @@ export function parseSizesInput(sizeObj) { return parsedSizes; } -// parse a GPT style sigle size array, (i.e [300,250]) +// Parse a GPT style single size array, (i.e [300, 250]) // into an AppNexus style string, (i.e. 300x250) export function parseGPTSingleSizeArray(singleSize) { - // if we aren't exactly 2 items in this array, it is invalid - if (isArray(singleSize) && singleSize.length === 2 && (!isNaN(singleSize[0]) && !isNaN(singleSize[1]))) { + if (isValidGPTSingleSize(singleSize)) { return singleSize[0] + 'x' + singleSize[1]; } } +// Parse a GPT style single size array, (i.e [300, 250]) +// into OpenRTB-compatible (imp.banner.w/h, imp.banner.format.w/h, imp.video.w/h) object(i.e. {w:300, h:250}) +export function parseGPTSingleSizeArrayToRtbSize(singleSize) { + if (isValidGPTSingleSize(singleSize)) { + return {w: singleSize[0], h: singleSize[1]}; + } +} + +function isValidGPTSingleSize(singleSize) { + // if we aren't exactly 2 items in this array, it is invalid + return isArray(singleSize) && singleSize.length === 2 && (!isNaN(singleSize[0]) && !isNaN(singleSize[1])); +} + /** * @deprecated This function will be removed soon. Use http://prebid.org/dev-docs/bidder-adaptor.html#referrers */ diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index 1d2d2215f02..a00f07603ee 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -5,9 +5,11 @@ import * as utils from 'src/utils'; describe('Adkernel adapter', function () { const bid1_zone1 = { bidder: 'adkernel', - bidId: 'Bid_01', params: {zoneId: 1, host: 'rtb.adkernel.com'}, adUnitCode: 'ad-unit-1', + bidId: 'Bid_01', + bidderRequestId: 'req-001', + auctionId: 'auc-001', mediaTypes: { banner: { sizes: [[300, 250], [300, 200]] @@ -15,19 +17,23 @@ describe('Adkernel adapter', function () { } }, bid2_zone2 = { bidder: 'adkernel', - bidId: 'Bid_02', params: {zoneId: 2, host: 'rtb.adkernel.com'}, adUnitCode: 'ad-unit-2', + bidId: 'Bid_02', + bidderRequestId: 'req-001', + auctionId: 'auc-001', mediaTypes: { banner: { - sizes: [728, 90] + sizes: [[728, 90]] } } }, bid3_host2 = { bidder: 'adkernel', - bidId: 'Bid_02', params: {zoneId: 1, host: 'rtb-private.adkernel.com'}, adUnitCode: 'ad-unit-2', + bidId: 'Bid_02', + bidderRequestId: 'req-001', + auctionId: 'auc-001', mediaTypes: { banner: { sizes: [[728, 90]] @@ -35,9 +41,11 @@ describe('Adkernel adapter', function () { } }, bid_without_zone = { bidder: 'adkernel', - bidId: 'Bid_W', params: {host: 'rtb-private.adkernel.com'}, adUnitCode: 'ad-unit-1', + bidId: 'Bid_W', + bidderRequestId: 'req-002', + auctionId: 'auc-002', mediaTypes: { banner: { sizes: [[728, 90]] @@ -45,9 +53,11 @@ describe('Adkernel adapter', function () { } }, bid_without_host = { bidder: 'adkernel', - bidId: 'Bid_W', params: {zoneId: 1}, adUnitCode: 'ad-unit-1', + bidId: 'Bid_W', + bidderRequestId: 'req-002', + auctionId: 'auc-002', mediaTypes: { banner: { sizes: [[728, 90]] @@ -55,9 +65,11 @@ describe('Adkernel adapter', function () { } }, bid_with_wrong_zoneId = { bidder: 'adkernel', - bidId: 'Bid_02', params: {zoneId: 'wrong id', host: 'rtb.adkernel.com'}, adUnitCode: 'ad-unit-2', + bidId: 'Bid_02', + bidderRequestId: 'req-002', + auctionId: 'auc-002', mediaTypes: { banner: { sizes: [[728, 90]] @@ -72,7 +84,8 @@ describe('Adkernel adapter', function () { sizes: [[640, 480]], params: { zoneId: 1, - host: 'rtb.adkernel.com' + host: 'rtb.adkernel.com', + video: {api: [1, 2]} }, mediaTypes: { video: { @@ -81,6 +94,19 @@ describe('Adkernel adapter', function () { } }, adUnitCode: 'ad-unit-1' + }, bid_multiformat = { + bidder: 'adkernel', + params: {zoneId: 1, host: 'rtb.adkernel.com'}, + mediaTypes: { + banner: {sizes: [[300, 250], [300, 200]]}, + video: {context: 'instream', playerSize: [[640, 480]]} + }, + adUnitCode: 'ad-unit-1', + transactionId: 'f82c64b8-c602-42a4-9791-4a268f6559ed', + sizes: [[300, 250], [300, 200]], + bidId: 'Bid_01', + bidderRequestId: 'req-001', + auctionId: 'auc-001' }; const bidResponse1 = { @@ -183,6 +209,11 @@ describe('Adkernel adapter', function () { expect(bidRequest.imp[0]).to.have.property('banner'); }); + it('should have id', function () { + expect(bidRequest.imp[0]).to.have.property('id'); + expect(bidRequest.imp[0].id).to.be.eql('Bid_01'); + }); + it('should have w/h', function () { expect(bidRequest.imp[0].banner).to.have.property('format'); expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); @@ -257,6 +288,27 @@ describe('Adkernel adapter', function () { it('should have tagid', function () { expect(bidRequests[0].imp[0]).to.have.property('tagid', 'ad-unit-1'); }); + + it('should have openrtb video impression parameters', function() { + expect(bidRequests[0].imp[0].video).to.have.property('api'); + expect(bidRequests[0].imp[0].video.api).to.be.eql([1, 2]); + }); + }); + + describe('multiformat request building', function () { + let _, bidRequests; + before(function () { + [_, bidRequests] = buildRequest([bid_multiformat]); + }); + it('should contain single request', function () { + expect(bidRequests).to.have.length(1); + expect(bidRequests[0].imp).to.have.length(1); + }); + it('should contain banner-only impression', function () { + expect(bidRequests[0].imp).to.have.length(1); + expect(bidRequests[0].imp[0]).to.have.property('banner'); + expect(bidRequests[0].imp[0]).to.not.have.property('video'); + }); }); describe('requests routing', function () { diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index ff9b6ec2371..50c332557e6 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -232,6 +232,56 @@ describe('Utils', function () { }); }); + describe('parseGPTSingleSizeArrayToRtbSize', function () { + it('should return size string with input single size array', function () { + var size = [300, 250]; + var output = utils.parseGPTSingleSizeArrayToRtbSize(size); + assert.deepEqual(output, {w: 300, h: 250}); + }); + + it('should return size string with input single size array', function () { + var size = ['300', '250']; + var output = utils.parseGPTSingleSizeArrayToRtbSize(size); + assert.deepEqual(output, {w: 300, h: 250}); + }); + + it('return undefined using string input', function () { + var size = '1'; + var output = utils.parseGPTSingleSizeArrayToRtbSize(size); + assert.equal(output, undefined); + }); + + it('return undefined using number input', function () { + var size = 1; + var output = utils.parseGPTSingleSizeArrayToRtbSize(size); + assert.equal(output, undefined); + }); + + it('return undefined using one length single array', function () { + var size = [300]; + var output = utils.parseGPTSingleSizeArrayToRtbSize(size); + assert.equal(output, undefined); + }); + + it('return undefined if the input is empty', function () { + var size = ''; + var output = utils.parseGPTSingleSizeArrayToRtbSize(size); + assert.equal(output, undefined); + }); + + it('return undefined if the input is not a number', function () { + var size = ['foo', 'bar']; + var output = utils.parseGPTSingleSizeArrayToRtbSize(size); + assert.equal(output, undefined); + }); + + it('return undefined if the input is not a number 2', function () { + var size = [300, 'foo']; + var output = utils.parseGPTSingleSizeArrayToRtbSize(size); + assert.equal(output, undefined); + }); + }); + describe('isA', function () { it('should return true with string object', function () { var output = utils.isA(obj_string, type_string); From 00f83b17b7bf6d1f7f5494b01440446d5fc21473 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 24 Jul 2019 16:03:18 -0400 Subject: [PATCH 1373/1594] remove console log statement in logicadBidAdapter unit tests (#4021) --- test/spec/modules/logicadBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/logicadBidAdapter_spec.js b/test/spec/modules/logicadBidAdapter_spec.js index 7d2916e3e0f..effb7334b69 100644 --- a/test/spec/modules/logicadBidAdapter_spec.js +++ b/test/spec/modules/logicadBidAdapter_spec.js @@ -108,7 +108,7 @@ describe('LogicadAdapter', function () { it('should perform usersync', function () { let syncs = spec.getUserSyncs({pixelEnabled: false}, [serverResponse]); expect(syncs).to.have.length(0); - console.log(serverResponse); + syncs = spec.getUserSyncs({pixelEnabled: true}, [serverResponse]); expect(syncs).to.have.length(1); From c16640a4ed61c553ed69c4861494ee7d90109f3b Mon Sep 17 00:00:00 2001 From: "Isaac A. Dettman" Date: Thu, 25 Jul 2019 14:27:09 -0700 Subject: [PATCH 1374/1594] Add oRTB cur to PrebidServer Adapter (#3951) * Add 'cur' to ORTB obj --- modules/prebidServerBidAdapter/index.js | 12 +++++ .../modules/prebidServerBidAdapter_spec.js | 46 ++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index e857bf1d665..582b12e59d7 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -533,6 +533,18 @@ const OPEN_RTB_PROTOCOL = { request.ext.prebid = Object.assign(request.ext.prebid, _s2sConfig.extPrebid); } + /** + * @type {(string[]|string|undefined)} - OpenRTB property 'cur', currencies available for bids + */ + const adServerCur = config.getConfig('currency.adServerCurrency'); + if (adServerCur && typeof adServerCur === 'string') { + // if the value is a string, wrap it with an array + request.cur = [adServerCur]; + } else if (Array.isArray(adServerCur) && adServerCur.length) { + // if it's an array, get the first element + request.cur = [adServerCur[0]]; + } + _appendSiteAppDevice(request); const digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 9562b2f4c07..8b077ca796a 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -904,9 +904,51 @@ describe('S2S Adapter', function () { expect(Array.isArray(requestBid.user.ext.eids)).to.be.true; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; ; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); - }) + }); + + it('when config \'currency.adServerCurrency\' value is an array: ORTB has property \'cur\' value set to a single item array', function () { + let s2sConfig = utils.deepClone(CONFIG); + s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + config.setConfig({ + currency: {adServerCurrency: ['USD', 'GB', 'UK', 'AU']}, + s2sConfig: s2sConfig + }); + + const bidRequests = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, bidRequests, addBidResponse, done, ajax); + + const parsedRequestBody = JSON.parse(requests[0].requestBody); + expect(parsedRequestBody.cur).to.deep.equal(['USD']); + }); + + it('when config \'currency.adServerCurrency\' value is a string: ORTB has property \'cur\' value set to a single item array', function () { + let s2sConfig = utils.deepClone(CONFIG); + s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + config.setConfig({ + currency: {adServerCurrency: 'NZ'}, + s2sConfig: s2sConfig + }); + + const bidRequests = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, bidRequests, addBidResponse, done, ajax); + + const parsedRequestBody = JSON.parse(requests[1].requestBody); + expect(parsedRequestBody.cur).to.deep.equal(['NZ']); + }); + + it('when config \'currency.adServerCurrency\' is unset: ORTB should not define a \'cur\' property', function () { + let s2sConfig = utils.deepClone(CONFIG); + s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + config.setConfig({s2sConfig: s2sConfig}); + + const bidRequests = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, bidRequests, addBidResponse, done, ajax); + + const parsedRequestBody = JSON.parse(requests[0].requestBody); + expect(typeof parsedRequestBody.cur).to.equal('undefined'); + }); it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () { const s2sConfig = Object.assign({}, CONFIG, { From 0f54ea239f79329c2cb359ef5589ed24d3880fae Mon Sep 17 00:00:00 2001 From: Jurij Sinickij Date: Fri, 26 Jul 2019 06:08:30 +0300 Subject: [PATCH 1375/1594] adformOpenRTB adapter: support currency param (#4016) * adformOpenRTB adapter: support currency param * use common currency settings --- modules/adformOpenRTBBidAdapter.js | 4 ++++ modules/adformOpenRTBBidAdapter.md | 2 +- test/spec/modules/adformOpenRTBBidAdapter_spec.js | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/modules/adformOpenRTBBidAdapter.js b/modules/adformOpenRTBBidAdapter.js index 94433d907c4..e40de8ad04d 100644 --- a/modules/adformOpenRTBBidAdapter.js +++ b/modules/adformOpenRTBBidAdapter.js @@ -8,6 +8,7 @@ import { NATIVE } from '../src/mediaTypes'; import * as utils from '../src/utils'; +import { config } from '../src/config'; const BIDDER_CODE = 'adformOpenRTB'; const NATIVE_ASSET_IDS = { 0: 'title', 2: 'icon', 3: 'image', 5: 'sponsoredBy', 4: 'body', 1: 'cta' }; @@ -56,6 +57,8 @@ export const spec = { const test = setOnAny(validBidRequests, 'params.test'); const publisher = setOnAny(validBidRequests, 'params.publisher'); const siteId = setOnAny(validBidRequests, 'params.siteId'); + const currency = config.getConfig('currency.adServerCurrency'); + const cur = currency && [ currency ]; const imp = validBidRequests.map((bid, id) => { bid.netRevenue = pt; @@ -94,6 +97,7 @@ export const spec = { device: { ua }, source: { tid, fd: 1 }, ext: { pt }, + cur, imp }; diff --git a/modules/adformOpenRTBBidAdapter.md b/modules/adformOpenRTBBidAdapter.md index f59f039f3ec..0dd98ad07b8 100644 --- a/modules/adformOpenRTBBidAdapter.md +++ b/modules/adformOpenRTBBidAdapter.md @@ -45,7 +45,7 @@ Only native format is supported. Using OpenRTB standard. bidder: 'adformOpenRTB', params: { mid: 606169, // required - adxDomain: 'axd.adform.net', // optional + adxDomain: 'adx.adform.net', // optional siteId: '23455', // optional priceType: 'gross' // optional, default is 'net' publisher: { // optional block diff --git a/test/spec/modules/adformOpenRTBBidAdapter_spec.js b/test/spec/modules/adformOpenRTBBidAdapter_spec.js index 5c0009ab1c7..f6c3098f3b6 100644 --- a/test/spec/modules/adformOpenRTBBidAdapter_spec.js +++ b/test/spec/modules/adformOpenRTBBidAdapter_spec.js @@ -3,6 +3,7 @@ import {assert, expect} from 'chai'; import * as url from 'src/url'; import {spec} from 'modules/adformOpenRTBBidAdapter'; import { NATIVE } from 'src/mediaTypes'; +import { config } from 'src/config'; describe('AdformOpenRTB adapter', function () { let serverResponse, bidRequest, bidResponses; @@ -144,6 +145,15 @@ describe('AdformOpenRTB adapter', function () { }); }); + 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); + + assert.deepEqual(request.cur, [ 'EUR' ]); + }); + describe('priceType', function () { it('should send default priceType', function () { let validBidRequests = [{ From 5394230d8cfd1b910c31faddcdb9b7f2c33b9d9a Mon Sep 17 00:00:00 2001 From: Jurij Sinickij Date: Fri, 26 Jul 2019 06:10:17 +0300 Subject: [PATCH 1376/1594] adformBidAdapter: currency module support (#4018) --- modules/adformBidAdapter.js | 4 ++++ test/spec/modules/adformBidAdapter_spec.js | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index caf9ce71a69..a3aef10e41e 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -1,6 +1,7 @@ 'use strict'; import {registerBidder} from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'adform'; @@ -12,6 +13,8 @@ export const spec = { }, buildRequests: function (validBidRequests, bidderRequest) { var i, l, j, k, bid, _key, _value, reqParams, netRevenue, gdprObject; + const currency = config.getConfig('currency.adServerCurrency'); + var request = []; var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ] ]; var bids = JSON.parse(JSON.stringify(validBidRequests)); @@ -31,6 +34,7 @@ export const spec = { } reqParams = bid.params; reqParams.transactionId = bid.transactionId; + reqParams.rcur = reqParams.rcur || currency; request.push(formRequestUrl(reqParams)); } diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index d3054794485..f50474ae500 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -2,6 +2,7 @@ import {assert, expect} from 'chai'; import * as url from 'src/url'; import {spec} from 'modules/adformBidAdapter'; import { BANNER, VIDEO } from 'src/mediaTypes'; +import { config } from 'src/config'; describe('Adform adapter', function () { let serverResponse, bidRequest, bidResponses; @@ -50,6 +51,24 @@ describe('Adform adapter', function () { assert.equal(request.method, 'GET'); }); + it('should pass request currency from config', function () { + config.setConfig({ currency: { adServerCurrency: 'PLN' } }); + let request = parseUrl(spec.buildRequests(bids).url); + + request.items.forEach(item => { + assert.equal(item.rcur, 'PLN'); + }); + }); + + it('should prefer bid currency over global config', function () { + config.setConfig({ currency: { adServerCurrency: 'PLN' } }); + bids[0].params.rcur = 'USD'; + let request = parseUrl(spec.buildRequests(bids).url); + const currencies = request.items.map(item => item.rcur); + + assert.deepEqual(currencies, [ 'USD', 'PLN', 'PLN', 'PLN', 'PLN', 'PLN', 'PLN' ]); + }); + it('should correctly form bid items', function () { let bidList = bids; let request = spec.buildRequests(bidList); @@ -286,6 +305,8 @@ describe('Adform adapter', function () { }); beforeEach(function () { + config.setConfig({ currency: {} }); + let sizes = [[250, 300], [300, 250], [300, 600]]; let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; let params = [{ mid: 1, url: 'some// there' }, {adxDomain: null, mid: 2, someVar: 'someValue', pt: 'gross'}, { adxDomain: null, mid: 3, pdom: 'home' }, {mid: 5, pt: 'net'}, {mid: 6, pt: 'gross'}]; From e2d877d33fb41fddf81f8a9278cdc1d8ba347f7f Mon Sep 17 00:00:00 2001 From: Valentin Date: Fri, 26 Jul 2019 15:17:15 +0200 Subject: [PATCH 1377/1594] Teads-adapter: Read placementId from response and add sync informations (#3963) * Read placementId and add informations * Secure gdprConsent object access --- modules/teadsBidAdapter.js | 28 ++++++-- test/spec/modules/teadsBidAdapter_spec.js | 87 ++++++++++++++++++++--- 2 files changed, 102 insertions(+), 13 deletions(-) diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js index 92cfce312b1..121232a6605 100644 --- a/modules/teadsBidAdapter.js +++ b/modules/teadsBidAdapter.js @@ -42,7 +42,8 @@ export const spec = { const payload = { referrer: getReferrerInfo(bidderRequest), data: bids, - deviceWidth: screen.width + deviceWidth: screen.width, + hb_version: '$prebid.version$' }; let gdpr = bidderRequest.gdprConsent; @@ -84,7 +85,8 @@ export const spec = { ttl: bid.ttl, ad: bid.ad, requestId: bid.bidId, - creativeId: bid.creativeId + creativeId: bid.creativeId, + placementId: bid.placementId }; bidResponses.push(bidResponse); }); @@ -92,11 +94,29 @@ export const spec = { return bidResponses; }, - getUserSyncs: function(syncOptions, responses, gdprApplies) { + getUserSyncs: function(syncOptions, responses, gdprConsent) { + let queryParams = { + hb_provider: 'prebid', + hb_version: '$prebid.version$' + }; + + if (gdprConsent) { + let gdprIab = { + status: findGdprStatus(gdprConsent.gdprApplies, gdprConsent.vendorData), + consent: gdprConsent.consentString + }; + + queryParams.gdprIab = JSON.stringify(gdprIab) + } + + if (utils.deepAccess(responses[0], 'body.responses.0.placementId')) { + queryParams.placementId = responses[0].body.responses[0].placementId + }; + if (syncOptions.iframeEnabled) { return [{ type: 'iframe', - url: '//sync.teads.tv/iframe' + url: '//sync.teads.tv/iframe?' + utils.parseQueryStringParameters(queryParams) }]; } } diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js index 57484d79b05..af1c7a9c01b 100644 --- a/test/spec/modules/teadsBidAdapter_spec.js +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -5,11 +5,11 @@ import {newBidder} from 'src/adapters/bidderFactory'; const ENDPOINT = '//a.teads.tv/hb/bid-request'; const AD_SCRIPT = '"'; -describe('teadsBidAdapter', function() { +describe('teadsBidAdapter', () => { const adapter = newBidder(spec); - describe('inherited functions', function() { - it('exists and is a function', function() { + describe('inherited functions', () => { + it('exists and is a function', () => { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); @@ -286,16 +286,17 @@ describe('teadsBidAdapter', function() { 'currency': 'USD', 'height': 250, 'netRevenue': true, - 'requestId': '3ede2a3fa0db94', + 'bidId': '3ede2a3fa0db94', 'ttl': 360, 'width': 300, - 'creativeId': 'er2ee' + 'creativeId': 'er2ee', + 'placementId': 34 }] } }; it('should get correct bid response', function() { - let expectedResponse = [{ + let expectedResponse = { 'cpm': 0.5, 'width': 300, 'height': 250, @@ -304,11 +305,12 @@ describe('teadsBidAdapter', function() { 'ttl': 360, 'ad': AD_SCRIPT, 'requestId': '3ede2a3fa0db94', - 'creativeId': 'er2ee' - }]; + 'creativeId': 'er2ee', + 'placementId': 34 + }; let result = spec.interpretResponse(bids); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + expect(result[0]).to.deep.equal(expectedResponse); }); it('handles nobid responses', function() { @@ -322,4 +324,71 @@ describe('teadsBidAdapter', function() { expect(result.length).to.equal(0); }); }); + + it('should call userSync with good params', function() { + let bids = [{ + 'body': { + 'responses': [{ + 'ad': ' + - - - + setTimeout(function() { + sendAdserverRequest(); + console.log('timeout in main pbjs fired'); + }, FAILSAFE_TIMEOUT); +
    - \ No newline at end of file + diff --git a/integrationExamples/gpt/gpt_aliasingBidder.html b/integrationExamples/gpt/gpt_aliasingBidder.html deleted file mode 100644 index 693be76e82e..00000000000 --- a/integrationExamples/gpt/gpt_aliasingBidder.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - - - - - - - - -

    Prebid.js Test

    - -
    - -
    - - -
    - -
    - - - - - - - diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index e1cdaa0dc29..337c762adc5 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -9,8 +9,11 @@ + + - - -
    - \ No newline at end of file + diff --git a/integrationExamples/gpt/hello_world_emoteev.html b/integrationExamples/gpt/hello_world_emoteev.html deleted file mode 100644 index f41ef308332..00000000000 --- a/integrationExamples/gpt/hello_world_emoteev.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - -

    Basic Prebid.js Example

    -
    Div-1
    -
    - -
    - - - diff --git a/integrationExamples/gpt/load_pbjs_before_dfp_example.html b/integrationExamples/gpt/load_pbjs_before_dfp_example.html deleted file mode 100644 index cb17b8c3348..00000000000 --- a/integrationExamples/gpt/load_pbjs_before_dfp_example.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - -

    Prebid.js Test

    -
    - -
    -
    - -
    - - diff --git a/integrationExamples/gpt/load_pbjs_dfp_concurrently.html b/integrationExamples/gpt/load_pbjs_dfp_concurrently.html deleted file mode 100644 index 0d6270ba7a5..00000000000 --- a/integrationExamples/gpt/load_pbjs_dfp_concurrently.html +++ /dev/null @@ -1,282 +0,0 @@ - - - - - - -

    Prebid.js Test

    -
    - -
    -
    - -
    - - diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html deleted file mode 100644 index 3a32eb5dbd6..00000000000 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ /dev/null @@ -1,633 +0,0 @@ - - - -Prebid.js integration example - - - - -

    Prebid.js Test

    - -
    - -
    - - -
    - -
    - - - - - - - diff --git a/integrationExamples/gpt/pbjs_innity_gpt.html b/integrationExamples/gpt/pbjs_innity_gpt.html deleted file mode 100644 index 7882d44791d..00000000000 --- a/integrationExamples/gpt/pbjs_innity_gpt.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -

    Prebid.js Test

    -
    Div-1
    -
    - -
    - - \ No newline at end of file diff --git a/integrationExamples/gpt/pbjs_partial_refresh_gpt.html b/integrationExamples/gpt/pbjs_partial_refresh_gpt.html deleted file mode 100644 index 09009a24d76..00000000000 --- a/integrationExamples/gpt/pbjs_partial_refresh_gpt.html +++ /dev/null @@ -1,296 +0,0 @@ - - - - - - - - - - - - - -

    Prebid.js Test

    - -
    Div-1, 300x250 or 300x600
    - - - -
    - -
    - - -
    Div-2, 728x90 or 970x90
    - - - - -
    - -
    - - - - - diff --git a/integrationExamples/gpt/pbjs_yieldbot_gpt.html b/integrationExamples/gpt/pbjs_yieldbot_gpt.html deleted file mode 100644 index 986eed8fc5e..00000000000 --- a/integrationExamples/gpt/pbjs_yieldbot_gpt.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - -

    Prebid.js Yieldbot Adapter Basic Example

    - Use the links below to enable and disable Yieldbot test bids.
    -
    - Note: -
    - The "Enable - Yieldbot Test Bids" link below will set a cookie to force Yieldbot bid requests to return static test creative: the cookie expires in 24 hrs. -
    - -
      -
    1. Enable - Yieldbot Test Bids
    2. -
    3. Disable - Yieldbot Test Bids
    4. -
    -
    Div-0, 728x90
    - -
    - -
    -
    Div-1, 300x250 or 300x600
    - -
    - -
    -
    Div-2, 300x250 or 300x600
    - The bid for the 300x250 | 300x600 slot is shown under Div-1 above. -
      -
    • Refresh this slot after initial page view and you should see the Yieldbot test creative.
    • -
    - -
    - -
    - - diff --git a/integrationExamples/gpt/pollux_example.html b/integrationExamples/gpt/pollux_example.html deleted file mode 100644 index 56eedbf2a9c..00000000000 --- a/integrationExamples/gpt/pollux_example.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - test - - - -
    - -
    - -
    -
    - -
    - -
    - - \ No newline at end of file diff --git a/integrationExamples/gpt/unruly_example.html b/integrationExamples/gpt/unruly_example.html deleted file mode 100644 index 038951b9eb8..00000000000 --- a/integrationExamples/gpt/unruly_example.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - test - - - -
    - -
    - - - From 5dfb923e884f6b260b3515faa9bc84d73404d1a7 Mon Sep 17 00:00:00 2001 From: PWyrembak Date: Tue, 30 Jul 2019 15:33:44 +0300 Subject: [PATCH 1382/1594] Hotfix for referrer in TrustX Bid Adapter (#4039) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Add support of gdpr to Trustx Bid Adapter * Add wtimeout to ad request params for TrustX Bid Adapter * TrustX Bid Adapter: remove last ampersand in the ad request * Update TrustX Bid Adapter to support identical uids in parameters * Update TrustX Bid Adapter to ignore bids that sizes do not match the size of the request * Update TrustX Bid Adapter to support instream and outstream video * Added wrapperType and wrapperVersion parameters in ad request for TrustX Bid Adapter * Update TrustX Bid Adapter to use refererInfo instead depricated function utils.getTopWindowUrl * HOTFIX for referrer encodind in TrustX Bid Adapter * Fix test for TrustX Bid Adapter --- modules/trustxBidAdapter.js | 2 +- test/spec/modules/trustxBidAdapter_spec.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index e9eb175671e..aecb6aba8af 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -94,7 +94,7 @@ export const spec = { if (bidderRequest) { if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + payload.u = bidderRequest.refererInfo.referer; } if (bidderRequest.timeout) { payload.wtimeout = bidderRequest.timeout; diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index 0a4fddcb852..f99831eeca1 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -53,7 +53,7 @@ describe('TrustXAdapter', function () { referer: 'http://example.com' } }; - const encodedReferer = encodeURIComponent(bidderRequest.refererInfo.referer); + const referrer = bidderRequest.refererInfo.referer; let bidRequests = [ { @@ -95,7 +95,7 @@ describe('TrustXAdapter', function () { const request = spec.buildRequests([bidRequests[0]], bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + 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'); @@ -108,7 +108,7 @@ describe('TrustXAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + 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'); @@ -120,7 +120,7 @@ describe('TrustXAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + 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'); @@ -133,7 +133,7 @@ describe('TrustXAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + 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'); From 8302d96a244116c9a74cdd2d5057bea86bda865b Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 30 Jul 2019 07:20:18 -0600 Subject: [PATCH 1383/1594] update userSync messaging for re-fire to not be warning (#4034) --- src/userSync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/userSync.js b/src/userSync.js index 2d5dfbd9a28..e2bd4e3f04a 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -152,7 +152,7 @@ export function newUserSync(userSyncDependencies) { */ publicApi.registerSync = (type, bidder, url) => { if (hasFiredBidder.has(bidder)) { - return utils.logWarn(`already registered syncs for "${bidder}"`); + return utils.logMessage(`already fired syncs for "${bidder}", ignoring registerSync call`); } if (!usConfig.syncEnabled || !utils.isArray(queue[type])) { return utils.logWarn(`User sync type "${type}" not supported`); From 03bc30db4501b8678c37a2797b2dee1ebcbe2be7 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 30 Jul 2019 09:02:14 -0600 Subject: [PATCH 1384/1594] update fun-hooks with fix checking if global Proxy is native (#4030) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a82ef44aec..9d2bb82f25c 100755 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "crypto-js": "^3.1.9-1", "dlv": "1.1.3", "dset": "2.0.1", - "fun-hooks": "^0.9.2", + "fun-hooks": "^0.9.5", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2" } From 0561222e8b20411d91bc4c275973fe4252b2ef3d Mon Sep 17 00:00:00 2001 From: Jurij Sinickij Date: Tue, 30 Jul 2019 19:20:44 +0300 Subject: [PATCH 1385/1594] adformOpenRTB adapter: size targeting using aspect ratios (#4019) * adformOpenRTB adatper: size targeting using aspect ratios * avoid throwing errors while parsing aspect_ratios --- modules/adformOpenRTBBidAdapter.js | 27 +++++- .../modules/adformOpenRTBBidAdapter_spec.js | 93 ++++++++++++++++++- 2 files changed, 115 insertions(+), 5 deletions(-) diff --git a/modules/adformOpenRTBBidAdapter.js b/modules/adformOpenRTBBidAdapter.js index e40de8ad04d..0f69ccd6262 100644 --- a/modules/adformOpenRTBBidAdapter.js +++ b/modules/adformOpenRTBBidAdapter.js @@ -69,11 +69,28 @@ export const spec = { }; 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]; + } + asset[props.name] = { len: bidParams.len, - wmin: bidParams.sizes && bidParams.sizes[0], - hmin: bidParams.sizes && bidParams.sizes[1], - type: props.type + type: props.type, + wmin, + hmin, + w, + h }; return asset; @@ -175,3 +192,7 @@ function setOnAny(collection, key) { } } } + +function flatten(arr) { + return [].concat(...arr); +} diff --git a/test/spec/modules/adformOpenRTBBidAdapter_spec.js b/test/spec/modules/adformOpenRTBBidAdapter_spec.js index f6c3098f3b6..cafbe4eff15 100644 --- a/test/spec/modules/adformOpenRTBBidAdapter_spec.js +++ b/test/spec/modules/adformOpenRTBBidAdapter_spec.js @@ -272,13 +272,102 @@ describe('AdformOpenRTB adapter', function () { let assets = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp[0].native.request.assets; assert.ok(assets[0].title); assert.equal(assets[0].title.len, 140); - assert.deepEqual(assets[1].img, { type: 3, wmin: 150, hmin: 50 }); - assert.deepEqual(assets[2].img, { type: 1, wmin: 50, hmin: 50 }); + 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: { siteId: 'siteId', mid: 1000 }, + nativeParams: { + image: { + sizes: [[200, 300], [100, 200]] + }, + } + }]; + + let assets = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp[0].native.request.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: { siteId: 'siteId', mid: 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 assets = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp[0].native.request.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: { siteId: 'siteId', mid: 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: { siteId: 'siteId', mid: 1000 }, + nativeParams: { + image: { + aspect_ratios: [{ + ratio_height: 3, + ratio_width: 1 + }] + } + } + }]; + + let assets = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' } }).data).imp[0].native.request.assets; + assert.ok(assets[0].img); + assert.equal(assets[0].img.wmin, 0); + assert.equal(assets[0].img.hmin, 0); + assert.ok(!assets[1]); }); }); }); From f013970bd77e8c416dffcaf063cabf307d74c2de Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 30 Jul 2019 10:30:42 -0600 Subject: [PATCH 1386/1594] Prebid server support for OpenRTB Native bids (#3145) * initial support for native requests in prebid server * add support for native request in prebid server OpenRTB * fixes and new test for native openrtb responses * updates to prebidServerBidAdapter for native support * resolve conflicts with prebid-server video changes * successfully returning and rendering native ad through prebid server * add example prebid server native page * fix bugs and tests for prebid-server native * resolve unused variable lint alert in native example * allow native adUnits without sizes in prebid server --- .../gpt/prebidServer_native_example.html | 174 +++++++++++++ modules/prebidServerBidAdapter/index.js | 236 ++++++++++++++++-- modules/rubiconAnalyticsAdapter.js | 49 +--- src/utils.js | 47 ++++ .../modules/prebidServerBidAdapter_spec.js | 177 ++++++++++++- 5 files changed, 621 insertions(+), 62 deletions(-) create mode 100644 integrationExamples/gpt/prebidServer_native_example.html diff --git a/integrationExamples/gpt/prebidServer_native_example.html b/integrationExamples/gpt/prebidServer_native_example.html new file mode 100644 index 00000000000..16c7d38a427 --- /dev/null +++ b/integrationExamples/gpt/prebidServer_native_example.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + +

    Prebid Native

    +
    +

    No response

    + +
    + +
    +
    + +
    +

    No response

    + +
    + + + + diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 582b12e59d7..2ae32dd1df2 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -5,7 +5,8 @@ import { ajax } from '../../src/ajax'; import { STATUS, S2S, EVENTS } from '../../src/constants'; import adapterManager from '../../src/adapterManager'; import { config } from '../../src/config'; -import { VIDEO } from '../../src/mediaTypes'; +import { VIDEO, NATIVE } from '../../src/mediaTypes'; +import { processNativeAdUnitParams } from '../../src/native'; import { isValid } from '../../src/adapters/bidderFactory'; import events from '../../src/events'; import includes from 'core-js/library/fn/array/includes'; @@ -346,7 +347,7 @@ const LEGACY_PROTOCOL = { return request; }, - interpretResponse(result, bidderRequests, requestedBidders) { + interpretResponse(result, bidderRequests) { const bids = []; if (result.status === 'OK' || result.status === 'no_cookie') { if (result.bidder_status) { @@ -431,11 +432,57 @@ const LEGACY_PROTOCOL = { } }; +// https://iabtechlab.com/wp-content/uploads/2016/07/OpenRTB-Native-Ads-Specification-Final-1.2.pdf#page=40 +let nativeDataIdMap = { + sponsoredBy: 1, // sponsored + body: 2, // desc + rating: 3, + likes: 4, + downloads: 5, + price: 6, + salePrice: 7, + phone: 8, + address: 9, + body2: 10, // desc2 + cta: 12 // ctatext +}; +let nativeDataNames = Object.keys(nativeDataIdMap); + +let nativeImgIdMap = { + icon: 1, + image: 3 +}; + +let nativeEventTrackerEventMap = { + impression: 1, + 'viewable-mrc50': 2, + 'viewable-mrc100': 3, + 'viewable-video50': 4, +}; + +let nativeEventTrackerMethodMap = { + img: 1, + js: 2 +}; + +// enable reverse lookup +[ + nativeDataIdMap, + nativeImgIdMap, + nativeEventTrackerEventMap, + nativeEventTrackerMethodMap +].forEach(map => { + Object.keys(map).forEach(key => { + map[map[key]] = key; + }); +}); + /* * Protocol spec for OpenRTB endpoint * e.g., https:///v1/openrtb2/auction */ let bidIdMap = {}; +let nativeAssetCache = {}; // store processed native params to preserve const OPEN_RTB_PROTOCOL = { buildRequest(s2sBidRequest, bidRequests, adUnits) { let imps = []; @@ -443,6 +490,74 @@ const OPEN_RTB_PROTOCOL = { // transform ad unit into array of OpenRTB impression objects adUnits.forEach(adUnit => { + const nativeParams = processNativeAdUnitParams(utils.deepAccess(adUnit, 'mediaTypes.native')); + let nativeAssets; + if (nativeParams) { + try { + nativeAssets = nativeAssetCache[adUnit.code] = Object.keys(nativeParams).reduce((assets, type) => { + let params = nativeParams[type]; + + function newAsset(obj) { + return Object.assign({ + required: params.required ? 1 : 0 + }, obj ? utils.cleanObj(obj) : {}); + } + + switch (type) { + case 'image': + case 'icon': + let imgTypeId = nativeImgIdMap[type]; + let asset = utils.cleanObj({ + type: imgTypeId, + w: utils.deepAccess(params, 'sizes.0'), + h: utils.deepAccess(params, 'sizes.1'), + wmin: utils.deepAccess(params, 'aspect_ratios.0.min_width') + }); + if (!(asset.w || asset.wmin)) { + throw 'invalid img sizes (must provided sizes or aspect_ratios)'; + } + if (Array.isArray(params.aspect_ratios)) { + // pass aspect_ratios as ext data I guess? + asset.ext = { + aspectratios: params.aspect_ratios.map( + ratio => `${ratio.ratio_width}:${ratio.ratio_height}` + ) + } + } + assets.push(newAsset({ + img: asset + })); + break; + case 'title': + if (!params.len) { + throw 'invalid title.len'; + } + assets.push(newAsset({ + title: { + len: params.len + } + })); + break; + default: + let dataAssetTypeId = nativeDataIdMap[type]; + if (dataAssetTypeId) { + assets.push(newAsset({ + data: { + type: dataAssetTypeId, + len: params.len + } + })) + } + } + return assets; + }, []); + } catch (e) { + utils.logError('error creating native request: ' + String(e)) + } + } + const videoParams = utils.deepAccess(adUnit, 'mediaTypes.video'); + const bannerParams = utils.deepAccess(adUnit, 'mediaTypes.banner'); + adUnit.bids.forEach(bid => { // OpenRTB response contains the adunit code and bidder name. These are // combined to create a unique key for each bid since an id isn't returned @@ -454,14 +569,13 @@ const OPEN_RTB_PROTOCOL = { } }); - let banner; + let mediaTypes = {}; // default to banner if mediaTypes isn't defined - if (utils.isEmpty(adUnit.mediaTypes)) { + if (!(nativeParams || videoParams || bannerParams)) { const sizeObjects = adUnit.sizes.map(size => ({ w: size[0], h: size[1] })); - banner = {format: sizeObjects}; + mediaTypes['banner'] = {format: sizeObjects}; } - const bannerParams = utils.deepAccess(adUnit, 'mediaTypes.banner'); if (bannerParams && bannerParams.sizes) { const sizes = utils.parseSizesInput(bannerParams.sizes); @@ -473,13 +587,37 @@ const OPEN_RTB_PROTOCOL = { return { w, h }; }); - banner = {format}; + mediaTypes['banner'] = {format}; } - let video; - const videoParams = utils.deepAccess(adUnit, 'mediaTypes.video'); if (!utils.isEmpty(videoParams)) { - video = videoParams; + if (videoParams.context === 'outstream' && !adUnit.renderer) { + // Don't push oustream w/o renderer to request object. + utils.logError('Outstream bid without renderer cannot be sent to Prebid Server.'); + } else { + mediaTypes['video'] = videoParams; + } + } + + if (nativeAssets) { + try { + mediaTypes['native'] = { + request: JSON.stringify({ + // TODO: determine best way to pass these and if we allow defaults + context: 1, + plcmttype: 1, + eventtrackers: [ + {event: 1, methods: [1]} + ], + // TODO: figure out how to support privacy field + // privacy: int + assets: nativeAssets + }), + ver: '1.2' + } + } catch (e) { + utils.logError('error creating native request: ' + String(e)) + } } // get bidder params in form { : {...params} } @@ -494,16 +632,11 @@ const OPEN_RTB_PROTOCOL = { const imp = { id: adUnit.code, ext, secure: _s2sConfig.secure }; - if (banner) { imp.banner = banner; } - if (video) { - if (video.context === 'outstream' && !adUnit.renderer) { - // Don't push oustream w/o renderer to request object. - utils.logError('Outstream bid without renderer cannot be sent to Prebid Server.'); - } else { - imp.video = video; - } + Object.assign(imp, mediaTypes); + + if (imp.banner || imp.video || imp.native) { + imps.push(imp); } - if (imp.banner || imp.video) { imps.push(imp); } }); if (!imps.length) { @@ -609,7 +742,7 @@ const OPEN_RTB_PROTOCOL = { return request; }, - interpretResponse(response, bidderRequests, requestedBidders) { + interpretResponse(response, bidderRequests) { const bids = []; if (response.seatbid) { @@ -665,6 +798,60 @@ const OPEN_RTB_PROTOCOL = { if (bid.adm) { bidObject.vastXml = bid.adm; } if (!bidObject.vastUrl && bid.nurl) { bidObject.vastUrl = bid.nurl; } + } else if (utils.deepAccess(bid, 'ext.prebid.type') === NATIVE) { + bidObject.mediaType = NATIVE; + let adm; + if (typeof bid.adm === 'string') { + adm = bidObject.adm = JSON.parse(bid.adm); + } else { + adm = bidObject.adm = bid.adm; + } + + let trackers = { + [nativeEventTrackerMethodMap.img]: adm.imptrackers || [], + [nativeEventTrackerMethodMap.js]: adm.jstracker ? [adm.jstracker] : [] + }; + if (adm.eventtrackers) { + adm.eventtrackers.forEach(tracker => { + switch (tracker.method) { + case nativeEventTrackerMethodMap.img: + trackers[nativeEventTrackerMethodMap.img].push(tracker.url); + break; + case nativeEventTrackerMethodMap.js: + trackers[nativeEventTrackerMethodMap.js].push(tracker.url); + break; + } + }); + } + + if (utils.isPlainObject(adm) && Array.isArray(adm.assets)) { + let origAssets = nativeAssetCache[bidRequest.adUnitCode]; + bidObject.native = utils.cleanObj(adm.assets.reduce((native, asset) => { + let origAsset = origAssets[asset.id]; + 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 (utils.isPlainObject(asset.title)) { + native['title'] = asset.title.text + } else if (utils.isPlainObject(asset.data)) { + nativeDataNames.forEach(dataType => { + if (nativeDataIdMap[dataType] === origAsset.data.type) { + native[dataType] = asset.data.value; + } + }); + } + return native; + }, utils.cleanObj({ + clickUrl: adm.link, + clickTrackers: utils.deepAccess(adm, 'link.clicktrackers'), + impressionTrackers: trackers[nativeEventTrackerMethodMap.img], + javascriptTrackers: trackers[nativeEventTrackerMethodMap.js] + }))); + } else { + utils.logError('prebid server native response contained no assets'); + } } else { // banner if (bid.adm && bid.nurl) { bidObject.ad = bid.adm; @@ -732,10 +919,13 @@ export function PrebidServer() { const adUnits = utils.deepClone(s2sBidRequest.ad_units); // at this point ad units should have a size array either directly or mapped so filter for that - const adUnitsWithSizes = adUnits.filter(unit => unit.sizes && unit.sizes.length); + const validAdUnits = adUnits.filter(unit => + (unit.sizes && unit.sizes.length) || + (unit.mediaTypes && unit.mediaTypes.native) + ); // in case config.bidders contains invalid bidders, we only process those we sent requests for - const requestedBidders = adUnitsWithSizes + const requestedBidders = validAdUnits .map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(utils.uniques)) .reduce(utils.flatten) .filter(utils.uniques); @@ -745,7 +935,7 @@ export function PrebidServer() { queueSync(_s2sConfig.bidders, consent); } - const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, adUnitsWithSizes); + const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, validAdUnits); const requestJson = request && JSON.stringify(request); if (request && requestJson) { ajax( diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index b165741b49d..560cab91dca 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -36,33 +36,6 @@ const cache = { timeouts: {}, }; -// basically lodash#pick that also allows transformation functions and property renaming -function _pick(obj, properties) { - return properties.reduce((newObj, prop, i) => { - if (typeof prop === 'function') { - return newObj; - } - - let newProp = prop; - let match = prop.match(/^(.+?)\sas\s(.+?)$/i); - - if (match) { - prop = match[1]; - newProp = match[2]; - } - - let value = obj[prop]; - if (typeof properties[i + 1] === 'function') { - value = properties[i + 1](value, newObj); - } - if (typeof value !== 'undefined') { - newObj[newProp] = value; - } - - return newObj; - }, {}); -} - function stringProperties(obj) { return Object.keys(obj).reduce((newObj, prop) => { let value = obj[prop]; @@ -98,7 +71,7 @@ function formatSource(src) { function sendMessage(auctionId, bidWonId) { function formatBid(bid) { - return _pick(bid, [ + return utils.pick(bid, [ 'bidder', 'bidId', 'status', @@ -113,7 +86,7 @@ function sendMessage(auctionId, bidWonId) { 'clientLatencyMillis', 'serverLatencyMillis', 'params', - 'bidResponse', bidResponse => bidResponse ? _pick(bidResponse, [ + 'bidResponse', bidResponse => bidResponse ? utils.pick(bidResponse, [ 'bidPriceUSD', 'dealId', 'dimensions', @@ -122,7 +95,7 @@ function sendMessage(auctionId, bidWonId) { ]); } 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, @@ -153,7 +126,7 @@ function sendMessage(auctionId, bidWonId) { 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', @@ -191,7 +164,7 @@ function sendMessage(auctionId, bidWonId) { // 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 = { @@ -237,7 +210,7 @@ function sendMessage(auctionId, bidWonId) { } export function parseBidResponse(bid) { - return _pick(bid, [ + return utils.pick(bid, [ 'bidPriceUSD', () => { if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === 'USD') { return Number(bid.cpm); @@ -251,7 +224,7 @@ export function parseBidResponse(bid) { 'dealId', 'status', 'mediaType', - 'dimensions', () => _pick(bid, [ + 'dimensions', () => utils.pick(bid, [ 'width', 'height' ]) @@ -327,7 +300,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { case AUCTION_INIT: // set the rubicon aliases setRubiconAliases(adapterManager.aliasRegistry); - let cacheEntry = _pick(args, [ + let cacheEntry = utils.pick(args, [ 'timestamp', 'timeout' ]); @@ -340,7 +313,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { // mark adUnits we expect bidWon events for cache.auctions[args.auctionId].bidsWon[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 @@ -349,7 +322,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' @@ -380,7 +353,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { } } }, - 'adUnit', () => _pick(bid, [ + 'adUnit', () => utils.pick(bid, [ 'adUnitCode', 'transactionId', 'sizes as dimensions', sizes => sizes.map(sizeToDimensions), diff --git a/src/utils.js b/src/utils.js index a43151f89e4..6f592a8bcfe 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1137,6 +1137,53 @@ export function convertCamelToUnderscore(value) { return value.replace(/(?:^|\.?)([A-Z])/g, function (x, y) { return '_' + y.toLowerCase() }).replace(/^_/, ''); } +/** + * Returns a new object with undefined properties removed from given object + * @param obj the object to clean + */ +export function cleanObj(obj) { + return Object.keys(obj).reduce((newObj, key) => { + if (typeof obj[key] !== 'undefined') { + newObj[key] = obj[key]; + } + return newObj; + }, {}) +} + +/** + * Create a new object with selected properties. Also allows property renaming and transform functions. + * @param obj the original object + * @param properties An array of desired properties + */ +export function pick(obj, properties) { + if (typeof obj !== 'object') { + return {}; + } + return properties.reduce((newObj, prop, i) => { + if (typeof prop === 'function') { + return newObj; + } + + let newProp = prop; + let match = prop.match(/^(.+?)\sas\s(.+?)$/i); + + if (match) { + prop = match[1]; + newProp = match[2]; + } + + let value = obj[prop]; + if (typeof properties[i + 1] === 'function') { + value = properties[i + 1](value, newObj); + } + if (typeof value !== 'undefined') { + newObj[newProp] = value; + } + + return newObj; + }, {}); +} + /** * Converts an object of arrays (either strings or numbers) into an array of objects containing key and value properties * normally read from bidder params diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 8b077ca796a..0542385c5d5 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -33,6 +33,19 @@ const REQUEST = { 'mediaTypes': { 'banner': { 'sizes': [[ 300, 250 ], [ 300, 300 ]] + }, + 'native': { + 'title': { + 'required': true, + 'len': 800 + }, + 'image': { + 'required': true, + 'sizes': [989, 742], + }, + 'sponsoredBy': { + 'required': true + } } }, 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', @@ -382,6 +395,93 @@ const RESPONSE_OPENRTB_VIDEO = { }, }; +const RESPONSE_OPENRTB_NATIVE = { + 'id': 'c7dcf14f', + 'seatbid': [ + { + 'bid': [ + { + 'id': '6451317310275562039', + 'impid': 'div-gpt-ad-1460505748561-0', + 'price': 10, + 'adm': { + 'ver': '1.2', + 'assets': [ + { + 'id': 1, + 'img': { + 'url': 'https://vcdn.adnxs.com/p/creative-image/f8/7f/0f/13/f87f0f13-230c-4f05-8087-db9216e393de.jpg', + 'w': 989, + 'h': 742, + 'ext': { + 'appnexus': { + 'prevent_crop': 0 + } + } + } + }, + { + 'id': 0, + 'title': { + 'text': 'This is a Prebid Native Creative' + } + }, + { + 'id': 2, + 'data': { + 'value': 'Prebid.org' + } + } + ], + 'link': { + 'url': 'https://lax1-ib.adnxs.com/click?AAAAAAAAJEAAAAAAAAAkQAAAAAAAACRAAAAAAAAAJEAAAAAAAAAkQGdce2vBWudAJZpFu1er1zA7ZzddAAAAAOLoyQBtJAAAbSQAAAIAAAC8pM8FnPgWAAAAAABVU0QAVVNEAAEAAQBNXQAAAAABAgMCAAAAALsAuhVqdgAAAAA./cpcpm=AAAAAAAAAAA=/bcr=AAAAAAAA8D8=/pp=${AUCTION_PRICE}/cnd=%213Q5HCQj8-LwKELzJvi4YnPFbIAQoADEAAAAAAAAkQDoJTEFYMTo0MDc3QKcPSQAAAAAAAPA_UQAAAAAAAAAAWQAAAAAAAAAAYQAAAAAAAAAAaQAAAAAAAAAAcQAAAAAAAAAA/cca=OTMyNSNMQVgxOjQwNzc=/bn=84305/test=1/clickenc=http%3A%2F%2Fprebid.org%2Fdev-docs%2Fshow-native-ads.html' + }, + 'eventtrackers': [ + { + 'event': 1, + 'method': 1, + 'url': 'https://lax1-ib.adnxs.com/it?an_audit=0&test=1&referrer=http%3A%2F%2Flocalhost%3A9999%2FintegrationExamples%2Fgpt%2Fdemo_native.html&e=wqT_3QKCCKACBAAAAwDWAAUBCLvO3ekFEOe47duW2NbzQBiltJba--rq6zAqNgkAAAECCCRAEQEHEAAAJEAZEQkAIREJACkRCQAxEQmoMOLRpwY47UhA7UhIAlC8yb4uWJzxW2AAaM26dXjRkgWAAQGKAQNVU0SSAQEG8FKYAQGgAQGoAQGwAQC4AQLAAQPIAQLQAQnYAQDgAQHwAQCKAjt1ZignYScsIDI1Mjk4ODUsIDE1NjM5MTE5OTUpO3VmKCdyJywgOTc0OTQyMDQsIC4eAPQ0AZICnQIhb2pkaWlnajgtTHdLRUx6SnZpNFlBQ0NjOFZzd0FEZ0FRQVJJN1VoUTR0R25CbGdBWVAwQmFBQndBSGdBZ0FFQWlBRUFrQUVCbUFFQm9BRUJxQUVEc0FFQXVRSHpyV3FrQUFBa1FNRUI4NjFxcEFBQUpFREpBVVZpYmxDaFpRQkEyUUVBQUFBQUFBRHdQLUFCQVBVQkFBQUFBUGdCQUpnQ0FLQUNBTFVDQUFBQUFMMENBQUFBQU1BQ0FNZ0NBT0FDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEX1BpOENyb0RDVXhCV0RFNk5EQTNOLUFEcHctUUJBQ1lCQUhCQkFBQUFBQUFBQUFBeVFRQUFBQUFBQUFBQU5nRUFBLi6aAoUBITNRNUhDUWo4LUx3S0VMeiUhJG5QRmJJQVFvQUQRvVhBa1FEb0pURUZZTVRvME1EYzNRS2NQUxFUDFBBX1URDAxBQUFXHQwAWR0MAGEdDABjHQz0FwHYAgDgAq2YSOoCPmh0dHA6Ly9sb2NhbGhvc3Q6OTk5OS9pbnRlZ3JhdGlvbkV4YW1wbGVzL2dwdC9kZW1vX25hdGl2ZS5odG1sgAMAiAMBkAMAmAMUoAMBqgMAwAPgqAHIAwDYAwDgAwDoAwD4AwOABACSBAkvb3BlbnJ0YjKYBACiBA0xNzMuMjQ0LjM2LjQwqATtoySyBAwIABAAGAAgADAAOAC4BADABADIBADSBA45MzI1I0xBWDE6NDA3N9oEAggB4AQA8AS8yb4uiAUBmAUAoAX___________8BqgUkZTU5YzNlYjYtNmRkNi00MmQ5LWExMWEtM2FhMTFjOTc5MGUwwAUAyQUAAAAAAADwP9IFCQkAaVh0ANgFAeAFAfAFmfQh-gUECAAQAJAGAZgGALgGAMEGCSQk8D_IBgDaBhYKEAkQGQEBwTTgBgzyBgIIAIAHAYgHAA..&s=11ababa390e9f7983de260493fc5b91ec5b1b3d4&pp=${AUCTION_PRICE}' + } + ] + }, + 'adid': '97494204', + 'adomain': [ + 'http://prebid.org' + ], + 'iurl': 'https://lax1-ib.adnxs.com/cr?id=97494204', + 'cid': '9325', + 'crid': '97494204', + 'cat': [ + 'IAB3-1' + ], + 'ext': { + 'prebid': { + 'targeting': { + 'hb_bidder': 'appnexus', + 'hb_pb': '10.00' + }, + 'type': 'native', + 'video': { + 'duration': 0, + 'primary_category': '' + } + }, + 'bidder': { + 'appnexus': { + 'brand_id': 555545, + 'auction_id': 4676806524825984103, + 'bidder_id': 2, + 'bid_ad_type': 3 + } + } + } + } + ], + 'seat': 'appnexus' + } + ] +}; + const RESPONSE_UNSUPPORTED_BIDDER = { 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', 'status': 'OK', @@ -641,7 +741,7 @@ describe('S2S Adapter', function () { }); }); - it('adds device and app objects to request for ORTB', function () { + it('adds device and app objects to request for OpenRTB', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -689,6 +789,54 @@ describe('S2S Adapter', function () { }); }); + it('adds native request for OpenRTB', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + + const _config = { + s2sConfig: s2sConfig + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.imp[0].native).to.deep.equal({ + request: JSON.stringify({ + 'context': 1, + 'plcmttype': 1, + 'eventtrackers': [{ + event: 1, + methods: [1] + }], + 'assets': [ + { + 'required': 1, + 'title': { + 'len': 800 + } + }, + { + 'required': 1, + 'img': { + 'type': 3, + 'w': 989, + 'h': 742 + } + }, + { + 'required': 1, + 'data': { + 'type': 1 + } + } + ] + }), + ver: '1.2' + }); + }); + it('adds site if app is not present', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' @@ -1404,6 +1552,33 @@ describe('S2S Adapter', function () { expect(response).to.have.property('vastUrl', 'https://prebid-cache.net/cache?uuid=a5ad3993'); }); + it('handles OpenRTB native responses', function () { + sinon.stub(utils, 'getBidRequest').returns({ + adUnitCode: 'div-gpt-ad-1460505748561-0', + bidder: 'appnexus', + bidId: '123' + }); + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' + }); + config.setConfig({s2sConfig}); + + server.respondWith(JSON.stringify(RESPONSE_OPENRTB_NATIVE)); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(addBidResponse); + const response = addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('adm').deep.equal(RESPONSE_OPENRTB_NATIVE.seatbid[0].bid[0].adm); + expect(response).to.have.property('mediaType', 'native'); + expect(response).to.have.property('bidderCode', 'appnexus'); + expect(response).to.have.property('requestId', '123'); + expect(response).to.have.property('cpm', 10); + + utils.getBidRequest.restore(); + }); + it('should log warning for unsupported bidder', function () { server.respondWith(JSON.stringify(RESPONSE_UNSUPPORTED_BIDDER)); From c079efeeaa9fce1b60c7a35a0fc0a471deb3a754 Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Tue, 30 Jul 2019 20:04:43 +0300 Subject: [PATCH 1387/1594] MarsMedia adapter: Update prebid api (#3978) * Create Mars bid adapter * Fix ESLint errors * Add more tab between 86-97 for ESLint --- modules/marsmediaBidAdapter.js | 130 ++++++++++++++++++ modules/marsmediaBidAdapter.md | 32 +++++ test/spec/modules/marsmediaBidAdapter_spec.js | 122 ++++++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 modules/marsmediaBidAdapter.js create mode 100644 modules/marsmediaBidAdapter.md create mode 100644 test/spec/modules/marsmediaBidAdapter_spec.js diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js new file mode 100644 index 00000000000..09eb4ac6c75 --- /dev/null +++ b/modules/marsmediaBidAdapter.js @@ -0,0 +1,130 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +const BIDDER_CODE = 'marsmedia'; + +function getDomain() { + if (!utils.inIframe()) { + return window.location.hostname + } + let origins = window.document.location.ancestorOrigins + if (origins && origins.length > 0) { + return origins[origins.length - 1] + } +} + +export const spec = { + code: BIDDER_CODE, + aliases: ['mars'], + isBidRequestValid: function(bid) { + return (bid.params.publisherID !== null); + }, + buildRequests: function(validBidRequests, bidderRequest) { + try { + let protocol = (window.location.protocol === 'https:'); + const parse = getSize(validBidRequests[0].sizes); + const publisherId = validBidRequests[0].params.publisherID; + const payload = { + id: validBidRequests[0].bidId, + cur: ['USD'], + + language: window.navigator.userLanguage || window.navigator.language, + site: { + id: publisherId, + domain: getDomain(), + page: document.URL, + ref: document.referrer, + publisher: { + id: publisherId, + domain: getDomain() + } + }, + imp: [{ + id: utils.getUniqueIdentifierStr(), + banner: { + w: parse.width, + h: parse.height, + secure: protocol + }, + bidfloor: parseFloat(validBidRequests[0].params.floor) > 0 ? validBidRequests[0].params.floor : 0 + }], + device: { + ua: navigator.userAgent + }, + user: { + id: publisherId + }, + publisher: { + id: publisherId, + domain: getDomain() + } + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr = { + applies: bidderRequest.gdprConsent.gdprApplies, + consent: bidderRequest.gdprConsent.consentString + }; + } + + return { + method: 'POST', + url: '//bid306.rtbsrv.com/bidder/?bid=3mhdom', + data: JSON.stringify(payload) + }; + } catch (e) { + utils.logError(e, {validBidRequests, bidderRequest}); + } + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + let res = serverResponse.body; + if (!res) { + return [] + } + + for (let x = 0; x < res.seatbid.length; x++) { + var bidAd = res.seatbid[x].bid[0]; + + bidResponses.push({ + requestId: res.id, + cpm: Number(bidAd.price), + width: bidAd.w, + height: bidAd.h, + ad: bidAd.adm, + ttl: 60, + creativeId: bidAd.cid, + netRevenue: true, + currency: 'USD' + }) + } + + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + return []; + } +}; + +function getSize(requestSizes) { + const parsed = {}; + const size = utils.parseSizesInput(requestSizes)[0]; + + if (typeof size !== 'string') { + return parsed; + } + + const parsedSize = size.toUpperCase().split('X'); + const width = parseInt(parsedSize[0], 10); + if (width) { + parsed.width = width; + } + + const height = parseInt(parsedSize[1], 10); + if (height) { + parsed.height = height; + } + + return parsed; +} + +registerBidder(spec); diff --git a/modules/marsmediaBidAdapter.md b/modules/marsmediaBidAdapter.md new file mode 100644 index 00000000000..fee962f9173 --- /dev/null +++ b/modules/marsmediaBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +``` +Module Name: Mars Media Group (mars.media) Bidder Adapter +Module Type: Bidder Adapter +Maintainer: vladi@mars.media +``` + +# Description + +Prebid adapter for Mars Media Group RTB. Requires approval and account setup. + +# Test Parameters + +## Web +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "marsmedia", + params: { + publisherID: 9999, + floor: 0.11 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js new file mode 100644 index 00000000000..a58857e0f3f --- /dev/null +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -0,0 +1,122 @@ +import { expect } from 'chai' +import { spec, _getPlatform } from 'modules/marsmediaBidAdapter' +import { newBidder } from 'src/adapters/bidderFactory' + +describe('marsmediaBidAdapter', function () { + const adapter = newBidder(spec) + + let bidRequest = { + 'bidId': '123', + 'sizes': [[ 300, 250 ]], + 'params': { + 'publisherID': 9999, + 'floor': 0.1 + } + } + + describe('codes', function () { + it('should return a bidder code of marsmedia', function () { + expect(spec.code).to.equal('marsmedia') + }) + it('should alias mars', function () { + expect(spec.aliases.length > 0 && spec.aliases[0] === 'mars').to.be.true + }) + }) + + describe('isBidRequestValid', function () { + it('should return true if all params present', function () { + expect(spec.isBidRequestValid(bidRequest)).to.be.true + }) + + it('should return false if any parameter missing', function () { + expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { publisherID: null } }))).to.be.false + }) + }) + + describe('buildRequests', function () { + let req = spec.buildRequests([ bidRequest ], { refererInfo: { } }) + 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 = JSON.parse(req.data) + expect(rdata.imp.length).to.equal(1) + }) + + it('should include all publisher params', function () { + let r = rdata.imp[0] + expect(r.publisherID !== null).to.be.true + }) + }) + + describe('interpretResponse', function () { + let response; + beforeEach(function () { + response = { + body: { + 'id': '37386aade21a71', + 'seatbid': [{ + 'bid': [{ + 'id': '1', + 'impid': '1', + 'cid': '1', + 'price': 0.1, + 'nurl': '', + 'adm': '', + 'w': 320, + 'h': 250 + }] + }] + } + }; + }); + + it('should get the correct bid response', function () { + let expectedResponse = [{ + 'requestId': '37386aade21a71', + 'cpm': 0.1, + 'width': 320, + 'height': 250, + 'creativeId': '1', + 'currency': 'USD', + 'netRevenue': true, + 'ad': ``, + 'ttl': 60 + }]; + + let result = spec.interpretResponse(response); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + 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({ iframeEnabled: true }) + expect(sync.length).to.equal(1) + expect(sync[0].type === 'iframe') + expect(typeof sync[0].url === 'string') + }) + + it('should return pixel sync', function () { + let sync = spec.getUserSyncs({ pixelEnabled: true }) + expect(sync.length).to.equal(1) + expect(sync[0].type === 'image') + expect(typeof sync[0].url === 'string') + }) */ + }) +}) From e603156fba59a32e47168b2e69cc7511bad0b473 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 30 Jul 2019 15:29:38 -0400 Subject: [PATCH 1388/1594] Appnexus native view tracker (#4022) * First pass: adding viewability script to rtbBid * Added viewability scrit in the right place * Clean up * Corrected script position, added a workaround to get the adId after the bid's creation and fixed tests * Removed debugging logs * More cleanup * Opted to append rtbBid.viewability.config to the existing (nativeAd.javascript_trackers) in the bidAdapter's newBid function * Removed AnalyticsAdaper code and added bidAdapter.onBidWon to check for our jstracker and update their src attributes. * Added a way to differentiate scripts and clean up * Changed newBid to disarm jstracker before it's ready and changed onBidWon to arm it. This prevents the tracker from being loaded twice. * Making the code more robust * Grouped code in a function. Also changed parameters to reflect that finding the element will now fall be a view_js responsability. * Changed parameter pbjs_iframeid name to pbjs_auc so its not misleading * Variable name change to better reflect its nature * Fixing URL parameters (; separated and replacing completely the useless one) * undo changes to appnexus Analytics adapter * update regex variable * update regex again --- modules/appnexusBidAdapter.js | 116 ++++++++++++++++++- src/native.js | 1 - test/spec/modules/appnexusBidAdapter_spec.js | 12 +- test/spec/unit/pbjs_api_spec.js | 12 +- 4 files changed, 134 insertions(+), 7 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 67388848815..d0f4774185e 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -33,6 +33,9 @@ const NATIVE_MAPPING = { const SOURCE = 'pbjs'; const MAX_IMPS_PER_REQUEST = 15; const mappingFileUrl = '//acdn.adnxs.com/prebid/appnexus-mapping/mappings.json'; +const SCRIPT_TAG_START = '= 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 (utils.isStr(jsTrackerArray) && strIsAppnexusViewabilityScript(jsTrackerArray)) { + viewJsPayload = jsTrackerArray; + } else if (utils.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 formatRequest(payload, bidderRequest) { let request = []; @@ -415,6 +513,22 @@ function newBid(serverBid, rtbBid, bidderRequest) { } } 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 (utils.isStr(jsTrackers)) { + jsTrackers = [jsTrackers, jsTrackerDisarmed]; + } else { + jsTrackers.push(jsTrackerDisarmed); + } + bid[NATIVE] = { title: nativeAd.title, body: nativeAd.desc, @@ -433,7 +547,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { displayUrl: nativeAd.displayurl, clickTrackers: nativeAd.link.click_trackers, impressionTrackers: nativeAd.impression_trackers, - javascriptTrackers: nativeAd.javascript_trackers + javascriptTrackers: jsTrackers }; if (nativeAd.main_img) { bid['native'].image = { diff --git a/src/native.js b/src/native.js index c9a67ca7541..6252eb133b3 100644 --- a/src/native.js +++ b/src/native.js @@ -132,7 +132,6 @@ export function nativeBidIsValid(bid, bidRequests) { */ export function fireNativeTrackers(message, adObject) { let trackers; - if (message.action === 'click') { trackers = adObject['native'] && adObject['native'].clickTrackers; } else { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 30d2dc08159..e1cca8c05ff 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -665,6 +665,9 @@ describe('AppNexusAdapter', function () { 'cpm_publisher_currency': 0.5, 'publisher_currency_code': '$', 'client_initiated_ad_counting': true, + 'viewability': { + 'config': '' + }, 'rtb': { 'banner': { 'content': '', @@ -744,7 +747,8 @@ describe('AppNexusAdapter', function () { 'video': { 'content': '' } - } + }, + 'javascriptTrackers': '' }] }] }; @@ -775,6 +779,9 @@ describe('AppNexusAdapter', function () { 'content': '', 'duration_ms': 30000, } + }, + 'viewability': { + 'config': '' } }] }] @@ -831,7 +838,8 @@ describe('AppNexusAdapter', function () { 'saleprice': 'FREE', 'phone': '1234567890', 'address': '28 W 23rd St, New York, NY 10010', - 'privacy_link': 'http://appnexus.com/?url=privacy_url' + 'privacy_link': 'http://appnexus.com/?url=privacy_url', + 'javascriptTrackers': '' }; let bidderRequest = { bids: [{ diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index d4daec0c266..c73604cac82 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -434,7 +434,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] }; @@ -574,7 +576,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] }; @@ -606,7 +610,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] }; From e8ed8f3aaf8bc674bdf192a5988b5ed4d9f0fb6d Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 30 Jul 2019 15:43:45 -0400 Subject: [PATCH 1389/1594] Prebid 2.26.0 release --- package-lock.json | 805 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 398 insertions(+), 409 deletions(-) diff --git a/package-lock.json b/package-lock.json index 56cac603a79..0c84e4db70d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,49 +1,49 @@ { "name": "prebid.js", - "version": "2.23.0-pre", + "version": "2.26.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", "dev": true, "requires": { "@babel/highlight": "^7.0.0" } }, "@babel/core": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", - "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helpers": "^7.4.4", - "@babel/parser": "^7.4.5", + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.5", - "@babel/types": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" } }, "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", "dev": true, "requires": { - "@babel/types": "^7.4.4", + "@babel/types": "^7.5.5", "jsesc": "^2.5.1", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -79,14 +79,14 @@ } }, "@babel/helper-define-map": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", - "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", + "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" } }, "@babel/helper-explode-assignable-expression": { @@ -129,12 +129,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", + "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.5.5" } }, "@babel/helper-module-imports": { @@ -147,17 +147,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", - "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", + "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-simple-access": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", "@babel/template": "^7.4.4", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" } }, "@babel/helper-optimise-call-expression": { @@ -176,12 +176,12 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", - "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.13" } }, "@babel/helper-remap-async-to-generator": { @@ -198,15 +198,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", - "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", + "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-member-expression-to-functions": "^7.5.5", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" } }, "@babel/helper-simple-access": { @@ -241,20 +241,20 @@ } }, "@babel/helpers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", - "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", "dev": true, "requires": { "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" } }, "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", "dev": true, "requires": { "chalk": "^2.0.0", @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -279,6 +279,16 @@ "@babel/plugin-syntax-async-generators": "^7.2.0" } }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", + "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0" + } + }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", @@ -290,9 +300,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", - "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", + "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -329,6 +339,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", + "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", @@ -366,9 +385,9 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", - "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", + "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -386,27 +405,27 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", - "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", + "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.11" + "lodash": "^4.17.13" } }, "@babel/plugin-transform-classes": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", - "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", + "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.4", + "@babel/helper-define-map": "^7.5.5", "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", + "@babel/helper-replace-supers": "^7.5.5", "@babel/helper-split-export-declaration": "^7.4.4", "globals": "^11.1.0" } @@ -421,9 +440,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", - "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", + "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -441,9 +460,9 @@ } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", - "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", + "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -497,34 +516,37 @@ } }, "@babel/plugin-transform-modules-amd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", - "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", + "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", - "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", + "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" + "@babel/helper-simple-access": "^7.1.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", - "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", + "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-umd": { @@ -556,13 +578,13 @@ } }, "@babel/plugin-transform-object-super": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", - "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", + "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" + "@babel/helper-replace-supers": "^7.5.5" } }, "@babel/plugin-transform-parameters": { @@ -662,43 +684,45 @@ } }, "@babel/preset-env": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", - "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", + "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-dynamic-import": "^7.5.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.4", + "@babel/plugin-proposal-object-rest-spread": "^7.5.5", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.4", + "@babel/plugin-transform-async-to-generator": "^7.5.0", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.4", - "@babel/plugin-transform-classes": "^7.4.4", + "@babel/plugin-transform-block-scoping": "^7.5.5", + "@babel/plugin-transform-classes": "^7.5.5", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.4", + "@babel/plugin-transform-destructuring": "^7.5.0", "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-duplicate-keys": "^7.5.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", "@babel/plugin-transform-for-of": "^7.4.4", "@babel/plugin-transform-function-name": "^7.4.4", "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.4", - "@babel/plugin-transform-modules-systemjs": "^7.4.4", + "@babel/plugin-transform-modules-amd": "^7.5.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", + "@babel/plugin-transform-modules-systemjs": "^7.5.0", "@babel/plugin-transform-modules-umd": "^7.2.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-object-super": "^7.5.5", "@babel/plugin-transform-parameters": "^7.4.4", "@babel/plugin-transform-property-literals": "^7.2.0", "@babel/plugin-transform-regenerator": "^7.4.5", @@ -709,7 +733,7 @@ "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.4.4", + "@babel/types": "^7.5.5", "browserslist": "^4.6.0", "core-js-compat": "^3.1.1", "invariant": "^2.2.2", @@ -729,30 +753,30 @@ } }, "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.11" + "lodash": "^4.17.13" } }, "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } }, @@ -829,14 +853,6 @@ "dev": true, "requires": { "samsam": "1.3.0" - }, - "dependencies": { - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - } } }, "@sinonjs/samsam": { @@ -923,9 +939,9 @@ } }, "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, "after": { @@ -1093,12 +1109,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "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.11" + "lodash": "^4.17.14" } } } @@ -1762,6 +1778,15 @@ "babel-runtime": "^6.22.0" } }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", @@ -2701,15 +2726,15 @@ } }, "bfj": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", - "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", + "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "check-types": "^7.3.0", - "hoopy": "^0.1.2", - "tryer": "^1.0.0" + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" } }, "big.js": { @@ -2816,6 +2841,12 @@ "toidentifier": "1.0.0" } }, + "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", @@ -2988,14 +3019,14 @@ } }, "browserslist": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", - "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", + "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000975", - "electron-to-chromium": "^1.3.164", - "node-releases": "^1.1.23" + "caniuse-lite": "^1.0.30000984", + "electron-to-chromium": "^1.3.191", + "node-releases": "^1.1.25" } }, "browserstack": { @@ -3008,30 +3039,15 @@ } }, "browserstack-local": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", - "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.2.tgz", + "integrity": "sha512-fRaynjF0MvtyyfPRy2NFnVwxLyNtD28K/v9xRsIjUVf7xLc80NIm7Nfr3KXlFmWizhG91PL/UAOXlHkoxQjaNw==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1", "is-running": "^2.0.0", "ps-tree": "=1.1.1", - "sinon": "^1.17.6", "temp-fs": "^0.9.9" - }, - "dependencies": { - "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": ">=0.10.3 <1" - } - } } }, "buffer": { @@ -3165,7 +3181,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3231,9 +3247,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000975", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", - "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", + "version": "1.0.30000987", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000987.tgz", + "integrity": "sha512-O3VrjtRMTxoU5Cn5/QSmXeIR1gkVps4j9jqfIm4FLaQ5JzqBlVjMUG1xWnoYFv8N+H3Lp++aa05TekyIbjHL7g==", "dev": true }, "caseless": { @@ -3320,9 +3336,9 @@ "dev": true }, "check-types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", - "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", + "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": { @@ -3774,9 +3790,9 @@ }, "dependencies": { "semver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", - "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -3794,13 +3810,13 @@ "dev": true }, "coveralls": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.4.tgz", - "integrity": "sha512-eyqUWA/7RT0JagiL0tThVhjbIjoiEUyWCjtUJoOPcWoeofP5WK/jb2OJYoBFrR6DvplR+AxOyuBqk4JHkk5ykA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", + "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", "dev": true, "requires": { "growl": "~> 1.10.0", - "js-yaml": "^3.11.0", + "js-yaml": "^3.13.1", "lcov-parse": "^0.0.10", "log-driver": "^1.2.7", "minimist": "^1.2.0", @@ -4729,15 +4745,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.164", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", - "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", + "version": "1.3.205", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.205.tgz", + "integrity": "sha512-VV+f2FVeFI5D/slUD7A3V1lTMDkQTUGWYH2dZGAijIutN5Aga4Fn/Hv4Gc+60OpXFVLYIq5HpXb2cG6NrGGQaA==", "dev": true }, "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -4779,7 +4795,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4793,7 +4809,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4809,7 +4825,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4835,7 +4851,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -5212,9 +5228,9 @@ } }, "eslint-module-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", - "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", "dev": true, "requires": { "debug": "^2.6.8", @@ -5291,9 +5307,9 @@ } }, "eslint-plugin-import": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", - "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -5303,8 +5319,8 @@ "eslint-import-resolver-node": "^0.3.2", "eslint-module-utils": "^2.4.0", "has": "^1.0.3", - "lodash": "^4.17.11", "minimatch": "^3.0.4", + "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", "resolve": "^1.11.0" }, @@ -5446,6 +5462,10 @@ } } }, + "eslint-plugin-prebid": { + "version": "file:plugins/eslint", + "dev": true + }, "eslint-plugin-promise": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", @@ -5538,7 +5558,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5778,13 +5798,13 @@ } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", + "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" @@ -6196,9 +6216,9 @@ } }, "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, "flush-write-stream": { @@ -6275,15 +6295,6 @@ "mime-types": "^2.1.12" } }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "~1.1" - } - }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -6921,9 +6932,9 @@ } }, "fun-hooks": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.3.tgz", - "integrity": "sha512-MC/zsGf+duq8lI6xym+H8HuL6DE1fLyE90FRzU/j2lTDmjDJ//+KC7M8vLzG9y/mhkLOH5u9wK4QEf3lBqIo4w==" + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.5.tgz", + "integrity": "sha512-xaj0r9Ex0dvehX8MbQSK/5EYVAddyoaK2sGNuQWX8xNaCiHtr/4zD9J10Y2irkFIsuaxbYOsQBKXvTHzjO2IFQ==" }, "function-bind": { "version": "1.1.1", @@ -7221,9 +7232,9 @@ } }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", + "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==", "dev": true }, "grapheme-splitter": { @@ -7672,7 +7683,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7689,7 +7700,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -7790,22 +7801,22 @@ "dev": true }, "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "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._reinterpolate": "^3.0.0", "lodash.templatesettings": "^4.0.0" } }, "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "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" + "lodash._reinterpolate": "^3.0.0" } } } @@ -7867,9 +7878,9 @@ } }, "gulp-match": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", - "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", + "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, "requires": { "minimatch": "^3.0.3" @@ -8146,9 +8157,9 @@ }, "dependencies": { "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -8416,7 +8427,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8424,6 +8435,14 @@ "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "http-parser-js": { @@ -8461,12 +8480,12 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", + "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", "dev": true, "requires": { - "agent-base": "^4.1.0", + "agent-base": "^4.3.0", "debug": "^3.1.0" }, "dependencies": { @@ -8540,9 +8559,9 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "ini": { @@ -8679,12 +8698,6 @@ "is-decimal": "^1.0.0" } }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8811,12 +8824,6 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", - "dev": true - }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -9125,12 +9132,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "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.11" + "lodash": "^4.17.14" } } } @@ -9409,7 +9416,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9629,12 +9636,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "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.11" + "lodash": "^4.17.14" } } } @@ -9800,9 +9807,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "lodash._basecopy": { @@ -10040,7 +10047,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -10053,7 +10060,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true }, "debug": { @@ -10078,9 +10085,9 @@ } }, "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", "dev": true }, "longest": { @@ -10639,14 +10646,14 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -10675,7 +10682,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -11033,22 +11040,13 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } } } }, "node-releases": { - "version": "1.1.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", - "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", + "version": "1.1.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", + "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", "dev": true, "requires": { "semver": "^5.3.0" @@ -11234,18 +11232,6 @@ "isobject": "^3.0.0" } }, - "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -11306,6 +11292,18 @@ "make-iterator": "^1.0.0" } }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -11368,7 +11366,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11567,9 +11565,9 @@ } }, "mocha": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", - "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", + "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -12035,9 +12033,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "progress": { @@ -12090,9 +12088,9 @@ "dev": true }, "psl": { - "version": "1.1.32", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", - "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", + "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==", "dev": true }, "public-encrypt": { @@ -12388,9 +12386,9 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", - "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", "dev": true, "requires": { "private": "^0.1.6" @@ -12416,9 +12414,9 @@ } }, "regexp-tree": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", - "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", + "integrity": "sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg==", "dev": true }, "regexpp": { @@ -12716,6 +12714,14 @@ "requires": { "caller-path": "^0.1.0", "resolve-from": "^1.0.0" + }, + "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 + } } }, "requires-port": { @@ -12725,9 +12731,9 @@ "dev": true }, "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -12744,9 +12750,9 @@ } }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, "resolve-options": { @@ -12878,9 +12884,9 @@ "dev": true }, "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "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": { @@ -13019,13 +13025,13 @@ } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", + "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" @@ -13073,9 +13079,9 @@ "dev": true }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -13181,12 +13187,6 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true - }, - "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true } } }, @@ -13330,7 +13330,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -13344,7 +13344,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13367,7 +13367,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -13395,7 +13395,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13411,7 +13411,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13429,7 +13429,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13537,14 +13537,14 @@ } }, "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13678,7 +13678,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13940,9 +13940,9 @@ } }, "ternary-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", - "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", + "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", "dev": true, "requires": { "duplexify": "^3.5.0", @@ -14434,38 +14434,15 @@ } }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "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": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "unique-stream": { @@ -14679,7 +14656,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14687,16 +14664,20 @@ } }, "util": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", - "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, "requires": { - "inherits": "2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "object.entries": "^1.1.0", - "safe-buffer": "^5.1.2" + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "util-deprecate": { @@ -15088,9 +15069,9 @@ }, "dependencies": { "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -15100,18 +15081,18 @@ } }, "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "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.11" + "lodash": "^4.17.14" } }, "camelcase": { @@ -15404,9 +15385,9 @@ } }, "webpack-bundle-analyzer": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", - "integrity": "sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", + "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", "dev": true, "requires": { "acorn": "^6.0.7", @@ -15418,16 +15399,16 @@ "express": "^4.16.3", "filesize": "^3.6.1", "gzip-size": "^5.0.0", - "lodash": "^4.17.10", + "lodash": "^4.17.15", "mkdirp": "^0.5.1", "opener": "^1.5.1", "ws": "^6.0.0" }, "dependencies": { "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", "dev": true }, "ejs": { @@ -15476,7 +15457,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -15990,6 +15971,14 @@ "dev": true, "requires": { "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "vinyl": { @@ -16204,9 +16193,9 @@ "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "y18n": { diff --git a/package.json b/package.json index 9d2bb82f25c..39c720953e2 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.26.0-pre", + "version": "2.26.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4817ef6977b506797e1723c6841a3dd843c1a6a3 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 30 Jul 2019 16:12:05 -0400 Subject: [PATCH 1390/1594] increment pre version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c84e4db70d..06746ab8c41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.26.0", + "version": "2.27.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 39c720953e2..cb921f61bed 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.26.0", + "version": "2.27.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 9b5083d028608ba0c949a9d1ec545ec2bd7e8dcf Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Tue, 30 Jul 2019 23:52:46 +0300 Subject: [PATCH 1391/1594] Fix referrer encoding in The Media Grid Bid Adapter (#4040) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Add video support in Grid Bid Adapter * Added test parameter for video slot * update Grid Bid Adapter to set size in response bid * Update Grid Bid Adapter to support identical uids in parameters * Fix typo in test file for Grid Bid Adapter * Update The Grid Media Bidder Adapter to send refererInfo.referer as 'u' parameter in ad request * Hotfix for referrer in Grid Bid Adapter --- modules/gridBidAdapter.js | 2 +- test/spec/modules/gridBidAdapter_spec.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index ee1ae85e7ee..2deaebf0635 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -86,7 +86,7 @@ export const spec = { if (bidderRequest) { if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + payload.u = bidderRequest.refererInfo.referer; } if (bidderRequest.timeout) { payload.wtimeout = bidderRequest.timeout; diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index d9bfb9e971a..a191d2211f5 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -48,7 +48,7 @@ describe('TheMediaGrid Adapter', function () { return res; } const bidderRequest = {refererInfo: {referer: 'http://example.com'}}; - const encodedReferer = encodeURIComponent(bidderRequest.refererInfo.referer); + const referrer = bidderRequest.refererInfo.referer; let bidRequests = [ { 'bidder': 'grid', @@ -89,7 +89,7 @@ describe('TheMediaGrid Adapter', function () { const request = spec.buildRequests([bidRequests[0]], bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('auids', '1'); expect(payload).to.have.property('sizes', '300x250,300x600'); expect(payload).to.have.property('r', '22edbae2733bf6'); @@ -99,7 +99,7 @@ describe('TheMediaGrid Adapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('auids', '1,1,2'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); @@ -109,7 +109,7 @@ describe('TheMediaGrid Adapter', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}, refererInfo: bidderRequest.refererInfo}); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('gdpr_consent', 'AAA'); expect(payload).to.have.property('gdpr_applies', '1'); }); From 30cfb6d09cc8df0ada535ad2399889045e05f3b5 Mon Sep 17 00:00:00 2001 From: Gaudeamus Date: Wed, 31 Jul 2019 07:56:52 +0300 Subject: [PATCH 1392/1594] [mgid] add referrer and utc offset to bid request (#4023) * make placementId optional * get referrer * fix formatting * fix formatting --- modules/mgidBidAdapter.js | 64 ++++++++++++++-------- test/spec/modules/mgidBidAdapter_spec.js | 68 +++++++++++++++++++----- 2 files changed, 96 insertions(+), 36 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index c3f88106893..154c00f6a06 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -60,7 +60,7 @@ utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); export const spec = { - VERSION: '1.3', + VERSION: '1.4', code: BIDDER_CODE, supportedMediaTypes: [BANNER, NATIVE], reId: /^[1-9][0-9]*$/, @@ -118,8 +118,9 @@ export const spec = { if (validBidRequests.length === 0) { return; } - const referer = utils.deepAccess(bidderRequest, 'refererInfo.referer'); - const hostname = urlUtils.parse(referer).hostname; + const info = pageInfo(); + const page = info.location || utils.deepAccess(bidderRequest, 'refererInfo.referer') || utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl'); + const hostname = urlUtils.parse(page).hostname; let domain = extractDomainFromHost(hostname) || hostname; const accountId = setOnAny(validBidRequests, 'params.accountId'); const muid = getLocalStorageSafely('mgMuidn'); @@ -127,8 +128,7 @@ export const spec = { if (utils.isStr(muid) && muid.length > 0) { url += '?muid=' + muid; } - const cur = [config.getConfig('currency.adServerCurrency') || setOnAny(validBidRequests, 'params.currency') || setOnAny(validBidRequests, 'params.cur') || DEFAULT_CUR]; - const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || referer; + 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 => { @@ -166,22 +166,11 @@ export const spec = { return; } - let ext = {mgid_ver: spec.VERSION, prebid_ver: $$PREBID_GLOBAL$$.version}; - let user = {}; - let regs = {}; - if (bidderRequest && bidderRequest.gdprConsent) { - user.ext = { - consent: bidderRequest.gdprConsent.consentString - }; - - regs.ext = { - gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) - }; - } let request = { id: utils.deepAccess(bidderRequest, 'bidderRequestId'), - site: { domain, page }, + site: {domain, page}, cur: cur, + geo: {utcoffset: info.timeOffset}, device: { ua: navigator.userAgent, js: 1, @@ -190,11 +179,16 @@ export const spec = { w: screen.width, language: getLanguage() }, - user, - regs, - ext, + ext: {mgid_ver: spec.VERSION, prebid_ver: $$PREBID_GLOBAL$$.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 + } utils.logInfo(LOG_INFO_PREFIX + `buildRequest:`, request); return { method: 'POST', @@ -376,11 +370,14 @@ function createBannerRequest(bid) { } } } - return { + let r = { w: sizes && sizes[0][0], h: sizes && sizes[0][1], - format, + }; + if (format.length) { + r.format = format } + return r } function createNativeRequest(params) { @@ -558,3 +555,24 @@ function parseNativeResponse(bid, newBid) { } } } + +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() + }; +} diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index 2216122da18..4a9f25a29a7 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -30,6 +30,7 @@ describe('Mgid bid adapter', function () { const secure = window.location.protocol === 'https:' ? 1 : 0; const mgid_ver = spec.VERSION; const prebid_ver = $$PREBID_GLOBAL$$.version; + const utcOffset = (new Date()).getTimezoneOffset().toString(); describe('isBidRequestValid', function () { let bid = { @@ -359,13 +360,14 @@ describe('Mgid bid adapter', function () { } }; let bidRequests = [bid]; - const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); - const domain = urlUtils.parse(referer).hostname; + const page = top.location.href; + const domain = urlUtils.parse(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); @@ -373,12 +375,12 @@ describe('Mgid bid adapter', function () { 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, format: []}); + 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 + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250,\"format\":[]}}]}', + '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\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250}}]}', }); }); it('should not return native imp if minimum asset list not requested', function () { @@ -406,14 +408,15 @@ describe('Mgid bid adapter', function () { }; let bidRequests = [bid]; - const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); - const domain = urlUtils.parse(referer).hostname; + const page = top.location.href; + const domain = urlUtils.parse(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); @@ -426,7 +429,44 @@ describe('Mgid bid adapter', function () { expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"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}}]}}}]}', + '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\":\"' + prebid_ver + '\"},\"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', 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 = urlUtils.parse(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\":\"' + prebid_ver + '\"},\"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 () { @@ -441,14 +481,15 @@ describe('Mgid bid adapter', function () { }; let bidRequests = [bid]; - const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); - const domain = urlUtils.parse(referer).hostname; + const page = top.location.href; + const domain = urlUtils.parse(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); @@ -461,7 +502,7 @@ describe('Mgid bid adapter', function () { expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"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}}]}}}]}', + '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\":\"' + prebid_ver + '\"},\"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 () { @@ -474,12 +515,13 @@ describe('Mgid bid adapter', function () { let bidRequests = [bid]; const request = spec.buildRequests(bidRequests); - const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); - const domain = urlUtils.parse(referer).hostname; + const page = top.location.href; + const domain = urlUtils.parse(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); @@ -493,7 +535,7 @@ describe('Mgid bid adapter', function () { expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', + '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\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', }); }); }); From 918305fbd269ff3167fdf9a977d1e45d2a1be37a Mon Sep 17 00:00:00 2001 From: ucfunnel <39581136+ucfunnel@users.noreply.github.com> Date: Wed, 31 Jul 2019 13:01:00 +0800 Subject: [PATCH 1393/1594] ucfunnel support tdid (#3977) * ucfunnel tdid support --- modules/ucfunnelBidAdapter.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index c1ac951066d..7974f053bbd 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -168,7 +168,7 @@ function getRequestData(bid, bidderRequest) { const dnt = (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0; const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - + const userIdTdid = (bid.userId && bid.userId.tdid) ? bid.userId.tdid : ''; // general bid data let bidData = { ver: VER, @@ -181,7 +181,8 @@ function getRequestData(bid, bidderRequest) { ru: ref, adid: utils.getBidIdParameter('adid', bid.params), w: size[0], - h: size[1] + h: size[1], + tdid: userIdTdid }; if (bid.mediaType === 'video' || videoMediaType) { From 4d1bad5a943d076c09f9a3f5aa6b83ff1c2d664e Mon Sep 17 00:00:00 2001 From: mafernandez80 <50341807+mafernandez80@users.noreply.github.com> Date: Wed, 31 Jul 2019 02:08:24 -0300 Subject: [PATCH 1394/1594] Reload Adapter & Spec: Added GDPR and multiple sizes (#3967) * Reload Adapter & Spec: Added GDPR and multiple sizes * Reload Adapter - Fixed LGTM alert * Reload Adapter - Fixed import (path relative) * Reload Adapter: Read values from refererInfo and utils class. * Reload Adapter - Added onBidWon * Reload Adapter - Changed attribute's name * Reload Adapter - Backward Compatibility * Reload Adapter - Backward compatibility --- modules/reloadBidAdapter.js | 183 +++++++++++---------- test/spec/modules/reloadBidAdapter_spec.js | 6 +- 2 files changed, 96 insertions(+), 93 deletions(-) diff --git a/modules/reloadBidAdapter.js b/modules/reloadBidAdapter.js index a5f5ba43c60..4ecd4ff3390 100644 --- a/modules/reloadBidAdapter.js +++ b/modules/reloadBidAdapter.js @@ -1,18 +1,13 @@ -import { - BANNER -} - from '../src/mediaTypes'; import { registerBidder } from '../src/adapters/bidderFactory'; - +import * as utils from '../src/utils'; const BIDDER_CODE = 'reload'; - -const VERSION_ADAPTER = '1.0'; - +const VERSION_ADAPTER = '1.10'; export const spec = { code: BIDDER_CODE, + png: {}, /** * Determines whether or not the given bid request is valid. * @@ -31,31 +26,31 @@ export const spec = { */ buildRequests: function (validBidRequests, bidderRequest) { let vRequests = []; - let bidReq = { id: Math.random().toString(10).substring(2), imp: [] }; - + let vgdprConsent = null; + if (utils.deepAccess(bidderRequest, 'gdprConsent')) { + vgdprConsent = bidderRequest.gdprConsent; + } let vPrxClientTool = null; + let vSrvUrl = null; for (let vIdx = 0; vIdx < validBidRequests.length; vIdx++) { let bidRequest = validBidRequests[vIdx]; - - if (BANNER in bidRequest.mediaTypes !== true) continue; - if (bidRequest.mediaTypes.banner.sizes.length <= 0) continue; - - let vDim = bidRequest.mediaTypes.banner.sizes[0]; - vPrxClientTool = new ReloadClientTool({ prxVer: VERSION_ADAPTER, prxType: 'bd', - plcmID: bidRequest.params.plcmID, partID: bidRequest.params.partID, opdomID: bidRequest.params.opdomID, - bsrvID: bidRequest.params.bsrvID + bsrvID: bidRequest.params.bsrvID, + gdprObj: vgdprConsent, + mediaObj: bidRequest.mediaTypes, + wnd: utils.getWindowTop(), + rtop: utils.deepAccess(bidderRequest, 'refererInfo.reachedTop') || false }); - + if (vSrvUrl === null) vSrvUrl = vPrxClientTool.getSrvUrl(); let vImpression = { id: bidRequest.bidId, bidId: bidRequest.bidId, @@ -63,10 +58,7 @@ export const spec = { transactionId: bidRequest.transactionId, bidderRequestId: bidRequest.bidderRequestId, auctionId: bidRequest.auctionId, - banner: { - h: vDim[1], - w: vDim[0], ext: { type: bidRequest.params.type || 'pcm', pcmdata: vPrxClientTool.getPCMObj() @@ -75,12 +67,11 @@ export const spec = { }; bidReq.imp.push(vImpression); } - if (bidReq.imp.length > 0) { const payloadString = JSON.stringify(bidReq); vRequests.push({ method: 'POST', - url: vPrxClientTool.getSrvUrl(), + url: vSrvUrl, data: payloadString }); } @@ -94,64 +85,57 @@ export const spec = { */ interpretResponse: function (serverResponse, bidRequest) { const serverBody = serverResponse.body; - const bidResponses = []; - for (let vIdx = 0; vIdx < serverBody.seatbid.length; vIdx++) { let vSeatBid = serverBody.seatbid[vIdx]; - for (let vIdxBid = 0; vIdxBid < vSeatBid.bid.length; vIdxBid++) { let vBid = vSeatBid.bid[vIdxBid]; - let vPrxClientTool = new ReloadClientTool({ plcmID: vBid.ext.plcmID, partID: vBid.ext.partID, opdomID: vBid.ext.opdomID, bsrvID: vBid.ext.bsrvID }); - vPrxClientTool.setPCMObj(vBid.ext.pcmdata); - if (vPrxClientTool.getBP() > 0) { let bidResponse = { requestId: vBid.impid, ad: vPrxClientTool.getAM(), cpm: vPrxClientTool.getBP() / 100, - width: vBid.ext.banner.w, - height: vBid.ext.banner.h, + width: vPrxClientTool.getW(), + height: vPrxClientTool.getH(), creativeId: vBid.id, currency: vPrxClientTool.getBC(), ttl: 300, netRevenue: true }; bidResponses.push(bidResponse); + this.png[vBid.ext.adUnitCode] = vPrxClientTool.getPingUrl('bidwon'); } } } - return bidResponses; + }, + /** + * 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) { + if (typeof this.png[bid.adUnitCode] !== 'string' || this.png[bid.adUnitCode] === '') return; + (new Image()).src = this.png[bid.adUnitCode]; } }; -/** - * Reload Client Tool - * @param {json} args - */ - function ReloadClientTool(args) { var that = this; - var _pcmClientVersion = '120'; var _pcmFilePref = 'prx_root_'; var _resFilePref = 'prx_pnws_'; - - var _pcmInputObjVers = '100'; - + var _pcmInputObjVers = '120'; var _instObj = null; var _status = 'NA'; var _message = ''; var _log = ''; - var _memFile = _getMemFile(); if (_memFile.status !== 'ok') { @@ -161,12 +145,12 @@ function ReloadClientTool(args) { that.getPCMObj = function () { return { thisVer: _pcmInputObjVers, - statStr: _memFile.statStr, plcmData: _getPlcmData(), - clntData: _getClientData(), + clntData: _getClientData(args.wnd, args.rtop), resultData: _getRD(), - + gdprObj: _getGdpr(), + mediaObj: _getMediaObj(), proxetString: null, dboData: null, plcmSett: null, @@ -210,32 +194,34 @@ function ReloadClientTool(args) { } }; + that.getMT = function () { + return _checkInstProp('mtype', 'dsp'); + }; + + that.getW = function () { + return _checkInstProp('width', 0); + }; + + that.getH = function () { + return _checkInstProp('height', 0); + }; + that.getBP = function () { - if (_instObj === null) return 0; - if (typeof _instObj === 'undefined') return 0; - if (_instObj.go !== true) return 0; - return _instObj.prc; + return _checkInstProp('prc', 0); }; that.getBC = function () { - if (_instObj === null) return 0; - if (typeof _instObj === 'undefined') return 0; - if (_instObj.go !== true) return 0; - return _instObj.cur; + return _checkInstProp('cur', 'USD'); }; that.getAM = function () { - if (_instObj === null) return null; - if (typeof _instObj === 'undefined') return null; - if (_instObj.go !== true) return null; - return _instObj.am; + return _checkInstProp('am', null); }; - that.getPM = function () { - if (_instObj === null) return null; - if (typeof _instObj === 'undefined') return null; - if (_instObj.go === true) return null; - return _instObj.pbm; + that.getPingUrl = function (pingName) { + var pingData = _checkInstProp('pingdata', {}); + if (pingData[pingName] !== 'undefined') return pingData[pingName]; + return ''; }; that.setRD = function (data) { @@ -254,6 +240,14 @@ function ReloadClientTool(args) { return _log; }; + function _checkInstProp (key, def) { + if (_instObj === null) return def; + if (typeof _instObj === 'undefined') return def; + if (_instObj.go !== true) return def; + if (typeof _instObj[key] === 'undefined') return def; + return _instObj[key]; + } + function _getPlcmData () { return { prxVer: args.prxVer, @@ -268,33 +262,37 @@ function ReloadClientTool(args) { }; } - function _getClientData () { + function _getClientData (wnd, rtop) { return { - version: 100, + version: 200, locTime: Date.now(), - - winInfo: _genWinInfo(), + winInfo: _winInf(wnd), envInfo: getEnvInfo(), - confined: detectConfined(), - protStr: _getProtocolString(), - - hostDomain: decodeURIComponent(window.location.host), - hostPagePath: decodeURIComponent(window.location.pathname), - hostPageUrl: decodeURIComponent(window.location.href), - hostPageTitle: document.title, + topw: rtop === true, + prot: wnd.document.location.protocol, + host: wnd.document.location.host, + title: wnd.document.title, }; - function _genWinInfo () { - var winInfo = { - physicalWidth: window.screen.width, - physicalHeight: window.screen.height, - screenWidth: window.screen.availWidth, - screenHeight: window.screen.availHeight, - windowWidth: window.innerWidth, - windowHeight: window.innerHeight, - bodyHeight: document.body.clientHeight + function _winInf (wnd) { + return { + phs: { + w: wnd.screen.width, + h: wnd.screen.height + }, + avl: { + w: wnd.screen.availWidth, + h: wnd.screen.availHeight + }, + inr: { + w: wnd.innerWidth, + h: wnd.innerHeight + }, + bdy: { + w: wnd.document.body.clientWidth, + h: wnd.document.body.clientHeight + } }; - return winInfo; } function getEnvInfo() { @@ -304,12 +302,6 @@ function ReloadClientTool(args) { appVersion: navigator.appVersion }; } - - function detectConfined () { - var confined = true; - try { if (window.top === window.self) confined = false; } catch (err) {} - return confined; - } } function _getMemFile () { @@ -369,8 +361,17 @@ function ReloadClientTool(args) { } } + function _getGdpr() { + return args.gdprObj; + } + + function _getMediaObj() { + return args.mediaObj; + } + function _getResltStatusFileName () { - return _resFilePref + args.plcmID + '_' + args.partID; + if (args.lmod === true) return _resFilePref + args.lplcmID + '_' + args.partID; + else return _resFilePref + args.plcmID + '_' + args.partID; } function _setItem (name, data) { diff --git a/test/spec/modules/reloadBidAdapter_spec.js b/test/spec/modules/reloadBidAdapter_spec.js index ebf7308caf2..674c810d48a 100644 --- a/test/spec/modules/reloadBidAdapter_spec.js +++ b/test/spec/modules/reloadBidAdapter_spec.js @@ -66,7 +66,7 @@ let getExt1ServerResponse = () => { 'testCase': 'A:00_B:100', 'opdomain': '1', 'checksum': '6378', - 'cmp': '0', + 'cpm': '0', 'bstfct': '100', 'totstop': 'false', 'pcmurl': 'bidsrv01.reload.net' @@ -82,6 +82,7 @@ let getExt1ServerResponse = () => { 'partID': 'prx_part', 'opdomID': '0', 'bsrvID': 1, + 'adUnitCode': '1b243858-3c53-43dc-9fdf-89f839ea4a0f', 'banner': {'w': 300, 'h': 250} })); } @@ -103,7 +104,7 @@ let getExt2ServerResponse = () => { 'testCase': 'A:00_B:100', 'opdomain': '1', 'checksum': '6378', - 'cmp': '0', + 'cpm': '0', 'bstfct': '100', 'totstop': 'false', 'pcmurl': 'bidsrv00.reload.net' @@ -117,6 +118,7 @@ let getExt2ServerResponse = () => { 'partID': 'prx_part', 'opdomID': '0', 'bsrvID': 1, + 'adUnitCode': '1b243858-3c53-43dc-9fdf-89f839ea4a0f', 'banner': {'w': 160, 'h': 600} })); } From 9ed95bb067ffcf457c90be9c716df5cf71bc2a9d Mon Sep 17 00:00:00 2001 From: Denis Logachov Date: Thu, 1 Aug 2019 11:52:15 +0300 Subject: [PATCH 1395/1594] AdkernelAdn adapter minor update (#4033) * Updated maintainer email * Minor refactoring & more unit tests * Updated config example --- modules/adkernelAdnBidAdapter.js | 36 +++++----- modules/adkernelAdnBidAdapter.md | 63 +++++++++-------- .../modules/adkernelAdnBidAdapter_spec.js | 70 +++++++++++++++---- 3 files changed, 107 insertions(+), 62 deletions(-) diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index 63321fb82ee..08842db37e3 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -1,11 +1,9 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import {BANNER, VIDEO} from '../src/mediaTypes'; -import includes from 'core-js/library/fn/array/includes'; import {parse as parseUrl} from '../src/url'; const DEFAULT_ADKERNEL_DSP_DOMAIN = 'tag.adkernel.com'; -const VIDEO_TARGETING = ['mimes', 'protocols', 'api']; const DEFAULT_MIMES = ['video/mp4', 'video/webm', 'application/x-shockwave-flash', 'application/javascript']; const DEFAULT_PROTOCOLS = [2, 3, 5, 6]; const DEFAULT_APIS = [1, 2]; @@ -19,25 +17,22 @@ function buildImp(bidRequest) { id: bidRequest.bidId, tagid: bidRequest.adUnitCode }; - if (utils.deepAccess(bidRequest, `mediaTypes.banner`)) { - let sizes = canonicalizeSizesArray(bidRequest.mediaTypes.banner.sizes); + let bannerReq = utils.deepAccess(bidRequest, `mediaTypes.banner`); + let videoReq = utils.deepAccess(bidRequest, `mediaTypes.video`); + if (bannerReq) { + let sizes = canonicalizeSizesArray(bannerReq.sizes); imp.banner = { format: utils.parseSizesInput(sizes) } - } else if (utils.deepAccess(bidRequest, `mediaTypes.video`)) { - let size = canonicalizeSizesArray(bidRequest.mediaTypes.video.playerSize)[0]; + } else if (videoReq) { + let size = canonicalizeSizesArray(videoReq.playerSize)[0]; imp.video = { w: size[0], h: size[1], - mimes: DEFAULT_MIMES, - protocols: DEFAULT_PROTOCOLS, - api: DEFAULT_APIS + mimes: videoReq.mimes || DEFAULT_MIMES, + protocols: videoReq.protocols || DEFAULT_PROTOCOLS, + api: videoReq.api || DEFAULT_APIS }; - if (bidRequest.params.video) { - Object.keys(bidRequest.params.video) - .filter(param => includes(VIDEO_TARGETING, param)) - .forEach(param => imp.video[param] = bidRequest.params.video[param]); - } } return imp; } @@ -118,8 +113,11 @@ export const spec = { aliases: ['engagesimply'], isBidRequestValid: function(bidRequest) { - return 'params' in bidRequest && (typeof bidRequest.params.host === 'undefined' || typeof bidRequest.params.host === 'string') && - typeof bidRequest.params.pubId === 'number' && 'mediaTypes' in bidRequest && ('banner' in bidRequest.mediaTypes || 'video' in bidRequest.mediaTypes); + return 'params' in bidRequest && + (typeof bidRequest.params.host === 'undefined' || typeof bidRequest.params.host === 'string') && + typeof bidRequest.params.pubId === 'number' && + 'mediaTypes' in bidRequest && + ('banner' in bidRequest.mediaTypes || 'video' in bidRequest.mediaTypes); }, buildRequests: function(bidRequests, bidderRequest) { @@ -133,10 +131,8 @@ export const spec = { acc[host][pubId].push(curr); return acc; }, {}); - let auctionId = bidderRequest.auctionId; - let gdprConsent = bidderRequest.gdprConsent; - let transactionId = bidderRequest.transactionId; - let refererInfo = bidderRequest.refererInfo; + + let {auctionId, gdprConsent, transactionId, refererInfo} = bidderRequest; let requests = []; Object.keys(dispatch).forEach(host => { Object.keys(dispatch[host]).forEach(pubId => { diff --git a/modules/adkernelAdnBidAdapter.md b/modules/adkernelAdnBidAdapter.md index d69bf3b8998..c536ee1438c 100644 --- a/modules/adkernelAdnBidAdapter.md +++ b/modules/adkernelAdnBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: AdKernel ADN Bidder Adapter Module Type: Bidder Adapter -Maintainer: denis@adkernel.com +Maintainer: prebid-dev@adkernel.com ``` # Description @@ -14,32 +14,37 @@ Banner and video formats are supported. # Test Parameters ``` - var adUnits = [ - { - code: 'banner-ad-div', - sizes: [[300, 250], [300, 200]], - bids: [ - { - bidder: 'adkernelAdn', - params: { - pubId: 50357, - host: 'dsp-staging.adkernel.com' - } - } - ] - }, { - code: 'video-ad-player', - sizes: [640, 480], - bids: [ - { - bidder: 'adkernelAdn', - mediaType : 'video', - params: { - pubId: 50357, - host: 'dsp-staging.adkernel.com' - } - } - ] - } - ]; +var adUnits = [{ + code: 'banner-ad-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 200] // banner sizes + ], + } + }, + bids: [{ + bidder: 'adkernelAdn', + params: { + pubId: 50357, + host: 'dsp-staging.adkernel.com' + } + }] +}, { + code: 'video-ad-player', + mediaTypes: { + video: { + context: 'instream', // or 'outstream' + playerSize: [640, 480] // video player size + } + }, + bids: [{ + bidder: 'adkernelAdn', + params: { + pubId: 50357, + host: 'dsp-staging.adkernel.com' + } + }] +}]; ``` diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index 833a8e27f95..1147520131b 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -18,8 +18,7 @@ describe('AdkernelAdn adapter', function () { } }, adUnitCode: 'ad-unit-1', - }, - bid2_pub1 = { + }, bid2_pub1 = { bidder: 'adkernelAdn', transactionId: 'transact0', bidderRequestId: 'req0', @@ -34,8 +33,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] } } - }, - bid1_pub2 = { + }, bid1_pub2 = { bidder: 'adkernelAdn', transactionId: 'transact2', bidderRequestId: 'req1', @@ -60,17 +58,15 @@ describe('AdkernelAdn adapter', function () { mediaTypes: { video: { context: 'instream', - playerSize: [640, 300] - } - }, - adUnitCode: 'video_wrapper', - params: { - pubId: 7, - video: { + playerSize: [640, 300], mimes: ['video/mp4', 'video/webm'], api: [1, 2], protocols: [5, 6] } + }, + adUnitCode: 'video_wrapper', + params: { + pubId: 7 } }, bid_video2 = { bidder: 'adkernelAdn', @@ -85,11 +81,23 @@ describe('AdkernelAdn adapter', function () { context: 'instream' } }, - adUnitCode: 'video_wrapper2', params: { pubId: 7 } + }, bid_multiformat = { + bidder: 'adkernelAdn', + transactionId: 'f82c64b8-c602-42a4-9791-4a268f6559ed', + bidderRequestId: 'req-001', + auctionId: 'auc-001', + bidId: 'Bid_01', + sizes: [[300, 250], [300, 200]], + mediaTypes: { + banner: {sizes: [[300, 250], [300, 200]]}, + video: {context: 'instream', playerSize: [[640, 480]]} + }, + adUnitCode: 'ad-unit-1', + params: {pubId: 7} }; const response = { @@ -137,9 +145,11 @@ describe('AdkernelAdn adapter', function () { describe('input parameters validation', () => { it('empty request shouldn\'t generate exception', () => { - expect(spec.isBidRequestValid({bidderCode: 'adkernelAdn' + expect(spec.isBidRequestValid({ + bidderCode: 'adkernelAdn' })).to.be.equal(false); }); + it('request without pubid should be ignored', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', @@ -148,6 +158,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] })).to.be.equal(false); }); + it('request with invalid pubid should be ignored', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', @@ -158,6 +169,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] })).to.be.equal(false); }); + it('request with totally invalid host should be ignored', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', @@ -169,6 +181,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] })).to.be.equal(false); }); + it('valid request should be accepted', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', @@ -205,19 +218,24 @@ describe('AdkernelAdn adapter', function () { it('should have request id', function () { expect(tagRequest).to.have.property('id'); }); + it('should have transaction id', function () { expect(tagRequest).to.have.property('tid'); }); + it('should have sizes', function () { expect(tagRequest.imp[0].banner).to.have.property('format'); expect(tagRequest.imp[0].banner.format).to.be.eql(['300x250', '300x200']); }); + it('should have impression id', function () { expect(tagRequest.imp[0]).to.have.property('id', 'bidid_1'); }); + it('should have tagid', function () { expect(tagRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); + it('should create proper site block', function () { expect(tagRequest.site).to.have.property('page', 'https://example.com/index.html'); expect(tagRequest.site).to.have.property('secure', 1); @@ -256,16 +274,19 @@ describe('AdkernelAdn adapter', function () { expect(tagRequest.imp[0]).to.have.property('video'); expect(tagRequest.imp[1]).to.have.property('video'); }); + it('should have tagid', () => { expect(tagRequest.imp[0]).to.have.property('tagid', 'video_wrapper'); expect(tagRequest.imp[1]).to.have.property('tagid', 'video_wrapper2'); }); + it('should have size', () => { expect(tagRequest.imp[0].video).to.have.property('w', 640); expect(tagRequest.imp[0].video).to.have.property('h', 300); expect(tagRequest.imp[1].video).to.have.property('w', 1920); expect(tagRequest.imp[1].video).to.have.property('h', 1080); }); + it('should have video params', () => { expect(tagRequest.imp[0].video).to.have.property('mimes'); expect(tagRequest.imp[0].video.mimes).to.be.eql(['video/mp4', 'video/webm']); @@ -276,6 +297,21 @@ describe('AdkernelAdn adapter', function () { }); }); + describe('multiformat request building', function () { + let [_, tagRequests] = buildRequest([bid_multiformat]); + + it('should contain single request', function () { + expect(tagRequests).to.have.length(1); + expect(tagRequests[0].imp).to.have.length(1); + }); + + it('should contain banner-only impression', function () { + expect(tagRequests[0].imp).to.have.length(1); + expect(tagRequests[0].imp[0]).to.have.property('banner'); + expect(tagRequests[0].imp[0]).to.not.have.property('video'); + }); + }); + describe('requests routing', function () { it('should issue a request for each publisher', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1, bid_video1]); @@ -285,6 +321,7 @@ describe('AdkernelAdn adapter', function () { expect(tagRequests[0].imp).to.have.length(1); expect(tagRequests[1].imp).to.have.length(1); }); + it('should issue a request for each host', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1, bid1_pub2]); expect(pbRequests).to.have.length(2); @@ -297,12 +334,15 @@ describe('AdkernelAdn adapter', function () { describe('responses processing', function () { let responses; + before(function () { responses = spec.interpretResponse({body: response}); }); + it('should parse all responses', function () { expect(responses).to.have.length(3); }); + it('should return fully-initialized bid-response', function () { let resp = responses[0]; expect(resp).to.have.property('bidderCode', 'adkernelAdn'); @@ -317,6 +357,7 @@ describe('AdkernelAdn adapter', function () { expect(resp).to.have.property('ad'); expect(resp.ad).to.have.string(''); }); + it('should return fully-initialized video bid-response', function () { let resp = responses[2]; expect(resp).to.have.property('bidderCode', 'adkernelAdn'); @@ -329,6 +370,7 @@ describe('AdkernelAdn adapter', function () { expect(resp).to.have.property('vastUrl', 'http://vast.com/vast.xml'); expect(resp).to.not.have.property('ad'); }); + it('should perform usersync', function () { let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: response}]); expect(syncs).to.have.length(0); @@ -337,11 +379,13 @@ describe('AdkernelAdn adapter', function () { expect(syncs[0]).to.have.property('type', 'iframe'); expect(syncs[0]).to.have.property('url', 'https://dsp.adkernel.com/sync'); }); + it('should handle user-sync only response', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1]); let resp = spec.interpretResponse({body: usersyncOnlyResponse}, pbRequests[0]); expect(resp).to.have.length(0); }); + it('shouldn\' fail on empty response', function () { let syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: ''}]); expect(syncs).to.have.length(0); From 92a5073aa6b9b2860af4fc022db4aad4eaec1056 Mon Sep 17 00:00:00 2001 From: OneTagDevOps <38786435+OneTagDevOps@users.noreply.github.com> Date: Fri, 2 Aug 2019 15:33:31 +0200 Subject: [PATCH 1396/1594] Minor bug fixing in onetagBidAdapter.js (#4054) Fixed a minor bug. Updated TTL in response to align the correct specifications. --- modules/onetagBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index 72a88039fed..ce671772dad 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -24,7 +24,7 @@ function isBidRequestValid(bid) { return false; } - if (typeof bid.params.pubId !== 'string' || bid.sizes === 'undefined' || bid.sizes.length === 0) { + if (typeof bid.params.pubId !== 'string' || typeof bid.sizes === 'undefined' || bid.sizes.length === 0) { return false; } @@ -90,7 +90,7 @@ function interpretResponse(serverResponse, request) { netRevenue: false, mediaType: bids.type ? bids.type : BANNER, ad: bid.ad, - ttl: bid.ttl || 6000 + ttl: bid.ttl || 300 }); }); } From 2fa43871e097011ecd700808cb097824442703ac Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Fri, 2 Aug 2019 19:18:05 +0530 Subject: [PATCH 1397/1594] Update karma to address vulnerabilities. (#4038) * update packages to fix vulns * upgrade node version to support advanced features * fix command gulp test --browserstack not exiting * fixes gulp view-coverage command failing * fix: command, gulp serve now keeps running without exiting * fix: error in package-lock.json * update README.md to reflect change in node version --- .circleci/config.yml | 2 +- README.md | 4 +- gulpfile.js | 28 +- package-lock.json | 2387 +++++++++++++++++++++--------------------- package.json | 8 +- 5 files changed, 1224 insertions(+), 1205 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 16bdd5b317e..85452b5aa88 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: build: docker: # specify the version you desire here - - image: circleci/node:7.10 + - image: circleci/node:9.0.0 # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images diff --git a/README.md b/README.md index 21e02ebee7f..a50c55f96ca 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ module.exports = { } ``` -Or for Babel 6 and/or Node v8.6.0 and less: +Or for Babel 6: ```javascript // you must manually install and specify the presets and plugins yourself options: { @@ -112,7 +112,7 @@ prebid.requestBids({ $ cd Prebid.js $ npm install -*Note:* You need to have `NodeJS` 6.x or greater installed. +*Note:* You need to have `NodeJS` 9.x or greater installed. *Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To compily with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in it's setup. diff --git a/gulpfile.js b/gulpfile.js index a89f570e496..24c628ef228 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -205,18 +205,6 @@ function bundle(dev, moduleArr) { .pipe(gulpif(dev, sourcemaps.write('.'))); } -// Workaround for incompatibility between Karma & gulp callbacks. -// See https://github.com/karma-runner/gulp-karma/issues/18 for some related discussion. -function newKarmaCallback(done) { - return function (exitCode) { - if (exitCode) { - done(new Error('Karma tests failed with exit code ' + exitCode)); - } else { - done(); - } - } -} - // Run the unit tests. // // By default, this runs in headless chrome. @@ -248,6 +236,22 @@ function test(done) { } } +function newKarmaCallback(done) { + return function(exitCode) { + if (exitCode) { + done(new Error('Karma tests failed with exit code ' + exitCode)); + if (argv.browserstack) { + process.exit(exitCode); + } + } else { + done(); + if (argv.browserstack) { + process.exit(exitCode); + } + } + } +} + // If --file "" is given, the task will only run tests in the specified file. function testCoverage(done) { new KarmaServer(karmaConfMaker(true, false, false, argv.file), newKarmaCallback(done)).start(); diff --git a/package-lock.json b/package-lock.json index 06746ab8c41..1ed87be2492 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,45 +5,45 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { "@babel/highlight": "^7.0.0" } }, "@babel/core": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", - "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", + "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", - "@babel/helpers": "^7.5.5", - "@babel/parser": "^7.5.5", + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helpers": "^7.4.4", + "@babel/parser": "^7.4.5", "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5", + "@babel/traverse": "^7.4.5", + "@babel/types": "^7.4.4", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", - "lodash": "^4.17.13", + "lodash": "^4.17.11", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" } }, "@babel/generator": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", - "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", "dev": true, "requires": { - "@babel/types": "^7.5.5", + "@babel/types": "^7.4.4", "jsesc": "^2.5.1", - "lodash": "^4.17.13", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -79,14 +79,14 @@ } }, "@babel/helper-define-map": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", - "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", + "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" + "@babel/types": "^7.4.4", + "lodash": "^4.17.11" } }, "@babel/helper-explode-assignable-expression": { @@ -129,12 +129,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", - "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", "dev": true, "requires": { - "@babel/types": "^7.5.5" + "@babel/types": "^7.0.0" } }, "@babel/helper-module-imports": { @@ -147,17 +147,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", - "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", + "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-simple-access": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", "@babel/template": "^7.4.4", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" + "@babel/types": "^7.4.4", + "lodash": "^4.17.11" } }, "@babel/helper-optimise-call-expression": { @@ -176,12 +176,12 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", - "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", + "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", "dev": true, "requires": { - "lodash": "^4.17.13" + "lodash": "^4.17.11" } }, "@babel/helper-remap-async-to-generator": { @@ -198,15 +198,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", - "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", + "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-member-expression-to-functions": "^7.0.0", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/helper-simple-access": { @@ -241,20 +241,20 @@ } }, "@babel/helpers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", - "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", "dev": true, "requires": { "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { "chalk": "^2.0.0", @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -279,16 +279,6 @@ "@babel/plugin-syntax-async-generators": "^7.2.0" } }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", - "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0" - } - }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", @@ -300,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", - "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", + "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -339,15 +329,6 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", @@ -385,9 +366,9 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", - "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", + "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -405,27 +386,27 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", - "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", + "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.13" + "lodash": "^4.17.11" } }, "@babel/plugin-transform-classes": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", - "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", + "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.5.5", + "@babel/helper-define-map": "^7.4.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-replace-supers": "^7.4.4", "@babel/helper-split-export-declaration": "^7.4.4", "globals": "^11.1.0" } @@ -440,9 +421,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", - "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", + "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -460,9 +441,9 @@ } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", + "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -516,37 +497,34 @@ } }, "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", + "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", - "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", + "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-simple-access": "^7.1.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", - "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", + "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-modules-umd": { @@ -578,13 +556,13 @@ } }, "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", + "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5" + "@babel/helper-replace-supers": "^7.1.0" } }, "@babel/plugin-transform-parameters": { @@ -684,45 +662,43 @@ } }, "@babel/preset-env": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", - "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", + "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-dynamic-import": "^7.5.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", + "@babel/plugin-proposal-object-rest-spread": "^7.4.4", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.5.0", + "@babel/plugin-transform-async-to-generator": "^7.4.4", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.5.5", - "@babel/plugin-transform-classes": "^7.5.5", + "@babel/plugin-transform-block-scoping": "^7.4.4", + "@babel/plugin-transform-classes": "^7.4.4", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.5.0", + "@babel/plugin-transform-destructuring": "^7.4.4", "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.5.0", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", "@babel/plugin-transform-for-of": "^7.4.4", "@babel/plugin-transform-function-name": "^7.4.4", "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.5.0", - "@babel/plugin-transform-modules-systemjs": "^7.5.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.4.4", + "@babel/plugin-transform-modules-systemjs": "^7.4.4", "@babel/plugin-transform-modules-umd": "^7.2.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.5.5", + "@babel/plugin-transform-object-super": "^7.2.0", "@babel/plugin-transform-parameters": "^7.4.4", "@babel/plugin-transform-property-literals": "^7.2.0", "@babel/plugin-transform-regenerator": "^7.4.5", @@ -733,7 +709,7 @@ "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.5.5", + "@babel/types": "^7.4.4", "browserslist": "^4.6.0", "core-js-compat": "^3.1.1", "invariant": "^2.2.2", @@ -753,30 +729,30 @@ } }, "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.5.5", - "@babel/types": "^7.5.5", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", - "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.13", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -853,6 +829,14 @@ "dev": true, "requires": { "samsam": "1.3.0" + }, + "dependencies": { + "samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "dev": true + } } }, "@sinonjs/samsam": { @@ -872,6 +856,194 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@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 + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -939,9 +1111,9 @@ } }, "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", "dev": true }, "after": { @@ -971,6 +1143,12 @@ "json-schema-traverse": "^0.3.0" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, "ajv-keywords": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", @@ -1003,7 +1181,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "dev": true, + "optional": true }, "ansi-colors": { "version": "3.2.3", @@ -1092,6 +1271,12 @@ "default-require-extensions": "^1.0.0" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -1109,12 +1294,12 @@ }, "dependencies": { "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } } } @@ -1778,15 +1963,6 @@ "babel-runtime": "^6.22.0" } }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", @@ -2726,15 +2902,15 @@ } }, "bfj": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", - "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", + "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", "dev": true, "requires": { - "bluebird": "^3.5.5", - "check-types": "^8.0.3", - "hoopy": "^0.1.4", - "tryer": "^1.0.1" + "bluebird": "^3.5.1", + "check-types": "^7.3.0", + "hoopy": "^0.1.2", + "tryer": "^1.0.0" } }, "big.js": { @@ -2841,12 +3017,6 @@ "toidentifier": "1.0.0" } }, - "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", @@ -3019,14 +3189,14 @@ } }, "browserslist": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", - "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", + "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000984", - "electron-to-chromium": "^1.3.191", - "node-releases": "^1.1.25" + "caniuse-lite": "^1.0.30000975", + "electron-to-chromium": "^1.3.164", + "node-releases": "^1.1.23" } }, "browserstack": { @@ -3039,15 +3209,30 @@ } }, "browserstack-local": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.2.tgz", - "integrity": "sha512-fRaynjF0MvtyyfPRy2NFnVwxLyNtD28K/v9xRsIjUVf7xLc80NIm7Nfr3KXlFmWizhG91PL/UAOXlHkoxQjaNw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", + "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1", "is-running": "^2.0.0", "ps-tree": "=1.1.1", + "sinon": "^1.17.6", "temp-fs": "^0.9.9" + }, + "dependencies": { + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": ">=0.10.3 <1" + } + } } }, "buffer": { @@ -3124,6 +3309,54 @@ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, + "cacache": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", + "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "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, + "requires": { + "yallist": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3181,7 +3414,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3247,9 +3480,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000987", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000987.tgz", - "integrity": "sha512-O3VrjtRMTxoU5Cn5/QSmXeIR1gkVps4j9jqfIm4FLaQ5JzqBlVjMUG1xWnoYFv8N+H3Lp++aa05TekyIbjHL7g==", + "version": "1.0.30000975", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", + "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", "dev": true }, "caseless": { @@ -3336,9 +3569,9 @@ "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==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", + "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", "dev": true }, "chokidar": { @@ -3361,6 +3594,21 @@ "upath": "^1.1.1" } }, + "chownr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", + "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3547,15 +3795,6 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3757,6 +3996,31 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -3790,9 +4054,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", "dev": true } } @@ -3810,13 +4074,13 @@ "dev": true }, "coveralls": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", - "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.4.tgz", + "integrity": "sha512-eyqUWA/7RT0JagiL0tThVhjbIjoiEUyWCjtUJoOPcWoeofP5WK/jb2OJYoBFrR6DvplR+AxOyuBqk4JHkk5ykA==", "dev": true, "requires": { "growl": "~> 1.10.0", - "js-yaml": "^3.13.1", + "js-yaml": "^3.11.0", "lcov-parse": "^0.0.10", "log-driver": "^1.2.7", "minimist": "^1.2.0", @@ -3966,6 +4230,12 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -3986,9 +4256,9 @@ } }, "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", "dev": true }, "date-now": { @@ -4745,15 +5015,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.205", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.205.tgz", - "integrity": "sha512-VV+f2FVeFI5D/slUD7A3V1lTMDkQTUGWYH2dZGAijIutN5Aga4Fn/Hv4Gc+60OpXFVLYIq5HpXb2cG6NrGGQaA==", + "version": "1.3.164", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", + "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", "dev": true }, "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -4795,7 +5065,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4809,7 +5079,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4825,7 +5095,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4851,7 +5121,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -5228,9 +5498,9 @@ } }, "eslint-module-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", - "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", + "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", "dev": true, "requires": { "debug": "^2.6.8", @@ -5307,9 +5577,9 @@ } }, "eslint-plugin-import": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", - "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", + "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -5319,8 +5589,8 @@ "eslint-import-resolver-node": "^0.3.2", "eslint-module-utils": "^2.4.0", "has": "^1.0.3", + "lodash": "^4.17.11", "minimatch": "^3.0.4", - "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", "resolve": "^1.11.0" }, @@ -5558,7 +5828,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5627,40 +5897,6 @@ } } }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "dependencies": { - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } - } - } - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -5711,34 +5947,10 @@ } } }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - }, - "dependencies": { - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "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, "requires": { "homedir-polyfill": "^1.0.1" @@ -5798,13 +6010,13 @@ } }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.4", + "inherits": "2.0.3", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" @@ -6028,6 +6240,12 @@ "detect-libc": "^1.0.3" } }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -6047,12 +6265,6 @@ "object-assign": "^4.0.1" } }, - "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 - }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", @@ -6295,6 +6507,15 @@ "mime-types": "^2.1.12" } }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "~1.1" + } + }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -6377,6 +6598,18 @@ "through2": "^2.0.3" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, "fs.extra": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", @@ -6422,7 +6655,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6443,12 +6677,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6463,17 +6699,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6590,7 +6829,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6602,6 +6842,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6616,6 +6857,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6623,12 +6865,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6647,6 +6891,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6727,7 +6972,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6739,6 +6985,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6824,7 +7071,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6860,6 +7108,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6879,6 +7128,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6922,19 +7172,21 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, "fun-hooks": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.5.tgz", - "integrity": "sha512-xaj0r9Ex0dvehX8MbQSK/5EYVAddyoaK2sGNuQWX8xNaCiHtr/4zD9J10Y2irkFIsuaxbYOsQBKXvTHzjO2IFQ==" + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.3.tgz", + "integrity": "sha512-MC/zsGf+duq8lI6xym+H8HuL6DE1fLyE90FRzU/j2lTDmjDJ//+KC7M8vLzG9y/mhkLOH5u9wK4QEf3lBqIo4w==" }, "function-bind": { "version": "1.1.1", @@ -7053,42 +7305,6 @@ "path-is-absolute": "^1.0.0" } }, - "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": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "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.0" - } - }, - "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": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -7232,9 +7448,9 @@ } }, "graceful-fs": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", - "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==", + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, "grapheme-splitter": { @@ -7683,7 +7899,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7700,7 +7916,7 @@ "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==", + "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", "dev": true } } @@ -7801,22 +8017,22 @@ "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": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", + "lodash._reinterpolate": "~3.0.0", "lodash.templatesettings": "^4.0.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==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0" + "lodash._reinterpolate": "~3.0.0" } } } @@ -7878,9 +8094,9 @@ } }, "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==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", "dev": true, "requires": { "minimatch": "^3.0.3" @@ -8157,9 +8373,9 @@ }, "dependencies": { "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -8427,7 +8643,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8435,14 +8651,6 @@ "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } } }, "http-parser-js": { @@ -8480,12 +8688,12 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "dev": true, "requires": { - "agent-base": "^4.3.0", + "agent-base": "^4.1.0", "debug": "^3.1.0" }, "dependencies": { @@ -8521,6 +8729,12 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -8559,9 +8773,9 @@ } }, "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=", "dev": true }, "ini": { @@ -8698,6 +8912,12 @@ "is-decimal": "^1.0.0" } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8782,21 +9002,6 @@ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", "dev": true }, - "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-primitive": "^2.0.0" - } - }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -8824,6 +9029,12 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -8886,18 +9097,6 @@ "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": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -9132,12 +9331,12 @@ }, "dependencies": { "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } } } @@ -9414,28 +9613,27 @@ "dev": true }, "karma": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.2.0.tgz", + "integrity": "sha512-fmCuxN1rwJxTdZfOXK5LjlmS4Ana/OvzNMpkyLL/TLE8hmgSkpVpMYQ7RTVa8TNKRVQDZNl5W1oF5cfKfgIMlA==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", - "chokidar": "^2.0.3", + "braces": "^3.0.2", + "chokidar": "^3.0.0", "colors": "^1.1.0", - "combine-lists": "^1.0.0", "connect": "^3.6.0", - "core-js": "^2.2.0", + "core-js": "^3.1.3", "di": "^0.0.1", "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.5", - "log4js": "^3.0.0", + "lodash": "^4.17.11", + "log4js": "^4.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", @@ -9449,12 +9647,108 @@ "useragent": "2.3.0" }, "dependencies": { + "anymatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.0.3.tgz", + "integrity": "sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz", + "integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==", + "dev": true, + "requires": { + "anymatch": "^3.0.1", + "braces": "^3.0.2", + "fsevents": "^2.0.6", + "glob-parent": "^5.0.0", + "is-binary-path": "^2.1.0", + "is-glob": "^4.0.1", + "normalize-path": "^3.0.0", + "readdirp": "^3.1.1" + } + }, + "core-js": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", + "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", + "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" + } + }, + "fsevents": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", + "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", + "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "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, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "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 + }, "mime": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, + "readdirp": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.1.tgz", + "integrity": "sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -9469,6 +9763,15 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "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" + } } } }, @@ -9636,12 +9939,12 @@ }, "dependencies": { "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } } } @@ -10045,33 +10348,16 @@ } }, "log4js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", + "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", "dev": true, "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" - }, - "dependencies": { - "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.6" } }, "loglevelnext": { @@ -10085,9 +10371,9 @@ } }, "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, "longest": { @@ -10180,6 +10466,12 @@ "kind-of": "^6.0.2" } }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -10263,12 +10555,6 @@ } } }, - "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", @@ -10646,10 +10932,28 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -10682,7 +10986,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10828,6 +11132,31 @@ } } }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11040,13 +11369,22 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true - } - } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + } + } }, "node-releases": { - "version": "1.1.26", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", - "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", + "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", "dev": true, "requires": { "semver": "^5.3.0" @@ -11232,6 +11570,18 @@ "isobject": "^3.0.0" } }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -11252,27 +11602,6 @@ "make-iterator": "^1.0.0" } }, - "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.4", - "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.1" - } - } - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -11292,18 +11621,6 @@ "make-iterator": "^1.0.0" } }, - "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -11366,7 +11683,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11493,6 +11810,17 @@ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -11565,9 +11893,9 @@ } }, "mocha": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", - "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", + "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -11685,35 +12013,6 @@ "ini": "^1.3.3" } }, - "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.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "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", @@ -11913,18 +12212,18 @@ "sha.js": "^2.4.8" } }, - "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 - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "dev": true + }, "pidtree": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", @@ -12008,12 +12307,6 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12033,9 +12326,9 @@ "dev": true }, "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, "progress": { @@ -12044,6 +12337,12 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12088,9 +12387,9 @@ "dev": true }, "psl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", - "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==", + "version": "1.1.32", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", + "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", "dev": true }, "public-encrypt": { @@ -12192,25 +12491,6 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "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.0", - "math-random": "^1.0.1" - }, - "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", @@ -12386,23 +12666,14 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", + "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", "dev": true, "requires": { "private": "^0.1.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", @@ -12414,9 +12685,9 @@ } }, "regexp-tree": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", - "integrity": "sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", + "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", "dev": true }, "regexpp": { @@ -12731,9 +13002,9 @@ "dev": true }, "resolve": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", - "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -12841,6 +13112,15 @@ "is-promise": "^2.1.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -12884,9 +13164,9 @@ "dev": true }, "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", "dev": true }, "schema-utils": { @@ -12963,6 +13243,12 @@ } } }, + "serialize-javascript": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", + "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -13025,13 +13311,13 @@ } }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.4", + "inherits": "2.0.3", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" @@ -13187,6 +13473,12 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true + }, + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true } } }, @@ -13330,7 +13622,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { "debug": "~3.1.0", @@ -13344,7 +13636,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13367,7 +13659,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", @@ -13395,7 +13687,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13411,7 +13703,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13429,7 +13721,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13537,14 +13829,14 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", "dev": true }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13583,6 +13875,15 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -13678,7 +13979,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13695,6 +13996,16 @@ "readable-stream": "^2.0.2" } }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, "stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", @@ -13721,17 +14032,27 @@ "dev": true }, "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", + "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.14" }, "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.14" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -13740,6 +14061,26 @@ "requires": { "ms": "^2.1.1" } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } } } }, @@ -13940,9 +14281,9 @@ } }, "ternary-stream": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", - "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", "dev": true, "requires": { "duplexify": "^3.5.0", @@ -13951,6 +14292,102 @@ "through2": "^2.0.1" } }, + "terser": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.2.tgz", + "integrity": "sha512-jvNoEQSPXJdssFwqPSgWjsOrb+ELoE+ILpHPKXC83tIxOlh2U75F1KuB2luLD/3a6/7K3Vw5pDn+hvu0C4AzSw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "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 + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", + "dev": true, + "requires": { + "cacache": "^11.3.2", + "find-cache-dir": "^2.0.0", + "is-wsl": "^1.1.0", + "loader-utils": "^1.2.3", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1", + "terser": "^4.0.0", + "webpack-sources": "^1.3.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "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 + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14205,6 +14642,12 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14285,7 +14728,8 @@ "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 + "dev": true, + "optional": true }, "uglifyjs-webpack-plugin": { "version": "0.4.6", @@ -14445,6 +14889,24 @@ "set-value": "^2.0.1" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", @@ -14515,6 +14977,12 @@ "unist-util-is": "^3.0.0" } }, + "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 + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -14656,7 +15124,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14664,20 +15132,16 @@ } }, "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", + "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", "dev": true, "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } + "inherits": "2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "object.entries": "^1.1.0", + "safe-buffer": "^5.1.2" } }, "util-deprecate": { @@ -15069,9 +15533,9 @@ }, "dependencies": { "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -15081,18 +15545,18 @@ } }, "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } }, "camelcase": { @@ -15385,9 +15849,9 @@ } }, "webpack-bundle-analyzer": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", - "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", + "integrity": "sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==", "dev": true, "requires": { "acorn": "^6.0.7", @@ -15399,16 +15863,16 @@ "express": "^4.16.3", "filesize": "^3.6.1", "gzip-size": "^5.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.10", "mkdirp": "^0.5.1", "opener": "^1.5.1", "ws": "^6.0.0" }, "dependencies": { "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, "ejs": { @@ -15428,36 +15892,9 @@ } } }, - "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": { - "source-list-map": "~0.1.7", - "source-map": "~0.4.1" - }, - "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": ">=0.0.4" - } - } - } - }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -15509,556 +15946,125 @@ } }, "webpack-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", - "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-5.2.1.tgz", + "integrity": "sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==", "dev": true, "requires": { - "gulp-util": "^3.0.7", + "fancy-log": "^1.3.3", "lodash.clone": "^4.3.2", "lodash.some": "^4.2.2", - "memory-fs": "^0.3.0", + "memory-fs": "^0.4.1", + "plugin-error": "^1.0.1", + "supports-color": "^5.5.0", "through": "^2.3.8", - "vinyl": "^1.1.0", - "webpack": "^1.12.9" + "vinyl": "^2.1.0", + "webpack": "^4.26.1" }, "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.1.5", - "normalize-path": "^2.0.0" - } - }, - "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.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "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 - }, - "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.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "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.1" - } - }, - "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.0" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", "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.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "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=", + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "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" - } - }, "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "memory-fs": "^0.2.0", - "tapable": "^0.1.8" - }, - "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 - } + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" } }, - "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=", + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "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.1.0" - } - }, - "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": "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": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.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.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "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-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": { + "fast-deep-equal": { "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" - } - }, - "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" - } - }, - "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" - } - }, - "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.5" - } - }, - "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.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.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.3", - "readable-stream": "^2.0.1" - } - }, - "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.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "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.1.1", - "browserify-zlib": "^0.1.4", - "buffer": "^4.9.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "3.3.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "0.0.1", - "os-browserify": "^0.2.0", - "path-browserify": "0.0.0", - "process": "^0.11.0", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.0.5", - "stream-browserify": "^2.0.1", - "stream-http": "^2.3.1", - "string_decoder": "^0.10.25", - "timers-browserify": "^2.0.2", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - } - }, - "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" - } - }, - "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 - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "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=", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "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 }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "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": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "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 - } - } - }, - "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" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "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": { - "indexof": "0.0.1" - } - }, - "watchpack": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", - "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", - "dev": true, - "requires": { - "async": "^0.9.0", - "chokidar": "^1.0.0", - "graceful-fs": "^4.1.2" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "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.0.0", - "async": "^1.3.0", - "clone": "^1.0.2", - "enhanced-resolve": "~0.9.0", - "interpret": "^0.6.4", - "loader-utils": "^0.2.11", - "memory-fs": "~0.3.0", + "version": "4.36.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.36.1.tgz", + "integrity": "sha512-Ej01/N9W8DVyhEpeQnbUdGvOECw0L46FxS12cCOs8gSK7bhUlrbHRnWkjiXckGlHjUrmL89kDpTRIkUk6Y+fKg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", "mkdirp": "~0.5.0", - "node-libs-browser": "^0.7.0", - "optimist": "~0.6.0", - "supports-color": "^3.1.0", - "tapable": "~0.1.8", - "uglify-js": "~2.7.3", - "watchpack": "^0.2.1", - "webpack-core": "~0.6.9" - } - }, - "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.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^1.0.0", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" } } } @@ -16122,6 +16128,15 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", @@ -16193,9 +16208,9 @@ "dev": true }, "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, "y18n": { diff --git a/package.json b/package.json index cb921f61bed..d028e6049a1 100755 --- a/package.json +++ b/package.json @@ -35,9 +35,9 @@ "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.2.0", "eslint-plugin-node": "^5.1.0", + "eslint-plugin-prebid": "file:./plugins/eslint", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", - "eslint-plugin-prebid": "file:./plugins/eslint", "execa": "^1.0.0", "faker": "^3.1.0", "fs.extra": "^1.3.2", @@ -58,7 +58,7 @@ "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", - "karma": "^3.1.3", + "karma": "^4.2.0", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", @@ -76,7 +76,7 @@ "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "^0.0.31", "karma-webpack": "^3.0.5", - "lodash": "^4.17.4", + "lodash": "^4.17.15", "mocha": "^5.0.0", "opn": "^5.4.0", "querystringify": "0.0.3", @@ -91,7 +91,7 @@ "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-bundle-analyzer": "^3.3.2", - "webpack-stream": "^3.2.0", + "webpack-stream": "^5.2.1", "yargs": "^1.3.1" }, "dependencies": { From a1eb122dcb10a929a643f2b8bf5ffe13bd3a97a8 Mon Sep 17 00:00:00 2001 From: Denis Logachov Date: Fri, 2 Aug 2019 22:01:11 +0300 Subject: [PATCH 1398/1594] New adkernel adapter aliases (#4057) --- modules/adkernelBidAdapter.js | 9 ++++++++- test/spec/modules/adkernelBidAdapter_spec.js | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 02b9d2a7967..7c48458f474 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -5,6 +5,13 @@ import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; import {parse as parseUrl} from '../src/url'; +/* + * In case you're AdKernel whitelable platform's client who needs branded adapter to + * work with Adkernel platform - DO NOT COPY THIS ADAPTER UNDER NEW NAME + * + * Please contact prebid@adkernel.com and we'll add your adapter as an alias. + */ + const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', 'pos', 'api', 'ext']; @@ -16,7 +23,7 @@ const VERSION = '1.3'; export const spec = { code: 'adkernel', - aliases: ['headbidding'], + aliases: ['headbidding', 'adsolut', 'oftmediahb'], supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bidRequest) { return 'params' in bidRequest && diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index a00f07603ee..621b9971304 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -379,8 +379,8 @@ describe('Adkernel adapter', function () { describe('adapter configuration', () => { it('should have aliases', () => { - expect(spec.aliases).to.have.lengthOf(1); - expect(spec.aliases[0]).to.be.equal('headbidding'); + expect(spec.aliases).to.have.lengthOf(3); + expect(spec.aliases).to.be.eql(['headbidding', 'adsolut', 'oftmediahb']); }); }); }); From 1e14de82fa9b77925ab76559a573a377f9ca7513 Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Mon, 5 Aug 2019 21:26:36 +0530 Subject: [PATCH 1399/1594] adding supply chain Object feature (#4051) * outstream changes * removing global filtet * reverting page * message * adapter change * remove space * testcases * testpage * spaces for test page * renderer exist case * reverting package-lock.json * adding schain object --- modules/oneVideoBidAdapter.js | 13 +++++++++++++ modules/oneVideoBidAdapter.md | 4 +++- test/spec/modules/oneVideoBidAdapter_spec.js | 16 +++++++++++++--- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index c05158f28c4..a4ea4c86e03 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -196,6 +196,19 @@ function getRequestData(bid, consentData) { if (bid.params.site && bid.params.site.id) { bidData.site.id = bid.params.site.id } + if (bid.params.video.sid) { + bidData.source = { + ext: { + schain: { + complete: 1, + nodes: [{ + sid: bid.params.video.sid, + rid: bidData.id, + }] + } + } + } + } if (isConsentRequired(consentData)) { bidData.regs = { diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md index 6e34d245c3e..c8c4d87f9cb 100644 --- a/modules/oneVideoBidAdapter.md +++ b/modules/oneVideoBidAdapter.md @@ -33,7 +33,9 @@ Connects to One Video demand source to fetch bids. position: 1, delivery: [2], playbackmethod: [1,5], - placement: 123 + placement: 123, + sid: , + }, }, site: { id: 1, diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 09118bba1d2..09ca6217fe2 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -30,7 +30,8 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123 + placement: 123, + sid: 134 }, site: { id: 1, @@ -65,7 +66,8 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123 + placement: 123, + sid: 134 } }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); @@ -81,7 +83,8 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123 + placement: 123, + sid: 134 }, pubId: 'brxd' }; @@ -196,5 +199,12 @@ describe('OneVideoBidAdapter', function () { const request = spec.buildRequests([ bidRequest ], bidderRequest); expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); }); + + it('should send schain object', function () { + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.source.ext.schain.nodes[0].sid).to.equal(bidRequest.params.video.sid); + expect(data.source.ext.schain.nodes[0].rid).to.equal(data.id); + }); }); }); From 2215c544a8a4bae95aa5c568af11cbc23a47db80 Mon Sep 17 00:00:00 2001 From: Sharath N Date: Tue, 6 Aug 2019 19:07:15 +0530 Subject: [PATCH 1400/1594] Adding new BidAdapter 'eywamedia' (#4055) * Adding new BidAdapter 'eywamedia' * removed unused import * removed unused variables * removed unused import * removed unused import - my bad! --- modules/eywamediaBidAdapter.js | 181 +++++++++++++ modules/eywamediaBidAdapter.md | 37 +++ test/spec/modules/eywamediaBidAdapter_spec.js | 253 ++++++++++++++++++ 3 files changed, 471 insertions(+) create mode 100644 modules/eywamediaBidAdapter.js create mode 100644 modules/eywamediaBidAdapter.md create mode 100644 test/spec/modules/eywamediaBidAdapter_spec.js diff --git a/modules/eywamediaBidAdapter.js b/modules/eywamediaBidAdapter.js new file mode 100644 index 00000000000..543775dc3aa --- /dev/null +++ b/modules/eywamediaBidAdapter.js @@ -0,0 +1,181 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; + +const BIDDER_CODE = 'eywamedia'; +const CURRENCY = 'USD'; +const VERSION = '1.0.0'; +const TIME_TO_LIVE = 360; +const NET_REVENUE = true; +const COOKIE_NAME = 'emaduuid'; +const UUID_LEN = 36; +const SERVER_ENDPOINT = 'https://adtarbostg.eywamedia.com/auctions/prebidjs/3000'; +const localWindow = getTopWindow(); + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['banner'], + /** + * Determines whether or not the given bid request is valid. + * @param {object} bid, bid to validate + * @return boolean, true if valid, otherwise false + */ + isBidRequestValid: function(bid) { + return !!(bid.params.publisherId); + }, + /** + * 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 requestPayload Info describing the request to the server. + */ + buildRequests: function(bidRequests, bidRequest) { + const device = getDeviceInfo(); + const site = getSiteInfo(); + const user = getUserInfo(); + + let requestPayload = { + id: utils.generateUUID(), + publisherId: bidRequests[0].params.publisherId, + device: device, + site: site, + user: user, + bidPayload: bidRequests, + cacheBust: new Date().getTime().toString(), + adapterVersion: VERSION, + tmax: bidRequest.timeout + }; + + return { + method: 'POST', + url: SERVER_ENDPOINT, + options: { + contentType: 'application/json' + }, + data: requestPayload + } + }, + + /** + * Makes Eywamedia Ad Server response compatible to Prebid specs + * @param serverResponse successful response from Ad Server + * @param bidderRequest original bidRequest + * @return {Bid[]} an array of bids + */ + interpretResponse: function (serverResponse, bidRequest) { + var bidObject, response; + var bidRespones = []; + var responses = serverResponse.body; + for (var i = 0; i < responses.length; i++) { + response = responses[i]; + bidObject = { + requestId: response.bidId, + cpm: response.cpm, + width: parseInt(response.width), + height: parseInt(response.height), + creativeId: response.bidId, + currency: CURRENCY, + netRevenue: NET_REVENUE, + ttl: TIME_TO_LIVE, + ad: response.ad, + bidderCode: BIDDER_CODE, + transactionId: response.transactionId, + mediaType: response.respType, + }; + bidRespones.push(bidObject); + } + return bidRespones; + } +} +registerBidder(spec); + +/*************************************** + * Helper Functions + ***************************************/ + +/** + * get device type + */ +function getDeviceType() { + let ua = navigator.userAgent; + // Tablets must be checked before phones. + if ((/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i).test(ua)) { + return 5; // "Tablet" + } + if ((/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/).test(ua)) { + return 4; // "Phone" + } + return 2; // Personal Computers +}; + +/** + * get device info + */ +function getDeviceInfo() { + const language = navigator.language; + return { + ua: navigator.userAgent, + language: navigator[language], + devicetype: getDeviceType(), + dnt: utils.getDNT(), + geo: {}, + js: 1 + }; +}; + +/** + * get site info + */ +function getSiteInfo() { + const topLocation = utils.getTopWindowLocation(); + return { + domain: topLocation.hostname, + page: topLocation.href, + referrer: utils.getTopWindowReferrer(), + desc: getPageDescription(), + title: localWindow.document.title, + }; +}; + +/** + * get user info + */ +function getUserInfo() { + return { + id: getUserID(), + }; +}; + +/** + * get user Id + */ +const getUserID = () => { + const i = document.cookie.indexOf(COOKIE_NAME); + + if (i === -1) { + const uuid = utils.generateUUID(); + document.cookie = `${COOKIE_NAME}=${uuid}; path=/`; + return uuid; + } + + const j = i + COOKIE_NAME.length + 1; + return document.cookie.substring(j, j + UUID_LEN); +}; + +/** + * get page description + */ +function getPageDescription() { + if (document.querySelector('meta[name="description"]')) { + return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. + } else { + return ''; + } +}; + +function getTopWindow() { + try { + return window.top; + } catch (e) { + return window; + } +}; diff --git a/modules/eywamediaBidAdapter.md b/modules/eywamediaBidAdapter.md new file mode 100644 index 00000000000..76b9b032c1b --- /dev/null +++ b/modules/eywamediaBidAdapter.md @@ -0,0 +1,37 @@ +# Overview + +``` +Module Name: Eywamedia Bid Adapter +Module Type: Bidder Adapter +Maintainer: sharath@eywamedia.com +Note: Our ads will only render in mobile and desktop +``` + +# Description + +Connects to Eywamedia Ad Server for bids. + +Eywamedia bid adapter supports Banners. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'eywamedia', + params: { + publisherId: 'f63a2362-5aa4-4829-bbd2-2678ced8b63e', //Required - GUID (may include numbers and characters) + bidFloor: 0.50, // optional + cats: ["iab1-1","iab23-2"], // optional + keywords: ["sports", "cricket"], // optional + lat: 12.33333, // optional + lon: 77.32322, // optional + locn: "country$region$city$zip" // optional + } + }] + } +]; +``` diff --git a/test/spec/modules/eywamediaBidAdapter_spec.js b/test/spec/modules/eywamediaBidAdapter_spec.js new file mode 100644 index 00000000000..945c0dd0d01 --- /dev/null +++ b/test/spec/modules/eywamediaBidAdapter_spec.js @@ -0,0 +1,253 @@ +import { expect } from 'chai'; +import { spec } from 'modules/eywamediaBidAdapter'; + +describe('EywamediaAdapter', function () { + let serverResponse, bidRequests, bidRequest, bidResponses; + const ENDPOINT = 'https://adtarbostg.eywamedia.com/auctions/prebidjs/3000'; + + bidRequests = [ + { + 'auctionId': 'fc917230-a5e1-4a42-b7d9-8fb776124e43', + 'sizes': [[300, 250]], + 'bidRequestsCount': 1, + 'params': { + 'publisherId': '1234_abcd' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'crumbs': { + 'pubcid': '8b640d4e-1f6d-4fd3-b63f-2570572d8100' + }, + 'bidId': '28b09d0543d671', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b1', + 'src': 'client', + 'bidder': 'eywamedia', + 'bidderRequestId': '14d8cbc769114b' + }, + { + 'auctionId': 'fc917230-a5e1-4a42-b7d9-8fb776124e43', + 'sizes': [[728, 90]], + 'bidRequestsCount': 1, + 'params': { + 'publisherId': '1234_abcd' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[728, 90]] + } + }, + 'crumbs': { + 'pubcid': '8b640d4e-1f6d-4fd3-b63f-2570572d8100' + }, + 'bidId': '28b09d0543d672', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b2', + 'src': 'client', + 'bidder': 'eywamedia', + 'bidderRequestId': '14d8cbc769114b' + } + ]; + + bidRequest = { + 'auctionId': 'c88115a4-7e71-43d0-9c96-a9b43ebd143d', + 'auctionStart': 1564725164517, + 'bidderCode': 'eywamedia', + 'bidderRequestId': '191afa18994fdd', + 'bids': [], + 'refererInfo': { + 'canonicalUrl': '', + 'numIframes': 0, + 'reachedTop': true, + 'referer': '' + }, + 'stack': [ + '' + ], + 'start': 1564725164520, + 'timeout': 3000 + }; + + let testBid = { + 'bidder': 'eywamedia', + 'params': { + 'publisherId': '1234_abcd' + } + }; + + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + assert(spec.isBidRequestValid(testBid)); + }); + + it('should return false when required params are missing', function () { + testBid.params = { + test: '231212312' + }; + assert.isFalse(spec.isBidRequestValid(testBid)); + }); + }); + + describe('buildRequests', function () { + it('should attempt to send bid requests to the endpoint via POST', function () { + const requests = spec.buildRequests(bidRequests, bidRequest); + expect(requests.method).to.equal('POST'); + expect(requests.url).to.be.equal(ENDPOINT); + }); + + it('should not blow up if crumbs is undefined', function () { + let bidArray = [ + { ...testBid, crumbs: undefined } + ] + expect(function () { spec.buildRequests(bidArray, bidRequest) }).not.to.throw() + }) + + it('should return true when required params found', function () { + testBid.params.publisherId = '1234_abcd'; + assert(spec.isBidRequestValid(testBid)); + }); + }); + + describe('interpretResponse', function () { + beforeEach(function () { + serverResponse = { + 'body': + [ + { + 'ad': '', + 'adSlot': '', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'adUrl': 'http://eywamedia.com', + 'bidId': '28b09d0543d671', + 'bidder': 'eywamedia', + 'bidderCode': 'eywamedia', + 'cpm': 1, + 'height': 250, + 'requestTimestamp': 1564725162, + 'respType': 'banner', + 'size': '300X250', + 'statusMessage': 'Bid available', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b1', + 'usesGenericKeys': true, + 'width': 300 + }, + { + 'ad': '', + 'adSlot': '', + 'adUnitCode': 'div-gpt-ad-1460505748561-1', + 'adUrl': 'http://eywamedia.com', + 'bidId': '28b09d0543d672', + 'bidder': 'eywamedia', + 'bidderCode': 'eywamedia', + 'cpm': 1, + 'height': 90, + 'requestTimestamp': 1564725164, + 'respType': 'banner', + 'size': '728X90', + 'statusMessage': 'Bid available', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b2', + 'usesGenericKeys': true, + 'width': 728 + } + ], + 'headers': 'header?' + }; + + bidRequest = { + 'data': + { + 'bidPayload': + [ + { + 'auctionId': 'fc917230-a5e1-4a42-b7d9-8fb776124e43', + 'sizes': [[300, 250]], + 'bidRequestsCount': 1, + 'params': { + 'publisherId': '1234_abcd' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'crumbs': { + 'pubcid': '8b640d4e-1f6d-4fd3-b63f-2570572d8100' + }, + 'bidId': '28b09d0543d671', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b1', + 'src': 'client', + 'bidder': 'eywamedia', + 'bidderRequestId': '14d8cbc769114b' + }, + { + 'auctionId': 'fc917230-a5e1-4a42-b7d9-8fb776124e43', + 'sizes': [[728, 90]], + 'bidRequestsCount': 1, + 'params': { + 'publisherId': '1234_abcd' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[728, 90]] + } + }, + 'crumbs': { + 'pubcid': '8b640d4e-1f6d-4fd3-b63f-2570572d8100' + }, + 'bidId': '28b09d0543d672', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b2', + 'src': 'client', + 'bidder': 'eywamedia', + 'bidderRequestId': '14d8cbc769114b' + } + ] + } + }; + bidResponses = [ + { + 'ad': '', + 'bidderCode': 'eywamedia', + 'cpm': 1, + 'creativeId': '28b09d0543d671', + 'currency': 'USD', + 'height': 250, + 'mediaType': 'banner', + 'netRevenue': true, + 'requestId': '28b09d0543d671', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b1', + 'ttl': 360, + 'width': 300 + }, + { + 'ad': '', + 'bidderCode': 'eywamedia', + 'cpm': 1, + 'creativeId': '28b09d0543d672', + 'currency': 'USD', + 'height': 90, + 'mediaType': 'banner', + 'netRevenue': true, + 'requestId': '28b09d0543d672', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b2', + 'ttl': 360, + 'width': 728 + } + ] + }); + + it('should respond with empty response when there is empty serverResponse', function () { + let result = spec.interpretResponse({ body: {} }, bidRequest); + assert.deepEqual(result, []); + }); + + it('should respond with multile response when there is multiple serverResponse', function () { + let result = spec.interpretResponse(serverResponse, bidRequest); + assert.deepEqual(result, bidResponses); + }); + }); +}); From b21252c8e8968d0e70a7414bd835b0602b658607 Mon Sep 17 00:00:00 2001 From: VideoReach <49446045+VideoReach@users.noreply.github.com> Date: Tue, 6 Aug 2019 18:10:36 +0200 Subject: [PATCH 1401/1594] Change Domain to videoreach.com (#4056) --- modules/videoreachBidAdapter.js | 4 ++-- modules/videoreachBidAdapter.md | 2 +- test/spec/modules/videoreachBidAdapter_spec.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/videoreachBidAdapter.js b/modules/videoreachBidAdapter.js index 03290c9b79c..363355292ca 100644 --- a/modules/videoreachBidAdapter.js +++ b/modules/videoreachBidAdapter.js @@ -1,7 +1,7 @@ import {registerBidder} from '../src/adapters/bidderFactory'; const utils = require('../src/utils'); const BIDDER_CODE = 'videoreach'; -const ENDPOINT_URL = '//a.videoreach.de/hb/'; +const ENDPOINT_URL = '//a.videoreach.com/hb/'; export const spec = { code: BIDDER_CODE, @@ -65,7 +65,7 @@ export const spec = { getUserSyncs: function(syncOptions, responses, gdprConsent) { const syncs = []; - if (syncOptions.pixelEnabled && responses.length) { + if (syncOptions.pixelEnabled && responses.length && responses[0].body.responses.length) { const SyncPixels = responses[0].body.responses[0].sync; let params = ''; diff --git a/modules/videoreachBidAdapter.md b/modules/videoreachBidAdapter.md index cdd1ecc04c5..a68c9b26aeb 100644 --- a/modules/videoreachBidAdapter.md +++ b/modules/videoreachBidAdapter.md @@ -2,7 +2,7 @@ **Module Name**: Video Reach Bidder Adapter **Module Type**: Bidder Adapter -**Maintainer**: hello@videoreach.de +**Maintainer**: hello@videoreach.com # Description diff --git a/test/spec/modules/videoreachBidAdapter_spec.js b/test/spec/modules/videoreachBidAdapter_spec.js index b74a0236551..237821f7102 100644 --- a/test/spec/modules/videoreachBidAdapter_spec.js +++ b/test/spec/modules/videoreachBidAdapter_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/videoreachBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -const ENDPOINT_URL = '//a.videoreach.de/hb/'; +const ENDPOINT_URL = '//a.videoreach.com/hb/'; describe('videoreachBidAdapter', function () { describe('isBidRequestValid', function () { @@ -86,7 +86,7 @@ describe('videoreachBidAdapter', function () { 'cpm': 10.0, 'width': '1', 'height': '1', - 'ad': '', + 'ad': '', 'ttl': 360, 'creativeId': '5cb5dc9375c0e', 'netRevenue': true, From a0ba466442a3b67685e10f5e37200c22f2d1b1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Tue, 6 Aug 2019 18:47:43 +0200 Subject: [PATCH 1402/1594] Add instream & outstream video support to Criteo adapter (#4037) * assign adapter version * Mapped video parameter from prebid.js to cdb * Mapped video parameter from prebid.js to cdb * Ensure that context is consistent with placement and that we do not support longform * updated playersize property name * fixed size parsing to be able to handle single player size as well as several * Changed playersize to plural playersizes in CDB contract * Use displayurl instead of creative as we want to fetch the direct url vast cache instead a vast wrapper --- modules/criteoBidAdapter.js | 106 ++++- test/spec/modules/criteoBidAdapter_spec.js | 431 ++++++++++++++++++++- 2 files changed, 530 insertions(+), 7 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 0507ba428be..56e22e45017 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -1,13 +1,14 @@ import { loadExternalScript } from '../src/adloader'; import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; +import { BANNER, VIDEO } from '../src/mediaTypes'; import { parse } from '../src/url'; import * as utils from '../src/utils'; import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -import { config } from '../src/config'; -const ADAPTER_VERSION = 17; +const ADAPTER_VERSION = 19; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -30,14 +31,27 @@ OmOSj0/qnYTAYCu0cR5LiyWG79KlIgUyMbp92ulGg24gAyGrVn4+v/4c53WlOEUp /** @type {BidderSpec} */ export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, VIDEO ], /** * @param {object} bid * @return {boolean} */ - isBidRequestValid: bid => ( - !!(bid && bid.params && (bid.params.zoneId || bid.params.networkId)) - ), + isBidRequestValid: (bid) => { + // either one of zoneId or networkId should be set + if (!(bid && bid.params && (bid.params.zoneId || bid.params.networkId))) { + return false; + } + + // video media types requires some mandatory params + if (hasVideoMediaType(bid)) { + if (!hasValidVideoMediaType(bid)) { + return false; + } + } + + return true; + }, /** * @param {BidRequest[]} bidRequests @@ -112,6 +126,9 @@ export const spec = { } if (slot.native) { bid.ad = createNativeAd(bidId, slot.native, bidRequest.params.nativeCallback); + } else if (slot.video) { + bid.vastUrl = slot.displayurl; + bid.mediaType = VIDEO; } else { bid.ad = slot.creative; } @@ -225,7 +242,7 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { impid: bidRequest.adUnitCode, transactionid: bidRequest.transactionId, auctionId: bidRequest.auctionId, - sizes: bidRequest.sizes.map(size => size[0] + 'x' + size[1]), + sizes: getBannerSizes(bidRequest), }; if (bidRequest.params.zoneId) { slot.zoneid = bidRequest.params.zoneId; @@ -236,6 +253,23 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { if (bidRequest.params.nativeCallback) { slot.native = true; } + if (hasVideoMediaType(bidRequest)) { + const video = { + playersizes: getVideoSizes(bidRequest), + mimes: bidRequest.mediaTypes.video.mimes, + protocols: bidRequest.mediaTypes.video.protocols, + maxduration: bidRequest.mediaTypes.video.maxduration, + api: bidRequest.mediaTypes.video.api + } + + video.skip = bidRequest.params.video.skip; + video.placement = bidRequest.params.video.placement; + video.minduration = bidRequest.params.video.minduration; + video.playbackmethod = bidRequest.params.video.playbackmethod; + video.startdelay = bidRequest.params.video.startdelay; + + slot.video = video; + } return slot; }), }; @@ -262,6 +296,66 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { return request; } +function getVideoSizes(bidRequest) { + return parseSizes(utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize')); +} + +function getBannerSizes(bidRequest) { + return parseSizes(utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes); +} + +function parseSize(size) { + return size[0] + 'x' + size[1]; +} + +function parseSizes(sizes) { + if (Array.isArray(sizes[0])) { // is there several sizes ? (ie. [[728,90],[200,300]]) + return sizes.map(size => parseSize(size)); + } + + return [parseSize(sizes)]; // or a single one ? (ie. [728,90]) +} + +function hasVideoMediaType(bidRequest) { + if (utils.deepAccess(bidRequest, 'params.video') === undefined) { + return false; + } + return utils.deepAccess(bidRequest, 'mediaTypes.video') !== undefined; +} + +function hasValidVideoMediaType(bidRequest) { + let isValid = true; + + var requiredMediaTypesParams = ['mimes', 'playerSize', 'maxduration', 'protocols', 'api']; + + requiredMediaTypesParams.forEach(function(param) { + if (utils.deepAccess(bidRequest, 'mediaTypes.video.' + param) === undefined) { + isValid = false; + utils.logError('Criteo Bid Adapter: mediaTypes.video.' + param + ' is required'); + } + }); + + var requiredParams = ['skip', 'placement', 'playbackmethod']; + + requiredParams.forEach(function(param) { + if (utils.deepAccess(bidRequest, 'params.video.' + param) === undefined) { + isValid = false; + utils.logError('Criteo Bid Adapter: params.video.' + param + ' is required'); + } + }); + + if (isValid) { + // We do not support long form for now, also we have to check that context & placement are consistent + if (bidRequest.mediaTypes.video.context == 'instream' && bidRequest.params.video.placement === 1) { + return true; + } else if (bidRequest.mediaTypes.video.context == 'outstream' && bidRequest.params.video.placement !== 1) { + return true; + } + } + + return false; +} + /** * @param {string} id * @param {*} payload diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index ac9ae53af07..4fe60bba17c 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -4,6 +4,7 @@ import { createBid } from 'src/bidfactory'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; import { config } from '../../../src/config'; +import { VIDEO } from '../../../src/mediaTypes'; describe('The Criteo bidding adapter', function () { beforeEach(function () { @@ -53,6 +54,309 @@ describe('The Criteo bidding adapter', function () { const isValid = spec.isBidRequestValid(bid); expect(isValid).to.equal(true); }); + + it('should return true when given a valid video bid request', function () { + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(true); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'outstream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 2, + playbackmethod: 1 + } + }, + })).to.equal(true); + }); + + it('should return false when given an invalid video bid request', function () { + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 2, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'outstream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'adpod', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30 + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1 + } + }, + })).to.equal(false); + }); }); describe('buildRequests', function () { @@ -118,7 +422,11 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - sizes: [[300, 250], [728, 90]], + mediaTypes: { + banner: { + sizes: [[300, 250], [728, 90]] + } + }, params: { networkId: 456, }, @@ -205,6 +513,94 @@ describe('The Criteo bidding adapter', function () { expect(ortbRequest.gdprConsent.consentGiven).to.equal(undefined); }); + it('should properly build a video request', function () { + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + mediaTypes: { + video: { + playerSize: [640, 480], + mimes: ['video/mp4', 'video/x-flv'], + maxduration: 30, + api: [1, 2], + protocols: [2, 3] + } + }, + params: { + zoneId: 123, + video: { + skip: 1, + minduration: 5, + startdelay: 5, + playbackmethod: [1, 3], + placement: 2 + } + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/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].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); + 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]); + expect(ortbRequest.slots[0].video.protocols).to.deep.equal([2, 3]); + expect(ortbRequest.slots[0].video.skip).to.equal(1); + expect(ortbRequest.slots[0].video.minduration).to.equal(5); + expect(ortbRequest.slots[0].video.startdelay).to.equal(5); + expect(ortbRequest.slots[0].video.playbackmethod).to.deep.equal([1, 3]); + expect(ortbRequest.slots[0].video.placement).to.equal(2); + }); + + it('should properly build a video request with more than one player size', function () { + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + mediaTypes: { + video: { + playerSize: [[640, 480], [800, 600]], + mimes: ['video/mp4', 'video/x-flv'], + maxduration: 30, + api: [1, 2], + protocols: [2, 3] + } + }, + params: { + zoneId: 123, + video: { + skip: 1, + minduration: 5, + startdelay: 5, + playbackmethod: [1, 3], + placement: 2 + } + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/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].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); + expect(ortbRequest.slots[0].video.api).to.deep.equal([1, 2]); + expect(ortbRequest.slots[0].video.protocols).to.deep.equal([2, 3]); + expect(ortbRequest.slots[0].video.skip).to.equal(1); + expect(ortbRequest.slots[0].video.minduration).to.equal(5); + expect(ortbRequest.slots[0].video.startdelay).to.equal(5); + expect(ortbRequest.slots[0].video.playbackmethod).to.deep.equal([1, 3]); + expect(ortbRequest.slots[0].video.placement).to.equal(2); + }); + it('should properly build a request with ceh', function () { const bidRequests = [ { @@ -299,6 +695,39 @@ describe('The Criteo bidding adapter', function () { expect(bids[0].height).to.equal(90); }); + it('should properly parse a bid responsewith with a video', function () { + const response = { + body: { + slots: [{ + impid: 'test-requestId', + bidId: 'abc123', + cpm: 1.23, + displayurl: 'http://test-ad', + width: 728, + height: 90, + zoneid: 123, + video: true + }], + }, + }; + const request = { + bidRequests: [{ + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + zoneId: 123, + }, + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('test-bidId'); + expect(bids[0].adId).to.equal('abc123'); + expect(bids[0].cpm).to.equal(1.23); + expect(bids[0].vastUrl).to.equal('http://test-ad'); + expect(bids[0].mediaType).to.equal(VIDEO); + }); + it('should properly parse a bid responsewith with a zoneId passed as a string', function () { const response = { body: { From 0183f2399c527f3a0b0306053a634e45f96448ce Mon Sep 17 00:00:00 2001 From: Unnamalai57 <49053809+Unnamalai57@users.noreply.github.com> Date: Tue, 6 Aug 2019 22:19:59 +0530 Subject: [PATCH 1403/1594] topRTBBidAdapter (#3817) * toprtbBidAdapter * topRTB adapter hbid queryparam added * toprtbBidAdapter-ssp aws url * topRTBBidAdapter * Video format topRTBBidAdapter * Video format topRTBBidAdapter * deviceType added * tracking new added * impression event added * fix test failed * fix testing failed * removed debug logs * added single quotes in adUnitId * remove console log * code committed to add SSL * adunitId changes for valid response --- modules/topRTBBidAdapter.js | 65 +++++++++++++++++++++ modules/topRTBBidAdapter.md | 30 ++++++++++ test/spec/modules/topRTBBidAdapter_spec.js | 67 ++++++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 modules/topRTBBidAdapter.js create mode 100644 modules/topRTBBidAdapter.md create mode 100644 test/spec/modules/topRTBBidAdapter_spec.js diff --git a/modules/topRTBBidAdapter.js b/modules/topRTBBidAdapter.js new file mode 100644 index 00000000000..783d4008b33 --- /dev/null +++ b/modules/topRTBBidAdapter.js @@ -0,0 +1,65 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER, VIDEO} from '../src/mediaTypes'; + +const BIDDER_CODE = 'topRTB'; +const ENDPOINT_URL = 'https://ssp.toprtb.com/ssp/rest/ReqAd?ref=www.google.com&hbid=0&adUnitId='; +var adName = ''; +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + isBidRequestValid: function (bid) { + if (utils.deepAccess(bid, 'mediaTypes.banner')) { + adName = 'banner'; + return bid.params && !!bid.params.adUnitId; + } + if (utils.deepAccess(bid, 'mediaTypes.video')) { + adName = 'video'; + return bid.params && !!bid.params.adUnitId; + } + }, + + buildRequests: function (validBidRequests, bidderRequest) { + let adunitid = []; + utils._each(validBidRequests, function (bid) { + adunitid.push(bid.params.adUnitId + '_' + bid.bidId); + }); + + return { + method: 'GET', + url: ENDPOINT_URL + adunitid.toString() + }; + }, + + interpretResponse: function(serverResponses, request) { + const bidResponses = []; + utils._each(serverResponses.body, function(response) { + if (response.cpm > 0) { + const bidResponse = { + requestId: response.bidId, + cpm: response.cpm, + width: response.width, + height: response.height, + ad: response.mediadata, + ttl: response.ttl, + creativeId: response.id, + netRevenue: true, + currency: response.currency, + tracking: response.tracking, + impression: response.impression + }; + if (adName == 'video') { + bidResponse.vastXml = response.mediadata; + bidResponse.mediaType = 'video'; + } else { + bidResponse.ad = response.mediadata; + bidResponse.mediaType = 'banner'; + } + bidResponses.push(bidResponse); + } + }); + return bidResponses; + } +}; + +registerBidder(spec); diff --git a/modules/topRTBBidAdapter.md b/modules/topRTBBidAdapter.md new file mode 100644 index 00000000000..d1930c928e4 --- /dev/null +++ b/modules/topRTBBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +``` +Module Name: topRTB Bidder Adapter +Module Type: Bidder Adapter +Maintainer: karthikeyan.d@djaxtech.com +``` + +# Description + +topRTB Bidder Adapter for Prebid.js. +Only Banner & video format is supported. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div-0', + sizes: [[728, 90]], // a display size + bids: [ + { + bidder: 'topRTB', + params: { + adUnitId: 'c5c06f77430c4c33814a0577cb4cc978' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/topRTBBidAdapter_spec.js b/test/spec/modules/topRTBBidAdapter_spec.js new file mode 100644 index 00000000000..83e5de3e4b9 --- /dev/null +++ b/test/spec/modules/topRTBBidAdapter_spec.js @@ -0,0 +1,67 @@ +import { expect } from 'chai'; +import { spec } from 'modules/topRTBBidAdapter'; + +describe('topRTBBidAdapterTests', function () { + it('validate_pub_params', function () { + expect(spec.isBidRequestValid({ + bidder: 'topRTB', + params: { + adUnitId: 'c5c06f77430c4c33814a0577cb4cc978' + }, + adName: 'banner' + })); + }); + + it('validate_generated_params', function () { + let bidRequestData = [{ + bidId: 'bid12345', + bidder: 'topRTB', + adName: 'banner', + adType: '{"banner":{"sizes":[[]]}}', + params: { + adUnitId: 'c5c06f77430c4c33814a0577cb4cc978' + }, + sizes: [[728, 90]] + }]; + + let request = spec.buildRequests(bidRequestData); + const current_url = request.url; + const search_params = current_url.searchParams; + }); + + it('validate_response_params', function () { + let bidRequestData = { + data: { + bidId: 'bid12345' + } + }; + + let serverResponse = { + body: [{ + 'cpm': 1, + 'mediadata': "Banner 728x90", + 'width': 728, + 'currency': 'USD', + 'id': 'cd95dffec6b645afbc4e5aa9f68f2ff3', + 'type': 'RICHMEDIA', + 'ttl': 4000, + 'bidId': 'bid12345', + 'status': 'success', + 'height': 90}], + 'adName': 'banner', + 'vastXml': '', + 'mediaType': 'banner', + 'tracking': 'https://ssp.toprtb.com/ssp/tracking?F0cloTiKIw%2BjZ2UNDvlKGn5%2FWoAO9cnlAUDm6gFBM8bImY2fKo%2BMTvI0XvXzFTZSb5v8o4EUbPId9hckptTqA4QPaWvpVYCRKRZceXNa4kjtvfm4j2e%2FcRKgkns2goHXi7IZC0sBIbE77WWg%2BPBYv%2BCu84H%2FSH69mi%2FDaWcQlfaEOdkaJdstJEkaZtkgWnFnS7aagte%2BfdEbOqcTxq5hzj%2BZ4NZbwgReuWTQZbfrMWjkXFbn%2B35vZuI319o6XH9n9fKLS4xp8zstXfQT2oSgjw1NmrwqRKf1efB1UaWlS1TbkSqxZ7Kcy7nJvAZrDk0tzcSeIxe4VfHpwgPPs%2BueUeGwz3o7OCh7H1sCmogSrmJFB9JTeXudFjC13iANAtu4SvG9bGIbiJxS%2BNfkjy2mLFm8kSIcIobjNkMEcUAwmoqJNRndwb66a3Iovk2NTo0Ly%2FV7Y5ECPcS5%2FPBrIEOuQXS5SNUPRWKoklX5nexHtOc%3D', + 'impression': 'https://ssp.toprtb.com/ssp/impression?id=64f29f7b226249f19925a680a506b32d' + }; + + let bids = spec.interpretResponse(serverResponse, bidRequestData); + expect(bids).to.have.lengthOf(1); + let bid = bids[0]; + expect(bid.cpm).to.equal(1); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(728); + expect(bid.height).to.equal(90); + expect(bid.requestId).to.equal('bid12345'); + }); +}); From a1ccdf0f6d390dcddc595e4e9d7492ec7b377944 Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 6 Aug 2019 22:21:36 +0530 Subject: [PATCH 1404/1594] add check to see if adObject is present (#4058) --- src/secureCreatives.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index f8ba9477b52..df7abe4ebee 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -31,7 +31,7 @@ function receiveMessage(ev) { return bid.adId === data.adId; }); - if (data.message === 'Prebid Request') { + if (adObject && data.message === 'Prebid Request') { _sendAdToCreative(adObject, data.adServerDomain, ev.source); // save winning bids @@ -45,7 +45,7 @@ function receiveMessage(ev) { // message: 'Prebid Native', // adId: '%%PATTERN:hb_adid%%' // }), '*'); - if (data.message === 'Prebid Native') { + if (adObject && data.message === 'Prebid Native') { if (data.action === 'assetRequest') { const message = getAssetMessage(data, adObject); ev.source.postMessage(JSON.stringify(message), ev.origin); From 32ce0eb96f6548501b539a8b1c20f785605a7c71 Mon Sep 17 00:00:00 2001 From: Rade Popovic <32302052+nanointeractive@users.noreply.github.com> Date: Tue, 6 Aug 2019 20:00:21 +0200 Subject: [PATCH 1405/1594] Consent String added to the HB request (#4044) * nanointeractive bid adapter * nanointeractive bid adapter * - using utils.getParameterByName instead of utils.getTopWindowLocation().href - bidderCode is removed - Default ALG changed to 'ihr' - added protocol to 'cors' param * markdown file * enabling localhost for bid requests * Bugfix interpretResponse - added body; Removed unnecessary parameters; Adjusted tests; * New feature - subId * Fixed lint errors * Nano Interactive Bid Adapter New Bid params: - categoryName - name Getting referrer information * Fixed documentation * Removed unnecessary parameter from documentation * Cleaning up documentation * - Sending window location to server if possible * - Lint errors fix * Using utils.js method for sending location to server * Removing unnecessary parameter passing * added ConsentString to HB request * removing unused location params in testing --- modules/nanointeractiveBidAdapter.js | 93 +++++++--- .../modules/nanointeractiveBidAdapter_spec.js | 164 +++++------------- 2 files changed, 112 insertions(+), 145 deletions(-) diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index cfef32b4c80..a76cc90ac10 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -1,11 +1,11 @@ import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER } from '../src/mediaTypes'; +import {config} from '../src/config'; +import {registerBidder} from '../src/adapters/bidderFactory'; export const BIDDER_CODE = 'nanointeractive'; -export const ENGINE_BASE_URL = 'https://www.audiencemanager.de/hb'; +export const END_POINT_URL = 'https://ad.audiencemanager.de'; -export const DATA_PARTNER_PIXEL_ID = 'pid'; +export const SSP_PLACEMENT_ID = 'pid'; export const NQ = 'nq'; export const NQ_NAME = 'name'; export const CATEGORY = 'category'; @@ -17,22 +17,27 @@ export const LOCATION = 'loc'; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [BANNER], + aliases: ['ni'], - isBidRequestValid (bid) { - const pid = bid.params[DATA_PARTNER_PIXEL_ID]; + isBidRequestValid(bid) { + const pid = bid.params[SSP_PLACEMENT_ID]; return !!(pid); }, - buildRequests (bidRequests) { + + buildRequests(validBidRequests, bidderRequest) { let payload = []; - bidRequests.forEach(bid => payload.push(createSingleBidRequest(bid))); + validBidRequests.forEach( + bid => payload.push(createSingleBidRequest(bid, bidderRequest)) + ); + const url = getEndpointUrl('main') + '/hb'; + return { method: 'POST', - url: ENGINE_BASE_URL, + url: url, data: JSON.stringify(payload) }; }, - interpretResponse (serverResponse) { + interpretResponse(serverResponse) { const bids = []; serverResponse.body.forEach(serverBid => { if (isEngineResponseValid(serverBid)) { @@ -41,23 +46,37 @@ export const spec = { }); return bids; } + }; -function createSingleBidRequest (bid) { - return { - [DATA_PARTNER_PIXEL_ID]: bid.params[DATA_PARTNER_PIXEL_ID], +function createSingleBidRequest(bid, bidderRequest) { + const location = utils.deepAccess(bidderRequest, 'refererInfo.referer'); + const origin = utils.getOrigin(); + const data = { + [SSP_PLACEMENT_ID]: bid.params[SSP_PLACEMENT_ID], [NQ]: [createNqParam(bid)], [CATEGORY]: [createCategoryParam(bid)], [SUB_ID]: createSubIdParam(bid), - [REF]: createRefParam(bid), + [REF]: createRefParam(), sizes: bid.sizes.map(value => value[0] + 'x' + value[1]), bidId: bid.bidId, - cors: utils.getOrigin(), - [LOCATION]: createLocationParam(), + cors: origin, + [LOCATION]: location, + lsUserId: getLsUserId() }; + + if (bidderRequest && bidderRequest.gdprConsent) { + data['gdprConsent'] = bidderRequest.gdprConsent.consentString; + data['gdprApplies'] = (bidderRequest.gdprConsent.gdprApplies) ? '1' : '0'; + } + + return data; } -function createSingleBidResponse (serverBid) { +function createSingleBidResponse(serverBid) { + if (serverBid.userId) { + localStorage.setItem('lsUserId', serverBid.userId); + } return { requestId: serverBid.id, cpm: serverBid.cpm, @@ -67,32 +86,50 @@ function createSingleBidResponse (serverBid) { ttl: serverBid.ttl, creativeId: serverBid.creativeId, netRevenue: serverBid.netRevenue || true, - currency: serverBid.currency, + currency: serverBid.currency }; } -function createNqParam (bid) { +function createNqParam(bid) { return bid.params[NQ_NAME] ? utils.getParameterByName(bid.params[NQ_NAME]) : bid.params[NQ] || null; } -function createCategoryParam (bid) { +function createCategoryParam(bid) { return bid.params[CATEGORY_NAME] ? utils.getParameterByName(bid.params[CATEGORY_NAME]) : bid.params[CATEGORY] || null; } -function createSubIdParam (bid) { +function createSubIdParam(bid) { return bid.params[SUB_ID] || null; } -function createRefParam (bid) { - return bid.params[REF] ? null : utils.getTopWindowReferrer() || null; +function createRefParam() { + try { + return window.top.document.referrer; + } catch (ex) { + return document.referrer; + } } -function createLocationParam () { - return utils.getTopWindowLocation().href; +function isEngineResponseValid(response) { + return !!response.cpm && !!response.ad; } -function isEngineResponseValid (response) { - return !!response.cpm && !!response.ad; +/** + * Used mainly for debugging + * + * @param type + * @returns string + */ +function getEndpointUrl(type) { + const nanoConfig = config.getConfig('nano'); + return (nanoConfig && nanoConfig['endpointUrl']) || END_POINT_URL; +} + +function getLsUserId() { + if (localStorage.getItem('lsUserId') != null) { + return localStorage.getItem('lsUserId'); + } + return null; } registerBidder(spec); diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index 3731535b88a..a357327fe96 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -1,4 +1,4 @@ -import { expect } from 'chai'; +import {expect} from 'chai'; import * as utils from 'src/utils'; import * as sinon from 'sinon'; @@ -6,8 +6,8 @@ import { BIDDER_CODE, CATEGORY, CATEGORY_NAME, - DATA_PARTNER_PIXEL_ID, - ENGINE_BASE_URL, + SSP_PLACEMENT_ID, + END_POINT_URL, NQ, NQ_NAME, REF, @@ -19,8 +19,6 @@ describe('nanointeractive adapter tests', function () { const SIZES_PARAM = 'sizes'; const BID_ID_PARAM = 'bidId'; const BID_ID_VALUE = '24a1c9ec270973'; - const CORS_PARAM = 'cors'; - const LOC_PARAM = 'loc'; const DATA_PARTNER_PIXEL_ID_VALUE = 'testPID'; const NQ_VALUE = 'rumpelstiltskin'; const NQ_NAME_QUERY_PARAM = 'nqName'; @@ -37,21 +35,7 @@ describe('nanointeractive adapter tests', function () { const AD = ' '; const CPM = 1; - function getBidResponse (pid, nq, category, subId, cors, ref, loc) { - return { - [DATA_PARTNER_PIXEL_ID]: pid, - [NQ]: nq, - [CATEGORY]: category, - [SUB_ID]: subId, - [REF]: ref, - [SIZES_PARAM]: [WIDTH1 + 'x' + HEIGHT1, WIDTH2 + 'x' + HEIGHT2], - [BID_ID_PARAM]: BID_ID_VALUE, - [CORS_PARAM]: cors, - [LOC_PARAM]: loc, - }; - } - - function getBidRequest (params) { + function getBidRequest(params) { return { bidder: BIDDER_CODE, params: params, @@ -70,85 +54,85 @@ describe('nanointeractive adapter tests', function () { describe('Methods', function () { it('Test isBidRequestValid() with valid param(s): pid', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq, category', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ, [CATEGORY]: CATEGORY_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq, categoryName', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ, [CATEGORY_NAME_QUERY_PARAM]: CATEGORY_NAME_QUERY_PARAM, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ, [SUB_ID]: SUB_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nqName', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nqName, category', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [CATEGORY]: CATEGORY_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nqName, categoryName', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [CATEGORY_NAME_QUERY_PARAM]: CATEGORY_NAME_QUERY_PARAM, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nqName, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [SUB_ID]: SUB_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, category', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [CATEGORY]: CATEGORY_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, category, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [SUB_ID]: SUB_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, @@ -156,7 +140,7 @@ describe('nanointeractive adapter tests', function () { }); it('Test isBidRequestValid() with valid param(s): pid, nqName, categoryName, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, [SUB_ID]: SUB_ID_VALUE, @@ -164,7 +148,7 @@ describe('nanointeractive adapter tests', function () { }); it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId, ref (value none)', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, @@ -173,7 +157,7 @@ describe('nanointeractive adapter tests', function () { }); it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId, ref (value other)', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, @@ -193,30 +177,22 @@ describe('nanointeractive adapter tests', function () { let sandbox; - function getMocks () { - let mockWindowLocationAddress = 'http://some-location.test'; + function getMocks() { let mockOriginAddress = 'http://localhost'; let mockRefAddress = 'http://some-ref.test'; return { - 'windowLocationAddress': mockWindowLocationAddress, + 'windowLocationAddress': mockRefAddress, 'originAddress': mockOriginAddress, - 'refAddress': mockRefAddress, + 'refAddress': '', }; } - function setUpMocks (mockRefAddress = null) { + function setUpMocks() { + sinon.sandbox.restore(); sandbox = sinon.sandbox.create(); sandbox.stub(utils, 'getOrigin').callsFake(() => getMocks()['originAddress']); - sandbox.stub(utils, 'getTopWindowLocation').callsFake(() => { - return { - 'href': getMocks()['windowLocationAddress'] - }; - }); - if (mockRefAddress == null) { - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => getMocks()['refAddress']); - } else { - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - } + sandbox.stub(utils, 'deepAccess').callsFake(() => getMocks()['windowLocationAddress']); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { switch (arg) { case CATEGORY_NAME_QUERY_PARAM: @@ -227,39 +203,31 @@ describe('nanointeractive adapter tests', function () { }); } - function assert ( + function assert( request, expectedPid, expectedNq, expectedCategory, - expectedSubId, - expectedRef = getMocks()['refAddress'], - expectedOrigin = getMocks()['originAddress'], - expectedLocation = getMocks()['windowLocationAddress'] + expectedSubId ) { + const requestData = JSON.parse(request.data); + expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - expectedPid, - expectedNq, - expectedCategory, - expectedSubId, - expectedOrigin, - expectedRef, - expectedLocation, - ), - ])); + expect(request.url).to.equal(END_POINT_URL + '/hb'); + expect(requestData[0].pid).to.equal(expectedPid); + expect(requestData[0].nq.toString()).to.equal(expectedNq.toString()); + expect(requestData[0].category.toString()).to.equal(expectedCategory.toString()); + expect(requestData[0].subId).to.equal(expectedSubId); } - function tearDownMocks () { + function tearDownMocks() { sandbox.restore(); } it('Test buildRequest() - pid', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, }; let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; let expectedNq = [null]; @@ -274,7 +242,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nq', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, }; let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; @@ -290,7 +258,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nq, category', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, }; @@ -308,7 +276,7 @@ describe('nanointeractive adapter tests', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, }; @@ -325,7 +293,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nq, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [SUB_ID]: SUB_ID_VALUE, }; @@ -342,7 +310,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, category', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [CATEGORY]: CATEGORY_VALUE, }; let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; @@ -358,7 +326,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, category, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, }; @@ -375,7 +343,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [SUB_ID]: SUB_ID_VALUE, }; let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; @@ -391,7 +359,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nq, category, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, @@ -409,7 +377,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nqName, categoryName, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, [SUB_ID]: SUB_ID_VALUE, @@ -424,44 +392,6 @@ describe('nanointeractive adapter tests', function () { assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); tearDownMocks(); }); - it('Test buildRequest() - pid, nq, category, subId, ref (value none)', function () { - setUpMocks(null); - let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY]: CATEGORY_VALUE, - [SUB_ID]: SUB_ID_VALUE, - [REF]: REF_NO_VALUE, - }; - let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; - let expectedNq = [NQ_VALUE]; - let expectedCategory = [CATEGORY_VALUE]; - let expectedSubId = SUB_ID_VALUE; - - let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); - - assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId, null); - tearDownMocks(); - }); - it('Test buildRequest() - pid, nq, category, subId, ref (value other)', function () { - setUpMocks(null); - let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY]: CATEGORY_VALUE, - [SUB_ID]: SUB_ID_VALUE, - [REF]: REF_OTHER_VALUE, - }; - let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; - let expectedNq = [NQ_VALUE]; - let expectedCategory = [CATEGORY_VALUE]; - let expectedSubId = SUB_ID_VALUE; - - let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); - - assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId, null); - tearDownMocks(); - }); it('Test interpretResponse() length', function () { let bids = nanoBidAdapter.interpretResponse({ body: [ From 36ef1de1b9833f3dd514d884c6896bb0fd1f5583 Mon Sep 17 00:00:00 2001 From: Andy Day Date: Tue, 6 Aug 2019 11:28:28 -0700 Subject: [PATCH 1406/1594] Update URI for IdentityLink integration (#4049) * Update URI for IdentityLink integration We have moved the URI for the Envelope API, and are currently shiming requests with the rt parameter. This will eventually be deprecated, so we want to update to the correct URI w/o the rt param. * bump --- modules/identityLinkSystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/identityLinkSystem.js b/modules/identityLinkSystem.js index 8b8fa491bad..ef916252811 100644 --- a/modules/identityLinkSystem.js +++ b/modules/identityLinkSystem.js @@ -37,7 +37,7 @@ export const identityLinkSubmodule = { return; } // use protocol relative urls for http or https - const url = `https://api.rlcdn.com/api/identity?pid=${configParams.pid}&rt=envelope`; + const url = `https://api.rlcdn.com/api/identity/envelope?pid=${configParams.pid}`; return function (callback) { ajax(url, response => { From 5cce306774ae9dca9af155b724f6174e25d72fd8 Mon Sep 17 00:00:00 2001 From: Jurij Sinickij Date: Tue, 6 Aug 2019 21:43:08 +0300 Subject: [PATCH 1407/1594] adformOpenRTB adapter: parse seatbid bid responses (#4043) --- modules/adformOpenRTBBidAdapter.js | 8 +- .../modules/adformOpenRTBBidAdapter_spec.js | 73 ++++++++++++++++++- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/modules/adformOpenRTBBidAdapter.js b/modules/adformOpenRTBBidAdapter.js index 0f69ccd6262..98e6de8036a 100644 --- a/modules/adformOpenRTBBidAdapter.js +++ b/modules/adformOpenRTBBidAdapter.js @@ -143,9 +143,13 @@ export const spec = { } 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 _cbid = seatbid && seatbid[id] && seatbid[id].bid; - const bidResponse = _cbid && _cbid[0]; + const bidResponse = bidResponses[id]; if (bidResponse) { return { requestId: bid.bidId, diff --git a/test/spec/modules/adformOpenRTBBidAdapter_spec.js b/test/spec/modules/adformOpenRTBBidAdapter_spec.js index cafbe4eff15..32795c24ef6 100644 --- a/test/spec/modules/adformOpenRTBBidAdapter_spec.js +++ b/test/spec/modules/adformOpenRTBBidAdapter_spec.js @@ -384,9 +384,9 @@ describe('AdformOpenRTB adapter', function () { let serverResponse = { body: { seatbid: [{ - bid: [{impid: 'impid1', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}}] + bid: [{impid: '1', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}}] }, { - bid: [{impid: 'impid2', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, data: {value: 'Asset title text'}}]}}] + bid: [{impid: '2', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, data: {value: 'Asset title text'}}]}}] }] } }; @@ -417,6 +417,71 @@ describe('AdformOpenRTB adapter', function () { bids = spec.interpretResponse(serverResponse, bidRequest); assert.equal(spec.interpretResponse(serverResponse, bidRequest).length, 2); }); + + it('should parse seatbids', function () { + let serverResponse = { + body: { + seatbid: [{ + bid: [ + {impid: '1', native: {ver: '1.1', link: { url: 'link1' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}}, + {impid: '4', native: {ver: '1.1', link: { url: 'link4' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}} + ] + }, { + bid: [{impid: '2', native: {ver: '1.1', link: { url: 'link2' }, assets: [{id: 1, data: {value: 'Asset title text'}}]}}] + }] + } + }; + let bidRequest = { + data: {}, + bids: [ + { + bidId: 'bidId1', + params: { siteId: 'siteId', mid: 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: { siteId: 'siteId', mid: 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: 'bidId3', + params: { siteId: 'siteId', mid: 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: 'bidId4', + params: { siteId: 'siteId', mid: 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 } + } + } + ] + }; + + bids = spec.interpretResponse(serverResponse, bidRequest).map(bid => { + const { requestId, native: { clickUrl } } = bid; + return [ requestId, clickUrl ]; + }); + + assert.equal(bids.length, 3); + assert.deepEqual(bids, [[ 'bidId1', 'link1' ], [ 'bidId2', 'link2' ], [ 'bidId4', 'link4' ]]); + }); + it('should set correct values to bid', function () { let serverResponse = { body: { @@ -425,7 +490,7 @@ describe('AdformOpenRTB adapter', function () { seatbid: [{ bid: [ { - impid: 'impid1', + impid: '1', price: 93.1231, crid: '12312312', native: { @@ -468,7 +533,7 @@ describe('AdformOpenRTB adapter', function () { it('should set correct native params', function () { const bid = [ { - impid: 'impid1', + impid: '1', price: 93.1231, crid: '12312312', native: { From 64a45da50fbfcf2318744db400f68a618ec88f01 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 6 Aug 2019 15:27:39 -0400 Subject: [PATCH 1408/1594] revert karma and other package updates (#4067) --- .circleci/config.yml | 2 +- README.md | 4 +- package-lock.json | 8591 +++++++++--------------------------------- package.json | 6 +- 4 files changed, 1735 insertions(+), 6868 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 85452b5aa88..16bdd5b317e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: build: docker: # specify the version you desire here - - image: circleci/node:9.0.0 + - image: circleci/node:7.10 # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images diff --git a/README.md b/README.md index a50c55f96ca..21e02ebee7f 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ module.exports = { } ``` -Or for Babel 6: +Or for Babel 6 and/or Node v8.6.0 and less: ```javascript // you must manually install and specify the presets and plugins yourself options: { @@ -112,7 +112,7 @@ prebid.requestBids({ $ cd Prebid.js $ npm install -*Note:* You need to have `NodeJS` 9.x or greater installed. +*Note:* You need to have `NodeJS` 6.x or greater installed. *Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To compily with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in it's setup. diff --git a/package-lock.json b/package-lock.json index 1ed87be2492..e8e1461cbe8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,172 +2,96 @@ "name": "prebid.js", "version": "2.27.0-pre", "lockfileVersion": 1, - "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true }, "@babel/core": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", - "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helpers": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.5", - "@babel/types": "^7.4.4", - "convert-source-map": "^1.1.0", - "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.11", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "dev": true }, "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4", - "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "dev": true }, "@babel/helper-annotate-as-pure": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-call-delegate": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } + "dev": true }, "@babel/helper-define-map": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", - "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", + "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", + "dev": true }, "@babel/helper-explode-assignable-expression": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-get-function-arity": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-hoist-variables": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } + "dev": true }, "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", + "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", + "dev": true }, "@babel/helper-module-imports": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-module-transforms": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", - "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/template": "^7.4.4", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", + "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "dev": true }, "@babel/helper-optimise-call-expression": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-plugin-utils": { "version": "7.0.0", @@ -176,607 +100,346 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", - "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "dev": true }, "@babel/helper-remap-async-to-generator": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-replace-supers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", - "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", + "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", + "dev": true }, "@babel/helper-simple-access": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-split-export-declaration": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } + "dev": true }, "@babel/helper-wrap-function": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.2.0" - } + "dev": true }, "@babel/helpers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", - "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", - "dev": true, - "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "dev": true }, "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true }, "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" - } + "dev": true + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", + "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "dev": true }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" - } + "dev": true }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", - "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", + "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", + "dev": true }, "@babel/plugin-proposal-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" - } + "dev": true }, "@babel/plugin-proposal-unicode-property-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } + "dev": true }, "@babel/plugin-syntax-async-generators": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", + "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "dev": true }, "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-syntax-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-async-to-generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", - "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", + "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", + "dev": true }, "@babel/plugin-transform-block-scoped-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-block-scoping": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", - "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", + "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", + "dev": true }, "@babel/plugin-transform-classes": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", - "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", - "@babel/helper-split-export-declaration": "^7.4.4", - "globals": "^11.1.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", + "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", + "dev": true }, "@babel/plugin-transform-computed-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-destructuring": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", - "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", + "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", + "dev": true }, "@babel/plugin-transform-dotall-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } + "dev": true }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", - "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", + "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "dev": true }, "@babel/plugin-transform-exponentiation-operator": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-for-of": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-function-name": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-member-expression-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-modules-amd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", - "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", + "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "dev": true }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", - "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", + "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", + "dev": true }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", - "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", + "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", + "dev": true }, "@babel/plugin-transform-modules-umd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", - "dev": true, - "requires": { - "regexp-tree": "^0.1.6" - } + "dev": true }, "@babel/plugin-transform-new-target": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-object-super": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", - "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", + "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "dev": true }, "@babel/plugin-transform-parameters": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-property-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-regenerator": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.0" - } + "dev": true }, "@babel/plugin-transform-reserved-words": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-shorthand-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-spread": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-sticky-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-template-literals": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-typeof-symbol": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-unicode-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } + "dev": true }, "@babel/preset-env": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", - "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.4", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.4", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.4", - "@babel/plugin-transform-classes": "^7.4.4", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.2.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.4", - "@babel/plugin-transform-modules-systemjs": "^7.4.4", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "browserslist": "^4.6.0", - "core-js-compat": "^3.1.1", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.5.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", + "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", + "dev": true }, "@babel/template": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" - } + "dev": true }, "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "dev": true }, "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "dev": true }, "@gulp-sourcemaps/identity-map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", "dev": true, - "requires": { - "acorn": "^5.0.3", - "css": "^2.2.1", - "normalize-path": "^2.1.1", - "source-map": "^0.6.0", - "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" - } + "dev": true }, "source-map": { "version": "0.6.1", @@ -791,19 +454,12 @@ "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" - } + "dev": true } } }, @@ -817,38 +473,19 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } + "dev": true }, "@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" - }, - "dependencies": { - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - } - } + "dev": true }, "@sinonjs/samsam": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.0.2", - "array-from": "^2.1.1", - "lodash": "^4.17.11" - } + "dev": true }, "@sinonjs/text-encoding": { "version": "0.7.1", @@ -856,219 +493,17 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@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 - }, - "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" - } - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", "dev": true }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } + "dev": true }, "acorn": { "version": "5.7.3", @@ -1081,9 +516,6 @@ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", "dev": true, - "requires": { - "acorn": "^4.0.3" - }, "dependencies": { "acorn": { "version": "4.0.13", @@ -1098,9 +530,6 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, - "requires": { - "acorn": "^3.0.4" - }, "dependencies": { "acorn": { "version": "3.3.0", @@ -1111,9 +540,9 @@ } }, "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, "after": { @@ -1126,27 +555,12 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } + "dev": true }, "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-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", "dev": true }, "ajv-keywords": { @@ -1160,20 +574,12 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, "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" - } + "dev": true } } }, @@ -1181,8 +587,7 @@ "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": "3.2.3", @@ -1200,10 +605,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } + "dev": true }, "ansi-html": { "version": "0.0.7", @@ -1221,10 +623,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } + "dev": true }, "ansi-wrap": { "version": "0.1.0", @@ -1237,19 +636,12 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "dev": true } } }, @@ -1257,24 +649,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } + "dev": true }, "append-transform": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "^1.0.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "archiver": { @@ -1282,25 +662,12 @@ "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", "dev": true, - "requires": { - "archiver-utils": "^1.3.0", - "async": "^2.0.0", - "buffer-crc32": "^0.2.1", - "glob": "^7.0.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0", - "tar-stream": "^1.5.0", - "zip-stream": "^1.2.0" - }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true } } }, @@ -1309,23 +676,12 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", "dev": true, - "requires": { - "glob": "^7.0.0", - "graceful-fs": "^4.1.0", - "lazystream": "^1.0.0", - "lodash": "^4.8.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" - }, "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" - } + "dev": true } } }, @@ -1339,10 +695,7 @@ "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.2" - } + "dev": true }, "arr-diff": { "version": "4.0.0", @@ -1354,10 +707,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } + "dev": true }, "arr-flatten": { "version": "1.1.0", @@ -1369,10 +719,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } + "dev": true }, "arr-union": { "version": "3.1.0", @@ -1420,21 +767,13 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" - } + "dev": true }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, "dependencies": { "is-number": { "version": "4.0.0", @@ -1449,9 +788,6 @@ "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", "dev": true, - "requires": { - "is-number": "^4.0.0" - }, "dependencies": { "is-number": { "version": "4.0.0", @@ -1484,11 +820,6 @@ "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -1520,31 +851,19 @@ "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.0" - } + "dev": true }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } + "dev": true }, "assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, "dependencies": { "inherits": { "version": "2.0.1", @@ -1556,10 +875,7 @@ "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" - } + "dev": true } } }, @@ -1591,13 +907,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", "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" - } + "dev": true }, "async-each": { "version": "1.0.3", @@ -1606,19 +916,16 @@ "dev": true }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "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" - } + "dev": true }, "asynckit": { "version": "0.4.0", @@ -1649,11 +956,6 @@ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -1665,14 +967,7 @@ "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" - } + "dev": true }, "js-tokens": { "version": "3.0.2", @@ -1693,36 +988,12 @@ "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" - } + "dev": true }, "json5": { "version": "0.5.1", @@ -1743,16 +1014,6 @@ "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": { "jsesc": { "version": "1.3.0", @@ -1766,202 +1027,115 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-builder-react-jsx": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" - } + "dev": true }, "babel-helper-call-delegate": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-define-map": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-helper-explode-assignable-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-explode-class": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-get-function-arity": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-hoist-variables": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-regex": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-helper-remap-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "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" - } + "dev": true }, "babel-loader": { "version": "8.0.6", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", - "dev": true, - "requires": { - "find-cache-dir": "^2.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "pify": "^4.0.1" - } + "dev": true }, "babel-messages": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-check-es2015-constants": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", @@ -2051,323 +1225,181 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0" - } + "dev": true }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-generators": "^6.5.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-class-constructor-call": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, - "requires": { - "babel-plugin-syntax-class-constructor-call": "^6.18.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-class-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-decorators": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "^6.24.1", - "babel-plugin-syntax-decorators": "^6.13.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-decorators-legacy": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", - "dev": true, - "requires": { - "babel-plugin-syntax-decorators": "^6.1.18", - "babel-runtime": "^6.2.0", - "babel-template": "^6.3.0" - } + "dev": true }, "babel-plugin-transform-do-expressions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true, - "requires": { - "babel-plugin-syntax-do-expressions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-block-scoping": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-plugin-transform-es2015-classes": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-computed-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-destructuring": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-duplicate-keys": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-for-of": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-modules-amd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } + "dev": true }, "babel-plugin-transform-es2015-modules-systemjs": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-modules-umd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-parameters": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-shorthand-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-spread": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-sticky-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-template-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-typeof-symbol": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-unicode-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -2379,12 +1411,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } + "dev": true }, "regjsgen": { "version": "0.2.0", @@ -2396,10 +1423,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } + "dev": true } } }, @@ -2407,120 +1431,72 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-export-extensions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, - "requires": { - "babel-plugin-syntax-export-extensions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-flow-strip-types": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-function-bind": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true, - "requires": { - "babel-plugin-syntax-function-bind": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "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=", - "requires": { - "babel-runtime": "^6.22.0" - } + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=" }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" - } + "dev": true }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx-source": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-regenerator": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - }, "dependencies": { "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } + "dev": true } } }, @@ -2528,59 +1504,19 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - }, "dependencies": { "browserslist": { "version": "3.2.8", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } + "dev": true } } }, @@ -2588,134 +1524,66 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } + "dev": true }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" - } + "dev": true }, "babel-preset-stage-0": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true, - "requires": { - "babel-plugin-transform-do-expressions": "^6.22.0", - "babel-plugin-transform-function-bind": "^6.22.0", - "babel-preset-stage-1": "^6.24.1" - } + "dev": true }, "babel-preset-stage-1": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, - "requires": { - "babel-plugin-transform-class-constructor-call": "^6.24.1", - "babel-plugin-transform-export-extensions": "^6.22.0", - "babel-preset-stage-2": "^6.24.1" - } + "dev": true }, "babel-preset-stage-2": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-decorators": "^6.24.1", - "babel-preset-stage-3": "^6.24.1" - } + "dev": true }, "babel-preset-stage-3": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-async-to-generator": "^6.24.1", - "babel-plugin-transform-exponentiation-operator": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.22.0" - } + "dev": true }, "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" - } + "dev": true }, "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=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=" }, "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" - } + "dev": true }, "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" - } + "dev": true }, "globals": { "version": "9.18.0", @@ -2736,12 +1604,6 @@ "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", @@ -2767,18 +1629,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", "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" - } + "dev": true }, "backo2": { "version": "1.0.2", @@ -2803,53 +1654,30 @@ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "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" - }, "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.0" - } + "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.0" - } + "dev": true }, "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.0" - } + "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.2" - } + "dev": true } } }, @@ -2860,9 +1688,9 @@ "dev": true }, "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, "base64id": { @@ -2881,10 +1709,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } + "dev": true }, "beeper": { "version": "1.1.1", @@ -2896,22 +1721,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } + "dev": true }, "bfj": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", - "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "check-types": "^7.3.0", - "hoopy": "^0.1.2", - "tryer": "^1.0.0" - } + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", + "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", + "dev": true }, "big.js": { "version": "5.2.2", @@ -2935,11 +1751,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } + "dev": true }, "blob": { "version": "0.0.5", @@ -2963,31 +1775,13 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "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" - } + "dev": true }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, "dependencies": { "bytes": { "version": "3.1.0", @@ -2999,23 +1793,19 @@ "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" - } + "dev": true }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } + "dev": true + }, + "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", @@ -3033,13 +1823,7 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } + "dev": true }, "setprototypeof": { "version": "1.1.1", @@ -3053,38 +1837,19 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "dev": true }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, "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" - } + "dev": true } } }, @@ -3099,9 +1864,6 @@ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, - "requires": { - "resolve": "1.1.7" - }, "dependencies": { "resolve": { "version": "1.1.7", @@ -3121,139 +1883,67 @@ "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.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "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.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } + "dev": true }, "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.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "dev": true }, "browserify-rsa": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } + "dev": true }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } + "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.5" - } + "dev": true }, "browserslist": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", - "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000975", - "electron-to-chromium": "^1.3.164", - "node-releases": "^1.1.23" - } + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", + "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", + "dev": true }, "browserstack": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", - "dev": true, - "requires": { - "https-proxy-agent": "^2.2.1" - } + "dev": true }, "browserstack-local": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", - "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", - "dev": true, - "requires": { - "https-proxy-agent": "^2.2.1", - "is-running": "^2.0.0", - "ps-tree": "=1.1.1", - "sinon": "^1.17.6", - "temp-fs": "^0.9.9" - }, - "dependencies": { - "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": ">=0.10.3 <1" - } - } - } + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.2.tgz", + "integrity": "sha512-fRaynjF0MvtyyfPRy2NFnVwxLyNtD28K/v9xRsIjUVf7xLc80NIm7Nfr3KXlFmWizhG91PL/UAOXlHkoxQjaNw==", + "dev": true }, "buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } + "dev": true }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } + "dev": true }, "buffer-alloc-unsafe": { "version": "1.1.0", @@ -3309,85 +1999,17 @@ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, - "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - }, - "dependencies": { - "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, - "requires": { - "yallist": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, "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, - "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" - } + "dev": true }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", "dev": true, - "requires": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - }, "dependencies": { "lowercase-keys": { "version": "1.0.0", @@ -3399,12 +2021,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, - "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" - } + "dev": true }, "prepend-http": { "version": "2.0.0", @@ -3414,23 +2031,15 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } + "dev": true }, "sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } + "dev": true } } }, @@ -3438,10 +2047,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } + "dev": true }, "callsite": { "version": "1.0.0", @@ -3466,10 +2072,6 @@ "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" - }, "dependencies": { "camelcase": { "version": "2.1.1", @@ -3480,9 +2082,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000975", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", - "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", + "version": "1.0.30000989", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz", + "integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==", "dev": true }, "caseless": { @@ -3501,36 +2103,19 @@ "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.3", - "lazy-cache": "^1.0.3" - } + "dev": true }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } + "dev": true }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "dev": true }, "character-entities": { "version": "1.2.3", @@ -3569,55 +2154,22 @@ "dev": true }, "check-types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", - "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", + "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": "2.1.6", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", - "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" - } - }, - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", "dev": true }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, "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.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "circular-json": { "version": "0.3.3", @@ -3630,21 +2182,12 @@ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "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" - }, "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" - } + "dev": true } } }, @@ -3652,10 +2195,7 @@ "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, - "requires": { - "restore-cursor": "^2.0.0" - } + "dev": true }, "cli-width": { "version": "2.2.0", @@ -3668,11 +2208,6 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -3684,10 +2219,7 @@ "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" - } + "dev": true } } }, @@ -3707,10 +2239,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } + "dev": true }, "clone-stats": { "version": "1.0.0", @@ -3722,12 +2251,7 @@ "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, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } + "dev": true }, "co": { "version": "4.6.0", @@ -3751,31 +2275,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "dev": true }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } + "dev": true }, "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, - "requires": { - "color-name": "1.1.3" - } + "dev": true }, "color-name": { "version": "1.1.3", @@ -3795,14 +2307,17 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } + "dev": true }, "comma-separated-tokens": { "version": "1.0.7", @@ -3845,21 +2360,12 @@ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", "dev": true, - "requires": { - "buffer-crc32": "^0.2.1", - "crc32-stream": "^2.0.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" - }, "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" - } + "dev": true } } }, @@ -3873,22 +2379,13 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "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" - } + "dev": true }, "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, - "requires": { - "source-map": "^0.6.1" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -3903,21 +2400,12 @@ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "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" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -3937,10 +2425,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } + "dev": true }, "constants-browserify": { "version": "1.0.0", @@ -3958,10 +2443,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } + "dev": true }, "content-type": { "version": "1.0.4", @@ -3979,10 +2461,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } + "dev": true }, "cookie": { "version": "0.3.1", @@ -3996,31 +2475,6 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -4031,11 +2485,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true, - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" - } + "dev": true }, "core-js": { "version": "2.6.9", @@ -4047,16 +2497,11 @@ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", "dev": true, - "requires": { - "browserslist": "^4.6.2", - "core-js-pure": "3.1.4", - "semver": "^6.1.1" - }, "dependencies": { "semver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", - "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -4074,106 +2519,52 @@ "dev": true }, "coveralls": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.4.tgz", - "integrity": "sha512-eyqUWA/7RT0JagiL0tThVhjbIjoiEUyWCjtUJoOPcWoeofP5WK/jb2OJYoBFrR6DvplR+AxOyuBqk4JHkk5ykA==", - "dev": true, - "requires": { - "growl": "~> 1.10.0", - "js-yaml": "^3.11.0", - "lcov-parse": "^0.0.10", - "log-driver": "^1.2.7", - "minimist": "^1.2.0", - "request": "^2.86.0" - } + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", + "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", + "dev": true }, "crc": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true, - "requires": { - "buffer": "^5.1.0" - } + "dev": true }, "crc32-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", - "dev": true, - "requires": { - "crc": "^3.4.4", - "readable-stream": "^2.0.0" - } + "dev": true }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } + "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.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } + "dev": true }, "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.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } + "dev": true }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "dev": true }, "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": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } + "dev": true }, "crypto-js": { "version": "3.1.9-1", @@ -4185,12 +2576,6 @@ "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", "dev": true, - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -4204,10 +2589,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true, - "requires": { - "css": "^2.0.0" - } + "dev": true }, "css-value": { "version": "0.0.1", @@ -4219,10 +2601,7 @@ "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" - } + "dev": true }, "custom-event": { "version": "1.0.1", @@ -4230,35 +2609,22 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, "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, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } + "dev": true }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } + "dev": true }, "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, "date-now": { @@ -4271,40 +2637,25 @@ "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" - } + "dev": true }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true }, "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, - "requires": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true } } }, @@ -4324,19 +2675,13 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } + "dev": true }, "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, - "requires": { - "type-detect": "^4.0.0" - } + "dev": true }, "deep-is": { "version": "0.1.3", @@ -4355,9 +2700,6 @@ "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -4372,18 +2714,12 @@ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, - "requires": { - "strip-bom": "^2.0.0" - }, "dependencies": { "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" - } + "dev": true } } }, @@ -4397,49 +2733,31 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } + "dev": true }, "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, - "requires": { - "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.0" - } + "dev": true }, "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.0" - } + "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.2" - } + "dev": true } } }, @@ -4465,11 +2783,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } + "dev": true }, "destroy": { "version": "1.0.4", @@ -4481,10 +2795,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.2.tgz", "integrity": "sha512-Q57yPrxScy816TTE1P/uLRXLDKjXhvYTbfxS/e6lPD+YrqghbsMlGB9nQzj/zVtSPaF0DFPSdO916EWO4sQUyQ==", - "dev": true, - "requires": { - "repeat-string": "^1.5.4" - } + "dev": true }, "detect-file": { "version": "1.0.0", @@ -4496,10 +2807,7 @@ "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" - } + "dev": true }, "detect-libc": { "version": "1.0.3", @@ -4517,11 +2825,7 @@ "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true, - "requires": { - "acorn": "^5.2.1", - "defined": "^1.0.0" - } + "dev": true }, "di": { "version": "0.0.1", @@ -4539,22 +2843,13 @@ "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.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } + "dev": true }, "disparity": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", "dev": true, - "requires": { - "ansi-styles": "^2.0.1", - "diff": "^1.3.2" - }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -4573,78 +2868,19 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } + "dev": true }, "doctrine-temporary-fork": { "version": "2.0.0-alpha-allowarrayindex", "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } + "dev": true }, "documentation": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", "dev": true, - "requires": { - "ansi-html": "^0.0.7", - "babel-core": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-plugin-system-import-transformer": "3.1.0", - "babel-plugin-transform-decorators-legacy": "^1.3.4", - "babel-preset-env": "^1.6.1", - "babel-preset-react": "^6.24.1", - "babel-preset-stage-0": "^6.24.1", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babelify": "^8.0.0", - "babylon": "^6.18.0", - "chalk": "^2.3.0", - "chokidar": "^2.0.0", - "concat-stream": "^1.6.0", - "disparity": "^2.0.0", - "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", - "get-port": "^3.2.0", - "git-url-parse": "^8.0.0", - "github-slugger": "1.2.0", - "glob": "^7.1.2", - "globals-docs": "^2.4.0", - "highlight.js": "^9.12.0", - "js-yaml": "^3.10.0", - "lodash": "^4.17.4", - "mdast-util-inject": "^1.1.0", - "micromatch": "^3.1.5", - "mime": "^1.4.1", - "module-deps-sortable": "4.0.6", - "parse-filepath": "^1.0.2", - "pify": "^3.0.0", - "read-pkg-up": "^3.0.0", - "remark": "^9.0.0", - "remark-html": "7.0.0", - "remark-reference-links": "^4.0.1", - "remark-toc": "^5.0.0", - "remote-origin-url": "0.4.0", - "shelljs": "^0.8.1", - "stream-array": "^1.1.2", - "strip-json-comments": "^2.0.1", - "tiny-lr": "^1.1.0", - "unist-builder": "^1.0.2", - "unist-util-visit": "^1.3.0", - "vfile": "^2.3.0", - "vfile-reporter": "^4.0.0", - "vfile-sort": "^2.1.0", - "vinyl": "^2.1.0", - "vinyl-fs": "^3.0.2", - "yargs": "^9.0.1" - }, "dependencies": { "camelcase": { "version": "4.1.0", @@ -4657,22 +2893,12 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, "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.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true } } }, @@ -4680,36 +2906,19 @@ "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.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "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.0.1", - "get-stream": "^3.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" - } + "dev": true }, "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" - } + "dev": true }, "get-caller-file": { "version": "1.0.3", @@ -4727,31 +2936,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "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.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, "dependencies": { "pify": { "version": "2.3.0", @@ -4765,20 +2962,19 @@ "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" - } + "dev": true + }, + "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 }, "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.0.0" - } + "dev": true }, "mimic-fn": { "version": "1.2.0", @@ -4790,30 +2986,19 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } + "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" - } + "dev": true }, "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.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -4825,19 +3010,13 @@ "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" - } + "dev": true }, "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.0.0" - }, "dependencies": { "pify": { "version": "2.3.0", @@ -4857,12 +3036,7 @@ "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.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "require-main-filename": { "version": "1.0.1", @@ -4876,36 +3050,23 @@ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, - "requires": { - "camelcase": "^4.1.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.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.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" - }, "dependencies": { "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.0.0", - "read-pkg": "^2.0.0" - } + "dev": true } } }, @@ -4913,10 +3074,7 @@ "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" - } + "dev": true } } }, @@ -4924,13 +3082,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } + "dev": true }, "domain-browser": { "version": "1.2.0", @@ -4953,10 +3105,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } + "dev": true }, "duplexer3": { "version": "0.1.4", @@ -4968,33 +3117,19 @@ "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" - } + "dev": true }, "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, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } + "dev": true }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } + "dev": true }, "editions": { "version": "1.3.4", @@ -5015,25 +3150,16 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.164", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", - "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", + "version": "1.3.215", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.215.tgz", + "integrity": "sha512-ZV3OnwF0FlIygwxAG2H92yt7WGjWBpawyFAFu8e9k7xJatY+BPowID0D0Bs3PMACYAJATEejw/I9cawO27ZvTg==", "dev": true }, "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "dev": true }, "emoji-regex": { "version": "7.0.3", @@ -5057,33 +3183,19 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } + "dev": true }, "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" - }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "ms": { "version": "2.0.0", @@ -5095,22 +3207,9 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -5121,11 +3220,8 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "ms": { "version": "2.0.0", @@ -5139,26 +3235,13 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } + "dev": true }, "enhanced-resolve": { "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.1.2", - "memory-fs": "^0.4.0", - "object-assign": "^4.0.1", - "tapable": "^0.2.7" - } + "dev": true }, "ent": { "version": "2.2.0", @@ -5170,65 +3253,37 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } + "dev": true }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true, - "requires": { - "string-template": "~0.2.1", - "xtend": "~4.0.0" - } + "dev": true }, "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, - "requires": { - "is-arrayish": "^0.2.1" - } + "dev": true }, "es-abstract": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" - } + "dev": true }, "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } + "dev": true }, "es5-ext": { "version": "0.10.50", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" - } + "dev": true }, "es5-shim": { "version": "4.5.13", @@ -5240,26 +3295,13 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } + "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", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } + "dev": true }, "es6-promise": { "version": "4.2.8", @@ -5271,45 +3313,25 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } + "dev": true }, "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", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } + "dev": true }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } + "dev": true }, "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, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } + "dev": true }, "escape-html": { "version": "1.0.3", @@ -5328,13 +3350,6 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, "dependencies": { "esprima": { "version": "2.7.3", @@ -5353,10 +3368,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } + "optional": true } } }, @@ -5364,59 +3376,13 @@ "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.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "dev": true }, "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "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", - "table": "4.0.2", - "text-table": "~0.2.0" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -5428,39 +3394,37 @@ "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.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "dev": true }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } + "dev": true + }, + "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 }, "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" - } + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true } } }, @@ -5475,19 +3439,12 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.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" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5498,42 +3455,28 @@ } }, "eslint-module-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", - "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", "dev": true, - "requires": { - "debug": "^2.6.8", - "pkg-dir": "^2.0.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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5545,19 +3488,13 @@ "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" - } + "dev": true }, "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.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -5569,71 +3506,39 @@ "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" - } + "dev": true } } }, "eslint-plugin-import": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", - "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", - "dev": true, - "requires": { - "array-includes": "^3.0.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.0", - "has": "^1.0.3", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "read-pkg-up": "^2.0.0", - "resolve": "^1.11.0" - }, + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "dev": true, "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" - } + "dev": true }, "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" - } + "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.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } + "dev": true }, "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" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5645,19 +3550,13 @@ "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" - } + "dev": true }, "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.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -5669,19 +3568,13 @@ "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" - } + "dev": true }, "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.0.0" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -5693,22 +3586,13 @@ "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.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "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.0.0", - "read-pkg": "^2.0.0" - } + "dev": true } } }, @@ -5717,12 +3601,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, - "requires": { - "ignore": "^3.3.6", - "minimatch": "^3.0.4", - "resolve": "^1.3.3", - "semver": "5.3.0" - }, "dependencies": { "semver": { "version": "5.3.0", @@ -5752,11 +3630,7 @@ "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, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "dev": true }, "eslint-visitor-keys": { "version": "1.0.0", @@ -5768,11 +3642,7 @@ "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } + "dev": true }, "esprima": { "version": "4.0.1", @@ -5784,19 +3654,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } + "dev": true }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } + "dev": true }, "estraverse": { "version": "4.2.0", @@ -5805,9 +3669,9 @@ "dev": true }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, "etag": { @@ -5820,26 +3684,13 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } + "dev": true }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, - "requires": { - "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" - }, "dependencies": { "map-stream": { "version": "0.1.0", @@ -5865,35 +3716,45 @@ "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.4", - "safe-buffer": "^5.1.1" - } + "dev": true }, "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" - }, "dependencies": { "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" - } + "dev": true + } + } + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true } } }, @@ -5902,42 +3763,24 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "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" - }, "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" - } + "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.0" - } + "dev": true }, "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" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5947,52 +3790,37 @@ } } }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "dependencies": { + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, "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, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "dev": true }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "dev": true, - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "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", - "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.5", - "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": { "cookie": { "version": "0.4.0", @@ -6004,23 +3832,13 @@ "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" - } + "dev": true }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true }, "ms": { "version": "2.0.0", @@ -6045,21 +3863,6 @@ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "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", - "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", @@ -6088,19 +3891,12 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, - "requires": { - "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" - } + "dev": true } } }, @@ -6108,75 +3904,43 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } + "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.0", - "snapdragon": "^0.8.1", - "to-regex": "^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.0" - } + "dev": true }, "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" - } + "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.0" - } + "dev": true }, "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.0" - } + "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.2" - } + "dev": true } } }, @@ -6196,13 +3960,7 @@ "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, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } + "dev": true }, "fast-deep-equal": { "version": "1.1.0", @@ -6226,54 +3984,37 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } + "dev": true }, "fibers": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fibers/-/fibers-3.1.1.tgz", "integrity": "sha512-dl3Ukt08rHVQfY8xGD0ODwyjwrRALtaghuqGH2jByYX1wpY+nAnRQjJ6Dbqq0DnVgNVQ9yibObzbF4IlPyiwPw==", - "dev": true, - "requires": { - "detect-libc": "^1.0.3" - } - }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", "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" - } + "dev": true }, "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, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } + "dev": true + }, + "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 }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, - "requires": { - "glob": "^7.0.3", - "minimatch": "^3.0.3" - } + "dev": true }, "filesize": { "version": "3.6.1", @@ -6286,21 +4027,12 @@ "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" - } + "dev": true } } }, @@ -6309,24 +4041,12 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, - "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" - }, "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" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -6340,46 +4060,25 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } + "dev": true }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "flagged-respawn": { "version": "1.0.1", @@ -6392,9 +4091,6 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, "dependencies": { "is-buffer": { "version": "2.0.3", @@ -6409,21 +4105,12 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", "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" - }, "dependencies": { "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } + "dev": true } } }, @@ -6437,29 +4124,19 @@ "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, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } + "dev": true }, "follow-redirects": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, - "requires": { - "debug": "^3.2.6" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true } } }, @@ -6473,10 +4150,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } + "dev": true }, "foreachasync": { "version": "3.0.0", @@ -6500,21 +4174,7 @@ "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, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "~1.1" - } + "dev": true }, "forwarded": { "version": "0.1.2", @@ -6526,10 +4186,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } + "dev": true }, "fresh": { "version": "0.5.2", @@ -6547,20 +4204,13 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } + "dev": true }, "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, - "requires": { - "null-check": "^1.0.0" - } + "dev": true }, "fs-constants": { "version": "1.0.0", @@ -6573,12 +4223,6 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, - "requires": { - "jsonfile": "~1.0.1", - "mkdirp": "0.3.x", - "ncp": "~0.4.2", - "rimraf": "~2.2.0" - }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -6592,34 +4236,13 @@ "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, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } + "dev": true }, "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, - "requires": { - "fs-extra": "~0.6.1", - "mkdirp": "~0.3.5", - "walk": "^2.3.9" - }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -6641,10 +4264,6 @@ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, "dependencies": { "abbrev": { "version": "1.1.1", @@ -6655,8 +4274,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6668,27 +4286,17 @@ "version": "1.1.5", "bundled": true, "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } + "optional": true }, "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "dev": true }, "chownr": { "version": "1.1.1", @@ -6699,20 +4307,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6724,10 +4329,7 @@ "version": "4.1.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } + "optional": true }, "deep-extend": { "version": "0.6.0", @@ -6751,10 +4353,7 @@ "version": "1.2.5", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } + "optional": true }, "fs.realpath": { "version": "1.0.0", @@ -6766,31 +4365,13 @@ "version": "2.7.4", "bundled": true, "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } + "optional": true }, "glob": { "version": "7.1.3", "bundled": true, "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "optional": true }, "has-unicode": { "version": "2.0.1", @@ -6802,35 +4383,24 @@ "version": "0.4.24", "bundled": true, "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } + "optional": true }, "ignore-walk": { "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } + "optional": true }, "inflight": { "version": "1.0.6", "bundled": true, "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } + "optional": true }, "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6841,11 +4411,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "isarray": { "version": "1.0.0", @@ -6856,45 +4422,28 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } + "dev": true }, "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } + "dev": true }, "minizlib": { "version": "1.2.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } + "optional": true }, "mkdirp": { "version": "0.5.1", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } + "dev": true }, "ms": { "version": "2.1.1", @@ -6906,40 +4455,19 @@ "version": "2.3.0", "bundled": true, "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } + "optional": true }, "node-pre-gyp": { "version": "0.12.0", "bundled": true, "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } + "optional": true }, "nopt": { "version": "4.0.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } + "optional": true }, "npm-bundled": { "version": "1.0.6", @@ -6951,29 +4479,18 @@ "version": "1.4.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } + "optional": true }, "npmlog": { "version": "4.1.2", "bundled": true, "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } + "optional": true }, "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6984,11 +4501,7 @@ "once": { "version": "1.4.0", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } + "dev": true }, "os-homedir": { "version": "1.0.2", @@ -7006,11 +4519,7 @@ "version": "0.1.5", "bundled": true, "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } + "optional": true }, "path-is-absolute": { "version": "1.0.1", @@ -7029,12 +4538,6 @@ "bundled": true, "dev": true, "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, "dependencies": { "minimist": { "version": "1.2.0", @@ -7048,31 +4551,18 @@ "version": "2.3.6", "bundled": true, "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "optional": true }, "rimraf": { "version": "2.6.3", "bundled": true, "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } + "optional": true }, "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7104,34 +4594,21 @@ "dev": true, "optional": true }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "string_decoder": { "version": "1.1.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true }, "strip-ansi": { "version": "3.0.1", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -7143,16 +4620,7 @@ "version": "4.4.8", "bundled": true, "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } + "optional": true }, "util-deprecate": { "version": "1.0.2", @@ -7164,29 +4632,24 @@ "version": "1.1.3", "bundled": true, "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } + "optional": true }, "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, "fun-hooks": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.3.tgz", - "integrity": "sha512-MC/zsGf+duq8lI6xym+H8HuL6DE1fLyE90FRzU/j2lTDmjDJ//+KC7M8vLzG9y/mhkLOH5u9wK4QEf3lBqIo4w==" + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.5.tgz", + "integrity": "sha512-xaj0r9Ex0dvehX8MbQSK/5EYVAddyoaK2sGNuQWX8xNaCiHtr/4zD9J10Y2irkFIsuaxbYOsQBKXvTHzjO2IFQ==" }, "function-bind": { "version": "1.1.1", @@ -7204,10 +4667,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } + "dev": true }, "get-caller-file": { "version": "2.0.5", @@ -7249,39 +4709,25 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } + "dev": true }, "git-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.1.0.tgz", "integrity": "sha512-MJgwfcSd9qxgDyEYpRU/CDxNpUadrK80JHuEQDG4Urn0m7tpSOgCBrtiSIa9S9KH8Tbuo/TN8SSQmJBvsw1HkA==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "parse-url": "^3.0.2" - } + "dev": true }, "git-url-parse": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true, - "requires": { - "git-up": "^2.0.0", - "parse-domain": "^2.0.0" - } + "dev": true }, "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, - "requires": { - "emoji-regex": ">=6.0.0 <=6.1.1" - }, "dependencies": { "emoji-regex": { "version": "6.1.1", @@ -7295,14 +4741,32 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true + }, + "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" + "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 + }, + "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 + } } }, "glob-parent": { @@ -7310,19 +4774,12 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } + "dev": true } } }, @@ -7330,57 +4787,25 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "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" - } + "dev": true }, "glob-watcher": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", - "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", - "object.defaults": "^1.1.0" - } + "dev": true }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } + "dev": true }, "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, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } + "dev": true }, "globals": { "version": "11.12.0", @@ -7398,46 +4823,19 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - } + "dev": true }, "glogg": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } + "dev": true }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", "dev": true, - "requires": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" - }, "dependencies": { "pify": { "version": "3.0.0", @@ -7448,9 +4846,9 @@ } }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.1.tgz", + "integrity": "sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw==", "dev": true }, "grapheme-splitter": { @@ -7470,21 +4868,12 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", "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" - }, "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" - } + "dev": true }, "camelcase": { "version": "3.0.0", @@ -7496,22 +4885,13 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } + "dev": true }, "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" - } + "dev": true }, "get-caller-file": { "version": "1.0.3", @@ -7523,27 +4903,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", - "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.1.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.0.1", - "yargs": "^7.1.0" - } + "dev": true }, "invert-kv": { "version": "1.0.0", @@ -7555,70 +4915,43 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "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" - } + "dev": true }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } + "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -7630,22 +4963,13 @@ "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" - } + "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=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "dev": true }, "require-main-filename": { "version": "1.0.1", @@ -7657,21 +4981,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true }, "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" - } + "dev": true }, "which-module": { "version": "1.0.0", @@ -7689,31 +5005,13 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "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.0" - } + "dev": true }, "yargs-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - } + "dev": true } } }, @@ -7722,11 +5020,6 @@ "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" - }, "dependencies": { "ansi-regex": { "version": "0.2.1", @@ -7744,14 +5037,7 @@ "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" - } + "dev": true }, "clone-stats": { "version": "0.0.1", @@ -7764,26 +5050,12 @@ "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" - } + "dev": true } } }, @@ -7791,10 +5063,7 @@ "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" - } + "dev": true }, "isarray": { "version": "0.0.1", @@ -7818,13 +5087,7 @@ "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" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -7836,10 +5099,7 @@ "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" - } + "dev": true }, "supports-color": { "version": "0.2.0", @@ -7852,19 +5112,12 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, - "requires": { - "readable-stream": "~1.0.17", - "xtend": "~2.1.1" - }, "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" - } + "dev": true } } }, @@ -7872,10 +5125,7 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "~0.0.1" - } + "dev": true }, "xtend": { "version": "3.0.0", @@ -7889,34 +5139,18 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - } + "dev": true }, "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", - "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" - }, + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "dev": true, "dependencies": { "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -7925,24 +5159,11 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", - "dev": true, - "requires": { - "eslint": "^4.0.0", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.0" - } + "dev": true }, "gulp-footer": { "version": "github:prebid/gulp-footer#ff2b46e6376c7f04900357ff9f7b30f219fe5f8a", - "from": "github:prebid/gulp-footer#master", "dev": true, - "requires": { - "event-stream": "3.3.4", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.6.2" - }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -7954,48 +5175,25 @@ "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" - } + "dev": true }, "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.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } + "dev": true }, "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.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" - } + "dev": true }, "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.0.0" - } + "dev": true } } }, @@ -8004,11 +5202,6 @@ "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, - "requires": { - "concat-with-sourcemaps": "*", - "lodash.template": "^4.4.0", - "through2": "^2.0.0" - }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -8017,23 +5210,16 @@ "dev": true }, "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0", - "lodash.templatesettings": "^4.0.0" - } + "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 }, "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0" - } + "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 } } }, @@ -8041,21 +5227,13 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true, - "requires": { - "gulp-match": "^1.0.3", - "ternary-stream": "^2.0.1", - "through2": "^2.0.1" - } + "dev": true }, "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, - "requires": { - "through2": "^0.6.3" - }, "dependencies": { "isarray": { "version": "0.0.1", @@ -8067,13 +5245,7 @@ "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" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -8085,64 +5257,33 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } + "dev": true } } }, "gulp-match": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", - "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true, - "requires": { - "minimatch": "^3.0.3" - } + "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 }, "gulp-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", - "dev": true, - "requires": { - "istextorbinary": "2.2.1", - "readable-stream": "^2.0.1", - "replacestream": "^4.0.0" - } + "dev": true }, "gulp-shell": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true, - "requires": { - "async": "^1.5.0", - "gulp-util": "^3.0.7", - "lodash": "^4.0.0", - "through2": "^2.0.0" - } + "dev": true }, "gulp-sourcemaps": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.5.tgz", "integrity": "sha512-SYLBRzPTew8T5Suh2U8jCSDKY+4NARua4aqjj8HOysBh2tSgT9u4jc1FYirAdPx1akUxxDeK++fqw6Jg0LkQRg==", "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "1.X", - "@gulp-sourcemaps/map-sources": "1.X", - "acorn": "5.X", - "convert-source-map": "1.X", - "css": "2.X", - "debug-fabulous": "1.X", - "detect-newline": "2.X", - "graceful-fs": "4.X", - "source-map": "~0.6.0", - "strip-bom-string": "1.X", - "through2": "2.X" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -8156,45 +5297,13 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "extend-shallow": "^3.0.2", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "isobject": "^3.0.1", - "make-error-cause": "^1.1.1", - "safe-buffer": "^5.1.2", - "through2": "^2.0.0", - "uglify-js": "^3.0.5", - "vinyl-sourcemaps-apply": "^0.2.0" - } + "dev": true }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "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", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -8206,14 +5315,7 @@ "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" - } + "dev": true }, "clone": { "version": "1.0.4", @@ -8243,48 +5345,25 @@ "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" - } + "dev": true }, "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.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } + "dev": true }, "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.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" - } + "dev": true }, "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.0.0" - } + "dev": true }, "object-assign": { "version": "3.0.0", @@ -8308,12 +5387,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } + "dev": true } } }, @@ -8321,32 +5395,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } + "dev": true }, "gzip-size": { "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.1", - "pify": "^4.0.1" - } + "dev": true }, "handlebars": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, - "requires": { - "neo-async": "^2.6.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -8367,22 +5428,12 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - }, "dependencies": { "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true }, "fast-deep-equal": { "version": "2.0.1", @@ -8402,28 +5453,19 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } + "dev": true }, "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, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, - "requires": { - "isarray": "2.0.1" - }, "dependencies": { "isarray": { "version": "2.0.1", @@ -8449,10 +5491,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } + "dev": true }, "has-symbol-support-x": { "version": "1.4.2", @@ -8470,40 +5509,25 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "requires": { - "has-symbol-support-x": "^1.4.1" - } + "dev": true }, "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" - } + "dev": true }, "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, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -8511,21 +5535,13 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "dev": 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" - } + "dev": true }, "hast-util-is-element": { "version": "1.0.3", @@ -8537,29 +5553,13 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.1.tgz", "integrity": "sha512-AIeKHuHx0Wk45nSkGVa2/ujQYTksnDl8gmmKo/mwQi7ag7IBZ8cM3nJ2G86SajbjGP/HRpud6kMkPtcM2i0Tlw==", - "dev": true, - "requires": { - "xtend": "^4.0.1" - } + "dev": true }, "hast-util-to-html": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", "dev": true, - "requires": { - "ccount": "^1.0.0", - "comma-separated-tokens": "^1.0.1", - "hast-util-is-element": "^1.0.0", - "hast-util-whitespace": "^1.0.0", - "html-void-elements": "^1.0.0", - "kebab-case": "^1.0.0", - "property-information": "^3.1.0", - "space-separated-tokens": "^1.0.0", - "stringify-entities": "^1.0.1", - "unist-util-is": "^2.0.0", - "xtend": "^4.0.1" - }, "dependencies": { "unist-util-is": { "version": "2.1.3", @@ -8582,40 +5582,28 @@ "dev": true }, "highlight.js": { - "version": "9.15.8", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz", - "integrity": "sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA==", + "version": "9.15.9", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.9.tgz", + "integrity": "sha512-M0zZvfLr5p0keDMCAhNBp03XJbKBxUx5AfyfufMdFMEP4N/Xj6dh0IqC75ys7BAzceR34NgcvXjupRVaHBPPVQ==", "dev": true }, "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": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } + "dev": true }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } + "dev": true }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } + "dev": true }, "hoopy": { "version": "0.1.4", @@ -8624,9 +5612,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.2.tgz", + "integrity": "sha512-CyjlXII6LMsPMyUzxpTt8fzh5QwzGqPmQXgY/Jyf4Zfp27t/FvfhwoE/8laaMUcMy816CkWF20I7NeQhwwY88w==", "dev": true }, "html-void-elements": { @@ -8643,14 +5631,16 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "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" + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "http-parser-js": { @@ -8663,23 +5653,13 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } + "dev": true }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } + "dev": true }, "https-browserify": { "version": "1.0.0", @@ -8688,23 +5668,16 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", + "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true } } }, @@ -8718,10 +5691,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } + "dev": true }, "ieee754": { "version": "1.1.13", @@ -8729,12 +5699,6 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -8751,10 +5715,7 @@ "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" - } + "dev": true }, "indexof": { "version": "0.0.1", @@ -8766,16 +5727,12 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } + "dev": true }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "ini": { @@ -8789,22 +5746,6 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "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", - "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" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -8816,10 +5757,7 @@ "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" - } + "dev": true } } }, @@ -8833,20 +5771,13 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, - "requires": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" - } + "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" - } + "dev": true }, "invert-kv": { "version": "2.0.0", @@ -8864,29 +5795,19 @@ "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, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } + "dev": true }, "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" - } + "dev": true } } }, @@ -8906,16 +5827,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", - "dev": true, - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, "is-arrayish": { @@ -8928,10 +5839,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } + "dev": true }, "is-buffer": { "version": "1.1.6", @@ -8950,18 +5858,12 @@ "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" - } + "dev": true } } }, @@ -8982,11 +5884,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", @@ -9002,6 +5899,18 @@ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", "dev": true }, + "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 + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -9018,10 +5927,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -9029,20 +5935,11 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", - "dev": true - }, "is-glob": { "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" - } + "dev": true }, "is-hexadecimal": { "version": "1.0.3", @@ -9061,18 +5958,12 @@ "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": { "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" - } + "dev": true } } }, @@ -9092,10 +5983,19 @@ "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" - } + "dev": true + }, + "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": { "version": "2.1.0", @@ -9107,19 +6007,13 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } + "dev": true }, "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, - "requires": { - "is-unc-path": "^1.0.0" - } + "dev": true }, "is-resolvable": { "version": "1.1.0", @@ -9143,10 +6037,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", - "dev": true, - "requires": { - "protocols": "^1.1.0" - } + "dev": true }, "is-stream": { "version": "1.1.0", @@ -9158,10 +6049,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.0" - } + "dev": true }, "is-typedarray": { "version": "1.0.0", @@ -9173,10 +6061,7 @@ "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, - "requires": { - "unc-path-regex": "^0.1.2" - } + "dev": true }, "is-utf8": { "version": "0.2.1", @@ -9224,10 +6109,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } + "dev": true }, "isexe": { "version": "2.0.0", @@ -9252,22 +6134,6 @@ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, "dependencies": { "esprima": { "version": "2.7.3", @@ -9279,14 +6145,7 @@ "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" - } + "dev": true }, "has-flag": { "version": "1.0.0", @@ -9304,10 +6163,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } + "dev": true } } }, @@ -9316,28 +6172,12 @@ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", "dev": true, - "requires": { - "async": "^2.1.4", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.1", - "istanbul-lib-hook": "^1.2.2", - "istanbul-lib-instrument": "^1.10.2", - "istanbul-lib-report": "^1.1.5", - "istanbul-lib-source-maps": "^1.2.6", - "istanbul-reports": "^1.5.1", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" - }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true } } }, @@ -9345,13 +6185,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true, - "requires": { - "convert-source-map": "^1.5.0", - "istanbul-lib-instrument": "^1.7.3", - "loader-utils": "^1.1.0", - "schema-utils": "^0.3.0" - } + "dev": true }, "istanbul-lib-coverage": { "version": "1.2.1", @@ -9363,37 +6197,19 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", - "dev": true, - "requires": { - "append-transform": "^0.4.0" - } + "dev": true }, "istanbul-lib-instrument": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } + "dev": true }, "istanbul-lib-report": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", "dev": true, - "requires": { - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" - }, "dependencies": { "has-flag": { "version": "1.0.0", @@ -9405,10 +6221,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } + "dev": true } } }, @@ -9417,31 +6230,18 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", "dev": true, - "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } + "dev": true } } }, @@ -9449,31 +6249,19 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", - "dev": true, - "requires": { - "handlebars": "^4.0.3" - } + "dev": true }, "istextorbinary": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "dev": true, - "requires": { - "binaryextensions": "2", - "editions": "^1.3.3", - "textextensions": "2" - } + "dev": true }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - } + "dev": true }, "js-levenshtein": { "version": "1.1.6", @@ -9491,11 +6279,7 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } + "dev": true }, "jsbn": { "version": "0.1.1", @@ -9560,10 +6344,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } + "dev": true }, "jsonfile": { "version": "1.0.1", @@ -9583,17 +6364,17 @@ "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 + }, "jsprim": { "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.2.3", - "verror": "1.10.0" - } + "dev": true }, "just-clone": { "version": "1.0.2", @@ -9613,165 +6394,28 @@ "dev": true }, "karma": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.2.0.tgz", - "integrity": "sha512-fmCuxN1rwJxTdZfOXK5LjlmS4Ana/OvzNMpkyLL/TLE8hmgSkpVpMYQ7RTVa8TNKRVQDZNl5W1oF5cfKfgIMlA==", - "dev": true, - "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "braces": "^3.0.2", - "chokidar": "^3.0.0", - "colors": "^1.1.0", - "connect": "^3.6.0", - "core-js": "^3.1.3", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "flatted": "^2.0.0", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.11", - "log4js": "^4.0.0", - "mime": "^2.3.1", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.1.1", - "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.3.0" - }, + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "dev": true, "dependencies": { - "anymatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.0.3.tgz", - "integrity": "sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz", - "integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==", - "dev": true, - "requires": { - "anymatch": "^3.0.1", - "braces": "^3.0.2", - "fsevents": "^2.0.6", - "glob-parent": "^5.0.0", - "is-binary-path": "^2.1.0", - "is-glob": "^4.0.1", - "normalize-path": "^3.0.0", - "readdirp": "^3.1.1" - } - }, - "core-js": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", - "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", - "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" - } - }, - "fsevents": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", - "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", - "dev": true, - "optional": true - }, - "glob-parent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", - "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "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, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "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 - }, "mime": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, - "readdirp": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.1.tgz", - "integrity": "sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ==", - "dev": true, - "requires": { - "picomatch": "^2.0.4" - } - }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } + "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 - }, - "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" - } } } }, @@ -9779,21 +6423,13 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true, - "requires": { - "babel-core": "^6.0.0" - } + "dev": true }, "karma-browserstack-launcher": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.5.1.tgz", "integrity": "sha512-zt9Ukow5A9WZHZXCFVO/h5kRsAdaZYeMNJK9Uan8v42amQXt3B/DZVxl24NCcAIxufKjW13UWd9iJ9knG9OCYw==", - "dev": true, - "requires": { - "browserstack": "~1.5.1", - "browserstack-local": "^1.3.7", - "q": "~1.5.0" - } + "dev": true }, "karma-chai": { "version": "0.1.0", @@ -9805,30 +6441,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true, - "requires": { - "fs-access": "^1.0.0", - "which": "^1.2.1" - } + "dev": true }, "karma-coverage-istanbul-reporter": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", - "dev": true, - "requires": { - "istanbul-api": "^1.3.1", - "minimatch": "^3.0.4" - } + "dev": true }, "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, - "requires": { - "es5-shim": "^4.0.5" - } + "dev": true }, "karma-firefox-launcher": { "version": "1.1.0", @@ -9840,30 +6465,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true, - "requires": { - "lodash": "^4.6.1" - } + "dev": true }, "karma-mocha": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true, - "requires": { - "minimist": "1.2.0" - } + "dev": true }, "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, - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "strip-ansi": "^4.0.0" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -9875,10 +6489,7 @@ "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" - } + "dev": true } } }, @@ -9910,42 +6521,25 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - } + "dev": true }, "karma-spec-reporter": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true, - "requires": { - "colors": "^1.1.2" - } + "dev": true }, "karma-webpack": { "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": { - "async": "^2.0.0", - "babel-runtime": "^6.0.0", - "loader-utils": "^1.0.0", - "lodash": "^4.0.0", - "source-map": "^0.5.6", - "webpack-dev-middleware": "^2.0.6" - }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true } } }, @@ -9959,10 +6553,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } + "dev": true }, "kind-of": { "version": "6.0.2", @@ -9974,11 +6565,7 @@ "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" - } + "dev": true }, "lazy-cache": { "version": "1.0.4", @@ -9990,19 +6577,13 @@ "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" - } + "dev": true }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } + "dev": true }, "lcov-parse": { "version": "0.0.10", @@ -10014,36 +6595,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } + "dev": true }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } + "dev": true }, "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", "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" - } + "dev": true }, "livereload-js": { "version": "2.4.0", @@ -10056,12 +6620,6 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "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", @@ -10082,20 +6640,12 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.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.0" - } + "dev": true } } }, @@ -10103,11 +6653,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } + "dev": true }, "lodash": { "version": "4.17.15", @@ -10137,10 +6683,7 @@ "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, - "requires": { - "lodash._htmlescapes": "~2.4.1" - } + "dev": true }, "lodash._escapestringchar": { "version": "2.4.1", @@ -10200,11 +6743,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "requires": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" - } + "dev": true }, "lodash._root": { "version": "3.0.1", @@ -10216,10 +6755,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1" - } + "dev": true }, "lodash.clone": { "version": "4.5.0", @@ -10231,22 +6767,13 @@ "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" - } + "dev": true }, "lodash.escape": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" - } + "dev": true }, "lodash.get": { "version": "4.4.2", @@ -10270,21 +6797,13 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1" - } + "dev": true }, "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, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } + "dev": true }, "lodash.restparam": { "version": "3.6.1", @@ -10302,35 +6821,19 @@ "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" - } + "dev": true }, "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" - } + "dev": true }, "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, - "requires": { - "lodash.keys": "~2.4.1" - } + "dev": true }, "log-driver": { "version": "1.2.7", @@ -10342,38 +6845,38 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } + "dev": true }, "log4js": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", - "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, - "requires": { - "date-format": "^2.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.0", - "rfdc": "^1.1.4", - "streamroller": "^1.0.6" + "dependencies": { + "circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "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.1", - "object.assign": "^4.1.0" - } + "dev": true }, "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", "dev": true }, "longest": { @@ -10392,20 +6895,13 @@ "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" - } + "dev": true }, "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" - } + "dev": true }, "lowercase-keys": { "version": "1.0.1", @@ -10414,33 +6910,22 @@ "dev": true }, "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" - } + "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 }, "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } + "dev": true }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } + "dev": true }, "make-error": { "version": "1.3.5", @@ -10452,34 +6937,19 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "^1.2.0" - } + "dev": true }, "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, - "requires": { - "kind-of": "^6.0.2" - } - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", "dev": true }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } + "dev": true }, "map-cache": { "version": "0.2.2", @@ -10503,10 +6973,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } + "dev": true }, "markdown-escapes": { "version": "1.0.3", @@ -10525,92 +6992,56 @@ "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, "dependencies": { "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" - } + "dev": true }, "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } + "dev": true } } }, + "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.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "dev": true }, "mdast-util-compact": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz", "integrity": "sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } + "dev": true }, "mdast-util-definitions": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.4.tgz", "integrity": "sha512-HfUArPog1j4Z78Xlzy9Q4aHLnrF/7fb57cooTHypyGoe2XFNbcx/kWZDoOz+ra8CkUzvg3+VHV434yqEd1DRmA==", - "dev": true, - "requires": { - "unist-util-visit": "^1.0.0" - } + "dev": true }, "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, - "requires": { - "mdast-util-to-string": "^1.0.0" - } + "dev": true }, "mdast-util-to-hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.4.tgz", "integrity": "sha512-/eIbly2YmyVgpJNo+bFLLMCI1XgolO/Ffowhf+pHDq3X4/V6FntC9sGQCDLM147eTS+uSXv5dRzJyFn+o0tazA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.0", - "detab": "^2.0.0", - "mdast-util-definitions": "^1.2.0", - "mdurl": "^1.0.1", - "trim": "0.0.1", - "trim-lines": "^1.0.0", - "unist-builder": "^1.0.1", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.0", - "xtend": "^4.0.1" - } + "dev": true }, "mdast-util-to-string": { "version": "1.0.6", @@ -10623,12 +7054,6 @@ "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-3.1.0.tgz", "integrity": "sha512-Za0hqL1PqWrvxGtA/3NH9D5nhGAUS9grMM4obEAz5+zsk1RIw/vWUchkaoDLNdrwk05A0CSC5eEXng36/1qE5w==", "dev": true, - "requires": { - "github-slugger": "^1.2.1", - "mdast-util-to-string": "^1.0.5", - "unist-util-is": "^2.1.2", - "unist-util-visit": "^1.1.0" - }, "dependencies": { "emoji-regex": { "version": "6.1.1", @@ -10640,10 +7065,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.1.tgz", "integrity": "sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ==", - "dev": true, - "requires": { - "emoji-regex": ">=6.0.0 <=6.1.1" - } + "dev": true }, "unist-util-is": { "version": "2.1.3", @@ -10670,11 +7092,6 @@ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, "dependencies": { "p-is-promise": { "version": "2.1.0", @@ -10688,27 +7105,13 @@ "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } + "dev": true }, "memory-fs": { "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" - } + "dev": true }, "memorystream": { "version": "0.3.1", @@ -10721,70 +7124,36 @@ "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": { "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" - } + "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" - } + "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" - } + "dev": true }, "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" - } + "dev": true }, "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" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -10796,31 +7165,19 @@ "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" - } + "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=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "dev": true }, "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" - } + "dev": true } } }, @@ -10834,10 +7191,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } + "dev": true }, "methods": { "version": "1.1.2", @@ -10849,32 +7203,13 @@ "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" - } + "dev": true }, "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.0.0", - "brorand": "^1.0.1" - } + "dev": true }, "mime": { "version": "1.6.0", @@ -10892,10 +7227,7 @@ "version": "2.1.24", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true, - "requires": { - "mime-db": "1.40.0" - } + "dev": true }, "mimic-fn": { "version": "2.1.0", @@ -10925,53 +7257,25 @@ "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" - } + "dev": true }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, "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, - "requires": { - "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" - } + "dev": true } } }, @@ -10980,13 +7284,10 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, - "requires": { - "minimist": "0.0.8" - }, "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10997,19 +7298,6 @@ "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, "dependencies": { "commander": { "version": "2.15.1", @@ -11021,10 +7309,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "diff": { "version": "3.5.0", @@ -11036,15 +7321,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "dev": true }, "he": { "version": "1.1.1", @@ -11062,10 +7339,7 @@ "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" - } + "dev": true } } }, @@ -11074,47 +7348,18 @@ "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "browser-resolve": "^1.7.0", - "concat-stream": "~1.5.0", - "defined": "^1.0.0", - "detective": "^4.0.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.3", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, "dependencies": { "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~2.0.0", - "typedarray": "~0.0.5" - }, "dependencies": { "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "~1.0.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" - } + "dev": true } } }, @@ -11132,31 +7377,6 @@ } } }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11168,18 +7388,12 @@ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, - "requires": { - "duplexer2": "0.0.2" - }, "dependencies": { "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - } + "dev": true }, "isarray": { "version": "0.0.1", @@ -11191,13 +7405,7 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -11230,20 +7438,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "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" - } + "dev": true }, "natural-compare": { "version": "1.4.0", @@ -11282,32 +7477,21 @@ "dev": true }, "nise": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz", - "integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.1.tgz", + "integrity": "sha512-edFWm0fsFG2n318rfEnKlTZTkjlbVOFF9XIA+fj+Ed+Qz1laYW2lobwavWoMzGrYDHH1EpiNJgDfvGnkZztR/g==", "dev": true, - "requires": { - "@sinonjs/formatio": "^3.1.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^4.1.0", - "path-to-regexp": "^1.7.0" - }, "dependencies": { "@sinonjs/formatio": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } + "dev": true }, "lolex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz", - "integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", "dev": true } } @@ -11316,100 +7500,45 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } + "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.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, "dependencies": { "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } + "dev": true }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } } } }, "node-releases": { - "version": "1.1.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", - "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } + "version": "1.1.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", + "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", + "dev": true }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } + "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.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } + "dev": true }, "normalize-path": { "version": "3.0.0", @@ -11421,22 +7550,13 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } + "dev": true }, "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, - "requires": { - "once": "^1.3.2" - } + "dev": true }, "npm-install-package": { "version": "2.1.0", @@ -11448,27 +7568,13 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - } + "dev": true }, "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, - "requires": { - "path-key": "^2.0.0" - } + "dev": true }, "null-check": { "version": "1.0.0", @@ -11505,29 +7611,18 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, "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" - } + "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" - } + "dev": true } } }, @@ -11541,112 +7636,81 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } + "dev": true }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } + "dev": true }, "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, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } + "dev": true }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } + "dev": true }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true + }, + "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": "^1.0.0", - "make-iterator": "^1.0.0" + "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 + } } }, "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, - "requires": { - "isobject": "^3.0.1" - } + "dev": true }, "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, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "dev": true + }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } + "dev": true }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } + "dev": true }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - }, "dependencies": { "mimic-fn": { "version": "1.2.0", @@ -11666,24 +7730,17 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } + "dev": true }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11699,24 +7756,13 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } + "dev": true }, "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, - "requires": { - "readable-stream": "^2.0.1" - } + "dev": true }, "os-browserify": { "version": "0.3.0", @@ -11734,12 +7780,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } + "dev": true }, "os-tmpdir": { "version": "1.0.2", @@ -11775,28 +7816,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } + "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.0.0" - } + "dev": true }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } + "dev": true }, "p-try": { "version": "2.2.0", @@ -11810,52 +7842,23 @@ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true, - "requires": { - "path-platform": "~0.11.15" - } + "dev": true }, "parse-asn1": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", - "dev": true, - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } + "dev": true }, "parse-domain": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.1.tgz", "integrity": "sha512-k/tkc7tfcoGfaUOCG5DuPNX+dt6UBqRWU9EtR0rA9esi5GpOY0OGEgprfylmYx8pykQbdBTYHLaM/UwFHXuZKA==", "dev": true, - "requires": { - "chai": "^4.2.0", - "got": "^8.3.2", - "mkdirp": "^0.5.1", - "mocha": "^6.1.4", - "npm-run-all": "^4.1.5" - }, "dependencies": { "ansi-regex": { "version": "4.1.0", @@ -11867,10 +7870,7 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true }, "diff": { "version": "3.5.0", @@ -11882,46 +7882,13 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "dev": true }, "mocha": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", - "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" - } + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", + "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "dev": true }, "ms": { "version": "2.1.1", @@ -11933,49 +7900,25 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } + "dev": true }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } + "dev": true }, "supports-color": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "dev": true }, "yargs": { "version": "13.2.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - } + "dev": true } } }, @@ -11983,45 +7926,45 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "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" - } + "dev": true }, "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, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } + "dev": true }, "parse-git-config": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", + "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": { - "ini": "^1.3.3" + "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 + } } }, "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.1", - "json-parse-better-errors": "^1.0.1" - } + "dev": true }, "parse-node-version": { "version": "1.0.1", @@ -12039,41 +7982,25 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-3.0.4.tgz", "integrity": "sha512-wP70vtwv2DyrM2YoA7ZHVv4zIXa4P7dGgHlj+VwyXNDduLLVJ7NMY1zsFxjUUJ3DAwJLupGb1H5gMDDiNlJaxw==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "protocols": "^1.4.0" - } + "dev": true }, "parse-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-3.0.2.tgz", "integrity": "sha1-YCeHpwY6eV1yuGcxl1BecvYGEL4=", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "normalize-url": "^1.9.1", - "parse-path": "^3.0.1", - "protocols": "^1.4.0" - } + "dev": true }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "dev": true }, "parseuri": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "dev": true }, "parseurl": { "version": "1.3.3", @@ -12139,10 +8066,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } + "dev": true }, "path-root-regex": { "version": "0.1.2", @@ -12155,9 +8079,6 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, - "requires": { - "isarray": "0.0.1" - }, "dependencies": { "isarray": { "version": "0.0.1", @@ -12172,9 +8093,6 @@ "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", @@ -12194,23 +8112,19 @@ "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "~2.3" - } + "dev": true }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } + "dev": true + }, + "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 }, "performance-now": { "version": "2.1.0", @@ -12218,12 +8132,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "picomatch": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", - "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", - "dev": true - }, "pidtree": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", @@ -12246,40 +8154,25 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } + "dev": true }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } + "dev": true }, "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, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.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" - } + "dev": true } } }, @@ -12307,6 +8200,12 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12326,9 +8225,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "progress": { @@ -12337,12 +8236,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12359,11 +8252,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - } + "dev": true }, "prr": { "version": "1.0.1", @@ -12375,10 +8264,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.1.tgz", "integrity": "sha512-kef7fYYSKVqQffmzTMsVcUD1ObNJMp8sNSmHGlGKsZQyL/ht9MZKk86u0Rd1NhpTOAuhqwKCLLpktwkqz+MF8A==", - "dev": true, - "requires": { - "event-stream": "=3.3.4" - } + "dev": true }, "pseudomap": { "version": "1.0.2", @@ -12387,55 +8273,34 @@ "dev": true }, "psl": { - "version": "1.1.32", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", - "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz", + "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==", "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.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "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" - } + "dev": true }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, "dependencies": { "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" - } + "dev": true } } }, @@ -12467,11 +8332,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } + "dev": true }, "querystring": { "version": "0.2.0", @@ -12491,24 +8352,31 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "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, + "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.0" - } + "dev": true }, "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.0.5", - "safe-buffer": "^5.1.0" - } + "dev": true }, "range-parser": { "version": "1.2.1", @@ -12521,10 +8389,6 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, - "requires": { - "bytes": "1", - "string_decoder": "0.10" - }, "dependencies": { "string_decoder": { "version": "0.10.31", @@ -12538,59 +8402,37 @@ "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.3.2", - "path-type": "^3.0.0" - } + "dev": true }, "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": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, "dependencies": { "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" - } + "dev": true }, "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" - } + "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" - } + "dev": true }, "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.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -12604,46 +8446,25 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "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" - } + "dev": true }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } + "dev": true }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } + "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" - } + "dev": true }, "regenerate": { "version": "1.4.0", @@ -12655,10 +8476,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } + "dev": true }, "regenerator-runtime": { "version": "0.11.1", @@ -12666,28 +8484,27 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", - "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", - "dev": true, - "requires": { - "private": "^0.1.6" - } + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true }, "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" - } + "dev": true }, "regexp-tree": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", - "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", + "integrity": "sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg==", "dev": true }, "regexpp": { @@ -12700,15 +8517,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } + "dev": true }, "regjsgen": { "version": "0.5.0", @@ -12721,9 +8530,6 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -12737,129 +8543,61 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true, - "requires": { - "remark-parse": "^5.0.0", - "remark-stringify": "^5.0.0", - "unified": "^6.0.0" - } + "dev": true }, "remark-html": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true, - "requires": { - "hast-util-sanitize": "^1.0.0", - "hast-util-to-html": "^3.0.0", - "mdast-util-to-hast": "^3.0.0", - "xtend": "^4.0.1" - } + "dev": true }, "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } + "dev": true }, "remark-reference-links": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.4.tgz", "integrity": "sha512-+2X8hwSQqxG4tvjYZNrTcEC+bXp8shQvwRGG6J/rnFTvBoU4G0BBviZoqKGZizLh/DG+0gSYhiDDWCqyxXW1iQ==", - "dev": true, - "requires": { - "unist-util-visit": "^1.0.0" - } + "dev": true }, "remark-slug": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.2.tgz", "integrity": "sha512-DWX+Kd9iKycqyD+/B+gEFO3jjnt7Yg1O05lygYSNTe5i5PIxxxPjp5qPBDxPIzp5wreF7+1ROCwRgjEcqmzr3A==", - "dev": true, - "requires": { - "github-slugger": "^1.0.0", - "mdast-util-to-string": "^1.0.0", - "unist-util-visit": "^1.0.0" - } + "dev": true }, "remark-stringify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "is-alphanumeric": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "longest-streak": "^2.0.1", - "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4", - "xtend": "^4.0.1" - } + "dev": true }, "remark-toc": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.1.1.tgz", "integrity": "sha512-vCPW4YOsm2CfyuScdktM9KDnJXVHJsd/ZeRtst+dnBU3B3KKvt8bc+bs5syJjyptAHfqo7H+5Uhz+2blWBfwow==", - "dev": true, - "requires": { - "mdast-util-toc": "^3.0.0", - "remark-slug": "^5.0.0" - } + "dev": true }, "remote-origin-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true, - "requires": { - "parse-git-config": "^0.2.0" - } + "dev": true }, "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, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } + "dev": true }, "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": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } + "dev": true }, "remove-trailing-separator": { "version": "1.1.0", @@ -12883,10 +8621,7 @@ "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" - } + "dev": true }, "replace-ext": { "version": "1.0.0", @@ -12898,72 +8633,31 @@ "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": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } + "dev": true }, "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": { - "escape-string-regexp": "^1.0.3", - "object-assign": "^4.0.1", - "readable-stream": "^2.0.2" - } + "dev": true }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } + "dev": true }, "request-promise": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", - "dev": true, - "requires": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } + "dev": true }, "request-promise-core": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "dev": true }, "require-directory": { "version": "2.1.1", @@ -12982,10 +8676,6 @@ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - }, "dependencies": { "resolve-from": { "version": "1.0.1", @@ -13002,23 +8692,16 @@ "dev": true }, "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "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": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } + "dev": true }, "resolve-from": { "version": "5.0.0", @@ -13030,10 +8713,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } + "dev": true }, "resolve-url": { "version": "0.2.1", @@ -13045,20 +8725,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } + "dev": true }, "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, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } + "dev": true }, "ret": { "version": "0.1.15", @@ -13082,10 +8755,7 @@ "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": { - "align-text": "^0.1.1" - } + "dev": true }, "rimraf": { "version": "2.2.8", @@ -13097,29 +8767,13 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } + "dev": true }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } + "dev": true }, "rx-lite": { "version": "4.0.8", @@ -13131,10 +8785,7 @@ "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": { - "rx-lite": "*" - } + "dev": true }, "safe-buffer": { "version": "5.1.2", @@ -13152,10 +8803,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -13164,19 +8812,16 @@ "dev": true }, "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "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": "0.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true, - "requires": { - "ajv": "^5.0.0" - } + "dev": true }, "semver": { "version": "5.7.0", @@ -13188,40 +8833,19 @@ "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": { - "sver-compat": "^1.5.0" - } + "dev": true }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "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", - "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" - }, "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" - } + "dev": true }, "mime": { "version": "1.4.1", @@ -13243,35 +8867,17 @@ } } }, - "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", - "dev": true - }, "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": { - "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" - }, "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" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -13286,21 +8892,12 @@ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.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" - }, "dependencies": { "ms": { "version": "2.0.0", @@ -13311,17 +8908,10 @@ } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true }, "ms": { "version": "2.1.1", @@ -13333,22 +8923,7 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "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", - "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" - } + "dev": true }, "setprototypeof": { "version": "1.1.1", @@ -13369,21 +8944,12 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "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" - } + "dev": true } } }, @@ -13403,20 +8969,13 @@ "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": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "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" - } + "dev": true }, "shebang-regex": { "version": "1.0.0", @@ -13428,24 +8987,13 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" - } + "dev": true }, "shelljs": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } + "dev": true }, "signal-exit": { "version": "3.0.2", @@ -13458,27 +9006,12 @@ "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "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" - }, "dependencies": { "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true - }, - "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true } } }, @@ -13492,53 +9025,31 @@ "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, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } + "dev": true }, "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": { - "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" - }, "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" - } + "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.0" - } + "dev": true }, "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" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -13553,49 +9064,30 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "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.0" - } + "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.0" - } + "dev": true }, "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.0" - } + "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.2" - } + "dev": true } } }, @@ -13604,43 +9096,26 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, "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" - } + "dev": true } } }, "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, - "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" - }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "ms": { "version": "2.0.0", @@ -13659,24 +9134,8 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - }, + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -13687,11 +9146,8 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "ms": { "version": "2.0.0", @@ -13703,14 +9159,9 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -13721,11 +9172,8 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "isarray": { "version": "2.0.1", @@ -13745,10 +9193,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } + "dev": true }, "source-list-map": { "version": "2.0.1", @@ -13766,23 +9211,13 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } + "dev": true }, "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" - } + "dev": true }, "source-map-url": { "version": "0.4.0", @@ -13806,11 +9241,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } + "dev": true }, "spdx-exceptions": { "version": "2.2.0", @@ -13822,35 +9253,25 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } + "dev": true }, "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2" - } + "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": { - "extend-shallow": "^3.0.0" - } + "dev": true }, "sprintf-js": { "version": "1.0.3", @@ -13862,27 +9283,7 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "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" - } - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } + "dev": true }, "stack-trace": { "version": "0.0.10", @@ -13901,19 +9302,12 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.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" - } + "dev": true } } }, @@ -13934,9 +9328,6 @@ "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", "dev": true, - "requires": { - "readable-stream": "~2.1.0" - }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -13948,16 +9339,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "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" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -13971,40 +9353,19 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } + "dev": true }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } + "dev": true }, "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" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } + "dev": true }, "stream-exhaust": { "version": "1.0.2", @@ -14016,14 +9377,7 @@ "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": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } + "dev": true }, "stream-shift": { "version": "1.0.0", @@ -14032,55 +9386,16 @@ "dev": true }, "streamroller": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", - "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, - "requires": { - "async": "^2.6.2", - "date-format": "^2.0.0", - "debug": "^3.2.6", - "fs-extra": "^7.0.1", - "lodash": "^4.17.14" - }, "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.14" - } - }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } + "dev": true } } }, @@ -14090,6 +9405,12 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "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 + }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", @@ -14101,10 +9422,6 @@ "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" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -14116,10 +9433,7 @@ "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" - } + "dev": true } } }, @@ -14127,42 +9441,19 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.4.3", - "function-bind": "^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.0" - } + "dev": true }, "stringify-entities": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, - "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } + "dev": true }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "strip-bom": { "version": "3.0.0", @@ -14186,10 +9477,7 @@ "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" - } + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -14201,43 +9489,25 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "requires": { - "minimist": "^1.1.0" - } + "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" - } + "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=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } + "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", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - } + "dev": true }, "tapable": { "version": "0.2.9", @@ -14249,144 +9519,27 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - } + "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=", "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" - } - } - } - }, - "ternary-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", - "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true, - "requires": { - "duplexify": "^3.5.0", - "fork-stream": "^0.0.4", - "merge-stream": "^1.0.0", - "through2": "^2.0.1" - } - }, - "terser": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.2.tgz", - "integrity": "sha512-jvNoEQSPXJdssFwqPSgWjsOrb+ELoE+ILpHPKXC83tIxOlh2U75F1KuB2luLD/3a6/7K3Vw5pDn+hvu0C4AzSw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "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 - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } } } }, - "terser-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", - "dev": true, - "requires": { - "cacache": "^11.3.2", - "find-cache-dir": "^2.0.0", - "is-wsl": "^1.1.0", - "loader-utils": "^1.2.3", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", - "source-map": "^0.6.1", - "terser": "^4.0.0", - "webpack-sources": "^1.3.0", - "worker-farm": "^1.7.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "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 - } - } + "ternary-stream": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", + "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", + "dev": true }, "text-table": { "version": "0.2.0", @@ -14395,9 +9548,9 @@ "dev": true }, "textextensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz", - "integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.5.0.tgz", + "integrity": "sha512-1IkVr355eHcomgK7fgj1Xsokturx6L5S2JRT5WcRdA6v5shk9sxWuO/w/VbpQexwkXJMQIa/j1dBi3oo7+HhcA==", "dev": true }, "through": { @@ -14410,21 +9563,13 @@ "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" - } + "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==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } + "dev": true }, "time-stamp": { "version": "1.1.0", @@ -14442,43 +9587,25 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } + "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==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } + "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==", "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" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true } } }, @@ -14486,20 +9613,13 @@ "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" - } + "dev": true }, "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" - } + "dev": true }, "to-array": { "version": "0.1.4", @@ -14530,18 +9650,12 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "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" - } + "dev": true } } }, @@ -14549,32 +9663,19 @@ "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" - } + "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" - } + "dev": true }, "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": { - "through2": "^2.0.3" - } + "dev": true }, "toidentifier": { "version": "1.0.0", @@ -14587,10 +9688,6 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, "dependencies": { "punycode": { "version": "1.4.1", @@ -14642,12 +9739,6 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14658,10 +9749,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } + "dev": true }, "tweetnacl": { "version": "0.14.5", @@ -14670,19 +9758,16 @@ "dev": true }, "type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/type/-/type-1.0.1.tgz", - "integrity": "sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/type/-/type-1.0.3.tgz", + "integrity": "sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg==", "dev": true }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } + "dev": true }, "type-detect": { "version": "4.0.8", @@ -14694,11 +9779,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } + "dev": true }, "typedarray": { "version": "0.0.6", @@ -14711,10 +9792,6 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", "dev": true, - "requires": { - "commander": "~2.20.0", - "source-map": "~0.6.1" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -14728,19 +9805,13 @@ "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, - "optional": true + "dev": true }, "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": { - "source-map": "^0.5.6", - "uglify-js": "^2.8.29", - "webpack-sources": "^1.0.1" - }, "dependencies": { "camelcase": { "version": "1.2.1", @@ -14752,23 +9823,13 @@ "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.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } + "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.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - } + "dev": true }, "wordwrap": { "version": "0.0.2", @@ -14780,13 +9841,7 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } + "dev": true } } }, @@ -14806,18 +9861,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "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", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } + "dev": true }, "undertaker-registry": { "version": "1.0.1", @@ -14829,11 +9873,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" - } + "dev": true }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", @@ -14845,11 +9885,7 @@ "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": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } + "dev": true }, "unicode-match-property-value-ecmascript": { "version": "1.1.0", @@ -14867,64 +9903,25 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^2.0.0", - "x-is-string": "^0.1.0" - } + "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" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } + "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" - } + "dev": true }, "unist-builder": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.4.tgz", "integrity": "sha512-v6xbUPP7ILrT15fHGrNyHc1Xda8H3xVhP7/HAIotHOhVPjH5dCXA097C3Rry1Q2O+HbOLCao4hfPB+EYEjHgVg==", - "dev": true, - "requires": { - "object-assign": "^4.1.0" - } + "dev": true }, "unist-util-generated": { "version": "1.1.4", @@ -14948,10 +9945,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.3.tgz", "integrity": "sha512-CtszTlOjP2sBGYc2zcKA/CvNdTdEs3ozbiJ63IPBxh8iZg42SCCb8m04f8z2+V1aSk5a7BxbZKEdoDjadmBkWA==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } + "dev": true }, "unist-util-stringify-position": { "version": "1.1.2", @@ -14963,24 +9957,12 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } + "dev": true }, "unist-util-visit-parents": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, - "requires": { - "unist-util-is": "^3.0.0" - } - }, - "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 }, "unpipe": { @@ -14994,30 +9976,18 @@ "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=", "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.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" - } + "dev": true } } }, @@ -15039,10 +10009,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } + "dev": true }, "urix": { "version": "0.1.0", @@ -15055,10 +10022,6 @@ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, "dependencies": { "punycode": { "version": "1.3.2", @@ -15079,10 +10042,6 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - }, "dependencies": { "querystringify": { "version": "2.1.1", @@ -15097,9 +10056,6 @@ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "dev": true, - "requires": { - "prepend-http": "^2.0.0" - }, "dependencies": { "prepend-http": { "version": "2.0.0", @@ -15124,24 +10080,35 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, - "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" + "dependencies": { + "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 + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } } }, "util": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", - "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, - "requires": { - "inherits": "2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "object.entries": "^1.1.0", - "safe-buffer": "^5.1.2" + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "util-deprecate": { @@ -15166,20 +10133,13 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "dev": true }, "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": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } + "dev": true }, "value-or-function": { "version": "3.0.0", @@ -15197,24 +10157,13 @@ "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.2.0" - } + "dev": true }, "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true, - "requires": { - "is-buffer": "^1.1.4", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } + "dev": true }, "vfile-location": { "version": "2.0.5", @@ -15226,23 +10175,13 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } + "dev": true }, "vfile-reporter": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, - "requires": { - "repeat-string": "^1.5.0", - "string-width": "^1.0.0", - "supports-color": "^4.1.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-statistics": "^1.1.0" - }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -15254,30 +10193,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true }, "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" - } + "dev": true } } }, @@ -15297,64 +10225,25 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "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" - } + "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" - } + "dev": true }, "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": { "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" - } + "dev": true } } }, @@ -15362,10 +10251,7 @@ "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" - } + "dev": true }, "vm-browserify": { "version": "1.1.0", @@ -15383,32 +10269,19 @@ "version": "2.3.14", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", - "dev": true, - "requires": { - "foreachasync": "^3.0.0" - } + "dev": true }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - } + "dev": true }, "wdio-browserstack-service": { "version": "0.1.18", "resolved": "https://registry.npmjs.org/wdio-browserstack-service/-/wdio-browserstack-service-0.1.18.tgz", "integrity": "sha512-6tISYMKzwr2oxx0yi2Q4GoFC2Mbq81iHhqxayacC4XgFR7QbmQkxwV8JPeq590AXhuhPqqmyuEGkMqc9fo/UoQ==", - "dev": true, - "requires": { - "browserstack-local": "^1.3.7", - "request": "^2.81.0", - "request-promise": "^4.2.1" - } + "dev": true }, "wdio-concise-reporter": { "version": "0.1.2", @@ -15426,64 +10299,25 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/wdio-mocha-framework/-/wdio-mocha-framework-0.6.4.tgz", "integrity": "sha512-GZsXwoW60/fkkfqZJR/ZAdiALaM+hW+BbnTT9x214qPR4Pe5XeyYxhJNEdyf0dNI9625cMdkyZYaWoFHN5zDcA==", - "dev": true, - "requires": { - "babel-runtime": "^6.23.0", - "mocha": "^5.2.0", - "wdio-sync": "0.7.3" - } + "dev": true }, "wdio-spec-reporter": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/wdio-spec-reporter/-/wdio-spec-reporter-0.1.5.tgz", "integrity": "sha512-MqvgTow8hFwhFT47q67JwyJyeynKodGRQCxF7ijKPGfsaG1NLssbXYc0JhiL7SiAyxnQxII0UxzTCd3I6sEdkg==", - "dev": true, - "requires": { - "babel-runtime": "~6.26.0", - "chalk": "^2.3.0", - "humanize-duration": "~3.15.0" - } + "dev": true }, "wdio-sync": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/wdio-sync/-/wdio-sync-0.7.3.tgz", "integrity": "sha512-ukASSHOQmOxaz5HTILR0jykqlHBtAPsBpMtwhpiG0aW9uc7SO7PF+E5LhVvTG4ypAh+UGmY3rTjohOsqDr39jw==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "fibers": "^3.0.0", - "object.assign": "^4.0.3" - } + "dev": true }, "webdriverio": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", "integrity": "sha512-Knp2vzuzP5c5ybgLu+zTwy/l1Gh0bRP4zAr8NWcrStbuomm9Krn9oRF0rZucT6AyORpXinETzmeowFwIoo7mNA==", "dev": true, - "requires": { - "archiver": "~2.1.0", - "babel-runtime": "^6.26.0", - "css-parse": "^2.0.0", - "css-value": "~0.0.1", - "deepmerge": "~2.0.1", - "ejs": "~2.5.6", - "gaze": "~1.1.2", - "glob": "~7.1.1", - "grapheme-splitter": "^1.0.2", - "inquirer": "~3.3.0", - "json-stringify-safe": "~5.0.1", - "mkdirp": "~0.5.1", - "npm-install-package": "~2.1.0", - "optimist": "~0.6.1", - "q": "~1.5.0", - "request": "^2.83.0", - "rgb2hex": "^0.1.9", - "safe-buffer": "~5.1.1", - "supports-color": "~5.0.0", - "url": "~0.11.0", - "wdio-dot-reporter": "~0.0.8", - "wgxpath": "~1.0.0" - }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -15495,10 +10329,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", "integrity": "sha512-7FQGOlSQ+AQxBNXJpVDj8efTA/FtyB5wcNE1omXXJ0cq6jm1jjDwuROlYDbnzHqdNPqliWFhcioCWSyav+xBnA==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } + "dev": true } } }, @@ -15507,57 +10338,24 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", "dev": true, - "requires": { - "acorn": "^5.0.0", - "acorn-dynamic-import": "^2.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "async": "^2.1.2", - "enhanced-resolve": "^3.4.0", - "escope": "^3.6.0", - "interpret": "^1.0.0", - "json-loader": "^0.5.4", - "json5": "^0.5.1", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "mkdirp": "~0.5.0", - "node-libs-browser": "^2.0.0", - "source-map": "^0.5.3", - "supports-color": "^4.2.1", - "tapable": "^0.2.7", - "uglifyjs-webpack-plugin": "^0.4.6", - "watchpack": "^1.4.0", - "webpack-sources": "^1.0.1", - "yargs": "^8.0.2" - }, "dependencies": { "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true }, "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true }, "camelcase": { "version": "4.1.0", @@ -15570,22 +10368,12 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, "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.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true } } }, @@ -15593,27 +10381,13 @@ "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.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "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.0.1", - "get-stream": "^3.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" - } + "dev": true }, "fast-deep-equal": { "version": "2.0.1", @@ -15625,10 +10399,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "dev": true }, "get-caller-file": { "version": "1.0.3", @@ -15652,10 +10423,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -15673,41 +10441,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "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.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } + "dev": true }, "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" - } + "dev": true + }, + "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 }, "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.0.0" - } + "dev": true }, "mimic-fn": { "version": "1.2.0", @@ -15719,30 +10477,19 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } + "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" - } + "dev": true }, "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.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -15754,19 +10501,13 @@ "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" - } + "dev": true }, "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.0.0" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -15778,22 +10519,13 @@ "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.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "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.0.0", - "read-pkg": "^2.0.0" - } + "dev": true }, "require-main-filename": { "version": "1.0.1", @@ -15805,10 +10537,7 @@ "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" - } + "dev": true }, "y18n": { "version": "3.2.1", @@ -15816,63 +10545,36 @@ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "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.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.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.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" - } + "dev": true }, "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" - } + "dev": true } } }, "webpack-bundle-analyzer": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", - "integrity": "sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==", - "dev": true, - "requires": { - "acorn": "^6.0.7", - "acorn-walk": "^6.1.1", - "bfj": "^6.1.1", - "chalk": "^2.4.1", - "commander": "^2.18.0", - "ejs": "^2.6.1", - "express": "^4.16.3", - "filesize": "^3.6.1", - "gzip-size": "^5.0.0", - "lodash": "^4.17.10", - "mkdirp": "^0.5.1", - "opener": "^1.5.1", - "ws": "^6.0.0" - }, + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", + "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", + "dev": true, "dependencies": { "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", "dev": true }, "ejs": { @@ -15885,27 +10587,35 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } + "dev": true + } + } + }, + "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, + "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 } } }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, - "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" - }, "dependencies": { "mime": { "version": "2.4.4", @@ -15919,23 +10629,13 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "loglevelnext": "^1.0.1", - "uuid": "^3.1.0" - } + "dev": true }, "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -15946,126 +10646,366 @@ } }, "webpack-stream": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-5.2.1.tgz", - "integrity": "sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==", - "dev": true, - "requires": { - "fancy-log": "^1.3.3", - "lodash.clone": "^4.3.2", - "lodash.some": "^4.2.2", - "memory-fs": "^0.4.1", - "plugin-error": "^1.0.1", - "supports-color": "^5.5.0", - "through": "^2.3.8", - "vinyl": "^2.1.0", - "webpack": "^4.26.1" - }, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", + "dev": true, "dependencies": { "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "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 + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true + }, + "browserify-aes": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", + "dev": true + }, + "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 + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true + }, + "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 + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true + }, + "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 + }, + "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 }, "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "version": "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.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" + "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 + } } }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "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 + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true + }, + "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 }, - "schema-utils": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true + }, + "has-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "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-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 + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "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": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true + }, + "tapable": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "dev": true + }, + "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": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } } }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true }, - "webpack": { - "version": "4.36.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.36.1.tgz", - "integrity": "sha512-Ej01/N9W8DVyhEpeQnbUdGvOECw0L46FxS12cCOs8gSK7bhUlrbHRnWkjiXckGlHjUrmL89kDpTRIkUk6Y+fKg==", + "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 + }, + "watchpack": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.2.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "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 + }, + "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 } } }, @@ -16073,12 +11013,7 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.4.0 <0.4.11", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } + "dev": true }, "websocket-extensions": { "version": "0.1.3", @@ -16096,10 +11031,7 @@ "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" - } + "dev": true }, "which-module": { "version": "2.0.0", @@ -16111,10 +11043,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } + "dev": true }, "window-size": { "version": "0.1.0", @@ -16128,44 +11057,23 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, "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.1", - "strip-ansi": "^3.0.1" - }, "dependencies": { "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true } } }, @@ -16179,21 +11087,13 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } + "dev": true }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } + "dev": true }, "x-is-string": { "version": "0.1.0", @@ -16208,9 +11108,9 @@ "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "y18n": { @@ -16220,9 +11120,9 @@ "dev": true }, "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true }, "yargs": { @@ -16235,22 +11135,13 @@ "version": "13.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "dev": true }, "yargs-unparser": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, "dependencies": { "get-caller-file": { "version": "1.0.3", @@ -16268,31 +11159,13 @@ "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } + "dev": true }, "yargs-parser": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "dev": true } } }, @@ -16306,13 +11179,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", - "dev": true, - "requires": { - "archiver-utils": "^1.3.0", - "compress-commons": "^1.2.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0" - } + "dev": true } } } diff --git a/package.json b/package.json index d028e6049a1..dc8af2c21a3 100755 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", - "karma": "^4.2.0", + "karma": "^3.1.3", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", @@ -76,7 +76,7 @@ "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "^0.0.31", "karma-webpack": "^3.0.5", - "lodash": "^4.17.15", + "lodash": "^4.17.4", "mocha": "^5.0.0", "opn": "^5.4.0", "querystringify": "0.0.3", @@ -91,7 +91,7 @@ "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-bundle-analyzer": "^3.3.2", - "webpack-stream": "^5.2.1", + "webpack-stream": "^3.2.0", "yargs": "^1.3.1" }, "dependencies": { From fe8074ad43648f93e753a170178e8505479d63d5 Mon Sep 17 00:00:00 2001 From: Alex Khmelnitsky Date: Tue, 6 Aug 2019 23:12:59 +0300 Subject: [PATCH 1409/1594] fix cedato adapter user sync logic (#4060) --- modules/cedatoBidAdapter.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/modules/cedatoBidAdapter.js b/modules/cedatoBidAdapter.js index c367c57fc25..155e6eda107 100644 --- a/modules/cedatoBidAdapter.js +++ b/modules/cedatoBidAdapter.js @@ -107,15 +107,10 @@ export const spec = { getUserSyncs: function(syncOptions, resps, gdprConsent) { const syncs = []; - if (syncOptions.pixelEnabled) { - resps.forEach(() => { - syncs.push(getSync('image', gdprConsent)); - }); - } if (syncOptions.iframeEnabled) { - resps.forEach(() => { - syncs.push(getSync('iframe', gdprConsent)); - }); + syncs.push(getSync('iframe', gdprConsent)); + } else if (syncOptions.pixelEnabled) { + syncs.push(getSync('image', gdprConsent)); } return syncs; } From 22b0b731df337d3aa42b1b1c54eaef84d9c3ed88 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 6 Aug 2019 16:35:50 -0400 Subject: [PATCH 1410/1594] Prebid 2.27.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc8af2c21a3..222da0c3b00 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.27.0-pre", + "version": "2.27.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d7ebb571021f38e0ad90657ffc1eaaa676a2ae16 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 6 Aug 2019 17:39:53 -0400 Subject: [PATCH 1411/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 222da0c3b00..b8062204ce1 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.27.0", + "version": "2.28.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 131c56a02eb5c49a28a64f0404ae585f2288b1ed Mon Sep 17 00:00:00 2001 From: Wayne Yang Date: Wed, 7 Aug 2019 06:41:10 -0700 Subject: [PATCH 1412/1594] GumGum adapter: push first indexed value in sizes array to bidResponses.height and width (#4006) * changed resizing unit tests to return the first size dimensions in the sizes array * added some changes --- modules/gumgumBidAdapter.js | 4 ++-- test/spec/modules/gumgumBidAdapter_spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 496941e3c1f..75ba5da4de9 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -175,7 +175,7 @@ function buildRequests (validBidRequests, bidderRequest) { tId: transactionId, pi: data.pi, selector: params.selector, - sizes: bidRequest.sizes, + sizes: bidRequest.sizes || bidRequest.mediatype[banner].sizes, url: BID_ENDPOINT, method: 'GET', data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) @@ -221,7 +221,7 @@ function interpretResponse (serverResponse, bidRequest) { let [width, height] = sizes[0].split('x') // return 1x1 when breakout expected - if ((product === 2 || product === 5) && includes(sizes, '1x1')) { + if (product === 5 && includes(sizes, '1x1')) { width = '1' height = '1' } diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index a7a588afd13..53a6849fce3 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -245,8 +245,8 @@ describe('gumgumAdapter', function () { 'thms': 10000 } let result = spec.interpretResponse({ body: inscreenServerResponse }, inscreenBidRequest); - expect(result[0].width).to.equal('1'); - expect(result[0].height).to.equal('1'); + expect(result[0].width).to.equal(inscreenBidRequest.sizes[0][0].toString()); + expect(result[0].height).to.equal(inscreenBidRequest.sizes[0][1].toString()); }) }) describe('getUserSyncs', function () { From cd252ec4faf336f8085186510edbc03f65974f23 Mon Sep 17 00:00:00 2001 From: christopher-allene-piximedia Date: Wed, 7 Aug 2019 15:57:58 +0200 Subject: [PATCH 1413/1594] Improve Piximedia Adapter (#4026) * Add Piximedia adapter * Add piximediaBidAdapter.md * Improve protocol of Piximedia bidder * Add Piximedia adapter * Fix piximediaBidAdapter_spec.js style * Fix Piximedia adapter * Revert "Fix Piximedia adapter" This reverts commit 10a10d6fbde61efe74f58539bdd9753f7048dd69. * Impprove Piximedia adapter * Remove CR at end of file * Add test for pbsizes in Piximedia adapter --- modules/piximediaBidAdapter.js | 1 + test/spec/modules/piximediaBidAdapter_spec.js | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/piximediaBidAdapter.js b/modules/piximediaBidAdapter.js index b97c91e5b5b..7fca4e32996 100644 --- a/modules/piximediaBidAdapter.js +++ b/modules/piximediaBidAdapter.js @@ -20,6 +20,7 @@ export const spec = { timestamp: utils.timestamp(), pver: '1.0', pbparams: JSON.stringify(bidRequest.params), + pbsizes: JSON.stringify(parseSized), pbwidth: arrSize[0], pbheight: arrSize[1], pbbidid: bidRequest.bidId, diff --git a/test/spec/modules/piximediaBidAdapter_spec.js b/test/spec/modules/piximediaBidAdapter_spec.js index 02cf80c614f..95e03734345 100644 --- a/test/spec/modules/piximediaBidAdapter_spec.js +++ b/test/spec/modules/piximediaBidAdapter_spec.js @@ -47,6 +47,7 @@ describe('piximediaAdapterTest', function() { it('bidRequest data', function() { const requests = spec.buildRequests(bidRequests); expect(typeof requests[0].data.timestamp).to.equal('number'); + expect(requests[0].data.pbsizes).to.equal('["300x250"]'); expect(requests[0].data.pver).to.equal('1.0'); expect(requests[0].data.pbparams).to.equal(JSON.stringify(bidRequests[0].params)); expect(requests[0].data.pbwidth).to.equal('300'); From 36d67b644e3c1b01ef9491e6c7038e39473ba5e0 Mon Sep 17 00:00:00 2001 From: rhythmonebhaines <49991465+rhythmonebhaines@users.noreply.github.com> Date: Wed, 7 Aug 2019 16:07:39 -0700 Subject: [PATCH 1414/1594] Rhythmone Adapter - deprecate direct usage of window objects. (#4061) --- modules/rhythmoneBidAdapter.js | 67 ++++++------- test/spec/modules/rhythmoneBidAdapter_spec.js | 97 ++++++++++++++++++- 2 files changed, 126 insertions(+), 38 deletions(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 84caca5508a..dc818e89f32 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -15,8 +15,7 @@ function RhythmOneBidAdapter() { let SUPPORTED_VIDEO_API = [1, 2, 5]; let slotsToBids = {}; let that = this; - let version = '2.0.1.0'; - var win = typeof window !== 'undefined' ? window : {}; + let version = '2.1'; this.isBidRequestValid = function (bid) { return !!(bid.params && bid.params.placementId); @@ -26,14 +25,21 @@ function RhythmOneBidAdapter() { return []; }; - function frameImp(BRs) { + function frameImp(BRs, bidderRequest) { var impList = []; + var isSecure = 0; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.stack.length) { + // clever trick to get the protocol + var el = document.createElement('a'); + el.href = bidderRequest.refererInfo.stack[0]; + isSecure = (el.protocol == 'https:') ? 1 : 0; + } for (var i = 0; i < BRs.length; i++) { - slotsToBids[BRs[i].adUnitCode || BRs[i].placementCode] = BRs[i]; + slotsToBids[BRs[i].adUnitCode] = BRs[i]; var impObj = {}; impObj.id = BRs[i].adUnitCode; impObj.bidfloor = parseFloat(utils.deepAccess(BRs[i], 'params.floor')) || 0; - impObj.secure = win.location.protocol === 'https:' ? 1 : 0; + impObj.secure = isSecure; if (utils.deepAccess(BRs[i], 'mediaTypes.banner') || utils.deepAccess(BRs[i], 'mediaType') === 'banner') { let banner = frameBanner(BRs[i]); @@ -54,31 +60,25 @@ function RhythmOneBidAdapter() { } function frameSite(bidderRequest) { - return { - domain: attempt(function() { - var d = win.document.location.ancestorOrigins; - if (d && d.length > 0) { - return d[d.length - 1]; - } - return win.top.document.location.hostname; // try/catch is in the attempt function - }, ''), - page: attempt(function() { - var l; - // try/catch is in the attempt function - try { - l = win.top.document.location.href.toString(); - } catch (ex) { - l = win.document.location.href.toString(); - } - return l; - }, ''), - ref: attempt(function() { - if (bidderRequest && bidderRequest.refererInfo) { - return bidderRequest.refererInfo.referer; - } - return ''; - }, '') + var site = { + domain: '', + page: '', + ref: '' } + if (bidderRequest && bidderRequest.refererInfo) { + var ri = bidderRequest.refererInfo; + site.ref = ri.referer; + + if (ri.stack.length) { + site.page = ri.stack[ri.stack.length - 1]; + + // clever trick to get the domain + var el = document.createElement('a'); + el.href = ri.stack[0]; + site.domain = el.hostname; + } + } + return site; } function frameDevice() { @@ -165,7 +165,7 @@ function RhythmOneBidAdapter() { function frameBid(BRs, bidderRequest) { return { id: BRs[0].bidderRequestId, - imp: frameImp(BRs), + imp: frameImp(BRs, bidderRequest), site: frameSite(bidderRequest), device: frameDevice(), user: { @@ -191,13 +191,6 @@ function RhythmOneBidAdapter() { } } - function attempt(valueFunction, defaultValue) { - try { - return valueFunction(); - } catch (ex) { } - return defaultValue; - } - this.buildRequests = function (BRs, bidderRequest) { let fallbackPlacementId = getFirstParam('placementId', BRs); if (fallbackPlacementId === undefined || BRs.length < 1) { diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index 6b414db47ab..b6ac09a6207 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -8,7 +8,11 @@ describe('rhythmone adapter tests', function () { beforeEach(function() { this.defaultBidderRequest = { 'refererInfo': { - 'referer': 'Reference Page' + 'referer': 'Reference Page', + 'stack': [ + 'aodomain.dvl', + 'page.dvl' + ] } }; }); @@ -611,6 +615,91 @@ describe('rhythmone adapter tests', function () { expect(bidRequest).to.be.empty; }); + + it('should return empty site data when refererInfo is missing', function() { + delete this.defaultBidderRequest.refererInfo; + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.site.domain).to.equal(''); + expect(openrtbRequest.site.page).to.equal(''); + expect(openrtbRequest.site.ref).to.equal(''); + }); + }); + + it('should return empty site.domain and site.page when refererInfo.stack is empty', function() { + this.defaultBidderRequest.refererInfo.stack = []; + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.site.domain).to.equal(''); + expect(openrtbRequest.site.page).to.equal(''); + expect(openrtbRequest.site.ref).to.equal('Reference Page'); + }); + + it('should secure correctly', function() { + this.defaultBidderRequest.refererInfo.stack[0] = ['https://securesite.dvl']; + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.imp[0].secure).to.equal(1); }); describe('misc interpretResponse', function () { @@ -647,4 +736,10 @@ describe('rhythmone adapter tests', function () { expect(r1adapter.isBidRequestValid(bid)).to.equal(false); }); }); + + describe('getUserSyncs', function () { + it('returns an empty string', function () { + expect(r1adapter.getUserSyncs()).to.deep.equal([]); + }); + }); }); From 6fb604943c8b19d845fe4a0d5e3afa30f0455635 Mon Sep 17 00:00:00 2001 From: Benjamin Clot Date: Fri, 9 Aug 2019 05:02:12 +0200 Subject: [PATCH 1415/1594] Fix removeAdUnit (#4053) * Fix removeAdUnit When there are multiple adUnits with the same code, only one of them gets removed. This fixes that. * snapwich fix --- src/prebid.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 90f6365585e..efa1198d36c 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -390,12 +390,12 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { } adUnitCodes.forEach((adUnitCode) => { - for (let i = 0; i < $$PREBID_GLOBAL$$.adUnits.length; i++) { + for (let i = $$PREBID_GLOBAL$$.adUnits.length - 1; i >= 0; i--) { if ($$PREBID_GLOBAL$$.adUnits[i].code === adUnitCode) { $$PREBID_GLOBAL$$.adUnits.splice(i, 1); } } - }) + }); }; /** From 6d9f85e809512af2da5d06841b0ee5c6fe2f69ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20DEYM=C3=88S?= <47388595+MaxSmileWanted@users.noreply.github.com> Date: Fri, 9 Aug 2019 08:55:15 +0200 Subject: [PATCH 1416/1594] Adding support of Instream/Outstream Video for the SmileWanted Adapter (#4064) --- modules/smilewantedBidAdapter.js | 53 +++- modules/smilewantedBidAdapter.md | 40 +++ .../modules/smilewantedBidAdapter_spec.js | 246 ++++++++++++++---- 3 files changed, 280 insertions(+), 59 deletions(-) diff --git a/modules/smilewantedBidAdapter.js b/modules/smilewantedBidAdapter.js index bf9a75b6650..ed7e02a51a8 100644 --- a/modules/smilewantedBidAdapter.js +++ b/modules/smilewantedBidAdapter.js @@ -1,11 +1,13 @@ import * as utils from '../src/utils'; +import { Renderer } from '../src/Renderer'; import { config } from '../src/config'; import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; export const spec = { code: 'smilewanted', aliases: ['smile', 'sw'], - + supportedMediaTypes: [BANNER, VIDEO], /** * Determines whether or not the given bid request is valid. * @@ -65,6 +67,7 @@ export const spec = { interpretResponse: function(serverResponse, bidRequest) { const bidResponses = []; var response = serverResponse.body; + try { if (response) { const bidResponse = { @@ -77,10 +80,19 @@ export const spec = { currency: response.currency, netRevenue: response.isNetCpm, ttl: response.ttl, - adUrl: response.adUrl, - ad: response.ad + ad: response.ad, }; + if (response.formatTypeSw == 'video_instream' || response.formatTypeSw == 'video_outstream') { + bidResponse['mediaType'] = 'video'; + bidResponse['vastUrl'] = response.ad; + bidResponse['ad'] = null; + } + + if (response.formatTypeSw == 'video_outstream') { + bidResponse['renderer'] = newRenderer(JSON.parse(bidRequest.data), response); + } + bidResponses.push(bidResponse); } } catch (error) { @@ -110,4 +122,39 @@ export const spec = { } } +/** + * Create SmileWanted renderer + * @param requestId + * @returns {*} + */ +function newRenderer(bidRequest, bidResponse) { + const renderer = Renderer.install({ + id: bidRequest.bidId, + url: bidResponse.OustreamTemplateUrl, + loaded: false + }); + + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on newRenderer', err); + } + return renderer; +} + +/** + * Initialise SmileWanted outstream + * @param bid + */ +function outstreamRender(bid) { + bid.renderer.push(() => { + window.SmileWantedOutStreamInit({ + width: bid.width, + height: bid.height, + vastUrl: bid.vastUrl, + elId: bid.adUnitCode + }); + }); +} + registerBidder(spec); diff --git a/modules/smilewantedBidAdapter.md b/modules/smilewantedBidAdapter.md index ddc25fe7456..678eda1eeee 100644 --- a/modules/smilewantedBidAdapter.md +++ b/modules/smilewantedBidAdapter.md @@ -13,6 +13,8 @@ To use us as a bidder you must have an account and an active "zoneId" on our Smi # Test Parameters ## Web + +### Display ``` var adUnits = [ { @@ -28,4 +30,42 @@ To use us as a bidder you must have an account and an active "zoneId" on our Smi ] } ]; +``` + +### Video Instream +``` + var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'smilewanted', + params: { + zoneId: 2, + } + }] + }; +``` + +### Video Outstream +``` + var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream' + } + }, + bids: [{ + bidder: 'smilewanted', + params: { + zoneId: 3, + } + }] + }; ``` \ No newline at end of file diff --git a/test/spec/modules/smilewantedBidAdapter_spec.js b/test/spec/modules/smilewantedBidAdapter_spec.js index 489f393523a..144c7ca60f6 100644 --- a/test/spec/modules/smilewantedBidAdapter_spec.js +++ b/test/spec/modules/smilewantedBidAdapter_spec.js @@ -5,62 +5,151 @@ import { config } from 'src/config'; import * as utils from 'src/utils'; import { requestBidsHook } from 'modules/consentManagement'; +const DISPLAY_REQUEST = [{ + adUnitCode: 'sw_300x250', + bidId: '12345', + sizes: [ + [300, 250], + [300, 200] + ], + bidder: 'smilewanted', + params: { + zoneId: 1, + bidfloor: 2.50 + }, + requestId: 'request_abcd1234', + transactionId: 'trans_abcd1234' +}]; + +const BID_RESPONSE_DISPLAY = { + body: { + cpm: 3, + width: 300, + height: 250, + creativeId: 'crea_sw_1', + currency: 'EUR', + isNetCpm: true, + ttl: 300, + ad: '< --- sw script --- >', + cSyncUrl: 'https://csync.smilewanted.com' + } +}; + +const VIDEO_INSTREAM_REQUEST = [{ + code: 'video1', + mediaTypes: { + video: {} + }, + sizes: [ + [640, 480] + ], + bidder: 'smilewanted', + params: { + zoneId: 2, + bidfloor: 2.50 + }, + requestId: 'request_abcd1234', + transactionId: 'trans_abcd1234' +}]; + +const BID_RESPONSE_VIDEO_INSTREAM = { + body: { + cpm: 3, + width: 640, + height: 480, + creativeId: 'crea_sw_2', + currency: 'EUR', + isNetCpm: true, + ttl: 300, + ad: 'https://vast.smilewanted.com', + cSyncUrl: 'https://csync.smilewanted.com', + formatTypeSw: 'video_instream' + } +}; + +const VIDEO_OUTSTREAM_REQUEST = [{ + code: 'video1', + mediaTypes: { + video: {} + }, + sizes: [ + [640, 480] + ], + bidder: 'smilewanted', + params: { + zoneId: 3, + bidfloor: 2.50 + }, + requestId: 'request_abcd1234', + transactionId: 'trans_abcd1234' +}]; + +const BID_RESPONSE_VIDEO_OUTSTREAM = { + body: { + cpm: 3, + width: 640, + height: 480, + creativeId: 'crea_sw_3', + currency: 'EUR', + isNetCpm: true, + ttl: 300, + ad: 'https://vast.smilewanted.com', + cSyncUrl: 'https://csync.smilewanted.com', + OustreamTemplateUrl: 'https://prebid.smilewanted.com/scripts_outstream/infeed.js', + formatTypeSw: 'video_outstream' + } +}; + // Default params with optional ones describe('smilewantedBidAdapterTests', function () { - var DEFAULT_PARAMS = [{ - adUnitCode: 'sw_300x250', - bidId: '12345', - sizes: [ - [300, 250], - [300, 200] - ], - bidder: 'smilewanted', - params: { - zoneId: '1234', - bidfloor: 2.50 - }, - requestId: 'request_abcd1234', - transactionId: 'trans_abcd1234' - }]; - - var BID_RESPONSE = { - body: { - cpm: 3, - width: 300, - height: 250, - creativeId: 'crea_sw_1', - currency: 'EUR', - isNetCpm: true, - ttl: 300, - adUrl: 'https://www.smilewanted.com', - ad: '< --- sw script --- >', - cSyncUrl: 'https://csync.smilewanted.com' - } - }; - it('SmileWanted - Verify build request', function () { config.setConfig({ 'currency': { 'adServerCurrency': 'EUR' } }); - const request = spec.buildRequests(DEFAULT_PARAMS); - expect(request[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com'); - expect(request[0]).to.have.property('method').and.to.equal('POST'); - const requestContent = JSON.parse(request[0].data); - expect(requestContent).to.have.property('zoneId').and.to.equal('1234'); - expect(requestContent).to.have.property('currencyCode').and.to.equal('EUR'); - expect(requestContent).to.have.property('bidfloor').and.to.equal(2.50); - expect(requestContent).to.have.property('sizes'); - expect(requestContent.sizes[0]).to.have.property('w').and.to.equal(300); - expect(requestContent.sizes[0]).to.have.property('h').and.to.equal(250); - expect(requestContent.sizes[1]).to.have.property('w').and.to.equal(300); - expect(requestContent.sizes[1]).to.have.property('h').and.to.equal(200); - expect(requestContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; + + const requestDisplay = spec.buildRequests(DISPLAY_REQUEST); + expect(requestDisplay[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com'); + expect(requestDisplay[0]).to.have.property('method').and.to.equal('POST'); + const requestDisplayContent = JSON.parse(requestDisplay[0].data); + expect(requestDisplayContent).to.have.property('zoneId').and.to.equal(1); + expect(requestDisplayContent).to.have.property('currencyCode').and.to.equal('EUR'); + expect(requestDisplayContent).to.have.property('bidfloor').and.to.equal(2.50); + expect(requestDisplayContent).to.have.property('sizes'); + expect(requestDisplayContent.sizes[0]).to.have.property('w').and.to.equal(300); + expect(requestDisplayContent.sizes[0]).to.have.property('h').and.to.equal(250); + expect(requestDisplayContent.sizes[1]).to.have.property('w').and.to.equal(300); + expect(requestDisplayContent.sizes[1]).to.have.property('h').and.to.equal(200); + expect(requestDisplayContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; + + const requestVideoInstream = spec.buildRequests(VIDEO_INSTREAM_REQUEST); + expect(requestVideoInstream[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com'); + expect(requestVideoInstream[0]).to.have.property('method').and.to.equal('POST'); + const requestVideoInstreamContent = JSON.parse(requestVideoInstream[0].data); + expect(requestVideoInstreamContent).to.have.property('zoneId').and.to.equal(2); + expect(requestVideoInstreamContent).to.have.property('currencyCode').and.to.equal('EUR'); + expect(requestVideoInstreamContent).to.have.property('bidfloor').and.to.equal(2.50); + expect(requestVideoInstreamContent).to.have.property('sizes'); + expect(requestVideoInstreamContent.sizes[0]).to.have.property('w').and.to.equal(640); + expect(requestVideoInstreamContent.sizes[0]).to.have.property('h').and.to.equal(480); + expect(requestVideoInstreamContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; + + const requestVideoOutstream = spec.buildRequests(VIDEO_OUTSTREAM_REQUEST); + expect(requestVideoOutstream[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com'); + expect(requestVideoOutstream[0]).to.have.property('method').and.to.equal('POST'); + const requestVideoOutstreamContent = JSON.parse(requestVideoOutstream[0].data); + expect(requestVideoOutstreamContent).to.have.property('zoneId').and.to.equal(3); + expect(requestVideoOutstreamContent).to.have.property('currencyCode').and.to.equal('EUR'); + expect(requestVideoOutstreamContent).to.have.property('bidfloor').and.to.equal(2.50); + expect(requestVideoOutstreamContent).to.have.property('sizes'); + expect(requestVideoOutstreamContent.sizes[0]).to.have.property('w').and.to.equal(640); + expect(requestVideoOutstreamContent.sizes[0]).to.have.property('h').and.to.equal(480); + expect(requestVideoOutstreamContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; }); it('SmileWanted - Verify build request with referrer', function () { - const request = spec.buildRequests(DEFAULT_PARAMS, { + const request = spec.buildRequests(DISPLAY_REQUEST, { refererInfo: { referer: 'http://localhost/Prebid.js/integrationExamples/gpt/hello_world.html' } @@ -87,7 +176,7 @@ describe('smilewantedBidAdapterTests', function () { allowAuctionWithoutConsent: true } }); - const request = spec.buildRequests(DEFAULT_PARAMS, { + const request = spec.buildRequests(DISPLAY_REQUEST, { gdprConsent: { consentString: 'BOO_ch7OO_ch7AKABBENA2-AAAAZ97_______9______9uz_Gv_r_f__33e8_39v_h_7_u___m_-zzV4-_lvQV1yPA1OrfArgFA', gdprApplies: true @@ -110,7 +199,7 @@ describe('smilewantedBidAdapterTests', function () { allowAuctionWithoutConsent: true } }); - const request = spec.buildRequests(DEFAULT_PARAMS, { + const request = spec.buildRequests(DISPLAY_REQUEST, { gdprConsent: { consentString: 'BOO_ch7OO_ch7AKABBENA2-AAAAZ97_______9______9uz_Gv_r_f__33e8_39v_h_7_u___m_-zzV4-_lvQV1yPA1OrfArgFA' } @@ -121,13 +210,12 @@ describe('smilewantedBidAdapterTests', function () { }); }); - it('SmileWanted - Verify parse response', function () { - const request = spec.buildRequests(DEFAULT_PARAMS); - const bids = spec.interpretResponse(BID_RESPONSE, request[0]); + it('SmileWanted - Verify parse response - Display', function () { + const request = spec.buildRequests(DISPLAY_REQUEST); + const bids = spec.interpretResponse(BID_RESPONSE_DISPLAY, request[0]); expect(bids).to.have.lengthOf(1); const bid = bids[0]; expect(bid.cpm).to.equal(3); - expect(bid.adUrl).to.equal('https://www.smilewanted.com'); expect(bid.ad).to.equal('< --- sw script --- >'); expect(bid.width).to.equal(300); expect(bid.height).to.equal(250); @@ -135,10 +223,56 @@ describe('smilewantedBidAdapterTests', function () { expect(bid.currency).to.equal('EUR'); expect(bid.netRevenue).to.equal(true); expect(bid.ttl).to.equal(300); - expect(bid.requestId).to.equal(DEFAULT_PARAMS[0].bidId); + expect(bid.requestId).to.equal(DISPLAY_REQUEST[0].bidId); + + expect(function () { + spec.interpretResponse(BID_RESPONSE_DISPLAY, { + data: 'invalid Json' + }) + }).to.not.throw(); + }); + + it('SmileWanted - Verify parse response - Video Instream', function () { + const request = spec.buildRequests(VIDEO_INSTREAM_REQUEST); + const bids = spec.interpretResponse(BID_RESPONSE_VIDEO_INSTREAM, request[0]); + expect(bids).to.have.lengthOf(1); + const bid = bids[0]; + expect(bid.cpm).to.equal(3); + expect(bid.ad).to.equal(null); + expect(bid.vastUrl).to.equal('https://vast.smilewanted.com'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.creativeId).to.equal('crea_sw_2'); + expect(bid.currency).to.equal('EUR'); + expect(bid.netRevenue).to.equal(true); + expect(bid.ttl).to.equal(300); + expect(bid.requestId).to.equal(VIDEO_INSTREAM_REQUEST[0].bidId); + + expect(function () { + spec.interpretResponse(BID_RESPONSE_VIDEO_INSTREAM, { + data: 'invalid Json' + }) + }).to.not.throw(); + }); + + it('SmileWanted - Verify parse response - Video Oustream', function () { + const request = spec.buildRequests(VIDEO_OUTSTREAM_REQUEST); + const bids = spec.interpretResponse(BID_RESPONSE_VIDEO_OUTSTREAM, request[0]); + expect(bids).to.have.lengthOf(1); + const bid = bids[0]; + expect(bid.cpm).to.equal(3); + expect(bid.vastUrl).to.equal('https://vast.smilewanted.com'); + expect(bid.renderer.url).to.equal('https://prebid.smilewanted.com/scripts_outstream/infeed.js'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.creativeId).to.equal('crea_sw_3'); + expect(bid.currency).to.equal('EUR'); + expect(bid.netRevenue).to.equal(true); + expect(bid.ttl).to.equal(300); + expect(bid.requestId).to.equal(VIDEO_OUTSTREAM_REQUEST[0].bidId); expect(function () { - spec.interpretResponse(BID_RESPONSE, { + spec.interpretResponse(BID_RESPONSE_VIDEO_OUTSTREAM, { data: 'invalid Json' }) }).to.not.throw(); @@ -155,7 +289,7 @@ describe('smilewantedBidAdapterTests', function () { }); it('SmileWanted - Verify if bid request valid', function () { - expect(spec.isBidRequestValid(DEFAULT_PARAMS[0])).to.equal(true); + expect(spec.isBidRequestValid(DISPLAY_REQUEST[0])).to.equal(true); expect(spec.isBidRequestValid({ params: { zoneId: 1234 @@ -173,14 +307,14 @@ describe('smilewantedBidAdapterTests', function () { it('SmileWanted - Verify user sync', function () { var syncs = spec.getUserSyncs({ iframeEnabled: true - }, [BID_RESPONSE]); + }, [BID_RESPONSE_DISPLAY]); expect(syncs).to.have.lengthOf(1); expect(syncs[0].type).to.equal('iframe'); expect(syncs[0].url).to.equal('https://csync.smilewanted.com'); syncs = spec.getUserSyncs({ iframeEnabled: false - }, [BID_RESPONSE]); + }, [BID_RESPONSE_DISPLAY]); expect(syncs).to.have.lengthOf(0); syncs = spec.getUserSyncs({ From ecd3815262661bb4e6186e6f6d79f21884e4746a Mon Sep 17 00:00:00 2001 From: dpapworth-qc <50959025+dpapworth-qc@users.noreply.github.com> Date: Fri, 9 Aug 2019 13:21:40 +0100 Subject: [PATCH 1417/1594] Fix for #4047 (#4063) * Changed isBidRequestValid to reject bid requests missing required parameters. * Filter outstream video bid requests. * Improved detection of different media types. Ignore all media types except instream video and banner. * Added test to confirm behaviour with multi-format request. * Removed unnecessary change to bid sizes. * Removed unused imports and tests. * Added log message for unsupported media types. --- modules/quantcastBidAdapter.js | 34 ++--- test/spec/modules/quantcastBidAdapter_spec.js | 131 +++++++++++------- 2 files changed, 100 insertions(+), 65 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 64cec7e231a..afe95ffb832 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -83,17 +83,7 @@ export const spec = { * @return boolean `true` is this is a valid bid, and `false` otherwise */ isBidRequestValid(bid) { - if (!bid) { - return false; - } - - const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (videoMediaType && context == 'outstream') { - return false; - } - - return true; + return !!bid.params.publisherId; }, /** @@ -112,12 +102,22 @@ export const spec = { const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href'); const domain = getDomain(page); - const bidRequestsList = bids.map(bid => { + let bidRequestsList = []; + + bids.forEach(bid => { let imp; - const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (videoContext === 'instream') { - imp = makeVideoImp(bid); + if (bid.mediaTypes) { + if (bid.mediaTypes.video && bid.mediaTypes.video.context === 'instream') { + imp = makeVideoImp(bid); + } else if (bid.mediaTypes.banner) { + imp = makeBannerImp(bid); + } else { + // Unsupported mediaType + utils.logInfo(`${BIDDER_CODE}: No supported mediaTypes found in ${JSON.stringify(bid.mediaTypes)}`); + return; + } } else { + // Parse as banner by default imp = makeBannerImp(bid); } @@ -143,11 +143,11 @@ export const spec = { : QUANTCAST_DOMAIN; const url = `${QUANTCAST_PROTOCOL}://${qcDomain}:${QUANTCAST_PORT}/qchb`; - return { + bidRequestsList.push({ data, method: 'POST', url - }; + }); }); return bidRequestsList; diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 662641de17b..e29a12a22be 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,6 +1,4 @@ -import * as utils from 'src/utils'; import { expect } from 'chai'; -import { stub, sandbox } from 'sinon'; import { QUANTCAST_DOMAIN, QUANTCAST_TEST_DOMAIN, @@ -13,11 +11,11 @@ import { } from '../../../modules/quantcastBidAdapter'; import { newBidder } from '../../../src/adapters/bidderFactory'; import { parse } from 'src/url'; -import * as ajax from 'src/ajax'; describe('Quantcast adapter', function () { const quantcastAdapter = newBidder(qcSpec); let bidRequest; + let bidderRequest; beforeEach(function () { bidRequest = { @@ -32,6 +30,13 @@ describe('Quantcast adapter', function () { }, sizes: [[300, 250]] }; + + bidderRequest = { + refererInfo: { + referer: 'http://example.com/hello.html', + canonicalUrl: 'http://example.com/hello.html' + } + }; }); function setupVideoBidRequest() { @@ -68,27 +73,25 @@ describe('Quantcast adapter', function () { }); describe('`isBidRequestValid`', function () { - it('should return `false` when bid is not passed', function () { - expect(qcSpec.isBidRequestValid()).to.equal(false); - }); - - it('should return `false` when bid is for outstream video', function () { + it('should return `true` when bid has publisherId', function () { const bidRequest = { - mediaType: 'video', - mediaTypes: { - video: { - context: 'outstream' - } + bidder: 'quantcast', + params: { + publisherId: 'my_publisher_id' } }; - expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); + expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return `true` when bid contains required params', function () { - const bidRequest = { mediaType: 'banner' }; + it('should return `false` when bid has no publisherId', function () { + const bidRequest = { + bidder: 'quantcast', + params: { + } + }; - expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); + expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); }); }); @@ -131,13 +134,6 @@ describe('Quantcast adapter', function () { }); it('sends banner bid requests contains all the required parameters', function () { - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/hello.html', - canonicalUrl: 'http://example.com/hello.html' - } - }; - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); const expectedBannerBidRequest = { publisherId: QUANTCAST_TEST_PUBLISHER, @@ -168,13 +164,6 @@ describe('Quantcast adapter', function () { it('sends video bid requests containing all the required parameters', function () { setupVideoBidRequest(); - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/hello.html', - canonicalUrl: 'http://example.com/hello.html' - } - }; - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); const expectedVideoBidRequest = { publisherId: QUANTCAST_TEST_PUBLISHER, @@ -213,6 +202,69 @@ describe('Quantcast adapter', function () { expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); }); + + it('ignores unsupported video bid requests', function () { + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [[550, 310]] + } + }; + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + + expect(requests).to.be.empty; + }); + + it('parses multi-format bid request', function () { + bidRequest.mediaTypes = { + banner: {sizes: [[300, 250], [728, 90], [250, 250], [468, 60], [320, 50]]}, + 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]} + }, + video: { + context: 'outstream', + playerSize: [[550, 310]] + } + }; + bidRequest.sizes = [[300, 250], [728, 90], [250, 250], [468, 60], [320, 50]]; + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + const expectedBidRequest = { + publisherId: QUANTCAST_TEST_PUBLISHER, + requestId: '2f7b179d443f14', + imp: [{ + banner: { + battr: [1, 2], + sizes: [ + {width: 300, height: 250}, + {width: 728, height: 90}, + {width: 250, height: 250}, + {width: 468, height: 60}, + {width: 320, height: 50} + ] + }, + placementCode: 'div-gpt-ad-1438287399331-0', + bidFloor: 1e-10 + }], + site: { + page: 'http://example.com/hello.html', + referrer: 'http://example.com/hello.html', + domain: 'example.com' + }, + bidId: '2f7b179d443f14', + gdprSignal: 0, + prebidJsVersion: '$prebid.version$' + }; + + expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); + }); }); it('propagates GDPR consent string and signal', function () { @@ -354,26 +406,9 @@ describe('Quantcast adapter', function () { body, headers: {} }; - const expectedResponse = []; const interpretedResponse = qcSpec.interpretResponse(response); expect(interpretedResponse.length).to.equal(0); }); }); - - // can't stub ajax with es6 anymore, need to fix this - // describe('`onTimeout`', function() { - // it('makes a request to the notify endpoint', function() { - // const sinonSandbox = sandbox.create(); - // const ajaxStub = sinonSandbox.stub(ajax, 'ajax').callsFake(function() {}); - // const timeoutData = { - // bidder: 'quantcast' - // }; - // qcSpec.onTimeout(timeoutData); - // const expectedUrl = `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb_notify?type=timeout`; - // ajaxStub.withArgs(expectedUrl, null, null).calledOnce.should.be.true; - // ajaxStub.restore(); - // sinonSandbox.restore(); - // }); - // }); }); From bad33585516f9afabf904532cfbb98156d3cb6fe Mon Sep 17 00:00:00 2001 From: Daniel McGraw Date: Fri, 9 Aug 2019 16:28:36 -0600 Subject: [PATCH 1418/1594] Clean up the 'Use case #2' example (#4068) --- modules/spotxBidAdapter.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/spotxBidAdapter.md b/modules/spotxBidAdapter.md index b9907e5bbd2..038c698a259 100644 --- a/modules/spotxBidAdapter.md +++ b/modules/spotxBidAdapter.md @@ -54,13 +54,12 @@ This adapter requires setup and approval from the SpotX team. ad_unit: 'outstream', outstream_options: { slot: 'adSlot1', - content_width: 300, - content_height: 250, custom_override: { // This option is not mandatory though used to override default renderer parameters using EASI player options in here: https://developer.spotxchange.com/content/local/docs/sdkDocs/EASI/README.md + content_width: 300, + content_height: 250, collapse: '1', hide_fullscreen: '1', unmute_on_mouse: '1', - click_to_replay: '1', continue_out_of_view: '1', ad_volume: '100', content_container_id: 'video1', From e6c819bb1f44b935fd689c32c6747e9f48eb54d9 Mon Sep 17 00:00:00 2001 From: Debbie Wang Date: Sun, 11 Aug 2019 07:56:33 -0700 Subject: [PATCH 1419/1594] referer changes (#4072) --- modules/gumgumBidAdapter.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 75ba5da4de9..557e23254de 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -14,7 +14,7 @@ let browserParams = {}; let pageViewId = null // TODO: potential 0 values for browserParams sent to ad server -function _getBrowserParams() { +function _getBrowserParams(topWindowUrl) { let topWindow let topScreen let topUrl @@ -41,7 +41,7 @@ function _getBrowserParams() { try { topWindow = global.top; topScreen = topWindow.screen; - topUrl = utils.getTopWindowUrl() + topUrl = topWindowUrl || utils.getTopWindowUrl(); } catch (error) { utils.logError(error); return browserParams @@ -145,7 +145,8 @@ function buildRequests (validBidRequests, bidderRequest) { params = {}, transactionId } = bidRequest; - const data = {} + const data = {}; + const topWindowUrl = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; if (pageViewId) { data.pv = pageViewId } @@ -178,7 +179,7 @@ function buildRequests (validBidRequests, bidderRequest) { sizes: bidRequest.sizes || bidRequest.mediatype[banner].sizes, url: BID_ENDPOINT, method: 'GET', - data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) + data: Object.assign(data, _getBrowserParams(topWindowUrl), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) }) }); return bids; From aa828d14525438faff6a6b3a57b9bdfac55376e5 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Sun, 11 Aug 2019 11:10:46 -0400 Subject: [PATCH 1420/1594] kargo adapter track request count (#4074) --- modules/kargoBidAdapter.js | 13 ++++++++++++- test/spec/modules/kargoBidAdapter_spec.js | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 74494ce66c9..7932822e90c 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -6,7 +6,9 @@ const HOST = 'https://krk.kargo.com'; const SYNC = 'https://crb.kargo.com/api/v1/initsyncrnd/{UUID}?seed={SEED}&idx={INDEX}'; const SYNC_COUNT = 5; -let sessionId; +let sessionId, + lastPageUrl, + requestCounter; export const spec = { code: BIDDER_CODE, @@ -31,6 +33,7 @@ export const spec = { } const transformedParams = Object.assign({}, { sessionId: spec._getSessionId(), + requestCount: spec._getRequestCount(), timeout: bidderRequest.timeout, currency: currency, cpmGranularity: 1, @@ -202,6 +205,14 @@ export const spec = { return sessionId; }, + _getRequestCount() { + if (lastPageUrl === window.location.pathname) { + return ++requestCounter; + } + lastPageUrl = window.location.pathname; + return requestCounter = 0; + }, + _generateRandomUuid() { try { // crypto.getRandomValues is supported everywhere but Opera Mini for years diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 7ff28a72c58..fd0e22b91b9 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -34,7 +34,7 @@ describe('kargo adapter tests', function () { }); describe('build request', function() { - var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = [], sessionIds = []; + var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = [], sessionIds = [], requestCount = 0; beforeEach(function () { undefinedCurrency = false; @@ -222,6 +222,7 @@ describe('kargo adapter tests', function () { function getExpectedKrakenParams(excludeUserIds, excludeKrux, expectedRawCRB, expectedRawCRBCookie) { var base = { timeout: 200, + requestCount: requestCount++, currency: 'USD', cpmGranularity: 1, timestamp: frozenNow.getTime(), From d6c394e8fadc699aaabf43e8c20d55cafed70e13 Mon Sep 17 00:00:00 2001 From: cdsmith16 <5227004+cdsmith16@users.noreply.github.com> Date: Sun, 11 Aug 2019 11:12:05 -0400 Subject: [PATCH 1421/1594] tlbidadapter missing semicolons (#4076) Fill in missing semicolons from TDID support update, which may be impacting TDID collection due to pb minification. Also updating for consistency with remainder of adapter. --- modules/tripleliftBidAdapter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index cd968475bd3..2d6b2dce8de 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -88,14 +88,14 @@ function _buildPostBody(bidRequests, bidderRequest) { banner: { format: _sizes(bid.sizes) } - } + }; }); - let eids = handleConsortiaUserIds(bidderRequest) + let eids = handleConsortiaUserIds(bidderRequest); if (eids.length > 0) { data.user = { ext: {eids} - } + }; } return data; @@ -126,7 +126,7 @@ function handleConsortiaUserIds(bidderRequest) { rtiPartner: 'TDID' } }] - }) + }); } return eids; From 8bd2ac08cfb1ac999fd4bd847dbdcf874fffb9bb Mon Sep 17 00:00:00 2001 From: Michael Kuryshev Date: Sun, 11 Aug 2019 17:14:37 +0200 Subject: [PATCH 1422/1594] VIS.X adapter: don't use utils.getTopWindowUrl() (#4078) --- modules/visxBidAdapter.js | 18 ++++++++----- test/spec/modules/visxBidAdapter_spec.js | 34 ++++++++++++++---------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 740c08111bc..2f9ec73c569 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -67,7 +67,6 @@ export const spec = { }); const payload = { - u: utils.getTopWindowUrl(), pt: 'net', auids: auids.join(','), sizes: utils.getKeys(sizeMap).join(','), @@ -77,13 +76,18 @@ export const spec = { wrapperVersion: '$prebid.version$' }; - if (bidderRequest && bidderRequest.gdprConsent) { - if (bidderRequest.gdprConsent.consentString) { - payload.gdpr_consent = bidderRequest.gdprConsent.consentString; + if (bidderRequest) { + if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + } + 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; } - payload.gdpr_applies = - (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') - ? Number(bidderRequest.gdprConsent.gdprApplies) : 1; } return { diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index aa9b2b553ed..09ce92479f9 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -40,6 +40,12 @@ describe('VisxAdapter', function () { }); describe('buildRequests', function () { + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; + const encodedReferrer = encodeURIComponent(bidderRequest.refererInfo.referer); let bidRequests = [ { 'bidder': 'visx', @@ -77,10 +83,10 @@ describe('VisxAdapter', function () { ]; it('should attach valid params to the tag', function () { - const request = spec.buildRequests([bidRequests[0]]); + const request = spec.buildRequests([bidRequests[0]], bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535'); expect(payload).to.have.property('sizes', '300x250,300x600'); @@ -89,10 +95,10 @@ describe('VisxAdapter', function () { }); it('sizes must not be duplicated', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -102,10 +108,10 @@ describe('VisxAdapter', function () { it('pt parameter must be "net" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -115,10 +121,10 @@ describe('VisxAdapter', function () { }); it('pt parameter must be "net" if params.priceType === "net"', function () { bidRequests[1].params.priceType = 'net'; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -129,10 +135,10 @@ describe('VisxAdapter', function () { it('pt parameter must be "net" if params.priceType === "undefined"', function () { bidRequests[1].params.priceType = 'undefined'; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -144,10 +150,10 @@ describe('VisxAdapter', function () { it('should add currency from currency.bidderCurrencyDefault', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'JPY' : 'USD'); - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -159,10 +165,10 @@ describe('VisxAdapter', function () { it('should add currency from currency.adServerCurrency', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? '' : 'USD'); - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); From 1f08933019dcc8ef8ba9005786280cd007e13d66 Mon Sep 17 00:00:00 2001 From: guiann Date: Sun, 11 Aug 2019 17:22:54 +0200 Subject: [PATCH 1423/1594] Multiple sizes handling in adYouLike adaptor (#4013) * Remove useless bidderCode in bid response * send all the available sizes in the bid request * Use the banner sizes if given * avoid compatibility issue with old bid format --- modules/adyoulikeBidAdapter.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index fd7a1697bac..12891b6e155 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -18,7 +18,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - const sizes = getSize(bid.sizes); + const sizes = getSize(getSizeArray(bid)); if (!bid.params || !bid.params.placement || !sizes.width || !sizes.height) { return false; } @@ -34,12 +34,14 @@ export const spec = { const payload = { Version: VERSION, Bids: bidRequests.reduce((accumulator, bid) => { - let size = getSize(bid.sizes); + let sizesArray = getSizeArray(bid); + let size = getSize(sizesArray); accumulator[bid.bidId] = {}; accumulator[bid.bidId].PlacementID = bid.params.placement; accumulator[bid.bidId].TransactionID = bid.transactionId; accumulator[bid.bidId].Width = size.width; accumulator[bid.bidId].Height = size.height; + accumulator[bid.bidId].AvaiableSizes = sizesArray.join(','); return accumulator; }, {}), PageRefreshed: getPageRefreshed() @@ -156,10 +158,20 @@ function createEndpointQS(bidderRequest) { return qs; } +function getSizeArray(bid) { + let inputSize = bid.sizes; + if (bid.mediaTypes && bid.mediaTypes.banner) { + inputSize = bid.mediaTypes.banner.sizes; + } + + return utils.parseSizesInput(inputSize); +} + /* Get parsed size from request size */ -function getSize(requestSizes) { +function getSize(sizesArray) { const parsed = {}; - const size = utils.parseSizesInput(requestSizes)[0]; + // the main requested size is the first one + const size = sizesArray[0]; if (typeof size !== 'string') { return parsed; From ec4a641b0971d011f4822c6d52d8310dfed5b8c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Mon, 12 Aug 2019 18:16:16 +0200 Subject: [PATCH 1424/1594] Criteo Adapter - Code cleaning & added missing tests to increase code coverage (#4073) --- modules/criteoBidAdapter.js | 79 ++++---- test/spec/modules/criteoBidAdapter_spec.js | 210 +++++++++++++++++++-- 2 files changed, 229 insertions(+), 60 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 56e22e45017..604278a14b9 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -8,15 +8,12 @@ import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -const ADAPTER_VERSION = 19; +export const ADAPTER_VERSION = 20; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; -const INTEGRATION_MODES = { - 'amp': 1, -}; const PROFILE_ID_INLINE = 207; -const PROFILE_ID_PUBLISHERTAG = 185; +export const PROFILE_ID_PUBLISHERTAG = 185; // Unminified source code can be found in: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js'; @@ -189,12 +186,12 @@ function buildContext(bidRequests) { url: url, debug: queryString['pbt_debug'] === '1', noLog: queryString['pbt_nolog'] === '1', - integrationMode: undefined, + amp: false, }; bidRequests.forEach(bidRequest => { - if (bidRequest.params.integrationMode) { - context.integrationMode = bidRequest.params.integrationMode; + if (bidRequest.params.integrationMode === 'amp') { + context.amp = true; } }) @@ -212,8 +209,8 @@ function buildCdbUrl(context) { url += '&wv=' + encodeURIComponent('$prebid.version$'); url += '&cb=' + String(Math.floor(Math.random() * 99999999999)); - if (context.integrationMode in INTEGRATION_MODES) { - url += '&im=' + INTEGRATION_MODES[context.integrationMode]; + if (context.amp) { + url += '&im=1'; } if (context.debug) { url += '&debug=1'; @@ -382,47 +379,37 @@ function createNativeAd(id, payload, callback) { `; } -export function cryptoVerify(key, hash, code) { - var jse = new JSEncrypt(); - jse.setPublicKey(key); - return jse.verify(code, hash, sha256); -} - -function validateFastBid(fastBid) { - // The value stored must contain the file's encrypted hash as first line - const firstLineEnd = fastBid.indexOf('\n'); - const firstLine = fastBid.substr(0, firstLineEnd).trim(); - if (firstLine.substr(0, 9) !== '// Hash: ') { - utils.logWarn('No hash found in FastBid'); - return false; - } - - // Remove the hash part from the locally stored value - const fileEncryptedHash = firstLine.substr(9); - const publisherTag = fastBid.substr(firstLineEnd + 1); - - // Verify the hash using cryptography - try { - return cryptoVerify(FAST_BID_PUBKEY, fileEncryptedHash, publisherTag); - } catch (e) { - utils.logWarn('Failed to verify Criteo FastBid'); - return undefined; - } -} - /** * @return {boolean} */ -function tryGetCriteoFastBid() { +export function tryGetCriteoFastBid() { try { - const fastBid = localStorage.getItem('criteo_fast_bid'); - if (fastBid !== null) { - if (validateFastBid(fastBid) === false) { - utils.logWarn('Invalid Criteo FastBid found'); - localStorage.removeItem('criteo_fast_bid'); + const fastBidStorageKey = 'criteo_fast_bid'; + const hashPrefix = '// Hash: '; + const fastBidFromStorage = localStorage.getItem(fastBidStorageKey); + + if (fastBidFromStorage !== null) { + // The value stored must contain the file's encrypted hash as first line + const firstLineEndPosition = fastBidFromStorage.indexOf('\n'); + const firstLine = fastBidFromStorage.substr(0, firstLineEndPosition).trim(); + + if (firstLine.substr(0, hashPrefix.length) !== hashPrefix) { + utils.logWarn('No hash found in FastBid'); + localStorage.removeItem(fastBidStorageKey); } else { - utils.logInfo('Using Criteo FastBid'); - eval(fastBid); // eslint-disable-line no-eval + // Remove the hash part from the locally stored value + const publisherTagHash = firstLine.substr(hashPrefix.length); + const publisherTag = fastBidFromStorage.substr(firstLineEndPosition + 1); + + var jsEncrypt = new JSEncrypt(); + jsEncrypt.setPublicKey(FAST_BID_PUBKEY); + if (jsEncrypt.verify(publisherTag, publisherTagHash, sha256)) { + utils.logInfo('Using Criteo FastBid'); + eval(publisherTag); // eslint-disable-line no-eval + } else { + utils.logWarn('Invalid Criteo FastBid found'); + localStorage.removeItem(fastBidStorageKey); + } } } } catch (e) { diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 4fe60bba17c..a6ba642cb6d 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter'; +import { tryGetCriteoFastBid, spec, PROFILE_ID_PUBLISHERTAG, ADAPTER_VERSION, PUBLISHER_TAG_URL } from 'modules/criteoBidAdapter'; import { createBid } from 'src/bidfactory'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; @@ -7,9 +7,17 @@ import { config } from '../../../src/config'; import { VIDEO } from '../../../src/mediaTypes'; describe('The Criteo bidding adapter', function () { + let utilsMock; + beforeEach(function () { - // Remove FastBid to avoid side effects. + // Remove FastBid to avoid side effects localStorage.removeItem('criteo_fast_bid'); + utilsMock = sinon.mock(utils); + }); + + afterEach(function() { + global.Criteo = undefined; + utilsMock.restore(); }); describe('isBidRequestValid', function () { @@ -360,7 +368,8 @@ describe('The Criteo bidding adapter', function () { }); describe('buildRequests', function () { - const bidderRequest = { timeout: 3000, + const bidderRequest = { + timeout: 3000, gdprConsent: { gdprApplies: 1, consentString: 'concentDataString', @@ -377,6 +386,9 @@ describe('The Criteo bidding adapter', function () { }); it('should properly build a zoneId request', function () { + const publisherUrl = 'https://criteo.com?pbt_debug=1&pbt_nolog=1'; + utilsMock.expects('getTopWindowUrl').withExactArgs().once().returns(publisherUrl); + const bidRequests = [ { bidder: 'criteo', @@ -385,14 +397,17 @@ describe('The Criteo bidding adapter', function () { sizes: [[728, 90]], params: { zoneId: 123, + publisherSubId: '123', + nativeCallback: function() {}, + integrationMode: 'amp' }, }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d+&im=1&debug=1&nolog=1/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; - expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.url).to.equal(publisherUrl); expect(ortbRequest.slots).to.have.lengthOf(1); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); @@ -794,20 +809,187 @@ describe('The Criteo bidding adapter', function () { }); }); - describe('cryptoVerify', function () { - const TEST_HASH = 'vBeD8Q7GU6lypFbzB07W8hLGj7NL+p7dI9ro2tCxkrmyv0F6stNuoNd75Us33iNKfEoW+cFWypelr6OJPXxki2MXWatRhJuUJZMcK4VBFnxi3Ro+3a0xEfxE4jJm4eGe98iC898M+/YFHfp+fEPEnS6pEyw124ONIFZFrcejpHU='; + describe('tryGetCriteoFastBid', function () { + const VALID_HASH = 'vBeD8Q7GU6lypFbzB07W8hLGj7NL+p7dI9ro2tCxkrmyv0F6stNuoNd75Us33iNKfEoW+cFWypelr6OJPXxki2MXWatRhJuUJZMcK4VBFnxi3Ro+3a0xEfxE4jJm4eGe98iC898M+/YFHfp+fEPEnS6pEyw124ONIFZFrcejpHU='; + const INVALID_HASH = 'invalid'; + const VALID_PUBLISHER_TAG = 'test'; + const INVALID_PUBLISHER_TAG = 'test invalid'; + + const FASTBID_LOCAL_STORAGE_KEY = 'criteo_fast_bid'; + + it('should verify valid hash with valid publisher tag', function () { + localStorage.setItem(FASTBID_LOCAL_STORAGE_KEY, '// Hash: ' + VALID_HASH + '\n' + VALID_PUBLISHER_TAG); + + utilsMock.expects('logInfo').withExactArgs('Using Criteo FastBid').once(); + utilsMock.expects('logWarn').withExactArgs('No hash found in FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Criteo FastBid found').never(); + + tryGetCriteoFastBid(); + + expect(localStorage.getItem(FASTBID_LOCAL_STORAGE_KEY)).to.equals('// Hash: ' + VALID_HASH + '\n' + VALID_PUBLISHER_TAG); + utilsMock.verify(); + }); + + it('should verify valid hash with invalid publisher tag', function () { + localStorage.setItem(FASTBID_LOCAL_STORAGE_KEY, '// Hash: ' + VALID_HASH + '\n' + INVALID_PUBLISHER_TAG); + + utilsMock.expects('logInfo').withExactArgs('Using Criteo FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Criteo FastBid found').once(); + + tryGetCriteoFastBid(); + + expect(localStorage.getItem(FASTBID_LOCAL_STORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + + it('should verify invalid hash with valid publisher tag', function () { + localStorage.setItem(FASTBID_LOCAL_STORAGE_KEY, '// Hash: ' + INVALID_HASH + '\n' + VALID_PUBLISHER_TAG); + + utilsMock.expects('logInfo').withExactArgs('Using Criteo FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Criteo FastBid found').once(); + + tryGetCriteoFastBid(); + + expect(localStorage.getItem(FASTBID_LOCAL_STORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + + it('should verify missing hash', function () { + localStorage.setItem(FASTBID_LOCAL_STORAGE_KEY, VALID_PUBLISHER_TAG); + + utilsMock.expects('logInfo').withExactArgs('Using Criteo FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in FastBid').once(); + utilsMock.expects('logWarn').withExactArgs('Invalid Criteo FastBid found').never(); + + tryGetCriteoFastBid(); + + expect(localStorage.getItem(FASTBID_LOCAL_STORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + }); + + describe('when pubtag prebid adapter is available', function () { + it('should forward response to pubtag when calling interpretResponse', () => { + const response = {}; + const request = {}; + + const adapter = { interpretResponse: function() {} }; + const adapterMock = sinon.mock(adapter); + adapterMock.expects('interpretResponse').withExactArgs(response, request).once().returns('ok'); + const prebidAdapter = { GetAdapter: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('GetAdapter').withExactArgs(request).once().returns(adapter); + + global.Criteo = { + PubTag: { + Adapters: { + Prebid: prebidAdapter + } + } + }; + + expect(spec.interpretResponse(response, request)).equal('ok'); + adapterMock.verify(); + prebidAdapterMock.verify(); + }); + + it('should forward bid to pubtag when calling onBidWon', () => { + const bid = { auctionId: 123 }; + + const adapter = { handleBidWon: function() {} }; + const adapterMock = sinon.mock(adapter); + adapterMock.expects('handleBidWon').withExactArgs(bid).once(); + const prebidAdapter = { GetAdapter: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('GetAdapter').withExactArgs(bid.auctionId).once().returns(adapter); + + global.Criteo = { + PubTag: { + Adapters: { + Prebid: prebidAdapter + } + } + }; - it('should verify right signature', function () { - expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test')).to.equal(true); + spec.onBidWon(bid); + adapterMock.verify(); + prebidAdapterMock.verify(); }); - it('should verify wrong signature', function () { - expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test wrong')).to.equal(false); + it('should forward bid to pubtag when calling onSetTargeting', () => { + const bid = { auctionId: 123 }; + + const adapter = { handleSetTargeting: function() {} }; + const adapterMock = sinon.mock(adapter); + adapterMock.expects('handleSetTargeting').withExactArgs(bid).once(); + const prebidAdapter = { GetAdapter: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('GetAdapter').withExactArgs(bid.auctionId).once().returns(adapter); + + global.Criteo = { + PubTag: { + Adapters: { + Prebid: prebidAdapter + } + } + }; + + spec.onSetTargeting(bid); + adapterMock.verify(); + prebidAdapterMock.verify(); }); - it('should return undefined with incompatible browsers', function () { - // Here use a null hash to make the call to crypto library fail and simulate a browser failure - expect(cryptoVerify(FAST_BID_PUBKEY, null, 'test')).to.be.false; + it('should forward bid to pubtag when calling onTimeout', () => { + const timeoutData = { auctionId: 123 }; + + const adapter = { handleBidTimeout: function() {} }; + const adapterMock = sinon.mock(adapter); + adapterMock.expects('handleBidTimeout').once(); + const prebidAdapter = { GetAdapter: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('GetAdapter').withExactArgs(timeoutData.auctionId).once().returns(adapter); + + global.Criteo = { + PubTag: { + Adapters: { + Prebid: prebidAdapter + } + } + }; + + spec.onTimeout(timeoutData); + adapterMock.verify(); + prebidAdapterMock.verify(); + }); + + it('should return a POST method with url & data from pubtag', () => { + const bidRequests = { }; + const bidderRequest = { }; + + 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 adaptersMock = sinon.mock(adapters); + adaptersMock.expects('Prebid').withExactArgs(PROFILE_ID_PUBLISHERTAG, ADAPTER_VERSION, bidRequests, bidderRequest, '$prebid.version$').once().returns(prebidAdapter); + + global.Criteo = { + PubTag: { + Adapters: adapters + } + }; + + const buildRequestsResult = spec.buildRequests(bidRequests, bidderRequest); + expect(buildRequestsResult.method).equal('POST'); + expect(buildRequestsResult.url).equal('cdbUrl'); + expect(buildRequestsResult.data).equal('cdbRequest'); + + adaptersMock.verify(); + prebidAdapterMock.verify(); }); }); }); From 0bd5d61f64545656c2dd3c183318dc68fa9f584e Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 13 Aug 2019 06:30:25 -0600 Subject: [PATCH 1425/1594] update to use dlv/index to fix webpack sourcemaps (#4071) --- src/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index 6f592a8bcfe..335cf8dbf68 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,7 +5,7 @@ import includes from 'core-js/library/fn/array/includes'; import { parse } from './url'; const CONSTANTS = require('./constants'); -export { default as deepAccess } from 'dlv'; +export { default as deepAccess } from 'dlv/index'; export { default as deepSetValue } from 'dset'; var tArr = 'Array'; From f4db14caef775da63d9445b94cd3d951ddc0036c Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Tue, 13 Aug 2019 13:34:15 -0400 Subject: [PATCH 1426/1594] Yieldmo unified id (#4041) * update maintainer email * Add TTD unified id * Remove console.log * Remove trailing spaces --- modules/yieldmoBidAdapter.js | 22 ++++++++++++----- modules/yieldmoBidAdapter.md | 1 - test/spec/modules/yieldmoBidAdapter_spec.js | 26 +++++++++++++++++++-- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 299baf49042..fd09cbaa4ea 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -43,7 +43,7 @@ export const spec = { bidRequests.forEach((request) => { serverRequest.p.push(addPlacement(request)); - const pubcid = getPubcId(request) + const pubcid = getId(request, 'pubcid'); if (pubcid) { serverRequest.pubcid = pubcid; } else if (request.crumbs) { @@ -51,6 +51,10 @@ export const spec = { serverRequest.pubcid = request.crumbs.pubcid; } } + const tdid = getId(request, 'tdid'); + if (tdid) { + serverRequest.tdid = tdid; + } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { @@ -317,10 +321,16 @@ function isMraid() { return !!(window.mraid); } -function getPubcId(request) { - let pubcid; - if (request && request.userId && request.userId.pubcid && typeof request.userId === 'object') { - pubcid = request.userId.pubcid; +/** + * Gets an id from the userId object if it exists + * @param {*} request + * @param {*} idType + * @returns an id if there is one, or undefined + */ +function getId(request, idType) { + let id; + if (request && request.userId && request.userId[idType] && typeof request.userId === 'object') { + id = request.userId[idType]; } - return pubcid; + return id; } diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index 7221f2ebdd0..d1e34a41ecb 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -4,7 +4,6 @@ Module Name: Yieldmo Bid Adapter Module Type: Bidder Adapter Maintainer: opensource@yieldmo.com -Note: Our ads will only render in mobile ``` # Description diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 2a94dc7e5c9..60fe25db95e 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -7,6 +7,8 @@ describe('YieldmoAdapter', function () { const adapter = newBidder(spec); const ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; + let tdid = '8d146286-91d4-4958-aff4-7e489dd1abd6'; + let bid = { bidder: 'yieldmo', params: { @@ -19,6 +21,9 @@ describe('YieldmoAdapter', function () { auctionId: '1d1a030790a475', crumbs: { pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' + }, + userId: { + tdid, } }; let bidArray = [bid]; @@ -109,7 +114,7 @@ describe('YieldmoAdapter', function () { expect(data.hasOwnProperty('h')).to.be.true; expect(data.hasOwnProperty('w')).to.be.true; expect(data.hasOwnProperty('pubcid')).to.be.true; - }) + }); it('should add pubcid as parameter of request', function () { const pubcidBid = { @@ -126,7 +131,24 @@ describe('YieldmoAdapter', function () { }; const data = spec.buildRequests([pubcidBid]).data; expect(data.pubcid).to.deep.equal('c604130c-0144-4b63-9bf2-c2bd8c8d86da2'); - }) + }); + + it('should add unified id as parameter of request', function () { + const unifiedIdBid = { + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + userId: { + tdid, + } + }; + const data = spec.buildRequests([unifiedIdBid]).data; + expect(data.tdid).to.deep.equal(tdid); + }); }); describe('interpretResponse', function () { From 051180759ac3316728d4e318f1bccaacb6f14a61 Mon Sep 17 00:00:00 2001 From: "Evgen A. Epanchin" Date: Tue, 13 Aug 2019 23:42:06 +0300 Subject: [PATCH 1427/1594] Add video support to LoopMe adapter (#4079) --- modules/loopmeBidAdapter.js | 64 ++++++++++++-- modules/loopmeBidAdapter.md | 21 ++++- test/spec/modules/loopmeBidAdapter_spec.js | 98 ++++++++++++++++++---- 3 files changed, 158 insertions(+), 25 deletions(-) diff --git a/modules/loopmeBidAdapter.js b/modules/loopmeBidAdapter.js index fcfe1fd0687..dd0c7e38553 100644 --- a/modules/loopmeBidAdapter.js +++ b/modules/loopmeBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER } from '../src/mediaTypes'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import { Renderer } from '../src/Renderer'; const LOOPME_ENDPOINT = 'https://loopme.me/api/hb'; @@ -16,7 +17,7 @@ const entries = (obj) => { export const spec = { code: 'loopme', - supportedMediaTypes: [BANNER], + supportedMediaTypes: [BANNER, VIDEO], /** * @param {object} bid * @return boolean @@ -46,14 +47,17 @@ export const spec = { .map(item => `${item[0]}=${encodeURI(item[1])}`) .join('&'); + const adUnitSizes = bidRequest.mediaTypes[BANNER] + ? utils.getAdUnitSizes(bidRequest) + : utils.deepAccess(bidRequest.mediaTypes, 'video.playerSize'); + const sizes = '&sizes=' + - utils - .getAdUnitSizes(bidRequest) + adUnitSizes .map(size => `${size[0]}x${size[1]}`) .join('&sizes='); - queryString = `${queryString}${sizes}`; + queryString = `${queryString}${sizes}${bidRequest.mediaTypes[VIDEO] ? '&media_type=video' : ''}`; return { method: 'GET', @@ -71,14 +75,58 @@ export const spec = { */ interpretResponse: function(response = {}, bidRequest) { const responseObj = response.body; + if ( + responseObj === null || + typeof responseObj !== 'object' + ) { + return []; + } if ( - responseObj == null || - typeof responseObj !== 'object' || - !responseObj.hasOwnProperty('ad') + !responseObj.hasOwnProperty('ad') && + !responseObj.hasOwnProperty('vastUrl') ) { return []; } + // responseObj.vastUrl = 'https://rawgit.com/InteractiveAdvertisingBureau/VAST_Samples/master/VAST%201-2.0%20Samples/Inline_NonLinear_Verification_VAST2.0.xml'; + if (responseObj.vastUrl) { + const renderer = Renderer.install({ + id: bidRequest.bidId, + url: 'https://i.loopme.me/html/vast/loopme_flex.js', + loaded: false + }); + renderer.setRender((bid) => { + renderer.push(function () { + var adverts = [{ + 'type': 'VAST', + 'url': bid.vastUrl, + 'autoClose': -1 + }]; + var config = { + containerId: bid.adUnitCode, + vastTimeout: 250, + ads: adverts, + user_consent: '%%USER_CONSENT%%', + }; + window.L.flex.loader.load(config); + }) + }); + return [ + { + requestId: bidRequest.bidId, + cpm: responseObj.cpm, + width: responseObj.width, + height: responseObj.height, + ttl: responseObj.ttl, + currency: responseObj.currency, + creativeId: responseObj.creativeId, + dealId: responseObj.dealId, + netRevenue: responseObj.netRevenue, + vastUrl: responseObj.vastUrl, + renderer + } + ]; + } return [ { diff --git a/modules/loopmeBidAdapter.md b/modules/loopmeBidAdapter.md index be8c20cfade..1b195a118f2 100644 --- a/modules/loopmeBidAdapter.md +++ b/modules/loopmeBidAdapter.md @@ -10,7 +10,7 @@ Maintainer: support@loopme.com Connect to LoopMe's exchange for bids. -# Test Parameters +# Test Parameters (Banner) ``` var adUnits = [{ code: 'test-div', @@ -27,3 +27,22 @@ var adUnits = [{ }] }]; ``` + +# Test Parameters (Video) +``` +var adUnits = [{ + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream' + } + }, + bids: [{ + bidder: 'loopme', + params: { + ak: '223051e07f' + } + }] +}]; +``` diff --git a/test/spec/modules/loopmeBidAdapter_spec.js b/test/spec/modules/loopmeBidAdapter_spec.js index 6d612746299..0d7e71c22db 100644 --- a/test/spec/modules/loopmeBidAdapter_spec.js +++ b/test/spec/modules/loopmeBidAdapter_spec.js @@ -15,37 +15,71 @@ describe('LoopMeAdapter', function () { }, adUnitCode: 'ad-1', bidId: '2652ca954bce9' - }]; + }, { + bidder: 'loopme', + params: { + ak: 'b510d5bcda' + }, + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'outstream' + } + }, + adUnitCode: 'ad-1', + bidId: '2652ca954bce9' + } + ]; describe('isBidRequestValid', function () { it('should return true if the ak parameter is present', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.be.true; + expect(spec.isBidRequestValid(bidRequests[1])).to.be.true; }); it('should return false if the ak parameter is not present', function () { - let bidRequest = utils.deepClone(bidRequests[0]); - delete bidRequest.params.ak; - expect(spec.isBidRequestValid(bidRequest)).to.be.false; + let bannerBidRequest = utils.deepClone(bidRequests[0]); + delete bannerBidRequest.params.ak; + expect(spec.isBidRequestValid(bannerBidRequest)).to.be.false; + + let videoBidRequest = utils.deepClone(bidRequests[1]); + delete videoBidRequest.params.ak; + expect(spec.isBidRequestValid(videoBidRequest)).to.be.false; }); it('should return false if the params object is not present', function () { - let bidRequest = utils.deepClone(bidRequests); - delete bidRequest[0].params; - expect(spec.isBidRequestValid(bidRequest)).to.be.false; + let bannerBidRequest = utils.deepClone(bidRequests)[0]; + delete bannerBidRequest.params; + expect(spec.isBidRequestValid(bannerBidRequest)).to.be.false; + + let videoBidRequest = utils.deepClone(bidRequests)[1]; + delete videoBidRequest.params; + expect(spec.isBidRequestValid(videoBidRequest)).to.be.false; }); }); describe('buildRequests', function () { it('should generate a valid single GET request for multiple bid requests', function () { - const request = spec.buildRequests(bidRequests)[0]; - expect(request.method).to.equal('GET'); - expect(request.url).to.equal('https://loopme.me/api/hb'); - expect(request.bidId).to.equal('2652ca954bce9'); - expect(request.data).to.exist; + const bannerRequest = spec.buildRequests(bidRequests)[0]; + expect(bannerRequest.method).to.equal('GET'); + expect(bannerRequest.url).to.equal('https://loopme.me/api/hb'); + expect(bannerRequest.bidId).to.equal('2652ca954bce9'); + expect(bannerRequest.data).to.exist; - const requestData = request.data; - expect(requestData).to.contain('ak=b510d5bcda'); - expect(requestData).to.contain('sizes=300x250'); + const bannerRequestData = bannerRequest.data; + expect(bannerRequestData).to.contain('ak=b510d5bcda'); + expect(bannerRequestData).to.contain('sizes=300x250'); + + const videoRequest = spec.buildRequests(bidRequests)[1]; + expect(videoRequest.method).to.equal('GET'); + expect(videoRequest.url).to.equal('https://loopme.me/api/hb'); + expect(videoRequest.bidId).to.equal('2652ca954bce9'); + expect(videoRequest.data).to.exist; + + const videoRquestData = videoRequest.data; + expect(videoRquestData).to.contain('ak=b510d5bcda'); + expect(videoRquestData).to.contain('sizes=640x480'); + expect(videoRquestData).to.contain('media_type=video'); }); it('should add GDPR data to request if available', function () { @@ -67,7 +101,7 @@ describe('LoopMeAdapter', function () { expect(interpretedResponse).to.be.an('array').that.is.empty; }); - it('should return valid response when passed valid server response', function () { + xit('should return valid response when passed valid server response', function () { const serverResponse = { body: { 'requestId': '2652ca954bce9', @@ -97,5 +131,37 @@ describe('LoopMeAdapter', function () { expect(interpretedResponse[0].ad).to.equal(serverResponse.body.ad); expect(interpretedResponse[0].ttl).to.equal(serverResponse.body.ttl); }); + + it('should return valid VAST response when passed valid server response', function () { + const serverResponse = { + body: { + 'requestId': '2652ca954bce9', + 'cpm': 1, + 'width': 640, + 'height': 480, + 'creativeId': '20154', + 'currency': 'USD', + 'netRevenue': false, + 'ttl': 360, + 'vastUrl': 'https://loopme.me/ads/vast?ak=cc885e3acc' + } + }; + + const request = spec.buildRequests(bidRequests)[1]; + const interpretedResponse = spec.interpretResponse(serverResponse, request); + + expect(interpretedResponse).to.have.lengthOf(1); + + expect(interpretedResponse[0].requestId).to.equal(serverResponse.body.requestId); + expect(interpretedResponse[0].cpm).to.equal(serverResponse.body.cpm); + expect(interpretedResponse[0].width).to.equal(serverResponse.body.width); + expect(interpretedResponse[0].height).to.equal(serverResponse.body.height); + expect(interpretedResponse[0].creativeId).to.equal(serverResponse.body.creativeId); + expect(interpretedResponse[0].currency).to.equal(serverResponse.body.currency); + expect(interpretedResponse[0].netRevenue).to.equal(serverResponse.body.netRevenue); + expect(interpretedResponse[0].vastUrl).to.equal(serverResponse.body.vastUrl); + expect(interpretedResponse[0].ttl).to.equal(serverResponse.body.ttl); + expect(interpretedResponse[0].renderer).to.have.property('render'); + }); }); }); From 74a6ea5ebfaff20f9a7e9017279ce0fca3012aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Thu, 15 Aug 2019 17:34:05 +0200 Subject: [PATCH 1428/1594] Criteo Adapter - Added support of deals (#4085) --- modules/criteoBidAdapter.js | 1 + test/spec/modules/criteoBidAdapter_spec.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 604278a14b9..559c02cd4a9 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -120,6 +120,7 @@ export const spec = { creativeId: bidId, width: slot.width, height: slot.height, + dealId: slot.dealCode, } if (slot.native) { bid.ad = createNativeAd(bidId, slot.native, bidRequest.params.nativeCallback); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index a6ba642cb6d..f85e5957950 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -656,6 +656,7 @@ describe('The Criteo bidding adapter', function () { creative: 'test-ad', width: 728, height: 90, + dealCode: 'myDealCode', }], }, }; @@ -675,6 +676,7 @@ describe('The Criteo bidding adapter', function () { expect(bids[0].ad).to.equal('test-ad'); expect(bids[0].width).to.equal(728); expect(bids[0].height).to.equal(90); + expect(bids[0].dealId).to.equal('myDealCode'); }); it('should properly parse a bid responsewith with a zoneId', function () { From 874b99cad668806d032f298ff7631d5eb125bc56 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Thu, 15 Aug 2019 14:06:11 -0400 Subject: [PATCH 1429/1594] 2.28.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b8062204ce1..1a9547a3da2 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.28.0-pre", + "version": "2.28.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From c1aa4e4068e9a92c33be2c64cd6026ada676fc59 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Thu, 15 Aug 2019 14:16:07 -0400 Subject: [PATCH 1430/1594] 2.29.0-pre --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a9547a3da2..da9bdf63507 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.28.0", + "version": "2.29.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d61756d82bc21870e2b8ad6e784026af62fc89d4 Mon Sep 17 00:00:00 2001 From: SublimeJeremy Date: Fri, 16 Aug 2019 19:53:17 +0200 Subject: [PATCH 1431/1594] Add bid adapter for Sublime (#3960) * Add bid adapter for Sublime * Fix tests for sublimeBidAdapter * Fix tests for sublimeBidAdapter * fix(sublime-adapter): fixes to submit sublimePrebidAdapter * fix(sublime-adapter): fixes to submit sublimePrebidAdapter * Remove callback and fix tests * Update adapter to version 0.4.0 - Support of multiple bid request - Remove pixel call - Remove tag - Refactor - Update test * Rearrange constant and import alphabetically * sublimeBidAdapter: remove deprecated method getTopWindowUrl --- modules/sublimeBidAdapter.js | 135 +++++++++++ modules/sublimeBidAdapter.md | 62 +++++ test/spec/modules/sublimeBidAdapter_spec.js | 255 ++++++++++++++++++++ 3 files changed, 452 insertions(+) create mode 100644 modules/sublimeBidAdapter.js create mode 100644 modules/sublimeBidAdapter.md create mode 100644 test/spec/modules/sublimeBidAdapter_spec.js diff --git a/modules/sublimeBidAdapter.js b/modules/sublimeBidAdapter.js new file mode 100644 index 00000000000..fce3df7675b --- /dev/null +++ b/modules/sublimeBidAdapter.js @@ -0,0 +1,135 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; + +const BIDDER_CODE = 'sublime'; +const DEFAULT_BID_HOST = 'pbjs.sskzlabs.com'; +const DEFAULT_CURRENCY = 'EUR'; +const DEFAULT_PROTOCOL = 'https'; +const DEFAULT_TTL = 600; +const SUBLIME_VERSION = '0.4.0'; + +export const spec = { + code: BIDDER_CODE, + aliases: [], + + /** + * 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) => { + return !!bid.params.zoneId; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests An array of bids + * @param {Object} bidderRequest - Info describing the request to the server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: (validBidRequests, bidderRequest) => { + let commonPayload = { + sublimeVersion: SUBLIME_VERSION, + // Current Prebid params + prebidVersion: '$prebid.version$', + currencyCode: config.getConfig('currency.adServerCurrency') || DEFAULT_CURRENCY, + timeout: config.getConfig('bidderTimeout'), + }; + + // RefererInfo + if (bidderRequest && bidderRequest.refererInfo) { + commonPayload.referer = bidderRequest.refererInfo.referer; + commonPayload.numIframes = bidderRequest.refererInfo.numIframes; + } + // GDPR handling + if (bidderRequest && bidderRequest.gdprConsent) { + commonPayload.gdprConsent = bidderRequest.gdprConsent.consentString; + commonPayload.gdpr = bidderRequest.gdprConsent.gdprApplies; // we're handling the undefined case server side + } + + return validBidRequests.map(bid => { + let bidPayload = { + adUnitCode: bid.adUnitCode, + auctionId: bid.auctionId, + bidder: bid.bidder, + bidderRequestId: bid.bidderRequestId, + bidRequestsCount: bid.bidRequestsCount, + requestId: bid.bidId, + sizes: bid.sizes.map(size => ({ + w: size[0], + h: size[1], + })), + transactionId: bid.transactionId, + zoneId: bid.params.zoneId, + }; + + let protocol = bid.params.protocol || DEFAULT_PROTOCOL; + let bidHost = bid.params.bidHost || DEFAULT_BID_HOST; + let payload = Object.assign({}, commonPayload, bidPayload); + + return { + method: 'POST', + url: protocol + '://' + bidHost + '/bid', + data: payload, + options: { + contentType: 'application/json', + withCredentials: true + }, + }; + }); + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param {*} bidRequest An object with bid request informations + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: (serverResponse, bidRequest) => { + const bidResponses = []; + const response = serverResponse.body; + + if (response) { + if (response.timeout || !response.ad || response.ad.match(//gmi)) { + return bidResponses; + } + + // Setting our returned sizes object to default values + let returnedSizes = { + width: 1800, + height: 1000 + }; + + // Verifying Banner sizes + if (bidRequest && bidRequest.data && bidRequest.data.w === 1 && bidRequest.data.h === 1) { + // If banner sizes are 1x1 we set our default size object to 1x1 + returnedSizes = { + width: 1, + height: 1 + }; + } + + const bidResponse = { + requestId: response.requestId || '', + cpm: response.cpm || 0, + width: response.width || returnedSizes.width, + height: response.height || returnedSizes.height, + creativeId: response.creativeId || 1, + dealId: response.dealId || 1, + currency: response.currency || DEFAULT_CURRENCY, + netRevenue: response.netRevenue || true, + ttl: response.ttl || DEFAULT_TTL, + ad: response.ad, + }; + + bidResponses.push(bidResponse); + } + + return bidResponses; + }, +}; + +registerBidder(spec); diff --git a/modules/sublimeBidAdapter.md b/modules/sublimeBidAdapter.md new file mode 100644 index 00000000000..e57f4a1fdb0 --- /dev/null +++ b/modules/sublimeBidAdapter.md @@ -0,0 +1,62 @@ +# Overview + +``` +Module Name: Sublime Bid Adapter +Module Type: Bidder Adapter +Maintainer: pbjs@sublimeskinz.com +``` + +# Description + +Connects to Sublime for bids. +Sublime bid adapter supports Skinz and M-Skinz formats. + +# Nota Bene + +Our prebid adapter is unusable with SafeFrame. + +# Build + +You can build your version of prebid.js, execute: + +```shell +gulp build --modules=sublimeBidAdapter +``` + +Or to build with multiple adapters + +```shell +gulp build --modules=sublimeBidAdapter,secondAdapter,thirdAdapter +``` + +More details in the root [README](../README.md#Build) + +## To build from you own repository + +- copy `/modules/sublimeBidAdapter.js` to your `/modules/` directory +- copy `/modules/sublimeBidAdapter.md` to your `/modules/` directory +- copy `/test/spec/modules/sublimeBidAdapter_spec.js` to your `/test/spec/modules/` directory + +Then build + + +# Invocation Parameters + +```js +var adUnits = [{ + code: 'sublime', + mediaTypes: { + banner: { + sizes: [1800, 1000] + } + }, + bids: [{ + bidder: 'sublime', + params: { + zoneId: + } + }] +}]; +``` + +Where you replace `` by your Sublime Zone id diff --git a/test/spec/modules/sublimeBidAdapter_spec.js b/test/spec/modules/sublimeBidAdapter_spec.js new file mode 100644 index 00000000000..45173b09953 --- /dev/null +++ b/test/spec/modules/sublimeBidAdapter_spec.js @@ -0,0 +1,255 @@ +import { expect } from 'chai'; +import { spec } from 'modules/sublimeBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('Sublime Adapter', 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: 'sublime', + params: { + zoneId: 24549, + endpoint: '', + }, + }; + + 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); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function() { + let bidRequests = [ + { + bidder: 'sublime', + adUnitCode: 'sublime_code', + bidId: 'abc1234', + sizes: [[1800, 1000], [640, 300]], + requestId: 'xyz654', + params: { + zoneId: 123, + callbackName: 'false' + } + }, { + bidder: 'sublime', + adUnitCode: 'sublime_code_2', + bidId: 'abc1234_2', + sizes: [[1, 1]], + requestId: 'xyz654_2', + params: { + zoneId: 456, + } + } + ]; + + let bidderRequest = { + gdprConsent: { + consentString: 'EOHEIRCOUCOUIEHZIOEIU-TEST', + gdprApplies: true + }, + refererInfo: { + referer: 'https://example.com', + numIframes: 2, + } + }; + + let request = spec.buildRequests(bidRequests, bidderRequest); + + it('should have a post method', function() { + 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() { + expect(request[0].data.requestId).to.equal(bidRequests[0].bidId); + expect(request[1].data.requestId).to.equal(bidRequests[1].bidId); + }); + + it('should have an url that contains bid keyword', function() { + expect(request[0].url).to.match(/bid/); + expect(request[1].url).to.match(/bid/); + }); + }); + + describe('buildRequests: default arguments', function() { + let bidRequests = [{ + bidder: 'sublime', + adUnitCode: 'sublime_code', + bidId: 'abc1234', + sizes: [[1800, 1000], [640, 300]], + requestId: 'xyz654', + params: { + zoneId: 123 + } + }]; + + let request = spec.buildRequests(bidRequests); + + it('should have an url that match the default endpoint', function() { + expect(request[0].url).to.equal('https://pbjs.sskzlabs.com/bid'); + }); + }); + + describe('interpretResponse', function() { + let serverResponse = { + 'request_id': '3db3773286ee59', + 'cpm': 0.5, + 'ad': '', + }; + + it('should get correct bid response', function() { + // Mock the fire method + top.window.sublime = { + analytics: { + fire: function() {} + } + }; + + let expectedResponse = [ + { + requestId: '', + cpm: 0.5, + width: 1800, + height: 1000, + creativeId: 1, + dealId: 1, + currency: 'USD', + netRevenue: true, + ttl: 600, + ad: '', + }, + ]; + let result = spec.interpretResponse({body: serverResponse}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('should get correct default size for 1x1', function() { + let serverResponse = { + 'requestId': 'xyz654_2', + 'cpm': 0.5, + 'ad': '', + }; + + let bidRequest = { + bidder: 'sublime', + adUnitCode: 'sublime_code_2', + bidId: 'abc1234_2', + data: { + w: 1, + h: 1, + }, + requestId: 'xyz654_2', + params: { + zoneId: 456, + } + }; + + let result = spec.interpretResponse({body: serverResponse}, bidRequest); + + let expectedResponse = { + requestId: 'xyz654_2', + cpm: 0.5, + width: 1, + height: 1, + creativeId: 1, + dealId: 1, + currency: 'EUR', + netRevenue: true, + ttl: 600, + ad: '', + }; + + expect(result[0]).to.deep.equal(expectedResponse); + }); + + it('should return bid empty response', function () { + let serverResponse = ''; + let bidRequest = {}; + + let result = spec.interpretResponse({ body: serverResponse }, bidRequest); + + let expectedResponse = []; + + expect(result).to.deep.equal(expectedResponse); + }); + + it('should return bid with default value in response', function () { + let serverResponse = { + 'requestId': 'xyz654_2', + 'ad': '', + }; + + let bidRequest = { + bidder: 'sublime', + adUnitCode: 'sublime_code_2', + bidId: 'abc1234_2', + data: { + w: 1, + h: 1, + }, + requestId: 'xyz654_2', + params: { + zoneId: 456, + } + }; + + let result = spec.interpretResponse({ body: serverResponse }, bidRequest); + + let expectedResponse = { + requestId: 'xyz654_2', + cpm: 0, + width: 1, + height: 1, + creativeId: 1, + dealId: 1, + currency: 'EUR', + netRevenue: true, + ttl: 600, + ad: '', + }; + + expect(result[0]).to.deep.equal(expectedResponse); + }); + + it('should return empty bid response because of timeout', function () { + let serverResponse = { + 'requestId': 'xyz654_2', + 'timeout': true, + 'ad': '', + }; + + let bidRequest = { + bidder: 'sublime', + adUnitCode: 'sublime_code_2', + bidId: 'abc1234_2', + data: { + w: 1, + h: 1, + }, + requestId: 'xyz654_2', + params: { + zoneId: 456, + } + }; + + let result = spec.interpretResponse({ body: serverResponse }, bidRequest); + + let expectedResponse = []; + + expect(result).to.deep.equal(expectedResponse); + }); + }); +}); From 72ff0e4d800c20fc96e4a5fb7031ce822b34feb9 Mon Sep 17 00:00:00 2001 From: mamatic <52153441+mamatic@users.noreply.github.com> Date: Mon, 19 Aug 2019 19:45:26 +0200 Subject: [PATCH 1432/1594] Identity Link - Use ats library for retrieving envelope (#4077) * Identity Link - Use ats library for retrieving envelope * Identity Link - add withCredentials options * Identity Link - renamed file identityLinkSystem to identityLinkIdSystem --- ...yLinkSystem.js => identityLinkIdSystem.js} | 42 +++++++++++++------ test/spec/modules/userId_spec.js | 2 +- 2 files changed, 30 insertions(+), 14 deletions(-) rename modules/{identityLinkSystem.js => identityLinkIdSystem.js} (60%) diff --git a/modules/identityLinkSystem.js b/modules/identityLinkIdSystem.js similarity index 60% rename from modules/identityLinkSystem.js rename to modules/identityLinkIdSystem.js index ef916252811..9aca5f85adf 100644 --- a/modules/identityLinkSystem.js +++ b/modules/identityLinkIdSystem.js @@ -38,21 +38,37 @@ export const identityLinkSubmodule = { } // use protocol relative urls for http or https const url = `https://api.rlcdn.com/api/identity/envelope?pid=${configParams.pid}`; - - return function (callback) { - ajax(url, response => { - let responseObj; - if (response) { - try { - responseObj = JSON.parse(response); - } catch (error) { - utils.logError(error); + // if ats library is initialised, use it to retrieve envelope. If not use standard third party endpoint + if (window.ats) { + return function(callback) { + window.ats.retrieveEnvelope(function (envelope) { + if (envelope) { + callback(JSON.parse(envelope).envelope); + } else { + getEnvelope(url, callback); } - } - callback(responseObj.envelope); - }, undefined, { method: 'GET' }); + }); + } + } else { + return function (callback) { + getEnvelope(url, callback); + } } } -}; +} +// return envelope from third party endpoint +function getEnvelope(url, callback) { + ajax(url, response => { + let responseObj; + if (response) { + try { + responseObj = JSON.parse(response); + } catch (error) { + utils.logError(error); + } + } + callback(responseObj.envelope); + }, undefined, {method: 'GET', withCredentials: true}); +} submodule('userId', identityLinkSubmodule); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index b581873089a..13f35b68545 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -10,7 +10,7 @@ import * as utils from 'src/utils'; import {unifiedIdSubmodule} from 'modules/userId/unifiedIdSystem'; import {pubCommonIdSubmodule} from 'modules/userId/pubCommonIdSystem'; import {id5IdSubmodule} from 'modules/id5IdSystem'; -import {identityLinkSubmodule} from 'modules/identityLinkSystem'; +import {identityLinkSubmodule} from 'modules/identityLinkIdSystem'; let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; From 511a38baa0d4bc64d8e43fdd537bfa5ded657ef3 Mon Sep 17 00:00:00 2001 From: Renato Aguilar <41385245+raguilar-ias@users.noreply.github.com> Date: Mon, 19 Aug 2019 18:43:17 -0500 Subject: [PATCH 1433/1594] OPT-1949 Update prebid.js to pass in window.href & add keyword process to our integration (#4083) * OPT-1949 Update prebid.js to pass in window.href & add keyword process to our integration * OPT-1949 remove kw custom value from test * OPT-1949 fix test * OPT-1949 specify url value --- modules/iasBidAdapter.js | 2 + test/spec/modules/iasBidAdapter_spec.js | 110 ++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/modules/iasBidAdapter.js b/modules/iasBidAdapter.js index bda5af1f4ec..5530cbefb82 100644 --- a/modules/iasBidAdapter.js +++ b/modules/iasBidAdapter.js @@ -59,6 +59,7 @@ function buildRequests(bidRequests) { queries.push(['wr', stringifyWindowSize()]); queries.push(['sr', stringifyScreenSize()]); + queries.push(['url', encodeURIComponent(window.location.href)]); const queryString = encodeURI(queries.map(qs => qs.join('=')).join('&')); @@ -80,6 +81,7 @@ function getPageLevelKeywords(response) { let result = {}; shallowMerge(result, response.brandSafety); result.fr = response.fr; + result.custom = response.custom; return result; } diff --git a/test/spec/modules/iasBidAdapter_spec.js b/test/spec/modules/iasBidAdapter_spec.js index 21ef9f8e15a..8197ee25856 100644 --- a/test/spec/modules/iasBidAdapter_spec.js +++ b/test/spec/modules/iasBidAdapter_spec.js @@ -116,6 +116,9 @@ describe('iasBidAdapter is an adapter that', function () { it('screen size', function () { expect(val).to.match(/.*sr=[0-9]*\.[0-9]*/); }); + it('url value', function () { + expect(val).to.match(/.*url=https?%3A%2F%2F[^\s$.?#].[^\s]*/); + }); }); it('has property `bidRequest` that is the first passed in bid request', function () { expect(spec.buildRequests(bidRequests)).to.deep.include({ @@ -229,5 +232,112 @@ describe('iasBidAdapter is an adapter that', function () { expect(adapter.interpretResponse(serverResponse, requests)).to.length(2); }); }); + describe('returns a list of bid response that with custom value', function () { + let bidRequests, bidResponse, slots, custom, serverResponse; + beforeEach(function () { + bidRequests = [ + { + adUnitCode: 'one-div-id', + auctionId: 'someAuctionId', + bidId: 'someBidId1', + bidder: 'ias', + bidderRequestId: 'someBidderRequestId', + params: { + pubId: '1234', + adUnitPath: '/a/b/c' + }, + sizes: [ + [10, 20], + [300, 400] + ], + transactionId: 'someTransactionId' + }, + { + adUnitCode: 'two-div-id', + auctionId: 'someAuctionId', + bidId: 'someBidId2', + bidder: 'ias', + bidderRequestId: 'someBidderRequestId', + params: { + pubId: '1234', + adUnitPath: '/d/e/f' + }, + sizes: [ + [50, 60] + ], + transactionId: 'someTransactionId' + } + ]; + const request = { + bidRequest: { + bidId: '102938' + } + }; + slots = {}; + slots['test-div-id'] = { + id: '1234', + vw: ['60', '70'] + }; + slots['test-div-id-two'] = { + id: '5678', + vw: ['80', '90'] + }; + custom = {}; + custom['ias-kw'] = ['IAS_1_KW', 'IAS_2_KW']; + serverResponse = { + body: { + brandSafety: { + adt: 'adtVal', + alc: 'alcVal', + dlm: 'dlmVal', + drg: 'drgVal', + hat: 'hatVal', + off: 'offVal', + vio: 'vioVal' + }, + fr: 'false', + slots: slots, + custom: custom + }, + headers: {} + }; + bidResponse = spec.interpretResponse(serverResponse, request); + }); + it('has IAS keyword `adt` as property', function () { + expect(bidResponse[0]).to.deep.include({ adt: 'adtVal' }); + }); + it('has IAS keyword `alc` as property', function () { + expect(bidResponse[0]).to.deep.include({ alc: 'alcVal' }); + }); + it('has IAS keyword `dlm` as property', function () { + expect(bidResponse[0]).to.deep.include({ dlm: 'dlmVal' }); + }); + it('has IAS keyword `drg` as property', function () { + expect(bidResponse[0]).to.deep.include({ drg: 'drgVal' }); + }); + it('has IAS keyword `hat` as property', function () { + expect(bidResponse[0]).to.deep.include({ hat: 'hatVal' }); + }); + it('has IAS keyword `off` as property', function () { + expect(bidResponse[0]).to.deep.include({ off: 'offVal' }); + }); + it('has IAS keyword `vio` as property', function () { + expect(bidResponse[0]).to.deep.include({ vio: 'vioVal' }); + }); + it('has IAS keyword `fr` as property', function () { + expect(bidResponse[0]).to.deep.include({ fr: 'false' }); + }); + it('has property `slots`', function () { + expect(bidResponse[0]).to.deep.include({ slots: slots }); + }); + it('has property `custom`', function () { + expect(bidResponse[0]).to.deep.include({ custom: custom }); + }); + it('response is the same for multiple slots', function () { + var adapter = spec; + var requests = adapter.buildRequests(bidRequests); + expect(adapter.interpretResponse(serverResponse, requests)).to.length(3); + }); + }); }); }); From f622bdca207dfd91c89742f23d961232a3829898 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 20 Aug 2019 08:19:45 -0400 Subject: [PATCH 1434/1594] Fix #4059 - ensure native keys are not seen as custom targeting keys (#4086) * ensure native keys are not seen as custom keys * add unit test for native keys --- src/targeting.js | 2 +- test/spec/unit/core/targeting_spec.js | 150 +++++++++++++++++++++++++- 2 files changed, 150 insertions(+), 2 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index a8c989bdf37..f9ed9e4e70c 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -443,7 +443,7 @@ export function newTargeting(auctionManager) { } function getCustomKeys() { - let standardKeys = getStandardKeys(); + let standardKeys = getStandardKeys().concat(NATIVE_TARGETING_KEYS); return function(key) { return standardKeys.indexOf(key) === -1; } diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index bc5958f0495..f4d3a5e0488 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -97,6 +97,131 @@ const bid3 = { 'ttl': 300 }; +const nativeBid1 = { + 'bidderCode': 'appnexus', + 'width': 0, + 'height': 0, + 'statusMessage': 'Bid available', + 'adId': '591e7c9354b633', + 'requestId': '24aae81e32d6f6', + 'mediaType': 'native', + 'source': 'client', + 'cpm': 10, + 'creativeId': 97494403, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'adUnitCode': '/19968336/prebid_native_example_1', + 'appnexus': { + 'buyerMemberId': 9325 + }, + 'meta': { + 'advertiserId': 2529885 + }, + 'native': { + 'title': 'This is a Prebid Native Creative', + 'body': 'This is a Prebid Native Creative. There are many like it, but this one is mine.', + 'sponsoredBy': 'Prebid.org', + 'clickUrl': 'http://prebid.org/dev-docs/show-native-ads.html', + 'clickTrackers': ['http://www.clickUrl.com/404'], + 'impressionTrackers': ['http://imp.trackerUrl.com/it1'], + 'javascriptTrackers': '', + 'image': { + 'url': 'http://vcdn.adnxs.com/p/creative-image/94/22/cd/0f/9422cd0f-f400-45d3-80f5-2b92629d9257.jpg', + 'height': 2250, + 'width': 3000 + }, + 'icon': { + 'url': 'http://vcdn.adnxs.com/p/creative-image/bd/59/a6/c6/bd59a6c6-0851-411d-a16d-031475a51312.png', + 'height': 83, + 'width': 127 + } + }, + 'auctionId': '72138a4a-b747-4192-9192-dcc41d675de8', + 'responseTimestamp': 1565785219461, + 'requestTimestamp': 1565785219405, + 'bidder': 'appnexus', + 'timeToRespond': 56, + 'pbLg': '5.00', + 'pbMg': '10.00', + 'pbHg': '10.00', + 'pbAg': '10.00', + 'pbDg': '10.00', + 'pbCg': '', + 'size': '0x0', + 'adserverTargeting': { + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '591e7c9354b633', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.SIZE]: '0x0', + [CONSTANTS.TARGETING_KEYS.SOURCE]: 'client', + [CONSTANTS.TARGETING_KEYS.FORMAT]: 'native', + [CONSTANTS.NATIVE_KEYS.title]: 'This is a Prebid Native Creative', + [CONSTANTS.NATIVE_KEYS.body]: 'This is a Prebid Native Creative. There are many like it, but this one is mine.', + [CONSTANTS.NATIVE_KEYS.sponsoredBy]: 'Prebid.org', + [CONSTANTS.NATIVE_KEYS.clickUrl]: 'http://prebid.org/dev-docs/show-native-ads.html', + [CONSTANTS.NATIVE_KEYS.image]: 'http://vcdn.adnxs.com/p/creative-image/94/22/cd/0f/9422cd0f-f400-45d3-80f5-2b92629d9257.jpg', + [CONSTANTS.NATIVE_KEYS.icon]: 'http://vcdn.adnxs.com/p/creative-image/bd/59/a6/c6/bd59a6c6-0851-411d-a16d-031475a51312.png' + } +}; +const nativeBid2 = { + 'bidderCode': 'dgads', + 'width': 0, + 'height': 0, + 'statusMessage': 'Bid available', + 'adId': '6e0aba55ed54e5', + 'requestId': '4de26ec83d9661', + 'mediaType': 'native', + 'source': 'client', + 'cpm': 1.90909091, + 'creativeId': 'xuidx6c901261b0x2b2', + 'currency': 'JPY', + 'netRevenue': true, + 'ttl': 60, + 'referrer': 'http://test.localhost:9999/integrationExamples/gpt/demo_native.html?pbjs_debug=true', + 'native': { + 'image': { + 'url': 'https://ads-tr.bigmining.com/img/300x250.png', + 'width': 300, + 'height': 250 + }, + 'title': 'Test Title', + 'body': 'Test Description', + 'sponsoredBy': 'test.com', + 'clickUrl': 'http://prebid.org/', + 'clickTrackers': ['https://www.clickUrl.com/404'], + 'impressionTrackers': [ + 'http://imp.trackerUrl.com/it2' + ] + }, + 'auctionId': '72138a4a-b747-4192-9192-dcc41d675de8', + 'responseTimestamp': 1565785219607, + 'requestTimestamp': 1565785219409, + 'bidder': 'dgads', + 'adUnitCode': '/19968336/prebid_native_example_1', + 'timeToRespond': 198, + 'pbLg': '1.50', + 'pbMg': '1.90', + 'pbHg': '1.90', + 'pbAg': '1.90', + 'pbDg': '1.90', + 'pbCg': '', + 'size': '0x0', + 'adserverTargeting': { + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'dgads', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '6e0aba55ed54e5', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '1.90', + [CONSTANTS.TARGETING_KEYS.SIZE]: '0x0', + [CONSTANTS.TARGETING_KEYS.SOURCE]: 'client', + [CONSTANTS.TARGETING_KEYS.FORMAT]: 'native', + [CONSTANTS.NATIVE_KEYS.image]: 'https://ads-tr.bigmining.com/img/300x250.png', + [CONSTANTS.NATIVE_KEYS.title]: 'Test Title', + [CONSTANTS.NATIVE_KEYS.body]: 'Test Description', + [CONSTANTS.NATIVE_KEYS.sponsoredBy]: 'test.com', + [CONSTANTS.NATIVE_KEYS.clickUrl]: 'http://prebid.org/' + } +}; + describe('targeting tests', function () { let sandbox; let enableSendAllBids = false; @@ -106,7 +231,6 @@ describe('targeting tests', function () { sandbox = sinon.sandbox.create(); useBidCache = true; - // enableSendAllBids = false; let origGetConfig = config.getConfig; sandbox.stub(config, 'getConfig').callsFake(function (key) { @@ -150,6 +274,9 @@ describe('targeting tests', function () { config.resetConfig(); logWarnStub.restore(); logErrorStub.restore(); + amBidsReceivedStub.restore(); + amGetAdUnitsStub.restore(); + bidExpiryStub.restore(); }); describe('when hb_deal is present in bid.adserverTargeting', function () { @@ -218,6 +345,27 @@ describe('targeting tests', function () { expect(targeting['/123456/header-bid-tag-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]); }); + it('ensures keys are properly generated when enableSendAllBids is true and multiple bidders use native', function() { + const nativeAdUnitCode = '/19968336/prebid_native_example_1'; + enableSendAllBids = true; + + // update mocks for this test to return native bids + amBidsReceivedStub.callsFake(function() { + return [nativeBid1, nativeBid2]; + }); + amGetAdUnitsStub.callsFake(function() { + return [nativeAdUnitCode]; + }); + + let targeting = targetingInstance.getAllTargeting([nativeAdUnitCode]); + expect(targeting[nativeAdUnitCode].hb_native_image).to.equal(nativeBid1.native.image.url); + expect(targeting[nativeAdUnitCode].hb_native_linkurl).to.equal(nativeBid1.native.clickUrl); + expect(targeting[nativeAdUnitCode].hb_native_title).to.equal(nativeBid1.native.title); + expect(targeting[nativeAdUnitCode].hb_native_image_dgad).to.exist.and.to.equal(nativeBid2.native.image.url); + expect(targeting[nativeAdUnitCode].hb_pb_dgads).to.exist.and.to.equal(nativeBid2.pbMg); + expect(targeting[nativeAdUnitCode].hb_native_body_appne).to.exist.and.to.equal(nativeBid1.native.body); + }); + it('does not include adpod type bids in the getBidsReceived results', function () { let adpodBid = utils.deepClone(bid1); adpodBid.video = { context: 'adpod', durationSeconds: 15, durationBucket: 15 }; From 7ee3eb27e73bccbbab342c4505f058115faf8b47 Mon Sep 17 00:00:00 2001 From: Cosmos Dev <48195282+dev-cosmos@users.noreply.github.com> Date: Tue, 20 Aug 2019 19:58:56 +0530 Subject: [PATCH 1435/1594] New Adapter request : cosmos (#4096) * Create cosmosBidAdapter.js Implemented cosmos adapter * Create cosmosBidAdapter.md Document file for cosmos * Create cosmos_sample.html Test File * Deleted cosmos_sample.html * Added unittesting. --- modules/cosmosBidAdapter.js | 392 +++++++++++++++++++++ modules/cosmosBidAdapter.md | 80 +++++ test/spec/modules/cosmosBidAdapter_spec.js | 355 +++++++++++++++++++ 3 files changed, 827 insertions(+) create mode 100644 modules/cosmosBidAdapter.js create mode 100644 modules/cosmosBidAdapter.md create mode 100644 test/spec/modules/cosmosBidAdapter_spec.js diff --git a/modules/cosmosBidAdapter.js b/modules/cosmosBidAdapter.js new file mode 100644 index 00000000000..84131bfa131 --- /dev/null +++ b/modules/cosmosBidAdapter.js @@ -0,0 +1,392 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import * as utils from '../src/utils'; + +const BIDDER_CODE = 'cosmos'; +const BID_ENDPOINT = '//bid.cosmoshq.com/openrtb2/bids'; +const USER_SYNC_ENDPOINT = '//sync.cosmoshq.com/js/v1/usersync.html'; +const HTTP_POST = 'POST'; +const LOG_PREFIX = 'COSMOS: '; +const DEFAULT_CURRENCY = 'USD'; +const HTTPS = 'https:'; +const MEDIA_TYPES = 'mediaTypes'; +const MIMES = 'mimes'; +const DEFAULT_NET_REVENUE = false; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + + /** + * generate UUID + **/ + _createUUID: function () { + return ('' + new Date().getTime()); + }, + + /** + * copy object if not null + **/ + _copyObject: function (src, dst) { + if (src) { + // copy complete object + Object.keys(src).forEach(param => dst[param] = src[param]); + } + }, + + /** + * parse object + **/ + _parse: function (rawPayload) { + try { + if (rawPayload) { + return JSON.parse(rawPayload); + } + } catch (ex) { + utils.logError(LOG_PREFIX, 'Exception: ', ex); + } + return null; + }, + + /** + * 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 || !bid.params) { + utils.logError(LOG_PREFIX, 'nil/empty bid object'); + return false; + } + + if (!utils.isEmpty(bid.params.publisherId) || + !utils.isNumber(bid.params.publisherId)) { + utils.logError(LOG_PREFIX, 'publisherId is mandatory and must be numeric. Ad Unit: ', JSON.stringify(bid)); + return false; + } + // video bid request validation + if (bid.hasOwnProperty(MEDIA_TYPES) && bid.mediaTypes.hasOwnProperty(VIDEO)) { + if (!bid.mediaTypes.video.hasOwnProperty(MIMES) || + !utils.isArray(bid.mediaTypes.video.mimes) || + bid.mediaTypes.video.mimes.length === 0) { + utils.logError(LOG_PREFIX, 'mimes are mandatory for video bid request. Ad Unit: ', JSON.stringify(bid)); + return false; + } + } + + return true; + }, + + /** + * 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) { + if (validBidRequests.length === 0) { + return []; + } + + var refererInfo; + if (bidderRequest && bidderRequest.refererInfo) { + refererInfo = bidderRequest.refererInfo; + } + + let clonedBidRequests = utils.deepClone(validBidRequests); + return clonedBidRequests.map(bidRequest => { + const oRequest = spec._createRequest(bidRequest, refererInfo); + if (oRequest) { + spec._setGDPRParams(bidderRequest, oRequest); + return { + method: HTTP_POST, + url: BID_ENDPOINT, + data: JSON.stringify(oRequest) + }; + } + }); + }, + + /** + * 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, request) { + let response = serverResponse.body; + var bidResponses = []; + try { + if (response.seatbid) { + var currency = response.cur ? response.cur : DEFAULT_CURRENCY; + response.seatbid.forEach(seatbid => { + var bids = seatbid.bid ? seatbid.bid : []; + bids.forEach(bid => { + var bidResponse = { + requestId: bid.impid, + cpm: (parseFloat(bid.price) || 0).toFixed(2), + width: bid.w, + height: bid.h, + creativeId: bid.crid, + currency: currency, + netRevenue: DEFAULT_NET_REVENUE, + ttl: 300 + }; + if (bid.dealid) { + bidResponse.dealId = bid.dealid; + } + + var req = spec._parse(request.data); + if (req.imp && req.imp.length > 0) { + req.imp.forEach(impr => { + if (impr.id === bid.impid) { + if (impr.banner) { + bidResponse.ad = bid.adm; + bidResponse.mediaType = BANNER; + } else { + bidResponse.width = bid.hasOwnProperty('w') ? bid.w : impr.video.w; + bidResponse.height = bid.hasOwnProperty('h') ? bid.h : impr.video.h; + bidResponse.vastXml = bid.adm; + bidResponse.mediaType = VIDEO; + } + } + }); + } + bidResponses.push(bidResponse); + }); + }); + } + } catch (ex) { + utils.logError(LOG_PREFIX, 'Exception: ', ex); + } + 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) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: USER_SYNC_ENDPOINT + }]; + } else { + utils.logWarn(LOG_PREFIX + 'Please enable iframe based user sync.'); + } + }, + + /** + * create IAB standard OpenRTB bid request + **/ + _createRequest: function (bidRequests, refererInfo) { + var oRequest = {}; + try { + oRequest = { + id: spec._createUUID(), + imp: spec._createImpressions(bidRequests), + user: {}, + ext: {} + }; + var site = spec._createSite(bidRequests, refererInfo); + var app = spec._createApp(bidRequests); + var device = spec._createDevice(bidRequests); + if (app) { + oRequest.app = app; + } + if (site) { + oRequest.site = site; + } + if (device) { + oRequest.device = device; + } + } catch (ex) { + utils.logError(LOG_PREFIX, 'Exception: ', ex); + oRequest = null; + } + return oRequest; + }, + + /** + * create impression array objects + **/ + _createImpressions: function (request) { + var impressions = []; + var impression = spec._creatImpression(request); + if (impression) { + impressions.push(impression); + } + return impressions; + }, + + /** + * create impression (single) object + **/ + _creatImpression: function (request) { + if (!request.hasOwnProperty(MEDIA_TYPES)) { + return undefined; + } + + var params = request && request.params ? request.params : null; + var impression = { + id: request.bidId ? request.bidId : spec._createUUID(), + secure: window.location.protocol === HTTPS ? 1 : 0, + bidfloorcur: request.params.currency ? request.params.currency : DEFAULT_CURRENCY + }; + if (params.bidFloor) { + impression.bidfloor = params.bidFloor; + } + + if (params.tagId) { + impression.tagid = params.tagId.toString(); + } + + var banner; + var video; + var mediaType; + for (mediaType in request.mediaTypes) { + switch (mediaType) { + case BANNER: + banner = spec._createBanner(request); + if (banner) { + impression.banner = banner; + } + break; + case VIDEO: + video = spec._createVideo(request); + if (video) { + impression.video = video; + } + break; + } + } + + return impression.hasOwnProperty(BANNER) || + impression.hasOwnProperty(VIDEO) ? impression : undefined; + }, + + /** + * create the banner object + **/ + _createBanner: function (request) { + if (utils.deepAccess(request, 'mediaTypes.banner')) { + var banner = {}; + var sizes = request.mediaTypes.banner.sizes; + if (sizes && utils.isArray(sizes) && sizes.length > 0) { + var format = []; + banner.w = sizes[0][0]; + banner.h = sizes[0][1]; + sizes.forEach(size => { + format.push({ + w: size[0], + h: size[1] + }); + }); + banner.format = format; + } + + spec._copyObject(request.mediaTypes.banner, banner); + spec._copyObject(request.params.banner, banner); + return banner; + } + return undefined; + }, + + /** + * create video object + **/ + _createVideo: function (request) { + if (utils.deepAccess(request, 'mediaTypes.video')) { + var video = {}; + var sizes = request.mediaTypes.video.playerSize; + if (sizes && utils.isArray(sizes) && sizes.length > 1) { + video.w = sizes[0]; + video.h = sizes[1]; + } + spec._copyObject(request.mediaTypes.video, video); + spec._copyObject(request.params.video, video); + return video; + } + return undefined; + }, + + /** + * create site object + **/ + _createSite: function (request, refererInfo) { + var rSite = request.params.site; + if (rSite || !request.params.app) { + var site = {}; + spec._copyObject(rSite, site); + + if (refererInfo) { + if (refererInfo.referer) { + site.ref = encodeURIComponent(refererInfo.referer); + } + if (utils.isArray(refererInfo.stack) && refererInfo.stack.length > 0) { + site.page = encodeURIComponent(refererInfo.stack[0]); + let anchrTag = document.createElement('a'); + anchrTag.href = site.page; + site.domain = anchrTag.hostname; + } + } + + // override publisher object + site.publisher = { + id: request.params.publisherId.toString() + }; + return site; + } + return undefined; + }, + + /** + * create app object + **/ + _createApp: function (request) { + var rApp = request.params.app; + if (rApp) { + var app = {}; + spec._copyObject(rApp, app); + // override publisher object + app.publisher = { + id: request.params.publisherId.toString() + }; + return app; + } + return undefined; + }, + + /** + * create device obejct + **/ + _createDevice: function (request) { + var device = {}; + var rDevice = request.params.device; + spec._copyObject(rDevice, device); + device.dnt = utils.getDNT() ? 1 : 0; + device.ua = navigator.userAgent; + device.language = (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage); + device.w = (window.screen.width || window.innerWidth); + device.h = (window.screen.height || window.innerHeigh); + return device; + }, + + /** + * set GDPR parameters + **/ + _setGDPRParams: function (bidderRequest, oRequest) { + if (!bidderRequest || !bidderRequest.gdprConsent) { + return; + } + + oRequest.regs = { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0 } }; + oRequest.user = { ext: { consent: bidderRequest.gdprConsent.consentString } }; + }, + +} +registerBidder(spec); diff --git a/modules/cosmosBidAdapter.md b/modules/cosmosBidAdapter.md new file mode 100644 index 00000000000..187a19ba17a --- /dev/null +++ b/modules/cosmosBidAdapter.md @@ -0,0 +1,80 @@ +# Overview + +``` +Module Name: Cosmos Bid Adapter +Module Type: Bidder Adapter +Maintainer: dev@cosmoshq.com +``` + +# Description + +Module that connects to Cosmos server for bids. +Supported Ad Fortmats: +* Banner +* Video + +# Configuration +## Following configuration required for enabling user sync. +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + enabledBidders: ['cosmos'], + syncDelay: 6000 + }}); +``` +## For Video ads, enable prebid cache +```javascript +pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } +}); +``` + +# Test Parameters +``` + var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { //supported as per the openRTB spec + sizes: [[300, 250]] // required + } + }, + bids: [ + { + bidder: "cosmos", + params: { + publisherId: 1001, // required + tagId: 1 // optional + } + } + ] + }, + // Video adUnit + { + code: 'video-div', + mediaTypes: { + video: { // supported as per the openRTB spec + sizes: [[300, 50]], // required + mimes : ['video/mp4', 'application/javascript'], // required + context: 'instream' // optional + } + }, + bids: [ + { + bidder: "cosmos", + params: { + publisherId: 1001, // required + tagId: 1, // optional + video: { // supported as per the openRTB spec + + } + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/cosmosBidAdapter_spec.js b/test/spec/modules/cosmosBidAdapter_spec.js new file mode 100644 index 00000000000..348f5ae3ddf --- /dev/null +++ b/test/spec/modules/cosmosBidAdapter_spec.js @@ -0,0 +1,355 @@ +import { expect } from 'chai'; +import { spec } from 'modules/cosmosBidAdapter'; +import * as utils from 'src/utils'; +const constants = require('src/constants.json'); + +describe('Cosmos adapter', function () { + let bannerBidRequests; + let bannerBidResponse; + let videoBidRequests; + let videoBidResponse; + + beforeEach(function () { + bannerBidRequests = [ + { + bidder: 'cosmos', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], + } + }, + params: { + publisherId: '1001', + currency: 'USD', + geo: { + lat: '09.5', + lon: '21.2', + } + }, + bidId: '29f8bd96defe76' + } + ]; + + videoBidRequests = + [ + { + mediaTypes: { + video: { + mimes: ['video/mp4', 'video/x-flv'], + context: 'instream' + } + }, + bidder: 'cosmos', + params: { + publisherId: 1001, + video: { + skippable: true, + minduration: 5, + maxduration: 30 + } + }, + bidId: '39f5cc6eff9b37' + } + ]; + + bannerBidResponse = { + 'body': { + 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', + 'seatbid': [{ + 'bid': [{ + 'id': '82DAAE22-FF66-4FAB-84AB-347B0C5CD02C', + 'impid': '29f8bd96defe76', + 'price': 1.858309, + 'adm': '

    COSMOS\"Connecting Advertisers and Publishers directly\"

    ', + 'adid': 'v55jutrh', + 'adomain': ['febreze.com'], + 'iurl': 'https://thetradedesk-t-general.s3.amazonaws.com/AdvertiserLogos/vgl908z.png', + 'cid': '1234', + 'crid': 'v55jutrh', + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + } + } + }], + 'seat': 'zeta' + }] + } + }; + + videoBidResponse = { + 'body': { + 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', + 'seatbid': [{ + 'bid': [{ + 'id': '82DAAE22-FF66-4FAB-84AB-347B0C5CD02C', + 'impid': '39f5cc6eff9b37', + 'price': 0.858309, + 'adm': 'CosmosHQVAST 2.0 Instream Test 1VAST 2.0 Instream Test 1https://track.cosmoshq.com/event?data=%7B%22id%22%3A%221566011421045%22%2C%22bid%22%3A%2282DAAE22-FF66-4FAB-84AB-347B0C5CD02C%22%2C%22ts%22%3A%2220190817031021%22%2C%22pid%22%3A1001%2C%22plcid%22%3A1%2C%22aid%22%3A1%2C%22did%22%3A1%2C%22cid%22%3A%2222918%22%2C%22af%22%3A3%2C%22at%22%3A1%2C%22w%22%3A300%2C%22h%22%3A250%2C%22crid%22%3A%22v55jutrh%22%2C%22pp%22%3A0.858309%2C%22cp%22%3A0.858309%2C%22mg%22%3A0%7D&type=1http://track.dsp.impression.com/impression00:00:60http://sync.cosmoshq.com/static/video/SampleVideo_1280x720_10mb.mp4', + 'adid': 'v55jutrh', + 'adomain': ['febreze.com'], + 'iurl': 'https://thetradedesk-t-general.s3.amazonaws.com/AdvertiserLogos/vgl908z.png', + 'cid': '1234', + 'crid': 'v55jutrh', + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'video' + } + } + }], + 'seat': 'zeta' + }] + } + }; + }); + + describe('isBidRequestValid', function () { + describe('validate the bid object: valid bid', function () { + it('valid bid case', function () { + let validBid = { + bidder: 'cosmos', + params: { + publisherId: 1001, + tagId: 1 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + + it('validate the bid object: nil/empty bid object', function () { + let validBid = { + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('validate the bid object: publisherId not passed', function () { + let validBid = { + bidder: 'cosmos', + params: { + tagId: 1 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('validate the bid object: publisherId is not number', function () { + let validBid = { + bidder: 'cosmos', + params: { + publisherId: '301', + tagId: 1 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('validate the bid object: mimes absent', function () { + let validBid = { + bidder: 'cosmos', + mediaTypes: { + video: {} + }, + params: { + publisherId: 1001 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('validate the bid object: mimes present', function () { + let validBid = { + bidder: 'cosmos', + mediaTypes: { + video: { + mimes: ['video/mp4', 'application/javascript'] + } + }, + params: { + publisherId: 1001 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + + it('validate the bid object: tagId is not passed', function () { + let validBid = { + bidder: 'cosmos', + params: { + publisherId: 1001 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + }); + + describe('buildRequests', function () { + it('build request object: buildRequests function should not modify original bannerBidRequests object', function () { + let originalBidRequests = utils.deepClone(bannerBidRequests); + let request = spec.buildRequests(bannerBidRequests); + expect(bannerBidRequests).to.deep.equal(originalBidRequests); + }); + + it('build request object: endpoint check', function () { + let request = spec.buildRequests(bannerBidRequests); + expect(request[0].url).to.equal('//bid.cosmoshq.com/openrtb2/bids'); + expect(request[0].method).to.equal('POST'); + }); + + it('build request object: request params check', function () { + let request = spec.buildRequests(bannerBidRequests); + let data = JSON.parse(request[0].data); + expect(data.site.publisher.id).to.equal(bannerBidRequests[0].params.publisherId); // publisher Id + expect(data.imp[0].bidfloorcur).to.equal(bannerBidRequests[0].params.currency); + }); + + it('build request object: request params check without tagId', function () { + delete bannerBidRequests[0].params.tagId; + let request = spec.buildRequests(bannerBidRequests); + let data = JSON.parse(request[0].data); + expect(data.site.publisher.id).to.equal(bannerBidRequests[0].params.publisherId); // publisher Id + expect(data.imp[0].tagid).to.equal(undefined); // tagid + expect(data.imp[0].bidfloorcur).to.equal(bannerBidRequests[0].params.currency); + }); + + it('build request object: request params multi size format object check', function () { + let bidRequest = [ + { + bidder: 'cosmos', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], + } + }, + params: { + publisherId: 1001, + currency: 'USD' + } + } + ]; + /* case 1 - size passed in adslot */ + let request = spec.buildRequests(bidRequest); + let data = JSON.parse(request[0].data); + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + + /* case 2 - size passed in adslot as well as in sizes array */ + bidRequest[0].sizes = [[300, 600], [300, 250]]; + bidRequest[0].mediaTypes = { + banner: { + sizes: [[300, 600], [300, 250]] + } + }; + request = spec.buildRequests(bidRequest); + data = JSON.parse(request[0].data); + + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(600); // height + + /* case 3 - size passed in sizes but not in adslot */ + bidRequest[0].params.tagId = 1; + bidRequest[0].sizes = [[300, 250], [300, 600]]; + bidRequest[0].mediaTypes = { + banner: { + sizes: [[300, 250], [300, 600]] + } + }; + request = spec.buildRequests(bidRequest); + data = JSON.parse(request[0].data); + + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].banner.format).exist.and.to.be.an('array'); + expect(data.imp[0].banner.format[0]).exist.and.to.be.an('object'); + expect(data.imp[0].banner.format[0].w).to.equal(300); // width + expect(data.imp[0].banner.format[0].h).to.equal(250); // height + }); + + it('build request object: request params currency check', function () { + let bidRequest = [ + { + bidder: 'cosmos', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], + } + }, + params: { + publisherId: 1001, + tagId: 1, + currency: 'USD' + }, + sizes: [[300, 250], [300, 600]] + } + ]; + + /* case 1 - + currency specified in adunits + output: imp[0] use currency specified in bannerBidRequests[0].params.currency + + */ + let request = spec.buildRequests(bidRequest); + let data = JSON.parse(request[0].data); + expect(data.imp[0].bidfloorcur).to.equal(bidRequest[0].params.currency); + + /* case 2 - + currency specified in adunit + output: imp[0] use default currency - USD + + */ + delete bidRequest[0].params.currency; + request = spec.buildRequests(bidRequest); + data = JSON.parse(request[0].data); + expect(data.imp[0].bidfloorcur).to.equal('USD'); + }); + + it('build request object: request params check for video ad', function () { + let request = spec.buildRequests(videoBidRequests); + let data = JSON.parse(request[0].data); + expect(data.imp[0].video).to.exist; + expect(data.imp[0]['video']['mimes']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['mimes'][0]).to.equal(videoBidRequests[0].mediaTypes.video['mimes'][0]); + expect(data.imp[0]['video']['mimes'][1]).to.equal(videoBidRequests[0].mediaTypes.video['mimes'][1]); + expect(data.imp[0]['video']['minduration']).to.equal(videoBidRequests[0].params.video['minduration']); + expect(data.imp[0]['video']['maxduration']).to.equal(videoBidRequests[0].params.video['maxduration']); + }); + + describe('interpretResponse', function () { + it('check for banner response', function () { + let request = spec.buildRequests(bannerBidRequests); + let data = JSON.parse(request[0].data); + let response = spec.interpretResponse(bannerBidResponse, request[0]); + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].requestId).to.equal(bannerBidResponse.body.seatbid[0].bid[0].impid); + expect(response[0].cpm).to.equal((bannerBidResponse.body.seatbid[0].bid[0].price).toFixed(2)); + expect(response[0].width).to.equal(bannerBidResponse.body.seatbid[0].bid[0].w); + expect(response[0].height).to.equal(bannerBidResponse.body.seatbid[0].bid[0].h); + if (bannerBidResponse.body.seatbid[0].bid[0].crid) { + expect(response[0].creativeId).to.equal(bannerBidResponse.body.seatbid[0].bid[0].crid); + } else { + expect(response[0].creativeId).to.equal(bannerBidResponse.body.seatbid[0].bid[0].id); + } + expect(response[0].dealId).to.equal(bannerBidResponse.body.seatbid[0].bid[0].dealid); + expect(response[0].currency).to.equal('USD'); + expect(response[0].netRevenue).to.equal(false); + expect(response[0].ttl).to.equal(300); + }); + it('check for video response', function () { + let request = spec.buildRequests(videoBidRequests); + let data = JSON.parse(request[0].data); + let response = spec.interpretResponse(videoBidResponse, request[0]); + }); + }); + }); + }); +}); From dca695f2cfff97b59849231341dc127fefea41e1 Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 20 Aug 2019 22:41:12 +0530 Subject: [PATCH 1436/1594] Banner e2e (#4092) * reorganize e2e/ tests into separate directories * new test page for e2e-banner testing * add test to check if Banner Ad is getting loaded * change location of the spec files to reflect change in test/e2e directory structure * add test case to check for generation of valid targeting keys --- test/pages/banner.html | 94 +++++++++++++++++++ test/spec/e2e/banner/basic_banner_ad.spec.js | 48 ++++++++++ ...asic_w_custom_adserver_translation.spec.js | 0 .../basic_w_requireExactDuration.spec.js | 0 .../basic_wo_brandCategoryExclusion.spec.js | 0 .../basic_wo_requireExactDuration.spec.js | 0 wdio.conf.js | 2 +- 7 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 test/pages/banner.html create mode 100644 test/spec/e2e/banner/basic_banner_ad.spec.js rename test/spec/{lfe2e/specs => e2e/longform}/basic_w_custom_adserver_translation.spec.js (100%) rename test/spec/{lfe2e/specs => e2e/longform}/basic_w_requireExactDuration.spec.js (100%) rename test/spec/{lfe2e/specs => e2e/longform}/basic_wo_brandCategoryExclusion.spec.js (100%) rename test/spec/{lfe2e/specs => e2e/longform}/basic_wo_requireExactDuration.spec.js (100%) diff --git a/test/pages/banner.html b/test/pages/banner.html new file mode 100644 index 00000000000..e8c30239ac0 --- /dev/null +++ b/test/pages/banner.html @@ -0,0 +1,94 @@ + + + + + + + Prebid.js Banner Ad Unit Example + + + + + + + + + + + + + + + +

    Prebid.js Banner Ad Unit Test

    +
    + +
    +
    + + + diff --git a/test/spec/e2e/banner/basic_banner_ad.spec.js b/test/spec/e2e/banner/basic_banner_ad.spec.js new file mode 100644 index 00000000000..ee01ce627db --- /dev/null +++ b/test/spec/e2e/banner/basic_banner_ad.spec.js @@ -0,0 +1,48 @@ +const expect = require('chai').expect; +const { host, protocol } = require('../../../helpers/testing-utils'); + +const TEST_PAGE_URL = `${protocol}://${host}:9999/test/pages/banner.html`; +const CREATIVE_IFRAME_CSS_SELECTOR = 'iframe[id="google_ads_iframe_/19968336/header-bid-tag-0_0"]'; + +const EXPECTED_TARGETING_KEYS = { + hb_format: 'banner', + hb_source: 'client', + hb_pb: '0.50', + hb_bidder: 'appnexus', + hb_format_appnexus: 'banner', + hb_source_appnexus: 'client', + hb_pb_appnexus: '0.50', + hb_bidder_appnexus: 'appnexus' +} + +describe('Prebid.js Banner Ad Unit Test', function () { + before(function loadTestPage() { + browser.url(TEST_PAGE_URL).pause(3000); + try { + browser.waitForExist(CREATIVE_IFRAME_CSS_SELECTOR, 2000); + const creativeIframe = $(CREATIVE_IFRAME_CSS_SELECTOR).value; + browser.frame(creativeIframe); + } catch (e) { + // If creative Iframe didn't load, repeat the steps again! + // Due to some reason if the Ad server doesn't respond, the test case will time out after 60000 ms as defined in file wdio.conf.js + loadTestPage(); + } + }); + + it('should load the targeting keys with correct values', function () { + const result = browser.execute(function () { + return window.top.pbjs.getAdserverTargeting('div-gpt-ad-1460505748561-1'); + }); + + const targetingKeys = result.value['div-gpt-ad-1460505748561-1']; + + expect(targetingKeys).to.include(EXPECTED_TARGETING_KEYS); + expect(targetingKeys.hb_adid).to.be.a('string'); + expect(targetingKeys.hb_adid_appnexus).to.be.a('string'); + expect(targetingKeys.hb_size).to.satisfy((size) => size === '300x250' || '300x600'); + }); + + it('should render the Banner Ad on the page', function () { + expect(browser.isVisible('body > div[class="GoogleActiveViewElement"] > a > img')).to.be.true; + }); +}); diff --git a/test/spec/lfe2e/specs/basic_w_custom_adserver_translation.spec.js b/test/spec/e2e/longform/basic_w_custom_adserver_translation.spec.js similarity index 100% rename from test/spec/lfe2e/specs/basic_w_custom_adserver_translation.spec.js rename to test/spec/e2e/longform/basic_w_custom_adserver_translation.spec.js diff --git a/test/spec/lfe2e/specs/basic_w_requireExactDuration.spec.js b/test/spec/e2e/longform/basic_w_requireExactDuration.spec.js similarity index 100% rename from test/spec/lfe2e/specs/basic_w_requireExactDuration.spec.js rename to test/spec/e2e/longform/basic_w_requireExactDuration.spec.js diff --git a/test/spec/lfe2e/specs/basic_wo_brandCategoryExclusion.spec.js b/test/spec/e2e/longform/basic_wo_brandCategoryExclusion.spec.js similarity index 100% rename from test/spec/lfe2e/specs/basic_wo_brandCategoryExclusion.spec.js rename to test/spec/e2e/longform/basic_wo_brandCategoryExclusion.spec.js diff --git a/test/spec/lfe2e/specs/basic_wo_requireExactDuration.spec.js b/test/spec/e2e/longform/basic_wo_requireExactDuration.spec.js similarity index 100% rename from test/spec/lfe2e/specs/basic_wo_requireExactDuration.spec.js rename to test/spec/e2e/longform/basic_wo_requireExactDuration.spec.js diff --git a/wdio.conf.js b/wdio.conf.js index 4e50e68af2e..9e816bef24b 100644 --- a/wdio.conf.js +++ b/wdio.conf.js @@ -30,7 +30,7 @@ function getCapabilities() { exports.config = { specs: [ - './test/spec/lfe2e/specs/*.js' + './test/spec/e2e/**/*.spec.js' ], services: ['browserstack'], user: process.env.BROWSERSTACK_USERNAME, From 99e3e52cd1afca305e07010043cec270717ef4dc Mon Sep 17 00:00:00 2001 From: Dima Shirokov Date: Tue, 20 Aug 2019 20:22:27 +0200 Subject: [PATCH 1437/1594] Add Meazy bid adapter (#4015) * add meazy bid adapter * fix dealid * jsnellbaker review * jsnellbaker review * jsnellbaker review --- modules/meazyBidAdapter.js | 149 ++++++++++++++++++ modules/meazyBidAdapter.md | 23 +++ test/spec/modules/meazyBidAdapter_spec.js | 177 ++++++++++++++++++++++ 3 files changed, 349 insertions(+) create mode 100644 modules/meazyBidAdapter.js create mode 100644 modules/meazyBidAdapter.md create mode 100644 test/spec/modules/meazyBidAdapter_spec.js diff --git a/modules/meazyBidAdapter.js b/modules/meazyBidAdapter.js new file mode 100644 index 00000000000..8604ef770da --- /dev/null +++ b/modules/meazyBidAdapter.js @@ -0,0 +1,149 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; + +const BIDDER_CODE = 'meazy'; +const PREBID_ENDPOINT = 'rtb-filter.meazy.co'; +const SYNC_ENDPOINT = '//sync.meazy.co/sync/iframe'; +const ENDPOINT_CONFIG = { + defaultCurrency: ['USD'], + availableSize: ['300x250', '320x480', '160x600'] +}; + +const buildURI = (pid) => { + return `//${PREBID_ENDPOINT}/pbjs?host=${utils.getOrigin()}&api_key=${pid}`; +} + +const validateSize = (size) => { + return ENDPOINT_CONFIG.availableSize.indexOf(size.join('x')) !== -1; +} + +const buildImpression = (bidRequest) => { + const impression = { + id: utils.getUniqueIdentifierStr(), + tagid: bidRequest.adUnitCode, + banner: { + format: bidRequest.sizes.map(size => ({ w: size[0], h: size[1] })) + } + }; + + return impression; +} + +export const spec = { + code: BIDDER_CODE, + 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 !!bid.params.pid && bid.sizes.some(validateSize); + }, + + /** + * 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) { + const payload = { + id: bidRequests[0].bidId, + site: { + domain: utils.getOrigin() + }, + device: { + w: window.screen.width, + h: window.screen.height, + language: navigator.language + }, + cur: ENDPOINT_CONFIG.defaultCurrency, + imp: bidRequests.map(buildImpression), + user: {} + }; + + if (bidderRequest.refererInfo) { + if (bidderRequest.refererInfo.referer) { + payload.site.ref = bidderRequest.refererInfo.referer; + } + + if (utils.isArray(bidderRequest.refererInfo) && bidderRequest.refererInfo.stack.length > 0) { + payload.site.page = bidderRequest.refererInfo.stack[0]; + } + } + + if (utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { + payload.user.ext = { + consent: bidderRequest.gdprConsent.consentString, + gdpr: bidderRequest.gdprConsent.gdprApplies & 1 + } + } + + const payloadString = JSON.stringify(payload); + + return { + method: 'POST', + url: buildURI(bidRequests[0].params.pid), + 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) { + const bids = []; + + if (!utils.isArray(serverResponse.body.seatbid) || !serverResponse.body.seatbid[0]) { + return bids; + } + + serverResponse.body.seatbid[0].bid.forEach(bidResponse => { + const bid = { + requestId: serverResponse.body.id, + cpm: bidResponse.price, + width: bidResponse.w, + height: bidResponse.h, + creativeId: bidResponse.crid, + netRevenue: bidResponse.netRevenue !== undefined ? bidResponse.netRevenue : true, + dealId: bidResponse.dealid, + currency: ENDPOINT_CONFIG.defaultCurrency[0], + ttl: bidResponse.exp || 900, + ad: bidResponse.adm + } + + bids.push(bid); + }); + + return bids; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = []; + + if (syncOptions.pixelEnabled && serverResponses[0] && utils.deepAccess(serverResponses[0], 'body.ext.syncUrl')) { + syncs.push({ + type: 'image', + url: serverResponses[0].body.ext.syncUrl + }); + } + + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: SYNC_ENDPOINT + }); + } + + return syncs; + } +} + +registerBidder(spec); diff --git a/modules/meazyBidAdapter.md b/modules/meazyBidAdapter.md new file mode 100644 index 00000000000..354673bf590 --- /dev/null +++ b/modules/meazyBidAdapter.md @@ -0,0 +1,23 @@ +# Overview + +Module Name: Meazy Bidder Adapter +Module Type: Bidder Adapter +Maintainer: dima@meazy.co + +# Description + +Module that connects to Meazy demand sources + +# Test Parameters +``` +var adUnits = [{ + code: 'test-div', + sizes: [[300, 250]], + bids: [{ + bidder: "meazy", + params: { + pid: '6910b7344ae566a1' + } + }] +}]; +``` \ No newline at end of file diff --git a/test/spec/modules/meazyBidAdapter_spec.js b/test/spec/modules/meazyBidAdapter_spec.js new file mode 100644 index 00000000000..9abe37ece62 --- /dev/null +++ b/test/spec/modules/meazyBidAdapter_spec.js @@ -0,0 +1,177 @@ +import * as utils from 'src/utils'; +import { expect } from 'chai'; +import { spec } from 'modules/meazyBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const MEAZY_PID = '6910b7344ae566a1' +const VALID_ENDPOINT = `//rtb-filter.meazy.co/pbjs?host=${utils.getOrigin()}&api_key=${MEAZY_PID}`; + +const bidderRequest = { + refererInfo: { + referer: 'page', + stack: ['page', 'page1'] + } +}; + +const bidRequest = { + bidder: 'meazy', + adUnitCode: 'test-div', + sizes: [[300, 250], [300, 600]], + params: { + pid: MEAZY_PID + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', +}; + +const bidContent = { + 'id': '30b31c1838de1e', + 'bidid': '9780a52ff05c0e92780f5baf9cf3f4e8', + 'cur': 'USD', + 'seatbid': [{ + 'bid': [{ + 'id': 'ccf05fb8effb3d02', + 'impid': 'B19C34BBD69DAF9F', + 'burl': 'https://track.meazy.co/imp?bidid=9780a52ff05c0e92780f5baf9cf3f4e8&user=fdc401a2-92f1-42bd-ac22-d570520ad0ec&burl=1&ssp=5&project=2&cost=${AUCTION_PRICE}', + 'adm': '', + 'adid': 'ad-2.6.75.300x250', + 'price': 1.5, + 'w': 300, + 'h': 250, + 'cid': '2.6.75', + 'crid': '2.6.75.300x250', + 'dealid': 'default' + }], + 'seat': '2' + }] +}; + +const bidContentExt = { + ...bidContent, + ext: { + 'syncUrl': '//sync.meazy.co/sync/img?api_key=6910b7344ae566a1' + } +}; + +const bidResponse = { + body: bidContent +}; + +const noBidResponse = { body: {'nbr': 2} }; + +describe('meazyBidAdapter', 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 false', function () { + let bid = Object.assign({}, bidRequest); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true', function () { + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + }); + + describe('buildRequests', function () { + it('should format valid url', function () { + const request = spec.buildRequests([bidRequest], bidderRequest); + expect(request.url).to.equal(VALID_ENDPOINT); + }); + + it('should format valid url', function () { + const request = spec.buildRequests([bidRequest], bidderRequest); + expect(request.url).to.equal(VALID_ENDPOINT); + }); + + it('should format valid request body', function () { + const request = spec.buildRequests([bidRequest], bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.id).to.exist; + expect(payload.imp).to.exist; + expect(payload.imp[0]).to.exist; + expect(payload.imp[0].banner).to.exist; + expect(payload.imp[0].banner.format).to.exist; + expect(payload.device).to.exist; + expect(payload.site).to.exist; + expect(payload.site.domain).to.exist; + expect(payload.cur).to.exist; + }); + + it('should format valid url', function () { + const request = spec.buildRequests([bidRequest], bidderRequest); + expect(request.url).to.equal(VALID_ENDPOINT); + }); + + it('should not fill user.ext object', function () { + const request = spec.buildRequests([bidRequest], bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.user.ext).to.equal(undefined); + }); + + it('should fill user.ext object', function () { + const consentString = 'hellogdpr'; + const request = spec.buildRequests([bidRequest], { ...bidderRequest, gdprConsent: { gdprApplies: true, consentString } }); + const payload = JSON.parse(request.data); + expect(payload.user.ext).to.exist.and.to.be.a('object'); + expect(payload.user.ext.consent).to.equal(consentString); + expect(payload.user.ext.gdpr).to.equal(1); + }); + }); + + describe('interpretResponse', function () { + it('should get correct bid response', function () { + const result = spec.interpretResponse(bidResponse); + const validResponse = [{ + requestId: '30b31c1838de1e', + cpm: 1.5, + width: 300, + height: 250, + creativeId: '2.6.75.300x250', + netRevenue: true, + dealId: 'default', + currency: 'USD', + ttl: 900, + ad: '' + }]; + + expect(result).to.deep.equal(validResponse); + }); + + it('handles nobid responses', function () { + let result = spec.interpretResponse(noBidResponse); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs', function () { + const syncOptionsFF = { iframeEnabled: false }; + const syncOptionsEF = { iframeEnabled: true }; + const syncOptionsEE = { pixelEnabled: true, iframeEnabled: true }; + const syncOptionsFE = { pixelEnabled: true, iframeEnabled: false }; + + const successIFrame = { type: 'iframe', url: '//sync.meazy.co/sync/iframe' }; + const successPixel = { type: 'image', url: '//sync.meazy.co/sync/img?api_key=6910b7344ae566a1' }; + + it('should return an empty array', function () { + expect(spec.getUserSyncs(syncOptionsFF, [])).to.be.empty; + expect(spec.getUserSyncs(syncOptionsFF, [ bidResponse ])).to.be.empty; + expect(spec.getUserSyncs(syncOptionsFE, [ bidResponse ])).to.be.empty; + }); + + it('should be equal to the expected result', function () { + expect(spec.getUserSyncs(syncOptionsEF, [ bidResponse ])).to.deep.equal([successIFrame]); + expect(spec.getUserSyncs(syncOptionsFE, [ { body: bidContentExt } ])).to.deep.equal([successPixel]); + expect(spec.getUserSyncs(syncOptionsEE, [ { body: bidContentExt } ])).to.deep.equal([successPixel, successIFrame]); + expect(spec.getUserSyncs(syncOptionsEE, [])).to.deep.equal([successIFrame]); + }) + }); +}); From b8565e7c8c11ea7e4f78681ca12aaaab85044afb Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 20 Aug 2019 13:12:16 -0700 Subject: [PATCH 1438/1594] Prebid 2.29.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da9bdf63507..8f86f3dfc00 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.29.0-pre", + "version": "2.29.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 6467bba4de3eb9e136fc098de84b9f6a3253ebcb Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 20 Aug 2019 13:27:04 -0700 Subject: [PATCH 1439/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f86f3dfc00..b802a31e78e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.29.0", + "version": "2.30.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From c0c1b3ef747997a8d7e9bc8b04fd3eac5c34ee0d Mon Sep 17 00:00:00 2001 From: minh-daole-ttd <54119199+minh-daole-ttd@users.noreply.github.com> Date: Tue, 20 Aug 2019 17:17:45 -0700 Subject: [PATCH 1440/1594] enable withCredentials on unifiedId ajax call (#4090) --- modules/userId/unifiedIdSystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/userId/unifiedIdSystem.js b/modules/userId/unifiedIdSystem.js index cf86c049d2a..1bc369bb9fc 100644 --- a/modules/userId/unifiedIdSystem.js +++ b/modules/userId/unifiedIdSystem.js @@ -49,7 +49,7 @@ export const unifiedIdSubmodule = { } } callback(responseObj); - }, undefined, { method: 'GET' }); + }, undefined, { method: 'GET', withCredentials: true }); } } }; From 20969809c65a2e8d6f16069432135f98386e4900 Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 20 Aug 2019 20:19:44 -0400 Subject: [PATCH 1441/1594] Rubicon adapter doc: adding video example (#4091) --- modules/rubiconBidAdapter.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.md b/modules/rubiconBidAdapter.md index d5beebee31b..d9df95b5941 100644 --- a/modules/rubiconBidAdapter.md +++ b/modules/rubiconBidAdapter.md @@ -35,7 +35,7 @@ globalsupport@rubiconproject.com for more information. } ] },{ - code: 'test-div', + code: 'test-native-size', mediaTypes: { banner: { sizes: [[300, 50]] @@ -53,4 +53,30 @@ globalsupport@rubiconproject.com for more information. ] } ]; + + var videoAdUnit = { + code: 'myVideoAdUnit', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + mimes: ['video/mp4', 'video/x-ms-wmv'] + protocols: [2,5], + maxduration:30, + linearity: 1, + api: [2] + } + }, + bids: [{ + bidder: 'rubicon', + params: { + accountId: '7780', + siteId: '87184', + zoneId: '413290', + video: { + language: 'en' + } + } + }] +}; ``` From 35e4b2b36ca36ea9f5642eab84023ed4f2f66358 Mon Sep 17 00:00:00 2001 From: bjorn-lw <32431346+bjorn-lw@users.noreply.github.com> Date: Wed, 21 Aug 2019 17:58:13 +0200 Subject: [PATCH 1442/1594] Collect info about which ad units receive bids (#4094) * Livewrapped bid and analytics adapter * Fixed some tests for browser compatibility * Fixed some tests for browser compatibility * Changed analytics adapter code name * Fix double quote in debug message * modified how gdpr is being passed * Added support for Publisher Common ID Module * Corrections for ttr in analytics * ANalytics updates * Auction start time stamp changed * Detect recovered ad blocked requests Make it possible to pass dynamic parameters to adapter * Collect info on ad units receiving any valid bid --- modules/livewrappedAnalyticsAdapter.js | 23 +++++++++++++++++++ .../livewrappedAnalyticsAdapter_spec.js | 10 ++++++++ 2 files changed, 33 insertions(+) diff --git a/modules/livewrappedAnalyticsAdapter.js b/modules/livewrappedAnalyticsAdapter.js index ec0ddb6fd54..72c46de744d 100644 --- a/modules/livewrappedAnalyticsAdapter.js +++ b/modules/livewrappedAnalyticsAdapter.js @@ -17,6 +17,7 @@ export const BID_WON_TIMEOUT = 500; const cache = { auctions: {}, + bidAdUnits: {} }; let livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTYPE}), { @@ -62,6 +63,9 @@ let livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTYPE if (!bidResponse.ttr) { bidResponse.ttr = time - bidResponse.start; } + if (!cache.bidAdUnits[bidResponse.adUnit]) { + cache.bidAdUnits[bidResponse.adUnit] = {sent: 0, timeStamp: cache.auctions[args.auctionId].timeStamp}; + } break; case CONSTANTS.EVENTS.BIDDER_DONE: utils.logInfo('LIVEWRAPPED_BIDDER_DONE:', args); @@ -114,6 +118,7 @@ livewrappedAnalyticsAdapter.sendEvents = function() { responses: getResponses(), wins: getWins(), timeouts: getTimeouts(), + bidAdUnits: getbidAdUnits(), rcv: getAdblockerRecovered() }; @@ -229,6 +234,24 @@ function getTimeouts() { return timeouts; } +function getbidAdUnits() { + var bidAdUnits = []; + + Object.keys(cache.bidAdUnits).forEach(adUnit => { + let bidAdUnit = cache.bidAdUnits[adUnit]; + if (!bidAdUnit.sent) { + bidAdUnit.sent = 1; + + bidAdUnits.push({ + adUnit: adUnit, + timeStamp: bidAdUnit.timeStamp + }); + } + }); + + return bidAdUnits; +} + adapterManager.registerAnalyticsAdapter({ adapter: livewrappedAnalyticsAdapter, code: 'livewrapped' diff --git a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js index 92c1c4d3ab3..611ff95a036 100644 --- a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +++ b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js @@ -117,6 +117,16 @@ const MOCK = { const ANALYTICS_MESSAGE = { publisherId: 'CC411485-42BC-4F92-8389-42C503EE38D7', + bidAdUnits: [ + { + adUnit: 'panorama_d_1', + timeStamp: 1519149562216 + }, + { + adUnit: 'box_d_1', + timeStamp: 1519149562216 + } + ], requests: [ { adUnit: 'panorama_d_1', From 801f0fb3ad9b8891cced991bf35095db4c2084a7 Mon Sep 17 00:00:00 2001 From: bretg Date: Wed, 21 Aug 2019 12:48:30 -0400 Subject: [PATCH 1443/1594] s2sTesting: random number moved to global (#3851) * s2sTesting: random number moved to global We got a request that if if 10% of bidderA and 10% of bidderB should be server-side, they should be the same 10% of requests. This is a simple approach to the change that implies that the same page experience only throws one random number for the purposes of s2sTesting. i.e. if there are dynamic ads on the page, all newly created ads on the page will continue to use the same number. This is ok from the purposes of the s2sTesting module. * Added get for randNum + fix lint & tests * update to remove getter * remove log * update test --- modules/s2sTesting.js | 3 +- test/spec/modules/s2sTesting_spec.js | 68 ++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/modules/s2sTesting.js b/modules/s2sTesting.js index ae68fc3b9f6..eccc3aa1f8a 100644 --- a/modules/s2sTesting.js +++ b/modules/s2sTesting.js @@ -11,6 +11,7 @@ s2sTesting.CLIENT = CLIENT; var testing = false; // whether testing is turned on var bidSource = {}; // store bidder sources determined from s2sConfing bidderControl +s2sTesting.globalRand = Math.random(); // if 10% of bidderA and 10% of bidderB should be server-side, make it the same 10% // load s2sConfig config.getConfig('s2sConfig', config => { @@ -82,7 +83,7 @@ s2sTesting.getSource = function(sourceWeights = {}, bidSources = [SERVER, CLIENT }); if (!totWeight) return; // bail if no source weights // choose a source randomly based on weights - var rndWeight = Math.random() * totWeight; + var rndWeight = s2sTesting.globalRand * totWeight; for (var i = 0; i < bidSources.length; i++) { let source = bidSources[i]; // choose the first source with an incremental weight > random weight diff --git a/test/spec/modules/s2sTesting_spec.js b/test/spec/modules/s2sTesting_spec.js index 34de6d9ec38..52377dcabf2 100644 --- a/test/spec/modules/s2sTesting_spec.js +++ b/test/spec/modules/s2sTesting_spec.js @@ -1,30 +1,14 @@ import s2sTesting from 'modules/s2sTesting'; import { config } from 'src/config'; -import find from 'core-js/library/fn/array/find'; - -var events = require('src/events'); -var CONSTANTS = require('src/constants.json'); -const BID_ADJUSTMENT = CONSTANTS.EVENTS.BID_ADJUSTMENT; var expect = require('chai').expect; describe('s2sTesting', function () { - let mathRandomStub; - let randomNumber = 0; - - beforeEach(function () { - mathRandomStub = sinon.stub(Math, 'random').callsFake(() => { return randomNumber; }); - }); - - afterEach(function () { - mathRandomStub.restore(); - }); - describe('s2sTesting.getSource', function () { // helper function to set random number and get the source function getExpectedSource(randNumber, sourceWeights, sources) { // set random number for testing - randomNumber = randNumber; + s2sTesting.globalRand = randNumber; return s2sTesting.getSource(sourceWeights, sources); } @@ -93,7 +77,7 @@ describe('s2sTesting', function () { describe('setting source through s2sConfig', function () { beforeEach(function () { // set random number for testing - randomNumber = 0.7; + s2sTesting.globalRand = 0.7; }); it('does not work if testing is "false"', function () { @@ -155,6 +139,50 @@ describe('s2sTesting', function () { expect(serverClientBidders.server).to.eql(['rubicon']); expect(serverClientBidders.client).to.have.members(['appnexus']); }); + + it('sends both bidders to same source when weights are the same', function () { + s2sTesting.globalRand = 0.01; + + config.setConfig({s2sConfig: { + bidders: ['rubicon', 'appnexus'], + testing: true, + bidderControl: { + rubicon: {bidSource: {server: 1, client: 99}}, + appnexus: {bidSource: {server: 1, client: 99}} + }}}); + expect(s2sTesting.getSourceBidderMap()).to.eql({ + client: ['rubicon', 'appnexus'], + server: [] + }); + expect(s2sTesting.getSourceBidderMap()).to.eql({ + client: ['rubicon', 'appnexus'], + server: [] + }); + expect(s2sTesting.getSourceBidderMap()).to.eql({ + client: ['rubicon', 'appnexus'], + server: [] + }); + + config.setConfig({s2sConfig: { + bidders: ['rubicon', 'appnexus'], + testing: true, + bidderControl: { + rubicon: {bidSource: {server: 99, client: 1}}, + appnexus: {bidSource: {server: 99, client: 1}} + }}}); + expect(s2sTesting.getSourceBidderMap()).to.eql({ + server: ['rubicon', 'appnexus'], + client: [] + }); + expect(s2sTesting.getSourceBidderMap()).to.eql({ + server: ['rubicon', 'appnexus'], + client: [] + }); + expect(s2sTesting.getSourceBidderMap()).to.eql({ + server: ['rubicon', 'appnexus'], + client: [] + }); + }); }); describe('setting source through adUnits', function () { @@ -162,7 +190,7 @@ describe('s2sTesting', function () { // reset s2sconfig bid sources config.setConfig({s2sConfig: {testing: true}}); // set random number for testing - randomNumber = 0.7; + s2sTesting.globalRand = 0.7; }); it('sets one bidder source from one adUnit', function () { @@ -280,7 +308,7 @@ describe('s2sTesting', function () { // reset s2sconfig bid sources config.setConfig({s2sConfig: {testing: true}}); // set random number for testing - randomNumber = 0.7; + s2sTesting.globalRand = 0.7; }); it('should get sources from both', function () { From bc3987d4adac1c45b27976f559457c590b15af76 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 21 Aug 2019 11:37:40 -0600 Subject: [PATCH 1444/1594] consolidate logic around common chunk inclusions (#4087) --- .eslintrc.js | 32 +++++--------------------------- allowedModules.js | 24 ++++++++++++++++++++++++ webpack.conf.js | 9 ++++++--- 3 files changed, 35 insertions(+), 30 deletions(-) create mode 100644 allowedModules.js diff --git a/.eslintrc.js b/.eslintrc.js index 610768f7dd2..56e4808f985 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,12 +1,5 @@ -const sharedWhiteList = [ - "core-js/library/fn/array/find", // no ie11 - "core-js/library/fn/array/includes", // no ie11 - "core-js/library/fn/set", // ie11 supports Set but not Set#values - "core-js/library/fn/string/includes", // no ie11 - "core-js/library/fn/number/is-integer", // no ie11, - "core-js/library/fn/array/from" // no ie11 -]; +const allowedModules = require("./allowedModules"); module.exports = { "env": { @@ -45,25 +38,10 @@ module.exports = { "no-undef": "off", "no-useless-escape": "off", }, - "overrides": [{ - "files": "modules/**/*.js", + "overrides": Object.keys(allowedModules).map((key) => ({ + "files": key + "/**/*.js", "rules": { - "prebid/validate-imports": ["error", [ - ...sharedWhiteList, - "jsencrypt", - "crypto-js" - ]] + "prebid/validate-imports": ["error", allowedModules[key]] } - }, { - "files": "src/**/*.js", - "rules": { - "prebid/validate-imports": ["error", [ - ...sharedWhiteList, - "fun-hooks/no-eval", - "just-clone", - "dlv", - "dset" - ]] - } - }] + })) }; diff --git a/allowedModules.js b/allowedModules.js new file mode 100644 index 00000000000..e66b8e24098 --- /dev/null +++ b/allowedModules.js @@ -0,0 +1,24 @@ + +const sharedWhiteList = [ + "core-js/library/fn/array/find", // no ie11 + "core-js/library/fn/array/includes", // no ie11 + "core-js/library/fn/set", // ie11 supports Set but not Set#values + "core-js/library/fn/string/includes", // no ie11 + "core-js/library/fn/number/is-integer", // no ie11, + "core-js/library/fn/array/from" // no ie11 +]; + +module.exports = { + 'modules': [ + ...sharedWhiteList, + 'jsencrypt', + 'crypto-js' + ], + 'src': [ + ...sharedWhiteList, + 'fun-hooks/no-eval', + 'just-clone', + 'dlv', + 'dset' + ] +}; diff --git a/webpack.conf.js b/webpack.conf.js index 8e1787de329..a5c75fa8a1a 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -5,6 +5,7 @@ var helpers = require('./gulpHelpers'); var RequireEnsureWithoutJsonp = require('./plugins/RequireEnsureWithoutJsonp.js'); var { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); var argv = require('yargs').argv; +var allowedModules = require('./allowedModules'); // list of module names to never include in the common bundle chunk var neverBundle = [ @@ -26,12 +27,14 @@ plugins.push( // this plugin must be last so it can be easily removed for karma name: 'prebid', filename: 'prebid-core.js', minChunks: function(module) { - return ( + return ( ( - module.context && module.context === path.resolve('./src') && + module.context && module.context.startsWith(path.resolve('./src')) && !(module.resource && neverBundle.some(name => module.resource.includes(name))) ) || - module.resource && module.resource.includes(path.resolve('./node_modules/core-js')) + module.resource && (allowedModules.src.concat(['core-js'])).some( + name => module.resource.includes(path.resolve('./node_modules/' + name)) + ) ); } }) From e798c0cfc8598f70a86b7fcd6f5a3c14942662c9 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Fri, 23 Aug 2019 18:01:03 -0600 Subject: [PATCH 1445/1594] Updates to RDN Adapter (#4080) * handle no bid in rdn adapter --- modules/rdnBidAdapter.js | 49 +++++++++++++------------ test/spec/modules/rdnBidAdapter_spec.js | 10 ++++- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/modules/rdnBidAdapter.js b/modules/rdnBidAdapter.js index d85b307263d..17071c54be0 100644 --- a/modules/rdnBidAdapter.js +++ b/modules/rdnBidAdapter.js @@ -3,16 +3,16 @@ import * as utils from '../src/utils' import { BANNER } from '../src/mediaTypes' import { config } from '../src/config' -const BIDDER_CODE = 'rdn' -const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h' +const BIDDER_CODE = 'rdn'; +const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h'; export const spec = { code: BIDDER_CODE, isBidRequestValid: bid => !!bid.params.adSpotId, buildRequests: validBidRequests => { - const bidRequests = [] + const bidRequests = []; validBidRequests.forEach(bid => { - const params = bid.params + const params = bid.params; bidRequests.push({ method: 'GET', url: config.getConfig('rdn.endpoint') || ENDPOINT, @@ -29,26 +29,29 @@ export const spec = { pp: encodeURIComponent(utils.getTopWindowReferrer()) } }) - }) + }); return bidRequests }, interpretResponse: (response, request) => { - const sb = response.body - const bidResponses = [] - bidResponses.push({ - requestId: sb.bid_id, - cpm: sb.cpm || 0, - width: sb.width || 0, - height: sb.height || 0, - creativeId: sb.creative_id || 0, - dealId: sb.deal_id || '', - currency: sb.currency || 'JPY', - netRevenue: (sb.net_revenue === undefined) ? true : sb.net_revenue, - mediaType: BANNER, - ttl: sb.ttl, - referrer: utils.getTopWindowUrl(), - ad: sb.ad - }) + const sb = response.body; + const bidResponses = []; + + if (sb.cpm && sb.ad) { + bidResponses.push({ + requestId: sb.bid_id, + cpm: sb.cpm, + width: sb.width || 0, + height: sb.height || 0, + creativeId: sb.creative_id || 0, + dealId: sb.deal_id || '', + currency: sb.currency || 'JPY', + netRevenue: (typeof sb.net_revenue === 'undefined') ? true : !!sb.net_revenue, + mediaType: BANNER, + ttl: sb.ttl, + referrer: utils.getTopWindowUrl(), + ad: sb.ad + }); + } return bidResponses }, @@ -62,7 +65,7 @@ export const spec = { } if (bidResponseObj.sync_urls && bidResponseObj.sync_urls.length > 0) { bidResponseObj.sync_urls.forEach(syncUrl => { - if (syncUrl && syncUrl != 'null' && syncUrl.length > 0) { + if (syncUrl && syncUrl !== 'null' && syncUrl.length > 0) { syncs.push({ type: 'image', url: syncUrl @@ -75,4 +78,4 @@ export const spec = { } } -registerBidder(spec) +registerBidder(spec); diff --git a/test/spec/modules/rdnBidAdapter_spec.js b/test/spec/modules/rdnBidAdapter_spec.js index 1fef1c7bf3d..8f53502bc44 100644 --- a/test/spec/modules/rdnBidAdapter_spec.js +++ b/test/spec/modules/rdnBidAdapter_spec.js @@ -95,6 +95,9 @@ describe('rdnBidAdapter', function() { const serverResponse = { noAd: [], + noAd2: { + requestId: 'biequa9oaph4we' + }, banner: { requestId: 'biequa9oaph4we', cpm: 37.66, @@ -113,10 +116,15 @@ describe('rdnBidAdapter', function() { it('handles nobid responses', () => { const result = spec.interpretResponse( { body: serverResponse.noAd }, + bidRequests.banner + ); + expect(result.length).to.equal(0); + const result2 = spec.interpretResponse( + { body: serverResponse.noAd2 }, bidRequests.banner ); - expect(result.length).to.equal(1) + expect(result2.length).to.equal(0); }) }); describe('spec.getUserSyncs', function () { From 60501c84093c0df7f437dca7ecbba240a7b98ff9 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Mon, 26 Aug 2019 17:03:33 +0300 Subject: [PATCH 1446/1594] Gamoshi: Add 9MediaOnline new adaptor alias (#4108) * Add support for multi-format ad units. Add favoredMediaType property to params. * Add tests for gdpr consent. * Add adId to outbids * Modify media type resolving * Refactor multi-format ad units handler. * Add 9MediaOnline bidder adaptor --- modules/gamoshiBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 3fb045cd7c2..6d243f155bf 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -42,7 +42,7 @@ export const helper = { export const spec = { code: 'gamoshi', - aliases: ['gambid', 'cleanmedia', 'viewdeos', 'adastaMedia'], + aliases: ['gambid', 'cleanmedia', 'viewdeos', 'adastaMedia', '9MediaOnline'], supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { From d6ba289837b0b7843d9149027133697e414eabaf Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 27 Aug 2019 19:09:57 +0530 Subject: [PATCH 1447/1594] remove comment since we're out of depcrecation phase (#4093) --- src/config.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/config.js b/src/config.js index 7645da18d8f..ec26c3d51d0 100644 --- a/src/config.js +++ b/src/config.js @@ -1,11 +1,5 @@ /* * Module for getting and setting Prebid configuration. - * - * Prebid previously defined these properties directly on the global object: - * pbjs.logging = true; - * - * Defining and access properties in this way is now deprecated, but these will - * continue to work during a deprecation window. */ import { isValidPriceConfig } from './cpmBucketManager'; import find from 'core-js/library/fn/array/find'; From d5ee7134b04298e48268d20f9f083b846633cae0 Mon Sep 17 00:00:00 2001 From: susyt Date: Tue, 27 Aug 2019 07:09:00 -0700 Subject: [PATCH 1448/1594] GumGum: add DigiTrust module (#4109) * adds digitrust module, mods gdpr from bool to int * update unit test --- modules/gumgumBidAdapter.js | 27 +++++++++++----------- test/spec/modules/gumgumBidAdapter_spec.js | 2 +- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 557e23254de..8afbed640d7 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -75,22 +75,20 @@ function getWrapperCode(wrapper, data) { return wrapper.replace('AD_JSON', window.btoa(JSON.stringify(data))) } -function _getTradeDeskIDParam(bidRequest) { +function _getTradeDeskIDParam(userId) { const unifiedIdObj = {}; - if (bidRequest.userId && bidRequest.userId.tdid) { - unifiedIdObj.tdid = bidRequest.userId.tdid; + if (userId.tdid) { + unifiedIdObj.tdid = userId.tdid; } return unifiedIdObj; } -// TODO: use getConfig() -function _getDigiTrustQueryParams() { - function getDigiTrustId () { - var digiTrustUser = (window.DigiTrust && window.DigiTrust.getUser) ? window.DigiTrust.getUser(DT_CREDENTIALS) : {}; - return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || ''; - }; - - let digiTrustId = getDigiTrustId(); +function _getDigiTrustQueryParams(userId) { + let digiTrustId = userId.digitrustid && userId.digitrustid.data; + if (!digiTrustId) { + const digiTrustUser = (window.DigiTrust && window.DigiTrust.getUser) ? window.DigiTrust.getUser(DT_CREDENTIALS) : {}; + digiTrustId = (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || ''; + } // Verify there is an ID and this user has not opted out if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { return {}; @@ -143,7 +141,8 @@ function buildRequests (validBidRequests, bidderRequest) { const { bidId, params = {}, - transactionId + transactionId, + userId = {} } = bidRequest; const data = {}; const topWindowUrl = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; @@ -165,7 +164,7 @@ function buildRequests (validBidRequests, bidderRequest) { data.ni = parseInt(params.ICV, 10); data.pi = 5; } - data.gdprApplies = gdprConsent.gdprApplies; + data.gdprApplies = gdprConsent.gdprApplies ? 1 : 0; if (gdprConsent.gdprApplies) { data.gdprConsent = gdprConsent.consentString; } @@ -179,7 +178,7 @@ function buildRequests (validBidRequests, bidderRequest) { sizes: bidRequest.sizes || bidRequest.mediatype[banner].sizes, url: BID_ENDPOINT, method: 'GET', - data: Object.assign(data, _getBrowserParams(topWindowUrl), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) + data: Object.assign(data, _getBrowserParams(topWindowUrl), _getDigiTrustQueryParams(userId), _getTradeDeskIDParam(userId)) }) }); return bids; diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 53a6849fce3..cedef568d56 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -113,7 +113,7 @@ describe('gumgumAdapter', function () { const gdprConsent = { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', gdprApplies: true }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; - expect(bidRequest.data.gdprApplies).to.eq(true); + expect(bidRequest.data.gdprApplies).to.eq(1); expect(bidRequest.data.gdprConsent).to.eq('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); it('should handle gdprConsent is present but values are undefined case', function () { From 11801ba1542607d847f1daa042562475de58af36 Mon Sep 17 00:00:00 2001 From: Omer Koren Date: Tue, 27 Aug 2019 21:57:07 +0300 Subject: [PATCH 1449/1594] Add GDPR and UID module support to Undertone adapter (#4102) * Added user sync support for undertone bid adapter (new pull request) * Added user sync support for undertone bid adapter * undertone adapter - send gdpr data in bid request in user sync request * undertone adapter - send gdpr data in bid request in user sync request - send external uids in the bid request * undertone adapter - send gdpr data in bid request in user sync request - send external uids and prebid version in the bid request * Update undertoneBidAdapter_spec.js * Update undertoneBidAdapter.js --- modules/undertoneBidAdapter.js | 40 ++++- test/spec/modules/undertoneBidAdapter_spec.js | 139 +++++++++++++++--- 2 files changed, 150 insertions(+), 29 deletions(-) diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index c04616a8385..107f4478102 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -41,6 +41,16 @@ function extractDomainFromHost(pageHost) { return domain; } +function getGdprQueryParams(gdprConsent) { + if (!gdprConsent) { + return null; + } + + let gdpr = gdprConsent.gdprApplies ? '1' : '0'; + let gdprstr = gdprConsent.consentString ? gdprConsent.consentString : ''; + return `gdpr=${gdpr}&gdprstr=${gdprstr}`; +} + export const spec = { code: BIDDER_CODE, isBidRequestValid: function(bid) { @@ -51,7 +61,11 @@ export const spec = { }, buildRequests: function(validBidRequests, bidderRequest) { const payload = { - 'x-ut-hb-params': [] + 'x-ut-hb-params': [], + 'commons': { + 'adapterVersion': '$prebid.version$', + 'uids': validBidRequests[0].userId + } }; const referer = bidderRequest.refererInfo.referer; const hostname = urlUtils.parse(referer).hostname; @@ -59,7 +73,12 @@ export const spec = { const pageUrl = getCanonicalUrl() || referer; const pubid = validBidRequests[0].params.publisherId; - const REQ_URL = `${URL}?pid=${pubid}&domain=${domain}`; + let reqUrl = `${URL}?pid=${pubid}&domain=${domain}`; + + let gdprParams = getGdprQueryParams(bidderRequest.gdprConsent); + if (gdprParams) { + reqUrl += `&${gdprParams}`; + } validBidRequests.map(bidReq => { const bid = { @@ -76,7 +95,7 @@ export const spec = { }); return { method: 'POST', - url: REQ_URL, + url: reqUrl, withCredentials: true, data: JSON.stringify(payload) }; @@ -107,23 +126,28 @@ export const spec = { }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { const syncs = []; - if (gdprConsent && gdprConsent.gdprApplies === true) { - return syncs; + + let gdprParams = getGdprQueryParams(gdprConsent); + let iframeGdprParams = ''; + let pixelGdprParams = ''; + if (gdprParams) { + iframeGdprParams += `?${gdprParams}`; + pixelGdprParams += `&${gdprParams}`; } if (syncOptions.iframeEnabled) { syncs.push({ type: 'iframe', - url: FRAME_USER_SYNC + url: FRAME_USER_SYNC + iframeGdprParams }); } else if (syncOptions.pixelEnabled) { syncs.push({ type: 'image', - url: PIXEL_USER_SYNC_1 + url: PIXEL_USER_SYNC_1 + pixelGdprParams }, { type: 'image', - url: PIXEL_USER_SYNC_2 + url: PIXEL_USER_SYNC_2 + pixelGdprParams }); } return syncs; diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index 400e86567ea..676f2714693 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -11,7 +11,7 @@ const validBidReq = { }, sizes: [[300, 250], [300, 600]], bidId: '263be71e91dd9d', - auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054747', }; const invalidBidReq = { @@ -44,12 +44,46 @@ const bidReq = [{ auctionId: '6c22f5a5-59df-4dc6-b92c-f433bcf0a874' }]; +const bidReqUserIds = [{ + bidder: BIDDER_CODE, + params: { + placementId: '10433394', + publisherId: 12345 + }, + sizes: [[300, 250], [300, 600]], + bidId: '263be71e91dd9d', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', + userId: { + tdid: '123456', + digitrustid: {data: {id: 'DTID', keyv: 4, privacy: {optout: false}, producer: 'ABC', version: 2}} + } +}, +{ + bidder: BIDDER_CODE, + params: { + publisherId: 12345 + }, + sizes: [[1, 1]], + bidId: '453cf42d72bb3c', + auctionId: '6c22f5a5-59df-4dc6-b92c-f433bcf0a874' +}]; + const bidderReq = { refererInfo: { referer: 'http://prebid.org/dev-docs/bidder-adaptor.html' } }; +const bidderReqGdpr = { + refererInfo: { + referer: 'http://prebid.org/dev-docs/bidder-adaptor.html' + }, + gdprConsent: { + gdprApplies: true, + consentString: 'acdefgh' + } +}; + const validBidRes = { ad: '
    Hello
    ', publisherId: 12345, @@ -103,7 +137,7 @@ describe('Undertone Adapter', function () { }); }); describe('build request', function () { - it('should send request to correct url via POST', function () { + it('should send request to correct url via POST not in GDPR', function () { const request = spec.buildRequests(bidReq, bidderReq); const domainStart = bidderReq.refererInfo.referer.indexOf('//'); const domainEnd = bidderReq.refererInfo.referer.indexOf('/', domainStart + 2); @@ -112,6 +146,16 @@ describe('Undertone Adapter', function () { expect(request.url).to.equal(REQ_URL); expect(request.method).to.equal('POST'); }); + it('should send request to correct url via POST when in GDPR', function () { + const request = spec.buildRequests(bidReq, bidderReqGdpr); + const domainStart = bidderReq.refererInfo.referer.indexOf('//'); + const domainEnd = bidderReq.refererInfo.referer.indexOf('/', domainStart + 2); + const domain = bidderReq.refererInfo.referer.substring(domainStart + 2, domainEnd); + let gdpr = bidderReqGdpr.gdprConsent.gdprApplies ? 1 : 0 + const REQ_URL = `${URL}?pid=${bidReq[0].params.publisherId}&domain=${domain}&gdpr=${gdpr}&gdprstr=${bidderReqGdpr.gdprConsent.consentString}`; + expect(request.url).to.equal(REQ_URL); + expect(request.method).to.equal('POST'); + }); it('should have all relevant fields', function () { const request = spec.buildRequests(bidReq, bidderReq); const bid1 = JSON.parse(request.data)['x-ut-hb-params'][0]; @@ -127,6 +171,14 @@ describe('Undertone Adapter', function () { expect(bid2.publisherId).to.equal(12345); expect(bid2.params).to.be.an('object'); }); + it('should send all userIds data to server', function () { + const request = spec.buildRequests(bidReqUserIds, bidderReq); + const bidCommons = JSON.parse(request.data)['commons']; + expect(bidCommons).to.be.an('object'); + expect(bidCommons.uids).to.be.an('object'); + expect(bidCommons.uids.tdid).to.equal('123456'); + expect(bidCommons.uids.digitrustid.data.id).to.equal('DTID'); + }); }); describe('interpretResponse', function () { @@ -160,25 +212,70 @@ describe('Undertone Adapter', function () { }); describe('getUserSyncs', () => { - it('verifies gdpr consent checked', () => { - const options = ({ iframeEnabled: true, pixelEnabled: true }); - expect(spec.getUserSyncs(options, {}, { gdprApplies: true }).length).to.equal(0); - }); - - it('Verifies sync iframe option', function () { - const result = spec.getUserSyncs({ iframeEnabled: true, pixelEnabled: true }); - expect(result).to.have.lengthOf(1); - expect(result[0].type).to.equal('iframe'); - expect(result[0].url).to.equal('//cdn.undertone.com/js/usersync.html'); - }); + let testParams = [ + { + name: 'with iframe and no gdpr data', + arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, null], + expect: { + type: 'iframe', + pixels: ['//cdn.undertone.com/js/usersync.html'] + } + }, + { + name: 'with iframe and gdpr on', + arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, {gdprApplies: true, consentString: '234234'}], + expect: { + type: 'iframe', + pixels: ['//cdn.undertone.com/js/usersync.html?gdpr=1&gdprstr=234234'] + } + }, + { + name: 'with iframe and no gdpr off', + arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, {gdprApplies: false}], + expect: { + type: 'iframe', + pixels: ['//cdn.undertone.com/js/usersync.html?gdpr=0&gdprstr='] + } + }, + { + name: 'with pixels and no gdpr data', + arguments: [{ pixelEnabled: true }, {}, null], + expect: { + type: 'image', + pixels: ['//usr.undertone.com/userPixel/syncOne?id=1&of=2', + '//usr.undertone.com/userPixel/syncOne?id=2&of=2'] + } + }, + { + name: 'with pixels and gdpr on', + arguments: [{ pixelEnabled: true }, {}, {gdprApplies: true, consentString: '234234'}], + expect: { + type: 'image', + pixels: ['//usr.undertone.com/userPixel/syncOne?id=1&of=2&gdpr=1&gdprstr=234234', + '//usr.undertone.com/userPixel/syncOne?id=2&of=2&gdpr=1&gdprstr=234234'] + } + }, + { + name: 'with pixels and gdpr off', + arguments: [{ pixelEnabled: true }, {}, {gdprApplies: false}], + expect: { + type: 'image', + pixels: ['//usr.undertone.com/userPixel/syncOne?id=1&of=2&gdpr=0&gdprstr=', + '//usr.undertone.com/userPixel/syncOne?id=2&of=2&gdpr=0&gdprstr='] + } + } + ]; - it('Verifies sync image option', function () { - const result = spec.getUserSyncs({ pixelEnabled: true }); - expect(result).to.have.lengthOf(2); - expect(result[0].type).to.equal('image'); - expect(result[0].url).to.equal('//usr.undertone.com/userPixel/syncOne?id=1&of=2'); - expect(result[1].type).to.equal('image'); - expect(result[1].url).to.equal('//usr.undertone.com/userPixel/syncOne?id=2&of=2'); - }); + for (let i = 0; i < testParams.length; i++) { + let currParams = testParams[i]; + it(currParams.name, function () { + const result = spec.getUserSyncs.apply(this, currParams.arguments); + expect(result).to.have.lengthOf(currParams.expect.pixels.length); + for (let ix = 0; ix < currParams.expect.pixels.length; ix++) { + expect(result[ix].url).to.equal(currParams.expect.pixels[ix]); + expect(result[ix].type).to.equal(currParams.expect.type); + } + }); + } }); }); From 9c128af02723f096f3b67c34a6ee207b91979c73 Mon Sep 17 00:00:00 2001 From: John Salis Date: Tue, 27 Aug 2019 14:58:55 -0400 Subject: [PATCH 1450/1594] Add placement support to beachfront adapter (#4117) --- modules/beachfrontBidAdapter.js | 4 ++-- test/spec/modules/beachfrontBidAdapter_spec.js | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 9e3da9dc7a1..0143f01835d 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -7,7 +7,7 @@ import { VIDEO, BANNER } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.6'; +const ADAPTER_VERSION = '1.7'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; @@ -15,7 +15,7 @@ export const VIDEO_ENDPOINT = 'https://reachms.bfmio.com/bid.json?exchange_id='; export const BANNER_ENDPOINT = 'https://display.bfmio.com/prebid_display'; export const OUTSTREAM_SRC = '//player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; -export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration']; +export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration', 'placement']; export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; let appId = ''; diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index c01a5a3a47c..4598a4e00c7 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -226,11 +226,12 @@ describe('BeachfrontAdapter', function () { const mimes = ['video/webm']; const playbackmethod = 2; const maxduration = 30; + const placement = 4; bidRequest.mediaTypes = { video: {} }; - bidRequest.params.video = { mimes, playbackmethod, maxduration }; + bidRequest.params.video = { mimes, playbackmethod, maxduration, placement }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video).to.deep.contain({ mimes, playbackmethod, maxduration }); + expect(data.imp[0].video).to.deep.contain({ mimes, playbackmethod, maxduration, placement }); }); it('must add GDPR consent data to the request', function () { From 18543d660688857401489d377b5b50b144b16e04 Mon Sep 17 00:00:00 2001 From: guiann Date: Wed, 28 Aug 2019 14:32:58 +0200 Subject: [PATCH 1451/1594] fix typo on size parameter (#4122) --- modules/adyoulikeBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index 12891b6e155..a3e07b25c35 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -41,7 +41,7 @@ export const spec = { accumulator[bid.bidId].TransactionID = bid.transactionId; accumulator[bid.bidId].Width = size.width; accumulator[bid.bidId].Height = size.height; - accumulator[bid.bidId].AvaiableSizes = sizesArray.join(','); + accumulator[bid.bidId].AvailableSizes = sizesArray.join(','); return accumulator; }, {}), PageRefreshed: getPageRefreshed() From 761226f43683ce5fd0071d496499ea894debdcba Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Wed, 28 Aug 2019 17:02:43 -0400 Subject: [PATCH 1452/1594] Long form video price bucket bugfix (#4125) * long form price bucket bugfix * updated logic to use medium as default granularity * remove unused import * use contants * move functions to auction module --- modules/adpod.js | 11 +- src/auction.js | 55 ++++--- test/spec/modules/adpod_spec.js | 162 ++++++++++++++++++++- test/spec/modules/dfpAdServerVideo_spec.js | 16 +- 4 files changed, 210 insertions(+), 34 deletions(-) diff --git a/modules/adpod.js b/modules/adpod.js index c678c854dc1..875809b8df5 100644 --- a/modules/adpod.js +++ b/modules/adpod.js @@ -13,7 +13,7 @@ */ import * as utils from '../src/utils'; -import { addBidToAuction, doCallbacksIfTimedout, AUCTION_IN_PROGRESS, callPrebidCache } from '../src/auction'; +import { addBidToAuction, doCallbacksIfTimedout, AUCTION_IN_PROGRESS, callPrebidCache, getPriceByGranularity, getPriceGranularity } from '../src/auction'; import { checkAdUnitSetup } from '../src/prebid'; import { checkVideoBidSetup } from '../src/video'; import { setupBeforeHookFnOnce, module } from '../src/hook'; @@ -23,6 +23,7 @@ import { ADPOD } from '../src/mediaTypes'; import Set from 'core-js/library/fn/set'; import find from 'core-js/library/fn/array/find'; import { auctionManager } from '../src/auctionManager'; +import CONSTANTS from '../src/constants.json'; const from = require('core-js/library/fn/array/from'); @@ -119,7 +120,9 @@ function createDispatcher(timeoutDuration) { function attachPriceIndustryDurationKeyToBid(bid, brandCategoryExclusion) { let initialCacheKey = bidCacheRegistry.getInitialCacheKey(bid); let duration = utils.deepAccess(bid, 'video.durationBucket'); - let cpmFixed = bid.cpm.toFixed(2); + const granularity = getPriceGranularity(bid.mediaType); + let cpmFixed = getPriceByGranularity(granularity)(bid); + let pcd; if (brandCategoryExclusion) { @@ -424,10 +427,10 @@ export function callPrebidCacheAfterAuction(bids, callback) { * @param {Object} bid */ export function sortByPricePerSecond(a, b) { - if (a.cpm / a.video.durationBucket < b.cpm / b.video.durationBucket) { + if (a.adserverTargeting[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] / a.video.durationBucket < b.adserverTargeting[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] / b.video.durationBucket) { return 1; } - if (a.cpm / a.video.durationBucket > b.cpm / b.video.durationBucket) { + if (a.adserverTargeting[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] / a.video.durationBucket > b.adserverTargeting[CONSTANTS.TARGETING_KEYS.PRICE_BUCKET] / b.video.durationBucket) { return -1; } return 0; diff --git a/src/auction.js b/src/auction.js index a1e8c33adfb..fd29aec4b16 100644 --- a/src/auction.js +++ b/src/auction.js @@ -510,6 +510,41 @@ function setupBidTargeting(bidObject, bidderRequest) { bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); } +/** + * This function returns the price granularity defined. It can be either publisher defined or default value + * @param {string} mediaType + * @returns {string} granularity + */ +export const getPriceGranularity = (mediaType) => { + // Use the config value 'mediaTypeGranularity' if it has been set for mediaType, else use 'priceGranularity' + const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${mediaType}`); + const granularity = (typeof mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); + return granularity; +} + +/** + * This function returns a function to get bid price by price granularity + * @param {string} granularity + * @returns {function} + */ +export const getPriceByGranularity = (granularity) => { + return (bid) => { + if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { + return bid.pbAg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { + return bid.pbDg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { + return bid.pbLg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { + return bid.pbMg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { + return bid.pbHg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { + return bid.pbCg; + } + } +} + /** * @param {string} mediaType * @param {string} bidderCode @@ -530,9 +565,7 @@ export function getStandardBidderSettings(mediaType, bidderCode) { }; } const TARGETING_KEYS = CONSTANTS.TARGETING_KEYS; - // Use the config value 'mediaTypeGranularity' if it has been set for mediaType, else use 'priceGranularity' - const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${mediaType}`); - const granularity = (typeof mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); + const granularity = getPriceGranularity(mediaType); let bidderSettings = $$PREBID_GLOBAL$$.bidderSettings; if (!bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { @@ -542,21 +575,7 @@ export function getStandardBidderSettings(mediaType, bidderCode) { 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, function(bidResponse) { - if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { - return bidResponse.pbAg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { - return bidResponse.pbDg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { - return bidResponse.pbLg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { - return bidResponse.pbMg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { - return bidResponse.pbHg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { - return bidResponse.pbCg; - } - }), + createKeyVal(TARGETING_KEYS.PRICE_BUCKET, getPriceByGranularity(granularity)), createKeyVal(TARGETING_KEYS.SIZE, 'size'), createKeyVal(TARGETING_KEYS.DEAL, 'dealId'), createKeyVal(TARGETING_KEYS.SOURCE, 'source'), diff --git a/test/spec/modules/adpod_spec.js b/test/spec/modules/adpod_spec.js index 507a3be9f14..8b7701c5631 100644 --- a/test/spec/modules/adpod_spec.js +++ b/test/spec/modules/adpod_spec.js @@ -99,6 +99,10 @@ describe('adpod.js', function () { auctionId: 'no_defer_123', mediaType: 'video', cpm: 5, + pbMg: '5.00', + adserverTargeting: { + hb_pb: '5.00' + }, meta: { adServerCatId: 'test' }, @@ -114,6 +118,10 @@ describe('adpod.js', function () { auctionId: 'no_defer_123', mediaType: 'video', cpm: 12, + pbMg: '12.00', + adserverTargeting: { + hb_pb: '12.00' + }, meta: { adServerCatId: 'value' }, @@ -175,6 +183,10 @@ describe('adpod.js', function () { auctionId: 'full_abc123', mediaType: 'video', cpm: 10, + pbMg: '10.00', + adserverTargeting: { + hb_pb: '10.00' + }, meta: { adServerCatId: 'airline' }, @@ -189,6 +201,10 @@ describe('adpod.js', function () { auctionId: 'full_abc123', mediaType: 'video', cpm: 15, + pbMg: '15.00', + adserverTargeting: { + hb_pb: '15.00' + }, meta: { adServerCatId: 'airline' }, @@ -247,6 +263,10 @@ describe('adpod.js', function () { auctionId: 'timer_abc234', mediaType: 'video', cpm: 15, + pbMg: '15.00', + adserverTargeting: { + hb_pb: '15.00' + }, meta: { adServerCatId: 'airline' }, @@ -300,6 +320,10 @@ describe('adpod.js', function () { auctionId: 'multi_call_abc345', mediaType: 'video', cpm: 15, + pbMg: '15.00', + adserverTargeting: { + hb_pb: '15.00' + }, meta: { adServerCatId: 'airline' }, @@ -314,6 +338,10 @@ describe('adpod.js', function () { auctionId: 'multi_call_abc345', mediaType: 'video', cpm: 15, + pbMg: '15.00', + adserverTargeting: { + hb_pb: '15.00' + }, meta: { adServerCatId: 'news' }, @@ -328,6 +356,10 @@ describe('adpod.js', function () { auctionId: 'multi_call_abc345', mediaType: 'video', cpm: 10, + pbMg: '10.00', + adserverTargeting: { + hb_pb: '10.00' + }, meta: { adServerCatId: 'sports' }, @@ -395,6 +427,10 @@ describe('adpod.js', function () { auctionId: 'no_category_abc345', mediaType: 'video', cpm: 10, + pbMg: '10.00', + adserverTargeting: { + hb_pb: '10.00' + }, meta: { adServerCatId: undefined }, @@ -409,6 +445,10 @@ describe('adpod.js', function () { auctionId: 'no_category_abc345', mediaType: 'video', cpm: 15, + pbMg: '15.00', + adserverTargeting: { + hb_pb: '15.00' + }, meta: { adServerCatId: undefined }, @@ -525,6 +565,10 @@ describe('adpod.js', function () { auctionId: 'duplicate_def123', mediaType: 'video', cpm: 5, + pbMg: '5.00', + adserverTargeting: { + hb_pb: '5.00' + }, meta: { adServerCatId: 'tech' }, @@ -539,6 +583,10 @@ describe('adpod.js', function () { auctionId: 'duplicate_def123', mediaType: 'video', cpm: 5, + pbMg: '5.00', + adserverTargeting: { + hb_pb: '5.00' + }, meta: { adServerCatId: 'tech' }, @@ -642,6 +690,82 @@ describe('adpod.js', function () { expect(logWarnStub.calledOnce).to.equal(true); expect(auctionBids.length).to.equal(0); }); + + it('should use bid.adserverTargeting.hb_pb when custom price granularity is configured', function() { + storeStub.callsFake(fakeStoreFn); + + const customConfigObject = { + 'buckets': [{ + 'precision': 2, // default is 2 if omitted - means 2.1234 rounded to 2 decimal places = 2.12 + 'min': 0, + 'max': 5, + 'increment': 0.01 // from $0 to $5, 1-cent increments + }, + { + 'precision': 2, + 'min': 5, + 'max': 8, + 'increment': 0.05 // from $5 to $8, round down to the previous 5-cent increment + }, + { + 'precision': 2, + 'min': 8, + 'max': 40, + 'increment': 0.5 // from $8 to $40, round down to the previous 50-cent increment + }] + }; + config.setConfig({ + priceGranularity: customConfigObject, + adpod: { + brandCategoryExclusion: true + } + }); + + let bidResponse1 = { + adId: 'cat_ad1', + auctionId: 'test_category_abc345', + mediaType: 'video', + cpm: 15, + pbAg: '15.00', + pbCg: '15.00', + pbDg: '15.00', + pbHg: '15.00', + pbLg: '5.00', + pbMg: '15.00', + adserverTargeting: { + hb_pb: '15.00', + }, + meta: { + adServerCatId: 'test' + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + + 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, bidderRequest); + + expect(callbackResult).to.be.null; + expect(afterBidAddedSpy.calledOnce).to.equal(true); + expect(storeStub.called).to.equal(false); + expect(auctionBids.length).to.equal(1); + }); }); describe('checkAdUnitSetupHook', function () { @@ -1021,53 +1145,83 @@ describe('adpod.js', function () { it('should sort bids array', function() { let bids = [{ cpm: 10.12345, + adserverTargeting: { + hb_pb: '10.00', + }, video: { durationBucket: 15 } }, { cpm: 15, + adserverTargeting: { + hb_pb: '15.00', + }, video: { durationBucket: 15 } }, { cpm: 15.00, + adserverTargeting: { + hb_pb: '15.00', + }, video: { durationBucket: 30 } }, { cpm: 5.45, + adserverTargeting: { + hb_pb: '5.00', + }, video: { durationBucket: 5 } }, { cpm: 20.1234567, + adserverTargeting: { + hb_pb: '20.10', + }, video: { durationBucket: 60 } }] bids.sort(sortByPricePerSecond); let sortedBids = [{ - cpm: 5.45, + cpm: 15, + adserverTargeting: { + hb_pb: '15.00', + }, video: { - durationBucket: 5 + durationBucket: 15 } }, { - cpm: 15, + cpm: 5.45, + adserverTargeting: { + hb_pb: '5.00', + }, video: { - durationBucket: 15 + durationBucket: 5 } }, { cpm: 10.12345, + adserverTargeting: { + hb_pb: '10.00', + }, video: { durationBucket: 15 } }, { cpm: 15.00, + adserverTargeting: { + hb_pb: '15.00', + }, video: { durationBucket: 30 } }, { cpm: 20.1234567, + adserverTargeting: { + hb_pb: '20.10', + }, video: { durationBucket: 60 } diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 62b0a752f50..bd417189aef 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -402,9 +402,9 @@ describe('The DFP video support module', function () { }); function getBids() { let bids = [ - createBid(10, 'adUnitCode-1', 15, '10.00_15s', '123', '395'), - createBid(15, 'adUnitCode-1', 15, '15.00_15s', '123', '395'), - createBid(25, 'adUnitCode-1', 30, '15.00_30s', '123', '406'), + createBid(10, 'adUnitCode-1', 15, '10.00_15s', '123', '395', '10.00'), + createBid(15, 'adUnitCode-1', 15, '15.00_15s', '123', '395', '15.00'), + createBid(25, 'adUnitCode-1', 30, '15.00_30s', '123', '406', '25.00'), ]; bids.forEach((bid) => { delete bid.meta; @@ -480,13 +480,13 @@ describe('The DFP video support module', function () { function getBidsReceived() { return [ - createBid(10, 'adUnitCode-1', 15, '10.00_395_15s', '123', '395'), - createBid(15, 'adUnitCode-1', 15, '15.00_395_15s', '123', '395'), - createBid(25, 'adUnitCode-1', 30, '15.00_406_30s', '123', '406'), + createBid(10, 'adUnitCode-1', 15, '10.00_395_15s', '123', '395', '10.00'), + createBid(15, 'adUnitCode-1', 15, '15.00_395_15s', '123', '395', '15.00'), + createBid(25, 'adUnitCode-1', 30, '15.00_406_30s', '123', '406', '25.00'), ] } -function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, label) { +function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, label, hbpb) { return { 'bidderCode': 'appnexus', 'width': 640, @@ -526,7 +526,7 @@ function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, 'adserverTargeting': { 'hb_bidder': 'appnexus', 'hb_adid': '28f24ced14586c', - 'hb_pb': '5.00', + 'hb_pb': hbpb, 'hb_size': '640x360', 'hb_source': 'client', 'hb_format': 'video', From 2005af4e628883c6b09c0e76b77c96575bef0c91 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 28 Aug 2019 17:06:25 -0400 Subject: [PATCH 1453/1594] Prebid 2.30.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b802a31e78e..d3e160d219b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.30.0-pre", + "version": "2.30.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 099a723aa38e4fe57095fbc27876cb12e2272af6 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 28 Aug 2019 17:14:50 -0400 Subject: [PATCH 1454/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3e160d219b..ee90af7522f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.30.0", + "version": "2.31.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 87e84b8aba3a521ae3e89a22c013be025a1e54c5 Mon Sep 17 00:00:00 2001 From: Michael Callari Date: Thu, 29 Aug 2019 12:16:22 -0400 Subject: [PATCH 1455/1594] Optimera added optional device param (#4105). (#4106) * Optimera added optional device param (#4105). * Updating to use deepAccess util method (#4105). * Condensing dealId check (#4105). --- modules/optimeraBidAdapter.js | 34 +++++++++++--------- modules/optimeraBidAdapter.md | 6 ++-- test/spec/modules/optimeraBidAdapter_spec.js | 26 ++++++++++++++- 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/modules/optimeraBidAdapter.js b/modules/optimeraBidAdapter.js index 7025045c7de..bc4407ababa 100644 --- a/modules/optimeraBidAdapter.js +++ b/modules/optimeraBidAdapter.js @@ -1,4 +1,5 @@ import { registerBidder } from '../src/adapters/bidderFactory'; +import { deepAccess } from '../src/utils'; const BIDDER_CODE = 'optimera'; const SCORES_BASE_URL = 'https://dyv1bugovvq1g.cloudfront.net/'; @@ -11,12 +12,11 @@ export const spec = { * @param {bidRequest} bid The bid params to validate. * @return boolean True if this is a valid bid, and false otherwise. */ - isBidRequestValid: function (bidRequest) { + isBidRequestValid (bidRequest) { if (typeof bidRequest.params !== 'undefined' && typeof bidRequest.params.clientID !== 'undefined') { return true; - } else { - return false; } + return false; }, /** * Make a server request from the list of BidRequests. @@ -27,18 +27,19 @@ export const spec = { * @param {validBidRequests[]} - an array of bids * @return ServerRequest Info describing the request to the server. */ - buildRequests: function (validBidRequests) { - let optimeraHost = window.location.host; - let optimeraPathName = window.location.pathname; + buildRequests (validBidRequests) { + const optimeraHost = window.location.host; + const optimeraPathName = window.location.pathname; if (typeof validBidRequests[0].params.clientID !== 'undefined') { - let clientID = validBidRequests[0].params.clientID; - let scoresURL = SCORES_BASE_URL + clientID + '/' + optimeraHost + optimeraPathName + '.js'; + const { clientID } = validBidRequests[0].params; + const scoresURL = `${SCORES_BASE_URL + clientID}/${optimeraHost}${optimeraPathName}.js`; return { method: 'GET', url: scoresURL, payload: validBidRequests, }; } + return {}; }, /** * Unpack the response from the server into a list of bids. @@ -49,24 +50,25 @@ export const spec = { * @param {*} serverResponse A successful response from the server. * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse, bidRequest) { - let validBids = bidRequest.payload; - let bidResponses = []; + interpretResponse (serverResponse, bidRequest) { + const validBids = bidRequest.payload; + const bidResponses = []; let dealId = ''; if (typeof serverResponse.body !== 'undefined') { - let scores = serverResponse.body; - for (let i = 0; i < validBids.length; i++) { + const scores = serverResponse.body; + for (let i = 0; i < validBids.length; i += 1) { if (typeof validBids[i].params.clientID !== 'undefined') { if (validBids[i].adUnitCode in scores) { - dealId = scores[validBids[i].adUnitCode]; + const deviceDealId = deepAccess(scores, `device.${validBids[i].params.device}.${validBids[i].adUnitCode}`); + dealId = deviceDealId || scores[validBids[i].adUnitCode]; } - let bidResponse = { + const bidResponse = { requestId: validBids[i].bidId, ad: '
    ', cpm: 0.01, width: 0, height: 0, - dealId: dealId, + dealId, ttl: 300, creativeId: '1', netRevenue: '0', diff --git a/modules/optimeraBidAdapter.md b/modules/optimeraBidAdapter.md index 909c0a46cd6..25da9b6236f 100644 --- a/modules/optimeraBidAdapter.md +++ b/modules/optimeraBidAdapter.md @@ -19,7 +19,8 @@ Module that adds ad placement visibility scores for DFP. { bidder: 'optimera', params: { - clientID: '9999' + clientID: '9999', + device: 'mo' } }] },{ @@ -29,7 +30,8 @@ Module that adds ad placement visibility scores for DFP. { bidder: 'optimera', params: { - clientID: '9999' + clientID: '9999', + device: 'mo' } }] }]; diff --git a/test/spec/modules/optimeraBidAdapter_spec.js b/test/spec/modules/optimeraBidAdapter_spec.js index d164c4dbb30..a0111ca9944 100644 --- a/test/spec/modules/optimeraBidAdapter_spec.js +++ b/test/spec/modules/optimeraBidAdapter_spec.js @@ -52,7 +52,7 @@ describe('OptimeraAdapter', function () { describe('interpretResponse', function () { let serverResponse = {}; - serverResponse.body = JSON.parse('{"div-0":["RB_K","728x90K"], "timestamp":["RB_K","1507565666"]}'); + serverResponse.body = JSON.parse('{"div-0":["RB_K","728x90K"], "timestamp":["RB_K","1507565666"], "device": { "de": { "div-0":["A1","728x90K"] }, "mo": { "div-0":["RB_K","728x90K"] }, "tb": { "div-0":["RB_K","728x90K"] } } }'); var bidRequest = { 'method': 'get', 'payload': [ @@ -72,4 +72,28 @@ describe('OptimeraAdapter', function () { expect(bidResponses[0].dealId[1]).to.equal('728x90K'); }); }); + + describe('interpretResponse with optional device param', function () { + let serverResponse = {}; + serverResponse.body = JSON.parse('{"div-0":["RB_K","728x90K"], "timestamp":["RB_K","1507565666"], "device": { "de": { "div-0":["A1","728x90K"] }, "mo": { "div-0":["RB_K","728x90K"] }, "tb": { "div-0":["RB_K","728x90K"] } } }'); + var bidRequest = { + 'method': 'get', + 'payload': [ + { + 'bidder': 'optimera', + 'params': { + 'clientID': '0', + 'device': 'de' + }, + 'adUnitCode': 'div-0', + 'bidId': '307440db8538ab' + } + ] + } + it('interpresResponse fires', function () { + let bidResponses = spec.interpretResponse(serverResponse, bidRequest); + expect(bidResponses[0].dealId[0]).to.equal('A1'); + expect(bidResponses[0].dealId[1]).to.equal('728x90K'); + }); + }); }); From a7ad5ef0c7284147c0027cbf4317997542a232d7 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Thu, 29 Aug 2019 19:36:13 -0700 Subject: [PATCH 1456/1594] SupplyChain object support in Prebid (#4084) * moving dctr related code in a function * moving parsedRequest variable out of the loop and moving GDPR related block at bottom * added a todo comment * exporting hasOwn function * added functionality to pass schain object - adapter manager will validate schain object - if it is valid then only it can be passed on to all bidders - bidders do not need to validate again * changed logMessage to logError - also fixed isInteger check * Moved schain related code from adapaterManager.js to schain.js * indentation chnages * logical bug fix * added test cases for schain * PubMatic: pass schain object in request * indentation * unit test for PubMatic schain support * using isInteger from utils * moved schain as a module * indentation * removed commented code * added try-catch as the statement code was breaking CI for IE-11 * Revert "added try-catch as the statement code was breaking CI for IE-11" This reverts commit 88f495f156a5f9db894de1728ebd7c5020882f31. * added a try-catch for a staement as it was breaking CI sometimes * added schain.md for schain module * added a few links * fixed typos * simplified the approach in adpater code * trying to restart CI * Revert "trying to restart CI" This reverts commit 25f877c1e760abb950d37d58f5d007e54ac2e179. * adding support in prebidServerBidAdpater as well * bug fix * minor changes - moved consts out of function - added a error log on finding an invalid schain object * modified a comment * added name to a test case * Revert "added a try-catch for a staement as it was breaking CI sometimes" This reverts commit e9606bfd348dc16c108ec3af807b95586ece5bbe. * moving schain validation logic inside PM adapter * Revert "moving schain validation logic inside PM adapter" This reverts commit 31d00d5f957ded9c8ed184af59dd24e1177c4b35. * added validation mode: strict, relaxed, off * updated documentation * moved a comment * changed value in example --- modules/prebidServerBidAdapter/index.js | 8 + modules/pubmaticBidAdapter.js | 92 +++--- modules/schain.js | 147 ++++++++++ modules/schain.md | 50 ++++ src/utils.js | 2 +- .../modules/prebidServerBidAdapter_spec.js | 25 ++ test/spec/modules/pubmaticBidAdapter_spec.js | 23 +- test/spec/modules/schain_spec.js | 269 ++++++++++++++++++ 8 files changed, 575 insertions(+), 41 deletions(-) create mode 100644 modules/schain.js create mode 100644 modules/schain.md create mode 100644 test/spec/modules/schain_spec.js diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 2ae32dd1df2..7ffaf9988dd 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -685,6 +685,14 @@ const OPEN_RTB_PROTOCOL = { utils.deepSetValue(request, 'user.ext.digitrust', digiTrust); } + // pass schain object if it is present + const schain = utils.deepAccess(bidRequests, '0.bids.0.schain'); + if (schain) { + request.source.ext = { + schain: schain + }; + } + if (!utils.isEmpty(aliases)) { request.ext.prebid.aliases = aliases; } diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 245ca3e60c9..facecdaa578 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -738,6 +738,38 @@ function _blockedIabCategoriesValidation(payload, blockedIabCategories) { } } +function _handleDealCustomTargetings(payload, dctrArr, validBidRequests) { + var dctr = ''; + var dctrLen; + // set dctr value in site.ext, if present in validBidRequests[0], else ignore + if (dctrArr.length > 0) { + if (validBidRequests[0].params.hasOwnProperty('dctr')) { + dctr = validBidRequests[0].params.dctr; + if (utils.isStr(dctr) && dctr.length > 0) { + var arr = dctr.split('|'); + dctr = ''; + arr.forEach(val => { + dctr += (val.length > 0) ? (val.trim() + '|') : ''; + }); + dctrLen = dctr.length; + if (dctr.substring(dctrLen, dctrLen - 1) === '|') { + dctr = dctr.substring(0, dctrLen - 1); + } + payload.site.ext = { + key_val: dctr.trim() + } + } else { + utils.logWarn(LOG_WARN_PREFIX + 'Ignoring param : dctr with value : ' + dctr + ', expects string-value, found empty or non-string value'); + } + if (dctrArr.length > 1) { + utils.logWarn(LOG_WARN_PREFIX + 'dctr value found in more than 1 adunits. Value from 1st adunit will be picked. Ignoring values from subsequent adunits'); + } + } else { + utils.logWarn(LOG_WARN_PREFIX + 'dctr value not found in 1st adunit, ignoring values from subsequent adunits'); + } + } +} + export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER, VIDEO, NATIVE], @@ -779,11 +811,10 @@ export const spec = { var conf = _initConf(refererInfo); var payload = _createOrtbTemplate(conf); var bidCurrency = ''; - var dctr = ''; - var dctrLen; var dctrArr = []; var bid; var blockedIabCategories = []; + validBidRequests.forEach(originalBid => { bid = utils.deepClone(originalBid); bid.params.adSlot = bid.params.adSlot || ''; @@ -835,6 +866,21 @@ export const spec = { payload.ext.wrapper.wp = 'pbjs'; payload.user.gender = (conf.gender ? conf.gender.trim() : UNDEFINED); payload.user.geo = {}; + payload.user.geo.lat = _parseSlotParam('lat', conf.lat); + payload.user.geo.lon = _parseSlotParam('lon', conf.lon); + payload.user.yob = _parseSlotParam('yob', conf.yob); + payload.device.geo = payload.user.geo; + payload.site.page = conf.kadpageurl.trim() || payload.site.page.trim(); + payload.site.domain = _getDomainFromURL(payload.site.page); + + // adding schain object + if (validBidRequests[0].schain) { + payload.source = { + ext: { + schain: validBidRequests[0].schain + } + }; + } // Attaching GDPR Consent Params if (bidderRequest && bidderRequest.gdprConsent) { @@ -849,43 +895,10 @@ export const spec = { }; } - payload.user.geo.lat = _parseSlotParam('lat', conf.lat); - payload.user.geo.lon = _parseSlotParam('lon', conf.lon); - payload.user.yob = _parseSlotParam('yob', conf.yob); - payload.device.geo = payload.user.geo; - payload.site.page = conf.kadpageurl.trim() || payload.site.page.trim(); - payload.site.domain = _getDomainFromURL(payload.site.page); - - // set dctr value in site.ext, if present in validBidRequests[0], else ignore - if (dctrArr.length > 0) { - if (validBidRequests[0].params.hasOwnProperty('dctr')) { - dctr = validBidRequests[0].params.dctr; - if (utils.isStr(dctr) && dctr.length > 0) { - var arr = dctr.split('|'); - dctr = ''; - arr.forEach(val => { - dctr += (val.length > 0) ? (val.trim() + '|') : ''; - }); - dctrLen = dctr.length; - if (dctr.substring(dctrLen, dctrLen - 1) === '|') { - dctr = dctr.substring(0, dctrLen - 1); - } - payload.site.ext = { - key_val: dctr.trim() - } - } else { - utils.logWarn(LOG_WARN_PREFIX + 'Ignoring param : dctr with value : ' + dctr + ', expects string-value, found empty or non-string value'); - } - if (dctrArr.length > 1) { - utils.logWarn(LOG_WARN_PREFIX + 'dctr value found in more than 1 adunits. Value from 1st adunit will be picked. Ignoring values from subsequent adunits'); - } - } else { - utils.logWarn(LOG_WARN_PREFIX + 'dctr value not found in 1st adunit, ignoring values from subsequent adunits'); - } - } - + _handleDealCustomTargetings(payload, dctrArr, validBidRequests); _handleEids(payload, validBidRequests); _blockedIabCategoriesValidation(payload, blockedIabCategories); + return { method: 'POST', url: ENDPOINT, @@ -902,6 +915,8 @@ export const spec = { interpretResponse: (response, request) => { const bidResponses = []; var respCur = DEFAULT_CURRENCY; + let parsedRequest = JSON.parse(request.data); + let parsedReferrer = parsedRequest.site && parsedRequest.site.ref ? parsedRequest.site.ref : ''; try { if (response.body && response.body.seatbid && utils.isArray(response.body.seatbid)) { // Supporting multiple bid responses for same adSize @@ -910,7 +925,6 @@ export const spec = { seatbidder.bid && utils.isArray(seatbidder.bid) && seatbidder.bid.forEach(bid => { - let parsedRequest = JSON.parse(request.data); let newBid = { requestId: bid.impid, cpm: (parseFloat(bid.price) || 0).toFixed(2), @@ -921,7 +935,7 @@ export const spec = { currency: respCur, netRevenue: NET_REVENUE, ttl: 300, - referrer: parsedRequest.site && parsedRequest.site.ref ? parsedRequest.site.ref : '', + referrer: parsedReferrer, ad: bid.adm }; if (parsedRequest.imp && parsedRequest.imp.length > 0) { diff --git a/modules/schain.js b/modules/schain.js new file mode 100644 index 00000000000..000b13615e5 --- /dev/null +++ b/modules/schain.js @@ -0,0 +1,147 @@ +import {config} from '../src/config'; +import {getGlobal} from '../src/prebidGlobal'; +import { isNumber, isStr, isArray, isPlainObject, hasOwn, logError, isInteger } from '../src/utils'; + +// https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md + +const schainErrorPrefix = 'Invalid schain object found: '; +const shouldBeAString = ' should be a string'; +const shouldBeAnInteger = ' should be an Integer'; +const shouldBeAnObject = ' should be an object'; +const shouldBeAnArray = ' should be an Array'; +const MODE = { + STRICT: 'strict', + RELAXED: 'relaxed', + OFF: 'off' +}; + +// validate the supply chain object +export function isSchainObjectValid(schainObject, returnOnError) { + if (!isPlainObject(schainObject)) { + logError(schainErrorPrefix + `schain` + shouldBeAnObject); + if (returnOnError) return false; + } + + // complete: Integer + if (!isNumber(schainObject.complete) || !isInteger(schainObject.complete)) { + logError(schainErrorPrefix + `schain.complete` + shouldBeAnInteger); + if (returnOnError) return false; + } + + // ver: String + if (!isStr(schainObject.ver)) { + logError(schainErrorPrefix + `schain.ver` + shouldBeAString); + if (returnOnError) return false; + } + + // ext: Object [optional] + if (hasOwn(schainObject, 'ext')) { + if (!isPlainObject(schainObject.ext)) { + logError(schainErrorPrefix + `schain.ext` + shouldBeAnObject); + if (returnOnError) return false; + } + } + + // nodes: Array of objects + if (!isArray(schainObject.nodes)) { + logError(schainErrorPrefix + `schain.nodes` + shouldBeAnArray); + if (returnOnError) return false; + } + + // now validate each node + let isEachNodeIsValid = true; + schainObject.nodes.forEach(node => { + // asi: String + if (!isStr(node.asi)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].asi` + shouldBeAString); + } + + // sid: String + if (!isStr(node.sid)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].sid` + shouldBeAString); + } + + // hp: Integer + if (!isNumber(node.hp) || !isInteger(node.hp)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].hp` + shouldBeAnInteger); + } + + // rid: String [Optional] + if (hasOwn(node, 'rid')) { + if (!isStr(node.rid)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].rid` + shouldBeAString); + } + } + + // name: String [Optional] + if (hasOwn(node, 'name')) { + if (!isStr(node.name)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].name` + shouldBeAString); + } + } + + // domain: String [Optional] + if (hasOwn(node, 'domain')) { + if (!isStr(node.domain)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].domain` + shouldBeAString); + } + } + + // ext: Object [Optional] + if (hasOwn(node, 'ext')) { + if (!isPlainObject(node.ext)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].ext` + shouldBeAnObject); + } + } + }); + + if (returnOnError && !isEachNodeIsValid) { + return false; + } + + return true; +} + +export function copySchainObjectInAdunits(adUnits, schainObject) { + // copy schain object in all adUnits as adUnits[].bid.schain + adUnits.forEach(adUnit => { + adUnit.bids.forEach(bid => { + bid.schain = schainObject; + }); + }); +} + +export function init(config) { + let mode = MODE.STRICT; + getGlobal().requestBids.before(function(fn, reqBidsConfigObj) { + let schainObject = config.getConfig('schain'); + if (!isPlainObject(schainObject)) { + logError(schainErrorPrefix + 'schain config will not be passed to bidders as schain is not an object.'); + } else { + if (isStr(schainObject.validation) && Object.values(MODE).indexOf(schainObject.validation) != -1) { + mode = schainObject.validation; + } + if (mode === MODE.OFF) { + // no need to validate + copySchainObjectInAdunits(reqBidsConfigObj.adUnits || getGlobal().adUnits, schainObject.config); + } else { + if (isSchainObjectValid(schainObject.config, mode === MODE.STRICT)) { + copySchainObjectInAdunits(reqBidsConfigObj.adUnits || getGlobal().adUnits, schainObject.config); + } else { + logError(schainErrorPrefix + 'schain config will not be passed to bidders as it is not valid.'); + } + } + } + // calling fn allows prebid to continue processing + return fn.call(this, reqBidsConfigObj); + }, 40); +} + +init(config) diff --git a/modules/schain.md b/modules/schain.md new file mode 100644 index 00000000000..0adf68c19e5 --- /dev/null +++ b/modules/schain.md @@ -0,0 +1,50 @@ +# schain module + +Aggregators who manage Prebid wrappers on behalf of multiple publishers need to declare their intermediary status in the Supply Chain Object. +As the spec prohibits us from adding upstream intermediaries, Prebid requests in this case need to come with the schain information. +In this use case, it's seems cumbersome to have every bidder in the wrapper separately configured the same schain information. + +Refer: +- https://iabtechlab.com/sellers-json/ +- https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md + +## Sample code for passing the schain object +``` +pbjs.setConfig( { + "schain": + "validation": "strict", + "config": { + "ver":"1.0", + "complete": 1, + "nodes": [ + { + "asi":"indirectseller.com", + "sid":"00001", + "hp":1 + }, + + { + "asi":"indirectseller-2.com", + "sid":"00002", + "hp":0 + }, + ] + } + } +}); +``` + +## Workflow +The schain module is not enabled by default as it may not be neccessary for all publishers. +If required, schain module can be included as following +``` + $ gulp build --modules=schain,pubmaticBidAdapter,openxBidAdapter,rubiconBidAdapter,sovrnBidAdapter +``` +The schain module will validate the schain object passed using pbjs.setConfig API. +If the schain object is valid then it will be passed on to bidders/adapters in ```validBidRequests[].schain``` +You may refer pubmaticBidAdapter implementaion for the same. + +## Validation modes +- ```strict```: It is the default validation mode. In this mode, schain object will not be passed to adapters if it is invalid. Errors are thrown for invalid schain object. +- ```relaxed```: In this mode, errors are thrown for an invalid schain object but the invalid schain object is still passed to adapters. +- ```off```: In this mode, no validations are performed and schain object is passed as is to adapters. \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index 335cf8dbf68..21a1943b1a1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -571,7 +571,7 @@ export function _map(object, callback) { return output; } -var hasOwn = function (objectToCheck, propertyToCheckFor) { +export function hasOwn(objectToCheck, propertyToCheckFor) { if (objectToCheck.hasOwnProperty) { return objectToCheck.hasOwnProperty(propertyToCheckFor); } else { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 0542385c5d5..3331a985afa 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1237,6 +1237,31 @@ describe('S2S Adapter', function () { } }); }); + + it('passes schain object in request', function() { + const bidRequests = utils.deepClone(BID_REQUESTS); + const schainObject = { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 2 + } + ] + }; + bidRequests[0].bids[0].schain = schainObject; + adapter.callBids(REQUEST, bidRequests, addBidResponse, done, ajax); + const parsedRequestBody = JSON.parse(requests[0].requestBody); + expect(parsedRequestBody.source.ext.schain).to.deep.equal(schainObject); + }) }); describe('response handler', function () { diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 289e0f461ec..3de83c56213 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -24,8 +24,27 @@ describe('PubMatic adapter', function () { let bannerVideoAndNativeBidRequests; let bannerBidResponse; let videoBidResponse; + let schainConfig; beforeEach(function () { + schainConfig = { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 2 + } + ] + }; + bidRequests = [ { bidder: 'pubmatic', @@ -55,7 +74,8 @@ describe('PubMatic adapter', function () { bidId: '23acc48ad47af5', requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729', + schain: schainConfig } ]; @@ -728,6 +748,7 @@ describe('PubMatic adapter', function () { expect(data.imp[0].banner.h).to.equal(250); // height expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); + expect(data.source.ext.schain).to.deep.equal(bidRequests[0].schain); }); it('Request params check: without adSlot', function () { diff --git a/test/spec/modules/schain_spec.js b/test/spec/modules/schain_spec.js new file mode 100644 index 00000000000..02aaa4c47c4 --- /dev/null +++ b/test/spec/modules/schain_spec.js @@ -0,0 +1,269 @@ +import {isSchainObjectValid, copySchainObjectInAdunits} from '../../../modules/schain'; +import { expect } from 'chai'; + +describe('#isSchainObjectValid: schain object validation', function() { + let schainConfig; + + beforeEach(function() { + schainConfig = { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 2 + } + ] + }; + }); + + it('Return true for correct config', function() { + expect(isSchainObjectValid(schainConfig, true)).to.true; + }); + + it('Return false for string config', function() { + schainConfig = JSON.stringify(schainConfig); + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if complete param is not an Integer', function() { + schainConfig.complete = 1; // integer + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.complete = '1'; // string + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.complete = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.complete = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.complete; // undefined + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.complete = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.complete = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if version param is not a String', function() { + schainConfig.ver = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.ver = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.ver = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.ver; // undefined + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.ver = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.ver = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if ext param is not an Object', function() { + schainConfig.ext = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.ext = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.ext = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.true; + delete schainConfig.ext; // undefined // param is optional thus this will result true + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.ext = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.ext = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if nodes param is not an Array', function() { + // by default schainConfig.nodes is array + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.nodes = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.nodes; // undefined + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if nodes[].asi is not a String', function() { + schainConfig.nodes[0].asi = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].asi = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].asi = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.nodes[0].asi; // undefined + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].asi = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].asi = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if nodes[].sid is not a String', function() { + schainConfig.nodes[1].sid = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].sid = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].sid = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.nodes[0].sid; // undefined + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].sid = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].sid = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if nodes[].hp is not an Integer', function() { + schainConfig.nodes[0].hp = '1'; // string + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].hp = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].hp = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.nodes[0].hp; // undefined + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].hp = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].hp = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if nodes[].rid is not a String', function() { + schainConfig.nodes[1].rid = 'rid value'; // string + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.nodes[1].rid = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].rid = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].rid = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.nodes[1].rid; // undefined // param is optional thus this will result true + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.nodes[1].rid = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].rid = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if nodes[].name is not a String', function() { + schainConfig.nodes[0].name = 'name value'; // string + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.nodes[0].name = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].name = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].name = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.nodes[0].name; // undefined // param is optional thus this will result true + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.nodes[0].name = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].name = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if nodes[].domain is not a String', function() { + schainConfig.nodes[1].domain = 'domain value'; // string + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.nodes[1].domain = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].domain = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].domain = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.false; + delete schainConfig.nodes[1].domain; // undefined // param is optional thus this will result true + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.nodes[1].domain = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[1].domain = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Returns false if nodes[].ext param is not an Object', function() { + schainConfig.nodes[0].ext = 1; // Integer + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].ext = 1.1; // float + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].ext = {}; // object + expect(isSchainObjectValid(schainConfig, true)).to.true; + delete schainConfig.nodes[0].ext; // undefined // param is optional thus this will result true + expect(isSchainObjectValid(schainConfig, true)).to.true; + schainConfig.nodes[0].ext = true; // boolean + expect(isSchainObjectValid(schainConfig, true)).to.false; + schainConfig.nodes[0].ext = []; // array + expect(isSchainObjectValid(schainConfig, true)).to.false; + }); + + it('Relaxed mode: Returns true even for invalid config if second argument is set to false', function() { + schainConfig = { + 'ver': 1.0, // invalid + 'complete': '1', // invalid + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': 1, // invalid + 'hp': '1' // invalid + }, + + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 2 + } + ] + }; + expect(isSchainObjectValid(schainConfig, false)).to.true; + }) +}); + +describe('Passing schain object to adUnits', function() { + let schainConfig; + + beforeEach(function() { + schainConfig = { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 2 + } + ] + }; + }); + + it('schain object should be applied to all adUnits', function() { + let adUnits = [ + { + bids: [{}, {}] + }, + { + bids: [{}, {}] + } + ]; + copySchainObjectInAdunits(adUnits, schainConfig); + expect(adUnits[0].bids[0].schain).to.equal(schainConfig); + expect(adUnits[0].bids[1].schain).to.equal(schainConfig); + expect(adUnits[1].bids[0].schain).to.equal(schainConfig); + expect(adUnits[1].bids[1].schain).to.equal(schainConfig); + }); +}); From 3fe149a732e8a02565592d660053b2b2c4b29b10 Mon Sep 17 00:00:00 2001 From: Eddy Pechuzal <46331062+epechuzal@users.noreply.github.com> Date: Tue, 3 Sep 2019 01:44:53 -0700 Subject: [PATCH 1457/1594] Auto detect if we can bust out of iframe (#15) (#4099) * Add HTML5 video support param to bid requests * Use const instead of var for consistency * Update supported sizes - Default size returned changed from 0x0 to 1x1 to support PrebidServer - Now will always respect the bid sizes supported when configured Co-authored-by: Josh Becker * Update maintainer contact email * Support Prebid.js User ID module - Add support for Unified ID solution of User ID module by checking for `bidRequest.userId.tdid` param in `buildRequests` method of Sharethrough's adapter - Update specs, maintain 80%+ code coverage * Update logic for changing userAgent string in tests * Add 3 pbjs callbacks to the adapter * Add comments on empty implementations * Update Sharethrough endpoint * Add logic to detect safeframe * Remove console.log statements Fix issue with clientjs detection Small refactors (linting) Co-authored-by: Josh Becker * Continue work on safeframe detection spec Co-authored-by: Josh Becker * [WIP] * update version of sharethrough adapter from 3.0.1 to 3.1.0 * create sharethroughInternal const in adapter so that we can properly stub methods for testing, and utilize utility functions * rename safeframe detection and iframe JS tag insertion code * Finish iframe handler specs Refactor spec file * Change method of detecting whether locked in a frame or not * Add logic to detect safeframe * Remove console.log statements Fix issue with clientjs detection Small refactors (linting) Co-authored-by: Josh Becker * Continue work on safeframe detection spec Co-authored-by: Josh Becker * [WIP] * update version of sharethrough adapter from 3.0.1 to 3.1.0 * create sharethroughInternal const in adapter so that we can properly stub methods for testing, and utilize utility functions * rename safeframe detection and iframe JS tag insertion code * Finish iframe handler specs Refactor spec file * Change method of detecting whether locked in a frame or not --- modules/sharethroughBidAdapter.js | 92 +++++++++++---- .../modules/sharethroughBidAdapter_spec.js | 108 ++++++++++++------ 2 files changed, 143 insertions(+), 57 deletions(-) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index a7a64e0bda3..7fe41b2b7ae 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -1,10 +1,17 @@ import { registerBidder } from '../src/adapters/bidderFactory'; -const VERSION = '3.0.1'; +const VERSION = '3.1.0'; const BIDDER_CODE = 'sharethrough'; const STR_ENDPOINT = document.location.protocol + '//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 = { + b64EncodeUnicode, + handleIframe, + isLockedInFrame +}; + export const sharethroughAdapterSpec = { code: BIDDER_CODE, @@ -37,10 +44,10 @@ export const sharethroughAdapterSpec = { // Data that does not need to go to the server, // but we need as part of interpretResponse() const strData = { - stayInIframe: bidRequest.params.iframe, + skipIframeBusting: bidRequest.params.iframe, iframeSize: bidRequest.params.iframeSize, sizes: bidRequest.sizes - } + }; return { method: 'GET', @@ -59,7 +66,7 @@ export const sharethroughAdapterSpec = { const creative = body.creatives[0]; let size = DEFAULT_SIZE; if (req.strData.iframeSize || req.strData.sizes.length) { - size = req.strData.iframeSize != undefined + size = req.strData.iframeSize ? req.strData.iframeSize : getLargestSize(req.strData.sizes); } @@ -102,7 +109,7 @@ export const sharethroughAdapterSpec = { // Empty implementation for prebid core to be able to find it onSetTargeting: (bid) => {} -} +}; function getLargestSize(sizes) { function area(size) { @@ -125,35 +132,72 @@ function generateAd(body, req) {
    - ` + `; - if (req.strData.stayInIframe) { + if (req.strData.skipIframeBusting) { // Don't break out of iframe - adMarkup = adMarkup + `` + adMarkup = adMarkup + ``; } else { - // Break out of iframe + // 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 + ` - ` + (${sharethroughInternal.isLockedInFrame.toString()})() + + `; } return adMarkup; } +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 = '//native.sharethrough.com/assets/sfp-set-targeting.js'; + sfpIframeBusterJs.type = 'text/javascript'; + try { + window.document.getElementsByTagName('body')[0].appendChild(sfpIframeBusterJs); + iframeBusterLoaded = true; + } catch (e) { + console.error(e); + } + } + + var clientJsLoaded = (!iframeBusterLoaded) ? !!(window.STR && window.STR.Tag) : !!(window.top.STR && window.top.STR.Tag); + if (!clientJsLoaded) { + var sfpJs = document.createElement('script'); + sfpJs.src = '//native.sharethrough.com/assets/sfp.js'; + sfpJs.type = 'text/javascript'; + + // 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) { + console.error(e); + } + } +} + +// 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( diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index d8feac3d0a2..afa5f44959c 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { sharethroughAdapterSpec } from 'modules/sharethroughBidAdapter'; +import { sharethroughAdapterSpec, sharethroughInternal } from 'modules/sharethroughBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; const spec = newBidder(sharethroughAdapterSpec).getSpec(); @@ -46,7 +46,7 @@ const prebidRequests = [ placement_key: 'pKey' }, strData: { - stayInIframe: false, + skipIframeBusting: false, sizes: [] } }, @@ -58,7 +58,7 @@ const prebidRequests = [ placement_key: 'pKey' }, strData: { - stayInIframe: true, + skipIframeBusting: true, sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] } }, @@ -70,7 +70,7 @@ const prebidRequests = [ placement_key: 'pKey' }, strData: { - stayInIframe: true, + skipIframeBusting: true, iframeSize: [500, 500], sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] } @@ -83,7 +83,7 @@ const prebidRequests = [ placement_key: 'pKey' }, strData: { - stayInIframe: false, + skipIframeBusting: false, sizes: [[0, 0]] } }, @@ -95,7 +95,7 @@ const prebidRequests = [ placement_key: 'pKey' }, strData: { - stayInIframe: false, + skipIframeBusting: false, sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] } }, @@ -120,27 +120,71 @@ const bidderResponse = { header: { get: (header) => header } }; -// Mirrors the one in modules/sharethroughBidAdapter.js as the function is unexported -const b64EncodeUnicode = (str) => { - return btoa( - encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, - function toSolidBytes(match, p1) { - return String.fromCharCode('0x' + p1); - })); -} - const setUserAgent = (str) => { window.navigator['__defineGetter__']('userAgent', function () { return str; }); -} +}; + +describe('sharethrough internal spec', function () { + let windowSpy, windowTopSpy; + + beforeEach(function() { + windowSpy = sinon.spy(window.document, 'getElementsByTagName'); + windowTopSpy = sinon.spy(window.top.document, 'getElementsByTagName'); + }); + + afterEach(function() { + windowSpy.restore(); + windowTopSpy.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; + }); + + it('appends sfp.js to the safeframe', function () { + sharethroughInternal.handleIframe(); + expect(windowSpy.calledOnce).to.be.true; + }); + + it('does not append anything if sfp.js is already loaded in the safeframe', function () { + window.STR = { Tag: true }; + sharethroughInternal.handleIframe(); + expect(windowSpy.notCalled).to.be.true; + expect(windowTopSpy.notCalled).to.be.true; + }); + }); + + describe('we are able to bust out of the iframe', function () { + it('appends sfp.js to window.top', function () { + sharethroughInternal.handleIframe(); + expect(windowSpy.calledOnce).to.be.true; + expect(windowTopSpy.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(windowSpy.calledOnce).to.be.true; + expect(windowTopSpy.notCalled).to.be.true; + }); + }); +}); 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 () { @@ -176,7 +220,7 @@ describe('sharethrough adapter spec', function () { expect(builtBidRequests[0].url).to.eq( 'http://btlr.sharethrough.com/WYu2BXv1/v1'); expect(builtBidRequests[1].url).to.eq( - 'http://btlr.sharethrough.com/WYu2BXv1/v1') + 'http://btlr.sharethrough.com/WYu2BXv1/v1'); expect(builtBidRequests[0].method).to.eq('GET'); }); @@ -230,7 +274,7 @@ describe('sharethrough adapter spec', function () { const builtBidRequests = spec.buildRequests(bidRequests); expect(builtBidRequests[0]).to.deep.include({ strData: { - stayInIframe: undefined, + skipIframeBusting: undefined, iframeSize: undefined, sizes: [[600, 300]] } @@ -253,7 +297,7 @@ describe('sharethrough adapter spec', function () { }); }); - it('returns a correctly parsed out response with largest size when strData.stayInIframe is true', function () { + 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, @@ -267,7 +311,7 @@ describe('sharethrough adapter spec', function () { }); }); - it('returns a correctly parsed out response with explicitly defined size when strData.stayInIframe is true and strData.iframeSize is provided', function () { + 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, @@ -281,7 +325,7 @@ describe('sharethrough adapter spec', function () { }); }); - it('returns a correctly parsed out response with explicitly defined size when strData.stayInIframe is false and strData.sizes contains [0, 0] only', function () { + 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, @@ -295,7 +339,7 @@ describe('sharethrough adapter spec', function () { }); }); - it('returns a correctly parsed out response with explicitly defined size when strData.stayInIframe is false and strData.sizes contains multiple sizes', function () { + 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, @@ -324,29 +368,27 @@ describe('sharethrough adapter spec', function () { expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; }); - it('correctly generates ad markup', function () { + it('correctly generates ad markup when skipIframeBusting is false', function () { const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[0])[0].ad; let resp = null; expect(() => btoa(JSON.stringify(bidderResponse))).to.throw(); - expect(() => resp = b64EncodeUnicode(JSON.stringify(bidderResponse))).not.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( - /`; + 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); export function ImproveDigitalAdServerJSClient(endPoint) { this.CONSTANTS = { - HTTP_SECURITY: { - STANDARD: 0, - SECURE: 1 - }, AD_SERVER_BASE_URL: 'ice.360yield.com', END_POINT: endPoint || 'hb', AD_SERVER_URL_PARAM: 'jsonp=', - CLIENT_VERSION: 'JS-6.0.0', + CLIENT_VERSION: 'JS-6.2.0', MAX_URL_LENGTH: 2083, ERROR_CODES: { MISSING_PLACEMENT_PARAMS: 2, @@ -300,6 +355,7 @@ export function ImproveDigitalAdServerJSClient(endPoint) { } requestParameters.returnObjType = requestParameters.returnObjType || this.CONSTANTS.RETURN_OBJ_TYPE.DEFAULT; + requestParameters.adServerBaseUrl = 'https://' + (requestParameters.adServerBaseUrl || this.CONSTANTS.AD_SERVER_BASE_URL); let impressionObjects = []; let impressionObject; @@ -325,7 +381,7 @@ export function ImproveDigitalAdServerJSClient(endPoint) { } let errors = null; - let baseUrl = `${(requestParameters.secure === 1 ? 'https' : 'http')}://${this.CONSTANTS.AD_SERVER_BASE_URL}/${this.CONSTANTS.END_POINT}?${this.CONSTANTS.AD_SERVER_URL_PARAM}`; + let baseUrl = `${requestParameters.adServerBaseUrl}/${this.CONSTANTS.END_POINT}?${this.CONSTANTS.AD_SERVER_URL_PARAM}`; let bidRequestObject = { bid_request: this.createBasicBidRequestObject(requestParameters, extraRequestParameters) @@ -386,12 +442,11 @@ export function ImproveDigitalAdServerJSClient(endPoint) { case this.CONSTANTS.RETURN_OBJ_TYPE.URL_PARAMS_SPLIT: return { method: 'GET', - url: `//${this.CONSTANTS.AD_SERVER_BASE_URL}/${this.CONSTANTS.END_POINT}`, + url: `${requestParameters.adServerBaseUrl}/${this.CONSTANTS.END_POINT}`, data: `${this.CONSTANTS.AD_SERVER_URL_PARAM}${encodeURIComponent(JSON.stringify(bidRequestObject))}` }; default: - const baseUrl = `${(requestParameters.secure === 1 ? 'https' : 'http')}://` + - `${this.CONSTANTS.AD_SERVER_BASE_URL}/` + + const baseUrl = `${requestParameters.adServerBaseUrl}/` + `${this.CONSTANTS.END_POINT}?${this.CONSTANTS.AD_SERVER_URL_PARAM}`; return { url: baseUrl + encodeURIComponent(JSON.stringify(bidRequestObject)) @@ -401,6 +456,7 @@ export function ImproveDigitalAdServerJSClient(endPoint) { this.createBasicBidRequestObject = function(requestParameters, extraRequestParameters) { let impressionBidRequestObject = {}; + impressionBidRequestObject.secure = 1; if (requestParameters.requestId) { impressionBidRequestObject.id = requestParameters.requestId; } else { @@ -418,9 +474,6 @@ export function ImproveDigitalAdServerJSClient(endPoint) { if (requestParameters.callback) { impressionBidRequestObject.callback = requestParameters.callback; } - if ('secure' in requestParameters) { - impressionBidRequestObject.secure = requestParameters.secure; - } if (requestParameters.libVersion) { impressionBidRequestObject.version = requestParameters.libVersion + '-' + this.CONSTANTS.CLIENT_VERSION; } @@ -455,6 +508,12 @@ export function ImproveDigitalAdServerJSClient(endPoint) { if (placementObject.currency) { impressionObject.currency = placementObject.currency.toUpperCase(); } + if (placementObject.bidFloor) { + impressionObject.bidfloor = placementObject.bidFloor; + } + if (placementObject.bidFloorCur) { + impressionObject.bidfloorcur = placementObject.bidFloorCur.toUpperCase(); + } if (placementObject.placementId) { impressionObject.pid = placementObject.placementId; } diff --git a/modules/improvedigitalBidAdapter.md b/modules/improvedigitalBidAdapter.md index d70b624171f..15602d11038 100644 --- a/modules/improvedigitalBidAdapter.md +++ b/modules/improvedigitalBidAdapter.md @@ -2,7 +2,7 @@ **Module Name**: Improve Digital Bidder Adapter **Module Type**: Bidder Adapter -**Maintainer**: hb@improvedigital.com +**Maintainer**: hb@azerion.com # Description diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 6c78afca6b2..8b8f6c4bf4c 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -7,7 +7,7 @@ describe('Improve Digital Adapter Tests', function () { let idClient = new ImproveDigitalAdServerJSClient('hb'); const METHOD = 'GET'; - const URL = '//ice.360yield.com/hb'; + const URL = 'https://ice.360yield.com/hb'; const PARAM_PREFIX = 'jsonp='; const simpleBidRequest = { @@ -33,11 +33,17 @@ describe('Improve Digital Adapter Tests', function () { } }; - const bidderRequest = { - 'gdprConsent': { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'vendorData': {}, - 'gdprApplies': true + const bidderRequestGdpr = { + gdprConsent: { + consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + vendorData: {}, + gdprApplies: true + }, + }; + + const bidderRequestReferrer = { + refererInfo: { + referer: 'https://blah.com/test.html', }, }; @@ -151,13 +157,42 @@ describe('Improve Digital Adapter Tests', function () { getConfigStub.restore(); }); + it('should add bid floor', function () { + const bidRequest = Object.assign({}, simpleBidRequest); + let request = spec.buildRequests([bidRequest])[0]; + let params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + // Floor price currency shouldn't be populated without a floor price + expect(params.bid_request.imp[0].bidfloorcur).to.not.exist; + + // Default floor price currency + bidRequest.params.bidFloor = 0.05; + request = spec.buildRequests([bidRequest])[0]; + params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].bidfloor).to.equal(0.05); + expect(params.bid_request.imp[0].bidfloorcur).to.equal('USD'); + + // Floor price currency + bidRequest.params.bidFloorCur = 'eUR'; + request = spec.buildRequests([bidRequest])[0]; + params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].bidfloor).to.equal(0.05); + expect(params.bid_request.imp[0].bidfloorcur).to.equal('EUR'); + }); + it('should add GDPR consent string', function () { const bidRequest = Object.assign({}, simpleBidRequest); - const request = spec.buildRequests([bidRequest], bidderRequest)[0]; + const request = spec.buildRequests([bidRequest], bidderRequestGdpr)[0]; const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); expect(params.bid_request.gdpr).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); + it('should add referrer', function () { + const bidRequest = Object.assign({}, simpleBidRequest); + const request = spec.buildRequests([bidRequest], bidderRequestReferrer)[0]; + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.referrer).to.equal('https://blah.com/test.html'); + }); + it('should return 2 requests', function () { const requests = spec.buildRequests([ simpleBidRequest, @@ -310,13 +345,61 @@ describe('Improve Digital Adapter Tests', function () { { data: { type: 3, - value: 'Should get ignored' + value: '4' // rating + } + }, + { + data: { + type: 4, + value: '10105' // likes + } + }, + { + data: { + type: 5, + value: '150000' // downloads + } + }, + { + data: { + type: 6, + value: '3.99' // price + } + }, + { + data: { + type: 7, + value: '4.49' // salePrice + } + }, + { + data: { + type: 8, + value: '(123) 456-7890' // phone + } + }, + { + data: { + type: 9, + value: '123 Main Street, Anywhere USA' // address + } + }, + { + data: { + type: 10, + value: 'body2' + } + }, + { + data: { + type: 11, + value: 'https://myurl.com' // displayUrl } }, { data: { type: 12, - value: 'Do it' + value: 'Do it' // cta } }, { @@ -334,6 +417,7 @@ describe('Improve Digital Adapter Tests', function () { h: 30, w: 40 } + }, { img: { @@ -354,7 +438,8 @@ describe('Improve Digital Adapter Tests', function () { 'http://imptrack1.com', 'http://imptrack2.com' ], - jstracker: '' + jstracker: '', + privacy: 'https://www.myprivacyurl.com' } } ], @@ -362,6 +447,19 @@ describe('Improve Digital Adapter Tests', function () { } }; + const nativeEventtrackers = [ + { + event: 1, + method: 1, + url: 'http://www.mytracker.com/imptracker' + }, + { + event: 1, + method: 2, + url: 'http://www.mytracker.com/tracker.js' + } + ]; + describe('interpretResponse', function () { let expectedBid = [ { @@ -411,8 +509,17 @@ describe('Improve Digital Adapter Tests', function () { native: { title: 'Native title', body: 'Native body', + body2: 'body2', cta: 'Do it', sponsoredBy: 'Improve Digital', + rating: '4', + likes: '10105', + downloads: '150000', + price: '3.99', + salePrice: '4.49', + phone: '(123) 456-7890', + address: '123 Main Street, Anywhere USA', + displayUrl: 'https://myurl.com', icon: { url: 'http://blah.com/icon.jpg', height: 30, @@ -430,7 +537,8 @@ describe('Improve Digital Adapter Tests', function () { 'http://imptrack1.com', 'http://imptrack2.com' ], - javascriptTrackers: '' + javascriptTrackers: '', + privacyLink: 'https://www.myprivacyurl.com' } } ]; @@ -532,8 +640,23 @@ describe('Improve Digital Adapter Tests', function () { // Native ads it('should return a well-formed native ad bid', function () { - const bids = spec.interpretResponse(serverResponseNative); + let bids = spec.interpretResponse(serverResponseNative); + expect(bids[0].ortbNative).to.deep.equal(serverResponseNative.body.bid[0].native); + delete bids[0].ortbNative; expect(bids).to.deep.equal(expectedBidNative); + + // eventtrackers + const response = JSON.parse(JSON.stringify(serverResponseNative)); + const expectedBids = JSON.parse(JSON.stringify(expectedBidNative)); + response.body.bid[0].native.eventtrackers = nativeEventtrackers; + expectedBids[0].native.impressionTrackers = [ + 'http://ice.360yield.com/imp_pixel?ic=wVm', + 'http://www.mytracker.com/imptracker' + ]; + expectedBids[0].native.javascriptTrackers = ''; + bids = spec.interpretResponse(response); + delete bids[0].ortbNative; + expect(bids).to.deep.equal(expectedBids); }); }); From 80cbd2c4070c877b05b17164c0e011219ebc8b01 Mon Sep 17 00:00:00 2001 From: koji-eguchi <50477903+DAC-KOJI-EGUCHI@users.noreply.github.com> Date: Wed, 4 Sep 2019 01:17:24 +0900 Subject: [PATCH 1461/1594] YIELDONE adapter - change urls to adapt https (#4139) * update: change urls to adapt https * fix test code --- modules/yieldoneBidAdapter.js | 6 +++--- test/spec/modules/yieldoneBidAdapter_spec.js | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index 1caf44e790f..c706a6e7d45 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -5,9 +5,9 @@ import { Renderer } from '../src/Renderer'; import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'yieldone'; -const ENDPOINT_URL = '//y.one.impact-ad.jp/h_bid'; -const USER_SYNC_URL = '//y.one.impact-ad.jp/push_sync'; -const VIDEO_PLAYER_URL = '//img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/dac-video-prebid.min.js'; +const ENDPOINT_URL = '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'; export const spec = { code: BIDDER_CODE, diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js index d06029c7f26..abc579514ef 100644 --- a/test/spec/modules/yieldoneBidAdapter_spec.js +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -2,9 +2,9 @@ import { expect } from 'chai'; import { spec } from 'modules/yieldoneBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -const ENDPOINT = '//y.one.impact-ad.jp/h_bid'; -const USER_SYNC_URL = '//y.one.impact-ad.jp/push_sync'; -const VIDEO_PLAYER_URL = '//img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/dac-video-prebid.min.js'; +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'; describe('yieldoneBidAdapter', function() { const adapter = newBidder(spec); @@ -100,7 +100,7 @@ describe('yieldoneBidAdapter', function() { let bidRequestBanner = [ { 'method': 'GET', - 'url': '//y.one.impact-ad.jp/h_bid', + 'url': 'https://y.one.impact-ad.jp/h_bid', 'data': { 'v': 'hb1', 'p': '36891', @@ -164,7 +164,7 @@ describe('yieldoneBidAdapter', function() { let bidRequestVideo = [ { 'method': 'GET', - 'url': '//y.one.impact-ad.jp/h_bid', + 'url': 'https://y.one.impact-ad.jp/h_bid', 'data': { 'v': 'hb1', 'p': '41993', From e61b246b45bd2c2390350eaeca693f208b1a3a24 Mon Sep 17 00:00:00 2001 From: Telaria Engineering <36203956+telariaEng@users.noreply.github.com> Date: Tue, 3 Sep 2019 09:49:14 -0700 Subject: [PATCH 1462/1594] Added SupplyChain Object support and an onTimeout Callback (#4137) * - Implemented the 'onTimeout' callback to fire a pixel when there's a timeout. - Added the ability to serialize an schain object according to the description provided here: https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md * some mods to the schain tag generation * - added tests for schain param checking. * - fixed a malformed url for timeouts * - Removed a trailing ',' while generating a schain param. --- modules/telariaBidAdapter.js | 126 ++++++++++++++++---- test/spec/modules/telariaBidAdapter_spec.js | 69 ++++++++++- 2 files changed, 167 insertions(+), 28 deletions(-) diff --git a/modules/telariaBidAdapter.js b/modules/telariaBidAdapter.js index 0dd2e5e6edb..050539d2ec9 100644 --- a/modules/telariaBidAdapter.js +++ b/modules/telariaBidAdapter.js @@ -5,7 +5,9 @@ import {VIDEO} from '../src/mediaTypes'; import {STATUS} from '../src/constants'; const BIDDER_CODE = 'telaria'; -const ENDPOINT = '.ads.tremorhub.com/ad/tag'; +const DOMAIN = 'tremorhub.com'; +const TAG_ENDPOINT = `ads.${DOMAIN}/ad/tag`; +const EVENTS_ENDPOINT = `events.${DOMAIN}/diag`; export const spec = { code: BIDDER_CODE, @@ -82,7 +84,7 @@ export const spec = { errorMessage += `: ${bidResult.error}`; } utils.logError(errorMessage); - } else if (bidResult.seatbid && bidResult.seatbid.length > 0) { + } else if (!utils.isEmpty(bidResult.seatbid)) { bidResult.seatbid[0].bid.forEach(tag => { bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, BIDDER_CODE)); }); @@ -100,11 +102,89 @@ export const spec = { getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; if (syncOptions.pixelEnabled && serverResponses.length) { - try { - serverResponses[0].body.ext.telaria.userSync.forEach(url => syncs.push({type: 'image', url: url})); - } catch (e) {} + (utils.deepAccess(serverResponses, '0.body.ext.telaria.userSync') || []).forEach(url => syncs.push({type: 'image', url: url})); } return syncs; + }, + + /** + * See http://prebid.org/dev-docs/bidder-adaptor.html#registering-on-timeout for detailed semantic. + * @param timeoutData bidRequest + */ + onTimeout: function (timeoutData) { + let url = getTimeoutUrl(timeoutData); + if (url) { + utils.triggerPixel(url); + } + } +}; + +function getScheme() { + return ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; +} + +function getSrcPageUrl(params) { + return (params && params['srcPageUrl']) || encodeURIComponent(document.location.href); +} + +function getEncodedValIfNotEmpty(val) { + return !utils.isEmpty(val) ? encodeURIComponent(val) : ''; +} + +/** + * Converts the schain object to a url param value. Please refer to + * https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md + * (schain for non ORTB section) for more information + * @param schainObject + * @returns {string} + */ +function getSupplyChainAsUrlParam(schainObject) { + if (utils.isEmpty(schainObject)) { + return ''; + } + + let scStr = `&schain=${schainObject.ver},${schainObject.complete}`; + + schainObject.nodes.forEach((node) => { + scStr += '!'; + scStr += `${getEncodedValIfNotEmpty(node.asi)},`; + scStr += `${getEncodedValIfNotEmpty(node.sid)},`; + scStr += `${getEncodedValIfNotEmpty(node.hp)},`; + scStr += `${getEncodedValIfNotEmpty(node.rid)},`; + scStr += `${getEncodedValIfNotEmpty(node.name)},`; + scStr += `${getEncodedValIfNotEmpty(node.domain)}`; + }); + + return scStr; +} + +function getUrlParams(params) { + let urlSuffix = ''; + + if (!utils.isEmpty(params)) { + for (let key in params) { + if (key !== 'schain' && params.hasOwnProperty(key) && !utils.isEmpty(params[key])) { + urlSuffix += `&${key}=${params[key]}`; + } + } + urlSuffix += getSupplyChainAsUrlParam(params['schain']); + } + + return urlSuffix; +} + +export const getTimeoutUrl = function(timeoutData) { + let params = utils.deepAccess(timeoutData, '0.params.0'); + + if (!utils.isEmpty(params)) { + let url = `${getScheme()}${EVENTS_ENDPOINT}`; + + url += `?srcPageUrl=${getSrcPageUrl(params)}`; + url += `${getUrlParams(params)}`; + + url += '&hb=1&evt=TO'; + + return url; } }; @@ -116,9 +196,9 @@ export const spec = { * @returns {string} */ function generateUrl(bid, bidderRequest) { - let playerSize = (bid.mediaTypes && bid.mediaTypes.video && bid.mediaTypes.video.playerSize); + let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); if (!playerSize) { - utils.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; @@ -132,45 +212,41 @@ function generateUrl(bid, bidderRequest) { } } - if (bid.params.supplyCode && bid.params.adCode) { - let scheme = ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; - let url = scheme + bid.params.supplyCode + ENDPOINT + '?adCode=' + bid.params.adCode; + let supplyCode = utils.deepAccess(bid, 'params.supplyCode'); + let adCode = utils.deepAccess(bid, 'params.adCode'); + + if (supplyCode && adCode) { + let url = `${getScheme()}${supplyCode}.${TAG_ENDPOINT}?adCode=${adCode}`; if (width) { - url += ('&playerWidth=' + width); + url += (`&playerWidth=${width}`); } if (height) { - url += ('&playerHeight=' + height); + url += (`&playerHeight=${height}`); } - for (let key in bid.params) { - if (bid.params.hasOwnProperty(key) && bid.params[key]) { - url += ('&' + key + '=' + bid.params[key]); - } - } + url += `${getUrlParams(bid.params)}`; - if (!bid.params['srcPageUrl']) { - url += ('&srcPageUrl=' + encodeURIComponent(document.location.href)); - } + url += `&srcPageUrl=${getSrcPageUrl(bid.params)}`; - url += ('&transactionId=' + bid.transactionId + '&hb=1'); + url += (`&transactionId=${bid.transactionId}`); if (bidderRequest) { if (bidderRequest.gdprConsent) { if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { - url += ('&gdpr=' + (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + url += (`&gdpr=${(bidderRequest.gdprConsent.gdprApplies ? 1 : 0)}`); } if (bidderRequest.gdprConsent.consentString) { - url += ('&gdpr_consent=' + bidderRequest.gdprConsent.consentString); + url += (`&gdpr_consent=${bidderRequest.gdprConsent.consentString}`); } } if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - url += ('&referrer=' + encodeURIComponent(bidderRequest.refererInfo.referer)); + url += (`&referrer=${encodeURIComponent(bidderRequest.refererInfo.referer)}`); } } - return (url + '&fmt=json'); + return (url + '&hb=1&fmt=json'); } } diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js index fdb63675224..8d7666d020f 100644 --- a/test/spec/modules/telariaBidAdapter_spec.js +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -1,6 +1,6 @@ -import {expect} from 'chai'; +import {expect, should} from 'chai'; import {newBidder} from 'src/adapters/bidderFactory'; -import {spec} from 'modules/telariaBidAdapter'; +import {spec, getTimeoutUrl} from 'modules/telariaBidAdapter'; const ENDPOINT = '.ads.tremorhub.com/ad/tag'; const AD_CODE = 'ssp-!demo!-lufip'; @@ -16,7 +16,7 @@ const REQUEST = { }, 'mediaType': 'video', 'bids': [{ - 'bidder': 'tremor', + 'bidder': 'telaria', 'params': { 'videoId': 'MyCoolVideo', 'inclSync': true @@ -24,6 +24,36 @@ const REQUEST = { }] }; +const REQUEST_WITH_SCHAIN = [{ + 'bidder': 'telaria', + 'params': { + 'videoId': 'MyCoolVideo', + 'inclSync': true, + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + }, + { + 'asi': 'exchange2.com', + 'sid': 'abcd', + 'hp': 1, + 'rid': 'bid-request-2', + 'name': 'intermediary', + 'domain': 'intermediary.com' + } + ] + } + } +}]; + const BIDDER_REQUEST = { 'refererInfo': { 'referer': 'www.test.com' @@ -102,6 +132,8 @@ describe('TelariaAdapter', () => { } }]; + const schainStub = REQUEST_WITH_SCHAIN; + it('exists and is a function', () => { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); @@ -147,6 +179,14 @@ describe('TelariaAdapter', () => { expect(tempRequest.length).to.equal(0); }); + + it('converts the schain object into a tag param', () => { + let tempBid = schainStub; + tempBid[0].params.adCode = 'ssp-!demo!-lufip'; + tempBid[0].params.supplyCode = 'ssp-demo-rm6rh'; + let builtRequests = spec.buildRequests(tempBid, BIDDER_REQUEST); + expect(builtRequests.length).to.equal(1); + }); }); describe('interpretResponse', () => { @@ -215,4 +255,27 @@ describe('TelariaAdapter', () => { expect(urls.length).to.equal(2); }); }); + + describe('onTimeout', () => { + const timeoutData = [{ + adUnitCode: 'video1', + auctionId: 'd8d239f4-303a-4798-8c8c-dd3151ced4e7', + bidId: '2c749c0101ea92', + bidder: 'telaria', + params: [{ + adCode: 'ssp-!demo!-lufip', + supplyCode: 'ssp-demo-rm6rh', + mediaId: 'MyCoolVideo' + }] + }]; + + it('should return a pixel url', () => { + let url = getTimeoutUrl(timeoutData); + assert(url); + }); + + it('should fire a pixel', () => { + expect(spec.onTimeout(timeoutData)).to.be.undefined; + }); + }); }); From fe0c9e818b25eafda6d8f6a2e1a786c940d2f534 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 3 Sep 2019 16:47:24 -0400 Subject: [PATCH 1463/1594] Revert "Added SupplyChain Object support and an onTimeout Callback (#4137)" This reverts commit e61b246b45bd2c2390350eaeca693f208b1a3a24. This commit doesn't use the schain module added in #4084 --- modules/telariaBidAdapter.js | 126 ++++---------------- test/spec/modules/telariaBidAdapter_spec.js | 69 +---------- 2 files changed, 28 insertions(+), 167 deletions(-) diff --git a/modules/telariaBidAdapter.js b/modules/telariaBidAdapter.js index 050539d2ec9..0dd2e5e6edb 100644 --- a/modules/telariaBidAdapter.js +++ b/modules/telariaBidAdapter.js @@ -5,9 +5,7 @@ import {VIDEO} from '../src/mediaTypes'; import {STATUS} from '../src/constants'; const BIDDER_CODE = 'telaria'; -const DOMAIN = 'tremorhub.com'; -const TAG_ENDPOINT = `ads.${DOMAIN}/ad/tag`; -const EVENTS_ENDPOINT = `events.${DOMAIN}/diag`; +const ENDPOINT = '.ads.tremorhub.com/ad/tag'; export const spec = { code: BIDDER_CODE, @@ -84,7 +82,7 @@ export const spec = { errorMessage += `: ${bidResult.error}`; } utils.logError(errorMessage); - } else if (!utils.isEmpty(bidResult.seatbid)) { + } else if (bidResult.seatbid && bidResult.seatbid.length > 0) { bidResult.seatbid[0].bid.forEach(tag => { bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, BIDDER_CODE)); }); @@ -102,89 +100,11 @@ export const spec = { getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; if (syncOptions.pixelEnabled && serverResponses.length) { - (utils.deepAccess(serverResponses, '0.body.ext.telaria.userSync') || []).forEach(url => syncs.push({type: 'image', url: url})); + try { + serverResponses[0].body.ext.telaria.userSync.forEach(url => syncs.push({type: 'image', url: url})); + } catch (e) {} } return syncs; - }, - - /** - * See http://prebid.org/dev-docs/bidder-adaptor.html#registering-on-timeout for detailed semantic. - * @param timeoutData bidRequest - */ - onTimeout: function (timeoutData) { - let url = getTimeoutUrl(timeoutData); - if (url) { - utils.triggerPixel(url); - } - } -}; - -function getScheme() { - return ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; -} - -function getSrcPageUrl(params) { - return (params && params['srcPageUrl']) || encodeURIComponent(document.location.href); -} - -function getEncodedValIfNotEmpty(val) { - return !utils.isEmpty(val) ? encodeURIComponent(val) : ''; -} - -/** - * Converts the schain object to a url param value. Please refer to - * https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md - * (schain for non ORTB section) for more information - * @param schainObject - * @returns {string} - */ -function getSupplyChainAsUrlParam(schainObject) { - if (utils.isEmpty(schainObject)) { - return ''; - } - - let scStr = `&schain=${schainObject.ver},${schainObject.complete}`; - - schainObject.nodes.forEach((node) => { - scStr += '!'; - scStr += `${getEncodedValIfNotEmpty(node.asi)},`; - scStr += `${getEncodedValIfNotEmpty(node.sid)},`; - scStr += `${getEncodedValIfNotEmpty(node.hp)},`; - scStr += `${getEncodedValIfNotEmpty(node.rid)},`; - scStr += `${getEncodedValIfNotEmpty(node.name)},`; - scStr += `${getEncodedValIfNotEmpty(node.domain)}`; - }); - - return scStr; -} - -function getUrlParams(params) { - let urlSuffix = ''; - - if (!utils.isEmpty(params)) { - for (let key in params) { - if (key !== 'schain' && params.hasOwnProperty(key) && !utils.isEmpty(params[key])) { - urlSuffix += `&${key}=${params[key]}`; - } - } - urlSuffix += getSupplyChainAsUrlParam(params['schain']); - } - - return urlSuffix; -} - -export const getTimeoutUrl = function(timeoutData) { - let params = utils.deepAccess(timeoutData, '0.params.0'); - - if (!utils.isEmpty(params)) { - let url = `${getScheme()}${EVENTS_ENDPOINT}`; - - url += `?srcPageUrl=${getSrcPageUrl(params)}`; - url += `${getUrlParams(params)}`; - - url += '&hb=1&evt=TO'; - - return url; } }; @@ -196,9 +116,9 @@ export const getTimeoutUrl = function(timeoutData) { * @returns {string} */ function generateUrl(bid, bidderRequest) { - let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); + let playerSize = (bid.mediaTypes && bid.mediaTypes.video && bid.mediaTypes.video.playerSize); if (!playerSize) { - utils.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; @@ -212,41 +132,45 @@ function generateUrl(bid, bidderRequest) { } } - let supplyCode = utils.deepAccess(bid, 'params.supplyCode'); - let adCode = utils.deepAccess(bid, 'params.adCode'); - - if (supplyCode && adCode) { - let url = `${getScheme()}${supplyCode}.${TAG_ENDPOINT}?adCode=${adCode}`; + if (bid.params.supplyCode && bid.params.adCode) { + let scheme = ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; + let url = scheme + bid.params.supplyCode + ENDPOINT + '?adCode=' + bid.params.adCode; if (width) { - url += (`&playerWidth=${width}`); + url += ('&playerWidth=' + width); } if (height) { - url += (`&playerHeight=${height}`); + url += ('&playerHeight=' + height); } - url += `${getUrlParams(bid.params)}`; + for (let key in bid.params) { + if (bid.params.hasOwnProperty(key) && bid.params[key]) { + url += ('&' + key + '=' + bid.params[key]); + } + } - url += `&srcPageUrl=${getSrcPageUrl(bid.params)}`; + if (!bid.params['srcPageUrl']) { + url += ('&srcPageUrl=' + encodeURIComponent(document.location.href)); + } - url += (`&transactionId=${bid.transactionId}`); + url += ('&transactionId=' + bid.transactionId + '&hb=1'); if (bidderRequest) { if (bidderRequest.gdprConsent) { if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { - url += (`&gdpr=${(bidderRequest.gdprConsent.gdprApplies ? 1 : 0)}`); + url += ('&gdpr=' + (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); } if (bidderRequest.gdprConsent.consentString) { - url += (`&gdpr_consent=${bidderRequest.gdprConsent.consentString}`); + url += ('&gdpr_consent=' + bidderRequest.gdprConsent.consentString); } } if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - url += (`&referrer=${encodeURIComponent(bidderRequest.refererInfo.referer)}`); + url += ('&referrer=' + encodeURIComponent(bidderRequest.refererInfo.referer)); } } - return (url + '&hb=1&fmt=json'); + return (url + '&fmt=json'); } } diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js index 8d7666d020f..fdb63675224 100644 --- a/test/spec/modules/telariaBidAdapter_spec.js +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -1,6 +1,6 @@ -import {expect, should} from 'chai'; +import {expect} from 'chai'; import {newBidder} from 'src/adapters/bidderFactory'; -import {spec, getTimeoutUrl} from 'modules/telariaBidAdapter'; +import {spec} from 'modules/telariaBidAdapter'; const ENDPOINT = '.ads.tremorhub.com/ad/tag'; const AD_CODE = 'ssp-!demo!-lufip'; @@ -16,7 +16,7 @@ const REQUEST = { }, 'mediaType': 'video', 'bids': [{ - 'bidder': 'telaria', + 'bidder': 'tremor', 'params': { 'videoId': 'MyCoolVideo', 'inclSync': true @@ -24,36 +24,6 @@ const REQUEST = { }] }; -const REQUEST_WITH_SCHAIN = [{ - 'bidder': 'telaria', - 'params': { - 'videoId': 'MyCoolVideo', - 'inclSync': true, - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'exchange1.com', - 'sid': '1234', - 'hp': 1, - 'rid': 'bid-request-1', - 'name': 'publisher', - 'domain': 'publisher.com' - }, - { - 'asi': 'exchange2.com', - 'sid': 'abcd', - 'hp': 1, - 'rid': 'bid-request-2', - 'name': 'intermediary', - 'domain': 'intermediary.com' - } - ] - } - } -}]; - const BIDDER_REQUEST = { 'refererInfo': { 'referer': 'www.test.com' @@ -132,8 +102,6 @@ describe('TelariaAdapter', () => { } }]; - const schainStub = REQUEST_WITH_SCHAIN; - it('exists and is a function', () => { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); @@ -179,14 +147,6 @@ describe('TelariaAdapter', () => { expect(tempRequest.length).to.equal(0); }); - - it('converts the schain object into a tag param', () => { - let tempBid = schainStub; - tempBid[0].params.adCode = 'ssp-!demo!-lufip'; - tempBid[0].params.supplyCode = 'ssp-demo-rm6rh'; - let builtRequests = spec.buildRequests(tempBid, BIDDER_REQUEST); - expect(builtRequests.length).to.equal(1); - }); }); describe('interpretResponse', () => { @@ -255,27 +215,4 @@ describe('TelariaAdapter', () => { expect(urls.length).to.equal(2); }); }); - - describe('onTimeout', () => { - const timeoutData = [{ - adUnitCode: 'video1', - auctionId: 'd8d239f4-303a-4798-8c8c-dd3151ced4e7', - bidId: '2c749c0101ea92', - bidder: 'telaria', - params: [{ - adCode: 'ssp-!demo!-lufip', - supplyCode: 'ssp-demo-rm6rh', - mediaId: 'MyCoolVideo' - }] - }]; - - it('should return a pixel url', () => { - let url = getTimeoutUrl(timeoutData); - assert(url); - }); - - it('should fire a pixel', () => { - expect(spec.onTimeout(timeoutData)).to.be.undefined; - }); - }); }); From deeb4c0016dd716cd2bfa863996d63448408df6e Mon Sep 17 00:00:00 2001 From: robdubois <53589945+robdubois@users.noreply.github.com> Date: Tue, 3 Sep 2019 17:25:21 -0700 Subject: [PATCH 1464/1594] Nobid Prebid Adapter commit (#4050) * Nobid Prebid Adapter commit * Fixed global replace and unit tests * Fixed find function * Added nobidBidAdapter.md * Removed description and added "Bid Params" section. * Added test siteId 2 for testing. * Refactored the Adapter to remove most references to the nobid object. We still need the nobid object because we have a passback tag in DFP that makes reference to it. * Fix concurrent responses on the page * Cosmetic change to log an error in case of missing ad markup * Keep nobid.bidResponses cross adapters. * Added GDPR support in user sync and added test coverage. gulp test-coverage gulp view-coverage * Padding issues * Fix padding issues * Fix padding --- modules/nobidBidAdapter.js | 305 ++++++++++++++++++++++ modules/nobidBidAdapter.md | 53 ++++ test/spec/modules/nobidBidAdapter_spec.js | 256 ++++++++++++++++++ 3 files changed, 614 insertions(+) create mode 100644 modules/nobidBidAdapter.js create mode 100644 modules/nobidBidAdapter.md create mode 100644 test/spec/modules/nobidBidAdapter_spec.js diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js new file mode 100644 index 00000000000..ce4c25d75fa --- /dev/null +++ b/modules/nobidBidAdapter.js @@ -0,0 +1,305 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; +const BIDDER_CODE = 'nobid'; +window.nobidVersion = '1.1.0'; +function log(msg, obj) { + utils.logInfo('-NoBid- ' + msg, obj) +} +function nobidBuildRequests(bids, bidderRequest) { + var serializeState = function(divIds, siteId, adunits) { + var filterAdUnitsByIds = function(divIds, adUnits) { + var filtered = []; + if (!divIds || !divIds.length) { + filtered = adUnits; + } else if (adUnits) { + var a = []; + if (!(divIds instanceof Array)) a.push(divIds); + else a = divIds; + for (var i = 0, l = adUnits.length; i < l; i++) { + var adUnit = adUnits[i]; + if (adUnit && adUnit.d && (a.indexOf(adUnit.d) > -1)) { + filtered.push(adUnit); + } + } + } + return filtered; + } + var gdprConsent = function(bidderRequest) { + var gdprConsent = {}; + if (bidderRequest && bidderRequest.gdprConsent) { + gdprConsent = { + consentString: 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 + consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : false + } + } + return gdprConsent; + } + var topLocation = function(bidderRequest) { + var ret = ''; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + ret = bidderRequest.refererInfo.referer; + } else { + ret = (window.context && window.context.location && window.context.location.href) ? window.context.location.href : document.location.href; + } + return encodeURIComponent(ret.replace(/\%/g, '')); + } + var timestamp = function() { + var date = new Date(); + var zp = function (val) { return (val <= 9 ? '0' + val : '' + val); } + var d = date.getDate(); + var y = date.getFullYear(); + var m = date.getMonth() + 1; + var h = date.getHours(); + var min = date.getMinutes(); + var s = date.getSeconds(); + return '' + y + '-' + zp(m) + '-' + zp(d) + ' ' + zp(h) + ':' + zp(min) + ':' + zp(s); + }; + var clientDim = function() { + try { + return `${screen.width}x${screen.height}`; + } catch (e) { + console.error(e); + } + } + var state = {}; + state['sid'] = siteId; + state['l'] = topLocation(bidderRequest); + state['tt'] = encodeURIComponent(document.title); + state['tt'] = state['tt'].replace(/'|;|quot;|39;|&|&|#|\r\n|\r|\n|\t|\f|\%0A|\"|\%22|\%5C|\%23|\%26|\%26|\%09/gm, ''); + state['a'] = filterAdUnitsByIds(divIds, adunits || []); + state['t'] = timestamp(); + state['tz'] = Math.round(new Date().getTimezoneOffset()); + state['r'] = clientDim(); + state['lang'] = (navigator.languages && navigator.languages[0]) || navigator.language || navigator.userLanguage; + state['ref'] = document.referrer; + state['gdpr'] = gdprConsent(bidderRequest); + return state; + } + function newAdunit(adunitObject, adunits) { + var getAdUnit = function(divid, adunits) { + for (var i = 0; i < adunits.length; i++) { + if (adunits[i].d === divid) { + return adunits[i]; + } + } + return false; + } + var removeByAttrValue = function(array, attribute, value) { + for (var i = array.length - 1; i >= 0; i--) { + var entry = array[i]; + if (entry[attribute] && entry[attribute] === value) { + array.splice(i, 1); + } + } + } + var a = getAdUnit(adunitObject.div, adunits) || {}; + if (adunitObject.account) { + a.s = adunitObject.account; + } + if (adunitObject.sizes) { + a.z = adunitObject.sizes; + } + if (adunitObject.div) { + a.d = adunitObject.div; + } + if (adunitObject.targeting) { + a.g = adunitObject.targeting; + } else { + a.g = {}; + } + if (adunitObject.companion) { + a.c = adunitObject.companion; + } + if (adunitObject.div) { + removeByAttrValue(adunits, 'd', adunitObject.div); + } + if (adunitObject.sizeMapping) { + a.sm = adunitObject.sizeMapping; + } + if (adunitObject.siteId) { + a.sid = adunitObject.siteId; + } + /* {"BIDDER_ID":{"WxH":"TAG_ID", "WxH":"TAG_ID"}} */ + if (adunitObject.rtb) { + a.rtb = adunitObject.rtb; + } + adunits.push(a); + return adunits; + } + /* DISCOVER SLOTS */ + var divids = []; + var siteId = 0; + var adunits = []; + for (var i = 0; i < bids.length; i++) { + var bid = bids[i]; + var divid = bid.adUnitCode; + divids.push(divid); + var sizes = bid.sizes; + siteId = (typeof bid.params['siteId'] != 'undefined' && bid.params['siteId']) ? bid.params['siteId'] : siteId; + if (siteId && bid.params && bid.params.tags) { + newAdunit({div: divid, sizes: sizes, rtb: bid.params.tags, siteId: siteId}, adunits); + } else if (siteId) { + newAdunit({div: divid, sizes: sizes, siteId: siteId}, adunits); + } + } + if (siteId) { + return serializeState(divids, siteId, adunits); + } else { + return false; + } +} +function nobidInterpretResponse(response, bidRequest) { + var findBid = function(divid, bids) { + for (var i = 0; i < bids.length; i++) { + if (bids[i].adUnitCode === divid) { + return bids[i]; + } + } + return false; + } + var bidResponses = []; + for (var i = 0; response.bids && i < response.bids.length; i++) { + var bid = response.bids[i]; + if (bid.bdrid < 100 || !bidRequest || !bidRequest.bidderRequest || !bidRequest.bidderRequest.bids) continue; + nobid.bidResponses['' + bid.id] = bid; + var reqBid = findBid(bid.divid, bidRequest.bidderRequest.bids); + if (!reqBid) continue; + const bidResponse = { + requestId: reqBid.bidId, + cpm: 1 * ((bid.price) ? bid.price : (bid.bucket) ? bid.bucket : 0), + width: bid.size.w, + height: bid.size.h, + creativeId: (bid.creativeid) || '', + dealId: (bid.dealid) || '', + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: bid.adm, + mediaType: BANNER + }; + bidResponses.push(bidResponse); + } + return bidResponses; +}; +window.nobid = window.nobid || {}; +nobid.bidResponses = nobid.bidResponses || {}; +nobid.timeoutTotal = 0; +nobid.bidWonTotal = 0; +nobid.renderTag = function(doc, id, win) { + log('nobid.renderTag()', id); + var bid = nobid.bidResponses['' + id]; + if (bid && bid.adm2) { + log('nobid.renderTag() found tag', id); + var markup = bid.adm2; + doc.write(markup); + doc.close(); + return; + } + log('nobid.renderTag() tag NOT FOUND *ERROR*', id); +} +export const spec = { + code: BIDDER_CODE, + 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) { + log('isBidRequestValid', bid); + return !!bid.params.siteId; + }, + /** + * 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) { + function resolveEndpoint() { + var ret = 'https://ads.servenobid.com/'; + 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/'; + else if (env == 'qa') ret = 'https://qa-ads.nobid.com/'; + return ret; + } + var buildEndpoint = function() { + return resolveEndpoint() + 'adreq?cb=' + Math.floor(Math.random() * 11000); + } + log('buildRequests', validBidRequests); + if (!validBidRequests || validBidRequests.length <= 0) { + log('Empty validBidRequests'); + return; + } + const payload = nobidBuildRequests(validBidRequests, bidderRequest); + if (!payload) return; + const payloadString = JSON.stringify(payload).replace(/'|&|#/g, '') + const endpoint = buildEndpoint(); + return { + method: 'POST', + url: endpoint, + data: payloadString, + 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) { + log('interpretResponse', serverResponse); + log('interpretResponse', bidRequest); + return nobidInterpretResponse(serverResponse.body, bidRequest); + }, + + /** + * 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) { + if (syncOptions.iframeEnabled) { + 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}`; + } + } + return [{ + type: 'iframe', + url: 'https://s3.amazonaws.com/nobid-public/sync.html' + params + }]; + } else { + utils.logWarn('-NoBid- Please enable iframe based user sync.', syncOptions); + return []; + } + }, + + /** + * Register bidder specific code, which will execute if bidder timed out after an auction + * @param {data} Containing timeout specific data + */ + onTimeout: function(data) { + nobid.timeoutTotal++; + log('Timeout total: ' + nobid.timeoutTotal, data); + return nobid.timeoutTotal; + }, + onBidWon: function(data) { + nobid.bidWonTotal++; + log('BidWon total: ' + nobid.bidWonTotal, data); + return nobid.bidWonTotal; + } +} +registerBidder(spec); diff --git a/modules/nobidBidAdapter.md b/modules/nobidBidAdapter.md new file mode 100644 index 00000000000..b80a7f6c4b6 --- /dev/null +++ b/modules/nobidBidAdapter.md @@ -0,0 +1,53 @@ +--- +layout: bidder +title: Nobid +description: Prebid Nobid Bidder Adaptor +biddercode: nobid +hide: true +media_types: banner +gdpr_supported: true +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-------------|---------|----------| +| `siteId` | required | siteId is provided by your Nobid account manager | | `integer` | + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, + bids: [ + { + bidder: "nobid", + params: { + siteId: 2 + } + } + ] + },{ + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[320, 50]], // a mobile size + } + }, + bids: [ + { + bidder: "nobid", + params: { + siteId: 2 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js new file mode 100644 index 00000000000..5134958d218 --- /dev/null +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -0,0 +1,256 @@ +import { expect } from 'chai'; +import { spec } from 'modules/nobidBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +describe('Nobid Adapter', 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': 'nobid', + 'params': { + 'siteId': 2 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + '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 = { + 'siteId': 2 + }; + + 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 = { + 'siteId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const SITE_ID = 2; + const REFERER = 'https://www.examplereferer.com'; + let bidRequests = [ + { + 'bidder': 'nobid', + 'params': { + 'siteId': SITE_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + let bidderRequest = { + refererInfo: {referer: REFERER} + } + + it('should add source and verison to the tag', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.sid).to.equal(SITE_ID); + expect(payload.l).to.exist.and.to.equal(encodeURIComponent(REFERER)); + expect(payload.tt).to.exist; + expect(payload.a).to.exist; + expect(payload.t).to.exist; + expect(payload.tz).to.exist; + expect(payload.r).to.exist; + expect(payload.lang).to.exist; + expect(payload.ref).to.exist; + expect(payload.gdpr).to.exist; + }); + + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.contain('ads.servenobid.com/adreq'); + expect(request.method).to.equal('POST'); + }); + + it('should add gdpr consent information to the request', function () { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'nobid', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + bidderRequest.bids = bidRequests; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.gdpr).to.exist; + expect(payload.gdpr.consentString).to.exist.and.to.equal(consentString); + expect(payload.gdpr.consentRequired).to.exist.and.to.be.true; + }); + }); + + describe('interpretResponse', function () { + const CREATIVE_ID_300x250 = 'CREATIVE-100'; + const ADUNIT_300x250 = 'ADUNIT-1'; + const ADMARKUP_300x250 = 'ADMARKUP-300x250'; + const PRICE_300x250 = 0.51; + const REQUEST_ID = '3db3773286ee59'; + const DEAL_ID = 'deal123'; + let response = { + country: 'US', + ip: '68.83.15.75', + device: 'COMPUTER', + site: 2, + bids: [ + {id: 1, + bdrid: 101, + divid: ADUNIT_300x250, + dealid: DEAL_ID, + creativeid: CREATIVE_ID_300x250, + size: {'w': 300, 'h': 250}, + adm: ADMARKUP_300x250, + price: '' + PRICE_300x250 + } + ] + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + requestId: REQUEST_ID, + cpm: PRICE_300x250, + width: 300, + height: 250, + creativeId: CREATIVE_ID_300x250, + dealId: DEAL_ID, + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: ADMARKUP_300x250, + mediaType: 'banner' + } + ]; + + let bidderRequest = { + bids: [{ + bidId: REQUEST_ID, + adUnitCode: ADUNIT_300x250 + }] + } + let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); + expect(result.length).to.equal(expectedResponse.length); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + expect(result[0].requestId).to.equal(expectedResponse[0].requestId); + expect(result[0].cpm).to.equal(expectedResponse[0].cpm); + }); + + it('should get correct empty response', function () { + let bidderRequest = { + bids: [{ + bidId: REQUEST_ID, + adUnitCode: ADUNIT_300x250 + '1' + }] + } + let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); + expect(result.length).to.equal(0); + }); + + it('should get correct deal id', function () { + let expectedResponse = [ + { + requestId: REQUEST_ID, + cpm: PRICE_300x250, + width: 300, + height: 250, + creativeId: CREATIVE_ID_300x250, + dealId: DEAL_ID, + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: ADMARKUP_300x250, + mediaType: 'banner' + } + ]; + + let bidderRequest = { + bids: [{ + bidId: REQUEST_ID, + adUnitCode: ADUNIT_300x250 + }] + } + let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); + expect(result.length).to.equal(expectedResponse.length); + expect(result[0].dealId).to.equal(expectedResponse[0].dealId); + }); + }); + + describe('getUserSyncs', function () { + const GDPR_CONSENT_STRING = 'GDPR_CONSENT_STRING'; + it('should get correct user sync when iframeEnabled', function () { + let pixel = spec.getUserSyncs({iframeEnabled: true}) + expect(pixel[0].type).to.equal('iframe'); + expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html'); + }); + + it('should get correct user sync when iframeEnabled and pixelEnabled', function () { + let pixel = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}) + expect(pixel[0].type).to.equal('iframe'); + expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html'); + }); + + it('should get correct user sync when iframeEnabled', function () { + let pixel = spec.getUserSyncs({iframeEnabled: true}, {}, {gdprApplies: true, consentString: GDPR_CONSENT_STRING}) + expect(pixel[0].type).to.equal('iframe'); + expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html?gdpr=1&gdpr_consent=' + GDPR_CONSENT_STRING); + }); + + it('should get correct user sync when !iframeEnabled', function () { + let pixel = spec.getUserSyncs({iframeEnabled: false}) + expect(pixel.length).to.equal(0); + }); + + it('should get correct user sync when !iframeEnabled', function () { + let pixel = spec.getUserSyncs({}) + expect(pixel.length).to.equal(0); + }); + }); + + describe('onTimeout', function (syncOptions) { + it('should increment timeoutTotal', function () { + let timeoutTotal = spec.onTimeout() + expect(timeoutTotal).to.equal(1); + }); + }); + + describe('onBidWon', function (syncOptions) { + it('should increment bidWonTotal', function () { + let bidWonTotal = spec.onBidWon() + expect(bidWonTotal).to.equal(1); + }); + }); +}); From e897d470880ef78ff7750d5fac1335359dea6668 Mon Sep 17 00:00:00 2001 From: sumit116 Date: Wed, 4 Sep 2019 13:08:56 +0530 Subject: [PATCH 1465/1594] update outstream prod url (#4104) --- modules/gridBidAdapter.js | 2 +- modules/trustxBidAdapter.js | 2 +- test/spec/modules/prebidServerBidAdapter_spec.js | 2 +- test/spec/modules/trustxBidAdapter_spec.js | 4 ++-- test/spec/renderer_spec.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index 2deaebf0635..edbf5ed08bd 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -6,7 +6,7 @@ import { VIDEO, BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'grid'; const ENDPOINT_URL = '//grid.bidswitch.net/hb'; const TIME_TO_LIVE = 360; -const RENDERER_URL = '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js'; +const RENDERER_URL = '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index aecb6aba8af..a1ba632a487 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -7,7 +7,7 @@ const BIDDER_CODE = 'trustx'; const ENDPOINT_URL = '//sofia.trustx.org/hb'; const TIME_TO_LIVE = 360; const ADAPTER_SYNC_URL = '//sofia.trustx.org/push_sync'; -const RENDERER_URL = '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js'; +const RENDERER_URL = '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 3331a985afa..c823e5aa370 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -144,7 +144,7 @@ const OUTSTREAM_VIDEO_REQUEST = { } ], renderer: { - url: 'http://cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + url: 'http://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', render: function (bid) { ANOutstreamVideo.renderAd({ targetId: bid.adUnitCode, diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index f99831eeca1..d7d16348bcf 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -735,12 +735,12 @@ describe('TrustXAdapter', function () { expect(spyRendererInstall.calledTwice).to.equal(true); expect(spyRendererInstall.getCall(0).args[0]).to.deep.equal({ id: 'e6e65553fc8', - url: '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + url: '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', loaded: false }); expect(spyRendererInstall.getCall(1).args[0]).to.deep.equal({ id: 'c8fdcb3f269f', - url: '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + url: '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', loaded: false }); diff --git a/test/spec/renderer_spec.js b/test/spec/renderer_spec.js index 7a7354add31..f9a670c1315 100644 --- a/test/spec/renderer_spec.js +++ b/test/spec/renderer_spec.js @@ -114,7 +114,7 @@ describe('Renderer', function () { $$PREBID_GLOBAL$$.adUnits = [{ code: 'video1', renderer: { - url: 'http://cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + url: 'http://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', render: sinon.spy() } }] From 7e43220c4a3569ef772d8e8a634795b80852fd09 Mon Sep 17 00:00:00 2001 From: nwlosinski Date: Wed, 4 Sep 2019 19:24:00 +0200 Subject: [PATCH 1466/1594] support pubcid and uids (#4143) --- modules/justpremiumBidAdapter.js | 9 +++++++++ test/spec/modules/justpremiumBidAdapter_spec.js | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index f8419f06faf..68b73c333ca 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -1,4 +1,5 @@ import { registerBidder } from '../src/adapters/bidderFactory' +import { deepAccess } from '../src/utils'; const BIDDER_CODE = 'justpremium' const ENDPOINT_URL = '//pre.ads.justpremium.com/v/2.0/t/xhr' @@ -46,6 +47,14 @@ export const spec = { sizes[zone].push.apply(sizes[zone], b.sizes) }) + if (deepAccess(validBidRequests[0], 'userId.pubcid')) { + payload.pubcid = deepAccess(validBidRequests[0], 'userId.pubcid') + } else if (deepAccess(validBidRequests[0], 'crumbs.pubcid')) { + payload.pubcid = deepAccess(validBidRequests[0], 'crumbs.pubcid') + } + + payload.uids = validBidRequests[0].userId + if (bidderRequest && bidderRequest.gdprConsent) { payload.gdpr_consent = { consent_string: bidderRequest.gdprConsent.consentString, diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index feaf593fe25..c3cd015b6e3 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -18,6 +18,18 @@ describe('justpremium adapter', function () { { adUnitCode: 'div-gpt-ad-1471513102552-1', bidder: 'justpremium', + crumbs: { + pubcid: '0000000' + }, + userId: { + tdid: '1111111', + id5id: '2222222', + digitrustid: { + data: { + id: '3333333' + } + } + }, params: { zone: 28313, allow: ['lb', 'wp'] @@ -71,6 +83,10 @@ describe('justpremium adapter', function () { expect(jpxRequest.sizes).to.not.equal('undefined') expect(jpxRequest.version.prebid).to.equal('$prebid.version$') expect(jpxRequest.version.jp_adapter).to.equal('1.4') + expect(jpxRequest.pubcid).to.equal('0000000') + expect(jpxRequest.uids.tdid).to.equal('1111111') + expect(jpxRequest.uids.id5id).to.equal('2222222') + expect(jpxRequest.uids.digitrustid.data.id).to.equal('3333333') }) }) From f125ac775ee4218fe98f757538c74323318fd804 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Wed, 4 Sep 2019 13:27:48 -0400 Subject: [PATCH 1467/1594] Fix misspelling and minor cleanup of schain docs (#4150) --- modules/schain.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/modules/schain.md b/modules/schain.md index 0adf68c19e5..9fe0c3bd0f5 100644 --- a/modules/schain.md +++ b/modules/schain.md @@ -1,13 +1,14 @@ # schain module -Aggregators who manage Prebid wrappers on behalf of multiple publishers need to declare their intermediary status in the Supply Chain Object. -As the spec prohibits us from adding upstream intermediaries, Prebid requests in this case need to come with the schain information. -In this use case, it's seems cumbersome to have every bidder in the wrapper separately configured the same schain information. +Aggregators who manage Prebid wrappers on behalf of multiple publishers and handle payment on behalf of the publishers +need to declare their intermediary status in the Supply Chain Object. As the Supply Chain Object spec prohibits SSPs from adding +upstream intermediaries, Prebid requests in this case need to come with the schain information. In this use case, it's cumbersome +to have every bidder in the wrapper separately configured the same schain information. Refer: - https://iabtechlab.com/sellers-json/ -- https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md - +- https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md + ## Sample code for passing the schain object ``` pbjs.setConfig( { @@ -26,16 +27,16 @@ pbjs.setConfig( { { "asi":"indirectseller-2.com", "sid":"00002", - "hp":0 + "hp":1 }, ] - } + } } }); ``` ## Workflow -The schain module is not enabled by default as it may not be neccessary for all publishers. +The schain module is not enabled by default as it may not be necessary for all publishers. If required, schain module can be included as following ``` $ gulp build --modules=schain,pubmaticBidAdapter,openxBidAdapter,rubiconBidAdapter,sovrnBidAdapter @@ -47,4 +48,4 @@ You may refer pubmaticBidAdapter implementaion for the same. ## Validation modes - ```strict```: It is the default validation mode. In this mode, schain object will not be passed to adapters if it is invalid. Errors are thrown for invalid schain object. - ```relaxed```: In this mode, errors are thrown for an invalid schain object but the invalid schain object is still passed to adapters. -- ```off```: In this mode, no validations are performed and schain object is passed as is to adapters. \ No newline at end of file +- ```off```: In this mode, no validations are performed and schain object is passed as is to adapters. From 777d03157b848d64f71194437926abd98ff0de9a Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Wed, 4 Sep 2019 14:36:21 -0400 Subject: [PATCH 1468/1594] Prebid 2.31.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bbdbf5437e8..9dc9b22b690 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.31.0-pre", + "version": "2.31.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From c716dd96dd341c9efc19927a3bd25ddfdd1ef820 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Wed, 4 Sep 2019 14:54:37 -0400 Subject: [PATCH 1469/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9dc9b22b690..72fedc1bfcb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.31.0", + "version": "2.32.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From ff0a8a61ae65ca177d073a3b2c1bb3221af04417 Mon Sep 17 00:00:00 2001 From: bretg Date: Wed, 4 Sep 2019 20:21:32 -0400 Subject: [PATCH 1470/1594] Rubicon: tuning logged messages (#4157) * Rubicon: tuning logged messages * Update rubiconBidAdapter.js * fixed indentation --- modules/rubiconBidAdapter.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 5193efb6358..75e1af23c8a 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -116,7 +116,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]])) { - utils.logError('Rubicon bid adapter Error: wrong format of accountId or siteId or zoneId.') + utils.logError('Rubicon: wrong format of accountId or siteId or zoneId.') return false } } @@ -468,9 +468,7 @@ export const spec = { if (responseObj.seatbid) { const responseErrors = utils.deepAccess(responseObj, 'ext.errors.rubicon'); if (Array.isArray(responseErrors) && responseErrors.length > 0) { - responseErrors.forEach(error => { - utils.logError('Got error from PBS Java openRTB: ' + error); - }); + utils.logWarn('Rubicon: Error in video response'); } const bids = []; responseObj.seatbid.forEach(seatbid => { @@ -520,7 +518,7 @@ export const spec = { if (bid.nurl) { bidObject.vastUrl = bid.nurl; } if (!bidObject.vastUrl && bid.nurl) { bidObject.vastUrl = bid.nurl; } } else { - utils.logError('Prebid Server Java openRTB returns response with media type other than video for video request.'); + utils.logWarn('Rubicon: video response received non-video media type'); } bids.push(bidObject); @@ -591,7 +589,7 @@ export const spec = { bids.push(bid); } else { - utils.logError(`Rubicon bid adapter Error: bidRequest undefined at index position:${i}`, bidRequest, responseObj); + utils.logError(`Rubicon: bidRequest undefined at index position:${i}`, bidRequest, responseObj); } return bids; @@ -724,7 +722,7 @@ function parseSizes(bid, mediaType) { } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) { sizes = mapSizes(bid.sizes) } else { - utils.logWarn('Warning: no sizes are setup or found'); + utils.logWarn('Rubicon: no sizes are setup or found'); } return masSizeOrdering(sizes); @@ -821,7 +819,7 @@ function bidType(bid, log = false) { // We require either context as instream or outstream if (['outstream', 'instream'].indexOf(utils.deepAccess(bid, `mediaTypes.${VIDEO}.context`)) === -1) { if (log) { - utils.logError('Rubicon bid adapter requires mediaTypes.video.context to be one of outstream or instream'); + utils.logError('Rubicon: mediaTypes.video.context must be outstream or instream'); } return; } @@ -829,13 +827,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) { - utils.logError('Rubicon bid adapter could not determine the playerSize of the video\nplayerWidth and playerHeight are inferred from one of params.playerWidth/playerHeight or mediaTypes.video.playerSize or adUnit.sizes, in that order'); + utils.logError('Rubicon: could not determine the playerSize of the video'); } return; } if (log) { - utils.logMessage('Rubicon bid adapter making video request for adUnit', bid.adUnitCode); + utils.logMessage('Rubicon: making video request for adUnit', bid.adUnitCode); } return 'video'; } else { @@ -843,14 +841,14 @@ function bidType(bid, log = false) { // if we cannot determine them, we reject it! if (parseSizes(bid, 'banner').length === 0) { if (log) { - utils.logError('Rubicon bid adapter could not determine the sizes for a banner request\nThey are inferred from one of params.sizes or mediaTypes.banner.sizes or adUnit.sizes, in that order'); + utils.logError('Rubicon: could not determine the sizes for banner request'); } return; } // everything looks good for banner so lets do it if (log) { - utils.logMessage('Rubicon bid adapter making banner request for adUnit', bid.adUnitCode); + utils.logMessage('Rubicon: making banner request for adUnit', bid.adUnitCode); } return 'banner'; } @@ -933,7 +931,7 @@ export function hasValidVideoParams(bid) { Object.keys(requiredParams).forEach(function(param) { if (Object.prototype.toString.call(utils.deepAccess(bid, 'mediaTypes.video.' + param)) !== requiredParams[param]) { isValid = false; - utils.logError('Rubicon Bid Adapter: 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; From c47bb80dd349a35b150609e4b4210cc2100c457e Mon Sep 17 00:00:00 2001 From: Artem Seryak Date: Thu, 5 Sep 2019 20:45:10 +0300 Subject: [PATCH 1471/1594] Rubicon Video COPPA fix (#4155) * Rubicon Video COPPA fix * Unit test for Rubicon Video COPPA fix --- modules/rubiconBidAdapter.js | 2 +- test/spec/modules/rubiconBidAdapter_spec.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 75e1af23c8a..f309e4b7cac 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -237,7 +237,7 @@ export const spec = { } if (config.getConfig('coppa') === true) { - utils.deepSetValue(request, 'regs.coppa', 1); + utils.deepSetValue(data, 'regs.coppa', 1); } return { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 988b518f348..f7432435060 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1356,6 +1356,24 @@ describe('the rubicon adapter', function () { expect(requests.length).to.equal(1); expect(requests[0].url).to.equal(FASTLANE_ENDPOINT); }); + + it('should include coppa flag in video bid request', () => { + createVideoBidderRequest(); + + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + + sandbox.stub(config, 'getConfig').callsFake(key => { + const config = { + 'coppa': true + }; + return config[key]; + }); + + const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(request.data.regs.coppa).to.equal(1); + }); }); describe('combineSlotUrlParams', function () { From 67e3a9ca235baa2d6e0243da3682ed0be6c5e8bd Mon Sep 17 00:00:00 2001 From: Jonathan Mullins Date: Fri, 6 Sep 2019 03:57:06 +1000 Subject: [PATCH 1472/1594] Playground XYZ adapter - iframe usersync bug fix (#4141) * corrected user sync type * removed support for iframe usersync * added unit tests for getUserSyncs --- modules/playgroundxyzBidAdapter.js | 16 +++-------- .../modules/playgroundxyzBidAdapter_spec.js | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/modules/playgroundxyzBidAdapter.js b/modules/playgroundxyzBidAdapter.js index 91f6b701b72..26483f1277a 100644 --- a/modules/playgroundxyzBidAdapter.js +++ b/modules/playgroundxyzBidAdapter.js @@ -102,18 +102,10 @@ export const spec = { }, getUserSyncs: function (syncOptions) { - if (syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' - }]; - } - if (syncOptions.pixelEnabled) { - return [{ - type: 'image', - url: '//ib.adnxs.com/getuidnb?https://ads.playground.xyz/usersync?partner=appnexus&uid=$UID' - }]; - } + return [{ + type: 'image', + url: '//ib.adnxs.com/getuidnb?https://ads.playground.xyz/usersync?partner=appnexus&uid=$UID' + }]; } } diff --git a/test/spec/modules/playgroundxyzBidAdapter_spec.js b/test/spec/modules/playgroundxyzBidAdapter_spec.js index fc430bfb31b..a90564003f4 100644 --- a/test/spec/modules/playgroundxyzBidAdapter_spec.js +++ b/test/spec/modules/playgroundxyzBidAdapter_spec.js @@ -182,4 +182,32 @@ describe('playgroundxyzBidAdapter', function () { expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); }); }); + + describe('getUserSyncs', function () { + const syncUrl = '//ib.adnxs.com/getuidnb?https://ads.playground.xyz/usersync?partner=appnexus&uid=$UID'; + + describe('when iframeEnabled is true', function () { + const syncOptions = { + 'iframeEnabled': true + } + it('should return one image type user sync pixel', function () { + let result = spec.getUserSyncs(syncOptions); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image') + expect(result[0].url).to.equal(syncUrl); + }); + }); + + describe('when iframeEnabled is false', function () { + const syncOptions = { + 'iframeEnabled': false + } + it('should return one image type user sync pixel', function () { + let result = spec.getUserSyncs(syncOptions); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image') + expect(result[0].url).to.equal(syncUrl); + }); + }); + }) }); From 0cbe57cdb5a8bc3836aa1a71de87857c06f8c68a Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 5 Sep 2019 16:56:57 -0400 Subject: [PATCH 1473/1594] update nvmrc file (#4162) --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 4fedf1d20e1..fa97ecedc28 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -7.0 +8.9 From 7a0bf6e982a0706897d4e8c6cf9ef3ac6dbc453a Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Thu, 5 Sep 2019 16:57:54 -0400 Subject: [PATCH 1474/1594] update gulp-footer package (#4160) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 72fedc1bfcb..cf061e9f357 100755 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "gulp-concat": "^2.6.0", "gulp-connect": "^5.7.0", "gulp-eslint": "^4.0.0", - "gulp-footer": "github:prebid/gulp-footer#master", + "gulp-footer": "^2.0.2", "gulp-header": "^1.7.1", "gulp-if": "^2.0.2", "gulp-js-escape": "^1.0.1", From f828b84f90eee79befa0266d2c562cbb6aebf120 Mon Sep 17 00:00:00 2001 From: htang555 Date: Fri, 6 Sep 2019 10:58:52 -0400 Subject: [PATCH 1475/1594] Datablocks bid/analytics adapter (#4128) * add datablocks Analytics and Bidder Adapters * remove preload param * remove preloadid * better coverage of tests * better coverage * IE doesn't support array.find * lint test * update example host * native asset id should be integer --- modules/datablocksAnalyticsAdapter.js | 19 ++ modules/datablocksAnalyticsAdapter.md | 23 ++ modules/datablocksBidAdapter.js | 285 +++++++++++++++++ modules/datablocksBidAdapter.md | 54 ++++ .../spec/modules/datablocksBidAdapter_spec.js | 287 ++++++++++++++++++ 5 files changed, 668 insertions(+) create mode 100644 modules/datablocksAnalyticsAdapter.js create mode 100644 modules/datablocksAnalyticsAdapter.md create mode 100644 modules/datablocksBidAdapter.js create mode 100644 modules/datablocksBidAdapter.md create mode 100644 test/spec/modules/datablocksBidAdapter_spec.js diff --git a/modules/datablocksAnalyticsAdapter.js b/modules/datablocksAnalyticsAdapter.js new file mode 100644 index 00000000000..76dd490180b --- /dev/null +++ b/modules/datablocksAnalyticsAdapter.js @@ -0,0 +1,19 @@ +/** + * Analytics Adapter for Datablocks + */ + +import adapter from '../src/AnalyticsAdapter'; +import adapterManager from '../src/adapterManager'; + +var datablocksAdapter = adapter({ + global: 'datablocksAnalytics', + handler: 'on', + analyticsType: 'bundle' +}); + +adapterManager.registerAnalyticsAdapter({ + adapter: datablocksAdapter, + code: 'datablocks' +}); + +export default datablocksAdapter; diff --git a/modules/datablocksAnalyticsAdapter.md b/modules/datablocksAnalyticsAdapter.md new file mode 100644 index 00000000000..07f65da6e2c --- /dev/null +++ b/modules/datablocksAnalyticsAdapter.md @@ -0,0 +1,23 @@ +# Overview + +Module Name: Datablocks Analytics Adapter +Module Type: Datablocks Adapter +Maintainer: support@datablocks.net + +# Description + +Analytics adapter for Datablocks.net. Contact support@datablocks.net for information. + +# Test Parameters + +``` +{ + provider: 'datablocks', + options: { + publisherId: 12345, + sourceId: 12356, + host: 'prebid.datablocks.net' + + } +} +``` \ No newline at end of file diff --git a/modules/datablocksBidAdapter.js b/modules/datablocksBidAdapter.js new file mode 100644 index 00000000000..aa427c6eae1 --- /dev/null +++ b/modules/datablocksBidAdapter.js @@ -0,0 +1,285 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, NATIVE } from '../src/mediaTypes'; +import { parse as parseUrl } from '../src/url'; +const NATIVE_MAP = { + 'body': 2, + 'body2': 10, + 'price': 6, + 'displayUrl': 11, + 'cta': 12 +}; +const NATIVE_IMAGE = [{ + id: 1, + required: 1, + title: { + len: 140 + } +}, { + id: 2, + required: 1, + img: { type: 3 } +}, { + id: 3, + required: 1, + data: { + type: 11 + } +}, { + id: 4, + required: 0, + data: { + type: 2 + } +}, { + id: 5, + required: 0, + img: { type: 1 } +}, { + id: 6, + required: 0, + data: { + type: 12 + } +}]; + +export const spec = { + supportedMediaTypes: [BANNER, NATIVE], + code: 'datablocks', + isBidRequestValid: function(bid) { + return !!(bid.params.host && bid.params.sourceId && + bid.mediaTypes && (bid.mediaTypes.banner || bid.mediaTypes.native)); + }, + buildRequests: function(validBidRequests, bidderRequest) { + if (!validBidRequests.length) { return []; } + + let imps = {}; + let site = {}; + let device = {}; + let refurl = parseUrl(bidderRequest.referrer); + let requests = []; + + validBidRequests.forEach(bidRequest => { + let imp = { + id: bidRequest.bidId, + tagid: bidRequest.adUnitCode, + secure: window.location.protocol == 'https:' + } + + if (utils.deepAccess(bidRequest, `mediaTypes.banner`)) { + let sizes = bidRequest.mediaTypes.banner.sizes; + if (sizes.length == 1) { + imp.banner = { + w: sizes[0][0], + h: sizes[0][1] + } + } else if (sizes.length > 1) { + imp.banner = { + format: sizes.map(size => ({ w: size[0], h: size[1] })) + }; + } else { + return; + } + } else if (utils.deepAccess(bidRequest, 'mediaTypes.native')) { + let nativeImp = bidRequest.mediaTypes.native; + + if (nativeImp.type) { + let nativeAssets = []; + switch (nativeImp.type) { + case 'image': + nativeAssets = NATIVE_IMAGE; + break; + default: + return; + } + imp.native = JSON.stringify({ assets: nativeAssets }); + } else { + let nativeAssets = []; + let nativeKeys = Object.keys(nativeImp); + nativeKeys.forEach((nativeKey, index) => { + let required = !!nativeImp[nativeKey].required; + let assetId = index + 1; + switch (nativeKey) { + case 'title': + nativeAssets.push({ + id: assetId, + required: required, + title: { + len: nativeImp[nativeKey].len || 140 + } + }); + break; + case 'body': // desc + case 'body2': // desc2 + case 'price': + case 'display_url': + let data = { + id: assetId, + required: required, + data: { + type: NATIVE_MAP[nativeKey] + } + } + if (nativeImp[nativeKey].data && nativeImp[nativeKey].data.len) { data.data.len = nativeImp[nativeKey].data.len; } + + nativeAssets.push(data); + break; + case 'image': + if (nativeImp[nativeKey].sizes && nativeImp[nativeKey].sizes.length) { + nativeAssets.push({ + id: assetId, + required: required, + image: { + type: 3, + w: nativeImp[nativeKey].sizes[0], + h: nativeImp[nativeKey].sizes[1] + } + }) + } + } + }); + imp.native = { + request: JSON.stringify({native: {assets: nativeAssets}}) + }; + } + } + let host = bidRequest.params.host; + let sourceId = bidRequest.params.sourceId; + imps[host] = imps[host] || {}; + let hostImp = imps[host][sourceId] = imps[host][sourceId] || { imps: [] }; + hostImp.imps.push(imp); + hostImp.subid = hostImp.imps.subid || bidRequest.params.subid || 'blank'; + hostImp.path = 'search'; + hostImp.idParam = 'sid'; + hostImp.protocol = '//'; + }); + + // Generate Site obj + site.domain = refurl.hostname; + site.page = refurl.protocol + '://' + refurl.hostname + refurl.pathname; + if (self === top && document.referrer) { + site.ref = document.referrer; + } + let keywords = document.getElementsByTagName('meta')['keywords']; + if (keywords && keywords.content) { + site.keywords = keywords.content; + } + + // Generate Device obj. + device.ip = 'peer'; + device.ua = window.navigator.userAgent; + device.js = 1; + device.language = ((navigator.language || navigator.userLanguage || '').split('-'))[0] || 'en'; + + RtbRequest(device, site, imps).forEach(formatted => { + requests.push({ + method: 'POST', + url: formatted.url, + data: formatted.body, + options: { + withCredentials: false + } + }) + }); + + return requests; + + function RtbRequest(device, site, imps) { + let collection = []; + Object.keys(imps).forEach(host => { + let sourceIds = imps[host]; + Object.keys(sourceIds).forEach(sourceId => { + let impObj = sourceIds[sourceId]; + collection.push({ + url: `${impObj.protocol}${host}/${impObj.path}/?${impObj.idParam}=${sourceId}`, + body: { + id: bidderRequest.auctionId, + imp: impObj.imps, + site: Object.assign({ id: impObj.subid || 'blank' }, site), + device: Object.assign({}, device) + } + }) + }) + }) + + return collection; + } + }, + interpretResponse: function(serverResponse, bidRequest) { + if (!serverResponse || !serverResponse.body || !serverResponse.body.seatbid) { + return []; + } + let body = serverResponse.body; + + let bids = body.seatbid + .map(seatbid => seatbid.bid) + .reduce((memo, bid) => memo.concat(bid), []); + let req = bidRequest.data; + let reqImps = req.imp; + + return bids.map(rtbBid => { + let imp; + for (let i in reqImps) { + let testImp = reqImps[i] + if (testImp.id == rtbBid.impid) { + imp = testImp; + break; + } + } + let br = { + requestId: rtbBid.impid, + cpm: rtbBid.price, + creativeId: rtbBid.crid, + currency: rtbBid.currency || 'USD', + netRevenue: true, + ttl: 360 + }; + if (!imp) { + return br; + } else if (imp.banner) { + br.mediaType = BANNER; + br.width = rtbBid.w; + br.height = rtbBid.h; + br.ad = rtbBid.adm; + } else if (imp.native) { + br.mediaType = NATIVE; + + let reverseNativeMap = {}; + let nativeKeys = Object.keys(NATIVE_MAP); + nativeKeys.forEach(k => { + reverseNativeMap[NATIVE_MAP[k]] = k; + }); + + let idMap = {}; + let nativeReq = JSON.parse(imp.native.request); + if (nativeReq.native && nativeReq.native.assets) { + nativeReq.native.assets.forEach(asset => { + if (asset.data) { idMap[asset.id] = reverseNativeMap[asset.data.type]; } + }) + } + + const nativeResponse = JSON.parse(rtbBid.adm); + const { assets, link, imptrackers, jstrackers } = nativeResponse.native; + const result = { + clickUrl: link.url, + clickTrackers: link.clicktrackers || undefined, + impressionTrackers: imptrackers || undefined, + javascriptTrackers: jstrackers ? [jstrackers] : undefined + }; + assets.forEach(asset => { + if (asset.title) { + result.title = asset.title.text; + } else if (asset.img) { + result.image = asset.img.url; + } else if (idMap[asset.id]) { + result[idMap[asset.id]] = asset.data.value; + } + }) + br.native = result; + } + return br; + }); + } + +}; +registerBidder(spec); diff --git a/modules/datablocksBidAdapter.md b/modules/datablocksBidAdapter.md new file mode 100644 index 00000000000..7562eee5704 --- /dev/null +++ b/modules/datablocksBidAdapter.md @@ -0,0 +1,54 @@ +# Overview + +``` +Module Name: Datablocks Bidder Adapter +Module Type: Bidder Adapter +Maintainer: support@datablocks.net +``` + +# Description + +Connects to Datablocks Version 5 Platform +Banner Native and + + +# Test Parameters +``` + var adUnits = [ + { + code: 'banner-div', + sizes: [[300, 250]], + mediaTypes:{ + banner: { + sizes: [300,250] + } + }, + bids: [ + { + bidder: 'datablocks', + params: { + sourceId: 12345, + host: 'prebid.datablocks.net' + } + } + ] + }, { + code: 'native-div', + mediaTypes : { + native: { + title:{required:true}, + body:{required:true} + } + }, + bids: [ + { + bidder: 'datablocks', + params: { + sourceId: 12345, + host: 'prebid.datablocks.net' + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/datablocksBidAdapter_spec.js b/test/spec/modules/datablocksBidAdapter_spec.js new file mode 100644 index 00000000000..07989b86535 --- /dev/null +++ b/test/spec/modules/datablocksBidAdapter_spec.js @@ -0,0 +1,287 @@ +import { expect } from 'chai'; +import { spec } from '../../../modules/datablocksBidAdapter'; + +let bid = { + bidId: '2dd581a2b6281d', + bidder: 'datablocks', + bidderRequestId: '145e1d6a7837c9', + params: { + sourceId: 7560, + host: 'v5demo.datablocks.net' + }, + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + mediaTypes: { + banner: { + sizes: [ + [300, 250] + ] + } + }, + sizes: [ + [300, 250] + ], + transactionId: '1ccbee15-f6f6-46ce-8998-58fe5542e8e1' +}; + +let bid2 = { + bidId: '2dd581a2b624324g', + bidder: 'datablocks', + bidderRequestId: '145e1d6a7837543', + params: { + sourceId: 7560, + host: 'v5demo.datablocks.net' + }, + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + mediaTypes: { + banner: { + sizes: + [728, 90] + } + }, + transactionId: '1ccbee15-f6f6-46ce-8998-58fe55425432' +}; + +let nativeBid = { + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '160c78a4-f808-410f-b682-d8728f3a79ee', + bidId: '332045ee374a99', + bidder: 'datablocks', + bidderRequestId: '15d9012765e36c', + mediaTypes: { + native: { + title: { + required: true + }, + body: { + required: true + }, + image: { + required: true + } + } + }, + nativeParams: { + title: { + required: true + }, + body: { + required: true, + data: { + len: 250 + } + }, + image: { + required: true, + sizes: [728, 90] + } + }, + params: { + sourceId: 7560, + host: 'v5demo.datablocks.net' + }, + transactionId: '0a4e9788-4def-4b94-bc25-564d7cac99f6' +} + +const bidderRequest = { + auctionId: '8bfef1be-d3ac-4d18-8859-754c7b4cf017', + auctionStart: Date.now(), + biddeCode: 'datablocks', + bidderRequestId: '10c47a5fc3c41', + bids: [bid, bid2, nativeBid], + refererInfo: { + numIframes: 0, + reachedTop: true, + referer: 'http://v5demo.datablocks.net/test', + stack: ['http://v5demo.datablocks.net/test'] + }, + start: Date.now(), + timeout: 10000 +}; + +let resObject = { + body: { + id: '10c47a5fc3c41', + bidid: '166895245-28-11347-1', + seatbid: [{ + seat: '7560', + bid: [{ + id: '1090738570', + impid: '2966b257c81d27', + price: 24.000000, + adm: 'RON', + cid: '55', + adid: '177654', + crid: '177656', + cat: [], + api: [], + w: 300, + h: 250 + }, { + id: '1090738571', + impid: '2966b257c81d28', + price: 24.000000, + adm: 'RON', + cid: '55', + adid: '177654', + crid: '177656', + cat: [], + api: [], + w: 728, + h: 90 + }, { + id: '1090738570', + impid: '15d9012765e36c', + price: 24.000000, + adm: '{"native":{"ver":"1.2","assets":[{"id":1,"required":1,"title":{"text":"Example Title"}},{"id":2,"required":1,"data":{"value":"Example Body"}},{"id":3,"required":1,"img":{"url":"http://example.image.com/"}}],"link":{"url":"http://click.example.com/c/264597/?fcid=29699699045816"},"imptrackers":["http://impression.example.com/i/264597/?fcid=29699699045816"]}}', + cid: '132145', + adid: '154321', + crid: '177432', + cat: [], + api: [] + }] + }], + cur: 'USD', + ext: {} + } +}; +let bidRequest = { + method: 'POST', + url: '//v5demo.datablocks.net/search/?sid=7560', + options: { + withCredentials: false + }, + data: { + device: { + ip: 'peer', + ua: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) Ap…ML, like Gecko) Chrome/73.0.3683.86 Safari/537.36', + js: 1, + language: 'en' + }, + id: '10c47a5fc3c41', + imp: [{ + banner: { w: 300, h: 250 }, + id: '2966b257c81d27', + secure: false, + tagid: '/19968336/header-bid-tag-0' + }, { + banner: { w: 728, h: 90 }, + id: '2966b257c81d28', + secure: false, + tagid: '/19968336/header-bid-tag-0' + }, { + id: '15d9012765e36c', + native: {request: '{"native":{"assets":[{"id":"1","required":true,"title":{"len":140}},{"id":"2","required":true,"data":{"type":2}},{"id":"3","img":{"w":728,"h":90,"type":3}}]}}'}, + secure: false, + tagid: '/19968336/header-bid-tag-0' + }], + site: { + domain: '', + id: 'blank', + page: 'http://v5demo.datablocks.net/test' + } + } +} + +describe('DatablocksAdapter', function() { + describe('isBidRequestValid', function() { + it('Should return true when sourceId and Host are set', function() { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when host/sourceId is not set', function() { + let moddedBid = Object.assign({}, bid); + delete moddedBid.params.sourceId; + delete moddedBid.params.host; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', function() { + let requests = spec.buildRequests([bid, bid2, nativeBid], bidderRequest); + it('Creates an array of request objects', function() { + expect(requests).to.be.an('array').that.is.not.empty; + }); + + requests.forEach(request => { + expect(request).to.exist; + it('Returns POST method', function() { + expect(request.method).to.exist; + expect(request.method).to.equal('POST'); + }); + it('Returns valid URL', function() { + expect(request.url).to.exist; + expect(request.url).to.equal('//v5demo.datablocks.net/search/?sid=7560'); + }); + + it('Should be a valid openRTB request', function() { + let data = request.data; + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('device', 'imp', 'site', 'id'); + expect(data.id).to.be.a('string'); + + let imps = data['imp']; + imps.forEach((imp, index) => { + let curBid = bidderRequest.bids[index]; + if (imp.banner) { + expect(imp).to.have.all.keys('banner', 'id', 'secure', 'tagid'); + expect(imp.banner).to.be.a('object'); + } else if (imp.native) { + expect(imp).to.have.all.keys('native', 'id', 'secure', 'tagid'); + expect(imp.native).to.have.all.keys('request'); + expect(imp.native.request).to.be.a('string'); + let native = JSON.parse(imp.native.request); + expect(native).to.be.a('object'); + } else { + expect(true).to.equal(false); + } + + expect(imp.id).to.be.a('string'); + expect(imp.id).to.equal(curBid.bidId); + expect(imp.tagid).to.be.a('string'); + expect(imp.tagid).to.equal(curBid.adUnitCode); + expect(imp.secure).to.equal(false); + }) + + expect(data.device.ip).to.equal('peer'); + }); + }) + + it('Returns empty data if no valid requests are passed', function() { + let request = spec.buildRequests([]); + expect(request).to.be.an('array').that.is.empty; + }); + }); + describe('interpretResponse', function() { + let serverResponses = spec.interpretResponse(resObject, bidRequest); + it('Returns an array of valid server responses if response object is valid', function() { + expect(serverResponses).to.be.an('array').that.is.not.empty; + for (let i = 0; i < serverResponses.length; i++) { + let dataItem = serverResponses[i]; + expect(Object.keys(dataItem)).to.include('cpm', 'ttl', 'creativeId', + 'netRevenue', 'currency', 'mediaType', 'requestId'); + expect(dataItem.requestId).to.be.a('string'); + expect(dataItem.cpm).to.be.a('number'); + 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'); + + if (dataItem.mediaType == 'banner') { + expect(dataItem.ad).to.be.a('string'); + expect(dataItem.width).to.be.a('number'); + expect(dataItem.height).to.be.a('number'); + } else if (dataItem.mediaType == 'native') { + expect(dataItem.native.title).to.be.a('string'); + expect(dataItem.native.body).to.be.a('string'); + expect(dataItem.native.clickUrl).to.be.a('string'); + } + } + it('Returns an empty array if invalid response is passed', function() { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); +}); From 2bdbb12ff4c07a19e482180615b416b703a46533 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Fri, 6 Sep 2019 13:39:03 -0400 Subject: [PATCH 1476/1594] update logic of ad_types field in appnexusBidAdapter (#4065) --- modules/appnexusBidAdapter.js | 11 +++-- test/spec/modules/appnexusBidAdapter_spec.js | 45 ++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index d0f4774185e..730ca18ce84 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -3,6 +3,7 @@ import * as utils from '../src/utils'; import { config } from '../src/config'; import { registerBidder, getIabSubCategory } from '../src/adapters/bidderFactory'; import { BANNER, NATIVE, VIDEO, ADPOD } from '../src/mediaTypes'; +import { auctionManager } from '../src/auctionManager'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; @@ -665,13 +666,15 @@ function bidToTag(bid) { tag.video = Object.assign({}, tag.video, {custom_renderer_present: true}); } - if ( - (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) || - (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER])) - ) { + 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; } diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index e1cca8c05ff..d5b11e95351 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -2,6 +2,7 @@ import { expect } from 'chai'; import { spec } from 'modules/appnexusBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import * as bidderFactory from 'src/adapters/bidderFactory'; +import { auctionManager } from 'src/auctionManager'; import { deepClone } from 'src/utils'; import { config } from 'src/config'; @@ -55,6 +56,7 @@ describe('AppNexusAdapter', function () { }); describe('buildRequests', function () { + let getAdUnitsStub; let bidRequests = [ { 'bidder': 'appnexus', @@ -66,9 +68,20 @@ describe('AppNexusAdapter', function () { '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], @@ -98,7 +111,27 @@ describe('AppNexusAdapter', function () { }); 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: 'appnexus', + 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] = {}; @@ -107,9 +140,21 @@ describe('AppNexusAdapter', function () { 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 = {}; From 02cd6e47dca60b801bfd5642d9f03648f4787e8f Mon Sep 17 00:00:00 2001 From: Bryan DeLong Date: Sat, 7 Sep 2019 22:41:55 -0400 Subject: [PATCH 1477/1594] Shorten SomoAudience to just Somo (#4163) * Shorten SomoAudience to just Somo * Make package-lock return --- ...udienceBidAdapter.js => somoBidAdapter.js} | 28 ++------------ ...udienceBidAdapter.md => somoBidAdapter.md} | 6 +-- ...Adapter_spec.js => somoBidAdapter_spec.js} | 38 +++++++++---------- 3 files changed, 25 insertions(+), 47 deletions(-) rename modules/{somoaudienceBidAdapter.js => somoBidAdapter.js} (91%) rename modules/{somoaudienceBidAdapter.md => somoBidAdapter.md} (89%) rename test/spec/modules/{somoaudienceBidAdapter_spec.js => somoBidAdapter_spec.js} (96%) diff --git a/modules/somoaudienceBidAdapter.js b/modules/somoBidAdapter.js similarity index 91% rename from modules/somoaudienceBidAdapter.js rename to modules/somoBidAdapter.js index 2afb9265d6c..95e823a5d94 100644 --- a/modules/somoaudienceBidAdapter.js +++ b/modules/somoBidAdapter.js @@ -13,10 +13,10 @@ const APP_TARGETING = ['name', 'bundle', 'domain', 'storeUrl', 'cat', 'ver', 'ke export const spec = { - code: 'somoaudience', + code: 'somo', supportedMediaTypes: [BANNER, VIDEO], - aliases: ['somo'], + aliases: ['somoaudience'], isBidRequestValid: bid => ( !!(bid && bid.params && bid.params.placementId) @@ -25,29 +25,7 @@ export const spec = { buildRequests: function(bidRequests, bidderRequest) { return bidRequests.map(bidRequest => { let da = openRtbRequest(bidRequest, bidderRequest); - if (window.top1 && window.top1.realvu_aa) { - let a = window.top1.realvu_aa.check({ - unit_id: bidRequest.adUnitCode, - size: bidRequest.sizes, - partner_id: 'E321' - }); - a.rq_bids.push({ - bidder: bidRequest.bidder, - adId: bidRequest.bidId, - partner_id: 'E321' - }); - if (a.riff == 'yes') { - da.imp[0].pmp = { - private_auction: 0, - deals: [ - { - id: 'realvu', - bidfloor: 1.5 - } - ] - }; - } - } + return { method: 'POST', url: '//publisher-east.mobileadtrading.com/rtb/bid?s=' + bidRequest.params.placementId.toString(), diff --git a/modules/somoaudienceBidAdapter.md b/modules/somoBidAdapter.md similarity index 89% rename from modules/somoaudienceBidAdapter.md rename to modules/somoBidAdapter.md index 10af6023cb5..de395478061 100644 --- a/modules/somoaudienceBidAdapter.md +++ b/modules/somoBidAdapter.md @@ -5,7 +5,7 @@ **Maintainer**: prebid@somoaudience.com # Description Connects to Somo Audience demand source. -Please use ```somoaudience``` as the bidder code. +Please use ```somo``` as the bidder code. For video integration, somoAudience 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 # Test Site Parameters @@ -14,7 +14,7 @@ For video integration, somoAudience returns content as vastXML and requires the code: 'banner-ad-div', sizes: [[300, 250]], bids: [{ - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: '22a58cfb0c9b656bff713d1236e930e8' } @@ -27,7 +27,7 @@ var adUnits = [{ code: 'banner-ad-div', sizes: [[300, 250]], bids: [{ - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: '22a58cfb0c9b656bff713d1236e930e8', app: { diff --git a/test/spec/modules/somoaudienceBidAdapter_spec.js b/test/spec/modules/somoBidAdapter_spec.js similarity index 96% rename from test/spec/modules/somoaudienceBidAdapter_spec.js rename to test/spec/modules/somoBidAdapter_spec.js index bdd2dade96f..16fd43841b7 100644 --- a/test/spec/modules/somoaudienceBidAdapter_spec.js +++ b/test/spec/modules/somoBidAdapter_spec.js @@ -1,19 +1,19 @@ import {expect} from 'chai'; -import {spec} from 'modules/somoaudienceBidAdapter'; +import {spec} from 'modules/somoBidAdapter'; import * as utils from 'src/utils'; describe('Somo Audience Adapter Tests', function () { describe('isBidRequestValid', function () { it('should return false when given an invalid bid', function () { const bid = { - bidder: 'somoaudience', + bidder: 'somo', }; const isValid = spec.isBidRequestValid(bid); expect(isValid).to.equal(false); }); it('should return true when given a placementId bid', function () { const bid = { - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test' } @@ -27,7 +27,7 @@ describe('Somo Audience Adapter Tests', function () { describe('buildBannerRequests', function () { it('should properly build a banner request with type not defined and sizes not defined', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test' } @@ -49,7 +49,7 @@ describe('Somo Audience Adapter Tests', function () { it('should properly build a banner request with sizes defined in 2d array', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', sizes: [[300, 250]], params: { placementId: 'test' @@ -71,7 +71,7 @@ describe('Somo Audience Adapter Tests', function () { }); it('should properly build a banner request with sizes defined in 1d array', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', sizes: [300, 250], params: { placementId: 'test' @@ -99,7 +99,7 @@ describe('Somo Audience Adapter Tests', function () { it('should populate optional banner parameters', function () { const bidRequests = [ { - bidder: 'somoaudience', + bidder: 'somo', sizes: [[300, 200]], mediaType: 'banner', params: { @@ -128,7 +128,7 @@ describe('Somo Audience Adapter Tests', function () { describe('buildVideoRequests', function () { it('should properly build a video request with sizes defined', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', mediaTypes: { video: {} }, @@ -151,7 +151,7 @@ describe('Somo Audience Adapter Tests', function () { it('should properly build a video request with sizes defined in 2d array', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', mediaTypes: { video: {} }, @@ -173,7 +173,7 @@ describe('Somo Audience Adapter Tests', function () { }); it('should properly build a video request with sizes not defined', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', mediaType: 'video', params: { placementId: 'test' @@ -199,7 +199,7 @@ describe('Somo Audience Adapter Tests', function () { it('should populate optional video parameters', function () { const bidRequests = [ { - bidder: 'somoaudience', + bidder: 'somo', sizes: [[200, 300]], mediaType: 'video', params: { @@ -242,7 +242,7 @@ describe('Somo Audience Adapter Tests', function () { describe('buildSiteRequests', function () { it('should fill in basic site parameters', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test' } @@ -258,7 +258,7 @@ describe('Somo Audience Adapter Tests', function () { it('should fill in optional site parameters', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test', site: { @@ -285,7 +285,7 @@ describe('Somo Audience Adapter Tests', function () { describe('buildAppRequests', function () { it('should fill in app parameters', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test', app: { @@ -325,7 +325,7 @@ describe('Somo Audience Adapter Tests', function () { it('should properly build request with gdpr consent', function () { const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test' } @@ -342,7 +342,7 @@ describe('Somo Audience Adapter Tests', function () { it('should properly build request with gdpr not applies', function () { bidderRequest.gdprConsent.gdprApplies = false; const bidRequests = [{ - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test' } @@ -362,7 +362,7 @@ describe('Somo Audience Adapter Tests', function () { it('should populate optional parameters', function () { const bidRequests = [ { - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test', bcat: ['IAB-2', 'IAB-7'], @@ -389,7 +389,7 @@ describe('Somo Audience Adapter Tests', function () { it('Verify banner parse response', function () { const bidRequests = [ { - bidder: 'somoaudience', + bidder: 'somo', params: { placementId: 'test', }, @@ -417,7 +417,7 @@ describe('Somo Audience Adapter Tests', function () { it('Verify video parse response', function () { const bidRequests = [ { - bidder: 'somoaudience', + bidder: 'somo', mediaTypes: { video: { } From 69107fe0ef5876c39e14ceda9d4e6d60e1bfa45d Mon Sep 17 00:00:00 2001 From: dpapworth-qc <50959025+dpapworth-qc@users.noreply.github.com> Date: Sun, 8 Sep 2019 03:47:52 +0100 Subject: [PATCH 1478/1594] Quantcast: Fix for empty video parameters (#4145) * Copy params from bid.params.video. * Added test for missing video parameters. * Include mimes from adunit. --- modules/quantcastBidAdapter.js | 19 +++- test/spec/modules/quantcastBidAdapter_spec.js | 96 +++++++++++++++---- 2 files changed, 98 insertions(+), 17 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index afe95ffb832..739cf75c555 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -34,7 +34,24 @@ function extractBidSizes(bid) { } function makeVideoImp(bid) { - const video = bid.params.video; + const video = {}; + if (bid.params.video) { + video['mimes'] = bid.params.video.mimes; + video['minduration'] = bid.params.video.minduration; + video['maxduration'] = bid.params.video.maxduration; + video['protocols'] = bid.params.video.protocols; + video['startdelay'] = bid.params.video.startdelay; + video['linearity'] = bid.params.video.linearity; + video['battr'] = bid.params.video.battr; + video['maxbitrate'] = bid.params.video.maxbitrate; + video['playbackmethod'] = bid.params.video.playbackmethod; + video['delivery'] = bid.params.video.delivery; + video['placement'] = bid.params.video.placement; + video['api'] = bid.params.video.api; + } + if (bid.mediaTypes.video.mimes) { + video['mimes'] = bid.mediaTypes.video.mimes; + } if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { video['w'] = bid.mediaTypes.video.playerSize[0][0]; video['h'] = bid.mediaTypes.video.playerSize[0][1]; diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index e29a12a22be..b553cf5d37e 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -39,24 +39,11 @@ describe('Quantcast adapter', function () { }; }); - function setupVideoBidRequest() { + function setupVideoBidRequest(videoParams) { bidRequest.params = { publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast // Video object as specified in OpenRTB 2.5 - video: { - mimes: ['video/mp4'], // required - minduration: 3, // optional - maxduration: 5, // optional - protocols: [3], // optional - startdelay: 1, // optional - linearity: 1, // optinal - battr: [1, 2], // optional - maxbitrate: 10, // optional - playbackmethod: [1], // optional - delivery: [1], // optional - placement: 1, // optional - api: [2, 3] // optional - } + video: videoParams }; bidRequest['mediaTypes'] = { video: { @@ -162,7 +149,20 @@ describe('Quantcast adapter', function () { }); it('sends video bid requests containing all the required parameters', function () { - setupVideoBidRequest(); + setupVideoBidRequest({ + mimes: ['video/mp4'], // required + minduration: 3, // optional + maxduration: 5, // optional + protocols: [3], // optional + startdelay: 1, // optional + linearity: 1, // optinal + battr: [1, 2], // optional + maxbitrate: 10, // optional + playbackmethod: [1], // optional + delivery: [1], // optional + placement: 1, // optional + api: [2, 3] // optional + }); const requests = qcSpec.buildRequests([bidRequest], bidderRequest); const expectedVideoBidRequest = { @@ -203,6 +203,70 @@ describe('Quantcast adapter', function () { expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); }); + it('overrides video parameters with parameters from adunit', function() { + setupVideoBidRequest({ + mimes: ['video/mp4'] + }); + bidRequest.mediaTypes.video.mimes = ['video/webm']; + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + const expectedVideoBidRequest = { + publisherId: QUANTCAST_TEST_PUBLISHER, + requestId: '2f7b179d443f14', + imp: [ + { + video: { + mimes: ['video/webm'], + w: 600, + h: 300 + }, + placementCode: 'div-gpt-ad-1438287399331-0', + bidFloor: 1e-10 + } + ], + site: { + page: 'http://example.com/hello.html', + referrer: 'http://example.com/hello.html', + domain: 'example.com' + }, + bidId: '2f7b179d443f14', + gdprSignal: 0, + prebidJsVersion: '$prebid.version$' + }; + + expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); + }); + + it('sends video bid request when no video parameters are given', function () { + setupVideoBidRequest(null); + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + const expectedVideoBidRequest = { + publisherId: QUANTCAST_TEST_PUBLISHER, + requestId: '2f7b179d443f14', + imp: [ + { + video: { + w: 600, + h: 300 + }, + placementCode: 'div-gpt-ad-1438287399331-0', + bidFloor: 1e-10 + } + ], + site: { + page: 'http://example.com/hello.html', + referrer: 'http://example.com/hello.html', + domain: 'example.com' + }, + bidId: '2f7b179d443f14', + gdprSignal: 0, + prebidJsVersion: '$prebid.version$' + }; + + expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); + }); + it('ignores unsupported video bid requests', function () { bidRequest.mediaTypes = { video: { From 97fab619e3e61b1022b6f8738b2bf2ff4a27374a Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Sun, 8 Sep 2019 08:20:11 +0530 Subject: [PATCH 1479/1594] One Video adding Rewarded Video Feature (#4142) * outstream changes * removing global filtet * reverting page * message * adapter change * remove space * testcases * testpage * spaces for test page * renderer exist case * reverting package-lock.json * adding schain object * adding tagid * syntaxx error fix * video.html * space trailing * space * tagid * inventoryId and placement * rewarded video * added unit test case --- modules/oneVideoBidAdapter.js | 3 +++ modules/oneVideoBidAdapter.md | 3 ++- test/pages/video.html | 2 +- test/spec/modules/oneVideoBidAdapter_spec.js | 11 ++++++++--- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index a4ea4c86e03..16883aedc86 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -193,6 +193,9 @@ function getRequestData(bid, consentData) { if (bid.params.video.placement) { bidData.imp[0].ext.placement = bid.params.video.placement } + if (bid.params.video.rewarded) { + bidData.imp[0].ext.rewarded = bid.params.video.rewarded + } if (bid.params.site && bid.params.site.id) { bidData.site.id = bid.params.site.id } diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md index c8c4d87f9cb..c7f6af399e7 100644 --- a/modules/oneVideoBidAdapter.md +++ b/modules/oneVideoBidAdapter.md @@ -35,8 +35,9 @@ Connects to One Video demand source to fetch bids. playbackmethod: [1,5], placement: 123, sid: , - }, + rewarded: 1 }, + }, site: { id: 1, page: 'http://abhi12345.com', diff --git a/test/pages/video.html b/test/pages/video.html index 09e75379e69..e040b65fe23 100644 --- a/test/pages/video.html +++ b/test/pages/video.html @@ -133,4 +133,4 @@

    Prebid Video -- video.js

    - \ No newline at end of file + diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 09ca6217fe2..58b90b0a017 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -31,7 +31,8 @@ describe('OneVideoBidAdapter', function () { delivery: [2], playbackmethod: [1, 5], placement: 123, - sid: 134 + sid: 134, + rewarded: 1 }, site: { id: 1, @@ -67,7 +68,8 @@ describe('OneVideoBidAdapter', function () { delivery: [2], playbackmethod: [1, 5], placement: 123, - sid: 134 + sid: 134, + rewarded: 1 } }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); @@ -84,7 +86,8 @@ describe('OneVideoBidAdapter', function () { delivery: [2], playbackmethod: [1, 5], placement: 123, - sid: 134 + sid: 134, + rewarded: 1 }, pubId: 'brxd' }; @@ -114,10 +117,12 @@ describe('OneVideoBidAdapter', function () { const data = requests[0].data; const [ width, height ] = bidRequest.sizes; const placement = bidRequest.params.video.placement; + const rewarded = bidRequest.params.video.rewarded; expect(data.imp[0].video.w).to.equal(width); expect(data.imp[0].video.h).to.equal(height); expect(data.imp[0].ext.placement).to.equal(placement); expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); + expect(data.imp[0].ext.rewarded).to.equal(rewarded); }); it('must parse bid size from a nested array', function () { From 25b64718a34916bac9904854796c986f40fc9268 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 9 Sep 2019 10:56:51 -0700 Subject: [PATCH 1480/1594] Module to pass User Ids to DFP (#4140) * first commit * renamed * minor doc change * documentation * small change * EB * removed unused imports * minor changes * reanmaed a const * adding more methods to test shareUserIds module * unit tets cases for shareUserIds * indentation * renamed DFP to GAM * renamed shareUserIds to userIdTargeting * Update userIdTargeting.md * trying to restart CI * digitrust userId case handled * minor comment change * using auctionEnd event instead of requestBids.before * using events.on --- modules/userIdTargeting.js | 61 ++++++++++++++++++++++++++ modules/userIdTargeting.md | 37 ++++++++++++++++ test/spec/modules/shareUserIds_spec.js | 53 ++++++++++++++++++++++ test/spec/unit/pbjs_api_spec.js | 13 ++++++ 4 files changed, 164 insertions(+) create mode 100644 modules/userIdTargeting.js create mode 100644 modules/userIdTargeting.md create mode 100644 test/spec/modules/shareUserIds_spec.js diff --git a/modules/userIdTargeting.js b/modules/userIdTargeting.js new file mode 100644 index 00000000000..2a19bd62fbb --- /dev/null +++ b/modules/userIdTargeting.js @@ -0,0 +1,61 @@ +import {config} from '../src/config'; +import {getGlobal} from '../src/prebidGlobal'; +import CONSTANTS from '../src/constants.json'; +import events from '../src/events'; +import { isStr, isPlainObject, isBoolean, isFn, hasOwn, logInfo } from '../src/utils'; + +const MODULE_NAME = 'userIdTargeting'; +const GAM = 'GAM'; +const GAM_KEYS_CONFIG = 'GAM_KEYS'; + +export function userIdTargeting(userIds, config) { + if (!isPlainObject(config)) { + logInfo(MODULE_NAME + ': Invalid config found, not sharing userIds externally.'); + return; + } + + const PUB_GAM_KEYS = isPlainObject(config[GAM_KEYS_CONFIG]) ? config[GAM_KEYS_CONFIG] : {}; + let SHARE_WITH_GAM = isBoolean(config[GAM]) ? config[GAM] : false; + let GAM_API; + + if (!SHARE_WITH_GAM) { + logInfo(MODULE_NAME + ': Not enabled for ' + GAM); + } + + if (window.googletag && isFn(window.googletag.pubads) && hasOwn(window.googletag.pubads(), 'setTargeting') && isFn(window.googletag.pubads().setTargeting)) { + GAM_API = window.googletag.pubads().setTargeting; + } else { + SHARE_WITH_GAM = false; + logInfo(MODULE_NAME + ': Could not find googletag.pubads().setTargeting API. Not adding User Ids in targeting.') + return; + } + + Object.keys(userIds).forEach(function(key) { + if (userIds[key]) { + // PUB_GAM_KEYS: { "tdid": '' } means the publisher does not want to send the tdid to GAM + if (SHARE_WITH_GAM && PUB_GAM_KEYS[key] !== '') { + let uidStr; + if (isStr(userIds[key])) { + uidStr = userIds[key]; + } else if (isPlainObject(userIds[key])) { + uidStr = JSON.stringify(userIds[key]) + } else { + logInfo(MODULE_NAME + ': ' + key + ' User ID is not an object or a string.'); + return; + } + GAM_API( + (hasOwn(PUB_GAM_KEYS, key) ? PUB_GAM_KEYS[key] : key), + [ uidStr ] + ); + } + } + }); +} + +export function init(config) { + events.on(CONSTANTS.EVENTS.AUCTION_END, function() { + userIdTargeting((getGlobal()).getUserIds(), config.getConfig(MODULE_NAME)); + }) +} + +init(config) diff --git a/modules/userIdTargeting.md b/modules/userIdTargeting.md new file mode 100644 index 00000000000..f99fd5308b3 --- /dev/null +++ b/modules/userIdTargeting.md @@ -0,0 +1,37 @@ +## userIdTargeting Module +- This module works with userId module. +- This module is used to pass userIds to GAM in targeting so that user ids can be used to pass in Google Exchange Bidding or can be used for targeting in GAM. + +## Sample config +``` +pbjs.setConfig({ + + // your existing userIds config + + usersync: { + userIds: [{...}, ...] + }, + + // new userIdTargeting config + + userIdTargeting: { + "GAM": true, + "GAM_KEYS": { + "tdid": "TTD_ID" // send tdid as TTD_ID + } + } +}); +``` + +## Config options +- GAM: is required to be set to true if a publisher wants to send UserIds as targeting in GAM call. This module uses ``` googletag.pubads().setTargeting('key-name', ['value']) ``` API to set GAM targeting. +- GAM_KEYS: is an optional config object to be used with ``` "GAM": true ```. If not passed then all UserIds are passed with respective key-name used in UserIds object. +If a publisher wants to pass ```UserId.tdid``` as TTD_ID in targeting then set ``` GAM_KEYS: { "tdid": "TTD_ID" }``` +If a publisher does not wants to pass ```UserId.tdid``` but wants to pass other Ids in UserId tthen set ``` GAM_KEYS: { "tdid": "" }``` + +## Including this module in Prebid +``` $ gulp build --modules=userId,userIdTargeting,pubmaticBidAdapter ``` + +## Notes +- We can add support for other external systems like GAM in future +- We have not added support for A9/APSTag as it is called in parallel with Prebid. This module executes when ```pbjs.requestBids``` is called, in practice, call to A9 is expected to execute in paralle to Prebid thus we have not covered A9 here. For sending Uids in A9, one will need to set those Ids in params key in the object passed to ```apstag.init```, ```pbjs.getUserIds``` can be used for the same. diff --git a/test/spec/modules/shareUserIds_spec.js b/test/spec/modules/shareUserIds_spec.js new file mode 100644 index 00000000000..4ae5f93a1a6 --- /dev/null +++ b/test/spec/modules/shareUserIds_spec.js @@ -0,0 +1,53 @@ +import {userIdTargeting} from '../../../modules/userIdTargeting'; +import { expect } from 'chai'; + +describe('#userIdTargeting', function() { + let userIds; + let config; + + beforeEach(function() { + userIds = { + tdid: 'my-tdid' + }; + config = { + 'GAM': true, + 'GAM_KEYS': { + 'tdid': 'TD_ID' + } + }; + }); + + it('Do nothing if config is invaild', function() { + let pubads = window.googletag.pubads(); + pubads.clearTargeting(); + pubads.setTargeting('test', ['TEST']); + userIdTargeting(userIds, JSON.stringify(config)); + expect(pubads.getTargeting()).to.deep.equal({test: ['TEST']}); + }); + + it('all UserIds are passed as is with GAM: true', function() { + let pubads = window.googletag.pubads(); + pubads.clearTargeting(); + pubads.setTargeting('test', ['TEST']); + delete config.GAM_KEYS; + userIdTargeting(userIds, config); + expect(pubads.getTargeting()).to.deep.equal({test: ['TEST'], tdid: ['my-tdid']}); + }) + + it('Publisher prefered key-names are used', function() { + let pubads = window.googletag.pubads(); + pubads.clearTargeting(); + pubads.setTargeting('test', ['TEST']); + userIdTargeting(userIds, config); + expect(pubads.getTargeting()).to.deep.equal({test: ['TEST'], 'TD_ID': ['my-tdid']}); + }); + + it('Publisher does not want to pass an id', function() { + let pubads = window.googletag.pubads(); + pubads.clearTargeting(); + pubads.setTargeting('test', ['TEST']); + config.GAM_KEYS.tdid = ''; + userIdTargeting(userIds, config); + expect(pubads.getTargeting()).to.deep.equal({test: ['TEST']}); + }); +}); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index c73604cac82..485dd5cf077 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -108,6 +108,7 @@ var createSlotArrayScenario2 = function createSlotArrayScenario2() { window.googletag = { _slots: [], + _targeting: {}, pubads: function () { var self = this; return { @@ -117,6 +118,18 @@ window.googletag = { setSlots: function (slots) { self._slots = slots; + }, + + setTargeting: function(key, arrayOfValues) { + self._targeting[key] = arrayOfValues; + }, + + getTargeting: function() { + return self._targeting; + }, + + clearTargeting: function() { + self._targeting = {}; } }; } From c520176a8cec2f549fd9c0d4121af1c1b2c898dc Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 10 Sep 2019 07:13:28 +0300 Subject: [PATCH 1481/1594] Buzzoola bid adapter (#4127) * initial commit for buzzoola adapter * leave only banners for now * fix bid validation * change endpoint url * add video type * restore renderer * fix renderer * add fixed player sizes * switch bids * convert dimentions to strings * write tests * 100% tests * remove new DOM element creation in tests * handle empty response from server * change description --- modules/buzzoolaBidAdapter.js | 108 + modules/buzzoolaBidAdapter.md | 72 + package-lock.json | 6864 +++++++++++++++--- test/spec/modules/buzzoolaBidAdapter_spec.js | 279 + 4 files changed, 6388 insertions(+), 935 deletions(-) create mode 100644 modules/buzzoolaBidAdapter.js create mode 100644 modules/buzzoolaBidAdapter.md create mode 100644 test/spec/modules/buzzoolaBidAdapter_spec.js diff --git a/modules/buzzoolaBidAdapter.js b/modules/buzzoolaBidAdapter.js new file mode 100644 index 00000000000..da2a3b30c2e --- /dev/null +++ b/modules/buzzoolaBidAdapter.js @@ -0,0 +1,108 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER, VIDEO} from '../src/mediaTypes'; +import {Renderer} from '../src/Renderer'; +import {OUTSTREAM} from '../src/video'; + +const BIDDER_CODE = 'buzzoola'; +const ENDPOINT = 'https://exchange.buzzoola.com/ssp/prebidjs'; +const RENDERER_SRC = 'https://tube.buzzoola.com/new/build/buzzlibrary.js'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['buzzoolaAdapter'], + 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) { + let types = bid.mediaTypes; + return !!(bid && bid.mediaTypes && (types.banner || types.video) && bid.params && bid.params.placementId); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests an array of bids + * @param bidderRequest + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (validBidRequests, bidderRequest) { + return { + url: ENDPOINT, + method: 'POST', + data: bidderRequest, + } + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @param bidderRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function ({body}, {data}) { + let requestBids = {}; + let response; + + try { + response = JSON.parse(body); + } catch (ex) { + response = body; + } + + if (!Array.isArray(response)) response = []; + + data.bids.forEach(bid => requestBids[bid.bidId] = bid); + + return response.map(bid => { + let requestBid = requestBids[bid.requestId]; + let context = utils.deepAccess(requestBid, 'mediaTypes.video.context'); + let validBid = utils.deepClone(bid); + + if (validBid.mediaType === VIDEO && context === OUTSTREAM) { + let renderer = Renderer.install({ + id: validBid.requestId, + url: RENDERER_SRC, + loaded: false + }); + + renderer.setRender(setOutstreamRenderer); + validBid.renderer = renderer + } + + return validBid; + }); + } +}; + +/** + * Initialize Buzzoola Outstream player + * + * @param bid + */ +function setOutstreamRenderer(bid) { + let adData = JSON.parse(bid.ad); + let unitSettings = utils.deepAccess(adData, 'placement.unit_settings'); + let extendedSettings = { + width: '' + bid.width, + height: '' + bid.height, + container_height: '' + bid.height + }; + + adData.placement = Object.assign({}, adData.placement); + adData.placement.unit_settings = Object.assign({}, unitSettings, extendedSettings); + + bid.renderer.push(() => { + window.Buzzoola.Core.install(document.querySelector(`#${bid.adUnitCode}`), { + data: adData + }); + }); +} + +registerBidder(spec); diff --git a/modules/buzzoolaBidAdapter.md b/modules/buzzoolaBidAdapter.md new file mode 100644 index 00000000000..aec3eda6c58 --- /dev/null +++ b/modules/buzzoolaBidAdapter.md @@ -0,0 +1,72 @@ +# Overview + +``` +Module Name: Buzzoola Bid Adapter +Module Type: Bidder Adapter +Maintainer: devteam@buzzoola.com +``` + +# Description + +Connects to Buzzoola exchange for bids. + +Buzzoola bid adapter supports Banner and Video (instream and outstream). + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[240, 400], [300, 600]], + } + }, + bids: [{ + bidder: 'buzzoola', + params: { + placementId: 417846 + } + }] + }, + // Video instream adUnit + { + code: 'video-instream', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 380], + mimes: ['video/mp4'], + minduration: 1, + maxduration: 2, + } + }, + bids: [{ + bidder: 'buzzoola', + params: { + placementId: 417845 + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 380], + mimes: ['video/mp4'], + minduration: 1, + maxduration: 2, + } + }, + bids: [{ + bidder: 'buzzoola', + params: { + placementId: 417845 + } + }] + } +]; +``` diff --git a/package-lock.json b/package-lock.json index e8e1461cbe8..9013350fb01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,97 +1,173 @@ { "name": "prebid.js", - "version": "2.27.0-pre", + "version": "2.30.0-pre", "lockfileVersion": 1, + "requires": true, "dependencies": { "@babel/code-frame": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "dev": true + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } }, "@babel/core": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", - "dev": true + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } }, "@babel/generator": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } }, "@babel/helper-annotate-as-pure": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-call-delegate": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } }, "@babel/helper-define-map": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } }, "@babel/helper-explode-assignable-expression": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-get-function-arity": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, "@babel/helper-hoist-variables": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } }, "@babel/helper-member-expression-to-functions": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.5.5" + } }, "@babel/helper-module-imports": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, "@babel/helper-module-transforms": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } }, "@babel/helper-optimise-call-expression": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, "@babel/helper-plugin-utils": { "version": "7.0.0", @@ -103,49 +179,88 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.13" + } }, "@babel/helper-remap-async-to-generator": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-replace-supers": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } }, "@babel/helper-simple-access": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-split-export-declaration": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } }, "@babel/helper-wrap-function": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + } }, "@babel/helpers": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", - "dev": true + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } }, "@babel/highlight": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", - "dev": true + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } }, "@babel/parser": { "version": "7.5.5", @@ -157,289 +272,535 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } }, "@babel/plugin-proposal-dynamic-import": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0" + } }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" + } }, "@babel/plugin-proposal-object-rest-spread": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + } }, "@babel/plugin-proposal-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } }, "@babel/plugin-proposal-unicode-property-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } }, "@babel/plugin-syntax-async-generators": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-syntax-dynamic-import": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-syntax-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-async-to-generator": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } }, "@babel/plugin-transform-block-scoped-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-block-scoping": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.13" + } }, "@babel/plugin-transform-classes": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-split-export-declaration": "^7.4.4", + "globals": "^11.1.0" + } }, "@babel/plugin-transform-computed-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-destructuring": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-dotall-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } }, "@babel/plugin-transform-duplicate-keys": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-exponentiation-operator": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-for-of": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-function-name": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-member-expression-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-modules-amd": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, "@babel/plugin-transform-modules-commonjs": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, "@babel/plugin-transform-modules-systemjs": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, "@babel/plugin-transform-modules-umd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", - "dev": true + "dev": true, + "requires": { + "regexp-tree": "^0.1.6" + } }, "@babel/plugin-transform-new-target": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-object-super": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5" + } }, "@babel/plugin-transform-parameters": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.4.4", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-property-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-regenerator": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", - "dev": true + "dev": true, + "requires": { + "regenerator-transform": "^0.14.0" + } }, "@babel/plugin-transform-reserved-words": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-shorthand-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-spread": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-sticky-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } }, "@babel/plugin-transform-template-literals": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-typeof-symbol": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-unicode-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } }, "@babel/preset-env": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-dynamic-import": "^7.5.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.5.5", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.5.0", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.5.5", + "@babel/plugin-transform-classes": "^7.5.5", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.5.0", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/plugin-transform-duplicate-keys": "^7.5.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.4.4", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-member-expression-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.5.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", + "@babel/plugin-transform-modules-systemjs": "^7.5.0", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", + "@babel/plugin-transform-new-target": "^7.4.4", + "@babel/plugin-transform-object-super": "^7.5.5", + "@babel/plugin-transform-parameters": "^7.4.4", + "@babel/plugin-transform-property-literals": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.4.5", + "@babel/plugin-transform-reserved-words": "^7.2.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.4.4", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.4.4", + "@babel/types": "^7.5.5", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.5.0" + } }, "@babel/template": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } }, "@babel/traverse": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", - "dev": true + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } }, "@babel/types": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } }, "@gulp-sourcemaps/identity-map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", "dev": true, + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "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 + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } }, "source-map": { "version": "0.6.1", @@ -454,12 +815,19 @@ "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 + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -469,23 +837,14 @@ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", "dev": true }, - "@sinonjs/commons": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", - "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", - "dev": true - }, "@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 - }, - "@sinonjs/samsam": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", - "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", - "dev": true + "dev": true, + "requires": { + "samsam": "1.3.0" + } }, "@sinonjs/text-encoding": { "version": "0.7.1", @@ -493,6 +852,16 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "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" + } + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -503,7 +872,11 @@ "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } }, "acorn": { "version": "5.7.3", @@ -516,6 +889,9 @@ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", "dev": true, + "requires": { + "acorn": "^4.0.3" + }, "dependencies": { "acorn": { "version": "4.0.13", @@ -530,6 +906,9 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, + "requires": { + "acorn": "^3.0.4" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -555,13 +934,22 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true + "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", @@ -574,12 +962,20 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -605,7 +1001,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-html": { "version": "0.0.7", @@ -616,14 +1015,16 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "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 + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "ansi-wrap": { "version": "0.1.0", @@ -636,12 +1037,19 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -649,25 +1057,44 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } }, "append-transform": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", "dev": true, + "requires": { + "archiver-utils": "^1.3.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^1.2.0" + }, "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 + "dev": true, + "requires": { + "lodash": "^4.17.14" + } } } }, @@ -676,12 +1103,23 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", "dev": true, + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash": "^4.8.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, "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 + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -695,7 +1133,10 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } }, "arr-diff": { "version": "4.0.0", @@ -707,7 +1148,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } }, "arr-flatten": { "version": "1.1.0", @@ -719,7 +1163,10 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } }, "arr-union": { "version": "3.1.0", @@ -757,23 +1204,25 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, "array-includes": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -788,6 +1237,9 @@ "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", "dev": true, + "requires": { + "is-number": "^4.0.0" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -820,6 +1272,11 @@ "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -851,25 +1308,36 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, + "requires": { + "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 + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" }, "util": { "version": "0.10.3", @@ -907,7 +1375,13 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } }, "async-each": { "version": "1.0.3", @@ -925,7 +1399,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true + "dev": true, + "requires": { + "async-done": "^1.2.2" + } }, "asynckit": { "version": "0.4.0", @@ -956,6 +1433,11 @@ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -967,7 +1449,14 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "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" + } }, "js-tokens": { "version": "3.0.2", @@ -988,12 +1477,36 @@ "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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "json5": { "version": "0.5.1", @@ -1014,6 +1527,16 @@ "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": { "jsesc": { "version": "1.3.0", @@ -1027,115 +1550,211 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-builder-react-jsx": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } }, "babel-helper-call-delegate": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-define-map": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-helper-explode-assignable-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-explode-class": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-get-function-arity": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-hoist-variables": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-regex": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-helper-remap-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helpers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-loader": { "version": "8.0.6", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", - "dev": true + "dev": true, + "requires": { + "find-cache-dir": "^2.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "pify": "^4.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 + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-check-es2015-constants": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-dynamic-import-node": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", @@ -1225,181 +1844,323 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0" + } }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-generators": "^6.5.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-class-constructor-call": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "^6.18.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-class-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-decorators": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true + "dev": true, + "requires": { + "babel-helper-explode-class": "^6.24.1", + "babel-plugin-syntax-decorators": "^6.13.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-decorators-legacy": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-decorators": "^6.1.18", + "babel-runtime": "^6.2.0", + "babel-template": "^6.3.0" + } }, "babel-plugin-transform-do-expressions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-block-scoping": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-plugin-transform-es2015-classes": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-computed-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-destructuring": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-duplicate-keys": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-for-of": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-modules-amd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } }, "babel-plugin-transform-es2015-modules-systemjs": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-modules-umd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-parameters": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-shorthand-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-spread": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-sticky-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-template-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-typeof-symbol": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-unicode-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -1411,7 +2172,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } }, "regjsgen": { "version": "0.2.0", @@ -1423,7 +2189,10 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } } } }, @@ -1431,72 +2200,120 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-export-extensions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-flow-strip-types": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-function-bind": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "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=" + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx-source": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-regenerator": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + }, "dependencies": { "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } } } }, @@ -1504,19 +2321,59 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + }, "dependencies": { "browserslist": { "version": "3.2.8", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } } } }, @@ -1524,66 +2381,134 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "^6.22.0" + } }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.3.13", + "babel-plugin-transform-react-display-name": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "babel-plugin-transform-react-jsx-self": "^6.22.0", + "babel-plugin-transform-react-jsx-source": "^6.22.0", + "babel-preset-flow": "^6.23.0" + } }, "babel-preset-stage-0": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-do-expressions": "^6.22.0", + "babel-plugin-transform-function-bind": "^6.22.0", + "babel-preset-stage-1": "^6.24.1" + } }, "babel-preset-stage-1": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-class-constructor-call": "^6.24.1", + "babel-plugin-transform-export-extensions": "^6.22.0", + "babel-preset-stage-2": "^6.24.1" + } }, "babel-preset-stage-2": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-decorators": "^6.24.1", + "babel-preset-stage-3": "^6.24.1" + } }, "babel-preset-stage-3": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-plugin-transform-exponentiation-operator": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^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 + "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" + } }, "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=" + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } }, "babel-template": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true + "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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "globals": { "version": "9.18.0", @@ -1604,6 +2529,12 @@ "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", @@ -1629,7 +2560,18 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true + "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" + } }, "backo2": { "version": "1.0.2", @@ -1654,30 +2596,53 @@ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "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" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -1709,7 +2674,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } }, "beeper": { "version": "1.1.1", @@ -1721,13 +2689,22 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true + "dev": true, + "requires": { + "callsite": "1.0.0" + } }, "bfj": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", - "dev": true + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } }, "big.js": { "version": "5.2.2", @@ -1751,7 +2728,11 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } }, "blob": { "version": "0.0.5", @@ -1775,13 +2756,31 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true + "dev": true, + "requires": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, "dependencies": { "bytes": { "version": "3.1.0", @@ -1799,7 +2798,14 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } }, "inherits": { "version": "2.0.3", @@ -1810,8 +2816,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "qs": { "version": "6.7.0", @@ -1823,7 +2828,13 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } }, "setprototypeof": { "version": "1.1.1", @@ -1837,19 +2848,38 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "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 + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -1864,6 +2894,9 @@ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, + "requires": { + "resolve": "1.1.7" + }, "dependencies": { "resolve": { "version": "1.1.7", @@ -1883,67 +2916,124 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "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 + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "browserify-rsa": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } }, "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 + "dev": true, + "requires": { + "pako": "~1.0.5" + } }, "browserslist": { "version": "4.6.6", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", - "dev": true + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000984", + "electron-to-chromium": "^1.3.191", + "node-releases": "^1.1.25" + } }, "browserstack": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", - "dev": true + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + } }, "browserstack-local": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.2.tgz", "integrity": "sha512-fRaynjF0MvtyyfPRy2NFnVwxLyNtD28K/v9xRsIjUVf7xLc80NIm7Nfr3KXlFmWizhG91PL/UAOXlHkoxQjaNw==", - "dev": true + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1", + "is-running": "^2.0.0", + "ps-tree": "=1.1.1", + "temp-fs": "^0.9.9" + } }, "buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } }, "buffer-alloc-unsafe": { "version": "1.1.0", @@ -2003,13 +3093,33 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true + "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" + } }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", "dev": true, + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, "dependencies": { "lowercase-keys": { "version": "1.0.0", @@ -2021,7 +3131,12 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true + "dev": true, + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } }, "prepend-http": { "version": "2.0.0", @@ -2033,13 +3148,21 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } }, "sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } } } }, @@ -2047,7 +3170,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true + "dev": true, + "requires": { + "callsites": "^0.2.0" + } }, "callsite": { "version": "1.0.0", @@ -2072,6 +3198,10 @@ "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" + }, "dependencies": { "camelcase": { "version": "2.1.1", @@ -2103,19 +3233,36 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } }, "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 + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "character-entities": { "version": "1.2.3", @@ -2163,13 +3310,31 @@ "version": "2.1.6", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", - "dev": true + "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" + } }, "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 + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "circular-json": { "version": "0.3.3", @@ -2182,12 +3347,21 @@ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "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" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, @@ -2195,7 +3369,10 @@ "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 + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } }, "cli-width": { "version": "2.2.0", @@ -2208,6 +3385,11 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -2219,7 +3401,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -2239,7 +3424,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, "clone-stats": { "version": "1.0.0", @@ -2251,7 +3439,12 @@ "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 + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } }, "co": { "version": "4.6.0", @@ -2262,8 +3455,7 @@ "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 + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "collapse-white-space": { "version": "1.0.5", @@ -2275,19 +3467,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "color-name": "1.1.3" + } }, "color-name": { "version": "1.1.3", @@ -2311,13 +3515,19 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.5.0" + } }, "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 + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } }, "comma-separated-tokens": { "version": "1.0.7", @@ -2360,12 +3570,21 @@ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", "dev": true, + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, "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 + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -2379,13 +3598,22 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } }, "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, + "requires": { + "source-map": "^0.6.1" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -2400,6 +3628,12 @@ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, "dependencies": { "debug": { "version": "2.6.9", @@ -2410,8 +3644,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -2425,7 +3658,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true + "dev": true, + "requires": { + "date-now": "^0.1.4" + } }, "constants-browserify": { "version": "1.0.0", @@ -2443,7 +3679,10 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } }, "content-type": { "version": "1.0.4", @@ -2461,7 +3700,10 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } }, "cookie": { "version": "0.3.1", @@ -2485,7 +3727,11 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } }, "core-js": { "version": "2.6.9", @@ -2497,6 +3743,11 @@ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", "dev": true, + "requires": { + "browserslist": "^4.6.2", + "core-js-pure": "3.1.4", + "semver": "^6.1.1" + }, "dependencies": { "semver": { "version": "6.3.0", @@ -2522,49 +3773,103 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", - "dev": true + "dev": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.13.1", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.86.0" + } }, "crc": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true + "dev": true, + "requires": { + "buffer": "^5.1.0" + } }, "crc32-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", - "dev": true + "dev": true, + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } }, "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 + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "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 + "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" + } }, "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 + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } }, "crypto-js": { "version": "3.1.9-1", @@ -2576,6 +3881,12 @@ "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -2589,7 +3900,10 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true + "dev": true, + "requires": { + "css": "^2.0.0" + } }, "css-value": { "version": "0.0.1", @@ -2601,7 +3915,10 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } }, "custom-event": { "version": "1.0.1", @@ -2613,13 +3930,20 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } }, "date-format": { "version": "1.2.0", @@ -2637,25 +3961,40 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "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, + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -2675,13 +4014,19 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } }, "deep-is": { "version": "0.1.3", @@ -2700,6 +4045,9 @@ "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -2714,12 +4062,18 @@ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, + "requires": { + "strip-bom": "^2.0.0" + }, "dependencies": { "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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } } } }, @@ -2733,31 +4087,49 @@ "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 + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } }, "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, + "requires": { + "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -2783,7 +4155,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "destroy": { "version": "1.0.4", @@ -2795,7 +4171,10 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.2.tgz", "integrity": "sha512-Q57yPrxScy816TTE1P/uLRXLDKjXhvYTbfxS/e6lPD+YrqghbsMlGB9nQzj/zVtSPaF0DFPSdO916EWO4sQUyQ==", - "dev": true + "dev": true, + "requires": { + "repeat-string": "^1.5.4" + } }, "detect-file": { "version": "1.0.0", @@ -2807,7 +4186,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "detect-libc": { "version": "1.0.3", @@ -2825,7 +4207,11 @@ "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } }, "di": { "version": "0.0.1", @@ -2843,13 +4229,22 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } }, "disparity": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", "dev": true, + "requires": { + "ansi-styles": "^2.0.1", + "diff": "^1.3.2" + }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -2868,19 +4263,78 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } }, "doctrine-temporary-fork": { "version": "2.0.0-alpha-allowarrayindex", "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } }, "documentation": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", "dev": true, + "requires": { + "ansi-html": "^0.0.7", + "babel-core": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-plugin-system-import-transformer": "3.1.0", + "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-preset-env": "^1.6.1", + "babel-preset-react": "^6.24.1", + "babel-preset-stage-0": "^6.24.1", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babelify": "^8.0.0", + "babylon": "^6.18.0", + "chalk": "^2.3.0", + "chokidar": "^2.0.0", + "concat-stream": "^1.6.0", + "disparity": "^2.0.0", + "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", + "get-port": "^3.2.0", + "git-url-parse": "^8.0.0", + "github-slugger": "1.2.0", + "glob": "^7.1.2", + "globals-docs": "^2.4.0", + "highlight.js": "^9.12.0", + "js-yaml": "^3.10.0", + "lodash": "^4.17.4", + "mdast-util-inject": "^1.1.0", + "micromatch": "^3.1.5", + "mime": "^1.4.1", + "module-deps-sortable": "4.0.6", + "parse-filepath": "^1.0.2", + "pify": "^3.0.0", + "read-pkg-up": "^3.0.0", + "remark": "^9.0.0", + "remark-html": "7.0.0", + "remark-reference-links": "^4.0.1", + "remark-toc": "^5.0.0", + "remote-origin-url": "0.4.0", + "shelljs": "^0.8.1", + "stream-array": "^1.1.2", + "strip-json-comments": "^2.0.1", + "tiny-lr": "^1.1.0", + "unist-builder": "^1.0.2", + "unist-util-visit": "^1.3.0", + "vfile": "^2.3.0", + "vfile-reporter": "^4.0.0", + "vfile-sort": "^2.1.0", + "vinyl": "^2.1.0", + "vinyl-fs": "^3.0.2", + "yargs": "^9.0.1" + }, "dependencies": { "camelcase": { "version": "4.1.0", @@ -2893,12 +4347,22 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, "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 + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } } } }, @@ -2906,19 +4370,36 @@ "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 + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, "get-caller-file": { "version": "1.0.3", @@ -2936,19 +4417,31 @@ "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 + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } }, "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.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", @@ -2962,19 +4455,30 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "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 + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "mimic-fn": { "version": "1.2.0", @@ -2986,19 +4490,30 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true + "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 + "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 + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } }, "p-try": { "version": "1.0.0", @@ -3010,13 +4525,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "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.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", @@ -3036,7 +4557,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } }, "require-main-filename": { "version": "1.0.1", @@ -3061,12 +4587,31 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.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.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, "dependencies": { "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } } } }, @@ -3074,7 +4619,10 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, @@ -3082,7 +4630,13 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } }, "domain-browser": { "version": "1.2.0", @@ -3105,7 +4659,10 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } }, "duplexer3": { "version": "0.1.4", @@ -3117,19 +4674,33 @@ "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } }, "editions": { "version": "1.3.4", @@ -3159,7 +4730,16 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } }, "emoji-regex": { "version": "7.0.3", @@ -3183,19 +4763,33 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true + "dev": true, + "requires": { + "once": "^1.4.0" + } }, "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -3210,6 +4804,19 @@ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -3221,7 +4828,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -3235,13 +4845,26 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } }, "enhanced-resolve": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.7" + } }, "ent": { "version": "2.2.0", @@ -3253,37 +4876,65 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true + "dev": true, + "requires": { + "prr": "~1.0.1" + } }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true + "dev": true, + "requires": { + "string-template": "~0.2.1", + "xtend": "~4.0.0" + } }, "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 + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } }, "es-abstract": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } }, "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } }, "es5-ext": { "version": "0.10.50", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", - "dev": true + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "^1.0.0" + } }, "es5-shim": { "version": "4.5.13", @@ -3295,13 +4946,26 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } }, "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 + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-promise": { "version": "4.2.8", @@ -3313,25 +4977,45 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "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 + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } }, "escape-html": { "version": "1.0.3", @@ -3350,6 +5034,13 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + }, "dependencies": { "esprima": { "version": "2.7.3", @@ -3368,7 +5059,10 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, - "optional": true + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -3376,13 +5070,59 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "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", + "table": "4.0.2", + "text-table": "~0.2.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -3394,31 +5134,49 @@ "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 + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.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 + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.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 + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "yallist": { "version": "2.1.2", @@ -3439,12 +5197,19 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.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 + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -3459,6 +5224,10 @@ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + }, "dependencies": { "debug": { "version": "2.6.9", @@ -3469,38 +5238,32 @@ "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "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 + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=" }, "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 + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "pkg-dir": { "version": "2.0.0", @@ -3515,6 +5278,19 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", "dev": true, + "requires": { + "array-includes": "^3.0.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.11.0" + }, "dependencies": { "debug": { "version": "2.6.9", @@ -3525,68 +5301,57 @@ "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" }, "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 + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=" }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "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 + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=" }, "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 + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=" }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=" }, "read-pkg-up": { "version": "2.0.0", @@ -3601,6 +5366,12 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "5.3.0" + }, "dependencies": { "semver": { "version": "5.3.0", @@ -3630,7 +5401,11 @@ "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 + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint-visitor-keys": { "version": "1.0.0", @@ -3642,7 +5417,11 @@ "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } }, "esprima": { "version": "4.0.1", @@ -3654,13 +5433,19 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } }, "estraverse": { "version": "4.2.0", @@ -3684,13 +5469,26 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "event-stream": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, + "requires": { + "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" + }, "dependencies": { "map-stream": { "version": "0.1.0", @@ -3716,19 +5514,35 @@ "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 + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, "dependencies": { "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 + "dev": true, + "requires": { + "pump": "^3.0.0" + } } } }, @@ -3737,6 +5551,11 @@ "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, "dependencies": { "array-slice": { "version": "0.2.3", @@ -3754,7 +5573,10 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } } } }, @@ -3763,24 +5585,42 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "ms": { "version": "2.0.0", @@ -3795,6 +5635,10 @@ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + }, "dependencies": { "is-number": { "version": "0.1.1", @@ -3814,13 +5658,48 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "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", + "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.5", + "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": { "cookie": { "version": "0.4.0", @@ -3832,13 +5711,23 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "http-errors": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } }, "ms": { "version": "2.0.0", @@ -3863,6 +5752,21 @@ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "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", + "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", @@ -3891,12 +5795,19 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, + "requires": { + "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 + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -3904,43 +5815,75 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } }, "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.0", + "snapdragon": "^0.8.1", + "to-regex": "^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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -3960,7 +5903,13 @@ "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 + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } }, "fast-deep-equal": { "version": "1.1.0", @@ -3984,25 +5933,38 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } }, "fibers": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fibers/-/fibers-3.1.1.tgz", "integrity": "sha512-dl3Ukt08rHVQfY8xGD0ODwyjwrRALtaghuqGH2jByYX1wpY+nAnRQjJ6Dbqq0DnVgNVQ9yibObzbF4IlPyiwPw==", - "dev": true + "dev": true, + "requires": { + "detect-libc": "^1.0.3" + } }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } }, "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 + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } }, "filename-regex": { "version": "2.0.1", @@ -4014,7 +5976,11 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } }, "filesize": { "version": "3.6.1", @@ -4027,12 +5993,21 @@ "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 + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -4041,6 +6016,15 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, + "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" + }, "dependencies": { "debug": { "version": "2.6.9", @@ -4051,8 +6035,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -4060,25 +6043,46 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true + "dev": true, + "requires": { + "locate-path": "^3.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 + "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 + "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" + } }, "flagged-respawn": { "version": "1.0.1", @@ -4091,6 +6095,9 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, "dependencies": { "is-buffer": { "version": "2.0.3", @@ -4105,12 +6112,21 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", "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" + }, "dependencies": { "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -4124,19 +6140,29 @@ "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 + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } }, "follow-redirects": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, + "requires": { + "debug": "^3.2.6" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -4150,7 +6176,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true + "dev": true, + "requires": { + "for-in": "^1.0.1" + } }, "foreachasync": { "version": "3.0.0", @@ -4174,7 +6203,12 @@ "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 + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } }, "forwarded": { "version": "0.1.2", @@ -4186,7 +6220,10 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } }, "fresh": { "version": "0.5.2", @@ -4204,13 +6241,20 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } }, "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 + "dev": true, + "requires": { + "null-check": "^1.0.0" + } }, "fs-constants": { "version": "1.0.0", @@ -4223,6 +6267,12 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, + "requires": { + "jsonfile": "~1.0.1", + "mkdirp": "0.3.x", + "ncp": "~0.4.2", + "rimraf": "~2.2.0" + }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -4236,13 +6286,22 @@ "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } }, "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, + "requires": { + "fs-extra": "~0.6.1", + "mkdirp": "~0.3.5", + "walk": "^2.3.9" + }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -4264,6 +6323,10 @@ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, "dependencies": { "abbrev": { "version": "1.1.1", @@ -4274,7 +6337,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4286,17 +6350,27 @@ "version": "1.1.5", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } }, "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "chownr": { "version": "1.1.1", @@ -4307,17 +6381,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4329,7 +6406,10 @@ "version": "4.1.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ms": "^2.1.1" + } }, "deep-extend": { "version": "0.6.0", @@ -4353,7 +6433,10 @@ "version": "1.2.5", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minipass": "^2.2.1" + } }, "fs.realpath": { "version": "1.0.0", @@ -4365,13 +6448,31 @@ "version": "2.7.4", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } }, "glob": { "version": "7.1.3", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-unicode": { "version": "2.0.1", @@ -4383,24 +6484,35 @@ "version": "0.4.24", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ignore-walk": { "version": "3.0.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } }, "inflight": { "version": "1.0.6", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4411,7 +6523,11 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "isarray": { "version": "1.0.0", @@ -4422,28 +6538,45 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } }, "minizlib": { "version": "1.2.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minipass": "^2.2.1" + } }, "mkdirp": { "version": "0.5.1", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } }, "ms": { "version": "2.1.1", @@ -4455,19 +6588,40 @@ "version": "2.3.0", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } }, "node-pre-gyp": { "version": "0.12.0", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } }, "nopt": { "version": "4.0.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } }, "npm-bundled": { "version": "1.0.6", @@ -4479,18 +6633,29 @@ "version": "1.4.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } }, "npmlog": { "version": "4.1.2", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } }, "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4501,7 +6666,11 @@ "once": { "version": "1.4.0", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } }, "os-homedir": { "version": "1.0.2", @@ -4519,7 +6688,11 @@ "version": "0.1.5", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "path-is-absolute": { "version": "1.0.1", @@ -4538,6 +6711,12 @@ "bundled": true, "dev": true, "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -4551,18 +6730,31 @@ "version": "2.3.6", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, "rimraf": { "version": "2.6.3", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "glob": "^7.1.3" + } }, "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4594,21 +6786,34 @@ "dev": true, "optional": true }, - "string_decoder": { - "version": "1.1.1", + "string-width": { + "version": "1.0.2", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, - "string-width": { - "version": "1.0.2", + "string_decoder": { + "version": "1.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, "strip-ansi": { "version": "3.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, "strip-json-comments": { "version": "2.0.1", @@ -4620,7 +6825,16 @@ "version": "4.4.8", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } }, "util-deprecate": { "version": "1.0.2", @@ -4632,17 +6846,22 @@ "version": "1.1.3", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } }, "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -4667,7 +6886,10 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true + "dev": true, + "requires": { + "globule": "^1.0.0" + } }, "get-caller-file": { "version": "2.0.5", @@ -4709,25 +6931,39 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } }, "git-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.1.0.tgz", "integrity": "sha512-MJgwfcSd9qxgDyEYpRU/CDxNpUadrK80JHuEQDG4Urn0m7tpSOgCBrtiSIa9S9KH8Tbuo/TN8SSQmJBvsw1HkA==", - "dev": true + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "parse-url": "^3.0.2" + } }, "git-url-parse": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true + "dev": true, + "requires": { + "git-up": "^2.0.0", + "parse-domain": "^2.0.0" + } }, "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, + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + }, "dependencies": { "emoji-regex": { "version": "6.1.1", @@ -4741,19 +6977,34 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true + "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-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, "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 + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } }, "is-extglob": { "version": "1.0.0", @@ -4765,7 +7016,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } } } }, @@ -4774,12 +7028,19 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } } } }, @@ -4787,25 +7048,57 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true + "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" + } }, "glob-watcher": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", - "dev": true + "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", + "object.defaults": "^1.1.0" + } }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } }, "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 + "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" + } }, "globals": { "version": "11.12.0", @@ -4823,19 +7116,46 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "dev": true + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } }, "glogg": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", "dev": true, + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, "dependencies": { "pify": { "version": "3.0.0", @@ -4868,138 +7188,163 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", "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" + }, "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 + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=" }, "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 + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" }, "gulp-cli": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", - "dev": true + "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.1.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.0.1", + "yargs": "^7.1.0" + } }, "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 + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "requires": { + "number-is-nan": "^1.0.0" + } }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true + "requires": { + "invert-kv": "^1.0.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=", - "dev": true + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=" }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=" }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" }, "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 + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=" }, "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 + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=" }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "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 + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=" }, "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 + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=" }, "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 + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" }, "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 + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, "y18n": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yargs": { "version": "7.1.0", @@ -5010,8 +7355,7 @@ "yargs-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=" } } }, @@ -5020,6 +7364,11 @@ "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" + }, "dependencies": { "ansi-regex": { "version": "0.2.1", @@ -5037,7 +7386,14 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true + "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", @@ -5050,12 +7406,26 @@ "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 + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } } } }, @@ -5063,7 +7433,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^0.2.0" + } }, "isarray": { "version": "0.0.1", @@ -5087,7 +7460,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -5099,7 +7478,10 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^0.2.1" + } }, "supports-color": { "version": "0.2.0", @@ -5112,12 +7494,19 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~2.1.1" + }, "dependencies": { "xtend": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true + "dev": true, + "requires": { + "object-keys": "~0.4.0" + } } } }, @@ -5125,7 +7514,10 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true + "dev": true, + "requires": { + "clone-stats": "~0.0.1" + } }, "xtend": { "version": "3.0.0", @@ -5139,13 +7531,29 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + } }, "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, + "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" + }, "dependencies": { "ansi-colors": { "version": "2.0.5", @@ -5159,11 +7567,24 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", - "dev": true + "dev": true, + "requires": { + "eslint": "^4.0.0", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.0" + } }, "gulp-footer": { "version": "github:prebid/gulp-footer#ff2b46e6376c7f04900357ff9f7b30f219fe5f8a", + "from": "github:prebid/gulp-footer#master", "dev": true, + "requires": { + "event-stream": "3.3.4", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.6.2" + }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -5175,25 +7596,48 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true + "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.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } } } }, @@ -5202,6 +7646,11 @@ "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, + "requires": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -5213,13 +7662,20 @@ "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 + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.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 + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } } } }, @@ -5227,13 +7683,21 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true + "dev": true, + "requires": { + "gulp-match": "^1.0.3", + "ternary-stream": "^2.0.1", + "through2": "^2.0.1" + } }, "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, + "requires": { + "through2": "^0.6.3" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -5245,7 +7709,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -5257,7 +7727,11 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } } } }, @@ -5265,25 +7739,52 @@ "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 + "dev": true, + "requires": { + "minimatch": "^3.0.3" + } }, "gulp-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", - "dev": true + "dev": true, + "requires": { + "istextorbinary": "2.2.1", + "readable-stream": "^2.0.1", + "replacestream": "^4.0.0" + } }, "gulp-shell": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true + "dev": true, + "requires": { + "async": "^1.5.0", + "gulp-util": "^3.0.7", + "lodash": "^4.0.0", + "through2": "^2.0.0" + } }, "gulp-sourcemaps": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.5.tgz", "integrity": "sha512-SYLBRzPTew8T5Suh2U8jCSDKY+4NARua4aqjj8HOysBh2tSgT9u4jc1FYirAdPx1akUxxDeK++fqw6Jg0LkQRg==", "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -5297,13 +7798,45 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", - "dev": true + "dev": true, + "requires": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + } }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "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", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -5315,7 +7848,14 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "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" + } }, "clone": { "version": "1.0.4", @@ -5345,25 +7885,48 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true + "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.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } }, "object-assign": { "version": "3.0.0", @@ -5387,7 +7950,12 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } } } }, @@ -5395,19 +7963,32 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true + "dev": true, + "requires": { + "glogg": "^1.0.0" + } }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", - "dev": true + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + } }, "handlebars": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -5428,12 +8009,22 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, "dependencies": { "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } }, "fast-deep-equal": { "version": "2.0.1", @@ -5453,19 +8044,28 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, + "requires": { + "isarray": "2.0.1" + }, "dependencies": { "isarray": { "version": "2.0.1", @@ -5491,7 +8091,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "has-symbol-support-x": { "version": "1.4.2", @@ -5509,25 +8112,40 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } }, "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, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5535,13 +8153,21 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "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 + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } }, "hast-util-is-element": { "version": "1.0.3", @@ -5553,13 +8179,29 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.1.tgz", "integrity": "sha512-AIeKHuHx0Wk45nSkGVa2/ujQYTksnDl8gmmKo/mwQi7ag7IBZ8cM3nJ2G86SajbjGP/HRpud6kMkPtcM2i0Tlw==", - "dev": true + "dev": true, + "requires": { + "xtend": "^4.0.1" + } }, "hast-util-to-html": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", "dev": true, + "requires": { + "ccount": "^1.0.0", + "comma-separated-tokens": "^1.0.1", + "hast-util-is-element": "^1.0.0", + "hast-util-whitespace": "^1.0.0", + "html-void-elements": "^1.0.0", + "kebab-case": "^1.0.0", + "property-information": "^3.1.0", + "space-separated-tokens": "^1.0.0", + "stringify-entities": "^1.0.1", + "unist-util-is": "^2.0.0", + "xtend": "^4.0.1" + }, "dependencies": { "unist-util-is": { "version": "2.1.3", @@ -5591,19 +8233,31 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } }, "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 + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } }, "hoopy": { "version": "0.1.4", @@ -5615,7 +8269,10 @@ "version": "2.8.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.2.tgz", "integrity": "sha512-CyjlXII6LMsPMyUzxpTt8fzh5QwzGqPmQXgY/Jyf4Zfp27t/FvfhwoE/8laaMUcMy816CkWF20I7NeQhwwY88w==", - "dev": true + "dev": true, + "requires": { + "lru-cache": "^5.1.1" + } }, "html-void-elements": { "version": "1.0.4", @@ -5634,6 +8291,12 @@ "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" + }, "dependencies": { "inherits": { "version": "2.0.3", @@ -5653,13 +8316,23 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } }, "https-browserify": { "version": "1.0.0", @@ -5672,6 +8345,10 @@ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, "dependencies": { "debug": { "version": "3.2.6", @@ -5691,7 +8368,10 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ieee754": { "version": "1.1.13", @@ -5715,7 +8395,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "indexof": { "version": "0.0.1", @@ -5727,7 +8410,11 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.4", @@ -5746,6 +8433,22 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "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", + "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" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -5757,7 +8460,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -5771,13 +8477,20 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true + "dev": true, + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } }, "invert-kv": { "version": "2.0.0", @@ -5795,19 +8508,29 @@ "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 + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.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.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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5827,7 +8550,11 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", - "dev": true + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -5839,7 +8566,10 @@ "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 + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } }, "is-buffer": { "version": "1.1.6", @@ -5858,12 +8588,18 @@ "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5884,6 +8620,11 @@ "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", @@ -5909,7 +8650,10 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } }, "is-extendable": { "version": "0.1.1", @@ -5927,7 +8671,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -5939,7 +8686,10 @@ "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 + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } }, "is-hexadecimal": { "version": "1.0.3", @@ -5958,12 +8708,18 @@ "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": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5983,7 +8739,10 @@ "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 + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "is-posix-bracket": { "version": "0.1.1", @@ -6007,13 +8766,19 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true + "dev": true, + "requires": { + "has": "^1.0.1" + } }, "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 + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } }, "is-resolvable": { "version": "1.1.0", @@ -6037,7 +8802,10 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", - "dev": true + "dev": true, + "requires": { + "protocols": "^1.1.0" + } }, "is-stream": { "version": "1.1.0", @@ -6049,7 +8817,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } }, "is-typedarray": { "version": "1.0.0", @@ -6061,7 +8832,10 @@ "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 + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } }, "is-utf8": { "version": "0.2.1", @@ -6109,7 +8883,10 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } }, "isexe": { "version": "2.0.0", @@ -6134,6 +8911,22 @@ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, "dependencies": { "esprima": { "version": "2.7.3", @@ -6145,7 +8938,14 @@ "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-flag": { "version": "1.0.0", @@ -6163,7 +8963,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } } } }, @@ -6172,12 +8975,28 @@ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", "dev": true, + "requires": { + "async": "^2.1.4", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + }, "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 + "dev": true, + "requires": { + "lodash": "^4.17.14" + } } } }, @@ -6185,7 +9004,13 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" + } }, "istanbul-lib-coverage": { "version": "1.2.1", @@ -6197,19 +9022,37 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", - "dev": true + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } }, "istanbul-lib-instrument": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } }, "istanbul-lib-report": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, "dependencies": { "has-flag": { "version": "1.0.0", @@ -6221,7 +9064,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } } } }, @@ -6230,18 +9076,31 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -6249,19 +9108,31 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", - "dev": true + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } }, "istextorbinary": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "dev": true + "dev": true, + "requires": { + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" + } }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } }, "js-levenshtein": { "version": "1.1.6", @@ -6279,7 +9150,11 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } }, "jsbn": { "version": "0.1.1", @@ -6344,7 +9219,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true + "dev": true, + "requires": { + "minimist": "^1.2.0" + } }, "jsonfile": { "version": "1.0.1", @@ -6358,23 +9236,23 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "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==", + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } }, "just-clone": { "version": "1.0.2", @@ -6398,6 +9276,36 @@ "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.5", + "log4js": "^3.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + }, "dependencies": { "mime": { "version": "2.4.4", @@ -6409,7 +9317,10 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.1.3" + } }, "source-map": { "version": "0.6.1", @@ -6423,13 +9334,21 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true + "dev": true, + "requires": { + "babel-core": "^6.0.0" + } }, "karma-browserstack-launcher": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.5.1.tgz", "integrity": "sha512-zt9Ukow5A9WZHZXCFVO/h5kRsAdaZYeMNJK9Uan8v42amQXt3B/DZVxl24NCcAIxufKjW13UWd9iJ9knG9OCYw==", - "dev": true + "dev": true, + "requires": { + "browserstack": "~1.5.1", + "browserstack-local": "^1.3.7", + "q": "~1.5.0" + } }, "karma-chai": { "version": "0.1.0", @@ -6441,19 +9360,30 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true + "dev": true, + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } }, "karma-coverage-istanbul-reporter": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", - "dev": true + "dev": true, + "requires": { + "istanbul-api": "^1.3.1", + "minimatch": "^3.0.4" + } }, "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 + "dev": true, + "requires": { + "es5-shim": "^4.0.5" + } }, "karma-firefox-launcher": { "version": "1.1.0", @@ -6465,19 +9395,30 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.6.1" + } }, "karma-mocha": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true + "dev": true, + "requires": { + "minimist": "1.2.0" + } }, "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, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "strip-ansi": "^4.0.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -6489,7 +9430,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -6521,25 +9465,42 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + } }, "karma-spec-reporter": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true + "dev": true, + "requires": { + "colors": "^1.1.2" + } }, "karma-webpack": { "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": { + "async": "^2.0.0", + "babel-runtime": "^6.0.0", + "loader-utils": "^1.0.0", + "lodash": "^4.0.0", + "source-map": "^0.5.6", + "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 + "dev": true, + "requires": { + "lodash": "^4.17.14" + } } } }, @@ -6553,7 +9514,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } }, "kind-of": { "version": "6.0.2", @@ -6565,7 +9529,11 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } }, "lazy-cache": { "version": "1.0.4", @@ -6577,13 +9545,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } }, "lcov-parse": { "version": "0.0.10", @@ -6595,19 +9569,36 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } }, "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true + "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" + } }, "livereload-js": { "version": "2.4.0", @@ -6620,6 +9611,12 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "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", @@ -6640,12 +9637,20 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.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 + "dev": true, + "requires": { + "minimist": "^1.2.0" + } } } }, @@ -6653,7 +9658,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } }, "lodash": { "version": "4.17.15", @@ -6683,7 +9692,10 @@ "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 + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1" + } }, "lodash._escapestringchar": { "version": "2.4.1", @@ -6743,7 +9755,11 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash._root": { "version": "3.0.1", @@ -6755,7 +9771,10 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } }, "lodash.clone": { "version": "4.5.0", @@ -6767,13 +9786,22 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash.escape": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true + "dev": true, + "requires": { + "lodash._escapehtmlchar": "~2.4.1", + "lodash._reunescapedhtml": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash.get": { "version": "4.4.2", @@ -6797,13 +9825,21 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } }, "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 + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } }, "lodash.restparam": { "version": "3.6.1", @@ -6821,19 +9857,35 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true + "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 + "dev": true, + "requires": { + "lodash._reinterpolate": "~2.4.1", + "lodash.escape": "~2.4.1" + } }, "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 + "dev": true, + "requires": { + "lodash.keys": "~2.4.1" + } }, "log-driver": { "version": "1.2.7", @@ -6845,13 +9897,23 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true + "dev": true, + "requires": { + "chalk": "^2.0.1" + } }, "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, + "requires": { + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", + "streamroller": "0.7.0" + }, "dependencies": { "circular-json": { "version": "0.5.9", @@ -6863,7 +9925,10 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -6871,7 +9936,11 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", - "dev": true + "dev": true, + "requires": { + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" + } }, "lolex": { "version": "2.7.5", @@ -6895,13 +9964,20 @@ "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 + "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 + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } }, "lowercase-keys": { "version": "1.0.1", @@ -6913,19 +9989,29 @@ "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 + "dev": true, + "requires": { + "yallist": "^3.0.2" + } }, "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } }, "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 + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } }, "make-error": { "version": "1.3.5", @@ -6937,19 +10023,28 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true + "dev": true, + "requires": { + "make-error": "^1.2.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } }, "map-cache": { "version": "0.2.2", @@ -6973,7 +10068,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } }, "markdown-escapes": { "version": "1.0.3", @@ -6992,18 +10090,33 @@ "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, "dependencies": { "findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } }, "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } } } }, @@ -7017,31 +10130,58 @@ "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 + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "mdast-util-compact": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz", "integrity": "sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } }, "mdast-util-definitions": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.4.tgz", "integrity": "sha512-HfUArPog1j4Z78Xlzy9Q4aHLnrF/7fb57cooTHypyGoe2XFNbcx/kWZDoOz+ra8CkUzvg3+VHV434yqEd1DRmA==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.0" + } }, "mdast-util-to-hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.4.tgz", "integrity": "sha512-/eIbly2YmyVgpJNo+bFLLMCI1XgolO/Ffowhf+pHDq3X4/V6FntC9sGQCDLM147eTS+uSXv5dRzJyFn+o0tazA==", - "dev": true + "dev": true, + "requires": { + "collapse-white-space": "^1.0.0", + "detab": "^2.0.0", + "mdast-util-definitions": "^1.2.0", + "mdurl": "^1.0.1", + "trim": "0.0.1", + "trim-lines": "^1.0.0", + "unist-builder": "^1.0.1", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.0", + "xtend": "^4.0.1" + } }, "mdast-util-to-string": { "version": "1.0.6", @@ -7054,6 +10194,12 @@ "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-3.1.0.tgz", "integrity": "sha512-Za0hqL1PqWrvxGtA/3NH9D5nhGAUS9grMM4obEAz5+zsk1RIw/vWUchkaoDLNdrwk05A0CSC5eEXng36/1qE5w==", "dev": true, + "requires": { + "github-slugger": "^1.2.1", + "mdast-util-to-string": "^1.0.5", + "unist-util-is": "^2.1.2", + "unist-util-visit": "^1.1.0" + }, "dependencies": { "emoji-regex": { "version": "6.1.1", @@ -7065,7 +10211,10 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.1.tgz", "integrity": "sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ==", - "dev": true + "dev": true, + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + } }, "unist-util-is": { "version": "2.1.3", @@ -7092,6 +10241,11 @@ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, "dependencies": { "p-is-promise": { "version": "2.1.0", @@ -7105,13 +10259,27 @@ "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } }, "memory-fs": { "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 + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } }, "memorystream": { "version": "0.3.1", @@ -7124,36 +10292,70 @@ "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": { "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.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=", - "dev": true + "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" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "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 + "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -7165,19 +10367,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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 + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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 + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } } } }, @@ -7191,7 +10405,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } }, "methods": { "version": "1.1.2", @@ -7203,13 +10420,32 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true + "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" + } }, "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 + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } }, "mime": { "version": "1.6.0", @@ -7227,7 +10463,10 @@ "version": "2.1.24", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true + "dev": true, + "requires": { + "mime-db": "1.40.0" + } }, "mimic-fn": { "version": "2.1.0", @@ -7257,7 +10496,10 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "1.2.0", @@ -7270,6 +10512,10 @@ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, "dependencies": { "is-extendable": { "version": "1.0.1", @@ -7284,6 +10530,9 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, + "requires": { + "minimist": "0.0.8" + }, "dependencies": { "minimist": { "version": "0.0.8", @@ -7298,6 +10547,19 @@ "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, "dependencies": { "commander": { "version": "2.15.1", @@ -7309,7 +10571,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "diff": { "version": "3.5.0", @@ -7321,7 +10586,15 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true + "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" + } }, "he": { "version": "1.1.1", @@ -7339,7 +10612,10 @@ "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -7348,18 +10624,47 @@ "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "concat-stream": "~1.5.0", + "defined": "^1.0.0", + "detective": "^4.0.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.3", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, "dependencies": { "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + }, "dependencies": { "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true + "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" + } } } }, @@ -7388,12 +10693,18 @@ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, "dependencies": { "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } }, "isarray": { "version": "0.0.1", @@ -7405,7 +10716,13 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -7438,7 +10755,20 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true + "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" + } }, "natural-compare": { "version": "1.4.0", @@ -7481,6 +10811,13 @@ "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.1.tgz", "integrity": "sha512-edFWm0fsFG2n318rfEnKlTZTkjlbVOFF9XIA+fj+Ed+Qz1laYW2lobwavWoMzGrYDHH1EpiNJgDfvGnkZztR/g==", "dev": true, + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^4.1.0", + "path-to-regexp": "^1.7.0" + }, "dependencies": { "@sinonjs/formatio": { "version": "3.2.1", @@ -7500,19 +10837,53 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } }, "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.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, "dependencies": { "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } }, "punycode": { "version": "1.4.1", @@ -7526,19 +10897,31 @@ "version": "1.1.26", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", - "dev": true + "dev": true, + "requires": { + "semver": "^5.3.0" + } }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true + "dev": true, + "requires": { + "abbrev": "1" + } }, "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 + "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" + } }, "normalize-path": { "version": "3.0.0", @@ -7550,13 +10933,22 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "once": "^1.3.2" + } }, "npm-install-package": { "version": "2.1.0", @@ -7568,13 +10960,27 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + } }, "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 + "dev": true, + "requires": { + "path-key": "^2.0.0" + } }, "null-check": { "version": "1.0.0", @@ -7585,8 +10991,7 @@ "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 + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth-sign": { "version": "0.9.0", @@ -7611,18 +11016,29 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -7636,43 +11052,73 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.0" + } }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "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.4", + "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 + "dev": true, + "requires": { + "for-in": "^1.0.1" + } } } }, @@ -7680,37 +11126,59 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "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 + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "object.values": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true + "dev": true, + "requires": { + "ee-first": "1.1.1" + } }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + }, "dependencies": { "mimic-fn": { "version": "1.2.0", @@ -7730,13 +11198,20 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, "dependencies": { "minimist": { "version": "0.0.10", @@ -7756,13 +11231,24 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } }, "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 + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } }, "os-browserify": { "version": "0.3.0", @@ -7780,7 +11266,12 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } }, "os-tmpdir": { "version": "1.0.2", @@ -7816,19 +11307,28 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true + "dev": true, + "requires": { + "p-try": "^2.0.0" + } }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } }, "p-try": { "version": "2.2.0", @@ -7846,19 +11346,37 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } }, "parse-asn1": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", - "dev": true + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } }, "parse-domain": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.1.tgz", "integrity": "sha512-k/tkc7tfcoGfaUOCG5DuPNX+dt6UBqRWU9EtR0rA9esi5GpOY0OGEgprfylmYx8pykQbdBTYHLaM/UwFHXuZKA==", "dev": true, + "requires": { + "chai": "^4.2.0", + "got": "^8.3.2", + "mkdirp": "^0.5.1", + "mocha": "^6.1.4", + "npm-run-all": "^4.1.5" + }, "dependencies": { "ansi-regex": { "version": "4.1.0", @@ -7870,7 +11388,10 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "diff": { "version": "3.5.0", @@ -7882,13 +11403,46 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true + "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" + } }, "mocha": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", - "dev": true + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + } }, "ms": { "version": "2.1.1", @@ -7900,25 +11454,49 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } }, "supports-color": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "yargs": { "version": "13.2.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + } } } }, @@ -7926,25 +11504,47 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true + "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" + } }, "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 + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } }, "parse-git-config": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", - "dev": true + "dev": true, + "requires": { + "ini": "^1.3.3" + } }, "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.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, "dependencies": { "is-extglob": { "version": "1.0.0", @@ -7956,7 +11556,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } } } }, @@ -7964,7 +11567,11 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } }, "parse-node-version": { "version": "1.0.1", @@ -7982,25 +11589,41 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-3.0.4.tgz", "integrity": "sha512-wP70vtwv2DyrM2YoA7ZHVv4zIXa4P7dGgHlj+VwyXNDduLLVJ7NMY1zsFxjUUJ3DAwJLupGb1H5gMDDiNlJaxw==", - "dev": true + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } }, "parse-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-3.0.2.tgz", "integrity": "sha1-YCeHpwY6eV1yuGcxl1BecvYGEL4=", - "dev": true + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "normalize-url": "^1.9.1", + "parse-path": "^3.0.1", + "protocols": "^1.4.0" + } }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } }, "parseuri": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } }, "parseurl": { "version": "1.3.3", @@ -8066,7 +11689,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } }, "path-root-regex": { "version": "0.1.2", @@ -8079,6 +11705,9 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, + "requires": { + "isarray": "0.0.1" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -8093,6 +11722,9 @@ "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", @@ -8112,13 +11744,23 @@ "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true + "dev": true, + "requires": { + "through": "~2.3" + } }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "pbkdf2-compat": { "version": "2.0.1", @@ -8154,25 +11796,40 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true + "dev": true, + "requires": { + "find-up": "^3.0.0" + } }, "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, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.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 + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } } } }, @@ -8252,7 +11909,11 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "dev": true + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } }, "prr": { "version": "1.0.1", @@ -8264,7 +11925,10 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.1.tgz", "integrity": "sha512-kef7fYYSKVqQffmzTMsVcUD1ObNJMp8sNSmHGlGKsZQyL/ht9MZKk86u0Rd1NhpTOAuhqwKCLLpktwkqz+MF8A==", - "dev": true + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } }, "pseudomap": { "version": "1.0.2", @@ -8282,25 +11946,46 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "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 + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, "dependencies": { "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } } } }, @@ -8332,7 +12017,11 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } }, "querystring": { "version": "0.2.0", @@ -8357,6 +12046,11 @@ "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.0", + "math-random": "^1.0.1" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -8370,13 +12064,20 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } }, "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 + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } }, "range-parser": { "version": "1.2.1", @@ -8389,6 +12090,10 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, + "requires": { + "bytes": "1", + "string_decoder": "0.10" + }, "dependencies": { "string_decoder": { "version": "0.10.31", @@ -8402,37 +12107,59 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "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": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, "dependencies": { "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "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 + "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 + "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 + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } }, "p-try": { "version": "1.0.0", @@ -8446,25 +12173,46 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true + "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" + } }, "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true + "dev": true, + "requires": { + "resolve": "^1.1.6" + } }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } }, "regenerate": { "version": "1.4.0", @@ -8476,7 +12224,10 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", - "dev": true + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } }, "regenerator-runtime": { "version": "0.11.1", @@ -8487,19 +12238,29 @@ "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", - "dev": true + "dev": true, + "requires": { + "private": "^0.1.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 + "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 + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } }, "regexp-tree": { "version": "0.1.11", @@ -8517,7 +12278,15 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.0.2", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } }, "regjsgen": { "version": "0.5.0", @@ -8530,6 +12299,9 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -8543,61 +12315,129 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true + "dev": true, + "requires": { + "remark-parse": "^5.0.0", + "remark-stringify": "^5.0.0", + "unified": "^6.0.0" + } }, "remark-html": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true + "dev": true, + "requires": { + "hast-util-sanitize": "^1.0.0", + "hast-util-to-html": "^3.0.0", + "mdast-util-to-hast": "^3.0.0", + "xtend": "^4.0.1" + } }, "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } }, "remark-reference-links": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.4.tgz", "integrity": "sha512-+2X8hwSQqxG4tvjYZNrTcEC+bXp8shQvwRGG6J/rnFTvBoU4G0BBviZoqKGZizLh/DG+0gSYhiDDWCqyxXW1iQ==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.0.0" + } }, "remark-slug": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.2.tgz", "integrity": "sha512-DWX+Kd9iKycqyD+/B+gEFO3jjnt7Yg1O05lygYSNTe5i5PIxxxPjp5qPBDxPIzp5wreF7+1ROCwRgjEcqmzr3A==", - "dev": true + "dev": true, + "requires": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^1.0.0" + } }, "remark-stringify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true + "dev": true, + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } }, "remark-toc": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.1.1.tgz", "integrity": "sha512-vCPW4YOsm2CfyuScdktM9KDnJXVHJsd/ZeRtst+dnBU3B3KKvt8bc+bs5syJjyptAHfqo7H+5Uhz+2blWBfwow==", - "dev": true + "dev": true, + "requires": { + "mdast-util-toc": "^3.0.0", + "remark-slug": "^5.0.0" + } }, "remote-origin-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true + "dev": true, + "requires": { + "parse-git-config": "^0.2.0" + } }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } }, "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 + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } }, "remove-trailing-separator": { "version": "1.1.0", @@ -8621,7 +12461,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } }, "replace-ext": { "version": "1.0.0", @@ -8633,31 +12476,72 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.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 + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + } }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } }, "request-promise": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", - "dev": true + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } }, "request-promise-core": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.11" + } }, "require-directory": { "version": "2.1.1", @@ -8676,6 +12560,10 @@ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, "dependencies": { "resolve-from": { "version": "1.0.1", @@ -8695,13 +12583,20 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } }, "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 + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } }, "resolve-from": { "version": "5.0.0", @@ -8713,7 +12608,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } }, "resolve-url": { "version": "0.2.1", @@ -8725,13 +12623,20 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } }, "ret": { "version": "0.1.15", @@ -8755,7 +12660,10 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true + "dev": true, + "requires": { + "align-text": "^0.1.1" + } }, "rimraf": { "version": "2.2.8", @@ -8767,13 +12675,20 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } }, "rx-lite": { "version": "4.0.8", @@ -8785,7 +12700,10 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true + "dev": true, + "requires": { + "rx-lite": "*" + } }, "safe-buffer": { "version": "5.1.2", @@ -8803,7 +12721,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true + "dev": true, + "requires": { + "ret": "~0.1.10" + } }, "safer-buffer": { "version": "2.1.2", @@ -8821,7 +12742,10 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true + "dev": true, + "requires": { + "ajv": "^5.0.0" + } }, "semver": { "version": "5.7.0", @@ -8833,19 +12757,40 @@ "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 + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "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", + "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "mime": { "version": "1.4.1", @@ -8872,12 +12817,24 @@ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -8892,12 +12849,21 @@ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.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" + }, "dependencies": { "ms": { "version": "2.0.0", @@ -8911,7 +12877,14 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } }, "ms": { "version": "2.1.1", @@ -8923,7 +12896,22 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true + "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", + "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" + } }, "setprototypeof": { "version": "1.1.1", @@ -8944,6 +12932,12 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", @@ -8969,13 +12963,20 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "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 + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } }, "shebang-regex": { "version": "1.0.0", @@ -8987,13 +12988,24 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true + "dev": true, + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } }, "shelljs": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } }, "signal-exit": { "version": "3.0.2", @@ -9006,6 +13018,15 @@ "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "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" + }, "dependencies": { "diff": { "version": "3.5.0", @@ -9025,31 +13046,53 @@ "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 + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } }, "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": { + "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" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "ms": { "version": "2.0.0", @@ -9064,30 +13107,49 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "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 + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "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 + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -9096,12 +13158,18 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -9110,12 +13178,23 @@ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -9136,6 +13215,22 @@ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -9147,7 +13242,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -9162,6 +13260,11 @@ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -9173,7 +13276,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "isarray": { "version": "2.0.1", @@ -9193,7 +13299,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } }, "source-list-map": { "version": "2.0.1", @@ -9211,13 +13320,23 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } }, "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 + "dev": true, + "requires": { + "source-map": "^0.5.6" + } }, "source-map-url": { "version": "0.4.0", @@ -9241,7 +13360,11 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-exceptions": { "version": "2.2.0", @@ -9253,7 +13376,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-license-ids": { "version": "3.0.5", @@ -9265,13 +13392,19 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true + "dev": true, + "requires": { + "through": "2" + } }, "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 + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } }, "sprintf-js": { "version": "1.0.3", @@ -9283,7 +13416,18 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true + "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" + } }, "stack-trace": { "version": "0.0.10", @@ -9302,12 +13446,19 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.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 + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, @@ -9328,6 +13479,9 @@ "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", "dev": true, + "requires": { + "readable-stream": "~2.1.0" + }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -9339,7 +13493,16 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true + "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" + } }, "string_decoder": { "version": "0.10.31", @@ -9353,19 +13516,30 @@ "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 + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } }, "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 + "dev": true, + "requires": { + "duplexer": "~0.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 + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } }, "stream-exhaust": { "version": "1.0.2", @@ -9377,7 +13551,14 @@ "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 + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } }, "stream-shift": { "version": "1.0.0", @@ -9390,12 +13571,21 @@ "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -9405,12 +13595,6 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "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 - }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", @@ -9422,6 +13606,10 @@ "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" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -9433,7 +13621,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -9441,19 +13632,41 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.4.3", + "function-bind": "^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.0" + } }, "stringify-entities": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true + "dev": true, + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "requires": { + "ansi-regex": "^2.0.0" + } }, "strip-bom": { "version": "3.0.0", @@ -9477,7 +13690,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } }, "strip-json-comments": { "version": "2.0.1", @@ -9489,25 +13705,43 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true + "dev": true, + "requires": { + "minimist": "^1.1.0" + } }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "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 + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } }, "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true + "dev": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } }, "tapable": { "version": "0.2.9", @@ -9519,19 +13753,34 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.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.2" + }, "dependencies": { "rimraf": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.5" + } } } }, @@ -9539,7 +13788,13 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", - "dev": true + "dev": true, + "requires": { + "duplexify": "^3.5.0", + "fork-stream": "^0.0.4", + "merge-stream": "^1.0.0", + "through2": "^2.0.1" + } }, "text-table": { "version": "0.2.0", @@ -9563,13 +13818,21 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } }, "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 + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } }, "time-stamp": { "version": "1.1.0", @@ -9587,25 +13850,43 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } }, "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 + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } }, "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": { + "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" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -9613,13 +13894,20 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true + "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 + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } }, "to-array": { "version": "0.1.4", @@ -9650,12 +13938,18 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "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 + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -9663,19 +13957,32 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } }, "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 + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } }, "to-through": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true + "dev": true, + "requires": { + "through2": "^2.0.3" + } }, "toidentifier": { "version": "1.0.0", @@ -9688,6 +13995,10 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, "dependencies": { "punycode": { "version": "1.4.1", @@ -9749,7 +14060,10 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } }, "tweetnacl": { "version": "0.14.5", @@ -9767,7 +14081,10 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } }, "type-detect": { "version": "4.0.8", @@ -9779,7 +14096,11 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } }, "typedarray": { "version": "0.0.6", @@ -9792,6 +14113,10 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", "dev": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -9812,6 +14137,11 @@ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + }, "dependencies": { "camelcase": { "version": "1.2.1", @@ -9823,13 +14153,23 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } }, "wordwrap": { "version": "0.0.2", @@ -9841,7 +14181,13 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } } } }, @@ -9861,7 +14207,18 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true + "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", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } }, "undertaker-registry": { "version": "1.0.1", @@ -9873,7 +14230,11 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + } }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", @@ -9885,7 +14246,11 @@ "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 + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } }, "unicode-match-property-value-ecmascript": { "version": "1.1.0", @@ -9903,25 +14268,46 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } }, "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 + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } }, "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 + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } }, "unist-builder": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.4.tgz", "integrity": "sha512-v6xbUPP7ILrT15fHGrNyHc1Xda8H3xVhP7/HAIotHOhVPjH5dCXA097C3Rry1Q2O+HbOLCao4hfPB+EYEjHgVg==", - "dev": true + "dev": true, + "requires": { + "object-assign": "^4.1.0" + } }, "unist-util-generated": { "version": "1.1.4", @@ -9945,7 +14331,10 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.3.tgz", "integrity": "sha512-CtszTlOjP2sBGYc2zcKA/CvNdTdEs3ozbiJ63IPBxh8iZg42SCCb8m04f8z2+V1aSk5a7BxbZKEdoDjadmBkWA==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } }, "unist-util-stringify-position": { "version": "1.1.2", @@ -9957,13 +14346,19 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } }, "unist-util-visit-parents": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true + "dev": true, + "requires": { + "unist-util-is": "^3.0.0" + } }, "unpipe": { "version": "1.0.0", @@ -9976,18 +14371,30 @@ "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=", "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.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 + "dev": true, + "requires": { + "isarray": "1.0.0" + } } } }, @@ -10009,7 +14416,10 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true + "dev": true, + "requires": { + "punycode": "^2.1.0" + } }, "urix": { "version": "0.1.0", @@ -10022,6 +14432,10 @@ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, "dependencies": { "punycode": { "version": "1.3.2", @@ -10042,6 +14456,10 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + }, "dependencies": { "querystringify": { "version": "2.1.1", @@ -10056,6 +14474,9 @@ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "dev": true, + "requires": { + "prepend-http": "^2.0.0" + }, "dependencies": { "prepend-http": { "version": "2.0.0", @@ -10082,12 +14503,20 @@ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + }, "dependencies": { "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 + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } }, "yallist": { "version": "2.1.2", @@ -10102,6 +14531,9 @@ "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, + "requires": { + "inherits": "2.0.3" + }, "dependencies": { "inherits": { "version": "2.0.3", @@ -10133,13 +14565,20 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "dev": true + "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==", - "dev": true + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } }, "value-or-function": { "version": "3.0.0", @@ -10157,13 +14596,24 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } }, "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } }, "vfile-location": { "version": "2.0.5", @@ -10175,13 +14625,23 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true + "dev": true, + "requires": { + "unist-util-stringify-position": "^1.1.1" + } }, "vfile-reporter": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, + "requires": { + "repeat-string": "^1.5.0", + "string-width": "^1.0.0", + "supports-color": "^4.1.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-statistics": "^1.1.0" + }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -10193,19 +14653,30 @@ "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 + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } } } }, @@ -10225,25 +14696,64 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true + "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" + } }, "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 + "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" + } }, "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": { "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 + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -10251,7 +14761,10 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true + "dev": true, + "requires": { + "source-map": "^0.5.1" + } }, "vm-browserify": { "version": "1.1.0", @@ -10269,19 +14782,32 @@ "version": "2.3.14", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", - "dev": true + "dev": true, + "requires": { + "foreachasync": "^3.0.0" + } }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } }, "wdio-browserstack-service": { "version": "0.1.18", "resolved": "https://registry.npmjs.org/wdio-browserstack-service/-/wdio-browserstack-service-0.1.18.tgz", "integrity": "sha512-6tISYMKzwr2oxx0yi2Q4GoFC2Mbq81iHhqxayacC4XgFR7QbmQkxwV8JPeq590AXhuhPqqmyuEGkMqc9fo/UoQ==", - "dev": true + "dev": true, + "requires": { + "browserstack-local": "^1.3.7", + "request": "^2.81.0", + "request-promise": "^4.2.1" + } }, "wdio-concise-reporter": { "version": "0.1.2", @@ -10299,25 +14825,64 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/wdio-mocha-framework/-/wdio-mocha-framework-0.6.4.tgz", "integrity": "sha512-GZsXwoW60/fkkfqZJR/ZAdiALaM+hW+BbnTT9x214qPR4Pe5XeyYxhJNEdyf0dNI9625cMdkyZYaWoFHN5zDcA==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.23.0", + "mocha": "^5.2.0", + "wdio-sync": "0.7.3" + } }, "wdio-spec-reporter": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/wdio-spec-reporter/-/wdio-spec-reporter-0.1.5.tgz", "integrity": "sha512-MqvgTow8hFwhFT47q67JwyJyeynKodGRQCxF7ijKPGfsaG1NLssbXYc0JhiL7SiAyxnQxII0UxzTCd3I6sEdkg==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "~6.26.0", + "chalk": "^2.3.0", + "humanize-duration": "~3.15.0" + } }, "wdio-sync": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/wdio-sync/-/wdio-sync-0.7.3.tgz", "integrity": "sha512-ukASSHOQmOxaz5HTILR0jykqlHBtAPsBpMtwhpiG0aW9uc7SO7PF+E5LhVvTG4ypAh+UGmY3rTjohOsqDr39jw==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "fibers": "^3.0.0", + "object.assign": "^4.0.3" + } }, "webdriverio": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", "integrity": "sha512-Knp2vzuzP5c5ybgLu+zTwy/l1Gh0bRP4zAr8NWcrStbuomm9Krn9oRF0rZucT6AyORpXinETzmeowFwIoo7mNA==", "dev": true, + "requires": { + "archiver": "~2.1.0", + "babel-runtime": "^6.26.0", + "css-parse": "^2.0.0", + "css-value": "~0.0.1", + "deepmerge": "~2.0.1", + "ejs": "~2.5.6", + "gaze": "~1.1.2", + "glob": "~7.1.1", + "grapheme-splitter": "^1.0.2", + "inquirer": "~3.3.0", + "json-stringify-safe": "~5.0.1", + "mkdirp": "~0.5.1", + "npm-install-package": "~2.1.0", + "optimist": "~0.6.1", + "q": "~1.5.0", + "request": "^2.83.0", + "rgb2hex": "^0.1.9", + "safe-buffer": "~5.1.1", + "supports-color": "~5.0.0", + "url": "~0.11.0", + "wdio-dot-reporter": "~0.0.8", + "wgxpath": "~1.0.0" + }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -10329,7 +14894,10 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", "integrity": "sha512-7FQGOlSQ+AQxBNXJpVDj8efTA/FtyB5wcNE1omXXJ0cq6jm1jjDwuROlYDbnzHqdNPqliWFhcioCWSyav+xBnA==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } } } }, @@ -10338,12 +14906,42 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", "dev": true, + "requires": { + "acorn": "^5.0.0", + "acorn-dynamic-import": "^2.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "async": "^2.1.2", + "enhanced-resolve": "^3.4.0", + "escope": "^3.6.0", + "interpret": "^1.0.0", + "json-loader": "^0.5.4", + "json5": "^0.5.1", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "mkdirp": "~0.5.0", + "node-libs-browser": "^2.0.0", + "source-map": "^0.5.3", + "supports-color": "^4.2.1", + "tapable": "^0.2.7", + "uglifyjs-webpack-plugin": "^0.4.6", + "watchpack": "^1.4.0", + "webpack-sources": "^1.0.1", + "yargs": "^8.0.2" + }, "dependencies": { "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } }, "ajv-keywords": { "version": "3.4.1", @@ -10355,7 +14953,10 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.14" + } }, "camelcase": { "version": "4.1.0", @@ -10368,12 +14969,22 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, "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 + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } } } }, @@ -10381,13 +14992,27 @@ "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 + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.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" + } }, "fast-deep-equal": { "version": "2.0.1", @@ -10399,7 +15024,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, "get-caller-file": { "version": "1.0.3", @@ -10423,7 +15051,10 @@ "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 + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "json-schema-traverse": { "version": "0.4.1", @@ -10441,31 +15072,51 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.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 + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "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 + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "mimic-fn": { "version": "1.2.0", @@ -10477,19 +15128,30 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true + "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 + "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 + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } }, "p-try": { "version": "1.0.0", @@ -10501,13 +15163,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true + "dev": true, + "requires": { + "pify": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -10519,13 +15187,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } }, "require-main-filename": { "version": "1.0.1", @@ -10537,7 +15214,10 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } }, "y18n": { "version": "3.2.1", @@ -10555,13 +15235,31 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.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.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "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 + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, @@ -10570,6 +15268,21 @@ "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-walk": "^6.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.15", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, "dependencies": { "acorn": { "version": "6.2.1", @@ -10587,7 +15300,10 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } } } }, @@ -10596,6 +15312,10 @@ "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, + "requires": { + "source-list-map": "~0.1.7", + "source-map": "~0.4.1" + }, "dependencies": { "source-list-map": { "version": "0.1.8", @@ -10607,7 +15327,10 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -10616,6 +15339,15 @@ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, + "requires": { + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "url-join": "^2.0.2", + "webpack-log": "^1.0.1" + }, "dependencies": { "mime": { "version": "2.4.4", @@ -10629,13 +15361,23 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", - "dev": true + "dev": true, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + } }, "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": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -10650,6 +15392,15 @@ "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", "dev": true, + "requires": { + "gulp-util": "^3.0.7", + "lodash.clone": "^4.3.2", + "lodash.some": "^4.2.2", + "memory-fs": "^0.3.0", + "through": "^2.3.8", + "vinyl": "^1.1.0", + "webpack": "^1.12.9" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -10661,13 +15412,20 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } }, "array-unique": { "version": "0.2.1", @@ -10685,25 +15443,41 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } }, "browserify-aes": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1" + } }, "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 + "dev": true, + "requires": { + "pako": "~0.2.0" + } }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } }, "camelcase": { "version": "1.2.1", @@ -10715,13 +15489,29 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } }, "clone": { "version": "1.0.4", @@ -10739,13 +15529,24 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", - "dev": true + "dev": true, + "requires": { + "browserify-aes": "0.4.0", + "pbkdf2-compat": "2.0.1", + "ripemd160": "0.2.0", + "sha.js": "2.2.6" + } }, "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.1.2", + "memory-fs": "^0.2.0", + "tapable": "^0.1.8" + }, "dependencies": { "memory-fs": { "version": "0.2.0", @@ -10765,31 +15566,50 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } }, "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 + "dev": true, + "requires": { + "fill-range": "^2.1.0" + } }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } }, "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 + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.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 + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } }, "has-flag": { "version": "1.0.0", @@ -10819,19 +15639,28 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } }, "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true + "dev": true, + "requires": { + "isarray": "1.0.0" + } }, "json5": { "version": "0.5.1", @@ -10843,37 +15672,93 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } }, "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 + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.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 + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } }, "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 + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.1.4", + "buffer": "^4.9.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "0.0.1", + "os-browserify": "^0.2.0", + "path-browserify": "0.0.0", + "process": "^0.11.0", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.0.5", + "stream-browserify": "^2.0.1", + "stream-http": "^2.3.1", + "string_decoder": "^0.10.25", + "timers-browserify": "^2.0.2", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + } }, "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 + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } }, "os-browserify": { "version": "0.2.1", @@ -10927,7 +15812,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } }, "tapable": { "version": "0.1.10", @@ -10940,6 +15828,12 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, "dependencies": { "async": { "version": "0.2.10", @@ -10954,6 +15848,9 @@ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "dev": true, + "requires": { + "inherits": "2.0.3" + }, "dependencies": { "inherits": { "version": "2.0.3", @@ -10967,19 +15864,32 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } }, "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 + "dev": true, + "requires": { + "indexof": "0.0.1" + } }, "watchpack": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, + "requires": { + "async": "^0.9.0", + "chokidar": "^1.0.0", + "graceful-fs": "^4.1.2" + }, "dependencies": { "async": { "version": "0.9.2", @@ -10993,7 +15903,24 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "dev": true + "dev": true, + "requires": { + "acorn": "^3.0.0", + "async": "^1.3.0", + "clone": "^1.0.2", + "enhanced-resolve": "~0.9.0", + "interpret": "^0.6.4", + "loader-utils": "^0.2.11", + "memory-fs": "~0.3.0", + "mkdirp": "~0.5.0", + "node-libs-browser": "^0.7.0", + "optimist": "~0.6.0", + "supports-color": "^3.1.0", + "tapable": "~0.1.8", + "uglify-js": "~2.7.3", + "watchpack": "^0.2.1", + "webpack-core": "~0.6.9" + } }, "wordwrap": { "version": "0.0.2", @@ -11005,7 +15932,13 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } } } }, @@ -11013,7 +15946,12 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", - "dev": true + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0 <0.4.11", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } }, "websocket-extensions": { "version": "0.1.3", @@ -11031,7 +15969,10 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true + "dev": true, + "requires": { + "isexe": "^2.0.0" + } }, "which-module": { "version": "2.0.0", @@ -11043,7 +15984,10 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } }, "window-size": { "version": "0.1.0", @@ -11061,19 +16005,28 @@ "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.1", + "strip-ansi": "^3.0.1" + }, "dependencies": { "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "requires": { + "number-is-nan": "^1.0.0" + } }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } } } }, @@ -11087,13 +16040,21 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } }, "x-is-string": { "version": "0.1.0", @@ -11135,13 +16096,22 @@ "version": "13.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } }, "yargs-unparser": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, "dependencies": { "get-caller-file": { "version": "1.0.3", @@ -11159,13 +16129,31 @@ "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } }, "yargs-parser": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -11179,7 +16167,13 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", - "dev": true + "dev": true, + "requires": { + "archiver-utils": "^1.3.0", + "compress-commons": "^1.2.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0" + } } } } diff --git a/test/spec/modules/buzzoolaBidAdapter_spec.js b/test/spec/modules/buzzoolaBidAdapter_spec.js new file mode 100644 index 00000000000..e6f22d1da20 --- /dev/null +++ b/test/spec/modules/buzzoolaBidAdapter_spec.js @@ -0,0 +1,279 @@ +import {expect} from 'chai'; +import {spec} from 'modules/buzzoolaBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +import {executeRenderer, Renderer} from '../../../src/Renderer'; +import {deepClone} from '../../../src/utils'; + +const ENDPOINT = 'https://exchange.buzzoola.com/ssp/prebidjs'; +const RENDERER_SRC = 'https://tube.buzzoola.com/new/build/buzzlibrary.js'; + +const INVALID_BIDS = [{ + 'bidder': 'buzzoola', + 'mediaTypes': {'banner': {'sizes': [[240, 400], [300, 600]]}}, + 'sizes': [[240, 400], [300, 600]] +}, { + 'bidder': 'buzzoola', + 'params': {'placementId': 417846}, + 'sizes': [[240, 400], [300, 600]] +}, { + 'bidder': 'buzzoola', + 'mediaTypes': { + 'video': { + 'playerSize': [[640, 380]], + 'mimes': ['video/mp4'], + 'minduration': 1, + 'maxduration': 2 + } + } +}, { + 'bidder': 'buzzoola', + 'params': {'placementId': 417845} +}]; + +const BANNER_BID = { + 'bidder': 'buzzoola', + 'params': {'placementId': 417846}, + 'mediaTypes': {'banner': {'sizes': [[240, 400], [300, 600]]}}, + 'sizes': [[240, 400], [300, 600]], + 'bidId': '2a11641ada3c6a' +}; + +const BANNER_BID_REQUEST = { + bidderCode: 'buzzoola', + bids: [BANNER_BID] +}; + +const BANNER_RESPONSE = [{ + 'requestId': '2a11641ada3c6a', + 'cpm': 5.583115, + 'width': 240, + 'height': 400, + 'creativeId': '11773', + 'dealId': '', + 'currency': 'RUB', + 'netRevenue': true, + 'ttl': 10800, + 'ad': '
    ', + 'mediaType': 'banner' +}]; + +const REQUIRED_BANNER_FIELDS = [ + 'requestId', + 'cpm', + 'width', + 'height', + 'ad', + 'ttl', + 'creativeId', + 'netRevenue', + 'currency', + 'mediaType' +]; + +const VIDEO_BID = { + 'bidder': 'buzzoola', + 'params': {'placementId': 417845}, + 'mediaTypes': { + 'video': { + 'context': 'instream', + 'playerSize': [[640, 380]], + 'mimes': ['video/mp4'], + 'minduration': 1, + 'maxduration': 2 + } + }, + 'bidId': '325a54271dc40a' +}; + +const VIDEO_BID_REQUEST = { + bidderCode: 'buzzoola', + bids: [VIDEO_BID] +}; + +const VIDEO_RESPONSE = [{ + 'requestId': '325a54271dc40a', + 'cpm': 4.6158956756756755, + 'width': 640, + 'height': 380, + 'creativeId': '11774', + 'dealId': '', + 'currency': 'RUB', + 'netRevenue': true, + 'ttl': 10800, + 'ad': '{"crs":[{"advertiser_id":165,"title":"qa//PrebidJStestVideoURL","description":"qa//PrebidJStest","duration":0,"ya_id":"55038886","raw_content":"{\\"main_content\\": \\"https://tube.buzzoola.com/xstatic/o42/mcaug/2.mp4\\"}","content":{"main_content":"https://tube.buzzoola.com/xstatic/o42/mcaug/2.mp4"},"content_type":"video_url","sponsor_link":"","sponsor_name":"","overlay":"","overlay_start_after":0,"overlay_close_after":0,"action_button_title":"","tracking_url":{},"iframe_domains":[],"soc_share_url":"https://tube.buzzoola.com/share.html","player_show_skip_button_before_play":false,"player_show_skip_button_seconds":5,"player_show_title":true,"player_data_attributes":{"expandable":"default","overroll":"default"},"click_event_view":"default","share_panel_position":"left","auto_play":true,"logo_url":{},"share_buttons":["vkontakte","facebook","twitter","moimir","odnoklassniki","embed"],"player_show_panels":false,"thumbnail":"","tracking_js":{},"click_event_url":"https://exchange.buzzoola.com/event/f9382ceb-49c2-4683-50d8-5c516c53cd69/14795a96-6261-49dc-7241-207333ab1490/m7JVQI9Y7J35_gEDugNO2bIiP2qTqPKfuLrqqh_LoJu0tD6PoLEglMXUBzVpSg75c-unsaijXpIERGosa1adogXgqjDml4Pm/click/0/","vpaid_js_url":"https://tube.buzzoola.com/new/js/lib/vpaid_js_proxy.js","skip_clickthru":false,"landing_link_text":"","sound_enabled_by_default":false,"landing_link_position":"right","displayed_price":"","js_wrapper_url":"","enable_moat":false,"branding_template":"","event_url":"https://exchange.buzzoola.com/event/f9382ceb-49c2-4683-50d8-5c516c53cd69/14795a96-6261-49dc-7241-207333ab1490/m7JVQI9Y7J35_gEDugNO2bIiP2qTqPKfuLrqqh_LoJu0tD6PoLEglMXUBzVpSg75c-unsaijXpIERGosa1adogXgqjDml4Pm/","resend_event_url":"https://exchange.buzzoola.com/resend_event/f9382ceb-49c2-4683-50d8-5c516c53cd69/14795a96-6261-49dc-7241-207333ab1490/m7JVQI9Y7J35_gEDugNO2bIiP2qTqPKfuLrqqh_LoJu0tD6PoLEglMXUBzVpSg75c-unsaijXpIERGosa1adogXgqjDml4Pm/","creative_hash":"m7JVQI9Y7J35_gEDugNO2bIiP2qTqPKfuLrqqh_LoJu0tD6PoLEglMXUBzVpSg75c-unsaijXpIERGosa1adogXgqjDml4Pm","custom_html":"","custom_js":"","height":0,"width":0,"campaign_id":5758,"line_item_id":17319,"creative_id":11774,"extra":{"imp_id":"14795a96-6261-49dc-7241-207333ab1490","rtime":"2019-08-27 13:58:36"},"subcontent":"vast","auction_settings":{"price":"4.6158956756756755","currency":"RUB","event_name":"player_seen","time_slice":0},"hash_to_embed":"kbDH64c7yFYkSu0KCwSkoUD2bNHAnUTHBERqLGtWnaIF4Kow5peD5g","need_ad":false}],"tracking_urls":{"ctor":["https://www.tns-counter.ru/V13a****buzzola_com/ru/CP1251/tmsec=buzzola_total/1322650417245790778","https://www.tns-counter.ru/V13a****buzzoola_kz/ru/UTF-8/tmsec=buzzoola_video/5395765100939533275","https://buzzoolaru.solution.weborama.fr/fcgi-bin/dispatch.fcgi?a.A=ev&a.si=3071&a.te=37&a.aap=1&a.agi=862&a.evn=PrebidJS.test&g.ra=4581478478720298652","https://x01.aidata.io/0.gif?pid=BUZZOOLA&id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://top-fwz1.mail.ru/counter?id=3026769","https://www.tns-counter.ru/V13a****buzzola_com/ru/UTF-8/tmsec=buzzola_inread/542059452789128996","https://dm.hybrid.ai/match?id=111&vid=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://px.adhigh.net/p/cm/buzzoola?u=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://ssp1.rtb.beeline.ru/userbind?src=buz&ssp_user_id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://sync.upravel.com/image?source=buzzoola&id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://relap.io/api/partners/bzcs.gif?uid=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://x.bidswitch.net/sync?ssp=sspicyads","https://inv-nets.admixer.net/adxcm.aspx?ssp=3C5173FC-CA30-4692-9116-009C19CB1BF9&rurl=%2F%2Fexchange.buzzoola.com%2Fcookiesync%2Fdsp%2Fadmixer-video%2F%24%24visitor_cookie%24%24","https://sync.datamind.ru/cookie/accepter?source=buzzoola&id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://dmp.vihub.ru/match?sysid=buz&redir=no&uid=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://ad.adriver.ru/cgi-bin/rle.cgi?sid=1&ad=608223&bt=21&pid=2551979&bid=6150299&bn=6150299&rnd=1279444531737367663","https://reichelcormier.bid/point/?method=match&type=ssp&key=4677290772f9000878093d69c199bfba&id=3509&extUid=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://sync.republer.com/match?src=buzzoola&id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://sm.rtb.mts.ru/p?id=dbdb5b13-e719-4987-7f6a-a882322bbfce&ssp=buzzoola","https://cm.mgid.com/m?cdsp=371151&adu=https%3A%2F%2Fexchange.buzzoola.com%2Fcookiesync%2Fdsp%2Fmarketgid-native%2F%7Bmuidn%7D","https://dmp.gotechnology.io/dmp/syncsspdmp?sspid=122258"]},"tracking_js":{"ctor":["https://buzzoola.fraudscore.mobi/dooJ9sheeeDaZ3fe.js?s=268671&l=417845"]},"placement":{"placement_id":417845,"unit_type":"inread","unit_settings":{"align":"left","autoplay_enable_sound":false,"creatives_amount":1,"debug_mode":false,"expandable":"never","sound_control":"default","target":"","width":"100%"},"unit_settings_list":["width","sound_control","debug_mode","target","creatives_amount","expandable","container_height","align","height"]},"uuid":"dbdb5b13-e719-4987-7f6a-a882322bbfce","auction_id":"f9382ceb-49c2-4683-50d8-5c516c53cd69","env":"prod"}', + 'vastXml': '\n00:00:30', + 'mediaType': 'video' +}]; + +const RENDERER_DATA = { + data: JSON.parse(VIDEO_RESPONSE[0].ad) +}; +RENDERER_DATA.data.placement.unit_settings.width = '' + VIDEO_RESPONSE[0].width; +RENDERER_DATA.data.placement.unit_settings.height = RENDERER_DATA.data.placement.unit_settings.container_height = '' + VIDEO_RESPONSE[0].height; + +const REQUIRED_VIDEO_FIELDS = [ + 'requestId', + 'cpm', + 'width', + 'height', + 'ad', + 'ttl', + 'creativeId', + 'netRevenue', + 'currency', + 'vastXml', + 'mediaType' +]; + +describe('buzzoolaBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(VIDEO_BID)).to.be.true; + }); + + it('should return false when required params are not passed', () => { + INVALID_BIDS.forEach(bid => { + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + }); + + describe('buildRequests', () => { + let videoBidRequests = [VIDEO_BID]; + let bannerBidRequests = [BANNER_BID]; + + const bannerRequest = spec.buildRequests(bannerBidRequests, BANNER_BID_REQUEST); + const videoRequest = spec.buildRequests(videoBidRequests, VIDEO_BID_REQUEST); + + it('sends bid request to ENDPOINT via POST', () => { + expect(videoRequest.method).to.equal('POST'); + expect(bannerRequest.method).to.equal('POST'); + }); + + it('sends bid request to correct ENDPOINT', () => { + expect(videoRequest.url).to.equal(ENDPOINT); + expect(bannerRequest.url).to.equal(ENDPOINT); + }); + + it('sends correct video bid parameters', () => { + expect(videoRequest.data).to.deep.equal(VIDEO_BID_REQUEST); + }); + + it('sends correct banner bid parameters', () => { + expect(bannerRequest.data).to.deep.equal(BANNER_BID_REQUEST); + }); + }); + + describe('interpretResponse', () => { + const noBidServerResponse = []; + const emptyResponse = ''; + + function nobidServerResponseCheck(request, response = noBidServerResponse) { + const noBidResult = spec.interpretResponse({body: response}, {data: request}); + + expect(noBidResult.length).to.equal(0); + } + + function bidServerResponseCheck(response, request, fields) { + const result = spec.interpretResponse({body: response}, {data: request}); + + expect(result).to.deep.equal(response); + result.forEach(bid => { + fields.forEach(field => { + expect(bid).to.have.own.property(field); + }) + }); + } + + it('handles video nobid responses', () => { + nobidServerResponseCheck(VIDEO_BID_REQUEST); + }); + + it('handles banner nobid responses', () => { + nobidServerResponseCheck(BANNER_BID_REQUEST); + }); + + it('handles video empty responses', () => { + nobidServerResponseCheck(VIDEO_BID_REQUEST, emptyResponse); + }); + + it('handles banner empty responses', () => { + nobidServerResponseCheck(BANNER_BID_REQUEST, emptyResponse); + }); + + it('should get correct video bid response', () => { + bidServerResponseCheck(VIDEO_RESPONSE, VIDEO_BID_REQUEST, REQUIRED_VIDEO_FIELDS); + }); + + it('should get correct banner bid response', () => { + bidServerResponseCheck(BANNER_RESPONSE, BANNER_BID_REQUEST, REQUIRED_BANNER_FIELDS); + }); + }); + + describe('outstream renderer', () => { + let result; + let renderer; + + before(() => { + const adContainer = document.createElement('div'); + adContainer.id = 'adUnitCode'; + document.body.appendChild(adContainer); + + const outstreamVideoBid = deepClone(VIDEO_BID); + outstreamVideoBid.mediaTypes.video.context = 'outstream'; + + const outstreamVideoRequest = deepClone(VIDEO_BID_REQUEST); + outstreamVideoRequest.bids = [outstreamVideoBid]; + + const scriptElement = document.createElement('div'); + + const scriptStub = sinon.stub(document, 'createElement'); + scriptStub.withArgs('script').returns(scriptElement); + + result = spec.interpretResponse({body: VIDEO_RESPONSE}, {data: outstreamVideoRequest})[0]; + renderer = result.renderer; + + result.adUnitCode = 'adUnitCode'; + + scriptElement.onload && scriptElement.onload(); + + scriptStub.restore(); + }); + + it('should add renderer for outstream video', () => { + expect(result).to.have.own.property('renderer'); + }); + + it('should be instance of Renderer', () => { + expect(renderer).to.be.instanceof(Renderer); + }); + + it('should have valid src', () => { + expect(renderer.url).to.equal(RENDERER_SRC); + }); + + it('should create player instance', () => { + window.Buzzoola = { + Core: { + install: () => {} + } + }; + const spy = sinon.spy(window.Buzzoola.Core, 'install'); + executeRenderer(renderer, result); + expect(spy.called).to.be.true; + + const spyCall = spy.getCall(0); + + expect(spyCall.args[0]).to.be.instanceof(Element); + expect(spyCall.args[1]).to.deep.equal(RENDERER_DATA); + }); + }); +}); From 8b92b1fbcc251067a740281880cbd85e3f90733f Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 10 Sep 2019 11:53:10 +0530 Subject: [PATCH 1482/1594] E2e tests for Native and Outstream video Ad formats. (#4116) * reorganize e2e/ tests into separate directories * new test page for e2e-banner testing * add test to check if Banner Ad is getting loaded * change location of the spec files to reflect change in test/e2e directory structure * add test case to check for generation of valid targeting keys * create Native Ad test page * add test case to check validity of the targeting keys and correct rendering of the Ad * update old browser versions to new * update browser version * update title * remove console.log statements * add basic functional test for e2e outstream video ad format --- browsers.json | 26 +-- test/pages/banner.html | 2 +- test/pages/native.html | 123 +++++++++++++ test/pages/outstream.html | 168 ++++++++++++++++++ test/spec/e2e/native/basic_native_ad.spec.js | 59 ++++++ .../basic_outstream_video_ad.spec.js | 53 ++++++ 6 files changed, 417 insertions(+), 14 deletions(-) create mode 100644 test/pages/native.html create mode 100644 test/pages/outstream.html create mode 100644 test/spec/e2e/native/basic_native_ad.spec.js create mode 100644 test/spec/e2e/outstream/basic_outstream_video_ad.spec.js diff --git a/browsers.json b/browsers.json index 8604e44a7b8..9042d7d0627 100644 --- a/browsers.json +++ b/browsers.json @@ -1,17 +1,17 @@ { - "bs_edge_16_windows_10": { + "bs_edge_17_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "edge", - "browser_version": "16.0", + "browser_version": "17.0", "device": null, "os": "Windows" }, - "bs_edge_17_windows_10": { + "bs_edge_16_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "edge", - "browser_version": "17.0", + "browser_version": "16.0", "device": null, "os": "Windows" }, @@ -23,35 +23,35 @@ "device": null, "os": "Windows" }, - "bs_chrome_72_windows_10": { + "bs_chrome_74_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "72.0", + "browser_version": "74.0", "device": null, "os": "Windows" }, - "bs_chrome_71_windows_10": { + "bs_chrome_75_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "71.0", + "browser_version": "75.0", "device": null, "os": "Windows" }, - "bs_firefox_65_windows_10": { + "bs_firefox_66_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "firefox", - "browser_version": "65.0", + "browser_version": "66.0", "device": null, "os": "Windows" }, - "bs_firefox_64_windows_10": { + "bs_firefox_67_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "firefox", - "browser_version": "64.0", + "browser_version": "67.0", "device": null, "os": "Windows" }, @@ -71,4 +71,4 @@ "device": null, "os": "OS X" } -} \ No newline at end of file +} diff --git a/test/pages/banner.html b/test/pages/banner.html index e8c30239ac0..03f3b9b9e54 100644 --- a/test/pages/banner.html +++ b/test/pages/banner.html @@ -4,7 +4,7 @@ - Prebid.js Banner Ad Unit Example + Prebid.js Banner Example diff --git a/test/pages/native.html b/test/pages/native.html new file mode 100644 index 00000000000..0823f486848 --- /dev/null +++ b/test/pages/native.html @@ -0,0 +1,123 @@ + + + + + + + Prebid.js Native Example + + + + + + + + + + + + + + + +

    Prebid.js Native Ad Unit Test

    +
    +

    No response

    + +
    + + + diff --git a/test/pages/outstream.html b/test/pages/outstream.html new file mode 100644 index 00000000000..56e443a519b --- /dev/null +++ b/test/pages/outstream.html @@ -0,0 +1,168 @@ + + + + + + + Prebid.js Video Outstream Example + + + + + + + + + + + + +
    +

    + In scelerisque sem sed tortor posuere sagittis. Fusce scelerisque odio at tincidunt ultricies. Fusce egestas, erat + non finibus dictum, nulla arcu viverra nibh, at bibendum ligula nisi egestas magna. Nulla eu finibus nulla. + Pellentesque at mi eget turpis + consequat scelerisque. Sed lacinia, nisi sit amet egestas vestibulum, elit odio iaculis leo, et lacinia risus enim + non lacus. Cras nec neque eget nunc gravida maximus. Ut hendrerit convallis sollicitudin. Donec cursus erat vel + metus gravida, + et pretium justo iaculis. Curabitur condimentum blandit augue, quis interdum leo. Vivamus dapibus est nec dui + efficitur, eu imperdiet nulla sollicitudin. Suspendisse laoreet velit vitae arcu mollis, ac interdum lorem + venenatis. Aenean + nec purus varius, accumsan ex at, luctus arcu. Quisque consectetur tortor eros, placerat lacinia eros aliquam a. + Proin non porttitor libero. +

    +

    + Proin eget vulputate est. Nunc sit amet neque a tortor ullamcorper suscipit non eu neque. Quisque at massa in + metus feugiat rutrum. Nulla et orci orci. Aliquam erat volutpat. Cras tincidunt metus lectus, sed suscipit augue + mollis vitae. Sed quis condimentum + tortor, sit amet consectetur erat. Nulla pellentesque turpis lacus, eu venenatis massa fringilla at. Duis sed + pharetra turpis. Maecenas vel porttitor neque. Praesent quis felis sapien. Donec suscipit euismod dui, vitae + fermentum nisi ornare + in. +

    +

    + Suspendisse tempor felis accumsan orci finibus, imperdiet mollis arcu imperdiet. In eu dolor condimentum, pulvinar + nisl a, sollicitudin nunc. Ut vel lectus libero. Praesent rhoncus leo tortor, at mollis nulla sagittis eget. + Quisque tempus tempor augue + sed rutrum. Sed vitae volutpat quam. Proin vestibulum eros metus, a luctus erat condimentum eu. Vivamus + ullamcorper ultricies dui, ac malesuada leo finibus semper. Cras diam augue, imperdiet sed efficitur id, aliquam + sed purus. Praesent + eget turpis quis sapien interdum sagittis. Vivamus placerat nunc a tempus fermentum. Praesent laoreet leo at + tellus porta, ut viverra tortor pharetra. Quisque elit velit, eleifend eget imperdiet vel, suscipit ac nisi. + Aliquam egestas mauris + ut massa fringilla laoreet. +

    +
    +

    Prebid Outstream Video Ad

    + +
    +

    + Quisque ac luctus nisi, vitae ornare arcu. Proin fermentum sapien vitae odio vestibulum porta. Suspendisse + faucibus sapien enim, et faucibus urna tempus et. Integer porttitor justo sed faucibus blandit. Morbi semper + lectus vitae semper facilisis. Quisque + molestie accumsan arcu, eget bibendum dui euismod et. Sed in mattis lacus, nec lacinia sem. Fusce sed tortor + posuere, iaculis justo varius, elementum est. +

    +

    + Etiam condimentum, eros commodo semper tristique, lorem leo pharetra massa, eget cursus justo enim id urna. Sed + imperdiet mauris vitae ante bibendum elementum. Etiam eu dui porttitor leo imperdiet cursus. Maecenas consequat, + neque a dapibus viverra, nunc + velit volutpat nibh, ut cursus sem tortor ac arcu. Praesent convallis lacus vel nisi aliquam, in posuere libero + scelerisque. Curabitur et lacinia nisl. Nunc id ligula neque. Phasellus non eros et leo ultrices ultricies. Nulla + facilisi. + Donec ut augue urna. Suspendisse sodales nisi at ex faucibus, et tempus magna fermentum. Proin non arcu interdum, + pulvinar est at, vehicula odio. Morbi nec maximus sem. Ut eu tristique urna. +

    +

    + Pellentesque eget quam sem. Nam interdum eleifend leo, mattis sagittis metus ornare tristique. Cras pretium odio + lectus, vitae viverra massa consequat eget. Suspendisse porttitor pretium lectus in scelerisque. Phasellus euismod + porta lectus eget pharetra. + Ut et viverra mi, ut imperdiet lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere + cubilia Curae; Nunc tempus sapien sit amet tortor rhoncus dignissim. Sed at augue et sem lacinia feugiat. Nulla + vitae convallis + urna. Morbi scelerisque erat quis nibh pretium, non elementum elit consectetur. Proin in feugiat nisl. +

    +

    + Morbi et ipsum purus. Integer ut pulvinar metus. Fusce maximus ex nec purus sollicitudin gravida. Vivamus dapibus + volutpat erat nec tristique. Aliquam mi dolor, pretium non elementum quis, viverra non est. Pellentesque egestas, + lectus a posuere imperdiet, + nisi sem elementum neque, eu volutpat arcu turpis venenatis magna. Curabitur non neque consectetur, vulputate urna + sed, vestibulum lacus. Aenean mollis, risus non pulvinar egestas, lectus lectus finibus dui, sit amet pretium + metus mauris + vitae nibh. In non ultricies odio. +

    +
    + + + diff --git a/test/spec/e2e/native/basic_native_ad.spec.js b/test/spec/e2e/native/basic_native_ad.spec.js new file mode 100644 index 00000000000..ed09228b532 --- /dev/null +++ b/test/spec/e2e/native/basic_native_ad.spec.js @@ -0,0 +1,59 @@ +const expect = require('chai').expect; +const { host, protocol } = require('../../../helpers/testing-utils'); + +const TEST_PAGE_URL = `${protocol}://${host}:9999/test/pages/native.html`; +const CREATIVE_IFRAME_CSS_SELECTOR = 'iframe[id="google_ads_iframe_/19968336/prebid_native_example_1_0"]'; + +const EXPECTED_TARGETING_KEYS = { + hb_source: 'client', + hb_source_appnexus: 'client', + hb_pb_appnexus: '10.00', + hb_native_title_appn: 'This is a Prebid Native Creative', + hb_native_linkurl: 'http://prebid.org/dev-docs/show-native-ads.html', + hb_format: 'native', + hb_native_brand: 'Prebid.org', + hb_size: '0x0', + hb_bidder_appnexus: 'appnexus', + hb_native_linkurl_ap: 'http://prebid.org/dev-docs/show-native-ads.html', + hb_native_title: 'This is a Prebid Native Creative', + hb_pb: '10.00', + hb_native_brand_appn: 'Prebid.org', + hb_bidder: 'appnexus', + hb_format_appnexus: 'native', + hb_size_appnexus: '0x0' +} + +describe('Prebid.js Native Ad Unit Test', function () { + before(function loadTestPage() { + browser.url(TEST_PAGE_URL).pause(3000); + try { + browser.waitForExist(CREATIVE_IFRAME_CSS_SELECTOR, 2000); + } catch (e) { + // If creative Iframe didn't load, repeat the steps again! + // Due to some reason if the Ad server doesn't respond, the test case will time out after 60000 ms as defined in file wdio.conf.js + loadTestPage(); + } + }); + + it('should load the targeting keys with correct values', function () { + const result = browser.execute(function () { + return window.pbjs.getAdserverTargeting('/19968336/prebid_native_example_2'); + }); + + const targetingKeys = result.value['/19968336/prebid_native_example_2']; + expect(targetingKeys).to.include(EXPECTED_TARGETING_KEYS); + expect(targetingKeys.hb_adid).to.be.a('string'); + expect(targetingKeys.hb_native_body).to.be.a('string'); + expect(targetingKeys.hb_native_body_appne).to.be.a('string'); + expect(targetingKeys.hb_native_icon).to.be.a('string'); + expect(targetingKeys.hb_native_icon_appne).to.be.a('string'); + expect(targetingKeys.hb_native_image).to.be.a('string'); + expect(targetingKeys.hb_adid_appnexus).to.be.a('string'); + }); + + it('should render the native ad on the page', function () { + const creativeIframe = $(CREATIVE_IFRAME_CSS_SELECTOR).value; + browser.frame(creativeIframe); + expect(browser.isVisible('body > div[class="GoogleActiveViewElement"] > div[class="card"]')).to.be.true; + }); +}); diff --git a/test/spec/e2e/outstream/basic_outstream_video_ad.spec.js b/test/spec/e2e/outstream/basic_outstream_video_ad.spec.js new file mode 100644 index 00000000000..15b0bb29309 --- /dev/null +++ b/test/spec/e2e/outstream/basic_outstream_video_ad.spec.js @@ -0,0 +1,53 @@ +const expect = require('chai').expect; +const { host, protocol } = require('../../../helpers/testing-utils'); + +const TEST_PAGE_URL = `${protocol}://${host}:9999/test/pages/outstream.html`; +const CREATIVE_IFRAME_CSS_SELECTOR = 'div[id="video_ad_unit_1"] > div:nth-child(2) > iframe:nth-child(1)'; + +const EXPECTED_TARGETING_KEYS = { + hb_cache_id: '', + hb_uuid: '', + hb_format: 'video', + hb_source: 'client', + hb_size: '640x480', + hb_pb: '10.00', + hb_bidder: 'appnexus', + hb_format_appnexus: 'video', + hb_source_appnexus: 'client', + hb_size_appnexus: '640x480', + hb_pb_appnexus: '10.00', + hb_bidder_appnexus: 'appnexus' +}; + +describe('Prebid.js Outstream Video Ad Test', function () { + before(function loadTestPage() { + browser + .url(TEST_PAGE_URL) + .scroll(0, 300) + .pause(3000); + try { + browser.waitForExist(CREATIVE_IFRAME_CSS_SELECTOR, 5000); + } catch (e) { + // If creative Iframe didn't load, repeat the steps again! + // Due to some reason if the Ad server doesn't respond, the test case will time out after 60000 ms as defined in file wdio.conf.js + loadTestPage(); + } + }); + + it('should load the targeting keys with correct values', function () { + const result = browser.execute(function () { + return window.pbjs.getAdserverTargeting('video_ad_unit_2'); + }); + + const targetingKeys = result.value['video_ad_unit_2']; + expect(targetingKeys).to.include(EXPECTED_TARGETING_KEYS); + expect(targetingKeys.hb_adid).to.be.a('string'); + expect(targetingKeys.hb_adid_appnexus).to.be.a('string'); + }); + + it('should render the native ad on the page', function() { + const creativeIframe = $(CREATIVE_IFRAME_CSS_SELECTOR).value; + browser.frame(creativeIframe); + expect(browser.isVisible('body > div[class="video-js"] > video')); + }); +}); From 276e1f70c0a88d4467182a856e7cb94b1ac58c08 Mon Sep 17 00:00:00 2001 From: Margaret Liu Date: Tue, 10 Sep 2019 11:33:26 -0500 Subject: [PATCH 1483/1594] Update LockerDome adUnitId bid param (#4176) This is not a breaking change --- modules/lockerdomeBidAdapter.md | 2 +- test/spec/modules/lockerdomeBidAdapter_spec.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/lockerdomeBidAdapter.md b/modules/lockerdomeBidAdapter.md index 2e2e69a7557..2dbec86ffba 100644 --- a/modules/lockerdomeBidAdapter.md +++ b/modules/lockerdomeBidAdapter.md @@ -22,7 +22,7 @@ var adUnits = [{ bids: [{ bidder: 'lockerdome', params: { - adUnitId: 10809467961050726 + adUnitId: 'LD10809467961050726' } }] }]; diff --git a/test/spec/modules/lockerdomeBidAdapter_spec.js b/test/spec/modules/lockerdomeBidAdapter_spec.js index 1cd6778b01f..6a3fd814030 100644 --- a/test/spec/modules/lockerdomeBidAdapter_spec.js +++ b/test/spec/modules/lockerdomeBidAdapter_spec.js @@ -6,7 +6,7 @@ describe('LockerDomeAdapter', function () { const bidRequests = [{ bidder: 'lockerdome', params: { - adUnitId: 10809467961050726 + adUnitId: 'LD10809467961050726' }, mediaTypes: { banner: { @@ -22,7 +22,7 @@ describe('LockerDomeAdapter', function () { }, { bidder: 'lockerdome', params: { - adUnitId: 9434769725128806 + adUnitId: 'LD9434769725128806' }, mediaTypes: { banner: { @@ -66,14 +66,14 @@ describe('LockerDomeAdapter', function () { expect(bids[0].requestId).to.equal('2652ca954bce9'); expect(bids[0].adUnitCode).to.equal('ad-1'); - expect(bids[0].adUnitId).to.equal(10809467961050726); + expect(bids[0].adUnitId).to.equal('LD10809467961050726'); expect(bids[0].sizes).to.have.lengthOf(1); expect(bids[0].sizes[0][0]).to.equal(300); expect(bids[0].sizes[0][1]).to.equal(250); expect(bids[1].requestId).to.equal('4510f2834773ce'); expect(bids[1].adUnitCode).to.equal('ad-2'); - expect(bids[1].adUnitId).to.equal(9434769725128806); + expect(bids[1].adUnitId).to.equal('LD9434769725128806'); expect(bids[1].sizes).to.have.lengthOf(1); expect(bids[1].sizes[0][0]).to.equal(300); expect(bids[1].sizes[0][1]).to.equal(600); From 2d0b75c61f836d54384f7d706328a4e101f2f5c8 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 10 Sep 2019 12:44:36 -0400 Subject: [PATCH 1484/1594] fix several issues in appnexus video bids (#4154) --- modules/appnexusBidAdapter.js | 50 +++++++++--------- src/video.js | 1 + test/spec/modules/appnexusBidAdapter_spec.js | 54 ++++++++++++++++++-- 3 files changed, 78 insertions(+), 27 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 730ca18ce84..5b682f747e2 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -6,6 +6,7 @@ import { BANNER, NATIVE, VIDEO, ADPOD } from '../src/mediaTypes'; import { auctionManager } from '../src/auctionManager'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; +import { OUTSTREAM, INSTREAM } from '../src/video'; const BIDDER_CODE = 'appnexus'; const URL = '//ib.adnxs.com/ut/v3/prebid'; @@ -480,37 +481,40 @@ function newBid(serverBid, rtbBid, bidderRequest) { } 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, - vastUrl: rtbBid.rtb.video.asset_url, vastImpUrl: rtbBid.notify_url, ttl: 3600 }); const videoContext = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); - if (videoContext === ADPOD) { - const iabSubCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); - bid.meta = Object.assign({}, bid.meta, { iabSubCatId }); - bid.video = { - context: ADPOD, - durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), - }; - } - - // This supports Outstream Video - if (rtbBid.renderer_url) { - const rendererOptions = utils.deepAccess( - bidderRequest.bids[0], - 'renderer.options' - ); - - Object.assign(bid, { - adResponse: serverBid, - renderer: newRenderer(bid.adUnitCode, rtbBid, rendererOptions) - }); - bid.adResponse.ad = bid.adResponse.ads[0]; - bid.adResponse.ad.video = bid.adResponse.ad.rtb.video; + switch (videoContext) { + case ADPOD: + const iabSubCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); + bid.meta = Object.assign({}, bid.meta, { iabSubCatId }); + bid.video = { + context: ADPOD, + durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), + }; + 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 = utils.deepAccess(videoBid, 'renderer.options'); + bid.renderer = newRenderer(bid.adUnitCode, rtbBid, rendererOptions); + } + break; + case INSTREAM: + bid.vastUrl = rtbBid.rtb.video.asset_url; + break; } } else if (rtbBid.rtb[NATIVE]) { const nativeAd = rtbBid.rtb[NATIVE]; diff --git a/src/video.js b/src/video.js index f59ff78a32a..57f44a76764 100644 --- a/src/video.js +++ b/src/video.js @@ -6,6 +6,7 @@ import { hook } from './hook'; const VIDEO_MEDIA_TYPE = 'video'; export const OUTSTREAM = 'outstream'; +export const INSTREAM = 'instream'; /** * Helper functions for working with video-enabled adUnits diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index d5b11e95351..ef3f3eef6b3 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -780,7 +780,7 @@ describe('AppNexusAdapter', function () { expect(result.length).to.equal(0); }); - it('handles non-banner media responses', function () { + it('handles outstream video responses', function () { let response = { 'tags': [{ 'uuid': '84ab500420319d', @@ -790,7 +790,7 @@ describe('AppNexusAdapter', function () { 'notify_url': 'imptracker.com', 'rtb': { 'video': { - 'content': '' + 'content': '' } }, 'javascriptTrackers': '' @@ -800,7 +800,47 @@ describe('AppNexusAdapter', function () { let bidderRequest = { bids: [{ bidId: '84ab500420319d', - adUnitCode: 'code' + 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': 'http://sample.vastURL.com/here/vid' + } + }, + 'javascriptTrackers': '' + }] + }] + }; + let bidderRequest = { + bids: [{ + bidId: '84ab500420319d', + adUnitCode: 'code', + mediaTypes: { + video: { + context: 'instream' + } + } }] } @@ -821,7 +861,7 @@ describe('AppNexusAdapter', function () { 'notify_url': 'imptracker.com', 'rtb': { 'video': { - 'content': '', + 'asset_url': 'http://sample.vastURL.com/here/adpod', 'duration_ms': 30000, } }, @@ -846,6 +886,7 @@ describe('AppNexusAdapter', function () { 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); }); @@ -912,6 +953,11 @@ describe('AppNexusAdapter', function () { options: { adText: 'configured' } + }, + mediaTypes: { + video: { + context: 'outstream' + } } }] }; From 7990f4bf06d784820b90611c1a032e3f877715f9 Mon Sep 17 00:00:00 2001 From: TJ Eastmond Date: Tue, 10 Sep 2019 13:42:28 -0400 Subject: [PATCH 1485/1594] S2s testing disable client side (#4123) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * reverted error merge * New testServerOnly flag * Tests and a bug fix * Removed dead code * Fixes requested in review * Check each adUnit * isTestingServerOnly changes per Eric * Fixed IE 11 bug * More tests * improved test case names --- .gitignore | 3 + src/adapterManager.js | 28 ++++- test/fixtures/fixtures.js | 61 ++++++++++ test/spec/unit/core/adapterManager_spec.js | 133 ++++++++++++++++++++- 4 files changed, 216 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 88e849a35ad..c0452b7b3d0 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,9 @@ build/coverage/ .idea/ # if you remove the above rule, at least ignore the following: +# VS Code +.vscode/ + # User-specific stuff: # .idea/workspace.xml # .idea/tasks.xml diff --git a/src/adapterManager.js b/src/adapterManager.js index 7cf0122f669..6b1bc9508c8 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -118,7 +118,8 @@ function getAdUnitCopyForPrebidServer(adUnits) { adUnitsCopy.forEach((adUnit) => { // filter out client side bids adUnit.bids = adUnit.bids.filter((bid) => { - return includes(adaptersServerSide, bid.bidder) && (!doingS2STesting() || bid.finalSource !== s2sTestingModule.CLIENT); + return includes(adaptersServerSide, bid.bidder) && + (!doingS2STesting() || bid.finalSource !== s2sTestingModule.CLIENT); }).map((bid) => { bid.bid_id = utils.getUniqueIdentifierStr(); return bid; @@ -170,20 +171,33 @@ adapterManager.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTi let clientBidderCodes = bidderCodes; let clientTestAdapters = []; + if (_s2sConfig.enabled) { // if s2sConfig.bidderControl testing is turned on if (doingS2STesting()) { // get all adapters doing client testing - clientTestAdapters = s2sTestingModule.getSourceBidderMap(adUnits)[s2sTestingModule.CLIENT]; + const bidderMap = s2sTestingModule.getSourceBidderMap(adUnits); + clientTestAdapters = bidderMap[s2sTestingModule.CLIENT]; } // these are called on the s2s adapter let adaptersServerSide = _s2sConfig.bidders; // don't call these client side (unless client request is needed for testing) - clientBidderCodes = bidderCodes.filter((elm) => { - return !includes(adaptersServerSide, elm) || includes(clientTestAdapters, elm); - }); + clientBidderCodes = bidderCodes.filter(elm => + !includes(adaptersServerSide, elm) || includes(clientTestAdapters, elm) + ); + + const adUnitsContainServerRequests = adUnits => Boolean( + find(adUnits, adUnit => find(adUnit.bids, bid => ( + bid.bidSource || + (_s2sConfig.bidderControl && _s2sConfig.bidderControl[bid.bidder]) + ) && bid.finalSource === s2sTestingModule.SERVER)) + ); + + if (isTestingServerOnly() && adUnitsContainServerRequests(adUnits)) { + clientBidderCodes.length = 0; + } let adUnitsS2SCopy = getAdUnitCopyForPrebidServer(adUnits); let tid = utils.generateUUID(); @@ -331,6 +345,10 @@ function doingS2STesting() { return _s2sConfig && _s2sConfig.enabled && _s2sConfig.testing && s2sTestingModule; } +function isTestingServerOnly() { + return Boolean(doingS2STesting() && _s2sConfig.testServerOnly); +}; + function getSupportedMediaTypes(bidderCode) { let result = []; if (includes(adapterManager.videoAdapters, bidderCode)) result.push('video'); diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index 050ff90bc7a..2637bb30de6 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -1484,3 +1484,64 @@ export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, ad } return bid; } + +export function getServerTestingsAds() { + return [ + { + code: 'test_div_1', + sizes: [[728, 90]], + bids: [ + { + 'bidSource': { 'client': 0, 'server': 100 }, + 'bidder': 'rubicon' + }, + { + 'bidSource': { 'client': 100, 'server': 0 }, + 'bidder': 'appnexus' + } + ] + }, + { + code: 'test_div_2', + sizes: [[300, 250]], + bids: [ + { + 'bidSource': { 'client': 100, 'server': 0 }, + 'bidder': 'rubicon' + }, + { + 'bidSource': { 'client': 100, 'server': 0 }, + 'bidder': 'appnexus' + } + ] + }, + { + code: 'test_div_3', + sizes: [[300, 250]], + bids: [{ bidder: 'adequant' }] + }, + { + code: 'test_div_4', + sizes: [[300, 250]], + bids: [{ bidder: 'openx' }] + } + ]; +}; + +export const getServerTestingConfig = (config, override = {}) => + Object.assign({}, config, { + enabled: true, + testing: true, + testServerOnly: true, + bidders: ['appnexus', 'rubicon', 'openx'], + bidderControl: { + rubicon: { + bidSource: { server: 100, client: 0 }, + includeSourceKvp: true + }, + appnexus: { + bidSource: { server: 0, client: 100 }, + includeSourceKvp: true + } + } + }, override); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index f52aadba647..8eb1e21b229 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -1,8 +1,10 @@ import { expect } from 'chai'; -import adapterManager, { - gdprDataHandler -} from 'src/adapterManager'; -import { getAdUnits } from 'test/fixtures/fixtures'; +import adapterManager, { gdprDataHandler } from 'src/adapterManager'; +import { + getAdUnits, + getServerTestingConfig, + getServerTestingsAds +} from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; import { config } from 'src/config'; @@ -1142,5 +1144,128 @@ describe('adapterManager tests', function () { expect(bidRequests[0].gdprConsent).to.be.undefined; }); }); + + describe('s2sTesting - testServerOnly', () => { + beforeEach(() => { + config.setConfig({ s2sConfig: getServerTestingConfig(CONFIG) }); + }); + + afterEach(() => config.resetConfig()); + + const makeBidRequests = ads => { + let bidRequests = adapterManager.makeBidRequests( + ads, 1111, 2222, 1000 + ); + + bidRequests.sort((a, b) => { + if (a.bidderCode < b.bidderCode) return -1; + if (a.bidderCode > b.bidderCode) return 1; + return 0; + }); + + return bidRequests; + }; + + const removeAdUnitsBidSource = adUnits => adUnits.map(adUnit => { + const newAdUnit = { ...adUnit }; + newAdUnit.bids = newAdUnit.bids.map(bid => { + if (bid.bidSource) delete bid.bidSource; + return bid; + }); + return newAdUnit; + }); + + it('suppresses all client bids if there are server bids resulting from bidSource at the adUnit Level', () => { + const bidRequests = makeBidRequests(getServerTestingsAds()); + + expect(bidRequests).lengthOf(2); + + expect(bidRequests[0].bids).lengthOf(1); + expect(bidRequests[0].bids[0].bidder).equals('openx'); + expect(bidRequests[0].bids[0].finalSource).equals('server'); + + expect(bidRequests[0].bids).lengthOf(1); + expect(bidRequests[1].bids[0].bidder).equals('rubicon'); + expect(bidRequests[1].bids[0].finalSource).equals('server'); + }); + + // todo: update description + it('suppresses all, and only, client bids if there are bids resulting from bidSource at the adUnit Level', () => { + const ads = getServerTestingsAds(); + + // change this adUnit to be server based + ads[1].bids[1].bidSource.client = 0; + ads[1].bids[1].bidSource.server = 100; + + const bidRequests = makeBidRequests(ads); + + expect(bidRequests).lengthOf(3); + + expect(bidRequests[0].bids).lengthOf(1); + expect(bidRequests[0].bids[0].bidder).equals('appnexus'); + expect(bidRequests[0].bids[0].finalSource).equals('server'); + + expect(bidRequests[1].bids).lengthOf(1); + expect(bidRequests[1].bids[0].bidder).equals('openx'); + expect(bidRequests[1].bids[0].finalSource).equals('server'); + + expect(bidRequests[2].bids).lengthOf(1); + expect(bidRequests[2].bids[0].bidder).equals('rubicon'); + expect(bidRequests[2].bids[0].finalSource).equals('server'); + }); + + // we have a server call now + it('does not suppress client bids if no "test case" bids result in a server bid', () => { + const ads = getServerTestingsAds(); + + // change this adUnit to be client based + ads[0].bids[0].bidSource.client = 100; + ads[0].bids[0].bidSource.server = 0; + + const bidRequests = makeBidRequests(ads); + + expect(bidRequests).lengthOf(4); + + expect(bidRequests[0].bids).lengthOf(1); + expect(bidRequests[0].bids[0].bidder).equals('adequant'); + expect(bidRequests[0].bids[0].finalSource).equals('client'); + + expect(bidRequests[1].bids).lengthOf(2); + expect(bidRequests[1].bids[0].bidder).equals('appnexus'); + expect(bidRequests[1].bids[0].finalSource).equals('client'); + expect(bidRequests[1].bids[1].bidder).equals('appnexus'); + expect(bidRequests[1].bids[1].finalSource).equals('client'); + + expect(bidRequests[2].bids).lengthOf(1); + expect(bidRequests[2].bids[0].bidder).equals('openx'); + expect(bidRequests[2].bids[0].finalSource).equals('server'); + + expect(bidRequests[3].bids).lengthOf(2); + expect(bidRequests[3].bids[0].bidder).equals('rubicon'); + expect(bidRequests[3].bids[0].finalSource).equals('client'); + expect(bidRequests[3].bids[1].bidder).equals('rubicon'); + expect(bidRequests[3].bids[1].finalSource).equals('client'); + }); + + it( + 'should surpress client side bids if no ad unit bidSources are set, ' + + 'but bidderControl resolves to server', + () => { + const ads = removeAdUnitsBidSource(getServerTestingsAds()); + + const bidRequests = makeBidRequests(ads); + + expect(bidRequests).lengthOf(2); + + expect(bidRequests[0].bids).lengthOf(1); + expect(bidRequests[0].bids[0].bidder).equals('openx'); + expect(bidRequests[0].bids[0].finalSource).equals('server'); + + expect(bidRequests[1].bids).lengthOf(2); + expect(bidRequests[1].bids[0].bidder).equals('rubicon'); + expect(bidRequests[1].bids[0].finalSource).equals('server'); + } + ); + }); }); }); From 730c5619da3ee72f7c872c62a3716eea40ba9f9b Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 10 Sep 2019 11:55:49 -0700 Subject: [PATCH 1486/1594] New option to Include deal KVPs when enableSendAllBids === false (#4136) * new option to include KVPs which have deals when enableSendAllBids === false * updating tests to be more realistic --- src/targeting.js | 42 +++++++-- test/spec/unit/core/targeting_spec.js | 122 ++++++++++++++++++++++++++ 2 files changed, 158 insertions(+), 6 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index f9ed9e4e70c..33108f9a6a4 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -129,6 +129,40 @@ export function newTargeting(auctionManager) { }); }; + /** + * checks if bid has targeting set and belongs based on matching ad unit codes + * @return {boolean} true or false + */ + function bidShouldBeAddedToTargeting(bid, adUnitCodes) { + return bid.adserverTargeting && adUnitCodes && + ((utils.isArray(adUnitCodes) && includes(adUnitCodes, bid.adUnitCode)) || + (typeof adUnitCodes === 'string' && bid.adUnitCode === adUnitCodes)); + }; + + /** + * Returns targeting for any bids which have deals if alwaysIncludeDeals === true + */ + function getDealBids(adUnitCodes, bidsReceived) { + if (config.getConfig('targetingControls.alwaysIncludeDeals') === true) { + const standardKeys = TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); + + // we only want the top bid from bidders who have multiple entries per ad unit code + const bids = getHighestCpmBidsFromBidPool(bidsReceived, getHighestCpm); + + // populate targeting keys for the remaining bids if they have a dealId + return bids.map(bid => { + if (bid.dealId && bidShouldBeAddedToTargeting(bid, adUnitCodes)) { + return { + [bid.adUnitCode]: getTargetingMap(bid, standardKeys.filter( + key => typeof bid.adserverTargeting[key] !== 'undefined') + ) + }; + } + }).filter(bid => bid); // removes empty elements in array + } + return []; + }; + /** * Returns all ad server targeting for all ad units. * @param {string=} adUnitCode @@ -141,7 +175,7 @@ export function newTargeting(auctionManager) { // `alwaysUseBid=true`. If sending all bids is enabled, add targeting for losing bids. var targeting = getWinningBidTargeting(adUnitCodes, bidsReceived) .concat(getCustomBidTargeting(adUnitCodes, bidsReceived)) - .concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes, bidsReceived) : []); + .concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes, bidsReceived) : getDealBids(adUnitCodes, bidsReceived)); // store a reference of the targeting keys targeting.map(adUnitCode => { @@ -489,11 +523,7 @@ export function newTargeting(auctionManager) { // populate targeting keys for the remaining bids return bids.map(bid => { - if ( - bid.adserverTargeting && adUnitCodes && - ((utils.isArray(adUnitCodes) && includes(adUnitCodes, bid.adUnitCode)) || - (typeof adUnitCodes === 'string' && bid.adUnitCode === adUnitCodes)) - ) { + if (bidShouldBeAddedToTargeting(bid, adUnitCodes)) { return { [bid.adUnitCode]: getTargetingMap(bid, standardKeys.filter( key => typeof bid.adserverTargeting[key] !== 'undefined') diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index f4d3a5e0488..b165a2a21fb 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -32,6 +32,7 @@ const bid1 = { [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '0.53', [CONSTANTS.TARGETING_KEYS.DEAL]: '1234' }, + 'dealId': '1234', 'netRevenue': true, 'currency': 'USD', 'ttl': 300 @@ -330,6 +331,127 @@ describe('targeting tests', function () { expect(logErrorStub.calledOnce).to.be.true; }); + describe('targetingControls.alwaysIncludeDeals', function () { + let bid4; + + beforeEach(function() { + bid4 = utils.deepClone(bid1); + bid4.adserverTargeting = { + hb_deal: '4321', + hb_pb: '0.1', + hb_adid: '567891011', + hb_bidder: 'appnexus', + }; + bid4.bidder = bid4.bidderCode = 'appnexus'; + bid4.cpm = 0.1; // losing bid so not included if enableSendAllBids === false + bid4.dealId = '4321'; + enableSendAllBids = false; + + bidsReceived.push(bid4); + }); + + it('does not include losing deals when alwaysIncludeDeals not set', function () { + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // Rubicon wins bid and has deal, but alwaysIncludeDeals is false, so only top bid plus deal_id + // appnexus does not get sent since alwaysIncludeDeals is not defined + expect(targeting['/123456/header-bid-tag-0']).to.deep.equal({ + 'hb_deal_rubicon': '1234', + 'hb_deal': '1234', + 'hb_pb': '0.53', + 'hb_adid': '148018fe5e', + 'hb_bidder': 'rubicon', + 'foobar': '300x250' + }); + }); + + it('does not include losing deals when alwaysIncludeDeals set to false', function () { + config.setConfig({ + targetingControls: { + alwaysIncludeDeals: false + } + }); + + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // Rubicon wins bid and has deal, but alwaysIncludeDeals is false, so only top bid plus deal_id + // appnexus does not get sent since alwaysIncludeDeals is false + expect(targeting['/123456/header-bid-tag-0']).to.deep.equal({ + 'hb_deal_rubicon': '1234', // This is just how it works before this PR, always added no matter what for winner if they have deal + 'hb_deal': '1234', + 'hb_pb': '0.53', + 'hb_adid': '148018fe5e', + 'hb_bidder': 'rubicon', + 'foobar': '300x250' + }); + }); + + it('includes losing deals when alwaysIncludeDeals set to true and also winning deals bidder KVPs', function () { + config.setConfig({ + targetingControls: { + alwaysIncludeDeals: true + } + }); + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // Rubicon wins bid and has a deal, so all KVPs for them are passed (top plus bidder specific) + // Appnexus had deal so passed through + expect(targeting['/123456/header-bid-tag-0']).to.deep.equal({ + 'hb_deal_rubicon': '1234', + 'hb_deal': '1234', + 'hb_pb': '0.53', + 'hb_adid': '148018fe5e', + 'hb_bidder': 'rubicon', + 'foobar': '300x250', + 'hb_pb_rubicon': '0.53', + 'hb_adid_rubicon': '148018fe5e', + 'hb_bidder_rubicon': 'rubicon', + 'hb_deal_appnexus': '4321', + 'hb_pb_appnexus': '0.1', + 'hb_adid_appnexus': '567891011', + 'hb_bidder_appnexus': 'appnexus' + }); + }); + + it('includes winning bid even when it is not a deal, plus other deal KVPs', function () { + config.setConfig({ + targetingControls: { + alwaysIncludeDeals: true + } + }); + let bid5 = utils.deepClone(bid4); + bid5.adserverTargeting = { + hb_pb: '3.0', + hb_adid: '111111', + hb_bidder: 'pubmatic', + }; + bid5.bidder = bid5.bidderCode = 'pubmatic'; + bid5.cpm = 3.0; // winning bid! + delete bid5.dealId; // no deal with winner + bidsReceived.push(bid5); + + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // Pubmatic wins but no deal. So only top bid KVPs for them is sent + // Rubicon has a dealId so passed through + // Appnexus has a dealId so passed through + expect(targeting['/123456/header-bid-tag-0']).to.deep.equal({ + 'hb_bidder': 'pubmatic', + 'hb_adid': '111111', + 'hb_pb': '3.0', + 'foobar': '300x250', + 'hb_deal_rubicon': '1234', + 'hb_pb_rubicon': '0.53', + 'hb_adid_rubicon': '148018fe5e', + 'hb_bidder_rubicon': 'rubicon', + 'hb_deal_appnexus': '4321', + 'hb_pb_appnexus': '0.1', + 'hb_adid_appnexus': '567891011', + 'hb_bidder_appnexus': 'appnexus' + }); + }); + }); + it('selects the top bid when enableSendAllBids true', function () { enableSendAllBids = true; let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); From 958859a7edca6bddce7753aca294063fb64c24ab Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 10 Sep 2019 15:05:37 -0400 Subject: [PATCH 1487/1594] Prebid 2.32.0 Release --- package-lock.json | 925 ++++++++++++++++++++++++++-------------------- package.json | 2 +- 2 files changed, 534 insertions(+), 393 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9013350fb01..2f64dc20b23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.30.0-pre", + "version": "2.32.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,18 +14,18 @@ } }, "@babel/core": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", - "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.0.tgz", + "integrity": "sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", - "@babel/helpers": "^7.5.5", - "@babel/parser": "^7.5.5", - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5", + "@babel/generator": "^7.6.0", + "@babel/helpers": "^7.6.0", + "@babel/parser": "^7.6.0", + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.0", + "@babel/types": "^7.6.0", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -36,12 +36,12 @@ } }, "@babel/generator": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", - "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", + "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", "dev": true, "requires": { - "@babel/types": "^7.5.5", + "@babel/types": "^7.6.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0", @@ -241,14 +241,14 @@ } }, "@babel/helpers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", - "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.0.tgz", + "integrity": "sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ==", "dev": true, "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.0", + "@babel/types": "^7.6.0" } }, "@babel/highlight": { @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -405,9 +405,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", - "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.0.tgz", + "integrity": "sha512-tIt4E23+kw6TgL/edACZwP1OUKrjOTyMrFMLoT5IOFrfMRabCgekjqFd5o6PaAMildBu46oFkekIdMuGkkPEpA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -440,9 +440,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", - "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", + "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -527,9 +527,9 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", - "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz", + "integrity": "sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.4.4", @@ -560,12 +560,12 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", - "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.0.tgz", + "integrity": "sha512-jem7uytlmrRl3iCAuQyw8BpB4c4LWvSpvIeXKpMb+7j84lkx4m4mYr5ErAcmN5KM7B6BqrAvRGjBIbbzqCczew==", "dev": true, "requires": { - "regexp-tree": "^0.1.6" + "regexp-tree": "^0.1.13" } }, "@babel/plugin-transform-new-target": { @@ -684,9 +684,9 @@ } }, "@babel/preset-env": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", - "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.0.tgz", + "integrity": "sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -705,10 +705,10 @@ "@babel/plugin-transform-arrow-functions": "^7.2.0", "@babel/plugin-transform-async-to-generator": "^7.5.0", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.5.5", + "@babel/plugin-transform-block-scoping": "^7.6.0", "@babel/plugin-transform-classes": "^7.5.5", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.5.0", + "@babel/plugin-transform-destructuring": "^7.6.0", "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/plugin-transform-duplicate-keys": "^7.5.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", @@ -717,10 +717,10 @@ "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.5.0", + "@babel/plugin-transform-modules-commonjs": "^7.6.0", "@babel/plugin-transform-modules-systemjs": "^7.5.0", "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.6.0", "@babel/plugin-transform-new-target": "^7.4.4", "@babel/plugin-transform-object-super": "^7.5.5", "@babel/plugin-transform-parameters": "^7.4.4", @@ -733,7 +733,7 @@ "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.5.5", + "@babel/types": "^7.6.0", "browserslist": "^4.6.0", "core-js-compat": "^3.1.1", "invariant": "^2.2.2", @@ -742,37 +742,37 @@ } }, "@babel/template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", - "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" } }, "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz", + "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", + "@babel/generator": "^7.6.0", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.5.5", - "@babel/types": "^7.5.5", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" } }, "@babel/types": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", - "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -837,6 +837,15 @@ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", "dev": true }, + "@sinonjs/commons": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz", + "integrity": "sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==", + "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", @@ -846,6 +855,17 @@ "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", @@ -1015,7 +1035,8 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true }, "ansi-styles": { "version": "3.2.1", @@ -1186,12 +1207,6 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, - "array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1204,6 +1219,12 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, "array-includes": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", @@ -1249,18 +1270,6 @@ } } }, - "array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", - "dev": true - }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -1337,13 +1346,17 @@ "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + "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 + "dev": true, + "requires": { + "inherits": "2.0.1" + } } } }, @@ -2792,7 +2805,10 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "http-errors": { "version": "1.7.2", @@ -2816,7 +2832,8 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "qs": { "version": "6.7.0", @@ -2984,20 +3001,20 @@ } }, "browserslist": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", - "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz", + "integrity": "sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000984", - "electron-to-chromium": "^1.3.191", - "node-releases": "^1.1.25" + "caniuse-lite": "^1.0.30000989", + "electron-to-chromium": "^1.3.247", + "node-releases": "^1.1.29" } }, "browserstack": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", - "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz", + "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1" @@ -3016,9 +3033,9 @@ } }, "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.2.tgz", + "integrity": "sha512-iy9koArjAFCzGnx3ZvNA6Z0clIbbFgbdWQ0mKD3hO0krOrZh8UgA6qMKcZvwLJxS+D6iVR76+5/pV56yMNYTag==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -3307,9 +3324,9 @@ "dev": true }, "chokidar": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", - "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -3455,7 +3472,8 @@ "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=" + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true }, "collapse-white-space": { "version": "1.0.5", @@ -3639,12 +3657,16 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "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=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -3739,14 +3761,13 @@ "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==" }, "core-js-compat": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", - "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.2.1.tgz", + "integrity": "sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A==", "dev": true, "requires": { - "browserslist": "^4.6.2", - "core-js-pure": "3.1.4", - "semver": "^6.1.1" + "browserslist": "^4.6.6", + "semver": "^6.3.0" }, "dependencies": { "semver": { @@ -3757,12 +3778,6 @@ } } }, - "core-js-pure": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.1.4.tgz", - "integrity": "sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -3770,9 +3785,9 @@ "dev": true }, "coveralls": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", - "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.6.tgz", + "integrity": "sha512-Pgh4v3gCI4T/9VijVrm8Ym5v0OgjvGLKj3zTUwkvsCiwqae/p6VLzpsFNjQS2i6ewV7ef+DjFJ5TSKxYt/mCrA==", "dev": true, "requires": { "growl": "~> 1.10.0", @@ -4461,16 +4476,6 @@ "path-exists": "^3.0.0" } }, - "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" - } - }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", @@ -4576,12 +4581,6 @@ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", @@ -4721,15 +4720,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.215", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.215.tgz", - "integrity": "sha512-ZV3OnwF0FlIygwxAG2H92yt7WGjWBpawyFAFu8e9k7xJatY+BPowID0D0Bs3PMACYAJATEejw/I9cawO27ZvTg==", + "version": "1.3.254", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.254.tgz", + "integrity": "sha512-7I5/OkgR6JKy6RFLJeru0kc0RMmmMu1UnkHBKInFKRrg1/4EQKIqOaUqITSww/SZ1LqWwp1qc/LLoIGy449eYw==", "dev": true }, "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", + "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -4901,17 +4900,21 @@ } }, "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.2.tgz", + "integrity": "sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg==", "dev": true, "requires": { "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", "has": "^1.0.3", + "has-symbols": "^1.0.0", "is-callable": "^1.1.4", "is-regex": "^1.0.4", - "object-keys": "^1.0.12" + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.0.0", + "string.prototype.trimright": "^2.0.0" } }, "es-to-primitive": { @@ -4926,9 +4929,9 @@ } }, "es5-ext": { - "version": "0.10.50", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", - "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", + "version": "0.10.51", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.51.tgz", + "integrity": "sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==", "dev": true, "requires": { "es6-iterator": "~2.0.3", @@ -4993,16 +4996,28 @@ "es6-iterator": "~2.0.1", "es6-symbol": "3.1.1", "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } } }, "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz", + "integrity": "sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "d": "^1.0.1", + "es5-ext": "^0.10.51" } }, "es6-weak-map": { @@ -5159,16 +5174,6 @@ "esutils": "^2.0.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" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -5177,12 +5182,6 @@ "requires": { "ansi-regex": "^3.0.0" } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true } } }, @@ -5233,43 +5232,68 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" + "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=" + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "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==" + "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=" + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.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=" + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "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 + "dev": true, + "requires": { + "find-up": "^2.1.0" + } } } }, @@ -5296,68 +5320,116 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, "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=" + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.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=" + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "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==" + "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=" + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.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=" + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=" + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=" + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "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 + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } } } }, @@ -5408,9 +5480,9 @@ } }, "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", "dev": true }, "espree": { @@ -5448,9 +5520,9 @@ } }, "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, "esutils": { @@ -6030,12 +6102,16 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "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=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -6147,12 +6223,12 @@ } }, "follow-redirects": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", - "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz", + "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==", "dev": true, "requires": { - "debug": "^3.2.6" + "debug": "^3.0.0" }, "dependencies": { "debug": { @@ -6337,8 +6413,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6359,14 +6434,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6381,20 +6454,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6511,8 +6581,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6524,7 +6593,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6539,7 +6607,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6547,14 +6614,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6573,7 +6638,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6654,8 +6718,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6667,7 +6730,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6753,8 +6815,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -6790,7 +6851,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6810,7 +6870,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6854,21 +6913,19 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, "fun-hooks": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.5.tgz", - "integrity": "sha512-xaj0r9Ex0dvehX8MbQSK/5EYVAddyoaK2sGNuQWX8xNaCiHtr/4zD9J10Y2irkFIsuaxbYOsQBKXvTHzjO2IFQ==" + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.6.tgz", + "integrity": "sha512-0+CUJWTcx/vtm3qfvb9IfILItgDAq28lEsdEzu8622ttSVfFStDQTaSpU/sn2NyFXo5dN2qwwPLcqB/CvDkacg==" }, "function-bind": { "version": "1.1.1", @@ -7107,9 +7164,9 @@ "dev": true }, "globals-docs": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/globals-docs/-/globals-docs-2.4.0.tgz", - "integrity": "sha512-B69mWcqCmT3jNYmSxRxxOXWfzu3Go8NQXPfl2o0qPd1EEFhwW0dFUg9ztTu915zPQzqwIhWAlw6hmfIcCK4kkQ==", + "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 }, "globule": { @@ -7166,9 +7223,9 @@ } }, "graceful-fs": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.1.tgz", - "integrity": "sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", "dev": true }, "grapheme-splitter": { @@ -7207,12 +7264,14 @@ "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1", @@ -7222,12 +7281,18 @@ "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=" + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^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==" + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true }, "gulp-cli": { "version": "2.2.0", @@ -7258,12 +7323,14 @@ "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=" + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "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.0" } @@ -7272,6 +7339,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, "requires": { "invert-kv": "^1.0.0" } @@ -7279,52 +7347,92 @@ "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=" + "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" + } }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=" + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" + "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=" + "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=" + "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=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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=" + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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=" + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.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=" + "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=", + "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7334,28 +7442,53 @@ "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } }, "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true }, "yargs": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true + "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.0" + } }, "yargs-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=" + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } } } }, @@ -7575,15 +7708,16 @@ } }, "gulp-footer": { - "version": "github:prebid/gulp-footer#ff2b46e6376c7f04900357ff9f7b30f219fe5f8a", - "from": "github:prebid/gulp-footer#master", + "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": { - "event-stream": "3.3.4", "lodash._reescape": "^3.0.0", "lodash._reevaluate": "^3.0.0", "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.6.2" + "lodash.template": "^3.6.2", + "map-stream": "0.0.7" }, "dependencies": { "lodash._reinterpolate": { @@ -7979,9 +8113,9 @@ } }, "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz", + "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -8224,9 +8358,9 @@ "dev": true }, "highlight.js": { - "version": "9.15.9", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.9.tgz", - "integrity": "sha512-M0zZvfLr5p0keDMCAhNBp03XJbKBxUx5AfyfufMdFMEP4N/Xj6dh0IqC75ys7BAzceR34NgcvXjupRVaHBPPVQ==", + "version": "9.15.10", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz", + "integrity": "sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw==", "dev": true }, "hmac-drbg": { @@ -8266,13 +8400,10 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.2.tgz", - "integrity": "sha512-CyjlXII6LMsPMyUzxpTt8fzh5QwzGqPmQXgY/Jyf4Zfp27t/FvfhwoE/8laaMUcMy816CkWF20I7NeQhwwY88w==", - "dev": true, - "requires": { - "lru-cache": "^5.1.1" - } + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", + "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "dev": true }, "html-void-elements": { "version": "1.0.4", @@ -8354,7 +8485,10 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -8787,9 +8921,9 @@ "dev": true }, "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", "dev": true }, "is-running": { @@ -8868,9 +9002,9 @@ "dev": true }, "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.0.tgz", + "integrity": "sha512-pFTjpv/x5HRj8kbZ/Msxi9VrvtOMRBqaDi3OIcbwPI3OuH+r3lLxVWukLITBaOGJIbA/w2+M1eVmVa4XNQlAmQ==", "dev": true }, "isarray": { @@ -9094,9 +9228,9 @@ } }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" @@ -9230,12 +9364,6 @@ "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", "dev": true }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -9314,9 +9442,9 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" @@ -9386,10 +9514,13 @@ } }, "karma-firefox-launcher": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.2.0.tgz", + "integrity": "sha512-j9Zp8M8+VLq1nI/5xZGfzeaEPtGQ/vk3G+Y8vpmFWLvKLNZ2TDjD6cu2dUu7lDbu1HXNgatsAX4jgCZTkR9qhQ==", + "dev": true, + "requires": { + "is-wsl": "^2.1.0" + } }, "karma-ie-launcher": { "version": "1.0.0", @@ -9986,12 +10117,13 @@ "dev": true }, "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==", + "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": "^3.0.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "lru-queue": { @@ -10521,7 +10653,10 @@ "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 + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -10807,9 +10942,9 @@ "dev": true }, "nise": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.1.tgz", - "integrity": "sha512-edFWm0fsFG2n318rfEnKlTZTkjlbVOFF9XIA+fj+Ed+Qz1laYW2lobwavWoMzGrYDHH1EpiNJgDfvGnkZztR/g==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", + "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", "dev": true, "requires": { "@sinonjs/formatio": "^3.2.1", @@ -10823,7 +10958,11 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", - "dev": true + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } }, "lolex": { "version": "4.2.0", @@ -10894,9 +11033,9 @@ } }, "node-releases": { - "version": "1.1.26", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", - "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", + "version": "1.1.30", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.30.tgz", + "integrity": "sha512-BHcr1g6NeUH12IL+X3Flvs4IOnl1TL0JczUhEZjDE+FXXPQcVCNr8NEPb01zqGxzhTpdyJL5GXemaCW7aw6Khw==", "dev": true, "requires": { "semver": "^5.3.0" @@ -10991,7 +11130,8 @@ "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=" + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true }, "oauth-sign": { "version": "0.9.0", @@ -11042,6 +11182,12 @@ } } }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -11201,6 +11347,14 @@ "dev": true, "requires": { "is-wsl": "^1.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } } }, "optimist": { @@ -11304,9 +11458,9 @@ "dev": true }, "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -11366,9 +11520,9 @@ } }, "parse-domain": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.1.tgz", - "integrity": "sha512-k/tkc7tfcoGfaUOCG5DuPNX+dt6UBqRWU9EtR0rA9esi5GpOY0OGEgprfylmYx8pykQbdBTYHLaM/UwFHXuZKA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.2.tgz", + "integrity": "sha512-ywE9/YZwJZ8b2viJybvAyu9xO+4qbuLr0Jx73zoL8bHsDdDrFKWKGJKKEuvyNT0ZN1whQGnUAwdQMnsU0dqlPA==", "dev": true, "requires": { "chai": "^4.2.0", @@ -11937,9 +12091,9 @@ "dev": true }, "psl": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz", - "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", + "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==", "dev": true }, "public-encrypt": { @@ -12263,9 +12417,9 @@ } }, "regexp-tree": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", - "integrity": "sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.13.tgz", + "integrity": "sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw==", "dev": true }, "regexpp": { @@ -12275,13 +12429,13 @@ "dev": true }, "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.5.tgz", + "integrity": "sha512-FpI67+ky9J+cDizQUJlIlNZFKual/lUkFr1AG6zOCpwZ9cLrg8UUVakyUQJD7fCDIe9Z2nwTQJNPyonatNmDFQ==", "dev": true, "requires": { "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", + "regenerate-unicode-properties": "^8.1.0", "regjsgen": "^0.5.0", "regjsparser": "^0.6.0", "unicode-match-property-ecmascript": "^1.0.4", @@ -12748,9 +12902,9 @@ } }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "semver-greatest-satisfied-range": { @@ -12943,7 +13097,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -12985,16 +13142,10 @@ "dev": true }, "shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" - } + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true }, "shelljs": { "version": "0.8.3", @@ -13639,6 +13790,26 @@ "function-bind": "^1.0.2" } }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -13664,6 +13835,7 @@ "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" } @@ -13847,9 +14019,9 @@ "dev": true }, "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", "dev": true, "requires": { "setimmediate": "^1.0.4" @@ -14407,9 +14579,9 @@ } }, "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, "uri-js": { @@ -14506,24 +14678,6 @@ "requires": { "lru-cache": "4.1.x", "tmp": "0.0.x" - }, - "dependencies": { - "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" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } } }, "util": { @@ -14556,9 +14710,9 @@ "dev": true }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", "dev": true }, "v8flags": { @@ -14799,9 +14953,9 @@ } }, "wdio-browserstack-service": { - "version": "0.1.18", - "resolved": "https://registry.npmjs.org/wdio-browserstack-service/-/wdio-browserstack-service-0.1.18.tgz", - "integrity": "sha512-6tISYMKzwr2oxx0yi2Q4GoFC2Mbq81iHhqxayacC4XgFR7QbmQkxwV8JPeq590AXhuhPqqmyuEGkMqc9fo/UoQ==", + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/wdio-browserstack-service/-/wdio-browserstack-service-0.1.19.tgz", + "integrity": "sha512-ZAq20McWrQy80FQst+4cn1l5WRP9u+9DOKif2TarxYFzw/EmhdNg9TFcXBT5dxH+LcP5v47v7mXMmsO7B3+92Q==", "dev": true, "requires": { "browserstack-local": "^1.3.7", @@ -15099,16 +15253,6 @@ "path-exists": "^3.0.0" } }, - "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" - } - }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", @@ -15225,12 +15369,6 @@ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -15285,15 +15423,15 @@ }, "dependencies": { "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", "dev": true }, "ejs": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz", - "integrity": "sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.1.tgz", + "integrity": "sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ==", "dev": true }, "ws": { @@ -16005,6 +16143,7 @@ "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.1", "strip-ansi": "^3.0.1" @@ -16014,6 +16153,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, "requires": { "number-is-nan": "^1.0.0" } @@ -16022,6 +16162,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -16081,9 +16222,9 @@ "dev": true }, "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yargs": { diff --git a/package.json b/package.json index cf061e9f357..e984419179b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.32.0-pre", + "version": "2.32.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 1b5f68f4e3b136d700bfcc23f9639894173df9c6 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 10 Sep 2019 15:19:14 -0400 Subject: [PATCH 1488/1594] increment pre version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2f64dc20b23..bb8263638fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.32.0", + "version": "2.33.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e984419179b..13744d61755 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.32.0", + "version": "2.33.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From fa21ea06194cd2bcfcfee5c1f2bbc799c0569a91 Mon Sep 17 00:00:00 2001 From: bretg Date: Wed, 11 Sep 2019 14:52:13 -0400 Subject: [PATCH 1489/1594] Rubicon doc: changing video test zone (#4187) --- modules/rubiconBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rubiconBidAdapter.md b/modules/rubiconBidAdapter.md index d9df95b5941..c6572e7b91f 100644 --- a/modules/rubiconBidAdapter.md +++ b/modules/rubiconBidAdapter.md @@ -72,7 +72,7 @@ globalsupport@rubiconproject.com for more information. params: { accountId: '7780', siteId: '87184', - zoneId: '413290', + zoneId: '412394', video: { language: 'en' } From f3bcfb6b559bcf7abec3387cde707f94bf334826 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Thu, 12 Sep 2019 16:42:06 -0400 Subject: [PATCH 1490/1594] added schain support to sonobi adapter (#4173) --- modules/sonobiBidAdapter.js | 4 ++++ test/spec/modules/sonobiBidAdapter_spec.js | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index 1d83f532eae..a9ce2dd3876 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -101,6 +101,10 @@ export const spec = { payload.digkeyv = digitrust.keyv; } + if (validBidRequests[0].schain) { + payload.schain = JSON.stringify(validBidRequests[0].schain) + } + // If there is no key_maker data, then don't make the request. if (isEmpty(data)) { return null; diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index a8443b9cad6..1701e21ceda 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -109,6 +109,22 @@ describe('SonobiBidAdapter', function () { userSync.canBidderRegisterSync.restore(); }); let bidRequest = [{ + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 0 + }, + ] + }, 'bidder': 'sonobi', 'params': { 'placement_id': '1a2b3c4d5e6f1a2b3c4d', @@ -350,6 +366,11 @@ describe('SonobiBidAdapter', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(bidRequests.data.ius).to.equal(1); }); + + it('should return a properly formatted request with schain defined', function () { + const bidRequests = spec.buildRequests(bidRequest, bidderRequests); + expect(JSON.parse(bidRequests.data.schain)).to.deep.equal(bidRequest[0].schain) + }) }) describe('.interpretResponse', function () { From 3915517ce62a4bfa47522595ca36b49009ae78dc Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Fri, 13 Sep 2019 10:30:00 -0700 Subject: [PATCH 1491/1594] if schain config is not defined then error should not be thrown (#4165) * if schain config is not defiend then error should not be thrown * relaxed mode nodes param not defined error handled * added test cases for config validation * a curly bracket was missing in the example --- modules/schain.js | 104 +++++++++++++++++-------------- modules/schain.md | 4 +- test/spec/modules/schain_spec.js | 19 +++++- 3 files changed, 76 insertions(+), 51 deletions(-) diff --git a/modules/schain.js b/modules/schain.js index 000b13615e5..a5797ba4b39 100644 --- a/modules/schain.js +++ b/modules/schain.js @@ -43,64 +43,63 @@ export function isSchainObjectValid(schainObject, returnOnError) { } // nodes: Array of objects + let isEachNodeIsValid = true; if (!isArray(schainObject.nodes)) { logError(schainErrorPrefix + `schain.nodes` + shouldBeAnArray); if (returnOnError) return false; - } - - // now validate each node - let isEachNodeIsValid = true; - schainObject.nodes.forEach(node => { - // asi: String - if (!isStr(node.asi)) { - isEachNodeIsValid = isEachNodeIsValid && false; - logError(schainErrorPrefix + `schain.nodes[].asi` + shouldBeAString); - } - - // sid: String - if (!isStr(node.sid)) { - isEachNodeIsValid = isEachNodeIsValid && false; - logError(schainErrorPrefix + `schain.nodes[].sid` + shouldBeAString); - } - - // hp: Integer - if (!isNumber(node.hp) || !isInteger(node.hp)) { - isEachNodeIsValid = isEachNodeIsValid && false; - logError(schainErrorPrefix + `schain.nodes[].hp` + shouldBeAnInteger); - } - - // rid: String [Optional] - if (hasOwn(node, 'rid')) { - if (!isStr(node.rid)) { + } else { + schainObject.nodes.forEach(node => { + // asi: String + if (!isStr(node.asi)) { isEachNodeIsValid = isEachNodeIsValid && false; - logError(schainErrorPrefix + `schain.nodes[].rid` + shouldBeAString); + logError(schainErrorPrefix + `schain.nodes[].asi` + shouldBeAString); } - } - // name: String [Optional] - if (hasOwn(node, 'name')) { - if (!isStr(node.name)) { + // sid: String + if (!isStr(node.sid)) { isEachNodeIsValid = isEachNodeIsValid && false; - logError(schainErrorPrefix + `schain.nodes[].name` + shouldBeAString); + logError(schainErrorPrefix + `schain.nodes[].sid` + shouldBeAString); } - } - // domain: String [Optional] - if (hasOwn(node, 'domain')) { - if (!isStr(node.domain)) { + // hp: Integer + if (!isNumber(node.hp) || !isInteger(node.hp)) { isEachNodeIsValid = isEachNodeIsValid && false; - logError(schainErrorPrefix + `schain.nodes[].domain` + shouldBeAString); + logError(schainErrorPrefix + `schain.nodes[].hp` + shouldBeAnInteger); } - } - // ext: Object [Optional] - if (hasOwn(node, 'ext')) { - if (!isPlainObject(node.ext)) { - isEachNodeIsValid = isEachNodeIsValid && false; - logError(schainErrorPrefix + `schain.nodes[].ext` + shouldBeAnObject); + // rid: String [Optional] + if (hasOwn(node, 'rid')) { + if (!isStr(node.rid)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].rid` + shouldBeAString); + } } - } - }); + + // name: String [Optional] + if (hasOwn(node, 'name')) { + if (!isStr(node.name)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].name` + shouldBeAString); + } + } + + // domain: String [Optional] + if (hasOwn(node, 'domain')) { + if (!isStr(node.domain)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].domain` + shouldBeAString); + } + } + + // ext: Object [Optional] + if (hasOwn(node, 'ext')) { + if (!isPlainObject(node.ext)) { + isEachNodeIsValid = isEachNodeIsValid && false; + logError(schainErrorPrefix + `schain.nodes[].ext` + shouldBeAnObject); + } + } + }); + } if (returnOnError && !isEachNodeIsValid) { return false; @@ -118,13 +117,22 @@ export function copySchainObjectInAdunits(adUnits, schainObject) { }); } +export function isValidSchainConfig(schainObject) { + if (schainObject === undefined) { + return false; + } + if (!isPlainObject(schainObject)) { + logError(schainErrorPrefix + 'schain config will not be passed to bidders as schain is not an object.'); + return false; + } + return true; +} + export function init(config) { let mode = MODE.STRICT; getGlobal().requestBids.before(function(fn, reqBidsConfigObj) { let schainObject = config.getConfig('schain'); - if (!isPlainObject(schainObject)) { - logError(schainErrorPrefix + 'schain config will not be passed to bidders as schain is not an object.'); - } else { + if (isValidSchainConfig(schainObject)) { if (isStr(schainObject.validation) && Object.values(MODE).indexOf(schainObject.validation) != -1) { mode = schainObject.validation; } diff --git a/modules/schain.md b/modules/schain.md index 9fe0c3bd0f5..f43cf0f0d07 100644 --- a/modules/schain.md +++ b/modules/schain.md @@ -12,7 +12,7 @@ Refer: ## Sample code for passing the schain object ``` pbjs.setConfig( { - "schain": + "schain": { "validation": "strict", "config": { "ver":"1.0", @@ -28,7 +28,7 @@ pbjs.setConfig( { "asi":"indirectseller-2.com", "sid":"00002", "hp":1 - }, + } ] } } diff --git a/test/spec/modules/schain_spec.js b/test/spec/modules/schain_spec.js index 02aaa4c47c4..8f5104f1822 100644 --- a/test/spec/modules/schain_spec.js +++ b/test/spec/modules/schain_spec.js @@ -1,6 +1,20 @@ -import {isSchainObjectValid, copySchainObjectInAdunits} from '../../../modules/schain'; +import {isValidSchainConfig, isSchainObjectValid, copySchainObjectInAdunits} from '../../../modules/schain'; import { expect } from 'chai'; +describe('#isValidSchainConfig: module config validation', function() { + it('if config is undefined or not an objct then return false', function() { + expect(isValidSchainConfig()).to.false; + expect(isValidSchainConfig('')).to.false; + expect(isValidSchainConfig([])).to.false; + expect(isValidSchainConfig(12)).to.false; + expect(isValidSchainConfig(3.14)).to.false; + }) + + it('if config is an object then return true', function() { + expect(isValidSchainConfig({})).to.true; + }) +}); + describe('#isSchainObjectValid: schain object validation', function() { let schainConfig; @@ -225,6 +239,9 @@ describe('#isSchainObjectValid: schain object validation', function() { ] }; expect(isSchainObjectValid(schainConfig, false)).to.true; + + schainConfig = {}; + expect(isSchainObjectValid(schainConfig, false)).to.true; }) }); From e4cc0811b808ce3785cde539d3a2357b4bc7852b Mon Sep 17 00:00:00 2001 From: bretg Date: Fri, 13 Sep 2019 14:23:53 -0400 Subject: [PATCH 1492/1594] Rubicon: updating test params (#4190) --- modules/rubiconBidAdapter.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/rubiconBidAdapter.md b/modules/rubiconBidAdapter.md index c6572e7b91f..540898f792e 100644 --- a/modules/rubiconBidAdapter.md +++ b/modules/rubiconBidAdapter.md @@ -28,9 +28,9 @@ globalsupport@rubiconproject.com for more information. { bidder: "rubicon", params: { - accountId: 1001, - siteId: 113932, - zoneId: 535510 + accountId: 14062, + siteId: 70608, + zoneId: 498816 } } ] @@ -45,9 +45,9 @@ globalsupport@rubiconproject.com for more information. { bidder: "rubicon", params: { - accountId: 1001, - siteId: 113932, - zoneId: 535510 + accountId: 14062, + siteId: 70608, + zoneId: 498816 } } ] From 59532e4bca4dc5305e32b54560801980575dbe88 Mon Sep 17 00:00:00 2001 From: Vladimir Fedoseev Date: Mon, 16 Sep 2019 09:05:33 +0300 Subject: [PATCH 1493/1594] myTargetBidAdapter: support currency config (#4188) --- modules/mytargetBidAdapter.js | 8 +++++- test/spec/modules/mytargetBidAdapter_spec.js | 30 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/modules/mytargetBidAdapter.js b/modules/mytargetBidAdapter.js index e5b6cc735ef..5b727f7043f 100644 --- a/modules/mytargetBidAdapter.js +++ b/modules/mytargetBidAdapter.js @@ -35,6 +35,12 @@ function getSiteName(referrer) { return sitename; } +function getCurrency() { + let currency = config.getConfig('currency.adServerCurrency'); + + return (currency === 'USD') ? currency : DEFAULT_CURRENCY; +} + function generateRandomId() { return Math.random().toString(16).substring(2); } @@ -60,7 +66,7 @@ export const spec = { page: referrer }, settings: { - currency: DEFAULT_CURRENCY, + currency: getCurrency(), windowSize: { width: window.screen.width, height: window.screen.height diff --git a/test/spec/modules/mytargetBidAdapter_spec.js b/test/spec/modules/mytargetBidAdapter_spec.js index 211d1df79a7..4e478fee1f0 100644 --- a/test/spec/modules/mytargetBidAdapter_spec.js +++ b/test/spec/modules/mytargetBidAdapter_spec.js @@ -1,4 +1,5 @@ import { expect } from 'chai'; +import { config } from 'src/config'; import { spec } from 'modules/mytargetBidAdapter'; describe('MyTarget Adapter', function() { @@ -114,6 +115,35 @@ describe('MyTarget Adapter', function() { expect(settings.windowSize.width).to.equal(window.screen.width); expect(settings.windowSize.height).to.equal(window.screen.height); }); + + it('should pass currency from currency.adServerCurrency', function() { + const configStub = sinon.stub(config, 'getConfig').callsFake( + key => key === 'currency.adServerCurrency' ? 'USD' : ''); + + let bidRequest = spec.buildRequests(bidRequests, bidderRequest); + let settings = bidRequest.data.settings; + + expect(settings).to.be.an('object'); + expect(settings.currency).to.equal('USD'); + 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); + + configStub.restore(); + }); + + it('should ignore currency other than "RUB" or "USD"', function() { + const configStub = sinon.stub(config, 'getConfig').callsFake( + key => key === 'currency.adServerCurrency' ? 'EUR' : ''); + + let bidRequest = spec.buildRequests(bidRequests, bidderRequest); + let settings = bidRequest.data.settings; + + expect(settings).to.be.an('object'); + expect(settings.currency).to.equal('RUB'); + + configStub.restore(); + }); }); describe('interpretResponse', function () { From 29066dd647276dc69d780bfeed10b3e9357fa1b5 Mon Sep 17 00:00:00 2001 From: DJ Rosenbaum Date: Mon, 16 Sep 2019 11:09:11 -0400 Subject: [PATCH 1494/1594] Update README.md (#4193) * Update README.md * Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b52e7d3f09..be07a27ddc1 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ prebid.requestBids({ *Note:* You need to have `NodeJS` 8.9.x or greater installed. -*Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To compily with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in it's setup. +*Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To comply with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in its setup. If you have a previous version of `gulp` installed globally, you'll need to remove it before installing `gulp-cli`. You can check if this is installed by running `gulp -v` and seeing the version that's listed in the `CLI` field of the output. If you have the `gulp` package installed globally, it's likely the same version that you'll see in the `Local` field. If you already have `gulp-cli` installed, it should be a lower major version (it's at version `2.0.1` at the time of the transition). From f60799fb110d0759a7c58ee0c10b458d7473b8f1 Mon Sep 17 00:00:00 2001 From: Alex Khmelnitsky Date: Mon, 16 Sep 2019 20:06:30 +0300 Subject: [PATCH 1495/1594] cedato bid adapter instream video support (#4153) --- modules/cedatoBidAdapter.js | 119 +++++++++++++++------ test/spec/modules/cedatoBidAdapter_spec.js | 12 ++- 2 files changed, 96 insertions(+), 35 deletions(-) diff --git a/modules/cedatoBidAdapter.js b/modules/cedatoBidAdapter.js index 155e6eda107..d81ae858869 100644 --- a/modules/cedatoBidAdapter.js +++ b/modules/cedatoBidAdapter.js @@ -1,6 +1,6 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER } from '../src/mediaTypes'; +import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'cedato'; const BID_URL = '//h.cedatoplayer.com/hb'; @@ -14,7 +14,7 @@ const NET_REVENUE = true; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [BANNER], + supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bid) { return !!( @@ -31,19 +31,23 @@ export const spec = { const params = req.params; const at = FIRST_PRICE; const site = { id: params.player_id, domain: document.domain }; - const device = { ua: navigator.userAgent, ip: '' }; + const device = { ua: navigator.userAgent }; const user = { id: getUserID() } const currency = CURRENCY; const tmax = bidderRequest.timeout; const imp = bidRequests.map(req => { - const banner = { 'format': getFormats(utils.deepAccess(req, 'mediaTypes.banner.sizes')) }; + const banner = getMediaType(req, 'banner'); + const video = getMediaType(req, 'video'); const bidfloor = params.bidfloor; const bidId = req.bidId; + const adUnitCode = req.adUnitCode; return { bidId, banner, + video, + adUnitCode, bidfloor, }; }); @@ -68,38 +72,24 @@ export const spec = { return { method: 'POST', - url: BID_URL, + url: params.bid_url || BID_URL, data: JSON.stringify(payload), + bidderRequest }; }, - interpretResponse: function(resp) { - if (resp.body === '') return []; - - const bids = resp.body.seatbid[0].bid.map(bid => { - const cpm = bid.price; - const requestId = bid.uuid; - const width = bid.w; - const height = bid.h; - const creativeId = bid.crid; - const dealId = bid.dealid; - const currency = resp.body.cur; - const netRevenue = NET_REVENUE; - const ttl = TTL; - const ad = bid.adm; + interpretResponse: function(resp, {bidderRequest}) { + resp = resp.body; + const bids = []; - return { - cpm, - requestId, - width, - height, - creativeId, - dealId, - currency, - netRevenue, - ttl, - ad, - }; + if (!resp) { + return bids; + } + + resp.seatbid[0].bid.map(serverBid => { + const bid = newBid(serverBid, bidderRequest); + bid.currency = resp.cur; + bids.push(bid); }); return bids; @@ -116,6 +106,73 @@ export const spec = { } } +function getMediaType(req, type) { + const { mediaTypes } = req; + + if (!mediaTypes) { + return; + } + + switch (type) { + case 'banner': + if (mediaTypes.banner) { + const { sizes } = mediaTypes.banner; + return { + format: getFormats(sizes) + }; + } + break; + + case 'video': + if (mediaTypes.video) { + const { playerSize, context } = mediaTypes.video; + return { + context: context, + format: getFormats(playerSize) + }; + } + } +} + +function newBid(serverBid, bidderRequest) { + const bidRequest = utils.getBidRequest(serverBid.uuid, [bidderRequest]); + + const cpm = serverBid.price; + const requestId = serverBid.uuid; + const width = serverBid.w; + const height = serverBid.h; + const creativeId = serverBid.crid; + const dealId = serverBid.dealid; + const mediaType = serverBid.media_type; + const netRevenue = NET_REVENUE; + const ttl = TTL; + + const bid = { + cpm, + requestId, + width, + height, + mediaType, + creativeId, + dealId, + netRevenue, + ttl, + }; + + if (mediaType == 'video') { + const videoContext = utils.deepAccess(bidRequest, 'mediaTypes.video.context'); + + if (videoContext == 'instream') { + bid.vastUrl = serverBid.vast_url; + bid.vastImpUrl = serverBid.notify_url; + } + } else { + bid.ad = serverBid.adm; + } + + return bid; +} + const getSync = (type, gdprConsent) => { const uuid = getUserID(); const syncUrl = SYNC_URL; diff --git a/test/spec/modules/cedatoBidAdapter_spec.js b/test/spec/modules/cedatoBidAdapter_spec.js index d6c1333c262..969c06a64a2 100644 --- a/test/spec/modules/cedatoBidAdapter_spec.js +++ b/test/spec/modules/cedatoBidAdapter_spec.js @@ -4,7 +4,7 @@ import {spec} from 'modules/cedatoBidAdapter'; describe('the cedato adapter', function () { function getValidBidObject() { return { - bidId: 123, + bidId: '2f4a613a702b6c', mediaTypes: { banner: { sizes: [[300, 250]] @@ -48,9 +48,10 @@ describe('the cedato adapter', function () { }); describe('interpretResponse', function() { - var serverResponse; + var bid, serverResponse, bidderRequest; beforeEach(function() { + bid = getValidBidObject(); serverResponse = { body: { bidid: '0.36157306192821', @@ -65,7 +66,7 @@ describe('the cedato adapter', function () { }, id: '0.75549202124378', adomain: 'cedato.com', - uuid: '2f4a613a702b6c', + uuid: bid.bidId, crid: '1450133326', adm: "
    \n\n\n", h: 250, @@ -77,10 +78,13 @@ describe('the cedato adapter', function () { cur: 'USD' } }; + bidderRequest = { + bids: [bid] + }; }); it('should return an array of bid responses', function() { - var responses = spec.interpretResponse(serverResponse); + var responses = spec.interpretResponse(serverResponse, {bidderRequest}); expect(responses).to.be.an('array').with.length(1); }); }); From c4564723ff127410935c4386a39b8d170bffc36e Mon Sep 17 00:00:00 2001 From: adxpremium <55161519+adxpremium@users.noreply.github.com> Date: Mon, 16 Sep 2019 21:02:13 +0200 Subject: [PATCH 1496/1594] Added adxpremium prebid analytics adapter (#4181) --- modules/adxpremiumAnalyticsAdapter.js | 160 ++++++++++++++++++++++++++ modules/adxpremiumAnalyticsAdapter.md | 41 +++++++ 2 files changed, 201 insertions(+) create mode 100644 modules/adxpremiumAnalyticsAdapter.js create mode 100644 modules/adxpremiumAnalyticsAdapter.md diff --git a/modules/adxpremiumAnalyticsAdapter.js b/modules/adxpremiumAnalyticsAdapter.js new file mode 100644 index 00000000000..2224759dc6a --- /dev/null +++ b/modules/adxpremiumAnalyticsAdapter.js @@ -0,0 +1,160 @@ +import { ajax } from '../src/ajax'; +import adapter from '../src/AnalyticsAdapter'; +import adapterManager from '../src/adapterManager'; +import CONSTANTS from '../src/constants.json'; +import * as utils from '../src/utils'; + +const analyticsType = 'endpoint'; +const url = 'https://adxpremium.services/graphql'; + +// Events needed +const { + EVENTS: { + AUCTION_INIT, + BID_REQUESTED, + BID_TIMEOUT, + BID_RESPONSE, + BID_WON, + AUCTION_END + } +} = CONSTANTS; + +// Memory objects +let completeObject = { + publisher_id: null, + auction_id: null, + referer: null, + screen_resolution: window.screen.width + 'x' + window.screen.height, + device_type: null, + geo: null, + events: [] +}; + +let adxpremiumAnalyticsAdapter = Object.assign(adapter({ url, analyticsType }), { + track({ eventType, args }) { + switch (eventType) { + case AUCTION_INIT: + auctionInit(args); + break; + case BID_REQUESTED: + bidRequested(args); + break; + case BID_RESPONSE: + bidResponse(args); + break; + case BID_WON: + bidWon(args); + break; + case BID_TIMEOUT: + bidTimeout(args); + break; + case AUCTION_END: + setTimeout(function () { sendEvent(completeObject) }, 3100); + break; + default: + break; + } + } +}); + +// DFP support +let googletag = window.googletag || {}; +googletag.cmd = googletag.cmd || []; +googletag.cmd.push(function() { + googletag.pubads().addEventListener('slotRenderEnded', args => { + console.log(Date.now() + ' GOOGLE SLOT: ' + JSON.stringify(args)); + }); +}); + +// Event handlers +let bidResponsesMapper = {}; + +function auctionInit(args) { + completeObject.auction_id = args.auctionId; + completeObject.publisher_id = adxpremiumAnalyticsAdapter.initOptions.pubId; + try { completeObject.referer = args.bidderRequests[0].refererInfo.referer.split('?')[0]; } catch (e) { console.log(e.message); } + completeObject.device_type = deviceType(); +} +function bidRequested(args) { + let tmpObject = { + type: 'REQUEST', + bidder_code: args.bidderCode, + event_timestamp: args.start, + bid_gpt_codes: {} + }; + + args.bids.forEach(bid => { + tmpObject.bid_gpt_codes[bid.adUnitCode] = bid.sizes; + }); + + completeObject.events.push(tmpObject); +} + +function bidResponse(args) { + let tmpObject = { + type: 'RESPONSE', + bidder_code: args.bidderCode, + event_timestamp: args.responseTimestamp, + size: args.size, + gpt_code: args.adUnitCode, + currency: args.currency, + creative_id: args.creativeId, + time_to_respond: args.timeToRespond, + cpm: args.cpm, + is_winning: false + }; + + bidResponsesMapper[args.requestId] = completeObject.events.push(tmpObject) - 1; +} + +function bidWon(args) { + let eventIndex = bidResponsesMapper[args.requestId]; + completeObject.events[eventIndex].is_winning = true; +} + +function bidTimeout(args) { /* TODO: implement timeout */ } + +// Methods +function deviceType() { + if ((/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(navigator.userAgent.toLowerCase()))) { + return 'tablet'; + } + if ((/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(navigator.userAgent.toLowerCase()))) { + return 'mobile'; + } + return 'desktop'; +} + +function sendEvent(completeObject) { + try { + let responseEvents = btoa(JSON.stringify(completeObject)); + let mutation = `mutation {createEvent(input: {event: {eventData: "${responseEvents}"}}) {event {createTime } } }`; + let dataToSend = JSON.stringify({ query: mutation }); + ajax(url, function () { console.log(Date.now() + ' Sending event to adxpremium server.') }, dataToSend, { + contentType: 'application/json', + method: 'POST' + }); + } catch (err) { console.log(err) } +} + +// save the base class function +adxpremiumAnalyticsAdapter.originEnableAnalytics = adxpremiumAnalyticsAdapter.enableAnalytics; + +// override enableAnalytics so we can get access to the config passed in from the page +adxpremiumAnalyticsAdapter.enableAnalytics = function (config) { + adxpremiumAnalyticsAdapter.initOptions = config.options; + + if (!config.options.pubId) { + utils.logError('Publisher ID (pubId) option is not defined. Analytics won\'t work'); + return; + } + + adxpremiumAnalyticsAdapter.originEnableAnalytics(config); // call the base class function +} + +adapterManager.registerAnalyticsAdapter({ + adapter: adxpremiumAnalyticsAdapter, + code: 'adxpremium' +}); + +export default adxpremiumAnalyticsAdapter; diff --git a/modules/adxpremiumAnalyticsAdapter.md b/modules/adxpremiumAnalyticsAdapter.md new file mode 100644 index 00000000000..b2a5efd653f --- /dev/null +++ b/modules/adxpremiumAnalyticsAdapter.md @@ -0,0 +1,41 @@ +# Overview + +Module Name: AdxPremium Analytics Adapter + +Module Type: Analytics Adapter + +Maintainer: info@luponmedia.com + +--- + +# Description + +Analytics adapter for luponmedia.com prebid platform. Contact [info@luponmedia.com]() if you have any questions about integration. + +--- + +# Integration + +AdxPremium Anaytics Adapter can be used as: + +- Part of the whole AdxPremium Header Bidding Ecosystem *(free)* + +- External Analytics tool for your Prebid script *(Paid)* + +##### AdxPremium Header Bidding Ecosystem + +Integration is as easy as adding the following lines of code: + +```javascript +pbjs.que.push(function () { + pbjs.enableAnalytics([{ + provider: 'adxpremium', + options: { + pubID: 12345678 + } + }); + }]); +}); +``` + +*Note*: To use AdxPremium Prebid Analytics Adapter, you have to be AdxPremium publisher and get the publisher ID as well as include the adapter in your **Prebid Core** script. From b50a95f86659f4442c3caceac0d99a7349764034 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Mon, 16 Sep 2019 15:21:40 -0700 Subject: [PATCH 1497/1594] feat(OAFLO-186): added support for schain (#4194) --- modules/openxBidAdapter.js | 19 ++- test/spec/modules/openxBidAdapter_spec.js | 175 ++++++++++++++++++---- 2 files changed, 160 insertions(+), 34 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 7be1023450f..a79343ab2ff 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from '../src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.7'; +const BIDDER_VERSION = '2.1.9'; let shouldSendBoPixel = true; @@ -243,9 +243,26 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { defaultParams.pubcid = bids[0].crumbs.pubcid; } + if (bids[0].schain) { + defaultParams.schain = serializeSupplyChain(bids[0].schain); + } + return defaultParams; } +function serializeSupplyChain(supplyChain) { + return `${supplyChain.ver},${supplyChain.complete}!${serializeSupplyChainNodes(supplyChain.nodes)}`; +} + +function serializeSupplyChainNodes(supplyChainNodes) { + const supplyChainNodePropertyOrder = ['asi', 'sid', 'hp', 'rid', 'name', 'domain']; + + return supplyChainNodes.map(supplyChainNode => { + return supplyChainNodePropertyOrder.map(property => supplyChainNode[property] || '') + .join(','); + }).join('!'); +} + function buildOXBannerRequest(bids, bidderRequest) { let customParamsForAllBids = []; let hasCustomParam = false; diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index cf8f4f8d62b..7476d06cf9a 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -394,39 +394,6 @@ describe('OpenxAdapter', function () { 'bidderRequestId': 'test-bid-request-1', 'auctionId': 'test-auction-1' }]; - const bidRequestsWithPlatformAndDelDomain = [{ - 'bidder': 'openx', - 'params': { - 'unit': '11', - 'delDomain': 'test-del-domain', - 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', - }, - 'adUnitCode': '/adunit-code/test-path', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - 'bidId': 'test-bid-id-1', - 'bidderRequestId': 'test-bid-request-1', - 'auctionId': 'test-auction-1' - }, { - 'bidder': 'openx', - 'params': { - 'unit': '11', - 'delDomain': 'test-del-domain', - 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', - }, - 'adUnitCode': '/adunit-code/test-path', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - 'bidId': 'test-bid-id-1', - 'bidderRequestId': 'test-bid-request-1', - 'auctionId': 'test-auction-1' - }]; it('should send bid request to openx url via GET, with mediaType specified as banner', function () { const request = spec.buildRequests(bidRequestsWithMediaType); @@ -450,6 +417,40 @@ describe('OpenxAdapter', function () { }); it('should send bid request to openx platform url via GET, if both params present', function () { + const bidRequestsWithPlatformAndDelDomain = [{ + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + }, + 'adUnitCode': '/adunit-code/test-path', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + }, + 'adUnitCode': '/adunit-code/test-path', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }]; + const request = spec.buildRequests(bidRequestsWithPlatformAndDelDomain); expect(request[0].url).to.equal(`//u.openx.net${URLBASE}`); expect(request[0].data.ph).to.equal(bidRequestsWithPlatform[0].params.platform); @@ -1000,6 +1001,114 @@ describe('OpenxAdapter', function () { expect(request[0].data.pubcid).to.equal('c1a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); }); }) + + describe('when schain is provided', function () { + let bidRequests; + let schainConfig; + const supplyChainNodePropertyOrder = ['asi', 'sid', 'hp', 'rid', 'name', 'domain']; + + beforeEach(function () { + schainConfig = { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + // omitted ext + }, + { + 'asi': 'exchange2.com', + 'sid': 'abcd', + 'hp': 1, + 'rid': 'bid-request-2', + // name field missing + 'domain': 'intermediary.com' + }, + { + 'asi': 'exchange3.com', + 'sid': '4321', + 'hp': 1, + // request id + // name field missing + 'domain': 'intermediary-2.com' + } + ] + }; + + bidRequests = [{ + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': '/adunit-code/test-path', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1', + 'schain': schainConfig + }]; + }); + + it('should send a schain parameter with the proper delimiter symbols', function () { + const request = spec.buildRequests(bidRequests); + const dataParams = request[0].data; + const numNodes = schainConfig.nodes.length; + + // each node will have a ! to denote beginning of a new node + expect(dataParams.schain.match(/!/g).length).to.equal(numNodes); + + // 1 comma in the front for version + // 5 commas per node + expect(dataParams.schain.match(/,/g).length).to.equal(numNodes * 5 + 1); + }); + + it('should send a schain with the right version', function () { + const request = spec.buildRequests(bidRequests); + const dataParams = request[0].data; + let serializedSupplyChain = dataParams.schain.split('!'); + let version = serializedSupplyChain.shift().split(',')[0]; + + expect(version).to.equal(bidRequests[0].schain.ver); + }); + + it('should send a schain with the right complete value', function () { + const request = spec.buildRequests(bidRequests); + const dataParams = request[0].data; + let serializedSupplyChain = dataParams.schain.split('!'); + let isComplete = serializedSupplyChain.shift().split(',')[1]; + + expect(isComplete).to.equal(String(bidRequests[0].schain.complete)); + }); + + it('should send all available params in the right order', function () { + const request = spec.buildRequests(bidRequests); + const dataParams = request[0].data; + let serializedSupplyChain = dataParams.schain.split('!'); + serializedSupplyChain.shift(); + + serializedSupplyChain.forEach((serializedNode, nodeIndex) => { + let nodeProperties = serializedNode.split(','); + + nodeProperties.forEach((nodeProperty, propertyIndex) => { + let node = schainConfig.nodes[nodeIndex]; + let key = supplyChainNodePropertyOrder[propertyIndex]; + + expect(nodeProperty).to.equal(node[key] ? String(node[key]) : '', + `expected node '${nodeIndex}' property '${nodeProperty}' to key '${key}' to be the same value`) + }); + }); + }); + }); }); describe('buildRequests for video', function () { From 017a8f0cdac9a0d0521e56a305e8632f770eb99a Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Mon, 16 Sep 2019 18:45:31 -0400 Subject: [PATCH 1498/1594] Sonobi - send entire userid payload (#4196) * added userid param to pass the entire userId payload to sonobis bid request endpoint * removed console log git p * fixed lint --- modules/sonobiBidAdapter.js | 3 ++ test/spec/modules/sonobiBidAdapter_spec.js | 35 +++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index a9ce2dd3876..a0390a981a5 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -104,6 +104,9 @@ export const spec = { if (validBidRequests[0].schain) { payload.schain = JSON.stringify(validBidRequests[0].schain) } + if (deepAccess(validBidRequests[0], 'userId') && Object.keys(validBidRequests[0].userId).length > 0) { + payload.userid = JSON.stringify(validBidRequests[0].userId); + } // If there is no key_maker data, then don't make the request. if (isEmpty(data)) { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 1701e21ceda..dc536846ae2 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -370,7 +370,40 @@ describe('SonobiBidAdapter', function () { it('should return a properly formatted request with schain defined', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(JSON.parse(bidRequests.data.schain)).to.deep.equal(bidRequest[0].schain) - }) + }); + + it('should return a properly formatted request with userid as a JSON-encoded set of User ID results', function () { + bidRequest[0].userId = {'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101'}; + bidRequest[1].userId = {'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101'}; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests); + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json'); + expect(bidRequests.method).to.equal('GET'); + expect(bidRequests.data.ref).not.to.be.empty; + expect(bidRequests.data.s).not.to.be.empty; + expect(JSON.parse(bidRequests.data.userid)).to.eql({'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101'}); + }); + + it('should return a properly formatted request with userid omitted if there are no userIds', function () { + bidRequest[0].userId = {}; + bidRequest[1].userId = {}; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests); + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json'); + expect(bidRequests.method).to.equal('GET'); + expect(bidRequests.data.ref).not.to.be.empty; + expect(bidRequests.data.s).not.to.be.empty; + expect(bidRequests.data.userid).to.equal(undefined); + }); + + it('should return a properly formatted request with userid omitted', function () { + bidRequest[0].userId = undefined; + bidRequest[1].userId = undefined; + const bidRequests = spec.buildRequests(bidRequest, bidderRequests); + expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json'); + expect(bidRequests.method).to.equal('GET'); + expect(bidRequests.data.ref).not.to.be.empty; + expect(bidRequests.data.s).not.to.be.empty; + expect(bidRequests.data.userid).to.equal(undefined); + }); }) describe('.interpretResponse', function () { From 94488e4de0991d222e75b6806bc717c86d7832b3 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Mon, 16 Sep 2019 15:53:13 -0700 Subject: [PATCH 1499/1594] OpenX Adapter fix: updating outdated video examples (#4198) --- modules/openxBidAdapter.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/openxBidAdapter.md b/modules/openxBidAdapter.md index 042399cf023..965b8ee1948 100644 --- a/modules/openxBidAdapter.md +++ b/modules/openxBidAdapter.md @@ -75,12 +75,8 @@ var adUnits = [ params: { unit: '1611023124', delDomain: 'PUBLISHER-d.openx.net', - openrtb: { - imp: [{ - video: { - mimes: ['video/x-ms-wmv, video/mp4'] - } - }] + video: { + mimes: ['video/x-ms-wmv, video/mp4'] } } }] From e98184947a2111e5a3078fa708beceeb8308e490 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Durgeat Date: Tue, 17 Sep 2019 15:44:54 +0200 Subject: [PATCH 1500/1594] userId - Add support for refreshing the cached user id (#4082) * [userId] Added support for refreshing the cached user id: refreshInSeconds storage parameter, related tests and implementation in id5 module * [userId] Added support for refreshing the cached user id: refreshInSeconds storage parameter, related tests and implementation in id5 module * UserId - ID5 - Updated doc with new contact point for partners * UserId - Merged getStoredValue and getStoredDate * [UserId] - ID5 - Moved back ID5 in ./modules * UserId - ID5 - Fixed incorrect GDPR condition * [UserId] - Doc update and test cleanup --- integrationExamples/gpt/userId_example.html | 5 +- modules/id5IdSystem.js | 20 +++--- modules/userId/index.js | 49 +++++++++----- modules/userId/userId.md | 5 +- test/spec/modules/userId_spec.js | 74 ++++++++++++--------- 5 files changed, 93 insertions(+), 60 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 5878d05aecd..9e1cd01f8fa 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -143,12 +143,13 @@ }, { name: "id5Id", params: { - partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one contact@id5.io + partner: 173 //Set your real ID5 partner ID here for production, please ask for one at http://id5.io/prebid }, storage: { type: "cookie", name: "id5id", - expires: 90 + expires: 90, + refreshInSeconds: 8*3600 // Refresh frequency of cookies, defaulting to 'expires' }, }, { diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js index 7ed1fdf6bf3..85619ba51ba 100644 --- a/modules/id5IdSystem.js +++ b/modules/id5IdSystem.js @@ -18,9 +18,9 @@ export const id5IdSubmodule = { name: 'id5Id', /** * decode the stored id value for passing to bid requests - * @function - * @param {{ID5ID:Object}} value - * @returns {{id5id:String}} + * @function decode + * @param {(Object|string)} value + * @returns {(Object|undefined)} */ decode(value) { return (value && typeof value['ID5ID'] === 'string') ? { 'id5id': value['ID5ID'] } : undefined; @@ -30,16 +30,18 @@ export const id5IdSubmodule = { * @function * @param {SubmoduleParams} [configParams] * @param {ConsentData} [consentData] - * @returns {function(callback:function)} + * @param {(Object|undefined)} cacheIdObj + * @returns {(Object|function(callback:function))} */ - getId(configParams, consentData) { + getId(configParams, consentData, cacheIdObj) { if (!configParams || typeof configParams.partner !== 'number') { utils.logError(`User ID - ID5 submodule requires partner to be defined as a number`); - return; + return undefined; } - const hasGdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0; + const hasGdpr = (typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0; const gdprConsentString = hasGdpr ? consentData.consentString : ''; - const url = `https://id5-sync.com/g/v1/${configParams.partner}.json?gdpr=${hasGdpr}&gdpr_consent=${gdprConsentString}`; + const storedUserId = this.decode(cacheIdObj); + const url = `https://id5-sync.com/g/v1/${configParams.partner}.json?1puid=${storedUserId ? storedUserId.id5id : ''}&gdpr=${hasGdpr}&gdpr_consent=${gdprConsentString}`; return function (callback) { ajax(url, response => { @@ -52,7 +54,7 @@ export const id5IdSubmodule = { } } callback(responseObj); - }, undefined, { method: 'GET' }); + }, undefined, { method: 'GET', withCredentials: true }); } } }; diff --git a/modules/userId/index.js b/modules/userId/index.js index 98d99f7d333..8a70a4bbf3c 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -13,6 +13,7 @@ * @name Submodule#getId * @param {SubmoduleParams} configParams * @param {ConsentData} consentData + * @param {(Object|undefined)} cacheIdObj * @return {(Object|function)} id data or a callback, the callback is called on the auction end event */ @@ -43,7 +44,8 @@ * @typedef {Object} SubmoduleStorage * @property {string} type - browser storage type (html5 or cookie) * @property {string} name - key name to use when saving/reading to local storage or cookies - * @property {(number|undefined)} expires - time to live for browser cookie + * @property {number} expires - time to live for browser storage in days + * @property {(number|undefined)} refreshInSeconds - if not empty, this value defines the maximum time span in seconds before refreshing user ID stored in browser */ /** @@ -112,18 +114,23 @@ export function setSubmoduleRegistry(submodules) { /** * @param {SubmoduleStorage} storage - * @param {string} value - * @param {(number|string)} expires + * @param {(Object|string)} value */ -function setStoredValue(storage, value, expires) { +function setStoredValue(storage, value) { try { const valueStr = utils.isPlainObject(value) ? JSON.stringify(value) : value; - const expiresStr = (new Date(Date.now() + (expires * (60 * 60 * 24 * 1000)))).toUTCString(); + const expiresStr = (new Date(Date.now() + (storage.expires * (60 * 60 * 24 * 1000)))).toUTCString(); if (storage.type === COOKIE) { utils.setCookie(storage.name, valueStr, expiresStr); + if (typeof storage.refreshInSeconds === 'number') { + utils.setCookie(`${storage.name}_last`, new Date().toUTCString(), expiresStr); + } } else if (storage.type === LOCAL_STORAGE) { localStorage.setItem(`${storage.name}_exp`, expiresStr); localStorage.setItem(storage.name, encodeURIComponent(valueStr)); + if (typeof storage.refreshInSeconds === 'number') { + localStorage.setItem(`${storage.name}_last`, new Date().toUTCString()); + } } } catch (error) { utils.logError(error); @@ -132,21 +139,23 @@ function setStoredValue(storage, value, expires) { /** * @param {SubmoduleStorage} storage + * @param {String|undefined} key optional key of the value * @returns {string} */ -function getStoredValue(storage) { +function getStoredValue(storage, key = undefined) { + const storedKey = key ? `${storage.name}_${key}` : storage.name; let storedValue; try { if (storage.type === COOKIE) { - storedValue = utils.getCookie(storage.name); + storedValue = utils.getCookie(storedKey); } else if (storage.type === LOCAL_STORAGE) { const storedValueExp = localStorage.getItem(`${storage.name}_exp`); // empty string means no expiration set if (storedValueExp === '') { - storedValue = localStorage.getItem(storage.name); + storedValue = localStorage.getItem(storedKey); } else if (storedValueExp) { if ((new Date(storedValueExp)).getTime() - Date.now() > 0) { - storedValue = decodeURIComponent(localStorage.getItem(storage.name)); + storedValue = decodeURIComponent(localStorage.getItem(storedKey)); } } } @@ -188,7 +197,7 @@ function processSubmoduleCallbacks(submodules) { // if valid, id data should be saved to cookie/html storage if (idObj) { if (submodule.config.storage) { - setStoredValue(submodule.config.storage, idObj, submodule.config.storage.expires); + setStoredValue(submodule.config.storage, idObj); } // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.submodule.decode(idObj); @@ -244,7 +253,7 @@ function initializeSubmodulesAndExecuteCallbacks() { if (typeof initializedSubmodules === 'undefined') { initializedSubmodules = initSubmodules(submodules, gdprDataHandler.getConsentData()); if (initializedSubmodules.length) { - // list of sumodules that have callbacks that need to be executed + // list of submodules that have callbacks that need to be executed const submodulesWithCallbacks = initializedSubmodules.filter(item => utils.isFn(item.callback)); if (submodulesWithCallbacks.length) { @@ -252,7 +261,7 @@ function initializeSubmodulesAndExecuteCallbacks() { events.on(CONSTANTS.EVENTS.AUCTION_END, function auctionEndHandler() { events.off(CONSTANTS.EVENTS.AUCTION_END, auctionEndHandler); - // when syncDelay is zero, process callbacks now, otherwise dealy process with a setTimeout + // when syncDelay is zero, process callbacks now, otherwise delay process with a setTimeout if (syncDelay > 0) { setTimeout(function() { processSubmoduleCallbacks(submodulesWithCallbacks); @@ -314,16 +323,22 @@ function initSubmodules(submodules, consentData) { if (storedId) { // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.submodule.decode(storedId); - } else { + } + let refreshNeeded = false; + if (typeof submodule.config.storage.refreshInSeconds === 'number') { + const storedDate = new Date(getStoredValue(submodule.config.storage, 'last')); + refreshNeeded = storedDate && (Date.now() - storedDate.getTime() > submodule.config.storage.refreshInSeconds * 1000); + } + if (!storedId || refreshNeeded) { // getId will return user id data or a function that will load the data - const getIdResult = submodule.submodule.getId(submodule.config.params, consentData); + const getIdResult = submodule.submodule.getId(submodule.config.params, consentData, storedId); // If the getId result has a type of function, it is asynchronous and cannot be called until later if (typeof getIdResult === 'function') { submodule.callback = getIdResult; - } else { + } else if (getIdResult) { // A getId result that is not a function is assumed to be valid user id data, which should be saved to users local storage or cookies - setStoredValue(submodule.config.storage, getIdResult, submodule.config.storage.expires); + setStoredValue(submodule.config.storage, getIdResult); // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.submodule.decode(getIdResult); } @@ -332,7 +347,7 @@ function initSubmodules(submodules, consentData) { // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.config.value; } else { - const result = submodule.submodule.getId(submodule.config.params, consentData); + const result = submodule.submodule.getId(submodule.config.params, consentData, undefined); if (typeof result === 'function') { submodule.callback = result; } else { diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 04bd34d13b9..623aeaa160e 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -25,12 +25,13 @@ pbjs.setConfig({ }, { name: "id5Id", params: { - partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one at http://id5.io/prebid + partner: 173 //Set your real ID5 partner ID here for production, please ask for one at http://id5.io/prebid }, storage: { type: "cookie", name: "id5id", - expires: 5 + expires: 5, // Expiration of cookies in days + refreshInSeconds: 8*3600 // User Id cache lifetime in seconds, defaulting to 'expires' } }, { name: 'identityLink', diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 13f35b68545..04aaec5baa7 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -1,16 +1,11 @@ -import { - init, - requestBidsHook, - setSubmoduleRegistry, - syncDelay, - attachIdSystem -} from 'modules/userId/index.js'; +import {attachIdSystem, init, requestBidsHook, setSubmoduleRegistry, syncDelay} from 'modules/userId/index.js'; import {config} from 'src/config'; import * as utils from 'src/utils'; import {unifiedIdSubmodule} from 'modules/userId/unifiedIdSystem'; import {pubCommonIdSubmodule} from 'modules/userId/pubCommonIdSystem'; import {id5IdSubmodule} from 'modules/id5IdSystem'; import {identityLinkSubmodule} from 'modules/identityLinkIdSystem'; + let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; @@ -21,15 +16,20 @@ describe('User ID', function() { userSync: { syncDelay: 0, userIds: [ - (configArr1 && configArr1.length === 3) ? getStorageMock.apply(null, configArr1) : null, - (configArr2 && configArr2.length === 3) ? getStorageMock.apply(null, configArr2) : null, - (configArr3 && configArr3.length === 3) ? getStorageMock.apply(null, configArr3) : null, - (configArr4 && configArr4.length === 3) ? getStorageMock.apply(null, configArr4) : null + (configArr1 && configArr1.length >= 3) ? getStorageMock.apply(null, configArr1) : null, + (configArr2 && configArr2.length >= 3) ? getStorageMock.apply(null, configArr2) : null, + (configArr3 && configArr3.length >= 3) ? getStorageMock.apply(null, configArr3) : null, + (configArr4 && configArr4.length >= 3) ? getStorageMock.apply(null, configArr4) : null ].filter(i => i)} } } - function getStorageMock(name = 'pubCommonId', key = 'pubcid', type = 'cookie', expires = 30) { - return { name: name, storage: { name: key, type: type, expires: expires } } + function getStorageMock(name = 'pubCommonId', key = 'pubcid', type = 'cookie', expires = 30, refreshInSeconds) { + return { name: name, storage: { name: key, type: type, expires: expires, refreshInSeconds: refreshInSeconds } } + } + function getConfigValueMock(name, value) { + return { + userSync: { syncDelay: 0, userIds: [{ name: name, value: value }] } + } } function getAdUnitMock(code = 'adUnit-code') { @@ -72,7 +72,7 @@ describe('User ID', function() { let pubcid = utils.getCookie('pubcid'); expect(pubcid).to.be.null; // there should be no cookie initially - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); @@ -98,7 +98,7 @@ describe('User ID', function() { let pubcid1; let pubcid2; - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); @@ -112,7 +112,7 @@ describe('User ID', function() { }); }); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); @@ -133,7 +133,7 @@ describe('User ID', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie'])); requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); @@ -168,14 +168,14 @@ describe('User ID', function() { }); it('fails initialization if opt out cookie exists', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule]); 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 () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); @@ -236,7 +236,7 @@ describe('User ID', function() { expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); - it('config with 1 configurations should create 1 submodules', function () { + it('config with 1 configuration should create 1 submodule', function () { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie'])); @@ -312,14 +312,7 @@ describe('User ID', function() { it('test hook from pubcommonid config value object', function(done) { setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); - config.setConfig({ - usersync: { - syncDelay: 0, - userIds: [{ - name: 'pubCommonId', - value: {'pubcidvalue': 'testpubcidvalue'} - }]} - }); + config.setConfig(getConfigValueMock('pubCommonId', {'pubcidvalue': 'testpubcidvalue'})); requestBidsHook(function() { adUnits.forEach(unit => { @@ -394,13 +387,16 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from id5id cookies', function(done) { + it('test hook from id5id cookies when refresh needed', function(done) { // simulate existing browser local storage values utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('id5id_last', (new Date(Date.now() - 7200 * 1000)).toUTCString(), (new Date(Date.now() + 5000).toUTCString())); + + sinon.stub(utils, 'logError'); // getId should failed with a logError as it has no partnerId setSubmoduleRegistry([id5IdSubmodule]); init(config); - config.setConfig(getConfigMock(['id5Id', 'id5id', 'cookie'])); + config.setConfig(getConfigMock(['id5Id', 'id5id', 'cookie', 10, 3600])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -409,7 +405,25 @@ describe('User ID', function() { expect(bid.userId.id5id).to.equal('testid5id'); }); }); + sinon.assert.calledOnce(utils.logError); utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + utils.logError.restore(); + done(); + }, {adUnits}); + }); + + it('test hook from id5id value-based config', function(done) { + setSubmoduleRegistry([id5IdSubmodule]); + init(config); + config.setConfig(getConfigValueMock('id5Id', {'id5id': 'testid5id'})); + + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); + }); + }); done(); }, {adUnits}); }); From 17969daffa32b5d0b7a6ef547206f5659f8b8492 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 17 Sep 2019 16:10:30 -0400 Subject: [PATCH 1501/1594] Prebid 2.33.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 13744d61755..dde06ed5c45 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.33.0-pre", + "version": "2.33.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 352470983eb737de12cee2adb71eb33bb8f17fa0 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 17 Sep 2019 17:36:45 -0400 Subject: [PATCH 1502/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dde06ed5c45..314323914a1 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.33.0", + "version": "2.34.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From a3cd6e689ea6284a2baedee12ede9707b93378af Mon Sep 17 00:00:00 2001 From: Telaria Engineering <36203956+telariaEng@users.noreply.github.com> Date: Tue, 17 Sep 2019 16:39:55 -0700 Subject: [PATCH 1503/1594] SupplyChainObject support and fires a pixel onTimeout (#4152) * - Implemented the 'onTimeout' callback to fire a pixel when there's a timeout. - Added the ability to serialize an schain object according to the description provided here: https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md * some mods to the schain tag generation * - added tests for schain param checking. * - fixed a malformed url for timeouts * - Removed a trailing ',' while generating a schain param. * - Using the schain object from validBidRequest if present. Reverting to checking if params has it if not. * - reverting changes to merge with master * - Resolving merge issues --- modules/telariaBidAdapter.js | 128 ++++++++++++++++---- test/spec/modules/telariaBidAdapter_spec.js | 67 +++++++++- 2 files changed, 167 insertions(+), 28 deletions(-) diff --git a/modules/telariaBidAdapter.js b/modules/telariaBidAdapter.js index 0dd2e5e6edb..fe0277f9fbe 100644 --- a/modules/telariaBidAdapter.js +++ b/modules/telariaBidAdapter.js @@ -5,7 +5,9 @@ import {VIDEO} from '../src/mediaTypes'; import {STATUS} from '../src/constants'; const BIDDER_CODE = 'telaria'; -const ENDPOINT = '.ads.tremorhub.com/ad/tag'; +const DOMAIN = 'tremorhub.com'; +const TAG_ENDPOINT = `ads.${DOMAIN}/ad/tag`; +const EVENTS_ENDPOINT = `events.${DOMAIN}/diag`; export const spec = { code: BIDDER_CODE, @@ -34,7 +36,7 @@ export const spec = { if (url) { requests.push({ method: 'GET', - url: generateUrl(bid, bidderRequest), + url: url, bidId: bid.bidId, vastUrl: url.split('&fmt=json')[0] }); @@ -82,7 +84,7 @@ export const spec = { errorMessage += `: ${bidResult.error}`; } utils.logError(errorMessage); - } else if (bidResult.seatbid && bidResult.seatbid.length > 0) { + } else if (!utils.isEmpty(bidResult.seatbid)) { bidResult.seatbid[0].bid.forEach(tag => { bids.push(createBid(STATUS.GOOD, bidderRequest, tag, width, height, BIDDER_CODE)); }); @@ -100,11 +102,89 @@ export const spec = { getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; if (syncOptions.pixelEnabled && serverResponses.length) { - try { - serverResponses[0].body.ext.telaria.userSync.forEach(url => syncs.push({type: 'image', url: url})); - } catch (e) {} + (utils.deepAccess(serverResponses, '0.body.ext.telaria.userSync') || []).forEach(url => syncs.push({type: 'image', url: url})); } return syncs; + }, + + /** + * See http://prebid.org/dev-docs/bidder-adaptor.html#registering-on-timeout for detailed semantic. + * @param timeoutData bidRequest + */ + onTimeout: function (timeoutData) { + let url = getTimeoutUrl(timeoutData); + if (url) { + utils.triggerPixel(url); + } + } +}; + +function getScheme() { + return ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; +} + +function getSrcPageUrl(params) { + return (params && params['srcPageUrl']) || encodeURIComponent(document.location.href); +} + +function getEncodedValIfNotEmpty(val) { + return !utils.isEmpty(val) ? encodeURIComponent(val) : ''; +} + +/** + * Converts the schain object to a url param value. Please refer to + * https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md + * (schain for non ORTB section) for more information + * @param schainObject + * @returns {string} + */ +function getSupplyChainAsUrlParam(schainObject) { + if (utils.isEmpty(schainObject)) { + return ''; + } + + let scStr = `&schain=${schainObject.ver},${schainObject.complete}`; + + schainObject.nodes.forEach((node) => { + scStr += '!'; + scStr += `${getEncodedValIfNotEmpty(node.asi)},`; + scStr += `${getEncodedValIfNotEmpty(node.sid)},`; + scStr += `${getEncodedValIfNotEmpty(node.hp)},`; + scStr += `${getEncodedValIfNotEmpty(node.rid)},`; + scStr += `${getEncodedValIfNotEmpty(node.name)},`; + scStr += `${getEncodedValIfNotEmpty(node.domain)}`; + }); + + return scStr; +} + +function getUrlParams(params, schainFromBidRequest) { + let urlSuffix = ''; + + if (!utils.isEmpty(params)) { + for (let key in params) { + if (key !== 'schain' && params.hasOwnProperty(key) && !utils.isEmpty(params[key])) { + urlSuffix += `&${key}=${params[key]}`; + } + } + urlSuffix += getSupplyChainAsUrlParam(!utils.isEmpty(schainFromBidRequest) ? schainFromBidRequest : params['schain']); + } + + return urlSuffix; +} + +export const getTimeoutUrl = function(timeoutData) { + let params = utils.deepAccess(timeoutData, '0.params.0'); + + if (!utils.isEmpty(params)) { + let url = `${getScheme()}${EVENTS_ENDPOINT}`; + + url += `?srcPageUrl=${getSrcPageUrl(params)}`; + url += `${getUrlParams(params)}`; + + url += '&hb=1&evt=TO'; + + return url; } }; @@ -116,9 +196,9 @@ export const spec = { * @returns {string} */ function generateUrl(bid, bidderRequest) { - let playerSize = (bid.mediaTypes && bid.mediaTypes.video && bid.mediaTypes.video.playerSize); + let playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); if (!playerSize) { - utils.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; @@ -132,45 +212,41 @@ function generateUrl(bid, bidderRequest) { } } - if (bid.params.supplyCode && bid.params.adCode) { - let scheme = ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; - let url = scheme + bid.params.supplyCode + ENDPOINT + '?adCode=' + bid.params.adCode; + let supplyCode = utils.deepAccess(bid, 'params.supplyCode'); + let adCode = utils.deepAccess(bid, 'params.adCode'); + + if (supplyCode && adCode) { + let url = `${getScheme()}${supplyCode}.${TAG_ENDPOINT}?adCode=${adCode}`; if (width) { - url += ('&playerWidth=' + width); + url += (`&playerWidth=${width}`); } if (height) { - url += ('&playerHeight=' + height); + url += (`&playerHeight=${height}`); } - for (let key in bid.params) { - if (bid.params.hasOwnProperty(key) && bid.params[key]) { - url += ('&' + key + '=' + bid.params[key]); - } - } + url += `${getUrlParams(bid.params, bid.schain)}`; - if (!bid.params['srcPageUrl']) { - url += ('&srcPageUrl=' + encodeURIComponent(document.location.href)); - } + url += `&srcPageUrl=${getSrcPageUrl(bid.params)}`; - url += ('&transactionId=' + bid.transactionId + '&hb=1'); + url += (`&transactionId=${bid.transactionId}`); if (bidderRequest) { if (bidderRequest.gdprConsent) { if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') { - url += ('&gdpr=' + (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + url += (`&gdpr=${(bidderRequest.gdprConsent.gdprApplies ? 1 : 0)}`); } if (bidderRequest.gdprConsent.consentString) { - url += ('&gdpr_consent=' + bidderRequest.gdprConsent.consentString); + url += (`&gdpr_consent=${bidderRequest.gdprConsent.consentString}`); } } if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - url += ('&referrer=' + encodeURIComponent(bidderRequest.refererInfo.referer)); + url += (`&referrer=${encodeURIComponent(bidderRequest.refererInfo.referer)}`); } } - return (url + '&fmt=json'); + return (url + '&hb=1&fmt=json'); } } diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js index fdb63675224..4c1c0c975b5 100644 --- a/test/spec/modules/telariaBidAdapter_spec.js +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -1,6 +1,6 @@ import {expect} from 'chai'; import {newBidder} from 'src/adapters/bidderFactory'; -import {spec} from 'modules/telariaBidAdapter'; +import {spec, getTimeoutUrl} from 'modules/telariaBidAdapter'; const ENDPOINT = '.ads.tremorhub.com/ad/tag'; const AD_CODE = 'ssp-!demo!-lufip'; @@ -16,7 +16,7 @@ const REQUEST = { }, 'mediaType': 'video', 'bids': [{ - 'bidder': 'tremor', + 'bidder': 'telaria', 'params': { 'videoId': 'MyCoolVideo', 'inclSync': true @@ -24,6 +24,36 @@ const REQUEST = { }] }; +const REQUEST_WITH_SCHAIN = [{ + 'bidder': 'telaria', + 'params': { + 'videoId': 'MyCoolVideo', + 'inclSync': true, + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + }, + { + 'asi': 'exchange2.com', + 'sid': 'abcd', + 'hp': 1, + 'rid': 'bid-request-2', + 'name': 'intermediary', + 'domain': 'intermediary.com' + } + ] + } + } +}]; + const BIDDER_REQUEST = { 'refererInfo': { 'referer': 'www.test.com' @@ -102,6 +132,8 @@ describe('TelariaAdapter', () => { } }]; + const schainStub = REQUEST_WITH_SCHAIN; + it('exists and is a function', () => { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); @@ -147,6 +179,14 @@ describe('TelariaAdapter', () => { expect(tempRequest.length).to.equal(0); }); + + it('converts the schain object into a tag param', () => { + let tempBid = schainStub; + tempBid[0].params.adCode = 'ssp-!demo!-lufip'; + tempBid[0].params.supplyCode = 'ssp-demo-rm6rh'; + let builtRequests = spec.buildRequests(tempBid, BIDDER_REQUEST); + expect(builtRequests.length).to.equal(1); + }); }); describe('interpretResponse', () => { @@ -215,4 +255,27 @@ describe('TelariaAdapter', () => { expect(urls.length).to.equal(2); }); }); + + describe('onTimeout', () => { + const timeoutData = [{ + adUnitCode: 'video1', + auctionId: 'd8d239f4-303a-4798-8c8c-dd3151ced4e7', + bidId: '2c749c0101ea92', + bidder: 'telaria', + params: [{ + adCode: 'ssp-!demo!-lufip', + supplyCode: 'ssp-demo-rm6rh', + mediaId: 'MyCoolVideo' + }] + }]; + + it('should return a pixel url', () => { + let url = getTimeoutUrl(timeoutData); + assert(url); + }); + + it('should fire a pixel', () => { + expect(spec.onTimeout(timeoutData)).to.be.undefined; + }); + }); }); From 313bdc8047b5ce5cea1b7e26e686d8f51efcc833 Mon Sep 17 00:00:00 2001 From: ujuettner Date: Wed, 18 Sep 2019 01:49:48 +0200 Subject: [PATCH 1504/1594] Feature/add profile parameter (#4185) * Add optional profile parameter --- modules/orbidderBidAdapter.js | 3 ++- test/spec/modules/orbidderBidAdapter_spec.js | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index fc6eac6e479..954ad82261f 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -19,7 +19,8 @@ export const spec = { (bid.params.accountId && (typeof bid.params.accountId === 'string')) && (bid.params.placementId && (typeof bid.params.placementId === 'string')) && ((typeof bid.params.bidfloor === 'undefined') || (typeof bid.params.bidfloor === 'number')) && - ((typeof bid.params.keyValues === 'undefined') || (typeof bid.params.keyValues === 'object'))); + ((typeof bid.params.keyValues === 'undefined') || (typeof bid.params.keyValues === 'object')) && + ((typeof bid.params.profile === 'undefined') || (typeof bid.params.profile === 'object'))); }, buildRequests(validBidRequests, bidderRequest) { diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 4a972c42d30..aeaa5f30446 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -52,6 +52,12 @@ describe('orbidderBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); + it('accepts optional profile object', () => { + const bidRequest = deepClone(defaultBidRequest); + bidRequest.params.profile = {'key': 'value'}; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + it('performs type checking', () => { const bidRequest = deepClone(defaultBidRequest); bidRequest.params.accountId = 1; // supposed to be a string @@ -64,6 +70,12 @@ describe('orbidderBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); + it('doesn\'t accept malformed profile', () => { + const bidRequest = deepClone(defaultBidRequest); + bidRequest.params.profile = 'another not usable string'; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + it('should return false when required params are not passed', () => { const bidRequest = deepClone(defaultBidRequest); delete bidRequest.params; From ebf4272e4d96119070e43d7a83da56b74fc3e0ba Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Wed, 18 Sep 2019 02:19:48 -0400 Subject: [PATCH 1505/1594] EMXDigital Bid Adapter: Add video dimensions in request (#4174) * addressed feedback from #3731 ticket * removed commented code from emx test spec * logging removed from spec * flip h & w values from playerSize for video requests * adding Outstream mediaType to EMX Digital * adding device info. update to grab video param. styling changes. * add video dimensions from playerSize * fix test for video dimensions --- modules/emx_digitalBidAdapter.js | 12 ++++++++++-- test/spec/modules/emx_digitalBidAdapter_spec.js | 12 ++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 2ca595151f9..9ab3a829158 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -7,7 +7,7 @@ import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; const ENDPOINT = 'hb.emxdgt.com'; const RENDERER_URL = '//js.brealtime.com/outstream/1.30.0/bundle.js'; -const ADAPTER_VERSION = '1.40.2'; +const ADAPTER_VERSION = '1.40.3'; const DEFAULT_CUR = 'USD'; export const emxAdapter = { @@ -103,7 +103,15 @@ export const emxAdapter = { return renderer; }, buildVideo: (bid) => { - let videoObj = Object.assign(bid.mediaTypes.video, bid.params.video) + let videoObj = Object.assign(bid.mediaTypes.video, bid.params.video); + + if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { + videoObj['w'] = bid.mediaTypes.video.playerSize[0][0]; + videoObj['h'] = bid.mediaTypes.video.playerSize[0][1]; + } else { + videoObj['w'] = bid.mediaTypes.video.playerSize[0]; + videoObj['h'] = bid.mediaTypes.video.playerSize[1]; + } return emxAdapter.cleanProtocols(videoObj); }, parseResponse: (bidResponseAdm) => { diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js index 10d0d74c49c..3487fd73aca 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -300,15 +300,15 @@ describe('emx_digital Adapter', function () { bidRequestWithVideo[0].mediaTypes = { video: { context: 'instream', - playerSize: [640, 480] + playerSize: [[640, 480]] }, }; bidRequestWithVideo[0].params.video = {}; let request = spec.buildRequests(bidRequestWithVideo, bidderRequest); const data = JSON.parse(request.data); expect(data.imp[0].video).to.exist.and.to.be.a('object'); - expect(data.imp[0].video.h).to.equal(bidRequestWithVideo[0].mediaTypes.video.playerSize[0][0]); - expect(data.imp[0].video.w).to.equal(bidRequestWithVideo[0].mediaTypes.video.playerSize[0][1]); + expect(data.imp[0].video.w).to.equal(bidRequestWithVideo[0].mediaTypes.video.playerSize[0][0]); + expect(data.imp[0].video.h).to.equal(bidRequestWithVideo[0].mediaTypes.video.playerSize[0][1]); }); it('builds correctly formatted request video object for outstream', function () { @@ -316,15 +316,15 @@ describe('emx_digital Adapter', function () { bidRequestWithOutstreamVideo[0].mediaTypes = { video: { context: 'outstream', - playerSize: [640, 480] + playerSize: [[640, 480]] }, }; bidRequestWithOutstreamVideo[0].params.video = {}; let request = spec.buildRequests(bidRequestWithOutstreamVideo, bidderRequest); const data = JSON.parse(request.data); expect(data.imp[0].video).to.exist.and.to.be.a('object'); - expect(data.imp[0].video.h).to.equal(bidRequestWithOutstreamVideo[0].mediaTypes.video.playerSize[0][0]); - expect(data.imp[0].video.w).to.equal(bidRequestWithOutstreamVideo[0].mediaTypes.video.playerSize[0][1]); + expect(data.imp[0].video.w).to.equal(bidRequestWithOutstreamVideo[0].mediaTypes.video.playerSize[0][0]); + expect(data.imp[0].video.h).to.equal(bidRequestWithOutstreamVideo[0].mediaTypes.video.playerSize[0][1]); }); it('shouldn\'t contain a user obj without GDPR information', function () { From fa0019c363d3744a9d18a505408e4b979e3cb31b Mon Sep 17 00:00:00 2001 From: PWyrembak Date: Wed, 18 Sep 2019 21:20:49 +0300 Subject: [PATCH 1506/1594] Added keywords parameter support in TrustX Bid Adapter (#4183) * Add trustx adapter and tests for it * update integration example * Update trustx adapter * Post-review fixes of Trustx adapter * Code improvement for trustx adapter: changed default price type from gross to net * Update TrustX adapter to support the 1.0 version * Make requested changes for TrustX adapter * Updated markdown file for TrustX adapter * Fix TrustX adapter and spec file * Update TrustX adapter: r parameter was added to ad request as cache buster * Add support of gdpr to Trustx Bid Adapter * Add wtimeout to ad request params for TrustX Bid Adapter * TrustX Bid Adapter: remove last ampersand in the ad request * Update TrustX Bid Adapter to support identical uids in parameters * Update TrustX Bid Adapter to ignore bids that sizes do not match the size of the request * Update TrustX Bid Adapter to support instream and outstream video * Added wrapperType and wrapperVersion parameters in ad request for TrustX Bid Adapter * Update TrustX Bid Adapter to use refererInfo instead depricated function utils.getTopWindowUrl * HOTFIX for referrer encodind in TrustX Bid Adapter * Fix test for TrustX Bid Adapter * TrustX Bid Adapter: added keywords passing support --- modules/trustxBidAdapter.js | 24 +++++++++++ modules/trustxBidAdapter.md | 6 ++- test/spec/modules/trustxBidAdapter_spec.js | 49 ++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js index a1ba632a487..00c86dec0d3 100644 --- a/modules/trustxBidAdapter.js +++ b/modules/trustxBidAdapter.js @@ -46,6 +46,7 @@ export const spec = { const sizeMap = {}; const bids = validBidRequests || []; let priceType = 'net'; + let pageKeywords; let reqId; bids.forEach(bid => { @@ -57,6 +58,15 @@ export const spec = { 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 (!slotsMapByUid[uid]) { slotsMapByUid[uid] = {}; } @@ -92,6 +102,10 @@ export const spec = { wrapperVersion: '$prebid.version$' }; + if (pageKeywords) { + payload.keywords = JSON.stringify(pageKeywords); + } + if (bidderRequest) { if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { payload.u = bidderRequest.refererInfo.referer; @@ -154,6 +168,16 @@ export const spec = { } } +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) { utils.logError(LOG_ERROR_MESS.emptySeatbid); diff --git a/modules/trustxBidAdapter.md b/modules/trustxBidAdapter.md index d6b660c6248..a72f1ba85aa 100644 --- a/modules/trustxBidAdapter.md +++ b/modules/trustxBidAdapter.md @@ -32,7 +32,11 @@ TrustX Bid Adapter supports Banner and Video (instream and outstream). bidder: "trustx", params: { uid: 45, - priceType: 'gross' + priceType: 'gross', + keywords: { + brandsafety: ['disaster'], + topic: ['stress', 'fear'] + } } } ] diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index d7d16348bcf..4256012ba0b 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -167,6 +167,55 @@ describe('TrustXAdapter', function () { expect(payload).to.have.property('gdpr_consent', 'AAA'); expect(payload).to.have.property('gdpr_applies', '1'); }); + + 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); + 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' + }]); + }); }); describe('interpretResponse', function () { From 53a13f227f76a0fab5fd6c0bfb7bb1ebb50263b2 Mon Sep 17 00:00:00 2001 From: bretg Date: Thu, 19 Sep 2019 16:30:16 -0400 Subject: [PATCH 1507/1594] rubicon: avoid passing unknown position (#4207) * rubicon: not passing pos if not specified * added comment * not sending pos for video when undefined * cleaning up test * fixed unit test --- modules/rubiconBidAdapter.js | 14 ++++++- test/spec/modules/rubiconBidAdapter_spec.js | 43 +++++++++++++++------ 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index f309e4b7cac..a1cdfdf8fea 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -395,7 +395,6 @@ export const spec = { 'zone_id': params.zoneId, 'size_id': parsedSizes[0], 'alt_size_ids': parsedSizes.slice(1).join(',') || undefined, - 'p_pos': params.position === 'atf' || params.position === 'btf' ? params.position : 'unknown', 'rp_floor': (params.floor = parseFloat(params.floor)) > 0.01 ? params.floor : 0.01, 'rp_secure': isSecure() ? '1' : '0', 'tk_flint': `${configIntType || DEFAULT_INTEGRATION}_v$prebid.version$`, @@ -409,6 +408,11 @@ export const spec = { 'rf': _getPageUrl(bidRequest, bidderRequest) }; + // add p_pos only if specified and valid + if (params.position === 'atf' || params.position === 'btf') { + data['p_pos'] = params.position; + } + if ((bidRequest.userId || {}).tdid) { data['tpid_tdid'] = bidRequest.userId.tdid; } @@ -768,8 +772,14 @@ function addVideoParameters(data, bidRequest) { if (typeof data.imp[0].video === 'object' && data.imp[0].video.skipafter === undefined) { data.imp[0].video.skipafter = bidRequest.params.video.skipdelay; } + // video.pos can already be specified by adunit.mediatypes.video.pos. + // but if not, it might be specified in the params if (typeof data.imp[0].video === 'object' && data.imp[0].video.pos === undefined) { - data.imp[0].video.pos = bidRequest.params.position === 'atf' ? 1 : (bidRequest.params.position === 'btf' ? 3 : 0); + if (bidRequest.params.position === 'atf') { + data.imp[0].video.pos = 1; + } else if (bidRequest.params.position === 'btf') { + data.imp[0].video.pos = 3; + } } const size = parseSizes(bidRequest, 'video') diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index f7432435060..8d65e1e97b4 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -353,6 +353,28 @@ describe('the rubicon adapter', function () { }); }); + it('should not send p_pos to AE if not params.position specified', function() { + var noposRequest = utils.deepClone(bidderRequest); + delete noposRequest.bids[0].params.position; + + let [request] = spec.buildRequests(noposRequest.bids, noposRequest); + let data = parseQuery(request.data); + + expect(data['site_id']).to.equal('70608'); + expect(data['p_pos']).to.equal(undefined); + }); + + it('should not send p_pos to AE if not params.position is invalid', function() { + var badposRequest = utils.deepClone(bidderRequest); + badposRequest.bids[0].params.position = 'bad'; + + let [request] = spec.buildRequests(badposRequest.bids, badposRequest); + let data = parseQuery(request.data); + + expect(data['site_id']).to.equal('70608'); + expect(data['p_pos']).to.equal(undefined); + }); + it('ad engine query params should be ordered correctly', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); @@ -1135,14 +1157,6 @@ describe('the rubicon adapter', function () { expect(post.ext.prebid.cache.vastxml.returnCreative).to.equal(false) }); - it('should send request with proper ad position', function () { - createVideoBidderRequest(); - let positionBidderRequest = utils.deepClone(bidderRequest); - positionBidderRequest.bids[0].mediaTypes.video.pos = 1; - let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); - expect(request.data.imp[0].video.pos).to.equal(1); - }); - it('should send correct bidfloor to PBS', function() { createVideoBidderRequest(); @@ -1171,13 +1185,18 @@ describe('the rubicon adapter', function () { expect(request.data.imp[0]).to.not.haveOwnProperty('bidfloor'); }); - it('should send request with proper ad position when mediaTypes.video.pos is not defined', function () { + it('should send request with proper ad position', function () { createVideoBidderRequest(); let positionBidderRequest = utils.deepClone(bidderRequest); + positionBidderRequest.bids[0].mediaTypes.video.pos = 1; + let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); + expect(request.data.imp[0].video.pos).to.equal(1); + + positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = undefined; positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; - let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); - expect(request.data.imp[0].video.pos).to.equal(0); + [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); + expect(request.data.imp[0].video.pos).to.equal(undefined); positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = 'atf' @@ -1195,7 +1214,7 @@ describe('the rubicon adapter', function () { positionBidderRequest.bids[0].params.position = 'foobar'; positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); - expect(request.data.imp[0].video.pos).to.equal(0); + expect(request.data.imp[0].video.pos).to.equal(undefined); }); it('should properly enforce video.context to be either instream or outstream', function () { From 93874d81f9c26841c614745811b9e2f4a30ecbef Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Fri, 20 Sep 2019 00:01:36 -0400 Subject: [PATCH 1508/1594] correctly reference bidrequest and determine mediatype of bidresponse (#4204) --- modules/emx_digitalBidAdapter.js | 25 +++++++++-------- .../modules/emx_digitalBidAdapter_spec.js | 28 +++++++++++++++++-- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 9ab3a829158..12f3482184b 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -7,7 +7,7 @@ import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; const ENDPOINT = 'hb.emxdgt.com'; const RENDERER_URL = '//js.brealtime.com/outstream/1.30.0/bundle.js'; -const ADAPTER_VERSION = '1.40.3'; +const ADAPTER_VERSION = '1.41.0'; const DEFAULT_CUR = 'USD'; export const emxAdapter = { @@ -39,11 +39,11 @@ export const emxAdapter = { h: sizes[0][1] }; }, - formatVideoResponse: (bidResponse, emxBid) => { + formatVideoResponse: (bidResponse, emxBid, bidRequest) => { bidResponse.vastXml = emxBid.adm; - if (!emxBid.renderer && (!emxBid.mediaTypes || !emxBid.mediaTypes.video || !emxBid.mediaTypes.video.context || emxBid.mediaTypes.video.context === 'outstream')) { + if (bidRequest.bidRequest && bidRequest.bidRequest.mediaTypes && bidRequest.bidRequest.mediaTypes.video && bidRequest.bidRequest.mediaTypes.video.context === 'outstream') { bidResponse.renderer = emxAdapter.createRenderer(bidResponse, { - id: emxBid.bidId, + id: emxBid.id, url: RENDERER_URL }); } @@ -188,14 +188,14 @@ export const spec = { return true; }, - buildRequests: function (validBidRequests, bidderRequest) { + buildRequests: function (validBidRequests, bidRequest) { const emxImps = []; - const timeout = bidderRequest.timeout || ''; + const timeout = bidRequest.timeout || ''; const timestamp = Date.now(); const url = location.protocol + '//' + ENDPOINT + ('?t=' + timeout + '&ts=' + timestamp + '&src=pbjs'); const secure = location.protocol.indexOf('https') > -1 ? 1 : 0; const domain = utils.getTopWindowLocation().hostname; - const page = bidderRequest.refererInfo.referer; + const page = bidRequest.refererInfo.referer; const device = emxAdapter.getDevice(); const ref = emxAdapter.getReferrer(); @@ -217,7 +217,7 @@ export const spec = { }); let emxData = { - id: bidderRequest.auctionId, + id: bidRequest.auctionId, imp: emxImps, device, site: { @@ -229,17 +229,18 @@ export const spec = { version: ADAPTER_VERSION }; - emxData = emxAdapter.getGdpr(bidderRequest, Object.assign({}, emxData)); + emxData = emxAdapter.getGdpr(bidRequest, Object.assign({}, emxData)); return { method: 'POST', url: url, data: JSON.stringify(emxData), options: { withCredentials: true - } + }, + bidRequest }; }, - interpretResponse: function (serverResponse) { + interpretResponse: function (serverResponse, bidRequest) { let emxBidResponses = []; let response = serverResponse.body || {}; if (response.seatbid && response.seatbid.length > 0 && response.seatbid[0].bid) { @@ -261,7 +262,7 @@ export const spec = { }; if (emxBid.adm && emxBid.adm.indexOf(' -1) { isVideo = true; - bidResponse = emxAdapter.formatVideoResponse(bidResponse, Object.assign({}, emxBid)); + bidResponse = emxAdapter.formatVideoResponse(bidResponse, Object.assign({}, emxBid), bidRequest); } bidResponse.mediaType = (isVideo ? VIDEO : BANNER); emxBidResponses.push(bidResponse); diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js index 3487fd73aca..16f17174f88 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -358,6 +358,28 @@ describe('emx_digital Adapter', function () { }); describe('interpretResponse', function () { + let bid = { + 'bidder': 'emx_digital', + 'params': { + 'tagid': '25251', + 'video': {} + }, + 'mediaTypes': { + 'video': { + 'context': 'instream', + 'playerSize': [640, 480] + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c2501de1e', + 'bidderRequestId': '22edbae3120bf6', + 'auctionId': '1d1a01234a475' + }; + const serverResponse = { 'id': '12819a18-56e1-4256-b836-b69a10202668', 'seatbid': [{ @@ -458,7 +480,8 @@ describe('emx_digital Adapter', function () { it('returns a banner bid for non-xml creatives', function () { let result = spec.interpretResponse({ body: serverResponse - }); + }, { bidRequest: bid } + ); const ad0 = result[0]; const ad1 = result[1]; expect(ad0.mediaType).to.equal('banner'); @@ -480,7 +503,8 @@ describe('emx_digital Adapter', function () { let result = spec.interpretResponse({ body: serverResponse - }); + }, { bidRequest: bid } + ); const ad0 = result[0]; const ad1 = result[1]; expect(ad0.mediaType).to.equal('video'); From def7138142de5259ba0182237d230a8b70c58070 Mon Sep 17 00:00:00 2001 From: susyt Date: Thu, 19 Sep 2019 21:05:46 -0700 Subject: [PATCH 1509/1594] GumGum: only send gdprConsent when found (#4205) * adds digitrust module, mods gdpr from bool to int * update unit test * only send gdprconsent if present --- modules/gumgumBidAdapter.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 8afbed640d7..898cd4a59bd 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -135,7 +135,7 @@ function isBidRequestValid (bid) { */ function buildRequests (validBidRequests, bidderRequest) { const bids = []; - const gdprConsent = Object.assign({ consentString: null, gdprApplies: true }, bidderRequest && bidderRequest.gdprConsent) + const gdprConsent = bidderRequest && bidderRequest.gdprConsent; utils._each(validBidRequests, bidRequest => { const timeout = config.getConfig('bidderTimeout'); const { @@ -164,8 +164,10 @@ function buildRequests (validBidRequests, bidderRequest) { data.ni = parseInt(params.ICV, 10); data.pi = 5; } - data.gdprApplies = gdprConsent.gdprApplies ? 1 : 0; - if (gdprConsent.gdprApplies) { + if (gdprConsent) { + data.gdprApplies = gdprConsent.gdprApplies ? 1 : 0; + } + if (data.gdprApplies) { data.gdprConsent = gdprConsent.consentString; } From 1e03b4ba3bc4e2f50a8712f62a247a7504c5b98e Mon Sep 17 00:00:00 2001 From: Max Crawford Date: Fri, 20 Sep 2019 00:11:47 -0400 Subject: [PATCH 1510/1594] LKQD: Use refererInfo.referer as fallback pageurl (#4210) * Refactored URL query parameter passthrough for additional values, changed SSP endpoint to v.lkqd.net, and updated associated unit tests * Use refererInfo.referer as fallback pageurl * Removed logs and testing values --- modules/lkqdBidAdapter.js | 4 +++- test/spec/modules/lkqdBidAdapter_spec.js | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/lkqdBidAdapter.js b/modules/lkqdBidAdapter.js index a97939c15b1..a39abb320b2 100644 --- a/modules/lkqdBidAdapter.js +++ b/modules/lkqdBidAdapter.js @@ -30,7 +30,7 @@ function isBidRequestValid(bidRequest) { return false; } -function buildRequests(validBidRequests) { +function buildRequests(validBidRequests, bidderRequest) { let bidRequests = []; for (let i = 0; i < validBidRequests.length; i++) { @@ -138,6 +138,8 @@ function buildRequests(validBidRequests) { } if (bidRequest.params.hasOwnProperty('pageurl') && bidRequest.params.pageurl != null) { sspData.pageurl = bidRequest.params.pageurl; + } else if (bidderRequest && bidderRequest.refererInfo) { + sspData.pageurl = encodeURIComponent(bidderRequest.refererInfo.referer); } if (bidRequest.params.hasOwnProperty('contentId') && bidRequest.params.contentId != null) { sspData.contentid = bidRequest.params.contentId; diff --git a/test/spec/modules/lkqdBidAdapter_spec.js b/test/spec/modules/lkqdBidAdapter_spec.js index 0cebb2651a9..73a4824f0ef 100644 --- a/test/spec/modules/lkqdBidAdapter_spec.js +++ b/test/spec/modules/lkqdBidAdapter_spec.js @@ -40,7 +40,7 @@ describe('LKQD Bid Adapter Test', function () { }); }); - describe('buildRequests', function () { + describe('buildRequests', () => { const ENDPOINT = 'https://v.lkqd.net/ad'; let bidRequests = [ { @@ -101,14 +101,12 @@ describe('LKQD Bid Adapter Test', function () { expect(requests.length).to.equal(2); const r1 = requests[0].data; expect(r1).to.not.have.property('dnt'); - expect(r1).to.not.have.property('pageurl'); expect(r1).to.not.have.property('contentid'); expect(r1).to.not.have.property('contenttitle'); expect(r1).to.not.have.property('contentlength'); expect(r1).to.not.have.property('contenturl'); const r2 = requests[1].data; expect(r2).to.not.have.property('dnt'); - expect(r2).to.not.have.property('pageurl'); expect(r2).to.not.have.property('contentid'); expect(r2).to.not.have.property('contenttitle'); expect(r2).to.not.have.property('contentlength'); From f1642f182cfbd69b5f5daee0eabb1e917aa1c972 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Durgeat Date: Fri, 20 Sep 2019 06:13:38 +0200 Subject: [PATCH 1511/1594] [UserId] - ID5 - Fixed case when consentData is undefined (No CMP) (#4215) --- modules/id5IdSystem.js | 2 +- modules/userId/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js index 85619ba51ba..6fb5014c962 100644 --- a/modules/id5IdSystem.js +++ b/modules/id5IdSystem.js @@ -38,7 +38,7 @@ export const id5IdSubmodule = { utils.logError(`User ID - ID5 submodule requires partner to be defined as a number`); return undefined; } - const hasGdpr = (typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0; + const hasGdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0; const gdprConsentString = hasGdpr ? consentData.consentString : ''; const storedUserId = this.decode(cacheIdObj); const url = `https://id5-sync.com/g/v1/${configParams.partner}.json?1puid=${storedUserId ? storedUserId.id5id : ''}&gdpr=${hasGdpr}&gdpr_consent=${gdprConsentString}`; diff --git a/modules/userId/index.js b/modules/userId/index.js index 8a70a4bbf3c..fb7a748b7ec 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -12,7 +12,7 @@ * @summary performs action to obtain id and return a value in the callback's response argument * @name Submodule#getId * @param {SubmoduleParams} configParams - * @param {ConsentData} consentData + * @param {ConsentData|undefined} consentData * @param {(Object|undefined)} cacheIdObj * @return {(Object|function)} id data or a callback, the callback is called on the auction end event */ From eb841b2fd69f37a805efd8aa3389f6136eaa7beb Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 23 Sep 2019 11:12:04 -0400 Subject: [PATCH 1512/1594] create stubs for localStorage in widespaceBidAdapter test file (#4208) --- test/spec/modules/widespaceBidAdapter_spec.js | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js index 55afbead72c..b3884a90b84 100644 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ b/test/spec/modules/widespaceBidAdapter_spec.js @@ -144,6 +144,35 @@ describe('+widespaceAdatperTest', function () { const request = spec.buildRequests(bidRequest, bidderRequest); const UrlRegExp = /^((ftp|http|https):)?\/\/[^ "]+$/; + let fakeLocalStorage = {}; + let lsSetStub; + let lsGetStub; + let lsRemoveStub; + + beforeEach(function() { + lsSetStub = sinon.stub(window.localStorage, 'setItem').callsFake(function (name, value) { + fakeLocalStorage[name] = value; + }); + + lsGetStub = sinon.stub(window.localStorage, 'getItem').callsFake(function (key) { + return fakeLocalStorage[key] || null; + }); + + lsRemoveStub = sinon.stub(window.localStorage, 'removeItem').callsFake(function (key) { + if (key && (fakeLocalStorage[key] !== null || fakeLocalStorage[key] !== undefined)) { + delete fakeLocalStorage[key]; + } + return true; + }); + }); + + afterEach(function() { + lsSetStub.restore(); + lsGetStub.restore(); + lsRemoveStub.restore(); + fakeLocalStorage = {}; + }); + it('-bidRequest method is POST', function () { expect(request[0].method).to.equal('POST'); }); From e817865d9806b0b3f624a1490d3bc32dc7fee945 Mon Sep 17 00:00:00 2001 From: Pascal S Date: Mon, 23 Sep 2019 20:12:32 +0200 Subject: [PATCH 1513/1594] added adId property to adRenderFailed event (#4097) When no bid (therefore no adUnitCode) is available in the adRenderFailed event it can be difficult to identify the erroring slot.But in almost all cases the given slot still has the adId targeting. --- src/prebid.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index efa1198d36c..14c63651ba5 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -276,18 +276,15 @@ $$PREBID_GLOBAL$$.setTargetingForAst = function(adUnitCodes) { events.emit(SET_TARGETING, targeting.getAllTargeting()); }; -function emitAdRenderFail(reason, message, bid) { - const data = {}; - - data.reason = reason; - data.message = message; - if (bid) { - data.bid = bid; - } +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); } + /** * 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 @@ -323,7 +320,7 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { executeRenderer(renderer, bid); } 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(PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid); + 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 @@ -352,19 +349,19 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { utils.callBurl(bid); } else { const message = `Error trying to write ad. No ad for bid response id: ${id}`; - emitAdRenderFail(NO_AD, message, bid); + emitAdRenderFail({ reason: NO_AD, message, bid, id }); } } else { const message = `Error trying to write ad. Cannot find ad by given id : ${id}`; - emitAdRenderFail(CANNOT_FIND_AD, message); + emitAdRenderFail({ reason: CANNOT_FIND_AD, message, id }); } } catch (e) { const message = `Error trying to write ad Id :${id} to the page:${e.message}`; - emitAdRenderFail(EXCEPTION, message); + emitAdRenderFail({ reason: EXCEPTION, message, id }); } } else { const message = `Error trying to write ad Id :${id} to the page. Missing document or adId`; - emitAdRenderFail(MISSING_DOC_OR_ADID, message); + emitAdRenderFail({ reason: MISSING_DOC_OR_ADID, message, id }); } }; From 495baa96b3936221c6289f61751fe97cec8fb968 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Mon, 23 Sep 2019 11:17:26 -0700 Subject: [PATCH 1514/1594] OpenX Adapter: Forcing https requests and adding UserID module support for LiveRamp and TTD (#4182) * OpenX Adapter: Updated requests to force https * OpenX Adapter: Added support for TTD's UnifiedID and LiveRamp's IDL --- modules/openxBidAdapter.js | 37 ++- test/spec/modules/openxBidAdapter_spec.js | 278 ++++++++++++++-------- 2 files changed, 209 insertions(+), 106 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index a79343ab2ff..a5c5b432a55 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -10,6 +10,12 @@ const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; const BIDDER_VERSION = '2.1.9'; +const USER_ID_CODE_TO_QUERY_ARG = { + idl_env: 'lre', // liveramp + pubcid: 'pubcid', // publisher common id + tdid: 'ttduuid' // the trade desk +}; + let shouldSendBoPixel = true; export function resetBoPixel() { @@ -59,7 +65,7 @@ export const spec = { let pixelType = syncOptions.iframeEnabled ? 'iframe' : 'image'; let url = utils.deepAccess(responses, '0.body.ads.pixels') || utils.deepAccess(responses, '0.body.pixels') || - '//u.openx.net/w/1.0/pd'; + 'https://u.openx.net/w/1.0/pd'; return [{ type: pixelType, url: url @@ -237,12 +243,13 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { } } - if ((bids[0].userId && bids[0].userId.pubcid)) { - defaultParams.pubcid = bids[0].userId.pubcid; - } else if (bids[0].crumbs && bids[0].crumbs.pubcid) { - defaultParams.pubcid = bids[0].crumbs.pubcid; + // normalize publisher common id + 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); + // supply chain support if (bids[0].schain) { defaultParams.schain = serializeSupplyChain(bids[0].schain); } @@ -250,6 +257,16 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { return defaultParams; } +function appendUserIdsToQueryParams(queryParams, userIds) { + utils._each(userIds, (userIdValue, userIdProviderKey) => { + if (USER_ID_CODE_TO_QUERY_ARG.hasOwnProperty(userIdProviderKey)) { + queryParams[USER_ID_CODE_TO_QUERY_ARG[userIdProviderKey]] = userIdValue; + } + }); + + return queryParams; +} + function serializeSupplyChain(supplyChain) { return `${supplyChain.ver},${supplyChain.complete}!${serializeSupplyChainNodes(supplyChain.nodes)}`; } @@ -312,8 +329,8 @@ function buildOXBannerRequest(bids, bidderRequest) { } let url = queryParams.ph - ? `//u.openx.net/w/1.0/arj` - : `//${bids[0].params.delDomain}/w/1.0/arj`; + ? `https://u.openx.net/w/1.0/arj` + : `https://${bids[0].params.delDomain}/w/1.0/arj`; return { method: 'GET', @@ -326,8 +343,8 @@ function buildOXBannerRequest(bids, bidderRequest) { function buildOXVideoRequest(bid, bidderRequest) { let oxVideoParams = generateVideoParameters(bid, bidderRequest); let url = oxVideoParams.ph - ? `//u.openx.net/v/1.0/avjp` - : `//${bid.params.delDomain}/v/1.0/avjp`; + ? `https://u.openx.net/v/1.0/avjp` + : `https://${bid.params.delDomain}/v/1.0/avjp`; return { method: 'GET', url: url, @@ -442,7 +459,7 @@ function registerBeacon(mediaType, adUnit, startTime) { if (mediaType === VIDEO) { let url = parse(adUnit.colo); beaconParams.ph = adUnit.ph; - beaconUrl = `//${url.hostname}/w/1.0/bo?${buildQueryStringFromParams(beaconParams)}` + beaconUrl = `https://${url.hostname}/w/1.0/bo?${buildQueryStringFromParams(beaconParams)}` } else { let recordPixel = utils.deepAccess(adUnit, 'creative.0.tracking.impression'); let boBase = recordPixel.match(/([^?]+\/)ri\?/); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 7476d06cf9a..0002d25c37d 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -116,7 +116,7 @@ describe('OpenxAdapter', function () { ads: { version: 0, count: 1, - pixels: 'http://testpixels.net', + pixels: 'https://testpixels.net', ad: [DEFAULT_TEST_ARJ_AD_UNIT] } }; @@ -203,13 +203,6 @@ describe('OpenxAdapter', function () { it('should return true multisize when required params found', function () { expect(spec.isBidRequestValid(multiformatBid)).to.equal(true); }); - - it('should send bid request to openx url via GET, with mediaType specified as banner', function () { - const request = spec.buildRequests([multiformatBid]); - expect(request[0].url).to.equal(`//${multiformatBid.params.delDomain}${URLBASE}`); - expect(request[0].data.ph).to.be.undefined; - expect(request[0].method).to.equal('GET'); - }); }); }); @@ -243,7 +236,7 @@ describe('OpenxAdapter', function () { }); it('should send bid request to openx url via GET, with mediaType specified as video', function () { const request = spec.buildRequests([videoBidWithMediaTypes]); - expect(request[0].url).to.equal(`//${videoBidWithMediaTypes.params.delDomain}${URLBASEVIDEO}`); + expect(request[0].url).to.equal(`https://${videoBidWithMediaTypes.params.delDomain}${URLBASEVIDEO}`); expect(request[0].data.ph).to.be.undefined; expect(request[0].method).to.equal('GET'); }); @@ -254,7 +247,7 @@ describe('OpenxAdapter', function () { params: { unit: '12345678', delDomain: 'test-del-domain', - platform: '1cabba9e-cafe-3665-beef-f00f00f00f00', + platform: '1cabba9e-cafe-3665-beef-f00f00f00f00' }, adUnitCode: 'adunit-code', mediaTypes: { @@ -278,7 +271,7 @@ describe('OpenxAdapter', function () { }); it('should send bid request to openx url via GET, with mediaType specified as video', function () { const request = spec.buildRequests([videoBidWithDelDomainAndPlatform]); - expect(request[0].url).to.equal(`//u.openx.net${URLBASEVIDEO}`); + expect(request[0].url).to.equal(`https://u.openx.net${URLBASEVIDEO}`); expect(request[0].data.ph).to.equal(videoBidWithDelDomainAndPlatform.params.platform); expect(request[0].method).to.equal('GET'); }); @@ -310,7 +303,7 @@ describe('OpenxAdapter', function () { }); it('should send bid request to openx url via GET, with mediaType specified as video', function () { const request = spec.buildRequests([videoBidWithMediaType]); - expect(request[0].url).to.equal(`//${videoBidWithMediaType.params.delDomain}${URLBASEVIDEO}`); + expect(request[0].url).to.equal(`https://${videoBidWithMediaType.params.delDomain}${URLBASEVIDEO}`); expect(request[0].data.ph).to.be.undefined; expect(request[0].method).to.equal('GET'); }); @@ -367,7 +360,7 @@ describe('OpenxAdapter', function () { 'bidder': 'openx', 'params': { 'unit': '11', - 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00' }, 'adUnitCode': '/adunit-code/test-path', mediaTypes: { @@ -382,7 +375,7 @@ describe('OpenxAdapter', function () { 'bidder': 'openx', 'params': { 'unit': '11', - 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00' }, 'adUnitCode': '/adunit-code/test-path', mediaTypes: { @@ -397,21 +390,21 @@ describe('OpenxAdapter', function () { it('should send bid request to openx url via GET, with mediaType specified as banner', function () { const request = spec.buildRequests(bidRequestsWithMediaType); - expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASE); + expect(request[0].url).to.equal('https://' + bidRequestsWithMediaType[0].params.delDomain + URLBASE); expect(request[0].data.ph).to.be.undefined; expect(request[0].method).to.equal('GET'); }); it('should send bid request to openx url via GET, with mediaTypes specified with banner type', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); - expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASE); + expect(request[0].url).to.equal('https://' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASE); expect(request[0].data.ph).to.be.undefined; expect(request[0].method).to.equal('GET'); }); it('should send bid request to openx platform url via GET, if platform is present', function () { const request = spec.buildRequests(bidRequestsWithPlatform); - expect(request[0].url).to.equal(`//u.openx.net${URLBASE}`); + expect(request[0].url).to.equal(`https://u.openx.net${URLBASE}`); expect(request[0].data.ph).to.equal(bidRequestsWithPlatform[0].params.platform); expect(request[0].method).to.equal('GET'); }); @@ -422,7 +415,7 @@ describe('OpenxAdapter', function () { 'params': { 'unit': '11', 'delDomain': 'test-del-domain', - 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00' }, 'adUnitCode': '/adunit-code/test-path', mediaTypes: { @@ -438,7 +431,7 @@ describe('OpenxAdapter', function () { 'params': { 'unit': '11', 'delDomain': 'test-del-domain', - 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00', + 'platform': '1cabba9e-cafe-3665-beef-f00f00f00f00' }, 'adUnitCode': '/adunit-code/test-path', mediaTypes: { @@ -452,7 +445,7 @@ describe('OpenxAdapter', function () { }]; const request = spec.buildRequests(bidRequestsWithPlatformAndDelDomain); - expect(request[0].url).to.equal(`//u.openx.net${URLBASE}`); + expect(request[0].url).to.equal(`https://u.openx.net${URLBASE}`); expect(request[0].data.ph).to.equal(bidRequestsWithPlatform[0].params.platform); expect(request[0].method).to.equal('GET'); }); @@ -947,61 +940,6 @@ describe('OpenxAdapter', function () { expect(request[0].data.ns).to.equal(1); }); - describe('publisher common id query param', function() { - it('should not send a pubcid query param when there is no crumbs.pubcid defined in the bid requests', function () { - const request = spec.buildRequests(bidRequestsWithMediaType); - expect(request[0].data).to.not.have.any.keys('pubcid'); - }); - - it('should send a pubcid query param when crumbs.pubcid is defined in the bid requests', function () { - const bidRequestsWithPubcid = [{ - bidder: 'openx', - params: { - unit: '11', - delDomain: 'test-del-domain' - }, - crumbs: { - pubcid: 'c4a4c843-2368-4b5e-b3b1-6ee4702b9ad6' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bidId: 'test-bid-id-1', - bidderRequestId: 'test-bid-request-1', - auctionId: 'test-auction-1' - }]; - const request = spec.buildRequests(bidRequestsWithPubcid); - expect(request[0].data.pubcid).to.equal('c4a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); - }); - - it('should send a pubcid query param when userId.pubcid is defined in the bid requests', function () { - const bidRequestsWithPubcid = [{ - bidder: 'openx', - params: { - unit: '11', - delDomain: 'test-del-domain' - }, - userId: { - pubcid: 'c1a4c843-2368-4b5e-b3b1-6ee4702b9ad6' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bidId: 'test-bid-id-1', - bidderRequestId: 'test-bid-request-1', - auctionId: 'test-auction-1' - }]; - const request = spec.buildRequests(bidRequestsWithPubcid); - expect(request[0].data.pubcid).to.equal('c1a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); - }); - }) - describe('when schain is provided', function () { let bidRequests; let schainConfig; @@ -1109,6 +1047,125 @@ describe('OpenxAdapter', function () { }); }); }); + + describe('when there are userid providers', function () { + describe('with publisher common id', function () { + it('should not send a pubcid query param when there is no crumbs.pubcid and no userId.pubcid defined in the bid requests', function () { + const request = spec.buildRequests(bidRequestsWithMediaType); + expect(request[0].data).to.not.have.any.keys('pubcid'); + }); + + it('should send a pubcid query param when crumbs.pubcid is defined in the bid requests', function () { + const bidRequestsWithPubcid = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain' + }, + crumbs: { + pubcid: 'c4a4c843-2368-4b5e-b3b1-6ee4702b9ad6' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }]; + const request = spec.buildRequests(bidRequestsWithPubcid); + expect(request[0].data.pubcid).to.equal('c4a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); + }); + + it('should send a pubcid query param when userId.pubcid is defined in the bid requests', function () { + const bidRequestsWithPubcid = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain' + }, + userId: { + pubcid: 'c1a4c843-2368-4b5e-b3b1-6ee4702b9ad6' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }]; + const request = spec.buildRequests(bidRequestsWithPubcid); + expect(request[0].data.pubcid).to.equal('c1a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); + }); + }); + + describe('with the trade desk unified id', function () { + it('should not send a tdid query param when there is no userId.tdid defined in the bid requests', function () { + const request = spec.buildRequests(bidRequestsWithMediaType); + expect(request[0].data).to.not.have.any.keys('ttduuid'); + }); + + it('should send a tdid query param when userId.tdid is defined in the bid requests', function () { + const bidRequestsWithTdid = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain' + }, + userId: { + tdid: '00000000-aaaa-1111-bbbb-222222222222' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }]; + const request = spec.buildRequests(bidRequestsWithTdid); + expect(request[0].data.ttduuid).to.equal('00000000-aaaa-1111-bbbb-222222222222'); + }); + }); + + describe('with the liveRamp identity link envelope', function () { + it('should not send a tdid query param when there is no userId.lre defined in the bid requests', function () { + const request = spec.buildRequests(bidRequestsWithMediaType); + expect(request[0].data).to.not.have.any.keys('lre'); + }); + + it('should send a lre query param when userId.lre is defined in the bid requests', function () { + const bidRequestsWithLiveRampEnvelope = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain' + }, + userId: { + idl_env: '00000000-aaaa-1111-bbbb-222222222222' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }]; + const request = spec.buildRequests(bidRequestsWithLiveRampEnvelope); + expect(request[0].data.lre).to.equal('00000000-aaaa-1111-bbbb-222222222222'); + }); + }); + }); }); describe('buildRequests for video', function () { @@ -1148,13 +1205,13 @@ describe('OpenxAdapter', function () { it('should send bid request to openx url via GET, with mediaType as video', function () { const request = spec.buildRequests(bidRequestsWithMediaType); - expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASEVIDEO); + expect(request[0].url).to.equal('https://' + bidRequestsWithMediaType[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); it('should send bid request to openx url via GET, with mediaTypes having video parameter', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); - expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASEVIDEO); + expect(request[0].url).to.equal('https://' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); @@ -1261,6 +1318,34 @@ describe('OpenxAdapter', function () { }); }); + describe('buildRequest for multi-format ad', function () { + const multiformatBid = { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + playerSize: [300, 250] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; + + it('should send bid request to openx url via GET, with mediaType specified as banner', function () { + const request = spec.buildRequests([multiformatBid]); + expect(request[0].url).to.equal(`https://${multiformatBid.params.delDomain}${URLBASE}`); + }); + }); + describe('interpretResponse for banner ads', function () { beforeEach(function () { sinon.spy(userSync, 'registerSync'); @@ -1276,7 +1361,7 @@ describe('OpenxAdapter', function () { width: '300', height: '250', tracking: { - impression: 'http://openx-d.openx.net/v/1.0/ri?ts=ts' + impression: 'https://openx-d.openx.net/v/1.0/ri?ts=ts' } }; @@ -1311,7 +1396,7 @@ describe('OpenxAdapter', function () { bidRequest = { method: 'GET', - url: '//openx-d.openx.net/v/1.0/arj', + url: 'https://openx-d.openx.net/v/1.0/arj', data: {}, payload: {'bids': bidRequestConfigs, 'startTime': new Date()} }; @@ -1369,7 +1454,7 @@ describe('OpenxAdapter', function () { it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequest); - sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(new RegExp(`\/\/openx-d\.openx\.net.*\/bo\?.*ts=${adUnitOverride.ts}`))); + sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(new RegExp(`https:\/\/openx-d\.openx\.net.*\/bo\?.*ts=${adUnitOverride.ts}`))); }); }); @@ -1401,7 +1486,7 @@ describe('OpenxAdapter', function () { bidRequest = { method: 'GET', - url: '//openx-d.openx.net/v/1.0/arj', + url: 'https://openx-d.openx.net/v/1.0/arj', data: {}, payload: {'bids': bidRequestConfigs, 'startTime': new Date()} }; @@ -1437,7 +1522,7 @@ describe('OpenxAdapter', function () { bidRequest = { method: 'GET', - url: '//openx-d.openx.net/v/1.0/arj', + url: 'https://openx-d.openx.net/v/1.0/arj', data: {}, payload: {'bids': bidRequestConfigs, 'startTime': new Date()} }; @@ -1449,7 +1534,7 @@ describe('OpenxAdapter', function () { { 'version': 1, 'count': 1, - 'pixels': 'http://testpixels.net', + 'pixels': 'https://testpixels.net', 'ad': [] } }; @@ -1508,7 +1593,7 @@ describe('OpenxAdapter', function () { }]; const bidRequest = { method: 'GET', - url: '//openx-d.openx.net/v/1.0/arj', + url: 'https://openx-d.openx.net/v/1.0/arj', data: {}, payload: {'bids': bidRequests, 'startTime': new Date()} }; @@ -1590,13 +1675,13 @@ describe('OpenxAdapter', function () { }]; const bidRequestsWithMediaTypes = { method: 'GET', - url: '//openx-d.openx.net/v/1.0/avjp', + url: 'https://openx-d.openx.net/v/1.0/avjp', data: {}, payload: {'bid': bidsWithMediaTypes[0], 'startTime': new Date()} }; const bidRequestsWithMediaType = { method: 'GET', - url: '//openx-d.openx.net/v/1.0/avjp', + url: 'https://openx-d.openx.net/v/1.0/avjp', data: {}, payload: {'bid': bidsWithMediaType[0], 'startTime': new Date()} }; @@ -1605,8 +1690,8 @@ describe('OpenxAdapter', function () { 'width': '640', 'height': '480', 'adid': '5678', - 'vastUrl': 'http://testvast.com/vastpath?colo=http://test-colo.com&ph=test-ph&ts=test-ts', - 'pixels': 'http://testpixels.net' + 'vastUrl': 'https://testvast.com/vastpath?colo=https://test-colo.com&ph=test-ph&ts=test-ts', + 'pixels': 'https://testpixels.net' }; it('should return correct bid response with MediaTypes', function () { @@ -1618,7 +1703,7 @@ describe('OpenxAdapter', function () { 'height': '480', 'mediaType': 'video', 'creativeId': '5678', - 'vastUrl': 'http://testvast.com', + 'vastUrl': 'https://testvast.com', 'ttl': 300, 'netRevenue': true, 'currency': 'USD' @@ -1638,7 +1723,7 @@ describe('OpenxAdapter', function () { 'height': '480', 'mediaType': 'video', 'creativeId': '5678', - 'vastUrl': 'http://testvast.com', + 'vastUrl': 'https://testvast.com', 'ttl': 300, 'netRevenue': true, 'currency': 'USD' @@ -1664,14 +1749,14 @@ describe('OpenxAdapter', function () { it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); - sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/^\/\/test-colo\.com/)) + sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/^https:\/\/test-colo\.com/)); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/ph=test-ph/)); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/ts=test-ts/)); }); }); describe('user sync', function () { - const syncUrl = 'http://testpixels.net'; + const syncUrl = 'https://testpixels.net'; describe('iframe sync', function () { it('should register the pixel iframe from banner ad response', function () { @@ -1695,7 +1780,7 @@ describe('OpenxAdapter', function () { {iframeEnabled: true}, [] ); - expect(syncs).to.deep.equal([{type: 'iframe', url: '//u.openx.net/w/1.0/pd'}]); + expect(syncs).to.deep.equal([{type: 'iframe', url: 'https://u.openx.net/w/1.0/pd'}]); }); }); @@ -1721,7 +1806,7 @@ describe('OpenxAdapter', function () { {pixelEnabled: true}, [] ); - expect(syncs).to.deep.equal([{type: 'image', url: '//u.openx.net/w/1.0/pd'}]); + expect(syncs).to.deep.equal([{type: 'image', url: 'https://u.openx.net/w/1.0/pd'}]); }); }); @@ -1772,7 +1857,7 @@ describe('OpenxAdapter', function () { if (adUnits.length) { mockedArjResponse.ads.count = adUnits.length; - mockedArjResponse.ads.ad = adUnits.map((adUnit, index) => { + mockedArjResponse.ads.ad = adUnits.map((adUnit) => { overrideKeyCheck(adUnit, DEFAULT_TEST_ARJ_AD_UNIT, 'OxArjAdUnit'); return Object.assign(utils.deepClone(DEFAULT_TEST_ARJ_AD_UNIT), adUnit); }); @@ -1803,4 +1888,5 @@ describe('OpenxAdapter', function () { return mockedAdUnit; } -}); +}) +; From 562a889e3f55a68ad93206a3b21f221e8fb02df4 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 23 Sep 2019 11:20:29 -0700 Subject: [PATCH 1515/1594] PubMatic to support userId sub-modules (#4191) * added support for pubcommon, digitrust, id5id * added support for IdentityLink * changed the source for id5 * added unit test cases * changed source param for identityLink --- modules/pubmaticBidAdapter.js | 23 +++ test/spec/modules/pubmaticBidAdapter_spec.js | 186 +++++++++++++++++++ 2 files changed, 209 insertions(+) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index facecdaa578..d1e1d072673 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -624,10 +624,33 @@ function _handleTTDId(eids, validBidRequests) { } } +/** + * Produces external userid object in ortb 3.0 model. + */ +function _addExternalUserId(eids, value, source, atype) { + if (utils.isStr(value)) { + eids.push({ + source, + uids: [{ + id: value, + atype + }] + }); + } +} + function _handleEids(payload, validBidRequests) { let eids = []; _handleDigitrustId(eids); _handleTTDId(eids, validBidRequests); + const bidRequest = validBidRequests[0]; + if (bidRequest && bidRequest.userId) { + _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.pubcid`), 'pubcommon', 1); + _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.digitrustid.data.id`), 'digitru.st', 1); + _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.id5id`), 'id5-sync.com', 1); + _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.criteortus.${BIDDER_CODE}.userid`), 'criteortus', 1); + _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.idl_env`), 'liveramp.com', 1); + } if (eids.length > 0) { payload.user.eids = eids; } diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 3de83c56213..ababf2dcf5f 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1476,6 +1476,192 @@ describe('PubMatic adapter', function () { }); }); + describe('UserIds from request', function() { + describe('pubcommon Id', function() { + it('send the pubcommon id if it is present', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.pubcid = 'pub_common_user_id'; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'pubcommon', + 'uids': [{ + 'id': 'pub_common_user_id', + 'atype': 1 + }] + }]); + }); + + it('do not pass if not string', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.pubcid = 1; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.pubcid = []; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.pubcid = null; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.pubcid = {}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + }); + }); + + describe('Digitrust Id', function() { + it('send the digitrust id if it is present', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.digitrustid = {data: {id: 'digitrust_user_id'}}; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'digitru.st', + 'uids': [{ + 'id': 'digitrust_user_id', + 'atype': 1 + }] + }]); + }); + + it('do not pass if not string', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.digitrustid = {data: {id: 1}}; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.digitrustid = {data: {id: []}}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.digitrustid = {data: {id: null}}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.digitrustid = {data: {id: {}}}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + }); + }); + + describe('ID5 Id', function() { + it('send the id5 id if it is present', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.id5id = 'id5-user-id'; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'id5-sync.com', + 'uids': [{ + 'id': 'id5-user-id', + 'atype': 1 + }] + }]); + }); + + it('do not pass if not string', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.id5id = 1; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.id5id = []; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.id5id = null; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.id5id = {}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + }); + }); + + describe('CriteoRTUS Id', function() { + it('send the criteo id if it is present', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.criteortus = {pubmatic: {userid: 'criteo-rtus-user-id'}}; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'criteortus', + 'uids': [{ + 'id': 'criteo-rtus-user-id', + 'atype': 1 + }] + }]); + }); + + it('do not pass if not string', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.criteortus = {appnexus: {userid: 'criteo-rtus-user-id'}}; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.criteortus = {pubmatic: {userid: 1}}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.criteortus = {pubmatic: {userid: []}}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.criteortus = {pubmatic: {userid: null}}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.criteortus = {pubmatic: {userid: {}}}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + }); + }); + + describe('IdentityLink Id', function() { + it('send the identity-link id if it is present', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.idl_env = 'identity-link-user-id'; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'liveramp.com', + 'uids': [{ + 'id': 'identity-link-user-id', + 'atype': 1 + }] + }]); + }); + + it('do not pass if not string', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.idl_env = 1; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.idl_env = []; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.idl_env = null; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.idl_env = {}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + }); + }); + }) + it('Request params check for video ad', function () { let request = spec.buildRequests(videoBidRequests); let data = JSON.parse(request.data); From f81b5678f69a806b0f004627b26cae9a5695b584 Mon Sep 17 00:00:00 2001 From: Will Chapin Date: Mon, 23 Sep 2019 14:25:00 -0400 Subject: [PATCH 1516/1594] TripleLift support for UnifiedId and IdentityLink (#4197) * Add IdentityLink support and fix UnifiedId. It appears we've been looking for UnifiedId userIds on the bidderRequest object, when they are found on bidRequests. This commit fixes that error, and adds support for IdentityLink. * change maintainer email to group --- modules/tripleliftBidAdapter.js | 56 +++--- modules/tripleliftBidAdapter.md | 2 +- .../spec/modules/tripleliftBidAdapter_spec.js | 164 ++++++++++++++---- 3 files changed, 163 insertions(+), 59 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 2d6b2dce8de..5ed88384b11 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -17,7 +17,7 @@ export const tripleliftAdapterSpec = { buildRequests: function(bidRequests, bidderRequest) { let tlCall = STR_ENDPOINT; - let data = _buildPostBody(bidRequests, bidderRequest); + let data = _buildPostBody(bidRequests); tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); @@ -78,7 +78,7 @@ export const tripleliftAdapterSpec = { } } -function _buildPostBody(bidRequests, bidderRequest) { +function _buildPostBody(bidRequests) { let data = {}; data.imp = bidRequests.map(function(bid, index) { return { @@ -91,7 +91,11 @@ function _buildPostBody(bidRequests, bidderRequest) { }; }); - let eids = handleConsortiaUserIds(bidderRequest); + let eids = [ + ...getUnifiedIdEids(bidRequests), + ...getIdentityLinkEids(bidRequests) + ]; + if (eids.length > 0) { data.user = { ext: {eids} @@ -101,6 +105,35 @@ function _buildPostBody(bidRequests, bidderRequest) { return data; } +function getUnifiedIdEids(bidRequests) { + return getEids(bidRequests, 'tdid', 'adserver.org', 'TDID'); +} + +function getIdentityLinkEids(bidRequests) { + return getEids(bidRequests, 'idl_env', 'liveramp.com', 'idl'); +} + +function getEids(bidRequests, type, source, rtiPartner) { + return bidRequests + .map(getUserId(type)) // bids -> userIds of a certain type + .filter((x) => !!x) // filter out null userIds + .map(formatEid(source, rtiPartner)); // userIds -> eid objects +} + +function getUserId(type) { + return (bid) => (bid && bid.userId && bid.userId[type]); +} + +function formatEid(source, rtiPartner) { + return (id) => ({ + source, + uids: [{ + id, + ext: { rtiPartner } + }] + }); +} + function _sizes(sizeArray) { let sizes = sizeArray.filter(_isValidSize); return sizes.map(function(size) { @@ -115,23 +148,6 @@ function _isValidSize(size) { return (size.length === 2 && typeof size[0] === 'number' && typeof size[1] === 'number'); } -function handleConsortiaUserIds(bidderRequest) { - let eids = []; - if (bidderRequest.userId && bidderRequest.userId.tdid) { - eids.push({ - source: 'adserver.org', - uids: [{ - id: bidderRequest.userId.tdid, - ext: { - rtiPartner: 'TDID' - } - }] - }); - } - - return eids; -} - function _buildResponseObject(bidderRequest, bid) { let bidResponse = {}; let width = bid.width || 1; diff --git a/modules/tripleliftBidAdapter.md b/modules/tripleliftBidAdapter.md index c10ea3675d4..d5f88a2bece 100644 --- a/modules/tripleliftBidAdapter.md +++ b/modules/tripleliftBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Triplelift Bid Adapter Module Type: Bidder Adapter -Maintainer: csmith+s2s@triplelift.com +Maintainer: prebid@triplelift.com ``` # Description diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 52a7be3020c..190f463f7a5 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -54,46 +54,49 @@ describe('triplelift adapter', function () { }); describe('buildRequests', function () { - let bidRequests = [ - { - bidder: 'triplelift', - params: { - inventoryCode: '12345', - floor: 1.0, - }, - adUnitCode: 'adunit-code', - sizes: [[300, 250], [300, 600], [1, 1, 1], ['flex']], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - } - ]; + let bidRequests; + let bidderRequest; - let bidderRequest = { - bidderCode: 'triplelift', - auctionId: 'a7ebcd1d-66ff-4b5c-a82c-6a21a6ee5a18', - bidderRequestId: '5c55612f99bc11', - bids: [ + this.beforeEach(() => { + bidRequests = [ { - imp_id: 0, - cpm: 1.062, - width: 300, - height: 250, - ad: 'ad-markup', - iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + bidder: 'triplelift', + params: { + inventoryCode: '12345', + floor: 1.0, + }, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600], [1, 1, 1], ['flex']], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + userId: {}, } - ], - refererInfo: { - referer: 'http://examplereferer.com' - }, - gdprConsent: { - consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', - gdprApplies: true - }, - userId: { - tdid: '6bca7f6b-a98a-46c0-be05-6020f7604598' - } - }; + ]; + + bidderRequest = { + bidderCode: 'triplelift', + auctionId: 'a7ebcd1d-66ff-4b5c-a82c-6a21a6ee5a18', + bidderRequestId: '5c55612f99bc11', + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 250, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ], + refererInfo: { + referer: 'http://examplereferer.com' + }, + gdprConsent: { + consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', + gdprApplies: true + }, + }; + }); it('exists and is an object', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); @@ -116,10 +119,95 @@ describe('triplelift adapter', function () { }); it('should add tdid to the payload if included', function () { + const id = '6bca7f6b-a98a-46c0-be05-6020f7604598'; + bidRequests[0].userId.tdid = id; + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); + const payload = request.data; + expect(payload).to.exist; + expect(payload.user).to.deep.equal({ext: {eids: [{source: 'adserver.org', uids: [{id, ext: {rtiPartner: 'TDID'}}]}]}}); + }); + + it('should add idl_env to the payload if included', function () { + const id = 'XY6104gr0njcH9UDIR7ysFFJcm2XNpqeJTYslleJ_cMlsFOfZI'; + bidRequests[0].userId.idl_env = id; + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); + const payload = request.data; + expect(payload).to.exist; + expect(payload.user).to.deep.equal({ext: {eids: [{source: 'liveramp.com', uids: [{id, ext: {rtiPartner: 'idl'}}]}]}}); + }); + + it('should add both tdid and idl_env to the payload if both are included', function () { + const tdidId = '6bca7f6b-a98a-46c0-be05-6020f7604598'; + const idlEnvId = 'XY6104gr0njcH9UDIR7ysFFJcm2XNpqeJTYslleJ_cMlsFOfZI'; + bidRequests[0].userId.tdid = tdidId; + bidRequests[0].userId.idl_env = idlEnvId; + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const payload = request.data; + expect(payload).to.exist; - expect(payload.user).to.deep.equal({ext: {eids: [{source: 'adserver.org', uids: [{id: '6bca7f6b-a98a-46c0-be05-6020f7604598', ext: {rtiPartner: 'TDID'}}]}]}}); + expect(payload.user).to.deep.equal({ + ext: { + eids: [ + { + source: 'adserver.org', + uids: [ + { + id: tdidId, + ext: { rtiPartner: 'TDID' } + } + ], + }, + { + source: 'liveramp.com', + uids: [ + { + id: idlEnvId, + ext: { rtiPartner: 'idl' } + } + ] + } + ] + } + }); + }); + + it('should add user ids from multiple bid requests', function () { + const tdidId = '6bca7f6b-a98a-46c0-be05-6020f7604598'; + const idlEnvId = 'XY6104gr0njcH9UDIR7ysFFJcm2XNpqeJTYslleJ_cMlsFOfZI'; + + const bidRequestsMultiple = [ + { ...bidRequests[0], userId: { tdid: tdidId } }, + { ...bidRequests[0], userId: { idl_env: idlEnvId } }, + ]; + + const request = tripleliftAdapterSpec.buildRequests(bidRequestsMultiple, bidderRequest); + const payload = request.data; + + expect(payload.user).to.deep.equal({ + ext: { + eids: [ + { + source: 'adserver.org', + uids: [ + { + id: tdidId, + ext: { rtiPartner: 'TDID' } + } + ], + }, + { + source: 'liveramp.com', + uids: [ + { + id: idlEnvId, + ext: { rtiPartner: 'idl' } + } + ] + } + ] + } + }); }); it('should return a query string for TL call', function () { From 8544dbff10e388fa0bf1915b46ad7265776b83b6 Mon Sep 17 00:00:00 2001 From: Lemma Dev <54662130+lemmadev@users.noreply.github.com> Date: Tue, 24 Sep 2019 02:57:17 +0530 Subject: [PATCH 1517/1594] Added lemma adapter (#4126) * lemmaBidAdapter.js Added lemma bid adapter file * lemmaBidAdapter.md Added lemma bid adapter md file * lemmaBidAdapter_spec.js Added lemma bid adapter test spec file * Update lemmaBidAdapter.js Fixed automated code review alert comparison between inconvertible types * Update lemmaBidAdapter.js Fixed review changes * Update lemmaBidAdapter.md Correct parameter value. --- modules/lemmaBidAdapter.js | 401 ++++++++++++++++++++++ modules/lemmaBidAdapter.md | 67 ++++ test/spec/modules/lemmaBidAdapter_spec.js | 335 ++++++++++++++++++ 3 files changed, 803 insertions(+) create mode 100644 modules/lemmaBidAdapter.js create mode 100644 modules/lemmaBidAdapter.md create mode 100644 test/spec/modules/lemmaBidAdapter_spec.js diff --git a/modules/lemmaBidAdapter.js b/modules/lemmaBidAdapter.js new file mode 100644 index 00000000000..ed97b1db052 --- /dev/null +++ b/modules/lemmaBidAdapter.js @@ -0,0 +1,401 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; + +var BIDDER_CODE = 'lemma'; +var LOG_WARN_PREFIX = 'LEMMA: '; +var ENDPOINT = '//ads.lemmatechnologies.com/lemma/servad'; +var DEFAULT_CURRENCY = 'USD'; +var AUCTION_TYPE = 2; +var DEFAULT_TMAX = 300; +var DEFAULT_NET_REVENUE = false; + +export var spec = { + + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + + isBidRequestValid: bid => { + if (bid && bid.params) { + if (!utils.isNumber(bid.params.pubId)) { + utils.logWarn(LOG_WARN_PREFIX + 'Error: publisherId is mandatory and cannot be string. Call to OpenBid will not be sent for ad unit: ' + JSON.stringify(bid)); + return false; + } + if (!bid.params.adunitId) { + utils.logWarn(LOG_WARN_PREFIX + 'Error: adUnitId is mandatory. Call to OpenBid will not be sent for ad unit: ' + JSON.stringify(bid)); + return false; + } + // video ad validation + if (bid.params.hasOwnProperty('video')) { + if (!bid.params.video.hasOwnProperty('mimes') || !utils.isArray(bid.params.video.mimes) || bid.params.video.mimes.length === 0) { + utils.logWarn(LOG_WARN_PREFIX + 'Error: For video ads, mimes is mandatory and must specify atlease 1 mime value. Call to OpenBid will not be sent for ad unit:' + JSON.stringify(bid)); + return false; + } + } + return true; + } + return false; + }, + buildRequests: (bidRequests, bidderRequest) => { + var refererInfo; + if (bidderRequest && bidderRequest.refererInfo) { + refererInfo = bidderRequest.refererInfo; + } + var conf = _initConf(refererInfo); + const request = oRTBTemplate(bidRequests, conf); + if (request.imp.length == 0) { + return; + } + setOtherParams(bidderRequest, request); + const endPoint = endPointURL(bidRequests); + return { + method: 'POST', + url: endPoint, + data: JSON.stringify(request), + }; + }, + interpretResponse: (response, request) => { + return parseRTBResponse(request, response.body); + }, +}; + +function _initConf(refererInfo) { + var conf = {}; + conf.pageURL = utils.getTopWindowUrl(); + if (refererInfo && refererInfo.referer) { + conf.refURL = refererInfo.referer; + } else { + conf.refURL = ''; + } + return conf; +} + +function parseRTBResponse(request, response) { + var bidResponses = []; + try { + if (response.seatbid) { + var currency = response.curr || DEFAULT_CURRENCY; + var seatbid = response.seatbid; + seatbid.forEach(seatbidder => { + var bidder = seatbidder.bid; + bidder.forEach(bid => { + var req = parse(request.data); + var newBid = { + requestId: bid.impid, + cpm: parseFloat(bid.price).toFixed(2), + width: bid.w, + height: bid.h, + creativeId: bid.crid, + currency: currency, + netRevenue: DEFAULT_NET_REVENUE, + ttl: 300, + referrer: req.site.ref, + ad: bid.adm + }; + if (bid.dealid) { + newBid.dealId = bid.dealid; + } + if (req.imp && req.imp.length > 0) { + newBid.mediaType = req.mediaType; + req.imp.forEach(robj => { + if (bid.impid === robj.id) { + switch (newBid.mediaType) { + case BANNER: + break; + case VIDEO: + newBid.width = bid.hasOwnProperty('w') ? bid.w : robj.video.w; + newBid.height = bid.hasOwnProperty('h') ? bid.h : robj.video.h; + newBid.vastXml = bid.adm; + break; + } + } + }); + } + bidResponses.push(newBid); + }); + }); + } + } catch (error) { + utils.logError(LOG_WARN_PREFIX, 'ERROR ', error); + } + return bidResponses; +} + +function oRTBTemplate(bidRequests, conf) { + try { + var oRTBObject = { + id: '' + new Date().getTime(), + at: AUCTION_TYPE, + tmax: DEFAULT_TMAX, + cur: [DEFAULT_CURRENCY], + imp: _getImpressionArray(bidRequests), + user: {}, + ext: {} + }; + var bid = bidRequests[0]; + var app = _getAppObject(bid); + var site = _getSiteObject(bid, conf); + var device = _getDeviceObject(bid); + if (app) { + oRTBObject.app = app; + } + if (site) { + oRTBObject.site = site; + } + if (device) { + oRTBObject.device = device; + } + return oRTBObject; + } catch (ex) { + utils.logError(LOG_WARN_PREFIX, 'ERROR ', ex); + } +} + +function _getImpressionArray(request) { + var impArray = []; + var map = request.map(bid => _getImpressionObject(bid)); + if (map) { + map.forEach(o => { + if (o) { + impArray.push(o); + } + }); + } + return impArray; +} + +function endPointURL(request) { + var params = request && request[0].params ? request[0].params : null; + if (params) { + var pubId = params.pubId ? params.pubId : 0; + var adunitId = params.adunitId ? params.adunitId : 0; + return ENDPOINT + '?pid=' + pubId + '&aid=' + adunitId; + } + return null; +} + +function _getDomain(url) { + var a = document.createElement('a'); + a.setAttribute('href', url); + return a.hostname; +} + +function _getSiteObject(request, conf) { + var params = request && request.params ? request.params : null; + if (params) { + var pubId = params.pubId ? params.pubId : '0'; + var siteId = params.siteId ? params.siteId : '0'; + var appParams = params.app; + if (!appParams) { + return { + publisher: { + id: pubId.toString() + }, + domain: _getDomain(conf.pageURL), + id: siteId.toString(), + ref: conf.refURL, + page: conf.pageURL + }; + } + } + return null; +} + +function _getAppObject(request) { + var params = request && request.params ? request.params : null; + if (params) { + var pubId = params.pubId ? params.pubId : 0; + var appParams = params.app; + if (appParams) { + return { + publisher: { + id: pubId.toString(), + }, + id: appParams.id, + name: appParams.name, + bundle: appParams.bundle, + storeurl: appParams.storeUrl, + domain: appParams.domain, + cat: appParams.categories, + pagecat: appParams.page_category + }; + } + } + return null; +} + +function _getDeviceObject(request) { + var params = request && request.params ? request.params : null; + if (params) { + return { + dnt: utils.getDNT() ? 1 : 0, + ua: navigator.userAgent, + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), + w: (window.screen.width || window.innerWidth), + h: (window.screen.height || window.innerHeigh), + geo: { + country: params.country, + lat: params.latitude, + lon: params.longitude, + region: params.region, + city: params.city, + zip: params.zip + }, + ip: params.ip, + devicetype: params.device_type, + ifa: params.ifa, + }; + } + return null; +} + +function setOtherParams(request, ortbRequest) { + var params = request && request.params ? request.params : null; + if (request && request.gdprConsent) { + ortbRequest.regs = { ext: { gdpr: request.gdprConsent.gdprApplies ? 1 : 0 } }; + ortbRequest.user = { ext: { consent: request.gdprConsent.consentString } }; + } + if (params) { + ortbRequest.tmax = params.tmax; + ortbRequest.bcat = params.bcat; + } +} + +function _getSizes(request) { + if (request.sizes && utils.isArray(request.sizes[0]) && request.sizes[0].length > 0) { + return request.sizes[0]; + } + return null; +} + +function _getBannerRequest(bid) { + var bObj; + var adFormat = []; + if (bid.mediaType === 'banner' || utils.deepAccess(bid, 'mediaTypes.banner')) { + var params = bid ? bid.params : null; + var bannerData = params.banner; + var sizes = _getSizes(bid) || []; + if (sizes && sizes.length == 0) { + sizes = bid.mediaTypes.banner.sizes[0]; + } + if (sizes && sizes.length > 0) { + bObj = {}; + bObj.w = sizes[0]; + bObj.h = sizes[1]; + bObj.pos = 0; + if (bannerData) { + bObj = utils.deepClone(bannerData); + } + sizes = bid.mediaTypes.banner.sizes; + if (sizes.length > 0) { + adFormat = []; + sizes.forEach(function(size) { + if (size.length > 1) { + adFormat.push({ w: size[0], h: size[1] }); + } + }); + if (adFormat.length > 0) { + bObj.format = adFormat; + } + } + } else { + utils.logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.sizes missing for adunit: ' + bid.params.adunitId); + } + } + return bObj; +} + +function _getVideoRequest(bid) { + var vObj; + if (bid.mediaType === 'video' || utils.deepAccess(bid, 'mediaTypes.video')) { + var params = bid ? bid.params : null; + var sizes = _getSizes(bid) || []; + if (sizes && sizes.length == 0) { + sizes = bid.mediaTypes && bid.mediaTypes.video ? bid.mediaTypes.video.playerSize : []; + } + if (sizes && sizes.length > 0) { + var videoData = params.video; + vObj = {}; + if (videoData) { + vObj = utils.deepClone(videoData); + } + vObj.w = sizes[0]; + vObj.h = sizes[1]; + } else { + utils.logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.video.sizes missing for adunit: ' + bid.params.adunitId); + } + } + return vObj; +} + +function _getImpressionObject(bid) { + var impression = {}; + var bObj; + var vObj; + var sizes = bid.hasOwnProperty('sizes') ? bid.sizes : []; + var mediaTypes = ''; + var format = []; + var params = bid && bid.params ? bid.params : null; + impression = { + id: bid.bidId, + tagid: params.adunitId ? params.adunitId.toString() : undefined, + secure: window.location.protocol === 'https:' ? 1 : 0, + bidfloorcur: params.currency ? params.currency : DEFAULT_CURRENCY + }; + + if (params.bidFloor) { + impression.bidfloor = params.bidFloor; + } + + if (bid.hasOwnProperty('mediaTypes')) { + for (mediaTypes in bid.mediaTypes) { + switch (mediaTypes) { + case BANNER: + bObj = _getBannerRequest(bid); + if (bObj) { + impression.banner = bObj; + } + break; + case VIDEO: + vObj = _getVideoRequest(bid); + if (vObj) { + impression.video = vObj; + } + break; + } + } + } else { + bObj = { + pos: 0, + w: sizes && sizes[0] ? sizes[0][0] : 0, + h: sizes && sizes[0] ? sizes[0][1] : 0, + }; + if (utils.isArray(sizes) && sizes.length > 1) { + sizes = sizes.splice(1, sizes.length - 1); + sizes.forEach(size => { + format.push({ + w: size[0], + h: size[1] + }); + }); + bObj.format = format; + } + impression.banner = bObj; + } + + return impression.hasOwnProperty(BANNER) || + impression.hasOwnProperty(VIDEO) ? impression : undefined; +} + +function parse(rawResp) { + try { + if (rawResp) { + return JSON.parse(rawResp); + } + } catch (ex) { + utils.logError(LOG_WARN_PREFIX, 'ERROR', ex); + } + return null; +} + +registerBidder(spec); diff --git a/modules/lemmaBidAdapter.md b/modules/lemmaBidAdapter.md new file mode 100644 index 00000000000..80c1a52b9d6 --- /dev/null +++ b/modules/lemmaBidAdapter.md @@ -0,0 +1,67 @@ +# Overview + +``` +Module Name: Lemma Bid Adapter +Module Type: Bidder Adapter +Maintainer: lemmadev@lemmatechnologies.com +``` + +# Description + +Connects to Lemma exchange for bids. +Lemma bid adapter supports Video, Banner formats. + +# Sample Banner Ad Unit: For Publishers +``` +var adUnits = [{ + code: 'div-lemma-ad-1', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], // required + } + }, + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'lemma', + params: { + pubId: 1, // required + adunitId: '3768', // required + latitude: 37.3230, + longitude: -122.0322, + device_type: 2, + banner: { + w: 300, + h: 250 + } + } + }] +}]; +``` + +# Sample Video Ad Unit: For Publishers +``` +var adUnits = [{ + mediaType: 'video', + sizes: [[640, 480]], + mediaTypes: { + video: { + playerSize: [640, 480], // required + context: 'instream' + } + }, + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'lemma', + params: { + pubId: 1, // required + adunitId: '3769', // required + latitude: 37.3230, + longitude: -122.0322, + device_type: 4, + video: { + mimes: ['video/mp4','video/x-flv'], // required + } + } + }] +}]; +``` diff --git a/test/spec/modules/lemmaBidAdapter_spec.js b/test/spec/modules/lemmaBidAdapter_spec.js new file mode 100644 index 00000000000..624e763ebe1 --- /dev/null +++ b/test/spec/modules/lemmaBidAdapter_spec.js @@ -0,0 +1,335 @@ +import { expect } from 'chai'; +import { spec } from 'modules/lemmaBidAdapter'; +import * as utils from 'src/utils'; +const constants = require('src/constants.json'); + +describe('lemmaBidAdapter', function() { + var bidRequests; + var videoBidRequests; + var bidResponses; + beforeEach(function() { + bidRequests = [{ + bidder: 'lemma', + mediaType: 'banner', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ], + } + }, + params: { + pubId: 1001, + adunitId: 1, + currency: 'AUD', + geo: { + lat: '12.3', + lon: '23.7', + } + }, + sizes: [ + [300, 250], + [300, 600] + ] + }]; + videoBidRequests = [{ + code: 'video1', + mediaType: 'video', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bidder: 'lemma', + params: { + pubId: 1001, + adunitId: 1, + video: { + mimes: ['video/mp4', 'video/x-flv'], + skippable: true, + minduration: 5, + maxduration: 30 + } + } + }]; + bidResponses = { + 'body': { + 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', + 'seatbid': [{ + 'bid': [{ + 'id': '74858439-49D7-4169-BA5D-44A046315B2F', + 'impid': '22bddb28db77d', + 'price': 1.3, + 'adm': '

    lemma"Connecting Advertisers and Publishers directly"

    ', + 'adomain': ['amazon.com'], + 'iurl': 'https://thetradedesk-t-general.s3.amazonaws.com/AdvertiserLogos/vgl908z.png', + 'cid': '22918', + 'crid': 'v55jutrh', + 'h': 250, + 'w': 300, + 'ext': {} + }] + }] + } + }; + }); + describe('implementation', function() { + describe('Bid validations', function() { + it('valid bid case', function() { + var validBid = { + bidder: 'lemma', + params: { + pubId: 1001, + adunitId: 1 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + it('invalid bid case', function() { + var isValid = spec.isBidRequestValid(); + expect(isValid).to.equal(false); + }); + it('invalid bid case: pubId not passed', function() { + var validBid = { + bidder: 'lemma', + params: { + adunitId: 1 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + it('invalid bid case: pubId is not number', function() { + var validBid = { + bidder: 'lemma', + params: { + pubId: '301', + adunitId: 1 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + it('invalid bid case: adunitId is not passed', function() { + var validBid = { + bidder: 'lemma', + params: { + pubId: 1001 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + it('invalid bid case: video bid request mimes is not passed', function() { + var validBid = { + bidder: 'lemma', + params: { + pubId: 1001, + adunitId: 1, + video: { + skippable: true, + minduration: 5, + maxduration: 30 + } + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + validBid.params.video.mimes = []; + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + }); + describe('Request formation', function() { + it('buildRequests function should not modify original bidRequests object', function() { + var originalBidRequests = utils.deepClone(bidRequests); + var request = spec.buildRequests(bidRequests); + expect(bidRequests).to.deep.equal(originalBidRequests); + }); + it('Endpoint checking', function() { + var request = spec.buildRequests(bidRequests); + expect(request.url).to.equal('//ads.lemmatechnologies.com/lemma/servad?pid=1001&aid=1'); + expect(request.method).to.equal('POST'); + }); + it('Request params check', function() { + var request = spec.buildRequests(bidRequests); + var data = JSON.parse(request.data); + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.publisher.id).to.equal(bidRequests[0].params.pubId.toString()); // publisher Id + expect(data.imp[0].tagid).to.equal('1'); // tagid + expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); + }); + it('Request params check without mediaTypes object', function() { + var bidRequests = [{ + bidder: 'lemma', + params: { + pubId: 1001, + adunitId: 1, + currency: 'AUD' + }, + sizes: [ + [300, 250], + [300, 600] + ] + }]; + var request = spec.buildRequests(bidRequests); + var data = JSON.parse(request.data); + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].banner.format).exist.and.to.be.an('array'); + expect(data.imp[0].banner.format[0]).exist.and.to.be.an('object'); + expect(data.imp[0].banner.format[0].w).to.equal(300); // width + expect(data.imp[0].banner.format[0].h).to.equal(600); // height + }); + it('Request params check: without tagId', function() { + delete bidRequests[0].params.adunitId; + var request = spec.buildRequests(bidRequests); + var data = JSON.parse(request.data); + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.publisher.id).to.equal(bidRequests[0].params.pubId.toString()); // publisher Id + expect(data.imp[0].tagid).to.equal(undefined); // tagid + expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); + }); + it('Request params multi size format object check', function() { + var bidRequests = [{ + bidder: 'lemma', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ], + } + }, + params: { + pubId: 1001, + adunitId: 1, + currency: 'AUD' + }, + sizes: [ + [300, 250], + [300, 600] + ] + }]; + /* case 1 - size passed in adslot */ + var request = spec.buildRequests(bidRequests); + var data = JSON.parse(request.data); + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + /* case 2 - size passed in adslot as well as in sizes array */ + bidRequests[0].sizes = [ + [300, 600], + [300, 250] + ]; + bidRequests[0].mediaTypes = { + banner: { + sizes: [ + [300, 600], + [300, 250] + ] + } + }; + request = spec.buildRequests(bidRequests); + data = JSON.parse(request.data); + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(600); // height + /* case 3 - size passed in sizes but not in adslot */ + bidRequests[0].params.adunitId = 1; + bidRequests[0].sizes = [ + [300, 250], + [300, 600] + ]; + bidRequests[0].mediaTypes = { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + }; + request = spec.buildRequests(bidRequests); + data = JSON.parse(request.data); + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].banner.format).exist.and.to.be.an('array'); + expect(data.imp[0].banner.format[0]).exist.and.to.be.an('object'); + expect(data.imp[0].banner.format[0].w).to.equal(300); // width + expect(data.imp[0].banner.format[0].h).to.equal(250); // height + }); + it('Request params currency check', function() { + var bidRequest = [{ + bidder: 'lemma', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ], + } + }, + params: { + pubId: 1001, + adunitId: 1, + currency: 'AUD' + }, + sizes: [ + [300, 250], + [300, 600] + ] + }]; + /* case 1 - + currency specified in adunits + output: imp[0] use currency specified in bidRequests[0].params.currency + */ + var request = spec.buildRequests(bidRequest); + var data = JSON.parse(request.data); + expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); + /* case 2 - + currency specified in adunit + output: imp[0] use default currency - USD + */ + delete bidRequest[0].params.currency; + request = spec.buildRequests(bidRequest); + data = JSON.parse(request.data); + expect(data.imp[0].bidfloorcur).to.equal('USD'); + }); + it('Request params check for video ad', function() { + var request = spec.buildRequests(videoBidRequests); + var data = JSON.parse(request.data); + expect(data.imp[0].video).to.exist; + expect(data.imp[0].tagid).to.equal('1'); + expect(data.imp[0]['video']['mimes']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['mimes'][0]).to.equal(videoBidRequests[0].params.video['mimes'][0]); + expect(data.imp[0]['video']['mimes'][1]).to.equal(videoBidRequests[0].params.video['mimes'][1]); + expect(data.imp[0]['video']['minduration']).to.equal(videoBidRequests[0].params.video['minduration']); + expect(data.imp[0]['video']['maxduration']).to.equal(videoBidRequests[0].params.video['maxduration']); + 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]); + }); + describe('Response checking', function() { + it('should check for valid response values', function() { + var request = spec.buildRequests(bidRequests); + var data = JSON.parse(request.data); + var response = spec.interpretResponse(bidResponses, request); + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].requestId).to.equal(bidResponses.body.seatbid[0].bid[0].impid); + expect(response[0].cpm).to.equal((bidResponses.body.seatbid[0].bid[0].price).toFixed(2)); + expect(response[0].width).to.equal(bidResponses.body.seatbid[0].bid[0].w); + expect(response[0].height).to.equal(bidResponses.body.seatbid[0].bid[0].h); + if (bidResponses.body.seatbid[0].bid[0].crid) { + expect(response[0].creativeId).to.equal(bidResponses.body.seatbid[0].bid[0].crid); + } else { + expect(response[0].creativeId).to.equal(bidResponses.body.seatbid[0].bid[0].id); + } + expect(response[0].dealId).to.equal(bidResponses.body.seatbid[0].bid[0].dealid); + expect(response[0].currency).to.equal('USD'); + expect(response[0].netRevenue).to.equal(false); + expect(response[0].ttl).to.equal(300); + }); + }); + }); + }); +}); From 565180027b18d7add0d65bf7d1381275411fa2fa Mon Sep 17 00:00:00 2001 From: Denis Logachov Date: Tue, 24 Sep 2019 19:07:10 +0300 Subject: [PATCH 1518/1594] Adkernel adapter new alias (#4221) --- modules/adkernelBidAdapter.js | 2 +- test/spec/modules/adkernelBidAdapter_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 7c48458f474..a5f8f65634d 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -23,7 +23,7 @@ const VERSION = '1.3'; export const spec = { code: 'adkernel', - aliases: ['headbidding', 'adsolut', 'oftmediahb'], + aliases: ['headbidding', 'adsolut', 'oftmediahb', 'audiencemedia'], supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bidRequest) { return 'params' in bidRequest && diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index 621b9971304..1f221cd956e 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -379,8 +379,8 @@ describe('Adkernel adapter', function () { describe('adapter configuration', () => { it('should have aliases', () => { - expect(spec.aliases).to.have.lengthOf(3); - expect(spec.aliases).to.be.eql(['headbidding', 'adsolut', 'oftmediahb']); + expect(spec.aliases).to.have.lengthOf(4); + expect(spec.aliases).to.be.eql(['headbidding', 'adsolut', 'oftmediahb', 'audiencemedia']); }); }); }); From 991b94d793249815fc4d32f3e13ea0505f098824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Tue, 24 Sep 2019 18:10:32 +0200 Subject: [PATCH 1519/1594] Force https scheme for Criteo Bidder (#4227) * assign adapter version number * Ensure that Criteo's bidder is always called through https --- modules/criteoBidAdapter.js | 4 ++-- test/spec/modules/criteoBidAdapter_spec.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 559c02cd4a9..86f289421ce 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -8,9 +8,9 @@ import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -export const ADAPTER_VERSION = 20; +export const ADAPTER_VERSION = 21; const BIDDER_CODE = 'criteo'; -const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; +const CDB_ENDPOINT = 'https://bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; const PROFILE_ID_INLINE = 207; export const PROFILE_ID_PUBLISHERTAG = 185; diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index f85e5957950..03500d4add6 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -404,7 +404,7 @@ describe('The Criteo bidding adapter', function () { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d+&im=1&debug=1&nolog=1/); + expect(request.url).to.match(/^https:\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d+&im=1&debug=1&nolog=1/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(publisherUrl); @@ -448,7 +448,7 @@ describe('The Criteo bidding adapter', function () { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); + 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.publisher.url).to.equal(utils.getTopWindowUrl()); @@ -487,7 +487,7 @@ describe('The Criteo bidding adapter', function () { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); + 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.publisher.url).to.equal(utils.getTopWindowUrl()); @@ -557,7 +557,7 @@ describe('The Criteo bidding adapter', function () { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); + 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].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); @@ -601,7 +601,7 @@ describe('The Criteo bidding adapter', function () { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); + 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].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); From 4be849535cce31fe9dd2738080d9b4020bd763e4 Mon Sep 17 00:00:00 2001 From: htang555 Date: Tue, 24 Sep 2019 13:04:22 -0400 Subject: [PATCH 1520/1594] Add Video Support for Datablocks Bid Adapter (#4195) * add datablocks Analytics and Bidder Adapters * remove preload param * remove preloadid * better coverage of tests * better coverage * IE doesn't support array.find * lint test * update example host * native asset id should be integer * add datablocks Video * remove isInteger * skip if empty --- modules/datablocksBidAdapter.js | 54 +++++++++++++++++-- modules/datablocksBidAdapter.md | 21 +++++++- .../spec/modules/datablocksBidAdapter_spec.js | 51 +++++++++++++++++- 3 files changed, 119 insertions(+), 7 deletions(-) diff --git a/modules/datablocksBidAdapter.js b/modules/datablocksBidAdapter.js index aa427c6eae1..3e9bf219c75 100644 --- a/modules/datablocksBidAdapter.js +++ b/modules/datablocksBidAdapter.js @@ -1,6 +1,6 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER, NATIVE } from '../src/mediaTypes'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; import { parse as parseUrl } from '../src/url'; const NATIVE_MAP = { 'body': 2, @@ -43,12 +43,17 @@ const NATIVE_IMAGE = [{ } }]; +const VIDEO_PARAMS = ['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']; + export const spec = { - supportedMediaTypes: [BANNER, NATIVE], + supportedMediaTypes: [BANNER, NATIVE, VIDEO], code: 'datablocks', isBidRequestValid: function(bid) { return !!(bid.params.host && bid.params.sourceId && - bid.mediaTypes && (bid.mediaTypes.banner || bid.mediaTypes.native)); + bid.mediaTypes && (bid.mediaTypes.banner || bid.mediaTypes.native || bid.mediaTypes.video)); }, buildRequests: function(validBidRequests, bidderRequest) { if (!validBidRequests.length) { return []; } @@ -142,6 +147,43 @@ export const spec = { request: JSON.stringify({native: {assets: nativeAssets}}) }; } + } else if (utils.deepAccess(bidRequest, 'mediaTypes.video')) { + let video = bidRequest.mediaTypes.video; + let sizes = video.playerSize || bidRequest.sizes || []; + if (sizes.length && Array.isArray(sizes[0])) { + imp.video = { + w: sizes[0][0], + h: sizes[0][1] + }; + } else if (sizes.length == 2 && !Array.isArray(sizes[0])) { + imp.video = { + w: sizes[0], + h: sizes[1] + }; + } else { + return; + } + + if (video.durationRangeSec) { + if (Array.isArray(video.durationRangeSec)) { + if (video.durationRangeSec.length == 1) { + imp.video.maxduration = video.durationRangeSec[0]; + } else if (video.durationRangeSec.length == 2) { + imp.video.minduration = video.durationRangeSec[0]; + imp.video.maxduration = video.durationRangeSec[1]; + } + } else { + imp.video.maxduration = video.durationRangeSec; + } + } + + if (bidRequest.params.video) { + Object.keys(bidRequest.params.video).forEach(k => { + if (VIDEO_PARAMS.indexOf(k) > -1) { + imp.video[k] = bidRequest.params.video[k]; + } + }) + } } let host = bidRequest.params.host; let sourceId = bidRequest.params.sourceId; @@ -181,7 +223,6 @@ export const spec = { } }) }); - return requests; function RtbRequest(device, site, imps) { @@ -276,6 +317,11 @@ export const spec = { } }) br.native = result; + } else if (imp.video) { + br.mediaType = VIDEO; + br.width = rtbBid.w; + br.height = rtbBid.h; + if (rtbBid.adm) { br.vastXml = rtbBid.adm; } else if (rtbBid.nurl) { br.vastUrl = rtbBid.nurl; } } return br; }); diff --git a/modules/datablocksBidAdapter.md b/modules/datablocksBidAdapter.md index 7562eee5704..e30cd361974 100644 --- a/modules/datablocksBidAdapter.md +++ b/modules/datablocksBidAdapter.md @@ -9,7 +9,7 @@ Maintainer: support@datablocks.net # Description Connects to Datablocks Version 5 Platform -Banner Native and +Banner Native and Video # Test Parameters @@ -47,6 +47,25 @@ Banner Native and sourceId: 12345, host: 'prebid.datablocks.net' } + }, { + code: 'video-div', + mediaTypes : { + video: { + playerSize:[500,400], + durationRangeSec:[15,30], + context: "linear" + } + }, + bids: [ + { + bidder: 'datablocks', + params: { + sourceId: 12345, + host: 'prebid.datablocks.net', + video: { + mimes:["video/flv"] + } + } } ] } diff --git a/test/spec/modules/datablocksBidAdapter_spec.js b/test/spec/modules/datablocksBidAdapter_spec.js index 07989b86535..d39116ccb71 100644 --- a/test/spec/modules/datablocksBidAdapter_spec.js +++ b/test/spec/modules/datablocksBidAdapter_spec.js @@ -84,12 +84,35 @@ let nativeBid = { transactionId: '0a4e9788-4def-4b94-bc25-564d7cac99f6' } +let videoBid = { + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '160c78a4-f808-410f-b682-d8728f3a79e1', + bidId: '332045ee374b99', + bidder: 'datablocks', + bidderRequestId: '15d9012765e36d', + mediaTypes: { + video: { + context: 'instream', + playerSize: [501, 400], + durationRangeSec: [15, 60] + } + }, + params: { + sourceId: 7560, + host: 'v5demo.datablocks.net', + video: { + minduration: 14 + } + }, + transactionId: '0a4e9788-4def-4b94-bc25-564d7cac99f7' +} + const bidderRequest = { auctionId: '8bfef1be-d3ac-4d18-8859-754c7b4cf017', auctionStart: Date.now(), biddeCode: 'datablocks', bidderRequestId: '10c47a5fc3c41', - bids: [bid, bid2, nativeBid], + bids: [bid, bid2, nativeBid, videoBid], refererInfo: { numIframes: 0, reachedTop: true, @@ -140,6 +163,18 @@ let resObject = { crid: '177432', cat: [], api: [] + }, { + id: '1090738575', + impid: '15d9012765e36f', + price: 25.000000, + cid: '12345', + adid: '12345', + crid: '123456', + nurl: 'http://click.v5demo.datablocks.net/m//?fcid=435235435432', + cat: [], + api: [], + w: 500, + h: 400 }] }], cur: 'USD', @@ -175,6 +210,11 @@ let bidRequest = { native: {request: '{"native":{"assets":[{"id":"1","required":true,"title":{"len":140}},{"id":"2","required":true,"data":{"type":2}},{"id":"3","img":{"w":728,"h":90,"type":3}}]}}'}, secure: false, tagid: '/19968336/header-bid-tag-0' + }, { + id: '15d9012765e36f', + video: {w: 500, h: 400, minduration: 15, maxduration: 60}, + secure: false, + tagid: '/19968336/header-bid-tag-0' }], site: { domain: '', @@ -198,7 +238,7 @@ describe('DatablocksAdapter', function() { }); describe('buildRequests', function() { - let requests = spec.buildRequests([bid, bid2, nativeBid], bidderRequest); + let requests = spec.buildRequests([bid, bid2, nativeBid, videoBid], bidderRequest); it('Creates an array of request objects', function() { expect(requests).to.be.an('array').that.is.not.empty; }); @@ -232,6 +272,9 @@ describe('DatablocksAdapter', function() { expect(imp.native.request).to.be.a('string'); let native = JSON.parse(imp.native.request); expect(native).to.be.a('object'); + } else if (imp.video) { + expect(imp).to.have.all.keys('video', 'id', 'secure', 'tagid'); + expect(imp.video).to.have.all.keys('w', 'h', 'minduration', 'maxduration') } else { expect(true).to.equal(false); } @@ -276,6 +319,10 @@ describe('DatablocksAdapter', function() { expect(dataItem.native.title).to.be.a('string'); expect(dataItem.native.body).to.be.a('string'); expect(dataItem.native.clickUrl).to.be.a('string'); + } else if (dataItem.mediaType == 'video') { + expect(dataItem.vastUrl).to.be.a('string'); + expect(dataItem.width).to.be.a('number'); + expect(dataItem.height).to.be.a('number'); } } it('Returns an empty array if invalid response is passed', function() { From 2ab711bf0f59286c771a604cffe5d09f2e22e9be Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 24 Sep 2019 22:35:35 +0530 Subject: [PATCH 1521/1594] update adUnit, bidRequest and bidResponse object (#4180) * update adUnit, bidRequest and bidResponse object * add test for mediaTypes object --- test/fixtures/fixtures.js | 391 +++++---------------- test/spec/unit/core/adapterManager_spec.js | 8 +- 2 files changed, 88 insertions(+), 311 deletions(-) diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index 2637bb30de6..2a0a7638fc4 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -53,11 +53,14 @@ export function getBidRequests() { 90 ] ], + 'mediaTypes': { + 'banner': { + 'sizes': [[728, 90], [970, 90]] + } + }, 'bidId': '392b5a6b05d648', 'bidderRequestId': '2946b569352ef2', 'auctionId': '1863e370099523', - 'startTime': 1462918897462, - 'status': 1, 'transactionId': 'fsafsa' }, { @@ -76,11 +79,14 @@ export function getBidRequests() { 600 ] ], + 'mediaTypes': { + 'banner': { + 'sizes': [[728, 90], [970, 90]] + } + }, 'bidId': '4dccdc37746135', 'bidderRequestId': '2946b569352ef2', 'auctionId': '1863e370099523', - 'startTime': 1462918897463, - 'status': 1, 'transactionId': 'fsafsa' } ], @@ -108,6 +114,11 @@ export function getBidRequests() { 600 ] ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '6d11aa2d5b3659', 'bidderRequestId': '5e1525bae3eb11', 'auctionId': '1863e370099523', @@ -157,6 +168,11 @@ export function getBidRequests() { 600 ] ], + 'mediaType': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '96aff279720d39', 'bidderRequestId': '8778750ee15a77', 'auctionId': '1863e370099523', @@ -186,10 +202,14 @@ export function getBidRequests() { 600 ] ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '1144e2f0de84363', 'bidderRequestId': '107f5e6e98dcf09', 'auctionId': '1863e370099523', - 'startTime': 1462918897477, 'transactionId': 'fsafsa' } ], @@ -216,10 +236,14 @@ export function getBidRequests() { 600 ] ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '135e89c039705da', 'bidderRequestId': '12eeded736650b4', 'auctionId': '1863e370099523', - 'status': 1, 'transactionId': 'fsafsa' } ], @@ -246,11 +270,14 @@ export function getBidRequests() { 600 ] ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '17dd1d869bed44e', 'bidderRequestId': '167c4d79b615948', 'auctionId': '1863e370099523', - 'startTime': 1462918897480, - 'status': 1, 'transactionId': 'fsafsa' } ], @@ -277,11 +304,14 @@ export function getBidRequests() { 600 ] ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '192c8c1df0f5d1d', 'bidderRequestId': '18bed198c172a69', 'auctionId': '1863e370099523', - 'startTime': 1462918897481, - 'status': 1, 'transactionId': 'fsafsa' } ], @@ -308,6 +338,11 @@ export function getBidRequests() { 600 ] ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '21ae8131ec04f6e', 'bidderRequestId': '20d0d30333715a7', 'auctionId': '1863e370099523', @@ -323,6 +358,7 @@ export function getBidResponses() { return [ { 'bidderCode': 'triplelift', + 'mediaType': 'banner', 'width': 0, 'height': 0, 'statusMessage': 'Bid available', @@ -354,6 +390,7 @@ export function getBidResponses() { }, { 'bidderCode': 'appnexus', + 'mediaType': 'banner', 'width': 300, 'height': 250, 'statusMessage': 'Bid available', @@ -387,6 +424,7 @@ export function getBidResponses() { }, { 'bidderCode': 'appnexus', + 'mediaType': 'banner', 'width': 728, 'height': 90, 'statusMessage': 'Bid available', @@ -420,6 +458,7 @@ export function getBidResponses() { }, { 'bidderCode': 'pagescience', + 'mediaType': 'banner', 'width': 300, 'height': 250, 'statusMessage': 'Bid available', @@ -452,6 +491,7 @@ export function getBidResponses() { }, { 'bidderCode': 'brightcom', + 'mediaType': 'banner', 'width': 300, 'height': 250, 'statusMessage': 'Bid available', @@ -483,6 +523,7 @@ export function getBidResponses() { }, { 'bidderCode': 'brealtime', + 'mediaType': 'banner', 'width': 300, 'height': 250, 'statusMessage': 'Bid available', @@ -515,6 +556,7 @@ export function getBidResponses() { }, { 'bidderCode': 'pubmatic', + 'mediaType': 'banner', 'width': '300', 'height': '250', 'statusMessage': 'Bid available', @@ -548,6 +590,7 @@ export function getBidResponses() { }, { 'bidderCode': 'rubicon', + 'mediaType': 'banner', 'width': 300, 'height': 600, 'statusMessage': 'Bid available', @@ -616,138 +659,54 @@ export function getAdUnits() { return [ { 'code': '/19968336/header-bid-tag1', - 'sizes': [ - [ - 728, - 90 - ], - [ - 970, - 90 - ] - ], + 'mediaTypes': { + 'banner': { + 'sizes': [[728, 90], [970, 90]] + }, + }, 'bids': [ { 'bidder': 'adequant', 'params': { 'publisher_id': '1234567', 'bidfloor': 0.01 - }, - 'adUnitCode': '/19968336/header-bid-tag1', - 'sizes': [ - [ - 728, - 90 - ], - [ - 970, - 90 - ] - ], - 'bidId': '3692954f816efc', - 'bidderRequestId': '2b1a75d5e826c4', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'appnexus', 'params': { 'placementId': '543221', 'test': 'me' - }, - 'adUnitCode': '/19968336/header-bid-tag1', - 'sizes': [ - [ - 728, - 90 - ], - [ - 970, - 90 - ] - ], - 'bidId': '68136e1c47023d', - 'bidderRequestId': '55e24a66bed717', - 'auctionId': '1ff753bd4ae5cb', - 'startTime': 1463510220995, - 'status': 1 + } } ] }, { 'code': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bids': [ { 'bidder': 'appnexus', 'params': { 'placementId': '5324321' - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '7e5d6af25ed188', - 'bidderRequestId': '55e24a66bed717', - 'auctionId': '1ff753bd4ae5cb', - 'startTime': 1463510220996 + } }, { 'bidder': 'adequant', 'params': { 'publisher_id': '12353433', 'bidfloor': 0.01 - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '4448d80ac1374e', - 'bidderRequestId': '2b1a75d5e826c4', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'triplelift', 'params': { 'inventoryCode': 'inv_code_here' - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '9514d586c52abf', - 'bidderRequestId': '8c4f03b838d7ee', - 'auctionId': '1ff753bd4ae5cb', - 'startTime': 1463510220997 + } }, { 'bidder': 'springserve', @@ -755,21 +714,7 @@ export function getAdUnits() { 'impId': 1234, 'supplyPartnerId': 1, 'test': true - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '113079fed03f58c', - 'bidderRequestId': '1048e0df882e965', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'rubicon', @@ -795,105 +740,33 @@ export function getAdUnits() { 15, 10 ] - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '13c2c2a79d155ea', - 'bidderRequestId': '129e383ac549e5d', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'openx', 'params': { 'jstag_url': 'http://servedbyopenx.com/w/1.0/jstag?nc=account_key', 'unit': 2345677 - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '154f9cbf82df565', - 'bidderRequestId': '1448569c2453b84', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'pubmatic', 'params': { 'publisherId': 1234567, 'adSlot': '1234567@300x250' - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '17f8c3a8fb13308', - 'bidderRequestId': '16095445eeb05e4', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'pagescience', 'params': { 'placementId': '1234567' - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '2074d5757675542', - 'bidderRequestId': '19883380ef5453a', - 'auctionId': '1ff753bd4ae5cb', - 'startTime': 1463510221014 + } }, { 'bidder': 'brealtime', 'params': { 'placementId': '1234567' - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '222b6ad5a9b835d', - 'bidderRequestId': '2163409fdf6f333', - 'auctionId': '1ff753bd4ae5cb', - 'startTime': 1463510221015 + } }, { 'bidder': 'indexExchange', @@ -901,21 +774,7 @@ export function getAdUnits() { 'id': '1', 'siteID': 123456, 'timeout': 10000 - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '2499961ab3f937a', - 'bidderRequestId': '23b57a2de4ae50b', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'adform', @@ -923,82 +782,26 @@ export function getAdUnits() { 'adxDomain': 'adx.adform.net', 'mid': 123456, 'test': 1 - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '26605265bf5e9c5', - 'bidderRequestId': '25a0902299c17d3', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'amazon', 'params': { 'aId': 3080 - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '2935d8f6764fe45', - 'bidderRequestId': '28afa21ca9246c1', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'aol', 'params': { 'network': '112345.45', 'placement': 12345 - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '31d1489681dc539', - 'bidderRequestId': '30bf32da9080fdd', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'sovrn', 'params': { 'tagid': '123556' - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '33c1a8028d91563', - 'bidderRequestId': '324bcb47cfcf034', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'pulsepoint', @@ -1006,41 +809,13 @@ export function getAdUnits() { 'cf': '300X250', 'cp': 1233456, 'ct': 12357 - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '379219f0506a26f', - 'bidderRequestId': '360ec66bbb0719c', - 'auctionId': '1ff753bd4ae5cb' + } }, { 'bidder': 'brightcom', 'params': { 'tagId': 75423 - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'sizes': [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - 'bidId': '395cfcf496e7d6d', - 'bidderRequestId': '38a776c7f001ea', - 'auctionId': '1ff753bd4ae5cb' + } } ] } @@ -1055,6 +830,7 @@ export function getBidResponsesFromAPI() { 'bidderCode': 'brightcom', 'width': 300, 'height': 250, + 'mediaType': 'banner', 'statusMessage': 'Bid available', 'adId': '26e0795ab963896', 'cpm': 0.17, @@ -1086,6 +862,7 @@ export function getBidResponsesFromAPI() { 'bidderCode': 'brealtime', 'width': 300, 'height': 250, + 'mediaType': 'banner', 'statusMessage': 'Bid available', 'adId': '275bd666f5a5a5d', 'creative_id': 29681110, @@ -1118,6 +895,7 @@ export function getBidResponsesFromAPI() { 'bidderCode': 'pubmatic', 'width': '300', 'height': '250', + 'mediaType': 'banner', 'statusMessage': 'Bid available', 'adId': '28f4039c636b6a7', 'adSlot': '39620189@300x250', @@ -1151,6 +929,7 @@ export function getBidResponsesFromAPI() { 'bidderCode': 'rubicon', 'width': 300, 'height': 600, + 'mediaType': 'banner', 'statusMessage': 'Bid available', 'adId': '29019e2ab586a5a', 'cpm': 2.74, diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 8eb1e21b229..1933e4a736d 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -927,12 +927,12 @@ describe('adapterManager tests', function () { expect(bidRequests.length).to.equal(2); let rubiconBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'rubicon'); expect(rubiconBidRequests.bids.length).to.equal(1); - expect(rubiconBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === rubiconBidRequests.bids[0].adUnitCode).sizes); + expect(rubiconBidRequests.bids[0].mediaTypes).to.deep.equal(find(adUnits, adUnit => adUnit.code === rubiconBidRequests.bids[0].adUnitCode).mediaTypes); let appnexusBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'appnexus'); expect(appnexusBidRequests.bids.length).to.equal(2); - expect(appnexusBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[0].adUnitCode).sizes); - expect(appnexusBidRequests.bids[1].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).sizes); + expect(appnexusBidRequests.bids[0].mediaTypes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[0].adUnitCode).mediaTypes); + expect(appnexusBidRequests.bids[1].mediaTypes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).mediaTypes); }); it('should not filter video bids', function () { @@ -1109,8 +1109,6 @@ describe('adapterManager tests', function () { expect(bidRequests[0].adUnitsS2SCopy.length).to.equal(1); expect(bidRequests[0].adUnitsS2SCopy[0].bids.length).to.equal(1); expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].bidder).to.equal('rubicon'); - expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].adUnitCode).to.equal(adUnits[1].code); - expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].bid_id).to.equal(bidRequests[0].bids[0].bid_id); expect(bidRequests[0].adUnitsS2SCopy[0].labelAny).to.deep.equal(['visitor-uk', 'desktop']); }); }); From 0ad0bd3f58500cf5485baa26fcbbe8caf7b77c42 Mon Sep 17 00:00:00 2001 From: onlsol <48312668+onlsol@users.noreply.github.com> Date: Wed, 25 Sep 2019 00:43:53 +0400 Subject: [PATCH 1522/1594] 3 display banner and video vast support for rads (#4209) * add stv adapter * remove comments from adapter file * start rads adapter * fix adapter and tests * fixes * fix adapter and doc * fix adapter * fix tests * little fix * add ip param * fix dev url * #3 radsBidAdapter.md * #3 radsBidAdapter.md: cleanup * fix code and doc --- modules/radsBidAdapter.js | 151 +++++++++++++++++ modules/radsBidAdapter.md | 37 ++++ test/spec/modules/radsBidAdapter_spec.js | 206 +++++++++++++++++++++++ 3 files changed, 394 insertions(+) create mode 100644 modules/radsBidAdapter.js create mode 100644 modules/radsBidAdapter.md create mode 100644 test/spec/modules/radsBidAdapter_spec.js diff --git a/modules/radsBidAdapter.js b/modules/radsBidAdapter.js new file mode 100644 index 00000000000..026dc3c4af6 --- /dev/null +++ b/modules/radsBidAdapter.js @@ -0,0 +1,151 @@ +import * as utils from '../src/utils'; +import {config} from '../src/config'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; + +const BIDDER_CODE = 'rads'; +const ENDPOINT_URL = 'https://rads.recognified.net/md.request.php'; +const ENDPOINT_URL_DEV = 'https://dcradn1.online-solution.biz/md.request.php'; +const DEFAULT_VAST_FORMAT = 'vast2'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['rads'], + supportedMediaTypes: [BANNER, VIDEO], + isBidRequestValid: function(bid) { + return !!(bid.params.placement); + }, + buildRequests: function(validBidRequests, bidderRequest) { + return validBidRequests.map(bidRequest => { + const params = bidRequest.params; + const videoData = utils.deepAccess(bidRequest, 'mediaTypes.video') || {}; + const sizes = utils.parseSizesInput(videoData.playerSize || bidRequest.sizes)[0]; + const [width, height] = sizes.split('x'); + const placementId = params.placement; + + const rnd = Math.floor(Math.random() * 99999999999); + const referrer = encodeURIComponent(bidderRequest.refererInfo.referer); + const bidId = bidRequest.bidId; + const isDev = params.devMode || false; + + let endpoint = isDev ? ENDPOINT_URL_DEV : ENDPOINT_URL; + + let payload = {}; + if (isVideoRequest(bidRequest)) { + let vastFormat = params.vastFormat || DEFAULT_VAST_FORMAT; + payload = { + rt: vastFormat, + _f: 'prebid_js', + _ps: placementId, + srw: width, + srh: height, + idt: 100, + rnd: rnd, + p: referrer, + bid_id: bidId, + }; + } else { + payload = { + rt: 'bid-response', + _f: 'prebid_js', + _ps: placementId, + srw: width, + srh: height, + idt: 100, + rnd: rnd, + p: referrer, + bid_id: bidId, + }; + } + prepareExtraParams(params, payload); + + return { + method: 'GET', + url: endpoint, + data: objectToQueryString(payload), + } + }); + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + const response = serverResponse.body; + const crid = response.crid || 0; + const cpm = response.cpm / 1000000 || 0; + if (cpm !== 0 && crid !== 0) { + const dealId = response.dealid || ''; + const currency = response.currency || 'EUR'; + const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; + const bidResponse = { + requestId: response.bid_id, + cpm: cpm, + width: response.width, + height: response.height, + creativeId: crid, + dealId: dealId, + currency: currency, + netRevenue: netRevenue, + ttl: config.getConfig('_bidderTimeout') + }; + + if (response.vastXml) { + bidResponse.vastXml = response.vastXml; + bidResponse.mediaType = 'video'; + } else { + bidResponse.ad = response.adTag; + } + + bidResponses.push(bidResponse); + } + return bidResponses; + } +} + +function objectToQueryString(obj, prefix) { + let str = []; + let p; + for (p in obj) { + if (obj.hasOwnProperty(p)) { + let k = prefix ? prefix + '[' + p + ']' : p; + let v = obj[p]; + str.push((v !== null && typeof v === 'object') + ? objectToQueryString(v, k) + : encodeURIComponent(k) + '=' + encodeURIComponent(v)); + } + } + return str.join('&'); +} + +/** + * Check if it's a video bid request + * + * @param {BidRequest} bid - Bid request generated from ad slots + * @returns {boolean} True if it's a video bid + */ +function isVideoRequest(bid) { + return bid.mediaType === 'video' || !!utils.deepAccess(bid, 'mediaTypes.video'); +} + +function prepareExtraParams(params, payload) { + if (params.pfilter !== undefined) { + payload.pfilter = params.pfilter; + } + if (params.bcat !== undefined) { + payload.bcat = params.bcat; + } + if (params.dvt !== undefined) { + payload.dvt = params.dvt; + } + + if (params.latitude !== undefined) { + payload.latitude = params.latitude; + } + + if (params.longitude !== undefined) { + payload.longitude = params.longitude; + } + if (params.ip !== undefined) { + payload.i = params.ip; + } +} + +registerBidder(spec); diff --git a/modules/radsBidAdapter.md b/modules/radsBidAdapter.md new file mode 100644 index 00000000000..6e970093154 --- /dev/null +++ b/modules/radsBidAdapter.md @@ -0,0 +1,37 @@ +# Overview + +``` +Module Name: RADS Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@recognified.net +``` + +# Description + +RADS Bidder Adapter for Prebid.js 1.x + +# Test Parameters +``` + var adUnits = [ + { + code: "test-div", + mediaTypes: { + banner: { + sizes: [[320, 50]] + } + }, + bids: [ + { + bidder: "rads", + params: { + placement: 3, // placement ID + devMode: true // if true: library uses dev server for tests + } + } + ] + } + ]; +``` + +Required param field is only `placement`. + diff --git a/test/spec/modules/radsBidAdapter_spec.js b/test/spec/modules/radsBidAdapter_spec.js new file mode 100644 index 00000000000..6981955f261 --- /dev/null +++ b/test/spec/modules/radsBidAdapter_spec.js @@ -0,0 +1,206 @@ +import { expect } from 'chai'; +import { spec } from 'modules/radsBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const RADS_ENDPOINT_URL = 'https://rads.recognified.net/md.request.php'; + +describe('radsAdapter', function () { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'rads', + 'params': { + 'placement': '6682', + 'pfilter': { + 'floorprice': 1000000 + }, + 'bcat': 'IAB2,IAB4', + 'dvt': 'desktop', + 'ip': '1.1.1.1' + }, + 'sizes': [ + [300, 250] + ], + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'someIncorrectParam': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [{ + 'bidder': 'rads', + 'params': { + 'placement': '6682', + 'pfilter': { + 'floorprice': 1000000, + 'geo': { + 'country': 'DE' + } + }, + 'bcat': 'IAB2,IAB4', + 'dvt': 'desktop', + 'ip': '1.1.1.1' + }, + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }, { + 'bidder': 'rads', + 'params': { + 'placement': '6682', + 'pfilter': { + 'floorprice': 1000000, + 'geo': { + 'country': 'DE', + 'region': 'DE-BE' + }, + }, + 'bcat': 'IAB2,IAB4', + 'dvt': 'desktop' + }, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'context': 'instream' + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + let bidderRequest = { + refererInfo: { + referer: 'some_referrer.net' + } + } + + const request = spec.buildRequests(bidRequests, bidderRequest); + it('sends bid request to our endpoint via GET', function () { + expect(request[0].method).to.equal('GET'); + let data = request[0].data.replace(/rnd=\d+\&/g, '').replace(/ref=.*\&bid/g, 'bid'); + expect(data).to.equal('rt=bid-response&_f=prebid_js&_ps=6682&srw=300&srh=250&idt=100&p=some_referrer.net&bid_id=30b31c1838de1e&pfilter%5Bfloorprice%5D=1000000&pfilter%5Bgeo%5D%5Bcountry%5D=DE&bcat=IAB2%2CIAB4&dvt=desktop&i=1.1.1.1'); + }); + + it('sends bid video request to our rads endpoint via GET', function () { + expect(request[1].method).to.equal('GET'); + let data = request[1].data.replace(/rnd=\d+\&/g, '').replace(/ref=.*\&bid/g, 'bid'); + expect(data).to.equal('rt=vast2&_f=prebid_js&_ps=6682&srw=640&srh=480&idt=100&p=some_referrer.net&bid_id=30b31c1838de1e&pfilter%5Bfloorprice%5D=1000000&pfilter%5Bgeo%5D%5Bcountry%5D=DE&pfilter%5Bgeo%5D%5Bregion%5D=DE-BE&bcat=IAB2%2CIAB4&dvt=desktop'); + }); + }); + + describe('interpretResponse', function () { + let serverBannerResponse = { + 'body': { + 'cpm': 5000000, + 'crid': 100500, + 'width': '300', + 'height': '250', + 'adTag': '', + 'requestId': '220ed41385952a', + 'currency': 'EUR', + 'ttl': 60, + 'netRevenue': true, + 'zone': '6682' + } + }; + let serverVideoResponse = { + 'body': { + 'cpm': 5000000, + 'crid': 100500, + 'width': '300', + 'height': '250', + 'vastXml': '{"reason":7001,"status":"accepted"}', + 'requestId': '220ed41385952a', + 'currency': 'EUR', + 'ttl': 60, + 'netRevenue': true, + 'zone': '6682' + } + }; + + let expectedResponse = [{ + requestId: '23beaa6af6cdde', + cpm: 0.5, + width: 0, + height: 0, + creativeId: 100500, + dealId: '', + currency: 'EUR', + netRevenue: true, + ttl: 300, + ad: '' + }, { + requestId: '23beaa6af6cdde', + cpm: 0.5, + width: 0, + height: 0, + creativeId: 100500, + dealId: '', + currency: 'EUR', + netRevenue: true, + ttl: 300, + vastXml: '{"reason":7001,"status":"accepted"}', + mediaType: 'video' + }]; + + it('should get the correct bid response by display ad', function () { + let bidRequest = [{ + 'method': 'GET', + 'url': RADS_ENDPOINT_URL, + 'refererInfo': { + 'referer': '' + }, + 'data': { + 'bid_id': '30b31c1838de1e' + } + }]; + let result = spec.interpretResponse(serverBannerResponse, bidRequest[0]); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('should get the correct rads video bid response by display ad', function () { + let bidRequest = [{ + 'method': 'GET', + 'url': RADS_ENDPOINT_URL, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'context': 'instream' + } + }, + 'data': { + 'bid_id': '30b31c1838de1e' + } + }]; + let result = spec.interpretResponse(serverVideoResponse, bidRequest[0]); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[1])); + }); + + it('handles empty bid response', function () { + let response = { + body: {} + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From 925f1b1f1b67e5647bd109f31276374ff9d657bf Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Wed, 25 Sep 2019 10:32:16 -0700 Subject: [PATCH 1523/1594] UserId - Add SameSite and server-side pubcid support (#3869) * Add SameSite and server-side pubcid support * Fix emoteevBidAdapter unit test --- modules/conversantBidAdapter.js | 5 +- modules/criteortusIdSystem.js | 9 +- modules/digiTrustIdSystem.js | 4 +- modules/id5IdSystem.js | 7 +- modules/identityLinkIdSystem.js | 8 +- modules/pubCommonId.js | 91 +++++++++--- modules/userId/index.js | 90 ++++++++---- modules/userId/pubCommonIdSystem.js | 68 +++++++-- modules/userId/unifiedIdSystem.js | 9 +- src/utils.js | 4 +- .../spec/modules/conversantBidAdapter_spec.js | 13 +- test/spec/modules/criteortusIdSystem_spec.js | 6 +- test/spec/modules/emoteevBidAdapter_spec.js | 4 +- test/spec/modules/pubCommonId_spec.js | 38 ++++- test/spec/modules/userId_spec.js | 134 +++++++++++++++++- 15 files changed, 396 insertions(+), 94 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index 90865493d8d..00ca6a7bbd6 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -4,7 +4,6 @@ import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'conversant'; const URL = '//web.hb.ad.cpe.dotomi.com/s2s/header/24'; -const VERSION = '2.2.4'; export const spec = { code: BIDDER_CODE, @@ -24,7 +23,7 @@ export const spec = { } if (!utils.isStr(bid.params.site_id)) { - utils.logWarn(BIDDER_CODE + ': site_id must be specified as a string') + utils.logWarn(BIDDER_CODE + ': site_id must be specified as a string'); return false; } @@ -67,7 +66,7 @@ export const spec = { secure: secure, bidfloor: bidfloor || 0, displaymanager: 'Prebid.js', - displaymanagerver: VERSION + displaymanagerver: '$prebid.version$' }; copyOptProperty(bid.params.tag_id, imp, 'tagid'); diff --git a/modules/criteortusIdSystem.js b/modules/criteortusIdSystem.js index 02edf0ef06e..8486bfae9f3 100644 --- a/modules/criteortusIdSystem.js +++ b/modules/criteortusIdSystem.js @@ -36,7 +36,7 @@ export const criteortusIdSubmodule = { * performs action to obtain id and return a value in the callback's response argument * @function * @param {SubmoduleParams} [configParams] - * @returns {function(callback:function)} + * @returns {IdResponse|undefined} */ getId(configParams) { if (!configParams || !utils.isPlainObject(configParams.clientIdentifier)) { @@ -46,10 +46,10 @@ export const criteortusIdSubmodule = { let uid = utils.getCookie(key); if (uid) { - return uid; + return {id: uid}; } else { let userIds = {}; - return function(callback) { + const resp = function(callback) { let bidders = Object.keys(configParams.clientIdentifier); function afterAllResponses() { @@ -97,7 +97,8 @@ export const criteortusIdSubmodule = { }) ); }) - } + }; + return {callback: resp}; } } }; diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index 17f6fd9f737..89557e0917e 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -342,7 +342,9 @@ export const digiTrustIdSubmodule = { utils.logError('DigiTrust ID submodule decode error'); } }, - getId: getDigiTrustId, + getId: function (configParams) { + return {callback: getDigiTrustId(configParams)}; + }, _testInit: surfaceTestHook }; diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js index 6fb5014c962..6ed56b89d6d 100644 --- a/modules/id5IdSystem.js +++ b/modules/id5IdSystem.js @@ -31,7 +31,7 @@ export const id5IdSubmodule = { * @param {SubmoduleParams} [configParams] * @param {ConsentData} [consentData] * @param {(Object|undefined)} cacheIdObj - * @returns {(Object|function(callback:function))} + * @returns {IdResponse|undefined} */ getId(configParams, consentData, cacheIdObj) { if (!configParams || typeof configParams.partner !== 'number') { @@ -43,7 +43,7 @@ export const id5IdSubmodule = { const storedUserId = this.decode(cacheIdObj); const url = `https://id5-sync.com/g/v1/${configParams.partner}.json?1puid=${storedUserId ? storedUserId.id5id : ''}&gdpr=${hasGdpr}&gdpr_consent=${gdprConsentString}`; - return function (callback) { + const resp = function (callback) { ajax(url, response => { let responseObj; if (response) { @@ -55,7 +55,8 @@ export const id5IdSubmodule = { } callback(responseObj); }, undefined, { method: 'GET', withCredentials: true }); - } + }; + return {callback: resp}; } }; diff --git a/modules/identityLinkIdSystem.js b/modules/identityLinkIdSystem.js index 9aca5f85adf..a269799e92a 100644 --- a/modules/identityLinkIdSystem.js +++ b/modules/identityLinkIdSystem.js @@ -29,7 +29,7 @@ export const identityLinkSubmodule = { * performs action to obtain id and return a value in the callback's response argument * @function * @param {SubmoduleParams} [configParams] - * @returns {function(callback:function)} + * @returns {IdResponse|undefined} */ getId(configParams) { if (!configParams || typeof configParams.pid !== 'string') { @@ -38,9 +38,10 @@ export const identityLinkSubmodule = { } // use protocol relative urls for http or https const url = `https://api.rlcdn.com/api/identity/envelope?pid=${configParams.pid}`; + let resp; // if ats library is initialised, use it to retrieve envelope. If not use standard third party endpoint if (window.ats) { - return function(callback) { + resp = function(callback) { window.ats.retrieveEnvelope(function (envelope) { if (envelope) { callback(JSON.parse(envelope).envelope); @@ -50,10 +51,11 @@ export const identityLinkSubmodule = { }); } } else { - return function (callback) { + resp = function (callback) { getEnvelope(url, callback); } } + return {callback: resp}; } } // return envelope from third party endpoint diff --git a/modules/pubCommonId.js b/modules/pubCommonId.js index 5b92592f07a..038ad3bef2f 100644 --- a/modules/pubCommonId.js +++ b/modules/pubCommonId.js @@ -5,6 +5,9 @@ */ import * as utils from '../src/utils' import { config } from '../src/config'; +import events from '../src/events'; +import * as url from '../src/url'; +import CONSTANTS from '../src/constants.json'; const ID_NAME = '_pubcid'; const OPTOUT_NAME = '_pubcid_optout'; @@ -18,7 +21,9 @@ let pubcidConfig = { enabled: true, interval: DEFAULT_EXPIRES, typeEnabled: LOCAL_STORAGE, - readOnly: false + create: true, + extend: true, + pixelUrl: '' }; /** @@ -89,17 +94,16 @@ export function removeStorageItem(key) { /** * Read a value either from cookie or local storage * @param {string} name Name of the item + * @param {string} type storage type override * @returns {string|null} a string if item exists */ -function readValue(name) { +function readValue(name, type) { let value; - if (pubcidConfig.typeEnabled === COOKIE) { + if (!type) { type = pubcidConfig.typeEnabled; } + if (type === COOKIE) { value = getCookie(name); - } else if (pubcidConfig.typeEnabled === LOCAL_STORAGE) { + } else if (type === LOCAL_STORAGE) { value = getStorageItem(name); - if (!value) { - value = getCookie(name); - } } if (value === 'undefined' || value === 'null') { return null; } @@ -116,13 +120,37 @@ function readValue(name) { function writeValue(name, value, expInterval) { if (name && value) { if (pubcidConfig.typeEnabled === COOKIE) { - setCookie(name, value, expInterval); + setCookie(name, value, expInterval, 'Lax'); } else if (pubcidConfig.typeEnabled === LOCAL_STORAGE) { setStorageItem(name, value, expInterval); } } } +/** + * Add a callback at end of auction to fetch a pixel + * @param {string} pixelUrl Pixel URL + * @param {string} id pubcid + * @returns {boolean} True if callback is queued + */ +function queuePixelCallback(pixelUrl, id) { + if (!pixelUrl) { return false; } + + id = id || ''; + + // Use pubcid as a cache buster + const urlInfo = url.parse(pixelUrl); + urlInfo.search.id = encodeURIComponent('pubcid:' + id); + const targetUrl = url.format(urlInfo); + + events.on(CONSTANTS.EVENTS.AUCTION_END, function auctionEndHandler() { + events.off(CONSTANTS.EVENTS.AUCTION_END, auctionEndHandler); + utils.triggerPixel(targetUrl); + }); + + return true; +} + export function isPubcidEnabled() { return pubcidConfig.enabled; } export function getExpInterval() { return pubcidConfig.interval; } export function getPubcidConfig() { return pubcidConfig; } @@ -152,15 +180,25 @@ export function requestBidHook(next, config) { // Otherwise get the existing cookie pubcid = readValue(ID_NAME); - if (!pubcidConfig.readOnly) { - if (!pubcid) { - pubcid = utils.generateUUID(); + if (!pubcid) { + if (pubcidConfig.create) { + // Special handling for local storage to retain previously stored id in cookies + if (pubcidConfig.typeEnabled === LOCAL_STORAGE) { + pubcid = readValue(ID_NAME, COOKIE); + } + // Generate a new id + if (!pubcid) { + pubcid = utils.generateUUID(); + } // Update the cookie/storage with the latest expiration date writeValue(ID_NAME, pubcid, pubcidConfig.interval); // Only return pubcid if it is saved successfully pubcid = readValue(ID_NAME); - } else { - // Update the cookie/storage with the latest expiration date + } + queuePixelCallback(pubcidConfig.pixelUrl, pubcid); + } else if (pubcidConfig.extend) { + // Update the cookie/storage with the latest expiration date + if (!queuePixelCallback(pubcidConfig.pixelUrl, pubcid)) { writeValue(ID_NAME, pubcid, pubcidConfig.interval); } } @@ -177,15 +215,17 @@ export function requestBidHook(next, config) { }); }); } + return next.call(this, config); } // Helper to set a cookie -export function setCookie(name, value, expires) { +export function setCookie(name, value, expires, sameSite) { let expTime = new Date(); expTime.setTime(expTime.getTime() + expires * 1000 * 60); window.document.cookie = name + '=' + encodeURIComponent(value) + ';path=/;expires=' + - expTime.toGMTString(); + expTime.toGMTString() + + (sameSite ? ';SameSite=' + sameSite : ''); } // Helper to read a cookie @@ -202,17 +242,23 @@ export function getCookie(name) { * @param {boolean} enable Enable or disable pubcid. By default the module is enabled. * @param {number} expInterval Expiration interval of the cookie in minutes. * @param {string} type Type of storage to use - * @param {boolean} readOnly Read but not update id + * @param {boolean} create Create the id if missing. Default is true. + * @param {boolean} extend Extend the stored value when id is retrieved. Default is true. + * @param {string} pixelUrl A pixel URL back to the publisher's own domain that may modify cookie attributes. */ -export function setConfig({ enable = true, expInterval = DEFAULT_EXPIRES, type = 'html5,cookie', readOnly = false } = {}) { - pubcidConfig.enabled = enable; - pubcidConfig.interval = parseInt(expInterval, 10); +export function setConfig({ enable, expInterval, type = 'html5,cookie', create, extend, pixelUrl } = {}) { + if (enable !== undefined) { pubcidConfig.enabled = enable; } + + if (expInterval !== undefined) { pubcidConfig.interval = parseInt(expInterval, 10); } + if (isNaN(pubcidConfig.interval)) { pubcidConfig.interval = DEFAULT_EXPIRES; } - pubcidConfig.readOnly = readOnly; + if (create !== undefined) { pubcidConfig.create = create; } + if (extend !== undefined) { pubcidConfig.extend = extend; } + if (pixelUrl !== undefined) { pubcidConfig.pixelUrl = pixelUrl; } // Default is to use local storage. Fall back to // cookie only if local storage is not supported. @@ -242,7 +288,10 @@ export function setConfig({ enable = true, expInterval = DEFAULT_EXPIRES, type = export function initPubcid() { config.getConfig('pubcid', config => setConfig(config.pubcid)); - if (!readValue(OPTOUT_NAME)) { + const optout = (utils.cookiesAreEnabled() && readValue(OPTOUT_NAME, COOKIE)) || + (utils.hasLocalStorage() && readValue(OPTOUT_NAME, LOCAL_STORAGE)); + + if (!optout) { $$PREBID_GLOBAL$$.requestBids.before(requestBidHook); } } diff --git a/modules/userId/index.js b/modules/userId/index.js index fb7a748b7ec..03c81d1ff89 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -9,12 +9,27 @@ /** * @function - * @summary performs action to obtain id and return a value in the callback's response argument + * @summary performs action to obtain id and return a value in the callback's response argument. + * If IdResponse#id is defined, then it will be written to the current active storage. + * If IdResponse#callback is defined, then it'll called at the end of auction. + * It's permissible to return neither, one, or both fields. * @name Submodule#getId * @param {SubmoduleParams} configParams * @param {ConsentData|undefined} consentData * @param {(Object|undefined)} cacheIdObj - * @return {(Object|function)} id data or a callback, the callback is called on the auction end event + * @return {(IdResponse|undefined)} A response object that contains id and/or callback. + */ + +/** + * @function + * @summary Similar to Submodule#getId, this optional method returns response to for id that exists already. + * If IdResponse#id is defined, then it will be written to the current active storage even if it exists already. + * If IdResponse#callback is defined, then it'll called at the end of auction. + * It's permissible to return neither, one, or both fields. + * @name Submodule#extendId + * @param {SubmoduleParams} configParams + * @param {Object} storedId - existing id, if any + * @return {(IdResponse|function(callback:function))} A response object that contains id and/or callback. */ /** @@ -52,6 +67,9 @@ * @typedef {Object} SubmoduleParams * @property {(string|undefined)} partner - partner url param value * @property {(string|undefined)} url - webservice request url used to load Id data + * @property {(string|undefined)} pixelUrl - publisher pixel to extend/modify cookies + * @property {(boolean|undefined)} create - create id if missing. default is true. + * @property {(boolean|undefined)} extend - extend expiration time on each access. default is false. * @property {(string|undefined)} pid - placement id url param value */ @@ -70,6 +88,12 @@ * @property {(boolean|undefined)} gdprApplies */ +/** + * @typedef {Object} IdResponse + * @property {(Object|undefined)} id - id data + * @property {(function|undefined)} callback - function that will return an id + */ + import find from 'core-js/library/fn/array/find'; import {config} from '../../src/config'; import events from '../../src/events'; @@ -121,7 +145,7 @@ function setStoredValue(storage, 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) { - utils.setCookie(storage.name, valueStr, expiresStr); + utils.setCookie(storage.name, valueStr, expiresStr, 'Lax'); if (typeof storage.refreshInSeconds === 'number') { utils.setCookie(`${storage.name}_last`, new Date().toUTCString(), expiresStr); } @@ -192,8 +216,6 @@ function hasGDPRConsent(consentData) { function processSubmoduleCallbacks(submodules) { submodules.forEach(function(submodule) { submodule.callback(function callbackCompleted(idObj) { - // clear callback, this prop is used to test if all submodule callbacks are complete below - submodule.callback = undefined; // if valid, id data should be saved to cookie/html storage if (idObj) { if (submodule.config.storage) { @@ -205,6 +227,9 @@ function processSubmoduleCallbacks(submodules) { utils.logError(`${MODULE_NAME}: ${submodule.submodule.name} - request id responded with an empty value`); } }); + + // clear callback, this prop is used to test if all submodule callbacks are complete below + submodule.callback = undefined; }); } @@ -301,7 +326,7 @@ function getUserIds() { // initialize submodules only when undefined initializeSubmodulesAndExecuteCallbacks(); return getCombinedSubmoduleIds(initializedSubmodules); -}; +} /** * @param {SubmoduleContainer[]} submodules @@ -319,39 +344,48 @@ function initSubmodules(submodules, consentData) { // 1. storage: retrieve user id data from cookie/html storage or with the submodule's getId method // 2. value: pass directly to bids if (submodule.config.storage) { - const storedId = getStoredValue(submodule.config.storage); - if (storedId) { - // cache decoded value (this is copied to every adUnit bid) - submodule.idObj = submodule.submodule.decode(storedId); - } + let storedId = getStoredValue(submodule.config.storage); + let response; + let refreshNeeded = false; if (typeof submodule.config.storage.refreshInSeconds === 'number') { const storedDate = new Date(getStoredValue(submodule.config.storage, 'last')); refreshNeeded = storedDate && (Date.now() - storedDate.getTime() > submodule.config.storage.refreshInSeconds * 1000); } + if (!storedId || refreshNeeded) { - // getId will return user id data or a function that will load the data - const getIdResult = submodule.submodule.getId(submodule.config.params, consentData, storedId); - - // If the getId result has a type of function, it is asynchronous and cannot be called until later - if (typeof getIdResult === 'function') { - submodule.callback = getIdResult; - } else if (getIdResult) { - // A getId result that is not a function is assumed to be valid user id data, which should be saved to users local storage or cookies - setStoredValue(submodule.config.storage, getIdResult); - // cache decoded value (this is copied to every adUnit bid) - submodule.idObj = submodule.submodule.decode(getIdResult); + // No previously saved id. Request one from submodule. + response = submodule.submodule.getId(submodule.config.params, consentData, storedId); + } else if (typeof submodule.submodule.extendId === 'function') { + // If the id exists already, give submodule a chance to decide additional actions that need to be taken + response = submodule.submodule.extendId(submodule.config.params, storedId); + } + + 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.config.storage, response.id); + storedId = response.id; + } + + if (typeof response.callback === 'function') { + // Save async callback to be invoked after auction + submodule.callback = response.callback; } } + + if (storedId) { + // cache decoded value (this is copied to every adUnit bid) + submodule.idObj = submodule.submodule.decode(storedId); + } } else if (submodule.config.value) { // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.config.value; } else { - const result = submodule.submodule.getId(submodule.config.params, consentData, undefined); - if (typeof result === 'function') { - submodule.callback = result; - } else { - submodule.idObj = submodule.submodule.decode(); + const response = submodule.submodule.getId(submodule.config.params, consentData, undefined); + if (utils.isPlainObject(response)) { + if (typeof response.callback === 'function') { submodule.callback = response.callback; } + if (response.id) { submodule.idObj = submodule.submodule.decode(response.id); } } } carry.push(submodule); @@ -452,7 +486,7 @@ export function init(config) { ].filter(i => i !== null); // exit immediately if opt out cookie or local storage keys exists. - if (validStorageTypes.indexOf(COOKIE) !== -1 && utils.getCookie('_pbjs_id_optout')) { + if (validStorageTypes.indexOf(COOKIE) !== -1 && (utils.getCookie('_pbjs_id_optout') || utils.getCookie('_pubcid_optout'))) { utils.logInfo(`${MODULE_NAME} - opt-out cookie found, exit module`); return; } diff --git a/modules/userId/pubCommonIdSystem.js b/modules/userId/pubCommonIdSystem.js index f4d6b41a127..2495f7365d5 100644 --- a/modules/userId/pubCommonIdSystem.js +++ b/modules/userId/pubCommonIdSystem.js @@ -6,6 +6,9 @@ */ import * as utils from '../../src/utils'; +import * as url from '../../src/url'; + +const PUB_COMMON_ID = 'PublisherCommonId'; /** @type {Submodule} */ export const pubCommonIdSubmodule = { @@ -14,6 +17,26 @@ export const pubCommonIdSubmodule = { * @type {string} */ name: 'pubCommonId', + /** + * Return a callback function that calls the pixelUrl with id as a query parameter + * @param pixelUrl + * @param id + * @returns {function} + */ + makeCallback: function (pixelUrl, id = '') { + if (!pixelUrl) { + return; + } + + // Use pubcid as a cache buster + const urlInfo = url.parse(pixelUrl); + urlInfo.search.id = encodeURIComponent('pubcid:' + id); + const targetUrl = url.format(urlInfo); + + return function () { + utils.triggerPixel(targetUrl); + }; + }, /** * decode the stored id value for passing to bid requests * @function @@ -26,17 +49,44 @@ export const pubCommonIdSubmodule = { /** * performs action to obtain id * @function - * @returns {string} + * @param {SubmoduleParams} [configParams] + * @returns {IdResponse} + */ + getId: function ({create = true, pixelUrl} = {}) { + try { + if (typeof window[PUB_COMMON_ID] === 'object') { + // If the page includes its own pubcid module, then save a copy of id. + return {id: window[PUB_COMMON_ID].getId()}; + } + } catch (e) { + } + + const newId = (create) ? utils.generateUUID() : undefined; + return { + id: newId, + callback: this.makeCallback(pixelUrl, newId) + } + }, + /** + * performs action to extend an id + * @function + * @param {SubmoduleParams} [configParams] + * @param {Object} storedId existing id + * @returns {IdResponse|undefined} */ - getId() { - // If the page includes its own pubcid object, then use that instead. - let pubcid; + extendId: function({extend = false, pixelUrl} = {}, storedId) { try { - if (typeof window['PublisherCommonId'] === 'object') { - pubcid = window['PublisherCommonId'].getId(); + if (typeof window[PUB_COMMON_ID] === 'object') { + // If the page includes its onw pubcid module, then there is nothing to do. + return; } - } catch (e) {} - // check pubcid and return if valid was otherwise create a new id - return (pubcid) || utils.generateUUID(); + } catch (e) { + } + + if (extend) { + // When extending, only one of response fields is needed + const callback = this.makeCallback(pixelUrl, storedId); + return callback ? {callback: callback} : {id: storedId}; + } } }; diff --git a/modules/userId/unifiedIdSystem.js b/modules/userId/unifiedIdSystem.js index 1bc369bb9fc..99f04ad8850 100644 --- a/modules/userId/unifiedIdSystem.js +++ b/modules/userId/unifiedIdSystem.js @@ -28,7 +28,7 @@ export const unifiedIdSubmodule = { * performs action to obtain id and return a value in the callback's response argument * @function * @param {SubmoduleParams} [configParams] - * @returns {function(callback:function)} + * @returns {IdResponse|undefined} */ getId(configParams) { if (!configParams || (typeof configParams.partner !== 'string' && typeof configParams.url !== 'string')) { @@ -38,7 +38,7 @@ export const unifiedIdSubmodule = { // use protocol relative urls for http or https const url = configParams.url || `//match.adsrvr.org/track/rid?ttd_pid=${configParams.partner}&fmt=json`; - return function (callback) { + const resp = function (callback) { ajax(url, response => { let responseObj; if (response) { @@ -49,7 +49,8 @@ export const unifiedIdSubmodule = { } } callback(responseObj); - }, undefined, { method: 'GET', withCredentials: true }); - } + }, undefined, {method: 'GET', withCredentials: true}); + }; + return {callback: resp}; } }; diff --git a/src/utils.js b/src/utils.js index 21a1943b1a1..2caaedc4164 100644 --- a/src/utils.js +++ b/src/utils.js @@ -918,8 +918,8 @@ export function getCookie(name) { return m ? decodeURIComponent(m[2]) : null; } -export function setCookie(key, value, expires) { - document.cookie = `${key}=${encodeURIComponent(value)}${(expires !== '') ? `; expires=${expires}` : ''}; path=/`; +export function setCookie(key, value, expires, sameSite) { + document.cookie = `${key}=${encodeURIComponent(value)}${(expires !== '') ? `; expires=${expires}` : ''}; path=/${sameSite ? `; SameSite=${sameSite}` : ''}`; } /** diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index bfe3c6e8fa1..aeadc3bf828 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -6,6 +6,7 @@ var Adapter = require('modules/conversantBidAdapter'); describe('Conversant adapter tests', function() { const siteId = '108060'; + const versionPattern = /^\d+\.\d+\.\d+(.)*$/; const bidRequests = [ // banner with single size @@ -211,7 +212,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[0]).to.have.property('secure', 0); expect(payload.imp[0]).to.have.property('bidfloor', 0.5); expect(payload.imp[0]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(versionPattern); expect(payload.imp[0]).to.have.property('tagid', 'tagid-1'); expect(payload.imp[0]).to.have.property('banner'); expect(payload.imp[0].banner).to.have.property('pos', 1); @@ -223,7 +224,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[1]).to.have.property('secure', 0); expect(payload.imp[1]).to.have.property('bidfloor', 0); expect(payload.imp[1]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[1]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[1]).to.have.property('displaymanagerver').that.matches(versionPattern); expect(payload.imp[1]).to.not.have.property('tagid'); expect(payload.imp[1]).to.have.property('banner'); expect(payload.imp[1].banner).to.not.have.property('pos'); @@ -234,7 +235,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[2]).to.have.property('secure', 0); expect(payload.imp[2]).to.have.property('bidfloor', 0); expect(payload.imp[2]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[2]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[2]).to.have.property('displaymanagerver').that.matches(versionPattern); expect(payload.imp[2]).to.have.property('banner'); expect(payload.imp[2].banner).to.have.property('pos', 2); expect(payload.imp[2].banner).to.have.property('format'); @@ -244,7 +245,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[3]).to.have.property('secure', 0); expect(payload.imp[3]).to.have.property('bidfloor', 0); expect(payload.imp[3]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[3]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[3]).to.have.property('displaymanagerver').that.matches(versionPattern); expect(payload.imp[3]).to.not.have.property('tagid'); expect(payload.imp[3]).to.have.property('video'); expect(payload.imp[3].video).to.not.have.property('pos'); @@ -263,7 +264,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[4]).to.have.property('secure', 0); expect(payload.imp[4]).to.have.property('bidfloor', 0); expect(payload.imp[4]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[4]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[4]).to.have.property('displaymanagerver').that.matches(versionPattern); expect(payload.imp[4]).to.not.have.property('tagid'); expect(payload.imp[4]).to.have.property('video'); expect(payload.imp[4].video).to.not.have.property('pos'); @@ -282,7 +283,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[5]).to.have.property('secure', 0); expect(payload.imp[5]).to.have.property('bidfloor', 0); expect(payload.imp[5]).to.have.property('displaymanager', 'Prebid.js'); - expect(payload.imp[5]).to.have.property('displaymanagerver').that.matches(/^\d+\.\d+\.\d+$/); + expect(payload.imp[5]).to.have.property('displaymanagerver').that.matches(versionPattern); expect(payload.imp[5]).to.not.have.property('tagid'); expect(payload.imp[5]).to.have.property('video'); expect(payload.imp[5].video).to.not.have.property('pos'); diff --git a/test/spec/modules/criteortusIdSystem_spec.js b/test/spec/modules/criteortusIdSystem_spec.js index 578f14d066d..217a2f86ba7 100644 --- a/test/spec/modules/criteortusIdSystem_spec.js +++ b/test/spec/modules/criteortusIdSystem_spec.js @@ -36,7 +36,8 @@ describe('Criteo RTUS', function() { let response = { 'status': 'ok', 'userid': 'sample-userid' } let callBackSpy = sinon.spy(); - let submoduleCallback = criteortusIdSubmodule.getId(configParams); + const idResp = criteortusIdSubmodule.getId(configParams); + const submoduleCallback = idResp.callback; submoduleCallback(callBackSpy); requests[0].respond( 200, @@ -70,7 +71,8 @@ describe('Criteo RTUS', function() { let response = { 'status': 'ok', 'userid': 'sample-userid' } let callBackSpy = sinon.spy(); - let submoduleCallback = criteortusIdSubmodule.getId(configParams); + const idResp = criteortusIdSubmodule.getId(configParams); + const submoduleCallback = idResp.callback; submoduleCallback(callBackSpy); requests[0].respond( 200, diff --git a/test/spec/modules/emoteevBidAdapter_spec.js b/test/spec/modules/emoteevBidAdapter_spec.js index aa97b58ec38..b6a62c16963 100644 --- a/test/spec/modules/emoteevBidAdapter_spec.js +++ b/test/spec/modules/emoteevBidAdapter_spec.js @@ -773,7 +773,9 @@ describe('emoteevBidAdapter', function () { sinon.assert.notCalled(config.getConfig); sinon.assert.notCalled(utils.getParameterByName); }); - it('has intended side-effects', function () { + }); + describe('isBidRequestValid empty request', function() { + it('has intended side-effects empty request', function () { const invalidBidRequest = {}; spec.isBidRequestValid(invalidBidRequest); sinon.assert.notCalled(utils.triggerPixel); diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js index fb4a58377c3..fd2bff5bac6 100644 --- a/test/spec/modules/pubCommonId_spec.js +++ b/test/spec/modules/pubCommonId_spec.js @@ -15,6 +15,9 @@ import * as auctionModule from 'src/auction'; import { registerBidder } from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; +let events = require('src/events'); +let constants = require('src/constants.json'); + var assert = require('chai').assert; var expect = require('chai').expect; @@ -231,13 +234,13 @@ describe('Publisher Common ID', function () { }); }); - it('read only', function() { + it('disable auto create', function() { setConfig({ - readOnly: true + create: false }); const config = getPubcidConfig(); - expect(config.readOnly).to.be.true; + expect(config.create).to.be.false; expect(config.typeEnabled).to.equal('html5'); let adUnits = getAdUnits(); @@ -335,4 +338,33 @@ describe('Publisher Common ID', function () { expect(localStorage.getItem(key)).to.be.null; }); }); + + describe('event callback', () => { + beforeEach(() => { + setConfig(); + cleanUp(); + sinon.stub(events, 'getEvents').returns([]); + sinon.stub(utils, 'triggerPixel'); + }); + afterEach(() => { + setConfig(); + cleanUp(); + events.getEvents.restore(); + utils.triggerPixel.restore(); + }); + it('auction end trigger', () => { + setConfig({ + pixelUrl: '/any/url' + }); + + let adUnits = getAdUnits(); + let innerAdUnits; + requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + expect(utils.triggerPixel.called).to.be.false; + events.emit(constants.EVENTS.AUCTION_END, {}); + expect(utils.triggerPixel.called).to.be.true; + expect(utils.triggerPixel.getCall(0).args[0]).to.include('/any/url'); + }); + }); }); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 04aaec5baa7..5bbd21a3c12 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -8,6 +8,8 @@ import {identityLinkSubmodule} from 'modules/identityLinkIdSystem'; let assert = require('chai').assert; let expect = require('chai').expect; +let events = require('src/events'); +let constants = require('src/constants.json'); const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; describe('User ID', function() { @@ -41,6 +43,16 @@ describe('User ID', function() { }; } + function addConfig(cfg, name, value) { + if (cfg && cfg.userSync && cfg.userSync.userIds) { + cfg.userSync.userIds.forEach(element => { + if (element[name] !== undefined) { element[name] = Object.assign(element[name], value); } else { element[name] = value; } + }); + } + + return cfg; + } + before(function() { utils.setCookie('_pubcid_optout', '', EXPIRED_COOKIE_DATE); localStorage.removeItem('_pbjs_id_optout'); @@ -51,11 +63,13 @@ describe('User ID', function() { beforeEach(function() { utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('pubcid_alt', 'altpubcid200000', (new Date(Date.now() + 5000).toUTCString())); + sinon.spy(utils, 'setCookie'); }); afterEach(function () { $$PREBID_GLOBAL$$.requestBids.removeAll(); config.resetConfig(); + utils.setCookie.restore(); }); after(function() { @@ -129,7 +143,7 @@ describe('User ID', function() { expect(pubcid1).to.not.equal(pubcid2); }); - it('Check new cookie', function () { + it('Use existing cookie', function () { let adUnits = [getAdUnitMock()]; let innerAdUnits; @@ -143,6 +157,46 @@ describe('User ID', function() { expect(bid.userId.pubcid).to.equal('altpubcid200000'); }); }); + // Because the cookie exists already, there should be no setCookie call by default + expect(utils.setCookie.callCount).to.equal(0); + }); + + it('Extend cookie', function () { + let adUnits = [getAdUnitMock()]; + let innerAdUnits; + let customConfig = getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie']); + customConfig = addConfig(customConfig, 'params', {extend: true}); + + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(customConfig); + requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal('altpubcid200000'); + }); + }); + // Because extend is true, the cookie will be updated even if it exists already + expect(utils.setCookie.callCount).to.equal(1); + }); + + it('Disable auto create', function () { + let adUnits = [getAdUnitMock()]; + let innerAdUnits; + let customConfig = getConfigMock(['pubCommonId', 'pubcid', 'cookie']); + customConfig = addConfig(customConfig, 'params', {create: false}); + + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(customConfig); + requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + innerAdUnits.forEach((unit) => { + unit.bids.forEach((bid) => { + expect(bid).to.not.have.deep.nested.property('userId.pubcid'); + }); + }); + expect(utils.setCookie.callCount).to.equal(0); }); }); @@ -549,8 +603,9 @@ describe('User ID', function() { 'mid': value['MOCKID'] }; }, - getId: function() { - return {'MOCKID': '1234'} + getId: function(params, storedId) { + if (storedId) return {}; + return {id: {'MOCKID': '1234'}}; } }); @@ -582,5 +637,76 @@ describe('User ID', function() { done(); }, {adUnits}); }); - }) + }); + + describe('callbacks at the end of auction', function() { + let xhr; + let requests; + + beforeEach(function() { + requests = []; + xhr = sinon.useFakeXMLHttpRequest(); + xhr.onCreate = request => requests.push(request); + sinon.stub(events, 'getEvents').returns([]); + sinon.stub(utils, 'triggerPixel'); + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + }); + + afterEach(function() { + xhr.restore(); + events.getEvents.restore(); + utils.triggerPixel.restore(); + utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + }); + + it('pubcid callback with url', function () { + let adUnits = [getAdUnitMock()]; + let innerAdUnits; + let customCfg = getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie']); + customCfg = addConfig(customCfg, 'params', {pixelUrl: '/any/pubcid/url'}); + + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(customCfg); + requestBidsHook((config) => { innerAdUnits = config.adUnits }, {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 () { + let adUnits = [getAdUnitMock()]; + let innerAdUnits; + let customCfg = getConfigMock(['unifiedId', 'unifiedid', 'cookie']); + addConfig(customCfg, 'params', {url: '/any/unifiedid/url'}); + + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(customCfg); + requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + expect(requests).to.be.empty; + events.emit(constants.EVENTS.AUCTION_END, {}); + expect(requests[0].url).to.equal('/any/unifiedid/url'); + }); + + it('unifiedid callback with partner', function () { + let adUnits = [getAdUnitMock()]; + let innerAdUnits; + let customCfg = getConfigMock(['unifiedId', 'unifiedid', 'cookie']); + addConfig(customCfg, 'params', {partner: 'rubicon'}); + + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + init(config); + config.setConfig(customCfg); + requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + + expect(requests).to.be.empty; + events.emit(constants.EVENTS.AUCTION_END, {}); + expect(requests[0].url).to.equal('//match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json'); + }); + }); }); From 112c953bda3c2b3367652d8298d52e34a9638735 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Wed, 25 Sep 2019 14:30:59 -0400 Subject: [PATCH 1524/1594] added schain to appnexus bid adapter (#4229) * added schain to appnexus bid adapter * semicolon --- modules/appnexusBidAdapter.js | 4 ++- test/spec/modules/appnexusBidAdapter_spec.js | 30 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 5b682f747e2..5fe2add5ba8 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -116,6 +116,7 @@ export const spec = { const memberIdBid = find(bidRequests, hasMemberId); const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; + const schain = bidRequests[0].schain; const payload = { tags: [...tags], @@ -123,7 +124,8 @@ export const spec = { sdk: { source: SOURCE, version: '$prebid.version$' - } + }, + schain: schain }; if (member > 0) { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index ef3f3eef6b3..e35560ac1d0 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -675,6 +675,36 @@ describe('AppNexusAdapter', function () { const payload = JSON.parse(request.data); expect(payload.tpuids).to.deep.equal([{provider: 'criteo', user_id: 'sample-userid'}]); }); + + 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 + } + ] + }); + }); }) describe('interpretResponse', function () { From 74ff666b2b2c743f1a8193b608fa1899017d0d56 Mon Sep 17 00:00:00 2001 From: Mike Sperone Date: Wed, 25 Sep 2019 13:34:36 -0500 Subject: [PATCH 1525/1594] update doubleclick url (#4179) --- modules/dfpAdServerVideo.js | 4 ++-- test/spec/modules/dfpAdServerVideo_spec.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 6f3c23f1f3d..c3f867308d1 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -101,7 +101,7 @@ export function buildDfpVideoUrl(options) { return buildUrl({ protocol: 'https', - host: 'pubads.g.doubleclick.net', + host: 'securepubads.g.doubleclick.net', pathname: '/gampad/ads', search: queryParams }); @@ -184,7 +184,7 @@ export function buildAdpodVideoUrl({code, params, callback} = {}) { const masterTag = buildUrl({ protocol: 'https', - host: 'pubads.g.doubleclick.net', + host: 'securepubads.g.doubleclick.net', pathname: '/gampad/ads', search: queryParams }); diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index bd417189aef..6271c9b38f4 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -30,7 +30,7 @@ describe('The DFP video support module', function () { })); expect(url.protocol).to.equal('https:'); - expect(url.host).to.equal('pubads.g.doubleclick.net'); + expect(url.host).to.equal('securepubads.g.doubleclick.net'); const queryParams = parseQS(url.query); expect(queryParams).to.have.property('correlator'); @@ -374,7 +374,7 @@ describe('The DFP video support module', function () { url = parse(masterTag); expect(url.protocol).to.equal('https:'); - expect(url.host).to.equal('pubads.g.doubleclick.net'); + expect(url.host).to.equal('securepubads.g.doubleclick.net'); const queryParams = parseQS(url.query); expect(queryParams).to.have.property('correlator'); @@ -428,7 +428,7 @@ describe('The DFP video support module', function () { } url = parse(masterTag); expect(url.protocol).to.equal('https:'); - expect(url.host).to.equal('pubads.g.doubleclick.net'); + expect(url.host).to.equal('securepubads.g.doubleclick.net'); const queryParams = parseQS(url.query); expect(queryParams).to.have.property('correlator'); From 124a2be5a0373c4dddcdb025172719b8b34c1db5 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 25 Sep 2019 15:15:54 -0400 Subject: [PATCH 1526/1594] Prebid 2.34.0 release --- package-lock.json | 220 ++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 107 insertions(+), 115 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb8263638fb..23c91d3921c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.33.0-pre", + "version": "2.34.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,17 +14,17 @@ } }, "@babel/core": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.0.tgz", - "integrity": "sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.2.tgz", + "integrity": "sha512-l8zto/fuoZIbncm+01p8zPSDZu/VuuJhAfA7d/AbzM09WR7iVhavvfNDYCNpo1VvLk6E6xgAoP9P+/EMJHuRkQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.0", - "@babel/helpers": "^7.6.0", - "@babel/parser": "^7.6.0", + "@babel/generator": "^7.6.2", + "@babel/helpers": "^7.6.2", + "@babel/parser": "^7.6.2", "@babel/template": "^7.6.0", - "@babel/traverse": "^7.6.0", + "@babel/traverse": "^7.6.2", "@babel/types": "^7.6.0", "convert-source-map": "^1.1.0", "debug": "^4.1.0", @@ -36,16 +36,15 @@ } }, "@babel/generator": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", - "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz", + "integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==", "dev": true, "requires": { "@babel/types": "^7.6.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" + "source-map": "^0.5.0" } }, "@babel/helper-annotate-as-pure": { @@ -241,13 +240,13 @@ } }, "@babel/helpers": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.0.tgz", - "integrity": "sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.2.tgz", + "integrity": "sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA==", "dev": true, "requires": { "@babel/template": "^7.6.0", - "@babel/traverse": "^7.6.0", + "@babel/traverse": "^7.6.2", "@babel/types": "^7.6.0" } }, @@ -263,9 +262,9 @@ } }, "@babel/parser": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz", - "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", + "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -300,9 +299,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", - "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz", + "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -320,14 +319,14 @@ } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", - "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz", + "integrity": "sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "regexpu-core": "^4.6.0" } }, "@babel/plugin-syntax-async-generators": { @@ -405,9 +404,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.0.tgz", - "integrity": "sha512-tIt4E23+kw6TgL/edACZwP1OUKrjOTyMrFMLoT5IOFrfMRabCgekjqFd5o6PaAMildBu46oFkekIdMuGkkPEpA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.2.tgz", + "integrity": "sha512-zZT8ivau9LOQQaOGC7bQLQOT4XPkPXgN2ERfUgk1X8ql+mVkLc4E8eKk+FO3o0154kxzqenWCorfmEXpEZcrSQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -449,14 +448,14 @@ } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", - "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz", + "integrity": "sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "regexpu-core": "^4.6.0" } }, "@babel/plugin-transform-duplicate-keys": { @@ -560,12 +559,12 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.0.tgz", - "integrity": "sha512-jem7uytlmrRl3iCAuQyw8BpB4c4LWvSpvIeXKpMb+7j84lkx4m4mYr5ErAcmN5KM7B6BqrAvRGjBIbbzqCczew==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.2.tgz", + "integrity": "sha512-xBdB+XOs+lgbZc2/4F5BVDVcDNS4tcSKQc96KmlqLEAwz6tpYPEvPdmDfvVG0Ssn8lAhronaRs6Z6KSexIpK5g==", "dev": true, "requires": { - "regexp-tree": "^0.1.13" + "regexpu-core": "^4.6.0" } }, "@babel/plugin-transform-new-target": { @@ -635,9 +634,9 @@ } }, "@babel/plugin-transform-spread": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", - "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz", + "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -673,20 +672,20 @@ } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", - "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz", + "integrity": "sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "regexpu-core": "^4.6.0" } }, "@babel/preset-env": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.0.tgz", - "integrity": "sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.2.tgz", + "integrity": "sha512-Ru7+mfzy9M1/YTEtlDS8CD45jd22ngb9tXnn64DvQK3ooyqSw9K4K9DUWmYknTTVk4TqygL9dqCrZgm1HMea/Q==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -694,9 +693,9 @@ "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-dynamic-import": "^7.5.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", + "@babel/plugin-proposal-object-rest-spread": "^7.6.2", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.6.2", "@babel/plugin-syntax-async-generators": "^7.2.0", "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", @@ -705,11 +704,11 @@ "@babel/plugin-transform-arrow-functions": "^7.2.0", "@babel/plugin-transform-async-to-generator": "^7.5.0", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.6.0", + "@babel/plugin-transform-block-scoping": "^7.6.2", "@babel/plugin-transform-classes": "^7.5.5", "@babel/plugin-transform-computed-properties": "^7.2.0", "@babel/plugin-transform-destructuring": "^7.6.0", - "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.6.2", "@babel/plugin-transform-duplicate-keys": "^7.5.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", "@babel/plugin-transform-for-of": "^7.4.4", @@ -720,7 +719,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.6.0", "@babel/plugin-transform-modules-systemjs": "^7.5.0", "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.6.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.6.2", "@babel/plugin-transform-new-target": "^7.4.4", "@babel/plugin-transform-object-super": "^7.5.5", "@babel/plugin-transform-parameters": "^7.4.4", @@ -728,11 +727,11 @@ "@babel/plugin-transform-regenerator": "^7.4.5", "@babel/plugin-transform-reserved-words": "^7.2.0", "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-spread": "^7.6.2", "@babel/plugin-transform-sticky-regex": "^7.2.0", "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.4", + "@babel/plugin-transform-unicode-regex": "^7.6.2", "@babel/types": "^7.6.0", "browserslist": "^4.6.0", "core-js-compat": "^3.1.1", @@ -753,16 +752,16 @@ } }, "@babel/traverse": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz", - "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", + "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.0", + "@babel/generator": "^7.6.2", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.0", + "@babel/parser": "^7.6.2", "@babel/types": "^7.6.0", "debug": "^4.1.0", "globals": "^11.1.0", @@ -3033,9 +3032,9 @@ } }, "buffer": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.2.tgz", - "integrity": "sha512-iy9koArjAFCzGnx3ZvNA6Z0clIbbFgbdWQ0mKD3hO0krOrZh8UgA6qMKcZvwLJxS+D6iVR76+5/pV56yMNYTag==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -3229,9 +3228,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000989", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz", - "integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==", + "version": "1.0.30000997", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000997.tgz", + "integrity": "sha512-BQLFPIdj2ntgBNWp9Q64LGUIEmvhKkzzHhUHR3CD5A9Lb7ZKF20/+sgadhFap69lk5XmK1fTUleDclaRFvgVUA==", "dev": true }, "caseless": { @@ -3524,9 +3523,9 @@ "dev": true }, "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true }, "combine-lists": { @@ -4720,9 +4719,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.254", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.254.tgz", - "integrity": "sha512-7I5/OkgR6JKy6RFLJeru0kc0RMmmMu1UnkHBKInFKRrg1/4EQKIqOaUqITSww/SZ1LqWwp1qc/LLoIGy449eYw==", + "version": "1.3.266", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.266.tgz", + "integrity": "sha512-UTuTZ4v8T0gLPHI7U75PXLQePWI65MTS3mckRrnLCkNljHvsutbYs+hn2Ua/RFul3Jt/L3Ht2rLP+dU/AlBfrQ==", "dev": true }, "elliptic": { @@ -4759,9 +4758,9 @@ "dev": true }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "requires": { "once": "^1.4.0" @@ -4881,13 +4880,12 @@ } }, "error": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", - "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/error/-/error-7.2.0.tgz", + "integrity": "sha512-M6t3j3Vt3uDicrViMP5fLq2AeADNrCVFD8Oj4Qt2MHsX0mPYG7D5XdnEfSdRpaHQzjAJ19wu+I1mw9rQYMTAPg==", "dev": true, "requires": { - "string-template": "~0.2.1", - "xtend": "~4.0.0" + "string-template": "~0.2.1" } }, "error-ex": { @@ -5571,9 +5569,9 @@ } }, "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", + "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", "dev": true }, "events": { @@ -8113,9 +8111,9 @@ } }, "handlebars": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz", - "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.3.1.tgz", + "integrity": "sha512-c0HoNHzDiHpBt4Kqe99N8tdLPKAnGCQ73gYMPWtAYM4PwGnf7xl8PBUHJqh9ijlzt2uQKaSRxbXRt+rZ7M2/kA==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -8444,12 +8442,12 @@ "dev": true }, "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", + "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", "dev": true, "requires": { - "eventemitter3": "^3.0.0", + "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } @@ -9002,9 +9000,9 @@ "dev": true }, "is-wsl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.0.tgz", - "integrity": "sha512-pFTjpv/x5HRj8kbZ/Msxi9VrvtOMRBqaDi3OIcbwPI3OuH+r3lLxVWukLITBaOGJIbA/w2+M1eVmVa4XNQlAmQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", + "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", "dev": true }, "isarray": { @@ -11033,9 +11031,9 @@ } }, "node-releases": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.30.tgz", - "integrity": "sha512-BHcr1g6NeUH12IL+X3Flvs4IOnl1TL0JczUhEZjDE+FXXPQcVCNr8NEPb01zqGxzhTpdyJL5GXemaCW7aw6Khw==", + "version": "1.1.32", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.32.tgz", + "integrity": "sha512-VhVknkitq8dqtWoluagsGPn3dxTvN9fwgR59fV3D7sLBHe0JfDramsMI8n8mY//ccq/Kkrf8ZRHRpsyVZ3qw1A==", "dev": true, "requires": { "semver": "^5.3.0" @@ -11506,9 +11504,9 @@ } }, "parse-asn1": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", - "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", "dev": true, "requires": { "asn1.js": "^4.0.0", @@ -12416,12 +12414,6 @@ "safe-regex": "^1.1.0" } }, - "regexp-tree": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.13.tgz", - "integrity": "sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw==", - "dev": true - }, "regexpp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", @@ -12429,9 +12421,9 @@ "dev": true }, "regexpu-core": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.5.tgz", - "integrity": "sha512-FpI67+ky9J+cDizQUJlIlNZFKual/lUkFr1AG6zOCpwZ9cLrg8UUVakyUQJD7fCDIe9Z2nwTQJNPyonatNmDFQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", + "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", "dev": true, "requires": { "regenerate": "^1.4.0", @@ -14244,9 +14236,9 @@ "dev": true }, "type": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/type/-/type-1.0.3.tgz", - "integrity": "sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg==", + "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": { @@ -15402,9 +15394,9 @@ } }, "webpack-bundle-analyzer": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", - "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.5.1.tgz", + "integrity": "sha512-CDdaT3TTu4F9X3tcDq6PNJOiNGgREOM0WdN2vVAoUUn+M6NLB5kJ543HImCWbrDwOpbpGARSwU8r+u0Pl367kA==", "dev": true, "requires": { "acorn": "^6.0.7", diff --git a/package.json b/package.json index 314323914a1..ae02c8f3340 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.34.0-pre", + "version": "2.34.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 0274410bc7e81dc4578651ff5c718cf02de8704b Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 25 Sep 2019 15:25:11 -0400 Subject: [PATCH 1527/1594] increment pre version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 23c91d3921c..c7256dd8e2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.34.0", + "version": "2.35.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ae02c8f3340..967dcede83c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.34.0", + "version": "2.35.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From d79483b6c81d44ac11485723198655b174693bc3 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Thu, 26 Sep 2019 11:04:41 -0700 Subject: [PATCH 1528/1594] Rubi Analytics handles > 1 bidResponse per bidRequest (#4224) --- modules/rubiconAnalyticsAdapter.js | 32 +++++++----- .../modules/rubiconAnalyticsAdapter_spec.js | 50 +++++++++++++++++++ 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index 560cab91dca..53c701151eb 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -209,18 +209,26 @@ function sendMessage(auctionId, bidWonId) { ); } -export function parseBidResponse(bid) { +function getBidPrice(bid) { + if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === 'USD') { + return Number(bid.cpm); + } + // use currency conversion function if present + if (typeof bid.getCpmInNewCurrency === 'function') { + return Number(bid.getCpmInNewCurrency('USD')); + } + utils.logWarn('Rubicon Analytics Adapter: Could not determine the bidPriceUSD of the bid ', bid); +} + +export function parseBidResponse(bid, previousBidResponse) { + // The current bidResponse for this matching requestId/bidRequestId + let responsePrice = getBidPrice(bid) + // we need to compare it with the previous one (if there was one) + if (previousBidResponse && previousBidResponse.bidPriceUSD > responsePrice) { + return previousBidResponse; + } return utils.pick(bid, [ - 'bidPriceUSD', () => { - if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === 'USD') { - return Number(bid.cpm); - } - // use currency conversion function if present - if (typeof bid.getCpmInNewCurrency === 'function') { - return Number(bid.getCpmInNewCurrency('USD')); - } - utils.logWarn('Rubicon Analytics Adapter: Could not determine the bidPriceUSD of the bid ', bid); - }, + 'bidPriceUSD', () => responsePrice, 'dealId', 'status', 'mediaType', @@ -405,7 +413,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { }; } bid.clientLatencyMillis = Date.now() - cache.auctions[args.auctionId].timestamp; - bid.bidResponse = parseBidResponse(args); + bid.bidResponse = parseBidResponse(args, bid.bidResponse); break; case BIDDER_DONE: args.bids.forEach(bid => { diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 9c005c3394f..3452ae747b9 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -657,6 +657,56 @@ describe('rubicon analytics adapter', function () { expect(message).to.deep.equal(ANALYTICS_MESSAGE); }); + it('should pick the highest cpm bid if more than one bid per bidRequestId', function () { + // Only want one bid request in our mock auction + let bidRequested = utils.deepClone(MOCK.BID_REQUESTED); + bidRequested.bids.shift(); + let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); + auctionInit.adUnits.shift(); + + // clone the mock bidResponse and duplicate + let duplicateResponse1 = utils.deepClone(BID2); + duplicateResponse1.cpm = 1.0; + duplicateResponse1.adserverTargeting.hb_pb = '1.0'; + duplicateResponse1.adserverTargeting.hb_adid = '1111'; + let duplicateResponse2 = utils.deepClone(BID2); + duplicateResponse2.cpm = 5.5; + duplicateResponse2.adserverTargeting.hb_pb = '5.5'; + duplicateResponse2.adserverTargeting.hb_adid = '5555'; + let duplicateResponse3 = utils.deepClone(BID2); + duplicateResponse3.cpm = 0.1; + duplicateResponse3.adserverTargeting.hb_pb = '0.1'; + duplicateResponse3.adserverTargeting.hb_adid = '3333'; + + const setTargeting = { + [duplicateResponse2.adUnitCode]: duplicateResponse2.adserverTargeting + }; + + const bidWon = Object.assign({}, duplicateResponse2, { + 'status': 'rendered' + }); + + // spoof the auction with just our duplicates + events.emit(AUCTION_INIT, auctionInit); + events.emit(BID_REQUESTED, bidRequested); + events.emit(BID_RESPONSE, duplicateResponse1); + events.emit(BID_RESPONSE, duplicateResponse2); + events.emit(BID_RESPONSE, duplicateResponse3); + events.emit(AUCTION_END, MOCK.AUCTION_END); + events.emit(SET_TARGETING, setTargeting); + events.emit(BID_WON, bidWon); + + let message = JSON.parse(requests[0].requestBody); + validate(message); + expect(message.auctions[0].adUnits[0].bids[0].bidResponse.bidPriceUSD).to.equal(5.5); + expect(message.auctions[0].adUnits[0].adserverTargeting.hb_pb).to.equal('5.5'); + expect(message.auctions[0].adUnits[0].adserverTargeting.hb_adid).to.equal('5555'); + expect(message.bidsWon.length).to.equal(1); + expect(message.bidsWon[0].bidResponse.bidPriceUSD).to.equal(5.5); + expect(message.bidsWon[0].adserverTargeting.hb_pb).to.equal('5.5'); + expect(message.bidsWon[0].adserverTargeting.hb_adid).to.equal('5555'); + }); + it('should send batched message without BID_WON if necessary and further BID_WON events individually', function () { events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); From 25e5fd0651e3251cc0710c174f07bce306eeee8a Mon Sep 17 00:00:00 2001 From: sdbaron Date: Fri, 27 Sep 2019 16:13:07 +0300 Subject: [PATCH 1529/1594] videoNow bid adapter (#4088) * -- first commit * -- cors and bidder's name fixed * -- almost ready * -- added docs * -- added nurl tracking * -- bid params * -- tests added * -- test fixed * -- replace placeholder in the onBidWon pixel's url * -- commit for restart tests * -- change response data format for display ad * -- tests updated * -- 100% tests coverage * -- a few clean the test's code * -- custom urls from localStorage * -- tests updated * -- a few clean the test's code * -- new init model * -- spec for new init model * -- fix for new init model * -- code cleaned * -- 100% tests coverage * -- 100% tests coverage * -- fixed test * -- commit for restart tests --- modules/videoNowBidAdapter.js | 191 +++++++ modules/videoNowBidAdapter.md | 35 ++ test/spec/modules/videoNowBidAdapter_spec.js | 566 +++++++++++++++++++ 3 files changed, 792 insertions(+) create mode 100644 modules/videoNowBidAdapter.js create mode 100644 modules/videoNowBidAdapter.md create mode 100644 test/spec/modules/videoNowBidAdapter_spec.js diff --git a/modules/videoNowBidAdapter.js b/modules/videoNowBidAdapter.js new file mode 100644 index 00000000000..7b358f64939 --- /dev/null +++ b/modules/videoNowBidAdapter.js @@ -0,0 +1,191 @@ +import * as utils from '../src/utils' +import { registerBidder } from '../src/adapters/bidderFactory' +import { BANNER } from '../src/mediaTypes' + +const RTB_URL = 'https://bidder.videonow.ru/prebid' + +const BIDDER_CODE = 'videonow' +const TTL_SECONDS = 60 * 5 + +function isBidRequestValid(bid) { + return !!(bid && bid.params && bid.params.pId) +} + +function buildRequest(bid, bidderRequest) { + const { refererInfo } = bidderRequest + const { ext, bidId, params, code, sizes } = bid + const { pId, bidFloor, cur, placementId, url: rtbUrl } = params || {} + + let url = rtbUrl || RTB_URL + url = `${url}${~url.indexOf('?') ? '&' : '?'}profile_id=${pId}` + + const dto = { + method: 'POST', + url, + data: { + id: bidId, + cpm: bidFloor, + code, + sizes, + cur: cur || 'RUB', + placementId, + ref: refererInfo && refererInfo.referer, + }, + } + + ext && Object.keys(ext).forEach(key => { + dto.data[`ext_${key}`] = ext[key] + }) + + return dto +} + +function buildRequests(validBidRequests, bidderRequest) { + utils.logInfo(`${BIDDER_CODE}. buildRequests`) + const requests = [] + validBidRequests.forEach(validBidRequest => { + const request = buildRequest(validBidRequest, bidderRequest) + request && requests.push(request) + }) + return requests +} + +function interpretResponse(serverResponse, bidRequest) { + if (!serverResponse || !serverResponse.body) { + return [] + } + const { id: bidId } = (bidRequest && bidRequest.data) || {} + if (!bidId) return [] + + const { seatbid, cur, ext } = serverResponse.body + if (!seatbid || !seatbid.length) return [] + + const { placementId } = ext || {} + if (!placementId) return [] + + const bids = [] + seatbid.forEach(sb => { + const { bid } = sb + bid && bid.length && bid.forEach(b => { + const res = createResponseBid(b, bidId, cur, placementId) + res && bids.push(res) + }) + }) + + return bids +} + +function createResponseBid(bidInfo, bidId, cur, placementId) { + const { id, nurl, code, price, crid, ext, ttl, netRevenue, w, h, adm } = bidInfo + + if (!id || !price || !adm) { + return null + } + + const { init: initPath, module, format } = ext || {} + if (!initPath) { + utils.logError(`vnInitModulePath is not defined`) + return null + } + + const { log, min } = module || {} + + if (!min && !log) { + utils.logError('module\'s paths are not defined') + return null + } + + return { + requestId: bidId, + cpm: price, + width: w, + height: h, + creativeId: crid, + currency: cur || 'RUB', + netRevenue: netRevenue !== undefined ? netRevenue : true, + ttl: ttl || TTL_SECONDS, + ad: code, + nurl, + renderer: { + url: min || log, + render: function() { + const d = window.document + const el = placementId && d.getElementById(placementId) + if (el) { + const pId = 1 + // prepare data for vn_init script + const profileData = { + module, + dataXml: adm, + } + + format && (profileData.format = format) + + // add init data for vn_init on the page + const videonow = window.videonow = window.videonow || {} + const init = videonow.init = window.videonow.init || {} + init[pId] = profileData + + // add vn_init js on the page + const scr = document.createElement('script') + scr.src = `${initPath}${~initPath.indexOf('?') ? '&' : '?'}profileId=${pId}` + el && el.appendChild(scr) + } else { + utils.logError(`bidAdapter ${BIDDER_CODE}: ${placementId} not found`) + } + } + } + } +} + +function getUserSyncs(syncOptions, serverResponses) { + const syncs = [] + + if (!serverResponses || !serverResponses.length) return syncs + + serverResponses.forEach(response => { + const { ext } = (response && response.body) || {} + const { pixels, iframes } = ext || {} + + if (syncOptions.iframeEnabled && iframes && iframes.length) { + iframes.forEach(i => syncs.push({ + type: 'iframe', + url: i, + }), + ) + } + + if (syncOptions.pixelEnabled && pixels && pixels.length) { + pixels.forEach(p => syncs.push({ + type: 'image', + url: p, + }), + ) + } + }) + + utils.logInfo(`${BIDDER_CODE} getUserSyncs() syncs=${syncs.length}`) + return syncs +} + +function onBidWon(bid) { + const { nurl } = bid || {} + if (nurl) { + const img = document.createElement('img') + img.src = utils.replaceAuctionPrice(nurl, bid.cpm) + img.style.cssText = 'display:none !important;' + document.body.appendChild(img) + } +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + isBidRequestValid, + buildRequests, + interpretResponse, + getUserSyncs, + onBidWon +} + +registerBidder(spec) diff --git a/modules/videoNowBidAdapter.md b/modules/videoNowBidAdapter.md new file mode 100644 index 00000000000..2ac2a431378 --- /dev/null +++ b/modules/videoNowBidAdapter.md @@ -0,0 +1,35 @@ +# Overview + +``` +Module Name: Videonow Bidder Adapter +Module Type: Bidder Adapter +Maintainer: info@videonow.ru +``` + +# Description + +Connect to Videonow for bids. + +The Videonow bidder adapter requires setup and approval from the videoNow team. +Please reach out to your account team or info@videonow.ru for more information. + +# Test Parameters +```javascript +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[640, 480], [300, 250], [336, 280]] + } + }, + bids: [{ + bidder: 'videonow', + params: { + pId: 1, + placementId: '36891' + } + }] + }] +``` diff --git a/test/spec/modules/videoNowBidAdapter_spec.js b/test/spec/modules/videoNowBidAdapter_spec.js new file mode 100644 index 00000000000..337960c6edd --- /dev/null +++ b/test/spec/modules/videoNowBidAdapter_spec.js @@ -0,0 +1,566 @@ +import { expect } from 'chai' +import { spec } from 'modules/videoNowBidAdapter' +import { replaceAuctionPrice } from '../../../src/utils' + +const placementId = 'div-gpt-ad-1438287399331-1' +const LS_ITEM_NAME = 'videonow-config' + +const getValidServerResponse = () => { + const serverResponse = { + body: { + id: '111-111', + bidid: '2955a162-699e-4811-ce88-5c3ac973e73c', + cur: 'RUB', + seatbid: [ + { + bid: [ + { + id: 'e3bf2b82e3e9485113fad6c9b27f8768.1', + impid: '1', + price: 10.97, + nurl: 'http://localhost:8086/event/nurl', + netRevenue: false, + ttl: 800, + adm: '', + crid: 'e3bf2b82e3e9485113fad6c9b27f8768.1', + h: 640, + w: 480, + ext: { + init: 'http://localhost:8086/vn_init.js', + module: { + min: 'http://localhost:8086/vn_module.js', + log: 'http://localhost:8086/vn_module.js?log=1' + }, + format: { + name: 'flyRoll', + }, + }, + + }, + ], + group: 0, + }, + ], + price: 10, + ext: { + placementId, + pixels: [ + 'http://localhost:8086/event/pxlcookiematching?uiid=1', + 'http://localhost:8086/event/pxlcookiematching?uiid=2', + ], + iframes: [ + 'http://localhost:8086/event/ifrcookiematching?uiid=1', + 'http://localhost:8086/event/ifrcookiematching?uiid=2', + ], + }, + }, + headers: {}, + } + + return JSON.parse(JSON.stringify(serverResponse)) +} + +describe('videonowAdapterTests', function() { + describe('bidRequestValidity', function() { + it('bidRequest with pId', function() { + expect(spec.isBidRequestValid({ + bidder: 'videonow', + params: { + pId: '86858', + }, + })).to.equal(true) + }) + + it('bidRequest without pId', function() { + expect(spec.isBidRequestValid({ + bidder: 'videonow', + params: { + nomater: 86858, + }, + })).to.equal(false) + + it('bidRequest is empty', function() { + expect(spec.isBidRequestValid({})).to.equal(false) + }) + + it('bidRequest is undefned', function() { + expect(spec.isBidRequestValid(undefined)).to.equal(false) + }) + }) + + describe('bidRequest', function() { + const validBidRequests = [ + { + bidder: 'videonow', + params: { + pId: '1', + placementId, + url: 'http://localhost:8086/bid?p=exists', + bidFloor: 10, + cur: 'RUB' + }, + crumbs: { + pubcid: 'feded041-35dd-4b54-979a-6d7805abfa75', + }, + mediaTypes: { + banner: { + sizes: [[640, 480], [320, 200]] + }, + }, + adUnitCode: 'test-ad', + transactionId: '676403c7-09c9-4b56-be82-e7cae81f40b9', + sizes: [[640, 480], [320, 200]], + bidId: '268c309f46390d', + bidderRequestId: '1dfdd514c36ef6', + auctionId: '4d523546-889a-4029-9a79-13d3c69f9922', + src: 'client', + bidRequestsCount: 1, + }, + ] + + const bidderRequest = { + bidderCode: 'videonow', + auctionId: '4d523546-889a-4029-9a79-13d3c69f9922', + bidderRequestId: '1dfdd514c36ef6', + bids: [ + { + bidder: 'videonow', + params: { + pId: '1', + placementId, + url: 'http://localhost:8086/bid', + bidFloor: 10, + cur: 'RUB', + }, + crumbs: { + pubcid: 'feded041-35dd-4b54-979a-6d7805abfa75', + }, + mediaTypes: { + banner: { + sizes: [[640, 480], [320, 200]], + }, + }, + adUnitCode: 'test-ad', + transactionId: '676403c7-09c9-4b56-be82-e7cae81f40b9', + sizes: [[640, 480], [320, 200]], + bidId: '268c309f46390d', + bidderRequestId: '1dfdd514c36ef6', + auctionId: '4d523546-889a-4029-9a79-13d3c69f9922', + src: 'client', + bidRequestsCount: 1, + }, + ], + auctionStart: 1565794308584, + timeout: 3000, + refererInfo: { + referer: 'http://localhost:8086/page', + reachedTop: true, + numIframes: 0, + stack: [ + 'http://localhost:8086/page', + ], + }, + start: 1565794308589, + } + + const requests = spec.buildRequests(validBidRequests, bidderRequest) + const request = (requests && requests.length && requests[0]) || {} + + it('bidRequest count', function() { + expect(requests.length).to.equal(1) + }) + + it('bidRequest method', function() { + expect(request.method).to.equal('POST') + }) + + it('bidRequest url', function() { + expect(request.url).to.equal('http://localhost:8086/bid?p=exists&profile_id=1') + }) + + it('bidRequest data', function() { + const data = request.data + expect(data.aid).to.be.eql(validBidRequests[0].params.aid) + expect(data.id).to.be.eql(validBidRequests[0].bidId) + expect(data.sizes).to.be.eql(validBidRequests[0].sizes) + }) + + describe('bidRequest advanced', function() { + const bidderRequestEmptyParamsAndExtParams = { + bidder: 'videonow', + params: { + pId: '1', + }, + ext: { + p1: 'ext1', + p2: 'ext2', + }, + } + + it('bidRequest count', function() { + const requests = spec.buildRequests([bidderRequestEmptyParamsAndExtParams], bidderRequest) + expect(requests.length).to.equal(1) + }) + + it('bidRequest default url', function() { + const requests = spec.buildRequests([bidderRequestEmptyParamsAndExtParams], bidderRequest) + const request = (requests && requests.length && requests[0]) || {} + expect(request.url).to.equal('https://bidder.videonow.ru/prebid?profile_id=1') + }) + + it('bidRequest default currency', function() { + const requests = spec.buildRequests([bidderRequestEmptyParamsAndExtParams], bidderRequest) + const request = (requests && requests.length && requests[0]) || {} + const data = (request && request.data) || {} + expect(data.cur).to.equal('RUB') + }) + + it('bidRequest ext parameters ', function() { + const requests = spec.buildRequests([bidderRequestEmptyParamsAndExtParams], bidderRequest) + const request = (requests && requests.length && requests[0]) || {} + const data = (request && request.data) || {} + expect(data['ext_p1']).to.equal('ext1') + expect(data['ext_p2']).to.equal('ext2') + }) + + it('bidRequest without params', function() { + const bidderReq = { + bidder: 'videonow', + } + const requests = spec.buildRequests([bidderReq], bidderRequest) + expect(requests.length).to.equal(1) + }) + }) + }) + + describe('onBidWon', function() { + const cpm = 10 + const nurl = 'http://fakedomain.nld?price=${AUCTION_PRICE}' + const imgSrc = replaceAuctionPrice(nurl, cpm) + const foundPixels = () => window.document.body.querySelectorAll(`img[src="${imgSrc}"]`) + + it('Should not create nurl pixel if bid is undefined', function() { + spec.onBidWon() + expect(foundPixels().length).to.equal(0) + }) + + it('Should not create nurl pixel if bid does not contains nurl', function() { + spec.onBidWon({}) + expect(foundPixels().length).to.equal(0) + }) + + it('Should create nurl pixel if bid nurl', function() { + spec.onBidWon({ nurl, cpm }) + expect(foundPixels().length).to.equal(1) + }) + }) + + describe('getUserSyncs', function() { + it('Should return an empty array if not get serverResponses', function() { + expect(spec.getUserSyncs({}).length).to.equal(0) + }) + + it('Should return an empty array if get serverResponses as empty array', function() { + expect(spec.getUserSyncs({}, []).length).to.equal(0) + }) + + it('Should return an empty array if serverResponses has no body', function() { + const serverResp = getValidServerResponse() + delete serverResp.body + const syncs = spec.getUserSyncs({}, [serverResp]) + expect(syncs.length).to.equal(0) + }) + + it('Should return an empty array if serverResponses has no ext', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.ext + const syncs = spec.getUserSyncs({}, [serverResp]) + expect(syncs.length).to.equal(0) + }) + + it('Should return an array', function() { + const serverResp = getValidServerResponse() + const syncs = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [serverResp]) + expect(syncs.length).to.equal(4) + }) + + it('Should return pixels', function() { + const serverResp = getValidServerResponse() + const syncs = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [serverResp]) + expect(syncs.length).to.equal(2) + expect(syncs[0].type).to.equal('image') + expect(syncs[1].type).to.equal('image') + }) + + it('Should return iframes', function() { + const serverResp = getValidServerResponse() + const syncs = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [serverResp]) + expect(syncs.length).to.equal(2) + expect(syncs[0].type).to.equal('iframe') + expect(syncs[1].type).to.equal('iframe') + }) + }) + + describe('interpretResponse', function() { + const bidRequest = { + method: 'POST', + url: 'http://localhost:8086/bid?profile_id=1', + data: { + id: '217b8ab59a18e8', + cpm: 10, + sizes: [[640, 480], [320, 200]], + cur: 'RUB', + placementId, + ref: 'http://localhost:8086/page', + }, + } + + it('Should have only one bid', function() { + const serverResponse = getValidServerResponse() + const result = spec.interpretResponse(serverResponse, bidRequest) + expect(result.length).to.equal(1) + }) + + it('Should have required keys', function() { + const serverResponse = getValidServerResponse() + const result = spec.interpretResponse(serverResponse, bidRequest) + const bid = serverResponse.body.seatbid[0].bid[0] + const res = result[0] + expect(res.requestId).to.be.eql(bidRequest.data.id) + expect(res.cpm).to.be.eql(bid.price) + expect(res.creativeId).to.be.eql(bid.crid) + expect(res.netRevenue).to.be.a('boolean') + expect(res.ttl).to.be.eql(bid.ttl) + expect(res.renderer).to.be.a('Object') + expect(res.renderer.render).to.be.a('function') + }) + + it('Should return an empty array if empty or no bids in response', function() { + expect(spec.interpretResponse({ body: '' }, {}).length).to.equal(0) + }) + + it('Should return an empty array if bidRequest\'s data is absent', function() { + const serverResponse = getValidServerResponse() + expect(spec.interpretResponse(serverResponse, undefined).length).to.equal(0) + }) + + it('Should return an empty array if bidRequest\'s data is not contains bidId ', function() { + const serverResponse = getValidServerResponse() + expect(spec.interpretResponse(serverResponse, { data: {} }).length).to.equal(0) + }) + + it('Should return an empty array if bidRequest\'s data bidId is undefined', function() { + const serverResponse = getValidServerResponse() + expect(spec.interpretResponse(serverResponse, { data: { id: null } }).length).to.equal(0) + }) + + it('Should return an empty array if serverResponse do not contains seatbid', function() { + expect(spec.interpretResponse({ body: {} }, bidRequest).length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s seatbid is empty', function() { + expect(spec.interpretResponse({ body: { seatbid: [] } }, bidRequest).length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s placementId is undefined', function() { + expect(spec.interpretResponse({ body: { seatbid: [1, 2] } }, bidRequest).length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s id in the bid is undefined', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].id + let res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s price in the bid is undefined', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].price + const res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s price in the bid is 0', function() { + const serverResp = getValidServerResponse() + serverResp.body.seatbid[0].bid[0].price = 0 + const res = spec.interpretResponse(serverResp, bidRequest) + + expect(res.length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s init in the bid\'s ext is undefined', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].ext.init + const res = spec.interpretResponse(serverResp, bidRequest) + + expect(res.length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s module in the bid\'s ext is undefined', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].ext.module + const res = spec.interpretResponse(serverResp, bidRequest) + + expect(res.length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s adm in the bid is undefined', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].adm + const res = spec.interpretResponse(serverResp, bidRequest) + + expect(res.length).to.equal(0) + }) + + it('Should return an empty array if serverResponse\'s the bid\'s ext is undefined', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].ext + const res = spec.interpretResponse(serverResp, bidRequest) + + expect(res.length).to.equal(0) + }) + + it('Default ttl is 300', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].ttl + const res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(1) + expect(res[0].ttl).to.equal(300) + }) + + it('Default netRevenue is true', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].netRevenue + const res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(1) + expect(res[0].netRevenue).to.be.true; + }) + + it('Default currency is RUB', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.cur + const res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(1) + expect(res[0].currency).to.equal('RUB') + }) + + describe('different module paths', function() { + beforeEach(function() { + window.localStorage && localStorage.setItem(LS_ITEM_NAME, '{}') + }) + + afterEach(function() { + const serverResp = getValidServerResponse() + const { module: { log, min }, init } = serverResp.body.seatbid[0].bid[0].ext + remove(init) + remove(log) + remove(min) + + function remove(src) { + if (!src) return + const d = document.querySelectorAll(`script[src^="${src}"]`) + d && d.length && Array.from(d).forEach(el => el && el.remove()) + } + }) + + it('should use prod module by default', function() { + const serverResp = getValidServerResponse() + const res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(1) + + const renderer = res[0].renderer + expect(renderer).to.be.an('object') + expect(renderer.url).to.equal(serverResp.body.seatbid[0].bid[0].ext.module.min) + }) + + it('should use "log" module if "prod" is not exists', function() { + const serverResp = getValidServerResponse() + delete serverResp.body.seatbid[0].bid[0].ext.module.min + const res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(1) + + const renderer = res[0].renderer + expect(renderer).to.be.an('object') + expect(renderer.url).to.equal(serverResp.body.seatbid[0].bid[0].ext.module.log) + }) + + it('should correct combine src for init', function() { + const serverResp = getValidServerResponse() + + const src = `${serverResp.body.seatbid[0].bid[0].ext.init}?profileId=1` + const placementElement = document.createElement('div') + placementElement.setAttribute('id', placementId) + + const resp = spec.interpretResponse(serverResp, bidRequest) + expect(resp.length).to.equal(1) + + const renderer = resp[0].renderer + expect(renderer).to.be.an('object') + + document.body.appendChild(placementElement) + + renderer.render() + + const res = document.querySelectorAll(`script[src="${src}"]`) + expect(res.length).to.equal(1) + }) + + it('should correct combine src for init if init url contains "?"', function() { + const serverResp = getValidServerResponse() + + serverResp.body.seatbid[0].bid[0].ext.init += '?div=1' + const src = `${serverResp.body.seatbid[0].bid[0].ext.init}&profileId=1` + + const placementElement = document.createElement('div') + placementElement.setAttribute('id', placementId) + + const resp = spec.interpretResponse(serverResp, bidRequest) + expect(resp.length).to.equal(1) + + const renderer = resp[0].renderer + expect(renderer).to.be.an('object') + + document.body.appendChild(placementElement) + + renderer.render() + + const res = document.querySelectorAll(`script[src="${src}"]`) + expect(res.length).to.equal(1) + }) + }) + + describe('renderer object', function() { + it('execute renderer.render() should create window.videonow object', function() { + const serverResp = getValidServerResponse() + const res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(1) + + const renderer = res[0].renderer + expect(renderer).to.be.an('object') + expect(renderer.render).to.a('function') + + const doc = window.document + const placementElement = doc.createElement('div') + placementElement.setAttribute('id', placementId) + doc.body.appendChild(placementElement) + + renderer.render() + expect(window.videonow).to.an('object') + }) + }) + + it('execute renderer.render() should not create window.videonow object if placement element not found', function() { + const serverResp = getValidServerResponse() + const res = spec.interpretResponse(serverResp, bidRequest) + expect(res.length).to.equal(1) + + const renderer = res[0].renderer + expect(renderer).to.be.an('object') + expect(renderer.render).to.a('function') + + renderer.render() + expect(window.videonow).to.be.undefined + }) + }) + }) +}) From 91146b62b4533df603215123d7f49a0a839fd024 Mon Sep 17 00:00:00 2001 From: djaxbidder <55269794+djaxbidder@users.noreply.github.com> Date: Fri, 27 Sep 2019 18:48:06 +0530 Subject: [PATCH 1530/1594] djax new bidder adapter (#4192) * djax bidder adapter * djax bidder adapter * Update hello_world.html --- modules/djaxBidAdapter.js | 129 ++++++++++++++++++ modules/djaxBidAdapter.md | 50 +++++++ test/spec/modules/djaxBidAdapter_spec.js | 159 +++++++++++++++++++++++ 3 files changed, 338 insertions(+) create mode 100644 modules/djaxBidAdapter.js create mode 100644 modules/djaxBidAdapter.md create mode 100644 test/spec/modules/djaxBidAdapter_spec.js diff --git a/modules/djaxBidAdapter.js b/modules/djaxBidAdapter.js new file mode 100644 index 00000000000..58f500d2a2b --- /dev/null +++ b/modules/djaxBidAdapter.js @@ -0,0 +1,129 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; +import * as utils from '../src/utils'; +import {BANNER, VIDEO} from '../src/mediaTypes'; +import { ajax } from '../src/ajax'; +import {Renderer} from '../src/Renderer'; + +const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const BIDDER_CODE = 'djax'; +const DOMAIN = 'https://demo.reviveadservermod.com/headerbidding_adminshare/'; +const RENDERER_URL = '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; + +function isBidRequestValid(bid) { + return (typeof bid.params !== 'undefined' && parseInt(utils.getValue(bid.params, 'publisherId')) > 0); +} + +function buildRequests(validBidRequests) { + return { + method: 'POST', + url: DOMAIN + 'www/admin/plugins/Prebid/getAd.php', + options: { + withCredentials: false, + crossOrigin: true + }, + data: validBidRequests, + }; +} + +function interpretResponse(serverResponse, request) { + const response = serverResponse.body; + const bidResponses = []; + var bidRequestResponses = []; + + utils._each(response, function(bidAd) { + bidAd.adResponse = { + content: bidAd.vastXml, + height: bidAd.height, + width: bidAd.width + }; + bidAd.ttl = config.getConfig('_bidderTimeout') + bidAd.renderer = bidAd.context === 'outstream' ? createRenderer(bidAd, { + id: bidAd.adUnitCode, + url: RENDERER_URL + }, bidAd.adUnitCode) : undefined; + bidResponses.push(bidAd); + }); + + bidRequestResponses.push({ + function: 'saveResponses', + request: request, + response: bidResponses + }); + sendResponseToServer(bidRequestResponses); + return bidResponses; +} + +function outstreamRender(bidAd) { + bidAd.renderer.push(() => { + window.ANOutstreamVideo.renderAd({ + sizes: [bidAd.width, bidAd.height], + width: bidAd.width, + height: bidAd.height, + targetId: bidAd.adUnitCode, + adResponse: bidAd.adResponse, + rendererOptions: { + showVolume: false, + allowFullscreen: false + } + }); + }); +} + +function createRenderer(bidAd, rendererParams, adUnitCode) { + const renderer = Renderer.install({ + id: rendererParams.id, + url: rendererParams.url, + loaded: false, + config: {'player_height': bidAd.height, 'player_width': bidAd.width}, + adUnitCode + }); + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + return renderer; +} + +function onBidWon(bid) { + let wonBids = []; + wonBids.push(bid); + wonBids[0].function = 'onBidWon'; + sendResponseToServer(wonBids); +} + +function onTimeout(details) { + details.unshift({ 'function': 'onTimeout' }); + sendResponseToServer(details); +} + +function sendResponseToServer(data) { + ajax(DOMAIN + 'www/admin/plugins/Prebid/tracking/track.php', null, JSON.stringify(data), { + withCredentials: false, + method: 'POST', + crossOrigin: true + }); +} + +function getUserSyncs(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: DOMAIN + 'www/admin/plugins/Prebid/userSync.php' + }]; + } +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: SUPPORTED_AD_TYPES, + isBidRequestValid, + buildRequests, + interpretResponse, + getUserSyncs, + onBidWon, + onTimeout +}; + +registerBidder(spec); diff --git a/modules/djaxBidAdapter.md b/modules/djaxBidAdapter.md new file mode 100644 index 00000000000..d597eb59b58 --- /dev/null +++ b/modules/djaxBidAdapter.md @@ -0,0 +1,50 @@ +# Overview + +``` +Module Name: djax Bid Adapter +Module Type: Bidder Adapter +Maintainer : support@djaxtech.com +``` + +# Description + +Connects to Djax Ad Server for bids. + +djax bid adapter supports Banner and Video. + +# Test Parameters +``` + var adUnits = [ + //bannner object + { + code: 'banner-ad-slot', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + }, + bids: [{ + bidder: 'djax', + params: { + publisherId: 2 + } + }] + + }, + //video object + { + code: 'video-ad-slot', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + }, + }, + bids: [{ + bidder: "djax", + params: { + publisherId: 2 + } + }] + }]; +``` \ No newline at end of file diff --git a/test/spec/modules/djaxBidAdapter_spec.js b/test/spec/modules/djaxBidAdapter_spec.js new file mode 100644 index 00000000000..82955ba43bc --- /dev/null +++ b/test/spec/modules/djaxBidAdapter_spec.js @@ -0,0 +1,159 @@ +import { expect } from 'chai'; +import { spec } from 'modules/djaxBidAdapter'; + +const ENDPOINT = 'https://demo.reviveadservermod.com/headerbidding_adminshare/www/admin/plugins/Prebid/getAd.php'; + +describe('The Djax bidding adapter', function () { + describe('isBidRequestValid', function () { + it('should return false when given an invalid bid', function () { + const bid = { + bidder: 'djax', + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + + it('should return true when given a publisherId in bid', function () { + const bid = { + bidder: 'djax', + params: { + publisherId: 2 + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + }); + + describe('buildRequests', function () { + const bidRequests = [{ + 'bidder': 'djax', + 'params': { + 'publisherId': 2 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ] + }]; + + const request = spec.buildRequests(bidRequests); + + it('sends bid request to our endpoint via POST', function () { + expect(request.method).to.equal('POST'); + }); + + it('check endpoint url', function () { + expect(request.url).to.equal(ENDPOINT) + }); + + it('sets the proper banner object', function () { + expect(bidRequests[0].params.publisherId).to.equal(2); + }) + }); + const response = { + body: [ + { + 'requestId': '2ee937f15015c6', + 'cpm': '0.2000', + 'width': 300, + 'height': 600, + 'creativeId': '4', + 'currency': 'USD', + 'netRevenue': true, + 'ad': 'ads.html', + 'mediaType': 'banner' + }, + { + 'requestId': '3e1af92622bdc', + 'cpm': '0.2000', + 'creativeId': '4', + 'context': 'outstream', + 'currency': 'USD', + 'netRevenue': true, + 'vastUrl': 'tezt.xml', + 'width': 640, + 'height': 480, + 'mediaType': 'video' + }] + }; + + const request = [ + { + 'bidder': 'djax', + 'params': { + 'publisherId': 2 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [ + [300, 600] + ] + } + }, + 'bidId': '2ee937f15015c6', + 'src': 'client', + }, + { + 'bidder': 'djax', + 'params': { + 'publisherId': 2 + }, + 'mediaTypes': { + 'video': { + 'context': 'outstream', + 'playerSize': [ + [640, 480] + ] + } + }, + 'bidId': '3e1af92622bdc', + 'src': 'client', + } + ]; + + describe('interpretResponse', function () { + it('return empty array when no ad found', function () { + const response = {}; + const request = { bidRequests: [] }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(0); + }); + + it('check response for banner and video', function () { + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(2); + expect(bids[0].requestId).to.equal('2ee937f15015c6'); + expect(bids[0].cpm).to.equal('0.2000'); + expect(bids[1].cpm).to.equal('0.2000'); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(600); + expect(bids[1].vastUrl).to.not.equal(''); + expect(bids[0].ad).to.not.equal(''); + expect(bids[1].adResponse).to.not.equal(''); + expect(bids[1].renderer).not.to.be.an('undefined'); + }); + }); + + describe('On winning bid', function () { + const bids = spec.interpretResponse(response, request); + spec.onBidWon(bids); + }); + + describe('On bid Time out', function () { + const bids = spec.interpretResponse(response, request); + spec.onTimeout(bids); + }); + + describe('user sync', function () { + it('to check the user sync iframe', function () { + let syncs = spec.getUserSyncs({ + iframeEnabled: true + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('iframe'); + }); + }); +}); From 21f1275ad2c45dca98b9bcc4a870c94021908ca2 Mon Sep 17 00:00:00 2001 From: turktelssp <54801433+turktelssp@users.noreply.github.com> Date: Mon, 30 Sep 2019 12:09:15 +0300 Subject: [PATCH 1531/1594] Added Turk Telekom Bid Adapter (#4203) * Added Turk Telekom Bid Adapter * Fix md file for Turk Telekom Bid Adapter --- modules/turktelekomBidAdapter.js | 261 ++++++ modules/turktelekomBidAdapter.md | 49 ++ .../modules/turktelekomBidAdapter_spec.js | 749 ++++++++++++++++++ 3 files changed, 1059 insertions(+) create mode 100644 modules/turktelekomBidAdapter.js create mode 100644 modules/turktelekomBidAdapter.md create mode 100644 test/spec/modules/turktelekomBidAdapter_spec.js diff --git a/modules/turktelekomBidAdapter.js b/modules/turktelekomBidAdapter.js new file mode 100644 index 00000000000..f2fef1962d0 --- /dev/null +++ b/modules/turktelekomBidAdapter.js @@ -0,0 +1,261 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import { Renderer } from '../src/Renderer'; +import { VIDEO, BANNER } from '../src/mediaTypes'; + +const BIDDER_CODE = 'turktelekom'; +const ENDPOINT_URL = '//ssp.programattik.com/hb'; +const TIME_TO_LIVE = 360; +const ADAPTER_SYNC_URL = '//ssp.programattik.com/sync'; +const RENDERER_URL = '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; + +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', + noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', + emptyUids: 'Uids should be not empty', + emptySeatbid: 'Seatbid array from response has empty item', + emptyResponse: 'Response is empty', + 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 ], + /** + * 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 !!bid.params.uid; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests - an array of bids + * @param {bidderRequest} - bidder request object + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + const auids = []; + const bidsMap = {}; + const slotsMapByUid = {}; + const sizeMap = {}; + const bids = validBidRequests || []; + let priceType = 'net'; + let reqId; + + bids.forEach(bid => { + if (bid.params.priceType === 'gross') { + priceType = 'gross'; + } + reqId = bid.bidderRequestId; + const {params: {uid}, adUnitCode} = bid; + auids.push(uid); + const sizesId = utils.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 = { + pt: priceType, + auids: auids.join(','), + sizes: utils.getKeys(sizeMap).join(','), + r: reqId, + wrapperType: 'Prebid_js', + wrapperVersion: '$prebid.version$' + }; + + 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; + } + } + + return { + method: 'GET', + url: ENDPOINT_URL, + data: utils.parseQueryStringParameters(payload).replace(/\&$/, ''), + bidsMap: bidsMap, + }; + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param {*} bidRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidRequest, RendererConst = Renderer) { + serverResponse = serverResponse && serverResponse.body; + const bidResponses = []; + const bidsMap = bidRequest.bidsMap; + const priceType = bidRequest.data.pt; + + let errorMessage; + + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } + + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses, RendererConst); + }); + } + if (errorMessage) utils.logError(errorMessage); + return bidResponses; + }, + getUserSyncs: function(syncOptions) { + if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: ADAPTER_SYNC_URL + }]; + } + } +} + +function _getBidFromResponse(respItem) { + if (!respItem) { + utils.logError(LOG_ERROR_MESS.emptySeatbid); + } else if (!respItem.bid) { + utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem)); + } else if (!respItem.bid[0]) { + utils.logError(LOG_ERROR_MESS.noBid); + } + return respItem && respItem.bid && respItem.bid[0]; +} + +function _addBidResponse(serverBid, bidsMap, priceType, bidResponses, RendererConst) { + if (!serverBid) return; + let errorMessage; + if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); + else { + const awaitingBids = bidsMap[serverBid.auid]; + if (awaitingBids) { + const sizeId = `${serverBid.w}x${serverBid.h}`; + if (awaitingBids[sizeId]) { + const slot = awaitingBids[sizeId][0]; + + const bid = slot.bids.shift(); + const bidResponse = { + requestId: bid.bidId, // bid.bidderRequestId, + bidderCode: spec.code, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, // bid.bidId, + currency: 'TRY', + netRevenue: priceType !== 'gross', + ttl: TIME_TO_LIVE, + dealId: serverBid.dealid + }; + if (serverBid.content_type === 'video') { + 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, + url: RENDERER_URL + }, RendererConst); + } + } else { + bidResponse.ad = serverBid.adm; + bidResponse.mediaType = BANNER; + } + + 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 (!utils.getKeys(parent).length) { + delete bidsMap[uid]; + } + } + }); + } + } + } else { + errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; + } + } + if (errorMessage) { + utils.logError(errorMessage); + } +} + +function outstreamRender (bid) { + bid.renderer.push(() => { + window.ANOutstreamVideo.renderAd({ + targetId: bid.adUnitCode, + adResponse: bid.adResponse + }); + }); +} + +function createRenderer (bid, rendererParams, RendererConst) { + const rendererInst = RendererConst.install({ + id: rendererParams.id, + url: rendererParams.url, + loaded: false + }); + + try { + rendererInst.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } + + return rendererInst; +} + +registerBidder(spec); 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/test/spec/modules/turktelekomBidAdapter_spec.js b/test/spec/modules/turktelekomBidAdapter_spec.js new file mode 100644 index 00000000000..066d2724a97 --- /dev/null +++ b/test/spec/modules/turktelekomBidAdapter_spec.js @@ -0,0 +1,749 @@ +import { expect } from 'chai'; +import { spec } from 'modules/turktelekomBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('TurkTelekomAdapter', 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': 'turktelekom', + 'params': { + 'uid': '17' + }, + '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 false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'uid': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + 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: 'http://example.com' + } + }; + const referrer = bidderRequest.refererInfo.referer; + + let bidRequests = [ + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '18' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '18' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90], [300, 250]], + 'bidId': '3150ccb55da321', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '20' + }, + '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); + 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', '18'); + 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); + 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', '18,18,20'); + 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); + 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', '18,18,20'); + 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); + 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', '18,18,20'); + 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); + 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); + 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); + 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'); + }); + }); + + describe('interpretResponse', function () { + const responses = [ + {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 17, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 18, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 3
    ', 'auid': 17, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 19, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
    test content 5
    ', 'h': 250, 'w': 300}], 'seat': '1'}, + undefined, + {'bid': [], 'seat': '1'}, + {'seat': '1'}, + ]; + + it('should get correct bid response', function () { + const bidRequests = [ + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '659423fff799cb', + 'bidderRequestId': '5f2009617a7c0a', + 'auctionId': '1cbd2feafe5e8b', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '659423fff799cb', + 'cpm': 1.15, + 'creativeId': 17, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
    test content 1
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should get correct multi bid response', function () { + const bidRequests = [ + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71a5b', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '18' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dff80cc4ee346', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '5703af74d0472a', + 'bidderRequestId': '2c2bb1972df9a', + 'auctionId': '1fa09aee5c8c99', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '300bfeb0d71a5b', + 'cpm': 1.15, + 'creativeId': 17, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
    test content 1
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4dff80cc4ee346', + 'cpm': 0.5, + 'creativeId': 18, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'ad': '
    test content 2
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '5703af74d0472a', + 'cpm': 0.15, + 'creativeId': 17, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
    test content 3
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(0, 3)}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('handles wrong and nobid responses', function () { + const bidRequests = [ + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '19' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d7190gf', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '20' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '300bfeb0d71321', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '25' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '300bfeb0d7183bb', + 'bidderRequestId': '2c2bb1972d23af', + 'auctionId': '1fa09aee5c84d34', + } + ]; + const request = spec.buildRequests(bidRequests); + const result = spec.interpretResponse({'body': {'seatbid': responses.slice(3)}}, request); + expect(result.length).to.equal(0); + }); + + it('complicated case', function () { + const fullResponse = [ + {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 17, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 18, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 3
    ', 'auid': 17, 'h': 90, 'w': 728}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 4
    ', 'auid': 17, 'h': 600, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 5
    ', 'auid': 18, 'h': 600, 'w': 350}], 'seat': '1'}, + ]; + const bidRequests = [ + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '2164be6358b9', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '326bde7fbf69', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '18' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4e111f1b66e4', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '26d6f897b516', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '44' + }, + 'adUnitCode': 'adunit-code-2', + 'sizes': [[728, 90]], + 'bidId': '1751cd90161', + 'bidderRequestId': '106efe3247', + 'auctionId': '32a1f276cb87cb8', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '2164be6358b9', + 'cpm': 1.15, + 'creativeId': 17, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
    test content 1
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '4e111f1b66e4', + 'cpm': 0.5, + 'creativeId': 18, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'ad': '
    test content 2
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '26d6f897b516', + 'cpm': 0.15, + 'creativeId': 17, + 'dealId': undefined, + 'width': 728, + 'height': 90, + 'ad': '
    test content 3
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '326bde7fbf69', + 'cpm': 0.15, + 'creativeId': 17, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'ad': '
    test content 4
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('dublicate uids and sizes in one slot', function () { + const fullResponse = [ + {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 17, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 17, 'h': 250, 'w': 300}], 'seat': '1'}, + ]; + const bidRequests = [ + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '5126e301f4be', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '57b2ebe70e16', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '17' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '225fcd44b18c', + 'bidderRequestId': '171c5405a390', + 'auctionId': '35bcbc0f7e79c', + } + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '5126e301f4be', + 'cpm': 1.15, + 'creativeId': 17, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
    test content 1
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + }, + { + 'requestId': '57b2ebe70e16', + 'cpm': 0.5, + 'creativeId': 17, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '
    test content 2
    ', + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 360, + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + }); + + it('should get correct video bid response', function () { + const bidRequests = [ + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '25' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '57dfefb80eca', + 'bidderRequestId': '20394420a762a2', + 'auctionId': '140132d07b031', + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + } + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '26' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'e893c787c22dd', + 'bidderRequestId': '20394420a762a2', + 'auctionId': '140132d07b031', + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + } + } + ]; + const response = [ + {'bid': [{'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 25, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, + {'bid': [{'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 26, content_type: 'video'}], 'seat': '2'} + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': '57dfefb80eca', + 'cpm': 1.15, + 'creativeId': 25, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'video', + 'netRevenue': true, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + } + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': response}}, request); + expect(result).to.deep.equal(expectedResponse); + }); + + it('should have right renderer in the bid response', function () { + const spySetRenderer = sinon.spy(); + const stubRenderer = { + setRender: spySetRenderer + }; + const spyRendererInstall = sinon.spy(function() { return stubRenderer; }); + const stubRendererConst = { + install: spyRendererInstall + }; + const bidRequests = [ + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '25' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'e6e65553fc8', + 'bidderRequestId': '1380f393215dc7', + 'auctionId': '10b8d2f3c697e3', + 'mediaTypes': { + 'video': { + 'context': 'outstream' + } + } + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '26' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'c8fdcb3f269f', + 'bidderRequestId': '1380f393215dc7', + 'auctionId': '10b8d2f3c697e3' + }, + { + 'bidder': 'turktelekom', + 'params': { + 'uid': '27' + }, + 'adUnitCode': 'adunit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '1de036c37685', + 'bidderRequestId': '1380f393215dc7', + 'auctionId': '10b8d2f3c697e3', + 'renderer': {} + } + ]; + const response = [ + {'bid': [{'price': 1.15, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 25, content_type: 'video', w: 300, h: 600}], 'seat': '2'}, + {'bid': [{'price': 1.00, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 26, content_type: 'video', w: 300, h: 250}], 'seat': '2'}, + {'bid': [{'price': 1.20, 'adm': '\n<\/Ad>\n<\/VAST>', 'auid': 27, content_type: 'video', w: 300, h: 250}], 'seat': '2'} + ]; + const request = spec.buildRequests(bidRequests); + const expectedResponse = [ + { + 'requestId': 'e6e65553fc8', + 'cpm': 1.15, + 'creativeId': 25, + 'dealId': undefined, + 'width': 300, + 'height': 600, + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'video', + 'netRevenue': true, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + }, + 'renderer': stubRenderer + }, + { + 'requestId': 'c8fdcb3f269f', + 'cpm': 1.00, + 'creativeId': 26, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'video', + 'netRevenue': true, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + }, + 'renderer': stubRenderer + }, + { + 'requestId': '1de036c37685', + 'cpm': 1.20, + 'creativeId': 27, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'bidderCode': 'turktelekom', + 'currency': 'TRY', + 'mediaType': 'video', + 'netRevenue': true, + 'ttl': 360, + 'vastXml': '\n<\/Ad>\n<\/VAST>', + 'adResponse': { + 'content': '\n<\/Ad>\n<\/VAST>' + } + } + ]; + + const result = spec.interpretResponse({'body': {'seatbid': response}}, request, stubRendererConst); + + expect(spySetRenderer.calledTwice).to.equal(true); + expect(spySetRenderer.getCall(0).args[0]).to.be.a('function'); + expect(spySetRenderer.getCall(1).args[0]).to.be.a('function'); + + expect(spyRendererInstall.calledTwice).to.equal(true); + expect(spyRendererInstall.getCall(0).args[0]).to.deep.equal({ + id: 'e6e65553fc8', + url: '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', + loaded: false + }); + expect(spyRendererInstall.getCall(1).args[0]).to.deep.equal({ + id: 'c8fdcb3f269f', + url: '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js', + loaded: false + }); + + expect(result).to.deep.equal(expectedResponse); + }); +}); From 3ed4ba2d8c00f80f9c03f511e007410ebe81b7cc Mon Sep 17 00:00:00 2001 From: nkmt <45026101+strong-zero@users.noreply.github.com> Date: Mon, 30 Sep 2019 23:45:10 +0900 Subject: [PATCH 1532/1594] MicroAd: Use HTTPS in all requests (#4220) * Always use HTTPS endpoint in MicroAd * Update code * Fixed a broken test in MicroAd --- modules/microadBidAdapter.js | 2 +- test/spec/modules/microadBidAdapter_spec.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/microadBidAdapter.js b/modules/microadBidAdapter.js index 391be2c465b..0d4da3e72f7 100644 --- a/modules/microadBidAdapter.js +++ b/modules/microadBidAdapter.js @@ -4,7 +4,7 @@ import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'microad'; const ENDPOINT_URLS = { - 'production': '//s-rtb-pb.send.microad.jp/prebid', + 'production': 'https://s-rtb-pb.send.microad.jp/prebid', 'test': 'https://rtbtest.send.microad.jp/prebid' }; export let ENVIRONMENT = 'production'; diff --git a/test/spec/modules/microadBidAdapter_spec.js b/test/spec/modules/microadBidAdapter_spec.js index a6d1aa1d266..32bf15d53b9 100644 --- a/test/spec/modules/microadBidAdapter_spec.js +++ b/test/spec/modules/microadBidAdapter_spec.js @@ -258,6 +258,13 @@ describe('microadBidAdapter', () => { ); }); }); + + it('should always use the HTTPS endpoint https://s-rtb-pb.send.microad.jp/prebid even if it is served via HTTP', () => { + const requests = spec.buildRequests([bidRequestTemplate], bidderRequest); + requests.forEach(request => { + expect(request.url.lastIndexOf('https', 0) === 0).to.be.true; + }); + }); }); describe('interpretResponse', () => { From 3921f98ff803091c862a07a03dae5ec92be11253 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 30 Sep 2019 08:00:29 -0700 Subject: [PATCH 1533/1594] Schain: avoiding Object.values as it is breaking on IE11 (#4238) * added support for pubcommon, digitrust, id5id * added support for IdentityLink * changed the source for id5 * added unit test cases * changed source param for identityLink * avoiding use of Object.values --- modules/schain.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/schain.js b/modules/schain.js index a5797ba4b39..45850aabc3d 100644 --- a/modules/schain.js +++ b/modules/schain.js @@ -1,6 +1,6 @@ import {config} from '../src/config'; import {getGlobal} from '../src/prebidGlobal'; -import { isNumber, isStr, isArray, isPlainObject, hasOwn, logError, isInteger } from '../src/utils'; +import { isNumber, isStr, isArray, isPlainObject, hasOwn, logError, isInteger, _each } from '../src/utils'; // https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md @@ -14,6 +14,8 @@ const MODE = { RELAXED: 'relaxed', OFF: 'off' }; +const MODES = []; // an array of modes +_each(MODE, mode => MODES.push(mode)); // validate the supply chain object export function isSchainObjectValid(schainObject, returnOnError) { @@ -133,7 +135,7 @@ export function init(config) { getGlobal().requestBids.before(function(fn, reqBidsConfigObj) { let schainObject = config.getConfig('schain'); if (isValidSchainConfig(schainObject)) { - if (isStr(schainObject.validation) && Object.values(MODE).indexOf(schainObject.validation) != -1) { + if (isStr(schainObject.validation) && MODES.indexOf(schainObject.validation) != -1) { mode = schainObject.validation; } if (mode === MODE.OFF) { From 696f1e95b660bd7600ad6f95c777653bf28214b8 Mon Sep 17 00:00:00 2001 From: Mutasem Aldmour Date: Mon, 30 Sep 2019 20:54:34 +0300 Subject: [PATCH 1534/1594] 3952 delay auction for ids (#4115) * 3952 delay auction for user ids * 3952 add integration example * 3952 add tests * 3952 fix html example * add todos * 3952 continue auction if ids received * 3952 add tests for auction delay * increase test coverage * set config for test * remove todo * add a few more checks to tests * add comment, force tests to rerun --- integrationExamples/gpt/userId_example.html | 3 +- modules/userId/index.js | 69 ++++-- modules/userId/userId.md | 3 +- src/userSync.js | 3 +- test/spec/config_spec.js | 3 +- test/spec/modules/userId_spec.js | 260 +++++++++++++++++++- 6 files changed, 312 insertions(+), 29 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 9e1cd01f8fa..085b89e9f58 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -174,7 +174,8 @@ expires: 60 } }], - syncDelay: 5000 + syncDelay: 5000, + auctionDelay: 1000 } }); pbjs.addAdUnits(adUnits); diff --git a/modules/userId/index.js b/modules/userId/index.js index 03c81d1ff89..8302a7a89e3 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -109,6 +109,7 @@ const MODULE_NAME = 'User ID'; const COOKIE = 'cookie'; const LOCAL_STORAGE = 'html5'; const DEFAULT_SYNC_DELAY = 500; +const NO_AUCTION_DELAY = 0; /** @type {string[]} */ let validStorageTypes = []; @@ -131,6 +132,9 @@ let submoduleRegistry = []; /** @type {(number|undefined)} */ export let syncDelay; +/** @type {(number|undefined)} */ +export let auctionDelay; + /** @param {Submodule[]} submodules */ export function setSubmoduleRegistry(submodules) { submoduleRegistry = submodules; @@ -212,8 +216,10 @@ function hasGDPRConsent(consentData) { /** * @param {SubmoduleContainer[]} submodules + * @param {function} cb - callback for after processing is done. */ -function processSubmoduleCallbacks(submodules) { +function processSubmoduleCallbacks(submodules, cb) { + const done = cb ? utils.delayExecution(cb, submodules.length) : function() { }; submodules.forEach(function(submodule) { submodule.callback(function callbackCompleted(idObj) { // if valid, id data should be saved to cookie/html storage @@ -226,6 +232,7 @@ function processSubmoduleCallbacks(submodules) { } else { utils.logError(`${MODULE_NAME}: ${submodule.submodule.name} - request id responded with an empty value`); } + done(); }); // clear callback, this prop is used to test if all submodule callbacks are complete below @@ -273,7 +280,9 @@ function addIdDataToAdUnitBids(adUnits, submodules) { /** * This is a common function that will initalize subModules if not already done and it will also execute subModule callbacks */ -function initializeSubmodulesAndExecuteCallbacks() { +function initializeSubmodulesAndExecuteCallbacks(continueAuction) { + let delayed = false; + // initialize submodules only when undefined if (typeof initializedSubmodules === 'undefined') { initializedSubmodules = initSubmodules(submodules, gdprDataHandler.getConsentData()); @@ -282,22 +291,42 @@ function initializeSubmodulesAndExecuteCallbacks() { const submodulesWithCallbacks = initializedSubmodules.filter(item => utils.isFn(item.callback)); if (submodulesWithCallbacks.length) { - // 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); + 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`); + processSubmoduleCallbacks(submodulesWithCallbacks, continueCallback); + + setTimeout(continueCallback, auctionDelay); + } else { + // 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); + } + }); + } } } } + + if (continueAuction && !delayed) { + continueAuction(); + } } /** @@ -311,11 +340,12 @@ function initializeSubmodulesAndExecuteCallbacks() { */ export function requestBidsHook(fn, reqBidsConfigObj) { // initialize submodules only when undefined - initializeSubmodulesAndExecuteCallbacks(); - // pass available user id data to bid adapters - addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || getGlobal().adUnits, initializedSubmodules); - // calling fn allows prebid to continue processing - return fn.call(this, reqBidsConfigObj); + initializeSubmodulesAndExecuteCallbacks(function() { + // pass available user id data to bid adapters + addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || getGlobal().adUnits, initializedSubmodules); + // calling fn allows prebid to continue processing + fn.call(this, reqBidsConfigObj); + }); } /** @@ -502,6 +532,7 @@ export function init(config) { if (userSync && userSync.userIds) { configRegistry = userSync.userIds; syncDelay = utils.isNumber(userSync.syncDelay) ? userSync.syncDelay : DEFAULT_SYNC_DELAY; + auctionDelay = utils.isNumber(userSync.auctionDelay) ? userSync.auctionDelay : NO_AUCTION_DELAY; updateSubmodules(); } }); diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 623aeaa160e..d3dcfa67443 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -44,7 +44,8 @@ pbjs.setConfig({ expires: 60 } }], - syncDelay: 5000 + syncDelay: 5000, + auctionDelay: 1000 } }); ``` diff --git a/src/userSync.js b/src/userSync.js index e2bd4e3f04a..aaa79f6a42f 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -8,7 +8,8 @@ config.setDefaults({ syncEnabled: true, pixelEnabled: true, syncsPerBidder: 5, - syncDelay: 3000 + syncDelay: 3000, + auctionDelay: 0 } }); diff --git a/test/spec/config_spec.js b/test/spec/config_spec.js index 196e167420a..c0f4f6bab89 100644 --- a/test/spec/config_spec.js +++ b/test/spec/config_spec.js @@ -77,7 +77,8 @@ describe('config API', function () { syncEnabled: true, pixelEnabled: true, syncsPerBidder: 5, - syncDelay: 3000 + syncDelay: 3000, + auctionDelay: 0 }; setDefaults({'userSync': DEFAULT_USERSYNC}); expect(getConfig('userSync')).to.eql(DEFAULT_USERSYNC); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 5bbd21a3c12..e1740dede85 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -1,6 +1,15 @@ -import {attachIdSystem, init, requestBidsHook, setSubmoduleRegistry, syncDelay} from 'modules/userId/index.js'; +import { + attachIdSystem, + auctionDelay, + init, + requestBidsHook, + setSubmoduleRegistry, + syncDelay +} from 'modules/userId/index.js'; import {config} from 'src/config'; import * as utils from 'src/utils'; +import events from 'src/events'; +import CONSTANTS from 'src/constants.json'; import {unifiedIdSubmodule} from 'modules/userId/unifiedIdSystem'; import {pubCommonIdSubmodule} from 'modules/userId/pubCommonIdSystem'; import {id5IdSubmodule} from 'modules/id5IdSystem'; @@ -8,8 +17,6 @@ import {identityLinkSubmodule} from 'modules/identityLinkIdSystem'; let assert = require('chai').assert; let expect = require('chai').expect; -let events = require('src/events'); -let constants = require('src/constants.json'); const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; describe('User ID', function() { @@ -335,6 +342,247 @@ describe('User ID', function() { }); expect(syncDelay).to.equal(99); }); + + it('config auctionDelay updates module correctly', function () { + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); + init(config); + config.setConfig({ + usersync: { + auctionDelay: 100, + userIds: [{ + name: 'unifiedId', + storage: { name: 'unifiedid', type: 'cookie' } + }] + } + }); + expect(auctionDelay).to.equal(100); + }); + + it('config auctionDelay defaults to 0 if not a number', function () { + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule]); + init(config); + config.setConfig({ + usersync: { + auctionDelay: '', + userIds: [{ + name: 'unifiedId', + storage: { name: 'unifiedid', type: 'cookie' } + }] + } + }); + expect(auctionDelay).to.equal(0); + }); + }); + + describe('auction and user sync delays', function() { + let sandbox; + let adUnits; + let mockIdCallback; + let auctionSpy; + + before(function() { + sandbox = sinon.createSandbox(); + sandbox.stub(global, 'setTimeout'); + sandbox.stub(events, 'on'); + }); + + beforeEach(function() { + // remove cookie + utils.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); + + adUnits = [getAdUnitMock()]; + + auctionSpy = sandbox.spy(); + mockIdCallback = sandbox.stub(); + const mockIdSystem = { + name: 'mockId', + decode: function(value) { + return { + 'mid': value['MOCKID'] + }; + }, + getId: function() { + const storedId = utils.getCookie('MOCKID'); + if (storedId) { + return {id: {'MOCKID': storedId}}; + } + return {callback: mockIdCallback}; + } + }; + + init(config); + + attachIdSystem(mockIdSystem, true); + }); + + afterEach(function () { + $$PREBID_GLOBAL$$.requestBids.removeAll(); + config.resetConfig(); + sandbox.resetHistory(); + }); + + after(function() { + sandbox.restore(); + }); + + it('delays auction if auctionDelay is set, timing out at auction delay', function() { + config.setConfig({ + usersync: { + auctionDelay: 33, + syncDelay: 77, + userIds: [{ + name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + }] + } + }); + + requestBidsHook(auctionSpy, {adUnits}); + + // check auction was delayed + global.setTimeout.calledOnce.should.equal(true); + global.setTimeout.calledWith(sinon.match.func, 33); + auctionSpy.calledOnce.should.equal(false); + + // check ids were fetched + mockIdCallback.calledOnce.should.equal(true); + + // callback to continue auction if timed out + global.setTimeout.callArg(0); + auctionSpy.calledOnce.should.equal(true); + + // 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(done) { + config.setConfig({ + usersync: { + auctionDelay: 33, + syncDelay: 77, + userIds: [{ + name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + }] + } + }); + + requestBidsHook(auctionSpy, {adUnits}); + + // check auction was delayed + global.setTimeout.calledOnce.should.equal(true); + global.setTimeout.calledWith(sinon.match.func, 33); + auctionSpy.calledOnce.should.equal(false); + + // check ids were fetched + mockIdCallback.calledOnce.should.equal(true); + + // if ids returned, should continue auction + mockIdCallback.callArgWith(0, {'MOCKID': '1234'}); + auctionSpy.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'); + }); + 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() { + config.setConfig({ + usersync: { + syncDelay: 77, + userIds: [{ + name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + }] + } + }); + + // check config has been set correctly + expect(auctionDelay).to.equal(0); + expect(syncDelay).to.equal(77); + + 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() { + config.setConfig({ + usersync: { + syncDelay: 0, + userIds: [{ + name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + }] + } + }); + + expect(syncDelay).to.equal(0); + + 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() { + utils.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); + + config.setConfig({ + usersync: { + auctionDelay: 33, + syncDelay: 77, + userIds: [{ + name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + }] + } + }); + + requestBidsHook(auctionSpy, {adUnits}); + + 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); + }); }); describe('Request bids hook appends userId to bid objs in adapters', function() { @@ -673,7 +921,7 @@ describe('User ID', function() { requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); expect(utils.triggerPixel.called).to.be.false; - events.emit(constants.EVENTS.AUCTION_END, {}); + events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); expect(utils.triggerPixel.getCall(0).args[0]).to.include('/any/pubcid/url'); }); @@ -689,7 +937,7 @@ describe('User ID', function() { requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); expect(requests).to.be.empty; - events.emit(constants.EVENTS.AUCTION_END, {}); + events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); expect(requests[0].url).to.equal('/any/unifiedid/url'); }); @@ -705,7 +953,7 @@ describe('User ID', function() { requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); expect(requests).to.be.empty; - events.emit(constants.EVENTS.AUCTION_END, {}); + events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); expect(requests[0].url).to.equal('//match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json'); }); }); From 4691c7c5a726d77649e3dbca86405e7e519beb17 Mon Sep 17 00:00:00 2001 From: r-schweitzer <50628828+r-schweitzer@users.noreply.github.com> Date: Tue, 1 Oct 2019 20:21:18 +0200 Subject: [PATCH 1535/1594] Feature: adUnitBidLimit (#3906) * added new feature to config to limit bids when sendallbids is enabled * cleaned up code. removed extra spaces etc * removed trailing spaces in config * remove .flat() and replaced with spread operator * removed flat function and instead pushing using spread operator * updated to use sendBidsControl instead * updated targeting_spec to test bidLimit * removed trailing spaces from targeting_spec --- src/targeting.js | 17 ++++++--- test/spec/unit/core/targeting_spec.js | 52 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index 33108f9a6a4..e2378e3b65c 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -31,14 +31,23 @@ export let filters = { // If two bids are found for same adUnitCode, we will use the highest one to take part in auction // This can happen in case of concurrent auctions -export function getHighestCpmBidsFromBidPool(bidsReceived, highestCpmCallback) { +// If adUnitBidLimit is set above 0 return top N number of bids +export function getHighestCpmBidsFromBidPool(bidsReceived, highestCpmCallback, adUnitBidLimit = 0) { const bids = []; // bucket by adUnitcode let buckets = groupBy(bidsReceived, 'adUnitCode'); // filter top bid for each bucket by bidder Object.keys(buckets).forEach(bucketKey => { + let bucketBids = []; let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); - Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(highestCpmCallback))); + Object.keys(bidsByBidder).forEach(key => bucketBids.push(bidsByBidder[key].reduce(highestCpmCallback))); + // if adUnitBidLimit is set, pass top N number bids + if (adUnitBidLimit > 0) { + bucketBids.sort((a, b) => b.cpm - a.cpm); + bids.push(...bucketBids.slice(0, adUnitBidLimit)); + } else { + bids.push(...bucketBids); + } }); return bids; } @@ -518,8 +527,8 @@ export function newTargeting(auctionManager) { */ function getBidLandscapeTargeting(adUnitCodes, bidsReceived) { const standardKeys = TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); - - const bids = getHighestCpmBidsFromBidPool(bidsReceived, getHighestCpm); + const adUnitBidLimit = config.getConfig('sendBidsControl.bidLimit'); + const bids = getHighestCpmBidsFromBidPool(bidsReceived, getHighestCpm, adUnitBidLimit); // populate targeting keys for the remaining bids return bids.map(bid => { diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index b165a2a21fb..ad94ebccfb2 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -331,6 +331,58 @@ describe('targeting tests', function () { expect(logErrorStub.calledOnce).to.be.true; }); + describe('when bidLimit is present in setConfig', function () { + let bid4; + + beforeEach(function() { + bid4 = utils.deepClone(bid1); + bid4.adserverTargeting['hb_bidder'] = bid4.bidder = bid4.bidderCode = 'appnexus'; + bid4.cpm = 2.25; + enableSendAllBids = true; + + bidsReceived.push(bid4); + }); + + it('selects the top n number of bids when enableSendAllBids is true and and bitLimit is set', function () { + config.setConfig({ + sendBidsControl: { + bidLimit: 1 + } + }); + + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + let limitedBids = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf(CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_') != -1) + + expect(limitedBids.length).to.equal(1); + }); + + it('sends all bids when enableSendAllBids is true and and bitLimit is above total number of bids received', function () { + config.setConfig({ + sendBidsControl: { + bidLimit: 50 + } + }); + + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + let limitedBids = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf(CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_') != -1) + + expect(limitedBids.length).to.equal(2); + }); + + it('Sends all bids when enableSendAllBids is true and and bitLimit is set to 0', function () { + config.setConfig({ + sendBidsControl: { + bidLimit: 0 + } + }); + + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + let limitedBids = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf(CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_') != -1) + + expect(limitedBids.length).to.equal(2); + }); + }); + describe('targetingControls.alwaysIncludeDeals', function () { let bid4; From fdc8e7848c4d24b99c08fcc0f9aae58089264da1 Mon Sep 17 00:00:00 2001 From: "Isaac A. Dettman" Date: Wed, 2 Oct 2019 09:33:24 -0700 Subject: [PATCH 1536/1594] Update Rubicon Adapter netRevenue default (#4242) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * reverted error merge * update changed default value of netRevenue to true --- modules/rubiconBidAdapter.js | 2 +- test/spec/modules/rubiconBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index a1cdfdf8fea..492e283596c 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -484,7 +484,7 @@ export const spec = { cpm: bid.price || 0, bidderCode: seatbid.seat, ttl: 300, - netRevenue: config.getConfig('rubicon.netRevenue') || false, + netRevenue: config.getConfig('rubicon.netRevenue') || true, 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'), }; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 8d65e1e97b4..d31b83fd923 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -2039,7 +2039,7 @@ describe('the rubicon adapter', function () { expect(bids[0].creativeId).to.equal('4259970'); expect(bids[0].cpm).to.equal(2); expect(bids[0].ttl).to.equal(300); - expect(bids[0].netRevenue).to.equal(false); + expect(bids[0].netRevenue).to.equal(true); expect(bids[0].adserverTargeting).to.deep.equal({hb_uuid: '0c498f63-5111-4bed-98e2-9be7cb932a64'}); expect(bids[0].mediaType).to.equal('video'); expect(bids[0].bidderCode).to.equal('rubicon'); From 88e38251c87adb9c83e3425be018f5ed0ba3dff3 Mon Sep 17 00:00:00 2001 From: Adasta Media <55529969+Adasta2019@users.noreply.github.com> Date: Thu, 3 Oct 2019 17:03:33 +0200 Subject: [PATCH 1537/1594] Removed AdastaMadia from alias (#4255) --- modules/gamoshiBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 6d243f155bf..ec146b77c70 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -42,7 +42,7 @@ export const helper = { export const spec = { code: 'gamoshi', - aliases: ['gambid', 'cleanmedia', 'viewdeos', 'adastaMedia', '9MediaOnline'], + aliases: ['gambid', 'cleanmedia', 'viewdeos', '9MediaOnline'], supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { From fbd6a0bf870cdc550abe29236f9a1017299882f5 Mon Sep 17 00:00:00 2001 From: Adasta Media <55529969+Adasta2019@users.noreply.github.com> Date: Thu, 3 Oct 2019 17:05:29 +0200 Subject: [PATCH 1538/1594] Update appnexusBidAdapter.js (#4251) --- modules/appnexusBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 5fe2add5ba8..f43c3c542b5 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -41,7 +41,7 @@ const VIEWABILITY_FILE_NAME = 'trk.js'; export const spec = { code: BIDDER_CODE, - aliases: ['appnexusAst', 'brealtime', 'emxdigital', 'pagescience', 'defymedia', 'gourmetads', 'matomy', 'featureforward', 'oftmedia', 'districtm'], + aliases: ['appnexusAst', 'brealtime', 'emxdigital', 'pagescience', 'defymedia', 'gourmetads', 'matomy', 'featureforward', 'oftmedia', 'districtm', 'adasta'], supportedMediaTypes: [BANNER, VIDEO, NATIVE], /** From 976718f7636a93dc732fee9f903450d9f2d53324 Mon Sep 17 00:00:00 2001 From: mamatic <52153441+mamatic@users.noreply.github.com> Date: Thu, 3 Oct 2019 19:36:06 +0200 Subject: [PATCH 1539/1594] IdentityLink - change expiration time to 30 days (#4239) --- integrationExamples/gpt/userId_example.html | 2 +- modules/userId/userId.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 085b89e9f58..09e9e4147fc 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -171,7 +171,7 @@ storage: { type: 'cookie', name: 'idl_env', - expires: 60 + expires: 30 } }], syncDelay: 5000, diff --git a/modules/userId/userId.md b/modules/userId/userId.md index d3dcfa67443..9f71d59e5e1 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -41,7 +41,7 @@ pbjs.setConfig({ storage: { type: 'cookie', name: 'idl_env', - expires: 60 + expires: 30 } }], syncDelay: 5000, @@ -80,7 +80,7 @@ pbjs.setConfig({ storage: { type: 'html5', name: 'idl_env', - expires: 60 + expires: 30 } }], syncDelay: 5000 From 1aecd87bea73808b682d0761c61ad04d61504cd3 Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Thu, 3 Oct 2019 13:44:01 -0400 Subject: [PATCH 1540/1594] Add coppa support for AppNexus adapter (#4253) * Add coppa support for AppNexus adapter * test name --- modules/appnexusBidAdapter.js | 6 ++++-- test/spec/modules/appnexusBidAdapter_spec.js | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index f43c3c542b5..0adf0a9bb70 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -63,9 +63,11 @@ export const spec = { buildRequests: function(bidRequests, bidderRequest) { const tags = bidRequests.map(bidToTag); const userObjBid = find(bidRequests, hasUserInfo); - let userObj; + let userObj = {}; + if (config.getConfig('coppa') === true) { + userObj = {'coppa': true}; + } if (userObjBid) { - userObj = {}; Object.keys(userObjBid.params.user) .filter(param => includes(USER_PARAMS, param)) .forEach(param => userObj[param] = userObjBid.params.user[param]); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index e35560ac1d0..762833f29b8 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -705,6 +705,20 @@ describe('AppNexusAdapter', function () { ] }); }); + + 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(); + }); }) describe('interpretResponse', function () { From 4ac35826e432579f5d448cbdbe7f1a796af1fa1f Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 7 Oct 2019 14:51:32 -0400 Subject: [PATCH 1541/1594] add new longform e2e tests (#4206) --- .../longform/basic_w_bidderSettings.html | 145 +++++++++++++++++ .../longform/basic_w_priceGran.html | 153 ++++++++++++++++++ .../longform/basic_w_bidderSettings.spec.js | 68 ++++++++ .../e2e/longform/basic_w_priceGran.spec.js | 68 ++++++++ 4 files changed, 434 insertions(+) create mode 100644 integrationExamples/longform/basic_w_bidderSettings.html create mode 100644 integrationExamples/longform/basic_w_priceGran.html create mode 100644 test/spec/e2e/longform/basic_w_bidderSettings.spec.js create mode 100644 test/spec/e2e/longform/basic_w_priceGran.spec.js diff --git a/integrationExamples/longform/basic_w_bidderSettings.html b/integrationExamples/longform/basic_w_bidderSettings.html new file mode 100644 index 00000000000..4ccb01fbd6e --- /dev/null +++ b/integrationExamples/longform/basic_w_bidderSettings.html @@ -0,0 +1,145 @@ + + + + + Prebid Freewheel Integration Demo + + + + + + + + + + + + + + + + + + +

    Prebid Freewheel Test Page

    +

    requireExactDuration = false

    +
    +
    + +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/integrationExamples/longform/basic_w_priceGran.html b/integrationExamples/longform/basic_w_priceGran.html new file mode 100644 index 00000000000..cda302b0079 --- /dev/null +++ b/integrationExamples/longform/basic_w_priceGran.html @@ -0,0 +1,153 @@ + + + + + Prebid Freewheel Integration Demo + + + + + + + + + + + + + + + + + + +

    Prebid Freewheel Test Page

    +

    requireExactDuration = false

    +
    +
    + +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +

    + +

    +
    +
    +
    + // bids +
    +
    +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/test/spec/e2e/longform/basic_w_bidderSettings.spec.js b/test/spec/e2e/longform/basic_w_bidderSettings.spec.js new file mode 100644 index 00000000000..06413fb809a --- /dev/null +++ b/test/spec/e2e/longform/basic_w_bidderSettings.spec.js @@ -0,0 +1,68 @@ +const includes = require('core-js/library/fn/array/includes'); +const expect = require('chai').expect; +const testServer = require('../../../helpers/testing-utils'); + +const host = testServer.host; +const protocol = testServer.protocol; + +const validDurations = ['15s', '30s']; +const validCats = ['Food', 'Retail Stores/Chains', 'Pet Food/Supplies', 'Travel/Hotels/Airlines', 'Automotive', 'Health Care Services']; +const validCpms = ['14.00', '13.00', '12.00', '9.00']; +const customKeyRegex = /\d{2}\.\d{2}_\d{1,3}_\d{2}s/; +const uuidRegex = /(\d|\w){8}-((\d|\w){4}-){3}(\d|\w){12}/; + +describe('longform ads not using requireExactDuration field', function() { + this.retries(3); + it('process the bids successfully', function() { + browser + .url(protocol + '://' + host + ':9999/integrationExamples/longform/basic_w_bidderSettings.html?pbjs_debug=true') + .pause(10000); + + const loadPrebidBtnXpath = '//*[@id="loadPrebidRequestBtn"]'; + browser.waitForExist(loadPrebidBtnXpath); + $(loadPrebidBtnXpath).click(); + browser.pause(3000); + + const listOfCpmsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[2]'; + const listOfCategoriesXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[3]'; + const listOfDurationsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[4]'; + + browser.waitForExist(listOfCpmsXpath); + + let listOfCpms = $$(listOfCpmsXpath); + let listOfCats = $$(listOfCategoriesXpath); + let listOfDuras = $$(listOfDurationsXpath); + + expect(listOfCpms.length).to.equal(listOfCats.length).and.to.equal(listOfDuras.length); + for (let i = 0; i < listOfCpms.length; i++) { + let cpm = listOfCpms[i].getText(); + let cat = listOfCats[i].getText(); + let dura = listOfDuras[i].getText(); + expect(includes(validCpms, cpm), `Could not find CPM ${cpm} in accepted list`).to.equal(true); + expect(includes(validCats, cat), `Could not find Category ${cat} in accepted list`).to.equal(true); + expect(includes(validDurations, dura), `Could not find Duration ${dura} in accepted list`).to.equal(true); + } + }); + + it('formats the targeting keys properly', function () { + const listOfKeyElementsXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[1]'; + const listOfKeyValuesXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[2]'; + browser.waitForExist(listOfKeyElementsXpath); + browser.waitForExist(listOfKeyValuesXpath); + + let listOfKeyElements = $$(listOfKeyElementsXpath); + let listOfKeyValues = $$(listOfKeyValuesXpath); + + let firstKey = listOfKeyElements[0].getText(); + expect(firstKey).to.equal('hb_pb_cat_dur'); + + let firstKeyValue = listOfKeyValues[0].getText(); + expect(firstKeyValue).match(customKeyRegex); + + let lastKey = listOfKeyElements[listOfKeyElements.length - 1].getText(); + expect(lastKey).to.equal('hb_cache_id'); + + let lastKeyValue = listOfKeyValues[listOfKeyValues.length - 1].getText(); + expect(lastKeyValue).to.match(uuidRegex); + }); +}) diff --git a/test/spec/e2e/longform/basic_w_priceGran.spec.js b/test/spec/e2e/longform/basic_w_priceGran.spec.js new file mode 100644 index 00000000000..696b7fa3359 --- /dev/null +++ b/test/spec/e2e/longform/basic_w_priceGran.spec.js @@ -0,0 +1,68 @@ +const includes = require('core-js/library/fn/array/includes'); +const expect = require('chai').expect; +const testServer = require('../../../helpers/testing-utils'); + +const host = testServer.host; +const protocol = testServer.protocol; + +const validDurations = ['15s', '30s']; +const validCats = ['Food', 'Retail Stores/Chains', 'Pet Food/Supplies', 'Travel/Hotels/Airlines', 'Automotive', 'Health Care Services']; +const validCpms = ['15.00', '14.00', '13.00', '10.00']; +const customKeyRegex = /\d{2}\.\d{2}_\d{1,3}_\d{2}s/; +const uuidRegex = /(\d|\w){8}-((\d|\w){4}-){3}(\d|\w){12}/; + +describe('longform ads not using requireExactDuration field', function() { + this.retries(3); + it('process the bids successfully', function() { + browser + .url(protocol + '://' + host + ':9999/integrationExamples/longform/basic_w_priceGran.html?pbjs_debug=true') + .pause(10000); + + const loadPrebidBtnXpath = '//*[@id="loadPrebidRequestBtn"]'; + browser.waitForExist(loadPrebidBtnXpath); + $(loadPrebidBtnXpath).click(); + browser.pause(3000); + + const listOfCpmsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[2]'; + const listOfCategoriesXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[3]'; + const listOfDurationsXpath = '/html/body/div[1]/div/div/div/div[1]/div[2]/div/table/tbody/tr/td[4]'; + + browser.waitForExist(listOfCpmsXpath); + + let listOfCpms = $$(listOfCpmsXpath); + let listOfCats = $$(listOfCategoriesXpath); + let listOfDuras = $$(listOfDurationsXpath); + + expect(listOfCpms.length).to.equal(listOfCats.length).and.to.equal(listOfDuras.length); + for (let i = 0; i < listOfCpms.length; i++) { + let cpm = listOfCpms[i].getText(); + let cat = listOfCats[i].getText(); + let dura = listOfDuras[i].getText(); + expect(includes(validCpms, cpm), `Could not find CPM ${cpm} in accepted list`).to.equal(true); + expect(includes(validCats, cat), `Could not find Category ${cat} in accepted list`).to.equal(true); + expect(includes(validDurations, dura), `Could not find Duration ${dura} in accepted list`).to.equal(true); + } + }); + + it('formats the targeting keys properly', function () { + const listOfKeyElementsXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[1]'; + const listOfKeyValuesXpath = '/html/body/div[1]/div/div/div/div[2]/div[2]/div/table/tbody/tr/td[2]'; + browser.waitForExist(listOfKeyElementsXpath); + browser.waitForExist(listOfKeyValuesXpath); + + let listOfKeyElements = $$(listOfKeyElementsXpath); + let listOfKeyValues = $$(listOfKeyValuesXpath); + + let firstKey = listOfKeyElements[0].getText(); + expect(firstKey).to.equal('hb_pb_cat_dur'); + + let firstKeyValue = listOfKeyValues[0].getText(); + expect(firstKeyValue).match(customKeyRegex); + + let lastKey = listOfKeyElements[listOfKeyElements.length - 1].getText(); + expect(lastKey).to.equal('hb_cache_id'); + + let lastKeyValue = listOfKeyValues[listOfKeyValues.length - 1].getText(); + expect(lastKeyValue).to.match(uuidRegex); + }); +}) From 214efe8e11a9a19d5f01159ebf5e220f25300928 Mon Sep 17 00:00:00 2001 From: Konduit <55142865+konduit-dev@users.noreply.github.com> Date: Mon, 7 Oct 2019 21:53:04 +0300 Subject: [PATCH 1542/1594] Konduit module (#4184) * Adding Konduit module * Removed superfluous arguments passed to obtainVastUrl function * Removed superfluous arguments passed to obtainVastUrl function. * Build trigger (empty commit) * Module documentation updated according to the comments * Logic in obtainVastUrl function updated according to the review comment. * Removed hook, enabled eslint --- modules/konduitWrapper.js | 89 ++++++++++++++++ modules/konduitWrapper.md | 73 +++++++++++++ test/spec/modules/konduitWrapper_spec.js | 127 +++++++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 modules/konduitWrapper.js create mode 100644 modules/konduitWrapper.md create mode 100644 test/spec/modules/konduitWrapper_spec.js diff --git a/modules/konduitWrapper.js b/modules/konduitWrapper.js new file mode 100644 index 00000000000..c155720c606 --- /dev/null +++ b/modules/konduitWrapper.js @@ -0,0 +1,89 @@ +import { registerVideoSupport } from '../src/adServerManager'; +import { targeting } from '../src/targeting'; +import { format as buildUrl } from '../src/url'; +import * as utils from '../src/utils'; +import { config } from '../src/config'; + +const MODULE_NAME = 'Konduit'; + +function addLogLabel(args) { + args = [].slice.call(args); + args.unshift(`${MODULE_NAME}: `); + return args; +} + +export function logInfo() { + utils.logInfo(...addLogLabel(arguments)); +} + +export function logError() { + utils.logError(...addLogLabel(arguments)); +} + +export function buildVastUrl(options) { + if (!options.params || !options.params.konduit_id) { + logError(`'konduit_id' parameter is required for $$PREBID_GLOBAL$$.adServers.konduit.buildVastUrl function`); + + return null; + } + + const bid = options.bid || targeting.getWinningBids()[0]; + + if (!bid) { + logError('Bid is not provided or not found'); + + return null; + } + + logInfo('The following bid will be wrapped: ', bid); + + const queryParams = {}; + + const vastUrl = obtainVastUrl(bid); + + if (vastUrl) { + queryParams.konduit_id = options.params.konduit_id; + queryParams.konduit_header_bidding = 1; + queryParams.konduit_url = vastUrl; + } else { + logError('No VAST url found in the bid'); + } + + let resultingUrl = null; + + if (queryParams.konduit_url) { + resultingUrl = buildUrl({ + protocol: 'https', + host: 'p.konduit.me', + pathname: '/api/vastProxy', + search: queryParams + }); + + logInfo(`Konduit wrapped VAST url: ${resultingUrl}`); + } + + return resultingUrl; +} + +function obtainVastUrl(bid) { + const vastUrl = bid && bid.vastUrl; + + if (vastUrl) { + logInfo(`VAST url found in the bid - ${vastUrl}`); + + return encodeURIComponent(vastUrl); + } + + const cacheUrl = config.getConfig('cache.url'); + if (cacheUrl) { + const composedCacheUrl = `${cacheUrl}?uuid=${bid.videoCacheKey}`; + + logInfo(`VAST url is taken from cache.url: ${composedCacheUrl}`); + + return encodeURIComponent(composedCacheUrl); + } +} + +registerVideoSupport('konduit', { + buildVastUrl: buildVastUrl, +}); diff --git a/modules/konduitWrapper.md b/modules/konduitWrapper.md new file mode 100644 index 00000000000..adbb50487da --- /dev/null +++ b/modules/konduitWrapper.md @@ -0,0 +1,73 @@ +## Konduit video tags wrapper + +Konduit Wrapper is a prebid module to generate Konduit wrapped VAST tag URLs for a provided bid or a winning bid. + + +### Setup + +``` +var videoAdUnit = [{ + code: 'videoAd', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'appnexus', + params: { + placementId: 13232361, + video: { + skippable: true, + playback_method: ['auto_play_sound_off'] + } + } + }] +}]; + +pbjs.que.push(function(){ + pbjs.addAdUnits(videoAdUnit); + pbjs.requestBids({ + timeout : 700, + bidsBackHandler : function(bids) { + var winnerBid = pbjs.getHighestCpmBids('videoAd')[0]; + var vastTagUrl = pbjs.adServers.konduit.buildVastUrl({ + bid: winnerBid, // just in case if you want to pass your bid + params: { + konduit_id: 'your_konduit_id' + } + }); + + invokeVideoPlayer(vastTagUrl); + } + }); +}); + +function invokeVideoPlayer(vastTagUrl) { + videojs("video_player_id").ready(function() { + this.vastClient({ + adTagUrl: vastTagUrl, + playAdAlways: true, + verbosity: 4, + autoplay: true + }); + + this.play(); + }); + } +``` + +Function parameters: +* `bid` - prebid object with VAST url that should be wrapped (if not passed first winning bid from `auctionManager.getWinningBids()` is used) +* `konduit_id` - your personal unique Konduit identifier (required) + +The function returns a Konduit wrapped VAST url if valid parameters are passed in. If some of the parameters are not passed or are invalid the function returns 'null' along with related error logs providing more details. + + +### Building Prebid with the Konduit wrapper function + +Your Prebid build must include the **konduitWrapper** module. Follow the build instructions for Prebid as explained in the top level README.md file of the Prebid source tree. + +ex: $ gulp build --modules=konduitWrapper + diff --git a/test/spec/modules/konduitWrapper_spec.js b/test/spec/modules/konduitWrapper_spec.js new file mode 100644 index 00000000000..bcc65ddd683 --- /dev/null +++ b/test/spec/modules/konduitWrapper_spec.js @@ -0,0 +1,127 @@ +import { expect } from 'chai'; + +import parse from 'url-parse'; +import { buildVastUrl } from 'modules/konduitWrapper'; +import { parseQS } from 'src/url'; +import { config } from 'src/config'; + +describe('The Konduit vast wrapper module', function () { + it('should make a wrapped request url when `bid` passed', function () { + const bid = createBid(10, 'video1', 15, '10.00_15s', '123', '395'); + + const url = parse(buildVastUrl({ + bid, + params: { 'konduit_id': 'testId' }, + })); + + expect(url.protocol).to.equal('https:'); + expect(url.host).to.equal('p.konduit.me'); + + const queryParams = parseQS(url.query); + expect(queryParams).to.have.property('konduit_url', encodeURIComponent('http://some-vast-url.com')); + expect(queryParams).to.have.property('konduit_header_bidding', '1'); + expect(queryParams).to.have.property('konduit_id', 'testId'); + }); + + it('should return null when no `konduit_id` (required param) passed', function () { + const bid = createBid(10, 'video1', 15, '10.00_15s', '123', '395'); + + const url = buildVastUrl({ bid }); + + expect(url).to.equal(null); + }); + + it('should return null when either bid or adUnit is not passed', function () { + const url = buildVastUrl({ params: { 'konduit_id': 'testId' } }); + + expect(url).to.equal(null); + }); + + it('should return null when bid does not contain vastUrl', function () { + const bid = createBid(10, 'video1', 15, '10.00_15s', '123', '395'); + + delete bid.vastUrl; + + const url = buildVastUrl({ + bid, + params: { 'konduit_id': 'testId' }, + }); + + expect(url).to.equal(null); + }); + + it('should return wrapped vastUrl based on cached url in params', function () { + config.setConfig({ cache: { url: 'https://cached.url.com' } }); + const bid = createBid(10, 'video1', 15, '10.00_15s', '123', '395'); + + delete bid.vastUrl; + + const expectedUrl = encodeURIComponent(`https://cached.url.com?uuid=${bid.videoCacheKey}`); + + const url = parse(buildVastUrl({ + bid, + params: { 'konduit_id': 'testId' }, + })); + const queryParams = parseQS(url.query); + + expect(queryParams).to.have.property('konduit_url', expectedUrl); + + config.resetConfig(); + }); +}); + +function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, label) { + return { + 'bidderCode': 'appnexus', + 'width': 640, + 'height': 360, + 'statusMessage': 'Bid available', + 'adId': '28f24ced14586c', + 'mediaType': 'video', + 'source': 'client', + 'requestId': '28f24ced14586c', + 'cpm': cpm, + 'creativeId': 97517771, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 3600, + 'adUnitCode': adUnitCode, + 'video': { + 'context': 'adpod', + 'durationBucket': durationBucket + }, + 'appnexus': { + 'buyerMemberId': 9325 + }, + 'vastUrl': 'http://some-vast-url.com', + 'vastImpUrl': 'http://some-vast-imp-url.com', + 'auctionId': 'ec266b31-d652-49c5-8295-e83fafe5532b', + 'responseTimestamp': 1548442460888, + 'requestTimestamp': 1548442460827, + 'bidder': 'appnexus', + 'timeToRespond': 61, + 'pbLg': '5.00', + 'pbMg': '5.00', + 'pbHg': '5.00', + 'pbAg': '5.00', + 'pbDg': '5.00', + 'pbCg': '', + 'size': '640x360', + 'adserverTargeting': { + 'hb_bidder': 'appnexus', + 'hb_adid': '28f24ced14586c', + 'hb_pb': '5.00', + 'hb_size': '640x360', + 'hb_source': 'client', + 'hb_format': 'video', + 'hb_pb_cat_dur': priceIndustryDuration, + 'hb_cache_id': uuid + }, + 'customCacheKey': `${priceIndustryDuration}_${uuid}`, + 'meta': { + 'iabSubCatId': 'iab-1', + 'adServerCatId': label + }, + 'videoCacheKey': '4cf395af-8fee-4960-af0e-88d44e399f14' + } +} From bc855ed6489beeff85250359fa4c1e3ac64bfceb Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 8 Oct 2019 00:26:04 +0530 Subject: [PATCH 1543/1594] Circle CI runs e2e tests on every push (#4200) * run functional tests on circle ci on push to any remote branch * remove extraneous key from config file * add test.localhost as alias to 127.0.0.1 * check 0: execute circle-ci * move /etc/config to a separate command * change bid partner to rubicon * test appnexus bid adapter in ci * comment browserstack command * remove console.log statement * test1: circle-ci * change reference dev -> prod while loading prebid * add console.log statement * check-2: circle-ci * comment browserstack testing * change bid adapter * change bid adapter * remove test case for checking targeting keys * remove the ci flag * uncomment test for checking correct generation of targeting keys * swap AN -> Rubicon for testing targeting keys --- .circleci/config.yml | 5 ++++ gulpfile.js | 29 +++++++++++++++---- .../basic_w_custom_adserver_translation.html | 4 +-- .../basic_w_requireExactDuration.html | 4 +-- .../basic_wo_brandCategoryExclusion.html | 4 +-- .../basic_wo_requireExactDuration.html | 4 +-- test/pages/banner.html | 16 +++++----- test/pages/native.html | 2 +- test/pages/outstream.html | 2 +- test/pages/video.html | 2 +- test/spec/e2e/banner/basic_banner_ad.spec.js | 20 ++++++------- wdio.conf.js | 8 ++++- 12 files changed, 66 insertions(+), 34 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ca6713bb587..73ec23aa740 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,6 +34,7 @@ jobs: key: v1-dependencies-{{ checksum "package.json" }} - run: sudo npm install -g gulp-cli + # Download and run BrowserStack local - run: name : Download BrowserStack Local binary and start it. @@ -48,3 +49,7 @@ jobs: - run: name: BrowserStack testing command: gulp test --browserstack --nolintfix + # run e2e tests + - run: + name: Functional testing + command: echo "127.0.0.1 test.localhost" | sudo tee -a /etc/hosts && gulp e2e-test --host=test.localhost --file=./test/spec/e2e/banner/basic_banner_ad.spec.js diff --git a/gulpfile.js b/gulpfile.js index 24c628ef228..2566b52de59 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -214,16 +214,35 @@ function bundle(dev, moduleArr) { // If --browserstack is given, it will run the full suite of currently supported browsers. // 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 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 = [ - wdioConf - ]; - return execa(wdioCmd, wdioOpts, { stdio: 'inherit' }); + let wdioOpts; + + if (argv.file) { + wdioOpts = [ + wdioConf, + `--spec`, + `${argv.file}` + ] + } else { + wdioOpts = [ + wdioConf + ]; + } + execa(wdioCmd, wdioOpts, { stdio: 'inherit' }) + .then(stdout => { + done(); + process.exit(0); + }) + .catch(err => { + done(new Error(`Tests failed with error: ${err}`)); + process.exit(1); + }); } else { var karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch, argv.file); @@ -315,7 +334,7 @@ gulp.task('build-postbid', gulp.series(escapePostbidConfig, buildPostbid)); gulp.task('serve', gulp.series(clean, lint, gulp.parallel('build-bundle-dev', watch, test))); gulp.task('default', gulp.series(clean, makeWebpackPkg)); -gulp.task('e2e-test', gulp.series(clean, setupE2e, gulp.parallel('build-bundle-dev', watch), test)) +gulp.task('e2e-test', gulp.series(clean, setupE2e, gulp.parallel('build-bundle-prod', watch), 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/longform/basic_w_custom_adserver_translation.html b/integrationExamples/longform/basic_w_custom_adserver_translation.html index 995ea822da4..8f4d46c3079 100644 --- a/integrationExamples/longform/basic_w_custom_adserver_translation.html +++ b/integrationExamples/longform/basic_w_custom_adserver_translation.html @@ -5,7 +5,7 @@ Prebid Freewheel Integration Demo - + + + + + @@ -38,9 +38,11 @@ } }, bids: [{ - bidder: 'appnexus', + bidder: "rubicon", params: { - placementId: 13144370 + accountId: 14062, + siteId: 70608, + zoneId: 498816 } }] }]; @@ -74,7 +76,7 @@ googletag .defineSlot('/19968336/header-bid-tag-0', [[300, 250], [300, 600]], 'div-gpt-ad-1460505748561-0') .addService(googletag.pubads()); - + googletag.pubads().enableSingleRequest(); googletag.enableServices(); }); @@ -84,9 +86,9 @@

    Prebid.js Banner Ad Unit Test

    - +
    diff --git a/test/pages/native.html b/test/pages/native.html index 0823f486848..f382ab8aad7 100644 --- a/test/pages/native.html +++ b/test/pages/native.html @@ -7,7 +7,7 @@ Prebid.js Native Example - + diff --git a/test/pages/outstream.html b/test/pages/outstream.html index 56e443a519b..2a0543095cd 100644 --- a/test/pages/outstream.html +++ b/test/pages/outstream.html @@ -7,7 +7,7 @@ Prebid.js Video Outstream Example - + diff --git a/test/pages/video.html b/test/pages/video.html index e040b65fe23..3fabeb14b94 100644 --- a/test/pages/video.html +++ b/test/pages/video.html @@ -16,7 +16,7 @@ - + + + + data-player-host="${urls.vlHost}">
    Date: Tue, 15 Oct 2019 19:49:51 +0200 Subject: [PATCH 1567/1594] [Orbidder-Adapter] Add bidRequestCount and remove bid.params.keyValues (#4264) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons * add bidfloor parameter to params object * fix gdpr object handling * default to consentRequired: false when not explicitly given * wip - use onSetTargeting callback * add tests for onSetTargeting callback * fix params and respective tests * remove not used bid.params.keyValues * add bidRequestCount to orbidder.otto.de/bid Post request * add bidRequestCount to test object defaultBidRequest --- modules/orbidderBidAdapter.js | 2 +- test/spec/modules/orbidderBidAdapter_spec.js | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index 954ad82261f..88534ae1596 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -19,7 +19,6 @@ export const spec = { (bid.params.accountId && (typeof bid.params.accountId === 'string')) && (bid.params.placementId && (typeof bid.params.placementId === 'string')) && ((typeof bid.params.bidfloor === 'undefined') || (typeof bid.params.bidfloor === 'number')) && - ((typeof bid.params.keyValues === 'undefined') || (typeof bid.params.keyValues === 'object')) && ((typeof bid.params.profile === 'undefined') || (typeof bid.params.profile === 'object'))); }, @@ -38,6 +37,7 @@ export const spec = { auctionId: bidRequest.auctionId, transactionId: bidRequest.transactionId, adUnitCode: bidRequest.adUnitCode, + bidRequestCount: bidRequest.bidRequestCount, sizes: bidRequest.sizes, params: bidRequest.params } diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index aeaa5f30446..1b76de9841a 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -10,6 +10,7 @@ describe('orbidderBidAdapter', () => { bidId: 'd66fa86787e0b0ca900a96eacfd5f0bb', auctionId: 'ccc4c7cdfe11cfbd74065e6dd28413d8', transactionId: 'd58851660c0c4461e4aa06344fc9c0c6', + bidRequestCount: 1, adUnitCode: 'adunit-code', sizes: [[300, 250], [300, 600]], params: { @@ -46,12 +47,6 @@ describe('orbidderBidAdapter', () => { expect(spec.isBidRequestValid(defaultBidRequest)).to.equal(true); }); - it('accepts optional keyValues object', () => { - const bidRequest = deepClone(defaultBidRequest); - bidRequest.params.keyValues = {'key': 'value'}; - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - it('accepts optional profile object', () => { const bidRequest = deepClone(defaultBidRequest); bidRequest.params.profile = {'key': 'value'}; @@ -64,12 +59,6 @@ describe('orbidderBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('doesn\'t accept malformed keyValues', () => { - const bidRequest = deepClone(defaultBidRequest); - bidRequest.params.keyValues = 'another not usable string'; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - it('doesn\'t accept malformed profile', () => { const bidRequest = deepClone(defaultBidRequest); bidRequest.params.profile = 'another not usable string'; From 6fb670620346c34c19b819661c1b59938cb06e41 Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Tue, 15 Oct 2019 23:23:37 +0530 Subject: [PATCH 1568/1594] PulsePoint: remove usage of deprecated utils method / prep for 3.0 (#4257) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * Removing usage of deprecated utils method * minor refactor --- modules/pulsepointBidAdapter.js | 12 +++--- .../spec/modules/pulsepointBidAdapter_spec.js | 42 +++++++++++-------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 9c0d67d9612..fee247ba31f 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -40,7 +40,7 @@ export const spec = { const request = { id: bidRequests[0].bidderRequestId, imp: bidRequests.map(slot => impression(slot)), - site: site(bidRequests), + site: site(bidRequests, bidderRequest), app: app(bidRequests), device: device(), bcat: bidRequests[0].params.bcat, @@ -100,7 +100,7 @@ function bidResponseAvailable(request, response) { idToBidMap[bid.impid] = bid; })); } - if (request.bidderRequest) { + if (request.bidderRequest && request.bidderRequest.bids) { request.bidderRequest.bids.forEach(bid => { idToSlotConfig[bid.bidId] = bid; }); @@ -307,16 +307,16 @@ function dataAsset(id, params, type, defaultLen) { /** * Produces an OpenRTB site object. */ -function site(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; - const appParams = bidderRequest[0].params.app; +function site(bidRequests, bidderRequest) { + const pubId = bidRequests && bidRequests.length > 0 ? bidRequests[0].params.cp : '0'; + const appParams = bidRequests[0].params.app; if (!appParams) { return { publisher: { id: pubId.toString(), }, ref: referrer(), - page: utils.getTopWindowLocation().href, + page: bidderRequest && bidderRequest.refererInfo ? bidderRequest.refererInfo.referer : '', } } return null; diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 1d22ca6eadc..9ed6d3631f5 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -1,7 +1,7 @@ /* eslint dot-notation:0, quote-props:0 */ import {expect} from 'chai'; import {spec} from 'modules/pulsepointBidAdapter'; -import {deepClone, getTopWindowLocation} from 'src/utils'; +import {deepClone} from 'src/utils'; describe('PulsePoint Adapter Tests', function () { const slotConfigs = [{ @@ -138,9 +138,14 @@ describe('PulsePoint Adapter Tests', function () { } } }]; + const bidderRequest = { + refererInfo: { + referer: 'https://publisher.com/home' + } + }; it('Verify build request', function () { - const request = spec.buildRequests(slotConfigs); + const request = spec.buildRequests(slotConfigs, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -149,7 +154,7 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.site.publisher).to.not.equal(null); expect(ortbRequest.site.publisher.id).to.equal('p10000'); expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); + expect(ortbRequest.site.page).to.equal('https://publisher.com/home'); expect(ortbRequest.imp).to.have.lengthOf(2); // device object expect(ortbRequest.device).to.not.equal(null); @@ -167,7 +172,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify parse response', function () { - const request = spec.buildRequests(slotConfigs); + const request = spec.buildRequests(slotConfigs, bidderRequest); const ortbRequest = request.data; const ortbResponse = { seatbid: [{ @@ -196,7 +201,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify use ttl in ext', function () { - const request = spec.buildRequests(slotConfigs); + const request = spec.buildRequests(slotConfigs, bidderRequest); const ortbRequest = request.data; const ortbResponse = { seatbid: [{ @@ -222,13 +227,13 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify full passback', function () { - const request = spec.buildRequests(slotConfigs); + const request = spec.buildRequests(slotConfigs, bidderRequest); const bids = spec.interpretResponse({ body: null }, request) expect(bids).to.have.lengthOf(0); }); it('Verify Native request', function () { - const request = spec.buildRequests(nativeSlotConfig); + const request = spec.buildRequests(nativeSlotConfig, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -266,7 +271,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify Native response', function () { - const request = spec.buildRequests(nativeSlotConfig); + const request = spec.buildRequests(nativeSlotConfig, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -355,7 +360,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify app requests', function () { - const request = spec.buildRequests(appSlotConfig); + const request = spec.buildRequests(appSlotConfig, bidderRequest); const ortbRequest = request.data; // site object expect(ortbRequest.site).to.equal(null); @@ -368,13 +373,13 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify GDPR', function () { - const bidderRequest = { + const bidderRequestGdpr = { gdprConsent: { gdprApplies: true, consentString: 'serialized_gpdr_data' } }; - const request = spec.buildRequests(slotConfigs, bidderRequest); + const request = spec.buildRequests(slotConfigs, Object.assign({}, bidderRequest, bidderRequestGdpr)); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -389,7 +394,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify Video request', function () { - const request = spec.buildRequests(videoSlotConfig); + const request = spec.buildRequests(videoSlotConfig, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -409,7 +414,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify Video response', function () { - const request = spec.buildRequests(videoSlotConfig); + const request = spec.buildRequests(videoSlotConfig, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -433,7 +438,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify extra parameters', function () { - let request = spec.buildRequests(additionalParamsConfig); + let request = spec.buildRequests(additionalParamsConfig, bidderRequest); let ortbRequest = request.data; expect(ortbRequest).to.not.equal(null); expect(ortbRequest.imp).to.have.lengthOf(1); @@ -448,7 +453,7 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.imp[0].ext.prebid.extra_key4).to.eql([1, 2, 3]); expect(Object.keys(ortbRequest.imp[0].ext.prebid)).to.eql(['extra_key1', 'extra_key2', 'extra_key3', 'extra_key4']); // attempting with a configuration with no unknown params. - request = spec.buildRequests(outstreamSlotConfig); + request = spec.buildRequests(outstreamSlotConfig, bidderRequest); ortbRequest = request.data; expect(ortbRequest).to.not.equal(null); expect(ortbRequest.imp).to.have.lengthOf(1); @@ -456,7 +461,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify ortb parameters', function () { - const request = spec.buildRequests(ortbParamsSlotConfig); + const request = spec.buildRequests(ortbParamsSlotConfig, bidderRequest); const ortbRequest = request.data; expect(ortbRequest).to.not.equal(null); expect(ortbRequest.bcat).to.eql(['IAB-1', 'IAB-20']); @@ -472,7 +477,8 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify outstream renderer', function () { - const request = spec.buildRequests(outstreamSlotConfig, {bids: [outstreamSlotConfig[0]]}); + const bidderRequestOutstream = Object.assign({}, bidderRequest, {bids: [outstreamSlotConfig[0]]}); + const request = spec.buildRequests(outstreamSlotConfig, bidderRequestOutstream); const ortbRequest = request.data; expect(ortbRequest).to.not.be.null; expect(ortbRequest.imp[0]).to.not.be.null; @@ -521,7 +527,7 @@ describe('PulsePoint Adapter Tests', function () { } } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request).to.be.not.null; const ortbRequest = request.data; expect(request.data).to.be.not.null; From d549a409db808f16a40b68f85d3dafdeeca4b32a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 15 Oct 2019 13:59:18 -0400 Subject: [PATCH 1569/1594] Use isArray method (#4288) --- src/adapters/bidderFactory.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 90cab154fd4..4ccbfd89457 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -9,7 +9,7 @@ import CONSTANTS from '../constants.json'; import events from '../events'; import includes from 'core-js/library/fn/array/includes'; import { ajax } from '../ajax'; -import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, setDataInLocalStorage, getDataFromLocalStorage, deepAccess } from '../utils'; +import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, setDataInLocalStorage, getDataFromLocalStorage, deepAccess, isArray } from '../utils'; import { ADPOD } from '../mediaTypes'; import { getHook } from '../hook'; @@ -290,7 +290,7 @@ export function newBidder(spec) { } if (bids) { - if (bids.forEach) { + if (isArray(bids)) { bids.forEach(addBidUsingRequestMap); } else { addBidUsingRequestMap(bids); From fceb471e7d1e61698e6e8c6141d551c01ed7a3db Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Tue, 15 Oct 2019 15:03:09 -0500 Subject: [PATCH 1570/1594] Add Parrable ID submodule (#4266) * add parrable id submodule * fix integration test config * fix var name * always refresh sotredId for parrable * add submodulesThatAlwaysRefresh concept * remove comment * add parrable url as one string * add parrable prod endpoint * use .indexOf instead of .includes * add params to test config * comment failing test * uncomment failing assertion * add parrable ID to prebid server adapter * add parrableIdSystem to .submodules.json * extract parrableId unit tests from userId spec * remove breakline between imports * remove unused param * remove userId generic feature from parrableId module * remove trailing space * fix failing test due to none merged conflict --- integrationExamples/gpt/userId_example.html | 11 +++ modules/.submodules.json | 1 + modules/parrableIdSystem.js | 92 +++++++++++++++++++ modules/prebidServerBidAdapter/index.js | 11 ++- modules/userId/index.js | 1 + modules/userId/userId.md | 11 +++ test/spec/modules/parrableIdSystem_spec.js | 77 ++++++++++++++++ .../modules/prebidServerBidAdapter_spec.js | 3 + 8 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 modules/parrableIdSystem.js create mode 100644 test/spec/modules/parrableIdSystem_spec.js diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 09e9e4147fc..6d2c2ce677a 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -152,6 +152,17 @@ refreshInSeconds: 8*3600 // Refresh frequency of cookies, defaulting to 'expires' }, + }, { + name: "parrableId", + params: { + // change to Parrable Partner Client ID(s) you received from the Parrable Partners you are using + partner: '30182847-e426-4ff9-b2b5-9ca1324ea09b' + }, + storage: { + type: "cookie", + name: "_parrable_eid", // create a cookie with this name + expires: 365 // cookie can last for a year + } }, { name: "pubCommonId", storage: { diff --git a/modules/.submodules.json b/modules/.submodules.json index 81c82603083..09063deea40 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -3,6 +3,7 @@ "digiTrustIdSystem", "id5IdSystem", "criteortusIdSystem", + "parrableIdSystem", "liveIntentIdSystem" ], "adpod": [ diff --git a/modules/parrableIdSystem.js b/modules/parrableIdSystem.js new file mode 100644 index 00000000000..e8ad7f9acc1 --- /dev/null +++ b/modules/parrableIdSystem.js @@ -0,0 +1,92 @@ +/** + * This module adds Parrable to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/parrableIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils' +import {ajax} from '../src/ajax'; +import {submodule} from '../src/hook'; + +const PARRABLE_URL = 'https://h.parrable.com/prebid'; + +function isValidConfig(configParams) { + if (!configParams) { + utils.logError('User ID - parrableId submodule requires configParams'); + return false; + } + if (!configParams.partner) { + utils.logError('User ID - parrableId submodule requires partner list'); + return false; + } + return true; +} + +function fetchId(configParams, consentData, currentStoredId) { + if (!isValidConfig(configParams)) return; + + const data = { + eid: currentStoredId || null, + trackers: configParams.partner.split(',') + }; + + const searchParams = { + data: btoa(JSON.stringify(data)), + _rand: Math.random() + }; + + const options = { + method: 'GET', + withCredentials: true + }; + + const callback = function (cb) { + const onSuccess = (response) => { + let eid; + if (response) { + try { + let responseObj = JSON.parse(response); + eid = responseObj ? responseObj.eid : undefined; + } catch (error) { + utils.logError(error); + } + } + cb(eid); + }; + ajax(PARRABLE_URL, onSuccess, searchParams, options); + }; + + return { callback }; +}; + +/** @type {Submodule} */ +export const parrableIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'parrableId', + /** + * decode the stored id value for passing to bid requests + * @function + * @param {Object|string} value + * @return {(Object|undefined} + */ + decode(value) { + return (value && typeof value === 'string') ? { 'parrableid': value } : undefined; + }, + + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @param {SubmoduleParams} [configParams] + * @param {ConsentData} [consentData] + * @returns {function(callback:function)} + */ + getId(configParams, consentData, currentStoredId) { + return fetchId(configParams, consentData, currentStoredId); + } +}; + +submodule('userId', parrableIdSubmodule); diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 7776db714dd..872e0bb81d9 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -698,7 +698,7 @@ const OPEN_RTB_PROTOCOL = { } const bidUserId = utils.deepAccess(bidRequests, '0.bids.0.userId'); - if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid || bidUserId.lipb)) { + if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid || bidUserId.parrableid || bidUserId.lipb)) { utils.deepSetValue(request, 'user.ext.eids', []); if (bidUserId.tdid) { @@ -722,6 +722,15 @@ const OPEN_RTB_PROTOCOL = { }); } + if (bidUserId.parrableid) { + request.user.ext.eids.push({ + source: 'parrable.com', + uids: [{ + id: bidUserId.parrableid + }] + }); + } + if (bidUserId.lipb && bidUserId.lipb.lipbid) { request.user.ext.eids.push({ source: 'liveintent.com', diff --git a/modules/userId/index.js b/modules/userId/index.js index baeb1e2574c..ac96fd2cec8 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -371,6 +371,7 @@ function initSubmodules(submodules, consentData) { utils.logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`); return []; } + return submodules.reduce((carry, submodule) => { // There are two submodule configuration types to handle: storage or value // 1. storage: retrieve user id data from cookie/html storage or with the submodule's getId method diff --git a/modules/userId/userId.md b/modules/userId/userId.md index b5b8c216ead..9b363bbcf64 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -32,6 +32,17 @@ pbjs.setConfig({ name: "id5id", expires: 5, // Expiration of cookies in days refreshInSeconds: 8*3600 // User Id cache lifetime in seconds, defaulting to 'expires' + }, + }, { + name: 'parrableId', + params: { + // Replace the list contents with the Parrable Partner Client IDs for Parrable-aware bid adapters in use + partners: [ "30182847-e426-4ff9-b2b5-9ca1324ea09b" ] + }, + storage: { + type: 'cookie', + name: '_parrable_eid', + expires: 365 } }, { name: 'identityLink', diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js new file mode 100644 index 00000000000..540e63aa630 --- /dev/null +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -0,0 +1,77 @@ +import { expect } from 'chai'; +import {config} from 'src/config'; +import * as utils from 'src/utils'; +import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; +import { parrableIdSubmodule } from 'modules/parrableIdSystem'; + +const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; +const P_COOKIE_NAME = '_parrable_eid'; +const P_COOKIE_VALUE = '01.1563917337.test-eid'; +const P_CONFIG_MOCK = { + name: 'parrableId', + params: { + partner: 'parrable_test_partner_123,parrable_test_partner_456' + }, + storage: { + name: '_parrable_eid', + type: 'cookie', + expires: 364 + } +}; + +describe('Parrable ID System', function() { + function getConfigMock() { + return { + userSync: { + syncDelay: 0, + userIds: [P_CONFIG_MOCK] + } + } + } + function getAdUnitMock(code = 'adUnit-code') { + return { + code, + mediaTypes: {banner: {}, native: {}}, + sizes: [ + [300, 200], + [300, 600] + ], + bids: [{ + bidder: 'sampleBidder', + params: { placementId: 'banner-only-bidder' } + }] + }; + } + + describe('Parrable ID in Bid Request', function() { + let adUnits; + + beforeEach(function() { + adUnits = [getAdUnitMock()]; + }); + + it('should append parrableid to bid request', function(done) { + // simulate existing browser local storage values + utils.setCookie( + P_COOKIE_NAME, + P_COOKIE_VALUE, + (new Date(Date.now() + 5000).toUTCString()) + ); + + setSubmoduleRegistry([parrableIdSubmodule]); + init(config); + config.setConfig(getConfigMock()); + + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.parrableid'); + expect(bid.userId.parrableid).to.equal(P_COOKIE_VALUE); + }); + }); + utils.setCookie(P_COOKIE_NAME, '', EXPIRED_COOKIE_DATE); + done(); + }, { adUnits }); + }); + }); +}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 1c10130a84e..658f130d144 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1044,6 +1044,7 @@ describe('S2S Adapter', function () { userIdBidRequest[0].bids[0].userId = { tdid: 'abc123', pubcid: '1234', + parrableid: '01.1563917337.test-eid', lipb: { lipbid: 'li-xyz' } @@ -1057,6 +1058,8 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'parrable.com')).is.not.empty; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'parrable.com')[0].uids[0].id).is.equal('01.1563917337.test-eid'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].uids[0].id).is.equal('li-xyz'); }); From 29520f396781647a377d60b34b3d9effac465102 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 15 Oct 2019 16:58:50 -0400 Subject: [PATCH 1571/1594] Prebid 2.36.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ca06ddb8b24..fbbf5ef66d3 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.36.0-pre", + "version": "2.36.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From f498ba8fbbf95bc0d26183a160dcf72fcaec1351 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 15 Oct 2019 17:11:39 -0400 Subject: [PATCH 1572/1594] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fbbf5ef66d3..0200db4eace 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.36.0", + "version": "2.37.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From b363e97ed3e4aa2f3799a54d832c7b341392d863 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 15 Oct 2019 15:20:11 -0700 Subject: [PATCH 1573/1594] Support schain module and send bidfloor param in Sharethrough adapter (#4271) * Add support for supply chain object module Story: [#168742394](https://www.pivotaltracker.com/story/show/168742394) Co-authored-by: Josh Becker * Add bidfloor parameter to bid request sent to STX Story: [#168742573](https://www.pivotaltracker.com/story/show/168742573) --- modules/sharethroughBidAdapter.js | 8 ++++ .../modules/sharethroughBidAdapter_spec.js | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index 7fe41b2b7ae..117088f5355 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -41,6 +41,14 @@ export const sharethroughAdapterSpec = { query.ttduid = bidRequest.userId.tdid; } + if (bidRequest.schain) { + query.schain = JSON.stringify(bidRequest.schain); + } + + if (bidRequest.bidfloor) { + query.bidfloor = parseFloat(bidRequest.bidfloor); + } + // Data that does not need to go to the server, // but we need as part of interpretResponse() const strData = { diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index afa5f44959c..8a8ccdbbeb3 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -280,6 +280,44 @@ describe('sharethrough adapter spec', function () { } }); }); + + 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 + } + ] + }; + + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.schain).to.eq(JSON.stringify(bidRequest.schain)); + }); + + 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'); + }); + + it('should include the bidfloor parameter if it is present in the bid request', function() { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest['bidfloor'] = 0.50; + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.bidfloor).to.eq(0.5); + }); + + 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'); + }); }); describe('.interpretResponse', function () { From 493bd5e0d7d97b00b3908c3e47372e8f69410817 Mon Sep 17 00:00:00 2001 From: hbanalytics <55453525+hbanalytics@users.noreply.github.com> Date: Wed, 16 Oct 2019 01:30:50 +0300 Subject: [PATCH 1574/1594] Platform One Analytics Adapter (#4233) * Added Y1 Analytics Adapter * rename y1AnalyticsAdapter in yieldoneAnalyticsAdapter * Yieldone Bid Adapter: fixes from lint check * Yieldone Analytics Adapter: fix endpoint protocol * Added spec file for yieldone Analytics Adapter --- modules/yieldoneAnalyticsAdapter.js | 122 +++++++++ modules/yieldoneAnalyticsAdapter.md | 21 ++ .../modules/yieldoneAnalyticsAdapter_spec.js | 256 ++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 modules/yieldoneAnalyticsAdapter.js create mode 100644 modules/yieldoneAnalyticsAdapter.md create mode 100644 test/spec/modules/yieldoneAnalyticsAdapter_spec.js diff --git a/modules/yieldoneAnalyticsAdapter.js b/modules/yieldoneAnalyticsAdapter.js new file mode 100644 index 00000000000..94dd0daa0b2 --- /dev/null +++ b/modules/yieldoneAnalyticsAdapter.js @@ -0,0 +1,122 @@ +import {ajax} from '../src/ajax'; +import adapter from '../src/AnalyticsAdapter'; +import CONSTANTS from '../src/constants.json'; +import adapterManager from '../src/adapterManager'; +import { targeting } from '../src/targeting'; +import { auctionManager } from '../src/auctionManager'; +import * as utils from '../src/utils'; + +const ANALYTICS_CODE = 'yieldone'; +const analyticsType = 'endpoint'; +// const VERSION = '1.0.0'; +const defaultUrl = '//pool.tsukiji.iponweb.net/hba'; +const requestedBidders = {}; +const requestedBids = {}; +const referrers = {}; + +let currentAuctionId = ''; +let url = defaultUrl; +let pubId = ''; + +const yieldoneAnalytics = Object.assign(adapter({analyticsType}), { + getUrl() { return url; }, + track({eventType, args = {}}) { + if (eventType === CONSTANTS.EVENTS.BID_REQUESTED) { + const reqBidderId = `${args.bidderCode}_${args.auctionId}`; + requestedBidders[reqBidderId] = utils.deepClone(args); + requestedBidders[reqBidderId].bids = []; + args.bids.forEach((bid) => { + requestedBids[`${bid.bidId}_${bid.auctionId}`] = bid; + }); + } + if (eventType === CONSTANTS.EVENTS.BID_TIMEOUT && utils.isArray(args)) { + const eventsStorage = yieldoneAnalytics.eventsStorage; + const reqBidders = {}; + args.forEach((bid) => { + const reqBidId = `${bid.bidId}_${bid.auctionId}`; + const reqBidderId = `${bid.bidder}_${bid.auctionId}`; + if (!eventsStorage[bid.auctionId]) eventsStorage[bid.auctionId] = []; + if (requestedBidders[reqBidderId] && requestedBids[reqBidId]) { + if (!reqBidders[bid.bidder]) { + reqBidders[bid.bidder] = requestedBidders[reqBidderId]; + reqBidders[bid.bidder].pubId = pubId; + eventsStorage[bid.auctionId].push({eventType, params: reqBidders[bid.bidder]}); + delete requestedBidders[reqBidderId]; + } + reqBidders[bid.bidder].bids.push(requestedBids[reqBidId]); + delete requestedBids[reqBidId]; + } + }); + } else { + args.pubId = pubId; + currentAuctionId = args.auctionId || currentAuctionId; + if (currentAuctionId) { + const eventsStorage = yieldoneAnalytics.eventsStorage; + if (!eventsStorage[currentAuctionId]) eventsStorage[currentAuctionId] = []; + const referrer = args.refererInfo && args.refererInfo.referer; + if (referrer && referrers[currentAuctionId] !== referrer) { + referrers[currentAuctionId] = referrer; + } + eventsStorage[currentAuctionId].push({ + eventType, + params: args + }); + } + } + if ( + eventType === CONSTANTS.EVENTS.AUCTION_END || eventType === CONSTANTS.EVENTS.BID_WON + ) { + args.adServerTargeting = targeting.getAllTargeting( + auctionManager.getAdUnitCodes(), + auctionManager.getBidsReceived() + ); + if (yieldoneAnalytics.eventsStorage[args.auctionId]) { + yieldoneAnalytics.eventsStorage[args.auctionId].forEach((it) => { + it.page = {url: referrers[currentAuctionId]}; + }); + } + yieldoneAnalytics.sendStat(yieldoneAnalytics.eventsStorage[args.auctionId], args.auctionId); + } + }, + sendStat(events, auctionId) { + if (!events) return; + delete yieldoneAnalytics.eventsStorage[auctionId]; + ajax( + url, + { + success: function() {}, + error: function() {} + }, + JSON.stringify(events), + { + method: 'POST' + } + ); + } +}); + +yieldoneAnalytics.eventsStorage = {}; + +// save the base class function +yieldoneAnalytics.originEnableAnalytics = yieldoneAnalytics.enableAnalytics; + +// override enableAnalytics so we can get access to the config passed in from the page +yieldoneAnalytics.enableAnalytics = function (config) { + const options = config && config.options; + if (options) { + if (typeof options.url === 'string') { + url = options.url; + } + if (options.pubId) { + pubId = options.pubId.toString(); + } + } + yieldoneAnalytics.originEnableAnalytics(config); // call the base class function +}; + +adapterManager.registerAnalyticsAdapter({ + adapter: yieldoneAnalytics, + code: ANALYTICS_CODE +}); + +export default yieldoneAnalytics; diff --git a/modules/yieldoneAnalyticsAdapter.md b/modules/yieldoneAnalyticsAdapter.md new file mode 100644 index 00000000000..43be87b114b --- /dev/null +++ b/modules/yieldoneAnalyticsAdapter.md @@ -0,0 +1,21 @@ +# Overview +Module Name: Platform One Analytics + +Module Type: Analytics Adapter + +Maintainer: y1s@platform-one.co.jp + +# Description + +Analytics adapter for Platform One. Please contact y1s@platform-one.co.jp for any additional information. Official website link to the vendor: www.platform-one.co.jp/. + +# Test Parameters + +``` +{ + provider: 'yieldone', + options : { + pubId : 'TestAnalyticsPublisher', //id provided by Platform One publisher team + } +} +``` \ No newline at end of file diff --git a/test/spec/modules/yieldoneAnalyticsAdapter_spec.js b/test/spec/modules/yieldoneAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..a297403b2e0 --- /dev/null +++ b/test/spec/modules/yieldoneAnalyticsAdapter_spec.js @@ -0,0 +1,256 @@ +import yieldoneAnalytics from 'modules/yieldoneAnalyticsAdapter'; +import { targeting } from 'src/targeting'; +import { expect } from 'chai'; +let events = require('src/events'); +let adapterManager = require('src/adapterManager').default; +let constants = require('src/constants.json'); + +describe('Yieldone Prebid Analytic', function () { + let sendStatStub; + let getAllTargetingStub; + const fakeTargeting = { + '0000': {'someId': 'someValue'} + }; + + describe('enableAnalytics', function () { + beforeEach(function () { + sendStatStub = sinon.stub(yieldoneAnalytics, 'sendStat'); + getAllTargetingStub = sinon.stub(targeting, 'getAllTargeting').returns(fakeTargeting); + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(function () { + sendStatStub.restore(); + getAllTargetingStub.restore(); + events.getEvents.restore(); + }); + + after(function () { + yieldoneAnalytics.disableAnalytics(); + }); + + it('should catch all events', function (done) { + adapterManager.registerAnalyticsAdapter({ + code: 'yieldone', + adapter: yieldoneAnalytics + }); + + const initOptions = { + pubId: '123456' + }; + + const auctionId = 'test-test-test'; + const testReferrer = 'http://test'; + + const request = [ + { + bidderCode: 'biddertest_1', + auctionId: auctionId, + refererInfo: {referer: testReferrer}, + bids: [ + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '1234', + bidder: 'biddertest_1', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {param1: '111', param2: '222'}, + sizes: [[300, 250], [336, 280]] + }, + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '5678', + bidder: 'biddertest_1', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {param1: '222', param2: '222'}, + sizes: [[300, 250], [336, 280]] + } + ] + }, + { + bidderCode: 'biddertest_2', + auctionId: auctionId, + refererInfo: {referer: testReferrer}, + bids: [ + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '91011', + bidder: 'biddertest_2', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {paramA: '111', paramB: '222'}, + sizes: [[300, 250], [336, 280]] + } + ] + }, + { + bidderCode: 'biddertest_3', + auctionId: auctionId, + refererInfo: {referer: testReferrer}, + bids: [ + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '12131', + bidder: 'biddertest_3', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {param_1: '111', param_2: '222'}, + sizes: [[300, 250], [336, 280]] + } + ] + } + ]; + + const responses = [ + { + width: 300, + height: 250, + statusMessage: 'Bid available', + bidId: '1234', + auctionId: auctionId, + cpm: 0.1, + bidder: 'biddertest_1', + adUnitCode: '0000', + timeToRespond: 100 + }, + { + width: 336, + height: 280, + statusMessage: 'Bid available', + bidId: '5678', + auctionId: auctionId, + cpm: 0.2, + bidder: 'biddertest_1', + adUnitCode: '0000', + timeToRespond: 100 + }, + { + width: 300, + height: 250, + statusMessage: 'Bid available', + bidId: '91011', + auctionId: auctionId, + cpm: 0.3, + bidder: 'biddertest_2', + adUnitCode: '0000', + timeToRespond: 100 + }, + { + bidId: '12131', + auctionId: auctionId, + bidder: 'biddertest_3' + } + ]; + + const winner = { + width: 300, + height: 250, + statusMessage: 'Bid available', + bidId: '91011', + auctionId: auctionId, + cpm: 0.3, + bidder: 'biddertest_2', + adUnitCode: '0000', + timeToRespond: 100 + }; + + const expectedEvents = [ + { + eventType: constants.EVENTS.AUCTION_INIT, + page: {url: testReferrer}, + params: { + config: initOptions, + auctionId: auctionId, + pubId: initOptions.pubId + } + }, + { + eventType: constants.EVENTS.BID_REQUESTED, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, request[0]) + }, + { + eventType: constants.EVENTS.BID_REQUESTED, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, request[1]) + }, + { + eventType: constants.EVENTS.BID_REQUESTED, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, request[2]) + }, + { + eventType: constants.EVENTS.BID_RESPONSE, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, responses[0]) + }, + { + eventType: constants.EVENTS.BID_RESPONSE, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, responses[1]) + }, + { + eventType: constants.EVENTS.BID_RESPONSE, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, responses[2]) + }, + { + eventType: constants.EVENTS.BID_TIMEOUT, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, request[2]) + }, + { + eventType: constants.EVENTS.AUCTION_END, + page: {url: testReferrer}, + params: { + auctionId: auctionId, + pubId: initOptions.pubId, + adServerTargeting: fakeTargeting + } + } + ]; + + const wonExpectedEvents = [ + { + eventType: constants.EVENTS.BID_WON, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId, adServerTargeting: fakeTargeting}, winner) + } + ]; + + adapterManager.enableAnalytics({ + provider: 'yieldone', + options: initOptions + }); + + events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions, auctionId: auctionId}); + + events.emit(constants.EVENTS.BID_REQUESTED, request[0]); + events.emit(constants.EVENTS.BID_REQUESTED, request[1]); + events.emit(constants.EVENTS.BID_REQUESTED, request[2]); + + events.emit(constants.EVENTS.BID_RESPONSE, responses[0]); + events.emit(constants.EVENTS.BID_RESPONSE, responses[1]); + events.emit(constants.EVENTS.BID_RESPONSE, responses[2]); + + events.emit(constants.EVENTS.BID_TIMEOUT, [responses[3]]); + + events.emit(constants.EVENTS.AUCTION_END, {auctionId: auctionId}); + + expect(yieldoneAnalytics.eventsStorage[auctionId]).to.deep.equal(expectedEvents); + + delete yieldoneAnalytics.eventsStorage[auctionId]; + + setTimeout(function() { + events.emit(constants.EVENTS.BID_WON, winner); + + sinon.assert.callCount(sendStatStub, 2); + expect(yieldoneAnalytics.eventsStorage[auctionId]).to.deep.equal(wonExpectedEvents); + + delete yieldoneAnalytics.eventsStorage[auctionId]; + done(); + }, 1000); + }); + }); +}); From 44192a8cdd0a92aac852c46bfe6ef0b9248be518 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Wed, 16 Oct 2019 09:07:40 -0500 Subject: [PATCH 1575/1594] Fix parrable id integration example (#4317) * fix parrableId integration example * add parentheses --- modules/userId/userId.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 9b363bbcf64..b10aa2adc20 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -36,8 +36,8 @@ pbjs.setConfig({ }, { name: 'parrableId', params: { - // Replace the list contents with the Parrable Partner Client IDs for Parrable-aware bid adapters in use - partners: [ "30182847-e426-4ff9-b2b5-9ca1324ea09b" ] + // Replace partner with comma-separated (if more than one) Parrable Partner Client ID(s) for Parrable-aware bid adapters in use + partner: "30182847-e426-4ff9-b2b5-9ca1324ea09b" }, storage: { type: 'cookie', From cb3c457b0d3c1bbbb397d7d21dd6a9658036a946 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Wed, 16 Oct 2019 17:55:43 +0200 Subject: [PATCH 1576/1594] Improve Digital adapter: support for video (#4318) * Bid floor, https, native ad update * Update the ad server protocol module * Adding referrer * Improve Digital support for video * Improve Digital adapter: video * adapter version -> 6.0.0 --- modules/improvedigitalBidAdapter.js | 14 +++- .../modules/improvedigitalBidAdapter_spec.js | 82 +++++++++++++++++++ 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 61074985597..4ee2226395b 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -1,15 +1,15 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { config } from '../src/config'; -import { BANNER, NATIVE } from '../src/mediaTypes'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'improvedigital'; export const spec = { - version: '5.3.0', + version: '6.0.0', code: BIDDER_CODE, aliases: ['id'], - supportedMediaTypes: [BANNER, NATIVE], + supportedMediaTypes: [BANNER, NATIVE, VIDEO], /** * Determines whether or not the given bid request is valid. @@ -87,6 +87,9 @@ export const spec = { bid.native.impressionTrackers.unshift(bidObject.nurl); } bid.mediaType = NATIVE; + } else if (bidObject.ad_type && bidObject.ad_type === 'video') { + bid.vastXml = bidObject.adm; + bid.mediaType = VIDEO; } else { // Banner let nurl = ''; @@ -186,6 +189,11 @@ function getNormalizedBidRequest(bid) { const bidFloorCur = utils.getBidIdParameter('bidFloorCur', bid.params); let normalizedBidRequest = {}; + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + if (bid.mediaType === 'video' || (videoMediaType && context !== 'outstream')) { + normalizedBidRequest.adTypes = [ VIDEO ]; + } if (placementId) { normalizedBidRequest.placementId = placementId; } else { diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 2bff6fba5bc..2d9d51c0d68 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -193,6 +193,38 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.referrer).to.equal('https://blah.com/test.html'); }); + it('should add ad type for instream video', function () { + let bidRequest = Object.assign({}, simpleBidRequest); + bidRequest.mediaType = 'video'; + let request = spec.buildRequests([bidRequest])[0]; + let params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].ad_types).to.deep.equal(['video']); + + bidRequest = Object.assign({}, simpleBidRequest); + bidRequest.mediaTypes = { + video: { + context: 'instream', + playerSize: [640, 480] + } + }; + request = spec.buildRequests([bidRequest])[0]; + params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].ad_types).to.deep.equal(['video']); + }); + + it('should not set ad type for outstream video', function() { + const bidRequest = Object.assign({}, simpleBidRequest); + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }; + const request = spec.buildRequests([bidRequest])[0]; + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].ad_types).to.not.exist; + }); + it('should add schain', function () { const schain = '{"ver":"1.0","complete":1,"nodes":[{"asi":"headerlift.com","sid":"xyz","hp":1}]}'; const bidRequest = Object.assign({}, simpleBidRequest); @@ -456,6 +488,34 @@ describe('Improve Digital Adapter Tests', function () { } }; + const serverResponseVideo = { + 'body': { + 'id': '687a06c541d8d1', + 'site_id': 191642, + 'bid': [ + { + 'isNet': false, + 'id': '33e9500b21129f', + 'advid': '5279', + 'price': 1.45888594164456, + 'nurl': 'http://ice.360yield.com/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', + 'h': 290, + 'pid': 1053688, + 'sync': [ + 'http://link1', + 'http://link2' + ], + 'crid': '422031', + 'w': 600, + 'cid': '99006', + 'adm': '', + 'ad_type': 'video' + } + ], + 'debug': '' + } + }; + const nativeEventtrackers = [ { event: 1, @@ -552,6 +612,22 @@ describe('Improve Digital Adapter Tests', function () { } ]; + let expectedBidVideo = [ + { + 'vastXml': '', + 'adId': '33e9500b21129f', + 'creativeId': '422031', + 'cpm': 1.45888594164456, + 'currency': 'USD', + 'height': 290, + 'mediaType': 'video', + 'netRevenue': false, + 'requestId': '33e9500b21129f', + 'ttl': 300, + 'width': 600 + } + ]; + it('should return a well-formed bid', function () { const bids = spec.interpretResponse(serverResponse); expect(bids).to.deep.equal(expectedBid); @@ -667,6 +743,12 @@ describe('Improve Digital Adapter Tests', function () { delete bids[0].ortbNative; expect(bids).to.deep.equal(expectedBids); }); + + // Video + it('should return a well-formed video bid', function () { + const bids = spec.interpretResponse(serverResponseVideo); + expect(bids).to.deep.equal(expectedBidVideo); + }); }); describe('getUserSyncs', function () { From fd865b1626ceebdaa5d6b4e346515c92317bc497 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Wed, 16 Oct 2019 19:04:57 +0300 Subject: [PATCH 1577/1594] Gamoshi: Update aliases list. Add support for userSync. (#4319) * Add support for multi-format ad units. Add favoredMediaType property to params. * Add tests for gdpr consent. * Add adId to outbids * Modify media type resolving * Refactor multi-format ad units handler. * Modify the way of sending GDPR data. Update aliases. * Add new consent fields. Add unit test. * Add new consent fields. Add unit test. * Add support for id5 and unified id cookie sync. * Add support for id5 and unified id cookie sync. * Add restricted check for gdpr consent. --- modules/gamoshiBidAdapter.js | 58 ++++++++++++++++----- test/spec/modules/gamoshiBidAdapter_spec.js | 38 +++++++++++++- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index ec146b77c70..b18188cf33a 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -42,17 +42,16 @@ export const helper = { export const spec = { code: 'gamoshi', - aliases: ['gambid', 'cleanmedia', 'viewdeos', '9MediaOnline'], + aliases: ['gambid', 'cleanmedia', '9MediaOnline'], supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - return !!bid.params.supplyPartnerId && - typeof bid.params.supplyPartnerId === 'string' && - (typeof bid.params['rtbEndpoint'] === 'undefined' || typeof bid.params['rtbEndpoint'] === 'string') && - (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && - (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number') && - (typeof bid.params['protocols'] === 'undefined' || Array.isArray(bid.params['protocols'])) && - (typeof bid.params.instl === 'undefined' || bid.params.instl === 0 || bid.params.instl === 1); + 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); }, buildRequests: function (validBidRequests, bidderRequest) { @@ -75,16 +74,24 @@ export const spec = { 'imp': [], 'ext': {} }; + const gdprConsent = bidderRequest.gdprConsent; - if (bidderRequest.gdprConsent && - bidderRequest.gdprConsent.consentString && - bidderRequest.gdprConsent.gdprApplies) { + if (gdprConsent && gdprConsent.consentString && gdprConsent.gdprApplies) { rtbBidRequest.ext.gdpr_consent = { - consent_string: bidderRequest.gdprConsent.consentString, - consent_required: bidderRequest.gdprConsent.gdprApplies + consent_string: gdprConsent.consentString, + consent_required: gdprConsent.gdprApplies }; + rtbBidRequest.regs = { + ext: { + gdpr: gdprConsent.gdprApplies === true ? 1 : 0 + } + }; + rtbBidRequest.user = { + ext: { + consent: gdprConsent.consentString + } + } } - const imp = { 'id': transactionId, 'instl': params.instl === 1 ? 1 : 0, @@ -129,6 +136,15 @@ export const spec = { } } + let eids = []; + if (bidRequest && bidRequest.userId) { + addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.id5id`), 'id5-sync.com', 'ID5ID'); + addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.tdid`), 'adserver.org', 'TDID'); + } + if (eids.length > 0) { + rtbBidRequest.user.ext.eids = eids; + } + if (rtbBidRequest.imp.length === 0) { return; } @@ -243,4 +259,18 @@ function renderOutstream(bid) { }); } +function addExternalUserId(eids, value, source, rtiPartner) { + if (utils.isStr(value)) { + eids.push({ + source, + uids: [{ + id: value, + ext: { + rtiPartner + } + }] + }); + } +} + registerBidder(spec); diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index a2c4eebc213..2d63d47a73e 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -227,13 +227,49 @@ describe('GamoshiAdapter', function () { it('builds request with gdpr consent', function () { let response = spec.buildRequests([bidRequest], bidRequest)[0]; + expect(response.data.ext.gdpr_consent).to.exist; expect(response.data.ext).to.have.property('gdpr_consent'); expect(response.data.ext.gdpr_consent.consent_string).to.equal('some string'); expect(response.data.ext.gdpr_consent.consent_required).to.equal(true); + + expect(response.data.regs.ext.gdpr).to.exist; + expect(response.data.user.ext.consent).to.equal('some string'); + }); + + it('build request with ID5 Id', function () { + const bidRequestClone = utils.deepClone(bidRequest); + bidRequestClone.userId = {}; + bidRequestClone.userId.id5id = 'id5-user-id'; + let request = spec.buildRequests([bidRequestClone], bidRequestClone)[0]; + expect(request.data.user.ext.eids).to.deep.equal([{ + 'source': 'id5-sync.com', + 'uids': [{ + 'id': 'id5-user-id', + 'ext': { + 'rtiPartner': 'ID5ID' + } + }] + }]); + }); + + it('build request with unified Id', function () { + const bidRequestClone = utils.deepClone(bidRequest); + bidRequestClone.userId = {}; + bidRequestClone.userId.tdid = 'tdid-user-id'; + let request = spec.buildRequests([bidRequestClone], bidRequestClone)[0]; + expect(request.data.user.ext.eids).to.deep.equal([{ + 'source': 'adserver.org', + 'uids': [{ + 'id': 'tdid-user-id', + 'ext': { + 'rtiPartner': 'TDID' + } + }] + }]); }); }); - describe('interpretResponse', function () { + describe('interpretResponse', () => { const bannerBidRequest = { 'adUnitCode': 'adunit-code', 'auctionId': '1d1a030790a475', From 0fed339f5ae03257b51bffb5c3391886afc53eb2 Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Thu, 17 Oct 2019 21:56:06 +0530 Subject: [PATCH 1578/1594] fix for userSync endpoint getting called with bidder alias names, instead of actual bidder names (#4265) --- modules/prebidServerBidAdapter/index.js | 9 +- .../modules/prebidServerBidAdapter_spec.js | 171 +++++++++++++----- 2 files changed, 134 insertions(+), 46 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 872e0bb81d9..93b8dc085f8 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -1,7 +1,6 @@ import Adapter from '../../src/adapter'; import { createBid } from '../../src/bidfactory'; import * as utils from '../../src/utils'; -import { ajax } from '../../src/ajax'; import { STATUS, S2S, EVENTS } from '../../src/constants'; import adapterManager from '../../src/adapterManager'; import { config } from '../../src/config'; @@ -11,6 +10,7 @@ import { isValid } from '../../src/adapters/bidderFactory'; import events from '../../src/events'; import includes from 'core-js/library/fn/array/includes'; import { S2S_VENDORS } from './config.js'; +import { ajax } from '../../src/ajax'; const getConfig = config.getConfig; @@ -148,7 +148,6 @@ function queueSync(bidderCodes, gdprConsent) { } } const jsonPayload = JSON.stringify(payload); - ajax(_s2sConfig.syncEndpoint, (response) => { try { @@ -960,7 +959,11 @@ export function PrebidServer() { if (_s2sConfig && _s2sConfig.syncEndpoint) { let consent = (Array.isArray(bidRequests) && bidRequests.length > 0) ? bidRequests[0].gdprConsent : undefined; - queueSync(_s2sConfig.bidders, consent); + let syncBidders = _s2sConfig.bidders + .map(bidder => adapterManager.aliasRegistry[bidder] || bidder) + .filter((bidder, index, array) => (array.indexOf(bidder) === index)); + + queueSync(syncBidders, consent); } const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, validAdUnits); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 658f130d144..7945be68282 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -2,10 +2,8 @@ import { expect } from 'chai'; import { PrebidServer as Adapter, resetSyncedStatus } from 'modules/prebidServerBidAdapter/index.js'; import adapterManager from 'src/adapterManager'; import * as utils from 'src/utils'; -import { userSync } from 'src/userSync'; import { ajax } from 'src/ajax'; import { config } from 'src/config'; -import { requestBidsHook } from 'modules/consentManagement'; import events from 'src/events'; import CONSTANTS from 'src/constants'; @@ -32,7 +30,7 @@ const REQUEST = { 'sizes': [[300, 250], [300, 600]], 'mediaTypes': { 'banner': { - 'sizes': [[ 300, 250 ], [ 300, 300 ]] + 'sizes': [[300, 250], [300, 300]] }, 'native': { 'title': { @@ -77,7 +75,7 @@ const VIDEO_REQUEST = { 'sizes': [640, 480], 'mediaTypes': { 'video': { - 'playerSize': [[ 640, 480 ]], + 'playerSize': [[640, 480]], 'mimes': ['video/mp4'] } }, @@ -107,7 +105,7 @@ const OUTSTREAM_VIDEO_REQUEST = { 'sizes': [640, 480], 'mediaTypes': { 'video': { - playerSize: [[ 640, 480 ]], + playerSize: [[640, 480]], context: 'outstream', mimes: ['video/mp4'] }, @@ -325,7 +323,7 @@ const RESPONSE_OPENRTB = { 'price': 0.5, 'adm': '', 'adid': '29681110', - 'adomain': [ 'appnexus.com' ], + 'adomain': ['appnexus.com'], 'iurl': 'http://lax1-ib.adnxs.com/cr?id=2968111', 'cid': '958', 'crid': '2968111', @@ -517,6 +515,11 @@ describe('S2S Adapter', function () { }, 'bid_id': '123', 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', 'sizes': [300, 250], 'bidId': '123', @@ -553,11 +556,11 @@ describe('S2S Adapter', function () { xhr.restore(); }); - it('should not add outstrean without renderer', function() { + it('should not add outstrean without renderer', function () { let ortb2Config = utils.deepClone(CONFIG); ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' - config.setConfig({s2sConfig: ortb2Config}); + config.setConfig({ s2sConfig: ortb2Config }); adapter.callBids(OUTSTREAM_VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); @@ -570,7 +573,7 @@ describe('S2S Adapter', function () { }); it('exists converts types', function () { - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid).to.have.property('cache_markup', 2); @@ -604,7 +607,7 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.consent).is.equal('abc123'); config.resetConfig(); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); requestBid = JSON.parse(requests[1].requestBody); @@ -681,7 +684,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { cacheMarkup: 999 }); - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid).to.have.property('cache_markup', 0); @@ -722,7 +725,8 @@ describe('S2S Adapter', function () { }); it('adds device and app objects to request', function () { - const _config = { s2sConfig: CONFIG, + const _config = { + s2sConfig: CONFIG, device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, app: { bundle: 'com.test.app' }, }; @@ -737,7 +741,7 @@ describe('S2S Adapter', function () { }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', - publisher: {'id': '1'} + publisher: { 'id': '1' } }); }); @@ -762,7 +766,7 @@ describe('S2S Adapter', function () { }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', - publisher: {'id': '1'} + publisher: { 'id': '1' } }); }); @@ -785,7 +789,7 @@ describe('S2S Adapter', function () { }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', - publisher: {'id': '1'} + publisher: { 'id': '1' } }); }); @@ -858,7 +862,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); const aliasBidder = { bidder: 'brealtime', @@ -889,7 +893,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); const alias = 'foobar'; const aliasBidder = { @@ -923,7 +927,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); const myRequest = utils.deepClone(REQUEST); myRequest.ad_units[0].bids[0].params.usePaymentRule = true; @@ -949,7 +953,7 @@ describe('S2S Adapter', function () { config.resetConfig(); const oldS2sConfig = Object.assign({}, CONFIG); - config.setConfig({s2sConfig: oldS2sConfig}); + config.setConfig({ s2sConfig: oldS2sConfig }); const myRequest2 = utils.deepClone(REQUEST); myRequest2.ad_units[0].bids[0].params.keywords = { @@ -1068,7 +1072,7 @@ describe('S2S Adapter', function () { let s2sConfig = utils.deepClone(CONFIG); s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; config.setConfig({ - currency: {adServerCurrency: ['USD', 'GB', 'UK', 'AU']}, + currency: { adServerCurrency: ['USD', 'GB', 'UK', 'AU'] }, s2sConfig: s2sConfig }); @@ -1083,7 +1087,7 @@ describe('S2S Adapter', function () { let s2sConfig = utils.deepClone(CONFIG); s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; config.setConfig({ - currency: {adServerCurrency: 'NZ'}, + currency: { adServerCurrency: 'NZ' }, s2sConfig: s2sConfig }); @@ -1097,7 +1101,7 @@ describe('S2S Adapter', function () { it('when config \'currency.adServerCurrency\' is unset: ORTB should not define a \'cur\' property', function () { let s2sConfig = utils.deepClone(CONFIG); s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); const bidRequests = utils.deepClone(BID_REQUESTS); adapter.callBids(REQUEST, bidRequests, addBidResponse, done, ajax); @@ -1246,7 +1250,7 @@ describe('S2S Adapter', function () { }); }); - it('passes schain object in request', function() { + it('passes schain object in request', function () { const bidRequests = utils.deepClone(BID_REQUESTS); const schainObject = { 'ver': '1.0', @@ -1298,7 +1302,7 @@ describe('S2S Adapter', function () { it('registers bids and calls BIDDER_DONE', function () { server.respondWith(JSON.stringify(RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); @@ -1321,7 +1325,7 @@ describe('S2S Adapter', function () { it('registers video bids', function () { server.respondWith(JSON.stringify(VIDEO_RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); @@ -1339,7 +1343,7 @@ describe('S2S Adapter', function () { it('does not call addBidResponse and calls done when ad unit not set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1350,7 +1354,7 @@ describe('S2S Adapter', function () { it('does not call addBidResponse and calls done when server requests cookie sync', function () { server.respondWith(JSON.stringify(RESPONSE_NO_COOKIE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1361,7 +1365,7 @@ describe('S2S Adapter', function () { it('does not call addBidResponse and calls done when ad unit is set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_UNIT_SET)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1372,7 +1376,7 @@ describe('S2S Adapter', function () { it('registers successful bids and calls done when there are less bids than requests', function () { server.respondWith(JSON.stringify(RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1390,7 +1394,7 @@ describe('S2S Adapter', function () { it('should have dealId in bidObject', function () { server.respondWith(JSON.stringify(RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); const response = addBidResponse.firstCall.args[1]; @@ -1400,11 +1404,11 @@ describe('S2S Adapter', function () { it('should pass through default adserverTargeting if present in bidObject', function () { server.respondWith(JSON.stringify(RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); const response = addBidResponse.firstCall.args[1]; - expect(response).to.have.property('adserverTargeting').that.deep.equals({'foo': 'bar'}); + expect(response).to.have.property('adserverTargeting').that.deep.equals({ 'foo': 'bar' }); }); it('registers client user syncs when client bid adapter is present', function () { @@ -1415,7 +1419,7 @@ describe('S2S Adapter', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1433,7 +1437,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); server.respondWith(JSON.stringify(RESPONSE_OPENRTB)); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -1447,7 +1451,7 @@ describe('S2S Adapter', function () { it('registers bid responses when server requests cookie sync', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); @@ -1467,7 +1471,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); server.respondWith(JSON.stringify(RESPONSE_OPENRTB)); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -1490,7 +1494,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); server.respondWith(JSON.stringify(RESPONSE_OPENRTB_VIDEO)); adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -1510,7 +1514,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); cacheResponse.seatbid.forEach(item => { item.bid[0].ext.prebid.cache = { @@ -1536,7 +1540,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); const targetingTestData = { hb_cache_path: '/cache', @@ -1564,7 +1568,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); cacheResponse.seatbid.forEach(item => { item.bid[0].ext.prebid.targeting = { @@ -1594,7 +1598,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); server.respondWith(JSON.stringify(RESPONSE_OPENRTB_NATIVE)); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -1624,7 +1628,7 @@ describe('S2S Adapter', function () { } config.setConfig(_config); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1633,13 +1637,20 @@ describe('S2S Adapter', function () { }); describe('s2sConfig', function () { + let xhr; + let requests; let logErrorSpy; beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); logErrorSpy = sinon.spy(utils, 'logError'); + resetSyncedStatus(); }); afterEach(function () { + xhr.restore(); utils.logError.restore(); }); @@ -1792,11 +1803,85 @@ describe('S2S Adapter', function () { config.setConfig({ s2sConfig: { syncUrlModifier: { - appnexus: () => {} + appnexus: () => { } } } }); expect(typeof config.getConfig('s2sConfig').syncUrlModifier.appnexus).to.equal('function') }); + + it('should set correct bidder names to bidders property when using an alias for that bidder', function () { + const s2sConfig = utils.deepClone(CONFIG); + + // 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 = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + s2sConfig.bidders = ['appnexus', 'rubicon-alias']; + + const request = utils.deepClone(REQUEST); + + // Add another bidder, `rubicon-alias` + request.ad_units[0].bids.push({ + bidder: 'rubicon-alias', + params: { + accoundId: 14062, + siteId: 70608, + zoneId: 498816 + } + }); + + // create an alias for the Rubicon Bid Adapter + adapterManager.aliasBidAdapter('rubicon', 'rubicon-alias'); + + config.setConfig({ s2sConfig }); + + const bidRequest = utils.deepClone(BID_REQUESTS); + bidRequest.push({ + 'bidderCode': 'rubicon-alias', + 'auctionId': '4146ab2b-9422-4040-9b1c-966fffbfe2d4', + 'bidderRequestId': '4b1a4f9c3e4546', + 'tid': 'd7fa8342-ae22-4ca1-b237-331169350f84', + 'bids': [ + { + 'bidder': 'rubicon-alias', + 'params': { + 'accountId': 14062, + 'siteId': 70608, + 'zoneId': 498816 + }, + 'bid_id': '2a9523915411c3', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ + 300, + 250 + ] + ] + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '78ddc106-b7d8-45d1-bd29-86993098e53d', + 'sizes': [ + [ + 300, + 250 + ] + ], + 'bidId': '2a9523915411c3', + 'bidderRequestId': '4b1a4f9c3e4546', + 'auctionId': '4146ab2b-9422-4040-9b1c-966fffbfe2d4' + } + ], + 'auctionStart': 1569234122602, + 'timeout': 1000, + 'src': 's2s' + }); + + adapter.callBids(request, bidRequest, addBidResponse, done, ajax); + + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.bidders).to.deep.equal(['appnexus', 'rubicon']); + }); }); }); From 315bd196b252124e3c21c56ac15d42eb3f7d438f Mon Sep 17 00:00:00 2001 From: Index Exchange 3 Prebid Team Date: Thu, 17 Oct 2019 13:11:20 -0400 Subject: [PATCH 1579/1594] modify ixBidAdapater to always use the secure endpoint (#4323) --- modules/ixBidAdapter.js | 10 +--------- test/spec/modules/ixBidAdapter_spec.js | 3 +-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index 8d76d862655..85d3be2f0ec 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -6,7 +6,6 @@ import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'ix'; const BANNER_SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; -const BANNER_INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; const SUPPORTED_AD_TYPES = [BANNER]; const ENDPOINT_VERSION = 7.2; const CENT_TO_DOLLAR_FACTOR = 100; @@ -188,10 +187,7 @@ export const spec = { let validBidRequest = null; let bannerImp = null; - // Always start by assuming the protocol is HTTPS. This way, it will work - // whether the page protocol is HTTP or HTTPS. Then check if the page is - // actually HTTP.If we can guarantee it is, then, and only then, set protocol to - // HTTP. + // Always use secure HTTPS protocol. let baseUrl = BANNER_SECURE_BID_URL; for (let i = 0; i < validBidRequests.length; i++) { @@ -258,10 +254,6 @@ export const spec = { if (options.refererInfo) { r.site.page = options.refererInfo.referer; - - if (options.refererInfo.referer && options.refererInfo.referer.indexOf('https') !== 0) { - baseUrl = BANNER_INSECURE_BID_URL; - } } } diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 38e64e8d338..120d02408d7 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -5,7 +5,6 @@ import { newBidder } from 'src/adapters/bidderFactory'; import { spec } from 'modules/ixBidAdapter'; describe('IndexexchangeAdapter', function () { - const IX_INSECURE_ENDPOINT = 'http://as.casalemedia.com/cygnus'; const IX_SECURE_ENDPOINT = 'https://as-sec.casalemedia.com/cygnus'; const BIDDER_VERSION = 7.2; @@ -401,7 +400,7 @@ describe('IndexexchangeAdapter', function () { it('request should be made to IX endpoint with GET method', function () { expect(requestMethod).to.equal('GET'); - expect(requestUrl).to.equal(IX_INSECURE_ENDPOINT); + expect(requestUrl).to.equal(IX_SECURE_ENDPOINT); }); it('query object (version, siteID and request) should be correct', function () { From 64bd8512dd36b4712bd9e53dbef86cf2b1ad8638 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Thu, 17 Oct 2019 10:33:52 -0700 Subject: [PATCH 1580/1594] PubMatic to support Parrable User Id sub-module (#4324) * added support for pubcommon, digitrust, id5id * added support for IdentityLink * changed the source for id5 * added unit test cases * changed source param for identityLink * PubMatic to support parrable id --- modules/pubmaticBidAdapter.js | 1 + test/spec/modules/pubmaticBidAdapter_spec.js | 36 ++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 58d8d773dae..59f0f7a7db8 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -651,6 +651,7 @@ function _handleEids(payload, validBidRequests) { _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.criteortus.${BIDDER_CODE}.userid`), 'criteortus', 1); _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.idl_env`), 'liveramp.com', 1); _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.lipb.lipbid`), 'liveintent.com', 1); + _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.parrableid`), 'parrable.com', 1); } if (eids.length > 0) { payload.user.eids = eids; diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 22c0f840026..32fdd774518 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1696,6 +1696,42 @@ describe('PubMatic adapter', function () { expect(data.user.eids).to.equal(undefined); }); }); + + describe('Parrable Id', function() { + it('send the Parrable id if it is present', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.parrableid = 'parrable-user-id'; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'parrable.com', + 'uids': [{ + 'id': 'parrable-user-id', + 'atype': 1 + }] + }]); + }); + + it('do not pass if not string', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.parrableid = 1; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.parrableid = []; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.parrableid = null; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.parrableid = {}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + }); + }); }); it('Request params check for video ad', function () { From b89d006abaec11b028422835c14776db68ed2724 Mon Sep 17 00:00:00 2001 From: Michael Kuryshev Date: Fri, 18 Oct 2019 21:45:30 +0200 Subject: [PATCH 1581/1594] VISX: currency validation & fix double escape of referer (#4299) --- modules/visxBidAdapter.js | 83 ++++++++++++++---------- test/spec/modules/visxBidAdapter_spec.js | 52 ++++++++------- 2 files changed, 75 insertions(+), 60 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 2f9ec73c569..15334e46e31 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -15,8 +15,11 @@ const LOG_ERROR_MESS = { emptySeatbid: 'Seatbid array from response has an empty item', emptyResponse: 'Response is empty', hasEmptySeatbidArray: 'Response has empty seatbid array', - hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ', + notAllowedCurrency: 'Currency is not supported - ', + currencyMismatch: 'Currency from the request is not match currency from the response - ' }; +const currencyWhiteList = ['EUR', 'USD', 'GBP', 'PLN']; export const spec = { code: BIDDER_CODE, isBidRequestValid: function(bid) { @@ -34,6 +37,11 @@ export const spec = { DEFAULT_CUR; let reqId; + if (currencyWhiteList.indexOf(currency) === -1) { + utils.logError(LOG_ERROR_MESS.notAllowedCurrency + currency); + return; + } + bids.forEach(bid => { reqId = bid.bidderRequestId; const {params: {uid}, adUnitCode} = bid; @@ -78,7 +86,7 @@ export const spec = { if (bidderRequest) { if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + payload.u = bidderRequest.refererInfo.referer; } if (bidderRequest.gdprConsent) { if (bidderRequest.gdprConsent.consentString) { @@ -158,43 +166,48 @@ function _addBidResponse(serverBid, bidsMap, currency, bidResponses, bidsWithout if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); else { + const reqCurrency = currency || DEFAULT_CUR; const awaitingBids = bidsMap[serverBid.auid]; if (awaitingBids) { - 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(); - bidResponses.push({ - requestId: bid.bidId, - bidderCode: spec.code, - cpm: serverBid.price, - width: serverBid.w, - height: serverBid.h, - creativeId: serverBid.auid, - currency: currency || DEFAULT_CUR, - netRevenue: true, - ttl: TIME_TO_LIVE, - ad: serverBid.adm, - dealId: serverBid.dealid - }); - - 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 (!utils.getKeys(parent).length) { - delete bidsMap[uid]; - } - } + if (serverBid.cur && serverBid.cur !== reqCurrency) { + errorMessage = LOG_ERROR_MESS.currencyMismatch + reqCurrency + ' - ' + serverBid.cur; + } else { + 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(); + bidResponses.push({ + requestId: bid.bidId, + bidderCode: spec.code, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, + currency: reqCurrency, + netRevenue: true, + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid }); + + 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 (!utils.getKeys(parent).length) { + delete bidsMap[uid]; + } + } + }); + } + } else { + bidsWithoutSizeMatching && bidsWithoutSizeMatching.push(serverBid); } - } else { - bidsWithoutSizeMatching && bidsWithoutSizeMatching.push(serverBid); } } else { errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 09ce92479f9..167d54e37a6 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -45,7 +45,7 @@ describe('VisxAdapter', function () { referer: 'http://example.com' } }; - const encodedReferrer = encodeURIComponent(bidderRequest.refererInfo.referer); + const referrer = bidderRequest.refererInfo.referer; let bidRequests = [ { 'bidder': 'visx', @@ -86,7 +86,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests([bidRequests[0]], bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + 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'); @@ -98,7 +98,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -111,7 +111,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -124,7 +124,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -138,7 +138,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -149,16 +149,16 @@ describe('VisxAdapter', function () { it('should add currency from currency.bidderCurrencyDefault', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( - arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'JPY' : 'USD'); + arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'GBP' : 'USD'); const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'JPY'); + expect(payload).to.have.property('cur', 'GBP'); getConfigStub.restore(); }); @@ -168,7 +168,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -204,11 +204,11 @@ describe('VisxAdapter', function () { describe('interpretResponse', function () { const responses = [ - {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903536, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
    test content 3
    ', 'auid': 903535, 'h': 90, 'w': 728}], 'seat': '1'}, - {'bid': [{'price': 0, 'auid': 903537, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0, 'adm': '
    test content 5
    ', 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 3
    ', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR'}], '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'}, {'seat': '1'}, @@ -346,7 +346,7 @@ describe('VisxAdapter', function () { 'auctionId': '1cbd2feafe5e8b', } ]; - const getConfigStub = sinon.stub(config, 'getConfig').returns('JPY'); + const getConfigStub = sinon.stub(config, 'getConfig').returns('PLN'); const request = spec.buildRequests(bidRequests); const expectedResponse = [ { @@ -358,13 +358,15 @@ describe('VisxAdapter', function () { 'height': 250, 'ad': '
    test content 1
    ', 'bidderCode': 'visx', - 'currency': 'JPY', + 'currency': 'PLN', 'netRevenue': true, 'ttl': 360, } ]; - const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + const response = Object.assign({}, responses[0]); + Object.assign(response.bid[0], {'cur': 'PLN'}); + const result = spec.interpretResponse({'body': {'seatbid': [response]}}, request); expect(result).to.deep.equal(expectedResponse); getConfigStub.restore(); }); @@ -412,11 +414,11 @@ describe('VisxAdapter', function () { it('complicated case', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903536, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
    test content 3
    ', 'auid': 903535, 'h': 90, 'w': 728}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
    test content 4
    ', 'auid': 903535, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
    test content 5
    ', 'auid': 903536, 'h': 600, 'w': 350}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 3
    ', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
    test content 4
    ', 'auid': 903535, 'h': 600, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 5
    ', 'auid': 903536, 'h': 600, 'w': 350, 'cur': 'EUR'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -550,8 +552,8 @@ describe('VisxAdapter', function () { it('dublicate uids and sizes in one slot', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
    test content 1
    ', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
    test content 2
    ', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, ]; const bidRequests = [ { From cde90dcba4db9b2b9cdaffd7ef87b9131c3e6fc4 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Sun, 20 Oct 2019 18:29:18 -0700 Subject: [PATCH 1582/1594] PubMatic to support coppa (#4336) * added support for pubcommon, digitrust, id5id * added support for IdentityLink * changed the source for id5 * added unit test cases * changed source param for identityLink * added coppa compliance --- modules/pubmaticBidAdapter.js | 10 +++++ test/spec/modules/pubmaticBidAdapter_spec.js | 40 ++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 59f0f7a7db8..51cebebf6e4 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -920,6 +920,11 @@ export const spec = { }; } + // coppa compliance + if (config.getConfig('coppa') === true) { + utils.deepSetValue(payload, 'regs.coppa', 1); + } + _handleDealCustomTargetings(payload, dctrArr, validBidRequests); _handleEids(payload, validBidRequests); _blockedIabCategoriesValidation(payload, blockedIabCategories); @@ -1019,6 +1024,11 @@ export const spec = { syncurl += '&gdpr_consent=' + encodeURIComponent(gdprConsent.consentString || ''); } + // coppa compliance + if (config.getConfig('coppa') === true) { + syncurl += '&coppa=1'; + } + if (syncOptions.iframeEnabled) { return [{ type: 'iframe', diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 32fdd774518..feb64dfe4ac 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1171,6 +1171,46 @@ describe('PubMatic adapter', function () { // should have called DigiTrust.getUser() once expect(window.DigiTrust.getUser.calledOnce).to.equal(true); }); + + it('should NOT include coppa flag in bid request if coppa config is not present', () => { + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + if (data.regs) { + // in case GDPR is set then data.regs will exist + expect(data.regs.coppa).to.equal(undefined); + } else { + expect(data.regs).to.equal(undefined); + } + }); + + it('should include coppa flag in bid request if coppa is set to true', () => { + sandbox.stub(config, 'getConfig').callsFake(key => { + const config = { + 'coppa': true + }; + return config[key]; + }); + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.regs.coppa).to.equal(1); + }); + + it('should NOT include coppa flag in bid request if coppa is set to false', () => { + sandbox.stub(config, 'getConfig').callsFake(key => { + const config = { + 'coppa': false + }; + return config[key]; + }); + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + if (data.regs) { + // in case GDPR is set then data.regs will exist + expect(data.regs.coppa).to.equal(undefined); + } else { + expect(data.regs).to.equal(undefined); + } + }); }); describe('AdsrvrOrgId from config', function() { From ab91441d6c8b1f35ef0c5ec77a3c8bbf3afb14bc Mon Sep 17 00:00:00 2001 From: Roffray Date: Mon, 21 Oct 2019 03:40:16 +0200 Subject: [PATCH 1583/1594] vuble: outstream has fullscreen option (#4320) * Mod: vuble oustream has fullscreen option * Add: vuble test for outstream scenario --- modules/vubleBidAdapter.js | 2 +- test/spec/modules/vubleBidAdapter_spec.js | 52 +++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/modules/vubleBidAdapter.js b/modules/vubleBidAdapter.js index 80d62d21842..63f817358de 100644 --- a/modules/vubleBidAdapter.js +++ b/modules/vubleBidAdapter.js @@ -23,7 +23,7 @@ const outstreamRender = bid => { showBigPlayButton: false, showProgressBar: 'bar', showVolume: false, - allowFullscreen: false, + allowFullscreen: true, skippable: false, } }); diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 8996c1b4957..b38ad8f8584 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -280,4 +280,56 @@ describe('VubleAdapter', function () { expect(adapter.getUserSyncs(syncOptions, [response])).to.deep.equal([result]); }) }); + + describe('Check outstream scenario with renderer', function () { + // bid Request + let bid = { + data: { + context: 'outstream', + env: 'net', + width: '640', + height: '360', + pub_id: '3', + zone_id: '12345', + bid_id: 'abdc', + floor_price: 5.50, // optional + adUnitCode: 'code' + }, + method: 'POST', + url: '//player.mediabong.net/prebid/request' + }; + // Server's response + let response = { + body: { + status: 'ok', + cpm: 5.00, + creativeId: '2468', + url: 'https//player.mediabong.net/prebid/ad/a1b2c3d4', + dealId: 'MDB-TEST-1357', + renderer_id: 0, + renderer_url: 'vuble_renderer.js', + content: 'test' + } + }; + + let adResponse = { + ad: { + video: { + content: 'test' + } + } + }; + let adUnitCode = 'code'; + let rendererUrl = 'vuble_renderer.js'; + let rendererId = 0; + + let formattedResponses = adapter.interpretResponse(response, bid); + it('should equal to the expected format result', function () { + expect(formattedResponses[0].adResponse).to.deep.equal(adResponse); + expect(formattedResponses[0].adUnitCode).to.deep.equal(adUnitCode); + expect(formattedResponses[0].renderer.url).to.equal(rendererUrl); + expect(formattedResponses[0].renderer.id).to.equal(rendererId); + expect(formattedResponses[0].renderer.render).to.exist.and.to.be.a('function'); + }); + }); }); From f919f581ab13c23954ae82850ec36f24951e0f31 Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Mon, 21 Oct 2019 09:06:52 -0400 Subject: [PATCH 1584/1594] EMXDigital: hotfix to resolve URIError from decodeURIComponent (#4333) * hotfix to resolve URIError from decodeURIComponent * added unit for decoding adm --- modules/emx_digitalBidAdapter.js | 4 ++-- test/spec/modules/emx_digitalBidAdapter_spec.js | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 12f3482184b..7167f9018aa 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -7,7 +7,7 @@ import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; const ENDPOINT = 'hb.emxdgt.com'; const RENDERER_URL = '//js.brealtime.com/outstream/1.30.0/bundle.js'; -const ADAPTER_VERSION = '1.41.0'; +const ADAPTER_VERSION = '1.41.1'; const DEFAULT_CUR = 'USD'; export const emxAdapter = { @@ -116,7 +116,7 @@ export const emxAdapter = { }, parseResponse: (bidResponseAdm) => { try { - return decodeURIComponent(bidResponseAdm); + return decodeURIComponent(bidResponseAdm.replace(/%(?![0-9][0-9a-fA-F]+)/g, '%25')); } catch (err) { utils.logError('emx_digitalBidAdapter', 'error', err); } diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js index 16f17174f88..80fd12a237c 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -527,6 +527,15 @@ describe('emx_digital Adapter', function () { }); expect(result.length).to.equal(0); }); + + it('should not throw an error when decoding an improperly encoded adm', function () { + serverResponse.seatbid[0].bid[0].adm = '\\<\\/script\\>'; + serverResponse.seatbid[1].bid[0].adm = '%3F%%3Demx%3C3prebid' + + assert.doesNotThrow(() => spec.interpretResponse({ + body: serverResponse + })); + }); }); describe('getUserSyncs', function () { From 56d6c59ec1614c1c43f734b19832851d2a9e0b75 Mon Sep 17 00:00:00 2001 From: rumesh Date: Mon, 21 Oct 2019 20:13:37 +0000 Subject: [PATCH 1585/1594] Specify second parameter for parseInt for pubmaticBidAdapter (#4347) --- modules/pubmaticBidAdapter.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 51cebebf6e4..73e6d8cfb52 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -174,8 +174,8 @@ function _parseAdSlot(bid) { utils.logWarn(LOG_WARN_PREFIX + 'AdSlot Error: adSlot not in required format'); return; } - bid.params.width = parseInt(splits[0]); - bid.params.height = parseInt(splits[1]); + bid.params.width = parseInt(splits[0], 10); + bid.params.height = parseInt(splits[1], 10); } else if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(BANNER) && bid.mediaTypes.banner.hasOwnProperty('sizes')) { @@ -441,8 +441,8 @@ function _createBannerRequest(bid) { 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]); - bannerObj.h = parseInt(sizes[0][1]); + bannerObj.w = parseInt(sizes[0][0], 10); + bannerObj.h = parseInt(sizes[0][1], 10); sizes = sizes.splice(1, sizes.length - 1); } } else { @@ -482,11 +482,11 @@ function _createVideoRequest(bid) { } // read playersize and assign to h and w. if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { - videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0][0]); - videoObj.h = parseInt(bid.mediaTypes.video.playerSize[0][1]); + videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0][0], 10); + videoObj.h = parseInt(bid.mediaTypes.video.playerSize[0][1], 10); } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { - videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0]); - videoObj.h = parseInt(bid.mediaTypes.video.playerSize[1]); + videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0], 10); + videoObj.h = parseInt(bid.mediaTypes.video.playerSize[1], 10); } if (bid.params.video.hasOwnProperty('skippable')) { videoObj.ext = { From a65a11b3b0b63d9a454e64c210844b3e2179107c Mon Sep 17 00:00:00 2001 From: oasis <2394426+bmwcmw@users.noreply.github.com> Date: Tue, 22 Oct 2019 11:42:04 +0200 Subject: [PATCH 1586/1594] Remove usage of getTopWindowUrl in Prebid Adapter (#4341) --- modules/criteoBidAdapter.js | 16 +++++--- test/spec/modules/criteoBidAdapter_spec.js | 45 +++++++++++++++++----- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 86f289421ce..7f292c76e20 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -8,7 +8,7 @@ import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -export const ADAPTER_VERSION = 21; +export const ADAPTER_VERSION = 23; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = 'https://bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -79,7 +79,7 @@ export const spec = { url = adapter.buildCdbUrl(); data = adapter.buildCdbRequest(); } else { - const context = buildContext(bidRequests); + const context = buildContext(bidRequests, bidderRequest); url = buildCdbUrl(context); data = buildCdbRequest(context, bidRequests, bidderRequest); } @@ -177,14 +177,18 @@ function publisherTagAvailable() { /** * @param {BidRequest[]} bidRequests + * @param bidderRequest * @return {CriteoContext} */ -function buildContext(bidRequests) { - const url = utils.getTopWindowUrl(); - const queryString = parse(url).search; +function buildContext(bidRequests, bidderRequest) { + let referrer = ''; + if (bidderRequest && bidderRequest.refererInfo) { + referrer = bidderRequest.refererInfo.referer; + } + const queryString = parse(referrer).search; const context = { - url: url, + url: referrer, debug: queryString['pbt_debug'] === '1', noLog: queryString['pbt_nolog'] === '1', amp: false, diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 03500d4add6..e5d789ff60d 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -368,7 +368,11 @@ describe('The Criteo bidding adapter', function () { }); describe('buildRequests', function () { + const refererUrl = 'https://criteo.com?pbt_debug=1&pbt_nolog=1'; const bidderRequest = { + refererInfo: { + referer: refererUrl + }, timeout: 3000, gdprConsent: { gdprApplies: 1, @@ -385,10 +389,23 @@ describe('The Criteo bidding adapter', function () { config.resetConfig(); }); - it('should properly build a zoneId request', function () { - const publisherUrl = 'https://criteo.com?pbt_debug=1&pbt_nolog=1'; - utilsMock.expects('getTopWindowUrl').withExactArgs().once().returns(publisherUrl); + it('should properly build a request if refererInfo is not provided', function () { + const bidderRequest = {}; + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + params: {} + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request.data; + expect(ortbRequest.publisher.url).to.equal(''); + }); + it('should properly build a zoneId request', function () { const bidRequests = [ { bidder: 'criteo', @@ -407,7 +424,7 @@ describe('The Criteo bidding adapter', function () { expect(request.url).to.match(/^https:\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d+&im=1&debug=1&nolog=1/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; - expect(ortbRequest.publisher.url).to.equal(publisherUrl); + expect(ortbRequest.publisher.url).to.equal(refererUrl); expect(ortbRequest.slots).to.have.lengthOf(1); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); @@ -421,6 +438,9 @@ describe('The Criteo bidding adapter', function () { it('should properly build a networkId request', function () { const bidderRequest = { + refererInfo: { + referer: refererUrl + }, timeout: 3000, gdprConsent: { gdprApplies: 0, @@ -451,7 +471,7 @@ 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.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.url).to.equal(refererUrl); expect(ortbRequest.publisher.networkid).to.equal(456); expect(ortbRequest.slots).to.have.lengthOf(1); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); @@ -465,7 +485,12 @@ describe('The Criteo bidding adapter', function () { }); it('should properly build a mixed request', function () { - const bidderRequest = { timeout: 3000 }; + const bidderRequest = { + refererInfo: { + referer: refererUrl + }, + timeout: 3000 + }; const bidRequests = [ { bidder: 'criteo', @@ -490,7 +515,7 @@ 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.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.url).to.equal(refererUrl); expect(ortbRequest.publisher.networkid).to.equal(456); expect(ortbRequest.slots).to.have.lengthOf(2); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); @@ -517,9 +542,9 @@ describe('The Criteo bidding adapter', function () { }, }, ]; - const bidderRequest = { timeout: 3000, - gdprConsent: { - }, + const bidderRequest = { + timeout: 3000, + gdprConsent: {}, }; const ortbRequest = spec.buildRequests(bidRequests, bidderRequest).data; From b5f3c995d827d1af3e3aa0dbd71d57618335f1c2 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Tue, 22 Oct 2019 05:40:58 -0700 Subject: [PATCH 1587/1594] Conversant Bid Adapter update for 3.0 (#4284) --- modules/conversantBidAdapter.js | 13 +++--- modules/conversantBidAdapter.md | 6 ++- .../spec/modules/conversantBidAdapter_spec.js | 40 +++++++++---------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index 00ca6a7bbd6..a3479a9d1d1 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory'; import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'conversant'; -const URL = '//web.hb.ad.cpe.dotomi.com/s2s/header/24'; +const URL = 'https://web.hb.ad.cpe.dotomi.com/s2s/header/24'; export const spec = { code: BIDDER_CODE, @@ -44,26 +44,24 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {BidRequest[]} validBidRequests - an array of bids + * @param bidderRequest * @return {ServerRequest} Info describing the request to the server. */ buildRequests: function(validBidRequests, bidderRequest) { - const loc = utils.getTopWindowLocation(); - const page = loc.href; - const isPageSecure = (loc.protocol === 'https:') ? 1 : 0; + const page = (bidderRequest && bidderRequest.refererInfo) ? bidderRequest.refererInfo.referer : ''; let siteId = ''; let requestId = ''; let pubcid = null; const conversantImps = validBidRequests.map(function(bid) { const bidfloor = utils.getBidIdParameter('bidfloor', bid.params); - const secure = isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0); siteId = utils.getBidIdParameter('site_id', bid.params); requestId = bid.auctionId; const imp = { id: bid.bidId, - secure: secure, + secure: 1, bidfloor: bidfloor || 0, displaymanager: 'Prebid.js', displaymanagerver: '$prebid.version$' @@ -154,6 +152,7 @@ export const spec = { * Unpack the response from the server into a list of bids. * * @param {*} serverResponse A successful response from the server. + * @param bidRequest * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: function(serverResponse, bidRequest) { @@ -249,7 +248,7 @@ function getDevice() { * * [[300, 250], [300, 600]] => [{w: 300, h: 250}, {w: 300, h: 600}] * - * @param {number[2][]|number[2]} bidSizes - arrays of widths and heights + * @param {Array.>} bidSizes - arrays of widths and heights * @returns {object[]} Array of objects with w and h */ function convertSizes(bidSizes) { diff --git a/modules/conversantBidAdapter.md b/modules/conversantBidAdapter.md index 3ce83d8c893..5aba5653043 100644 --- a/modules/conversantBidAdapter.md +++ b/modules/conversantBidAdapter.md @@ -13,7 +13,11 @@ Module that connects to Conversant's demand sources. Supports banners and video var adUnits = [ { code: 'banner-test-div', - sizes: [[300, 250]], + mediaTypes: { + banner: { + sizes: [[300, 250],[300,600]] + } + }, bids: [{ bidder: "conversant", params: { diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index aeadc3bf828..6c9f0c8e6e5 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} from 'modules/conversantBidAdapter'; import * as utils from 'src/utils'; -var Adapter = require('modules/conversantBidAdapter'); - describe('Conversant adapter tests', function() { const siteId = '108060'; const versionPattern = /^\d+\.\d+\.\d+(.)*$/; @@ -16,7 +14,6 @@ describe('Conversant adapter tests', function() { site_id: siteId, position: 1, tag_id: 'tagid-1', - secure: false, bidfloor: 0.5 }, placementCode: 'pcode000', @@ -30,8 +27,7 @@ describe('Conversant adapter tests', function() { { bidder: 'conversant', params: { - site_id: siteId, - secure: false + site_id: siteId }, mediaTypes: { banner: { @@ -50,8 +46,7 @@ describe('Conversant adapter tests', function() { params: { site_id: siteId, position: 2, - tag_id: '', - secure: false + tag_id: '' }, placementCode: 'pcode002', transactionId: 'tx002', @@ -198,9 +193,15 @@ describe('Conversant adapter tests', function() { }); it('Verify buildRequest', function() { - const request = spec.buildRequests(bidRequests); + const page = 'http://test.com?a=b&c=123'; + const bidderRequest = { + refererInfo: { + referer: page + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.method).to.equal('POST'); - expect(request.url).to.equal('//web.hb.ad.cpe.dotomi.com/s2s/header/24'); + expect(request.url).to.equal('https://web.hb.ad.cpe.dotomi.com/s2s/header/24'); const payload = request.data; expect(payload).to.have.property('id', 'req000'); @@ -209,7 +210,7 @@ describe('Conversant adapter tests', function() { 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', 0); + expect(payload.imp[0]).to.have.property('secure', 1); expect(payload.imp[0]).to.have.property('bidfloor', 0.5); expect(payload.imp[0]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -221,7 +222,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[0]).to.not.have.property('video'); expect(payload.imp[1]).to.have.property('id', 'bid001'); - expect(payload.imp[1]).to.have.property('secure', 0); + expect(payload.imp[1]).to.have.property('secure', 1); expect(payload.imp[1]).to.have.property('bidfloor', 0); expect(payload.imp[1]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[1]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -232,7 +233,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[1].banner.format).to.deep.equal([{w: 728, h: 90}, {w: 468, h: 60}]); expect(payload.imp[2]).to.have.property('id', 'bid002'); - expect(payload.imp[2]).to.have.property('secure', 0); + expect(payload.imp[2]).to.have.property('secure', 1); expect(payload.imp[2]).to.have.property('bidfloor', 0); expect(payload.imp[2]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[2]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -242,7 +243,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[2].banner.format).to.deep.equal([{w: 300, h: 600}, {w: 160, h: 600}]); expect(payload.imp[3]).to.have.property('id', 'bid003'); - expect(payload.imp[3]).to.have.property('secure', 0); + expect(payload.imp[3]).to.have.property('secure', 1); expect(payload.imp[3]).to.have.property('bidfloor', 0); expect(payload.imp[3]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[3]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -261,7 +262,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[3]).to.not.have.property('banner'); expect(payload.imp[4]).to.have.property('id', 'bid004'); - expect(payload.imp[4]).to.have.property('secure', 0); + expect(payload.imp[4]).to.have.property('secure', 1); expect(payload.imp[4]).to.have.property('bidfloor', 0); expect(payload.imp[4]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[4]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -280,7 +281,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[4]).to.not.have.property('banner'); expect(payload.imp[5]).to.have.property('id', 'bid005'); - expect(payload.imp[5]).to.have.property('secure', 0); + expect(payload.imp[5]).to.have.property('secure', 1); expect(payload.imp[5]).to.have.property('bidfloor', 0); expect(payload.imp[5]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[5]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -299,8 +300,7 @@ describe('Conversant adapter tests', function() { 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]); - const loc = utils.getTopWindowLocation(); - const page = loc.href; + expect(payload.site).to.have.property('page', page); expect(payload).to.have.property('device'); @@ -365,7 +365,7 @@ describe('Conversant adapter tests', function() { it('Verify publisher commond id support', function() { // clone bidRequests - let requests = utils.deepClone(bidRequests) + let requests = utils.deepClone(bidRequests); // add pubcid to every entry requests.forEach((unit) => { @@ -378,7 +378,7 @@ describe('Conversant adapter tests', function() { it('Verify User ID publisher commond id support', function() { // clone bidRequests - let requests = utils.deepClone(bidRequests) + let requests = utils.deepClone(bidRequests); // add pubcid to every entry requests.forEach((unit) => { @@ -415,4 +415,4 @@ describe('Conversant adapter tests', function() { expect(payload).to.have.deep.nested.property('user.ext.consent', ''); expect(payload).to.not.have.deep.nested.property('regs.ext.gdpr'); }); -}) +}); From f92650f022463ed16fc9faaaadb279d14819ce95 Mon Sep 17 00:00:00 2001 From: Nepomuk Seiler Date: Tue, 22 Oct 2019 17:32:18 +0200 Subject: [PATCH 1588/1594] Add cpmDistribution function for Google Analytics adapter (#4240) * Add cpmDistribution function for Google Analytics adapter * Add test for the cpmDistribution function * Remove half written comment --- modules/googleAnalyticsAdapter.js | 12 ++++++ modules/googleAnalyticsAdapter.md | 37 +++++++++++++++++++ .../modules/googleAnalyticsAdapter_spec.js | 18 +++++++-- 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 modules/googleAnalyticsAdapter.md diff --git a/modules/googleAnalyticsAdapter.js b/modules/googleAnalyticsAdapter.js index c1c16019449..2e569cd7ba1 100644 --- a/modules/googleAnalyticsAdapter.js +++ b/modules/googleAnalyticsAdapter.js @@ -19,6 +19,7 @@ var _enableCheck = true; var _category = 'Prebid.js Bids'; var _eventCount = 0; var _enableDistribution = false; +var _cpmDistribution = null; var _trackerSend = null; var _sampled = true; @@ -42,6 +43,9 @@ adapter.enableAnalytics = function ({ provider, options }) { if (options && typeof options.enableDistribution !== 'undefined') { _enableDistribution = options.enableDistribution; } + if (options && typeof options.cpmDistribution === 'function') { + _cpmDistribution = options.cpmDistribution; + } var bid = null; @@ -166,6 +170,9 @@ function getLoadTimeDistribution(time) { } function getCpmDistribution(cpm) { + if (_cpmDistribution) { + return _cpmDistribution(cpm); + } var distribution; if (cpm >= 0 && cpm < 0.5) { distribution = '$0-0.5'; @@ -255,6 +262,11 @@ function sendBidWonToGa(bid) { checkAnalytics(); } +/** + * Exposed for testing purposes + */ +adapter.getCpmDistribution = getCpmDistribution; + adapterManager.registerAnalyticsAdapter({ adapter, code: 'ga' diff --git a/modules/googleAnalyticsAdapter.md b/modules/googleAnalyticsAdapter.md new file mode 100644 index 00000000000..08423a1d492 --- /dev/null +++ b/modules/googleAnalyticsAdapter.md @@ -0,0 +1,37 @@ +# Google Analytics Adapter + +The google analytics adapter pushes prebid events into google analytics. + +## Usage + +The simplest way to enable the analytics adapter is this + +```javascript +pbjs.enableAnalytics([{ + provider: 'ga' +}]); +``` + +Defaults will be used and you should see events being pushed to analytics. + +You can customize the adapter with various `options` like this + +```javascript +pbjs.enableAnalytics([{ + provider: 'ga', + options: { ... } +}]); + +Here is a full list of settings available + +- `global` (string) - name of the global analytics object. Default is `ga` +- `trackerName` (string) - use another tracker for prebid events. Default is the default tracker +- `sampling` (number) - choose a value from `0` to `1`, where `0` means 0% and `1` means 100% tracked +- `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 + + +## Additional resources + +- [Prebid GA Analytics](http://prebid.org/overview/ga-analytics.html) diff --git a/test/spec/modules/googleAnalyticsAdapter_spec.js b/test/spec/modules/googleAnalyticsAdapter_spec.js index 20517f4138d..6bc0d4e192d 100644 --- a/test/spec/modules/googleAnalyticsAdapter_spec.js +++ b/test/spec/modules/googleAnalyticsAdapter_spec.js @@ -4,12 +4,24 @@ var assert = require('assert'); describe('Ga', function () { describe('enableAnalytics', function () { - it('should accept a tracker name option and output prefixed send string', function () { - var config = { options: { trackerName: 'foo' } }; - ga.enableAnalytics(config); + var cpmDistribution = function(cpm) { + return cpm <= 1 ? '<= 1$' : '> 1$'; + } + var config = { options: { trackerName: 'foo', enableDistribution: true, cpmDistribution: cpmDistribution } }; + + // enableAnalytics can only be called once + ga.enableAnalytics(config); + it('should accept a tracker name option and output prefixed send string', function () { var output = ga.getTrackerSend(); assert.equal(output, 'foo.send'); }); + + it('should use the custom cpm distribution', function() { + assert.equal(ga.getCpmDistribution(0.5), '<= 1$'); + assert.equal(ga.getCpmDistribution(1), '<= 1$'); + assert.equal(ga.getCpmDistribution(2), '> 1$'); + assert.equal(ga.getCpmDistribution(5.23), '> 1$'); + }); }); }); From 2318453cc97df8e904bf433bf4848f40f91260b7 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 22 Oct 2019 10:30:18 -0700 Subject: [PATCH 1589/1594] fixing SRA p_pos (#4337) --- modules/rubiconBidAdapter.js | 5 ++- test/spec/modules/rubiconBidAdapter_spec.js | 36 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index cc17e259695..7885158425b 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -410,9 +410,8 @@ export const spec = { }; // add p_pos only if specified and valid - if (params.position === 'atf' || params.position === 'btf') { - data['p_pos'] = params.position; - } + // For SRA we need to explicitly put empty semi colons so AE treats it as empty, instead of copying the latter value + data['p_pos'] = (params.position === 'atf' || params.position === 'btf') ? params.position : ''; if ((bidRequest.userId || {}).tdid) { data['tpid_tdid'] = bidRequest.userId.tdid; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 4688f0f5d32..0390d4598ae 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -375,6 +375,42 @@ describe('the rubicon adapter', function () { expect(data['p_pos']).to.equal(undefined); }); + it('should correctly send p_pos in sra fashion', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + const config = { + 'rubicon.singleRequest': true + }; + return config[key]; + }); + // first one is atf + var sraPosRequest = utils.deepClone(bidderRequest); + + // second is not present + const bidCopy = utils.deepClone(sraPosRequest.bids[0]); + delete bidCopy.params.position; + sraPosRequest.bids.push(bidCopy); + + // third is btf + const bidCopy1 = utils.deepClone(sraPosRequest.bids[0]); + bidCopy1.params.position = 'btf'; + sraPosRequest.bids.push(bidCopy1); + + // fourth is invalid (aka not atf or btf) + const bidCopy2 = utils.deepClone(sraPosRequest.bids[0]); + bidCopy2.params.position = 'unknown'; + sraPosRequest.bids.push(bidCopy2); + + // fifth is not present + const bidCopy3 = utils.deepClone(sraPosRequest.bids[0]); + delete bidCopy3.params.position; + sraPosRequest.bids.push(bidCopy3); + + let [request] = spec.buildRequests(sraPosRequest.bids, sraPosRequest); + let data = parseQuery(request.data); + + expect(data['p_pos']).to.equal('atf;;btf;;'); + }); + it('ad engine query params should be ordered correctly', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); From 23fad51b12ea5e9e596525aad2f691170f6ea16b Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Tue, 22 Oct 2019 13:36:45 -0400 Subject: [PATCH 1590/1594] In Sonobi Adapter, only read sizes from bid.mediaTypes (#4311) --- modules/sonobiBidAdapter.js | 43 +++- test/spec/modules/sonobiBidAdapter_spec.js | 279 +++++++++++++++------ 2 files changed, 248 insertions(+), 74 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index a0390a981a5..3fb9a83d259 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -20,8 +20,36 @@ export const spec = { * @param {BidRequest} bid - The bid params to validate. * @return {boolean} True if this is a valid bid, and false otherwise. */ - isBidRequestValid: bid => !!(bid.params && (bid.params.ad_unit || bid.params.placement_id) && (bid.params.sizes || bid.sizes)), + isBidRequestValid: (bid) => { + if (!bid.params) { + return false; + } + if (!bid.params.ad_unit && !bid.params.placement_id) { + return false; + } + + if (!deepAccess(bid, 'mediaTypes.banner') && !deepAccess(bid, 'mediaTypes.video')) { + return false; + } + if (deepAccess(bid, 'mediaTypes.banner')) { // Sonobi does not support multi type bids, favor banner over video + if (!deepAccess(bid, 'mediaTypes.banner.sizes') && !bid.params.sizes) { + // sizes at the banner or params level is required. + return false; + } + } else if (deepAccess(bid, 'mediaTypes.video')) { + if (deepAccess(bid, 'mediaTypes.video.context') === 'outstream' && !bid.params.sizes) { + // bids.params.sizes is required for outstream video adUnits + return false; + } + if (deepAccess(bid, 'mediaTypes.video.context') === 'instream' && !deepAccess(bid, 'mediaTypes.video.playerSize')) { + // playerSize is required for instream adUnits. + return false; + } + } + + return true; + }, /** * Make a server request from the list of BidRequests. * @@ -227,10 +255,21 @@ function _findBidderRequest(bidderRequests, bidId) { } function _validateSize (bid) { + if (deepAccess(bid, 'mediaTypes.video')) { + return ''; // Video bids arent allowed to override sizes via the trinity request + } + if (bid.params.sizes) { return parseSizesInput(bid.params.sizes).join(','); } - return parseSizesInput(bid.sizes).join(','); + if (deepAccess(bid, 'mediaTypes.banner.sizes')) { + return parseSizesInput(deepAccess(bid, 'mediaTypes.banner.sizes')).join(','); + } + + // Handle deprecated sizes definition + if (bid.sizes) { + return parseSizesInput(bid.sizes).join(','); + } } function _validateSlot (bid) { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index dc536846ae2..a6bf88cfc74 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -19,87 +19,222 @@ describe('SonobiBidAdapter', function () { }) describe('.isBidRequestValid', function () { - let bid = { - 'bidder': 'sonobi', - 'params': { - 'ad_unit': '/7780971/sparks_prebid_MR', - 'sizes': [[300, 250], [300, 600]], - 'floor': '1' - }, - '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 bid.params.placement_id and bid.params.sizes are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - delete bid.sizes - bid.params = { - 'placement_id': '1a2b3c4d5e6f1a2b3c4d', - 'sizes': [[300, 250], [300, 600]], - } + it('should return false if there are no params', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + 'mediaTypes': { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) + it('should return false if there is no placement_id param and no ad_unit param', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placementId: '1a2b3c4d5e6f1a2b3c4d', + }, + 'mediaTypes': { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); - it('should return true when bid.params.placement_id and bid.sizes are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - bid.sizes = [[300, 250], [300, 600]] - bid.params = { - 'placement_id': '1a2b3c4d5e6f1a2b3c4d', - } + it('should return false if there is no mediaTypes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d' + }, + 'mediaTypes': { + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) + it('should return true if the bid is valid', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d' + }, + 'mediaTypes': { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); - it('should return true when bid.params.ad_unit and bid.params.sizes are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - delete bid.sizes - bid.params = { - 'ad_unit': '/7780971/sparks_prebid_MR', - 'sizes': [[300, 250], [300, 600]], - } + describe('banner', () => { + it('should return false if there are no banner sizes and no param sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d' + }, + 'mediaTypes': { + banner: { - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); - it('should return true when bid.params.ad_unit and bid.sizes are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - bid.sizes = [[300, 250], [300, 600]] - bid.params = { - 'ad_unit': '/7780971/sparks_prebid_MR', - } + it('should return true if there is banner sizes and no param sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d' + }, + 'mediaTypes': { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) + it('should return true if there is param sizes and no banner sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + sizes: [[300, 250], [300, 600]] + }, + 'mediaTypes': { + banner: { + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); - it('should return false when no params are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) + describe('video', () => { + describe('instream', () => { + it('should return false if there is no playerSize defined in the video mediaType', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + sizes: [[300, 250], [300, 600]] + }, + 'mediaTypes': { + video: { + context: 'instream' + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true if there is playerSize defined on the video mediaType', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + }, + 'mediaTypes': { + video: { + context: 'instream', + playerSize: [300, 250] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); - it('should return false when bid.params.placement_id and bid.params.ad_unit are not found', function () { - let bid = Object.assign({}, bid) - delete bid.params - bid.params = { - 'placement_id': 0, - 'ad_unit': 0, - 'sizes': [[300, 250], [300, 600]], - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - }) + describe('outstream', () => { + it('should return false if there is no param sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + }, + 'mediaTypes': { + video: { + context: 'outstream', + playerSize: [300, 250] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true if there is param sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + sizes: [300, 250] + + }, + 'mediaTypes': { + video: { + context: 'outstream' + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + }); + }); describe('.buildRequests', function () { beforeEach(function() { From 8b85edcb4af77532482336c062065d34cbf71996 Mon Sep 17 00:00:00 2001 From: TinchoF <50110327+TinchoF@users.noreply.github.com> Date: Tue, 22 Oct 2019 15:54:08 -0300 Subject: [PATCH 1591/1594] Fix mediaTypes (#4332) * Outcon bid adapter. * Fix identation * Fixes * Fixes * Fixes * Spec fixes * Fixes * Fix urls * Fix * Fix parameters * Fix space operators * Fix bidder timeout * Update * Fix whitespace * no message * Outcon unit test * no message * no message * no message * no message * Fixes * Fixes * Change url * no message * no message * no message * Added bidId * no message * no message * no message * no message * Wrapping url with html * no message * no message * no message * Fix mediaTypes * no message * Update outconBidAdapter_spec.js * Adding VAS response * no message * no message * no message * Fix * Changed ttl * no message * supportedMediaTypes * no message * no message --- modules/outconBidAdapter.js | 18 ++++++++++++++---- test/spec/modules/outconBidAdapter_spec.js | 13 +++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/modules/outconBidAdapter.js b/modules/outconBidAdapter.js index d691e807059..ba0c1164279 100644 --- a/modules/outconBidAdapter.js +++ b/modules/outconBidAdapter.js @@ -1,18 +1,20 @@ import {registerBidder} from '../src/adapters/bidderFactory'; -import {config} from '../src/config'; const BIDDER_CODE = 'outcon'; + export const spec = { code: BIDDER_CODE, + supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function(bid) { return !!((bid.params.pod || (bid.params.internalId && bid.params.publisher)) && bid.params.env); }, buildRequests: function(validBidRequests) { for (let i = 0; i < validBidRequests.length; i++) { - let par = ''; let url = ''; + let par = ''; if (validBidRequests[i].params.pod != undefined) par = 'get?pod=' + validBidRequests[i].params.pod + '&bidId=' + validBidRequests[i].bidId; else par = 'get?internalId=' + validBidRequests[i].params.internalId + '&publisher=' + validBidRequests[i].params.publisher + '&bidId=' + validBidRequests[i].bidId; + par = par + '&vast=true'; switch (validBidRequests[i].params.env) { case 'test': par = par + '&demo=true'; @@ -42,10 +44,17 @@ export const spec = { creativeId: serverResponse.body.creatives[0].id, currency: serverResponse.body.cur, netRevenue: true, - ttl: config.getConfig('_bidderTimeout'), + ttl: 300, ad: wrapDisplayUrl(serverResponse.body.creatives[0].url, serverResponse.body.type), - vastImpUrl: serverResponse.body.trackingURL + vastImpUrl: serverResponse.body.trackingURL, + mediaType: serverResponse.body.type }; + if (serverResponse.body.type == 'video') { + Object.assign(bidResponse, { + vastUrl: serverResponse.body.vastURL, + ttl: 3600 + }); + } bidResponses.push(bidResponse); return bidResponses; }, @@ -54,6 +63,7 @@ export const spec = { function wrapDisplayUrl(displayUrl, type) { if (type == 'video') return `
    `; if (type == 'banner') return `
    `; + return null; } registerBidder(spec); diff --git a/test/spec/modules/outconBidAdapter_spec.js b/test/spec/modules/outconBidAdapter_spec.js index dc9c96ed3a3..a263bc9dbf9 100644 --- a/test/spec/modules/outconBidAdapter_spec.js +++ b/test/spec/modules/outconBidAdapter_spec.js @@ -23,6 +23,7 @@ describe('outconBidAdapter', function () { })).to.equal(true); }); }); + describe('buildRequests', function () { it('Build requests with pod param', function () { expect(spec.buildRequests([{ @@ -52,7 +53,8 @@ describe('outconBidAdapter', function () { url: 'http://test.outcondigital.com:8048/ad/', data: { pod: '5d603538eba7192ae14e39a4', - env: 'test' + env: 'test', + vast: 'true' } }; const bidResponse = { @@ -69,10 +71,11 @@ describe('outconBidAdapter', function () { codec: 'video/mp4' } ], - id: '5d6e6aef22063e392bf7f564', + ad: '5d6e6aef22063e392bf7f564', type: 'video', campaign: '5d42e44b306ea469593c76a2', - trackingURL: 'http://test.outcondigital.com:8048/ad/track?track=5d6e6aef22063e392bf7f564' + trackingURL: 'http://test.outcondigital.com:8048/ad/track?track=5d6e6aef22063e392bf7f564', + vastURL: 'http://test.outcondigital.com:8048/outcon.xml?impression=5d6e6aef22063e392bf7f564&demo=true' }, }; it('check all the keys that are needed to interpret the response', function () { @@ -87,7 +90,9 @@ describe('outconBidAdapter', function () { 'netRevenue', 'ttl', 'ad', - 'vastImpUrl' + 'vastImpUrl', + 'mediaType', + 'vastUrl' ]; let resultKeys = Object.keys(result[0]); resultKeys.forEach(function(key) { From d4e09b4dc0ae3d5790dee83f765c22ae6f7b038c Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 22 Oct 2019 15:41:07 -0400 Subject: [PATCH 1592/1594] Prebid 2.37.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0200db4eace..0228e16ff55 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.37.0-pre", + "version": "2.37.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From ecb5ff4c6f515683cc4907872bb058628809e4ec Mon Sep 17 00:00:00 2001 From: adamjung Date: Thu, 13 Feb 2020 14:45:58 -0500 Subject: [PATCH 1593/1594] patch on our things to 2.37 --- .gitignore | 1 - genius-adapters.json | 9 +++++++++ gulpfile.js | 2 -- package.json | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 genius-adapters.json diff --git a/.gitignore b/.gitignore index c0452b7b3d0..8046a2b0cab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # Built Files node_modules/ -build # Test Files test/app diff --git a/genius-adapters.json b/genius-adapters.json new file mode 100644 index 00000000000..48d335a90c2 --- /dev/null +++ b/genius-adapters.json @@ -0,0 +1,9 @@ +[ + "appnexusBidAdapter", + "consentManagement", + "ixBidAdapter", + "prebidServerBidAdapter", + "tripleliftBidAdapter", + "rubiconBidAdapter", + "undertoneBidAdapter" +] diff --git a/gulpfile.js b/gulpfile.js index 2566b52de59..428ae54b0d8 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -7,7 +7,6 @@ var gutil = require('gulp-util'); var connect = require('gulp-connect'); var webpack = require('webpack'); var webpackStream = require('webpack-stream'); -var uglify = require('gulp-uglify'); var gulpClean = require('gulp-clean'); var KarmaServer = require('karma').Server; var karmaConfMaker = require('./karma.conf.maker'); @@ -142,7 +141,6 @@ function makeWebpackPkg() { return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) .pipe(helpers.nameModules(externalModules)) .pipe(webpackStream(cloned, webpack)) - .pipe(uglify()) .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid }))) .pipe(gulp.dest('build/dist')); } diff --git a/package.json b/package.json index 0228e16ff55..40c02116d23 100755 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "prebid" ], "globalVarName": "pbjs", + "analytics": ["ga"], "author": "the prebid.js contributors", "license": "Apache-2.0", "engines": { From c1b8b5e86a12771efda42e3d7a49080949ef674b Mon Sep 17 00:00:00 2001 From: adamjung Date: Thu, 13 Feb 2020 14:54:22 -0500 Subject: [PATCH 1594/1594] update repo --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 40c02116d23..e70a485fe65 100755 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/prebid/Prebid.js.git" + "url": "https://github.com/Genius/Prebid.js.git" }, "keywords": [ "advertising",